Skip to content

Commit 428c20d

Browse files
Merge branch 'master' into tl-expected
2 parents 2867bce + a014322 commit 428c20d

22 files changed

+1025
-393
lines changed

doc/migration.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ joint_state_broadcaster
88
*****************************
99
* Removed interfaces with other data types than double for publishing to ``dynamic_joint_states``. (`#2115 <https://github.com/ros-controls/ros2_controllers/pull/2115>`_).
1010
Use a custom controller for publishing non-double interfaces.
11+
* Parameter ``publish_dynamic_joint_states`` is now deprecated (default changed to ``false``). (`#2107 <https://github.com/ros-controls/ros2_controllers/pull/2107>`_)
12+
For publishing non-standard interfaces, consider using alternatives:
13+
14+
* :ref:`state_interfaces_broadcaster <state_interfaces_broadcaster_userdoc>` for broadcasting arbitrary state interfaces
15+
* :ref:`gpio_controllers <gpio_controllers_userdoc>` for GPIO and custom hardware interfaces
16+
* `pal_statistics <https://github.com/pal-robotics/pal_statistics>`_ for flexible runtime statistics publishing
1117

1218
effort_controllers
1319
*****************************

doc/release_notes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ joint_state_broadcaster
3030
* Make all parameters read-only (the never got re-evaluated after initialization anyways). (`#2064 <https://github.com/ros-controls/ros2_controllers/pull/2064>`_)
3131
* Added parameter ``publish_dynamic_joint_states`` to enable/disable publishing of dynamic joint states. (`#2064 <https://github.com/ros-controls/ros2_controllers/pull/2064>`_)
3232
* Removed interfaces with other data types than double for publishing to ``dynamic_joint_states``. (`#2115 <https://github.com/ros-controls/ros2_controllers/pull/2115>`_)
33+
* Parameter ``publish_dynamic_joint_states`` is now deprecated (default changed to ``false``).
3334

3435
omni_wheel_drive_controller
3536
*****************************
@@ -43,6 +44,7 @@ joint_trajectory_controller
4344
don't contain velocity / acceleration information, but the trajectory does. This way, the segment
4445
up to the first waypoint will use the same interpolation as the rest of the trajectory. (`#2043
4546
<https://github.com/ros-controls/ros2_controllers/pull/2043>`_)
47+
* Added decelerate-to-stop functionality when a trajectory is canceled or preempted. Instead of immediately holding position, the controller can now smoothly decelerate each joint to a stop using the per-joint ``max_deceleration_on_cancel`` parameter. (`#2163 <https://github.com/ros-controls/ros2_controllers/pull/2163>`_)
4648

4749
pid_controller
4850
**************

joint_state_broadcaster/src/joint_state_broadcaster.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,14 @@ controller_interface::CallbackReturn JointStateBroadcaster::on_configure(
9292
{
9393
params_ = param_listener_->get_params();
9494

95+
if (params_.publish_dynamic_joint_states)
96+
{
97+
RCLCPP_WARN(
98+
get_node()->get_logger(),
99+
"[Deprecated] The 'publish_dynamic_joint_states' parameter is deprecated and will be removed "
100+
"in future releases. Please update your configuration.");
101+
}
102+
95103
if (use_all_available_interfaces())
96104
{
97105
RCLCPP_INFO(
@@ -420,8 +428,13 @@ controller_interface::return_type JointStateBroadcaster::update(
420428
const auto & opt = state_interfaces_[i].get_optional(0);
421429
if (opt.has_value())
422430
{
423-
*mapped_values_[map_index++] = opt.value();
431+
*mapped_values_[map_index] = opt.value();
424432
}
433+
// Always advance map_index for every DOUBLE interface, regardless of whether the read
434+
// succeeded. If we only advance on success, a temporary read failure (e.g. lock contention
435+
// on a chained interface) causes all subsequent interfaces to be written into the wrong
436+
// mapped_values_ slots, corrupting the published joint states.
437+
++map_index;
425438
}
426439
}
427440

joint_state_broadcaster/src/joint_state_broadcaster_parameters.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ joint_state_broadcaster:
6262
}
6363
publish_dynamic_joint_states: {
6464
type: bool,
65-
default_value: true,
65+
default_value: false,
6666
read_only: true,
67-
description: "Whether to publish dynamic joint states."
67+
description: "[Deprecated] Whether to publish dynamic joint states. This parameter is deprecated and will be removed in future releases."
6868
}

joint_state_broadcaster/test/test_joint_state_broadcaster.cpp

Lines changed: 106 additions & 368 deletions
Large diffs are not rendered by default.

joint_state_broadcaster/test/test_joint_state_broadcaster.hpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ class FriendJointStateBroadcaster : public joint_state_broadcaster::JointStateBr
3434
{
3535
FRIEND_TEST(JointStateBroadcasterTest, ConfigureErrorTest);
3636
FRIEND_TEST(JointStateBroadcasterTest, ActivateEmptyTest);
37-
FRIEND_TEST(JointStateBroadcasterTest, ActivateEmptyWithoutDynamicJointStatesPublisherTest);
3837
FRIEND_TEST(JointStateBroadcasterTest, ReactivateTheControllerWithDifferentInterfacesTest);
3938
FRIEND_TEST(JointStateBroadcasterTest, ActivateTestWithoutJointsParameter);
4039
FRIEND_TEST(JointStateBroadcasterTest, ActivateTestWithoutJointsParameterInvalidURDF);
@@ -52,6 +51,7 @@ class FriendJointStateBroadcaster : public joint_state_broadcaster::JointStateBr
5251
FRIEND_TEST(JointStateBroadcasterTest, ExtraJointStatePublishTest);
5352
FRIEND_TEST(JointStateBroadcasterTest, NoThrowWithBooleanInterfaceTest);
5453
FRIEND_TEST(JointStateBroadcasterTest, NoThrowWithBooleanAndDoubleInterfaceTest);
54+
FRIEND_TEST(JointStateBroadcasterTest, CorrectMappingWhenInterfaceReadFailsTest);
5555
};
5656

5757
class JointStateBroadcasterTest : public ::testing::Test
@@ -79,8 +79,6 @@ class JointStateBroadcasterTest : public ::testing::Test
7979

8080
void test_published_joint_state_message(const std::string & topic);
8181

82-
void test_published_dynamic_joint_state_message(const std::string & topic);
83-
8482
void activate_and_get_joint_state_message(
8583
const std::string & topic, sensor_msgs::msg::JointState & msg);
8684

joint_trajectory_controller/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ if(BUILD_TESTING)
103103
ament_add_gmock(test_trajectory_actions
104104
test/test_trajectory_actions.cpp
105105
)
106-
set_tests_properties(test_trajectory_actions PROPERTIES TIMEOUT 300)
106+
set_tests_properties(test_trajectory_actions PROPERTIES TIMEOUT 330)
107107
target_link_libraries(test_trajectory_actions
108108
joint_trajectory_controller
109109
ros2_control_test_assets::ros2_control_test_assets)
564 KB
Loading
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
:github_url: https://github.com/ros-controls/ros2_controllers/blob/{REPOS_FILE_BRANCH}/joint_trajectory_controller/doc/decelerate_on_cancel.rst
2+
3+
.. _joint_trajectory_controller_decelerate_on_cancel:
4+
5+
Decelerate on cancel
6+
====================
7+
8+
By default, when a trajectory is canceled or preempted, the controller immediately holds the current position.
9+
This can cause problems for hardware that is moving at high velocity, as the abrupt stop may trigger faults or cause excessive wear.
10+
11+
When the ``decelerate_on_cancel`` feature is enabled, the controller instead generates a smooth stop trajectory that decelerates each joint to zero velocity using a constant deceleration profile before holding position.
12+
13+
.. image:: decelerate_hold_position.png
14+
:alt: Default behavior: immediate hold position on cancel
15+
16+
*Default behavior: the controller instantly sets the command position to the current position when a trajectory is canceled, causing an abrupt stop.*
17+
18+
.. image:: decelerate_to_stop.png
19+
:alt: Decelerate to stop behavior on cancel
20+
21+
*With decelerate on cancel enabled: the controller generates a ramped stop trajectory that smoothly decelerates each joint before holding position.*
22+
23+
How it works
24+
------------
25+
26+
When a trajectory is canceled or preempted and ``decelerate_on_cancel`` is enabled, the controller:
27+
28+
1. Reads the current velocity of each joint from the velocity state interface.
29+
2. Computes the stopping distance and time for each joint using its configured ``max_deceleration_on_cancel`` value:
30+
31+
.. math::
32+
33+
t_{stop} = \frac{|v|}{a_{max}}
34+
35+
.. math::
36+
37+
d_{stop} = \frac{v \cdot t_{stop}}{2}
38+
39+
where :math:`v` is the current velocity and :math:`a_{max}` is the configured maximum deceleration.
40+
41+
3. Generates a trajectory with intermediate waypoints that linearly ramp velocity to zero over the computed stopping time.
42+
4. Appends a final hold-position point at the computed stop position.
43+
44+
Each joint decelerates independently based on its own ``max_deceleration_on_cancel`` value, but the trajectory is synchronized so all joints finish at the same time (the slowest joint's stop time).
45+
46+
Requirements
47+
------------
48+
49+
* The hardware must provide a ``velocity`` state interface for all joints in the controller. If velocity state feedback is not available, the controller falls back to the default hold-position behavior.
50+
* Each joint must have a valid (greater than zero) ``max_deceleration_on_cancel`` value. Joints with a value of ``0.0`` cause the controller to fall back to hold-position behavior.
51+
52+
Configuration
53+
-------------
54+
55+
Enable the feature by setting ``constraints.decelerate_on_cancel`` to ``true`` and providing a ``max_deceleration_on_cancel`` value (in rad/s^2 or m/s^2) for each joint under ``constraints.<joint_name>``:
56+
57+
.. code-block:: yaml
58+
59+
controller_name:
60+
ros__parameters:
61+
joints:
62+
- joint_1
63+
- joint_2
64+
- joint_3
65+
66+
constraints:
67+
decelerate_on_cancel: true
68+
stopped_velocity_tolerance: 0.01
69+
goal_time: 0.0
70+
joint_1:
71+
max_deceleration_on_cancel: 10.0
72+
joint_2:
73+
max_deceleration_on_cancel: 3.0
74+
joint_3:
75+
max_deceleration_on_cancel: 6.0
76+
77+
.. note::
78+
79+
Both ``decelerate_on_cancel`` and ``max_deceleration_on_cancel`` are read-only parameters. They can only be set at controller configuration time and cannot be changed at runtime.
80+
81+
.. note::
82+
83+
Choose ``max_deceleration_on_cancel`` values that are within the physical limits of your hardware. Values that are too high may still cause faults, while values that are too low will result in longer stopping distances.
544 KB
Loading

0 commit comments

Comments
 (0)