Skip to content

Commit df643a8

Browse files
URJalamergify[bot]
authored andcommitted
Add force mode controller (#1049)
This enables using the robot's force_mode in a standalone controller. Force mode can be enabled and parametrized using a service call provided by the controller. --------- Co-authored-by: urmarp <[email protected]> Co-authored-by: Felix Exner <[email protected]> (cherry picked from commit e949995) # Conflicts: # ur_controllers/controller_plugins.xml # ur_controllers/doc/index.rst # ur_robot_driver/CMakeLists.txt # ur_robot_driver/config/ur_controllers.yaml # ur_robot_driver/doc/usage/controllers.rst # ur_robot_driver/include/ur_robot_driver/hardware_interface.hpp # ur_robot_driver/launch/ur_control.launch.py # ur_robot_driver/src/hardware_interface.cpp # ur_robot_driver/test/integration_test_controller_switch.py # ur_robot_driver/test/robot_driver.py # ur_robot_driver/urdf/ur.ros2_control.xacro
1 parent d2876cb commit df643a8

22 files changed

+2960
-14
lines changed

ur_controllers/CMakeLists.txt

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ endif()
88
find_package(ament_cmake REQUIRED)
99
find_package(angles REQUIRED)
1010
find_package(controller_interface REQUIRED)
11+
find_package(geometry_msgs REQUIRED)
1112
find_package(joint_trajectory_controller REQUIRED)
1213
find_package(lifecycle_msgs REQUIRED)
1314
find_package(pluginlib REQUIRED)
@@ -16,13 +17,16 @@ find_package(rcutils REQUIRED)
1617
find_package(realtime_tools REQUIRED)
1718
find_package(std_msgs REQUIRED)
1819
find_package(std_srvs REQUIRED)
20+
find_package(tf2_geometry_msgs REQUIRED)
21+
find_package(tf2_ros REQUIRED)
1922
find_package(ur_dashboard_msgs REQUIRED)
2023
find_package(ur_msgs REQUIRED)
2124
find_package(generate_parameter_library REQUIRED)
2225

2326
set(THIS_PACKAGE_INCLUDE_DEPENDS
2427
angles
2528
controller_interface
29+
geometry_msgs
2630
joint_trajectory_controller
2731
lifecycle_msgs
2832
pluginlib
@@ -31,13 +35,19 @@ set(THIS_PACKAGE_INCLUDE_DEPENDS
3135
realtime_tools
3236
std_msgs
3337
std_srvs
38+
tf2_geometry_msgs
39+
tf2_ros
3440
ur_dashboard_msgs
3541
ur_msgs
3642
generate_parameter_library
3743
)
3844

3945
include_directories(include)
4046

47+
generate_parameter_library(
48+
force_mode_controller_parameters
49+
src/force_mode_controller_parameters.yaml
50+
)
4151

4252
generate_parameter_library(
4353
gpio_controller_parameters
@@ -60,6 +70,7 @@ generate_parameter_library(
6070
)
6171

6272
add_library(${PROJECT_NAME} SHARED
73+
src/force_mode_controller.cpp
6374
src/scaled_joint_trajectory_controller.cpp
6475
src/speed_scaling_state_broadcaster.cpp
6576
src/gpio_controller.cpp
@@ -69,6 +80,7 @@ target_include_directories(${PROJECT_NAME} PRIVATE
6980
include
7081
)
7182
target_link_libraries(${PROJECT_NAME}
83+
force_mode_controller_parameters
7284
gpio_controller_parameters
7385
speed_scaling_state_broadcaster_parameters
7486
scaled_joint_trajectory_controller_parameters
@@ -110,4 +122,23 @@ ament_export_libraries(
110122
${PROJECT_NAME}
111123
)
112124

125+
if(BUILD_TESTING)
126+
find_package(ament_cmake_gmock REQUIRED)
127+
find_package(controller_manager REQUIRED)
128+
find_package(hardware_interface REQUIRED)
129+
find_package(ros2_control_test_assets REQUIRED)
130+
131+
add_definitions(-DTEST_FILES_DIRECTORY="${CMAKE_CURRENT_SOURCE_DIR}/test")
132+
ament_add_gmock(test_load_force_mode_controller
133+
test/test_load_force_mode_controller.cpp
134+
)
135+
target_link_libraries(test_load_force_mode_controller
136+
${PROJECT_NAME}
137+
)
138+
ament_target_dependencies(test_load_force_mode_controller
139+
controller_manager
140+
ros2_control_test_assets
141+
)
142+
endif()
143+
113144
ament_package()

ur_controllers/controller_plugins.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,19 @@
1414
This controller publishes the Tool IO.
1515
</description>
1616
</class>
17+
<<<<<<< HEAD
18+
=======
19+
<class name="ur_controllers/ForceModeController" type="ur_controllers::ForceModeController" base_class_type="controller_interface::ControllerInterface">
20+
<description>
21+
Controller to use UR's force_mode.
22+
</description>
23+
</class>
24+
<class name="ur_controllers/PassthroughTrajectoryController" type="ur_controllers::PassthroughTrajectoryController" base_class_type="controller_interface::ControllerInterface">
25+
<description>
26+
This controller forwards a joint-based trajectory to the robot controller for interpolation.
27+
</description>
28+
</class>
29+
>>>>>>> e949995 (Add force mode controller (#1049))
1730
<class name="ur_controllers/URConfigurationController" type="ur_controllers::URConfigurationController" base_class_type="controller_interface::ControllerInterface">
1831
<description>
1932
Controller used to get and change the configuration of the robot

ur_controllers/doc/index.rst

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,3 +135,211 @@ Advertised services
135135
* ``~/set_speed_slider [ur_msgs/srv/SetSpeedSliderFraction]``: Set the value of the speed slider.
136136
* ``~/zero_ftsensor [std_srvs/srv/Trigger]``: Zeroes the reported wrench of the force torque
137137
sensor.
138+
<<<<<<< HEAD
139+
=======
140+
141+
.. _passthrough_trajectory_controller:
142+
143+
ur_controllers/PassthroughTrajectoryController
144+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
145+
146+
This controller uses a ``control_msgs/FollowJointTrajectory`` action but instead of interpolating
147+
the trajectory on the ROS pc it forwards the complete trajectory to the robot controller for
148+
interpolation and execution. This way, the realtime requirements for the control PC can be
149+
massively decreased, since the robot always "knows" what to do next. That means that you should be
150+
able to run a stable driver connection also without a real-time patched kernel.
151+
152+
Interpolation depends on the robot controller's implementation, but in conjunction with the
153+
ur_robot_driver it defaults to mimicking ros2_control's spline interpolation. So, any trajectory
154+
planned e.g. with MoveIt! will be executed following the trajectory exactly.
155+
156+
A trajectory sent to the controller's action server will be forwarded to the robot controller and
157+
executed there. Once all setpoints are transferred to the robot, the controller goes into a waiting
158+
state where it waits for the trajectory to be finished. While waiting, the controller tracks the
159+
time spent on the trajectory to ensure the robot isn't stuck during execution.
160+
161+
This controller also supports **speed scaling** such that and scaling down of the trajectory done
162+
by the robot, for example due to safety settings on the robot or simply because a slower execution
163+
is configured on the teach pendant. This will be considered, during execution monitoring, so the
164+
controller basically tracks the scaled time instead of the real time.
165+
166+
.. note::
167+
168+
When using this controller with the URSim simulator execution times can be slightly larger than
169+
the expected time depending on the simulation host's resources. This effect will not be present
170+
when using a real UR arm.
171+
172+
.. note::
173+
174+
This controller can currently only be used with URSim or a real UR robot. Neither mock hardware
175+
nor gazebo support this type of trajectory interfaces at the time being.
176+
177+
Tolerances
178+
""""""""""
179+
180+
Currently, the trajectory passthrough controller only supports goal tolerances and goal time
181+
tolerances passed in the action directly. Please make sure that the tolerances are completely
182+
filled with all joint names.
183+
184+
A **goal time tolerance** of ``0.0`` means that no goal time tolerance is set and the action will
185+
not fail when execution takes too long.
186+
187+
Action interface / usage
188+
""""""""""""""""""""""""
189+
190+
To use this controller, publish a goal to the ``~/follow_joint_trajectory`` action interface
191+
similar to the `joint_trajectory_controller <https://control.ros.org/master/doc/ros2_controllers/joint_trajectory_controller/doc/userdoc.html>`_.
192+
193+
Currently, the controller doesn't support replacing a running trajectory action. While a trajectory
194+
is being executed, goals will be rejected until the action has finished. If you want to replace it,
195+
first cancel the running action and then send a new one.
196+
197+
Parameters
198+
""""""""""
199+
200+
The trajectory passthrough controller uses the following parameters:
201+
202+
+----------------------------------+--------------+----------------------------------------+------------------------------------------------------------------------------------------------------------------+
203+
| Parameter name | Type | Default value | Description |
204+
| | | | |
205+
+----------------------------------+--------------+----------------------------------------+------------------------------------------------------------------------------------------------------------------+
206+
| ``joints`` (required) | string_array | <empty> | Joint names to listen to |
207+
+----------------------------------+--------------+----------------------------------------+------------------------------------------------------------------------------------------------------------------+
208+
| ``state_interfaces`` (required) | string_array | <empty> | State interfaces provided by the hardware for all joints. Subset of ``["position", "velocity", "acceleration"]`` |
209+
+----------------------------------+--------------+----------------------------------------+------------------------------------------------------------------------------------------------------------------+
210+
| ``speed_scaling_interface_name`` | string | ``speed_scaling/speed_scaling_factor`` | Fully qualified name of the speed scaling interface name. |
211+
+----------------------------------+--------------+----------------------------------------+------------------------------------------------------------------------------------------------------------------+
212+
| ``tf_prefix`` | string | <empty> | Urdf prefix of the corresponding arm |
213+
+----------------------------------+--------------+----------------------------------------+------------------------------------------------------------------------------------------------------------------+
214+
215+
Interfaces
216+
""""""""""
217+
218+
In order to use this, the hardware has to export a command interface for passthrough operations for each joint. It always has
219+
to export position, velocity and acceleration interfaces in order to be able to project the full
220+
JointTrajectory definition. This is why there are separate fields used, as for passthrough mode
221+
accelerations might be relevant also for robots that don't support commanding accelerations
222+
directly to their joints.
223+
224+
.. code:: xml
225+
226+
<gpio name="${tf_prefix}trajectory_passthrough">
227+
<command_interface name="setpoint_positions_0"/>
228+
<command_interface name="setpoint_positions_1"/>
229+
<command_interface name="setpoint_positions_2"/>
230+
<command_interface name="setpoint_positions_3"/>
231+
<command_interface name="setpoint_positions_4"/>
232+
<command_interface name="setpoint_positions_5"/>
233+
<command_interface name="setpoint_velocities_0"/>
234+
<command_interface name="setpoint_velocities_1"/>
235+
<command_interface name="setpoint_velocities_2"/>
236+
<command_interface name="setpoint_velocities_3"/>
237+
<command_interface name="setpoint_velocities_4"/>
238+
<command_interface name="setpoint_velocities_5"/>
239+
<command_interface name="setpoint_accelerations_0"/>
240+
<command_interface name="setpoint_accelerations_1"/>
241+
<command_interface name="setpoint_accelerations_2"/>
242+
<command_interface name="setpoint_accelerations_3"/>
243+
<command_interface name="setpoint_accelerations_4"/>
244+
<command_interface name="setpoint_accelerations_5"/>
245+
<command_interface name="transfer_state"/>
246+
<command_interface name="time_from_start"/>
247+
<command_interface name="abort"/>
248+
</gpio>
249+
250+
.. note::
251+
252+
The hardware component has to take care that the passthrough command interfaces cannot be
253+
activated in parallel to the streaming command interfaces.
254+
255+
Implementation details / dataflow
256+
"""""""""""""""""""""""""""""""""
257+
258+
* A trajectory passed to the controller will be sent to the hardware component one by one.
259+
* The controller will send one setpoint and then wait for the hardware to acknowledge that it can
260+
take a new setpoint.
261+
* This happens until all setpoints have been transferred to the hardware. Then, the controller goes
262+
into a waiting state where it monitors execution time and waits for the hardware to finish
263+
execution.
264+
* If execution takes longer than anticipated, a warning will be printed.
265+
* If execution finished taking longer than expected (plus the goal time tolerance), the action will fail.
266+
* When the hardware reports that execution has been aborted (The ``passthrough_trajectory_abort``
267+
command interface), the action will be aborted.
268+
* When the action is preempted, execution on the hardware is preempted.
269+
270+
.. _force_mode_controller:
271+
272+
ur_controllers/ForceModeController
273+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
274+
275+
This controller activates the robot's *Force Mode*. This allows direct force control running on the
276+
robot control box. This controller basically interfaces the URScript function ``force_mode(...)``.
277+
278+
Force mode can be combined with (and only with) the :ref:`passthrough trajectory controller
279+
<passthrough_trajectory_controller>` in order to execute motions under a given force constraints.
280+
281+
.. note::
282+
This is not an admittance controller, as given force constraints in a certain Cartesian
283+
dimension will overwrite the motion commands in that dimension. E.g. when specifying a certain
284+
force in the base frame's ``z`` direction, any motion resulting from the move command in the
285+
base frame's ``z`` axis will not be executed.
286+
287+
Parameters
288+
""""""""""
289+
290+
+----------------------------------+--------+---------------+---------------------------------------------------------------------+
291+
| Parameter name | Type | Default value | Description |
292+
| | | | |
293+
+----------------------------------+--------+---------------+---------------------------------------------------------------------+
294+
| ``tf_prefix`` | string | <empty> | Urdf prefix of the corresponding arm |
295+
+----------------------------------+--------+---------------+---------------------------------------------------------------------+
296+
| ``check_io_successful_retries`` | int | 10 | Amount of retries for checking if setting force_mode was successful |
297+
+----------------------------------+--------+---------------+---------------------------------------------------------------------+
298+
299+
Service interface / usage
300+
"""""""""""""""""""""""""
301+
302+
The controller provides two services: One for activating force_mode and one for leaving it. To use
303+
those services, the controller has to be in ``active`` state.
304+
305+
* ``~/stop_force_mode [std_srvs/srv/Trigger]``: Stop force mode
306+
* ``~/start_force_mode [ur_msgs/srv/SetForceMode]``: Start force mode
307+
308+
In ``ur_msgs/srv/SetForceMode`` the fields have the following meanings:
309+
310+
task_frame
311+
All information (selection vector, wrench, limits, etc) will be considered to be relative
312+
to that pose. The pose's frame_id can be anything that is transformable to the robot's
313+
``base`` frame.
314+
selection_vector_<x,y,z,rx,ry,rz>
315+
1 means that the robot will be compliant in the corresponding axis of the task frame.
316+
wrench
317+
The forces/torques the robot will apply to its environment. The robot adjusts its position
318+
along/about compliant axis in order to achieve the specified force/torque. Values have no effect for non-
319+
compliant axes.
320+
Actual wrench applied may be lower than requested due to joint safety limits.
321+
type
322+
An integer [1;3] specifying how the robot interprets the force frame
323+
324+
1
325+
The force frame is transformed in a way such that its y-axis is aligned with a vector pointing
326+
from the robot tcp towards the origin of the force frame.
327+
2
328+
The force frame is not transformed.
329+
3
330+
The force frame is transformed in a way such that its x-axis is the projection of the robot tcp
331+
velocity vector onto the x-y plane of the force frame.
332+
speed_limits
333+
Maximum allowed tcp speed (relative to the task frame). This is **only relevant for axes marked as
334+
compliant** in the selection_vector.
335+
deviation_limits
336+
For **non-compliant axes**, these values are the maximum allowed deviation along/about an axis
337+
between the actual tcp position and the one set by the program.
338+
damping_factor
339+
Force mode damping factor. Sets the damping parameter in force mode. In range [0;1], default value is 0.025
340+
A value of 1 is full damping, so the robot will decelerate quickly if no force is present. A value of 0
341+
is no damping, here the robot will maintain the speed.
342+
gain_scaling
343+
Force mode gain scaling factor. Scales the gain in force mode. scaling parameter is in range [0;2], default is 0.5.
344+
A value larger than 1 can make force mode unstable, e.g. in case of collisions or pushing against hard surfaces.
345+
>>>>>>> e949995 (Add force mode controller (#1049))

0 commit comments

Comments
 (0)