RTDE Client example

This example shows how to use the RTDEClient class for the robot’s Real-Time Data Exchange (RTDE) interface.

The RTDE client has to be initialized with a list of keys that should be streamed from the robot and a list of keys that should be sent to the robot. The client will then start a background thread establishing communication.

In this example, those keys are stored in two text files relative to this repository’s root: rtde_input_keys.txt and rtde_output_keys.txt. The example will read those files and use them to initialize the RTDE client.

Listing 29 examples/rtde_client.cpp
40const std::string OUTPUT_RECIPE = "examples/resources/rtde_output_recipe.txt";
41const std::string INPUT_RECIPE = "examples/resources/rtde_input_recipe.txt";

Internally, the RTDE client uses the same producer / consumer architecture as show in the Primary Pipeline example example. However, it doesn’t have a consumer thread, so data has to be read by the user to avoid the pipeline’s queue from overflowing.

Creating an RTDE Client

An RTDE client can be directly created passing the robot’s IP address, a INotifier object, an output and an input recipe. Optionally, a communication frequency can be passed as well. If that is omitted, RTDE communication will be established at the robot’s control frequency.

Listing 30 examples/rtde_client.cpp
74  comm::INotifier notifier;
75  const double rtde_frequency = 50;  // Hz
76  rtde_interface::RTDEClient my_client(robot_ip, notifier, OUTPUT_RECIPE, INPUT_RECIPE, rtde_frequency);
77  my_client.init();

An RTDE data package containing every key-value pair from the output recipe can be fetched using the getDataPackage() method. This method will block until a new package is available.

Reading data from the RTDE client

Once the RTDE client is initialized, we’ll have to start communication separately. As mentioned above, we’ll have to read data from the client once communication is started, hence we start communication right before a loop reading data.

Listing 31 examples/rtde_client.cpp
 84  // Once RTDE communication is started, we have to make sure to read from the interface buffer, as
 85  // otherwise we will get pipeline overflows. Therefor, do this directly before starting your main
 86  // loop.
 87  my_client.start();
 88
 89  auto start_time = std::chrono::steady_clock::now();
 90  while (second_to_run <= 0 ||
 91         std::chrono::duration_cast<std::chrono::seconds>(std::chrono::steady_clock::now() - start_time).count() <
 92             second_to_run)
 93  {
 94    // Read latest RTDE package. This will block for READ_TIMEOUT, so the
 95    // robot will effectively be in charge of setting the frequency of this loop unless RTDE
 96    // communication doesn't work in which case the user will be notified.
 97    // In a real-world application this thread should be scheduled with real-time priority in order
 98    // to ensure that this is called in time.
 99    std::unique_ptr<rtde_interface::DataPackage> data_pkg = my_client.getDataPackage(READ_TIMEOUT);
100    if (data_pkg)
101    {
102      // Data fields in the data package are accessed by their name. Only names present in the
103      // output recipe can be accessed. Otherwise this function will return false.
104      data_pkg->getData("target_speed_fraction", target_speed_fraction);
105      printFraction(target_speed_fraction, "target_speed_fraction");
106    }
107    else
108    {
109      // The client isn't connected properly anymore / doesn't receive any data anymore. Stop the
110      // program.
111      std::cout << "Could not get fresh data package from robot" << std::endl;
112      return 1;
113    }

Writing Data to the RTDE client

In this example, we use the RTDE client to oscillate the speed slider on the teach pendant between 0 and 1. While this doesn’t bear any practical use it shows how sending data to the RTDE interface works.

To send data to the RTDE client, we can use RTDEWriter object stored in the RTDE client. This has methods implemented for each data type that can be sent to the robot. The input recipe used to initialize the RTDE client has to contain the keys necessary to send that specific data.

Listing 32 examples/rtde_client.cpp
130    if (!my_client.getWriter().sendSpeedSlider(speed_slider_fraction))
131    {
132      // This will happen for example, when the required keys are not configured inside the input
133      // recipe.
134      std::cout << "\033[1;31mSending RTDE data failed." << "\033[0m\n" << std::endl;
135      return 1;
136    }

Note

Many RTDE inputs require setting up the data key and a mask key. See the RTDE guide for more information.