Java ZMQ Remote API

Typically: "How do I... ", "How can I... " questions
lumeqi
Posts: 29
Joined: 04 Dec 2023, 06:20

Java ZMQ Remote API

Post by lumeqi »

Hello,
I want to connect CoppeliaSim in the SpringBoot project. How do I use the Java ZMQ Remote API?
I found an example in "programming \ zmqRemote API \ clients \ Java", but I cannot solve the problem that appears in the example.
Do I need to copy the code under "programming \ zmqRemote API \ clients \ Java \ src \ main \ Java \ com" to my own project when using it, so that I can create objects of the "RemoteAPIClient" class?
Where is the "RemoteAPIObjects" class? Is it a file in the template directory? But it doesn't look like a normal Java class.
Could you please provide an example of a Java ZMQ Remote API that runs without errors? Thank you very much.
My CoppeliaSim version is 4.6.0, Windows 11

fferri
Posts: 1231
Joined: 09 Sep 2013, 19:28

Re: Java ZMQ Remote API

Post by fferri »


lumeqi
Posts: 29
Joined: 04 Dec 2023, 06:20

Re: Java ZMQ Remote API

Post by lumeqi »

Hello,
First of all, thank you very much for your help.
I roughly understand that I need to package the project provided by CoppeliaSim before using it.


(1) I modified the content under the<Python3-EXECUTABLE>tag corresponding to the Windows operating system in the provided pom.xml
(<Python3_EXECUTABLE>C:\Users\LMQ\.conda\envs\py39-cuda116\python.exe</Python3_EXECUTABLE>)

(2) I added COPPELIASIM_ROOT_DIR=C:\bed\CoppeliaSim_Edu_V4_6_0_rev10_Win to the system's environment variables

(3) Then enter the C:\bed\CoppeliaSim_Edu_V4_6_0_rev10_Win\programming\zmqRemoteApi\clients\java directory, select the corresponding Conda environment, and execute:
mvn package -DGENERATE_INCLUDE_OBJECTS=sim,simIK


But after executing step (3), the cmd got stuck. Is the process I followed correct? I'm very sorry to disturb you.

lumeqi
Posts: 29
Joined: 04 Dec 2023, 06:20

Re: Java ZMQ Remote API

Post by lumeqi »

Hello,
I have successfully packaged the project, but when using it, I am not sure if the parameter types I passed are correct. For example, when passing a List in Python, I am not sure if I should pass a List (or ArrayList) or a regular array in Java. Do you have any relevant reference materials? Thank you very much for your help.

fferri
Posts: 1231
Joined: 09 Sep 2013, 19:28

Re: Java ZMQ Remote API

Post by fferri »

If a list is used in Python, in Java that would be List<T>, with T being the type of the elements of the list.

There are a couple of examples in zmqRemoteApi/clients/java/src/main/java.

lumeqi
Posts: 29
Joined: 04 Dec 2023, 06:20

Re: Java ZMQ Remote API

Post by lumeqi »

Hello,
Do you know how to pass a callback function in Java clients? I tried for a long time but couldn't find a solution. I found the convertArg function in the "RemoteAPIClient" class, which specifies the type of parameter passed (objects that cannot pass custom interface implementation classes):

Code: Select all

...
else {
            return arg.getClass().isArray() ? this.convertArg((byte[])arg) : null;
        }
I really don't know how to solve this problem, so I am seeking your help. My code is:

Code: Select all

...
RemoteAPIObjects._sim simT = getClient().getSim();

        ConfigCallBack callback = (configs1, vel1, accel1, sim) -> {
            int i = 0;
            for (int joint : joints) {
                if (sim.isDynamicallyEnabled(joint)) {
                    sim.setJointTargetPosition(joint, configs1.get(i));
                } else {
                    sim.setJointPosition(joint, configs1.get(i));
                }
                i++;
            }
        };

        this.getClient().getSim().moveToConfig(
                -1, currentConfig, currentV, currentA,
                vel, accel, jerk,
                configs, targetV,
                callback, simT, cyclicJoints, 0.0
        );
...
I don't know how to avoid my callback function being converted to null. What should be passed as the position of the callback function parameter in moveToConfig? The error I always receive is:

Code: Select all

sim.lua:712: attempt to call a nil value (local 'callback')
Code in Example:

Code: Select all

Client.registerCallback ("myFunc", Example::myFunc);
Is it related to my question? But I don't know how it is used.

Please! I really need help with this issue. Thank you very much!

fferri
Posts: 1231
Joined: 09 Sep 2013, 19:28

Re: Java ZMQ Remote API

Post by fferri »

lumeqi wrote: 06 Apr 2024, 06:40 RemoteAPIObjects._sim simT = getClient().getSim();
what's that?
lumeqi wrote: 06 Apr 2024, 06:40 if (sim.isDynamicallyEnabled(joint)) {
what's sim here?
lumeqi wrote: 06 Apr 2024, 06:40 this.getClient().getSim().moveToConfig(
same...

lumeqi
Posts: 29
Joined: 04 Dec 2023, 06:20

Re: Java ZMQ Remote API

Post by lumeqi »

"simT" is an object of the "RemoteAPIObjects._sim" class, and what I want to call is sim.moveToConfig. "this.getClient().getSim()" represents an object of the "RemoteAPIObjects._sim" class. However, I have encapsulated it according to my own task, and I can obtain the object of the "RemoteAPIObjects._sim" class normally.
The most important thing is that I don't know how to pass one of the parameters (the callback function) in sim.moveToConfig in the Java client.

fferri
Posts: 1231
Joined: 09 Sep 2013, 19:28

Re: Java ZMQ Remote API

Post by fferri »

The point is that sim, simT and the result of RemoteAPIClient.getSim() are all the same thing which you are fetching three times.

just wanted to make sure wether you understand the Java ZMQ remote API client interface...

fferri
Posts: 1231
Joined: 09 Sep 2013, 19:28

Re: Java ZMQ Remote API

Post by fferri »

lumeqi wrote: 06 Apr 2024, 06:40

Code: Select all

        ConfigCallBack callback = (configs1, vel1, accel1, sim) -> {
            int i = 0;
            for (int joint : joints) {
                if (sim.isDynamicallyEnabled(joint)) {
                    sim.setJointTargetPosition(joint, configs1.get(i));
                } else {
                    sim.setJointPosition(joint, configs1.get(i));
                }
                i++;
            }
        };

        this.getClient().getSim().moveToConfig(
                -1, currentConfig, currentV, currentA,
                vel, accel, jerk,
                configs, targetV,
                callback, simT, cyclicJoints, 0.0
        );
...
I don't know how to avoid my callback function being converted to null. What should be passed as the position of the callback function parameter in moveToConfig? The error I always receive is:

Code: Select all

sim.lua:712: attempt to call a nil value (local 'callback')
Code in Example:

Code: Select all

Client.registerCallback ("myFunc", Example::myFunc);
Is it related to my question? But I don't know how it is used.
in the same 'Example' code there is an example of registering and then calling a callback.

Post Reply