Skip to content

Commit 1a95cf9

Browse files
urfeexurmahpdomire8
authored
Direct torque control (#381)
This PR adds the functionality to command the robot by sending joint torques directly. --------- Co-authored-by: Mads Holm Peters <79145214+urmahp@users.noreply.github.com> Co-authored-by: Dominic Reber <71256590+domire8@users.noreply.github.com>
1 parent 6c27110 commit 1a95cf9

18 files changed

+733
-14
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ The library has no external dependencies besides the standard C++ libraries such
88
to make it easy to integrate and maintain. It also serves as the foundation for the ROS and ROS 2
99
drivers.
1010

11+
---
12+
1113
<!-- markdownlint-disable MD033 -->
1214
<div align="center">
1315
<img src="doc/resources/family_photo.png" alt="Universal Robot family" style="width: 90%;"/>

doc/architecture/reverse_interface.rst

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ meaning:
5757
- freedrive instruction (FREEDRIVE)
5858

5959
- field 1: Freedrive mode (1: FREEDRIVE_MODE_START, -1: FREEDRIVE_MODE_STOP)
60+
- target joint torques (TORQUE, see :ref:`direct_torque_control_mode`).
6061

6162
7 Control mode. Can be either of
6263

@@ -72,6 +73,7 @@ meaning:
7273
- 7: TOOL_IN_CONTACT -- status - not meant to be sent.
7374
In tool contact mode this will
7475
encode whether tool contact has been established or not.
76+
- 8: TORQUE -- :ref:`direct_torque_control_mode` (since PolyScope 5.23.0 / 10.10.0)
7577
===== =====
7678

7779
.. note::
@@ -84,4 +86,19 @@ meaning:
8486
``MULT_JOINTSTATE`` constant to get the actual floating point value. This constant is defined in
8587
``ReverseInterface`` class.
8688

87-
Depending on the control mode one can use the ``write()`` (SERVOJ, SPEEDJ, SPEEDL, POSE), ``writeTrajectoryControlMessage()`` (FORWARD) or ``writeFreedriveControlMessage()`` (FREEDRIVE) function to write a message to the "reverse_socket".
89+
Depending on the control mode one can use the ``write()`` (SERVOJ, SPEEDJ, SPEEDL, POSE, TORQUE), ``writeTrajectoryControlMessage()`` (FORWARD) or ``writeFreedriveControlMessage()`` (FREEDRIVE) function to write a message to the "reverse_socket".
90+
91+
.. _direct_torque_control_mode:
92+
93+
Direct torque control mode
94+
~~~~~~~~~~~~~~~~~~~~~~~~~~
95+
96+
Direct torque control mode is available since PolyScope version 5.23.0 / 10.10.0. It allows to command
97+
joint torques directly to the robot.
98+
99+
.. note:: Target torques are given **after** gravity compensation. A vector of zeros will hold the current position
100+
given that the payload is known to the controller.
101+
102+
.. warning:: Direct torque control is a very low-level command interface. Commanding high torques in
103+
free space can make the robot move very fast and hereby trigger a fault due to joint velocities
104+
or the TCP speed violating the safety settings. Keep that in mind when using this mode.

doc/architecture/script_command_interface.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ At the time of writing the ``ScriptCommandInterface`` provides the following fun
2020
contact example
2121
<https://github.com/UniversalRobots/Universal_Robots_Client_Library/blob/master/examples/tool_contact_example.cpp>`_
2222
for more information.
23+
- ``setFrictionCompensation()``: Set friction compensation for torque command.
2324

2425
Communication protocol
2526
----------------------
@@ -48,6 +49,7 @@ The robot reads from the "script_command_socket" expecting a 32 bit integer repr
4849
- 4: endForceMode
4950
- 5: startToolContact
5051
- 6: endToolContact
52+
- 7: setFrictionCompensation
5153
1-27 data fields specific to the command
5254
===== =====
5355

@@ -121,6 +123,15 @@ The robot reads from the "script_command_socket" expecting a 32 bit integer repr
121123
1 No specific meaning / values ignored
122124
===== =====
123125

126+
.. table:: With setFrictionCompensation command
127+
:widths: auto
128+
129+
===== =====
130+
index meaning
131+
===== =====
132+
1 friction_compensation_enabled enable/disable friction compensation for torque command.
133+
===== =====
134+
124135
.. note::
125136
In URScript the ``socket_read_binary_integer()`` function is used to read the data from the
126137
script command socket. The first index in that function's return value is the number of integers read,

doc/examples.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,10 @@ may be running forever until manually stopped.
2323
examples/primary_pipeline
2424
examples/primary_pipeline_calibration
2525
examples/rtde_client
26+
examples/script_command_interface
2627
examples/script_sender
2728
examples/spline_example
2829
examples/tool_contact_example
30+
examples/direct_torque_control
2931
examples/trajectory_point_interface
3032
examples/ur_driver
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
:github_url: https://github.com/UniversalRobots/Universal_Robots_Client_Library/blob/master/doc/examples/direct_torque_control.rst
2+
3+
.. _direct_torque_control_example:
4+
5+
Torque control example
6+
======================
7+
8+
In the ``examples`` subfolder you will find a minimal example for commanding torques to the robot.
9+
It moves the robot in the 5th axis back and forth, while reading the joint positions. To run it
10+
make sure to
11+
12+
* have an instance of a robot controller / URSim running at the configured IP address (or adapt the
13+
address to your needs)
14+
* have PolyScope version 5.23.0 / 10.10.0 or later installed on the robot.
15+
* run it from the package's main folder (the one where the README.md file is stored), as for
16+
simplicity reasons it doesn't use any sophisticated method to locate the required files.
17+
18+
This page will walk you through the `full_driver.cpp
19+
<https://github.com/UniversalRobots/Universal_Robots_Client_Library/blob/master/examples/full_driver.cpp>`_
20+
example.
21+
22+
Initialization
23+
--------------
24+
25+
At first, we create a ``ExampleRobotWrapper`` object giving it the robot's IP address, script file and RTDE
26+
recipes.
27+
28+
.. literalinclude:: ../../examples/direct_torque_control.cpp
29+
:language: c++
30+
:caption: examples/direct_torque_control.cpp
31+
:linenos:
32+
:lineno-match:
33+
:start-at: bool headless_mode = true;
34+
:end-at: // --------------- INITIALIZATION END -------------------
35+
36+
.. note::
37+
This example requires PolyScope version 5.23.0 / 10.10.0 or later, as it uses the direct_torque_control
38+
mode which is only available in these versions and later. If you try to run it on an older
39+
software version, this example will print an error and exit.
40+
41+
Robot control loop
42+
------------------
43+
44+
This example reads the robot's joint positions, commands a torque for the 5th axis and sends that
45+
back as a joint command for the next cycle. This way, the robot will move its wrist first until a
46+
positive limit and then back to 0.
47+
48+
To read the joint data, the driver's RTDE client is used:
49+
50+
51+
.. literalinclude:: ../../examples/direct_torque_control.cpp
52+
:language: c++
53+
:caption: examples/direct_torque_control.cpp
54+
:linenos:
55+
:lineno-match:
56+
:start-at: // Once RTDE communication is started
57+
:end-before: // Open loop control
58+
59+
The first read operation will initialize the target buffer with the current robot position. Next,
60+
the target joint torques are set based on the current joint positions:
61+
62+
63+
.. literalinclude:: ../../examples/direct_torque_control.cpp
64+
:language: c++
65+
:caption: examples/direct_torque_control.cpp
66+
:linenos:
67+
:lineno-match:
68+
:start-at: // Open loop control
69+
:end-at: target_torques[JOINT_INDEX] = cmd_torque;
70+
71+
To send the control command, the robot's :ref:`reverse_interface` is used via the
72+
``writeJointCommand()`` function:
73+
74+
.. literalinclude:: ../../examples/direct_torque_control.cpp
75+
:language: c++
76+
:caption: examples/direct_torque_control.cpp
77+
:linenos:
78+
:lineno-match:
79+
:start-at: // Setting the RobotReceiveTimeout
80+
:end-before: URCL_LOG_DEBUG("data_pkg:\n%s", data_pkg->toString().c_str());
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
:github_url: https://github.com/UniversalRobots/Universal_Robots_Client_Library/blob/master/doc/examples/script_command_interface.rst
2+
3+
Script command interface
4+
========================
5+
6+
The :ref:`script_command_interface` allows sending predefined commands to the robot while there is
7+
URScript running that is connected to it.
8+
9+
An example to utilize the script command interface can be found in the `freedrive_example.cpp <https://github.com/UniversalRobots/Universal_Robots_Client_Library/blob/master/examples/script_command_interface.cpp>`_.
10+
11+
In order to use the ``ScriptCommandInterface``, there has to be a script code running on the robot
12+
that connects to the ``ScriptCommandInterface``. This happens as part of the big
13+
`external_control.urscript <https://github.com/UniversalRobots/Universal_Robots_Client_Library/blob/master/resources/external_control.urscript>`_. In order to reuse that with this example, we will create a full
14+
``UrDriver`` and leverage the ``ScriptCommandInterface`` through this.
15+
16+
At first, we create a ``ExampleRobotWrapper`` object in order to initialize communication with the
17+
robot.
18+
19+
.. literalinclude:: ../../examples/script_command_interface.cpp
20+
:language: c++
21+
:caption: examples/script_command_interface.cpp
22+
:linenos:
23+
:lineno-match:
24+
:start-at: g_my_robot =
25+
:end-at: std::thread script_command_send_thread(sendScriptCommands);
26+
27+
The script commands will be sent in a separate thread which will be explained later.
28+
29+
Since the connection to the script command interface runs as part of the bigger external_control
30+
script, we'll wrap the calls alongside a full ``ExampleRobotWrapper``. Hence, we'll have to send
31+
keepalive signals regularly to keep the script running:
32+
33+
.. literalinclude:: ../../examples/script_command_interface.cpp
34+
:language: c++
35+
:caption: examples/script_command_interface.cpp
36+
:linenos:
37+
:lineno-match:
38+
:start-at: std::chrono::duration<double> time_done(0);
39+
:end-at: g_my_robot->getUrDriver()->stopControl();
40+
41+
Sending script commands
42+
-----------------------
43+
44+
Once the script is running on the robot, a connection to the driver's script command interface
45+
should be established. The ``UrDriver`` forwards most calls of the ``ScriptCommandInterface`` and
46+
we will use that interface in this example. To send a script command, we can e.g. use
47+
``g_my_robot->getUrDriver()->zeroFTSensor()``.
48+
49+
In the example, we have wrapped the calls into a lambda function that will wait a specific timeout,
50+
print a log output what command will be sent and then call the respective command:
51+
52+
.. literalinclude:: ../../examples/script_command_interface.cpp
53+
:language: c++
54+
:caption: examples/script_command_interface.cpp
55+
:linenos:
56+
:lineno-match:
57+
:start-at: run_cmd(
58+
:end-before: URCL_LOG_INFO("Script command thread finished.");
59+
60+
The lambda itself looks like this:
61+
62+
.. literalinclude:: ../../examples/script_command_interface.cpp
63+
:language: c++
64+
:caption: examples/script_command_interface.cpp
65+
:linenos:
66+
:lineno-match:
67+
:start-at: auto run_cmd =
68+
:end-before: // Keep running all commands in a loop
69+
70+
For a list of all available script commands, please refer to the ``ScriptCommandInterface`` class
71+
`here <https://github.com/UniversalRobots/Universal_Robots_Client_Library/blob/master/include/ur_client_library/control/script_command_interface.h>`_.

doc/polyscope_compatibility.rst

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
|polyscope| version compatibility
44
=================================
55

6+
Version-breaking changes
7+
------------------------
8+
69
The table below shows breaking changes in the library compared to |polyscope| versions. Compatibility
710
is listed for CB3 robots (versions 3.x.y) and e-Series robots (versions 5.x.y) respectively.
811

@@ -44,3 +47,17 @@ table below or checkout the latest tag before the breaking changes were introduc
4447
See `Universal Robots External Control URCapX <https://github.com/UniversalRobots/Universal_Robots_ExternalControl_URCapX>`_
4548

4649
.. |polyscope| replace:: PolyScope
50+
51+
Features requiring a specific |polyscope| version
52+
-------------------------------------------------
53+
54+
Features in this section have been added in a backwards-compatible way. It is still possible to use
55+
this library with an older compatible version, but trying to use one of the features below might
56+
lead to a runtime exception.
57+
58+
Torque control (From version 2.4.0)
59+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
60+
61+
The direct torque control mode is only available on |polyscope| 5.23.0 / 10.10.0 and later. This
62+
includes the ``TORQUE`` control mode in the ``ReverseInterface`` as well as the
63+
``setFrictionCompensation()`` function in the ``ScriptCommandInterface``.

examples/CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,14 @@ add_executable(script_sender_example
4444
script_sender.cpp)
4545
target_link_libraries(script_sender_example ur_client_library::urcl)
4646

47+
add_executable(script_command_interface_example
48+
script_command_interface.cpp)
49+
target_link_libraries(script_command_interface_example ur_client_library::urcl)
50+
51+
add_executable(direct_torque_control_example
52+
direct_torque_control.cpp)
53+
target_link_libraries(direct_torque_control_example ur_client_library::urcl)
54+
4755
add_executable(trajectory_point_interface_example
4856
trajectory_point_interface.cpp)
4957
target_link_libraries(trajectory_point_interface_example ur_client_library::urcl)

0 commit comments

Comments
 (0)