Skip to content

Commit 07a2147

Browse files
committed
Add example documentation for trajectory_point_interface
1 parent b1a9bb1 commit 07a2147

File tree

3 files changed

+132
-3
lines changed

3 files changed

+132
-3
lines changed

doc/examples.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,5 @@ may be running forever until manually stopped.
2424
examples/script_sender
2525
examples/spline_example
2626
examples/tool_contact_example
27+
examples/trajectory_point_interface
2728
examples/ur_driver
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
:github_url: https://github.com/UniversalRobots/Universal_Robots_Client_Library/blob/master/doc/examples/trajecotry_joint_interface_example.rst
2+
3+
.. _trajecotry_joint_interface_example:
4+
5+
Trajectory Joint Interface example
6+
==================================
7+
8+
9+
10+
At first, we create a ``UrDriver`` object as usual:
11+
12+
.. literalinclude:: ../../examples/trajectory_point_interface.cpp
13+
:language: c++
14+
:caption: examples/trajectory_point_interface.cpp
15+
:linenos:
16+
:lineno-match:
17+
:start-at: std::unique_ptr<urcl::ToolCommSetup> tool_comm_setup;
18+
:end-before: // --------------- INITIALIZATION END -------------------
19+
20+
We use a small helper function to make sure that the reverse interface is active and connected
21+
before proceeding.
22+
23+
24+
Initialization
25+
--------------
26+
27+
As trajectory execution will be triggered asynchronously, we define a callback function to handle a
28+
finished trajectory. A trajectory is considered finished when the robot is no longer executing it,
29+
independent of whether it successfully reached its final point. The trajectory result will reflect
30+
whether it was executed successfully, was canceled upon request or failed for some reason.
31+
32+
.. literalinclude:: ../../examples/trajectory_point_interface.cpp
33+
:language: c++
34+
:caption: examples/trajectory_point_interface.cpp
35+
:linenos:
36+
:lineno-match:
37+
:start-at: void trajDoneCallback(const urcl::control::TrajectoryResult& result)
38+
:end-at: }
39+
40+
That callback can be registered at the ``UrDriver`` object:
41+
42+
43+
.. literalinclude:: ../../examples/trajectory_point_interface.cpp
44+
:language: c++
45+
:caption: examples/trajectory_point_interface.cpp
46+
:linenos:
47+
:lineno-match:
48+
:start-at: g_my_driver->registerTrajectoryDoneCallback(&trajDoneCallback);
49+
:end-at: g_my_driver->registerTrajectoryDoneCallback(&trajDoneCallback);
50+
51+
52+
MoveJ Trajectory
53+
----------------
54+
55+
Then, in order to execute a trajectory, we need to define a trajectory as a sequence of points and
56+
parameters. The following example shows execution of a 2-point trajectory using URScript's
57+
``movej`` function:
58+
59+
.. literalinclude:: ../../examples/trajectory_point_interface.cpp
60+
:language: c++
61+
:caption: examples/trajectory_point_interface.cpp
62+
:linenos:
63+
:lineno-match:
64+
:start-after: // --------------- MOVEJ TRAJECTORY -------------------
65+
:end-before: // --------------- END MOVEJ TRAJECTORY -------------------
66+
67+
In fact, the path is followed twice, once parametrized by a segment duration and once using maximum
68+
velocity / acceleration settings. If a duration > 0 is given for a segment, the velocity and
69+
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
71+
``movej`` command in URScript.
72+
73+
While the trajectory is running, we need to tell the robot program that connection is still active
74+
and we expect the trajectory to be running. This is being done by the
75+
``g_my_driver->writeTrajectoryControlMessage(urcl::control::TrajectoryControlMessage::TRAJECTORY_NOOP);``
76+
call.
77+
78+
MoveL Trajectory
79+
----------------
80+
81+
Similar to the ``movej``-based trajectory, execution can be done interpolating in joint space:
82+
83+
.. literalinclude:: ../../examples/trajectory_point_interface.cpp
84+
:language: c++
85+
:caption: examples/trajectory_point_interface.cpp
86+
:linenos:
87+
:lineno-match:
88+
:start-after: // --------------- MOVEL TRAJECTORY -------------------
89+
:end-before: // --------------- END MOVEL TRAJECTORY -------------------
90+
91+
Spline based interpolation
92+
--------------------------
93+
94+
Similar to the :ref:`spline_example`, the trajectory point interface can be used to execute motions
95+
using the spline interpolation:
96+
97+
.. literalinclude:: ../../examples/trajectory_point_interface.cpp
98+
:language: c++
99+
:caption: examples/trajectory_point_interface.cpp
100+
:linenos:
101+
:lineno-match:
102+
:start-after: // --------------- SPLINE TRAJECTORY -------------------
103+
:end-before: // --------------- END SPLINE TRAJECTORY -------------------

examples/trajectory_point_interface.cpp

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,18 +42,38 @@ const std::string DEFAULT_ROBOT_IP = "192.168.56.101";
4242
const std::string SCRIPT_FILE = "resources/external_control.urscript";
4343
const std::string OUTPUT_RECIPE = "examples/resources/rtde_output_recipe.txt";
4444
const std::string INPUT_RECIPE = "examples/resources/rtde_input_recipe.txt";
45-
const std::string CALIBRATION_CHECKSUM = "calib_12788084448423163542";
4645

4746
std::unique_ptr<urcl::DashboardClient> g_my_dashboard;
4847
std::unique_ptr<urcl::UrDriver> g_my_driver;
4948

5049
std::atomic<bool> g_trajectory_done = false;
5150

51+
std::atomic<bool> g_program_running;
52+
std::condition_variable g_program_running_cv;
53+
std::mutex g_program_running_mutex;
54+
55+
bool waitForProgramRunning(int milliseconds = 100)
56+
{
57+
std::unique_lock<std::mutex> lk(g_program_running_mutex);
58+
if (g_program_running_cv.wait_for(lk, std::chrono::milliseconds(milliseconds)) == std::cv_status::no_timeout ||
59+
g_program_running == true)
60+
{
61+
return true;
62+
}
63+
return false;
64+
}
65+
5266
// We need a callback function to register. See UrDriver's parameters for details.
5367
void handleRobotProgramState(bool program_running)
5468
{
5569
// Print the text in green so we see it better
5670
std::cout << "\033[1;32mProgram running: " << std::boolalpha << program_running << "\033[0m\n" << std::endl;
71+
g_program_running = program_running;
72+
if (program_running)
73+
{
74+
std::lock_guard<std::mutex> lk(g_program_running_mutex);
75+
g_program_running_cv.notify_one();
76+
}
5777
}
5878

5979
void trajDoneCallback(const urcl::control::TrajectoryResult& result)
@@ -113,7 +133,12 @@ int main(int argc, char* argv[])
113133
std::unique_ptr<urcl::ToolCommSetup> tool_comm_setup;
114134
const bool headless = true;
115135
g_my_driver.reset(new urcl::UrDriver(robot_ip, SCRIPT_FILE, OUTPUT_RECIPE, INPUT_RECIPE, &handleRobotProgramState,
116-
headless, std::move(tool_comm_setup), CALIBRATION_CHECKSUM));
136+
headless, std::move(tool_comm_setup)));
137+
if (!waitForProgramRunning(1000))
138+
{
139+
URCL_LOG_ERROR("Program did not start running. Is the robot in remote control?");
140+
return 1;
141+
}
117142
// --------------- INITIALIZATION END -------------------
118143

119144
g_my_driver->registerTrajectoryDoneCallback(&trajDoneCallback);
@@ -218,7 +243,7 @@ int main(int argc, char* argv[])
218243
g_my_driver->writeTrajectoryControlMessage(urcl::control::TrajectoryControlMessage::TRAJECTORY_NOOP);
219244
}
220245
}
221-
// --------------- END MOVEJ TRAJECTORY -------------------
246+
// --------------- END SPLINE TRAJECTORY -------------------
222247

223248
g_my_driver->stopControl();
224249
return 0;

0 commit comments

Comments
 (0)