Skip to content

Commit f717f83

Browse files
authored
Use ExampleRobotWrapper for initialization in all examples (#265)
This way the examples are a lot shorter and initialization is the same everywhere, making things easier to maintain.
1 parent b9b9fcf commit f717f83

17 files changed

+228
-512
lines changed

doc/examples/force_mode.rst

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,16 @@ Force Mode example
66
The ``ur_client_library`` supports leveraging the robot's force mode directly. An example on how to
77
use it can be found in `force_mode_example.cpp <https://github.com/UniversalRobots/Universal_Robots_Client_Library/blob/master/examples/force_mode_example.cpp>`_.
88

9-
In order to utilize force mode, we'll have to create and initialize a full ``UrDriver`` object
10-
first:
9+
In order to utilize force mode, we'll have to create and initialize a driver object
10+
first. We use the ``ExampleRobotWrapper`` class for this example. That starts a :ref:`ur_driver`
11+
and a :ref:`dashboard_client` to communicate with the robot:
1112

1213
.. literalinclude:: ../../examples/force_mode_example.cpp
1314
:language: c++
1415
:caption: examples/force_mode_example.cpp
1516
:linenos:
1617
:lineno-match:
17-
:start-at: // Now the robot is ready to receive a program
18+
:start-at: bool headless_mode = true;
1819
:end-at: // End of initialization
1920

2021
Start force mode

doc/examples/instruction_executor.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ The `instruction_executor.cpp <https://github.com/UniversalRobots/Universal_Robo
2020
:caption: examples/instruction_executor.cpp
2121
:linenos:
2222
:lineno-match:
23-
:start-at: std::unique_ptr<urcl::ToolCommSetup> tool_comm_setup;
24-
:end-at: auto instruction_executor = std::make_shared<urcl::InstructionExecutor>(g_my_driver);
23+
:start-at: bool headless_mode = true;
24+
:end-at: auto instruction_executor = std::make_shared<urcl::InstructionExecutor>(g_my_robot->ur_driver_);
2525

2626
At first, a ``InstructionExecutor`` object is created with the URDriver object as it needs that
2727
for communication with the robot.
@@ -61,6 +61,6 @@ To run a single motion, the ``InstructionExecutor`` provides the methods ``moveJ
6161
:linenos:
6262
:lineno-match:
6363
:start-at: double goal_time_sec = 2.0;
64-
:end-before: g_my_driver->stopControl();
64+
:end-before: g_my_robot->ur_driver_->stopControl();
6565

6666
Again, time parametrization has priority over acceleration / velocity parameters.

doc/examples/tool_contact_example.rst

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@ tool contact mode to detect collisions and stop the robot.
1212
As a basic concept, we will move the robot linearly in the negative z axis until the tool hits
1313
something or the program's timeout is hit.
1414

15-
At first, we create a ``UrDriver`` object as usual:
15+
At first, we create a initialize a driver as usual:
1616

1717
.. literalinclude:: ../../examples/tool_contact_example.cpp
1818
:language: c++
1919
:caption: examples/tool_contact_example.cpp
2020
:linenos:
2121
:lineno-match:
22-
:start-at: std::unique_ptr<ToolCommSetup> tool_comm_setup;
23-
:end-before: g_my_driver->registerToolContactResultCallback
22+
:start-at: bool headless_mode = true;
23+
:end-before: g_my_robot->ur_driver_->registerToolContactResultCallback
2424

2525
We use a small helper function to make sure that the reverse interface is active and connected
2626
before proceeding.
@@ -45,8 +45,8 @@ This function is registered as a callback to the driver and then tool_contact mo
4545
:caption: examples/tool_contact_example.cpp
4646
:linenos:
4747
:lineno-match:
48-
:start-at: g_my_driver->registerToolContactResultCallback(&handleToolContactResult);
49-
:end-at: g_my_driver->startToolContact()
48+
:start-at: g_my_robot->ur_driver_->registerToolContactResultCallback(&handleToolContactResult);
49+
:end-at: g_my_robot->ur_driver_->startToolContact()
5050

5151
Once everything is initialized, we can start a control loop commanding the robot to move in the
5252
negative z direction until the program timeout is hit or a tool contact is detected:

doc/examples/trajectory_point_interface.rst

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ At first, we create a ``UrDriver`` object as usual:
1414
:caption: examples/trajectory_point_interface.cpp
1515
:linenos:
1616
:lineno-match:
17-
:start-at: std::unique_ptr<urcl::ToolCommSetup> tool_comm_setup;
17+
:start-at: bool headless_mode = true;
1818
:end-before: // --------------- INITIALIZATION END -------------------
1919

2020
We use a small helper function to make sure that the reverse interface is active and connected
@@ -45,8 +45,8 @@ That callback can be registered at the ``UrDriver`` object:
4545
:caption: examples/trajectory_point_interface.cpp
4646
:linenos:
4747
:lineno-match:
48-
:start-at: g_my_driver->registerTrajectoryDoneCallback(&trajDoneCallback);
49-
:end-at: g_my_driver->registerTrajectoryDoneCallback(&trajDoneCallback);
48+
:start-at: g_my_robot->ur_driver_->registerTrajectoryDoneCallback(&trajDoneCallback);
49+
:end-at: g_my_robot->ur_driver_->registerTrajectoryDoneCallback(&trajDoneCallback);
5050

5151

5252
MoveJ Trajectory
@@ -67,12 +67,12 @@ parameters. The following example shows execution of a 2-point trajectory using
6767
In fact, the path is followed twice, once parametrized by a segment duration and once using maximum
6868
velocity / acceleration settings. If a duration > 0 is given for a segment, the velocity and
6969
acceleration settings will be ignored as in the underlying URScript functions. In the example
70-
above, each of the ``g_my_driver->writeTrajectoryPoint()`` calls will be translated into a
70+
above, each of the ``g_my_robot->ur_driver_->writeTrajectoryPoint()`` calls will be translated into a
7171
``movej`` command in URScript.
7272

7373
While the trajectory is running, we need to tell the robot program that connection is still active
7474
and we expect the trajectory to be running. This is being done by the
75-
``g_my_driver->writeTrajectoryControlMessage(urcl::control::TrajectoryControlMessage::TRAJECTORY_NOOP);``
75+
``g_my_robot->ur_driver_->writeTrajectoryControlMessage(urcl::control::TrajectoryControlMessage::TRAJECTORY_NOOP);``
7676
call.
7777

7878
MoveL Trajectory

doc/examples/ur_driver.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,16 @@ example.
2020
Initialization
2121
--------------
2222

23-
At first, we create a ``UrDriver`` object giving it the robot's IP address, script file and RTDE
23+
At first, we create a ``ExampleRobotWrapper`` object giving it the robot's IP address, script file and RTDE
2424
recipes.
2525

2626
.. literalinclude:: ../../examples/full_driver.cpp
2727
:language: c++
2828
:caption: examples/full_driver.cpp
2929
:linenos:
3030
:lineno-match:
31-
:start-at: std::unique_ptr<ToolCommSetup> tool_comm_setup;
32-
:end-at: std::move(tool_comm_setup)
31+
:start-at: bool headless_mode = true;
32+
:end-at: // --------------- INITIALIZATION END -------------------
3333

3434
Robot control loop
3535
------------------

examples/force_mode_example.cpp

Lines changed: 27 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
// In a real-world example it would be better to get those values from command line parameters / a
3434
// better configuration system such as Boost.Program_options
3535

36+
#include <ur_client_library/example_robot_wrapper.h>
3637
#include <ur_client_library/ur/dashboard_client.h>
3738
#include <ur_client_library/ur/ur_driver.h>
3839
#include <ur_client_library/types.h>
@@ -52,47 +53,18 @@ const std::string OUTPUT_RECIPE = "examples/resources/rtde_output_recipe.txt";
5253
const std::string INPUT_RECIPE = "examples/resources/rtde_input_recipe.txt";
5354
const std::string CALIBRATION_CHECKSUM = "calib_12788084448423163542";
5455

55-
std::unique_ptr<UrDriver> g_my_driver;
56-
std::unique_ptr<DashboardClient> g_my_dashboard;
57-
58-
std::condition_variable g_program_running_cv;
59-
std::mutex g_program_running_mutex;
60-
bool g_program_running;
61-
62-
// We need a callback function to register. See UrDriver's parameters for details.
63-
void handleRobotProgramState(bool program_running)
64-
{
65-
// Print the text in green so we see it better
66-
std::cout << "\033[1;32mProgram running: " << std::boolalpha << program_running << "\033[0m\n" << std::endl;
67-
if (program_running)
68-
{
69-
std::lock_guard<std::mutex> lk(g_program_running_mutex);
70-
g_program_running = program_running;
71-
g_program_running_cv.notify_one();
72-
}
73-
}
56+
std::unique_ptr<ExampleRobotWrapper> g_my_robot;
7457

7558
void sendFreedriveMessageOrDie(const control::FreedriveControlMessage freedrive_action)
7659
{
77-
bool ret = g_my_driver->writeFreedriveControlMessage(freedrive_action);
60+
bool ret = g_my_robot->ur_driver_->writeFreedriveControlMessage(freedrive_action);
7861
if (!ret)
7962
{
8063
URCL_LOG_ERROR("Could not send joint command. Is the robot in remote control?");
8164
exit(1);
8265
}
8366
}
8467

85-
bool waitForProgramRunning(int milliseconds = 100)
86-
{
87-
std::unique_lock<std::mutex> lk(g_program_running_mutex);
88-
if (g_program_running_cv.wait_for(lk, std::chrono::milliseconds(milliseconds)) == std::cv_status::no_timeout ||
89-
g_program_running == true)
90-
{
91-
return true;
92-
}
93-
return false;
94-
}
95-
9668
int main(int argc, char* argv[])
9769
{
9870
urcl::setLogLevel(urcl::LogLevel::INFO);
@@ -110,50 +82,16 @@ int main(int argc, char* argv[])
11082
second_to_run = std::chrono::seconds(std::stoi(argv[2]));
11183
}
11284

113-
// Making the robot ready for the program by:
114-
// Connect the robot Dashboard
115-
g_my_dashboard.reset(new DashboardClient(robot_ip));
116-
if (!g_my_dashboard->connect())
117-
{
118-
URCL_LOG_ERROR("Could not connect to dashboard");
119-
return 1;
120-
}
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");
12188

122-
// // Stop program, if there is one running
123-
if (!g_my_dashboard->commandStop())
89+
if (!g_my_robot->isHealthy())
12490
{
125-
URCL_LOG_ERROR("Could not send stop program command");
91+
URCL_LOG_ERROR("Something in the robot initialization went wrong. Exiting. Please check the output above.");
12692
return 1;
12793
}
128-
129-
// Power it off
130-
// if (!g_my_dashboard->commandPowerOff())
131-
//{
132-
// URCL_LOG_ERROR("Could not send Power off command");
133-
// return 1;
134-
//}
135-
136-
// Power it on
137-
// if (!g_my_dashboard->commandPowerOn())
138-
//{
139-
// URCL_LOG_ERROR("Could not send Power on command");
140-
// return 1;
141-
//}
142-
143-
// Release the brakes
144-
// if (!g_my_dashboard->commandBrakeRelease())
145-
//{
146-
// URCL_LOG_ERROR("Could not send BrakeRelease command");
147-
// return 1;
148-
//}
149-
150-
// Now the robot is ready to receive a program
151-
std::unique_ptr<ToolCommSetup> tool_comm_setup;
152-
const bool headless = true;
153-
g_my_driver.reset(new UrDriver(robot_ip, SCRIPT_FILE, OUTPUT_RECIPE, INPUT_RECIPE, &handleRobotProgramState, headless,
154-
std::move(tool_comm_setup)));
155-
156-
if (!g_my_driver->checkCalibration(CALIBRATION_CHECKSUM))
94+
if (!g_my_robot->ur_driver_->checkCalibration(CALIBRATION_CHECKSUM))
15795
{
15896
URCL_LOG_ERROR("Calibration checksum does not match actual robot.");
15997
URCL_LOG_ERROR("Use the ur_calibration tool to extract the correct calibration from the robot and pass that into "
@@ -162,35 +100,31 @@ int main(int argc, char* argv[])
162100
"for details.");
163101
}
164102

165-
// Make sure that external control script is running
166-
if (!waitForProgramRunning())
167-
{
168-
URCL_LOG_ERROR("External Control script not running.");
169-
return 1;
170-
}
171103
// End of initialization -- We've started the external control program, which means we have to
172104
// write keepalive signals from now on. Otherwise the connection will be dropped.
173105

174106
// Start force mode
175107
// Task frame at the robot's base with limits being large enough to cover the whole workspace
176108
// Compliance in z axis and rotation around z axis
177109
bool success;
178-
if (g_my_driver->getVersion().major < 5)
179-
success = g_my_driver->startForceMode({ 0, 0, 0, 0, 0, 0 }, // Task frame at the robot's base
180-
{ 0, 0, 1, 0, 0, 1 }, // Compliance in z axis and rotation around z axis
181-
{ 0, 0, -2, 0, 0, 0 }, // Press in -z direction
182-
2, // do not transform the force frame at all
183-
{ 0.1, 0.1, 1.5, 3.14, 3.14, 0.5 }, // limits
184-
0.005); // damping_factor. See ScriptManual for details.
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.
185118
else
186119
{
187-
success = g_my_driver->startForceMode({ 0, 0, 0, 0, 0, 0 }, // Task frame at the robot's base
188-
{ 0, 0, 1, 0, 0, 1 }, // Compliance in z axis and rotation around z axis
189-
{ 0, 0, -2, 0, 0, 0 }, // Press in -z direction
190-
2, // do not transform the force frame at all
191-
{ 0.1, 0.1, 1.5, 3.14, 3.14, 0.5 }, // limits
192-
0.005, // damping_factor
193-
1.0); // gain_scaling. See ScriptManual for details.
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.
194128
}
195129
if (!success)
196130
{
@@ -204,13 +138,13 @@ int main(int argc, char* argv[])
204138
auto stopwatch_now = stopwatch_last;
205139
while (time_done < timeout || second_to_run.count() == 0)
206140
{
207-
g_my_driver->writeKeepalive();
141+
g_my_robot->ur_driver_->writeKeepalive();
208142

209143
stopwatch_now = std::chrono::steady_clock::now();
210144
time_done += stopwatch_now - stopwatch_last;
211145
stopwatch_last = stopwatch_now;
212146
std::this_thread::sleep_for(std::chrono::milliseconds(2));
213147
}
214148
URCL_LOG_INFO("Timeout reached.");
215-
g_my_driver->endForceMode();
149+
g_my_robot->ur_driver_->endForceMode();
216150
}

examples/freedrive_example.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,9 @@ int main(int argc, char* argv[])
8585
g_my_robot = std::make_unique<ExampleRobotWrapper>(robot_ip, OUTPUT_RECIPE, INPUT_RECIPE, headless_mode,
8686
"external_control.urp");
8787

88-
if (!g_my_robot->waitForProgramRunning())
88+
if (!g_my_robot->isHealthy())
8989
{
90-
URCL_LOG_ERROR("External Control script not running.");
90+
URCL_LOG_ERROR("Something in the robot initialization went wrong. Exiting. Please check the output above.");
9191
return 1;
9292
}
9393

0 commit comments

Comments
 (0)