Minimal example: synchronous mode#

Goals

  1. Understand the synchronous mode.

  2. Know the methods:

    • set_synchronous().

    • trigger_next_simulation_step().

    • wait_for_simulation_step_to_end().

We learned previously the asynchronous mode, the default operation mode. In this section we are going to see the synchronous mode (now called stepped mode). In this mode, the simulation will take into account the progress of your script. To enable it, you need to use set_synchronous(true).

Once enabled, the simulation will wait for a trigger to start computing the next simulation step. Such a trigger is sent by the method trigger_next_simulation_step(). To keep the synchrony, we need to ensure that the simulation step is finished before sending the next trigger. This can be done by using the method wait_for_simulation_step_to_end().

Recommendation

Check Legacy remote API modus operandi to learn more about the synchronous mode.

Templates:#

The templates show how to establish communication with a CoppeliaSim scene in synchronous mode using the default port. It’s assumed that both the script and the scene are running in the same computer (default IP).

template_synchronous.m

 1clear all;
 2close all;
 3clc;
 4
 5
 6include_namespace_dq;
 7vi = DQ_VrepInterface();
 8
 9try
10    vi.connect('127.0.0.1', 19997);
11    vi.set_synchronous(true);
12    vi.start_simulation();
13    pause(0.1);
14    %-----------Your code here---------------------
15    vi.trigger_next_simulation_step();
16    vi.wait_for_simulation_step_to_end();
17    %----------------------------------------------
18    vi.stop_simulation();
19    vi.disconnect();
20catch ME
21    vi.stop_simulation();
22    vi.disconnect();
23    rethrow(ME)
24end

template_synchronous.py

 1#!/bin/python3
 2from dqrobotics.interfaces.vrep import DQ_VrepInterface
 3import time
 4
 5
 6def main() -> None:
 7    vi = DQ_VrepInterface()
 8    try:
 9        if not vi.connect("127.0.0.1", 19997, 100, 10):
10            raise RuntimeError("Unable to connect to CoppeliaSim.")
11
12        vi.set_synchronous(True)
13        vi.start_simulation()
14        time.sleep(0.1)
15        # --------------Your code here----------------------------
16        vi.trigger_next_simulation_step()
17        vi.wait_for_simulation_step_to_end()
18        # ---------------------------------------------------------
19
20    except (Exception, KeyboardInterrupt) as e:
21        print(e)
22        pass
23
24    finally:
25        vi.stop_simulation()
26        vi.disconnect()
27
28
29if __name__ == "__main__":
30    main()

template_synchronous.cpp

 1#include <iostream>
 2#include <dqrobotics/interfaces/vrep/DQ_VrepInterface.h>
 3#include <thread>
 4
 5int main()
 6{
 7    auto vi = DQ_VrepInterface();
 8    try {
 9        if (!vi.connect("127.0.0.1", 19997,100,10))
10            throw std::runtime_error("Unable to connect to CoppeliaSim.");
11        vi.set_synchronous(true);
12        vi.start_simulation();
13        std::this_thread::sleep_for(std::chrono::milliseconds(100));
14        //------------------Your code here--------------------------
15        vi.trigger_next_simulation_step();
16        vi.wait_for_simulation_step_to_end();
17        //---------------------------------------------------------
18        vi.stop_simulation();
19        vi.disconnect();
20
21    } catch (std::exception& e) {
22        std::cout<<e.what()<<std::endl;
23        vi.stop_simulation();
24        vi.disconnect();
25    }
26    return 0;
27}

See also

CMake examples for Ubuntu, Windows and MacOS dqrobotics/cpp-examples

 1# Example CMAKE project for Ubuntu
 2make_minimum_required(VERSION 3.5)
 3
 4project(template_synchronous)
 5
 6set(CMAKE_CXX_STANDARD 11)
 7
 8FIND_PACKAGE(Threads REQUIRED)
 9FIND_PACKAGE(Eigen3 REQUIRED)
10INCLUDE_DIRECTORIES(${EIGEN3_INCLUDE_DIR})
11ADD_COMPILE_OPTIONS(-Werror=return-type
12                    -Wall -Wextra -Wmissing-declarations
13                    -Wredundant-decls -Woverloaded-virtual)
14
15add_executable(${PROJECT_NAME}
16               ${PROJECT_NAME}.cpp)
17
18target_link_libraries(${PROJECT_NAME}
19                      dqrobotics
20                      dqrobotics-interface-vrep
21                      Threads::Threads)

Free fall experiment#


It’s time to test the synchronous mode! To do so, we are going to compare the height of the red ball (/Sphere) that is in free fall with the expected height after 0.25 s in the simulation time. The dynamics of the red ball is handled by the engine and its behavior is affected by the simulation time step and the gravity.

In the DQ_Robotics_lab.ttt scene (see One scene to rule them all), the engine is Newton, the simulation time step is 50ms and the gravity is -9,81. You can modify those parameters, but you’ll need to update the examples as well.

Note

As reported in dqrobotics/python#51 the synchronous mode is working properly on Ubuntu (Matlab, Python and C++) and on Windows (Matlab). Other combinations of OS and languages could not ensure the synchrony.


free_fall_test.m

 1clear all;
 2close all;
 3clc;
 4
 5
 6
 7include_namespace_dq;
 8vi = DQ_VrepInterface();
 9
10
11try
12
13    vi.connect('127.0.0.1', 19997);
14    vi.set_synchronous(true);
15    vi.start_simulation();
16    pause(0.1);
17    p0 = vec3(translation(vi.get_object_pose('/Sphere')));
18    y0 = p0(3);
19    time_simulation_step = 0.05;
20    disp('---------------------------------')
21    disp(['Initial height: ',num2str(y0)])
22    disp('---------------------------------')
23
24    for i=0:5
25        t = i*time_simulation_step;
26        p = vec3(translation(vi.get_object_pose('/Sphere')));
27        y_sim = p(3);
28        y_est = y0 - 0.5*9.81*t^2;
29        vi.trigger_next_simulation_step();
30        vi.wait_for_simulation_step_to_end();
31    end
32    disp(['Elapsed time: ',num2str(t)])
33    disp(['Estimated height: ',num2str(y_est),' Measured height: ', num2str(y_sim)])
34    vi.stop_simulation();
35    vi.disconnect();
36
37catch ME
38
39    vi.stop_simulation();
40    vi.disconnect();
41    rethrow(ME)
42
43end

free_fall_test.py

 1#!/bin/python3
 2from dqrobotics.interfaces.vrep import DQ_VrepInterface
 3import time
 4
 5
 6
 7def main() -> None:
 8    vi = DQ_VrepInterface()
 9    try:
10        if not vi.connect("127.0.0.1", 19997, 100, 10):
11            raise RuntimeError("Unable to connect to CoppeliaSim.")
12
13        vi.set_synchronous(True)
14        vi.start_simulation()
15        time.sleep(0.1)
16        time_simulation_step = 0.05
17        y_0 = vi.get_object_pose("/Sphere").translation().vec3()[2]
18        print("---------------------------")
19        print("Initial height: ", y_0)
20        print("---------------------------")
21        for i in range(0, 6):
22            t = i * time_simulation_step
23            y_sim = vi.get_object_pose("/Sphere").translation().vec3()[2]
24            y_est = y_0 - 0.5 * 9.81 * pow(t, 2)
25            vi.trigger_next_simulation_step()
26            vi.wait_for_simulation_step_to_end()
27        print("Elapsed time: ", t)
28        print("Estimated height: ", y_est, "Measured height: ", y_sim)
29
30    except (Exception, KeyboardInterrupt) as e:
31        print(e)
32        pass
33
34    finally:
35        vi.stop_simulation()
36        vi.disconnect()
37
38
39if __name__ == "__main__":
40    main()
41
42
43

free_fall_test.cpp

 1#include <iostream>
 2#include <dqrobotics/interfaces/vrep/DQ_VrepInterface.h>
 3#include <thread>
 4
 5int main()
 6{
 7    auto vi = DQ_VrepInterface();
 8    try {
 9        if (!vi.connect("127.0.0.1", 19997,100,10))
10            throw std::runtime_error("Unable to connect to CoppeliaSim.");
11        vi.set_synchronous(true);
12        vi.start_simulation();
13        std::this_thread::sleep_for(std::chrono::milliseconds(100));
14        //---------------Your code here----------------------------
15
16        double time_simulation_step = 0.05;
17        double y_0 = vi.get_object_pose("/Sphere").translation().vec3()[2];
18        double y_sim;
19        double y_est;
20        double t;
21        std::cout<<"-----------------"<<std::endl;
22        std::cout<<"Initial height: "<<y_0<<std::endl;
23        std::cout<<"-----------------"<<std::endl;
24
25        for (int i=0; i<=5; i++)
26        {
27            t = i*time_simulation_step;
28            y_sim = vi.get_object_pose("/Sphere").translation().vec3()[2];
29            y_est = y_0 - 0.5 * 9.81 * std::pow(t, 2);
30            vi.trigger_next_simulation_step();
31            vi.wait_for_simulation_step_to_end();
32        }
33        std::cout<<"Elapsed time: "<<t<<std::endl;
34        std::cout<<"Estimated height: "<<y_est<<", Measured height: "<<y_sim<<std::endl;
35        vi.stop_simulation();
36        vi.disconnect();
37    } catch (std::exception& e) {
38        std::cout<<e.what()<<std::endl;
39        vi.stop_simulation();
40        vi.disconnect();
41    }
42    return 0;
43}

You will have the following output:

———————————
Initial height: 1
———————————
Elapsed time: 0.25
Estimated height: 0.69344 Measured height: 0.68731

See also

Synchronous test dqrobotics/python-examples