Skip to content

Commit d392c39

Browse files
committed
Add documentation for force_mode example
1 parent af7a315 commit d392c39

File tree

3 files changed

+87
-40
lines changed

3 files changed

+87
-40
lines changed

doc/examples.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,5 @@ starting point for your own applications.
1111
:maxdepth: 1
1212

1313
examples/dashboard_client
14+
examples/force_mode
1415
examples/ur_driver

doc/examples/force_mode.rst

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
:github_url: https://github.com/UniversalRobots/Universal_Robots_Client_Library/blob/master/doc/examples/force_mode.rst
2+
3+
Force Mode example
4+
==================
5+
6+
The ``ur_client_library`` supports leveraging the robot's force mode directly. An example on how to
7+
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>`_.
8+
9+
In order to utilize force mode, we'll have to create and initialize a full ``UrDriver`` object
10+
first:
11+
12+
.. literalinclude:: ../../examples/force_mode_example.cpp
13+
:language: c++
14+
:caption: examples/force_mode_example.cpp
15+
:linenos:
16+
:lineno-match:
17+
:start-at: // Now the robot is ready to receive a program
18+
:end-at: // End of initialization
19+
20+
Start force mode
21+
----------------
22+
23+
After that, we can start force mode by calling the ``startForceMode()`` function:
24+
25+
.. literalinclude:: ../../examples/force_mode_example.cpp
26+
:language: c++
27+
:caption: examples/force_mode_example.cpp
28+
:linenos:
29+
:lineno-match:
30+
:start-at: // Start force mode
31+
:end-at: if (!success)
32+
33+
All parameters for the force mode are included into the ``startForceMode()`` function call. If you
34+
want to change the parameters, e.g. change the forces applied, you can simply call
35+
``startForceMode()`` again with the new parameters.
36+
37+
.. note::
38+
CB3 robots don't support specifying force_mode's ``gain_scaling``, so there are two different
39+
functions available.
40+
41+
Once force mode is started successfully, we'll have to send keepalive messages to the robot in
42+
order to keep the communication active:
43+
44+
.. literalinclude:: ../../examples/force_mode_example.cpp
45+
:language: c++
46+
:caption: examples/force_mode_example.cpp
47+
:linenos:
48+
:lineno-match:
49+
:start-at: std::chrono::duration<double> time_done(0);
50+
:end-at: URCL_LOG_INFO("Timeout reached.");
51+
52+
Stop force mode
53+
---------------
54+
55+
Once finished, force_mode can be stopped by calling ``endForceMode()``.
56+
57+
.. literalinclude:: ../../examples/force_mode_example.cpp
58+
:language: c++
59+
:caption: examples/force_mode_example.cpp
60+
:linenos:
61+
:lineno-match:
62+
:start-at: endForceMode()
63+
:end-at: endForceMode()

examples/force_mode_example.cpp

Lines changed: 23 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -162,72 +162,55 @@ int main(int argc, char* argv[])
162162
"for details.");
163163
}
164164

165-
// Once RTDE communication is started, we have to make sure to read from the interface buffer, as
166-
// otherwise we will get pipeline overflows. Therefore, do this directly before starting your main
167-
// loop.
168-
g_my_driver->startRTDECommunication();
169-
170-
std::chrono::duration<double> time_done(0);
171-
std::chrono::duration<double> timeout(second_to_run);
172-
auto stopwatch_last = std::chrono::steady_clock::now();
173-
auto stopwatch_now = stopwatch_last;
174165
// Make sure that external control script is running
175166
if (!waitForProgramRunning())
176167
{
177168
URCL_LOG_ERROR("External Control script not running.");
178169
return 1;
179170
}
171+
// End of initialization -- We've started the external control program, which means we have to
172+
// write keepalive signals from now on. Otherwise the connection will be dropped.
173+
174+
// Start force mode
180175
// Task frame at the robot's base with limits being large enough to cover the whole workspace
181176
// Compliance in z axis and rotation around z axis
182177
bool success;
183178
if (g_my_driver->getVersion().major < 5)
184-
success = g_my_driver->startForceMode({ 0, 0, 0, 0, 0, 0 }, // Task frame at the robot's base
185-
{ 0, 0, 1, 0, 0, 1 }, // Compliance in z axis and rotation around z axis
186-
{ 0, 0, 0, 0, 0, 0 }, // do not apply any active wrench
187-
2, // do not transform the force frame at all
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
188183
{ 0.1, 0.1, 1.5, 3.14, 3.14, 0.5 }, // limits
189-
0.025); // damping_factor. See ScriptManual for details.
184+
0.005); // damping_factor. See ScriptManual for details.
190185
else
191186
{
192-
success = g_my_driver->startForceMode({ 0, 0, 0, 0, 0, 0 }, // Task frame at the robot's base
193-
{ 0, 0, 1, 0, 0, 1 }, // Compliance in z axis and rotation around z axis
194-
{ 0, 0, 0, 0, 0, 0 }, // do not apply any active wrench
195-
2, // do not transform the force frame at all
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
196191
{ 0.1, 0.1, 1.5, 3.14, 3.14, 0.5 }, // limits
197-
0.025, // damping_factor
198-
0.8); // gain_scaling. See ScriptManual for details.
192+
0.005, // damping_factor
193+
1.0); // gain_scaling. See ScriptManual for details.
199194
}
200195
if (!success)
201196
{
202197
URCL_LOG_ERROR("Failed to start force mode.");
203198
return 1;
204199
}
205200

206-
while (true)
201+
std::chrono::duration<double> time_done(0);
202+
std::chrono::duration<double> timeout(second_to_run);
203+
auto stopwatch_last = std::chrono::steady_clock::now();
204+
auto stopwatch_now = stopwatch_last;
205+
while (time_done < timeout || second_to_run.count() == 0)
207206
{
208-
// Read latest RTDE package. This will block for a hard-coded timeout (see UrDriver), so the
209-
// robot will effectively be in charge of setting the frequency of this loop.
210-
// In a real-world application this thread should be scheduled with real-time priority in order
211-
// to ensure that this is called in time.
212-
std::unique_ptr<rtde_interface::DataPackage> data_pkg = g_my_driver->getDataPackage();
213-
if (data_pkg)
214-
{
215-
g_my_driver->writeKeepalive();
216-
217-
if (time_done > timeout && second_to_run.count() != 0)
218-
{
219-
URCL_LOG_INFO("Timeout reached.");
220-
break;
221-
}
222-
}
223-
else
224-
{
225-
URCL_LOG_WARN("Could not get fresh data package from robot");
226-
}
207+
g_my_driver->writeKeepalive();
227208

228209
stopwatch_now = std::chrono::steady_clock::now();
229210
time_done += stopwatch_now - stopwatch_last;
230211
stopwatch_last = stopwatch_now;
212+
std::this_thread::sleep_for(std::chrono::milliseconds(2));
231213
}
214+
URCL_LOG_INFO("Timeout reached.");
232215
g_my_driver->endForceMode();
233216
}

0 commit comments

Comments
 (0)