Force Mode example

The ur_client_library supports leveraging the robot’s force mode directly. An example on how to use it can be found in force_mode_example.cpp.

In order to utilize force mode, we’ll have to create and initialize a driver object first. We use the ExampleRobotWrapper class for this example. That starts a UrDriver and a DashboardClient to communicate with the robot:

Listing 9 examples/force_mode_example.cpp
 85  bool headless_mode = true;
 86  g_my_robot = std::make_unique<ExampleRobotWrapper>(robot_ip, OUTPUT_RECIPE, INPUT_RECIPE, headless_mode,
 87                                                     "external_control.urp");
 88
 89  if (!g_my_robot->isHealthy())
 90  {
 91    URCL_LOG_ERROR("Something in the robot initialization went wrong. Exiting. Please check the output above.");
 92    return 1;
 93  }
 94  if (!g_my_robot->ur_driver_->checkCalibration(CALIBRATION_CHECKSUM))
 95  {
 96    URCL_LOG_ERROR("Calibration checksum does not match actual robot.");
 97    URCL_LOG_ERROR("Use the ur_calibration tool to extract the correct calibration from the robot and pass that into "
 98                   "the description. See "
 99                   "[https://github.com/UniversalRobots/Universal_Robots_ROS_Driver#extract-calibration-information] "
100                   "for details.");
101  }
102
103  // End of initialization -- We've started the external control program, which means we have to

Start force mode

After that, we can start force mode by calling the startForceMode() function:

Listing 10 examples/force_mode_example.cpp
106  // Start force mode
107  // Task frame at the robot's base with limits being large enough to cover the whole workspace
108  // Compliance in z axis and rotation around z axis
109  bool success;
110  if (g_my_robot->ur_driver_->getVersion().major < 5)
111    success =
112        g_my_robot->ur_driver_->startForceMode({ 0, 0, 0, 0, 0, 0 },  // Task frame at the robot's base
113                                               { 0, 0, 1, 0, 0, 1 },  // Compliance in z axis and rotation around z axis
114                                               { 0, 0, -2, 0, 0, 0 },  // Press in -z direction
115                                               2,                      // do not transform the force frame at all
116                                               { 0.1, 0.1, 1.5, 3.14, 3.14, 0.5 },  // limits
117                                               0.005);  // damping_factor. See ScriptManual for details.
118  else
119  {
120    success =
121        g_my_robot->ur_driver_->startForceMode({ 0, 0, 0, 0, 0, 0 },  // Task frame at the robot's base
122                                               { 0, 0, 1, 0, 0, 1 },  // Compliance in z axis and rotation around z axis
123                                               { 0, 0, -2, 0, 0, 0 },  // Press in -z direction
124                                               2,                      // do not transform the force frame at all
125                                               { 0.1, 0.1, 1.5, 3.14, 3.14, 0.5 },  // limits
126                                               0.005,                               // damping_factor
127                                               1.0);  // gain_scaling. See ScriptManual for details.
128  }
129  if (!success)

All parameters for the force mode are included into the startForceMode() function call. If you want to change the parameters, e.g. change the forces applied, you can simply call startForceMode() again with the new parameters.

Note

CB3 robots don’t support specifying force_mode’s gain_scaling, so there are two different functions available.

Once force mode is started successfully, we’ll have to send keepalive messages to the robot in order to keep the communication active:

Listing 11 examples/force_mode_example.cpp
135  std::chrono::duration<double> time_done(0);
136  std::chrono::duration<double> timeout(second_to_run);
137  auto stopwatch_last = std::chrono::steady_clock::now();
138  auto stopwatch_now = stopwatch_last;
139  while (time_done < timeout || second_to_run.count() == 0)
140  {
141    g_my_robot->ur_driver_->writeKeepalive();
142
143    stopwatch_now = std::chrono::steady_clock::now();
144    time_done += stopwatch_now - stopwatch_last;
145    stopwatch_last = stopwatch_now;
146    std::this_thread::sleep_for(std::chrono::milliseconds(2));
147  }
148  URCL_LOG_INFO("Timeout reached.");

Stop force mode

Once finished, force_mode can be stopped by calling endForceMode().

Listing 12 examples/force_mode_example.cpp
149  g_my_robot->ur_driver_->endForceMode();