Example driver

In the examples subfolder you will find a minimal example of a running driver. It starts an instance of the UrDriver class and prints the RTDE values read from the controller. To run it make sure to

  • have an instance of a robot controller / URSim running at the configured IP address (or adapt the address to your needs)

  • run it from the package’s main folder (the one where the README.md file is stored), as for simplicity reasons it doesn’t use any sophisticated method to locate the required files.

This page will walk you through the full_driver.cpp example.

Initialization

At first, we create a ExampleRobotWrapper object giving it the robot’s IP address, script file and RTDE recipes.

Listing 42 examples/full_driver.cpp
62  bool headless_mode = true;
63  g_my_robot = std::make_unique<ExampleRobotWrapper>(robot_ip, OUTPUT_RECIPE, INPUT_RECIPE, headless_mode,
64                                                     "external_control.urp");
65  if (!g_my_robot->isHealthy())
66  {
67    URCL_LOG_ERROR("Something in the robot initialization went wrong. Exiting. Please check the output above.");
68    return 1;
69  }
70  // --------------- INITIALIZATION END -------------------

Robot control loop

This example reads the robot’s joint positions, increments / decrements the 5th axis and sends that back as a joint command for the next cycle. This way, the robot will move its wrist first until a positive limit and then back to 0.

To read the joint data, the driver’s RTDE client is used:

Listing 43 examples/full_driver.cpp
 86  // Once RTDE communication is started, we have to make sure to read from the interface buffer, as
 87  // otherwise we will get pipeline overflows. Therefor, do this directly before starting your main
 88  // loop.
 89  g_my_robot->ur_driver_->startRTDECommunication();
 90  while (!(passed_positive_part && passed_negative_part))
 91  {
 92    // Read latest RTDE package. This will block for a hard-coded timeout (see UrDriver), so the
 93    // robot will effectively be in charge of setting the frequency of this loop.
 94    // In a real-world application this thread should be scheduled with real-time priority in order
 95    // to ensure that this is called in time.
 96    std::unique_ptr<rtde_interface::DataPackage> data_pkg = g_my_robot->ur_driver_->getDataPackage();
 97    if (!data_pkg)
 98    {
 99      URCL_LOG_WARN("Could not get fresh data package from robot");
100      return 1;
101    }
102    // Read current joint positions from robot data
103    if (!data_pkg->getData("actual_q", g_joint_positions))
104    {
105      // This throwing should never happen unless misconfigured
106      std::string error_msg = "Did not find 'actual_q' in data sent from robot. This should not happen!";
107      throw std::runtime_error(error_msg);
108    }
109
110    if (first_pass)
111    {
112      joint_target = g_joint_positions;
113      first_pass = false;
114    }

The first read operation will initialize the target buffer with the current robot position. Next, the target joint configuration is calculated:

Listing 44 examples/full_driver.cpp
116    // Open loop control. The target is incremented with a constant each control loop
117    if (passed_positive_part == false)
118    {
119      increment = increment_constant;
120      if (g_joint_positions[5] >= 2)
121      {
122        passed_positive_part = true;
123      }
124    }
125    else if (passed_negative_part == false)
126    {
127      increment = -increment_constant;
128      if (g_joint_positions[5] <= 0)
129      {
130        passed_negative_part = true;
131      }
132    }
133    joint_target[5] += increment;

To send the control command, the robot’s ReverseInterface is used via the writeJointCommand() function:

Listing 45 examples/full_driver.cpp
134    // Setting the RobotReceiveTimeout time is for example purposes only. This will make the example running more
135    // reliable on non-realtime systems. Use with caution in productive applications.
136    bool ret = g_my_robot->ur_driver_->writeJointCommand(joint_target, comm::ControlMode::MODE_SERVOJ,
137                                                         RobotReceiveTimeout::millisec(100));
138    if (!ret)
139    {
140      URCL_LOG_ERROR("Could not send joint command. Is the robot in remote control?");
141      return 1;
142    }