From 9f013cc93f77cb5fee7e48a29f8be2f7bf898b57 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Fri, 14 Apr 2023 18:51:38 +0100 Subject: [PATCH 001/238] Update changelogs --- admittance_controller/CHANGELOG.rst | 6 ++++++ diff_drive_controller/CHANGELOG.rst | 3 +++ effort_controllers/CHANGELOG.rst | 3 +++ force_torque_sensor_broadcaster/CHANGELOG.rst | 3 +++ forward_command_controller/CHANGELOG.rst | 3 +++ gripper_controllers/CHANGELOG.rst | 5 +++++ imu_sensor_broadcaster/CHANGELOG.rst | 3 +++ joint_state_broadcaster/CHANGELOG.rst | 3 +++ joint_trajectory_controller/CHANGELOG.rst | 6 ++++++ position_controllers/CHANGELOG.rst | 3 +++ ros2_controllers/CHANGELOG.rst | 3 +++ ros2_controllers_test_nodes/CHANGELOG.rst | 3 +++ rqt_joint_trajectory_controller/CHANGELOG.rst | 3 +++ tricycle_controller/CHANGELOG.rst | 3 +++ velocity_controllers/CHANGELOG.rst | 3 +++ 15 files changed, 53 insertions(+) diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index aaee61bb37..ccd68d1b69 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Misplaced param init in admittance_controller (`#547 `_) +* [Parameters] Use `gt_eq` instead of deprecated `lower_bounds` in validators (`#561 `_) +* Contributors: Dr. Denis, GuiHome + 3.4.0 (2023-04-02) ------------------ * [AdmittanceController] Addintional argument in methods of ControllerInterface (`#553 `_) diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index 4265863ac9..8c79b5202d 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.4.0 (2023-04-02) ------------------ diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index 8fcd65c3dc..965d261408 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.4.0 (2023-04-02) ------------------ diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index 819d48b324..b2e216be9f 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.4.0 (2023-04-02) ------------------ diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index 0ea80f13fe..a9506f9b0a 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.4.0 (2023-04-02) ------------------ * Fix broken links (`#554 `_) diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index 18dc5cf460..07f5c34088 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* [Parameters] Use `gt_eq` instead of deprecated `lower_bounds` in validators (`#561 `_) +* Contributors: Dr. Denis + 3.4.0 (2023-04-02) ------------------ diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index ed969086e6..cf061dcce2 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.4.0 (2023-04-02) ------------------ diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index 331862cb96..7cf6fe6248 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.4.0 (2023-04-02) ------------------ diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index 998463f27a..3952c659ad 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* [Parameters] Use `gt_eq` instead of deprecated `lower_bounds` in validators (`#561 `_) +* [JTC] Disable use of closed-loop PID adapter if controller is used in open-loop mode. (`#551 `_) +* Contributors: Dr. Denis + 3.4.0 (2023-04-02) ------------------ * Update JTC documentation (`#541 `_) diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index 509f562201..67b7b63a76 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.4.0 (2023-04-02) ------------------ diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index 5ede96124f..c385511abe 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.4.0 (2023-04-02) ------------------ diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index 409fb0ec91..0bef349cdd 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.4.0 (2023-04-02) ------------------ diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index eab9296f8c..7c11677cc8 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.4.0 (2023-04-02) ------------------ diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index a5c51feece..0cf955a431 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.4.0 (2023-04-02) ------------------ diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index ac39176a5e..c48f17db99 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.4.0 (2023-04-02) ------------------ From 48cc202108d4c91af2556176cae0c796f31d40fa Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Fri, 14 Apr 2023 18:52:07 +0100 Subject: [PATCH 002/238] 3.5.0 --- admittance_controller/CHANGELOG.rst | 4 ++-- admittance_controller/package.xml | 2 +- diff_drive_controller/CHANGELOG.rst | 4 ++-- diff_drive_controller/package.xml | 2 +- effort_controllers/CHANGELOG.rst | 4 ++-- effort_controllers/package.xml | 2 +- force_torque_sensor_broadcaster/CHANGELOG.rst | 4 ++-- force_torque_sensor_broadcaster/package.xml | 2 +- forward_command_controller/CHANGELOG.rst | 4 ++-- forward_command_controller/package.xml | 2 +- gripper_controllers/CHANGELOG.rst | 4 ++-- gripper_controllers/package.xml | 2 +- imu_sensor_broadcaster/CHANGELOG.rst | 4 ++-- imu_sensor_broadcaster/package.xml | 2 +- joint_state_broadcaster/CHANGELOG.rst | 4 ++-- joint_state_broadcaster/package.xml | 2 +- joint_trajectory_controller/CHANGELOG.rst | 4 ++-- joint_trajectory_controller/package.xml | 2 +- position_controllers/CHANGELOG.rst | 4 ++-- position_controllers/package.xml | 2 +- ros2_controllers/CHANGELOG.rst | 4 ++-- ros2_controllers/package.xml | 2 +- ros2_controllers_test_nodes/CHANGELOG.rst | 4 ++-- ros2_controllers_test_nodes/package.xml | 2 +- ros2_controllers_test_nodes/setup.py | 2 +- rqt_joint_trajectory_controller/CHANGELOG.rst | 4 ++-- rqt_joint_trajectory_controller/package.xml | 2 +- rqt_joint_trajectory_controller/setup.py | 2 +- tricycle_controller/CHANGELOG.rst | 4 ++-- tricycle_controller/package.xml | 2 +- velocity_controllers/CHANGELOG.rst | 4 ++-- velocity_controllers/package.xml | 2 +- 32 files changed, 47 insertions(+), 47 deletions(-) diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index ccd68d1b69..b7d6801e3c 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.5.0 (2023-04-14) +------------------ * Misplaced param init in admittance_controller (`#547 `_) * [Parameters] Use `gt_eq` instead of deprecated `lower_bounds` in validators (`#561 `_) * Contributors: Dr. Denis, GuiHome diff --git a/admittance_controller/package.xml b/admittance_controller/package.xml index 047e42b098..65f2b9c9b2 100644 --- a/admittance_controller/package.xml +++ b/admittance_controller/package.xml @@ -2,7 +2,7 @@ admittance_controller - 3.4.0 + 3.5.0 Implementation of admittance controllers for different input and output interface. Denis Štogl Bence Magyar diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index 8c79b5202d..1d2f0a3fbd 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.5.0 (2023-04-14) +------------------ 3.4.0 (2023-04-02) ------------------ diff --git a/diff_drive_controller/package.xml b/diff_drive_controller/package.xml index db993d32cf..96050a2f01 100644 --- a/diff_drive_controller/package.xml +++ b/diff_drive_controller/package.xml @@ -1,7 +1,7 @@ diff_drive_controller - 3.4.0 + 3.5.0 Controller for a differential drive mobile base. Bence Magyar Jordan Palacios diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index 965d261408..3611be1381 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.5.0 (2023-04-14) +------------------ 3.4.0 (2023-04-02) ------------------ diff --git a/effort_controllers/package.xml b/effort_controllers/package.xml index 9f988f052e..24228506a7 100644 --- a/effort_controllers/package.xml +++ b/effort_controllers/package.xml @@ -1,7 +1,7 @@ effort_controllers - 3.4.0 + 3.5.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index b2e216be9f..a1f9adbadd 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.5.0 (2023-04-14) +------------------ 3.4.0 (2023-04-02) ------------------ diff --git a/force_torque_sensor_broadcaster/package.xml b/force_torque_sensor_broadcaster/package.xml index 6db14c62e1..df76d575c6 100644 --- a/force_torque_sensor_broadcaster/package.xml +++ b/force_torque_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ force_torque_sensor_broadcaster - 3.4.0 + 3.5.0 Controller to publish state of force-torque sensors. Bence Magyar Denis Štogl diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index a9506f9b0a..fa71f9125a 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.5.0 (2023-04-14) +------------------ 3.4.0 (2023-04-02) ------------------ diff --git a/forward_command_controller/package.xml b/forward_command_controller/package.xml index a490369e96..f05ea322c5 100644 --- a/forward_command_controller/package.xml +++ b/forward_command_controller/package.xml @@ -1,7 +1,7 @@ forward_command_controller - 3.4.0 + 3.5.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index 07f5c34088..d390f60ed8 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.5.0 (2023-04-14) +------------------ * [Parameters] Use `gt_eq` instead of deprecated `lower_bounds` in validators (`#561 `_) * Contributors: Dr. Denis diff --git a/gripper_controllers/package.xml b/gripper_controllers/package.xml index 7cb3ef3a89..770c4b257a 100644 --- a/gripper_controllers/package.xml +++ b/gripper_controllers/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> gripper_controllers - 3.4.0 + 3.5.0 The gripper_controllers package Bence Magyar diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index cf061dcce2..2de70959cf 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.5.0 (2023-04-14) +------------------ 3.4.0 (2023-04-02) ------------------ diff --git a/imu_sensor_broadcaster/package.xml b/imu_sensor_broadcaster/package.xml index e28a48d3c2..19ff483aba 100644 --- a/imu_sensor_broadcaster/package.xml +++ b/imu_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ imu_sensor_broadcaster - 3.4.0 + 3.5.0 Controller to publish readings of IMU sensors. Bence Magyar Denis Štogl diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index 7cf6fe6248..39d94ad9fd 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.5.0 (2023-04-14) +------------------ 3.4.0 (2023-04-02) ------------------ diff --git a/joint_state_broadcaster/package.xml b/joint_state_broadcaster/package.xml index 19e545e44f..3f8b0ee517 100644 --- a/joint_state_broadcaster/package.xml +++ b/joint_state_broadcaster/package.xml @@ -1,7 +1,7 @@ joint_state_broadcaster - 3.4.0 + 3.5.0 Broadcaster to publish joint state Bence Magyar Denis Stogl diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index 3952c659ad..b153636ec0 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.5.0 (2023-04-14) +------------------ * [Parameters] Use `gt_eq` instead of deprecated `lower_bounds` in validators (`#561 `_) * [JTC] Disable use of closed-loop PID adapter if controller is used in open-loop mode. (`#551 `_) * Contributors: Dr. Denis diff --git a/joint_trajectory_controller/package.xml b/joint_trajectory_controller/package.xml index 59ba2a291d..f8e3908657 100644 --- a/joint_trajectory_controller/package.xml +++ b/joint_trajectory_controller/package.xml @@ -1,7 +1,7 @@ joint_trajectory_controller - 3.4.0 + 3.5.0 Controller for executing joint-space trajectories on a group of joints Bence Magyar Jordan Palacios diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index 67b7b63a76..428b6b5f1d 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.5.0 (2023-04-14) +------------------ 3.4.0 (2023-04-02) ------------------ diff --git a/position_controllers/package.xml b/position_controllers/package.xml index eb524c526a..c16c0895dc 100644 --- a/position_controllers/package.xml +++ b/position_controllers/package.xml @@ -1,7 +1,7 @@ position_controllers - 3.4.0 + 3.5.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index c385511abe..5629c27780 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.5.0 (2023-04-14) +------------------ 3.4.0 (2023-04-02) ------------------ diff --git a/ros2_controllers/package.xml b/ros2_controllers/package.xml index 973d2dc759..799b733945 100644 --- a/ros2_controllers/package.xml +++ b/ros2_controllers/package.xml @@ -1,7 +1,7 @@ ros2_controllers - 3.4.0 + 3.5.0 Metapackage for ROS2 controllers related packages Bence Magyar Jordan Palacios diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index 0bef349cdd..638312ac61 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.5.0 (2023-04-14) +------------------ 3.4.0 (2023-04-02) ------------------ diff --git a/ros2_controllers_test_nodes/package.xml b/ros2_controllers_test_nodes/package.xml index c481adf3c7..af7b40c799 100644 --- a/ros2_controllers_test_nodes/package.xml +++ b/ros2_controllers_test_nodes/package.xml @@ -2,7 +2,7 @@ ros2_controllers_test_nodes - 3.4.0 + 3.5.0 Demo nodes for showing and testing functionalities of the ros2_control framework. Denis Štogl diff --git a/ros2_controllers_test_nodes/setup.py b/ros2_controllers_test_nodes/setup.py index 031e08e22e..dc28906b5e 100644 --- a/ros2_controllers_test_nodes/setup.py +++ b/ros2_controllers_test_nodes/setup.py @@ -20,7 +20,7 @@ setup( name=package_name, - version="3.4.0", + version="3.5.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index 7c11677cc8..5cac7c803a 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.5.0 (2023-04-14) +------------------ 3.4.0 (2023-04-02) ------------------ diff --git a/rqt_joint_trajectory_controller/package.xml b/rqt_joint_trajectory_controller/package.xml index a2a54c29e5..5d9bd8215e 100644 --- a/rqt_joint_trajectory_controller/package.xml +++ b/rqt_joint_trajectory_controller/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> rqt_joint_trajectory_controller - 3.4.0 + 3.5.0 Graphical frontend for interacting with joint_trajectory_controller instances. Bence Magyar diff --git a/rqt_joint_trajectory_controller/setup.py b/rqt_joint_trajectory_controller/setup.py index e3fc02453b..81db8a055a 100644 --- a/rqt_joint_trajectory_controller/setup.py +++ b/rqt_joint_trajectory_controller/setup.py @@ -7,7 +7,7 @@ setup( name=package_name, - version="3.4.0", + version="3.5.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index 0cf955a431..d73a931b9b 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.5.0 (2023-04-14) +------------------ 3.4.0 (2023-04-02) ------------------ diff --git a/tricycle_controller/package.xml b/tricycle_controller/package.xml index c33f099d0c..3bb3095ddd 100644 --- a/tricycle_controller/package.xml +++ b/tricycle_controller/package.xml @@ -2,7 +2,7 @@ tricycle_controller - 3.4.0 + 3.5.0 Controller for a tricycle drive mobile base Bence Magyar Tony Najjar diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index c48f17db99..538a095495 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.5.0 (2023-04-14) +------------------ 3.4.0 (2023-04-02) ------------------ diff --git a/velocity_controllers/package.xml b/velocity_controllers/package.xml index 1fe9aee0d5..50c8dfa619 100644 --- a/velocity_controllers/package.xml +++ b/velocity_controllers/package.xml @@ -1,7 +1,7 @@ velocity_controllers - 3.4.0 + 3.5.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios From 467bc4adffaaf10c07d87f517bd729a9d6e8f4bd Mon Sep 17 00:00:00 2001 From: muritane <31107191+muritane@users.noreply.github.com> Date: Wed, 19 Apr 2023 16:30:34 +0200 Subject: [PATCH 003/238] adjusted open_loop param description in diff_drive_controller_parameter.yaml (#570) --- diff_drive_controller/src/diff_drive_controller_parameter.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/diff_drive_controller/src/diff_drive_controller_parameter.yaml b/diff_drive_controller/src/diff_drive_controller_parameter.yaml index fb50f2fb50..f909b27e8b 100644 --- a/diff_drive_controller/src/diff_drive_controller_parameter.yaml +++ b/diff_drive_controller/src/diff_drive_controller_parameter.yaml @@ -62,7 +62,7 @@ diff_drive_controller: open_loop: { type: bool, default_value: false, - description: "If set to false the odometry of the robot will be calculated from the commanded values and not from feedback.", + description: "If set to true the odometry of the robot will be calculated from the commanded values and not from feedback.", } position_feedback: { type: bool, From 74c9e33b43570e6c87ba70e35a1e616301b7299d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 20 Apr 2023 17:30:55 +0200 Subject: [PATCH 004/238] Bump codecov/codecov-action from 3.1.1 to 3.1.2 (#575) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 3.1.1 to 3.1.2. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v3.1.1...v3.1.2) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-coverage-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-coverage-build.yml b/.github/workflows/ci-coverage-build.yml index f7854aae5b..043f09dce3 100644 --- a/.github/workflows/ci-coverage-build.yml +++ b/.github/workflows/ci-coverage-build.yml @@ -37,7 +37,7 @@ jobs: } } colcon-mixin-repository: https://raw.githubusercontent.com/colcon/colcon-mixin-repository/master/index.yaml - - uses: codecov/codecov-action@v3.1.1 + - uses: codecov/codecov-action@v3.1.2 with: file: ros_ws/lcov/total_coverage.info flags: unittests From b1dcab1469fa8bac46be942420e64a6effaa23f6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 27 Apr 2023 17:17:21 +0100 Subject: [PATCH 005/238] Bump codecov/codecov-action from 3.1.2 to 3.1.3 (#581) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 3.1.2 to 3.1.3. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v3.1.2...v3.1.3) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-coverage-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-coverage-build.yml b/.github/workflows/ci-coverage-build.yml index 043f09dce3..6e6e96f032 100644 --- a/.github/workflows/ci-coverage-build.yml +++ b/.github/workflows/ci-coverage-build.yml @@ -37,7 +37,7 @@ jobs: } } colcon-mixin-repository: https://raw.githubusercontent.com/colcon/colcon-mixin-repository/master/index.yaml - - uses: codecov/codecov-action@v3.1.2 + - uses: codecov/codecov-action@v3.1.3 with: file: ros_ws/lcov/total_coverage.info flags: unittests From 5f076e2da11561f028b8d74900b21401cf001ed0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 27 Apr 2023 17:17:38 +0100 Subject: [PATCH 006/238] Bump actions/setup-python from 4.5.0 to 4.6.0 (#582) --- .github/workflows/ci-format.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-format.yml b/.github/workflows/ci-format.yml index 9816e137c6..f0993bf717 100644 --- a/.github/workflows/ci-format.yml +++ b/.github/workflows/ci-format.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: actions/setup-python@v4.5.0 + - uses: actions/setup-python@v4.6.0 with: python-version: '3.10' - name: Install system hooks From cf2723189f175a31201c251d1fa78277e105d52c Mon Sep 17 00:00:00 2001 From: "Dr. Denis" Date: Fri, 28 Apr 2023 12:27:06 +0200 Subject: [PATCH 007/238] Switch to recommended versions of ros-tooling (#577) --- .github/workflows/ci-ros-lint.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-ros-lint.yml b/.github/workflows/ci-ros-lint.yml index 5dd0b6f086..fd3e6b634b 100644 --- a/.github/workflows/ci-ros-lint.yml +++ b/.github/workflows/ci-ros-lint.yml @@ -41,8 +41,8 @@ jobs: linter: [cpplint] steps: - uses: actions/checkout@v3 - - uses: ros-tooling/setup-ros@0.6.1 - - uses: ros-tooling/action-ros-lint@v0.1 + - uses: ros-tooling/setup-ros@master + - uses: ros-tooling/action-ros-lint@master with: distribution: rolling linter: cpplint From edd494ca177b15838f3a5e1af5931d06b1129ec7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Fri, 28 Apr 2023 21:11:32 +0200 Subject: [PATCH 008/238] [JTC] Implement new ~/controller_state message (#557) --- joint_trajectory_controller/doc/userdoc.rst | 2 +- .../joint_trajectory_controller.hpp | 4 + .../src/joint_trajectory_controller.cpp | 146 ++++++++++++++-- .../test/test_trajectory_controller.cpp | 162 ++++++++++++------ .../test/test_trajectory_controller_utils.hpp | 11 +- 5 files changed, 251 insertions(+), 74 deletions(-) diff --git a/joint_trajectory_controller/doc/userdoc.rst b/joint_trajectory_controller/doc/userdoc.rst index fc223d2eb0..2370e9ca20 100644 --- a/joint_trajectory_controller/doc/userdoc.rst +++ b/joint_trajectory_controller/doc/userdoc.rst @@ -230,7 +230,7 @@ ROS2 interface of the controller ~/joint_trajectory (input topic) [trajectory_msgs::msg::JointTrajectory] Topic for commanding the controller. -~/state (output topic) [control_msgs::msg::JointTrajectoryControllerState] +~/controller_state (output topic) [control_msgs::msg::JointTrajectoryControllerState] Topic publishing internal states with the update-rate of the controller manager. ~/follow_joint_trajectory (action server) [control_msgs::action::FollowJointTrajectory] diff --git a/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp b/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp index 2a6454f454..dfbdf7436e 100644 --- a/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp +++ b/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp @@ -127,6 +127,7 @@ class JointTrajectoryController : public controller_interface::ControllerInterfa // Preallocate variables used in the realtime update() function trajectory_msgs::msg::JointTrajectoryPoint state_current_; + trajectory_msgs::msg::JointTrajectoryPoint command_current_; trajectory_msgs::msg::JointTrajectoryPoint state_desired_; trajectory_msgs::msg::JointTrajectoryPoint state_error_; @@ -256,6 +257,7 @@ class JointTrajectoryController : public controller_interface::ControllerInterfa void read_state_from_hardware(JointTrajectoryPoint & state); bool read_state_from_command_interfaces(JointTrajectoryPoint & state); + bool read_commands_from_command_interfaces(JointTrajectoryPoint & commands); void query_state_service( const std::shared_ptr request, @@ -267,6 +269,8 @@ class JointTrajectoryController : public controller_interface::ControllerInterfa void resize_joint_trajectory_point( trajectory_msgs::msg::JointTrajectoryPoint & point, size_t size); + void resize_joint_trajectory_point_command( + trajectory_msgs::msg::JointTrajectoryPoint & point, size_t size); }; } // namespace joint_trajectory_controller diff --git a/joint_trajectory_controller/src/joint_trajectory_controller.cpp b/joint_trajectory_controller/src/joint_trajectory_controller.cpp index 5c719f7471..b6a60526fa 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller.cpp +++ b/joint_trajectory_controller/src/joint_trajectory_controller.cpp @@ -467,6 +467,81 @@ bool JointTrajectoryController::read_state_from_command_interfaces(JointTrajecto return has_values; } +bool JointTrajectoryController::read_commands_from_command_interfaces( + JointTrajectoryPoint & commands) +{ + bool has_values = true; + + auto assign_point_from_interface = + [&](std::vector & trajectory_point_interface, const auto & joint_interface) + { + for (size_t index = 0; index < dof_; ++index) + { + trajectory_point_interface[index] = joint_interface[index].get().get_value(); + } + }; + + auto interface_has_values = [](const auto & joint_interface) + { + return std::find_if( + joint_interface.begin(), joint_interface.end(), + [](const auto & interface) + { return std::isnan(interface.get().get_value()); }) == joint_interface.end(); + }; + + // Assign values from the command interfaces as command. + if (has_position_command_interface_) + { + if (interface_has_values(joint_command_interface_[0])) + { + assign_point_from_interface(commands.positions, joint_command_interface_[0]); + } + else + { + commands.positions.clear(); + has_values = false; + } + } + if (has_velocity_command_interface_) + { + if (interface_has_values(joint_command_interface_[1])) + { + assign_point_from_interface(commands.velocities, joint_command_interface_[1]); + } + else + { + commands.velocities.clear(); + has_values = false; + } + } + if (has_acceleration_command_interface_) + { + if (interface_has_values(joint_command_interface_[2])) + { + assign_point_from_interface(commands.accelerations, joint_command_interface_[2]); + } + else + { + commands.accelerations.clear(); + has_values = false; + } + } + if (has_effort_command_interface_) + { + if (interface_has_values(joint_command_interface_[3])) + { + assign_point_from_interface(commands.effort, joint_command_interface_[3]); + } + else + { + commands.effort.clear(); + has_values = false; + } + } + + return has_values; +} + void JointTrajectoryController::query_state_service( const std::shared_ptr request, std::shared_ptr response) @@ -706,27 +781,44 @@ controller_interface::CallbackReturn JointTrajectoryController::on_configure( "~/joint_trajectory", rclcpp::SystemDefaultsQoS(), std::bind(&JointTrajectoryController::topic_callback, this, std::placeholders::_1)); - publisher_ = - get_node()->create_publisher("~/state", rclcpp::SystemDefaultsQoS()); + publisher_ = get_node()->create_publisher( + "~/controller_state", rclcpp::SystemDefaultsQoS()); state_publisher_ = std::make_unique(publisher_); state_publisher_->lock(); state_publisher_->msg_.joint_names = params_.joints; - state_publisher_->msg_.desired.positions.resize(dof_); - state_publisher_->msg_.desired.velocities.resize(dof_); - state_publisher_->msg_.desired.accelerations.resize(dof_); - state_publisher_->msg_.actual.positions.resize(dof_); + state_publisher_->msg_.reference.positions.resize(dof_); + state_publisher_->msg_.reference.velocities.resize(dof_); + state_publisher_->msg_.reference.accelerations.resize(dof_); + state_publisher_->msg_.feedback.positions.resize(dof_); state_publisher_->msg_.error.positions.resize(dof_); if (has_velocity_state_interface_) { - state_publisher_->msg_.actual.velocities.resize(dof_); + state_publisher_->msg_.feedback.velocities.resize(dof_); state_publisher_->msg_.error.velocities.resize(dof_); } if (has_acceleration_state_interface_) { - state_publisher_->msg_.actual.accelerations.resize(dof_); + state_publisher_->msg_.feedback.accelerations.resize(dof_); state_publisher_->msg_.error.accelerations.resize(dof_); } + if (has_position_command_interface_) + { + state_publisher_->msg_.output.positions.resize(dof_); + } + if (has_velocity_command_interface_) + { + state_publisher_->msg_.output.velocities.resize(dof_); + } + if (has_acceleration_command_interface_) + { + state_publisher_->msg_.output.accelerations.resize(dof_); + } + if (has_effort_command_interface_) + { + state_publisher_->msg_.output.effort.resize(dof_); + } + state_publisher_->unlock(); // action server configuration @@ -749,6 +841,7 @@ controller_interface::CallbackReturn JointTrajectoryController::on_configure( std::bind(&JointTrajectoryController::goal_accepted_callback, this, _1)); resize_joint_trajectory_point(state_current_, dof_); + resize_joint_trajectory_point_command(command_current_, dof_); resize_joint_trajectory_point(state_desired_, dof_); resize_joint_trajectory_point(state_error_, dof_); resize_joint_trajectory_point(last_commanded_state_, dof_); @@ -929,21 +1022,25 @@ void JointTrajectoryController::publish_state( if (state_publisher_->trylock()) { state_publisher_->msg_.header.stamp = time; - state_publisher_->msg_.desired.positions = desired_state.positions; - state_publisher_->msg_.desired.velocities = desired_state.velocities; - state_publisher_->msg_.desired.accelerations = desired_state.accelerations; - state_publisher_->msg_.actual.positions = current_state.positions; + state_publisher_->msg_.reference.positions = desired_state.positions; + state_publisher_->msg_.reference.velocities = desired_state.velocities; + state_publisher_->msg_.reference.accelerations = desired_state.accelerations; + state_publisher_->msg_.feedback.positions = current_state.positions; state_publisher_->msg_.error.positions = state_error.positions; if (has_velocity_state_interface_) { - state_publisher_->msg_.actual.velocities = current_state.velocities; + state_publisher_->msg_.feedback.velocities = current_state.velocities; state_publisher_->msg_.error.velocities = state_error.velocities; } if (has_acceleration_state_interface_) { - state_publisher_->msg_.actual.accelerations = current_state.accelerations; + state_publisher_->msg_.feedback.accelerations = current_state.accelerations; state_publisher_->msg_.error.accelerations = state_error.accelerations; } + if (read_commands_from_command_interfaces(command_current_)) + { + state_publisher_->msg_.output = command_current_; + } state_publisher_->unlockAndPublish(); } @@ -1315,6 +1412,27 @@ void JointTrajectoryController::resize_joint_trajectory_point( } } +void JointTrajectoryController::resize_joint_trajectory_point_command( + trajectory_msgs::msg::JointTrajectoryPoint & point, size_t size) +{ + if (has_position_command_interface_) + { + point.positions.resize(size, 0.0); + } + if (has_velocity_command_interface_) + { + point.velocities.resize(size, 0.0); + } + if (has_acceleration_command_interface_) + { + point.accelerations.resize(size, 0.0); + } + if (has_effort_command_interface_) + { + point.effort.resize(size, 0.0); + } +} + } // namespace joint_trajectory_controller #include "pluginlib/class_list_macros.hpp" diff --git a/joint_trajectory_controller/test/test_trajectory_controller.cpp b/joint_trajectory_controller/test/test_trajectory_controller.cpp index 1c0dbb5482..e8073086dc 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller.cpp +++ b/joint_trajectory_controller/test/test_trajectory_controller.cpp @@ -29,7 +29,6 @@ #include "builtin_interfaces/msg/duration.hpp" #include "builtin_interfaces/msg/time.hpp" -#include "control_msgs/msg/detail/joint_trajectory_controller_state__struct.hpp" #include "controller_interface/controller_interface.hpp" #include "hardware_interface/resource_manager.hpp" #include "joint_trajectory_controller/joint_trajectory_controller.hpp" @@ -49,10 +48,11 @@ #include "rclcpp_lifecycle/lifecycle_node.hpp" #include "rclcpp_lifecycle/state.hpp" #include "std_msgs/msg/header.hpp" -#include "test_trajectory_controller_utils.hpp" #include "trajectory_msgs/msg/joint_trajectory.hpp" #include "trajectory_msgs/msg/joint_trajectory_point.hpp" +#include "test_trajectory_controller_utils.hpp" + using lifecycle_msgs::msg::State; using test_trajectory_controllers::TrajectoryControllerTest; using test_trajectory_controllers::TrajectoryControllerTestParameterized; @@ -469,38 +469,83 @@ TEST_P(TrajectoryControllerTestParameterized, state_topic_consistency) EXPECT_EQ(joint_names_[i], state->joint_names[i]); } - // No trajectory by default, no desired state or error - EXPECT_TRUE(state->desired.positions.empty() || state->desired.positions == INITIAL_POS_JOINTS); - EXPECT_TRUE(state->desired.velocities.empty() || state->desired.velocities == INITIAL_VEL_JOINTS); + // No trajectory by default, no reference state or error + EXPECT_TRUE( + state->reference.positions.empty() || state->reference.positions == INITIAL_POS_JOINTS); EXPECT_TRUE( - state->desired.accelerations.empty() || state->desired.accelerations == INITIAL_EFF_JOINTS); + state->reference.velocities.empty() || state->reference.velocities == INITIAL_VEL_JOINTS); + EXPECT_TRUE( + state->reference.accelerations.empty() || state->reference.accelerations == INITIAL_EFF_JOINTS); - EXPECT_EQ(n_joints, state->actual.positions.size()); + std::vector zeros(3, 0); + EXPECT_EQ(state->error.positions, zeros); + EXPECT_TRUE(state->error.velocities.empty() || state->error.velocities == zeros); + EXPECT_TRUE(state->error.accelerations.empty() || state->error.accelerations == zeros); + + // expect feedback including all state_interfaces + EXPECT_EQ(n_joints, state->feedback.positions.size()); if ( std::find(state_interface_types_.begin(), state_interface_types_.end(), "velocity") == state_interface_types_.end()) { - EXPECT_TRUE(state->actual.velocities.empty()); + EXPECT_TRUE(state->feedback.velocities.empty()); } else { - EXPECT_EQ(n_joints, state->actual.velocities.size()); + EXPECT_EQ(n_joints, state->feedback.velocities.size()); } if ( std::find(state_interface_types_.begin(), state_interface_types_.end(), "acceleration") == state_interface_types_.end()) { - EXPECT_TRUE(state->actual.accelerations.empty()); + EXPECT_TRUE(state->feedback.accelerations.empty()); } else { - EXPECT_EQ(n_joints, state->actual.accelerations.size()); + EXPECT_EQ(n_joints, state->feedback.accelerations.size()); } - std::vector zeros(3, 0); - EXPECT_EQ(state->error.positions, zeros); - EXPECT_TRUE(state->error.velocities.empty() || state->error.velocities == zeros); - EXPECT_TRUE(state->error.accelerations.empty() || state->error.accelerations == zeros); + // expect output including all command_interfaces + if ( + std::find(command_interface_types_.begin(), command_interface_types_.end(), "position") == + command_interface_types_.end()) + { + EXPECT_TRUE(state->output.positions.empty()); + } + else + { + EXPECT_EQ(n_joints, state->output.positions.size()); + } + if ( + std::find(command_interface_types_.begin(), command_interface_types_.end(), "velocity") == + command_interface_types_.end()) + { + EXPECT_TRUE(state->output.velocities.empty()); + } + else + { + EXPECT_EQ(n_joints, state->output.velocities.size()); + } + if ( + std::find(command_interface_types_.begin(), command_interface_types_.end(), "acceleration") == + command_interface_types_.end()) + { + EXPECT_TRUE(state->output.accelerations.empty()); + } + else + { + EXPECT_EQ(n_joints, state->output.accelerations.size()); + } + if ( + std::find(command_interface_types_.begin(), command_interface_types_.end(), "effort") == + command_interface_types_.end()) + { + EXPECT_TRUE(state->output.effort.empty()); + } + else + { + EXPECT_EQ(n_joints, state->output.effort.size()); + } } // Floating-point value comparison threshold @@ -540,25 +585,25 @@ TEST_P(TrajectoryControllerTestParameterized, position_error_not_normalized) const auto allowed_delta = 0.1; // no update of state_interface - EXPECT_EQ(state_msg->actual.positions, INITIAL_POS_JOINTS); + EXPECT_EQ(state_msg->feedback.positions, INITIAL_POS_JOINTS); // has the msg the correct vector sizes? - EXPECT_EQ(n_joints, state_msg->desired.positions.size()); - EXPECT_EQ(n_joints, state_msg->actual.positions.size()); + EXPECT_EQ(n_joints, state_msg->reference.positions.size()); + EXPECT_EQ(n_joints, state_msg->feedback.positions.size()); EXPECT_EQ(n_joints, state_msg->error.positions.size()); - // are the correct desired positions used? - EXPECT_NEAR(points[0][0], state_msg->desired.positions[0], allowed_delta); - EXPECT_NEAR(points[0][1], state_msg->desired.positions[1], allowed_delta); - EXPECT_NEAR(points[0][2], state_msg->desired.positions[2], 3 * allowed_delta); + // are the correct reference positions used? + EXPECT_NEAR(points[0][0], state_msg->reference.positions[0], allowed_delta); + EXPECT_NEAR(points[0][1], state_msg->reference.positions[1], allowed_delta); + EXPECT_NEAR(points[0][2], state_msg->reference.positions[2], 3 * allowed_delta); // no normalization of position error EXPECT_NEAR( - state_msg->error.positions[0], state_msg->desired.positions[0] - INITIAL_POS_JOINTS[0], EPS); + state_msg->error.positions[0], state_msg->reference.positions[0] - INITIAL_POS_JOINTS[0], EPS); EXPECT_NEAR( - state_msg->error.positions[1], state_msg->desired.positions[1] - INITIAL_POS_JOINTS[1], EPS); + state_msg->error.positions[1], state_msg->reference.positions[1] - INITIAL_POS_JOINTS[1], EPS); EXPECT_NEAR( - state_msg->error.positions[2], state_msg->desired.positions[2] - INITIAL_POS_JOINTS[2], EPS); + state_msg->error.positions[2], state_msg->reference.positions[2] - INITIAL_POS_JOINTS[2], EPS); if (traj_controller_->has_position_command_interface()) { @@ -566,28 +611,34 @@ TEST_P(TrajectoryControllerTestParameterized, position_error_not_normalized) EXPECT_NEAR(points[0][0], joint_pos_[0], allowed_delta); EXPECT_NEAR(points[0][1], joint_pos_[1], allowed_delta); EXPECT_NEAR(points[0][2], joint_pos_[2], allowed_delta); + EXPECT_NEAR(points[0][0], state_msg->output.positions[0], allowed_delta); + EXPECT_NEAR(points[0][1], state_msg->output.positions[1], allowed_delta); + EXPECT_NEAR(points[0][2], state_msg->output.positions[2], allowed_delta); } if (traj_controller_->has_velocity_command_interface()) { // check command interface - EXPECT_LE(0.0, joint_vel_[0]); - EXPECT_LE(0.0, joint_vel_[1]); - EXPECT_LE(0.0, joint_vel_[2]); + EXPECT_LT(0.0, joint_vel_[0]); + EXPECT_LT(0.0, joint_vel_[1]); + EXPECT_LT(0.0, joint_vel_[2]); + EXPECT_LT(0.0, state_msg->output.velocities[0]); + EXPECT_LT(0.0, state_msg->output.velocities[1]); + EXPECT_LT(0.0, state_msg->output.velocities[2]); // use_closed_loop_pid_adapter_ if (traj_controller_->use_closed_loop_pid_adapter()) { // we expect u = k_p * (s_d-s) EXPECT_NEAR( - k_p * (state_msg->desired.positions[0] - INITIAL_POS_JOINTS[0]), joint_vel_[0], + k_p * (state_msg->reference.positions[0] - INITIAL_POS_JOINTS[0]), joint_vel_[0], k_p * allowed_delta); EXPECT_NEAR( - k_p * (state_msg->desired.positions[1] - INITIAL_POS_JOINTS[1]), joint_vel_[1], + k_p * (state_msg->reference.positions[1] - INITIAL_POS_JOINTS[1]), joint_vel_[1], k_p * allowed_delta); // no normalization of position error EXPECT_NEAR( - k_p * (state_msg->desired.positions[2] - INITIAL_POS_JOINTS[2]), joint_vel_[2], + k_p * (state_msg->reference.positions[2] - INITIAL_POS_JOINTS[2]), joint_vel_[2], k_p * allowed_delta); } } @@ -595,9 +646,12 @@ TEST_P(TrajectoryControllerTestParameterized, position_error_not_normalized) if (traj_controller_->has_effort_command_interface()) { // check command interface - EXPECT_LE(0.0, joint_eff_[0]); - EXPECT_LE(0.0, joint_eff_[1]); - EXPECT_LE(0.0, joint_eff_[2]); + EXPECT_LT(0.0, joint_eff_[0]); + EXPECT_LT(0.0, joint_eff_[1]); + EXPECT_LT(0.0, joint_eff_[2]); + EXPECT_LT(0.0, state_msg->output.effort[0]); + EXPECT_LT(0.0, state_msg->output.effort[1]); + EXPECT_LT(0.0, state_msg->output.effort[2]); } executor.cancel(); @@ -638,26 +692,26 @@ TEST_P(TrajectoryControllerTestParameterized, position_error_normalized) const auto allowed_delta = 0.1; // no update of state_interface - EXPECT_EQ(state_msg->actual.positions, INITIAL_POS_JOINTS); + EXPECT_EQ(state_msg->feedback.positions, INITIAL_POS_JOINTS); // has the msg the correct vector sizes? - EXPECT_EQ(n_joints, state_msg->desired.positions.size()); - EXPECT_EQ(n_joints, state_msg->actual.positions.size()); + EXPECT_EQ(n_joints, state_msg->reference.positions.size()); + EXPECT_EQ(n_joints, state_msg->feedback.positions.size()); EXPECT_EQ(n_joints, state_msg->error.positions.size()); - // are the correct desired positions used? - EXPECT_NEAR(points[0][0], state_msg->desired.positions[0], allowed_delta); - EXPECT_NEAR(points[0][1], state_msg->desired.positions[1], allowed_delta); - EXPECT_NEAR(points[0][2], state_msg->desired.positions[2], 3 * allowed_delta); + // are the correct reference positions used? + EXPECT_NEAR(points[0][0], state_msg->reference.positions[0], allowed_delta); + EXPECT_NEAR(points[0][1], state_msg->reference.positions[1], allowed_delta); + EXPECT_NEAR(points[0][2], state_msg->reference.positions[2], 3 * allowed_delta); // is error.positions[2] normalized? EXPECT_NEAR( - state_msg->error.positions[0], state_msg->desired.positions[0] - INITIAL_POS_JOINTS[0], EPS); + state_msg->error.positions[0], state_msg->reference.positions[0] - INITIAL_POS_JOINTS[0], EPS); EXPECT_NEAR( - state_msg->error.positions[1], state_msg->desired.positions[1] - INITIAL_POS_JOINTS[1], EPS); + state_msg->error.positions[1], state_msg->reference.positions[1] - INITIAL_POS_JOINTS[1], EPS); EXPECT_NEAR( state_msg->error.positions[2], - state_msg->desired.positions[2] - INITIAL_POS_JOINTS[2] - 2 * M_PI, EPS); + state_msg->reference.positions[2] - INITIAL_POS_JOINTS[2] - 2 * M_PI, EPS); if (traj_controller_->has_position_command_interface()) { @@ -670,38 +724,38 @@ TEST_P(TrajectoryControllerTestParameterized, position_error_normalized) if (traj_controller_->has_velocity_command_interface()) { // check command interface - EXPECT_LE(0.0, joint_vel_[0]); - EXPECT_LE(0.0, joint_vel_[1]); + EXPECT_LT(0.0, joint_vel_[0]); + EXPECT_LT(0.0, joint_vel_[1]); // use_closed_loop_pid_adapter_ if (traj_controller_->use_closed_loop_pid_adapter()) { - EXPECT_GE(0.0, joint_vel_[2]); + EXPECT_GT(0.0, joint_vel_[2]); // we expect u = k_p * (s_d-s) for positions[0] and positions[1] EXPECT_NEAR( - k_p * (state_msg->desired.positions[0] - INITIAL_POS_JOINTS[0]), joint_vel_[0], + k_p * (state_msg->reference.positions[0] - INITIAL_POS_JOINTS[0]), joint_vel_[0], k_p * allowed_delta); EXPECT_NEAR( - k_p * (state_msg->desired.positions[1] - INITIAL_POS_JOINTS[1]), joint_vel_[1], + k_p * (state_msg->reference.positions[1] - INITIAL_POS_JOINTS[1]), joint_vel_[1], k_p * allowed_delta); // is error of positions[2] normalized? EXPECT_NEAR( - k_p * (state_msg->desired.positions[2] - INITIAL_POS_JOINTS[2] - 2 * M_PI), joint_vel_[2], + k_p * (state_msg->reference.positions[2] - INITIAL_POS_JOINTS[2] - 2 * M_PI), joint_vel_[2], k_p * allowed_delta); } else { // interpolated points_velocities only - EXPECT_LE(0.0, joint_vel_[2]); + EXPECT_LT(0.0, joint_vel_[2]); } } if (traj_controller_->has_effort_command_interface()) { // check command interface - EXPECT_LE(0.0, joint_eff_[0]); - EXPECT_LE(0.0, joint_eff_[1]); - EXPECT_LE(0.0, joint_eff_[2]); + EXPECT_LT(0.0, joint_eff_[0]); + EXPECT_LT(0.0, joint_eff_[1]); + EXPECT_LT(0.0, joint_eff_[2]); } executor.cancel(); diff --git a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp index 25612f56e9..c85eb59f58 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp +++ b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp @@ -281,7 +281,7 @@ class TrajectoryControllerTest : public ::testing::Test // I do not understand why spin_some provides only one message qos.keep_last(1); state_subscriber_ = traj_lifecycle_node->create_subscription( - controller_name_ + "/state", qos, + controller_name_ + "/controller_state", qos, [&](std::shared_ptr msg) { std::lock_guard guard(state_mutex_); @@ -385,20 +385,21 @@ class TrajectoryControllerTest : public ::testing::Test for (size_t i = 0; i < expected_actual.positions.size(); ++i) { SCOPED_TRACE("Joint " + std::to_string(i)); - // TODO(anyone): add checking for velocties and accelerations + // TODO(anyone): add checking for velocities and accelerations if (traj_controller_->has_position_command_interface()) { - EXPECT_NEAR(expected_actual.positions[i], state_msg->actual.positions[i], allowed_delta); + EXPECT_NEAR(expected_actual.positions[i], state_msg->feedback.positions[i], allowed_delta); } } for (size_t i = 0; i < expected_desired.positions.size(); ++i) { SCOPED_TRACE("Joint " + std::to_string(i)); - // TODO(anyone): add checking for velocties and accelerations + // TODO(anyone): add checking for velocities and accelerations if (traj_controller_->has_position_command_interface()) { - EXPECT_NEAR(expected_desired.positions[i], state_msg->desired.positions[i], allowed_delta); + EXPECT_NEAR( + expected_desired.positions[i], state_msg->reference.positions[i], allowed_delta); } } } From 8da513533292b6a7add0d2026b6d718797df8010 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Sat, 29 Apr 2023 11:20:31 +0200 Subject: [PATCH 009/238] Fix docs format (#589) * Fix docs format * Fix trailing whitespace --- admittance_controller/doc/userdoc.rst | 5 +- doc/controllers_index.rst | 4 +- forward_command_controller/doc/userdoc.rst | 6 +-- joint_state_broadcaster/doc/userdoc.rst | 10 ++-- joint_trajectory_controller/doc/userdoc.rst | 57 +++++++++++---------- 5 files changed, 42 insertions(+), 40 deletions(-) diff --git a/admittance_controller/doc/userdoc.rst b/admittance_controller/doc/userdoc.rst index 60837457f9..ed2da84ad5 100644 --- a/admittance_controller/doc/userdoc.rst +++ b/admittance_controller/doc/userdoc.rst @@ -1,4 +1,4 @@ -.. _joint_trajectory_controller_userdoc: +.. _addmittance_controller_userdoc: Admittance Controller ====================== @@ -8,9 +8,6 @@ The controller implements ``ChainedControllerInterface``, so it is possible to a The controller requires an external kinematics plugin to function. The `kinematics_interface `_ repository provides an interface and an implementation that the admittance controller can use. -Parameters: - - ROS2 interface of the controller --------------------------------- diff --git a/doc/controllers_index.rst b/doc/controllers_index.rst index 15d4bdd631..1c6b1dbd9e 100644 --- a/doc/controllers_index.rst +++ b/doc/controllers_index.rst @@ -41,13 +41,13 @@ Available Controllers :titlesonly: Admittance Controller <../admittance_controller/doc/userdoc.rst> - Tricycle Controller <../tricycle_controller/doc/userdoc.rst> Differential Drive Controller <../diff_drive_controller/doc/userdoc.rst> + Effort Controllers <../effort_controllers/doc/userdoc.rst> Forward Command Controller <../forward_command_controller/doc/userdoc.rst> Joint Trajectory Controller <../joint_trajectory_controller/doc/userdoc.rst> Position Controllers <../position_controllers/doc/userdoc.rst> + Tricycle Controller <../tricycle_controller/doc/userdoc.rst> Velocity Controllers <../velocity_controllers/doc/userdoc.rst> - Effort Controllers <../effort_controllers/doc/userdoc.rst> Available Broadcasters diff --git a/forward_command_controller/doc/userdoc.rst b/forward_command_controller/doc/userdoc.rst index 1f3a47997a..8292bdc1b3 100644 --- a/forward_command_controller/doc/userdoc.rst +++ b/forward_command_controller/doc/userdoc.rst @@ -5,9 +5,9 @@ forward_command_controller This is a base class implementing a feedforward controller. Specific implementations can be found in: -- :ref:`position_controllers_userdoc` -- :ref:`velocity_controllers_userdoc` -- :ref:`effort_controllers_userdoc` +* :ref:`position_controllers_userdoc` +* :ref:`velocity_controllers_userdoc` +* :ref:`effort_controllers_userdoc` Hardware interface type ----------------------- diff --git a/joint_state_broadcaster/doc/userdoc.rst b/joint_state_broadcaster/doc/userdoc.rst index 8a030d9356..fbdb439992 100644 --- a/joint_state_broadcaster/doc/userdoc.rst +++ b/joint_state_broadcaster/doc/userdoc.rst @@ -21,26 +21,26 @@ If none of the requested interface are not defined, the controller returns error Parameters ---------- -``use_local_topics`` +use_local_topics Optional parameter (boolean; default: ``False``) defining if ``joint_states`` and ``dynamic_joint_states`` messages should be published into local namespace, e.g., ``/my_state_broadcaster/joint_states``. -``joints`` +joints Optional parameter (string array) to support broadcasting of only specific joints and interfaces. It has to be used in combination with the ``interfaces`` parameter. Joint state broadcaster asks for access to all defined interfaces on all defined joints. -``interfaces`` +interfaces Optional parameter (string array) to support broadcasting of only specific joints and interfaces. It has to be used in combination with the ``joints`` parameter. -``extra_joints`` +extra_joints Optional parameter (string array) with names of extra joints to be added to ``joint_states`` and ``dynamic_joint_states`` with state set to 0. -``map_interface_to_joint_state`` +map_interface_to_joint_state Optional parameter (map) providing mapping between custom interface names to standard fields in ``joint_states`` message. Usecases: diff --git a/joint_trajectory_controller/doc/userdoc.rst b/joint_trajectory_controller/doc/userdoc.rst index 2370e9ca20..1ba6257a5a 100644 --- a/joint_trajectory_controller/doc/userdoc.rst +++ b/joint_trajectory_controller/doc/userdoc.rst @@ -10,11 +10,11 @@ Trajectory representation The controller is templated to work with multiple trajectory representations. By default, a spline interpolator is provided, but it's possible to support other representations. The spline interpolator uses the following interpolation strategies depending on the waypoint specification: - Linear: Only position is specified. Guarantees continuity at the position level. Discouraged because it yields trajectories with discontinuous velocities at the waypoints. +* Linear: Only position is specified. Guarantees continuity at the position level. Discouraged because it yields trajectories with discontinuous velocities at the waypoints. - Cubic: Position and velocity are specified. Guarantees continuity at the velocity level. +* Cubic: Position and velocity are specified. Guarantees continuity at the velocity level. - Quintic: Position, velocity and acceleration are specified: Guarantees continuity at the acceleration level. +* Quintic: Position, velocity and acceleration are specified: Guarantees continuity at the acceleration level. Hardware interface type ----------------------- @@ -26,11 +26,11 @@ Similarly to the trajectory representation case above, it's possible to support Other features -------------- - Realtime-safe implementation. +* Realtime-safe implementation. - Proper handling of wrapping (continuous) joints. +* Proper handling of wrapping (continuous) joints. - Robust to system clock changes: Discontinuous system clock changes do not cause discontinuities in the execution of already queued trajectory segments. +* Robust to system clock changes: Discontinuous system clock changes do not cause discontinuities in the execution of already queued trajectory segments. ros2_control interfaces ------------------------ @@ -45,10 +45,10 @@ The state interfaces are defined with ``joints`` and ``state_interfaces`` parame Supported state interfaces are ``position``, ``velocity``, ``acceleration`` and ``effort`` as defined in the `hardware_interface/hardware_interface_type_values.hpp `_. Legal combinations of state interfaces are: -- ``position`` -- ``position`` and ``velocity`` -- ``position``, ``velocity`` and ``acceleration`` -- ``effort`` +* ``position`` +* ``position`` and ``velocity`` +* ``position``, ``velocity`` and ``acceleration`` +* ``effort`` Commands ^^^^^^^^^ @@ -244,23 +244,28 @@ The controller types are placed into namespaces according to their command types The following version of the Joint Trajectory Controller are available mapping the following interfaces: - - position_controllers::JointTrajectoryController - - Input: position, [velocity, [acceleration]] - - Output: position - - position_velocity_controllers::JointTrajectoryController - - Input: position, [velocity, [acceleration]] - - Output: position and velocity - - position_velocity_acceleration_controllers::JointTrajectoryController - - Input: position, [velocity, [acceleration]] - - Output: position, velocity and acceleration - -.. - velocity_controllers::JointTrajectoryController -.. - Input: position, [velocity, [acceleration]] -.. - Output: velocity +* position_controllers::JointTrajectoryController + + * Input: position, [velocity, [acceleration]] + * Output: position + +* position_velocity_controllers::JointTrajectoryController + + * Input: position, [velocity, [acceleration]] + * Output: position and velocity + +* position_velocity_acceleration_controllers::JointTrajectoryController + + * Input: position, [velocity, [acceleration]] + * Output: position, velocity and acceleration + +.. * velocity_controllers::JointTrajectoryController +.. * Input: position, [velocity, [acceleration]] +.. * Output: velocity .. TODO(anyone): would it be possible to output velocty and acceleration? .. (to have an vel_acc_controllers) -.. - effort_controllers::JointTrajectoryController -.. - Input: position, [velocity, [acceleration]] -.. - Output: effort +.. * effort_controllers::JointTrajectoryController +.. * Input: position, [velocity, [acceleration]] +.. * Output: effort (*Not implemented yet*) When using pure ``velocity`` or ``effort`` controllers a command is generated using the desired state and state error using a velocity feedforward term plus a corrective PID term. (#171) From 1db184b012217158335f91cdf7521097c36f0777 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Sat, 29 Apr 2023 21:23:10 +0100 Subject: [PATCH 010/238] Update reviewer-lottery.yml (#588) --- .github/reviewer-lottery.yml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/reviewer-lottery.yml b/.github/reviewer-lottery.yml index 50c707e12b..84b156f5a1 100644 --- a/.github/reviewer-lottery.yml +++ b/.github/reviewer-lottery.yml @@ -16,13 +16,16 @@ groups: - rosterloh - progtologist - arne48 + - christophfroehlich - DasRoteSkelett - - Serafadam + - sgmurray - harderthan - jaron-l - malapatiravi - - homalozoa - erickisos + - sachinkum0009 + - qiayuanliao + - homalozoa - anfemosa - jackcenter - VX792 @@ -31,6 +34,7 @@ groups: - aprotyas - peterdavidfagan - duringhof + - VanshGehlot - bijoua29 - - lm2292 + - LukasMacha97 - mcbed From 1e3129d44c7781b5b9f36f48238477060cc92fba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Sat, 29 Apr 2023 22:23:59 +0200 Subject: [PATCH 011/238] Fix PR template (#587) --- .../pull_request_template.md | 10 ---------- 1 file changed, 10 deletions(-) rename .github/{PULL_REQUEST_TEMPLATE => }/pull_request_template.md (92%) diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md b/.github/pull_request_template.md similarity index 92% rename from .github/PULL_REQUEST_TEMPLATE/pull_request_template.md rename to .github/pull_request_template.md index 87f389a124..8e9178c167 100644 --- a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,13 +1,3 @@ - ---- -name: Pull request -about: Create a pull request -title: '' -labels: '' -assignees: '' - ---- - Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 1. Limited scope. Your PR should do one thing or one set of things. Avoid adding “random fixes” to PRs. Put those on separate PRs. From 4037719b3342595ae2ff31d99dde44d55b33c788 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Sat, 29 Apr 2023 22:22:19 +0100 Subject: [PATCH 012/238] Renovate load controller tests (#569) --- .../test/test_load_admittance_controller.cpp | 5 +++-- .../test/test_load_diff_drive_controller.cpp | 5 +++-- .../test/test_load_joint_group_effort_controller.cpp | 6 ++++-- .../test_load_force_torque_sensor_broadcaster.cpp | 8 +++++--- .../test/test_load_forward_command_controller.cpp | 6 ++++-- ...ad_multi_interface_forward_command_controller.cpp | 8 +++++--- .../test/test_load_gripper_action_controllers.cpp | 12 ++++++++---- .../test/test_load_imu_sensor_broadcaster.cpp | 6 ++++-- .../test/test_load_joint_state_broadcaster.cpp | 6 ++++-- .../test/test_load_joint_trajectory_controller.cpp | 6 ++++-- .../test_load_joint_group_position_controller.cpp | 6 ++++-- .../test/test_load_tricycle_controller.cpp | 7 ++++--- .../test_load_joint_group_velocity_controller.cpp | 6 ++++-- 13 files changed, 56 insertions(+), 31 deletions(-) diff --git a/admittance_controller/test/test_load_admittance_controller.cpp b/admittance_controller/test/test_load_admittance_controller.cpp index 1f290aeff6..23be1f23f5 100644 --- a/admittance_controller/test/test_load_admittance_controller.cpp +++ b/admittance_controller/test/test_load_admittance_controller.cpp @@ -33,8 +33,9 @@ TEST(TestLoadAdmittanceController, load_controller) ros2_control_test_assets::minimal_robot_urdf), executor, "test_controller_manager"); - ASSERT_NO_THROW( - cm.load_controller("load_admittance_controller", "admittance_controller/AdmittanceController")); + ASSERT_EQ( + cm.load_controller("load_admittance_controller", "admittance_controller/AdmittanceController"), + nullptr); } int main(int argc, char ** argv) diff --git a/diff_drive_controller/test/test_load_diff_drive_controller.cpp b/diff_drive_controller/test/test_load_diff_drive_controller.cpp index 20caf46b6f..1eb8939031 100644 --- a/diff_drive_controller/test/test_load_diff_drive_controller.cpp +++ b/diff_drive_controller/test/test_load_diff_drive_controller.cpp @@ -30,8 +30,9 @@ TEST(TestLoadDiffDriveController, load_controller) std::make_unique(ros2_control_test_assets::diffbot_urdf), executor, "test_controller_manager"); - ASSERT_NO_THROW( - cm.load_controller("test_diff_drive_controller", "diff_drive_controller/DiffDriveController")); + ASSERT_NE( + cm.load_controller("test_diff_drive_controller", "diff_drive_controller/DiffDriveController"), + nullptr); rclcpp::shutdown(); } diff --git a/effort_controllers/test/test_load_joint_group_effort_controller.cpp b/effort_controllers/test/test_load_joint_group_effort_controller.cpp index a216d46db3..61bb1ddf9a 100644 --- a/effort_controllers/test/test_load_joint_group_effort_controller.cpp +++ b/effort_controllers/test/test_load_joint_group_effort_controller.cpp @@ -32,8 +32,10 @@ TEST(TestLoadJointGroupVelocityController, load_controller) ros2_control_test_assets::minimal_robot_urdf), executor, "test_controller_manager"); - ASSERT_NO_THROW(cm.load_controller( - "test_joint_group_effort_controller", "effort_controllers/JointGroupEffortController")); + ASSERT_NE( + cm.load_controller( + "test_joint_group_effort_controller", "effort_controllers/JointGroupEffortController"), + nullptr); rclcpp::shutdown(); } diff --git a/force_torque_sensor_broadcaster/test/test_load_force_torque_sensor_broadcaster.cpp b/force_torque_sensor_broadcaster/test/test_load_force_torque_sensor_broadcaster.cpp index 6e9b6b1167..a9ca5e88fc 100644 --- a/force_torque_sensor_broadcaster/test/test_load_force_torque_sensor_broadcaster.cpp +++ b/force_torque_sensor_broadcaster/test/test_load_force_torque_sensor_broadcaster.cpp @@ -38,9 +38,11 @@ TEST(TestLoadForceTorqueSensorBroadcaster, load_controller) ros2_control_test_assets::minimal_robot_urdf), executor, "test_controller_manager"); - ASSERT_NO_THROW(cm.load_controller( - "test_force_torque_sensor_broadcaster", - "force_torque_sensor_broadcaster/ForceTorqueSensorBroadcaster")); + ASSERT_NE( + cm.load_controller( + "test_force_torque_sensor_broadcaster", + "force_torque_sensor_broadcaster/ForceTorqueSensorBroadcaster"), + nullptr); rclcpp::shutdown(); } diff --git a/forward_command_controller/test/test_load_forward_command_controller.cpp b/forward_command_controller/test/test_load_forward_command_controller.cpp index 464b57b69d..b493e52b2a 100644 --- a/forward_command_controller/test/test_load_forward_command_controller.cpp +++ b/forward_command_controller/test/test_load_forward_command_controller.cpp @@ -34,8 +34,10 @@ TEST(TestLoadForwardCommandController, load_controller) ros2_control_test_assets::minimal_robot_urdf), executor, "test_controller_manager"); - ASSERT_NO_THROW(cm.load_controller( - "test_forward_command_controller", "forward_command_controller/ForwardCommandController")); + ASSERT_NE( + cm.load_controller( + "test_forward_command_controller", "forward_command_controller/ForwardCommandController"), + nullptr); rclcpp::shutdown(); } diff --git a/forward_command_controller/test/test_load_multi_interface_forward_command_controller.cpp b/forward_command_controller/test/test_load_multi_interface_forward_command_controller.cpp index 2f540bd0e5..41a9b74698 100644 --- a/forward_command_controller/test/test_load_multi_interface_forward_command_controller.cpp +++ b/forward_command_controller/test/test_load_multi_interface_forward_command_controller.cpp @@ -35,7 +35,9 @@ TEST(TestLoadMultiInterfaceForwardController, load_controller) ros2_control_test_assets::minimal_robot_urdf), executor, "test_controller_manager"); - ASSERT_NO_THROW(cm.load_controller( - "test_forward_command_controller", - "forward_command_controller/MultiInterfaceForwardCommandController")); + ASSERT_NE( + cm.load_controller( + "test_forward_command_controller", + "forward_command_controller/MultiInterfaceForwardCommandController"), + nullptr); } diff --git a/gripper_controllers/test/test_load_gripper_action_controllers.cpp b/gripper_controllers/test/test_load_gripper_action_controllers.cpp index b355cdf34a..130b12e0bb 100644 --- a/gripper_controllers/test/test_load_gripper_action_controllers.cpp +++ b/gripper_controllers/test/test_load_gripper_action_controllers.cpp @@ -32,10 +32,14 @@ TEST(TestLoadGripperActionControllers, load_controller) ros2_control_test_assets::minimal_robot_urdf), executor, "test_controller_manager"); - ASSERT_NO_THROW(cm.load_controller( - "test_gripper_action_position_controller", "position_controllers/GripperActionController")); - ASSERT_NO_THROW(cm.load_controller( - "test_gripper_action_effort_controller", "effort_controllers/GripperActionController")); + ASSERT_NE( + cm.load_controller( + "test_gripper_action_position_controller", "position_controllers/GripperActionController"), + nullptr); + ASSERT_NE( + cm.load_controller( + "test_gripper_action_effort_controller", "effort_controllers/GripperActionController"), + nullptr); rclcpp::shutdown(); } diff --git a/imu_sensor_broadcaster/test/test_load_imu_sensor_broadcaster.cpp b/imu_sensor_broadcaster/test/test_load_imu_sensor_broadcaster.cpp index e90c9915ed..e7cfd1bcf7 100644 --- a/imu_sensor_broadcaster/test/test_load_imu_sensor_broadcaster.cpp +++ b/imu_sensor_broadcaster/test/test_load_imu_sensor_broadcaster.cpp @@ -38,8 +38,10 @@ TEST(TestLoadIMUSensorBroadcaster, load_controller) ros2_control_test_assets::minimal_robot_urdf), executor, "test_controller_manager"); - ASSERT_NO_THROW(cm.load_controller( - "test_imu_sensor_broadcaster", "imu_sensor_broadcaster/IMUSensorBroadcaster")); + ASSERT_NE( + cm.load_controller( + "test_imu_sensor_broadcaster", "imu_sensor_broadcaster/IMUSensorBroadcaster"), + nullptr); rclcpp::shutdown(); } diff --git a/joint_state_broadcaster/test/test_load_joint_state_broadcaster.cpp b/joint_state_broadcaster/test/test_load_joint_state_broadcaster.cpp index d7a2934f57..5efb587805 100644 --- a/joint_state_broadcaster/test/test_load_joint_state_broadcaster.cpp +++ b/joint_state_broadcaster/test/test_load_joint_state_broadcaster.cpp @@ -34,8 +34,10 @@ TEST(TestLoadJointStateBroadcaster, load_controller) ros2_control_test_assets::minimal_robot_urdf), executor, "test_controller_manager"); - ASSERT_NO_THROW(cm.load_controller( - "test_joint_state_broadcaster", "joint_state_broadcaster/JointStateBroadcaster")); + ASSERT_NE( + cm.load_controller( + "test_joint_state_broadcaster", "joint_state_broadcaster/JointStateBroadcaster"), + nullptr); rclcpp::shutdown(); } diff --git a/joint_trajectory_controller/test/test_load_joint_trajectory_controller.cpp b/joint_trajectory_controller/test/test_load_joint_trajectory_controller.cpp index 0f94d0b16c..eb1a3691e6 100644 --- a/joint_trajectory_controller/test/test_load_joint_trajectory_controller.cpp +++ b/joint_trajectory_controller/test/test_load_joint_trajectory_controller.cpp @@ -35,8 +35,10 @@ TEST(TestLoadJointStateController, load_controller) ros2_control_test_assets::minimal_robot_urdf), executor, "test_controller_manager"); - ASSERT_NO_THROW(cm.load_controller( - "test_joint_trajectory_controller", "joint_trajectory_controller/JointTrajectoryController")); + ASSERT_NE( + cm.load_controller( + "test_joint_trajectory_controller", "joint_trajectory_controller/JointTrajectoryController"), + nullptr); rclcpp::shutdown(); } diff --git a/position_controllers/test/test_load_joint_group_position_controller.cpp b/position_controllers/test/test_load_joint_group_position_controller.cpp index cc376bd2d4..fe61039fdb 100644 --- a/position_controllers/test/test_load_joint_group_position_controller.cpp +++ b/position_controllers/test/test_load_joint_group_position_controller.cpp @@ -32,8 +32,10 @@ TEST(TestLoadJointGroupPositionController, load_controller) ros2_control_test_assets::minimal_robot_urdf), executor, "test_controller_manager"); - ASSERT_NO_THROW(cm.load_controller( - "test_joint_group_position_controller", "position_controllers/JointGroupPositionController")); + ASSERT_NE( + cm.load_controller( + "test_joint_group_position_controller", "position_controllers/JointGroupPositionController"), + nullptr); rclcpp::shutdown(); } diff --git a/tricycle_controller/test/test_load_tricycle_controller.cpp b/tricycle_controller/test/test_load_tricycle_controller.cpp index d04b83ae27..9298fae574 100644 --- a/tricycle_controller/test/test_load_tricycle_controller.cpp +++ b/tricycle_controller/test/test_load_tricycle_controller.cpp @@ -16,7 +16,7 @@ * Author: Tony Najjar */ -#include +#include #include #include "controller_manager/controller_manager.hpp" @@ -36,8 +36,9 @@ TEST(TestLoadTricycleController, load_controller) ros2_control_test_assets::minimal_robot_urdf), executor, "test_controller_manager"); - ASSERT_NO_THROW( - cm.load_controller("test_tricycle_controller", "tricycle_controller/TricycleController")); + ASSERT_NE( + cm.load_controller("test_tricycle_controller", "tricycle_controller/TricycleController"), + nullptr); rclcpp::shutdown(); } diff --git a/velocity_controllers/test/test_load_joint_group_velocity_controller.cpp b/velocity_controllers/test/test_load_joint_group_velocity_controller.cpp index 36d5a8368d..1872b5f746 100644 --- a/velocity_controllers/test/test_load_joint_group_velocity_controller.cpp +++ b/velocity_controllers/test/test_load_joint_group_velocity_controller.cpp @@ -32,8 +32,10 @@ TEST(TestLoadJointGroupVelocityController, load_controller) ros2_control_test_assets::minimal_robot_urdf), executor, "test_controller_manager"); - ASSERT_NO_THROW(cm.load_controller( - "test_joint_group_velocity_controller", "velocity_controllers/JointGroupVelocityController")); + ASSERT_NE( + cm.load_controller( + "test_joint_group_velocity_controller", "velocity_controllers/JointGroupVelocityController"), + nullptr); rclcpp::shutdown(); } From 3bb74e7fff99eda85eb5583b9ad7f733e62bcdeb Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Sat, 29 Apr 2023 22:37:12 +0100 Subject: [PATCH 013/238] Update changelogs --- admittance_controller/CHANGELOG.rst | 6 ++++++ diff_drive_controller/CHANGELOG.rst | 6 ++++++ effort_controllers/CHANGELOG.rst | 5 +++++ force_torque_sensor_broadcaster/CHANGELOG.rst | 5 +++++ forward_command_controller/CHANGELOG.rst | 6 ++++++ gripper_controllers/CHANGELOG.rst | 5 +++++ imu_sensor_broadcaster/CHANGELOG.rst | 5 +++++ joint_state_broadcaster/CHANGELOG.rst | 6 ++++++ joint_trajectory_controller/CHANGELOG.rst | 7 +++++++ position_controllers/CHANGELOG.rst | 5 +++++ ros2_controllers/CHANGELOG.rst | 3 +++ ros2_controllers_test_nodes/CHANGELOG.rst | 3 +++ rqt_joint_trajectory_controller/CHANGELOG.rst | 3 +++ tricycle_controller/CHANGELOG.rst | 5 +++++ velocity_controllers/CHANGELOG.rst | 5 +++++ 15 files changed, 75 insertions(+) diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index b7d6801e3c..a5621304b8 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Renovate load controller tests (`#569 `_) +* Fix docs format (`#589 `_) +* Contributors: Bence Magyar, Christoph Fröhlich + 3.5.0 (2023-04-14) ------------------ * Misplaced param init in admittance_controller (`#547 `_) diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index 1d2f0a3fbd..a28cd0baea 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Renovate load controller tests (`#569 `_) +* adjusted open_loop param description in diff_drive_controller_parameter.yaml (`#570 `_) +* Contributors: Bence Magyar, muritane + 3.5.0 (2023-04-14) ------------------ diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index 3611be1381..355f6a0576 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Renovate load controller tests (`#569 `_) +* Contributors: Bence Magyar + 3.5.0 (2023-04-14) ------------------ diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index a1f9adbadd..34450fa1cb 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Renovate load controller tests (`#569 `_) +* Contributors: Bence Magyar + 3.5.0 (2023-04-14) ------------------ diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index fa71f9125a..786962aa42 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Renovate load controller tests (`#569 `_) +* Fix docs format (`#589 `_) +* Contributors: Bence Magyar, Christoph Fröhlich + 3.5.0 (2023-04-14) ------------------ diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index d390f60ed8..c46a42bb3e 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Renovate load controller tests (`#569 `_) +* Contributors: Bence Magyar + 3.5.0 (2023-04-14) ------------------ * [Parameters] Use `gt_eq` instead of deprecated `lower_bounds` in validators (`#561 `_) diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index 2de70959cf..e333525386 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Renovate load controller tests (`#569 `_) +* Contributors: Bence Magyar + 3.5.0 (2023-04-14) ------------------ diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index 39d94ad9fd..084358ac4a 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Renovate load controller tests (`#569 `_) +* Fix docs format (`#589 `_) +* Contributors: Bence Magyar, Christoph Fröhlich + 3.5.0 (2023-04-14) ------------------ diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index b153636ec0..b5797f1a3f 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,13 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Renovate load controller tests (`#569 `_) +* Fix docs format (`#589 `_) +* [JTC] Implement new ~/controller_state message (`#557 `_) +* Contributors: Bence Magyar, Christoph Fröhlich + 3.5.0 (2023-04-14) ------------------ * [Parameters] Use `gt_eq` instead of deprecated `lower_bounds` in validators (`#561 `_) diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index 428b6b5f1d..3a3936bc61 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Renovate load controller tests (`#569 `_) +* Contributors: Bence Magyar + 3.5.0 (2023-04-14) ------------------ diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index 5629c27780..348f0df662 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.5.0 (2023-04-14) ------------------ diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index 638312ac61..b1bb0e217c 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.5.0 (2023-04-14) ------------------ diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index 5cac7c803a..ce7da67d6d 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.5.0 (2023-04-14) ------------------ diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index d73a931b9b..f1dacc5a6f 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Renovate load controller tests (`#569 `_) +* Contributors: Bence Magyar + 3.5.0 (2023-04-14) ------------------ diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index 538a095495..794d2d32db 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Renovate load controller tests (`#569 `_) +* Contributors: Bence Magyar + 3.5.0 (2023-04-14) ------------------ From 00a8c2e3a2152fc7d627187d0e7434765f1777b1 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Sat, 29 Apr 2023 22:39:22 +0100 Subject: [PATCH 014/238] 3.6.0 --- admittance_controller/CHANGELOG.rst | 4 ++-- admittance_controller/package.xml | 2 +- diff_drive_controller/CHANGELOG.rst | 4 ++-- diff_drive_controller/package.xml | 2 +- effort_controllers/CHANGELOG.rst | 4 ++-- effort_controllers/package.xml | 2 +- force_torque_sensor_broadcaster/CHANGELOG.rst | 4 ++-- force_torque_sensor_broadcaster/package.xml | 2 +- forward_command_controller/CHANGELOG.rst | 4 ++-- forward_command_controller/package.xml | 2 +- gripper_controllers/CHANGELOG.rst | 4 ++-- gripper_controllers/package.xml | 2 +- imu_sensor_broadcaster/CHANGELOG.rst | 4 ++-- imu_sensor_broadcaster/package.xml | 2 +- joint_state_broadcaster/CHANGELOG.rst | 4 ++-- joint_state_broadcaster/package.xml | 2 +- joint_trajectory_controller/CHANGELOG.rst | 4 ++-- joint_trajectory_controller/package.xml | 2 +- position_controllers/CHANGELOG.rst | 4 ++-- position_controllers/package.xml | 2 +- ros2_controllers/CHANGELOG.rst | 4 ++-- ros2_controllers/package.xml | 2 +- ros2_controllers_test_nodes/CHANGELOG.rst | 4 ++-- ros2_controllers_test_nodes/package.xml | 2 +- ros2_controllers_test_nodes/setup.py | 2 +- rqt_joint_trajectory_controller/CHANGELOG.rst | 4 ++-- rqt_joint_trajectory_controller/package.xml | 2 +- rqt_joint_trajectory_controller/setup.py | 2 +- tricycle_controller/CHANGELOG.rst | 4 ++-- tricycle_controller/package.xml | 2 +- velocity_controllers/CHANGELOG.rst | 4 ++-- velocity_controllers/package.xml | 2 +- 32 files changed, 47 insertions(+), 47 deletions(-) diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index a5621304b8..775c6cb1f0 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.6.0 (2023-04-29) +------------------ * Renovate load controller tests (`#569 `_) * Fix docs format (`#589 `_) * Contributors: Bence Magyar, Christoph Fröhlich diff --git a/admittance_controller/package.xml b/admittance_controller/package.xml index 65f2b9c9b2..253848eeba 100644 --- a/admittance_controller/package.xml +++ b/admittance_controller/package.xml @@ -2,7 +2,7 @@ admittance_controller - 3.5.0 + 3.6.0 Implementation of admittance controllers for different input and output interface. Denis Štogl Bence Magyar diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index a28cd0baea..2cb66cfd13 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.6.0 (2023-04-29) +------------------ * Renovate load controller tests (`#569 `_) * adjusted open_loop param description in diff_drive_controller_parameter.yaml (`#570 `_) * Contributors: Bence Magyar, muritane diff --git a/diff_drive_controller/package.xml b/diff_drive_controller/package.xml index 96050a2f01..259e3a4835 100644 --- a/diff_drive_controller/package.xml +++ b/diff_drive_controller/package.xml @@ -1,7 +1,7 @@ diff_drive_controller - 3.5.0 + 3.6.0 Controller for a differential drive mobile base. Bence Magyar Jordan Palacios diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index 355f6a0576..5d6b5ad33f 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.6.0 (2023-04-29) +------------------ * Renovate load controller tests (`#569 `_) * Contributors: Bence Magyar diff --git a/effort_controllers/package.xml b/effort_controllers/package.xml index 24228506a7..4b810f018f 100644 --- a/effort_controllers/package.xml +++ b/effort_controllers/package.xml @@ -1,7 +1,7 @@ effort_controllers - 3.5.0 + 3.6.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index 34450fa1cb..7aaedabd91 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.6.0 (2023-04-29) +------------------ * Renovate load controller tests (`#569 `_) * Contributors: Bence Magyar diff --git a/force_torque_sensor_broadcaster/package.xml b/force_torque_sensor_broadcaster/package.xml index df76d575c6..884910a239 100644 --- a/force_torque_sensor_broadcaster/package.xml +++ b/force_torque_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ force_torque_sensor_broadcaster - 3.5.0 + 3.6.0 Controller to publish state of force-torque sensors. Bence Magyar Denis Štogl diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index 786962aa42..c6a70728c8 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.6.0 (2023-04-29) +------------------ * Renovate load controller tests (`#569 `_) * Fix docs format (`#589 `_) * Contributors: Bence Magyar, Christoph Fröhlich diff --git a/forward_command_controller/package.xml b/forward_command_controller/package.xml index f05ea322c5..f300283bea 100644 --- a/forward_command_controller/package.xml +++ b/forward_command_controller/package.xml @@ -1,7 +1,7 @@ forward_command_controller - 3.5.0 + 3.6.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index c46a42bb3e..ffbd89cdc8 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.6.0 (2023-04-29) +------------------ * Renovate load controller tests (`#569 `_) * Contributors: Bence Magyar diff --git a/gripper_controllers/package.xml b/gripper_controllers/package.xml index 770c4b257a..1741f468bd 100644 --- a/gripper_controllers/package.xml +++ b/gripper_controllers/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> gripper_controllers - 3.5.0 + 3.6.0 The gripper_controllers package Bence Magyar diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index e333525386..976b41ec54 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.6.0 (2023-04-29) +------------------ * Renovate load controller tests (`#569 `_) * Contributors: Bence Magyar diff --git a/imu_sensor_broadcaster/package.xml b/imu_sensor_broadcaster/package.xml index 19ff483aba..16a276b218 100644 --- a/imu_sensor_broadcaster/package.xml +++ b/imu_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ imu_sensor_broadcaster - 3.5.0 + 3.6.0 Controller to publish readings of IMU sensors. Bence Magyar Denis Štogl diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index 084358ac4a..14b1b2a517 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.6.0 (2023-04-29) +------------------ * Renovate load controller tests (`#569 `_) * Fix docs format (`#589 `_) * Contributors: Bence Magyar, Christoph Fröhlich diff --git a/joint_state_broadcaster/package.xml b/joint_state_broadcaster/package.xml index 3f8b0ee517..5a2c3665a3 100644 --- a/joint_state_broadcaster/package.xml +++ b/joint_state_broadcaster/package.xml @@ -1,7 +1,7 @@ joint_state_broadcaster - 3.5.0 + 3.6.0 Broadcaster to publish joint state Bence Magyar Denis Stogl diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index b5797f1a3f..26e1447b0e 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.6.0 (2023-04-29) +------------------ * Renovate load controller tests (`#569 `_) * Fix docs format (`#589 `_) * [JTC] Implement new ~/controller_state message (`#557 `_) diff --git a/joint_trajectory_controller/package.xml b/joint_trajectory_controller/package.xml index f8e3908657..64a56b0375 100644 --- a/joint_trajectory_controller/package.xml +++ b/joint_trajectory_controller/package.xml @@ -1,7 +1,7 @@ joint_trajectory_controller - 3.5.0 + 3.6.0 Controller for executing joint-space trajectories on a group of joints Bence Magyar Jordan Palacios diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index 3a3936bc61..e056c8544d 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.6.0 (2023-04-29) +------------------ * Renovate load controller tests (`#569 `_) * Contributors: Bence Magyar diff --git a/position_controllers/package.xml b/position_controllers/package.xml index c16c0895dc..b1e0609a43 100644 --- a/position_controllers/package.xml +++ b/position_controllers/package.xml @@ -1,7 +1,7 @@ position_controllers - 3.5.0 + 3.6.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index 348f0df662..6cb91dc982 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.6.0 (2023-04-29) +------------------ 3.5.0 (2023-04-14) ------------------ diff --git a/ros2_controllers/package.xml b/ros2_controllers/package.xml index 799b733945..ad3ed5493d 100644 --- a/ros2_controllers/package.xml +++ b/ros2_controllers/package.xml @@ -1,7 +1,7 @@ ros2_controllers - 3.5.0 + 3.6.0 Metapackage for ROS2 controllers related packages Bence Magyar Jordan Palacios diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index b1bb0e217c..5e7a1de558 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.6.0 (2023-04-29) +------------------ 3.5.0 (2023-04-14) ------------------ diff --git a/ros2_controllers_test_nodes/package.xml b/ros2_controllers_test_nodes/package.xml index af7b40c799..44207cf598 100644 --- a/ros2_controllers_test_nodes/package.xml +++ b/ros2_controllers_test_nodes/package.xml @@ -2,7 +2,7 @@ ros2_controllers_test_nodes - 3.5.0 + 3.6.0 Demo nodes for showing and testing functionalities of the ros2_control framework. Denis Štogl diff --git a/ros2_controllers_test_nodes/setup.py b/ros2_controllers_test_nodes/setup.py index dc28906b5e..b0050c83e5 100644 --- a/ros2_controllers_test_nodes/setup.py +++ b/ros2_controllers_test_nodes/setup.py @@ -20,7 +20,7 @@ setup( name=package_name, - version="3.5.0", + version="3.6.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index ce7da67d6d..7068d774ac 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.6.0 (2023-04-29) +------------------ 3.5.0 (2023-04-14) ------------------ diff --git a/rqt_joint_trajectory_controller/package.xml b/rqt_joint_trajectory_controller/package.xml index 5d9bd8215e..f5d567edb5 100644 --- a/rqt_joint_trajectory_controller/package.xml +++ b/rqt_joint_trajectory_controller/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> rqt_joint_trajectory_controller - 3.5.0 + 3.6.0 Graphical frontend for interacting with joint_trajectory_controller instances. Bence Magyar diff --git a/rqt_joint_trajectory_controller/setup.py b/rqt_joint_trajectory_controller/setup.py index 81db8a055a..8e57dd1123 100644 --- a/rqt_joint_trajectory_controller/setup.py +++ b/rqt_joint_trajectory_controller/setup.py @@ -7,7 +7,7 @@ setup( name=package_name, - version="3.5.0", + version="3.6.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index f1dacc5a6f..d84e66bb4e 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.6.0 (2023-04-29) +------------------ * Renovate load controller tests (`#569 `_) * Contributors: Bence Magyar diff --git a/tricycle_controller/package.xml b/tricycle_controller/package.xml index 3bb3095ddd..2072b334a7 100644 --- a/tricycle_controller/package.xml +++ b/tricycle_controller/package.xml @@ -2,7 +2,7 @@ tricycle_controller - 3.5.0 + 3.6.0 Controller for a tricycle drive mobile base Bence Magyar Tony Najjar diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index 794d2d32db..dca69ca6d1 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.6.0 (2023-04-29) +------------------ * Renovate load controller tests (`#569 `_) * Contributors: Bence Magyar diff --git a/velocity_controllers/package.xml b/velocity_controllers/package.xml index 50c8dfa619..f3205e00cc 100644 --- a/velocity_controllers/package.xml +++ b/velocity_controllers/package.xml @@ -1,7 +1,7 @@ velocity_controllers - 3.5.0 + 3.6.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios From 634e6fe03497bedd4ffa805c327a53f2fe297e5e Mon Sep 17 00:00:00 2001 From: Marq Rasmussen Date: Tue, 2 May 2023 11:40:25 -0600 Subject: [PATCH 015/238] Fix JTC from immediately returning success (#565) Co-authored-by: Bence Magyar --- .../src/joint_trajectory_controller.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/joint_trajectory_controller/src/joint_trajectory_controller.cpp b/joint_trajectory_controller/src/joint_trajectory_controller.cpp index b6a60526fa..07080bb1fc 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller.cpp +++ b/joint_trajectory_controller/src/joint_trajectory_controller.cpp @@ -152,6 +152,8 @@ controller_interface::return_type JointTrajectoryController::update( sort_to_local_joint_order(*new_external_msg); // TODO(denis): Add here integration of position and velocity traj_external_point_ptr_->update(*new_external_msg); + // set the active trajectory pointer to the new goal + traj_point_active_ptr_ = &traj_external_point_ptr_; } // TODO(anyone): can I here also use const on joint_interface since the reference_wrapper is not @@ -315,6 +317,8 @@ controller_interface::return_type JointTrajectoryController::update( // TODO(matthew-reynolds): Need a lock-free write here // See https://github.com/ros-controls/ros2_controllers/issues/168 rt_active_goal_.writeFromNonRT(RealtimeGoalHandlePtr()); + // remove the active trajectory pointer so that we stop commanding the hardware + traj_point_active_ptr_ = nullptr; // check goal tolerance } @@ -328,6 +332,8 @@ controller_interface::return_type JointTrajectoryController::update( // TODO(matthew-reynolds): Need a lock-free write here // See https://github.com/ros-controls/ros2_controllers/issues/168 rt_active_goal_.writeFromNonRT(RealtimeGoalHandlePtr()); + // remove the active trajectory pointer so that we stop commanding the hardware + traj_point_active_ptr_ = nullptr; RCLCPP_INFO(get_node()->get_logger(), "Goal reached, success!"); } From 7cb412887c79ff405103c57fd8fd08aaedf33365 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noel=20Jim=C3=A9nez=20Garc=C3=ADa?= <48183611+Noel215@users.noreply.github.com> Date: Tue, 2 May 2023 23:14:53 +0200 Subject: [PATCH 016/238] Fix wrong publish timestamp initialization (#585) * Fix publish timestamp Signed-off-by: Noel Jimenez * Document catch purpose Signed-off-by: Noel Jimenez --------- Signed-off-by: Noel Jimenez --- .../diff_drive_controller.hpp | 2 +- .../src/diff_drive_controller.cpp | 19 +++++++++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/diff_drive_controller/include/diff_drive_controller/diff_drive_controller.hpp b/diff_drive_controller/include/diff_drive_controller/diff_drive_controller.hpp index 277c7bd99b..5923a27d4d 100644 --- a/diff_drive_controller/include/diff_drive_controller/diff_drive_controller.hpp +++ b/diff_drive_controller/include/diff_drive_controller/diff_drive_controller.hpp @@ -148,7 +148,7 @@ class DiffDriveController : public controller_interface::ControllerInterface // publish rate limiter double publish_rate_ = 50.0; rclcpp::Duration publish_period_ = rclcpp::Duration::from_nanoseconds(0); - rclcpp::Time previous_publish_timestamp_{0}; + rclcpp::Time previous_publish_timestamp_{0, 0, RCL_CLOCK_UNINITIALIZED}; bool is_halted = false; bool use_stamped_vel_ = true; diff --git a/diff_drive_controller/src/diff_drive_controller.cpp b/diff_drive_controller/src/diff_drive_controller.cpp index b6d9b07a49..22b9acd829 100644 --- a/diff_drive_controller/src/diff_drive_controller.cpp +++ b/diff_drive_controller/src/diff_drive_controller.cpp @@ -185,7 +185,23 @@ controller_interface::return_type DiffDriveController::update( tf2::Quaternion orientation; orientation.setRPY(0.0, 0.0, odometry_.getHeading()); - if (previous_publish_timestamp_ + publish_period_ < time) + bool should_publish = false; + try + { + if (previous_publish_timestamp_ + publish_period_ < time) + { + previous_publish_timestamp_ += publish_period_; + should_publish = true; + } + } + catch (const std::runtime_error) + { + // Handle exceptions when the time source changes and initialize publish timestamp + previous_publish_timestamp_ = time; + should_publish = true; + } + + if (should_publish) { previous_publish_timestamp_ += publish_period_; @@ -400,7 +416,6 @@ controller_interface::CallbackReturn DiffDriveController::on_configure( // limit the publication on the topics /odom and /tf publish_rate_ = get_node()->get_parameter("publish_rate").as_double(); publish_period_ = rclcpp::Duration::from_seconds(1.0 / publish_rate_); - previous_publish_timestamp_ = get_node()->get_clock()->now(); // initialize odom values zeros odometry_message.twist = From 34008468dbb702278e26b6d65cb8bf1c411b8ee5 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Tue, 2 May 2023 22:22:32 +0100 Subject: [PATCH 017/238] Update changelogs --- admittance_controller/CHANGELOG.rst | 3 +++ diff_drive_controller/CHANGELOG.rst | 5 +++++ effort_controllers/CHANGELOG.rst | 3 +++ force_torque_sensor_broadcaster/CHANGELOG.rst | 3 +++ forward_command_controller/CHANGELOG.rst | 3 +++ gripper_controllers/CHANGELOG.rst | 3 +++ imu_sensor_broadcaster/CHANGELOG.rst | 3 +++ joint_state_broadcaster/CHANGELOG.rst | 3 +++ joint_trajectory_controller/CHANGELOG.rst | 5 +++++ position_controllers/CHANGELOG.rst | 3 +++ ros2_controllers/CHANGELOG.rst | 3 +++ ros2_controllers_test_nodes/CHANGELOG.rst | 3 +++ rqt_joint_trajectory_controller/CHANGELOG.rst | 3 +++ tricycle_controller/CHANGELOG.rst | 3 +++ velocity_controllers/CHANGELOG.rst | 3 +++ 15 files changed, 49 insertions(+) diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index 775c6cb1f0..65ab9c3fab 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.6.0 (2023-04-29) ------------------ * Renovate load controller tests (`#569 `_) diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index 2cb66cfd13..ead77a8092 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Fix wrong publish timestamp initialization (`#585 `_) +* Contributors: Noel Jiménez García + 3.6.0 (2023-04-29) ------------------ * Renovate load controller tests (`#569 `_) diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index 5d6b5ad33f..dc27b09976 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.6.0 (2023-04-29) ------------------ * Renovate load controller tests (`#569 `_) diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index 7aaedabd91..faf8141487 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.6.0 (2023-04-29) ------------------ * Renovate load controller tests (`#569 `_) diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index c6a70728c8..025e0e8b3c 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.6.0 (2023-04-29) ------------------ * Renovate load controller tests (`#569 `_) diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index ffbd89cdc8..8d91e270d3 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.6.0 (2023-04-29) ------------------ * Renovate load controller tests (`#569 `_) diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index 976b41ec54..e39f245d37 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.6.0 (2023-04-29) ------------------ * Renovate load controller tests (`#569 `_) diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index 14b1b2a517..73a8fc2d0b 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.6.0 (2023-04-29) ------------------ * Renovate load controller tests (`#569 `_) diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index 26e1447b0e..987beab601 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Fix JTC from immediately returning success (`#565 `_) +* Contributors: Marq Rasmussen + 3.6.0 (2023-04-29) ------------------ * Renovate load controller tests (`#569 `_) diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index e056c8544d..0ff0f42f79 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.6.0 (2023-04-29) ------------------ * Renovate load controller tests (`#569 `_) diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index 6cb91dc982..46094516e2 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.6.0 (2023-04-29) ------------------ diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index 5e7a1de558..8cbec95721 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.6.0 (2023-04-29) ------------------ diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index 7068d774ac..6d488c190c 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.6.0 (2023-04-29) ------------------ diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index d84e66bb4e..c6e39022fa 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.6.0 (2023-04-29) ------------------ * Renovate load controller tests (`#569 `_) diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index dca69ca6d1..745b6cb87f 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.6.0 (2023-04-29) ------------------ * Renovate load controller tests (`#569 `_) From 6793e0278f35b34800c14a085188f3d7a3b4f6ad Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Tue, 2 May 2023 22:23:06 +0100 Subject: [PATCH 018/238] 3.7.0 --- admittance_controller/CHANGELOG.rst | 4 ++-- admittance_controller/package.xml | 2 +- diff_drive_controller/CHANGELOG.rst | 4 ++-- diff_drive_controller/package.xml | 2 +- effort_controllers/CHANGELOG.rst | 4 ++-- effort_controllers/package.xml | 2 +- force_torque_sensor_broadcaster/CHANGELOG.rst | 4 ++-- force_torque_sensor_broadcaster/package.xml | 2 +- forward_command_controller/CHANGELOG.rst | 4 ++-- forward_command_controller/package.xml | 2 +- gripper_controllers/CHANGELOG.rst | 4 ++-- gripper_controllers/package.xml | 2 +- imu_sensor_broadcaster/CHANGELOG.rst | 4 ++-- imu_sensor_broadcaster/package.xml | 2 +- joint_state_broadcaster/CHANGELOG.rst | 4 ++-- joint_state_broadcaster/package.xml | 2 +- joint_trajectory_controller/CHANGELOG.rst | 4 ++-- joint_trajectory_controller/package.xml | 2 +- position_controllers/CHANGELOG.rst | 4 ++-- position_controllers/package.xml | 2 +- ros2_controllers/CHANGELOG.rst | 4 ++-- ros2_controllers/package.xml | 2 +- ros2_controllers_test_nodes/CHANGELOG.rst | 4 ++-- ros2_controllers_test_nodes/package.xml | 2 +- ros2_controllers_test_nodes/setup.py | 2 +- rqt_joint_trajectory_controller/CHANGELOG.rst | 4 ++-- rqt_joint_trajectory_controller/package.xml | 2 +- rqt_joint_trajectory_controller/setup.py | 2 +- tricycle_controller/CHANGELOG.rst | 4 ++-- tricycle_controller/package.xml | 2 +- velocity_controllers/CHANGELOG.rst | 4 ++-- velocity_controllers/package.xml | 2 +- 32 files changed, 47 insertions(+), 47 deletions(-) diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index 65ab9c3fab..63ca4f4c0c 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.7.0 (2023-05-02) +------------------ 3.6.0 (2023-04-29) ------------------ diff --git a/admittance_controller/package.xml b/admittance_controller/package.xml index 253848eeba..022e8e1353 100644 --- a/admittance_controller/package.xml +++ b/admittance_controller/package.xml @@ -2,7 +2,7 @@ admittance_controller - 3.6.0 + 3.7.0 Implementation of admittance controllers for different input and output interface. Denis Štogl Bence Magyar diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index ead77a8092..272656ce20 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.7.0 (2023-05-02) +------------------ * Fix wrong publish timestamp initialization (`#585 `_) * Contributors: Noel Jiménez García diff --git a/diff_drive_controller/package.xml b/diff_drive_controller/package.xml index 259e3a4835..0fdbb3a8a5 100644 --- a/diff_drive_controller/package.xml +++ b/diff_drive_controller/package.xml @@ -1,7 +1,7 @@ diff_drive_controller - 3.6.0 + 3.7.0 Controller for a differential drive mobile base. Bence Magyar Jordan Palacios diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index dc27b09976..767184b5d3 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.7.0 (2023-05-02) +------------------ 3.6.0 (2023-04-29) ------------------ diff --git a/effort_controllers/package.xml b/effort_controllers/package.xml index 4b810f018f..02fc8594c0 100644 --- a/effort_controllers/package.xml +++ b/effort_controllers/package.xml @@ -1,7 +1,7 @@ effort_controllers - 3.6.0 + 3.7.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index faf8141487..672d2b53ca 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.7.0 (2023-05-02) +------------------ 3.6.0 (2023-04-29) ------------------ diff --git a/force_torque_sensor_broadcaster/package.xml b/force_torque_sensor_broadcaster/package.xml index 884910a239..f7ab4d61ab 100644 --- a/force_torque_sensor_broadcaster/package.xml +++ b/force_torque_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ force_torque_sensor_broadcaster - 3.6.0 + 3.7.0 Controller to publish state of force-torque sensors. Bence Magyar Denis Štogl diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index 025e0e8b3c..bf3b24ab82 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.7.0 (2023-05-02) +------------------ 3.6.0 (2023-04-29) ------------------ diff --git a/forward_command_controller/package.xml b/forward_command_controller/package.xml index f300283bea..4441a019ab 100644 --- a/forward_command_controller/package.xml +++ b/forward_command_controller/package.xml @@ -1,7 +1,7 @@ forward_command_controller - 3.6.0 + 3.7.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index 8d91e270d3..b7378fa760 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.7.0 (2023-05-02) +------------------ 3.6.0 (2023-04-29) ------------------ diff --git a/gripper_controllers/package.xml b/gripper_controllers/package.xml index 1741f468bd..4d53c64d7f 100644 --- a/gripper_controllers/package.xml +++ b/gripper_controllers/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> gripper_controllers - 3.6.0 + 3.7.0 The gripper_controllers package Bence Magyar diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index e39f245d37..9049c11f6a 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.7.0 (2023-05-02) +------------------ 3.6.0 (2023-04-29) ------------------ diff --git a/imu_sensor_broadcaster/package.xml b/imu_sensor_broadcaster/package.xml index 16a276b218..b5e9e6c9f8 100644 --- a/imu_sensor_broadcaster/package.xml +++ b/imu_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ imu_sensor_broadcaster - 3.6.0 + 3.7.0 Controller to publish readings of IMU sensors. Bence Magyar Denis Štogl diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index 73a8fc2d0b..3812d61ac3 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.7.0 (2023-05-02) +------------------ 3.6.0 (2023-04-29) ------------------ diff --git a/joint_state_broadcaster/package.xml b/joint_state_broadcaster/package.xml index 5a2c3665a3..5ad73b4ea0 100644 --- a/joint_state_broadcaster/package.xml +++ b/joint_state_broadcaster/package.xml @@ -1,7 +1,7 @@ joint_state_broadcaster - 3.6.0 + 3.7.0 Broadcaster to publish joint state Bence Magyar Denis Stogl diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index 987beab601..fbb24978b7 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.7.0 (2023-05-02) +------------------ * Fix JTC from immediately returning success (`#565 `_) * Contributors: Marq Rasmussen diff --git a/joint_trajectory_controller/package.xml b/joint_trajectory_controller/package.xml index 64a56b0375..00cad650c4 100644 --- a/joint_trajectory_controller/package.xml +++ b/joint_trajectory_controller/package.xml @@ -1,7 +1,7 @@ joint_trajectory_controller - 3.6.0 + 3.7.0 Controller for executing joint-space trajectories on a group of joints Bence Magyar Jordan Palacios diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index 0ff0f42f79..3b04f3b06f 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.7.0 (2023-05-02) +------------------ 3.6.0 (2023-04-29) ------------------ diff --git a/position_controllers/package.xml b/position_controllers/package.xml index b1e0609a43..b1ca3b38b7 100644 --- a/position_controllers/package.xml +++ b/position_controllers/package.xml @@ -1,7 +1,7 @@ position_controllers - 3.6.0 + 3.7.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index 46094516e2..3397d446e8 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.7.0 (2023-05-02) +------------------ 3.6.0 (2023-04-29) ------------------ diff --git a/ros2_controllers/package.xml b/ros2_controllers/package.xml index ad3ed5493d..b2b7fe286c 100644 --- a/ros2_controllers/package.xml +++ b/ros2_controllers/package.xml @@ -1,7 +1,7 @@ ros2_controllers - 3.6.0 + 3.7.0 Metapackage for ROS2 controllers related packages Bence Magyar Jordan Palacios diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index 8cbec95721..69e4765398 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.7.0 (2023-05-02) +------------------ 3.6.0 (2023-04-29) ------------------ diff --git a/ros2_controllers_test_nodes/package.xml b/ros2_controllers_test_nodes/package.xml index 44207cf598..3fee344465 100644 --- a/ros2_controllers_test_nodes/package.xml +++ b/ros2_controllers_test_nodes/package.xml @@ -2,7 +2,7 @@ ros2_controllers_test_nodes - 3.6.0 + 3.7.0 Demo nodes for showing and testing functionalities of the ros2_control framework. Denis Štogl diff --git a/ros2_controllers_test_nodes/setup.py b/ros2_controllers_test_nodes/setup.py index b0050c83e5..3cdf9a76ef 100644 --- a/ros2_controllers_test_nodes/setup.py +++ b/ros2_controllers_test_nodes/setup.py @@ -20,7 +20,7 @@ setup( name=package_name, - version="3.6.0", + version="3.7.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index 6d488c190c..b9c0b090d0 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.7.0 (2023-05-02) +------------------ 3.6.0 (2023-04-29) ------------------ diff --git a/rqt_joint_trajectory_controller/package.xml b/rqt_joint_trajectory_controller/package.xml index f5d567edb5..86196cac41 100644 --- a/rqt_joint_trajectory_controller/package.xml +++ b/rqt_joint_trajectory_controller/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> rqt_joint_trajectory_controller - 3.6.0 + 3.7.0 Graphical frontend for interacting with joint_trajectory_controller instances. Bence Magyar diff --git a/rqt_joint_trajectory_controller/setup.py b/rqt_joint_trajectory_controller/setup.py index 8e57dd1123..f04123ec65 100644 --- a/rqt_joint_trajectory_controller/setup.py +++ b/rqt_joint_trajectory_controller/setup.py @@ -7,7 +7,7 @@ setup( name=package_name, - version="3.6.0", + version="3.7.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index c6e39022fa..bf0c5a0102 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.7.0 (2023-05-02) +------------------ 3.6.0 (2023-04-29) ------------------ diff --git a/tricycle_controller/package.xml b/tricycle_controller/package.xml index 2072b334a7..83cb39cc7f 100644 --- a/tricycle_controller/package.xml +++ b/tricycle_controller/package.xml @@ -2,7 +2,7 @@ tricycle_controller - 3.6.0 + 3.7.0 Controller for a tricycle drive mobile base Bence Magyar Tony Najjar diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index 745b6cb87f..4d584c209f 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.7.0 (2023-05-02) +------------------ 3.6.0 (2023-04-29) ------------------ diff --git a/velocity_controllers/package.xml b/velocity_controllers/package.xml index f3205e00cc..4bbf7a2723 100644 --- a/velocity_controllers/package.xml +++ b/velocity_controllers/package.xml @@ -1,7 +1,7 @@ velocity_controllers - 3.6.0 + 3.7.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios From 0ffadb8840bdca0c4658cbf3539f6ee4e1057131 Mon Sep 17 00:00:00 2001 From: Alex Moriarty Date: Sun, 7 May 2023 17:46:00 -0300 Subject: [PATCH 019/238] [EOL] Drop EOL Galactic from github actions (#598) Galactic EOL Date: December 9th, 2022 https://docs.ros.org/en/rolling/Releases.html - remove all galactic repo files - remove all galactic workflows - remove all galactic status badges Signed-off-by: Alex Moriarty --- .github/mergify.yml | 9 ----- .github/workflows/README.md | 1 - .../workflows/galactic-abi-compatibility.yml | 20 ----------- .../workflows/galactic-binary-build-main.yml | 26 --------------- .../galactic-binary-build-testing.yml | 26 --------------- .../workflows/galactic-rhel-binary-build.yml | 33 ------------------- .../galactic-semi-binary-build-main.yml | 25 -------------- .../galactic-semi-binary-build-testing.yml | 25 -------------- .github/workflows/prerelease-check.yml | 2 -- .../reusable-ros-tooling-source-build.yml | 2 +- README.md | 1 - ros2_controllers-not-released.galactic.repos | 6 ---- ros2_controllers.galactic.repos | 13 -------- 13 files changed, 1 insertion(+), 188 deletions(-) delete mode 100644 .github/workflows/galactic-abi-compatibility.yml delete mode 100644 .github/workflows/galactic-binary-build-main.yml delete mode 100644 .github/workflows/galactic-binary-build-testing.yml delete mode 100644 .github/workflows/galactic-rhel-binary-build.yml delete mode 100644 .github/workflows/galactic-semi-binary-build-main.yml delete mode 100644 .github/workflows/galactic-semi-binary-build-testing.yml delete mode 100644 ros2_controllers-not-released.galactic.repos delete mode 100644 ros2_controllers.galactic.repos diff --git a/.github/mergify.yml b/.github/mergify.yml index 6bfd4470ac..87490702f6 100644 --- a/.github/mergify.yml +++ b/.github/mergify.yml @@ -1,13 +1,4 @@ pull_request_rules: - - name: Backport to galactic at reviewers discretion - conditions: - - base=master - - "label=backport-galactic" - actions: - backport: - branches: - - galactic - - name: Backport to foxy at reviewers discretion conditions: - base=master diff --git a/.github/workflows/README.md b/.github/workflows/README.md index 34bfb4cc03..5789859350 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -4,7 +4,6 @@ ROS2 Distro | Branch | Build status | Documentation | Released packages :---------: | :----: | :----------: | :-----------: | :---------------: **Rolling** | [`rolling`](https://github.com/ros-controls/ros2_controllers/tree/rolling) | [![Rolling Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-binary-build-main.yml?branch=master)
[![Rolling Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-binary-build-testing.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-binary-build-testing.yml?branch=master)
[![Rolling Semi-Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-semi-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-semi-binary-build-main.yml?branch=master)
[![Rolling Semi-Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-semi-binary-build-testing.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-semi-binary-build-testing.yml?branch=master)
[![Rolling Source Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-source-build.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-source-build.yml?branch=master) | | [ros2_controllers](https://index.ros.org/p/ros2_controllers/#rolling) **Humble** | [`humble`](https://github.com/ros-controls/ros2_controllers/tree/humble) | [![Humble Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-binary-build-main.yml?branch=master)
[![Humble Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-binary-build-testing.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-binary-build-testing.yml?branch=master)
[![Humble Semi-Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-semi-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-semi-binary-build-main.yml?branch=master)
[![Humble Semi-Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-semi-binary-build-testing.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-semi-binary-build-testing.yml?branch=master)
[![Humble Source Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-source-build.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-source-build.yml?branch=master) | | [ros2_controllers](https://index.ros.org/p/ros2_controllers/#humble) -**Galactic** | [`galactic`](https://github.com/ros-controls/ros2_controllers/tree/galactic) | [![Galactic Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/galactic-binary-build-main.yml/badge.svg?branch=galactic)](https://github.com/ros-controls/ros2_controllers/actions/workflows/galactic-binary-build-main.yml?branch=galactic)
[![Galactic Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/galactic-binary-build-testing.yml/badge.svg?branch=galactic)](https://github.com/ros-controls/ros2_controllers/actions/workflows/galactic-binary-build-testing.yml?branch=galactic)
[![Galactic Semi-Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/galactic-semi-binary-build-main.yml/badge.svg?branch=galactic)](https://github.com/ros-controls/ros2_controllers/actions/workflows/galactic-semi-binary-build-main.yml?branch=galactic)
[![Galactic Semi-Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/galactic-semi-binary-build-testing.yml/badge.svg?branch=galactic)](https://github.com/ros-controls/ros2_controllers/actions/workflows/galactic-semi-binary-build-testing.yml?branch=galactic) | | [ros2_controllers](https://index.ros.org/p/ros2_controllers/#galactic) **Foxy** | [`foxy`](https://github.com/ros-controls/ros2_controllers/tree/foxy) | [![Foxy Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/foxy-binary-build-main.yml/badge.svg?branch=foxy)](https://github.com/ros-controls/ros2_controllers/actions/workflows/foxy-binary-build-main.yml?branch=foxy)
[![Foxy Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/foxy-binary-build-testing.yml/badge.svg?branch=foxy)](https://github.com/ros-controls/ros2_controllers/actions/workflows/foxy-binary-build-testing.yml?branch=foxy)
[![Foxy Semi-Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/foxy-semi-binary-build-main.yml/badge.svg?branch=foxy)](https://github.com/ros-controls/ros2_controllers/actions/workflows/foxy-semi-binary-build-main.yml?branch=foxy)
[![Foxy Semi-Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/foxy-semi-binary-build-testing.yml/badge.svg?branch=foxy)](https://github.com/ros-controls/ros2_controllers/actions/workflows/foxy-semi-binary-build-testing.yml?branch=foxy) | | [ros2_controllers](https://index.ros.org/p/ros2_controllers/#foxy) diff --git a/.github/workflows/galactic-abi-compatibility.yml b/.github/workflows/galactic-abi-compatibility.yml deleted file mode 100644 index 06a48ef9c7..0000000000 --- a/.github/workflows/galactic-abi-compatibility.yml +++ /dev/null @@ -1,20 +0,0 @@ -name: Galactic - ABI Compatibility Check -on: - workflow_dispatch: - branches: - - galactic - pull_request: - branches: - - galactic - -jobs: - abi_check: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: ros-industrial/industrial_ci@master - env: - ROS_DISTRO: galactic - ROS_REPO: main - ABICHECK_URL: github:${{ github.repository }}#${{ github.base_ref }} - NOT_TEST_BUILD: true diff --git a/.github/workflows/galactic-binary-build-main.yml b/.github/workflows/galactic-binary-build-main.yml deleted file mode 100644 index 14fe56407c..0000000000 --- a/.github/workflows/galactic-binary-build-main.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: Galactic Binary Build - main -# author: Denis Štogl -# description: 'Build & test all dependencies from released (binary) packages.' - -on: - workflow_dispatch: - branches: - - galactic - pull_request: - branches: - - galactic - push: - branches: - - galactic - schedule: - # Run every morning to detect flakiness and broken dependencies - - cron: '03 1 * * *' - -jobs: - binary: - uses: ./.github/workflows/reusable-industrial-ci-with-cache.yml - with: - ros_distro: galactic - ros_repo: main - upstream_workspace: ros2_controllers-not-released.galactic.repos - ref_for_scheduled_build: galactic diff --git a/.github/workflows/galactic-binary-build-testing.yml b/.github/workflows/galactic-binary-build-testing.yml deleted file mode 100644 index c4b22a3a7a..0000000000 --- a/.github/workflows/galactic-binary-build-testing.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: Galactic Binary Build - testing -# author: Denis Štogl -# description: 'Build & test all dependencies from released (binary) packages.' - -on: - workflow_dispatch: - branches: - - galactic - pull_request: - branches: - - galactic - push: - branches: - - galactic - schedule: - # Run every morning to detect flakiness and broken dependencies - - cron: '03 1 * * *' - -jobs: - binary: - uses: ./.github/workflows/reusable-industrial-ci-with-cache.yml - with: - ros_distro: galactic - ros_repo: testing - upstream_workspace: ros2_controllers-not-released.galactic.repos - ref_for_scheduled_build: galactic diff --git a/.github/workflows/galactic-rhel-binary-build.yml b/.github/workflows/galactic-rhel-binary-build.yml deleted file mode 100644 index 518fcc186a..0000000000 --- a/.github/workflows/galactic-rhel-binary-build.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: Galactic RHEL Binary Build -on: - workflow_dispatch: - branches: - - galactic - pull_request: - branches: - - galactic - push: - branches: - - galactic - schedule: - # Run every day to detect flakiness and broken dependencies - - cron: '03 1 * * *' - - -jobs: - galactic_rhel_binary: - name: Galactic RHEL binary build - runs-on: ubuntu-latest - env: - ROS_DISTRO: galactic - container: ghcr.io/ros-controls/ros:galactic-rhel - steps: - - uses: actions/checkout@v3 - with: - path: src/ros2_controllers - - run: | - rosdep update - rosdep install -iy --from-path src/ros2_controllers - source /opt/ros/${{ env.ROS_DISTRO }}/setup.bash - colcon build - colcon test diff --git a/.github/workflows/galactic-semi-binary-build-main.yml b/.github/workflows/galactic-semi-binary-build-main.yml deleted file mode 100644 index 7e498679cb..0000000000 --- a/.github/workflows/galactic-semi-binary-build-main.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: Galactic Semi-Binary Build - main -# description: 'Build & test that compiles the main dependencies from source.' - -on: - workflow_dispatch: - branches: - - galactic - pull_request: - branches: - - galactic - push: - branches: - - galactic - schedule: - # Run every morning to detect flakiness and broken dependencies - - cron: '33 1 * * *' - -jobs: - semi_binary: - uses: ./.github/workflows/reusable-industrial-ci-with-cache.yml - with: - ros_distro: galactic - ros_repo: main - upstream_workspace: ros2_controllers.galactic.repos - ref_for_scheduled_build: galactic diff --git a/.github/workflows/galactic-semi-binary-build-testing.yml b/.github/workflows/galactic-semi-binary-build-testing.yml deleted file mode 100644 index 82a74a358b..0000000000 --- a/.github/workflows/galactic-semi-binary-build-testing.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: Galactic Semi-Binary Build - testing -# description: 'Build & test that compiles the main dependencies from source.' - -on: - workflow_dispatch: - branches: - - galactic - pull_request: - branches: - - galactic - push: - branches: - - galactic - schedule: - # Run every morning to detect flakiness and broken dependencies - - cron: '33 1 * * *' - -jobs: - semi_binary: - uses: ./.github/workflows/reusable-industrial-ci-with-cache.yml - with: - ros_distro: galactic - ros_repo: testing - upstream_workspace: ros2_controllers.galactic.repos - ref_for_scheduled_build: galactic diff --git a/.github/workflows/prerelease-check.yml b/.github/workflows/prerelease-check.yml index b9460bda47..acbb42e16b 100644 --- a/.github/workflows/prerelease-check.yml +++ b/.github/workflows/prerelease-check.yml @@ -10,7 +10,6 @@ on: type: choice options: - foxy - - galactic - humble - rolling branch: @@ -20,7 +19,6 @@ on: type: choice options: - foxy - - galactic - humble - master diff --git a/.github/workflows/reusable-ros-tooling-source-build.yml b/.github/workflows/reusable-ros-tooling-source-build.yml index 51519dfb2c..31bc0d4475 100644 --- a/.github/workflows/reusable-ros-tooling-source-build.yml +++ b/.github/workflows/reusable-ros-tooling-source-build.yml @@ -14,7 +14,7 @@ on: required: true type: string ros2_repo_branch: - description: 'Branch in the ros2/ros2 repozitory from which ".repos" should be used. Possible values: master (Rolling), humble, galactic, foxy.' + description: 'Branch in the ros2/ros2 repozitory from which ".repos" should be used. Possible values: master (Rolling), humble, foxy.' default: 'master' required: false type: string diff --git a/README.md b/README.md index 6a59d0054e..d7986d34c6 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,6 @@ ROS2 Distro | Branch | Build status | Documentation | Released packages :---------: | :----: | :----------: | :-----------: | :---------------: **Rolling** | [`rolling`](https://github.com/ros-controls/ros2_controllers/tree/rolling) | [![Rolling Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-binary-build-main.yml?branch=master)
[![Rolling Semi-Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-semi-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-semi-binary-build-main.yml?branch=master) | | [ros2_controllers](https://index.ros.org/p/ros2_controllers/#rolling) **Humble** | [`humble`](https://github.com/ros-controls/ros2_controllers/tree/humble) | [![Humble Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-binary-build-main.yml?branch=master)
[![Humble Semi-Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-semi-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-semi-binary-build-main.yml?branch=master) | | [ros2_controllers](https://index.ros.org/p/ros2_controllers/#humble) -**Galactic** | [`galactic`](https://github.com/ros-controls/ros2_controllers/tree/galactic) | [![Galactic Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/galactic-binary-build-main.yml/badge.svg?branch=galactic)](https://github.com/ros-controls/ros2_controllers/actions/workflows/galactic-binary-build-main.yml?branch=galactic)
[![Galactic Semi-Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/galactic-semi-binary-build-main.yml/badge.svg?branch=galactic)](https://github.com/ros-controls/ros2_controllers/actions/workflows/galactic-semi-binary-build-main.yml?branch=galactic) | | [ros2_controllers](https://index.ros.org/p/ros2_controllers/#galactic) **Foxy** | [`foxy`](https://github.com/ros-controls/ros2_controllers/tree/foxy) | [![Foxy Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/foxy-binary-build-main.yml/badge.svg?branch=foxy)](https://github.com/ros-controls/ros2_controllers/actions/workflows/foxy-binary-build-main.yml?branch=foxy)
[![Foxy Semi-Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/foxy-semi-binary-build-main.yml/badge.svg?branch=foxy)](https://github.com/ros-controls/ros2_controllers/actions/workflows/foxy-semi-binary-build-main.yml?branch=foxy) | | [ros2_controllers](https://index.ros.org/p/ros2_controllers/#foxy) ### Explanation of different build types diff --git a/ros2_controllers-not-released.galactic.repos b/ros2_controllers-not-released.galactic.repos deleted file mode 100644 index 1b3910e7e7..0000000000 --- a/ros2_controllers-not-released.galactic.repos +++ /dev/null @@ -1,6 +0,0 @@ -repositories: - ## EXAMPLE DEPENDENCY -# : -# type: git -# url: git@github.com:/.git -# version: master diff --git a/ros2_controllers.galactic.repos b/ros2_controllers.galactic.repos deleted file mode 100644 index b9b8674fc9..0000000000 --- a/ros2_controllers.galactic.repos +++ /dev/null @@ -1,13 +0,0 @@ -repositories: - ros-controls/ros2_control: - type: git - url: https://github.com/ros-controls/ros2_control.git - version: galactic - control_msgs: - type: git - url: https://github.com/ros-controls/control_msgs.git - version: foxy-devel - realtime_tools: - type: git - url: https://github.com/ros-controls/realtime_tools.git - version: foxy-devel From 546422d8639082fea5d224511505e281e8566ecf Mon Sep 17 00:00:00 2001 From: Alex Moriarty Date: Sun, 7 May 2023 17:46:38 -0300 Subject: [PATCH 020/238] switch from dash to underscore in setup.cfg (#595) This fixes the warning which was introduced here: https://github.com/pypa/setuptools/commit/a2e9ae4cb Signed-off-by: Alex Moriarty --- rqt_joint_trajectory_controller/setup.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rqt_joint_trajectory_controller/setup.cfg b/rqt_joint_trajectory_controller/setup.cfg index 4c0b982e25..59deadec31 100644 --- a/rqt_joint_trajectory_controller/setup.cfg +++ b/rqt_joint_trajectory_controller/setup.cfg @@ -1,4 +1,4 @@ [develop] -script-dir=$base/lib/rqt_joint_trajectory_controller +script_dir=$base/lib/rqt_joint_trajectory_controller [install] -install-scripts=$base/lib/rqt_joint_trajectory_controller +install_scripts=$base/lib/rqt_joint_trajectory_controller From 6851df137cf2118d1a7166921d34eb759c225526 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Tue, 9 May 2023 19:02:17 +0200 Subject: [PATCH 021/238] [JTC] Import docs from wiki.ros.org (#566) * Remove trajectory replacement doc from this PR Co-authored-by: Dr. Denis --- joint_trajectory_controller/doc/userdoc.rst | 180 +++++++++++++------- 1 file changed, 121 insertions(+), 59 deletions(-) diff --git a/joint_trajectory_controller/doc/userdoc.rst b/joint_trajectory_controller/doc/userdoc.rst index 1ba6257a5a..6494d7116a 100644 --- a/joint_trajectory_controller/doc/userdoc.rst +++ b/joint_trajectory_controller/doc/userdoc.rst @@ -3,12 +3,22 @@ joint_trajectory_controller =========================== -Controller for executing joint-space trajectories on a group of joints. Trajectories are specified as a set of waypoints to be reached at specific time instants, which the controller attempts to execute as well as the mechanism allows. Waypoints consist of positions, and optionally velocities and accelerations. +Controller for executing joint-space trajectories on a group of joints. +The controller interpolates in time between the points so that their distance can be arbitrary. +Even trajectories with only one point are accepted. +Trajectories are specified as a set of waypoints to be reached at specific time instants, +which the controller attempts to execute as well as the mechanism allows. +Waypoints consist of positions, and optionally velocities and accelerations. -Trajectory representation -------------------------- -The controller is templated to work with multiple trajectory representations. By default, a spline interpolator is provided, but it's possible to support other representations. The spline interpolator uses the following interpolation strategies depending on the waypoint specification: +*Parts of this documentation were originally published in the ROS 1 wiki under the* `CC BY 3.0 license `_. *Citations are given in the respective section, but were adapted for the ROS 2 implementation.* [#f1]_ [#f2]_ + +Trajectory representation [#f1]_ +--------------------------------- + +Trajectories are represented internally with ``trajectory_msgs/msg/JointTrajectory`` data structure. +By default, a spline interpolator is provided, but it's possible to support other representations. +The spline interpolator uses the following interpolation strategies depending on the waypoint specification: * Linear: Only position is specified. Guarantees continuity at the position level. Discouraged because it yields trajectories with discontinuous velocities at the waypoints. @@ -16,10 +26,27 @@ The controller is templated to work with multiple trajectory representations. By * Quintic: Position, velocity and acceleration are specified: Guarantees continuity at the acceleration level. -Hardware interface type ------------------------ +Hardware interface type [#f1]_ +------------------------------- + +Currently joints with position, velocity, acceleration, and effort interfaces are supported. The joints can have one or more command interfaces, where the following control laws are applied at the same time: + +* For command interfaces ``position``, the desired positions are simply forwarded to the joints, +* For command interfaces ``acceleration``, desired accelerations are simply forwarded to the joints. +* For ``velocity`` (``effort``) command interfaces, the position+velocity trajectory following error is mapped to ``velocity`` (``effort``) commands through a PID loop (:ref:`parameters`). + +This leads to the the following allowed combinations of command and state interfaces: -The controller is templated to work with multiple hardware interface types. Currently joints with position, velocity and effort interfaces are supported. For position-controlled joints, desired positions are simply forwarded to the joints; while for velocity (effort) joints, the position+velocity trajectory following error is mapped to velocity (effort) commands through a PID loop. Example controller configurations can be found here. +* With command interface ``position``, there are no restrictions for state interfaces. +* With command interface ``velocity``: + + * if command interface ``velocity`` is the only one, state interfaces must include ``position, velocity`` . + * no restrictions otherwise. + +* With command interface ``effort``, state interfaces must include ``position, velocity``. +* With command interface ``acceleration``, there are no restrictions for state interfaces. + +Example controller configurations can be found :ref:`below `. Similarly to the trajectory representation case above, it's possible to support new hardware interfaces, or alternative mappings to an already supported interface (eg. a proxy controller for generating effort commands). @@ -32,27 +59,6 @@ Other features * Robust to system clock changes: Discontinuous system clock changes do not cause discontinuities in the execution of already queued trajectory segments. -ros2_control interfaces ------------------------- - -References -^^^^^^^^^^^ -(the controller is not yet implemented as chainable controller) - -States -^^^^^^^ -The state interfaces are defined with ``joints`` and ``state_interfaces`` parameters as follows: ``/``. -Supported state interfaces are ``position``, ``velocity``, ``acceleration`` and ``effort`` as defined in the `hardware_interface/hardware_interface_type_values.hpp `_. -Legal combinations of state interfaces are: - -* ``position`` -* ``position`` and ``velocity`` -* ``position``, ``velocity`` and ``acceleration`` -* ``effort`` - -Commands -^^^^^^^^^ - Using Joint Trajectory Controller(s) ------------------------------------ @@ -101,6 +107,17 @@ A yaml file for using it could be: goal: 0.03 +Preemption policy [#f1]_ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Only one action goal can be active at any moment, or none if the topic interface is used. Path and goal tolerances are checked only for the trajectory segments of the active goal. + +When an active action goal is preempted by another command coming from the action interface, the goal is canceled and the client is notified. + +Sending an empty trajectory message from the topic interface (not the action interface) will override the current action goal and not abort the action. + +.. _parameters: + Details about parameters ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -143,8 +160,9 @@ interpolation_method (string) open_loop_control (boolean) Use controller in open-loop control mode: - + The controller ignores the states provided by hardware interface but using last commands as states for starting the trajectory interpolation. - + It deactivates the feedback control, see the ``gains`` structure. + + * The controller ignores the states provided by hardware interface but using last commands as states for starting the trajectory interpolation. + * It deactivates the feedback control, see the ``gains`` structure. This is useful if hardware states are not following commands, i.e., an offset between those (typical for hydraulic manipulators). @@ -224,17 +242,79 @@ gains..normalize_error (bool) Default: false -ROS2 interface of the controller -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -~/joint_trajectory (input topic) [trajectory_msgs::msg::JointTrajectory] - Topic for commanding the controller. +.. _ROS 2 interface: -~/controller_state (output topic) [control_msgs::msg::JointTrajectoryControllerState] - Topic publishing internal states with the update-rate of the controller manager. +Description of controller's interfaces +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -~/follow_joint_trajectory (action server) [control_msgs::action::FollowJointTrajectory] - Action server for commanding the controller. +References +,,,,,,,,,,,,,,,,,, + +(the controller is not yet implemented as chainable controller) + +States +,,,,,,,,,,,,,,,,,, + +The state interfaces are defined with ``joints`` and ``state_interfaces`` parameters as follows: ``/``. +Supported state interfaces are ``position``, ``velocity``, ``acceleration`` and ``effort`` as defined in the `hardware_interface/hardware_interface_type_values.hpp `_. + +Legal combinations of state interfaces are: + +* ``position`` +* ``position`` and ``velocity`` +* ``position``, ``velocity`` and ``acceleration`` +* ``effort`` + +Commands +,,,,,,,,, + +There are two mechanisms for sending trajectories to the controller: + +* via action, see :ref:`actions ` +* via topic, see :ref:`subscriber ` + +Both use the ``trajectory_msgs/JointTrajectory`` message to specify trajectories, and require specifying values for all the controller joints (as opposed to only a subset) if ``allow_partial_joints_goal`` is not set to ``True``. + +.. _Actions: + +Actions [#f1]_ +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, + +/follow_joint_trajectory [control_msgs::action::FollowJointTrajectory] + Action server for commanding the controller + + +The primary way to send trajectories is through the action interface, and should be favored when execution monitoring is desired. +Action goals allow to specify not only the trajectory to execute, but also (optionally) path and goal tolerances. +When no tolerances are specified, the defaults given in the parameter interface are used (see :ref:`parameters`). +If tolerances are violated during trajectory execution, the action goal is aborted, the client is notified, and the current position is held. + +.. _Subscriber: + +Subscriber [#f1]_ +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, + +/joint_trajectory [trajectory_msgs::msg::JointTrajectory] + Topic for commanding the controller + +The topic interface is a fire-and-forget alternative. Use this interface if you don't care about execution monitoring. +The controller's path and goal tolerance specification is not used in this case, as there is no mechanism to notify the sender about tolerance violations. +Note that although some degree of monitoring is available through the ``~/query_state`` service and ``~/state`` topic it is much more cumbersome to realize than with the action interface. + + +Publishers +,,,,,,,,,,, + +/controller_state [control_msgs::msg::JointTrajectoryControllerState] + Topic publishing internal states with the update-rate of the controller manager + + +Services +,,,,,,,,,,, + +/query_state [control_msgs::srv::QueryTrajectoryState] + Query controller state at any future time Specialized versions of JointTrajectoryController (TBD in ...) @@ -246,26 +326,8 @@ The following version of the Joint Trajectory Controller are available mapping t * position_controllers::JointTrajectoryController - * Input: position, [velocity, [acceleration]] - * Output: position - -* position_velocity_controllers::JointTrajectoryController - - * Input: position, [velocity, [acceleration]] - * Output: position and velocity - -* position_velocity_acceleration_controllers::JointTrajectoryController - - * Input: position, [velocity, [acceleration]] - * Output: position, velocity and acceleration -.. * velocity_controllers::JointTrajectoryController -.. * Input: position, [velocity, [acceleration]] -.. * Output: velocity -.. TODO(anyone): would it be possible to output velocty and acceleration? -.. (to have an vel_acc_controllers) -.. * effort_controllers::JointTrajectoryController -.. * Input: position, [velocity, [acceleration]] -.. * Output: effort +.. rubric:: Footnote -(*Not implemented yet*) When using pure ``velocity`` or ``effort`` controllers a command is generated using the desired state and state error using a velocity feedforward term plus a corrective PID term. (#171) +.. [#f1] Adolfo Rodriguez: `joint_trajectory_controller `_ +.. [#f2] Adolfo Rodriguez: `Understanding trajectory replacement `_ From 83042fbb9e4cfed9c0a06d3dc6bda5d070c8a138 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noel=20Jim=C3=A9nez=20Garc=C3=ADa?= Date: Thu, 11 May 2023 15:37:40 +0200 Subject: [PATCH 022/238] Clear registered handles of DiffDriveController on deactivate (#596) --- diff_drive_controller/src/diff_drive_controller.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/diff_drive_controller/src/diff_drive_controller.cpp b/diff_drive_controller/src/diff_drive_controller.cpp index 22b9acd829..fa12bd8105 100644 --- a/diff_drive_controller/src/diff_drive_controller.cpp +++ b/diff_drive_controller/src/diff_drive_controller.cpp @@ -481,6 +481,13 @@ controller_interface::CallbackReturn DiffDriveController::on_deactivate( const rclcpp_lifecycle::State &) { subscriber_is_active_ = false; + if (!is_halted) + { + halt(); + is_halted = true; + } + registered_left_wheel_handles_.clear(); + registered_right_wheel_handles_.clear(); return controller_interface::CallbackReturn::SUCCESS; } From b94cb58ea94a5616102ee78da07d070af9643f09 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Sun, 14 May 2023 19:49:13 +0100 Subject: [PATCH 023/238] Update changelogs --- admittance_controller/CHANGELOG.rst | 3 +++ diff_drive_controller/CHANGELOG.rst | 5 +++++ effort_controllers/CHANGELOG.rst | 3 +++ force_torque_sensor_broadcaster/CHANGELOG.rst | 3 +++ forward_command_controller/CHANGELOG.rst | 3 +++ gripper_controllers/CHANGELOG.rst | 3 +++ imu_sensor_broadcaster/CHANGELOG.rst | 3 +++ joint_state_broadcaster/CHANGELOG.rst | 3 +++ joint_trajectory_controller/CHANGELOG.rst | 5 +++++ position_controllers/CHANGELOG.rst | 3 +++ ros2_controllers/CHANGELOG.rst | 3 +++ ros2_controllers_test_nodes/CHANGELOG.rst | 3 +++ rqt_joint_trajectory_controller/CHANGELOG.rst | 5 +++++ tricycle_controller/CHANGELOG.rst | 3 +++ velocity_controllers/CHANGELOG.rst | 3 +++ 15 files changed, 51 insertions(+) diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index 63ca4f4c0c..dd22bd8892 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.7.0 (2023-05-02) ------------------ diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index 272656ce20..bbab2ab10d 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Clear registered handles of DiffDriveController on deactivate (`#596 `_) +* Contributors: Noel Jiménez García + 3.7.0 (2023-05-02) ------------------ * Fix wrong publish timestamp initialization (`#585 `_) diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index 767184b5d3..63ec09e4c4 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.7.0 (2023-05-02) ------------------ diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index 672d2b53ca..a17b54b2c0 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.7.0 (2023-05-02) ------------------ diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index bf3b24ab82..b714c9884c 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.7.0 (2023-05-02) ------------------ diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index b7378fa760..40aa2169ff 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.7.0 (2023-05-02) ------------------ diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index 9049c11f6a..445341daab 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.7.0 (2023-05-02) ------------------ diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index 3812d61ac3..c4449185ab 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.7.0 (2023-05-02) ------------------ diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index fbb24978b7..20ec4abe17 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* [JTC] Import docs from wiki.ros.org (`#566 `_) +* Contributors: Christoph Fröhlich + 3.7.0 (2023-05-02) ------------------ * Fix JTC from immediately returning success (`#565 `_) diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index 3b04f3b06f..e19405332b 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.7.0 (2023-05-02) ------------------ diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index 3397d446e8..7b682a1de2 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.7.0 (2023-05-02) ------------------ diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index 69e4765398..8a82c81953 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.7.0 (2023-05-02) ------------------ diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index b9c0b090d0..e3e7d12444 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* switch from dash to underscore in setup.cfg (`#595 `_) +* Contributors: Alex Moriarty + 3.7.0 (2023-05-02) ------------------ diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index bf0c5a0102..9f9b5924e0 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.7.0 (2023-05-02) ------------------ diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index 4d584c209f..9ef655fb17 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.7.0 (2023-05-02) ------------------ From d510cc1af1923956e8da738012ca6677e20697db Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Sun, 14 May 2023 19:49:51 +0100 Subject: [PATCH 024/238] 3.8.0 --- admittance_controller/CHANGELOG.rst | 4 ++-- admittance_controller/package.xml | 2 +- diff_drive_controller/CHANGELOG.rst | 4 ++-- diff_drive_controller/package.xml | 2 +- effort_controllers/CHANGELOG.rst | 4 ++-- effort_controllers/package.xml | 2 +- force_torque_sensor_broadcaster/CHANGELOG.rst | 4 ++-- force_torque_sensor_broadcaster/package.xml | 2 +- forward_command_controller/CHANGELOG.rst | 4 ++-- forward_command_controller/package.xml | 2 +- gripper_controllers/CHANGELOG.rst | 4 ++-- gripper_controllers/package.xml | 2 +- imu_sensor_broadcaster/CHANGELOG.rst | 4 ++-- imu_sensor_broadcaster/package.xml | 2 +- joint_state_broadcaster/CHANGELOG.rst | 4 ++-- joint_state_broadcaster/package.xml | 2 +- joint_trajectory_controller/CHANGELOG.rst | 4 ++-- joint_trajectory_controller/package.xml | 2 +- position_controllers/CHANGELOG.rst | 4 ++-- position_controllers/package.xml | 2 +- ros2_controllers/CHANGELOG.rst | 4 ++-- ros2_controllers/package.xml | 2 +- ros2_controllers_test_nodes/CHANGELOG.rst | 4 ++-- ros2_controllers_test_nodes/package.xml | 2 +- ros2_controllers_test_nodes/setup.py | 2 +- rqt_joint_trajectory_controller/CHANGELOG.rst | 4 ++-- rqt_joint_trajectory_controller/package.xml | 2 +- rqt_joint_trajectory_controller/setup.py | 2 +- tricycle_controller/CHANGELOG.rst | 4 ++-- tricycle_controller/package.xml | 2 +- velocity_controllers/CHANGELOG.rst | 4 ++-- velocity_controllers/package.xml | 2 +- 32 files changed, 47 insertions(+), 47 deletions(-) diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index dd22bd8892..446d92eddc 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.8.0 (2023-05-14) +------------------ 3.7.0 (2023-05-02) ------------------ diff --git a/admittance_controller/package.xml b/admittance_controller/package.xml index 022e8e1353..8246b78bda 100644 --- a/admittance_controller/package.xml +++ b/admittance_controller/package.xml @@ -2,7 +2,7 @@ admittance_controller - 3.7.0 + 3.8.0 Implementation of admittance controllers for different input and output interface. Denis Štogl Bence Magyar diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index bbab2ab10d..7947ff0f1a 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.8.0 (2023-05-14) +------------------ * Clear registered handles of DiffDriveController on deactivate (`#596 `_) * Contributors: Noel Jiménez García diff --git a/diff_drive_controller/package.xml b/diff_drive_controller/package.xml index 0fdbb3a8a5..3fadb63efd 100644 --- a/diff_drive_controller/package.xml +++ b/diff_drive_controller/package.xml @@ -1,7 +1,7 @@ diff_drive_controller - 3.7.0 + 3.8.0 Controller for a differential drive mobile base. Bence Magyar Jordan Palacios diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index 63ec09e4c4..167f7c1efb 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.8.0 (2023-05-14) +------------------ 3.7.0 (2023-05-02) ------------------ diff --git a/effort_controllers/package.xml b/effort_controllers/package.xml index 02fc8594c0..5381859c32 100644 --- a/effort_controllers/package.xml +++ b/effort_controllers/package.xml @@ -1,7 +1,7 @@ effort_controllers - 3.7.0 + 3.8.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index a17b54b2c0..7fd8390321 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.8.0 (2023-05-14) +------------------ 3.7.0 (2023-05-02) ------------------ diff --git a/force_torque_sensor_broadcaster/package.xml b/force_torque_sensor_broadcaster/package.xml index f7ab4d61ab..f6bc61e8e7 100644 --- a/force_torque_sensor_broadcaster/package.xml +++ b/force_torque_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ force_torque_sensor_broadcaster - 3.7.0 + 3.8.0 Controller to publish state of force-torque sensors. Bence Magyar Denis Štogl diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index b714c9884c..39599caf99 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.8.0 (2023-05-14) +------------------ 3.7.0 (2023-05-02) ------------------ diff --git a/forward_command_controller/package.xml b/forward_command_controller/package.xml index 4441a019ab..76a1731fe7 100644 --- a/forward_command_controller/package.xml +++ b/forward_command_controller/package.xml @@ -1,7 +1,7 @@ forward_command_controller - 3.7.0 + 3.8.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index 40aa2169ff..4a054fb361 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.8.0 (2023-05-14) +------------------ 3.7.0 (2023-05-02) ------------------ diff --git a/gripper_controllers/package.xml b/gripper_controllers/package.xml index 4d53c64d7f..0b30330683 100644 --- a/gripper_controllers/package.xml +++ b/gripper_controllers/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> gripper_controllers - 3.7.0 + 3.8.0 The gripper_controllers package Bence Magyar diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index 445341daab..128cc17eda 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.8.0 (2023-05-14) +------------------ 3.7.0 (2023-05-02) ------------------ diff --git a/imu_sensor_broadcaster/package.xml b/imu_sensor_broadcaster/package.xml index b5e9e6c9f8..d8a40cc4c9 100644 --- a/imu_sensor_broadcaster/package.xml +++ b/imu_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ imu_sensor_broadcaster - 3.7.0 + 3.8.0 Controller to publish readings of IMU sensors. Bence Magyar Denis Štogl diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index c4449185ab..b3f65276f6 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.8.0 (2023-05-14) +------------------ 3.7.0 (2023-05-02) ------------------ diff --git a/joint_state_broadcaster/package.xml b/joint_state_broadcaster/package.xml index 5ad73b4ea0..4601434879 100644 --- a/joint_state_broadcaster/package.xml +++ b/joint_state_broadcaster/package.xml @@ -1,7 +1,7 @@ joint_state_broadcaster - 3.7.0 + 3.8.0 Broadcaster to publish joint state Bence Magyar Denis Stogl diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index 20ec4abe17..fa5824cfe1 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.8.0 (2023-05-14) +------------------ * [JTC] Import docs from wiki.ros.org (`#566 `_) * Contributors: Christoph Fröhlich diff --git a/joint_trajectory_controller/package.xml b/joint_trajectory_controller/package.xml index 00cad650c4..74f2dc6a6e 100644 --- a/joint_trajectory_controller/package.xml +++ b/joint_trajectory_controller/package.xml @@ -1,7 +1,7 @@ joint_trajectory_controller - 3.7.0 + 3.8.0 Controller for executing joint-space trajectories on a group of joints Bence Magyar Jordan Palacios diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index e19405332b..cafd1bb4df 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.8.0 (2023-05-14) +------------------ 3.7.0 (2023-05-02) ------------------ diff --git a/position_controllers/package.xml b/position_controllers/package.xml index b1ca3b38b7..b2b635ec6c 100644 --- a/position_controllers/package.xml +++ b/position_controllers/package.xml @@ -1,7 +1,7 @@ position_controllers - 3.7.0 + 3.8.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index 7b682a1de2..7216b78b1d 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.8.0 (2023-05-14) +------------------ 3.7.0 (2023-05-02) ------------------ diff --git a/ros2_controllers/package.xml b/ros2_controllers/package.xml index b2b7fe286c..b2150411d8 100644 --- a/ros2_controllers/package.xml +++ b/ros2_controllers/package.xml @@ -1,7 +1,7 @@ ros2_controllers - 3.7.0 + 3.8.0 Metapackage for ROS2 controllers related packages Bence Magyar Jordan Palacios diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index 8a82c81953..0b5de6cc52 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.8.0 (2023-05-14) +------------------ 3.7.0 (2023-05-02) ------------------ diff --git a/ros2_controllers_test_nodes/package.xml b/ros2_controllers_test_nodes/package.xml index 3fee344465..171eb3e6ef 100644 --- a/ros2_controllers_test_nodes/package.xml +++ b/ros2_controllers_test_nodes/package.xml @@ -2,7 +2,7 @@ ros2_controllers_test_nodes - 3.7.0 + 3.8.0 Demo nodes for showing and testing functionalities of the ros2_control framework. Denis Štogl diff --git a/ros2_controllers_test_nodes/setup.py b/ros2_controllers_test_nodes/setup.py index 3cdf9a76ef..b8be85a628 100644 --- a/ros2_controllers_test_nodes/setup.py +++ b/ros2_controllers_test_nodes/setup.py @@ -20,7 +20,7 @@ setup( name=package_name, - version="3.7.0", + version="3.8.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index e3e7d12444..17ad4218ca 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.8.0 (2023-05-14) +------------------ * switch from dash to underscore in setup.cfg (`#595 `_) * Contributors: Alex Moriarty diff --git a/rqt_joint_trajectory_controller/package.xml b/rqt_joint_trajectory_controller/package.xml index 86196cac41..adf8511b0b 100644 --- a/rqt_joint_trajectory_controller/package.xml +++ b/rqt_joint_trajectory_controller/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> rqt_joint_trajectory_controller - 3.7.0 + 3.8.0 Graphical frontend for interacting with joint_trajectory_controller instances. Bence Magyar diff --git a/rqt_joint_trajectory_controller/setup.py b/rqt_joint_trajectory_controller/setup.py index f04123ec65..0026688db3 100644 --- a/rqt_joint_trajectory_controller/setup.py +++ b/rqt_joint_trajectory_controller/setup.py @@ -7,7 +7,7 @@ setup( name=package_name, - version="3.7.0", + version="3.8.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index 9f9b5924e0..04b28102c6 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.8.0 (2023-05-14) +------------------ 3.7.0 (2023-05-02) ------------------ diff --git a/tricycle_controller/package.xml b/tricycle_controller/package.xml index 83cb39cc7f..b75fc43885 100644 --- a/tricycle_controller/package.xml +++ b/tricycle_controller/package.xml @@ -2,7 +2,7 @@ tricycle_controller - 3.7.0 + 3.8.0 Controller for a tricycle drive mobile base Bence Magyar Tony Najjar diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index 9ef655fb17..178077380a 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.8.0 (2023-05-14) +------------------ 3.7.0 (2023-05-02) ------------------ diff --git a/velocity_controllers/package.xml b/velocity_controllers/package.xml index 4bbf7a2723..5b81d5721f 100644 --- a/velocity_controllers/package.xml +++ b/velocity_controllers/package.xml @@ -1,7 +1,7 @@ velocity_controllers - 3.7.0 + 3.8.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios From 334e4f2ace819c9912ccd4f5e63c342648b25fc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Sun, 14 May 2023 20:53:50 +0200 Subject: [PATCH 025/238] Fix github links on control.ros.org (#604) * Fix github links * Add local github_url for sphinx --- admittance_controller/doc/userdoc.rst | 4 +++- diff_drive_controller/doc/userdoc.rst | 2 ++ doc/controllers_index.rst | 2 ++ doc/writing_new_controller.rst | 2 ++ effort_controllers/doc/userdoc.rst | 2 ++ force_torque_sensor_broadcaster/doc/userdoc.rst | 2 ++ forward_command_controller/doc/userdoc.rst | 2 ++ imu_sensor_broadcaster/doc/userdoc.rst | 2 ++ joint_state_broadcaster/doc/userdoc.rst | 2 ++ joint_trajectory_controller/doc/userdoc.rst | 2 ++ position_controllers/doc/userdoc.rst | 2 ++ tricycle_controller/doc/userdoc.rst | 2 ++ velocity_controllers/doc/userdoc.rst | 2 ++ 13 files changed, 27 insertions(+), 1 deletion(-) diff --git a/admittance_controller/doc/userdoc.rst b/admittance_controller/doc/userdoc.rst index ed2da84ad5..c6a3b91b78 100644 --- a/admittance_controller/doc/userdoc.rst +++ b/admittance_controller/doc/userdoc.rst @@ -1,4 +1,6 @@ -.. _addmittance_controller_userdoc: +:github_url: https://github.com/ros-controls/ros2_controllers/blob/|github_branch|/admittance_controller/doc/userdoc.rst + +.. _admittance_controller_userdoc: Admittance Controller ====================== diff --git a/diff_drive_controller/doc/userdoc.rst b/diff_drive_controller/doc/userdoc.rst index 1ef47bd975..25d2383364 100644 --- a/diff_drive_controller/doc/userdoc.rst +++ b/diff_drive_controller/doc/userdoc.rst @@ -1,3 +1,5 @@ +:github_url: https://github.com/ros-controls/ros2_controllers/blob/|github_branch|/diff_drive_controller/doc/userdoc.rst + .. _diff_drive_controller_userdoc: diff_drive_controller diff --git a/doc/controllers_index.rst b/doc/controllers_index.rst index 1c6b1dbd9e..effe814325 100644 --- a/doc/controllers_index.rst +++ b/doc/controllers_index.rst @@ -1,3 +1,5 @@ +:github_url: https://github.com/ros-controls/ros2_controllers/blob/|github_branch|/doc/controllers_index.rst + .. _controllers: ################# diff --git a/doc/writing_new_controller.rst b/doc/writing_new_controller.rst index dcf577e131..49bd8a11ee 100644 --- a/doc/writing_new_controller.rst +++ b/doc/writing_new_controller.rst @@ -1,3 +1,5 @@ +:github_url: https://github.com/ros-controls/ros2_controllers/blob/|github_branch|/doc/writing_new_controller.rst + .. _writing_new_controllers: Writing a new controller diff --git a/effort_controllers/doc/userdoc.rst b/effort_controllers/doc/userdoc.rst index 000bfcf26c..52539ef795 100644 --- a/effort_controllers/doc/userdoc.rst +++ b/effort_controllers/doc/userdoc.rst @@ -1,3 +1,5 @@ +:github_url: https://github.com/ros-controls/ros2_controllers/blob/|github_branch|/effort_controllers/doc/userdoc.rst + .. _effort_controllers_userdoc: effort_controllers diff --git a/force_torque_sensor_broadcaster/doc/userdoc.rst b/force_torque_sensor_broadcaster/doc/userdoc.rst index de8a1bd7c6..1d7f1ac1b8 100644 --- a/force_torque_sensor_broadcaster/doc/userdoc.rst +++ b/force_torque_sensor_broadcaster/doc/userdoc.rst @@ -1,3 +1,5 @@ +:github_url: https://github.com/ros-controls/ros2_controllers/blob/|github_branch|/force_torque_sensor_broadcaster/doc/userdoc.rst + .. _force_torque_sensor_broadcaster_userdoc: Force Torque Sensor Broadcaster diff --git a/forward_command_controller/doc/userdoc.rst b/forward_command_controller/doc/userdoc.rst index 8292bdc1b3..522d671438 100644 --- a/forward_command_controller/doc/userdoc.rst +++ b/forward_command_controller/doc/userdoc.rst @@ -1,3 +1,5 @@ +:github_url: https://github.com/ros-controls/ros2_controllers/blob/|github_branch|/forward_command_controller/doc/userdoc.rst + .. _forward_command_controller_userdoc: forward_command_controller diff --git a/imu_sensor_broadcaster/doc/userdoc.rst b/imu_sensor_broadcaster/doc/userdoc.rst index 90704c8504..6f4730b17f 100644 --- a/imu_sensor_broadcaster/doc/userdoc.rst +++ b/imu_sensor_broadcaster/doc/userdoc.rst @@ -1,3 +1,5 @@ +:github_url: https://github.com/ros-controls/ros2_controllers/blob/|github_branch|/imu_sensor_broadcaster/doc/userdoc.rst + .. _imu_sensor_broadcaster_userdoc: IMU Sensor Broadcaster diff --git a/joint_state_broadcaster/doc/userdoc.rst b/joint_state_broadcaster/doc/userdoc.rst index fbdb439992..f809a5b49a 100644 --- a/joint_state_broadcaster/doc/userdoc.rst +++ b/joint_state_broadcaster/doc/userdoc.rst @@ -1,3 +1,5 @@ +:github_url: https://github.com/ros-controls/ros2_controllers/blob/|github_branch|/joint_state_broadcaster/doc/userdoc.rst + .. _joint_state_broadcaster_userdoc: joint_state_broadcaster diff --git a/joint_trajectory_controller/doc/userdoc.rst b/joint_trajectory_controller/doc/userdoc.rst index 6494d7116a..63cf0e5b8f 100644 --- a/joint_trajectory_controller/doc/userdoc.rst +++ b/joint_trajectory_controller/doc/userdoc.rst @@ -1,3 +1,5 @@ +:github_url: https://github.com/ros-controls/ros2_controllers/blob/|github_branch|/joint_trajectory_controller/doc/userdoc.rst + .. _joint_trajectory_controller_userdoc: joint_trajectory_controller diff --git a/position_controllers/doc/userdoc.rst b/position_controllers/doc/userdoc.rst index 1e5dd53e63..69557209ae 100644 --- a/position_controllers/doc/userdoc.rst +++ b/position_controllers/doc/userdoc.rst @@ -1,3 +1,5 @@ +:github_url: https://github.com/ros-controls/ros2_controllers/blob/|github_branch|/position_controllers/doc/userdoc.rst + .. _position_controllers_userdoc: position_controllers diff --git a/tricycle_controller/doc/userdoc.rst b/tricycle_controller/doc/userdoc.rst index a248bbec96..9dd46cc79a 100644 --- a/tricycle_controller/doc/userdoc.rst +++ b/tricycle_controller/doc/userdoc.rst @@ -1,3 +1,5 @@ +:github_url: https://github.com/ros-controls/ros2_controllers/blob/|github_branch|/tricycle_controller/doc/userdoc.rst + .. _tricycle_controller_userdoc: tricycle_controller diff --git a/velocity_controllers/doc/userdoc.rst b/velocity_controllers/doc/userdoc.rst index 62b6aa019f..56fdde5220 100644 --- a/velocity_controllers/doc/userdoc.rst +++ b/velocity_controllers/doc/userdoc.rst @@ -1,3 +1,5 @@ +:github_url: https://github.com/ros-controls/ros2_controllers/blob/|github_branch|/velocity_controllers/doc/userdoc.rst + .. _velocity_controllers_userdoc: velocity_controllers From 05d7a5ec73a02eab2cab5943c2d32e95889e73ef Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 May 2023 09:03:22 +0200 Subject: [PATCH 026/238] Bump codecov/codecov-action from 3.1.3 to 3.1.4 (#615) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 3.1.3 to 3.1.4. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v3.1.3...v3.1.4) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-coverage-build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-coverage-build.yml b/.github/workflows/ci-coverage-build.yml index 6e6e96f032..27528e4e16 100644 --- a/.github/workflows/ci-coverage-build.yml +++ b/.github/workflows/ci-coverage-build.yml @@ -37,7 +37,7 @@ jobs: } } colcon-mixin-repository: https://raw.githubusercontent.com/colcon/colcon-mixin-repository/master/index.yaml - - uses: codecov/codecov-action@v3.1.3 + - uses: codecov/codecov-action@v3.1.4 with: file: ros_ws/lcov/total_coverage.info flags: unittests From 372725edeaba9a77553ee57ce57f8c1d245c837d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Mon, 22 May 2023 21:47:47 +0200 Subject: [PATCH 027/238] [JTC] Fix deprecated header (#610) * [JTC] Renovate action tests (#603) * Fix deprecation of qos_event.hpp --- .../src/joint_state_broadcaster.cpp | 2 +- joint_trajectory_controller/CMakeLists.txt | 13 +++++------ .../src/joint_trajectory_controller.cpp | 2 +- .../test/test_trajectory_actions.cpp | 22 ++++++++----------- .../test/test_trajectory_controller.cpp | 2 +- 5 files changed, 18 insertions(+), 23 deletions(-) diff --git a/joint_state_broadcaster/src/joint_state_broadcaster.cpp b/joint_state_broadcaster/src/joint_state_broadcaster.cpp index 74a19c9ed0..3c2192d40e 100644 --- a/joint_state_broadcaster/src/joint_state_broadcaster.cpp +++ b/joint_state_broadcaster/src/joint_state_broadcaster.cpp @@ -24,8 +24,8 @@ #include "hardware_interface/types/hardware_interface_return_values.hpp" #include "hardware_interface/types/hardware_interface_type_values.hpp" #include "rclcpp/clock.hpp" +#include "rclcpp/event_handler.hpp" #include "rclcpp/qos.hpp" -#include "rclcpp/qos_event.hpp" #include "rclcpp/time.hpp" #include "rclcpp_lifecycle/lifecycle_node.hpp" #include "rcpputils/split.hpp" diff --git a/joint_trajectory_controller/CMakeLists.txt b/joint_trajectory_controller/CMakeLists.txt index 5ec478d989..615acf0dd7 100644 --- a/joint_trajectory_controller/CMakeLists.txt +++ b/joint_trajectory_controller/CMakeLists.txt @@ -80,13 +80,12 @@ if(BUILD_TESTING) ros2_control_test_assets ) - # TODO(andyz): Disabled due to flakiness - # ament_add_gmock(test_trajectory_actions - # test/test_trajectory_actions.cpp - # ) - # target_link_libraries(test_trajectory_actions - # joint_trajectory_controller - # ) + ament_add_gmock(test_trajectory_actions + test/test_trajectory_actions.cpp + ) + target_link_libraries(test_trajectory_actions + joint_trajectory_controller + ) endif() diff --git a/joint_trajectory_controller/src/joint_trajectory_controller.cpp b/joint_trajectory_controller/src/joint_trajectory_controller.cpp index 07080bb1fc..71ed051f66 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller.cpp +++ b/joint_trajectory_controller/src/joint_trajectory_controller.cpp @@ -31,10 +31,10 @@ #include "hardware_interface/types/hardware_interface_type_values.hpp" #include "joint_trajectory_controller/trajectory.hpp" #include "lifecycle_msgs/msg/state.hpp" +#include "rclcpp/event_handler.hpp" #include "rclcpp/logging.hpp" #include "rclcpp/parameter.hpp" #include "rclcpp/qos.hpp" -#include "rclcpp/qos_event.hpp" #include "rclcpp/time.hpp" #include "rclcpp_action/create_server.hpp" #include "rclcpp_action/server_goal_handle.hpp" diff --git a/joint_trajectory_controller/test/test_trajectory_actions.cpp b/joint_trajectory_controller/test/test_trajectory_actions.cpp index 10dd3a6b90..ef0a11d961 100644 --- a/joint_trajectory_controller/test/test_trajectory_actions.cpp +++ b/joint_trajectory_controller/test/test_trajectory_actions.cpp @@ -70,17 +70,13 @@ class TestTrajectoryActions : public TrajectoryControllerTest { setup_executor_ = true; - executor_ = std::make_unique(); - - SetUpAndActivateTrajectoryController(true, parameters); - - executor_->add_node(traj_controller_->get_node()->get_node_base_interface()); + SetUpAndActivateTrajectoryController(executor_, true, parameters); SetUpActionClient(); - executor_->add_node(node_->get_node_base_interface()); + executor_.add_node(node_->get_node_base_interface()); - executor_future_handle_ = std::async(std::launch::async, [&]() -> void { executor_->spin(); }); + executor_future_handle_ = std::async(std::launch::async, [&]() -> void { executor_.spin(); }); } void SetUpControllerHardware() @@ -132,7 +128,7 @@ class TestTrajectoryActions : public TrajectoryControllerTest if (setup_executor_) { setup_executor_ = false; - executor_->cancel(); + executor_.cancel(); executor_future_handle_.wait(); } } @@ -169,7 +165,7 @@ class TestTrajectoryActions : public TrajectoryControllerTest int common_action_result_code_ = control_msgs::action::FollowJointTrajectory_Result::SUCCESSFUL; bool setup_executor_ = false; - rclcpp::executors::MultiThreadedExecutor::UniquePtr executor_; + rclcpp::executors::MultiThreadedExecutor executor_; std::future executor_future_handle_; bool setup_controller_hw_ = false; @@ -417,7 +413,7 @@ TEST_F(TestTrajectoryActions, test_state_tolerances_fail) common_action_result_code_); // run an update, it should be holding - traj_controller_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)); + updateController(rclcpp::Duration::from_seconds(0.01)); EXPECT_NEAR(INITIAL_POS_JOINT1, joint_pos_[0], COMMON_THRESHOLD); EXPECT_NEAR(INITIAL_POS_JOINT2, joint_pos_[1], COMMON_THRESHOLD); @@ -467,7 +463,7 @@ TEST_F(TestTrajectoryActions, test_goal_tolerances_fail) common_action_result_code_); // run an update, it should be holding - traj_controller_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)); + updateController(rclcpp::Duration::from_seconds(0.01)); EXPECT_NEAR(init_pos1, joint_pos_[0], COMMON_THRESHOLD); EXPECT_NEAR(init_pos2, joint_pos_[1], COMMON_THRESHOLD); @@ -514,7 +510,7 @@ TEST_F(TestTrajectoryActions, test_no_time_from_start_state_tolerance_fail) common_action_result_code_); // run an update, it should be holding - traj_controller_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)); + updateController(rclcpp::Duration::from_seconds(0.01)); EXPECT_NEAR(init_pos1, joint_pos_[0], COMMON_THRESHOLD); EXPECT_NEAR(init_pos2, joint_pos_[1], COMMON_THRESHOLD); @@ -563,7 +559,7 @@ TEST_F(TestTrajectoryActions, test_cancel_hold_position) const double prev_pos3 = joint_pos_[2]; // run an update, it should be holding - traj_controller_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)); + updateController(rclcpp::Duration::from_seconds(0.01)); EXPECT_EQ(prev_pos1, joint_pos_[0]); EXPECT_EQ(prev_pos2, joint_pos_[1]); diff --git a/joint_trajectory_controller/test/test_trajectory_controller.cpp b/joint_trajectory_controller/test/test_trajectory_controller.cpp index e8073086dc..74c17dd03d 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller.cpp +++ b/joint_trajectory_controller/test/test_trajectory_controller.cpp @@ -35,13 +35,13 @@ #include "lifecycle_msgs/msg/state.hpp" #include "rclcpp/clock.hpp" #include "rclcpp/duration.hpp" +#include "rclcpp/event_handler.hpp" #include "rclcpp/executors/multi_threaded_executor.hpp" #include "rclcpp/executors/single_threaded_executor.hpp" #include "rclcpp/node.hpp" #include "rclcpp/parameter.hpp" #include "rclcpp/publisher.hpp" #include "rclcpp/qos.hpp" -#include "rclcpp/qos_event.hpp" #include "rclcpp/subscription.hpp" #include "rclcpp/time.hpp" #include "rclcpp/utilities.hpp" From 70e282f7434cf2e3683c233fe8080720c96b3cf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noel=20Jim=C3=A9nez=20Garc=C3=ADa?= Date: Thu, 25 May 2023 19:46:43 +0200 Subject: [PATCH 028/238] Fix compilation warnings (#621) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * catch exception by reference * Enforce internal linkage for classes in test_gripper_controllers.hpp To avoid problems with HW_IF_POSITION (-Wsubobject-linkage) --------- Co-authored-by: Mathias Lüdtke --- diff_drive_controller/src/diff_drive_controller.cpp | 2 +- gripper_controllers/test/test_gripper_controllers.hpp | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/diff_drive_controller/src/diff_drive_controller.cpp b/diff_drive_controller/src/diff_drive_controller.cpp index fa12bd8105..abefd4307f 100644 --- a/diff_drive_controller/src/diff_drive_controller.cpp +++ b/diff_drive_controller/src/diff_drive_controller.cpp @@ -194,7 +194,7 @@ controller_interface::return_type DiffDriveController::update( should_publish = true; } } - catch (const std::runtime_error) + catch (const std::runtime_error &) { // Handle exceptions when the time source changes and initialize publish timestamp previous_publish_timestamp_ = time; diff --git a/gripper_controllers/test/test_gripper_controllers.hpp b/gripper_controllers/test/test_gripper_controllers.hpp index 3e9750a603..350e551cb8 100644 --- a/gripper_controllers/test/test_gripper_controllers.hpp +++ b/gripper_controllers/test/test_gripper_controllers.hpp @@ -30,6 +30,9 @@ using hardware_interface::HW_IF_POSITION; using hardware_interface::HW_IF_VELOCITY; using hardware_interface::StateInterface; +namespace +{ + // subclassing and friending so we can access member variables class FriendGripperController : public gripper_action_controller::GripperActionController @@ -62,4 +65,6 @@ class GripperControllerTest : public ::testing::Test CommandInterface joint_1_pos_cmd_{joint_name_, HW_IF_POSITION, &joint_commands_[0]}; }; +} // anonymous namespace + #endif // TEST_GRIPPER_CONTROLLERS_HPP_ From 45d008321fe593db0e7f68921baa326b25c38daa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomislav=20Petkovi=C4=87?= <51706321+petkovich@users.noreply.github.com> Date: Fri, 26 May 2023 23:34:42 +0200 Subject: [PATCH 029/238] Steering odometry library and controllers (#484) --- .pre-commit-config.yaml | 2 +- ackermann_steering_controller/CMakeLists.txt | 107 ++++ .../ackermann_steering_controller.xml | 8 + ackermann_steering_controller/doc/userdoc.rst | 18 + .../ackermann_steering_controller.hpp | 65 ++ .../visibility_control.h | 52 ++ ackermann_steering_controller/package.xml | 36 ++ .../src/ackermann_steering_controller.cpp | 98 +++ .../src/ackermann_steering_controller.yaml | 40 ++ .../ackermann_steering_controller_params.yaml | 17 + ...steering_controller_preceeding_params.yaml | 17 + .../test_ackermann_steering_controller.cpp | 292 +++++++++ .../test_ackermann_steering_controller.hpp | 319 ++++++++++ ...kermann_steering_controller_preceeding.cpp | 107 ++++ ...est_load_ackermann_steering_controller.cpp | 49 ++ bicycle_steering_controller/CMakeLists.txt | 105 ++++ .../bicycle_steering_controller.xml | 8 + bicycle_steering_controller/doc/userdoc.rst | 19 + .../bicycle_steering_controller.hpp | 61 ++ .../visibility_control.h | 52 ++ bicycle_steering_controller/package.xml | 36 ++ .../src/bicycle_steering_controller.cpp | 87 +++ .../src/bicycle_steering_controller.yaml | 24 + .../bicycle_steering_controller_params.yaml | 15 + ...steering_controller_preceeding_params.yaml | 16 + .../test/test_bicycle_steering_controller.cpp | 266 +++++++++ .../test/test_bicycle_steering_controller.hpp | 284 +++++++++ ...bicycle_steering_controller_preceeding.cpp | 95 +++ .../test_load_bicycle_steering_controller.cpp | 48 ++ doc/controllers_index.rst | 5 + ros2_controllers/package.xml | 4 + steering_controllers_library/CMakeLists.txt | 88 +++ steering_controllers_library/doc/userdoc.rst | 90 +++ .../steering_controllers_library.hpp | 151 +++++ .../steering_odometry.hpp | 261 ++++++++ .../visibility_control.h | 50 ++ steering_controllers_library/package.xml | 45 ++ .../src/steering_controllers_library.cpp | 558 ++++++++++++++++++ .../src/steering_controllers_library.yaml | 122 ++++ .../src/steering_odometry.cpp | 333 +++++++++++ .../steering_controllers_library_params.yaml | 17 + .../test_steering_controllers_library.cpp | 200 +++++++ .../test_steering_controllers_library.hpp | 341 +++++++++++ tricycle_steering_controller/CMakeLists.txt | 105 ++++ tricycle_steering_controller/doc/userdocs.rst | 18 + .../tricycle_steering_controller.hpp | 63 ++ .../visibility_control.h | 52 ++ tricycle_steering_controller/package.xml | 38 ++ .../src/tricycle_steering_controller.cpp | 93 +++ .../src/tricycle_steering_controller.yaml | 32 + ...test_load_tricycle_steering_controller.cpp | 49 ++ .../test_tricycle_steering_controller.cpp | 274 +++++++++ .../test_tricycle_steering_controller.hpp | 302 ++++++++++ ...ricycle_steering_controller_preceeding.cpp | 100 ++++ .../tricycle_steering_controller_params.yaml | 16 + ...steering_controller_preceeding_params.yaml | 16 + .../tricycle_steering_controller.xml | 8 + 57 files changed, 5773 insertions(+), 1 deletion(-) create mode 100644 ackermann_steering_controller/CMakeLists.txt create mode 100644 ackermann_steering_controller/ackermann_steering_controller.xml create mode 100644 ackermann_steering_controller/doc/userdoc.rst create mode 100644 ackermann_steering_controller/include/ackermann_steering_controller/ackermann_steering_controller.hpp create mode 100644 ackermann_steering_controller/include/ackermann_steering_controller/visibility_control.h create mode 100644 ackermann_steering_controller/package.xml create mode 100644 ackermann_steering_controller/src/ackermann_steering_controller.cpp create mode 100644 ackermann_steering_controller/src/ackermann_steering_controller.yaml create mode 100644 ackermann_steering_controller/test/ackermann_steering_controller_params.yaml create mode 100644 ackermann_steering_controller/test/ackermann_steering_controller_preceeding_params.yaml create mode 100644 ackermann_steering_controller/test/test_ackermann_steering_controller.cpp create mode 100644 ackermann_steering_controller/test/test_ackermann_steering_controller.hpp create mode 100644 ackermann_steering_controller/test/test_ackermann_steering_controller_preceeding.cpp create mode 100644 ackermann_steering_controller/test/test_load_ackermann_steering_controller.cpp create mode 100644 bicycle_steering_controller/CMakeLists.txt create mode 100644 bicycle_steering_controller/bicycle_steering_controller.xml create mode 100644 bicycle_steering_controller/doc/userdoc.rst create mode 100644 bicycle_steering_controller/include/bicycle_steering_controller/bicycle_steering_controller.hpp create mode 100644 bicycle_steering_controller/include/bicycle_steering_controller/visibility_control.h create mode 100644 bicycle_steering_controller/package.xml create mode 100644 bicycle_steering_controller/src/bicycle_steering_controller.cpp create mode 100644 bicycle_steering_controller/src/bicycle_steering_controller.yaml create mode 100644 bicycle_steering_controller/test/bicycle_steering_controller_params.yaml create mode 100644 bicycle_steering_controller/test/bicycle_steering_controller_preceeding_params.yaml create mode 100644 bicycle_steering_controller/test/test_bicycle_steering_controller.cpp create mode 100644 bicycle_steering_controller/test/test_bicycle_steering_controller.hpp create mode 100644 bicycle_steering_controller/test/test_bicycle_steering_controller_preceeding.cpp create mode 100644 bicycle_steering_controller/test/test_load_bicycle_steering_controller.cpp create mode 100644 steering_controllers_library/CMakeLists.txt create mode 100644 steering_controllers_library/doc/userdoc.rst create mode 100644 steering_controllers_library/include/steering_controllers_library/steering_controllers_library.hpp create mode 100644 steering_controllers_library/include/steering_controllers_library/steering_odometry.hpp create mode 100644 steering_controllers_library/include/steering_controllers_library/visibility_control.h create mode 100644 steering_controllers_library/package.xml create mode 100644 steering_controllers_library/src/steering_controllers_library.cpp create mode 100644 steering_controllers_library/src/steering_controllers_library.yaml create mode 100644 steering_controllers_library/src/steering_odometry.cpp create mode 100644 steering_controllers_library/test/steering_controllers_library_params.yaml create mode 100644 steering_controllers_library/test/test_steering_controllers_library.cpp create mode 100644 steering_controllers_library/test/test_steering_controllers_library.hpp create mode 100644 tricycle_steering_controller/CMakeLists.txt create mode 100644 tricycle_steering_controller/doc/userdocs.rst create mode 100644 tricycle_steering_controller/include/tricycle_steering_controller/tricycle_steering_controller.hpp create mode 100644 tricycle_steering_controller/include/tricycle_steering_controller/visibility_control.h create mode 100644 tricycle_steering_controller/package.xml create mode 100644 tricycle_steering_controller/src/tricycle_steering_controller.cpp create mode 100644 tricycle_steering_controller/src/tricycle_steering_controller.yaml create mode 100644 tricycle_steering_controller/test/test_load_tricycle_steering_controller.cpp create mode 100644 tricycle_steering_controller/test/test_tricycle_steering_controller.cpp create mode 100644 tricycle_steering_controller/test/test_tricycle_steering_controller.hpp create mode 100644 tricycle_steering_controller/test/test_tricycle_steering_controller_preceeding.cpp create mode 100644 tricycle_steering_controller/test/tricycle_steering_controller_params.yaml create mode 100644 tricycle_steering_controller/test/tricycle_steering_controller_preceeding_params.yaml create mode 100644 tricycle_steering_controller/tricycle_steering_controller.xml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b927aeac78..5a7ac74d9b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -126,7 +126,7 @@ repos: exclude: CHANGELOG\.rst$ - repo: https://github.com/pre-commit/pygrep-hooks - rev: v1.9.0 + rev: v1.10.0 hooks: - id: rst-backticks exclude: CHANGELOG\.rst$ diff --git a/ackermann_steering_controller/CMakeLists.txt b/ackermann_steering_controller/CMakeLists.txt new file mode 100644 index 0000000000..ff76da8853 --- /dev/null +++ b/ackermann_steering_controller/CMakeLists.txt @@ -0,0 +1,107 @@ +cmake_minimum_required(VERSION 3.16) +project(ackermann_steering_controller LANGUAGES CXX) + +if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +# find dependencies +set(THIS_PACKAGE_INCLUDE_DEPENDS + controller_interface + hardware_interface + generate_parameter_library + pluginlib + rclcpp + rclcpp_lifecycle + realtime_tools + std_srvs + steering_controllers_library +) + +find_package(ament_cmake REQUIRED) +find_package(backward_ros REQUIRED) +foreach(Dependency IN ITEMS ${THIS_PACKAGE_INCLUDE_DEPENDS}) + find_package(${Dependency} REQUIRED) +endforeach() + +generate_parameter_library(ackermann_steering_controller_parameters + src/ackermann_steering_controller.yaml +) + +add_library( + ackermann_steering_controller + SHARED + src/ackermann_steering_controller.cpp +) +target_compile_features(ackermann_steering_controller PUBLIC cxx_std_17) +target_include_directories(ackermann_steering_controller PUBLIC + $ + $) +target_link_libraries(ackermann_steering_controller PUBLIC + ackermann_steering_controller_parameters) +ament_target_dependencies(ackermann_steering_controller PUBLIC ${THIS_PACKAGE_INCLUDE_DEPENDS}) + +# Causes the visibility macros to use dllexport rather than dllimport, +# which is appropriate when building the dll but not consuming it. +target_compile_definitions(ackermann_steering_controller PRIVATE "ACKERMANN_STEERING_CONTROLLER_BUILDING_DLL") + +pluginlib_export_plugin_description_file( + controller_interface ackermann_steering_controller.xml) + +if(BUILD_TESTING) + find_package(ament_cmake_gmock REQUIRED) + find_package(controller_manager REQUIRED) + find_package(hardware_interface REQUIRED) + find_package(ros2_control_test_assets REQUIRED) + + + add_rostest_with_parameters_gmock(test_load_ackermann_steering_controller + test/test_load_ackermann_steering_controller.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test/ackermann_steering_controller_params.yaml + ) + ament_target_dependencies(test_load_ackermann_steering_controller + controller_manager + hardware_interface + ros2_control_test_assets + ) + + add_rostest_with_parameters_gmock(test_ackermann_steering_controller + test/test_ackermann_steering_controller.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test/ackermann_steering_controller_params.yaml + ) + target_include_directories(test_ackermann_steering_controller PRIVATE include) + target_link_libraries(test_ackermann_steering_controller ackermann_steering_controller) + ament_target_dependencies( + test_ackermann_steering_controller + controller_interface + hardware_interface + ) + + add_rostest_with_parameters_gmock( + test_ackermann_steering_controller_preceeding test/test_ackermann_steering_controller_preceeding.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test/ackermann_steering_controller_preceeding_params.yaml) + target_include_directories(test_ackermann_steering_controller_preceeding PRIVATE include) + target_link_libraries(test_ackermann_steering_controller_preceeding ackermann_steering_controller) + ament_target_dependencies( + test_ackermann_steering_controller_preceeding + controller_interface + hardware_interface + ) +endif() + +install( + DIRECTORY include/ + DESTINATION include/ackermann_steering_controller +) + +install( + TARGETS ackermann_steering_controller ackermann_steering_controller_parameters + EXPORT export_ackermann_steering_controller + RUNTIME DESTINATION bin + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib +) + +ament_export_targets(export_ackermann_steering_controller HAS_LIBRARY_TARGET) +ament_export_dependencies(${THIS_PACKAGE_INCLUDE_DEPENDS}) +ament_package() diff --git a/ackermann_steering_controller/ackermann_steering_controller.xml b/ackermann_steering_controller/ackermann_steering_controller.xml new file mode 100644 index 0000000000..2ac2150dd1 --- /dev/null +++ b/ackermann_steering_controller/ackermann_steering_controller.xml @@ -0,0 +1,8 @@ + + + + Steering controller for Ackermann (car-like) kinematics with two traction and two steering joints. + + + diff --git a/ackermann_steering_controller/doc/userdoc.rst b/ackermann_steering_controller/doc/userdoc.rst new file mode 100644 index 0000000000..59cdb78108 --- /dev/null +++ b/ackermann_steering_controller/doc/userdoc.rst @@ -0,0 +1,18 @@ +.. _ackermann_steering_controller_userdoc: + +ackermann_steering_controller +============================= + +This controller implements the kinematics with two axes and four wheels, where the wheels on one axis are fixed (traction/drive) wheels, and the wheels on the other axis are steerable. + +The controller expects to have two commanding joints for traction, one for each fixed wheel and two commanding joints for steering, one for each wheel. + +For more details on controller's execution and interfaces check the :ref:`Steering Controller Library `. + + +Parameters +,,,,,,,,,,, + +For list of parameters and their meaning YAML file in the ``src`` folder of the controller's package. + +For an exemplary parameterization see the ``test`` folder of the controller's package. diff --git a/ackermann_steering_controller/include/ackermann_steering_controller/ackermann_steering_controller.hpp b/ackermann_steering_controller/include/ackermann_steering_controller/ackermann_steering_controller.hpp new file mode 100644 index 0000000000..0cb6bcd016 --- /dev/null +++ b/ackermann_steering_controller/include/ackermann_steering_controller/ackermann_steering_controller.hpp @@ -0,0 +1,65 @@ +// Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Authors: dr. sc. Tomislav Petkovic, Dr. Ing. Denis Štogl +// + +#ifndef ACKERMANN_STEERING_CONTROLLER__ACKERMANN_STEERING_CONTROLLER_HPP_ +#define ACKERMANN_STEERING_CONTROLLER__ACKERMANN_STEERING_CONTROLLER_HPP_ + +#include + +#include "ackermann_steering_controller/visibility_control.h" +#include "ackermann_steering_controller_parameters.hpp" +#include "steering_controllers_library/steering_controllers_library.hpp" + +namespace ackermann_steering_controller +{ +// name constants for state interfaces +static constexpr size_t STATE_TRACTION_RIGHT_WHEEL = 0; +static constexpr size_t STATE_TRACTION_LEFT_WHEEL = 1; +static constexpr size_t STATE_STEER_RIGHT_WHEEL = 2; +static constexpr size_t STATE_STEER_LEFT_WHEEL = 3; + +// name constants for command interfaces +static constexpr size_t CMD_TRACTION_RIGHT_WHEEL = 0; +static constexpr size_t CMD_TRACTION_LEFT_WHEEL = 1; +static constexpr size_t CMD_STEER_RIGHT_WHEEL = 2; +static constexpr size_t CMD_STEER_LEFT_WHEEL = 3; + +static constexpr size_t NR_STATE_ITFS = 4; +static constexpr size_t NR_CMD_ITFS = 4; +static constexpr size_t NR_REF_ITFS = 2; + +class AckermannSteeringController : public steering_controllers_library::SteeringControllersLibrary +{ +public: + AckermannSteeringController(); + + ACKERMANN_STEERING_CONTROLLER__VISIBILITY_PUBLIC controller_interface::CallbackReturn + configure_odometry() override; + + ACKERMANN_STEERING_CONTROLLER__VISIBILITY_PUBLIC bool update_odometry( + const rclcpp::Duration & period) override; + + ACKERMANN_STEERING_CONTROLLER__VISIBILITY_PUBLIC void + initialize_implementation_parameter_listener() override; + +protected: + std::shared_ptr ackermann_param_listener_; + ackermann_steering_controller::Params ackermann_params_; +}; +} // namespace ackermann_steering_controller + +#endif // ACKERMANN_STEERING_CONTROLLER__ACKERMANN_STEERING_CONTROLLER_HPP_ diff --git a/ackermann_steering_controller/include/ackermann_steering_controller/visibility_control.h b/ackermann_steering_controller/include/ackermann_steering_controller/visibility_control.h new file mode 100644 index 0000000000..177f0bf87c --- /dev/null +++ b/ackermann_steering_controller/include/ackermann_steering_controller/visibility_control.h @@ -0,0 +1,52 @@ +// Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef ACKERMANN_STEERING_CONTROLLER__VISIBILITY_CONTROL_H_ +#define ACKERMANN_STEERING_CONTROLLER__VISIBILITY_CONTROL_H_ + +// This logic was borrowed (then namespaced) from the examples on the gcc wiki: +// https://gcc.gnu.org/wiki/Visibility + +#if defined _WIN32 || defined __CYGWIN__ +#ifdef __GNUC__ +#define ACKERMANN_STEERING_CONTROLLER__VISIBILITY_EXPORT __attribute__((dllexport)) +#define ACKERMANN_STEERING_CONTROLLER__VISIBILITY_IMPORT __attribute__((dllimport)) +#else +#define ACKERMANN_STEERING_CONTROLLER__VISIBILITY_EXPORT __declspec(dllexport) +#define ACKERMANN_STEERING_CONTROLLER__VISIBILITY_IMPORT __declspec(dllimport) +#endif +#ifdef ACKERMANN_STEERING_CONTROLLER__VISIBILITY_BUILDING_DLL +#define ACKERMANN_STEERING_CONTROLLER__VISIBILITY_PUBLIC \ + ACKERMANN_STEERING_CONTROLLER__VISIBILITY_EXPORT +#else +#define ACKERMANN_STEERING_CONTROLLER__VISIBILITY_PUBLIC \ + ACKERMANN_STEERING_CONTROLLER__VISIBILITY_IMPORT +#endif +#define ACKERMANN_STEERING_CONTROLLER__VISIBILITY_PUBLIC_TYPE \ + ACKERMANN_STEERING_CONTROLLER__VISIBILITY_PUBLIC +#define ACKERMANN_STEERING_CONTROLLER__VISIBILITY_LOCAL +#else +#define ACKERMANN_STEERING_CONTROLLER__VISIBILITY_EXPORT __attribute__((visibility("default"))) +#define ACKERMANN_STEERING_CONTROLLER__VISIBILITY_IMPORT +#if __GNUC__ >= 4 +#define ACKERMANN_STEERING_CONTROLLER__VISIBILITY_PUBLIC __attribute__((visibility("default"))) +#define ACKERMANN_STEERING_CONTROLLER__VISIBILITY_LOCAL __attribute__((visibility("hidden"))) +#else +#define ACKERMANN_STEERING_CONTROLLER__VISIBILITY_PUBLIC +#define ACKERMANN_STEERING_CONTROLLER__VISIBILITY_LOCAL +#endif +#define ACKERMANN_STEERING_CONTROLLER__VISIBILITY_PUBLIC_TYPE +#endif + +#endif // ACKERMANN_STEERING_CONTROLLER__VISIBILITY_CONTROL_H_ diff --git a/ackermann_steering_controller/package.xml b/ackermann_steering_controller/package.xml new file mode 100644 index 0000000000..24c3c8406b --- /dev/null +++ b/ackermann_steering_controller/package.xml @@ -0,0 +1,36 @@ + + + + ackermann_steering_controller + 0.0.0 + Steering controller for Ackermann kinematics. Rear fixed wheels are powering the vehicle and front wheels are steering it. + Apache License 2.0 + Bence Magyar + Dr.-Ing. Denis Štogl + dr. sc. Tomislav Petkovic + + Dr.-Ing. Denis Štogl + dr. sc. Tomislav Petkovic + + ament_cmake + + generate_parameter_library + + control_msgs + controller_interface + hardware_interface + pluginlib + rclcpp + rclcpp_lifecycle + std_srvs + steering_controllers_library + + ament_cmake_gmock + controller_manager + hardware_interface + ros2_control_test_assets + + + ament_cmake + + diff --git a/ackermann_steering_controller/src/ackermann_steering_controller.cpp b/ackermann_steering_controller/src/ackermann_steering_controller.cpp new file mode 100644 index 0000000000..c3a7539c5a --- /dev/null +++ b/ackermann_steering_controller/src/ackermann_steering_controller.cpp @@ -0,0 +1,98 @@ +// Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "ackermann_steering_controller/ackermann_steering_controller.hpp" + +namespace ackermann_steering_controller +{ +AckermannSteeringController::AckermannSteeringController() +: steering_controllers_library::SteeringControllersLibrary() +{ +} + +void AckermannSteeringController::initialize_implementation_parameter_listener() +{ + ackermann_param_listener_ = + std::make_shared(get_node()); +} + +controller_interface::CallbackReturn AckermannSteeringController::configure_odometry() +{ + ackermann_params_ = ackermann_param_listener_->get_params(); + + const double front_wheels_radius = ackermann_params_.front_wheels_radius; + const double rear_wheels_radius = ackermann_params_.rear_wheels_radius; + const double front_wheel_track = ackermann_params_.front_wheel_track; + const double rear_wheel_track = ackermann_params_.rear_wheel_track; + const double wheelbase = ackermann_params_.wheelbase; + + if (params_.front_steering) + { + odometry_.set_wheel_params(rear_wheels_radius, wheelbase, rear_wheel_track); + } + else + { + odometry_.set_wheel_params(front_wheels_radius, wheelbase, front_wheel_track); + } + + odometry_.set_odometry_type(steering_odometry::ACKERMANN_CONFIG); + + set_interface_numbers(NR_STATE_ITFS, NR_CMD_ITFS, NR_REF_ITFS); + + RCLCPP_INFO(get_node()->get_logger(), "ackermann odom configure successful"); + return controller_interface::CallbackReturn::SUCCESS; +} + +bool AckermannSteeringController::update_odometry(const rclcpp::Duration & period) +{ + if (params_.open_loop) + { + odometry_.update_open_loop(last_linear_velocity_, last_angular_velocity_, period.seconds()); + } + else + { + const double rear_right_wheel_value = state_interfaces_[STATE_TRACTION_RIGHT_WHEEL].get_value(); + const double rear_left_wheel_value = state_interfaces_[STATE_TRACTION_LEFT_WHEEL].get_value(); + const double front_right_steer_position = + state_interfaces_[STATE_STEER_RIGHT_WHEEL].get_value(); + const double front_left_steer_position = state_interfaces_[STATE_STEER_LEFT_WHEEL].get_value(); + if ( + !std::isnan(rear_right_wheel_value) && !std::isnan(rear_left_wheel_value) && + !std::isnan(front_right_steer_position) && !std::isnan(front_left_steer_position)) + { + if (params_.position_feedback) + { + // Estimate linear and angular velocity using joint information + odometry_.update_from_position( + rear_right_wheel_value, rear_left_wheel_value, front_right_steer_position, + front_left_steer_position, period.seconds()); + } + else + { + // Estimate linear and angular velocity using joint information + odometry_.update_from_velocity( + rear_right_wheel_value, rear_left_wheel_value, front_right_steer_position, + front_left_steer_position, period.seconds()); + } + } + } + return true; +} +} // namespace ackermann_steering_controller + +#include "pluginlib/class_list_macros.hpp" + +PLUGINLIB_EXPORT_CLASS( + ackermann_steering_controller::AckermannSteeringController, + controller_interface::ChainableControllerInterface) diff --git a/ackermann_steering_controller/src/ackermann_steering_controller.yaml b/ackermann_steering_controller/src/ackermann_steering_controller.yaml new file mode 100644 index 0000000000..3726146919 --- /dev/null +++ b/ackermann_steering_controller/src/ackermann_steering_controller.yaml @@ -0,0 +1,40 @@ +ackermann_steering_controller: + front_wheel_track: + { + type: double, + default_value: 0.0, + description: "Front wheel track length. For details see: https://en.wikipedia.org/wiki/Wheelbase", + read_only: false, + } + + rear_wheel_track: + { + type: double, + default_value: 0.0, + description: "Rear wheel track length. For details see: https://en.wikipedia.org/wiki/Wheelbase", + read_only: false, + } + + wheelbase: + { + type: double, + default_value: 0.0, + description: "Distance between front and rear wheels. For details see: https://en.wikipedia.org/wiki/Wheelbase", + read_only: false, + } + + front_wheels_radius: + { + type: double, + default_value: 0.0, + description: "Front wheels radius.", + read_only: false, + } + + rear_wheels_radius: + { + type: double, + default_value: 0.0, + description: "Rear wheels radius.", + read_only: false, + } diff --git a/ackermann_steering_controller/test/ackermann_steering_controller_params.yaml b/ackermann_steering_controller/test/ackermann_steering_controller_params.yaml new file mode 100644 index 0000000000..6b64f901c3 --- /dev/null +++ b/ackermann_steering_controller/test/ackermann_steering_controller_params.yaml @@ -0,0 +1,17 @@ +test_ackermann_steering_controller: + ros__parameters: + + reference_timeout: 2.0 + front_steering: true + open_loop: false + velocity_rolling_window_size: 10 + position_feedback: false + use_stamped_vel: true + rear_wheels_names: [rear_right_wheel_joint, rear_left_wheel_joint] + front_wheels_names: [front_right_steering_joint, front_left_steering_joint] + + wheelbase: 3.24644 + front_wheel_track: 2.12321 + rear_wheel_track: 1.76868 + front_wheels_radius: 0.45 + rear_wheels_radius: 0.45 diff --git a/ackermann_steering_controller/test/ackermann_steering_controller_preceeding_params.yaml b/ackermann_steering_controller/test/ackermann_steering_controller_preceeding_params.yaml new file mode 100644 index 0000000000..ecb1b071e3 --- /dev/null +++ b/ackermann_steering_controller/test/ackermann_steering_controller_preceeding_params.yaml @@ -0,0 +1,17 @@ +test_ackermann_steering_controller: + ros__parameters: + reference_timeout: 2.0 + front_steering: true + open_loop: false + velocity_rolling_window_size: 10 + position_feedback: false + use_stamped_vel: true + rear_wheels_names: [pid_controller/rear_right_wheel_joint, pid_controller/rear_left_wheel_joint] + front_wheels_names: [pid_controller/front_right_steering_joint, pid_controller/front_left_steering_joint] + rear_wheels_state_names: [rear_right_wheel_joint, rear_left_wheel_joint] + front_wheels_state_names: [front_right_steering_joint, front_left_steering_joint] + wheelbase: 3.24644 + front_wheel_track: 2.12321 + rear_wheel_track: 1.76868 + front_wheels_radius: 0.45 + rear_wheels_radius: 0.45 diff --git a/ackermann_steering_controller/test/test_ackermann_steering_controller.cpp b/ackermann_steering_controller/test/test_ackermann_steering_controller.cpp new file mode 100644 index 0000000000..480e90e166 --- /dev/null +++ b/ackermann_steering_controller/test/test_ackermann_steering_controller.cpp @@ -0,0 +1,292 @@ +// Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "test_ackermann_steering_controller.hpp" + +#include +#include +#include +#include +#include + +class AckermannSteeringControllerTest +: public AckermannSteeringControllerFixture +{ +}; + +TEST_F(AckermannSteeringControllerTest, all_parameters_set_configure_success) +{ + SetUpController(); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + + ASSERT_THAT( + controller_->params_.rear_wheels_names, testing::ElementsAreArray(rear_wheels_names_)); + ASSERT_THAT( + controller_->params_.front_wheels_names, testing::ElementsAreArray(front_wheels_names_)); + ASSERT_EQ(controller_->params_.front_steering, front_steering_); + ASSERT_EQ(controller_->params_.open_loop, open_loop_); + ASSERT_EQ(controller_->params_.velocity_rolling_window_size, velocity_rolling_window_size_); + ASSERT_EQ(controller_->params_.position_feedback, position_feedback_); + ASSERT_EQ(controller_->ackermann_params_.wheelbase, wheelbase_); + ASSERT_EQ(controller_->ackermann_params_.front_wheels_radius, front_wheels_radius_); + ASSERT_EQ(controller_->ackermann_params_.rear_wheels_radius, rear_wheels_radius_); + ASSERT_EQ(controller_->ackermann_params_.front_wheel_track, front_wheel_track_); + ASSERT_EQ(controller_->ackermann_params_.rear_wheel_track, rear_wheel_track_); +} + +TEST_F(AckermannSteeringControllerTest, check_exported_intefaces) +{ + SetUpController(); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + + auto command_intefaces = controller_->command_interface_configuration(); + ASSERT_EQ(command_intefaces.names.size(), joint_command_values_.size()); + EXPECT_EQ( + command_intefaces.names[CMD_TRACTION_RIGHT_WHEEL], + rear_wheels_names_[0] + "/" + traction_interface_name_); + EXPECT_EQ( + command_intefaces.names[CMD_TRACTION_LEFT_WHEEL], + rear_wheels_names_[1] + "/" + traction_interface_name_); + EXPECT_EQ( + command_intefaces.names[CMD_STEER_RIGHT_WHEEL], + front_wheels_names_[0] + "/" + steering_interface_name_); + EXPECT_EQ( + command_intefaces.names[CMD_STEER_LEFT_WHEEL], + front_wheels_names_[1] + "/" + steering_interface_name_); + + auto state_intefaces = controller_->state_interface_configuration(); + ASSERT_EQ(state_intefaces.names.size(), joint_state_values_.size()); + EXPECT_EQ( + state_intefaces.names[STATE_TRACTION_RIGHT_WHEEL], + controller_->rear_wheels_state_names_[0] + "/" + traction_interface_name_); + EXPECT_EQ( + state_intefaces.names[STATE_TRACTION_LEFT_WHEEL], + controller_->rear_wheels_state_names_[1] + "/" + traction_interface_name_); + EXPECT_EQ( + state_intefaces.names[STATE_STEER_RIGHT_WHEEL], + controller_->front_wheels_state_names_[0] + "/" + steering_interface_name_); + EXPECT_EQ( + state_intefaces.names[STATE_STEER_LEFT_WHEEL], + controller_->front_wheels_state_names_[1] + "/" + steering_interface_name_); + + // check ref itfsTIME + auto reference_interfaces = controller_->export_reference_interfaces(); + ASSERT_EQ(reference_interfaces.size(), joint_reference_interfaces_.size()); + for (size_t i = 0; i < joint_reference_interfaces_.size(); ++i) + { + const std::string ref_itf_name = + std::string(controller_->get_node()->get_name()) + "/" + joint_reference_interfaces_[i]; + EXPECT_EQ(reference_interfaces[i].get_name(), ref_itf_name); + EXPECT_EQ(reference_interfaces[i].get_prefix_name(), controller_->get_node()->get_name()); + EXPECT_EQ(reference_interfaces[i].get_interface_name(), joint_reference_interfaces_[i]); + } +} + +TEST_F(AckermannSteeringControllerTest, activate_success) +{ + SetUpController(); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + + // check that the message is reset + auto msg = controller_->input_ref_.readFromNonRT(); + EXPECT_TRUE(std::isnan((*msg)->twist.linear.x)); + EXPECT_TRUE(std::isnan((*msg)->twist.linear.y)); + EXPECT_TRUE(std::isnan((*msg)->twist.linear.z)); + EXPECT_TRUE(std::isnan((*msg)->twist.angular.x)); + EXPECT_TRUE(std::isnan((*msg)->twist.angular.y)); + EXPECT_TRUE(std::isnan((*msg)->twist.angular.z)); +} + +TEST_F(AckermannSteeringControllerTest, update_success) +{ + SetUpController(); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + + ASSERT_EQ( + controller_->update(rclcpp::Time(0, 0, RCL_ROS_TIME), rclcpp::Duration::from_seconds(0.01)), + controller_interface::return_type::OK); +} + +TEST_F(AckermannSteeringControllerTest, deactivate_success) +{ + SetUpController(); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_EQ(controller_->on_deactivate(rclcpp_lifecycle::State()), NODE_SUCCESS); +} + +TEST_F(AckermannSteeringControllerTest, reactivate_success) +{ + SetUpController(); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_EQ(controller_->on_deactivate(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_TRUE(std::isnan(controller_->command_interfaces_[0].get_value())); + ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_TRUE(std::isnan(controller_->command_interfaces_[0].get_value())); + + ASSERT_EQ( + controller_->update(rclcpp::Time(0, 0, RCL_ROS_TIME), rclcpp::Duration::from_seconds(0.01)), + controller_interface::return_type::OK); +} + +TEST_F(AckermannSteeringControllerTest, test_update_logic) +{ + SetUpController(); + rclcpp::executors::MultiThreadedExecutor executor; + executor.add_node(controller_->get_node()->get_node_base_interface()); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + controller_->set_chained_mode(false); + ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_FALSE(controller_->is_in_chained_mode()); + + // set command statically + std::shared_ptr msg = std::make_shared(); + msg->header.stamp = controller_->get_node()->now(); + msg->twist.linear.x = 0.1; + msg->twist.angular.z = 0.2; + controller_->input_ref_.writeFromNonRT(msg); + + ASSERT_EQ( + controller_->update(rclcpp::Time(0, 0, RCL_ROS_TIME), rclcpp::Duration::from_seconds(0.01)), + controller_interface::return_type::OK); + + EXPECT_NEAR( + controller_->command_interfaces_[CMD_TRACTION_RIGHT_WHEEL].get_value(), 0.22222222222222224, + COMMON_THRESHOLD); + EXPECT_NEAR( + controller_->command_interfaces_[CMD_TRACTION_LEFT_WHEEL].get_value(), 0.22222222222222224, + COMMON_THRESHOLD); + EXPECT_NEAR( + controller_->command_interfaces_[CMD_STEER_RIGHT_WHEEL].get_value(), 1.4179821977774734, + COMMON_THRESHOLD); + EXPECT_NEAR( + controller_->command_interfaces_[CMD_STEER_LEFT_WHEEL].get_value(), 1.4179821977774734, + COMMON_THRESHOLD); + + EXPECT_FALSE(std::isnan((*(controller_->input_ref_.readFromRT()))->twist.linear.x)); + EXPECT_EQ(controller_->reference_interfaces_.size(), joint_reference_interfaces_.size()); + for (const auto & interface : controller_->reference_interfaces_) + { + EXPECT_TRUE(std::isnan(interface)); + } +} + +TEST_F(AckermannSteeringControllerTest, test_update_logic_chained) +{ + SetUpController(); + rclcpp::executors::MultiThreadedExecutor executor; + executor.add_node(controller_->get_node()->get_node_base_interface()); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + controller_->set_chained_mode(true); + ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_TRUE(controller_->is_in_chained_mode()); + + controller_->reference_interfaces_[0] = 0.1; + controller_->reference_interfaces_[1] = 0.2; + + ASSERT_EQ( + controller_->update(rclcpp::Time(0, 0, RCL_ROS_TIME), rclcpp::Duration::from_seconds(0.01)), + controller_interface::return_type::OK); + EXPECT_NEAR( + + controller_->command_interfaces_[STATE_TRACTION_RIGHT_WHEEL].get_value(), 0.22222222222222224, + COMMON_THRESHOLD); + EXPECT_NEAR( + controller_->command_interfaces_[STATE_TRACTION_LEFT_WHEEL].get_value(), 0.22222222222222224, + COMMON_THRESHOLD); + EXPECT_NEAR( + controller_->command_interfaces_[STATE_STEER_RIGHT_WHEEL].get_value(), 1.4179821977774734, + COMMON_THRESHOLD); + EXPECT_NEAR( + controller_->command_interfaces_[STATE_STEER_LEFT_WHEEL].get_value(), 1.4179821977774734, + COMMON_THRESHOLD); + + EXPECT_TRUE(std::isnan((*(controller_->input_ref_.readFromRT()))->twist.linear.x)); + EXPECT_EQ(controller_->reference_interfaces_.size(), joint_reference_interfaces_.size()); + for (const auto & interface : controller_->reference_interfaces_) + { + EXPECT_TRUE(std::isnan(interface)); + } +} + +TEST_F(AckermannSteeringControllerTest, receive_message_and_publish_updated_status) +{ + SetUpController(); + rclcpp::executors::MultiThreadedExecutor executor; + executor.add_node(controller_->get_node()->get_node_base_interface()); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + + ASSERT_EQ( + controller_->update(rclcpp::Time(0, 0, RCL_ROS_TIME), rclcpp::Duration::from_seconds(0.01)), + controller_interface::return_type::OK); + + ControllerStateMsg msg; + subscribe_and_get_messages(msg); + + EXPECT_EQ(msg.linear_velocity_command[STATE_TRACTION_RIGHT_WHEEL], 1.1); + EXPECT_EQ(msg.linear_velocity_command[STATE_TRACTION_LEFT_WHEEL], 3.3); + EXPECT_EQ(msg.steering_angle_command[0], 2.2); + EXPECT_EQ(msg.steering_angle_command[1], 4.4); + + publish_commands(); + ASSERT_TRUE(controller_->wait_for_commands(executor)); + + ASSERT_EQ( + controller_->update(rclcpp::Time(0, 0, RCL_ROS_TIME), rclcpp::Duration::from_seconds(0.01)), + controller_interface::return_type::OK); + + EXPECT_NEAR( + controller_->command_interfaces_[CMD_TRACTION_RIGHT_WHEEL].get_value(), 0.22222222222222224, + COMMON_THRESHOLD); + EXPECT_NEAR( + controller_->command_interfaces_[CMD_TRACTION_LEFT_WHEEL].get_value(), 0.22222222222222224, + COMMON_THRESHOLD); + EXPECT_NEAR( + controller_->command_interfaces_[CMD_STEER_RIGHT_WHEEL].get_value(), 1.4179821977774734, + COMMON_THRESHOLD); + EXPECT_NEAR( + controller_->command_interfaces_[CMD_STEER_LEFT_WHEEL].get_value(), 1.4179821977774734, + COMMON_THRESHOLD); + + subscribe_and_get_messages(msg); + + EXPECT_NEAR( + msg.linear_velocity_command[CMD_TRACTION_RIGHT_WHEEL], 0.22222222222222224, COMMON_THRESHOLD); + EXPECT_NEAR( + msg.linear_velocity_command[CMD_TRACTION_LEFT_WHEEL], 0.22222222222222224, COMMON_THRESHOLD); + EXPECT_NEAR(msg.steering_angle_command[0], 1.4179821977774734, COMMON_THRESHOLD); + EXPECT_NEAR(msg.steering_angle_command[1], 1.4179821977774734, COMMON_THRESHOLD); +} + +int main(int argc, char ** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + rclcpp::init(argc, argv); + int result = RUN_ALL_TESTS(); + rclcpp::shutdown(); + return result; +} diff --git a/ackermann_steering_controller/test/test_ackermann_steering_controller.hpp b/ackermann_steering_controller/test/test_ackermann_steering_controller.hpp new file mode 100644 index 0000000000..80258258c2 --- /dev/null +++ b/ackermann_steering_controller/test/test_ackermann_steering_controller.hpp @@ -0,0 +1,319 @@ +// Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef TEST_ACKERMANN_STEERING_CONTROLLER_HPP_ +#define TEST_ACKERMANN_STEERING_CONTROLLER_HPP_ + +#include +#include +#include +#include +#include +#include +#include + +#include "ackermann_steering_controller/ackermann_steering_controller.hpp" +#include "gmock/gmock.h" +#include "hardware_interface/loaned_command_interface.hpp" +#include "hardware_interface/loaned_state_interface.hpp" +#include "hardware_interface/types/hardware_interface_return_values.hpp" +#include "rclcpp/parameter_value.hpp" +#include "rclcpp/time.hpp" +#include "rclcpp/utilities.hpp" +#include "rclcpp_lifecycle/node_interfaces/lifecycle_node_interface.hpp" + +using ControllerStateMsg = + steering_controllers_library::SteeringControllersLibrary::AckermanControllerState; +using ControllerReferenceMsg = + steering_controllers_library::SteeringControllersLibrary::ControllerTwistReferenceMsg; + +// name constants for state interfaces +using ackermann_steering_controller::STATE_STEER_LEFT_WHEEL; +using ackermann_steering_controller::STATE_STEER_RIGHT_WHEEL; +using ackermann_steering_controller::STATE_TRACTION_LEFT_WHEEL; +using ackermann_steering_controller::STATE_TRACTION_RIGHT_WHEEL; + +// name constants for command interfaces +using ackermann_steering_controller::CMD_STEER_LEFT_WHEEL; +using ackermann_steering_controller::CMD_STEER_RIGHT_WHEEL; +using ackermann_steering_controller::CMD_TRACTION_LEFT_WHEEL; +using ackermann_steering_controller::CMD_TRACTION_RIGHT_WHEEL; + +namespace +{ +constexpr auto NODE_SUCCESS = controller_interface::CallbackReturn::SUCCESS; +constexpr auto NODE_ERROR = controller_interface::CallbackReturn::ERROR; +const double COMMON_THRESHOLD = 1e-6; +} // namespace + +// subclassing and friending so we can access member variables +class TestableAckermannSteeringController +: public ackermann_steering_controller::AckermannSteeringController +{ + FRIEND_TEST(AckermannSteeringControllerTest, all_parameters_set_configure_success); + FRIEND_TEST(AckermannSteeringControllerTest, check_exported_intefaces); + FRIEND_TEST(AckermannSteeringControllerTest, activate_success); + FRIEND_TEST(AckermannSteeringControllerTest, update_success); + FRIEND_TEST(AckermannSteeringControllerTest, deactivate_success); + FRIEND_TEST(AckermannSteeringControllerTest, reactivate_success); + FRIEND_TEST(AckermannSteeringControllerTest, test_update_logic); + FRIEND_TEST(AckermannSteeringControllerTest, test_update_logic_chained); + FRIEND_TEST(AckermannSteeringControllerTest, publish_status_success); + FRIEND_TEST(AckermannSteeringControllerTest, receive_message_and_publish_updated_status); + +public: + controller_interface::CallbackReturn on_configure( + const rclcpp_lifecycle::State & previous_state) override + { + auto ret = + ackermann_steering_controller::AckermannSteeringController::on_configure(previous_state); + // Only if on_configure is successful create subscription + if (ret == CallbackReturn::SUCCESS) + { + ref_subscriber_wait_set_.add_subscription(ref_subscriber_twist_); + } + return ret; + } + + controller_interface::CallbackReturn on_activate( + const rclcpp_lifecycle::State & previous_state) override + { + auto ref_itfs = on_export_reference_interfaces(); + return ackermann_steering_controller::AckermannSteeringController::on_activate(previous_state); + } + + /** + * @brief wait_for_command blocks until a new ControllerReferenceMsg is received. + * Requires that the executor is not spinned elsewhere between the + * message publication and the call to this function. + * + * @return true if new ControllerReferenceMsg msg was received, false if timeout. + */ + bool wait_for_command( + rclcpp::Executor & executor, rclcpp::WaitSet & subscriber_wait_set, + const std::chrono::milliseconds & timeout = std::chrono::milliseconds{500}) + { + bool success = subscriber_wait_set.wait(timeout).kind() == rclcpp::WaitResultKind::Ready; + if (success) + { + executor.spin_some(); + } + return success; + } + + bool wait_for_commands( + rclcpp::Executor & executor, + const std::chrono::milliseconds & timeout = std::chrono::milliseconds{500}) + { + return wait_for_command(executor, ref_subscriber_wait_set_, timeout); + } + +private: + rclcpp::WaitSet ref_subscriber_wait_set_; +}; + +// We are using template class here for easier reuse of Fixture in specializations of controllers +template +class AckermannSteeringControllerFixture : public ::testing::Test +{ +public: + static void SetUpTestCase() {} + + void SetUp() + { + // initialize controller + controller_ = std::make_unique(); + + command_publisher_node_ = std::make_shared("command_publisher"); + command_publisher_ = command_publisher_node_->create_publisher( + "/test_ackermann_steering_controller/reference", rclcpp::SystemDefaultsQoS()); + } + + static void TearDownTestCase() {} + + void TearDown() { controller_.reset(nullptr); } + +protected: + void SetUpController(const std::string controller_name = "test_ackermann_steering_controller") + { + ASSERT_EQ(controller_->init(controller_name), controller_interface::return_type::OK); + + if (position_feedback_ == true) + { + traction_interface_name_ = "position"; + } + else + { + traction_interface_name_ = "velocity"; + } + + std::vector command_ifs; + command_itfs_.reserve(joint_command_values_.size()); + command_ifs.reserve(joint_command_values_.size()); + + command_itfs_.emplace_back(hardware_interface::CommandInterface( + rear_wheels_names_[0], traction_interface_name_, + &joint_command_values_[CMD_TRACTION_RIGHT_WHEEL])); + command_ifs.emplace_back(command_itfs_.back()); + + command_itfs_.emplace_back(hardware_interface::CommandInterface( + rear_wheels_names_[1], steering_interface_name_, + &joint_command_values_[CMD_TRACTION_LEFT_WHEEL])); + command_ifs.emplace_back(command_itfs_.back()); + + command_itfs_.emplace_back(hardware_interface::CommandInterface( + front_wheels_names_[0], steering_interface_name_, + &joint_command_values_[CMD_STEER_RIGHT_WHEEL])); + command_ifs.emplace_back(command_itfs_.back()); + + command_itfs_.emplace_back(hardware_interface::CommandInterface( + front_wheels_names_[1], steering_interface_name_, + &joint_command_values_[CMD_STEER_LEFT_WHEEL])); + command_ifs.emplace_back(command_itfs_.back()); + + std::vector state_ifs; + state_itfs_.reserve(joint_state_values_.size()); + state_ifs.reserve(joint_state_values_.size()); + + state_itfs_.emplace_back(hardware_interface::StateInterface( + rear_wheels_names_[0], traction_interface_name_, + &joint_state_values_[STATE_TRACTION_RIGHT_WHEEL])); + state_ifs.emplace_back(state_itfs_.back()); + + state_itfs_.emplace_back(hardware_interface::StateInterface( + rear_wheels_names_[1], traction_interface_name_, + &joint_state_values_[STATE_TRACTION_LEFT_WHEEL])); + state_ifs.emplace_back(state_itfs_.back()); + + state_itfs_.emplace_back(hardware_interface::StateInterface( + front_wheels_names_[0], steering_interface_name_, + &joint_state_values_[STATE_STEER_RIGHT_WHEEL])); + state_ifs.emplace_back(state_itfs_.back()); + + state_itfs_.emplace_back(hardware_interface::StateInterface( + front_wheels_names_[1], steering_interface_name_, + &joint_state_values_[STATE_STEER_LEFT_WHEEL])); + state_ifs.emplace_back(state_itfs_.back()); + + controller_->assign_interfaces(std::move(command_ifs), std::move(state_ifs)); + } + + void subscribe_and_get_messages(ControllerStateMsg & msg) + { + // create a new subscriber + rclcpp::Node test_subscription_node("test_subscription_node"); + auto subs_callback = [&](const ControllerStateMsg::SharedPtr) {}; + auto subscription = test_subscription_node.create_subscription( + "/test_ackermann_steering_controller/controller_state", 10, subs_callback); + + // call update to publish the test value + ASSERT_EQ( + controller_->update(rclcpp::Time(0, 0, RCL_ROS_TIME), rclcpp::Duration::from_seconds(0.01)), + controller_interface::return_type::OK); + + // call update to publish the test value + // since update doesn't guarantee a published message, republish until received + int max_sub_check_loop_count = 5; // max number of tries for pub/sub loop + rclcpp::WaitSet wait_set; // block used to wait on message + wait_set.add_subscription(subscription); + while (max_sub_check_loop_count--) + { + controller_->update(rclcpp::Time(0, 0, RCL_ROS_TIME), rclcpp::Duration::from_seconds(0.01)); + // check if message has been received + if (wait_set.wait(std::chrono::milliseconds(2)).kind() == rclcpp::WaitResultKind::Ready) + { + break; + } + } + ASSERT_GE(max_sub_check_loop_count, 0) << "Test was unable to publish a message through " + "controller/broadcaster update loop"; + + // take message from subscription + rclcpp::MessageInfo msg_info; + ASSERT_TRUE(subscription->take(msg, msg_info)); + } + + void publish_commands(const double linear = 0.1, const double angular = 0.2) + { + auto wait_for_topic = [&](const auto topic_name) + { + size_t wait_count = 0; + while (command_publisher_node_->count_subscribers(topic_name) == 0) + { + if (wait_count >= 5) + { + auto error_msg = + std::string("publishing to ") + topic_name + " but no node subscribes to it"; + throw std::runtime_error(error_msg); + } + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + ++wait_count; + } + }; + + wait_for_topic(command_publisher_->get_topic_name()); + + ControllerReferenceMsg msg; + msg.twist.linear.x = linear; + msg.twist.angular.z = angular; + + command_publisher_->publish(msg); + } + +protected: + // Controller-related parameters + double reference_timeout_ = 2.0; + bool front_steering_ = true; + bool open_loop_ = false; + unsigned int velocity_rolling_window_size_ = 10; + bool position_feedback_ = false; + bool use_stamped_vel_ = true; + std::vector rear_wheels_names_ = {"rear_right_wheel_joint", "rear_left_wheel_joint"}; + std::vector front_wheels_names_ = { + "front_right_steering_joint", "front_left_steering_joint"}; + std::vector joint_names_ = { + rear_wheels_names_[0], rear_wheels_names_[1], front_wheels_names_[0], front_wheels_names_[1]}; + + std::vector rear_wheels_preceeding_names_ = { + "pid_controller/rear_right_wheel_joint", "pid_controller/rear_left_wheel_joint"}; + std::vector front_wheels_preceeding_names_ = { + "pid_controller/front_right_steering_joint", "pid_controller/front_left_steering_joint"}; + std::vector preceeding_joint_names_ = { + rear_wheels_preceeding_names_[0], rear_wheels_preceeding_names_[1], + front_wheels_preceeding_names_[0], front_wheels_preceeding_names_[1]}; + + double wheelbase_ = 3.24644; + double front_wheel_track_ = 2.12321; + double rear_wheel_track_ = 1.76868; + double front_wheels_radius_ = 0.45; + double rear_wheels_radius_ = 0.45; + + std::array joint_state_values_ = {0.5, 0.5, 0.0, 0.0}; + std::array joint_command_values_ = {1.1, 3.3, 2.2, 4.4}; + std::array joint_reference_interfaces_ = {"linear/velocity", "angular/position"}; + std::string steering_interface_name_ = "position"; + // defined in setup + std::string traction_interface_name_ = ""; + std::string preceeding_prefix_ = "pid_controller"; + + std::vector state_itfs_; + std::vector command_itfs_; + + // Test related parameters + std::unique_ptr controller_; + rclcpp::Node::SharedPtr command_publisher_node_; + rclcpp::Publisher::SharedPtr command_publisher_; +}; + +#endif // TEST_ACKERMANN_STEERING_CONTROLLER_HPP_ diff --git a/ackermann_steering_controller/test/test_ackermann_steering_controller_preceeding.cpp b/ackermann_steering_controller/test/test_ackermann_steering_controller_preceeding.cpp new file mode 100644 index 0000000000..2d951588c5 --- /dev/null +++ b/ackermann_steering_controller/test/test_ackermann_steering_controller_preceeding.cpp @@ -0,0 +1,107 @@ +// Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "test_ackermann_steering_controller.hpp" + +#include +#include +#include +#include +#include + +class AckermannSteeringControllerTest +: public AckermannSteeringControllerFixture +{ +}; + +TEST_F(AckermannSteeringControllerTest, all_parameters_set_configure_success) +{ + SetUpController(); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + + ASSERT_THAT( + controller_->params_.rear_wheels_names, + testing::ElementsAreArray(rear_wheels_preceeding_names_)); + ASSERT_THAT( + controller_->params_.front_wheels_names, + testing::ElementsAreArray(front_wheels_preceeding_names_)); + ASSERT_EQ(controller_->params_.front_steering, front_steering_); + ASSERT_EQ(controller_->params_.open_loop, open_loop_); + ASSERT_EQ(controller_->params_.velocity_rolling_window_size, velocity_rolling_window_size_); + ASSERT_EQ(controller_->params_.position_feedback, position_feedback_); + ASSERT_EQ(controller_->ackermann_params_.wheelbase, wheelbase_); + ASSERT_EQ(controller_->ackermann_params_.front_wheels_radius, front_wheels_radius_); + ASSERT_EQ(controller_->ackermann_params_.rear_wheels_radius, rear_wheels_radius_); + ASSERT_EQ(controller_->ackermann_params_.front_wheel_track, front_wheel_track_); + ASSERT_EQ(controller_->ackermann_params_.rear_wheel_track, rear_wheel_track_); +} + +TEST_F(AckermannSteeringControllerTest, check_exported_intefaces) +{ + SetUpController(); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + + auto command_intefaces = controller_->command_interface_configuration(); + ASSERT_EQ(command_intefaces.names.size(), joint_command_values_.size()); + EXPECT_EQ( + command_intefaces.names[CMD_TRACTION_RIGHT_WHEEL], + preceeding_prefix_ + "/" + rear_wheels_names_[0] + "/" + traction_interface_name_); + EXPECT_EQ( + command_intefaces.names[CMD_TRACTION_LEFT_WHEEL], + preceeding_prefix_ + "/" + rear_wheels_names_[1] + "/" + traction_interface_name_); + EXPECT_EQ( + command_intefaces.names[CMD_STEER_RIGHT_WHEEL], + preceeding_prefix_ + "/" + front_wheels_names_[0] + "/" + steering_interface_name_); + EXPECT_EQ( + command_intefaces.names[CMD_STEER_LEFT_WHEEL], + preceeding_prefix_ + "/" + front_wheels_names_[1] + "/" + steering_interface_name_); + + auto state_intefaces = controller_->state_interface_configuration(); + ASSERT_EQ(state_intefaces.names.size(), joint_state_values_.size()); + EXPECT_EQ( + state_intefaces.names[STATE_TRACTION_RIGHT_WHEEL], + controller_->rear_wheels_state_names_[0] + "/" + traction_interface_name_); + EXPECT_EQ( + state_intefaces.names[STATE_TRACTION_LEFT_WHEEL], + controller_->rear_wheels_state_names_[1] + "/" + traction_interface_name_); + EXPECT_EQ( + state_intefaces.names[STATE_STEER_RIGHT_WHEEL], + controller_->front_wheels_state_names_[0] + "/" + steering_interface_name_); + EXPECT_EQ( + state_intefaces.names[STATE_STEER_LEFT_WHEEL], + controller_->front_wheels_state_names_[1] + "/" + steering_interface_name_); + + // check ref itfs + auto reference_interfaces = controller_->export_reference_interfaces(); + ASSERT_EQ(reference_interfaces.size(), joint_reference_interfaces_.size()); + for (size_t i = 0; i < joint_reference_interfaces_.size(); ++i) + { + const std::string ref_itf_name = + std::string(controller_->get_node()->get_name()) + "/" + joint_reference_interfaces_[i]; + EXPECT_EQ(reference_interfaces[i].get_name(), ref_itf_name); + EXPECT_EQ(reference_interfaces[i].get_prefix_name(), controller_->get_node()->get_name()); + EXPECT_EQ(reference_interfaces[i].get_interface_name(), joint_reference_interfaces_[i]); + } +} + +int main(int argc, char ** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + rclcpp::init(argc, argv); + int result = RUN_ALL_TESTS(); + rclcpp::shutdown(); + return result; +} diff --git a/ackermann_steering_controller/test/test_load_ackermann_steering_controller.cpp b/ackermann_steering_controller/test/test_load_ackermann_steering_controller.cpp new file mode 100644 index 0000000000..0a8cd7b80c --- /dev/null +++ b/ackermann_steering_controller/test/test_load_ackermann_steering_controller.cpp @@ -0,0 +1,49 @@ +// Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include + +#include "controller_manager/controller_manager.hpp" +#include "hardware_interface/resource_manager.hpp" +#include "rclcpp/executor.hpp" +#include "rclcpp/executors/single_threaded_executor.hpp" +#include "rclcpp/utilities.hpp" +#include "ros2_control_test_assets/descriptions.hpp" + +TEST(TestLoadAckermannSteeringController, load_controller) +{ + std::shared_ptr executor = + std::make_shared(); + + controller_manager::ControllerManager cm( + std::make_unique( + ros2_control_test_assets::minimal_robot_urdf), + executor, "test_controller_manager"); + + ASSERT_NE( + cm.load_controller( + "test_ackermann_steering_controller", + "ackermann_steering_controller/AckermannSteeringController"), + nullptr); +} + +int main(int argc, char ** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + rclcpp::init(argc, argv); + int result = RUN_ALL_TESTS(); + rclcpp::shutdown(); + return result; +} diff --git a/bicycle_steering_controller/CMakeLists.txt b/bicycle_steering_controller/CMakeLists.txt new file mode 100644 index 0000000000..8ac12fe0a0 --- /dev/null +++ b/bicycle_steering_controller/CMakeLists.txt @@ -0,0 +1,105 @@ +cmake_minimum_required(VERSION 3.16) +project(bicycle_steering_controller LANGUAGES CXX) + +if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +# find dependencies +set(THIS_PACKAGE_INCLUDE_DEPENDS + controller_interface + hardware_interface + generate_parameter_library + pluginlib + rclcpp + rclcpp_lifecycle + realtime_tools + std_srvs + steering_controllers_library +) + +find_package(ament_cmake REQUIRED) +find_package(backward_ros REQUIRED) +foreach(Dependency IN ITEMS ${THIS_PACKAGE_INCLUDE_DEPENDS}) + find_package(${Dependency} REQUIRED) +endforeach() + +generate_parameter_library(bicycle_steering_controller_parameters + src/bicycle_steering_controller.yaml +) + +add_library( + bicycle_steering_controller + SHARED + src/bicycle_steering_controller.cpp +) +target_compile_features(bicycle_steering_controller PUBLIC cxx_std_17) +target_include_directories(bicycle_steering_controller PUBLIC + "$" + "$") +target_link_libraries(bicycle_steering_controller PUBLIC + bicycle_steering_controller_parameters) +ament_target_dependencies(bicycle_steering_controller PUBLIC ${THIS_PACKAGE_INCLUDE_DEPENDS}) + +# Causes the visibility macros to use dllexport rather than dllimport, +# which is appropriate when building the dll but not consuming it. +target_compile_definitions(bicycle_steering_controller PRIVATE "ACKERMANN_STEERING_CONTROLLER_BUILDING_DLL") + +pluginlib_export_plugin_description_file( + controller_interface bicycle_steering_controller.xml) + +if(BUILD_TESTING) + find_package(ament_cmake_gmock REQUIRED) + find_package(controller_manager REQUIRED) + find_package(hardware_interface REQUIRED) + find_package(ros2_control_test_assets REQUIRED) + + add_rostest_with_parameters_gmock(test_load_bicycle_steering_controller + test/test_load_bicycle_steering_controller.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test/bicycle_steering_controller_params.yaml + ) + ament_target_dependencies(test_load_bicycle_steering_controller + controller_manager + hardware_interface + ros2_control_test_assets + ) + + add_rostest_with_parameters_gmock( + test_bicycle_steering_controller test/test_bicycle_steering_controller.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test/bicycle_steering_controller_params.yaml) + target_include_directories(test_bicycle_steering_controller PRIVATE include) + target_link_libraries(test_bicycle_steering_controller bicycle_steering_controller) + ament_target_dependencies( + test_bicycle_steering_controller + controller_interface + hardware_interface + ) + + add_rostest_with_parameters_gmock( + test_bicycle_steering_controller_preceeding test/test_bicycle_steering_controller_preceeding.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test/bicycle_steering_controller_preceeding_params.yaml) + target_include_directories(test_bicycle_steering_controller_preceeding PRIVATE include) + target_link_libraries(test_bicycle_steering_controller_preceeding bicycle_steering_controller) + ament_target_dependencies( + test_bicycle_steering_controller_preceeding + controller_interface + hardware_interface + ) +endif() + +install( + DIRECTORY include/ + DESTINATION include/bicycle_steering_controller +) + +install( + TARGETS bicycle_steering_controller bicycle_steering_controller_parameters + EXPORT export_bicycle_steering_controller + RUNTIME DESTINATION bin + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib +) + +ament_export_targets(export_bicycle_steering_controller HAS_LIBRARY_TARGET) +ament_export_dependencies(${THIS_PACKAGE_INCLUDE_DEPENDS}) +ament_package() diff --git a/bicycle_steering_controller/bicycle_steering_controller.xml b/bicycle_steering_controller/bicycle_steering_controller.xml new file mode 100644 index 0000000000..644c8840fa --- /dev/null +++ b/bicycle_steering_controller/bicycle_steering_controller.xml @@ -0,0 +1,8 @@ + + + + Steering controller for Bicycle kinematics with one traction and one steering joint. + + + diff --git a/bicycle_steering_controller/doc/userdoc.rst b/bicycle_steering_controller/doc/userdoc.rst new file mode 100644 index 0000000000..6815dc6953 --- /dev/null +++ b/bicycle_steering_controller/doc/userdoc.rst @@ -0,0 +1,19 @@ +.. _bicycle_steering_controller_userdoc: + +bicycle_steering_controller +============================= + +This controller implements the kinematics with two axes and two wheels, where the wheel on one axis is fixed (traction/drive), and the wheel on the other axis is steerable. + +The controller expects to have one commanding joint for traction, and one commanding joint for steering. +If your Ackermann steering vehicle uses differentials on axes, then you should probably use this controller since you can command only one traction velocity and steering angle for virtual wheels in the middle of the axes. + +For more details on controller's execution and interfaces check the :ref:`Steering Controller Library `. + + +Parameters +,,,,,,,,,,, + +For list of parameters and their meaning YAML file in the ``src`` folder of the controller's package. + +For an exemplary parameterization see the ``test`` folder of the controller's package. diff --git a/bicycle_steering_controller/include/bicycle_steering_controller/bicycle_steering_controller.hpp b/bicycle_steering_controller/include/bicycle_steering_controller/bicycle_steering_controller.hpp new file mode 100644 index 0000000000..1b3e050a37 --- /dev/null +++ b/bicycle_steering_controller/include/bicycle_steering_controller/bicycle_steering_controller.hpp @@ -0,0 +1,61 @@ +// Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Authors: dr. sc. Tomislav Petkovic, Dr. Ing. Denis Štogl +// + +#ifndef BICYCLE_STEERING_CONTROLLER__BICYCLE_STEERING_CONTROLLER_HPP_ +#define BICYCLE_STEERING_CONTROLLER__BICYCLE_STEERING_CONTROLLER_HPP_ + +#include + +#include "bicycle_steering_controller/visibility_control.h" +#include "bicycle_steering_controller_parameters.hpp" +#include "steering_controllers_library/steering_controllers_library.hpp" + +namespace bicycle_steering_controller +{ +// name constants for state interfaces +static constexpr size_t STATE_TRACTION_WHEEL = 0; +static constexpr size_t STATE_STEER_AXIS = 1; + +// name constants for command interfaces +static constexpr size_t CMD_TRACTION_WHEEL = 0; +static constexpr size_t CMD_STEER_WHEEL = 1; + +static constexpr size_t NR_STATE_ITFS = 2; +static constexpr size_t NR_CMD_ITFS = 2; +static constexpr size_t NR_REF_ITFS = 2; + +class BicycleSteeringController : public steering_controllers_library::SteeringControllersLibrary +{ +public: + BicycleSteeringController(); + + BICYCLE_STEERING_CONTROLLER__VISIBILITY_PUBLIC controller_interface::CallbackReturn + configure_odometry() override; + + BICYCLE_STEERING_CONTROLLER__VISIBILITY_PUBLIC bool update_odometry( + const rclcpp::Duration & period) override; + + BICYCLE_STEERING_CONTROLLER__VISIBILITY_PUBLIC void initialize_implementation_parameter_listener() + override; + +protected: + std::shared_ptr bicycle_param_listener_; + bicycle_steering_controller::Params bicycle_params_; +}; +} // namespace bicycle_steering_controller + +#endif // BICYCLE_STEERING_CONTROLLER__BICYCLE_STEERING_CONTROLLER_HPP_ diff --git a/bicycle_steering_controller/include/bicycle_steering_controller/visibility_control.h b/bicycle_steering_controller/include/bicycle_steering_controller/visibility_control.h new file mode 100644 index 0000000000..b076a00215 --- /dev/null +++ b/bicycle_steering_controller/include/bicycle_steering_controller/visibility_control.h @@ -0,0 +1,52 @@ +// Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef BICYCLE_STEERING_CONTROLLER__VISIBILITY_CONTROL_H_ +#define BICYCLE_STEERING_CONTROLLER__VISIBILITY_CONTROL_H_ + +// This logic was borrowed (then namespaced) from the examples on the gcc wiki: +// https://gcc.gnu.org/wiki/Visibility + +#if defined _WIN32 || defined __CYGWIN__ +#ifdef __GNUC__ +#define BICYCLE_STEERING_CONTROLLER__VISIBILITY_EXPORT __attribute__((dllexport)) +#define BICYCLE_STEERING_CONTROLLER__VISIBILITY_IMPORT __attribute__((dllimport)) +#else +#define BICYCLE_STEERING_CONTROLLER__VISIBILITY_EXPORT __declspec(dllexport) +#define BICYCLE_STEERING_CONTROLLER__VISIBILITY_IMPORT __declspec(dllimport) +#endif +#ifdef BICYCLE_STEERING_CONTROLLER__VISIBILITY_BUILDING_DLL +#define BICYCLE_STEERING_CONTROLLER__VISIBILITY_PUBLIC \ + BICYCLE_STEERING_CONTROLLER__VISIBILITY_EXPORT +#else +#define BICYCLE_STEERING_CONTROLLER__VISIBILITY_PUBLIC \ + BICYCLE_STEERING_CONTROLLER__VISIBILITY_IMPORT +#endif +#define BICYCLE_STEERING_CONTROLLER__VISIBILITY_PUBLIC_TYPE \ + BICYCLE_STEERING_CONTROLLER__VISIBILITY_PUBLIC +#define BICYCLE_STEERING_CONTROLLER__VISIBILITY_LOCAL +#else +#define BICYCLE_STEERING_CONTROLLER__VISIBILITY_EXPORT __attribute__((visibility("default"))) +#define BICYCLE_STEERING_CONTROLLER__VISIBILITY_IMPORT +#if __GNUC__ >= 4 +#define BICYCLE_STEERING_CONTROLLER__VISIBILITY_PUBLIC __attribute__((visibility("default"))) +#define BICYCLE_STEERING_CONTROLLER__VISIBILITY_LOCAL __attribute__((visibility("hidden"))) +#else +#define BICYCLE_STEERING_CONTROLLER__VISIBILITY_PUBLIC +#define BICYCLE_STEERING_CONTROLLER__VISIBILITY_LOCAL +#endif +#define BICYCLE_STEERING_CONTROLLER__VISIBILITY_PUBLIC_TYPE +#endif + +#endif // BICYCLE_STEERING_CONTROLLER__VISIBILITY_CONTROL_H_ diff --git a/bicycle_steering_controller/package.xml b/bicycle_steering_controller/package.xml new file mode 100644 index 0000000000..80932f7fda --- /dev/null +++ b/bicycle_steering_controller/package.xml @@ -0,0 +1,36 @@ + + + + bicycle_steering_controller + 0.0.0 + Steering controller with bicycle kinematics. Rear fixed wheel is powering the vehicle and front wheel is steering. + Apache License 2.0 + Bence Magyar + Dr.-Ing. Denis Štogl + dr. sc. Tomislav Petkovic + + Dr.-Ing. Denis Štogl + dr. sc. Tomislav Petkovic + + ament_cmake + + generate_parameter_library + + control_msgs + controller_interface + hardware_interface + pluginlib + rclcpp + rclcpp_lifecycle + std_srvs + steering_controllers_library + + ament_cmake_gmock + controller_manager + hardware_interface + ros2_control_test_assets + + + ament_cmake + + diff --git a/bicycle_steering_controller/src/bicycle_steering_controller.cpp b/bicycle_steering_controller/src/bicycle_steering_controller.cpp new file mode 100644 index 0000000000..5f013d7d7a --- /dev/null +++ b/bicycle_steering_controller/src/bicycle_steering_controller.cpp @@ -0,0 +1,87 @@ +// Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "bicycle_steering_controller/bicycle_steering_controller.hpp" + +namespace bicycle_steering_controller +{ +BicycleSteeringController::BicycleSteeringController() +: steering_controllers_library::SteeringControllersLibrary() +{ +} + +void BicycleSteeringController::initialize_implementation_parameter_listener() +{ + bicycle_param_listener_ = + std::make_shared(get_node()); +} + +controller_interface::CallbackReturn BicycleSteeringController::configure_odometry() +{ + bicycle_params_ = bicycle_param_listener_->get_params(); + + const double wheelbase = bicycle_params_.wheelbase; + const double front_wheel_radius = bicycle_params_.front_wheel_radius; + const double rear_wheel_radius = bicycle_params_.rear_wheel_radius; + + if (params_.front_steering) + { + odometry_.set_wheel_params(rear_wheel_radius, wheelbase); + } + else + { + odometry_.set_wheel_params(front_wheel_radius, wheelbase); + } + + odometry_.set_odometry_type(steering_odometry::BICYCLE_CONFIG); + + set_interface_numbers(NR_STATE_ITFS, NR_CMD_ITFS, NR_REF_ITFS); + + RCLCPP_INFO(get_node()->get_logger(), "bicycle odometry configure successful"); + return controller_interface::CallbackReturn::SUCCESS; +} + +bool BicycleSteeringController::update_odometry(const rclcpp::Duration & period) +{ + if (params_.open_loop) + { + odometry_.update_open_loop(last_linear_velocity_, last_angular_velocity_, period.seconds()); + } + else + { + const double rear_wheel_value = state_interfaces_[STATE_TRACTION_WHEEL].get_value(); + const double steer_position = state_interfaces_[STATE_STEER_AXIS].get_value(); + if (!std::isnan(rear_wheel_value) && !std::isnan(steer_position)) + { + if (params_.position_feedback) + { + // Estimate linear and angular velocity using joint information + odometry_.update_from_position(rear_wheel_value, steer_position, period.seconds()); + } + else + { + // Estimate linear and angular velocity using joint information + odometry_.update_from_velocity(rear_wheel_value, steer_position, period.seconds()); + } + } + } + return true; +} +} // namespace bicycle_steering_controller + +#include "pluginlib/class_list_macros.hpp" + +PLUGINLIB_EXPORT_CLASS( + bicycle_steering_controller::BicycleSteeringController, + controller_interface::ChainableControllerInterface) diff --git a/bicycle_steering_controller/src/bicycle_steering_controller.yaml b/bicycle_steering_controller/src/bicycle_steering_controller.yaml new file mode 100644 index 0000000000..c40e27ef96 --- /dev/null +++ b/bicycle_steering_controller/src/bicycle_steering_controller.yaml @@ -0,0 +1,24 @@ +bicycle_steering_controller: + wheelbase: + { + type: double, + default_value: 0.0, + description: "Distance between front and rear wheel. For details see: https://en.wikipedia.org/wiki/Wheelbase", + read_only: false, + } + + front_wheel_radius: + { + type: double, + default_value: 0.0, + description: "Front wheel radius.", + read_only: false, + } + + rear_wheel_radius: + { + type: double, + default_value: 0.0, + description: "Rear wheel radius.", + read_only: false, + } diff --git a/bicycle_steering_controller/test/bicycle_steering_controller_params.yaml b/bicycle_steering_controller/test/bicycle_steering_controller_params.yaml new file mode 100644 index 0000000000..a2a6c6508b --- /dev/null +++ b/bicycle_steering_controller/test/bicycle_steering_controller_params.yaml @@ -0,0 +1,15 @@ +test_bicycle_steering_controller: + ros__parameters: + + reference_timeout: 2.0 + front_steering: true + open_loop: false + velocity_rolling_window_size: 10 + position_feedback: false + use_stamped_vel: true + rear_wheels_names: [rear_wheel_joint] + front_wheels_names: [steering_axis_joint] + + wheelbase: 3.24644 + front_wheel_radius: 0.45 + rear_wheel_radius: 0.45 diff --git a/bicycle_steering_controller/test/bicycle_steering_controller_preceeding_params.yaml b/bicycle_steering_controller/test/bicycle_steering_controller_preceeding_params.yaml new file mode 100644 index 0000000000..39ffeed878 --- /dev/null +++ b/bicycle_steering_controller/test/bicycle_steering_controller_preceeding_params.yaml @@ -0,0 +1,16 @@ +test_bicycle_steering_controller: + ros__parameters: + reference_timeout: 2.0 + front_steering: true + open_loop: false + velocity_rolling_window_size: 10 + position_feedback: false + use_stamped_vel: true + rear_wheels_names: [pid_controller/rear_wheel_joint] + front_wheels_names: [pid_controller/steering_axis_joint] + rear_wheels_state_names: [rear_wheel_joint] + front_wheels_state_names: [steering_axis_joint] + + wheelbase: 3.24644 + front_wheel_radius: 0.45 + rear_wheel_radius: 0.45 diff --git a/bicycle_steering_controller/test/test_bicycle_steering_controller.cpp b/bicycle_steering_controller/test/test_bicycle_steering_controller.cpp new file mode 100644 index 0000000000..06b0c7e846 --- /dev/null +++ b/bicycle_steering_controller/test/test_bicycle_steering_controller.cpp @@ -0,0 +1,266 @@ +// Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "test_bicycle_steering_controller.hpp" + +#include +#include +#include +#include +#include + +class BicycleSteeringControllerTest +: public BicycleSteeringControllerFixture +{ +}; + +TEST_F(BicycleSteeringControllerTest, all_parameters_set_configure_success) +{ + SetUpController(); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + + ASSERT_THAT( + controller_->params_.rear_wheels_names, testing::ElementsAreArray(rear_wheels_names_)); + ASSERT_THAT( + controller_->params_.front_wheels_names, testing::ElementsAreArray(front_wheels_names_)); + ASSERT_EQ(controller_->params_.front_steering, front_steering_); + ASSERT_EQ(controller_->params_.open_loop, open_loop_); + ASSERT_EQ(controller_->params_.velocity_rolling_window_size, velocity_rolling_window_size_); + ASSERT_EQ(controller_->params_.position_feedback, position_feedback_); + ASSERT_EQ(controller_->bicycle_params_.wheelbase, wheelbase_); + ASSERT_EQ(controller_->bicycle_params_.front_wheel_radius, front_wheels_radius_); + ASSERT_EQ(controller_->bicycle_params_.rear_wheel_radius, rear_wheels_radius_); +} + +TEST_F(BicycleSteeringControllerTest, check_exported_intefaces) +{ + SetUpController(); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + + auto command_intefaces = controller_->command_interface_configuration(); + ASSERT_EQ(command_intefaces.names.size(), joint_command_values_.size()); + EXPECT_EQ( + command_intefaces.names[CMD_TRACTION_WHEEL], + rear_wheels_names_[0] + "/" + traction_interface_name_); + EXPECT_EQ( + command_intefaces.names[CMD_STEER_WHEEL], + front_wheels_names_[0] + "/" + steering_interface_name_); + + auto state_intefaces = controller_->state_interface_configuration(); + ASSERT_EQ(state_intefaces.names.size(), joint_state_values_.size()); + EXPECT_EQ( + state_intefaces.names[STATE_TRACTION_WHEEL], + controller_->rear_wheels_state_names_[0] + "/" + traction_interface_name_); + EXPECT_EQ( + state_intefaces.names[STATE_STEER_AXIS], + controller_->front_wheels_state_names_[0] + "/" + steering_interface_name_); + + // check ref itfsTIME + auto reference_interfaces = controller_->export_reference_interfaces(); + ASSERT_EQ(reference_interfaces.size(), joint_reference_interfaces_.size()); + for (size_t i = 0; i < joint_reference_interfaces_.size(); ++i) + { + const std::string ref_itf_name = + std::string(controller_->get_node()->get_name()) + "/" + joint_reference_interfaces_[i]; + EXPECT_EQ(reference_interfaces[i].get_name(), ref_itf_name); + EXPECT_EQ(reference_interfaces[i].get_prefix_name(), controller_->get_node()->get_name()); + EXPECT_EQ(reference_interfaces[i].get_interface_name(), joint_reference_interfaces_[i]); + } +} + +TEST_F(BicycleSteeringControllerTest, activate_success) +{ + SetUpController(); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + + // check that the message is reset + auto msg = controller_->input_ref_.readFromNonRT(); + EXPECT_TRUE(std::isnan((*msg)->twist.linear.x)); + EXPECT_TRUE(std::isnan((*msg)->twist.linear.y)); + EXPECT_TRUE(std::isnan((*msg)->twist.linear.z)); + EXPECT_TRUE(std::isnan((*msg)->twist.angular.x)); + EXPECT_TRUE(std::isnan((*msg)->twist.angular.y)); + EXPECT_TRUE(std::isnan((*msg)->twist.angular.z)); +} + +TEST_F(BicycleSteeringControllerTest, update_success) +{ + SetUpController(); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + + ASSERT_EQ( + controller_->update(rclcpp::Time(0, 0, RCL_ROS_TIME), rclcpp::Duration::from_seconds(0.01)), + controller_interface::return_type::OK); +} + +TEST_F(BicycleSteeringControllerTest, deactivate_success) +{ + SetUpController(); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_EQ(controller_->on_deactivate(rclcpp_lifecycle::State()), NODE_SUCCESS); +} + +TEST_F(BicycleSteeringControllerTest, reactivate_success) +{ + SetUpController(); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_EQ(controller_->on_deactivate(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_TRUE(std::isnan(controller_->command_interfaces_[0].get_value())); + ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_TRUE(std::isnan(controller_->command_interfaces_[0].get_value())); + + ASSERT_EQ( + controller_->update(rclcpp::Time(0, 0, RCL_ROS_TIME), rclcpp::Duration::from_seconds(0.01)), + controller_interface::return_type::OK); +} + +TEST_F(BicycleSteeringControllerTest, test_update_logic) +{ + SetUpController(); + rclcpp::executors::MultiThreadedExecutor executor; + executor.add_node(controller_->get_node()->get_node_base_interface()); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + controller_->set_chained_mode(false); + ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_FALSE(controller_->is_in_chained_mode()); + + // set command statically + std::shared_ptr msg = std::make_shared(); + msg->header.stamp = controller_->get_node()->now(); + msg->twist.linear.x = 0.1; + msg->twist.angular.z = 0.2; + controller_->input_ref_.writeFromNonRT(msg); + + ASSERT_EQ( + controller_->update(rclcpp::Time(0, 0, RCL_ROS_TIME), rclcpp::Duration::from_seconds(0.01)), + controller_interface::return_type::OK); + + EXPECT_NEAR( + controller_->command_interfaces_[CMD_TRACTION_WHEEL].get_value(), 0.253221, COMMON_THRESHOLD); + EXPECT_NEAR( + controller_->command_interfaces_[CMD_STEER_WHEEL].get_value(), 1.4179821977774734, + COMMON_THRESHOLD); + + EXPECT_FALSE(std::isnan((*(controller_->input_ref_.readFromRT()))->twist.linear.x)); + EXPECT_EQ(controller_->reference_interfaces_.size(), joint_reference_interfaces_.size()); + for (const auto & interface : controller_->reference_interfaces_) + { + EXPECT_TRUE(std::isnan(interface)); + } +} + +TEST_F(BicycleSteeringControllerTest, test_update_logic_chained) +{ + SetUpController(); + rclcpp::executors::MultiThreadedExecutor executor; + executor.add_node(controller_->get_node()->get_node_base_interface()); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + controller_->set_chained_mode(true); + ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_TRUE(controller_->is_in_chained_mode()); + + controller_->reference_interfaces_[0] = 0.1; + controller_->reference_interfaces_[1] = 0.2; + + ASSERT_EQ( + controller_->update(rclcpp::Time(0, 0, RCL_ROS_TIME), rclcpp::Duration::from_seconds(0.01)), + controller_interface::return_type::OK); + + EXPECT_NEAR( + controller_->command_interfaces_[CMD_TRACTION_WHEEL].get_value(), 0.253221, COMMON_THRESHOLD); + EXPECT_NEAR( + controller_->command_interfaces_[CMD_STEER_WHEEL].get_value(), 1.4179821977774734, + COMMON_THRESHOLD); + + EXPECT_TRUE(std::isnan((*(controller_->input_ref_.readFromRT()))->twist.linear.x)); + EXPECT_EQ(controller_->reference_interfaces_.size(), joint_reference_interfaces_.size()); + for (const auto & interface : controller_->reference_interfaces_) + { + EXPECT_TRUE(std::isnan(interface)); + } +} + +TEST_F(BicycleSteeringControllerTest, publish_status_success) +{ + SetUpController(); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + + ASSERT_EQ( + controller_->update(rclcpp::Time(0, 0, RCL_ROS_TIME), rclcpp::Duration::from_seconds(0.01)), + controller_interface::return_type::OK); + + ControllerStateMsg msg; + subscribe_and_get_messages(msg); +} + +TEST_F(BicycleSteeringControllerTest, receive_message_and_publish_updated_status) +{ + SetUpController(); + rclcpp::executors::MultiThreadedExecutor executor; + executor.add_node(controller_->get_node()->get_node_base_interface()); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + + ASSERT_EQ( + controller_->update(rclcpp::Time(0, 0, RCL_ROS_TIME), rclcpp::Duration::from_seconds(0.01)), + controller_interface::return_type::OK); + + ControllerStateMsg msg; + subscribe_and_get_messages(msg); + + EXPECT_EQ(msg.linear_velocity_command[0], 1.1); + EXPECT_EQ(msg.steering_angle_command[0], 2.2); + + publish_commands(); + ASSERT_TRUE(controller_->wait_for_commands(executor)); + + ASSERT_EQ( + controller_->update(rclcpp::Time(0, 0, RCL_ROS_TIME), rclcpp::Duration::from_seconds(0.01)), + controller_interface::return_type::OK); + + EXPECT_NEAR( + controller_->command_interfaces_[CMD_TRACTION_WHEEL].get_value(), 0.253221, COMMON_THRESHOLD); + EXPECT_NEAR( + controller_->command_interfaces_[CMD_STEER_WHEEL].get_value(), 1.4179821977774734, + COMMON_THRESHOLD); + + subscribe_and_get_messages(msg); + + EXPECT_NEAR(msg.linear_velocity_command[0], 0.253221, COMMON_THRESHOLD); + EXPECT_NEAR(msg.steering_angle_command[0], 1.4179821977774734, COMMON_THRESHOLD); +} + +int main(int argc, char ** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + rclcpp::init(argc, argv); + int result = RUN_ALL_TESTS(); + rclcpp::shutdown(); + return result; +} diff --git a/bicycle_steering_controller/test/test_bicycle_steering_controller.hpp b/bicycle_steering_controller/test/test_bicycle_steering_controller.hpp new file mode 100644 index 0000000000..065f9e1a0d --- /dev/null +++ b/bicycle_steering_controller/test/test_bicycle_steering_controller.hpp @@ -0,0 +1,284 @@ +// Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef TEST_BICYCLE_STEERING_CONTROLLER_HPP_ +#define TEST_BICYCLE_STEERING_CONTROLLER_HPP_ + +#include +#include +#include +#include +#include +#include +#include + +#include "bicycle_steering_controller/bicycle_steering_controller.hpp" +#include "gmock/gmock.h" +#include "hardware_interface/loaned_command_interface.hpp" +#include "hardware_interface/loaned_state_interface.hpp" +#include "hardware_interface/types/hardware_interface_return_values.hpp" +#include "rclcpp/parameter_value.hpp" +#include "rclcpp/time.hpp" +#include "rclcpp/utilities.hpp" +#include "rclcpp_lifecycle/node_interfaces/lifecycle_node_interface.hpp" + +using ControllerStateMsg = + steering_controllers_library::SteeringControllersLibrary::AckermanControllerState; +using ControllerReferenceMsg = + steering_controllers_library::SteeringControllersLibrary::ControllerTwistReferenceMsg; + +// name constants for state interfaces +using bicycle_steering_controller::STATE_STEER_AXIS; +using bicycle_steering_controller::STATE_TRACTION_WHEEL; + +// name constants for command interfaces +using bicycle_steering_controller::CMD_STEER_WHEEL; +using bicycle_steering_controller::CMD_TRACTION_WHEEL; + +namespace +{ +constexpr auto NODE_SUCCESS = controller_interface::CallbackReturn::SUCCESS; +constexpr auto NODE_ERROR = controller_interface::CallbackReturn::ERROR; +const double COMMON_THRESHOLD = 1e-6; + +} // namespace +// namespace + +// subclassing and friending so we can access member variables +class TestableBicycleSteeringController +: public bicycle_steering_controller::BicycleSteeringController +{ + FRIEND_TEST(BicycleSteeringControllerTest, all_parameters_set_configure_success); + FRIEND_TEST(BicycleSteeringControllerTest, check_exported_intefaces); + FRIEND_TEST(BicycleSteeringControllerTest, activate_success); + FRIEND_TEST(BicycleSteeringControllerTest, update_success); + FRIEND_TEST(BicycleSteeringControllerTest, deactivate_success); + FRIEND_TEST(BicycleSteeringControllerTest, reactivate_success); + FRIEND_TEST(BicycleSteeringControllerTest, test_update_logic); + FRIEND_TEST(BicycleSteeringControllerTest, test_update_logic_chained); + FRIEND_TEST(BicycleSteeringControllerTest, publish_status_success); + FRIEND_TEST(BicycleSteeringControllerTest, receive_message_and_publish_updated_status); + +public: + controller_interface::CallbackReturn on_configure( + const rclcpp_lifecycle::State & previous_state) override + { + auto ret = bicycle_steering_controller::BicycleSteeringController::on_configure(previous_state); + // Only if on_configure is successful create subscription + if (ret == CallbackReturn::SUCCESS) + { + ref_subscriber_wait_set_.add_subscription(ref_subscriber_twist_); + } + return ret; + } + + controller_interface::CallbackReturn on_activate( + const rclcpp_lifecycle::State & previous_state) override + { + auto ref_itfs = on_export_reference_interfaces(); + return bicycle_steering_controller::BicycleSteeringController::on_activate(previous_state); + } + + /** + * @brief wait_for_command blocks until a new ControllerReferenceMsg is received. + * Requires that the executor is not spinned elsewhere between the + * message publication and the call to this function. + * + * @return true if new ControllerReferenceMsg msg was received, false if timeout. + */ + bool wait_for_command( + rclcpp::Executor & executor, rclcpp::WaitSet & subscriber_wait_set, + const std::chrono::milliseconds & timeout = std::chrono::milliseconds{500}) + { + bool success = subscriber_wait_set.wait(timeout).kind() == rclcpp::WaitResultKind::Ready; + if (success) + { + executor.spin_some(); + } + return success; + } + + bool wait_for_commands( + rclcpp::Executor & executor, + const std::chrono::milliseconds & timeout = std::chrono::milliseconds{500}) + { + return wait_for_command(executor, ref_subscriber_wait_set_, timeout); + } + +private: + rclcpp::WaitSet ref_subscriber_wait_set_; +}; + +// We are using template class here for easier reuse of Fixture in specializations of controllers +template +class BicycleSteeringControllerFixture : public ::testing::Test +{ +public: + static void SetUpTestCase() {} + + void SetUp() + { + // initialize controller + controller_ = std::make_unique(); + + command_publisher_node_ = std::make_shared("command_publisher"); + command_publisher_ = command_publisher_node_->create_publisher( + "/test_bicycle_steering_controller/reference", rclcpp::SystemDefaultsQoS()); + } + + static void TearDownTestCase() {} + + void TearDown() { controller_.reset(nullptr); } + +protected: + void SetUpController(const std::string controller_name = "test_bicycle_steering_controller") + { + ASSERT_EQ(controller_->init(controller_name), controller_interface::return_type::OK); + + if (position_feedback_ == true) + { + traction_interface_name_ = "position"; + } + else + { + traction_interface_name_ = "velocity"; + } + + std::vector command_ifs; + command_itfs_.reserve(joint_command_values_.size()); + command_ifs.reserve(joint_command_values_.size()); + + command_itfs_.emplace_back(hardware_interface::CommandInterface( + rear_wheels_names_[0], traction_interface_name_, &joint_command_values_[CMD_TRACTION_WHEEL])); + command_ifs.emplace_back(command_itfs_.back()); + + command_itfs_.emplace_back(hardware_interface::CommandInterface( + front_wheels_names_[0], steering_interface_name_, &joint_command_values_[CMD_STEER_WHEEL])); + command_ifs.emplace_back(command_itfs_.back()); + + std::vector state_ifs; + state_itfs_.reserve(joint_state_values_.size()); + state_ifs.reserve(joint_state_values_.size()); + + state_itfs_.emplace_back(hardware_interface::StateInterface( + rear_wheels_names_[0], traction_interface_name_, &joint_state_values_[STATE_TRACTION_WHEEL])); + state_ifs.emplace_back(state_itfs_.back()); + + state_itfs_.emplace_back(hardware_interface::StateInterface( + front_wheels_names_[0], steering_interface_name_, &joint_state_values_[STATE_STEER_AXIS])); + state_ifs.emplace_back(state_itfs_.back()); + + controller_->assign_interfaces(std::move(command_ifs), std::move(state_ifs)); + } + + void subscribe_and_get_messages(ControllerStateMsg & msg) + { + // create a new subscriber + rclcpp::Node test_subscription_node("test_subscription_node"); + auto subs_callback = [&](const ControllerStateMsg::SharedPtr) {}; + auto subscription = test_subscription_node.create_subscription( + "/test_bicycle_steering_controller/controller_state", 10, subs_callback); + + // call update to publish the test value + ASSERT_EQ( + controller_->update(rclcpp::Time(0, 0, RCL_ROS_TIME), rclcpp::Duration::from_seconds(0.01)), + controller_interface::return_type::OK); + // since update doesn't guarantee a published message, republish until received + int max_sub_check_loop_count = 5; // max number of tries for pub/sub loop + rclcpp::WaitSet wait_set; // block used to wait on max_sub_check_loop_count + wait_set.add_subscription(subscription); + while (max_sub_check_loop_count--) + { + controller_->update(rclcpp::Time(0, 0, RCL_ROS_TIME), rclcpp::Duration::from_seconds(0.01)); + // check if message has been received + if (wait_set.wait(std::chrono::milliseconds(2)).kind() == rclcpp::WaitResultKind::Ready) + { + break; + } + } + ASSERT_GE(max_sub_check_loop_count, 0) << "Test was unable to publish a message through " + "controller/broadcaster update loop"; + + // take message from subscription + rclcpp::MessageInfo msg_info; + ASSERT_TRUE(subscription->take(msg, msg_info)); + } + + void publish_commands(const double linear = 0.1, const double angular = 0.2) + { + auto wait_for_topic = [&](const auto topic_name) + { + size_t wait_count = 0; + while (command_publisher_node_->count_subscribers(topic_name) == 0) + { + if (wait_count >= 5) + { + auto error_msg = + std::string("publishing to ") + topic_name + " but no node subscribes to it"; + throw std::runtime_error(error_msg); + } + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + ++wait_count; + } + }; + + wait_for_topic(command_publisher_->get_topic_name()); + + ControllerReferenceMsg msg; + msg.twist.linear.x = linear; + msg.twist.angular.z = angular; + + command_publisher_->publish(msg); + } + +protected: + // Controller-related parameters + double reference_timeout_ = 2.0; + bool front_steering_ = true; + bool open_loop_ = false; + unsigned int velocity_rolling_window_size_ = 10; + bool position_feedback_ = false; + bool use_stamped_vel_ = true; + std::vector rear_wheels_names_ = {"rear_wheel_joint"}; + std::vector front_wheels_names_ = {"steering_axis_joint"}; + std::vector joint_names_ = {rear_wheels_names_[0], front_wheels_names_[0]}; + + std::vector rear_wheels_preceeding_names_ = {"pid_controller/rear_wheel_joint"}; + std::vector front_wheels_preceeding_names_ = {"pid_controller/steering_axis_joint"}; + std::vector preceeding_joint_names_ = { + rear_wheels_preceeding_names_[0], front_wheels_preceeding_names_[0]}; + + double wheelbase_ = 3.24644; + double front_wheels_radius_ = 0.45; + double rear_wheels_radius_ = 0.45; + + std::array joint_state_values_ = {3.3, 0.5}; + std::array joint_command_values_ = {1.1, 2.2}; + std::array joint_reference_interfaces_ = {"linear/velocity", "angular/position"}; + std::string steering_interface_name_ = "position"; + + // defined in setup + std::string traction_interface_name_ = ""; + std::string preceeding_prefix_ = "pid_controller"; + + std::vector state_itfs_; + std::vector command_itfs_; + + // Test related parameters + std::unique_ptr controller_; + rclcpp::Node::SharedPtr command_publisher_node_; + rclcpp::Publisher::SharedPtr command_publisher_; +}; + +#endif // TEST_BICYCLE_STEERING_CONTROLLER_HPP_ diff --git a/bicycle_steering_controller/test/test_bicycle_steering_controller_preceeding.cpp b/bicycle_steering_controller/test/test_bicycle_steering_controller_preceeding.cpp new file mode 100644 index 0000000000..875910ba23 --- /dev/null +++ b/bicycle_steering_controller/test/test_bicycle_steering_controller_preceeding.cpp @@ -0,0 +1,95 @@ +// Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "test_bicycle_steering_controller.hpp" + +#include +#include +#include +#include +#include + +class BicycleSteeringControllerTest +: public BicycleSteeringControllerFixture +{ +}; + +TEST_F(BicycleSteeringControllerTest, all_parameters_set_configure_success) +{ + SetUpController(); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + + ASSERT_THAT( + controller_->params_.rear_wheels_names, + testing::ElementsAreArray(rear_wheels_preceeding_names_)); + ASSERT_THAT( + controller_->params_.front_wheels_names, + testing::ElementsAreArray(front_wheels_preceeding_names_)); + ASSERT_EQ(controller_->params_.front_steering, front_steering_); + ASSERT_EQ(controller_->params_.open_loop, open_loop_); + ASSERT_EQ(controller_->params_.velocity_rolling_window_size, velocity_rolling_window_size_); + ASSERT_EQ(controller_->params_.position_feedback, position_feedback_); + ASSERT_EQ(controller_->bicycle_params_.wheelbase, wheelbase_); + ASSERT_EQ(controller_->bicycle_params_.front_wheel_radius, front_wheels_radius_); + ASSERT_EQ(controller_->bicycle_params_.rear_wheel_radius, rear_wheels_radius_); +} + +TEST_F(BicycleSteeringControllerTest, check_exported_intefaces) +{ + SetUpController(); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + + auto command_intefaces = controller_->command_interface_configuration(); + ASSERT_EQ(command_intefaces.names.size(), joint_command_values_.size()); + EXPECT_EQ( + command_intefaces.names[CMD_TRACTION_WHEEL], + preceeding_prefix_ + "/" + rear_wheels_names_[0] + "/" + traction_interface_name_); + + EXPECT_EQ( + command_intefaces.names[CMD_STEER_WHEEL], + preceeding_prefix_ + "/" + front_wheels_names_[0] + "/" + steering_interface_name_); + + auto state_intefaces = controller_->state_interface_configuration(); + ASSERT_EQ(state_intefaces.names.size(), joint_state_values_.size()); + + EXPECT_EQ( + state_intefaces.names[STATE_TRACTION_WHEEL], + controller_->rear_wheels_state_names_[0] + "/" + traction_interface_name_); + EXPECT_EQ( + state_intefaces.names[STATE_STEER_AXIS], + controller_->front_wheels_state_names_[0] + "/" + steering_interface_name_); + + // check ref itfs + auto reference_interfaces = controller_->export_reference_interfaces(); + ASSERT_EQ(reference_interfaces.size(), joint_reference_interfaces_.size()); + for (size_t i = 0; i < joint_reference_interfaces_.size(); ++i) + { + const std::string ref_itf_name = + std::string(controller_->get_node()->get_name()) + "/" + joint_reference_interfaces_[i]; + EXPECT_EQ(reference_interfaces[i].get_name(), ref_itf_name); + EXPECT_EQ(reference_interfaces[i].get_prefix_name(), controller_->get_node()->get_name()); + EXPECT_EQ(reference_interfaces[i].get_interface_name(), joint_reference_interfaces_[i]); + } +} + +int main(int argc, char ** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + rclcpp::init(argc, argv); + int result = RUN_ALL_TESTS(); + rclcpp::shutdown(); + return result; +} diff --git a/bicycle_steering_controller/test/test_load_bicycle_steering_controller.cpp b/bicycle_steering_controller/test/test_load_bicycle_steering_controller.cpp new file mode 100644 index 0000000000..955feb33c5 --- /dev/null +++ b/bicycle_steering_controller/test/test_load_bicycle_steering_controller.cpp @@ -0,0 +1,48 @@ +// Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include + +#include "controller_manager/controller_manager.hpp" +#include "hardware_interface/resource_manager.hpp" +#include "rclcpp/executor.hpp" +#include "rclcpp/executors/single_threaded_executor.hpp" +#include "rclcpp/utilities.hpp" +#include "ros2_control_test_assets/descriptions.hpp" + +TEST(TestLoadBicycleSteeringController, load_controller) +{ + std::shared_ptr executor = + std::make_shared(); + + controller_manager::ControllerManager cm( + std::make_unique( + ros2_control_test_assets::minimal_robot_urdf), + executor, "test_controller_manager"); + + ASSERT_NE( + cm.load_controller( + "test_bicycle_steering_controller", "bicycle_steering_controller/BicycleSteeringController"), + nullptr); +} + +int main(int argc, char ** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + rclcpp::init(argc, argv); + int result = RUN_ALL_TESTS(); + rclcpp::shutdown(); + return result; +} diff --git a/doc/controllers_index.rst b/doc/controllers_index.rst index effe814325..cb5528bdb0 100644 --- a/doc/controllers_index.rst +++ b/doc/controllers_index.rst @@ -42,14 +42,19 @@ Available Controllers .. toctree:: :titlesonly: + Ackermann Steering Controller <../ackermann_steering_controller/doc/userdoc.rst> Admittance Controller <../admittance_controller/doc/userdoc.rst> + Bicycle Steering Controller <../bicycle_steering_controller/doc/userdoc.rst> Differential Drive Controller <../diff_drive_controller/doc/userdoc.rst> Effort Controllers <../effort_controllers/doc/userdoc.rst> Forward Command Controller <../forward_command_controller/doc/userdoc.rst> Joint Trajectory Controller <../joint_trajectory_controller/doc/userdoc.rst> Position Controllers <../position_controllers/doc/userdoc.rst> Tricycle Controller <../tricycle_controller/doc/userdoc.rst> + Tricycle Steering Controller <../tricycle_steering_controller/doc/userdoc.rst> Velocity Controllers <../velocity_controllers/doc/userdoc.rst> + Effort Controllers <../effort_controllers/doc/userdoc.rst> + Steering Controllers Library <../steering_controllers_library/doc/userdoc.rst> Available Broadcasters diff --git a/ros2_controllers/package.xml b/ros2_controllers/package.xml index b2150411d8..ffdcc89d1a 100644 --- a/ros2_controllers/package.xml +++ b/ros2_controllers/package.xml @@ -10,7 +10,9 @@ ament_cmake + ackermann_steering_controller admittance_controller + bicycle_steering_controller diff_drive_controller effort_controllers force_torque_sensor_broadcaster @@ -19,7 +21,9 @@ joint_state_broadcaster joint_trajectory_controller position_controllers + steering_controllers_library tricycle_controller + tricycle_steering_controller velocity_controllers diff --git a/steering_controllers_library/CMakeLists.txt b/steering_controllers_library/CMakeLists.txt new file mode 100644 index 0000000000..5fdd727188 --- /dev/null +++ b/steering_controllers_library/CMakeLists.txt @@ -0,0 +1,88 @@ +cmake_minimum_required(VERSION 3.16) +project(steering_controllers_library LANGUAGES CXX) + +if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +# find dependencies +set(THIS_PACKAGE_INCLUDE_DEPENDS + control_msgs + controller_interface + generate_parameter_library + geometry_msgs + hardware_interface + nav_msgs + pluginlib + rclcpp + rclcpp_lifecycle + realtime_tools + std_srvs + tf2 + tf2_msgs + tf2_geometry_msgs + ackermann_msgs +) + +find_package(ament_cmake REQUIRED) +find_package(backward_ros REQUIRED) +foreach(Dependency IN ITEMS ${THIS_PACKAGE_INCLUDE_DEPENDS}) + find_package(${Dependency} REQUIRED) +endforeach() + +generate_parameter_library(steering_controllers_library_parameters + src/steering_controllers_library.yaml +) + +add_library( + steering_controllers_library + SHARED + src/steering_controllers_library.cpp + src/steering_odometry.cpp +) +target_compile_features(steering_controllers_library PUBLIC cxx_std_17) +target_include_directories(steering_controllers_library PUBLIC + "$" + "$") +target_link_libraries(steering_controllers_library PUBLIC + steering_controllers_library_parameters) +ament_target_dependencies(steering_controllers_library PUBLIC ${THIS_PACKAGE_INCLUDE_DEPENDS}) + +# Causes the visibility macros to use dllexport rather than dllimport, +# which is appropriate when building the dll but not consuming it. +target_compile_definitions(steering_controllers_library PRIVATE "STEERING_CONTROLLERS_BUILDING_DLL") + +if(BUILD_TESTING) + find_package(ament_cmake_gmock REQUIRED) + find_package(controller_manager REQUIRED) + find_package(hardware_interface REQUIRED) + find_package(ros2_control_test_assets REQUIRED) + + add_rostest_with_parameters_gmock( + test_steering_controllers_library test/test_steering_controllers_library.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test/steering_controllers_library_params.yaml) + target_include_directories(test_steering_controllers_library PRIVATE include) + target_link_libraries(test_steering_controllers_library steering_controllers_library) + ament_target_dependencies( + test_steering_controllers_library + controller_interface + hardware_interface + ) +endif() + +install( + DIRECTORY include/ + DESTINATION include/steering_controllers_library +) + +install( + TARGETS steering_controllers_library steering_controllers_library_parameters + EXPORT export_steering_controllers_library + RUNTIME DESTINATION bin + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib +) + +ament_export_targets(export_steering_controllers_library HAS_LIBRARY_TARGET) +ament_export_dependencies(${THIS_PACKAGE_INCLUDE_DEPENDS}) +ament_package() diff --git a/steering_controllers_library/doc/userdoc.rst b/steering_controllers_library/doc/userdoc.rst new file mode 100644 index 0000000000..27133e2e77 --- /dev/null +++ b/steering_controllers_library/doc/userdoc.rst @@ -0,0 +1,90 @@ +.. _steering_controllers_library_userdoc: + +steering_controllers_library +============================= + +Library with shared functionalities for mobile robot controllers with steering drive (2 degrees of freedom). +The library implements generic odometry and update methods and defines the main interfaces. + +Nomenclature used for the controller is used from `wikipedia `_. + +Execution logic of the controller +---------------------------------- + +The controller uses velocity input, i.e., stamped or unstamped Twist messages where linear ``x`` and angular ``z`` components are used. +Angular component under +Values in other components are ignored. +In the chain mode the controller provides two reference interfaces, one for linear velocity and one for steering angle position. +Other relevant features are: + +* support for front and rear steering configurations; +* odometry publishing as Odometry and TF message; +* input command timeout based on a parameter. + +The command for the wheels are calculated using ``odometry`` library where based on concrete kinematics traction and steering commands are calculated. +Currently implemented kinematics in corresponding packages are: + +* :ref:`Bicycle ` - with one steering and one drive joints; +* :ref:`Tricylce ` - with one steering and two drive joints; +* :ref:`Ackermann ` - with two seering and two drive joints. + + + +Description of controller's interfaces +-------------------------------------- + +References (from a preceding controller) +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +- /linear/velocity [double], in m/s +- /angular/position [double] # in [rad] + +Commands +,,,,,,,,, +``front_steering == true`` + +- /position [double] # in [rad] +- /velocity [double] # in [m/s] + +``front_steering == false`` + +- /velocity [double] # in [m/s] +- /position [double] # in [rad] + +States +,,,,,,, +Depending on the ``position_feedback``, different feedback types are expected + +* ``position_feedback == true`` --> ``TRACTION_FEEDBACK_TYPE = position`` +* ``position_feedback == false`` --> ``TRACTION_FEEDBACK_TYPE = velocity`` + +``front_steering == true`` + +- /position [double] # in [rad] +- / [double] # in [m] or [m/s] + +``front_steering == false`` + +- / [double] # [m] or [m/s] +- /position [double] # in [rad] + +Subscribers +,,,,,,,,,,,, +Used when controller is not in chained mode (``in_chained_mode == false``). + +- /reference [geometry_msgs/msg/TwistStamped] + If parameter ``use_stamped_vel`` is ``true``. +- /reference_unstamped [geometry_msgs/msg/Twist] + If parameter ``use_stamped_vel`` is ``false``. + +Publishers +,,,,,,,,,,, +- /odometry [nav_msgs/msg/Odometry] +- /tf_odometry [tf2_msgs/msg/TFMessage] +- /controller_state [control_msgs/msg/SteeringControllerStatus] + +Parameters +,,,,,,,,,,, + +For list of parameters and their meaning YAML file in the ``src`` folder of the controller's package. + +For an exemplary parameterization see the ``test`` folder of the controller's package. diff --git a/steering_controllers_library/include/steering_controllers_library/steering_controllers_library.hpp b/steering_controllers_library/include/steering_controllers_library/steering_controllers_library.hpp new file mode 100644 index 0000000000..b560e2a782 --- /dev/null +++ b/steering_controllers_library/include/steering_controllers_library/steering_controllers_library.hpp @@ -0,0 +1,151 @@ +// Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef STEERING_CONTROLLERS_LIBRARY__STEERING_CONTROLLERS_LIBRARY_HPP_ +#define STEERING_CONTROLLERS_LIBRARY__STEERING_CONTROLLERS_LIBRARY_HPP_ + +#include +#include +#include +#include +#include +#include +#include + +#include "controller_interface/chainable_controller_interface.hpp" +#include "hardware_interface/handle.hpp" +#include "rclcpp_lifecycle/node_interfaces/lifecycle_node_interface.hpp" +#include "rclcpp_lifecycle/state.hpp" +#include "realtime_tools/realtime_buffer.h" +#include "realtime_tools/realtime_publisher.h" +#include "std_srvs/srv/set_bool.hpp" +#include "steering_controllers_library/steering_odometry.hpp" +#include "steering_controllers_library/visibility_control.h" +#include "steering_controllers_library_parameters.hpp" + +// TODO(anyone): Replace with controller specific messages +#include "ackermann_msgs/msg/ackermann_drive_stamped.hpp" +#include "control_msgs/msg/steering_controller_status.hpp" +#include "geometry_msgs/msg/twist.hpp" +#include "geometry_msgs/msg/twist_stamped.hpp" +#include "nav_msgs/msg/odometry.hpp" +#include "tf2_msgs/msg/tf_message.hpp" + +namespace steering_controllers_library +{ +class SteeringControllersLibrary : public controller_interface::ChainableControllerInterface +{ +public: + STEERING_CONTROLLERS__VISIBILITY_PUBLIC SteeringControllersLibrary(); + + virtual STEERING_CONTROLLERS__VISIBILITY_PUBLIC void + initialize_implementation_parameter_listener() = 0; + + STEERING_CONTROLLERS__VISIBILITY_PUBLIC controller_interface::CallbackReturn on_init() override; + + STEERING_CONTROLLERS__VISIBILITY_PUBLIC controller_interface::InterfaceConfiguration + command_interface_configuration() const override; + + STEERING_CONTROLLERS__VISIBILITY_PUBLIC controller_interface::InterfaceConfiguration + state_interface_configuration() const override; + + virtual STEERING_CONTROLLERS__VISIBILITY_PUBLIC controller_interface::CallbackReturn + configure_odometry() = 0; + + virtual STEERING_CONTROLLERS__VISIBILITY_PUBLIC bool update_odometry( + const rclcpp::Duration & period) = 0; + + STEERING_CONTROLLERS__VISIBILITY_PUBLIC controller_interface::CallbackReturn on_configure( + const rclcpp_lifecycle::State & previous_state) override; + + STEERING_CONTROLLERS__VISIBILITY_PUBLIC controller_interface::CallbackReturn on_activate( + const rclcpp_lifecycle::State & previous_state) override; + + STEERING_CONTROLLERS__VISIBILITY_PUBLIC controller_interface::CallbackReturn on_deactivate( + const rclcpp_lifecycle::State & previous_state) override; + + STEERING_CONTROLLERS__VISIBILITY_PUBLIC controller_interface::return_type + update_reference_from_subscribers( + const rclcpp::Time & time, const rclcpp::Duration & period) override; + + STEERING_CONTROLLERS__VISIBILITY_PUBLIC controller_interface::return_type + update_and_write_commands(const rclcpp::Time & time, const rclcpp::Duration & period) override; + + using ControllerAckermannReferenceMsg = ackermann_msgs::msg::AckermannDriveStamped; + using ControllerTwistReferenceMsg = geometry_msgs::msg::TwistStamped; + using ControllerStateMsgOdom = nav_msgs::msg::Odometry; + using ControllerStateMsgTf = tf2_msgs::msg::TFMessage; + using AckermanControllerState = control_msgs::msg::SteeringControllerStatus; + +protected: + controller_interface::CallbackReturn set_interface_numbers( + size_t nr_state_itfs, size_t nr_cmd_itfs, size_t nr_ref_itfs); + + std::shared_ptr param_listener_; + steering_controllers_library::Params params_; + + // Command subscribers and Controller State publisher + rclcpp::Subscription::SharedPtr ref_subscriber_twist_ = nullptr; + rclcpp::Subscription::SharedPtr ref_subscriber_ackermann_ = nullptr; + rclcpp::Subscription::SharedPtr ref_subscriber_unstamped_ = nullptr; + realtime_tools::RealtimeBuffer> input_ref_; + rclcpp::Duration ref_timeout_ = rclcpp::Duration::from_seconds(0.0); // 0ms + + using ControllerStatePublisherOdom = realtime_tools::RealtimePublisher; + using ControllerStatePublisherTf = realtime_tools::RealtimePublisher; + + rclcpp::Publisher::SharedPtr odom_s_publisher_; + rclcpp::Publisher::SharedPtr tf_odom_s_publisher_; + + std::unique_ptr rt_odom_state_publisher_; + std::unique_ptr rt_tf_odom_state_publisher_; + + // override methods from ChainableControllerInterface + std::vector on_export_reference_interfaces() override; + + bool on_set_chained_mode(bool chained_mode) override; + + /// Odometry: + steering_odometry::SteeringOdometry odometry_; + + AckermanControllerState published_state_; + + using ControllerStatePublisher = realtime_tools::RealtimePublisher; + rclcpp::Publisher::SharedPtr controller_s_publisher_; + std::unique_ptr controller_state_publisher_; + + // name constants for state interfaces + size_t nr_state_itfs_; + // name constants for command interfaces + size_t nr_cmd_itfs_; + // name constants for reference interfaces + size_t nr_ref_itfs_; + + // store last velocity + double last_linear_velocity_ = 0.0; + double last_angular_velocity_ = 0.0; + + std::vector rear_wheels_state_names_; + std::vector front_wheels_state_names_; + +private: + // callback for topic interface + STEERING_CONTROLLERS__VISIBILITY_LOCAL void reference_callback( + const std::shared_ptr msg); + void reference_callback_unstamped(const std::shared_ptr msg); +}; + +} // namespace steering_controllers_library + +#endif // STEERING_CONTROLLERS_LIBRARY__STEERING_CONTROLLERS_LIBRARY_HPP_ diff --git a/steering_controllers_library/include/steering_controllers_library/steering_odometry.hpp b/steering_controllers_library/include/steering_controllers_library/steering_odometry.hpp new file mode 100644 index 0000000000..002db32354 --- /dev/null +++ b/steering_controllers_library/include/steering_controllers_library/steering_odometry.hpp @@ -0,0 +1,261 @@ +// Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Authors: dr. sc. Tomislav Petkovic, Dr. Ing. Denis Štogl +// + +#ifndef STEERING_CONTROLLERS_LIBRARY__STEERING_ODOMETRY_HPP_ +#define STEERING_CONTROLLERS_LIBRARY__STEERING_ODOMETRY_HPP_ + +#include +#include + +#include "realtime_tools/realtime_buffer.h" +#include "realtime_tools/realtime_publisher.h" + +#include +#include "rcpputils/rolling_mean_accumulator.hpp" + +namespace steering_odometry +{ +const unsigned int BICYCLE_CONFIG = 0; +const unsigned int TRICYCLE_CONFIG = 1; +const unsigned int ACKERMANN_CONFIG = 2; +/** + * \brief The Odometry class handles odometry readings + * (2D pose and velocity with related timestamp) + */ +class SteeringOdometry +{ +public: + /** + * \brief Constructor + * Timestamp will get the current time value + * Value will be set to zero + * \param velocity_rolling_window_size Rolling window size used to compute the velocity mean + * + */ + explicit SteeringOdometry(size_t velocity_rolling_window_size = 10); + + /** + * \brief Initialize the odometry + * \param time Current time + */ + void init(const rclcpp::Time & time); + + /** + * \brief Updates the odometry class with latest wheels position + * \param traction_wheel_pos traction wheel position [rad] + * \param steer_pos Front Steer position [rad] + * \param dt time difference to last call + * \return true if the odometry is actually updated + */ + bool update_from_position( + const double traction_wheel_pos, const double steer_pos, const double dt); + + /** + * \brief Updates the odometry class with latest wheels position + * \param right_traction_wheel_pos Right traction wheel velocity [rad] + * \param left_traction_wheel_pos Left traction wheel velocity [rad] + * \param front_steer_pos Steer wheel position [rad] + * \param dt time difference to last call + * \return true if the odometry is actually updated + */ + bool update_from_position( + const double right_traction_wheel_pos, const double left_traction_wheel_pos, + const double steer_pos, const double dt); + + /** + * \brief Updates the odometry class with latest wheels position + * \param right_traction_wheel_pos Right traction wheel position [rad] + * \param left_traction_wheel_pos Left traction wheel position [rad] + * \param right_steer_pos Right steer wheel position [rad] + * \param left_steer_pos Left steer wheel position [rad] + * \param dt time difference to last call + * \return true if the odometry is actually updated + */ + bool update_from_position( + const double right_traction_wheel_pos, const double left_traction_wheel_pos, + const double right_steer_pos, const double left_steer_pos, const double dt); + + /** + * \brief Updates the odometry class with latest wheels position + * \param traction_wheel_vel Traction wheel velocity [rad/s] + * \param front_steer_pos Steer wheel position [rad] + * \param dt time difference to last call + * \return true if the odometry is actually updated + */ + bool update_from_velocity( + const double traction_wheel_vel, const double steer_pos, const double dt); + + /** + * \brief Updates the odometry class with latest wheels position + * \param right_traction_wheel_vel Right traction wheel velocity [rad/s] + * \param left_traction_wheel_vel Left traction wheel velocity [rad/s] + * \param front_steer_pos Steer wheel position [rad] + * \param dt time difference to last call + * \return true if the odometry is actually updated + */ + bool update_from_velocity( + const double right_traction_wheel_vel, const double left_traction_wheel_vel, + const double steer_pos, const double dt); + + /** + * \brief Updates the odometry class with latest wheels position + * \param right_traction_wheel_vel Right traction wheel velocity [rad/s] + * \param left_traction_wheel_vel Left traction wheel velocity [rad/s] + * \param right_steer_pos Right steer wheel position [rad] + * \param left_steer_pos Left steer wheel position [rad] + * \param dt time difference to last call + * \return true if the odometry is actually updated + */ + bool update_from_velocity( + const double right_traction_wheel_vel, const double left_traction_wheel_vel, + const double right_steer_pos, const double left_steer_pos, const double dt); + + /** + * \brief Updates the odometry class with latest velocity command + * \param linear Linear velocity [m/s] + * \param angular Angular velocity [rad/s] + * \param time Current time + */ + void update_open_loop(const double linear, const double angular, const double dt); + + /** + * \brief Set odometry type + * \param type odometry type + */ + void set_odometry_type(const unsigned int type); + + /** + * \brief heading getter + * \return heading [rad] + */ + double get_heading() const { return heading_; } + + /** + * \brief x position getter + * \return x position [m] + */ + double get_x() const { return x_; } + + /** + * \brief y position getter + * \return y position [m] + */ + double get_y() const { return y_; } + + /** + * \brief linear velocity getter + * \return linear velocity [m/s] + */ + double get_linear() const { return linear_; } + + /** + * \brief angular velocity getter + * \return angular velocity [rad/s] + */ + double get_angular() const { return angular_; } + + /** + * \brief Sets the wheel parameters: radius, separation and wheelbase + */ + void set_wheel_params(double wheel_radius, double wheelbase = 0.0, double wheel_track = 0.0); + + /** + * \brief Velocity rolling window size setter + * \param velocity_rolling_window_size Velocity rolling window size + */ + void set_velocity_rolling_window_size(size_t velocity_rolling_window_size); + + /** + * \brief Calculates inverse kinematics for the desired linear and angular velocities + * \param Vx Desired linear velocity [m/s] + * \param theta_dot Desired angular velocity [rad/s] + * \return Tuple of velocity commands and steering commands + */ + std::tuple, std::vector> get_commands(double Vx, double theta_dot); + + /** + * \brief Reset poses, heading, and accumulators + */ + void reset_odometry(); + +private: + /** + * \brief Uses precomputed linear and angular velocities to compute dometry and update accumulators + * \param linear Linear velocity [m] (linear displacement, i.e. m/s * dt) computed by previous odometry method + * \param angular Angular velocity [rad] (angular displacement, i.e. m/s * dt) computed by previous odometry method + */ + bool update_odometry(const double linear_velocity, const double angular, const double dt); + + /** + * \brief Integrates the velocities (linear and angular) using 2nd order Runge-Kutta + * \param linear Linear velocity [m] (linear displacement, i.e. m/s * dt) computed by encoders + * \param angular Angular velocity [rad] (angular displacement, i.e. m/s * dt) computed by encoders + */ + void integrate_runge_kutta_2(double linear, double angular); + + /** + * \brief Integrates the velocities (linear and angular) using exact method + * \param linear Linear velocity [m] (linear displacement, i.e. m/s * dt) computed by encoders + * \param angular Angular velocity [rad] (angular displacement, i.e. m/s * dt) computed by encoders + */ + void integrate_exact(double linear, double angular); + + /** + * \brief Calculates steering angle from the desired translational and rotational velocity + * \param Vx Linear velocity [m] + * \param theta_dot Angular velocity [rad] + */ + double convert_trans_rot_vel_to_steering_angle(double Vx, double theta_dot); + + /** + * \brief Reset linear and angular accumulators + */ + void reset_accumulators(); + + /// Current timestamp: + rclcpp::Time timestamp_; + + /// Current pose: + double x_; // [m] + double y_; // [m] + double steer_pos_; // [rad] + double heading_; // [rad] + + /// Current velocity: + double linear_; // [m/s] + double angular_; // [rad/s] + + /// Kinematic parameters + double wheel_track_; // [m] + double wheelbase_; // [m] + double wheel_radius_; // [m] + + /// Configuration type used for the forward kinematics + int config_type_ = -1; + + /// Previous wheel position/state [rad]: + double traction_wheel_old_pos_; + double traction_right_wheel_old_pos_; + double traction_left_wheel_old_pos_; + /// Rolling mean accumulators for the linear and angular velocities: + size_t velocity_rolling_window_size_; + rcpputils::RollingMeanAccumulator linear_acc_; + rcpputils::RollingMeanAccumulator angular_acc_; +}; +} // namespace steering_odometry + +#endif // STEERING_CONTROLLERS_LIBRARY__STEERING_ODOMETRY_HPP_ diff --git a/steering_controllers_library/include/steering_controllers_library/visibility_control.h b/steering_controllers_library/include/steering_controllers_library/visibility_control.h new file mode 100644 index 0000000000..123662031b --- /dev/null +++ b/steering_controllers_library/include/steering_controllers_library/visibility_control.h @@ -0,0 +1,50 @@ +// Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef STEERING_CONTROLLERS_LIBRARY__VISIBILITY_CONTROL_H_ +#define STEERING_CONTROLLERS_LIBRARY__VISIBILITY_CONTROL_H_ + +// This logic was borrowed (then namespaced) from the examples on the gcc wiki: +// https://gcc.gnu.org/wiki/Visibility + +#if defined _WIN32 || defined __CYGWIN__ +#ifdef __GNUC__ +#define STEERING_CONTROLLERS__VISIBILITY_EXPORT __attribute__((dllexport)) +#define STEERING_CONTROLLERS__VISIBILITY_IMPORT __attribute__((dllimport)) +#else +#define STEERING_CONTROLLERS__VISIBILITY_EXPORT __declspec(dllexport) +#define STEERING_CONTROLLERS__VISIBILITY_IMPORT __declspec(dllimport) +#endif +#ifdef STEERING_CONTROLLERS__VISIBILITY_BUILDING_DLL +#define STEERING_CONTROLLERS__VISIBILITY_PUBLIC STEERING_CONTROLLERS__VISIBILITY_EXPORT +#else +#define STEERING_CONTROLLERS__VISIBILITY_PUBLIC STEERING_CONTROLLERS__VISIBILITY_IMPORT +#endif +#define STEERING_CONTROLLERS__VISIBILITY_PUBLIC_TYPE STEERING_CONTROLLERS__VISIBILITY_PUBLIC +#define STEERING_CONTROLLERS__VISIBILITY_LOCAL +#else +#define STEERING_CONTROLLERS__VISIBILITY_EXPORT __attribute__((visibility("default"))) +#define STEERING_CONTROLLERS__VISIBILITY_IMPORT +#if __GNUC__ >= 4 +#define STEERING_CONTROLLERS__VISIBILITY_PUBLIC __attribute__((visibility("default"))) +#define STEERING_CONTROLLERS__VISIBILITY_PROTECTED __attribute__((visibility("protected"))) +#define STEERING_CONTROLLERS__VISIBILITY_LOCAL __attribute__((visibility("hidden"))) +#else +#define STEERING_CONTROLLERS__VISIBILITY_PUBLIC +#define STEERING_CONTROLLERS__VISIBILITY_LOCAL +#endif +#define STEERING_CONTROLLERS__VISIBILITY_PUBLIC_TYPE +#endif + +#endif // STEERING_CONTROLLERS_LIBRARY__VISIBILITY_CONTROL_H_ diff --git a/steering_controllers_library/package.xml b/steering_controllers_library/package.xml new file mode 100644 index 0000000000..0d9aa9da39 --- /dev/null +++ b/steering_controllers_library/package.xml @@ -0,0 +1,45 @@ + + + + steering_controllers_library + 0.0.0 + Package for steering robot configurations including odometry and interfaces. + Apache License 2.0 + Bence Magyar + Dr.-Ing. Denis Štogl + dr. sc. Tomislav Petkovic + Tony Najjar + + Dr.-Ing. Denis Štogl + dr. sc. Tomislav Petkovic + Tony Najjar + + ament_cmake + + generate_parameter_library + + control_msgs + controller_interface + geometry_msgs + hardware_interface + nav_msgs + pluginlib + rclcpp + rclcpp_lifecycle + realtime_tools + rcpputils + std_srvs + tf2 + tf2_msgs + tf2_geometry_msgs + ackermann_msgs + + ament_cmake_gmock + controller_manager + hardware_interface + ros2_control_test_assets + + + ament_cmake + + diff --git a/steering_controllers_library/src/steering_controllers_library.cpp b/steering_controllers_library/src/steering_controllers_library.cpp new file mode 100644 index 0000000000..af2736a8a3 --- /dev/null +++ b/steering_controllers_library/src/steering_controllers_library.cpp @@ -0,0 +1,558 @@ +// Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "steering_controllers_library/steering_controllers_library.hpp" + +#include +#include +#include +#include +#include +#include + +#include "controller_interface/helpers.hpp" +#include "hardware_interface/types/hardware_interface_type_values.hpp" +#include "lifecycle_msgs/msg/state.hpp" +#include "tf2/transform_datatypes.h" +#include "tf2_geometry_msgs/tf2_geometry_msgs.hpp" + +namespace +{ // utility + +using ControllerTwistReferenceMsg = + steering_controllers_library::SteeringControllersLibrary::ControllerTwistReferenceMsg; + +// called from RT control loop +void reset_controller_reference_msg( + const std::shared_ptr & msg, + const std::shared_ptr & node) +{ + msg->header.stamp = node->now(); + msg->twist.linear.x = std::numeric_limits::quiet_NaN(); + msg->twist.linear.y = std::numeric_limits::quiet_NaN(); + msg->twist.linear.z = std::numeric_limits::quiet_NaN(); + msg->twist.angular.x = std::numeric_limits::quiet_NaN(); + msg->twist.angular.y = std::numeric_limits::quiet_NaN(); + msg->twist.angular.z = std::numeric_limits::quiet_NaN(); +} + +} // namespace + +namespace steering_controllers_library +{ +SteeringControllersLibrary::SteeringControllersLibrary() +: controller_interface::ChainableControllerInterface() +{ +} + +controller_interface::CallbackReturn SteeringControllersLibrary::on_init() +{ + try + { + param_listener_ = std::make_shared(get_node()); + initialize_implementation_parameter_listener(); + } + catch (const std::exception & e) + { + fprintf(stderr, "Exception thrown during controller's init with message: %s \n", e.what()); + return controller_interface::CallbackReturn::ERROR; + } + + return controller_interface::CallbackReturn::SUCCESS; +} + +controller_interface::CallbackReturn SteeringControllersLibrary::set_interface_numbers( + size_t nr_state_itfs = 2, size_t nr_cmd_itfs = 2, size_t nr_ref_itfs = 2) +{ + nr_state_itfs_ = nr_state_itfs; + nr_cmd_itfs_ = nr_cmd_itfs; + nr_ref_itfs_ = nr_ref_itfs; + return controller_interface::CallbackReturn::SUCCESS; +} + +controller_interface::CallbackReturn SteeringControllersLibrary::on_configure( + const rclcpp_lifecycle::State & /*previous_state*/) +{ + params_ = param_listener_->get_params(); + odometry_.set_velocity_rolling_window_size(params_.velocity_rolling_window_size); + + configure_odometry(); + + if (!params_.rear_wheels_state_names.empty()) + { + rear_wheels_state_names_ = params_.rear_wheels_state_names; + } + else + { + rear_wheels_state_names_ = params_.rear_wheels_names; + } + + if (!params_.front_wheels_state_names.empty()) + { + front_wheels_state_names_ = params_.front_wheels_state_names; + } + else + { + front_wheels_state_names_ = params_.front_wheels_names; + } + + // topics QoS + auto subscribers_qos = rclcpp::SystemDefaultsQoS(); + subscribers_qos.keep_last(1); + subscribers_qos.best_effort(); + + // Reference Subscriber + ref_timeout_ = rclcpp::Duration::from_seconds(params_.reference_timeout); + if (params_.use_stamped_vel) + { + ref_subscriber_twist_ = get_node()->create_subscription( + "~/reference", subscribers_qos, + std::bind(&SteeringControllersLibrary::reference_callback, this, std::placeholders::_1)); + } + else + { + ref_subscriber_unstamped_ = get_node()->create_subscription( + "~/reference_unstamped", subscribers_qos, + std::bind( + &SteeringControllersLibrary::reference_callback_unstamped, this, std::placeholders::_1)); + } + + std::shared_ptr msg = + std::make_shared(); + reset_controller_reference_msg(msg, get_node()); + input_ref_.writeFromNonRT(msg); + + try + { + // Odom state publisher + odom_s_publisher_ = get_node()->create_publisher( + "~/odometry", rclcpp::SystemDefaultsQoS()); + rt_odom_state_publisher_ = std::make_unique(odom_s_publisher_); + } + catch (const std::exception & e) + { + fprintf( + stderr, "Exception thrown during publisher creation at configure stage with message : %s \n", + e.what()); + return controller_interface::CallbackReturn::ERROR; + } + + rt_odom_state_publisher_->lock(); + rt_odom_state_publisher_->msg_.header.stamp = get_node()->now(); + rt_odom_state_publisher_->msg_.header.frame_id = params_.odom_frame_id; + rt_odom_state_publisher_->msg_.child_frame_id = params_.base_frame_id; + rt_odom_state_publisher_->msg_.pose.pose.position.z = 0; + + auto & covariance = rt_odom_state_publisher_->msg_.twist.covariance; + constexpr size_t NUM_DIMENSIONS = 6; + for (size_t index = 0; index < 6; ++index) + { + // 0, 7, 14, 21, 28, 35 + const size_t diagonal_index = NUM_DIMENSIONS * index + index; + covariance[diagonal_index] = params_.pose_covariance_diagonal[index]; + covariance[diagonal_index] = params_.twist_covariance_diagonal[index]; + } + rt_odom_state_publisher_->unlock(); + + try + { + // Tf State publisher + tf_odom_s_publisher_ = get_node()->create_publisher( + "~/tf_odometry", rclcpp::SystemDefaultsQoS()); + rt_tf_odom_state_publisher_ = + std::make_unique(tf_odom_s_publisher_); + } + catch (const std::exception & e) + { + fprintf( + stderr, "Exception thrown during publisher creation at configure stage with message : %s \n", + e.what()); + return controller_interface::CallbackReturn::ERROR; + } + + rt_tf_odom_state_publisher_->lock(); + rt_tf_odom_state_publisher_->msg_.transforms.resize(1); + rt_tf_odom_state_publisher_->msg_.transforms[0].header.stamp = get_node()->now(); + rt_tf_odom_state_publisher_->msg_.transforms[0].header.frame_id = params_.odom_frame_id; + rt_tf_odom_state_publisher_->msg_.transforms[0].child_frame_id = params_.base_frame_id; + rt_tf_odom_state_publisher_->msg_.transforms[0].transform.translation.z = 0.0; + rt_tf_odom_state_publisher_->unlock(); + + try + { + // State publisher + controller_s_publisher_ = get_node()->create_publisher( + "~/controller_state", rclcpp::SystemDefaultsQoS()); + controller_state_publisher_ = + std::make_unique(controller_s_publisher_); + } + catch (const std::exception & e) + { + fprintf( + stderr, "Exception thrown during publisher creation at configure stage with message : %s \n", + e.what()); + return controller_interface::CallbackReturn::ERROR; + } + + controller_state_publisher_->lock(); + controller_state_publisher_->msg_.header.stamp = get_node()->now(); + controller_state_publisher_->msg_.header.frame_id = params_.odom_frame_id; + controller_state_publisher_->unlock(); + RCLCPP_INFO(get_node()->get_logger(), "configure successful"); + return controller_interface::CallbackReturn::SUCCESS; +} + +void SteeringControllersLibrary::reference_callback( + const std::shared_ptr msg) +{ + // if no timestamp provided use current time for command timestamp + if (msg->header.stamp.sec == 0 && msg->header.stamp.nanosec == 0u) + { + RCLCPP_WARN( + get_node()->get_logger(), + "Timestamp in header is missing, using current time as command timestamp."); + msg->header.stamp = get_node()->now(); + } + const auto age_of_last_command = get_node()->now() - msg->header.stamp; + + if (ref_timeout_ == rclcpp::Duration::from_seconds(0) || age_of_last_command <= ref_timeout_) + { + input_ref_.writeFromNonRT(msg); + } + else + { + RCLCPP_ERROR( + get_node()->get_logger(), + "Received message has timestamp %.10f older for %.10f which is more then allowed timeout " + "(%.4f).", + rclcpp::Time(msg->header.stamp).seconds(), age_of_last_command.seconds(), + ref_timeout_.seconds()); + } +} + +void SteeringControllersLibrary::reference_callback_unstamped( + const std::shared_ptr msg) +{ + RCLCPP_WARN( + get_node()->get_logger(), + "Use of Twist message without stamped is deprecated and it will be removed in ROS 2 J-Turtle " + "version. Use '~/reference' topic with 'geometry_msgs::msg::TwistStamped' message type in the " + "future."); + auto twist_stamped = *(input_ref_.readFromNonRT()); + twist_stamped->header.stamp = get_node()->now(); + // if no timestamp provided use current time for command timestamp + if (twist_stamped->header.stamp.sec == 0 && twist_stamped->header.stamp.nanosec == 0u) + { + RCLCPP_WARN( + get_node()->get_logger(), + "Timestamp in header is missing, using current time as command timestamp."); + twist_stamped->header.stamp = get_node()->now(); + } + + const auto age_of_last_command = get_node()->now() - twist_stamped->header.stamp; + + if (ref_timeout_ == rclcpp::Duration::from_seconds(0) || age_of_last_command <= ref_timeout_) + { + twist_stamped->twist = *msg; + } + else + { + RCLCPP_ERROR( + get_node()->get_logger(), + "Received message has timestamp %.10f older for %.10f which is more then allowed timeout " + "(%.4f).", + rclcpp::Time(twist_stamped->header.stamp).seconds(), age_of_last_command.seconds(), + ref_timeout_.seconds()); + } +} + +controller_interface::InterfaceConfiguration +SteeringControllersLibrary::command_interface_configuration() const +{ + controller_interface::InterfaceConfiguration command_interfaces_config; + command_interfaces_config.type = controller_interface::interface_configuration_type::INDIVIDUAL; + command_interfaces_config.names.reserve(nr_cmd_itfs_); + + if (params_.front_steering) + { + for (size_t i = 0; i < params_.rear_wheels_names.size(); i++) + { + command_interfaces_config.names.push_back( + params_.rear_wheels_names[i] + "/" + hardware_interface::HW_IF_VELOCITY); + } + + for (size_t i = 0; i < params_.front_wheels_names.size(); i++) + { + command_interfaces_config.names.push_back( + params_.front_wheels_names[i] + "/" + hardware_interface::HW_IF_POSITION); + } + } + else + { + for (size_t i = 0; i < params_.front_wheels_names.size(); i++) + { + command_interfaces_config.names.push_back( + params_.front_wheels_names[i] + "/" + hardware_interface::HW_IF_VELOCITY); + } + + for (size_t i = 0; i < params_.rear_wheels_names.size(); i++) + { + command_interfaces_config.names.push_back( + params_.rear_wheels_names[i] + "/" + hardware_interface::HW_IF_POSITION); + } + } + return command_interfaces_config; +} + +controller_interface::InterfaceConfiguration +SteeringControllersLibrary::state_interface_configuration() const +{ + controller_interface::InterfaceConfiguration state_interfaces_config; + state_interfaces_config.type = controller_interface::interface_configuration_type::INDIVIDUAL; + + state_interfaces_config.names.reserve(nr_state_itfs_); + const auto traction_wheels_feedback = params_.position_feedback + ? hardware_interface::HW_IF_POSITION + : hardware_interface::HW_IF_VELOCITY; + if (params_.front_steering) + { + for (size_t i = 0; i < rear_wheels_state_names_.size(); i++) + { + state_interfaces_config.names.push_back( + rear_wheels_state_names_[i] + "/" + traction_wheels_feedback); + } + + for (size_t i = 0; i < front_wheels_state_names_.size(); i++) + { + state_interfaces_config.names.push_back( + front_wheels_state_names_[i] + "/" + hardware_interface::HW_IF_POSITION); + } + } + else + { + for (size_t i = 0; i < front_wheels_state_names_.size(); i++) + { + state_interfaces_config.names.push_back( + front_wheels_state_names_[i] + "/" + traction_wheels_feedback); + } + + for (size_t i = 0; i < rear_wheels_state_names_.size(); i++) + { + state_interfaces_config.names.push_back( + rear_wheels_state_names_[i] + "/" + hardware_interface::HW_IF_POSITION); + } + } + + return state_interfaces_config; +} + +std::vector +SteeringControllersLibrary::on_export_reference_interfaces() +{ + reference_interfaces_.resize(nr_ref_itfs_, std::numeric_limits::quiet_NaN()); + + std::vector reference_interfaces; + reference_interfaces.reserve(nr_ref_itfs_); + + reference_interfaces.push_back(hardware_interface::CommandInterface( + get_node()->get_name(), std::string("linear/") + hardware_interface::HW_IF_VELOCITY, + &reference_interfaces_[0])); + + reference_interfaces.push_back(hardware_interface::CommandInterface( + get_node()->get_name(), std::string("angular/") + hardware_interface::HW_IF_POSITION, + &reference_interfaces_[1])); + + return reference_interfaces; +} + +bool SteeringControllersLibrary::on_set_chained_mode(bool chained_mode) +{ + // Always accept switch to/from chained mode + return true || chained_mode; +} + +controller_interface::CallbackReturn SteeringControllersLibrary::on_activate( + const rclcpp_lifecycle::State & /*previous_state*/) +{ + // Set default value in command + reset_controller_reference_msg(*(input_ref_.readFromRT()), get_node()); + + return controller_interface::CallbackReturn::SUCCESS; +} + +controller_interface::CallbackReturn SteeringControllersLibrary::on_deactivate( + const rclcpp_lifecycle::State & /*previous_state*/) +{ + for (size_t i = 0; i < nr_cmd_itfs_; ++i) + { + command_interfaces_[i].set_value(std::numeric_limits::quiet_NaN()); + } + return controller_interface::CallbackReturn::SUCCESS; +} + +controller_interface::return_type SteeringControllersLibrary::update_reference_from_subscribers( + const rclcpp::Time & time, const rclcpp::Duration & /*period*/) +{ + auto current_ref = *(input_ref_.readFromRT()); + const auto age_of_last_command = time - (current_ref)->header.stamp; + + // send message only if there is no timeout + if (age_of_last_command <= ref_timeout_ || ref_timeout_ == rclcpp::Duration::from_seconds(0)) + { + if (!std::isnan(current_ref->twist.linear.x) && !std::isnan(current_ref->twist.angular.z)) + { + reference_interfaces_[0] = current_ref->twist.linear.x; + reference_interfaces_[1] = current_ref->twist.angular.z; + } + } + else + { + if (!std::isnan(current_ref->twist.linear.x) && !std::isnan(current_ref->twist.angular.z)) + { + reference_interfaces_[0] = 0.0; + reference_interfaces_[1] = 0.0; + current_ref->twist.linear.x = std::numeric_limits::quiet_NaN(); + current_ref->twist.angular.z = std::numeric_limits::quiet_NaN(); + } + } + + return controller_interface::return_type::OK; +} + +controller_interface::return_type SteeringControllersLibrary::update_and_write_commands( + const rclcpp::Time & time, const rclcpp::Duration & period) +{ + update_odometry(period); + + // MOVE ROBOT + + // Limit velocities and accelerations: + // TODO(destogl): add limiter for the velocities + + if (!std::isnan(reference_interfaces_[0]) && !std::isnan(reference_interfaces_[1])) + { + // store and set commands + const double linear_command = reference_interfaces_[0]; + const double angular_command = reference_interfaces_[1]; + auto [traction_commands, steering_commands] = + odometry_.get_commands(linear_command, angular_command); + if (params_.front_steering) + { + for (size_t i = 0; i < params_.rear_wheels_names.size(); i++) + { + command_interfaces_[i].set_value(traction_commands[i]); + } + for (size_t i = 0; i < params_.front_wheels_names.size(); i++) + { + command_interfaces_[i + params_.rear_wheels_names.size()].set_value(steering_commands[i]); + } + } + else + { + { + for (size_t i = 0; i < params_.front_wheels_names.size(); i++) + { + command_interfaces_[i].set_value(traction_commands[i]); + } + for (size_t i = 0; i < params_.rear_wheels_names.size(); i++) + { + command_interfaces_[i + params_.front_wheels_names.size()].set_value( + steering_commands[i]); + } + } + } + } + + // Publish odometry message + // Compute and store orientation info + tf2::Quaternion orientation; + orientation.setRPY(0.0, 0.0, odometry_.get_heading()); + + // Populate odom message and publish + if (rt_odom_state_publisher_->trylock()) + { + rt_odom_state_publisher_->msg_.header.stamp = time; + rt_odom_state_publisher_->msg_.pose.pose.position.x = odometry_.get_x(); + rt_odom_state_publisher_->msg_.pose.pose.position.y = odometry_.get_y(); + rt_odom_state_publisher_->msg_.pose.pose.orientation = tf2::toMsg(orientation); + rt_odom_state_publisher_->msg_.twist.twist.linear.x = odometry_.get_linear(); + rt_odom_state_publisher_->msg_.twist.twist.angular.z = odometry_.get_angular(); + rt_odom_state_publisher_->unlockAndPublish(); + } + + // Publish tf /odom frame + if (params_.enable_odom_tf && rt_tf_odom_state_publisher_->trylock()) + { + rt_tf_odom_state_publisher_->msg_.transforms.front().header.stamp = time; + rt_tf_odom_state_publisher_->msg_.transforms.front().transform.translation.x = + odometry_.get_x(); + rt_tf_odom_state_publisher_->msg_.transforms.front().transform.translation.y = + odometry_.get_y(); + rt_tf_odom_state_publisher_->msg_.transforms.front().transform.rotation = + tf2::toMsg(orientation); + rt_tf_odom_state_publisher_->unlockAndPublish(); + } + + if (controller_state_publisher_->trylock()) + { + controller_state_publisher_->msg_.header.stamp = time; + controller_state_publisher_->msg_.traction_wheels_position.clear(); + controller_state_publisher_->msg_.traction_wheels_velocity.clear(); + controller_state_publisher_->msg_.linear_velocity_command.clear(); + controller_state_publisher_->msg_.steer_positions.clear(); + controller_state_publisher_->msg_.steering_angle_command.clear(); + + auto number_of_traction_wheels = params_.rear_wheels_names.size(); + auto number_of_steering_wheels = params_.front_wheels_names.size(); + + if (!params_.front_steering) + { + number_of_traction_wheels = params_.front_wheels_names.size(); + number_of_steering_wheels = params_.rear_wheels_names.size(); + } + + for (size_t i = 0; i < number_of_traction_wheels; ++i) + { + if (params_.position_feedback) + { + controller_state_publisher_->msg_.traction_wheels_position.push_back( + state_interfaces_[i].get_value()); + } + else + { + controller_state_publisher_->msg_.traction_wheels_velocity.push_back( + state_interfaces_[i].get_value()); + } + controller_state_publisher_->msg_.linear_velocity_command.push_back( + command_interfaces_[i].get_value()); + } + + for (size_t i = 0; i < number_of_steering_wheels; ++i) + { + controller_state_publisher_->msg_.steer_positions.push_back( + state_interfaces_[number_of_traction_wheels + i].get_value()); + controller_state_publisher_->msg_.steering_angle_command.push_back( + command_interfaces_[number_of_traction_wheels + i].get_value()); + } + + controller_state_publisher_->unlockAndPublish(); + } + + reference_interfaces_[0] = std::numeric_limits::quiet_NaN(); + reference_interfaces_[1] = std::numeric_limits::quiet_NaN(); + + return controller_interface::return_type::OK; +} + +} // namespace steering_controllers_library diff --git a/steering_controllers_library/src/steering_controllers_library.yaml b/steering_controllers_library/src/steering_controllers_library.yaml new file mode 100644 index 0000000000..86acb01dae --- /dev/null +++ b/steering_controllers_library/src/steering_controllers_library.yaml @@ -0,0 +1,122 @@ +steering_controllers_library: + reference_timeout: { + type: double, + default_value: 1, + description: "Timeout for controller references after which they will be reset. This is especially useful for controllers that can cause unwanted and dangerous behaviour if reference is not reset, e.g., velocity controllers. If value is 0 the reference is reset after each run.", + } + + front_steering: { + type: bool, + default_value: true, + description: "Is the steering on the front of the robot?", + read_only: true, + } + + rear_wheels_names: { + type: string_array, + description: "Names of rear wheel joints.", + read_only: true, + validation: { + size_lt<>: [5], + unique<>: null, + not_empty<>: null, + } + } + + front_wheels_names: { + type: string_array, + description: "Names of front wheel joints.", + read_only: true, + validation: { + size_lt<>: [5], + unique<>: null, + not_empty<>: null, + } + } + + rear_wheels_state_names: { + type: string_array, + description: "(Optional) Names of rear wheel joints to read states from. If not set joint names from 'rear_wheels_names' will be used.", + default_value: [], + read_only: true, + validation: { + size_lt<>: [5], + unique<>: null, + } + } + + front_wheels_state_names: { + type: string_array, + description: "(Optional) Names of front wheel joints to read states from. If not set joint names from 'front_wheels_names' will be used.", + default_value: [], + read_only: true, + validation: { + size_lt<>: [5], + unique<>: null, + } + } + + open_loop: { + type: bool, + default_value: false, + description: "bool parameter decides if open oop or not (feedback).", + read_only: false, + } + + velocity_rolling_window_size: { + type: int, + default_value: 10, + description: "The number of velocity samples to average together to compute the odometry twist.linear.x and twist.angular.z velocities.", + read_only: false, + } + + base_frame_id: { + type: string, + default_value: "base_link", + description: "Base frame_id set to value of base_frame_id.", + read_only: false, + } + + odom_frame_id: { + type: string, + default_value: "odom", + description: "Odometry frame_id set to value of odom_frame_id.", + read_only: false, + } + + enable_odom_tf: { + type: bool, + default_value: true, + description: "Publishing to tf is enabled or disabled ?.", + read_only: false, + } + + twist_covariance_diagonal: { + type: double_array, + default_value: [0, 7, 14, 21, 28, 35], + description: "diagonal values of twist covariance matrix.", + read_only: false, + } + + pose_covariance_diagonal: { + type: double_array, + default_value: [0, 7, 14, 21, 28, 35], + description: "diagonal values of pose covariance matrix.", + read_only: false, + } + + position_feedback: { + type: bool, + default_value: false, + description: "Choice of feedback type, if position_feedback is false then HW_IF_VELOCITY is taken as interface type, if + position_feedback is true then HW_IF_POSITION is taken as interface type", + read_only: false, + } + + use_stamped_vel: { + type: bool, + default_value: false, + description: "Choice of vel type, if use_stamped_vel is false then geometry_msgs::msg::Twist is taken as vel msg type, if + use_stamped_vel is true then geometry_msgs::msg::TwistStamped is taken as vel msg type", + read_only: false, + } diff --git a/steering_controllers_library/src/steering_odometry.cpp b/steering_controllers_library/src/steering_odometry.cpp new file mode 100644 index 0000000000..28cd7fc80d --- /dev/null +++ b/steering_controllers_library/src/steering_odometry.cpp @@ -0,0 +1,333 @@ +/********************************************************************* +* Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt) +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. + *********************************************************************/ + +/* + * Author: dr. sc. Tomislav Petkovic + * Author: Dr. Ing. Denis Stogl + */ + +#include "steering_controllers_library/steering_odometry.hpp" + +#include +#include + +namespace steering_odometry +{ +SteeringOdometry::SteeringOdometry(size_t velocity_rolling_window_size) +: timestamp_(0.0), + x_(0.0), + y_(0.0), + heading_(0.0), + linear_(0.0), + angular_(0.0), + wheel_track_(0.0), + wheelbase_(0.0), + wheel_radius_(0.0), + traction_wheel_old_pos_(0.0), + velocity_rolling_window_size_(velocity_rolling_window_size), + linear_acc_(velocity_rolling_window_size), + angular_acc_(velocity_rolling_window_size) +{ +} + +void SteeringOdometry::init(const rclcpp::Time & time) +{ + // Reset accumulators and timestamp: + reset_accumulators(); + timestamp_ = time; +} + +bool SteeringOdometry::update_odometry( + const double linear_velocity, const double angular, const double dt) +{ + /// Integrate odometry: + SteeringOdometry::integrate_exact(linear_velocity * dt, angular); + + /// We cannot estimate the speed with very small time intervals: + if (dt < 0.0001) + { + return false; // Interval too small to integrate with + } + + /// Estimate speeds using a rolling mean to filter them out: + linear_acc_.accumulate(linear_velocity); + angular_acc_.accumulate(angular / dt); + + linear_ = linear_acc_.getRollingMean(); + angular_ = angular_acc_.getRollingMean(); + + return true; +} + +bool SteeringOdometry::update_from_position( + const double traction_wheel_pos, const double steer_pos, const double dt) +{ + /// Get current wheel joint positions: + const double traction_wheel_cur_pos = traction_wheel_pos * wheel_radius_; + const double traction_wheel_est_pos_diff = traction_wheel_cur_pos - traction_wheel_old_pos_; + + /// Update old position with current: + traction_wheel_old_pos_ = traction_wheel_cur_pos; + + /// Compute linear and angular diff: + const double linear_velocity = traction_wheel_est_pos_diff / dt; + steer_pos_ = steer_pos; + const double angular = tan(steer_pos) * linear_velocity / wheelbase_; + + return update_odometry(linear_velocity, angular, dt); +} + +bool SteeringOdometry::update_from_position( + const double traction_right_wheel_pos, const double traction_left_wheel_pos, + const double steer_pos, const double dt) +{ + /// Get current wheel joint positions: + const double traction_right_wheel_cur_pos = traction_right_wheel_pos * wheel_radius_; + const double traction_left_wheel_cur_pos = traction_left_wheel_pos * wheel_radius_; + + const double traction_right_wheel_est_pos_diff = + traction_right_wheel_cur_pos - traction_right_wheel_old_pos_; + const double traction_left_wheel_est_pos_diff = + traction_left_wheel_cur_pos - traction_left_wheel_old_pos_; + + /// Update old position with current: + traction_right_wheel_old_pos_ = traction_right_wheel_cur_pos; + traction_left_wheel_old_pos_ = traction_left_wheel_cur_pos; + + const double linear_velocity = + (traction_right_wheel_est_pos_diff + traction_left_wheel_est_pos_diff) * 0.5 / dt; + steer_pos_ = steer_pos; + const double angular = tan(steer_pos_) * linear_velocity / wheelbase_; + + return update_odometry(linear_velocity, angular, dt); +} + +bool SteeringOdometry::update_from_position( + const double traction_right_wheel_pos, const double traction_left_wheel_pos, + const double right_steer_pos, const double left_steer_pos, const double dt) +{ + /// Get current wheel joint positions: + const double traction_right_wheel_cur_pos = traction_right_wheel_pos * wheel_radius_; + const double traction_left_wheel_cur_pos = traction_left_wheel_pos * wheel_radius_; + + const double traction_right_wheel_est_pos_diff = + traction_right_wheel_cur_pos - traction_right_wheel_old_pos_; + const double traction_left_wheel_est_pos_diff = + traction_left_wheel_cur_pos - traction_left_wheel_old_pos_; + + /// Update old position with current: + traction_right_wheel_old_pos_ = traction_right_wheel_cur_pos; + traction_left_wheel_old_pos_ = traction_left_wheel_cur_pos; + + /// Compute linear and angular diff: + const double linear_velocity = + (traction_right_wheel_est_pos_diff + traction_left_wheel_est_pos_diff) * 0.5 / dt; + steer_pos_ = (right_steer_pos + left_steer_pos) * 0.5; + const double angular = tan(steer_pos_) * linear_velocity / wheelbase_; + + return update_odometry(linear_velocity, angular, dt); +} + +bool SteeringOdometry::update_from_velocity( + const double traction_wheel_vel, const double steer_pos, const double dt) +{ + steer_pos_ = steer_pos; + double linear_velocity = traction_wheel_vel * wheel_radius_; + const double angular = tan(steer_pos) * linear_velocity / wheelbase_; + + return update_odometry(linear_velocity, angular, dt); +} + +bool SteeringOdometry::update_from_velocity( + const double right_traction_wheel_vel, const double left_traction_wheel_vel, + const double steer_pos, const double dt) +{ + double linear_velocity = + (right_traction_wheel_vel + left_traction_wheel_vel) * wheel_radius_ * 0.5; + steer_pos_ = steer_pos; + + const double angular = tan(steer_pos_) * linear_velocity / wheelbase_; + + return update_odometry(linear_velocity, angular, dt); +} + +bool SteeringOdometry::update_from_velocity( + const double right_traction_wheel_vel, const double left_traction_wheel_vel, + const double right_steer_pos, const double left_steer_pos, const double dt) +{ + steer_pos_ = (right_steer_pos + left_steer_pos) * 0.5; + double linear_velocity = + (right_traction_wheel_vel + left_traction_wheel_vel) * wheel_radius_ * 0.5; + const double angular = steer_pos_ * linear_velocity / wheelbase_; + + return update_odometry(linear_velocity, angular, dt); +} + +void SteeringOdometry::update_open_loop(const double linear, const double angular, const double dt) +{ + /// Save last linear and angular velocity: + linear_ = linear; + angular_ = angular; + + /// Integrate odometry: + SteeringOdometry::integrate_exact(linear * dt, angular * dt); +} + +void SteeringOdometry::set_wheel_params(double wheel_radius, double wheelbase, double wheel_track) +{ + wheel_radius_ = wheel_radius; + wheelbase_ = wheelbase; + wheel_track_ = wheel_track; +} + +void SteeringOdometry::set_velocity_rolling_window_size(size_t velocity_rolling_window_size) +{ + velocity_rolling_window_size_ = velocity_rolling_window_size; + + reset_accumulators(); +} + +void SteeringOdometry::set_odometry_type(const unsigned int type) { config_type_ = type; } + +double SteeringOdometry::convert_trans_rot_vel_to_steering_angle(double Vx, double theta_dot) +{ + if (theta_dot == 0 || Vx == 0) + { + return 0; + } + return std::atan(theta_dot * wheelbase_ / Vx); +} + +std::tuple, std::vector> SteeringOdometry::get_commands( + double Vx, double theta_dot) +{ + // desired velocity and steering angle of the middle of traction and steering axis + double Ws, alpha; + + if (Vx == 0 && theta_dot != 0) + { + alpha = theta_dot > 0 ? M_PI_2 : -M_PI_2; + Ws = abs(theta_dot) * wheelbase_ / wheel_radius_; + } + else + { + alpha = SteeringOdometry::convert_trans_rot_vel_to_steering_angle(Vx, theta_dot); + Ws = Vx / (wheel_radius_ * std::cos(steer_pos_)); + } + + if (config_type_ == BICYCLE_CONFIG) + { + std::vector traction_commands = {Ws}; + std::vector steering_commands = {alpha}; + return std::make_tuple(traction_commands, steering_commands); + } + else if (config_type_ == TRICYCLE_CONFIG) + { + std::vector traction_commands; + std::vector steering_commands; + if (fabs(steer_pos_) < 1e-6) + { + traction_commands = {Ws, Ws}; + } + else + { + double turning_radius = wheelbase_ / std::tan(steer_pos_); + double Wr = Ws * (turning_radius + wheel_track_ * 0.5) / turning_radius; + double Wl = Ws * (turning_radius - wheel_track_ * 0.5) / turning_radius; + traction_commands = {Wr, Wl}; + } + steering_commands = {alpha}; + return std::make_tuple(traction_commands, steering_commands); + } + else if (config_type_ == ACKERMANN_CONFIG) + { + std::vector traction_commands; + std::vector steering_commands; + if (fabs(steer_pos_) < 1e-6) + { + traction_commands = {Ws, Ws}; + steering_commands = {alpha, alpha}; + } + else + { + double turning_radius = wheelbase_ / std::tan(steer_pos_); + double Wr = Ws * (turning_radius + wheel_track_ * 0.5) / turning_radius; + double Wl = Ws * (turning_radius - wheel_track_ * 0.5) / turning_radius; + traction_commands = {Wr, Wl}; + + double numerator = 2 * wheelbase_ * std::sin(alpha); + double denominator_first_member = 2 * wheelbase_ * std::cos(alpha); + double denominator_second_member = wheel_track_ * std::sin(alpha); + + double alpha_r = std::atan2(numerator, denominator_first_member - denominator_second_member); + double alpha_l = std::atan2(numerator, denominator_first_member + denominator_second_member); + steering_commands = {alpha_r, alpha_l}; + } + return std::make_tuple(traction_commands, steering_commands); + } + else + { + throw std::runtime_error("Config not implemented"); + } +} + +void SteeringOdometry::reset_odometry() +{ + x_ = 0.0; + y_ = 0.0; + heading_ = 0.0; + reset_accumulators(); +} + +void SteeringOdometry::integrate_runge_kutta_2(double linear, double angular) +{ + const double direction = heading_ + angular * 0.5; + + /// Runge-Kutta 2nd order integration: + x_ += linear * cos(direction); + y_ += linear * sin(direction); + heading_ += angular; +} + +/** + * \brief Other possible integration method provided by the class + * \param linear + * \param angular + */ +void SteeringOdometry::integrate_exact(double linear, double angular) +{ + if (fabs(angular) < 1e-6) + { + integrate_runge_kutta_2(linear, angular); + } + else + { + /// Exact integration (should solve problems when angular is zero): + const double heading_old = heading_; + const double r = linear / angular; + heading_ += angular; + x_ += r * (sin(heading_) - sin(heading_old)); + y_ += -r * (cos(heading_) - cos(heading_old)); + } +} + +void SteeringOdometry::reset_accumulators() +{ + linear_acc_ = rcpputils::RollingMeanAccumulator(velocity_rolling_window_size_); + angular_acc_ = rcpputils::RollingMeanAccumulator(velocity_rolling_window_size_); +} + +} // namespace steering_odometry diff --git a/steering_controllers_library/test/steering_controllers_library_params.yaml b/steering_controllers_library/test/steering_controllers_library_params.yaml new file mode 100644 index 0000000000..d200d34961 --- /dev/null +++ b/steering_controllers_library/test/steering_controllers_library_params.yaml @@ -0,0 +1,17 @@ +test_steering_controllers_library: + ros__parameters: + + reference_timeout: 0.1 + front_steering: true + open_loop: false + velocity_rolling_window_size: 10 + position_feedback: false + use_stamped_vel: true + rear_wheels_names: [rear_right_wheel_joint, rear_left_wheel_joint] + front_wheels_names: [front_right_steering_joint, front_left_steering_joint] + + wheelbase: 3.24644 + front_wheel_track: 2.12321 + rear_wheel_track: 1.76868 + front_wheels_radius: 0.45 + rear_wheels_radius: 0.45 diff --git a/steering_controllers_library/test/test_steering_controllers_library.cpp b/steering_controllers_library/test/test_steering_controllers_library.cpp new file mode 100644 index 0000000000..81075d1082 --- /dev/null +++ b/steering_controllers_library/test/test_steering_controllers_library.cpp @@ -0,0 +1,200 @@ +// Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "test_steering_controllers_library.hpp" + +#include +#include +#include +#include +#include + +#include "hardware_interface/types/hardware_interface_type_values.hpp" + +class SteeringControllersLibraryTest +: public SteeringControllersLibraryFixture +{ +}; + +// checking if all interfaces, command, state and reference are exported as expected +TEST_F(SteeringControllersLibraryTest, check_exported_intefaces) +{ + SetUpController(); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + + auto command_intefaces = controller_->command_interface_configuration(); + ASSERT_EQ(command_intefaces.names.size(), joint_command_values_.size()); + EXPECT_EQ( + command_intefaces.names[CMD_TRACTION_RIGHT_WHEEL], + rear_wheels_names_[0] + "/" + traction_interface_name_); + EXPECT_EQ( + command_intefaces.names[CMD_TRACTION_LEFT_WHEEL], + rear_wheels_names_[1] + "/" + traction_interface_name_); + EXPECT_EQ( + command_intefaces.names[CMD_STEER_RIGHT_WHEEL], + front_wheels_names_[0] + "/" + steering_interface_name_); + EXPECT_EQ( + command_intefaces.names[CMD_STEER_LEFT_WHEEL], + front_wheels_names_[1] + "/" + steering_interface_name_); + + auto state_intefaces = controller_->state_interface_configuration(); + ASSERT_EQ(state_intefaces.names.size(), joint_state_values_.size()); + EXPECT_EQ( + state_intefaces.names[STATE_TRACTION_RIGHT_WHEEL], + controller_->rear_wheels_state_names_[0] + "/" + traction_interface_name_); + EXPECT_EQ( + state_intefaces.names[STATE_TRACTION_LEFT_WHEEL], + controller_->rear_wheels_state_names_[1] + "/" + traction_interface_name_); + EXPECT_EQ( + state_intefaces.names[STATE_STEER_RIGHT_WHEEL], + controller_->front_wheels_state_names_[0] + "/" + steering_interface_name_); + EXPECT_EQ( + state_intefaces.names[STATE_STEER_LEFT_WHEEL], + controller_->front_wheels_state_names_[1] + "/" + steering_interface_name_); + + // check ref itfsTIME + auto reference_interfaces = controller_->export_reference_interfaces(); + ASSERT_EQ(reference_interfaces.size(), joint_reference_interfaces_.size()); + for (size_t i = 0; i < joint_reference_interfaces_.size(); ++i) + { + const std::string ref_itf_name = + std::string(controller_->get_node()->get_name()) + "/" + joint_reference_interfaces_[i]; + EXPECT_EQ(reference_interfaces[i].get_name(), ref_itf_name); + EXPECT_EQ(reference_interfaces[i].get_prefix_name(), controller_->get_node()->get_name()); + EXPECT_EQ(reference_interfaces[i].get_interface_name(), joint_reference_interfaces_[i]); + } +} + +// Tests controller update_reference_from_subscribers and +// its two cases for position_feedback true/false behavior +// when too old msg is sent i.e age_of_last_command > ref_timeout case +TEST_F(SteeringControllersLibraryTest, test_both_update_methods_for_ref_timeout) +{ + SetUpController(); + + rclcpp::executors::MultiThreadedExecutor executor; + executor.add_node(controller_->get_node()->get_node_base_interface()); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + controller_->set_chained_mode(false); + ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_FALSE(controller_->is_in_chained_mode()); + + for (const auto & interface : controller_->reference_interfaces_) + { + EXPECT_TRUE(std::isnan(interface)); + } + + // set command statically + const double TEST_LINEAR_VELOCITY_X = 1.5; + const double TEST_LINEAR_VELOCITY_Y = 0.0; + const double TEST_ANGULAR_VELOCITY_Z = 0.3; + + std::shared_ptr msg = std::make_shared(); + + // adjusting to achieve age_of_last_command > ref_timeout + msg->header.stamp = controller_->get_node()->now() - controller_->ref_timeout_ - + rclcpp::Duration::from_seconds(0.1); + msg->twist.linear.x = TEST_LINEAR_VELOCITY_X; + msg->twist.linear.y = TEST_LINEAR_VELOCITY_Y; + msg->twist.linear.z = std::numeric_limits::quiet_NaN(); + msg->twist.angular.x = std::numeric_limits::quiet_NaN(); + msg->twist.angular.y = std::numeric_limits::quiet_NaN(); + msg->twist.angular.z = TEST_ANGULAR_VELOCITY_Z; + controller_->input_ref_.writeFromNonRT(msg); + + const auto age_of_last_command = + controller_->get_node()->now() - (*(controller_->input_ref_.readFromNonRT()))->header.stamp; + + // case 1 position_feedback = false + controller_->params_.position_feedback = false; + + // age_of_last_command > ref_timeout_ + ASSERT_FALSE(age_of_last_command <= controller_->ref_timeout_); + ASSERT_EQ((*(controller_->input_ref_.readFromRT()))->twist.linear.x, TEST_LINEAR_VELOCITY_X); + ASSERT_EQ( + controller_->update(controller_->get_node()->now(), rclcpp::Duration::from_seconds(0.01)), + controller_interface::return_type::OK); + + EXPECT_TRUE(std::isnan(controller_->reference_interfaces_[0])); + EXPECT_TRUE(std::isnan(controller_->reference_interfaces_[1])); + for (const auto & interface : controller_->reference_interfaces_) + { + EXPECT_TRUE(std::isnan(interface)); + } + EXPECT_TRUE(std::isnan((*(controller_->input_ref_.readFromNonRT()))->twist.linear.x)); + EXPECT_TRUE(std::isnan((*(controller_->input_ref_.readFromNonRT()))->twist.angular.z)); + + EXPECT_TRUE(std::isnan(controller_->reference_interfaces_[0])); + for (const auto & interface : controller_->reference_interfaces_) + { + EXPECT_TRUE(std::isnan(interface)); + } + + for (size_t i = 0; i < controller_->command_interfaces_.size(); ++i) + { + EXPECT_EQ(controller_->command_interfaces_[i].get_value(), 0); + } + + // case 2 position_feedback = true + controller_->params_.position_feedback = true; + + // adjusting to achieve age_of_last_command > ref_timeout + msg->header.stamp = controller_->get_node()->now() - controller_->ref_timeout_ - + rclcpp::Duration::from_seconds(0.1); + msg->twist.linear.x = TEST_LINEAR_VELOCITY_X; + msg->twist.linear.y = TEST_LINEAR_VELOCITY_Y; + msg->twist.linear.z = std::numeric_limits::quiet_NaN(); + msg->twist.angular.x = std::numeric_limits::quiet_NaN(); + msg->twist.angular.y = std::numeric_limits::quiet_NaN(); + msg->twist.angular.z = TEST_ANGULAR_VELOCITY_Z; + controller_->input_ref_.writeFromNonRT(msg); + + // age_of_last_command > ref_timeout_ + ASSERT_FALSE(age_of_last_command <= controller_->ref_timeout_); + ASSERT_EQ((*(controller_->input_ref_.readFromRT()))->twist.linear.x, TEST_LINEAR_VELOCITY_X); + ASSERT_EQ( + controller_->update(controller_->get_node()->now(), rclcpp::Duration::from_seconds(0.01)), + controller_interface::return_type::OK); + + EXPECT_TRUE(std::isnan(controller_->reference_interfaces_[0])); + EXPECT_TRUE(std::isnan(controller_->reference_interfaces_[1])); + for (const auto & interface : controller_->reference_interfaces_) + { + EXPECT_TRUE(std::isnan(interface)); + } + EXPECT_TRUE(std::isnan((*(controller_->input_ref_.readFromNonRT()))->twist.linear.x)); + EXPECT_TRUE(std::isnan((*(controller_->input_ref_.readFromNonRT()))->twist.angular.z)); + + EXPECT_TRUE(std::isnan(controller_->reference_interfaces_[0])); + for (const auto & interface : controller_->reference_interfaces_) + { + EXPECT_TRUE(std::isnan(interface)); + } + + for (size_t i = 0; i < controller_->command_interfaces_.size(); ++i) + { + EXPECT_EQ(controller_->command_interfaces_[i].get_value(), 0); + } +} + +int main(int argc, char ** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + rclcpp::init(argc, argv); + int result = RUN_ALL_TESTS(); + rclcpp::shutdown(); + return result; +} diff --git a/steering_controllers_library/test/test_steering_controllers_library.hpp b/steering_controllers_library/test/test_steering_controllers_library.hpp new file mode 100644 index 0000000000..23ab7b64f2 --- /dev/null +++ b/steering_controllers_library/test/test_steering_controllers_library.hpp @@ -0,0 +1,341 @@ +// Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef TEST_STEERING_CONTROLLERS_LIBRARY_HPP_ +#define TEST_STEERING_CONTROLLERS_LIBRARY_HPP_ + +#include +#include +#include +#include +#include +#include +#include + +#include "gmock/gmock.h" +#include "hardware_interface/loaned_command_interface.hpp" +#include "hardware_interface/loaned_state_interface.hpp" +#include "hardware_interface/types/hardware_interface_return_values.hpp" +#include "rclcpp/parameter_value.hpp" +#include "rclcpp/time.hpp" +#include "rclcpp/utilities.hpp" +#include "rclcpp_lifecycle/node_interfaces/lifecycle_node_interface.hpp" +#include "steering_controllers_library/steering_controllers_library.hpp" + +using ControllerStateMsg = + steering_controllers_library::SteeringControllersLibrary::AckermanControllerState; +using ControllerReferenceMsg = + steering_controllers_library::SteeringControllersLibrary::ControllerTwistReferenceMsg; + +// NOTE: Testing steering_controllers_library for ackermann vehicle configuration only + +// name constants for state interfaces +static constexpr size_t STATE_TRACTION_RIGHT_WHEEL = 0; +static constexpr size_t STATE_TRACTION_LEFT_WHEEL = 1; +static constexpr size_t STATE_STEER_RIGHT_WHEEL = 2; +static constexpr size_t STATE_STEER_LEFT_WHEEL = 3; + +// name constants for command interfaces +static constexpr size_t CMD_TRACTION_RIGHT_WHEEL = 0; +static constexpr size_t CMD_TRACTION_LEFT_WHEEL = 1; +static constexpr size_t CMD_STEER_RIGHT_WHEEL = 2; +static constexpr size_t CMD_STEER_LEFT_WHEEL = 3; + +static constexpr size_t NR_STATE_ITFS = 4; +static constexpr size_t NR_CMD_ITFS = 4; +static constexpr size_t NR_REF_ITFS = 2; + +static constexpr double WHEELBASE_ = 3.24644; +static constexpr double FRONT_WHEEL_TRACK_ = 2.12321; +static constexpr double REAR_WHEEL_TRACK_ = 1.76868; +static constexpr double FRONT_WHEELS_RADIUS_ = 0.45; +static constexpr double REAR_WHEELS_RADIUS_ = 0.45; + +namespace +{ +constexpr auto NODE_SUCCESS = controller_interface::CallbackReturn::SUCCESS; +constexpr auto NODE_ERROR = controller_interface::CallbackReturn::ERROR; +} // namespace +// namespace + +// subclassing and friending so we can access member variables +class TestableSteeringControllersLibrary +: public steering_controllers_library::SteeringControllersLibrary +{ + FRIEND_TEST(SteeringControllersLibraryTest, check_exported_intefaces); + FRIEND_TEST(SteeringControllersLibraryTest, test_both_update_methods_for_ref_timeout); + +public: + controller_interface::CallbackReturn on_configure( + const rclcpp_lifecycle::State & previous_state) override + { + auto ret = + steering_controllers_library::SteeringControllersLibrary::on_configure(previous_state); + // Only if on_configure is successful create subscription + if (ret == CallbackReturn::SUCCESS) + { + ref_subscriber_wait_set_.add_subscription(ref_subscriber_twist_); + } + return ret; + } + + controller_interface::CallbackReturn on_activate( + const rclcpp_lifecycle::State & previous_state) override + { + auto ref_itfs = on_export_reference_interfaces(); + return steering_controllers_library::SteeringControllersLibrary::on_activate(previous_state); + } + + /** + * @brief wait_for_command blocks until a new ControllerReferenceMsg is received. + * Requires that the executor is not spinned elsewhere between the + * message publication and the call to this function. + * + * @return true if new ControllerReferenceMsg msg was received, false if timeout. + */ + bool wait_for_command( + rclcpp::Executor & executor, rclcpp::WaitSet & subscriber_wait_set, + const std::chrono::milliseconds & timeout = std::chrono::milliseconds{500}) + { + bool success = subscriber_wait_set.wait(timeout).kind() == rclcpp::WaitResultKind::Ready; + if (success) + { + executor.spin_some(); + } + return success; + } + + bool wait_for_commands( + rclcpp::Executor & executor, + const std::chrono::milliseconds & timeout = std::chrono::milliseconds{500}) + { + return wait_for_command(executor, ref_subscriber_wait_set_, timeout); + } + + // implementing methods which are declared virtual in the steering_controllers_library.hpp + void initialize_implementation_parameter_listener() + { + param_listener_ = std::make_shared(get_node()); + } + + controller_interface::CallbackReturn configure_odometry() + { + set_interface_numbers(NR_STATE_ITFS, NR_CMD_ITFS, NR_REF_ITFS); + odometry_.set_wheel_params(FRONT_WHEELS_RADIUS_, WHEELBASE_, REAR_WHEEL_TRACK_); + odometry_.set_odometry_type(steering_odometry::ACKERMANN_CONFIG); + + return controller_interface::CallbackReturn::SUCCESS; + } + + bool update_odometry(const rclcpp::Duration & period) { return true; } + +private: + rclcpp::WaitSet ref_subscriber_wait_set_; +}; + +// We are using template class here for easier reuse of Fixture in specializations of controllers +template +class SteeringControllersLibraryFixture : public ::testing::Test +{ +public: + static void SetUpTestCase() {} + + void SetUp() + { + // initialize controller + controller_ = std::make_unique(); + + command_publisher_node_ = std::make_shared("command_publisher"); + command_publisher_ = command_publisher_node_->create_publisher( + "/test_steering_controllers_library/reference", rclcpp::SystemDefaultsQoS()); + } + + static void TearDownTestCase() {} + + void TearDown() { controller_.reset(nullptr); } + +protected: + void SetUpController(const std::string controller_name = "test_steering_controllers_library") + { + ASSERT_EQ(controller_->init(controller_name), controller_interface::return_type::OK); + + if (position_feedback_ == true) + { + traction_interface_name_ = "position"; + } + else + { + traction_interface_name_ = "velocity"; + } + + std::vector command_ifs; + command_itfs_.reserve(joint_command_values_.size()); + command_ifs.reserve(joint_command_values_.size()); + + command_itfs_.emplace_back(hardware_interface::CommandInterface( + rear_wheels_names_[0], traction_interface_name_, + &joint_command_values_[CMD_TRACTION_RIGHT_WHEEL])); + command_ifs.emplace_back(command_itfs_.back()); + + command_itfs_.emplace_back(hardware_interface::CommandInterface( + rear_wheels_names_[1], steering_interface_name_, + &joint_command_values_[CMD_TRACTION_LEFT_WHEEL])); + command_ifs.emplace_back(command_itfs_.back()); + + command_itfs_.emplace_back(hardware_interface::CommandInterface( + front_wheels_names_[0], steering_interface_name_, + &joint_command_values_[CMD_STEER_RIGHT_WHEEL])); + command_ifs.emplace_back(command_itfs_.back()); + + command_itfs_.emplace_back(hardware_interface::CommandInterface( + front_wheels_names_[1], steering_interface_name_, + &joint_command_values_[CMD_STEER_LEFT_WHEEL])); + command_ifs.emplace_back(command_itfs_.back()); + + std::vector state_ifs; + state_itfs_.reserve(joint_state_values_.size()); + state_ifs.reserve(joint_state_values_.size()); + + state_itfs_.emplace_back(hardware_interface::StateInterface( + rear_wheels_names_[0], traction_interface_name_, + &joint_state_values_[STATE_TRACTION_RIGHT_WHEEL])); + state_ifs.emplace_back(state_itfs_.back()); + + state_itfs_.emplace_back(hardware_interface::StateInterface( + rear_wheels_names_[1], traction_interface_name_, + &joint_state_values_[STATE_TRACTION_LEFT_WHEEL])); + state_ifs.emplace_back(state_itfs_.back()); + + state_itfs_.emplace_back(hardware_interface::StateInterface( + front_wheels_names_[0], steering_interface_name_, + &joint_state_values_[STATE_STEER_RIGHT_WHEEL])); + state_ifs.emplace_back(state_itfs_.back()); + + state_itfs_.emplace_back(hardware_interface::StateInterface( + front_wheels_names_[1], steering_interface_name_, + &joint_state_values_[STATE_STEER_LEFT_WHEEL])); + state_ifs.emplace_back(state_itfs_.back()); + + controller_->assign_interfaces(std::move(command_ifs), std::move(state_ifs)); + } + + void subscribe_and_get_messages(ControllerStateMsg & msg) + { + // create a new subscriber + rclcpp::Node test_subscription_node("test_subscription_node"); + auto subs_callback = [&](const ControllerStateMsg::SharedPtr) {}; + auto subscription = test_subscription_node.create_subscription( + "/test_steering_controllers_library/controller_state", 10, subs_callback); + + // call update to publish the test value + ASSERT_EQ( + controller_->update(rclcpp::Time(0, 0, RCL_ROS_TIME), rclcpp::Duration::from_seconds(0.01)), + controller_interface::return_type::OK); + + // call update to publish the test value + // since update doesn't guarantee a published message, republish until received + int max_sub_check_loop_count = 5; // max number of tries for pub/sub loop + rclcpp::WaitSet wait_set; // block used to wait on message + wait_set.add_subscription(subscription); + while (max_sub_check_loop_count--) + { + controller_->update(rclcpp::Time(0, 0, RCL_ROS_TIME), rclcpp::Duration::from_seconds(0.01)); + // check if message has been received + if (wait_set.wait(std::chrono::milliseconds(2)).kind() == rclcpp::WaitResultKind::Ready) + { + break; + } + } + ASSERT_GE(max_sub_check_loop_count, 0) << "Test was unable to publish a message through " + "controller/broadcaster update loop"; + + // take message from subscription + rclcpp::MessageInfo msg_info; + ASSERT_TRUE(subscription->take(msg, msg_info)); + } + + void publish_commands(const double linear = 0.1, const double angular = 0.2) + { + auto wait_for_topic = [&](const auto topic_name) + { + size_t wait_count = 0; + while (command_publisher_node_->count_subscribers(topic_name) == 0) + { + if (wait_count >= 5) + { + auto error_msg = + std::string("publishing to ") + topic_name + " but no node subscribes to it"; + throw std::runtime_error(error_msg); + } + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + ++wait_count; + } + }; + + wait_for_topic(command_publisher_->get_topic_name()); + + ControllerReferenceMsg msg; + msg.twist.linear.x = linear; + msg.twist.angular.z = angular; + + command_publisher_->publish(msg); + } + +protected: + // Controller-related parameters + double reference_timeout_ = 2.0; + bool front_steering_ = true; + bool open_loop_ = false; + unsigned int velocity_rolling_window_size_ = 10; + bool position_feedback_ = false; + bool use_stamped_vel_ = true; + std::vector rear_wheels_names_ = {"rear_right_wheel_joint", "rear_left_wheel_joint"}; + std::vector front_wheels_names_ = { + "front_right_steering_joint", "front_left_steering_joint"}; + std::vector joint_names_ = { + rear_wheels_names_[0], rear_wheels_names_[1], front_wheels_names_[0], front_wheels_names_[1]}; + + std::vector rear_wheels_preceeding_names_ = { + "pid_controller/rear_right_wheel_joint", "pid_controller/rear_left_wheel_joint"}; + std::vector front_wheels_preceeding_names_ = { + "pid_controller/front_right_steering_joint", "pid_controller/front_left_steering_joint"}; + std::vector preceeding_joint_names_ = { + rear_wheels_preceeding_names_[0], rear_wheels_preceeding_names_[1], + front_wheels_preceeding_names_[0], front_wheels_preceeding_names_[1]}; + + double wheelbase_ = 3.24644; + double front_wheel_track_ = 2.12321; + double rear_wheel_track_ = 1.76868; + double front_wheels_radius_ = 0.45; + double rear_wheels_radius_ = 0.45; + + std::array joint_state_values_ = {0.5, 0.5, 0.0, 0.0}; + std::array joint_command_values_ = {1.1, 3.3, 2.2, 4.4}; + + std::array joint_reference_interfaces_ = {"linear/velocity", "angular/position"}; + std::string steering_interface_name_ = "position"; + // defined in setup + std::string traction_interface_name_ = ""; + std::string preceeding_prefix_ = "pid_controller"; + + std::vector state_itfs_; + std::vector command_itfs_; + + // Test related parameters + std::unique_ptr controller_; + rclcpp::Node::SharedPtr command_publisher_node_; + rclcpp::Publisher::SharedPtr command_publisher_; +}; + +#endif // TEST_STEERING_CONTROLLERS_LIBRARY_HPP_ diff --git a/tricycle_steering_controller/CMakeLists.txt b/tricycle_steering_controller/CMakeLists.txt new file mode 100644 index 0000000000..c604b89452 --- /dev/null +++ b/tricycle_steering_controller/CMakeLists.txt @@ -0,0 +1,105 @@ +cmake_minimum_required(VERSION 3.16) +project(tricycle_steering_controller LANGUAGES CXX) + +if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +# find dependencies +set(THIS_PACKAGE_INCLUDE_DEPENDS + controller_interface + hardware_interface + generate_parameter_library + pluginlib + rclcpp + rclcpp_lifecycle + realtime_tools + std_srvs + steering_controllers_library +) + +find_package(ament_cmake REQUIRED) +find_package(backward_ros REQUIRED) +foreach(Dependency IN ITEMS ${THIS_PACKAGE_INCLUDE_DEPENDS}) + find_package(${Dependency} REQUIRED) +endforeach() + +generate_parameter_library(tricycle_steering_controller_parameters + src/tricycle_steering_controller.yaml +) + +add_library( + tricycle_steering_controller + SHARED + src/tricycle_steering_controller.cpp +) +target_compile_features(tricycle_steering_controller PUBLIC cxx_std_17) +target_include_directories(tricycle_steering_controller PUBLIC + "$" + "$") +target_link_libraries(tricycle_steering_controller PUBLIC + tricycle_steering_controller_parameters) +ament_target_dependencies(tricycle_steering_controller PUBLIC ${THIS_PACKAGE_INCLUDE_DEPENDS}) + +# Causes the visibility macros to use dllexport rather than dllimport, +# which is appropriate when building the dll but not consuming it. +target_compile_definitions(tricycle_steering_controller PRIVATE "ACKERMANN_STEERING_CONTROLLER_BUILDING_DLL") + +pluginlib_export_plugin_description_file( + controller_interface tricycle_steering_controller.xml) + +if(BUILD_TESTING) + find_package(ament_cmake_gmock REQUIRED) + find_package(controller_manager REQUIRED) + find_package(hardware_interface REQUIRED) + find_package(ros2_control_test_assets REQUIRED) + + add_rostest_with_parameters_gmock(test_load_tricycle_steering_controller + test/test_load_tricycle_steering_controller.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test/tricycle_steering_controller_params.yaml + ) + ament_target_dependencies(test_load_tricycle_steering_controller + controller_manager + hardware_interface + ros2_control_test_assets + ) + + add_rostest_with_parameters_gmock( + test_tricycle_steering_controller test/test_tricycle_steering_controller.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test/tricycle_steering_controller_params.yaml) + target_include_directories(test_tricycle_steering_controller PRIVATE include) + target_link_libraries(test_tricycle_steering_controller tricycle_steering_controller) + ament_target_dependencies( + test_tricycle_steering_controller + controller_interface + hardware_interface + ) + + add_rostest_with_parameters_gmock( + test_tricycle_steering_controller_preceeding test/test_tricycle_steering_controller_preceeding.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test/tricycle_steering_controller_preceeding_params.yaml) + target_include_directories(test_tricycle_steering_controller_preceeding PRIVATE include) + target_link_libraries(test_tricycle_steering_controller_preceeding tricycle_steering_controller) + ament_target_dependencies( + test_tricycle_steering_controller_preceeding + controller_interface + hardware_interface + ) +endif() + +install( + DIRECTORY include/ + DESTINATION include/tricycle_steering_controller +) + +install( + TARGETS tricycle_steering_controller tricycle_steering_controller_parameters + EXPORT export_tricycle_steering_controller + RUNTIME DESTINATION bin + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib +) + +ament_export_targets(export_tricycle_steering_controller HAS_LIBRARY_TARGET) +ament_export_dependencies(${THIS_PACKAGE_INCLUDE_DEPENDS}) +ament_package() diff --git a/tricycle_steering_controller/doc/userdocs.rst b/tricycle_steering_controller/doc/userdocs.rst new file mode 100644 index 0000000000..9a6adfca37 --- /dev/null +++ b/tricycle_steering_controller/doc/userdocs.rst @@ -0,0 +1,18 @@ +.. _tricycle_steering_controller_userdoc: + +tricycle_steering_controller +============================= + +This controller implements the kinematics with two axes and three wheels, where two wheels on an axis are fixed (traction/drive), and the wheel on the other axis is steerable. + +The controller expects to have two commanding joints for traction, one for each fixed wheel and one commanding joint for steering. + +For more details on controller's execution and interfaces check the :ref:`Steering Controller Library `. + + +Parameters +,,,,,,,,,,, + +For list of parameters and their meaning YAML file in the ``src`` folder of the controller's package. + +For an exemplary parameterization see the ``test`` folder of the controller's package. diff --git a/tricycle_steering_controller/include/tricycle_steering_controller/tricycle_steering_controller.hpp b/tricycle_steering_controller/include/tricycle_steering_controller/tricycle_steering_controller.hpp new file mode 100644 index 0000000000..607a684df5 --- /dev/null +++ b/tricycle_steering_controller/include/tricycle_steering_controller/tricycle_steering_controller.hpp @@ -0,0 +1,63 @@ +// Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Authors: dr. sc. Tomislav Petkovic, Dr. Ing. Denis Štogl +// + +#ifndef TRICYCLE_STEERING_CONTROLLER__TRICYCLE_STEERING_CONTROLLER_HPP_ +#define TRICYCLE_STEERING_CONTROLLER__TRICYCLE_STEERING_CONTROLLER_HPP_ + +#include + +#include "steering_controllers_library/steering_controllers_library.hpp" +#include "tricycle_steering_controller/visibility_control.h" +#include "tricycle_steering_controller_parameters.hpp" + +namespace tricycle_steering_controller +{ +// name constants for state interfaces +static constexpr size_t STATE_TRACTION_RIGHT_WHEEL = 0; +static constexpr size_t STATE_TRACTION_LEFT_WHEEL = 1; +static constexpr size_t STATE_STEER_AXIS = 2; + +// name constants for command interfaces +static constexpr size_t CMD_TRACTION_RIGHT_WHEEL = 0; +static constexpr size_t CMD_TRACTION_LEFT_WHEEL = 1; +static constexpr size_t CMD_STEER_WHEEL = 2; + +static constexpr size_t NR_STATE_ITFS = 3; +static constexpr size_t NR_CMD_ITFS = 3; +static constexpr size_t NR_REF_ITFS = 2; + +class TricycleSteeringController : public steering_controllers_library::SteeringControllersLibrary +{ +public: + TricycleSteeringController(); + + STEERING_CONTROLLERS__VISIBILITY_PUBLIC controller_interface::CallbackReturn configure_odometry() + override; + + STEERING_CONTROLLERS__VISIBILITY_PUBLIC bool update_odometry( + const rclcpp::Duration & period) override; + + STEERING_CONTROLLERS__VISIBILITY_PUBLIC void initialize_implementation_parameter_listener() + override; + +protected: + std::shared_ptr tricycle_param_listener_; + tricycle_steering_controller::Params tricycle_params_; +}; +} // namespace tricycle_steering_controller + +#endif // TRICYCLE_STEERING_CONTROLLER__TRICYCLE_STEERING_CONTROLLER_HPP_ diff --git a/tricycle_steering_controller/include/tricycle_steering_controller/visibility_control.h b/tricycle_steering_controller/include/tricycle_steering_controller/visibility_control.h new file mode 100644 index 0000000000..606b067ad8 --- /dev/null +++ b/tricycle_steering_controller/include/tricycle_steering_controller/visibility_control.h @@ -0,0 +1,52 @@ +// Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef TRICYCLE_STEERING_CONTROLLER__VISIBILITY_CONTROL_H_ +#define TRICYCLE_STEERING_CONTROLLER__VISIBILITY_CONTROL_H_ + +// This logic was borrowed (then namespaced) from the examples on the gcc wiki: +// https://gcc.gnu.org/wiki/Visibility + +#if defined _WIN32 || defined __CYGWIN__ +#ifdef __GNUC__ +#define TRICYCLE_STEERING_CONTROLLER__VISIBILITY_EXPORT __attribute__((dllexport)) +#define TRICYCLE_STEERING_CONTROLLER__VISIBILITY_IMPORT __attribute__((dllimport)) +#else +#define TRICYCLE_STEERING_CONTROLLER__VISIBILITY_EXPORT __declspec(dllexport) +#define TRICYCLE_STEERING_CONTROLLER__VISIBILITY_IMPORT __declspec(dllimport) +#endif +#ifdef TRICYCLE_STEERING_CONTROLLER__VISIBILITY_BUILDING_DLL +#define TRICYCLE_STEERING_CONTROLLER__VISIBILITY_PUBLIC \ + TRICYCLE_STEERING_CONTROLLER__VISIBILITY_EXPORT +#else +#define TRICYCLE_STEERING_CONTROLLER__VISIBILITY_PUBLIC \ + TRICYCLE_STEERING_CONTROLLER__VISIBILITY_IMPORT +#endif +#define TRICYCLE_STEERING_CONTROLLER__VISIBILITY_PUBLIC_TYPE \ + TRICYCLE_STEERING_CONTROLLER__VISIBILITY_PUBLIC +#define TRICYCLE_STEERING_CONTROLLER__VISIBILITY_LOCAL +#else +#define TRICYCLE_STEERING_CONTROLLER__VISIBILITY_EXPORT __attribute__((visibility("default"))) +#define TRICYCLE_STEERING_CONTROLLER__VISIBILITY_IMPORT +#if __GNUC__ >= 4 +#define TRICYCLE_STEERING_CONTROLLER__VISIBILITY_PUBLIC __attribute__((visibility("default"))) +#define TRICYCLE_STEERING_CONTROLLER__VISIBILITY_LOCAL __attribute__((visibility("hidden"))) +#else +#define TRICYCLE_STEERING_CONTROLLER__VISIBILITY_PUBLIC +#define TRICYCLE_STEERING_CONTROLLER__VISIBILITY_LOCAL +#endif +#define TRICYCLE_STEERING_CONTROLLER__VISIBILITY_PUBLIC_TYPE +#endif + +#endif // TRICYCLE_STEERING_CONTROLLER__VISIBILITY_CONTROL_H_ diff --git a/tricycle_steering_controller/package.xml b/tricycle_steering_controller/package.xml new file mode 100644 index 0000000000..e911041cd1 --- /dev/null +++ b/tricycle_steering_controller/package.xml @@ -0,0 +1,38 @@ + + + + tricycle_steering_controller + 0.0.0 + Steering controller with tricycle kinematics. Rear fixed wheels are powering the vehicle and front wheel is steering. + Apache License 2.0 + Bence Magyar + Dr.-Ing. Denis Štogl + dr. sc. Tomislav Petkovic + Tony Najjar + + Dr.-Ing. Denis Štogl + dr. sc. Tomislav Petkovic + Tony Najjar + + ament_cmake + + generate_parameter_library + + control_msgs + controller_interface + hardware_interface + pluginlib + rclcpp + rclcpp_lifecycle + std_srvs + steering_controllers_library + + ament_cmake_gmock + controller_manager + hardware_interface + ros2_control_test_assets + + + ament_cmake + + diff --git a/tricycle_steering_controller/src/tricycle_steering_controller.cpp b/tricycle_steering_controller/src/tricycle_steering_controller.cpp new file mode 100644 index 0000000000..f89d78a52c --- /dev/null +++ b/tricycle_steering_controller/src/tricycle_steering_controller.cpp @@ -0,0 +1,93 @@ +// Copyright 2022 Pixel Robotics. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "tricycle_steering_controller/tricycle_steering_controller.hpp" + +namespace tricycle_steering_controller +{ +TricycleSteeringController::TricycleSteeringController() +: steering_controllers_library::SteeringControllersLibrary() +{ +} +void TricycleSteeringController::initialize_implementation_parameter_listener() +{ + tricycle_param_listener_ = + std::make_shared(get_node()); +} + +controller_interface::CallbackReturn TricycleSteeringController::configure_odometry() +{ + tricycle_params_ = tricycle_param_listener_->get_params(); + + const double front_wheels_radius = tricycle_params_.front_wheels_radius; + const double rear_wheels_radius = tricycle_params_.rear_wheels_radius; + const double wheel_track = tricycle_params_.wheel_track; + const double wheelbase = tricycle_params_.wheelbase; + + if (params_.front_steering) + { + odometry_.set_wheel_params(rear_wheels_radius, wheelbase, wheel_track); + } + else + { + odometry_.set_wheel_params(front_wheels_radius, wheelbase, wheel_track); + } + + odometry_.set_odometry_type(steering_odometry::TRICYCLE_CONFIG); + + set_interface_numbers(NR_STATE_ITFS, NR_CMD_ITFS, NR_REF_ITFS); + + RCLCPP_INFO(get_node()->get_logger(), "tricycle odom configure successful"); + return controller_interface::CallbackReturn::SUCCESS; +} + +bool TricycleSteeringController::update_odometry(const rclcpp::Duration & period) +{ + if (params_.open_loop) + { + odometry_.update_open_loop(last_linear_velocity_, last_angular_velocity_, period.seconds()); + } + else + { + const double rear_right_wheel_value = state_interfaces_[STATE_TRACTION_RIGHT_WHEEL].get_value(); + const double rear_left_wheel_value = state_interfaces_[STATE_TRACTION_LEFT_WHEEL].get_value(); + const double steer_position = state_interfaces_[STATE_STEER_AXIS].get_value(); + if ( + !std::isnan(rear_right_wheel_value) && !std::isnan(rear_left_wheel_value) && + !std::isnan(steer_position)) + { + if (params_.position_feedback) + { + // Estimate linear and angular velocity using joint information + odometry_.update_from_position( + rear_right_wheel_value, rear_left_wheel_value, steer_position, period.seconds()); + } + else + { + // Estimate linear and angular velocity using joint information + odometry_.update_from_velocity( + rear_right_wheel_value, rear_left_wheel_value, steer_position, period.seconds()); + } + } + } + return true; +} + +} // namespace tricycle_steering_controller + +#include "pluginlib/class_list_macros.hpp" + +PLUGINLIB_EXPORT_CLASS( + tricycle_steering_controller::TricycleSteeringController, + controller_interface::ChainableControllerInterface) diff --git a/tricycle_steering_controller/src/tricycle_steering_controller.yaml b/tricycle_steering_controller/src/tricycle_steering_controller.yaml new file mode 100644 index 0000000000..1015865fd9 --- /dev/null +++ b/tricycle_steering_controller/src/tricycle_steering_controller.yaml @@ -0,0 +1,32 @@ +tricycle_steering_controller: + wheel_track: + { + type: double, + default_value: 0.0, + description: "Wheel track length. For details see: https://en.wikipedia.org/wiki/Wheelbase", + read_only: false, + } + + wheelbase: + { + type: double, + default_value: 0.0, + description: "Distance between front and rear wheels. For details see: https://en.wikipedia.org/wiki/Wheelbase", + read_only: false, + } + + front_wheels_radius: + { + type: double, + default_value: 0.0, + description: "Front wheels radius.", + read_only: false, + } + + rear_wheels_radius: + { + type: double, + default_value: 0.0, + description: "Rear wheels radius.", + read_only: false, + } diff --git a/tricycle_steering_controller/test/test_load_tricycle_steering_controller.cpp b/tricycle_steering_controller/test/test_load_tricycle_steering_controller.cpp new file mode 100644 index 0000000000..0d04afdf38 --- /dev/null +++ b/tricycle_steering_controller/test/test_load_tricycle_steering_controller.cpp @@ -0,0 +1,49 @@ +// Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include + +#include "controller_manager/controller_manager.hpp" +#include "hardware_interface/resource_manager.hpp" +#include "rclcpp/executor.hpp" +#include "rclcpp/executors/single_threaded_executor.hpp" +#include "rclcpp/utilities.hpp" +#include "ros2_control_test_assets/descriptions.hpp" + +TEST(TestLoadTricycleSteeringController, load_controller) +{ + std::shared_ptr executor = + std::make_shared(); + + controller_manager::ControllerManager cm( + std::make_unique( + ros2_control_test_assets::minimal_robot_urdf), + executor, "test_controller_manager"); + + ASSERT_NE( + cm.load_controller( + "test_tricycle_steering_controller", + "tricycle_steering_controller/TricycleSteeringController"), + nullptr); +} + +int main(int argc, char ** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + rclcpp::init(argc, argv); + int result = RUN_ALL_TESTS(); + rclcpp::shutdown(); + return result; +} diff --git a/tricycle_steering_controller/test/test_tricycle_steering_controller.cpp b/tricycle_steering_controller/test/test_tricycle_steering_controller.cpp new file mode 100644 index 0000000000..82ba924305 --- /dev/null +++ b/tricycle_steering_controller/test/test_tricycle_steering_controller.cpp @@ -0,0 +1,274 @@ +// Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "test_tricycle_steering_controller.hpp" + +#include +#include +#include +#include +#include + +class TricycleSteeringControllerTest +: public TricycleSteeringControllerFixture +{ +}; + +TEST_F(TricycleSteeringControllerTest, all_parameters_set_configure_success) +{ + SetUpController(); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + + ASSERT_THAT( + controller_->params_.rear_wheels_names, testing::ElementsAreArray(rear_wheels_names_)); + ASSERT_THAT( + controller_->params_.front_wheels_names, testing::ElementsAreArray(front_wheels_names_)); + ASSERT_EQ(controller_->params_.front_steering, front_steering_); + ASSERT_EQ(controller_->params_.open_loop, open_loop_); + ASSERT_EQ(controller_->params_.velocity_rolling_window_size, velocity_rolling_window_size_); + ASSERT_EQ(controller_->params_.position_feedback, position_feedback_); + ASSERT_EQ(controller_->tricycle_params_.wheelbase, wheelbase_); + ASSERT_EQ(controller_->tricycle_params_.front_wheels_radius, front_wheels_radius_); + ASSERT_EQ(controller_->tricycle_params_.rear_wheels_radius, rear_wheels_radius_); + ASSERT_EQ(controller_->tricycle_params_.wheel_track, wheel_track_); +} + +TEST_F(TricycleSteeringControllerTest, check_exported_intefaces) +{ + SetUpController(); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + + auto command_intefaces = controller_->command_interface_configuration(); + ASSERT_EQ(command_intefaces.names.size(), joint_command_values_.size()); + EXPECT_EQ( + command_intefaces.names[CMD_TRACTION_RIGHT_WHEEL], + rear_wheels_names_[0] + "/" + traction_interface_name_); + EXPECT_EQ( + command_intefaces.names[CMD_TRACTION_LEFT_WHEEL], + rear_wheels_names_[1] + "/" + traction_interface_name_); + EXPECT_EQ( + command_intefaces.names[CMD_STEER_WHEEL], + front_wheels_names_[0] + "/" + steering_interface_name_); + + auto state_intefaces = controller_->state_interface_configuration(); + ASSERT_EQ(state_intefaces.names.size(), joint_state_values_.size()); + EXPECT_EQ( + state_intefaces.names[STATE_TRACTION_RIGHT_WHEEL], + controller_->rear_wheels_state_names_[0] + "/" + traction_interface_name_); + EXPECT_EQ( + state_intefaces.names[STATE_TRACTION_LEFT_WHEEL], + controller_->rear_wheels_state_names_[1] + "/" + traction_interface_name_); + EXPECT_EQ( + state_intefaces.names[STATE_STEER_AXIS], + controller_->front_wheels_state_names_[0] + "/" + steering_interface_name_); + + // check ref itfsTIME + auto reference_interfaces = controller_->export_reference_interfaces(); + ASSERT_EQ(reference_interfaces.size(), joint_reference_interfaces_.size()); + for (size_t i = 0; i < joint_reference_interfaces_.size(); ++i) + { + const std::string ref_itf_name = + std::string(controller_->get_node()->get_name()) + "/" + joint_reference_interfaces_[i]; + EXPECT_EQ(reference_interfaces[i].get_name(), ref_itf_name); + EXPECT_EQ(reference_interfaces[i].get_prefix_name(), controller_->get_node()->get_name()); + EXPECT_EQ(reference_interfaces[i].get_interface_name(), joint_reference_interfaces_[i]); + } +} + +TEST_F(TricycleSteeringControllerTest, activate_success) +{ + SetUpController(); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + + // check that the message is reset + auto msg = controller_->input_ref_.readFromNonRT(); + EXPECT_TRUE(std::isnan((*msg)->twist.linear.x)); + EXPECT_TRUE(std::isnan((*msg)->twist.linear.y)); + EXPECT_TRUE(std::isnan((*msg)->twist.linear.z)); + EXPECT_TRUE(std::isnan((*msg)->twist.angular.x)); + EXPECT_TRUE(std::isnan((*msg)->twist.angular.y)); + EXPECT_TRUE(std::isnan((*msg)->twist.angular.z)); +} + +TEST_F(TricycleSteeringControllerTest, update_success) +{ + SetUpController(); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + + ASSERT_EQ( + controller_->update(rclcpp::Time(0, 0, RCL_ROS_TIME), rclcpp::Duration::from_seconds(0.01)), + controller_interface::return_type::OK); +} + +TEST_F(TricycleSteeringControllerTest, deactivate_success) +{ + SetUpController(); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_EQ(controller_->on_deactivate(rclcpp_lifecycle::State()), NODE_SUCCESS); +} + +TEST_F(TricycleSteeringControllerTest, reactivate_success) +{ + SetUpController(); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_EQ(controller_->on_deactivate(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_TRUE(std::isnan(controller_->command_interfaces_[0].get_value())); + ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_TRUE(std::isnan(controller_->command_interfaces_[0].get_value())); + + ASSERT_EQ( + controller_->update(rclcpp::Time(0, 0, RCL_ROS_TIME), rclcpp::Duration::from_seconds(0.01)), + controller_interface::return_type::OK); +} + +TEST_F(TricycleSteeringControllerTest, test_update_logic) +{ + SetUpController(); + rclcpp::executors::MultiThreadedExecutor executor; + executor.add_node(controller_->get_node()->get_node_base_interface()); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + controller_->set_chained_mode(false); + ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_FALSE(controller_->is_in_chained_mode()); + + // set command statically + std::shared_ptr msg = std::make_shared(); + msg->header.stamp = controller_->get_node()->now(); + msg->twist.linear.x = 0.1; + msg->twist.angular.z = 0.2; + controller_->input_ref_.writeFromNonRT(msg); + + ASSERT_EQ( + controller_->update(rclcpp::Time(0, 0, RCL_ROS_TIME), rclcpp::Duration::from_seconds(0.01)), + controller_interface::return_type::OK); + + EXPECT_NEAR( + controller_->command_interfaces_[CMD_TRACTION_RIGHT_WHEEL].get_value(), 0.22222222222222224, + COMMON_THRESHOLD); + EXPECT_NEAR( + controller_->command_interfaces_[CMD_TRACTION_LEFT_WHEEL].get_value(), 0.22222222222222224, + COMMON_THRESHOLD); + EXPECT_NEAR( + controller_->command_interfaces_[CMD_STEER_WHEEL].get_value(), 1.4179821977774734, + COMMON_THRESHOLD); + + EXPECT_FALSE(std::isnan((*(controller_->input_ref_.readFromRT()))->twist.linear.x)); + EXPECT_EQ(controller_->reference_interfaces_.size(), joint_reference_interfaces_.size()); + for (const auto & interface : controller_->reference_interfaces_) + { + EXPECT_TRUE(std::isnan(interface)); + } +} + +TEST_F(TricycleSteeringControllerTest, test_update_logic_chained) +{ + SetUpController(); + rclcpp::executors::MultiThreadedExecutor executor; + executor.add_node(controller_->get_node()->get_node_base_interface()); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + controller_->set_chained_mode(true); + ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_TRUE(controller_->is_in_chained_mode()); + + controller_->reference_interfaces_[0] = 0.1; + controller_->reference_interfaces_[1] = 0.2; + + ASSERT_EQ( + controller_->update(rclcpp::Time(0, 0, RCL_ROS_TIME), rclcpp::Duration::from_seconds(0.01)), + controller_interface::return_type::OK); + + EXPECT_NEAR( + controller_->command_interfaces_[CMD_TRACTION_RIGHT_WHEEL].get_value(), 0.22222222222222224, + COMMON_THRESHOLD); + EXPECT_NEAR( + controller_->command_interfaces_[CMD_TRACTION_LEFT_WHEEL].get_value(), 0.22222222222222224, + COMMON_THRESHOLD); + EXPECT_NEAR( + controller_->command_interfaces_[CMD_STEER_WHEEL].get_value(), 1.4179821977774734, + COMMON_THRESHOLD); + + EXPECT_TRUE(std::isnan((*(controller_->input_ref_.readFromRT()))->twist.linear.x)); + EXPECT_EQ(controller_->reference_interfaces_.size(), joint_reference_interfaces_.size()); + for (const auto & interface : controller_->reference_interfaces_) + { + EXPECT_TRUE(std::isnan(interface)); + } +} + +TEST_F(TricycleSteeringControllerTest, receive_message_and_publish_updated_status) +{ + SetUpController(); + rclcpp::executors::MultiThreadedExecutor executor; + executor.add_node(controller_->get_node()->get_node_base_interface()); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + + ASSERT_EQ( + controller_->update(rclcpp::Time(0, 0, RCL_ROS_TIME), rclcpp::Duration::from_seconds(0.01)), + controller_interface::return_type::OK); + + ControllerStateMsg msg; + subscribe_and_get_messages(msg); + + EXPECT_EQ(msg.linear_velocity_command[STATE_TRACTION_RIGHT_WHEEL], 1.1); + EXPECT_EQ(msg.linear_velocity_command[STATE_TRACTION_LEFT_WHEEL], 3.3); + EXPECT_EQ(msg.steering_angle_command[0], 2.2); + + publish_commands(); + ASSERT_TRUE(controller_->wait_for_commands(executor)); + + ASSERT_EQ( + controller_->update(rclcpp::Time(0, 0, RCL_ROS_TIME), rclcpp::Duration::from_seconds(0.01)), + controller_interface::return_type::OK); + + EXPECT_NEAR( + controller_->command_interfaces_[CMD_TRACTION_RIGHT_WHEEL].get_value(), 0.22222222222222224, + COMMON_THRESHOLD); + EXPECT_NEAR( + controller_->command_interfaces_[CMD_TRACTION_LEFT_WHEEL].get_value(), 0.22222222222222224, + COMMON_THRESHOLD); + EXPECT_NEAR( + controller_->command_interfaces_[CMD_STEER_WHEEL].get_value(), 1.4179821977774734, + COMMON_THRESHOLD); + + subscribe_and_get_messages(msg); + + EXPECT_NEAR( + msg.linear_velocity_command[STATE_TRACTION_RIGHT_WHEEL], 0.22222222222222224, COMMON_THRESHOLD); + EXPECT_NEAR( + msg.linear_velocity_command[STATE_TRACTION_LEFT_WHEEL], 0.22222222222222224, COMMON_THRESHOLD); + EXPECT_NEAR(msg.steering_angle_command[0], 1.4179821977774734, COMMON_THRESHOLD); +} + +int main(int argc, char ** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + rclcpp::init(argc, argv); + int result = RUN_ALL_TESTS(); + rclcpp::shutdown(); + return result; +} diff --git a/tricycle_steering_controller/test/test_tricycle_steering_controller.hpp b/tricycle_steering_controller/test/test_tricycle_steering_controller.hpp new file mode 100644 index 0000000000..422f399ad4 --- /dev/null +++ b/tricycle_steering_controller/test/test_tricycle_steering_controller.hpp @@ -0,0 +1,302 @@ +// Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef TEST_TRICYCLE_STEERING_CONTROLLER_HPP_ +#define TEST_TRICYCLE_STEERING_CONTROLLER_HPP_ + +#include +#include +#include +#include +#include +#include +#include + +#include "gmock/gmock.h" +#include "hardware_interface/loaned_command_interface.hpp" +#include "hardware_interface/loaned_state_interface.hpp" +#include "hardware_interface/types/hardware_interface_return_values.hpp" +#include "rclcpp/parameter_value.hpp" +#include "rclcpp/time.hpp" +#include "rclcpp/utilities.hpp" +#include "rclcpp_lifecycle/node_interfaces/lifecycle_node_interface.hpp" +#include "tricycle_steering_controller/tricycle_steering_controller.hpp" + +using ControllerStateMsg = + steering_controllers_library::SteeringControllersLibrary::AckermanControllerState; +using ControllerReferenceMsg = + steering_controllers_library::SteeringControllersLibrary::ControllerTwistReferenceMsg; + +// name constants for state interfaces +using tricycle_steering_controller::STATE_STEER_AXIS; +using tricycle_steering_controller::STATE_TRACTION_LEFT_WHEEL; +using tricycle_steering_controller::STATE_TRACTION_RIGHT_WHEEL; + +// name constants for command interfaces +using tricycle_steering_controller::CMD_STEER_WHEEL; +using tricycle_steering_controller::CMD_TRACTION_LEFT_WHEEL; +using tricycle_steering_controller::CMD_TRACTION_RIGHT_WHEEL; + +namespace +{ +constexpr auto NODE_SUCCESS = controller_interface::CallbackReturn::SUCCESS; +constexpr auto NODE_ERROR = controller_interface::CallbackReturn::ERROR; +const double COMMON_THRESHOLD = 1e-6; +} // namespace +// namespace + +// subclassing and friending so we can access member variables +class TestableTricycleSteeringController +: public tricycle_steering_controller::TricycleSteeringController +{ + FRIEND_TEST(TricycleSteeringControllerTest, all_parameters_set_configure_success); + FRIEND_TEST(TricycleSteeringControllerTest, check_exported_intefaces); + FRIEND_TEST(TricycleSteeringControllerTest, activate_success); + FRIEND_TEST(TricycleSteeringControllerTest, update_success); + FRIEND_TEST(TricycleSteeringControllerTest, deactivate_success); + FRIEND_TEST(TricycleSteeringControllerTest, reactivate_success); + FRIEND_TEST(TricycleSteeringControllerTest, test_update_logic); + FRIEND_TEST(TricycleSteeringControllerTest, test_update_logic_chained); + FRIEND_TEST(TricycleSteeringControllerTest, publish_status_success); + FRIEND_TEST(TricycleSteeringControllerTest, receive_message_and_publish_updated_status); + +public: + controller_interface::CallbackReturn on_configure( + const rclcpp_lifecycle::State & previous_state) override + { + auto ret = + tricycle_steering_controller::TricycleSteeringController::on_configure(previous_state); + // Only if on_configure is successful create subscription + if (ret == CallbackReturn::SUCCESS) + { + ref_subscriber_wait_set_.add_subscription(ref_subscriber_twist_); + } + return ret; + } + + controller_interface::CallbackReturn on_activate( + const rclcpp_lifecycle::State & previous_state) override + { + auto ref_itfs = on_export_reference_interfaces(); + return tricycle_steering_controller::TricycleSteeringController::on_activate(previous_state); + } + + /** + * @brief wait_for_command blocks until a new ControllerReferenceMsg is received. + * Requires that the executor is not spinned elsewhere between the + * message publication and the call to this function. + * + * @return true if new ControllerReferenceMsg msg was received, false if timeout. + */ + bool wait_for_command( + rclcpp::Executor & executor, rclcpp::WaitSet & subscriber_wait_set, + const std::chrono::milliseconds & timeout = std::chrono::milliseconds{500}) + { + bool success = subscriber_wait_set.wait(timeout).kind() == rclcpp::WaitResultKind::Ready; + if (success) + { + executor.spin_some(); + } + return success; + } + + bool wait_for_commands( + rclcpp::Executor & executor, + const std::chrono::milliseconds & timeout = std::chrono::milliseconds{500}) + { + return wait_for_command(executor, ref_subscriber_wait_set_, timeout); + } + +private: + rclcpp::WaitSet ref_subscriber_wait_set_; +}; + +// We are using template class here for easier reuse of Fixture in specializations of controllers +template +class TricycleSteeringControllerFixture : public ::testing::Test +{ +public: + static void SetUpTestCase() {} + + void SetUp() + { + // initialize controller + controller_ = std::make_unique(); + + command_publisher_node_ = std::make_shared("command_publisher"); + command_publisher_ = command_publisher_node_->create_publisher( + "/test_tricycle_steering_controller/reference", rclcpp::SystemDefaultsQoS()); + } + + static void TearDownTestCase() {} + + void TearDown() { controller_.reset(nullptr); } + +protected: + void SetUpController(const std::string controller_name = "test_tricycle_steering_controller") + { + ASSERT_EQ(controller_->init(controller_name), controller_interface::return_type::OK); + + if (position_feedback_ == true) + { + traction_interface_name_ = "position"; + } + else + { + traction_interface_name_ = "velocity"; + } + + std::vector command_ifs; + command_itfs_.reserve(joint_command_values_.size()); + command_ifs.reserve(joint_command_values_.size()); + + command_itfs_.emplace_back(hardware_interface::CommandInterface( + rear_wheels_names_[0], traction_interface_name_, + &joint_command_values_[CMD_TRACTION_RIGHT_WHEEL])); + command_ifs.emplace_back(command_itfs_.back()); + + command_itfs_.emplace_back(hardware_interface::CommandInterface( + rear_wheels_names_[1], steering_interface_name_, + &joint_command_values_[CMD_TRACTION_LEFT_WHEEL])); + command_ifs.emplace_back(command_itfs_.back()); + + command_itfs_.emplace_back(hardware_interface::CommandInterface( + front_wheels_names_[0], steering_interface_name_, &joint_command_values_[CMD_STEER_WHEEL])); + command_ifs.emplace_back(command_itfs_.back()); + + std::vector state_ifs; + state_itfs_.reserve(joint_state_values_.size()); + state_ifs.reserve(joint_state_values_.size()); + + state_itfs_.emplace_back(hardware_interface::StateInterface( + rear_wheels_names_[0], traction_interface_name_, + &joint_state_values_[STATE_TRACTION_RIGHT_WHEEL])); + state_ifs.emplace_back(state_itfs_.back()); + + state_itfs_.emplace_back(hardware_interface::StateInterface( + rear_wheels_names_[1], traction_interface_name_, + &joint_state_values_[STATE_TRACTION_LEFT_WHEEL])); + state_ifs.emplace_back(state_itfs_.back()); + + state_itfs_.emplace_back(hardware_interface::StateInterface( + front_wheels_names_[0], steering_interface_name_, &joint_state_values_[STATE_STEER_AXIS])); + state_ifs.emplace_back(state_itfs_.back()); + + controller_->assign_interfaces(std::move(command_ifs), std::move(state_ifs)); + } + + void subscribe_and_get_messages(ControllerStateMsg & msg) + { + // create a new subscriber + rclcpp::Node test_subscription_node("test_subscription_node"); + auto subs_callback = [&](const ControllerStateMsg::SharedPtr) {}; + auto subscription = test_subscription_node.create_subscription( + "/test_tricycle_steering_controller/controller_state", 10, subs_callback); + + // call update to publish the test value + ASSERT_EQ( + controller_->update(rclcpp::Time(0, 0, RCL_ROS_TIME), rclcpp::Duration::from_seconds(0.01)), + controller_interface::return_type::OK); + // since update doesn't guarantee a published message, republish until received + int max_sub_check_loop_count = 5; // max number of tries for pub/sub loop + rclcpp::WaitSet wait_set; // block used to wait on message + wait_set.add_subscription(subscription); + while (max_sub_check_loop_count--) + { + controller_->update(rclcpp::Time(0, 0, RCL_ROS_TIME), rclcpp::Duration::from_seconds(0.01)); + // check if message has been received + if (wait_set.wait(std::chrono::milliseconds(2)).kind() == rclcpp::WaitResultKind::Ready) + { + break; + } + } + ASSERT_GE(max_sub_check_loop_count, 0) << "Test was unable to publish a message through " + "controller/broadcaster update loop"; + + // take message from subscription + rclcpp::MessageInfo msg_info; + ASSERT_TRUE(subscription->take(msg, msg_info)); + } + + void publish_commands(const double linear = 0.1, const double angular = 0.2) + { + auto wait_for_topic = [&](const auto topic_name) + { + size_t wait_count = 0; + while (command_publisher_node_->count_subscribers(topic_name) == 0) + { + if (wait_count >= 5) + { + auto error_msg = + std::string("publishing to ") + topic_name + " but no node subscribes to it"; + throw std::runtime_error(error_msg); + } + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + ++wait_count; + } + }; + + wait_for_topic(command_publisher_->get_topic_name()); + + ControllerReferenceMsg msg; + msg.twist.linear.x = linear; + msg.twist.angular.z = angular; + + command_publisher_->publish(msg); + } + +protected: + // Controller-related parameters + double reference_timeout_ = 2.0; + bool front_steering_ = true; + bool open_loop_ = false; + unsigned int velocity_rolling_window_size_ = 10; + bool position_feedback_ = false; + bool use_stamped_vel_ = true; + std::vector rear_wheels_names_ = {"rear_right_wheel_joint", "rear_left_wheel_joint"}; + std::vector front_wheels_names_ = {"steering_axis_joint"}; + std::vector joint_names_ = { + rear_wheels_names_[0], rear_wheels_names_[1], front_wheels_names_[0]}; + + std::vector rear_wheels_preceeding_names_ = { + "pid_controller/rear_right_wheel_joint", "pid_controller/rear_left_wheel_joint"}; + std::vector front_wheels_preceeding_names_ = {"pid_controller/steering_axis_joint"}; + std::vector preceeding_joint_names_ = { + rear_wheels_preceeding_names_[0], rear_wheels_preceeding_names_[1], + front_wheels_preceeding_names_[0]}; + + double wheelbase_ = 3.24644; + double wheel_track_ = 1.212121; + + double front_wheels_radius_ = 0.45; + double rear_wheels_radius_ = 0.45; + + std::array joint_state_values_ = {0.5, 0.5, 0.0}; + std::array joint_command_values_ = {1.1, 3.3, 2.2}; + std::array joint_reference_interfaces_ = {"linear/velocity", "angular/position"}; + std::string steering_interface_name_ = "position"; + // defined in setup + std::string traction_interface_name_ = ""; + std::string preceeding_prefix_ = "pid_controller"; + + std::vector state_itfs_; + std::vector command_itfs_; + + // Test related parameters + std::unique_ptr controller_; + rclcpp::Node::SharedPtr command_publisher_node_; + rclcpp::Publisher::SharedPtr command_publisher_; +}; + +#endif // TEST_TRICYCLE_STEERING_CONTROLLER_HPP_ diff --git a/tricycle_steering_controller/test/test_tricycle_steering_controller_preceeding.cpp b/tricycle_steering_controller/test/test_tricycle_steering_controller_preceeding.cpp new file mode 100644 index 0000000000..dd72332875 --- /dev/null +++ b/tricycle_steering_controller/test/test_tricycle_steering_controller_preceeding.cpp @@ -0,0 +1,100 @@ +// Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "test_tricycle_steering_controller.hpp" + +#include +#include +#include +#include +#include + +class TricycleSteeringControllerTest +: public TricycleSteeringControllerFixture +{ +}; + +TEST_F(TricycleSteeringControllerTest, all_parameters_set_configure_success) +{ + SetUpController(); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + + ASSERT_THAT( + controller_->params_.rear_wheels_names, + testing::ElementsAreArray(rear_wheels_preceeding_names_)); + ASSERT_THAT( + controller_->params_.front_wheels_names, + testing::ElementsAreArray(front_wheels_preceeding_names_)); + ASSERT_EQ(controller_->params_.front_steering, front_steering_); + ASSERT_EQ(controller_->params_.open_loop, open_loop_); + ASSERT_EQ(controller_->params_.velocity_rolling_window_size, velocity_rolling_window_size_); + ASSERT_EQ(controller_->params_.position_feedback, position_feedback_); + ASSERT_EQ(controller_->tricycle_params_.wheelbase, wheelbase_); + ASSERT_EQ(controller_->tricycle_params_.front_wheels_radius, front_wheels_radius_); + ASSERT_EQ(controller_->tricycle_params_.rear_wheels_radius, rear_wheels_radius_); + ASSERT_EQ(controller_->tricycle_params_.wheel_track, wheel_track_); +} + +TEST_F(TricycleSteeringControllerTest, check_exported_intefaces) +{ + SetUpController(); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + + auto command_intefaces = controller_->command_interface_configuration(); + ASSERT_EQ(command_intefaces.names.size(), joint_command_values_.size()); + EXPECT_EQ( + command_intefaces.names[CMD_TRACTION_RIGHT_WHEEL], + preceeding_prefix_ + "/" + rear_wheels_names_[0] + "/" + traction_interface_name_); + EXPECT_EQ( + command_intefaces.names[CMD_TRACTION_LEFT_WHEEL], + preceeding_prefix_ + "/" + rear_wheels_names_[1] + "/" + traction_interface_name_); + EXPECT_EQ( + command_intefaces.names[CMD_STEER_WHEEL], + preceeding_prefix_ + "/" + front_wheels_names_[0] + "/" + steering_interface_name_); + + auto state_intefaces = controller_->state_interface_configuration(); + ASSERT_EQ(state_intefaces.names.size(), joint_state_values_.size()); + EXPECT_EQ( + state_intefaces.names[STATE_TRACTION_RIGHT_WHEEL], + controller_->rear_wheels_state_names_[0] + "/" + traction_interface_name_); + EXPECT_EQ( + state_intefaces.names[STATE_TRACTION_LEFT_WHEEL], + controller_->rear_wheels_state_names_[1] + "/" + traction_interface_name_); + EXPECT_EQ( + state_intefaces.names[STATE_STEER_AXIS], + controller_->front_wheels_state_names_[0] + "/" + steering_interface_name_); + + // check ref itfs + auto reference_interfaces = controller_->export_reference_interfaces(); + ASSERT_EQ(reference_interfaces.size(), joint_reference_interfaces_.size()); + for (size_t i = 0; i < joint_reference_interfaces_.size(); ++i) + { + const std::string ref_itf_name = + std::string(controller_->get_node()->get_name()) + "/" + joint_reference_interfaces_[i]; + EXPECT_EQ(reference_interfaces[i].get_name(), ref_itf_name); + EXPECT_EQ(reference_interfaces[i].get_prefix_name(), controller_->get_node()->get_name()); + EXPECT_EQ(reference_interfaces[i].get_interface_name(), joint_reference_interfaces_[i]); + } +} + +int main(int argc, char ** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + rclcpp::init(argc, argv); + int result = RUN_ALL_TESTS(); + rclcpp::shutdown(); + return result; +} diff --git a/tricycle_steering_controller/test/tricycle_steering_controller_params.yaml b/tricycle_steering_controller/test/tricycle_steering_controller_params.yaml new file mode 100644 index 0000000000..6bfb87a892 --- /dev/null +++ b/tricycle_steering_controller/test/tricycle_steering_controller_params.yaml @@ -0,0 +1,16 @@ +test_tricycle_steering_controller: + ros__parameters: + + reference_timeout: 2.0 + front_steering: true + open_loop: false + velocity_rolling_window_size: 10 + position_feedback: false + use_stamped_vel: true + rear_wheels_names: [rear_right_wheel_joint, rear_left_wheel_joint] + front_wheels_names: [steering_axis_joint] + + wheelbase: 3.24644 + wheel_track: 1.212121 + front_wheels_radius: 0.45 + rear_wheels_radius: 0.45 diff --git a/tricycle_steering_controller/test/tricycle_steering_controller_preceeding_params.yaml b/tricycle_steering_controller/test/tricycle_steering_controller_preceeding_params.yaml new file mode 100644 index 0000000000..ea8b88002e --- /dev/null +++ b/tricycle_steering_controller/test/tricycle_steering_controller_preceeding_params.yaml @@ -0,0 +1,16 @@ +test_tricycle_steering_controller: + ros__parameters: + reference_timeout: 2.0 + front_steering: true + open_loop: false + velocity_rolling_window_size: 10 + position_feedback: false + use_stamped_vel: true + rear_wheels_names: [pid_controller/rear_right_wheel_joint, pid_controller/rear_left_wheel_joint] + front_wheels_names: [pid_controller/steering_axis_joint] + rear_wheels_state_names: [rear_right_wheel_joint, rear_left_wheel_joint] + front_wheels_state_names: [steering_axis_joint] + wheelbase: 3.24644 + wheel_track: 1.212121 + front_wheels_radius: 0.45 + rear_wheels_radius: 0.45 diff --git a/tricycle_steering_controller/tricycle_steering_controller.xml b/tricycle_steering_controller/tricycle_steering_controller.xml new file mode 100644 index 0000000000..f0d5d85467 --- /dev/null +++ b/tricycle_steering_controller/tricycle_steering_controller.xml @@ -0,0 +1,8 @@ + + + + Steering controller for Tricycle kinematics with two traction and one steering joint. + + + From aece9740c50266e34f5edf54c76a9f925f6a48f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Sat, 27 May 2023 18:55:15 +0200 Subject: [PATCH 030/238] Use branch name substitution for all links (#618) --- admittance_controller/doc/userdoc.rst | 12 ++++++------ diff_drive_controller/doc/userdoc.rst | 6 +++--- doc/controllers_index.rst | 4 ++-- doc/writing_new_controller.rst | 2 +- effort_controllers/doc/userdoc.rst | 2 +- force_torque_sensor_broadcaster/doc/userdoc.rst | 2 +- forward_command_controller/doc/userdoc.rst | 2 +- imu_sensor_broadcaster/doc/userdoc.rst | 2 +- joint_state_broadcaster/doc/userdoc.rst | 2 +- joint_trajectory_controller/doc/userdoc.rst | 4 ++-- position_controllers/doc/userdoc.rst | 2 +- tricycle_controller/doc/userdoc.rst | 2 +- velocity_controllers/doc/userdoc.rst | 2 +- 13 files changed, 22 insertions(+), 22 deletions(-) diff --git a/admittance_controller/doc/userdoc.rst b/admittance_controller/doc/userdoc.rst index c6a3b91b78..152ed890dc 100644 --- a/admittance_controller/doc/userdoc.rst +++ b/admittance_controller/doc/userdoc.rst @@ -1,4 +1,4 @@ -:github_url: https://github.com/ros-controls/ros2_controllers/blob/|github_branch|/admittance_controller/doc/userdoc.rst +:github_url: https://github.com/ros-controls/ros2_controllers/blob/{REPOS_FILE_BRANCH}/admittance_controller/doc/userdoc.rst .. _admittance_controller_userdoc: @@ -18,8 +18,8 @@ Parameters ^^^^^^^^^^^ The admittance controller's uses the `generate_parameter_library `_ to handle its parameters. -The parameter `definition file located in the src folder `_ contains descriptions for all the parameters used by the controller. -An example parameter file can be found in the `test folder of the controller `_ +The parameter `definition file located in the src folder `_ contains descriptions for all the parameters used by the controller. +An example parameter file can be found in the `test folder of the controller `_ Topics @@ -44,14 +44,14 @@ The controller has ``position`` and ``velocity`` reference interfaces exported i States ^^^^^^^ The state interfaces are defined with ``joints`` and ``state_interfaces`` parameters as follows: ``/``. -Supported state interfaces are ``position``, ``velocity``, and ``acceleration`` as defined in the `hardware_interface/hardware_interface_type_values.hpp `_. +Supported state interfaces are ``position``, ``velocity``, and ``acceleration`` as defined in the `hardware_interface/hardware_interface_type_values.hpp `_. If some interface is not provided, the last commanded interface will be used for calculation. -For handling TCP wrenches `*Force Torque Sensor* semantic component (from package *controller_interface*) `_ is used. +For handling TCP wrenches `*Force Torque Sensor* semantic component (from package *controller_interface*) `_ is used. The interfaces have prefix ``ft_sensor.name``, building the interfaces: ``/[force.x|force.y|force.z|torque.x|torque.y|torque.z]``. Commands ^^^^^^^^^ The command interfaces are defined with ``joints`` and ``command_interfaces`` parameters as follows: ``/``. -Supported state interfaces are ``position``, ``velocity``, and ``acceleration`` as defined in the `hardware_interface/hardware_interface_type_values.hpp `_. +Supported state interfaces are ``position``, ``velocity``, and ``acceleration`` as defined in the `hardware_interface/hardware_interface_type_values.hpp `_. diff --git a/diff_drive_controller/doc/userdoc.rst b/diff_drive_controller/doc/userdoc.rst index 25d2383364..6bd682af26 100644 --- a/diff_drive_controller/doc/userdoc.rst +++ b/diff_drive_controller/doc/userdoc.rst @@ -1,4 +1,4 @@ -:github_url: https://github.com/ros-controls/ros2_controllers/blob/|github_branch|/diff_drive_controller/doc/userdoc.rst +:github_url: https://github.com/ros-controls/ros2_controllers/blob/{REPOS_FILE_BRANCH}/diff_drive_controller/doc/userdoc.rst .. _diff_drive_controller_userdoc: @@ -72,9 +72,9 @@ Services Parameters ------------ -Check `parameter definition file for details `_. +Check `parameter definition file for details `_. -Note that the documentation on parameters for joint limits can be found in `their header file `_. +Note that the documentation on parameters for joint limits can be found in `their header file `_. Those parameters are: linear.x [JointLimits structure] diff --git a/doc/controllers_index.rst b/doc/controllers_index.rst index cb5528bdb0..f4ce929e78 100644 --- a/doc/controllers_index.rst +++ b/doc/controllers_index.rst @@ -1,4 +1,4 @@ -:github_url: https://github.com/ros-controls/ros2_controllers/blob/|github_branch|/doc/controllers_index.rst +:github_url: https://github.com/ros-controls/ros2_controllers/blob/{REPOS_FILE_BRANCH}/doc/controllers_index.rst .. _controllers: @@ -22,7 +22,7 @@ The controllers' namespaces are commanding the following command interface types - ``effort_controllers``: ``hardware_interface::HW_IF_EFFORT`` - ... -.. _common hardware interface definitions: https://github.com/ros-controls/ros2_control/blob/master/hardware_interface/include/hardware_interface/types/hardware_interface_type_values.hpp +.. _common hardware interface definitions: https://github.com/ros-controls/ros2_control/blob/{REPOS_FILE_BRANCH}/hardware_interface/include/hardware_interface/types/hardware_interface_type_values.hpp diff --git a/doc/writing_new_controller.rst b/doc/writing_new_controller.rst index 49bd8a11ee..a2e26104a7 100644 --- a/doc/writing_new_controller.rst +++ b/doc/writing_new_controller.rst @@ -1,4 +1,4 @@ -:github_url: https://github.com/ros-controls/ros2_controllers/blob/|github_branch|/doc/writing_new_controller.rst +:github_url: https://github.com/ros-controls/ros2_controllers/blob/{REPOS_FILE_BRANCH}/doc/writing_new_controller.rst .. _writing_new_controllers: diff --git a/effort_controllers/doc/userdoc.rst b/effort_controllers/doc/userdoc.rst index 52539ef795..74caf63391 100644 --- a/effort_controllers/doc/userdoc.rst +++ b/effort_controllers/doc/userdoc.rst @@ -1,4 +1,4 @@ -:github_url: https://github.com/ros-controls/ros2_controllers/blob/|github_branch|/effort_controllers/doc/userdoc.rst +:github_url: https://github.com/ros-controls/ros2_controllers/blob/{REPOS_FILE_BRANCH}/effort_controllers/doc/userdoc.rst .. _effort_controllers_userdoc: diff --git a/force_torque_sensor_broadcaster/doc/userdoc.rst b/force_torque_sensor_broadcaster/doc/userdoc.rst index 1d7f1ac1b8..053723e8f0 100644 --- a/force_torque_sensor_broadcaster/doc/userdoc.rst +++ b/force_torque_sensor_broadcaster/doc/userdoc.rst @@ -1,4 +1,4 @@ -:github_url: https://github.com/ros-controls/ros2_controllers/blob/|github_branch|/force_torque_sensor_broadcaster/doc/userdoc.rst +:github_url: https://github.com/ros-controls/ros2_controllers/blob/{REPOS_FILE_BRANCH}/force_torque_sensor_broadcaster/doc/userdoc.rst .. _force_torque_sensor_broadcaster_userdoc: diff --git a/forward_command_controller/doc/userdoc.rst b/forward_command_controller/doc/userdoc.rst index 522d671438..2ecba6003a 100644 --- a/forward_command_controller/doc/userdoc.rst +++ b/forward_command_controller/doc/userdoc.rst @@ -1,4 +1,4 @@ -:github_url: https://github.com/ros-controls/ros2_controllers/blob/|github_branch|/forward_command_controller/doc/userdoc.rst +:github_url: https://github.com/ros-controls/ros2_controllers/blob/{REPOS_FILE_BRANCH}/forward_command_controller/doc/userdoc.rst .. _forward_command_controller_userdoc: diff --git a/imu_sensor_broadcaster/doc/userdoc.rst b/imu_sensor_broadcaster/doc/userdoc.rst index 6f4730b17f..24438c9959 100644 --- a/imu_sensor_broadcaster/doc/userdoc.rst +++ b/imu_sensor_broadcaster/doc/userdoc.rst @@ -1,4 +1,4 @@ -:github_url: https://github.com/ros-controls/ros2_controllers/blob/|github_branch|/imu_sensor_broadcaster/doc/userdoc.rst +:github_url: https://github.com/ros-controls/ros2_controllers/blob/{REPOS_FILE_BRANCH}/imu_sensor_broadcaster/doc/userdoc.rst .. _imu_sensor_broadcaster_userdoc: diff --git a/joint_state_broadcaster/doc/userdoc.rst b/joint_state_broadcaster/doc/userdoc.rst index f809a5b49a..c9164ec723 100644 --- a/joint_state_broadcaster/doc/userdoc.rst +++ b/joint_state_broadcaster/doc/userdoc.rst @@ -1,4 +1,4 @@ -:github_url: https://github.com/ros-controls/ros2_controllers/blob/|github_branch|/joint_state_broadcaster/doc/userdoc.rst +:github_url: https://github.com/ros-controls/ros2_controllers/blob/{REPOS_FILE_BRANCH}/joint_state_broadcaster/doc/userdoc.rst .. _joint_state_broadcaster_userdoc: diff --git a/joint_trajectory_controller/doc/userdoc.rst b/joint_trajectory_controller/doc/userdoc.rst index 63cf0e5b8f..7529a60918 100644 --- a/joint_trajectory_controller/doc/userdoc.rst +++ b/joint_trajectory_controller/doc/userdoc.rst @@ -1,4 +1,4 @@ -:github_url: https://github.com/ros-controls/ros2_controllers/blob/|github_branch|/joint_trajectory_controller/doc/userdoc.rst +:github_url: https://github.com/ros-controls/ros2_controllers/blob/{REPOS_FILE_BRANCH}/joint_trajectory_controller/doc/userdoc.rst .. _joint_trajectory_controller_userdoc: @@ -259,7 +259,7 @@ States ,,,,,,,,,,,,,,,,,, The state interfaces are defined with ``joints`` and ``state_interfaces`` parameters as follows: ``/``. -Supported state interfaces are ``position``, ``velocity``, ``acceleration`` and ``effort`` as defined in the `hardware_interface/hardware_interface_type_values.hpp `_. +Supported state interfaces are ``position``, ``velocity``, ``acceleration`` and ``effort`` as defined in the `hardware_interface/hardware_interface_type_values.hpp `_. Legal combinations of state interfaces are: diff --git a/position_controllers/doc/userdoc.rst b/position_controllers/doc/userdoc.rst index 69557209ae..f321e8a698 100644 --- a/position_controllers/doc/userdoc.rst +++ b/position_controllers/doc/userdoc.rst @@ -1,4 +1,4 @@ -:github_url: https://github.com/ros-controls/ros2_controllers/blob/|github_branch|/position_controllers/doc/userdoc.rst +:github_url: https://github.com/ros-controls/ros2_controllers/blob/{REPOS_FILE_BRANCH}/position_controllers/doc/userdoc.rst .. _position_controllers_userdoc: diff --git a/tricycle_controller/doc/userdoc.rst b/tricycle_controller/doc/userdoc.rst index 9dd46cc79a..d153aeacba 100644 --- a/tricycle_controller/doc/userdoc.rst +++ b/tricycle_controller/doc/userdoc.rst @@ -1,4 +1,4 @@ -:github_url: https://github.com/ros-controls/ros2_controllers/blob/|github_branch|/tricycle_controller/doc/userdoc.rst +:github_url: https://github.com/ros-controls/ros2_controllers/blob/{REPOS_FILE_BRANCH}/tricycle_controller/doc/userdoc.rst .. _tricycle_controller_userdoc: diff --git a/velocity_controllers/doc/userdoc.rst b/velocity_controllers/doc/userdoc.rst index 56fdde5220..fa7e36062e 100644 --- a/velocity_controllers/doc/userdoc.rst +++ b/velocity_controllers/doc/userdoc.rst @@ -1,4 +1,4 @@ -:github_url: https://github.com/ros-controls/ros2_controllers/blob/|github_branch|/velocity_controllers/doc/userdoc.rst +:github_url: https://github.com/ros-controls/ros2_controllers/blob/{REPOS_FILE_BRANCH}/velocity_controllers/doc/userdoc.rst .. _velocity_controllers_userdoc: From a3f2a16085fa58a56c52ee9520e4b029996ef303 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Sun, 28 May 2023 16:05:03 +0200 Subject: [PATCH 031/238] Fix sphinx for steering odometry library/controllers (#626) --- ackermann_steering_controller/doc/userdoc.rst | 4 +++- bicycle_steering_controller/doc/userdoc.rst | 4 +++- doc/controllers_index.rst | 3 +-- steering_controllers_library/doc/userdoc.rst | 2 ++ .../doc/{userdocs.rst => userdoc.rst} | 4 +++- 5 files changed, 12 insertions(+), 5 deletions(-) rename tricycle_steering_controller/doc/{userdocs.rst => userdoc.rst} (83%) diff --git a/ackermann_steering_controller/doc/userdoc.rst b/ackermann_steering_controller/doc/userdoc.rst index 59cdb78108..c743b5d709 100644 --- a/ackermann_steering_controller/doc/userdoc.rst +++ b/ackermann_steering_controller/doc/userdoc.rst @@ -1,3 +1,5 @@ +:github_url: https://github.com/ros-controls/ros2_controllers/blob/{REPOS_FILE_BRANCH}/ackermann_steering_controller/doc/userdoc.rst + .. _ackermann_steering_controller_userdoc: ackermann_steering_controller @@ -7,7 +9,7 @@ This controller implements the kinematics with two axes and four wheels, where t The controller expects to have two commanding joints for traction, one for each fixed wheel and two commanding joints for steering, one for each wheel. -For more details on controller's execution and interfaces check the :ref:`Steering Controller Library `. +For more details on controller's execution and interfaces check the :ref:`Steering Controller Library `. Parameters diff --git a/bicycle_steering_controller/doc/userdoc.rst b/bicycle_steering_controller/doc/userdoc.rst index 6815dc6953..dd6db9ceaa 100644 --- a/bicycle_steering_controller/doc/userdoc.rst +++ b/bicycle_steering_controller/doc/userdoc.rst @@ -1,3 +1,5 @@ +:github_url: https://github.com/ros-controls/ros2_controllers/blob/{REPOS_FILE_BRANCH}/bicycle_steering_controller/doc/userdoc.rst + .. _bicycle_steering_controller_userdoc: bicycle_steering_controller @@ -8,7 +10,7 @@ This controller implements the kinematics with two axes and two wheels, where th The controller expects to have one commanding joint for traction, and one commanding joint for steering. If your Ackermann steering vehicle uses differentials on axes, then you should probably use this controller since you can command only one traction velocity and steering angle for virtual wheels in the middle of the axes. -For more details on controller's execution and interfaces check the :ref:`Steering Controller Library `. +For more details on controller's execution and interfaces check the :ref:`Steering Controller Library `. Parameters diff --git a/doc/controllers_index.rst b/doc/controllers_index.rst index f4ce929e78..80e5e4fda2 100644 --- a/doc/controllers_index.rst +++ b/doc/controllers_index.rst @@ -50,11 +50,10 @@ Available Controllers Forward Command Controller <../forward_command_controller/doc/userdoc.rst> Joint Trajectory Controller <../joint_trajectory_controller/doc/userdoc.rst> Position Controllers <../position_controllers/doc/userdoc.rst> + Steering Controllers Library <../steering_controllers_library/doc/userdoc.rst> Tricycle Controller <../tricycle_controller/doc/userdoc.rst> Tricycle Steering Controller <../tricycle_steering_controller/doc/userdoc.rst> Velocity Controllers <../velocity_controllers/doc/userdoc.rst> - Effort Controllers <../effort_controllers/doc/userdoc.rst> - Steering Controllers Library <../steering_controllers_library/doc/userdoc.rst> Available Broadcasters diff --git a/steering_controllers_library/doc/userdoc.rst b/steering_controllers_library/doc/userdoc.rst index 27133e2e77..47d9516fd1 100644 --- a/steering_controllers_library/doc/userdoc.rst +++ b/steering_controllers_library/doc/userdoc.rst @@ -1,3 +1,5 @@ +:github_url: https://github.com/ros-controls/ros2_controllers/blob/{REPOS_FILE_BRANCH}/steering_controllers_library/doc/userdoc.rst + .. _steering_controllers_library_userdoc: steering_controllers_library diff --git a/tricycle_steering_controller/doc/userdocs.rst b/tricycle_steering_controller/doc/userdoc.rst similarity index 83% rename from tricycle_steering_controller/doc/userdocs.rst rename to tricycle_steering_controller/doc/userdoc.rst index 9a6adfca37..bf20dc58c2 100644 --- a/tricycle_steering_controller/doc/userdocs.rst +++ b/tricycle_steering_controller/doc/userdoc.rst @@ -1,3 +1,5 @@ +:github_url: https://github.com/ros-controls/ros2_controllers/blob/{REPOS_FILE_BRANCH}/tricycle_steering_controller/doc/userdoc.rst + .. _tricycle_steering_controller_userdoc: tricycle_steering_controller @@ -7,7 +9,7 @@ This controller implements the kinematics with two axes and three wheels, where The controller expects to have two commanding joints for traction, one for each fixed wheel and one commanding joint for steering. -For more details on controller's execution and interfaces check the :ref:`Steering Controller Library `. +For more details on controller's execution and interfaces check the :ref:`Steering Controller Library `. Parameters From 0cb6f28cb5444d1a2bdef4d65f01bc2bed8ed121 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Sun, 28 May 2023 16:47:50 +0200 Subject: [PATCH 032/238] Use generate_parameter_library for all params (#601) --- diff_drive_controller/src/diff_drive_controller.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/diff_drive_controller/src/diff_drive_controller.cpp b/diff_drive_controller/src/diff_drive_controller.cpp index abefd4307f..fc8114630e 100644 --- a/diff_drive_controller/src/diff_drive_controller.cpp +++ b/diff_drive_controller/src/diff_drive_controller.cpp @@ -302,10 +302,9 @@ controller_interface::CallbackReturn DiffDriveController::on_configure( odometry_.setWheelParams(wheel_separation, left_wheel_radius, right_wheel_radius); odometry_.setVelocityRollingWindowSize(params_.velocity_rolling_window_size); - cmd_vel_timeout_ = std::chrono::milliseconds{ - static_cast(get_node()->get_parameter("cmd_vel_timeout").as_double() * 1000.0)}; - publish_limited_velocity_ = get_node()->get_parameter("publish_limited_velocity").as_bool(); - use_stamped_vel_ = get_node()->get_parameter("use_stamped_vel").as_bool(); + cmd_vel_timeout_ = std::chrono::milliseconds{static_cast(params_.cmd_vel_timeout * 1000.0)}; + publish_limited_velocity_ = params_.publish_limited_velocity; + use_stamped_vel_ = params_.use_stamped_vel; limiter_linear_ = SpeedLimiter( params_.linear.x.has_velocity_limits, params_.linear.x.has_acceleration_limits, @@ -414,7 +413,7 @@ controller_interface::CallbackReturn DiffDriveController::on_configure( odometry_message.child_frame_id = controller_namespace + base_frame_id; // limit the publication on the topics /odom and /tf - publish_rate_ = get_node()->get_parameter("publish_rate").as_double(); + publish_rate_ = params_.publish_rate; publish_period_ = rclcpp::Duration::from_seconds(1.0 / publish_rate_); // initialize odom values zeros From 7d785034f40e6375d8305c587710976daef98e21 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Sun, 28 May 2023 15:56:59 +0100 Subject: [PATCH 033/238] Bring new packages up to version --- ackermann_steering_controller/package.xml | 2 +- bicycle_steering_controller/package.xml | 2 +- steering_controllers_library/package.xml | 2 +- tricycle_steering_controller/package.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ackermann_steering_controller/package.xml b/ackermann_steering_controller/package.xml index 24c3c8406b..83fc710c22 100644 --- a/ackermann_steering_controller/package.xml +++ b/ackermann_steering_controller/package.xml @@ -2,7 +2,7 @@ ackermann_steering_controller - 0.0.0 + 3.8.0 Steering controller for Ackermann kinematics. Rear fixed wheels are powering the vehicle and front wheels are steering it. Apache License 2.0 Bence Magyar diff --git a/bicycle_steering_controller/package.xml b/bicycle_steering_controller/package.xml index 80932f7fda..95dd240d58 100644 --- a/bicycle_steering_controller/package.xml +++ b/bicycle_steering_controller/package.xml @@ -2,7 +2,7 @@ bicycle_steering_controller - 0.0.0 + 3.8.0 Steering controller with bicycle kinematics. Rear fixed wheel is powering the vehicle and front wheel is steering. Apache License 2.0 Bence Magyar diff --git a/steering_controllers_library/package.xml b/steering_controllers_library/package.xml index 0d9aa9da39..0395c935da 100644 --- a/steering_controllers_library/package.xml +++ b/steering_controllers_library/package.xml @@ -2,7 +2,7 @@ steering_controllers_library - 0.0.0 + 3.8.0 Package for steering robot configurations including odometry and interfaces. Apache License 2.0 Bence Magyar diff --git a/tricycle_steering_controller/package.xml b/tricycle_steering_controller/package.xml index e911041cd1..652546d098 100644 --- a/tricycle_steering_controller/package.xml +++ b/tricycle_steering_controller/package.xml @@ -2,7 +2,7 @@ tricycle_steering_controller - 0.0.0 + 3.8.0 Steering controller with tricycle kinematics. Rear fixed wheels are powering the vehicle and front wheel is steering. Apache License 2.0 Bence Magyar From 63057baa85d89566a1bd3e711f5ebdf2149e1da3 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Sun, 28 May 2023 15:59:38 +0100 Subject: [PATCH 034/238] Update changelogs --- ackermann_steering_controller/CHANGELOG.rst | 129 ++++++++++++++++++ admittance_controller/CHANGELOG.rst | 6 + bicycle_steering_controller/CHANGELOG.rst | 129 ++++++++++++++++++ diff_drive_controller/CHANGELOG.rst | 8 ++ effort_controllers/CHANGELOG.rst | 6 + force_torque_sensor_broadcaster/CHANGELOG.rst | 6 + forward_command_controller/CHANGELOG.rst | 6 + gripper_controllers/CHANGELOG.rst | 5 + imu_sensor_broadcaster/CHANGELOG.rst | 6 + joint_state_broadcaster/CHANGELOG.rst | 7 + joint_trajectory_controller/CHANGELOG.rst | 7 + position_controllers/CHANGELOG.rst | 6 + ros2_controllers/CHANGELOG.rst | 5 + ros2_controllers_test_nodes/CHANGELOG.rst | 3 + rqt_joint_trajectory_controller/CHANGELOG.rst | 3 + steering_controllers_library/CHANGELOG.rst | 129 ++++++++++++++++++ tricycle_controller/CHANGELOG.rst | 6 + tricycle_steering_controller/CHANGELOG.rst | 129 ++++++++++++++++++ velocity_controllers/CHANGELOG.rst | 6 + 19 files changed, 602 insertions(+) create mode 100644 ackermann_steering_controller/CHANGELOG.rst create mode 100644 bicycle_steering_controller/CHANGELOG.rst create mode 100644 steering_controllers_library/CHANGELOG.rst create mode 100644 tricycle_steering_controller/CHANGELOG.rst diff --git a/ackermann_steering_controller/CHANGELOG.rst b/ackermann_steering_controller/CHANGELOG.rst new file mode 100644 index 0000000000..afaf8893e5 --- /dev/null +++ b/ackermann_steering_controller/CHANGELOG.rst @@ -0,0 +1,129 @@ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Changelog for package ackermann_steering_controller +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Forthcoming +----------- +* Fix sphinx for steering odometry library/controllers (`#626 `_) +* Steering odometry library and controllers (`#484 `_) +* Contributors: Bence Magyar, Christoph Fröhlich, Tomislav Petković + +3.8.0 (2023-05-14) +------------------ + +3.7.0 (2023-05-02) +------------------ + +3.6.0 (2023-04-29) +------------------ + +3.5.0 (2023-04-14) +------------------ + +3.4.0 (2023-04-02) +------------------ + +3.3.0 (2023-03-07) +------------------ + +3.2.0 (2023-02-10) +------------------ + +3.1.0 (2023-01-26) +------------------ + +3.0.0 (2023-01-19) +------------------ + +2.15.0 (2022-12-06) +------------------- + +2.14.0 (2022-11-18) +------------------- + +2.13.0 (2022-10-05) +------------------- + +2.12.0 (2022-09-01) +------------------- + +2.11.0 (2022-08-04) +------------------- + +2.10.0 (2022-08-01) +------------------- + +2.9.0 (2022-07-14) +------------------ + +2.8.0 (2022-07-09) +------------------ + +2.7.0 (2022-07-03) +------------------ + +2.6.0 (2022-06-18) +------------------ + +2.5.0 (2022-05-13) +------------------ + +2.4.0 (2022-04-29) +------------------ + +2.3.0 (2022-04-21) +------------------ + +2.2.0 (2022-03-25) +------------------ + +2.1.0 (2022-02-23) +------------------ + +2.0.1 (2022-02-01) +------------------ + +2.0.0 (2022-01-28) +------------------ + +1.3.0 (2022-01-11) +------------------ + +1.2.0 (2021-12-29) +------------------ + +1.1.0 (2021-10-25) +------------------ + +1.0.0 (2021-09-29) +------------------ + +0.5.0 (2021-08-30) +------------------ + +0.4.1 (2021-07-08) +------------------ + +0.4.0 (2021-06-28) +------------------ + +0.3.1 (2021-05-23) +------------------ + +0.3.0 (2021-05-21) +------------------ + +0.2.1 (2021-05-03) +------------------ + +0.2.0 (2021-02-06) +------------------ + +0.1.2 (2021-01-07) +------------------ + +0.1.1 (2021-01-06) +------------------ + +0.1.0 (2020-12-23) +------------------ diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index 446d92eddc..dd4292fbe6 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Use branch name substitution for all links (`#618 `_) +* Fix github links on control.ros.org (`#604 `_) +* Contributors: Christoph Fröhlich + 3.8.0 (2023-05-14) ------------------ diff --git a/bicycle_steering_controller/CHANGELOG.rst b/bicycle_steering_controller/CHANGELOG.rst new file mode 100644 index 0000000000..5d175f004f --- /dev/null +++ b/bicycle_steering_controller/CHANGELOG.rst @@ -0,0 +1,129 @@ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Changelog for package bicycle_steering_controller +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Forthcoming +----------- +* Fix sphinx for steering odometry library/controllers (`#626 `_) +* Steering odometry library and controllers (`#484 `_) +* Contributors: Bence Magyar, Christoph Fröhlich, Tomislav Petković + +3.8.0 (2023-05-14) +------------------ + +3.7.0 (2023-05-02) +------------------ + +3.6.0 (2023-04-29) +------------------ + +3.5.0 (2023-04-14) +------------------ + +3.4.0 (2023-04-02) +------------------ + +3.3.0 (2023-03-07) +------------------ + +3.2.0 (2023-02-10) +------------------ + +3.1.0 (2023-01-26) +------------------ + +3.0.0 (2023-01-19) +------------------ + +2.15.0 (2022-12-06) +------------------- + +2.14.0 (2022-11-18) +------------------- + +2.13.0 (2022-10-05) +------------------- + +2.12.0 (2022-09-01) +------------------- + +2.11.0 (2022-08-04) +------------------- + +2.10.0 (2022-08-01) +------------------- + +2.9.0 (2022-07-14) +------------------ + +2.8.0 (2022-07-09) +------------------ + +2.7.0 (2022-07-03) +------------------ + +2.6.0 (2022-06-18) +------------------ + +2.5.0 (2022-05-13) +------------------ + +2.4.0 (2022-04-29) +------------------ + +2.3.0 (2022-04-21) +------------------ + +2.2.0 (2022-03-25) +------------------ + +2.1.0 (2022-02-23) +------------------ + +2.0.1 (2022-02-01) +------------------ + +2.0.0 (2022-01-28) +------------------ + +1.3.0 (2022-01-11) +------------------ + +1.2.0 (2021-12-29) +------------------ + +1.1.0 (2021-10-25) +------------------ + +1.0.0 (2021-09-29) +------------------ + +0.5.0 (2021-08-30) +------------------ + +0.4.1 (2021-07-08) +------------------ + +0.4.0 (2021-06-28) +------------------ + +0.3.1 (2021-05-23) +------------------ + +0.3.0 (2021-05-21) +------------------ + +0.2.1 (2021-05-03) +------------------ + +0.2.0 (2021-02-06) +------------------ + +0.1.2 (2021-01-07) +------------------ + +0.1.1 (2021-01-06) +------------------ + +0.1.0 (2020-12-23) +------------------ diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index 7947ff0f1a..09dbef17da 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,6 +2,14 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Use generate_parameter_library for all params (`#601 `_) +* Use branch name substitution for all links (`#618 `_) +* Fix compilation warnings (`#621 `_) +* Fix github links on control.ros.org (`#604 `_) +* Contributors: Christoph Fröhlich, Noel Jiménez García, Mathias Lüdtke + 3.8.0 (2023-05-14) ------------------ * Clear registered handles of DiffDriveController on deactivate (`#596 `_) diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index 167f7c1efb..a5180731bf 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Use branch name substitution for all links (`#618 `_) +* Fix github links on control.ros.org (`#604 `_) +* Contributors: Christoph Fröhlich + 3.8.0 (2023-05-14) ------------------ diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index 7fd8390321..0821ea65b2 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Use branch name substitution for all links (`#618 `_) +* Fix github links on control.ros.org (`#604 `_) +* Contributors: Christoph Fröhlich + 3.8.0 (2023-05-14) ------------------ diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index 39599caf99..64cdb55364 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Use branch name substitution for all links (`#618 `_) +* Fix github links on control.ros.org (`#604 `_) +* Contributors: Christoph Fröhlich + 3.8.0 (2023-05-14) ------------------ diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index 4a054fb361..a1ec654cac 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Fix compilation warnings (`#621 `_) +* Contributors: Noel Jiménez García, Mathias Lüdtke + 3.8.0 (2023-05-14) ------------------ diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index 128cc17eda..34249024d1 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Use branch name substitution for all links (`#618 `_) +* Fix github links on control.ros.org (`#604 `_) +* Contributors: Christoph Fröhlich + 3.8.0 (2023-05-14) ------------------ diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index b3f65276f6..166fde3cdb 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,6 +2,13 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Use branch name substitution for all links (`#618 `_) +* [JTC] Fix deprecated header (`#610 `_) +* Fix github links on control.ros.org (`#604 `_) +* Contributors: Christoph Fröhlich + 3.8.0 (2023-05-14) ------------------ diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index fa5824cfe1..6ee1c3eafd 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,13 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Use branch name substitution for all links (`#618 `_) +* [JTC] Fix deprecated header (`#610 `_) +* Fix github links on control.ros.org (`#604 `_) +* Contributors: Christoph Fröhlich + 3.8.0 (2023-05-14) ------------------ * [JTC] Import docs from wiki.ros.org (`#566 `_) diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index cafd1bb4df..54c96370d3 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Use branch name substitution for all links (`#618 `_) +* Fix github links on control.ros.org (`#604 `_) +* Contributors: Christoph Fröhlich + 3.8.0 (2023-05-14) ------------------ diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index 7216b78b1d..a340fa0163 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Steering odometry library and controllers (`#484 `_) +* Contributors: Tomislav Petković + 3.8.0 (2023-05-14) ------------------ diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index 0b5de6cc52..e17316759d 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.8.0 (2023-05-14) ------------------ diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index 17ad4218ca..2c99b05426 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.8.0 (2023-05-14) ------------------ * switch from dash to underscore in setup.cfg (`#595 `_) diff --git a/steering_controllers_library/CHANGELOG.rst b/steering_controllers_library/CHANGELOG.rst new file mode 100644 index 0000000000..fdfab092f7 --- /dev/null +++ b/steering_controllers_library/CHANGELOG.rst @@ -0,0 +1,129 @@ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Changelog for package steering_controllers_library +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Forthcoming +----------- +* Fix sphinx for steering odometry library/controllers (`#626 `_) +* Steering odometry library and controllers (`#484 `_) +* Contributors: Bence Magyar, Christoph Fröhlich, Tomislav Petković + +3.8.0 (2023-05-14) +------------------ + +3.7.0 (2023-05-02) +------------------ + +3.6.0 (2023-04-29) +------------------ + +3.5.0 (2023-04-14) +------------------ + +3.4.0 (2023-04-02) +------------------ + +3.3.0 (2023-03-07) +------------------ + +3.2.0 (2023-02-10) +------------------ + +3.1.0 (2023-01-26) +------------------ + +3.0.0 (2023-01-19) +------------------ + +2.15.0 (2022-12-06) +------------------- + +2.14.0 (2022-11-18) +------------------- + +2.13.0 (2022-10-05) +------------------- + +2.12.0 (2022-09-01) +------------------- + +2.11.0 (2022-08-04) +------------------- + +2.10.0 (2022-08-01) +------------------- + +2.9.0 (2022-07-14) +------------------ + +2.8.0 (2022-07-09) +------------------ + +2.7.0 (2022-07-03) +------------------ + +2.6.0 (2022-06-18) +------------------ + +2.5.0 (2022-05-13) +------------------ + +2.4.0 (2022-04-29) +------------------ + +2.3.0 (2022-04-21) +------------------ + +2.2.0 (2022-03-25) +------------------ + +2.1.0 (2022-02-23) +------------------ + +2.0.1 (2022-02-01) +------------------ + +2.0.0 (2022-01-28) +------------------ + +1.3.0 (2022-01-11) +------------------ + +1.2.0 (2021-12-29) +------------------ + +1.1.0 (2021-10-25) +------------------ + +1.0.0 (2021-09-29) +------------------ + +0.5.0 (2021-08-30) +------------------ + +0.4.1 (2021-07-08) +------------------ + +0.4.0 (2021-06-28) +------------------ + +0.3.1 (2021-05-23) +------------------ + +0.3.0 (2021-05-21) +------------------ + +0.2.1 (2021-05-03) +------------------ + +0.2.0 (2021-02-06) +------------------ + +0.1.2 (2021-01-07) +------------------ + +0.1.1 (2021-01-06) +------------------ + +0.1.0 (2020-12-23) +------------------ diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index 04b28102c6..5ebbbb8c88 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Use branch name substitution for all links (`#618 `_) +* Fix github links on control.ros.org (`#604 `_) +* Contributors: Christoph Fröhlich + 3.8.0 (2023-05-14) ------------------ diff --git a/tricycle_steering_controller/CHANGELOG.rst b/tricycle_steering_controller/CHANGELOG.rst new file mode 100644 index 0000000000..571ad07d52 --- /dev/null +++ b/tricycle_steering_controller/CHANGELOG.rst @@ -0,0 +1,129 @@ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Changelog for package tricycle_steering_controller +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Forthcoming +----------- +* Fix sphinx for steering odometry library/controllers (`#626 `_) +* Steering odometry library and controllers (`#484 `_) +* Contributors: Bence Magyar, Christoph Fröhlich, Tomislav Petković + +3.8.0 (2023-05-14) +------------------ + +3.7.0 (2023-05-02) +------------------ + +3.6.0 (2023-04-29) +------------------ + +3.5.0 (2023-04-14) +------------------ + +3.4.0 (2023-04-02) +------------------ + +3.3.0 (2023-03-07) +------------------ + +3.2.0 (2023-02-10) +------------------ + +3.1.0 (2023-01-26) +------------------ + +3.0.0 (2023-01-19) +------------------ + +2.15.0 (2022-12-06) +------------------- + +2.14.0 (2022-11-18) +------------------- + +2.13.0 (2022-10-05) +------------------- + +2.12.0 (2022-09-01) +------------------- + +2.11.0 (2022-08-04) +------------------- + +2.10.0 (2022-08-01) +------------------- + +2.9.0 (2022-07-14) +------------------ + +2.8.0 (2022-07-09) +------------------ + +2.7.0 (2022-07-03) +------------------ + +2.6.0 (2022-06-18) +------------------ + +2.5.0 (2022-05-13) +------------------ + +2.4.0 (2022-04-29) +------------------ + +2.3.0 (2022-04-21) +------------------ + +2.2.0 (2022-03-25) +------------------ + +2.1.0 (2022-02-23) +------------------ + +2.0.1 (2022-02-01) +------------------ + +2.0.0 (2022-01-28) +------------------ + +1.3.0 (2022-01-11) +------------------ + +1.2.0 (2021-12-29) +------------------ + +1.1.0 (2021-10-25) +------------------ + +1.0.0 (2021-09-29) +------------------ + +0.5.0 (2021-08-30) +------------------ + +0.4.1 (2021-07-08) +------------------ + +0.4.0 (2021-06-28) +------------------ + +0.3.1 (2021-05-23) +------------------ + +0.3.0 (2021-05-21) +------------------ + +0.2.1 (2021-05-03) +------------------ + +0.2.0 (2021-02-06) +------------------ + +0.1.2 (2021-01-07) +------------------ + +0.1.1 (2021-01-06) +------------------ + +0.1.0 (2020-12-23) +------------------ diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index 178077380a..79a68f4f19 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Use branch name substitution for all links (`#618 `_) +* Fix github links on control.ros.org (`#604 `_) +* Contributors: Christoph Fröhlich + 3.8.0 (2023-05-14) ------------------ From 1d6ca87b38b1c4bb40980923b5f747e17d7fef27 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Sun, 28 May 2023 16:00:32 +0100 Subject: [PATCH 035/238] 3.9.0 --- ackermann_steering_controller/CHANGELOG.rst | 4 ++-- ackermann_steering_controller/package.xml | 2 +- admittance_controller/CHANGELOG.rst | 4 ++-- admittance_controller/package.xml | 2 +- bicycle_steering_controller/CHANGELOG.rst | 4 ++-- bicycle_steering_controller/package.xml | 2 +- diff_drive_controller/CHANGELOG.rst | 4 ++-- diff_drive_controller/package.xml | 2 +- effort_controllers/CHANGELOG.rst | 4 ++-- effort_controllers/package.xml | 2 +- force_torque_sensor_broadcaster/CHANGELOG.rst | 4 ++-- force_torque_sensor_broadcaster/package.xml | 2 +- forward_command_controller/CHANGELOG.rst | 4 ++-- forward_command_controller/package.xml | 2 +- gripper_controllers/CHANGELOG.rst | 4 ++-- gripper_controllers/package.xml | 2 +- imu_sensor_broadcaster/CHANGELOG.rst | 4 ++-- imu_sensor_broadcaster/package.xml | 2 +- joint_state_broadcaster/CHANGELOG.rst | 4 ++-- joint_state_broadcaster/package.xml | 2 +- joint_trajectory_controller/CHANGELOG.rst | 4 ++-- joint_trajectory_controller/package.xml | 2 +- position_controllers/CHANGELOG.rst | 4 ++-- position_controllers/package.xml | 2 +- ros2_controllers/CHANGELOG.rst | 4 ++-- ros2_controllers/package.xml | 2 +- ros2_controllers_test_nodes/CHANGELOG.rst | 4 ++-- ros2_controllers_test_nodes/package.xml | 2 +- ros2_controllers_test_nodes/setup.py | 2 +- rqt_joint_trajectory_controller/CHANGELOG.rst | 4 ++-- rqt_joint_trajectory_controller/package.xml | 2 +- rqt_joint_trajectory_controller/setup.py | 2 +- steering_controllers_library/CHANGELOG.rst | 4 ++-- steering_controllers_library/package.xml | 2 +- tricycle_controller/CHANGELOG.rst | 4 ++-- tricycle_controller/package.xml | 2 +- tricycle_steering_controller/CHANGELOG.rst | 4 ++-- tricycle_steering_controller/package.xml | 2 +- velocity_controllers/CHANGELOG.rst | 4 ++-- velocity_controllers/package.xml | 2 +- 40 files changed, 59 insertions(+), 59 deletions(-) diff --git a/ackermann_steering_controller/CHANGELOG.rst b/ackermann_steering_controller/CHANGELOG.rst index afaf8893e5..9a47b7d265 100644 --- a/ackermann_steering_controller/CHANGELOG.rst +++ b/ackermann_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ackermann_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.9.0 (2023-05-28) +------------------ * Fix sphinx for steering odometry library/controllers (`#626 `_) * Steering odometry library and controllers (`#484 `_) * Contributors: Bence Magyar, Christoph Fröhlich, Tomislav Petković diff --git a/ackermann_steering_controller/package.xml b/ackermann_steering_controller/package.xml index 83fc710c22..5060e3f4f9 100644 --- a/ackermann_steering_controller/package.xml +++ b/ackermann_steering_controller/package.xml @@ -2,7 +2,7 @@ ackermann_steering_controller - 3.8.0 + 3.9.0 Steering controller for Ackermann kinematics. Rear fixed wheels are powering the vehicle and front wheels are steering it. Apache License 2.0 Bence Magyar diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index dd4292fbe6..fddcfe1f76 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.9.0 (2023-05-28) +------------------ * Use branch name substitution for all links (`#618 `_) * Fix github links on control.ros.org (`#604 `_) * Contributors: Christoph Fröhlich diff --git a/admittance_controller/package.xml b/admittance_controller/package.xml index 8246b78bda..48f59db5b6 100644 --- a/admittance_controller/package.xml +++ b/admittance_controller/package.xml @@ -2,7 +2,7 @@ admittance_controller - 3.8.0 + 3.9.0 Implementation of admittance controllers for different input and output interface. Denis Štogl Bence Magyar diff --git a/bicycle_steering_controller/CHANGELOG.rst b/bicycle_steering_controller/CHANGELOG.rst index 5d175f004f..2784d4af94 100644 --- a/bicycle_steering_controller/CHANGELOG.rst +++ b/bicycle_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package bicycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.9.0 (2023-05-28) +------------------ * Fix sphinx for steering odometry library/controllers (`#626 `_) * Steering odometry library and controllers (`#484 `_) * Contributors: Bence Magyar, Christoph Fröhlich, Tomislav Petković diff --git a/bicycle_steering_controller/package.xml b/bicycle_steering_controller/package.xml index 95dd240d58..04fe1ce855 100644 --- a/bicycle_steering_controller/package.xml +++ b/bicycle_steering_controller/package.xml @@ -2,7 +2,7 @@ bicycle_steering_controller - 3.8.0 + 3.9.0 Steering controller with bicycle kinematics. Rear fixed wheel is powering the vehicle and front wheel is steering. Apache License 2.0 Bence Magyar diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index 09dbef17da..897e6c5161 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.9.0 (2023-05-28) +------------------ * Use generate_parameter_library for all params (`#601 `_) * Use branch name substitution for all links (`#618 `_) * Fix compilation warnings (`#621 `_) diff --git a/diff_drive_controller/package.xml b/diff_drive_controller/package.xml index 3fadb63efd..3b58854492 100644 --- a/diff_drive_controller/package.xml +++ b/diff_drive_controller/package.xml @@ -1,7 +1,7 @@ diff_drive_controller - 3.8.0 + 3.9.0 Controller for a differential drive mobile base. Bence Magyar Jordan Palacios diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index a5180731bf..ee2c3664f5 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.9.0 (2023-05-28) +------------------ * Use branch name substitution for all links (`#618 `_) * Fix github links on control.ros.org (`#604 `_) * Contributors: Christoph Fröhlich diff --git a/effort_controllers/package.xml b/effort_controllers/package.xml index 5381859c32..5bf20f3ac5 100644 --- a/effort_controllers/package.xml +++ b/effort_controllers/package.xml @@ -1,7 +1,7 @@ effort_controllers - 3.8.0 + 3.9.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index 0821ea65b2..2f8129ba55 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.9.0 (2023-05-28) +------------------ * Use branch name substitution for all links (`#618 `_) * Fix github links on control.ros.org (`#604 `_) * Contributors: Christoph Fröhlich diff --git a/force_torque_sensor_broadcaster/package.xml b/force_torque_sensor_broadcaster/package.xml index f6bc61e8e7..503f971b11 100644 --- a/force_torque_sensor_broadcaster/package.xml +++ b/force_torque_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ force_torque_sensor_broadcaster - 3.8.0 + 3.9.0 Controller to publish state of force-torque sensors. Bence Magyar Denis Štogl diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index 64cdb55364..c01351a3fd 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.9.0 (2023-05-28) +------------------ * Use branch name substitution for all links (`#618 `_) * Fix github links on control.ros.org (`#604 `_) * Contributors: Christoph Fröhlich diff --git a/forward_command_controller/package.xml b/forward_command_controller/package.xml index 76a1731fe7..78bb855476 100644 --- a/forward_command_controller/package.xml +++ b/forward_command_controller/package.xml @@ -1,7 +1,7 @@ forward_command_controller - 3.8.0 + 3.9.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index a1ec654cac..df4099b89c 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.9.0 (2023-05-28) +------------------ * Fix compilation warnings (`#621 `_) * Contributors: Noel Jiménez García, Mathias Lüdtke diff --git a/gripper_controllers/package.xml b/gripper_controllers/package.xml index 0b30330683..189ea82978 100644 --- a/gripper_controllers/package.xml +++ b/gripper_controllers/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> gripper_controllers - 3.8.0 + 3.9.0 The gripper_controllers package Bence Magyar diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index 34249024d1..3675cdd017 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.9.0 (2023-05-28) +------------------ * Use branch name substitution for all links (`#618 `_) * Fix github links on control.ros.org (`#604 `_) * Contributors: Christoph Fröhlich diff --git a/imu_sensor_broadcaster/package.xml b/imu_sensor_broadcaster/package.xml index d8a40cc4c9..d2c62459f3 100644 --- a/imu_sensor_broadcaster/package.xml +++ b/imu_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ imu_sensor_broadcaster - 3.8.0 + 3.9.0 Controller to publish readings of IMU sensors. Bence Magyar Denis Štogl diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index 166fde3cdb..ee09457d8b 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.9.0 (2023-05-28) +------------------ * Use branch name substitution for all links (`#618 `_) * [JTC] Fix deprecated header (`#610 `_) * Fix github links on control.ros.org (`#604 `_) diff --git a/joint_state_broadcaster/package.xml b/joint_state_broadcaster/package.xml index 4601434879..5c6755b678 100644 --- a/joint_state_broadcaster/package.xml +++ b/joint_state_broadcaster/package.xml @@ -1,7 +1,7 @@ joint_state_broadcaster - 3.8.0 + 3.9.0 Broadcaster to publish joint state Bence Magyar Denis Stogl diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index 6ee1c3eafd..5c42a5b977 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.9.0 (2023-05-28) +------------------ * Use branch name substitution for all links (`#618 `_) * [JTC] Fix deprecated header (`#610 `_) * Fix github links on control.ros.org (`#604 `_) diff --git a/joint_trajectory_controller/package.xml b/joint_trajectory_controller/package.xml index 74f2dc6a6e..4647f59b83 100644 --- a/joint_trajectory_controller/package.xml +++ b/joint_trajectory_controller/package.xml @@ -1,7 +1,7 @@ joint_trajectory_controller - 3.8.0 + 3.9.0 Controller for executing joint-space trajectories on a group of joints Bence Magyar Jordan Palacios diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index 54c96370d3..1ed079a953 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.9.0 (2023-05-28) +------------------ * Use branch name substitution for all links (`#618 `_) * Fix github links on control.ros.org (`#604 `_) * Contributors: Christoph Fröhlich diff --git a/position_controllers/package.xml b/position_controllers/package.xml index b2b635ec6c..8b99f3f094 100644 --- a/position_controllers/package.xml +++ b/position_controllers/package.xml @@ -1,7 +1,7 @@ position_controllers - 3.8.0 + 3.9.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index a340fa0163..d3ec738b80 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.9.0 (2023-05-28) +------------------ * Steering odometry library and controllers (`#484 `_) * Contributors: Tomislav Petković diff --git a/ros2_controllers/package.xml b/ros2_controllers/package.xml index ffdcc89d1a..0de09db8a6 100644 --- a/ros2_controllers/package.xml +++ b/ros2_controllers/package.xml @@ -1,7 +1,7 @@ ros2_controllers - 3.8.0 + 3.9.0 Metapackage for ROS2 controllers related packages Bence Magyar Jordan Palacios diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index e17316759d..56b507196d 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.9.0 (2023-05-28) +------------------ 3.8.0 (2023-05-14) ------------------ diff --git a/ros2_controllers_test_nodes/package.xml b/ros2_controllers_test_nodes/package.xml index 171eb3e6ef..4efd3a7b67 100644 --- a/ros2_controllers_test_nodes/package.xml +++ b/ros2_controllers_test_nodes/package.xml @@ -2,7 +2,7 @@ ros2_controllers_test_nodes - 3.8.0 + 3.9.0 Demo nodes for showing and testing functionalities of the ros2_control framework. Denis Štogl diff --git a/ros2_controllers_test_nodes/setup.py b/ros2_controllers_test_nodes/setup.py index b8be85a628..3aa059415d 100644 --- a/ros2_controllers_test_nodes/setup.py +++ b/ros2_controllers_test_nodes/setup.py @@ -20,7 +20,7 @@ setup( name=package_name, - version="3.8.0", + version="3.9.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index 2c99b05426..fe97238c44 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.9.0 (2023-05-28) +------------------ 3.8.0 (2023-05-14) ------------------ diff --git a/rqt_joint_trajectory_controller/package.xml b/rqt_joint_trajectory_controller/package.xml index adf8511b0b..51ca570d42 100644 --- a/rqt_joint_trajectory_controller/package.xml +++ b/rqt_joint_trajectory_controller/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> rqt_joint_trajectory_controller - 3.8.0 + 3.9.0 Graphical frontend for interacting with joint_trajectory_controller instances. Bence Magyar diff --git a/rqt_joint_trajectory_controller/setup.py b/rqt_joint_trajectory_controller/setup.py index 0026688db3..1de53a74c8 100644 --- a/rqt_joint_trajectory_controller/setup.py +++ b/rqt_joint_trajectory_controller/setup.py @@ -7,7 +7,7 @@ setup( name=package_name, - version="3.8.0", + version="3.9.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/steering_controllers_library/CHANGELOG.rst b/steering_controllers_library/CHANGELOG.rst index fdfab092f7..628c3c9722 100644 --- a/steering_controllers_library/CHANGELOG.rst +++ b/steering_controllers_library/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package steering_controllers_library ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.9.0 (2023-05-28) +------------------ * Fix sphinx for steering odometry library/controllers (`#626 `_) * Steering odometry library and controllers (`#484 `_) * Contributors: Bence Magyar, Christoph Fröhlich, Tomislav Petković diff --git a/steering_controllers_library/package.xml b/steering_controllers_library/package.xml index 0395c935da..67461e6708 100644 --- a/steering_controllers_library/package.xml +++ b/steering_controllers_library/package.xml @@ -2,7 +2,7 @@ steering_controllers_library - 3.8.0 + 3.9.0 Package for steering robot configurations including odometry and interfaces. Apache License 2.0 Bence Magyar diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index 5ebbbb8c88..bd3eb809fb 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.9.0 (2023-05-28) +------------------ * Use branch name substitution for all links (`#618 `_) * Fix github links on control.ros.org (`#604 `_) * Contributors: Christoph Fröhlich diff --git a/tricycle_controller/package.xml b/tricycle_controller/package.xml index b75fc43885..398618c0bb 100644 --- a/tricycle_controller/package.xml +++ b/tricycle_controller/package.xml @@ -2,7 +2,7 @@ tricycle_controller - 3.8.0 + 3.9.0 Controller for a tricycle drive mobile base Bence Magyar Tony Najjar diff --git a/tricycle_steering_controller/CHANGELOG.rst b/tricycle_steering_controller/CHANGELOG.rst index 571ad07d52..ff8cda542f 100644 --- a/tricycle_steering_controller/CHANGELOG.rst +++ b/tricycle_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package tricycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.9.0 (2023-05-28) +------------------ * Fix sphinx for steering odometry library/controllers (`#626 `_) * Steering odometry library and controllers (`#484 `_) * Contributors: Bence Magyar, Christoph Fröhlich, Tomislav Petković diff --git a/tricycle_steering_controller/package.xml b/tricycle_steering_controller/package.xml index 652546d098..f7dc25b420 100644 --- a/tricycle_steering_controller/package.xml +++ b/tricycle_steering_controller/package.xml @@ -2,7 +2,7 @@ tricycle_steering_controller - 3.8.0 + 3.9.0 Steering controller with tricycle kinematics. Rear fixed wheels are powering the vehicle and front wheel is steering. Apache License 2.0 Bence Magyar diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index 79a68f4f19..e22c823287 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.9.0 (2023-05-28) +------------------ * Use branch name substitution for all links (`#618 `_) * Fix github links on control.ros.org (`#604 `_) * Contributors: Christoph Fröhlich diff --git a/velocity_controllers/package.xml b/velocity_controllers/package.xml index 5b81d5721f..714ac4366a 100644 --- a/velocity_controllers/package.xml +++ b/velocity_controllers/package.xml @@ -1,7 +1,7 @@ velocity_controllers - 3.8.0 + 3.9.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios From b27b8af7ae9722023612958ac345e20fdf188e81 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 May 2023 06:56:10 +0100 Subject: [PATCH 036/238] Bump actions/setup-python from 4.6.0 to 4.6.1 (#632) --- .github/workflows/ci-format.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-format.yml b/.github/workflows/ci-format.yml index f0993bf717..8f5be014c5 100644 --- a/.github/workflows/ci-format.yml +++ b/.github/workflows/ci-format.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: actions/setup-python@v4.6.0 + - uses: actions/setup-python@v4.6.1 with: python-version: '3.10' - name: Install system hooks From 13039200fc7433c039ff8bb9a179b46d5b72bc75 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 May 2023 06:58:35 +0100 Subject: [PATCH 037/238] Bump ros-tooling/setup-ros from 0.6.1 to 0.6.2 (#631) --- .github/workflows/ci-coverage-build.yml | 2 +- .github/workflows/ci-ros-lint.yml | 2 +- .github/workflows/reusable-ros-tooling-source-build.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-coverage-build.yml b/.github/workflows/ci-coverage-build.yml index 27528e4e16..735a713719 100644 --- a/.github/workflows/ci-coverage-build.yml +++ b/.github/workflows/ci-coverage-build.yml @@ -16,7 +16,7 @@ jobs: env: ROS_DISTRO: rolling steps: - - uses: ros-tooling/setup-ros@0.6.1 + - uses: ros-tooling/setup-ros@0.6.2 with: required-ros-distributions: ${{ env.ROS_DISTRO }} - uses: actions/checkout@v3 diff --git a/.github/workflows/ci-ros-lint.yml b/.github/workflows/ci-ros-lint.yml index fd3e6b634b..3149bba54d 100644 --- a/.github/workflows/ci-ros-lint.yml +++ b/.github/workflows/ci-ros-lint.yml @@ -12,7 +12,7 @@ jobs: linter: [cppcheck, copyright, lint_cmake] steps: - uses: actions/checkout@v3 - - uses: ros-tooling/setup-ros@0.6.1 + - uses: ros-tooling/setup-ros@0.6.2 - uses: ros-tooling/action-ros-lint@v0.1 with: distribution: rolling diff --git a/.github/workflows/reusable-ros-tooling-source-build.yml b/.github/workflows/reusable-ros-tooling-source-build.yml index 31bc0d4475..375c3c7f40 100644 --- a/.github/workflows/reusable-ros-tooling-source-build.yml +++ b/.github/workflows/reusable-ros-tooling-source-build.yml @@ -26,7 +26,7 @@ jobs: strategy: fail-fast: false steps: - - uses: ros-tooling/setup-ros@0.6.1 + - uses: ros-tooling/setup-ros@0.6.2 with: required-ros-distributions: ${{ inputs.ros_distro }} - uses: actions/checkout@v3 From ce60d2f1858331172ea719f9671057d417be6241 Mon Sep 17 00:00:00 2001 From: Sai Kishor Kothakota Date: Tue, 30 May 2023 08:16:31 +0200 Subject: [PATCH 038/238] enable ReflowComments to also use ColumnLimit on comments (#625) --- .clang-format | 2 +- .../admittance_controller.hpp | 14 +- .../admittance_controller/admittance_rule.hpp | 55 +++-- .../test/test_diff_drive_controller.cpp | 12 +- .../forward_controllers_base.hpp | 4 +- .../tolerances.hpp | 4 +- .../trajectory.hpp | 35 +-- .../test/test_trajectory_controller.cpp | 4 +- .../test/test_trajectory_controller_utils.hpp | 15 +- .../steering_odometry.hpp | 217 +++++++++--------- .../src/steering_odometry.cpp | 34 +-- .../test/test_tricycle_controller.cpp | 12 +- 12 files changed, 212 insertions(+), 196 deletions(-) diff --git a/.clang-format b/.clang-format index ab8d077577..9e92cf780a 100644 --- a/.clang-format +++ b/.clang-format @@ -10,5 +10,5 @@ ConstructorInitializerIndentWidth: 0 ContinuationIndentWidth: 2 DerivePointerAlignment: false PointerAlignment: Middle -ReflowComments: false +ReflowComments: true IncludeBlocks: Preserve diff --git a/admittance_controller/include/admittance_controller/admittance_controller.hpp b/admittance_controller/include/admittance_controller/admittance_controller.hpp index e4aef2cf3d..6ff6cdae7a 100644 --- a/admittance_controller/include/admittance_controller/admittance_controller.hpp +++ b/admittance_controller/include/admittance_controller/admittance_controller.hpp @@ -166,20 +166,22 @@ class AdmittanceController : public controller_interface::ChainableControllerInt geometry_msgs::msg::Wrench ft_values_; /** - * @brief Read values from hardware interfaces and set corresponding fields of state_current and ft_values - */ + * @brief Read values from hardware interfaces and set corresponding fields of state_current and + * ft_values + */ void read_state_from_hardware( trajectory_msgs::msg::JointTrajectoryPoint & state_current, geometry_msgs::msg::Wrench & ft_values); /** - * @brief Set fields of state_reference with values from controllers exported position and velocity references - */ + * @brief Set fields of state_reference with values from controllers exported position and + * velocity references + */ void read_state_reference_interfaces(trajectory_msgs::msg::JointTrajectoryPoint & state); /** -* @brief Write values from state_command to claimed hardware interfaces -*/ + * @brief Write values from state_command to claimed hardware interfaces + */ void write_state_to_hardware(const trajectory_msgs::msg::JointTrajectoryPoint & state_command); }; diff --git a/admittance_controller/include/admittance_controller/admittance_rule.hpp b/admittance_controller/include/admittance_controller/admittance_rule.hpp index 0f0aabb063..36c027491c 100644 --- a/admittance_controller/include/admittance_controller/admittance_rule.hpp +++ b/admittance_controller/include/admittance_controller/admittance_rule.hpp @@ -43,13 +43,17 @@ struct AdmittanceTransforms { // transformation from force torque sensor frame to base link frame at reference joint angles Eigen::Isometry3d ref_base_ft_; - // transformation from force torque sensor frame to base link frame at reference + admittance offset joint angles + // transformation from force torque sensor frame to base link frame at reference + admittance + // offset joint angles Eigen::Isometry3d base_ft_; - // transformation from control frame to base link frame at reference + admittance offset joint angles + // transformation from control frame to base link frame at reference + admittance offset joint + // angles Eigen::Isometry3d base_control_; - // transformation from end effector frame to base link frame at reference + admittance offset joint angles + // transformation from end effector frame to base link frame at reference + admittance offset + // joint angles Eigen::Isometry3d base_tip_; - // transformation from center of gravity frame to base link frame at reference + admittance offset joint angles + // transformation from center of gravity frame to base link frame at reference + admittance offset + // joint angles Eigen::Isometry3d base_cog_; // transformation from world frame to base link frame Eigen::Isometry3d world_base_; @@ -111,20 +115,20 @@ class AdmittanceRule controller_interface::return_type reset(const size_t num_joints); /** - * Calculate all transforms needed for admittance control using the loader kinematics plugin. If the transform does - * not exist in the kinematics model, then TF will be used for lookup. The return value is true if all transformation - * are calculated without an error - * \param[in] current_joint_state current joint state of the robot - * \param[in] reference_joint_state input joint state reference - * \param[out] success true if no calls to the kinematics interface fail + * Calculate all transforms needed for admittance control using the loader kinematics plugin. If + * the transform does not exist in the kinematics model, then TF will be used for lookup. The + * return value is true if all transformation are calculated without an error \param[in] + * current_joint_state current joint state of the robot \param[in] reference_joint_state input + * joint state reference \param[out] success true if no calls to the kinematics interface fail */ bool get_all_transforms( const trajectory_msgs::msg::JointTrajectoryPoint & current_joint_state, const trajectory_msgs::msg::JointTrajectoryPoint & reference_joint_state); /** - * Updates parameter_ struct if any parameters have changed since last update. Parameter dependent Eigen field - * members (end_effector_weight_, cog_pos_, mass_, mass_inv_ stiffness, selected_axes, damping_) are also updated + * Updates parameter_ struct if any parameters have changed since last update. Parameter dependent + * Eigen field members (end_effector_weight_, cog_pos_, mass_, mass_inv_ stiffness, selected_axes, + * damping_) are also updated */ void apply_parameters_update(); @@ -136,7 +140,8 @@ class AdmittanceRule * \param[in] measured_wrench most recent measured wrench from force torque sensor * \param[in] reference_joint_state input joint state reference * \param[in] period time in seconds since last controller update - * \param[out] desired_joint_state joint state reference after the admittance offset is applied to the input reference + * \param[out] desired_joint_state joint state reference after the admittance offset is applied to + * the input reference */ controller_interface::return_type update( const trajectory_msgs::msg::JointTrajectoryPoint & current_joint_state, @@ -148,7 +153,8 @@ class AdmittanceRule /** * Set fields of `state_message` from current admittance controller state. * - * \param[out] state_message message containing target position/vel/accel, wrench, and actual robot state, among other things + * \param[out] state_message message containing target position/vel/accel, wrench, and actual + * robot state, among other things */ const control_msgs::msg::AdmittanceControllerState & get_controller_state(); @@ -159,22 +165,21 @@ class AdmittanceRule protected: /** - * Calculates the admittance rule from given the robot's current joint angles. The admittance controller state input - * is updated with the new calculated values. A boolean value is returned indicating if any of the kinematics plugin - * calls failed. - * \param[in] admittance_state contains all the information needed to calculate the admittance offset - * \param[in] dt controller period + * Calculates the admittance rule from given the robot's current joint angles. The admittance + * controller state input is updated with the new calculated values. A boolean value is returned + * indicating if any of the kinematics plugin calls failed. \param[in] admittance_state contains + * all the information needed to calculate the admittance offset \param[in] dt controller period * \param[out] success true if no calls to the kinematics interface fail */ bool calculate_admittance_rule(AdmittanceState & admittance_state, double dt); /** - * Updates internal estimate of wrench in world frame `wrench_world_` given the new measurement `measured_wrench`, - * the sensor to base frame rotation `sensor_world_rot`, and the center of gravity frame to base frame rotation `cog_world_rot`. - * The `wrench_world_` estimate includes gravity compensation - * \param[in] measured_wrench most recent measured wrench from force torque sensor - * \param[in] sensor_world_rot rotation matrix from world frame to sensor frame - * \param[in] cog_world_rot rotation matrix from world frame to center of gravity frame + * Updates internal estimate of wrench in world frame `wrench_world_` given the new measurement + * `measured_wrench`, the sensor to base frame rotation `sensor_world_rot`, and the center of + * gravity frame to base frame rotation `cog_world_rot`. The `wrench_world_` estimate includes + * gravity compensation \param[in] measured_wrench most recent measured wrench from force torque + * sensor \param[in] sensor_world_rot rotation matrix from world frame to sensor frame \param[in] + * cog_world_rot rotation matrix from world frame to center of gravity frame */ void process_wrench_measurements( const geometry_msgs::msg::Wrench & measured_wrench, diff --git a/diff_drive_controller/test/test_diff_drive_controller.cpp b/diff_drive_controller/test/test_diff_drive_controller.cpp index 236f34e9a2..adf4e79afc 100644 --- a/diff_drive_controller/test/test_diff_drive_controller.cpp +++ b/diff_drive_controller/test/test_diff_drive_controller.cpp @@ -48,12 +48,12 @@ class TestableDiffDriveController : public diff_drive_controller::DiffDriveContr } /** - * @brief wait_for_twist block until a new twist is received. - * Requires that the executor is not spinned elsewhere between the - * message publication and the call to this function - * - * @return true if new twist msg was received, false if timeout - */ + * @brief wait_for_twist block until a new twist is received. + * Requires that the executor is not spinned elsewhere between the + * message publication and the call to this function + * + * @return true if new twist msg was received, false if timeout + */ bool wait_for_twist( rclcpp::Executor & executor, const std::chrono::milliseconds & timeout = std::chrono::milliseconds(500)) diff --git a/forward_command_controller/include/forward_command_controller/forward_controllers_base.hpp b/forward_command_controller/include/forward_command_controller/forward_controllers_base.hpp index 3e153d7e2e..d60245f328 100644 --- a/forward_command_controller/include/forward_command_controller/forward_controllers_base.hpp +++ b/forward_command_controller/include/forward_command_controller/forward_controllers_base.hpp @@ -87,8 +87,8 @@ class ForwardControllersBase : public controller_interface::ControllerInterface * * It is expected that error handling of exceptions is done. * - * \returns controller_interface::CallbackReturn::SUCCESS if parameters are successfully read and their values are - * allowed, controller_interface::CallbackReturn::ERROR otherwise. + * \returns controller_interface::CallbackReturn::SUCCESS if parameters are successfully read and + * their values are allowed, controller_interface::CallbackReturn::ERROR otherwise. */ virtual controller_interface::CallbackReturn read_parameters() = 0; diff --git a/joint_trajectory_controller/include/joint_trajectory_controller/tolerances.hpp b/joint_trajectory_controller/include/joint_trajectory_controller/tolerances.hpp index de8f060b1a..e540b06e51 100644 --- a/joint_trajectory_controller/include/joint_trajectory_controller/tolerances.hpp +++ b/joint_trajectory_controller/include/joint_trajectory_controller/tolerances.hpp @@ -123,8 +123,8 @@ SegmentTolerances get_segment_tolerances(Params const & params) * \param state_error State error to check. * \param joint_idx Joint index for the state error * \param state_tolerance State tolerance of joint to check \p state_error against. - * \param show_errors If the joint that violate its tolerance should be output to console. NOT REALTIME if true - * \return True if \p state_error fulfills \p state_tolerance. + * \param show_errors If the joint that violate its tolerance should be output to console. NOT + * REALTIME if true \return True if \p state_error fulfills \p state_tolerance. */ inline bool check_state_tolerance_per_joint( const trajectory_msgs::msg::JointTrajectoryPoint & state_error, int joint_idx, diff --git a/joint_trajectory_controller/include/joint_trajectory_controller/trajectory.hpp b/joint_trajectory_controller/include/joint_trajectory_controller/trajectory.hpp index 7dac4ddbe1..230d0198f7 100644 --- a/joint_trajectory_controller/include/joint_trajectory_controller/trajectory.hpp +++ b/joint_trajectory_controller/include/joint_trajectory_controller/trajectory.hpp @@ -60,26 +60,29 @@ class Trajectory /// containing trajectory. /** * Sampling trajectory at given \p sample_time. - * If position in the \p end_segment_itr is missing it will be deduced from provided velocity, or acceleration respectively. - * Deduction assumes that the provided velocity or acceleration have to be reached at the time defined in the segment. + * If position in the \p end_segment_itr is missing it will be deduced from provided velocity, or + * acceleration respectively. Deduction assumes that the provided velocity or acceleration have to + * be reached at the time defined in the segment. * * Specific case returns for start_segment_itr and end_segment_itr: * - Sampling before the trajectory start: * start_segment_itr = begin(), end_segment_itr = begin() * - Sampling exactly on a point of the trajectory: - * start_segment_itr = iterator where point is, end_segment_itr = iterator after start_segment_itr + * start_segment_itr = iterator where point is, end_segment_itr = iterator after + * start_segment_itr * - Sampling between points: - * start_segment_itr = iterator before the sampled point, end_segment_itr = iterator after start_segment_itr + * start_segment_itr = iterator before the sampled point, end_segment_itr = iterator after + * start_segment_itr * - Sampling after entire trajectory: * start_segment_itr = --end(), end_segment_itr = end() * - Sampling empty msg or before the time given in set_point_before_trajectory_msg() * return false * * \param[in] sample_time Time at which trajectory will be sampled. - * \param[in] interpolation_method Specify whether splines, another method, or no interpolation at all. - * \param[out] expected_state Calculated new at \p sample_time. - * \param[out] start_segment_itr Iterator to the start segment for given \p sample_time. See description above. - * \param[out] end_segment_itr Iterator to the end segment for given \p sample_time. See description above. + * \param[in] interpolation_method Specify whether splines, another method, or no interpolation at + * all. \param[out] expected_state Calculated new at \p sample_time. \param[out] start_segment_itr + * Iterator to the start segment for given \p sample_time. See description above. \param[out] + * end_segment_itr Iterator to the end segment for given \p sample_time. See description above. */ JOINT_TRAJECTORY_CONTROLLER_PUBLIC bool sample( @@ -91,14 +94,16 @@ class Trajectory /** * Do interpolation between 2 states given a time in between their respective timestamps * - * The start and end states need not necessarily be specified all the way to the acceleration level: + * The start and end states need not necessarily be specified all the way to the acceleration + * level: * - If only \b positions are specified, linear interpolation will be used. * - If \b positions and \b velocities are specified, a cubic spline will be used. - * - If \b positions, \b velocities and \b accelerations are specified, a quintic spline will be used. + * - If \b positions, \b velocities and \b accelerations are specified, a quintic spline will be + * used. * * If start and end states have different specifications - * (eg. start is position-only, end is position-velocity), the lowest common specification will be used - * (position-only in the example). + * (eg. start is position-only, end is position-velocity), the lowest common specification will be + * used (position-only in the example). * * \param[in] time_a Time at which the segment state equals \p state_a. * \param[in] state_a State at \p time_a. @@ -153,9 +158,9 @@ class Trajectory }; /** - * \return The map between \p t1 indices (implicitly encoded in return vector indices) to \p t2 indices. - * If \p t1 is "{C, B}" and \p t2 is "{A, B, C, D}", the associated mapping vector is - * "{2, 1}". + * \return The map between \p t1 indices (implicitly encoded in return vector indices) to \p t2 + * indices. If \p t1 is "{C, B}" and \p t2 is "{A, B, C, D}", the associated + * mapping vector is "{2, 1}". */ template inline std::vector mapping(const T & t1, const T & t2) diff --git a/joint_trajectory_controller/test/test_trajectory_controller.cpp b/joint_trajectory_controller/test/test_trajectory_controller.cpp index 74c17dd03d..b1188eede7 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller.cpp +++ b/joint_trajectory_controller/test/test_trajectory_controller.cpp @@ -552,7 +552,7 @@ TEST_P(TrajectoryControllerTestParameterized, state_topic_consistency) const double EPS = 1e-6; /** * @brief check if position error of revolute joints are normalized if not configured so -*/ + */ TEST_P(TrajectoryControllerTestParameterized, position_error_not_normalized) { rclcpp::executors::MultiThreadedExecutor executor; @@ -659,7 +659,7 @@ TEST_P(TrajectoryControllerTestParameterized, position_error_not_normalized) /** * @brief check if position error of revolute joints are normalized if configured so -*/ + */ TEST_P(TrajectoryControllerTestParameterized, position_error_normalized) { rclcpp::executors::MultiThreadedExecutor executor; diff --git a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp index c85eb59f58..8f5f64d57f 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp +++ b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp @@ -61,12 +61,12 @@ class TestableJointTrajectoryController } /** - * @brief wait_for_trajectory block until a new JointTrajectory is received. - * Requires that the executor is not spinned elsewhere between the - * message publication and the call to this function - * - * @return true if new JointTrajectory msg was received, false if timeout - */ + * @brief wait_for_trajectory block until a new JointTrajectory is received. + * Requires that the executor is not spinned elsewhere between the + * message publication and the call to this function + * + * @return true if new JointTrajectory msg was received, false if timeout + */ bool wait_for_trajectory( rclcpp::Executor & executor, const std::chrono::milliseconds & timeout = std::chrono::milliseconds{500}) @@ -293,7 +293,8 @@ class TrajectoryControllerTest : public ::testing::Test /** * delay_btwn_points - delay between each points * points - vector of trajectories. One point per controlled joint - * joint_names - names of joints, if empty, will use joint_names_ up to the number of provided points + * joint_names - names of joints, if empty, will use joint_names_ up to the number of provided + * points */ void publish( const builtin_interfaces::msg::Duration & delay_btwn_points, diff --git a/steering_controllers_library/include/steering_controllers_library/steering_odometry.hpp b/steering_controllers_library/include/steering_controllers_library/steering_odometry.hpp index 002db32354..51cac3c9a9 100644 --- a/steering_controllers_library/include/steering_controllers_library/steering_odometry.hpp +++ b/steering_controllers_library/include/steering_controllers_library/steering_odometry.hpp @@ -33,197 +33,200 @@ const unsigned int BICYCLE_CONFIG = 0; const unsigned int TRICYCLE_CONFIG = 1; const unsigned int ACKERMANN_CONFIG = 2; /** - * \brief The Odometry class handles odometry readings - * (2D pose and velocity with related timestamp) - */ + * \brief The Odometry class handles odometry readings + * (2D pose and velocity with related timestamp) + */ class SteeringOdometry { public: /** - * \brief Constructor - * Timestamp will get the current time value - * Value will be set to zero - * \param velocity_rolling_window_size Rolling window size used to compute the velocity mean - * - */ + * \brief Constructor + * Timestamp will get the current time value + * Value will be set to zero + * \param velocity_rolling_window_size Rolling window size used to compute the velocity mean + * + */ explicit SteeringOdometry(size_t velocity_rolling_window_size = 10); /** - * \brief Initialize the odometry - * \param time Current time - */ + * \brief Initialize the odometry + * \param time Current time + */ void init(const rclcpp::Time & time); /** - * \brief Updates the odometry class with latest wheels position - * \param traction_wheel_pos traction wheel position [rad] - * \param steer_pos Front Steer position [rad] - * \param dt time difference to last call - * \return true if the odometry is actually updated - */ + * \brief Updates the odometry class with latest wheels position + * \param traction_wheel_pos traction wheel position [rad] + * \param steer_pos Front Steer position [rad] + * \param dt time difference to last call + * \return true if the odometry is actually updated + */ bool update_from_position( const double traction_wheel_pos, const double steer_pos, const double dt); /** - * \brief Updates the odometry class with latest wheels position - * \param right_traction_wheel_pos Right traction wheel velocity [rad] - * \param left_traction_wheel_pos Left traction wheel velocity [rad] - * \param front_steer_pos Steer wheel position [rad] - * \param dt time difference to last call - * \return true if the odometry is actually updated - */ + * \brief Updates the odometry class with latest wheels position + * \param right_traction_wheel_pos Right traction wheel velocity [rad] + * \param left_traction_wheel_pos Left traction wheel velocity [rad] + * \param front_steer_pos Steer wheel position [rad] + * \param dt time difference to last call + * \return true if the odometry is actually updated + */ bool update_from_position( const double right_traction_wheel_pos, const double left_traction_wheel_pos, const double steer_pos, const double dt); /** - * \brief Updates the odometry class with latest wheels position - * \param right_traction_wheel_pos Right traction wheel position [rad] - * \param left_traction_wheel_pos Left traction wheel position [rad] - * \param right_steer_pos Right steer wheel position [rad] - * \param left_steer_pos Left steer wheel position [rad] - * \param dt time difference to last call - * \return true if the odometry is actually updated - */ + * \brief Updates the odometry class with latest wheels position + * \param right_traction_wheel_pos Right traction wheel position [rad] + * \param left_traction_wheel_pos Left traction wheel position [rad] + * \param right_steer_pos Right steer wheel position [rad] + * \param left_steer_pos Left steer wheel position [rad] + * \param dt time difference to last call + * \return true if the odometry is actually updated + */ bool update_from_position( const double right_traction_wheel_pos, const double left_traction_wheel_pos, const double right_steer_pos, const double left_steer_pos, const double dt); /** - * \brief Updates the odometry class with latest wheels position - * \param traction_wheel_vel Traction wheel velocity [rad/s] - * \param front_steer_pos Steer wheel position [rad] - * \param dt time difference to last call - * \return true if the odometry is actually updated - */ + * \brief Updates the odometry class with latest wheels position + * \param traction_wheel_vel Traction wheel velocity [rad/s] + * \param front_steer_pos Steer wheel position [rad] + * \param dt time difference to last call + * \return true if the odometry is actually updated + */ bool update_from_velocity( const double traction_wheel_vel, const double steer_pos, const double dt); /** - * \brief Updates the odometry class with latest wheels position - * \param right_traction_wheel_vel Right traction wheel velocity [rad/s] - * \param left_traction_wheel_vel Left traction wheel velocity [rad/s] - * \param front_steer_pos Steer wheel position [rad] - * \param dt time difference to last call - * \return true if the odometry is actually updated - */ + * \brief Updates the odometry class with latest wheels position + * \param right_traction_wheel_vel Right traction wheel velocity [rad/s] + * \param left_traction_wheel_vel Left traction wheel velocity [rad/s] + * \param front_steer_pos Steer wheel position [rad] + * \param dt time difference to last call + * \return true if the odometry is actually updated + */ bool update_from_velocity( const double right_traction_wheel_vel, const double left_traction_wheel_vel, const double steer_pos, const double dt); /** - * \brief Updates the odometry class with latest wheels position - * \param right_traction_wheel_vel Right traction wheel velocity [rad/s] - * \param left_traction_wheel_vel Left traction wheel velocity [rad/s] - * \param right_steer_pos Right steer wheel position [rad] - * \param left_steer_pos Left steer wheel position [rad] - * \param dt time difference to last call - * \return true if the odometry is actually updated - */ + * \brief Updates the odometry class with latest wheels position + * \param right_traction_wheel_vel Right traction wheel velocity [rad/s] + * \param left_traction_wheel_vel Left traction wheel velocity [rad/s] + * \param right_steer_pos Right steer wheel position [rad] + * \param left_steer_pos Left steer wheel position [rad] + * \param dt time difference to last call + * \return true if the odometry is actually updated + */ bool update_from_velocity( const double right_traction_wheel_vel, const double left_traction_wheel_vel, const double right_steer_pos, const double left_steer_pos, const double dt); /** - * \brief Updates the odometry class with latest velocity command - * \param linear Linear velocity [m/s] - * \param angular Angular velocity [rad/s] - * \param time Current time - */ + * \brief Updates the odometry class with latest velocity command + * \param linear Linear velocity [m/s] + * \param angular Angular velocity [rad/s] + * \param time Current time + */ void update_open_loop(const double linear, const double angular, const double dt); /** - * \brief Set odometry type - * \param type odometry type - */ + * \brief Set odometry type + * \param type odometry type + */ void set_odometry_type(const unsigned int type); /** - * \brief heading getter - * \return heading [rad] - */ + * \brief heading getter + * \return heading [rad] + */ double get_heading() const { return heading_; } /** - * \brief x position getter - * \return x position [m] - */ + * \brief x position getter + * \return x position [m] + */ double get_x() const { return x_; } /** - * \brief y position getter - * \return y position [m] - */ + * \brief y position getter + * \return y position [m] + */ double get_y() const { return y_; } /** - * \brief linear velocity getter - * \return linear velocity [m/s] - */ + * \brief linear velocity getter + * \return linear velocity [m/s] + */ double get_linear() const { return linear_; } /** - * \brief angular velocity getter - * \return angular velocity [rad/s] - */ + * \brief angular velocity getter + * \return angular velocity [rad/s] + */ double get_angular() const { return angular_; } /** - * \brief Sets the wheel parameters: radius, separation and wheelbase - */ + * \brief Sets the wheel parameters: radius, separation and wheelbase + */ void set_wheel_params(double wheel_radius, double wheelbase = 0.0, double wheel_track = 0.0); /** - * \brief Velocity rolling window size setter - * \param velocity_rolling_window_size Velocity rolling window size - */ + * \brief Velocity rolling window size setter + * \param velocity_rolling_window_size Velocity rolling window size + */ void set_velocity_rolling_window_size(size_t velocity_rolling_window_size); /** - * \brief Calculates inverse kinematics for the desired linear and angular velocities - * \param Vx Desired linear velocity [m/s] - * \param theta_dot Desired angular velocity [rad/s] - * \return Tuple of velocity commands and steering commands - */ + * \brief Calculates inverse kinematics for the desired linear and angular velocities + * \param Vx Desired linear velocity [m/s] + * \param theta_dot Desired angular velocity [rad/s] + * \return Tuple of velocity commands and steering commands + */ std::tuple, std::vector> get_commands(double Vx, double theta_dot); /** - * \brief Reset poses, heading, and accumulators - */ + * \brief Reset poses, heading, and accumulators + */ void reset_odometry(); private: /** - * \brief Uses precomputed linear and angular velocities to compute dometry and update accumulators - * \param linear Linear velocity [m] (linear displacement, i.e. m/s * dt) computed by previous odometry method - * \param angular Angular velocity [rad] (angular displacement, i.e. m/s * dt) computed by previous odometry method - */ + * \brief Uses precomputed linear and angular velocities to compute dometry and update + * accumulators \param linear Linear velocity [m] (linear displacement, i.e. m/s * dt) + * computed by previous odometry method \param angular Angular velocity [rad] (angular + * displacement, i.e. m/s * dt) computed by previous odometry method + */ bool update_odometry(const double linear_velocity, const double angular, const double dt); /** - * \brief Integrates the velocities (linear and angular) using 2nd order Runge-Kutta - * \param linear Linear velocity [m] (linear displacement, i.e. m/s * dt) computed by encoders - * \param angular Angular velocity [rad] (angular displacement, i.e. m/s * dt) computed by encoders - */ + * \brief Integrates the velocities (linear and angular) using 2nd order Runge-Kutta + * \param linear Linear velocity [m] (linear displacement, i.e. m/s * dt) computed by + * encoders \param angular Angular velocity [rad] (angular displacement, i.e. m/s * dt) computed + * by encoders + */ void integrate_runge_kutta_2(double linear, double angular); /** - * \brief Integrates the velocities (linear and angular) using exact method - * \param linear Linear velocity [m] (linear displacement, i.e. m/s * dt) computed by encoders - * \param angular Angular velocity [rad] (angular displacement, i.e. m/s * dt) computed by encoders - */ + * \brief Integrates the velocities (linear and angular) using exact method + * \param linear Linear velocity [m] (linear displacement, i.e. m/s * dt) computed by + * encoders \param angular Angular velocity [rad] (angular displacement, i.e. m/s * dt) computed + * by encoders + */ void integrate_exact(double linear, double angular); /** - * \brief Calculates steering angle from the desired translational and rotational velocity - * \param Vx Linear velocity [m] - * \param theta_dot Angular velocity [rad] - */ + * \brief Calculates steering angle from the desired translational and rotational velocity + * \param Vx Linear velocity [m] + * \param theta_dot Angular velocity [rad] + */ double convert_trans_rot_vel_to_steering_angle(double Vx, double theta_dot); /** - * \brief Reset linear and angular accumulators - */ + * \brief Reset linear and angular accumulators + */ void reset_accumulators(); /// Current timestamp: diff --git a/steering_controllers_library/src/steering_odometry.cpp b/steering_controllers_library/src/steering_odometry.cpp index 28cd7fc80d..c480dc1253 100644 --- a/steering_controllers_library/src/steering_odometry.cpp +++ b/steering_controllers_library/src/steering_odometry.cpp @@ -1,17 +1,17 @@ /********************************************************************* -* Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt) -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. + * Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. *********************************************************************/ /* @@ -303,10 +303,10 @@ void SteeringOdometry::integrate_runge_kutta_2(double linear, double angular) } /** - * \brief Other possible integration method provided by the class - * \param linear - * \param angular - */ + * \brief Other possible integration method provided by the class + * \param linear + * \param angular + */ void SteeringOdometry::integrate_exact(double linear, double angular) { if (fabs(angular) < 1e-6) diff --git a/tricycle_controller/test/test_tricycle_controller.cpp b/tricycle_controller/test/test_tricycle_controller.cpp index a1f09ddaf8..1d6edf261a 100644 --- a/tricycle_controller/test/test_tricycle_controller.cpp +++ b/tricycle_controller/test/test_tricycle_controller.cpp @@ -52,12 +52,12 @@ class TestableTricycleController : public tricycle_controller::TricycleControlle } /** - * @brief wait_for_twist block until a new twist is received. - * Requires that the executor is not spinned elsewhere between the - * message publication and the call to this function - * - * @return true if new twist msg was received, false if timeout - */ + * @brief wait_for_twist block until a new twist is received. + * Requires that the executor is not spinned elsewhere between the + * message publication and the call to this function + * + * @return true if new twist msg was received, false if timeout + */ bool wait_for_twist( rclcpp::Executor & executor, const std::chrono::milliseconds & timeout = std::chrono::milliseconds(500)) From 96320c66f51fe45b2c75db04cb9de96a0cc6716d Mon Sep 17 00:00:00 2001 From: Alex Moriarty Date: Fri, 2 Jun 2023 12:59:51 -0300 Subject: [PATCH 039/238] [EOL] Drop Foxy (#641) - Foxy now past EOL date of May 2023 Signed-off-by: Alex Moriarty --- .github/ISSUE_TEMPLATE/good-first-issue.md | 4 +-- .github/mergify.yml | 6 ++--- .github/workflows/README.md | 1 - .github/workflows/foxy-abi-compatibility.yml | 20 -------------- .github/workflows/foxy-binary-build-main.yml | 26 ------------------- .../workflows/foxy-binary-build-testing.yml | 26 ------------------- .../workflows/foxy-semi-binary-build-main.yml | 25 ------------------ .../foxy-semi-binary-build-testing.yml | 25 ------------------ .github/workflows/prerelease-check.yml | 2 -- .../reusable-ros-tooling-source-build.yml | 2 +- README.md | 1 - ros2_controllers-not-released.foxy.repos | 6 ----- ros2_controllers.foxy.repos | 13 ---------- 13 files changed, 6 insertions(+), 151 deletions(-) delete mode 100644 .github/workflows/foxy-abi-compatibility.yml delete mode 100644 .github/workflows/foxy-binary-build-main.yml delete mode 100644 .github/workflows/foxy-binary-build-testing.yml delete mode 100644 .github/workflows/foxy-semi-binary-build-main.yml delete mode 100644 .github/workflows/foxy-semi-binary-build-testing.yml delete mode 100644 ros2_controllers-not-released.foxy.repos delete mode 100644 ros2_controllers.foxy.repos diff --git a/.github/ISSUE_TEMPLATE/good-first-issue.md b/.github/ISSUE_TEMPLATE/good-first-issue.md index 6bbf2e957a..95181eceb0 100644 --- a/.github/ISSUE_TEMPLATE/good-first-issue.md +++ b/.github/ISSUE_TEMPLATE/good-first-issue.md @@ -28,7 +28,7 @@ Nothing. This issue is meant to welcome you to Open Source :) We are happy to wa - [ ] 🙋 **Claim this issue**: Comment below. If someone else has claimed it, ask if they've opened a pull request already and if they're stuck -- maybe you can help them solve a problem or move it along! -- [ ] 🗄️ **Create a local workspace** for making your changes and testing [following these instructions](https://docs.ros.org/en/foxy/Tutorials/Workspace/Creating-A-Workspace.html), for Step3 use "Download Source Code" section with [these instructions](https://ros-controls.github.io/control.ros.org/getting_started.html#compiling). +- [ ] 🗄️ **Create a local workspace** for making your changes and testing [following these instructions](https://docs.ros.org/en/rolling/Tutorials/Workspace/Creating-A-Workspace.html), for Step3 use "Download Source Code" section with [these instructions](https://ros-controls.github.io/control.ros.org/getting_started.html#compiling). - [ ] 🍴 **Fork the repository** using the handy button at the top of the repository page and **clone** it into `~/ws_ros2_control/src/ros-controls/ros2_controllers`, [here is a guide that you can follow](https://guides.github.com/activities/forking/) (You will have to remove or empty the existing `ros2_controllers` folder before cloning your own fork) @@ -54,7 +54,7 @@ Nothing. This issue is meant to welcome you to Open Source :) We are happy to wa Don’t hesitate to ask questions or to get help if you feel like you are getting stuck. For example leave a comment below! Furthermore, you find helpful resources here: * [ROS2 Control Contribution Guide](https://ros-controls.github.io/control.ros.org/contributing.html) -* [ROS2 Tutorials](https://docs.ros.org/en/foxy/Tutorials.html) +* [ROS2 Tutorials](https://docs.ros.org/en/rolling/Tutorials.html) * [ROS Answers](https://answers.ros.org/questions/) **Good luck with your first issue!** diff --git a/.github/mergify.yml b/.github/mergify.yml index 87490702f6..49d2acedfa 100644 --- a/.github/mergify.yml +++ b/.github/mergify.yml @@ -1,12 +1,12 @@ pull_request_rules: - - name: Backport to foxy at reviewers discretion + - name: Backport to humble at reviewers discretion conditions: - base=master - - "label=backport-foxy" + - "label=backport-humble" actions: backport: branches: - - foxy + - humble - name: Ask to resolve conflict conditions: diff --git a/.github/workflows/README.md b/.github/workflows/README.md index 5789859350..7727495a97 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -4,7 +4,6 @@ ROS2 Distro | Branch | Build status | Documentation | Released packages :---------: | :----: | :----------: | :-----------: | :---------------: **Rolling** | [`rolling`](https://github.com/ros-controls/ros2_controllers/tree/rolling) | [![Rolling Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-binary-build-main.yml?branch=master)
[![Rolling Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-binary-build-testing.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-binary-build-testing.yml?branch=master)
[![Rolling Semi-Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-semi-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-semi-binary-build-main.yml?branch=master)
[![Rolling Semi-Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-semi-binary-build-testing.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-semi-binary-build-testing.yml?branch=master)
[![Rolling Source Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-source-build.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-source-build.yml?branch=master) | | [ros2_controllers](https://index.ros.org/p/ros2_controllers/#rolling) **Humble** | [`humble`](https://github.com/ros-controls/ros2_controllers/tree/humble) | [![Humble Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-binary-build-main.yml?branch=master)
[![Humble Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-binary-build-testing.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-binary-build-testing.yml?branch=master)
[![Humble Semi-Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-semi-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-semi-binary-build-main.yml?branch=master)
[![Humble Semi-Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-semi-binary-build-testing.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-semi-binary-build-testing.yml?branch=master)
[![Humble Source Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-source-build.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-source-build.yml?branch=master) | | [ros2_controllers](https://index.ros.org/p/ros2_controllers/#humble) -**Foxy** | [`foxy`](https://github.com/ros-controls/ros2_controllers/tree/foxy) | [![Foxy Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/foxy-binary-build-main.yml/badge.svg?branch=foxy)](https://github.com/ros-controls/ros2_controllers/actions/workflows/foxy-binary-build-main.yml?branch=foxy)
[![Foxy Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/foxy-binary-build-testing.yml/badge.svg?branch=foxy)](https://github.com/ros-controls/ros2_controllers/actions/workflows/foxy-binary-build-testing.yml?branch=foxy)
[![Foxy Semi-Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/foxy-semi-binary-build-main.yml/badge.svg?branch=foxy)](https://github.com/ros-controls/ros2_controllers/actions/workflows/foxy-semi-binary-build-main.yml?branch=foxy)
[![Foxy Semi-Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/foxy-semi-binary-build-testing.yml/badge.svg?branch=foxy)](https://github.com/ros-controls/ros2_controllers/actions/workflows/foxy-semi-binary-build-testing.yml?branch=foxy) | | [ros2_controllers](https://index.ros.org/p/ros2_controllers/#foxy) ### Explanation of different build types diff --git a/.github/workflows/foxy-abi-compatibility.yml b/.github/workflows/foxy-abi-compatibility.yml deleted file mode 100644 index 7ce17effd0..0000000000 --- a/.github/workflows/foxy-abi-compatibility.yml +++ /dev/null @@ -1,20 +0,0 @@ -name: Foxy - ABI Compatibility Check -on: - workflow_dispatch: - branches: - - foxy - pull_request: - branches: - - foxy - -jobs: - abi_check: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: ros-industrial/industrial_ci@master - env: - ROS_DISTRO: foxy - ROS_REPO: main - ABICHECK_URL: github:${{ github.repository }}#${{ github.base_ref }} - NOT_TEST_BUILD: true diff --git a/.github/workflows/foxy-binary-build-main.yml b/.github/workflows/foxy-binary-build-main.yml deleted file mode 100644 index b306d7e44d..0000000000 --- a/.github/workflows/foxy-binary-build-main.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: Foxy Binary Build - main -# author: Denis Štogl -# description: 'Build & test all dependencies from released (binary) packages.' - -on: - workflow_dispatch: - branches: - - foxy - pull_request: - branches: - - foxy - push: - branches: - - foxy - schedule: - # Run every morning to detect flakiness and broken dependencies - - cron: '03 1 * * *' - -jobs: - binary: - uses: ./.github/workflows/reusable-industrial-ci-with-cache.yml - with: - ros_distro: foxy - ros_repo: main - upstream_workspace: ros2_controllers-not-released.foxy.repos - ref_for_scheduled_build: foxy diff --git a/.github/workflows/foxy-binary-build-testing.yml b/.github/workflows/foxy-binary-build-testing.yml deleted file mode 100644 index 260751abea..0000000000 --- a/.github/workflows/foxy-binary-build-testing.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: Foxy Binary Build - testing -# author: Denis Štogl -# description: 'Build & test all dependencies from released (binary) packages.' - -on: - workflow_dispatch: - branches: - - foxy - pull_request: - branches: - - foxy - push: - branches: - - foxy - schedule: - # Run every morning to detect flakiness and broken dependencies - - cron: '03 1 * * *' - -jobs: - binary: - uses: ./.github/workflows/reusable-industrial-ci-with-cache.yml - with: - ros_distro: foxy - ros_repo: testing - upstream_workspace: ros2_controllers-not-released.foxy.repos - ref_for_scheduled_build: foxy diff --git a/.github/workflows/foxy-semi-binary-build-main.yml b/.github/workflows/foxy-semi-binary-build-main.yml deleted file mode 100644 index 75c3295124..0000000000 --- a/.github/workflows/foxy-semi-binary-build-main.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: Foxy Semi-Binary Build - main -# description: 'Build & test that compiles the main dependencies from source.' - -on: - workflow_dispatch: - branches: - - foxy - pull_request: - branches: - - foxy - push: - branches: - - foxy - schedule: - # Run every morning to detect flakiness and broken dependencies - - cron: '33 1 * * *' - -jobs: - semi_binary: - uses: ./.github/workflows/reusable-industrial-ci-with-cache.yml - with: - ros_distro: foxy - ros_repo: main - upstream_workspace: ros2_controllers.foxy.repos - ref_for_scheduled_build: foxy diff --git a/.github/workflows/foxy-semi-binary-build-testing.yml b/.github/workflows/foxy-semi-binary-build-testing.yml deleted file mode 100644 index f6d663cc2c..0000000000 --- a/.github/workflows/foxy-semi-binary-build-testing.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: Foxy Semi-Binary Build - testing -# description: 'Build & test that compiles the main dependencies from source.' - -on: - workflow_dispatch: - branches: - - foxy - pull_request: - branches: - - foxy - push: - branches: - - foxy - schedule: - # Run every morning to detect flakiness and broken dependencies - - cron: '33 1 * * *' - -jobs: - semi_binary: - uses: ./.github/workflows/reusable-industrial-ci-with-cache.yml - with: - ros_distro: foxy - ros_repo: testing - upstream_workspace: ros2_controllers.foxy.repos - ref_for_scheduled_build: foxy diff --git a/.github/workflows/prerelease-check.yml b/.github/workflows/prerelease-check.yml index acbb42e16b..5e7326e510 100644 --- a/.github/workflows/prerelease-check.yml +++ b/.github/workflows/prerelease-check.yml @@ -9,7 +9,6 @@ on: default: 'rolling' type: choice options: - - foxy - humble - rolling branch: @@ -18,7 +17,6 @@ on: default: 'master' type: choice options: - - foxy - humble - master diff --git a/.github/workflows/reusable-ros-tooling-source-build.yml b/.github/workflows/reusable-ros-tooling-source-build.yml index 375c3c7f40..4b2e69c06f 100644 --- a/.github/workflows/reusable-ros-tooling-source-build.yml +++ b/.github/workflows/reusable-ros-tooling-source-build.yml @@ -14,7 +14,7 @@ on: required: true type: string ros2_repo_branch: - description: 'Branch in the ros2/ros2 repozitory from which ".repos" should be used. Possible values: master (Rolling), humble, foxy.' + description: 'Branch in the ros2/ros2 repozitory from which ".repos" should be used. Possible values: master (Rolling), humble.' default: 'master' required: false type: string diff --git a/README.md b/README.md index d7986d34c6..8c8539a02b 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,6 @@ ROS2 Distro | Branch | Build status | Documentation | Released packages :---------: | :----: | :----------: | :-----------: | :---------------: **Rolling** | [`rolling`](https://github.com/ros-controls/ros2_controllers/tree/rolling) | [![Rolling Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-binary-build-main.yml?branch=master)
[![Rolling Semi-Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-semi-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-semi-binary-build-main.yml?branch=master) | | [ros2_controllers](https://index.ros.org/p/ros2_controllers/#rolling) **Humble** | [`humble`](https://github.com/ros-controls/ros2_controllers/tree/humble) | [![Humble Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-binary-build-main.yml?branch=master)
[![Humble Semi-Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-semi-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-semi-binary-build-main.yml?branch=master) | | [ros2_controllers](https://index.ros.org/p/ros2_controllers/#humble) -**Foxy** | [`foxy`](https://github.com/ros-controls/ros2_controllers/tree/foxy) | [![Foxy Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/foxy-binary-build-main.yml/badge.svg?branch=foxy)](https://github.com/ros-controls/ros2_controllers/actions/workflows/foxy-binary-build-main.yml?branch=foxy)
[![Foxy Semi-Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/foxy-semi-binary-build-main.yml/badge.svg?branch=foxy)](https://github.com/ros-controls/ros2_controllers/actions/workflows/foxy-semi-binary-build-main.yml?branch=foxy) | | [ros2_controllers](https://index.ros.org/p/ros2_controllers/#foxy) ### Explanation of different build types diff --git a/ros2_controllers-not-released.foxy.repos b/ros2_controllers-not-released.foxy.repos deleted file mode 100644 index 1b3910e7e7..0000000000 --- a/ros2_controllers-not-released.foxy.repos +++ /dev/null @@ -1,6 +0,0 @@ -repositories: - ## EXAMPLE DEPENDENCY -# : -# type: git -# url: git@github.com:/.git -# version: master diff --git a/ros2_controllers.foxy.repos b/ros2_controllers.foxy.repos deleted file mode 100644 index d9a1c841a5..0000000000 --- a/ros2_controllers.foxy.repos +++ /dev/null @@ -1,13 +0,0 @@ -repositories: - ros-controls/ros2_control: - type: git - url: https://github.com/ros-controls/ros2_control.git - version: foxy - control_msgs: - type: git - url: https://github.com/ros-controls/control_msgs.git - version: foxy-devel - realtime_tools: - type: git - url: https://github.com/ros-controls/realtime_tools.git - version: foxy-devel From 77420cb47482c3c580de51e0086622533d82f7d4 Mon Sep 17 00:00:00 2001 From: julescarpentier <44528057+julescarpentier@users.noreply.github.com> Date: Sat, 3 Jun 2023 01:14:33 +0200 Subject: [PATCH 040/238] removed duplicated previous_publish_timestamp_ increment by publish_period_ in diff_drive_controller.cpp (#644) Co-authored-by: Jules CARPENTIER --- diff_drive_controller/src/diff_drive_controller.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/diff_drive_controller/src/diff_drive_controller.cpp b/diff_drive_controller/src/diff_drive_controller.cpp index fc8114630e..2b3b2477b6 100644 --- a/diff_drive_controller/src/diff_drive_controller.cpp +++ b/diff_drive_controller/src/diff_drive_controller.cpp @@ -203,8 +203,6 @@ controller_interface::return_type DiffDriveController::update( if (should_publish) { - previous_publish_timestamp_ += publish_period_; - if (realtime_odometry_publisher_->trylock()) { auto & odometry_message = realtime_odometry_publisher_->msg_; From 73c848bc42e0c3638e140335a041d78b916f7550 Mon Sep 17 00:00:00 2001 From: Alex Moriarty Date: Sun, 4 Jun 2023 08:07:33 -0300 Subject: [PATCH 041/238] [CI] bump action-ros-ci and pass ref for scheduled build (#640) - fixes #619 where scheduled jobs ran with latest commit from default branch instead of the correct branch Signed-off-by: Alex Moriarty --- .github/workflows/ci-coverage-build.yml | 2 +- .github/workflows/reusable-ros-tooling-source-build.yml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-coverage-build.yml b/.github/workflows/ci-coverage-build.yml index 735a713719..67d4c43375 100644 --- a/.github/workflows/ci-coverage-build.yml +++ b/.github/workflows/ci-coverage-build.yml @@ -20,7 +20,7 @@ jobs: with: required-ros-distributions: ${{ env.ROS_DISTRO }} - uses: actions/checkout@v3 - - uses: ros-tooling/action-ros-ci@0.3.0 + - uses: ros-tooling/action-ros-ci@0.3.2 with: target-ros2-distro: ${{ env.ROS_DISTRO }} import-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/reusable-ros-tooling-source-build.yml b/.github/workflows/reusable-ros-tooling-source-build.yml index 4b2e69c06f..daa378297e 100644 --- a/.github/workflows/reusable-ros-tooling-source-build.yml +++ b/.github/workflows/reusable-ros-tooling-source-build.yml @@ -32,9 +32,10 @@ jobs: - uses: actions/checkout@v3 with: ref: ${{ inputs.ref }} - - uses: ros-tooling/action-ros-ci@0.3.0 + - uses: ros-tooling/action-ros-ci@0.3.2 with: target-ros2-distro: ${{ inputs.ros_distro }} + ref: ${{ inputs.ref }} # build all packages listed in the meta package package-name: diff_drive_controller From b47b42df93e264c901ee8293b4db3c4c2e1fcc19 Mon Sep 17 00:00:00 2001 From: gwalck Date: Sun, 4 Jun 2023 17:57:17 +0200 Subject: [PATCH 042/238] Adapted rqt_jtc to newest control_msgs for jtc (#643) --- .../joint_trajectory_controller.py | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/rqt_joint_trajectory_controller/rqt_joint_trajectory_controller/joint_trajectory_controller.py b/rqt_joint_trajectory_controller/rqt_joint_trajectory_controller/joint_trajectory_controller.py index 7e8ec4948e..99f43e125e 100644 --- a/rqt_joint_trajectory_controller/rqt_joint_trajectory_controller/joint_trajectory_controller.py +++ b/rqt_joint_trajectory_controller/rqt_joint_trajectory_controller/joint_trajectory_controller.py @@ -80,8 +80,8 @@ class JointTrajectoryController(Plugin): the following requisites: - The controller type contains the C{JointTrajectoryController} substring, e.g., C{position_controllers/JointTrajectoryController} - - The controller exposes the C{command} and C{state} topics in its - ROS interface. + - The controller exposes the C{command} and C{controller_state} topics + in its ROS interface. Additionally, there must be a URDF loaded with a valid joint limit specification, namely position (when applicable) and velocity limits. @@ -252,10 +252,10 @@ def _update_jtc_list(self): def _on_speed_scaling_change(self, val): self._speed_scale = val / self._speed_scaling_widget.slider.maximum() - def _on_joint_state_change(self, actual_pos): - assert len(actual_pos) == len(self._joint_pos) - for name in actual_pos.keys(): - self._joint_pos[name]["position"] = actual_pos[name] + def _on_joint_state_change(self, current_pos): + assert len(current_pos) == len(self._joint_pos) + for name in current_pos.keys(): + self._joint_pos[name]["position"] = current_pos[name] def _on_cm_change(self, cm_ns): self._cm_ns = cm_ns @@ -289,11 +289,11 @@ def _on_jtc_enabled(self, val): self._speed_scaling_widget.setEnabled(val) if val: - # Widgets send desired position commands to controller + # Widgets send reference position commands to controller self._update_act_pos_timer.stop() self._update_cmd_timer.start() else: - # Controller updates widgets with actual position + # Controller updates widgets with feedback position self._update_cmd_timer.stop() self._update_act_pos_timer.start() @@ -332,7 +332,7 @@ def _load_jtc(self): # Setup ROS interfaces jtc_ns = _resolve_controller_ns(self._cm_ns, self._jtc_name) - state_topic = jtc_ns + "/state" + state_topic = jtc_ns + "/controller_state" cmd_topic = jtc_ns + "/joint_trajectory" self._state_sub = self._node.create_subscription( JointTrajectoryControllerState, state_topic, self._state_cb, 1 @@ -404,12 +404,12 @@ def _unregister_executor(self): self._executor = None def _state_cb(self, msg): - actual_pos = {} + current_pos = {} for i in range(len(msg.joint_names)): joint_name = msg.joint_names[i] - joint_pos = msg.actual.positions[i] - actual_pos[joint_name] = joint_pos - self.jointStateChanged.emit(actual_pos) + joint_pos = msg.feedback.positions[i] + current_pos[joint_name] = joint_pos + self.jointStateChanged.emit(current_pos) def _update_single_cmd_cb(self, val, name): self._joint_pos[name]["command"] = val From a910b9d93395f6d8dd20d06d7aa5b95968cbf152 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Sun, 4 Jun 2023 19:00:02 +0100 Subject: [PATCH 043/238] Remove unnecessary include (#645) --- .../include/steering_controllers_library/steering_odometry.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/steering_controllers_library/include/steering_controllers_library/steering_odometry.hpp b/steering_controllers_library/include/steering_controllers_library/steering_odometry.hpp index 51cac3c9a9..3cfa056b27 100644 --- a/steering_controllers_library/include/steering_controllers_library/steering_odometry.hpp +++ b/steering_controllers_library/include/steering_controllers_library/steering_odometry.hpp @@ -24,7 +24,6 @@ #include "realtime_tools/realtime_buffer.h" #include "realtime_tools/realtime_publisher.h" -#include #include "rcpputils/rolling_mean_accumulator.hpp" namespace steering_odometry From 9958e32146312547f8741ce1050c0b99d2d7358a Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Sun, 4 Jun 2023 19:03:08 +0100 Subject: [PATCH 044/238] Update changelogs --- ackermann_steering_controller/CHANGELOG.rst | 3 +++ admittance_controller/CHANGELOG.rst | 5 +++++ bicycle_steering_controller/CHANGELOG.rst | 3 +++ diff_drive_controller/CHANGELOG.rst | 6 ++++++ effort_controllers/CHANGELOG.rst | 3 +++ force_torque_sensor_broadcaster/CHANGELOG.rst | 3 +++ forward_command_controller/CHANGELOG.rst | 5 +++++ gripper_controllers/CHANGELOG.rst | 3 +++ imu_sensor_broadcaster/CHANGELOG.rst | 3 +++ joint_state_broadcaster/CHANGELOG.rst | 3 +++ joint_trajectory_controller/CHANGELOG.rst | 5 +++++ position_controllers/CHANGELOG.rst | 3 +++ ros2_controllers/CHANGELOG.rst | 3 +++ ros2_controllers_test_nodes/CHANGELOG.rst | 3 +++ rqt_joint_trajectory_controller/CHANGELOG.rst | 5 +++++ steering_controllers_library/CHANGELOG.rst | 6 ++++++ tricycle_controller/CHANGELOG.rst | 5 +++++ tricycle_steering_controller/CHANGELOG.rst | 3 +++ velocity_controllers/CHANGELOG.rst | 3 +++ 19 files changed, 73 insertions(+) diff --git a/ackermann_steering_controller/CHANGELOG.rst b/ackermann_steering_controller/CHANGELOG.rst index 9a47b7d265..43b97d734a 100644 --- a/ackermann_steering_controller/CHANGELOG.rst +++ b/ackermann_steering_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ackermann_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.9.0 (2023-05-28) ------------------ * Fix sphinx for steering odometry library/controllers (`#626 `_) diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index fddcfe1f76..a857a50765 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* enable ReflowComments to also use ColumnLimit on comments (`#625 `_) +* Contributors: Sai Kishor Kothakota + 3.9.0 (2023-05-28) ------------------ * Use branch name substitution for all links (`#618 `_) diff --git a/bicycle_steering_controller/CHANGELOG.rst b/bicycle_steering_controller/CHANGELOG.rst index 2784d4af94..960d0ddac3 100644 --- a/bicycle_steering_controller/CHANGELOG.rst +++ b/bicycle_steering_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package bicycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.9.0 (2023-05-28) ------------------ * Fix sphinx for steering odometry library/controllers (`#626 `_) diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index 897e6c5161..5b727ccb91 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* removed duplicated previous_publish_timestamp\_ increment by publish_period\_ in diff_drive_controller.cpp (`#644 `_) +* enable ReflowComments to also use ColumnLimit on comments (`#625 `_) +* Contributors: Sai Kishor Kothakota, Jules CARPENTIER + 3.9.0 (2023-05-28) ------------------ * Use generate_parameter_library for all params (`#601 `_) diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index ee2c3664f5..7a59a19bc7 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.9.0 (2023-05-28) ------------------ * Use branch name substitution for all links (`#618 `_) diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index 2f8129ba55..cc0517a432 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.9.0 (2023-05-28) ------------------ * Use branch name substitution for all links (`#618 `_) diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index c01351a3fd..2980fdbb80 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* enable ReflowComments to also use ColumnLimit on comments (`#625 `_) +* Contributors: Sai Kishor Kothakota + 3.9.0 (2023-05-28) ------------------ * Use branch name substitution for all links (`#618 `_) diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index df4099b89c..837218b797 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.9.0 (2023-05-28) ------------------ * Fix compilation warnings (`#621 `_) diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index 3675cdd017..02bdacd02b 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.9.0 (2023-05-28) ------------------ * Use branch name substitution for all links (`#618 `_) diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index ee09457d8b..4dfd19e5e2 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.9.0 (2023-05-28) ------------------ * Use branch name substitution for all links (`#618 `_) diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index 5c42a5b977..81a668731b 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* enable ReflowComments to also use ColumnLimit on comments (`#625 `_) +* Contributors: Sai Kishor Kothakota + 3.9.0 (2023-05-28) ------------------ * Use branch name substitution for all links (`#618 `_) diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index 1ed079a953..98def79a4c 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.9.0 (2023-05-28) ------------------ * Use branch name substitution for all links (`#618 `_) diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index d3ec738b80..ba8fa08837 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.9.0 (2023-05-28) ------------------ * Steering odometry library and controllers (`#484 `_) diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index 56b507196d..4f518a2848 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.9.0 (2023-05-28) ------------------ diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index fe97238c44..9de665c74e 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Adapted rqt_jtc to newest control_msgs for jtc (`#643 `_) +* Contributors: gwalck + 3.9.0 (2023-05-28) ------------------ diff --git a/steering_controllers_library/CHANGELOG.rst b/steering_controllers_library/CHANGELOG.rst index 628c3c9722..d2b56d2b22 100644 --- a/steering_controllers_library/CHANGELOG.rst +++ b/steering_controllers_library/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package steering_controllers_library ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Remove unnecessary include (`#645 `_) +* enable ReflowComments to also use ColumnLimit on comments (`#625 `_) +* Contributors: Bence Magyar, Sai Kishor Kothakota + 3.9.0 (2023-05-28) ------------------ * Fix sphinx for steering odometry library/controllers (`#626 `_) diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index bd3eb809fb..0aaf79cc07 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* enable ReflowComments to also use ColumnLimit on comments (`#625 `_) +* Contributors: Sai Kishor Kothakota + 3.9.0 (2023-05-28) ------------------ * Use branch name substitution for all links (`#618 `_) diff --git a/tricycle_steering_controller/CHANGELOG.rst b/tricycle_steering_controller/CHANGELOG.rst index ff8cda542f..ce09dd7765 100644 --- a/tricycle_steering_controller/CHANGELOG.rst +++ b/tricycle_steering_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package tricycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.9.0 (2023-05-28) ------------------ * Fix sphinx for steering odometry library/controllers (`#626 `_) diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index e22c823287..f6d0f96ed6 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.9.0 (2023-05-28) ------------------ * Use branch name substitution for all links (`#618 `_) From 9a6eec1af1816ff255a334ff67b2ade63e509503 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Sun, 4 Jun 2023 19:03:58 +0100 Subject: [PATCH 045/238] 3.10.0 --- ackermann_steering_controller/CHANGELOG.rst | 4 ++-- ackermann_steering_controller/package.xml | 2 +- admittance_controller/CHANGELOG.rst | 4 ++-- admittance_controller/package.xml | 2 +- bicycle_steering_controller/CHANGELOG.rst | 4 ++-- bicycle_steering_controller/package.xml | 2 +- diff_drive_controller/CHANGELOG.rst | 4 ++-- diff_drive_controller/package.xml | 2 +- effort_controllers/CHANGELOG.rst | 4 ++-- effort_controllers/package.xml | 2 +- force_torque_sensor_broadcaster/CHANGELOG.rst | 4 ++-- force_torque_sensor_broadcaster/package.xml | 2 +- forward_command_controller/CHANGELOG.rst | 4 ++-- forward_command_controller/package.xml | 2 +- gripper_controllers/CHANGELOG.rst | 4 ++-- gripper_controllers/package.xml | 2 +- imu_sensor_broadcaster/CHANGELOG.rst | 4 ++-- imu_sensor_broadcaster/package.xml | 2 +- joint_state_broadcaster/CHANGELOG.rst | 4 ++-- joint_state_broadcaster/package.xml | 2 +- joint_trajectory_controller/CHANGELOG.rst | 4 ++-- joint_trajectory_controller/package.xml | 2 +- position_controllers/CHANGELOG.rst | 4 ++-- position_controllers/package.xml | 2 +- ros2_controllers/CHANGELOG.rst | 4 ++-- ros2_controllers/package.xml | 2 +- ros2_controllers_test_nodes/CHANGELOG.rst | 4 ++-- ros2_controllers_test_nodes/package.xml | 2 +- ros2_controllers_test_nodes/setup.py | 2 +- rqt_joint_trajectory_controller/CHANGELOG.rst | 4 ++-- rqt_joint_trajectory_controller/package.xml | 2 +- rqt_joint_trajectory_controller/setup.py | 2 +- steering_controllers_library/CHANGELOG.rst | 4 ++-- steering_controllers_library/package.xml | 2 +- tricycle_controller/CHANGELOG.rst | 4 ++-- tricycle_controller/package.xml | 2 +- tricycle_steering_controller/CHANGELOG.rst | 4 ++-- tricycle_steering_controller/package.xml | 2 +- velocity_controllers/CHANGELOG.rst | 4 ++-- velocity_controllers/package.xml | 2 +- 40 files changed, 59 insertions(+), 59 deletions(-) diff --git a/ackermann_steering_controller/CHANGELOG.rst b/ackermann_steering_controller/CHANGELOG.rst index 43b97d734a..bede1541f2 100644 --- a/ackermann_steering_controller/CHANGELOG.rst +++ b/ackermann_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ackermann_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.10.0 (2023-06-04) +------------------- 3.9.0 (2023-05-28) ------------------ diff --git a/ackermann_steering_controller/package.xml b/ackermann_steering_controller/package.xml index 5060e3f4f9..5bd9c96bc1 100644 --- a/ackermann_steering_controller/package.xml +++ b/ackermann_steering_controller/package.xml @@ -2,7 +2,7 @@ ackermann_steering_controller - 3.9.0 + 3.10.0 Steering controller for Ackermann kinematics. Rear fixed wheels are powering the vehicle and front wheels are steering it. Apache License 2.0 Bence Magyar diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index a857a50765..03146c20cf 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.10.0 (2023-06-04) +------------------- * enable ReflowComments to also use ColumnLimit on comments (`#625 `_) * Contributors: Sai Kishor Kothakota diff --git a/admittance_controller/package.xml b/admittance_controller/package.xml index 48f59db5b6..4d7530cecc 100644 --- a/admittance_controller/package.xml +++ b/admittance_controller/package.xml @@ -2,7 +2,7 @@ admittance_controller - 3.9.0 + 3.10.0 Implementation of admittance controllers for different input and output interface. Denis Štogl Bence Magyar diff --git a/bicycle_steering_controller/CHANGELOG.rst b/bicycle_steering_controller/CHANGELOG.rst index 960d0ddac3..868e74bb9c 100644 --- a/bicycle_steering_controller/CHANGELOG.rst +++ b/bicycle_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package bicycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.10.0 (2023-06-04) +------------------- 3.9.0 (2023-05-28) ------------------ diff --git a/bicycle_steering_controller/package.xml b/bicycle_steering_controller/package.xml index 04fe1ce855..99023fffb9 100644 --- a/bicycle_steering_controller/package.xml +++ b/bicycle_steering_controller/package.xml @@ -2,7 +2,7 @@ bicycle_steering_controller - 3.9.0 + 3.10.0 Steering controller with bicycle kinematics. Rear fixed wheel is powering the vehicle and front wheel is steering. Apache License 2.0 Bence Magyar diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index 5b727ccb91..30af3cfb36 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.10.0 (2023-06-04) +------------------- * removed duplicated previous_publish_timestamp\_ increment by publish_period\_ in diff_drive_controller.cpp (`#644 `_) * enable ReflowComments to also use ColumnLimit on comments (`#625 `_) * Contributors: Sai Kishor Kothakota, Jules CARPENTIER diff --git a/diff_drive_controller/package.xml b/diff_drive_controller/package.xml index 3b58854492..0875ba94cd 100644 --- a/diff_drive_controller/package.xml +++ b/diff_drive_controller/package.xml @@ -1,7 +1,7 @@ diff_drive_controller - 3.9.0 + 3.10.0 Controller for a differential drive mobile base. Bence Magyar Jordan Palacios diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index 7a59a19bc7..d719d701ff 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.10.0 (2023-06-04) +------------------- 3.9.0 (2023-05-28) ------------------ diff --git a/effort_controllers/package.xml b/effort_controllers/package.xml index 5bf20f3ac5..9a59fe42cd 100644 --- a/effort_controllers/package.xml +++ b/effort_controllers/package.xml @@ -1,7 +1,7 @@ effort_controllers - 3.9.0 + 3.10.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index cc0517a432..74a8612a85 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.10.0 (2023-06-04) +------------------- 3.9.0 (2023-05-28) ------------------ diff --git a/force_torque_sensor_broadcaster/package.xml b/force_torque_sensor_broadcaster/package.xml index 503f971b11..d517ed204a 100644 --- a/force_torque_sensor_broadcaster/package.xml +++ b/force_torque_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ force_torque_sensor_broadcaster - 3.9.0 + 3.10.0 Controller to publish state of force-torque sensors. Bence Magyar Denis Štogl diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index 2980fdbb80..8d581028b6 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.10.0 (2023-06-04) +------------------- * enable ReflowComments to also use ColumnLimit on comments (`#625 `_) * Contributors: Sai Kishor Kothakota diff --git a/forward_command_controller/package.xml b/forward_command_controller/package.xml index 78bb855476..5c17d80379 100644 --- a/forward_command_controller/package.xml +++ b/forward_command_controller/package.xml @@ -1,7 +1,7 @@ forward_command_controller - 3.9.0 + 3.10.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index 837218b797..f136ab4e44 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.10.0 (2023-06-04) +------------------- 3.9.0 (2023-05-28) ------------------ diff --git a/gripper_controllers/package.xml b/gripper_controllers/package.xml index 189ea82978..cc55d0be39 100644 --- a/gripper_controllers/package.xml +++ b/gripper_controllers/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> gripper_controllers - 3.9.0 + 3.10.0 The gripper_controllers package Bence Magyar diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index 02bdacd02b..4cdeba5f33 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.10.0 (2023-06-04) +------------------- 3.9.0 (2023-05-28) ------------------ diff --git a/imu_sensor_broadcaster/package.xml b/imu_sensor_broadcaster/package.xml index d2c62459f3..6a9a53d3a6 100644 --- a/imu_sensor_broadcaster/package.xml +++ b/imu_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ imu_sensor_broadcaster - 3.9.0 + 3.10.0 Controller to publish readings of IMU sensors. Bence Magyar Denis Štogl diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index 4dfd19e5e2..f94d8a7e13 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.10.0 (2023-06-04) +------------------- 3.9.0 (2023-05-28) ------------------ diff --git a/joint_state_broadcaster/package.xml b/joint_state_broadcaster/package.xml index 5c6755b678..ea7a5c9a54 100644 --- a/joint_state_broadcaster/package.xml +++ b/joint_state_broadcaster/package.xml @@ -1,7 +1,7 @@ joint_state_broadcaster - 3.9.0 + 3.10.0 Broadcaster to publish joint state Bence Magyar Denis Stogl diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index 81a668731b..09ff60ce87 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.10.0 (2023-06-04) +------------------- * enable ReflowComments to also use ColumnLimit on comments (`#625 `_) * Contributors: Sai Kishor Kothakota diff --git a/joint_trajectory_controller/package.xml b/joint_trajectory_controller/package.xml index 4647f59b83..9166118724 100644 --- a/joint_trajectory_controller/package.xml +++ b/joint_trajectory_controller/package.xml @@ -1,7 +1,7 @@ joint_trajectory_controller - 3.9.0 + 3.10.0 Controller for executing joint-space trajectories on a group of joints Bence Magyar Jordan Palacios diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index 98def79a4c..43389c6f1d 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.10.0 (2023-06-04) +------------------- 3.9.0 (2023-05-28) ------------------ diff --git a/position_controllers/package.xml b/position_controllers/package.xml index 8b99f3f094..f2a968e2d9 100644 --- a/position_controllers/package.xml +++ b/position_controllers/package.xml @@ -1,7 +1,7 @@ position_controllers - 3.9.0 + 3.10.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index ba8fa08837..76adc2f316 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.10.0 (2023-06-04) +------------------- 3.9.0 (2023-05-28) ------------------ diff --git a/ros2_controllers/package.xml b/ros2_controllers/package.xml index 0de09db8a6..3a09b034e0 100644 --- a/ros2_controllers/package.xml +++ b/ros2_controllers/package.xml @@ -1,7 +1,7 @@ ros2_controllers - 3.9.0 + 3.10.0 Metapackage for ROS2 controllers related packages Bence Magyar Jordan Palacios diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index 4f518a2848..e590ac15b8 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.10.0 (2023-06-04) +------------------- 3.9.0 (2023-05-28) ------------------ diff --git a/ros2_controllers_test_nodes/package.xml b/ros2_controllers_test_nodes/package.xml index 4efd3a7b67..0649b1afce 100644 --- a/ros2_controllers_test_nodes/package.xml +++ b/ros2_controllers_test_nodes/package.xml @@ -2,7 +2,7 @@ ros2_controllers_test_nodes - 3.9.0 + 3.10.0 Demo nodes for showing and testing functionalities of the ros2_control framework. Denis Štogl diff --git a/ros2_controllers_test_nodes/setup.py b/ros2_controllers_test_nodes/setup.py index 3aa059415d..0b9f5078e3 100644 --- a/ros2_controllers_test_nodes/setup.py +++ b/ros2_controllers_test_nodes/setup.py @@ -20,7 +20,7 @@ setup( name=package_name, - version="3.9.0", + version="3.10.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index 9de665c74e..9a90919f3c 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.10.0 (2023-06-04) +------------------- * Adapted rqt_jtc to newest control_msgs for jtc (`#643 `_) * Contributors: gwalck diff --git a/rqt_joint_trajectory_controller/package.xml b/rqt_joint_trajectory_controller/package.xml index 51ca570d42..fd0dd6199b 100644 --- a/rqt_joint_trajectory_controller/package.xml +++ b/rqt_joint_trajectory_controller/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> rqt_joint_trajectory_controller - 3.9.0 + 3.10.0 Graphical frontend for interacting with joint_trajectory_controller instances. Bence Magyar diff --git a/rqt_joint_trajectory_controller/setup.py b/rqt_joint_trajectory_controller/setup.py index 1de53a74c8..4bf28a6f1c 100644 --- a/rqt_joint_trajectory_controller/setup.py +++ b/rqt_joint_trajectory_controller/setup.py @@ -7,7 +7,7 @@ setup( name=package_name, - version="3.9.0", + version="3.10.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/steering_controllers_library/CHANGELOG.rst b/steering_controllers_library/CHANGELOG.rst index d2b56d2b22..2a9c549160 100644 --- a/steering_controllers_library/CHANGELOG.rst +++ b/steering_controllers_library/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package steering_controllers_library ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.10.0 (2023-06-04) +------------------- * Remove unnecessary include (`#645 `_) * enable ReflowComments to also use ColumnLimit on comments (`#625 `_) * Contributors: Bence Magyar, Sai Kishor Kothakota diff --git a/steering_controllers_library/package.xml b/steering_controllers_library/package.xml index 67461e6708..64f078762a 100644 --- a/steering_controllers_library/package.xml +++ b/steering_controllers_library/package.xml @@ -2,7 +2,7 @@ steering_controllers_library - 3.9.0 + 3.10.0 Package for steering robot configurations including odometry and interfaces. Apache License 2.0 Bence Magyar diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index 0aaf79cc07..f1cf482346 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.10.0 (2023-06-04) +------------------- * enable ReflowComments to also use ColumnLimit on comments (`#625 `_) * Contributors: Sai Kishor Kothakota diff --git a/tricycle_controller/package.xml b/tricycle_controller/package.xml index 398618c0bb..7444292e41 100644 --- a/tricycle_controller/package.xml +++ b/tricycle_controller/package.xml @@ -2,7 +2,7 @@ tricycle_controller - 3.9.0 + 3.10.0 Controller for a tricycle drive mobile base Bence Magyar Tony Najjar diff --git a/tricycle_steering_controller/CHANGELOG.rst b/tricycle_steering_controller/CHANGELOG.rst index ce09dd7765..0565dc1548 100644 --- a/tricycle_steering_controller/CHANGELOG.rst +++ b/tricycle_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package tricycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.10.0 (2023-06-04) +------------------- 3.9.0 (2023-05-28) ------------------ diff --git a/tricycle_steering_controller/package.xml b/tricycle_steering_controller/package.xml index f7dc25b420..3478ce0e96 100644 --- a/tricycle_steering_controller/package.xml +++ b/tricycle_steering_controller/package.xml @@ -2,7 +2,7 @@ tricycle_steering_controller - 3.9.0 + 3.10.0 Steering controller with tricycle kinematics. Rear fixed wheels are powering the vehicle and front wheel is steering. Apache License 2.0 Bence Magyar diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index f6d0f96ed6..cb7feca8da 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.10.0 (2023-06-04) +------------------- 3.9.0 (2023-05-28) ------------------ diff --git a/velocity_controllers/package.xml b/velocity_controllers/package.xml index 714ac4366a..c1ab7d16b3 100644 --- a/velocity_controllers/package.xml +++ b/velocity_controllers/package.xml @@ -1,7 +1,7 @@ velocity_controllers - 3.9.0 + 3.10.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios From ec4a24b1afd7e8b51d2c3ca9f5c421bd2843e96e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Jun 2023 12:34:03 +0100 Subject: [PATCH 046/238] Bump uesteibar/reviewer-lottery from 2 to 3 (#654) --- .github/workflows/reviewer_lottery.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/reviewer_lottery.yml b/.github/workflows/reviewer_lottery.yml index 94f3d9bde6..772809825f 100644 --- a/.github/workflows/reviewer_lottery.yml +++ b/.github/workflows/reviewer_lottery.yml @@ -8,6 +8,6 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: uesteibar/reviewer-lottery@v2 + - uses: uesteibar/reviewer-lottery@v3 with: repo-token: ${{ secrets.GITHUB_TOKEN }} From d96f662b9830e030ea80e6564952730744c9c594 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Tue, 6 Jun 2023 12:46:37 +0100 Subject: [PATCH 047/238] Second round of dependencies fix (#655) * Add missing backward_ros dependency and minor cmake cleanup * Fix unused arg warning --- steering_controllers_library/CMakeLists.txt | 1 - steering_controllers_library/package.xml | 2 +- .../test/test_steering_controllers_library.hpp | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/steering_controllers_library/CMakeLists.txt b/steering_controllers_library/CMakeLists.txt index 5fdd727188..4a98dbf320 100644 --- a/steering_controllers_library/CMakeLists.txt +++ b/steering_controllers_library/CMakeLists.txt @@ -55,7 +55,6 @@ target_compile_definitions(steering_controllers_library PRIVATE "STEERING_CONTRO if(BUILD_TESTING) find_package(ament_cmake_gmock REQUIRED) find_package(controller_manager REQUIRED) - find_package(hardware_interface REQUIRED) find_package(ros2_control_test_assets REQUIRED) add_rostest_with_parameters_gmock( diff --git a/steering_controllers_library/package.xml b/steering_controllers_library/package.xml index 64f078762a..2684a2f727 100644 --- a/steering_controllers_library/package.xml +++ b/steering_controllers_library/package.xml @@ -18,6 +18,7 @@ generate_parameter_library + backward_ros control_msgs controller_interface geometry_msgs @@ -36,7 +37,6 @@ ament_cmake_gmock controller_manager - hardware_interface ros2_control_test_assets diff --git a/steering_controllers_library/test/test_steering_controllers_library.hpp b/steering_controllers_library/test/test_steering_controllers_library.hpp index 23ab7b64f2..c72c61257a 100644 --- a/steering_controllers_library/test/test_steering_controllers_library.hpp +++ b/steering_controllers_library/test/test_steering_controllers_library.hpp @@ -138,7 +138,7 @@ class TestableSteeringControllersLibrary return controller_interface::CallbackReturn::SUCCESS; } - bool update_odometry(const rclcpp::Duration & period) { return true; } + bool update_odometry(const rclcpp::Duration & /*period*/) { return true; } private: rclcpp::WaitSet ref_subscriber_wait_set_; From 129057ba50477c78f5883d8c735d5957821b0585 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Tue, 6 Jun 2023 12:47:46 +0100 Subject: [PATCH 048/238] Update changelogs --- ackermann_steering_controller/CHANGELOG.rst | 3 +++ admittance_controller/CHANGELOG.rst | 3 +++ bicycle_steering_controller/CHANGELOG.rst | 3 +++ diff_drive_controller/CHANGELOG.rst | 3 +++ effort_controllers/CHANGELOG.rst | 3 +++ force_torque_sensor_broadcaster/CHANGELOG.rst | 3 +++ forward_command_controller/CHANGELOG.rst | 3 +++ gripper_controllers/CHANGELOG.rst | 3 +++ imu_sensor_broadcaster/CHANGELOG.rst | 3 +++ joint_state_broadcaster/CHANGELOG.rst | 3 +++ joint_trajectory_controller/CHANGELOG.rst | 3 +++ position_controllers/CHANGELOG.rst | 3 +++ ros2_controllers/CHANGELOG.rst | 3 +++ ros2_controllers_test_nodes/CHANGELOG.rst | 3 +++ rqt_joint_trajectory_controller/CHANGELOG.rst | 3 +++ steering_controllers_library/CHANGELOG.rst | 5 +++++ tricycle_controller/CHANGELOG.rst | 3 +++ tricycle_steering_controller/CHANGELOG.rst | 3 +++ velocity_controllers/CHANGELOG.rst | 3 +++ 19 files changed, 59 insertions(+) diff --git a/ackermann_steering_controller/CHANGELOG.rst b/ackermann_steering_controller/CHANGELOG.rst index bede1541f2..6375badb25 100644 --- a/ackermann_steering_controller/CHANGELOG.rst +++ b/ackermann_steering_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ackermann_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.10.0 (2023-06-04) ------------------- diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index 03146c20cf..57e7dd84ac 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.10.0 (2023-06-04) ------------------- * enable ReflowComments to also use ColumnLimit on comments (`#625 `_) diff --git a/bicycle_steering_controller/CHANGELOG.rst b/bicycle_steering_controller/CHANGELOG.rst index 868e74bb9c..f913267b94 100644 --- a/bicycle_steering_controller/CHANGELOG.rst +++ b/bicycle_steering_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package bicycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.10.0 (2023-06-04) ------------------- diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index 30af3cfb36..d33d4c3018 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.10.0 (2023-06-04) ------------------- * removed duplicated previous_publish_timestamp\_ increment by publish_period\_ in diff_drive_controller.cpp (`#644 `_) diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index d719d701ff..29ff565560 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.10.0 (2023-06-04) ------------------- diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index 74a8612a85..f7025b8e60 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.10.0 (2023-06-04) ------------------- diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index 8d581028b6..2256b00eb6 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.10.0 (2023-06-04) ------------------- * enable ReflowComments to also use ColumnLimit on comments (`#625 `_) diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index f136ab4e44..6c7bee11e0 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.10.0 (2023-06-04) ------------------- diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index 4cdeba5f33..fb8749605d 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.10.0 (2023-06-04) ------------------- diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index f94d8a7e13..f786d648f2 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.10.0 (2023-06-04) ------------------- diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index 09ff60ce87..f538df0739 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.10.0 (2023-06-04) ------------------- * enable ReflowComments to also use ColumnLimit on comments (`#625 `_) diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index 43389c6f1d..460d1c16ce 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.10.0 (2023-06-04) ------------------- diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index 76adc2f316..a702904ba9 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.10.0 (2023-06-04) ------------------- diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index e590ac15b8..c92759797c 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.10.0 (2023-06-04) ------------------- diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index 9a90919f3c..f9b0f43a29 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.10.0 (2023-06-04) ------------------- * Adapted rqt_jtc to newest control_msgs for jtc (`#643 `_) diff --git a/steering_controllers_library/CHANGELOG.rst b/steering_controllers_library/CHANGELOG.rst index 2a9c549160..b2fa703063 100644 --- a/steering_controllers_library/CHANGELOG.rst +++ b/steering_controllers_library/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package steering_controllers_library ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Second round of dependencies fix (`#655 `_) +* Contributors: Bence Magyar + 3.10.0 (2023-06-04) ------------------- * Remove unnecessary include (`#645 `_) diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index f1cf482346..e67efd3d4b 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.10.0 (2023-06-04) ------------------- * enable ReflowComments to also use ColumnLimit on comments (`#625 `_) diff --git a/tricycle_steering_controller/CHANGELOG.rst b/tricycle_steering_controller/CHANGELOG.rst index 0565dc1548..95d95e9ad5 100644 --- a/tricycle_steering_controller/CHANGELOG.rst +++ b/tricycle_steering_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package tricycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.10.0 (2023-06-04) ------------------- diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index cb7feca8da..79d4bc0a32 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.10.0 (2023-06-04) ------------------- From d14c70416d0a88db810904d274112414cdcd7a57 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Tue, 6 Jun 2023 12:48:23 +0100 Subject: [PATCH 049/238] 3.10.1 --- ackermann_steering_controller/CHANGELOG.rst | 4 ++-- ackermann_steering_controller/package.xml | 2 +- admittance_controller/CHANGELOG.rst | 4 ++-- admittance_controller/package.xml | 2 +- bicycle_steering_controller/CHANGELOG.rst | 4 ++-- bicycle_steering_controller/package.xml | 2 +- diff_drive_controller/CHANGELOG.rst | 4 ++-- diff_drive_controller/package.xml | 2 +- effort_controllers/CHANGELOG.rst | 4 ++-- effort_controllers/package.xml | 2 +- force_torque_sensor_broadcaster/CHANGELOG.rst | 4 ++-- force_torque_sensor_broadcaster/package.xml | 2 +- forward_command_controller/CHANGELOG.rst | 4 ++-- forward_command_controller/package.xml | 2 +- gripper_controllers/CHANGELOG.rst | 4 ++-- gripper_controllers/package.xml | 2 +- imu_sensor_broadcaster/CHANGELOG.rst | 4 ++-- imu_sensor_broadcaster/package.xml | 2 +- joint_state_broadcaster/CHANGELOG.rst | 4 ++-- joint_state_broadcaster/package.xml | 2 +- joint_trajectory_controller/CHANGELOG.rst | 4 ++-- joint_trajectory_controller/package.xml | 2 +- position_controllers/CHANGELOG.rst | 4 ++-- position_controllers/package.xml | 2 +- ros2_controllers/CHANGELOG.rst | 4 ++-- ros2_controllers/package.xml | 2 +- ros2_controllers_test_nodes/CHANGELOG.rst | 4 ++-- ros2_controllers_test_nodes/package.xml | 2 +- ros2_controllers_test_nodes/setup.py | 2 +- rqt_joint_trajectory_controller/CHANGELOG.rst | 4 ++-- rqt_joint_trajectory_controller/package.xml | 2 +- rqt_joint_trajectory_controller/setup.py | 2 +- steering_controllers_library/CHANGELOG.rst | 4 ++-- steering_controllers_library/package.xml | 2 +- tricycle_controller/CHANGELOG.rst | 4 ++-- tricycle_controller/package.xml | 2 +- tricycle_steering_controller/CHANGELOG.rst | 4 ++-- tricycle_steering_controller/package.xml | 2 +- velocity_controllers/CHANGELOG.rst | 4 ++-- velocity_controllers/package.xml | 2 +- 40 files changed, 59 insertions(+), 59 deletions(-) diff --git a/ackermann_steering_controller/CHANGELOG.rst b/ackermann_steering_controller/CHANGELOG.rst index 6375badb25..af5ef64661 100644 --- a/ackermann_steering_controller/CHANGELOG.rst +++ b/ackermann_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ackermann_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.10.1 (2023-06-06) +------------------- 3.10.0 (2023-06-04) ------------------- diff --git a/ackermann_steering_controller/package.xml b/ackermann_steering_controller/package.xml index 5bd9c96bc1..0c833147ea 100644 --- a/ackermann_steering_controller/package.xml +++ b/ackermann_steering_controller/package.xml @@ -2,7 +2,7 @@ ackermann_steering_controller - 3.10.0 + 3.10.1 Steering controller for Ackermann kinematics. Rear fixed wheels are powering the vehicle and front wheels are steering it. Apache License 2.0 Bence Magyar diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index 57e7dd84ac..82bd365880 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.10.1 (2023-06-06) +------------------- 3.10.0 (2023-06-04) ------------------- diff --git a/admittance_controller/package.xml b/admittance_controller/package.xml index 4d7530cecc..4506992846 100644 --- a/admittance_controller/package.xml +++ b/admittance_controller/package.xml @@ -2,7 +2,7 @@ admittance_controller - 3.10.0 + 3.10.1 Implementation of admittance controllers for different input and output interface. Denis Štogl Bence Magyar diff --git a/bicycle_steering_controller/CHANGELOG.rst b/bicycle_steering_controller/CHANGELOG.rst index f913267b94..6d4921dea9 100644 --- a/bicycle_steering_controller/CHANGELOG.rst +++ b/bicycle_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package bicycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.10.1 (2023-06-06) +------------------- 3.10.0 (2023-06-04) ------------------- diff --git a/bicycle_steering_controller/package.xml b/bicycle_steering_controller/package.xml index 99023fffb9..3a777bd441 100644 --- a/bicycle_steering_controller/package.xml +++ b/bicycle_steering_controller/package.xml @@ -2,7 +2,7 @@ bicycle_steering_controller - 3.10.0 + 3.10.1 Steering controller with bicycle kinematics. Rear fixed wheel is powering the vehicle and front wheel is steering. Apache License 2.0 Bence Magyar diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index d33d4c3018..2cc4720e5a 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.10.1 (2023-06-06) +------------------- 3.10.0 (2023-06-04) ------------------- diff --git a/diff_drive_controller/package.xml b/diff_drive_controller/package.xml index 0875ba94cd..669d1067b7 100644 --- a/diff_drive_controller/package.xml +++ b/diff_drive_controller/package.xml @@ -1,7 +1,7 @@ diff_drive_controller - 3.10.0 + 3.10.1 Controller for a differential drive mobile base. Bence Magyar Jordan Palacios diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index 29ff565560..b30dbb4d6e 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.10.1 (2023-06-06) +------------------- 3.10.0 (2023-06-04) ------------------- diff --git a/effort_controllers/package.xml b/effort_controllers/package.xml index 9a59fe42cd..5a9f239d58 100644 --- a/effort_controllers/package.xml +++ b/effort_controllers/package.xml @@ -1,7 +1,7 @@ effort_controllers - 3.10.0 + 3.10.1 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index f7025b8e60..8b303c862d 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.10.1 (2023-06-06) +------------------- 3.10.0 (2023-06-04) ------------------- diff --git a/force_torque_sensor_broadcaster/package.xml b/force_torque_sensor_broadcaster/package.xml index d517ed204a..955650fcf9 100644 --- a/force_torque_sensor_broadcaster/package.xml +++ b/force_torque_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ force_torque_sensor_broadcaster - 3.10.0 + 3.10.1 Controller to publish state of force-torque sensors. Bence Magyar Denis Štogl diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index 2256b00eb6..e7b0a22fcf 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.10.1 (2023-06-06) +------------------- 3.10.0 (2023-06-04) ------------------- diff --git a/forward_command_controller/package.xml b/forward_command_controller/package.xml index 5c17d80379..f7b744ef61 100644 --- a/forward_command_controller/package.xml +++ b/forward_command_controller/package.xml @@ -1,7 +1,7 @@ forward_command_controller - 3.10.0 + 3.10.1 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index 6c7bee11e0..1c2e25f72e 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.10.1 (2023-06-06) +------------------- 3.10.0 (2023-06-04) ------------------- diff --git a/gripper_controllers/package.xml b/gripper_controllers/package.xml index cc55d0be39..06fd59362f 100644 --- a/gripper_controllers/package.xml +++ b/gripper_controllers/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> gripper_controllers - 3.10.0 + 3.10.1 The gripper_controllers package Bence Magyar diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index fb8749605d..3869b5e229 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.10.1 (2023-06-06) +------------------- 3.10.0 (2023-06-04) ------------------- diff --git a/imu_sensor_broadcaster/package.xml b/imu_sensor_broadcaster/package.xml index 6a9a53d3a6..a5b4dd06bf 100644 --- a/imu_sensor_broadcaster/package.xml +++ b/imu_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ imu_sensor_broadcaster - 3.10.0 + 3.10.1 Controller to publish readings of IMU sensors. Bence Magyar Denis Štogl diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index f786d648f2..050460c0a8 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.10.1 (2023-06-06) +------------------- 3.10.0 (2023-06-04) ------------------- diff --git a/joint_state_broadcaster/package.xml b/joint_state_broadcaster/package.xml index ea7a5c9a54..1be245a957 100644 --- a/joint_state_broadcaster/package.xml +++ b/joint_state_broadcaster/package.xml @@ -1,7 +1,7 @@ joint_state_broadcaster - 3.10.0 + 3.10.1 Broadcaster to publish joint state Bence Magyar Denis Stogl diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index f538df0739..a8f89aea96 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.10.1 (2023-06-06) +------------------- 3.10.0 (2023-06-04) ------------------- diff --git a/joint_trajectory_controller/package.xml b/joint_trajectory_controller/package.xml index 9166118724..f91322b047 100644 --- a/joint_trajectory_controller/package.xml +++ b/joint_trajectory_controller/package.xml @@ -1,7 +1,7 @@ joint_trajectory_controller - 3.10.0 + 3.10.1 Controller for executing joint-space trajectories on a group of joints Bence Magyar Jordan Palacios diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index 460d1c16ce..4f064e3140 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.10.1 (2023-06-06) +------------------- 3.10.0 (2023-06-04) ------------------- diff --git a/position_controllers/package.xml b/position_controllers/package.xml index f2a968e2d9..2829642bba 100644 --- a/position_controllers/package.xml +++ b/position_controllers/package.xml @@ -1,7 +1,7 @@ position_controllers - 3.10.0 + 3.10.1 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index a702904ba9..1c600fbd73 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.10.1 (2023-06-06) +------------------- 3.10.0 (2023-06-04) ------------------- diff --git a/ros2_controllers/package.xml b/ros2_controllers/package.xml index 3a09b034e0..1b7f76ed01 100644 --- a/ros2_controllers/package.xml +++ b/ros2_controllers/package.xml @@ -1,7 +1,7 @@ ros2_controllers - 3.10.0 + 3.10.1 Metapackage for ROS2 controllers related packages Bence Magyar Jordan Palacios diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index c92759797c..0688058681 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.10.1 (2023-06-06) +------------------- 3.10.0 (2023-06-04) ------------------- diff --git a/ros2_controllers_test_nodes/package.xml b/ros2_controllers_test_nodes/package.xml index 0649b1afce..71dec82527 100644 --- a/ros2_controllers_test_nodes/package.xml +++ b/ros2_controllers_test_nodes/package.xml @@ -2,7 +2,7 @@ ros2_controllers_test_nodes - 3.10.0 + 3.10.1 Demo nodes for showing and testing functionalities of the ros2_control framework. Denis Štogl diff --git a/ros2_controllers_test_nodes/setup.py b/ros2_controllers_test_nodes/setup.py index 0b9f5078e3..96f08db712 100644 --- a/ros2_controllers_test_nodes/setup.py +++ b/ros2_controllers_test_nodes/setup.py @@ -20,7 +20,7 @@ setup( name=package_name, - version="3.10.0", + version="3.10.1", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index f9b0f43a29..2e9e8325f7 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.10.1 (2023-06-06) +------------------- 3.10.0 (2023-06-04) ------------------- diff --git a/rqt_joint_trajectory_controller/package.xml b/rqt_joint_trajectory_controller/package.xml index fd0dd6199b..4be20ed909 100644 --- a/rqt_joint_trajectory_controller/package.xml +++ b/rqt_joint_trajectory_controller/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> rqt_joint_trajectory_controller - 3.10.0 + 3.10.1 Graphical frontend for interacting with joint_trajectory_controller instances. Bence Magyar diff --git a/rqt_joint_trajectory_controller/setup.py b/rqt_joint_trajectory_controller/setup.py index 4bf28a6f1c..146c961401 100644 --- a/rqt_joint_trajectory_controller/setup.py +++ b/rqt_joint_trajectory_controller/setup.py @@ -7,7 +7,7 @@ setup( name=package_name, - version="3.10.0", + version="3.10.1", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/steering_controllers_library/CHANGELOG.rst b/steering_controllers_library/CHANGELOG.rst index b2fa703063..a773bb2bcc 100644 --- a/steering_controllers_library/CHANGELOG.rst +++ b/steering_controllers_library/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package steering_controllers_library ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.10.1 (2023-06-06) +------------------- * Second round of dependencies fix (`#655 `_) * Contributors: Bence Magyar diff --git a/steering_controllers_library/package.xml b/steering_controllers_library/package.xml index 2684a2f727..688b84167a 100644 --- a/steering_controllers_library/package.xml +++ b/steering_controllers_library/package.xml @@ -2,7 +2,7 @@ steering_controllers_library - 3.10.0 + 3.10.1 Package for steering robot configurations including odometry and interfaces. Apache License 2.0 Bence Magyar diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index e67efd3d4b..13b98ea203 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.10.1 (2023-06-06) +------------------- 3.10.0 (2023-06-04) ------------------- diff --git a/tricycle_controller/package.xml b/tricycle_controller/package.xml index 7444292e41..4098984815 100644 --- a/tricycle_controller/package.xml +++ b/tricycle_controller/package.xml @@ -2,7 +2,7 @@ tricycle_controller - 3.10.0 + 3.10.1 Controller for a tricycle drive mobile base Bence Magyar Tony Najjar diff --git a/tricycle_steering_controller/CHANGELOG.rst b/tricycle_steering_controller/CHANGELOG.rst index 95d95e9ad5..a20856bd65 100644 --- a/tricycle_steering_controller/CHANGELOG.rst +++ b/tricycle_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package tricycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.10.1 (2023-06-06) +------------------- 3.10.0 (2023-06-04) ------------------- diff --git a/tricycle_steering_controller/package.xml b/tricycle_steering_controller/package.xml index 3478ce0e96..e82ef7e202 100644 --- a/tricycle_steering_controller/package.xml +++ b/tricycle_steering_controller/package.xml @@ -2,7 +2,7 @@ tricycle_steering_controller - 3.10.0 + 3.10.1 Steering controller with tricycle kinematics. Rear fixed wheels are powering the vehicle and front wheel is steering. Apache License 2.0 Bence Magyar diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index 79d4bc0a32..0852b7e474 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.10.1 (2023-06-06) +------------------- 3.10.0 (2023-06-04) ------------------- diff --git a/velocity_controllers/package.xml b/velocity_controllers/package.xml index c1ab7d16b3..5d71730f8f 100644 --- a/velocity_controllers/package.xml +++ b/velocity_controllers/package.xml @@ -1,7 +1,7 @@ velocity_controllers - 3.10.0 + 3.10.1 Generic controller for forwarding commands. Bence Magyar Jordan Palacios From c74a3299e3d5f5bf27bddb7021007988e76ea7b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Mon, 12 Jun 2023 15:55:15 +0200 Subject: [PATCH 050/238] Let sphinx add parameter description to documentation (#651) --- ackermann_steering_controller/doc/userdoc.rst | 4 +++- bicycle_steering_controller/doc/userdoc.rst | 4 +++- doc/controllers_index.rst | 1 + forward_command_controller/doc/userdoc.rst | 15 +++++++++++++++ gripper_controllers/doc/userdoc.rst | 14 ++++++++++++++ imu_sensor_broadcaster/doc/userdoc.rst | 8 ++------ .../src/imu_sensor_broadcaster_parameters.yaml | 4 +++- steering_controllers_library/doc/userdoc.rst | 5 +++-- tricycle_steering_controller/doc/userdoc.rst | 4 +++- 9 files changed, 47 insertions(+), 12 deletions(-) create mode 100644 gripper_controllers/doc/userdoc.rst diff --git a/ackermann_steering_controller/doc/userdoc.rst b/ackermann_steering_controller/doc/userdoc.rst index c743b5d709..c4ae35e5b0 100644 --- a/ackermann_steering_controller/doc/userdoc.rst +++ b/ackermann_steering_controller/doc/userdoc.rst @@ -15,6 +15,8 @@ For more details on controller's execution and interfaces check the :ref:`Steeri Parameters ,,,,,,,,,,, -For list of parameters and their meaning YAML file in the ``src`` folder of the controller's package. +This controller uses the `generate_parameter_library `_ to handle its parameters. For an exemplary parameterization see the ``test`` folder of the controller's package. + +.. generate_parameter_library_details:: ../src/ackermann_steering_controller.yaml diff --git a/bicycle_steering_controller/doc/userdoc.rst b/bicycle_steering_controller/doc/userdoc.rst index dd6db9ceaa..a720ff887d 100644 --- a/bicycle_steering_controller/doc/userdoc.rst +++ b/bicycle_steering_controller/doc/userdoc.rst @@ -16,6 +16,8 @@ For more details on controller's execution and interfaces check the :ref:`Steeri Parameters ,,,,,,,,,,, -For list of parameters and their meaning YAML file in the ``src`` folder of the controller's package. +This controller uses the `generate_parameter_library `_ to handle its parameters. For an exemplary parameterization see the ``test`` folder of the controller's package. + +.. generate_parameter_library_details:: ../src/bicycle_steering_controller.yaml diff --git a/doc/controllers_index.rst b/doc/controllers_index.rst index 80e5e4fda2..763381c065 100644 --- a/doc/controllers_index.rst +++ b/doc/controllers_index.rst @@ -48,6 +48,7 @@ Available Controllers Differential Drive Controller <../diff_drive_controller/doc/userdoc.rst> Effort Controllers <../effort_controllers/doc/userdoc.rst> Forward Command Controller <../forward_command_controller/doc/userdoc.rst> + Gripper Controller <../gripper_controllers/doc/userdoc.rst> Joint Trajectory Controller <../joint_trajectory_controller/doc/userdoc.rst> Position Controllers <../position_controllers/doc/userdoc.rst> Steering Controllers Library <../steering_controllers_library/doc/userdoc.rst> diff --git a/forward_command_controller/doc/userdoc.rst b/forward_command_controller/doc/userdoc.rst index 2ecba6003a..ee0af57d7b 100644 --- a/forward_command_controller/doc/userdoc.rst +++ b/forward_command_controller/doc/userdoc.rst @@ -15,3 +15,18 @@ Hardware interface type ----------------------- This controller can be used for every type of command interface. + +Parameters +------------ + +This controller uses the `generate_parameter_library `_ to handle its parameters. + +forward_command_controller +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. generate_parameter_library_details:: ../src/forward_command_controller_parameters.yaml + +multi_interface_forward_command_controller +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. generate_parameter_library_details:: ../src/multi_interface_forward_command_controller_parameters.yaml diff --git a/gripper_controllers/doc/userdoc.rst b/gripper_controllers/doc/userdoc.rst new file mode 100644 index 0000000000..28262e90f9 --- /dev/null +++ b/gripper_controllers/doc/userdoc.rst @@ -0,0 +1,14 @@ +:github_url: https://github.com/ros-controls/ros2_controllers/blob/{REPOS_FILE_BRANCH}/gripper_controllers/doc/userdoc.rst + +.. _gripper_controllers_userdoc: + +Gripper Action Controller +-------------------------------- + +Controller for executing a gripper command action for simple single-dof grippers. + +Parameters +^^^^^^^^^^^ +This controller uses the `generate_parameter_library `_ to handle its parameters. + +.. generate_parameter_library_details:: ../src/gripper_action_controller_parameters.yaml diff --git a/imu_sensor_broadcaster/doc/userdoc.rst b/imu_sensor_broadcaster/doc/userdoc.rst index 24438c9959..3b8ae172db 100644 --- a/imu_sensor_broadcaster/doc/userdoc.rst +++ b/imu_sensor_broadcaster/doc/userdoc.rst @@ -11,10 +11,6 @@ The controller is a wrapper around ``IMUSensor`` semantic component (see ``contr Parameters ^^^^^^^^^^^ -frame_id (mandatory) - Frame in which the output message will be published. +This controller uses the `generate_parameter_library `_ to handle its parameters. -sensor_name (mandatory) - Defines sensor name used as prefix for its interfaces. - Interface names are: /orientation.x, ..., /angular_velocity.x, ..., - /linear_acceleration.x. +.. generate_parameter_library_details:: ../src/imu_sensor_broadcaster_parameters.yaml diff --git a/imu_sensor_broadcaster/src/imu_sensor_broadcaster_parameters.yaml b/imu_sensor_broadcaster/src/imu_sensor_broadcaster_parameters.yaml index c0daba9f11..bd63bf4aa6 100644 --- a/imu_sensor_broadcaster/src/imu_sensor_broadcaster_parameters.yaml +++ b/imu_sensor_broadcaster/src/imu_sensor_broadcaster_parameters.yaml @@ -2,7 +2,9 @@ imu_sensor_broadcaster: sensor_name: { type: string, default_value: "", - description: "Name of the sensor used as prefix for interfaces if there are no individual interface names defined.", + description: "Defines sensor name used as prefix for its interfaces. + Interface names are: ``/orientation.x, ..., /angular_velocity.x, ..., + /linear_acceleration.x.``", } frame_id: { type: string, diff --git a/steering_controllers_library/doc/userdoc.rst b/steering_controllers_library/doc/userdoc.rst index 47d9516fd1..df3d1529d0 100644 --- a/steering_controllers_library/doc/userdoc.rst +++ b/steering_controllers_library/doc/userdoc.rst @@ -86,7 +86,8 @@ Publishers Parameters ,,,,,,,,,,, - -For list of parameters and their meaning YAML file in the ``src`` folder of the controller's package. +This controller uses the `generate_parameter_library `_ to handle its parameters. For an exemplary parameterization see the ``test`` folder of the controller's package. + +.. generate_parameter_library_details:: ../src/steering_controllers_library.yaml diff --git a/tricycle_steering_controller/doc/userdoc.rst b/tricycle_steering_controller/doc/userdoc.rst index bf20dc58c2..d76f489745 100644 --- a/tricycle_steering_controller/doc/userdoc.rst +++ b/tricycle_steering_controller/doc/userdoc.rst @@ -15,6 +15,8 @@ For more details on controller's execution and interfaces check the :ref:`Steeri Parameters ,,,,,,,,,,, -For list of parameters and their meaning YAML file in the ``src`` folder of the controller's package. +This controller uses the `generate_parameter_library `_ to handle its parameters. For an exemplary parameterization see the ``test`` folder of the controller's package. + +.. generate_parameter_library_details:: ../src/tricycle_steering_controller.yaml From c02bc40787fbfb5a9e487022fa6f210cfb95a8f0 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 12 Jun 2023 17:45:56 +0100 Subject: [PATCH 051/238] Updated hyperlink of pluginlib documentation (#647) (#662) --- doc/writing_new_controller.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/writing_new_controller.rst b/doc/writing_new_controller.rst index a2e26104a7..190b76832b 100644 --- a/doc/writing_new_controller.rst +++ b/doc/writing_new_controller.rst @@ -5,7 +5,7 @@ Writing a new controller ======================== -In this framework controllers are libraries, dynamically loaded by the controller manager using the `pluginlib `_ interface. +In this framework controllers are libraries, dynamically loaded by the controller manager using the `pluginlib `_ interface. The following is a step-by-step guide to create source files, basic tests, and compile rules for a new controller. 1. **Preparing package** From 23f0defd94a5a80f07c339b0babc736d2d0dcd25 Mon Sep 17 00:00:00 2001 From: gwalck Date: Tue, 13 Jun 2023 20:46:31 +0200 Subject: [PATCH 052/238] Added -Wconversion flag and fix warnings (#667) --- ackermann_steering_controller/CMakeLists.txt | 2 +- admittance_controller/CMakeLists.txt | 2 +- bicycle_steering_controller/CMakeLists.txt | 2 +- diff_drive_controller/CMakeLists.txt | 2 +- diff_drive_controller/src/diff_drive_controller.cpp | 4 ++-- effort_controllers/CMakeLists.txt | 2 +- force_torque_sensor_broadcaster/CMakeLists.txt | 2 +- forward_command_controller/CMakeLists.txt | 2 +- .../test/test_forward_command_controller.cpp | 2 +- ...test_multi_interface_forward_command_controller.cpp | 4 ++-- gripper_controllers/CMakeLists.txt | 2 +- imu_sensor_broadcaster/CMakeLists.txt | 2 +- joint_state_broadcaster/CMakeLists.txt | 2 +- joint_trajectory_controller/CMakeLists.txt | 2 +- .../include/joint_trajectory_controller/tolerances.hpp | 2 +- .../src/joint_trajectory_controller.cpp | 2 +- position_controllers/CMakeLists.txt | 2 +- steering_controllers_library/CMakeLists.txt | 2 +- tricycle_controller/CMakeLists.txt | 2 +- tricycle_controller/src/traction_limiter.cpp | 2 +- tricycle_controller/src/tricycle_controller.cpp | 10 +++++----- tricycle_steering_controller/CMakeLists.txt | 2 +- velocity_controllers/CMakeLists.txt | 2 +- 23 files changed, 29 insertions(+), 29 deletions(-) diff --git a/ackermann_steering_controller/CMakeLists.txt b/ackermann_steering_controller/CMakeLists.txt index ff76da8853..6ad0e9485f 100644 --- a/ackermann_steering_controller/CMakeLists.txt +++ b/ackermann_steering_controller/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.16) project(ackermann_steering_controller LANGUAGES CXX) if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") - add_compile_options(-Wall -Wextra -Wpedantic) + add_compile_options(-Wall -Wextra -Wpedantic -Wconversion) endif() # find dependencies diff --git a/admittance_controller/CMakeLists.txt b/admittance_controller/CMakeLists.txt index 9ece5e7fb0..a8a8832fce 100644 --- a/admittance_controller/CMakeLists.txt +++ b/admittance_controller/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.16) project(admittance_controller LANGUAGES CXX) if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") - add_compile_options(-Wall -Wextra -Wpedantic) + add_compile_options(-Wall -Wextra -Wpedantic -Wconversion) endif() set(THIS_PACKAGE_INCLUDE_DEPENDS diff --git a/bicycle_steering_controller/CMakeLists.txt b/bicycle_steering_controller/CMakeLists.txt index 8ac12fe0a0..5d662c1fec 100644 --- a/bicycle_steering_controller/CMakeLists.txt +++ b/bicycle_steering_controller/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.16) project(bicycle_steering_controller LANGUAGES CXX) if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") - add_compile_options(-Wall -Wextra -Wpedantic) + add_compile_options(-Wall -Wextra -Wpedantic -Wconversion) endif() # find dependencies diff --git a/diff_drive_controller/CMakeLists.txt b/diff_drive_controller/CMakeLists.txt index 1077982380..b944ff1e88 100644 --- a/diff_drive_controller/CMakeLists.txt +++ b/diff_drive_controller/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.16) project(diff_drive_controller LANGUAGES CXX) if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") - add_compile_options(-Wall -Wextra) + add_compile_options(-Wall -Wextra -Wconversion) endif() set(THIS_PACKAGE_INCLUDE_DEPENDS diff --git a/diff_drive_controller/src/diff_drive_controller.cpp b/diff_drive_controller/src/diff_drive_controller.cpp index 2b3b2477b6..20736fda09 100644 --- a/diff_drive_controller/src/diff_drive_controller.cpp +++ b/diff_drive_controller/src/diff_drive_controller.cpp @@ -167,8 +167,8 @@ controller_interface::return_type DiffDriveController::update( left_feedback_mean += left_feedback; right_feedback_mean += right_feedback; } - left_feedback_mean /= params_.wheels_per_side; - right_feedback_mean /= params_.wheels_per_side; + left_feedback_mean /= static_cast(params_.wheels_per_side); + right_feedback_mean /= static_cast(params_.wheels_per_side); if (params_.position_feedback) { diff --git a/effort_controllers/CMakeLists.txt b/effort_controllers/CMakeLists.txt index 340bb19825..ad97690655 100644 --- a/effort_controllers/CMakeLists.txt +++ b/effort_controllers/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.16) project(effort_controllers LANGUAGES CXX) if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") - add_compile_options(-Wall -Wextra -Wpedantic) + add_compile_options(-Wall -Wextra -Wpedantic -Wconversion) endif() set(THIS_PACKAGE_INCLUDE_DEPENDS diff --git a/force_torque_sensor_broadcaster/CMakeLists.txt b/force_torque_sensor_broadcaster/CMakeLists.txt index 207e978c10..eaa5cabac6 100644 --- a/force_torque_sensor_broadcaster/CMakeLists.txt +++ b/force_torque_sensor_broadcaster/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.16) project(force_torque_sensor_broadcaster LANGUAGES CXX) if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") - add_compile_options(-Wall -Wextra -Wpedantic) + add_compile_options(-Wall -Wextra -Wpedantic -Wconversion) endif() set(THIS_PACKAGE_INCLUDE_DEPENDS diff --git a/forward_command_controller/CMakeLists.txt b/forward_command_controller/CMakeLists.txt index 46189fe5ac..15ffe09750 100644 --- a/forward_command_controller/CMakeLists.txt +++ b/forward_command_controller/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.16) project(forward_command_controller LANGUAGES CXX) if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") - add_compile_options(-Wall -Wextra -Wpedantic) + add_compile_options(-Wall -Wextra -Wpedantic -Wconversion) endif() set(THIS_PACKAGE_INCLUDE_DEPENDS diff --git a/forward_command_controller/test/test_forward_command_controller.cpp b/forward_command_controller/test/test_forward_command_controller.cpp index 697e42d671..b39294f36c 100644 --- a/forward_command_controller/test/test_forward_command_controller.cpp +++ b/forward_command_controller/test/test_forward_command_controller.cpp @@ -206,7 +206,7 @@ TEST_F(ForwardCommandControllerTest, CommandSuccessTest) // update successful, command received ASSERT_EQ( - controller_->update(rclcpp::Time(0.1), rclcpp::Duration::from_seconds(0.01)), + controller_->update(rclcpp::Time(100000000), rclcpp::Duration::from_seconds(0.01)), controller_interface::return_type::OK); // check joint commands have been modified diff --git a/forward_command_controller/test/test_multi_interface_forward_command_controller.cpp b/forward_command_controller/test/test_multi_interface_forward_command_controller.cpp index 0cada04859..c629b36ba8 100644 --- a/forward_command_controller/test/test_multi_interface_forward_command_controller.cpp +++ b/forward_command_controller/test/test_multi_interface_forward_command_controller.cpp @@ -205,7 +205,7 @@ TEST_F(MultiInterfaceForwardCommandControllerTest, CommandSuccessTest) // update successful, command received ASSERT_EQ( - controller_->update(rclcpp::Time(0.1), rclcpp::Duration::from_seconds(0.01)), + controller_->update(rclcpp::Time(100000000), rclcpp::Duration::from_seconds(0.01)), controller_interface::return_type::OK); // check command in handle was set @@ -289,7 +289,7 @@ TEST_F(MultiInterfaceForwardCommandControllerTest, ActivateDeactivateCommandsRes // update successful, command received ASSERT_EQ( - controller_->update(rclcpp::Time(0.1), rclcpp::Duration::from_seconds(0.01)), + controller_->update(rclcpp::Time(100000000), rclcpp::Duration::from_seconds(0.01)), controller_interface::return_type::OK); // check command in handle was set diff --git a/gripper_controllers/CMakeLists.txt b/gripper_controllers/CMakeLists.txt index e8fd1e5d7e..8edaaf6386 100644 --- a/gripper_controllers/CMakeLists.txt +++ b/gripper_controllers/CMakeLists.txt @@ -7,7 +7,7 @@ if(APPLE OR WIN32) endif() if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") - add_compile_options(-Wall -Wextra) + add_compile_options(-Wall -Wextra -Wconversion) endif() set(THIS_PACKAGE_INCLUDE_DEPENDS diff --git a/imu_sensor_broadcaster/CMakeLists.txt b/imu_sensor_broadcaster/CMakeLists.txt index 18d883503b..991a463284 100644 --- a/imu_sensor_broadcaster/CMakeLists.txt +++ b/imu_sensor_broadcaster/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.16) project(imu_sensor_broadcaster LANGUAGES CXX) if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") - add_compile_options(-Wall -Wextra -Wpedantic) + add_compile_options(-Wall -Wextra -Wpedantic -Wconversion) endif() set(THIS_PACKAGE_INCLUDE_DEPENDS diff --git a/joint_state_broadcaster/CMakeLists.txt b/joint_state_broadcaster/CMakeLists.txt index 018adef23a..cadc96b4e3 100644 --- a/joint_state_broadcaster/CMakeLists.txt +++ b/joint_state_broadcaster/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.16) project(joint_state_broadcaster LANGUAGES CXX) if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") - add_compile_options(-Wall -Wextra) + add_compile_options(-Wall -Wextra -Wconversion) endif() set(THIS_PACKAGE_INCLUDE_DEPENDS diff --git a/joint_trajectory_controller/CMakeLists.txt b/joint_trajectory_controller/CMakeLists.txt index 615acf0dd7..35223016b7 100644 --- a/joint_trajectory_controller/CMakeLists.txt +++ b/joint_trajectory_controller/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.16) project(joint_trajectory_controller LANGUAGES CXX) if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") - add_compile_options(-Wall -Wextra) + add_compile_options(-Wall -Wextra -Wconversion) endif() set(THIS_PACKAGE_INCLUDE_DEPENDS diff --git a/joint_trajectory_controller/include/joint_trajectory_controller/tolerances.hpp b/joint_trajectory_controller/include/joint_trajectory_controller/tolerances.hpp index e540b06e51..b4cb029dd9 100644 --- a/joint_trajectory_controller/include/joint_trajectory_controller/tolerances.hpp +++ b/joint_trajectory_controller/include/joint_trajectory_controller/tolerances.hpp @@ -127,7 +127,7 @@ SegmentTolerances get_segment_tolerances(Params const & params) * REALTIME if true \return True if \p state_error fulfills \p state_tolerance. */ inline bool check_state_tolerance_per_joint( - const trajectory_msgs::msg::JointTrajectoryPoint & state_error, int joint_idx, + const trajectory_msgs::msg::JointTrajectoryPoint & state_error, size_t joint_idx, const StateTolerances & state_tolerance, bool show_errors = false) { using std::abs; diff --git a/joint_trajectory_controller/src/joint_trajectory_controller.cpp b/joint_trajectory_controller/src/joint_trajectory_controller.cpp index 71ed051f66..6941527649 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller.cpp +++ b/joint_trajectory_controller/src/joint_trajectory_controller.cpp @@ -117,7 +117,7 @@ controller_interface::return_type JointTrajectoryController::update( } auto compute_error_for_joint = [&]( - JointTrajectoryPoint & error, int index, + JointTrajectoryPoint & error, size_t index, const JointTrajectoryPoint & current, const JointTrajectoryPoint & desired) { diff --git a/position_controllers/CMakeLists.txt b/position_controllers/CMakeLists.txt index 05714a6e46..54a4f94656 100644 --- a/position_controllers/CMakeLists.txt +++ b/position_controllers/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.16) project(position_controllers LANGUAGES CXX) if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") - add_compile_options(-Wall -Wextra -Wpedantic) + add_compile_options(-Wall -Wextra -Wpedantic -Wconversion) endif() set(THIS_PACKAGE_INCLUDE_DEPENDS diff --git a/steering_controllers_library/CMakeLists.txt b/steering_controllers_library/CMakeLists.txt index 4a98dbf320..b64ea204a8 100644 --- a/steering_controllers_library/CMakeLists.txt +++ b/steering_controllers_library/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.16) project(steering_controllers_library LANGUAGES CXX) if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") - add_compile_options(-Wall -Wextra -Wpedantic) + add_compile_options(-Wall -Wextra -Wpedantic -Wconversion) endif() # find dependencies diff --git a/tricycle_controller/CMakeLists.txt b/tricycle_controller/CMakeLists.txt index ea2232f88f..291f08ad9f 100644 --- a/tricycle_controller/CMakeLists.txt +++ b/tricycle_controller/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.16) project(tricycle_controller LANGUAGES CXX) if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") - add_compile_options(-Wall -Wextra -Wpedantic) + add_compile_options(-Wall -Wextra -Wpedantic -Wconversion) endif() set(THIS_PACKAGE_INCLUDE_DEPENDS diff --git a/tricycle_controller/src/traction_limiter.cpp b/tricycle_controller/src/traction_limiter.cpp index b9759e3624..a8019714e1 100644 --- a/tricycle_controller/src/traction_limiter.cpp +++ b/tricycle_controller/src/traction_limiter.cpp @@ -102,7 +102,7 @@ double TractionLimiter::limit_acceleration(double & v, double v0, double dt) double dv_min; double dv_max; - if (abs(v) >= abs(v0)) + if (std::fabs(v) >= std::fabs(v0)) { dv_min = min_acceleration_ * dt; dv_max = max_acceleration_ * dt; diff --git a/tricycle_controller/src/tricycle_controller.cpp b/tricycle_controller/src/tricycle_controller.cpp index 4f4e22ec9d..d6aeec0af1 100644 --- a/tricycle_controller/src/tricycle_controller.cpp +++ b/tricycle_controller/src/tricycle_controller.cpp @@ -67,7 +67,7 @@ CallbackReturn TricycleController::on_init() auto_declare("enable_odom_tf", odom_params_.enable_odom_tf); auto_declare("odom_only_twist", odom_params_.odom_only_twist); - auto_declare("cmd_vel_timeout", cmd_vel_timeout_.count()); + auto_declare("cmd_vel_timeout", static_cast(cmd_vel_timeout_.count())); auto_declare("publish_ackermann_command", publish_ackermann_command_); auto_declare("velocity_rolling_window_size", 10); auto_declare("use_stamped_vel", use_stamped_vel_); @@ -234,8 +234,8 @@ controller_interface::return_type TricycleController::update( AckermannDrive ackermann_command; // speed in AckermannDrive is defined as desired forward speed (m/s) but it is used here as wheel // speed (rad/s) - ackermann_command.speed = Ws_write; - ackermann_command.steering_angle = alpha_write; + ackermann_command.speed = static_cast(Ws_write); + ackermann_command.steering_angle = static_cast(alpha_write); previous_commands_.emplace(ackermann_command); // Publish ackermann command @@ -244,8 +244,8 @@ controller_interface::return_type TricycleController::update( auto & realtime_ackermann_command = realtime_ackermann_command_publisher_->msg_; // speed in AckermannDrive is defined desired forward speed (m/s) but we use it here as wheel // speed (rad/s) - realtime_ackermann_command.speed = Ws_write; - realtime_ackermann_command.steering_angle = alpha_write; + realtime_ackermann_command.speed = static_cast(Ws_write); + realtime_ackermann_command.steering_angle = static_cast(alpha_write); realtime_ackermann_command_publisher_->unlockAndPublish(); } diff --git a/tricycle_steering_controller/CMakeLists.txt b/tricycle_steering_controller/CMakeLists.txt index c604b89452..4c56d68185 100644 --- a/tricycle_steering_controller/CMakeLists.txt +++ b/tricycle_steering_controller/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.16) project(tricycle_steering_controller LANGUAGES CXX) if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") - add_compile_options(-Wall -Wextra -Wpedantic) + add_compile_options(-Wall -Wextra -Wpedantic -Wconversion) endif() # find dependencies diff --git a/velocity_controllers/CMakeLists.txt b/velocity_controllers/CMakeLists.txt index 27ec8417bb..3642ae1cb9 100644 --- a/velocity_controllers/CMakeLists.txt +++ b/velocity_controllers/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.16) project(velocity_controllers LANGUAGES CXX) if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") - add_compile_options(-Wall -Wextra -Wpedantic) + add_compile_options(-Wall -Wextra -Wpedantic -Wconversion) endif() set(THIS_PACKAGE_INCLUDE_DEPENDS From 2f6176f71feead172bf1f22e603d78b184bb20d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Tue, 13 Jun 2023 20:49:49 +0200 Subject: [PATCH 053/238] Use link pointing to docs.ros.org (#666) --- doc/writing_new_controller.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/writing_new_controller.rst b/doc/writing_new_controller.rst index 190b76832b..65ffc6795b 100644 --- a/doc/writing_new_controller.rst +++ b/doc/writing_new_controller.rst @@ -5,7 +5,7 @@ Writing a new controller ======================== -In this framework controllers are libraries, dynamically loaded by the controller manager using the `pluginlib `_ interface. +In this framework controllers are libraries, dynamically loaded by the controller manager using the `pluginlib `_ interface. The following is a step-by-step guide to create source files, basic tests, and compile rules for a new controller. 1. **Preparing package** From f059022622e12115d006e0677ca2e312eed78858 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Wed, 14 Jun 2023 13:45:10 +0200 Subject: [PATCH 054/238] Broadcaster parameters (#650) --- .../CMakeLists.txt | 11 +++-- .../src/force_torque_sensor_broadcaster.cpp | 6 --- ..._torque_sensor_broadcaster_parameters.yaml | 3 ++ ...orce_torque_sensor_broadcaster_params.yaml | 4 ++ .../test_force_torque_sensor_broadcaster.cpp | 36 +++++----------- ...t_load_force_torque_sensor_broadcaster.cpp | 9 +++- imu_sensor_broadcaster/CMakeLists.txt | 11 +++-- .../src/imu_sensor_broadcaster.cpp | 11 ----- .../imu_sensor_broadcaster_parameters.yaml | 6 +++ .../test/imu_sensor_broadcaster_params.yaml | 5 +++ .../test/test_imu_sensor_broadcaster.cpp | 43 +++++-------------- .../test/test_load_imu_sensor_broadcaster.cpp | 9 +++- 12 files changed, 68 insertions(+), 86 deletions(-) create mode 100644 force_torque_sensor_broadcaster/test/force_torque_sensor_broadcaster_params.yaml create mode 100644 imu_sensor_broadcaster/test/imu_sensor_broadcaster_params.yaml diff --git a/force_torque_sensor_broadcaster/CMakeLists.txt b/force_torque_sensor_broadcaster/CMakeLists.txt index eaa5cabac6..2af5500e21 100644 --- a/force_torque_sensor_broadcaster/CMakeLists.txt +++ b/force_torque_sensor_broadcaster/CMakeLists.txt @@ -49,11 +49,13 @@ pluginlib_export_plugin_description_file( if(BUILD_TESTING) find_package(ament_cmake_gmock REQUIRED) find_package(controller_manager REQUIRED) + find_package(hardware_interface REQUIRED) find_package(ros2_control_test_assets REQUIRED) - ament_add_gmock(test_load_force_torque_sensor_broadcaster + add_rostest_with_parameters_gmock(test_load_force_torque_sensor_broadcaster test/test_load_force_torque_sensor_broadcaster.cpp - ) + ${CMAKE_CURRENT_SOURCE_DIR}/test/force_torque_sensor_broadcaster_params.yaml) + target_include_directories(test_load_force_torque_sensor_broadcaster PRIVATE include) target_link_libraries(test_load_force_torque_sensor_broadcaster force_torque_sensor_broadcaster ) @@ -63,9 +65,10 @@ if(BUILD_TESTING) ros2_control_test_assets ) - ament_add_gmock(test_force_torque_sensor_broadcaster + add_rostest_with_parameters_gmock(test_force_torque_sensor_broadcaster test/test_force_torque_sensor_broadcaster.cpp - ) + ${CMAKE_CURRENT_SOURCE_DIR}/test/force_torque_sensor_broadcaster_params.yaml) + target_include_directories(test_force_torque_sensor_broadcaster PRIVATE include) target_link_libraries(test_force_torque_sensor_broadcaster force_torque_sensor_broadcaster ) diff --git a/force_torque_sensor_broadcaster/src/force_torque_sensor_broadcaster.cpp b/force_torque_sensor_broadcaster/src/force_torque_sensor_broadcaster.cpp index 9687f9dfee..9b570d353f 100644 --- a/force_torque_sensor_broadcaster/src/force_torque_sensor_broadcaster.cpp +++ b/force_torque_sensor_broadcaster/src/force_torque_sensor_broadcaster.cpp @@ -72,12 +72,6 @@ controller_interface::CallbackReturn ForceTorqueSensorBroadcaster::on_configure( return controller_interface::CallbackReturn::ERROR; } - if (params_.frame_id.empty()) - { - RCLCPP_ERROR(get_node()->get_logger(), "'frame_id' parameter has to be provided."); - return controller_interface::CallbackReturn::ERROR; - } - if (!params_.sensor_name.empty()) { force_torque_sensor_ = std::make_unique( diff --git a/force_torque_sensor_broadcaster/src/force_torque_sensor_broadcaster_parameters.yaml b/force_torque_sensor_broadcaster/src/force_torque_sensor_broadcaster_parameters.yaml index 059d5ab9a1..68a85d9d8e 100644 --- a/force_torque_sensor_broadcaster/src/force_torque_sensor_broadcaster_parameters.yaml +++ b/force_torque_sensor_broadcaster/src/force_torque_sensor_broadcaster_parameters.yaml @@ -3,6 +3,9 @@ force_torque_sensor_broadcaster: type: string, default_value: "", description: "Sensor's frame_id in which values are published.", + validation: { + not_empty<>: null + } } sensor_name: { type: string, diff --git a/force_torque_sensor_broadcaster/test/force_torque_sensor_broadcaster_params.yaml b/force_torque_sensor_broadcaster/test/force_torque_sensor_broadcaster_params.yaml new file mode 100644 index 0000000000..58cc1c6b16 --- /dev/null +++ b/force_torque_sensor_broadcaster/test/force_torque_sensor_broadcaster_params.yaml @@ -0,0 +1,4 @@ +test_force_torque_sensor_broadcaster: + ros__parameters: + + frame_id: "fts_sensor_frame" diff --git a/force_torque_sensor_broadcaster/test/test_force_torque_sensor_broadcaster.cpp b/force_torque_sensor_broadcaster/test/test_force_torque_sensor_broadcaster.cpp index 74e2b15da0..b88266712b 100644 --- a/force_torque_sensor_broadcaster/test/test_force_torque_sensor_broadcaster.cpp +++ b/force_torque_sensor_broadcaster/test/test_force_torque_sensor_broadcaster.cpp @@ -39,9 +39,9 @@ constexpr auto NODE_SUCCESS = controller_interface::CallbackReturn::SUCCESS; constexpr auto NODE_ERROR = controller_interface::CallbackReturn::ERROR; } // namespace -void ForceTorqueSensorBroadcasterTest::SetUpTestCase() { rclcpp::init(0, nullptr); } +void ForceTorqueSensorBroadcasterTest::SetUpTestCase() {} -void ForceTorqueSensorBroadcasterTest::TearDownTestCase() { rclcpp::shutdown(); } +void ForceTorqueSensorBroadcasterTest::TearDownTestCase() {} void ForceTorqueSensorBroadcasterTest::SetUp() { @@ -106,29 +106,6 @@ TEST_F(ForceTorqueSensorBroadcasterTest, SensorName_InterfaceNames_NotSet) ASSERT_EQ(fts_broadcaster_->on_configure(rclcpp_lifecycle::State()), NODE_ERROR); } -TEST_F(ForceTorqueSensorBroadcasterTest, SensorName_FrameId_NotSet) -{ - SetUpFTSBroadcaster(); - - // set the 'interface_names' - fts_broadcaster_->get_node()->set_parameter({"interface_names.force.x", "fts_sensor/force.x"}); - fts_broadcaster_->get_node()->set_parameter({"interface_names.torque.z", "fts_sensor/torque.z"}); - - // configure failed, 'frame_id' parameter not set - ASSERT_EQ(fts_broadcaster_->on_configure(rclcpp_lifecycle::State()), NODE_ERROR); -} - -TEST_F(ForceTorqueSensorBroadcasterTest, InterfaceNames_FrameId_NotSet) -{ - SetUpFTSBroadcaster(); - - // set the 'sensor_name' - fts_broadcaster_->get_node()->set_parameter({"sensor_name", sensor_name_}); - - // configure failed, 'frame_id' parameter not set - ASSERT_EQ(fts_broadcaster_->on_configure(rclcpp_lifecycle::State()), NODE_ERROR); -} - TEST_F(ForceTorqueSensorBroadcasterTest, SensorName_InterfaceNames_Set) { SetUpFTSBroadcaster(); @@ -315,3 +292,12 @@ TEST_F(ForceTorqueSensorBroadcasterTest, All_InterfaceNames_Publish_Success) ASSERT_EQ(wrench_msg.wrench.torque.y, sensor_values_[4]); ASSERT_EQ(wrench_msg.wrench.torque.z, sensor_values_[5]); } + +int main(int argc, char ** argv) +{ + ::testing::InitGoogleMock(&argc, argv); + rclcpp::init(argc, argv); + int result = RUN_ALL_TESTS(); + rclcpp::shutdown(); + return result; +} diff --git a/force_torque_sensor_broadcaster/test/test_load_force_torque_sensor_broadcaster.cpp b/force_torque_sensor_broadcaster/test/test_load_force_torque_sensor_broadcaster.cpp index a9ca5e88fc..0c269d6a31 100644 --- a/force_torque_sensor_broadcaster/test/test_load_force_torque_sensor_broadcaster.cpp +++ b/force_torque_sensor_broadcaster/test/test_load_force_torque_sensor_broadcaster.cpp @@ -28,8 +28,6 @@ TEST(TestLoadForceTorqueSensorBroadcaster, load_controller) { - rclcpp::init(0, nullptr); - std::shared_ptr executor = std::make_shared(); @@ -43,6 +41,13 @@ TEST(TestLoadForceTorqueSensorBroadcaster, load_controller) "test_force_torque_sensor_broadcaster", "force_torque_sensor_broadcaster/ForceTorqueSensorBroadcaster"), nullptr); +} +int main(int argc, char ** argv) +{ + ::testing::InitGoogleMock(&argc, argv); + rclcpp::init(argc, argv); + int result = RUN_ALL_TESTS(); rclcpp::shutdown(); + return result; } diff --git a/imu_sensor_broadcaster/CMakeLists.txt b/imu_sensor_broadcaster/CMakeLists.txt index 991a463284..3b09d9e72e 100644 --- a/imu_sensor_broadcaster/CMakeLists.txt +++ b/imu_sensor_broadcaster/CMakeLists.txt @@ -49,11 +49,13 @@ pluginlib_export_plugin_description_file( if(BUILD_TESTING) find_package(ament_cmake_gmock REQUIRED) find_package(controller_manager REQUIRED) + find_package(hardware_interface REQUIRED) find_package(ros2_control_test_assets REQUIRED) - ament_add_gmock(test_load_imu_sensor_broadcaster + add_rostest_with_parameters_gmock(test_load_imu_sensor_broadcaster test/test_load_imu_sensor_broadcaster.cpp - ) + ${CMAKE_CURRENT_SOURCE_DIR}/test/imu_sensor_broadcaster_params.yaml) + target_include_directories(test_load_imu_sensor_broadcaster PRIVATE include) target_link_libraries(test_load_imu_sensor_broadcaster imu_sensor_broadcaster ) @@ -63,9 +65,10 @@ if(BUILD_TESTING) ros2_control_test_assets ) - ament_add_gmock(test_imu_sensor_broadcaster + add_rostest_with_parameters_gmock(test_imu_sensor_broadcaster test/test_imu_sensor_broadcaster.cpp - ) + ${CMAKE_CURRENT_SOURCE_DIR}/test/imu_sensor_broadcaster_params.yaml) + target_include_directories(test_imu_sensor_broadcaster PRIVATE include) target_link_libraries(test_imu_sensor_broadcaster imu_sensor_broadcaster ) diff --git a/imu_sensor_broadcaster/src/imu_sensor_broadcaster.cpp b/imu_sensor_broadcaster/src/imu_sensor_broadcaster.cpp index 3e2d574f0f..04a28e5368 100644 --- a/imu_sensor_broadcaster/src/imu_sensor_broadcaster.cpp +++ b/imu_sensor_broadcaster/src/imu_sensor_broadcaster.cpp @@ -44,17 +44,6 @@ controller_interface::CallbackReturn IMUSensorBroadcaster::on_configure( const rclcpp_lifecycle::State & /*previous_state*/) { params_ = param_listener_->get_params(); - if (params_.sensor_name.empty()) - { - RCLCPP_ERROR(get_node()->get_logger(), "'sensor_name' parameter has to be specified."); - return CallbackReturn::ERROR; - } - - if (params_.frame_id.empty()) - { - RCLCPP_ERROR(get_node()->get_logger(), "'frame_id' parameter has to be provided."); - return CallbackReturn::ERROR; - } imu_sensor_ = std::make_unique( semantic_components::IMUSensor(params_.sensor_name)); diff --git a/imu_sensor_broadcaster/src/imu_sensor_broadcaster_parameters.yaml b/imu_sensor_broadcaster/src/imu_sensor_broadcaster_parameters.yaml index bd63bf4aa6..d45bf8583b 100644 --- a/imu_sensor_broadcaster/src/imu_sensor_broadcaster_parameters.yaml +++ b/imu_sensor_broadcaster/src/imu_sensor_broadcaster_parameters.yaml @@ -5,11 +5,17 @@ imu_sensor_broadcaster: description: "Defines sensor name used as prefix for its interfaces. Interface names are: ``/orientation.x, ..., /angular_velocity.x, ..., /linear_acceleration.x.``", + validation: { + not_empty<>: null + } } frame_id: { type: string, default_value: "", description: "Sensor's frame_id in which values are published.", + validation: { + not_empty<>: null + } } static_covariance_orientation: { type: double_array, diff --git a/imu_sensor_broadcaster/test/imu_sensor_broadcaster_params.yaml b/imu_sensor_broadcaster/test/imu_sensor_broadcaster_params.yaml new file mode 100644 index 0000000000..c1c660d2c4 --- /dev/null +++ b/imu_sensor_broadcaster/test/imu_sensor_broadcaster_params.yaml @@ -0,0 +1,5 @@ +test_imu_sensor_broadcaster: + ros__parameters: + + sensor_name: "imu_sensor" + frame_id: "imu_sensor_frame" diff --git a/imu_sensor_broadcaster/test/test_imu_sensor_broadcaster.cpp b/imu_sensor_broadcaster/test/test_imu_sensor_broadcaster.cpp index 31c8d9e2f0..8358088b1d 100644 --- a/imu_sensor_broadcaster/test/test_imu_sensor_broadcaster.cpp +++ b/imu_sensor_broadcaster/test/test_imu_sensor_broadcaster.cpp @@ -40,9 +40,9 @@ constexpr auto NODE_ERROR = controller_interface::CallbackReturn::ERROR; } // namespace -void IMUSensorBroadcasterTest::SetUpTestCase() { rclcpp::init(0, nullptr); } +void IMUSensorBroadcasterTest::SetUpTestCase() {} -void IMUSensorBroadcasterTest::TearDownTestCase() { rclcpp::shutdown(); } +void IMUSensorBroadcasterTest::TearDownTestCase() {} void IMUSensorBroadcasterTest::SetUp() { @@ -102,36 +102,6 @@ void IMUSensorBroadcasterTest::subscribe_and_get_message(sensor_msgs::msg::Imu & ASSERT_TRUE(subscription->take(imu_msg, msg_info)); } -TEST_F(IMUSensorBroadcasterTest, SensorName_FrameId_NotSet) -{ - SetUpIMUBroadcaster(); - - // configure failed - ASSERT_EQ(imu_broadcaster_->on_configure(rclcpp_lifecycle::State()), NODE_ERROR); -} - -TEST_F(IMUSensorBroadcasterTest, SensorName_NotSet) -{ - SetUpIMUBroadcaster(); - - // set the 'frame_id' - imu_broadcaster_->get_node()->set_parameter({"frame_id", frame_id_}); - - // configure failed, 'sensor_name' parameter not set - ASSERT_EQ(imu_broadcaster_->on_configure(rclcpp_lifecycle::State()), NODE_ERROR); -} - -TEST_F(IMUSensorBroadcasterTest, FrameId_NotSet) -{ - SetUpIMUBroadcaster(); - - // set the 'sensor_name' - imu_broadcaster_->get_node()->set_parameter({"sensor_name", sensor_name_}); - - // configure failed, 'frame_id' parameter not set - ASSERT_EQ(imu_broadcaster_->on_configure(rclcpp_lifecycle::State()), NODE_ERROR); -} - TEST_F(IMUSensorBroadcasterTest, SensorName_Configure_Success) { SetUpIMUBroadcaster(); @@ -208,3 +178,12 @@ TEST_F(IMUSensorBroadcasterTest, SensorName_Publish_Success) EXPECT_EQ(imu_msg.linear_acceleration_covariance[i], 0.0); } } + +int main(int argc, char ** argv) +{ + ::testing::InitGoogleMock(&argc, argv); + rclcpp::init(argc, argv); + int result = RUN_ALL_TESTS(); + rclcpp::shutdown(); + return result; +} diff --git a/imu_sensor_broadcaster/test/test_load_imu_sensor_broadcaster.cpp b/imu_sensor_broadcaster/test/test_load_imu_sensor_broadcaster.cpp index e7cfd1bcf7..f4e6105ed6 100644 --- a/imu_sensor_broadcaster/test/test_load_imu_sensor_broadcaster.cpp +++ b/imu_sensor_broadcaster/test/test_load_imu_sensor_broadcaster.cpp @@ -28,8 +28,6 @@ TEST(TestLoadIMUSensorBroadcaster, load_controller) { - rclcpp::init(0, nullptr); - std::shared_ptr executor = std::make_shared(); @@ -42,6 +40,13 @@ TEST(TestLoadIMUSensorBroadcaster, load_controller) cm.load_controller( "test_imu_sensor_broadcaster", "imu_sensor_broadcaster/IMUSensorBroadcaster"), nullptr); +} +int main(int argc, char ** argv) +{ + ::testing::InitGoogleMock(&argc, argv); + rclcpp::init(argc, argv); + int result = RUN_ALL_TESTS(); rclcpp::shutdown(); + return result; } From 6c979091a7e6477963226765a23ecadd33a70d3a Mon Sep 17 00:00:00 2001 From: "G.A. vd. Hoorn" Date: Fri, 16 Jun 2023 23:54:16 +0200 Subject: [PATCH 055/238] jtc: fix minor typo in traj validation error msg (#674) --- joint_trajectory_controller/src/joint_trajectory_controller.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/joint_trajectory_controller/src/joint_trajectory_controller.cpp b/joint_trajectory_controller/src/joint_trajectory_controller.cpp index 6941527649..4d994e26bf 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller.cpp +++ b/joint_trajectory_controller/src/joint_trajectory_controller.cpp @@ -1299,7 +1299,7 @@ bool JointTrajectoryController::validate_trajectory_msg( { RCLCPP_ERROR( get_node()->get_logger(), - "Received trajectory with non zero time start time (%f) that ends on the past (%f)", + "Received trajectory with non-zero start time (%f) that ends in the past (%f)", trajectory_start_time.seconds(), trajectory_end_time.seconds()); return false; } From 21e3f2268da78f6157deec88107e394845942049 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Tue, 20 Jun 2023 22:39:15 +0200 Subject: [PATCH 056/238] Removes deprecated if-branch (#653) --- .../publisher_joint_trajectory_controller.py | 114 +++++++----------- 1 file changed, 45 insertions(+), 69 deletions(-) diff --git a/ros2_controllers_test_nodes/ros2_controllers_test_nodes/publisher_joint_trajectory_controller.py b/ros2_controllers_test_nodes/ros2_controllers_test_nodes/publisher_joint_trajectory_controller.py index 56b56c5998..4ed198515e 100644 --- a/ros2_controllers_test_nodes/ros2_controllers_test_nodes/publisher_joint_trajectory_controller.py +++ b/ros2_controllers_test_nodes/ros2_controllers_test_nodes/publisher_joint_trajectory_controller.py @@ -68,83 +68,59 @@ def __init__(self): self.goals = [] # List of JointTrajectoryPoint for name in goal_names: self.declare_parameter(name, descriptor=ParameterDescriptor(dynamic_typing=True)) - goal = self.get_parameter(name).value - # TODO(anyone): remove this "if" part in ROS Iron - if isinstance(goal, list): - self.get_logger().warn( - f'Goal "{name}" is defined as a list. This is deprecated. ' - "Use the following structure:\n:\n " - "positions: [joint1, joint2, joint3, ...]\n " - "velocities: [v_joint1, v_joint2, ...]\n " - "accelerations: [a_joint1, a_joint2, ...]\n " - "effort: [eff_joint1, eff_joint2, ...]" - ) + point = JointTrajectoryPoint() - if goal is None or len(goal) == 0: - raise Exception(f'Values for goal "{name}" not set!') + def get_sub_param(sub_param): + param_name = name + "." + sub_param + self.declare_parameter(param_name, [float()]) + param_value = self.get_parameter(param_name).value - float_goal = [float(value) for value in goal] + float_values = [] - point = JointTrajectoryPoint() - point.positions = float_goal - point.time_from_start = Duration(sec=4) + if len(param_value) != len(self.joints): + return [False, float_values] + + float_values = [float(value) for value in param_value] + + return [True, float_values] + + one_ok = False + + [ok, values] = get_sub_param("positions") + if ok: + point.positions = values + one_ok = True + [ok, values] = get_sub_param("velocities") + if ok: + point.velocities = values + one_ok = True + + [ok, values] = get_sub_param("accelerations") + if ok: + point.accelerations = values + one_ok = True + + [ok, values] = get_sub_param("effort") + if ok: + point.effort = values + one_ok = True + + if one_ok: + point.time_from_start = Duration(sec=4) self.goals.append(point) + self.get_logger().info(f'Goal "{name}" has definition {point}') else: - point = JointTrajectoryPoint() - - def get_sub_param(sub_param): - param_name = name + "." + sub_param - self.declare_parameter(param_name, [float()]) - param_value = self.get_parameter(param_name).value - - float_values = [] - - if len(param_value) != len(self.joints): - return [False, float_values] - - float_values = [float(value) for value in param_value] - - return [True, float_values] - - one_ok = False - - [ok, values] = get_sub_param("positions") - if ok: - point.positions = values - one_ok = True - - [ok, values] = get_sub_param("velocities") - if ok: - point.velocities = values - one_ok = True - - [ok, values] = get_sub_param("accelerations") - if ok: - point.accelerations = values - one_ok = True - - [ok, values] = get_sub_param("effort") - if ok: - point.effort = values - one_ok = True - - if one_ok: - point.time_from_start = Duration(sec=4) - self.goals.append(point) - self.get_logger().info(f'Goal "{name}" has definition {point}') - - else: - self.get_logger().warn( - f'Goal "{name}" definition is wrong. This goal will not be used. ' - "Use the following structure: \n:\n " - "positions: [joint1, joint2, joint3, ...]\n " - "velocities: [v_joint1, v_joint2, ...]\n " - "accelerations: [a_joint1, a_joint2, ...]\n " - "effort: [eff_joint1, eff_joint2, ...]" - ) + self.get_logger().warn( + f'Goal "{name}" definition is wrong. This goal will not be used. ' + "Use the following structure: \n:\n " + "positions: [joint1, joint2, joint3, ...]\n " + "velocities: [v_joint1, v_joint2, ...]\n " + "accelerations: [a_joint1, a_joint2, ...]\n " + "effort: [eff_joint1, eff_joint2, ...]" + ) if len(self.goals) < 1: self.get_logger().error("No valid goal found. Exiting...") From c619aac5f67cd323129eec6889d814ab1c160c87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Thu, 22 Jun 2023 15:19:45 +0200 Subject: [PATCH 057/238] Fix cpplint (#681) --- admittance_controller/test/test_admittance_controller.hpp | 2 +- ..._description.hpp => test_asset_6d_robot_description.hpp} | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) rename admittance_controller/test/{6d_robot_description.hpp => test_asset_6d_robot_description.hpp} (98%) diff --git a/admittance_controller/test/test_admittance_controller.hpp b/admittance_controller/test/test_admittance_controller.hpp index 7dca2e2010..d6c95d2e1c 100644 --- a/admittance_controller/test/test_admittance_controller.hpp +++ b/admittance_controller/test/test_admittance_controller.hpp @@ -27,7 +27,6 @@ #include "gmock/gmock.h" -#include "6d_robot_description.hpp" #include "admittance_controller/admittance_controller.hpp" #include "control_msgs/msg/admittance_controller_state.hpp" #include "geometry_msgs/msg/transform_stamped.hpp" @@ -38,6 +37,7 @@ #include "rclcpp/utilities.hpp" #include "rclcpp_lifecycle/node_interfaces/lifecycle_node_interface.hpp" #include "semantic_components/force_torque_sensor.hpp" +#include "test_asset_6d_robot_description.hpp" #include "tf2_ros/transform_broadcaster.h" #include "trajectory_msgs/msg/joint_trajectory.hpp" diff --git a/admittance_controller/test/6d_robot_description.hpp b/admittance_controller/test/test_asset_6d_robot_description.hpp similarity index 98% rename from admittance_controller/test/6d_robot_description.hpp rename to admittance_controller/test/test_asset_6d_robot_description.hpp index f67b5bd054..4d38df7c30 100644 --- a/admittance_controller/test/6d_robot_description.hpp +++ b/admittance_controller/test/test_asset_6d_robot_description.hpp @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef ROS2_CONTROL_TEST_ASSETS__6D_ROBOT_DESCRIPTION_HPP_ -#define ROS2_CONTROL_TEST_ASSETS__6D_ROBOT_DESCRIPTION_HPP_ +#ifndef TEST_ASSET_6D_ROBOT_DESCRIPTION_HPP_ +#define TEST_ASSET_6D_ROBOT_DESCRIPTION_HPP_ #include @@ -310,4 +310,4 @@ const auto valid_6d_robot_srdf = } // namespace ros2_control_test_assets -#endif // ROS2_CONTROL_TEST_ASSETS__6D_ROBOT_DESCRIPTION_HPP_ +#endif // TEST_ASSET_6D_ROBOT_DESCRIPTION_HPP_ From 38ebec73bf176a4161924db5681073f12c491d0f Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Sat, 24 Jun 2023 08:13:38 +0100 Subject: [PATCH 058/238] Update changelogs --- ackermann_steering_controller/CHANGELOG.rst | 6 ++++++ admittance_controller/CHANGELOG.rst | 6 ++++++ bicycle_steering_controller/CHANGELOG.rst | 6 ++++++ diff_drive_controller/CHANGELOG.rst | 5 +++++ effort_controllers/CHANGELOG.rst | 5 +++++ force_torque_sensor_broadcaster/CHANGELOG.rst | 6 ++++++ forward_command_controller/CHANGELOG.rst | 6 ++++++ gripper_controllers/CHANGELOG.rst | 6 ++++++ imu_sensor_broadcaster/CHANGELOG.rst | 7 +++++++ joint_state_broadcaster/CHANGELOG.rst | 5 +++++ joint_trajectory_controller/CHANGELOG.rst | 6 ++++++ position_controllers/CHANGELOG.rst | 5 +++++ ros2_controllers/CHANGELOG.rst | 3 +++ ros2_controllers_test_nodes/CHANGELOG.rst | 5 +++++ rqt_joint_trajectory_controller/CHANGELOG.rst | 3 +++ steering_controllers_library/CHANGELOG.rst | 6 ++++++ tricycle_controller/CHANGELOG.rst | 5 +++++ tricycle_steering_controller/CHANGELOG.rst | 6 ++++++ velocity_controllers/CHANGELOG.rst | 5 +++++ 19 files changed, 102 insertions(+) diff --git a/ackermann_steering_controller/CHANGELOG.rst b/ackermann_steering_controller/CHANGELOG.rst index af5ef64661..4aba3813d5 100644 --- a/ackermann_steering_controller/CHANGELOG.rst +++ b/ackermann_steering_controller/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package ackermann_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Added -Wconversion flag and fix warnings (`#667 `_) +* Let sphinx add parameter description to documentation (`#651 `_) +* Contributors: Christoph Fröhlich, gwalck + 3.10.1 (2023-06-06) ------------------- diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index 82bd365880..aaf039ec89 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Fix cpplint (`#681 `_) +* Added -Wconversion flag and fix warnings (`#667 `_) +* Contributors: Christoph Fröhlich, gwalck + 3.10.1 (2023-06-06) ------------------- diff --git a/bicycle_steering_controller/CHANGELOG.rst b/bicycle_steering_controller/CHANGELOG.rst index 6d4921dea9..f1c5028d3d 100644 --- a/bicycle_steering_controller/CHANGELOG.rst +++ b/bicycle_steering_controller/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package bicycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Added -Wconversion flag and fix warnings (`#667 `_) +* Let sphinx add parameter description to documentation (`#651 `_) +* Contributors: Christoph Fröhlich, gwalck + 3.10.1 (2023-06-06) ------------------- diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index 2cc4720e5a..86de416fe9 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Added -Wconversion flag and fix warnings (`#667 `_) +* Contributors: gwalck + 3.10.1 (2023-06-06) ------------------- diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index b30dbb4d6e..87b712bf6a 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Added -Wconversion flag and fix warnings (`#667 `_) +* Contributors: gwalck + 3.10.1 (2023-06-06) ------------------- diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index 8b303c862d..5265a506d6 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Broadcaster parameters (`#650 `_) +* Added -Wconversion flag and fix warnings (`#667 `_) +* Contributors: Christoph Fröhlich, gwalck + 3.10.1 (2023-06-06) ------------------- diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index e7b0a22fcf..f6add3e14c 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Added -Wconversion flag and fix warnings (`#667 `_) +* Let sphinx add parameter description to documentation (`#651 `_) +* Contributors: Christoph Fröhlich, gwalck + 3.10.1 (2023-06-06) ------------------- diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index 1c2e25f72e..93fc28bf7f 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Added -Wconversion flag and fix warnings (`#667 `_) +* Let sphinx add parameter description to documentation (`#651 `_) +* Contributors: Christoph Fröhlich, gwalck + 3.10.1 (2023-06-06) ------------------- diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index 3869b5e229..00d8b01884 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,13 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Broadcaster parameters (`#650 `_) +* Added -Wconversion flag and fix warnings (`#667 `_) +* Let sphinx add parameter description to documentation (`#651 `_) +* Contributors: Christoph Fröhlich, gwalck + 3.10.1 (2023-06-06) ------------------- diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index 050460c0a8..07eef0514a 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Added -Wconversion flag and fix warnings (`#667 `_) +* Contributors: gwalck + 3.10.1 (2023-06-06) ------------------- diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index a8f89aea96..ec1192edfe 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* jtc: fix minor typo in traj validation error msg (`#674 `_) +* Added -Wconversion flag and fix warnings (`#667 `_) +* Contributors: G.A. vd. Hoorn, gwalck + 3.10.1 (2023-06-06) ------------------- diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index 4f064e3140..5484a1efcf 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Added -Wconversion flag and fix warnings (`#667 `_) +* Contributors: gwalck + 3.10.1 (2023-06-06) ------------------- diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index 1c600fbd73..25beb674e5 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.10.1 (2023-06-06) ------------------- diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index 0688058681..a25db69db8 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Removes deprecated if-branch (`#653 `_) +* Contributors: Christoph Fröhlich + 3.10.1 (2023-06-06) ------------------- diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index 2e9e8325f7..5e50dcb841 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.10.1 (2023-06-06) ------------------- diff --git a/steering_controllers_library/CHANGELOG.rst b/steering_controllers_library/CHANGELOG.rst index a773bb2bcc..57d4845268 100644 --- a/steering_controllers_library/CHANGELOG.rst +++ b/steering_controllers_library/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package steering_controllers_library ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Added -Wconversion flag and fix warnings (`#667 `_) +* Let sphinx add parameter description to documentation (`#651 `_) +* Contributors: Christoph Fröhlich, gwalck + 3.10.1 (2023-06-06) ------------------- * Second round of dependencies fix (`#655 `_) diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index 13b98ea203..2af274323f 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Added -Wconversion flag and fix warnings (`#667 `_) +* Contributors: gwalck + 3.10.1 (2023-06-06) ------------------- diff --git a/tricycle_steering_controller/CHANGELOG.rst b/tricycle_steering_controller/CHANGELOG.rst index a20856bd65..81ff7aa1e1 100644 --- a/tricycle_steering_controller/CHANGELOG.rst +++ b/tricycle_steering_controller/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package tricycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Added -Wconversion flag and fix warnings (`#667 `_) +* Let sphinx add parameter description to documentation (`#651 `_) +* Contributors: Christoph Fröhlich, gwalck + 3.10.1 (2023-06-06) ------------------- diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index 0852b7e474..f766725611 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Added -Wconversion flag and fix warnings (`#667 `_) +* Contributors: gwalck + 3.10.1 (2023-06-06) ------------------- From cd40ec0e9410b303d94709405be7c4d0e97c3b3b Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Sat, 24 Jun 2023 08:14:03 +0100 Subject: [PATCH 059/238] 3.11.0 --- ackermann_steering_controller/CHANGELOG.rst | 4 ++-- ackermann_steering_controller/package.xml | 2 +- admittance_controller/CHANGELOG.rst | 4 ++-- admittance_controller/package.xml | 2 +- bicycle_steering_controller/CHANGELOG.rst | 4 ++-- bicycle_steering_controller/package.xml | 2 +- diff_drive_controller/CHANGELOG.rst | 4 ++-- diff_drive_controller/package.xml | 2 +- effort_controllers/CHANGELOG.rst | 4 ++-- effort_controllers/package.xml | 2 +- force_torque_sensor_broadcaster/CHANGELOG.rst | 4 ++-- force_torque_sensor_broadcaster/package.xml | 2 +- forward_command_controller/CHANGELOG.rst | 4 ++-- forward_command_controller/package.xml | 2 +- gripper_controllers/CHANGELOG.rst | 4 ++-- gripper_controllers/package.xml | 2 +- imu_sensor_broadcaster/CHANGELOG.rst | 4 ++-- imu_sensor_broadcaster/package.xml | 2 +- joint_state_broadcaster/CHANGELOG.rst | 4 ++-- joint_state_broadcaster/package.xml | 2 +- joint_trajectory_controller/CHANGELOG.rst | 4 ++-- joint_trajectory_controller/package.xml | 2 +- position_controllers/CHANGELOG.rst | 4 ++-- position_controllers/package.xml | 2 +- ros2_controllers/CHANGELOG.rst | 4 ++-- ros2_controllers/package.xml | 2 +- ros2_controllers_test_nodes/CHANGELOG.rst | 4 ++-- ros2_controllers_test_nodes/package.xml | 2 +- ros2_controllers_test_nodes/setup.py | 2 +- rqt_joint_trajectory_controller/CHANGELOG.rst | 4 ++-- rqt_joint_trajectory_controller/package.xml | 2 +- rqt_joint_trajectory_controller/setup.py | 2 +- steering_controllers_library/CHANGELOG.rst | 4 ++-- steering_controllers_library/package.xml | 2 +- tricycle_controller/CHANGELOG.rst | 4 ++-- tricycle_controller/package.xml | 2 +- tricycle_steering_controller/CHANGELOG.rst | 4 ++-- tricycle_steering_controller/package.xml | 2 +- velocity_controllers/CHANGELOG.rst | 4 ++-- velocity_controllers/package.xml | 2 +- 40 files changed, 59 insertions(+), 59 deletions(-) diff --git a/ackermann_steering_controller/CHANGELOG.rst b/ackermann_steering_controller/CHANGELOG.rst index 4aba3813d5..6d5626ccd0 100644 --- a/ackermann_steering_controller/CHANGELOG.rst +++ b/ackermann_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ackermann_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.11.0 (2023-06-24) +------------------- * Added -Wconversion flag and fix warnings (`#667 `_) * Let sphinx add parameter description to documentation (`#651 `_) * Contributors: Christoph Fröhlich, gwalck diff --git a/ackermann_steering_controller/package.xml b/ackermann_steering_controller/package.xml index 0c833147ea..132cac06c0 100644 --- a/ackermann_steering_controller/package.xml +++ b/ackermann_steering_controller/package.xml @@ -2,7 +2,7 @@ ackermann_steering_controller - 3.10.1 + 3.11.0 Steering controller for Ackermann kinematics. Rear fixed wheels are powering the vehicle and front wheels are steering it. Apache License 2.0 Bence Magyar diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index aaf039ec89..56feda699a 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.11.0 (2023-06-24) +------------------- * Fix cpplint (`#681 `_) * Added -Wconversion flag and fix warnings (`#667 `_) * Contributors: Christoph Fröhlich, gwalck diff --git a/admittance_controller/package.xml b/admittance_controller/package.xml index 4506992846..ba6d549877 100644 --- a/admittance_controller/package.xml +++ b/admittance_controller/package.xml @@ -2,7 +2,7 @@ admittance_controller - 3.10.1 + 3.11.0 Implementation of admittance controllers for different input and output interface. Denis Štogl Bence Magyar diff --git a/bicycle_steering_controller/CHANGELOG.rst b/bicycle_steering_controller/CHANGELOG.rst index f1c5028d3d..1b7a761aeb 100644 --- a/bicycle_steering_controller/CHANGELOG.rst +++ b/bicycle_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package bicycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.11.0 (2023-06-24) +------------------- * Added -Wconversion flag and fix warnings (`#667 `_) * Let sphinx add parameter description to documentation (`#651 `_) * Contributors: Christoph Fröhlich, gwalck diff --git a/bicycle_steering_controller/package.xml b/bicycle_steering_controller/package.xml index 3a777bd441..e77fd0e0bb 100644 --- a/bicycle_steering_controller/package.xml +++ b/bicycle_steering_controller/package.xml @@ -2,7 +2,7 @@ bicycle_steering_controller - 3.10.1 + 3.11.0 Steering controller with bicycle kinematics. Rear fixed wheel is powering the vehicle and front wheel is steering. Apache License 2.0 Bence Magyar diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index 86de416fe9..fddec6b53d 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.11.0 (2023-06-24) +------------------- * Added -Wconversion flag and fix warnings (`#667 `_) * Contributors: gwalck diff --git a/diff_drive_controller/package.xml b/diff_drive_controller/package.xml index 669d1067b7..f7d2f2f361 100644 --- a/diff_drive_controller/package.xml +++ b/diff_drive_controller/package.xml @@ -1,7 +1,7 @@ diff_drive_controller - 3.10.1 + 3.11.0 Controller for a differential drive mobile base. Bence Magyar Jordan Palacios diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index 87b712bf6a..b21b0c547d 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.11.0 (2023-06-24) +------------------- * Added -Wconversion flag and fix warnings (`#667 `_) * Contributors: gwalck diff --git a/effort_controllers/package.xml b/effort_controllers/package.xml index 5a9f239d58..567dc00741 100644 --- a/effort_controllers/package.xml +++ b/effort_controllers/package.xml @@ -1,7 +1,7 @@ effort_controllers - 3.10.1 + 3.11.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index 5265a506d6..de8adc57f1 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.11.0 (2023-06-24) +------------------- * Broadcaster parameters (`#650 `_) * Added -Wconversion flag and fix warnings (`#667 `_) * Contributors: Christoph Fröhlich, gwalck diff --git a/force_torque_sensor_broadcaster/package.xml b/force_torque_sensor_broadcaster/package.xml index 955650fcf9..a363551958 100644 --- a/force_torque_sensor_broadcaster/package.xml +++ b/force_torque_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ force_torque_sensor_broadcaster - 3.10.1 + 3.11.0 Controller to publish state of force-torque sensors. Bence Magyar Denis Štogl diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index f6add3e14c..796b01c03f 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.11.0 (2023-06-24) +------------------- * Added -Wconversion flag and fix warnings (`#667 `_) * Let sphinx add parameter description to documentation (`#651 `_) * Contributors: Christoph Fröhlich, gwalck diff --git a/forward_command_controller/package.xml b/forward_command_controller/package.xml index f7b744ef61..0069f28315 100644 --- a/forward_command_controller/package.xml +++ b/forward_command_controller/package.xml @@ -1,7 +1,7 @@ forward_command_controller - 3.10.1 + 3.11.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index 93fc28bf7f..e4cb8cad5e 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.11.0 (2023-06-24) +------------------- * Added -Wconversion flag and fix warnings (`#667 `_) * Let sphinx add parameter description to documentation (`#651 `_) * Contributors: Christoph Fröhlich, gwalck diff --git a/gripper_controllers/package.xml b/gripper_controllers/package.xml index 06fd59362f..646399f14f 100644 --- a/gripper_controllers/package.xml +++ b/gripper_controllers/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> gripper_controllers - 3.10.1 + 3.11.0 The gripper_controllers package Bence Magyar diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index 00d8b01884..5252da9c44 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.11.0 (2023-06-24) +------------------- * Broadcaster parameters (`#650 `_) * Added -Wconversion flag and fix warnings (`#667 `_) * Let sphinx add parameter description to documentation (`#651 `_) diff --git a/imu_sensor_broadcaster/package.xml b/imu_sensor_broadcaster/package.xml index a5b4dd06bf..993bec7ab4 100644 --- a/imu_sensor_broadcaster/package.xml +++ b/imu_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ imu_sensor_broadcaster - 3.10.1 + 3.11.0 Controller to publish readings of IMU sensors. Bence Magyar Denis Štogl diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index 07eef0514a..9337cd24b2 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.11.0 (2023-06-24) +------------------- * Added -Wconversion flag and fix warnings (`#667 `_) * Contributors: gwalck diff --git a/joint_state_broadcaster/package.xml b/joint_state_broadcaster/package.xml index 1be245a957..da7683d69e 100644 --- a/joint_state_broadcaster/package.xml +++ b/joint_state_broadcaster/package.xml @@ -1,7 +1,7 @@ joint_state_broadcaster - 3.10.1 + 3.11.0 Broadcaster to publish joint state Bence Magyar Denis Stogl diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index ec1192edfe..354516fbb2 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.11.0 (2023-06-24) +------------------- * jtc: fix minor typo in traj validation error msg (`#674 `_) * Added -Wconversion flag and fix warnings (`#667 `_) * Contributors: G.A. vd. Hoorn, gwalck diff --git a/joint_trajectory_controller/package.xml b/joint_trajectory_controller/package.xml index f91322b047..edf2ac91a9 100644 --- a/joint_trajectory_controller/package.xml +++ b/joint_trajectory_controller/package.xml @@ -1,7 +1,7 @@ joint_trajectory_controller - 3.10.1 + 3.11.0 Controller for executing joint-space trajectories on a group of joints Bence Magyar Jordan Palacios diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index 5484a1efcf..299b7b7de7 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.11.0 (2023-06-24) +------------------- * Added -Wconversion flag and fix warnings (`#667 `_) * Contributors: gwalck diff --git a/position_controllers/package.xml b/position_controllers/package.xml index 2829642bba..d2c4eaecc6 100644 --- a/position_controllers/package.xml +++ b/position_controllers/package.xml @@ -1,7 +1,7 @@ position_controllers - 3.10.1 + 3.11.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index 25beb674e5..4ca34fc0a5 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.11.0 (2023-06-24) +------------------- 3.10.1 (2023-06-06) ------------------- diff --git a/ros2_controllers/package.xml b/ros2_controllers/package.xml index 1b7f76ed01..ce06ac9d71 100644 --- a/ros2_controllers/package.xml +++ b/ros2_controllers/package.xml @@ -1,7 +1,7 @@ ros2_controllers - 3.10.1 + 3.11.0 Metapackage for ROS2 controllers related packages Bence Magyar Jordan Palacios diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index a25db69db8..f1a00b9bf4 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.11.0 (2023-06-24) +------------------- * Removes deprecated if-branch (`#653 `_) * Contributors: Christoph Fröhlich diff --git a/ros2_controllers_test_nodes/package.xml b/ros2_controllers_test_nodes/package.xml index 71dec82527..27cc252293 100644 --- a/ros2_controllers_test_nodes/package.xml +++ b/ros2_controllers_test_nodes/package.xml @@ -2,7 +2,7 @@ ros2_controllers_test_nodes - 3.10.1 + 3.11.0 Demo nodes for showing and testing functionalities of the ros2_control framework. Denis Štogl diff --git a/ros2_controllers_test_nodes/setup.py b/ros2_controllers_test_nodes/setup.py index 96f08db712..35f7f7b942 100644 --- a/ros2_controllers_test_nodes/setup.py +++ b/ros2_controllers_test_nodes/setup.py @@ -20,7 +20,7 @@ setup( name=package_name, - version="3.10.1", + version="3.11.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index 5e50dcb841..648b093d2f 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.11.0 (2023-06-24) +------------------- 3.10.1 (2023-06-06) ------------------- diff --git a/rqt_joint_trajectory_controller/package.xml b/rqt_joint_trajectory_controller/package.xml index 4be20ed909..c44049b9ff 100644 --- a/rqt_joint_trajectory_controller/package.xml +++ b/rqt_joint_trajectory_controller/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> rqt_joint_trajectory_controller - 3.10.1 + 3.11.0 Graphical frontend for interacting with joint_trajectory_controller instances. Bence Magyar diff --git a/rqt_joint_trajectory_controller/setup.py b/rqt_joint_trajectory_controller/setup.py index 146c961401..5610eff43c 100644 --- a/rqt_joint_trajectory_controller/setup.py +++ b/rqt_joint_trajectory_controller/setup.py @@ -7,7 +7,7 @@ setup( name=package_name, - version="3.10.1", + version="3.11.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/steering_controllers_library/CHANGELOG.rst b/steering_controllers_library/CHANGELOG.rst index 57d4845268..596f1fe9d3 100644 --- a/steering_controllers_library/CHANGELOG.rst +++ b/steering_controllers_library/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package steering_controllers_library ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.11.0 (2023-06-24) +------------------- * Added -Wconversion flag and fix warnings (`#667 `_) * Let sphinx add parameter description to documentation (`#651 `_) * Contributors: Christoph Fröhlich, gwalck diff --git a/steering_controllers_library/package.xml b/steering_controllers_library/package.xml index 688b84167a..5918c1491e 100644 --- a/steering_controllers_library/package.xml +++ b/steering_controllers_library/package.xml @@ -2,7 +2,7 @@ steering_controllers_library - 3.10.1 + 3.11.0 Package for steering robot configurations including odometry and interfaces. Apache License 2.0 Bence Magyar diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index 2af274323f..f58f8f1539 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.11.0 (2023-06-24) +------------------- * Added -Wconversion flag and fix warnings (`#667 `_) * Contributors: gwalck diff --git a/tricycle_controller/package.xml b/tricycle_controller/package.xml index 4098984815..2b5106ff83 100644 --- a/tricycle_controller/package.xml +++ b/tricycle_controller/package.xml @@ -2,7 +2,7 @@ tricycle_controller - 3.10.1 + 3.11.0 Controller for a tricycle drive mobile base Bence Magyar Tony Najjar diff --git a/tricycle_steering_controller/CHANGELOG.rst b/tricycle_steering_controller/CHANGELOG.rst index 81ff7aa1e1..3782216e48 100644 --- a/tricycle_steering_controller/CHANGELOG.rst +++ b/tricycle_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package tricycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.11.0 (2023-06-24) +------------------- * Added -Wconversion flag and fix warnings (`#667 `_) * Let sphinx add parameter description to documentation (`#651 `_) * Contributors: Christoph Fröhlich, gwalck diff --git a/tricycle_steering_controller/package.xml b/tricycle_steering_controller/package.xml index e82ef7e202..b8893108e0 100644 --- a/tricycle_steering_controller/package.xml +++ b/tricycle_steering_controller/package.xml @@ -2,7 +2,7 @@ tricycle_steering_controller - 3.10.1 + 3.11.0 Steering controller with tricycle kinematics. Rear fixed wheels are powering the vehicle and front wheel is steering. Apache License 2.0 Bence Magyar diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index f766725611..b86820e783 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.11.0 (2023-06-24) +------------------- * Added -Wconversion flag and fix warnings (`#667 `_) * Contributors: gwalck diff --git a/velocity_controllers/package.xml b/velocity_controllers/package.xml index 5d71730f8f..eba1e97ad2 100644 --- a/velocity_controllers/package.xml +++ b/velocity_controllers/package.xml @@ -1,7 +1,7 @@ velocity_controllers - 3.10.1 + 3.11.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios From 9ce288b9cd9caabb1d29df6fb4e1baefa52781cb Mon Sep 17 00:00:00 2001 From: Ethan Gordon Date: Mon, 26 Jun 2023 10:38:05 -0700 Subject: [PATCH 060/238] [JTC] Command final waypoint identically when traj_point_active_ptr_ is nullptr (#682) --- .../src/joint_trajectory_controller.cpp | 102 +++++++++--------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/joint_trajectory_controller/src/joint_trajectory_controller.cpp b/joint_trajectory_controller/src/joint_trajectory_controller.cpp index 4d994e26bf..5e3e0fd770 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller.cpp +++ b/joint_trajectory_controller/src/joint_trajectory_controller.cpp @@ -241,57 +241,6 @@ controller_interface::return_type JointTrajectoryController::update( } } - // set values for next hardware write() if tolerance is met - if (!tolerance_violated_while_moving && within_goal_time) - { - if (use_closed_loop_pid_adapter_) - { - // Update PIDs - for (auto i = 0ul; i < dof_; ++i) - { - tmp_command_[i] = (state_desired_.velocities[i] * ff_velocity_scale_[i]) + - pids_[i]->computeCommand( - state_error_.positions[i], state_error_.velocities[i], - (uint64_t)period.nanoseconds()); - } - } - - // set values for next hardware write() - if (has_position_command_interface_) - { - assign_interface_from_point(joint_command_interface_[0], state_desired_.positions); - } - if (has_velocity_command_interface_) - { - if (use_closed_loop_pid_adapter_) - { - assign_interface_from_point(joint_command_interface_[1], tmp_command_); - } - else - { - assign_interface_from_point(joint_command_interface_[1], state_desired_.velocities); - } - } - if (has_acceleration_command_interface_) - { - assign_interface_from_point(joint_command_interface_[2], state_desired_.accelerations); - } - if (has_effort_command_interface_) - { - if (use_closed_loop_pid_adapter_) - { - assign_interface_from_point(joint_command_interface_[3], tmp_command_); - } - else - { - assign_interface_from_point(joint_command_interface_[3], state_desired_.effort); - } - } - - // store the previous command. Used in open-loop control mode - last_commanded_state_ = state_desired_; - } - const auto active_goal = *rt_active_goal_.readFromRT(); if (active_goal) { @@ -359,6 +308,57 @@ controller_interface::return_type JointTrajectoryController::update( set_hold_position(); RCLCPP_ERROR(get_node()->get_logger(), "Holding position due to state tolerance violation"); } + + // set values for next hardware write() if tolerance is met + if (!tolerance_violated_while_moving && within_goal_time) + { + if (use_closed_loop_pid_adapter_) + { + // Update PIDs + for (auto i = 0ul; i < dof_; ++i) + { + tmp_command_[i] = (state_desired_.velocities[i] * ff_velocity_scale_[i]) + + pids_[i]->computeCommand( + state_error_.positions[i], state_error_.velocities[i], + (uint64_t)period.nanoseconds()); + } + } + + // set values for next hardware write() + if (has_position_command_interface_) + { + assign_interface_from_point(joint_command_interface_[0], state_desired_.positions); + } + if (has_velocity_command_interface_) + { + if (traj_point_active_ptr_ && use_closed_loop_pid_adapter_) + { + assign_interface_from_point(joint_command_interface_[1], tmp_command_); + } + else + { + assign_interface_from_point(joint_command_interface_[1], state_desired_.velocities); + } + } + if (has_acceleration_command_interface_) + { + assign_interface_from_point(joint_command_interface_[2], state_desired_.accelerations); + } + if (has_effort_command_interface_) + { + if (traj_point_active_ptr_ && use_closed_loop_pid_adapter_) + { + assign_interface_from_point(joint_command_interface_[3], tmp_command_); + } + else + { + assign_interface_from_point(joint_command_interface_[3], state_desired_.effort); + } + } + + // store the previous command. Used in open-loop control mode + last_commanded_state_ = state_desired_; + } } } From 76b1ce7da5e7a102ef3a1c8c4f1b0de90ed0d137 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Sat, 1 Jul 2023 18:56:28 +0200 Subject: [PATCH 061/238] Add CI workflow to check docs (#691) --- .github/workflows/ci-check-docs.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .github/workflows/ci-check-docs.yml diff --git a/.github/workflows/ci-check-docs.yml b/.github/workflows/ci-check-docs.yml new file mode 100644 index 0000000000..629279615b --- /dev/null +++ b/.github/workflows/ci-check-docs.yml @@ -0,0 +1,12 @@ +name: Check Docs + +on: + workflow_dispatch: + pull_request: + +jobs: + check-docs: + name: Check Docs + uses: ros-controls/control.ros.org/.github/workflows/reusable-sphinx-check-single-version.yml@master + with: + ROS2_CONTROLLERS_PR: ${{ github.ref }} From 9908a9cbe8e00548b457f0417eb9e643ffdc8656 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Mon, 17 Jul 2023 10:06:38 +0000 Subject: [PATCH 062/238] [JTC] Extend tests (#612) --- .../test/test_trajectory_actions.cpp | 153 +- .../test/test_trajectory_controller.cpp | 1743 ++++++++--------- .../test/test_trajectory_controller_utils.hpp | 10 +- 3 files changed, 958 insertions(+), 948 deletions(-) diff --git a/joint_trajectory_controller/test/test_trajectory_actions.cpp b/joint_trajectory_controller/test/test_trajectory_actions.cpp index ef0a11d961..fc2dd42314 100644 --- a/joint_trajectory_controller/test/test_trajectory_actions.cpp +++ b/joint_trajectory_controller/test/test_trajectory_actions.cpp @@ -197,7 +197,24 @@ class TestTrajectoryActions : public TrajectoryControllerTest } }; -TEST_F(TestTrajectoryActions, test_success_single_point_sendgoal) +// From the tutorial: https://www.sandordargo.com/blog/2019/04/24/parameterized-testing-with-gtest +class TestTrajectoryActionsTestParameterized +: public TestTrajectoryActions, + public ::testing::WithParamInterface< + std::tuple, std::vector>> +{ +public: + virtual void SetUp() + { + TestTrajectoryActions::SetUp(); + command_interface_types_ = std::get<0>(GetParam()); + state_interface_types_ = std::get<1>(GetParam()); + } + + static void TearDownTestCase() { TrajectoryControllerTest::TearDownTestCase(); } +}; + +TEST_P(TestTrajectoryActionsTestParameterized, test_success_single_point_sendgoal) { SetUpExecutor(); SetUpControllerHardware(); @@ -223,12 +240,15 @@ TEST_F(TestTrajectoryActions, test_success_single_point_sendgoal) EXPECT_TRUE(gh_future.get()); EXPECT_EQ(rclcpp_action::ResultCode::SUCCEEDED, common_resultcode_); - EXPECT_EQ(1.0, joint_pos_[0]); - EXPECT_EQ(2.0, joint_pos_[1]); - EXPECT_EQ(3.0, joint_pos_[2]); + if (traj_controller_->has_position_command_interface()) + { + EXPECT_EQ(1.0, joint_pos_[0]); + EXPECT_EQ(2.0, joint_pos_[1]); + EXPECT_EQ(3.0, joint_pos_[2]); + } } -TEST_F(TestTrajectoryActions, test_success_multi_point_sendgoal) +TEST_P(TestTrajectoryActionsTestParameterized, test_success_multi_point_sendgoal) { SetUpExecutor(); SetUpControllerHardware(); @@ -270,11 +290,18 @@ TEST_F(TestTrajectoryActions, test_success_multi_point_sendgoal) EXPECT_TRUE(gh_future.get()); EXPECT_EQ(rclcpp_action::ResultCode::SUCCEEDED, common_resultcode_); - EXPECT_NEAR(7.0, joint_pos_[0], COMMON_THRESHOLD); - EXPECT_NEAR(8.0, joint_pos_[1], COMMON_THRESHOLD); - EXPECT_NEAR(9.0, joint_pos_[2], COMMON_THRESHOLD); + if (traj_controller_->has_position_command_interface()) + { + EXPECT_NEAR(7.0, joint_pos_[0], COMMON_THRESHOLD); + EXPECT_NEAR(8.0, joint_pos_[1], COMMON_THRESHOLD); + EXPECT_NEAR(9.0, joint_pos_[2], COMMON_THRESHOLD); + } } +/** + * Makes sense with position command interface only, + * because no integration to position state interface is implemented +*/ TEST_F(TestTrajectoryActions, test_goal_tolerances_single_point_success) { // set tolerance parameters @@ -308,11 +335,18 @@ TEST_F(TestTrajectoryActions, test_goal_tolerances_single_point_success) EXPECT_EQ( control_msgs::action::FollowJointTrajectory_Result::SUCCESSFUL, common_action_result_code_); - EXPECT_NEAR(1.0, joint_pos_[0], COMMON_THRESHOLD); - EXPECT_NEAR(2.0, joint_pos_[1], COMMON_THRESHOLD); - EXPECT_NEAR(3.0, joint_pos_[2], COMMON_THRESHOLD); + if (traj_controller_->has_position_command_interface()) + { + EXPECT_NEAR(1.0, joint_pos_[0], COMMON_THRESHOLD); + EXPECT_NEAR(2.0, joint_pos_[1], COMMON_THRESHOLD); + EXPECT_NEAR(3.0, joint_pos_[2], COMMON_THRESHOLD); + } } +/** + * Makes sense with position command interface only, + * because no integration to position state interface is implemented +*/ TEST_F(TestTrajectoryActions, test_goal_tolerances_multi_point_success) { // set tolerance parameters @@ -363,12 +397,15 @@ TEST_F(TestTrajectoryActions, test_goal_tolerances_multi_point_success) EXPECT_EQ( control_msgs::action::FollowJointTrajectory_Result::SUCCESSFUL, common_action_result_code_); - EXPECT_NEAR(7.0, joint_pos_[0], COMMON_THRESHOLD); - EXPECT_NEAR(8.0, joint_pos_[1], COMMON_THRESHOLD); - EXPECT_NEAR(9.0, joint_pos_[2], COMMON_THRESHOLD); + if (traj_controller_->has_position_command_interface()) + { + EXPECT_NEAR(7.0, joint_pos_[0], COMMON_THRESHOLD); + EXPECT_NEAR(8.0, joint_pos_[1], COMMON_THRESHOLD); + EXPECT_NEAR(9.0, joint_pos_[2], COMMON_THRESHOLD); + } } -TEST_F(TestTrajectoryActions, test_state_tolerances_fail) +TEST_P(TestTrajectoryActionsTestParameterized, test_state_tolerances_fail) { // set joint tolerance parameters const double state_tol = 0.0001; @@ -415,12 +452,15 @@ TEST_F(TestTrajectoryActions, test_state_tolerances_fail) // run an update, it should be holding updateController(rclcpp::Duration::from_seconds(0.01)); - EXPECT_NEAR(INITIAL_POS_JOINT1, joint_pos_[0], COMMON_THRESHOLD); - EXPECT_NEAR(INITIAL_POS_JOINT2, joint_pos_[1], COMMON_THRESHOLD); - EXPECT_NEAR(INITIAL_POS_JOINT3, joint_pos_[2], COMMON_THRESHOLD); + if (traj_controller_->has_position_command_interface()) + { + EXPECT_NEAR(INITIAL_POS_JOINT1, joint_pos_[0], COMMON_THRESHOLD); + EXPECT_NEAR(INITIAL_POS_JOINT2, joint_pos_[1], COMMON_THRESHOLD); + EXPECT_NEAR(INITIAL_POS_JOINT3, joint_pos_[2], COMMON_THRESHOLD); + } } -TEST_F(TestTrajectoryActions, test_goal_tolerances_fail) +TEST_P(TestTrajectoryActionsTestParameterized, test_goal_tolerances_fail) { // set joint tolerance parameters const double goal_tol = 0.1; @@ -465,12 +505,15 @@ TEST_F(TestTrajectoryActions, test_goal_tolerances_fail) // run an update, it should be holding updateController(rclcpp::Duration::from_seconds(0.01)); - EXPECT_NEAR(init_pos1, joint_pos_[0], COMMON_THRESHOLD); - EXPECT_NEAR(init_pos2, joint_pos_[1], COMMON_THRESHOLD); - EXPECT_NEAR(init_pos3, joint_pos_[2], COMMON_THRESHOLD); + if (traj_controller_->has_position_command_interface()) + { + EXPECT_NEAR(init_pos1, joint_pos_[0], COMMON_THRESHOLD); + EXPECT_NEAR(init_pos2, joint_pos_[1], COMMON_THRESHOLD); + EXPECT_NEAR(init_pos3, joint_pos_[2], COMMON_THRESHOLD); + } } -TEST_F(TestTrajectoryActions, test_no_time_from_start_state_tolerance_fail) +TEST_P(TestTrajectoryActionsTestParameterized, test_no_time_from_start_state_tolerance_fail) { // set joint tolerance parameters const double state_tol = 0.0001; @@ -512,12 +555,15 @@ TEST_F(TestTrajectoryActions, test_no_time_from_start_state_tolerance_fail) // run an update, it should be holding updateController(rclcpp::Duration::from_seconds(0.01)); - EXPECT_NEAR(init_pos1, joint_pos_[0], COMMON_THRESHOLD); - EXPECT_NEAR(init_pos2, joint_pos_[1], COMMON_THRESHOLD); - EXPECT_NEAR(init_pos3, joint_pos_[2], COMMON_THRESHOLD); + if (traj_controller_->has_position_command_interface()) + { + EXPECT_NEAR(init_pos1, joint_pos_[0], COMMON_THRESHOLD); + EXPECT_NEAR(init_pos2, joint_pos_[1], COMMON_THRESHOLD); + EXPECT_NEAR(init_pos3, joint_pos_[2], COMMON_THRESHOLD); + } } -TEST_F(TestTrajectoryActions, test_cancel_hold_position) +TEST_P(TestTrajectoryActionsTestParameterized, test_cancel_hold_position) { SetUpExecutor(); SetUpControllerHardware(); @@ -561,7 +607,54 @@ TEST_F(TestTrajectoryActions, test_cancel_hold_position) // run an update, it should be holding updateController(rclcpp::Duration::from_seconds(0.01)); - EXPECT_EQ(prev_pos1, joint_pos_[0]); - EXPECT_EQ(prev_pos2, joint_pos_[1]); - EXPECT_EQ(prev_pos3, joint_pos_[2]); + if (traj_controller_->has_position_command_interface()) + { + EXPECT_EQ(prev_pos1, joint_pos_[0]); + EXPECT_EQ(prev_pos2, joint_pos_[1]); + EXPECT_EQ(prev_pos3, joint_pos_[2]); + } } + +// position controllers +INSTANTIATE_TEST_SUITE_P( + PositionTrajectoryControllersActions, TestTrajectoryActionsTestParameterized, + ::testing::Values( + std::make_tuple(std::vector({"position"}), std::vector({"position"})), + std::make_tuple( + std::vector({"position"}), std::vector({"position", "velocity"})), + std::make_tuple( + std::vector({"position"}), + std::vector({"position", "velocity", "acceleration"})))); + +// position_velocity controllers +INSTANTIATE_TEST_SUITE_P( + PositionVelocityTrajectoryControllersActions, TestTrajectoryActionsTestParameterized, + ::testing::Values( + std::make_tuple( + std::vector({"position", "velocity"}), std::vector({"position"})), + std::make_tuple( + std::vector({"position", "velocity"}), + std::vector({"position", "velocity"})), + std::make_tuple( + std::vector({"position", "velocity"}), + std::vector({"position", "velocity", "acceleration"})))); + +// only velocity controller +INSTANTIATE_TEST_SUITE_P( + OnlyVelocityTrajectoryControllersAction, TestTrajectoryActionsTestParameterized, + ::testing::Values( + std::make_tuple( + std::vector({"velocity"}), std::vector({"position", "velocity"})), + std::make_tuple( + std::vector({"velocity"}), + std::vector({"position", "velocity", "acceleration"})))); + +// only effort controller +INSTANTIATE_TEST_SUITE_P( + OnlyEffortTrajectoryControllers, TestTrajectoryActionsTestParameterized, + ::testing::Values( + std::make_tuple( + std::vector({"effort"}), std::vector({"position", "velocity"})), + std::make_tuple( + std::vector({"effort"}), + std::vector({"position", "velocity", "acceleration"})))); diff --git a/joint_trajectory_controller/test/test_trajectory_controller.cpp b/joint_trajectory_controller/test/test_trajectory_controller.cpp index b1188eede7..714d3c8d49 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller.cpp +++ b/joint_trajectory_controller/test/test_trajectory_controller.cpp @@ -199,119 +199,6 @@ TEST_P(TrajectoryControllerTestParameterized, activate) executor.cancel(); } -// TEST_F(TestTrajectoryController, activation) { -// auto traj_controller = std::make_shared( -// joint_names_, op_mode_); -// auto ret = traj_controller->init(test_robot_, controller_name_); -// if (ret != controller_interface::return_type::OK) { -// FAIL(); -// } -// -// auto traj_node = traj_controller->get_node(); -// rclcpp::executors::MultiThreadedExecutor executor; -// executor.add_node(traj_node->get_node_base_interface()); -// -// auto state = traj_controller_->configure(); -// ASSERT_EQ(state.id(), State::PRIMARY_STATE_INACTIVE); -// -// state = traj_node->activate(); -// ASSERT_EQ(state.id(), State::PRIMARY_STATE_ACTIVE); -// -// // wait for the subscriber and publisher to completely setup -// std::this_thread::sleep_for(std::chrono::seconds(2)); -// -// // send msg -// builtin_interfaces::msg::Duration time_from_start; -// time_from_start.sec = 1; -// time_from_start.nanosec = 0; -// std::vector> points {{{3.3, 4.4, 5.5}}}; -// publish(time_from_start, points, rclcpp::Time()); -// // wait for msg is be published to the system -// std::this_thread::sleep_for(std::chrono::milliseconds(1000)); -// executor.spin_once(); -// -// traj_controller->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)); -// resource_manager_->write(); -// -// // change in hw position -// EXPECT_EQ(3.3, joint_pos_[0]); -// EXPECT_EQ(4.4, joint_pos_[1]); -// EXPECT_EQ(5.5, joint_pos_[2]); -// -// executor.cancel(); -// } - -// TEST_F(TestTrajectoryController, reactivation) { -// auto traj_controller = std::make_shared( -// joint_names_, op_mode_); -// auto ret = traj_controller->init(test_robot_, controller_name_); -// if (ret != controller_interface::return_type::OK) { -// FAIL(); -// } -// -// auto traj_node = traj_controller->get_node(); -// rclcpp::executors::MultiThreadedExecutor executor; -// executor.add_node(traj_node->get_node_base_interface()); -// -// auto state = traj_controller_->configure(); -// ASSERT_EQ(state.id(), State::PRIMARY_STATE_INACTIVE); -// -// state = traj_node->activate(); -// ASSERT_EQ(state.id(), State::PRIMARY_STATE_ACTIVE); -// -// // wait for the subscriber and publisher to completely setup -// std::this_thread::sleep_for(std::chrono::seconds(2)); -// -// // send msg -// builtin_interfaces::msg::Duration time_from_start; -// time_from_start.sec = 1; -// time_from_start.nanosec = 0; -// // *INDENT-OFF* -// std::vector> points { -// {{3.3, 4.4, 5.5}}, -// {{7.7, 8.8, 9.9}}, -// {{10.10, 11.11, 12.12}} -// }; -// // *INDENT-ON* -// publish(time_from_start, points, rclcpp::Time()); -// // wait for msg is be published to the system -// std::this_thread::sleep_for(std::chrono::milliseconds(500)); -// executor.spin_once(); -// -// traj_controller->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)); -// resource_manager_->write(); -// -// // deactivated -// // wait so controller process the second point when deactivated -// std::this_thread::sleep_for(std::chrono::milliseconds(500)); -// state = traj_controller_->deactivate(); -// ASSERT_EQ(state.id(), State::PRIMARY_STATE_INACTIVE); -// resource_manager_->read(); -// traj_controller->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)); -// resource_manager_->write(); -// -// // no change in hw position -// EXPECT_EQ(3.3, joint_pos_[0]); -// EXPECT_EQ(4.4, joint_pos_[1]); -// EXPECT_EQ(5.5, joint_pos_[2]); -// -// // reactivated -// // wait so controller process the third point when reactivated -// std::this_thread::sleep_for(std::chrono::milliseconds(3000)); -// state = traj_node->activate(); -// ASSERT_EQ(state.id(), State::PRIMARY_STATE_ACTIVE); -// resource_manager_->read(); -// traj_controller->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)); -// resource_manager_->write(); -// -// // change in hw position to 3rd point -// EXPECT_EQ(10.10, joint_pos_[0]); -// EXPECT_EQ(11.11, joint_pos_[1]); -// EXPECT_EQ(12.12, joint_pos_[2]); -// -// executor.cancel(); -// } - TEST_P(TrajectoryControllerTestParameterized, cleanup) { rclcpp::executors::MultiThreadedExecutor executor; @@ -338,7 +225,10 @@ TEST_P(TrajectoryControllerTestParameterized, cleanup) state = traj_controller_->get_node()->cleanup(); ASSERT_EQ(State::PRIMARY_STATE_UNCONFIGURED, state.id()); + // update for 0.25 seconds + // TODO(anyone): should the controller even allow calling update() when it is not active? + // update loop receives a new msg and updates accordingly updateController(rclcpp::Duration::from_seconds(0.25)); // should be home pose again @@ -428,25 +318,28 @@ TEST_P(TrajectoryControllerTestParameterized, correct_initialization_using_param EXPECT_LE(0.0, joint_eff_[2]); } - // cleanup - state = traj_controller_->get_node()->cleanup(); - ASSERT_EQ(State::PRIMARY_STATE_UNCONFIGURED, state.id()); + // reactivated + // wait so controller process the third point when reactivated + std::this_thread::sleep_for(std::chrono::milliseconds(3000)); + // TODO(anyone) test copied from ROS 1: it fails now! + // should the old trajectory really be processed after reactivation? +#if 0 + ActivateTrajectoryController(); + state = traj_controller_->get_state(); + ASSERT_EQ(state.id(), State::PRIMARY_STATE_ACTIVE); - // TODO(anyone): should the controller even allow calling update() when it is not active? - // update loop receives a new msg and updates accordingly - traj_controller_->update( - rclcpp::Time(static_cast(0.35 * 1e9)), rclcpp::Duration::from_seconds(0.1)); + updateController(rclcpp::Duration::from_seconds(0.5)); + // traj_controller_->update( + // rclcpp::Time(static_cast(0.75 * 1e9)), rclcpp::Duration::from_seconds(0.01)); + // change in hw position to 3rd point if (traj_controller_->has_position_command_interface()) { - // otherwise this won't be updated - EXPECT_NEAR(3.3, joint_pos_[0], allowed_delta); - EXPECT_NEAR(4.4, joint_pos_[1], allowed_delta); - EXPECT_NEAR(5.5, joint_pos_[2], allowed_delta); + EXPECT_NEAR(10.10, joint_pos_[0], allowed_delta); + EXPECT_NEAR(11.11, joint_pos_[1], allowed_delta); + EXPECT_NEAR(12.12, joint_pos_[2], allowed_delta); } - - // state = traj_controller_->get_node()->configure(); - // ASSERT_EQ(State::PRIMARY_STATE_INACTIVE, state.id()); +#endif executor.cancel(); } @@ -723,14 +616,9 @@ TEST_P(TrajectoryControllerTestParameterized, position_error_normalized) if (traj_controller_->has_velocity_command_interface()) { - // check command interface - EXPECT_LT(0.0, joint_vel_[0]); - EXPECT_LT(0.0, joint_vel_[1]); - // use_closed_loop_pid_adapter_ if (traj_controller_->use_closed_loop_pid_adapter()) { - EXPECT_GT(0.0, joint_vel_[2]); // we expect u = k_p * (s_d-s) for positions[0] and positions[1] EXPECT_NEAR( k_p * (state_msg->reference.positions[0] - INITIAL_POS_JOINTS[0]), joint_vel_[0], @@ -739,6 +627,7 @@ TEST_P(TrajectoryControllerTestParameterized, position_error_normalized) k_p * (state_msg->reference.positions[1] - INITIAL_POS_JOINTS[1]), joint_vel_[1], k_p * allowed_delta); // is error of positions[2] normalized? + EXPECT_GT(0.0, joint_vel_[2]); EXPECT_NEAR( k_p * (state_msg->reference.positions[2] - INITIAL_POS_JOINTS[2] - 2 * M_PI), joint_vel_[2], k_p * allowed_delta); @@ -746,819 +635,839 @@ TEST_P(TrajectoryControllerTestParameterized, position_error_normalized) else { // interpolated points_velocities only + // check command interface + EXPECT_LT(0.0, joint_vel_[0]); + EXPECT_LT(0.0, joint_vel_[1]); EXPECT_LT(0.0, joint_vel_[2]); } } if (traj_controller_->has_effort_command_interface()) { - // check command interface - EXPECT_LT(0.0, joint_eff_[0]); - EXPECT_LT(0.0, joint_eff_[1]); - EXPECT_LT(0.0, joint_eff_[2]); + // use_closed_loop_pid_adapter_ + if (traj_controller_->use_closed_loop_pid_adapter()) + { + // we expect u = k_p * (s_d-s) for positions[0] and positions[1] + EXPECT_NEAR( + k_p * (state_msg->reference.positions[0] - INITIAL_POS_JOINTS[0]), joint_eff_[0], + k_p * allowed_delta); + EXPECT_NEAR( + k_p * (state_msg->reference.positions[1] - INITIAL_POS_JOINTS[1]), joint_eff_[1], + k_p * allowed_delta); + // is error of positions[2] normalized? + EXPECT_GT(0.0, joint_eff_[2]); + EXPECT_NEAR( + k_p * (state_msg->reference.positions[2] - INITIAL_POS_JOINTS[2] - 2 * M_PI), joint_eff_[2], + k_p * allowed_delta); + } + else + { + // interpolated points_velocities only + // check command interface + EXPECT_LT(0.0, joint_eff_[0]); + EXPECT_LT(0.0, joint_eff_[1]); + EXPECT_LT(0.0, joint_eff_[2]); + } } executor.cancel(); } -// /** -// * @brief test_jumbled_joint_order Test sending trajectories with a joint order different from -// * internal controller order -// */ -// TEST_P(TrajectoryControllerTestParameterized, test_jumbled_joint_order) -// { -// rclcpp::executors::SingleThreadedExecutor executor; -// SetUpAndActivateTrajectoryController(true, {}, &executor); -// { -// trajectory_msgs::msg::JointTrajectory traj_msg; -// const std::vector jumbled_joint_names{ -// joint_names_[1], joint_names_[2], joint_names_[0]}; -// traj_msg.joint_names = jumbled_joint_names; -// traj_msg.header.stamp = rclcpp::Time(0); -// traj_msg.points.resize(1); - -// traj_msg.points[0].time_from_start = rclcpp::Duration::from_seconds(0.25); -// traj_msg.points[0].positions.resize(3); -// traj_msg.points[0].positions[0] = 2.0; -// traj_msg.points[0].positions[1] = 3.0; -// traj_msg.points[0].positions[2] = 1.0; - -// if (traj_controller_->has_velocity_command_interface()) -// { -// traj_msg.points[0].velocities.resize(3); -// traj_msg.points[0].velocities[0] = -0.1; -// traj_msg.points[0].velocities[1] = -0.1; -// traj_msg.points[0].velocities[2] = -0.1; -// } - -// if (traj_controller_->has_effort_command_interface()) -// { -// traj_msg.points[0].effort.resize(3); -// traj_msg.points[0].effort[0] = -0.1; -// traj_msg.points[0].effort[1] = -0.1; -// traj_msg.points[0].effort[2] = -0.1; -// } - -// trajectory_publisher_->publish(traj_msg); -// } - -// traj_controller_->wait_for_trajectory(executor); -// // update for 0.25 seconds -// // TODO(destogl): Make this time a bit shorter to increase stability on the CI? -// // Currently COMMON_THRESHOLD is adjusted. -// updateController(rclcpp::Duration::from_seconds(0.25)); - -// if (traj_controller_->has_position_command_interface()) -// { -// EXPECT_NEAR(1.0, joint_pos_[0], COMMON_THRESHOLD); -// EXPECT_NEAR(2.0, joint_pos_[1], COMMON_THRESHOLD); -// EXPECT_NEAR(3.0, joint_pos_[2], COMMON_THRESHOLD); -// } +/** + * @brief test_jumbled_joint_order Test sending trajectories with a joint order different from + * internal controller order + */ +TEST_P(TrajectoryControllerTestParameterized, test_jumbled_joint_order) +{ + rclcpp::executors::SingleThreadedExecutor executor; + SetUpAndActivateTrajectoryController(executor); + { + trajectory_msgs::msg::JointTrajectory traj_msg; + const std::vector jumbled_joint_names{ + joint_names_[1], joint_names_[2], joint_names_[0]}; + traj_msg.joint_names = jumbled_joint_names; + traj_msg.header.stamp = rclcpp::Time(0); + traj_msg.points.resize(1); + + traj_msg.points[0].time_from_start = rclcpp::Duration::from_seconds(0.25); + traj_msg.points[0].positions.resize(3); + traj_msg.points[0].positions[0] = 2.0; + traj_msg.points[0].positions[1] = 3.0; + traj_msg.points[0].positions[2] = 1.0; + + if (traj_controller_->has_velocity_command_interface()) + { + traj_msg.points[0].velocities.resize(3); + traj_msg.points[0].velocities[0] = -0.1; + traj_msg.points[0].velocities[1] = -0.1; + traj_msg.points[0].velocities[2] = -0.1; + } -// if (traj_controller_->has_velocity_command_interface()) -// { -// EXPECT_GT(0.0, joint_vel_[0]); -// EXPECT_GT(0.0, joint_vel_[1]); -// EXPECT_GT(0.0, joint_vel_[2]); -// } + if (traj_controller_->has_effort_command_interface()) + { + traj_msg.points[0].effort.resize(3); + traj_msg.points[0].effort[0] = -0.1; + traj_msg.points[0].effort[1] = -0.1; + traj_msg.points[0].effort[2] = -0.1; + } -// if (traj_controller_->has_effort_command_interface()) -// { -// EXPECT_GT(0.0, joint_eff_[0]); -// EXPECT_GT(0.0, joint_eff_[1]); -// EXPECT_GT(0.0, joint_eff_[2]); -// } -// } + trajectory_publisher_->publish(traj_msg); + } -// /** -// * @brief test_partial_joint_list Test sending trajectories with a subset of the controlled -// * joints -// */ -// TEST_P(TrajectoryControllerTestParameterized, test_partial_joint_list) -// { -// rclcpp::Parameter partial_joints_parameters("allow_partial_joints_goal", true); + traj_controller_->wait_for_trajectory(executor); + // update for 0.25 seconds + // TODO(destogl): Make this time a bit shorter to increase stability on the CI? + // Currently COMMON_THRESHOLD is adjusted. + updateController(rclcpp::Duration::from_seconds(0.25)); -// rclcpp::executors::SingleThreadedExecutor executor; -// SetUpAndActivateTrajectoryController(true, {partial_joints_parameters}, &executor); + if (traj_controller_->has_position_command_interface()) + { + EXPECT_NEAR(1.0, joint_pos_[0], COMMON_THRESHOLD); + EXPECT_NEAR(2.0, joint_pos_[1], COMMON_THRESHOLD); + EXPECT_NEAR(3.0, joint_pos_[2], COMMON_THRESHOLD); + } -// const double initial_joint1_cmd = joint_pos_[0]; -// const double initial_joint2_cmd = joint_pos_[1]; -// const double initial_joint3_cmd = joint_pos_[2]; -// trajectory_msgs::msg::JointTrajectory traj_msg; + if (traj_controller_->has_velocity_command_interface()) + { + EXPECT_GT(0.0, joint_vel_[0]); + EXPECT_GT(0.0, joint_vel_[1]); + EXPECT_GT(0.0, joint_vel_[2]); + } -// { -// std::vector partial_joint_names{joint_names_[1], joint_names_[0]}; -// traj_msg.joint_names = partial_joint_names; -// traj_msg.header.stamp = rclcpp::Time(0); -// traj_msg.points.resize(1); - -// traj_msg.points[0].time_from_start = rclcpp::Duration::from_seconds(0.25); -// traj_msg.points[0].positions.resize(2); -// traj_msg.points[0].positions[0] = 2.0; -// traj_msg.points[0].positions[1] = 1.0; -// traj_msg.points[0].velocities.resize(2); -// traj_msg.points[0].velocities[0] = -// copysign(2.0, traj_msg.points[0].positions[0] - initial_joint2_cmd); -// traj_msg.points[0].velocities[1] = -// copysign(1.0, traj_msg.points[0].positions[1] - initial_joint1_cmd); - -// trajectory_publisher_->publish(traj_msg); -// } - -// traj_controller_->wait_for_trajectory(executor); -// // update for 0.5 seconds -// updateController(rclcpp::Duration::from_seconds(0.25)); - -// double threshold = 0.001; - -// if (traj_controller_->has_position_command_interface()) -// { -// EXPECT_NEAR(traj_msg.points[0].positions[1], joint_pos_[0], threshold); -// EXPECT_NEAR(traj_msg.points[0].positions[0], joint_pos_[1], threshold); -// EXPECT_NEAR(initial_joint3_cmd, joint_pos_[2], threshold) -// << "Joint 3 command should be current position"; -// } - -// if ( -// std::find(command_interface_types_.begin(), command_interface_types_.end(), "velocity") != -// command_interface_types_.end()) -// { -// // estimate the sign of the velocity -// // joint rotates forward -// EXPECT_TRUE( -// is_same_sign(traj_msg.points[0].positions[0] - initial_joint2_cmd, joint_vel_[0])); -// EXPECT_TRUE( -// is_same_sign(traj_msg.points[0].positions[1] - initial_joint1_cmd, joint_vel_[1])); -// EXPECT_NEAR(0.0, joint_vel_[2], threshold) -// << "Joint 3 velocity should be 0.0 since it's not in the goal"; -// } - -// if ( -// std::find(command_interface_types_.begin(), command_interface_types_.end(), "effort") != -// command_interface_types_.end()) -// { -// // estimate the sign of the velocity -// // joint rotates forward -// EXPECT_TRUE( -// is_same_sign(traj_msg.points[0].positions[0] - initial_joint2_cmd, joint_eff_[0])); -// EXPECT_TRUE( -// is_same_sign(traj_msg.points[0].positions[1] - initial_joint1_cmd, joint_eff_[1])); -// EXPECT_NEAR(0.0, joint_eff_[2], threshold) -// << "Joint 3 effort should be 0.0 since it's not in the goal"; -// } -// // TODO(anyone): add here ckecks for acceleration commands - -// executor.cancel(); -// } + if (traj_controller_->has_effort_command_interface()) + { + EXPECT_GT(0.0, joint_eff_[0]); + EXPECT_GT(0.0, joint_eff_[1]); + EXPECT_GT(0.0, joint_eff_[2]); + } + // TODO(anyone): add here checks for acceleration commands +} -// /** -// * @brief test_partial_joint_list Test sending trajectories with a subset of the controlled -// * joints without allow_partial_joints_goal -// */ -// TEST_P(TrajectoryControllerTestParameterized, test_partial_joint_list_not_allowed) -// { -// rclcpp::Parameter partial_joints_parameters("allow_partial_joints_goal", false); +/** + * @brief test_partial_joint_list Test sending trajectories with a subset of the controlled + * joints + */ +TEST_P(TrajectoryControllerTestParameterized, test_partial_joint_list) +{ + rclcpp::Parameter partial_joints_parameters("allow_partial_joints_goal", true); -// rclcpp::executors::SingleThreadedExecutor executor; -// SetUpAndActivateTrajectoryController(true, {partial_joints_parameters}, &executor); + rclcpp::executors::SingleThreadedExecutor executor; + SetUpAndActivateTrajectoryController(executor, true, {partial_joints_parameters}); -// const double initial_joint1_cmd = joint_pos_[0]; -// const double initial_joint2_cmd = joint_pos_[1]; -// const double initial_joint3_cmd = joint_pos_[2]; -// const double initial_joint_vel = 0.0; -// const double initial_joint_acc = 0.0; -// trajectory_msgs::msg::JointTrajectory traj_msg; + const double initial_joint1_cmd = joint_pos_[0]; + const double initial_joint2_cmd = joint_pos_[1]; + const double initial_joint3_cmd = joint_pos_[2]; + trajectory_msgs::msg::JointTrajectory traj_msg; -// { -// std::vector partial_joint_names{joint_names_[1], joint_names_[0]}; -// traj_msg.joint_names = partial_joint_names; -// traj_msg.header.stamp = rclcpp::Time(0); -// traj_msg.points.resize(1); - -// traj_msg.points[0].time_from_start = rclcpp::Duration::from_seconds(0.25); -// traj_msg.points[0].positions.resize(2); -// traj_msg.points[0].positions[0] = 2.0; -// traj_msg.points[0].positions[1] = 1.0; -// traj_msg.points[0].velocities.resize(2); -// traj_msg.points[0].velocities[0] = 2.0; -// traj_msg.points[0].velocities[1] = 1.0; - -// trajectory_publisher_->publish(traj_msg); -// } - -// traj_controller_->wait_for_trajectory(executor); -// // update for 0.5 seconds -// updateController(rclcpp::Duration::from_seconds(0.25)); - -// double threshold = 0.001; -// EXPECT_NEAR(initial_joint1_cmd, joint_pos_[0], threshold) -// << "All joints command should be current position because goal was rejected"; -// EXPECT_NEAR(initial_joint2_cmd, joint_pos_[1], threshold) -// << "All joints command should be current position because goal was rejected"; -// EXPECT_NEAR(initial_joint3_cmd, joint_pos_[2], threshold) -// << "All joints command should be current position because goal was rejected"; - -// if ( -// std::find(command_interface_types_.begin(), command_interface_types_.end(), "velocity") != -// command_interface_types_.end()) -// { -// EXPECT_NEAR(initial_joint_vel, joint_vel_[0], threshold) -// << "All joints velocities should be 0.0 because goal was rejected"; -// EXPECT_NEAR(initial_joint_vel, joint_vel_[1], threshold) -// << "All joints velocities should be 0.0 because goal was rejected"; -// EXPECT_NEAR(initial_joint_vel, joint_vel_[2], threshold) -// << "All joints velocities should be 0.0 because goal was rejected"; -// } - -// if ( -// std::find( -// command_interface_types_.begin(), command_interface_types_.end(), "acceleration") != -// command_interface_types_.end()) -// { -// EXPECT_NEAR(initial_joint_acc, joint_acc_[0], threshold) -// << "All joints accelerations should be 0.0 because goal was rejected"; -// EXPECT_NEAR(initial_joint_acc, joint_acc_[1], threshold) -// << "All joints accelerations should be 0.0 because goal was rejected"; -// EXPECT_NEAR(initial_joint_acc, joint_acc_[2], threshold) -// << "All joints accelerations should be 0.0 because goal was rejected"; -// } - -// executor.cancel(); -// } + { + std::vector partial_joint_names{joint_names_[1], joint_names_[0]}; + traj_msg.joint_names = partial_joint_names; + traj_msg.header.stamp = rclcpp::Time(0); + traj_msg.points.resize(1); + + traj_msg.points[0].time_from_start = rclcpp::Duration::from_seconds(0.25); + traj_msg.points[0].positions.resize(2); + traj_msg.points[0].positions[0] = 2.0; + traj_msg.points[0].positions[1] = 1.0; + traj_msg.points[0].velocities.resize(2); + traj_msg.points[0].velocities[0] = + copysign(2.0, traj_msg.points[0].positions[0] - initial_joint2_cmd); + traj_msg.points[0].velocities[1] = + copysign(1.0, traj_msg.points[0].positions[1] - initial_joint1_cmd); + + trajectory_publisher_->publish(traj_msg); + } -// /** -// * @brief invalid_message Test mismatched joint and reference vector sizes -// */ -// TEST_P(TrajectoryControllerTestParameterized, invalid_message) -// { -// rclcpp::Parameter partial_joints_parameters("allow_partial_joints_goal", false); -// rclcpp::Parameter allow_integration_parameters( -// "allow_integration_in_goal_trajectories", false); -// rclcpp::executors::SingleThreadedExecutor executor; -// SetUpAndActivateTrajectoryController( -// true, {partial_joints_parameters, allow_integration_parameters}, &executor); - -// trajectory_msgs::msg::JointTrajectory traj_msg, good_traj_msg; - -// good_traj_msg.joint_names = joint_names_; -// good_traj_msg.header.stamp = rclcpp::Time(0); -// good_traj_msg.points.resize(1); -// good_traj_msg.points[0].time_from_start = rclcpp::Duration::from_seconds(0.25); -// good_traj_msg.points[0].positions.resize(1); -// good_traj_msg.points[0].positions = {1.0, 2.0, 3.0}; -// good_traj_msg.points[0].velocities.resize(1); -// good_traj_msg.points[0].velocities = {-1.0, -2.0, -3.0}; -// EXPECT_TRUE(traj_controller_->validate_trajectory_msg(good_traj_msg)); - -// // Incompatible joint names -// traj_msg = good_traj_msg; -// traj_msg.joint_names = {"bad_name"}; -// EXPECT_FALSE(traj_controller_->validate_trajectory_msg(traj_msg)); - -// // No position data -// traj_msg = good_traj_msg; -// traj_msg.points[0].positions.clear(); -// EXPECT_FALSE(traj_controller_->validate_trajectory_msg(traj_msg)); - -// // Incompatible data sizes, too few positions -// traj_msg = good_traj_msg; -// traj_msg.points[0].positions = {1.0, 2.0}; -// EXPECT_FALSE(traj_controller_->validate_trajectory_msg(traj_msg)); - -// // Incompatible data sizes, too many positions -// traj_msg = good_traj_msg; -// traj_msg.points[0].positions = {1.0, 2.0, 3.0, 4.0}; -// EXPECT_FALSE(traj_controller_->validate_trajectory_msg(traj_msg)); - -// // Incompatible data sizes, too few velocities -// traj_msg = good_traj_msg; -// traj_msg.points[0].velocities = {1.0, 2.0}; -// EXPECT_FALSE(traj_controller_->validate_trajectory_msg(traj_msg)); - -// // Incompatible data sizes, too few accelerations -// traj_msg = good_traj_msg; -// traj_msg.points[0].accelerations = {1.0, 2.0}; -// EXPECT_FALSE(traj_controller_->validate_trajectory_msg(traj_msg)); - -// // Incompatible data sizes, too few efforts -// traj_msg = good_traj_msg; -// traj_msg.points[0].positions.clear(); -// traj_msg.points[0].effort = {1.0, 2.0}; -// EXPECT_FALSE(traj_controller_->validate_trajectory_msg(traj_msg)); - -// // Non-strictly increasing waypoint times -// traj_msg = good_traj_msg; -// traj_msg.points.push_back(traj_msg.points.front()); -// EXPECT_FALSE(traj_controller_->validate_trajectory_msg(traj_msg)); -// } + traj_controller_->wait_for_trajectory(executor); + updateController(rclcpp::Duration::from_seconds(0.25)); -// /// With allow_integration_in_goal_trajectories parameter trajectory missing position or -// /// velocities are accepted -// TEST_P(TrajectoryControllerTestParameterized, missing_positions_message_accepted) -// { -// rclcpp::Parameter allow_integration_parameters("allow_integration_in_goal_trajectories", true); -// rclcpp::executors::SingleThreadedExecutor executor; -// SetUpAndActivateTrajectoryController(true, {allow_integration_parameters}, &executor); - -// trajectory_msgs::msg::JointTrajectory traj_msg, good_traj_msg; - -// good_traj_msg.joint_names = joint_names_; -// good_traj_msg.header.stamp = rclcpp::Time(0); -// good_traj_msg.points.resize(1); -// good_traj_msg.points[0].time_from_start = rclcpp::Duration::from_seconds(0.25); -// good_traj_msg.points[0].positions.resize(1); -// good_traj_msg.points[0].positions = {1.0, 2.0, 3.0}; -// good_traj_msg.points[0].velocities.resize(1); -// good_traj_msg.points[0].velocities = {-1.0, -2.0, -3.0}; -// good_traj_msg.points[0].accelerations.resize(1); -// good_traj_msg.points[0].accelerations = {1.0, 2.0, 3.0}; -// EXPECT_TRUE(traj_controller_->validate_trajectory_msg(good_traj_msg)); - -// // No position data -// traj_msg = good_traj_msg; -// traj_msg.points[0].positions.clear(); -// EXPECT_TRUE(traj_controller_->validate_trajectory_msg(traj_msg)); - -// // No position and velocity data -// traj_msg = good_traj_msg; -// traj_msg.points[0].positions.clear(); -// traj_msg.points[0].velocities.clear(); -// EXPECT_TRUE(traj_controller_->validate_trajectory_msg(traj_msg)); - -// // All empty -// traj_msg = good_traj_msg; -// traj_msg.points[0].positions.clear(); -// traj_msg.points[0].velocities.clear(); -// traj_msg.points[0].accelerations.clear(); -// EXPECT_FALSE(traj_controller_->validate_trajectory_msg(traj_msg)); - -// // Incompatible data sizes, too few positions -// traj_msg = good_traj_msg; -// traj_msg.points[0].positions = {1.0, 2.0}; -// EXPECT_FALSE(traj_controller_->validate_trajectory_msg(traj_msg)); - -// // Incompatible data sizes, too many positions -// traj_msg = good_traj_msg; -// traj_msg.points[0].positions = {1.0, 2.0, 3.0, 4.0}; -// EXPECT_FALSE(traj_controller_->validate_trajectory_msg(traj_msg)); - -// // Incompatible data sizes, too few velocities -// traj_msg = good_traj_msg; -// traj_msg.points[0].velocities = {1.0}; -// EXPECT_FALSE(traj_controller_->validate_trajectory_msg(traj_msg)); - -// // Incompatible data sizes, too few accelerations -// traj_msg = good_traj_msg; -// traj_msg.points[0].accelerations = {2.0}; -// EXPECT_FALSE(traj_controller_->validate_trajectory_msg(traj_msg)); -// } + double threshold = 0.001; -// /** -// * @brief test_trajectory_replace Test replacing an existing trajectory -// */ -// TEST_P(TrajectoryControllerTestParameterized, test_trajectory_replace) -// { -// rclcpp::executors::SingleThreadedExecutor executor; -// rclcpp::Parameter partial_joints_parameters("allow_partial_joints_goal", true); -// SetUpAndActivateTrajectoryController(true, {partial_joints_parameters}, &executor); - -// subscribeToState(); - -// std::vector> points_old{{{2., 3., 4.}}}; -// std::vector> points_old_velocities{{{0.2, 0.3, 0.4}}}; -// std::vector> points_partial_new{{1.5}}; -// std::vector> points_partial_new_velocities{{0.15}}; - -// const auto delay = std::chrono::milliseconds(500); -// builtin_interfaces::msg::Duration time_from_start{rclcpp::Duration(delay)}; -// publish(time_from_start, points_old, rclcpp::Time(), {}, points_old_velocities); -// trajectory_msgs::msg::JointTrajectoryPoint expected_actual, expected_desired; -// expected_actual.positions = {points_old[0].begin(), points_old[0].end()}; -// expected_desired.positions = {points_old[0].begin(), points_old[0].end()}; -// expected_actual.velocities = { -// points_old_velocities[0].begin(), points_old_velocities[0].end()}; -// expected_desired.velocities = { -// points_old_velocities[0].begin(), points_old_velocities[0].end()}; -// // Check that we reached end of points_old trajectory -// // Denis: delta was 0.1 with 0.2 works for me -// waitAndCompareState(expected_actual, expected_desired, executor, rclcpp::Duration(delay), 0.2); - -// RCLCPP_INFO(traj_controller_->get_node()->get_logger(), "Sending new trajectory"); -// points_partial_new_velocities[0][0] = -// copysign(0.15, points_partial_new[0][0] - joint_state_pos_[0]); -// publish( -// time_from_start, points_partial_new, rclcpp::Time(), {}, points_partial_new_velocities); - -// // Replaced trajectory is a mix of previous and current goal -// expected_desired.positions[0] = points_partial_new[0][0]; -// expected_desired.positions[1] = points_old[0][1]; -// expected_desired.positions[2] = points_old[0][2]; -// expected_desired.velocities[0] = points_partial_new_velocities[0][0]; -// expected_desired.velocities[1] = 0.0; -// expected_desired.velocities[2] = 0.0; -// expected_actual = expected_desired; -// waitAndCompareState(expected_actual, expected_desired, executor, rclcpp::Duration(delay), 0.1); -// } + if (traj_controller_->has_position_command_interface()) + { + EXPECT_NEAR(traj_msg.points[0].positions[1], joint_pos_[0], threshold); + EXPECT_NEAR(traj_msg.points[0].positions[0], joint_pos_[1], threshold); + EXPECT_NEAR(initial_joint3_cmd, joint_pos_[2], threshold) + << "Joint 3 command should be current position"; + } -// /** -// * @brief test_ignore_old_trajectory Sending an old trajectory replacing an existing trajectory -// */ -// TEST_P(TrajectoryControllerTestParameterized, test_ignore_old_trajectory) -// { -// rclcpp::executors::SingleThreadedExecutor executor; -// SetUpAndActivateTrajectoryController(true, {}, &executor); -// subscribeToState(); - -// // TODO(anyone): add expectations for velocities and accelerations -// std::vector> points_old{{{2., 3., 4.}, {4., 5., 6.}}}; -// std::vector> points_new{{{-1., -2., -3.}}}; - -// RCLCPP_INFO( -// traj_controller_->get_node()->get_logger(), "Sending new trajectory in the future"); -// const auto delay = std::chrono::milliseconds(500); -// builtin_interfaces::msg::Duration time_from_start{rclcpp::Duration(delay)}; -// publish(time_from_start, points_old, rclcpp::Time()); -// trajectory_msgs::msg::JointTrajectoryPoint expected_actual, expected_desired; -// expected_actual.positions = {points_old[0].begin(), points_old[0].end()}; -// expected_desired = expected_actual; -// // Check that we reached end of points_old[0] trajectory -// waitAndCompareState(expected_actual, expected_desired, executor, rclcpp::Duration(delay), 0.1); - -// RCLCPP_INFO(traj_controller_->get_node()->get_logger(), "Sending new trajectory in the past"); -// // New trajectory will end before current time -// rclcpp::Time new_traj_start = rclcpp::Clock().now() - delay - std::chrono::milliseconds(100); -// expected_actual.positions = {points_old[1].begin(), points_old[1].end()}; -// expected_desired = expected_actual; -// std::cout << "Sending old trajectory" << std::endl; -// publish(time_from_start, points_new, new_traj_start); -// waitAndCompareState(expected_actual, expected_desired, executor, rclcpp::Duration(delay), 0.1); -// } + if (traj_controller_->has_velocity_command_interface()) + { + // estimate the sign of the velocity + // joint rotates forward + EXPECT_TRUE(is_same_sign(traj_msg.points[0].positions[0] - initial_joint2_cmd, joint_vel_[0])); + EXPECT_TRUE(is_same_sign(traj_msg.points[0].positions[1] - initial_joint1_cmd, joint_vel_[1])); + EXPECT_NEAR(0.0, joint_vel_[2], threshold) + << "Joint 3 velocity should be 0.0 since it's not in the goal"; + } -// TEST_P(TrajectoryControllerTestParameterized, test_ignore_partial_old_trajectory) -// { -// rclcpp::executors::SingleThreadedExecutor executor; -// SetUpAndActivateTrajectoryController(true, {}, &executor); -// subscribeToState(); - -// std::vector> points_old{{{2., 3., 4.}, {4., 5., 6.}}}; -// std::vector> points_new{{{-1., -2., -3.}, {-2., -4., -6.}}}; - -// const auto delay = std::chrono::milliseconds(500); -// builtin_interfaces::msg::Duration time_from_start{rclcpp::Duration(delay)}; -// publish(time_from_start, points_old, rclcpp::Time()); -// trajectory_msgs::msg::JointTrajectoryPoint expected_actual, expected_desired; -// expected_actual.positions = {points_old[0].begin(), points_old[0].end()}; -// expected_desired = expected_actual; -// // Check that we reached end of points_old[0]trajectory -// waitAndCompareState(expected_actual, expected_desired, executor, rclcpp::Duration(delay), 0.1); - -// RCLCPP_INFO( -// traj_controller_->get_node()->get_logger(), "Sending new trajectory partially in the past"); -// // New trajectory first point is in the past, second is in the future -// rclcpp::Time new_traj_start = rclcpp::Clock().now() - delay - std::chrono::milliseconds(100); -// expected_actual.positions = {points_new[1].begin(), points_new[1].end()}; -// expected_desired = expected_actual; -// publish(time_from_start, points_new, new_traj_start); -// waitAndCompareState(expected_actual, expected_desired, executor, rclcpp::Duration(delay), 0.1); -// } + if (traj_controller_->has_effort_command_interface()) + { + // estimate the sign of the effort + // joint rotates forward + EXPECT_TRUE(is_same_sign(traj_msg.points[0].positions[0] - initial_joint2_cmd, joint_eff_[0])); + EXPECT_TRUE(is_same_sign(traj_msg.points[0].positions[1] - initial_joint1_cmd, joint_eff_[1])); + EXPECT_NEAR(0.0, joint_eff_[2], threshold) + << "Joint 3 effort should be 0.0 since it's not in the goal"; + } + // TODO(anyone): add here checks for acceleration commands -// TEST_P(TrajectoryControllerTestParameterized, test_execute_partial_traj_in_future) -// { -// SetUpTrajectoryController(); -// auto traj_node = traj_controller_->get_node(); -// RCLCPP_WARN( -// traj_node->get_logger(), -// "Test disabled until current_trajectory is taken into account when adding a new trajectory."); -// // https://github.com/ros-controls/ros_controllers/blob/melodic-devel/ -// // joint_trajectory_controller/include/joint_trajectory_controller/init_joint_trajectory.h#L149 -// return; - -// // TODO(anyone): use SetUpAndActivateTrajectoryController method instead of the next line -// rclcpp::executors::SingleThreadedExecutor executor; -// executor.add_node(traj_node->get_node_base_interface()); -// subscribeToState(); -// rclcpp::Parameter partial_joints_parameters("allow_partial_joints_goal", true); -// traj_node->set_parameter(partial_joints_parameters); -// traj_controller_->get_node()->configure(); -// traj_controller_->get_node()->activate(); - -// std::vector> full_traj{{{2., 3., 4.}, {4., 6., 8.}}}; -// std::vector> full_traj_velocities{{{0.2, 0.3, 0.4}, {0.4, 0.6, 0.8}}}; -// std::vector> partial_traj{ -// {{-1., -2.}, -// { -// -2., -// -4, -// }}}; -// std::vector> partial_traj_velocities{ -// {{-0.1, -0.2}, -// { -// -0.2, -// -0.4, -// }}}; -// const auto delay = std::chrono::milliseconds(500); -// builtin_interfaces::msg::Duration points_delay{rclcpp::Duration(delay)}; -// // Send full trajectory -// publish(points_delay, full_traj, rclcpp::Time(), {}, full_traj_velocities); -// // Sleep until first waypoint of full trajectory - -// trajectory_msgs::msg::JointTrajectoryPoint expected_actual, expected_desired; -// expected_actual.positions = {full_traj[0].begin(), full_traj[0].end()}; -// expected_desired = expected_actual; -// // Check that we reached end of points_old[0]trajectory and are starting points_old[1] -// waitAndCompareState(expected_actual, expected_desired, executor, rclcpp::Duration(delay), 0.1); - -// // Send partial trajectory starting after full trajecotry is complete -// RCLCPP_INFO(traj_node->get_logger(), "Sending new trajectory in the future"); -// publish( -// points_delay, partial_traj, rclcpp::Clock().now() + delay * 2, {}, partial_traj_velocities); -// // Wait until the end start and end of partial traj - -// expected_actual.positions = { -// partial_traj.back()[0], partial_traj.back()[1], full_traj.back()[2]}; -// expected_desired = expected_actual; - -// waitAndCompareState( -// expected_actual, expected_desired, executor, rclcpp::Duration(delay * (2 + 2)), 0.1); -// } + executor.cancel(); +} -// TEST_P(TrajectoryControllerTestParameterized, test_jump_when_state_tracking_error_updated) -// { -// rclcpp::executors::SingleThreadedExecutor executor; -// // default if false so it will not be actually set parameter -// rclcpp::Parameter is_open_loop_parameters("open_loop_control", false); -// SetUpAndActivateTrajectoryController(true, {is_open_loop_parameters}, &executor, true); - -// // goal setup -// std::vector first_goal = {3.3, 4.4, 5.5}; -// std::vector> first_goal_velocities = {{0.33, 0.44, 0.55}}; -// std::vector second_goal = {6.6, 8.8, 11.0}; -// std::vector> second_goal_velocities = {{0.66, 0.88, 1.1}}; -// double state_from_command_offset = 0.3; - -// // send msg -// builtin_interfaces::msg::Duration time_from_start; -// time_from_start.sec = 1; -// time_from_start.nanosec = 0; -// std::vector> points{{first_goal}}; -// publish(time_from_start, points, rclcpp::Time(), {}, first_goal_velocities); -// traj_controller_->wait_for_trajectory(executor); -// updateController(rclcpp::Duration::from_seconds(1.1)); - -// if (traj_controller_->has_position_command_interface()) -// { -// // JTC is executing trajectory in open-loop therefore: -// // - internal state does not have to be updated (in this test-case it shouldn't) -// // - internal command is updated -// EXPECT_NEAR(INITIAL_POS_JOINT1, joint_state_pos_[0], COMMON_THRESHOLD); -// EXPECT_NEAR(first_goal[0], joint_pos_[0], COMMON_THRESHOLD); - -// // State interface should have offset from the command before starting a new trajectory -// joint_state_pos_[0] = first_goal[0] - state_from_command_offset; - -// // Move joint further in the same direction as before (to the second goal) -// points = {{second_goal}}; -// publish(time_from_start, points, rclcpp::Time(1.0), {}, second_goal_velocities); -// traj_controller_->wait_for_trajectory(executor); - -// // One the first update(s) there should be a "jump" in opposite direction from command -// // (towards the state value) -// EXPECT_NEAR(first_goal[0], joint_pos_[0], COMMON_THRESHOLD); -// traj_controller_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)); -// // Expect backward commands at first -// EXPECT_NEAR(joint_state_pos_[0], joint_pos_[0], COMMON_THRESHOLD); -// EXPECT_GT(joint_pos_[0], joint_state_pos_[0]); -// EXPECT_LT(joint_pos_[0], first_goal[0]); -// traj_controller_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)); -// EXPECT_GT(joint_pos_[0], joint_state_pos_[0]); -// EXPECT_LT(joint_pos_[0], first_goal[0]); -// traj_controller_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)); -// EXPECT_GT(joint_pos_[0], joint_state_pos_[0]); -// EXPECT_LT(joint_pos_[0], first_goal[0]); - -// // Finally the second goal will be commanded/reached -// updateController(rclcpp::Duration::from_seconds(1.1)); -// EXPECT_NEAR(second_goal[0], joint_pos_[0], COMMON_THRESHOLD); - -// // State interface should have offset from the command before starting a new trajectory -// joint_state_pos_[0] = second_goal[0] - state_from_command_offset; - -// // Move joint back to the first goal -// points = {{first_goal}}; -// publish(time_from_start, points, rclcpp::Time()); -// traj_controller_->wait_for_trajectory(executor); - -// // One the first update(s) there should be a "jump" in the goal direction from command -// // (towards the state value) -// EXPECT_NEAR(second_goal[0], joint_pos_[0], COMMON_THRESHOLD); -// traj_controller_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)); -// // Expect backward commands at first -// EXPECT_NEAR(joint_state_pos_[0], joint_pos_[0], COMMON_THRESHOLD); -// EXPECT_LT(joint_pos_[0], joint_state_pos_[0]); -// EXPECT_GT(joint_pos_[0], first_goal[0]); -// traj_controller_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)); -// EXPECT_LT(joint_pos_[0], joint_state_pos_[0]); -// EXPECT_GT(joint_pos_[0], first_goal[0]); -// traj_controller_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)); -// EXPECT_LT(joint_pos_[0], joint_state_pos_[0]); -// EXPECT_GT(joint_pos_[0], first_goal[0]); - -// // Finally the first goal will be commanded/reached -// updateController(rclcpp::Duration::from_seconds(1.1)); -// EXPECT_NEAR(first_goal[0], joint_pos_[0], COMMON_THRESHOLD); -// } - -// executor.cancel(); -// } +/** + * @brief test_partial_joint_list Test sending trajectories with a subset of the controlled + * joints without allow_partial_joints_goal + */ +TEST_P(TrajectoryControllerTestParameterized, test_partial_joint_list_not_allowed) +{ + rclcpp::Parameter partial_joints_parameters("allow_partial_joints_goal", false); -// TEST_P(TrajectoryControllerTestParameterized, test_no_jump_when_state_tracking_error_not_updated) -// { -// rclcpp::executors::SingleThreadedExecutor executor; -// // default if false so it will not be actually set parameter -// rclcpp::Parameter is_open_loop_parameters("open_loop_control", true); -// SetUpAndActivateTrajectoryController(true, {is_open_loop_parameters}, &executor, true); - -// // goal setup -// std::vector first_goal = {3.3, 4.4, 5.5}; -// std::vector second_goal = {6.6, 8.8, 11.0}; -// double state_from_command_offset = 0.3; - -// // send msg -// builtin_interfaces::msg::Duration time_from_start; -// time_from_start.sec = 1; -// time_from_start.nanosec = 0; -// std::vector> points{{first_goal}}; -// publish(time_from_start, points, rclcpp::Time()); -// traj_controller_->wait_for_trajectory(executor); -// updateController(rclcpp::Duration::from_seconds(1.1)); - -// if (traj_controller_->has_position_command_interface()) -// { -// // JTC is executing trajectory in open-loop therefore: -// // - internal state does not have to be updated (in this test-case it shouldn't) -// // - internal command is updated -// EXPECT_NEAR(INITIAL_POS_JOINT1, joint_state_pos_[0], COMMON_THRESHOLD); -// EXPECT_NEAR(first_goal[0], joint_pos_[0], COMMON_THRESHOLD); - -// // State interface should have offset from the command before starting a new trajectory -// joint_state_pos_[0] = first_goal[0] - state_from_command_offset; - -// // Move joint further in the same direction as before (to the second goal) -// points = {{second_goal}}; -// publish(time_from_start, points, rclcpp::Time()); -// traj_controller_->wait_for_trajectory(executor); - -// // One the first update(s) there **should not** be a "jump" in opposite direction from -// // command (towards the state value) -// EXPECT_NEAR(first_goal[0], joint_pos_[0], COMMON_THRESHOLD); -// traj_controller_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)); -// // There should not be backward commands -// EXPECT_NEAR(first_goal[0], joint_pos_[0], COMMON_THRESHOLD); -// EXPECT_GT(joint_pos_[0], first_goal[0]); -// EXPECT_LT(joint_pos_[0], second_goal[0]); -// traj_controller_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)); -// EXPECT_GT(joint_pos_[0], first_goal[0]); -// EXPECT_LT(joint_pos_[0], second_goal[0]); -// traj_controller_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)); -// EXPECT_GT(joint_pos_[0], first_goal[0]); -// EXPECT_LT(joint_pos_[0], second_goal[0]); - -// // Finally the second goal will be commanded/reached -// updateController(rclcpp::Duration::from_seconds(1.1)); -// EXPECT_NEAR(second_goal[0], joint_pos_[0], COMMON_THRESHOLD); - -// // State interface should have offset from the command before starting a new trajectory -// joint_state_pos_[0] = second_goal[0] - state_from_command_offset; - -// // Move joint back to the first goal -// points = {{first_goal}}; -// publish(time_from_start, points, rclcpp::Time()); -// traj_controller_->wait_for_trajectory(executor); - -// // One the first update(s) there **should not** be a "jump" in the goal direction from -// // command (towards the state value) -// EXPECT_NEAR(second_goal[0], joint_pos_[0], COMMON_THRESHOLD); -// traj_controller_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)); -// // There should not be a jump toward commands -// EXPECT_NEAR(second_goal[0], joint_pos_[0], COMMON_THRESHOLD); -// EXPECT_LT(joint_pos_[0], second_goal[0]); -// EXPECT_GT(joint_pos_[0], first_goal[0]); -// traj_controller_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)); -// EXPECT_GT(joint_pos_[0], first_goal[0]); -// EXPECT_LT(joint_pos_[0], second_goal[0]); -// traj_controller_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)); -// EXPECT_GT(joint_pos_[0], first_goal[0]); -// EXPECT_LT(joint_pos_[0], second_goal[0]); - -// // Finally the first goal will be commanded/reached -// updateController(rclcpp::Duration::from_seconds(1.1)); -// EXPECT_NEAR(first_goal[0], joint_pos_[0], COMMON_THRESHOLD); -// } - -// executor.cancel(); -// } + rclcpp::executors::SingleThreadedExecutor executor; + SetUpAndActivateTrajectoryController(executor, true, {partial_joints_parameters}); -// // Testing that values are read from state interfaces when hardware is started for the first -// // time and hardware state has offset --> this is indicated by NaN values in state interfaces -// TEST_P(TrajectoryControllerTestParameterized, test_hw_states_has_offset_first_controller_start) -// { -// rclcpp::executors::SingleThreadedExecutor executor; -// // default if false so it will not be actually set parameter -// rclcpp::Parameter is_open_loop_parameters("open_loop_control", true); + const double initial_joint1_cmd = joint_pos_[0]; + const double initial_joint2_cmd = joint_pos_[1]; + const double initial_joint3_cmd = joint_pos_[2]; + trajectory_msgs::msg::JointTrajectory traj_msg; -// // set command values to NaN -// for (size_t i = 0; i < 3; ++i) -// { -// joint_pos_[i] = std::numeric_limits::quiet_NaN(); -// joint_vel_[i] = std::numeric_limits::quiet_NaN(); -// joint_acc_[i] = std::numeric_limits::quiet_NaN(); -// } -// SetUpAndActivateTrajectoryController(true, {is_open_loop_parameters}, &executor, true); + { + std::vector partial_joint_names{joint_names_[1], joint_names_[0]}; + traj_msg.joint_names = partial_joint_names; + traj_msg.header.stamp = rclcpp::Time(0); + traj_msg.points.resize(1); + + traj_msg.points[0].time_from_start = rclcpp::Duration::from_seconds(0.25); + traj_msg.points[0].positions.resize(2); + traj_msg.points[0].positions[0] = 2.0; + traj_msg.points[0].positions[1] = 1.0; + traj_msg.points[0].velocities.resize(2); + traj_msg.points[0].velocities[0] = 2.0; + traj_msg.points[0].velocities[1] = 1.0; + + trajectory_publisher_->publish(traj_msg); + } -// auto current_state_when_offset = traj_controller_->get_current_state_when_offset(); + traj_controller_->wait_for_trajectory(executor); + // update for 0.5 seconds + updateController(rclcpp::Duration::from_seconds(0.25)); -// for (size_t i = 0; i < 3; ++i) -// { -// EXPECT_EQ(current_state_when_offset.positions[i], joint_state_pos_[i]); - -// // check velocity -// if ( -// std::find( -// state_interface_types_.begin(), state_interface_types_.end(), -// hardware_interface::HW_IF_VELOCITY) != state_interface_types_.end() && -// std::find( -// command_interface_types_.begin(), command_interface_types_.end(), -// hardware_interface::HW_IF_VELOCITY) != command_interface_types_.end()) -// { -// EXPECT_EQ(current_state_when_offset.positions[i], joint_state_pos_[i]); -// } - -// // check acceleration -// if ( -// std::find( -// state_interface_types_.begin(), state_interface_types_.end(), -// hardware_interface::HW_IF_ACCELERATION) != state_interface_types_.end() && -// std::find( -// command_interface_types_.begin(), command_interface_types_.end(), -// hardware_interface::HW_IF_ACCELERATION) != command_interface_types_.end()) -// { -// EXPECT_EQ(current_state_when_offset.positions[i], joint_state_pos_[i]); -// } -// } - -// executor.cancel(); -// } + double threshold = 0.001; -// // Testing that values are read from state interfaces when hardware is started after some values -// // are set on the hardware commands -// TEST_P(TrajectoryControllerTestParameterized, test_hw_states_has_offset_later_controller_start) -// { -// rclcpp::executors::SingleThreadedExecutor executor; -// // default if false so it will not be actually set parameter -// rclcpp::Parameter is_open_loop_parameters("open_loop_control", true); + if (traj_controller_->has_position_command_interface()) + { + EXPECT_NEAR(initial_joint1_cmd, joint_pos_[0], threshold) + << "All joints command should be current position because goal was rejected"; + EXPECT_NEAR(initial_joint2_cmd, joint_pos_[1], threshold) + << "All joints command should be current position because goal was rejected"; + EXPECT_NEAR(initial_joint3_cmd, joint_pos_[2], threshold) + << "All joints command should be current position because goal was rejected"; + } -// // set command values to NaN -// for (size_t i = 0; i < 3; ++i) -// { -// joint_pos_[i] = 3.1 + i; -// joint_vel_[i] = 0.25 + i; -// joint_acc_[i] = 0.02 + i / 10.0; -// } -// SetUpAndActivateTrajectoryController(true, {is_open_loop_parameters}, &executor, true); + if (traj_controller_->has_velocity_command_interface()) + { + EXPECT_NEAR(INITIAL_VEL_JOINTS[0], joint_vel_[0], threshold) + << "All joints velocities should be 0.0 because goal was rejected"; + EXPECT_NEAR(INITIAL_VEL_JOINTS[1], joint_vel_[1], threshold) + << "All joints velocities should be 0.0 because goal was rejected"; + EXPECT_NEAR(INITIAL_VEL_JOINTS[2], joint_vel_[2], threshold) + << "All joints velocities should be 0.0 because goal was rejected"; + } -// auto current_state_when_offset = traj_controller_->get_current_state_when_offset(); + if (traj_controller_->has_acceleration_command_interface()) + { + EXPECT_NEAR(INITIAL_ACC_JOINTS[0], joint_acc_[0], threshold) + << "All joints accelerations should be 0.0 because goal was rejected"; + EXPECT_NEAR(INITIAL_ACC_JOINTS[1], joint_acc_[1], threshold) + << "All joints accelerations should be 0.0 because goal was rejected"; + EXPECT_NEAR(INITIAL_ACC_JOINTS[2], joint_acc_[2], threshold) + << "All joints accelerations should be 0.0 because goal was rejected"; + } -// for (size_t i = 0; i < 3; ++i) -// { -// EXPECT_EQ(current_state_when_offset.positions[i], joint_pos_[i]); - -// // check velocity -// if ( -// std::find( -// state_interface_types_.begin(), state_interface_types_.end(), -// hardware_interface::HW_IF_VELOCITY) != state_interface_types_.end() && -// std::find( -// command_interface_types_.begin(), command_interface_types_.end(), -// hardware_interface::HW_IF_VELOCITY) != command_interface_types_.end()) -// { -// EXPECT_EQ(current_state_when_offset.positions[i], joint_pos_[i]); -// } - -// // check acceleration -// if ( -// std::find( -// state_interface_types_.begin(), state_interface_types_.end(), -// hardware_interface::HW_IF_ACCELERATION) != state_interface_types_.end() && -// std::find( -// command_interface_types_.begin(), command_interface_types_.end(), -// hardware_interface::HW_IF_ACCELERATION) != command_interface_types_.end()) -// { -// EXPECT_EQ(current_state_when_offset.positions[i], joint_pos_[i]); -// } -// } - -// executor.cancel(); -// } + if (traj_controller_->has_effort_command_interface()) + { + EXPECT_NEAR(INITIAL_EFF_JOINTS[0], joint_eff_[0], threshold) + << "All joints efforts should be 0.0 because goal was rejected"; + EXPECT_NEAR(INITIAL_EFF_JOINTS[1], joint_eff_[1], threshold) + << "All joints efforts should be 0.0 because goal was rejected"; + EXPECT_NEAR(INITIAL_EFF_JOINTS[2], joint_eff_[2], threshold) + << "All joints efforts should be 0.0 because goal was rejected"; + } + + executor.cancel(); +} + +/** + * @brief invalid_message Test mismatched joint and reference vector sizes + */ +TEST_P(TrajectoryControllerTestParameterized, invalid_message) +{ + rclcpp::Parameter partial_joints_parameters("allow_partial_joints_goal", false); + rclcpp::Parameter allow_integration_parameters("allow_integration_in_goal_trajectories", false); + rclcpp::executors::SingleThreadedExecutor executor; + SetUpAndActivateTrajectoryController( + executor, true, {partial_joints_parameters, allow_integration_parameters}); + + trajectory_msgs::msg::JointTrajectory traj_msg, good_traj_msg; + + good_traj_msg.joint_names = joint_names_; + good_traj_msg.header.stamp = rclcpp::Time(0); + good_traj_msg.points.resize(1); + good_traj_msg.points[0].time_from_start = rclcpp::Duration::from_seconds(0.25); + good_traj_msg.points[0].positions.resize(1); + good_traj_msg.points[0].positions = {1.0, 2.0, 3.0}; + good_traj_msg.points[0].velocities.resize(1); + good_traj_msg.points[0].velocities = {-1.0, -2.0, -3.0}; + EXPECT_TRUE(traj_controller_->validate_trajectory_msg(good_traj_msg)); + + // Incompatible joint names + traj_msg = good_traj_msg; + traj_msg.joint_names = {"bad_name"}; + EXPECT_FALSE(traj_controller_->validate_trajectory_msg(traj_msg)); + + // No position data + traj_msg = good_traj_msg; + traj_msg.points[0].positions.clear(); + EXPECT_FALSE(traj_controller_->validate_trajectory_msg(traj_msg)); + + // Incompatible data sizes, too few positions + traj_msg = good_traj_msg; + traj_msg.points[0].positions = {1.0, 2.0}; + EXPECT_FALSE(traj_controller_->validate_trajectory_msg(traj_msg)); + + // Incompatible data sizes, too many positions + traj_msg = good_traj_msg; + traj_msg.points[0].positions = {1.0, 2.0, 3.0, 4.0}; + EXPECT_FALSE(traj_controller_->validate_trajectory_msg(traj_msg)); + + // Incompatible data sizes, too few velocities + traj_msg = good_traj_msg; + traj_msg.points[0].velocities = {1.0, 2.0}; + EXPECT_FALSE(traj_controller_->validate_trajectory_msg(traj_msg)); + + // Incompatible data sizes, too few accelerations + traj_msg = good_traj_msg; + traj_msg.points[0].accelerations = {1.0, 2.0}; + EXPECT_FALSE(traj_controller_->validate_trajectory_msg(traj_msg)); + + // Incompatible data sizes, too few efforts + traj_msg = good_traj_msg; + traj_msg.points[0].positions.clear(); + traj_msg.points[0].effort = {1.0, 2.0}; + EXPECT_FALSE(traj_controller_->validate_trajectory_msg(traj_msg)); + + // Non-strictly increasing waypoint times + traj_msg = good_traj_msg; + traj_msg.points.push_back(traj_msg.points.front()); + EXPECT_FALSE(traj_controller_->validate_trajectory_msg(traj_msg)); +} + +/// With allow_integration_in_goal_trajectories parameter trajectory missing position or +/// velocities are accepted +TEST_P(TrajectoryControllerTestParameterized, missing_positions_message_accepted) +{ + rclcpp::Parameter allow_integration_parameters("allow_integration_in_goal_trajectories", true); + rclcpp::executors::SingleThreadedExecutor executor; + SetUpAndActivateTrajectoryController(executor, true, {allow_integration_parameters}); + + trajectory_msgs::msg::JointTrajectory traj_msg, good_traj_msg; + + good_traj_msg.joint_names = joint_names_; + good_traj_msg.header.stamp = rclcpp::Time(0); + good_traj_msg.points.resize(1); + good_traj_msg.points[0].time_from_start = rclcpp::Duration::from_seconds(0.25); + good_traj_msg.points[0].positions.resize(1); + good_traj_msg.points[0].positions = {1.0, 2.0, 3.0}; + good_traj_msg.points[0].velocities.resize(1); + good_traj_msg.points[0].velocities = {-1.0, -2.0, -3.0}; + good_traj_msg.points[0].accelerations.resize(1); + good_traj_msg.points[0].accelerations = {1.0, 2.0, 3.0}; + EXPECT_TRUE(traj_controller_->validate_trajectory_msg(good_traj_msg)); + + // No position data + traj_msg = good_traj_msg; + traj_msg.points[0].positions.clear(); + EXPECT_TRUE(traj_controller_->validate_trajectory_msg(traj_msg)); + + // No position and velocity data + traj_msg = good_traj_msg; + traj_msg.points[0].positions.clear(); + traj_msg.points[0].velocities.clear(); + EXPECT_TRUE(traj_controller_->validate_trajectory_msg(traj_msg)); + + // All empty + traj_msg = good_traj_msg; + traj_msg.points[0].positions.clear(); + traj_msg.points[0].velocities.clear(); + traj_msg.points[0].accelerations.clear(); + EXPECT_FALSE(traj_controller_->validate_trajectory_msg(traj_msg)); + + // Incompatible data sizes, too few positions + traj_msg = good_traj_msg; + traj_msg.points[0].positions = {1.0, 2.0}; + EXPECT_FALSE(traj_controller_->validate_trajectory_msg(traj_msg)); + + // Incompatible data sizes, too many positions + traj_msg = good_traj_msg; + traj_msg.points[0].positions = {1.0, 2.0, 3.0, 4.0}; + EXPECT_FALSE(traj_controller_->validate_trajectory_msg(traj_msg)); + + // Incompatible data sizes, too few velocities + traj_msg = good_traj_msg; + traj_msg.points[0].velocities = {1.0}; + EXPECT_FALSE(traj_controller_->validate_trajectory_msg(traj_msg)); + + // Incompatible data sizes, too few accelerations + traj_msg = good_traj_msg; + traj_msg.points[0].accelerations = {2.0}; + EXPECT_FALSE(traj_controller_->validate_trajectory_msg(traj_msg)); +} + +/** + * @brief test_trajectory_replace Test replacing an existing trajectory + */ +TEST_P(TrajectoryControllerTestParameterized, test_trajectory_replace) +{ + rclcpp::executors::SingleThreadedExecutor executor; + rclcpp::Parameter partial_joints_parameters("allow_partial_joints_goal", true); + SetUpAndActivateTrajectoryController(executor, true, {partial_joints_parameters}); + + subscribeToState(); + + std::vector> points_old{{{2., 3., 4.}}}; + std::vector> points_old_velocities{{{0.2, 0.3, 0.4}}}; + std::vector> points_partial_new{{1.5}}; + std::vector> points_partial_new_velocities{{0.15}}; + + const auto delay = std::chrono::milliseconds(500); + builtin_interfaces::msg::Duration time_from_start{rclcpp::Duration(delay)}; + publish(time_from_start, points_old, rclcpp::Time(), {}, points_old_velocities); + trajectory_msgs::msg::JointTrajectoryPoint expected_actual, expected_desired; + expected_actual.positions = {points_old[0].begin(), points_old[0].end()}; + expected_desired.positions = {points_old[0].begin(), points_old[0].end()}; + expected_actual.velocities = {points_old_velocities[0].begin(), points_old_velocities[0].end()}; + expected_desired.velocities = {points_old_velocities[0].begin(), points_old_velocities[0].end()}; + // Check that we reached end of points_old trajectory + // Denis: delta was 0.1 with 0.2 works for me + waitAndCompareState(expected_actual, expected_desired, executor, rclcpp::Duration(delay), 0.2); + + RCLCPP_INFO(traj_controller_->get_node()->get_logger(), "Sending new trajectory"); + points_partial_new_velocities[0][0] = + copysign(0.15, points_partial_new[0][0] - joint_state_pos_[0]); + publish(time_from_start, points_partial_new, rclcpp::Time(), {}, points_partial_new_velocities); + + // Replaced trajectory is a mix of previous and current goal + expected_desired.positions[0] = points_partial_new[0][0]; + expected_desired.positions[1] = points_old[0][1]; + expected_desired.positions[2] = points_old[0][2]; + expected_desired.velocities[0] = points_partial_new_velocities[0][0]; + expected_desired.velocities[1] = 0.0; + expected_desired.velocities[2] = 0.0; + expected_actual = expected_desired; + waitAndCompareState(expected_actual, expected_desired, executor, rclcpp::Duration(delay), 0.1); +} + +/** + * @brief test_ignore_old_trajectory Sending an old trajectory replacing an existing trajectory + */ +TEST_P(TrajectoryControllerTestParameterized, test_ignore_old_trajectory) +{ + rclcpp::executors::SingleThreadedExecutor executor; + SetUpAndActivateTrajectoryController(executor, true, {}); + subscribeToState(); + + // TODO(anyone): add expectations for velocities and accelerations + std::vector> points_old{{{2., 3., 4.}, {4., 5., 6.}}}; + std::vector> points_new{{{-1., -2., -3.}}}; + + RCLCPP_INFO(traj_controller_->get_node()->get_logger(), "Sending new trajectory in the future"); + const auto delay = std::chrono::milliseconds(500); + builtin_interfaces::msg::Duration time_from_start{rclcpp::Duration(delay)}; + publish(time_from_start, points_old, rclcpp::Time()); + trajectory_msgs::msg::JointTrajectoryPoint expected_actual, expected_desired; + expected_actual.positions = {points_old[0].begin(), points_old[0].end()}; + expected_desired = expected_actual; + // Check that we reached end of points_old[0] trajectory + waitAndCompareState(expected_actual, expected_desired, executor, rclcpp::Duration(delay), 0.1); + + RCLCPP_INFO(traj_controller_->get_node()->get_logger(), "Sending new trajectory in the past"); + // New trajectory will end before current time + rclcpp::Time new_traj_start = rclcpp::Clock().now() - delay - std::chrono::milliseconds(100); + expected_actual.positions = {points_old[1].begin(), points_old[1].end()}; + expected_desired = expected_actual; + std::cout << "Sending old trajectory" << std::endl; + publish(time_from_start, points_new, new_traj_start); + waitAndCompareState(expected_actual, expected_desired, executor, rclcpp::Duration(delay), 0.1); +} + +TEST_P(TrajectoryControllerTestParameterized, test_ignore_partial_old_trajectory) +{ + rclcpp::executors::SingleThreadedExecutor executor; + SetUpAndActivateTrajectoryController(executor, true, {}); + subscribeToState(); + + std::vector> points_old{{{2., 3., 4.}, {4., 5., 6.}}}; + std::vector> points_new{{{-1., -2., -3.}, {-2., -4., -6.}}}; + + const auto delay = std::chrono::milliseconds(500); + builtin_interfaces::msg::Duration time_from_start{rclcpp::Duration(delay)}; + publish(time_from_start, points_old, rclcpp::Time()); + trajectory_msgs::msg::JointTrajectoryPoint expected_actual, expected_desired; + expected_actual.positions = {points_old[0].begin(), points_old[0].end()}; + expected_desired = expected_actual; + // Check that we reached end of points_old[0]trajectory + waitAndCompareState(expected_actual, expected_desired, executor, rclcpp::Duration(delay), 0.1); + + RCLCPP_INFO( + traj_controller_->get_node()->get_logger(), "Sending new trajectory partially in the past"); + // New trajectory first point is in the past, second is in the future + rclcpp::Time new_traj_start = rclcpp::Clock().now() - delay - std::chrono::milliseconds(100); + expected_actual.positions = {points_new[1].begin(), points_new[1].end()}; + expected_desired = expected_actual; + publish(time_from_start, points_new, new_traj_start); + waitAndCompareState(expected_actual, expected_desired, executor, rclcpp::Duration(delay), 0.1); +} + +TEST_P(TrajectoryControllerTestParameterized, test_execute_partial_traj_in_future) +{ + rclcpp::Parameter partial_joints_parameters("allow_partial_joints_goal", true); + rclcpp::executors::SingleThreadedExecutor executor; + SetUpAndActivateTrajectoryController(executor, true, {partial_joints_parameters}); + subscribeToState(); + + RCLCPP_WARN( + traj_controller_->get_node()->get_logger(), + "Test disabled until current_trajectory is taken into account when adding a new trajectory."); + // https://github.com/ros-controls/ros_controllers/blob/melodic-devel/ + // joint_trajectory_controller/include/joint_trajectory_controller/init_joint_trajectory.h#L149 + return; + + // *INDENT-OFF* + std::vector> full_traj{{{2., 3., 4.}, {4., 6., 8.}}}; + std::vector> full_traj_velocities{{{0.2, 0.3, 0.4}, {0.4, 0.6, 0.8}}}; + std::vector> partial_traj{{{-1., -2.}, {-2., -4}}}; + std::vector> partial_traj_velocities{{{-0.1, -0.2}, {-0.2, -0.4}}}; + // *INDENT-ON* + const auto delay = std::chrono::milliseconds(500); + builtin_interfaces::msg::Duration points_delay{rclcpp::Duration(delay)}; + // Send full trajectory + publish(points_delay, full_traj, rclcpp::Time(), {}, full_traj_velocities); + // Sleep until first waypoint of full trajectory + + trajectory_msgs::msg::JointTrajectoryPoint expected_actual, expected_desired; + expected_actual.positions = {full_traj[0].begin(), full_traj[0].end()}; + expected_desired = expected_actual; + // Check that we reached end of points_old[0]trajectory and are starting points_old[1] + waitAndCompareState(expected_actual, expected_desired, executor, rclcpp::Duration(delay), 0.1); + + // Send partial trajectory starting after full trajecotry is complete + RCLCPP_INFO(traj_controller_->get_node()->get_logger(), "Sending new trajectory in the future"); + publish( + points_delay, partial_traj, rclcpp::Clock().now() + delay * 2, {}, partial_traj_velocities); + // Wait until the end start and end of partial traj + + expected_actual.positions = {partial_traj.back()[0], partial_traj.back()[1], full_traj.back()[2]}; + expected_desired = expected_actual; + + waitAndCompareState( + expected_actual, expected_desired, executor, rclcpp::Duration(delay * (2 + 2)), 0.1); +} + +// TODO(destogl) this test fails with errors +// second publish() gives an error, because end time is before current time +// as well as +// 2: The difference between joint_state_pos_[0] and joint_pos_[0] is 0.02999799000000003, +// which exceeds COMMON_THRESHOLD, where +// 2: joint_state_pos_[0] evaluates to 6.2999999999999998, +// 2: joint_pos_[0] evaluates to 6.2700020099999998, and +// 2: COMMON_THRESHOLD evaluates to 0.0011000000000000001. +// 2: [ FAILED ] PositionTrajectoryControllers/TrajectoryControllerTestParameterized. +// test_jump_when_state_tracking_error_updated/0, where GetParam() = +// ({ "position" }, { "position" }) (3372 ms) + +#if 0 +TEST_P(TrajectoryControllerTestParameterized, test_jump_when_state_tracking_error_updated) +{ + rclcpp::executors::SingleThreadedExecutor executor; + // default if false so it will not be actually set parameter + rclcpp::Parameter is_open_loop_parameters("open_loop_control", false); + SetUpAndActivateTrajectoryController(executor, true, {is_open_loop_parameters}, true); + + // goal setup + std::vector first_goal = {3.3, 4.4, 5.5}; + std::vector> first_goal_velocities = {{0.33, 0.44, 0.55}}; + std::vector second_goal = {6.6, 8.8, 11.0}; + std::vector> second_goal_velocities = {{0.66, 0.88, 1.1}}; + double state_from_command_offset = 0.3; + + // send msg + builtin_interfaces::msg::Duration time_from_start; + time_from_start.sec = 1; + time_from_start.nanosec = 0; + std::vector> points{{first_goal}}; + publish(time_from_start, points, + rclcpp::Time(0.0, 0.0, RCL_STEADY_TIME), {}, first_goal_velocities); + traj_controller_->wait_for_trajectory(executor); + updateController(rclcpp::Duration::from_seconds(1.1)); + + if (traj_controller_->has_position_command_interface()) + { + // JTC is executing trajectory in open-loop therefore: + // - internal state does not have to be updated (in this test-case it shouldn't) + // - internal command is updated + EXPECT_NEAR(INITIAL_POS_JOINT1, joint_state_pos_[0], COMMON_THRESHOLD); + EXPECT_NEAR(first_goal[0], joint_pos_[0], COMMON_THRESHOLD); + + // State interface should have offset from the command before starting a new trajectory + joint_state_pos_[0] = first_goal[0] - state_from_command_offset; + + // Move joint further in the same direction as before (to the second goal) + points = {{second_goal}}; + publish(time_from_start, points, + rclcpp::Time(1.0, 0.0, RCL_STEADY_TIME), {}, second_goal_velocities); + traj_controller_->wait_for_trajectory(executor); + + // One the first update(s) there should be a "jump" in opposite direction from command + // (towards the state value) + EXPECT_NEAR(first_goal[0], joint_pos_[0], COMMON_THRESHOLD); + updateController(rclcpp::Duration::from_seconds(0.01)); + // Expect backward commands at first + EXPECT_NEAR(joint_state_pos_[0], joint_pos_[0], state_from_command_offset + COMMON_THRESHOLD); + EXPECT_GT(joint_pos_[0], joint_state_pos_[0]); + EXPECT_LT(joint_pos_[0], first_goal[0]); + updateController(rclcpp::Duration::from_seconds(0.01)); + EXPECT_GT(joint_pos_[0], joint_state_pos_[0]); + EXPECT_LT(joint_pos_[0], first_goal[0]); + updateController(rclcpp::Duration::from_seconds(0.01)); + EXPECT_GT(joint_pos_[0], joint_state_pos_[0]); + EXPECT_LT(joint_pos_[0], first_goal[0]); + + // Finally the second goal will be commanded/reached + updateController(rclcpp::Duration::from_seconds(1.1)); + EXPECT_NEAR(second_goal[0], joint_pos_[0], COMMON_THRESHOLD); + + // State interface should have offset from the command before starting a new trajectory + joint_state_pos_[0] = second_goal[0] - state_from_command_offset; + + // Move joint back to the first goal + points = {{first_goal}}; + publish(time_from_start, points, rclcpp::Time(0.0, 0.0, RCL_STEADY_TIME)); + traj_controller_->wait_for_trajectory(executor); + + // One the first update(s) there should be a "jump" in the goal direction from command + // (towards the state value) + EXPECT_NEAR(second_goal[0], joint_pos_[0], COMMON_THRESHOLD); + updateController(rclcpp::Duration::from_seconds(0.01)); + // Expect backward commands at first + EXPECT_NEAR(joint_state_pos_[0], joint_pos_[0], COMMON_THRESHOLD); + EXPECT_LT(joint_pos_[0], joint_state_pos_[0]); + EXPECT_GT(joint_pos_[0], first_goal[0]); + updateController(rclcpp::Duration::from_seconds(0.01)); + EXPECT_LT(joint_pos_[0], joint_state_pos_[0]); + EXPECT_GT(joint_pos_[0], first_goal[0]); + updateController(rclcpp::Duration::from_seconds(0.01)); + EXPECT_LT(joint_pos_[0], joint_state_pos_[0]); + EXPECT_GT(joint_pos_[0], first_goal[0]); + + // Finally the first goal will be commanded/reached + updateController(rclcpp::Duration::from_seconds(1.1)); + EXPECT_NEAR(first_goal[0], joint_pos_[0], COMMON_THRESHOLD); + } + + executor.cancel(); +} +#endif + +// TODO(destogl) this test fails +// 2: The difference between second_goal[0] and joint_pos_[0] is 0.032986635000000319, +// which exceeds COMMON_THRESHOLD, where +// 2: second_goal[0] evaluates to 6.5999999999999996, +// 2: joint_pos_[0] evaluates to 6.5670133649999993, and +// 2: COMMON_THRESHOLD evaluates to 0.0011000000000000001. +// 2: [ FAILED ] PositionTrajectoryControllers/TrajectoryControllerTestParameterized. +// test_no_jump_when_state_tracking_error_not_updated/1, where GetParam() = +// ({ "position" }, { "position", "velocity" }) (3374 ms) +#if 0 +TEST_P(TrajectoryControllerTestParameterized, test_no_jump_when_state_tracking_error_not_updated) +{ + rclcpp::executors::SingleThreadedExecutor executor; + rclcpp::Parameter is_open_loop_parameters("open_loop_control", true); + SetUpAndActivateTrajectoryController(executor, true, {is_open_loop_parameters}, true); + + // goal setup + std::vector first_goal = {3.3, 4.4, 5.5}; + std::vector second_goal = {6.6, 8.8, 11.0}; + double state_from_command_offset = 0.3; + + // send msg + builtin_interfaces::msg::Duration time_from_start; + time_from_start.sec = 1; + time_from_start.nanosec = 0; + std::vector> points{{first_goal}}; + publish(time_from_start, points, rclcpp::Time(0.0, 0.0, RCL_STEADY_TIME)); + traj_controller_->wait_for_trajectory(executor); + updateController(rclcpp::Duration::from_seconds(1.1)); + + if (traj_controller_->has_position_command_interface()) + { + // JTC is executing trajectory in open-loop therefore: + // - internal state does not have to be updated (in this test-case it shouldn't) + // - internal command is updated + EXPECT_NEAR(INITIAL_POS_JOINT1, joint_state_pos_[0], COMMON_THRESHOLD); + EXPECT_NEAR(first_goal[0], joint_pos_[0], COMMON_THRESHOLD); + + // State interface should have offset from the command before starting a new trajectory + joint_state_pos_[0] = first_goal[0] - state_from_command_offset; + + // Move joint further in the same direction as before (to the second goal) + points = {{second_goal}}; + publish(time_from_start, points, rclcpp::Time(0.0, 0.0, RCL_STEADY_TIME)); + traj_controller_->wait_for_trajectory(executor); + + // One the first update(s) there **should not** be a "jump" in opposite direction from + // command (towards the state value) + EXPECT_NEAR(first_goal[0], joint_pos_[0], COMMON_THRESHOLD); + updateController(rclcpp::Duration::from_seconds(0.01)); + // There should not be backward commands + EXPECT_NEAR(first_goal[0], joint_pos_[0], COMMON_THRESHOLD); + EXPECT_GT(joint_pos_[0], first_goal[0]); + EXPECT_LT(joint_pos_[0], second_goal[0]); + updateController(rclcpp::Duration::from_seconds(0.01)); + EXPECT_GT(joint_pos_[0], first_goal[0]); + EXPECT_LT(joint_pos_[0], second_goal[0]); + updateController(rclcpp::Duration::from_seconds(0.01)); + EXPECT_GT(joint_pos_[0], first_goal[0]); + EXPECT_LT(joint_pos_[0], second_goal[0]); + + // Finally the second goal will be commanded/reached + updateController(rclcpp::Duration::from_seconds(1.1)); + EXPECT_NEAR(second_goal[0], joint_pos_[0], COMMON_THRESHOLD); + + // State interface should have offset from the command before starting a new trajectory + joint_state_pos_[0] = second_goal[0] - state_from_command_offset; + + // Move joint back to the first goal + points = {{first_goal}}; + publish(time_from_start, points, rclcpp::Time(0.0, 0.0, RCL_STEADY_TIME)); + traj_controller_->wait_for_trajectory(executor); + + // One the first update(s) there **should not** be a "jump" in the goal direction from + // command (towards the state value) + EXPECT_NEAR(second_goal[0], joint_pos_[0], COMMON_THRESHOLD); + updateController(rclcpp::Duration::from_seconds(0.01)); + // There should not be a jump toward commands + EXPECT_NEAR(second_goal[0], joint_pos_[0], COMMON_THRESHOLD); + EXPECT_LT(joint_pos_[0], second_goal[0]); + EXPECT_GT(joint_pos_[0], first_goal[0]); + updateController(rclcpp::Duration::from_seconds(0.01)); + EXPECT_GT(joint_pos_[0], first_goal[0]); + EXPECT_LT(joint_pos_[0], second_goal[0]); + updateController(rclcpp::Duration::from_seconds(0.01)); + EXPECT_GT(joint_pos_[0], first_goal[0]); + EXPECT_LT(joint_pos_[0], second_goal[0]); + + // Finally the first goal will be commanded/reached + updateController(rclcpp::Duration::from_seconds(1.1)); + EXPECT_NEAR(first_goal[0], joint_pos_[0], COMMON_THRESHOLD); + } + + executor.cancel(); +} +#endif + +// Testing that values are read from state interfaces when hardware is started for the first +// time and hardware state has offset --> this is indicated by NaN values in state interfaces +TEST_P(TrajectoryControllerTestParameterized, test_hw_states_has_offset_first_controller_start) +{ + rclcpp::executors::SingleThreadedExecutor executor; + // default if false so it will not be actually set parameter + rclcpp::Parameter is_open_loop_parameters("open_loop_control", true); + + // set command values to NaN + for (size_t i = 0; i < 3; ++i) + { + joint_pos_[i] = std::numeric_limits::quiet_NaN(); + joint_vel_[i] = std::numeric_limits::quiet_NaN(); + joint_acc_[i] = std::numeric_limits::quiet_NaN(); + } + SetUpAndActivateTrajectoryController(executor, true, {is_open_loop_parameters}, true); + + auto current_state_when_offset = traj_controller_->get_current_state_when_offset(); + + for (size_t i = 0; i < 3; ++i) + { + EXPECT_EQ(current_state_when_offset.positions[i], joint_state_pos_[i]); + + // check velocity + if ( + std::find( + state_interface_types_.begin(), state_interface_types_.end(), + hardware_interface::HW_IF_VELOCITY) != state_interface_types_.end() && + traj_controller_->has_velocity_command_interface()) + { + EXPECT_EQ(current_state_when_offset.positions[i], joint_state_pos_[i]); + } + + // check acceleration + if ( + std::find( + state_interface_types_.begin(), state_interface_types_.end(), + hardware_interface::HW_IF_ACCELERATION) != state_interface_types_.end() && + traj_controller_->has_acceleration_command_interface()) + { + EXPECT_EQ(current_state_when_offset.positions[i], joint_state_pos_[i]); + } + } + + executor.cancel(); +} + +// Testing that values are read from state interfaces when hardware is started after some values +// are set on the hardware commands +TEST_P(TrajectoryControllerTestParameterized, test_hw_states_has_offset_later_controller_start) +{ + rclcpp::executors::SingleThreadedExecutor executor; + // default if false so it will not be actually set parameter + rclcpp::Parameter is_open_loop_parameters("open_loop_control", true); + + // set command values to NaN + for (size_t i = 0; i < 3; ++i) + { + joint_pos_[i] = 3.1 + i; + joint_vel_[i] = 0.25 + i; + joint_acc_[i] = 0.02 + i / 10.0; + } + SetUpAndActivateTrajectoryController(executor, true, {is_open_loop_parameters}, true); + + auto current_state_when_offset = traj_controller_->get_current_state_when_offset(); + + for (size_t i = 0; i < 3; ++i) + { + EXPECT_EQ(current_state_when_offset.positions[i], joint_pos_[i]); + + // check velocity + if ( + std::find( + state_interface_types_.begin(), state_interface_types_.end(), + hardware_interface::HW_IF_VELOCITY) != state_interface_types_.end() && + traj_controller_->has_velocity_command_interface()) + { + EXPECT_EQ(current_state_when_offset.positions[i], joint_pos_[i]); + } + + // check acceleration + if ( + std::find( + state_interface_types_.begin(), state_interface_types_.end(), + hardware_interface::HW_IF_ACCELERATION) != state_interface_types_.end() && + traj_controller_->has_acceleration_command_interface()) + { + EXPECT_EQ(current_state_when_offset.positions[i], joint_pos_[i]); + } + } + + executor.cancel(); +} // position controllers INSTANTIATE_TEST_SUITE_P( @@ -1608,15 +1517,15 @@ INSTANTIATE_TEST_SUITE_P( std::vector({"velocity"}), std::vector({"position", "velocity", "acceleration"})))); -// // only effort controller -// INSTANTIATE_TEST_SUITE_P( -// OnlyEffortTrajectoryControllers, TrajectoryControllerTestParameterized, -// ::testing::Values( -// std::make_tuple( -// std::vector({"effort"}), std::vector({"position", "velocity"})), -// std::make_tuple( -// std::vector({"effort"}), -// std::vector({"position", "velocity", "acceleration"})))); +// only effort controller +INSTANTIATE_TEST_SUITE_P( + OnlyEffortTrajectoryControllers, TrajectoryControllerTestParameterized, + ::testing::Values( + std::make_tuple( + std::vector({"effort"}), std::vector({"position", "velocity"})), + std::make_tuple( + std::vector({"effort"}), + std::vector({"position", "velocity", "acceleration"})))); // TODO(destogl): this tests should be changed because we are using `generate_parameters_library` // TEST_F(TrajectoryControllerTest, incorrect_initialization_using_interface_parameters) diff --git a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp index 8f5f64d57f..9855341edf 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp +++ b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp @@ -110,6 +110,8 @@ class TestableJointTrajectoryController bool has_velocity_command_interface() { return has_velocity_command_interface_; } + bool has_acceleration_command_interface() { return has_acceleration_command_interface_; } + bool has_effort_command_interface() { return has_effort_command_interface_; } bool use_closed_loop_pid_adapter() { return use_closed_loop_pid_adapter_; } @@ -364,7 +366,13 @@ class TrajectoryControllerTest : public ::testing::Test const auto end_time = start_time + wait_time; while (clock.now() < end_time) { - traj_controller_->update(clock.now(), clock.now() - start_time); + // TODO(christophfroehlich): use the node's clock here for internal comparison + // if using RCL_STEADY_TIME -> + // C++ exception with description + // "can't compare times with different time sources" thrown in the test body. + // traj_controller_->update(clock.now(), clock.now() - start_time); + // maybe we can set the node clock to use RCL_STEADY_TIME too? + traj_controller_->update(node_->get_clock()->now(), clock.now() - start_time); } } From 8674f2db00fd7dbd53971c0f97bac906b9b0361a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Mon, 17 Jul 2023 10:06:38 +0000 Subject: [PATCH 063/238] Increase action tests timeout (#680) --- joint_trajectory_controller/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/joint_trajectory_controller/CMakeLists.txt b/joint_trajectory_controller/CMakeLists.txt index 35223016b7..0552e0bc86 100644 --- a/joint_trajectory_controller/CMakeLists.txt +++ b/joint_trajectory_controller/CMakeLists.txt @@ -83,6 +83,7 @@ if(BUILD_TESTING) ament_add_gmock(test_trajectory_actions test/test_trajectory_actions.cpp ) + set_tests_properties(test_trajectory_actions PROPERTIES TIMEOUT 300) target_link_libraries(test_trajectory_actions joint_trajectory_controller ) From 7e13d1d4e48990f3e3a7aef78eb38d377ae8f161 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Mon, 17 Jul 2023 10:06:38 +0000 Subject: [PATCH 064/238] [JTC] Fix time sources and wrong checks in tests (#686) * Fix time sources and wrong checks in tests * Use time from update-method instead of node clock * Readd test of last command in test_goal_tolerances_fail --------- Co-authored-by: Bence Magyar --- .../src/joint_trajectory_controller.cpp | 2 +- .../test/test_trajectory_actions.cpp | 25 ++++++++++--------- .../test/test_trajectory_controller.cpp | 20 +++++++++------ .../test/test_trajectory_controller_utils.hpp | 8 +----- 4 files changed, 28 insertions(+), 27 deletions(-) diff --git a/joint_trajectory_controller/src/joint_trajectory_controller.cpp b/joint_trajectory_controller/src/joint_trajectory_controller.cpp index 5e3e0fd770..3b8f5f89bd 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller.cpp +++ b/joint_trajectory_controller/src/joint_trajectory_controller.cpp @@ -231,7 +231,7 @@ controller_interface::return_type JointTrajectoryController::update( const rclcpp::Time traj_start = (*traj_point_active_ptr_)->get_trajectory_start_time(); const rclcpp::Time traj_end = traj_start + start_segment_itr->time_from_start; - time_difference = get_node()->now().seconds() - traj_end.seconds(); + time_difference = time.seconds() - traj_end.seconds(); if (time_difference > default_tolerances_.goal_time_tolerance) { diff --git a/joint_trajectory_controller/test/test_trajectory_actions.cpp b/joint_trajectory_controller/test/test_trajectory_actions.cpp index fc2dd42314..085c20cacd 100644 --- a/joint_trajectory_controller/test/test_trajectory_actions.cpp +++ b/joint_trajectory_controller/test/test_trajectory_actions.cpp @@ -66,11 +66,14 @@ class TestTrajectoryActions : public TrajectoryControllerTest goal_options_.feedback_callback = nullptr; } - void SetUpExecutor(const std::vector & parameters = {}) + void SetUpExecutor( + const std::vector & parameters = {}, + bool separate_cmd_and_state_values = false) { setup_executor_ = true; - SetUpAndActivateTrajectoryController(executor_, true, parameters); + SetUpAndActivateTrajectoryController( + executor_, true, parameters, separate_cmd_and_state_values); SetUpActionClient(); @@ -472,15 +475,13 @@ TEST_P(TestTrajectoryActionsTestParameterized, test_goal_tolerances_fail) rclcpp::Parameter("constraints.joint3.goal", goal_tol), rclcpp::Parameter("constraints.goal_time", goal_time)}; - SetUpExecutor(params); + // separate command from states -> goal won't never be reached + bool separate_cmd_and_state_values = true; + SetUpExecutor(params, separate_cmd_and_state_values); SetUpControllerHardware(); - const double init_pos1 = joint_pos_[0]; - const double init_pos2 = joint_pos_[1]; - const double init_pos3 = joint_pos_[2]; - std::shared_future gh_future; - // send goal + // send goal; one point only -> command is directly set to reach this goal (no interpolation) { std::vector points; JointTrajectoryPoint point; @@ -502,14 +503,14 @@ TEST_P(TestTrajectoryActionsTestParameterized, test_goal_tolerances_fail) control_msgs::action::FollowJointTrajectory_Result::GOAL_TOLERANCE_VIOLATED, common_action_result_code_); - // run an update, it should be holding + // run an update, it should be holding the last received goal updateController(rclcpp::Duration::from_seconds(0.01)); if (traj_controller_->has_position_command_interface()) { - EXPECT_NEAR(init_pos1, joint_pos_[0], COMMON_THRESHOLD); - EXPECT_NEAR(init_pos2, joint_pos_[1], COMMON_THRESHOLD); - EXPECT_NEAR(init_pos3, joint_pos_[2], COMMON_THRESHOLD); + EXPECT_NEAR(4.0, joint_pos_[0], COMMON_THRESHOLD); + EXPECT_NEAR(5.0, joint_pos_[1], COMMON_THRESHOLD); + EXPECT_NEAR(6.0, joint_pos_[2], COMMON_THRESHOLD); } } diff --git a/joint_trajectory_controller/test/test_trajectory_controller.cpp b/joint_trajectory_controller/test/test_trajectory_controller.cpp index 714d3c8d49..0c8b3ae939 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller.cpp +++ b/joint_trajectory_controller/test/test_trajectory_controller.cpp @@ -1092,7 +1092,8 @@ TEST_P(TrajectoryControllerTestParameterized, test_ignore_old_trajectory) RCLCPP_INFO(traj_controller_->get_node()->get_logger(), "Sending new trajectory in the past"); // New trajectory will end before current time - rclcpp::Time new_traj_start = rclcpp::Clock().now() - delay - std::chrono::milliseconds(100); + rclcpp::Time new_traj_start = + rclcpp::Clock(RCL_STEADY_TIME).now() - delay - std::chrono::milliseconds(100); expected_actual.positions = {points_old[1].begin(), points_old[1].end()}; expected_desired = expected_actual; std::cout << "Sending old trajectory" << std::endl; @@ -1108,23 +1109,27 @@ TEST_P(TrajectoryControllerTestParameterized, test_ignore_partial_old_trajectory std::vector> points_old{{{2., 3., 4.}, {4., 5., 6.}}}; std::vector> points_new{{{-1., -2., -3.}, {-2., -4., -6.}}}; - + trajectory_msgs::msg::JointTrajectoryPoint expected_actual, expected_desired; const auto delay = std::chrono::milliseconds(500); builtin_interfaces::msg::Duration time_from_start{rclcpp::Duration(delay)}; + + // send points_old and wait to reach first point publish(time_from_start, points_old, rclcpp::Time()); - trajectory_msgs::msg::JointTrajectoryPoint expected_actual, expected_desired; expected_actual.positions = {points_old[0].begin(), points_old[0].end()}; expected_desired = expected_actual; // Check that we reached end of points_old[0]trajectory waitAndCompareState(expected_actual, expected_desired, executor, rclcpp::Duration(delay), 0.1); + // send points_new before the old trajectory is finished RCLCPP_INFO( traj_controller_->get_node()->get_logger(), "Sending new trajectory partially in the past"); // New trajectory first point is in the past, second is in the future - rclcpp::Time new_traj_start = rclcpp::Clock().now() - delay - std::chrono::milliseconds(100); - expected_actual.positions = {points_new[1].begin(), points_new[1].end()}; - expected_desired = expected_actual; + rclcpp::Time new_traj_start = + rclcpp::Clock(RCL_STEADY_TIME).now() - delay - std::chrono::milliseconds(100); publish(time_from_start, points_new, new_traj_start); + // it should not have accepted the new goal but finish the old one + expected_actual.positions = {points_old[1].begin(), points_old[1].end()}; + expected_desired.positions = {points_old[1].begin(), points_old[1].end()}; waitAndCompareState(expected_actual, expected_desired, executor, rclcpp::Duration(delay), 0.1); } @@ -1163,7 +1168,8 @@ TEST_P(TrajectoryControllerTestParameterized, test_execute_partial_traj_in_futur // Send partial trajectory starting after full trajecotry is complete RCLCPP_INFO(traj_controller_->get_node()->get_logger(), "Sending new trajectory in the future"); publish( - points_delay, partial_traj, rclcpp::Clock().now() + delay * 2, {}, partial_traj_velocities); + points_delay, partial_traj, rclcpp::Clock(RCL_STEADY_TIME).now() + delay * 2, {}, + partial_traj_velocities); // Wait until the end start and end of partial traj expected_actual.positions = {partial_traj.back()[0], partial_traj.back()[1], full_traj.back()[2]}; diff --git a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp index 9855341edf..97156f1a2e 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp +++ b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp @@ -366,13 +366,7 @@ class TrajectoryControllerTest : public ::testing::Test const auto end_time = start_time + wait_time; while (clock.now() < end_time) { - // TODO(christophfroehlich): use the node's clock here for internal comparison - // if using RCL_STEADY_TIME -> - // C++ exception with description - // "can't compare times with different time sources" thrown in the test body. - // traj_controller_->update(clock.now(), clock.now() - start_time); - // maybe we can set the node clock to use RCL_STEADY_TIME too? - traj_controller_->update(node_->get_clock()->now(), clock.now() - start_time); + traj_controller_->update(clock.now(), clock.now() - start_time); } } From f70c98649dfcddc620286b72abe868b1204c1391 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Mon, 17 Jul 2023 10:06:38 +0000 Subject: [PATCH 065/238] Match feature branches (#689) --- .github/workflows/rolling-binary-build-main.yml | 4 ++++ .github/workflows/rolling-binary-build-testing.yml | 4 ++++ .github/workflows/rolling-semi-binary-build-main.yml | 4 ++++ .github/workflows/rolling-semi-binary-build-testing.yml | 4 ++++ 4 files changed, 16 insertions(+) diff --git a/.github/workflows/rolling-binary-build-main.yml b/.github/workflows/rolling-binary-build-main.yml index b51bbabe29..793db5d7e5 100644 --- a/.github/workflows/rolling-binary-build-main.yml +++ b/.github/workflows/rolling-binary-build-main.yml @@ -6,9 +6,13 @@ on: workflow_dispatch: branches: - master + - '*feature*' + - '*feature/**' pull_request: branches: - master + - '*feature*' + - '*feature/**' push: branches: - master diff --git a/.github/workflows/rolling-binary-build-testing.yml b/.github/workflows/rolling-binary-build-testing.yml index a1db89b8d9..9b480d99c3 100644 --- a/.github/workflows/rolling-binary-build-testing.yml +++ b/.github/workflows/rolling-binary-build-testing.yml @@ -6,9 +6,13 @@ on: workflow_dispatch: branches: - master + - '*feature*' + - '*feature/**' pull_request: branches: - master + - '*feature*' + - '*feature/**' push: branches: - master diff --git a/.github/workflows/rolling-semi-binary-build-main.yml b/.github/workflows/rolling-semi-binary-build-main.yml index eca9483438..8b395e5163 100644 --- a/.github/workflows/rolling-semi-binary-build-main.yml +++ b/.github/workflows/rolling-semi-binary-build-main.yml @@ -5,9 +5,13 @@ on: workflow_dispatch: branches: - master + - '*feature*' + - '*feature/**' pull_request: branches: - master + - '*feature*' + - '*feature/**' push: branches: - master diff --git a/.github/workflows/rolling-semi-binary-build-testing.yml b/.github/workflows/rolling-semi-binary-build-testing.yml index 62214adae9..630881dc0a 100644 --- a/.github/workflows/rolling-semi-binary-build-testing.yml +++ b/.github/workflows/rolling-semi-binary-build-testing.yml @@ -5,9 +5,13 @@ on: workflow_dispatch: branches: - master + - '*feature*' + - '*feature/**' pull_request: branches: - master + - '*feature*' + - '*feature/**' push: branches: - master From ddb02e8e2422596b9870062eee30653387b58b5c Mon Sep 17 00:00:00 2001 From: Christoph Froehlich Date: Mon, 17 Jul 2023 10:06:38 +0000 Subject: [PATCH 066/238] Revert "[JTC] Command final waypoint identically when traj_point_active_ptr_ is nullptr (#682)" This reverts commit 9ce288b9cd9caabb1d29df6fb4e1baefa52781cb. --- .../src/joint_trajectory_controller.cpp | 102 +++++++++--------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/joint_trajectory_controller/src/joint_trajectory_controller.cpp b/joint_trajectory_controller/src/joint_trajectory_controller.cpp index 3b8f5f89bd..c870791daf 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller.cpp +++ b/joint_trajectory_controller/src/joint_trajectory_controller.cpp @@ -241,6 +241,57 @@ controller_interface::return_type JointTrajectoryController::update( } } + // set values for next hardware write() if tolerance is met + if (!tolerance_violated_while_moving && within_goal_time) + { + if (use_closed_loop_pid_adapter_) + { + // Update PIDs + for (auto i = 0ul; i < dof_; ++i) + { + tmp_command_[i] = (state_desired_.velocities[i] * ff_velocity_scale_[i]) + + pids_[i]->computeCommand( + state_error_.positions[i], state_error_.velocities[i], + (uint64_t)period.nanoseconds()); + } + } + + // set values for next hardware write() + if (has_position_command_interface_) + { + assign_interface_from_point(joint_command_interface_[0], state_desired_.positions); + } + if (has_velocity_command_interface_) + { + if (use_closed_loop_pid_adapter_) + { + assign_interface_from_point(joint_command_interface_[1], tmp_command_); + } + else + { + assign_interface_from_point(joint_command_interface_[1], state_desired_.velocities); + } + } + if (has_acceleration_command_interface_) + { + assign_interface_from_point(joint_command_interface_[2], state_desired_.accelerations); + } + if (has_effort_command_interface_) + { + if (use_closed_loop_pid_adapter_) + { + assign_interface_from_point(joint_command_interface_[3], tmp_command_); + } + else + { + assign_interface_from_point(joint_command_interface_[3], state_desired_.effort); + } + } + + // store the previous command. Used in open-loop control mode + last_commanded_state_ = state_desired_; + } + const auto active_goal = *rt_active_goal_.readFromRT(); if (active_goal) { @@ -308,57 +359,6 @@ controller_interface::return_type JointTrajectoryController::update( set_hold_position(); RCLCPP_ERROR(get_node()->get_logger(), "Holding position due to state tolerance violation"); } - - // set values for next hardware write() if tolerance is met - if (!tolerance_violated_while_moving && within_goal_time) - { - if (use_closed_loop_pid_adapter_) - { - // Update PIDs - for (auto i = 0ul; i < dof_; ++i) - { - tmp_command_[i] = (state_desired_.velocities[i] * ff_velocity_scale_[i]) + - pids_[i]->computeCommand( - state_error_.positions[i], state_error_.velocities[i], - (uint64_t)period.nanoseconds()); - } - } - - // set values for next hardware write() - if (has_position_command_interface_) - { - assign_interface_from_point(joint_command_interface_[0], state_desired_.positions); - } - if (has_velocity_command_interface_) - { - if (traj_point_active_ptr_ && use_closed_loop_pid_adapter_) - { - assign_interface_from_point(joint_command_interface_[1], tmp_command_); - } - else - { - assign_interface_from_point(joint_command_interface_[1], state_desired_.velocities); - } - } - if (has_acceleration_command_interface_) - { - assign_interface_from_point(joint_command_interface_[2], state_desired_.accelerations); - } - if (has_effort_command_interface_) - { - if (traj_point_active_ptr_ && use_closed_loop_pid_adapter_) - { - assign_interface_from_point(joint_command_interface_[3], tmp_command_); - } - else - { - assign_interface_from_point(joint_command_interface_[3], state_desired_.effort); - } - } - - // store the previous command. Used in open-loop control mode - last_commanded_state_ = state_desired_; - } } } From ff6e81d45dee018cd852e94978bf1c5627b0c3fd Mon Sep 17 00:00:00 2001 From: Christoph Froehlich Date: Mon, 17 Jul 2023 10:06:38 +0000 Subject: [PATCH 067/238] Add test for velocity error with effort cmd interface (#690) --- .../test/test_trajectory_controller.cpp | 90 +++++++++++++++++++ .../test/test_trajectory_controller_utils.hpp | 25 ++++-- 2 files changed, 107 insertions(+), 8 deletions(-) diff --git a/joint_trajectory_controller/test/test_trajectory_controller.cpp b/joint_trajectory_controller/test/test_trajectory_controller.cpp index 0c8b3ae939..bd547dc6be 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller.cpp +++ b/joint_trajectory_controller/test/test_trajectory_controller.cpp @@ -673,6 +673,96 @@ TEST_P(TrajectoryControllerTestParameterized, position_error_normalized) executor.cancel(); } +/** + * @brief check if use_closed_loop_pid is active + */ +TEST_P(TrajectoryControllerTestParameterized, use_closed_loop_pid) +{ + rclcpp::executors::MultiThreadedExecutor executor; + + SetUpAndActivateTrajectoryController(executor); + + if ( + (traj_controller_->has_velocity_command_interface() && + !traj_controller_->has_position_command_interface() && + !traj_controller_->has_effort_command_interface() && + !traj_controller_->has_acceleration_command_interface() && + !traj_controller_->is_open_loop()) || + traj_controller_->has_effort_command_interface()) + { + EXPECT_TRUE(traj_controller_->use_closed_loop_pid_adapter()); + } +} + +/** + * @brief check if velocity error is calculated correctly + */ +TEST_P(TrajectoryControllerTestParameterized, velocity_error) +{ + rclcpp::executors::MultiThreadedExecutor executor; + SetUpAndActivateTrajectoryController(executor, true, {}, true); + subscribeToState(); + + size_t n_joints = joint_names_.size(); + + // send msg + constexpr auto FIRST_POINT_TIME = std::chrono::milliseconds(250); + builtin_interfaces::msg::Duration time_from_start{rclcpp::Duration(FIRST_POINT_TIME)}; + // *INDENT-OFF* + std::vector> points_positions{ + {{3.3, 4.4, 6.6}}, {{7.7, 8.8, 9.9}}, {{10.10, 11.11, 12.12}}}; + std::vector> points_velocities{ + {{0.1, 0.1, 0.1}}, {{0.2, 0.2, 0.2}}, {{0.3, 0.3, 0.3}}}; + // *INDENT-ON* + publish(time_from_start, points_positions, rclcpp::Time(), {}, points_velocities); + traj_controller_->wait_for_trajectory(executor); + + // first update + updateController(rclcpp::Duration(FIRST_POINT_TIME)); + + // Spin to receive latest state + executor.spin_some(); + auto state_msg = getState(); + ASSERT_TRUE(state_msg); + + // has the msg the correct vector sizes? + EXPECT_EQ(n_joints, state_msg->reference.positions.size()); + EXPECT_EQ(n_joints, state_msg->feedback.positions.size()); + EXPECT_EQ(n_joints, state_msg->error.positions.size()); + if (traj_controller_->has_velocity_state_interface()) + { + EXPECT_EQ(n_joints, state_msg->reference.velocities.size()); + EXPECT_EQ(n_joints, state_msg->feedback.velocities.size()); + EXPECT_EQ(n_joints, state_msg->error.velocities.size()); + } + if (traj_controller_->has_acceleration_state_interface()) + { + EXPECT_EQ(n_joints, state_msg->reference.accelerations.size()); + EXPECT_EQ(n_joints, state_msg->feedback.accelerations.size()); + EXPECT_EQ(n_joints, state_msg->error.accelerations.size()); + } + + // no change in state interface should happen + if (traj_controller_->has_velocity_state_interface()) + { + EXPECT_EQ(state_msg->feedback.velocities, INITIAL_VEL_JOINTS); + } + // is the velocity error correct? + if ( + traj_controller_->use_closed_loop_pid_adapter() // always needed for PID controller + || (traj_controller_->has_velocity_state_interface() && + traj_controller_->has_velocity_command_interface())) + { + // don't check against a value, because spline intepolation might overshoot depending on + // interface combinations + EXPECT_GE(state_msg->error.velocities[0], points_velocities[0][0]); + EXPECT_GE(state_msg->error.velocities[1], points_velocities[0][1]); + EXPECT_GE(state_msg->error.velocities[2], points_velocities[0][2]); + } + + executor.cancel(); +} + /** * @brief test_jumbled_joint_order Test sending trajectories with a joint order different from * internal controller order diff --git a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp index 97156f1a2e..4dd5f1a780 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp +++ b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp @@ -105,6 +105,11 @@ class TestableJointTrajectoryController { return last_commanded_state_; } + bool has_position_state_interface() { return has_position_state_interface_; } + + bool has_velocity_state_interface() { return has_velocity_state_interface_; } + + bool has_acceleration_state_interface() { return has_acceleration_state_interface_; } bool has_position_command_interface() { return has_position_command_interface_; } @@ -116,6 +121,8 @@ class TestableJointTrajectoryController bool use_closed_loop_pid_adapter() { return use_closed_loop_pid_adapter_; } + bool is_open_loop() { return params_.open_loop_control; } + rclcpp::WaitSet joint_cmd_sub_wait_set_; }; @@ -294,13 +301,14 @@ class TrajectoryControllerTest : public ::testing::Test /// Publish trajectory msgs with multiple points /** * delay_btwn_points - delay between each points - * points - vector of trajectories. One point per controlled joint + * points_positions - vector of trajectory-positions. One point per controlled joint * joint_names - names of joints, if empty, will use joint_names_ up to the number of provided * points + * points - vector of trajectory-velocities. One point per controlled joint */ void publish( const builtin_interfaces::msg::Duration & delay_btwn_points, - const std::vector> & points, rclcpp::Time start_time, + const std::vector> & points_positions, rclcpp::Time start_time, const std::vector & joint_names = {}, const std::vector> & points_velocities = {}) { @@ -320,14 +328,15 @@ class TrajectoryControllerTest : public ::testing::Test trajectory_msgs::msg::JointTrajectory traj_msg; if (joint_names.empty()) { - traj_msg.joint_names = {joint_names_.begin(), joint_names_.begin() + points[0].size()}; + traj_msg.joint_names = { + joint_names_.begin(), joint_names_.begin() + points_positions[0].size()}; } else { traj_msg.joint_names = joint_names; } traj_msg.header.stamp = start_time; - traj_msg.points.resize(points.size()); + traj_msg.points.resize(points_positions.size()); builtin_interfaces::msg::Duration duration_msg; duration_msg.sec = delay_btwn_points.sec; @@ -335,14 +344,14 @@ class TrajectoryControllerTest : public ::testing::Test rclcpp::Duration duration(duration_msg); rclcpp::Duration duration_total(duration_msg); - for (size_t index = 0; index < points.size(); ++index) + for (size_t index = 0; index < points_positions.size(); ++index) { traj_msg.points[index].time_from_start = duration_total; - traj_msg.points[index].positions.resize(points[index].size()); - for (size_t j = 0; j < points[index].size(); ++j) + traj_msg.points[index].positions.resize(points_positions[index].size()); + for (size_t j = 0; j < points_positions[index].size(); ++j) { - traj_msg.points[index].positions[j] = points[index][j]; + traj_msg.points[index].positions[j] = points_positions[index][j]; } duration_total = duration_total + duration; } From 12d46f20f666fab3f74d5bb33841a7bcc1857299 Mon Sep 17 00:00:00 2001 From: Lars Tingelstad Date: Mon, 17 Jul 2023 10:06:38 +0000 Subject: [PATCH 068/238] Compute velocity errors when using an effort command interface (#679) (cherry picked from commit 2e0da5d2f0a8462f735e44c5b5ad0a58fe11aedb) --- .../src/joint_trajectory_controller.cpp | 4 +++- joint_trajectory_controller/test/test_trajectory_actions.cpp | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/joint_trajectory_controller/src/joint_trajectory_controller.cpp b/joint_trajectory_controller/src/joint_trajectory_controller.cpp index c870791daf..153515d089 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller.cpp +++ b/joint_trajectory_controller/src/joint_trajectory_controller.cpp @@ -133,7 +133,9 @@ controller_interface::return_type JointTrajectoryController::update( { error.positions[index] = desired.positions[index] - current.positions[index]; } - if (has_velocity_state_interface_ && has_velocity_command_interface_) + if ( + has_velocity_state_interface_ && + (has_velocity_command_interface_ || has_effort_command_interface_)) { error.velocities[index] = desired.velocities[index] - current.velocities[index]; } diff --git a/joint_trajectory_controller/test/test_trajectory_actions.cpp b/joint_trajectory_controller/test/test_trajectory_actions.cpp index 085c20cacd..6482b8e921 100644 --- a/joint_trajectory_controller/test/test_trajectory_actions.cpp +++ b/joint_trajectory_controller/test/test_trajectory_actions.cpp @@ -304,7 +304,7 @@ TEST_P(TestTrajectoryActionsTestParameterized, test_success_multi_point_sendgoal /** * Makes sense with position command interface only, * because no integration to position state interface is implemented -*/ + */ TEST_F(TestTrajectoryActions, test_goal_tolerances_single_point_success) { // set tolerance parameters @@ -349,7 +349,7 @@ TEST_F(TestTrajectoryActions, test_goal_tolerances_single_point_success) /** * Makes sense with position command interface only, * because no integration to position state interface is implemented -*/ + */ TEST_F(TestTrajectoryActions, test_goal_tolerances_multi_point_success) { // set tolerance parameters From 99b67d73dc8223b0aca412e5d546dd26dd56d0de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Mon, 17 Jul 2023 10:06:38 +0000 Subject: [PATCH 069/238] [JTC] Reject trajectories with nonzero terminal velocity (#567) * Reject receiving trajectory of last velocity point is non-zero * Update docs * Add tests * Change to parameterized test * Rename parameter * not true -> false --------- Co-authored-by: Bence Magyar --- joint_trajectory_controller/doc/userdoc.rst | 5 + .../src/joint_trajectory_controller.cpp | 23 ++++ ...oint_trajectory_controller_parameters.yaml | 5 + .../test/test_trajectory_actions.cpp | 124 ++++++++++++++++++ .../test/test_trajectory_controller.cpp | 16 ++- 5 files changed, 170 insertions(+), 3 deletions(-) diff --git a/joint_trajectory_controller/doc/userdoc.rst b/joint_trajectory_controller/doc/userdoc.rst index 7529a60918..b04f1109e3 100644 --- a/joint_trajectory_controller/doc/userdoc.rst +++ b/joint_trajectory_controller/doc/userdoc.rst @@ -175,6 +175,11 @@ open_loop_control (boolean) Default: false +allow_nonzero_velocity_at_trajectory_end (boolean) + If false, the last velocity point has to be zero or the goal will be rejected. + + Default: true + constraints (structure) Default values for tolerances if no explicit values are states in JointTrajectory message. diff --git a/joint_trajectory_controller/src/joint_trajectory_controller.cpp b/joint_trajectory_controller/src/joint_trajectory_controller.cpp index 153515d089..dccb9fceff 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller.cpp +++ b/joint_trajectory_controller/src/joint_trajectory_controller.cpp @@ -64,6 +64,15 @@ controller_interface::CallbackReturn JointTrajectoryController::on_init() return CallbackReturn::ERROR; } + // TODO(christophfroehlich): remove deprecation warning + if (params_.allow_nonzero_velocity_at_trajectory_end) + { + RCLCPP_WARN( + get_node()->get_logger(), + "[Deprecated]: \"allow_nonzero_velocity_at_trajectory_end\" is set to " + "true. The default behavior will change to false."); + } + return CallbackReturn::SUCCESS; } @@ -1321,6 +1330,20 @@ bool JointTrajectoryController::validate_trajectory_msg( } } + if (!params_.allow_nonzero_velocity_at_trajectory_end) + { + for (size_t i = 0; i < trajectory.points.back().velocities.size(); ++i) + { + if (trajectory.points.back().velocities.at(i) != 0.) + { + RCLCPP_ERROR( + get_node()->get_logger(), "Velocity of last trajectory point of joint %s is not zero: %f", + trajectory.joint_names.at(i).c_str(), trajectory.points.back().velocities.at(i)); + return false; + } + } + } + rclcpp::Duration previous_traj_time(0ms); for (size_t i = 0; i < trajectory.points.size(); ++i) { diff --git a/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml b/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml index 90ca12a268..77eaf3537f 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml +++ b/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml @@ -66,6 +66,11 @@ joint_trajectory_controller: one_of<>: [["splines", "none"]], } } + allow_nonzero_velocity_at_trajectory_end: { + type: bool, + default_value: true, + description: "If false, the last velocity point has to be zero or the goal will be rejected", + } gains: __map_joints: p: { diff --git a/joint_trajectory_controller/test/test_trajectory_actions.cpp b/joint_trajectory_controller/test/test_trajectory_actions.cpp index 6482b8e921..fdea551c30 100644 --- a/joint_trajectory_controller/test/test_trajectory_actions.cpp +++ b/joint_trajectory_controller/test/test_trajectory_actions.cpp @@ -616,6 +616,130 @@ TEST_P(TestTrajectoryActionsTestParameterized, test_cancel_hold_position) } } +TEST_P(TestTrajectoryActionsTestParameterized, test_allow_nonzero_velocity_at_trajectory_end_true) +{ + std::vector params = { + rclcpp::Parameter("allow_nonzero_velocity_at_trajectory_end", true)}; + SetUpExecutor(params); + SetUpControllerHardware(); + + std::shared_future gh_future; + // send goal with nonzero last velocities + { + std::vector points; + JointTrajectoryPoint point1; + point1.time_from_start = rclcpp::Duration::from_seconds(0.0); + point1.positions.resize(joint_names_.size()); + point1.velocities.resize(joint_names_.size()); + + point1.positions[0] = 4.0; + point1.positions[1] = 5.0; + point1.positions[2] = 6.0; + point1.velocities[0] = 4.0; + point1.velocities[1] = 5.0; + point1.velocities[2] = 6.0; + points.push_back(point1); + + JointTrajectoryPoint point2; + point2.time_from_start = rclcpp::Duration::from_seconds(0.1); + point2.positions.resize(joint_names_.size()); + point2.velocities.resize(joint_names_.size()); + + point2.positions[0] = 7.0; + point2.positions[1] = 8.0; + point2.positions[2] = 9.0; + point2.velocities[0] = 4.0; + point2.velocities[1] = 5.0; + point2.velocities[2] = 6.0; + points.push_back(point2); + + gh_future = sendActionGoal(points, 1.0, goal_options_); + } + controller_hw_thread_.join(); + + // will be accepted despite nonzero last point + EXPECT_TRUE(gh_future.get()); + EXPECT_EQ(rclcpp_action::ResultCode::SUCCEEDED, common_resultcode_); +} + +TEST_P(TestTrajectoryActionsTestParameterized, test_allow_nonzero_velocity_at_trajectory_end_false) +{ + std::vector params = { + rclcpp::Parameter("allow_nonzero_velocity_at_trajectory_end", false)}; + SetUpExecutor(params); + SetUpControllerHardware(); + + std::shared_future gh_future; + // send goal with nonzero last velocities + { + std::vector points; + JointTrajectoryPoint point1; + point1.time_from_start = rclcpp::Duration::from_seconds(0.0); + point1.positions.resize(joint_names_.size()); + point1.velocities.resize(joint_names_.size()); + + point1.positions[0] = 4.0; + point1.positions[1] = 5.0; + point1.positions[2] = 6.0; + point1.velocities[0] = 4.0; + point1.velocities[1] = 5.0; + point1.velocities[2] = 6.0; + points.push_back(point1); + + JointTrajectoryPoint point2; + point2.time_from_start = rclcpp::Duration::from_seconds(0.1); + point2.positions.resize(joint_names_.size()); + point2.velocities.resize(joint_names_.size()); + + point2.positions[0] = 7.0; + point2.positions[1] = 8.0; + point2.positions[2] = 9.0; + point2.velocities[0] = 4.0; + point2.velocities[1] = 5.0; + point2.velocities[2] = 6.0; + points.push_back(point2); + + gh_future = sendActionGoal(points, 1.0, goal_options_); + } + controller_hw_thread_.join(); + + EXPECT_FALSE(gh_future.get()); + + // send goal with last velocity being zero + { + std::vector points; + JointTrajectoryPoint point1; + point1.time_from_start = rclcpp::Duration::from_seconds(0.0); + point1.positions.resize(joint_names_.size()); + point1.velocities.resize(joint_names_.size()); + + point1.positions[0] = 4.0; + point1.positions[1] = 5.0; + point1.positions[2] = 6.0; + point1.velocities[0] = 4.0; + point1.velocities[1] = 5.0; + point1.velocities[2] = 6.0; + points.push_back(point1); + + JointTrajectoryPoint point2; + point2.time_from_start = rclcpp::Duration::from_seconds(0.1); + point2.positions.resize(joint_names_.size()); + point2.velocities.resize(joint_names_.size()); + + point2.positions[0] = 7.0; + point2.positions[1] = 8.0; + point2.positions[2] = 9.0; + point2.velocities[0] = 0.0; + point2.velocities[1] = 0.0; + point2.velocities[2] = 0.0; + points.push_back(point2); + + gh_future = sendActionGoal(points, 1.0, goal_options_); + } + + EXPECT_TRUE(gh_future.get()); +} + // position controllers INSTANTIATE_TEST_SUITE_P( PositionTrajectoryControllersActions, TestTrajectoryActionsTestParameterized, diff --git a/joint_trajectory_controller/test/test_trajectory_controller.cpp b/joint_trajectory_controller/test/test_trajectory_controller.cpp index bd547dc6be..d22498a795 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller.cpp +++ b/joint_trajectory_controller/test/test_trajectory_controller.cpp @@ -65,6 +65,8 @@ TEST_P(TrajectoryControllerTestParameterized, configure_state_ignores_commands) { rclcpp::executors::MultiThreadedExecutor executor; SetUpTrajectoryController(executor); + traj_controller_->get_node()->set_parameter( + rclcpp::Parameter("allow_nonzero_velocity_at_trajectory_end", true)); // const auto future_handle_ = std::async(std::launch::async, spin, &executor); @@ -202,7 +204,9 @@ TEST_P(TrajectoryControllerTestParameterized, activate) TEST_P(TrajectoryControllerTestParameterized, cleanup) { rclcpp::executors::MultiThreadedExecutor executor; - SetUpAndActivateTrajectoryController(executor); + std::vector params = { + rclcpp::Parameter("allow_nonzero_velocity_at_trajectory_end", true)}; + SetUpAndActivateTrajectoryController(executor, true, params); // send msg constexpr auto FIRST_POINT_TIME = std::chrono::milliseconds(250); @@ -259,6 +263,8 @@ TEST_P(TrajectoryControllerTestParameterized, correct_initialization_using_param { rclcpp::executors::MultiThreadedExecutor executor; SetUpTrajectoryController(executor, false); + traj_controller_->get_node()->set_parameter( + rclcpp::Parameter("allow_nonzero_velocity_at_trajectory_end", true)); // This call is replacing the way parameters are set via launch SetParameters(); @@ -450,7 +456,9 @@ TEST_P(TrajectoryControllerTestParameterized, position_error_not_normalized) { rclcpp::executors::MultiThreadedExecutor executor; constexpr double k_p = 10.0; - SetUpAndActivateTrajectoryController(executor, true, {}, true, k_p, 0.0, false); + std::vector params = { + rclcpp::Parameter("allow_nonzero_velocity_at_trajectory_end", true)}; + SetUpAndActivateTrajectoryController(executor, true, params, true, k_p, 0.0, false); subscribeToState(); size_t n_joints = joint_names_.size(); @@ -557,7 +565,9 @@ TEST_P(TrajectoryControllerTestParameterized, position_error_normalized) { rclcpp::executors::MultiThreadedExecutor executor; constexpr double k_p = 10.0; - SetUpAndActivateTrajectoryController(executor, true, {}, true, k_p, 0.0, true); + std::vector params = { + rclcpp::Parameter("allow_nonzero_velocity_at_trajectory_end", true)}; + SetUpAndActivateTrajectoryController(executor, true, params, true, k_p, 0.0, true); subscribeToState(); size_t n_joints = joint_names_.size(); From 88c34631e4964eafca4674b574231f569151cc74 Mon Sep 17 00:00:00 2001 From: gwalck Date: Mon, 17 Jul 2023 10:06:38 +0000 Subject: [PATCH 070/238] Fixed update period computation in test (#693) --- .../test/test_trajectory_controller_utils.hpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp index 4dd5f1a780..5ec0f4f29e 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp +++ b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp @@ -373,9 +373,13 @@ class TrajectoryControllerTest : public ::testing::Test auto clock = rclcpp::Clock(RCL_STEADY_TIME); const auto start_time = clock.now(); const auto end_time = start_time + wait_time; + auto previous_time = start_time; + while (clock.now() < end_time) { - traj_controller_->update(clock.now(), clock.now() - start_time); + auto now = clock.now(); + traj_controller_->update(now, now - previous_time); + previous_time = now; } } From e49c540d4c90c9ba0bb0620c76abf8afac84dbb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Mon, 17 Jul 2023 10:06:38 +0000 Subject: [PATCH 071/238] Fix namespace for parameter traits(#703) --- .../joint_trajectory_controller/validate_jtc_parameters.hpp | 5 ++--- .../src/joint_trajectory_controller_parameters.yaml | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/joint_trajectory_controller/include/joint_trajectory_controller/validate_jtc_parameters.hpp b/joint_trajectory_controller/include/joint_trajectory_controller/validate_jtc_parameters.hpp index fc6319fabf..5a656e7754 100644 --- a/joint_trajectory_controller/include/joint_trajectory_controller/validate_jtc_parameters.hpp +++ b/joint_trajectory_controller/include/joint_trajectory_controller/validate_jtc_parameters.hpp @@ -18,12 +18,11 @@ #include #include -#include "parameter_traits/parameter_traits.hpp" #include "rclcpp/parameter.hpp" #include "rsl/algorithm.hpp" #include "tl_expected/expected.hpp" -namespace parameter_traits +namespace joint_trajectory_controller { tl::expected command_interface_type_combinations( rclcpp::Parameter const & parameter) @@ -95,6 +94,6 @@ tl::expected state_interface_type_combinations( return {}; } -} // namespace parameter_traits +} // namespace joint_trajectory_controller #endif // JOINT_TRAJECTORY_CONTROLLER__VALIDATE_JTC_PARAMETERS_HPP_ diff --git a/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml b/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml index 77eaf3537f..5627f1d8f5 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml +++ b/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml @@ -22,7 +22,7 @@ joint_trajectory_controller: validation: { unique<>: null, subset_of<>: [["position", "velocity", "acceleration", "effort",]], - command_interface_type_combinations: null, + "joint_trajectory_controller::command_interface_type_combinations": null, } } state_interfaces: { @@ -32,7 +32,7 @@ joint_trajectory_controller: validation: { unique<>: null, subset_of<>: [["position", "velocity", "acceleration",]], - state_interface_type_combinations: null, + "joint_trajectory_controller::state_interface_type_combinations": null, } } allow_partial_joints_goal: { From 259d3d89c10156c7e1dac9cdcd42e0b84e0f6118 Mon Sep 17 00:00:00 2001 From: Christoph Froehlich Date: Mon, 17 Jul 2023 10:06:38 +0000 Subject: [PATCH 072/238] Don't test update after cleanup --- .../test/test_trajectory_controller.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/joint_trajectory_controller/test/test_trajectory_controller.cpp b/joint_trajectory_controller/test/test_trajectory_controller.cpp index d22498a795..132a74c6fd 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller.cpp +++ b/joint_trajectory_controller/test/test_trajectory_controller.cpp @@ -230,16 +230,6 @@ TEST_P(TrajectoryControllerTestParameterized, cleanup) state = traj_controller_->get_node()->cleanup(); ASSERT_EQ(State::PRIMARY_STATE_UNCONFIGURED, state.id()); - // update for 0.25 seconds - // TODO(anyone): should the controller even allow calling update() when it is not active? - // update loop receives a new msg and updates accordingly - updateController(rclcpp::Duration::from_seconds(0.25)); - - // should be home pose again - EXPECT_NEAR(INITIAL_POS_JOINT1, joint_pos_[0], COMMON_THRESHOLD); - EXPECT_NEAR(INITIAL_POS_JOINT2, joint_pos_[1], COMMON_THRESHOLD); - EXPECT_NEAR(INITIAL_POS_JOINT3, joint_pos_[2], COMMON_THRESHOLD); - executor.cancel(); } From 126b95cc8b913175b0d65578ac9e7b2292289e53 Mon Sep 17 00:00:00 2001 From: Christoph Froehlich Date: Mon, 17 Jul 2023 10:06:38 +0000 Subject: [PATCH 073/238] Remove reactivation test from ROS 1 --- .../test/test_trajectory_controller.cpp | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/joint_trajectory_controller/test/test_trajectory_controller.cpp b/joint_trajectory_controller/test/test_trajectory_controller.cpp index 132a74c6fd..d56a2c9b0c 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller.cpp +++ b/joint_trajectory_controller/test/test_trajectory_controller.cpp @@ -317,25 +317,12 @@ TEST_P(TrajectoryControllerTestParameterized, correct_initialization_using_param // reactivated // wait so controller process the third point when reactivated std::this_thread::sleep_for(std::chrono::milliseconds(3000)); - // TODO(anyone) test copied from ROS 1: it fails now! - // should the old trajectory really be processed after reactivation? -#if 0 ActivateTrajectoryController(); state = traj_controller_->get_state(); ASSERT_EQ(state.id(), State::PRIMARY_STATE_ACTIVE); - updateController(rclcpp::Duration::from_seconds(0.5)); - // traj_controller_->update( - // rclcpp::Time(static_cast(0.75 * 1e9)), rclcpp::Duration::from_seconds(0.01)); - - // change in hw position to 3rd point - if (traj_controller_->has_position_command_interface()) - { - EXPECT_NEAR(10.10, joint_pos_[0], allowed_delta); - EXPECT_NEAR(11.11, joint_pos_[1], allowed_delta); - EXPECT_NEAR(12.12, joint_pos_[2], allowed_delta); - } -#endif + // TODO(christophfroehlich) add test if there is no active trajectory after + // reactivation once #558 or #609 got merged (needs methods for TestableJointTrajectoryController) executor.cancel(); } From 8436ed549becce0b694dfe23cfa053436f2b6d42 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 17 Jul 2023 20:06:00 +0200 Subject: [PATCH 074/238] Update external ros2 controller setup link (backport #695) (#707) * Update external ros2 controller setup link (cherry picked from commit 9975ec10ef24761e2373fc77362996c804b665c4) * Update doc/writing_new_controller.rst (cherry picked from commit dd453b2f210c8b6cc34825915b32b2d34d887e91) --------- Co-authored-by: maurice Co-authored-by: Dr. Denis --- doc/writing_new_controller.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/writing_new_controller.rst b/doc/writing_new_controller.rst index 65ffc6795b..4d8c3752ae 100644 --- a/doc/writing_new_controller.rst +++ b/doc/writing_new_controller.rst @@ -138,4 +138,4 @@ That's it! Enjoy writing great controllers! Useful External References --------------------------- -- `Templates and scripts for generating controllers shell `_ +- `Templates and scripts for generating controllers shell `_ From 317969489c0477bf8a1e45fcd46ad55cc1d22a90 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Jul 2023 07:05:09 +0100 Subject: [PATCH 075/238] Bump actions/setup-python from 4.6.1 to 4.7.0 (#710) --- .github/workflows/ci-format.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-format.yml b/.github/workflows/ci-format.yml index 8f5be014c5..8955904bea 100644 --- a/.github/workflows/ci-format.yml +++ b/.github/workflows/ci-format.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: actions/setup-python@v4.6.1 + - uses: actions/setup-python@v4.7.0 with: python-version: '3.10' - name: Install system hooks From 3c7072e79c9f3c0c2ea4769abaf2dc7f47ef87ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Tue, 18 Jul 2023 18:14:01 +0200 Subject: [PATCH 076/238] Activate AdmittanceControllerTestParameterizedInvalidParameters (#711) --- .../test/test_admittance_controller.cpp | 16 ++++++++++++---- .../test/test_admittance_controller.hpp | 10 ++++++++-- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/admittance_controller/test/test_admittance_controller.cpp b/admittance_controller/test/test_admittance_controller.cpp index f1c3de8abd..fe1d3214e0 100644 --- a/admittance_controller/test/test_admittance_controller.cpp +++ b/admittance_controller/test/test_admittance_controller.cpp @@ -65,10 +65,18 @@ INSTANTIATE_TEST_SUITE_P( // wrong length selected axes std::make_tuple( std::string("admittance.selected_axes"), - rclcpp::ParameterValue(std::vector() = {1, 2, 3})), - // invalid robot description - std::make_tuple( - std::string("robot_description"), rclcpp::ParameterValue(std::string() = "bad_robot")))); + rclcpp::ParameterValue(std::vector() = {1, 2, 3})) + // invalid robot description. + // TODO(anyone): deactivated, because SetUpController returns SUCCESS here? + // ,std::make_tuple( + // std::string("robot_description"), rclcpp::ParameterValue(std::string() = "bad_robot"))) + )); + +// Test on_init returns ERROR when a parameter is invalid +TEST_P(AdmittanceControllerTestParameterizedInvalidParameters, invalid_parameters) +{ + ASSERT_EQ(SetUpController(), controller_interface::return_type::ERROR); +} TEST_F(AdmittanceControllerTest, all_parameters_set_configure_success) { diff --git a/admittance_controller/test/test_admittance_controller.hpp b/admittance_controller/test/test_admittance_controller.hpp index d6c95d2e1c..8888cd700a 100644 --- a/admittance_controller/test/test_admittance_controller.hpp +++ b/admittance_controller/test/test_admittance_controller.hpp @@ -456,9 +456,15 @@ class AdmittanceControllerTestParameterizedInvalidParameters static void TearDownTestCase() { AdmittanceControllerTest::TearDownTestCase(); } protected: - void SetUpController() + controller_interface::return_type SetUpController() { - AdmittanceControllerTest::SetUpController("test_admittance_controller"); + auto param_name = std::get<0>(GetParam()); + auto param_value = std::get<1>(GetParam()); + std::vector parameter_overrides; + rclcpp::Parameter param(param_name, param_value); + parameter_overrides.push_back(param); + return AdmittanceControllerTest::SetUpController( + "test_admittance_controller", parameter_overrides); } }; From 72bdf88089d4b9158d4df1bc26968a61f7835e84 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Tue, 18 Jul 2023 19:14:52 +0100 Subject: [PATCH 077/238] Update changelogs --- ackermann_steering_controller/CHANGELOG.rst | 3 +++ admittance_controller/CHANGELOG.rst | 5 +++++ bicycle_steering_controller/CHANGELOG.rst | 3 +++ diff_drive_controller/CHANGELOG.rst | 3 +++ effort_controllers/CHANGELOG.rst | 3 +++ force_torque_sensor_broadcaster/CHANGELOG.rst | 3 +++ forward_command_controller/CHANGELOG.rst | 3 +++ gripper_controllers/CHANGELOG.rst | 3 +++ imu_sensor_broadcaster/CHANGELOG.rst | 3 +++ joint_state_broadcaster/CHANGELOG.rst | 3 +++ joint_trajectory_controller/CHANGELOG.rst | 16 ++++++++++++++++ position_controllers/CHANGELOG.rst | 3 +++ ros2_controllers/CHANGELOG.rst | 3 +++ ros2_controllers_test_nodes/CHANGELOG.rst | 3 +++ rqt_joint_trajectory_controller/CHANGELOG.rst | 3 +++ steering_controllers_library/CHANGELOG.rst | 3 +++ tricycle_controller/CHANGELOG.rst | 3 +++ tricycle_steering_controller/CHANGELOG.rst | 3 +++ velocity_controllers/CHANGELOG.rst | 3 +++ 19 files changed, 72 insertions(+) diff --git a/ackermann_steering_controller/CHANGELOG.rst b/ackermann_steering_controller/CHANGELOG.rst index 6d5626ccd0..a07f3372b6 100644 --- a/ackermann_steering_controller/CHANGELOG.rst +++ b/ackermann_steering_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ackermann_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.11.0 (2023-06-24) ------------------- * Added -Wconversion flag and fix warnings (`#667 `_) diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index 56feda699a..eb56a4bcd2 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Activate AdmittanceControllerTestParameterizedInvalidParameters (`#711 `_) +* Contributors: Christoph Fröhlich + 3.11.0 (2023-06-24) ------------------- * Fix cpplint (`#681 `_) diff --git a/bicycle_steering_controller/CHANGELOG.rst b/bicycle_steering_controller/CHANGELOG.rst index 1b7a761aeb..0b9b4abb2b 100644 --- a/bicycle_steering_controller/CHANGELOG.rst +++ b/bicycle_steering_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package bicycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.11.0 (2023-06-24) ------------------- * Added -Wconversion flag and fix warnings (`#667 `_) diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index fddec6b53d..c99e27900d 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.11.0 (2023-06-24) ------------------- * Added -Wconversion flag and fix warnings (`#667 `_) diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index b21b0c547d..e1cf1be3d9 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.11.0 (2023-06-24) ------------------- * Added -Wconversion flag and fix warnings (`#667 `_) diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index de8adc57f1..d10ebf1b6e 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.11.0 (2023-06-24) ------------------- * Broadcaster parameters (`#650 `_) diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index 796b01c03f..af62c3d352 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.11.0 (2023-06-24) ------------------- * Added -Wconversion flag and fix warnings (`#667 `_) diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index e4cb8cad5e..25dd4ec05c 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.11.0 (2023-06-24) ------------------- * Added -Wconversion flag and fix warnings (`#667 `_) diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index 5252da9c44..06f9003e1f 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.11.0 (2023-06-24) ------------------- * Broadcaster parameters (`#650 `_) diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index 9337cd24b2..ec928921ce 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.11.0 (2023-06-24) ------------------- * Added -Wconversion flag and fix warnings (`#667 `_) diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index 354516fbb2..6bf514fa9f 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,22 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Remove reactivation test from ROS 1 +* Don't test update after cleanup +* Fix namespace for parameter traits(`#703 `_) +* Fixed update period computation in test (`#693 `_) +* [JTC] Reject trajectories with nonzero terminal velocity (`#567 `_) +* Compute velocity errors when using an effort command interface (`#679 `_) +* Add test for velocity error with effort cmd interface (`#690 `_) +* Revert "[JTC] Command final waypoint identically when traj_point_active_ptr\_ is nullptr (`#682 `_)" +* [JTC] Fix time sources and wrong checks in tests (`#686 `_) +* Increase action tests timeout (`#680 `_) +* [JTC] Extend tests (`#612 `_) +* [JTC] Command final waypoint identically when traj_point_active_ptr\_ is nullptr (`#682 `_) +* Contributors: Christoph Fröhlich, Ethan Gordon, Lars Tingelstad, gwalck, Bence Magyar + 3.11.0 (2023-06-24) ------------------- * jtc: fix minor typo in traj validation error msg (`#674 `_) diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index 299b7b7de7..047540cd7e 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.11.0 (2023-06-24) ------------------- * Added -Wconversion flag and fix warnings (`#667 `_) diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index 4ca34fc0a5..e53ccfe66b 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.11.0 (2023-06-24) ------------------- diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index f1a00b9bf4..a0ebfba35d 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.11.0 (2023-06-24) ------------------- * Removes deprecated if-branch (`#653 `_) diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index 648b093d2f..067ba3be8b 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.11.0 (2023-06-24) ------------------- diff --git a/steering_controllers_library/CHANGELOG.rst b/steering_controllers_library/CHANGELOG.rst index 596f1fe9d3..e97c21bf78 100644 --- a/steering_controllers_library/CHANGELOG.rst +++ b/steering_controllers_library/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package steering_controllers_library ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.11.0 (2023-06-24) ------------------- * Added -Wconversion flag and fix warnings (`#667 `_) diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index f58f8f1539..67322908ce 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.11.0 (2023-06-24) ------------------- * Added -Wconversion flag and fix warnings (`#667 `_) diff --git a/tricycle_steering_controller/CHANGELOG.rst b/tricycle_steering_controller/CHANGELOG.rst index 3782216e48..5e94416668 100644 --- a/tricycle_steering_controller/CHANGELOG.rst +++ b/tricycle_steering_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package tricycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.11.0 (2023-06-24) ------------------- * Added -Wconversion flag and fix warnings (`#667 `_) diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index b86820e783..6d8c399de6 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.11.0 (2023-06-24) ------------------- * Added -Wconversion flag and fix warnings (`#667 `_) From 6a4fb70283118ed3ca4818cae1591e15c7a7ced6 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Tue, 18 Jul 2023 19:15:15 +0100 Subject: [PATCH 078/238] 3.12.0 --- ackermann_steering_controller/CHANGELOG.rst | 4 ++-- ackermann_steering_controller/package.xml | 2 +- admittance_controller/CHANGELOG.rst | 4 ++-- admittance_controller/package.xml | 2 +- bicycle_steering_controller/CHANGELOG.rst | 4 ++-- bicycle_steering_controller/package.xml | 2 +- diff_drive_controller/CHANGELOG.rst | 4 ++-- diff_drive_controller/package.xml | 2 +- effort_controllers/CHANGELOG.rst | 4 ++-- effort_controllers/package.xml | 2 +- force_torque_sensor_broadcaster/CHANGELOG.rst | 4 ++-- force_torque_sensor_broadcaster/package.xml | 2 +- forward_command_controller/CHANGELOG.rst | 4 ++-- forward_command_controller/package.xml | 2 +- gripper_controllers/CHANGELOG.rst | 4 ++-- gripper_controllers/package.xml | 2 +- imu_sensor_broadcaster/CHANGELOG.rst | 4 ++-- imu_sensor_broadcaster/package.xml | 2 +- joint_state_broadcaster/CHANGELOG.rst | 4 ++-- joint_state_broadcaster/package.xml | 2 +- joint_trajectory_controller/CHANGELOG.rst | 4 ++-- joint_trajectory_controller/package.xml | 2 +- position_controllers/CHANGELOG.rst | 4 ++-- position_controllers/package.xml | 2 +- ros2_controllers/CHANGELOG.rst | 4 ++-- ros2_controllers/package.xml | 2 +- ros2_controllers_test_nodes/CHANGELOG.rst | 4 ++-- ros2_controllers_test_nodes/package.xml | 2 +- ros2_controllers_test_nodes/setup.py | 2 +- rqt_joint_trajectory_controller/CHANGELOG.rst | 4 ++-- rqt_joint_trajectory_controller/package.xml | 2 +- rqt_joint_trajectory_controller/setup.py | 2 +- steering_controllers_library/CHANGELOG.rst | 4 ++-- steering_controllers_library/package.xml | 2 +- tricycle_controller/CHANGELOG.rst | 4 ++-- tricycle_controller/package.xml | 2 +- tricycle_steering_controller/CHANGELOG.rst | 4 ++-- tricycle_steering_controller/package.xml | 2 +- velocity_controllers/CHANGELOG.rst | 4 ++-- velocity_controllers/package.xml | 2 +- 40 files changed, 59 insertions(+), 59 deletions(-) diff --git a/ackermann_steering_controller/CHANGELOG.rst b/ackermann_steering_controller/CHANGELOG.rst index a07f3372b6..f2cb336a5d 100644 --- a/ackermann_steering_controller/CHANGELOG.rst +++ b/ackermann_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ackermann_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.12.0 (2023-07-18) +------------------- 3.11.0 (2023-06-24) ------------------- diff --git a/ackermann_steering_controller/package.xml b/ackermann_steering_controller/package.xml index 132cac06c0..dab9499c7d 100644 --- a/ackermann_steering_controller/package.xml +++ b/ackermann_steering_controller/package.xml @@ -2,7 +2,7 @@ ackermann_steering_controller - 3.11.0 + 3.12.0 Steering controller for Ackermann kinematics. Rear fixed wheels are powering the vehicle and front wheels are steering it. Apache License 2.0 Bence Magyar diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index eb56a4bcd2..8f5804fbe5 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.12.0 (2023-07-18) +------------------- * Activate AdmittanceControllerTestParameterizedInvalidParameters (`#711 `_) * Contributors: Christoph Fröhlich diff --git a/admittance_controller/package.xml b/admittance_controller/package.xml index ba6d549877..83ca1f1b2d 100644 --- a/admittance_controller/package.xml +++ b/admittance_controller/package.xml @@ -2,7 +2,7 @@ admittance_controller - 3.11.0 + 3.12.0 Implementation of admittance controllers for different input and output interface. Denis Štogl Bence Magyar diff --git a/bicycle_steering_controller/CHANGELOG.rst b/bicycle_steering_controller/CHANGELOG.rst index 0b9b4abb2b..c9e4604a07 100644 --- a/bicycle_steering_controller/CHANGELOG.rst +++ b/bicycle_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package bicycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.12.0 (2023-07-18) +------------------- 3.11.0 (2023-06-24) ------------------- diff --git a/bicycle_steering_controller/package.xml b/bicycle_steering_controller/package.xml index e77fd0e0bb..d6a971ab6d 100644 --- a/bicycle_steering_controller/package.xml +++ b/bicycle_steering_controller/package.xml @@ -2,7 +2,7 @@ bicycle_steering_controller - 3.11.0 + 3.12.0 Steering controller with bicycle kinematics. Rear fixed wheel is powering the vehicle and front wheel is steering. Apache License 2.0 Bence Magyar diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index c99e27900d..1df6139577 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.12.0 (2023-07-18) +------------------- 3.11.0 (2023-06-24) ------------------- diff --git a/diff_drive_controller/package.xml b/diff_drive_controller/package.xml index f7d2f2f361..34d236a9eb 100644 --- a/diff_drive_controller/package.xml +++ b/diff_drive_controller/package.xml @@ -1,7 +1,7 @@ diff_drive_controller - 3.11.0 + 3.12.0 Controller for a differential drive mobile base. Bence Magyar Jordan Palacios diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index e1cf1be3d9..1134b1cc09 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.12.0 (2023-07-18) +------------------- 3.11.0 (2023-06-24) ------------------- diff --git a/effort_controllers/package.xml b/effort_controllers/package.xml index 567dc00741..c3280f9c9b 100644 --- a/effort_controllers/package.xml +++ b/effort_controllers/package.xml @@ -1,7 +1,7 @@ effort_controllers - 3.11.0 + 3.12.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index d10ebf1b6e..7a420bb146 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.12.0 (2023-07-18) +------------------- 3.11.0 (2023-06-24) ------------------- diff --git a/force_torque_sensor_broadcaster/package.xml b/force_torque_sensor_broadcaster/package.xml index a363551958..c89df2b397 100644 --- a/force_torque_sensor_broadcaster/package.xml +++ b/force_torque_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ force_torque_sensor_broadcaster - 3.11.0 + 3.12.0 Controller to publish state of force-torque sensors. Bence Magyar Denis Štogl diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index af62c3d352..7e33097a52 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.12.0 (2023-07-18) +------------------- 3.11.0 (2023-06-24) ------------------- diff --git a/forward_command_controller/package.xml b/forward_command_controller/package.xml index 0069f28315..de09d505ba 100644 --- a/forward_command_controller/package.xml +++ b/forward_command_controller/package.xml @@ -1,7 +1,7 @@ forward_command_controller - 3.11.0 + 3.12.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index 25dd4ec05c..797fc118ed 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.12.0 (2023-07-18) +------------------- 3.11.0 (2023-06-24) ------------------- diff --git a/gripper_controllers/package.xml b/gripper_controllers/package.xml index 646399f14f..3e48f395af 100644 --- a/gripper_controllers/package.xml +++ b/gripper_controllers/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> gripper_controllers - 3.11.0 + 3.12.0 The gripper_controllers package Bence Magyar diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index 06f9003e1f..9920deb233 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.12.0 (2023-07-18) +------------------- 3.11.0 (2023-06-24) ------------------- diff --git a/imu_sensor_broadcaster/package.xml b/imu_sensor_broadcaster/package.xml index 993bec7ab4..4ba9bb7a55 100644 --- a/imu_sensor_broadcaster/package.xml +++ b/imu_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ imu_sensor_broadcaster - 3.11.0 + 3.12.0 Controller to publish readings of IMU sensors. Bence Magyar Denis Štogl diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index ec928921ce..a33b0cc011 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.12.0 (2023-07-18) +------------------- 3.11.0 (2023-06-24) ------------------- diff --git a/joint_state_broadcaster/package.xml b/joint_state_broadcaster/package.xml index da7683d69e..89a23fc15b 100644 --- a/joint_state_broadcaster/package.xml +++ b/joint_state_broadcaster/package.xml @@ -1,7 +1,7 @@ joint_state_broadcaster - 3.11.0 + 3.12.0 Broadcaster to publish joint state Bence Magyar Denis Stogl diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index 6bf514fa9f..c2e3fa332d 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.12.0 (2023-07-18) +------------------- * Remove reactivation test from ROS 1 * Don't test update after cleanup * Fix namespace for parameter traits(`#703 `_) diff --git a/joint_trajectory_controller/package.xml b/joint_trajectory_controller/package.xml index edf2ac91a9..63774d5c2e 100644 --- a/joint_trajectory_controller/package.xml +++ b/joint_trajectory_controller/package.xml @@ -1,7 +1,7 @@ joint_trajectory_controller - 3.11.0 + 3.12.0 Controller for executing joint-space trajectories on a group of joints Bence Magyar Jordan Palacios diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index 047540cd7e..e5c55a3569 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.12.0 (2023-07-18) +------------------- 3.11.0 (2023-06-24) ------------------- diff --git a/position_controllers/package.xml b/position_controllers/package.xml index d2c4eaecc6..ef214c3563 100644 --- a/position_controllers/package.xml +++ b/position_controllers/package.xml @@ -1,7 +1,7 @@ position_controllers - 3.11.0 + 3.12.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index e53ccfe66b..1cc86b0d0e 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.12.0 (2023-07-18) +------------------- 3.11.0 (2023-06-24) ------------------- diff --git a/ros2_controllers/package.xml b/ros2_controllers/package.xml index ce06ac9d71..1bfa80d078 100644 --- a/ros2_controllers/package.xml +++ b/ros2_controllers/package.xml @@ -1,7 +1,7 @@ ros2_controllers - 3.11.0 + 3.12.0 Metapackage for ROS2 controllers related packages Bence Magyar Jordan Palacios diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index a0ebfba35d..73e59702f9 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.12.0 (2023-07-18) +------------------- 3.11.0 (2023-06-24) ------------------- diff --git a/ros2_controllers_test_nodes/package.xml b/ros2_controllers_test_nodes/package.xml index 27cc252293..bc0fab74b0 100644 --- a/ros2_controllers_test_nodes/package.xml +++ b/ros2_controllers_test_nodes/package.xml @@ -2,7 +2,7 @@ ros2_controllers_test_nodes - 3.11.0 + 3.12.0 Demo nodes for showing and testing functionalities of the ros2_control framework. Denis Štogl diff --git a/ros2_controllers_test_nodes/setup.py b/ros2_controllers_test_nodes/setup.py index 35f7f7b942..c90806a128 100644 --- a/ros2_controllers_test_nodes/setup.py +++ b/ros2_controllers_test_nodes/setup.py @@ -20,7 +20,7 @@ setup( name=package_name, - version="3.11.0", + version="3.12.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index 067ba3be8b..75d8985836 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.12.0 (2023-07-18) +------------------- 3.11.0 (2023-06-24) ------------------- diff --git a/rqt_joint_trajectory_controller/package.xml b/rqt_joint_trajectory_controller/package.xml index c44049b9ff..1aa9b0df6d 100644 --- a/rqt_joint_trajectory_controller/package.xml +++ b/rqt_joint_trajectory_controller/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> rqt_joint_trajectory_controller - 3.11.0 + 3.12.0 Graphical frontend for interacting with joint_trajectory_controller instances. Bence Magyar diff --git a/rqt_joint_trajectory_controller/setup.py b/rqt_joint_trajectory_controller/setup.py index 5610eff43c..844e8a51d8 100644 --- a/rqt_joint_trajectory_controller/setup.py +++ b/rqt_joint_trajectory_controller/setup.py @@ -7,7 +7,7 @@ setup( name=package_name, - version="3.11.0", + version="3.12.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/steering_controllers_library/CHANGELOG.rst b/steering_controllers_library/CHANGELOG.rst index e97c21bf78..88400b4e3b 100644 --- a/steering_controllers_library/CHANGELOG.rst +++ b/steering_controllers_library/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package steering_controllers_library ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.12.0 (2023-07-18) +------------------- 3.11.0 (2023-06-24) ------------------- diff --git a/steering_controllers_library/package.xml b/steering_controllers_library/package.xml index 5918c1491e..2b8004356a 100644 --- a/steering_controllers_library/package.xml +++ b/steering_controllers_library/package.xml @@ -2,7 +2,7 @@ steering_controllers_library - 3.11.0 + 3.12.0 Package for steering robot configurations including odometry and interfaces. Apache License 2.0 Bence Magyar diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index 67322908ce..ce14946944 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.12.0 (2023-07-18) +------------------- 3.11.0 (2023-06-24) ------------------- diff --git a/tricycle_controller/package.xml b/tricycle_controller/package.xml index 2b5106ff83..91f6fb5a19 100644 --- a/tricycle_controller/package.xml +++ b/tricycle_controller/package.xml @@ -2,7 +2,7 @@ tricycle_controller - 3.11.0 + 3.12.0 Controller for a tricycle drive mobile base Bence Magyar Tony Najjar diff --git a/tricycle_steering_controller/CHANGELOG.rst b/tricycle_steering_controller/CHANGELOG.rst index 5e94416668..70b91d59b8 100644 --- a/tricycle_steering_controller/CHANGELOG.rst +++ b/tricycle_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package tricycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.12.0 (2023-07-18) +------------------- 3.11.0 (2023-06-24) ------------------- diff --git a/tricycle_steering_controller/package.xml b/tricycle_steering_controller/package.xml index b8893108e0..e24d2f97c2 100644 --- a/tricycle_steering_controller/package.xml +++ b/tricycle_steering_controller/package.xml @@ -2,7 +2,7 @@ tricycle_steering_controller - 3.11.0 + 3.12.0 Steering controller with tricycle kinematics. Rear fixed wheels are powering the vehicle and front wheel is steering. Apache License 2.0 Bence Magyar diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index 6d8c399de6..c832892dd9 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.12.0 (2023-07-18) +------------------- 3.11.0 (2023-06-24) ------------------- diff --git a/velocity_controllers/package.xml b/velocity_controllers/package.xml index eba1e97ad2..d861c91806 100644 --- a/velocity_controllers/package.xml +++ b/velocity_controllers/package.xml @@ -1,7 +1,7 @@ velocity_controllers - 3.11.0 + 3.12.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios From d63b47b3cb8dc7b5220a6c318682d0ac2ceab1a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Mon, 24 Jul 2023 19:21:43 +0200 Subject: [PATCH 079/238] [Doc] Fix links (#715) --- .github/ISSUE_TEMPLATE/good-first-issue.md | 4 ++-- doc/writing_new_controller.rst | 2 +- joint_trajectory_controller/README.md | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/good-first-issue.md b/.github/ISSUE_TEMPLATE/good-first-issue.md index 95181eceb0..4a2664918a 100644 --- a/.github/ISSUE_TEMPLATE/good-first-issue.md +++ b/.github/ISSUE_TEMPLATE/good-first-issue.md @@ -28,7 +28,7 @@ Nothing. This issue is meant to welcome you to Open Source :) We are happy to wa - [ ] 🙋 **Claim this issue**: Comment below. If someone else has claimed it, ask if they've opened a pull request already and if they're stuck -- maybe you can help them solve a problem or move it along! -- [ ] 🗄️ **Create a local workspace** for making your changes and testing [following these instructions](https://docs.ros.org/en/rolling/Tutorials/Workspace/Creating-A-Workspace.html), for Step3 use "Download Source Code" section with [these instructions](https://ros-controls.github.io/control.ros.org/getting_started.html#compiling). +- [ ] 🗄️ **Create a local workspace** for making your changes and testing [following these instructions](https://docs.ros.org/en/rolling/Tutorials/Workspace/Creating-A-Workspace.html), for Step3 use "Download Source Code" section with [these instructions](https://control.ros.org/master/doc/getting_started/getting_started.html#building-from-source). - [ ] 🍴 **Fork the repository** using the handy button at the top of the repository page and **clone** it into `~/ws_ros2_control/src/ros-controls/ros2_controllers`, [here is a guide that you can follow](https://guides.github.com/activities/forking/) (You will have to remove or empty the existing `ros2_controllers` folder before cloning your own fork) @@ -53,7 +53,7 @@ Nothing. This issue is meant to welcome you to Open Source :) We are happy to wa Don’t hesitate to ask questions or to get help if you feel like you are getting stuck. For example leave a comment below! Furthermore, you find helpful resources here: -* [ROS2 Control Contribution Guide](https://ros-controls.github.io/control.ros.org/contributing.html) +* [ROS2 Control Contribution Guide](https://control.ros.org/master/doc/contributing/contributing.html) * [ROS2 Tutorials](https://docs.ros.org/en/rolling/Tutorials.html) * [ROS Answers](https://answers.ros.org/questions/) diff --git a/doc/writing_new_controller.rst b/doc/writing_new_controller.rst index 4d8c3752ae..1543e79722 100644 --- a/doc/writing_new_controller.rst +++ b/doc/writing_new_controller.rst @@ -5,7 +5,7 @@ Writing a new controller ======================== -In this framework controllers are libraries, dynamically loaded by the controller manager using the `pluginlib `_ interface. +In this framework controllers are libraries, dynamically loaded by the controller manager using the `pluginlib `_ interface. The following is a step-by-step guide to create source files, basic tests, and compile rules for a new controller. 1. **Preparing package** diff --git a/joint_trajectory_controller/README.md b/joint_trajectory_controller/README.md index 9bffcc3566..874176d228 100644 --- a/joint_trajectory_controller/README.md +++ b/joint_trajectory_controller/README.md @@ -2,4 +2,4 @@ The package implements controllers to interpolate joint's trajectory. -For detailed documentation check the `docs` folder or [ros2_control documentation](https://ros-controls.github.io/control.ros.org/). +For detailed documentation check the `docs` folder or [ros2_control documentation](https://control.ros.org/). From af5f8c8e3cb39760178e1438f221eaf722a8556d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Jul 2023 10:02:27 +0100 Subject: [PATCH 080/238] Bump ros-tooling/action-ros-ci from 0.3.2 to 0.3.3 (#718) --- .github/workflows/ci-coverage-build.yml | 2 +- .github/workflows/reusable-ros-tooling-source-build.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-coverage-build.yml b/.github/workflows/ci-coverage-build.yml index 67d4c43375..b7698dbbe4 100644 --- a/.github/workflows/ci-coverage-build.yml +++ b/.github/workflows/ci-coverage-build.yml @@ -20,7 +20,7 @@ jobs: with: required-ros-distributions: ${{ env.ROS_DISTRO }} - uses: actions/checkout@v3 - - uses: ros-tooling/action-ros-ci@0.3.2 + - uses: ros-tooling/action-ros-ci@0.3.3 with: target-ros2-distro: ${{ env.ROS_DISTRO }} import-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/reusable-ros-tooling-source-build.yml b/.github/workflows/reusable-ros-tooling-source-build.yml index daa378297e..99a4ed66a5 100644 --- a/.github/workflows/reusable-ros-tooling-source-build.yml +++ b/.github/workflows/reusable-ros-tooling-source-build.yml @@ -32,7 +32,7 @@ jobs: - uses: actions/checkout@v3 with: ref: ${{ inputs.ref }} - - uses: ros-tooling/action-ros-ci@0.3.2 + - uses: ros-tooling/action-ros-ci@0.3.3 with: target-ros2-distro: ${{ inputs.ros_distro }} ref: ${{ inputs.ref }} From a572381bb4364beca50136c9a5b7c5639b2d396f Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Tue, 25 Jul 2023 12:52:34 +0100 Subject: [PATCH 081/238] [JTC] Reject messages with effort fields (#699) (#719) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Christoph Fröhlich --- .../src/joint_trajectory_controller.cpp | 24 +++++++++---------- .../test/test_trajectory_controller.cpp | 21 ++-------------- 2 files changed, 14 insertions(+), 31 deletions(-) diff --git a/joint_trajectory_controller/src/joint_trajectory_controller.cpp b/joint_trajectory_controller/src/joint_trajectory_controller.cpp index dccb9fceff..4b3a73c3a9 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller.cpp +++ b/joint_trajectory_controller/src/joint_trajectory_controller.cpp @@ -289,14 +289,7 @@ controller_interface::return_type JointTrajectoryController::update( } if (has_effort_command_interface_) { - if (use_closed_loop_pid_adapter_) - { - assign_interface_from_point(joint_command_interface_[3], tmp_command_); - } - else - { - assign_interface_from_point(joint_command_interface_[3], state_desired_.effort); - } + assign_interface_from_point(joint_command_interface_[3], tmp_command_); } // store the previous command. Used in open-loop control mode @@ -1267,8 +1260,9 @@ bool JointTrajectoryController::validate_trajectory_point_field( if (joint_names_size != vector_field.size()) { RCLCPP_ERROR( - get_node()->get_logger(), "Mismatch between joint_names (%zu) and %s (%zu) at point #%zu.", - joint_names_size, string_for_vector_field.c_str(), vector_field.size(), i); + get_node()->get_logger(), + "Mismatch between joint_names size (%zu) and %s (%zu) at point #%zu.", joint_names_size, + string_for_vector_field.c_str(), vector_field.size(), i); return false; } return true; @@ -1384,11 +1378,17 @@ bool JointTrajectoryController::validate_trajectory_msg( !validate_trajectory_point_field(joint_count, points[i].positions, "positions", i, false) || !validate_trajectory_point_field(joint_count, points[i].velocities, "velocities", i, true) || !validate_trajectory_point_field( - joint_count, points[i].accelerations, "accelerations", i, true) || - !validate_trajectory_point_field(joint_count, points[i].effort, "effort", i, true)) + joint_count, points[i].accelerations, "accelerations", i, true)) { return false; } + // reject effort entries + if (!points[i].effort.empty()) + { + RCLCPP_ERROR( + get_node()->get_logger(), "Trajectories with effort fields are currently not supported."); + return false; + } } return true; } diff --git a/joint_trajectory_controller/test/test_trajectory_controller.cpp b/joint_trajectory_controller/test/test_trajectory_controller.cpp index d56a2c9b0c..375cdc0346 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller.cpp +++ b/joint_trajectory_controller/test/test_trajectory_controller.cpp @@ -779,15 +779,6 @@ TEST_P(TrajectoryControllerTestParameterized, test_jumbled_joint_order) traj_msg.points[0].velocities[1] = -0.1; traj_msg.points[0].velocities[2] = -0.1; } - - if (traj_controller_->has_effort_command_interface()) - { - traj_msg.points[0].effort.resize(3); - traj_msg.points[0].effort[0] = -0.1; - traj_msg.points[0].effort[1] = -0.1; - traj_msg.points[0].effort[2] = -0.1; - } - trajectory_publisher_->publish(traj_msg); } @@ -810,13 +801,6 @@ TEST_P(TrajectoryControllerTestParameterized, test_jumbled_joint_order) EXPECT_GT(0.0, joint_vel_[1]); EXPECT_GT(0.0, joint_vel_[2]); } - - if (traj_controller_->has_effort_command_interface()) - { - EXPECT_GT(0.0, joint_eff_[0]); - EXPECT_GT(0.0, joint_eff_[1]); - EXPECT_GT(0.0, joint_eff_[2]); - } // TODO(anyone): add here checks for acceleration commands } @@ -1027,10 +1011,9 @@ TEST_P(TrajectoryControllerTestParameterized, invalid_message) traj_msg.points[0].accelerations = {1.0, 2.0}; EXPECT_FALSE(traj_controller_->validate_trajectory_msg(traj_msg)); - // Incompatible data sizes, too few efforts + // Effort is not supported in trajectory message traj_msg = good_traj_msg; - traj_msg.points[0].positions.clear(); - traj_msg.points[0].effort = {1.0, 2.0}; + traj_msg.points[0].effort = {1.0, 2.0, 3.0}; EXPECT_FALSE(traj_controller_->validate_trajectory_msg(traj_msg)); // Non-strictly increasing waypoint times From 683696523fb193ede2d28ec107a5d18f01031344 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Thu, 27 Jul 2023 13:14:08 +0200 Subject: [PATCH 082/238] Update ci-ros-lint.yml and copyright format (#720) --- .github/workflows/ci-ros-lint.yml | 20 +++++++++++-- .../src/steering_odometry.cpp | 28 +++++++++---------- 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ci-ros-lint.yml b/.github/workflows/ci-ros-lint.yml index 3149bba54d..9e08bec730 100644 --- a/.github/workflows/ci-ros-lint.yml +++ b/.github/workflows/ci-ros-lint.yml @@ -18,23 +18,30 @@ jobs: distribution: rolling linter: ${{ matrix.linter }} package-name: + ackermann_steering_controller + admittance_controller + bicycle_steering_controller diff_drive_controller effort_controllers force_torque_sensor_broadcaster forward_command_controller + gripper_controllers + imu_sensor_broadcaster joint_state_broadcaster joint_trajectory_controller - gripper_controllers position_controllers ros2_controllers ros2_controllers_test_nodes + rqt_joint_trajectory_controller + steering_controllers_library tricycle_controller + tricycle_steering_controller velocity_controllers ament_lint_100: name: ament_${{ matrix.linter }} - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest strategy: fail-fast: false matrix: @@ -48,15 +55,22 @@ jobs: linter: cpplint arguments: "--linelength=100 --filter=-whitespace/newline" package-name: + ackermann_steering_controller + admittance_controller + bicycle_steering_controller diff_drive_controller effort_controllers force_torque_sensor_broadcaster forward_command_controller + gripper_controllers + imu_sensor_broadcaster joint_state_broadcaster joint_trajectory_controller - gripper_controllers position_controllers ros2_controllers ros2_controllers_test_nodes + rqt_joint_trajectory_controller + steering_controllers_library tricycle_controller + tricycle_steering_controller velocity_controllers diff --git a/steering_controllers_library/src/steering_odometry.cpp b/steering_controllers_library/src/steering_odometry.cpp index c480dc1253..0a7dc23ef2 100644 --- a/steering_controllers_library/src/steering_odometry.cpp +++ b/steering_controllers_library/src/steering_odometry.cpp @@ -1,18 +1,16 @@ -/********************************************************************* - * Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *********************************************************************/ +// Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. /* * Author: dr. sc. Tomislav Petkovic From 76c22ffce19c7b2535bc465e21c8fa0620b0f0a6 Mon Sep 17 00:00:00 2001 From: Abishalini Sivaraman Date: Thu, 27 Jul 2023 14:28:31 -0600 Subject: [PATCH 083/238] Fix out of bound access in admittance controller (#721) --- .../admittance_rule_impl.hpp | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/admittance_controller/include/admittance_controller/admittance_rule_impl.hpp b/admittance_controller/include/admittance_controller/admittance_rule_impl.hpp index 87c16e4787..9b03924882 100644 --- a/admittance_controller/include/admittance_controller/admittance_rule_impl.hpp +++ b/admittance_controller/include/admittance_controller/admittance_rule_impl.hpp @@ -28,6 +28,9 @@ namespace admittance_controller { + +constexpr auto NUM_CARTESIAN_DOF = 6; // (3 translation + 3 rotation) + /// Configure admittance rule memory for num joints and load kinematics interface controller_interface::return_type AdmittanceRule::configure( const std::shared_ptr & node, const size_t num_joints) @@ -83,10 +86,10 @@ controller_interface::return_type AdmittanceRule::reset(const size_t num_joints) { state_message_.joint_state.name = parameters_.joints; } - state_message_.mass.data.resize(6, 0.0); - state_message_.selected_axes.data.resize(6, 0); - state_message_.damping.data.resize(6, 0); - state_message_.stiffness.data.resize(6, 0); + state_message_.mass.data.resize(NUM_CARTESIAN_DOF, 0.0); + state_message_.selected_axes.data.resize(NUM_CARTESIAN_DOF, 0); + state_message_.damping.data.resize(NUM_CARTESIAN_DOF, 0); + state_message_.stiffness.data.resize(NUM_CARTESIAN_DOF, 0); state_message_.wrench_base.header.frame_id = parameters_.kinematics.base; state_message_.admittance_velocity.header.frame_id = parameters_.kinematics.base; state_message_.admittance_acceleration.header.frame_id = parameters_.kinematics.base; @@ -122,7 +125,7 @@ void AdmittanceRule::apply_parameters_update() vec_to_eigen(parameters_.admittance.stiffness, admittance_state_.stiffness); vec_to_eigen(parameters_.admittance.selected_axes, admittance_state_.selected_axes); - for (size_t i = 0; i < 6; ++i) + for (size_t i = 0; i < NUM_CARTESIAN_DOF; ++i) { admittance_state_.mass_inv[i] = 1.0 / parameters_.admittance.mass[i]; admittance_state_.damping[i] = parameters_.admittance.damping_ratio[i] * 2 * @@ -331,16 +334,20 @@ void AdmittanceRule::process_wrench_measurements( const control_msgs::msg::AdmittanceControllerState & AdmittanceRule::get_controller_state() { + for (size_t i = 0; i < NUM_CARTESIAN_DOF; ++i) + { + state_message_.stiffness.data[i] = admittance_state_.stiffness[i]; + state_message_.damping.data[i] = admittance_state_.damping[i]; + state_message_.selected_axes.data[i] = static_cast(admittance_state_.selected_axes[i]); + state_message_.mass.data[i] = admittance_state_.mass[i]; + } + for (size_t i = 0; i < parameters_.joints.size(); ++i) { state_message_.joint_state.name[i] = parameters_.joints[i]; state_message_.joint_state.position[i] = admittance_state_.joint_pos[i]; state_message_.joint_state.velocity[i] = admittance_state_.joint_vel[i]; state_message_.joint_state.effort[i] = admittance_state_.joint_acc[i]; - state_message_.stiffness.data[i] = admittance_state_.stiffness[i]; - state_message_.damping.data[i] = admittance_state_.damping[i]; - state_message_.selected_axes.data[i] = static_cast(admittance_state_.selected_axes[i]); - state_message_.mass.data[i] = admittance_state_.mass[i]; } state_message_.wrench_base.wrench.force.x = admittance_state_.wrench_base[0]; From fa721709a3390b6f6465490f85a9538d216efd74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Mon, 31 Jul 2023 19:42:57 +0200 Subject: [PATCH 084/238] [JTC] Update trajectory documentation (#714) --- .../doc/new_trajectory.png | Bin 0 -> 73149 bytes .../doc/parameters.rst | 132 ++++++++++++++ .../doc/spline_acceleration.png | Bin 0 -> 34639 bytes .../doc/spline_position.png | Bin 0 -> 28511 bytes .../doc/spline_position_velocity.png | Bin 0 -> 37882 bytes .../spline_position_velocity_acceleration.png | Bin 0 -> 39812 bytes ...ion_velocity_acceleration_initialpoint.png | Bin 0 -> 39086 bytes ...ocity_acceleration_initialpoint_notime.png | Bin 0 -> 36267 bytes .../doc/spline_velocity.png | Bin 0 -> 32183 bytes .../doc/spline_wrong_points.png | Bin 0 -> 41712 bytes .../doc/trajectory.rst | 168 ++++++++++++++++++ .../doc/trajectory_replacement_future.png | Bin 0 -> 71754 bytes .../doc/trajectory_replacement_now.png | Bin 0 -> 64005 bytes .../doc/trajectory_replacement_past.png | Bin 0 -> 74230 bytes joint_trajectory_controller/doc/userdoc.rst | 167 ++--------------- 15 files changed, 316 insertions(+), 151 deletions(-) create mode 100644 joint_trajectory_controller/doc/new_trajectory.png create mode 100644 joint_trajectory_controller/doc/parameters.rst create mode 100644 joint_trajectory_controller/doc/spline_acceleration.png create mode 100644 joint_trajectory_controller/doc/spline_position.png create mode 100644 joint_trajectory_controller/doc/spline_position_velocity.png create mode 100644 joint_trajectory_controller/doc/spline_position_velocity_acceleration.png create mode 100644 joint_trajectory_controller/doc/spline_position_velocity_acceleration_initialpoint.png create mode 100644 joint_trajectory_controller/doc/spline_position_velocity_acceleration_initialpoint_notime.png create mode 100644 joint_trajectory_controller/doc/spline_velocity.png create mode 100644 joint_trajectory_controller/doc/spline_wrong_points.png create mode 100644 joint_trajectory_controller/doc/trajectory.rst create mode 100644 joint_trajectory_controller/doc/trajectory_replacement_future.png create mode 100644 joint_trajectory_controller/doc/trajectory_replacement_now.png create mode 100644 joint_trajectory_controller/doc/trajectory_replacement_past.png diff --git a/joint_trajectory_controller/doc/new_trajectory.png b/joint_trajectory_controller/doc/new_trajectory.png new file mode 100644 index 0000000000000000000000000000000000000000..b7c07eeffee46b4602ef8f2a9333afdcab666a14 GIT binary patch literal 73149 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 literal 0 HcmV?d00001 diff --git a/joint_trajectory_controller/doc/parameters.rst b/joint_trajectory_controller/doc/parameters.rst new file mode 100644 index 0000000000..40aa8e6ba1 --- /dev/null +++ b/joint_trajectory_controller/doc/parameters.rst @@ -0,0 +1,132 @@ +:github_url: https://github.com/ros-controls/ros2_controllers/blob/{REPOS_FILE_BRANCH}/joint_trajectory_controller/doc/parameters.rst + +.. _parameters: + +Details about parameters +^^^^^^^^^^^^^^^^^^^^^^^^ + +joints (list(string)) + Joint names to control and listen to. + +command_joints (list(string)) + Joint names to control. This parameters is used if JTC is used in a controller chain where command and state interfaces don't have same names. + +command_interface (list(string)) + Command interfaces provided by the hardware interface for all joints. + + Values: [position | velocity | acceleration] (multiple allowed) + +state_interfaces (list(string)) + State interfaces provided by the hardware for all joints. + + Values: position (mandatory) [velocity, [acceleration]]. + Acceleration interface can only be used in combination with position and velocity. + +action_monitor_rate (double) + Rate to monitor status changes when the controller is executing action (control_msgs::action::FollowJointTrajectory). + + Default: 20.0 + +allow_partial_joints_goal (boolean) + Allow joint goals defining trajectory for only some joints. + + Default: false + +allow_integration_in_goal_trajectories (boolean) + Allow integration in goal trajectories to accept goals without position or velocity specified + + Default: false + +interpolation_method (string) + The type of interpolation to use, if any. Can be "splines" or "none". + + Default: splines + +open_loop_control (boolean) + Use controller in open-loop control mode: + + * The controller ignores the states provided by hardware interface but using last commands as states for starting the trajectory interpolation. + * It deactivates the feedback control, see the ``gains`` structure. + + This is useful if hardware states are not following commands, i.e., an offset between those (typical for hydraulic manipulators). + + .. Note:: + If this flag is set, the controller tries to read the values from the command interfaces on activation. + If they have real numeric values, those will be used instead of state interfaces. + Therefore it is important set command interfaces to NaN (i.e., ``std::numeric_limits::quiet_NaN()``) or state values when the hardware is started. + + Default: false + +allow_nonzero_velocity_at_trajectory_end (boolean) + If false, the last velocity point has to be zero or the goal will be rejected. + + Default: true + +constraints (structure) + Default values for tolerances if no explicit values are states in JointTrajectory message. + +constraints.stopped_velocity_tolerance (double) + Default value for end velocity deviation. + + Default: 0.01 + +constraints.goal_time (double) + Maximally allowed tolerance for not reaching the end of the trajectory in a predefined time. + + Default: 0.0 (not checked) + +constraints..trajectory (double) + Maximally allowed deviation from the target trajectory for a given joint. + + Default: 0.0 (tolerance is not enforced) + +constraints..goal (double) + Maximally allowed deviation from the goal (end of the trajectory) for a given joint. + + Default: 0.0 (tolerance is not enforced) + +gains (structure) + Only relevant, if ``open_loop_control`` is not set. + + If ``velocity`` is the only command interface for all joints or an ``effort`` command interface is configured, PID controllers are used for every joint. + This structure contains the controller gains for every joint with the control law + + .. math:: + + u = k_{ff} v_d + k_p e + k_i \sum e dt + k_d (v_d - v) + + with the desired velocity :math:`v_d`, the measured velocity :math:`v`, the position error :math:`e` (definition see below), + the controller period :math:`dt`, and the ``velocity`` or ``effort`` manipulated variable (control variable) :math:`u`, respectively. + +gains..p (double) + Proportional gain :math:`k_p` for PID + + Default: 0.0 + +gains..i (double) + Integral gain :math:`k_i` for PID + + Default: 0.0 + +gains..d (double) + Derivative gain :math:`k_d` for PID + + Default: 0.0 + +gains..i_clamp (double) + Integral clamp. Symmetrical in both positive and negative direction. + + Default: 0.0 + +gains..ff_velocity_scale (double) + Feed-forward scaling :math:`k_{ff}` of velocity + + Default: 0.0 + +gains..normalize_error (bool) + If true, the position error :math:`e = normalize(s_d - s)` is normalized between :math:`-\pi, \pi`. + Otherwise :math:`e = s_d - s` is used, with the desired position :math:`s_d` and the measured + position :math:`s` from the state interface. Use this for revolute joints without end stop, + where the shortest rotation to the target position is the desired motion. + + Default: false diff --git a/joint_trajectory_controller/doc/spline_acceleration.png b/joint_trajectory_controller/doc/spline_acceleration.png new file mode 100644 index 0000000000000000000000000000000000000000..98672beedd184285cf0bf4b311b9efa93e916e0f GIT binary patch literal 34639 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 literal 0 HcmV?d00001 diff --git a/joint_trajectory_controller/doc/spline_position_velocity_acceleration.png b/joint_trajectory_controller/doc/spline_position_velocity_acceleration.png new file mode 100644 index 0000000000000000000000000000000000000000..70152eec4e097d26ed93c3986d4e97d217bc7967 GIT binary patch literal 39812 zcmce;1yomC*Dw4h1WD;`5fPD;5Rej3NFw_^E~hKzW09Pj&IyCKF08zBWK6jYp*ru{KeeiDtB)a;L_ltP$&ZVJ2LlCDD-+1 z3T^H@7X0QmLnHhGb;DU!%UR9N)YQm>ky3Ymxi;hB ztu%Ioz4cL^&<15qC%a?tV`0; z)?eT)j)tS)~els!Ibiaw|o z`+Mu%^0ue1uE=&8`1W|`htPcXRJyve&BxC_zq(rF6U)Xj^aRb0+G2=mdS>P-`PTcI zn&z3AnOxr%@^;=iDij??vujs#&T~ALM3(u*AHfAPxt3i9v-2J)J3Dmk`w?$Gd2y=s zhvl;(^V27J9!*r1L1y4qzJ`L6Tb`Emc`@~T0@wO*dNye>b)${hS{2i)gKT*Mrt~Qx z<4?8V0v&yGsaT?v#PL|jOp}sIGwlS~JBzzvxe0RepZ-QI-uadxOF_cZxv6oyvSu^K z;392f-5I)ge0!xlBy7FcAUQ1R2^u$Xe7MYI**3lMu3fIgS7L6t_q#Z(h^*>gjo2^l zJ7U$z7^@>ARBG2NzioVvXCzF(*oZs|Q;aeCq$nfT2J1wrq;Rp6W)f~} zkWtj0_1e9j-31F(EOJWxHKxBSYEJ9*%Z+e>ql9QjTR%oOYX;J=i1y+EKCd9GI)@Jq zVImaK`IoakF;`&ReV-u%gG2EwUt-BNXjYVAGx>3>;l$20BY8(M;Y(5e(y@T&(OESw zwLAX9Ee~{*@v~L2Z#aeo^zSs)bsg#89T87mrBJI=?kIUw$8*zMWNm$odY2@AkO!7^ zB1!Fyqyha(){vm7o~1s`4yGzGb?KZpov&2b-%SZfl_=!*jR>%m8^T0&TZ>6dp=*;r zo z-7+UfK{p|Vr;Kxjr$-W7$6dGMo@;vkkaFO!+#wveJ>5br^1Fx^+f;Jtm1*;B8RI{T z2bY~>u7vAm^9beij~4~eiZQoz6<7_u`2CW?x}PFf?*EKgOHN?l`#iMySc8RS2bmzj z0x>CDS&Zq{lqLlkV+Lg8rcVXB1=Rf&Wn`WOz`D?`jKHkLw+|01#)Ab`t{{Eh_ zA_*}u@>d3v)P9pVMHyo+xPxlagGpzW&*_^uC)Kj-BAcs+UnW;V}sa z3*!hxu3GnPAL_!>&iA-~3wkDofrC5j*7cnt4CUTSW=ggclbkYMO ztIM6!&3e#@i8aXJ_k7{Yug%95_fuv~?#F*OO#E7QqT)1NyIEM#@L2i58Wm+ba{WRw zxV16Ke!@*;2gc>K-$9{Ex~Ah+keC^*>)CY&+m@|vF2v9;1R9uiF+tGcfZY%uj>Bw_ z*B#XDalTT)Vq+tv4;JSfoSd~-OBKUKHE7Oys_RZA>D7H|)kgh@g@q3b?!v|zEV+a| zzwEt%zhSLq3a33qZDp~xsa!dK>qS&Mc^8eyM<+SBMN|mf0w;W$j{RdAubYt4U4q4r z%OYN@)(;fM?72Ky&78x-y7QH2woFY-9?#Z$+)+}J@$?iKwyYf3q2$u#F>wp)>)ENe z7FS!FT1P9FsP7_0z>JCId(6)@Ey{k_c8&Hj`7PopQLO)E_YlXc zPNe=cPESwISIw4NA?P*u){|sDUdH_L7vxEfWSk#_F*2(dbR8q57VSE@$ zB5kyklux?5?^utQp>c6>k&6%HD!<@)+=^MOTT23C?&@Oni}F1=WEK!0kG;9C_4X)D z)QxasV`H+b(sHEGo-vGF-=P;pS@NFfv*`PABYRWib$xh^wwWaxX@7d`;qK+t_VMEd zzEq{}zx928=O}fB$HsQi+SLcZv!S7$acT#`ZHz_=HBv;~Y~LP@lsuwkU|=BMkRbkc z)q>i93rz_&RwrC=t|jQIPgH%q*h^stbhW&@BNGfXG!bo2E+p63Jt3rzOH9P@^YiOV z;l*h1I^e3Zv9;xLbaJYU<>%iqD<#7{M}{jKa#%7^nsxLL;~^u4>YU3}GKD)D_H^(j zTZ&@7uI(L(Or6y0mYuAZoSl1*u3)kqX*quAf~2;#sDNv+jKoQ4@))!E`S}Wr3!`ry zsuZYi?T^0szOud^y*gI9I@8tFg>5xjEF~$4f;(?_Q0l+Bmmz*fK|%Us`pvx!ezy(X z_V#wNiAJ-J=?XbUC`oB)>74y)tSS*K*9bA^)6KJ^{Y%o<5?@qGm|Vh)JJ2U@3CUY? z;J@v*RFxjt{3|#0&fRIXl7-11E-FM_uN;ly($Z|2(~06M6M~6ahcDlB_=-7@eiKhV zVQzCXmXKcLsmB+qv64)^22Ww{Up(j-7?o3S>uB!AUs-)ZSp;;#L!4E0H5{Uz&G0?M@jBR$?R|Ewa_acxWP9*7BlGp^@A|r+h-)r;-1ezJ z?J_17mSO*Mfg11Me4SC$7^oCM8=4ZmhKP?6XLORjs`1?8V7vP=Ox)-2>8h4dS4_wFTcbVkYTpyj zw64U<_c|9pBwighW3keljqWJj5;M49NjjVg#<+HmX?O_HrA|gEFQ12EQ4E{ChFoqUV&a>ILmUKe z-@ff07~m>DnQwa%79A~M@*u4E?)(otUFPVpF!l@x2`MR5V(we7y7$-CtYL?zlwXz6 zlzl@%RmOSlG`=p96TA2d?-GkyDvY>XneELGQ}CxFyo2g5zPF-j1e7MoS&HH$ii$YO zrD>XX&%sj>Bx2S>_>W_S5TB`CVJae3s*uwPai7Puk4nusq?^MWedhZE#=+Vv(Ib?A z8zT7Ro9m1}kep}UI$SNi$i{{>QuJU<{Bm;d{P*uqnwurzq|T%XPfXG5W)P6s!D z$cc@*Zaq!}8z4xDjlaVpyja1(r1RKk`mKi&lkVcnL3mX|UCU^8u$7=%M?=wzI5)#- z+gtOu8f*mC!|o(E@)_Yn@(t_hTt+L+%exGVQl-w-#@*e0`J|(`HdQ(2K6Ra_jE0;= z(QDpMa6JxMnB=4V_0O6H<4t}|Z|~hUCa+PTfh9Umb#sn@kZ=@ce<-%-H8E5(&*WFP zPIo`w%h!BE6BrnXLNWU65{v&{B>i=Cw2&Pu9+;Pxcct!@vFh%~un97|Sv~wK3Ras< zXX1SPI}%wZCkJ2PIsvCAM+>bXcrZ~s@bWk#OmnW6B*?+aaA!-KZ*bpcfu)CrdRS%M z(j0)nYc@cKEX?IEO-)zoq>b+n$`6($ukkkYvaVMhQ$M=2ME^2&{fQ0}|CIa@-DhO_ z@w;G+>T=z7brnPzY|b{guUC$tPy&|2p9YRev@d#nV2GEGx9?UnWJL-1w^-f#x)#le zTCZH!3V`~qdkYE|taIm>Sy<4KjC*!^AYncE4hOaMJ;N^xa&PV$ZfZCYI;04Q!YV~i zmo{QPC~flL5PB$ZDx^owF9&8S&$cJg)?b13*i8mkL-r=JoneJVY7}WA2>|5}n~eCL z`0v;7Or}i#v+$a}GpAa%nxbF$apn^C?Ogn?$`-Kq>58ie$w8hYiMp*0DyT83s zCuPdw=mdbLb9#mc4{a_p4Zn>xdKjxtVTHywjW+_>a58eHL;jQ~bq?|>yDu>nW*?;! zSl?MskOW~71U57@6uaFDrzKwt7pVHg-Rb#* z%$~n}0v8+o2+9A8-&r*B7JrNsna|eW2qyZq^HBm2Wh4^n92Por*9cSN|6QD!Uk}*W zVPw2guA@Ux&Dm%DE&5C0Z5F;OBq*v~D8#AbVb5-D*UNKAsyUHWgITQ(y zRN~&kPyjF|en6pcL(t(>v<~Gc!g*P^SGjzo__KSTBX90m2dv~LPp})0HbjqM_uNrd zK8J$cmMx#imb-?f8j|$1F^-D3@6W*$-HR^nV7w_ie){S|P%KfB=;L#oI9kU)#fLoL5Lp`=6Wi zY!D?ytl+`X8c1M;#XFyPPrOBuyW#cBK170So2e=)AzL~OJwQ1@)88LZJ`xW6dwirk zhF+3F$lWv%@(BhaB2>=v_X?e z0A%rdJQmG$erLXF=`nY1%L`>YAULPnGgT}np!=ypQ4Pxe&o3r{A1Zn+ug%WYeU4!! zYKi4LlBwbajG7fSvx_Tgi)(;SGJZ(4b^qU3@(-B&gC+S8_}E>=JD0-|bOo7Hbz*$? z4_~*ju0xI~#K)>Pju(Cb=|Cp5)jv6kOXLa-puSwURQ1K$nnmIKU|iJ}Rrh=qG!*iT zEPU*6g7bgj!tS#w9A=_aVcH79fzBufeqIA@g|{oXC^ZU*i1}Zswh{*W@zZgb{cGB5 z-Bo|!GNWNUTkl-QUf-swn%lud%~`{f5L07g=<(qy6WX4h1!OnvN!!TY-rYYdZ3)Uc zBEz>w!>Wbh8B^iA7YyNIRsW8S{Md3W3=KIk6&*v5BRK-A8a1bJ4ey1Y9)UdS%_M!t z>UwU=$lE8pb;yH3ijR1ZI!Ey-ttHLPUR+!$A~^CrEov@^Ve_%6BP;6_i7uG-Foa2X z9;Sk0%xWg-DjAADhVQ<&A82fMgYgS3U(Lv;*X-?=x|q2xkvMtEp*L+{pp*!`8Cz9j zx?kTx;d?^*>vk`+Zmx6urogFNLxdD+BZcG$v|+dzapo>|;|4VhSlDR^AIh%C4~dtJ zVB4~-toFYV+CKQz6n|vLr8^h+c{^`j>kF~+GeN00%#}(**ssi0j?C-k10VXRONWf> zy-gW1AsI?u|7<&kS<9jN?jAg!Oz8bf7_-VR1Ru8s<7m}7UV87g83U1u3fQ|_mX;h0 zUTbez*17fS!yv>M?Jf@@rKiL4C*~-6Q3_b0trZ`|t%e(Cr#(r{(nT@O&#c!zaB^6x z-U@`U`P$U$}htW%F=>noHG_(9o}2^KG67HyjtwOW(TX zQWX*s@_2o+QiYu??t`)H{)hg4SzFtZeFsz1)4qJ^On+(B>-Hm;FW$hYJzHXg0X4r^ zNb=OV67UgiN@>b_nJUs83&J|I{d;PotKBpX z_`+EJk2{;6b;XADl=PgdueO~DRLBXeuC5+%wX?I+ZSsAzDLz)JKQ^UTp#Bvw>Of)N5X z^3x}kn!38=f>`PjYGHam8WdA+{Nw)nC+j-awrB^<<@6P-1AL-)hMbbbV|cHSDbR`9 zqnI-@JxwAq`tSVoq+x+mqL%GNz)x5j(4eRuDbdVc! z+!+4@&h;F3u8mCL#q80?dkIh`lm&_9ecEPie%pA_`{<^r>ZP72`TOiBd5$q*ovSfu zT`1s$lV}03i$dur>g4vSe$nv;Iy!oUH|DdrIDgxj_bW4(d3eh19NqNVe+9IFoKMBm zwM*BvCl{NrLo)i#@;)T636dgNlsNTP(u?_X{t&s=JycX?M3y9gM%yrLpLHPxbmpC5Ts&AcdleyryQ_xioA z6UU2d@XbLz&2IapF?xJl>vc{}rpxN+c%>C3&2@7W>W-pf+qd52%5_>n>o7<`k0D9^ zTF#DDskVK@`LL>3_tJ-rFHILvTYGx~eUUY|1}TpTWo3+4;g_*cB)zDkl`+m_ZIOuV zm3gDN07JKTa=JQ}g?G-v)*A^_sdnBKg8z)_&!UBb;^<&A8z!`@qR3I(Q^uG@!!dM> zZf$K%rODSPh^`lCdQ-m^3wv1PsK4)p5d+E-Rf}KWd0=*lwFQ9FgCFA&h^BGb*%!02 zvUW!gD#`zS8&sEnn9>uWH^|ZP8VmT`|MN8DEyZg-Jl7EhJNyFJHdM#Duzg_pbSHKCx!0o=sLd%>$24=KtWtl*WzPZrIPEun6hG-n*P!cwK~jlS*q!0EL1GCHs9KZGLGf6z0bWE-efUO~H}&=Sr1$-m*@sfG|!B z3_XmAcNS37r1(RAUjRhBJeZArxVQQQ7R{=S-}YD8-OVqIH$8WoA+T?^U^6m_iO~U+ z;C1*&P*lJ0%3)*r2E1I0rssk-mRSt6nwpvvaJwhuS2dp&GzjQnf1}4Bu&TxKKW^Sj zbDM1$%)T8T7YEf#IP6tp6BF{f*vdzEGOPHz{%-GQS-~0J&dHd)(!!0 zuPQ^#quhKjD`cRmde&3Xd3|!k+~<18&zLrd`{z&&2OEz_cL&~~!k~Og8t>F8#fUDC z3J}o8pjla2LH7p=ovSLkQXkKR8slLN+(k^d%?brfg)lHmf5PW~2Gl$8`;Q+#7WO?B zCc_OGJhW6Ir^b#3wy7EDFQ3ER7Pw{fgmR=|^q7>a_KrYYd^{QoVKU#^6rbp@_fnZ_ z?Nmz2EVcNLpl30{@$OvF)lgze}2ue`T*9d)OFnp~-mA$=ZJ4HG;2c{q`)Dop^MhaSVK z37*HBu5Sj-ibXzQz=&BU-X^DVth%A_%17brcC&Q-FNDU#3GwmUldeA4nt#HW1r(Xw zdR|W1=<2KD;u9M8gBdr6AH!E(zkdC6a#W`@q&y}7rb@C1FyVc7M$+6yiQ=QU1fh@|Ic+`e=`mU(OUMI4ZR8M6F!^1G>))kaFs zv6K^;);${N@jlrb10^pU6u^k#VRc?0f9HSv;NW`no;8@r@W*h0;dt5O$$j9_iGU$C zggC?^AfQqFs7|xnm~VT%`pfgxOH?u*U5~fFb{I}o*?a}Ui!AS61_cCTa#Z`XYY+SO zNI1U1s`v`K2l<2U9~K)+dHG&C+1c?u(uy%oe3kMSHe622*i0fLuny=Zft$7wASN=nKQcE9Oz11(Fmgk}|6>6A|L*{7$c=?6MI$w? z>on8T(@gRSwRN{-WKh9G2q%Z|eWIcR^F;B!pyw__074Rnn^0KTo!F}nN?rlYu(W|i ztPM53$>P!y7SoyX$jnTGbQcs%;}vEXAP4|-#Gh#32r_~^_9p}I^idg`nzoLOJvd@e zmU(>vW0r5|H7}GG4>;yr92^4b>gtrw0xLRr!|q0eHWa&1FW->ijGmIHc)eO3i--)2|5&D3mm6!b3rZZ9s1LbV8-bxO+hDhc^y$-?SB! zG^@?jdVE)yG1tgEh;CfS)V$I^L!X#BYeE82YnWmbmgCQ@&jnm5_Rfs{`+wETEss{) zG@pOyEmj=+XA@3XkpNW!0jhjB&m8w#N?0UAG)R>8S!$gqn-EE}y>r{Aqkj95x4Ux! z0@q02Wc>^>06`U$GE7lXMB$P7*5RM5B)7OE>9G-2Tlbg(z4?|Xb*Kw~p#-J^9$F+|~zRg`H$qApw)p<22R`25@-nhOhjo&PbO? zcd>63A?NTkEtvSwnK8>9lO`p}QDj3J^$gy0v|PnO^!^_LHZN8^D89Rg<+HZN$|{GM z4XPokx#OX>Ie8^52v1B`lSk+P7AUk)>#<;{6`f1hNzY0QTHQzp`tCW~995DS-{@HC zT4!qd;F9_!1~t-M3bB%%6Bo&^4LZ? zJ>;Hi_!p#I(-pqwRs{xdU%dhREP2OMEEbGU$*rIM%3Y7mYUTq~K>zr$?4LF-B}__+ z<(F~0=+uJaM*fJB0~0)A7#g?gC17Z#e_VudKfFAy9CbdlC_6}X2p<=_@!XErQTt{7 zYJfNSC@5!=o~GrshWl+;G9De(yeM`~VcWX4kt;Z`590-BUP#tYU`f+uwku$cdrRBG z*79@m*SMr28CM1~Zx9h(w{r!ua5=n#o;Ssc*6V&VEqbc51*4DDAk$4xK_;u4!XY#{ zA3d08@)b$<$B7wUuI{w};})_fffWtS*_MRQ4;x zpvZxpo4P*2d9S!Mih9d@wA%jV24@8}N=*H!E@RF00lon?QsVgEFh~w;pGXBQ%k`~!ZT zlYgqv_@KF1>ab0IoQ$}rh9$+evP9T*sY~jTde{c}qf<&*ATe+w@!W-MCWCQE*$`!P zdA31R{PdU6?&{cuf`S4BZbr;(0;IBc^K(wT3mnY5GYNo!h?G)OBP_Pl$3I?WL#yXL ze-2XmE5&3kIiH*Adm14xXCm0Cjw#f6h)R@bq+2G8`x)_4C+;Gv``T*FymHgAD`KBe zijc7`9gk=vgWXG_t=mk?$QUa$>yD8v7mbeM)Go)YbKC4J)F|R{+n6>yD0);UC?+Ph zD_#u{I5;@iVDg;>%HQI1E;FzKiqAM(pbj87rRnyh;x~J+xF~roQR7g!b8h!b6U&2u zo?(YibeA8mEx3F3f4tLhibC1%ANuswn#JnRm|fgAz&G^jFf`rj>v2wn^{PcdzP0r2 z+kAUCX^MzT;lMr=kaUpM+I>Wwm;GP9qyrw$2&5?y3ql0Wz+o*_E358!Z+A#F^}?ibI)*Ui!c#t9ezE{b?MhHzJmnnLM#yajkNF*lffQC;tQ2 z?*d*-%gk8D8)wF%gh~{{@nJ;2zD9C?%DczN3QG$r zGn79_t;wq?D45=VtEmh%H8oEUa#lb~${#+}NJ?Y5kal)-*60(i(z|H7eosCaMUh_K zHL`Y`I<0dTeY09a%GM1}0v1gU;TphdTcHw~{5*{(n9Z_pnsb}R49pXS96H`&EoSjP zpSAD@jyXy6-nh>Ak0U9mB`HWiYtthssq-4c5bb~0R6R#qlfR!ly;6ZWYTFfmO}l;NYc z+DUzw+?@EGVs}ZU=k97UlrSh`p?-PP8o0T;1$|pv3JEs&5?lA@ute>}*jK6@j44kD ztVZXws7&#%XEYKMC$(q!P66H}-QVArHP!q4 z`Ez97r)RH0B1UMT%Ggza5*tQ9NVg6SzU_8RRnlD1zZ)tnr}0|zO66Jd2Rcqi{M~PB z8~B@Ow{N$d=I5I@cF#=1FQcw--5_*|?eDU85qj7EK2WWs5%tr_Geg@4U$m{iNhhsf z;_uY`gX1H0bhNmV0mHrO?s|xWgR=}ZYHF<0&qaAC^vxNuv9Ks^ECCnNu;6 zlSVO&5)42mv_r|rYyOGJ8xX*Fog4T4`}g~P(tP--rI_|eF_(k`ag#meN{nl?W@JT` zIC{~g^4+Nu?ojJh6W#zAY>$QG?zQ(LWK7?W9%^E-muYENU5YbrJ^8x7J_SOeED}Ad zZKDC*XG#TOq5R*yyAA`@o)QNtE0ImP6*Rp0wY4aqs~ z6B{DE0{!VuW1Rv~=G)BmKF>`EPj=5jLU=amoYq63~;$R`AY zQ)q5;XW8@gjq9Qkd@GrX~qw*G$(qv=QYo@d+=j z=@5#F;)u2d*|V|X1O7!fxC;d}bxez`PDOQf*DI-@GM^(?-3Cu`?xtftNHaL#VZdh) zqXL1Ef4CrwLz#4qqHp3RDQRfG5qheqC0hb(%g7*_Xy-YL>YFeYO93;F@UVPGe7&4` zzq2DourF*Q5D-LmggLVuD~S%kz&0FuEgvdQuUflOCv}aNg{mZm5a0EhKU*Fp3aTvW zj9pNN{!&lbGH6Mz3awXo3X(CoQ5**W#KPNvSGGaWHEItd&WD8>F9_VOu!!46 zv6&sq=TFu7m~gg|t1Ah~#Xy%v{Q`^BWzvj32^B~N)A%G?Y;0^rX0sbOz z5Xo}9`mzFV3(AMQ+W2dt_i~h_244%8X~MK7J(0Rk1C)(D2$(EWz!z?VUx4Z>nG87# zVl7G#%GXeRPCEg&O8xq;M}-^)EP-s*_r=9I@aKdIpHr>1uw1K(nCzz=E)-UdxHYfS z;PW*RJb}cj1sq93_5h?&zbnikQ6pe~{{|>Fh`R!K;v(G(;T)3sxEK#M3nx?l+(M(k zzuM<$|Bnv7qWs9-)wT2Ix8AExxLJWGMLmpmR_fR8B4Q=GW=M*(f)9L_nuP6IHnjMH?D3oR8BvTr5 zA$u;*czVKpIz%W`l_Do}Z#p~mLP`t1RD2L2eZp;ExGNFqq50~E&u~m}gKXHjIs!ZZ z45+JwV9d4zVJ`qVgxn450)wu#sC>e!`vn}HG+Bn^$)&v$H>a}Y9Srnfx>wZZ%Z)87 zX#jSQo;KBRW7QesUrM4gvNw96^*#zDeWN&$dYRnU@{ifwosjx5=+V&9UV1prXYG7& zRPaHGP6TBzar`yDJI!F3iUI2b`9z~(2d+{IPYdiH4u_FC zVEhxfqgbZuTvkKvnodUHINC0a&-wL#CY%N$mL2es@G>YTz~mJJlmqowGUK+CR!MRV z-H0{_Z7HzMjc>u~60{h?lsMT{i(iLCdXYxJ(l|^lj=&HXgF3L0>46@^vTA&h zqjD=4)OO5SpMyuR9n|XD?F|iCpgs(S!Vy-Ou~CgB4fXT1G$d9au?qF-b8!RbLpeAX zZiLu{z=7PcHc>%LNr{cx+SzG?`f6*^suUUAtzdSVH9j8ZTlVo&*=iW~=+3@#p}1}< zfxHSQqc>04HARCEPAga)9ouDO1Up~3 zxZBOvhXXe_4<{}3TdFfZSI3HmfoX*V;1|}En-q`0Gc~}a!E87Wq4-H`>;=#LwQz=; zo(KbGSHFz~yf1+RZn@*3t;)`U!;{GA*}j_>t#YnB)U46m+$oAh{I=zMFxe22<6gdu zV)XrmcCazi2CrrdC>x|S+-x{VXTB??SzJR?2jL0?mna4OH?s?8)3UA%$ugH&%Gt0U zx*LL|u{>7F2=0t|cwMl^7eFqZZzWY{86Cgm^m+KlP4Vnf*D1B$S{A5S1bFW>zer0X zu(R7_nS!+6{}hYkSuPER)mlQWd;%u-gId?zY;35wX5mdpW78PJ6x|5*3SY+V$ z;Ta$!L+6)b9wflFN;dhPAoiz*^$T>u{&8_cYm=3Dp#Mlh^y0OjlZ3EiSlI5QwKEvbS4H{5@-=|>rd4T4zBG{b@U_o; z()3baYS3om5uwEK7KVuP@~asxc@iMe)J`dHCz*0jTm%;a7&oF&JXwQxjy*0a9@STW z$Ivulip>15(g5>wlD$^&?MmO(%PfVh_*GlTl9h{PcvN7t_`fObmAVkd2lyS!;rz^s z6NobPGdg$c2g?rzRz3oDr$?bLCtBI^!`d-2A5hL!~m(B`{cD~15;D9pj~l)=0&z{ zaWQB8Rx9454Zyr+2zi6K%CtZS8LkZFAc)NOXk7^00P33#V1y@SiR;e70ho@5zUR6r60a6vsT{~JAw`UTt&~jQ zqx>kg6Xog!3Ly})>T3{hZQEB%n_{AAg$$eh(Q?vnpAUdKh}>rK-Ic0nP>1N~=_9R^ zKNu&Selrd;QYW{pZ00YzV8OU~XhbchF`*@DOJm9q7SNE^AlNlFIzHs05~s7r9wN); zl+R~0cP-Jv$&-6#pfj=e0_~!l;KK$&+(JN>hvR@Osa|uYD&$D(>e4|bdjdY?d2oNB z{8RbOkbwD3L=%#cIHWG`{RuN+uYFF$1PO8uBFm$Gn(66#tqa&3!N9*(j_I|5k@-`l z)dSFO>0$NXmXiyuQdUyJcio(g1`1>jf<*^nXNG6f@KWLv`$L{V8CLvAtF=gn0-hx9 zk6qwxgCTJ$S%F%4RQLUrqR&UeKgmWR4HTk7CIQnfE!5jxf#>j;k|lb&tUl)w!1z8p z(pv$StyOM}V`yYF*y!U$Cv10Kt#X;L9y&f3iUe!q97&@`bINK=uIun zHh3YH$iZ?GMQGId3ex~$35o&S=n9RF97?3igj&x6HC5{>TT1E_31ei%LIRy0gXM~) z>H(*EpupV%%TL2ABbZ2FfS}z4j;HQcYSx^2a9wqQ<2tLgCARIGE+5fQE6@b}BPW*yQwMekMzC5NLiv>XRPY7fB6jVIE==hJlo_>|%ZI8zx#=f0 zoP5KPRnKQn1DFur@wX&7{Y!k^mpo+>KYJZ#)S(!@?b2i+@JJ(F3Vjwl!$z>{wtoI> z1@Bbw1AQOz^{Hy1_RJ5#J^U|vk9D(dNA#|&16uHQWnsZHi1R-HA9xp1fbs9YHI3J-YW%m;q0Q{%au&f`=XH!)gmyw zusEOGt=LEJKJzewhmZH5;+&gl@{?$UfDQKQa~w&yw?gq-E=U~vUru*#Re`H;*vdUn z6H1oiil4uO)I2x-11I~AYT|F4VjHIadUfaMuLo+dAxrs-HVeyDv$&+uA7iDlNRb6( z&o4l~Kxh&aKddH1>Xo!Ksk>51uQelCu4bbB=6@ef++y$I>>oKD(83ju2IbC&@=$?C zXeeM5e~D$@L|^hQs^EC|w~6X8_r!~$B2c{hnfUAD6WD@1C3L z1uaTxNCEwO=|!k8KDCNN?R!Ace6ewyoxs-#xKS#ZUh{wA%7<@vo#X+X71K^8Kie7p zqPzf4#U^Lpvi9|UfJpd3)%XuH6C7Qrkt#9fuD$snO^?Lg7j;+JE}_}0UM*YM6!_EN z<2=xm`GAXNVFz>W*9w`YEUX9;ta?qk^CvA_$s(5&ndM2Q&A2-@Hk)o~X;INxGv#EK zHHKHb_3TfkS~w^a+){=OT$Ddk{8U=T7!%+9O&Ae+b;ZwjEnH46AMQhaTB$_%;RCg+ zAjMYarLM;tZ)@F^X9z%?X!}u}(R>-Zfr&C2O$^r?ZH6xZdnAm)qQWF4 zPCAD%%b|2WU`_w7zf7QENm>e6XDW!+98iV5rZ7g}$H;G!Z3{L!#lWMoWQ z{Hr5|l3SZO@MT7CLHOuqY>=hI_Ydg7Zo&5t?|#NJ_a<;Rho=k|Bi`jI9SS1}FOV8V z8h`C^^TQCHkbp4ULM0;I`>4LTM6$oO3NEIR4bfB=MDS;5p<#j_lXo z20mzIjdRHvEX1lBo&IC3PfzWgoe|mz z5}9f72Bm}3sxsZ4XvAmcym^w%K=_x#@Fu&hZ37O|S?6`1fD(Y=&{TEemVMq#IjsBm zA5F^AS}Wced!4{GJ~r@6Yk-~e{p%oK?lOo1D+=cE&NXr33HJXGEe>~Aggt(;dhRX< zfbKdEl!oUNn5&6Tjt+pXxoHnPsP|S2HeyBw!2ZrAhVDin(1wT({|oeX9_U9yN^fD; zwUj~qkKiIi9DCg-LJ!Qm21dZUK4fuR@mmDEz^eq#ZlTz~ctH#z)_z*P^qV4muYW+T zm2e+q3{H|=*hkC&NcKr2`dL`o5`#m0HimN)DV^8GiHkJffPOepehGMts9LA*6c!RD zJ!IZzCkIe56}wKQ@EUCaw4U#dzlidO(XsIJlR_<$UDXc=6zAT(dl32GDxLK7^~u15 zLr_C=b2}Jvlk}x&Q*FwI(NdyYvcDwzJ%!fis~X-r`+ohzQh4D>wa7yohL_zRTKXT~ z!$4VjSCTqbmq%w;s)7y;-l)Ta%?qgz1UFJb-oyrod}kiYxNr{T?pt+^Pe_RWApd7D z5ja+Foe#)d^_BXuhwVA_8yad$`V)CJx4i4WtoywCU>*I%DqYT6f%6~n#4)X!1?gDw z;{1_Y3B5G`v%PF}<~uy&c>;ow2?`2|PyiItnJSWOiO7?u2s;?Y3xbSurHUJ<)9!ws z>sMc-rb=KG{lz)Eo_q=X@A&I*FQ1#GE9I=RfhxT0bWX&W91ki*Ffx6U7Z=ArQYV0ba+LXYPeuzR$u3qiYL4l~ zt6Qen0L_c0zk`#b#M&*q8%s;Qxk&Zbf;Y2FIOF!JmA<=|N9+xo$?HJdn=_jIaTHKy zW@eh4j&rsNVB{^pIxxP$SFBxlRIjUg;QiEYa;b{kXt*0i>lI8NS2p(4+!G4U>N2L~^cUK^&3Bvlm#3%C>W`;K=RZ9?r6f~iZb~R5Ze(X0#jo?F7WXy1YVh=G0SBXF z>5?>wYutA-k#x-NRnaU{^P6|}t9YlbTp{ykO|qhULk_L-ubzEic5|vI;I)@IC9r&Z z7AXs_aXD@R?efe$mL*AiXrb;+YqL^>UN&+wRSlYd`5pUG|F?d}Nuk!SlQ5)P@&8-b zqeUSv$P^<3%Xcq4j{y_0XOR#QF?FD9{}wusxR{{?w4vabX9mIsF~fu7kQZ8vP`?YX z{^f*ZYGP@NAioM?djQbc3$W<5>RjL4-3!@X=*k8`E=9sm91veH!g(M)ataCxsYf~T ziR_zQW-&hW+vDG3=UboRbvNuUvk7;-k1@YqN(|1)$>H0M(1$QFG11-E_iiGU8u5CT z&G2^n#zkKc@$=uN@4U#*uO^DMAR2Z1t|nnQqjB=;P1Vn%t+<55@j1j4;DrLl2Qf#?z;)z`igoI@SVRND9G>!?6#XUXf6_;iW3E>AW*% zuCkuEUn2gf)=`$JDT}JPmg(slP5qN2m4`d^s39NpZiC-m)U z{_TX6{MPl#bMFV%8UeBP#nT(m4D!eC2<7`R9HiRJUW zvK4Z)@rZC6NCp4>w7>rYTFc=wh>y}r63jg^ZJ`86Z=AnBicZYEtbPB(hY#n^pZ5n# zC9t-^pfbJ4&+F7kcYsdSKvsF##?xO57fAQV?FoTd1NkEhTzWvk1Ek<~VYI3v>=DHp zbtOPGgTy`vbOd}_A`|oy=z!ya)|m%Cd`F$HsT<=LZ|g9z^fvpCNg{v;(dz%dr9Gu- zr#6mFVe^;JZwyFxvJ|+G=lNZsNl8f|aJ$DH5#%P8cHlAe=#p&HDM4eBu=n{6CjZ@K zRnS!>3)ESzUnkSn*6!FavKf<>?UaNDM#S?Li2rrFi;)rpw84qdELl8Wmmlg4>tIIX zgf)>_vHqrdmIM?z0Ubu=%=(2gXwg8EoNn+M!))NchC=*pm#W^5u1aQe8X5GD`OA5F zzDF@ZlX#?!(fXLQc4spM+=cJLz!r_9o*u*9m%;&{!l$i6JcAb8vRNO<<@aCvK>Z6E zBVma2<9CfTYO!HwXCWp;=vZwGiT*bjv_`k!?!VIUGP-|HpwSE-tQBVM+iiJ`lW- zS)fxdf6luA@7ExL>qQ!3LN!?*g9cq#Hs^715$P(@#;hNnr>l7qoPvCe;4W)^ekbAe zj@Efqgu^~mB%@tz3#RjVc}g!O+Z z;(~kS%9Wg|%2BJ#Vk3ifaPp;IFmoq(1x-I?)z#d5k*VqFdd8h{*$|C9r$mK?n|phE z&3y!NBcg)D;eB)fzhbhyq0MSlPl(^5QxX8!3u#?ObSty8K_LhvYqBO@cBV#tD~Dso`o$)PFU`)Iv-$rA@lb=CpMlDA+? zd4Y7cb%58n14!d@D5Ou=sUcXQ*6*wlipJN-9~2X?&>dhm?vOY;z8G8=LF^b7U> zd*I}Ah>gw`Tj23K^&YHoFoHot-o2%GN zpzG)T*%-2&%`}MR6hDFJY=&IwPn-%#`9BA+|6_#vzdgW-#|^s>w^An>UPudk<|cs^ z%zuy=|I-e?Ku3s})2gGOKOGAcW+%6xu&`akU+rnIJYn<$w^hOAIgZL_ZL!1?G}b2mQXX zlSyHzw94B*J#(EJ;WWQe{rUWW6tv)a`}kCD4uZ*HT&elRKT&Y8JKh~g%-)73w&)fx zY~DvJjf}(tZrSDs<{5U;RCJ%HVIto4llBr(sNnr#H+Pvh}TBwj}LLBKmGR7Aq z-Fo)mzdp0TkGA;n4m(){F1=cXzU)D1Pp<0=+#H3F*n{`2^6UO|qLecG(XGR_YBsiF z*1ttQ&Ha6}f4-~$X5*!e-~#ysbxT4!XXopNhK3Q=XFrNcp&`bweO9|vmz?LfU+ih8 z&Q=Xc4EWQCh&4Q*d_cGNi;K=81M5cTigjC)^{K@kZtiaF)KC8eQM<&$eb@@tQCtEWM_O9fI@$Nq*~W zCNsJm+zdLt!{+SG?2O263J-VpR}kRj8h$@TT zVuBhK2cK#HQ!wqdh8DQ+LRV}y*!U*9o*z$xEN2A%bkiS6Het9itxiR;uRh=NiWEB- zX{=fvZYIr2F6-7NWyWOSQ11}mztr=&mVuZiGU(Xjj7Gl2Rn?(wdqKYE%xa)lgU~PIn8XeU@9u%C;x5f8 z|4BPMVjbUufuyGJyzUe~6d@(eT^Eh}awfk00jP?jerNqAAzRBJIN|I)5`B7X=&}|Y=<75 zPjdKjxra6dT@qYHAje_9`X%WCS{#MPX76kH#JH3ctrED^G17^*;0!(R+V^QlNJ-;U zQo?q3oq^R(`!0U8#_!}D9wl==0KP47W#8k!JVbxh{GjBb>E!|f5Nf~&usg8yOyKf^ ze{FK#c!TK&q2=aA^-|25`(#v;)S>@|_ z2YXV*<{mZtKb^gIJlB2SH~v)_iL{WiQX2M1BBi9EC}m|UMJSYA$VikCA`zh?A$ufb z6=jbiGcyU<%Kkmy)p=d_{kZS@`r~&z&g0Q>w)lQN@9}y)*XxEvW3v8z5CrETXCjqB zH7oP!^(oBr@h7N0V^7@pstlnn_Mpn#UJ1d5&Z4JUf+7Z*^z&Qoo*@GWGzK;0^0|i0 zVpsD+)W$a@4ka6vzTtDa@AV<&_FwPiYzNI^>-4YN1-?%@qEgS7(4cT3_VRNn22^02 z;6sYa9wvDNltK_n@MGLT_4wmz2reJ^;^yZkYLK*aJ0gMulHO3B$j*mGAlfdsW(hja z^sy?!PKQtQXPfq3;mWQQaO**#ajxZtQXYY-(4 zAFSYinI|y9@oU_AX)5Y);xH;|c)5&zG^m^Ksxj3%t`JsusJ}kzb&`pZL;8fOy{Q8| zk-c}kQ*StJ)7H5RXrvB0YQMZjttZI%NkbEua?gm>?pc<#K_i$j{DaMp`RRi zv^9E9-e-&Z0|(^cO7Q8BGID|FeW6F#Yx83R@<-@UI#3D`h~o-HUl-V; zqhOJyI3dGa&##{7lApgH9f&K{avE+?(X}x51FMuUu&`i~l*|^3xvu=#Xq>GBtF;T{ zjM$V(f|uBy31QbPRsKWSTDck+u-MiUQg3(03}Tj?a;`$()+ zV{|Zapt-7{2^ZLBhoPRHXS$7SXK85kG@l%c_=ri4Sx z{r2tK7VIJfWps6QMPGe(8ZEUoi_UcaV1blc@wzQ0C>8(~gDxa@;bR zT&me-%V?OV7ayj$*!l}Eq~-Z|!;8~{GR8kCRe^{;+{b@*$j-az`TOtY-Itz@W%=wL1=I_D@~*i&pr$Gx51vU1jPfts*uvr6sANlNWEw z+^{E(Rh%h5YI=gl6C~^>M@4L!PVk2G({}NxjY-rK85MMq-H=E^zOkP|LHolj{S^?3 zw~Tq+Q)-v_<~AG?J%FoQG&|tCLYo&wBwW&5{!5!q-f+6OUy*YZZqBctUL;*8S%(m5ABk^igXCKRqK01ml8AcLl# z?)>@l6wct26O)tj@YRtBqTQyS=pZ?Y|77Ol>-!!Oq*^pS!%8 zksxY6&dKpwj&$ztjp;k|bF1euCMNIjW(kr;g-(?U##RwKjSmbAGgj*C4_@php8-eP z`#gsU2nFr1Ul0}`f9%-S9Xn{TocGv-2%IRAm7OHtdCp10{i<=+ZtbTSWxNIUp3$Rj zkc{7?^!ZNDlJCd66~9D+m@U1o_+1nZeLlHyE%T-Eflp|nJ8_x5Cz?DQ6Hn3DZ`@}q zKq7s-bso0{(Q8P=Rm#Umoit>Yc|XSHR1sWY=DSTnE`jCd==k~<8LbbWWHmVpgI!q@ zvEgcL2SLkZAJFE(YEjo=qp1wttz~~Thl*XO1hyVD02a@uJ>`dR@kgMo+_{qBT z)jkIW9hXziS=w*;#_lI~CHY(>!xNKloB--Hh4BGau?T>!U!Gz&qPK$P8?B8e6IUsK z#uT$AA$%B~?-dS$ulNo-Y|yLhf;#LA8|THK&?dJ51`l`JEi1%i>5lcIv@tFb+kaC# zJAk4W^d>6%)?$y%oXnc_r3NrFefXmIq<#%MyAKe9^-$_CAQH_JyV(G`ZMdGpvo2@8 z61A;PFcS52d&yY3^S+wa>a-74uH$WN?oZO=udSosebat91q`d`%huiEzes4tY-nHB zFWkp1juJGCDt&ojPp=;~8DOAx_{+w)hiCI?W?1Y|zctVMUh1+JmF4FqYo*oS2Y(=y>VCppHtya%4gD~ zR6-zl`O5v$tTlHHhO;zjd$_HX#b1%26EDSeqX-=0Bq|-eG@_RQV)d)XS|RYt4J9+f zkP-ZSASB5XL^XX}0L3p|k1zU4McXQ`%)Gz2bgs6uqzlr|OlT=I7Y45n&p7*VZ1j?$O0N*+6Al zmX-hk!4t8Wo!$EMD*$=FN6$xOH71QF#_eKGYJ)=7&g1$GU$wJUE%Lwa(NN;7I9VM0 z#F06BIVPW$iR(a~ocDe~-8Y}2BxUYz6kSH7rRYrl>qee~hO2cn}?YUfB7yR>M2KCGN^@xcAYC#V0Tu(@~$ik2nD{grk|C#32^V}j!T(ur%xHX?39r^-vWD{5Bo z?_VDf+I;dKiMh!t<~`87%LO=dS1SZ&+_$=Zy%RDNNKk0LLfIc#RAwJ64jngs;5cWnQgs_j<>_nQ>c>`cNnYSiIa2>pN}p3)eMp z@Edcd`V7<3EWkS@%~VQU6rrJ!9|A5kc99ebE*9WvtD&9R9ko|q7=06Dc<{Zpm9a+Hyx8}RfH9IpY6}Ky9fx3Mg@xx>D@uZcFTcZzlR{3l-oqwM#7oU zNO^R28W2+lfHL`Hz5Eoo*YOH^P>w(v`e?VwI_TxRD=QU=^oF90{*A~gKkkT>#~nL{ zt+RFieh#?tit&aL9^65TOJ`?iM@RuWDlB#Am^=R!-&DOCccsC^@3H96={}dYv^aO} zjrA_5b={c`{HC0iUD&-iKXDp1cftt^=Z!9V`s|sg^>^Z`+lao*BP1kbkMidoh}$FQ zH#CN+jx*PZR`@r*0OGX0;V9~CHjaFcMbP>4=W1hPV}P<IjpyH;4BpfkNKA_jRx2H-D zA-;w>{(HDtd1Q|_WKg+4Vzgvd67@=8xA$qpSNo!IM(D?DNWZihyo5%Pag zE;M=H!M5jg!tq%*OxP0{3Gy}+Vh_SR``&Bl#%6k?@-`Dqly$=1Dl zHky}e85Fy+Jy9MT?De0BcTB%!$ zGC?PJ?=Y}E&5u<0>La1%^U=A&bn(Un%mlzku1Gr_`g*qbq4MX054x2tr`5$5~ z>z!Yq-gYb6X5F%!MWA7!!~lQ}2*?_N9nLhYU&U1E7FFA(A-jz2Fpq zt`L69t5ImPFsrLEHR=_@Cg?3E6H4+!aKn4!!eaM+wh766HHx~*D zRweOw{`f&JDJl8<#S7L}PXLI~2+F`gz*t;dOpulSCpTB)n24E&Soz>!LH95`qchhwTqBcUv5r|>6rej33>-2d@VbBVzv^#O#+O- zt(l*mcReTXgPRI|3zRs^)6&v14h^HzH!wDS@nCiIee@w9L6WLYIwShGLUn%^l46J( znL@#>`abg3;$7(GFV8&)41C(Kh;%Ak37VimcAVNcseQPNegYO4dakT22TA z)VIviO#3g4^D)AhSOW6>4AM1;1%epC^78U5QI8P3{!_cC)E1YJ0}IVO$`SGg5Ku9TUcU`pz%#|z_`BN-l4E3(u#CjnKvS^mxK@dP< zo5`0T+Z?D2g+gdB(&xHwHz4<;;E+S1o(_!>VIj^ zDipxnkeG4Ke!Ir{Nv-k|-Z*XK%ltUjLiz(ZFdFE6Oj10{-_-2Nh<&U$;^jf-I{)sX z9X>V+Q145&1sA7`y$dceVvoT=R98LihYTq~mZHoh9vOCNYdVCfe96Bl`Liv@9ne@$ zPXCj`g#Eqn{+?LAAIgNMxEzsn>5%%FmmVL8v-CdKeNg!10s-&YR9$QfmDX3s2}by% z%reZ|H-QC#t5k68PGcXjiizTv}YH!*NY6Uo=Z; zcRwCf@xOidRs-fRbYhzk`v`G8;u(>O1feyoZ)}H21o7jveU~0$5dg@?qgxJlSjSnx0Lt{g9Xmyj6+wUjVB@iBvW{^UNwJMarDCG`Vxhm zwW*8G^s7NMXkU4Y_^q5>!6%-_#&%;%A*?SrCs!pAIQYA=G7>SmQR@10q^GdF>uvBR zMICv$L=#86UBoK@=Nt<*g78@;{|{OUls#`7S$++N*P1lykqH}d@>t79u^Vc0?JSVf zgrwA655dlxHYVPMuRSH4bwI?SFc-GutD1hIhNV%cJC7?UknCB(S9!H1Tqtu)Qtd2Q`F?c6RuFE2!9e$8kEA_C2M=xl}-)Fhues5kx%q2II+E}7l& z4r;#R9FOALr_+~eUgu23*3~GfdGb2P$NtG_7TWWLdfei5MRgCOo$4N_A>TJf_+r+A z_1O#)@T_}^dZqF}FO{GiCsCQ$F&i{Djly}frzPkA9rDn^tj;j}58OXU*{N)^Ls*a% z35M?KU$f+pp6GMkJYMUGzS9cuDFQ~Zs_Ta!SO0^CGZTO`!5dQl49PZP0Y)vAlAiAK z_Ca4-$WSJ~kJ9iSwcPy9ZU%%a8jZXBg5Z*df_1^_a4PUQPsI@1Sw}~i4*MQPpG^|< z6hfyAb>weGrCtm@45Rab=yinnaG|XD^ug-v<;Vv^V z(@oinc^tpzUT+0C1nQT#PPYdHXY>rm_l#&?bh?Z zYQ=jQP5)~E;_KA=&MzexA=3!B6+X#Y@k=Wa5rDTaNKeS|ik6eH8f~=4};n zj2aFv4<&yyj!Tq1*?5%B)yJf#cBV!ZDF~HqIG72H;Z~Ao zZbQV_jVAiYeRe{B*kvLE(b3TRRHFE}PASU*zb9q}esOPWG)V0d(XLTJ@5+6ff#*$m}rL?fOb!N^w zBGTuM`LZ7Em*tbgO30H+TIn%E&o&kF%Q3BeyAl0&qI0Qs1KzxLoHQ_(-Nx?WO7? zapTpnmczSb-igcsd9*t;M$}N-CM^UpW87mZ{i~2n~OK9@S z3Js&zMxEC4h$j&^c1PmmM0N!;6G0_9ew~RS%JHUKka8jH->6!XB|sC$?E@%Zfd^OKdw9A2YwT z*Owdd57fuq@h?yE%A#~!meKm&&+(x-$6_VtI(a$|E-rB$ci21Nysp7LHe_yZ*y*ov zaX6qW!=;GIc&mBaYbt1r$sGmaj*fw0x81M!pp1-+>w*_kVLBz)CSZ?*PYxl%`hHsu z-y!#K5ehPX8v#QT;P1pBLOL}xU)+exs%+=YS6qB-Gd|fhJ_mUN`_1J ze`HFJG1EZrVk0XB?zOJ(-_KplRou=$A$&QxL(ejC#H%eK$Nx4*uhf0N9h8I1*#AjD z_xP8r;+FM26j(0d*ZABZDOT~DzwGMnx?dedhiF18WvDDLxx+ZQpEeg9=jgPhpw)q& z*%o#s!-+D(N>?s9apbM0IAogo=Qfve-i#n>`wn^n> z*)IfrMxN^`NK8;KMWNDqeXWNEB=0pqqE>dV%F*ikX;z!zCWTnDTA*L(epD3qJgTs7 zKabv3)O$Ge&)qdz&YxV^u~=uEO<;a_CC_I}l>cXBg2dmE3F75ayf;@OtafJPP}h!$ zC6l!0cdJ(9s=fhrELssS3!fEGg6V4xgFjgGB&v0i-39cW2U4Z{y-O+M4MtDhUJ$Dp z)Fs}6nn(MrAdo;9kHO;n3<0H(fa!veL-vMPr4pc`8N<*!5q~M@NyLq@61y3sH5oO@ z`UT)*Il)-chDlni1|ULWDL#~!7o&{r?C+<=5<$}Rss30iU?}h2zwaXEOF}u56ixlN zdG8MB180Et&I8%?D5ph`_JJ4-g}FS~2cZIzk&!`wsRyK1A+rab4J-jgBh?cz7a+I= zfzWj(*`}ZQNRasT9Finhh8j6~A`dK0#$71DFmsEz#bB$t16dAo*X(sW;`Z(jHY z4HKOsvcrE5rPo+a4{0if?_G<{vgb!&>3>r#Kd+=3IvsnsZ7bz|JO`y#-Bg5k%L;Sj zJ`=Oy*}2ymmp>X>6|9cm6lBWWQgNW^0OwaNYK1_NzwL$`ufWoqwQ>g|CTa!rFD)ES zLsS&`95~jJtd`rJx3#rBmvx2hROA7Irx~Ctc!U(oQ;%_+BjJ<*U4{gr7IvWYI1iMX zsQ*d9NE#0!RsMs}eMKEphf|Z}^^?F36ldqIbT}i2|HiMMzQp*6q6)QD9nCf5R8U-w zc(Zh2i3)U<=v}kCYS<8JIzT!%bU0 zDNX4_7|Stq9KbT%Af-5uO+uM&X0XXQqd%k*)w!oZsTc(?Y*^_w?@tjOKk0i z4HqXTZvF4tzk5LG#D<}u+CuU2@$sRL(0HZl{dlG1`)aR+pCXVd2vV zP}PMAJv5i!DEh`D!TKlk>r75l-)*Zr)>QA#?r~Y^Z&{tS*;(rS6@mbL6hRX=dNsf{T3z-W+|R6ApVsLYs|p^RI99 zGLFBMQJvod4Pu(jJiiz^dvZ!7x6)||@sQZ6FD$QLUx&zn_4w@T3l^re@6I{G?OI$> zadOTcKflc7H(I33){Yy4f?eI+JfKmN+hN|=PJUvz2Xb|<9g&V_`@i6YGox&1I6%V< zI%+%eE&=`$d8~93RC`IV{Iej(fJKh3tEXox`pp+kdeO>W5GQy8JYb%?v3o)G#$=pr zE8ZtkRsl_HxlP7ttOtAF*gOKPofQg)rq(8JR$+QdH+Jdg1Gm0avQZr*7|zWOv>Jo# zR_N@}o$10n&(iuet^SwO47BaHkr_RG4SyGjy|9@cY|BXpQ+6d(zYIpycaJUJzO?ee z8AuO_c|_#h^7>y^MwhprX7TwSovI7-FfNYc-zgDpWPD<2gDql>inT-$j$MM z?_9ut((dd`J2j)5b$#8EOX^wbQ)prYClb3xdKUGyPAnQ4hvpw~LNWK{0)7#XmSpM*RXzVEzB%PK4qVoqhhOz^mWdacM^PkKW z3BuusB%{RrNobQGQc`|ZSoILa+VRt;o1|`aZSEm4PN=l=oydrzMWhq(NXqmfa|YTG z!c}N#g;k4ku(M+f&x^Ch`4Ypsp`;*KFCH@sK}rZ<3`kzZI1;>+t3t(BmO?`dWlNZ-s8C6skr=R8P_+x=iZ)u5*Gd$Sr{-DUw{_S3yT3yeiVgZ z)UBmO5^3Gt-Aw><+_jyk2Wu5X1sn~dCcpZYd1MF2R6AcA5e6PfMMWj;8hrGXR`BVC z2D=Wo)^e?)mr-tpQ6}2;8zJ}af?VX#*|Y0VEV+Zm06p9Tp!bfa=P^yaqpAH(lhKx= z`VX7b>IacdVL$jPdkv;8_0E@SMK_+S9Dlr1K!5?L@3*}Y0q+NQn+e0bE%3|NurD~` zMg7OtS65P2^%iJi4ny4fD`)zGvntc?teFuX^e}c&X%MS}EF<^6l#%0tJmWDVZCVTu*U{u>z|db*8d_t_44q4*`1 zh4&8^C&$J};&P?~2JEaO@gabEP7aYj4|~hl@1B`e5d_-8+isYS!97e)TFiimZSMzw z7aW!!RMB@s!w((xL0n%%Iv{`KNKr}2a$L$K{#y?7ISM)9GB|^B1CRWB?@BJ@Q0!ZM ziOh+>RyaD6uc5~HLeERUCB2d}Vv~LM?^{$wW4C^8va!t=9ZK5bKIrCoKKf4i+Dkg$ za-!gOZrM!Z;bQw0nO+&UydK>s)p&3(I(laJAuB@$whnM;W6)&v0L(mwYmEe3L&<4a zuN&_}-5M#lRfn1*OFGC=pjtWW|bBHoTAe=oSELxcpX-Zw&Ubb?CbXoikW z+4M8xNy9*wriO;}$^u1AF8?b5Mn)M1g4%{_Y2wS3St@&8?RA=Y6GNTr5-Z>KEPMK$ zS0_)IXrE8=8o3We}&#pEGJ1t}6qhv#w}rJ_W^1x`p45*i0L z+vHI5dZY+_4joAJA!sI9T!@W8uaSbF?hCT*h{!F1yG8`AN(MHu6_}-U3~VJyRv7jf zxjB;WiSoe*>@CV9!Uv3jE#k&>wRg@4A~68dMug8}cosZRCcG2)($Z zga|+gLx#UJe$;FPbTTsI+<{mBiJ!Z7PYx@Vm>d47JFq9-L!{`NC9R2K1*6i&plR6x zCJk`+Z@j)bAT(lJWc~_Ne5F9*v2B>>wve~Lz#;uWkT+R>vSr;S1Y)hn)Hy@HpKCO?878W$k6My+*cRVw)J&lfFS_H+ zE~)Nqmlxmqu2MRor~nA+~q&l+dC6%`-VCHVPY%CQ~@Y;Itq7yx>J@P%STXAh|Q z9%he$g`Oe#XY zQ!Q3{1hH_*W35A)!{cofm!{`oY^Nk@^=K(o%4$zVcXaWnw~MO0f~&ByHFb9PxnhzR zNe!K?6Sk2k_8{bKnzbJRnUfddA&X6yY{Lm38t~d}KB4pOD1NOKJP4{%FXkxO``x8wPTyU3e&+N2!fF zvz2ti1PJVHB;%3+-(zyfq#>MT9iM^@_gK>c~%rnY^)J(98#@ zL|QvS)In?E1^Sv>K)^?0gr8ebkP*EBztvnZ)ukhX`fu3@jYs;10mI;n2&RGddH3&Y zN}rd~L>%NAQH)!&gxBKQ`%o#cxY~e6TlMvY!x)^Ki??{8cu30BY@C=XX-n_RnWO^%fElYNFilOC!0Z7Yea?x0XS+Ns~k zjJby1ly4--LZk@7EmsG6WB27+3MsHr1;kG5G6OV@eB?B+v{t}FFE_Z&&|wi5fWNW_6}4bcc3l1Ff-oAJ3T`< z8Egai&WN~%5Vw#Pwe+j;F+)lQtq&E3Ehs*b$@z3TfA<3JwS7>s(f~?<0J{?kTj^mk z@(Z`yVWAKb(o0%y>nFmG>Mj48G>9h>FBe{$LlF06i1$O%LwbENF)?n1bOX?ZukKR}hxIw3r z|D}idlu7OLd&DORyQgbN2y2H!KL=j%)yIe)z(-(1N#+iH1o;yv8R_#mRYYbO$k?CzLB!$Ppt0$B1SJiF(~}fDIH!(UHYCh9E6L>xb6VoXktv z&zs4-$RZ{Sn#)`_|D`2Ne~>X6)~9UiUy@Ziz?Qzct)$W*R$P@?jxN33MYD0-B8)8; zCFL{V%)psGwN^u>hhEhkP&8?AQVq*4jQ4)T)Tx*(B_J+DgG&@4C}he|`iflqum&5L z=w4r2b}b_-c?C7~dE{BOEI^9uMHDuGZV3fSC^b;y$U=U8To#5!vanFSEeBue0#Y5= zs|U8-I$TI@IznYcb_-1nndUV5>lgXIDOX$fTopJI4&bN~Nm?jCFgl|QZSEM}b2nr| z6qkQs4gqIor-!`}+hhRiT%3Nv0RTn1Lx1obCfWHlqzXc9GX^}T3$+zt@d(9(hN>I% zPRmFc+5&>A5flo|c?qJS|IDPB(+jujaG)h4Q;@TzqpJ&JfY!x3(-@&whNVizA(2QA zGOKS4O9uM*-~o0t#3Vcth|>LnrNzxC$d90J5Jey_r4YR2HNtVA@*|`M(1|lUuoqY!x2T{J-b#XFxksJ_#*LYZZ}TwWfb=gzV2u_>ZK3$ z8sXx1K7C0M3-+`Efd~wQe4~ka`J3=CT)TG79y&Ce zWqKZR(GgT20uL+^vT}{3$4r2nvY2 zZNdnee$6JzGPL!81TlVh1Bp*ZRXU1|v5Z1kkM`V?O9!x-h;>8vjWrd89GoEN-w_Xs z3~cSc(RYYmct=OZpHW~EBr_DdOPFLKBZ}B<5@?$x11%RSlVWUEUo1)D(f8k`u;Y&> zf^-w`{!l|LL5@9gFJ~^z64&84Z%oX!)1_9&xUva}=$^|Zo*ac_gDlCo<`WFGcp8I3 zx-8unuj4UhWUIuU$}9asOiI{kMIOlp!A*pRlX_u#8^$WZ zvlxYEqJ6FY2GYGmE#<2zP@V z4?AqdzT9~x#{ww0+#?3T&mG~+zFa3~(TaNE0?=I&qznLMDhp!<2~bm)ZhV^J0(j=` z`W>~nf!56-RgMf5B)gm9LSlPSptQUt<7VNwAOt+a=Q=Uy4-O$Lf3u8Vm9yYKyO zIoN!!r9!C>Q!c)7&qIDDSGF(RRZ>#=eDj(uehC@Zu|HRz304ih)uoQR7_@#6k9h0s z-$W4tJJmoY^bb;@GX$Sn#iKaNsfVSCAe);2{N;3Hywp^+5k;K zTe0J2e1}FQ<;Ik$`&8He)u!{Qbvjr>uZZY8z-j%Xi~ggJLKnsbuU#1=Q=-r>5*0C# zF`;_H-qSFZh4&f7k|$uDL+D2kk9q{RcqY{-K=u2qdiGT0#D`W1hpDUq;1}FE79RS! zs0)bh3EoXY%My7Llu$xCuU#NED~8Dpb&;FatE1>5DxBsK2oj}V;7nxEkf3{`!e?Gt zYiMYQ`i_hPBR&*pWp;nz;edFngdkB(dN&zKt~&09j9u|iOCExjiSat;VX+wtMRW-$ zBA*?1vw{7Uo&Cxn>)rst@@kbsl$|H(;zR40<$jgs)#J%iRnR$mtg$zrS{o7bM39?i z2R}+f3G0D+Y9IxrkatHb?7a$|=-K z(qtS8n82VfM3t@>Dn?DpUlN^&a*2>t4F@n8*g!z{%?2Q1^1x=GjPin~DH^+w*?E{$ zA;{tqfh?IQ+;RJSZ_O4aDmYL+K-ivoYsh>tf0(O5o1HdL^21Qexr4 z_zjJja{dh)%FNUw z^>t78q?(fLle7Iv(^;Atqhm2k?iwo%mD_xhV(C2=ncJcy3p7h~9I7>QPF$s|rVz|D zK~lO4Y;i_&Bz2+42<;tv3n7#=t4WQDd!iU;duLg;I=s4%M9#aNVy3e?SKz!K1O1d^ zLk-LVf`V@2#OT4or_mg)+MqaQWi-C)Gp=YdZA7|nFA?s7k!9UAsVLuAq-k^?Zl`PW z1#HzAa`7SH9+TzmTCSmoyau0pB?nhI|Ana8AS&9v>V|}CZYfMmU4482ly`re!9*Yi zDhpr~Bn6)cd$~wTG72|C65{}o+ZEe~?jKrAPCRI@ExIq<_&=ZkpZxAe0-cjAyNsK zd5>K%>-5q-jR{fZliB))%zNVCpH^2B`Hk5}LTUE226?+_|IoSvE8CFrIK}^ZTZ)t~ zut!)4MC>FLA@1E0? z@?TgOJnt>LJu&DqZ6YW*jN{Co>DCyxjaR-&z;ee#rw?1e*rV?L3b;=R--Pp=NGrcI zHy3quaALgMBj|j9gI+_No{HUFugZfPybPy;hs7FwE^9Whmur_Rsu*W?GGuPQY!{$? zRM3D=wkn?&i4tJ__E=eXB|b2^d&#h);u269%#sd?NI*O@(cqw@c!m~~*rw1=%NvQ6 zj;PI#e$}69cHoOJXi^n_${QoKVYRdODlG|D^R9bqkhvL_v1tXHCoWYe3Xrw1n!6yD zf60D}7z5&hF(ec}!^Cu-r((nAKwvGXa(jU55gv-PfgsTi3WXTr96ZAEjGJe$TOi%@ zR)i^;2XssNW>2&nW6m0T=c%<*dVLG18%A@@{6zTNb8S%JpPFy?L=YO2k*y-b%bQMWJk{^ZP zzLH7*)Fqe*UF5f)2nssnCue8dRL{qTyjG+l3@2J#^U1NNCQ-K^D*{6+z>wC#!UAkT zH8eBkZlW$UfC~k@l|NaIi4SVGg~Uuh_VOBUMrsPw_^7uy3B;6>D|hk1zdZQ#S2f3E z&6Z^QJK4!f@w#&R$n)KgS2Jg*p)V%`3;08KWLlTS?g(cYZI_Jd3f| zs~@klzboMT;iGGd*O4s2D!@&h{x9A=ea>`-QQs_E|Jn`eGx;5dFD8c?4ROHkCr*?1 z9^(xDYy7aU1ii=8;!7sG=bEo;Zr0{nex}prtJ8v}`1CuOqsuTk+oxmkewNZOr>jZ( ziS^?{pm?pMfI4aZ;AfY$5<{@7fC6%>^tl#AWwbl{Eb>`E4zx`-{}Zd zLoOWg4nx&^rt6mxPnxsZZ1z?B#2F~WpRu>r)vZM=%aN>#i)km8u8X}BjhDu=LqsfM z%&UCKm_eTVm2&?_w4SK=mpxYYR~L+_;@bYDg{uy@WXlNYzx4sG)(P*s@=MjWFZLw$Xq7)CUJj17;$MRI3BIzvwd7kwHDQ!=U_HbonaAuh2m0b55 zFsjPZ8Z2!V)2@o1IFxaBTX5>m8mUIU>>l+sW>n zr{C&enKY5R_v=J+(@bCXp!Dsmy#^cXi%sV!(KN9yY5x0bhpXILT3Vml+7c6B*J;sR zDYh}6ZMVKzqo2dRjQ8nBaI6nk8h9IfFPhJ4S2cyvPK}s7XM5!|YH{jfZJqem-#=t1 zB?j{PCHunhd=lYSQx2h`&^?WfJ&M|Vl?@xEc*AlFuFUN0K?q?!gIS@OH_h&?mM zr9&&mz5Fi2HZgyi$U{0h;qIR)DQgQ>FQ-rnO&Rhi6iUjb7S@l@&jz8+KAtC@!Bj+H*`cYFq3Q6jZ`~AyY-6)VfwO z&>Np;ZPpws39 z>gQxPw`Id^IV!FP55na22F#$Et}ci50@M=E(TVPol+?g4fuyd*HKTU+tXO66zJvlP z>$t>3)vH&p_M?3^e8gv~uA=hb=j)!;`G|IQ(y}n*nv`^3oi*t)S=0Fjb`>Y6VdCTB zl+DZ%PzQX%KRr@eQ^g0xz8k0rQ|Q*y_@SPC>wpx6T=t6caxqLtKh%U~sQu!lOEyx| z82s}H#P4cN-;(G8Df@iAtsmz>0hTDYj|N^maq^_a>(a&p-)ln{uKaXeJvB9TG;nNg zVSiF;KI?2?(dF;dl<1<>$;(L^9ikWb5t~sl26WSD>a)h7ni;e=xv%tr8WPkhGb4jR z^VMM!ZYk?gdl_U$)|2pwsT-bYl_?htxfp_~_K)JkJ`uQGDeP0vrq-L$!fe(lIjof1 zG|Q8hZ`!o!Q)6Q+P+p<3_3PHDYG|-dhNA|G8r0U-{#;utaxrstjBBrdP|$OrbH{jj zd8HxO0k@e6n^=U5!}YxJ>LS^Vf3UP=^E`z_@pOl`%IveIXoKNAlF1_=H z^7yq*l2DDWXuIE3)`2f$0kN`D(ChGti>FV_0D)9hQF%saExUG`CjUk@p)14gZ`1N= z_n5cE!8QK_0Wm{1uU_TXHZfco!P6&tY<^sDTX;V5Tqw3mRP{QxtLsEJhpGi)U(#se+MIIAr{~@T=t4V#uN)vcUWNSXY!d?G%A>&Xaa;;}$Ga>nbAi^!^ z>FF!cN-C+T1&fwGDlV3r_^|c9brN)Jfq1Y$Y?3?_%#L_3Fn8Jv+=ow7F^&uLLvBHe0=;H-FiUUhu)W!4I*OotdUVH#PS(%t4K&l3;=65 z0e}NtZ>CAZ_RP#oo5gwP(aiuvzv+9Zy&F}&;JK882O^W3-T=ahh5L#R|9l^W1}QK0 zbYv0?hd4vc00NwPM@4bj`lXAy_yZa+8yMNDLdB0kZufATQmEJwH8r*N#yygfgU~4{ zU%QsNY4hex;2p2@^0m;813-F>iE7Vjxg3>Y7}7!{?Y4o`GENn&!F%4`!QtVF_4Q}l zaZO-aS~z%|8;J>tiHa~)ubgcO*m^7juo#}&Ag%1? zt-(9)6c93@9F0RXbM<+RK-5q{VPWxKzI+iX`!P7ktAOco5k8{8E+0Zsx{nJN7^|?} z(3n$sd3gq?3Zn4+KFG9x(jTTE;TQ~(fz?jK#N?%xwl>FX5QW0Pxi7Dfj+u?Exi6=p zkN!qte!gztr;d&!=z${+IBCIisN1-3^Y~(NTAEn0@0?;f)!NAm3KjlOT+rU$}79(^2~G6g3mse|5c zZ(n~uzpSi2I2vVj^@nH*UI2iUJ_CoWdvW2a+o4Fp0j+rgZ~vaJ@9@}Jw?* z2kw0;Ie$7#hVwqoee3RbE8A^buO3RS6BHKKz*Ls{1`NW;0rsG(t^Jq?__6LeAh*JC z)&O*s{pDtgOHubGJ?=_4E0ypm$?F41^Yq6L(=unp71R-A>(97z;~Bd6q(bnS%T!*$LD?D`+fJ$t(uytsi~pLKkPnz!Y}N-_F8M7h|9VcNr@SWQ79CtrUupk zg*w%MLg7pi;=?BwS)1Sk)OmL`6Zb35H{I`Bx!IvES-HD7IJ-OCwr2OVbGvuj+3B3H zq_CJE`z?2OmwU1zB98w#K-k&MUS!y6vk^{0ehL~McLI@r$?elaP(_sW@>hJs`ja%oAXV%wyDpA z_JxwQggQ@;^@NCbO5DGaV5UE4HGh1Z#lS$nlUi5dH&H?-l6qmc@4@PZxLmq--}xZk zNK82LSD5hpD-H!3{urpJ%rWp+en-bE0>0^fBR0*2d{EF8oc#At#{b6$JZt=lV}hx= z_Bc)2x$WCGnjm%!7BY0~M@ltx46D3K(X}c|`*#Y=n1L7~=hI^i-c(IZO$K4gSnNri z|B>v^ulZ*^=&`nWDeFdo1qA|uhtej}(lu^uC5HTEcZY<7!@^XBlbK}YqAY(oTK*a$ zFC|5dIy^d0FyEqE+J0cQMpt)SN3ftG^hT`e%UAJca~~gBzXuPh)_SnmebMP6)Fp;T zX=&F(sLbu{?Q84mMtVi++8i259gg;Ks&OpS9H-1W8T2FcUEEze63DJp4xRK*$E;76 zk)uZ?t5wzt1Vzqf$BDwA#f9@mmR^}x>Fo=;mdN8FqZXbWF8K0$R>}Dn-|)gs@AQty z6L_b3-%1*%uGsmcvfOIY;rX~TTKF7^j{*i0NF;)e<;3b^_bUl2&)>)29Tbx6JCCwG zL-XrA?P<$|le;o&KOBd%P$-V|w)-Z@2`9Xl6v)fuQvhZzO%gJg0$^yp(r?vSfkfZ0R6=N$d?TFB}C~3A&vidDe&+ie&0{xyj+t zp>W%pZDYTTNng6K6y}9`D9`wjRNsxCJX62LDZ%zTAePWCHpRB|H^E-*biMwI*SDH} zawap#jXc(lRNX2O3twe@Y_wGLbU7*dbq6oXazGoa-U=&Er;mEOATO`vN7kS6APU1) ze0OKFrhA5*-jeEV*BD$iUBk7aRUC#)be2R zo9{Rg^VB33C13r1qit{TzSbq%k3!x>go&>Q`ns|V`Kv}HHH)X7rM2*;-Eb6G-(}Fnp2B8(wgj-jC2=gdL+{5R`Lv znfZAxnd(LVpo0B1->FW$7!H0_SA+wam5s4AMca{5+%Nd*hd{}TbBg4#ws}_sp zl!tq@y(*z8Ol5|_3|PXsjb0Sa5kJEYnYQ93hj$wxLlAW}X~Jyh2PGN}8@QZz?vh*T z)W7~iXvb%2S$7JJUTTM-?xpp;7ZKh~k+M!1JHl5aovbO0Mkf-$uf$XTv!o1v)D3sY z{P+=(GI;x1euS_#ZFu-=IpinrVa;Vz=2&K?g;}AnsMI?C-tXs_GS`ZUL;g@VO*CFv zpx>FNMC;qZlf?!8_btMGu5p}mcwyd3d4`#!`b<0T$&icxgcVBY1#hLu-@CdDmq<mBr`BH7S{>oFeH z3)A=m%seU)?@YY5aBjM%a_9%cFIM0#G&Nk@gP-Tbf3>1FYu&q-dBc?=dChiFE>pm) zquYG<^M1dvhNreVY%Y}O5`@s4(s)^vs!5sk=~JgpO)V~lPfb}e%eZ6>KcJ$b;viIs zEona9?+HdznPwi=-TVDCHa^Tgi4}YKtFA=EME)gD+&A@8kIkEBpUtvI|2(2#bALvL zN@0~^DZ62VPNWa1&6VL3d5DB^TloeC28KV2IWeX7pICEWzEmzU`Xv{zH1JZqv9Ief zlbHXZSD{JSDV7VK9j`L|BNZO(vvYBs_V_g@v{QR;p|ADh$4dvb>W>*|>M1Zm*Mw$9 z>8M&fI6%?22f>zvwN7o+JP=H_xX9Pj^H z-`L1sS4s>yLpM`YGtm}~K8r#{(TQ~RJ-<-qHmB8_dhXTmY(qoC)at7Fi+hy%3LhhH zeG(S9R-NVC6_Qdc*4aec!vN{W1Wp@pyl3w)*~9`jT)2Ms$NcJ0Z)<4tS?ePd_48P^xhnj~tig;UPGG{`~iMOG|r=CR#5IUM0UNlz3HIL{q61J>pMGGbloRrV`HQB z&D8=5X6EShbml^fW>$HhEhTGfjO_i@!rhef_vS6FevGd7{X{@uKbB zwKLZpa4*;ie?QzknrQURN}@A&YxRr3JT1UaN>7?r&s%*ZUiDlpx*+pOu6+H6?Pt|q zm?--5z*qe0=ge= z-gPlG_|;?h)}FMhq~7?bskf^HyuE(c%7e}cQ?K@)4(yV=v9S^^HD`|gn6!pNdfgdU z)hqxq>l@>eCt>7lMvF%&;SP^rX`Z1KZ0U@mn_gKV4G1{FID7KwWe9Fd!f|A&I!3wD z(n3N-8YRw}-)o#>N}BfH3@@-SGfz!TUAC<^6E68GlK+9#nbe_-lvtQcFnKg>dplWz z{^MoslkYR~ms5&rl78Yd^`)ZRkokdvN8>ht2xhmBUJ5`+KJ>|sW;;lywy0*5Q<^e|@!NI}o5)#w} zMn!Efj-q$I@}gS4=3jB0?IQKtn@dJ*+Pkjr?p}=NzVtLLEedX%I8Dm2E$>nq2_<8!VBsvnciZZ^YKiRHAoy#h;E#&<^$Pg&{mWr}N6cdi!C5|Fb-*WX{mNJ-J= z=jY%0UdiXVJdC5LsEAU!bBDk9Mt$D6qO>#}T&3+Xll0V&AHm$0o>?C3tSpY!lqi=( zbsHqSyohYm;SsU-@Ekpyrfq3SNukLW{tOWj5ia-dhw(;w{aNRLRS`nnCl=<5#2;EiT=<@#`$O>9QSlXLbE zb{lOw8q?aR>Ptg(h$_Ok2C_%?| z#utX|!o9Svj@S3sy4tK%XJxVbZNBFrBqvYi7sM1?HHay0y4sK6(GXjrl50hS7oJC( z35Q)PN@B-geq9~2l<2Ef!eXnH%7bfscUS49otT@BcCLSYbM*|$1?EC0MHB~i+Ee6Y z`U92{+;3sDwIPBeiTK00WhoMZzmNr8tmRD46V;^s#!GrXX1E#vQ7);h>jCTS$C z@9*!={CFR)p`p=Y5pZ-`pBha~9h@QWt3^W@t2Vo34bQr-sX*>rV&3?pP7ZF z>{fra^)40OLn0A?oN;1!*hJ@<1QA3E+0lyf za#80AIjowRCN)Fso>dIwX8lfNb|9o~{MnerjGjApPVC;i4iPM5y*pLmtY_kD@kHUM z)0%_r0+HDh7M}wSHwYj;aRa2D&#B!!y|V~FATjejl{q;%Ibje=nc{PnGVXJWVTf!o zY>Hj4^>cJsXk$ls^Zl&!Z0QF79v=UmY63R0DzzF3n*uW|3M_=gs!x2>#D5MB&Pqsp z{c43yJ$-5K6hSUhS3H5kr6>KUP!tptfn+SQO2Wx$vUnKH4$dwm?ru@Y`_EUhc`-g~ zVV5KLnU5RK_0YjWAnDB|a)vN6Ha3PrL1Ca`WJFtDUcR+jFcQ;!?Y|(66UQr2m>|VN z)?L=BL+74&+vK@3Fjb*e1An76?5Fk3&7k`F`UzHnkCsx2T6P~kcXwd*gP)7jK~Vep zMlQcyEMjSeyH!D&{0!y7lpP02HY!*|OUWl`^{bzt1*|}E!FcWlSa;w0T1uTK6|Q7F z>jjAaKafaVa!R$-KS;z$d18<0_#p7n-@E9t83?Y?P8RlQ<{8EO2a}wa3~b$==<*;K zzrFi+{%y_TKDHn9h%{$uCGr!VIfIKrcE_LPicb`<2K5y7@K{+{4MNnp{|8pNwYl)+ zDonxF!4`e-WY5~b$9B@(^SW5p1o{bU+2v(fO=dncI(9owaQeYo;RtG8@b{taH+c>x0*ZS}q?pmwsvmZaS}S`^@{=Q=CPM;wIe zT@+W%)_}!Xm}X0~HrJC3I|L6kTzQ)cl1Ui3;vofubnIl)gO|inuMHxvb6h%WTpO<6 z$Yy=#-4etQg1oRxVZFiuJNSW`B5-qJu52iY9zVav@(X6W@fBUHnF_2NkIz_J7J2+a@!x4${pBj&Sp%kSi9*QCyk z>&{RyDe4d8iH)r>*y$}-3=_4s9!F7Hbl#GVD&VR5oq(N;V)!3s_D4}|ynS3nIHjE0K?I{IAW zY%x~riVNX5m^V@;;8+f7(Xs~zo^sn?ufSaAUNy)*Q;NioZb}#@bu4x&|5ZjCgzc&x z(#b|&x{}5nM!11e_({IXS$?s8(oNU)`#CBjNJO#afZ!J&7v~;#1GT=j)p3#SLGTln z3tBX^Bc(yxbzEF;`-l+;j7`DhFqXFsZzS?s~!!1(!#)#GbtzMEPYqO*b5*5BkCtG#T006}*BXF-V;HBIW-OF?NT^6^lcVEEbI6BMlg_FEaP zAwV(9`%n*+SiEC$Zg>d0a>YL+-nv{zEJExlk+_btbbj|esBR%9cDO&rxx8a;7KoH% z=tQ0J;N7jIFSo|uN}{G_I-^j5jFNY{og!a*GVAa(7cC(w{yUlOqu*l^5nC z(?7@-&G{l|J3s#y9$+3pR2Z*u&NO_*9RZsf7e!ISgRk0;GZMsHK`yK`R>GE(co^_U zyp_R%d-tAjw)P)mJLLhO-~Tnt+WU<;3yWkYBZ9*R7MIJm|>m#uOECj?l?Y%z=4kC7|~=2gM!XBCdNuE10f@bU4zzFy-LdjvT=y6M4z^^fk@KQR3+i=R27S><7V zzP4m3KjN%C)pI#1E@S{dH6Kf3UEeixrJ#T8X3HJL51lXwJsbJ zKEH&b>BUZ=O1(C$m&fX;1dNM2($C+ETxMfqivcKSy)n~?3WUOL7Is65Vt@jbx%>x% z@+?jF=QLbHQ+H?+FWcMGct4pVK~5`3`+R-=e=VU**2FG8VOI9?s_m-=aA&jq^V?QO@jufJh3Zg`fe{M}yI`L=ATi3|5vm0lXOj*ecpudk_*b{c>CayJDYera4$ zM1=hQ>e$1W7`<2-Z~J1BM>w5VO(eB z-s8J(XGYPE#GG{)6uXE>iQfXR%ea;uE8aN=0-JLSzAc8s_zqA~G#6E~pc7-%cp4Z( zeCgEm1o+OY+i+hZ|2+axK zeO8cFS|0-i6#oO(|5|Jb@E<)(`Y^VN!&gc=jGtI{+}qnba36z7v+pNzhT-6de;>Iu zpZD@5%~I#L*QOPD6Gtm6E7MC$`MW9kS6*Sn#SIQ*~G0}8Qj)`&k5fTR*& zMNW|yykj}OIiE#hpj0Z`e!f#$an9_0P|EWV-(N|mP;c+A;e-?vw3?3^qVvn zZJ`({+3R>5{+bh}3=$+B#2XF{oKK1;4W7O#DyQ~$*GhI%Ai5nwu96+~T=^dI^yyRU zNtgenV6rgn{I-a1c)zu}%u2oB)765E1f}k|9jU!2bJd@|EzJKsu>W-@X$=2`sLU{F zadAoj3Fn*s%$z}z85Orq%fIWMy~YaXhK*3q6a5_Z>7U;U!lR=*Mk?$#I_WGdVU$uN zZpRrWTN<2R_`Fgks=0Pp=ZmRt>1<`~BlaazKMT<>%D!K|0VV3SZaD_&tE{X{?a@`t)Mn~^cTIN zQ>h9xyo4fNQ*MYZar`)#^IF`b$QYO7=qAZ@NUF5N`-{H2lSHQ_Uj#^>M4g!xW?#r; zmT6~rMVAq(%0lqe&d(F7?jUHzMvaQpC5vZhWT5or^!D@&XIMpB)3C^0O;2P==tK~eM0}+;!M)Vv zd@Afand~UbPZ`5oTHsQpT zp_2BGA3qYJpD6-ea=qC<&=FNiO5%Ey%{zmf;c5Zx^0LXxi`f0Lu$oiL%gdKv=|0zL zev+1!cIh}ypnGt%Ww3@lnXHGsAVl9t|Qt>3&ld_P^D4B;#lVjM&-PQBc-GTJ3s>OQ1ET$j3+2 z+S-bwT}w;$nc3M()cG3;uShBX8=J}02X%LUiG?CkqzAEE{u(TL$!g=ctK>b}@_qFo zP+?h@(xhBGJVKI_>F`PD1A%}{^hvK8BcQ4Czgtfb-t7l_FbMb#>%%`ADGCo{7hiyZ`)31dL9Kl;dAKeESPG)kPba7qqI$*TufoBbb9 zsX3ScI|{Y;=_C;g^Sq;?4OU)frduXG@=p^Ig6~g0pt~5uss`b8b90k|mGwz8bwW~jtUXcvV}MaPm9Lk%zkRk3?D~lh>nIxg>T4V1R*B%Ca7{DL&BM;B!g{%^R>d4K_wcah8Kgbds za$bQeX@yDu0<_(1%>k?+*o1RaO1_5+znef3HDQ@^Jj$B<6(d zXk%leD=@*0@5bJGXs;c6dwT;X{N!KfkBK2SD!LW|GiLRB{^PCTQVyT3#fL`+yJ;BP z_oi?q^xx+R2OJw567u5qm%PqZ`=VWC(~`+&YdDy=Bt-cWP^NHajmkE$y?*=P*Qk@` zhcEb0{b1WeNvmR1RaIS&_C0zt71^F&xG!}leZCC_YO{3S*RnT7Ovd9UH5sd%$NAvcZraNmeyL6O{0JnCPFN|(cU!x=bjHPIw`amhOXM6824Vv$SV|Ta z7Byg-!~_L(#+n|~9dW`Uf8H?rE5JfVgZ#_;p~6;y}h-N9RbHwI?N*%8@- zS?1_ZJHmk+2&mPKjj8Wp(y zp1)N4_N@v9UVb|Vrrh+uhVtPsRqVdlbWtE8dk+m6{}c@mUsQzB@8WY=k6f}x;l0#U z6T}b-Pd`1u|202vv^txp#f88+P&uH0hE;|Bj}F};CEBt5>eZ`uIMG3q4mOt@e)~B= z3mFJH2+&kJrf<-kSR@?HJDfJJ+GjwqWo#Xs!1FJ39%yu1NbJpTpmhJWe4b6B|$|VC0(w?*Y)_X93mqEb=pxlwjm0N8LiA=)bH8FCP~yrZDfbVhKV# zcS2|4%#|tN0pKofStQ$$!D4?oE7yR<=LX%_ZPPt&Jn*NmSJeU$A{<_k)$1P#P)}wE zUtv50%J;6D+VBX`FxALuWrep<8Mi(#f4$T9cNi&ry&OSmmBr1K_|xyzng7i?)@KyX zbn@-H=f_E&3kBV-o!iT_VSg`Z2ar&GNxS#&p^E}mqBpOX_ktez+QDSN@)5S|k1d_o zX1|v@S#q6FLEC#LB@epv)Dfo9vpVq(Nk;P^cfPZW0uKHrg!3+NO4KvdeYXYKBx+~Y z`N6%W&_CXXHN8T;5MOW8`W zdkhS|#Kt{)0;|i6*{lB6E&QX~%qLkqayO`NCV!@39jQ|kosEZdbLRmQ5@({OkH7zBDP?;jq?`V6-f;)P6i`f585nPn- zJQW_!vrZc zT{1O6;%gP1A^MyyRhY?lK(o*Zn}yd*_?$Vb9<4On^|%c9k3akS)^i^cxmXwG=0cuH z-o4XoEB@;+ylTCWL|MVf?pP+Zu|e-v9*aOq<>|dzOP`m)mApmaZ;Sx{+QZ0`y&M2m zJ$?TCF``$kw-PK47Nv=)CI;W6eHesW@ZmzI$+Y=|;7hI13%AZhrg;|TGA_C``g=-! zb*tl0k@S6nvX)hE)89rLEuUW2XOb2_-K(=t$j16a-C=0htwiP`L@Zj`=XL*)lK(3T z`}60IC8T0N-Rio!WP>FZz|i`zi;1BD9u4~Hz-K_QRK|Sy^4oVWL5nLv%dT#Akoiii zP0!hL(t122q{Y9;>av7)y_>xS@PzDFPNQ<|ZQEHB3yf*bq+8_oKC=Ab`I@)tT1Q~w zMc19dvnx^odiICn)ws*c*dKFqR~J3bn4cU?KjLS3^^$>X%I?DXx6&DeD3kgc?mUmo zh+Wl5>HSZ^bz(a-KYt{g*s$;m;SqMC-r7zV_Xv@j*_U{xxBqDoWCFr`d*h=^xgP zevPlBC}Wn}a_9L?TtYNL7!Dd+#;(rqgLFnpPlPrVh|=`}lKX$BNCQxeM5x+X&^}>B zVi0UTb={ONQ43V&EaMXMr%X$;4*Jyn0iF7&y~g;X{b1u-YGrCQhXxN4o?>|v%FLfL z>w1Y+gE{EwMc0W@ixZ6m)WyX#J}fpLy5G0|$=PfCew@)ayszu~s8}~?w195sxB+*( zemBs}sb4XarrhP^q6t$ozAA3mbif5C{~^x*h8nQWB)@Mw=f`s@6wdRjO?+#Cf@i*4o-z^Z_Q57ESN~}-y@)@yu z^iAVBu}u@5NzezgW}zA;bmH^QPXiPT3=uH%%octdr~5MGqll=ur-0j`m%KwAcsMZv z0+DL{32@$JAhsMH?M}+vnng>eH4lvl`?S~b6m3PxUx(NzMWgiit}cTfEo#D$J@`K9ubgtjo05tGciSd z{c0%T_?;R|Wr3NQY$$d~NgAZ?T+M{SOf#N)8i-dHH#Zef3|_E#RMlH{chxYP7@RsA{`Hy~*WVh~%Y%xAavk>RX4z$}Lv?2s>;inKE0jc| zuRgnKD*&8A*J6LpwnB~P%C+b3;(7GCK$N~jk?2k=B4Ne*%-dVC=kqmff|8q0Zd@u6 zemYrE@92>7@oU_($ea2^9-c!pIX)oYD6gAK%7{@ZetGpD+221{SnOjEPfPr>i7ej1ZE$>bYQ(MM z6A&N<1K>}&)t@j&z;kM$L$3}LlH^$}HWaP9wL{K}`sGnEXctrz!A>|VC8d+LbtgAB zFXvqwCpS!xp>Q1MUlR#X0_$_h7BiCpCu$3Q&k>m(Ld)#V%BVrGEscaW(cL_K<5FG`25CM=3=LKEaG1=v@g`vjW z@h<{Sj)&iR2sn+^KIBjhwFE(FeS5nz5C^vu%I*P+V0XZfvf4ypf4u1{{f*l-g%O~z zv$0XI`?0C=MXk?`B+-vLo0=QXkm7jOXREhd~V z?ErlBK_xC2JTs)=t5E_L6`@8BK^_|}wZbhns|!j!XOEO}f4~hy!Nw+{=0#gzIdFUV zDhPWV#Dl-C(OpW#)n*2mCdZjNR<8S8*6U~fD^b5cE+j0n)Ie_Vmg|Ai*PnNZi72~5 zr|X$-4d;9VMaa$djGGF^Q}0zMt1E4bBnNbERP&TaRb$mI#N#gLabqy@oJ-T=753!F z_T8QE)pIUCgK~0mLb#BKvlV7t>Ap2GA@&ZUbm?xrQVE7LEfav3`8D8KWMvu2S><@k z<$+6wEhzm!$*9Yus(znZ?(z8_bb?l;LY;{+x9}^)5VWq89V`tzR9#)2S~b{p5g zhgs1#ztU?xd#FsY>H9qO^RQIk4{*esPL-J6{{0&l_4?bLD;a}%8nFwh<;eEN?V)=u z^DLE_c;XzgxXb0a!A^I$aS>t9-0GMWkN?<294PFL-Q$k@Agduy*yv)adb9WgZ)4%U z7X9$`i!b?1Mz7a)JcPn5)=|{7?Sf?s3I^7CvYZry{J<@)hhk>o z#RI>?pAT&L1Wp3pt8sQemEa=VpI@H)Y6oJjcAU4@dzoDN(!3XZcV&*1^;W7sBwd4Z zi-*P;-Le6Hux}_kI`h;FXnlNy<34G$)jA zp4|A>R`Boe`$Oykk)$1#nt|;Bq`2so79}D~xtysMjjmZ^$phw@1&)!xsUBEkhTHR&=wBYF!EO6$P*+)1XNfGtKVXc7oU9Bp)*+65RNueZFt z^RvgBy*&kdR#OQ!oK-V`>wHYfccqV;!!Q-=FX%I63@H?ljqi_`=NIx<|ZsI-hdD?)KpKX5^jo;0qSrZMjH+ zLqf`&7r$(D@1t$G_RUs^$w=CH$5G*VkDUn}dm7RD15S?UAg;Hw1st}v-kGx$E+|OE zPBt_U#9gqynQYRrk{NO!Zl8XC6CVYz-YaKlO-5|xG(lLkaUOyBH0R1IT`>K%UUzN`>Fw3wQz_@2FMoUOHlA|et0DYSNxr~59!L}^M21-iwitc{4Qe*J7F%KbNX>~G}gd?(tm%6N6u><1tF^itS^CJ ze+6HSe&kcZqy)I(5cVGd5`~)d#bX~k#@`8lU--S;XMJ<`wn4~6LrmW{SiCHp*S)M^ zO)P$SMGh{fsrmU(;35$#!fYGWoNZTKaZ;1FE|cwe*F?n`7rh;Yn=6@IR_;*XBXA`N zmZCJM6cZB@YSq5p-etKjNCY?H4L{1ga^Bi!xxGnOwmQHlQ;-NYZAKVe#`)z+S{sTNHdnCr(f6uOA|7QU}uQ&{6l2ZvIWBw$0r< zp}*n8TqkM$_|I&N-NbI)LdH33&LnMWHQV`3n*hu`{n9++3hFZMrEw{#UcuxeZcMov zgj50&`pbDou!gicbBjg)2?ObW)@H9@#Mz$R?jh!Gyp(;vycn$bIw=lG_*K_#b6i-79{tesnD9*alytf z4LF2_$v}@)PvpPqvNXVjYKdkzSL(BU2U*R9XE?Ulv@5(;MU1!;ZOeH)UVluJeg_UnE;SAC z%NQGO8=dOdSTD08|$>v9?F>TW7#XKHEQOMv9FJUKsLog?BfYZvMQ3 zt=6@OQ1!_>d#&&Lp~Vg7WB-5pG=g-dK1rivUuc%EV*xh1Ots*E@Vn%2vRc3P8EnVxXNeWBNclVwTbHR#7_<&)Vu6MaojxEg)+M@>U*gzv3Szqr-m88!Fj5f-b? zuGz-K!t!{?B7g<#8G+Y|y5>KoxdJnR7<7lL9n+{eOiAY7+B&Y1vvGP5a&MCczIfQ~ z0#YZ+W|>58DCZ4kvQr_kK@tF0>e8FsgC6xd6(9ncb*ngUV zMXmy>K19nx*A_-orq)*U&f{lVETNpsD5TQy{UogPsBrZA$}a2q1rZ~3qGFn=x-P5u zz4M6-;9JocXusevEZVU1{jP?Nj;)9~pN!?>!dOUFX^nUn0uFH+eRo3}A16pqS6Z$) z6ke~xH}!OLC-z}=6T5t1_7880_tc^$)8fO{50f1f6?h^ziPiuvZS*Cwt3Y)A7 zixRl+^zIKH_u{^NUlQ8HNpFeK!5T7aQcge^Mk7J)La^1 z|7X|CO;7y9*FhDSlOpfG^eO*}0vA`S(nf@6%K#y!+z~umj9_Me7sK`rdMqNrKhpxf zm7h<0iQg4am?lHF0SfiEWFpqnud^&Dz@q$qZC`y-aM1T z_evsgfZ-C5b?7M`1p^GwrimMw4wS_3>sU~dEb0Y6jEkRc(=6r2@iY?Sv zE(_vzfNAYQS}y#L_FMb=^Bz7M zv?IsbrgE}Xs_!E#_E`3|7i513$!5&U+RJ;Vx02;choIXBDCTpV5KzMvgQ$$xv{{JJ zBlHjCn@zQ@M%a-rZ*yVp+4FdyLQAbXiSh98TKfCZz$3`GOesYi@NjW)$jHzmsxS!& z*3YjY0wa_LL>SOc8^5PuNaBLIaR#@JGl1v?dQSG>R@@}g)ADyG{APF4Rl|s%rJZcA zcb!#_W>aJpFe+4f_k?9*=~ZSnNLLz~n#y3fj9L!Z+q8qinhsRY4r7Z4A*x|yR$y8O z0Tv&hl##QQCSe(hr0Jz>%Mv2AX0gkNs;SR|GoQ97;^}cy*#*QGM4vVjKi4w6y}-|n z5vPt?`)|f7C?vapOh6=gFaiD?S5#17g=Uye_zbbBBi<`u0pA_&{l3KPy+Q05y?#~& zBQ8C+v`rfM;bdUz_{~)}>{{C6*YXt}J`W|eg?sS)pQ&L(5uXbbCNi!wczHUh*%k6~ za?H>QG3eV1W<-#diz|wtk~C@bkp$xIhg)6$jL;cjDP>#Vj%A0}T>fkMBs?g^MwV#7 zmyFrG*6YvWHR`ra>@#^9n}zg&L9;tmdem*CQzT+Jcx)OjPag$2)yLOABAmbHKmIHl z(biHP4H8VLm47^({@7}%Y7K7%P?)UHe6?FAJo%{j6gG#<((gmlF zV*5`%_I~{0FE?D9C$RjY`1ASRRFf&6gb#9rMxGDs^atcE1we=*K4u?;}ualEeW&L?W#t z>`?nVLp3*S`qIxsQ_RiSm3q&Wpo)rn-tFJCG&Fe2g)W}Hb$mVaTVo8kk?Pt?oQsze z>Tdm>+y&e6!)wJ)C0O~E>Iobkf2@AUi|MYHGIO4MDogo@3MCV9!j+9F1?b~=iiG-7 z(8_7wN-gIQXdp^BFiTBM4JAwsFH8p)85l~#bhrfu(x6YmD3{JS=jO*}KD#wFHDREw zP1qo$(tjuVm;vtl#PCIcmlZq$ko2zR24l|hkjDp%o?$ucLjS_$G6IghS9U;&-ddZqSQC5k;>91>D(=;YmlQ0ioyP+nE-rzO9;wEz zxYacnG`~K>CK8DWEtI*o=pA(|GN4`b;fudW^602TIj-R`YdL=P1U_U0Vq@d9JCC4& z49oI7WO23sR^kNld#Cp)bphPAp8NLByb(fGOz5lW|5uqg*q1IaFj#fEuaqr{%_BECcW=T^P8q-!vHc_Q6ixznff1(w z&(_x3e1NOf*lF->;o8g0Znb^6{8gX*=8yQRW9c;F-1UfZjo%SGggqWV6zOYl!Kd)3 zdG%^;>M%gyv@8E#TT{CYIJdI3Izn9OP-u!5p#x$8{H$oDtzUYyR>ObP&xD^J3Atxo za2C8`EYReM9zm}AFRz$Ib(Xu~%!;eG+Rp8#9!xQlUib`oWKR%B&hB{{ks z&f-wp?wIK!H=q;5Mas?IjR#h{wPu2l%-)k%6Ei+i@rZXHol5EJC7^WZ{4#uNYfGGM z_VX7UkLJQC?KKOPzK=Y=S7pITHg)l#%i_}I;-Lz6NdK_yHT3kt%m7d_$5;H@0|g#S z?@4O4yP1=r;rx%F-(1dTix4&S>(})?x_X?c?GMc)=vX1&twr=3qayyledlY7!{g43=Bj;jfR0#PC&-Y>v{r3EU1d@km?^k zd>9@RBdwp?btOXzplUEXp;{BPcZyJ{JIEaDu3c>QKe}9CBt#e#2C0q4%|*5DyRsegH?_qUcbbamB1TKNpx zqFKG?rL|+=a@4`bgm9XiJUlkvD{sTHXo0pm9p<`e@P|miDZ_xDUok$~-@Zg$W@Tq< zo23>-YtrQBow`%g<(t*um<6USB`DM<9_-#gtoEQXb@%kBf|E*ITs%^~>)9&eY6-0Z zyN|6pR=l>_aWpbV{qexa;A{P}i1Ef}H&f2Ld>H=s-0@^L;Do2zd2-^G7~^&CQN&|~ zL2ZDJ!X4gMi3-17?ZD^CcDI3mm|vU8zP}uHcXqlE z48VF1@pm17f;tW3_pkFSC@7dz-JyXQ3x;K#1EL+s4+J}Flg^P(x$NOeYJZ;xgE@N^ zO-maJb3j|4Sv5gm*XVy2Y)l&0b_@tCi|~{`dkaQd$2z`TDRHjn;?rZ2a2Tclch^@1 zGE&k`=-3boIQDa29UFP=`s@r0)Q9$GYY)Y2x~71SMPhya!L`{3mj{2<%=-q0=XSE1 z;})1V%G!#X#%ADKMZCV7M)_>b}GZY=@Q z`hgTJ&>yJ^1{O>C1RVpEl$7q(JRsZwtn`T?A|(|n zKY?aT3QEdTb!JYLCXZiY9JBP?+{FF-{76_bOv|f%TP_Rku~Mj^ZMvdcq0B71zh(~D zIKd}cavbq3K7eo8G3PKNF6RZRt=jSRg_EN|PNcnJV9){FWR$S5@C-mrtUh%o-<7;@ zC`#UXoA1%R|QQ z12sCZ7AQAXz z@5Z@#GtZOlZWB4b+YvawC}Q_4+wO8^`fWxmE-dhX=^P}sLD?%C4SVxx){q|Ecl300 zsG-@K3%={0oV0+3nwJr0r5ZLXTS33>e3jv&k^NdIgpkvO0c z&XLXgy-WV`gj8v@uhL`{F2zuxY0iIlmf`6iI%Dx5!lPqptV#dBb9DXNH1^T_CrU8( zKhd68nIe}g3~VY;Q-PQ61(@7QD{R=v&`a-vYfd>$G!R)>SRf|p>=UzQe-@V-?`H zN>{po88n&>9vT^800=6zr%h(bG`zo!>wp{RXxaVC-kSlP7)(@h8k%QJwGwyA;?26G zy&=dW9;7OYe}oLI)}6PW*TH-Ot;mm_vmh2FO!kb6M#1UJe=SD2@yn-_fL-tr)KP&N z4XdBP3l0_x=64sX`8l4*J^6Z2O5tTV@Fs#+Wmb#3lhxo!`poIWqjD&>KK}Z0k_-i! zAwuhAkU@R|Jaqvkxd*x?qWxL98*U0~=MU^GBTWby-NL06RHdL7=|;4JTn6TtR@2rK z1K?ZW4KPrvw1N7XOBT}2Usqp`0CM$}N*hnxd151e>cXKa_$gRp?w@l*i{HH;`v5FM zq7v_m!9AS*{P~_HW9&mP4*|0a?>zv&mY-j=r!ZVyhgz)xap%;o`xgF{1or5s{*hC< zq-`)5T>X5*@3uo^9wyGlAAhS9}~bk_5Q9a?f{;03v}dF#aKiu zwlOe4S8H@;Iw{8Z%wIjw(b17**OR0!Phg5XC9igVTSUPw*k}*swvx`>qF$Y| zBY-WGC@pq65Vkv_`T#BRGmcBU6m;cwyxU5^zqLVk^9PUU=4M4&5p#$1!0tkq&(Bi- zB_(LBtcv`RASeOE#iq|S)B2DA5MfB$MVwvTRSMhrZG{`qPG_*24|aDV3|}+<)i+4< zD!i@d=7%i#2H&0K*2>#oM4?3wnuN_3qCON`k{4B|80B?TtxriNNm8IwW03xeoa2id z7i$z00DdYSBUu;aM$J4BmN!nF@f$dDG1zRCKvrUDlFZ&i1V!Ej3h?J$At zgv*@eZur_>_I>FQkintQApjp#D|n$jnqE5)>!}$Th4e52jFvmB-?K>fo+fcSe&0Wm z0k9X^Lu>|e?*p~r;_BLpP*O39$Mi@ijE2VN`Zb`y@KM8!zS7VLQwF}_#sh#g?9h?} z)JQwbm8HFX*g|Fi>z%5%W@V79$q}X&8u!IOMTQP|Wu`QEVUMUK3aF_tKyvVh^as+* zdAUTC)Ir~}S%Vjn6x*S73|R$^=Mkn<9~i2Rt}YC?8=zNuE;3m#s#S{-T>WKm2=YRY zP#?`S!=(J~$SdnHU%<7N{=@DU3kbcl|7v1cWV+6AiX!mLtVov6$xm)R=UWpE=d*Ki z{^`?%Hrq0I8Oav-o4cDpRz{(`e0-8jev01u%>Mix7eoRGprWzcY|d%7j;s_ zPot1FbY@w1Ldbjw-CF9q>y$3*K@7Ms6kb$;vIN+7Yao{hT3SN^xhy`o1dd`siza6A zRFcPxl5OWc$vu+y-LV9||FuyOqpdiD*^L`Lh98uZK3e|eW)L&?3-c$J4-IYYAe>0Q z;ysIr8-9dK9=Wyrlj33euk&6mQx7#~ZcjAS_1S>4dxhVa#$#hfjf6oQ53sSzy?bAh zQ~<0NnUzp6GG6=_378K3v!41&`v zV%B&Fov7N#{NhJ`_m=B_5kdzyDbbp|(vm}22UnBKgonHZ303N}$%&z1gl%=AF$&f- z3DSA%f3$6k+GDXwe7UrRR?~MTxa>MA8SUC=n@VCdfcVuQ(_4X12{Yjxo8|zJAXJuy zM)k@&U+J^P_GA`dP7H0kX!ZF>NApE@jOI)Jrr95`Xpq-ZAT5nZLj}rZeX5oC`5J&h zHCE|6UkR1`omXMkxPVFDQN&qGi zmKfCM3VS^X=Lu#+$$*F!-OwP1w20k!>#htNETjZr3mcR!@1W711bTQ4VPUnEsLg-0 z!=I$^zb$L}K!4)F6?L74^Ji5Fqw%*@QR`#(DS5@@X3cHc*Z zD5X+{W`)cVWtOQz8B1m|r6?)MtWrXTP(&yskz}q6nKG0ynPrYdLdp-tUClJ(6H);G2<)9SrV^>F*#{-*83+FP=9H*}gs2>MZR z>%=L=&cTt;+A=XcEvQ{_8zqk~9j>y=6QyfqndaP%9`&!yFZr$G#hah3kB2@1e(EmU zW<41%OF3AjaHW)7r(QKaGht345pSGoQ9fTkCYILLjz42r#L|!mLgBa^0txc`poA2d z(8a%CqivSrR7k2`%@C>I#rZ*!VarC`&58lnL^TRLFK3#Z38>V^-iwBdNauxdK#=|s}&BMpbTo98&d4#u+@Vx_+l*Q@OyY}o^x!rA?3dg3-w>L}B zsq>GM&Mqzp?D3 znoXr9Rj6mx;^xo&InEcJ>MD5^o80!PG_dEc{M&h zzSsl?vB^tTX*XJc1)w#T_o88N$ayGvWeprAiaI)BJJqyPh-a$frCmj_7cFj)=!;uB zVD|zbfaXhcZ1T5@le@dSJ@{Yxf?_y;|4~S`f9-%Xroi7Y>*0eHlo|6w(<)7!R)d4F zN`?!j#UxFrbZE*-)WG}A{xpvN^w8j)(=2eg42#F6Y9`s!G`wg2v2q0_sD=;Qn!Irn z*Uz#(_4MPAsN*-?dC<76xZq!h8to{w{`2g`8=fg=?0J~snA!xwt9XB@s$9xPD9+A> zmC#?9488VSoPO2TVMCi5UGQtAbDGyB4&ypqo(}J@+W+v{{Y$7=Ec}QZKXp=*t4VA{ zef>PuN#OhC=yHjdRU!Hi;&w=a0Q5oEVWkwDU6g}RJYLRup_fU69+{f*_{oz#D5cuJ zT)cEi=uE?I5?}%06S;~3js!x#5Xtjxy*RIb=-t0^pdgiFS0H^;wD9G*M=l3?e2$yZ z(OaQ6JJI(B^~;Ouq@O%hPI)C8)YVbyLGQTViEprSNmNH0xOh^)9s(f&dE)rlpQsg~ zUKPeqTxvu#hx(Usg`C}bo|Vgv^PI3$Q`-0_slVVs@NEbQ640vo@O`R}RhZ~0_G0JF zYLoEv^dwYMe??HZ1QXApg!Nrj;es~dp9|b(Gvt=Bmx3g%rB{Pv$U;?x*T@x2=P!W* zgGdh5u)AMBHf3alt@sU7G72~D$pwTeK?}YaThgxi*&F>(6^?ul50CaS+$esyouFx( z=9v8PS06V^#zdDdm0fXipP&L0fR~Ge8SrL9L#x@NSOi3Tn6UH zR0D&9^069696gSG*&ZP%sZgMS&gcTJCiaf)GH$wk83j3NOHIvNi!X?2@{wDV;9`#p zDf^eNhfwXx{z5b2Hq9wXf0FgHc>vDH0ATRW%adG~E?kU-F5rTL!xEu})TzFECynKR zli;-QN6*#UVOQAX+!?EI%M2-6?G*sMkr8$X7f)1FRDGP%Dw3EYQGpx+8nOY1a%Fhf z5AU-VwWbe_9~_fdpR!QJ;V8iB{~J4l@}l(JJGz*d7^k_>mrHp?_Qbjm^opD5+xuOc|2ag@Kq-(CXv5INJZ0=i{{Z&l#JaEO`4 z|G)>x4x*MT!fy&Bbuzy5Q-qy4+CKyHYdy)nlyUTEt2Mqrcf4MvRr|>IwoERdfj`UD z2F%lLoMcie*d7bI_N8Ixd=95-k~~^s%8ts4=M9r%!~MI%cUE$FQpeqGgaTAg{g|Q! zkFcEg)3;CAmF*0*wm@XFW5Z)^Nmu;!05PsXEf5Equd=rG5U?hoi{2j-)%!gzHUr&E)^TG#W zM~nbeok-Lv4Gsyp4o}CKX>oWfAqCH-v$XGW9g`*wO!OOGD9dA9zl$U7k5c5jfor@$ zRj?PT+j5d2bpJjJ)YkEhA$OoM?MnzZE?bsMx7w9Q;Gc4%P z(M-JOePKE?-b<=XTvkFLk{z{Jk0jh0S&L(ilI0o8WEgxjL8}*tAj)$EOLg-N{-TyF z%&|MzLu!$ZN}+%wYOjd2IFMtLGUcqjS=J+e>dLF~$I78u-9cL=H$lm=iWGxcSm2ct zF#GBvMPurF=TZ>NL9Ad{NPWQFGod0ZhKcbyQd-R5K5Y;21)FSbLKY~lcM|d7*nwqy z=ia@WM6lO!D#va1;!h;X;&t3a=mn*ytc;p4lWN=w*qG^fgJ@r94lal!kYdx+)YSLf zI%ra0uRK#{f(FaBErVLH;OF{HFt!kjE;PmMGXMoi>9>BvS8O)23jtd|t_u|@tH<2v z0rDbRbwYwf}s?$XW2h3(}@*FwhQ)_-tPZ7dE$m4cNOAx^b*5BFwuib@(wF@Y|-eR}LY9;Lm{W=yaD7N+4 z?c1x+qXmPFwO!4xpLGy+mwITHetz%V42ayR_a<{sZ?ERr`Qy1NT=_WKsP32)3gZe2 z6V#=6NXRQ%xa`ZVuIJ37kC1P$U_Kb!-9iEf;fW>bDIzw_tAV|;$a+ZO=K8hmh0Zf7 z3QCv5sFg3rd~|C!aJpcq$8?gNZm3o!R1QH?i3aVHjzC!S6+%l#(XVl5m>p5WNBe%vx|$f z!aV|VBdK2eNVr`1r{4>6V-tmof7YTb;Qhhe3-E!#nTLm~rYIYy;%Jd*>Z?PF7Hl_d z97Thuj&yx|ruo8Hnh0l59(muoMN8H{vSMP9kmWLc1tkpjE=gyCdKtFyozl`<@f(S{ zZ5-vR8O|888HnQVXtcyeR61pdNBEF)&VY~$3kwUauP<@o7Ntdtc>KBkM$-2Ic$mPS zW#{CiSzMSCBwPS$DI84P_E!e)0-YodnoKjtyQ#FUZte9QrZ_y2xhRO;a$&HVm0&+uoZ~-!ln^in!qu0p zQ;9!>bk~ld?-PR13w6p)JVm4i+)Pa5LWOq&p{p#zBFE(-ui2n1(*I5Kv<3-GaESb> z?b>mVb)VHE0PjPcc?SpphPOC;RPKqoq2ZRexVXKiYqyA;|HMMXL^#GC|5@1uunUri zG88o*V86zi>4$#wqsJ%Ni=U5>hXio|5zC+^Spk(i2@%4Tpnz{VUb0H?5pe7!#w;}+ zx+I*r%dt(LUP+6V+3x;x9eVp)xQt23hbFCYswC%pC)?s&_abRui7^H?2A_Zc{>y{6 zLK;(zHY0@R?Okr|p3%_&@H#~`H4KC%BrG1V9O9nSO*5ssv}d`HE^{|bjA>_^c=CU| z=hc0Aek-SX4ADcAdq4VN_>YK;jH}CAzyqsuB>!Ba@li_0w>+BXB0iwRy9mh5x-xRk zHYMN7?bCw`F8O#;oIBsjWhh_4Oly7fl_xA*(N+@ghM7s`WA0*f zA1Ep&JVEJ|eb?62)n!4LrO~%ZvcuCi&Ah+It7Nw48&-fs(CO;?vC*?~{m8E5mex&X z^y0`T4j?tzK}2xk;ZadYMrf8@_nT_Zh_;Y>AqG=+*LL618G|lQ&vzy&urJd>_ZdtI_CoQo`kgqXEuTL!%0TRZDHb zG^s97M+m>I3cY4+b@tWYDxSml6zs~3N~UE3hsBadgL#jaR(BmGaW9oltF=mP?CgS& z)wVI>U_^Bg0r&5x>gYaH-uk3ObL$F!ApS;@CjDy zHW09AHz%jgSz`%dY3_^JL2Ih1>$T=)AOnY+$rsi)w*x#(we%6nBN5l;Z|ql1T3owd zv)UwDZC_E^-eaGr6&ynzECA>AIUr5|Tt*{@a|&e!}~RFz+x5Tgsrn2y9VYi8xE`cPee&~lgGL7h|)&lT1*FE)O^ zC$hihtilF`?uu|a$;I2$KBGcgr!tW69ewae#CZui3wvL4WpQ(*(Dnvn1CxvbY4((( z1!a*VPX{A?mxspOGOT~j;j8NBrE>h9n4C03CV{B7d(d&0AnCUE^XJ`{#me;a9Qm-X-#EXG6-6LDo(t%$lALk)87^Dvs zI3(;B=ABp2(3lYm82SrX2P~gz>*ez$(1&lAR!#x=bu{G>%kDQOWsgVI6`RL!d_i}xW3V>*HoWY`xZZI|mthMNA+`0i0qR)X zzBJ6t%*1*Qy_nPdjBTF#oE*|LPQjmupaxknRgG!DX7n zIfUUtt`CW{910qumEkkUNqKvpXy)<5OA#fG5`-Xous^|On?}T@P=TkMB z)@Z{bV#Ue*36)M9?8UD<{^ZtrV1K>UR+pwmzBSUE&A^37)UCSyi2uQ>iv#qa9Kq^* zcy4e&Oj44x&SDooucQ#;I69qD9Jf1HE(1t>^yq4eDPj!KAj@pox)rJ10nEluv2SNo z^HPDU#-T!cs+B+=%nQxz$h>#vcN(r2 zWTu}VVEYs<9uMmcr6KGdqvotn+)5!XgOE$B)&yD(?@q#p!Bu}9m{%NjF8s>%c@F_3 zg$WqZV`m$}Mn|l(cy8&?E04ftGK91*Tf=rVaKP=PJ+VSRN+7b<%da&+c5Mp)B(N8!Hz*E;-LhUeAPlYJ`L;qk$e-=pw6zZNd zk3TNt*HGG(l7ue*f~=897)%iwuvSu1l9&w$WPqN`hEhZ*VAJAdZoj`KS~n$cBuRf# zumKV$^)Mo7hA)#20*9g^8e2l0LMYphjaUZj*n6Tj~pA)R=E9d%YpKr&ufd-CSUfv&0-d_WDTZfyp$0<6(_Q*q2Nsi zb?oY~h^eV5U0fH$Bs??Yl!c;`wCmXZ{#e&G(@S0d94O$oWo5n5SGqnZJKa-B$f0GT z7(4Y+ryz3wrCm2^AxLyGUfd~Epb~U;fHZ`lnxP!Tdnd7+IN^@imE@t6ZEb7o#o5~O zW^F29PV7IZ-4vk`BMcH?4Kq-Yl&kn8-#+QNBnD_Dy#-AEA=OBdLNfO2p%b5nTfw>` zho8JL0-NEipj?G`n263Mztjl|^+v7aD^jPqF_+EI>3 zHOCre5w`G|l1ajr#0^eaq9yLCYh~YPgk;jaFx9)EXAH7jE7i) zI(q`hAi=oE6T`y2d}w~GLRCXd(+8K}u&`6Q7-U<_!jeu-0q0%P5{bn_O$t-qC^j z_i>}+o_u7E1Yn3nYQO;6Fr=}@*9rkv;M=bgaNSc3=^2!R!Ta|hO4xXOa#8`{4=L42 zL`r3KHJ|80AJc*-rZs$sk(HL-iiAGCkC*Q`Y~@mmA}4(IBG-xJ<8s&mu}F5B{V_ma zAwZ4OYzhz%!Ax*RA#jCQf^ah&obvQGL=dkSiL&VEr zIS|B@Bw6B!5`w)tzTEozTd?#3t#DVpaob5FxivJbajxKCfJU z@%)||y^Twsn8yAo*e99|?7rS*e?O4xbrS$a-gCam3FhgACpyp8ZP}9YN9@fbAOm*? zw5r^@u6NMO3i>4!GBevQuX)3feGPOR(lvbn%YK9EoHTy`dvThQK^|dMd#2_iS?F6t z!Uu9ya@SzQ)8bs=BJx}mgC|>XW`7b=efOx-2A%66NHVv{diVpa+#=;vKeS;TF2r?c zU@Opx2S-Ku14@pC2ZWHlUH=Nyjl+Y4NVFU%8=AapAQ4za)fhB6*#DU3)|y{}Gdo!8 z_9DZvy+Nu6BG7v&dAyUX8qM;e9h1H&R8?$4MBN84LqfY-)*`~<`s%-8^N($*vnv!i zj~q}k*Mpr|@-Ub38=g5@dku{{Inz^6VL~rj3Us;tjk~Lebv*^kL_~1|6(w++wEky% zEWe-M0TbE~$OaIAJl4I#8;FJdP^OerR2=>yN+`$r5%hoAL3PlrV%meX`I%3z zgaAiAy;R*>dJAroeqj?E;5zbS^qDvShk#4Vz@kkw4~S4J2L8+I7So4}FQPlU_a>FB zJHY2k3+fP7(B70kHIx?cerDtyTU*J^Rpc$7dh4@}LfpaTAmB*AISwCfi$$Dcjn563 zaf{I0@r>Ut>#+qVR7*28YgOTc#WLu~?|4XV_NnfkGUzwA&P|g!yEzgk+AtfLK62Ny8P6VZvIZlgL4qw+}(#vWP4X~Ck$2kiHY|6N^ z$`2sxJCSdoF8zy1KgZS=Qr4d7ZqJsE+s0A&=XUfO6_6U;MyXx`Xc>ngf+*#aGSA8Q@fUw)$noB zbC&nsd*Ql+_E)Nm=70S#nO(J&NlfYd*)_yd5U^k5`j^QVOBa5H--FK?v!d=Twj^jJ z-Ds%nOjWTo4z9Q!P}8?_(<@^P%yD*9-*yWoe~f^caa7!_9Ad2LmeJ73`*3?{n?cZf zH(RhJxq?UDHeYF1U{o=Atu~oy{w(tq`k-6d6>&AQO#cMBon^UN>}XVP6!GxFf42!e zY#@p(TppzWZZ81w2K_+FZ-6JHKBExL8$p;!)sDM44tV_ieW%xSIrTGmz1?fyr$}T0 z0HTn$%1a6{?3NP#!HstQzI*hoGA3z<~p!BMDEQnBl}s%giLa$OH_C z{n(Qn<-H)p$jdD?P-D^tAXX^%6ZVOH&{}E6A#=;{<$0rsX?HM`ye^Suo&U`ELFob3 zgm!d_3}V1-{85coO9L16ULc;MYo+dVmvuv3g%()bAk9bv^}khZl%B;LMsqAbefmqo z@)K04c6suzcqxn%ttWib<0m&1o>2W3tFbID(WgRnI~C`Gh~Q!Bqbjw9-m}kzdrd!2 zGD~&8xl1kfr(9B_ihsmB_vYMP}}b25FDYfhNndf`Dm=JlR2HgCu6c-C4uqx)<{ zJuY_rxeB6`BIz<--R=2rK709*k{pV@9=xUYx0QDQCE$*>gbrJ`(Z?Za7MTV}(UizM zc%)c^HzwFVqVG$JmUMpk5i{Pn{IbEn&NHy(2vlf<15W)G6lIX(R{f-zLnO3Xw=@H# z@^W<(XC6hPu*Fd9j1Jpea$~sgD?Yh3D~_$8tZ<(bmpUGC=#Qn|xEqD|x%N~$u*#dS z%goG@c8MGr>p1xz@&;Y|4-AsKBqAS69n{XChf}e<#6=7kkczw>7t| zF|7>u?D;mzwQG2@YhKTT1NuyJm%i@7L3}3#EqUY$0RF>}Sh9$*>>K%F(}-D;e2h|{kD98g{N!*5p$>Itr9(_yhB?13KSFv zPNyy9$N;{RLyM3OSq(uYq5mb_oy_9=B|>+5OWX^S|CeQ890!EWOV|diZ~s`e3g!j^ z#b=%aFuanEPN;ozV#$|xho_d}v1je_gehMpKGzhq)z!fM)VW89=`fSh3Qzm>T&Z7L z4n|*`xH-}yiD`3m_@jysGIcC@8lXASkp)2e-@dMCi9d9bR zzq{ZZYIezmJr!@?l2-SfyYb(yRDCKDzLqh*-i0fL;uweHWk`swvMu*2a(i+{e_0;K}Ha58Q;kd&kq*3{u<>!{>qFS}R`Wd?VadVwd>$Oyw-@n(}i9{w^ zfY57q$i8zS0Vq?t2J|&jSsy!&@%%8fHQSQ2?W~V$kfEQ{$*`C=!ahh-vsAYvK6x@+{cbZRAE7rfExAEQ)ICdBkWp^qQ|%BsVX9wY zjinLHwUpWZW_qc=>cQR0j#S6$qP`wFvK6+$PfW`^FbFR+`eVqD>Lypdqa_g1Z&Y(> z!n8sGN$a1ACl&T}>H|SE=(_W-U`booVM%=9sn^ad-t#ZLpz^UAjR=T~vpRuwthb9jCST>{?Sdc}p~Vs%p`oFgd5-6x zYI*?>!=|N3Af;!$-%?W!`Y(V@`xN5v4~C9C=qY)%s&e+rJEqfc`DxhMOGCcNADG^< zwsJ9{LW$llUQjRJjVu0>vRyGoA-sq`m7@4^{4#PVM}F!SLZjbNWpn#d{WA5zSfe{4 zw03b@y)mIjb~h8bn=Jrc+i3<@@gYE$;c( zrriaRiYx1n?S8K%nWX&KKVoRpU`oAF&*$@p1d_$8f@S!ZovV#be=TlJWx5CT3uZss z-FG}Iz>qW?{fncNa+RSCie&T}YYm$lb&0u3yU3Ah< z+Z|yNw4?P!r^Lp7T5v{4^>Wsht={Jpbl&ow4!fM91^4PHHO}y=34o#mctkAu4gKdN z82o*99IbNV1ugkOh0veF&x-khB8_^MYKAC9~@A{1HEX3{6)ec$C-io+8YUWctJ zy)@pAg*W%J@{hYV?NNKDwEr+16A)QI68v=BhD4Z=$O?2x44cAbynV9s0XmR~W|DC2 zQnBmAq27%{1nna^g5b1iByS1zzgUTPCzwCJ45jy8U`5fRDECVt%J+uwu2v(FeZyXh z>pTcd@Rv1v#hj&iQ`Wfoq{$fpx>T9#JBmIk#qvjsk9~fw9Y|sET%-TUP1}yuW=*?c zFZ-ci9zIE16U}hJMBNJWXNSRLpH+1cVIH7CAV4q?JfI>&xOl>vx;Ox?s7KeT^x4+98wgErf|A z@sO-K0lE`z4Ak(xKRywDGdk9I2wg8GN-5=34O~pUe14}0uwQH1R91bDAEq(VcP!j+ z#_G}bWd$wPEs9!vPG-zLyed)0L2&|d9pu_a1;gfo#EX8l`qJ3J$ z-z2|gkLZXt1J}Bdc;y>jaVm>v*B5BpWjuTBeYbUf=A|*M*GCdFnG1 zbHR>Wg~`Yaqb`YnZ+?Eh9?c$67eLJBk0rH=IS$G&z;V}56{7D8s0e!4SoXpwZxfI~ zq{(asMZOYLdOisBN(4*+1MC?aL&LY$9||O%rqFIyumA|xD!sE)K?5)s8Gis$idSe5 z$dM`90x$$up#>mATr$lbs3gc^co}eM%#-oOd8)uS(0}CEJVX*osNKo5Scr&v0R&6T zJ%>n)G?2iYiJS(F?1+@$%Ii6{ec-H7D*)3w1gRj=@j<22QyDz3E)2ULks(N72EbBK z9ehI+3UU78ZzMKfu*XDNqvBsE2Bb_0re3IQs6cuUeI1f7>tjr?u^_I;3WYFu7r?Pw z=!G&{TWQ8HbapGCgbHGDPVxQ&)=xCD);^A8K64S@E>x+QfhWM8}v z(oam&zQ@8xYKAu4$Iq{!?F~>^%x`5K7O_x#!t$!z@MQS?Xol?Iu&n)uab;iU<66r* zZG3(8wV950o1Y&Q!IGUydMQTBfA6vBSHGltzdRa#ww~+E-H0~&mY0`T*B>IXclfFW z4J;8g!|5+VBnF5vww``hUHul~jCA}=;`k;c8OSig>EMR$!LP7j!IzYjkU2G@I5KKV z3Frj24HSnNE^zC{r|U@i!|p&JSb*ypK#7z9us8)W8Y`z4xeVnffgWk>S%TToFp`Sr z`t|GNU&#@LtRBI1eqqdNB*R$28bM-1s0)H{Lu5-uA*x}}FQ+iwiQqs)IS8sL7PuIe ztU>wkP3aaoR7`~(hNkExSq+J zHgG2XV1Ul5ZUFt{4K~UY)DrPlkxvdZlnv!kqMn+rY1+~_Hu6B>#(G*Xi`Y3YoTp*G z@-{v0nX|S^^(#yX__lDN|M~doRPW_ZZEAtv1GqLhtNA5;^y6jd-I8@Y3S_ICW<#}g z==zSlqX|dCzrpv=A=b2?z# zN&$C5BD2~bJ_KGvGKwJkC6qCgYs7Lj`u-^pkgA|AX$i5UDp+v*$t5Qz zCsP2|civf$1smf$xFl90IXb`u2>{Ut{h}O%Sb3&+>oYjRc^!<(Ez&}~G1qSm z&Y&`UEaF5!vfVo3E`i+rT!UtSg%|?+`eCC?@UT!E*d-=b@P<`J)*4gdc zJfi|%-9Fn5J72%8t?#R7Z*tV}o#ARWk(Gc@-$Fa@17KzsC`n*z&8$L&SYBv$R{^o} z25>{r90Crqva0J?IXF5tqZ5a!2vdVSqqiwxvf^5|lrC;d9 z43*^+rS?aUaOx6H7*;PQa0W{?)xLe1c>WNd6rm%k2bKb;y&q3qX^Oj52mOx%c7bZa zlj{Kgmqi?X;{L6_Kfd4%6z!Oe0QmUe+~Nt`2f%fRQhH-9r}@4ipYYQ$&W95B`|t&Y z8eVzR2=&ZKmv!`mRk?_i>-fgeI@`aNXu-and-_<;{QI?_G}pzv%207R-_?9lzpw7w zaHs4-NY$P79R?Yf!f!pX%Elp%Bb7|uW`zC}jT{*)LKJIcSR-sj$Dipi0Dpc9DMNzx zGrgHz7vva!p4WbMyEfcN*WQycx#=tsk)g2@_+f|#_5NbgfQ()7xtkA}mC_q!jaTJd zv+5363U?s0KF!S7iS7|c4lb4+B9FgvMX<`!Isnm0M5P9jKOM7Dh|n8q%srQ%-25>w zXWX!ujzG|(oTZ?9974<}hgj#WR>DyU4KEV%p8u&l*bmL#O~mtjG&!|f+I=!XhbD3N zM|H*(PY38%2CAiHrr$U~BHVA8uj`a%d){EMvyDIEqkXVa`dd~l5uCMIUN4|_3WUap z_^2EmXSdHRjCn5ZYkmFSuzOo@4`}u;T>2<`r?H}f7F;pO6sDp;X1(Ob0@P+kG}nY` zZO=KkiUQH=7E}?B0ur#tiGqME*HIy&Tf}`<d<61xGY4FOx2{IZl|hH`>J z!9#e9J6i}taY*rr+M*o%po5D9FM)%}$^$w}2R8Vx4{$_~+8$C9EQ|?sE9U42oDfWd znY95>lUuvG;r#P~wS@FN&;hf^xQUU(D4c$2Z^ht_U;0BZdyyBx2w@Fq7x}q)l4y;Q ztkp0QL$m?sR}lm+^*Ds-OD9Xy3WxyswO%38j`IO4}P(imy{crz1gn3#f2Ni3l9!)#Z^*U?fbRe!Sxg z+1&~6J${wdmT^b%hZ=-+8SKD$*bg^y6M`DnHCZy_9YtR+TmjsZ$=fW9>BBn0UIxOU zlF#V5f@|SHmp?`c9xmp%mLLLrA20s+@ZO`zFg`@dnymGzeb(34M-1_V?87snT*a$l zJ-AT9WbyhRJ)-3{hp>d>Uw7y2^w<^^i#&0k-KWxSOrrpHLd`RQl_Jl0gFSTr$b+E3 z>IY8(i8<7u!XWrHSI}SoSZ)15eE5*Px(s8WFUfFk(#(QuNmPGGNM3Z&ckbV}#uujB znA-n*h-)`Sf`lSf%X;4Dex=jViAhWRJRpKZSA?qu?snRUqu%(?JVxZ&kMM+wMiyMdd zzQ!|^Z+WzucU%-d#h$SqQhg%sP*q)ir_hH=Hl1B~wI&mx60)*Ha5^h+?(5Rs4g`RJ zcPQW)Sy+5c+1BYVNKw_kZ1w)QWFZl!(8xTsbjW zG_m-ERnp^^M|uLo%_`Oz6KLGzIYT2pGw)l+8dFU3{HrzwYjfu59Mo>UFz*%9ey)r` z#aw(jo^!-#>L63xeMH<@QH-EHa!@Jf&HTs#7)^j%a<=FF|hDfWi*l* z*TqAV1$vl42X=u4Q*AXQ#YVq*E-ss0-gKWNiv^2gXvxWkICkQe+`r+Ns`J-d9FL3T zzO?Ip1or!N%EAl+lTdrb*RQj5FV8FF6O3$Zez0-en{y-i8u(d6;`vR6a7nJ70~ehWJd{sN{g=O5 z&N8(-tRukZeeJjPUAUv;(R*9APlI3}_|0`MFJiuGZM)|gmQB2jfHeR@a8C+Fs@Wgo zw{ym17L1o?mzM6d>P|UVz+n65H&qVR(hN15u3I(VN>$i}_gS56(9nq#_C`lY>V`(W z?);wBOF0s_lL_5JY7L@xfr6C`StK1VBFVsaut7Qt%~p$W^c=bS5dBd60u2JsAU+2~ z2Z2k2K!x+Rb!7lJ!BnGHS649$Fgb_v-Y+FyYRH;aP%43*;rSE31YXtU=(8W8^TG*X z9uaCpA#F8==d8gGp+8obkVN$c6409Fs5X~>hXDDEFe|NtL_wbTgtu&6rw1o^Z?**n zn37?n$JS>2=ZK-D*`F0=;hPZQfx!!_{yj5Kr3iE2KYaL5Cg5;t)qk2dhq0kt>>p44 zE0SsI|2|yrP{#i(D^@h-N0uCVhZS;reqj51M(i~!ZG*THPwf`=p4{K`n?`et0sI?Z zMVv3hVV9bkO3XH>TrL2?(+bKABjY*$84bvpe<A}@{{7DVe>2pyzdoDT!-4! z=jxr>;7B!Umeje2N1sLa1AB&k){sZ&1y=s+L+sS-Os77uGvBi~@J=OQ&kdE7mBN1S z{En{nd;f^7&TdkDVPOkzMLKKU*q`fq)w43)voc@C`L?b3A_)-aBWnC?2x!*yV>vhC ze33~VR|hw8^^^i)-EyU9F69)hHQMMcH4q@;Ia(#MV+^XT`S zpNWNo=AXYCa15Mk_fgp=;;*mjpRfk9f=%4qeMI~-e#*gC!{y~Hqn}=DqhgH|vo{O3 z&uK1xSld0wMq$+dBOiVB`Ia?@Z;h4TS2HiXJ$;}n+~G8X)V3h0ZR&H=@W0`>IVs^Z z{>Z8>rt_Jz_o~e{k0fnVub~Paf%G63Z_dvAT#A=$bYYDsWk*(PFGB{Hs6B|*`lx1w z3N2By5CIGMCLGjOw;sO8X#wJKYm=q6FLJE zWubp|`kLH*o}RW(sVK3BOE+5xgsWopXj)oY-kNy-UIpO|zY9)7(iPnYX!;4tmG@sA zru0(_IPQp!C#I&V;n5VU3G%h+EH7>dw<%(YCm$N&0=dqUPk?Iw>2S48_BuE?rf!l- zMLD(G;zgBSN>)~*ShU(D=!+&lzuSdpm}Iai0B=AT(I0xxCY8dB<6TByw_cmLEqlEp)s&p85s`9p<*F z_^fsY43w4IMe++CKYd#14`||*p+IO%OjqvJbG$v=<<#2o}U3_Vvz62{Dg_f`&p_I7)@e=MS8HlxJgVz%cV5 zZ#VjbhHd7TwyqHN>^Ms~ICFtzvhV;q1^>6o-kTZ!(24J*rckanSvyftD5j!p#`tf# z0soU<`h913_^kMrHSWk7X-uL}>QC2?FFSP>M_T(Ech_6#=w}Pu=X9VLid9x=z&Ue5 zQ*&L$m*tdtBdl7=RoO2WU*84sp7BN2ZAN3PyAWoGN%^ql6iR2=8bL;HgxWrfjAYv? zeo=AFEd~6)@r#!qgS`Po@$BEPg9|^TqCdD}v>8v}*FY6B5Ns8M2eOG>c!YJx{;;lP zVUFx_AjYB~50sRYxOeSRXliOItQkSm3a4r?*o(30-%!7az-agjf;*(mv_lKI7a!v4 zwo|v5S1KG1+@h(V-~~4DDUJk{5OgG;f4NAO<>cfH<16v-^EY8V+K18})f9@0k2gLF9^}Q>h8OcX3#CiO|IA(4$jod5$S>qE zFxwG8=q}UWqk*H|i;PT$pDZakSp`>oBhHk|FnJbu{2^I7A&=+h-A)`o{`B!ip1yfw49tAOwIDrR6GmYDG}CL?4$!VAA+~1PbR&hba!sHJ#XYKH^t_!T2e*uj zF`l$vVBq(?&7VH;DZ7mKT=N%V1Au~`-yth1D(V8yQFtAfku@{eswhV0L!4a!7l7JLbB_V#)L3 zC{p;ec;MZljKP9 zSBsXiV~0ro!TTy|YC7l6J;wop@0KT}Qf~w(;3FETyW!!9K*YKE`H%7Q^OGY9jOOQQ z|MN;pHxUIUVpV-#z;hb+B!2q)%E~)fsd$<|&yxU}QFGW)D9g%NjdvU!`0@qcP#$Hg z-|gGl=H}-09(i~>KWZ8E9XBmUD>qM57faMFQ#U6&M>jhgGbRs97grlchs%5- ze1beo_ubr_TqXGV?f>-xK1Ua8{z=oFR=5bhlajtG3U$^L`5#8nwL%*d>JhcFoQ$^D z(~VEwUaAv|xZC?yLP=8OGT6*H^>J+scb&bD9?Sl{X$pc zIU93Iy;7jcW6cZf7kri2(g$ZgGk%RxwW?8d;k=yQlD*R3J#%G$_A;kfl9=_dlp?9T z1~wV|BqY}edg7pwAJxd9#o~^1f8>?aVk63t>+OVMk97&h_841*N4A z(qnV9xt-@aFdja9c%3ixrhY4Tl`AVr3j-jx-+U9o~ zZ1Saz6clhVq`8JttH>9jo#a(JA;Oq zF6ZRQ;*!@0q*ky`@ktp=1y>5M^bNd`E!{{-bN4!LmS{#g#)^A6)LQqxKf1`)1lE%q zM}s0kP>P72?`iiZ;(O=Qh}=eZsFz1p>! zWM>&OMc%8ReS^Xxgy^!wtsAppu9nhj-rXhMSS2J9iUAF$#?^3{O7H3OJSGF;^_7Fde7E&{09&u7tj>8b=M!h0=Hb zTTje0n)r`>)IO1Y7O-2(($bO)E1V0HH8gT`*95C9@hg+1%2Z_7OX_L`xsp{jJ#O{s zL~^_8JVKXIWASTH&i`H#?JKu)`Q0T;`keaGz4vLlLuq4@>BKwn5n|JWK}m)ULfM5S zQEOy6UtBjnva@Kxx|gtE`}$5!UQKJhV41?`po7DJ#qZ}qchQDMfxhs0mcDFjRru?t z3LFa8NvTKCXl^XHwHk5U?#;E)i0OqJ<<;E;;>(ZGMLS45)e6ZsCcBjJ^gbmg(+Pmc z)1DV*o*3;aXQp#ik<&he*h^4OesN}kZaxKK^&D(FE!U|mrxagc{93s(uPhpLUlq@%UEIW|5cfs2ws9oR> zQv%!MI?i+@*X86s#KQ9>kY|^Z;ph{{8)Iu-F*|3TP^fFFG7&c!4S}zNiN&8lnTRhW z$0pYyDt4CjbebcIg@q&_Mqkk?ul(ea-DG=v-!B^Ex=#eQ6XnU}$wc26pg+dt=q{x< zOC%4+s3kEC^mlhXl=o6zMQNap_^0Ep#!cl)*DpBKJ9v}mFtM;afFyHXkwV@=^{i|J z;fj-Iw~(t|p{6F5(tUCAVUmoIv90z;ac%=uRFK3<2yl&R#Ld)1cle%O_7vf!B)eYE z^!BtJMdT<>KCw}BHa-2HNsX(T!P)F!Rm2W??-03(a~qqc=36G;Z0|ho8beDp3*qZISg$3QeoG9q zSQ3zvrpGuX3S?{MU=xfUjq}MeuLAAHHhlhvPk-(}L z#gh>qkCGwXZTo$&7)MYhm|zo`i!Pgyv{?RwR1^pI1yQ%$N`x%YIiNEmNx0Fw71Ps`~BpbBcRy zGmVao<>;2WXPvHBwyU^59m)_hKRNh*r^$u=rN?H}Tj^sW|KmM*6%~TDiAv)y0aSbj zL8Yaod(J~oLYXnO6R>k2OQh8ad0gBoG^|^P1Q?x4A-x_Pd4kb&fD^9ZyFWEelx}7^!KkjFKj87 z2h+8_1iY{v56Q^5mp-g)p{!C{=cqh}mj8+7-Z`KfhV7{H$Rc>Zmoe~FmXzmQ*xPMp9Df)2DQs zi!m`L*P&>*`*g?Te5@=x9y@0iEUL}@gGoC-p_hQaVHeio+Te* zXJ_Z7scaM!5{Z-jQ`rcT8@zgHFQg0DqON}n%nMA(N}l&g`OV4dPA?zxpg5#!nSuN) z1J{oxFME{;`-|l}b=JDNDGx=MSst*XbGcFs$}Efne~Gl6{`R$-tjZb8`3~Qq=w1U~ zEdAB+j*jb_dvVu(Q`3q$@cevq9}AZ#hzW1<#e>w&72==UKEA$-dz;e|i$RZIy~wDj zBBcF~pvb0vrGBhF7!cE3xqAlHXm`Lsa493DY%V@*bbmR;zs~!M?uh zk1mL8&vk|hwFjO{_?c7|;W^(G*64RABq=2|zqpvUzwCar`;|OSBTs?2&qAnmc4l|i zt<~uBg4?$l8u;e!32&!Ae(W3`RN;N#!t7rYp&F-~cqa)+hZ^2~)%Hs>}I6B7y+*X#G;%8Tj6g#`hp zxeiT6&MQ}FjEszyD$Z(n)A(Xt(7VRU!jhO}5iBMoq?x$*Fd||R_O9ab-X<9}HCp7s z2PP2_$~?t5T$E~tC^5uHub#0#4pZRyGmMOkb@$(4HZ?UJ9IaPY+fR$yP1oN_JR(h& zS00NL`~qE*4qd6jav){0 z*^~c*@O>0Y>E=yYTicR)KL-asj$2P2u1{2UcXnd%-mU9EVxZFanzAvKhH}i;A(5VV z9O%b{RBJjiva(`RjePLo$H~<-lqdk({AZzJ+nhA7Po(pPDM<^ooO)S++7joXb@ zzJKXY67=5rvZI|@q)Nd5ePGrAt~0=oe?o)#!W5Cf@PWwq5)U|8Z{EogB;^E^b ztO?6mX*7!Me_T>-bh)ZkN$2Yd9VJhkMX+AEF6~nW1-?|-a^0Km7jg;o3>+&Qi8(hI zXtlqPx5H&E0z@_GSHBi!zixD1bbUe3Yb|JG+(+SP_o%rO8h{30l zyLTVo`7${ZI^XG3QyZ4YavE(4b)j!Z=|gw3Sq}jboj9qqwDk7gUN{q;(yd$arMl%& zhS(u}iB)3A>y99CwYIi8AMM(_>gkz>014uX+WzrFc5AjZUjirLOAJj$v#%YgogK9k z+yOUj|H}O4Sm9aN$gDq2BiVY91n|jD9upRf^WQ_2yb#mZCaO&!yA;SuZ8o z8o?GpLBTX(8*(~&diVNk0VmWyR^BSg$vuPz!hQbFtBRQVm**eF#=eHFx?68;X~`@h zakpfQloFcl;S8i<_hDO~r<8wZ;&sq|dVEd0(#R10{B?xLkW_vyY`oV!gzwLV@Zy=a zUp6<(l49e91i=Pe#U@Br2~&(?Fx_2!wn8JHWb-)s|tcvE61Ks5%#B-ezI-UAS;Yk$uszq z#BFSBigZfP&&NYANEX)I&*i!?7(n!IZGFCqjY6Sv)zDCP*Q+bkv1-)s zoY?q=ui;+zEV+tnhyoj3HIyqIr^QMs{{<6O;;k71}$~n^!R+O+Y z1Z`TbP?8eqfzWC#Afa&mIA4FS^i>62lJmOfqQFvEEJr_f)= z`>evk6!k66m3IzZS4v)-GH!pYZ1m9!-0-Z}rW)ONZTc=UBaKF~Hn&t6)>HRJO~>(k z1fv<`BUI4mz*GA9`S~<)XBHBAiHFS~r#;L}j1bMWLVPT%E743;GFD4oO;eh7lUD)m#`Vd%^22Gfd6i^-Y_R|6;9jL)9 zDcVByY=!oKU(Y3ob%dTIkL;YDm28&$+fx1b;Ud2xijP)}xejf{|I+9~hzzn3w!rq% z*Vjh{Wd|JLJGOksMLqNRxz^V=vNgoIUZ@-GRi8FH(>3s0fs;WF#)W@2E3k{W-}zV{ zL4(OMmcX-(i-W@~DM@G8?9s#Dei8z`5f+Nis09tzQg**kWAb`;`NG{ju@Xh?gkGz+ ze8}TUwg~p@iK3*wY(-S>@F_~CR5!=r(@RtkW8ewdTge|WkeLWA?Hu{64d6p^qgeFk zAmvJXY|WN8_0+HBd8o>fv?FZ6 z@g)9IR0m;cTT=~3LcURX)kp}BiapxP&GuxS0J-4SGR5C+e_ubn_Sku2cLZHk`0A$R%sCs8G*!x}>#rIz*+$Hc;7P94BNspONxy1W|AznL#VOjBGZ zONol@hv;BghpOf7>e{{kIWX>KDjzdDI}QrUY(!y}k4lNw?Tgh^NX)O|E3eGMW9B{2 zZxnOw^yD0Bq|wN$yVe--E zzuFnsS`i!h|I{f~Gf#dq8cOI?gyahi8>N7;sbH)#BTcT>sE){UoKAq1w0wU}i+A?y zM9L+)s7s|q54m9Kx59n<-j`2Q@I1FhSP_GU#B@GE0}2b-#Bh!CUPz1Vu{ni-;xld| zLKW%Pa@c+-i>$SNYdfH?bv^0Ne1}36c%+wnV#uJ5hO8=grkCl`e!mlmc{nGEE*H9U zIX2jmj(&bE+7Ttf!cxs--^u!hDc>oK<7(i$3aqT!4Q_}Ma{jKoda}34KVCfz3&zEqdbGk&)^_3L55ovAxc~$eAP`+9OE9EZ~cD; zUKSyK_#Kb9=$Ya@#%|pz`K+{vxR*n(-aBZa1ZEJBDxDU~@k$TJYZe&85;_yM-)<|` zJP^t~8;IRhJ~g*Nj4ZTvwcVg0hOBOd0lu-Z@#OS0EA)wqv2+*f{mjf*FflQa+8s_z zYxZ+(oKjPL$c{)*$_$ybP$mi^M6Y(yGIBStVJN=zoZ-*qgrf;tGQ=ETAADaFG=ELR z#>ts?ufbt;x`AI)ON%(A-DQd3=;wL_WC>iGm`Rsv?Hj|7^O+h8w-WlbxCx0e|ft7`W+} z4HMRvFJJC6T3dX1n_8;PJwTTzax7?ZGxVRJ+-PF1)L|=A?r2p}N2!L_1%3^R=*+2s z+upL%A}|7muCCs1-8@4=7nGNmS3N!sQ-@x~FJ-D}EeX4u|7h(8-@Hkz;*hf_=i%P| zP^5t+l&)GSCMG3iSV^Uq2b&moV0vn*tGl~kca98*tkLTKEu zSeu29kHr6IHyEahF~L>*`a(bq|1r0`_q(Aer%e}4fD{%O-O$m|-9O%5tNg?OGY|yZ zg&9r(0n%$H+o8ktkcXZjBXe8u)c^=%5sVgfW8#Xz#2geA76tLGZH0Ik)Ki4PL?FmUpUVj}cyk&3+ z`Jj>*9tR~^OSTd@NhLqjq3IO{HtC=u@*zVcFj%i7@JP*rMu22Y-X6m`|{YNNYr zX`e0fVhv`vE?XbA#FK`E-4nF7}y_nc6PTb zjii)gm)6$a7(XO8^F?q10Lbg!OlJXznVY!%))ZN!e@FV+&8)2>`udb6KYmPa=GG1V zSMZwol55D%-+F-T9EMZ=rt$1X}X*_cw(s3WbjDip%rK9cU#0`3h=nmAW8m zhaNB0)4P3(H(Ss?{eMEisx2k_4g_$CsDmWj*MKe9m}#ngUdwSi#fNp1Jhm@Q=WN>hhWqRaNDwA*xh|qPVx6a^t_4 z%6Sd-r!>1ie`W-@1BPa*g~i2N`nO7Z)<=cC>{B*6L(ias*5LR0;S-!>=>%Ag7iZf1 zX}OaLva+%yrlq8$oPR9e3O$}_@g6fdY-y2%zfN1Yzi_j(x%m%}Yr5XP8}Oocbv9bN zYvY8l7c0=*_b820M;Bh`OXPB~KywWv%YA6(5|)ssR6O~l88bPO2~Q$UUgQ0=t|k68k@0#`%`trd(I{%OcjRB;W&in5x|V2yijDp{UW_lM*fe^GmLYC>6evMRJf~o zkhQ=;)&kHbrlkH|AEvRfv7bJy!nP9?_EjzA<-E|gs_N?9)Jv%se(t(5d;sY@zandV z(cQ+UMb!Nf{nhi$9-BA({3Kxs^z8JFvgIteiCXfX-R2@CB@Jq96wllQ@Cc^U=uUs= zLVvzN5WCIkh6n>bF?~a1ZAat3e6jHI_Et8OD(zh#-Sx6xhR&POZyTfD@pCL})Xs^C z2H3xF-~DOd!<$qrp*ZCl@KH@v7+xxP{v5s78%LG-^yw?;ETeL{qF|#?A^@2EVf*i+ zn{IAy6r8GQOvnqN^`=~MX=-#|*L7{hjyAQs2UE(OnQHS0ukQ=;-#0$iE&v=Vk6M7X zV(=$9&+G1pvpw+T1g~7t$7bTYTc@O|rgr}H_pze}g}32_fxqFjKkKVrrd$3bEk2&9 z0NMGF#p*2K>uSiG&WUstW(RPK-XFQH%|&4bOXXHDK_l(gNKHpqrX|hHEVH}6Pen-( zwz{~;T5_PYY`WoX&z6Z39qI>^7lR2@kA-rThRW=l$@K?5@fG4zpt z6TILyCgd)R_|x#OYioB4%z=`kgG~k9Sp2|}rf#Lmf28W?_uu|a{SQ9(Mxu#K=Wyz} zsSOMb2PnPh>FMYHWOhr6WKx`TrtZPHbe~O{3~IvUq8r+AT&{Yxqw_ERB>d-g>LiM+ zxeHDm=k$rvnPmSqt{A9XJd34e=7qUlbj&HWZ8DvHlQ(X=oQAOLCbWNjn$;0{nEy90 zNc_?l(+}#d@u}$%*~4xf2j?PCb@Kjp-FnU)dd|nh-_}=_qImPLa=w0Xjvts@l!an} zqV{5EUba~LcInqUj1Gk4G|W^{#@?P(h{evHxIJJ>C`u>laQe88s1EH%9!`jB5^fB& zu>|PlK{a9%x$cC<)w$w*gDfW;s$7M_|Hz3y}FrCXM$Oo*#!#i=76#E*#o|{8bP~R)O!EX#0Cmwhxfh*gxXb%Fp$D}@l z+|)t)4{?|;>4jORa?ZcmR5fVIEZ*E)qW*K^!NIBA4-544&Pj?8#8y61lSIQXkv3{W zKAK8Dn)2?UL2{AMQA-F@NB{8oGu@%?A)>tp2pUOG)MBAIHBVUjGlHLj;qEhi?HifD z?re$YfBncC`{>cL%}rj182(U*!-Su}d?sCVI0(7oz%aJEcV6suYBxQ^Y1vsUe&q_` zZmK~V7UDH4=`PN~CeAPD*!KrM_Q7qvV(y>~B zpT|BL=`XkOZaSU09!O&z#GD4(FHvwik*&r>N5ZtBh6IPprV;B|dyJroIJTZ}xC68; z-PB&i1_ZGaL;z+&l5^7hZ4VbFEJ zROj@iFM(x%gN^M=rJL^RI$*p-9T)VZph#WjJo_t^JxBgaz~+!mfKi1mnFrzM?vZVm zql#+L-nxMs*GY@PkfA(E{f6hMrE=e3zpSnU1B8p`3;3+T;RPQrF~`}M?~A?W@QJHa zFD^+RZ(QEpoTj>X@nVs2dqBdmVWSg9MTL5ZBCu+ga$o9bDvv$V*P7%l+ZKA=k(3`Z zl>hwu>(6cD3^=Zic4j=w*Jb~TJq%gf71%}A4QFB#s0p^)yXN7#Y|hK?QhmqT-TmA+8t(0$*h+s-c1|oy8fH6h8Yy4L-(NwMnl6+VB!p z_?+4QtfhdWX$mU=E#Y-FH4;&W8MINW52QhiPtBfUjq30_7Z;bhxXVI2vQIUOVKC*< z`Xq9k>>hZNJ&MKXXhH9(T5Dx(tG7MXhF|4nJ3Bc9PVpVawD;N?Voqde=Ke@Lmo-TC z>q!^}N|f`U`?KX`4o?OP_X!*M>JQnjt_lA>kv2Bmrs!euCCw1Ek1Dv8Vas?17k2>~ z?mJZ`G6}(+00*ICV?Rs>faFA6LLwz^8QMOBro9HXTs+A)SZamRO{!}WQPdNfIAKFl z8`JxF{c0O4`c!|p{U@&)^o!qtm7+R4sk0d)WnifA ze+uJeD&BwyYd+gwaf8t zXAa~3!q-Ay8NP<1fjUinw}W$j^+&Xl^$B^tKT=JiUp6N5n(Xk`-#41Z`P}*`=S^%Y zAK`=JD`H|7r?h_H)01g9^KdJ3Q4nBbLtDW|^7h(ki-#|C!MG%Jch(jG`T$Izv~Oi| zW5dMSy0F0zsKevbG>TqYE`3t47SOcdMzsl7G*jbq$zr@T)(NABHC{c=vHwrXpc8#MKR>^bTzSGTu4hchzAl*m8f8DRb6;h}(YS6a4Lg8EcP>&+ck)W!n)!9OL>vM}nnBsr;^S z%0qa&dsjtv>Lrr!Gu{2eDW(ks)zxHGP&-$0W#?CZT7)OU2LT<2238K5jKD~o2~HTQ zOXS$T&J%<90ihl}Htw_>EJS;)mp33N=0%cQRMkusan6+jSt_W znv)0J`VxCid0UE_p=@lrRHJGlwY3#8U%HZLxE@E6>0C!JwYU=#U~*xI0^+ju@GFR& zcL1zE3=5kFQYB^0O`G7UfAE_dmj~yoHG%K#Y3*ulJF$S~l>3~rj~C(5QmQd28Cftg zsQ@OICTf2HQgIjt7Ou(Yb7jr!SfY{LwY|HKi^SCQ#!3gOZuXEtH$ZStoZF6g@5t7{ zVZEIP-&Vxe7j!Z;%A?%~g$u2t*{7H8$gCm=Oo`o89ez$u&eUu+U`J%3xWru{IE2r| z*=agHQuS#Ix3+~<@(&4|F*1hHyq^uf1sYA+JcUQw%NdSluh3+G=@uBJ1MQy+vxw%? zSfaUY9HAG94i1X~XJGo*PQ;!KJ##h}CgPqHXLombz;P)G^DxDaF?H%f#2P3?BDPZA z1(RZT$PBN?L7`Jm?4YHgiG&%bduZsEwJ#uSxWpG8!o_K36W+vhQ}xY6(JntrAC3w1 zg4)F%&$i9M!NDRXrswGE;UOAJcZH?rBHkhMKCGw4L!%KKalc@0qj^)3u*#biGk{H{ zJTnO1hpL9!3B3b?6wp%?`>W+^ntpEc2LXe_p{UHEq@f_dLCR>ls_r)xU3vCTF|TPu`bLwNmqkfjnE(&EUC}Z9Oa==TbhkX^ zxzMYOcYQ}rB+$+XH3*%Vg%&@@@pBur@Svm6tG3Mc{nk{IRiH9&@Y14OJOY}hbggu( zt!FZ!PB2fuFVP`{C&^v&lnL*4v9_hut>lg-x8jmHy zwtmSL3rP~=XC<-SbkI5GPAWOaS5*n{+^bi0JdUEgBmkhtMKx0qISn~0H3lDEmG}6~ z(8!2W(ML&{5;beTprBixTUjdkR6(;m5~xr9-u7LL2pe=`YKa}qkOV<)spIII%4b*w z6Xr!VjjuK#4$$e`Cu=gksyopTo+P>|@$q8~XLJeAkU)g%yBwd+hKXD`5G%=0(D=ay z_DUqOX>?s7DbXn{X!tZfPTAo2Ic0$&`9cIgX);N~6;iTqNUEBN&m+VDGeBl&h|PRMvjb3)+-Y=TPT|pq&BIMO+;*Mq z(SnsLG|l9D4{^R*!@#1#rab5WV@NCk^gf8TrMkKrg#vL#+1(cezzv2|6jmu|;A_O= z3jq&U{HZ`UdbJ&PEBd+Sdw~eZRx|yBVG&6oNTVOc{;|$tt974Y)^|&4=A}Epq9jfp z9w}=h=WlZKk%A}`l{RI`Ek{OOw}w6Z*{_JVTQEXybOie|$fHJBT&|&>{VK~oxD1<_ zJ<*L}7IrPDUkFLDF@UU-hr#%{WJ}Mx-3^6TicDAaPF1b1r9E2I!re&~NO(m@ zDOBe;7Ynrpt3ziB9<>DoDTujZ0Iq;Kmh3SulCByqHtU5okjftcfH_5BwGs$QZ=_p? zRxV7f*0fSrU3;HD=obQV=0n3{Xl1Ta&)4R+x9)RZ{P9$6Mi?q%mAinjc9A(g0>L221 zC*4<9_dIBUe%4PwC;*A8`LxUIf1zwx&apD#jik2*qg5mRywe$}A4EiQ78YzZwY4v% z8LkDy0CNB(U&Waqn&K}*1>{U8NJ3FTG%}YFsVx~k8TwX?h%0eqNo;QTmHP$!i`%#` zTHZ`#m<1wrA>BGlrq$=?NWm>y5IcZ$jTj_)K(e$WTjp;?J`}6Cm^`)lB+C$HD7|rX z36GjFJl!y5a<6;!c995|h{&x##&;I_VMK!iMU$J3j_$d5nEYSiCG*#dh&HZd@vYqqwa5vUpOZS1gR&Ke;pq9(vHD_^EuH+2osz3_xt9n~N~`eP63 zPhSr=OlgnV#u6#Doot0b_t}l?tP%!g%u1E~8+LX)Yahx9t*xz3put21fk4e{bLxfW z(-5?hCbD^o)*z1uoP6)S(;grN0PC5s8#$k5OLQ*zeea<{Ue?Eke9OKgSdsRlwM&Tj z4Os#Up>z-5^$+FWLA|HsOu)jDbkQbFwqv6lHxwCha>;WCZ<|BP3ug=72Y$?Jt+;Tv zzI5C+ld=yqLi!rrbl;@i)+bYhjDM54zv~<#hyo?$2;}9= zO?VW+?d|Z`m~vgnYin~-28IkDsVqi#V#X(zc2&6-Cb;|{L(QEGMWp!~hbO81i=1S1 z&vsaTLQbZk4D~Z1ApvP6oqrv<1K4Btxs4vwkR2fR3WK@iCfoyep|2x}peH4F{tFbt zbe~|$yplm}Y3#j^m~B_6gN`P{D;I*2tdpuN-I%a3oZ?+E2;s}J^~Z-JUBQp#Aw=Yb zEdz-T8}wjtNF)Lum9Rh|r;Q7^gt2Qh``gOR@ zdOUC6yWAms)ipsZ&bJ;D6;rs9`0Y40Dg2_lANm+fp|~+C&$UA8KHA?p3qJ^v?X~%0 zVx->w9yDfhOKf?-yPN#0ncDjYjgEZ&%3nokNR@KNoIPDL9)_ zn`{Y?C1}G#L(MHOhkMR?pV?~pK>{g=(Qp5g=fTbZ0v-kfYF(@*E2o{KolAhQxcOsj z&-t%D|0I3ct6$(DdxtIH_o1~x zs}ChW;+okZ=%OyUpJ+@}Q7z-TR3Uz=ydXu0NEAW$^+TTsVjRi?q3k7$m8IImF5eII<~LlaaF!i6ZR2{?Rw$rtc!1tN@t~JLGs!oXihrUd1CO z?y=7HNA^p{?5t6g>^U+W<=1;8w7!c5^Q40)Rk;tU(1pRBQ5kt*eEarIlP(sjmWDR9 z=<@5PF6KrPl+^({%L7)Zh@e7yE=~lJ6mDB9`cf$f`e$zhM0E}8VbNxn3{zD@{AHJJG3`Vv@sQq)yd<*r{x zZESA7t1^`>GirSqVv8u%Z7{2nGI^mUGqZCbT4iWH2msT{ta-A%PF2ka2n#a+E&5G| z#<^TizEYBsQNH~@0Vi!nhnMs!kXeaZ#FnD%_t67jRVd6~$H>5xCuq?}dbtG?nwWvK z+0P5%()TI8;l!$-Lsa8wo_34>(LLm69;cy|xX)90QT@N7(h(=jlC}Vf_VTVwo)eyK z=@;}Baze{2Vh#_IhytxUwGUlEU6j<$!BXP$pJOV6bJD$WjEYK1=;8X2k=sbs1SyM4 z(~QMW_S_QX!Qt?iQEd(Pt?r!8XQCu^O8}eYGMjukrqpz(RM`SmH2QB=sazn*$*B#p zNYzIxN6DzhrIG7Zva)a!0$2d8R=7(3=)KswIimp}0S5H`?0F=TiynhoVd zO88KnY;t=-B9qi$#GLlZkq99cYLcKHq#M1nt-g<>9d&he^-FHb>BPw6%w7<&z0Q&J z_2+UyVd47E1>5%(hSMhA_wL>E^75jdv7V~4K~yl(!+m|=B@(-FRo1)`icV|@5Lo42g(sE>>+_8 z@h9r55M<^WTa*8Fb--_zhT7WD%*@PLk0t}7Z`YZ6{v|oM{RjD|;vHayO-jaT#k})X z>A?Dc^`i*QyNEpIT0u!)S?7a407s*@7pNMb&>GJT@VCD@{IMcv+J*hRpuh~on5Z3J z>(5?`#P)}vBUs#OKUMJZ5=ROPqA~!=sOPzI60kwgMdIODn~&_S4&yxu29N>q(Ab%k zr9V)T`_Px`G!#sfkoCLvnW{tj%FnHrX3NEqxjhFMu}WAn=IpcNh$mI$| z-$VARm!Kk+U8xAx$_wFm#LJ@{|!!T%4m2T#hO|HglBE8;NIh(Sd~ zg%@J-Z4DF!;5q&e&6g=72^r1n4#GLmjDfjD6l7%Rq8LO!1M@_B^94DJoHCYe25CRU zFVb7ARfv>#P#BrO)SN&2`9Dn6#rqkq79@7qw5s?|Fo8<~jUy8q8@5Xmoomwa4c-#L z@@ZjnV-gIXO=Zho#3ZeGSF_F<0N{Uls_)3p4Gj*;0f{Ey@nxBo--m3 z_$K)NpfI8WsHuGW2gqdcQD}7Bb&m?PXo)CVB`x%$A}iV0Wrbr&q&rBD)4?_}U;6Te ziIY?DSR7m;*8?0wLD#x=N2^&?9^U0hf;&fxx{i`)^pCh09QsK5yi|_O)q2yzYTp0J z=f@P4d;gn?k}~N-^4@I)d3nT5<9H0iDj3M#|_;rvEEflH2z!wWZVE; z%gB3)QqpTXNVX4Mq@+_5;rY*w^ux?9$iy@Y#0K>hr4>qkamEu4Z~L@hpy0QdoIqH% zB*MfAvQyb?X@7Cuny3FRP1Vx?lYnn>BpX}m0CQ4$TSS!#htSolS3#`z)joA#NumAg zYtTF|D+#lNvd(+HWlRd}|NMJ*^pm)VKbPZkuEH8W^*(_=4*5}Tbzj~0`!W>rAnQ5@ zIACS`512q592|-ao9mS?Yb6u4XhzH=KCet{Q;R2St@)o!cyu0SoORyMVFg!? zf@&qras>x8aY-B-9{|MzBjd&(QzDqA`rf>`;o~EL>KGUpuvn>y>Ns9~$7=A>P5Jl$ zX32xihR?TKecazy8h^G}0pIAW-M;KcGR4|ANQ1U!zXjFTl3<`*cI42xePRkMxhksp znl{}P5fKqhrLq<}0IH!-U%!3@*G@`*xESm>DVWf~r0cZkvak>jrG2WId9NzRK6YYvF{K>)>eXAT-5Is-#e9%?6fGB4Ag&d;Ay28N=uQ`ZAA zuAK^E36SX%wxyD#E6AVN>C4Z(U<+X~0pB|S%kszi*Dz31Z;$XdX&d#TvW#x^@!EIr z^04z_@v`hcU_1tgJdkgblXv#k5$)-EPsamH5NdQQ=S+-cB$w7q7QX>hU$>&!V zv9s3GQ5G8?pIsS~y_h z{2PTeECoeHR!DJY&N94$DcN~zRw}cyL}6^K^j*LQ^;O{J(yw?^9#Odj^bN@ZsdB`B z^9F#CKBkB==r6~Jr{+=bq&=B(DQ$WZZ}Qyvhk&_m|L~~^F@y&M>t~T5g$KK37}Uc((fn=bz|&uP$9~${kJZ%c3bF{#^8}@)QXvkX-^W`ItUm#5e&#pG z1Xa@nFhZENlN2v;dY|0_g=BTWFQ1m*N9&r5FGpRpSBGbwef?U7rv0coo^kK)Uttj- zbO5%FlDJkqo&}wb7P$@!-=k)1>Z4;LY$jCdYvUV_f<;s%T4c<-!-)|=Jg5g^KmutF zR3##s0W)Qu-d?J4fJ|>J{dW+q=YS37HWvkM94K)k!HHI9J5B)q1kFtc5TtPkTrVn` zzonOPEl|2ZJv+9jh->3>JL5SH)$5?N9Vt|21VmmY6t}a#A0GtBeSn7`K3L%F0XC)Z z9y~bk0wD^sv@`>3*{&+nZUpm;xgbIS-UdY|WZT16w@ls_Y2;UM>Zm22nFS`_?dz!g zTDPw46QkL#&awAmHO1q(!|@>@+&+@!90%VRXrE{HMXw7shW=Gq;SgKa}5N6%r!<<3K9AQ;i8bP?*~5!G}RcThKCSY}}4umJMH(Gy=C0 zLMT6eOi^d|vF5$|I;>HFS|$PN{^)c3SO%#m1V#l!;{fPtr{zH!gC-Z8+1XiC5U|L( zuyhB2=fBI5JrmmN=IPlBEFtJ*N6Pds?{0l&M0S0VMjn!j!GjHFvplxtI-}!|c-96{ z8GVNwq2fQOQfZ>T(jVvZpy67x!OMB#C#Hl?atK?`v#&ig9EuNnoW|LGo?F7g)~8uS zxb+j{kzr;MISY4}F&B1TJ)`n_4IjKW0DLn1@S+SnMlpIu-Z;dxq7UJ80S_)YusCb< z;u8_Q_x1aI;*IJ6Xk&hJvz)jYac`Xw6BDzikp;0tPHlWJMP({CXMgi~2;OR|p$jLw zW9s)my%hQ4(lq=d`aEyq(c@&5dD@QzZ%s@#MnXmh>*nrt_nQ^qT&id|uGY+V9it`F zuq@mbk|cUow)CcSd&>e2UU1+O`w)bI1xn3Fun*~wvuN&?D}b3IA>-a}(#pe3_Nd&> z&&Klh69PT!`EQhW+?-*JH=lh6ht!&+^|va^i$JhJ3dXe-Kt*M(*H?}5keEhZW}(>F zCMeoAuUwFdLuC+BBFDZWa18FqMjD- zABgfE;51WMEoctTqMmtf%_2_(ajWs@*U0&f-F0#jm}+n|UY-Dba44ve7xPn%LNYVy zZ6ThP%@Zt>{D>T7PEUTEtuStPc%!9li{mSyWp?9d!4@~Kthp;aIFAlJv|jchySkG z(-D|yQgAx)O+1K+jO>Ku{0^*>o40%{GO;xl+~7D3!3Q6Bcnlgz;~1ncQ4l^R3$G#} zw}fkGJ=T5lBUE;G0l5mp7_uz9Vz*`YN4%iRAKB5r{w^FSTB;)HzmQFoC zqPZ0NMfQT#U|KNLxrHQkX&E39L0gIB2FQgL*4B%Qao19g9_!|B+gj?#%zHrWrgPjDYl1*`c-Kr-nPRmaED%cW&$v$6+fUWWfDAH<8vd%9g*m?3v7+A19$6V*icv;Gl24sCWhsmF8(D zZN(V<55KR?@&&|zY{}+5mnr7R0PI#A;uQ`K20;r36qs&UvnudS6{}m5y?Salu)Bkc1UQbGf3_wVe2*qo=Sh4ZH)#W z#UgP0Q_97WQRe*I@4kF*N1?(d@seJuUUmiY9bF`Jx!(;18KziMtPtO0ujuzC15&6! z+EcaUCcjj(J<@yU*T)I3mxpqw4o<~omVybQ%M(%XR_;qcp8+L1Qe$~@a&i*!KlG&7 ze|q_XqOguDgbDFt->nET*+S8R8!Gx%OwZGEt^(Rb9~?5=+0MJ%6NwN3iIPUT61f*x zHKJil=Ymw}{vWZ7K;zvMCOm`MCsEJSADMbI;LSC#PHi%}XGEeO#-W08Kn;P8;Q($B z4kPeTZUZ7l$yuo+TVL`R)ikholPp(tG z_yDK!oc+kN;Js65J;YwReZ{e*F}V*l==j;dVcK_z-({dt(Ph)TyVq;L0FgF%7ovWTPZhpZ2Cd$dyu*WuIZSg^#~=_OM2`!ahPNp@_&y( zViFb9wQjzsmjLum{az{LQ&Mc1W9YzhoH4H;$&LWKCN3_HM8M=r_tIf$Xx?Sv}+SQE4!ri0vf z=GGHo8C6vx`0V_N^N8IMjTV?xgTq50Hoy-q1I-U&f`vYE9xgR;u>qJ&ESk;s0tE)GYg1F<%)WCt?99C&}GQ4k!NAehr>f@gqDOW0&+=ZTL5{5fzs@B%XX!hTzKfw}rAKJOoww&?0OUX{ zr@35RLqo*x-o5*0Lxwu6RbuDlG>7upQ{NN87=VU-o(qeXChaeg<@@c5L5mj|KrhHC zM@Y{Oxtxerln6;$P-Eui=W~cl!sQed&1YM@)1dcF;Wv&2kpd+WV8}@T@UQ@X!Tx)a z(L5^~v7C^yQ41@EQP#w_N8~c3^8@?TmaI0V= zqV<|6zZWq#X95+xYO)?36C($BO5IAOUL}La#$+&}qlA|6Mx{}!fa|iV{Vy#|O@YAQ zCuUe%XfoDqPz_+AtlnllS{g`Qgca+&{8lm)rXMU6bmIB+-M)uAmLN4Zh4YQ3jx&jV z-qHG~l)@k!n0a_`fT%t}$+pCTI@nkf>sYx;+W5s9Iq$G&265tt8-}Tx?qxW`Y*G2+ zPQKM zXtVA8L8x7%)dp|BQ)7V-p=Ke}EvrdTadqy?7i`EX&kGBw^dsOip6OK@-5)QZydf(K z7U~c<-2{#qX?=C1)z7xY7abGx_$Xdm9v`)_G#Y2m3c5v*aNAD~=`6u1fgj3p8l2+6 z@xY86wgB$*XAo_Wy1T$2pOBI9z$x&>U1Ai{ID+t~^v6@HJLdBliz<0VzQL$ZA32F| zz9Z^~;bD@i9veZ>GJ+LA0J#3V_1oJ9;cHq?OmV|x+nDgCL@Br!vPA%OusUzOjX z3*!6)N!DfPmj<>8ikOo8q+3AJh$v5xLzQOFzCldR&MJVkMC*7BRxAseTp8nIxZ;A1 zoG$U8vK5!<+6ah9vhUBfGZqMZu{=8YCwrzC5jMu_2I*L=y@k%Zw7qLPn}y`y|eJ(n)3oSxb@GX8a=ldkTXWW z8fvqi^!V{}t=~`yVe2a=v^KN9+f}6s*o2`U9uYDW!xu#qP8*ZeSTGz~N}QEqKI9>W z(CUT&)+p8GMUESQ<21Inw>zM^gthq}tN2SGw`aAA`y##bG6Ju{!3WDbAicElrG5)r z$n8_h}pnwIEjLga`kFp8VNOb%FrP-0TjcbF&5;6G78XQdBN;DGjmn{e9sqI?4D zGTG>y=Mg0g>dL2ATyYV36o4miR@nEo(#kHVaB$nbA8W127#ZW>5DerLxCs(#uHk9N z_D7Hc=8==!G926VOC}i3oeKr^@d9`ksRhljVJ^tYd}Ib~G;(I0nYlUAWg%;ONw;i- zX3MS&l*Wi7c(#?c!QoRERI_c!WafJt9}$%f9JEmFf9wH*&C8rNyxrFVf zC}3d_yN@&M3-FDYLFsP%ADw-7JeO_X|2Ik{86{dO8YB@VQk0#BB0@yA$jHdbh{ztH zA|pbitWe6#3ME_7Fhepjll6Na)!lR7_w&1--}vKty{_wZ@pXRB^E{5@^Lek2;}oxm zb)PF%QykV8u1z{wQ?{$zzb@f8D}E*G)%)$VGukXMlBkd3*1i^vu55_*k74hYO56+)!11hfB5y`de)ABw(jDUT!sU@(>B_ z!4=y%yjF281ArZQ*k#ko_4|&%Ma_tS1FZLUT)Px1jLW?>Y&%bJdjCrg^E-2uqzsG? zw7g9!o{m2iHMh2(?>dF@tz}rEZMq`s?PUjnuJ5gXn1Kh(!=JZT*3^{aDYXCA4~0bD z&$OHFxy>F@IfA$1?h9@b42ks1lU@?eaE4euDj;fx-9Tr29Z@1aUsKz#f*98N`X zE=ONkLZ~UbI;5K|F9J_W^e`w+g&WPDI)mP^pBc{T1ljak&X;&euw1aZFV=$^v zqM4laIG_}&8W`19LQ}&Q*RkdHmOi#$P>^U~b=8Td^*s|M8?W=gA^83S1ihsQv zzAIlGnLp{EmW$thB&#H$6g*Z#s042IhdR5EzUbDiYX@Aw7izr@tW+4bYSn)Z=k`X2 z{0ybI{>LmypDPp0ne=~<<*?M2GYu&-P^)Udv-okSx96u8-%v=VS}r$Q>bJb7Uj72I zE$pb3odv`b&ud=->Cig3gw=2h$IXcDYg74CpQtH3Ffk7w0C01wE~E^z;e6d)F79ZEZAmB5jfq5*FXy z@#l{oIB)>vOC8Z5F|b4Hbu1zCgiY-?mFBtr-W{VEHY70Gx;U^eEL{^O?n1X@NGk3;lZ^Zm%E>hDgytqsGGt3$CUGqhX;51 z(dHwX65al$6B~T#S4e{Wb;>)G9;>y z|8l1kT8ld`M5NC_)JrfEH~_6w5>$5#a#YvUqy{NpH2YkzGVEBw)AF1L4;~cT6!rdF zQp@)>rx#^1uj`)b79O8rPnuPt7}jy`{pS$Nw_2b0WtSN7zMq?6C`w(Gbvb}mIO=D2 z#iP{wUYB<(pMLkDq`>L$t!E1_#ER}a6v=Xq1=jt77o_}5V%;*>@?pO(A3P$0uD{QM zzwAR(`mr3h-LrdV$wqX4>M`9J{a|enEja$S^J-~C{ulr8KyN}o%IEp|>WYe`h?OpK z9L~RihEnC7y?+zf5qRd>aS&zoNy`B|L*4-(y>i@|?`WbrJIj1YyI@cgxg3Wa@m(s$ zD5hAX-RAP4aeN6xDe=jN3%`j^6h=DZ^`W*`J``(pxUf$-q+YojmrAvgRq%Sn*e00* zDk=*9Oh(SqLE^aU=%k{&s(Mq>tu^XsCn+h(<9rkkooJg~XE(L3KI7&;6xFoRQ1)k< z@ProM_plpO4wF0Q22}o%g3mUZ9bnGmjcU2%`SShy*Mbl8q!da=OOCt7&sGFp*Fg5H zF5-#q2PRBk4;W8)@IV*YIzJ%3Cf^FR8yf+2&@3X#;LZ8`W7~J{ev{nTF@eG zn0-K9{Xn;6m-AKs`~o?Z;sM2uZ*(5Mmt8iV5mR8UyEwEECIX z`}p(n5`FihnuH*bR2RUbOOd(bODd6}k1xKYo=Z6M;)>~$NSMSrW`+xes&oCBn3=DG zYj}el{8o3vO{a+_6>+dmUC<&ci;Rfsj!~Fy^sA!V~ZWqEO=KpXo}dBzyTf)jZb&q(5CG-OiqhR+7^7n zVC&p`$fwI%tW3ehXHduyKZCTqnoM~vpeG>3du)d^2oyq&a;yS=)7E_e_qEi`&;yX- zJu)(q;M+*0YDXX2+6xaN1CVu6L;+Rs0Q%rb&*lSr3Aq&@=`6q#pcb_;JBH@|zY|LK z88!vzknz-M5bXe9;R0-Q&m1NmPTC_O5(Le&+}z@l5^Cg7@qTwYeP#i8NgO)o^ruf{ z(S?zmvM5WuDH5JX7ek7iY{W*^#Q5Pbq?QK`mSO%`Y;bIQKD|E*=UAkSSXfvPx#-K6FN44|RmqGNIif2&G|_m* zp{>a{Th5&Kf1lrEoY~_yyg4^8(#6t;cMH{l7E23+6@^3=a$5#f*A^6q1cst*PJ5?Z z^;*2)iR0H{$5vC&z{fN9Wg2{;p|pl`!%L{ZoG~M%JJ^LSU|~Zb?*)UA6R@#dJC-#& zaE@6TO7putDOoOkA_otaAOP~9?NDQ`+>1RMHf$h}x8d99GCU89zFKzBh-wc`0F;1y z(-V)E_^imCgMo@{nBP9WU`6O}X@sB&F?mJJeR&%b2r7yQGKqH)!p_s(`HSJlf$N(y zGAiowj}dKj>K7$7%*^J4ial1ab`l9HYO~GkjvalXHK40x5J^ zcvM~C=-h%>GZM%*KRfnTF`u6D18yg{BYX&63mo-bp8Z~|p%E0!p}C*Fa7+hz0;nJw zcL-mv)lBYI&jJ6c^|j$5HVHc0p$`Nx!?h787B>@sf@0;#>fO0POg%|@zxn>Cz{%a- ziH1)vyb~qS1fkj=QrRO~KEoE~I-Bc|J8sdVT%TFLM6G&iIz!Rp1;bdc!PJ=LocW2F zkltO@p?XL#uh-i1maRWKXQS%{tx>j_oSYnDyFuCM0m$h-tcJ@F)ODOM|2iI>Nwq(4 zml+qN*p-%-ccM%xfyN@c4aauQQf3NS+n@qF5$WlH^?9CnHv>%}TpajPA_pSb1Mr`dZk$qt12e;AVSZJc zM6!|&F#Ep7wUx&jqJu)wI>EiXCJR$EMB{gHaH@JmXni{aNNMAz~Zi~3iAb#ayCu#@m#@GJT@b=pNB!- z%i}rh+x`9gO5p?#fPoq@#JZ?+0jN+Fz{7+cQvGW~KQhw%Cfx)DJ#I^Y^cL|r-1>AI zs#c_tCBICSDVEHRnONQX^B2F9!bme$sdp4?kpXttpQ5oUdM z8QDgwA$$?(<-4k@frKQuA$8JI2|ftqaNNwU3au6(E3!jk%j@6R0008*CtpU3`WgBA zxUC3Dq+?5P}yAmjW0-GBXW%ji#Q@4=>E8HKs|9IZXq2%F>ro zxQ-w*G;Xy(vIUwxZbYGltnnfe(B(LJ31&Os?^$SSVT^GvF8s>9>vve&jmUumo)zC| zUBQ}?ytclF$~$k>SMNmXgX)~#hmcUw7fUXB+C$T-!x5xMMe-D}Tk-3ZE}O-s(ASc- zSq9;I5aA#dnN3bkjyTh;J-4tF@SkQ}?A~^4FN2H1u(xscdNfiZ#mDX&yczvGYucB$ z1aBDd-^cs-?!Ou{`FdJ-_VyQ> zHB%x`_I+}iIuAsmKdLbEv5v{j&o_ZBzyKsz7Q5SX%j%KF`Ue(feFu)Xn)S^MpK~y- zJj19L_Tzm1s`Trc@^7Ap`y|B zU6tW@Dd>vJ@gH4j>2c-R2Vdz+^FG(&C#O3(g zh54z&l{Gf#zVj=jC!7iT0PaWzaDh+crpD^(63w^2`vI2}{IibnTOzXa@y0x`64vlKx#}`6)79B8g0U#pC zs=nB5c7!`8oq0fy{n@&F`R0RHPPEY{)TN$374&s@N~>5k?u=OCU0d zx1zp_H|9`w_fB~^1CCpb)fba`s~S6AjHJ^a@9){+6ruU?cWw@+t)PipYOH?3ini4( z@q3$9m}5nw4c_;=RbBO2sML?!l^A1gOdz8*K@Mk_gBotPC>bk5G=F zfFTPOOHQ}QbrIP=u`TUZVkq9Nr9&v9X4SBtK$x zc9k$3mIC2Uz#cNJfiNc|#uErem~pgvu0{Y5G#x~z!CC&J-JO9%C76!P0Lb{>>B|>~ z)k{L%oPTsIB~Hb|b4ru)OR!%Yau{C*l>kv<0(tZzs9Rd$yaed7j-jCd5HAvs&l2~Y zzSybDVzVQXQZh1e$l@oYAinAiQt4jcb5KY;5$*;2$!`%s3FDR#mNGQDsuFxc z{oKYs-2P;|Kg6P4SQ;>-K2bb!!CkccR^z}fpP$+-%w4UOd*DU2{@S>lWbon+16+hK z#2=Ta4TTWJ6?lpc>f1Zm?$M2TqH5O#a3>-f)kE6aND&)apkX*N2rJ|}JKj=PM~Z~< z(4A-Yptt!ocW9tl8U#R=DA8F+LAXZ9DHK$B*t^KE0Bob~Is+ZJc{|S}wuh-`76Vdt zzjtrTRp3{xy-SgKfNfW2es&tgi93W^@B8|B zXs4yy0%nW+knWx`ODMg5)`%f3*-($`&9s)PlSW(hO6HF=z!DT%2Qr^^tWcaRV2SLB zy^vIhe06_f)Ncw(#u37xix{(PBfx)e^qs<;M7P z-~CRca5$H5lUsIctxmFWa-ZPZO}kDW-YR*SC*k&8>vdn7_8I(ePWS ztkT;_g8pQ7Efe7o*c_5aeZJu8I?x>@c=8$6{fZ zMQVF4+%-9&(~*&IHfT`!>Moh7I(v$J>OpvnDy`9T%Z`i+CvRcl>L2%b- zYwh??5$;PJdWOE3FVGsp)LuDm;LJ2rhad$gII5i9pnv;4gCMEpi4(6#sBU#i5;FZF zoP?<%eys7xPrm~h${NL=6B47Nt2dqr3X31HEK$mM?KGxy z5iJ$xLG?k48!xS9ShAC(6~?Gpg@n=*PWsA7#k1R!aBWGf5ilw?IVi~Pqum95ezZEY z!Ai}NFWRH~A$R2mA-?tZ+fSN70_byo;?3!0yaCB(ueWmC^Z|TF77$inx_&jwprSjG z5W$zW?QUD((fb@Mu}O6Kc6ys`S&ZqZF%L~Naivb>>^bv^A}h5`u#$QhFpVE@oqPDB z7%%`j29X(dJz**%b+Vh~oJ1aW(w%&}eWKR$(TA!A-wNdx?tp|(c}8@SzUP?fi={hk z0P%ZwUsK_|-G!~3bhPp@Vk<#ExnKy#*~u*eG9CT7@f%xD3pc7d@NH5#pR)GWm9e-` z7??>o#;Dr*eI&0Gczq`lsp zR#aWMo1e=C#^6Tuvp%T2IsmVHNj(;>dTwqzLmqbHGR~N*aZjDFd)Re&u*QqAF}ZR| zZjg6wRDbdKP=oLK2$d#9N&nau`TF2r8Qd3!f@i0)FNp^0N=wH=2z)cTBy@srMF`KK zI+UjQgGj8Wqu(sXGtuvrMay8yH6THE>(Ew71=_+%H`H+c0<1cdx=GXe<1HB4wCBa~ z#Vk8&t}ScN@YiU|Njv03!?~l-DA;8g6Y!?4kG7ws=YCFTBS;oaB4!YTT6NwQ$E$-3 zR`su=9@P43yR`~7;vg!4RzPz|ca0%PFVH>rx+@+h{k-kjO`VNhH2z8Zbx#dmSs9s1 z+xb;tHw@T4p#=t%+b(aAs!+m6w>!|dzw3(cR>b}!-iR&nu!3qQJU8XcMgPTnsG>#! zhE0Ba%!s}+BP%NQD70mX@=8fhx@(HbrRb9h`#cL+hj2`g?wAZcR2G2_Xn(c6zQ8&% zF()LZ0!=pbvNtzBjr*##{^rz34(JvXKh13g;9f9a2(KLnn}>>)$>D(qio0XaHI62c zTXq?Vb$CVpF@(zIkwngxmgO(d?yJA?H`a3+`dkuFJ z5FwZ}0|^Gm!)xG3JJGeZ_9}C)K^O>1E}|kPsZph;zVDlW7LgO0Z7P_(fe9>ymaJjt zQ%I*VRbUx>uYeTFfVkL1^9jdy;A0>aAv#%XV&tR*g=FMdvwGDk;{JdGf&y_8<6>ye z7f}$j?)~4Onksaq{)FcRGAS=FZ&Vkz1QNLv(L!)BV1{9vpvHBOG63+LV{pZ;L-FE! zmGlsAJ~BG$cH_p4QN@gmbV!nz0Kkx*ckgZ> zVnIksR^Y`IKYf}JFK*&Tb8HwyAA*)5-DSaW;6LuU^GTgWE2qjIs%ZGNV0)ll2C9>hyLxvW=~1i zt)TbYAViO@UmSMe496)mzl{f0k&r1eJK)d|+`Z|5VNkc=_g)tfB!_hI_=kuKz?oVg zQh9Ky>o6i}$<__7GhZ ze0D>*y%yktU-gV~1U%e@rWt9*UV(uXD8Y!7JIl0<1qBingpTi?h>M@EZCxC(JV+!1x$kI@~p5JzR1eO!NdZhSTP+XOMT;7up_%saN+{o6M& zE{^S!o7^=pn&ipaaoQw?_4g3C)UV3M{L3>`o!+rU6rVfu!t?LYw~Nis70MhRDHZd* zJXCG}p!E7J<5pp)Q{hY5go}KMWkb4{#qdEx4=aH>C%Xr(h_tyvRFNRPzhl?#U#y9_ zYJ-cGjGD`Tes*~)i8+ImtmN%m2C{J=q)WaXEcJhrf^VS9L&@*v@4u1=IZf|rJvC#) zY@48t-klLU7Kzka*MuuDFC0<5=cKZMr}>Rq-t$*g2orqJL~h_$7i!(U@y&eaN*$wt{Q>!tok0n>nSYK;XQ!U3vC1*T7FL~8v=HKB3J1H4~&CO3Cb{=n$2t1CQaF4 zh6Bxj12oC7L@np_5cBv?$jxO{_rypU+*p!sg2szzJjhglPxifRQBGuXAKrf!#}95U z!hmBIy(&~lN3lUuJ%yc{&;eM_-wA4igri~zB^YF7D|FuK9>wGdQW$JR>M%ONa(q$i zuhe}xE?Cqg#2dPRg2rC58S7-_JsX zcZ!Ou2#p_=5#e!|igj^u`~K{6{x_K?Hl>_RAu{ z%%?xEq`lkLTJi1u;|T6CV{6p6t#{MpqYrrl5hwEU{rjh<(ib3J3i+l%AQwjsrC~!T zLelNW3`l1Ln1rSp&%XnUv+q;>LCO|BJ_f*o68IUP$FiE5o5+VD0g#IF9}yXTs9N%@ z`5Gz6b+TF=?Nq;QdirZ ziWI(v2SiOlCw>DxJInj|^3kcO8_1SIZws~Lj!OQMCr4x6L95};8dF$!SW!_CWv@cA z@)s?|F9t@>bLwlyqgP1utSF4wuwD?A@P<^{MTh5q++SxRtt0~Ey?6y*o~zL3tE=HD z@q}iHd?^C6fPSL5VryW>x5n;J0Y8TY)HcYZIhQFy&M+c)grt^eTma`^z_CSB4SY9+ zs3xI=^TPN&Oc`cCz{R@)r-K9yA^!*1Hyl{^@n=-CjF?cpY3Yb|TONR+%@^mn zI64XlJ&)ix$zJpWKu#$UZ$QEsizA5Wg9wi`JAUT<4Nph|3HwHNF;dk)eX~)-dYQ}I z1S_Pb^dQm*GXrQ5^_AeyALylJv8|ES_Thys!wq`2`W1bc^Z|XBE4C6M_D2TF(VU~Q zm^&Ej;4q&NoH z5n|~?xWEz=J0z!G;i=hq3=cTo)^!m04d82S_`wJRLBKa6Du$1OD~CvniK>@a+_10? zFQcV>iIXbX$r-JW>T~OzgwBGQ4!8tK(1c`1He8D&8t%ahOVqQ3z(IB#d9{JPZRO^s zg|&h}ZUr+#2XTba#v^@>p=jNSbn0`h0tRMKhb%=`l)|y@2 zF0x!d8=B+S5rQiK9SE3a(W@8+3tTSo zuf}h_eRMk@APoN~!Hw{lOh`M$>>EeaC&kMwb1fsAMmE`M9OmVdL z!lNH0^|$zN_;3vAeKB^w*zrk2_r@0HjeF0Jcow@!Zrj&Ts`gS*&f z=i5Zn^|_bYLWf88ep|IJrTu2nmwg}z1|v(9rD5}_y1L*g7y_Rp#A|j0B*c=!z_$F{ zZ*(Uc#HGGyC#kG{wfTv0)$~=thSGJktxImZrFylS7`+y_!OzH~#=0SyK^RCcUeI5R z9LRUVjS@u4{PQMA?*XcKRUzO#p(VwhS7f}fV@cvl$0aHy$Gw-A<@TNaVK187e{}WL z8Te3PN6oYx+cubuh7*q)sqzY(-|)n1(vQ<*wD`T+2OZsU=;*MSko^ETusbjm2KGNj zNEt9hWedi>VLl2@CoiAx?_}s5!{$$##Bp_E3S@TRo2C>syGQ07nxEqm_wO1|{T%0M zVN}keUbWI%@4&vP7(IP`Jg4H<+3cBOV2df^Dz+gvfw91jGuIVnbQWC(J zp!(?ZD=VqZi}k5d0ej(SByAD$+-A!pl&+1IbcP5qG1U&de|+Kz6SGj7xm?QgMfH9Q z+izCttr@Kj_lnoQX>Ye81)2uwNKY@H;Kxe+6W`9>N>^9yuyuUTbx za*!x>&>fDTvcWA<+d&6M$1M^E35A>SMariNZxC! z?8PI2ah#ZQW|Nbj`Q2}F!S~eb?1*%dAHOQ4Z1|kWUPGd_xB11 z)Q^)N_{CCv=Y<^{1BMxLM2-q>##1i9)X;D#&iVX7%iO#Vg{ASrG(Bg2r;LeKbCHy> z3d4U*8PnbsqHVCJV&v9RmzuxBlS_1{)A*sKz6|FcGR7p}Qh@f0nnIK?NWtB2-sANe zUMCh3tJ=@xjwCpe6GkSH3*4Q3zk#v`Gd~r=wAWk{0?CT^x>js*YHBG3k^^ueo3;<7 zt!s+SwSUZmw)6MEtl~{em#2$Xa}Fr5B--8yxIEv5DO$0n)#P8I!u=n~s`Whol){a9 zLYN^Z*plH9P_va|g?5In-L87Hfz+r)tW?~+ys99TH%U@Si-x&hipA#|D}tI)y^%3m zieH)@>=P;gTjnn$f7JEwTq}Gad{(6X09XL#x2!W(N{{L+e|&5n_R4Jo>)`(B;geXN zAxd&VNZ?72>02D)a;h6RGG%71Fsb5SGpM|Y{YXHdzJ0bp@6g}ba=wFdQfoYf9+PyE zU}ar~|2WddKOItC91cW8|68tmG^1zr>eXmyC_uu9BNc6X>b;0_V!EvYIG)|M^f}D| zx>=*DTWyV!iWp;vix~hKz$fpSk>@-S8H1H3PmEBKiKCDt^fY!MLQY~|mhhhW{&O40 z84OBG_@mr&$GOJH`&;poy>=vVbBs{@@N;J#D|N99f}e- zC!~i;212|}$iyr5zstA}F4ZW?6x;Y}v@yo%vuLTxfCKbjazv_U8IZNRj{?FxGECQP z-pohEI1C-mqU@ABiWj^hTsd@U)%CkhlDR_p2$o=Sy>sV|s@}R^lbtY!&I3pxp$9Q% z;;&rSeFpMzjkK$f{G+MBK>LfC&(A&2%u4V?pMv(c7PH&&`rgfqIP2SzaB-xS=RK;m zU;Zz?KLfdFJ}EwPn!z~vHIU!ix3|at&8hrq++S6H3(ysj z4uZn;#LhriSVG|ffY)GB&f(7EO(-*YVhzR*Iev(FfYPX%qx#oV$`G_&!o6CY(R!0_ zT+-9W@uQwOD$?ayWS|u3+XuT)c)}#U5_+2>D9}!xJ7rQjpeT~J|9CIjlp;7tgF-`< zbbd{_q9ym@A3=&oeg!GY82xjQ;+;pSw^DgbFCImA^Bu+TvA^@JzOKi7aCA8yh)zJK zl=dz&Pt5z3(ptOYI9dLTTNfdt)@uRuxz8-7q4^qi*rJ^RD>wrVy+8Ms9kmBg+?&rG z&IYz5^nY)C4R}E8M>{p)vGJn1rKOqU{l(iE!r!&hDy$0CgjB8uFJuO1PsqtJK~2Ml z8qXW8)*5LAX1ple$Oau~9Ys@hyRWa0Oa9Itaq@#?&Q?{A{F7`DJt@-7F?x{PPQ znlOpiw-X>v8RQE-lu|Gw;RD-M{Xi7^;No;FEi;!L(a16iz7rYA0|4%G9M|aceYbuu zC&YtCs{-!g#}KR&ASS!8k@IJ43vD9DmdbCu#&^`A)Fi)0#pVPVw= zS0yCe`i6)3Ab_Z=sF2mjHdbEJ^3HNy!!0=4)@%?o-qzaI=8Gyo=k)2IXHX98ZEPJi zN-X1^6~ssU)99{!l7qOur)E)j=O@m-`1K3+FiX<^-ab0~}o77yb13m*jkD5Xf= zRj;El60t`BQ@*(}Pbz#YTry1N{a2`Bwqb_ds_;6uy(vB^4a009h z9gPRVH;a4k$Hkp4bauk#9E%?SVILBA06X^yH_<#PgDf!2#B2$0Knm(U$~|l~M9`}F z{?Q{IqOSy^`VwaZQAHDc9%u*&!NkkPM;w+IZAa)8$_0!T!mn|I1i4Pg7r>{#WK(Dn z?!#p&-3&9=`L#l3k;T1aW;Aj;bg^&=%!UyM-U~B@3%gu&Vbl&^M$H$z4gl#&@Gbc2 z+v&9t3Z;q>!&t71DdbL&Svi2jSV2*d`Sd_Eh}8-@tqzE{39~T*B<>!*Da94aKB58r zgOHkz9D@9}g0xw&2-KyCId$@+G#(I%J9yP&iA1K&paghicaiI0xv`H?c@?gpHGKsI z`dXNNuOWS-CI{Opr3i-rdL8p1w(TI4QO=RlZ^puG!EHgG%+q9H%ESa*ChuR zfxZDkK{CTxmxA%OH#a%jd2=t%)kqyvCHg98p(scGqH1t2iuBNWcE2Q_2hNIRIuE26 z!LM*`knj(}Qjm5Zy;J^AT&@}w-q^ioxR^zRBIL@DnFC2bngysQ)RQOeVb6jrkeJ$7 z)N9aS5=kgA*^*Y@2oW2EAb=80-sjH-ekUwCu5q2vHC<^HU>OLZxhbTNi*09)rK<_D;pco6}1b}cUN|BECc2{8G zM-|P%izH*TU2r(muge9(=>YnX1`TD`_Jfmv%SOsKn3FgOj6>W>u9M)1B->3D2|a~; zS0E`sf6{@=lf_F_2eHV;Lv~~`Ej8jgwxytL2o7DWz$|U0;)aPGxCS`li4EYu0H#N) zk)?+mbS%d^d$g(GMY}Nc5O+|{2dm-NX7PV9;Pdwn{{QSM`0D>WbJTmj@S{l3A_|4F ow%gn(FpZ0f(tMqj;+jnnp33=nhSoq8|BE6gEiaWSal!3>0rivN9smFU literal 0 HcmV?d00001 diff --git a/joint_trajectory_controller/doc/spline_velocity.png b/joint_trajectory_controller/doc/spline_velocity.png new file mode 100644 index 0000000000000000000000000000000000000000..d427f4da8819e2ec818bac73e13398f9404006a8 GIT binary patch literal 32183 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 literal 0 HcmV?d00001 diff --git a/joint_trajectory_controller/doc/spline_wrong_points.png b/joint_trajectory_controller/doc/spline_wrong_points.png new file mode 100644 index 0000000000000000000000000000000000000000..f73310c031dccb9a038d3d4a67d781e38ac1cefc GIT binary patch literal 41712 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. [#f1]_ + +Joint trajectory messages allow to specify the time at which a new trajectory should start executing by means of the header timestamp, where zero time (the default) means "start now". + +The arrival of a new trajectory command does not necessarily mean that the controller will completely discard the currently running trajectory and substitute it with the new one. +Rather, the controller will take the useful parts of both and combine them appropriately, yielding a smarter trajectory replacement strategy. + +The steps followed by the controller for trajectory replacement are as follows: + + + Get useful parts of the new trajectory: Preserve all waypoints whose time to be reached is in the future, and discard those with times in the past. + If there are no useful parts (ie. all waypoints are in the past) the new trajectory is rejected and the current one continues execution without changes. + + + Get useful parts of the current trajectory: Preserve the current trajectory up to the start time of the new trajectory, discard the later parts. + + + Combine the useful parts of the current and new trajectories. + +The following examples describe this behavior in detail. + +The first example shows a joint which is in hold position mode (flat grey line labeled *pos hold* in the figure below). +A new trajectory (shown in red) arrives at the current time (now), which contains three waypoints and a start time in the future (*traj start*). +The time at which waypoints should be reached (``time_from_start`` member of ``trajectory_msgs/JointTrajectoryPoint``) is relative to the trajectory start time. + +The controller splices the current hold trajectory at time *traj start* and appends the three waypoints. +Notice that between now and *traj start* the previous position hold is still maintained, as the new trajectory is not supposed to start yet. +After the last waypoint is reached, its position is held until new commands arrive. + +.. image:: new_trajectory.png + :alt: Receiving a new trajectory. + +| + +The controller guarantees that the transition between the current and new trajectories will be smooth. Longer times to reach the first waypoint mean slower transitions. + +The next examples discuss the effect of sending the same trajectory to the controller with different start times. +The scenario is that of a controller executing the trajectory from the previous example (shown in red), +and receiving a new command (shown in green) with a trajectory start time set to either zero (start now), +a future time, or a time in the past. + +.. image:: trajectory_replacement_future.png + :alt: Trajectory start time in the future. + +| + +.. image:: trajectory_replacement_now.png + :alt: Zero trajectory start time (start now). + +| + +Of special interest is the last example, where the new trajectory start time and first waypoint are in the past (before now). +In this case, the first waypoint is discarded and only the second one is realized. + +.. image:: trajectory_replacement_past.png + :alt: Trajectory start time in the past. + +| + +.. [#f1] Adolfo Rodriguez: `Understanding trajectory replacement `_ diff --git a/joint_trajectory_controller/doc/trajectory_replacement_future.png b/joint_trajectory_controller/doc/trajectory_replacement_future.png new file mode 100644 index 0000000000000000000000000000000000000000..582a6acce85995fae84013dbc0ad0569d3c15ab7 GIT binary patch literal 71754 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
h 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 literal 0 HcmV?d00001 diff --git a/joint_trajectory_controller/doc/trajectory_replacement_past.png b/joint_trajectory_controller/doc/trajectory_replacement_past.png new file mode 100644 index 0000000000000000000000000000000000000000..a719f6fc66bd9c9dddc0a8dbfb5801df45413b23 GIT binary patch literal 74230 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 SC`6C|0000`_. *Citations are given in the respective section, but were adapted for the ROS 2 implementation.* [#f1]_ [#f2]_ - -Trajectory representation [#f1]_ ---------------------------------- - -Trajectories are represented internally with ``trajectory_msgs/msg/JointTrajectory`` data structure. -By default, a spline interpolator is provided, but it's possible to support other representations. -The spline interpolator uses the following interpolation strategies depending on the waypoint specification: - -* Linear: Only position is specified. Guarantees continuity at the position level. Discouraged because it yields trajectories with discontinuous velocities at the waypoints. - -* Cubic: Position and velocity are specified. Guarantees continuity at the velocity level. - -* Quintic: Position, velocity and acceleration are specified: Guarantees continuity at the acceleration level. +*Parts of this documentation were originally published in the ROS 1 wiki under the* `CC BY 3.0 license `_. *Citations are given in the respective section, but were adapted for the ROS 2 implementation.* [#f1]_ Hardware interface type [#f1]_ ------------------------------- @@ -114,141 +100,10 @@ Preemption policy [#f1]_ Only one action goal can be active at any moment, or none if the topic interface is used. Path and goal tolerances are checked only for the trajectory segments of the active goal. -When an active action goal is preempted by another command coming from the action interface, the goal is canceled and the client is notified. +When an active action goal is preempted by another command coming from the action interface, the goal is canceled and the client is notified. The trajectory is replaced in a defined way, see :ref:`trajectory replacement `. Sending an empty trajectory message from the topic interface (not the action interface) will override the current action goal and not abort the action. -.. _parameters: - -Details about parameters -^^^^^^^^^^^^^^^^^^^^^^^^ - -joints (list(string)) - Joint names to control and listen to. - -command_joints (list(string)) - Joint names to control. This parameters is used if JTC is used in a controller chain where command and state interfaces don't have same names. - -command_interface (list(string)) - Command interfaces provided by the hardware interface for all joints. - - Values: [position | velocity | acceleration] (multiple allowed) - -state_interfaces (list(string)) - State interfaces provided by the hardware for all joints. - - Values: position (mandatory) [velocity, [acceleration]]. - Acceleration interface can only be used in combination with position and velocity. - -action_monitor_rate (double) - Rate to monitor status changes when the controller is executing action (control_msgs::action::FollowJointTrajectory). - - Default: 20.0 - -allow_partial_joints_goal (boolean) - Allow joint goals defining trajectory for only some joints. - - Default: false - -allow_integration_in_goal_trajectories (boolean) - Allow integration in goal trajectories to accept goals without position or velocity specified - - Default: false - -interpolation_method (string) - The type of interpolation to use, if any. Can be "splines" or "none". - - Default: splines - -open_loop_control (boolean) - Use controller in open-loop control mode: - - * The controller ignores the states provided by hardware interface but using last commands as states for starting the trajectory interpolation. - * It deactivates the feedback control, see the ``gains`` structure. - - This is useful if hardware states are not following commands, i.e., an offset between those (typical for hydraulic manipulators). - - .. Note:: - If this flag is set, the controller tries to read the values from the command interfaces on activation. - If they have real numeric values, those will be used instead of state interfaces. - Therefore it is important set command interfaces to NaN (i.e., ``std::numeric_limits::quiet_NaN()``) or state values when the hardware is started. - - Default: false - -allow_nonzero_velocity_at_trajectory_end (boolean) - If false, the last velocity point has to be zero or the goal will be rejected. - - Default: true - -constraints (structure) - Default values for tolerances if no explicit values are states in JointTrajectory message. - -constraints.stopped_velocity_tolerance (double) - Default value for end velocity deviation. - - Default: 0.01 - -constraints.goal_time (double) - Maximally allowed tolerance for not reaching the end of the trajectory in a predefined time. - - Default: 0.0 (not checked) - -constraints..trajectory (double) - Maximally allowed deviation from the target trajectory for a given joint. - - Default: 0.0 (tolerance is not enforced) - -constraints..goal (double) - Maximally allowed deviation from the goal (end of the trajectory) for a given joint. - - Default: 0.0 (tolerance is not enforced) - -gains (structure) - Only relevant, if ``open_loop_control`` is not set. - - If ``velocity`` is the only command interface for all joints or an ``effort`` command interface is configured, PID controllers are used for every joint. - This structure contains the controller gains for every joint with the control law - - .. math:: - - u = k_{ff} v_d + k_p e + k_i \sum e dt + k_d (v_d - v) - - with the desired velocity :math:`v_d`, the measured velocity :math:`v`, the position error :math:`e` (definition see below), - the controller period :math:`dt`, and the ``velocity`` or ``effort`` manipulated variable (control variable) :math:`u`, respectively. - -gains..p (double) - Proportional gain :math:`k_p` for PID - - Default: 0.0 - -gains..i (double) - Integral gain :math:`k_i` for PID - - Default: 0.0 - -gains..d (double) - Derivative gain :math:`k_d` for PID - - Default: 0.0 - -gains..i_clamp (double) - Integral clamp. Symmetrical in both positive and negative direction. - - Default: 0.0 - -gains..ff_velocity_scale (double) - Feed-forward scaling :math:`k_{ff}` of velocity - - Default: 0.0 - -gains..normalize_error (bool) - If true, the position error :math:`e = normalize(s_d - s)` is normalized between :math:`-\pi, \pi`. - Otherwise :math:`e = s_d - s` is used, with the desired position :math:`s_d` and the measured - position :math:`s` from the state interface. Use this for revolute joints without end stop, - where the shortest rotation to the target position is the desired motion. - - Default: false - .. _ROS 2 interface: @@ -281,7 +136,7 @@ There are two mechanisms for sending trajectories to the controller: * via action, see :ref:`actions ` * via topic, see :ref:`subscriber ` -Both use the ``trajectory_msgs/JointTrajectory`` message to specify trajectories, and require specifying values for all the controller joints (as opposed to only a subset) if ``allow_partial_joints_goal`` is not set to ``True``. +Both use the ``trajectory_msgs/msg/JointTrajectory`` message to specify trajectories, and require specifying values for all the controller joints (as opposed to only a subset) if ``allow_partial_joints_goal`` is not set to ``True``. For further information on the message format, see :ref:`trajectory representation `. .. _Actions: @@ -324,17 +179,27 @@ Services Query controller state at any future time -Specialized versions of JointTrajectoryController (TBD in ...) +Specialized versions of JointTrajectoryController -------------------------------------------------------------- +(TBD in ...) -The controller types are placed into namespaces according to their command types for the hardware (see `general introduction into controllers <../../index.rst>`_). +The controller types are placed into namespaces according to their command types for the hardware (see :ref:`controllers`). The following version of the Joint Trajectory Controller are available mapping the following interfaces: * position_controllers::JointTrajectoryController +Further information +-------------------------------------------------------------- + +.. toctree:: + :titlesonly: + + Trajectory Representation + joint_trajectory_controller Parameters + + .. rubric:: Footnote .. [#f1] Adolfo Rodriguez: `joint_trajectory_controller `_ -.. [#f2] Adolfo Rodriguez: `Understanding trajectory replacement `_ From cc4c221a680294ffefc7fb061a1d25341823226a Mon Sep 17 00:00:00 2001 From: AndyZe Date: Mon, 31 Jul 2023 14:47:00 -0500 Subject: [PATCH 085/238] Small improvement in remapping (#393) Co-authored-by: Bence Magyar --- .../src/joint_trajectory_controller.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/joint_trajectory_controller/src/joint_trajectory_controller.cpp b/joint_trajectory_controller/src/joint_trajectory_controller.cpp index 4b3a73c3a9..616af7a648 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller.cpp +++ b/joint_trajectory_controller/src/joint_trajectory_controller.cpp @@ -1223,8 +1223,12 @@ void JointTrajectoryController::sort_to_local_joint_order( get_node()->get_logger(), "Invalid input size (%zu) for sorting", to_remap.size()); return to_remap; } - std::vector output; - output.resize(mapping.size(), 0.0); + static std::vector output(dof_, 0.0); + // Only resize if necessary since it's an expensive operation + if (output.size() != mapping.size()) + { + output.resize(mapping.size(), 0.0); + } for (size_t index = 0; index < mapping.size(); ++index) { auto map_index = mapping[index]; From 5c0327d4e72b164aaa4a365a40d7a3fa913c0f97 Mon Sep 17 00:00:00 2001 From: Ben Holden <94607409+bobbleballs@users.noreply.github.com> Date: Tue, 1 Aug 2023 16:24:34 +0100 Subject: [PATCH 086/238] [DiffDriveController] Optional tf namespace prefixes instead of using node namespace (#533) * [DiffDiveController] Changed the namespace appending from '/' to '_' with optional tf_frame_prefix parameter. If not set it will not append anything. * [DiffDriveController] Add option to enable/disable TF prefix. On by default. If prefix not set and is enabled then namespace is used by default. --- .../src/diff_drive_controller.cpp | 36 ++- .../src/diff_drive_controller_parameter.yaml | 10 + .../test/test_diff_drive_controller.cpp | 221 ++++++++++++++++++ 3 files changed, 255 insertions(+), 12 deletions(-) diff --git a/diff_drive_controller/src/diff_drive_controller.cpp b/diff_drive_controller/src/diff_drive_controller.cpp index 20736fda09..23097c0df2 100644 --- a/diff_drive_controller/src/diff_drive_controller.cpp +++ b/diff_drive_controller/src/diff_drive_controller.cpp @@ -392,23 +392,35 @@ controller_interface::CallbackReturn DiffDriveController::on_configure( std::make_shared>( odometry_publisher_); - std::string controller_namespace = std::string(get_node()->get_namespace()); - - if (controller_namespace == "/") - { - controller_namespace = ""; - } - else + // Append the tf prefix if there is one + std::string tf_prefix = ""; + if (params_.tf_frame_prefix_enable) { - controller_namespace = controller_namespace + "/"; + if (params_.tf_frame_prefix != "") + { + tf_prefix = params_.tf_frame_prefix; + } + else + { + tf_prefix = std::string(get_node()->get_namespace()); + } + + if (tf_prefix == "/") + { + tf_prefix = ""; + } + else + { + tf_prefix = tf_prefix + "/"; + } } - const auto odom_frame_id = controller_namespace + params_.odom_frame_id; - const auto base_frame_id = controller_namespace + params_.base_frame_id; + const auto odom_frame_id = tf_prefix + params_.odom_frame_id; + const auto base_frame_id = tf_prefix + params_.base_frame_id; auto & odometry_message = realtime_odometry_publisher_->msg_; - odometry_message.header.frame_id = controller_namespace + odom_frame_id; - odometry_message.child_frame_id = controller_namespace + base_frame_id; + odometry_message.header.frame_id = odom_frame_id; + odometry_message.child_frame_id = base_frame_id; // limit the publication on the topics /odom and /tf publish_rate_ = params_.publish_rate; diff --git a/diff_drive_controller/src/diff_drive_controller_parameter.yaml b/diff_drive_controller/src/diff_drive_controller_parameter.yaml index f909b27e8b..5d20970cab 100644 --- a/diff_drive_controller/src/diff_drive_controller_parameter.yaml +++ b/diff_drive_controller/src/diff_drive_controller_parameter.yaml @@ -39,6 +39,16 @@ diff_drive_controller: default_value: 1.0, description: "Correction factor when radius of right wheels differs from the nominal value in ``wheel_radius`` parameter.", } + tf_frame_prefix_enable: { + type: bool, + default_value: true, + description: "Enables or disables appending tf_prefix to tf frame id's.", + } + tf_frame_prefix: { + type: string, + default_value: "", + description: "(optional) Prefix to be appended to the tf frames, will be added to odom_id and base_frame_id before publishing. If the parameter is empty, controller's namespace will be used.", + } odom_frame_id: { type: string, default_value: "odom", diff --git a/diff_drive_controller/test/test_diff_drive_controller.cpp b/diff_drive_controller/test/test_diff_drive_controller.cpp index adf4e79afc..edaaa84e4b 100644 --- a/diff_drive_controller/test/test_diff_drive_controller.cpp +++ b/diff_drive_controller/test/test_diff_drive_controller.cpp @@ -68,6 +68,17 @@ class TestableDiffDriveController : public diff_drive_controller::DiffDriveContr } return false; } + + /** + * @brief Used to get the real_time_odometry_publisher to verify its contents + * + * @return Copy of realtime_odometry_publisher_ object + */ + std::shared_ptr> + get_rt_odom_publisher() + { + return realtime_odometry_publisher_; + } }; class TestDiffDriveController : public ::testing::Test @@ -244,6 +255,216 @@ TEST_F(TestDiffDriveController, configure_succeeds_when_wheels_are_specified) SizeIs(left_wheel_names.size() + right_wheel_names.size())); } +TEST_F(TestDiffDriveController, configure_succeeds_tf_test_prefix_false_no_namespace) +{ + const auto ret = controller_->init(controller_name); + ASSERT_EQ(ret, controller_interface::return_type::OK); + + std::string odom_id = "odom"; + std::string base_link_id = "base_link"; + std::string frame_prefix = "test_prefix"; + + controller_->get_node()->set_parameter( + rclcpp::Parameter("left_wheel_names", rclcpp::ParameterValue(left_wheel_names))); + controller_->get_node()->set_parameter( + rclcpp::Parameter("right_wheel_names", rclcpp::ParameterValue(right_wheel_names))); + + controller_->get_node()->set_parameter( + rclcpp::Parameter("tf_frame_prefix_enable", rclcpp::ParameterValue(false))); + controller_->get_node()->set_parameter( + rclcpp::Parameter("tf_frame_prefix", rclcpp::ParameterValue(frame_prefix))); + controller_->get_node()->set_parameter( + rclcpp::Parameter("odom_frame_id", rclcpp::ParameterValue(odom_id))); + controller_->get_node()->set_parameter( + rclcpp::Parameter("base_frame_id", rclcpp::ParameterValue(base_link_id))); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), CallbackReturn::SUCCESS); + + auto odometry_message = controller_->get_rt_odom_publisher()->msg_; + std::string test_odom_frame_id = odometry_message.header.frame_id; + std::string test_base_frame_id = odometry_message.child_frame_id; + /* tf_frame_prefix_enable is false so no modifications to the frame id's */ + ASSERT_EQ(test_odom_frame_id, odom_id); + ASSERT_EQ(test_base_frame_id, base_link_id); +} + +TEST_F(TestDiffDriveController, configure_succeeds_tf_test_prefix_true_no_namespace) +{ + const auto ret = controller_->init(controller_name); + ASSERT_EQ(ret, controller_interface::return_type::OK); + + std::string odom_id = "odom"; + std::string base_link_id = "base_link"; + std::string frame_prefix = "test_prefix"; + + controller_->get_node()->set_parameter( + rclcpp::Parameter("left_wheel_names", rclcpp::ParameterValue(left_wheel_names))); + controller_->get_node()->set_parameter( + rclcpp::Parameter("right_wheel_names", rclcpp::ParameterValue(right_wheel_names))); + + controller_->get_node()->set_parameter( + rclcpp::Parameter("tf_frame_prefix_enable", rclcpp::ParameterValue(true))); + controller_->get_node()->set_parameter( + rclcpp::Parameter("tf_frame_prefix", rclcpp::ParameterValue(frame_prefix))); + controller_->get_node()->set_parameter( + rclcpp::Parameter("odom_frame_id", rclcpp::ParameterValue(odom_id))); + controller_->get_node()->set_parameter( + rclcpp::Parameter("base_frame_id", rclcpp::ParameterValue(base_link_id))); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), CallbackReturn::SUCCESS); + + auto odometry_message = controller_->get_rt_odom_publisher()->msg_; + std::string test_odom_frame_id = odometry_message.header.frame_id; + std::string test_base_frame_id = odometry_message.child_frame_id; + + /* tf_frame_prefix_enable is true and frame_prefix is not blank so should be appended to the frame + * id's */ + ASSERT_EQ(test_odom_frame_id, frame_prefix + "/" + odom_id); + ASSERT_EQ(test_base_frame_id, frame_prefix + "/" + base_link_id); +} + +TEST_F(TestDiffDriveController, configure_succeeds_tf_blank_prefix_true_no_namespace) +{ + const auto ret = controller_->init(controller_name); + ASSERT_EQ(ret, controller_interface::return_type::OK); + + std::string odom_id = "odom"; + std::string base_link_id = "base_link"; + std::string frame_prefix = ""; + + controller_->get_node()->set_parameter( + rclcpp::Parameter("left_wheel_names", rclcpp::ParameterValue(left_wheel_names))); + controller_->get_node()->set_parameter( + rclcpp::Parameter("right_wheel_names", rclcpp::ParameterValue(right_wheel_names))); + + controller_->get_node()->set_parameter( + rclcpp::Parameter("tf_frame_prefix_enable", rclcpp::ParameterValue(true))); + controller_->get_node()->set_parameter( + rclcpp::Parameter("tf_frame_prefix", rclcpp::ParameterValue(frame_prefix))); + controller_->get_node()->set_parameter( + rclcpp::Parameter("odom_frame_id", rclcpp::ParameterValue(odom_id))); + controller_->get_node()->set_parameter( + rclcpp::Parameter("base_frame_id", rclcpp::ParameterValue(base_link_id))); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), CallbackReturn::SUCCESS); + + auto odometry_message = controller_->get_rt_odom_publisher()->msg_; + std::string test_odom_frame_id = odometry_message.header.frame_id; + std::string test_base_frame_id = odometry_message.child_frame_id; + /* tf_frame_prefix_enable is true but frame_prefix is blank so should not be appended to the frame + * id's */ + ASSERT_EQ(test_odom_frame_id, odom_id); + ASSERT_EQ(test_base_frame_id, base_link_id); +} + +TEST_F(TestDiffDriveController, configure_succeeds_tf_test_prefix_false_set_namespace) +{ + std::string test_namespace = "/test_namespace"; + + const auto ret = controller_->init(controller_name, test_namespace); + ASSERT_EQ(ret, controller_interface::return_type::OK); + + std::string odom_id = "odom"; + std::string base_link_id = "base_link"; + std::string frame_prefix = "test_prefix"; + + controller_->get_node()->set_parameter( + rclcpp::Parameter("left_wheel_names", rclcpp::ParameterValue(left_wheel_names))); + controller_->get_node()->set_parameter( + rclcpp::Parameter("right_wheel_names", rclcpp::ParameterValue(right_wheel_names))); + + controller_->get_node()->set_parameter( + rclcpp::Parameter("tf_frame_prefix_enable", rclcpp::ParameterValue(false))); + controller_->get_node()->set_parameter( + rclcpp::Parameter("tf_frame_prefix", rclcpp::ParameterValue(frame_prefix))); + controller_->get_node()->set_parameter( + rclcpp::Parameter("odom_frame_id", rclcpp::ParameterValue(odom_id))); + controller_->get_node()->set_parameter( + rclcpp::Parameter("base_frame_id", rclcpp::ParameterValue(base_link_id))); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), CallbackReturn::SUCCESS); + + auto odometry_message = controller_->get_rt_odom_publisher()->msg_; + std::string test_odom_frame_id = odometry_message.header.frame_id; + std::string test_base_frame_id = odometry_message.child_frame_id; + /* tf_frame_prefix_enable is false so no modifications to the frame id's */ + ASSERT_EQ(test_odom_frame_id, odom_id); + ASSERT_EQ(test_base_frame_id, base_link_id); +} + +TEST_F(TestDiffDriveController, configure_succeeds_tf_test_prefix_true_set_namespace) +{ + std::string test_namespace = "/test_namespace"; + + const auto ret = controller_->init(controller_name, test_namespace); + ASSERT_EQ(ret, controller_interface::return_type::OK); + + std::string odom_id = "odom"; + std::string base_link_id = "base_link"; + std::string frame_prefix = "test_prefix"; + + controller_->get_node()->set_parameter( + rclcpp::Parameter("left_wheel_names", rclcpp::ParameterValue(left_wheel_names))); + controller_->get_node()->set_parameter( + rclcpp::Parameter("right_wheel_names", rclcpp::ParameterValue(right_wheel_names))); + + controller_->get_node()->set_parameter( + rclcpp::Parameter("tf_frame_prefix_enable", rclcpp::ParameterValue(true))); + controller_->get_node()->set_parameter( + rclcpp::Parameter("tf_frame_prefix", rclcpp::ParameterValue(frame_prefix))); + controller_->get_node()->set_parameter( + rclcpp::Parameter("odom_frame_id", rclcpp::ParameterValue(odom_id))); + controller_->get_node()->set_parameter( + rclcpp::Parameter("base_frame_id", rclcpp::ParameterValue(base_link_id))); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), CallbackReturn::SUCCESS); + + auto odometry_message = controller_->get_rt_odom_publisher()->msg_; + std::string test_odom_frame_id = odometry_message.header.frame_id; + std::string test_base_frame_id = odometry_message.child_frame_id; + + /* tf_frame_prefix_enable is true and frame_prefix is not blank so should be appended to the frame + * id's instead of the namespace*/ + ASSERT_EQ(test_odom_frame_id, frame_prefix + "/" + odom_id); + ASSERT_EQ(test_base_frame_id, frame_prefix + "/" + base_link_id); +} + +TEST_F(TestDiffDriveController, configure_succeeds_tf_blank_prefix_true_set_namespace) +{ + std::string test_namespace = "/test_namespace"; + + const auto ret = controller_->init(controller_name, test_namespace); + ASSERT_EQ(ret, controller_interface::return_type::OK); + + std::string odom_id = "odom"; + std::string base_link_id = "base_link"; + std::string frame_prefix = ""; + + controller_->get_node()->set_parameter( + rclcpp::Parameter("left_wheel_names", rclcpp::ParameterValue(left_wheel_names))); + controller_->get_node()->set_parameter( + rclcpp::Parameter("right_wheel_names", rclcpp::ParameterValue(right_wheel_names))); + + controller_->get_node()->set_parameter( + rclcpp::Parameter("tf_frame_prefix_enable", rclcpp::ParameterValue(true))); + controller_->get_node()->set_parameter( + rclcpp::Parameter("tf_frame_prefix", rclcpp::ParameterValue(frame_prefix))); + controller_->get_node()->set_parameter( + rclcpp::Parameter("odom_frame_id", rclcpp::ParameterValue(odom_id))); + controller_->get_node()->set_parameter( + rclcpp::Parameter("base_frame_id", rclcpp::ParameterValue(base_link_id))); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), CallbackReturn::SUCCESS); + + auto odometry_message = controller_->get_rt_odom_publisher()->msg_; + std::string test_odom_frame_id = odometry_message.header.frame_id; + std::string test_base_frame_id = odometry_message.child_frame_id; + /* tf_frame_prefix_enable is true but frame_prefix is blank so namespace should be appended to the + * frame id's */ + ASSERT_EQ(test_odom_frame_id, test_namespace + "/" + odom_id); + ASSERT_EQ(test_base_frame_id, test_namespace + "/" + base_link_id); +} + TEST_F(TestDiffDriveController, activate_fails_without_resources_assigned) { const auto ret = controller_->init(controller_name); From 3aa0b5ca0e2d4fdefde41d2ff2d4fd5624a89b5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Wed, 2 Aug 2023 15:03:56 +0200 Subject: [PATCH 087/238] [CI] Bump ubuntu version of ament_lint jobs (#727) --- .github/workflows/ci-ros-lint.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci-ros-lint.yml b/.github/workflows/ci-ros-lint.yml index 9e08bec730..85afe2dc6f 100644 --- a/.github/workflows/ci-ros-lint.yml +++ b/.github/workflows/ci-ros-lint.yml @@ -5,11 +5,13 @@ on: jobs: ament_lint: name: ament_${{ matrix.linter }} - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest strategy: fail-fast: false matrix: linter: [cppcheck, copyright, lint_cmake] + env: + AMENT_CPPCHECK_ALLOW_SLOW_VERSIONS: true steps: - uses: actions/checkout@v3 - uses: ros-tooling/setup-ros@0.6.2 From 8b02e9fd7f470cebc4fa9b15424e96977ca79caf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 2 Aug 2023 14:28:17 +0100 Subject: [PATCH 088/238] Bump ros-tooling/setup-ros from 0.6.2 to 0.7.0 (#717) --- .github/workflows/ci-coverage-build.yml | 2 +- .github/workflows/ci-ros-lint.yml | 2 +- .github/workflows/reusable-ros-tooling-source-build.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-coverage-build.yml b/.github/workflows/ci-coverage-build.yml index b7698dbbe4..3d8a7431c0 100644 --- a/.github/workflows/ci-coverage-build.yml +++ b/.github/workflows/ci-coverage-build.yml @@ -16,7 +16,7 @@ jobs: env: ROS_DISTRO: rolling steps: - - uses: ros-tooling/setup-ros@0.6.2 + - uses: ros-tooling/setup-ros@0.7.0 with: required-ros-distributions: ${{ env.ROS_DISTRO }} - uses: actions/checkout@v3 diff --git a/.github/workflows/ci-ros-lint.yml b/.github/workflows/ci-ros-lint.yml index 85afe2dc6f..3d102b53a2 100644 --- a/.github/workflows/ci-ros-lint.yml +++ b/.github/workflows/ci-ros-lint.yml @@ -14,7 +14,7 @@ jobs: AMENT_CPPCHECK_ALLOW_SLOW_VERSIONS: true steps: - uses: actions/checkout@v3 - - uses: ros-tooling/setup-ros@0.6.2 + - uses: ros-tooling/setup-ros@0.7.0 - uses: ros-tooling/action-ros-lint@v0.1 with: distribution: rolling diff --git a/.github/workflows/reusable-ros-tooling-source-build.yml b/.github/workflows/reusable-ros-tooling-source-build.yml index 99a4ed66a5..d5f836f026 100644 --- a/.github/workflows/reusable-ros-tooling-source-build.yml +++ b/.github/workflows/reusable-ros-tooling-source-build.yml @@ -26,7 +26,7 @@ jobs: strategy: fail-fast: false steps: - - uses: ros-tooling/setup-ros@0.6.2 + - uses: ros-tooling/setup-ros@0.7.0 with: required-ros-distributions: ${{ inputs.ros_distro }} - uses: actions/checkout@v3 From 882b634871ab5cdd399153ad9ada36e192be3249 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Wed, 2 Aug 2023 15:11:59 +0100 Subject: [PATCH 089/238] tf_frame_prefix should be off by default (#728) --- diff_drive_controller/src/diff_drive_controller_parameter.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/diff_drive_controller/src/diff_drive_controller_parameter.yaml b/diff_drive_controller/src/diff_drive_controller_parameter.yaml index 5d20970cab..f3acfcf3c8 100644 --- a/diff_drive_controller/src/diff_drive_controller_parameter.yaml +++ b/diff_drive_controller/src/diff_drive_controller_parameter.yaml @@ -41,7 +41,7 @@ diff_drive_controller: } tf_frame_prefix_enable: { type: bool, - default_value: true, + default_value: false, description: "Enables or disables appending tf_prefix to tf frame id's.", } tf_frame_prefix: { From c37dfe63ec2f8929a14e185784c8e39417df5284 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Wed, 2 Aug 2023 16:25:45 +0100 Subject: [PATCH 090/238] Revert "tf_frame_prefix should be off by default (#728)" (#729) This reverts commit 882b634871ab5cdd399153ad9ada36e192be3249. --- diff_drive_controller/src/diff_drive_controller_parameter.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/diff_drive_controller/src/diff_drive_controller_parameter.yaml b/diff_drive_controller/src/diff_drive_controller_parameter.yaml index f3acfcf3c8..5d20970cab 100644 --- a/diff_drive_controller/src/diff_drive_controller_parameter.yaml +++ b/diff_drive_controller/src/diff_drive_controller_parameter.yaml @@ -41,7 +41,7 @@ diff_drive_controller: } tf_frame_prefix_enable: { type: bool, - default_value: false, + default_value: true, description: "Enables or disables appending tf_prefix to tf frame id's.", } tf_frame_prefix: { From 29fc1c32f15e660c95115f0e6263e4c199248181 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Fri, 4 Aug 2023 20:20:02 +0100 Subject: [PATCH 091/238] Update changelogs --- ackermann_steering_controller/CHANGELOG.rst | 3 +++ admittance_controller/CHANGELOG.rst | 5 +++++ bicycle_steering_controller/CHANGELOG.rst | 3 +++ diff_drive_controller/CHANGELOG.rst | 5 +++++ effort_controllers/CHANGELOG.rst | 3 +++ force_torque_sensor_broadcaster/CHANGELOG.rst | 3 +++ forward_command_controller/CHANGELOG.rst | 3 +++ gripper_controllers/CHANGELOG.rst | 3 +++ imu_sensor_broadcaster/CHANGELOG.rst | 3 +++ joint_state_broadcaster/CHANGELOG.rst | 3 +++ joint_trajectory_controller/CHANGELOG.rst | 8 ++++++++ position_controllers/CHANGELOG.rst | 3 +++ ros2_controllers/CHANGELOG.rst | 3 +++ ros2_controllers_test_nodes/CHANGELOG.rst | 3 +++ rqt_joint_trajectory_controller/CHANGELOG.rst | 3 +++ steering_controllers_library/CHANGELOG.rst | 5 +++++ tricycle_controller/CHANGELOG.rst | 3 +++ tricycle_steering_controller/CHANGELOG.rst | 3 +++ velocity_controllers/CHANGELOG.rst | 3 +++ 19 files changed, 68 insertions(+) diff --git a/ackermann_steering_controller/CHANGELOG.rst b/ackermann_steering_controller/CHANGELOG.rst index f2cb336a5d..a95ddb5426 100644 --- a/ackermann_steering_controller/CHANGELOG.rst +++ b/ackermann_steering_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ackermann_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.12.0 (2023-07-18) ------------------- diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index 8f5804fbe5..2949cc9f10 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Fix out of bound access in admittance controller (`#721 `_) +* Contributors: Abishalini Sivaraman + 3.12.0 (2023-07-18) ------------------- * Activate AdmittanceControllerTestParameterizedInvalidParameters (`#711 `_) diff --git a/bicycle_steering_controller/CHANGELOG.rst b/bicycle_steering_controller/CHANGELOG.rst index c9e4604a07..1d42125c3e 100644 --- a/bicycle_steering_controller/CHANGELOG.rst +++ b/bicycle_steering_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package bicycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.12.0 (2023-07-18) ------------------- diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index 1df6139577..69e8f2981b 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* [DiffDriveController] Optional tf namespace prefixes instead of using node namespace (`#533 `_) +* Contributors: Ben Holden, Bence Magyar + 3.12.0 (2023-07-18) ------------------- diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index 1134b1cc09..7489bbdffe 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.12.0 (2023-07-18) ------------------- diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index 7a420bb146..f884fdb0e9 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.12.0 (2023-07-18) ------------------- diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index 7e33097a52..d7960a5d5d 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.12.0 (2023-07-18) ------------------- diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index 797fc118ed..5ed71b34e9 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.12.0 (2023-07-18) ------------------- diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index 9920deb233..2cef7bbe7b 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.12.0 (2023-07-18) ------------------- diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index a33b0cc011..cd36386655 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.12.0 (2023-07-18) ------------------- diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index c2e3fa332d..4ff9cbbfc9 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,14 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Small improvement in remapping (`#393 `_) +* [JTC] Update trajectory documentation (`#714 `_) +* [JTC] Reject messages with effort fields (`#699 `_) (`#719 `_) +* [Doc] Fix links (`#715 `_) +* Contributors: Andy Zelenak, Bence Magyar, Christoph Fröhlich + 3.12.0 (2023-07-18) ------------------- * Remove reactivation test from ROS 1 diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index e5c55a3569..cb5e519cc4 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.12.0 (2023-07-18) ------------------- diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index 1cc86b0d0e..75bf98c565 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.12.0 (2023-07-18) ------------------- diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index 73e59702f9..d0080d7ea8 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.12.0 (2023-07-18) ------------------- diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index 75d8985836..4fc80aa5f8 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.12.0 (2023-07-18) ------------------- diff --git a/steering_controllers_library/CHANGELOG.rst b/steering_controllers_library/CHANGELOG.rst index 88400b4e3b..408df542dd 100644 --- a/steering_controllers_library/CHANGELOG.rst +++ b/steering_controllers_library/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package steering_controllers_library ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Update ci-ros-lint.yml and copyright format (`#720 `_) +* Contributors: Christoph Fröhlich + 3.12.0 (2023-07-18) ------------------- diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index ce14946944..fec2d8782c 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.12.0 (2023-07-18) ------------------- diff --git a/tricycle_steering_controller/CHANGELOG.rst b/tricycle_steering_controller/CHANGELOG.rst index 70b91d59b8..88b6ff647d 100644 --- a/tricycle_steering_controller/CHANGELOG.rst +++ b/tricycle_steering_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package tricycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.12.0 (2023-07-18) ------------------- diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index c832892dd9..7f9643a50b 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.12.0 (2023-07-18) ------------------- From 83e415c0f00512398df3c3a508f738fc76a7ecda Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Fri, 4 Aug 2023 20:21:17 +0100 Subject: [PATCH 092/238] 3.13.0 --- ackermann_steering_controller/CHANGELOG.rst | 4 ++-- ackermann_steering_controller/package.xml | 2 +- admittance_controller/CHANGELOG.rst | 4 ++-- admittance_controller/package.xml | 2 +- bicycle_steering_controller/CHANGELOG.rst | 4 ++-- bicycle_steering_controller/package.xml | 2 +- diff_drive_controller/CHANGELOG.rst | 4 ++-- diff_drive_controller/package.xml | 2 +- effort_controllers/CHANGELOG.rst | 4 ++-- effort_controllers/package.xml | 2 +- force_torque_sensor_broadcaster/CHANGELOG.rst | 4 ++-- force_torque_sensor_broadcaster/package.xml | 2 +- forward_command_controller/CHANGELOG.rst | 4 ++-- forward_command_controller/package.xml | 2 +- gripper_controllers/CHANGELOG.rst | 4 ++-- gripper_controllers/package.xml | 2 +- imu_sensor_broadcaster/CHANGELOG.rst | 4 ++-- imu_sensor_broadcaster/package.xml | 2 +- joint_state_broadcaster/CHANGELOG.rst | 4 ++-- joint_state_broadcaster/package.xml | 2 +- joint_trajectory_controller/CHANGELOG.rst | 4 ++-- joint_trajectory_controller/package.xml | 2 +- position_controllers/CHANGELOG.rst | 4 ++-- position_controllers/package.xml | 2 +- ros2_controllers/CHANGELOG.rst | 4 ++-- ros2_controllers/package.xml | 2 +- ros2_controllers_test_nodes/CHANGELOG.rst | 4 ++-- ros2_controllers_test_nodes/package.xml | 2 +- ros2_controllers_test_nodes/setup.py | 2 +- rqt_joint_trajectory_controller/CHANGELOG.rst | 4 ++-- rqt_joint_trajectory_controller/package.xml | 2 +- rqt_joint_trajectory_controller/setup.py | 2 +- steering_controllers_library/CHANGELOG.rst | 4 ++-- steering_controllers_library/package.xml | 2 +- tricycle_controller/CHANGELOG.rst | 4 ++-- tricycle_controller/package.xml | 2 +- tricycle_steering_controller/CHANGELOG.rst | 4 ++-- tricycle_steering_controller/package.xml | 2 +- velocity_controllers/CHANGELOG.rst | 4 ++-- velocity_controllers/package.xml | 2 +- 40 files changed, 59 insertions(+), 59 deletions(-) diff --git a/ackermann_steering_controller/CHANGELOG.rst b/ackermann_steering_controller/CHANGELOG.rst index a95ddb5426..b4c1815bdc 100644 --- a/ackermann_steering_controller/CHANGELOG.rst +++ b/ackermann_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ackermann_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.13.0 (2023-08-04) +------------------- 3.12.0 (2023-07-18) ------------------- diff --git a/ackermann_steering_controller/package.xml b/ackermann_steering_controller/package.xml index dab9499c7d..d4c6b3b3b4 100644 --- a/ackermann_steering_controller/package.xml +++ b/ackermann_steering_controller/package.xml @@ -2,7 +2,7 @@ ackermann_steering_controller - 3.12.0 + 3.13.0 Steering controller for Ackermann kinematics. Rear fixed wheels are powering the vehicle and front wheels are steering it. Apache License 2.0 Bence Magyar diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index 2949cc9f10..5f85999abd 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.13.0 (2023-08-04) +------------------- * Fix out of bound access in admittance controller (`#721 `_) * Contributors: Abishalini Sivaraman diff --git a/admittance_controller/package.xml b/admittance_controller/package.xml index 83ca1f1b2d..966c268d93 100644 --- a/admittance_controller/package.xml +++ b/admittance_controller/package.xml @@ -2,7 +2,7 @@ admittance_controller - 3.12.0 + 3.13.0 Implementation of admittance controllers for different input and output interface. Denis Štogl Bence Magyar diff --git a/bicycle_steering_controller/CHANGELOG.rst b/bicycle_steering_controller/CHANGELOG.rst index 1d42125c3e..e100f537f6 100644 --- a/bicycle_steering_controller/CHANGELOG.rst +++ b/bicycle_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package bicycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.13.0 (2023-08-04) +------------------- 3.12.0 (2023-07-18) ------------------- diff --git a/bicycle_steering_controller/package.xml b/bicycle_steering_controller/package.xml index d6a971ab6d..42693418f6 100644 --- a/bicycle_steering_controller/package.xml +++ b/bicycle_steering_controller/package.xml @@ -2,7 +2,7 @@ bicycle_steering_controller - 3.12.0 + 3.13.0 Steering controller with bicycle kinematics. Rear fixed wheel is powering the vehicle and front wheel is steering. Apache License 2.0 Bence Magyar diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index 69e8f2981b..7fdcf063e2 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.13.0 (2023-08-04) +------------------- * [DiffDriveController] Optional tf namespace prefixes instead of using node namespace (`#533 `_) * Contributors: Ben Holden, Bence Magyar diff --git a/diff_drive_controller/package.xml b/diff_drive_controller/package.xml index 34d236a9eb..80d3f6334e 100644 --- a/diff_drive_controller/package.xml +++ b/diff_drive_controller/package.xml @@ -1,7 +1,7 @@ diff_drive_controller - 3.12.0 + 3.13.0 Controller for a differential drive mobile base. Bence Magyar Jordan Palacios diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index 7489bbdffe..4b223619e0 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.13.0 (2023-08-04) +------------------- 3.12.0 (2023-07-18) ------------------- diff --git a/effort_controllers/package.xml b/effort_controllers/package.xml index c3280f9c9b..852cf77829 100644 --- a/effort_controllers/package.xml +++ b/effort_controllers/package.xml @@ -1,7 +1,7 @@ effort_controllers - 3.12.0 + 3.13.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index f884fdb0e9..d9c0f2de24 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.13.0 (2023-08-04) +------------------- 3.12.0 (2023-07-18) ------------------- diff --git a/force_torque_sensor_broadcaster/package.xml b/force_torque_sensor_broadcaster/package.xml index c89df2b397..b2c04e6a57 100644 --- a/force_torque_sensor_broadcaster/package.xml +++ b/force_torque_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ force_torque_sensor_broadcaster - 3.12.0 + 3.13.0 Controller to publish state of force-torque sensors. Bence Magyar Denis Štogl diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index d7960a5d5d..324eead77a 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.13.0 (2023-08-04) +------------------- 3.12.0 (2023-07-18) ------------------- diff --git a/forward_command_controller/package.xml b/forward_command_controller/package.xml index de09d505ba..25895a4696 100644 --- a/forward_command_controller/package.xml +++ b/forward_command_controller/package.xml @@ -1,7 +1,7 @@ forward_command_controller - 3.12.0 + 3.13.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index 5ed71b34e9..506aaa48ec 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.13.0 (2023-08-04) +------------------- 3.12.0 (2023-07-18) ------------------- diff --git a/gripper_controllers/package.xml b/gripper_controllers/package.xml index 3e48f395af..c977a0ed36 100644 --- a/gripper_controllers/package.xml +++ b/gripper_controllers/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> gripper_controllers - 3.12.0 + 3.13.0 The gripper_controllers package Bence Magyar diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index 2cef7bbe7b..ef997c8733 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.13.0 (2023-08-04) +------------------- 3.12.0 (2023-07-18) ------------------- diff --git a/imu_sensor_broadcaster/package.xml b/imu_sensor_broadcaster/package.xml index 4ba9bb7a55..41c087f3ca 100644 --- a/imu_sensor_broadcaster/package.xml +++ b/imu_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ imu_sensor_broadcaster - 3.12.0 + 3.13.0 Controller to publish readings of IMU sensors. Bence Magyar Denis Štogl diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index cd36386655..9a5c4efc30 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.13.0 (2023-08-04) +------------------- 3.12.0 (2023-07-18) ------------------- diff --git a/joint_state_broadcaster/package.xml b/joint_state_broadcaster/package.xml index 89a23fc15b..fd5deab3e7 100644 --- a/joint_state_broadcaster/package.xml +++ b/joint_state_broadcaster/package.xml @@ -1,7 +1,7 @@ joint_state_broadcaster - 3.12.0 + 3.13.0 Broadcaster to publish joint state Bence Magyar Denis Stogl diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index 4ff9cbbfc9..e2b1c6f613 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.13.0 (2023-08-04) +------------------- * Small improvement in remapping (`#393 `_) * [JTC] Update trajectory documentation (`#714 `_) * [JTC] Reject messages with effort fields (`#699 `_) (`#719 `_) diff --git a/joint_trajectory_controller/package.xml b/joint_trajectory_controller/package.xml index 63774d5c2e..08a5392977 100644 --- a/joint_trajectory_controller/package.xml +++ b/joint_trajectory_controller/package.xml @@ -1,7 +1,7 @@ joint_trajectory_controller - 3.12.0 + 3.13.0 Controller for executing joint-space trajectories on a group of joints Bence Magyar Jordan Palacios diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index cb5e519cc4..15242a2018 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.13.0 (2023-08-04) +------------------- 3.12.0 (2023-07-18) ------------------- diff --git a/position_controllers/package.xml b/position_controllers/package.xml index ef214c3563..1259239ac5 100644 --- a/position_controllers/package.xml +++ b/position_controllers/package.xml @@ -1,7 +1,7 @@ position_controllers - 3.12.0 + 3.13.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index 75bf98c565..04ed272d86 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.13.0 (2023-08-04) +------------------- 3.12.0 (2023-07-18) ------------------- diff --git a/ros2_controllers/package.xml b/ros2_controllers/package.xml index 1bfa80d078..560ea5df88 100644 --- a/ros2_controllers/package.xml +++ b/ros2_controllers/package.xml @@ -1,7 +1,7 @@ ros2_controllers - 3.12.0 + 3.13.0 Metapackage for ROS2 controllers related packages Bence Magyar Jordan Palacios diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index d0080d7ea8..d84a55f26a 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.13.0 (2023-08-04) +------------------- 3.12.0 (2023-07-18) ------------------- diff --git a/ros2_controllers_test_nodes/package.xml b/ros2_controllers_test_nodes/package.xml index bc0fab74b0..02af7f67b8 100644 --- a/ros2_controllers_test_nodes/package.xml +++ b/ros2_controllers_test_nodes/package.xml @@ -2,7 +2,7 @@ ros2_controllers_test_nodes - 3.12.0 + 3.13.0 Demo nodes for showing and testing functionalities of the ros2_control framework. Denis Štogl diff --git a/ros2_controllers_test_nodes/setup.py b/ros2_controllers_test_nodes/setup.py index c90806a128..6aceaa2cc2 100644 --- a/ros2_controllers_test_nodes/setup.py +++ b/ros2_controllers_test_nodes/setup.py @@ -20,7 +20,7 @@ setup( name=package_name, - version="3.12.0", + version="3.13.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index 4fc80aa5f8..3683d03c16 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.13.0 (2023-08-04) +------------------- 3.12.0 (2023-07-18) ------------------- diff --git a/rqt_joint_trajectory_controller/package.xml b/rqt_joint_trajectory_controller/package.xml index 1aa9b0df6d..c2541f3a96 100644 --- a/rqt_joint_trajectory_controller/package.xml +++ b/rqt_joint_trajectory_controller/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> rqt_joint_trajectory_controller - 3.12.0 + 3.13.0 Graphical frontend for interacting with joint_trajectory_controller instances. Bence Magyar diff --git a/rqt_joint_trajectory_controller/setup.py b/rqt_joint_trajectory_controller/setup.py index 844e8a51d8..701c285e61 100644 --- a/rqt_joint_trajectory_controller/setup.py +++ b/rqt_joint_trajectory_controller/setup.py @@ -7,7 +7,7 @@ setup( name=package_name, - version="3.12.0", + version="3.13.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/steering_controllers_library/CHANGELOG.rst b/steering_controllers_library/CHANGELOG.rst index 408df542dd..5bf04ede76 100644 --- a/steering_controllers_library/CHANGELOG.rst +++ b/steering_controllers_library/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package steering_controllers_library ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.13.0 (2023-08-04) +------------------- * Update ci-ros-lint.yml and copyright format (`#720 `_) * Contributors: Christoph Fröhlich diff --git a/steering_controllers_library/package.xml b/steering_controllers_library/package.xml index 2b8004356a..1da3cfa9df 100644 --- a/steering_controllers_library/package.xml +++ b/steering_controllers_library/package.xml @@ -2,7 +2,7 @@ steering_controllers_library - 3.12.0 + 3.13.0 Package for steering robot configurations including odometry and interfaces. Apache License 2.0 Bence Magyar diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index fec2d8782c..a40f09e557 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.13.0 (2023-08-04) +------------------- 3.12.0 (2023-07-18) ------------------- diff --git a/tricycle_controller/package.xml b/tricycle_controller/package.xml index 91f6fb5a19..9cc16d3b60 100644 --- a/tricycle_controller/package.xml +++ b/tricycle_controller/package.xml @@ -2,7 +2,7 @@ tricycle_controller - 3.12.0 + 3.13.0 Controller for a tricycle drive mobile base Bence Magyar Tony Najjar diff --git a/tricycle_steering_controller/CHANGELOG.rst b/tricycle_steering_controller/CHANGELOG.rst index 88b6ff647d..8d3c61ff6b 100644 --- a/tricycle_steering_controller/CHANGELOG.rst +++ b/tricycle_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package tricycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.13.0 (2023-08-04) +------------------- 3.12.0 (2023-07-18) ------------------- diff --git a/tricycle_steering_controller/package.xml b/tricycle_steering_controller/package.xml index e24d2f97c2..26083760d1 100644 --- a/tricycle_steering_controller/package.xml +++ b/tricycle_steering_controller/package.xml @@ -2,7 +2,7 @@ tricycle_steering_controller - 3.12.0 + 3.13.0 Steering controller with tricycle kinematics. Rear fixed wheels are powering the vehicle and front wheel is steering. Apache License 2.0 Bence Magyar diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index 7f9643a50b..b9fe5f9553 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.13.0 (2023-08-04) +------------------- 3.12.0 (2023-07-18) ------------------- diff --git a/velocity_controllers/package.xml b/velocity_controllers/package.xml index d861c91806..3551021f82 100644 --- a/velocity_controllers/package.xml +++ b/velocity_controllers/package.xml @@ -1,7 +1,7 @@ velocity_controllers - 3.12.0 + 3.13.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios From 2e7492e8c47c06de31232481c686d2215248fd83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Tue, 15 Aug 2023 13:37:52 +0200 Subject: [PATCH 093/238] [JTC] Explicitly set hold position (#558) --- .../doc/parameters.rst | 6 + joint_trajectory_controller/doc/userdoc.rst | 3 +- .../joint_trajectory_controller.hpp | 7 +- .../trajectory.hpp | 3 + .../src/joint_trajectory_controller.cpp | 146 +++++++++++------ ...oint_trajectory_controller_parameters.yaml | 5 + .../src/trajectory.cpp | 5 + .../test/test_trajectory_actions.cpp | 149 ++++++++---------- .../test/test_trajectory_controller.cpp | 88 +++++++---- .../test/test_trajectory_controller_utils.hpp | 85 +++++++++- 10 files changed, 331 insertions(+), 166 deletions(-) diff --git a/joint_trajectory_controller/doc/parameters.rst b/joint_trajectory_controller/doc/parameters.rst index 40aa8e6ba1..d5ddb831ca 100644 --- a/joint_trajectory_controller/doc/parameters.rst +++ b/joint_trajectory_controller/doc/parameters.rst @@ -57,6 +57,12 @@ open_loop_control (boolean) Default: false +start_with_holding (bool) + If true, start with holding position after activation. Otherwise, no command will be sent until + the first trajectory is received. + + Default: true + allow_nonzero_velocity_at_trajectory_end (boolean) If false, the last velocity point has to be zero or the goal will be rejected. diff --git a/joint_trajectory_controller/doc/userdoc.rst b/joint_trajectory_controller/doc/userdoc.rst index ccdef8a8e6..750e47d255 100644 --- a/joint_trajectory_controller/doc/userdoc.rst +++ b/joint_trajectory_controller/doc/userdoc.rst @@ -104,7 +104,6 @@ When an active action goal is preempted by another command coming from the actio Sending an empty trajectory message from the topic interface (not the action interface) will override the current action goal and not abort the action. - .. _ROS 2 interface: Description of controller's interfaces @@ -161,7 +160,7 @@ Subscriber [#f1]_ Topic for commanding the controller The topic interface is a fire-and-forget alternative. Use this interface if you don't care about execution monitoring. -The controller's path and goal tolerance specification is not used in this case, as there is no mechanism to notify the sender about tolerance violations. +The goal tolerance specification is not used in this case, as there is no mechanism to notify the sender about tolerance violations. If state tolerances are violated, the trajectory is aborted and the current position is held. Note that although some degree of monitoring is available through the ``~/query_state`` service and ``~/state`` topic it is much more cumbersome to realize than with the action interface. diff --git a/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp b/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp index dfbdf7436e..10b0f5923b 100644 --- a/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp +++ b/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp @@ -181,7 +181,6 @@ class JointTrajectoryController : public controller_interface::ControllerInterfa rclcpp::Service::SharedPtr query_state_srv_; - std::shared_ptr * traj_point_active_ptr_ = nullptr; std::shared_ptr traj_external_point_ptr_ = nullptr; std::shared_ptr traj_home_point_ptr_ = nullptr; std::shared_ptr traj_msg_home_ptr_ = nullptr; @@ -201,6 +200,7 @@ class JointTrajectoryController : public controller_interface::ControllerInterfa rclcpp_action::Server::SharedPtr action_server_; RealtimeGoalHandleBuffer rt_active_goal_; ///< Currently active action goal, if any. + realtime_tools::RealtimeBuffer rt_has_pending_goal_; ///< Is there a pending action goal? rclcpp::TimerBase::SharedPtr goal_handle_timer_; rclcpp::Duration action_monitor_period_ = rclcpp::Duration(50ms); @@ -243,11 +243,14 @@ class JointTrajectoryController : public controller_interface::ControllerInterfa JOINT_TRAJECTORY_CONTROLLER_PUBLIC void preempt_active_goal(); JOINT_TRAJECTORY_CONTROLLER_PUBLIC - void set_hold_position(); + std::shared_ptr set_hold_position(); JOINT_TRAJECTORY_CONTROLLER_PUBLIC bool reset(); + JOINT_TRAJECTORY_CONTROLLER_PUBLIC + bool has_active_trajectory(); + using JointTrajectoryPoint = trajectory_msgs::msg::JointTrajectoryPoint; JOINT_TRAJECTORY_CONTROLLER_PUBLIC void publish_state( diff --git a/joint_trajectory_controller/include/joint_trajectory_controller/trajectory.hpp b/joint_trajectory_controller/include/joint_trajectory_controller/trajectory.hpp index 230d0198f7..d2d0dc9dbd 100644 --- a/joint_trajectory_controller/include/joint_trajectory_controller/trajectory.hpp +++ b/joint_trajectory_controller/include/joint_trajectory_controller/trajectory.hpp @@ -130,6 +130,9 @@ class Trajectory JOINT_TRAJECTORY_CONTROLLER_PUBLIC bool has_trajectory_msg() const; + JOINT_TRAJECTORY_CONTROLLER_PUBLIC + bool has_nontrivial_msg() const; + JOINT_TRAJECTORY_CONTROLLER_PUBLIC std::shared_ptr get_trajectory_msg() const { diff --git a/joint_trajectory_controller/src/joint_trajectory_controller.cpp b/joint_trajectory_controller/src/joint_trajectory_controller.cpp index 616af7a648..ee9b0bf816 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller.cpp +++ b/joint_trajectory_controller/src/joint_trajectory_controller.cpp @@ -154,17 +154,21 @@ controller_interface::return_type JointTrajectoryController::update( } }; + // don't update goal after we sampled the trajectory to avoid any racecondition + const auto active_goal = *rt_active_goal_.readFromRT(); + // Check if a new external message has been received from nonRT threads auto current_external_msg = traj_external_point_ptr_->get_trajectory_msg(); auto new_external_msg = traj_msg_external_point_ptr_.readFromRT(); - if (current_external_msg != *new_external_msg) + // Discard, if a goal is pending but still not active (somewhere stuck in goal_handle_timer_) + if ( + current_external_msg != *new_external_msg && + (*(rt_has_pending_goal_.readFromRT()) && !active_goal) == false) { fill_partial_goal(*new_external_msg); sort_to_local_joint_order(*new_external_msg); // TODO(denis): Add here integration of position and velocity traj_external_point_ptr_->update(*new_external_msg); - // set the active trajectory pointer to the new goal - traj_point_active_ptr_ = &traj_external_point_ptr_; } // TODO(anyone): can I here also use const on joint_interface since the reference_wrapper is not @@ -182,29 +186,28 @@ controller_interface::return_type JointTrajectoryController::update( state_current_.time_from_start.set__sec(0); read_state_from_hardware(state_current_); - // currently carrying out a trajectory - if (traj_point_active_ptr_ && (*traj_point_active_ptr_)->has_trajectory_msg()) + // currently carrying out a trajectory. + if (has_active_trajectory()) { bool first_sample = false; // if sampling the first time, set the point before you sample - if (!(*traj_point_active_ptr_)->is_sampled_already()) + if (!traj_external_point_ptr_->is_sampled_already()) { first_sample = true; if (params_.open_loop_control) { - (*traj_point_active_ptr_)->set_point_before_trajectory_msg(time, last_commanded_state_); + traj_external_point_ptr_->set_point_before_trajectory_msg(time, last_commanded_state_); } else { - (*traj_point_active_ptr_)->set_point_before_trajectory_msg(time, state_current_); + traj_external_point_ptr_->set_point_before_trajectory_msg(time, state_current_); } } // find segment for current timestamp TrajectoryPointConstIter start_segment_itr, end_segment_itr; - const bool valid_point = - (*traj_point_active_ptr_) - ->sample(time, interpolation_method_, state_desired_, start_segment_itr, end_segment_itr); + const bool valid_point = traj_external_point_ptr_->sample( + time, interpolation_method_, state_desired_, start_segment_itr, end_segment_itr); if (valid_point) { @@ -212,7 +215,7 @@ controller_interface::return_type JointTrajectoryController::update( bool outside_goal_tolerance = false; bool within_goal_time = true; double time_difference = 0.0; - const bool before_last_point = end_segment_itr != (*traj_point_active_ptr_)->end(); + const bool before_last_point = end_segment_itr != traj_external_point_ptr_->end(); // Check state/goal tolerance for (size_t index = 0; index < dof_; ++index) @@ -239,7 +242,7 @@ controller_interface::return_type JointTrajectoryController::update( if (default_tolerances_.goal_time_tolerance != 0.0) { // if we exceed goal_time_tolerance set it to aborted - const rclcpp::Time traj_start = (*traj_point_active_ptr_)->get_trajectory_start_time(); + const rclcpp::Time traj_start = traj_external_point_ptr_->get_trajectory_start_time(); const rclcpp::Time traj_end = traj_start + start_segment_itr->time_from_start; time_difference = time.seconds() - traj_end.seconds(); @@ -296,7 +299,6 @@ controller_interface::return_type JointTrajectoryController::update( last_commanded_state_ = state_desired_; } - const auto active_goal = *rt_active_goal_.readFromRT(); if (active_goal) { // send feedback @@ -312,20 +314,20 @@ controller_interface::return_type JointTrajectoryController::update( // check abort if (tolerance_violated_while_moving) { - set_hold_position(); auto result = std::make_shared(); - - RCLCPP_WARN(get_node()->get_logger(), "Aborted due to state tolerance violation"); result->set__error_code(FollowJTrajAction::Result::PATH_TOLERANCE_VIOLATED); active_goal->setAborted(result); // TODO(matthew-reynolds): Need a lock-free write here // See https://github.com/ros-controls/ros2_controllers/issues/168 rt_active_goal_.writeFromNonRT(RealtimeGoalHandlePtr()); - // remove the active trajectory pointer so that we stop commanding the hardware - traj_point_active_ptr_ = nullptr; + rt_has_pending_goal_.writeFromNonRT(false); - // check goal tolerance + RCLCPP_WARN(get_node()->get_logger(), "Aborted due to state tolerance violation"); + + traj_msg_external_point_ptr_.reset(); + traj_msg_external_point_ptr_.initRT(set_hold_position()); } + // check goal tolerance else if (!before_last_point) { if (!outside_goal_tolerance) @@ -336,32 +338,42 @@ controller_interface::return_type JointTrajectoryController::update( // TODO(matthew-reynolds): Need a lock-free write here // See https://github.com/ros-controls/ros2_controllers/issues/168 rt_active_goal_.writeFromNonRT(RealtimeGoalHandlePtr()); - // remove the active trajectory pointer so that we stop commanding the hardware - traj_point_active_ptr_ = nullptr; + rt_has_pending_goal_.writeFromNonRT(false); RCLCPP_INFO(get_node()->get_logger(), "Goal reached, success!"); + + traj_msg_external_point_ptr_.reset(); + traj_msg_external_point_ptr_.initRT(set_hold_position()); } else if (!within_goal_time) { - set_hold_position(); auto result = std::make_shared(); result->set__error_code(FollowJTrajAction::Result::GOAL_TOLERANCE_VIOLATED); active_goal->setAborted(result); // TODO(matthew-reynolds): Need a lock-free write here // See https://github.com/ros-controls/ros2_controllers/issues/168 rt_active_goal_.writeFromNonRT(RealtimeGoalHandlePtr()); + rt_has_pending_goal_.writeFromNonRT(false); + RCLCPP_WARN( get_node()->get_logger(), "Aborted due goal_time_tolerance exceeding by %f seconds", time_difference); + + traj_msg_external_point_ptr_.reset(); + traj_msg_external_point_ptr_.initRT(set_hold_position()); } // else, run another cycle while waiting for outside_goal_tolerance // to be satisfied or violated within the goal_time_tolerance } } - else if (tolerance_violated_while_moving) + else if (tolerance_violated_while_moving && *(rt_has_pending_goal_.readFromRT()) == false) { - set_hold_position(); + // we need to ensure that there is no pending goal -> we get a race condition otherwise + RCLCPP_ERROR(get_node()->get_logger(), "Holding position due to state tolerance violation"); + + traj_msg_external_point_ptr_.reset(); + traj_msg_external_point_ptr_.initRT(set_hold_position()); } } } @@ -567,17 +579,16 @@ void JointTrajectoryController::query_state_service( const auto active_goal = *rt_active_goal_.readFromRT(); response->name = params_.joints; trajectory_msgs::msg::JointTrajectoryPoint state_requested = state_current_; - if ((traj_point_active_ptr_ && (*traj_point_active_ptr_)->has_trajectory_msg())) + if (has_active_trajectory()) { TrajectoryPointConstIter start_segment_itr, end_segment_itr; - response->success = (*traj_point_active_ptr_) - ->sample( - static_cast(request->time), interpolation_method_, - state_requested, start_segment_itr, end_segment_itr); + response->success = traj_external_point_ptr_->sample( + static_cast(request->time), interpolation_method_, state_requested, + start_segment_itr, end_segment_itr); // If the requested sample time precedes the trajectory finish time respond as failure if (response->success) { - if (end_segment_itr == (*traj_point_active_ptr_)->end()) + if (end_segment_itr == traj_external_point_ptr_->end()) { RCLCPP_ERROR(logger, "Requested sample time precedes the current trajectory end time."); response->success = false; @@ -916,7 +927,6 @@ controller_interface::CallbackReturn JointTrajectoryController::on_activate( std::shared_ptr()); subscriber_is_active_ = true; - traj_point_active_ptr_ = &traj_external_point_ptr_; // Initialize current state storage if hardware state has tracking offset read_state_from_hardware(state_current_); @@ -933,13 +943,18 @@ controller_interface::CallbackReturn JointTrajectoryController::on_activate( last_commanded_state_ = state; } + // Should the controller start by holding position after on_configure? + if (params_.start_with_holding) + { + add_new_trajectory_msg(set_hold_position()); + } + return CallbackReturn::SUCCESS; } controller_interface::CallbackReturn JointTrajectoryController::on_deactivate( const rclcpp_lifecycle::State &) { - // TODO(anyone): How to halt when using effort commands? for (size_t index = 0; index < dof_; ++index) { if (has_position_command_interface_) @@ -953,6 +968,12 @@ controller_interface::CallbackReturn JointTrajectoryController::on_deactivate( joint_command_interface_[1][index].get().set_value(0.0); } + if (has_acceleration_command_interface_) + { + joint_command_interface_[2][index].get().set_value(0.0); + } + + // TODO(anyone): How to halt when using effort commands? if (has_effort_command_interface_) { joint_command_interface_[3][index].get().set_value(0.0); @@ -968,6 +989,10 @@ controller_interface::CallbackReturn JointTrajectoryController::on_deactivate( subscriber_is_active_ = false; + traj_external_point_ptr_.reset(); + traj_home_point_ptr_.reset(); + traj_msg_home_ptr_.reset(); + return CallbackReturn::SUCCESS; } @@ -978,7 +1003,7 @@ controller_interface::CallbackReturn JointTrajectoryController::on_cleanup( if (traj_home_point_ptr_ != nullptr) { traj_home_point_ptr_->update(traj_msg_home_ptr_); - traj_point_active_ptr_ = &traj_home_point_ptr_; + traj_external_point_ptr_ = traj_home_point_ptr_; } return CallbackReturn::SUCCESS; @@ -1009,7 +1034,6 @@ bool JointTrajectoryController::reset() // iterator has no default value // prev_traj_point_ptr_; - traj_point_active_ptr_ = nullptr; traj_external_point_ptr_.reset(); traj_home_point_ptr_.reset(); traj_msg_home_ptr_.reset(); @@ -1102,17 +1126,17 @@ rclcpp_action::CancelResponse JointTrajectoryController::goal_cancelled_callback const auto active_goal = *rt_active_goal_.readFromNonRT(); if (active_goal && active_goal->gh_ == goal_handle) { - // Controller uptime - // Enter hold current position mode - set_hold_position(); - - RCLCPP_DEBUG( + RCLCPP_INFO( get_node()->get_logger(), "Canceling active action goal because cancel callback received."); // Mark the current goal as canceled + rt_has_pending_goal_.writeFromNonRT(false); auto action_res = std::make_shared(); active_goal->setCanceled(action_res); rt_active_goal_.writeFromNonRT(RealtimeGoalHandlePtr()); + + // Enter hold current position mode + add_new_trajectory_msg(set_hold_position()); } return rclcpp_action::CancelResponse::ACCEPT; } @@ -1120,6 +1144,9 @@ rclcpp_action::CancelResponse JointTrajectoryController::goal_cancelled_callback void JointTrajectoryController::goal_accepted_callback( std::shared_ptr> goal_handle) { + // mark a pending goal + rt_has_pending_goal_.writeFromNonRT(true); + // Update new trajectory { preempt_active_goal(); @@ -1408,7 +1435,7 @@ void JointTrajectoryController::preempt_active_goal() const auto active_goal = *rt_active_goal_.readFromNonRT(); if (active_goal) { - set_hold_position(); + add_new_trajectory_msg(set_hold_position()); auto action_res = std::make_shared(); action_res->set__error_code(FollowJTrajAction::Result::INVALID_GOAL); action_res->set__error_string("Current goal cancelled due to new incoming action."); @@ -1417,13 +1444,35 @@ void JointTrajectoryController::preempt_active_goal() } } -void JointTrajectoryController::set_hold_position() +std::shared_ptr +JointTrajectoryController::set_hold_position() { - trajectory_msgs::msg::JointTrajectory empty_msg; - empty_msg.header.stamp = rclcpp::Time(0); + // Command to stay at current position + trajectory_msgs::msg::JointTrajectory current_pose_msg; + current_pose_msg.header.stamp = + rclcpp::Time(0.0, 0.0, get_node()->get_clock()->get_clock_type()); // start immediately + current_pose_msg.joint_names = params_.joints; + current_pose_msg.points.push_back(state_current_); + current_pose_msg.points[0].velocities.clear(); + current_pose_msg.points[0].accelerations.clear(); + current_pose_msg.points[0].effort.clear(); + if (has_velocity_command_interface_) + { + // ensure no velocity (PID will fix this) + current_pose_msg.points[0].velocities.resize(dof_, 0.0); + } + if (has_acceleration_command_interface_) + { + // ensure no acceleration + current_pose_msg.points[0].accelerations.resize(dof_, 0.0); + } + if (has_effort_command_interface_) + { + // ensure no explicit effort (PID will fix this) + current_pose_msg.points[0].effort.resize(dof_, 0.0); + } - auto traj_msg = std::make_shared(empty_msg); - add_new_trajectory_msg(traj_msg); + return std::make_shared(current_pose_msg); } bool JointTrajectoryController::contains_interface_type( @@ -1468,6 +1517,11 @@ void JointTrajectoryController::resize_joint_trajectory_point_command( } } +bool JointTrajectoryController::has_active_trajectory() +{ + return traj_external_point_ptr_ != nullptr && traj_external_point_ptr_->has_trajectory_msg(); +} + } // namespace joint_trajectory_controller #include "pluginlib/class_list_macros.hpp" diff --git a/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml b/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml index 5627f1d8f5..1112c3304b 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml +++ b/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml @@ -66,6 +66,11 @@ joint_trajectory_controller: one_of<>: [["splines", "none"]], } } + start_with_holding: { + type: bool, + default_value: true, + description: "If true, start with holding position after activation. Otherwise, no command will be sent until the first trajectory is received.", + } allow_nonzero_velocity_at_trajectory_end: { type: bool, default_value: true, diff --git a/joint_trajectory_controller/src/trajectory.cpp b/joint_trajectory_controller/src/trajectory.cpp index 06b3ca6e9b..fae4c41ff9 100644 --- a/joint_trajectory_controller/src/trajectory.cpp +++ b/joint_trajectory_controller/src/trajectory.cpp @@ -351,4 +351,9 @@ rclcpp::Time Trajectory::time_from_start() const { return trajectory_start_time_ bool Trajectory::has_trajectory_msg() const { return trajectory_msg_.get() != nullptr; } +bool Trajectory::has_nontrivial_msg() const +{ + return has_trajectory_msg() && trajectory_msg_->points.size() > 1; +} + } // namespace joint_trajectory_controller diff --git a/joint_trajectory_controller/test/test_trajectory_actions.cpp b/joint_trajectory_controller/test/test_trajectory_actions.cpp index fdea551c30..2c28319d52 100644 --- a/joint_trajectory_controller/test/test_trajectory_actions.cpp +++ b/joint_trajectory_controller/test/test_trajectory_actions.cpp @@ -224,15 +224,14 @@ TEST_P(TestTrajectoryActionsTestParameterized, test_success_single_point_sendgoa std::shared_future gh_future; // send goal + std::vector point_positions{1.0, 2.0, 3.0}; { std::vector points; JointTrajectoryPoint point; point.time_from_start = rclcpp::Duration::from_seconds(0.5); point.positions.resize(joint_names_.size()); - point.positions[0] = 1.0; - point.positions[1] = 2.0; - point.positions[2] = 3.0; + point.positions = point_positions; points.push_back(point); @@ -243,12 +242,13 @@ TEST_P(TestTrajectoryActionsTestParameterized, test_success_single_point_sendgoa EXPECT_TRUE(gh_future.get()); EXPECT_EQ(rclcpp_action::ResultCode::SUCCEEDED, common_resultcode_); - if (traj_controller_->has_position_command_interface()) - { - EXPECT_EQ(1.0, joint_pos_[0]); - EXPECT_EQ(2.0, joint_pos_[1]); - EXPECT_EQ(3.0, joint_pos_[2]); - } + // run an update + updateController(rclcpp::Duration::from_seconds(0.01)); + + // it should be holding the last position goal + // i.e., active but trivial trajectory (one point only) + // note: the action goal also is a trivial trajectory + expectHoldingPoint(point_positions); } TEST_P(TestTrajectoryActionsTestParameterized, test_success_multi_point_sendgoal) @@ -265,24 +265,21 @@ TEST_P(TestTrajectoryActionsTestParameterized, test_success_multi_point_sendgoal std::shared_future gh_future; // send goal with multiple points + std::vector> points_positions{{{4.0, 5.0, 6.0}}, {{7.0, 8.0, 9.0}}}; { std::vector points; JointTrajectoryPoint point1; point1.time_from_start = rclcpp::Duration::from_seconds(0.2); point1.positions.resize(joint_names_.size()); - point1.positions[0] = 4.0; - point1.positions[1] = 5.0; - point1.positions[2] = 6.0; + point1.positions = points_positions.at(0); points.push_back(point1); JointTrajectoryPoint point2; point2.time_from_start = rclcpp::Duration::from_seconds(0.3); point2.positions.resize(joint_names_.size()); - point2.positions[0] = 7.0; - point2.positions[1] = 8.0; - point2.positions[2] = 9.0; + point2.positions = points_positions.at(1); points.push_back(point2); gh_future = sendActionGoal(points, 1.0, goal_options_); @@ -293,12 +290,12 @@ TEST_P(TestTrajectoryActionsTestParameterized, test_success_multi_point_sendgoal EXPECT_TRUE(gh_future.get()); EXPECT_EQ(rclcpp_action::ResultCode::SUCCEEDED, common_resultcode_); - if (traj_controller_->has_position_command_interface()) - { - EXPECT_NEAR(7.0, joint_pos_[0], COMMON_THRESHOLD); - EXPECT_NEAR(8.0, joint_pos_[1], COMMON_THRESHOLD); - EXPECT_NEAR(9.0, joint_pos_[2], COMMON_THRESHOLD); - } + // run an update + updateController(rclcpp::Duration::from_seconds(0.01)); + + // it should be holding the last position goal + // i.e., active but trivial trajectory (one point only) + expectHoldingPoint(points_positions.at(1)); } /** @@ -318,15 +315,14 @@ TEST_F(TestTrajectoryActions, test_goal_tolerances_single_point_success) std::shared_future gh_future; // send goal + std::vector> points_positions{{{1.0, 2.0, 3.0}}}; { std::vector points; JointTrajectoryPoint point; point.time_from_start = rclcpp::Duration::from_seconds(0.5); point.positions.resize(joint_names_.size()); - point.positions[0] = 1.0; - point.positions[1] = 2.0; - point.positions[2] = 3.0; + point.positions = points_positions.at(0); points.push_back(point); gh_future = sendActionGoal(points, 1.0, goal_options_); @@ -338,12 +334,12 @@ TEST_F(TestTrajectoryActions, test_goal_tolerances_single_point_success) EXPECT_EQ( control_msgs::action::FollowJointTrajectory_Result::SUCCESSFUL, common_action_result_code_); - if (traj_controller_->has_position_command_interface()) - { - EXPECT_NEAR(1.0, joint_pos_[0], COMMON_THRESHOLD); - EXPECT_NEAR(2.0, joint_pos_[1], COMMON_THRESHOLD); - EXPECT_NEAR(3.0, joint_pos_[2], COMMON_THRESHOLD); - } + // run an update + updateController(rclcpp::Duration::from_seconds(0.01)); + + // it should be holding the last position goal + // i.e., active but trivial trajectory (one point only) + expectHoldingPoint(points_positions.at(0)); } /** @@ -370,24 +366,21 @@ TEST_F(TestTrajectoryActions, test_goal_tolerances_multi_point_success) std::shared_future gh_future; // send goal with multiple points + std::vector> points_positions{{{4.0, 5.0, 6.0}}, {{7.0, 8.0, 9.0}}}; { std::vector points; JointTrajectoryPoint point1; point1.time_from_start = rclcpp::Duration::from_seconds(0.2); point1.positions.resize(joint_names_.size()); - point1.positions[0] = 4.0; - point1.positions[1] = 5.0; - point1.positions[2] = 6.0; + point1.positions = points_positions.at(0); points.push_back(point1); JointTrajectoryPoint point2; point2.time_from_start = rclcpp::Duration::from_seconds(0.3); point2.positions.resize(joint_names_.size()); - point2.positions[0] = 7.0; - point2.positions[1] = 8.0; - point2.positions[2] = 9.0; + point2.positions = points_positions.at(1); points.push_back(point2); gh_future = sendActionGoal(points, 1.0, goal_options_); @@ -400,12 +393,12 @@ TEST_F(TestTrajectoryActions, test_goal_tolerances_multi_point_success) EXPECT_EQ( control_msgs::action::FollowJointTrajectory_Result::SUCCESSFUL, common_action_result_code_); - if (traj_controller_->has_position_command_interface()) - { - EXPECT_NEAR(7.0, joint_pos_[0], COMMON_THRESHOLD); - EXPECT_NEAR(8.0, joint_pos_[1], COMMON_THRESHOLD); - EXPECT_NEAR(9.0, joint_pos_[2], COMMON_THRESHOLD); - } + // run an update + updateController(rclcpp::Duration::from_seconds(0.01)); + + // it should be holding the last position goal + // i.e., active but trivial trajectory (one point only) + expectHoldingPoint(points_positions.at(1)); } TEST_P(TestTrajectoryActionsTestParameterized, test_state_tolerances_fail) @@ -417,29 +410,28 @@ TEST_P(TestTrajectoryActionsTestParameterized, test_state_tolerances_fail) rclcpp::Parameter("constraints.joint2.trajectory", state_tol), rclcpp::Parameter("constraints.joint3.trajectory", state_tol)}; - SetUpExecutor(params); + // separate command from states -> immediate state tolerance fail + bool separate_cmd_and_state_values = true; + SetUpExecutor(params, separate_cmd_and_state_values); SetUpControllerHardware(); std::shared_future gh_future; // send goal + std::vector> points_positions{{{4.0, 5.0, 6.0}}, {{7.0, 8.0, 9.0}}}; { std::vector points; JointTrajectoryPoint point1; point1.time_from_start = rclcpp::Duration::from_seconds(0.0); point1.positions.resize(joint_names_.size()); - point1.positions[0] = 4.0; - point1.positions[1] = 5.0; - point1.positions[2] = 6.0; + point1.positions = points_positions.at(0); points.push_back(point1); JointTrajectoryPoint point2; point2.time_from_start = rclcpp::Duration::from_seconds(0.1); point2.positions.resize(joint_names_.size()); - point2.positions[0] = 7.0; - point2.positions[1] = 8.0; - point2.positions[2] = 9.0; + point2.positions = points_positions.at(1); points.push_back(point2); gh_future = sendActionGoal(points, 1.0, goal_options_); @@ -452,15 +444,13 @@ TEST_P(TestTrajectoryActionsTestParameterized, test_state_tolerances_fail) control_msgs::action::FollowJointTrajectory_Result::PATH_TOLERANCE_VIOLATED, common_action_result_code_); - // run an update, it should be holding + // run an update updateController(rclcpp::Duration::from_seconds(0.01)); - if (traj_controller_->has_position_command_interface()) - { - EXPECT_NEAR(INITIAL_POS_JOINT1, joint_pos_[0], COMMON_THRESHOLD); - EXPECT_NEAR(INITIAL_POS_JOINT2, joint_pos_[1], COMMON_THRESHOLD); - EXPECT_NEAR(INITIAL_POS_JOINT3, joint_pos_[2], COMMON_THRESHOLD); - } + // it should be holding the position (being the initial one) + // i.e., active but trivial trajectory (one point only) + std::vector initial_positions{INITIAL_POS_JOINT1, INITIAL_POS_JOINT2, INITIAL_POS_JOINT3}; + expectHoldingPoint(initial_positions); } TEST_P(TestTrajectoryActionsTestParameterized, test_goal_tolerances_fail) @@ -503,15 +493,13 @@ TEST_P(TestTrajectoryActionsTestParameterized, test_goal_tolerances_fail) control_msgs::action::FollowJointTrajectory_Result::GOAL_TOLERANCE_VIOLATED, common_action_result_code_); - // run an update, it should be holding the last received goal + // run an update updateController(rclcpp::Duration::from_seconds(0.01)); - if (traj_controller_->has_position_command_interface()) - { - EXPECT_NEAR(4.0, joint_pos_[0], COMMON_THRESHOLD); - EXPECT_NEAR(5.0, joint_pos_[1], COMMON_THRESHOLD); - EXPECT_NEAR(6.0, joint_pos_[2], COMMON_THRESHOLD); - } + // it should be holding the position (being the initial one) + // i.e., active but trivial trajectory (one point only) + std::vector initial_positions{INITIAL_POS_JOINT1, INITIAL_POS_JOINT2, INITIAL_POS_JOINT3}; + expectHoldingPoint(initial_positions); } TEST_P(TestTrajectoryActionsTestParameterized, test_no_time_from_start_state_tolerance_fail) @@ -523,13 +511,11 @@ TEST_P(TestTrajectoryActionsTestParameterized, test_no_time_from_start_state_tol rclcpp::Parameter("constraints.joint2.trajectory", state_tol), rclcpp::Parameter("constraints.joint3.trajectory", state_tol)}; - SetUpExecutor(params); + // separate command from states -> goal won't never be reached + bool separate_cmd_and_state_values = true; + SetUpExecutor(params, separate_cmd_and_state_values); SetUpControllerHardware(); - const double init_pos1 = joint_pos_[0]; - const double init_pos2 = joint_pos_[1]; - const double init_pos3 = joint_pos_[2]; - std::shared_future gh_future; // send goal { @@ -553,15 +539,13 @@ TEST_P(TestTrajectoryActionsTestParameterized, test_no_time_from_start_state_tol control_msgs::action::FollowJointTrajectory_Result::PATH_TOLERANCE_VIOLATED, common_action_result_code_); - // run an update, it should be holding + // run an update updateController(rclcpp::Duration::from_seconds(0.01)); - if (traj_controller_->has_position_command_interface()) - { - EXPECT_NEAR(init_pos1, joint_pos_[0], COMMON_THRESHOLD); - EXPECT_NEAR(init_pos2, joint_pos_[1], COMMON_THRESHOLD); - EXPECT_NEAR(init_pos3, joint_pos_[2], COMMON_THRESHOLD); - } + // it should be holding the position (being the initial one) + // i.e., active but trivial trajectory (one point only) + std::vector initial_positions{INITIAL_POS_JOINT1, INITIAL_POS_JOINT2, INITIAL_POS_JOINT3}; + expectHoldingPoint(initial_positions); } TEST_P(TestTrajectoryActionsTestParameterized, test_cancel_hold_position) @@ -601,19 +585,14 @@ TEST_P(TestTrajectoryActionsTestParameterized, test_cancel_hold_position) EXPECT_EQ( control_msgs::action::FollowJointTrajectory_Result::SUCCESSFUL, common_action_result_code_); - const double prev_pos1 = joint_pos_[0]; - const double prev_pos2 = joint_pos_[1]; - const double prev_pos3 = joint_pos_[2]; + std::vector cancelled_position{joint_pos_[0], joint_pos_[1], joint_pos_[2]}; - // run an update, it should be holding + // run an update updateController(rclcpp::Duration::from_seconds(0.01)); - if (traj_controller_->has_position_command_interface()) - { - EXPECT_EQ(prev_pos1, joint_pos_[0]); - EXPECT_EQ(prev_pos2, joint_pos_[1]); - EXPECT_EQ(prev_pos3, joint_pos_[2]); - } + // it should be holding the last position, + // i.e., active but trivial trajectory (one point only) + expectHoldingPoint(cancelled_position); } TEST_P(TestTrajectoryActionsTestParameterized, test_allow_nonzero_velocity_at_trajectory_end_true) diff --git a/joint_trajectory_controller/test/test_trajectory_controller.cpp b/joint_trajectory_controller/test/test_trajectory_controller.cpp index 375cdc0346..6cdf324596 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller.cpp +++ b/joint_trajectory_controller/test/test_trajectory_controller.cpp @@ -285,44 +285,38 @@ TEST_P(TrajectoryControllerTestParameterized, correct_initialization_using_param // first update traj_controller_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.1)); - // wait so controller process the second point when deactivated + // wait for reaching the first point + // controller would process the second point when deactivated below traj_controller_->update( rclcpp::Time(static_cast(0.25 * 1e9)), rclcpp::Duration::from_seconds(0.15)); - // deactivated - state = traj_controller_->get_node()->deactivate(); - ASSERT_EQ(state.id(), State::PRIMARY_STATE_INACTIVE); - - const auto allowed_delta = 0.05; + EXPECT_TRUE(traj_controller_->has_active_traj()); if (traj_controller_->has_position_command_interface()) { - EXPECT_NEAR(3.3, joint_pos_[0], allowed_delta); - EXPECT_NEAR(4.4, joint_pos_[1], allowed_delta); - EXPECT_NEAR(5.5, joint_pos_[2], allowed_delta); - } - - if (traj_controller_->has_velocity_command_interface()) - { - EXPECT_LE(0.0, joint_vel_[0]); - EXPECT_LE(0.0, joint_vel_[1]); - EXPECT_LE(0.0, joint_vel_[2]); + EXPECT_NEAR(points.at(0).at(0), joint_pos_[0], COMMON_THRESHOLD); + EXPECT_NEAR(points.at(0).at(1), joint_pos_[1], COMMON_THRESHOLD); + EXPECT_NEAR(points.at(0).at(2), joint_pos_[2], COMMON_THRESHOLD); } - if (traj_controller_->has_effort_command_interface()) - { - EXPECT_LE(0.0, joint_eff_[0]); - EXPECT_LE(0.0, joint_eff_[1]); - EXPECT_LE(0.0, joint_eff_[2]); - } + // deactivate + std::vector deactivated_positions{joint_pos_[0], joint_pos_[1], joint_pos_[2]}; + state = traj_controller_->get_node()->deactivate(); + ASSERT_EQ(state.id(), State::PRIMARY_STATE_INACTIVE); + // it should be holding the current point + traj_controller_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.1)); + expectHoldingPointDeactivated(deactivated_positions); - // reactivated - // wait so controller process the third point when reactivated + // reactivate + // wait so controller would have processed the third point when reactivated -> but it shouldn't std::this_thread::sleep_for(std::chrono::milliseconds(3000)); - ActivateTrajectoryController(); + + ActivateTrajectoryController(false, deactivated_positions); state = traj_controller_->get_state(); ASSERT_EQ(state.id(), State::PRIMARY_STATE_ACTIVE); - // TODO(christophfroehlich) add test if there is no active trajectory after - // reactivation once #558 or #609 got merged (needs methods for TestableJointTrajectoryController) + // it should still be holding the position at time of deactivation + // i.e., active but trivial trajectory (one point only) + traj_controller_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.1)); + expectHoldingPoint(deactivated_positions); executor.cancel(); } @@ -424,6 +418,45 @@ TEST_P(TrajectoryControllerTestParameterized, state_topic_consistency) } } +/** + * @brief check if hold on startup is deactivated + */ +TEST_P(TrajectoryControllerTestParameterized, no_hold_on_startup) +{ + rclcpp::executors::MultiThreadedExecutor executor; + + rclcpp::Parameter start_with_holding_parameter("start_with_holding", false); + SetUpAndActivateTrajectoryController(executor, true, {start_with_holding_parameter}); + + constexpr auto FIRST_POINT_TIME = std::chrono::milliseconds(250); + updateController(rclcpp::Duration(FIRST_POINT_TIME)); + // after startup without start_with_holding being set, we expect no active trajectory + ASSERT_FALSE(traj_controller_->has_active_traj()); + + executor.cancel(); +} + +/** + * @brief check if hold on startup + */ +TEST_P(TrajectoryControllerTestParameterized, hold_on_startup) +{ + rclcpp::executors::MultiThreadedExecutor executor; + + rclcpp::Parameter start_with_holding_parameter("start_with_holding", true); + SetUpAndActivateTrajectoryController(executor, true, {start_with_holding_parameter}); + + constexpr auto FIRST_POINT_TIME = std::chrono::milliseconds(250); + updateController(rclcpp::Duration(FIRST_POINT_TIME)); + // after startup with start_with_holding being set, we expect an active trajectory: + ASSERT_TRUE(traj_controller_->has_active_traj()); + // one point, being the position at startup + std::vector initial_positions{INITIAL_POS_JOINT1, INITIAL_POS_JOINT2, INITIAL_POS_JOINT3}; + expectHoldingPoint(initial_positions); + + executor.cancel(); +} + // Floating-point value comparison threshold const double EPS = 1e-6; /** @@ -1156,7 +1189,6 @@ TEST_P(TrajectoryControllerTestParameterized, test_ignore_old_trajectory) rclcpp::Clock(RCL_STEADY_TIME).now() - delay - std::chrono::milliseconds(100); expected_actual.positions = {points_old[1].begin(), points_old[1].end()}; expected_desired = expected_actual; - std::cout << "Sending old trajectory" << std::endl; publish(time_from_start, points_new, new_traj_start); waitAndCompareState(expected_actual, expected_desired, executor, rclcpp::Duration(delay), 0.1); } diff --git a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp index 5ec0f4f29e..87324d61b0 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp +++ b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp @@ -25,6 +25,7 @@ #include "hardware_interface/types/hardware_interface_type_values.hpp" #include "joint_trajectory_controller/joint_trajectory_controller.hpp" +#include "joint_trajectory_controller/trajectory.hpp" namespace { @@ -123,6 +124,13 @@ class TestableJointTrajectoryController bool is_open_loop() { return params_.open_loop_control; } + bool has_active_traj() { return has_active_trajectory(); } + + bool has_trivial_traj() + { + return has_active_trajectory() && traj_external_point_ptr_->has_nontrivial_msg() == false; + } + rclcpp::WaitSet joint_cmd_sub_wait_set_; }; @@ -224,7 +232,9 @@ class TrajectoryControllerTest : public ::testing::Test ActivateTrajectoryController(separate_cmd_and_state_values); } - void ActivateTrajectoryController(bool separate_cmd_and_state_values = false) + void ActivateTrajectoryController( + bool separate_cmd_and_state_values = false, + const std::vector initial_pos_joints = INITIAL_POS_JOINTS) { std::vector cmd_interfaces; std::vector state_interfaces; @@ -258,14 +268,14 @@ class TrajectoryControllerTest : public ::testing::Test // Add to export lists and set initial values cmd_interfaces.emplace_back(pos_cmd_interfaces_.back()); - cmd_interfaces.back().set_value(INITIAL_POS_JOINTS[i]); + cmd_interfaces.back().set_value(initial_pos_joints[i]); cmd_interfaces.emplace_back(vel_cmd_interfaces_.back()); cmd_interfaces.back().set_value(INITIAL_VEL_JOINTS[i]); cmd_interfaces.emplace_back(acc_cmd_interfaces_.back()); cmd_interfaces.back().set_value(INITIAL_ACC_JOINTS[i]); cmd_interfaces.emplace_back(eff_cmd_interfaces_.back()); cmd_interfaces.back().set_value(INITIAL_EFF_JOINTS[i]); - joint_state_pos_[i] = INITIAL_POS_JOINTS[i]; + joint_state_pos_[i] = initial_pos_joints[i]; joint_state_vel_[i] = INITIAL_VEL_JOINTS[i]; joint_state_acc_[i] = INITIAL_ACC_JOINTS[i]; state_interfaces.emplace_back(pos_state_interfaces_.back()); @@ -426,6 +436,75 @@ class TrajectoryControllerTest : public ::testing::Test return state_msg_; } + void expectHoldingPoint(std::vector point) + { + // it should be holding the given point + // i.e., active but trivial trajectory (one point only) + EXPECT_TRUE(traj_controller_->has_trivial_traj()); + + if (traj_controller_->has_position_command_interface()) + { + EXPECT_NEAR(point.at(0), joint_pos_[0], COMMON_THRESHOLD); + EXPECT_NEAR(point.at(1), joint_pos_[1], COMMON_THRESHOLD); + EXPECT_NEAR(point.at(2), joint_pos_[2], COMMON_THRESHOLD); + } + + if (traj_controller_->has_velocity_command_interface()) + { + EXPECT_EQ(0.0, joint_vel_[0]); + EXPECT_EQ(0.0, joint_vel_[1]); + EXPECT_EQ(0.0, joint_vel_[2]); + } + + if (traj_controller_->has_acceleration_command_interface()) + { + EXPECT_EQ(0.0, joint_acc_[0]); + EXPECT_EQ(0.0, joint_acc_[1]); + EXPECT_EQ(0.0, joint_acc_[2]); + } + + if (traj_controller_->has_effort_command_interface()) + { + EXPECT_EQ(0.0, joint_eff_[0]); + EXPECT_EQ(0.0, joint_eff_[1]); + EXPECT_EQ(0.0, joint_eff_[2]); + } + } + + void expectHoldingPointDeactivated(std::vector point) + { + // it should be holding the given point, but no active trajectory + EXPECT_FALSE(traj_controller_->has_active_traj()); + + if (traj_controller_->has_position_command_interface()) + { + EXPECT_NEAR(point.at(0), joint_pos_[0], COMMON_THRESHOLD); + EXPECT_NEAR(point.at(1), joint_pos_[1], COMMON_THRESHOLD); + EXPECT_NEAR(point.at(2), joint_pos_[2], COMMON_THRESHOLD); + } + + if (traj_controller_->has_velocity_command_interface()) + { + EXPECT_EQ(0.0, joint_vel_[0]); + EXPECT_EQ(0.0, joint_vel_[1]); + EXPECT_EQ(0.0, joint_vel_[2]); + } + + if (traj_controller_->has_acceleration_command_interface()) + { + EXPECT_EQ(0.0, joint_acc_[0]); + EXPECT_EQ(0.0, joint_acc_[1]); + EXPECT_EQ(0.0, joint_acc_[2]); + } + + if (traj_controller_->has_effort_command_interface()) + { + EXPECT_EQ(0.0, joint_eff_[0]); + EXPECT_EQ(0.0, joint_eff_[1]); + EXPECT_EQ(0.0, joint_eff_[2]); + } + } + std::string controller_name_; std::vector joint_names_; From af54985bc09121d4ca5d45fba68effc279cb2689 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Tue, 15 Aug 2023 13:40:35 +0200 Subject: [PATCH 094/238] Use tabs (#743) Co-authored-by: Bence Magyar --- forward_command_controller/doc/userdoc.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/forward_command_controller/doc/userdoc.rst b/forward_command_controller/doc/userdoc.rst index ee0af57d7b..a91479c9af 100644 --- a/forward_command_controller/doc/userdoc.rst +++ b/forward_command_controller/doc/userdoc.rst @@ -21,12 +21,12 @@ Parameters This controller uses the `generate_parameter_library `_ to handle its parameters. -forward_command_controller -^^^^^^^^^^^^^^^^^^^^^^^^^^ + .. tabs:: + + .. group-tab:: forward_command_controller -.. generate_parameter_library_details:: ../src/forward_command_controller_parameters.yaml + .. generate_parameter_library_details:: ../src/forward_command_controller_parameters.yaml -multi_interface_forward_command_controller -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + .. group-tab:: multi_interface_forward_command_controller -.. generate_parameter_library_details:: ../src/multi_interface_forward_command_controller_parameters.yaml + .. generate_parameter_library_details:: ../src/multi_interface_forward_command_controller_parameters.yaml From 5178503f1044cc988663c196c32a0039c72418b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Tue, 15 Aug 2023 13:40:52 +0200 Subject: [PATCH 095/238] Remove wrong description (#742) --- joint_trajectory_controller/doc/userdoc.rst | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/joint_trajectory_controller/doc/userdoc.rst b/joint_trajectory_controller/doc/userdoc.rst index 750e47d255..b9d8e274cf 100644 --- a/joint_trajectory_controller/doc/userdoc.rst +++ b/joint_trajectory_controller/doc/userdoc.rst @@ -178,17 +178,6 @@ Services Query controller state at any future time -Specialized versions of JointTrajectoryController --------------------------------------------------------------- -(TBD in ...) - -The controller types are placed into namespaces according to their command types for the hardware (see :ref:`controllers`). - -The following version of the Joint Trajectory Controller are available mapping the following interfaces: - -* position_controllers::JointTrajectoryController - - Further information -------------------------------------------------------------- From 6b73cf56d20b8d85db9ea54775765e67aef014a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Wed, 16 Aug 2023 15:35:57 +0200 Subject: [PATCH 096/238] [JTC] Fix typos, implicit cast, const member functions (#748) --- .../joint_trajectory_controller.hpp | 2 +- .../src/joint_trajectory_controller.cpp | 2 +- ...oint_trajectory_controller_parameters.yaml | 4 ++-- .../test/test_trajectory_controller.cpp | 6 ++--- .../test/test_trajectory_controller_utils.hpp | 24 +++++++++---------- 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp b/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp index 10b0f5923b..1df557d029 100644 --- a/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp +++ b/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp @@ -249,7 +249,7 @@ class JointTrajectoryController : public controller_interface::ControllerInterfa bool reset(); JOINT_TRAJECTORY_CONTROLLER_PUBLIC - bool has_active_trajectory(); + bool has_active_trajectory() const; using JointTrajectoryPoint = trajectory_msgs::msg::JointTrajectoryPoint; JOINT_TRAJECTORY_CONTROLLER_PUBLIC diff --git a/joint_trajectory_controller/src/joint_trajectory_controller.cpp b/joint_trajectory_controller/src/joint_trajectory_controller.cpp index ee9b0bf816..9c5ee68132 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller.cpp +++ b/joint_trajectory_controller/src/joint_trajectory_controller.cpp @@ -1517,7 +1517,7 @@ void JointTrajectoryController::resize_joint_trajectory_point_command( } } -bool JointTrajectoryController::has_active_trajectory() +bool JointTrajectoryController::has_active_trajectory() const { return traj_external_point_ptr_ != nullptr && traj_external_point_ptr_->has_trajectory_msg(); } diff --git a/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml b/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml index 1112c3304b..5b8a8d14f2 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml +++ b/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml @@ -86,7 +86,7 @@ joint_trajectory_controller: i: { type: double, default_value: 0.0, - description: "Intigral gain for PID" + description: "Integral gain for PID" } d: { type: double, @@ -96,7 +96,7 @@ joint_trajectory_controller: i_clamp: { type: double, default_value: 0.0, - description: "Integrale clamp. Symmetrical in both positive and negative direction." + description: "Integral clamp. Symmetrical in both positive and negative direction." } ff_velocity_scale: { type: double, diff --git a/joint_trajectory_controller/test/test_trajectory_controller.cpp b/joint_trajectory_controller/test/test_trajectory_controller.cpp index 6cdf324596..4149058c77 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller.cpp +++ b/joint_trajectory_controller/test/test_trajectory_controller.cpp @@ -1531,9 +1531,9 @@ TEST_P(TrajectoryControllerTestParameterized, test_hw_states_has_offset_later_co // set command values to NaN for (size_t i = 0; i < 3; ++i) { - joint_pos_[i] = 3.1 + i; - joint_vel_[i] = 0.25 + i; - joint_acc_[i] = 0.02 + i / 10.0; + joint_pos_[i] = 3.1 + static_cast(i); + joint_vel_[i] = 0.25 + static_cast(i); + joint_acc_[i] = 0.02 + static_cast(i) / 10.0; } SetUpAndActivateTrajectoryController(executor, true, {is_open_loop_parameters}, true); diff --git a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp index 87324d61b0..8a22f986aa 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp +++ b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp @@ -102,31 +102,31 @@ class TestableJointTrajectoryController void trigger_declare_parameters() { param_listener_->declare_params(); } - trajectory_msgs::msg::JointTrajectoryPoint get_current_state_when_offset() + trajectory_msgs::msg::JointTrajectoryPoint get_current_state_when_offset() const { return last_commanded_state_; } - bool has_position_state_interface() { return has_position_state_interface_; } + bool has_position_state_interface() const { return has_position_state_interface_; } - bool has_velocity_state_interface() { return has_velocity_state_interface_; } + bool has_velocity_state_interface() const { return has_velocity_state_interface_; } - bool has_acceleration_state_interface() { return has_acceleration_state_interface_; } + bool has_acceleration_state_interface() const { return has_acceleration_state_interface_; } - bool has_position_command_interface() { return has_position_command_interface_; } + bool has_position_command_interface() const { return has_position_command_interface_; } - bool has_velocity_command_interface() { return has_velocity_command_interface_; } + bool has_velocity_command_interface() const { return has_velocity_command_interface_; } - bool has_acceleration_command_interface() { return has_acceleration_command_interface_; } + bool has_acceleration_command_interface() const { return has_acceleration_command_interface_; } - bool has_effort_command_interface() { return has_effort_command_interface_; } + bool has_effort_command_interface() const { return has_effort_command_interface_; } - bool use_closed_loop_pid_adapter() { return use_closed_loop_pid_adapter_; } + bool use_closed_loop_pid_adapter() const { return use_closed_loop_pid_adapter_; } - bool is_open_loop() { return params_.open_loop_control; } + bool is_open_loop() const { return params_.open_loop_control; } - bool has_active_traj() { return has_active_trajectory(); } + bool has_active_traj() const { return has_active_trajectory(); } - bool has_trivial_traj() + bool has_trivial_traj() const { return has_active_trajectory() && traj_external_point_ptr_->has_nontrivial_msg() == false; } From be366452e15f27bba73f7f44719c97ee1ddd1f56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Wed, 16 Aug 2023 17:01:34 +0200 Subject: [PATCH 097/238] [JTC] Tolerance tests + Hold on time violation (#613) * Add new test to ensure that controller goes into position holding when tolerances are violated * Hold position if goal_time is exceeded with topic interface * Fix hold on time-violation --- .../src/joint_trajectory_controller.cpp | 14 ++++- .../test/test_trajectory_controller.cpp | 61 +++++++++++++++++++ 2 files changed, 72 insertions(+), 3 deletions(-) diff --git a/joint_trajectory_controller/src/joint_trajectory_controller.cpp b/joint_trajectory_controller/src/joint_trajectory_controller.cpp index 9c5ee68132..92b3b5af8d 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller.cpp +++ b/joint_trajectory_controller/src/joint_trajectory_controller.cpp @@ -362,19 +362,27 @@ controller_interface::return_type JointTrajectoryController::update( traj_msg_external_point_ptr_.reset(); traj_msg_external_point_ptr_.initRT(set_hold_position()); } - // else, run another cycle while waiting for outside_goal_tolerance - // to be satisfied or violated within the goal_time_tolerance } } else if (tolerance_violated_while_moving && *(rt_has_pending_goal_.readFromRT()) == false) { // we need to ensure that there is no pending goal -> we get a race condition otherwise - RCLCPP_ERROR(get_node()->get_logger(), "Holding position due to state tolerance violation"); traj_msg_external_point_ptr_.reset(); traj_msg_external_point_ptr_.initRT(set_hold_position()); } + else if ( + !before_last_point && !within_goal_time && *(rt_has_pending_goal_.readFromRT()) == false) + { + RCLCPP_ERROR(get_node()->get_logger(), "Exceeded goal_time_tolerance: holding position..."); + + traj_msg_external_point_ptr_.reset(); + traj_msg_external_point_ptr_.initRT(set_hold_position()); + } + // else, run another cycle while waiting for outside_goal_tolerance + // to be satisfied (will stay in this state until new message arrives) + // or outside_goal_tolerance violated within the goal_time_tolerance } } diff --git a/joint_trajectory_controller/test/test_trajectory_controller.cpp b/joint_trajectory_controller/test/test_trajectory_controller.cpp index 4149058c77..7850f15183 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller.cpp +++ b/joint_trajectory_controller/test/test_trajectory_controller.cpp @@ -1567,6 +1567,67 @@ TEST_P(TrajectoryControllerTestParameterized, test_hw_states_has_offset_later_co executor.cancel(); } +TEST_P(TrajectoryControllerTestParameterized, test_state_tolerances_fail) +{ + // set joint tolerance parameters + const double state_tol = 0.0001; + std::vector params = { + rclcpp::Parameter("constraints.joint1.trajectory", state_tol), + rclcpp::Parameter("constraints.joint2.trajectory", state_tol), + rclcpp::Parameter("constraints.joint3.trajectory", state_tol)}; + + rclcpp::executors::MultiThreadedExecutor executor; + SetUpAndActivateTrajectoryController(executor, false, {params}, true); + + // send msg + constexpr auto FIRST_POINT_TIME = std::chrono::milliseconds(100); + builtin_interfaces::msg::Duration time_from_start{rclcpp::Duration(FIRST_POINT_TIME)}; + // *INDENT-OFF* + std::vector> points{ + {{3.3, 4.4, 5.5}}, {{7.7, 8.8, 9.9}}, {{10.10, 11.11, 12.12}}}; + std::vector> points_velocities{ + {{0.01, 0.01, 0.01}}, {{0.05, 0.05, 0.05}}, {{0.06, 0.06, 0.06}}}; + // *INDENT-ON* + publish(time_from_start, points, rclcpp::Time(0, 0, RCL_STEADY_TIME), {}, points_velocities); + traj_controller_->wait_for_trajectory(executor); + updateController(rclcpp::Duration(FIRST_POINT_TIME)); + + // it should have aborted and be holding now + expectHoldingPoint(joint_state_pos_); +} + +TEST_P(TrajectoryControllerTestParameterized, test_goal_tolerances_fail) +{ + // set joint tolerance parameters + const double goal_tol = 0.1; + // set very small goal_time so that goal_time is violated + const double goal_time = 0.000001; + std::vector params = { + rclcpp::Parameter("constraints.joint1.goal", goal_tol), + rclcpp::Parameter("constraints.joint2.goal", goal_tol), + rclcpp::Parameter("constraints.joint3.goal", goal_tol), + rclcpp::Parameter("constraints.goal_time", goal_time)}; + + rclcpp::executors::MultiThreadedExecutor executor; + SetUpAndActivateTrajectoryController(executor, false, {params}, true); + + // send msg + constexpr auto FIRST_POINT_TIME = std::chrono::milliseconds(100); + builtin_interfaces::msg::Duration time_from_start{rclcpp::Duration(FIRST_POINT_TIME)}; + // *INDENT-OFF* + std::vector> points{ + {{3.3, 4.4, 5.5}}, {{7.7, 8.8, 9.9}}, {{10.10, 11.11, 12.12}}}; + std::vector> points_velocities{ + {{0.01, 0.01, 0.01}}, {{0.05, 0.05, 0.05}}, {{0.06, 0.06, 0.06}}}; + // *INDENT-ON* + publish(time_from_start, points, rclcpp::Time(0, 0, RCL_STEADY_TIME), {}, points_velocities); + traj_controller_->wait_for_trajectory(executor); + updateController(rclcpp::Duration(4 * FIRST_POINT_TIME)); + + // it should have aborted and be holding now + expectHoldingPoint(joint_state_pos_); +} + // position controllers INSTANTIATE_TEST_SUITE_P( PositionTrajectoryControllers, TrajectoryControllerTestParameterized, From bf9b7e802ca4005ca4a9927941b550f0853eab89 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Wed, 16 Aug 2023 17:54:35 +0100 Subject: [PATCH 098/238] Update changelogs --- ackermann_steering_controller/CHANGELOG.rst | 3 +++ admittance_controller/CHANGELOG.rst | 3 +++ bicycle_steering_controller/CHANGELOG.rst | 3 +++ diff_drive_controller/CHANGELOG.rst | 3 +++ effort_controllers/CHANGELOG.rst | 3 +++ force_torque_sensor_broadcaster/CHANGELOG.rst | 3 +++ forward_command_controller/CHANGELOG.rst | 5 +++++ gripper_controllers/CHANGELOG.rst | 3 +++ imu_sensor_broadcaster/CHANGELOG.rst | 3 +++ joint_state_broadcaster/CHANGELOG.rst | 3 +++ joint_trajectory_controller/CHANGELOG.rst | 11 +++++++++++ position_controllers/CHANGELOG.rst | 3 +++ ros2_controllers/CHANGELOG.rst | 3 +++ ros2_controllers_test_nodes/CHANGELOG.rst | 3 +++ rqt_joint_trajectory_controller/CHANGELOG.rst | 3 +++ steering_controllers_library/CHANGELOG.rst | 3 +++ tricycle_controller/CHANGELOG.rst | 3 +++ tricycle_steering_controller/CHANGELOG.rst | 3 +++ velocity_controllers/CHANGELOG.rst | 3 +++ 19 files changed, 67 insertions(+) diff --git a/ackermann_steering_controller/CHANGELOG.rst b/ackermann_steering_controller/CHANGELOG.rst index b4c1815bdc..377cdbd996 100644 --- a/ackermann_steering_controller/CHANGELOG.rst +++ b/ackermann_steering_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ackermann_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.13.0 (2023-08-04) ------------------- diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index 5f85999abd..622b740832 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.13.0 (2023-08-04) ------------------- * Fix out of bound access in admittance controller (`#721 `_) diff --git a/bicycle_steering_controller/CHANGELOG.rst b/bicycle_steering_controller/CHANGELOG.rst index e100f537f6..7b0b59004c 100644 --- a/bicycle_steering_controller/CHANGELOG.rst +++ b/bicycle_steering_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package bicycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.13.0 (2023-08-04) ------------------- diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index 7fdcf063e2..60491ee06a 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.13.0 (2023-08-04) ------------------- * [DiffDriveController] Optional tf namespace prefixes instead of using node namespace (`#533 `_) diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index 4b223619e0..de743ce39b 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.13.0 (2023-08-04) ------------------- diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index d9c0f2de24..04551f4d8a 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.13.0 (2023-08-04) ------------------- diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index 324eead77a..538d974f6b 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Use tabs (`#743 `_) +* Contributors: Christoph Fröhlich + 3.13.0 (2023-08-04) ------------------- diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index 506aaa48ec..2187613b1f 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.13.0 (2023-08-04) ------------------- diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index ef997c8733..3616493072 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.13.0 (2023-08-04) ------------------- diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index 9a5c4efc30..f4d6c40c2e 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.13.0 (2023-08-04) ------------------- diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index e2b1c6f613..283cdac64d 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,17 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* [JTC] Tolerance tests + Hold on time violation (`#613 `_) + * Add new test to ensure that controller goes into position holding when tolerances are violated + * Hold position if goal_time is exceeded with topic interface + * Fix hold on time-violation +* [JTC] Fix typos, implicit cast, const member functions (`#748 `_) +* Remove wrong description (`#742 `_) +* [JTC] Explicitly set hold position (`#558 `_) +* Contributors: Christoph Fröhlich + 3.13.0 (2023-08-04) ------------------- * Small improvement in remapping (`#393 `_) diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index 15242a2018..c9a11310e9 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.13.0 (2023-08-04) ------------------- diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index 04ed272d86..a1a91ccbb4 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.13.0 (2023-08-04) ------------------- diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index d84a55f26a..08ce2bf191 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.13.0 (2023-08-04) ------------------- diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index 3683d03c16..47735b98ce 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.13.0 (2023-08-04) ------------------- diff --git a/steering_controllers_library/CHANGELOG.rst b/steering_controllers_library/CHANGELOG.rst index 5bf04ede76..094e3c77a6 100644 --- a/steering_controllers_library/CHANGELOG.rst +++ b/steering_controllers_library/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package steering_controllers_library ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.13.0 (2023-08-04) ------------------- * Update ci-ros-lint.yml and copyright format (`#720 `_) diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index a40f09e557..f5d801cfe5 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.13.0 (2023-08-04) ------------------- diff --git a/tricycle_steering_controller/CHANGELOG.rst b/tricycle_steering_controller/CHANGELOG.rst index 8d3c61ff6b..f4252616f5 100644 --- a/tricycle_steering_controller/CHANGELOG.rst +++ b/tricycle_steering_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package tricycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.13.0 (2023-08-04) ------------------- diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index b9fe5f9553..23875e9ec4 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.13.0 (2023-08-04) ------------------- From 102c1cf698acd80b10c00e19a901a82e066358d4 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Wed, 16 Aug 2023 17:54:55 +0100 Subject: [PATCH 099/238] 3.14.0 --- ackermann_steering_controller/CHANGELOG.rst | 4 ++-- ackermann_steering_controller/package.xml | 2 +- admittance_controller/CHANGELOG.rst | 4 ++-- admittance_controller/package.xml | 2 +- bicycle_steering_controller/CHANGELOG.rst | 4 ++-- bicycle_steering_controller/package.xml | 2 +- diff_drive_controller/CHANGELOG.rst | 4 ++-- diff_drive_controller/package.xml | 2 +- effort_controllers/CHANGELOG.rst | 4 ++-- effort_controllers/package.xml | 2 +- force_torque_sensor_broadcaster/CHANGELOG.rst | 4 ++-- force_torque_sensor_broadcaster/package.xml | 2 +- forward_command_controller/CHANGELOG.rst | 4 ++-- forward_command_controller/package.xml | 2 +- gripper_controllers/CHANGELOG.rst | 4 ++-- gripper_controllers/package.xml | 2 +- imu_sensor_broadcaster/CHANGELOG.rst | 4 ++-- imu_sensor_broadcaster/package.xml | 2 +- joint_state_broadcaster/CHANGELOG.rst | 4 ++-- joint_state_broadcaster/package.xml | 2 +- joint_trajectory_controller/CHANGELOG.rst | 4 ++-- joint_trajectory_controller/package.xml | 2 +- position_controllers/CHANGELOG.rst | 4 ++-- position_controllers/package.xml | 2 +- ros2_controllers/CHANGELOG.rst | 4 ++-- ros2_controllers/package.xml | 2 +- ros2_controllers_test_nodes/CHANGELOG.rst | 4 ++-- ros2_controllers_test_nodes/package.xml | 2 +- ros2_controllers_test_nodes/setup.py | 2 +- rqt_joint_trajectory_controller/CHANGELOG.rst | 4 ++-- rqt_joint_trajectory_controller/package.xml | 2 +- rqt_joint_trajectory_controller/setup.py | 2 +- steering_controllers_library/CHANGELOG.rst | 4 ++-- steering_controllers_library/package.xml | 2 +- tricycle_controller/CHANGELOG.rst | 4 ++-- tricycle_controller/package.xml | 2 +- tricycle_steering_controller/CHANGELOG.rst | 4 ++-- tricycle_steering_controller/package.xml | 2 +- velocity_controllers/CHANGELOG.rst | 4 ++-- velocity_controllers/package.xml | 2 +- 40 files changed, 59 insertions(+), 59 deletions(-) diff --git a/ackermann_steering_controller/CHANGELOG.rst b/ackermann_steering_controller/CHANGELOG.rst index 377cdbd996..cad245cc4e 100644 --- a/ackermann_steering_controller/CHANGELOG.rst +++ b/ackermann_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ackermann_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.14.0 (2023-08-16) +------------------- 3.13.0 (2023-08-04) ------------------- diff --git a/ackermann_steering_controller/package.xml b/ackermann_steering_controller/package.xml index d4c6b3b3b4..1301b19bc9 100644 --- a/ackermann_steering_controller/package.xml +++ b/ackermann_steering_controller/package.xml @@ -2,7 +2,7 @@ ackermann_steering_controller - 3.13.0 + 3.14.0 Steering controller for Ackermann kinematics. Rear fixed wheels are powering the vehicle and front wheels are steering it. Apache License 2.0 Bence Magyar diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index 622b740832..79c80f357e 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.14.0 (2023-08-16) +------------------- 3.13.0 (2023-08-04) ------------------- diff --git a/admittance_controller/package.xml b/admittance_controller/package.xml index 966c268d93..4ea34b3852 100644 --- a/admittance_controller/package.xml +++ b/admittance_controller/package.xml @@ -2,7 +2,7 @@ admittance_controller - 3.13.0 + 3.14.0 Implementation of admittance controllers for different input and output interface. Denis Štogl Bence Magyar diff --git a/bicycle_steering_controller/CHANGELOG.rst b/bicycle_steering_controller/CHANGELOG.rst index 7b0b59004c..0569a0fe8d 100644 --- a/bicycle_steering_controller/CHANGELOG.rst +++ b/bicycle_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package bicycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.14.0 (2023-08-16) +------------------- 3.13.0 (2023-08-04) ------------------- diff --git a/bicycle_steering_controller/package.xml b/bicycle_steering_controller/package.xml index 42693418f6..1b9844a090 100644 --- a/bicycle_steering_controller/package.xml +++ b/bicycle_steering_controller/package.xml @@ -2,7 +2,7 @@ bicycle_steering_controller - 3.13.0 + 3.14.0 Steering controller with bicycle kinematics. Rear fixed wheel is powering the vehicle and front wheel is steering. Apache License 2.0 Bence Magyar diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index 60491ee06a..e12543aa85 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.14.0 (2023-08-16) +------------------- 3.13.0 (2023-08-04) ------------------- diff --git a/diff_drive_controller/package.xml b/diff_drive_controller/package.xml index 80d3f6334e..df4d92a19b 100644 --- a/diff_drive_controller/package.xml +++ b/diff_drive_controller/package.xml @@ -1,7 +1,7 @@ diff_drive_controller - 3.13.0 + 3.14.0 Controller for a differential drive mobile base. Bence Magyar Jordan Palacios diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index de743ce39b..adc12b0caf 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.14.0 (2023-08-16) +------------------- 3.13.0 (2023-08-04) ------------------- diff --git a/effort_controllers/package.xml b/effort_controllers/package.xml index 852cf77829..6edbd5454a 100644 --- a/effort_controllers/package.xml +++ b/effort_controllers/package.xml @@ -1,7 +1,7 @@ effort_controllers - 3.13.0 + 3.14.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index 04551f4d8a..6ae71de6a6 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.14.0 (2023-08-16) +------------------- 3.13.0 (2023-08-04) ------------------- diff --git a/force_torque_sensor_broadcaster/package.xml b/force_torque_sensor_broadcaster/package.xml index b2c04e6a57..3907edbd31 100644 --- a/force_torque_sensor_broadcaster/package.xml +++ b/force_torque_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ force_torque_sensor_broadcaster - 3.13.0 + 3.14.0 Controller to publish state of force-torque sensors. Bence Magyar Denis Štogl diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index 538d974f6b..35ad79d4f2 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.14.0 (2023-08-16) +------------------- * Use tabs (`#743 `_) * Contributors: Christoph Fröhlich diff --git a/forward_command_controller/package.xml b/forward_command_controller/package.xml index 25895a4696..522964019b 100644 --- a/forward_command_controller/package.xml +++ b/forward_command_controller/package.xml @@ -1,7 +1,7 @@ forward_command_controller - 3.13.0 + 3.14.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index 2187613b1f..28e73faf8c 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.14.0 (2023-08-16) +------------------- 3.13.0 (2023-08-04) ------------------- diff --git a/gripper_controllers/package.xml b/gripper_controllers/package.xml index c977a0ed36..5804d3919b 100644 --- a/gripper_controllers/package.xml +++ b/gripper_controllers/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> gripper_controllers - 3.13.0 + 3.14.0 The gripper_controllers package Bence Magyar diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index 3616493072..9443ee51c2 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.14.0 (2023-08-16) +------------------- 3.13.0 (2023-08-04) ------------------- diff --git a/imu_sensor_broadcaster/package.xml b/imu_sensor_broadcaster/package.xml index 41c087f3ca..8d26b48211 100644 --- a/imu_sensor_broadcaster/package.xml +++ b/imu_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ imu_sensor_broadcaster - 3.13.0 + 3.14.0 Controller to publish readings of IMU sensors. Bence Magyar Denis Štogl diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index f4d6c40c2e..9ebf7177ba 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.14.0 (2023-08-16) +------------------- 3.13.0 (2023-08-04) ------------------- diff --git a/joint_state_broadcaster/package.xml b/joint_state_broadcaster/package.xml index fd5deab3e7..919bac78f8 100644 --- a/joint_state_broadcaster/package.xml +++ b/joint_state_broadcaster/package.xml @@ -1,7 +1,7 @@ joint_state_broadcaster - 3.13.0 + 3.14.0 Broadcaster to publish joint state Bence Magyar Denis Stogl diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index 283cdac64d..88df65577c 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.14.0 (2023-08-16) +------------------- * [JTC] Tolerance tests + Hold on time violation (`#613 `_) * Add new test to ensure that controller goes into position holding when tolerances are violated * Hold position if goal_time is exceeded with topic interface diff --git a/joint_trajectory_controller/package.xml b/joint_trajectory_controller/package.xml index 08a5392977..2941e11a56 100644 --- a/joint_trajectory_controller/package.xml +++ b/joint_trajectory_controller/package.xml @@ -1,7 +1,7 @@ joint_trajectory_controller - 3.13.0 + 3.14.0 Controller for executing joint-space trajectories on a group of joints Bence Magyar Jordan Palacios diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index c9a11310e9..7dcb2aadaa 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.14.0 (2023-08-16) +------------------- 3.13.0 (2023-08-04) ------------------- diff --git a/position_controllers/package.xml b/position_controllers/package.xml index 1259239ac5..c88fc6ddc7 100644 --- a/position_controllers/package.xml +++ b/position_controllers/package.xml @@ -1,7 +1,7 @@ position_controllers - 3.13.0 + 3.14.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index a1a91ccbb4..b1758acc83 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.14.0 (2023-08-16) +------------------- 3.13.0 (2023-08-04) ------------------- diff --git a/ros2_controllers/package.xml b/ros2_controllers/package.xml index 560ea5df88..ca4a031da6 100644 --- a/ros2_controllers/package.xml +++ b/ros2_controllers/package.xml @@ -1,7 +1,7 @@ ros2_controllers - 3.13.0 + 3.14.0 Metapackage for ROS2 controllers related packages Bence Magyar Jordan Palacios diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index 08ce2bf191..3c92dbdb61 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.14.0 (2023-08-16) +------------------- 3.13.0 (2023-08-04) ------------------- diff --git a/ros2_controllers_test_nodes/package.xml b/ros2_controllers_test_nodes/package.xml index 02af7f67b8..f5b887b01d 100644 --- a/ros2_controllers_test_nodes/package.xml +++ b/ros2_controllers_test_nodes/package.xml @@ -2,7 +2,7 @@ ros2_controllers_test_nodes - 3.13.0 + 3.14.0 Demo nodes for showing and testing functionalities of the ros2_control framework. Denis Štogl diff --git a/ros2_controllers_test_nodes/setup.py b/ros2_controllers_test_nodes/setup.py index 6aceaa2cc2..2e1336e543 100644 --- a/ros2_controllers_test_nodes/setup.py +++ b/ros2_controllers_test_nodes/setup.py @@ -20,7 +20,7 @@ setup( name=package_name, - version="3.13.0", + version="3.14.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index 47735b98ce..d931108078 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.14.0 (2023-08-16) +------------------- 3.13.0 (2023-08-04) ------------------- diff --git a/rqt_joint_trajectory_controller/package.xml b/rqt_joint_trajectory_controller/package.xml index c2541f3a96..122b55116b 100644 --- a/rqt_joint_trajectory_controller/package.xml +++ b/rqt_joint_trajectory_controller/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> rqt_joint_trajectory_controller - 3.13.0 + 3.14.0 Graphical frontend for interacting with joint_trajectory_controller instances. Bence Magyar diff --git a/rqt_joint_trajectory_controller/setup.py b/rqt_joint_trajectory_controller/setup.py index 701c285e61..168d929a1c 100644 --- a/rqt_joint_trajectory_controller/setup.py +++ b/rqt_joint_trajectory_controller/setup.py @@ -7,7 +7,7 @@ setup( name=package_name, - version="3.13.0", + version="3.14.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/steering_controllers_library/CHANGELOG.rst b/steering_controllers_library/CHANGELOG.rst index 094e3c77a6..033fddb95a 100644 --- a/steering_controllers_library/CHANGELOG.rst +++ b/steering_controllers_library/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package steering_controllers_library ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.14.0 (2023-08-16) +------------------- 3.13.0 (2023-08-04) ------------------- diff --git a/steering_controllers_library/package.xml b/steering_controllers_library/package.xml index 1da3cfa9df..302b1cbd90 100644 --- a/steering_controllers_library/package.xml +++ b/steering_controllers_library/package.xml @@ -2,7 +2,7 @@ steering_controllers_library - 3.13.0 + 3.14.0 Package for steering robot configurations including odometry and interfaces. Apache License 2.0 Bence Magyar diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index f5d801cfe5..df31f03c74 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.14.0 (2023-08-16) +------------------- 3.13.0 (2023-08-04) ------------------- diff --git a/tricycle_controller/package.xml b/tricycle_controller/package.xml index 9cc16d3b60..d8e1b0e6e8 100644 --- a/tricycle_controller/package.xml +++ b/tricycle_controller/package.xml @@ -2,7 +2,7 @@ tricycle_controller - 3.13.0 + 3.14.0 Controller for a tricycle drive mobile base Bence Magyar Tony Najjar diff --git a/tricycle_steering_controller/CHANGELOG.rst b/tricycle_steering_controller/CHANGELOG.rst index f4252616f5..8fc50f7378 100644 --- a/tricycle_steering_controller/CHANGELOG.rst +++ b/tricycle_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package tricycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.14.0 (2023-08-16) +------------------- 3.13.0 (2023-08-04) ------------------- diff --git a/tricycle_steering_controller/package.xml b/tricycle_steering_controller/package.xml index 26083760d1..972300f590 100644 --- a/tricycle_steering_controller/package.xml +++ b/tricycle_steering_controller/package.xml @@ -2,7 +2,7 @@ tricycle_steering_controller - 3.13.0 + 3.14.0 Steering controller with tricycle kinematics. Rear fixed wheels are powering the vehicle and front wheel is steering. Apache License 2.0 Bence Magyar diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index 23875e9ec4..49b945c3dc 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.14.0 (2023-08-16) +------------------- 3.13.0 (2023-08-04) ------------------- diff --git a/velocity_controllers/package.xml b/velocity_controllers/package.xml index 3551021f82..e626c9849a 100644 --- a/velocity_controllers/package.xml +++ b/velocity_controllers/package.xml @@ -1,7 +1,7 @@ velocity_controllers - 3.13.0 + 3.14.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios From 32aaef7552638826aba0b3f3a72b1c1453739afa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noel=20Jim=C3=A9nez=20Garc=C3=ADa?= Date: Fri, 18 Aug 2023 22:44:30 +0200 Subject: [PATCH 100/238] [ForceTorqueSensorBroadcaster] Create ParamListener and get parameters on configure (#698) * Create ParamListener and get parameters on configure * Declare parameters for test_force_torque_sensor_broadcaster Since the parameters are not declared on init anymore, they cannot be set without declaring them before --------- Co-authored-by: Bence Magyar --- .../src/force_torque_sensor_broadcaster.cpp | 16 ++--- .../test_force_torque_sensor_broadcaster.cpp | 67 ++++++++++--------- 2 files changed, 44 insertions(+), 39 deletions(-) diff --git a/force_torque_sensor_broadcaster/src/force_torque_sensor_broadcaster.cpp b/force_torque_sensor_broadcaster/src/force_torque_sensor_broadcaster.cpp index 9b570d353f..e9a173380b 100644 --- a/force_torque_sensor_broadcaster/src/force_torque_sensor_broadcaster.cpp +++ b/force_torque_sensor_broadcaster/src/force_torque_sensor_broadcaster.cpp @@ -29,6 +29,12 @@ ForceTorqueSensorBroadcaster::ForceTorqueSensorBroadcaster() } controller_interface::CallbackReturn ForceTorqueSensorBroadcaster::on_init() +{ + return controller_interface::CallbackReturn::SUCCESS; +} + +controller_interface::CallbackReturn ForceTorqueSensorBroadcaster::on_configure( + const rclcpp_lifecycle::State & /*previous_state*/) { try { @@ -37,18 +43,10 @@ controller_interface::CallbackReturn ForceTorqueSensorBroadcaster::on_init() } catch (const std::exception & e) { - fprintf(stderr, "Exception thrown during init stage with message: %s \n", e.what()); + fprintf(stderr, "Exception thrown during configure stage with message: %s \n", e.what()); return controller_interface::CallbackReturn::ERROR; } - return controller_interface::CallbackReturn::SUCCESS; -} - -controller_interface::CallbackReturn ForceTorqueSensorBroadcaster::on_configure( - const rclcpp_lifecycle::State & /*previous_state*/) -{ - params_ = param_listener_->get_params(); - const bool no_interface_names_defined = params_.interface_names.force.x.empty() && params_.interface_names.force.y.empty() && params_.interface_names.force.z.empty() && params_.interface_names.torque.x.empty() && diff --git a/force_torque_sensor_broadcaster/test/test_force_torque_sensor_broadcaster.cpp b/force_torque_sensor_broadcaster/test/test_force_torque_sensor_broadcaster.cpp index b88266712b..57650c9302 100644 --- a/force_torque_sensor_broadcaster/test/test_force_torque_sensor_broadcaster.cpp +++ b/force_torque_sensor_broadcaster/test/test_force_torque_sensor_broadcaster.cpp @@ -111,11 +111,12 @@ TEST_F(ForceTorqueSensorBroadcasterTest, SensorName_InterfaceNames_Set) SetUpFTSBroadcaster(); // set the 'sensor_name' - fts_broadcaster_->get_node()->set_parameter({"sensor_name", sensor_name_}); + fts_broadcaster_->get_node()->declare_parameter("sensor_name", sensor_name_); // set the 'interface_names' - fts_broadcaster_->get_node()->set_parameter({"interface_names.force.x", "fts_sensor/force.x"}); - fts_broadcaster_->get_node()->set_parameter({"interface_names.torque.z", "fts_sensor/torque.z"}); + fts_broadcaster_->get_node()->declare_parameter("interface_names.force.x", "fts_sensor/force.x"); + fts_broadcaster_->get_node()->declare_parameter( + "interface_names.torque.z", "fts_sensor/torque.z"); // configure failed, both 'sensor_name' and 'interface_names' supplied ASSERT_EQ(fts_broadcaster_->on_configure(rclcpp_lifecycle::State()), NODE_ERROR); @@ -126,7 +127,7 @@ TEST_F(ForceTorqueSensorBroadcasterTest, SensorName_IsEmpty_InterfaceNames_NotSe SetUpFTSBroadcaster(); // set the 'sensor_name' empty - fts_broadcaster_->get_node()->set_parameter({"sensor_name", ""}); + fts_broadcaster_->get_node()->declare_parameter("sensor_name", ""); // configure failed, 'sensor_name' parameter empty ASSERT_EQ(fts_broadcaster_->on_configure(rclcpp_lifecycle::State()), NODE_ERROR); @@ -137,8 +138,8 @@ TEST_F(ForceTorqueSensorBroadcasterTest, InterfaceNames_IsEmpty_SensorName_NotSe SetUpFTSBroadcaster(); // set the 'interface_names' empty - fts_broadcaster_->get_node()->set_parameter({"interface_names.force.x", ""}); - fts_broadcaster_->get_node()->set_parameter({"interface_names.torque.z", ""}); + fts_broadcaster_->get_node()->declare_parameter("interface_names.force.x", ""); + fts_broadcaster_->get_node()->declare_parameter("interface_names.torque.z", ""); // configure failed, 'interface_name' parameter empty ASSERT_EQ(fts_broadcaster_->on_configure(rclcpp_lifecycle::State()), NODE_ERROR); @@ -149,10 +150,10 @@ TEST_F(ForceTorqueSensorBroadcasterTest, SensorName_Configure_Success) SetUpFTSBroadcaster(); // set the 'sensor_name' - fts_broadcaster_->get_node()->set_parameter({"sensor_name", sensor_name_}); + fts_broadcaster_->get_node()->declare_parameter("sensor_name", sensor_name_); // set the 'frame_id' - fts_broadcaster_->get_node()->set_parameter({"frame_id", frame_id_}); + fts_broadcaster_->get_node()->declare_parameter("frame_id", frame_id_); // configure passed ASSERT_EQ(fts_broadcaster_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); @@ -163,11 +164,12 @@ TEST_F(ForceTorqueSensorBroadcasterTest, InterfaceNames_Configure_Success) SetUpFTSBroadcaster(); // set the 'interface_names' - fts_broadcaster_->get_node()->set_parameter({"interface_names.force.x", "fts_sensor/force.x"}); - fts_broadcaster_->get_node()->set_parameter({"interface_names.torque.z", "fts_sensor/torque.z"}); + fts_broadcaster_->get_node()->declare_parameter("interface_names.force.x", "fts_sensor/force.x"); + fts_broadcaster_->get_node()->declare_parameter( + "interface_names.torque.z", "fts_sensor/torque.z"); // set the 'frame_id' - fts_broadcaster_->get_node()->set_parameter({"frame_id", frame_id_}); + fts_broadcaster_->get_node()->declare_parameter("frame_id", frame_id_); // configure passed ASSERT_EQ(fts_broadcaster_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); @@ -178,8 +180,8 @@ TEST_F(ForceTorqueSensorBroadcasterTest, SensorName_Activate_Success) SetUpFTSBroadcaster(); // set the params 'sensor_name' and 'frame_id' - fts_broadcaster_->get_node()->set_parameter({"sensor_name", sensor_name_}); - fts_broadcaster_->get_node()->set_parameter({"frame_id", frame_id_}); + fts_broadcaster_->get_node()->declare_parameter("sensor_name", sensor_name_); + fts_broadcaster_->get_node()->declare_parameter("frame_id", frame_id_); // configure and activate success ASSERT_EQ(fts_broadcaster_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); @@ -191,8 +193,8 @@ TEST_F(ForceTorqueSensorBroadcasterTest, SensorName_Update_Success) SetUpFTSBroadcaster(); // set the params 'sensor_name' and 'frame_id' - fts_broadcaster_->get_node()->set_parameter({"sensor_name", sensor_name_}); - fts_broadcaster_->get_node()->set_parameter({"frame_id", frame_id_}); + fts_broadcaster_->get_node()->declare_parameter("sensor_name", sensor_name_); + fts_broadcaster_->get_node()->declare_parameter("frame_id", frame_id_); ASSERT_EQ(fts_broadcaster_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); ASSERT_EQ(fts_broadcaster_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); @@ -207,9 +209,10 @@ TEST_F(ForceTorqueSensorBroadcasterTest, InterfaceNames_Success) SetUpFTSBroadcaster(); // set the params 'interface_names' and 'frame_id' - fts_broadcaster_->get_node()->set_parameter({"interface_names.force.x", "fts_sensor/force.x"}); - fts_broadcaster_->get_node()->set_parameter({"interface_names.torque.z", "fts_sensor/torque.z"}); - fts_broadcaster_->get_node()->set_parameter({"frame_id", frame_id_}); + fts_broadcaster_->get_node()->declare_parameter("interface_names.force.x", "fts_sensor/force.x"); + fts_broadcaster_->get_node()->declare_parameter( + "interface_names.torque.z", "fts_sensor/torque.z"); + fts_broadcaster_->get_node()->declare_parameter("frame_id", frame_id_); ASSERT_EQ(fts_broadcaster_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); ASSERT_EQ(fts_broadcaster_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); @@ -223,8 +226,8 @@ TEST_F(ForceTorqueSensorBroadcasterTest, SensorName_Publish_Success) SetUpFTSBroadcaster(); // set the params 'sensor_name' and 'frame_id' - fts_broadcaster_->get_node()->set_parameter({"sensor_name", sensor_name_}); - fts_broadcaster_->get_node()->set_parameter({"frame_id", frame_id_}); + fts_broadcaster_->get_node()->declare_parameter("sensor_name", sensor_name_); + fts_broadcaster_->get_node()->declare_parameter("frame_id", frame_id_); ASSERT_EQ(fts_broadcaster_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); ASSERT_EQ(fts_broadcaster_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); @@ -246,9 +249,10 @@ TEST_F(ForceTorqueSensorBroadcasterTest, InterfaceNames_Publish_Success) SetUpFTSBroadcaster(); // set the params 'interface_names' and 'frame_id' - fts_broadcaster_->get_node()->set_parameter({"interface_names.force.x", "fts_sensor/force.x"}); - fts_broadcaster_->get_node()->set_parameter({"interface_names.torque.z", "fts_sensor/torque.z"}); - fts_broadcaster_->get_node()->set_parameter({"frame_id", frame_id_}); + fts_broadcaster_->get_node()->declare_parameter("interface_names.force.x", "fts_sensor/force.x"); + fts_broadcaster_->get_node()->declare_parameter( + "interface_names.torque.z", "fts_sensor/torque.z"); + fts_broadcaster_->get_node()->declare_parameter("frame_id", frame_id_); ASSERT_EQ(fts_broadcaster_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); ASSERT_EQ(fts_broadcaster_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); @@ -270,13 +274,16 @@ TEST_F(ForceTorqueSensorBroadcasterTest, All_InterfaceNames_Publish_Success) SetUpFTSBroadcaster(); // set all the params 'interface_names' and 'frame_id' - fts_broadcaster_->get_node()->set_parameter({"interface_names.force.x", "fts_sensor/force.x"}); - fts_broadcaster_->get_node()->set_parameter({"interface_names.force.y", "fts_sensor/force.y"}); - fts_broadcaster_->get_node()->set_parameter({"interface_names.force.z", "fts_sensor/force.z"}); - fts_broadcaster_->get_node()->set_parameter({"interface_names.torque.x", "fts_sensor/torque.x"}); - fts_broadcaster_->get_node()->set_parameter({"interface_names.torque.y", "fts_sensor/torque.y"}); - fts_broadcaster_->get_node()->set_parameter({"interface_names.torque.z", "fts_sensor/torque.z"}); - fts_broadcaster_->get_node()->set_parameter({"frame_id", frame_id_}); + fts_broadcaster_->get_node()->declare_parameter("interface_names.force.x", "fts_sensor/force.x"); + fts_broadcaster_->get_node()->declare_parameter("interface_names.force.y", "fts_sensor/force.y"); + fts_broadcaster_->get_node()->declare_parameter("interface_names.force.z", "fts_sensor/force.z"); + fts_broadcaster_->get_node()->declare_parameter( + "interface_names.torque.x", "fts_sensor/torque.x"); + fts_broadcaster_->get_node()->declare_parameter( + "interface_names.torque.y", "fts_sensor/torque.y"); + fts_broadcaster_->get_node()->declare_parameter( + "interface_names.torque.z", "fts_sensor/torque.z"); + fts_broadcaster_->get_node()->declare_parameter("frame_id", frame_id_); ASSERT_EQ(fts_broadcaster_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); ASSERT_EQ(fts_broadcaster_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); From 1dac309979fb9392dc12feb6b46555582fed6fc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Mon, 21 Aug 2023 14:39:00 +0200 Subject: [PATCH 101/238] Update docs for diff drive controller (#751) --- admittance_controller/doc/userdoc.rst | 2 +- diff_drive_controller/doc/userdoc.rst | 61 ++++++++++++--------------- doc/writing_new_controller.rst | 2 +- 3 files changed, 30 insertions(+), 35 deletions(-) diff --git a/admittance_controller/doc/userdoc.rst b/admittance_controller/doc/userdoc.rst index 152ed890dc..0e4469cd50 100644 --- a/admittance_controller/doc/userdoc.rst +++ b/admittance_controller/doc/userdoc.rst @@ -11,7 +11,7 @@ The controller implements ``ChainedControllerInterface``, so it is possible to a The controller requires an external kinematics plugin to function. The `kinematics_interface `_ repository provides an interface and an implementation that the admittance controller can use. -ROS2 interface of the controller +ROS 2 interface of the controller --------------------------------- Parameters diff --git a/diff_drive_controller/doc/userdoc.rst b/diff_drive_controller/doc/userdoc.rst index 6bd682af26..f8318bc4b8 100644 --- a/diff_drive_controller/doc/userdoc.rst +++ b/diff_drive_controller/doc/userdoc.rst @@ -6,71 +6,66 @@ diff_drive_controller ===================== Controller for mobile robots with differential drive. -Input for control are robot body velocity commands which are translated to wheel commands for the differential drive base. -Odometry is computed from hardware feedback and published. - -Velocity commands ------------------ -The controller works with a velocity twist from which it extracts the x component of the linear velocity and the z component of the angular velocity. Velocities on other components are ignored. +As input it takes velocity commands for the robot body, which are translated to wheel commands for the differential drive base. -Hardware interface type ------------------------ - -The controller works with wheel joints through a velocity interface. +Odometry is computed from hardware feedback and published. Other features -------------- - Realtime-safe implementation. - Odometry publishing - Task-space velocity, acceleration and jerk limits - Automatic stop after command time-out + + Realtime-safe implementation. + + Odometry publishing + + Task-space velocity, acceleration and jerk limits + + Automatic stop after command time-out -ros2_control Interfaces ------------------------- +Description of controller's interfaces +------------------------------------------------ References -,,,,,,,,,,, +,,,,,,,,,,,,,,,,,, +(the controller is not yet implemented as chainable controller) -States -,,,,,,, +Feedback +,,,,,,,,,,,,,, +As feedback interface type the joints' position (``hardware_interface::HW_IF_POSITION``) or velocity (``hardware_interface::HW_IF_VELOCITY``,if parameter ``position_feedback=false``) are used. -Commands +Output ,,,,,,,,, +Joints' velocity (``hardware_interface::HW_IF_VELOCITY``) are used. -ROS2 Interfaces ----------------- + +ROS 2 Interfaces +------------------------ Subscribers ,,,,,,,,,,,, + ~/cmd_vel [geometry_msgs/msg/TwistStamped] - Velocity command for the controller. + Velocity command for the controller, if ``use_stamped_vel=true``. The controller extracts the x component of the linear velocity and the z component of the angular velocity. Velocities on other components are ignored. ~/cmd_vel_unstamped [geometry_msgs::msg::Twist] - -~/cmd_vel_out [] - - + Velocity command for the controller, if ``use_stamped_vel=false``. The controller extracts the x component of the linear velocity and the z component of the angular velocity. Velocities on other components are ignored. Publishers ,,,,,,,,,,, -~/odom [] +~/odom [nav_msgs::msg::Odometry] + This represents an estimate of the robot's position and velocity in free space. -/tf +/tf [tf2_msgs::msg::TFMessage] + tf tree. Published only if ``enable_odom_tf=true`` - -Services -,,,,,,,,, +~/cmd_vel_out [geometry_msgs/msg/TwistStamped] + Velocity command for the controller, where limits were applied. Published only if ``publish_limited_velocity=true`` Parameters ------------- +,,,,,,,,,,,, Check `parameter definition file for details `_. diff --git a/doc/writing_new_controller.rst b/doc/writing_new_controller.rst index 1543e79722..0475f8f4fd 100644 --- a/doc/writing_new_controller.rst +++ b/doc/writing_new_controller.rst @@ -27,7 +27,7 @@ The following is a step-by-step guide to create source files, basic tests, and c 3. **Adding declarations into header file (.hpp)** - 1. Take care that you use header guards. ROS2-style is using ``#ifndef`` and ``#define`` preprocessor directives. (For more information on this, a search engine is your friend :) ). + 1. Take care that you use header guards. ROS 2-style is using ``#ifndef`` and ``#define`` preprocessor directives. (For more information on this, a search engine is your friend :) ). 2. include ``"controller_interface/controller_interface.hpp"`` and ``visibility_control.h`` if you are using one. From dcdbb94498260232038ccb7f1eee7373deddd39a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Sep 2023 09:27:36 +0200 Subject: [PATCH 102/238] Bump actions/checkout from 3 to 4 (#763) --- .github/workflows/ci-coverage-build.yml | 2 +- .github/workflows/ci-format.yml | 2 +- .github/workflows/ci-ros-lint.yml | 4 ++-- .github/workflows/humble-abi-compatibility.yml | 2 +- .github/workflows/humble-rhel-binary-build.yml | 2 +- .github/workflows/prerelease-check.yml | 2 +- .github/workflows/reusable-industrial-ci-with-cache.yml | 4 ++-- .github/workflows/reusable-ros-tooling-source-build.yml | 2 +- .github/workflows/reviewer_lottery.yml | 2 +- .github/workflows/rolling-abi-compatibility.yml | 2 +- .github/workflows/rolling-rhel-binary-build.yml | 2 +- 11 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ci-coverage-build.yml b/.github/workflows/ci-coverage-build.yml index 3d8a7431c0..cc5dd32596 100644 --- a/.github/workflows/ci-coverage-build.yml +++ b/.github/workflows/ci-coverage-build.yml @@ -19,7 +19,7 @@ jobs: - uses: ros-tooling/setup-ros@0.7.0 with: required-ros-distributions: ${{ env.ROS_DISTRO }} - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: ros-tooling/action-ros-ci@0.3.3 with: target-ros2-distro: ${{ env.ROS_DISTRO }} diff --git a/.github/workflows/ci-format.yml b/.github/workflows/ci-format.yml index 8955904bea..c868650adb 100644 --- a/.github/workflows/ci-format.yml +++ b/.github/workflows/ci-format.yml @@ -11,7 +11,7 @@ jobs: name: Format runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/setup-python@v4.7.0 with: python-version: '3.10' diff --git a/.github/workflows/ci-ros-lint.yml b/.github/workflows/ci-ros-lint.yml index 3d102b53a2..bfb6fd3386 100644 --- a/.github/workflows/ci-ros-lint.yml +++ b/.github/workflows/ci-ros-lint.yml @@ -13,7 +13,7 @@ jobs: env: AMENT_CPPCHECK_ALLOW_SLOW_VERSIONS: true steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: ros-tooling/setup-ros@0.7.0 - uses: ros-tooling/action-ros-lint@v0.1 with: @@ -49,7 +49,7 @@ jobs: matrix: linter: [cpplint] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: ros-tooling/setup-ros@master - uses: ros-tooling/action-ros-lint@master with: diff --git a/.github/workflows/humble-abi-compatibility.yml b/.github/workflows/humble-abi-compatibility.yml index 3f38d5b6ce..708ea5c1f4 100644 --- a/.github/workflows/humble-abi-compatibility.yml +++ b/.github/workflows/humble-abi-compatibility.yml @@ -11,7 +11,7 @@ jobs: abi_check: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: ros-industrial/industrial_ci@master env: ROS_DISTRO: humble diff --git a/.github/workflows/humble-rhel-binary-build.yml b/.github/workflows/humble-rhel-binary-build.yml index 2a4b627d5e..9da6059892 100644 --- a/.github/workflows/humble-rhel-binary-build.yml +++ b/.github/workflows/humble-rhel-binary-build.yml @@ -22,7 +22,7 @@ jobs: ROS_DISTRO: humble container: ghcr.io/ros-controls/ros:humble-rhel steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: path: src/ros2_controllers - run: | diff --git a/.github/workflows/prerelease-check.yml b/.github/workflows/prerelease-check.yml index 5e7326e510..856d877d85 100644 --- a/.github/workflows/prerelease-check.yml +++ b/.github/workflows/prerelease-check.yml @@ -24,7 +24,7 @@ jobs: pre_release: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: ${{ github.event.inputs.branch }} - name: industrial_ci diff --git a/.github/workflows/reusable-industrial-ci-with-cache.yml b/.github/workflows/reusable-industrial-ci-with-cache.yml index bca08ce5d2..acefeebfac 100644 --- a/.github/workflows/reusable-industrial-ci-with-cache.yml +++ b/.github/workflows/reusable-industrial-ci-with-cache.yml @@ -58,10 +58,10 @@ jobs: steps: - name: Checkout ${{ inputs.ref }} when build is not scheduled if: ${{ github.event_name != 'schedule' }} - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Checkout ${{ inputs.ref }} on scheduled build if: ${{ github.event_name == 'schedule' }} - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: ${{ inputs.ref_for_scheduled_build }} - name: cache target_ws diff --git a/.github/workflows/reusable-ros-tooling-source-build.yml b/.github/workflows/reusable-ros-tooling-source-build.yml index d5f836f026..5a01d23533 100644 --- a/.github/workflows/reusable-ros-tooling-source-build.yml +++ b/.github/workflows/reusable-ros-tooling-source-build.yml @@ -29,7 +29,7 @@ jobs: - uses: ros-tooling/setup-ros@0.7.0 with: required-ros-distributions: ${{ inputs.ros_distro }} - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: ref: ${{ inputs.ref }} - uses: ros-tooling/action-ros-ci@0.3.3 diff --git a/.github/workflows/reviewer_lottery.yml b/.github/workflows/reviewer_lottery.yml index 772809825f..2edbc9b59e 100644 --- a/.github/workflows/reviewer_lottery.yml +++ b/.github/workflows/reviewer_lottery.yml @@ -7,7 +7,7 @@ jobs: test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: uesteibar/reviewer-lottery@v3 with: repo-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/rolling-abi-compatibility.yml b/.github/workflows/rolling-abi-compatibility.yml index 4589e92e3b..3911434a23 100644 --- a/.github/workflows/rolling-abi-compatibility.yml +++ b/.github/workflows/rolling-abi-compatibility.yml @@ -11,7 +11,7 @@ jobs: abi_check: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: ros-industrial/industrial_ci@master env: ROS_DISTRO: rolling diff --git a/.github/workflows/rolling-rhel-binary-build.yml b/.github/workflows/rolling-rhel-binary-build.yml index 91e645d9e3..04dc58775f 100644 --- a/.github/workflows/rolling-rhel-binary-build.yml +++ b/.github/workflows/rolling-rhel-binary-build.yml @@ -17,7 +17,7 @@ jobs: ROS_DISTRO: rolling container: ghcr.io/ros-controls/ros:rolling-rhel steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: path: src/ros2_controllers - run: | From 6352a70d210a6bdec6228a24f41b6d542d0e4364 Mon Sep 17 00:00:00 2001 From: chama1176 Date: Thu, 7 Sep 2023 03:16:41 +0900 Subject: [PATCH 103/238] Fixed implementation so that effort_controllers/GripperActionController works. (#756) --- .../gripper_action_controller.hpp | 2 +- .../gripper_action_controller_impl.hpp | 23 ++++++++++--------- .../hardware_interface_adapter.hpp | 2 +- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/gripper_controllers/include/gripper_controllers/gripper_action_controller.hpp b/gripper_controllers/include/gripper_controllers/gripper_action_controller.hpp index 9d67249405..38e0bd8191 100644 --- a/gripper_controllers/include/gripper_controllers/gripper_action_controller.hpp +++ b/gripper_controllers/include/gripper_controllers/gripper_action_controller.hpp @@ -126,7 +126,7 @@ class GripperActionController : public controller_interface::ControllerInterface bool verbose_ = false; ///< Hard coded verbose flag to help in debugging std::string name_; ///< Controller name. std::optional> - joint_position_command_interface_; + joint_command_interface_; std::optional> joint_position_state_interface_; std::optional> diff --git a/gripper_controllers/include/gripper_controllers/gripper_action_controller_impl.hpp b/gripper_controllers/include/gripper_controllers/gripper_action_controller_impl.hpp index 666fced1c0..77598591ae 100644 --- a/gripper_controllers/include/gripper_controllers/gripper_action_controller_impl.hpp +++ b/gripper_controllers/include/gripper_controllers/gripper_action_controller_impl.hpp @@ -226,20 +226,21 @@ template controller_interface::CallbackReturn GripperActionController::on_activate( const rclcpp_lifecycle::State &) { - auto position_command_interface_it = std::find_if( + auto command_interface_it = std::find_if( command_interfaces_.begin(), command_interfaces_.end(), [](const hardware_interface::LoanedCommandInterface & command_interface) - { return command_interface.get_interface_name() == hardware_interface::HW_IF_POSITION; }); - if (position_command_interface_it == command_interfaces_.end()) + { return command_interface.get_interface_name() == HardwareInterface; }); + if (command_interface_it == command_interfaces_.end()) { - RCLCPP_ERROR(get_node()->get_logger(), "Expected 1 position command interface"); + RCLCPP_ERROR_STREAM( + get_node()->get_logger(), "Expected 1 " << HardwareInterface << " command interface"); return controller_interface::CallbackReturn::ERROR; } - if (position_command_interface_it->get_prefix_name() != params_.joint) + if (command_interface_it->get_prefix_name() != params_.joint) { RCLCPP_ERROR_STREAM( - get_node()->get_logger(), "Position command interface is different than joint name `" - << position_command_interface_it->get_prefix_name() << "` != `" + get_node()->get_logger(), "Command interface is different than joint name `" + << command_interface_it->get_prefix_name() << "` != `" << params_.joint << "`"); return controller_interface::CallbackReturn::ERROR; } @@ -278,12 +279,12 @@ controller_interface::CallbackReturn GripperActionController: return controller_interface::CallbackReturn::ERROR; } - joint_position_command_interface_ = *position_command_interface_it; + joint_command_interface_ = *command_interface_it; joint_position_state_interface_ = *position_state_interface_it; joint_velocity_state_interface_ = *velocity_state_interface_it; // Hardware interface adapter - hw_iface_adapter_.init(joint_position_command_interface_, get_node()); + hw_iface_adapter_.init(joint_command_interface_, get_node()); // Command - non RT version command_struct_.position_ = joint_position_state_interface_->get().get_value(); @@ -311,7 +312,7 @@ template controller_interface::CallbackReturn GripperActionController::on_deactivate( const rclcpp_lifecycle::State &) { - joint_position_command_interface_ = std::nullopt; + joint_command_interface_ = std::nullopt; joint_position_state_interface_ = std::nullopt; joint_velocity_state_interface_ = std::nullopt; release_interfaces(); @@ -324,7 +325,7 @@ GripperActionController::command_interface_configuration() co { return { controller_interface::interface_configuration_type::INDIVIDUAL, - {params_.joint + "/" + hardware_interface::HW_IF_POSITION}}; + {params_.joint + "/" + HardwareInterface}}; } template diff --git a/gripper_controllers/include/gripper_controllers/hardware_interface_adapter.hpp b/gripper_controllers/include/gripper_controllers/hardware_interface_adapter.hpp index 97ebbb1f4b..b125ab12d0 100644 --- a/gripper_controllers/include/gripper_controllers/hardware_interface_adapter.hpp +++ b/gripper_controllers/include/gripper_controllers/hardware_interface_adapter.hpp @@ -131,7 +131,7 @@ class HardwareInterfaceAdapter { joint_handle_ = joint_handle; // Init PID gains from ROS parameter server - const std::string prefix = "gains." + joint_handle_->get().get_name(); + const std::string prefix = "gains." + joint_handle_->get().get_prefix_name(); const auto k_p = auto_declare(node, prefix + ".p", 0.0); const auto k_i = auto_declare(node, prefix + ".i", 0.0); const auto k_d = auto_declare(node, prefix + ".d", 0.0); From 5b86e3c848a0f1498978e24fe5b1b48566c2d14e Mon Sep 17 00:00:00 2001 From: flochre <39066045+flochre@users.noreply.github.com> Date: Thu, 7 Sep 2023 06:17:30 +0600 Subject: [PATCH 104/238] add a broadcaster for range sensor (#725) --- range_sensor_broadcaster/CMakeLists.txt | 106 ++++++++ range_sensor_broadcaster/README.md | 8 + range_sensor_broadcaster/doc/userdoc.rst | 15 ++ .../range_sensor_broadcaster.hpp | 77 ++++++ .../visibility_control.h | 53 ++++ range_sensor_broadcaster/package.xml | 31 +++ .../range_sensor_broadcaster.xml | 8 + .../src/range_sensor_broadcaster.cpp | 138 ++++++++++ .../range_sensor_broadcaster_parameters.yaml | 16 ++ .../test/range_sensor_broadcaster_params.yaml | 12 + .../test_load_range_sensor_broadcaster.cpp | 52 ++++ .../test/test_range_sensor_broadcaster.cpp | 252 ++++++++++++++++++ .../test/test_range_sensor_broadcaster.hpp | 59 ++++ ros2_controllers/package.xml | 1 + 14 files changed, 828 insertions(+) create mode 100644 range_sensor_broadcaster/CMakeLists.txt create mode 100644 range_sensor_broadcaster/README.md create mode 100644 range_sensor_broadcaster/doc/userdoc.rst create mode 100644 range_sensor_broadcaster/include/range_sensor_broadcaster/range_sensor_broadcaster.hpp create mode 100644 range_sensor_broadcaster/include/range_sensor_broadcaster/visibility_control.h create mode 100644 range_sensor_broadcaster/package.xml create mode 100644 range_sensor_broadcaster/range_sensor_broadcaster.xml create mode 100644 range_sensor_broadcaster/src/range_sensor_broadcaster.cpp create mode 100644 range_sensor_broadcaster/src/range_sensor_broadcaster_parameters.yaml create mode 100644 range_sensor_broadcaster/test/range_sensor_broadcaster_params.yaml create mode 100644 range_sensor_broadcaster/test/test_load_range_sensor_broadcaster.cpp create mode 100644 range_sensor_broadcaster/test/test_range_sensor_broadcaster.cpp create mode 100644 range_sensor_broadcaster/test/test_range_sensor_broadcaster.hpp diff --git a/range_sensor_broadcaster/CMakeLists.txt b/range_sensor_broadcaster/CMakeLists.txt new file mode 100644 index 0000000000..00da395db5 --- /dev/null +++ b/range_sensor_broadcaster/CMakeLists.txt @@ -0,0 +1,106 @@ +cmake_minimum_required(VERSION 3.8) +project(range_sensor_broadcaster) + +# Default to C++17 +if(NOT CMAKE_CXX_STANDARD) + set(CMAKE_CXX_STANDARD 17) + set(CMAKE_CXX_STANDARD_REQUIRED ON) +endif() + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") + add_compile_options(-Wall -Wextra -Wpedantic) +endif() + +set(THIS_PACKAGE_INCLUDE_DEPENDS + controller_interface + generate_parameter_library + hardware_interface + pluginlib + rclcpp + rclcpp_lifecycle + realtime_tools + sensor_msgs +) + +# find dependencies +find_package(ament_cmake REQUIRED) +find_package(backward_ros REQUIRED) +foreach(Dependency IN ITEMS ${THIS_PACKAGE_INCLUDE_DEPENDS}) + find_package(${Dependency} REQUIRED) +endforeach() + + +generate_parameter_library(range_sensor_broadcaster_parameters + src/range_sensor_broadcaster_parameters.yaml +) + +add_library( + range_sensor_broadcaster SHARED + src/range_sensor_broadcaster.cpp +) +target_include_directories(range_sensor_broadcaster + PRIVATE $ + PRIVATE $ +) +ament_target_dependencies(range_sensor_broadcaster ${THIS_PACKAGE_INCLUDE_DEPENDS}) +# Causes the visibility macros to use dllexport rather than dllimport, +# which is appropriate when building the dll but not consuming it. +target_compile_definitions(range_sensor_broadcaster PRIVATE "RANGE_SENSOR_BROADCASTER_BUILDING_DLL") +target_link_libraries(range_sensor_broadcaster + range_sensor_broadcaster_parameters +) + +pluginlib_export_plugin_description_file( + controller_interface range_sensor_broadcaster.xml) + +if(BUILD_TESTING) + find_package(ament_cmake_gmock REQUIRED) + find_package(controller_manager REQUIRED) + find_package(hardware_interface REQUIRED) + find_package(ros2_control_test_assets REQUIRED) + + add_rostest_with_parameters_gmock(test_load_range_sensor_broadcaster + test/test_load_range_sensor_broadcaster.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test/range_sensor_broadcaster_params.yaml) + target_include_directories(test_load_range_sensor_broadcaster PRIVATE include) + target_link_libraries(test_load_range_sensor_broadcaster + range_sensor_broadcaster + ) + ament_target_dependencies(test_load_range_sensor_broadcaster + controller_manager + hardware_interface + ros2_control_test_assets + ) + + add_rostest_with_parameters_gmock(test_range_sensor_broadcaster + test/test_range_sensor_broadcaster.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test/range_sensor_broadcaster_params.yaml) + target_include_directories(test_range_sensor_broadcaster PRIVATE include) + target_link_libraries(test_range_sensor_broadcaster + range_sensor_broadcaster + ) + ament_target_dependencies(test_range_sensor_broadcaster + hardware_interface + ) +endif() + +install( + DIRECTORY include/ + DESTINATION include +) + +install( + TARGETS + range_sensor_broadcaster + range_sensor_broadcaster_parameters + EXPORT export_range_sensor_broadcaster + RUNTIME DESTINATION bin + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib + INCLUDES DESTINATION include +) + +ament_export_targets(export_range_sensor_broadcaster HAS_LIBRARY_TARGET) +ament_export_dependencies(${THIS_PACKAGE_INCLUDE_DEPENDS}) + +ament_package() diff --git a/range_sensor_broadcaster/README.md b/range_sensor_broadcaster/README.md new file mode 100644 index 0000000000..33195d272b --- /dev/null +++ b/range_sensor_broadcaster/README.md @@ -0,0 +1,8 @@ +range_sensor_broadcaster +========================================== + +Controller to publish readings of Range sensors. + +Pluginlib-Library: range_sensor_broadcaster + +Plugin: range_sensor_broadcaster/RangeSensorBroadcaster (controller_interface::ControllerInterface) diff --git a/range_sensor_broadcaster/doc/userdoc.rst b/range_sensor_broadcaster/doc/userdoc.rst new file mode 100644 index 0000000000..e35bec67ad --- /dev/null +++ b/range_sensor_broadcaster/doc/userdoc.rst @@ -0,0 +1,15 @@ +:github_url: https://github.com/ros-controls/ros2_controllers/blob/{REPOS_FILE_BRANCH}/range_sensor_broadcaster/doc/userdoc.rst + +.. _range_sensor_broadcaster_userdoc: + +Range Sensor Broadcaster +-------------------------------- +Broadcaster of messages from Range sensor. +The published message type is ``sensor_msgs/msg/Range``. + +The controller is a wrapper around ``RangeSensor`` semantic component (see ``controller_interface`` package). + +Parameters +^^^^^^^^^^^ + +.. generate_parameter_library_details:: ../src/range_sensor_broadcaster_parameters.yaml diff --git a/range_sensor_broadcaster/include/range_sensor_broadcaster/range_sensor_broadcaster.hpp b/range_sensor_broadcaster/include/range_sensor_broadcaster/range_sensor_broadcaster.hpp new file mode 100644 index 0000000000..b2e5fbfac0 --- /dev/null +++ b/range_sensor_broadcaster/include/range_sensor_broadcaster/range_sensor_broadcaster.hpp @@ -0,0 +1,77 @@ +// Copyright 2021 PAL Robotics SL. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/* + * Authors: Subhas Das, Denis Stogl, Victor Lopez + */ + +#ifndef RANGE_SENSOR_BROADCASTER__RANGE_SENSOR_BROADCASTER_HPP_ +#define RANGE_SENSOR_BROADCASTER__RANGE_SENSOR_BROADCASTER_HPP_ + +#include +#include +#include + +#include "controller_interface/controller_interface.hpp" +#include "range_sensor_broadcaster/visibility_control.h" +#include "range_sensor_broadcaster_parameters.hpp" +#include "rclcpp_lifecycle/node_interfaces/lifecycle_node_interface.hpp" +#include "rclcpp_lifecycle/state.hpp" +#include "realtime_tools/realtime_publisher.h" +#include "semantic_components/range_sensor.hpp" +#include "sensor_msgs/msg/range.hpp" + +namespace range_sensor_broadcaster +{ +class RangeSensorBroadcaster : public controller_interface::ControllerInterface +{ +public: + RANGE_SENSOR_BROADCASTER_PUBLIC + controller_interface::InterfaceConfiguration command_interface_configuration() const override; + + RANGE_SENSOR_BROADCASTER_PUBLIC + controller_interface::InterfaceConfiguration state_interface_configuration() const override; + + RANGE_SENSOR_BROADCASTER_PUBLIC controller_interface::CallbackReturn on_init() override; + + RANGE_SENSOR_BROADCASTER_PUBLIC + controller_interface::CallbackReturn on_configure( + const rclcpp_lifecycle::State & previous_state) override; + + RANGE_SENSOR_BROADCASTER_PUBLIC + controller_interface::CallbackReturn on_activate( + const rclcpp_lifecycle::State & previous_state) override; + + RANGE_SENSOR_BROADCASTER_PUBLIC + controller_interface::CallbackReturn on_deactivate( + const rclcpp_lifecycle::State & previous_state) override; + + RANGE_SENSOR_BROADCASTER_PUBLIC + controller_interface::return_type update( + const rclcpp::Time & time, const rclcpp::Duration & period) override; + +protected: + std::shared_ptr param_listener_; + Params params_; + + std::unique_ptr range_sensor_; + + using StatePublisher = realtime_tools::RealtimePublisher; + rclcpp::Publisher::SharedPtr sensor_state_publisher_; + std::unique_ptr realtime_publisher_; +}; + +} // namespace range_sensor_broadcaster + +#endif // RANGE_SENSOR_BROADCASTER__RANGE_SENSOR_BROADCASTER_HPP_ diff --git a/range_sensor_broadcaster/include/range_sensor_broadcaster/visibility_control.h b/range_sensor_broadcaster/include/range_sensor_broadcaster/visibility_control.h new file mode 100644 index 0000000000..0a9a9f53a8 --- /dev/null +++ b/range_sensor_broadcaster/include/range_sensor_broadcaster/visibility_control.h @@ -0,0 +1,53 @@ +// Copyright (c) 2021, Stogl Robotics Consulting UG (haftungsbeschränkt) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/* + * Author: Subhas Das, Denis Stogl + */ + +#ifndef RANGE_SENSOR_BROADCASTER__VISIBILITY_CONTROL_H_ +#define RANGE_SENSOR_BROADCASTER__VISIBILITY_CONTROL_H_ + +// This logic was borrowed (then namespaced) from the examples on the gcc wiki: +// https://gcc.gnu.org/wiki/Visibility + +#if defined _WIN32 || defined __CYGWIN__ +#ifdef __GNUC__ +#define RANGE_SENSOR_BROADCASTER_EXPORT __attribute__((dllexport)) +#define RANGE_SENSOR_BROADCASTER_IMPORT __attribute__((dllimport)) +#else +#define RANGE_SENSOR_BROADCASTER_EXPORT __declspec(dllexport) +#define RANGE_SENSOR_BROADCASTER_IMPORT __declspec(dllimport) +#endif +#ifdef RANGE_SENSOR_BROADCASTER_BUILDING_DLL +#define RANGE_SENSOR_BROADCASTER_PUBLIC RANGE_SENSOR_BROADCASTER_EXPORT +#else +#define RANGE_SENSOR_BROADCASTER_PUBLIC RANGE_SENSOR_BROADCASTER_IMPORT +#endif +#define RANGE_SENSOR_BROADCASTER_PUBLIC_TYPE RANGE_SENSOR_BROADCASTER_PUBLIC +#define RANGE_SENSOR_BROADCASTER_LOCAL +#else +#define RANGE_SENSOR_BROADCASTER_EXPORT __attribute__((visibility("default"))) +#define RANGE_SENSOR_BROADCASTER_IMPORT +#if __GNUC__ >= 4 +#define RANGE_SENSOR_BROADCASTER_PUBLIC __attribute__((visibility("default"))) +#define RANGE_SENSOR_BROADCASTER_LOCAL __attribute__((visibility("hidden"))) +#else +#define RANGE_SENSOR_BROADCASTER_PUBLIC +#define RANGE_SENSOR_BROADCASTER_LOCAL +#endif +#define RANGE_SENSOR_BROADCASTER_PUBLIC_TYPE +#endif + +#endif // RANGE_SENSOR_BROADCASTER__VISIBILITY_CONTROL_H_ diff --git a/range_sensor_broadcaster/package.xml b/range_sensor_broadcaster/package.xml new file mode 100644 index 0000000000..11175d9f03 --- /dev/null +++ b/range_sensor_broadcaster/package.xml @@ -0,0 +1,31 @@ + + + + range_sensor_broadcaster + 3.14.0 + Controller to publish readings of Range sensors. + Bence Magyar + Florent Chretien + Apache License 2.0 + + ament_cmake + + backward_ros + controller_interface + generate_parameter_library + hardware_interface + pluginlib + rclcpp + rclcpp_lifecycle + realtime_tools + sensor_msgs + + ament_cmake_gmock + controller_manager + hardware_interface + ros2_control_test_assets + + + ament_cmake + + diff --git a/range_sensor_broadcaster/range_sensor_broadcaster.xml b/range_sensor_broadcaster/range_sensor_broadcaster.xml new file mode 100644 index 0000000000..fd82c7ae25 --- /dev/null +++ b/range_sensor_broadcaster/range_sensor_broadcaster.xml @@ -0,0 +1,8 @@ + + + + This controller publishes the readings of an Range sensor as sensor_msgs/Range message. + + + diff --git a/range_sensor_broadcaster/src/range_sensor_broadcaster.cpp b/range_sensor_broadcaster/src/range_sensor_broadcaster.cpp new file mode 100644 index 0000000000..b821da8c13 --- /dev/null +++ b/range_sensor_broadcaster/src/range_sensor_broadcaster.cpp @@ -0,0 +1,138 @@ +// Copyright 2021 PAL Robotics SL. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/* + * Authors: Subhas Das, Denis Stogl, Victor Lopez + */ + +#include "range_sensor_broadcaster/range_sensor_broadcaster.hpp" + +#include +#include + +namespace range_sensor_broadcaster +{ +controller_interface::CallbackReturn RangeSensorBroadcaster::on_init() +{ + try + { + param_listener_ = std::make_shared(get_node()); + params_ = param_listener_->get_params(); + } + catch (const std::exception & e) + { + RCLCPP_ERROR( + get_node()->get_logger(), "Exception thrown during init stage with message: %s \n", e.what()); + return CallbackReturn::ERROR; + } + + return CallbackReturn::SUCCESS; +} + +controller_interface::CallbackReturn RangeSensorBroadcaster::on_configure( + const rclcpp_lifecycle::State & /*previous_state*/) +{ + params_ = param_listener_->get_params(); + if (params_.sensor_name.empty()) + { + RCLCPP_ERROR(get_node()->get_logger(), "'sensor_name' parameter has to be specified."); + return CallbackReturn::ERROR; + } + + if (params_.frame_id.empty()) + { + RCLCPP_ERROR(get_node()->get_logger(), "'frame_id' parameter has to be provided."); + return CallbackReturn::ERROR; + } + + range_sensor_ = std::make_unique( + semantic_components::RangeSensor(params_.sensor_name)); + try + { + // register ft sensor data publisher + sensor_state_publisher_ = + get_node()->create_publisher("~/range", rclcpp::SystemDefaultsQoS()); + realtime_publisher_ = std::make_unique(sensor_state_publisher_); + } + catch (const std::exception & e) + { + fprintf( + stderr, "Exception thrown during publisher creation at configure stage with message : %s \n", + e.what()); + return CallbackReturn::ERROR; + } + + realtime_publisher_->lock(); + realtime_publisher_->msg_.header.frame_id = params_.frame_id; + realtime_publisher_->msg_.radiation_type = params_.radiation_type; + realtime_publisher_->msg_.field_of_view = params_.field_of_view; + realtime_publisher_->msg_.min_range = params_.min_range; + realtime_publisher_->msg_.max_range = params_.max_range; + realtime_publisher_->msg_.variance = params_.variance; + realtime_publisher_->unlock(); + + RCLCPP_DEBUG(get_node()->get_logger(), "configure successful"); + return CallbackReturn::SUCCESS; +} + +controller_interface::InterfaceConfiguration +RangeSensorBroadcaster::command_interface_configuration() const +{ + controller_interface::InterfaceConfiguration command_interfaces_config; + command_interfaces_config.type = controller_interface::interface_configuration_type::NONE; + return command_interfaces_config; +} + +controller_interface::InterfaceConfiguration RangeSensorBroadcaster::state_interface_configuration() + const +{ + controller_interface::InterfaceConfiguration state_interfaces_config; + state_interfaces_config.type = controller_interface::interface_configuration_type::INDIVIDUAL; + state_interfaces_config.names = range_sensor_->get_state_interface_names(); + return state_interfaces_config; +} + +controller_interface::CallbackReturn RangeSensorBroadcaster::on_activate( + const rclcpp_lifecycle::State & /*previous_state*/) +{ + range_sensor_->assign_loaned_state_interfaces(state_interfaces_); + return CallbackReturn::SUCCESS; +} + +controller_interface::CallbackReturn RangeSensorBroadcaster::on_deactivate( + const rclcpp_lifecycle::State & /*previous_state*/) +{ + range_sensor_->release_interfaces(); + return CallbackReturn::SUCCESS; +} + +controller_interface::return_type RangeSensorBroadcaster::update( + const rclcpp::Time & time, const rclcpp::Duration & /*period*/) +{ + if (realtime_publisher_ && realtime_publisher_->trylock()) + { + realtime_publisher_->msg_.header.stamp = time; + range_sensor_->get_values_as_message(realtime_publisher_->msg_); + realtime_publisher_->unlockAndPublish(); + } + + return controller_interface::return_type::OK; +} + +} // namespace range_sensor_broadcaster + +#include "pluginlib/class_list_macros.hpp" + +PLUGINLIB_EXPORT_CLASS( + range_sensor_broadcaster::RangeSensorBroadcaster, controller_interface::ControllerInterface) diff --git a/range_sensor_broadcaster/src/range_sensor_broadcaster_parameters.yaml b/range_sensor_broadcaster/src/range_sensor_broadcaster_parameters.yaml new file mode 100644 index 0000000000..57d39d20c4 --- /dev/null +++ b/range_sensor_broadcaster/src/range_sensor_broadcaster_parameters.yaml @@ -0,0 +1,16 @@ +range_sensor_broadcaster: + sensor_name: { + type: string, + default_value: "", + description: "Name of the sensor used as prefix for interfaces if there are no individual interface names defined.", + } + frame_id: { + type: string, + default_value: "", + description: "Sensor's frame_id in which values are published.", + } + radiation_type: {type: int, default_value: 0, description: "The type of radiation used by the sensor / 0 = Ultrason / 1 = Infrared",} + field_of_view: {type: double, default_value: 0.52, description: "The size of the arc that the distance reading is valid for [rad]",} + min_range: {type: double, default_value: 0.52, description: "Minimum range value [m]",} + max_range: {type: double, default_value: 4.0, description: "Maximum range value [m]",} + variance: {type: double, default_value: 0.0, description: "Variance of the range value",} diff --git a/range_sensor_broadcaster/test/range_sensor_broadcaster_params.yaml b/range_sensor_broadcaster/test/range_sensor_broadcaster_params.yaml new file mode 100644 index 0000000000..1e59a7f27b --- /dev/null +++ b/range_sensor_broadcaster/test/range_sensor_broadcaster_params.yaml @@ -0,0 +1,12 @@ +test_range_sensor_broadcaster: + ros__parameters: + # Setting mendatory parameters + sensor_name: "range_sensor" + frame_id: "range_sensor_frame" + + # Setting parameters with changed default value to check those are used + radiation_type: 1 + field_of_view: 0.1 + min_range: 0.10 + max_range: 7.0 + variance: 1.0 diff --git a/range_sensor_broadcaster/test/test_load_range_sensor_broadcaster.cpp b/range_sensor_broadcaster/test/test_load_range_sensor_broadcaster.cpp new file mode 100644 index 0000000000..5c400bef91 --- /dev/null +++ b/range_sensor_broadcaster/test/test_load_range_sensor_broadcaster.cpp @@ -0,0 +1,52 @@ +// Copyright (c) 2021, Stogl Robotics Consulting UG (haftungsbeschränkt) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/* + * Author: Subhas Das, Denis Stogl, Florent Chretien + */ + +#include +#include + +#include "controller_manager/controller_manager.hpp" +#include "hardware_interface/resource_manager.hpp" +#include "rclcpp/executor.hpp" +#include "rclcpp/executors/single_threaded_executor.hpp" +#include "rclcpp/utilities.hpp" +#include "ros2_control_test_assets/descriptions.hpp" + +TEST(TestLoadRangeSensorBroadcaster, load_controller) +{ + std::shared_ptr executor = + std::make_shared(); + + controller_manager::ControllerManager cm( + std::make_unique( + ros2_control_test_assets::minimal_robot_urdf), + executor, "test_controller_manager"); + + ASSERT_NE( + cm.load_controller( + "test_range_sensor_broadcaster", "range_sensor_broadcaster/RangeSensorBroadcaster"), + nullptr); +} + +int main(int argc, char ** argv) +{ + ::testing::InitGoogleMock(&argc, argv); + rclcpp::init(argc, argv); + int result = RUN_ALL_TESTS(); + rclcpp::shutdown(); + return result; +} diff --git a/range_sensor_broadcaster/test/test_range_sensor_broadcaster.cpp b/range_sensor_broadcaster/test/test_range_sensor_broadcaster.cpp new file mode 100644 index 0000000000..855f7e037b --- /dev/null +++ b/range_sensor_broadcaster/test/test_range_sensor_broadcaster.cpp @@ -0,0 +1,252 @@ +// Copyright 2023 flochre +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/* + * Authors: flochre + */ + +#include + +#include "test_range_sensor_broadcaster.hpp" + +#include "hardware_interface/loaned_state_interface.hpp" + +void RangeSensorBroadcasterTest::SetUp() +{ + // initialize controller + range_broadcaster_ = std::make_unique(); +} + +void RangeSensorBroadcasterTest::TearDown() { range_broadcaster_.reset(nullptr); } + +controller_interface::return_type RangeSensorBroadcasterTest::init_broadcaster( + std::string broadcaster_name) +{ + controller_interface::return_type result = controller_interface::return_type::ERROR; + result = range_broadcaster_->init(broadcaster_name); + + if (controller_interface::return_type::OK == result) + { + std::vector state_interfaces; + state_interfaces.emplace_back(range_); + + range_broadcaster_->assign_interfaces({}, std::move(state_interfaces)); + } + + return result; +} + +controller_interface::CallbackReturn RangeSensorBroadcasterTest::configure_broadcaster( + std::vector & parameters) +{ + // Configure the broadcaster + for (auto parameter : parameters) + { + range_broadcaster_->get_node()->set_parameter(parameter); + } + + return range_broadcaster_->on_configure(rclcpp_lifecycle::State()); +} + +void RangeSensorBroadcasterTest::subscribe_and_get_message(sensor_msgs::msg::Range & range_msg) +{ + // create a new subscriber + rclcpp::Node test_subscription_node("test_subscription_node"); + auto subs_callback = [&](const sensor_msgs::msg::Range::SharedPtr) {}; + auto subscription = test_subscription_node.create_subscription( + "/test_range_sensor_broadcaster/range", 10, subs_callback); + + // call update to publish the test value + // since update doesn't guarantee a published message, republish until received + int max_sub_check_loop_count = 5; // max number of tries for pub/sub loop + rclcpp::WaitSet wait_set; // block used to wait on message + wait_set.add_subscription(subscription); + while (max_sub_check_loop_count--) + { + range_broadcaster_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)); + // check if message has been received + if (wait_set.wait(std::chrono::milliseconds(2)).kind() == rclcpp::WaitResultKind::Ready) + { + break; + } + } + ASSERT_GE(max_sub_check_loop_count, 0) << "Test was unable to publish a message through " + "controller/broadcaster update loop"; + + // take message from subscription + rclcpp::MessageInfo msg_info; + ASSERT_TRUE(subscription->take(range_msg, msg_info)); +} + +TEST_F(RangeSensorBroadcasterTest, Initialize_RangeBroadcaster_Exception) +{ + ASSERT_THROW(init_broadcaster(""), std::exception); +} + +TEST_F(RangeSensorBroadcasterTest, Initialize_RangeBroadcaster_Success) +{ + ASSERT_EQ( + init_broadcaster("test_range_sensor_broadcaster"), controller_interface::return_type::OK); +} + +TEST_F(RangeSensorBroadcasterTest, Configure_RangeBroadcaster_Error_1) +{ + // First Test without frame_id ERROR Expected + init_broadcaster("test_range_sensor_broadcaster"); + + std::vector parameters; + // explicitly give an empty sensor name to generate an error + parameters.emplace_back(rclcpp::Parameter("sensor_name", "")); + ASSERT_EQ(configure_broadcaster(parameters), controller_interface::CallbackReturn::ERROR); +} + +TEST_F(RangeSensorBroadcasterTest, Configure_RangeBroadcaster_Error_2) +{ + // Second Test without sensor_name ERROR Expected + init_broadcaster("test_range_sensor_broadcaster"); + + std::vector parameters; + // explicitly give an empty frame_id to generate an error + parameters.emplace_back(rclcpp::Parameter("frame_id", "")); + ASSERT_EQ(configure_broadcaster(parameters), controller_interface::CallbackReturn::ERROR); +} + +TEST_F(RangeSensorBroadcasterTest, Configure_RangeBroadcaster_Success) +{ + // Third Test without sensor_name SUCCESS Expected + init_broadcaster("test_range_sensor_broadcaster"); + + ASSERT_EQ( + range_broadcaster_->on_configure(rclcpp_lifecycle::State()), + controller_interface::CallbackReturn::SUCCESS); +} + +TEST_F(RangeSensorBroadcasterTest, Activate_RangeBroadcaster_Success) +{ + init_broadcaster("test_range_sensor_broadcaster"); + + range_broadcaster_->on_configure(rclcpp_lifecycle::State()); + + ASSERT_EQ( + range_broadcaster_->on_activate(rclcpp_lifecycle::State()), + controller_interface::CallbackReturn::SUCCESS); +} + +TEST_F(RangeSensorBroadcasterTest, Update_RangeBroadcaster_Success) +{ + init_broadcaster("test_range_sensor_broadcaster"); + + range_broadcaster_->on_configure(rclcpp_lifecycle::State()); + ASSERT_EQ( + range_broadcaster_->on_activate(rclcpp_lifecycle::State()), + controller_interface::CallbackReturn::SUCCESS); + auto result = range_broadcaster_->update( + range_broadcaster_->get_node()->get_clock()->now(), rclcpp::Duration::from_seconds(0.01)); + + ASSERT_EQ(result, controller_interface::return_type::OK); +} + +TEST_F(RangeSensorBroadcasterTest, Publish_RangeBroadcaster_Success) +{ + init_broadcaster("test_range_sensor_broadcaster"); + + range_broadcaster_->on_configure(rclcpp_lifecycle::State()); + range_broadcaster_->on_activate(rclcpp_lifecycle::State()); + + sensor_msgs::msg::Range range_msg; + subscribe_and_get_message(range_msg); + + EXPECT_EQ(range_msg.header.frame_id, frame_id_); + EXPECT_THAT(range_msg.range, ::testing::FloatEq(sensor_range_)); + EXPECT_EQ(range_msg.radiation_type, radiation_type_); + EXPECT_THAT(range_msg.field_of_view, ::testing::FloatEq(field_of_view_)); + EXPECT_THAT(range_msg.min_range, ::testing::FloatEq(min_range_)); + EXPECT_THAT(range_msg.max_range, ::testing::FloatEq(max_range_)); + EXPECT_THAT(range_msg.variance, ::testing::FloatEq(variance_)); +} + +TEST_F(RangeSensorBroadcasterTest, Publish_Bandaries_RangeBroadcaster_Success) +{ + init_broadcaster("test_range_sensor_broadcaster"); + + range_broadcaster_->on_configure(rclcpp_lifecycle::State()); + range_broadcaster_->on_activate(rclcpp_lifecycle::State()); + + sensor_msgs::msg::Range range_msg; + + sensor_range_ = 0.10; + subscribe_and_get_message(range_msg); + + EXPECT_EQ(range_msg.header.frame_id, frame_id_); + EXPECT_THAT(range_msg.range, ::testing::FloatEq(sensor_range_)); + EXPECT_EQ(range_msg.radiation_type, radiation_type_); + EXPECT_THAT(range_msg.field_of_view, ::testing::FloatEq(field_of_view_)); + EXPECT_THAT(range_msg.min_range, ::testing::FloatEq(min_range_)); + EXPECT_THAT(range_msg.max_range, ::testing::FloatEq(max_range_)); + EXPECT_THAT(range_msg.variance, ::testing::FloatEq(variance_)); + + sensor_range_ = 4.0; + subscribe_and_get_message(range_msg); + + EXPECT_EQ(range_msg.header.frame_id, frame_id_); + EXPECT_THAT(range_msg.range, ::testing::FloatEq(sensor_range_)); + EXPECT_EQ(range_msg.radiation_type, radiation_type_); + EXPECT_THAT(range_msg.field_of_view, ::testing::FloatEq(field_of_view_)); + EXPECT_THAT(range_msg.min_range, ::testing::FloatEq(min_range_)); + EXPECT_THAT(range_msg.max_range, ::testing::FloatEq(max_range_)); + EXPECT_THAT(range_msg.variance, ::testing::FloatEq(variance_)); +} + +TEST_F(RangeSensorBroadcasterTest, Publish_OutOfBandaries_RangeBroadcaster_Success) +{ + init_broadcaster("test_range_sensor_broadcaster"); + + range_broadcaster_->on_configure(rclcpp_lifecycle::State()); + range_broadcaster_->on_activate(rclcpp_lifecycle::State()); + + sensor_msgs::msg::Range range_msg; + + sensor_range_ = 0.0; + subscribe_and_get_message(range_msg); + + EXPECT_EQ(range_msg.header.frame_id, frame_id_); + // Even out of boundaries you will get the out_of_range range value + EXPECT_THAT(range_msg.range, ::testing::FloatEq(sensor_range_)); + EXPECT_EQ(range_msg.radiation_type, radiation_type_); + EXPECT_THAT(range_msg.field_of_view, ::testing::FloatEq(field_of_view_)); + EXPECT_THAT(range_msg.min_range, ::testing::FloatEq(min_range_)); + EXPECT_THAT(range_msg.max_range, ::testing::FloatEq(max_range_)); + EXPECT_THAT(range_msg.variance, ::testing::FloatEq(variance_)); + + sensor_range_ = 6.0; + subscribe_and_get_message(range_msg); + + EXPECT_EQ(range_msg.header.frame_id, frame_id_); + // Even out of boundaries you will get the out_of_range range value + EXPECT_THAT(range_msg.range, ::testing::FloatEq(sensor_range_)); + EXPECT_EQ(range_msg.radiation_type, radiation_type_); + EXPECT_THAT(range_msg.field_of_view, ::testing::FloatEq(field_of_view_)); + EXPECT_THAT(range_msg.min_range, ::testing::FloatEq(min_range_)); + EXPECT_THAT(range_msg.max_range, ::testing::FloatEq(max_range_)); + EXPECT_THAT(range_msg.variance, ::testing::FloatEq(variance_)); +} + +int main(int argc, char ** argv) +{ + testing::InitGoogleMock(&argc, argv); + rclcpp::init(argc, argv); + int result = RUN_ALL_TESTS(); + rclcpp::shutdown(); + return result; +} diff --git a/range_sensor_broadcaster/test/test_range_sensor_broadcaster.hpp b/range_sensor_broadcaster/test/test_range_sensor_broadcaster.hpp new file mode 100644 index 0000000000..10696d071f --- /dev/null +++ b/range_sensor_broadcaster/test/test_range_sensor_broadcaster.hpp @@ -0,0 +1,59 @@ +// Copyright 2023 flochre +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/* + * Authors: flochre + */ + +#ifndef TEST_RANGE_SENSOR_BROADCASTER_HPP_ +#define TEST_RANGE_SENSOR_BROADCASTER_HPP_ + +#include +#include +#include + +#include "gmock/gmock.h" + +#include "range_sensor_broadcaster/range_sensor_broadcaster.hpp" + +class RangeSensorBroadcasterTest : public ::testing::Test +{ +public: + void SetUp(); + void TearDown(); + +protected: + // for the sake of the test + // defining the parameter names same as in test/range_sensor_broadcaster_params.yaml + const std::string sensor_name_ = "range_sensor"; + const std::string frame_id_ = "range_sensor_frame"; + + const double field_of_view_ = 0.1; + const int radiation_type_ = 1; + const double min_range_ = 0.1; + const double max_range_ = 7.0; + const double variance_ = 1.0; + + double sensor_range_ = 3.1; + hardware_interface::StateInterface range_{sensor_name_, "range", &sensor_range_}; + + std::unique_ptr range_broadcaster_; + + controller_interface::return_type init_broadcaster(std::string broadcaster_name); + controller_interface::CallbackReturn configure_broadcaster( + std::vector & parameters); + void subscribe_and_get_message(sensor_msgs::msg::Range & range_msg); +}; + +#endif // TEST_RANGE_SENSOR_BROADCASTER_HPP_ diff --git a/ros2_controllers/package.xml b/ros2_controllers/package.xml index ca4a031da6..51d4d9ae44 100644 --- a/ros2_controllers/package.xml +++ b/ros2_controllers/package.xml @@ -21,6 +21,7 @@ joint_state_broadcaster joint_trajectory_controller position_controllers + range_sensor_broadcaster steering_controllers_library tricycle_controller tricycle_steering_controller From 4d0b999540177f4237550184caae0f2960d5b72b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Thu, 7 Sep 2023 19:00:45 +0200 Subject: [PATCH 105/238] [Docs+CI] Add range sensor to controller index and lint job (#767) --- .github/workflows/ci-ros-lint.yml | 2 ++ doc/controllers_index.rst | 5 +++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-ros-lint.yml b/.github/workflows/ci-ros-lint.yml index bfb6fd3386..5789c2dee4 100644 --- a/.github/workflows/ci-ros-lint.yml +++ b/.github/workflows/ci-ros-lint.yml @@ -32,6 +32,7 @@ jobs: joint_state_broadcaster joint_trajectory_controller position_controllers + range_sensor_broadcaster ros2_controllers ros2_controllers_test_nodes rqt_joint_trajectory_controller @@ -69,6 +70,7 @@ jobs: joint_state_broadcaster joint_trajectory_controller position_controllers + range_sensor_broadcaster ros2_controllers ros2_controllers_test_nodes rqt_joint_trajectory_controller diff --git a/doc/controllers_index.rst b/doc/controllers_index.rst index 763381c065..de33c3284c 100644 --- a/doc/controllers_index.rst +++ b/doc/controllers_index.rst @@ -63,6 +63,7 @@ Available Broadcasters .. toctree:: :titlesonly: - Joint State Broadcaster <../joint_state_broadcaster/doc/userdoc.rst> - Imu Sensor Broadcaster <../imu_sensor_broadcaster/doc/userdoc.rst> Force Torque Sensor Broadcaster <../force_torque_sensor_broadcaster/doc/userdoc.rst> + Imu Sensor Broadcaster <../imu_sensor_broadcaster/doc/userdoc.rst> + Joint State Broadcaster <../joint_state_broadcaster/doc/userdoc.rst> + Range Sensor Broadcaster <../range_sensor_broadcaster/doc/userdoc.rst> From fb46a77df7a6179a7724c7ac0145b0be4740cbfa Mon Sep 17 00:00:00 2001 From: chama1176 Date: Fri, 8 Sep 2023 16:30:34 +0900 Subject: [PATCH 106/238] Add test for effort gripper controller (#769) --- .../test/test_gripper_controllers.cpp | 103 +++++++++++------- .../test/test_gripper_controllers.hpp | 10 +- 2 files changed, 67 insertions(+), 46 deletions(-) diff --git a/gripper_controllers/test/test_gripper_controllers.cpp b/gripper_controllers/test/test_gripper_controllers.cpp index 4c82eb6961..506f968b99 100644 --- a/gripper_controllers/test/test_gripper_controllers.cpp +++ b/gripper_controllers/test/test_gripper_controllers.cpp @@ -32,123 +32,142 @@ using hardware_interface::LoanedStateInterface; using GripperCommandAction = control_msgs::action::GripperCommand; using GoalHandle = rclcpp_action::ServerGoalHandle; -void GripperControllerTest::SetUpTestCase() { rclcpp::init(0, nullptr); } +template +void GripperControllerTest::SetUpTestCase() +{ + rclcpp::init(0, nullptr); +} -void GripperControllerTest::TearDownTestCase() { rclcpp::shutdown(); } +template +void GripperControllerTest::TearDownTestCase() +{ + rclcpp::shutdown(); +} -void GripperControllerTest::SetUp() +template +void GripperControllerTest::SetUp() { // initialize controller - controller_ = std::make_unique(); + controller_ = std::make_unique>(); } -void GripperControllerTest::TearDown() { controller_.reset(nullptr); } +template +void GripperControllerTest::TearDown() +{ + controller_.reset(nullptr); +} -void GripperControllerTest::SetUpController() +template +void GripperControllerTest::SetUpController() { const auto result = controller_->init("gripper_controller"); ASSERT_EQ(result, controller_interface::return_type::OK); std::vector command_ifs; - command_ifs.emplace_back(joint_1_pos_cmd_); + command_ifs.emplace_back(this->joint_1_cmd_); std::vector state_ifs; - state_ifs.emplace_back(joint_1_pos_state_); - state_ifs.emplace_back(joint_1_vel_state_); + state_ifs.emplace_back(this->joint_1_pos_state_); + state_ifs.emplace_back(this->joint_1_vel_state_); controller_->assign_interfaces(std::move(command_ifs), std::move(state_ifs)); } -TEST_F(GripperControllerTest, ParametersNotSet) +using TestTypes = ::testing::Types< + std::integral_constant, + std::integral_constant>; +TYPED_TEST_SUITE(GripperControllerTest, TestTypes); + +TYPED_TEST(GripperControllerTest, ParametersNotSet) { - SetUpController(); + this->SetUpController(); // configure failed, 'joints' parameter not set ASSERT_EQ( - controller_->on_configure(rclcpp_lifecycle::State()), + this->controller_->on_configure(rclcpp_lifecycle::State()), controller_interface::CallbackReturn::ERROR); } -TEST_F(GripperControllerTest, JointParameterIsEmpty) +TYPED_TEST(GripperControllerTest, JointParameterIsEmpty) { - SetUpController(); + this->SetUpController(); - controller_->get_node()->set_parameter({"joint", ""}); + this->controller_->get_node()->set_parameter({"joint", ""}); // configure failed, 'joints' is empty ASSERT_EQ( - controller_->on_configure(rclcpp_lifecycle::State()), + this->controller_->on_configure(rclcpp_lifecycle::State()), controller_interface::CallbackReturn::ERROR); } -TEST_F(GripperControllerTest, ConfigureParamsSuccess) +TYPED_TEST(GripperControllerTest, ConfigureParamsSuccess) { - SetUpController(); + this->SetUpController(); - controller_->get_node()->set_parameter({"joint", "joint_1"}); + this->controller_->get_node()->set_parameter({"joint", "joint_1"}); // configure successful ASSERT_EQ( - controller_->on_configure(rclcpp_lifecycle::State()), + this->controller_->on_configure(rclcpp_lifecycle::State()), controller_interface::CallbackReturn::SUCCESS); } -TEST_F(GripperControllerTest, ActivateWithWrongJointsNamesFails) +TYPED_TEST(GripperControllerTest, ActivateWithWrongJointsNamesFails) { - SetUpController(); + this->SetUpController(); - controller_->get_node()->set_parameter({"joint", "unicorn_joint"}); + this->controller_->get_node()->set_parameter({"joint", "unicorn_joint"}); // activate failed, 'joint4' is not a valid joint name for the hardware ASSERT_EQ( - controller_->on_configure(rclcpp_lifecycle::State()), + this->controller_->on_configure(rclcpp_lifecycle::State()), controller_interface::CallbackReturn::SUCCESS); ASSERT_EQ( - controller_->on_activate(rclcpp_lifecycle::State()), + this->controller_->on_activate(rclcpp_lifecycle::State()), controller_interface::CallbackReturn::ERROR); } -TEST_F(GripperControllerTest, ActivateSuccess) +TYPED_TEST(GripperControllerTest, ActivateSuccess) { - SetUpController(); + this->SetUpController(); - controller_->get_node()->set_parameter({"joint", "joint1"}); + this->controller_->get_node()->set_parameter({"joint", "joint1"}); // activate successful ASSERT_EQ( - controller_->on_configure(rclcpp_lifecycle::State()), + this->controller_->on_configure(rclcpp_lifecycle::State()), controller_interface::CallbackReturn::SUCCESS); ASSERT_EQ( - controller_->on_activate(rclcpp_lifecycle::State()), + this->controller_->on_activate(rclcpp_lifecycle::State()), controller_interface::CallbackReturn::SUCCESS); } -TEST_F(GripperControllerTest, ActivateDeactivateActivateSuccess) +TYPED_TEST(GripperControllerTest, ActivateDeactivateActivateSuccess) { - SetUpController(); + this->SetUpController(); - controller_->get_node()->set_parameter({"joint", "joint1"}); + this->controller_->get_node()->set_parameter({"joint", "joint1"}); ASSERT_EQ( - controller_->on_configure(rclcpp_lifecycle::State()), + this->controller_->on_configure(rclcpp_lifecycle::State()), controller_interface::CallbackReturn::SUCCESS); ASSERT_EQ( - controller_->on_activate(rclcpp_lifecycle::State()), + this->controller_->on_activate(rclcpp_lifecycle::State()), controller_interface::CallbackReturn::SUCCESS); ASSERT_EQ( - controller_->on_deactivate(rclcpp_lifecycle::State()), + this->controller_->on_deactivate(rclcpp_lifecycle::State()), controller_interface::CallbackReturn::SUCCESS); // re-assign interfaces std::vector command_ifs; - command_ifs.emplace_back(joint_1_pos_cmd_); + command_ifs.emplace_back(this->joint_1_cmd_); std::vector state_ifs; - state_ifs.emplace_back(joint_1_pos_state_); - state_ifs.emplace_back(joint_1_vel_state_); - controller_->assign_interfaces(std::move(command_ifs), std::move(state_ifs)); + state_ifs.emplace_back(this->joint_1_pos_state_); + state_ifs.emplace_back(this->joint_1_vel_state_); + this->controller_->assign_interfaces(std::move(command_ifs), std::move(state_ifs)); ASSERT_EQ( - controller_->on_configure(rclcpp_lifecycle::State()), + this->controller_->on_configure(rclcpp_lifecycle::State()), controller_interface::CallbackReturn::SUCCESS); ASSERT_EQ( - controller_->on_activate(rclcpp_lifecycle::State()), + this->controller_->on_activate(rclcpp_lifecycle::State()), controller_interface::CallbackReturn::SUCCESS); } diff --git a/gripper_controllers/test/test_gripper_controllers.hpp b/gripper_controllers/test/test_gripper_controllers.hpp index 350e551cb8..4983c8102d 100644 --- a/gripper_controllers/test/test_gripper_controllers.hpp +++ b/gripper_controllers/test/test_gripper_controllers.hpp @@ -26,20 +26,22 @@ #include "hardware_interface/types/hardware_interface_type_values.hpp" using hardware_interface::CommandInterface; +using hardware_interface::HW_IF_EFFORT; using hardware_interface::HW_IF_POSITION; using hardware_interface::HW_IF_VELOCITY; using hardware_interface::StateInterface; namespace { - // subclassing and friending so we can access member variables +template class FriendGripperController -: public gripper_action_controller::GripperActionController +: public gripper_action_controller::GripperActionController { FRIEND_TEST(GripperControllerTest, CommandSuccessTest); }; +template class GripperControllerTest : public ::testing::Test { public: @@ -53,7 +55,7 @@ class GripperControllerTest : public ::testing::Test void SetUpHandles(); protected: - std::unique_ptr controller_; + std::unique_ptr> controller_; // dummy joint state values used for tests const std::string joint_name_ = "joint1"; @@ -62,7 +64,7 @@ class GripperControllerTest : public ::testing::Test StateInterface joint_1_pos_state_{joint_name_, HW_IF_POSITION, &joint_states_[0]}; StateInterface joint_1_vel_state_{joint_name_, HW_IF_VELOCITY, &joint_states_[1]}; - CommandInterface joint_1_pos_cmd_{joint_name_, HW_IF_POSITION, &joint_commands_[0]}; + CommandInterface joint_1_cmd_{joint_name_, T::value, &joint_commands_[0]}; }; } // anonymous namespace From 4e917db2474ae84573165fc0414ecaccbf8698b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Mon, 11 Sep 2023 11:28:37 +0200 Subject: [PATCH 107/238] [JTC] Make most parameters read-only (#771) --- joint_trajectory_controller/CMakeLists.txt | 3 +- .../src/joint_trajectory_controller.cpp | 2 +- ...oint_trajectory_controller_parameters.yaml | 7 +++ .../test_joint_trajectory_controller.yaml | 12 ----- .../test/test_trajectory_actions.cpp | 3 +- .../test/test_trajectory_controller.cpp | 49 +++++++++---------- .../test/test_trajectory_controller_utils.hpp | 35 ++++++------- 7 files changed, 47 insertions(+), 64 deletions(-) delete mode 100644 joint_trajectory_controller/test/config/test_joint_trajectory_controller.yaml diff --git a/joint_trajectory_controller/CMakeLists.txt b/joint_trajectory_controller/CMakeLists.txt index 0552e0bc86..88bb7891a3 100644 --- a/joint_trajectory_controller/CMakeLists.txt +++ b/joint_trajectory_controller/CMakeLists.txt @@ -60,8 +60,7 @@ if(BUILD_TESTING) target_link_libraries(test_trajectory joint_trajectory_controller) ament_add_gmock(test_trajectory_controller - test/test_trajectory_controller.cpp - ENV config_file=${CMAKE_CURRENT_SOURCE_DIR}/test/config/test_joint_trajectory_controller.yaml) + test/test_trajectory_controller.cpp) set_tests_properties(test_trajectory_controller PROPERTIES TIMEOUT 220) target_link_libraries(test_trajectory_controller joint_trajectory_controller diff --git a/joint_trajectory_controller/src/joint_trajectory_controller.cpp b/joint_trajectory_controller/src/joint_trajectory_controller.cpp index 92b3b5af8d..7e1cd04a15 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller.cpp +++ b/joint_trajectory_controller/src/joint_trajectory_controller.cpp @@ -951,7 +951,7 @@ controller_interface::CallbackReturn JointTrajectoryController::on_activate( last_commanded_state_ = state; } - // Should the controller start by holding position after on_configure? + // Should the controller start by holding position at the beginning of active state? if (params_.start_with_holding) { add_new_trajectory_msg(set_hold_position()); diff --git a/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml b/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml index 5b8a8d14f2..0daf3f41bd 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml +++ b/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml @@ -3,6 +3,7 @@ joint_trajectory_controller: type: string_array, default_value: [], description: "Names of joints used by the controller", + read_only: true, validation: { unique<>: null, } @@ -11,6 +12,7 @@ joint_trajectory_controller: type: string_array, default_value: [], description: "Names of the commanding joints used by the controller", + read_only: true, validation: { unique<>: null, } @@ -19,6 +21,7 @@ joint_trajectory_controller: type: string_array, default_value: [], description: "Names of command interfaces to claim", + read_only: true, validation: { unique<>: null, subset_of<>: [["position", "velocity", "acceleration", "effort",]], @@ -29,6 +32,7 @@ joint_trajectory_controller: type: string_array, default_value: [], description: "Names of state interfaces to claim", + read_only: true, validation: { unique<>: null, subset_of<>: [["position", "velocity", "acceleration",]], @@ -44,6 +48,7 @@ joint_trajectory_controller: type: bool, default_value: false, description: "Run the controller in open-loop, i.e., read hardware states only when starting controller. This is useful when robot is not exactly following the commanded trajectory.", + read_only: true, } allow_integration_in_goal_trajectories: { type: bool, @@ -54,6 +59,7 @@ joint_trajectory_controller: type: double, default_value: 20.0, description: "Rate status changes will be monitored", + read_only: true, validation: { gt_eq: [0.1] } @@ -62,6 +68,7 @@ joint_trajectory_controller: type: string, default_value: "splines", description: "The type of interpolation to use, if any", + read_only: true, validation: { one_of<>: [["splines", "none"]], } diff --git a/joint_trajectory_controller/test/config/test_joint_trajectory_controller.yaml b/joint_trajectory_controller/test/config/test_joint_trajectory_controller.yaml deleted file mode 100644 index 09a134e06a..0000000000 --- a/joint_trajectory_controller/test/config/test_joint_trajectory_controller.yaml +++ /dev/null @@ -1,12 +0,0 @@ -test_joint_trajectory_controller: - joints: - - joint1 - - joint2 - - joint3 - - command_interfaces: - - position - - state_interfaces: - - position - - velocity diff --git a/joint_trajectory_controller/test/test_trajectory_actions.cpp b/joint_trajectory_controller/test/test_trajectory_actions.cpp index 2c28319d52..fc24c2c029 100644 --- a/joint_trajectory_controller/test/test_trajectory_actions.cpp +++ b/joint_trajectory_controller/test/test_trajectory_actions.cpp @@ -72,8 +72,7 @@ class TestTrajectoryActions : public TrajectoryControllerTest { setup_executor_ = true; - SetUpAndActivateTrajectoryController( - executor_, true, parameters, separate_cmd_and_state_values); + SetUpAndActivateTrajectoryController(executor_, parameters, separate_cmd_and_state_values); SetUpActionClient(); diff --git a/joint_trajectory_controller/test/test_trajectory_controller.cpp b/joint_trajectory_controller/test/test_trajectory_controller.cpp index 7850f15183..e0655d2368 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller.cpp +++ b/joint_trajectory_controller/test/test_trajectory_controller.cpp @@ -138,11 +138,9 @@ TEST_P(TrajectoryControllerTestParameterized, check_interface_names) TEST_P(TrajectoryControllerTestParameterized, check_interface_names_with_command_joints) { rclcpp::executors::MultiThreadedExecutor executor; - SetUpTrajectoryController(executor); - // set command_joints parameter const rclcpp::Parameter command_joint_names_param("command_joints", command_joint_names_); - traj_controller_->get_node()->set_parameter({command_joint_names_param}); + SetUpTrajectoryController(executor, {command_joint_names_param}); const auto state = traj_controller_->get_node()->configure(); ASSERT_EQ(state.id(), State::PRIMARY_STATE_INACTIVE); @@ -206,7 +204,7 @@ TEST_P(TrajectoryControllerTestParameterized, cleanup) rclcpp::executors::MultiThreadedExecutor executor; std::vector params = { rclcpp::Parameter("allow_nonzero_velocity_at_trajectory_end", true)}; - SetUpAndActivateTrajectoryController(executor, true, params); + SetUpAndActivateTrajectoryController(executor, params); // send msg constexpr auto FIRST_POINT_TIME = std::chrono::milliseconds(250); @@ -252,12 +250,11 @@ TEST_P(TrajectoryControllerTestParameterized, cleanup_after_configure) TEST_P(TrajectoryControllerTestParameterized, correct_initialization_using_parameters) { rclcpp::executors::MultiThreadedExecutor executor; - SetUpTrajectoryController(executor, false); + SetUpTrajectoryController(executor); traj_controller_->get_node()->set_parameter( rclcpp::Parameter("allow_nonzero_velocity_at_trajectory_end", true)); // This call is replacing the way parameters are set via launch - SetParameters(); traj_controller_->configure(); auto state = traj_controller_->get_state(); ASSERT_EQ(State::PRIMARY_STATE_INACTIVE, state.id()); @@ -324,7 +321,7 @@ TEST_P(TrajectoryControllerTestParameterized, correct_initialization_using_param TEST_P(TrajectoryControllerTestParameterized, state_topic_consistency) { rclcpp::executors::SingleThreadedExecutor executor; - SetUpAndActivateTrajectoryController(executor, true, {}); + SetUpAndActivateTrajectoryController(executor, {}); subscribeToState(); updateController(); @@ -426,7 +423,7 @@ TEST_P(TrajectoryControllerTestParameterized, no_hold_on_startup) rclcpp::executors::MultiThreadedExecutor executor; rclcpp::Parameter start_with_holding_parameter("start_with_holding", false); - SetUpAndActivateTrajectoryController(executor, true, {start_with_holding_parameter}); + SetUpAndActivateTrajectoryController(executor, {start_with_holding_parameter}); constexpr auto FIRST_POINT_TIME = std::chrono::milliseconds(250); updateController(rclcpp::Duration(FIRST_POINT_TIME)); @@ -444,7 +441,7 @@ TEST_P(TrajectoryControllerTestParameterized, hold_on_startup) rclcpp::executors::MultiThreadedExecutor executor; rclcpp::Parameter start_with_holding_parameter("start_with_holding", true); - SetUpAndActivateTrajectoryController(executor, true, {start_with_holding_parameter}); + SetUpAndActivateTrajectoryController(executor, {start_with_holding_parameter}); constexpr auto FIRST_POINT_TIME = std::chrono::milliseconds(250); updateController(rclcpp::Duration(FIRST_POINT_TIME)); @@ -468,7 +465,7 @@ TEST_P(TrajectoryControllerTestParameterized, position_error_not_normalized) constexpr double k_p = 10.0; std::vector params = { rclcpp::Parameter("allow_nonzero_velocity_at_trajectory_end", true)}; - SetUpAndActivateTrajectoryController(executor, true, params, true, k_p, 0.0, false); + SetUpAndActivateTrajectoryController(executor, params, true, k_p, 0.0, false); subscribeToState(); size_t n_joints = joint_names_.size(); @@ -577,7 +574,7 @@ TEST_P(TrajectoryControllerTestParameterized, position_error_normalized) constexpr double k_p = 10.0; std::vector params = { rclcpp::Parameter("allow_nonzero_velocity_at_trajectory_end", true)}; - SetUpAndActivateTrajectoryController(executor, true, params, true, k_p, 0.0, true); + SetUpAndActivateTrajectoryController(executor, params, true, k_p, 0.0, true); subscribeToState(); size_t n_joints = joint_names_.size(); @@ -720,7 +717,7 @@ TEST_P(TrajectoryControllerTestParameterized, use_closed_loop_pid) TEST_P(TrajectoryControllerTestParameterized, velocity_error) { rclcpp::executors::MultiThreadedExecutor executor; - SetUpAndActivateTrajectoryController(executor, true, {}, true); + SetUpAndActivateTrajectoryController(executor, {}, true); subscribeToState(); size_t n_joints = joint_names_.size(); @@ -846,7 +843,7 @@ TEST_P(TrajectoryControllerTestParameterized, test_partial_joint_list) rclcpp::Parameter partial_joints_parameters("allow_partial_joints_goal", true); rclcpp::executors::SingleThreadedExecutor executor; - SetUpAndActivateTrajectoryController(executor, true, {partial_joints_parameters}); + SetUpAndActivateTrajectoryController(executor, {partial_joints_parameters}); const double initial_joint1_cmd = joint_pos_[0]; const double initial_joint2_cmd = joint_pos_[1]; @@ -918,7 +915,7 @@ TEST_P(TrajectoryControllerTestParameterized, test_partial_joint_list_not_allowe rclcpp::Parameter partial_joints_parameters("allow_partial_joints_goal", false); rclcpp::executors::SingleThreadedExecutor executor; - SetUpAndActivateTrajectoryController(executor, true, {partial_joints_parameters}); + SetUpAndActivateTrajectoryController(executor, {partial_joints_parameters}); const double initial_joint1_cmd = joint_pos_[0]; const double initial_joint2_cmd = joint_pos_[1]; @@ -1000,7 +997,7 @@ TEST_P(TrajectoryControllerTestParameterized, invalid_message) rclcpp::Parameter allow_integration_parameters("allow_integration_in_goal_trajectories", false); rclcpp::executors::SingleThreadedExecutor executor; SetUpAndActivateTrajectoryController( - executor, true, {partial_joints_parameters, allow_integration_parameters}); + executor, {partial_joints_parameters, allow_integration_parameters}); trajectory_msgs::msg::JointTrajectory traj_msg, good_traj_msg; @@ -1061,7 +1058,7 @@ TEST_P(TrajectoryControllerTestParameterized, missing_positions_message_accepted { rclcpp::Parameter allow_integration_parameters("allow_integration_in_goal_trajectories", true); rclcpp::executors::SingleThreadedExecutor executor; - SetUpAndActivateTrajectoryController(executor, true, {allow_integration_parameters}); + SetUpAndActivateTrajectoryController(executor, {allow_integration_parameters}); trajectory_msgs::msg::JointTrajectory traj_msg, good_traj_msg; @@ -1123,7 +1120,7 @@ TEST_P(TrajectoryControllerTestParameterized, test_trajectory_replace) { rclcpp::executors::SingleThreadedExecutor executor; rclcpp::Parameter partial_joints_parameters("allow_partial_joints_goal", true); - SetUpAndActivateTrajectoryController(executor, true, {partial_joints_parameters}); + SetUpAndActivateTrajectoryController(executor, {partial_joints_parameters}); subscribeToState(); @@ -1166,7 +1163,7 @@ TEST_P(TrajectoryControllerTestParameterized, test_trajectory_replace) TEST_P(TrajectoryControllerTestParameterized, test_ignore_old_trajectory) { rclcpp::executors::SingleThreadedExecutor executor; - SetUpAndActivateTrajectoryController(executor, true, {}); + SetUpAndActivateTrajectoryController(executor, {}); subscribeToState(); // TODO(anyone): add expectations for velocities and accelerations @@ -1196,7 +1193,7 @@ TEST_P(TrajectoryControllerTestParameterized, test_ignore_old_trajectory) TEST_P(TrajectoryControllerTestParameterized, test_ignore_partial_old_trajectory) { rclcpp::executors::SingleThreadedExecutor executor; - SetUpAndActivateTrajectoryController(executor, true, {}); + SetUpAndActivateTrajectoryController(executor, {}); subscribeToState(); std::vector> points_old{{{2., 3., 4.}, {4., 5., 6.}}}; @@ -1229,7 +1226,7 @@ TEST_P(TrajectoryControllerTestParameterized, test_execute_partial_traj_in_futur { rclcpp::Parameter partial_joints_parameters("allow_partial_joints_goal", true); rclcpp::executors::SingleThreadedExecutor executor; - SetUpAndActivateTrajectoryController(executor, true, {partial_joints_parameters}); + SetUpAndActivateTrajectoryController(executor, {partial_joints_parameters}); subscribeToState(); RCLCPP_WARN( @@ -1289,7 +1286,7 @@ TEST_P(TrajectoryControllerTestParameterized, test_jump_when_state_tracking_erro rclcpp::executors::SingleThreadedExecutor executor; // default if false so it will not be actually set parameter rclcpp::Parameter is_open_loop_parameters("open_loop_control", false); - SetUpAndActivateTrajectoryController(executor, true, {is_open_loop_parameters}, true); + SetUpAndActivateTrajectoryController(executor, {is_open_loop_parameters}, true); // goal setup std::vector first_goal = {3.3, 4.4, 5.5}; @@ -1390,7 +1387,7 @@ TEST_P(TrajectoryControllerTestParameterized, test_no_jump_when_state_tracking_e { rclcpp::executors::SingleThreadedExecutor executor; rclcpp::Parameter is_open_loop_parameters("open_loop_control", true); - SetUpAndActivateTrajectoryController(executor, true, {is_open_loop_parameters}, true); + SetUpAndActivateTrajectoryController(executor, {is_open_loop_parameters}, true); // goal setup std::vector first_goal = {3.3, 4.4, 5.5}; @@ -1488,7 +1485,7 @@ TEST_P(TrajectoryControllerTestParameterized, test_hw_states_has_offset_first_co joint_vel_[i] = std::numeric_limits::quiet_NaN(); joint_acc_[i] = std::numeric_limits::quiet_NaN(); } - SetUpAndActivateTrajectoryController(executor, true, {is_open_loop_parameters}, true); + SetUpAndActivateTrajectoryController(executor, {is_open_loop_parameters}, true); auto current_state_when_offset = traj_controller_->get_current_state_when_offset(); @@ -1535,7 +1532,7 @@ TEST_P(TrajectoryControllerTestParameterized, test_hw_states_has_offset_later_co joint_vel_[i] = 0.25 + static_cast(i); joint_acc_[i] = 0.02 + static_cast(i) / 10.0; } - SetUpAndActivateTrajectoryController(executor, true, {is_open_loop_parameters}, true); + SetUpAndActivateTrajectoryController(executor, {is_open_loop_parameters}, true); auto current_state_when_offset = traj_controller_->get_current_state_when_offset(); @@ -1577,7 +1574,7 @@ TEST_P(TrajectoryControllerTestParameterized, test_state_tolerances_fail) rclcpp::Parameter("constraints.joint3.trajectory", state_tol)}; rclcpp::executors::MultiThreadedExecutor executor; - SetUpAndActivateTrajectoryController(executor, false, {params}, true); + SetUpAndActivateTrajectoryController(executor, params, true); // send msg constexpr auto FIRST_POINT_TIME = std::chrono::milliseconds(100); @@ -1609,7 +1606,7 @@ TEST_P(TrajectoryControllerTestParameterized, test_goal_tolerances_fail) rclcpp::Parameter("constraints.goal_time", goal_time)}; rclcpp::executors::MultiThreadedExecutor executor; - SetUpAndActivateTrajectoryController(executor, false, {params}, true); + SetUpAndActivateTrajectoryController(executor, params, true); // send msg constexpr auto FIRST_POINT_TIME = std::chrono::milliseconds(100); diff --git a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp index 8a22f986aa..59d20c33d2 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp +++ b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp @@ -162,32 +162,26 @@ class TrajectoryControllerTest : public ::testing::Test controller_name_ + "/joint_trajectory", rclcpp::SystemDefaultsQoS()); } - void SetUpTrajectoryController(rclcpp::Executor & executor, bool use_local_parameters = true) + void SetUpTrajectoryController( + rclcpp::Executor & executor, const std::vector & parameters = {}) { traj_controller_ = std::make_shared(); - if (use_local_parameters) - { - traj_controller_->set_joint_names(joint_names_); - traj_controller_->set_command_interfaces(command_interface_types_); - traj_controller_->set_state_interfaces(state_interface_types_); - } - auto ret = traj_controller_->init(controller_name_); + auto node_options = rclcpp::NodeOptions(); + std::vector parameter_overrides; + parameter_overrides.push_back(rclcpp::Parameter("joints", joint_names_)); + parameter_overrides.push_back( + rclcpp::Parameter("command_interfaces", command_interface_types_)); + parameter_overrides.push_back(rclcpp::Parameter("state_interfaces", state_interface_types_)); + parameter_overrides.insert(parameter_overrides.end(), parameters.begin(), parameters.end()); + node_options.parameter_overrides(parameter_overrides); + + auto ret = traj_controller_->init(controller_name_, "", node_options); if (ret != controller_interface::return_type::OK) { FAIL(); } executor.add_node(traj_controller_->get_node()->get_node_base_interface()); - SetParameters(); - } - - void SetParameters() - { - auto node = traj_controller_->get_node(); - const rclcpp::Parameter joint_names_param("joints", joint_names_); - const rclcpp::Parameter cmd_interfaces_params("command_interfaces", command_interface_types_); - const rclcpp::Parameter state_interfaces_params("state_interfaces", state_interface_types_); - node->set_parameters({joint_names_param, cmd_interfaces_params, state_interfaces_params}); } void SetPidParameters( @@ -210,12 +204,11 @@ class TrajectoryControllerTest : public ::testing::Test } void SetUpAndActivateTrajectoryController( - rclcpp::Executor & executor, bool use_local_parameters = true, - const std::vector & parameters = {}, + rclcpp::Executor & executor, const std::vector & parameters = {}, bool separate_cmd_and_state_values = false, double k_p = 0.0, double ff = 1.0, bool normalize_error = false) { - SetUpTrajectoryController(executor, use_local_parameters); + SetUpTrajectoryController(executor); // set pid parameters before configure SetPidParameters(k_p, ff, normalize_error); From be3b6c1867516b892a3a5e3a076fd330379fce8f Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Mon, 11 Sep 2023 14:46:16 +0100 Subject: [PATCH 108/238] Update changelogs --- ackermann_steering_controller/CHANGELOG.rst | 3 + admittance_controller/CHANGELOG.rst | 5 + bicycle_steering_controller/CHANGELOG.rst | 3 + diff_drive_controller/CHANGELOG.rst | 5 + effort_controllers/CHANGELOG.rst | 3 + force_torque_sensor_broadcaster/CHANGELOG.rst | 5 + forward_command_controller/CHANGELOG.rst | 3 + gripper_controllers/CHANGELOG.rst | 6 + imu_sensor_broadcaster/CHANGELOG.rst | 3 + joint_state_broadcaster/CHANGELOG.rst | 3 + joint_trajectory_controller/CHANGELOG.rst | 5 + position_controllers/CHANGELOG.rst | 3 + range_sensor_broadcaster/CHANGELOG.rst | 149 ++++++++++++++++++ ros2_controllers/CHANGELOG.rst | 5 + ros2_controllers_test_nodes/CHANGELOG.rst | 3 + rqt_joint_trajectory_controller/CHANGELOG.rst | 3 + steering_controllers_library/CHANGELOG.rst | 3 + tricycle_controller/CHANGELOG.rst | 3 + tricycle_steering_controller/CHANGELOG.rst | 3 + velocity_controllers/CHANGELOG.rst | 3 + 20 files changed, 219 insertions(+) create mode 100644 range_sensor_broadcaster/CHANGELOG.rst diff --git a/ackermann_steering_controller/CHANGELOG.rst b/ackermann_steering_controller/CHANGELOG.rst index cad245cc4e..6aec45a94b 100644 --- a/ackermann_steering_controller/CHANGELOG.rst +++ b/ackermann_steering_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ackermann_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.14.0 (2023-08-16) ------------------- diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index 79c80f357e..0bfc81e20d 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Update docs for diff drive controller (`#751 `_) +* Contributors: Christoph Fröhlich + 3.14.0 (2023-08-16) ------------------- diff --git a/bicycle_steering_controller/CHANGELOG.rst b/bicycle_steering_controller/CHANGELOG.rst index 0569a0fe8d..7798499535 100644 --- a/bicycle_steering_controller/CHANGELOG.rst +++ b/bicycle_steering_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package bicycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.14.0 (2023-08-16) ------------------- diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index e12543aa85..e1e9ef0f14 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Update docs for diff drive controller (`#751 `_) +* Contributors: Christoph Fröhlich + 3.14.0 (2023-08-16) ------------------- diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index adc12b0caf..2b57ffdaed 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.14.0 (2023-08-16) ------------------- diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index 6ae71de6a6..261cdd2406 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* [ForceTorqueSensorBroadcaster] Create ParamListener and get parameters on configure (`#698 `_) +* Contributors: Noel Jiménez García + 3.14.0 (2023-08-16) ------------------- diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index 35ad79d4f2..e7adf8759a 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.14.0 (2023-08-16) ------------------- * Use tabs (`#743 `_) diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index 28e73faf8c..2535205c0e 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add test for effort gripper controller (`#769 `_) +* Fixed implementation so that effort_controllers/GripperActionController works. (`#756 `_) +* Contributors: chama1176 + 3.14.0 (2023-08-16) ------------------- diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index 9443ee51c2..eee2391f3c 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.14.0 (2023-08-16) ------------------- diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index 9ebf7177ba..9d277af9d6 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.14.0 (2023-08-16) ------------------- diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index 88df65577c..9e55d425b6 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* [JTC] Make most parameters read-only (`#771 `_) +* Contributors: Christoph Fröhlich + 3.14.0 (2023-08-16) ------------------- * [JTC] Tolerance tests + Hold on time violation (`#613 `_) diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index 7dcb2aadaa..92e530b5dc 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.14.0 (2023-08-16) ------------------- diff --git a/range_sensor_broadcaster/CHANGELOG.rst b/range_sensor_broadcaster/CHANGELOG.rst new file mode 100644 index 0000000000..76e55d05f0 --- /dev/null +++ b/range_sensor_broadcaster/CHANGELOG.rst @@ -0,0 +1,149 @@ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Changelog for package range_sensor_broadcaster +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Forthcoming +----------- +* add a broadcaster for range sensor (`#725 `_) +* Contributors: flochre + +3.14.0 (2023-08-16) +------------------- + +3.13.0 (2023-08-04) +------------------- + +3.12.0 (2023-07-18) +------------------- + +3.11.0 (2023-06-24) +------------------- + +3.10.1 (2023-06-06) +------------------- + +3.10.0 (2023-06-04) +------------------- + +3.9.0 (2023-05-28) +------------------ + +3.8.0 (2023-05-14) +------------------ + +3.7.0 (2023-05-02) +------------------ + +3.6.0 (2023-04-29) +------------------ + +3.5.0 (2023-04-14) +------------------ + +3.4.0 (2023-04-02) +------------------ + +3.3.0 (2023-03-07) +------------------ + +3.2.0 (2023-02-10) +------------------ + +3.1.0 (2023-01-26) +------------------ + +3.0.0 (2023-01-19) +------------------ + +2.15.0 (2022-12-06) +------------------- + +2.14.0 (2022-11-18) +------------------- + +2.13.0 (2022-10-05) +------------------- + +2.12.0 (2022-09-01) +------------------- + +2.11.0 (2022-08-04) +------------------- + +2.10.0 (2022-08-01) +------------------- + +2.9.0 (2022-07-14) +------------------ + +2.8.0 (2022-07-09) +------------------ + +2.7.0 (2022-07-03) +------------------ + +2.6.0 (2022-06-18) +------------------ + +2.5.0 (2022-05-13) +------------------ + +2.4.0 (2022-04-29) +------------------ + +2.3.0 (2022-04-21) +------------------ + +2.2.0 (2022-03-25) +------------------ + +2.1.0 (2022-02-23) +------------------ + +2.0.1 (2022-02-01) +------------------ + +2.0.0 (2022-01-28) +------------------ + +1.3.0 (2022-01-11) +------------------ + +1.2.0 (2021-12-29) +------------------ + +1.1.0 (2021-10-25) +------------------ + +1.0.0 (2021-09-29) +------------------ + +0.5.0 (2021-08-30) +------------------ + +0.4.1 (2021-07-08) +------------------ + +0.4.0 (2021-06-28) +------------------ + +0.3.1 (2021-05-23) +------------------ + +0.3.0 (2021-05-21) +------------------ + +0.2.1 (2021-05-03) +------------------ + +0.2.0 (2021-02-06) +------------------ + +0.1.2 (2021-01-07) +------------------ + +0.1.1 (2021-01-06) +------------------ + +0.1.0 (2020-12-23) +------------------ diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index b1758acc83..2f35c7568b 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* add a broadcaster for range sensor (`#725 `_) +* Contributors: flochre + 3.14.0 (2023-08-16) ------------------- diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index 3c92dbdb61..742a89fb40 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.14.0 (2023-08-16) ------------------- diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index d931108078..1ebf3a133a 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.14.0 (2023-08-16) ------------------- diff --git a/steering_controllers_library/CHANGELOG.rst b/steering_controllers_library/CHANGELOG.rst index 033fddb95a..44273d2561 100644 --- a/steering_controllers_library/CHANGELOG.rst +++ b/steering_controllers_library/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package steering_controllers_library ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.14.0 (2023-08-16) ------------------- diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index df31f03c74..b64fdaedbc 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.14.0 (2023-08-16) ------------------- diff --git a/tricycle_steering_controller/CHANGELOG.rst b/tricycle_steering_controller/CHANGELOG.rst index 8fc50f7378..7431aa9160 100644 --- a/tricycle_steering_controller/CHANGELOG.rst +++ b/tricycle_steering_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package tricycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.14.0 (2023-08-16) ------------------- diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index 49b945c3dc..5bc0a93bd2 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.14.0 (2023-08-16) ------------------- From ab1f935236565f27a08e9579196523d770d72173 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Mon, 11 Sep 2023 14:46:45 +0100 Subject: [PATCH 109/238] 3.15.0 --- ackermann_steering_controller/CHANGELOG.rst | 4 ++-- ackermann_steering_controller/package.xml | 2 +- admittance_controller/CHANGELOG.rst | 4 ++-- admittance_controller/package.xml | 2 +- bicycle_steering_controller/CHANGELOG.rst | 4 ++-- bicycle_steering_controller/package.xml | 2 +- diff_drive_controller/CHANGELOG.rst | 4 ++-- diff_drive_controller/package.xml | 2 +- effort_controllers/CHANGELOG.rst | 4 ++-- effort_controllers/package.xml | 2 +- force_torque_sensor_broadcaster/CHANGELOG.rst | 4 ++-- force_torque_sensor_broadcaster/package.xml | 2 +- forward_command_controller/CHANGELOG.rst | 4 ++-- forward_command_controller/package.xml | 2 +- gripper_controllers/CHANGELOG.rst | 4 ++-- gripper_controllers/package.xml | 2 +- imu_sensor_broadcaster/CHANGELOG.rst | 4 ++-- imu_sensor_broadcaster/package.xml | 2 +- joint_state_broadcaster/CHANGELOG.rst | 4 ++-- joint_state_broadcaster/package.xml | 2 +- joint_trajectory_controller/CHANGELOG.rst | 4 ++-- joint_trajectory_controller/package.xml | 2 +- position_controllers/CHANGELOG.rst | 4 ++-- position_controllers/package.xml | 2 +- range_sensor_broadcaster/CHANGELOG.rst | 4 ++-- range_sensor_broadcaster/package.xml | 2 +- ros2_controllers/CHANGELOG.rst | 4 ++-- ros2_controllers/package.xml | 2 +- ros2_controllers_test_nodes/CHANGELOG.rst | 4 ++-- ros2_controllers_test_nodes/package.xml | 2 +- ros2_controllers_test_nodes/setup.py | 2 +- rqt_joint_trajectory_controller/CHANGELOG.rst | 4 ++-- rqt_joint_trajectory_controller/package.xml | 2 +- rqt_joint_trajectory_controller/setup.py | 2 +- steering_controllers_library/CHANGELOG.rst | 4 ++-- steering_controllers_library/package.xml | 2 +- tricycle_controller/CHANGELOG.rst | 4 ++-- tricycle_controller/package.xml | 2 +- tricycle_steering_controller/CHANGELOG.rst | 4 ++-- tricycle_steering_controller/package.xml | 2 +- velocity_controllers/CHANGELOG.rst | 4 ++-- velocity_controllers/package.xml | 2 +- 42 files changed, 62 insertions(+), 62 deletions(-) diff --git a/ackermann_steering_controller/CHANGELOG.rst b/ackermann_steering_controller/CHANGELOG.rst index 6aec45a94b..723ca88779 100644 --- a/ackermann_steering_controller/CHANGELOG.rst +++ b/ackermann_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ackermann_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.15.0 (2023-09-11) +------------------- 3.14.0 (2023-08-16) ------------------- diff --git a/ackermann_steering_controller/package.xml b/ackermann_steering_controller/package.xml index 1301b19bc9..40a3545b99 100644 --- a/ackermann_steering_controller/package.xml +++ b/ackermann_steering_controller/package.xml @@ -2,7 +2,7 @@ ackermann_steering_controller - 3.14.0 + 3.15.0 Steering controller for Ackermann kinematics. Rear fixed wheels are powering the vehicle and front wheels are steering it. Apache License 2.0 Bence Magyar diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index 0bfc81e20d..593fa56562 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.15.0 (2023-09-11) +------------------- * Update docs for diff drive controller (`#751 `_) * Contributors: Christoph Fröhlich diff --git a/admittance_controller/package.xml b/admittance_controller/package.xml index 4ea34b3852..9f2de80dad 100644 --- a/admittance_controller/package.xml +++ b/admittance_controller/package.xml @@ -2,7 +2,7 @@ admittance_controller - 3.14.0 + 3.15.0 Implementation of admittance controllers for different input and output interface. Denis Štogl Bence Magyar diff --git a/bicycle_steering_controller/CHANGELOG.rst b/bicycle_steering_controller/CHANGELOG.rst index 7798499535..be6ac52313 100644 --- a/bicycle_steering_controller/CHANGELOG.rst +++ b/bicycle_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package bicycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.15.0 (2023-09-11) +------------------- 3.14.0 (2023-08-16) ------------------- diff --git a/bicycle_steering_controller/package.xml b/bicycle_steering_controller/package.xml index 1b9844a090..ddc110f81a 100644 --- a/bicycle_steering_controller/package.xml +++ b/bicycle_steering_controller/package.xml @@ -2,7 +2,7 @@ bicycle_steering_controller - 3.14.0 + 3.15.0 Steering controller with bicycle kinematics. Rear fixed wheel is powering the vehicle and front wheel is steering. Apache License 2.0 Bence Magyar diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index e1e9ef0f14..52c8572739 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.15.0 (2023-09-11) +------------------- * Update docs for diff drive controller (`#751 `_) * Contributors: Christoph Fröhlich diff --git a/diff_drive_controller/package.xml b/diff_drive_controller/package.xml index df4d92a19b..cc849d12ef 100644 --- a/diff_drive_controller/package.xml +++ b/diff_drive_controller/package.xml @@ -1,7 +1,7 @@ diff_drive_controller - 3.14.0 + 3.15.0 Controller for a differential drive mobile base. Bence Magyar Jordan Palacios diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index 2b57ffdaed..4b93f1f69a 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.15.0 (2023-09-11) +------------------- 3.14.0 (2023-08-16) ------------------- diff --git a/effort_controllers/package.xml b/effort_controllers/package.xml index 6edbd5454a..d0aca9701a 100644 --- a/effort_controllers/package.xml +++ b/effort_controllers/package.xml @@ -1,7 +1,7 @@ effort_controllers - 3.14.0 + 3.15.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index 261cdd2406..296cad54bf 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.15.0 (2023-09-11) +------------------- * [ForceTorqueSensorBroadcaster] Create ParamListener and get parameters on configure (`#698 `_) * Contributors: Noel Jiménez García diff --git a/force_torque_sensor_broadcaster/package.xml b/force_torque_sensor_broadcaster/package.xml index 3907edbd31..4cbad1c014 100644 --- a/force_torque_sensor_broadcaster/package.xml +++ b/force_torque_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ force_torque_sensor_broadcaster - 3.14.0 + 3.15.0 Controller to publish state of force-torque sensors. Bence Magyar Denis Štogl diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index e7adf8759a..b3d33964b6 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.15.0 (2023-09-11) +------------------- 3.14.0 (2023-08-16) ------------------- diff --git a/forward_command_controller/package.xml b/forward_command_controller/package.xml index 522964019b..af90230c7e 100644 --- a/forward_command_controller/package.xml +++ b/forward_command_controller/package.xml @@ -1,7 +1,7 @@ forward_command_controller - 3.14.0 + 3.15.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index 2535205c0e..82cf6cf45b 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.15.0 (2023-09-11) +------------------- * Add test for effort gripper controller (`#769 `_) * Fixed implementation so that effort_controllers/GripperActionController works. (`#756 `_) * Contributors: chama1176 diff --git a/gripper_controllers/package.xml b/gripper_controllers/package.xml index 5804d3919b..d3c8d9bf9f 100644 --- a/gripper_controllers/package.xml +++ b/gripper_controllers/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> gripper_controllers - 3.14.0 + 3.15.0 The gripper_controllers package Bence Magyar diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index eee2391f3c..915544197c 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.15.0 (2023-09-11) +------------------- 3.14.0 (2023-08-16) ------------------- diff --git a/imu_sensor_broadcaster/package.xml b/imu_sensor_broadcaster/package.xml index 8d26b48211..31684ec958 100644 --- a/imu_sensor_broadcaster/package.xml +++ b/imu_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ imu_sensor_broadcaster - 3.14.0 + 3.15.0 Controller to publish readings of IMU sensors. Bence Magyar Denis Štogl diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index 9d277af9d6..57bc1b7f45 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.15.0 (2023-09-11) +------------------- 3.14.0 (2023-08-16) ------------------- diff --git a/joint_state_broadcaster/package.xml b/joint_state_broadcaster/package.xml index 919bac78f8..248dbcb099 100644 --- a/joint_state_broadcaster/package.xml +++ b/joint_state_broadcaster/package.xml @@ -1,7 +1,7 @@ joint_state_broadcaster - 3.14.0 + 3.15.0 Broadcaster to publish joint state Bence Magyar Denis Stogl diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index 9e55d425b6..8b1a1c6a54 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.15.0 (2023-09-11) +------------------- * [JTC] Make most parameters read-only (`#771 `_) * Contributors: Christoph Fröhlich diff --git a/joint_trajectory_controller/package.xml b/joint_trajectory_controller/package.xml index 2941e11a56..521aa0ea9d 100644 --- a/joint_trajectory_controller/package.xml +++ b/joint_trajectory_controller/package.xml @@ -1,7 +1,7 @@ joint_trajectory_controller - 3.14.0 + 3.15.0 Controller for executing joint-space trajectories on a group of joints Bence Magyar Jordan Palacios diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index 92e530b5dc..5da7a35e1a 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.15.0 (2023-09-11) +------------------- 3.14.0 (2023-08-16) ------------------- diff --git a/position_controllers/package.xml b/position_controllers/package.xml index c88fc6ddc7..c947f00bdb 100644 --- a/position_controllers/package.xml +++ b/position_controllers/package.xml @@ -1,7 +1,7 @@ position_controllers - 3.14.0 + 3.15.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/range_sensor_broadcaster/CHANGELOG.rst b/range_sensor_broadcaster/CHANGELOG.rst index 76e55d05f0..6e63a22917 100644 --- a/range_sensor_broadcaster/CHANGELOG.rst +++ b/range_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package range_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.15.0 (2023-09-11) +------------------- * add a broadcaster for range sensor (`#725 `_) * Contributors: flochre diff --git a/range_sensor_broadcaster/package.xml b/range_sensor_broadcaster/package.xml index 11175d9f03..33ed7d5e4d 100644 --- a/range_sensor_broadcaster/package.xml +++ b/range_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ range_sensor_broadcaster - 3.14.0 + 3.15.0 Controller to publish readings of Range sensors. Bence Magyar Florent Chretien diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index 2f35c7568b..6684adfabc 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.15.0 (2023-09-11) +------------------- * add a broadcaster for range sensor (`#725 `_) * Contributors: flochre diff --git a/ros2_controllers/package.xml b/ros2_controllers/package.xml index 51d4d9ae44..ea2456486b 100644 --- a/ros2_controllers/package.xml +++ b/ros2_controllers/package.xml @@ -1,7 +1,7 @@ ros2_controllers - 3.14.0 + 3.15.0 Metapackage for ROS2 controllers related packages Bence Magyar Jordan Palacios diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index 742a89fb40..3caadb3880 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.15.0 (2023-09-11) +------------------- 3.14.0 (2023-08-16) ------------------- diff --git a/ros2_controllers_test_nodes/package.xml b/ros2_controllers_test_nodes/package.xml index f5b887b01d..845e65d233 100644 --- a/ros2_controllers_test_nodes/package.xml +++ b/ros2_controllers_test_nodes/package.xml @@ -2,7 +2,7 @@ ros2_controllers_test_nodes - 3.14.0 + 3.15.0 Demo nodes for showing and testing functionalities of the ros2_control framework. Denis Štogl diff --git a/ros2_controllers_test_nodes/setup.py b/ros2_controllers_test_nodes/setup.py index 2e1336e543..e4d9a72f89 100644 --- a/ros2_controllers_test_nodes/setup.py +++ b/ros2_controllers_test_nodes/setup.py @@ -20,7 +20,7 @@ setup( name=package_name, - version="3.14.0", + version="3.15.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index 1ebf3a133a..180dd35033 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.15.0 (2023-09-11) +------------------- 3.14.0 (2023-08-16) ------------------- diff --git a/rqt_joint_trajectory_controller/package.xml b/rqt_joint_trajectory_controller/package.xml index 122b55116b..9987061405 100644 --- a/rqt_joint_trajectory_controller/package.xml +++ b/rqt_joint_trajectory_controller/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> rqt_joint_trajectory_controller - 3.14.0 + 3.15.0 Graphical frontend for interacting with joint_trajectory_controller instances. Bence Magyar diff --git a/rqt_joint_trajectory_controller/setup.py b/rqt_joint_trajectory_controller/setup.py index 168d929a1c..0dea799d80 100644 --- a/rqt_joint_trajectory_controller/setup.py +++ b/rqt_joint_trajectory_controller/setup.py @@ -7,7 +7,7 @@ setup( name=package_name, - version="3.14.0", + version="3.15.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/steering_controllers_library/CHANGELOG.rst b/steering_controllers_library/CHANGELOG.rst index 44273d2561..4c4dae365d 100644 --- a/steering_controllers_library/CHANGELOG.rst +++ b/steering_controllers_library/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package steering_controllers_library ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.15.0 (2023-09-11) +------------------- 3.14.0 (2023-08-16) ------------------- diff --git a/steering_controllers_library/package.xml b/steering_controllers_library/package.xml index 302b1cbd90..48c137460b 100644 --- a/steering_controllers_library/package.xml +++ b/steering_controllers_library/package.xml @@ -2,7 +2,7 @@ steering_controllers_library - 3.14.0 + 3.15.0 Package for steering robot configurations including odometry and interfaces. Apache License 2.0 Bence Magyar diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index b64fdaedbc..625c0f4a06 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.15.0 (2023-09-11) +------------------- 3.14.0 (2023-08-16) ------------------- diff --git a/tricycle_controller/package.xml b/tricycle_controller/package.xml index d8e1b0e6e8..a53be880f2 100644 --- a/tricycle_controller/package.xml +++ b/tricycle_controller/package.xml @@ -2,7 +2,7 @@ tricycle_controller - 3.14.0 + 3.15.0 Controller for a tricycle drive mobile base Bence Magyar Tony Najjar diff --git a/tricycle_steering_controller/CHANGELOG.rst b/tricycle_steering_controller/CHANGELOG.rst index 7431aa9160..afe6360322 100644 --- a/tricycle_steering_controller/CHANGELOG.rst +++ b/tricycle_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package tricycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.15.0 (2023-09-11) +------------------- 3.14.0 (2023-08-16) ------------------- diff --git a/tricycle_steering_controller/package.xml b/tricycle_steering_controller/package.xml index 972300f590..f320c08c9f 100644 --- a/tricycle_steering_controller/package.xml +++ b/tricycle_steering_controller/package.xml @@ -2,7 +2,7 @@ tricycle_steering_controller - 3.14.0 + 3.15.0 Steering controller with tricycle kinematics. Rear fixed wheels are powering the vehicle and front wheel is steering. Apache License 2.0 Bence Magyar diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index 5bc0a93bd2..2551b76bd8 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.15.0 (2023-09-11) +------------------- 3.14.0 (2023-08-16) ------------------- diff --git a/velocity_controllers/package.xml b/velocity_controllers/package.xml index e626c9849a..d0b6cf0ed1 100644 --- a/velocity_controllers/package.xml +++ b/velocity_controllers/package.xml @@ -1,7 +1,7 @@ velocity_controllers - 3.14.0 + 3.15.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios From 923767fcf8df2ef82c313a5cfadb1e0fbe46cab2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Mon, 11 Sep 2023 17:40:15 +0200 Subject: [PATCH 110/238] [JTC] Add note on goal_time=0 in docs (#773) --- joint_trajectory_controller/doc/parameters.rst | 1 + .../src/joint_trajectory_controller_parameters.yaml | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/joint_trajectory_controller/doc/parameters.rst b/joint_trajectory_controller/doc/parameters.rst index d5ddb831ca..199f1b30dc 100644 --- a/joint_trajectory_controller/doc/parameters.rst +++ b/joint_trajectory_controller/doc/parameters.rst @@ -78,6 +78,7 @@ constraints.stopped_velocity_tolerance (double) constraints.goal_time (double) Maximally allowed tolerance for not reaching the end of the trajectory in a predefined time. + If set to zero, the controller will wait a potentially infinite amount of time. Default: 0.0 (not checked) diff --git a/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml b/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml index 0daf3f41bd..d299944976 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml +++ b/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml @@ -124,7 +124,8 @@ joint_trajectory_controller: goal_time: { type: double, default_value: 0.0, - description: "Time tolerance for achieving trajectory goal before or after commanded time.", + description: "Time tolerance for achieving trajectory goal before or after commanded time. + If set to zero, the controller will wait a potentially infinite amount of time.", validation: { gt_eq: [0.0], } From 66c5ac384bc3eac0ec5fb41fe92cdae9b3c5ac9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Tue, 12 Sep 2023 11:54:55 +0200 Subject: [PATCH 111/238] [JTC] Fix hold position mode with goal_time>0 (#758) --- .../joint_trajectory_controller.hpp | 4 + .../src/joint_trajectory_controller.cpp | 64 +++++++++------ .../test/test_trajectory_actions.cpp | 24 +++++- .../test/test_trajectory_controller.cpp | 12 ++- .../test/test_trajectory_controller_utils.hpp | 81 ++++++++++++++----- 5 files changed, 132 insertions(+), 53 deletions(-) diff --git a/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp b/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp index 1df557d029..1f805ee95b 100644 --- a/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp +++ b/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp @@ -174,6 +174,7 @@ class JointTrajectoryController : public controller_interface::ControllerInterfa // reserved storage for result of the command when closed loop pid adapter is used std::vector tmp_command_; + realtime_tools::RealtimeBuffer rt_is_holding_; ///< are we holding position? // TODO(karsten1987): eventually activate and deactivate subscriber directly when its supported bool subscriber_is_active_ = false; rclcpp::Subscription::SharedPtr joint_command_subscriber_ = @@ -187,6 +188,8 @@ class JointTrajectoryController : public controller_interface::ControllerInterfa realtime_tools::RealtimeBuffer> traj_msg_external_point_ptr_; + std::shared_ptr hold_position_msg_ptr_ = nullptr; + using ControllerStateMsg = control_msgs::msg::JointTrajectoryControllerState; using StatePublisher = realtime_tools::RealtimePublisher; using StatePublisherPtr = std::unique_ptr; @@ -270,6 +273,7 @@ class JointTrajectoryController : public controller_interface::ControllerInterfa bool contains_interface_type( const std::vector & interface_type_list, const std::string & interface_type); + void init_hold_position_msg(); void resize_joint_trajectory_point( trajectory_msgs::msg::JointTrajectoryPoint & point, size_t size); void resize_joint_trajectory_point_command( diff --git a/joint_trajectory_controller/src/joint_trajectory_controller.cpp b/joint_trajectory_controller/src/joint_trajectory_controller.cpp index 7e1cd04a15..229456c104 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller.cpp +++ b/joint_trajectory_controller/src/joint_trajectory_controller.cpp @@ -227,7 +227,8 @@ controller_interface::return_type JointTrajectoryController::update( if ( (before_last_point || first_sample) && !check_state_tolerance_per_joint( - state_error_, index, default_tolerances_.state_tolerance[index], false)) + state_error_, index, default_tolerances_.state_tolerance[index], false) && + *(rt_is_holding_.readFromRT()) == false) { tolerance_violated_while_moving = true; } @@ -235,7 +236,8 @@ controller_interface::return_type JointTrajectoryController::update( if ( !before_last_point && !check_state_tolerance_per_joint( - state_error_, index, default_tolerances_.goal_state_tolerance[index], false)) + state_error_, index, default_tolerances_.goal_state_tolerance[index], false) && + *(rt_is_holding_.readFromRT()) == false) { outside_goal_tolerance = true; @@ -805,6 +807,10 @@ controller_interface::CallbackReturn JointTrajectoryController::on_configure( logger, "Using '%s' interpolation method.", interpolation_methods::InterpolationMethodMap.at(interpolation_method_).c_str()); + // prepare hold_position_msg + init_hold_position_msg(); + + // create subscriber and publishers joint_command_subscriber_ = get_node()->create_subscription( "~/joint_trajectory", rclcpp::SystemDefaultsQoS(), @@ -956,6 +962,7 @@ controller_interface::CallbackReturn JointTrajectoryController::on_activate( { add_new_trajectory_msg(set_hold_position()); } + rt_is_holding_.writeFromNonRT(true); return CallbackReturn::SUCCESS; } @@ -1100,6 +1107,7 @@ void JointTrajectoryController::topic_callback( if (subscriber_is_active_) { add_new_trajectory_msg(msg); + rt_is_holding_.writeFromNonRT(false); } }; @@ -1162,6 +1170,7 @@ void JointTrajectoryController::goal_accepted_callback( std::make_shared(goal_handle->get_goal()->trajectory); add_new_trajectory_msg(traj_msg); + rt_is_holding_.writeFromNonRT(false); } // Update the active goal @@ -1456,31 +1465,12 @@ std::shared_ptr JointTrajectoryController::set_hold_position() { // Command to stay at current position - trajectory_msgs::msg::JointTrajectory current_pose_msg; - current_pose_msg.header.stamp = - rclcpp::Time(0.0, 0.0, get_node()->get_clock()->get_clock_type()); // start immediately - current_pose_msg.joint_names = params_.joints; - current_pose_msg.points.push_back(state_current_); - current_pose_msg.points[0].velocities.clear(); - current_pose_msg.points[0].accelerations.clear(); - current_pose_msg.points[0].effort.clear(); - if (has_velocity_command_interface_) - { - // ensure no velocity (PID will fix this) - current_pose_msg.points[0].velocities.resize(dof_, 0.0); - } - if (has_acceleration_command_interface_) - { - // ensure no acceleration - current_pose_msg.points[0].accelerations.resize(dof_, 0.0); - } - if (has_effort_command_interface_) - { - // ensure no explicit effort (PID will fix this) - current_pose_msg.points[0].effort.resize(dof_, 0.0); - } + hold_position_msg_ptr_->points[0].positions = state_current_.positions; - return std::make_shared(current_pose_msg); + // set flag, otherwise tolerances will be checked with holding position too + rt_is_holding_.writeFromNonRT(true); + + return hold_position_msg_ptr_; } bool JointTrajectoryController::contains_interface_type( @@ -1530,6 +1520,28 @@ bool JointTrajectoryController::has_active_trajectory() const return traj_external_point_ptr_ != nullptr && traj_external_point_ptr_->has_trajectory_msg(); } +void JointTrajectoryController::init_hold_position_msg() +{ + hold_position_msg_ptr_ = std::make_shared(); + hold_position_msg_ptr_->header.stamp = + rclcpp::Time(0.0, 0.0, get_node()->get_clock()->get_clock_type()); // start immediately + hold_position_msg_ptr_->joint_names = params_.joints; + hold_position_msg_ptr_->points.resize(1); // a trivial msg only + hold_position_msg_ptr_->points[0].velocities.clear(); + hold_position_msg_ptr_->points[0].accelerations.clear(); + hold_position_msg_ptr_->points[0].effort.clear(); + if (has_velocity_command_interface_ || has_acceleration_command_interface_) + { + // add velocity, so that trajectory sampling returns velocity points in any case + hold_position_msg_ptr_->points[0].velocities.resize(dof_, 0.0); + } + if (has_acceleration_command_interface_) + { + // add velocity, so that trajectory sampling returns acceleration points in any case + hold_position_msg_ptr_->points[0].accelerations.resize(dof_, 0.0); + } +} + } // namespace joint_trajectory_controller #include "pluginlib/class_list_macros.hpp" diff --git a/joint_trajectory_controller/test/test_trajectory_actions.cpp b/joint_trajectory_controller/test/test_trajectory_actions.cpp index fc24c2c029..371be914e2 100644 --- a/joint_trajectory_controller/test/test_trajectory_actions.cpp +++ b/joint_trajectory_controller/test/test_trajectory_actions.cpp @@ -68,11 +68,11 @@ class TestTrajectoryActions : public TrajectoryControllerTest void SetUpExecutor( const std::vector & parameters = {}, - bool separate_cmd_and_state_values = false) + bool separate_cmd_and_state_values = false, double kp = 0.0) { setup_executor_ = true; - SetUpAndActivateTrajectoryController(executor_, parameters, separate_cmd_and_state_values); + SetUpAndActivateTrajectoryController(executor_, parameters, separate_cmd_and_state_values, kp); SetUpActionClient(); @@ -247,7 +247,15 @@ TEST_P(TestTrajectoryActionsTestParameterized, test_success_single_point_sendgoa // it should be holding the last position goal // i.e., active but trivial trajectory (one point only) // note: the action goal also is a trivial trajectory - expectHoldingPoint(point_positions); + if (traj_controller_->has_position_command_interface()) + { + expectHoldingPoint(point_positions); + } + else + { + // no integration to position state interface from velocity/acceleration + expectHoldingPoint(INITIAL_POS_JOINTS); + } } TEST_P(TestTrajectoryActionsTestParameterized, test_success_multi_point_sendgoal) @@ -294,7 +302,15 @@ TEST_P(TestTrajectoryActionsTestParameterized, test_success_multi_point_sendgoal // it should be holding the last position goal // i.e., active but trivial trajectory (one point only) - expectHoldingPoint(points_positions.at(1)); + if (traj_controller_->has_position_command_interface()) + { + expectHoldingPoint(points_positions.at(1)); + } + else + { + // no integration to position state interface from velocity/acceleration + expectHoldingPoint(INITIAL_POS_JOINTS); + } } /** diff --git a/joint_trajectory_controller/test/test_trajectory_controller.cpp b/joint_trajectory_controller/test/test_trajectory_controller.cpp index e0655d2368..e02215e842 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller.cpp +++ b/joint_trajectory_controller/test/test_trajectory_controller.cpp @@ -1574,7 +1574,8 @@ TEST_P(TrajectoryControllerTestParameterized, test_state_tolerances_fail) rclcpp::Parameter("constraints.joint3.trajectory", state_tol)}; rclcpp::executors::MultiThreadedExecutor executor; - SetUpAndActivateTrajectoryController(executor, params, true); + double kp = 1.0; // activate feedback control for testing velocity/effort PID + SetUpAndActivateTrajectoryController(executor, params, true, kp); // send msg constexpr auto FIRST_POINT_TIME = std::chrono::milliseconds(100); @@ -1606,7 +1607,7 @@ TEST_P(TrajectoryControllerTestParameterized, test_goal_tolerances_fail) rclcpp::Parameter("constraints.goal_time", goal_time)}; rclcpp::executors::MultiThreadedExecutor executor; - SetUpAndActivateTrajectoryController(executor, params, true); + SetUpAndActivateTrajectoryController(executor, params, true, 1.0); // send msg constexpr auto FIRST_POINT_TIME = std::chrono::milliseconds(100); @@ -1623,6 +1624,13 @@ TEST_P(TrajectoryControllerTestParameterized, test_goal_tolerances_fail) // it should have aborted and be holding now expectHoldingPoint(joint_state_pos_); + + // what happens if we wait longer but it harms the tolerance again? + auto hold_position = joint_state_pos_; + joint_state_pos_.at(0) = -3.3; + updateController(rclcpp::Duration(FIRST_POINT_TIME)); + // it should be still holding the old point + expectHoldingPoint(hold_position); } // position controllers diff --git a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp index 59d20c33d2..f25f2a03f8 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp +++ b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp @@ -38,6 +38,12 @@ const std::vector INITIAL_POS_JOINTS = { const std::vector INITIAL_VEL_JOINTS = {0.0, 0.0, 0.0}; const std::vector INITIAL_ACC_JOINTS = {0.0, 0.0, 0.0}; const std::vector INITIAL_EFF_JOINTS = {0.0, 0.0, 0.0}; + +bool is_same_sign_or_zero(double val1, double val2) +{ + return val1 * val2 > 0.0 || (val1 == 0.0 && val2 == 0.0); +} + } // namespace namespace test_trajectory_controllers @@ -435,32 +441,65 @@ class TrajectoryControllerTest : public ::testing::Test // i.e., active but trivial trajectory (one point only) EXPECT_TRUE(traj_controller_->has_trivial_traj()); - if (traj_controller_->has_position_command_interface()) + if (traj_controller_->use_closed_loop_pid_adapter() == false) { - EXPECT_NEAR(point.at(0), joint_pos_[0], COMMON_THRESHOLD); - EXPECT_NEAR(point.at(1), joint_pos_[1], COMMON_THRESHOLD); - EXPECT_NEAR(point.at(2), joint_pos_[2], COMMON_THRESHOLD); - } + if (traj_controller_->has_position_command_interface()) + { + EXPECT_NEAR(point.at(0), joint_pos_[0], COMMON_THRESHOLD); + EXPECT_NEAR(point.at(1), joint_pos_[1], COMMON_THRESHOLD); + EXPECT_NEAR(point.at(2), joint_pos_[2], COMMON_THRESHOLD); + } - if (traj_controller_->has_velocity_command_interface()) - { - EXPECT_EQ(0.0, joint_vel_[0]); - EXPECT_EQ(0.0, joint_vel_[1]); - EXPECT_EQ(0.0, joint_vel_[2]); - } + if (traj_controller_->has_velocity_command_interface()) + { + EXPECT_EQ(0.0, joint_vel_[0]); + EXPECT_EQ(0.0, joint_vel_[1]); + EXPECT_EQ(0.0, joint_vel_[2]); + } - if (traj_controller_->has_acceleration_command_interface()) - { - EXPECT_EQ(0.0, joint_acc_[0]); - EXPECT_EQ(0.0, joint_acc_[1]); - EXPECT_EQ(0.0, joint_acc_[2]); - } + if (traj_controller_->has_acceleration_command_interface()) + { + EXPECT_EQ(0.0, joint_acc_[0]); + EXPECT_EQ(0.0, joint_acc_[1]); + EXPECT_EQ(0.0, joint_acc_[2]); + } - if (traj_controller_->has_effort_command_interface()) + if (traj_controller_->has_effort_command_interface()) + { + EXPECT_EQ(0.0, joint_eff_[0]); + EXPECT_EQ(0.0, joint_eff_[1]); + EXPECT_EQ(0.0, joint_eff_[2]); + } + } + else { - EXPECT_EQ(0.0, joint_eff_[0]); - EXPECT_EQ(0.0, joint_eff_[1]); - EXPECT_EQ(0.0, joint_eff_[2]); + // velocity or effort PID? + // velocity setpoint is always zero -> feedforward term does not have an effect + // --> set kp > 0.0 in test + if (traj_controller_->has_velocity_command_interface()) + { + EXPECT_TRUE(is_same_sign_or_zero(point.at(0) - joint_state_pos_[0], joint_vel_[0])) + << "current error: " << point.at(0) - joint_state_pos_[0] << ", velocity command is " + << joint_vel_[0]; + EXPECT_TRUE(is_same_sign_or_zero(point.at(1) - joint_state_pos_[1], joint_vel_[1])) + << "current error: " << point.at(1) - joint_state_pos_[1] << ", velocity command is " + << joint_vel_[1]; + EXPECT_TRUE(is_same_sign_or_zero(point.at(2) - joint_state_pos_[2], joint_vel_[2])) + << "current error: " << point.at(2) - joint_state_pos_[2] << ", velocity command is " + << joint_vel_[2]; + } + if (traj_controller_->has_effort_command_interface()) + { + EXPECT_TRUE(is_same_sign_or_zero(point.at(0) - joint_state_pos_[0], joint_eff_[0])) + << "current error: " << point.at(0) - joint_state_pos_[0] << ", effort command is " + << joint_eff_[0]; + EXPECT_TRUE(is_same_sign_or_zero(point.at(1) - joint_state_pos_[1], joint_eff_[1])) + << "current error: " << point.at(1) - joint_state_pos_[1] << ", effort command is " + << joint_eff_[1]; + EXPECT_TRUE(is_same_sign_or_zero(point.at(2) - joint_state_pos_[2], joint_eff_[2])) + << "current error: " << point.at(2) - joint_state_pos_[2] << ", effort command is " + << joint_eff_[2]; + } } } From cad7894f64ea26fd5c1fe9aa29f067bb5b0304e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Wed, 13 Sep 2023 11:12:03 +0200 Subject: [PATCH 112/238] [JTC] Rename parameter: normalize_error to angle_wraparound (#772) --- joint_trajectory_controller/doc/parameters.rst | 10 ++++++---- .../src/joint_trajectory_controller.cpp | 13 +++++++++++-- .../src/joint_trajectory_controller_parameters.yaml | 8 +++++++- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/joint_trajectory_controller/doc/parameters.rst b/joint_trajectory_controller/doc/parameters.rst index 199f1b30dc..bb16f5b250 100644 --- a/joint_trajectory_controller/doc/parameters.rst +++ b/joint_trajectory_controller/doc/parameters.rst @@ -102,7 +102,7 @@ gains (structure) u = k_{ff} v_d + k_p e + k_i \sum e dt + k_d (v_d - v) - with the desired velocity :math:`v_d`, the measured velocity :math:`v`, the position error :math:`e` (definition see below), + with the desired velocity :math:`v_d`, the measured velocity :math:`v`, the position error :math:`e` (definition see ``angle_wraparound`` below), the controller period :math:`dt`, and the ``velocity`` or ``effort`` manipulated variable (control variable) :math:`u`, respectively. gains..p (double) @@ -130,10 +130,12 @@ gains..ff_velocity_scale (double) Default: 0.0 -gains..normalize_error (bool) +gains..angle_wraparound (bool) + For joints that wrap around (without end stop, ie. are continuous), + where the shortest rotation to the target position is the desired motion. If true, the position error :math:`e = normalize(s_d - s)` is normalized between :math:`-\pi, \pi`. Otherwise :math:`e = s_d - s` is used, with the desired position :math:`s_d` and the measured - position :math:`s` from the state interface. Use this for revolute joints without end stop, - where the shortest rotation to the target position is the desired motion. + position :math:`s` from the state interface. + Default: false diff --git a/joint_trajectory_controller/src/joint_trajectory_controller.cpp b/joint_trajectory_controller/src/joint_trajectory_controller.cpp index 229456c104..ad40fc2da8 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller.cpp +++ b/joint_trajectory_controller/src/joint_trajectory_controller.cpp @@ -726,12 +726,21 @@ controller_interface::CallbackReturn JointTrajectoryController::on_configure( } } - // Configure joint position error normalization from ROS parameters + // Configure joint position error normalization from ROS parameters (angle_wraparound) normalize_joint_error_.resize(dof_); for (size_t i = 0; i < dof_; ++i) { const auto & gains = params_.gains.joints_map.at(params_.joints[i]); - normalize_joint_error_[i] = gains.normalize_error; + if (gains.normalize_error) + { + // TODO(anyone): Remove deprecation warning in the end of 2023 + RCLCPP_INFO(logger, "`normalize_error` is deprecated, use `angle_wraparound` instead!"); + normalize_joint_error_[i] = gains.normalize_error; + } + else + { + normalize_joint_error_[i] = gains.angle_wraparound; + } } if (params_.state_interfaces.empty()) diff --git a/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml b/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml index d299944976..5a1d985a7a 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml +++ b/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml @@ -113,7 +113,13 @@ joint_trajectory_controller: normalize_error: { type: bool, default_value: false, - description: "Use position error normalization to -pi to pi." + description: "(Deprecated) Use position error normalization to -pi to pi." + } + angle_wraparound: { + type: bool, + default_value: false, + description: "For joints that wrap around (ie. are continuous). + Normalizes position-error to -pi to pi." } constraints: stopped_velocity_tolerance: { From 0f08731a7ca236dd129321f7c81eb10cfaffa20e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Thu, 14 Sep 2023 18:20:07 +0200 Subject: [PATCH 113/238] [JTC] Add time-out for trajectory interfaces (#609) --- .../doc/parameters.rst | 10 ++ .../joint_trajectory_controller.hpp | 5 +- .../trajectory.hpp | 3 - .../src/joint_trajectory_controller.cpp | 50 ++++++- ...oint_trajectory_controller_parameters.yaml | 8 + .../test/test_trajectory_controller.cpp | 141 ++++++++++++++++++ .../test/test_trajectory_controller_utils.hpp | 7 + 7 files changed, 212 insertions(+), 12 deletions(-) diff --git a/joint_trajectory_controller/doc/parameters.rst b/joint_trajectory_controller/doc/parameters.rst index bb16f5b250..95a6599191 100644 --- a/joint_trajectory_controller/doc/parameters.rst +++ b/joint_trajectory_controller/doc/parameters.rst @@ -68,6 +68,16 @@ allow_nonzero_velocity_at_trajectory_end (boolean) Default: true +cmd_timeout (double) + Timeout after which the input command is considered stale. + Timeout is counted from the end of the trajectory (the last point). + ``cmd_timeout`` must be greater than ``constraints.goal_time``, + otherwise ignored. + + If zero, timeout is deactivated" + + Default: 0.0 + constraints (structure) Default values for tolerances if no explicit values are states in JointTrajectory message. diff --git a/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp b/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp index 1f805ee95b..b3e2f55742 100644 --- a/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp +++ b/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp @@ -174,7 +174,10 @@ class JointTrajectoryController : public controller_interface::ControllerInterfa // reserved storage for result of the command when closed loop pid adapter is used std::vector tmp_command_; - realtime_tools::RealtimeBuffer rt_is_holding_; ///< are we holding position? + // Timeout to consider commands old + double cmd_timeout_; + // Are we holding position? + realtime_tools::RealtimeBuffer rt_is_holding_; // TODO(karsten1987): eventually activate and deactivate subscriber directly when its supported bool subscriber_is_active_ = false; rclcpp::Subscription::SharedPtr joint_command_subscriber_ = diff --git a/joint_trajectory_controller/include/joint_trajectory_controller/trajectory.hpp b/joint_trajectory_controller/include/joint_trajectory_controller/trajectory.hpp index d2d0dc9dbd..3bd4873a31 100644 --- a/joint_trajectory_controller/include/joint_trajectory_controller/trajectory.hpp +++ b/joint_trajectory_controller/include/joint_trajectory_controller/trajectory.hpp @@ -139,9 +139,6 @@ class Trajectory return trajectory_msg_; } - JOINT_TRAJECTORY_CONTROLLER_PUBLIC - rclcpp::Time get_trajectory_start_time() const { return trajectory_start_time_; } - JOINT_TRAJECTORY_CONTROLLER_PUBLIC bool is_sampled_already() const { return sampled_already_; } diff --git a/joint_trajectory_controller/src/joint_trajectory_controller.cpp b/joint_trajectory_controller/src/joint_trajectory_controller.cpp index ad40fc2da8..5e39bffc73 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller.cpp +++ b/joint_trajectory_controller/src/joint_trajectory_controller.cpp @@ -186,7 +186,7 @@ controller_interface::return_type JointTrajectoryController::update( state_current_.time_from_start.set__sec(0); read_state_from_hardware(state_current_); - // currently carrying out a trajectory. + // currently carrying out a trajectory if (has_active_trajectory()) { bool first_sample = false; @@ -211,12 +211,32 @@ controller_interface::return_type JointTrajectoryController::update( if (valid_point) { + const rclcpp::Time traj_start = traj_external_point_ptr_->time_from_start(); + // this is the time instance + // - started with the first segment: when the first point will be reached (in the future) + // - later: when the point of the current segment was reached + const rclcpp::Time segment_time_from_start = traj_start + start_segment_itr->time_from_start; + // time_difference is + // - negative until first point is reached + // - counting from zero to time_from_start of next point + double time_difference = time.seconds() - segment_time_from_start.seconds(); bool tolerance_violated_while_moving = false; bool outside_goal_tolerance = false; bool within_goal_time = true; - double time_difference = 0.0; const bool before_last_point = end_segment_itr != traj_external_point_ptr_->end(); + // have we reached the end, are not holding position, and is a timeout configured? + // Check independently of other tolerances + if ( + !before_last_point && *(rt_is_holding_.readFromRT()) == false && cmd_timeout_ > 0.0 && + time_difference > cmd_timeout_) + { + RCLCPP_WARN(get_node()->get_logger(), "Aborted due to command timeout"); + + traj_msg_external_point_ptr_.reset(); + traj_msg_external_point_ptr_.initRT(set_hold_position()); + } + // Check state/goal tolerance for (size_t index = 0; index < dof_; ++index) { @@ -243,12 +263,6 @@ controller_interface::return_type JointTrajectoryController::update( if (default_tolerances_.goal_time_tolerance != 0.0) { - // if we exceed goal_time_tolerance set it to aborted - const rclcpp::Time traj_start = traj_external_point_ptr_->get_trajectory_start_time(); - const rclcpp::Time traj_end = traj_start + start_segment_itr->time_from_start; - - time_difference = time.seconds() - traj_end.seconds(); - if (time_difference > default_tolerances_.goal_time_tolerance) { within_goal_time = false; @@ -894,6 +908,26 @@ controller_interface::CallbackReturn JointTrajectoryController::on_configure( std::string(get_node()->get_name()) + "/query_state", std::bind(&JointTrajectoryController::query_state_service, this, _1, _2)); + if (params_.cmd_timeout > 0.0) + { + if (params_.cmd_timeout > default_tolerances_.goal_time_tolerance) + { + cmd_timeout_ = params_.cmd_timeout; + } + else + { + // deactivate timeout + RCLCPP_WARN( + logger, "Command timeout must be higher than goal_time tolerance (%f vs. %f)", + params_.cmd_timeout, default_tolerances_.goal_time_tolerance); + cmd_timeout_ = 0.0; + } + } + else + { + cmd_timeout_ = 0.0; + } + return CallbackReturn::SUCCESS; } diff --git a/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml b/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml index 5a1d985a7a..ce17ba8bf9 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml +++ b/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml @@ -83,6 +83,14 @@ joint_trajectory_controller: default_value: true, description: "If false, the last velocity point has to be zero or the goal will be rejected", } + cmd_timeout: { + type: double, + default_value: 0.0, # seconds + description: "Timeout after which the input command is considered stale. + Timeout is counted from the end of the trajectory (the last point). + cmd_timeout must be greater than constraints.goal_time, otherwise ignored. + If zero, timeout is deactivated", + } gains: __map_joints: p: { diff --git a/joint_trajectory_controller/test/test_trajectory_controller.cpp b/joint_trajectory_controller/test/test_trajectory_controller.cpp index e02215e842..bb387dbc4d 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller.cpp +++ b/joint_trajectory_controller/test/test_trajectory_controller.cpp @@ -565,6 +565,147 @@ TEST_P(TrajectoryControllerTestParameterized, position_error_not_normalized) executor.cancel(); } +/** + * @brief cmd_timeout must be greater than constraints.goal_time + */ +TEST_P(TrajectoryControllerTestParameterized, accept_correct_cmd_timeout) +{ + rclcpp::executors::MultiThreadedExecutor executor; + // zero is default value, just for demonstration + double cmd_timeout = 3.0; + rclcpp::Parameter cmd_timeout_parameter("cmd_timeout", cmd_timeout); + rclcpp::Parameter goal_time_parameter("constraints.goal_time", 2.0); + SetUpAndActivateTrajectoryController( + executor, {cmd_timeout_parameter, goal_time_parameter}, false); + + EXPECT_DOUBLE_EQ(cmd_timeout, traj_controller_->get_cmd_timeout()); +} + +/** + * @brief cmd_timeout must be greater than constraints.goal_time + */ +TEST_P(TrajectoryControllerTestParameterized, decline_false_cmd_timeout) +{ + rclcpp::executors::MultiThreadedExecutor executor; + // zero is default value, just for demonstration + rclcpp::Parameter cmd_timeout_parameter("cmd_timeout", 1.0); + rclcpp::Parameter goal_time_parameter("constraints.goal_time", 2.0); + SetUpAndActivateTrajectoryController( + executor, {cmd_timeout_parameter, goal_time_parameter}, false); + + EXPECT_DOUBLE_EQ(0.0, traj_controller_->get_cmd_timeout()); +} + +/** + * @brief check if no timeout is triggered + */ +TEST_P(TrajectoryControllerTestParameterized, no_timeout) +{ + rclcpp::executors::MultiThreadedExecutor executor; + // zero is default value, just for demonstration + rclcpp::Parameter cmd_timeout_parameter("cmd_timeout", 0.0); + SetUpAndActivateTrajectoryController(executor, {cmd_timeout_parameter}, false); + subscribeToState(); + + size_t n_joints = joint_names_.size(); + + // send msg + constexpr auto FIRST_POINT_TIME = std::chrono::milliseconds(250); + builtin_interfaces::msg::Duration time_from_start{rclcpp::Duration(FIRST_POINT_TIME)}; + // *INDENT-OFF* + std::vector> points{ + {{3.3, 4.4, 6.6}}, {{7.7, 8.8, 9.9}}, {{10.10, 11.11, 12.12}}}; + std::vector> points_velocities{ + {{0.01, 0.01, 0.01}}, {{0.05, 0.05, 0.05}}, {{0.06, 0.06, 0.06}}}; + // *INDENT-ON* + publish(time_from_start, points, rclcpp::Time(0, 0, RCL_STEADY_TIME), {}, points_velocities); + traj_controller_->wait_for_trajectory(executor); + + // first update + updateController(rclcpp::Duration(FIRST_POINT_TIME) * 4); + + // Spin to receive latest state + executor.spin_some(); + auto state_msg = getState(); + ASSERT_TRUE(state_msg); + + // has the msg the correct vector sizes? + EXPECT_EQ(n_joints, state_msg->reference.positions.size()); + + // is the trajectory still active? + EXPECT_TRUE(traj_controller_->has_active_traj()); + // should still hold the points from above + EXPECT_TRUE(traj_controller_->has_nontrivial_traj()); + EXPECT_NEAR(state_msg->reference.positions[0], points.at(2).at(0), 1e-2); + EXPECT_NEAR(state_msg->reference.positions[1], points.at(2).at(1), 1e-2); + EXPECT_NEAR(state_msg->reference.positions[2], points.at(2).at(2), 1e-2); + // value of velocities is different from above due to spline interpolation + EXPECT_GT(state_msg->reference.velocities[0], 0.0); + EXPECT_GT(state_msg->reference.velocities[1], 0.0); + EXPECT_GT(state_msg->reference.velocities[2], 0.0); + + executor.cancel(); +} + +/** + * @brief check if timeout is triggered + */ +TEST_P(TrajectoryControllerTestParameterized, timeout) +{ + rclcpp::executors::MultiThreadedExecutor executor; + constexpr double cmd_timeout = 0.1; + rclcpp::Parameter cmd_timeout_parameter("cmd_timeout", cmd_timeout); + double kp = 1.0; // activate feedback control for testing velocity/effort PID + SetUpAndActivateTrajectoryController(executor, {cmd_timeout_parameter}, false, kp); + subscribeToState(); + + // send msg + constexpr auto FIRST_POINT_TIME = std::chrono::milliseconds(250); + builtin_interfaces::msg::Duration time_from_start{rclcpp::Duration(FIRST_POINT_TIME)}; + // *INDENT-OFF* + std::vector> points{ + {{3.3, 4.4, 6.6}}, {{7.7, 8.8, 9.9}}, {{10.10, 11.11, 12.12}}}; + std::vector> points_velocities{ + {{0.01, 0.01, 0.01}}, {{0.05, 0.05, 0.05}}, {{0.06, 0.06, 0.06}}}; + // *INDENT-ON* + + publish(time_from_start, points, rclcpp::Time(0, 0, RCL_STEADY_TIME), {}, points_velocities); + traj_controller_->wait_for_trajectory(executor); + + // update until end of trajectory -> no timeout should have occurred + updateController(rclcpp::Duration(FIRST_POINT_TIME) * 3); + // is a trajectory active? + EXPECT_TRUE(traj_controller_->has_active_traj()); + // should have the trajectory with three points + EXPECT_TRUE(traj_controller_->has_nontrivial_traj()); + + // update until timeout should have happened + updateController(rclcpp::Duration(FIRST_POINT_TIME)); + + // Spin to receive latest state + executor.spin_some(); + auto state_msg = getState(); + ASSERT_TRUE(state_msg); + + // after timeout, set_hold_position adds a new trajectory + // is a trajectory active? + EXPECT_TRUE(traj_controller_->has_active_traj()); + // should be not more than one point now (from hold position) + EXPECT_FALSE(traj_controller_->has_nontrivial_traj()); + // should hold last position with zero velocity + if (traj_controller_->has_position_command_interface()) + { + expectHoldingPoint(points.at(2)); + } + else + { + // no integration to position state interface from velocity/acceleration + expectHoldingPoint(INITIAL_POS_JOINTS); + } + + executor.cancel(); +} + /** * @brief check if position error of revolute joints are normalized if configured so */ diff --git a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp index f25f2a03f8..cea61c92bf 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp +++ b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp @@ -137,6 +137,13 @@ class TestableJointTrajectoryController return has_active_trajectory() && traj_external_point_ptr_->has_nontrivial_msg() == false; } + bool has_nontrivial_traj() + { + return has_active_trajectory() && traj_external_point_ptr_->has_nontrivial_msg(); + } + + double get_cmd_timeout() { return cmd_timeout_; } + rclcpp::WaitSet joint_cmd_sub_wait_set_; }; From e763ef0dd58fd2bea36ef66692bcb2b76b7740ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Sat, 16 Sep 2023 21:02:59 +0200 Subject: [PATCH 114/238] [Docs] Improve interface description of JTC (#770) --- joint_trajectory_controller/doc/userdoc.rst | 27 ++++++++++----------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/joint_trajectory_controller/doc/userdoc.rst b/joint_trajectory_controller/doc/userdoc.rst index b9d8e274cf..deedc4a7b6 100644 --- a/joint_trajectory_controller/doc/userdoc.rst +++ b/joint_trajectory_controller/doc/userdoc.rst @@ -14,16 +14,24 @@ Waypoints consist of positions, and optionally velocities and accelerations. *Parts of this documentation were originally published in the ROS 1 wiki under the* `CC BY 3.0 license `_. *Citations are given in the respective section, but were adapted for the ROS 2 implementation.* [#f1]_ -Hardware interface type [#f1]_ +Hardware interface types ------------------------------- -Currently joints with position, velocity, acceleration, and effort interfaces are supported. The joints can have one or more command interfaces, where the following control laws are applied at the same time: +Currently, joints with hardware interface types ``position``, ``velocity``, ``acceleration``, and ``effort`` (defined `here `_) are supported in the following combinations: + +* ``position`` +* ``position``, ``velocity`` +* ``position``, ``velocity``, ``acceleration`` +* ``velocity`` +* ``effort`` + +This means that the joints can have one or more command interfaces, where the following control laws are applied at the same time: * For command interfaces ``position``, the desired positions are simply forwarded to the joints, * For command interfaces ``acceleration``, desired accelerations are simply forwarded to the joints. -* For ``velocity`` (``effort``) command interfaces, the position+velocity trajectory following error is mapped to ``velocity`` (``effort``) commands through a PID loop (:ref:`parameters`). +* For ``velocity`` (``effort``) command interfaces, the position+velocity trajectory following error is mapped to ``velocity`` (``effort``) commands through a PID loop if it is configured (:ref:`parameters`). -This leads to the the following allowed combinations of command and state interfaces: +This leads to the following allowed combinations of command and state interfaces: * With command interface ``position``, there are no restrictions for state interfaces. * With command interface ``velocity``: @@ -32,12 +40,9 @@ This leads to the the following allowed combinations of command and state interf * no restrictions otherwise. * With command interface ``effort``, state interfaces must include ``position, velocity``. -* With command interface ``acceleration``, there are no restrictions for state interfaces. Example controller configurations can be found :ref:`below `. -Similarly to the trajectory representation case above, it's possible to support new hardware interfaces, or alternative mappings to an already supported interface (eg. a proxy controller for generating effort commands). - Other features -------------- @@ -118,14 +123,8 @@ States ,,,,,,,,,,,,,,,,,, The state interfaces are defined with ``joints`` and ``state_interfaces`` parameters as follows: ``/``. -Supported state interfaces are ``position``, ``velocity``, ``acceleration`` and ``effort`` as defined in the `hardware_interface/hardware_interface_type_values.hpp `_. - -Legal combinations of state interfaces are: -* ``position`` -* ``position`` and ``velocity`` -* ``position``, ``velocity`` and ``acceleration`` -* ``effort`` +Legal combinations of state interfaces are given in section `Hardware Interface Types`_. Commands ,,,,,,,,, From fc5454a5c2508cccd2858364465f792f98a2c4b9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 17 Sep 2023 15:23:39 +0100 Subject: [PATCH 115/238] Bump actions/upload-artifact from 3.1.2 to 3.1.3 (#774) --- .github/workflows/ci-coverage-build.yml | 2 +- .github/workflows/reusable-ros-tooling-source-build.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-coverage-build.yml b/.github/workflows/ci-coverage-build.yml index cc5dd32596..f3a096f40d 100644 --- a/.github/workflows/ci-coverage-build.yml +++ b/.github/workflows/ci-coverage-build.yml @@ -42,7 +42,7 @@ jobs: file: ros_ws/lcov/total_coverage.info flags: unittests name: codecov-umbrella - - uses: actions/upload-artifact@v3.1.2 + - uses: actions/upload-artifact@v3.1.3 with: name: colcon-logs-coverage-rolling path: ros_ws/log diff --git a/.github/workflows/reusable-ros-tooling-source-build.yml b/.github/workflows/reusable-ros-tooling-source-build.yml index 5a01d23533..167386ceff 100644 --- a/.github/workflows/reusable-ros-tooling-source-build.yml +++ b/.github/workflows/reusable-ros-tooling-source-build.yml @@ -44,7 +44,7 @@ jobs: https://raw.githubusercontent.com/ros2/ros2/${{ inputs.ros2_repo_branch }}/ros2.repos https://raw.githubusercontent.com/${{ github.repository }}/${{ github.sha }}/ros2_controllers.${{ inputs.ros_distro }}.repos?token=${{ secrets.GITHUB_TOKEN }} colcon-mixin-repository: https://raw.githubusercontent.com/colcon/colcon-mixin-repository/master/index.yaml - - uses: actions/upload-artifact@v3.1.2 + - uses: actions/upload-artifact@v3.1.3 with: name: colcon-logs-ubuntu-22.04 path: ros_ws/log From 84d988c78646a9cf34a6f06532504416f29a3873 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Sun, 17 Sep 2023 20:50:55 +0200 Subject: [PATCH 116/238] [Doc] Add specific documentation on the available fw cmd controllers (#765) --- effort_controllers/doc/userdoc.rst | 40 ++++++++++++++++++++-- forward_command_controller/doc/userdoc.rst | 12 ++++++- position_controllers/doc/userdoc.rst | 40 ++++++++++++++++++++-- velocity_controllers/doc/userdoc.rst | 40 ++++++++++++++++++++-- 4 files changed, 122 insertions(+), 10 deletions(-) diff --git a/effort_controllers/doc/userdoc.rst b/effort_controllers/doc/userdoc.rst index 74caf63391..62e98a75f9 100644 --- a/effort_controllers/doc/userdoc.rst +++ b/effort_controllers/doc/userdoc.rst @@ -7,7 +7,41 @@ effort_controllers This is a collection of controllers that work using the "effort" joint command interface but may accept different joint-level commands at the controller level, e.g. controlling the effort on a certain joint to achieve a set position. -Hardware interface type ------------------------ +The package contains the following controllers: -These controllers work with joints using the "effort" command interface. +effort_controllers/JointGroupEffortController +------------------------------------------------- + +This is specialization of the :ref:`forward_command_controller ` that works using the "effort" joint interface. + + +ROS 2 interface of the controller +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Topics +,,,,,,,,,,,,,,,,,, + +~/commands (input topic) [std_msgs::msg::Float64MultiArray] + Joints' effort commands + + +Parameters +,,,,,,,,,,,,,,,,,, +This controller overrides the interface parameter from :ref:`forward_command_controller `, and the +``joints`` parameter is the only one that is required. + +An example parameter file is given here + +.. code-block:: yaml + + controller_manager: + ros__parameters: + update_rate: 100 # Hz + + effort_controller: + type: effort_controllers/JointGroupEffortController + + effort_controller: + ros__parameters: + joints: + - slider_to_cart diff --git a/forward_command_controller/doc/userdoc.rst b/forward_command_controller/doc/userdoc.rst index a91479c9af..01aa2492a8 100644 --- a/forward_command_controller/doc/userdoc.rst +++ b/forward_command_controller/doc/userdoc.rst @@ -16,8 +16,18 @@ Hardware interface type This controller can be used for every type of command interface. + +ROS 2 interface of the controller +--------------------------------- + +Topics +^^^^^^^ + +~/commands (input topic) [std_msgs::msg::Float64MultiArray] + Target joint commands + Parameters ------------- +^^^^^^^^^^^^^^ This controller uses the `generate_parameter_library `_ to handle its parameters. diff --git a/position_controllers/doc/userdoc.rst b/position_controllers/doc/userdoc.rst index f321e8a698..89766df9d4 100644 --- a/position_controllers/doc/userdoc.rst +++ b/position_controllers/doc/userdoc.rst @@ -7,7 +7,41 @@ position_controllers This is a collection of controllers that work using the "position" joint command interface but may accept different joint-level commands at the controller level, e.g. controlling the position on a certain joint to achieve a set velocity. -Hardware interface type ------------------------ +The package contains the following controllers: -These controllers work with joints using the "position" command interface. +position_controllers/JointGroupPositionController +------------------------------------------------- + +This is specialization of the :ref:`forward_command_controller ` that works using the "position" joint interface. + + +ROS 2 interface of the controller +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Topics +,,,,,,,,,,,,,,,,,, + +~/commands (input topic) [std_msgs::msg::Float64MultiArray] + Joints' position commands + + +Parameters +,,,,,,,,,,,,,,,,,, +This controller overrides the interface parameter from :ref:`forward_command_controller `, and the +``joints`` parameter is the only one that is required. + +An example parameter file is given here + +.. code-block:: yaml + + controller_manager: + ros__parameters: + update_rate: 100 # Hz + + position_controller: + type: position_controllers/JointGroupPositionController + + position_controller: + ros__parameters: + joints: + - slider_to_cart diff --git a/velocity_controllers/doc/userdoc.rst b/velocity_controllers/doc/userdoc.rst index fa7e36062e..469b975a97 100644 --- a/velocity_controllers/doc/userdoc.rst +++ b/velocity_controllers/doc/userdoc.rst @@ -7,7 +7,41 @@ velocity_controllers This is a collection of controllers that work using the "velocity" joint command interface but may accept different joint-level commands at the controller level, e.g. controlling the velocity on a certain joint to achieve a set position. -Hardware interface type ------------------------ +The package contains the following controllers: -These controllers work with joints using the "velocity" command interface. +velocity_controllers/JointGroupVelocityController +------------------------------------------------- + +This is specialization of the :ref:`forward_command_controller ` that works using the "velocity" joint interface. + + +ROS 2 interface of the controller +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Topics +,,,,,,,,,,,,,,,,,, + +~/commands (input topic) [std_msgs::msg::Float64MultiArray] + Joints' velocity commands + + +Parameters +,,,,,,,,,,,,,,,,,, +This controller overrides the interface parameter from :ref:`forward_command_controller `, and the +``joints`` parameter is the only one that is required. + +An example parameter file is given here + +.. code-block:: yaml + + controller_manager: + ros__parameters: + update_rate: 100 # Hz + + velocity_controller: + type: velocity_controllers/JointGroupVelocityController + + velocity_controller: + ros__parameters: + joints: + - slider_to_cart From 43a9a0bba4160ad87226806c1d9d0be5cbcd90ad Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Wed, 20 Sep 2023 12:40:36 +0100 Subject: [PATCH 117/238] Update changelogs --- ackermann_steering_controller/CHANGELOG.rst | 3 +++ admittance_controller/CHANGELOG.rst | 3 +++ bicycle_steering_controller/CHANGELOG.rst | 3 +++ diff_drive_controller/CHANGELOG.rst | 3 +++ effort_controllers/CHANGELOG.rst | 5 +++++ force_torque_sensor_broadcaster/CHANGELOG.rst | 3 +++ forward_command_controller/CHANGELOG.rst | 5 +++++ gripper_controllers/CHANGELOG.rst | 3 +++ imu_sensor_broadcaster/CHANGELOG.rst | 3 +++ joint_state_broadcaster/CHANGELOG.rst | 3 +++ joint_trajectory_controller/CHANGELOG.rst | 9 +++++++++ position_controllers/CHANGELOG.rst | 5 +++++ range_sensor_broadcaster/CHANGELOG.rst | 3 +++ ros2_controllers/CHANGELOG.rst | 3 +++ ros2_controllers_test_nodes/CHANGELOG.rst | 3 +++ rqt_joint_trajectory_controller/CHANGELOG.rst | 3 +++ steering_controllers_library/CHANGELOG.rst | 3 +++ tricycle_controller/CHANGELOG.rst | 3 +++ tricycle_steering_controller/CHANGELOG.rst | 3 +++ velocity_controllers/CHANGELOG.rst | 5 +++++ 20 files changed, 74 insertions(+) diff --git a/ackermann_steering_controller/CHANGELOG.rst b/ackermann_steering_controller/CHANGELOG.rst index 723ca88779..3a5780a430 100644 --- a/ackermann_steering_controller/CHANGELOG.rst +++ b/ackermann_steering_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ackermann_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.15.0 (2023-09-11) ------------------- diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index 593fa56562..64969ca7a0 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.15.0 (2023-09-11) ------------------- * Update docs for diff drive controller (`#751 `_) diff --git a/bicycle_steering_controller/CHANGELOG.rst b/bicycle_steering_controller/CHANGELOG.rst index be6ac52313..195b484703 100644 --- a/bicycle_steering_controller/CHANGELOG.rst +++ b/bicycle_steering_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package bicycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.15.0 (2023-09-11) ------------------- diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index 52c8572739..79c903b365 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.15.0 (2023-09-11) ------------------- * Update docs for diff drive controller (`#751 `_) diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index 4b93f1f69a..57635be0aa 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* [Doc] Add specific documentation on the available fw cmd controllers (`#765 `_) +* Contributors: Christoph Fröhlich + 3.15.0 (2023-09-11) ------------------- diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index 296cad54bf..bd0168c08d 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.15.0 (2023-09-11) ------------------- * [ForceTorqueSensorBroadcaster] Create ParamListener and get parameters on configure (`#698 `_) diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index b3d33964b6..afe614402f 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* [Doc] Add specific documentation on the available fw cmd controllers (`#765 `_) +* Contributors: Christoph Fröhlich + 3.15.0 (2023-09-11) ------------------- diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index 82cf6cf45b..fa20eb1305 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.15.0 (2023-09-11) ------------------- * Add test for effort gripper controller (`#769 `_) diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index 915544197c..4fde46e25e 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.15.0 (2023-09-11) ------------------- diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index 57bc1b7f45..2d25987021 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.15.0 (2023-09-11) ------------------- diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index 8b1a1c6a54..ad98fac23d 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,15 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* [Docs] Improve interface description of JTC (`#770 `_) +* [JTC] Add time-out for trajectory interfaces (`#609 `_) +* [JTC] Rename parameter: normalize_error to angle_wraparound (`#772 `_) +* [JTC] Fix hold position mode with goal_time>0 (`#758 `_) +* [JTC] Add note on goal_time=0 in docs (`#773 `_) +* Contributors: Christoph Fröhlich + 3.15.0 (2023-09-11) ------------------- * [JTC] Make most parameters read-only (`#771 `_) diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index 5da7a35e1a..c4697db65a 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* [Doc] Add specific documentation on the available fw cmd controllers (`#765 `_) +* Contributors: Christoph Fröhlich + 3.15.0 (2023-09-11) ------------------- diff --git a/range_sensor_broadcaster/CHANGELOG.rst b/range_sensor_broadcaster/CHANGELOG.rst index 6e63a22917..4c5850cff1 100644 --- a/range_sensor_broadcaster/CHANGELOG.rst +++ b/range_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package range_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.15.0 (2023-09-11) ------------------- * add a broadcaster for range sensor (`#725 `_) diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index 6684adfabc..d6c3429105 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.15.0 (2023-09-11) ------------------- * add a broadcaster for range sensor (`#725 `_) diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index 3caadb3880..78d6a6af53 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.15.0 (2023-09-11) ------------------- diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index 180dd35033..ef5e35e33e 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.15.0 (2023-09-11) ------------------- diff --git a/steering_controllers_library/CHANGELOG.rst b/steering_controllers_library/CHANGELOG.rst index 4c4dae365d..8eb6b6eb0e 100644 --- a/steering_controllers_library/CHANGELOG.rst +++ b/steering_controllers_library/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package steering_controllers_library ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.15.0 (2023-09-11) ------------------- diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index 625c0f4a06..f1a1dfe854 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.15.0 (2023-09-11) ------------------- diff --git a/tricycle_steering_controller/CHANGELOG.rst b/tricycle_steering_controller/CHANGELOG.rst index afe6360322..06bdd6e477 100644 --- a/tricycle_steering_controller/CHANGELOG.rst +++ b/tricycle_steering_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package tricycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.15.0 (2023-09-11) ------------------- diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index 2551b76bd8..07df2c825e 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* [Doc] Add specific documentation on the available fw cmd controllers (`#765 `_) +* Contributors: Christoph Fröhlich + 3.15.0 (2023-09-11) ------------------- From 79c6d1cb37be84deeb9103448b5cf93b9c3b8327 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Wed, 20 Sep 2023 12:40:51 +0100 Subject: [PATCH 118/238] 3.16.0 --- ackermann_steering_controller/CHANGELOG.rst | 4 ++-- ackermann_steering_controller/package.xml | 2 +- admittance_controller/CHANGELOG.rst | 4 ++-- admittance_controller/package.xml | 2 +- bicycle_steering_controller/CHANGELOG.rst | 4 ++-- bicycle_steering_controller/package.xml | 2 +- diff_drive_controller/CHANGELOG.rst | 4 ++-- diff_drive_controller/package.xml | 2 +- effort_controllers/CHANGELOG.rst | 4 ++-- effort_controllers/package.xml | 2 +- force_torque_sensor_broadcaster/CHANGELOG.rst | 4 ++-- force_torque_sensor_broadcaster/package.xml | 2 +- forward_command_controller/CHANGELOG.rst | 4 ++-- forward_command_controller/package.xml | 2 +- gripper_controllers/CHANGELOG.rst | 4 ++-- gripper_controllers/package.xml | 2 +- imu_sensor_broadcaster/CHANGELOG.rst | 4 ++-- imu_sensor_broadcaster/package.xml | 2 +- joint_state_broadcaster/CHANGELOG.rst | 4 ++-- joint_state_broadcaster/package.xml | 2 +- joint_trajectory_controller/CHANGELOG.rst | 4 ++-- joint_trajectory_controller/package.xml | 2 +- position_controllers/CHANGELOG.rst | 4 ++-- position_controllers/package.xml | 2 +- range_sensor_broadcaster/CHANGELOG.rst | 4 ++-- range_sensor_broadcaster/package.xml | 2 +- ros2_controllers/CHANGELOG.rst | 4 ++-- ros2_controllers/package.xml | 2 +- ros2_controllers_test_nodes/CHANGELOG.rst | 4 ++-- ros2_controllers_test_nodes/package.xml | 2 +- ros2_controllers_test_nodes/setup.py | 2 +- rqt_joint_trajectory_controller/CHANGELOG.rst | 4 ++-- rqt_joint_trajectory_controller/package.xml | 2 +- rqt_joint_trajectory_controller/setup.py | 2 +- steering_controllers_library/CHANGELOG.rst | 4 ++-- steering_controllers_library/package.xml | 2 +- tricycle_controller/CHANGELOG.rst | 4 ++-- tricycle_controller/package.xml | 2 +- tricycle_steering_controller/CHANGELOG.rst | 4 ++-- tricycle_steering_controller/package.xml | 2 +- velocity_controllers/CHANGELOG.rst | 4 ++-- velocity_controllers/package.xml | 2 +- 42 files changed, 62 insertions(+), 62 deletions(-) diff --git a/ackermann_steering_controller/CHANGELOG.rst b/ackermann_steering_controller/CHANGELOG.rst index 3a5780a430..d576811bdb 100644 --- a/ackermann_steering_controller/CHANGELOG.rst +++ b/ackermann_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ackermann_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.16.0 (2023-09-20) +------------------- 3.15.0 (2023-09-11) ------------------- diff --git a/ackermann_steering_controller/package.xml b/ackermann_steering_controller/package.xml index 40a3545b99..f866089f1c 100644 --- a/ackermann_steering_controller/package.xml +++ b/ackermann_steering_controller/package.xml @@ -2,7 +2,7 @@ ackermann_steering_controller - 3.15.0 + 3.16.0 Steering controller for Ackermann kinematics. Rear fixed wheels are powering the vehicle and front wheels are steering it. Apache License 2.0 Bence Magyar diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index 64969ca7a0..e17d56865d 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.16.0 (2023-09-20) +------------------- 3.15.0 (2023-09-11) ------------------- diff --git a/admittance_controller/package.xml b/admittance_controller/package.xml index 9f2de80dad..43a7ab0aad 100644 --- a/admittance_controller/package.xml +++ b/admittance_controller/package.xml @@ -2,7 +2,7 @@ admittance_controller - 3.15.0 + 3.16.0 Implementation of admittance controllers for different input and output interface. Denis Štogl Bence Magyar diff --git a/bicycle_steering_controller/CHANGELOG.rst b/bicycle_steering_controller/CHANGELOG.rst index 195b484703..7c652e7fa7 100644 --- a/bicycle_steering_controller/CHANGELOG.rst +++ b/bicycle_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package bicycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.16.0 (2023-09-20) +------------------- 3.15.0 (2023-09-11) ------------------- diff --git a/bicycle_steering_controller/package.xml b/bicycle_steering_controller/package.xml index ddc110f81a..8707502915 100644 --- a/bicycle_steering_controller/package.xml +++ b/bicycle_steering_controller/package.xml @@ -2,7 +2,7 @@ bicycle_steering_controller - 3.15.0 + 3.16.0 Steering controller with bicycle kinematics. Rear fixed wheel is powering the vehicle and front wheel is steering. Apache License 2.0 Bence Magyar diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index 79c903b365..d670ccc047 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.16.0 (2023-09-20) +------------------- 3.15.0 (2023-09-11) ------------------- diff --git a/diff_drive_controller/package.xml b/diff_drive_controller/package.xml index cc849d12ef..611dfbe15a 100644 --- a/diff_drive_controller/package.xml +++ b/diff_drive_controller/package.xml @@ -1,7 +1,7 @@ diff_drive_controller - 3.15.0 + 3.16.0 Controller for a differential drive mobile base. Bence Magyar Jordan Palacios diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index 57635be0aa..efc583475d 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.16.0 (2023-09-20) +------------------- * [Doc] Add specific documentation on the available fw cmd controllers (`#765 `_) * Contributors: Christoph Fröhlich diff --git a/effort_controllers/package.xml b/effort_controllers/package.xml index d0aca9701a..9e3cc8bc32 100644 --- a/effort_controllers/package.xml +++ b/effort_controllers/package.xml @@ -1,7 +1,7 @@ effort_controllers - 3.15.0 + 3.16.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index bd0168c08d..70fe56b159 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.16.0 (2023-09-20) +------------------- 3.15.0 (2023-09-11) ------------------- diff --git a/force_torque_sensor_broadcaster/package.xml b/force_torque_sensor_broadcaster/package.xml index 4cbad1c014..12ec3d1945 100644 --- a/force_torque_sensor_broadcaster/package.xml +++ b/force_torque_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ force_torque_sensor_broadcaster - 3.15.0 + 3.16.0 Controller to publish state of force-torque sensors. Bence Magyar Denis Štogl diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index afe614402f..ca209a52f5 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.16.0 (2023-09-20) +------------------- * [Doc] Add specific documentation on the available fw cmd controllers (`#765 `_) * Contributors: Christoph Fröhlich diff --git a/forward_command_controller/package.xml b/forward_command_controller/package.xml index af90230c7e..c8d0b99a59 100644 --- a/forward_command_controller/package.xml +++ b/forward_command_controller/package.xml @@ -1,7 +1,7 @@ forward_command_controller - 3.15.0 + 3.16.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index fa20eb1305..bc66422a37 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.16.0 (2023-09-20) +------------------- 3.15.0 (2023-09-11) ------------------- diff --git a/gripper_controllers/package.xml b/gripper_controllers/package.xml index d3c8d9bf9f..dcd778363e 100644 --- a/gripper_controllers/package.xml +++ b/gripper_controllers/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> gripper_controllers - 3.15.0 + 3.16.0 The gripper_controllers package Bence Magyar diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index 4fde46e25e..477134c496 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.16.0 (2023-09-20) +------------------- 3.15.0 (2023-09-11) ------------------- diff --git a/imu_sensor_broadcaster/package.xml b/imu_sensor_broadcaster/package.xml index 31684ec958..6173569630 100644 --- a/imu_sensor_broadcaster/package.xml +++ b/imu_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ imu_sensor_broadcaster - 3.15.0 + 3.16.0 Controller to publish readings of IMU sensors. Bence Magyar Denis Štogl diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index 2d25987021..35298737f0 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.16.0 (2023-09-20) +------------------- 3.15.0 (2023-09-11) ------------------- diff --git a/joint_state_broadcaster/package.xml b/joint_state_broadcaster/package.xml index 248dbcb099..05f761169a 100644 --- a/joint_state_broadcaster/package.xml +++ b/joint_state_broadcaster/package.xml @@ -1,7 +1,7 @@ joint_state_broadcaster - 3.15.0 + 3.16.0 Broadcaster to publish joint state Bence Magyar Denis Stogl diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index ad98fac23d..a322fef5ad 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.16.0 (2023-09-20) +------------------- * [Docs] Improve interface description of JTC (`#770 `_) * [JTC] Add time-out for trajectory interfaces (`#609 `_) * [JTC] Rename parameter: normalize_error to angle_wraparound (`#772 `_) diff --git a/joint_trajectory_controller/package.xml b/joint_trajectory_controller/package.xml index 521aa0ea9d..d8f2e8e997 100644 --- a/joint_trajectory_controller/package.xml +++ b/joint_trajectory_controller/package.xml @@ -1,7 +1,7 @@ joint_trajectory_controller - 3.15.0 + 3.16.0 Controller for executing joint-space trajectories on a group of joints Bence Magyar Jordan Palacios diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index c4697db65a..06e2f3e8db 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.16.0 (2023-09-20) +------------------- * [Doc] Add specific documentation on the available fw cmd controllers (`#765 `_) * Contributors: Christoph Fröhlich diff --git a/position_controllers/package.xml b/position_controllers/package.xml index c947f00bdb..712d03068a 100644 --- a/position_controllers/package.xml +++ b/position_controllers/package.xml @@ -1,7 +1,7 @@ position_controllers - 3.15.0 + 3.16.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/range_sensor_broadcaster/CHANGELOG.rst b/range_sensor_broadcaster/CHANGELOG.rst index 4c5850cff1..9d5242684a 100644 --- a/range_sensor_broadcaster/CHANGELOG.rst +++ b/range_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package range_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.16.0 (2023-09-20) +------------------- 3.15.0 (2023-09-11) ------------------- diff --git a/range_sensor_broadcaster/package.xml b/range_sensor_broadcaster/package.xml index 33ed7d5e4d..70d9c1fa2f 100644 --- a/range_sensor_broadcaster/package.xml +++ b/range_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ range_sensor_broadcaster - 3.15.0 + 3.16.0 Controller to publish readings of Range sensors. Bence Magyar Florent Chretien diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index d6c3429105..d21abd09ca 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.16.0 (2023-09-20) +------------------- 3.15.0 (2023-09-11) ------------------- diff --git a/ros2_controllers/package.xml b/ros2_controllers/package.xml index ea2456486b..35cbdbf9bd 100644 --- a/ros2_controllers/package.xml +++ b/ros2_controllers/package.xml @@ -1,7 +1,7 @@ ros2_controllers - 3.15.0 + 3.16.0 Metapackage for ROS2 controllers related packages Bence Magyar Jordan Palacios diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index 78d6a6af53..525d0a0221 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.16.0 (2023-09-20) +------------------- 3.15.0 (2023-09-11) ------------------- diff --git a/ros2_controllers_test_nodes/package.xml b/ros2_controllers_test_nodes/package.xml index 845e65d233..398a279ae7 100644 --- a/ros2_controllers_test_nodes/package.xml +++ b/ros2_controllers_test_nodes/package.xml @@ -2,7 +2,7 @@ ros2_controllers_test_nodes - 3.15.0 + 3.16.0 Demo nodes for showing and testing functionalities of the ros2_control framework. Denis Štogl diff --git a/ros2_controllers_test_nodes/setup.py b/ros2_controllers_test_nodes/setup.py index e4d9a72f89..9b4e3a8b6b 100644 --- a/ros2_controllers_test_nodes/setup.py +++ b/ros2_controllers_test_nodes/setup.py @@ -20,7 +20,7 @@ setup( name=package_name, - version="3.15.0", + version="3.16.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index ef5e35e33e..ecf0568408 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.16.0 (2023-09-20) +------------------- 3.15.0 (2023-09-11) ------------------- diff --git a/rqt_joint_trajectory_controller/package.xml b/rqt_joint_trajectory_controller/package.xml index 9987061405..96b34a5609 100644 --- a/rqt_joint_trajectory_controller/package.xml +++ b/rqt_joint_trajectory_controller/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> rqt_joint_trajectory_controller - 3.15.0 + 3.16.0 Graphical frontend for interacting with joint_trajectory_controller instances. Bence Magyar diff --git a/rqt_joint_trajectory_controller/setup.py b/rqt_joint_trajectory_controller/setup.py index 0dea799d80..cf09679e00 100644 --- a/rqt_joint_trajectory_controller/setup.py +++ b/rqt_joint_trajectory_controller/setup.py @@ -7,7 +7,7 @@ setup( name=package_name, - version="3.15.0", + version="3.16.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/steering_controllers_library/CHANGELOG.rst b/steering_controllers_library/CHANGELOG.rst index 8eb6b6eb0e..a7546cb59d 100644 --- a/steering_controllers_library/CHANGELOG.rst +++ b/steering_controllers_library/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package steering_controllers_library ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.16.0 (2023-09-20) +------------------- 3.15.0 (2023-09-11) ------------------- diff --git a/steering_controllers_library/package.xml b/steering_controllers_library/package.xml index 48c137460b..c7c654846a 100644 --- a/steering_controllers_library/package.xml +++ b/steering_controllers_library/package.xml @@ -2,7 +2,7 @@ steering_controllers_library - 3.15.0 + 3.16.0 Package for steering robot configurations including odometry and interfaces. Apache License 2.0 Bence Magyar diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index f1a1dfe854..91175391f3 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.16.0 (2023-09-20) +------------------- 3.15.0 (2023-09-11) ------------------- diff --git a/tricycle_controller/package.xml b/tricycle_controller/package.xml index a53be880f2..ec4d5e064d 100644 --- a/tricycle_controller/package.xml +++ b/tricycle_controller/package.xml @@ -2,7 +2,7 @@ tricycle_controller - 3.15.0 + 3.16.0 Controller for a tricycle drive mobile base Bence Magyar Tony Najjar diff --git a/tricycle_steering_controller/CHANGELOG.rst b/tricycle_steering_controller/CHANGELOG.rst index 06bdd6e477..dd50c98185 100644 --- a/tricycle_steering_controller/CHANGELOG.rst +++ b/tricycle_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package tricycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.16.0 (2023-09-20) +------------------- 3.15.0 (2023-09-11) ------------------- diff --git a/tricycle_steering_controller/package.xml b/tricycle_steering_controller/package.xml index f320c08c9f..64ebddd5e2 100644 --- a/tricycle_steering_controller/package.xml +++ b/tricycle_steering_controller/package.xml @@ -2,7 +2,7 @@ tricycle_steering_controller - 3.15.0 + 3.16.0 Steering controller with tricycle kinematics. Rear fixed wheels are powering the vehicle and front wheel is steering. Apache License 2.0 Bence Magyar diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index 07df2c825e..ce8bcfefa3 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.16.0 (2023-09-20) +------------------- * [Doc] Add specific documentation on the available fw cmd controllers (`#765 `_) * Contributors: Christoph Fröhlich diff --git a/velocity_controllers/package.xml b/velocity_controllers/package.xml index d0b6cf0ed1..e47e170226 100644 --- a/velocity_controllers/package.xml +++ b/velocity_controllers/package.xml @@ -1,7 +1,7 @@ velocity_controllers - 3.15.0 + 3.16.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios From 3571c551bc28c10638386b1592aef3d662a34e03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Wed, 27 Sep 2023 14:26:56 +0200 Subject: [PATCH 119/238] Update ci-coverage-build.yml (#781) --- .github/workflows/ci-coverage-build.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci-coverage-build.yml b/.github/workflows/ci-coverage-build.yml index f3a096f40d..d2dba1bce8 100644 --- a/.github/workflows/ci-coverage-build.yml +++ b/.github/workflows/ci-coverage-build.yml @@ -3,6 +3,9 @@ on: workflow_dispatch: branches: - master + push: + branches: + - master pull_request: branches: - master From f7c13ad25938246609b724104054754ec7fad18d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Wed, 27 Sep 2023 14:38:46 +0200 Subject: [PATCH 120/238] [JTC] Add tests for acceleration command interface (#752) --- .../test/test_trajectory_controller.cpp | 113 +++++++++++++----- 1 file changed, 86 insertions(+), 27 deletions(-) diff --git a/joint_trajectory_controller/test/test_trajectory_controller.cpp b/joint_trajectory_controller/test/test_trajectory_controller.cpp index bb387dbc4d..07d60ce077 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller.cpp +++ b/joint_trajectory_controller/test/test_trajectory_controller.cpp @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -57,8 +58,6 @@ using lifecycle_msgs::msg::State; using test_trajectory_controllers::TrajectoryControllerTest; using test_trajectory_controllers::TrajectoryControllerTestParameterized; -bool is_same_sign(double val1, double val2) { return val1 * val2 >= 0.0; } - void spin(rclcpp::executors::MultiThreadedExecutor * exe) { exe->spin(); } TEST_P(TrajectoryControllerTestParameterized, configure_state_ignores_commands) @@ -911,7 +910,7 @@ TEST_P(TrajectoryControllerTestParameterized, velocity_error) || (traj_controller_->has_velocity_state_interface() && traj_controller_->has_velocity_command_interface())) { - // don't check against a value, because spline intepolation might overshoot depending on + // don't check against a value, because spline interpolation might overshoot depending on // interface combinations EXPECT_GE(state_msg->error.velocities[0], points_velocities[0][0]); EXPECT_GE(state_msg->error.velocities[1], points_velocities[0][1]); @@ -929,50 +928,82 @@ TEST_P(TrajectoryControllerTestParameterized, test_jumbled_joint_order) { rclcpp::executors::SingleThreadedExecutor executor; SetUpAndActivateTrajectoryController(executor); + std::vector points_positions = {1.0, 2.0, 3.0}; + std::vector jumble_map = {1, 2, 0}; { trajectory_msgs::msg::JointTrajectory traj_msg; const std::vector jumbled_joint_names{ - joint_names_[1], joint_names_[2], joint_names_[0]}; + joint_names_[jumble_map[0]], joint_names_[jumble_map[1]], joint_names_[jumble_map[2]]}; + traj_msg.joint_names = jumbled_joint_names; traj_msg.header.stamp = rclcpp::Time(0); traj_msg.points.resize(1); traj_msg.points[0].time_from_start = rclcpp::Duration::from_seconds(0.25); traj_msg.points[0].positions.resize(3); - traj_msg.points[0].positions[0] = 2.0; - traj_msg.points[0].positions[1] = 3.0; - traj_msg.points[0].positions[2] = 1.0; - - if (traj_controller_->has_velocity_command_interface()) + traj_msg.points[0].positions[0] = points_positions.at(jumble_map[0]); + traj_msg.points[0].positions[1] = points_positions.at(jumble_map[1]); + traj_msg.points[0].positions[2] = points_positions.at(jumble_map[2]); + traj_msg.points[0].velocities.resize(3); + for (size_t i = 0; i < 3; i++) { - traj_msg.points[0].velocities.resize(3); - traj_msg.points[0].velocities[0] = -0.1; - traj_msg.points[0].velocities[1] = -0.1; - traj_msg.points[0].velocities[2] = -0.1; + // factor 2 comes from the linear interpolation in the spline trajectory for constant + // acceleration + traj_msg.points[0].velocities[i] = + 2 * (traj_msg.points[0].positions[i] - joint_pos_[jumble_map[i]]) / 0.25; } + trajectory_publisher_->publish(traj_msg); } traj_controller_->wait_for_trajectory(executor); - // update for 0.25 seconds + // update just before 0.25 seconds (shorter than the trajectory duration of 0.25 seconds, + // otherwise acceleration is zero from the spline trajectory) // TODO(destogl): Make this time a bit shorter to increase stability on the CI? // Currently COMMON_THRESHOLD is adjusted. - updateController(rclcpp::Duration::from_seconds(0.25)); + updateController(rclcpp::Duration::from_seconds(0.25 - 1e-3)); if (traj_controller_->has_position_command_interface()) { - EXPECT_NEAR(1.0, joint_pos_[0], COMMON_THRESHOLD); - EXPECT_NEAR(2.0, joint_pos_[1], COMMON_THRESHOLD); - EXPECT_NEAR(3.0, joint_pos_[2], COMMON_THRESHOLD); + EXPECT_NEAR(points_positions.at(0), joint_pos_[0], COMMON_THRESHOLD); + EXPECT_NEAR(points_positions.at(1), joint_pos_[1], COMMON_THRESHOLD); + EXPECT_NEAR(points_positions.at(2), joint_pos_[2], COMMON_THRESHOLD); } if (traj_controller_->has_velocity_command_interface()) { + // if use_closed_loop_pid_adapter_==false: we expect desired velocities from direct sampling + // if use_closed_loop_pid_adapter_==true: we expect desired velocities, because we use PID with + // feedforward term only EXPECT_GT(0.0, joint_vel_[0]); EXPECT_GT(0.0, joint_vel_[1]); EXPECT_GT(0.0, joint_vel_[2]); } - // TODO(anyone): add here checks for acceleration commands + + if (traj_controller_->has_acceleration_command_interface()) + { + if (traj_controller_->has_velocity_state_interface()) + { + EXPECT_GT(0.0, joint_acc_[0]); + EXPECT_GT(0.0, joint_acc_[1]); + EXPECT_GT(0.0, joint_acc_[2]); + } + else + { + // no velocity state interface: no acceleration from trajectory sampling + EXPECT_EQ(0.0, joint_acc_[0]); + EXPECT_EQ(0.0, joint_acc_[1]); + EXPECT_EQ(0.0, joint_acc_[2]); + } + } + + if (traj_controller_->has_effort_command_interface()) + { + // effort should be nonzero, because we use PID with feedforward term + EXPECT_GT(0.0, joint_eff_[0]); + EXPECT_GT(0.0, joint_eff_[1]); + EXPECT_GT(0.0, joint_eff_[2]); + } } /** @@ -1003,9 +1034,9 @@ TEST_P(TrajectoryControllerTestParameterized, test_partial_joint_list) traj_msg.points[0].positions[1] = 1.0; traj_msg.points[0].velocities.resize(2); traj_msg.points[0].velocities[0] = - copysign(2.0, traj_msg.points[0].positions[0] - initial_joint2_cmd); + std::copysign(2.0, traj_msg.points[0].positions[0] - initial_joint2_cmd); traj_msg.points[0].velocities[1] = - copysign(1.0, traj_msg.points[0].positions[1] - initial_joint1_cmd); + std::copysign(1.0, traj_msg.points[0].positions[1] - initial_joint1_cmd); trajectory_publisher_->publish(traj_msg); } @@ -1027,22 +1058,50 @@ TEST_P(TrajectoryControllerTestParameterized, test_partial_joint_list) { // estimate the sign of the velocity // joint rotates forward - EXPECT_TRUE(is_same_sign(traj_msg.points[0].positions[0] - initial_joint2_cmd, joint_vel_[0])); - EXPECT_TRUE(is_same_sign(traj_msg.points[0].positions[1] - initial_joint1_cmd, joint_vel_[1])); + EXPECT_TRUE( + is_same_sign_or_zero(traj_msg.points[0].positions[0] - initial_joint2_cmd, joint_vel_[0])); + EXPECT_TRUE( + is_same_sign_or_zero(traj_msg.points[0].positions[1] - initial_joint1_cmd, joint_vel_[1])); EXPECT_NEAR(0.0, joint_vel_[2], threshold) << "Joint 3 velocity should be 0.0 since it's not in the goal"; } + if (traj_controller_->has_acceleration_command_interface()) + { + // estimate the sign of the acceleration + // joint rotates forward + if (traj_controller_->has_velocity_state_interface()) + { + EXPECT_TRUE( + is_same_sign_or_zero(traj_msg.points[0].positions[0] - initial_joint2_cmd, joint_acc_[0])) + << "Joint1: " << traj_msg.points[0].positions[0] - initial_joint2_cmd << " vs. " + << joint_acc_[0]; + EXPECT_TRUE( + is_same_sign_or_zero(traj_msg.points[0].positions[1] - initial_joint1_cmd, joint_acc_[1])) + << "Joint2: " << traj_msg.points[0].positions[1] - initial_joint1_cmd << " vs. " + << joint_acc_[1]; + } + else + { + // no velocity state interface: no acceleration from trajectory sampling + EXPECT_EQ(0.0, joint_acc_[0]); + EXPECT_EQ(0.0, joint_acc_[1]); + } + EXPECT_NEAR(0.0, joint_acc_[2], threshold) + << "Joint 3 acc should be 0.0 since it's not in the goal"; + } + if (traj_controller_->has_effort_command_interface()) { // estimate the sign of the effort // joint rotates forward - EXPECT_TRUE(is_same_sign(traj_msg.points[0].positions[0] - initial_joint2_cmd, joint_eff_[0])); - EXPECT_TRUE(is_same_sign(traj_msg.points[0].positions[1] - initial_joint1_cmd, joint_eff_[1])); + EXPECT_TRUE( + is_same_sign_or_zero(traj_msg.points[0].positions[0] - initial_joint2_cmd, joint_eff_[0])); + EXPECT_TRUE( + is_same_sign_or_zero(traj_msg.points[0].positions[1] - initial_joint1_cmd, joint_eff_[1])); EXPECT_NEAR(0.0, joint_eff_[2], threshold) << "Joint 3 effort should be 0.0 since it's not in the goal"; } - // TODO(anyone): add here checks for acceleration commands executor.cancel(); } @@ -1284,7 +1343,7 @@ TEST_P(TrajectoryControllerTestParameterized, test_trajectory_replace) RCLCPP_INFO(traj_controller_->get_node()->get_logger(), "Sending new trajectory"); points_partial_new_velocities[0][0] = - copysign(0.15, points_partial_new[0][0] - joint_state_pos_[0]); + std::copysign(0.15, points_partial_new[0][0] - joint_state_pos_[0]); publish(time_from_start, points_partial_new, rclcpp::Time(), {}, points_partial_new_velocities); // Replaced trajectory is a mix of previous and current goal From ca38c06f712663449ddf1372234d74a983b7d5f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Fri, 29 Sep 2023 20:07:47 +0200 Subject: [PATCH 121/238] Improve docs (#785) --- ackermann_steering_controller/doc/userdoc.rst | 2 ++ bicycle_steering_controller/doc/userdoc.rst | 2 ++ .../src/steering_controllers_library.yaml | 12 ++++++------ tricycle_steering_controller/doc/userdoc.rst | 2 ++ 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/ackermann_steering_controller/doc/userdoc.rst b/ackermann_steering_controller/doc/userdoc.rst index c4ae35e5b0..daf4561861 100644 --- a/ackermann_steering_controller/doc/userdoc.rst +++ b/ackermann_steering_controller/doc/userdoc.rst @@ -19,4 +19,6 @@ This controller uses the `generate_parameter_library `, this controller adds the following parameters: + .. generate_parameter_library_details:: ../src/ackermann_steering_controller.yaml diff --git a/bicycle_steering_controller/doc/userdoc.rst b/bicycle_steering_controller/doc/userdoc.rst index a720ff887d..6fccaf7b73 100644 --- a/bicycle_steering_controller/doc/userdoc.rst +++ b/bicycle_steering_controller/doc/userdoc.rst @@ -20,4 +20,6 @@ This controller uses the `generate_parameter_library `, this controller adds the following parameters: + .. generate_parameter_library_details:: ../src/bicycle_steering_controller.yaml diff --git a/steering_controllers_library/src/steering_controllers_library.yaml b/steering_controllers_library/src/steering_controllers_library.yaml index 86acb01dae..8acdfb1448 100644 --- a/steering_controllers_library/src/steering_controllers_library.yaml +++ b/steering_controllers_library/src/steering_controllers_library.yaml @@ -59,7 +59,7 @@ steering_controllers_library: open_loop: { type: bool, default_value: false, - description: "bool parameter decides if open oop or not (feedback).", + description: "Choose if open-loop or not (feedback) is used for odometry calculation.", read_only: false, } @@ -87,7 +87,7 @@ steering_controllers_library: enable_odom_tf: { type: bool, default_value: true, - description: "Publishing to tf is enabled or disabled ?.", + description: "Publishing to tf is enabled or disabled?", read_only: false, } @@ -108,15 +108,15 @@ steering_controllers_library: position_feedback: { type: bool, default_value: false, - description: "Choice of feedback type, if position_feedback is false then HW_IF_VELOCITY is taken as interface type, if - position_feedback is true then HW_IF_POSITION is taken as interface type", + description: "Choice of feedback type, if position_feedback is false then ``HW_IF_VELOCITY`` is taken as interface type, if + position_feedback is true then ``HW_IF_POSITION`` is taken as interface type", read_only: false, } use_stamped_vel: { type: bool, default_value: false, - description: "Choice of vel type, if use_stamped_vel is false then geometry_msgs::msg::Twist is taken as vel msg type, if - use_stamped_vel is true then geometry_msgs::msg::TwistStamped is taken as vel msg type", + description: "Choice of vel type, if use_stamped_vel is false then ``geometry_msgs::msg::Twist`` is taken as vel msg type, if + use_stamped_vel is true then ``geometry_msgs::msg::TwistStamped`` is taken as vel msg type", read_only: false, } diff --git a/tricycle_steering_controller/doc/userdoc.rst b/tricycle_steering_controller/doc/userdoc.rst index d76f489745..618d7f04a7 100644 --- a/tricycle_steering_controller/doc/userdoc.rst +++ b/tricycle_steering_controller/doc/userdoc.rst @@ -19,4 +19,6 @@ This controller uses the `generate_parameter_library `, this controller adds the following parameters: + .. generate_parameter_library_details:: ../src/tricycle_steering_controller.yaml From 26a130b8fef94854d94b866b3e5d272e6bf29262 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Oct 2023 07:49:22 +0100 Subject: [PATCH 122/238] Bump actions/setup-python from 4.7.0 to 4.7.1 (#788) --- .github/workflows/ci-format.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-format.yml b/.github/workflows/ci-format.yml index c868650adb..5d801016f9 100644 --- a/.github/workflows/ci-format.yml +++ b/.github/workflows/ci-format.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: actions/setup-python@v4.7.0 + - uses: actions/setup-python@v4.7.1 with: python-version: '3.10' - name: Install system hooks From f62fc3ac5f480b5a74765e642cd33d17600f7f5a Mon Sep 17 00:00:00 2001 From: Reza Kermani Date: Fri, 6 Oct 2023 04:04:59 -0400 Subject: [PATCH 123/238] writing_new_controller docs fix (#790) * fixing structure * format * typo fix --- doc/writing_new_controller.rst | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/doc/writing_new_controller.rst b/doc/writing_new_controller.rst index 0475f8f4fd..501c231def 100644 --- a/doc/writing_new_controller.rst +++ b/doc/writing_new_controller.rst @@ -34,10 +34,12 @@ The following is a step-by-step guide to create source files, basic tests, and c 3. Define a unique namespace for your controller. This is usually a package name written in ``snake_case``. 4. Define the class of the controller, extending ``ControllerInterface``, e.g., + .. code:: c++ - class ControllerName : public controller_interface::ControllerInterface - 5. Add a constructor without parameters and the following public methods overriding the ``ControllerInterface`` definition: ``init``, ``command_interface_configuration``, ``state_interface_configuration``, ``on_configure``, ``on_activate``, ``on_deactivate``, ``update``. + class ControllerName : public controller_interface::ControllerInterface + + 5. Add a constructor without parameters and the following public methods overriding the ``ControllerInterface`` definition: ``on_init``, ``command_interface_configuration``, ``state_interface_configuration``, ``on_configure``, ``on_activate``, ``on_deactivate``, ``update``. For exact definitions check the ``controller_interface/controller_interface.hpp`` header or one of the controllers from `ros2_controllers `_. 6. (optional) Often, controllers accept lists of joint names and interface names as parameters. @@ -48,9 +50,9 @@ The following is a step-by-step guide to create source files, basic tests, and c 1. Include the header file of your controller and add a namespace definition to simplify further development. 2. (optional) Implement a constructor if needed. There, you could initialize member variables. - This could also be done in the ``init`` method. + This could also be done in the ``on_init`` method. - 3. Implement the ``init`` method. The first line usually calls the parent ``init`` method. + 3. Implement the ``on_init`` method. The first line usually calls the parent ``on_init`` method. Here is the best place to initialize the variables, reserve memory, and most importantly, declare node parameters used by the controller. If everything works fine return ``controller_interface::return_type::OK`` or ``controller_interface::return_type::ERROR`` otherwise. 4. Write the ``on_configure`` method. Parameters are usually read here, and everything is prepared so that the controller can be started. @@ -105,6 +107,7 @@ The following is a step-by-step guide to create source files, basic tests, and c 4. Add ament dependencies needed by the library. You should add at least those listed under 1. 5. Export for pluginlib description file using the following command: + .. code:: cmake pluginlib_export_plugin_description_file(controller_interface .xml) From c831b6cee52886bf3e93300b63f7b8d9e3566bb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Mon, 16 Oct 2023 12:58:44 +0200 Subject: [PATCH 124/238] Update requirements of state interfaces (#798) --- joint_trajectory_controller/doc/userdoc.rst | 10 ++++++++-- .../validate_jtc_parameters.hpp | 4 ++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/joint_trajectory_controller/doc/userdoc.rst b/joint_trajectory_controller/doc/userdoc.rst index deedc4a7b6..58ba734b45 100644 --- a/joint_trajectory_controller/doc/userdoc.rst +++ b/joint_trajectory_controller/doc/userdoc.rst @@ -17,7 +17,7 @@ Waypoints consist of positions, and optionally velocities and accelerations. Hardware interface types ------------------------------- -Currently, joints with hardware interface types ``position``, ``velocity``, ``acceleration``, and ``effort`` (defined `here `_) are supported in the following combinations: +Currently, joints with hardware interface types ``position``, ``velocity``, ``acceleration``, and ``effort`` (defined `here `_) are supported in the following combinations as command interfaces: * ``position`` * ``position``, ``velocity`` @@ -37,10 +37,16 @@ This leads to the following allowed combinations of command and state interfaces * With command interface ``velocity``: * if command interface ``velocity`` is the only one, state interfaces must include ``position, velocity`` . - * no restrictions otherwise. * With command interface ``effort``, state interfaces must include ``position, velocity``. +* With command interface ``acceleration``, state interfaces must include ``position, velocity``. + +Further restrictions of state interfaces exist: + +* ``velocity`` state interface cannot be used if ``position`` interface is missing. +* ``acceleration`` state interface cannot be used if ``position`` and ``velocity`` interfaces are not present." + Example controller configurations can be found :ref:`below `. Other features diff --git a/joint_trajectory_controller/include/joint_trajectory_controller/validate_jtc_parameters.hpp b/joint_trajectory_controller/include/joint_trajectory_controller/validate_jtc_parameters.hpp index 5a656e7754..0a6bf99bb7 100644 --- a/joint_trajectory_controller/include/joint_trajectory_controller/validate_jtc_parameters.hpp +++ b/joint_trajectory_controller/include/joint_trajectory_controller/validate_jtc_parameters.hpp @@ -41,7 +41,7 @@ tl::expected command_interface_type_combinations( { return tl::make_unexpected( "'velocity' command interface can be used either alone or 'position' " - "interface has to be present"); + "command interface has to be present"); } if ( @@ -51,7 +51,7 @@ tl::expected command_interface_type_combinations( { return tl::make_unexpected( "'acceleration' command interface can only be used if 'velocity' and " - "'position' interfaces are present"); + "'position' command interfaces are present"); } if ( From ac291ab511545074564155f361673d8301550d74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Mon, 16 Oct 2023 13:00:53 +0200 Subject: [PATCH 125/238] Steering controllers library: fix open loop mode (#793) * set last*velocity variables for open loop odometry * Make function arguments const * Update function in header file too --- .../steering_controllers_library/steering_odometry.hpp | 3 ++- .../src/steering_controllers_library.cpp | 7 ++++--- steering_controllers_library/src/steering_odometry.cpp | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/steering_controllers_library/include/steering_controllers_library/steering_odometry.hpp b/steering_controllers_library/include/steering_controllers_library/steering_odometry.hpp index 3cfa056b27..95bcef7e63 100644 --- a/steering_controllers_library/include/steering_controllers_library/steering_odometry.hpp +++ b/steering_controllers_library/include/steering_controllers_library/steering_odometry.hpp @@ -184,7 +184,8 @@ class SteeringOdometry * \param theta_dot Desired angular velocity [rad/s] * \return Tuple of velocity commands and steering commands */ - std::tuple, std::vector> get_commands(double Vx, double theta_dot); + std::tuple, std::vector> get_commands( + const double Vx, const double theta_dot); /** * \brief Reset poses, heading, and accumulators diff --git a/steering_controllers_library/src/steering_controllers_library.cpp b/steering_controllers_library/src/steering_controllers_library.cpp index af2736a8a3..eb497ebb3d 100644 --- a/steering_controllers_library/src/steering_controllers_library.cpp +++ b/steering_controllers_library/src/steering_controllers_library.cpp @@ -443,10 +443,11 @@ controller_interface::return_type SteeringControllersLibrary::update_and_write_c if (!std::isnan(reference_interfaces_[0]) && !std::isnan(reference_interfaces_[1])) { // store and set commands - const double linear_command = reference_interfaces_[0]; - const double angular_command = reference_interfaces_[1]; + last_linear_velocity_ = reference_interfaces_[0]; + last_angular_velocity_ = reference_interfaces_[1]; + auto [traction_commands, steering_commands] = - odometry_.get_commands(linear_command, angular_command); + odometry_.get_commands(last_linear_velocity_, last_angular_velocity_); if (params_.front_steering) { for (size_t i = 0; i < params_.rear_wheels_names.size(); i++) diff --git a/steering_controllers_library/src/steering_odometry.cpp b/steering_controllers_library/src/steering_odometry.cpp index 0a7dc23ef2..bf254bfcfa 100644 --- a/steering_controllers_library/src/steering_odometry.cpp +++ b/steering_controllers_library/src/steering_odometry.cpp @@ -210,7 +210,7 @@ double SteeringOdometry::convert_trans_rot_vel_to_steering_angle(double Vx, doub } std::tuple, std::vector> SteeringOdometry::get_commands( - double Vx, double theta_dot) + const double Vx, const double theta_dot) { // desired velocity and steering angle of the middle of traction and steering axis double Ws, alpha; From 22356e0e9d39c726926f3f3a0ddb7afd51333295 Mon Sep 17 00:00:00 2001 From: "Dr. Denis" Date: Mon, 16 Oct 2023 18:49:47 +0200 Subject: [PATCH 126/238] [TestNodes] Optimize output about setup of JTC publisher (#792) --- .../publisher_forward_position_controller.py | 4 ++-- .../publisher_joint_trajectory_controller.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ros2_controllers_test_nodes/ros2_controllers_test_nodes/publisher_forward_position_controller.py b/ros2_controllers_test_nodes/ros2_controllers_test_nodes/publisher_forward_position_controller.py index 59a39164ec..5cf28ac604 100644 --- a/ros2_controllers_test_nodes/ros2_controllers_test_nodes/publisher_forward_position_controller.py +++ b/ros2_controllers_test_nodes/ros2_controllers_test_nodes/publisher_forward_position_controller.py @@ -46,8 +46,8 @@ def __init__(self): self.goals.append(float_goal) self.get_logger().info( - f'Publishing {len(goal_names)} goals on topic "{publish_topic}"\ - every {wait_sec_between_publish} s' + f"Publishing {len(goal_names)} goals on topic '{publish_topic}' " + f"every {wait_sec_between_publish} s'" ) self.publisher_ = self.create_publisher(Float64MultiArray, publish_topic, 1) diff --git a/ros2_controllers_test_nodes/ros2_controllers_test_nodes/publisher_joint_trajectory_controller.py b/ros2_controllers_test_nodes/ros2_controllers_test_nodes/publisher_joint_trajectory_controller.py index 4ed198515e..cb66f58468 100644 --- a/ros2_controllers_test_nodes/ros2_controllers_test_nodes/publisher_joint_trajectory_controller.py +++ b/ros2_controllers_test_nodes/ros2_controllers_test_nodes/publisher_joint_trajectory_controller.py @@ -129,8 +129,8 @@ def get_sub_param(sub_param): publish_topic = "/" + controller_name + "/" + "joint_trajectory" self.get_logger().info( - f'Publishing {len(goal_names)} goals on topic "{publish_topic}" every ' - "{wait_sec_between_publish} s" + f"Publishing {len(goal_names)} goals on topic '{publish_topic}' every " + f"{wait_sec_between_publish} s" ) self.publisher_ = self.create_publisher(JointTrajectory, publish_topic, 1) From b36b9d20f186f50ce9261aa8a55fb0d28f849959 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Tue, 24 Oct 2023 20:17:28 +0200 Subject: [PATCH 127/238] [CI] Fix coverage build and codecov stats (#804) --- .github/workflows/ci-coverage-build.yml | 18 +++++++++++++++++- codecov.yml | 2 ++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci-coverage-build.yml b/.github/workflows/ci-coverage-build.yml index d2dba1bce8..8ca9b968d3 100644 --- a/.github/workflows/ci-coverage-build.yml +++ b/.github/workflows/ci-coverage-build.yml @@ -27,9 +27,25 @@ jobs: with: target-ros2-distro: ${{ env.ROS_DISTRO }} import-token: ${{ secrets.GITHUB_TOKEN }} - # build all packages listed in the meta package + # build all packages listed here package-name: + ackermann_steering_controller + admittance_controller + bicycle_steering_controller diff_drive_controller + effort_controllers + force_torque_sensor_broadcaster + forward_command_controller + gripper_controllers + imu_sensor_broadcaster + joint_state_broadcaster + joint_trajectory_controller + position_controllers + range_sensor_broadcaster + steering_controllers_library + tricycle_controller + tricycle_steering_controller + velocity_controllers vcs-repo-file-url: | https://raw.githubusercontent.com/${{ github.repository }}/${{ github.sha }}/ros2_controllers-not-released.${{ env.ROS_DISTRO }}.repos?token=${{ secrets.GITHUB_TOKEN }} diff --git a/codecov.yml b/codecov.yml index 02deea2321..ca8c1cc0ac 100644 --- a/codecov.yml +++ b/codecov.yml @@ -9,6 +9,8 @@ coverage: patch: off fixes: - "ros_ws/src/ros2_controllers/::" +ignore: + - "**/test" comment: layout: "diff, flags, files" behavior: default From b65314d6fcb0d57b3c86e7bf3b05baa4ccdb984f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Thu, 26 Oct 2023 12:09:27 +0200 Subject: [PATCH 128/238] Cleanup comments and unnecessary checks (#803) --- .../joint_trajectory_controller.hpp | 6 ++---- .../src/joint_trajectory_controller.cpp | 18 +----------------- 2 files changed, 3 insertions(+), 21 deletions(-) diff --git a/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp b/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp index b3e2f55742..0366c8e6d6 100644 --- a/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp +++ b/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp @@ -71,15 +71,13 @@ class JointTrajectoryController : public controller_interface::ControllerInterfa JointTrajectoryController(); /** - * @brief command_interface_configuration This controller requires the position command - * interfaces for the controlled joints + * @brief command_interface_configuration */ JOINT_TRAJECTORY_CONTROLLER_PUBLIC controller_interface::InterfaceConfiguration command_interface_configuration() const override; /** - * @brief command_interface_configuration This controller requires the position and velocity - * state interfaces for the controlled joints + * @brief command_interface_configuration */ JOINT_TRAJECTORY_CONTROLLER_PUBLIC controller_interface::InterfaceConfiguration state_interface_configuration() const override; diff --git a/joint_trajectory_controller/src/joint_trajectory_controller.cpp b/joint_trajectory_controller/src/joint_trajectory_controller.cpp index 5e39bffc73..9e0b4823f3 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller.cpp +++ b/joint_trajectory_controller/src/joint_trajectory_controller.cpp @@ -651,17 +651,7 @@ controller_interface::CallbackReturn JointTrajectoryController::on_configure( // get parameters from the listener in case they were updated params_ = param_listener_->get_params(); - // Check if the DoF has changed - if ((dof_ > 0) && (params_.joints.size() != dof_)) - { - RCLCPP_ERROR( - logger, - "The JointTrajectoryController does not support restarting with a different number of DOF"); - // TODO(andyz): update vector lengths if num. joints did change and re-initialize them so we - // can continue - return CallbackReturn::FAILURE; - } - + // get degrees of freedom dof_ = params_.joints.size(); // TODO(destogl): why is this here? Add comment or move @@ -691,12 +681,6 @@ controller_interface::CallbackReturn JointTrajectoryController::on_configure( return CallbackReturn::FAILURE; } - // // Specialized, child controllers set interfaces before calling configure function. - // if (command_interface_types_.empty()) - // { - // command_interface_types_ = get_node()->get_parameter("command_interfaces").as_string_array(); - // } - if (params_.command_interfaces.empty()) { RCLCPP_ERROR(logger, "'command_interfaces' parameter is empty."); From 8a90b5143669c61ec8eded494cc8c75bbb6c07e5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 31 Oct 2023 20:27:04 +0000 Subject: [PATCH 129/238] Bump ros-tooling/action-ros-ci from 0.3.3 to 0.3.4 (#810) --- .github/workflows/ci-coverage-build.yml | 2 +- .github/workflows/reusable-ros-tooling-source-build.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-coverage-build.yml b/.github/workflows/ci-coverage-build.yml index 8ca9b968d3..d33ee89cc9 100644 --- a/.github/workflows/ci-coverage-build.yml +++ b/.github/workflows/ci-coverage-build.yml @@ -23,7 +23,7 @@ jobs: with: required-ros-distributions: ${{ env.ROS_DISTRO }} - uses: actions/checkout@v4 - - uses: ros-tooling/action-ros-ci@0.3.3 + - uses: ros-tooling/action-ros-ci@0.3.4 with: target-ros2-distro: ${{ env.ROS_DISTRO }} import-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/reusable-ros-tooling-source-build.yml b/.github/workflows/reusable-ros-tooling-source-build.yml index 167386ceff..ad3dcd505d 100644 --- a/.github/workflows/reusable-ros-tooling-source-build.yml +++ b/.github/workflows/reusable-ros-tooling-source-build.yml @@ -32,7 +32,7 @@ jobs: - uses: actions/checkout@v4 with: ref: ${{ inputs.ref }} - - uses: ros-tooling/action-ros-ci@0.3.3 + - uses: ros-tooling/action-ros-ci@0.3.4 with: target-ros2-distro: ${{ inputs.ros_distro }} ref: ${{ inputs.ref }} From 822552fb700885ca8a821651c13eb5263e2c148c Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Tue, 31 Oct 2023 21:33:40 +0000 Subject: [PATCH 130/238] Update changelogs --- ackermann_steering_controller/CHANGELOG.rst | 5 +++++ admittance_controller/CHANGELOG.rst | 3 +++ bicycle_steering_controller/CHANGELOG.rst | 5 +++++ diff_drive_controller/CHANGELOG.rst | 3 +++ effort_controllers/CHANGELOG.rst | 3 +++ force_torque_sensor_broadcaster/CHANGELOG.rst | 3 +++ forward_command_controller/CHANGELOG.rst | 3 +++ gripper_controllers/CHANGELOG.rst | 3 +++ imu_sensor_broadcaster/CHANGELOG.rst | 3 +++ joint_state_broadcaster/CHANGELOG.rst | 3 +++ joint_trajectory_controller/CHANGELOG.rst | 7 +++++++ position_controllers/CHANGELOG.rst | 3 +++ range_sensor_broadcaster/CHANGELOG.rst | 3 +++ ros2_controllers/CHANGELOG.rst | 3 +++ ros2_controllers_test_nodes/CHANGELOG.rst | 5 +++++ rqt_joint_trajectory_controller/CHANGELOG.rst | 3 +++ steering_controllers_library/CHANGELOG.rst | 9 +++++++++ tricycle_controller/CHANGELOG.rst | 3 +++ tricycle_steering_controller/CHANGELOG.rst | 5 +++++ velocity_controllers/CHANGELOG.rst | 3 +++ 20 files changed, 78 insertions(+) diff --git a/ackermann_steering_controller/CHANGELOG.rst b/ackermann_steering_controller/CHANGELOG.rst index d576811bdb..171dd78b5f 100644 --- a/ackermann_steering_controller/CHANGELOG.rst +++ b/ackermann_steering_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package ackermann_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Improve docs (`#785 `_) +* Contributors: Christoph Fröhlich + 3.16.0 (2023-09-20) ------------------- diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index e17d56865d..077d31f1de 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.16.0 (2023-09-20) ------------------- diff --git a/bicycle_steering_controller/CHANGELOG.rst b/bicycle_steering_controller/CHANGELOG.rst index 7c652e7fa7..aed3400b0a 100644 --- a/bicycle_steering_controller/CHANGELOG.rst +++ b/bicycle_steering_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package bicycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Improve docs (`#785 `_) +* Contributors: Christoph Fröhlich + 3.16.0 (2023-09-20) ------------------- diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index d670ccc047..0369169b8f 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.16.0 (2023-09-20) ------------------- diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index efc583475d..5b36e548a5 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.16.0 (2023-09-20) ------------------- * [Doc] Add specific documentation on the available fw cmd controllers (`#765 `_) diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index 70fe56b159..0d9dc0f8dd 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.16.0 (2023-09-20) ------------------- diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index ca209a52f5..7cefd99297 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.16.0 (2023-09-20) ------------------- * [Doc] Add specific documentation on the available fw cmd controllers (`#765 `_) diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index bc66422a37..3b2a414598 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.16.0 (2023-09-20) ------------------- diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index 477134c496..fcda055f9d 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.16.0 (2023-09-20) ------------------- diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index 35298737f0..71df1d5728 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.16.0 (2023-09-20) ------------------- diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index a322fef5ad..e294291f02 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,13 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Cleanup comments and unnecessary checks (`#803 `_) +* Update requirements of state interfaces (`#798 `_) +* [JTC] Add tests for acceleration command interface (`#752 `_) +* Contributors: Christoph Fröhlich + 3.16.0 (2023-09-20) ------------------- * [Docs] Improve interface description of JTC (`#770 `_) diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index 06e2f3e8db..b0492117d2 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.16.0 (2023-09-20) ------------------- * [Doc] Add specific documentation on the available fw cmd controllers (`#765 `_) diff --git a/range_sensor_broadcaster/CHANGELOG.rst b/range_sensor_broadcaster/CHANGELOG.rst index 9d5242684a..499a28868d 100644 --- a/range_sensor_broadcaster/CHANGELOG.rst +++ b/range_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package range_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.16.0 (2023-09-20) ------------------- diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index d21abd09ca..012264e6e6 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.16.0 (2023-09-20) ------------------- diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index 525d0a0221..07b540f28a 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* [TestNodes] Optimize output about setup of JTC publisher (`#792 `_) +* Contributors: Dr. Denis + 3.16.0 (2023-09-20) ------------------- diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index ecf0568408..6c7f06200c 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.16.0 (2023-09-20) ------------------- diff --git a/steering_controllers_library/CHANGELOG.rst b/steering_controllers_library/CHANGELOG.rst index a7546cb59d..e3b9d163af 100644 --- a/steering_controllers_library/CHANGELOG.rst +++ b/steering_controllers_library/CHANGELOG.rst @@ -2,6 +2,15 @@ Changelog for package steering_controllers_library ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Steering controllers library: fix open loop mode (`#793 `_) + * set last*velocity variables for open loop odometry + * Make function arguments const + * Update function in header file too +* Improve docs (`#785 `_) +* Contributors: Christoph Fröhlich + 3.16.0 (2023-09-20) ------------------- diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index 91175391f3..5cad2f94f7 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.16.0 (2023-09-20) ------------------- diff --git a/tricycle_steering_controller/CHANGELOG.rst b/tricycle_steering_controller/CHANGELOG.rst index dd50c98185..a4645ebfb5 100644 --- a/tricycle_steering_controller/CHANGELOG.rst +++ b/tricycle_steering_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package tricycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Improve docs (`#785 `_) +* Contributors: Christoph Fröhlich + 3.16.0 (2023-09-20) ------------------- diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index ce8bcfefa3..0b8c320035 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.16.0 (2023-09-20) ------------------- * [Doc] Add specific documentation on the available fw cmd controllers (`#765 `_) From 6e4605316ab63c8407f58f40884bebc90ca0b2be Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Tue, 31 Oct 2023 21:34:10 +0000 Subject: [PATCH 131/238] 3.17.0 --- ackermann_steering_controller/CHANGELOG.rst | 4 ++-- ackermann_steering_controller/package.xml | 2 +- admittance_controller/CHANGELOG.rst | 4 ++-- admittance_controller/package.xml | 2 +- bicycle_steering_controller/CHANGELOG.rst | 4 ++-- bicycle_steering_controller/package.xml | 2 +- diff_drive_controller/CHANGELOG.rst | 4 ++-- diff_drive_controller/package.xml | 2 +- effort_controllers/CHANGELOG.rst | 4 ++-- effort_controllers/package.xml | 2 +- force_torque_sensor_broadcaster/CHANGELOG.rst | 4 ++-- force_torque_sensor_broadcaster/package.xml | 2 +- forward_command_controller/CHANGELOG.rst | 4 ++-- forward_command_controller/package.xml | 2 +- gripper_controllers/CHANGELOG.rst | 4 ++-- gripper_controllers/package.xml | 2 +- imu_sensor_broadcaster/CHANGELOG.rst | 4 ++-- imu_sensor_broadcaster/package.xml | 2 +- joint_state_broadcaster/CHANGELOG.rst | 4 ++-- joint_state_broadcaster/package.xml | 2 +- joint_trajectory_controller/CHANGELOG.rst | 4 ++-- joint_trajectory_controller/package.xml | 2 +- position_controllers/CHANGELOG.rst | 4 ++-- position_controllers/package.xml | 2 +- range_sensor_broadcaster/CHANGELOG.rst | 4 ++-- range_sensor_broadcaster/package.xml | 2 +- ros2_controllers/CHANGELOG.rst | 4 ++-- ros2_controllers/package.xml | 2 +- ros2_controllers_test_nodes/CHANGELOG.rst | 4 ++-- ros2_controllers_test_nodes/package.xml | 2 +- ros2_controllers_test_nodes/setup.py | 2 +- rqt_joint_trajectory_controller/CHANGELOG.rst | 4 ++-- rqt_joint_trajectory_controller/package.xml | 2 +- rqt_joint_trajectory_controller/setup.py | 2 +- steering_controllers_library/CHANGELOG.rst | 4 ++-- steering_controllers_library/package.xml | 2 +- tricycle_controller/CHANGELOG.rst | 4 ++-- tricycle_controller/package.xml | 2 +- tricycle_steering_controller/CHANGELOG.rst | 4 ++-- tricycle_steering_controller/package.xml | 2 +- velocity_controllers/CHANGELOG.rst | 4 ++-- velocity_controllers/package.xml | 2 +- 42 files changed, 62 insertions(+), 62 deletions(-) diff --git a/ackermann_steering_controller/CHANGELOG.rst b/ackermann_steering_controller/CHANGELOG.rst index 171dd78b5f..d679a782d4 100644 --- a/ackermann_steering_controller/CHANGELOG.rst +++ b/ackermann_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ackermann_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.17.0 (2023-10-31) +------------------- * Improve docs (`#785 `_) * Contributors: Christoph Fröhlich diff --git a/ackermann_steering_controller/package.xml b/ackermann_steering_controller/package.xml index f866089f1c..656c88feae 100644 --- a/ackermann_steering_controller/package.xml +++ b/ackermann_steering_controller/package.xml @@ -2,7 +2,7 @@ ackermann_steering_controller - 3.16.0 + 3.17.0 Steering controller for Ackermann kinematics. Rear fixed wheels are powering the vehicle and front wheels are steering it. Apache License 2.0 Bence Magyar diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index 077d31f1de..ba5a131094 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.17.0 (2023-10-31) +------------------- 3.16.0 (2023-09-20) ------------------- diff --git a/admittance_controller/package.xml b/admittance_controller/package.xml index 43a7ab0aad..62cf127d9f 100644 --- a/admittance_controller/package.xml +++ b/admittance_controller/package.xml @@ -2,7 +2,7 @@ admittance_controller - 3.16.0 + 3.17.0 Implementation of admittance controllers for different input and output interface. Denis Štogl Bence Magyar diff --git a/bicycle_steering_controller/CHANGELOG.rst b/bicycle_steering_controller/CHANGELOG.rst index aed3400b0a..7b14b2d617 100644 --- a/bicycle_steering_controller/CHANGELOG.rst +++ b/bicycle_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package bicycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.17.0 (2023-10-31) +------------------- * Improve docs (`#785 `_) * Contributors: Christoph Fröhlich diff --git a/bicycle_steering_controller/package.xml b/bicycle_steering_controller/package.xml index 8707502915..9ee4c53049 100644 --- a/bicycle_steering_controller/package.xml +++ b/bicycle_steering_controller/package.xml @@ -2,7 +2,7 @@ bicycle_steering_controller - 3.16.0 + 3.17.0 Steering controller with bicycle kinematics. Rear fixed wheel is powering the vehicle and front wheel is steering. Apache License 2.0 Bence Magyar diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index 0369169b8f..b3f4b127e3 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.17.0 (2023-10-31) +------------------- 3.16.0 (2023-09-20) ------------------- diff --git a/diff_drive_controller/package.xml b/diff_drive_controller/package.xml index 611dfbe15a..01dc69413a 100644 --- a/diff_drive_controller/package.xml +++ b/diff_drive_controller/package.xml @@ -1,7 +1,7 @@ diff_drive_controller - 3.16.0 + 3.17.0 Controller for a differential drive mobile base. Bence Magyar Jordan Palacios diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index 5b36e548a5..baaada7c22 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.17.0 (2023-10-31) +------------------- 3.16.0 (2023-09-20) ------------------- diff --git a/effort_controllers/package.xml b/effort_controllers/package.xml index 9e3cc8bc32..d0627bea10 100644 --- a/effort_controllers/package.xml +++ b/effort_controllers/package.xml @@ -1,7 +1,7 @@ effort_controllers - 3.16.0 + 3.17.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index 0d9dc0f8dd..9b6dea8ef9 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.17.0 (2023-10-31) +------------------- 3.16.0 (2023-09-20) ------------------- diff --git a/force_torque_sensor_broadcaster/package.xml b/force_torque_sensor_broadcaster/package.xml index 12ec3d1945..81c865ddfb 100644 --- a/force_torque_sensor_broadcaster/package.xml +++ b/force_torque_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ force_torque_sensor_broadcaster - 3.16.0 + 3.17.0 Controller to publish state of force-torque sensors. Bence Magyar Denis Štogl diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index 7cefd99297..4bc9d41c74 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.17.0 (2023-10-31) +------------------- 3.16.0 (2023-09-20) ------------------- diff --git a/forward_command_controller/package.xml b/forward_command_controller/package.xml index c8d0b99a59..246bc6777d 100644 --- a/forward_command_controller/package.xml +++ b/forward_command_controller/package.xml @@ -1,7 +1,7 @@ forward_command_controller - 3.16.0 + 3.17.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index 3b2a414598..b7c7242520 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.17.0 (2023-10-31) +------------------- 3.16.0 (2023-09-20) ------------------- diff --git a/gripper_controllers/package.xml b/gripper_controllers/package.xml index dcd778363e..391bd1bb7d 100644 --- a/gripper_controllers/package.xml +++ b/gripper_controllers/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> gripper_controllers - 3.16.0 + 3.17.0 The gripper_controllers package Bence Magyar diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index fcda055f9d..8644b008a0 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.17.0 (2023-10-31) +------------------- 3.16.0 (2023-09-20) ------------------- diff --git a/imu_sensor_broadcaster/package.xml b/imu_sensor_broadcaster/package.xml index 6173569630..2dcacc1f0f 100644 --- a/imu_sensor_broadcaster/package.xml +++ b/imu_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ imu_sensor_broadcaster - 3.16.0 + 3.17.0 Controller to publish readings of IMU sensors. Bence Magyar Denis Štogl diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index 71df1d5728..fd56b72c3b 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.17.0 (2023-10-31) +------------------- 3.16.0 (2023-09-20) ------------------- diff --git a/joint_state_broadcaster/package.xml b/joint_state_broadcaster/package.xml index 05f761169a..e4fecb14d7 100644 --- a/joint_state_broadcaster/package.xml +++ b/joint_state_broadcaster/package.xml @@ -1,7 +1,7 @@ joint_state_broadcaster - 3.16.0 + 3.17.0 Broadcaster to publish joint state Bence Magyar Denis Stogl diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index e294291f02..9eece3af21 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.17.0 (2023-10-31) +------------------- * Cleanup comments and unnecessary checks (`#803 `_) * Update requirements of state interfaces (`#798 `_) * [JTC] Add tests for acceleration command interface (`#752 `_) diff --git a/joint_trajectory_controller/package.xml b/joint_trajectory_controller/package.xml index d8f2e8e997..f4efc2c060 100644 --- a/joint_trajectory_controller/package.xml +++ b/joint_trajectory_controller/package.xml @@ -1,7 +1,7 @@ joint_trajectory_controller - 3.16.0 + 3.17.0 Controller for executing joint-space trajectories on a group of joints Bence Magyar Jordan Palacios diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index b0492117d2..5239c43407 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.17.0 (2023-10-31) +------------------- 3.16.0 (2023-09-20) ------------------- diff --git a/position_controllers/package.xml b/position_controllers/package.xml index 712d03068a..b3cd9b6cfb 100644 --- a/position_controllers/package.xml +++ b/position_controllers/package.xml @@ -1,7 +1,7 @@ position_controllers - 3.16.0 + 3.17.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/range_sensor_broadcaster/CHANGELOG.rst b/range_sensor_broadcaster/CHANGELOG.rst index 499a28868d..b1084b4a24 100644 --- a/range_sensor_broadcaster/CHANGELOG.rst +++ b/range_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package range_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.17.0 (2023-10-31) +------------------- 3.16.0 (2023-09-20) ------------------- diff --git a/range_sensor_broadcaster/package.xml b/range_sensor_broadcaster/package.xml index 70d9c1fa2f..cf6545d65e 100644 --- a/range_sensor_broadcaster/package.xml +++ b/range_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ range_sensor_broadcaster - 3.16.0 + 3.17.0 Controller to publish readings of Range sensors. Bence Magyar Florent Chretien diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index 012264e6e6..187db3d351 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.17.0 (2023-10-31) +------------------- 3.16.0 (2023-09-20) ------------------- diff --git a/ros2_controllers/package.xml b/ros2_controllers/package.xml index 35cbdbf9bd..49c87b152d 100644 --- a/ros2_controllers/package.xml +++ b/ros2_controllers/package.xml @@ -1,7 +1,7 @@ ros2_controllers - 3.16.0 + 3.17.0 Metapackage for ROS2 controllers related packages Bence Magyar Jordan Palacios diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index 07b540f28a..acca28227f 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.17.0 (2023-10-31) +------------------- * [TestNodes] Optimize output about setup of JTC publisher (`#792 `_) * Contributors: Dr. Denis diff --git a/ros2_controllers_test_nodes/package.xml b/ros2_controllers_test_nodes/package.xml index 398a279ae7..ef8c7b572d 100644 --- a/ros2_controllers_test_nodes/package.xml +++ b/ros2_controllers_test_nodes/package.xml @@ -2,7 +2,7 @@ ros2_controllers_test_nodes - 3.16.0 + 3.17.0 Demo nodes for showing and testing functionalities of the ros2_control framework. Denis Štogl diff --git a/ros2_controllers_test_nodes/setup.py b/ros2_controllers_test_nodes/setup.py index 9b4e3a8b6b..102c39b607 100644 --- a/ros2_controllers_test_nodes/setup.py +++ b/ros2_controllers_test_nodes/setup.py @@ -20,7 +20,7 @@ setup( name=package_name, - version="3.16.0", + version="3.17.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index 6c7f06200c..e723d39c6f 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.17.0 (2023-10-31) +------------------- 3.16.0 (2023-09-20) ------------------- diff --git a/rqt_joint_trajectory_controller/package.xml b/rqt_joint_trajectory_controller/package.xml index 96b34a5609..08f885aef3 100644 --- a/rqt_joint_trajectory_controller/package.xml +++ b/rqt_joint_trajectory_controller/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> rqt_joint_trajectory_controller - 3.16.0 + 3.17.0 Graphical frontend for interacting with joint_trajectory_controller instances. Bence Magyar diff --git a/rqt_joint_trajectory_controller/setup.py b/rqt_joint_trajectory_controller/setup.py index cf09679e00..c0f4a96c2a 100644 --- a/rqt_joint_trajectory_controller/setup.py +++ b/rqt_joint_trajectory_controller/setup.py @@ -7,7 +7,7 @@ setup( name=package_name, - version="3.16.0", + version="3.17.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/steering_controllers_library/CHANGELOG.rst b/steering_controllers_library/CHANGELOG.rst index e3b9d163af..8082dc9070 100644 --- a/steering_controllers_library/CHANGELOG.rst +++ b/steering_controllers_library/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package steering_controllers_library ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.17.0 (2023-10-31) +------------------- * Steering controllers library: fix open loop mode (`#793 `_) * set last*velocity variables for open loop odometry * Make function arguments const diff --git a/steering_controllers_library/package.xml b/steering_controllers_library/package.xml index c7c654846a..0194cfd041 100644 --- a/steering_controllers_library/package.xml +++ b/steering_controllers_library/package.xml @@ -2,7 +2,7 @@ steering_controllers_library - 3.16.0 + 3.17.0 Package for steering robot configurations including odometry and interfaces. Apache License 2.0 Bence Magyar diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index 5cad2f94f7..bda1c89d32 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.17.0 (2023-10-31) +------------------- 3.16.0 (2023-09-20) ------------------- diff --git a/tricycle_controller/package.xml b/tricycle_controller/package.xml index ec4d5e064d..9a6cf3ef2d 100644 --- a/tricycle_controller/package.xml +++ b/tricycle_controller/package.xml @@ -2,7 +2,7 @@ tricycle_controller - 3.16.0 + 3.17.0 Controller for a tricycle drive mobile base Bence Magyar Tony Najjar diff --git a/tricycle_steering_controller/CHANGELOG.rst b/tricycle_steering_controller/CHANGELOG.rst index a4645ebfb5..a7e6854ea8 100644 --- a/tricycle_steering_controller/CHANGELOG.rst +++ b/tricycle_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package tricycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.17.0 (2023-10-31) +------------------- * Improve docs (`#785 `_) * Contributors: Christoph Fröhlich diff --git a/tricycle_steering_controller/package.xml b/tricycle_steering_controller/package.xml index 64ebddd5e2..e39971982c 100644 --- a/tricycle_steering_controller/package.xml +++ b/tricycle_steering_controller/package.xml @@ -2,7 +2,7 @@ tricycle_steering_controller - 3.16.0 + 3.17.0 Steering controller with tricycle kinematics. Rear fixed wheels are powering the vehicle and front wheel is steering. Apache License 2.0 Bence Magyar diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index 0b8c320035..358ee9f499 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.17.0 (2023-10-31) +------------------- 3.16.0 (2023-09-20) ------------------- diff --git a/velocity_controllers/package.xml b/velocity_controllers/package.xml index e47e170226..f336606b26 100644 --- a/velocity_controllers/package.xml +++ b/velocity_controllers/package.xml @@ -1,7 +1,7 @@ velocity_controllers - 3.16.0 + 3.17.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios From c6ecab7e14f6f2935a642f742f03142e1d18c9b2 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Wed, 1 Nov 2023 21:38:16 +0000 Subject: [PATCH 132/238] Use pre-commit fork of clang-format instead of local (#813) --- .pre-commit-config.yaml | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5a7ac74d9b..32d194d73d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -58,21 +58,10 @@ repos: args: ["--ignore=E501"] # CPP hooks - - repo: local + - repo: https://github.com/pre-commit/mirrors-clang-format + rev: v14.0.6 hooks: - id: clang-format - name: clang-format - description: Format files with ClangFormat. - entry: clang-format-14 - language: system - files: \.(c|cc|cxx|cpp|frag|glsl|h|hpp|hxx|ih|ispc|ipp|java|js|m|proto|vert)$ - args: ['-fallback-style=none', '-i'] - # The same options as in ament_cppcheck are used, but its not working... - #- repo: https://github.com/pocc/pre-commit-hooks - #rev: v1.1.1 - #hooks: - #- id: cppcheck - #args: ['--error-exitcode=1', '-f', '--inline-suppr', '-q', '-rp', '--suppress=internalAstError', '--suppress=unknownMacro', '--verbose'] - repo: local hooks: From f81a82c9d73f9fc06aeec3b031a1c63dc144ebdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Fri, 3 Nov 2023 21:18:31 +0100 Subject: [PATCH 133/238] [CI] Codecov (#807) --- .github/workflows/ci-coverage-build.yml | 2 -- README.md | 3 +++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-coverage-build.yml b/.github/workflows/ci-coverage-build.yml index d33ee89cc9..694f3dd8a1 100644 --- a/.github/workflows/ci-coverage-build.yml +++ b/.github/workflows/ci-coverage-build.yml @@ -1,8 +1,6 @@ name: Coverage Build on: workflow_dispatch: - branches: - - master push: branches: - master diff --git a/README.md b/README.md index 8c8539a02b..49d6b28ea0 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ # ros2_controllers +[![Licence](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) +[![codecov](https://codecov.io/gh/ros-controls/ros2_controllers/graph/badge.svg?token=KSdY0tsHm6)](https://codecov.io/gh/ros-controls/ros2_controllers) + Commonly used and generalized controllers for ros2-control framework that are ready to use with many robots, MoveIt2 and Navigation2. ## Build status From 2c6d7a6b83e905786490a328967a87460f2c52b1 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Mon, 6 Nov 2023 18:29:10 +0000 Subject: [PATCH 134/238] Add iron branch (#814) --- .github/mergify.yml | 10 +++++++ ...ibility.yml => iron-abi-compatibility.yml} | 8 ++--- ...ld-main.yml => iron-binary-build-main.yml} | 18 +++++++----- ...ting.yml => iron-binary-build-testing.yml} | 18 +++++++----- ...y-build.yml => iron-rhel-binary-build.yml} | 17 ++++------- ...in.yml => iron-semi-binary-build-main.yml} | 18 +++++++----- ...yml => iron-semi-binary-build-testing.yml} | 18 +++++++----- ...source-build.yml => iron-source-build.yml} | 12 ++++---- .github/workflows/prerelease-check.yml | 2 ++ ros2_controllers.iron.repos | 29 +++++++++++++++++++ 10 files changed, 101 insertions(+), 49 deletions(-) rename .github/workflows/{humble-abi-compatibility.yml => iron-abi-compatibility.yml} (78%) rename .github/workflows/{humble-binary-build-main.yml => iron-binary-build-main.yml} (61%) rename .github/workflows/{humble-binary-build-testing.yml => iron-binary-build-testing.yml} (61%) rename .github/workflows/{humble-rhel-binary-build.yml => iron-rhel-binary-build.yml} (65%) rename .github/workflows/{humble-semi-binary-build-main.yml => iron-semi-binary-build-main.yml} (59%) rename .github/workflows/{humble-semi-binary-build-testing.yml => iron-semi-binary-build-testing.yml} (59%) rename .github/workflows/{humble-source-build.yml => iron-source-build.yml} (66%) create mode 100644 ros2_controllers.iron.repos diff --git a/.github/mergify.yml b/.github/mergify.yml index 49d2acedfa..3aaaab2001 100644 --- a/.github/mergify.yml +++ b/.github/mergify.yml @@ -8,6 +8,16 @@ pull_request_rules: branches: - humble + + - name: Backport to iron at reviewers discretion + conditions: + - base=master + - "label=backport-iron" + actions: + backport: + branches: + - iron + - name: Ask to resolve conflict conditions: - conflict diff --git a/.github/workflows/humble-abi-compatibility.yml b/.github/workflows/iron-abi-compatibility.yml similarity index 78% rename from .github/workflows/humble-abi-compatibility.yml rename to .github/workflows/iron-abi-compatibility.yml index 708ea5c1f4..20d93f5af1 100644 --- a/.github/workflows/humble-abi-compatibility.yml +++ b/.github/workflows/iron-abi-compatibility.yml @@ -1,11 +1,11 @@ -name: Humble - ABI Compatibility Check +name: Iron - ABI Compatibility Check on: workflow_dispatch: branches: - - humble + - iron pull_request: branches: - - humble + - iron jobs: abi_check: @@ -14,7 +14,7 @@ jobs: - uses: actions/checkout@v4 - uses: ros-industrial/industrial_ci@master env: - ROS_DISTRO: humble + ROS_DISTRO: iron ROS_REPO: main ABICHECK_URL: github:${{ github.repository }}#${{ github.base_ref }} NOT_TEST_BUILD: true diff --git a/.github/workflows/humble-binary-build-main.yml b/.github/workflows/iron-binary-build-main.yml similarity index 61% rename from .github/workflows/humble-binary-build-main.yml rename to .github/workflows/iron-binary-build-main.yml index 64d78f281a..ef35397855 100644 --- a/.github/workflows/humble-binary-build-main.yml +++ b/.github/workflows/iron-binary-build-main.yml @@ -1,17 +1,21 @@ -name: Humble Binary Build - main +name: Iron Binary Build - main # author: Denis Štogl # description: 'Build & test all dependencies from released (binary) packages.' on: workflow_dispatch: branches: - - humble + - iron + - '*feature*' + - '*feature/**' pull_request: branches: - - humble + - iron + - '*feature*' + - '*feature/**' push: branches: - - humble + - iron schedule: # Run every morning to detect flakiness and broken dependencies - cron: '03 1 * * *' @@ -20,7 +24,7 @@ jobs: binary: uses: ./.github/workflows/reusable-industrial-ci-with-cache.yml with: - ros_distro: humble + ros_distro: iron ros_repo: main - upstream_workspace: ros2_controllers-not-released.humble.repos - ref_for_scheduled_build: humble + upstream_workspace: ros2_controllers-not-released.iron.repos + ref_for_scheduled_build: iron diff --git a/.github/workflows/humble-binary-build-testing.yml b/.github/workflows/iron-binary-build-testing.yml similarity index 61% rename from .github/workflows/humble-binary-build-testing.yml rename to .github/workflows/iron-binary-build-testing.yml index 524cacd685..25a693dc23 100644 --- a/.github/workflows/humble-binary-build-testing.yml +++ b/.github/workflows/iron-binary-build-testing.yml @@ -1,17 +1,21 @@ -name: Humble Binary Build - testing +name: Iron Binary Build - testing # author: Denis Štogl # description: 'Build & test all dependencies from released (binary) packages.' on: workflow_dispatch: branches: - - humble + - iron + - '*feature*' + - '*feature/**' pull_request: branches: - - humble + - iron + - '*feature*' + - '*feature/**' push: branches: - - humble + - iron schedule: # Run every morning to detect flakiness and broken dependencies - cron: '03 1 * * *' @@ -20,7 +24,7 @@ jobs: binary: uses: ./.github/workflows/reusable-industrial-ci-with-cache.yml with: - ros_distro: humble + ros_distro: iron ros_repo: testing - upstream_workspace: ros2_controllers-not-released.humble.repos - ref_for_scheduled_build: humble + upstream_workspace: ros2_controllers-not-released.iron.repos + ref_for_scheduled_build: iron diff --git a/.github/workflows/humble-rhel-binary-build.yml b/.github/workflows/iron-rhel-binary-build.yml similarity index 65% rename from .github/workflows/humble-rhel-binary-build.yml rename to .github/workflows/iron-rhel-binary-build.yml index 9da6059892..5664d61768 100644 --- a/.github/workflows/humble-rhel-binary-build.yml +++ b/.github/workflows/iron-rhel-binary-build.yml @@ -1,26 +1,21 @@ -name: Humble RHEL Binary Build +name: Iron RHEL Binary Build on: workflow_dispatch: - branches: - - humble - pull_request: - branches: - - humble push: branches: - - humble + - iron schedule: # Run every day to detect flakiness and broken dependencies - cron: '03 1 * * *' jobs: - humble_rhel_binary: - name: Humble RHEL binary build + iron_rhel_binary: + name: Iron RHEL binary build runs-on: ubuntu-latest env: - ROS_DISTRO: humble - container: ghcr.io/ros-controls/ros:humble-rhel + ROS_DISTRO: iron + container: ghcr.io/ros-controls/ros:iron-rhel steps: - uses: actions/checkout@v4 with: diff --git a/.github/workflows/humble-semi-binary-build-main.yml b/.github/workflows/iron-semi-binary-build-main.yml similarity index 59% rename from .github/workflows/humble-semi-binary-build-main.yml rename to .github/workflows/iron-semi-binary-build-main.yml index 863df79a22..2224a59f0e 100644 --- a/.github/workflows/humble-semi-binary-build-main.yml +++ b/.github/workflows/iron-semi-binary-build-main.yml @@ -1,16 +1,20 @@ -name: Humble Semi-Binary Build - main +name: Iron Semi-Binary Build - main # description: 'Build & test that compiles the main dependencies from source.' on: workflow_dispatch: branches: - - humble + - iron + - '*feature*' + - '*feature/**' pull_request: branches: - - humble + - iron + - '*feature*' + - '*feature/**' push: branches: - - humble + - iron schedule: # Run every morning to detect flakiness and broken dependencies - cron: '33 1 * * *' @@ -19,7 +23,7 @@ jobs: semi_binary: uses: ./.github/workflows/reusable-industrial-ci-with-cache.yml with: - ros_distro: humble + ros_distro: iron ros_repo: main - upstream_workspace: ros2_controllers.humble.repos - ref_for_scheduled_build: humble + upstream_workspace: ros2_controllers.iron.repos + ref_for_scheduled_build: iron diff --git a/.github/workflows/humble-semi-binary-build-testing.yml b/.github/workflows/iron-semi-binary-build-testing.yml similarity index 59% rename from .github/workflows/humble-semi-binary-build-testing.yml rename to .github/workflows/iron-semi-binary-build-testing.yml index 6286636e1f..c5ff430c89 100644 --- a/.github/workflows/humble-semi-binary-build-testing.yml +++ b/.github/workflows/iron-semi-binary-build-testing.yml @@ -1,16 +1,20 @@ -name: Humble Semi-Binary Build - testing +name: Iron Semi-Binary Build - testing # description: 'Build & test that compiles the main dependencies from source.' on: workflow_dispatch: branches: - - humble + - iron + - '*feature*' + - '*feature/**' pull_request: branches: - - humble + - iron + - '*feature*' + - '*feature/**' push: branches: - - humble + - iron schedule: # Run every morning to detect flakiness and broken dependencies - cron: '33 1 * * *' @@ -19,7 +23,7 @@ jobs: semi_binary: uses: ./.github/workflows/reusable-industrial-ci-with-cache.yml with: - ros_distro: humble + ros_distro: iron ros_repo: testing - upstream_workspace: ros2_controllers.humble.repos - ref_for_scheduled_build: humble + upstream_workspace: ros2_controllers.iron.repos + ref_for_scheduled_build: iron diff --git a/.github/workflows/humble-source-build.yml b/.github/workflows/iron-source-build.yml similarity index 66% rename from .github/workflows/humble-source-build.yml rename to .github/workflows/iron-source-build.yml index ff0fd62e05..1e9d865c49 100644 --- a/.github/workflows/humble-source-build.yml +++ b/.github/workflows/iron-source-build.yml @@ -1,11 +1,11 @@ -name: Humble Source Build +name: Iron Source Build on: workflow_dispatch: branches: - - humble + - iron push: branches: - - humble + - iron schedule: # Run every day to detect flakiness and broken dependencies - cron: '03 3 * * *' @@ -14,6 +14,6 @@ jobs: source: uses: ./.github/workflows/reusable-ros-tooling-source-build.yml with: - ros_distro: humble - ref: humble - ros2_repo_branch: humble + ros_distro: iron + ref: iron + ros2_repo_branch: iron diff --git a/.github/workflows/prerelease-check.yml b/.github/workflows/prerelease-check.yml index 856d877d85..182df6e22b 100644 --- a/.github/workflows/prerelease-check.yml +++ b/.github/workflows/prerelease-check.yml @@ -10,6 +10,7 @@ on: type: choice options: - humble + - iron - rolling branch: description: 'Chose branch for distro' @@ -18,6 +19,7 @@ on: type: choice options: - humble + - iron - master jobs: diff --git a/ros2_controllers.iron.repos b/ros2_controllers.iron.repos new file mode 100644 index 0000000000..4e2c7abbbd --- /dev/null +++ b/ros2_controllers.iron.repos @@ -0,0 +1,29 @@ +repositories: + ros2_control: + type: git + url: https://github.com/ros-controls/ros2_control.git + version: iron + realtime_tools: + type: git + url: https://github.com/ros-controls/realtime_tools.git + version: master + control_msgs: + type: git + url: https://github.com/ros-controls/control_msgs.git + version: master + control_toolbox: + type: git + url: https://github.com/ros-controls/control_toolbox.git + version: ros2-master + kinematics_interface: + type: git + url: https://github.com/ros-controls/kinematics_interface.git + version: master + angles: + type: git + url: https://github.com/ros/angles.git + version: ros2 + generate_parameter_library: + type: git + url: https://github.com/picknikrobotics/generate_parameter_library.git + version: main From 5f78fe40bd2573ce3d3da6c22c6b4e69897a7a4d Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Tue, 7 Nov 2023 12:01:02 +0000 Subject: [PATCH 135/238] Adjust tests after passing URDF to controllers (#817) --- .../test_ackermann_steering_controller.hpp | 2 +- .../test/test_admittance_controller.hpp | 2 +- .../test/test_bicycle_steering_controller.hpp | 2 +- .../test/test_diff_drive_controller.cpp | 36 ++++++++++--------- .../test_joint_group_effort_controller.cpp | 2 +- .../test_force_torque_sensor_broadcaster.cpp | 2 +- .../test/test_forward_command_controller.cpp | 2 +- ...i_interface_forward_command_controller.cpp | 2 +- .../test/test_gripper_controllers.cpp | 2 +- .../test/test_imu_sensor_broadcaster.cpp | 3 +- .../test/test_joint_state_broadcaster.cpp | 2 +- .../test/test_trajectory_controller_utils.hpp | 2 +- .../test_joint_group_position_controller.cpp | 2 +- .../test/test_range_sensor_broadcaster.cpp | 2 +- .../test_steering_controllers_library.hpp | 2 +- .../test/test_tricycle_controller.cpp | 16 +++++---- .../test_tricycle_steering_controller.hpp | 2 +- .../test_joint_group_velocity_controller.cpp | 2 +- 18 files changed, 44 insertions(+), 41 deletions(-) diff --git a/ackermann_steering_controller/test/test_ackermann_steering_controller.hpp b/ackermann_steering_controller/test/test_ackermann_steering_controller.hpp index 80258258c2..8af2f6bc94 100644 --- a/ackermann_steering_controller/test/test_ackermann_steering_controller.hpp +++ b/ackermann_steering_controller/test/test_ackermann_steering_controller.hpp @@ -147,7 +147,7 @@ class AckermannSteeringControllerFixture : public ::testing::Test protected: void SetUpController(const std::string controller_name = "test_ackermann_steering_controller") { - ASSERT_EQ(controller_->init(controller_name), controller_interface::return_type::OK); + ASSERT_EQ(controller_->init(controller_name, ""), controller_interface::return_type::OK); if (position_feedback_ == true) { diff --git a/admittance_controller/test/test_admittance_controller.hpp b/admittance_controller/test/test_admittance_controller.hpp index 8888cd700a..db708db6c5 100644 --- a/admittance_controller/test/test_admittance_controller.hpp +++ b/admittance_controller/test/test_admittance_controller.hpp @@ -185,7 +185,7 @@ class AdmittanceControllerTest : public ::testing::Test controller_interface::return_type SetUpControllerCommon( const std::string & controller_name, const rclcpp::NodeOptions & options) { - auto result = controller_->init(controller_name, "", options); + auto result = controller_->init(controller_name, "", "", options); controller_->export_reference_interfaces(); assign_interfaces(); diff --git a/bicycle_steering_controller/test/test_bicycle_steering_controller.hpp b/bicycle_steering_controller/test/test_bicycle_steering_controller.hpp index 065f9e1a0d..34d6883a83 100644 --- a/bicycle_steering_controller/test/test_bicycle_steering_controller.hpp +++ b/bicycle_steering_controller/test/test_bicycle_steering_controller.hpp @@ -144,7 +144,7 @@ class BicycleSteeringControllerFixture : public ::testing::Test protected: void SetUpController(const std::string controller_name = "test_bicycle_steering_controller") { - ASSERT_EQ(controller_->init(controller_name), controller_interface::return_type::OK); + ASSERT_EQ(controller_->init(controller_name, ""), controller_interface::return_type::OK); if (position_feedback_ == true) { diff --git a/diff_drive_controller/test/test_diff_drive_controller.cpp b/diff_drive_controller/test/test_diff_drive_controller.cpp index edaaa84e4b..505aa44d2b 100644 --- a/diff_drive_controller/test/test_diff_drive_controller.cpp +++ b/diff_drive_controller/test/test_diff_drive_controller.cpp @@ -189,11 +189,13 @@ class TestDiffDriveController : public ::testing::Test rclcpp::Node::SharedPtr pub_node; rclcpp::Publisher::SharedPtr velocity_publisher; + + const std::string urdf_ = ""; }; TEST_F(TestDiffDriveController, configure_fails_without_parameters) { - const auto ret = controller_->init(controller_name); + const auto ret = controller_->init(controller_name, urdf_); ASSERT_EQ(ret, controller_interface::return_type::OK); ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), CallbackReturn::ERROR); @@ -201,7 +203,7 @@ TEST_F(TestDiffDriveController, configure_fails_without_parameters) TEST_F(TestDiffDriveController, configure_fails_with_only_left_or_only_right_side_defined) { - const auto ret = controller_->init(controller_name); + const auto ret = controller_->init(controller_name, urdf_); ASSERT_EQ(ret, controller_interface::return_type::OK); controller_->get_node()->set_parameter( @@ -221,7 +223,7 @@ TEST_F(TestDiffDriveController, configure_fails_with_only_left_or_only_right_sid TEST_F(TestDiffDriveController, configure_fails_with_mismatching_wheel_side_size) { - const auto ret = controller_->init(controller_name); + const auto ret = controller_->init(controller_name, urdf_); ASSERT_EQ(ret, controller_interface::return_type::OK); controller_->get_node()->set_parameter( @@ -237,7 +239,7 @@ TEST_F(TestDiffDriveController, configure_fails_with_mismatching_wheel_side_size TEST_F(TestDiffDriveController, configure_succeeds_when_wheels_are_specified) { - const auto ret = controller_->init(controller_name); + const auto ret = controller_->init(controller_name, urdf_); ASSERT_EQ(ret, controller_interface::return_type::OK); controller_->get_node()->set_parameter( @@ -257,7 +259,7 @@ TEST_F(TestDiffDriveController, configure_succeeds_when_wheels_are_specified) TEST_F(TestDiffDriveController, configure_succeeds_tf_test_prefix_false_no_namespace) { - const auto ret = controller_->init(controller_name); + const auto ret = controller_->init(controller_name, urdf_); ASSERT_EQ(ret, controller_interface::return_type::OK); std::string odom_id = "odom"; @@ -290,7 +292,7 @@ TEST_F(TestDiffDriveController, configure_succeeds_tf_test_prefix_false_no_names TEST_F(TestDiffDriveController, configure_succeeds_tf_test_prefix_true_no_namespace) { - const auto ret = controller_->init(controller_name); + const auto ret = controller_->init(controller_name, urdf_); ASSERT_EQ(ret, controller_interface::return_type::OK); std::string odom_id = "odom"; @@ -325,7 +327,7 @@ TEST_F(TestDiffDriveController, configure_succeeds_tf_test_prefix_true_no_namesp TEST_F(TestDiffDriveController, configure_succeeds_tf_blank_prefix_true_no_namespace) { - const auto ret = controller_->init(controller_name); + const auto ret = controller_->init(controller_name, urdf_); ASSERT_EQ(ret, controller_interface::return_type::OK); std::string odom_id = "odom"; @@ -361,7 +363,7 @@ TEST_F(TestDiffDriveController, configure_succeeds_tf_test_prefix_false_set_name { std::string test_namespace = "/test_namespace"; - const auto ret = controller_->init(controller_name, test_namespace); + const auto ret = controller_->init(controller_name, urdf_, test_namespace); ASSERT_EQ(ret, controller_interface::return_type::OK); std::string odom_id = "odom"; @@ -396,7 +398,7 @@ TEST_F(TestDiffDriveController, configure_succeeds_tf_test_prefix_true_set_names { std::string test_namespace = "/test_namespace"; - const auto ret = controller_->init(controller_name, test_namespace); + const auto ret = controller_->init(controller_name, urdf_, test_namespace); ASSERT_EQ(ret, controller_interface::return_type::OK); std::string odom_id = "odom"; @@ -433,7 +435,7 @@ TEST_F(TestDiffDriveController, configure_succeeds_tf_blank_prefix_true_set_name { std::string test_namespace = "/test_namespace"; - const auto ret = controller_->init(controller_name, test_namespace); + const auto ret = controller_->init(controller_name, urdf_, test_namespace); ASSERT_EQ(ret, controller_interface::return_type::OK); std::string odom_id = "odom"; @@ -467,7 +469,7 @@ TEST_F(TestDiffDriveController, configure_succeeds_tf_blank_prefix_true_set_name TEST_F(TestDiffDriveController, activate_fails_without_resources_assigned) { - const auto ret = controller_->init(controller_name); + const auto ret = controller_->init(controller_name, urdf_); ASSERT_EQ(ret, controller_interface::return_type::OK); controller_->get_node()->set_parameter( @@ -481,7 +483,7 @@ TEST_F(TestDiffDriveController, activate_fails_without_resources_assigned) TEST_F(TestDiffDriveController, activate_succeeds_with_pos_resources_assigned) { - const auto ret = controller_->init(controller_name); + const auto ret = controller_->init(controller_name, urdf_); ASSERT_EQ(ret, controller_interface::return_type::OK); // We implicitly test that by default position feedback is required @@ -497,7 +499,7 @@ TEST_F(TestDiffDriveController, activate_succeeds_with_pos_resources_assigned) TEST_F(TestDiffDriveController, activate_succeeds_with_vel_resources_assigned) { - const auto ret = controller_->init(controller_name); + const auto ret = controller_->init(controller_name, urdf_); ASSERT_EQ(ret, controller_interface::return_type::OK); controller_->get_node()->set_parameter( @@ -514,7 +516,7 @@ TEST_F(TestDiffDriveController, activate_succeeds_with_vel_resources_assigned) TEST_F(TestDiffDriveController, activate_fails_with_wrong_resources_assigned_1) { - const auto ret = controller_->init(controller_name); + const auto ret = controller_->init(controller_name, urdf_); ASSERT_EQ(ret, controller_interface::return_type::OK); controller_->get_node()->set_parameter( @@ -531,7 +533,7 @@ TEST_F(TestDiffDriveController, activate_fails_with_wrong_resources_assigned_1) TEST_F(TestDiffDriveController, activate_fails_with_wrong_resources_assigned_2) { - const auto ret = controller_->init(controller_name); + const auto ret = controller_->init(controller_name, urdf_); ASSERT_EQ(ret, controller_interface::return_type::OK); controller_->get_node()->set_parameter( @@ -548,7 +550,7 @@ TEST_F(TestDiffDriveController, activate_fails_with_wrong_resources_assigned_2) TEST_F(TestDiffDriveController, cleanup) { - const auto ret = controller_->init(controller_name); + const auto ret = controller_->init(controller_name, urdf_); ASSERT_EQ(ret, controller_interface::return_type::OK); controller_->get_node()->set_parameter( @@ -597,7 +599,7 @@ TEST_F(TestDiffDriveController, cleanup) TEST_F(TestDiffDriveController, correct_initialization_using_parameters) { - const auto ret = controller_->init(controller_name); + const auto ret = controller_->init(controller_name, urdf_); ASSERT_EQ(ret, controller_interface::return_type::OK); controller_->get_node()->set_parameter( diff --git a/effort_controllers/test/test_joint_group_effort_controller.cpp b/effort_controllers/test/test_joint_group_effort_controller.cpp index 256a4ce465..23555c578f 100644 --- a/effort_controllers/test/test_joint_group_effort_controller.cpp +++ b/effort_controllers/test/test_joint_group_effort_controller.cpp @@ -54,7 +54,7 @@ void JointGroupEffortControllerTest::TearDown() { controller_.reset(nullptr); } void JointGroupEffortControllerTest::SetUpController() { - const auto result = controller_->init("test_joint_group_effort_controller"); + const auto result = controller_->init("test_joint_group_effort_controller", ""); ASSERT_EQ(result, controller_interface::return_type::OK); std::vector command_ifs; diff --git a/force_torque_sensor_broadcaster/test/test_force_torque_sensor_broadcaster.cpp b/force_torque_sensor_broadcaster/test/test_force_torque_sensor_broadcaster.cpp index 57650c9302..82f677410e 100644 --- a/force_torque_sensor_broadcaster/test/test_force_torque_sensor_broadcaster.cpp +++ b/force_torque_sensor_broadcaster/test/test_force_torque_sensor_broadcaster.cpp @@ -53,7 +53,7 @@ void ForceTorqueSensorBroadcasterTest::TearDown() { fts_broadcaster_.reset(nullp void ForceTorqueSensorBroadcasterTest::SetUpFTSBroadcaster() { - const auto result = fts_broadcaster_->init("test_force_torque_sensor_broadcaster"); + const auto result = fts_broadcaster_->init("test_force_torque_sensor_broadcaster", ""); ASSERT_EQ(result, controller_interface::return_type::OK); std::vector state_ifs; diff --git a/forward_command_controller/test/test_forward_command_controller.cpp b/forward_command_controller/test/test_forward_command_controller.cpp index b39294f36c..2ab507ef29 100644 --- a/forward_command_controller/test/test_forward_command_controller.cpp +++ b/forward_command_controller/test/test_forward_command_controller.cpp @@ -60,7 +60,7 @@ void ForwardCommandControllerTest::TearDown() { controller_.reset(nullptr); } void ForwardCommandControllerTest::SetUpController() { - const auto result = controller_->init("forward_command_controller"); + const auto result = controller_->init("forward_command_controller", ""); ASSERT_EQ(result, controller_interface::return_type::OK); std::vector command_ifs; diff --git a/forward_command_controller/test/test_multi_interface_forward_command_controller.cpp b/forward_command_controller/test/test_multi_interface_forward_command_controller.cpp index c629b36ba8..00ca4ae2d1 100644 --- a/forward_command_controller/test/test_multi_interface_forward_command_controller.cpp +++ b/forward_command_controller/test/test_multi_interface_forward_command_controller.cpp @@ -62,7 +62,7 @@ void MultiInterfaceForwardCommandControllerTest::TearDown() { controller_.reset( void MultiInterfaceForwardCommandControllerTest::SetUpController(bool set_params_and_activate) { - const auto result = controller_->init("multi_interface_forward_command_controller"); + const auto result = controller_->init("multi_interface_forward_command_controller", ""); ASSERT_EQ(result, controller_interface::return_type::OK); std::vector command_ifs; diff --git a/gripper_controllers/test/test_gripper_controllers.cpp b/gripper_controllers/test/test_gripper_controllers.cpp index 506f968b99..572e755743 100644 --- a/gripper_controllers/test/test_gripper_controllers.cpp +++ b/gripper_controllers/test/test_gripper_controllers.cpp @@ -60,7 +60,7 @@ void GripperControllerTest::TearDown() template void GripperControllerTest::SetUpController() { - const auto result = controller_->init("gripper_controller"); + const auto result = controller_->init("gripper_controller", ""); ASSERT_EQ(result, controller_interface::return_type::OK); std::vector command_ifs; diff --git a/imu_sensor_broadcaster/test/test_imu_sensor_broadcaster.cpp b/imu_sensor_broadcaster/test/test_imu_sensor_broadcaster.cpp index 8358088b1d..0b782efc5f 100644 --- a/imu_sensor_broadcaster/test/test_imu_sensor_broadcaster.cpp +++ b/imu_sensor_broadcaster/test/test_imu_sensor_broadcaster.cpp @@ -37,7 +37,6 @@ namespace { constexpr auto NODE_SUCCESS = controller_interface::CallbackReturn::SUCCESS; constexpr auto NODE_ERROR = controller_interface::CallbackReturn::ERROR; - } // namespace void IMUSensorBroadcasterTest::SetUpTestCase() {} @@ -54,7 +53,7 @@ void IMUSensorBroadcasterTest::TearDown() { imu_broadcaster_.reset(nullptr); } void IMUSensorBroadcasterTest::SetUpIMUBroadcaster() { - const auto result = imu_broadcaster_->init("test_imu_sensor_broadcaster"); + const auto result = imu_broadcaster_->init("test_imu_sensor_broadcaster", ""); ASSERT_EQ(result, controller_interface::return_type::OK); std::vector state_ifs; diff --git a/joint_state_broadcaster/test/test_joint_state_broadcaster.cpp b/joint_state_broadcaster/test/test_joint_state_broadcaster.cpp index 7f95e232e2..a6c0708fd9 100644 --- a/joint_state_broadcaster/test/test_joint_state_broadcaster.cpp +++ b/joint_state_broadcaster/test/test_joint_state_broadcaster.cpp @@ -69,7 +69,7 @@ void JointStateBroadcasterTest::SetUpStateBroadcaster( void JointStateBroadcasterTest::init_broadcaster_and_set_parameters( const std::vector & joint_names, const std::vector & interfaces) { - const auto result = state_broadcaster_->init("joint_state_broadcaster"); + const auto result = state_broadcaster_->init("joint_state_broadcaster", ""); ASSERT_EQ(result, controller_interface::return_type::OK); state_broadcaster_->get_node()->set_parameter({"joints", joint_names}); diff --git a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp index cea61c92bf..7c65fec29c 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp +++ b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp @@ -189,7 +189,7 @@ class TrajectoryControllerTest : public ::testing::Test parameter_overrides.insert(parameter_overrides.end(), parameters.begin(), parameters.end()); node_options.parameter_overrides(parameter_overrides); - auto ret = traj_controller_->init(controller_name_, "", node_options); + auto ret = traj_controller_->init(controller_name_, "", "", node_options); if (ret != controller_interface::return_type::OK) { FAIL(); diff --git a/position_controllers/test/test_joint_group_position_controller.cpp b/position_controllers/test/test_joint_group_position_controller.cpp index a712cc81c2..07f42e4eba 100644 --- a/position_controllers/test/test_joint_group_position_controller.cpp +++ b/position_controllers/test/test_joint_group_position_controller.cpp @@ -54,7 +54,7 @@ void JointGroupPositionControllerTest::TearDown() { controller_.reset(nullptr); void JointGroupPositionControllerTest::SetUpController() { - const auto result = controller_->init("test_joint_group_position_controller"); + const auto result = controller_->init("test_joint_group_position_controller", ""); ASSERT_EQ(result, controller_interface::return_type::OK); std::vector command_ifs; diff --git a/range_sensor_broadcaster/test/test_range_sensor_broadcaster.cpp b/range_sensor_broadcaster/test/test_range_sensor_broadcaster.cpp index 855f7e037b..ab937146cb 100644 --- a/range_sensor_broadcaster/test/test_range_sensor_broadcaster.cpp +++ b/range_sensor_broadcaster/test/test_range_sensor_broadcaster.cpp @@ -34,7 +34,7 @@ controller_interface::return_type RangeSensorBroadcasterTest::init_broadcaster( std::string broadcaster_name) { controller_interface::return_type result = controller_interface::return_type::ERROR; - result = range_broadcaster_->init(broadcaster_name); + result = range_broadcaster_->init(broadcaster_name, ""); if (controller_interface::return_type::OK == result) { diff --git a/steering_controllers_library/test/test_steering_controllers_library.hpp b/steering_controllers_library/test/test_steering_controllers_library.hpp index c72c61257a..226d4f4291 100644 --- a/steering_controllers_library/test/test_steering_controllers_library.hpp +++ b/steering_controllers_library/test/test_steering_controllers_library.hpp @@ -168,7 +168,7 @@ class SteeringControllersLibraryFixture : public ::testing::Test protected: void SetUpController(const std::string controller_name = "test_steering_controllers_library") { - ASSERT_EQ(controller_->init(controller_name), controller_interface::return_type::OK); + ASSERT_EQ(controller_->init(controller_name, ""), controller_interface::return_type::OK); if (position_feedback_ == true) { diff --git a/tricycle_controller/test/test_tricycle_controller.cpp b/tricycle_controller/test/test_tricycle_controller.cpp index 1d6edf261a..054fff10ce 100644 --- a/tricycle_controller/test/test_tricycle_controller.cpp +++ b/tricycle_controller/test/test_tricycle_controller.cpp @@ -167,18 +167,20 @@ class TestTricycleController : public ::testing::Test rclcpp::Node::SharedPtr pub_node; rclcpp::Publisher::SharedPtr velocity_publisher; + + const std::string urdf_ = ""; }; TEST_F(TestTricycleController, configure_fails_without_parameters) { - const auto ret = controller_->init(controller_name); + const auto ret = controller_->init(controller_name, urdf_); ASSERT_EQ(ret, controller_interface::return_type::OK); ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), CallbackReturn::ERROR); } TEST_F(TestTricycleController, configure_fails_if_only_traction_or_steering_side_defined) { - const auto ret = controller_->init(controller_name); + const auto ret = controller_->init(controller_name, urdf_); ASSERT_EQ(ret, controller_interface::return_type::OK); controller_->get_node()->set_parameter( @@ -198,7 +200,7 @@ TEST_F(TestTricycleController, configure_fails_if_only_traction_or_steering_side TEST_F(TestTricycleController, configure_succeeds_when_joints_are_specified) { - const auto ret = controller_->init(controller_name); + const auto ret = controller_->init(controller_name, urdf_); ASSERT_EQ(ret, controller_interface::return_type::OK); controller_->get_node()->set_parameter( @@ -211,7 +213,7 @@ TEST_F(TestTricycleController, configure_succeeds_when_joints_are_specified) TEST_F(TestTricycleController, activate_fails_without_resources_assigned) { - const auto ret = controller_->init(controller_name); + const auto ret = controller_->init(controller_name, urdf_); ASSERT_EQ(ret, controller_interface::return_type::OK); controller_->get_node()->set_parameter( @@ -225,7 +227,7 @@ TEST_F(TestTricycleController, activate_fails_without_resources_assigned) TEST_F(TestTricycleController, activate_succeeds_with_resources_assigned) { - const auto ret = controller_->init(controller_name); + const auto ret = controller_->init(controller_name, urdf_); ASSERT_EQ(ret, controller_interface::return_type::OK); // We implicitly test that by default position feedback is required @@ -241,7 +243,7 @@ TEST_F(TestTricycleController, activate_succeeds_with_resources_assigned) TEST_F(TestTricycleController, cleanup) { - const auto ret = controller_->init(controller_name); + const auto ret = controller_->init(controller_name, urdf_); ASSERT_EQ(ret, controller_interface::return_type::OK); controller_->get_node()->set_parameter( @@ -290,7 +292,7 @@ TEST_F(TestTricycleController, cleanup) TEST_F(TestTricycleController, correct_initialization_using_parameters) { - const auto ret = controller_->init(controller_name); + const auto ret = controller_->init(controller_name, urdf_); ASSERT_EQ(ret, controller_interface::return_type::OK); controller_->get_node()->set_parameter( diff --git a/tricycle_steering_controller/test/test_tricycle_steering_controller.hpp b/tricycle_steering_controller/test/test_tricycle_steering_controller.hpp index 422f399ad4..e9d1023d98 100644 --- a/tricycle_steering_controller/test/test_tricycle_steering_controller.hpp +++ b/tricycle_steering_controller/test/test_tricycle_steering_controller.hpp @@ -146,7 +146,7 @@ class TricycleSteeringControllerFixture : public ::testing::Test protected: void SetUpController(const std::string controller_name = "test_tricycle_steering_controller") { - ASSERT_EQ(controller_->init(controller_name), controller_interface::return_type::OK); + ASSERT_EQ(controller_->init(controller_name, ""), controller_interface::return_type::OK); if (position_feedback_ == true) { diff --git a/velocity_controllers/test/test_joint_group_velocity_controller.cpp b/velocity_controllers/test/test_joint_group_velocity_controller.cpp index 43c1545461..185c630bc9 100644 --- a/velocity_controllers/test/test_joint_group_velocity_controller.cpp +++ b/velocity_controllers/test/test_joint_group_velocity_controller.cpp @@ -54,7 +54,7 @@ void JointGroupVelocityControllerTest::TearDown() { controller_.reset(nullptr); void JointGroupVelocityControllerTest::SetUpController() { - const auto result = controller_->init("test_joint_group_velocity_controller"); + const auto result = controller_->init("test_joint_group_velocity_controller", ""); ASSERT_EQ(result, controller_interface::return_type::OK); std::vector command_ifs; From 9d4ea6b7cf7476e21e690a5c05e8f7339c8819b1 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Tue, 7 Nov 2023 12:01:23 +0000 Subject: [PATCH 136/238] [diff_drive_controller] Remove non-stamped Twist option (#812) --- diff_drive_controller/doc/userdoc.rst | 3 - .../diff_drive_controller.hpp | 3 - .../src/diff_drive_controller.cpp | 64 ++++++------------- .../src/diff_drive_controller_parameter.yaml | 5 -- 4 files changed, 18 insertions(+), 57 deletions(-) diff --git a/diff_drive_controller/doc/userdoc.rst b/diff_drive_controller/doc/userdoc.rst index f8318bc4b8..d2dd284cf3 100644 --- a/diff_drive_controller/doc/userdoc.rst +++ b/diff_drive_controller/doc/userdoc.rst @@ -48,9 +48,6 @@ Subscribers ~/cmd_vel [geometry_msgs/msg/TwistStamped] Velocity command for the controller, if ``use_stamped_vel=true``. The controller extracts the x component of the linear velocity and the z component of the angular velocity. Velocities on other components are ignored. -~/cmd_vel_unstamped [geometry_msgs::msg::Twist] - Velocity command for the controller, if ``use_stamped_vel=false``. The controller extracts the x component of the linear velocity and the z component of the angular velocity. Velocities on other components are ignored. - Publishers ,,,,,,,,,,, diff --git a/diff_drive_controller/include/diff_drive_controller/diff_drive_controller.hpp b/diff_drive_controller/include/diff_drive_controller/diff_drive_controller.hpp index 5923a27d4d..554bedba59 100644 --- a/diff_drive_controller/include/diff_drive_controller/diff_drive_controller.hpp +++ b/diff_drive_controller/include/diff_drive_controller/diff_drive_controller.hpp @@ -127,8 +127,6 @@ class DiffDriveController : public controller_interface::ControllerInterface bool subscriber_is_active_ = false; rclcpp::Subscription::SharedPtr velocity_command_subscriber_ = nullptr; - rclcpp::Subscription::SharedPtr - velocity_command_unstamped_subscriber_ = nullptr; realtime_tools::RealtimeBox> received_velocity_msg_ptr_{nullptr}; @@ -151,7 +149,6 @@ class DiffDriveController : public controller_interface::ControllerInterface rclcpp::Time previous_publish_timestamp_{0, 0, RCL_CLOCK_UNINITIALIZED}; bool is_halted = false; - bool use_stamped_vel_ = true; bool reset(); void halt(); diff --git a/diff_drive_controller/src/diff_drive_controller.cpp b/diff_drive_controller/src/diff_drive_controller.cpp index 23097c0df2..ea08aef89b 100644 --- a/diff_drive_controller/src/diff_drive_controller.cpp +++ b/diff_drive_controller/src/diff_drive_controller.cpp @@ -31,7 +31,6 @@ namespace { constexpr auto DEFAULT_COMMAND_TOPIC = "~/cmd_vel"; -constexpr auto DEFAULT_COMMAND_UNSTAMPED_TOPIC = "~/cmd_vel_unstamped"; constexpr auto DEFAULT_COMMAND_OUT_TOPIC = "~/cmd_vel_out"; constexpr auto DEFAULT_ODOMETRY_TOPIC = "~/odom"; constexpr auto DEFAULT_TRANSFORM_TOPIC = "/tf"; @@ -302,7 +301,6 @@ controller_interface::CallbackReturn DiffDriveController::on_configure( cmd_vel_timeout_ = std::chrono::milliseconds{static_cast(params_.cmd_vel_timeout * 1000.0)}; publish_limited_velocity_ = params_.publish_limited_velocity; - use_stamped_vel_ = params_.use_stamped_vel; limiter_linear_ = SpeedLimiter( params_.linear.x.has_velocity_limits, params_.linear.x.has_acceleration_limits, @@ -340,50 +338,25 @@ controller_interface::CallbackReturn DiffDriveController::on_configure( previous_commands_.emplace(empty_twist); // initialize command subscriber - if (use_stamped_vel_) - { - velocity_command_subscriber_ = get_node()->create_subscription( - DEFAULT_COMMAND_TOPIC, rclcpp::SystemDefaultsQoS(), - [this](const std::shared_ptr msg) -> void + velocity_command_subscriber_ = get_node()->create_subscription( + DEFAULT_COMMAND_TOPIC, rclcpp::SystemDefaultsQoS(), + [this](const std::shared_ptr msg) -> void + { + if (!subscriber_is_active_) { - if (!subscriber_is_active_) - { - RCLCPP_WARN( - get_node()->get_logger(), "Can't accept new commands. subscriber is inactive"); - return; - } - if ((msg->header.stamp.sec == 0) && (msg->header.stamp.nanosec == 0)) - { - RCLCPP_WARN_ONCE( - get_node()->get_logger(), - "Received TwistStamped with zero timestamp, setting it to current " - "time, this message will only be shown once"); - msg->header.stamp = get_node()->get_clock()->now(); - } - received_velocity_msg_ptr_.set(std::move(msg)); - }); - } - else - { - velocity_command_unstamped_subscriber_ = - get_node()->create_subscription( - DEFAULT_COMMAND_UNSTAMPED_TOPIC, rclcpp::SystemDefaultsQoS(), - [this](const std::shared_ptr msg) -> void - { - if (!subscriber_is_active_) - { - RCLCPP_WARN( - get_node()->get_logger(), "Can't accept new commands. subscriber is inactive"); - return; - } - - // Write fake header in the stored stamped command - std::shared_ptr twist_stamped; - received_velocity_msg_ptr_.get(twist_stamped); - twist_stamped->twist = *msg; - twist_stamped->header.stamp = get_node()->get_clock()->now(); - }); - } + RCLCPP_WARN(get_node()->get_logger(), "Can't accept new commands. subscriber is inactive"); + return; + } + if ((msg->header.stamp.sec == 0) && (msg->header.stamp.nanosec == 0)) + { + RCLCPP_WARN_ONCE( + get_node()->get_logger(), + "Received TwistStamped with zero timestamp, setting it to current " + "time, this message will only be shown once"); + msg->header.stamp = get_node()->get_clock()->now(); + } + received_velocity_msg_ptr_.set(std::move(msg)); + }); // initialize odometry publisher and messasge odometry_publisher_ = get_node()->create_publisher( @@ -534,7 +507,6 @@ bool DiffDriveController::reset() subscriber_is_active_ = false; velocity_command_subscriber_.reset(); - velocity_command_unstamped_subscriber_.reset(); received_velocity_msg_ptr_.set(nullptr); is_halted = false; diff --git a/diff_drive_controller/src/diff_drive_controller_parameter.yaml b/diff_drive_controller/src/diff_drive_controller_parameter.yaml index 5d20970cab..46d89ae2d6 100644 --- a/diff_drive_controller/src/diff_drive_controller_parameter.yaml +++ b/diff_drive_controller/src/diff_drive_controller_parameter.yaml @@ -99,11 +99,6 @@ diff_drive_controller: default_value: 10, description: "Size of the rolling window for calculation of mean velocity use in odometry.", } - use_stamped_vel: { - type: bool, - default_value: true, - description: "Use stamp from input velocity message to calculate how old the command actually is.", - } publish_rate: { type: double, default_value: 50.0, # Hz From 71ec842bed2f024628bec614b4e6326488edf307 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Tue, 7 Nov 2023 13:47:23 +0100 Subject: [PATCH 137/238] [CI] Re-add humble workflow files and add iron to readme (#818) --- .github/workflows/README.md | 22 ------------- .../workflows/humble-abi-compatibility.yml | 20 +++++++++++ .../workflows/humble-binary-build-main.yml | 26 +++++++++++++++ .../workflows/humble-binary-build-testing.yml | 26 +++++++++++++++ .../workflows/humble-rhel-binary-build.yml | 33 +++++++++++++++++++ .../humble-semi-binary-build-main.yml | 25 ++++++++++++++ .../humble-semi-binary-build-testing.yml | 25 ++++++++++++++ .github/workflows/humble-source-build.yml | 19 +++++++++++ README.md | 1 + ros2_controllers-not-released.iron.repos | 6 ++++ 10 files changed, 181 insertions(+), 22 deletions(-) delete mode 100644 .github/workflows/README.md create mode 100644 .github/workflows/humble-abi-compatibility.yml create mode 100644 .github/workflows/humble-binary-build-main.yml create mode 100644 .github/workflows/humble-binary-build-testing.yml create mode 100644 .github/workflows/humble-rhel-binary-build.yml create mode 100644 .github/workflows/humble-semi-binary-build-main.yml create mode 100644 .github/workflows/humble-semi-binary-build-testing.yml create mode 100644 .github/workflows/humble-source-build.yml create mode 100644 ros2_controllers-not-released.iron.repos diff --git a/.github/workflows/README.md b/.github/workflows/README.md deleted file mode 100644 index 7727495a97..0000000000 --- a/.github/workflows/README.md +++ /dev/null @@ -1,22 +0,0 @@ -## Build status - -ROS2 Distro | Branch | Build status | Documentation | Released packages -:---------: | :----: | :----------: | :-----------: | :---------------: -**Rolling** | [`rolling`](https://github.com/ros-controls/ros2_controllers/tree/rolling) | [![Rolling Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-binary-build-main.yml?branch=master)
[![Rolling Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-binary-build-testing.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-binary-build-testing.yml?branch=master)
[![Rolling Semi-Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-semi-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-semi-binary-build-main.yml?branch=master)
[![Rolling Semi-Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-semi-binary-build-testing.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-semi-binary-build-testing.yml?branch=master)
[![Rolling Source Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-source-build.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-source-build.yml?branch=master) | | [ros2_controllers](https://index.ros.org/p/ros2_controllers/#rolling) -**Humble** | [`humble`](https://github.com/ros-controls/ros2_controllers/tree/humble) | [![Humble Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-binary-build-main.yml?branch=master)
[![Humble Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-binary-build-testing.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-binary-build-testing.yml?branch=master)
[![Humble Semi-Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-semi-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-semi-binary-build-main.yml?branch=master)
[![Humble Semi-Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-semi-binary-build-testing.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-semi-binary-build-testing.yml?branch=master)
[![Humble Source Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-source-build.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-source-build.yml?branch=master) | | [ros2_controllers](https://index.ros.org/p/ros2_controllers/#humble) - - -### Explanation of different build types - -**NOTE**: There are three build stages checking current and future compatibility of the package. - -1. Binary builds - against released packages (main and testing) in ROS distributions. Shows that direct local build is possible. - - Uses repos file: `$NAME$-not-released..repos` - -1. Semi-binary builds - against released core ROS packages (main and testing), but the immediate dependencies are pulled from source. - Shows that local build with dependencies is possible and if fails there we can expect that after the next package sync we will not be able to build. - - Uses repos file: `$NAME$.repos` - -1. Source build - also core ROS packages are build from source. It shows potential issues in the mid future. diff --git a/.github/workflows/humble-abi-compatibility.yml b/.github/workflows/humble-abi-compatibility.yml new file mode 100644 index 0000000000..708ea5c1f4 --- /dev/null +++ b/.github/workflows/humble-abi-compatibility.yml @@ -0,0 +1,20 @@ +name: Humble - ABI Compatibility Check +on: + workflow_dispatch: + branches: + - humble + pull_request: + branches: + - humble + +jobs: + abi_check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: ros-industrial/industrial_ci@master + env: + ROS_DISTRO: humble + ROS_REPO: main + ABICHECK_URL: github:${{ github.repository }}#${{ github.base_ref }} + NOT_TEST_BUILD: true diff --git a/.github/workflows/humble-binary-build-main.yml b/.github/workflows/humble-binary-build-main.yml new file mode 100644 index 0000000000..64d78f281a --- /dev/null +++ b/.github/workflows/humble-binary-build-main.yml @@ -0,0 +1,26 @@ +name: Humble Binary Build - main +# author: Denis Štogl +# description: 'Build & test all dependencies from released (binary) packages.' + +on: + workflow_dispatch: + branches: + - humble + pull_request: + branches: + - humble + push: + branches: + - humble + schedule: + # Run every morning to detect flakiness and broken dependencies + - cron: '03 1 * * *' + +jobs: + binary: + uses: ./.github/workflows/reusable-industrial-ci-with-cache.yml + with: + ros_distro: humble + ros_repo: main + upstream_workspace: ros2_controllers-not-released.humble.repos + ref_for_scheduled_build: humble diff --git a/.github/workflows/humble-binary-build-testing.yml b/.github/workflows/humble-binary-build-testing.yml new file mode 100644 index 0000000000..524cacd685 --- /dev/null +++ b/.github/workflows/humble-binary-build-testing.yml @@ -0,0 +1,26 @@ +name: Humble Binary Build - testing +# author: Denis Štogl +# description: 'Build & test all dependencies from released (binary) packages.' + +on: + workflow_dispatch: + branches: + - humble + pull_request: + branches: + - humble + push: + branches: + - humble + schedule: + # Run every morning to detect flakiness and broken dependencies + - cron: '03 1 * * *' + +jobs: + binary: + uses: ./.github/workflows/reusable-industrial-ci-with-cache.yml + with: + ros_distro: humble + ros_repo: testing + upstream_workspace: ros2_controllers-not-released.humble.repos + ref_for_scheduled_build: humble diff --git a/.github/workflows/humble-rhel-binary-build.yml b/.github/workflows/humble-rhel-binary-build.yml new file mode 100644 index 0000000000..9da6059892 --- /dev/null +++ b/.github/workflows/humble-rhel-binary-build.yml @@ -0,0 +1,33 @@ +name: Humble RHEL Binary Build +on: + workflow_dispatch: + branches: + - humble + pull_request: + branches: + - humble + push: + branches: + - humble + schedule: + # Run every day to detect flakiness and broken dependencies + - cron: '03 1 * * *' + + +jobs: + humble_rhel_binary: + name: Humble RHEL binary build + runs-on: ubuntu-latest + env: + ROS_DISTRO: humble + container: ghcr.io/ros-controls/ros:humble-rhel + steps: + - uses: actions/checkout@v4 + with: + path: src/ros2_controllers + - run: | + rosdep update + rosdep install -iy --from-path src/ros2_controllers + source /opt/ros/${{ env.ROS_DISTRO }}/setup.bash + colcon build + colcon test diff --git a/.github/workflows/humble-semi-binary-build-main.yml b/.github/workflows/humble-semi-binary-build-main.yml new file mode 100644 index 0000000000..863df79a22 --- /dev/null +++ b/.github/workflows/humble-semi-binary-build-main.yml @@ -0,0 +1,25 @@ +name: Humble Semi-Binary Build - main +# description: 'Build & test that compiles the main dependencies from source.' + +on: + workflow_dispatch: + branches: + - humble + pull_request: + branches: + - humble + push: + branches: + - humble + schedule: + # Run every morning to detect flakiness and broken dependencies + - cron: '33 1 * * *' + +jobs: + semi_binary: + uses: ./.github/workflows/reusable-industrial-ci-with-cache.yml + with: + ros_distro: humble + ros_repo: main + upstream_workspace: ros2_controllers.humble.repos + ref_for_scheduled_build: humble diff --git a/.github/workflows/humble-semi-binary-build-testing.yml b/.github/workflows/humble-semi-binary-build-testing.yml new file mode 100644 index 0000000000..6286636e1f --- /dev/null +++ b/.github/workflows/humble-semi-binary-build-testing.yml @@ -0,0 +1,25 @@ +name: Humble Semi-Binary Build - testing +# description: 'Build & test that compiles the main dependencies from source.' + +on: + workflow_dispatch: + branches: + - humble + pull_request: + branches: + - humble + push: + branches: + - humble + schedule: + # Run every morning to detect flakiness and broken dependencies + - cron: '33 1 * * *' + +jobs: + semi_binary: + uses: ./.github/workflows/reusable-industrial-ci-with-cache.yml + with: + ros_distro: humble + ros_repo: testing + upstream_workspace: ros2_controllers.humble.repos + ref_for_scheduled_build: humble diff --git a/.github/workflows/humble-source-build.yml b/.github/workflows/humble-source-build.yml new file mode 100644 index 0000000000..ff0fd62e05 --- /dev/null +++ b/.github/workflows/humble-source-build.yml @@ -0,0 +1,19 @@ +name: Humble Source Build +on: + workflow_dispatch: + branches: + - humble + push: + branches: + - humble + schedule: + # Run every day to detect flakiness and broken dependencies + - cron: '03 3 * * *' + +jobs: + source: + uses: ./.github/workflows/reusable-ros-tooling-source-build.yml + with: + ros_distro: humble + ref: humble + ros2_repo_branch: humble diff --git a/README.md b/README.md index 49d6b28ea0..d41ec09b6c 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ Commonly used and generalized controllers for ros2-control framework that are re ROS2 Distro | Branch | Build status | Documentation | Released packages :---------: | :----: | :----------: | :-----------: | :---------------: **Rolling** | [`rolling`](https://github.com/ros-controls/ros2_controllers/tree/rolling) | [![Rolling Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-binary-build-main.yml?branch=master)
[![Rolling Semi-Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-semi-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-semi-binary-build-main.yml?branch=master) | | [ros2_controllers](https://index.ros.org/p/ros2_controllers/#rolling) +**Iron** | [`iron`](https://github.com/ros-controls/ros2_controllers/tree/iron) | [![Iron Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/iron-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/iron-binary-build-main.yml?branch=master)
[![Iron Semi-Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/iron-semi-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/iron-semi-binary-build-main.yml?branch=master) | | [ros2_controllers](https://index.ros.org/p/ros2_controllers/#iron) **Humble** | [`humble`](https://github.com/ros-controls/ros2_controllers/tree/humble) | [![Humble Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-binary-build-main.yml?branch=master)
[![Humble Semi-Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-semi-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-semi-binary-build-main.yml?branch=master) | | [ros2_controllers](https://index.ros.org/p/ros2_controllers/#humble) ### Explanation of different build types diff --git a/ros2_controllers-not-released.iron.repos b/ros2_controllers-not-released.iron.repos new file mode 100644 index 0000000000..1b3910e7e7 --- /dev/null +++ b/ros2_controllers-not-released.iron.repos @@ -0,0 +1,6 @@ +repositories: + ## EXAMPLE DEPENDENCY +# : +# type: git +# url: git@github.com:/.git +# version: master From 0196eeb29ad0e2c908b547f57d31a8a1ea13e869 Mon Sep 17 00:00:00 2001 From: Tony Baltovski Date: Thu, 9 Nov 2023 17:15:45 -0500 Subject: [PATCH 138/238] [diff_drive_controller] Fixed typos in diff_drive_controller_parameter.yaml. (#822) --- .../src/diff_drive_controller_parameter.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/diff_drive_controller/src/diff_drive_controller_parameter.yaml b/diff_drive_controller/src/diff_drive_controller_parameter.yaml index 46d89ae2d6..0c0285e7c2 100644 --- a/diff_drive_controller/src/diff_drive_controller_parameter.yaml +++ b/diff_drive_controller/src/diff_drive_controller_parameter.yaml @@ -17,7 +17,7 @@ diff_drive_controller: wheels_per_side: { type: int, default_value: 0, - description: "Number of wheels on each wide of the robot. This is important to take the wheels slip into account when multiple wheels on each side are present. If there are more wheels then control signals for each side, you should enter number or control signals. For example, Husky has two wheels on each side, but they use one control signal, in this case '1' is the correct value of the parameter.", + description: "Number of wheels on each side of the robot. This is important to take the wheels slip into account when multiple wheels on each side are present. If there are more wheels then control signals for each side, you should enter number for control signals. For example, Husky has two wheels on each side, but they use one control signal, in this case '1' is the correct value of the parameter.", } wheel_radius: { type: double, @@ -87,7 +87,7 @@ diff_drive_controller: cmd_vel_timeout: { type: double, default_value: 0.5, # seconds - description: "Timeout after which input command on ``cmd_vel`` topic is considered staled.", + description: "Timeout in seconds, after which input command on ``cmd_vel`` topic is considered staled.", } publish_limited_velocity: { type: bool, From 232154dab5f5363704c7f7640b2d42f5d6f3665b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Sat, 11 Nov 2023 15:30:19 +0100 Subject: [PATCH 139/238] [CI] Update coverage workflows and some cleanup (#819) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add CI coverage jobs for humble and iron * Add all packages to source build * Update repos files * Build ros-control packages from source * use humble job names Co-authored-by: Christoph Fröhlich --------- Co-authored-by: Bence Magyar --- .../workflows/ci-coverage-build-humble.yml | 65 +++++++++++++++++++ .github/workflows/ci-coverage-build-iron.yml | 65 +++++++++++++++++++ .github/workflows/ci-coverage-build.yml | 2 +- .../reusable-ros-tooling-source-build.yml | 19 ++++++ ros2_controllers.iron.repos | 8 --- ros2_controllers.rolling.repos | 5 -- 6 files changed, 150 insertions(+), 14 deletions(-) create mode 100644 .github/workflows/ci-coverage-build-humble.yml create mode 100644 .github/workflows/ci-coverage-build-iron.yml diff --git a/.github/workflows/ci-coverage-build-humble.yml b/.github/workflows/ci-coverage-build-humble.yml new file mode 100644 index 0000000000..46922ccaac --- /dev/null +++ b/.github/workflows/ci-coverage-build-humble.yml @@ -0,0 +1,65 @@ +name: Coverage Build - Humble +on: + workflow_dispatch: + push: + branches: + - humble + pull_request: + branches: + - humble + +jobs: + coverage: + name: coverage build + runs-on: ubuntu-22.04 + strategy: + fail-fast: false + env: + ROS_DISTRO: humble + steps: + - uses: ros-tooling/setup-ros@0.7.0 + with: + required-ros-distributions: ${{ env.ROS_DISTRO }} + - uses: actions/checkout@v4 + - uses: ros-tooling/action-ros-ci@0.3.4 + with: + target-ros2-distro: ${{ env.ROS_DISTRO }} + import-token: ${{ secrets.GITHUB_TOKEN }} + # build all packages listed here + package-name: + ackermann_steering_controller + admittance_controller + bicycle_steering_controller + diff_drive_controller + effort_controllers + force_torque_sensor_broadcaster + forward_command_controller + gripper_controllers + imu_sensor_broadcaster + joint_state_broadcaster + joint_trajectory_controller + position_controllers + range_sensor_broadcaster + steering_controllers_library + tricycle_controller + tricycle_steering_controller + velocity_controllers + + vcs-repo-file-url: | + https://raw.githubusercontent.com/${{ github.repository }}/${{ github.sha }}/ros2_controllers.${{ env.ROS_DISTRO }}.repos?token=${{ secrets.GITHUB_TOKEN }} + colcon-defaults: | + { + "build": { + "mixin": ["coverage-gcc"] + } + } + colcon-mixin-repository: https://raw.githubusercontent.com/colcon/colcon-mixin-repository/master/index.yaml + - uses: codecov/codecov-action@v3.1.4 + with: + file: ros_ws/lcov/total_coverage.info + flags: unittests + name: codecov-umbrella + - uses: actions/upload-artifact@v3.1.3 + with: + name: colcon-logs-coverage-humble + path: ros_ws/log diff --git a/.github/workflows/ci-coverage-build-iron.yml b/.github/workflows/ci-coverage-build-iron.yml new file mode 100644 index 0000000000..723654b33e --- /dev/null +++ b/.github/workflows/ci-coverage-build-iron.yml @@ -0,0 +1,65 @@ +name: Coverage Build - Iron +on: + workflow_dispatch: + push: + branches: + - iron + pull_request: + branches: + - iron + +jobs: + coverage: + name: coverage build + runs-on: ubuntu-22.04 + strategy: + fail-fast: false + env: + ROS_DISTRO: iron + steps: + - uses: ros-tooling/setup-ros@0.7.0 + with: + required-ros-distributions: ${{ env.ROS_DISTRO }} + - uses: actions/checkout@v4 + - uses: ros-tooling/action-ros-ci@0.3.4 + with: + target-ros2-distro: ${{ env.ROS_DISTRO }} + import-token: ${{ secrets.GITHUB_TOKEN }} + # build all packages listed here + package-name: + ackermann_steering_controller + admittance_controller + bicycle_steering_controller + diff_drive_controller + effort_controllers + force_torque_sensor_broadcaster + forward_command_controller + gripper_controllers + imu_sensor_broadcaster + joint_state_broadcaster + joint_trajectory_controller + position_controllers + range_sensor_broadcaster + steering_controllers_library + tricycle_controller + tricycle_steering_controller + velocity_controllers + + vcs-repo-file-url: | + https://raw.githubusercontent.com/${{ github.repository }}/${{ github.sha }}/ros2_controllers.${{ env.ROS_DISTRO }}.repos?token=${{ secrets.GITHUB_TOKEN }} + colcon-defaults: | + { + "build": { + "mixin": ["coverage-gcc"] + } + } + colcon-mixin-repository: https://raw.githubusercontent.com/colcon/colcon-mixin-repository/master/index.yaml + - uses: codecov/codecov-action@v3.1.4 + with: + file: ros_ws/lcov/total_coverage.info + flags: unittests + name: codecov-umbrella + - uses: actions/upload-artifact@v3.1.3 + with: + name: colcon-logs-coverage-iron + path: ros_ws/log diff --git a/.github/workflows/ci-coverage-build.yml b/.github/workflows/ci-coverage-build.yml index 694f3dd8a1..6a932a2dcd 100644 --- a/.github/workflows/ci-coverage-build.yml +++ b/.github/workflows/ci-coverage-build.yml @@ -46,7 +46,7 @@ jobs: velocity_controllers vcs-repo-file-url: | - https://raw.githubusercontent.com/${{ github.repository }}/${{ github.sha }}/ros2_controllers-not-released.${{ env.ROS_DISTRO }}.repos?token=${{ secrets.GITHUB_TOKEN }} + https://raw.githubusercontent.com/${{ github.repository }}/${{ github.sha }}/ros2_controllers.${{ env.ROS_DISTRO }}.repos?token=${{ secrets.GITHUB_TOKEN }} colcon-defaults: | { "build": { diff --git a/.github/workflows/reusable-ros-tooling-source-build.yml b/.github/workflows/reusable-ros-tooling-source-build.yml index ad3dcd505d..a444a7f645 100644 --- a/.github/workflows/reusable-ros-tooling-source-build.yml +++ b/.github/workflows/reusable-ros-tooling-source-build.yml @@ -38,7 +38,26 @@ jobs: ref: ${{ inputs.ref }} # build all packages listed in the meta package package-name: + ackermann_steering_controller + admittance_controller + bicycle_steering_controller diff_drive_controller + effort_controllers + force_torque_sensor_broadcaster + forward_command_controller + gripper_controllers + imu_sensor_broadcaster + joint_state_broadcaster + joint_trajectory_controller + position_controllers + range_sensor_broadcaster + ros2_controllers + ros2_controllers_test_nodes + rqt_joint_trajectory_controller + steering_controllers_library + tricycle_controller + tricycle_steering_controller + velocity_controllers vcs-repo-file-url: | https://raw.githubusercontent.com/ros2/ros2/${{ inputs.ros2_repo_branch }}/ros2.repos diff --git a/ros2_controllers.iron.repos b/ros2_controllers.iron.repos index 4e2c7abbbd..7f2db052cb 100644 --- a/ros2_controllers.iron.repos +++ b/ros2_controllers.iron.repos @@ -19,11 +19,3 @@ repositories: type: git url: https://github.com/ros-controls/kinematics_interface.git version: master - angles: - type: git - url: https://github.com/ros/angles.git - version: ros2 - generate_parameter_library: - type: git - url: https://github.com/picknikrobotics/generate_parameter_library.git - version: main diff --git a/ros2_controllers.rolling.repos b/ros2_controllers.rolling.repos index 42ec854e25..8c20eccc96 100644 --- a/ros2_controllers.rolling.repos +++ b/ros2_controllers.rolling.repos @@ -15,15 +15,10 @@ repositories: type: git url: https://github.com/ros-controls/control_toolbox.git version: ros2-master - kinematics_interface: type: git url: https://github.com/ros-controls/kinematics_interface.git version: master - angles: - type: git - url: https://github.com/ros/angles.git - version: ros2 generate_parameter_library: type: git url: https://github.com/picknikrobotics/generate_parameter_library.git From f1a5397eb169f4358651654d144a0dea2e89ff1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Wed, 15 Nov 2023 12:18:38 +0100 Subject: [PATCH 140/238] [JTC] Remove deprecation warnings, set `allow_nonzero_velocity_at_trajectory_end` default false (#834) --- .../doc/parameters.rst | 3 +-- .../joint_trajectory_controller.hpp | 4 ++-- .../src/joint_trajectory_controller.cpp | 24 +++---------------- ...oint_trajectory_controller_parameters.yaml | 7 +----- .../test/test_trajectory_actions.cpp | 6 ++++- .../test/test_trajectory_controller.cpp | 23 ++++++++---------- .../test/test_trajectory_controller_utils.hpp | 20 +++++++++------- 7 files changed, 34 insertions(+), 53 deletions(-) diff --git a/joint_trajectory_controller/doc/parameters.rst b/joint_trajectory_controller/doc/parameters.rst index 95a6599191..8ad2b406d6 100644 --- a/joint_trajectory_controller/doc/parameters.rst +++ b/joint_trajectory_controller/doc/parameters.rst @@ -66,7 +66,7 @@ start_with_holding (bool) allow_nonzero_velocity_at_trajectory_end (boolean) If false, the last velocity point has to be zero or the goal will be rejected. - Default: true + Default: false cmd_timeout (double) Timeout after which the input command is considered stale. @@ -147,5 +147,4 @@ gains..angle_wraparound (bool) Otherwise :math:`e = s_d - s` is used, with the desired position :math:`s_d` and the measured position :math:`s` from the state interface. - Default: false diff --git a/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp b/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp index 0366c8e6d6..bf75e3f99b 100644 --- a/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp +++ b/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp @@ -167,8 +167,8 @@ class JointTrajectoryController : public controller_interface::ControllerInterfa std::vector pids_; // Feed-forward velocity weight factor when calculating closed loop pid adapter's command std::vector ff_velocity_scale_; - // Configuration for every joint, if position error is normalized - std::vector normalize_joint_error_; + // Configuration for every joint, if position error is wrapped around + std::vector joints_angle_wraparound_; // reserved storage for result of the command when closed loop pid adapter is used std::vector tmp_command_; diff --git a/joint_trajectory_controller/src/joint_trajectory_controller.cpp b/joint_trajectory_controller/src/joint_trajectory_controller.cpp index 9e0b4823f3..88dd75b08a 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller.cpp +++ b/joint_trajectory_controller/src/joint_trajectory_controller.cpp @@ -64,15 +64,6 @@ controller_interface::CallbackReturn JointTrajectoryController::on_init() return CallbackReturn::ERROR; } - // TODO(christophfroehlich): remove deprecation warning - if (params_.allow_nonzero_velocity_at_trajectory_end) - { - RCLCPP_WARN( - get_node()->get_logger(), - "[Deprecated]: \"allow_nonzero_velocity_at_trajectory_end\" is set to " - "true. The default behavior will change to false."); - } - return CallbackReturn::SUCCESS; } @@ -131,7 +122,7 @@ controller_interface::return_type JointTrajectoryController::update( const JointTrajectoryPoint & desired) { // error defined as the difference between current and desired - if (normalize_joint_error_[index]) + if (joints_angle_wraparound_[index]) { // if desired, the shortest_angular_distance is calculated, i.e., the error is // normalized between -pihas_effort_command_interface()) == false) + { + // can't succeed with effort cmd if + EXPECT_EQ(rclcpp_action::ResultCode::SUCCEEDED, common_resultcode_); + } } TEST_P(TestTrajectoryActionsTestParameterized, test_allow_nonzero_velocity_at_trajectory_end_false) diff --git a/joint_trajectory_controller/test/test_trajectory_controller.cpp b/joint_trajectory_controller/test/test_trajectory_controller.cpp index 07d60ce077..b2efc44bff 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller.cpp +++ b/joint_trajectory_controller/test/test_trajectory_controller.cpp @@ -201,8 +201,7 @@ TEST_P(TrajectoryControllerTestParameterized, activate) TEST_P(TrajectoryControllerTestParameterized, cleanup) { rclcpp::executors::MultiThreadedExecutor executor; - std::vector params = { - rclcpp::Parameter("allow_nonzero_velocity_at_trajectory_end", true)}; + std::vector params = {}; SetUpAndActivateTrajectoryController(executor, params); // send msg @@ -456,14 +455,13 @@ TEST_P(TrajectoryControllerTestParameterized, hold_on_startup) // Floating-point value comparison threshold const double EPS = 1e-6; /** - * @brief check if position error of revolute joints are normalized if not configured so + * @brief check if position error of revolute joints are angle_wraparound if not configured so */ -TEST_P(TrajectoryControllerTestParameterized, position_error_not_normalized) +TEST_P(TrajectoryControllerTestParameterized, position_error_not_angle_wraparound) { rclcpp::executors::MultiThreadedExecutor executor; constexpr double k_p = 10.0; - std::vector params = { - rclcpp::Parameter("allow_nonzero_velocity_at_trajectory_end", true)}; + std::vector params = {}; SetUpAndActivateTrajectoryController(executor, params, true, k_p, 0.0, false); subscribeToState(); @@ -706,14 +704,13 @@ TEST_P(TrajectoryControllerTestParameterized, timeout) } /** - * @brief check if position error of revolute joints are normalized if configured so + * @brief check if position error of revolute joints are angle_wraparound if configured so */ -TEST_P(TrajectoryControllerTestParameterized, position_error_normalized) +TEST_P(TrajectoryControllerTestParameterized, position_error_angle_wraparound) { rclcpp::executors::MultiThreadedExecutor executor; constexpr double k_p = 10.0; - std::vector params = { - rclcpp::Parameter("allow_nonzero_velocity_at_trajectory_end", true)}; + std::vector params = {}; SetUpAndActivateTrajectoryController(executor, params, true, k_p, 0.0, true); subscribeToState(); @@ -754,7 +751,7 @@ TEST_P(TrajectoryControllerTestParameterized, position_error_normalized) EXPECT_NEAR(points[0][1], state_msg->reference.positions[1], allowed_delta); EXPECT_NEAR(points[0][2], state_msg->reference.positions[2], 3 * allowed_delta); - // is error.positions[2] normalized? + // is error.positions[2] angle_wraparound? EXPECT_NEAR( state_msg->error.positions[0], state_msg->reference.positions[0] - INITIAL_POS_JOINTS[0], EPS); EXPECT_NEAR( @@ -783,7 +780,7 @@ TEST_P(TrajectoryControllerTestParameterized, position_error_normalized) EXPECT_NEAR( k_p * (state_msg->reference.positions[1] - INITIAL_POS_JOINTS[1]), joint_vel_[1], k_p * allowed_delta); - // is error of positions[2] normalized? + // is error of positions[2] angle_wraparound? EXPECT_GT(0.0, joint_vel_[2]); EXPECT_NEAR( k_p * (state_msg->reference.positions[2] - INITIAL_POS_JOINTS[2] - 2 * M_PI), joint_vel_[2], @@ -811,7 +808,7 @@ TEST_P(TrajectoryControllerTestParameterized, position_error_normalized) EXPECT_NEAR( k_p * (state_msg->reference.positions[1] - INITIAL_POS_JOINTS[1]), joint_eff_[1], k_p * allowed_delta); - // is error of positions[2] normalized? + // is error of positions[2] angle_wraparound? EXPECT_GT(0.0, joint_eff_[2]); EXPECT_NEAR( k_p * (state_msg->reference.positions[2] - INITIAL_POS_JOINTS[2] - 2 * M_PI), joint_eff_[2], diff --git a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp index 7c65fec29c..69f41d2cd9 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp +++ b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp @@ -198,7 +198,7 @@ class TrajectoryControllerTest : public ::testing::Test } void SetPidParameters( - double p_default = 0.0, double ff_default = 1.0, bool normalize_error_default = false) + double p_default = 0.0, double ff_default = 1.0, bool angle_wraparound_default = false) { traj_controller_->trigger_declare_parameters(); auto node = traj_controller_->get_node(); @@ -211,27 +211,31 @@ class TrajectoryControllerTest : public ::testing::Test const rclcpp::Parameter k_d(prefix + ".d", 0.0); const rclcpp::Parameter i_clamp(prefix + ".i_clamp", 0.0); const rclcpp::Parameter ff_velocity_scale(prefix + ".ff_velocity_scale", ff_default); - const rclcpp::Parameter normalize_error(prefix + ".normalize_error", normalize_error_default); - node->set_parameters({k_p, k_i, k_d, i_clamp, ff_velocity_scale, normalize_error}); + const rclcpp::Parameter angle_wraparound( + prefix + ".angle_wraparound", angle_wraparound_default); + node->set_parameters({k_p, k_i, k_d, i_clamp, ff_velocity_scale, angle_wraparound}); } } void SetUpAndActivateTrajectoryController( rclcpp::Executor & executor, const std::vector & parameters = {}, bool separate_cmd_and_state_values = false, double k_p = 0.0, double ff = 1.0, - bool normalize_error = false) + bool angle_wraparound = false) { SetUpTrajectoryController(executor); + // add this to simplify tests, can be overwritten by parameters + rclcpp::Parameter nonzero_vel_parameter("allow_nonzero_velocity_at_trajectory_end", true); + traj_controller_->get_node()->set_parameter(nonzero_vel_parameter); + // set pid parameters before configure - SetPidParameters(k_p, ff, normalize_error); + SetPidParameters(k_p, ff, angle_wraparound); + + // set optional parameters for (const auto & param : parameters) { traj_controller_->get_node()->set_parameter(param); } - // ignore velocity tolerances for this test since they aren't committed in test_robot->write() - rclcpp::Parameter stopped_velocity_parameters("constraints.stopped_velocity_tolerance", 0.0); - traj_controller_->get_node()->set_parameter(stopped_velocity_parameters); traj_controller_->get_node()->configure(); From b13ae5b5c35dfb40283a51b5fe0285d41571aa5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Wed, 15 Nov 2023 19:14:09 +0100 Subject: [PATCH 141/238] [JTC] Fix tests when state offset is used (#797) * Simplify initialization of states * Rename read_state_from_hardware method * Don't set state_desired in on_activate --------- Co-authored-by: Dr. Denis --- .../joint_trajectory_controller.hpp | 8 +- .../src/joint_trajectory_controller.cpp | 19 +-- .../test/test_trajectory_controller.cpp | 118 +++++++++++------- .../test/test_trajectory_controller_utils.hpp | 72 +++++++---- 4 files changed, 135 insertions(+), 82 deletions(-) diff --git a/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp b/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp index bf75e3f99b..eaf821aa26 100644 --- a/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp +++ b/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp @@ -261,8 +261,14 @@ class JointTrajectoryController : public controller_interface::ControllerInterfa const rclcpp::Time & time, const JointTrajectoryPoint & desired_state, const JointTrajectoryPoint & current_state, const JointTrajectoryPoint & state_error); - void read_state_from_hardware(JointTrajectoryPoint & state); + void read_state_from_state_interfaces(JointTrajectoryPoint & state); + /** Assign values from the command interfaces as state. + * This is only possible if command AND state interfaces exist for the same type, + * therefore needs check for both. + * @param[out] state to be filled with values from command interfaces. + * @return true if all interfaces exists and contain non-NaN values, false otherwise. + */ bool read_state_from_command_interfaces(JointTrajectoryPoint & state); bool read_commands_from_command_interfaces(JointTrajectoryPoint & commands); diff --git a/joint_trajectory_controller/src/joint_trajectory_controller.cpp b/joint_trajectory_controller/src/joint_trajectory_controller.cpp index 88dd75b08a..cf35156541 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller.cpp +++ b/joint_trajectory_controller/src/joint_trajectory_controller.cpp @@ -175,7 +175,7 @@ controller_interface::return_type JointTrajectoryController::update( // current state update state_current_.time_from_start.set__sec(0); - read_state_from_hardware(state_current_); + read_state_from_state_interfaces(state_current_); // currently carrying out a trajectory if (has_active_trajectory()) @@ -397,7 +397,7 @@ controller_interface::return_type JointTrajectoryController::update( return controller_interface::return_type::OK; } -void JointTrajectoryController::read_state_from_hardware(JointTrajectoryPoint & state) +void JointTrajectoryController::read_state_from_state_interfaces(JointTrajectoryPoint & state) { auto assign_point_from_interface = [&](std::vector & trajectory_point_interface, const auto & joint_interface) @@ -951,20 +951,21 @@ controller_interface::CallbackReturn JointTrajectoryController::on_activate( subscriber_is_active_ = true; - // Initialize current state storage if hardware state has tracking offset - read_state_from_hardware(state_current_); - read_state_from_hardware(state_desired_); - read_state_from_hardware(last_commanded_state_); - // Handle restart of controller by reading from commands if - // those are not nan + // Handle restart of controller by reading from commands if those are not NaN (a controller was + // running already) trajectory_msgs::msg::JointTrajectoryPoint state; resize_joint_trajectory_point(state, dof_); if (read_state_from_command_interfaces(state)) { state_current_ = state; - state_desired_ = state; last_commanded_state_ = state; } + else + { + // Initialize current state storage from hardware + read_state_from_state_interfaces(state_current_); + read_state_from_state_interfaces(last_commanded_state_); + } // Should the controller start by holding position at the beginning of active state? if (params_.start_with_holding) diff --git a/joint_trajectory_controller/test/test_trajectory_controller.cpp b/joint_trajectory_controller/test/test_trajectory_controller.cpp index b2efc44bff..117575be37 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller.cpp +++ b/joint_trajectory_controller/test/test_trajectory_controller.cpp @@ -1668,21 +1668,23 @@ TEST_P(TrajectoryControllerTestParameterized, test_no_jump_when_state_tracking_e #endif // Testing that values are read from state interfaces when hardware is started for the first -// time and hardware state has offset --> this is indicated by NaN values in state interfaces +// time and hardware state has offset --> this is indicated by NaN values in command interfaces TEST_P(TrajectoryControllerTestParameterized, test_hw_states_has_offset_first_controller_start) { rclcpp::executors::SingleThreadedExecutor executor; - // default if false so it will not be actually set parameter rclcpp::Parameter is_open_loop_parameters("open_loop_control", true); // set command values to NaN - for (size_t i = 0; i < 3; ++i) - { - joint_pos_[i] = std::numeric_limits::quiet_NaN(); - joint_vel_[i] = std::numeric_limits::quiet_NaN(); - joint_acc_[i] = std::numeric_limits::quiet_NaN(); - } - SetUpAndActivateTrajectoryController(executor, {is_open_loop_parameters}, true); + std::vector initial_pos_cmd{3, std::numeric_limits::quiet_NaN()}; + std::vector initial_vel_cmd{3, std::numeric_limits::quiet_NaN()}; + std::vector initial_acc_cmd{3, std::numeric_limits::quiet_NaN()}; + + SetUpAndActivateTrajectoryController( + executor, {is_open_loop_parameters}, true, 0., 1., false, initial_pos_cmd, initial_vel_cmd, + initial_acc_cmd); + + // no call of update method, so the values should be read from state interfaces + // (command interface are NaN) auto current_state_when_offset = traj_controller_->get_current_state_when_offset(); @@ -1691,70 +1693,96 @@ TEST_P(TrajectoryControllerTestParameterized, test_hw_states_has_offset_first_co EXPECT_EQ(current_state_when_offset.positions[i], joint_state_pos_[i]); // check velocity - if ( - std::find( - state_interface_types_.begin(), state_interface_types_.end(), - hardware_interface::HW_IF_VELOCITY) != state_interface_types_.end() && - traj_controller_->has_velocity_command_interface()) + if (traj_controller_->has_velocity_state_interface()) { - EXPECT_EQ(current_state_when_offset.positions[i], joint_state_pos_[i]); + EXPECT_EQ(current_state_when_offset.velocities[i], joint_state_vel_[i]); } // check acceleration - if ( - std::find( - state_interface_types_.begin(), state_interface_types_.end(), - hardware_interface::HW_IF_ACCELERATION) != state_interface_types_.end() && - traj_controller_->has_acceleration_command_interface()) + if (traj_controller_->has_acceleration_state_interface()) { - EXPECT_EQ(current_state_when_offset.positions[i], joint_state_pos_[i]); + EXPECT_EQ(current_state_when_offset.accelerations[i], joint_state_acc_[i]); } } executor.cancel(); } -// Testing that values are read from state interfaces when hardware is started after some values +// Testing that values are read from command interfaces when hardware is started after some values // are set on the hardware commands TEST_P(TrajectoryControllerTestParameterized, test_hw_states_has_offset_later_controller_start) { rclcpp::executors::SingleThreadedExecutor executor; - // default if false so it will not be actually set parameter rclcpp::Parameter is_open_loop_parameters("open_loop_control", true); - // set command values to NaN + // set command values to arbitrary values + std::vector initial_pos_cmd, initial_vel_cmd, initial_acc_cmd; for (size_t i = 0; i < 3; ++i) { - joint_pos_[i] = 3.1 + static_cast(i); - joint_vel_[i] = 0.25 + static_cast(i); - joint_acc_[i] = 0.02 + static_cast(i) / 10.0; + initial_pos_cmd.push_back(3.1 + static_cast(i)); + initial_vel_cmd.push_back(0.25 + static_cast(i)); + initial_acc_cmd.push_back(0.02 + static_cast(i) / 10.0); } - SetUpAndActivateTrajectoryController(executor, {is_open_loop_parameters}, true); + SetUpAndActivateTrajectoryController( + executor, {is_open_loop_parameters}, true, 0., 1., false, initial_pos_cmd, initial_vel_cmd, + initial_acc_cmd); + + // no call of update method, so the values should be read from command interfaces auto current_state_when_offset = traj_controller_->get_current_state_when_offset(); for (size_t i = 0; i < 3; ++i) { - EXPECT_EQ(current_state_when_offset.positions[i], joint_pos_[i]); - - // check velocity - if ( - std::find( - state_interface_types_.begin(), state_interface_types_.end(), - hardware_interface::HW_IF_VELOCITY) != state_interface_types_.end() && - traj_controller_->has_velocity_command_interface()) + // check position + if (traj_controller_->has_position_command_interface()) { - EXPECT_EQ(current_state_when_offset.positions[i], joint_pos_[i]); + // check velocity + if (traj_controller_->has_velocity_state_interface()) + { + if (traj_controller_->has_velocity_command_interface()) + { + // check acceleration + if (traj_controller_->has_acceleration_state_interface()) + { + if (traj_controller_->has_acceleration_command_interface()) + { + // should have set it to last position + velocity + acceleration command + EXPECT_EQ(current_state_when_offset.positions[i], initial_pos_cmd[i]); + EXPECT_EQ(current_state_when_offset.velocities[i], initial_vel_cmd[i]); + EXPECT_EQ(current_state_when_offset.accelerations[i], initial_acc_cmd[i]); + } + else + { + // should have set it to the state interface instead + EXPECT_EQ(current_state_when_offset.positions[i], joint_state_pos_[i]); + EXPECT_EQ(current_state_when_offset.velocities[i], joint_state_vel_[i]); + EXPECT_EQ(current_state_when_offset.accelerations[i], joint_state_acc_[i]); + } + } + else + { + // should have set it to last position + velocity command + EXPECT_EQ(current_state_when_offset.positions[i], initial_pos_cmd[i]); + EXPECT_EQ(current_state_when_offset.velocities[i], initial_vel_cmd[i]); + } + } + else + { + // should have set it to the state interface instead + EXPECT_EQ(current_state_when_offset.positions[i], joint_state_pos_[i]); + EXPECT_EQ(current_state_when_offset.velocities[i], joint_state_vel_[i]); + } + } + else + { + // should have set it to last position command + EXPECT_EQ(current_state_when_offset.positions[i], initial_pos_cmd[i]); + } } - - // check acceleration - if ( - std::find( - state_interface_types_.begin(), state_interface_types_.end(), - hardware_interface::HW_IF_ACCELERATION) != state_interface_types_.end() && - traj_controller_->has_acceleration_command_interface()) + else { - EXPECT_EQ(current_state_when_offset.positions[i], joint_pos_[i]); + // should have set it to the state interface instead + EXPECT_EQ(current_state_when_offset.positions[i], joint_state_pos_[i]); } } diff --git a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp index 69f41d2cd9..7118882da1 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp +++ b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp @@ -220,7 +220,11 @@ class TrajectoryControllerTest : public ::testing::Test void SetUpAndActivateTrajectoryController( rclcpp::Executor & executor, const std::vector & parameters = {}, bool separate_cmd_and_state_values = false, double k_p = 0.0, double ff = 1.0, - bool angle_wraparound = false) + bool angle_wraparound = false, + const std::vector initial_pos_joints = INITIAL_POS_JOINTS, + const std::vector initial_vel_joints = INITIAL_VEL_JOINTS, + const std::vector initial_acc_joints = INITIAL_ACC_JOINTS, + const std::vector initial_eff_joints = INITIAL_EFF_JOINTS) { SetUpTrajectoryController(executor); @@ -239,12 +243,17 @@ class TrajectoryControllerTest : public ::testing::Test traj_controller_->get_node()->configure(); - ActivateTrajectoryController(separate_cmd_and_state_values); + ActivateTrajectoryController( + separate_cmd_and_state_values, initial_pos_joints, initial_vel_joints, initial_acc_joints, + initial_eff_joints); } void ActivateTrajectoryController( bool separate_cmd_and_state_values = false, - const std::vector initial_pos_joints = INITIAL_POS_JOINTS) + const std::vector initial_pos_joints = INITIAL_POS_JOINTS, + const std::vector initial_vel_joints = INITIAL_VEL_JOINTS, + const std::vector initial_acc_joints = INITIAL_ACC_JOINTS, + const std::vector initial_eff_joints = INITIAL_EFF_JOINTS) { std::vector cmd_interfaces; std::vector state_interfaces; @@ -280,14 +289,17 @@ class TrajectoryControllerTest : public ::testing::Test cmd_interfaces.emplace_back(pos_cmd_interfaces_.back()); cmd_interfaces.back().set_value(initial_pos_joints[i]); cmd_interfaces.emplace_back(vel_cmd_interfaces_.back()); - cmd_interfaces.back().set_value(INITIAL_VEL_JOINTS[i]); + cmd_interfaces.back().set_value(initial_vel_joints[i]); cmd_interfaces.emplace_back(acc_cmd_interfaces_.back()); - cmd_interfaces.back().set_value(INITIAL_ACC_JOINTS[i]); + cmd_interfaces.back().set_value(initial_acc_joints[i]); cmd_interfaces.emplace_back(eff_cmd_interfaces_.back()); - cmd_interfaces.back().set_value(INITIAL_EFF_JOINTS[i]); - joint_state_pos_[i] = initial_pos_joints[i]; - joint_state_vel_[i] = INITIAL_VEL_JOINTS[i]; - joint_state_acc_[i] = INITIAL_ACC_JOINTS[i]; + cmd_interfaces.back().set_value(initial_eff_joints[i]); + if (separate_cmd_and_state_values) + { + joint_state_pos_[i] = INITIAL_POS_JOINTS[i]; + joint_state_vel_[i] = INITIAL_VEL_JOINTS[i]; + joint_state_acc_[i] = INITIAL_ACC_JOINTS[i]; + } state_interfaces.emplace_back(pos_state_interfaces_.back()); state_interfaces.emplace_back(vel_state_interfaces_.back()); state_interfaces.emplace_back(acc_state_interfaces_.back()); @@ -489,27 +501,33 @@ class TrajectoryControllerTest : public ::testing::Test // --> set kp > 0.0 in test if (traj_controller_->has_velocity_command_interface()) { - EXPECT_TRUE(is_same_sign_or_zero(point.at(0) - joint_state_pos_[0], joint_vel_[0])) - << "current error: " << point.at(0) - joint_state_pos_[0] << ", velocity command is " - << joint_vel_[0]; - EXPECT_TRUE(is_same_sign_or_zero(point.at(1) - joint_state_pos_[1], joint_vel_[1])) - << "current error: " << point.at(1) - joint_state_pos_[1] << ", velocity command is " - << joint_vel_[1]; - EXPECT_TRUE(is_same_sign_or_zero(point.at(2) - joint_state_pos_[2], joint_vel_[2])) - << "current error: " << point.at(2) - joint_state_pos_[2] << ", velocity command is " - << joint_vel_[2]; + EXPECT_TRUE( + is_same_sign_or_zero(point.at(0) - pos_state_interfaces_[0].get_value(), joint_vel_[0])) + << "current error: " << point.at(0) - pos_state_interfaces_[0].get_value() + << ", velocity command is " << joint_vel_[0]; + EXPECT_TRUE( + is_same_sign_or_zero(point.at(1) - pos_state_interfaces_[1].get_value(), joint_vel_[1])) + << "current error: " << point.at(1) - pos_state_interfaces_[1].get_value() + << ", velocity command is " << joint_vel_[1]; + EXPECT_TRUE( + is_same_sign_or_zero(point.at(2) - pos_state_interfaces_[2].get_value(), joint_vel_[2])) + << "current error: " << point.at(2) - pos_state_interfaces_[2].get_value() + << ", velocity command is " << joint_vel_[2]; } if (traj_controller_->has_effort_command_interface()) { - EXPECT_TRUE(is_same_sign_or_zero(point.at(0) - joint_state_pos_[0], joint_eff_[0])) - << "current error: " << point.at(0) - joint_state_pos_[0] << ", effort command is " - << joint_eff_[0]; - EXPECT_TRUE(is_same_sign_or_zero(point.at(1) - joint_state_pos_[1], joint_eff_[1])) - << "current error: " << point.at(1) - joint_state_pos_[1] << ", effort command is " - << joint_eff_[1]; - EXPECT_TRUE(is_same_sign_or_zero(point.at(2) - joint_state_pos_[2], joint_eff_[2])) - << "current error: " << point.at(2) - joint_state_pos_[2] << ", effort command is " - << joint_eff_[2]; + EXPECT_TRUE( + is_same_sign_or_zero(point.at(0) - pos_state_interfaces_[0].get_value(), joint_eff_[0])) + << "current error: " << point.at(0) - pos_state_interfaces_[0].get_value() + << ", effort command is " << joint_eff_[0]; + EXPECT_TRUE( + is_same_sign_or_zero(point.at(1) - pos_state_interfaces_[1].get_value(), joint_eff_[1])) + << "current error: " << point.at(1) - pos_state_interfaces_[1].get_value() + << ", effort command is " << joint_eff_[1]; + EXPECT_TRUE( + is_same_sign_or_zero(point.at(2) - pos_state_interfaces_[2].get_value(), joint_eff_[2])) + << "current error: " << point.at(2) - pos_state_interfaces_[2].get_value() + << ", effort command is " << joint_eff_[2]; } } } From 3fc0f50c440ad49b2194b2c7dae8c54d6cda7b07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Wed, 15 Nov 2023 20:03:40 +0100 Subject: [PATCH 142/238] [JTC] Activate update of dynamic parameters (#761) --- .../joint_trajectory_controller.hpp | 2 + .../src/joint_trajectory_controller.cpp | 95 +++++++++++++------ .../test/test_trajectory_controller.cpp | 36 +++++++ .../test/test_trajectory_controller_utils.hpp | 2 + 4 files changed, 104 insertions(+), 31 deletions(-) diff --git a/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp b/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp index eaf821aa26..7542aa6951 100644 --- a/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp +++ b/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp @@ -277,6 +277,8 @@ class JointTrajectoryController : public controller_interface::ControllerInterfa std::shared_ptr response); private: + void update_pids(); + bool contains_interface_type( const std::vector & interface_type_list, const std::string & interface_type); diff --git a/joint_trajectory_controller/src/joint_trajectory_controller.cpp b/joint_trajectory_controller/src/joint_trajectory_controller.cpp index cf35156541..3936da155f 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller.cpp +++ b/joint_trajectory_controller/src/joint_trajectory_controller.cpp @@ -115,6 +115,17 @@ controller_interface::return_type JointTrajectoryController::update( { return controller_interface::return_type::OK; } + // update dynamic parameters + if (param_listener_->is_old(params_)) + { + params_ = param_listener_->get_params(); + // use_closed_loop_pid_adapter_ is updated in on_configure only + if (use_closed_loop_pid_adapter_) + { + update_pids(); + default_tolerances_ = get_segment_tolerances(params_); + } + } auto compute_error_for_joint = [&]( JointTrajectoryPoint & error, size_t index, @@ -704,15 +715,7 @@ controller_interface::CallbackReturn JointTrajectoryController::on_configure( ff_velocity_scale_.resize(dof_); tmp_command_.resize(dof_, 0.0); - // Init PID gains from ROS parameters - for (size_t i = 0; i < dof_; ++i) - { - const auto & gains = params_.gains.joints_map.at(params_.joints[i]); - pids_[i] = std::make_shared( - gains.p, gains.i, gains.d, gains.i_clamp, -gains.i_clamp); - - ff_velocity_scale_[i] = gains.ff_velocity_scale; - } + update_pids(); } // Configure joint position error normalization from ROS parameters (angle_wraparound) @@ -787,8 +790,7 @@ controller_interface::CallbackReturn JointTrajectoryController::on_configure( get_interface_list(params_.command_interfaces).c_str(), get_interface_list(params_.state_interfaces).c_str()); - default_tolerances_ = get_segment_tolerances(params_); - + // parse remaining parameters const std::string interpolation_string = get_node()->get_parameter("interpolation_method").as_string(); interpolation_method_ = interpolation_methods::from_string(interpolation_string); @@ -874,32 +876,21 @@ controller_interface::CallbackReturn JointTrajectoryController::on_configure( std::string(get_node()->get_name()) + "/query_state", std::bind(&JointTrajectoryController::query_state_service, this, _1, _2)); - if (params_.cmd_timeout > 0.0) - { - if (params_.cmd_timeout > default_tolerances_.goal_time_tolerance) - { - cmd_timeout_ = params_.cmd_timeout; - } - else - { - // deactivate timeout - RCLCPP_WARN( - logger, "Command timeout must be higher than goal_time tolerance (%f vs. %f)", - params_.cmd_timeout, default_tolerances_.goal_time_tolerance); - cmd_timeout_ = 0.0; - } - } - else - { - cmd_timeout_ = 0.0; - } - return CallbackReturn::SUCCESS; } controller_interface::CallbackReturn JointTrajectoryController::on_activate( const rclcpp_lifecycle::State &) { + // update the dynamic map parameters + param_listener_->refresh_dynamic_parameters(); + + // get parameters from the listener in case they were updated + params_ = param_listener_->get_params(); + + // parse remaining parameters + default_tolerances_ = get_segment_tolerances(params_); + // order all joints in the storage for (const auto & interface : params_.command_interfaces) { @@ -974,6 +965,28 @@ controller_interface::CallbackReturn JointTrajectoryController::on_activate( } rt_is_holding_.writeFromNonRT(true); + // parse timeout parameter + if (params_.cmd_timeout > 0.0) + { + if (params_.cmd_timeout > default_tolerances_.goal_time_tolerance) + { + cmd_timeout_ = params_.cmd_timeout; + } + else + { + // deactivate timeout + RCLCPP_WARN( + get_node()->get_logger(), + "Command timeout must be higher than goal_time tolerance (%f vs. %f)", params_.cmd_timeout, + default_tolerances_.goal_time_tolerance); + cmd_timeout_ = 0.0; + } + } + else + { + cmd_timeout_ = 0.0; + } + return CallbackReturn::SUCCESS; } @@ -1530,6 +1543,26 @@ bool JointTrajectoryController::has_active_trajectory() const return traj_external_point_ptr_ != nullptr && traj_external_point_ptr_->has_trajectory_msg(); } +void JointTrajectoryController::update_pids() +{ + for (size_t i = 0; i < dof_; ++i) + { + const auto & gains = params_.gains.joints_map.at(params_.joints[i]); + if (pids_[i]) + { + // update PIDs with gains from ROS parameters + pids_[i]->setGains(gains.p, gains.i, gains.d, gains.i_clamp, -gains.i_clamp); + } + else + { + // Init PIDs with gains from ROS parameters + pids_[i] = std::make_shared( + gains.p, gains.i, gains.d, gains.i_clamp, -gains.i_clamp); + } + ff_velocity_scale_[i] = gains.ff_velocity_scale; + } +} + void JointTrajectoryController::init_hold_position_msg() { hold_position_msg_ptr_ = std::make_shared(); diff --git a/joint_trajectory_controller/test/test_trajectory_controller.cpp b/joint_trajectory_controller/test/test_trajectory_controller.cpp index 117575be37..7842d50434 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller.cpp +++ b/joint_trajectory_controller/test/test_trajectory_controller.cpp @@ -413,6 +413,42 @@ TEST_P(TrajectoryControllerTestParameterized, state_topic_consistency) } } +/** + * @brief check if dynamic parameters are updated + */ +TEST_P(TrajectoryControllerTestParameterized, update_dynamic_parameters) +{ + rclcpp::executors::MultiThreadedExecutor executor; + + SetUpAndActivateTrajectoryController(executor); + + updateController(); + auto pids = traj_controller_->get_pids(); + + if (traj_controller_->use_closed_loop_pid_adapter()) + { + EXPECT_EQ(pids.size(), 3); + auto gain_0 = pids.at(0)->getGains(); + EXPECT_EQ(gain_0.p_gain_, 0.0); + + double kp = 1.0; + SetPidParameters(kp); + updateController(); + + pids = traj_controller_->get_pids(); + EXPECT_EQ(pids.size(), 3); + gain_0 = pids.at(0)->getGains(); + EXPECT_EQ(gain_0.p_gain_, kp); + } + else + { + // nothing to check here, skip further test + EXPECT_EQ(pids.size(), 0); + } + + executor.cancel(); +} + /** * @brief check if hold on startup is deactivated */ diff --git a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp index 7118882da1..224265ad83 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp +++ b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp @@ -130,6 +130,8 @@ class TestableJointTrajectoryController bool is_open_loop() const { return params_.open_loop_control; } + std::vector get_pids() const { return pids_; } + bool has_active_traj() const { return has_active_trajectory(); } bool has_trivial_traj() const From 0a9f4b0c2b10c926d6c283520d763eefed0f06b5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Nov 2023 23:17:20 +0000 Subject: [PATCH 143/238] Bump ros-tooling/action-ros-ci from 0.3.4 to 0.3.5 (#833) --- .github/workflows/ci-coverage-build-humble.yml | 2 +- .github/workflows/ci-coverage-build-iron.yml | 2 +- .github/workflows/ci-coverage-build.yml | 2 +- .github/workflows/reusable-ros-tooling-source-build.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-coverage-build-humble.yml b/.github/workflows/ci-coverage-build-humble.yml index 46922ccaac..76b2c22e53 100644 --- a/.github/workflows/ci-coverage-build-humble.yml +++ b/.github/workflows/ci-coverage-build-humble.yml @@ -21,7 +21,7 @@ jobs: with: required-ros-distributions: ${{ env.ROS_DISTRO }} - uses: actions/checkout@v4 - - uses: ros-tooling/action-ros-ci@0.3.4 + - uses: ros-tooling/action-ros-ci@0.3.5 with: target-ros2-distro: ${{ env.ROS_DISTRO }} import-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/ci-coverage-build-iron.yml b/.github/workflows/ci-coverage-build-iron.yml index 723654b33e..1aaf30c639 100644 --- a/.github/workflows/ci-coverage-build-iron.yml +++ b/.github/workflows/ci-coverage-build-iron.yml @@ -21,7 +21,7 @@ jobs: with: required-ros-distributions: ${{ env.ROS_DISTRO }} - uses: actions/checkout@v4 - - uses: ros-tooling/action-ros-ci@0.3.4 + - uses: ros-tooling/action-ros-ci@0.3.5 with: target-ros2-distro: ${{ env.ROS_DISTRO }} import-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/ci-coverage-build.yml b/.github/workflows/ci-coverage-build.yml index 6a932a2dcd..72aa9af66c 100644 --- a/.github/workflows/ci-coverage-build.yml +++ b/.github/workflows/ci-coverage-build.yml @@ -21,7 +21,7 @@ jobs: with: required-ros-distributions: ${{ env.ROS_DISTRO }} - uses: actions/checkout@v4 - - uses: ros-tooling/action-ros-ci@0.3.4 + - uses: ros-tooling/action-ros-ci@0.3.5 with: target-ros2-distro: ${{ env.ROS_DISTRO }} import-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/reusable-ros-tooling-source-build.yml b/.github/workflows/reusable-ros-tooling-source-build.yml index a444a7f645..6b1af2b86c 100644 --- a/.github/workflows/reusable-ros-tooling-source-build.yml +++ b/.github/workflows/reusable-ros-tooling-source-build.yml @@ -32,7 +32,7 @@ jobs: - uses: actions/checkout@v4 with: ref: ${{ inputs.ref }} - - uses: ros-tooling/action-ros-ci@0.3.4 + - uses: ros-tooling/action-ros-ci@0.3.5 with: target-ros2-distro: ${{ inputs.ros_distro }} ref: ${{ inputs.ref }} From 25f2a14757e5624eabfd5804fb64b42100e72b52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Sun, 19 Nov 2023 15:31:39 +0100 Subject: [PATCH 144/238] Resort overview page (#846) --- README.md | 2 +- doc/controllers_index.rst | 55 ++++++++++++---------- forward_command_controller/doc/userdoc.rst | 2 +- 3 files changed, 32 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index d41ec09b6c..4183b38fdc 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![Licence](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![codecov](https://codecov.io/gh/ros-controls/ros2_controllers/graph/badge.svg?token=KSdY0tsHm6)](https://codecov.io/gh/ros-controls/ros2_controllers) -Commonly used and generalized controllers for ros2-control framework that are ready to use with many robots, MoveIt2 and Navigation2. +Commonly used and generalized controllers for ros2-control framework that are ready to use with many robots, MoveIt2 and Nav2. ## Build status diff --git a/doc/controllers_index.rst b/doc/controllers_index.rst index de33c3284c..9fceb90fd3 100644 --- a/doc/controllers_index.rst +++ b/doc/controllers_index.rst @@ -6,24 +6,9 @@ ros2_controllers ################# -`GitHub Repository `_ - - -Nomenclature -************ - -The ros2_control framework uses namespaces to sort controller according to the type of command interface they are using. -The controllers are using `common hardware interface definitions`_. -The controllers' namespaces are commanding the following command interface types: - - - ``position_controllers``: ``hardware_interface::HW_IF_POSITION`` - - ``velocity_controller``: ``hardware_interface::HW_IF_VELOCITY`` - - ``effort_controllers``: ``hardware_interface::HW_IF_ACCELERATION`` - - ``effort_controllers``: ``hardware_interface::HW_IF_EFFORT`` - - ... - -.. _common hardware interface definitions: https://github.com/ros-controls/ros2_control/blob/{REPOS_FILE_BRANCH}/hardware_interface/include/hardware_interface/types/hardware_interface_type_values.hpp +Commonly used and generalized controllers for ros2_control framework that are ready to use with many robots, `MoveIt2 `_ and `Nav2 `_. +`Link to GitHub Repository `_ Guidelines and Best Practices @@ -36,34 +21,54 @@ Guidelines and Best Practices * -Available Controllers -********************* +Controllers for Mobile Robots +***************************** .. toctree:: :titlesonly: Ackermann Steering Controller <../ackermann_steering_controller/doc/userdoc.rst> - Admittance Controller <../admittance_controller/doc/userdoc.rst> Bicycle Steering Controller <../bicycle_steering_controller/doc/userdoc.rst> Differential Drive Controller <../diff_drive_controller/doc/userdoc.rst> + Steering Controllers Library <../steering_controllers_library/doc/userdoc.rst> + Tricycle Controller <../tricycle_controller/doc/userdoc.rst> + Tricycle Steering Controller <../tricycle_steering_controller/doc/userdoc.rst> + +Controllers for Manipulators and Other Robots +********************************************* + +The controllers are using `common hardware interface definitions`_, and may use namespaces depending on the following command interface types: + + - ``position_controllers``: ``hardware_interface::HW_IF_POSITION`` + - ``velocity_controller``: ``hardware_interface::HW_IF_VELOCITY`` + - ``effort_controllers``: ``hardware_interface::HW_IF_ACCELERATION`` + - ``effort_controllers``: ``hardware_interface::HW_IF_EFFORT`` + +.. _common hardware interface definitions: https://github.com/ros-controls/ros2_control/blob/{REPOS_FILE_BRANCH}/hardware_interface/include/hardware_interface/types/hardware_interface_type_values.hpp + + +.. toctree:: + :titlesonly: + + Admittance Controller <../admittance_controller/doc/userdoc.rst> Effort Controllers <../effort_controllers/doc/userdoc.rst> Forward Command Controller <../forward_command_controller/doc/userdoc.rst> Gripper Controller <../gripper_controllers/doc/userdoc.rst> Joint Trajectory Controller <../joint_trajectory_controller/doc/userdoc.rst> Position Controllers <../position_controllers/doc/userdoc.rst> - Steering Controllers Library <../steering_controllers_library/doc/userdoc.rst> - Tricycle Controller <../tricycle_controller/doc/userdoc.rst> - Tricycle Steering Controller <../tricycle_steering_controller/doc/userdoc.rst> Velocity Controllers <../velocity_controllers/doc/userdoc.rst> -Available Broadcasters +Broadcasters ********************** +Broadcasters are used to publish sensor data from hardware components to ROS topics. +In the sense of ros2_control, broadcasters are still controllers using the same controller interface as the other controllers above. + .. toctree:: :titlesonly: Force Torque Sensor Broadcaster <../force_torque_sensor_broadcaster/doc/userdoc.rst> - Imu Sensor Broadcaster <../imu_sensor_broadcaster/doc/userdoc.rst> + IMU Sensor Broadcaster <../imu_sensor_broadcaster/doc/userdoc.rst> Joint State Broadcaster <../joint_state_broadcaster/doc/userdoc.rst> Range Sensor Broadcaster <../range_sensor_broadcaster/doc/userdoc.rst> diff --git a/forward_command_controller/doc/userdoc.rst b/forward_command_controller/doc/userdoc.rst index 01aa2492a8..cd623a5acb 100644 --- a/forward_command_controller/doc/userdoc.rst +++ b/forward_command_controller/doc/userdoc.rst @@ -5,7 +5,7 @@ forward_command_controller ========================== -This is a base class implementing a feedforward controller. Specific implementations can be found in: +This is a base class implementing a feedforward controller. Specific implementations of this base class can be found in: * :ref:`position_controllers_userdoc` * :ref:`velocity_controllers_userdoc` From 41610fdf43b9875f079aa5933b3f95e9687e524d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Sun, 19 Nov 2023 20:17:24 +0100 Subject: [PATCH 145/238] [JTC] Remove unused home pose (#845) --- .../joint_trajectory_controller.hpp | 2 -- .../src/joint_trajectory_controller.cpp | 28 ------------------- 2 files changed, 30 deletions(-) diff --git a/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp b/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp index 7542aa6951..397ccf347c 100644 --- a/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp +++ b/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp @@ -184,8 +184,6 @@ class JointTrajectoryController : public controller_interface::ControllerInterfa rclcpp::Service::SharedPtr query_state_srv_; std::shared_ptr traj_external_point_ptr_ = nullptr; - std::shared_ptr traj_home_point_ptr_ = nullptr; - std::shared_ptr traj_msg_home_ptr_ = nullptr; realtime_tools::RealtimeBuffer> traj_msg_external_point_ptr_; diff --git a/joint_trajectory_controller/src/joint_trajectory_controller.cpp b/joint_trajectory_controller/src/joint_trajectory_controller.cpp index 3936da155f..18f61f0e49 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller.cpp +++ b/joint_trajectory_controller/src/joint_trajectory_controller.cpp @@ -921,22 +921,7 @@ controller_interface::CallbackReturn JointTrajectoryController::on_activate( } } - // Store 'home' pose - traj_msg_home_ptr_ = std::make_shared(); - traj_msg_home_ptr_->header.stamp.sec = 0; - traj_msg_home_ptr_->header.stamp.nanosec = 0; - traj_msg_home_ptr_->points.resize(1); - traj_msg_home_ptr_->points[0].time_from_start.sec = 0; - traj_msg_home_ptr_->points[0].time_from_start.nanosec = 50000000; - traj_msg_home_ptr_->points[0].positions.resize(joint_state_interface_[0].size()); - for (size_t index = 0; index < joint_state_interface_[0].size(); ++index) - { - traj_msg_home_ptr_->points[0].positions[index] = - joint_state_interface_[0][index].get().get_value(); - } - traj_external_point_ptr_ = std::make_shared(); - traj_home_point_ptr_ = std::make_shared(); traj_msg_external_point_ptr_.writeFromNonRT( std::shared_ptr()); @@ -1028,8 +1013,6 @@ controller_interface::CallbackReturn JointTrajectoryController::on_deactivate( subscriber_is_active_ = false; traj_external_point_ptr_.reset(); - traj_home_point_ptr_.reset(); - traj_msg_home_ptr_.reset(); return CallbackReturn::SUCCESS; } @@ -1037,13 +1020,6 @@ controller_interface::CallbackReturn JointTrajectoryController::on_deactivate( controller_interface::CallbackReturn JointTrajectoryController::on_cleanup( const rclcpp_lifecycle::State &) { - // go home - if (traj_home_point_ptr_ != nullptr) - { - traj_home_point_ptr_->update(traj_msg_home_ptr_); - traj_external_point_ptr_ = traj_home_point_ptr_; - } - return CallbackReturn::SUCCESS; } @@ -1070,11 +1046,7 @@ bool JointTrajectoryController::reset() } } - // iterator has no default value - // prev_traj_point_ptr_; traj_external_point_ptr_.reset(); - traj_home_point_ptr_.reset(); - traj_msg_home_ptr_.reset(); return true; } From d9a6bb43e312d8d74e52eddfb700e5249c18f4f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Sun, 19 Nov 2023 20:18:46 +0100 Subject: [PATCH 146/238] [JTC] Fix dynamic reconfigure of tolerances (#849) * Fix dynamic reconfigure of tolerances * Fix static cast syntax --- .../src/joint_trajectory_controller.cpp | 5 +- .../test/test_trajectory_controller.cpp | 53 +++++++++++++++++++ .../test/test_trajectory_controller_utils.hpp | 5 ++ 3 files changed, 61 insertions(+), 2 deletions(-) diff --git a/joint_trajectory_controller/src/joint_trajectory_controller.cpp b/joint_trajectory_controller/src/joint_trajectory_controller.cpp index 18f61f0e49..dae7f13148 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller.cpp +++ b/joint_trajectory_controller/src/joint_trajectory_controller.cpp @@ -119,11 +119,12 @@ controller_interface::return_type JointTrajectoryController::update( if (param_listener_->is_old(params_)) { params_ = param_listener_->get_params(); - // use_closed_loop_pid_adapter_ is updated in on_configure only + default_tolerances_ = get_segment_tolerances(params_); + // update the PID gains + // variable use_closed_loop_pid_adapter_ is updated in on_configure only if (use_closed_loop_pid_adapter_) { update_pids(); - default_tolerances_ = get_segment_tolerances(params_); } } diff --git a/joint_trajectory_controller/test/test_trajectory_controller.cpp b/joint_trajectory_controller/test/test_trajectory_controller.cpp index 7842d50434..8b29c2cb16 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller.cpp +++ b/joint_trajectory_controller/test/test_trajectory_controller.cpp @@ -449,6 +449,59 @@ TEST_P(TrajectoryControllerTestParameterized, update_dynamic_parameters) executor.cancel(); } +/** + * @brief check if dynamic tolerances are updated + */ +TEST_P(TrajectoryControllerTestParameterized, update_dynamic_tolerances) +{ + rclcpp::executors::MultiThreadedExecutor executor; + + SetUpAndActivateTrajectoryController(executor); + + updateController(); + + // test default parameters + { + auto tols = traj_controller_->get_tolerances(); + EXPECT_EQ(tols.goal_time_tolerance, 0.0); + for (size_t i = 0; i < joint_names_.size(); ++i) + { + EXPECT_EQ(tols.state_tolerance.at(i).position, 0.0); + EXPECT_EQ(tols.goal_state_tolerance.at(i).position, 0.0); + EXPECT_EQ(tols.goal_state_tolerance.at(i).velocity, 0.01); + } + } + + // change parameters, update and see what happens + std::vector new_tolerances{ + rclcpp::Parameter("constraints.goal_time", 1.0), + rclcpp::Parameter("constraints.stopped_velocity_tolerance", 0.02), + rclcpp::Parameter("constraints.joint1.trajectory", 1.0), + rclcpp::Parameter("constraints.joint2.trajectory", 2.0), + rclcpp::Parameter("constraints.joint3.trajectory", 3.0), + rclcpp::Parameter("constraints.joint1.goal", 10.0), + rclcpp::Parameter("constraints.joint2.goal", 20.0), + rclcpp::Parameter("constraints.joint3.goal", 30.0)}; + for (const auto & param : new_tolerances) + { + traj_controller_->get_node()->set_parameter(param); + } + updateController(); + + { + auto tols = traj_controller_->get_tolerances(); + EXPECT_EQ(tols.goal_time_tolerance, 1.0); + for (size_t i = 0; i < joint_names_.size(); ++i) + { + EXPECT_EQ(tols.state_tolerance.at(i).position, static_cast(i) + 1.0); + EXPECT_EQ(tols.goal_state_tolerance.at(i).position, 10.0 * (static_cast(i) + 1.0)); + EXPECT_EQ(tols.goal_state_tolerance.at(i).velocity, 0.02); + } + } + + executor.cancel(); +} + /** * @brief check if hold on startup is deactivated */ diff --git a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp index 224265ad83..fdf4305cec 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp +++ b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp @@ -132,6 +132,11 @@ class TestableJointTrajectoryController std::vector get_pids() const { return pids_; } + joint_trajectory_controller::SegmentTolerances get_tolerances() const + { + return default_tolerances_; + } + bool has_active_traj() const { return has_active_trajectory(); } bool has_trivial_traj() const From 6d4fb2d9c5dc44751a19b277054ffb570406eebc Mon Sep 17 00:00:00 2001 From: Sai Kishor Kothakota Date: Mon, 20 Nov 2023 22:33:01 +0100 Subject: [PATCH 147/238] fix tests for API break of passing controller manager update rate in init method (#854) --- .../test_ackermann_steering_controller.hpp | 2 +- .../test/test_admittance_controller.hpp | 2 +- .../test/test_bicycle_steering_controller.hpp | 2 +- .../test/test_diff_drive_controller.cpp | 34 +++++++++---------- .../test_joint_group_effort_controller.cpp | 2 +- .../test_force_torque_sensor_broadcaster.cpp | 2 +- .../test/test_forward_command_controller.cpp | 2 +- ...i_interface_forward_command_controller.cpp | 2 +- .../test/test_gripper_controllers.cpp | 2 +- .../test/test_imu_sensor_broadcaster.cpp | 2 +- .../test/test_joint_state_broadcaster.cpp | 2 +- .../test/test_trajectory_controller_utils.hpp | 2 +- .../test_joint_group_position_controller.cpp | 2 +- .../test/test_range_sensor_broadcaster.cpp | 2 +- .../test_steering_controllers_library.hpp | 2 +- .../test/test_tricycle_controller.cpp | 14 ++++---- .../test_tricycle_steering_controller.hpp | 2 +- .../test_joint_group_velocity_controller.cpp | 2 +- 18 files changed, 40 insertions(+), 40 deletions(-) diff --git a/ackermann_steering_controller/test/test_ackermann_steering_controller.hpp b/ackermann_steering_controller/test/test_ackermann_steering_controller.hpp index 8af2f6bc94..a2849d5742 100644 --- a/ackermann_steering_controller/test/test_ackermann_steering_controller.hpp +++ b/ackermann_steering_controller/test/test_ackermann_steering_controller.hpp @@ -147,7 +147,7 @@ class AckermannSteeringControllerFixture : public ::testing::Test protected: void SetUpController(const std::string controller_name = "test_ackermann_steering_controller") { - ASSERT_EQ(controller_->init(controller_name, ""), controller_interface::return_type::OK); + ASSERT_EQ(controller_->init(controller_name, "", 0), controller_interface::return_type::OK); if (position_feedback_ == true) { diff --git a/admittance_controller/test/test_admittance_controller.hpp b/admittance_controller/test/test_admittance_controller.hpp index db708db6c5..19908d7f9f 100644 --- a/admittance_controller/test/test_admittance_controller.hpp +++ b/admittance_controller/test/test_admittance_controller.hpp @@ -185,7 +185,7 @@ class AdmittanceControllerTest : public ::testing::Test controller_interface::return_type SetUpControllerCommon( const std::string & controller_name, const rclcpp::NodeOptions & options) { - auto result = controller_->init(controller_name, "", "", options); + auto result = controller_->init(controller_name, "", 0, "", options); controller_->export_reference_interfaces(); assign_interfaces(); diff --git a/bicycle_steering_controller/test/test_bicycle_steering_controller.hpp b/bicycle_steering_controller/test/test_bicycle_steering_controller.hpp index 34d6883a83..521506762b 100644 --- a/bicycle_steering_controller/test/test_bicycle_steering_controller.hpp +++ b/bicycle_steering_controller/test/test_bicycle_steering_controller.hpp @@ -144,7 +144,7 @@ class BicycleSteeringControllerFixture : public ::testing::Test protected: void SetUpController(const std::string controller_name = "test_bicycle_steering_controller") { - ASSERT_EQ(controller_->init(controller_name, ""), controller_interface::return_type::OK); + ASSERT_EQ(controller_->init(controller_name, "", 0), controller_interface::return_type::OK); if (position_feedback_ == true) { diff --git a/diff_drive_controller/test/test_diff_drive_controller.cpp b/diff_drive_controller/test/test_diff_drive_controller.cpp index 505aa44d2b..eb970d34a3 100644 --- a/diff_drive_controller/test/test_diff_drive_controller.cpp +++ b/diff_drive_controller/test/test_diff_drive_controller.cpp @@ -195,7 +195,7 @@ class TestDiffDriveController : public ::testing::Test TEST_F(TestDiffDriveController, configure_fails_without_parameters) { - const auto ret = controller_->init(controller_name, urdf_); + const auto ret = controller_->init(controller_name, urdf_, 0); ASSERT_EQ(ret, controller_interface::return_type::OK); ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), CallbackReturn::ERROR); @@ -203,7 +203,7 @@ TEST_F(TestDiffDriveController, configure_fails_without_parameters) TEST_F(TestDiffDriveController, configure_fails_with_only_left_or_only_right_side_defined) { - const auto ret = controller_->init(controller_name, urdf_); + const auto ret = controller_->init(controller_name, urdf_, 0); ASSERT_EQ(ret, controller_interface::return_type::OK); controller_->get_node()->set_parameter( @@ -223,7 +223,7 @@ TEST_F(TestDiffDriveController, configure_fails_with_only_left_or_only_right_sid TEST_F(TestDiffDriveController, configure_fails_with_mismatching_wheel_side_size) { - const auto ret = controller_->init(controller_name, urdf_); + const auto ret = controller_->init(controller_name, urdf_, 0); ASSERT_EQ(ret, controller_interface::return_type::OK); controller_->get_node()->set_parameter( @@ -239,7 +239,7 @@ TEST_F(TestDiffDriveController, configure_fails_with_mismatching_wheel_side_size TEST_F(TestDiffDriveController, configure_succeeds_when_wheels_are_specified) { - const auto ret = controller_->init(controller_name, urdf_); + const auto ret = controller_->init(controller_name, urdf_, 0); ASSERT_EQ(ret, controller_interface::return_type::OK); controller_->get_node()->set_parameter( @@ -259,7 +259,7 @@ TEST_F(TestDiffDriveController, configure_succeeds_when_wheels_are_specified) TEST_F(TestDiffDriveController, configure_succeeds_tf_test_prefix_false_no_namespace) { - const auto ret = controller_->init(controller_name, urdf_); + const auto ret = controller_->init(controller_name, urdf_, 0); ASSERT_EQ(ret, controller_interface::return_type::OK); std::string odom_id = "odom"; @@ -292,7 +292,7 @@ TEST_F(TestDiffDriveController, configure_succeeds_tf_test_prefix_false_no_names TEST_F(TestDiffDriveController, configure_succeeds_tf_test_prefix_true_no_namespace) { - const auto ret = controller_->init(controller_name, urdf_); + const auto ret = controller_->init(controller_name, urdf_, 0); ASSERT_EQ(ret, controller_interface::return_type::OK); std::string odom_id = "odom"; @@ -327,7 +327,7 @@ TEST_F(TestDiffDriveController, configure_succeeds_tf_test_prefix_true_no_namesp TEST_F(TestDiffDriveController, configure_succeeds_tf_blank_prefix_true_no_namespace) { - const auto ret = controller_->init(controller_name, urdf_); + const auto ret = controller_->init(controller_name, urdf_, 0); ASSERT_EQ(ret, controller_interface::return_type::OK); std::string odom_id = "odom"; @@ -363,7 +363,7 @@ TEST_F(TestDiffDriveController, configure_succeeds_tf_test_prefix_false_set_name { std::string test_namespace = "/test_namespace"; - const auto ret = controller_->init(controller_name, urdf_, test_namespace); + const auto ret = controller_->init(controller_name, urdf_, 0, test_namespace); ASSERT_EQ(ret, controller_interface::return_type::OK); std::string odom_id = "odom"; @@ -398,7 +398,7 @@ TEST_F(TestDiffDriveController, configure_succeeds_tf_test_prefix_true_set_names { std::string test_namespace = "/test_namespace"; - const auto ret = controller_->init(controller_name, urdf_, test_namespace); + const auto ret = controller_->init(controller_name, urdf_, 0, test_namespace); ASSERT_EQ(ret, controller_interface::return_type::OK); std::string odom_id = "odom"; @@ -435,7 +435,7 @@ TEST_F(TestDiffDriveController, configure_succeeds_tf_blank_prefix_true_set_name { std::string test_namespace = "/test_namespace"; - const auto ret = controller_->init(controller_name, urdf_, test_namespace); + const auto ret = controller_->init(controller_name, urdf_, 0, test_namespace); ASSERT_EQ(ret, controller_interface::return_type::OK); std::string odom_id = "odom"; @@ -469,7 +469,7 @@ TEST_F(TestDiffDriveController, configure_succeeds_tf_blank_prefix_true_set_name TEST_F(TestDiffDriveController, activate_fails_without_resources_assigned) { - const auto ret = controller_->init(controller_name, urdf_); + const auto ret = controller_->init(controller_name, urdf_, 0); ASSERT_EQ(ret, controller_interface::return_type::OK); controller_->get_node()->set_parameter( @@ -483,7 +483,7 @@ TEST_F(TestDiffDriveController, activate_fails_without_resources_assigned) TEST_F(TestDiffDriveController, activate_succeeds_with_pos_resources_assigned) { - const auto ret = controller_->init(controller_name, urdf_); + const auto ret = controller_->init(controller_name, urdf_, 0); ASSERT_EQ(ret, controller_interface::return_type::OK); // We implicitly test that by default position feedback is required @@ -499,7 +499,7 @@ TEST_F(TestDiffDriveController, activate_succeeds_with_pos_resources_assigned) TEST_F(TestDiffDriveController, activate_succeeds_with_vel_resources_assigned) { - const auto ret = controller_->init(controller_name, urdf_); + const auto ret = controller_->init(controller_name, urdf_, 0); ASSERT_EQ(ret, controller_interface::return_type::OK); controller_->get_node()->set_parameter( @@ -516,7 +516,7 @@ TEST_F(TestDiffDriveController, activate_succeeds_with_vel_resources_assigned) TEST_F(TestDiffDriveController, activate_fails_with_wrong_resources_assigned_1) { - const auto ret = controller_->init(controller_name, urdf_); + const auto ret = controller_->init(controller_name, urdf_, 0); ASSERT_EQ(ret, controller_interface::return_type::OK); controller_->get_node()->set_parameter( @@ -533,7 +533,7 @@ TEST_F(TestDiffDriveController, activate_fails_with_wrong_resources_assigned_1) TEST_F(TestDiffDriveController, activate_fails_with_wrong_resources_assigned_2) { - const auto ret = controller_->init(controller_name, urdf_); + const auto ret = controller_->init(controller_name, urdf_, 0); ASSERT_EQ(ret, controller_interface::return_type::OK); controller_->get_node()->set_parameter( @@ -550,7 +550,7 @@ TEST_F(TestDiffDriveController, activate_fails_with_wrong_resources_assigned_2) TEST_F(TestDiffDriveController, cleanup) { - const auto ret = controller_->init(controller_name, urdf_); + const auto ret = controller_->init(controller_name, urdf_, 0); ASSERT_EQ(ret, controller_interface::return_type::OK); controller_->get_node()->set_parameter( @@ -599,7 +599,7 @@ TEST_F(TestDiffDriveController, cleanup) TEST_F(TestDiffDriveController, correct_initialization_using_parameters) { - const auto ret = controller_->init(controller_name, urdf_); + const auto ret = controller_->init(controller_name, urdf_, 0); ASSERT_EQ(ret, controller_interface::return_type::OK); controller_->get_node()->set_parameter( diff --git a/effort_controllers/test/test_joint_group_effort_controller.cpp b/effort_controllers/test/test_joint_group_effort_controller.cpp index 23555c578f..f9d72ab202 100644 --- a/effort_controllers/test/test_joint_group_effort_controller.cpp +++ b/effort_controllers/test/test_joint_group_effort_controller.cpp @@ -54,7 +54,7 @@ void JointGroupEffortControllerTest::TearDown() { controller_.reset(nullptr); } void JointGroupEffortControllerTest::SetUpController() { - const auto result = controller_->init("test_joint_group_effort_controller", ""); + const auto result = controller_->init("test_joint_group_effort_controller", "", 0); ASSERT_EQ(result, controller_interface::return_type::OK); std::vector command_ifs; diff --git a/force_torque_sensor_broadcaster/test/test_force_torque_sensor_broadcaster.cpp b/force_torque_sensor_broadcaster/test/test_force_torque_sensor_broadcaster.cpp index 82f677410e..bfe7561642 100644 --- a/force_torque_sensor_broadcaster/test/test_force_torque_sensor_broadcaster.cpp +++ b/force_torque_sensor_broadcaster/test/test_force_torque_sensor_broadcaster.cpp @@ -53,7 +53,7 @@ void ForceTorqueSensorBroadcasterTest::TearDown() { fts_broadcaster_.reset(nullp void ForceTorqueSensorBroadcasterTest::SetUpFTSBroadcaster() { - const auto result = fts_broadcaster_->init("test_force_torque_sensor_broadcaster", ""); + const auto result = fts_broadcaster_->init("test_force_torque_sensor_broadcaster", "", 0); ASSERT_EQ(result, controller_interface::return_type::OK); std::vector state_ifs; diff --git a/forward_command_controller/test/test_forward_command_controller.cpp b/forward_command_controller/test/test_forward_command_controller.cpp index 2ab507ef29..62d5512b4e 100644 --- a/forward_command_controller/test/test_forward_command_controller.cpp +++ b/forward_command_controller/test/test_forward_command_controller.cpp @@ -60,7 +60,7 @@ void ForwardCommandControllerTest::TearDown() { controller_.reset(nullptr); } void ForwardCommandControllerTest::SetUpController() { - const auto result = controller_->init("forward_command_controller", ""); + const auto result = controller_->init("forward_command_controller", "", 0); ASSERT_EQ(result, controller_interface::return_type::OK); std::vector command_ifs; diff --git a/forward_command_controller/test/test_multi_interface_forward_command_controller.cpp b/forward_command_controller/test/test_multi_interface_forward_command_controller.cpp index 00ca4ae2d1..7826c85355 100644 --- a/forward_command_controller/test/test_multi_interface_forward_command_controller.cpp +++ b/forward_command_controller/test/test_multi_interface_forward_command_controller.cpp @@ -62,7 +62,7 @@ void MultiInterfaceForwardCommandControllerTest::TearDown() { controller_.reset( void MultiInterfaceForwardCommandControllerTest::SetUpController(bool set_params_and_activate) { - const auto result = controller_->init("multi_interface_forward_command_controller", ""); + const auto result = controller_->init("multi_interface_forward_command_controller", "", 0); ASSERT_EQ(result, controller_interface::return_type::OK); std::vector command_ifs; diff --git a/gripper_controllers/test/test_gripper_controllers.cpp b/gripper_controllers/test/test_gripper_controllers.cpp index 572e755743..0fc10c0c73 100644 --- a/gripper_controllers/test/test_gripper_controllers.cpp +++ b/gripper_controllers/test/test_gripper_controllers.cpp @@ -60,7 +60,7 @@ void GripperControllerTest::TearDown() template void GripperControllerTest::SetUpController() { - const auto result = controller_->init("gripper_controller", ""); + const auto result = controller_->init("gripper_controller", "", 0); ASSERT_EQ(result, controller_interface::return_type::OK); std::vector command_ifs; diff --git a/imu_sensor_broadcaster/test/test_imu_sensor_broadcaster.cpp b/imu_sensor_broadcaster/test/test_imu_sensor_broadcaster.cpp index 0b782efc5f..0fb987ce77 100644 --- a/imu_sensor_broadcaster/test/test_imu_sensor_broadcaster.cpp +++ b/imu_sensor_broadcaster/test/test_imu_sensor_broadcaster.cpp @@ -53,7 +53,7 @@ void IMUSensorBroadcasterTest::TearDown() { imu_broadcaster_.reset(nullptr); } void IMUSensorBroadcasterTest::SetUpIMUBroadcaster() { - const auto result = imu_broadcaster_->init("test_imu_sensor_broadcaster", ""); + const auto result = imu_broadcaster_->init("test_imu_sensor_broadcaster", "", 0); ASSERT_EQ(result, controller_interface::return_type::OK); std::vector state_ifs; diff --git a/joint_state_broadcaster/test/test_joint_state_broadcaster.cpp b/joint_state_broadcaster/test/test_joint_state_broadcaster.cpp index a6c0708fd9..3a74f599b4 100644 --- a/joint_state_broadcaster/test/test_joint_state_broadcaster.cpp +++ b/joint_state_broadcaster/test/test_joint_state_broadcaster.cpp @@ -69,7 +69,7 @@ void JointStateBroadcasterTest::SetUpStateBroadcaster( void JointStateBroadcasterTest::init_broadcaster_and_set_parameters( const std::vector & joint_names, const std::vector & interfaces) { - const auto result = state_broadcaster_->init("joint_state_broadcaster", ""); + const auto result = state_broadcaster_->init("joint_state_broadcaster", "", 0); ASSERT_EQ(result, controller_interface::return_type::OK); state_broadcaster_->get_node()->set_parameter({"joints", joint_names}); diff --git a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp index fdf4305cec..3a7e7e5cf1 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp +++ b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp @@ -196,7 +196,7 @@ class TrajectoryControllerTest : public ::testing::Test parameter_overrides.insert(parameter_overrides.end(), parameters.begin(), parameters.end()); node_options.parameter_overrides(parameter_overrides); - auto ret = traj_controller_->init(controller_name_, "", "", node_options); + auto ret = traj_controller_->init(controller_name_, "", 0, "", node_options); if (ret != controller_interface::return_type::OK) { FAIL(); diff --git a/position_controllers/test/test_joint_group_position_controller.cpp b/position_controllers/test/test_joint_group_position_controller.cpp index 07f42e4eba..3b4f00be12 100644 --- a/position_controllers/test/test_joint_group_position_controller.cpp +++ b/position_controllers/test/test_joint_group_position_controller.cpp @@ -54,7 +54,7 @@ void JointGroupPositionControllerTest::TearDown() { controller_.reset(nullptr); void JointGroupPositionControllerTest::SetUpController() { - const auto result = controller_->init("test_joint_group_position_controller", ""); + const auto result = controller_->init("test_joint_group_position_controller", "", 0); ASSERT_EQ(result, controller_interface::return_type::OK); std::vector command_ifs; diff --git a/range_sensor_broadcaster/test/test_range_sensor_broadcaster.cpp b/range_sensor_broadcaster/test/test_range_sensor_broadcaster.cpp index ab937146cb..a857141ea9 100644 --- a/range_sensor_broadcaster/test/test_range_sensor_broadcaster.cpp +++ b/range_sensor_broadcaster/test/test_range_sensor_broadcaster.cpp @@ -34,7 +34,7 @@ controller_interface::return_type RangeSensorBroadcasterTest::init_broadcaster( std::string broadcaster_name) { controller_interface::return_type result = controller_interface::return_type::ERROR; - result = range_broadcaster_->init(broadcaster_name, ""); + result = range_broadcaster_->init(broadcaster_name, "", 0); if (controller_interface::return_type::OK == result) { diff --git a/steering_controllers_library/test/test_steering_controllers_library.hpp b/steering_controllers_library/test/test_steering_controllers_library.hpp index 226d4f4291..5caf347ac1 100644 --- a/steering_controllers_library/test/test_steering_controllers_library.hpp +++ b/steering_controllers_library/test/test_steering_controllers_library.hpp @@ -168,7 +168,7 @@ class SteeringControllersLibraryFixture : public ::testing::Test protected: void SetUpController(const std::string controller_name = "test_steering_controllers_library") { - ASSERT_EQ(controller_->init(controller_name, ""), controller_interface::return_type::OK); + ASSERT_EQ(controller_->init(controller_name, "", 0), controller_interface::return_type::OK); if (position_feedback_ == true) { diff --git a/tricycle_controller/test/test_tricycle_controller.cpp b/tricycle_controller/test/test_tricycle_controller.cpp index 054fff10ce..504ca381ce 100644 --- a/tricycle_controller/test/test_tricycle_controller.cpp +++ b/tricycle_controller/test/test_tricycle_controller.cpp @@ -173,14 +173,14 @@ class TestTricycleController : public ::testing::Test TEST_F(TestTricycleController, configure_fails_without_parameters) { - const auto ret = controller_->init(controller_name, urdf_); + const auto ret = controller_->init(controller_name, urdf_, 0); ASSERT_EQ(ret, controller_interface::return_type::OK); ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), CallbackReturn::ERROR); } TEST_F(TestTricycleController, configure_fails_if_only_traction_or_steering_side_defined) { - const auto ret = controller_->init(controller_name, urdf_); + const auto ret = controller_->init(controller_name, urdf_, 0); ASSERT_EQ(ret, controller_interface::return_type::OK); controller_->get_node()->set_parameter( @@ -200,7 +200,7 @@ TEST_F(TestTricycleController, configure_fails_if_only_traction_or_steering_side TEST_F(TestTricycleController, configure_succeeds_when_joints_are_specified) { - const auto ret = controller_->init(controller_name, urdf_); + const auto ret = controller_->init(controller_name, urdf_, 0); ASSERT_EQ(ret, controller_interface::return_type::OK); controller_->get_node()->set_parameter( @@ -213,7 +213,7 @@ TEST_F(TestTricycleController, configure_succeeds_when_joints_are_specified) TEST_F(TestTricycleController, activate_fails_without_resources_assigned) { - const auto ret = controller_->init(controller_name, urdf_); + const auto ret = controller_->init(controller_name, urdf_, 0); ASSERT_EQ(ret, controller_interface::return_type::OK); controller_->get_node()->set_parameter( @@ -227,7 +227,7 @@ TEST_F(TestTricycleController, activate_fails_without_resources_assigned) TEST_F(TestTricycleController, activate_succeeds_with_resources_assigned) { - const auto ret = controller_->init(controller_name, urdf_); + const auto ret = controller_->init(controller_name, urdf_, 0); ASSERT_EQ(ret, controller_interface::return_type::OK); // We implicitly test that by default position feedback is required @@ -243,7 +243,7 @@ TEST_F(TestTricycleController, activate_succeeds_with_resources_assigned) TEST_F(TestTricycleController, cleanup) { - const auto ret = controller_->init(controller_name, urdf_); + const auto ret = controller_->init(controller_name, urdf_, 0); ASSERT_EQ(ret, controller_interface::return_type::OK); controller_->get_node()->set_parameter( @@ -292,7 +292,7 @@ TEST_F(TestTricycleController, cleanup) TEST_F(TestTricycleController, correct_initialization_using_parameters) { - const auto ret = controller_->init(controller_name, urdf_); + const auto ret = controller_->init(controller_name, urdf_, 0); ASSERT_EQ(ret, controller_interface::return_type::OK); controller_->get_node()->set_parameter( diff --git a/tricycle_steering_controller/test/test_tricycle_steering_controller.hpp b/tricycle_steering_controller/test/test_tricycle_steering_controller.hpp index e9d1023d98..c5f6985d4e 100644 --- a/tricycle_steering_controller/test/test_tricycle_steering_controller.hpp +++ b/tricycle_steering_controller/test/test_tricycle_steering_controller.hpp @@ -146,7 +146,7 @@ class TricycleSteeringControllerFixture : public ::testing::Test protected: void SetUpController(const std::string controller_name = "test_tricycle_steering_controller") { - ASSERT_EQ(controller_->init(controller_name, ""), controller_interface::return_type::OK); + ASSERT_EQ(controller_->init(controller_name, "", 0), controller_interface::return_type::OK); if (position_feedback_ == true) { diff --git a/velocity_controllers/test/test_joint_group_velocity_controller.cpp b/velocity_controllers/test/test_joint_group_velocity_controller.cpp index 185c630bc9..4cbf1b7342 100644 --- a/velocity_controllers/test/test_joint_group_velocity_controller.cpp +++ b/velocity_controllers/test/test_joint_group_velocity_controller.cpp @@ -54,7 +54,7 @@ void JointGroupVelocityControllerTest::TearDown() { controller_.reset(nullptr); void JointGroupVelocityControllerTest::SetUpController() { - const auto result = controller_->init("test_joint_group_velocity_controller", ""); + const auto result = controller_->init("test_joint_group_velocity_controller", "", 0); ASSERT_EQ(result, controller_interface::return_type::OK); std::vector command_ifs; From ba7405443b1cdb78c0e0f3ec458738da37d690d0 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Tue, 21 Nov 2023 11:52:35 +0000 Subject: [PATCH 148/238] Update changelogs --- ackermann_steering_controller/CHANGELOG.rst | 6 ++++++ admittance_controller/CHANGELOG.rst | 6 ++++++ bicycle_steering_controller/CHANGELOG.rst | 6 ++++++ diff_drive_controller/CHANGELOG.rst | 8 ++++++++ effort_controllers/CHANGELOG.rst | 6 ++++++ force_torque_sensor_broadcaster/CHANGELOG.rst | 6 ++++++ forward_command_controller/CHANGELOG.rst | 7 +++++++ gripper_controllers/CHANGELOG.rst | 6 ++++++ imu_sensor_broadcaster/CHANGELOG.rst | 6 ++++++ joint_state_broadcaster/CHANGELOG.rst | 6 ++++++ joint_trajectory_controller/CHANGELOG.rst | 11 +++++++++++ position_controllers/CHANGELOG.rst | 6 ++++++ range_sensor_broadcaster/CHANGELOG.rst | 6 ++++++ ros2_controllers/CHANGELOG.rst | 3 +++ ros2_controllers_test_nodes/CHANGELOG.rst | 3 +++ rqt_joint_trajectory_controller/CHANGELOG.rst | 3 +++ steering_controllers_library/CHANGELOG.rst | 6 ++++++ tricycle_controller/CHANGELOG.rst | 6 ++++++ tricycle_steering_controller/CHANGELOG.rst | 6 ++++++ velocity_controllers/CHANGELOG.rst | 6 ++++++ 20 files changed, 119 insertions(+) diff --git a/ackermann_steering_controller/CHANGELOG.rst b/ackermann_steering_controller/CHANGELOG.rst index d679a782d4..7b9a59976e 100644 --- a/ackermann_steering_controller/CHANGELOG.rst +++ b/ackermann_steering_controller/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package ackermann_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* fix tests for API break of passing controller manager update rate in init method (`#854 `_) +* Adjust tests after passing URDF to controllers (`#817 `_) +* Contributors: Bence Magyar, Sai Kishor Kothakota + 3.17.0 (2023-10-31) ------------------- * Improve docs (`#785 `_) diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index ba5a131094..1a359ce855 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* fix tests for API break of passing controller manager update rate in init method (`#854 `_) +* Adjust tests after passing URDF to controllers (`#817 `_) +* Contributors: Bence Magyar, Sai Kishor Kothakota + 3.17.0 (2023-10-31) ------------------- diff --git a/bicycle_steering_controller/CHANGELOG.rst b/bicycle_steering_controller/CHANGELOG.rst index 7b14b2d617..f18f0188a7 100644 --- a/bicycle_steering_controller/CHANGELOG.rst +++ b/bicycle_steering_controller/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package bicycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* fix tests for API break of passing controller manager update rate in init method (`#854 `_) +* Adjust tests after passing URDF to controllers (`#817 `_) +* Contributors: Bence Magyar, Sai Kishor Kothakota + 3.17.0 (2023-10-31) ------------------- * Improve docs (`#785 `_) diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index b3f4b127e3..6862ea574c 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,6 +2,14 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* fix tests for API break of passing controller manager update rate in init method (`#854 `_) +* [diff_drive_controller] Fixed typos in diff_drive_controller_parameter.yaml. (`#822 `_) +* [diff_drive_controller] Remove non-stamped Twist option (`#812 `_) +* Adjust tests after passing URDF to controllers (`#817 `_) +* Contributors: Bence Magyar, Sai Kishor Kothakota, Tony Baltovski + 3.17.0 (2023-10-31) ------------------- diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index baaada7c22..15c3edef1b 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* fix tests for API break of passing controller manager update rate in init method (`#854 `_) +* Adjust tests after passing URDF to controllers (`#817 `_) +* Contributors: Bence Magyar, Sai Kishor Kothakota + 3.17.0 (2023-10-31) ------------------- diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index 9b6dea8ef9..8bc4a07db2 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* fix tests for API break of passing controller manager update rate in init method (`#854 `_) +* Adjust tests after passing URDF to controllers (`#817 `_) +* Contributors: Bence Magyar, Sai Kishor Kothakota + 3.17.0 (2023-10-31) ------------------- diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index 4bc9d41c74..77f249ccbd 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,6 +2,13 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* fix tests for API break of passing controller manager update rate in init method (`#854 `_) +* Resort overview page (`#846 `_) +* Adjust tests after passing URDF to controllers (`#817 `_) +* Contributors: Bence Magyar, Christoph Fröhlich, Sai Kishor Kothakota + 3.17.0 (2023-10-31) ------------------- diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index b7c7242520..a59b2c24ce 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* fix tests for API break of passing controller manager update rate in init method (`#854 `_) +* Adjust tests after passing URDF to controllers (`#817 `_) +* Contributors: Bence Magyar, Sai Kishor Kothakota + 3.17.0 (2023-10-31) ------------------- diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index 8644b008a0..d1fdff1378 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* fix tests for API break of passing controller manager update rate in init method (`#854 `_) +* Adjust tests after passing URDF to controllers (`#817 `_) +* Contributors: Bence Magyar, Sai Kishor Kothakota + 3.17.0 (2023-10-31) ------------------- diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index fd56b72c3b..456e81090b 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* fix tests for API break of passing controller manager update rate in init method (`#854 `_) +* Adjust tests after passing URDF to controllers (`#817 `_) +* Contributors: Bence Magyar, Sai Kishor Kothakota + 3.17.0 (2023-10-31) ------------------- diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index 9eece3af21..66d24ea513 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,17 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* fix tests for API break of passing controller manager update rate in init method (`#854 `_) +* [JTC] Fix dynamic reconfigure of tolerances (`#849 `_) +* [JTC] Remove unused home pose (`#845 `_) +* [JTC] Activate update of dynamic parameters (`#761 `_) +* [JTC] Fix tests when state offset is used (`#797 `_) +* [JTC] Remove deprecation warnings, set `allow_nonzero_velocity_at_trajectory_end` default false (`#834 `_) +* Adjust tests after passing URDF to controllers (`#817 `_) +* Contributors: Bence Magyar, Christoph Fröhlich, Sai Kishor Kothakota, Dr Denis + 3.17.0 (2023-10-31) ------------------- * Cleanup comments and unnecessary checks (`#803 `_) diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index 5239c43407..b214480e86 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* fix tests for API break of passing controller manager update rate in init method (`#854 `_) +* Adjust tests after passing URDF to controllers (`#817 `_) +* Contributors: Bence Magyar, Sai Kishor Kothakota + 3.17.0 (2023-10-31) ------------------- diff --git a/range_sensor_broadcaster/CHANGELOG.rst b/range_sensor_broadcaster/CHANGELOG.rst index b1084b4a24..1f04cf47e7 100644 --- a/range_sensor_broadcaster/CHANGELOG.rst +++ b/range_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package range_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* fix tests for API break of passing controller manager update rate in init method (`#854 `_) +* Adjust tests after passing URDF to controllers (`#817 `_) +* Contributors: Bence Magyar, Sai Kishor Kothakota + 3.17.0 (2023-10-31) ------------------- diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index 187db3d351..873dd5b55f 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.17.0 (2023-10-31) ------------------- diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index acca28227f..0d1e8ad2ef 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.17.0 (2023-10-31) ------------------- * [TestNodes] Optimize output about setup of JTC publisher (`#792 `_) diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index e723d39c6f..7263a948d5 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.17.0 (2023-10-31) ------------------- diff --git a/steering_controllers_library/CHANGELOG.rst b/steering_controllers_library/CHANGELOG.rst index 8082dc9070..5279d003cf 100644 --- a/steering_controllers_library/CHANGELOG.rst +++ b/steering_controllers_library/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package steering_controllers_library ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* fix tests for API break of passing controller manager update rate in init method (`#854 `_) +* Adjust tests after passing URDF to controllers (`#817 `_) +* Contributors: Bence Magyar, Sai Kishor Kothakota + 3.17.0 (2023-10-31) ------------------- * Steering controllers library: fix open loop mode (`#793 `_) diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index bda1c89d32..605a4f896d 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* fix tests for API break of passing controller manager update rate in init method (`#854 `_) +* Adjust tests after passing URDF to controllers (`#817 `_) +* Contributors: Bence Magyar, Sai Kishor Kothakota + 3.17.0 (2023-10-31) ------------------- diff --git a/tricycle_steering_controller/CHANGELOG.rst b/tricycle_steering_controller/CHANGELOG.rst index a7e6854ea8..a41ee0623c 100644 --- a/tricycle_steering_controller/CHANGELOG.rst +++ b/tricycle_steering_controller/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package tricycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* fix tests for API break of passing controller manager update rate in init method (`#854 `_) +* Adjust tests after passing URDF to controllers (`#817 `_) +* Contributors: Bence Magyar, Sai Kishor Kothakota + 3.17.0 (2023-10-31) ------------------- * Improve docs (`#785 `_) diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index 358ee9f499..9d4102e69a 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* fix tests for API break of passing controller manager update rate in init method (`#854 `_) +* Adjust tests after passing URDF to controllers (`#817 `_) +* Contributors: Bence Magyar, Sai Kishor Kothakota + 3.17.0 (2023-10-31) ------------------- From 0d3fc520831d10d4c1d16784e7378c2a0bf7b10f Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Tue, 21 Nov 2023 11:52:59 +0000 Subject: [PATCH 149/238] 4.0.0 --- ackermann_steering_controller/CHANGELOG.rst | 4 ++-- ackermann_steering_controller/package.xml | 2 +- admittance_controller/CHANGELOG.rst | 4 ++-- admittance_controller/package.xml | 2 +- bicycle_steering_controller/CHANGELOG.rst | 4 ++-- bicycle_steering_controller/package.xml | 2 +- diff_drive_controller/CHANGELOG.rst | 4 ++-- diff_drive_controller/package.xml | 2 +- effort_controllers/CHANGELOG.rst | 4 ++-- effort_controllers/package.xml | 2 +- force_torque_sensor_broadcaster/CHANGELOG.rst | 4 ++-- force_torque_sensor_broadcaster/package.xml | 2 +- forward_command_controller/CHANGELOG.rst | 4 ++-- forward_command_controller/package.xml | 2 +- gripper_controllers/CHANGELOG.rst | 4 ++-- gripper_controllers/package.xml | 2 +- imu_sensor_broadcaster/CHANGELOG.rst | 4 ++-- imu_sensor_broadcaster/package.xml | 2 +- joint_state_broadcaster/CHANGELOG.rst | 4 ++-- joint_state_broadcaster/package.xml | 2 +- joint_trajectory_controller/CHANGELOG.rst | 4 ++-- joint_trajectory_controller/package.xml | 2 +- position_controllers/CHANGELOG.rst | 4 ++-- position_controllers/package.xml | 2 +- range_sensor_broadcaster/CHANGELOG.rst | 4 ++-- range_sensor_broadcaster/package.xml | 2 +- ros2_controllers/CHANGELOG.rst | 4 ++-- ros2_controllers/package.xml | 2 +- ros2_controllers_test_nodes/CHANGELOG.rst | 4 ++-- ros2_controllers_test_nodes/package.xml | 2 +- ros2_controllers_test_nodes/setup.py | 2 +- rqt_joint_trajectory_controller/CHANGELOG.rst | 4 ++-- rqt_joint_trajectory_controller/package.xml | 2 +- rqt_joint_trajectory_controller/setup.py | 2 +- steering_controllers_library/CHANGELOG.rst | 4 ++-- steering_controllers_library/package.xml | 2 +- tricycle_controller/CHANGELOG.rst | 4 ++-- tricycle_controller/package.xml | 2 +- tricycle_steering_controller/CHANGELOG.rst | 4 ++-- tricycle_steering_controller/package.xml | 2 +- velocity_controllers/CHANGELOG.rst | 4 ++-- velocity_controllers/package.xml | 2 +- 42 files changed, 62 insertions(+), 62 deletions(-) diff --git a/ackermann_steering_controller/CHANGELOG.rst b/ackermann_steering_controller/CHANGELOG.rst index 7b9a59976e..7a94360e4b 100644 --- a/ackermann_steering_controller/CHANGELOG.rst +++ b/ackermann_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ackermann_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.0.0 (2023-11-21) +------------------ * fix tests for API break of passing controller manager update rate in init method (`#854 `_) * Adjust tests after passing URDF to controllers (`#817 `_) * Contributors: Bence Magyar, Sai Kishor Kothakota diff --git a/ackermann_steering_controller/package.xml b/ackermann_steering_controller/package.xml index 656c88feae..421f098f96 100644 --- a/ackermann_steering_controller/package.xml +++ b/ackermann_steering_controller/package.xml @@ -2,7 +2,7 @@ ackermann_steering_controller - 3.17.0 + 4.0.0 Steering controller for Ackermann kinematics. Rear fixed wheels are powering the vehicle and front wheels are steering it. Apache License 2.0 Bence Magyar diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index 1a359ce855..b94892ac83 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.0.0 (2023-11-21) +------------------ * fix tests for API break of passing controller manager update rate in init method (`#854 `_) * Adjust tests after passing URDF to controllers (`#817 `_) * Contributors: Bence Magyar, Sai Kishor Kothakota diff --git a/admittance_controller/package.xml b/admittance_controller/package.xml index 62cf127d9f..a5f7e7e353 100644 --- a/admittance_controller/package.xml +++ b/admittance_controller/package.xml @@ -2,7 +2,7 @@ admittance_controller - 3.17.0 + 4.0.0 Implementation of admittance controllers for different input and output interface. Denis Štogl Bence Magyar diff --git a/bicycle_steering_controller/CHANGELOG.rst b/bicycle_steering_controller/CHANGELOG.rst index f18f0188a7..278921e18b 100644 --- a/bicycle_steering_controller/CHANGELOG.rst +++ b/bicycle_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package bicycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.0.0 (2023-11-21) +------------------ * fix tests for API break of passing controller manager update rate in init method (`#854 `_) * Adjust tests after passing URDF to controllers (`#817 `_) * Contributors: Bence Magyar, Sai Kishor Kothakota diff --git a/bicycle_steering_controller/package.xml b/bicycle_steering_controller/package.xml index 9ee4c53049..e3063672d6 100644 --- a/bicycle_steering_controller/package.xml +++ b/bicycle_steering_controller/package.xml @@ -2,7 +2,7 @@ bicycle_steering_controller - 3.17.0 + 4.0.0 Steering controller with bicycle kinematics. Rear fixed wheel is powering the vehicle and front wheel is steering. Apache License 2.0 Bence Magyar diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index 6862ea574c..5f57b7e833 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.0.0 (2023-11-21) +------------------ * fix tests for API break of passing controller manager update rate in init method (`#854 `_) * [diff_drive_controller] Fixed typos in diff_drive_controller_parameter.yaml. (`#822 `_) * [diff_drive_controller] Remove non-stamped Twist option (`#812 `_) diff --git a/diff_drive_controller/package.xml b/diff_drive_controller/package.xml index 01dc69413a..56b9552f93 100644 --- a/diff_drive_controller/package.xml +++ b/diff_drive_controller/package.xml @@ -1,7 +1,7 @@ diff_drive_controller - 3.17.0 + 4.0.0 Controller for a differential drive mobile base. Bence Magyar Jordan Palacios diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index 15c3edef1b..6c7d7d6fa3 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.0.0 (2023-11-21) +------------------ * fix tests for API break of passing controller manager update rate in init method (`#854 `_) * Adjust tests after passing URDF to controllers (`#817 `_) * Contributors: Bence Magyar, Sai Kishor Kothakota diff --git a/effort_controllers/package.xml b/effort_controllers/package.xml index d0627bea10..ef2610d34f 100644 --- a/effort_controllers/package.xml +++ b/effort_controllers/package.xml @@ -1,7 +1,7 @@ effort_controllers - 3.17.0 + 4.0.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index 8bc4a07db2..17a6d4f280 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.0.0 (2023-11-21) +------------------ * fix tests for API break of passing controller manager update rate in init method (`#854 `_) * Adjust tests after passing URDF to controllers (`#817 `_) * Contributors: Bence Magyar, Sai Kishor Kothakota diff --git a/force_torque_sensor_broadcaster/package.xml b/force_torque_sensor_broadcaster/package.xml index 81c865ddfb..4a1df9ff11 100644 --- a/force_torque_sensor_broadcaster/package.xml +++ b/force_torque_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ force_torque_sensor_broadcaster - 3.17.0 + 4.0.0 Controller to publish state of force-torque sensors. Bence Magyar Denis Štogl diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index 77f249ccbd..941b849edd 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.0.0 (2023-11-21) +------------------ * fix tests for API break of passing controller manager update rate in init method (`#854 `_) * Resort overview page (`#846 `_) * Adjust tests after passing URDF to controllers (`#817 `_) diff --git a/forward_command_controller/package.xml b/forward_command_controller/package.xml index 246bc6777d..0fe44110b1 100644 --- a/forward_command_controller/package.xml +++ b/forward_command_controller/package.xml @@ -1,7 +1,7 @@ forward_command_controller - 3.17.0 + 4.0.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index a59b2c24ce..f35dcd1a32 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.0.0 (2023-11-21) +------------------ * fix tests for API break of passing controller manager update rate in init method (`#854 `_) * Adjust tests after passing URDF to controllers (`#817 `_) * Contributors: Bence Magyar, Sai Kishor Kothakota diff --git a/gripper_controllers/package.xml b/gripper_controllers/package.xml index 391bd1bb7d..08b0298e1f 100644 --- a/gripper_controllers/package.xml +++ b/gripper_controllers/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> gripper_controllers - 3.17.0 + 4.0.0 The gripper_controllers package Bence Magyar diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index d1fdff1378..4d2d2d01b3 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.0.0 (2023-11-21) +------------------ * fix tests for API break of passing controller manager update rate in init method (`#854 `_) * Adjust tests after passing URDF to controllers (`#817 `_) * Contributors: Bence Magyar, Sai Kishor Kothakota diff --git a/imu_sensor_broadcaster/package.xml b/imu_sensor_broadcaster/package.xml index 2dcacc1f0f..1819b974e2 100644 --- a/imu_sensor_broadcaster/package.xml +++ b/imu_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ imu_sensor_broadcaster - 3.17.0 + 4.0.0 Controller to publish readings of IMU sensors. Bence Magyar Denis Štogl diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index 456e81090b..ce89b01912 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.0.0 (2023-11-21) +------------------ * fix tests for API break of passing controller manager update rate in init method (`#854 `_) * Adjust tests after passing URDF to controllers (`#817 `_) * Contributors: Bence Magyar, Sai Kishor Kothakota diff --git a/joint_state_broadcaster/package.xml b/joint_state_broadcaster/package.xml index e4fecb14d7..1364b1a164 100644 --- a/joint_state_broadcaster/package.xml +++ b/joint_state_broadcaster/package.xml @@ -1,7 +1,7 @@ joint_state_broadcaster - 3.17.0 + 4.0.0 Broadcaster to publish joint state Bence Magyar Denis Stogl diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index 66d24ea513..a4486e4e98 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.0.0 (2023-11-21) +------------------ * fix tests for API break of passing controller manager update rate in init method (`#854 `_) * [JTC] Fix dynamic reconfigure of tolerances (`#849 `_) * [JTC] Remove unused home pose (`#845 `_) diff --git a/joint_trajectory_controller/package.xml b/joint_trajectory_controller/package.xml index f4efc2c060..fe10d9583d 100644 --- a/joint_trajectory_controller/package.xml +++ b/joint_trajectory_controller/package.xml @@ -1,7 +1,7 @@ joint_trajectory_controller - 3.17.0 + 4.0.0 Controller for executing joint-space trajectories on a group of joints Bence Magyar Jordan Palacios diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index b214480e86..26462d51a9 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.0.0 (2023-11-21) +------------------ * fix tests for API break of passing controller manager update rate in init method (`#854 `_) * Adjust tests after passing URDF to controllers (`#817 `_) * Contributors: Bence Magyar, Sai Kishor Kothakota diff --git a/position_controllers/package.xml b/position_controllers/package.xml index b3cd9b6cfb..2112f7d8c5 100644 --- a/position_controllers/package.xml +++ b/position_controllers/package.xml @@ -1,7 +1,7 @@ position_controllers - 3.17.0 + 4.0.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/range_sensor_broadcaster/CHANGELOG.rst b/range_sensor_broadcaster/CHANGELOG.rst index 1f04cf47e7..71ee9a7119 100644 --- a/range_sensor_broadcaster/CHANGELOG.rst +++ b/range_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package range_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.0.0 (2023-11-21) +------------------ * fix tests for API break of passing controller manager update rate in init method (`#854 `_) * Adjust tests after passing URDF to controllers (`#817 `_) * Contributors: Bence Magyar, Sai Kishor Kothakota diff --git a/range_sensor_broadcaster/package.xml b/range_sensor_broadcaster/package.xml index cf6545d65e..3ece4bda4b 100644 --- a/range_sensor_broadcaster/package.xml +++ b/range_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ range_sensor_broadcaster - 3.17.0 + 4.0.0 Controller to publish readings of Range sensors. Bence Magyar Florent Chretien diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index 873dd5b55f..2c2e5ec358 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.0.0 (2023-11-21) +------------------ 3.17.0 (2023-10-31) ------------------- diff --git a/ros2_controllers/package.xml b/ros2_controllers/package.xml index 49c87b152d..6a213308c5 100644 --- a/ros2_controllers/package.xml +++ b/ros2_controllers/package.xml @@ -1,7 +1,7 @@ ros2_controllers - 3.17.0 + 4.0.0 Metapackage for ROS2 controllers related packages Bence Magyar Jordan Palacios diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index 0d1e8ad2ef..e8eaf9c382 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.0.0 (2023-11-21) +------------------ 3.17.0 (2023-10-31) ------------------- diff --git a/ros2_controllers_test_nodes/package.xml b/ros2_controllers_test_nodes/package.xml index ef8c7b572d..5698930bff 100644 --- a/ros2_controllers_test_nodes/package.xml +++ b/ros2_controllers_test_nodes/package.xml @@ -2,7 +2,7 @@ ros2_controllers_test_nodes - 3.17.0 + 4.0.0 Demo nodes for showing and testing functionalities of the ros2_control framework. Denis Štogl diff --git a/ros2_controllers_test_nodes/setup.py b/ros2_controllers_test_nodes/setup.py index 102c39b607..a129b2d0a7 100644 --- a/ros2_controllers_test_nodes/setup.py +++ b/ros2_controllers_test_nodes/setup.py @@ -20,7 +20,7 @@ setup( name=package_name, - version="3.17.0", + version="4.0.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index 7263a948d5..0c08780904 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.0.0 (2023-11-21) +------------------ 3.17.0 (2023-10-31) ------------------- diff --git a/rqt_joint_trajectory_controller/package.xml b/rqt_joint_trajectory_controller/package.xml index 08f885aef3..41cf5e85d7 100644 --- a/rqt_joint_trajectory_controller/package.xml +++ b/rqt_joint_trajectory_controller/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> rqt_joint_trajectory_controller - 3.17.0 + 4.0.0 Graphical frontend for interacting with joint_trajectory_controller instances. Bence Magyar diff --git a/rqt_joint_trajectory_controller/setup.py b/rqt_joint_trajectory_controller/setup.py index c0f4a96c2a..5a5b979d41 100644 --- a/rqt_joint_trajectory_controller/setup.py +++ b/rqt_joint_trajectory_controller/setup.py @@ -7,7 +7,7 @@ setup( name=package_name, - version="3.17.0", + version="4.0.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/steering_controllers_library/CHANGELOG.rst b/steering_controllers_library/CHANGELOG.rst index 5279d003cf..1a76469d6c 100644 --- a/steering_controllers_library/CHANGELOG.rst +++ b/steering_controllers_library/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package steering_controllers_library ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.0.0 (2023-11-21) +------------------ * fix tests for API break of passing controller manager update rate in init method (`#854 `_) * Adjust tests after passing URDF to controllers (`#817 `_) * Contributors: Bence Magyar, Sai Kishor Kothakota diff --git a/steering_controllers_library/package.xml b/steering_controllers_library/package.xml index 0194cfd041..932fda9a35 100644 --- a/steering_controllers_library/package.xml +++ b/steering_controllers_library/package.xml @@ -2,7 +2,7 @@ steering_controllers_library - 3.17.0 + 4.0.0 Package for steering robot configurations including odometry and interfaces. Apache License 2.0 Bence Magyar diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index 605a4f896d..6bc3d26f53 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.0.0 (2023-11-21) +------------------ * fix tests for API break of passing controller manager update rate in init method (`#854 `_) * Adjust tests after passing URDF to controllers (`#817 `_) * Contributors: Bence Magyar, Sai Kishor Kothakota diff --git a/tricycle_controller/package.xml b/tricycle_controller/package.xml index 9a6cf3ef2d..a663dcacde 100644 --- a/tricycle_controller/package.xml +++ b/tricycle_controller/package.xml @@ -2,7 +2,7 @@ tricycle_controller - 3.17.0 + 4.0.0 Controller for a tricycle drive mobile base Bence Magyar Tony Najjar diff --git a/tricycle_steering_controller/CHANGELOG.rst b/tricycle_steering_controller/CHANGELOG.rst index a41ee0623c..0ade9bca61 100644 --- a/tricycle_steering_controller/CHANGELOG.rst +++ b/tricycle_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package tricycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.0.0 (2023-11-21) +------------------ * fix tests for API break of passing controller manager update rate in init method (`#854 `_) * Adjust tests after passing URDF to controllers (`#817 `_) * Contributors: Bence Magyar, Sai Kishor Kothakota diff --git a/tricycle_steering_controller/package.xml b/tricycle_steering_controller/package.xml index e39971982c..7f9d14c2fe 100644 --- a/tricycle_steering_controller/package.xml +++ b/tricycle_steering_controller/package.xml @@ -2,7 +2,7 @@ tricycle_steering_controller - 3.17.0 + 4.0.0 Steering controller with tricycle kinematics. Rear fixed wheels are powering the vehicle and front wheel is steering. Apache License 2.0 Bence Magyar diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index 9d4102e69a..bb7e231222 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.0.0 (2023-11-21) +------------------ * fix tests for API break of passing controller manager update rate in init method (`#854 `_) * Adjust tests after passing URDF to controllers (`#817 `_) * Contributors: Bence Magyar, Sai Kishor Kothakota diff --git a/velocity_controllers/package.xml b/velocity_controllers/package.xml index f336606b26..6ce13e6adf 100644 --- a/velocity_controllers/package.xml +++ b/velocity_controllers/package.xml @@ -1,7 +1,7 @@ velocity_controllers - 3.17.0 + 4.0.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios From 2854a0bc5da016b6ddc55383e6f7bd7b8e1e57ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Sun, 26 Nov 2023 22:06:17 +0100 Subject: [PATCH 150/238] Use testing and remove wrong field of workflow_dispatch (#860) --- .github/workflows/humble-abi-compatibility.yml | 4 +--- .github/workflows/iron-abi-compatibility.yml | 4 +--- .github/workflows/rolling-abi-compatibility.yml | 4 +--- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/.github/workflows/humble-abi-compatibility.yml b/.github/workflows/humble-abi-compatibility.yml index 708ea5c1f4..5c288fabfb 100644 --- a/.github/workflows/humble-abi-compatibility.yml +++ b/.github/workflows/humble-abi-compatibility.yml @@ -1,8 +1,6 @@ name: Humble - ABI Compatibility Check on: workflow_dispatch: - branches: - - humble pull_request: branches: - humble @@ -15,6 +13,6 @@ jobs: - uses: ros-industrial/industrial_ci@master env: ROS_DISTRO: humble - ROS_REPO: main + ROS_REPO: testing ABICHECK_URL: github:${{ github.repository }}#${{ github.base_ref }} NOT_TEST_BUILD: true diff --git a/.github/workflows/iron-abi-compatibility.yml b/.github/workflows/iron-abi-compatibility.yml index 20d93f5af1..ab6642625f 100644 --- a/.github/workflows/iron-abi-compatibility.yml +++ b/.github/workflows/iron-abi-compatibility.yml @@ -1,8 +1,6 @@ name: Iron - ABI Compatibility Check on: workflow_dispatch: - branches: - - iron pull_request: branches: - iron @@ -15,6 +13,6 @@ jobs: - uses: ros-industrial/industrial_ci@master env: ROS_DISTRO: iron - ROS_REPO: main + ROS_REPO: testing ABICHECK_URL: github:${{ github.repository }}#${{ github.base_ref }} NOT_TEST_BUILD: true diff --git a/.github/workflows/rolling-abi-compatibility.yml b/.github/workflows/rolling-abi-compatibility.yml index 3911434a23..73055ef3e5 100644 --- a/.github/workflows/rolling-abi-compatibility.yml +++ b/.github/workflows/rolling-abi-compatibility.yml @@ -1,8 +1,6 @@ name: Rolling - ABI Compatibility Check on: workflow_dispatch: - branches: - - master pull_request: branches: - master @@ -15,6 +13,6 @@ jobs: - uses: ros-industrial/industrial_ci@master env: ROS_DISTRO: rolling - ROS_REPO: main + ROS_REPO: testing ABICHECK_URL: github:${{ github.repository }}#${{ github.base_ref }} NOT_TEST_BUILD: true From b8532284853c990a83741b85983f18ed38ef5f89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Mon, 27 Nov 2023 12:31:10 +0100 Subject: [PATCH 151/238] [JTC] Improve update methods for tests (#858) --- .../test/test_trajectory_actions.cpp | 16 +- .../test/test_trajectory_controller.cpp | 967 ++++++++---------- .../test/test_trajectory_controller_utils.hpp | 143 ++- 3 files changed, 565 insertions(+), 561 deletions(-) diff --git a/joint_trajectory_controller/test/test_trajectory_actions.cpp b/joint_trajectory_controller/test/test_trajectory_actions.cpp index 3b80abcb9b..ed13a24485 100644 --- a/joint_trajectory_controller/test/test_trajectory_actions.cpp +++ b/joint_trajectory_controller/test/test_trajectory_actions.cpp @@ -242,7 +242,7 @@ TEST_P(TestTrajectoryActionsTestParameterized, test_success_single_point_sendgoa EXPECT_EQ(rclcpp_action::ResultCode::SUCCEEDED, common_resultcode_); // run an update - updateController(rclcpp::Duration::from_seconds(0.01)); + updateControllerAsync(rclcpp::Duration::from_seconds(0.01)); // it should be holding the last position goal // i.e., active but trivial trajectory (one point only) @@ -298,7 +298,7 @@ TEST_P(TestTrajectoryActionsTestParameterized, test_success_multi_point_sendgoal EXPECT_EQ(rclcpp_action::ResultCode::SUCCEEDED, common_resultcode_); // run an update - updateController(rclcpp::Duration::from_seconds(0.01)); + updateControllerAsync(rclcpp::Duration::from_seconds(0.01)); // it should be holding the last position goal // i.e., active but trivial trajectory (one point only) @@ -350,7 +350,7 @@ TEST_F(TestTrajectoryActions, test_goal_tolerances_single_point_success) control_msgs::action::FollowJointTrajectory_Result::SUCCESSFUL, common_action_result_code_); // run an update - updateController(rclcpp::Duration::from_seconds(0.01)); + updateControllerAsync(rclcpp::Duration::from_seconds(0.01)); // it should be holding the last position goal // i.e., active but trivial trajectory (one point only) @@ -409,7 +409,7 @@ TEST_F(TestTrajectoryActions, test_goal_tolerances_multi_point_success) control_msgs::action::FollowJointTrajectory_Result::SUCCESSFUL, common_action_result_code_); // run an update - updateController(rclcpp::Duration::from_seconds(0.01)); + updateControllerAsync(rclcpp::Duration::from_seconds(0.01)); // it should be holding the last position goal // i.e., active but trivial trajectory (one point only) @@ -460,7 +460,7 @@ TEST_P(TestTrajectoryActionsTestParameterized, test_state_tolerances_fail) common_action_result_code_); // run an update - updateController(rclcpp::Duration::from_seconds(0.01)); + updateControllerAsync(rclcpp::Duration::from_seconds(0.01)); // it should be holding the position (being the initial one) // i.e., active but trivial trajectory (one point only) @@ -509,7 +509,7 @@ TEST_P(TestTrajectoryActionsTestParameterized, test_goal_tolerances_fail) common_action_result_code_); // run an update - updateController(rclcpp::Duration::from_seconds(0.01)); + updateControllerAsync(rclcpp::Duration::from_seconds(0.01)); // it should be holding the position (being the initial one) // i.e., active but trivial trajectory (one point only) @@ -555,7 +555,7 @@ TEST_P(TestTrajectoryActionsTestParameterized, test_no_time_from_start_state_tol common_action_result_code_); // run an update - updateController(rclcpp::Duration::from_seconds(0.01)); + updateControllerAsync(rclcpp::Duration::from_seconds(0.01)); // it should be holding the position (being the initial one) // i.e., active but trivial trajectory (one point only) @@ -603,7 +603,7 @@ TEST_P(TestTrajectoryActionsTestParameterized, test_cancel_hold_position) std::vector cancelled_position{joint_pos_[0], joint_pos_[1], joint_pos_[2]}; // run an update - updateController(rclcpp::Duration::from_seconds(0.01)); + updateControllerAsync(rclcpp::Duration::from_seconds(0.01)); // it should be holding the last position, // i.e., active but trivial trajectory (one point only) diff --git a/joint_trajectory_controller/test/test_trajectory_controller.cpp b/joint_trajectory_controller/test/test_trajectory_controller.cpp index 8b29c2cb16..7c026d5e7a 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller.cpp +++ b/joint_trajectory_controller/test/test_trajectory_controller.cpp @@ -26,8 +26,6 @@ #include #include -#include "gmock/gmock.h" - #include "builtin_interfaces/msg/duration.hpp" #include "builtin_interfaces/msg/time.hpp" #include "controller_interface/controller_interface.hpp" @@ -103,77 +101,20 @@ TEST_P(TrajectoryControllerTestParameterized, check_interface_names) const auto state = traj_controller_->get_node()->configure(); ASSERT_EQ(state.id(), State::PRIMARY_STATE_INACTIVE); - std::vector state_interface_names; - state_interface_names.reserve(joint_names_.size() * state_interface_types_.size()); - for (const auto & joint : joint_names_) - { - for (const auto & interface : state_interface_types_) - { - state_interface_names.push_back(joint + "/" + interface); - } - } - auto state_interfaces = traj_controller_->state_interface_configuration(); - EXPECT_EQ(state_interfaces.type, controller_interface::interface_configuration_type::INDIVIDUAL); - EXPECT_EQ(state_interfaces.names.size(), joint_names_.size() * state_interface_types_.size()); - ASSERT_THAT(state_interfaces.names, testing::UnorderedElementsAreArray(state_interface_names)); - - std::vector command_interface_names; - command_interface_names.reserve(joint_names_.size() * command_interface_types_.size()); - for (const auto & joint : joint_names_) - { - for (const auto & interface : command_interface_types_) - { - command_interface_names.push_back(joint + "/" + interface); - } - } - auto command_interfaces = traj_controller_->command_interface_configuration(); - EXPECT_EQ( - command_interfaces.type, controller_interface::interface_configuration_type::INDIVIDUAL); - EXPECT_EQ(command_interfaces.names.size(), joint_names_.size() * command_interface_types_.size()); - ASSERT_THAT( - command_interfaces.names, testing::UnorderedElementsAreArray(command_interface_names)); + compare_joints(joint_names_, joint_names_); } TEST_P(TrajectoryControllerTestParameterized, check_interface_names_with_command_joints) { rclcpp::executors::MultiThreadedExecutor executor; - // set command_joints parameter + // set command_joints parameter different than joint_names_ const rclcpp::Parameter command_joint_names_param("command_joints", command_joint_names_); SetUpTrajectoryController(executor, {command_joint_names_param}); const auto state = traj_controller_->get_node()->configure(); ASSERT_EQ(state.id(), State::PRIMARY_STATE_INACTIVE); - std::vector state_interface_names; - state_interface_names.reserve(joint_names_.size() * state_interface_types_.size()); - for (const auto & joint : joint_names_) - { - for (const auto & interface : state_interface_types_) - { - state_interface_names.push_back(joint + "/" + interface); - } - } - auto state_interfaces = traj_controller_->state_interface_configuration(); - EXPECT_EQ(state_interfaces.type, controller_interface::interface_configuration_type::INDIVIDUAL); - EXPECT_EQ(state_interfaces.names.size(), joint_names_.size() * state_interface_types_.size()); - ASSERT_THAT(state_interfaces.names, testing::UnorderedElementsAreArray(state_interface_names)); - - std::vector command_interface_names; - command_interface_names.reserve(command_joint_names_.size() * command_interface_types_.size()); - for (const auto & joint : command_joint_names_) - { - for (const auto & interface : command_interface_types_) - { - command_interface_names.push_back(joint + "/" + interface); - } - } - auto command_interfaces = traj_controller_->command_interface_configuration(); - EXPECT_EQ( - command_interfaces.type, controller_interface::interface_configuration_type::INDIVIDUAL); - EXPECT_EQ( - command_interfaces.names.size(), command_joint_names_.size() * command_interface_types_.size()); - ASSERT_THAT( - command_interfaces.names, testing::UnorderedElementsAreArray(command_interface_names)); + compare_joints(joint_names_, command_joint_names_); } TEST_P(TrajectoryControllerTestParameterized, activate) @@ -316,6 +257,11 @@ TEST_P(TrajectoryControllerTestParameterized, correct_initialization_using_param executor.cancel(); } +/** + * @brief test if correct topic is received + * + * this test doesn't use class variables but subscribes to the state topic + */ TEST_P(TrajectoryControllerTestParameterized, state_topic_consistency) { rclcpp::executors::SingleThreadedExecutor executor; @@ -422,7 +368,7 @@ TEST_P(TrajectoryControllerTestParameterized, update_dynamic_parameters) SetUpAndActivateTrajectoryController(executor); - updateController(); + updateControllerAsync(); auto pids = traj_controller_->get_pids(); if (traj_controller_->use_closed_loop_pid_adapter()) @@ -433,7 +379,7 @@ TEST_P(TrajectoryControllerTestParameterized, update_dynamic_parameters) double kp = 1.0; SetPidParameters(kp); - updateController(); + updateControllerAsync(); pids = traj_controller_->get_pids(); EXPECT_EQ(pids.size(), 3); @@ -458,7 +404,7 @@ TEST_P(TrajectoryControllerTestParameterized, update_dynamic_tolerances) SetUpAndActivateTrajectoryController(executor); - updateController(); + updateControllerAsync(); // test default parameters { @@ -486,7 +432,7 @@ TEST_P(TrajectoryControllerTestParameterized, update_dynamic_tolerances) { traj_controller_->get_node()->set_parameter(param); } - updateController(); + updateControllerAsync(); { auto tols = traj_controller_->get_tolerances(); @@ -513,7 +459,7 @@ TEST_P(TrajectoryControllerTestParameterized, no_hold_on_startup) SetUpAndActivateTrajectoryController(executor, {start_with_holding_parameter}); constexpr auto FIRST_POINT_TIME = std::chrono::milliseconds(250); - updateController(rclcpp::Duration(FIRST_POINT_TIME)); + updateControllerAsync(rclcpp::Duration(FIRST_POINT_TIME)); // after startup without start_with_holding being set, we expect no active trajectory ASSERT_FALSE(traj_controller_->has_active_traj()); @@ -531,7 +477,7 @@ TEST_P(TrajectoryControllerTestParameterized, hold_on_startup) SetUpAndActivateTrajectoryController(executor, {start_with_holding_parameter}); constexpr auto FIRST_POINT_TIME = std::chrono::milliseconds(250); - updateController(rclcpp::Duration(FIRST_POINT_TIME)); + updateControllerAsync(rclcpp::Duration(FIRST_POINT_TIME)); // after startup with start_with_holding being set, we expect an active trajectory: ASSERT_TRUE(traj_controller_->has_active_traj()); // one point, being the position at startup @@ -552,7 +498,6 @@ TEST_P(TrajectoryControllerTestParameterized, position_error_not_angle_wraparoun constexpr double k_p = 10.0; std::vector params = {}; SetUpAndActivateTrajectoryController(executor, params, true, k_p, 0.0, false); - subscribeToState(); size_t n_joints = joint_names_.size(); @@ -568,84 +513,206 @@ TEST_P(TrajectoryControllerTestParameterized, position_error_not_angle_wraparoun publish(time_from_start, points, rclcpp::Time(), {}, points_velocities); traj_controller_->wait_for_trajectory(executor); - // first update - updateController(rclcpp::Duration(FIRST_POINT_TIME)); - - // Spin to receive latest state - executor.spin_some(); - auto state_msg = getState(); - ASSERT_TRUE(state_msg); + updateControllerAsync(rclcpp::Duration(FIRST_POINT_TIME)); - const auto allowed_delta = 0.1; + // get states from class variables + auto state_feedback = traj_controller_->get_state_feedback(); + auto state_reference = traj_controller_->get_state_reference(); + auto state_error = traj_controller_->get_state_error(); // no update of state_interface - EXPECT_EQ(state_msg->feedback.positions, INITIAL_POS_JOINTS); + EXPECT_EQ(state_feedback.positions, INITIAL_POS_JOINTS); // has the msg the correct vector sizes? - EXPECT_EQ(n_joints, state_msg->reference.positions.size()); - EXPECT_EQ(n_joints, state_msg->feedback.positions.size()); - EXPECT_EQ(n_joints, state_msg->error.positions.size()); + EXPECT_EQ(n_joints, state_reference.positions.size()); + EXPECT_EQ(n_joints, state_feedback.positions.size()); + EXPECT_EQ(n_joints, state_error.positions.size()); // are the correct reference positions used? - EXPECT_NEAR(points[0][0], state_msg->reference.positions[0], allowed_delta); - EXPECT_NEAR(points[0][1], state_msg->reference.positions[1], allowed_delta); - EXPECT_NEAR(points[0][2], state_msg->reference.positions[2], 3 * allowed_delta); + EXPECT_NEAR(points[0][0], state_reference.positions[0], COMMON_THRESHOLD); + EXPECT_NEAR(points[0][1], state_reference.positions[1], COMMON_THRESHOLD); + EXPECT_NEAR(points[0][2], state_reference.positions[2], COMMON_THRESHOLD); // no normalization of position error - EXPECT_NEAR( - state_msg->error.positions[0], state_msg->reference.positions[0] - INITIAL_POS_JOINTS[0], EPS); - EXPECT_NEAR( - state_msg->error.positions[1], state_msg->reference.positions[1] - INITIAL_POS_JOINTS[1], EPS); - EXPECT_NEAR( - state_msg->error.positions[2], state_msg->reference.positions[2] - INITIAL_POS_JOINTS[2], EPS); + EXPECT_NEAR(state_error.positions[0], state_reference.positions[0] - INITIAL_POS_JOINTS[0], EPS); + EXPECT_NEAR(state_error.positions[1], state_reference.positions[1] - INITIAL_POS_JOINTS[1], EPS); + EXPECT_NEAR(state_error.positions[2], state_reference.positions[2] - INITIAL_POS_JOINTS[2], EPS); if (traj_controller_->has_position_command_interface()) { // check command interface - EXPECT_NEAR(points[0][0], joint_pos_[0], allowed_delta); - EXPECT_NEAR(points[0][1], joint_pos_[1], allowed_delta); - EXPECT_NEAR(points[0][2], joint_pos_[2], allowed_delta); - EXPECT_NEAR(points[0][0], state_msg->output.positions[0], allowed_delta); - EXPECT_NEAR(points[0][1], state_msg->output.positions[1], allowed_delta); - EXPECT_NEAR(points[0][2], state_msg->output.positions[2], allowed_delta); + EXPECT_NEAR(points[0][0], joint_pos_[0], COMMON_THRESHOLD); + EXPECT_NEAR(points[0][1], joint_pos_[1], COMMON_THRESHOLD); + EXPECT_NEAR(points[0][2], joint_pos_[2], COMMON_THRESHOLD); } if (traj_controller_->has_velocity_command_interface()) + { + // use_closed_loop_pid_adapter_ + if (traj_controller_->use_closed_loop_pid_adapter()) + { + // we expect u = k_p * (s_d-s) for positions + EXPECT_NEAR( + k_p * (state_reference.positions[0] - INITIAL_POS_JOINTS[0]), joint_vel_[0], + k_p * COMMON_THRESHOLD); + EXPECT_NEAR( + k_p * (state_reference.positions[1] - INITIAL_POS_JOINTS[1]), joint_vel_[1], + k_p * COMMON_THRESHOLD); + EXPECT_NEAR( + k_p * (state_reference.positions[2] - INITIAL_POS_JOINTS[2]), joint_vel_[2], + k_p * COMMON_THRESHOLD); + } + else + { + // interpolated points_velocities only + // check command interface + EXPECT_LT(0.0, joint_vel_[0]); + EXPECT_LT(0.0, joint_vel_[1]); + EXPECT_LT(0.0, joint_vel_[2]); + } + } + + if (traj_controller_->has_effort_command_interface()) + { + // use_closed_loop_pid_adapter_ + if (traj_controller_->use_closed_loop_pid_adapter()) + { + // we expect u = k_p * (s_d-s) for positions + EXPECT_NEAR( + k_p * (state_reference.positions[0] - INITIAL_POS_JOINTS[0]), joint_eff_[0], + k_p * COMMON_THRESHOLD); + EXPECT_NEAR( + k_p * (state_reference.positions[1] - INITIAL_POS_JOINTS[1]), joint_eff_[1], + k_p * COMMON_THRESHOLD); + EXPECT_NEAR( + k_p * (state_reference.positions[2] - INITIAL_POS_JOINTS[2]), joint_eff_[2], + k_p * COMMON_THRESHOLD); + } + else + { + // interpolated points_velocities only + // check command interface + EXPECT_LT(0.0, joint_eff_[0]); + EXPECT_LT(0.0, joint_eff_[1]); + EXPECT_LT(0.0, joint_eff_[2]); + } + } + + executor.cancel(); +} + +/** + * @brief check if position error of revolute joints are angle_wraparound if configured so + */ +TEST_P(TrajectoryControllerTestParameterized, position_error_angle_wraparound) +{ + rclcpp::executors::MultiThreadedExecutor executor; + constexpr double k_p = 10.0; + std::vector params = {}; + SetUpAndActivateTrajectoryController(executor, params, true, k_p, 0.0, true); + + size_t n_joints = joint_names_.size(); + + // send msg + constexpr auto FIRST_POINT_TIME = std::chrono::milliseconds(250); + builtin_interfaces::msg::Duration time_from_start{rclcpp::Duration(FIRST_POINT_TIME)}; + // *INDENT-OFF* + std::vector> points{ + {{3.3, 4.4, 6.6}}, {{7.7, 8.8, 9.9}}, {{10.10, 11.11, 12.12}}}; + std::vector> points_velocities{ + {{0.01, 0.01, 0.01}}, {{0.05, 0.05, 0.05}}, {{0.06, 0.06, 0.06}}}; + // *INDENT-ON* + publish(time_from_start, points, rclcpp::Time(), {}, points_velocities); + traj_controller_->wait_for_trajectory(executor); + + updateControllerAsync(rclcpp::Duration(FIRST_POINT_TIME)); + + // get states from class variables + auto state_feedback = traj_controller_->get_state_feedback(); + auto state_reference = traj_controller_->get_state_reference(); + auto state_error = traj_controller_->get_state_error(); + + // no update of state_interface + EXPECT_EQ(state_feedback.positions, INITIAL_POS_JOINTS); + + // has the msg the correct vector sizes? + EXPECT_EQ(n_joints, state_reference.positions.size()); + EXPECT_EQ(n_joints, state_feedback.positions.size()); + EXPECT_EQ(n_joints, state_error.positions.size()); + + // are the correct reference positions used? + EXPECT_NEAR(points[0][0], state_reference.positions[0], COMMON_THRESHOLD); + EXPECT_NEAR(points[0][1], state_reference.positions[1], COMMON_THRESHOLD); + EXPECT_NEAR(points[0][2], state_reference.positions[2], COMMON_THRESHOLD); + + // is error.positions[2] angle_wraparound? + EXPECT_NEAR(state_error.positions[0], state_reference.positions[0] - INITIAL_POS_JOINTS[0], EPS); + EXPECT_NEAR(state_error.positions[1], state_reference.positions[1] - INITIAL_POS_JOINTS[1], EPS); + EXPECT_NEAR( + state_error.positions[2], state_reference.positions[2] - INITIAL_POS_JOINTS[2] - 2 * M_PI, EPS); + + if (traj_controller_->has_position_command_interface()) { // check command interface - EXPECT_LT(0.0, joint_vel_[0]); - EXPECT_LT(0.0, joint_vel_[1]); - EXPECT_LT(0.0, joint_vel_[2]); - EXPECT_LT(0.0, state_msg->output.velocities[0]); - EXPECT_LT(0.0, state_msg->output.velocities[1]); - EXPECT_LT(0.0, state_msg->output.velocities[2]); + EXPECT_NEAR(points[0][0], joint_pos_[0], COMMON_THRESHOLD); + EXPECT_NEAR(points[0][1], joint_pos_[1], COMMON_THRESHOLD); + EXPECT_NEAR(points[0][2], joint_pos_[2], COMMON_THRESHOLD); + } + if (traj_controller_->has_velocity_command_interface()) + { // use_closed_loop_pid_adapter_ if (traj_controller_->use_closed_loop_pid_adapter()) { - // we expect u = k_p * (s_d-s) + // we expect u = k_p * (s_d-s) for positions[0] and positions[1] EXPECT_NEAR( - k_p * (state_msg->reference.positions[0] - INITIAL_POS_JOINTS[0]), joint_vel_[0], - k_p * allowed_delta); + k_p * (state_reference.positions[0] - INITIAL_POS_JOINTS[0]), joint_vel_[0], + k_p * COMMON_THRESHOLD); EXPECT_NEAR( - k_p * (state_msg->reference.positions[1] - INITIAL_POS_JOINTS[1]), joint_vel_[1], - k_p * allowed_delta); - // no normalization of position error + k_p * (state_reference.positions[1] - INITIAL_POS_JOINTS[1]), joint_vel_[1], + k_p * COMMON_THRESHOLD); + // is error of positions[2] angle_wraparound? + EXPECT_GT(0.0, joint_vel_[2]); EXPECT_NEAR( - k_p * (state_msg->reference.positions[2] - INITIAL_POS_JOINTS[2]), joint_vel_[2], - k_p * allowed_delta); + k_p * (state_reference.positions[2] - INITIAL_POS_JOINTS[2] - 2 * M_PI), joint_vel_[2], + k_p * COMMON_THRESHOLD); + } + else + { + // interpolated points_velocities only + // check command interface + EXPECT_LT(0.0, joint_vel_[0]); + EXPECT_LT(0.0, joint_vel_[1]); + EXPECT_LT(0.0, joint_vel_[2]); } } if (traj_controller_->has_effort_command_interface()) { - // check command interface - EXPECT_LT(0.0, joint_eff_[0]); - EXPECT_LT(0.0, joint_eff_[1]); - EXPECT_LT(0.0, joint_eff_[2]); - EXPECT_LT(0.0, state_msg->output.effort[0]); - EXPECT_LT(0.0, state_msg->output.effort[1]); - EXPECT_LT(0.0, state_msg->output.effort[2]); + // use_closed_loop_pid_adapter_ + if (traj_controller_->use_closed_loop_pid_adapter()) + { + // we expect u = k_p * (s_d-s) for positions[0] and positions[1] + EXPECT_NEAR( + k_p * (state_reference.positions[0] - INITIAL_POS_JOINTS[0]), joint_eff_[0], + k_p * COMMON_THRESHOLD); + EXPECT_NEAR( + k_p * (state_reference.positions[1] - INITIAL_POS_JOINTS[1]), joint_eff_[1], + k_p * COMMON_THRESHOLD); + // is error of positions[2] angle_wraparound? + EXPECT_GT(0.0, joint_eff_[2]); + EXPECT_NEAR( + k_p * (state_reference.positions[2] - INITIAL_POS_JOINTS[2] - 2 * M_PI), joint_eff_[2], + k_p * COMMON_THRESHOLD); + } + else + { + // interpolated points_velocities only + // check command interface + EXPECT_LT(0.0, joint_eff_[0]); + EXPECT_LT(0.0, joint_eff_[1]); + EXPECT_LT(0.0, joint_eff_[2]); + } } executor.cancel(); @@ -685,13 +752,13 @@ TEST_P(TrajectoryControllerTestParameterized, decline_false_cmd_timeout) /** * @brief check if no timeout is triggered */ +// TODO(anyone) make test independent of clock source to use updateControllerAsync TEST_P(TrajectoryControllerTestParameterized, no_timeout) { rclcpp::executors::MultiThreadedExecutor executor; // zero is default value, just for demonstration rclcpp::Parameter cmd_timeout_parameter("cmd_timeout", 0.0); SetUpAndActivateTrajectoryController(executor, {cmd_timeout_parameter}, false); - subscribeToState(); size_t n_joints = joint_names_.size(); @@ -707,28 +774,27 @@ TEST_P(TrajectoryControllerTestParameterized, no_timeout) publish(time_from_start, points, rclcpp::Time(0, 0, RCL_STEADY_TIME), {}, points_velocities); traj_controller_->wait_for_trajectory(executor); - // first update updateController(rclcpp::Duration(FIRST_POINT_TIME) * 4); - // Spin to receive latest state - executor.spin_some(); - auto state_msg = getState(); - ASSERT_TRUE(state_msg); + // get states from class variables + auto state_feedback = traj_controller_->get_state_feedback(); + auto state_reference = traj_controller_->get_state_reference(); + auto state_error = traj_controller_->get_state_error(); // has the msg the correct vector sizes? - EXPECT_EQ(n_joints, state_msg->reference.positions.size()); + EXPECT_EQ(n_joints, state_reference.positions.size()); // is the trajectory still active? EXPECT_TRUE(traj_controller_->has_active_traj()); // should still hold the points from above EXPECT_TRUE(traj_controller_->has_nontrivial_traj()); - EXPECT_NEAR(state_msg->reference.positions[0], points.at(2).at(0), 1e-2); - EXPECT_NEAR(state_msg->reference.positions[1], points.at(2).at(1), 1e-2); - EXPECT_NEAR(state_msg->reference.positions[2], points.at(2).at(2), 1e-2); + EXPECT_NEAR(state_reference.positions[0], points.at(2).at(0), 1e-2); + EXPECT_NEAR(state_reference.positions[1], points.at(2).at(1), 1e-2); + EXPECT_NEAR(state_reference.positions[2], points.at(2).at(2), 1e-2); // value of velocities is different from above due to spline interpolation - EXPECT_GT(state_msg->reference.velocities[0], 0.0); - EXPECT_GT(state_msg->reference.velocities[1], 0.0); - EXPECT_GT(state_msg->reference.velocities[2], 0.0); + EXPECT_GT(state_reference.velocities[0], 0.0); + EXPECT_GT(state_reference.velocities[1], 0.0); + EXPECT_GT(state_reference.velocities[2], 0.0); executor.cancel(); } @@ -736,6 +802,7 @@ TEST_P(TrajectoryControllerTestParameterized, no_timeout) /** * @brief check if timeout is triggered */ +// TODO(anyone) make test independent of clock source to use updateControllerAsync TEST_P(TrajectoryControllerTestParameterized, timeout) { rclcpp::executors::MultiThreadedExecutor executor; @@ -743,7 +810,6 @@ TEST_P(TrajectoryControllerTestParameterized, timeout) rclcpp::Parameter cmd_timeout_parameter("cmd_timeout", cmd_timeout); double kp = 1.0; // activate feedback control for testing velocity/effort PID SetUpAndActivateTrajectoryController(executor, {cmd_timeout_parameter}, false, kp); - subscribeToState(); // send msg constexpr auto FIRST_POINT_TIME = std::chrono::milliseconds(250); @@ -768,11 +834,6 @@ TEST_P(TrajectoryControllerTestParameterized, timeout) // update until timeout should have happened updateController(rclcpp::Duration(FIRST_POINT_TIME)); - // Spin to receive latest state - executor.spin_some(); - auto state_msg = getState(); - ASSERT_TRUE(state_msg); - // after timeout, set_hold_position adds a new trajectory // is a trajectory active? EXPECT_TRUE(traj_controller_->has_active_traj()); @@ -792,130 +853,6 @@ TEST_P(TrajectoryControllerTestParameterized, timeout) executor.cancel(); } -/** - * @brief check if position error of revolute joints are angle_wraparound if configured so - */ -TEST_P(TrajectoryControllerTestParameterized, position_error_angle_wraparound) -{ - rclcpp::executors::MultiThreadedExecutor executor; - constexpr double k_p = 10.0; - std::vector params = {}; - SetUpAndActivateTrajectoryController(executor, params, true, k_p, 0.0, true); - subscribeToState(); - - size_t n_joints = joint_names_.size(); - - // send msg - constexpr auto FIRST_POINT_TIME = std::chrono::milliseconds(250); - builtin_interfaces::msg::Duration time_from_start{rclcpp::Duration(FIRST_POINT_TIME)}; - // *INDENT-OFF* - std::vector> points{ - {{3.3, 4.4, 6.6}}, {{7.7, 8.8, 9.9}}, {{10.10, 11.11, 12.12}}}; - std::vector> points_velocities{ - {{0.01, 0.01, 0.01}}, {{0.05, 0.05, 0.05}}, {{0.06, 0.06, 0.06}}}; - // *INDENT-ON* - publish(time_from_start, points, rclcpp::Time(), {}, points_velocities); - traj_controller_->wait_for_trajectory(executor); - - // first update - updateController(rclcpp::Duration(FIRST_POINT_TIME)); - - // Spin to receive latest state - executor.spin_some(); - auto state_msg = getState(); - ASSERT_TRUE(state_msg); - - const auto allowed_delta = 0.1; - - // no update of state_interface - EXPECT_EQ(state_msg->feedback.positions, INITIAL_POS_JOINTS); - - // has the msg the correct vector sizes? - EXPECT_EQ(n_joints, state_msg->reference.positions.size()); - EXPECT_EQ(n_joints, state_msg->feedback.positions.size()); - EXPECT_EQ(n_joints, state_msg->error.positions.size()); - - // are the correct reference positions used? - EXPECT_NEAR(points[0][0], state_msg->reference.positions[0], allowed_delta); - EXPECT_NEAR(points[0][1], state_msg->reference.positions[1], allowed_delta); - EXPECT_NEAR(points[0][2], state_msg->reference.positions[2], 3 * allowed_delta); - - // is error.positions[2] angle_wraparound? - EXPECT_NEAR( - state_msg->error.positions[0], state_msg->reference.positions[0] - INITIAL_POS_JOINTS[0], EPS); - EXPECT_NEAR( - state_msg->error.positions[1], state_msg->reference.positions[1] - INITIAL_POS_JOINTS[1], EPS); - EXPECT_NEAR( - state_msg->error.positions[2], - state_msg->reference.positions[2] - INITIAL_POS_JOINTS[2] - 2 * M_PI, EPS); - - if (traj_controller_->has_position_command_interface()) - { - // check command interface - EXPECT_NEAR(points[0][0], joint_pos_[0], allowed_delta); - EXPECT_NEAR(points[0][1], joint_pos_[1], allowed_delta); - EXPECT_NEAR(points[0][2], joint_pos_[2], allowed_delta); - } - - if (traj_controller_->has_velocity_command_interface()) - { - // use_closed_loop_pid_adapter_ - if (traj_controller_->use_closed_loop_pid_adapter()) - { - // we expect u = k_p * (s_d-s) for positions[0] and positions[1] - EXPECT_NEAR( - k_p * (state_msg->reference.positions[0] - INITIAL_POS_JOINTS[0]), joint_vel_[0], - k_p * allowed_delta); - EXPECT_NEAR( - k_p * (state_msg->reference.positions[1] - INITIAL_POS_JOINTS[1]), joint_vel_[1], - k_p * allowed_delta); - // is error of positions[2] angle_wraparound? - EXPECT_GT(0.0, joint_vel_[2]); - EXPECT_NEAR( - k_p * (state_msg->reference.positions[2] - INITIAL_POS_JOINTS[2] - 2 * M_PI), joint_vel_[2], - k_p * allowed_delta); - } - else - { - // interpolated points_velocities only - // check command interface - EXPECT_LT(0.0, joint_vel_[0]); - EXPECT_LT(0.0, joint_vel_[1]); - EXPECT_LT(0.0, joint_vel_[2]); - } - } - - if (traj_controller_->has_effort_command_interface()) - { - // use_closed_loop_pid_adapter_ - if (traj_controller_->use_closed_loop_pid_adapter()) - { - // we expect u = k_p * (s_d-s) for positions[0] and positions[1] - EXPECT_NEAR( - k_p * (state_msg->reference.positions[0] - INITIAL_POS_JOINTS[0]), joint_eff_[0], - k_p * allowed_delta); - EXPECT_NEAR( - k_p * (state_msg->reference.positions[1] - INITIAL_POS_JOINTS[1]), joint_eff_[1], - k_p * allowed_delta); - // is error of positions[2] angle_wraparound? - EXPECT_GT(0.0, joint_eff_[2]); - EXPECT_NEAR( - k_p * (state_msg->reference.positions[2] - INITIAL_POS_JOINTS[2] - 2 * M_PI), joint_eff_[2], - k_p * allowed_delta); - } - else - { - // interpolated points_velocities only - // check command interface - EXPECT_LT(0.0, joint_eff_[0]); - EXPECT_LT(0.0, joint_eff_[1]); - EXPECT_LT(0.0, joint_eff_[2]); - } - } - - executor.cancel(); -} - /** * @brief check if use_closed_loop_pid is active */ @@ -944,7 +881,6 @@ TEST_P(TrajectoryControllerTestParameterized, velocity_error) { rclcpp::executors::MultiThreadedExecutor executor; SetUpAndActivateTrajectoryController(executor, {}, true); - subscribeToState(); size_t n_joints = joint_names_.size(); @@ -960,35 +896,34 @@ TEST_P(TrajectoryControllerTestParameterized, velocity_error) publish(time_from_start, points_positions, rclcpp::Time(), {}, points_velocities); traj_controller_->wait_for_trajectory(executor); - // first update - updateController(rclcpp::Duration(FIRST_POINT_TIME)); + updateControllerAsync(rclcpp::Duration(FIRST_POINT_TIME)); - // Spin to receive latest state - executor.spin_some(); - auto state_msg = getState(); - ASSERT_TRUE(state_msg); + // get states from class variables + auto state_feedback = traj_controller_->get_state_feedback(); + auto state_reference = traj_controller_->get_state_reference(); + auto state_error = traj_controller_->get_state_error(); // has the msg the correct vector sizes? - EXPECT_EQ(n_joints, state_msg->reference.positions.size()); - EXPECT_EQ(n_joints, state_msg->feedback.positions.size()); - EXPECT_EQ(n_joints, state_msg->error.positions.size()); + EXPECT_EQ(n_joints, state_reference.positions.size()); + EXPECT_EQ(n_joints, state_feedback.positions.size()); + EXPECT_EQ(n_joints, state_error.positions.size()); if (traj_controller_->has_velocity_state_interface()) { - EXPECT_EQ(n_joints, state_msg->reference.velocities.size()); - EXPECT_EQ(n_joints, state_msg->feedback.velocities.size()); - EXPECT_EQ(n_joints, state_msg->error.velocities.size()); + EXPECT_EQ(n_joints, state_reference.velocities.size()); + EXPECT_EQ(n_joints, state_feedback.velocities.size()); + EXPECT_EQ(n_joints, state_error.velocities.size()); } if (traj_controller_->has_acceleration_state_interface()) { - EXPECT_EQ(n_joints, state_msg->reference.accelerations.size()); - EXPECT_EQ(n_joints, state_msg->feedback.accelerations.size()); - EXPECT_EQ(n_joints, state_msg->error.accelerations.size()); + EXPECT_EQ(n_joints, state_reference.accelerations.size()); + EXPECT_EQ(n_joints, state_feedback.accelerations.size()); + EXPECT_EQ(n_joints, state_error.accelerations.size()); } // no change in state interface should happen if (traj_controller_->has_velocity_state_interface()) { - EXPECT_EQ(state_msg->feedback.velocities, INITIAL_VEL_JOINTS); + EXPECT_EQ(state_feedback.velocities, INITIAL_VEL_JOINTS); } // is the velocity error correct? if ( @@ -998,9 +933,9 @@ TEST_P(TrajectoryControllerTestParameterized, velocity_error) { // don't check against a value, because spline interpolation might overshoot depending on // interface combinations - EXPECT_GE(state_msg->error.velocities[0], points_velocities[0][0]); - EXPECT_GE(state_msg->error.velocities[1], points_velocities[0][1]); - EXPECT_GE(state_msg->error.velocities[2], points_velocities[0][2]); + EXPECT_GE(state_error.velocities[0], points_velocities[0][0]); + EXPECT_GE(state_error.velocities[1], points_velocities[0][1]); + EXPECT_GE(state_error.velocities[2], points_velocities[0][2]); } executor.cancel(); @@ -1016,6 +951,7 @@ TEST_P(TrajectoryControllerTestParameterized, test_jumbled_joint_order) SetUpAndActivateTrajectoryController(executor); std::vector points_positions = {1.0, 2.0, 3.0}; std::vector jumble_map = {1, 2, 0}; + double dt = 0.25; { trajectory_msgs::msg::JointTrajectory traj_msg; const std::vector jumbled_joint_names{ @@ -1025,29 +961,27 @@ TEST_P(TrajectoryControllerTestParameterized, test_jumbled_joint_order) traj_msg.header.stamp = rclcpp::Time(0); traj_msg.points.resize(1); - traj_msg.points[0].time_from_start = rclcpp::Duration::from_seconds(0.25); + traj_msg.points[0].time_from_start = rclcpp::Duration::from_seconds(dt); traj_msg.points[0].positions.resize(3); traj_msg.points[0].positions[0] = points_positions.at(jumble_map[0]); traj_msg.points[0].positions[1] = points_positions.at(jumble_map[1]); traj_msg.points[0].positions[2] = points_positions.at(jumble_map[2]); traj_msg.points[0].velocities.resize(3); - for (size_t i = 0; i < 3; i++) + traj_msg.points[0].accelerations.resize(3); + + for (size_t dof = 0; dof < 3; dof++) { - // factor 2 comes from the linear interpolation in the spline trajectory for constant - // acceleration - traj_msg.points[0].velocities[i] = - 2 * (traj_msg.points[0].positions[i] - joint_pos_[jumble_map[i]]) / 0.25; + traj_msg.points[0].velocities[dof] = + (traj_msg.points[0].positions[dof] - joint_pos_[jumble_map[dof]]) / dt; + traj_msg.points[0].accelerations[dof] = + (traj_msg.points[0].velocities[dof] - joint_vel_[jumble_map[dof]]) / dt; } trajectory_publisher_->publish(traj_msg); } traj_controller_->wait_for_trajectory(executor); - // update just before 0.25 seconds (shorter than the trajectory duration of 0.25 seconds, - // otherwise acceleration is zero from the spline trajectory) - // TODO(destogl): Make this time a bit shorter to increase stability on the CI? - // Currently COMMON_THRESHOLD is adjusted. - updateController(rclcpp::Duration::from_seconds(0.25 - 1e-3)); + updateControllerAsync(rclcpp::Duration::from_seconds(dt)); if (traj_controller_->has_position_command_interface()) { @@ -1068,19 +1002,9 @@ TEST_P(TrajectoryControllerTestParameterized, test_jumbled_joint_order) if (traj_controller_->has_acceleration_command_interface()) { - if (traj_controller_->has_velocity_state_interface()) - { - EXPECT_GT(0.0, joint_acc_[0]); - EXPECT_GT(0.0, joint_acc_[1]); - EXPECT_GT(0.0, joint_acc_[2]); - } - else - { - // no velocity state interface: no acceleration from trajectory sampling - EXPECT_EQ(0.0, joint_acc_[0]); - EXPECT_EQ(0.0, joint_acc_[1]); - EXPECT_EQ(0.0, joint_acc_[2]); - } + EXPECT_GT(0.0, joint_acc_[0]); + EXPECT_GT(0.0, joint_acc_[1]); + EXPECT_GT(0.0, joint_acc_[2]); } if (traj_controller_->has_effort_command_interface()) @@ -1106,37 +1030,42 @@ TEST_P(TrajectoryControllerTestParameterized, test_partial_joint_list) const double initial_joint1_cmd = joint_pos_[0]; const double initial_joint2_cmd = joint_pos_[1]; const double initial_joint3_cmd = joint_pos_[2]; + const double dt = 0.25; trajectory_msgs::msg::JointTrajectory traj_msg; { - std::vector partial_joint_names{joint_names_[1], joint_names_[0]}; + std::vector jumble_map = {1, 0}; + std::vector partial_joint_names{ + joint_names_[jumble_map[0]], joint_names_[jumble_map[1]]}; traj_msg.joint_names = partial_joint_names; traj_msg.header.stamp = rclcpp::Time(0); traj_msg.points.resize(1); - traj_msg.points[0].time_from_start = rclcpp::Duration::from_seconds(0.25); + traj_msg.points[0].time_from_start = rclcpp::Duration::from_seconds(dt); traj_msg.points[0].positions.resize(2); traj_msg.points[0].positions[0] = 2.0; traj_msg.points[0].positions[1] = 1.0; traj_msg.points[0].velocities.resize(2); - traj_msg.points[0].velocities[0] = - std::copysign(2.0, traj_msg.points[0].positions[0] - initial_joint2_cmd); - traj_msg.points[0].velocities[1] = - std::copysign(1.0, traj_msg.points[0].positions[1] - initial_joint1_cmd); + traj_msg.points[0].accelerations.resize(2); + for (size_t dof = 0; dof < 2; dof++) + { + traj_msg.points[0].velocities[dof] = + (traj_msg.points[0].positions[dof] - joint_pos_[jumble_map[dof]]) / dt; + traj_msg.points[0].accelerations[dof] = + (traj_msg.points[0].velocities[dof] - joint_vel_[jumble_map[dof]]) / dt; + } trajectory_publisher_->publish(traj_msg); } traj_controller_->wait_for_trajectory(executor); - updateController(rclcpp::Duration::from_seconds(0.25)); - - double threshold = 0.001; + updateControllerAsync(rclcpp::Duration::from_seconds(dt)); if (traj_controller_->has_position_command_interface()) { - EXPECT_NEAR(traj_msg.points[0].positions[1], joint_pos_[0], threshold); - EXPECT_NEAR(traj_msg.points[0].positions[0], joint_pos_[1], threshold); - EXPECT_NEAR(initial_joint3_cmd, joint_pos_[2], threshold) + EXPECT_NEAR(traj_msg.points[0].positions[1], joint_pos_[0], COMMON_THRESHOLD); + EXPECT_NEAR(traj_msg.points[0].positions[0], joint_pos_[1], COMMON_THRESHOLD); + EXPECT_NEAR(initial_joint3_cmd, joint_pos_[2], COMMON_THRESHOLD) << "Joint 3 command should be current position"; } @@ -1148,7 +1077,7 @@ TEST_P(TrajectoryControllerTestParameterized, test_partial_joint_list) is_same_sign_or_zero(traj_msg.points[0].positions[0] - initial_joint2_cmd, joint_vel_[0])); EXPECT_TRUE( is_same_sign_or_zero(traj_msg.points[0].positions[1] - initial_joint1_cmd, joint_vel_[1])); - EXPECT_NEAR(0.0, joint_vel_[2], threshold) + EXPECT_NEAR(0.0, joint_vel_[2], COMMON_THRESHOLD) << "Joint 3 velocity should be 0.0 since it's not in the goal"; } @@ -1156,24 +1085,15 @@ TEST_P(TrajectoryControllerTestParameterized, test_partial_joint_list) { // estimate the sign of the acceleration // joint rotates forward - if (traj_controller_->has_velocity_state_interface()) - { - EXPECT_TRUE( - is_same_sign_or_zero(traj_msg.points[0].positions[0] - initial_joint2_cmd, joint_acc_[0])) - << "Joint1: " << traj_msg.points[0].positions[0] - initial_joint2_cmd << " vs. " - << joint_acc_[0]; - EXPECT_TRUE( - is_same_sign_or_zero(traj_msg.points[0].positions[1] - initial_joint1_cmd, joint_acc_[1])) - << "Joint2: " << traj_msg.points[0].positions[1] - initial_joint1_cmd << " vs. " - << joint_acc_[1]; - } - else - { - // no velocity state interface: no acceleration from trajectory sampling - EXPECT_EQ(0.0, joint_acc_[0]); - EXPECT_EQ(0.0, joint_acc_[1]); - } - EXPECT_NEAR(0.0, joint_acc_[2], threshold) + EXPECT_TRUE( + is_same_sign_or_zero(traj_msg.points[0].positions[0] - initial_joint2_cmd, joint_acc_[0])) + << "Joint1: " << traj_msg.points[0].positions[0] - initial_joint2_cmd << " vs. " + << joint_acc_[0]; + EXPECT_TRUE( + is_same_sign_or_zero(traj_msg.points[0].positions[1] - initial_joint1_cmd, joint_acc_[1])) + << "Joint2: " << traj_msg.points[0].positions[1] - initial_joint1_cmd << " vs. " + << joint_acc_[1]; + EXPECT_NEAR(0.0, joint_acc_[2], COMMON_THRESHOLD) << "Joint 3 acc should be 0.0 since it's not in the goal"; } @@ -1185,7 +1105,7 @@ TEST_P(TrajectoryControllerTestParameterized, test_partial_joint_list) is_same_sign_or_zero(traj_msg.points[0].positions[0] - initial_joint2_cmd, joint_eff_[0])); EXPECT_TRUE( is_same_sign_or_zero(traj_msg.points[0].positions[1] - initial_joint1_cmd, joint_eff_[1])); - EXPECT_NEAR(0.0, joint_eff_[2], threshold) + EXPECT_NEAR(0.0, joint_eff_[2], COMMON_THRESHOLD) << "Joint 3 effort should be 0.0 since it's not in the goal"; } @@ -1227,47 +1147,45 @@ TEST_P(TrajectoryControllerTestParameterized, test_partial_joint_list_not_allowe traj_controller_->wait_for_trajectory(executor); // update for 0.5 seconds - updateController(rclcpp::Duration::from_seconds(0.25)); - - double threshold = 0.001; + updateControllerAsync(rclcpp::Duration::from_seconds(0.25)); if (traj_controller_->has_position_command_interface()) { - EXPECT_NEAR(initial_joint1_cmd, joint_pos_[0], threshold) + EXPECT_NEAR(initial_joint1_cmd, joint_pos_[0], COMMON_THRESHOLD) << "All joints command should be current position because goal was rejected"; - EXPECT_NEAR(initial_joint2_cmd, joint_pos_[1], threshold) + EXPECT_NEAR(initial_joint2_cmd, joint_pos_[1], COMMON_THRESHOLD) << "All joints command should be current position because goal was rejected"; - EXPECT_NEAR(initial_joint3_cmd, joint_pos_[2], threshold) + EXPECT_NEAR(initial_joint3_cmd, joint_pos_[2], COMMON_THRESHOLD) << "All joints command should be current position because goal was rejected"; } if (traj_controller_->has_velocity_command_interface()) { - EXPECT_NEAR(INITIAL_VEL_JOINTS[0], joint_vel_[0], threshold) + EXPECT_NEAR(INITIAL_VEL_JOINTS[0], joint_vel_[0], COMMON_THRESHOLD) << "All joints velocities should be 0.0 because goal was rejected"; - EXPECT_NEAR(INITIAL_VEL_JOINTS[1], joint_vel_[1], threshold) + EXPECT_NEAR(INITIAL_VEL_JOINTS[1], joint_vel_[1], COMMON_THRESHOLD) << "All joints velocities should be 0.0 because goal was rejected"; - EXPECT_NEAR(INITIAL_VEL_JOINTS[2], joint_vel_[2], threshold) + EXPECT_NEAR(INITIAL_VEL_JOINTS[2], joint_vel_[2], COMMON_THRESHOLD) << "All joints velocities should be 0.0 because goal was rejected"; } if (traj_controller_->has_acceleration_command_interface()) { - EXPECT_NEAR(INITIAL_ACC_JOINTS[0], joint_acc_[0], threshold) + EXPECT_NEAR(INITIAL_ACC_JOINTS[0], joint_acc_[0], COMMON_THRESHOLD) << "All joints accelerations should be 0.0 because goal was rejected"; - EXPECT_NEAR(INITIAL_ACC_JOINTS[1], joint_acc_[1], threshold) + EXPECT_NEAR(INITIAL_ACC_JOINTS[1], joint_acc_[1], COMMON_THRESHOLD) << "All joints accelerations should be 0.0 because goal was rejected"; - EXPECT_NEAR(INITIAL_ACC_JOINTS[2], joint_acc_[2], threshold) + EXPECT_NEAR(INITIAL_ACC_JOINTS[2], joint_acc_[2], COMMON_THRESHOLD) << "All joints accelerations should be 0.0 because goal was rejected"; } if (traj_controller_->has_effort_command_interface()) { - EXPECT_NEAR(INITIAL_EFF_JOINTS[0], joint_eff_[0], threshold) + EXPECT_NEAR(INITIAL_EFF_JOINTS[0], joint_eff_[0], COMMON_THRESHOLD) << "All joints efforts should be 0.0 because goal was rejected"; - EXPECT_NEAR(INITIAL_EFF_JOINTS[1], joint_eff_[1], threshold) + EXPECT_NEAR(INITIAL_EFF_JOINTS[1], joint_eff_[1], COMMON_THRESHOLD) << "All joints efforts should be 0.0 because goal was rejected"; - EXPECT_NEAR(INITIAL_EFF_JOINTS[2], joint_eff_[2], threshold) + EXPECT_NEAR(INITIAL_EFF_JOINTS[2], joint_eff_[2], COMMON_THRESHOLD) << "All joints efforts should be 0.0 because goal was rejected"; } @@ -1408,8 +1326,6 @@ TEST_P(TrajectoryControllerTestParameterized, test_trajectory_replace) rclcpp::Parameter partial_joints_parameters("allow_partial_joints_goal", true); SetUpAndActivateTrajectoryController(executor, {partial_joints_parameters}); - subscribeToState(); - std::vector> points_old{{{2., 3., 4.}}}; std::vector> points_old_velocities{{{0.2, 0.3, 0.4}}}; std::vector> points_partial_new{{1.5}}; @@ -1424,8 +1340,8 @@ TEST_P(TrajectoryControllerTestParameterized, test_trajectory_replace) expected_actual.velocities = {points_old_velocities[0].begin(), points_old_velocities[0].end()}; expected_desired.velocities = {points_old_velocities[0].begin(), points_old_velocities[0].end()}; // Check that we reached end of points_old trajectory - // Denis: delta was 0.1 with 0.2 works for me - waitAndCompareState(expected_actual, expected_desired, executor, rclcpp::Duration(delay), 0.2); + auto end_time = + waitAndCompareState(expected_actual, expected_desired, executor, rclcpp::Duration(delay), 0.1); RCLCPP_INFO(traj_controller_->get_node()->get_logger(), "Sending new trajectory"); points_partial_new_velocities[0][0] = @@ -1440,7 +1356,8 @@ TEST_P(TrajectoryControllerTestParameterized, test_trajectory_replace) expected_desired.velocities[1] = 0.0; expected_desired.velocities[2] = 0.0; expected_actual = expected_desired; - waitAndCompareState(expected_actual, expected_desired, executor, rclcpp::Duration(delay), 0.1); + waitAndCompareState( + expected_actual, expected_desired, executor, rclcpp::Duration(delay), 0.1, end_time); } /** @@ -1450,7 +1367,6 @@ TEST_P(TrajectoryControllerTestParameterized, test_ignore_old_trajectory) { rclcpp::executors::SingleThreadedExecutor executor; SetUpAndActivateTrajectoryController(executor, {}); - subscribeToState(); // TODO(anyone): add expectations for velocities and accelerations std::vector> points_old{{{2., 3., 4.}, {4., 5., 6.}}}; @@ -1464,7 +1380,8 @@ TEST_P(TrajectoryControllerTestParameterized, test_ignore_old_trajectory) expected_actual.positions = {points_old[0].begin(), points_old[0].end()}; expected_desired = expected_actual; // Check that we reached end of points_old[0] trajectory - waitAndCompareState(expected_actual, expected_desired, executor, rclcpp::Duration(delay), 0.1); + auto end_time = + waitAndCompareState(expected_actual, expected_desired, executor, rclcpp::Duration(delay), 0.1); RCLCPP_INFO(traj_controller_->get_node()->get_logger(), "Sending new trajectory in the past"); // New trajectory will end before current time @@ -1473,14 +1390,14 @@ TEST_P(TrajectoryControllerTestParameterized, test_ignore_old_trajectory) expected_actual.positions = {points_old[1].begin(), points_old[1].end()}; expected_desired = expected_actual; publish(time_from_start, points_new, new_traj_start); - waitAndCompareState(expected_actual, expected_desired, executor, rclcpp::Duration(delay), 0.1); + waitAndCompareState( + expected_actual, expected_desired, executor, rclcpp::Duration(delay), 0.1, end_time); } TEST_P(TrajectoryControllerTestParameterized, test_ignore_partial_old_trajectory) { rclcpp::executors::SingleThreadedExecutor executor; SetUpAndActivateTrajectoryController(executor, {}); - subscribeToState(); std::vector> points_old{{{2., 3., 4.}, {4., 5., 6.}}}; std::vector> points_new{{{-1., -2., -3.}, {-2., -4., -6.}}}; @@ -1493,19 +1410,20 @@ TEST_P(TrajectoryControllerTestParameterized, test_ignore_partial_old_trajectory expected_actual.positions = {points_old[0].begin(), points_old[0].end()}; expected_desired = expected_actual; // Check that we reached end of points_old[0]trajectory - waitAndCompareState(expected_actual, expected_desired, executor, rclcpp::Duration(delay), 0.1); + auto end_time = + waitAndCompareState(expected_actual, expected_desired, executor, rclcpp::Duration(delay), 0.1); // send points_new before the old trajectory is finished RCLCPP_INFO( traj_controller_->get_node()->get_logger(), "Sending new trajectory partially in the past"); // New trajectory first point is in the past, second is in the future - rclcpp::Time new_traj_start = - rclcpp::Clock(RCL_STEADY_TIME).now() - delay - std::chrono::milliseconds(100); + rclcpp::Time new_traj_start = end_time - delay - std::chrono::milliseconds(100); publish(time_from_start, points_new, new_traj_start); // it should not have accepted the new goal but finish the old one expected_actual.positions = {points_old[1].begin(), points_old[1].end()}; expected_desired.positions = {points_old[1].begin(), points_old[1].end()}; - waitAndCompareState(expected_actual, expected_desired, executor, rclcpp::Duration(delay), 0.1); + waitAndCompareState( + expected_actual, expected_desired, executor, rclcpp::Duration(delay), 0.1, end_time); } TEST_P(TrajectoryControllerTestParameterized, test_execute_partial_traj_in_future) @@ -1513,7 +1431,6 @@ TEST_P(TrajectoryControllerTestParameterized, test_execute_partial_traj_in_futur rclcpp::Parameter partial_joints_parameters("allow_partial_joints_goal", true); rclcpp::executors::SingleThreadedExecutor executor; SetUpAndActivateTrajectoryController(executor, {partial_joints_parameters}); - subscribeToState(); RCLCPP_WARN( traj_controller_->get_node()->get_logger(), @@ -1538,7 +1455,8 @@ TEST_P(TrajectoryControllerTestParameterized, test_execute_partial_traj_in_futur expected_actual.positions = {full_traj[0].begin(), full_traj[0].end()}; expected_desired = expected_actual; // Check that we reached end of points_old[0]trajectory and are starting points_old[1] - waitAndCompareState(expected_actual, expected_desired, executor, rclcpp::Duration(delay), 0.1); + auto end_time = + waitAndCompareState(expected_actual, expected_desired, executor, rclcpp::Duration(delay), 0.1); // Send partial trajectory starting after full trajecotry is complete RCLCPP_INFO(traj_controller_->get_node()->get_logger(), "Sending new trajectory in the future"); @@ -1551,28 +1469,21 @@ TEST_P(TrajectoryControllerTestParameterized, test_execute_partial_traj_in_futur expected_desired = expected_actual; waitAndCompareState( - expected_actual, expected_desired, executor, rclcpp::Duration(delay * (2 + 2)), 0.1); + expected_actual, expected_desired, executor, rclcpp::Duration(delay * (2 + 2)), 0.1, end_time); } -// TODO(destogl) this test fails with errors -// second publish() gives an error, because end time is before current time -// as well as -// 2: The difference between joint_state_pos_[0] and joint_pos_[0] is 0.02999799000000003, -// which exceeds COMMON_THRESHOLD, where -// 2: joint_state_pos_[0] evaluates to 6.2999999999999998, -// 2: joint_pos_[0] evaluates to 6.2700020099999998, and -// 2: COMMON_THRESHOLD evaluates to 0.0011000000000000001. -// 2: [ FAILED ] PositionTrajectoryControllers/TrajectoryControllerTestParameterized. -// test_jump_when_state_tracking_error_updated/0, where GetParam() = -// ({ "position" }, { "position" }) (3372 ms) - -#if 0 TEST_P(TrajectoryControllerTestParameterized, test_jump_when_state_tracking_error_updated) { rclcpp::executors::SingleThreadedExecutor executor; // default if false so it will not be actually set parameter rclcpp::Parameter is_open_loop_parameters("open_loop_control", false); - SetUpAndActivateTrajectoryController(executor, {is_open_loop_parameters}, true); + SetUpAndActivateTrajectoryController(executor, {is_open_loop_parameters}, true); + + if (traj_controller_->has_position_command_interface() == false) + { + // only makes sense with position command interface + return; + } // goal setup std::vector first_goal = {3.3, 4.4, 5.5}; @@ -1585,95 +1496,95 @@ TEST_P(TrajectoryControllerTestParameterized, test_jump_when_state_tracking_erro builtin_interfaces::msg::Duration time_from_start; time_from_start.sec = 1; time_from_start.nanosec = 0; + double trajectory_frac = rclcpp::Duration::from_seconds(0.01).seconds() / + (time_from_start.sec + time_from_start.nanosec * 1e-9); std::vector> points{{first_goal}}; - publish(time_from_start, points, - rclcpp::Time(0.0, 0.0, RCL_STEADY_TIME), {}, first_goal_velocities); + publish( + time_from_start, points, rclcpp::Time(0.0, 0.0, RCL_STEADY_TIME), {}, first_goal_velocities); traj_controller_->wait_for_trajectory(executor); - updateController(rclcpp::Duration::from_seconds(1.1)); + updateControllerAsync(rclcpp::Duration::from_seconds(1.1)); - if (traj_controller_->has_position_command_interface()) - { - // JTC is executing trajectory in open-loop therefore: - // - internal state does not have to be updated (in this test-case it shouldn't) - // - internal command is updated - EXPECT_NEAR(INITIAL_POS_JOINT1, joint_state_pos_[0], COMMON_THRESHOLD); - EXPECT_NEAR(first_goal[0], joint_pos_[0], COMMON_THRESHOLD); - - // State interface should have offset from the command before starting a new trajectory - joint_state_pos_[0] = first_goal[0] - state_from_command_offset; - - // Move joint further in the same direction as before (to the second goal) - points = {{second_goal}}; - publish(time_from_start, points, - rclcpp::Time(1.0, 0.0, RCL_STEADY_TIME), {}, second_goal_velocities); - traj_controller_->wait_for_trajectory(executor); - - // One the first update(s) there should be a "jump" in opposite direction from command - // (towards the state value) - EXPECT_NEAR(first_goal[0], joint_pos_[0], COMMON_THRESHOLD); - updateController(rclcpp::Duration::from_seconds(0.01)); - // Expect backward commands at first - EXPECT_NEAR(joint_state_pos_[0], joint_pos_[0], state_from_command_offset + COMMON_THRESHOLD); - EXPECT_GT(joint_pos_[0], joint_state_pos_[0]); - EXPECT_LT(joint_pos_[0], first_goal[0]); - updateController(rclcpp::Duration::from_seconds(0.01)); - EXPECT_GT(joint_pos_[0], joint_state_pos_[0]); - EXPECT_LT(joint_pos_[0], first_goal[0]); - updateController(rclcpp::Duration::from_seconds(0.01)); - EXPECT_GT(joint_pos_[0], joint_state_pos_[0]); - EXPECT_LT(joint_pos_[0], first_goal[0]); - - // Finally the second goal will be commanded/reached - updateController(rclcpp::Duration::from_seconds(1.1)); - EXPECT_NEAR(second_goal[0], joint_pos_[0], COMMON_THRESHOLD); - - // State interface should have offset from the command before starting a new trajectory - joint_state_pos_[0] = second_goal[0] - state_from_command_offset; - - // Move joint back to the first goal - points = {{first_goal}}; - publish(time_from_start, points, rclcpp::Time(0.0, 0.0, RCL_STEADY_TIME)); - traj_controller_->wait_for_trajectory(executor); - - // One the first update(s) there should be a "jump" in the goal direction from command - // (towards the state value) - EXPECT_NEAR(second_goal[0], joint_pos_[0], COMMON_THRESHOLD); - updateController(rclcpp::Duration::from_seconds(0.01)); - // Expect backward commands at first - EXPECT_NEAR(joint_state_pos_[0], joint_pos_[0], COMMON_THRESHOLD); - EXPECT_LT(joint_pos_[0], joint_state_pos_[0]); - EXPECT_GT(joint_pos_[0], first_goal[0]); - updateController(rclcpp::Duration::from_seconds(0.01)); - EXPECT_LT(joint_pos_[0], joint_state_pos_[0]); - EXPECT_GT(joint_pos_[0], first_goal[0]); - updateController(rclcpp::Duration::from_seconds(0.01)); - EXPECT_LT(joint_pos_[0], joint_state_pos_[0]); - EXPECT_GT(joint_pos_[0], first_goal[0]); - - // Finally the first goal will be commanded/reached - updateController(rclcpp::Duration::from_seconds(1.1)); - EXPECT_NEAR(first_goal[0], joint_pos_[0], COMMON_THRESHOLD); - } + // JTC is executing trajectory in open-loop therefore: + // - internal state does not have to be updated (in this test-case it shouldn't) + // - internal command is updated + EXPECT_NEAR(INITIAL_POS_JOINT1, joint_state_pos_[0], COMMON_THRESHOLD); + EXPECT_NEAR(first_goal[0], joint_pos_[0], COMMON_THRESHOLD); + + // State interface should have offset from the command before starting a new trajectory + joint_state_pos_[0] = first_goal[0] - state_from_command_offset; + + // Move joint further in the same direction as before (to the second goal) + points = {{second_goal}}; + publish(time_from_start, points, rclcpp::Time(0, 0, RCL_STEADY_TIME), {}, second_goal_velocities); + traj_controller_->wait_for_trajectory(executor); + + // One the first update(s) there should be a "jump" in opposite direction from command + // (towards the state value) + EXPECT_NEAR(first_goal[0], joint_pos_[0], COMMON_THRESHOLD); + auto end_time = updateControllerAsync(rclcpp::Duration::from_seconds(0.01)); + // Expect backward commands at first, consider advancement of the trajectory + // exact value is not directly predictable, because of the spline interpolation -> increase + // tolerance + EXPECT_NEAR( + joint_state_pos_[0] + (second_goal[0] - joint_state_pos_[0]) * trajectory_frac, joint_pos_[0], + 0.1); + EXPECT_GT(joint_pos_[0], joint_state_pos_[0]); + EXPECT_LT(joint_pos_[0], first_goal[0]); + end_time = updateControllerAsync(rclcpp::Duration::from_seconds(0.01), end_time); + EXPECT_GT(joint_pos_[0], joint_state_pos_[0]); + EXPECT_LT(joint_pos_[0], first_goal[0]); + end_time = updateControllerAsync(rclcpp::Duration::from_seconds(0.01), end_time); + EXPECT_GT(joint_pos_[0], joint_state_pos_[0]); + EXPECT_LT(joint_pos_[0], first_goal[0]); + + // Finally the second goal will be commanded/reached + updateControllerAsync(rclcpp::Duration::from_seconds(1.1), end_time); + EXPECT_NEAR(second_goal[0], joint_pos_[0], COMMON_THRESHOLD); + + // State interface should have offset from the command before starting a new trajectory + joint_state_pos_[0] = second_goal[0] - state_from_command_offset; + + // Move joint back to the first goal + points = {{first_goal}}; + publish(time_from_start, points, rclcpp::Time(0.0, 0.0, RCL_STEADY_TIME)); + traj_controller_->wait_for_trajectory(executor); + + // One the first update(s) there should be a "jump" in the goal direction from command + // (towards the state value) + EXPECT_NEAR(second_goal[0], joint_pos_[0], COMMON_THRESHOLD); + end_time = updateControllerAsync(rclcpp::Duration::from_seconds(0.01)); + // Expect backward commands at first, consider advancement of the trajectory + EXPECT_NEAR( + joint_state_pos_[0] + (first_goal[0] - joint_state_pos_[0]) * trajectory_frac, joint_pos_[0], + COMMON_THRESHOLD); + EXPECT_LT(joint_pos_[0], joint_state_pos_[0]); + EXPECT_GT(joint_pos_[0], first_goal[0]); + end_time = updateControllerAsync(rclcpp::Duration::from_seconds(0.01), end_time); + EXPECT_LT(joint_pos_[0], joint_state_pos_[0]); + EXPECT_GT(joint_pos_[0], first_goal[0]); + end_time = updateControllerAsync(rclcpp::Duration::from_seconds(0.01), end_time); + EXPECT_LT(joint_pos_[0], joint_state_pos_[0]); + EXPECT_GT(joint_pos_[0], first_goal[0]); + + // Finally the first goal will be commanded/reached + updateControllerAsync(rclcpp::Duration::from_seconds(1.1), end_time); + EXPECT_NEAR(first_goal[0], joint_pos_[0], COMMON_THRESHOLD); executor.cancel(); } -#endif - -// TODO(destogl) this test fails -// 2: The difference between second_goal[0] and joint_pos_[0] is 0.032986635000000319, -// which exceeds COMMON_THRESHOLD, where -// 2: second_goal[0] evaluates to 6.5999999999999996, -// 2: joint_pos_[0] evaluates to 6.5670133649999993, and -// 2: COMMON_THRESHOLD evaluates to 0.0011000000000000001. -// 2: [ FAILED ] PositionTrajectoryControllers/TrajectoryControllerTestParameterized. -// test_no_jump_when_state_tracking_error_not_updated/1, where GetParam() = -// ({ "position" }, { "position", "velocity" }) (3374 ms) -#if 0 + TEST_P(TrajectoryControllerTestParameterized, test_no_jump_when_state_tracking_error_not_updated) { rclcpp::executors::SingleThreadedExecutor executor; + // set open loop to true, this should change behavior from above rclcpp::Parameter is_open_loop_parameters("open_loop_control", true); - SetUpAndActivateTrajectoryController(executor, {is_open_loop_parameters}, true); + SetUpAndActivateTrajectoryController(executor, {is_open_loop_parameters}, true); + + if (traj_controller_->has_position_command_interface() == false) + { + // only makes sense with position command interface + return; + } // goal setup std::vector first_goal = {3.3, 4.4, 5.5}; @@ -1684,77 +1595,79 @@ TEST_P(TrajectoryControllerTestParameterized, test_no_jump_when_state_tracking_e builtin_interfaces::msg::Duration time_from_start; time_from_start.sec = 1; time_from_start.nanosec = 0; + double trajectory_frac = rclcpp::Duration::from_seconds(0.01).seconds() / + (time_from_start.sec + time_from_start.nanosec * 1e-9); std::vector> points{{first_goal}}; publish(time_from_start, points, rclcpp::Time(0.0, 0.0, RCL_STEADY_TIME)); traj_controller_->wait_for_trajectory(executor); - updateController(rclcpp::Duration::from_seconds(1.1)); + updateControllerAsync(rclcpp::Duration::from_seconds(1.1)); - if (traj_controller_->has_position_command_interface()) - { - // JTC is executing trajectory in open-loop therefore: - // - internal state does not have to be updated (in this test-case it shouldn't) - // - internal command is updated - EXPECT_NEAR(INITIAL_POS_JOINT1, joint_state_pos_[0], COMMON_THRESHOLD); - EXPECT_NEAR(first_goal[0], joint_pos_[0], COMMON_THRESHOLD); - - // State interface should have offset from the command before starting a new trajectory - joint_state_pos_[0] = first_goal[0] - state_from_command_offset; - - // Move joint further in the same direction as before (to the second goal) - points = {{second_goal}}; - publish(time_from_start, points, rclcpp::Time(0.0, 0.0, RCL_STEADY_TIME)); - traj_controller_->wait_for_trajectory(executor); - - // One the first update(s) there **should not** be a "jump" in opposite direction from - // command (towards the state value) - EXPECT_NEAR(first_goal[0], joint_pos_[0], COMMON_THRESHOLD); - updateController(rclcpp::Duration::from_seconds(0.01)); - // There should not be backward commands - EXPECT_NEAR(first_goal[0], joint_pos_[0], COMMON_THRESHOLD); - EXPECT_GT(joint_pos_[0], first_goal[0]); - EXPECT_LT(joint_pos_[0], second_goal[0]); - updateController(rclcpp::Duration::from_seconds(0.01)); - EXPECT_GT(joint_pos_[0], first_goal[0]); - EXPECT_LT(joint_pos_[0], second_goal[0]); - updateController(rclcpp::Duration::from_seconds(0.01)); - EXPECT_GT(joint_pos_[0], first_goal[0]); - EXPECT_LT(joint_pos_[0], second_goal[0]); - - // Finally the second goal will be commanded/reached - updateController(rclcpp::Duration::from_seconds(1.1)); - EXPECT_NEAR(second_goal[0], joint_pos_[0], COMMON_THRESHOLD); - - // State interface should have offset from the command before starting a new trajectory - joint_state_pos_[0] = second_goal[0] - state_from_command_offset; - - // Move joint back to the first goal - points = {{first_goal}}; - publish(time_from_start, points, rclcpp::Time(0.0, 0.0, RCL_STEADY_TIME)); - traj_controller_->wait_for_trajectory(executor); - - // One the first update(s) there **should not** be a "jump" in the goal direction from - // command (towards the state value) - EXPECT_NEAR(second_goal[0], joint_pos_[0], COMMON_THRESHOLD); - updateController(rclcpp::Duration::from_seconds(0.01)); - // There should not be a jump toward commands - EXPECT_NEAR(second_goal[0], joint_pos_[0], COMMON_THRESHOLD); - EXPECT_LT(joint_pos_[0], second_goal[0]); - EXPECT_GT(joint_pos_[0], first_goal[0]); - updateController(rclcpp::Duration::from_seconds(0.01)); - EXPECT_GT(joint_pos_[0], first_goal[0]); - EXPECT_LT(joint_pos_[0], second_goal[0]); - updateController(rclcpp::Duration::from_seconds(0.01)); - EXPECT_GT(joint_pos_[0], first_goal[0]); - EXPECT_LT(joint_pos_[0], second_goal[0]); - - // Finally the first goal will be commanded/reached - updateController(rclcpp::Duration::from_seconds(1.1)); - EXPECT_NEAR(first_goal[0], joint_pos_[0], COMMON_THRESHOLD); - } + // JTC is executing trajectory in open-loop therefore: + // - internal state does not have to be updated (in this test-case it shouldn't) + // - internal command is updated + EXPECT_NEAR(INITIAL_POS_JOINT1, joint_state_pos_[0], COMMON_THRESHOLD); + EXPECT_NEAR(first_goal[0], joint_pos_[0], COMMON_THRESHOLD); + + // State interface should have offset from the command before starting a new trajectory + joint_state_pos_[0] = first_goal[0] - state_from_command_offset; + + // Move joint further in the same direction as before (to the second goal) + points = {{second_goal}}; + publish(time_from_start, points, rclcpp::Time(0.0, 0.0, RCL_STEADY_TIME)); + traj_controller_->wait_for_trajectory(executor); + + // One the first update(s) there **should not** be a "jump" in opposite direction from + // command (towards the state value) + EXPECT_NEAR(first_goal[0], joint_pos_[0], COMMON_THRESHOLD); + auto end_time = updateControllerAsync(rclcpp::Duration::from_seconds(0.01)); + // There should not be backward commands + EXPECT_NEAR( + first_goal[0] + (second_goal[0] - first_goal[0]) * trajectory_frac, joint_pos_[0], + COMMON_THRESHOLD); + EXPECT_GT(joint_pos_[0], first_goal[0]); + EXPECT_LT(joint_pos_[0], second_goal[0]); + end_time = updateControllerAsync(rclcpp::Duration::from_seconds(0.01), end_time); + EXPECT_GT(joint_pos_[0], first_goal[0]); + EXPECT_LT(joint_pos_[0], second_goal[0]); + end_time = updateControllerAsync(rclcpp::Duration::from_seconds(0.01), end_time); + EXPECT_GT(joint_pos_[0], first_goal[0]); + EXPECT_LT(joint_pos_[0], second_goal[0]); + + // Finally the second goal will be commanded/reached + updateControllerAsync(rclcpp::Duration::from_seconds(1.1), end_time); + EXPECT_NEAR(second_goal[0], joint_pos_[0], COMMON_THRESHOLD); + + // State interface should have offset from the command before starting a new trajectory + joint_state_pos_[0] = second_goal[0] - state_from_command_offset; + + // Move joint back to the first goal + points = {{first_goal}}; + publish(time_from_start, points, rclcpp::Time(0.0, 0.0, RCL_STEADY_TIME)); + traj_controller_->wait_for_trajectory(executor); + + // One the first update(s) there **should not** be a "jump" in the goal direction from + // command (towards the state value) + EXPECT_NEAR(second_goal[0], joint_pos_[0], COMMON_THRESHOLD); + end_time = updateControllerAsync(rclcpp::Duration::from_seconds(0.01), end_time); + // There should not be a jump toward commands + EXPECT_NEAR( + second_goal[0] + (first_goal[0] - second_goal[0]) * trajectory_frac, joint_pos_[0], + COMMON_THRESHOLD); + EXPECT_LT(joint_pos_[0], second_goal[0]); + EXPECT_GT(joint_pos_[0], first_goal[0]); + end_time = updateControllerAsync(rclcpp::Duration::from_seconds(0.01), end_time); + EXPECT_GT(joint_pos_[0], first_goal[0]); + EXPECT_LT(joint_pos_[0], second_goal[0]); + end_time = updateControllerAsync(rclcpp::Duration::from_seconds(0.01), end_time); + EXPECT_GT(joint_pos_[0], first_goal[0]); + EXPECT_LT(joint_pos_[0], second_goal[0]); + + // Finally the first goal will be commanded/reached + updateControllerAsync(rclcpp::Duration::from_seconds(1.1), end_time); + EXPECT_NEAR(first_goal[0], joint_pos_[0], COMMON_THRESHOLD); executor.cancel(); } -#endif // Testing that values are read from state interfaces when hardware is started for the first // time and hardware state has offset --> this is indicated by NaN values in command interfaces @@ -1902,7 +1815,7 @@ TEST_P(TrajectoryControllerTestParameterized, test_state_tolerances_fail) // *INDENT-ON* publish(time_from_start, points, rclcpp::Time(0, 0, RCL_STEADY_TIME), {}, points_velocities); traj_controller_->wait_for_trajectory(executor); - updateController(rclcpp::Duration(FIRST_POINT_TIME)); + updateControllerAsync(rclcpp::Duration(FIRST_POINT_TIME)); // it should have aborted and be holding now expectHoldingPoint(joint_state_pos_); @@ -1934,7 +1847,7 @@ TEST_P(TrajectoryControllerTestParameterized, test_goal_tolerances_fail) // *INDENT-ON* publish(time_from_start, points, rclcpp::Time(0, 0, RCL_STEADY_TIME), {}, points_velocities); traj_controller_->wait_for_trajectory(executor); - updateController(rclcpp::Duration(4 * FIRST_POINT_TIME)); + auto end_time = updateControllerAsync(rclcpp::Duration(4 * FIRST_POINT_TIME)); // it should have aborted and be holding now expectHoldingPoint(joint_state_pos_); @@ -1942,7 +1855,7 @@ TEST_P(TrajectoryControllerTestParameterized, test_goal_tolerances_fail) // what happens if we wait longer but it harms the tolerance again? auto hold_position = joint_state_pos_; joint_state_pos_.at(0) = -3.3; - updateController(rclcpp::Duration(FIRST_POINT_TIME)); + updateControllerAsync(rclcpp::Duration(FIRST_POINT_TIME), end_time); // it should be still holding the old point expectHoldingPoint(hold_position); } diff --git a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp index 3a7e7e5cf1..3c8e252067 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp +++ b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp @@ -21,7 +21,7 @@ #include #include -#include "gtest/gtest.h" +#include "gmock/gmock.h" #include "hardware_interface/types/hardware_interface_type_values.hpp" #include "joint_trajectory_controller/joint_trajectory_controller.hpp" @@ -29,7 +29,7 @@ namespace { -const double COMMON_THRESHOLD = 0.0011; // destogl: increased for 0.0001 for stable CI builds? +const double COMMON_THRESHOLD = 0.001; const double INITIAL_POS_JOINT1 = 1.1; const double INITIAL_POS_JOINT2 = 2.1; const double INITIAL_POS_JOINT3 = 3.1; @@ -151,6 +151,10 @@ class TestableJointTrajectoryController double get_cmd_timeout() { return cmd_timeout_; } + trajectory_msgs::msg::JointTrajectoryPoint get_state_feedback() { return state_current_; } + trajectory_msgs::msg::JointTrajectoryPoint get_state_reference() { return state_desired_; } + trajectory_msgs::msg::JointTrajectoryPoint get_state_error() { return state_error_; } + rclcpp::WaitSet joint_cmd_sub_wait_set_; }; @@ -233,21 +237,24 @@ class TrajectoryControllerTest : public ::testing::Test const std::vector initial_acc_joints = INITIAL_ACC_JOINTS, const std::vector initial_eff_joints = INITIAL_EFF_JOINTS) { - SetUpTrajectoryController(executor); - - // add this to simplify tests, can be overwritten by parameters - rclcpp::Parameter nonzero_vel_parameter("allow_nonzero_velocity_at_trajectory_end", true); - traj_controller_->get_node()->set_parameter(nonzero_vel_parameter); - - // set pid parameters before configure - SetPidParameters(k_p, ff, angle_wraparound); - - // set optional parameters - for (const auto & param : parameters) + auto has_nonzero_vel_param = + std::find_if( + parameters.begin(), parameters.end(), + [](const rclcpp::Parameter & param) { + return param.get_name() == "allow_nonzero_velocity_at_trajectory_end"; + }) != parameters.end(); + + std::vector parameters_local = parameters; + if (!has_nonzero_vel_param) { - traj_controller_->get_node()->set_parameter(param); + // add this to simplify tests, if not set already + parameters_local.emplace_back("allow_nonzero_velocity_at_trajectory_end", true); } + // read-only parameters have to be set before init -> won't be read otherwise + SetUpTrajectoryController(executor, parameters_local); + // set pid parameters before configure + SetPidParameters(k_p, ff, angle_wraparound); traj_controller_->get_node()->configure(); ActivateTrajectoryController( @@ -407,43 +414,85 @@ class TrajectoryControllerTest : public ::testing::Test trajectory_publisher_->publish(traj_msg); } - void updateController(rclcpp::Duration wait_time = rclcpp::Duration::from_seconds(0.2)) + /** + * @brief a wrapper for update() method of JTC, running synchronously with the clock + * @param wait_time - the time span for updating the controller + * @param update_rate - the rate at which the controller is updated + * + * @note use the faster updateControllerAsync() if no subscriptions etc. + * have to be used from the waitSet/executor + */ + void updateController( + rclcpp::Duration wait_time = rclcpp::Duration::from_seconds(0.2), + const rclcpp::Duration update_rate = rclcpp::Duration::from_seconds(0.01)) { auto clock = rclcpp::Clock(RCL_STEADY_TIME); const auto start_time = clock.now(); const auto end_time = start_time + wait_time; auto previous_time = start_time; - while (clock.now() < end_time) + while (clock.now() <= end_time) { auto now = clock.now(); traj_controller_->update(now, now - previous_time); previous_time = now; + std::this_thread::sleep_for(update_rate.to_chrono()); + } + } + + /** + * @brief a wrapper for update() method of JTC, running asynchronously from the clock + * @return the time at which the update finished + * @param wait_time - the time span for updating the controller + * @param start_time - the time at which the update should start + * @param update_rate - the rate at which the controller is updated + * + * @note this is faster than updateController() and can be used if no subscriptions etc. + * have to be used from the waitSet/executor + */ + rclcpp::Time updateControllerAsync( + rclcpp::Duration wait_time = rclcpp::Duration::from_seconds(0.2), + rclcpp::Time start_time = rclcpp::Time(0, 0, RCL_STEADY_TIME), + const rclcpp::Duration update_rate = rclcpp::Duration::from_seconds(0.01)) + { + if (start_time == rclcpp::Time(0, 0, RCL_STEADY_TIME)) + { + start_time = rclcpp::Clock(RCL_STEADY_TIME).now(); } + const auto end_time = start_time + wait_time; + auto time_counter = start_time; + while (time_counter <= end_time) + { + traj_controller_->update(time_counter, update_rate); + time_counter += update_rate; + } + return end_time; } - void waitAndCompareState( + rclcpp::Time waitAndCompareState( trajectory_msgs::msg::JointTrajectoryPoint expected_actual, trajectory_msgs::msg::JointTrajectoryPoint expected_desired, rclcpp::Executor & executor, - rclcpp::Duration controller_wait_time, double allowed_delta) + rclcpp::Duration controller_wait_time, double allowed_delta, + rclcpp::Time start_time = rclcpp::Time(0, 0, RCL_STEADY_TIME)) { { std::lock_guard guard(state_mutex_); state_msg_.reset(); } traj_controller_->wait_for_trajectory(executor); - updateController(controller_wait_time); - // Spin to receive latest state - executor.spin_some(); - auto state_msg = getState(); - ASSERT_TRUE(state_msg); + auto end_time = updateControllerAsync(controller_wait_time, start_time); + + // get states from class variables + auto state_feedback = traj_controller_->get_state_feedback(); + auto state_reference = traj_controller_->get_state_reference(); + for (size_t i = 0; i < expected_actual.positions.size(); ++i) { SCOPED_TRACE("Joint " + std::to_string(i)); // TODO(anyone): add checking for velocities and accelerations if (traj_controller_->has_position_command_interface()) { - EXPECT_NEAR(expected_actual.positions[i], state_msg->feedback.positions[i], allowed_delta); + EXPECT_NEAR(expected_actual.positions[i], state_feedback.positions[i], allowed_delta); } } @@ -453,10 +502,11 @@ class TrajectoryControllerTest : public ::testing::Test // TODO(anyone): add checking for velocities and accelerations if (traj_controller_->has_position_command_interface()) { - EXPECT_NEAR( - expected_desired.positions[i], state_msg->reference.positions[i], allowed_delta); + EXPECT_NEAR(expected_desired.positions[i], state_reference.positions[i], allowed_delta); } } + + return end_time; } std::shared_ptr getState() const @@ -573,6 +623,47 @@ class TrajectoryControllerTest : public ::testing::Test } } + /** + * @brief compares the joint names and interface types of the controller with the given ones + */ + void compare_joints( + std::vector state_joint_names, std::vector command_joint_names) + { + std::vector state_interface_names; + state_interface_names.reserve(state_joint_names.size() * state_interface_types_.size()); + for (const auto & joint : state_joint_names) + { + for (const auto & interface : state_interface_types_) + { + state_interface_names.push_back(joint + "/" + interface); + } + } + auto state_interfaces = traj_controller_->state_interface_configuration(); + EXPECT_EQ( + state_interfaces.type, controller_interface::interface_configuration_type::INDIVIDUAL); + EXPECT_EQ( + state_interfaces.names.size(), state_joint_names.size() * state_interface_types_.size()); + ASSERT_THAT(state_interfaces.names, testing::UnorderedElementsAreArray(state_interface_names)); + + std::vector command_interface_names; + command_interface_names.reserve(command_joint_names.size() * command_interface_types_.size()); + for (const auto & joint : command_joint_names) + { + for (const auto & interface : command_interface_types_) + { + command_interface_names.push_back(joint + "/" + interface); + } + } + auto command_interfaces = traj_controller_->command_interface_configuration(); + EXPECT_EQ( + command_interfaces.type, controller_interface::interface_configuration_type::INDIVIDUAL); + EXPECT_EQ( + command_interfaces.names.size(), + command_joint_names.size() * command_interface_types_.size()); + ASSERT_THAT( + command_interfaces.names, testing::UnorderedElementsAreArray(command_interface_names)); + } + std::string controller_name_; std::vector joint_names_; From fe0c91d4f36939866276d63c1d8f552544f6818f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Mon, 27 Nov 2023 12:32:27 +0100 Subject: [PATCH 152/238] joint_state_broadcaster: Add proper subscription to TestCustomInterfaceMappingUpdate (#859) --- .../test/test_joint_state_broadcaster.cpp | 21 +++++++++---------- .../test/test_joint_state_broadcaster.hpp | 3 +++ 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/joint_state_broadcaster/test/test_joint_state_broadcaster.cpp b/joint_state_broadcaster/test/test_joint_state_broadcaster.cpp index 3a74f599b4..b44152a453 100644 --- a/joint_state_broadcaster/test/test_joint_state_broadcaster.cpp +++ b/joint_state_broadcaster/test/test_joint_state_broadcaster.cpp @@ -531,19 +531,12 @@ TEST_F(JointStateBroadcasterTest, TestCustomInterfaceMappingUpdate) state_broadcaster_->get_node()->set_parameter( {std::string("map_interface_to_joint_state.") + HW_IF_POSITION, custom_interface_name_}); - // configure ok - ASSERT_EQ(state_broadcaster_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); - - ASSERT_EQ(state_broadcaster_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); - - ASSERT_EQ( - state_broadcaster_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)), - controller_interface::return_type::OK); + sensor_msgs::msg::JointState joint_state_msg; + activate_and_get_joint_state_message("joint_states", joint_state_msg); const size_t NUM_JOINTS = JOINT_NAMES.size(); // joint state initialized - const auto & joint_state_msg = state_broadcaster_->realtime_joint_state_publisher_->msg_; ASSERT_THAT(joint_state_msg.name, ElementsAreArray(JOINT_NAMES)); ASSERT_THAT(joint_state_msg.position, SizeIs(NUM_JOINTS)); ASSERT_EQ(joint_state_msg.position[0], custom_joint_value_); @@ -585,7 +578,8 @@ TEST_F(JointStateBroadcasterTest, UpdateTest) controller_interface::return_type::OK); } -void JointStateBroadcasterTest::test_published_joint_state_message(const std::string & topic) +void JointStateBroadcasterTest::activate_and_get_joint_state_message( + const std::string & topic, sensor_msgs::msg::JointState & joint_state_msg) { auto node_state = state_broadcaster_->get_node()->configure(); ASSERT_EQ(node_state.id(), lifecycle_msgs::msg::State::PRIMARY_STATE_INACTIVE); @@ -616,9 +610,14 @@ void JointStateBroadcasterTest::test_published_joint_state_message(const std::st "controller/broadcaster update loop"; // take message from subscription - sensor_msgs::msg::JointState joint_state_msg; rclcpp::MessageInfo msg_info; ASSERT_TRUE(subscription->take(joint_state_msg, msg_info)); +} + +void JointStateBroadcasterTest::test_published_joint_state_message(const std::string & topic) +{ + sensor_msgs::msg::JointState joint_state_msg; + activate_and_get_joint_state_message(topic, joint_state_msg); const size_t NUM_JOINTS = joint_names_.size(); ASSERT_THAT(joint_state_msg.name, SizeIs(NUM_JOINTS)); diff --git a/joint_state_broadcaster/test/test_joint_state_broadcaster.hpp b/joint_state_broadcaster/test/test_joint_state_broadcaster.hpp index 63cc7a5483..fcaa40e8d5 100644 --- a/joint_state_broadcaster/test/test_joint_state_broadcaster.hpp +++ b/joint_state_broadcaster/test/test_joint_state_broadcaster.hpp @@ -71,6 +71,9 @@ class JointStateBroadcasterTest : public ::testing::Test void test_published_dynamic_joint_state_message(const std::string & topic); + void activate_and_get_joint_state_message( + const std::string & topic, sensor_msgs::msg::JointState & msg); + protected: // dummy joint state values used for tests const std::vector joint_names_ = {"joint1", "joint2", "joint3"}; From b6841ead459f6efb76153e8474a3f5443d48d2b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Mon, 27 Nov 2023 12:54:41 +0100 Subject: [PATCH 153/238] Increase test coverage of interface configuration getters (#856) --- .../test_force_torque_sensor_broadcaster.cpp | 25 +++++++- .../test_force_torque_sensor_broadcaster.hpp | 2 +- .../test/test_forward_command_controller.cpp | 42 +++++++++++++ ...i_interface_forward_command_controller.cpp | 23 +++++++ .../test/test_gripper_controllers.cpp | 12 ++++ .../test/test_imu_sensor_broadcaster.cpp | 23 +++++++ .../test/test_joint_state_broadcaster.cpp | 62 ++++++++++++++++++- .../test/test_joint_state_broadcaster.hpp | 4 +- .../test/test_range_sensor_broadcaster.cpp | 27 +++++++- .../test/test_tricycle_controller.cpp | 15 +++++ 10 files changed, 228 insertions(+), 7 deletions(-) diff --git a/force_torque_sensor_broadcaster/test/test_force_torque_sensor_broadcaster.cpp b/force_torque_sensor_broadcaster/test/test_force_torque_sensor_broadcaster.cpp index bfe7561642..ce6a04ec1f 100644 --- a/force_torque_sensor_broadcaster/test/test_force_torque_sensor_broadcaster.cpp +++ b/force_torque_sensor_broadcaster/test/test_force_torque_sensor_broadcaster.cpp @@ -32,6 +32,8 @@ #include "rclcpp_lifecycle/node_interfaces/lifecycle_node_interface.hpp" using hardware_interface::LoanedStateInterface; +using testing::IsEmpty; +using testing::SizeIs; namespace { @@ -157,6 +159,12 @@ TEST_F(ForceTorqueSensorBroadcasterTest, SensorName_Configure_Success) // configure passed ASSERT_EQ(fts_broadcaster_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + + // check interface configuration + auto cmd_if_conf = fts_broadcaster_->command_interface_configuration(); + ASSERT_THAT(cmd_if_conf.names, IsEmpty()); + auto state_if_conf = fts_broadcaster_->state_interface_configuration(); + ASSERT_THAT(state_if_conf.names, SizeIs(6lu)); } TEST_F(ForceTorqueSensorBroadcasterTest, InterfaceNames_Configure_Success) @@ -175,7 +183,7 @@ TEST_F(ForceTorqueSensorBroadcasterTest, InterfaceNames_Configure_Success) ASSERT_EQ(fts_broadcaster_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); } -TEST_F(ForceTorqueSensorBroadcasterTest, SensorName_Activate_Success) +TEST_F(ForceTorqueSensorBroadcasterTest, SensorName_ActivateDeactivate_Success) { SetUpFTSBroadcaster(); @@ -186,6 +194,21 @@ TEST_F(ForceTorqueSensorBroadcasterTest, SensorName_Activate_Success) // configure and activate success ASSERT_EQ(fts_broadcaster_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); ASSERT_EQ(fts_broadcaster_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + + // check interface configuration + auto cmd_if_conf = fts_broadcaster_->command_interface_configuration(); + ASSERT_THAT(cmd_if_conf.names, IsEmpty()); + auto state_if_conf = fts_broadcaster_->state_interface_configuration(); + ASSERT_THAT(state_if_conf.names, SizeIs(6lu)); + + // deactivate passed + ASSERT_EQ(fts_broadcaster_->on_deactivate(rclcpp_lifecycle::State()), NODE_SUCCESS); + + // check interface configuration + cmd_if_conf = fts_broadcaster_->command_interface_configuration(); + ASSERT_THAT(cmd_if_conf.names, IsEmpty()); + state_if_conf = fts_broadcaster_->state_interface_configuration(); + ASSERT_THAT(state_if_conf.names, SizeIs(6lu)); // did not change } TEST_F(ForceTorqueSensorBroadcasterTest, SensorName_Update_Success) diff --git a/force_torque_sensor_broadcaster/test/test_force_torque_sensor_broadcaster.hpp b/force_torque_sensor_broadcaster/test/test_force_torque_sensor_broadcaster.hpp index 5477b3fa6f..fe5b0ab3ba 100644 --- a/force_torque_sensor_broadcaster/test/test_force_torque_sensor_broadcaster.hpp +++ b/force_torque_sensor_broadcaster/test/test_force_torque_sensor_broadcaster.hpp @@ -36,7 +36,7 @@ class FriendForceTorqueSensorBroadcaster FRIEND_TEST(ForceTorqueSensorBroadcasterTest, SensorNameParameterIsEmpty); FRIEND_TEST(ForceTorqueSensorBroadcasterTest, InterfaceNameParameterIsEmpty); - FRIEND_TEST(ForceTorqueSensorBroadcasterTest, ActivateSuccess); + FRIEND_TEST(ForceTorqueSensorBroadcasterTest, SensorName_ActivateDeactivate_Success); FRIEND_TEST(ForceTorqueSensorBroadcasterTest, UpdateTest); FRIEND_TEST(ForceTorqueSensorBroadcasterTest, SensorStatePublishTest); }; diff --git a/forward_command_controller/test/test_forward_command_controller.cpp b/forward_command_controller/test/test_forward_command_controller.cpp index 62d5512b4e..236cb14edd 100644 --- a/forward_command_controller/test/test_forward_command_controller.cpp +++ b/forward_command_controller/test/test_forward_command_controller.cpp @@ -34,6 +34,8 @@ #include "rclcpp_lifecycle/node_interfaces/lifecycle_node_interface.hpp" using hardware_interface::LoanedCommandInterface; +using testing::IsEmpty; +using testing::SizeIs; namespace { @@ -128,6 +130,13 @@ TEST_F(ForwardCommandControllerTest, ConfigureParamsSuccess) ASSERT_EQ( controller_->on_configure(rclcpp_lifecycle::State()), controller_interface::CallbackReturn::SUCCESS); + + // check interface configuration + auto cmd_if_conf = controller_->command_interface_configuration(); + EXPECT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); + ASSERT_THAT(cmd_if_conf.names, SizeIs(2lu)); + auto state_if_conf = controller_->state_interface_configuration(); + ASSERT_THAT(state_if_conf.names, IsEmpty()); } TEST_F(ForwardCommandControllerTest, ActivateWithWrongJointsNamesFails) @@ -173,9 +182,23 @@ TEST_F(ForwardCommandControllerTest, ActivateSuccess) ASSERT_EQ( controller_->on_configure(rclcpp_lifecycle::State()), controller_interface::CallbackReturn::SUCCESS); + + // check interface configuration + auto cmd_if_conf = controller_->command_interface_configuration(); + EXPECT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); + ASSERT_THAT(cmd_if_conf.names, SizeIs(joint_names_.size())); + auto state_if_conf = controller_->state_interface_configuration(); + ASSERT_THAT(state_if_conf.names, IsEmpty()); + ASSERT_EQ( controller_->on_activate(rclcpp_lifecycle::State()), controller_interface::CallbackReturn::SUCCESS); + + // check interface configuration + cmd_if_conf = controller_->command_interface_configuration(); + ASSERT_THAT(cmd_if_conf.names, SizeIs(joint_names_.size())); + state_if_conf = controller_->state_interface_configuration(); + ASSERT_THAT(state_if_conf.names, IsEmpty()); } TEST_F(ForwardCommandControllerTest, CommandSuccessTest) @@ -323,9 +346,22 @@ TEST_F(ForwardCommandControllerTest, ActivateDeactivateCommandsResetSuccess) auto node_state = controller_->configure(); ASSERT_EQ(node_state.id(), lifecycle_msgs::msg::State::PRIMARY_STATE_INACTIVE); + // check interface configuration + auto cmd_if_conf = controller_->command_interface_configuration(); + ASSERT_THAT(cmd_if_conf.names, SizeIs(joint_names_.size())); + EXPECT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); + auto state_if_conf = controller_->state_interface_configuration(); + ASSERT_THAT(state_if_conf.names, IsEmpty()); + node_state = controller_->get_node()->activate(); ASSERT_EQ(node_state.id(), lifecycle_msgs::msg::State::PRIMARY_STATE_ACTIVE); + // check interface configuration + cmd_if_conf = controller_->command_interface_configuration(); + ASSERT_THAT(cmd_if_conf.names, SizeIs(joint_names_.size())); + state_if_conf = controller_->state_interface_configuration(); + ASSERT_THAT(state_if_conf.names, IsEmpty()); + auto command_msg = std::make_shared(); command_msg->data = {10.0, 20.0, 30.0}; @@ -344,6 +380,12 @@ TEST_F(ForwardCommandControllerTest, ActivateDeactivateCommandsResetSuccess) node_state = controller_->get_node()->deactivate(); ASSERT_EQ(node_state.id(), lifecycle_msgs::msg::State::PRIMARY_STATE_INACTIVE); + // check interface configuration + cmd_if_conf = controller_->command_interface_configuration(); + ASSERT_THAT(cmd_if_conf.names, SizeIs(joint_names_.size())); // did not change + state_if_conf = controller_->state_interface_configuration(); + ASSERT_THAT(state_if_conf.names, IsEmpty()); + // command ptr should be reset (nullptr) after deactivation - same check as in `update` ASSERT_FALSE( controller_->rt_command_ptr_.readFromNonRT() && diff --git a/forward_command_controller/test/test_multi_interface_forward_command_controller.cpp b/forward_command_controller/test/test_multi_interface_forward_command_controller.cpp index 7826c85355..2d3b61e211 100644 --- a/forward_command_controller/test/test_multi_interface_forward_command_controller.cpp +++ b/forward_command_controller/test/test_multi_interface_forward_command_controller.cpp @@ -36,6 +36,8 @@ #include "rclcpp_lifecycle/node_interfaces/lifecycle_node_interface.hpp" using hardware_interface::LoanedCommandInterface; +using testing::IsEmpty; +using testing::SizeIs; namespace { @@ -148,6 +150,13 @@ TEST_F(MultiInterfaceForwardCommandControllerTest, ConfigureParamsSuccess) ASSERT_EQ( controller_->on_configure(rclcpp_lifecycle::State()), controller_interface::CallbackReturn::SUCCESS); + + // check interface configuration + auto cmd_if_conf = controller_->command_interface_configuration(); + ASSERT_THAT(cmd_if_conf.names, SizeIs(3lu)); + EXPECT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); + auto state_if_conf = controller_->state_interface_configuration(); + ASSERT_THAT(state_if_conf.names, IsEmpty()); } TEST_F(MultiInterfaceForwardCommandControllerTest, ActivateWithWrongJointsNamesFails) @@ -282,6 +291,13 @@ TEST_F(MultiInterfaceForwardCommandControllerTest, ActivateDeactivateCommandsRes { SetUpController(true); + // check interface configuration + auto cmd_if_conf = controller_->command_interface_configuration(); + ASSERT_THAT(cmd_if_conf.names, SizeIs(3lu)); + EXPECT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); + auto state_if_conf = controller_->state_interface_configuration(); + ASSERT_THAT(state_if_conf.names, IsEmpty()); + // send command auto command_ptr = std::make_shared(); command_ptr->data = {10.0, 20.0, 30.0}; @@ -300,6 +316,13 @@ TEST_F(MultiInterfaceForwardCommandControllerTest, ActivateDeactivateCommandsRes auto node_state = controller_->get_node()->deactivate(); ASSERT_EQ(node_state.id(), lifecycle_msgs::msg::State::PRIMARY_STATE_INACTIVE); + // check interface configuration + cmd_if_conf = controller_->command_interface_configuration(); + ASSERT_THAT(cmd_if_conf.names, SizeIs(3lu)); + EXPECT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); + state_if_conf = controller_->state_interface_configuration(); + ASSERT_THAT(state_if_conf.names, IsEmpty()); + // command ptr should be reset (nullptr) after deactivation - same check as in `update` ASSERT_FALSE( controller_->rt_command_ptr_.readFromNonRT() && diff --git a/gripper_controllers/test/test_gripper_controllers.cpp b/gripper_controllers/test/test_gripper_controllers.cpp index 0fc10c0c73..da9e15840e 100644 --- a/gripper_controllers/test/test_gripper_controllers.cpp +++ b/gripper_controllers/test/test_gripper_controllers.cpp @@ -31,6 +31,8 @@ using hardware_interface::LoanedCommandInterface; using hardware_interface::LoanedStateInterface; using GripperCommandAction = control_msgs::action::GripperCommand; using GoalHandle = rclcpp_action::ServerGoalHandle; +using testing::SizeIs; +using testing::UnorderedElementsAre; template void GripperControllerTest::SetUpTestCase() @@ -108,6 +110,16 @@ TYPED_TEST(GripperControllerTest, ConfigureParamsSuccess) ASSERT_EQ( this->controller_->on_configure(rclcpp_lifecycle::State()), controller_interface::CallbackReturn::SUCCESS); + + // check interface configuration + auto cmd_if_conf = this->controller_->command_interface_configuration(); + ASSERT_THAT(cmd_if_conf.names, SizeIs(1lu)); + ASSERT_THAT(cmd_if_conf.names, UnorderedElementsAre(std::string("joint_1/") + TypeParam::value)); + EXPECT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); + auto state_if_conf = this->controller_->state_interface_configuration(); + ASSERT_THAT(state_if_conf.names, SizeIs(2lu)); + ASSERT_THAT(state_if_conf.names, UnorderedElementsAre("joint_1/position", "joint_1/velocity")); + EXPECT_EQ(state_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); } TYPED_TEST(GripperControllerTest, ActivateWithWrongJointsNamesFails) diff --git a/imu_sensor_broadcaster/test/test_imu_sensor_broadcaster.cpp b/imu_sensor_broadcaster/test/test_imu_sensor_broadcaster.cpp index 0fb987ce77..83edc044d3 100644 --- a/imu_sensor_broadcaster/test/test_imu_sensor_broadcaster.cpp +++ b/imu_sensor_broadcaster/test/test_imu_sensor_broadcaster.cpp @@ -32,6 +32,8 @@ #include "sensor_msgs/msg/imu.hpp" using hardware_interface::LoanedStateInterface; +using testing::IsEmpty; +using testing::SizeIs; namespace { @@ -113,6 +115,12 @@ TEST_F(IMUSensorBroadcasterTest, SensorName_Configure_Success) // configure passed ASSERT_EQ(imu_broadcaster_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + + // check interface configuration + auto cmd_if_conf = imu_broadcaster_->command_interface_configuration(); + ASSERT_THAT(cmd_if_conf.names, IsEmpty()); + auto state_if_conf = imu_broadcaster_->state_interface_configuration(); + ASSERT_THAT(state_if_conf.names, SizeIs(10lu)); } TEST_F(IMUSensorBroadcasterTest, SensorName_Activate_Success) @@ -126,6 +134,21 @@ TEST_F(IMUSensorBroadcasterTest, SensorName_Activate_Success) // configure and activate success ASSERT_EQ(imu_broadcaster_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); ASSERT_EQ(imu_broadcaster_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + + // check interface configuration + auto cmd_if_conf = imu_broadcaster_->command_interface_configuration(); + ASSERT_THAT(cmd_if_conf.names, IsEmpty()); + auto state_if_conf = imu_broadcaster_->state_interface_configuration(); + ASSERT_THAT(state_if_conf.names, SizeIs(10lu)); + + // deactivate passed + ASSERT_EQ(imu_broadcaster_->on_deactivate(rclcpp_lifecycle::State()), NODE_SUCCESS); + + // check interface configuration + cmd_if_conf = imu_broadcaster_->command_interface_configuration(); + ASSERT_THAT(cmd_if_conf.names, IsEmpty()); + state_if_conf = imu_broadcaster_->state_interface_configuration(); + ASSERT_THAT(state_if_conf.names, SizeIs(10lu)); // did not change } TEST_F(IMUSensorBroadcasterTest, SensorName_Update_Success) diff --git a/joint_state_broadcaster/test/test_joint_state_broadcaster.cpp b/joint_state_broadcaster/test/test_joint_state_broadcaster.cpp index b44152a453..3e45740bbc 100644 --- a/joint_state_broadcaster/test/test_joint_state_broadcaster.cpp +++ b/joint_state_broadcaster/test/test_joint_state_broadcaster.cpp @@ -163,7 +163,7 @@ TEST_F(JointStateBroadcasterTest, ConfigureErrorTest) ASSERT_FALSE(state_broadcaster_->realtime_dynamic_joint_state_publisher_); } -TEST_F(JointStateBroadcasterTest, ActivateTest) +TEST_F(JointStateBroadcasterTest, ActivateEmptyTest) { // publishers not initialized yet ASSERT_FALSE(state_broadcaster_->joint_state_publisher_); @@ -177,6 +177,12 @@ TEST_F(JointStateBroadcasterTest, ActivateTest) const size_t NUM_JOINTS = joint_names_.size(); + // check interface configuration + auto cmd_if_conf = state_broadcaster_->command_interface_configuration(); + ASSERT_THAT(cmd_if_conf.names, IsEmpty()); + auto state_if_conf = state_broadcaster_->state_interface_configuration(); + ASSERT_THAT(state_if_conf.names, IsEmpty()); + // publishers initialized ASSERT_TRUE(state_broadcaster_->realtime_joint_state_publisher_); ASSERT_TRUE(state_broadcaster_->realtime_dynamic_joint_state_publisher_); @@ -218,6 +224,12 @@ TEST_F(JointStateBroadcasterTest, ActivateTestWithoutJointsParameter) const size_t NUM_JOINTS = joint_names_.size(); + // check interface configuration + auto cmd_if_conf = state_broadcaster_->command_interface_configuration(); + ASSERT_THAT(cmd_if_conf.names, IsEmpty()); + auto state_if_conf = state_broadcaster_->state_interface_configuration(); + ASSERT_THAT(state_if_conf.names, IsEmpty()); + // publishers initialized ASSERT_TRUE(state_broadcaster_->realtime_joint_state_publisher_); ASSERT_TRUE(state_broadcaster_->realtime_dynamic_joint_state_publisher_); @@ -259,6 +271,12 @@ TEST_F(JointStateBroadcasterTest, ActivateTestWithoutInterfacesParameter) const size_t NUM_JOINTS = joint_names_.size(); + // check interface configuration + auto cmd_if_conf = state_broadcaster_->command_interface_configuration(); + ASSERT_THAT(cmd_if_conf.names, IsEmpty()); + auto state_if_conf = state_broadcaster_->state_interface_configuration(); + ASSERT_THAT(state_if_conf.names, IsEmpty()); + // publishers initialized ASSERT_TRUE(state_broadcaster_->realtime_joint_state_publisher_); ASSERT_TRUE(state_broadcaster_->realtime_dynamic_joint_state_publisher_); @@ -287,7 +305,7 @@ TEST_F(JointStateBroadcasterTest, ActivateTestWithoutInterfacesParameter) ElementsAreArray(interface_names_)); } -TEST_F(JointStateBroadcasterTest, ActivateTestTwoJointsOneInterface) +TEST_F(JointStateBroadcasterTest, ActivateDeactivateTestTwoJointsOneInterface) { const std::vector JOINT_NAMES = {joint_names_[0], joint_names_[1]}; const std::vector IF_NAMES = {interface_names_[0]}; @@ -300,6 +318,12 @@ TEST_F(JointStateBroadcasterTest, ActivateTestTwoJointsOneInterface) const size_t NUM_JOINTS = JOINT_NAMES.size(); + // check interface configuration + auto cmd_if_conf = state_broadcaster_->command_interface_configuration(); + ASSERT_THAT(cmd_if_conf.names, IsEmpty()); + auto state_if_conf = state_broadcaster_->state_interface_configuration(); + ASSERT_THAT(state_if_conf.names, SizeIs(JOINT_NAMES.size() * IF_NAMES.size())); + // publishers initialized ASSERT_TRUE(state_broadcaster_->realtime_joint_state_publisher_); ASSERT_TRUE(state_broadcaster_->realtime_dynamic_joint_state_publisher_); @@ -329,6 +353,16 @@ TEST_F(JointStateBroadcasterTest, ActivateTestTwoJointsOneInterface) dynamic_joint_state_msg.interface_values[0].interface_names, ElementsAreArray(IF_NAMES)); ASSERT_THAT( dynamic_joint_state_msg.interface_values[1].interface_names, ElementsAreArray(IF_NAMES)); + + // deactivate + ASSERT_EQ(state_broadcaster_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + + // check interface configuration + cmd_if_conf = state_broadcaster_->command_interface_configuration(); + ASSERT_THAT(cmd_if_conf.names, IsEmpty()); + state_if_conf = state_broadcaster_->state_interface_configuration(); + ASSERT_THAT( + state_if_conf.names, SizeIs(JOINT_NAMES.size() * IF_NAMES.size())); // does not change } TEST_F(JointStateBroadcasterTest, ActivateTestOneJointTwoInterfaces) @@ -344,6 +378,12 @@ TEST_F(JointStateBroadcasterTest, ActivateTestOneJointTwoInterfaces) const size_t NUM_JOINTS = JOINT_NAMES.size(); + // check interface configuration + auto cmd_if_conf = state_broadcaster_->command_interface_configuration(); + ASSERT_THAT(cmd_if_conf.names, IsEmpty()); + auto state_if_conf = state_broadcaster_->state_interface_configuration(); + ASSERT_THAT(state_if_conf.names, SizeIs(JOINT_NAMES.size() * IF_NAMES.size())); + // publishers initialized ASSERT_TRUE(state_broadcaster_->realtime_joint_state_publisher_); ASSERT_TRUE(state_broadcaster_->realtime_dynamic_joint_state_publisher_); @@ -412,6 +452,12 @@ TEST_F(JointStateBroadcasterTest, ActivateTestTwoJointTwoInterfacesOneMissing) const size_t NUM_JOINTS = JOINT_NAMES.size(); + // check interface configuration + auto cmd_if_conf = state_broadcaster_->command_interface_configuration(); + ASSERT_THAT(cmd_if_conf.names, IsEmpty()); + auto state_if_conf = state_broadcaster_->state_interface_configuration(); + ASSERT_THAT(state_if_conf.names, SizeIs(JOINT_NAMES.size() * IF_NAMES.size())); + // publishers initialized ASSERT_TRUE(state_broadcaster_->realtime_joint_state_publisher_); ASSERT_TRUE(state_broadcaster_->realtime_dynamic_joint_state_publisher_); @@ -455,6 +501,12 @@ TEST_F(JointStateBroadcasterTest, TestCustomInterfaceWithoutMapping) const size_t NUM_JOINTS = JOINT_NAMES.size(); + // check interface configuration + auto cmd_if_conf = state_broadcaster_->command_interface_configuration(); + ASSERT_THAT(cmd_if_conf.names, IsEmpty()); + auto state_if_conf = state_broadcaster_->state_interface_configuration(); + ASSERT_THAT(state_if_conf.names, SizeIs(JOINT_NAMES.size() * IF_NAMES.size())); + // joint state initialized const auto & joint_state_msg = state_broadcaster_->realtime_joint_state_publisher_->msg_; ASSERT_THAT(joint_state_msg.name, SizeIs(0)); @@ -492,6 +544,12 @@ TEST_F(JointStateBroadcasterTest, TestCustomInterfaceMapping) const size_t NUM_JOINTS = JOINT_NAMES.size(); + // check interface configuration + auto cmd_if_conf = state_broadcaster_->command_interface_configuration(); + ASSERT_THAT(cmd_if_conf.names, IsEmpty()); + auto state_if_conf = state_broadcaster_->state_interface_configuration(); + ASSERT_THAT(state_if_conf.names, SizeIs(JOINT_NAMES.size() * IF_NAMES.size())); + // joint state initialized const auto & joint_state_msg = state_broadcaster_->realtime_joint_state_publisher_->msg_; ASSERT_THAT(joint_state_msg.name, ElementsAreArray(JOINT_NAMES)); diff --git a/joint_state_broadcaster/test/test_joint_state_broadcaster.hpp b/joint_state_broadcaster/test/test_joint_state_broadcaster.hpp index fcaa40e8d5..fa9d29c936 100644 --- a/joint_state_broadcaster/test/test_joint_state_broadcaster.hpp +++ b/joint_state_broadcaster/test/test_joint_state_broadcaster.hpp @@ -33,10 +33,10 @@ using hardware_interface::HW_IF_VELOCITY; class FriendJointStateBroadcaster : public joint_state_broadcaster::JointStateBroadcaster { FRIEND_TEST(JointStateBroadcasterTest, ConfigureErrorTest); - FRIEND_TEST(JointStateBroadcasterTest, ActivateTest); + FRIEND_TEST(JointStateBroadcasterTest, ActivateEmptyTest); FRIEND_TEST(JointStateBroadcasterTest, ActivateTestWithoutJointsParameter); FRIEND_TEST(JointStateBroadcasterTest, ActivateTestWithoutInterfacesParameter); - FRIEND_TEST(JointStateBroadcasterTest, ActivateTestTwoJointsOneInterface); + FRIEND_TEST(JointStateBroadcasterTest, ActivateDeactivateTestTwoJointsOneInterface); FRIEND_TEST(JointStateBroadcasterTest, ActivateTestOneJointTwoInterfaces); FRIEND_TEST(JointStateBroadcasterTest, ActivateTestTwoJointTwoInterfacesAllMissing); FRIEND_TEST(JointStateBroadcasterTest, ActivateTestTwoJointTwoInterfacesOneMissing); diff --git a/range_sensor_broadcaster/test/test_range_sensor_broadcaster.cpp b/range_sensor_broadcaster/test/test_range_sensor_broadcaster.cpp index a857141ea9..7b8e6d0e02 100644 --- a/range_sensor_broadcaster/test/test_range_sensor_broadcaster.cpp +++ b/range_sensor_broadcaster/test/test_range_sensor_broadcaster.cpp @@ -22,6 +22,9 @@ #include "hardware_interface/loaned_state_interface.hpp" +using testing::IsEmpty; +using testing::SizeIs; + void RangeSensorBroadcasterTest::SetUp() { // initialize controller @@ -130,9 +133,15 @@ TEST_F(RangeSensorBroadcasterTest, Configure_RangeBroadcaster_Success) ASSERT_EQ( range_broadcaster_->on_configure(rclcpp_lifecycle::State()), controller_interface::CallbackReturn::SUCCESS); + + // check interface configuration + auto cmd_if_conf = range_broadcaster_->command_interface_configuration(); + ASSERT_THAT(cmd_if_conf.names, IsEmpty()); + auto state_if_conf = range_broadcaster_->state_interface_configuration(); + ASSERT_THAT(state_if_conf.names, SizeIs(1lu)); } -TEST_F(RangeSensorBroadcasterTest, Activate_RangeBroadcaster_Success) +TEST_F(RangeSensorBroadcasterTest, ActivateDeactivate_RangeBroadcaster_Success) { init_broadcaster("test_range_sensor_broadcaster"); @@ -141,6 +150,22 @@ TEST_F(RangeSensorBroadcasterTest, Activate_RangeBroadcaster_Success) ASSERT_EQ( range_broadcaster_->on_activate(rclcpp_lifecycle::State()), controller_interface::CallbackReturn::SUCCESS); + + // check interface configuration + auto cmd_if_conf = range_broadcaster_->command_interface_configuration(); + ASSERT_THAT(cmd_if_conf.names, IsEmpty()); + auto state_if_conf = range_broadcaster_->state_interface_configuration(); + ASSERT_THAT(state_if_conf.names, SizeIs(1lu)); + + ASSERT_EQ( + range_broadcaster_->on_deactivate(rclcpp_lifecycle::State()), + controller_interface::CallbackReturn::SUCCESS); + + // check interface configuration + cmd_if_conf = range_broadcaster_->command_interface_configuration(); + ASSERT_THAT(cmd_if_conf.names, IsEmpty()); + state_if_conf = range_broadcaster_->state_interface_configuration(); + ASSERT_THAT(state_if_conf.names, SizeIs(1lu)); // did not change } TEST_F(RangeSensorBroadcasterTest, Update_RangeBroadcaster_Success) diff --git a/tricycle_controller/test/test_tricycle_controller.cpp b/tricycle_controller/test/test_tricycle_controller.cpp index 504ca381ce..d8beedae42 100644 --- a/tricycle_controller/test/test_tricycle_controller.cpp +++ b/tricycle_controller/test/test_tricycle_controller.cpp @@ -39,6 +39,7 @@ using hardware_interface::LoanedCommandInterface; using hardware_interface::LoanedStateInterface; using lifecycle_msgs::msg::State; using testing::SizeIs; +using testing::UnorderedElementsAre; class TestableTricycleController : public tricycle_controller::TricycleController { @@ -209,6 +210,20 @@ TEST_F(TestTricycleController, configure_succeeds_when_joints_are_specified) rclcpp::Parameter("steering_joint_name", rclcpp::ParameterValue(steering_joint_name))); ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), CallbackReturn::SUCCESS); + + // check interface configuration + auto cmd_if_conf = controller_->command_interface_configuration(); + ASSERT_THAT(cmd_if_conf.names, SizeIs(2lu)); + ASSERT_THAT( + cmd_if_conf.names, + UnorderedElementsAre(traction_joint_name + "/velocity", steering_joint_name + "/position")); + EXPECT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); + auto state_if_conf = controller_->state_interface_configuration(); + ASSERT_THAT(state_if_conf.names, SizeIs(2lu)); + ASSERT_THAT( + state_if_conf.names, + UnorderedElementsAre(traction_joint_name + "/velocity", steering_joint_name + "/position")); + EXPECT_EQ(state_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); } TEST_F(TestTricycleController, activate_fails_without_resources_assigned) From 35556854883b546143d7773c43053650a8b23840 Mon Sep 17 00:00:00 2001 From: Sai Kishor Kothakota Date: Thu, 30 Nov 2023 16:26:33 +0100 Subject: [PATCH 154/238] added documentation on common controller parameters (#855) --- doc/controllers_index.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/doc/controllers_index.rst b/doc/controllers_index.rst index 9fceb90fd3..5f8780d961 100644 --- a/doc/controllers_index.rst +++ b/doc/controllers_index.rst @@ -72,3 +72,12 @@ In the sense of ros2_control, broadcasters are still controllers using the same IMU Sensor Broadcaster <../imu_sensor_broadcaster/doc/userdoc.rst> Joint State Broadcaster <../joint_state_broadcaster/doc/userdoc.rst> Range Sensor Broadcaster <../range_sensor_broadcaster/doc/userdoc.rst> + + +Common Controller Parameters +**************************** + +Every controller and broadcaster has a few common parameters. They are optional, but if needed they have to be set before ``onConfigure`` transition to ``inactive`` state, see `lifecycle documents `__. Once the controllers are already loaded, this transition is done using the service ``configure_controller`` of the controller_manager. + +* ``update_rate``: An unsigned integer parameter representing the rate at which every controller/broadcaster runs its update cycle. When unspecified, they run at the same frequency as the controller_manager. +* ``is_async``: A boolean parameter that is needed to specify if the controller update needs to run asynchronously. From fcc0847958c17a942e2b233d3bea1ab2d2ac05dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Thu, 30 Nov 2023 17:36:36 +0100 Subject: [PATCH 155/238] [JTC] Activate checks for parameter validation (#857) --- .../test/test_trajectory_controller.cpp | 157 +++++++++--------- .../test/test_trajectory_controller_utils.hpp | 22 ++- 2 files changed, 91 insertions(+), 88 deletions(-) diff --git a/joint_trajectory_controller/test/test_trajectory_controller.cpp b/joint_trajectory_controller/test/test_trajectory_controller.cpp index 7c026d5e7a..0b6651e79f 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller.cpp +++ b/joint_trajectory_controller/test/test_trajectory_controller.cpp @@ -122,8 +122,8 @@ TEST_P(TrajectoryControllerTestParameterized, activate) rclcpp::executors::MultiThreadedExecutor executor; SetUpTrajectoryController(executor); - traj_controller_->get_node()->configure(); - ASSERT_EQ(traj_controller_->get_state().id(), State::PRIMARY_STATE_INACTIVE); + auto state = traj_controller_->get_node()->configure(); + ASSERT_EQ(state.id(), State::PRIMARY_STATE_INACTIVE); auto cmd_interface_config = traj_controller_->command_interface_configuration(); ASSERT_EQ( @@ -133,8 +133,8 @@ TEST_P(TrajectoryControllerTestParameterized, activate) ASSERT_EQ( state_interface_config.names.size(), joint_names_.size() * state_interface_types_.size()); - ActivateTrajectoryController(); - ASSERT_EQ(traj_controller_->get_state().id(), State::PRIMARY_STATE_ACTIVE); + state = ActivateTrajectoryController(); + ASSERT_EQ(state.id(), State::PRIMARY_STATE_ACTIVE); executor.cancel(); } @@ -194,13 +194,10 @@ TEST_P(TrajectoryControllerTestParameterized, correct_initialization_using_param rclcpp::Parameter("allow_nonzero_velocity_at_trajectory_end", true)); // This call is replacing the way parameters are set via launch - traj_controller_->configure(); - auto state = traj_controller_->get_state(); + auto state = traj_controller_->configure(); ASSERT_EQ(State::PRIMARY_STATE_INACTIVE, state.id()); - ActivateTrajectoryController(); - - state = traj_controller_->get_state(); + state = ActivateTrajectoryController(); ASSERT_EQ(State::PRIMARY_STATE_ACTIVE, state.id()); EXPECT_EQ(INITIAL_POS_JOINT1, joint_pos_[0]); EXPECT_EQ(INITIAL_POS_JOINT2, joint_pos_[1]); @@ -245,8 +242,7 @@ TEST_P(TrajectoryControllerTestParameterized, correct_initialization_using_param // wait so controller would have processed the third point when reactivated -> but it shouldn't std::this_thread::sleep_for(std::chrono::milliseconds(3000)); - ActivateTrajectoryController(false, deactivated_positions); - state = traj_controller_->get_state(); + state = ActivateTrajectoryController(false, deactivated_positions); ASSERT_EQ(state.id(), State::PRIMARY_STATE_ACTIVE); // it should still be holding the position at time of deactivation @@ -1918,72 +1914,73 @@ INSTANTIATE_TEST_SUITE_P( std::vector({"effort"}), std::vector({"position", "velocity", "acceleration"})))); -// TODO(destogl): this tests should be changed because we are using `generate_parameters_library` -// TEST_F(TrajectoryControllerTest, incorrect_initialization_using_interface_parameters) -// { -// auto set_parameter_and_check_result = [&]() -// { -// EXPECT_EQ(traj_controller_->get_state().id(), State::PRIMARY_STATE_UNCONFIGURED); -// SetParameters(); // This call is replacing the way parameters are set via launch -// traj_controller_->get_node()->configure(); -// EXPECT_EQ(traj_controller_->get_state().id(), State::PRIMARY_STATE_UNCONFIGURED); -// }; -// -// SetUpTrajectoryController(false); -// -// // command interfaces: empty -// command_interface_types_ = {}; -// set_parameter_and_check_result(); -// -// // command interfaces: bad_name -// command_interface_types_ = {"bad_name"}; -// set_parameter_and_check_result(); -// -// // command interfaces: effort has to be only -// command_interface_types_ = {"effort", "position"}; -// set_parameter_and_check_result(); -// -// // command interfaces: velocity - position not present -// command_interface_types_ = {"velocity", "acceleration"}; -// set_parameter_and_check_result(); -// -// // command interfaces: acceleration without position and velocity -// command_interface_types_ = {"acceleration"}; -// set_parameter_and_check_result(); -// -// // state interfaces: empty -// state_interface_types_ = {}; -// set_parameter_and_check_result(); -// -// // state interfaces: cannot not be effort -// state_interface_types_ = {"effort"}; -// set_parameter_and_check_result(); -// -// // state interfaces: bad name -// state_interface_types_ = {"bad_name"}; -// set_parameter_and_check_result(); -// -// // state interfaces: velocity - position not present -// state_interface_types_ = {"velocity"}; -// set_parameter_and_check_result(); -// state_interface_types_ = {"velocity", "acceleration"}; -// set_parameter_and_check_result(); -// -// // state interfaces: acceleration without position and velocity -// state_interface_types_ = {"acceleration"}; -// set_parameter_and_check_result(); -// -// // velocity-only command interface: position - velocity not present -// command_interface_types_ = {"velocity"}; -// state_interface_types_ = {"position"}; -// set_parameter_and_check_result(); -// state_interface_types_ = {"velocity"}; -// set_parameter_and_check_result(); -// -// // effort-only command interface: position - velocity not present -// command_interface_types_ = {"effort"}; -// state_interface_types_ = {"position"}; -// set_parameter_and_check_result(); -// state_interface_types_ = {"velocity"}; -// set_parameter_and_check_result(); -// } +/** + * @brief see if parameter validation is correct + * + * Note: generate_parameter_library validates parameters itself during on_init() method, but + * combinations of parameters are checked from JTC during on_configure() + */ +TEST_F(TrajectoryControllerTest, incorrect_initialization_using_interface_parameters) +{ + // command interfaces: empty + command_interface_types_ = {}; + EXPECT_EQ(SetUpTrajectoryControllerLocal(), controller_interface::return_type::OK); + auto state = traj_controller_->get_node()->configure(); + EXPECT_EQ(state.id(), State::PRIMARY_STATE_UNCONFIGURED); + + // command interfaces: bad_name + command_interface_types_ = {"bad_name"}; + EXPECT_EQ(SetUpTrajectoryControllerLocal(), controller_interface::return_type::ERROR); + + // command interfaces: effort has to be only + command_interface_types_ = {"effort", "position"}; + EXPECT_EQ(SetUpTrajectoryControllerLocal(), controller_interface::return_type::ERROR); + + // command interfaces: velocity - position not present + command_interface_types_ = {"velocity", "acceleration"}; + EXPECT_EQ(SetUpTrajectoryControllerLocal(), controller_interface::return_type::ERROR); + + // command interfaces: acceleration without position and velocity + command_interface_types_ = {"acceleration"}; + EXPECT_EQ(SetUpTrajectoryControllerLocal(), controller_interface::return_type::ERROR); + + // state interfaces: empty + state_interface_types_ = {}; + EXPECT_EQ(SetUpTrajectoryControllerLocal(), controller_interface::return_type::ERROR); + + // state interfaces: cannot not be effort + state_interface_types_ = {"effort"}; + EXPECT_EQ(SetUpTrajectoryControllerLocal(), controller_interface::return_type::ERROR); + + // state interfaces: bad name + state_interface_types_ = {"bad_name"}; + EXPECT_EQ(SetUpTrajectoryControllerLocal(), controller_interface::return_type::ERROR); + + // state interfaces: velocity - position not present + state_interface_types_ = {"velocity"}; + EXPECT_EQ(SetUpTrajectoryControllerLocal(), controller_interface::return_type::ERROR); + state_interface_types_ = {"velocity", "acceleration"}; + EXPECT_EQ(SetUpTrajectoryControllerLocal(), controller_interface::return_type::ERROR); + + // state interfaces: acceleration without position and velocity + state_interface_types_ = {"acceleration"}; + EXPECT_EQ(SetUpTrajectoryControllerLocal(), controller_interface::return_type::ERROR); + + // velocity-only command interface: position - velocity not present + command_interface_types_ = {"velocity"}; + state_interface_types_ = {"position"}; + EXPECT_EQ(SetUpTrajectoryControllerLocal(), controller_interface::return_type::OK); + state = traj_controller_->get_node()->configure(); + EXPECT_EQ(state.id(), State::PRIMARY_STATE_UNCONFIGURED); + state_interface_types_ = {"velocity"}; + EXPECT_EQ(SetUpTrajectoryControllerLocal(), controller_interface::return_type::ERROR); + + // effort-only command interface: position - velocity not present + command_interface_types_ = {"effort"}; + state_interface_types_ = {"position"}; + EXPECT_EQ(SetUpTrajectoryControllerLocal(), controller_interface::return_type::OK); + state = traj_controller_->get_node()->configure(); + EXPECT_EQ(state.id(), State::PRIMARY_STATE_UNCONFIGURED); + state_interface_types_ = {"velocity"}; + EXPECT_EQ(SetUpTrajectoryControllerLocal(), controller_interface::return_type::ERROR); +} diff --git a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp index 3c8e252067..b530517517 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp +++ b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp @@ -188,6 +188,17 @@ class TrajectoryControllerTest : public ::testing::Test void SetUpTrajectoryController( rclcpp::Executor & executor, const std::vector & parameters = {}) + { + auto ret = SetUpTrajectoryControllerLocal(parameters); + if (ret != controller_interface::return_type::OK) + { + FAIL(); + } + executor.add_node(traj_controller_->get_node()->get_node_base_interface()); + } + + controller_interface::return_type SetUpTrajectoryControllerLocal( + const std::vector & parameters = {}) { traj_controller_ = std::make_shared(); @@ -200,12 +211,7 @@ class TrajectoryControllerTest : public ::testing::Test parameter_overrides.insert(parameter_overrides.end(), parameters.begin(), parameters.end()); node_options.parameter_overrides(parameter_overrides); - auto ret = traj_controller_->init(controller_name_, "", 0, "", node_options); - if (ret != controller_interface::return_type::OK) - { - FAIL(); - } - executor.add_node(traj_controller_->get_node()->get_node_base_interface()); + return traj_controller_->init(controller_name_, "", 0, "", node_options); } void SetPidParameters( @@ -262,7 +268,7 @@ class TrajectoryControllerTest : public ::testing::Test initial_eff_joints); } - void ActivateTrajectoryController( + rclcpp_lifecycle::State ActivateTrajectoryController( bool separate_cmd_and_state_values = false, const std::vector initial_pos_joints = INITIAL_POS_JOINTS, const std::vector initial_vel_joints = INITIAL_VEL_JOINTS, @@ -320,7 +326,7 @@ class TrajectoryControllerTest : public ::testing::Test } traj_controller_->assign_interfaces(std::move(cmd_interfaces), std::move(state_interfaces)); - traj_controller_->get_node()->activate(); + return traj_controller_->get_node()->activate(); } static void TearDownTestCase() { rclcpp::shutdown(); } From 62ce4879e45fdec2f462f14a695cf579afbfe866 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Fri, 1 Dec 2023 14:39:06 +0100 Subject: [PATCH 156/238] [JTC] Remove start_with_holding option (#839) --- .../src/joint_trajectory_controller.cpp | 7 ++---- ...oint_trajectory_controller_parameters.yaml | 5 ---- .../test/test_trajectory_controller.cpp | 23 ++----------------- 3 files changed, 4 insertions(+), 31 deletions(-) diff --git a/joint_trajectory_controller/src/joint_trajectory_controller.cpp b/joint_trajectory_controller/src/joint_trajectory_controller.cpp index dae7f13148..d24fd5a34a 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller.cpp +++ b/joint_trajectory_controller/src/joint_trajectory_controller.cpp @@ -944,11 +944,8 @@ controller_interface::CallbackReturn JointTrajectoryController::on_activate( read_state_from_state_interfaces(last_commanded_state_); } - // Should the controller start by holding position at the beginning of active state? - if (params_.start_with_holding) - { - add_new_trajectory_msg(set_hold_position()); - } + // The controller should start by holding position at the beginning of active state + add_new_trajectory_msg(set_hold_position()); rt_is_holding_.writeFromNonRT(true); // parse timeout parameter diff --git a/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml b/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml index 87ca1daea5..4981489d36 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml +++ b/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml @@ -73,11 +73,6 @@ joint_trajectory_controller: one_of<>: [["splines", "none"]], } } - start_with_holding: { - type: bool, - default_value: true, - description: "If true, start with holding position after activation. Otherwise, no command will be sent until the first trajectory is received.", - } allow_nonzero_velocity_at_trajectory_end: { type: bool, default_value: false, diff --git a/joint_trajectory_controller/test/test_trajectory_controller.cpp b/joint_trajectory_controller/test/test_trajectory_controller.cpp index 0b6651e79f..0b049000e3 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller.cpp +++ b/joint_trajectory_controller/test/test_trajectory_controller.cpp @@ -444,24 +444,6 @@ TEST_P(TrajectoryControllerTestParameterized, update_dynamic_tolerances) executor.cancel(); } -/** - * @brief check if hold on startup is deactivated - */ -TEST_P(TrajectoryControllerTestParameterized, no_hold_on_startup) -{ - rclcpp::executors::MultiThreadedExecutor executor; - - rclcpp::Parameter start_with_holding_parameter("start_with_holding", false); - SetUpAndActivateTrajectoryController(executor, {start_with_holding_parameter}); - - constexpr auto FIRST_POINT_TIME = std::chrono::milliseconds(250); - updateControllerAsync(rclcpp::Duration(FIRST_POINT_TIME)); - // after startup without start_with_holding being set, we expect no active trajectory - ASSERT_FALSE(traj_controller_->has_active_traj()); - - executor.cancel(); -} - /** * @brief check if hold on startup */ @@ -469,12 +451,11 @@ TEST_P(TrajectoryControllerTestParameterized, hold_on_startup) { rclcpp::executors::MultiThreadedExecutor executor; - rclcpp::Parameter start_with_holding_parameter("start_with_holding", true); - SetUpAndActivateTrajectoryController(executor, {start_with_holding_parameter}); + SetUpAndActivateTrajectoryController(executor, {}); constexpr auto FIRST_POINT_TIME = std::chrono::milliseconds(250); updateControllerAsync(rclcpp::Duration(FIRST_POINT_TIME)); - // after startup with start_with_holding being set, we expect an active trajectory: + // after startup, we expect an active trajectory: ASSERT_TRUE(traj_controller_->has_active_traj()); // one point, being the position at startup std::vector initial_positions{INITIAL_POS_JOINT1, INITIAL_POS_JOINT2, INITIAL_POS_JOINT3}; From e4f1700ef653268130e25e65e351dc4d5572b54d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Fri, 1 Dec 2023 14:40:56 +0100 Subject: [PATCH 157/238] [JTC] Continue with last trajectory-point on success (#842) --- joint_trajectory_controller/doc/userdoc.rst | 4 +- .../joint_trajectory_controller.hpp | 12 +- .../src/joint_trajectory_controller.cpp | 16 ++- .../test/test_trajectory_actions.cpp | 136 +++++++++++++----- .../test/test_trajectory_controller.cpp | 14 +- .../test/test_trajectory_controller_utils.hpp | 56 +++----- 6 files changed, 162 insertions(+), 76 deletions(-) diff --git a/joint_trajectory_controller/doc/userdoc.rst b/joint_trajectory_controller/doc/userdoc.rst index 58ba734b45..6a34185437 100644 --- a/joint_trajectory_controller/doc/userdoc.rst +++ b/joint_trajectory_controller/doc/userdoc.rst @@ -150,12 +150,14 @@ Actions [#f1]_ /follow_joint_trajectory [control_msgs::action::FollowJointTrajectory] Action server for commanding the controller - The primary way to send trajectories is through the action interface, and should be favored when execution monitoring is desired. + Action goals allow to specify not only the trajectory to execute, but also (optionally) path and goal tolerances. When no tolerances are specified, the defaults given in the parameter interface are used (see :ref:`parameters`). If tolerances are violated during trajectory execution, the action goal is aborted, the client is notified, and the current position is held. +The action server returns success to the client and continues with the last commanded point after the target is reached within the specified tolerances. + .. _Subscriber: Subscriber [#f1]_ diff --git a/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp b/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp index 397ccf347c..d16e4f8267 100644 --- a/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp +++ b/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp @@ -174,7 +174,7 @@ class JointTrajectoryController : public controller_interface::ControllerInterfa // Timeout to consider commands old double cmd_timeout_; - // Are we holding position? + // True if holding position or repeating last trajectory point in case of success realtime_tools::RealtimeBuffer rt_is_holding_; // TODO(karsten1987): eventually activate and deactivate subscriber directly when its supported bool subscriber_is_active_ = false; @@ -244,9 +244,19 @@ class JointTrajectoryController : public controller_interface::ControllerInterfa JOINT_TRAJECTORY_CONTROLLER_PUBLIC void preempt_active_goal(); + + /** @brief set the current position with zero velocity and acceleration as new command + */ JOINT_TRAJECTORY_CONTROLLER_PUBLIC std::shared_ptr set_hold_position(); + /** @brief set last trajectory point to be repeated at success + * + * no matter if it has nonzero velocity or acceleration + */ + JOINT_TRAJECTORY_CONTROLLER_PUBLIC + std::shared_ptr set_success_trajectory_point(); + JOINT_TRAJECTORY_CONTROLLER_PUBLIC bool reset(); diff --git a/joint_trajectory_controller/src/joint_trajectory_controller.cpp b/joint_trajectory_controller/src/joint_trajectory_controller.cpp index d24fd5a34a..9306b07354 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller.cpp +++ b/joint_trajectory_controller/src/joint_trajectory_controller.cpp @@ -362,7 +362,7 @@ controller_interface::return_type JointTrajectoryController::update( RCLCPP_INFO(get_node()->get_logger(), "Goal reached, success!"); traj_msg_external_point_ptr_.reset(); - traj_msg_external_point_ptr_.initRT(set_hold_position()); + traj_msg_external_point_ptr_.initRT(set_success_trajectory_point()); } else if (!within_goal_time) { @@ -1466,6 +1466,20 @@ JointTrajectoryController::set_hold_position() return hold_position_msg_ptr_; } +std::shared_ptr +JointTrajectoryController::set_success_trajectory_point() +{ + // set last command to be repeated at success, no matter if it has nonzero velocity or + // acceleration + hold_position_msg_ptr_->points[0] = traj_external_point_ptr_->get_trajectory_msg()->points.back(); + hold_position_msg_ptr_->points[0].time_from_start = rclcpp::Duration(0, 0); + + // set flag, otherwise tolerances will be checked with success_trajectory_point too + rt_is_holding_.writeFromNonRT(true); + + return hold_position_msg_ptr_; +} + bool JointTrajectoryController::contains_interface_type( const std::vector & interface_type_list, const std::string & interface_type) { diff --git a/joint_trajectory_controller/test/test_trajectory_actions.cpp b/joint_trajectory_controller/test/test_trajectory_actions.cpp index ed13a24485..87d557df1b 100644 --- a/joint_trajectory_controller/test/test_trajectory_actions.cpp +++ b/joint_trajectory_controller/test/test_trajectory_actions.cpp @@ -68,11 +68,12 @@ class TestTrajectoryActions : public TrajectoryControllerTest void SetUpExecutor( const std::vector & parameters = {}, - bool separate_cmd_and_state_values = false, double kp = 0.0) + bool separate_cmd_and_state_values = false, double kp = 0.0, double ff = 1.0) { setup_executor_ = true; - SetUpAndActivateTrajectoryController(executor_, parameters, separate_cmd_and_state_values, kp); + SetUpAndActivateTrajectoryController( + executor_, parameters, separate_cmd_and_state_values, kp, ff); SetUpActionClient(); @@ -218,7 +219,10 @@ class TestTrajectoryActionsTestParameterized TEST_P(TestTrajectoryActionsTestParameterized, test_success_single_point_sendgoal) { - SetUpExecutor(); + // deactivate velocity tolerance + std::vector params = { + rclcpp::Parameter("constraints.stopped_velocity_tolerance", 0.0)}; + SetUpExecutor(params, false, 1.0, 0.0); SetUpControllerHardware(); std::shared_future gh_future; @@ -228,8 +232,6 @@ TEST_P(TestTrajectoryActionsTestParameterized, test_success_single_point_sendgoa std::vector points; JointTrajectoryPoint point; point.time_from_start = rclcpp::Duration::from_seconds(0.5); - point.positions.resize(joint_names_.size()); - point.positions = point_positions; points.push_back(point); @@ -247,20 +249,53 @@ TEST_P(TestTrajectoryActionsTestParameterized, test_success_single_point_sendgoa // it should be holding the last position goal // i.e., active but trivial trajectory (one point only) // note: the action goal also is a trivial trajectory - if (traj_controller_->has_position_command_interface()) - { - expectHoldingPoint(point_positions); - } - else + expectCommandPoint(point_positions); +} + +TEST_P(TestTrajectoryActionsTestParameterized, test_success_single_point_with_velocity_sendgoal) +{ + // deactivate velocity tolerance and allow velocity at trajectory end + std::vector params = { + rclcpp::Parameter("constraints.stopped_velocity_tolerance", 0.0), + rclcpp::Parameter("allow_nonzero_velocity_at_trajectory_end", true)}; + SetUpExecutor(params, false, 1.0, 0.0); + SetUpControllerHardware(); + + std::shared_future gh_future; + // send goal + std::vector point_positions{1.0, 2.0, 3.0}; + std::vector point_velocities{1.0, 1.0, 1.0}; { - // no integration to position state interface from velocity/acceleration - expectHoldingPoint(INITIAL_POS_JOINTS); + std::vector points; + JointTrajectoryPoint point; + point.time_from_start = rclcpp::Duration::from_seconds(0.5); + point.positions = point_positions; + point.velocities = point_velocities; + + points.push_back(point); + + gh_future = sendActionGoal(points, 1.0, goal_options_); } + controller_hw_thread_.join(); + + EXPECT_TRUE(gh_future.get()); + EXPECT_EQ(rclcpp_action::ResultCode::SUCCEEDED, common_resultcode_); + + // run an update + updateControllerAsync(rclcpp::Duration::from_seconds(0.01)); + + // it should be holding the last position goal + // i.e., active but trivial trajectory (one point only) + // note: the action goal also is a trivial trajectory + expectCommandPoint(point_positions, point_velocities); } TEST_P(TestTrajectoryActionsTestParameterized, test_success_multi_point_sendgoal) { - SetUpExecutor(); + // deactivate velocity tolerance + std::vector params = { + rclcpp::Parameter("constraints.stopped_velocity_tolerance", 0.0)}; + SetUpExecutor({params}, false, 1.0, 0.0); SetUpControllerHardware(); // add feedback @@ -277,15 +312,11 @@ TEST_P(TestTrajectoryActionsTestParameterized, test_success_multi_point_sendgoal std::vector points; JointTrajectoryPoint point1; point1.time_from_start = rclcpp::Duration::from_seconds(0.2); - point1.positions.resize(joint_names_.size()); - point1.positions = points_positions.at(0); points.push_back(point1); JointTrajectoryPoint point2; point2.time_from_start = rclcpp::Duration::from_seconds(0.3); - point2.positions.resize(joint_names_.size()); - point2.positions = points_positions.at(1); points.push_back(point2); @@ -302,15 +333,57 @@ TEST_P(TestTrajectoryActionsTestParameterized, test_success_multi_point_sendgoal // it should be holding the last position goal // i.e., active but trivial trajectory (one point only) - if (traj_controller_->has_position_command_interface()) - { - expectHoldingPoint(points_positions.at(1)); - } - else + expectCommandPoint(points_positions.at(1)); +} + +TEST_P(TestTrajectoryActionsTestParameterized, test_success_multi_point_with_velocity_sendgoal) +{ + // deactivate velocity tolerance and allow velocity at trajectory end + std::vector params = { + rclcpp::Parameter("constraints.stopped_velocity_tolerance", 0.0), + rclcpp::Parameter("allow_nonzero_velocity_at_trajectory_end", true)}; + SetUpExecutor(params, false, 1.0, 0.0); + SetUpControllerHardware(); + + // add feedback + bool feedback_recv = false; + goal_options_.feedback_callback = + [&]( + rclcpp_action::ClientGoalHandle::SharedPtr, + const std::shared_ptr) { feedback_recv = true; }; + + std::shared_future gh_future; + // send goal with multiple points + std::vector> points_positions{{{4.0, 5.0, 6.0}}, {{7.0, 8.0, 9.0}}}; + std::vector> points_velocities{{{1.0, 1.0, 1.0}}, {{2.0, 2.0, 2.0}}}; { - // no integration to position state interface from velocity/acceleration - expectHoldingPoint(INITIAL_POS_JOINTS); + std::vector points; + JointTrajectoryPoint point1; + point1.time_from_start = rclcpp::Duration::from_seconds(0.2); + point1.positions = points_positions.at(0); + point1.velocities = points_velocities.at(0); + points.push_back(point1); + + JointTrajectoryPoint point2; + point2.time_from_start = rclcpp::Duration::from_seconds(0.3); + point2.positions = points_positions.at(1); + point2.velocities = points_velocities.at(1); + points.push_back(point2); + + gh_future = sendActionGoal(points, 1.0, goal_options_); } + controller_hw_thread_.join(); + + EXPECT_TRUE(feedback_recv); + EXPECT_TRUE(gh_future.get()); + EXPECT_EQ(rclcpp_action::ResultCode::SUCCEEDED, common_resultcode_); + + // run an update + updateControllerAsync(rclcpp::Duration::from_seconds(0.01)); + + // it should be holding the last position goal + // i.e., active but trivial trajectory (one point only) + expectCommandPoint(points_positions.at(1), points_velocities.at(1)); } /** @@ -354,7 +427,7 @@ TEST_F(TestTrajectoryActions, test_goal_tolerances_single_point_success) // it should be holding the last position goal // i.e., active but trivial trajectory (one point only) - expectHoldingPoint(points_positions.at(0)); + expectCommandPoint(points_positions.at(0)); } /** @@ -413,7 +486,7 @@ TEST_F(TestTrajectoryActions, test_goal_tolerances_multi_point_success) // it should be holding the last position goal // i.e., active but trivial trajectory (one point only) - expectHoldingPoint(points_positions.at(1)); + expectCommandPoint(points_positions.at(1)); } TEST_P(TestTrajectoryActionsTestParameterized, test_state_tolerances_fail) @@ -464,8 +537,7 @@ TEST_P(TestTrajectoryActionsTestParameterized, test_state_tolerances_fail) // it should be holding the position (being the initial one) // i.e., active but trivial trajectory (one point only) - std::vector initial_positions{INITIAL_POS_JOINT1, INITIAL_POS_JOINT2, INITIAL_POS_JOINT3}; - expectHoldingPoint(initial_positions); + expectCommandPoint(INITIAL_POS_JOINTS); } TEST_P(TestTrajectoryActionsTestParameterized, test_goal_tolerances_fail) @@ -513,8 +585,7 @@ TEST_P(TestTrajectoryActionsTestParameterized, test_goal_tolerances_fail) // it should be holding the position (being the initial one) // i.e., active but trivial trajectory (one point only) - std::vector initial_positions{INITIAL_POS_JOINT1, INITIAL_POS_JOINT2, INITIAL_POS_JOINT3}; - expectHoldingPoint(initial_positions); + expectCommandPoint(INITIAL_POS_JOINTS); } TEST_P(TestTrajectoryActionsTestParameterized, test_no_time_from_start_state_tolerance_fail) @@ -559,8 +630,7 @@ TEST_P(TestTrajectoryActionsTestParameterized, test_no_time_from_start_state_tol // it should be holding the position (being the initial one) // i.e., active but trivial trajectory (one point only) - std::vector initial_positions{INITIAL_POS_JOINT1, INITIAL_POS_JOINT2, INITIAL_POS_JOINT3}; - expectHoldingPoint(initial_positions); + expectCommandPoint(INITIAL_POS_JOINTS); } TEST_P(TestTrajectoryActionsTestParameterized, test_cancel_hold_position) @@ -607,7 +677,7 @@ TEST_P(TestTrajectoryActionsTestParameterized, test_cancel_hold_position) // it should be holding the last position, // i.e., active but trivial trajectory (one point only) - expectHoldingPoint(cancelled_position); + expectCommandPoint(cancelled_position); } TEST_P(TestTrajectoryActionsTestParameterized, test_allow_nonzero_velocity_at_trajectory_end_true) diff --git a/joint_trajectory_controller/test/test_trajectory_controller.cpp b/joint_trajectory_controller/test/test_trajectory_controller.cpp index 0b049000e3..05010c562c 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller.cpp +++ b/joint_trajectory_controller/test/test_trajectory_controller.cpp @@ -248,7 +248,7 @@ TEST_P(TrajectoryControllerTestParameterized, correct_initialization_using_param // it should still be holding the position at time of deactivation // i.e., active but trivial trajectory (one point only) traj_controller_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.1)); - expectHoldingPoint(deactivated_positions); + expectCommandPoint(deactivated_positions); executor.cancel(); } @@ -459,7 +459,7 @@ TEST_P(TrajectoryControllerTestParameterized, hold_on_startup) ASSERT_TRUE(traj_controller_->has_active_traj()); // one point, being the position at startup std::vector initial_positions{INITIAL_POS_JOINT1, INITIAL_POS_JOINT2, INITIAL_POS_JOINT3}; - expectHoldingPoint(initial_positions); + expectCommandPoint(initial_positions); executor.cancel(); } @@ -819,12 +819,12 @@ TEST_P(TrajectoryControllerTestParameterized, timeout) // should hold last position with zero velocity if (traj_controller_->has_position_command_interface()) { - expectHoldingPoint(points.at(2)); + expectCommandPoint(points.at(2)); } else { // no integration to position state interface from velocity/acceleration - expectHoldingPoint(INITIAL_POS_JOINTS); + expectCommandPoint(INITIAL_POS_JOINTS); } executor.cancel(); @@ -1795,7 +1795,7 @@ TEST_P(TrajectoryControllerTestParameterized, test_state_tolerances_fail) updateControllerAsync(rclcpp::Duration(FIRST_POINT_TIME)); // it should have aborted and be holding now - expectHoldingPoint(joint_state_pos_); + expectCommandPoint(joint_state_pos_); } TEST_P(TrajectoryControllerTestParameterized, test_goal_tolerances_fail) @@ -1827,14 +1827,14 @@ TEST_P(TrajectoryControllerTestParameterized, test_goal_tolerances_fail) auto end_time = updateControllerAsync(rclcpp::Duration(4 * FIRST_POINT_TIME)); // it should have aborted and be holding now - expectHoldingPoint(joint_state_pos_); + expectCommandPoint(joint_state_pos_); // what happens if we wait longer but it harms the tolerance again? auto hold_position = joint_state_pos_; joint_state_pos_.at(0) = -3.3; updateControllerAsync(rclcpp::Duration(FIRST_POINT_TIME), end_time); // it should be still holding the old point - expectHoldingPoint(hold_position); + expectCommandPoint(hold_position); } // position controllers diff --git a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp index b530517517..4a65b4ad51 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp +++ b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp @@ -521,7 +521,8 @@ class TrajectoryControllerTest : public ::testing::Test return state_msg_; } - void expectHoldingPoint(std::vector point) + void expectCommandPoint( + std::vector position, std::vector velocity = {0.0, 0.0, 0.0}) { // it should be holding the given point // i.e., active but trivial trajectory (one point only) @@ -531,16 +532,16 @@ class TrajectoryControllerTest : public ::testing::Test { if (traj_controller_->has_position_command_interface()) { - EXPECT_NEAR(point.at(0), joint_pos_[0], COMMON_THRESHOLD); - EXPECT_NEAR(point.at(1), joint_pos_[1], COMMON_THRESHOLD); - EXPECT_NEAR(point.at(2), joint_pos_[2], COMMON_THRESHOLD); + EXPECT_NEAR(position.at(0), joint_pos_[0], COMMON_THRESHOLD); + EXPECT_NEAR(position.at(1), joint_pos_[1], COMMON_THRESHOLD); + EXPECT_NEAR(position.at(2), joint_pos_[2], COMMON_THRESHOLD); } if (traj_controller_->has_velocity_command_interface()) { - EXPECT_EQ(0.0, joint_vel_[0]); - EXPECT_EQ(0.0, joint_vel_[1]); - EXPECT_EQ(0.0, joint_vel_[2]); + EXPECT_EQ(velocity.at(0), joint_vel_[0]); + EXPECT_EQ(velocity.at(1), joint_vel_[1]); + EXPECT_EQ(velocity.at(2), joint_vel_[2]); } if (traj_controller_->has_acceleration_command_interface()) @@ -557,40 +558,29 @@ class TrajectoryControllerTest : public ::testing::Test EXPECT_EQ(0.0, joint_eff_[2]); } } - else + else // traj_controller_->use_closed_loop_pid_adapter() == true { // velocity or effort PID? - // velocity setpoint is always zero -> feedforward term does not have an effect // --> set kp > 0.0 in test if (traj_controller_->has_velocity_command_interface()) { - EXPECT_TRUE( - is_same_sign_or_zero(point.at(0) - pos_state_interfaces_[0].get_value(), joint_vel_[0])) - << "current error: " << point.at(0) - pos_state_interfaces_[0].get_value() - << ", velocity command is " << joint_vel_[0]; - EXPECT_TRUE( - is_same_sign_or_zero(point.at(1) - pos_state_interfaces_[1].get_value(), joint_vel_[1])) - << "current error: " << point.at(1) - pos_state_interfaces_[1].get_value() - << ", velocity command is " << joint_vel_[1]; - EXPECT_TRUE( - is_same_sign_or_zero(point.at(2) - pos_state_interfaces_[2].get_value(), joint_vel_[2])) - << "current error: " << point.at(2) - pos_state_interfaces_[2].get_value() - << ", velocity command is " << joint_vel_[2]; + for (size_t i = 0; i < 3; i++) + { + EXPECT_TRUE(is_same_sign_or_zero( + position.at(i) - pos_state_interfaces_[i].get_value(), joint_vel_[i])) + << "test position point " << position.at(i) << ", position state is " + << pos_state_interfaces_[i].get_value() << ", velocity command is " << joint_vel_[i]; + } } if (traj_controller_->has_effort_command_interface()) { - EXPECT_TRUE( - is_same_sign_or_zero(point.at(0) - pos_state_interfaces_[0].get_value(), joint_eff_[0])) - << "current error: " << point.at(0) - pos_state_interfaces_[0].get_value() - << ", effort command is " << joint_eff_[0]; - EXPECT_TRUE( - is_same_sign_or_zero(point.at(1) - pos_state_interfaces_[1].get_value(), joint_eff_[1])) - << "current error: " << point.at(1) - pos_state_interfaces_[1].get_value() - << ", effort command is " << joint_eff_[1]; - EXPECT_TRUE( - is_same_sign_or_zero(point.at(2) - pos_state_interfaces_[2].get_value(), joint_eff_[2])) - << "current error: " << point.at(2) - pos_state_interfaces_[2].get_value() - << ", effort command is " << joint_eff_[2]; + for (size_t i = 0; i < 3; i++) + { + EXPECT_TRUE(is_same_sign_or_zero( + position.at(i) - pos_state_interfaces_[i].get_value(), joint_eff_[i])) + << "test position point " << position.at(i) << ", position state is " + << pos_state_interfaces_[i].get_value() << ", effort command is " << joint_eff_[i]; + } } } } From 757310073cadb20e551c407354f5a40e09e39a2a Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Fri, 1 Dec 2023 13:45:13 +0000 Subject: [PATCH 158/238] Update changelogs --- ackermann_steering_controller/CHANGELOG.rst | 3 +++ admittance_controller/CHANGELOG.rst | 3 +++ bicycle_steering_controller/CHANGELOG.rst | 3 +++ diff_drive_controller/CHANGELOG.rst | 3 +++ effort_controllers/CHANGELOG.rst | 3 +++ force_torque_sensor_broadcaster/CHANGELOG.rst | 5 +++++ forward_command_controller/CHANGELOG.rst | 5 +++++ gripper_controllers/CHANGELOG.rst | 5 +++++ imu_sensor_broadcaster/CHANGELOG.rst | 5 +++++ joint_state_broadcaster/CHANGELOG.rst | 6 ++++++ joint_trajectory_controller/CHANGELOG.rst | 8 ++++++++ position_controllers/CHANGELOG.rst | 3 +++ range_sensor_broadcaster/CHANGELOG.rst | 5 +++++ ros2_controllers/CHANGELOG.rst | 3 +++ ros2_controllers_test_nodes/CHANGELOG.rst | 3 +++ rqt_joint_trajectory_controller/CHANGELOG.rst | 3 +++ steering_controllers_library/CHANGELOG.rst | 3 +++ tricycle_controller/CHANGELOG.rst | 5 +++++ tricycle_steering_controller/CHANGELOG.rst | 3 +++ velocity_controllers/CHANGELOG.rst | 3 +++ 20 files changed, 80 insertions(+) diff --git a/ackermann_steering_controller/CHANGELOG.rst b/ackermann_steering_controller/CHANGELOG.rst index 7a94360e4b..ebd6d5ef43 100644 --- a/ackermann_steering_controller/CHANGELOG.rst +++ b/ackermann_steering_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ackermann_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.0.0 (2023-11-21) ------------------ * fix tests for API break of passing controller manager update rate in init method (`#854 `_) diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index b94892ac83..19fbe5864d 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.0.0 (2023-11-21) ------------------ * fix tests for API break of passing controller manager update rate in init method (`#854 `_) diff --git a/bicycle_steering_controller/CHANGELOG.rst b/bicycle_steering_controller/CHANGELOG.rst index 278921e18b..dbfe611d52 100644 --- a/bicycle_steering_controller/CHANGELOG.rst +++ b/bicycle_steering_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package bicycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.0.0 (2023-11-21) ------------------ * fix tests for API break of passing controller manager update rate in init method (`#854 `_) diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index 5f57b7e833..e0166e9dd8 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.0.0 (2023-11-21) ------------------ * fix tests for API break of passing controller manager update rate in init method (`#854 `_) diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index 6c7d7d6fa3..963c8916db 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.0.0 (2023-11-21) ------------------ * fix tests for API break of passing controller manager update rate in init method (`#854 `_) diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index 17a6d4f280..005b4ba6ac 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Increase test coverage of interface configuration getters (`#856 `_) +* Contributors: Christoph Fröhlich + 4.0.0 (2023-11-21) ------------------ * fix tests for API break of passing controller manager update rate in init method (`#854 `_) diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index 941b849edd..f65fefd016 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Increase test coverage of interface configuration getters (`#856 `_) +* Contributors: Christoph Fröhlich + 4.0.0 (2023-11-21) ------------------ * fix tests for API break of passing controller manager update rate in init method (`#854 `_) diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index f35dcd1a32..3e06cc1830 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Increase test coverage of interface configuration getters (`#856 `_) +* Contributors: Christoph Fröhlich + 4.0.0 (2023-11-21) ------------------ * fix tests for API break of passing controller manager update rate in init method (`#854 `_) diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index 4d2d2d01b3..b05b8ce192 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Increase test coverage of interface configuration getters (`#856 `_) +* Contributors: Christoph Fröhlich + 4.0.0 (2023-11-21) ------------------ * fix tests for API break of passing controller manager update rate in init method (`#854 `_) diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index ce89b01912..9f80626bb2 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Increase test coverage of interface configuration getters (`#856 `_) +* joint_state_broadcaster: Add proper subscription to TestCustomInterfaceMappingUpdate (`#859 `_) +* Contributors: Christoph Fröhlich + 4.0.0 (2023-11-21) ------------------ * fix tests for API break of passing controller manager update rate in init method (`#854 `_) diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index a4486e4e98..1ad5b44a48 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,14 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* [JTC] Continue with last trajectory-point on success (`#842 `_) +* [JTC] Remove start_with_holding option (`#839 `_) +* [JTC] Activate checks for parameter validation (`#857 `_) +* [JTC] Improve update methods for tests (`#858 `_) +* Contributors: Christoph Fröhlich + 4.0.0 (2023-11-21) ------------------ * fix tests for API break of passing controller manager update rate in init method (`#854 `_) diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index 26462d51a9..caf8f3925c 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.0.0 (2023-11-21) ------------------ * fix tests for API break of passing controller manager update rate in init method (`#854 `_) diff --git a/range_sensor_broadcaster/CHANGELOG.rst b/range_sensor_broadcaster/CHANGELOG.rst index 71ee9a7119..d15eb127e6 100644 --- a/range_sensor_broadcaster/CHANGELOG.rst +++ b/range_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package range_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Increase test coverage of interface configuration getters (`#856 `_) +* Contributors: Christoph Fröhlich + 4.0.0 (2023-11-21) ------------------ * fix tests for API break of passing controller manager update rate in init method (`#854 `_) diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index 2c2e5ec358..9ae67679d7 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.0.0 (2023-11-21) ------------------ diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index e8eaf9c382..c3f8302d06 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.0.0 (2023-11-21) ------------------ diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index 0c08780904..58694e910d 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.0.0 (2023-11-21) ------------------ diff --git a/steering_controllers_library/CHANGELOG.rst b/steering_controllers_library/CHANGELOG.rst index 1a76469d6c..b8f6854520 100644 --- a/steering_controllers_library/CHANGELOG.rst +++ b/steering_controllers_library/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package steering_controllers_library ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.0.0 (2023-11-21) ------------------ * fix tests for API break of passing controller manager update rate in init method (`#854 `_) diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index 6bc3d26f53..9e67804591 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Increase test coverage of interface configuration getters (`#856 `_) +* Contributors: Christoph Fröhlich + 4.0.0 (2023-11-21) ------------------ * fix tests for API break of passing controller manager update rate in init method (`#854 `_) diff --git a/tricycle_steering_controller/CHANGELOG.rst b/tricycle_steering_controller/CHANGELOG.rst index 0ade9bca61..bd2fc2d678 100644 --- a/tricycle_steering_controller/CHANGELOG.rst +++ b/tricycle_steering_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package tricycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.0.0 (2023-11-21) ------------------ * fix tests for API break of passing controller manager update rate in init method (`#854 `_) diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index bb7e231222..cb05fb45f1 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.0.0 (2023-11-21) ------------------ * fix tests for API break of passing controller manager update rate in init method (`#854 `_) From 23f944f26e7e21764be3acdb6610cd59866c9bfc Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Fri, 1 Dec 2023 13:45:35 +0000 Subject: [PATCH 159/238] 4.1.0 --- ackermann_steering_controller/CHANGELOG.rst | 4 ++-- ackermann_steering_controller/package.xml | 2 +- admittance_controller/CHANGELOG.rst | 4 ++-- admittance_controller/package.xml | 2 +- bicycle_steering_controller/CHANGELOG.rst | 4 ++-- bicycle_steering_controller/package.xml | 2 +- diff_drive_controller/CHANGELOG.rst | 4 ++-- diff_drive_controller/package.xml | 2 +- effort_controllers/CHANGELOG.rst | 4 ++-- effort_controllers/package.xml | 2 +- force_torque_sensor_broadcaster/CHANGELOG.rst | 4 ++-- force_torque_sensor_broadcaster/package.xml | 2 +- forward_command_controller/CHANGELOG.rst | 4 ++-- forward_command_controller/package.xml | 2 +- gripper_controllers/CHANGELOG.rst | 4 ++-- gripper_controllers/package.xml | 2 +- imu_sensor_broadcaster/CHANGELOG.rst | 4 ++-- imu_sensor_broadcaster/package.xml | 2 +- joint_state_broadcaster/CHANGELOG.rst | 4 ++-- joint_state_broadcaster/package.xml | 2 +- joint_trajectory_controller/CHANGELOG.rst | 4 ++-- joint_trajectory_controller/package.xml | 2 +- position_controllers/CHANGELOG.rst | 4 ++-- position_controllers/package.xml | 2 +- range_sensor_broadcaster/CHANGELOG.rst | 4 ++-- range_sensor_broadcaster/package.xml | 2 +- ros2_controllers/CHANGELOG.rst | 4 ++-- ros2_controllers/package.xml | 2 +- ros2_controllers_test_nodes/CHANGELOG.rst | 4 ++-- ros2_controllers_test_nodes/package.xml | 2 +- ros2_controllers_test_nodes/setup.py | 2 +- rqt_joint_trajectory_controller/CHANGELOG.rst | 4 ++-- rqt_joint_trajectory_controller/package.xml | 2 +- rqt_joint_trajectory_controller/setup.py | 2 +- steering_controllers_library/CHANGELOG.rst | 4 ++-- steering_controllers_library/package.xml | 2 +- tricycle_controller/CHANGELOG.rst | 4 ++-- tricycle_controller/package.xml | 2 +- tricycle_steering_controller/CHANGELOG.rst | 4 ++-- tricycle_steering_controller/package.xml | 2 +- velocity_controllers/CHANGELOG.rst | 4 ++-- velocity_controllers/package.xml | 2 +- 42 files changed, 62 insertions(+), 62 deletions(-) diff --git a/ackermann_steering_controller/CHANGELOG.rst b/ackermann_steering_controller/CHANGELOG.rst index ebd6d5ef43..a1cbe9596e 100644 --- a/ackermann_steering_controller/CHANGELOG.rst +++ b/ackermann_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ackermann_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.1.0 (2023-12-01) +------------------ 4.0.0 (2023-11-21) ------------------ diff --git a/ackermann_steering_controller/package.xml b/ackermann_steering_controller/package.xml index 421f098f96..476c4d3050 100644 --- a/ackermann_steering_controller/package.xml +++ b/ackermann_steering_controller/package.xml @@ -2,7 +2,7 @@ ackermann_steering_controller - 4.0.0 + 4.1.0 Steering controller for Ackermann kinematics. Rear fixed wheels are powering the vehicle and front wheels are steering it. Apache License 2.0 Bence Magyar diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index 19fbe5864d..615a457992 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.1.0 (2023-12-01) +------------------ 4.0.0 (2023-11-21) ------------------ diff --git a/admittance_controller/package.xml b/admittance_controller/package.xml index a5f7e7e353..da5b652bd0 100644 --- a/admittance_controller/package.xml +++ b/admittance_controller/package.xml @@ -2,7 +2,7 @@ admittance_controller - 4.0.0 + 4.1.0 Implementation of admittance controllers for different input and output interface. Denis Štogl Bence Magyar diff --git a/bicycle_steering_controller/CHANGELOG.rst b/bicycle_steering_controller/CHANGELOG.rst index dbfe611d52..bee3606ec8 100644 --- a/bicycle_steering_controller/CHANGELOG.rst +++ b/bicycle_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package bicycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.1.0 (2023-12-01) +------------------ 4.0.0 (2023-11-21) ------------------ diff --git a/bicycle_steering_controller/package.xml b/bicycle_steering_controller/package.xml index e3063672d6..c627577ee8 100644 --- a/bicycle_steering_controller/package.xml +++ b/bicycle_steering_controller/package.xml @@ -2,7 +2,7 @@ bicycle_steering_controller - 4.0.0 + 4.1.0 Steering controller with bicycle kinematics. Rear fixed wheel is powering the vehicle and front wheel is steering. Apache License 2.0 Bence Magyar diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index e0166e9dd8..8ee42d701f 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.1.0 (2023-12-01) +------------------ 4.0.0 (2023-11-21) ------------------ diff --git a/diff_drive_controller/package.xml b/diff_drive_controller/package.xml index 56b9552f93..03dffe764d 100644 --- a/diff_drive_controller/package.xml +++ b/diff_drive_controller/package.xml @@ -1,7 +1,7 @@ diff_drive_controller - 4.0.0 + 4.1.0 Controller for a differential drive mobile base. Bence Magyar Jordan Palacios diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index 963c8916db..f4496d3927 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.1.0 (2023-12-01) +------------------ 4.0.0 (2023-11-21) ------------------ diff --git a/effort_controllers/package.xml b/effort_controllers/package.xml index ef2610d34f..e55e095c57 100644 --- a/effort_controllers/package.xml +++ b/effort_controllers/package.xml @@ -1,7 +1,7 @@ effort_controllers - 4.0.0 + 4.1.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index 005b4ba6ac..b87aaa2641 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.1.0 (2023-12-01) +------------------ * Increase test coverage of interface configuration getters (`#856 `_) * Contributors: Christoph Fröhlich diff --git a/force_torque_sensor_broadcaster/package.xml b/force_torque_sensor_broadcaster/package.xml index 4a1df9ff11..48db0e49b6 100644 --- a/force_torque_sensor_broadcaster/package.xml +++ b/force_torque_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ force_torque_sensor_broadcaster - 4.0.0 + 4.1.0 Controller to publish state of force-torque sensors. Bence Magyar Denis Štogl diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index f65fefd016..b38f021587 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.1.0 (2023-12-01) +------------------ * Increase test coverage of interface configuration getters (`#856 `_) * Contributors: Christoph Fröhlich diff --git a/forward_command_controller/package.xml b/forward_command_controller/package.xml index 0fe44110b1..c500c1f714 100644 --- a/forward_command_controller/package.xml +++ b/forward_command_controller/package.xml @@ -1,7 +1,7 @@ forward_command_controller - 4.0.0 + 4.1.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index 3e06cc1830..798a0f3e67 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.1.0 (2023-12-01) +------------------ * Increase test coverage of interface configuration getters (`#856 `_) * Contributors: Christoph Fröhlich diff --git a/gripper_controllers/package.xml b/gripper_controllers/package.xml index 08b0298e1f..34c7ba663e 100644 --- a/gripper_controllers/package.xml +++ b/gripper_controllers/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> gripper_controllers - 4.0.0 + 4.1.0 The gripper_controllers package Bence Magyar diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index b05b8ce192..2c311626cf 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.1.0 (2023-12-01) +------------------ * Increase test coverage of interface configuration getters (`#856 `_) * Contributors: Christoph Fröhlich diff --git a/imu_sensor_broadcaster/package.xml b/imu_sensor_broadcaster/package.xml index 1819b974e2..3ab9c5fff6 100644 --- a/imu_sensor_broadcaster/package.xml +++ b/imu_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ imu_sensor_broadcaster - 4.0.0 + 4.1.0 Controller to publish readings of IMU sensors. Bence Magyar Denis Štogl diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index 9f80626bb2..f2295beca3 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.1.0 (2023-12-01) +------------------ * Increase test coverage of interface configuration getters (`#856 `_) * joint_state_broadcaster: Add proper subscription to TestCustomInterfaceMappingUpdate (`#859 `_) * Contributors: Christoph Fröhlich diff --git a/joint_state_broadcaster/package.xml b/joint_state_broadcaster/package.xml index 1364b1a164..37ba7b4912 100644 --- a/joint_state_broadcaster/package.xml +++ b/joint_state_broadcaster/package.xml @@ -1,7 +1,7 @@ joint_state_broadcaster - 4.0.0 + 4.1.0 Broadcaster to publish joint state Bence Magyar Denis Stogl diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index 1ad5b44a48..7e4c25a474 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.1.0 (2023-12-01) +------------------ * [JTC] Continue with last trajectory-point on success (`#842 `_) * [JTC] Remove start_with_holding option (`#839 `_) * [JTC] Activate checks for parameter validation (`#857 `_) diff --git a/joint_trajectory_controller/package.xml b/joint_trajectory_controller/package.xml index fe10d9583d..b41a7cad0c 100644 --- a/joint_trajectory_controller/package.xml +++ b/joint_trajectory_controller/package.xml @@ -1,7 +1,7 @@ joint_trajectory_controller - 4.0.0 + 4.1.0 Controller for executing joint-space trajectories on a group of joints Bence Magyar Jordan Palacios diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index caf8f3925c..6f0870c9ae 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.1.0 (2023-12-01) +------------------ 4.0.0 (2023-11-21) ------------------ diff --git a/position_controllers/package.xml b/position_controllers/package.xml index 2112f7d8c5..1aec89e59d 100644 --- a/position_controllers/package.xml +++ b/position_controllers/package.xml @@ -1,7 +1,7 @@ position_controllers - 4.0.0 + 4.1.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/range_sensor_broadcaster/CHANGELOG.rst b/range_sensor_broadcaster/CHANGELOG.rst index d15eb127e6..be35427e46 100644 --- a/range_sensor_broadcaster/CHANGELOG.rst +++ b/range_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package range_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.1.0 (2023-12-01) +------------------ * Increase test coverage of interface configuration getters (`#856 `_) * Contributors: Christoph Fröhlich diff --git a/range_sensor_broadcaster/package.xml b/range_sensor_broadcaster/package.xml index 3ece4bda4b..222d87e3bb 100644 --- a/range_sensor_broadcaster/package.xml +++ b/range_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ range_sensor_broadcaster - 4.0.0 + 4.1.0 Controller to publish readings of Range sensors. Bence Magyar Florent Chretien diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index 9ae67679d7..46f994c792 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.1.0 (2023-12-01) +------------------ 4.0.0 (2023-11-21) ------------------ diff --git a/ros2_controllers/package.xml b/ros2_controllers/package.xml index 6a213308c5..d34a5b1375 100644 --- a/ros2_controllers/package.xml +++ b/ros2_controllers/package.xml @@ -1,7 +1,7 @@ ros2_controllers - 4.0.0 + 4.1.0 Metapackage for ROS2 controllers related packages Bence Magyar Jordan Palacios diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index c3f8302d06..a7a2f7a1fd 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.1.0 (2023-12-01) +------------------ 4.0.0 (2023-11-21) ------------------ diff --git a/ros2_controllers_test_nodes/package.xml b/ros2_controllers_test_nodes/package.xml index 5698930bff..16dd709c25 100644 --- a/ros2_controllers_test_nodes/package.xml +++ b/ros2_controllers_test_nodes/package.xml @@ -2,7 +2,7 @@ ros2_controllers_test_nodes - 4.0.0 + 4.1.0 Demo nodes for showing and testing functionalities of the ros2_control framework. Denis Štogl diff --git a/ros2_controllers_test_nodes/setup.py b/ros2_controllers_test_nodes/setup.py index a129b2d0a7..baa01b97c2 100644 --- a/ros2_controllers_test_nodes/setup.py +++ b/ros2_controllers_test_nodes/setup.py @@ -20,7 +20,7 @@ setup( name=package_name, - version="4.0.0", + version="4.1.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index 58694e910d..ee80d4b30d 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.1.0 (2023-12-01) +------------------ 4.0.0 (2023-11-21) ------------------ diff --git a/rqt_joint_trajectory_controller/package.xml b/rqt_joint_trajectory_controller/package.xml index 41cf5e85d7..24ed2c9d63 100644 --- a/rqt_joint_trajectory_controller/package.xml +++ b/rqt_joint_trajectory_controller/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> rqt_joint_trajectory_controller - 4.0.0 + 4.1.0 Graphical frontend for interacting with joint_trajectory_controller instances. Bence Magyar diff --git a/rqt_joint_trajectory_controller/setup.py b/rqt_joint_trajectory_controller/setup.py index 5a5b979d41..2d855d9255 100644 --- a/rqt_joint_trajectory_controller/setup.py +++ b/rqt_joint_trajectory_controller/setup.py @@ -7,7 +7,7 @@ setup( name=package_name, - version="4.0.0", + version="4.1.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/steering_controllers_library/CHANGELOG.rst b/steering_controllers_library/CHANGELOG.rst index b8f6854520..bae8e6e557 100644 --- a/steering_controllers_library/CHANGELOG.rst +++ b/steering_controllers_library/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package steering_controllers_library ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.1.0 (2023-12-01) +------------------ 4.0.0 (2023-11-21) ------------------ diff --git a/steering_controllers_library/package.xml b/steering_controllers_library/package.xml index 932fda9a35..5de0ddc872 100644 --- a/steering_controllers_library/package.xml +++ b/steering_controllers_library/package.xml @@ -2,7 +2,7 @@ steering_controllers_library - 4.0.0 + 4.1.0 Package for steering robot configurations including odometry and interfaces. Apache License 2.0 Bence Magyar diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index 9e67804591..0203298259 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.1.0 (2023-12-01) +------------------ * Increase test coverage of interface configuration getters (`#856 `_) * Contributors: Christoph Fröhlich diff --git a/tricycle_controller/package.xml b/tricycle_controller/package.xml index a663dcacde..5f382bf8d2 100644 --- a/tricycle_controller/package.xml +++ b/tricycle_controller/package.xml @@ -2,7 +2,7 @@ tricycle_controller - 4.0.0 + 4.1.0 Controller for a tricycle drive mobile base Bence Magyar Tony Najjar diff --git a/tricycle_steering_controller/CHANGELOG.rst b/tricycle_steering_controller/CHANGELOG.rst index bd2fc2d678..4abf0788fb 100644 --- a/tricycle_steering_controller/CHANGELOG.rst +++ b/tricycle_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package tricycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.1.0 (2023-12-01) +------------------ 4.0.0 (2023-11-21) ------------------ diff --git a/tricycle_steering_controller/package.xml b/tricycle_steering_controller/package.xml index 7f9d14c2fe..f565ef0c02 100644 --- a/tricycle_steering_controller/package.xml +++ b/tricycle_steering_controller/package.xml @@ -2,7 +2,7 @@ tricycle_steering_controller - 4.0.0 + 4.1.0 Steering controller with tricycle kinematics. Rear fixed wheels are powering the vehicle and front wheel is steering. Apache License 2.0 Bence Magyar diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index cb05fb45f1..91575e6075 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.1.0 (2023-12-01) +------------------ 4.0.0 (2023-11-21) ------------------ diff --git a/velocity_controllers/package.xml b/velocity_controllers/package.xml index 6ce13e6adf..d7376e8e6b 100644 --- a/velocity_controllers/package.xml +++ b/velocity_controllers/package.xml @@ -1,7 +1,7 @@ velocity_controllers - 4.0.0 + 4.1.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios From 038a54794ef06147e7a4ab5298b8c9eabe65e287 Mon Sep 17 00:00:00 2001 From: "Dr. Denis" Date: Mon, 4 Dec 2023 20:01:15 +0100 Subject: [PATCH 160/238] =?UTF-8?q?=F0=9F=9A=80=20Add=20PID=20controller?= =?UTF-8?q?=20=F0=9F=8E=89=20(#434)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/controllers_index.rst | 1 + pid_controller/CMakeLists.txt | 108 ++++ pid_controller/README.md | 7 + pid_controller/doc/userdoc.rst | 86 +++ .../include/pid_controller/pid_controller.hpp | 141 +++++ .../pid_controller/visibility_control.h | 49 ++ pid_controller/package.xml | 35 ++ pid_controller/pid_controller.xml | 8 + pid_controller/src/pid_controller.cpp | 521 +++++++++++++++++ pid_controller/src/pid_controller.yaml | 87 +++ .../test/pid_controller_params.yaml | 11 + .../test/pid_controller_preceding_params.yaml | 11 + .../test/test_load_pid_controller.cpp | 43 ++ pid_controller/test/test_pid_controller.cpp | 531 ++++++++++++++++++ pid_controller/test/test_pid_controller.hpp | 285 ++++++++++ .../test/test_pid_controller_preceding.cpp | 103 ++++ ros2_controllers/package.xml | 1 + 17 files changed, 2028 insertions(+) create mode 100644 pid_controller/CMakeLists.txt create mode 100644 pid_controller/README.md create mode 100644 pid_controller/doc/userdoc.rst create mode 100644 pid_controller/include/pid_controller/pid_controller.hpp create mode 100644 pid_controller/include/pid_controller/visibility_control.h create mode 100644 pid_controller/package.xml create mode 100644 pid_controller/pid_controller.xml create mode 100644 pid_controller/src/pid_controller.cpp create mode 100644 pid_controller/src/pid_controller.yaml create mode 100644 pid_controller/test/pid_controller_params.yaml create mode 100644 pid_controller/test/pid_controller_preceding_params.yaml create mode 100644 pid_controller/test/test_load_pid_controller.cpp create mode 100644 pid_controller/test/test_pid_controller.cpp create mode 100644 pid_controller/test/test_pid_controller.hpp create mode 100644 pid_controller/test/test_pid_controller_preceding.cpp diff --git a/doc/controllers_index.rst b/doc/controllers_index.rst index 5f8780d961..d042fe79dd 100644 --- a/doc/controllers_index.rst +++ b/doc/controllers_index.rst @@ -55,6 +55,7 @@ The controllers are using `common hardware interface definitions`_, and may use Forward Command Controller <../forward_command_controller/doc/userdoc.rst> Gripper Controller <../gripper_controllers/doc/userdoc.rst> Joint Trajectory Controller <../joint_trajectory_controller/doc/userdoc.rst> + PID Controller <../pid_controller/doc/userdoc.rst> Position Controllers <../position_controllers/doc/userdoc.rst> Velocity Controllers <../velocity_controllers/doc/userdoc.rst> diff --git a/pid_controller/CMakeLists.txt b/pid_controller/CMakeLists.txt new file mode 100644 index 0000000000..81cbe6f006 --- /dev/null +++ b/pid_controller/CMakeLists.txt @@ -0,0 +1,108 @@ +cmake_minimum_required(VERSION 3.16) +project(pid_controller LANGUAGES CXX) + +if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") + add_compile_options(-Wall -Wextra) +endif() + +set(THIS_PACKAGE_INCLUDE_DEPENDS + angles + control_msgs + control_toolbox + controller_interface + generate_parameter_library + hardware_interface + parameter_traits + pluginlib + rclcpp + rclcpp_lifecycle + realtime_tools + std_srvs +) + +find_package(ament_cmake REQUIRED) +find_package(backward_ros REQUIRED) +foreach(Dependency IN ITEMS ${THIS_PACKAGE_INCLUDE_DEPENDS}) + find_package(${Dependency} REQUIRED) +endforeach() + +generate_parameter_library(pid_controller_parameters + src/pid_controller.yaml +) + +add_library(pid_controller SHARED + src/pid_controller.cpp +) +target_compile_features(pid_controller PUBLIC cxx_std_17) +target_include_directories(pid_controller PUBLIC + $ + $ +) +target_link_libraries(pid_controller PUBLIC + pid_controller_parameters +) +ament_target_dependencies(pid_controller PUBLIC ${THIS_PACKAGE_INCLUDE_DEPENDS}) + +# Causes the visibility macros to use dllexport rather than dllimport, +# which is appropriate when building the dll but not consuming it. +target_compile_definitions(pid_controller PRIVATE "PID_CONTROLLER_BUILDING_DLL") + +pluginlib_export_plugin_description_file(controller_interface pid_controller.xml) + +if(BUILD_TESTING) + find_package(ament_cmake_gmock REQUIRED) + find_package(controller_manager REQUIRED) + find_package(ros2_control_test_assets REQUIRED) + + add_rostest_with_parameters_gmock( + test_pid_controller + test/test_pid_controller.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test/pid_controller_params.yaml + ) + target_include_directories(test_pid_controller PRIVATE include) + target_link_libraries(test_pid_controller pid_controller) + ament_target_dependencies( + test_pid_controller + controller_interface + hardware_interface + ) + + add_rostest_with_parameters_gmock( + test_pid_controller_preceding + test/test_pid_controller_preceding.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test/pid_controller_preceding_params.yaml + ) + target_include_directories(test_pid_controller_preceding PRIVATE include) + target_link_libraries(test_pid_controller_preceding pid_controller) + ament_target_dependencies( + test_pid_controller_preceding + controller_interface + hardware_interface + ) + + ament_add_gmock(test_load_pid_controller test/test_load_pid_controller.cpp) + target_include_directories(test_load_pid_controller PRIVATE include) + ament_target_dependencies( + test_load_pid_controller + controller_manager + ros2_control_test_assets + ) +endif() + +install( + DIRECTORY include/ + DESTINATION include/pid_controller +) + +install(TARGETS + pid_controller + pid_controller_parameters + EXPORT export_pid_controller + RUNTIME DESTINATION bin + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib +) + +ament_export_targets(export_pid_controller HAS_LIBRARY_TARGET) +ament_export_dependencies(${THIS_PACKAGE_INCLUDE_DEPENDS}) +ament_package() diff --git a/pid_controller/README.md b/pid_controller/README.md new file mode 100644 index 0000000000..01e8fddac8 --- /dev/null +++ b/pid_controller/README.md @@ -0,0 +1,7 @@ +pid_controller +========================================== + +Controller based on PID implementation from control_toolbox package. + +Pluginlib-Library: pid_controller +Plugin: pid_controller/PidController (controller_interface::ControllerInterface) diff --git a/pid_controller/doc/userdoc.rst b/pid_controller/doc/userdoc.rst new file mode 100644 index 0000000000..5570f523fe --- /dev/null +++ b/pid_controller/doc/userdoc.rst @@ -0,0 +1,86 @@ +:github_url: https://github.com/ros-controls/ros2_controllers/blob/{REPOS_FILE_BRANCH}/pid_controller/doc/userdoc.rst + +.. _pid_controller_userdoc: + +PID Controller +-------------------------------- + +PID Controller implementation that uses PidROS implementation from `control_toolbox `_ package. +The controller can be used directly by sending references through a topic or in a chain having preceding or following controllers. +It also enables to use the first derivative of the reference and its feedback to have second-order PID control. + +Depending on the reference/state and command interface of the hardware a different parameter setup of PidROS should be used as for example: + +- reference/state POSITION; command VELOCITY --> PI CONTROLLER +- reference/state VELOCITY; command ACCELERATION --> PI CONTROLLER + +- reference/state VELOCITY; command POSITION --> PD CONTROLLER +- reference/state ACCELERATION; command VELOCITY --> PD CONTROLLER + +- reference/state POSITION; command POSITION --> PID CONTROLLER +- reference/state VELOCITY; command VELOCITY --> PID CONTROLLER +- reference/state ACCELERATION; command ACCELERATION --> PID CONTROLLER +- reference/state EFFORT; command EFFORT --> PID CONTROLLER + +.. note:: + + Theoretically one can misuse :ref:`Joint Trajectory Controller (JTC)` for the same purpose by sending only one reference point into it. + Nevertheless, this is not recommended. JTC should be used if you need to interpolate between trajectory points using linear, cubic or quintic interpolation. PID Controller doesn't do that. + PID term of JTC has different purpose - it enables commanding only ``velocity`` or ``effort`` interfaces to hardware. + +Execution logic of the controller +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The controller can be also used in "feed-forward" mode where feed-forward gain is used to increase controllers dynamics. +If one type of the reference and state interfaces is used, only immediate error is used. If there are two, then the second interface type is considered to be the first derivative of the first type. +For example a valid combination would be ``position`` and ``velocity`` interface types. + +Using the controller +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Pluginlib-Library: pid_controller +Plugin name: pid_controller/PidController + +Description of controller's interfaces +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +References (from a preceding controller) +,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +- / [double] + **NOTE**: ``reference_and_state_dof_names[i]`` can be from ``reference_and_state_dof_names`` parameter, or if it is empty then ``dof_names``. + +Commands +,,,,,,,,, +- / [double] + +States +,,,,,,, +- / [double] + **NOTE**: ``reference_and_state_dof_names[i]`` can be from ``reference_and_state_dof_names`` parameter, or if it is empty then ``dof_names``. + + +Subscribers +,,,,,,,,,,,, +If controller is not in chained mode (``in_chained_mode == false``): + +- /reference [control_msgs/msg/MultiDOFCommand] + +If controller parameter ``use_external_measured_states`` is true: + +- /measured_state [control_msgs/msg/MultiDOFCommand] + +Services +,,,,,,,,,,, + +- /set_feedforward_control [std_srvs/srv/SetBool] + +Publishers +,,,,,,,,,,, +- /controller_state [control_msgs/msg/MultiDOFStateStamped] + +Parameters +,,,,,,,,,,, + +The PID controller uses the `generate_parameter_library `_ to handle its parameters. + +.. generate_parameter_library_details:: ../src/pid_controller.yaml diff --git a/pid_controller/include/pid_controller/pid_controller.hpp b/pid_controller/include/pid_controller/pid_controller.hpp new file mode 100644 index 0000000000..a34dc9f87f --- /dev/null +++ b/pid_controller/include/pid_controller/pid_controller.hpp @@ -0,0 +1,141 @@ +// Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Authors: Daniel Azanov, Dr. Denis +// + +#ifndef PID_CONTROLLER__PID_CONTROLLER_HPP_ +#define PID_CONTROLLER__PID_CONTROLLER_HPP_ + +#include +#include +#include + +#include "control_msgs/msg/multi_dof_command.hpp" +#include "control_msgs/msg/multi_dof_state_stamped.hpp" +#include "control_toolbox/pid_ros.hpp" +#include "controller_interface/chainable_controller_interface.hpp" +#include "pid_controller/visibility_control.h" +#include "pid_controller_parameters.hpp" +#include "rclcpp_lifecycle/node_interfaces/lifecycle_node_interface.hpp" +#include "rclcpp_lifecycle/state.hpp" +#include "realtime_tools/realtime_buffer.h" +#include "realtime_tools/realtime_publisher.h" +#include "std_srvs/srv/set_bool.hpp" + +#include "control_msgs/msg/joint_controller_state.hpp" +#include "control_msgs/msg/joint_jog.hpp" + +#include "control_msgs/msg/pid_state.hpp" +#include "trajectory_msgs/msg/joint_trajectory_point.hpp" + +namespace pid_controller +{ + +enum class feedforward_mode_type : std::uint8_t +{ + OFF = 0, + ON = 1, +}; + +class PidController : public controller_interface::ChainableControllerInterface +{ +public: + PID_CONTROLLER__VISIBILITY_PUBLIC + PidController(); + + PID_CONTROLLER__VISIBILITY_PUBLIC + controller_interface::CallbackReturn on_init() override; + + PID_CONTROLLER__VISIBILITY_PUBLIC + controller_interface::InterfaceConfiguration command_interface_configuration() const override; + + PID_CONTROLLER__VISIBILITY_PUBLIC + controller_interface::InterfaceConfiguration state_interface_configuration() const override; + + PID_CONTROLLER__VISIBILITY_PUBLIC + controller_interface::CallbackReturn on_cleanup( + const rclcpp_lifecycle::State & previous_state) override; + + PID_CONTROLLER__VISIBILITY_PUBLIC + controller_interface::CallbackReturn on_configure( + const rclcpp_lifecycle::State & previous_state) override; + + PID_CONTROLLER__VISIBILITY_PUBLIC + controller_interface::CallbackReturn on_activate( + const rclcpp_lifecycle::State & previous_state) override; + + PID_CONTROLLER__VISIBILITY_PUBLIC + controller_interface::CallbackReturn on_deactivate( + const rclcpp_lifecycle::State & previous_state) override; + + PID_CONTROLLER__VISIBILITY_PUBLIC + controller_interface::return_type update_reference_from_subscribers( + const rclcpp::Time & time, const rclcpp::Duration & period) override; + + PID_CONTROLLER__VISIBILITY_PUBLIC + controller_interface::return_type update_and_write_commands( + const rclcpp::Time & time, const rclcpp::Duration & period) override; + + using ControllerReferenceMsg = control_msgs::msg::MultiDOFCommand; + using ControllerMeasuredStateMsg = control_msgs::msg::MultiDOFCommand; + using ControllerModeSrvType = std_srvs::srv::SetBool; + using ControllerStateMsg = control_msgs::msg::MultiDOFStateStamped; + +protected: + std::shared_ptr param_listener_; + pid_controller::Params params_; + + std::vector reference_and_state_dof_names_; + size_t dof_; + std::vector measured_state_values_; + + using PidPtr = std::shared_ptr; + std::vector pids_; + // Feed-forward velocity weight factor when calculating closed loop pid adapter's command + std::vector feedforward_gain_; + + // Command subscribers and Controller State publisher + rclcpp::Subscription::SharedPtr ref_subscriber_ = nullptr; + realtime_tools::RealtimeBuffer> input_ref_; + + rclcpp::Subscription::SharedPtr measured_state_subscriber_ = nullptr; + realtime_tools::RealtimeBuffer> measured_state_; + + rclcpp::Service::SharedPtr set_feedforward_control_service_; + realtime_tools::RealtimeBuffer control_mode_; + + using ControllerStatePublisher = realtime_tools::RealtimePublisher; + + rclcpp::Publisher::SharedPtr s_publisher_; + std::unique_ptr state_publisher_; + + // override methods from ChainableControllerInterface + std::vector on_export_reference_interfaces() override; + + bool on_set_chained_mode(bool chained_mode) override; + + // internal methods + void update_parameters(); + controller_interface::CallbackReturn configure_parameters(); + +private: + // callback for topic interface + PID_CONTROLLER__VISIBILITY_LOCAL + void reference_callback(const std::shared_ptr msg); +}; + +} // namespace pid_controller + +#endif // PID_CONTROLLER__PID_CONTROLLER_HPP_ diff --git a/pid_controller/include/pid_controller/visibility_control.h b/pid_controller/include/pid_controller/visibility_control.h new file mode 100644 index 0000000000..1509364b5a --- /dev/null +++ b/pid_controller/include/pid_controller/visibility_control.h @@ -0,0 +1,49 @@ +// Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef PID_CONTROLLER__VISIBILITY_CONTROL_H_ +#define PID_CONTROLLER__VISIBILITY_CONTROL_H_ + +// This logic was borrowed (then namespaced) from the examples on the gcc wiki: +// https://gcc.gnu.org/wiki/Visibility + +#if defined _WIN32 || defined __CYGWIN__ +#ifdef __GNUC__ +#define PID_CONTROLLER__VISIBILITY_EXPORT __attribute__((dllexport)) +#define PID_CONTROLLER__VISIBILITY_IMPORT __attribute__((dllimport)) +#else +#define PID_CONTROLLER__VISIBILITY_EXPORT __declspec(dllexport) +#define PID_CONTROLLER__VISIBILITY_IMPORT __declspec(dllimport) +#endif +#ifdef PID_CONTROLLER__VISIBILITY_BUILDING_DLL +#define PID_CONTROLLER__VISIBILITY_PUBLIC PID_CONTROLLER__VISIBILITY_EXPORT +#else +#define PID_CONTROLLER__VISIBILITY_PUBLIC PID_CONTROLLER__VISIBILITY_IMPORT +#endif +#define PID_CONTROLLER__VISIBILITY_PUBLIC_TYPE PID_CONTROLLER__VISIBILITY_PUBLIC +#define PID_CONTROLLER__VISIBILITY_LOCAL +#else +#define PID_CONTROLLER__VISIBILITY_EXPORT __attribute__((visibility("default"))) +#define PID_CONTROLLER__VISIBILITY_IMPORT +#if __GNUC__ >= 4 +#define PID_CONTROLLER__VISIBILITY_PUBLIC __attribute__((visibility("default"))) +#define PID_CONTROLLER__VISIBILITY_LOCAL __attribute__((visibility("hidden"))) +#else +#define PID_CONTROLLER__VISIBILITY_PUBLIC +#define PID_CONTROLLER__VISIBILITY_LOCAL +#endif +#define PID_CONTROLLER__VISIBILITY_PUBLIC_TYPE +#endif + +#endif // PID_CONTROLLER__VISIBILITY_CONTROL_H_ diff --git a/pid_controller/package.xml b/pid_controller/package.xml new file mode 100644 index 0000000000..7d52121582 --- /dev/null +++ b/pid_controller/package.xml @@ -0,0 +1,35 @@ + + + + pid_controller + 0.0.0 + Controller based on PID implememenation from control_toolbox package. + Bence Magyar + Denis Štogl + Denis Štogl + Apache-2.0 + + ament_cmake + + generate_parameter_library + + angles + control_msgs + control_toolbox + controller_interface + hardware_interface + parameter_traits + pluginlib + rclcpp + rclcpp_lifecycle + realtime_tools + std_srvs + + ament_cmake_gmock + controller_manager + ros2_control_test_assets + + + ament_cmake + + diff --git a/pid_controller/pid_controller.xml b/pid_controller/pid_controller.xml new file mode 100644 index 0000000000..5b90741ae6 --- /dev/null +++ b/pid_controller/pid_controller.xml @@ -0,0 +1,8 @@ + + + + PidController ros2_control controller. + + + diff --git a/pid_controller/src/pid_controller.cpp b/pid_controller/src/pid_controller.cpp new file mode 100644 index 0000000000..373e941d96 --- /dev/null +++ b/pid_controller/src/pid_controller.cpp @@ -0,0 +1,521 @@ +// Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Authors: Daniel Azanov, Dr. Denis +// + +#include "pid_controller/pid_controller.hpp" + +#include +#include +#include +#include + +#include "angles/angles.h" +#include "control_msgs/msg/single_dof_state.hpp" +#include "controller_interface/helpers.hpp" + +namespace +{ // utility + +// Changed services history QoS to keep all so we don't lose any client service calls +rclcpp::QoS qos_services = + rclcpp::QoS(rclcpp::QoSInitialization(RMW_QOS_POLICY_HISTORY_KEEP_ALL, 1)) + .reliable() + .durability_volatile(); + +using ControllerCommandMsg = pid_controller::PidController::ControllerReferenceMsg; + +// called from RT control loop +void reset_controller_reference_msg( + const std::shared_ptr & msg, const std::vector & dof_names) +{ + msg->dof_names = dof_names; + msg->values.resize(dof_names.size(), std::numeric_limits::quiet_NaN()); + msg->values_dot.resize(dof_names.size(), std::numeric_limits::quiet_NaN()); +} + +void reset_controller_measured_state_msg( + const std::shared_ptr & msg, const std::vector & dof_names) +{ + reset_controller_reference_msg(msg, dof_names); +} + +} // namespace + +namespace pid_controller +{ +PidController::PidController() : controller_interface::ChainableControllerInterface() {} + +controller_interface::CallbackReturn PidController::on_init() +{ + control_mode_.initRT(feedforward_mode_type::OFF); + + try + { + param_listener_ = std::make_shared(get_node()); + } + catch (const std::exception & e) + { + fprintf(stderr, "Exception thrown during controller's init with message: %s \n", e.what()); + return controller_interface::CallbackReturn::ERROR; + } + + return controller_interface::CallbackReturn::SUCCESS; +} + +void PidController::update_parameters() +{ + if (!param_listener_->is_old(params_)) + { + return; + } + params_ = param_listener_->get_params(); +} + +controller_interface::CallbackReturn PidController::configure_parameters() +{ + update_parameters(); + + if (!params_.reference_and_state_dof_names.empty()) + { + reference_and_state_dof_names_ = params_.reference_and_state_dof_names; + } + else + { + reference_and_state_dof_names_ = params_.dof_names; + } + + if (params_.dof_names.size() != reference_and_state_dof_names_.size()) + { + RCLCPP_FATAL( + get_node()->get_logger(), + "Size of 'dof_names' (%zu) and 'reference_and_state_dof_names' (%zu) parameters has to be " + "the same!", + params_.dof_names.size(), reference_and_state_dof_names_.size()); + return CallbackReturn::FAILURE; + } + + dof_ = params_.dof_names.size(); + + // TODO(destogl): is this even possible? Test it... + if (params_.gains.dof_names_map.size() != dof_) + { + RCLCPP_FATAL( + get_node()->get_logger(), + "Size of 'gains' (%zu) map and number or 'dof_names' (%zu) have to be the same!", + params_.gains.dof_names_map.size(), dof_); + return CallbackReturn::FAILURE; + } + + pids_.resize(dof_); + + for (size_t i = 0; i < dof_; ++i) + { + // prefix should be interpreted as parameters prefix + pids_[i] = + std::make_shared(get_node(), "gains." + params_.dof_names[i], true); + if (!pids_[i]->initPid()) + { + return CallbackReturn::FAILURE; + } + } + + return CallbackReturn::SUCCESS; +} + +controller_interface::CallbackReturn PidController::on_cleanup( + const rclcpp_lifecycle::State & /*previous_state*/) +{ + reference_and_state_dof_names_.clear(); + pids_.clear(); + + return CallbackReturn::SUCCESS; +} + +controller_interface::CallbackReturn PidController::on_configure( + const rclcpp_lifecycle::State & /*previous_state*/) +{ + auto ret = configure_parameters(); + if (ret != CallbackReturn::SUCCESS) + { + return ret; + } + + // topics QoS + auto subscribers_qos = rclcpp::SystemDefaultsQoS(); + subscribers_qos.keep_last(1); + subscribers_qos.best_effort(); + + // Reference Subscriber + ref_subscriber_ = get_node()->create_subscription( + "~/reference", subscribers_qos, + std::bind(&PidController::reference_callback, this, std::placeholders::_1)); + + std::shared_ptr msg = std::make_shared(); + reset_controller_reference_msg(msg, reference_and_state_dof_names_); + input_ref_.writeFromNonRT(msg); + + // input state Subscriber and callback + if (params_.use_external_measured_states) + { + auto measured_state_callback = + [&](const std::shared_ptr msg) -> void + { + // TODO(destogl): Sort the input values based on joint and interface names + measured_state_.writeFromNonRT(msg); + }; + measured_state_subscriber_ = get_node()->create_subscription( + "~/measured_state", subscribers_qos, measured_state_callback); + } + std::shared_ptr measured_state_msg = + std::make_shared(); + reset_controller_measured_state_msg(measured_state_msg, reference_and_state_dof_names_); + measured_state_.writeFromNonRT(measured_state_msg); + + measured_state_values_.resize( + dof_ * params_.reference_and_state_interfaces.size(), std::numeric_limits::quiet_NaN()); + + auto set_feedforward_control_callback = + [&]( + const std::shared_ptr request, + std::shared_ptr response) + { + if (request->data) + { + control_mode_.writeFromNonRT(feedforward_mode_type::ON); + } + else + { + control_mode_.writeFromNonRT(feedforward_mode_type::OFF); + } + response->success = true; + }; + + set_feedforward_control_service_ = get_node()->create_service( + "~/set_feedforward_control", set_feedforward_control_callback, qos_services); + + try + { + // State publisher + s_publisher_ = get_node()->create_publisher( + "~/controller_state", rclcpp::SystemDefaultsQoS()); + state_publisher_ = std::make_unique(s_publisher_); + } + catch (const std::exception & e) + { + fprintf( + stderr, "Exception thrown during publisher creation at configure stage with message : %s \n", + e.what()); + return controller_interface::CallbackReturn::ERROR; + } + + // Reserve memory in state publisher + state_publisher_->lock(); + state_publisher_->msg_.dof_states.resize(reference_and_state_dof_names_.size()); + for (size_t i = 0; i < reference_and_state_dof_names_.size(); ++i) + { + state_publisher_->msg_.dof_states[i].name = reference_and_state_dof_names_[i]; + } + state_publisher_->unlock(); + + RCLCPP_INFO(get_node()->get_logger(), "configure successful"); + return controller_interface::CallbackReturn::SUCCESS; +} + +void PidController::reference_callback(const std::shared_ptr msg) +{ + if (msg->dof_names.empty() && msg->values.size() == reference_and_state_dof_names_.size()) + { + RCLCPP_WARN( + get_node()->get_logger(), + "Reference massage does not have DoF names defined. " + "Assuming that value have order as defined state DoFs"); + auto ref_msg = msg; + ref_msg->dof_names = reference_and_state_dof_names_; + input_ref_.writeFromNonRT(ref_msg); + } + else if ( + msg->dof_names.size() == reference_and_state_dof_names_.size() && + msg->values.size() == reference_and_state_dof_names_.size()) + { + auto ref_msg = msg; // simple initialization + + // sort values in the ref_msg + reset_controller_reference_msg(msg, reference_and_state_dof_names_); + + bool all_found = true; + for (size_t i = 0; i < msg->dof_names.size(); ++i) + { + auto found_it = + std::find(ref_msg->dof_names.begin(), ref_msg->dof_names.end(), msg->dof_names[i]); + if (found_it == msg->dof_names.end()) + { + all_found = false; + RCLCPP_WARN( + get_node()->get_logger(), "DoF name '%s' not found in the defined list of state DoFs.", + msg->dof_names[i].c_str()); + break; + } + + auto position = std::distance(ref_msg->dof_names.begin(), found_it); + ref_msg->values[position] = msg->values[i]; + ref_msg->values_dot[position] = msg->values_dot[i]; + } + + if (all_found) + { + input_ref_.writeFromNonRT(ref_msg); + } + } + else + { + RCLCPP_ERROR( + get_node()->get_logger(), + "Size of input data names (%zu) and/or values (%zu) is not matching the expected size (%zu).", + msg->dof_names.size(), msg->values.size(), reference_and_state_dof_names_.size()); + } +} + +controller_interface::InterfaceConfiguration PidController::command_interface_configuration() const +{ + controller_interface::InterfaceConfiguration command_interfaces_config; + command_interfaces_config.type = controller_interface::interface_configuration_type::INDIVIDUAL; + + command_interfaces_config.names.reserve(params_.dof_names.size()); + for (const auto & dof_name : params_.dof_names) + { + command_interfaces_config.names.push_back(dof_name + "/" + params_.command_interface); + } + + return command_interfaces_config; +} + +controller_interface::InterfaceConfiguration PidController::state_interface_configuration() const +{ + controller_interface::InterfaceConfiguration state_interfaces_config; + + if (params_.use_external_measured_states) + { + state_interfaces_config.type = controller_interface::interface_configuration_type::NONE; + } + else + { + state_interfaces_config.type = controller_interface::interface_configuration_type::INDIVIDUAL; + + state_interfaces_config.names.reserve(dof_ * params_.reference_and_state_interfaces.size()); + for (const auto & interface : params_.reference_and_state_interfaces) + { + for (const auto & dof_name : reference_and_state_dof_names_) + { + state_interfaces_config.names.push_back(dof_name + "/" + interface); + } + } + } + + return state_interfaces_config; +} + +std::vector PidController::on_export_reference_interfaces() +{ + reference_interfaces_.resize( + dof_ * params_.reference_and_state_interfaces.size(), std::numeric_limits::quiet_NaN()); + + std::vector reference_interfaces; + reference_interfaces.reserve(reference_interfaces_.size()); + + size_t index = 0; + for (const auto & interface : params_.reference_and_state_interfaces) + { + for (const auto & dof_name : reference_and_state_dof_names_) + { + reference_interfaces.push_back(hardware_interface::CommandInterface( + get_node()->get_name(), dof_name + "/" + interface, &reference_interfaces_[index])); + ++index; + } + } + + return reference_interfaces; +} + +bool PidController::on_set_chained_mode(bool chained_mode) +{ + // Always accept switch to/from chained mode + return true || chained_mode; +} + +controller_interface::CallbackReturn PidController::on_activate( + const rclcpp_lifecycle::State & /*previous_state*/) +{ + // Set default value in command (the same number as state interfaces) + reset_controller_reference_msg(*(input_ref_.readFromRT()), reference_and_state_dof_names_); + reset_controller_measured_state_msg( + *(measured_state_.readFromRT()), reference_and_state_dof_names_); + + reference_interfaces_.assign( + reference_interfaces_.size(), std::numeric_limits::quiet_NaN()); + measured_state_values_.assign( + measured_state_values_.size(), std::numeric_limits::quiet_NaN()); + + return controller_interface::CallbackReturn::SUCCESS; +} + +controller_interface::CallbackReturn PidController::on_deactivate( + const rclcpp_lifecycle::State & /*previous_state*/) +{ + return controller_interface::CallbackReturn::SUCCESS; +} + +controller_interface::return_type PidController::update_reference_from_subscribers( + const rclcpp::Time & /*time*/, const rclcpp::Duration & /*period*/) +{ + auto current_ref = input_ref_.readFromRT(); + + for (size_t i = 0; i < dof_; ++i) + { + if (!std::isnan((*current_ref)->values[i])) + { + reference_interfaces_[i] = (*current_ref)->values[i]; + if (reference_interfaces_.size() == 2 * dof_ && !std::isnan((*current_ref)->values_dot[i])) + { + reference_interfaces_[dof_ + i] = (*current_ref)->values_dot[i]; + } + + (*current_ref)->values[i] = std::numeric_limits::quiet_NaN(); + } + } + return controller_interface::return_type::OK; +} + +controller_interface::return_type PidController::update_and_write_commands( + const rclcpp::Time & time, const rclcpp::Duration & period) +{ + // check for any parameter updates + update_parameters(); + + if (params_.use_external_measured_states) + { + const auto measured_state = *(measured_state_.readFromRT()); + for (size_t i = 0; i < dof_; ++i) + { + measured_state_values_[i] = measured_state->values[i]; + if (measured_state_values_.size() == 2 * dof_) + { + measured_state_values_[dof_ + i] = measured_state->values_dot[i]; + } + } + } + else + { + for (size_t i = 0; i < measured_state_values_.size(); ++i) + { + measured_state_values_[i] = state_interfaces_[i].get_value(); + } + } + + for (size_t i = 0; i < dof_; ++i) + { + double tmp_command = std::numeric_limits::quiet_NaN(); + + // Using feedforward + if (!std::isnan(reference_interfaces_[i]) && !std::isnan(measured_state_values_[i])) + { + // calculate feed-forward + if (*(control_mode_.readFromRT()) == feedforward_mode_type::ON) + { + tmp_command = reference_interfaces_[dof_ + i] * + params_.gains.dof_names_map[params_.dof_names[i]].feedforward_gain; + } + else + { + tmp_command = 0.0; + } + + double error = reference_interfaces_[i] - measured_state_values_[i]; + if (params_.gains.dof_names_map[params_.dof_names[i]].angle_wraparound) + { + // for continuous angles the error is normalized between -picomputeCommand( + error, reference_interfaces_[dof_ + i] - measured_state_values_[dof_ + i], period); + } + else + { + // Fallback to calculation with 'error' only + tmp_command += pids_[i]->computeCommand(error, period); + } + } + else + { + // use calculation with 'error' only + tmp_command += pids_[i]->computeCommand(error, period); + } + + // write calculated values + command_interfaces_[i].set_value(tmp_command); + } + } + + if (state_publisher_ && state_publisher_->trylock()) + { + state_publisher_->msg_.header.stamp = time; + for (size_t i = 0; i < dof_; ++i) + { + state_publisher_->msg_.dof_states[i].reference = reference_interfaces_[i]; + state_publisher_->msg_.dof_states[i].feedback = measured_state_values_[i]; + if (reference_interfaces_.size() == 2 * dof_ && measured_state_values_.size() == 2 * dof_) + { + state_publisher_->msg_.dof_states[i].feedback_dot = measured_state_values_[dof_ + i]; + } + state_publisher_->msg_.dof_states[i].error = + reference_interfaces_[i] - measured_state_values_[i]; + if (params_.gains.dof_names_map[params_.dof_names[i]].angle_wraparound) + { + // for continuous angles the error is normalized between -pimsg_.dof_states[i].error = + angles::shortest_angular_distance(measured_state_values_[i], reference_interfaces_[i]); + } + if (reference_interfaces_.size() == 2 * dof_ && measured_state_values_.size() == 2 * dof_) + { + state_publisher_->msg_.dof_states[i].error_dot = + reference_interfaces_[dof_ + i] - measured_state_values_[dof_ + i]; + } + state_publisher_->msg_.dof_states[i].time_step = period.seconds(); + // Command can store the old calculated values. This should be obvious because at least one + // another value is NaN. + state_publisher_->msg_.dof_states[i].output = command_interfaces_[i].get_value(); + } + state_publisher_->unlockAndPublish(); + } + + return controller_interface::return_type::OK; +} + +} // namespace pid_controller + +#include "pluginlib/class_list_macros.hpp" + +PLUGINLIB_EXPORT_CLASS( + pid_controller::PidController, controller_interface::ChainableControllerInterface) diff --git a/pid_controller/src/pid_controller.yaml b/pid_controller/src/pid_controller.yaml new file mode 100644 index 0000000000..f645738862 --- /dev/null +++ b/pid_controller/src/pid_controller.yaml @@ -0,0 +1,87 @@ +pid_controller: + dof_names: { + type: string_array, + default_value: [], + description: "Specifies dof_names or axes used by the controller. If 'reference_and_state_dof_names' parameter is defined, then only command dof names are defined with this parameter.", + read_only: true, + validation: { + unique<>: null, + not_empty<>: null, + } + } + reference_and_state_dof_names: { + type: string_array, + default_value: [], + description: "(optional) Specifies dof_names or axes for getting reference and reading states. This parameter is only relevant when state dof names are different then command dof names, i.e., when a following controller is used.", + read_only: true, + validation: { + unique<>: null, + } + } + command_interface: { + type: string, + default_value: "", + description: "Name of the interface used by the controller for writing commands to the hardware.", + read_only: true, + validation: { + not_empty<>: null, + } + } + reference_and_state_interfaces: { + type: string_array, + default_value: [], + description: "Name of the interfaces used by the controller getting hardware states and reference commands. The second interface should be the derivative of the first.", + read_only: true, + validation: { + not_empty<>: null, + size_lt<>: 3, + } + } + use_external_measured_states: { + type: bool, + default_value: false, + description: "Use external states from a topic instead from state interfaces." + } + gains: + __map_dof_names: + p: { + type: double, + default_value: 0.0, + description: "Proportional gain for PID" + } + i: { + type: double, + default_value: 0.0, + description: "Integral gain for PID" + } + d: { + type: double, + default_value: 0.0, + description: "Derivative gain for PID" + } + antiwindup: { + type: bool, + default_value: false, + description: "Antiwindup functionality." + } + i_clamp_max: { + type: double, + default_value: 0.0, + description: "Upper integral clamp. Only used if antiwindup is activated." + } + i_clamp_min: { + type: double, + default_value: 0.0, + description: "Lower integral clamp. Only used if antiwindup is activated." + } + feedforward_gain: { + type: double, + default_value: 0.0, + description: "Gain for the feed-forward part." + } + angle_wraparound: { + type: bool, + default_value: false, + description: "For joints that wrap around (i.e., are continuous). + Normalizes position-error to -pi to pi." + } diff --git a/pid_controller/test/pid_controller_params.yaml b/pid_controller/test/pid_controller_params.yaml new file mode 100644 index 0000000000..7555cfc156 --- /dev/null +++ b/pid_controller/test/pid_controller_params.yaml @@ -0,0 +1,11 @@ +test_pid_controller: + ros__parameters: + dof_names: + - joint1 + + command_interface: position + + reference_and_state_interfaces: ["position"] + + gains: + joint1: {p: 1.0, i: 2.0, d: 10.0, i_clamp_max: 5.0, i_clamp_min: -5.0} diff --git a/pid_controller/test/pid_controller_preceding_params.yaml b/pid_controller/test/pid_controller_preceding_params.yaml new file mode 100644 index 0000000000..673abfe08e --- /dev/null +++ b/pid_controller/test/pid_controller_preceding_params.yaml @@ -0,0 +1,11 @@ +test_pid_controller: + ros__parameters: + dof_names: + - joint1 + + command_interface: position + + reference_and_state_interfaces: ["position"] + + reference_and_state_dof_names: + - joint1state diff --git a/pid_controller/test/test_load_pid_controller.cpp b/pid_controller/test/test_load_pid_controller.cpp new file mode 100644 index 0000000000..3a75f6e170 --- /dev/null +++ b/pid_controller/test/test_load_pid_controller.cpp @@ -0,0 +1,43 @@ +// Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Authors: Daniel Azanov, Dr. Denis +// + +#include +#include + +#include "controller_manager/controller_manager.hpp" +#include "hardware_interface/resource_manager.hpp" +#include "rclcpp/executor.hpp" +#include "rclcpp/executors/single_threaded_executor.hpp" +#include "rclcpp/utilities.hpp" +#include "ros2_control_test_assets/descriptions.hpp" + +TEST(TestLoadPidController, load_controller) +{ + rclcpp::init(0, nullptr); + + std::shared_ptr executor = + std::make_shared(); + + controller_manager::ControllerManager cm( + std::make_unique( + ros2_control_test_assets::minimal_robot_urdf), + executor, "test_controller_manager"); + + ASSERT_NO_THROW(cm.load_controller("test_pid_controller", "pid_controller/PidController")); + + rclcpp::shutdown(); +} diff --git a/pid_controller/test/test_pid_controller.cpp b/pid_controller/test/test_pid_controller.cpp new file mode 100644 index 0000000000..11f703a1a4 --- /dev/null +++ b/pid_controller/test/test_pid_controller.cpp @@ -0,0 +1,531 @@ +// Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Authors: Daniel Azanov, Dr. Denis +// + +#include "test_pid_controller.hpp" + +#include +#include +#include +#include +#include + +using pid_controller::feedforward_mode_type; + +class PidControllerTest : public PidControllerFixture +{ +}; + +TEST_F(PidControllerTest, all_parameters_set_configure_success) +{ + SetUpController(); + + ASSERT_TRUE(controller_->params_.dof_names.empty()); + ASSERT_TRUE(controller_->params_.reference_and_state_dof_names.empty()); + ASSERT_TRUE(controller_->params_.command_interface.empty()); + ASSERT_TRUE(controller_->params_.reference_and_state_interfaces.empty()); + ASSERT_FALSE(controller_->params_.use_external_measured_states); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + + ASSERT_THAT(controller_->params_.dof_names, testing::ElementsAreArray(dof_names_)); + ASSERT_TRUE(controller_->params_.reference_and_state_dof_names.empty()); + ASSERT_THAT(controller_->reference_and_state_dof_names_, testing::ElementsAreArray(dof_names_)); + for (const auto & dof_name : dof_names_) + { + ASSERT_EQ(controller_->params_.gains.dof_names_map[dof_name].p, 1.0); + ASSERT_EQ(controller_->params_.gains.dof_names_map[dof_name].i, 2.0); + ASSERT_EQ(controller_->params_.gains.dof_names_map[dof_name].d, 10.0); + ASSERT_FALSE(controller_->params_.gains.dof_names_map[dof_name].antiwindup); + ASSERT_EQ(controller_->params_.gains.dof_names_map[dof_name].i_clamp_max, 5.0); + ASSERT_EQ(controller_->params_.gains.dof_names_map[dof_name].i_clamp_min, -5.0); + ASSERT_EQ(controller_->params_.gains.dof_names_map[dof_name].feedforward_gain, 0.0); + } + ASSERT_EQ(controller_->params_.command_interface, command_interface_); + EXPECT_THAT( + controller_->params_.reference_and_state_interfaces, + testing::ElementsAreArray(state_interfaces_)); + ASSERT_FALSE(controller_->params_.use_external_measured_states); +} + +TEST_F(PidControllerTest, check_exported_intefaces) +{ + SetUpController(); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + + auto command_interfaces = controller_->command_interface_configuration(); + ASSERT_EQ(command_interfaces.names.size(), dof_command_values_.size()); + for (size_t i = 0; i < command_interfaces.names.size(); ++i) + { + EXPECT_EQ(command_interfaces.names[i], dof_names_[i] + "/" + command_interface_); + } + + auto state_intefaces = controller_->state_interface_configuration(); + ASSERT_EQ(state_intefaces.names.size(), dof_state_values_.size()); + size_t si_index = 0; + for (const auto & interface : state_interfaces_) + { + for (const auto & dof_name : dof_names_) + { + EXPECT_EQ(state_intefaces.names[si_index], dof_name + "/" + interface); + ++si_index; + } + } + + // check ref itfs + auto reference_interfaces = controller_->export_reference_interfaces(); + ASSERT_EQ(reference_interfaces.size(), dof_state_values_.size()); + size_t ri_index = 0; + for (const auto & interface : state_interfaces_) + { + for (const auto & dof_name : dof_names_) + { + const std::string ref_itf_name = + std::string(controller_->get_node()->get_name()) + "/" + dof_name + "/" + interface; + EXPECT_EQ(reference_interfaces[ri_index].get_name(), ref_itf_name); + EXPECT_EQ( + reference_interfaces[ri_index].get_prefix_name(), controller_->get_node()->get_name()); + EXPECT_EQ(reference_interfaces[ri_index].get_interface_name(), dof_name + "/" + interface); + ++ri_index; + } + } +} + +TEST_F(PidControllerTest, activate_success) +{ + SetUpController(); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + + // check that the message is reset + auto msg = controller_->input_ref_.readFromNonRT(); + EXPECT_EQ((*msg)->values.size(), dof_names_.size()); + for (const auto & cmd : (*msg)->values) + { + EXPECT_TRUE(std::isnan(cmd)); + } + EXPECT_EQ((*msg)->values_dot.size(), dof_names_.size()); + for (const auto & cmd : (*msg)->values_dot) + { + EXPECT_TRUE(std::isnan(cmd)); + } + + EXPECT_EQ(controller_->reference_interfaces_.size(), dof_state_values_.size()); + for (const auto & interface : controller_->reference_interfaces_) + { + EXPECT_TRUE(std::isnan(interface)); + } +} + +TEST_F(PidControllerTest, update_success) +{ + SetUpController(); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + + ASSERT_EQ( + controller_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)), + controller_interface::return_type::OK); +} + +TEST_F(PidControllerTest, deactivate_success) +{ + SetUpController(); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_EQ(controller_->on_deactivate(rclcpp_lifecycle::State()), NODE_SUCCESS); +} + +TEST_F(PidControllerTest, reactivate_success) +{ + SetUpController(); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_TRUE(std::isnan(controller_->reference_interfaces_[0])); + ASSERT_TRUE(std::isnan(controller_->measured_state_values_[0])); + ASSERT_EQ(controller_->command_interfaces_[0].get_value(), 101.101); + ASSERT_EQ(controller_->on_deactivate(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_TRUE(std::isnan(controller_->reference_interfaces_[0])); + ASSERT_TRUE(std::isnan(controller_->measured_state_values_[0])); + ASSERT_EQ(controller_->command_interfaces_[0].get_value(), 101.101); + ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_TRUE(std::isnan(controller_->reference_interfaces_[0])); + ASSERT_TRUE(std::isnan(controller_->measured_state_values_[0])); + ASSERT_EQ(controller_->command_interfaces_[0].get_value(), 101.101); + + ASSERT_EQ( + controller_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)), + controller_interface::return_type::OK); +} + +TEST_F(PidControllerTest, test_feedforward_mode_service) +{ + SetUpController(); + + rclcpp::executors::MultiThreadedExecutor executor; + executor.add_node(controller_->get_node()->get_node_base_interface()); + executor.add_node(service_caller_node_->get_node_base_interface()); + + // initially set to OFF + ASSERT_EQ(*(controller_->control_mode_.readFromRT()), feedforward_mode_type::OFF); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + + // should stay false + ASSERT_EQ(*(controller_->control_mode_.readFromRT()), feedforward_mode_type::OFF); + + // set to true + ASSERT_NO_THROW(call_service(true, executor)); + ASSERT_EQ(*(controller_->control_mode_.readFromRT()), feedforward_mode_type::ON); + + // set back to false + ASSERT_NO_THROW(call_service(false, executor)); + ASSERT_EQ(*(controller_->control_mode_.readFromRT()), feedforward_mode_type::OFF); +} + +TEST_F(PidControllerTest, test_update_logic_feedforward_off) +{ + SetUpController(); + rclcpp::executors::MultiThreadedExecutor executor; + executor.add_node(controller_->get_node()->get_node_base_interface()); + executor.add_node(service_caller_node_->get_node_base_interface()); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + controller_->set_chained_mode(false); + ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_FALSE(controller_->is_in_chained_mode()); + EXPECT_TRUE(std::isnan((*(controller_->input_ref_.readFromRT()))->values[0])); + EXPECT_EQ(*(controller_->control_mode_.readFromRT()), feedforward_mode_type::OFF); + for (const auto & interface : controller_->reference_interfaces_) + { + EXPECT_TRUE(std::isnan(interface)); + } + + std::shared_ptr msg = std::make_shared(); + msg->dof_names = dof_names_; + msg->values.resize(dof_names_.size(), 0.0); + for (size_t i = 0; i < dof_command_values_.size(); ++i) + { + msg->values[i] = dof_command_values_[i]; + } + msg->values_dot.resize(dof_names_.size(), std::numeric_limits::quiet_NaN()); + controller_->input_ref_.writeFromNonRT(msg); + + for (size_t i = 0; i < dof_command_values_.size(); ++i) + { + EXPECT_FALSE(std::isnan((*(controller_->input_ref_.readFromRT()))->values[i])); + EXPECT_EQ((*(controller_->input_ref_.readFromRT()))->values[i], dof_command_values_[i]); + EXPECT_TRUE(std::isnan(controller_->reference_interfaces_[i])); + } + + ASSERT_EQ( + controller_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)), + controller_interface::return_type::OK); + + EXPECT_EQ(*(controller_->control_mode_.readFromRT()), feedforward_mode_type::OFF); + EXPECT_EQ( + controller_->reference_interfaces_.size(), dof_names_.size() * state_interfaces_.size()); + EXPECT_EQ(controller_->reference_interfaces_.size(), dof_state_values_.size()); + for (size_t i = 0; i < dof_command_values_.size(); ++i) + { + EXPECT_TRUE(std::isnan((*(controller_->input_ref_.readFromRT()))->values[i])); + } +} + +TEST_F(PidControllerTest, test_update_logic_feedforward_on) +{ + SetUpController(); + rclcpp::executors::MultiThreadedExecutor executor; + executor.add_node(controller_->get_node()->get_node_base_interface()); + executor.add_node(service_caller_node_->get_node_base_interface()); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + controller_->set_chained_mode(false); + ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_FALSE(controller_->is_in_chained_mode()); + EXPECT_TRUE(std::isnan((*(controller_->input_ref_.readFromRT()))->values[0])); + EXPECT_EQ(*(controller_->control_mode_.readFromRT()), feedforward_mode_type::OFF); + for (const auto & interface : controller_->reference_interfaces_) + { + EXPECT_TRUE(std::isnan(interface)); + } + + std::shared_ptr msg = std::make_shared(); + msg->dof_names = dof_names_; + msg->values.resize(dof_names_.size(), 0.0); + for (size_t i = 0; i < dof_command_values_.size(); ++i) + { + msg->values[i] = dof_command_values_[i]; + } + msg->values_dot.resize(dof_names_.size(), std::numeric_limits::quiet_NaN()); + controller_->input_ref_.writeFromNonRT(msg); + + controller_->control_mode_.writeFromNonRT(feedforward_mode_type::ON); + EXPECT_EQ(*(controller_->control_mode_.readFromRT()), feedforward_mode_type::ON); + + for (size_t i = 0; i < dof_command_values_.size(); ++i) + { + EXPECT_FALSE(std::isnan((*(controller_->input_ref_.readFromRT()))->values[i])); + EXPECT_EQ((*(controller_->input_ref_.readFromRT()))->values[i], dof_command_values_[i]); + EXPECT_TRUE(std::isnan(controller_->reference_interfaces_[i])); + } + + ASSERT_EQ( + controller_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)), + controller_interface::return_type::OK); + + EXPECT_EQ(*(controller_->control_mode_.readFromRT()), feedforward_mode_type::ON); + EXPECT_EQ( + controller_->reference_interfaces_.size(), dof_names_.size() * state_interfaces_.size()); + EXPECT_EQ(controller_->reference_interfaces_.size(), dof_state_values_.size()); + for (size_t i = 0; i < dof_command_values_.size(); ++i) + { + EXPECT_TRUE(std::isnan((*(controller_->input_ref_.readFromRT()))->values[i])); + } +} + +TEST_F(PidControllerTest, test_update_logic_chainable_feedforward_off) +{ + SetUpController(); + rclcpp::executors::MultiThreadedExecutor executor; + executor.add_node(controller_->get_node()->get_node_base_interface()); + executor.add_node(service_caller_node_->get_node_base_interface()); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + controller_->set_chained_mode(true); + ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_TRUE(controller_->is_in_chained_mode()); + + std::shared_ptr msg = std::make_shared(); + msg->dof_names = dof_names_; + msg->values.resize(dof_names_.size(), 0.0); + for (size_t i = 0; i < dof_command_values_.size(); ++i) + { + msg->values[i] = dof_command_values_[i]; + } + msg->values_dot.resize(dof_names_.size(), std::numeric_limits::quiet_NaN()); + controller_->input_ref_.writeFromNonRT(msg); + + for (size_t i = 0; i < dof_command_values_.size(); ++i) + { + EXPECT_FALSE(std::isnan((*(controller_->input_ref_.readFromRT()))->values[i])); + EXPECT_EQ((*(controller_->input_ref_.readFromRT()))->values[i], dof_command_values_[i]); + EXPECT_TRUE(std::isnan(controller_->reference_interfaces_[i])); + } + + ASSERT_EQ( + controller_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)), + controller_interface::return_type::OK); + + ASSERT_TRUE(controller_->is_in_chained_mode()); + EXPECT_EQ(*(controller_->control_mode_.readFromRT()), feedforward_mode_type::OFF); + EXPECT_EQ( + controller_->reference_interfaces_.size(), dof_names_.size() * state_interfaces_.size()); + EXPECT_EQ(controller_->reference_interfaces_.size(), dof_state_values_.size()); + for (size_t i = 0; i < dof_command_values_.size(); ++i) + { + EXPECT_FALSE(std::isnan((*(controller_->input_ref_.readFromRT()))->values[i])); + EXPECT_EQ((*(controller_->input_ref_.readFromRT()))->values[i], dof_command_values_[i]); + } +} + +TEST_F(PidControllerTest, test_update_logic_chainable_feedforward_on) +{ + SetUpController(); + rclcpp::executors::MultiThreadedExecutor executor; + executor.add_node(controller_->get_node()->get_node_base_interface()); + executor.add_node(service_caller_node_->get_node_base_interface()); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + controller_->set_chained_mode(true); + ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_TRUE(controller_->is_in_chained_mode()); + EXPECT_EQ(*(controller_->control_mode_.readFromRT()), feedforward_mode_type::OFF); + + std::shared_ptr msg = std::make_shared(); + msg->dof_names = dof_names_; + msg->values.resize(dof_names_.size(), 0.0); + for (size_t i = 0; i < dof_command_values_.size(); ++i) + { + msg->values[i] = dof_command_values_[i]; + } + msg->values_dot.resize(dof_names_.size(), std::numeric_limits::quiet_NaN()); + controller_->input_ref_.writeFromNonRT(msg); + + controller_->control_mode_.writeFromNonRT(feedforward_mode_type::ON); + EXPECT_EQ(*(controller_->control_mode_.readFromRT()), feedforward_mode_type::ON); + + for (size_t i = 0; i < dof_command_values_.size(); ++i) + { + EXPECT_FALSE(std::isnan((*(controller_->input_ref_.readFromRT()))->values[i])); + EXPECT_EQ((*(controller_->input_ref_.readFromRT()))->values[i], dof_command_values_[i]); + EXPECT_TRUE(std::isnan(controller_->reference_interfaces_[i])); + } + + ASSERT_EQ( + controller_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)), + controller_interface::return_type::OK); + + ASSERT_TRUE(controller_->is_in_chained_mode()); + EXPECT_EQ(*(controller_->control_mode_.readFromRT()), feedforward_mode_type::ON); + EXPECT_EQ( + controller_->reference_interfaces_.size(), dof_names_.size() * state_interfaces_.size()); + EXPECT_EQ(controller_->reference_interfaces_.size(), dof_state_values_.size()); + for (size_t i = 0; i < dof_command_values_.size(); ++i) + { + EXPECT_FALSE(std::isnan((*(controller_->input_ref_.readFromRT()))->values[i])); + EXPECT_EQ((*(controller_->input_ref_.readFromRT()))->values[i], dof_command_values_[i]); + } +} + +/** + * @brief check default calculation with angle_wraparound turned off + */ +TEST_F(PidControllerTest, test_update_logic_angle_wraparound_off) +{ + SetUpController(); + rclcpp::executors::MultiThreadedExecutor executor; + executor.add_node(controller_->get_node()->get_node_base_interface()); + executor.add_node(service_caller_node_->get_node_base_interface()); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + controller_->set_chained_mode(true); + ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_TRUE(controller_->is_in_chained_mode()); + + // write reference interface so that the values are would be wrapped + + // run update + + // check the result of the commands - the values are not wrapped +} + +/** + * @brief check default calculation with angle_wraparound turned off + */ +TEST_F(PidControllerTest, test_update_logic_angle_wraparound_on) +{ + SetUpController(); + rclcpp::executors::MultiThreadedExecutor executor; + executor.add_node(controller_->get_node()->get_node_base_interface()); + executor.add_node(service_caller_node_->get_node_base_interface()); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + controller_->set_chained_mode(true); + ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_TRUE(controller_->is_in_chained_mode()); + + // write reference interface so that the values are would be wrapped + + // run update + + // check the result of the commands - the values are wrapped +} + +TEST_F(PidControllerTest, subscribe_and_get_messages_success) +{ + SetUpController(); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + + ASSERT_EQ( + controller_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)), + controller_interface::return_type::OK); + + ControllerStateMsg msg; + subscribe_and_get_messages(msg); + + ASSERT_EQ(msg.dof_states.size(), dof_names_.size()); + for (size_t i = 0; i < dof_names_.size(); ++i) + { + ASSERT_EQ(msg.dof_states[i].name, dof_names_[i]); + EXPECT_TRUE(std::isnan(msg.dof_states[i].reference)); + ASSERT_EQ(msg.dof_states[i].output, dof_command_values_[i]); + } +} + +TEST_F(PidControllerTest, receive_message_and_publish_updated_status) +{ + SetUpController(); + rclcpp::executors::MultiThreadedExecutor executor; + executor.add_node(controller_->get_node()->get_node_base_interface()); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); + + ASSERT_EQ( + controller_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)), + controller_interface::return_type::OK); + + ControllerStateMsg msg; + subscribe_and_get_messages(msg); + + ASSERT_EQ(msg.dof_states.size(), dof_names_.size()); + for (size_t i = 0; i < dof_names_.size(); ++i) + { + ASSERT_EQ(msg.dof_states[i].name, dof_names_[i]); + EXPECT_TRUE(std::isnan(msg.dof_states[i].reference)); + ASSERT_EQ(msg.dof_states[i].output, dof_command_values_[i]); + } + + for (size_t i = 0; i < controller_->reference_interfaces_.size(); ++i) + { + EXPECT_TRUE(std::isnan(controller_->reference_interfaces_[i])); + } + + publish_commands(); + ASSERT_TRUE(controller_->wait_for_commands(executor)); + + for (size_t i = 0; i < controller_->reference_interfaces_.size(); ++i) + { + EXPECT_TRUE(std::isnan(controller_->reference_interfaces_[i])); + } + + ASSERT_EQ( + controller_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)), + controller_interface::return_type::OK); + + for (size_t i = 0; i < controller_->reference_interfaces_.size(); ++i) + { + ASSERT_EQ(controller_->reference_interfaces_[i], 0.45); + } + + subscribe_and_get_messages(msg); + + ASSERT_EQ(msg.dof_states.size(), dof_names_.size()); + for (size_t i = 0; i < dof_names_.size(); ++i) + { + ASSERT_EQ(msg.dof_states[i].name, dof_names_[i]); + ASSERT_EQ(msg.dof_states[i].reference, 0.45); + ASSERT_NE(msg.dof_states[i].output, dof_command_values_[i]); + } +} + +int main(int argc, char ** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + rclcpp::init(argc, argv); + int result = RUN_ALL_TESTS(); + rclcpp::shutdown(); + return result; +} diff --git a/pid_controller/test/test_pid_controller.hpp b/pid_controller/test/test_pid_controller.hpp new file mode 100644 index 0000000000..ab32f5cb48 --- /dev/null +++ b/pid_controller/test/test_pid_controller.hpp @@ -0,0 +1,285 @@ +// Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Authors: Daniel Azanov, Dr. Denis +// + +#ifndef TEST_PID_CONTROLLER_HPP_ +#define TEST_PID_CONTROLLER_HPP_ + +#include +#include +#include +#include +#include +#include +#include + +#include "gmock/gmock.h" +#include "hardware_interface/loaned_command_interface.hpp" +#include "hardware_interface/loaned_state_interface.hpp" +#include "hardware_interface/types/hardware_interface_return_values.hpp" +#include "pid_controller/pid_controller.hpp" +#include "rclcpp/parameter_value.hpp" +#include "rclcpp/time.hpp" +#include "rclcpp/utilities.hpp" +#include "rclcpp_lifecycle/node_interfaces/lifecycle_node_interface.hpp" + +using ControllerStateMsg = pid_controller::PidController::ControllerStateMsg; +using ControllerCommandMsg = pid_controller::PidController::ControllerReferenceMsg; +using ControllerModeSrvType = pid_controller::PidController::ControllerModeSrvType; + +namespace +{ +constexpr auto NODE_SUCCESS = controller_interface::CallbackReturn::SUCCESS; +constexpr auto NODE_ERROR = controller_interface::CallbackReturn::ERROR; +} // namespace +// namespace + +// subclassing and friending so we can access member variables +class TestablePidController : public pid_controller::PidController +{ + FRIEND_TEST(PidControllerTest, all_parameters_set_configure_success); + FRIEND_TEST(PidControllerTest, activate_success); + FRIEND_TEST(PidControllerTest, reactivate_success); + FRIEND_TEST(PidControllerTest, test_feedforward_mode_service); + FRIEND_TEST(PidControllerTest, test_update_logic_feedforward_off); + FRIEND_TEST(PidControllerTest, test_update_logic_feedforward_on); + FRIEND_TEST(PidControllerTest, test_update_logic_chainable_feedforward_off); + FRIEND_TEST(PidControllerTest, test_update_logic_chainable_feedforward_on); + FRIEND_TEST(PidControllerTest, subscribe_and_get_messages_success); + FRIEND_TEST(PidControllerTest, receive_message_and_publish_updated_status); + +public: + controller_interface::CallbackReturn on_configure( + const rclcpp_lifecycle::State & previous_state) override + { + auto ret = pid_controller::PidController::on_configure(previous_state); + // Only if on_configure is successful create subscription + if (ret == CallbackReturn::SUCCESS) + { + ref_subscriber_wait_set_.add_subscription(ref_subscriber_); + } + return ret; + } + + controller_interface::CallbackReturn on_activate( + const rclcpp_lifecycle::State & previous_state) override + { + auto ref_itfs = on_export_reference_interfaces(); + return pid_controller::PidController::on_activate(previous_state); + } + + /** + * @brief wait_for_command blocks until a new ControllerCommandMsg is received. + * Requires that the executor is not spinned elsewhere between the + * message publication and the call to this function. + * + * @return true if new ControllerCommandMsg msg was received, false if timeout. + */ + bool wait_for_command( + rclcpp::Executor & executor, rclcpp::WaitSet & subscriber_wait_set, + const std::chrono::milliseconds & timeout = std::chrono::milliseconds{500}) + { + bool success = subscriber_wait_set.wait(timeout).kind() == rclcpp::WaitResultKind::Ready; + if (success) + { + executor.spin_some(); + } + return success; + } + + bool wait_for_commands( + rclcpp::Executor & executor, + const std::chrono::milliseconds & timeout = std::chrono::milliseconds{500}) + { + return wait_for_command(executor, ref_subscriber_wait_set_, timeout); + } + +private: + rclcpp::WaitSet ref_subscriber_wait_set_; +}; + +// We are using template class here for easier reuse of Fixture in specializations of controllers +template +class PidControllerFixture : public ::testing::Test +{ +public: + static void SetUpTestCase() {} + + void SetUp() + { + dof_names_ = {"joint1"}; + command_interface_ = "position"; + state_interfaces_ = {"position"}; + dof_state_values_ = {1.1}; + dof_command_values_ = {101.101}; + reference_and_state_dof_names_ = {"joint1state"}; + + // initialize controller + controller_ = std::make_unique(); + + command_publisher_node_ = std::make_shared("command_publisher"); + command_publisher_ = command_publisher_node_->create_publisher( + "/test_pid_controller/reference", rclcpp::SystemDefaultsQoS()); + + service_caller_node_ = std::make_shared("service_caller"); + feedforward_service_client_ = service_caller_node_->create_client( + "/test_pid_controller/set_feedforward_control"); + } + + static void TearDownTestCase() { rclcpp::shutdown(); } + + void TearDown() { controller_.reset(nullptr); } + +protected: + void SetUpController(const std::string controller_name = "test_pid_controller") + { + ASSERT_EQ(controller_->init(controller_name, "", 0), controller_interface::return_type::OK); + + std::vector command_ifs; + command_itfs_.reserve(dof_names_.size()); + command_ifs.reserve(dof_names_.size()); + + for (size_t i = 0; i < dof_names_.size(); ++i) + { + command_itfs_.emplace_back(hardware_interface::CommandInterface( + dof_names_[i], command_interface_, &dof_command_values_[i])); + command_ifs.emplace_back(command_itfs_.back()); + } + + std::vector state_ifs; + state_ifs.reserve(dof_names_.size() * state_interfaces_.size()); + state_itfs_.reserve(dof_names_.size() * state_interfaces_.size()); + size_t index = 0; + for (const auto & interface : state_interfaces_) + { + for (const auto & dof_name : dof_names_) + { + state_itfs_.emplace_back( + hardware_interface::StateInterface(dof_name, interface, &dof_state_values_[index])); + state_ifs.emplace_back(state_itfs_.back()); + ++index; + } + } + + controller_->assign_interfaces(std::move(command_ifs), std::move(state_ifs)); + } + + void subscribe_and_get_messages(ControllerStateMsg & msg) + { + // create a new subscriber + rclcpp::Node test_subscription_node("test_subscription_node"); + auto subs_callback = [&](const ControllerStateMsg::SharedPtr) {}; + auto subscription = test_subscription_node.create_subscription( + "/test_pid_controller/controller_state", 10, subs_callback); + + // call update to publish the test value + ASSERT_EQ( + controller_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)), + controller_interface::return_type::OK); + + // call update to publish the test value + // since update doesn't guarantee a published message, republish until received + int max_sub_check_loop_count = 5; // max number of tries for pub/sub loop + rclcpp::WaitSet wait_set; // block used to wait on message + wait_set.add_subscription(subscription); + while (max_sub_check_loop_count--) + { + controller_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)); + // check if message has been received + if (wait_set.wait(std::chrono::milliseconds(2)).kind() == rclcpp::WaitResultKind::Ready) + { + break; + } + } + ASSERT_GE(max_sub_check_loop_count, 0) << "Test was unable to publish a message through " + "controller/broadcaster update loop"; + + // take message from subscription + rclcpp::MessageInfo msg_info; + ASSERT_TRUE(subscription->take(msg, msg_info)); + } + + void publish_commands( + const std::vector & values = {0.45}, const std::vector & values_dot = {0.0}) + { + auto wait_for_topic = [&](const auto topic_name) + { + size_t wait_count = 0; + while (command_publisher_node_->count_subscribers(topic_name) == 0) + { + if (wait_count >= 5) + { + auto error_msg = + std::string("publishing to ") + topic_name + " but no node subscribes to it"; + throw std::runtime_error(error_msg); + } + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + ++wait_count; + } + }; + + wait_for_topic(command_publisher_->get_topic_name()); + + ControllerCommandMsg msg; + msg.dof_names = dof_names_; + msg.values = values; + msg.values_dot = values_dot; + + command_publisher_->publish(msg); + } + + std::shared_ptr call_service( + const bool feedforward, rclcpp::Executor & executor) + { + auto request = std::make_shared(); + request->data = feedforward; + + bool wait_for_service_ret = + feedforward_service_client_->wait_for_service(std::chrono::milliseconds(500)); + EXPECT_TRUE(wait_for_service_ret); + if (!wait_for_service_ret) + { + throw std::runtime_error("Service is not available!"); + } + auto result = feedforward_service_client_->async_send_request(request); + EXPECT_EQ(executor.spin_until_future_complete(result), rclcpp::FutureReturnCode::SUCCESS); + + return result.get(); + } + +protected: + // TODO(anyone): adjust the members as needed + + // Controller-related parameters + std::vector dof_names_; + std::string command_interface_; + std::vector state_interfaces_; + std::vector dof_state_values_; + std::vector dof_command_values_; + std::vector reference_and_state_dof_names_; + + std::vector state_itfs_; + std::vector command_itfs_; + + // Test related parameters + std::unique_ptr controller_; + rclcpp::Node::SharedPtr command_publisher_node_; + rclcpp::Publisher::SharedPtr command_publisher_; + rclcpp::Node::SharedPtr service_caller_node_; + rclcpp::Client::SharedPtr feedforward_service_client_; +}; + +#endif // TEST_PID_CONTROLLER_HPP_ diff --git a/pid_controller/test/test_pid_controller_preceding.cpp b/pid_controller/test/test_pid_controller_preceding.cpp new file mode 100644 index 0000000000..e0d3051226 --- /dev/null +++ b/pid_controller/test/test_pid_controller_preceding.cpp @@ -0,0 +1,103 @@ +// Copyright (c) 2023, Stogl Robotics Consulting UG (haftungsbeschränkt) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Authors: Daniel Azanov, Dr. Denis +// + +#include "test_pid_controller.hpp" + +#include +#include +#include +#include +#include + +using pid_controller::feedforward_mode_type; + +class PidControllerTest : public PidControllerFixture +{ +}; + +TEST_F(PidControllerTest, all_parameters_set_configure_success) +{ + SetUpController(); + + ASSERT_TRUE(controller_->params_.dof_names.empty()); + ASSERT_TRUE(controller_->params_.reference_and_state_dof_names.empty()); + ASSERT_TRUE(controller_->params_.command_interface.empty()); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + + ASSERT_THAT(controller_->params_.dof_names, testing::ElementsAreArray(dof_names_)); + ASSERT_THAT( + controller_->params_.reference_and_state_dof_names, + testing::ElementsAreArray(reference_and_state_dof_names_)); + ASSERT_THAT( + controller_->reference_and_state_dof_names_, + testing::ElementsAreArray(reference_and_state_dof_names_)); + ASSERT_EQ(controller_->params_.command_interface, command_interface_); +} + +TEST_F(PidControllerTest, check_exported_intefaces) +{ + SetUpController(); + + ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); + + auto command_intefaces = controller_->command_interface_configuration(); + ASSERT_EQ(command_intefaces.names.size(), dof_command_values_.size()); + for (size_t i = 0; i < command_intefaces.names.size(); ++i) + { + EXPECT_EQ(command_intefaces.names[i], dof_names_[i] + "/" + command_interface_); + } + + auto state_intefaces = controller_->state_interface_configuration(); + ASSERT_EQ(state_intefaces.names.size(), dof_state_values_.size()); + size_t si_index = 0; + for (const auto & interface : state_interfaces_) + { + for (const auto & dof_name : reference_and_state_dof_names_) + { + EXPECT_EQ(state_intefaces.names[si_index], dof_name + "/" + interface); + ++si_index; + } + } + + // check ref itfs + auto reference_interfaces = controller_->export_reference_interfaces(); + ASSERT_EQ(reference_interfaces.size(), dof_state_values_.size()); + size_t ri_index = 0; + for (const auto & interface : state_interfaces_) + { + for (const auto & dof_name : reference_and_state_dof_names_) + { + const std::string ref_itf_name = + std::string(controller_->get_node()->get_name()) + "/" + dof_name + "/" + interface; + EXPECT_EQ(reference_interfaces[ri_index].get_name(), ref_itf_name); + EXPECT_EQ( + reference_interfaces[ri_index].get_prefix_name(), controller_->get_node()->get_name()); + EXPECT_EQ(reference_interfaces[ri_index].get_interface_name(), dof_name + "/" + interface); + ++ri_index; + } + } +} + +int main(int argc, char ** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + rclcpp::init(argc, argv); + int result = RUN_ALL_TESTS(); + rclcpp::shutdown(); + return result; +} diff --git a/ros2_controllers/package.xml b/ros2_controllers/package.xml index d34a5b1375..3b77b7cc69 100644 --- a/ros2_controllers/package.xml +++ b/ros2_controllers/package.xml @@ -20,6 +20,7 @@ imu_sensor_broadcaster joint_state_broadcaster joint_trajectory_controller + pid_controller position_controllers range_sensor_broadcaster steering_controllers_library From 71b06d01c1374914b93f202c80182210b385fb5f Mon Sep 17 00:00:00 2001 From: Abishalini Sivaraman Date: Mon, 4 Dec 2023 13:21:13 -0700 Subject: [PATCH 161/238] Fix floating point comparison in JTC (#879) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix floating point comparison in JTC * Fix format --------- Co-authored-by: Christoph Fröhlich --- .../src/joint_trajectory_controller.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/joint_trajectory_controller/src/joint_trajectory_controller.cpp b/joint_trajectory_controller/src/joint_trajectory_controller.cpp index 9306b07354..59e2c408c5 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller.cpp +++ b/joint_trajectory_controller/src/joint_trajectory_controller.cpp @@ -1369,10 +1369,11 @@ bool JointTrajectoryController::validate_trajectory_msg( { for (size_t i = 0; i < trajectory.points.back().velocities.size(); ++i) { - if (trajectory.points.back().velocities.at(i) != 0.) + if (fabs(trajectory.points.back().velocities.at(i)) > std::numeric_limits::epsilon()) { RCLCPP_ERROR( - get_node()->get_logger(), "Velocity of last trajectory point of joint %s is not zero: %f", + get_node()->get_logger(), + "Velocity of last trajectory point of joint %s is not zero: %.15f", trajectory.joint_names.at(i).c_str(), trajectory.points.back().velocities.at(i)); return false; } From 4b267648fa1ac10120cb597e7f6ee23593b6633d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 5 Dec 2023 17:53:25 +0100 Subject: [PATCH 162/238] Bump ros-tooling/setup-ros from 0.7.0 to 0.7.1 (#881) Bumps [ros-tooling/setup-ros](https://github.com/ros-tooling/setup-ros) from 0.7.0 to 0.7.1. - [Release notes](https://github.com/ros-tooling/setup-ros/releases) - [Commits](https://github.com/ros-tooling/setup-ros/compare/0.7.0...0.7.1) --- updated-dependencies: - dependency-name: ros-tooling/setup-ros dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-coverage-build-humble.yml | 2 +- .github/workflows/ci-coverage-build-iron.yml | 2 +- .github/workflows/ci-coverage-build.yml | 2 +- .github/workflows/ci-ros-lint.yml | 2 +- .github/workflows/reusable-ros-tooling-source-build.yml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-coverage-build-humble.yml b/.github/workflows/ci-coverage-build-humble.yml index 76b2c22e53..f263cd2da3 100644 --- a/.github/workflows/ci-coverage-build-humble.yml +++ b/.github/workflows/ci-coverage-build-humble.yml @@ -17,7 +17,7 @@ jobs: env: ROS_DISTRO: humble steps: - - uses: ros-tooling/setup-ros@0.7.0 + - uses: ros-tooling/setup-ros@0.7.1 with: required-ros-distributions: ${{ env.ROS_DISTRO }} - uses: actions/checkout@v4 diff --git a/.github/workflows/ci-coverage-build-iron.yml b/.github/workflows/ci-coverage-build-iron.yml index 1aaf30c639..720f0416c9 100644 --- a/.github/workflows/ci-coverage-build-iron.yml +++ b/.github/workflows/ci-coverage-build-iron.yml @@ -17,7 +17,7 @@ jobs: env: ROS_DISTRO: iron steps: - - uses: ros-tooling/setup-ros@0.7.0 + - uses: ros-tooling/setup-ros@0.7.1 with: required-ros-distributions: ${{ env.ROS_DISTRO }} - uses: actions/checkout@v4 diff --git a/.github/workflows/ci-coverage-build.yml b/.github/workflows/ci-coverage-build.yml index 72aa9af66c..e55285b179 100644 --- a/.github/workflows/ci-coverage-build.yml +++ b/.github/workflows/ci-coverage-build.yml @@ -17,7 +17,7 @@ jobs: env: ROS_DISTRO: rolling steps: - - uses: ros-tooling/setup-ros@0.7.0 + - uses: ros-tooling/setup-ros@0.7.1 with: required-ros-distributions: ${{ env.ROS_DISTRO }} - uses: actions/checkout@v4 diff --git a/.github/workflows/ci-ros-lint.yml b/.github/workflows/ci-ros-lint.yml index 5789c2dee4..60cf153978 100644 --- a/.github/workflows/ci-ros-lint.yml +++ b/.github/workflows/ci-ros-lint.yml @@ -14,7 +14,7 @@ jobs: AMENT_CPPCHECK_ALLOW_SLOW_VERSIONS: true steps: - uses: actions/checkout@v4 - - uses: ros-tooling/setup-ros@0.7.0 + - uses: ros-tooling/setup-ros@0.7.1 - uses: ros-tooling/action-ros-lint@v0.1 with: distribution: rolling diff --git a/.github/workflows/reusable-ros-tooling-source-build.yml b/.github/workflows/reusable-ros-tooling-source-build.yml index 6b1af2b86c..f0ac7b447d 100644 --- a/.github/workflows/reusable-ros-tooling-source-build.yml +++ b/.github/workflows/reusable-ros-tooling-source-build.yml @@ -26,7 +26,7 @@ jobs: strategy: fail-fast: false steps: - - uses: ros-tooling/setup-ros@0.7.0 + - uses: ros-tooling/setup-ros@0.7.1 with: required-ros-distributions: ${{ inputs.ros_distro }} - uses: actions/checkout@v4 From 925a690fcb469cb705ec67185cd67c6f1481dd61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Tue, 5 Dec 2023 22:52:01 +0100 Subject: [PATCH 163/238] Add pid_controller to CI jobs (#883) --- .github/workflows/ci-coverage-build-humble.yml | 1 + .github/workflows/ci-coverage-build-iron.yml | 1 + .github/workflows/ci-coverage-build.yml | 1 + .github/workflows/ci-ros-lint.yml | 2 ++ 4 files changed, 5 insertions(+) diff --git a/.github/workflows/ci-coverage-build-humble.yml b/.github/workflows/ci-coverage-build-humble.yml index f263cd2da3..ece507aaa1 100644 --- a/.github/workflows/ci-coverage-build-humble.yml +++ b/.github/workflows/ci-coverage-build-humble.yml @@ -38,6 +38,7 @@ jobs: imu_sensor_broadcaster joint_state_broadcaster joint_trajectory_controller + pid_controller position_controllers range_sensor_broadcaster steering_controllers_library diff --git a/.github/workflows/ci-coverage-build-iron.yml b/.github/workflows/ci-coverage-build-iron.yml index 720f0416c9..8d77e65b6b 100644 --- a/.github/workflows/ci-coverage-build-iron.yml +++ b/.github/workflows/ci-coverage-build-iron.yml @@ -38,6 +38,7 @@ jobs: imu_sensor_broadcaster joint_state_broadcaster joint_trajectory_controller + pid_controller position_controllers range_sensor_broadcaster steering_controllers_library diff --git a/.github/workflows/ci-coverage-build.yml b/.github/workflows/ci-coverage-build.yml index e55285b179..bf9ad847b4 100644 --- a/.github/workflows/ci-coverage-build.yml +++ b/.github/workflows/ci-coverage-build.yml @@ -38,6 +38,7 @@ jobs: imu_sensor_broadcaster joint_state_broadcaster joint_trajectory_controller + pid_controller position_controllers range_sensor_broadcaster steering_controllers_library diff --git a/.github/workflows/ci-ros-lint.yml b/.github/workflows/ci-ros-lint.yml index 60cf153978..f6b9c027c9 100644 --- a/.github/workflows/ci-ros-lint.yml +++ b/.github/workflows/ci-ros-lint.yml @@ -31,6 +31,7 @@ jobs: imu_sensor_broadcaster joint_state_broadcaster joint_trajectory_controller + pid_controller position_controllers range_sensor_broadcaster ros2_controllers @@ -69,6 +70,7 @@ jobs: imu_sensor_broadcaster joint_state_broadcaster joint_trajectory_controller + pid_controller position_controllers range_sensor_broadcaster ros2_controllers From e8a127f2b8bc6b5561f54d4afcb30a641f60ec3a Mon Sep 17 00:00:00 2001 From: Sai Kishor Kothakota Date: Fri, 8 Dec 2023 13:42:43 +0100 Subject: [PATCH 164/238] Fix rqt jtc bugs for continuous joints and other minor bugs (#890) --- .../joint_limits_urdf.py | 57 ++++++++++++------- .../joint_trajectory_controller.py | 10 +++- 2 files changed, 42 insertions(+), 25 deletions(-) diff --git a/rqt_joint_trajectory_controller/rqt_joint_trajectory_controller/joint_limits_urdf.py b/rqt_joint_trajectory_controller/rqt_joint_trajectory_controller/joint_limits_urdf.py index 7914a76b17..5655e12f7a 100644 --- a/rqt_joint_trajectory_controller/rqt_joint_trajectory_controller/joint_limits_urdf.py +++ b/rqt_joint_trajectory_controller/rqt_joint_trajectory_controller/joint_limits_urdf.py @@ -14,6 +14,10 @@ # See the License for the specific language governing permissions and # limitations under the License. +# Code inspired on the joint_state_publisher package by David Lu!!! +# https://github.com/ros/robot_model/blob/indigo-devel/ +# joint_state_publisher/joint_state_publisher/joint_state_publisher + # TODO: Use urdf_parser_py.urdf instead. I gave it a try, but got # Exception: Required attribute not set in XML: upper # upper is an optional attribute, so I don't understand what's going on @@ -33,21 +37,24 @@ def callback(msg): description = msg.data -def get_joint_limits(node, key="robot_description", use_smallest_joint_limits=True): - global description - use_small = use_smallest_joint_limits - use_mimic = True - - # Code inspired on the joint_state_publisher package by David Lu!!! - # https://github.com/ros/robot_model/blob/indigo-devel/ - # joint_state_publisher/joint_state_publisher/joint_state_publisher - +def subscribe_to_robot_description(node, key="robot_description"): qos_profile = rclpy.qos.QoSProfile(depth=1) qos_profile.durability = rclpy.qos.DurabilityPolicy.TRANSIENT_LOCAL qos_profile.reliability = rclpy.qos.ReliabilityPolicy.RELIABLE - node.create_subscription(String, "/robot_description", callback, qos_profile) - rclpy.spin_once(node) + node.create_subscription(String, key, callback, qos_profile) + + +def get_joint_limits(node, use_smallest_joint_limits=True): + global description + use_small = use_smallest_joint_limits + use_mimic = True + + count = 0 + while description == "" and count < 10: + print("Waiting for the robot_description!") + count += 1 + rclpy.spin_once(node, timeout_sec=1.0) free_joints = {} dependent_joints = {} @@ -66,21 +73,27 @@ def get_joint_limits(node, key="robot_description", use_smallest_joint_limits=Tr name = child.getAttribute("name") try: limit = child.getElementsByTagName("limit")[0] - except IndexError: - continue - if jtype == "continuous": - minval = -pi - maxval = pi - else: try: minval = float(limit.getAttribute("lower")) maxval = float(limit.getAttribute("upper")) except ValueError: - continue - try: - maxvel = float(limit.getAttribute("velocity")) - except ValueError: - continue + if jtype == "continuous": + minval = -pi + maxval = pi + else: + raise Exception( + f"Missing lower/upper position limits for the joint : {name} of type : {jtype} in the robot_description!" + ) + try: + maxvel = float(limit.getAttribute("velocity")) + except ValueError: + raise Exception( + f"Missing velocity limits for the joint : {name} of type : {jtype} in the robot_description!" + ) + except IndexError: + raise Exception( + f"Missing limits tag for the joint : {name} in the robot_description!" + ) safety_tags = child.getElementsByTagName("safety_controller") if use_small and len(safety_tags) == 1: tag = safety_tags[0] diff --git a/rqt_joint_trajectory_controller/rqt_joint_trajectory_controller/joint_trajectory_controller.py b/rqt_joint_trajectory_controller/rqt_joint_trajectory_controller/joint_trajectory_controller.py index 99f43e125e..162977cdfe 100644 --- a/rqt_joint_trajectory_controller/rqt_joint_trajectory_controller/joint_trajectory_controller.py +++ b/rqt_joint_trajectory_controller/rqt_joint_trajectory_controller/joint_trajectory_controller.py @@ -29,7 +29,7 @@ from .utils import ControllerLister, ControllerManagerLister from .double_editor import DoubleEditor -from .joint_limits_urdf import get_joint_limits +from .joint_limits_urdf import get_joint_limits, subscribe_to_robot_description from .update_combo import update_combo # TODO: @@ -170,6 +170,9 @@ def __init__(self, context): self._update_jtc_list_timer.timeout.connect(self._update_jtc_list) self._update_jtc_list_timer.start() + # subscriptions + subscribe_to_robot_description(self._node) + # Signal connections w = self._widget w.enable_button.toggled.connect(self._on_jtc_enabled) @@ -460,8 +463,9 @@ def _jtc_joint_names(jtc_info): joint_names = [] for interface in jtc_info.claimed_interfaces: - name = interface.split("/")[0] - joint_names.append(name) + name = interface.split("/")[-2] + if name not in joint_names: + joint_names.append(name) return joint_names From 960e073185b15f330d5d9e1b7af2682cc7c2e8b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Fri, 8 Dec 2023 19:47:20 +0100 Subject: [PATCH 165/238] Use more mergify features (#888) --- .github/mergify.yml | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/.github/mergify.yml b/.github/mergify.yml index 3aaaab2001..692c346ab4 100644 --- a/.github/mergify.yml +++ b/.github/mergify.yml @@ -8,7 +8,6 @@ pull_request_rules: branches: - humble - - name: Backport to iron at reviewers discretion conditions: - base=master @@ -21,7 +20,29 @@ pull_request_rules: - name: Ask to resolve conflict conditions: - conflict - - author!=mergify + - author!=mergify[bot] actions: comment: message: This pull request is in conflict. Could you fix it @{{author}}? + + - name: Ask to resolve conflict for backports + conditions: + - conflict + - author=mergify[bot] + actions: + comment: + message: This pull request is in conflict. Could you fix it @bmagyar @dstogl @christophfroehlich? + + - name: development targets master branch + conditions: + - base!=master + - author!=bmagyar + - author!=dstogl + - author!=christophfroehlich + - author!=mergify[bot] + actions: + comment: + message: | + @{{author}}, all pull requests must be targeted towards the `master` development branch. + Once merged into `master`, it is possible to backport to @{{base}}, but it must be in `master` + to have these changes reflected into new distributions. From 999eae5491a79f9734f8d5e4e18ffea3e7a04e2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Sat, 9 Dec 2023 21:09:32 +0100 Subject: [PATCH 166/238] Update good-first-issue.md (#895) --- .github/ISSUE_TEMPLATE/good-first-issue.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/good-first-issue.md b/.github/ISSUE_TEMPLATE/good-first-issue.md index 4a2664918a..4de9ad8d30 100644 --- a/.github/ISSUE_TEMPLATE/good-first-issue.md +++ b/.github/ISSUE_TEMPLATE/good-first-issue.md @@ -55,6 +55,6 @@ Don’t hesitate to ask questions or to get help if you feel like you are gettin Furthermore, you find helpful resources here: * [ROS2 Control Contribution Guide](https://control.ros.org/master/doc/contributing/contributing.html) * [ROS2 Tutorials](https://docs.ros.org/en/rolling/Tutorials.html) -* [ROS Answers](https://answers.ros.org/questions/) +* [Robotics Stack Exchange](https://robotics.stackexchange.com) **Good luck with your first issue!** From cb56213c7836caa208c6049048088d33a72b6aff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Mon, 11 Dec 2023 17:52:20 +0100 Subject: [PATCH 167/238] Add configs for humble and iron (#901) --- .github/dependabot.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 05a48fc654..aafd67c236 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -11,3 +11,17 @@ updates: directory: "/" schedule: interval: "weekly" + - package-ecosystem: "github-actions" + # Workflow files stored in the + # default location of `.github/workflows` + directory: "/" + schedule: + interval: "weekly" + target-branch: "humble" + - package-ecosystem: "github-actions" + # Workflow files stored in the + # default location of `.github/workflows` + directory: "/" + schedule: + interval: "weekly" + target-branch: "iron" From 52d3d3f2f64c357361c8f99f018bbaa49584e27f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 11 Dec 2023 18:05:29 +0100 Subject: [PATCH 168/238] Bump actions/setup-python from 4.7.1 to 5.0.0 (#906) Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4.7.1 to 5.0.0. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v4.7.1...v5.0.0) --- updated-dependencies: - dependency-name: actions/setup-python dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-format.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-format.yml b/.github/workflows/ci-format.yml index 5d801016f9..9f090b48ca 100644 --- a/.github/workflows/ci-format.yml +++ b/.github/workflows/ci-format.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: actions/setup-python@v4.7.1 + - uses: actions/setup-python@v5.0.0 with: python-version: '3.10' - name: Install system hooks From 0a96cbb513282880d2d64adfb8c3c8c0ffc84b5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Mon, 11 Dec 2023 19:08:10 +0100 Subject: [PATCH 169/238] Update list of reviewers (#884) --- .github/reviewer-lottery.yml | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/.github/reviewer-lottery.yml b/.github/reviewer-lottery.yml index 84b156f5a1..c6580eacd4 100644 --- a/.github/reviewer-lottery.yml +++ b/.github/reviewer-lottery.yml @@ -13,28 +13,21 @@ groups: - name: reviewers reviewers: 5 usernames: - - rosterloh - - progtologist + - aprotyas - arne48 + - bijoua29 - christophfroehlich - DasRoteSkelett - - sgmurray - - harderthan - - jaron-l - - malapatiravi + - duringhof - erickisos - - sachinkum0009 - - qiayuanliao - - homalozoa - - anfemosa - - jackcenter - - VX792 - - mhubii + - fmauch + - jaron-l - livanov93 - - aprotyas + - mcbed + - moriarty + - olivier-stasse - peterdavidfagan - - duringhof + - progtologist + - saikishor - VanshGehlot - - bijoua29 - - LukasMacha97 - - mcbed + - VX792 From e8e091da251778985ec1c36b24874f8ba5886d93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Tue, 12 Dec 2023 08:12:43 +0100 Subject: [PATCH 170/238] mergify: Ignore dependabot[bot] (#916) --- .github/mergify.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/mergify.yml b/.github/mergify.yml index 692c346ab4..0a6e425a30 100644 --- a/.github/mergify.yml +++ b/.github/mergify.yml @@ -21,6 +21,7 @@ pull_request_rules: conditions: - conflict - author!=mergify[bot] + - author!=dependabot[bot] actions: comment: message: This pull request is in conflict. Could you fix it @{{author}}? @@ -40,6 +41,7 @@ pull_request_rules: - author!=dstogl - author!=christophfroehlich - author!=mergify[bot] + - author!=dependabot[bot] actions: comment: message: | From 1d0d7531ef8d24ea52e761a872b8bf277652dd33 Mon Sep 17 00:00:00 2001 From: "Dr. Denis" Date: Tue, 12 Dec 2023 09:51:22 +0100 Subject: [PATCH 171/238] Cleanup package.xml und clarify tests of JTC. (#889) * Cleanup package.xml und clarify tests of JTC. * Update joint_trajectory_controller/package.xml Co-authored-by: Bence Magyar --------- Co-authored-by: Bence Magyar --- joint_trajectory_controller/package.xml | 15 +++++---------- .../test/test_trajectory_controller_utils.hpp | 8 ++++---- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/joint_trajectory_controller/package.xml b/joint_trajectory_controller/package.xml index b41a7cad0c..70d9bd51d2 100644 --- a/joint_trajectory_controller/package.xml +++ b/joint_trajectory_controller/package.xml @@ -4,29 +4,24 @@ 4.1.0 Controller for executing joint-space trajectories on a group of joints Bence Magyar - Jordan Palacios - Karsten Knese + Dr. Denis Štogl + Christoph Froehlich Apache License 2.0 ament_cmake - angles - pluginlib - realtime_tools - - angles - pluginlib - realtime_tools - + angles backward_ros controller_interface control_msgs control_toolbox generate_parameter_library hardware_interface + pluginlib rclcpp rclcpp_lifecycle + realtime_tools rsl tl_expected trajectory_msgs diff --git a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp index 4a65b4ad51..7b68d882ff 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp +++ b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp @@ -215,7 +215,7 @@ class TrajectoryControllerTest : public ::testing::Test } void SetPidParameters( - double p_default = 0.0, double ff_default = 1.0, bool angle_wraparound_default = false) + double p_value = 0.0, double ff_value = 1.0, bool angle_wraparound_value = false) { traj_controller_->trigger_declare_parameters(); auto node = traj_controller_->get_node(); @@ -223,13 +223,13 @@ class TrajectoryControllerTest : public ::testing::Test for (size_t i = 0; i < joint_names_.size(); ++i) { const std::string prefix = "gains." + joint_names_[i]; - const rclcpp::Parameter k_p(prefix + ".p", p_default); + const rclcpp::Parameter k_p(prefix + ".p", p_value); const rclcpp::Parameter k_i(prefix + ".i", 0.0); const rclcpp::Parameter k_d(prefix + ".d", 0.0); const rclcpp::Parameter i_clamp(prefix + ".i_clamp", 0.0); - const rclcpp::Parameter ff_velocity_scale(prefix + ".ff_velocity_scale", ff_default); + const rclcpp::Parameter ff_velocity_scale(prefix + ".ff_velocity_scale", ff_value); const rclcpp::Parameter angle_wraparound( - prefix + ".angle_wraparound", angle_wraparound_default); + prefix + ".angle_wraparound", angle_wraparound_value); node->set_parameters({k_p, k_i, k_d, i_clamp, ff_velocity_scale, angle_wraparound}); } } From 364df81e9947671e6e51d45ce306b93afceebec8 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Tue, 12 Dec 2023 16:07:22 +0000 Subject: [PATCH 172/238] Update changelogs --- ackermann_steering_controller/CHANGELOG.rst | 3 + admittance_controller/CHANGELOG.rst | 3 + bicycle_steering_controller/CHANGELOG.rst | 3 + diff_drive_controller/CHANGELOG.rst | 3 + effort_controllers/CHANGELOG.rst | 3 + force_torque_sensor_broadcaster/CHANGELOG.rst | 3 + forward_command_controller/CHANGELOG.rst | 3 + gripper_controllers/CHANGELOG.rst | 3 + imu_sensor_broadcaster/CHANGELOG.rst | 3 + joint_state_broadcaster/CHANGELOG.rst | 3 + joint_trajectory_controller/CHANGELOG.rst | 6 + pid_controller/CHANGELOG.rst | 164 ++++++++++++++++++ pid_controller/package.xml | 2 +- position_controllers/CHANGELOG.rst | 3 + range_sensor_broadcaster/CHANGELOG.rst | 3 + ros2_controllers/CHANGELOG.rst | 5 + ros2_controllers_test_nodes/CHANGELOG.rst | 3 + rqt_joint_trajectory_controller/CHANGELOG.rst | 5 + steering_controllers_library/CHANGELOG.rst | 3 + tricycle_controller/CHANGELOG.rst | 3 + tricycle_steering_controller/CHANGELOG.rst | 3 + velocity_controllers/CHANGELOG.rst | 3 + 22 files changed, 232 insertions(+), 1 deletion(-) create mode 100644 pid_controller/CHANGELOG.rst diff --git a/ackermann_steering_controller/CHANGELOG.rst b/ackermann_steering_controller/CHANGELOG.rst index a1cbe9596e..15e7408f00 100644 --- a/ackermann_steering_controller/CHANGELOG.rst +++ b/ackermann_steering_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ackermann_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.1.0 (2023-12-01) ------------------ diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index 615a457992..c1053639c0 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.1.0 (2023-12-01) ------------------ diff --git a/bicycle_steering_controller/CHANGELOG.rst b/bicycle_steering_controller/CHANGELOG.rst index bee3606ec8..89d3f6291d 100644 --- a/bicycle_steering_controller/CHANGELOG.rst +++ b/bicycle_steering_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package bicycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.1.0 (2023-12-01) ------------------ diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index 8ee42d701f..646903a5ac 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.1.0 (2023-12-01) ------------------ diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index f4496d3927..7cf9e2f114 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.1.0 (2023-12-01) ------------------ diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index b87aaa2641..027158d18c 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.1.0 (2023-12-01) ------------------ * Increase test coverage of interface configuration getters (`#856 `_) diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index b38f021587..e23dc6db47 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.1.0 (2023-12-01) ------------------ * Increase test coverage of interface configuration getters (`#856 `_) diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index 798a0f3e67..4c492457f2 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.1.0 (2023-12-01) ------------------ * Increase test coverage of interface configuration getters (`#856 `_) diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index 2c311626cf..55c324f22c 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.1.0 (2023-12-01) ------------------ * Increase test coverage of interface configuration getters (`#856 `_) diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index f2295beca3..d46f807ab5 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.1.0 (2023-12-01) ------------------ * Increase test coverage of interface configuration getters (`#856 `_) diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index 7e4c25a474..f2406abef0 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Cleanup package.xml und clarify tests of JTC. (`#889 `_) +* Fix floating point comparison in JTC (`#879 `_) +* Contributors: Abishalini Sivaraman, Dr. Denis + 4.1.0 (2023-12-01) ------------------ * [JTC] Continue with last trajectory-point on success (`#842 `_) diff --git a/pid_controller/CHANGELOG.rst b/pid_controller/CHANGELOG.rst new file mode 100644 index 0000000000..af41de496e --- /dev/null +++ b/pid_controller/CHANGELOG.rst @@ -0,0 +1,164 @@ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Changelog for package pid_controller +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Forthcoming +----------- +* 🚀 Add PID controller 🎉 (`#434 `_) +* Contributors: Dr. Denis + +4.1.0 (2023-12-01) +------------------ + +4.0.0 (2023-11-21) +------------------ + +3.17.0 (2023-10-31) +------------------- + +3.16.0 (2023-09-20) +------------------- + +3.15.0 (2023-09-11) +------------------- + +3.14.0 (2023-08-16) +------------------- + +3.13.0 (2023-08-04) +------------------- + +3.12.0 (2023-07-18) +------------------- + +3.11.0 (2023-06-24) +------------------- + +3.10.1 (2023-06-06) +------------------- + +3.10.0 (2023-06-04) +------------------- + +3.9.0 (2023-05-28) +------------------ + +3.8.0 (2023-05-14) +------------------ + +3.7.0 (2023-05-02) +------------------ + +3.6.0 (2023-04-29) +------------------ + +3.5.0 (2023-04-14) +------------------ + +3.4.0 (2023-04-02) +------------------ + +3.3.0 (2023-03-07) +------------------ + +3.2.0 (2023-02-10) +------------------ + +3.1.0 (2023-01-26) +------------------ + +3.0.0 (2023-01-19) +------------------ + +2.15.0 (2022-12-06) +------------------- + +2.14.0 (2022-11-18) +------------------- + +2.13.0 (2022-10-05) +------------------- + +2.12.0 (2022-09-01) +------------------- + +2.11.0 (2022-08-04) +------------------- + +2.10.0 (2022-08-01) +------------------- + +2.9.0 (2022-07-14) +------------------ + +2.8.0 (2022-07-09) +------------------ + +2.7.0 (2022-07-03) +------------------ + +2.6.0 (2022-06-18) +------------------ + +2.5.0 (2022-05-13) +------------------ + +2.4.0 (2022-04-29) +------------------ + +2.3.0 (2022-04-21) +------------------ + +2.2.0 (2022-03-25) +------------------ + +2.1.0 (2022-02-23) +------------------ + +2.0.1 (2022-02-01) +------------------ + +2.0.0 (2022-01-28) +------------------ + +1.3.0 (2022-01-11) +------------------ + +1.2.0 (2021-12-29) +------------------ + +1.1.0 (2021-10-25) +------------------ + +1.0.0 (2021-09-29) +------------------ + +0.5.0 (2021-08-30) +------------------ + +0.4.1 (2021-07-08) +------------------ + +0.4.0 (2021-06-28) +------------------ + +0.3.1 (2021-05-23) +------------------ + +0.3.0 (2021-05-21) +------------------ + +0.2.1 (2021-05-03) +------------------ + +0.2.0 (2021-02-06) +------------------ + +0.1.2 (2021-01-07) +------------------ + +0.1.1 (2021-01-06) +------------------ + +0.1.0 (2020-12-23) +------------------ diff --git a/pid_controller/package.xml b/pid_controller/package.xml index 7d52121582..c955c4747a 100644 --- a/pid_controller/package.xml +++ b/pid_controller/package.xml @@ -2,7 +2,7 @@ pid_controller - 0.0.0 + 4.1.0 Controller based on PID implememenation from control_toolbox package. Bence Magyar Denis Štogl diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index 6f0870c9ae..ef93a8b3d9 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.1.0 (2023-12-01) ------------------ diff --git a/range_sensor_broadcaster/CHANGELOG.rst b/range_sensor_broadcaster/CHANGELOG.rst index be35427e46..b530b7c721 100644 --- a/range_sensor_broadcaster/CHANGELOG.rst +++ b/range_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package range_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.1.0 (2023-12-01) ------------------ * Increase test coverage of interface configuration getters (`#856 `_) diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index 46f994c792..03064c6f95 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* 🚀 Add PID controller 🎉 (`#434 `_) +* Contributors: Dr. Denis + 4.1.0 (2023-12-01) ------------------ diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index a7a2f7a1fd..b6dcdc8d3a 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.1.0 (2023-12-01) ------------------ diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index ee80d4b30d..5e0c8f82da 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Fix rqt jtc bugs for continuous joints and other minor bugs (`#890 `_) +* Contributors: Sai Kishor Kothakota + 4.1.0 (2023-12-01) ------------------ diff --git a/steering_controllers_library/CHANGELOG.rst b/steering_controllers_library/CHANGELOG.rst index bae8e6e557..44f3fa515f 100644 --- a/steering_controllers_library/CHANGELOG.rst +++ b/steering_controllers_library/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package steering_controllers_library ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.1.0 (2023-12-01) ------------------ diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index 0203298259..98957eb42f 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.1.0 (2023-12-01) ------------------ * Increase test coverage of interface configuration getters (`#856 `_) diff --git a/tricycle_steering_controller/CHANGELOG.rst b/tricycle_steering_controller/CHANGELOG.rst index 4abf0788fb..cb3a5af24d 100644 --- a/tricycle_steering_controller/CHANGELOG.rst +++ b/tricycle_steering_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package tricycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.1.0 (2023-12-01) ------------------ diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index 91575e6075..8b84ddf784 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.1.0 (2023-12-01) ------------------ From 2bcff2f87505bbc32fdfaa8a2938cecddcadc3f8 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Tue, 12 Dec 2023 16:07:51 +0000 Subject: [PATCH 173/238] 4.2.0 --- ackermann_steering_controller/CHANGELOG.rst | 4 ++-- ackermann_steering_controller/package.xml | 2 +- admittance_controller/CHANGELOG.rst | 4 ++-- admittance_controller/package.xml | 2 +- bicycle_steering_controller/CHANGELOG.rst | 4 ++-- bicycle_steering_controller/package.xml | 2 +- diff_drive_controller/CHANGELOG.rst | 4 ++-- diff_drive_controller/package.xml | 2 +- effort_controllers/CHANGELOG.rst | 4 ++-- effort_controllers/package.xml | 2 +- force_torque_sensor_broadcaster/CHANGELOG.rst | 4 ++-- force_torque_sensor_broadcaster/package.xml | 2 +- forward_command_controller/CHANGELOG.rst | 4 ++-- forward_command_controller/package.xml | 2 +- gripper_controllers/CHANGELOG.rst | 4 ++-- gripper_controllers/package.xml | 2 +- imu_sensor_broadcaster/CHANGELOG.rst | 4 ++-- imu_sensor_broadcaster/package.xml | 2 +- joint_state_broadcaster/CHANGELOG.rst | 4 ++-- joint_state_broadcaster/package.xml | 2 +- joint_trajectory_controller/CHANGELOG.rst | 4 ++-- joint_trajectory_controller/package.xml | 2 +- pid_controller/CHANGELOG.rst | 4 ++-- pid_controller/package.xml | 2 +- position_controllers/CHANGELOG.rst | 4 ++-- position_controllers/package.xml | 2 +- range_sensor_broadcaster/CHANGELOG.rst | 4 ++-- range_sensor_broadcaster/package.xml | 2 +- ros2_controllers/CHANGELOG.rst | 4 ++-- ros2_controllers/package.xml | 2 +- ros2_controllers_test_nodes/CHANGELOG.rst | 4 ++-- ros2_controllers_test_nodes/package.xml | 2 +- ros2_controllers_test_nodes/setup.py | 2 +- rqt_joint_trajectory_controller/CHANGELOG.rst | 4 ++-- rqt_joint_trajectory_controller/package.xml | 2 +- rqt_joint_trajectory_controller/setup.py | 2 +- steering_controllers_library/CHANGELOG.rst | 4 ++-- steering_controllers_library/package.xml | 2 +- tricycle_controller/CHANGELOG.rst | 4 ++-- tricycle_controller/package.xml | 2 +- tricycle_steering_controller/CHANGELOG.rst | 4 ++-- tricycle_steering_controller/package.xml | 2 +- velocity_controllers/CHANGELOG.rst | 4 ++-- velocity_controllers/package.xml | 2 +- 44 files changed, 65 insertions(+), 65 deletions(-) diff --git a/ackermann_steering_controller/CHANGELOG.rst b/ackermann_steering_controller/CHANGELOG.rst index 15e7408f00..975ecbf5a6 100644 --- a/ackermann_steering_controller/CHANGELOG.rst +++ b/ackermann_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ackermann_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.2.0 (2023-12-12) +------------------ 4.1.0 (2023-12-01) ------------------ diff --git a/ackermann_steering_controller/package.xml b/ackermann_steering_controller/package.xml index 476c4d3050..20bfca8003 100644 --- a/ackermann_steering_controller/package.xml +++ b/ackermann_steering_controller/package.xml @@ -2,7 +2,7 @@ ackermann_steering_controller - 4.1.0 + 4.2.0 Steering controller for Ackermann kinematics. Rear fixed wheels are powering the vehicle and front wheels are steering it. Apache License 2.0 Bence Magyar diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index c1053639c0..86ba49d92a 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.2.0 (2023-12-12) +------------------ 4.1.0 (2023-12-01) ------------------ diff --git a/admittance_controller/package.xml b/admittance_controller/package.xml index da5b652bd0..478b10bb55 100644 --- a/admittance_controller/package.xml +++ b/admittance_controller/package.xml @@ -2,7 +2,7 @@ admittance_controller - 4.1.0 + 4.2.0 Implementation of admittance controllers for different input and output interface. Denis Štogl Bence Magyar diff --git a/bicycle_steering_controller/CHANGELOG.rst b/bicycle_steering_controller/CHANGELOG.rst index 89d3f6291d..d7259fbc75 100644 --- a/bicycle_steering_controller/CHANGELOG.rst +++ b/bicycle_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package bicycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.2.0 (2023-12-12) +------------------ 4.1.0 (2023-12-01) ------------------ diff --git a/bicycle_steering_controller/package.xml b/bicycle_steering_controller/package.xml index c627577ee8..2573605890 100644 --- a/bicycle_steering_controller/package.xml +++ b/bicycle_steering_controller/package.xml @@ -2,7 +2,7 @@ bicycle_steering_controller - 4.1.0 + 4.2.0 Steering controller with bicycle kinematics. Rear fixed wheel is powering the vehicle and front wheel is steering. Apache License 2.0 Bence Magyar diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index 646903a5ac..eb40ec1db1 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.2.0 (2023-12-12) +------------------ 4.1.0 (2023-12-01) ------------------ diff --git a/diff_drive_controller/package.xml b/diff_drive_controller/package.xml index 03dffe764d..5cacf41dad 100644 --- a/diff_drive_controller/package.xml +++ b/diff_drive_controller/package.xml @@ -1,7 +1,7 @@ diff_drive_controller - 4.1.0 + 4.2.0 Controller for a differential drive mobile base. Bence Magyar Jordan Palacios diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index 7cf9e2f114..6cd3b74a95 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.2.0 (2023-12-12) +------------------ 4.1.0 (2023-12-01) ------------------ diff --git a/effort_controllers/package.xml b/effort_controllers/package.xml index e55e095c57..e42456c828 100644 --- a/effort_controllers/package.xml +++ b/effort_controllers/package.xml @@ -1,7 +1,7 @@ effort_controllers - 4.1.0 + 4.2.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index 027158d18c..a808f82c70 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.2.0 (2023-12-12) +------------------ 4.1.0 (2023-12-01) ------------------ diff --git a/force_torque_sensor_broadcaster/package.xml b/force_torque_sensor_broadcaster/package.xml index 48db0e49b6..154e597c5f 100644 --- a/force_torque_sensor_broadcaster/package.xml +++ b/force_torque_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ force_torque_sensor_broadcaster - 4.1.0 + 4.2.0 Controller to publish state of force-torque sensors. Bence Magyar Denis Štogl diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index e23dc6db47..45e5a8081c 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.2.0 (2023-12-12) +------------------ 4.1.0 (2023-12-01) ------------------ diff --git a/forward_command_controller/package.xml b/forward_command_controller/package.xml index c500c1f714..324ec1c5be 100644 --- a/forward_command_controller/package.xml +++ b/forward_command_controller/package.xml @@ -1,7 +1,7 @@ forward_command_controller - 4.1.0 + 4.2.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index 4c492457f2..ff2046a41b 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.2.0 (2023-12-12) +------------------ 4.1.0 (2023-12-01) ------------------ diff --git a/gripper_controllers/package.xml b/gripper_controllers/package.xml index 34c7ba663e..ce981141a5 100644 --- a/gripper_controllers/package.xml +++ b/gripper_controllers/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> gripper_controllers - 4.1.0 + 4.2.0 The gripper_controllers package Bence Magyar diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index 55c324f22c..e8be87d1f3 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.2.0 (2023-12-12) +------------------ 4.1.0 (2023-12-01) ------------------ diff --git a/imu_sensor_broadcaster/package.xml b/imu_sensor_broadcaster/package.xml index 3ab9c5fff6..48a26ead3f 100644 --- a/imu_sensor_broadcaster/package.xml +++ b/imu_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ imu_sensor_broadcaster - 4.1.0 + 4.2.0 Controller to publish readings of IMU sensors. Bence Magyar Denis Štogl diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index d46f807ab5..4e92131965 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.2.0 (2023-12-12) +------------------ 4.1.0 (2023-12-01) ------------------ diff --git a/joint_state_broadcaster/package.xml b/joint_state_broadcaster/package.xml index 37ba7b4912..300f8b2238 100644 --- a/joint_state_broadcaster/package.xml +++ b/joint_state_broadcaster/package.xml @@ -1,7 +1,7 @@ joint_state_broadcaster - 4.1.0 + 4.2.0 Broadcaster to publish joint state Bence Magyar Denis Stogl diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index f2406abef0..1b3559af58 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.2.0 (2023-12-12) +------------------ * Cleanup package.xml und clarify tests of JTC. (`#889 `_) * Fix floating point comparison in JTC (`#879 `_) * Contributors: Abishalini Sivaraman, Dr. Denis diff --git a/joint_trajectory_controller/package.xml b/joint_trajectory_controller/package.xml index 70d9bd51d2..1d0929b8b5 100644 --- a/joint_trajectory_controller/package.xml +++ b/joint_trajectory_controller/package.xml @@ -1,7 +1,7 @@ joint_trajectory_controller - 4.1.0 + 4.2.0 Controller for executing joint-space trajectories on a group of joints Bence Magyar Dr. Denis Štogl diff --git a/pid_controller/CHANGELOG.rst b/pid_controller/CHANGELOG.rst index af41de496e..5924bc6d94 100644 --- a/pid_controller/CHANGELOG.rst +++ b/pid_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package pid_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.2.0 (2023-12-12) +------------------ * 🚀 Add PID controller 🎉 (`#434 `_) * Contributors: Dr. Denis diff --git a/pid_controller/package.xml b/pid_controller/package.xml index c955c4747a..7caa3f7856 100644 --- a/pid_controller/package.xml +++ b/pid_controller/package.xml @@ -2,7 +2,7 @@ pid_controller - 4.1.0 + 4.2.0 Controller based on PID implememenation from control_toolbox package. Bence Magyar Denis Štogl diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index ef93a8b3d9..2e1e38fa43 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.2.0 (2023-12-12) +------------------ 4.1.0 (2023-12-01) ------------------ diff --git a/position_controllers/package.xml b/position_controllers/package.xml index 1aec89e59d..8ed752c536 100644 --- a/position_controllers/package.xml +++ b/position_controllers/package.xml @@ -1,7 +1,7 @@ position_controllers - 4.1.0 + 4.2.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/range_sensor_broadcaster/CHANGELOG.rst b/range_sensor_broadcaster/CHANGELOG.rst index b530b7c721..c92b4867b5 100644 --- a/range_sensor_broadcaster/CHANGELOG.rst +++ b/range_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package range_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.2.0 (2023-12-12) +------------------ 4.1.0 (2023-12-01) ------------------ diff --git a/range_sensor_broadcaster/package.xml b/range_sensor_broadcaster/package.xml index 222d87e3bb..08e8fd9506 100644 --- a/range_sensor_broadcaster/package.xml +++ b/range_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ range_sensor_broadcaster - 4.1.0 + 4.2.0 Controller to publish readings of Range sensors. Bence Magyar Florent Chretien diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index 03064c6f95..5839d43b68 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.2.0 (2023-12-12) +------------------ * 🚀 Add PID controller 🎉 (`#434 `_) * Contributors: Dr. Denis diff --git a/ros2_controllers/package.xml b/ros2_controllers/package.xml index 3b77b7cc69..793aea9140 100644 --- a/ros2_controllers/package.xml +++ b/ros2_controllers/package.xml @@ -1,7 +1,7 @@ ros2_controllers - 4.1.0 + 4.2.0 Metapackage for ROS2 controllers related packages Bence Magyar Jordan Palacios diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index b6dcdc8d3a..d7c37b2fee 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.2.0 (2023-12-12) +------------------ 4.1.0 (2023-12-01) ------------------ diff --git a/ros2_controllers_test_nodes/package.xml b/ros2_controllers_test_nodes/package.xml index 16dd709c25..84ebaea6fa 100644 --- a/ros2_controllers_test_nodes/package.xml +++ b/ros2_controllers_test_nodes/package.xml @@ -2,7 +2,7 @@ ros2_controllers_test_nodes - 4.1.0 + 4.2.0 Demo nodes for showing and testing functionalities of the ros2_control framework. Denis Štogl diff --git a/ros2_controllers_test_nodes/setup.py b/ros2_controllers_test_nodes/setup.py index baa01b97c2..b9aa443081 100644 --- a/ros2_controllers_test_nodes/setup.py +++ b/ros2_controllers_test_nodes/setup.py @@ -20,7 +20,7 @@ setup( name=package_name, - version="4.1.0", + version="4.2.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index 5e0c8f82da..67d9eb85df 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.2.0 (2023-12-12) +------------------ * Fix rqt jtc bugs for continuous joints and other minor bugs (`#890 `_) * Contributors: Sai Kishor Kothakota diff --git a/rqt_joint_trajectory_controller/package.xml b/rqt_joint_trajectory_controller/package.xml index 24ed2c9d63..4e7c622798 100644 --- a/rqt_joint_trajectory_controller/package.xml +++ b/rqt_joint_trajectory_controller/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> rqt_joint_trajectory_controller - 4.1.0 + 4.2.0 Graphical frontend for interacting with joint_trajectory_controller instances. Bence Magyar diff --git a/rqt_joint_trajectory_controller/setup.py b/rqt_joint_trajectory_controller/setup.py index 2d855d9255..1e49983693 100644 --- a/rqt_joint_trajectory_controller/setup.py +++ b/rqt_joint_trajectory_controller/setup.py @@ -7,7 +7,7 @@ setup( name=package_name, - version="4.1.0", + version="4.2.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/steering_controllers_library/CHANGELOG.rst b/steering_controllers_library/CHANGELOG.rst index 44f3fa515f..fa8cd4ee2f 100644 --- a/steering_controllers_library/CHANGELOG.rst +++ b/steering_controllers_library/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package steering_controllers_library ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.2.0 (2023-12-12) +------------------ 4.1.0 (2023-12-01) ------------------ diff --git a/steering_controllers_library/package.xml b/steering_controllers_library/package.xml index 5de0ddc872..85398f1d90 100644 --- a/steering_controllers_library/package.xml +++ b/steering_controllers_library/package.xml @@ -2,7 +2,7 @@ steering_controllers_library - 4.1.0 + 4.2.0 Package for steering robot configurations including odometry and interfaces. Apache License 2.0 Bence Magyar diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index 98957eb42f..d7424ca31a 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.2.0 (2023-12-12) +------------------ 4.1.0 (2023-12-01) ------------------ diff --git a/tricycle_controller/package.xml b/tricycle_controller/package.xml index 5f382bf8d2..4f131da79c 100644 --- a/tricycle_controller/package.xml +++ b/tricycle_controller/package.xml @@ -2,7 +2,7 @@ tricycle_controller - 4.1.0 + 4.2.0 Controller for a tricycle drive mobile base Bence Magyar Tony Najjar diff --git a/tricycle_steering_controller/CHANGELOG.rst b/tricycle_steering_controller/CHANGELOG.rst index cb3a5af24d..3d04f2ba8d 100644 --- a/tricycle_steering_controller/CHANGELOG.rst +++ b/tricycle_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package tricycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.2.0 (2023-12-12) +------------------ 4.1.0 (2023-12-01) ------------------ diff --git a/tricycle_steering_controller/package.xml b/tricycle_steering_controller/package.xml index f565ef0c02..f6eb3fff49 100644 --- a/tricycle_steering_controller/package.xml +++ b/tricycle_steering_controller/package.xml @@ -2,7 +2,7 @@ tricycle_steering_controller - 4.1.0 + 4.2.0 Steering controller with tricycle kinematics. Rear fixed wheels are powering the vehicle and front wheel is steering. Apache License 2.0 Bence Magyar diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index 8b84ddf784..98d6523639 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.2.0 (2023-12-12) +------------------ 4.1.0 (2023-12-01) ------------------ diff --git a/velocity_controllers/package.xml b/velocity_controllers/package.xml index d7376e8e6b..3d901585db 100644 --- a/velocity_controllers/package.xml +++ b/velocity_controllers/package.xml @@ -1,7 +1,7 @@ velocity_controllers - 4.1.0 + 4.2.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios From 13a43c32b5b4d0040c96d4e192db4f1ed6d4f046 Mon Sep 17 00:00:00 2001 From: Reza Kermani Date: Wed, 13 Dec 2023 07:16:11 -0500 Subject: [PATCH 174/238] Changing default int values to double in steering controller's yaml file (#927) --- .../src/steering_controllers_library.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/steering_controllers_library/src/steering_controllers_library.yaml b/steering_controllers_library/src/steering_controllers_library.yaml index 8acdfb1448..a9f7fa75fb 100644 --- a/steering_controllers_library/src/steering_controllers_library.yaml +++ b/steering_controllers_library/src/steering_controllers_library.yaml @@ -1,7 +1,7 @@ steering_controllers_library: reference_timeout: { type: double, - default_value: 1, + default_value: 1.0, description: "Timeout for controller references after which they will be reset. This is especially useful for controllers that can cause unwanted and dangerous behaviour if reference is not reset, e.g., velocity controllers. If value is 0 the reference is reset after each run.", } @@ -93,14 +93,14 @@ steering_controllers_library: twist_covariance_diagonal: { type: double_array, - default_value: [0, 7, 14, 21, 28, 35], + default_value: [0.0, 7.0, 14.0, 21.0, 28.0, 35.0], description: "diagonal values of twist covariance matrix.", read_only: false, } pose_covariance_diagonal: { type: double_array, - default_value: [0, 7, 14, 21, 28, 35], + default_value: [0.0, 7.0, 14.0, 21.0, 28.0, 35.0], description: "diagonal values of pose covariance matrix.", read_only: false, } From 691175034c8de94dc70318fa3edb9f3e889434d5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 21 Dec 2023 11:23:49 +0000 Subject: [PATCH 175/238] Bump actions/upload-artifact from 3.1.3 to 4.0.0 (#934) --- .github/workflows/ci-coverage-build-humble.yml | 2 +- .github/workflows/ci-coverage-build-iron.yml | 2 +- .github/workflows/ci-coverage-build.yml | 2 +- .github/workflows/reusable-ros-tooling-source-build.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-coverage-build-humble.yml b/.github/workflows/ci-coverage-build-humble.yml index ece507aaa1..a1d159541d 100644 --- a/.github/workflows/ci-coverage-build-humble.yml +++ b/.github/workflows/ci-coverage-build-humble.yml @@ -60,7 +60,7 @@ jobs: file: ros_ws/lcov/total_coverage.info flags: unittests name: codecov-umbrella - - uses: actions/upload-artifact@v3.1.3 + - uses: actions/upload-artifact@v4.0.0 with: name: colcon-logs-coverage-humble path: ros_ws/log diff --git a/.github/workflows/ci-coverage-build-iron.yml b/.github/workflows/ci-coverage-build-iron.yml index 8d77e65b6b..08e6eafd82 100644 --- a/.github/workflows/ci-coverage-build-iron.yml +++ b/.github/workflows/ci-coverage-build-iron.yml @@ -60,7 +60,7 @@ jobs: file: ros_ws/lcov/total_coverage.info flags: unittests name: codecov-umbrella - - uses: actions/upload-artifact@v3.1.3 + - uses: actions/upload-artifact@v4.0.0 with: name: colcon-logs-coverage-iron path: ros_ws/log diff --git a/.github/workflows/ci-coverage-build.yml b/.github/workflows/ci-coverage-build.yml index bf9ad847b4..f785652989 100644 --- a/.github/workflows/ci-coverage-build.yml +++ b/.github/workflows/ci-coverage-build.yml @@ -60,7 +60,7 @@ jobs: file: ros_ws/lcov/total_coverage.info flags: unittests name: codecov-umbrella - - uses: actions/upload-artifact@v3.1.3 + - uses: actions/upload-artifact@v4.0.0 with: name: colcon-logs-coverage-rolling path: ros_ws/log diff --git a/.github/workflows/reusable-ros-tooling-source-build.yml b/.github/workflows/reusable-ros-tooling-source-build.yml index f0ac7b447d..fcc1a297fd 100644 --- a/.github/workflows/reusable-ros-tooling-source-build.yml +++ b/.github/workflows/reusable-ros-tooling-source-build.yml @@ -63,7 +63,7 @@ jobs: https://raw.githubusercontent.com/ros2/ros2/${{ inputs.ros2_repo_branch }}/ros2.repos https://raw.githubusercontent.com/${{ github.repository }}/${{ github.sha }}/ros2_controllers.${{ inputs.ros_distro }}.repos?token=${{ secrets.GITHUB_TOKEN }} colcon-mixin-repository: https://raw.githubusercontent.com/colcon/colcon-mixin-repository/master/index.yaml - - uses: actions/upload-artifact@v3.1.3 + - uses: actions/upload-artifact@v4.0.0 with: name: colcon-logs-ubuntu-22.04 path: ros_ws/log From 4c6d7236245c527f275b1e03a7e5242b658dc782 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Thu, 21 Dec 2023 12:29:46 +0100 Subject: [PATCH 176/238] [JTC] Add console output for tolerance checks (#932) --- .../joint_trajectory_controller/tolerances.hpp | 2 +- .../src/joint_trajectory_controller.cpp | 17 +++++++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/joint_trajectory_controller/include/joint_trajectory_controller/tolerances.hpp b/joint_trajectory_controller/include/joint_trajectory_controller/tolerances.hpp index b4cb029dd9..b5e660be54 100644 --- a/joint_trajectory_controller/include/joint_trajectory_controller/tolerances.hpp +++ b/joint_trajectory_controller/include/joint_trajectory_controller/tolerances.hpp @@ -150,7 +150,7 @@ inline bool check_state_tolerance_per_joint( if (show_errors) { const auto logger = rclcpp::get_logger("tolerances"); - RCLCPP_ERROR(logger, "Path state tolerances failed:"); + RCLCPP_ERROR(logger, "State tolerances failed for joint %d:", joint_idx); if (state_tolerance.position > 0.0 && abs(error_position) > state_tolerance.position) { diff --git a/joint_trajectory_controller/src/joint_trajectory_controller.cpp b/joint_trajectory_controller/src/joint_trajectory_controller.cpp index 59e2c408c5..c6a5169855 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller.cpp +++ b/joint_trajectory_controller/src/joint_trajectory_controller.cpp @@ -247,20 +247,21 @@ controller_interface::return_type JointTrajectoryController::update( // Always check the state tolerance on the first sample in case the first sample // is the last point + // print output per default, goal will be aborted afterwards if ( - (before_last_point || first_sample) && + (before_last_point || first_sample) && *(rt_is_holding_.readFromRT()) == false && !check_state_tolerance_per_joint( - state_error_, index, default_tolerances_.state_tolerance[index], false) && - *(rt_is_holding_.readFromRT()) == false) + state_error_, index, default_tolerances_.state_tolerance[index], + true /* show_errors */)) { tolerance_violated_while_moving = true; } // past the final point, check that we end up inside goal tolerance if ( - !before_last_point && + !before_last_point && *(rt_is_holding_.readFromRT()) == false && !check_state_tolerance_per_joint( - state_error_, index, default_tolerances_.goal_state_tolerance[index], false) && - *(rt_is_holding_.readFromRT()) == false) + state_error_, index, default_tolerances_.goal_state_tolerance[index], + false /* show_errors */)) { outside_goal_tolerance = true; @@ -269,6 +270,10 @@ controller_interface::return_type JointTrajectoryController::update( if (time_difference > default_tolerances_.goal_time_tolerance) { within_goal_time = false; + // print once, goal will be aborted afterwards + check_state_tolerance_per_joint( + state_error_, index, default_tolerances_.goal_state_tolerance[index], + true /* show_errors */); } } } From 3c3f61437b89d53f01918d6e49f4428112609824 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Sat, 23 Dec 2023 08:53:42 +0100 Subject: [PATCH 177/238] Do not run reviewer lottery for dependabot and mergify (#946) --- .github/workflows/reviewer_lottery.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/reviewer_lottery.yml b/.github/workflows/reviewer_lottery.yml index 2edbc9b59e..ed28964e01 100644 --- a/.github/workflows/reviewer_lottery.yml +++ b/.github/workflows/reviewer_lottery.yml @@ -6,6 +6,7 @@ on: jobs: test: runs-on: ubuntu-latest + if: github.actor != 'dependabot[bot]' && github.actor != 'mergify[bot]' steps: - uses: actions/checkout@v4 - uses: uesteibar/reviewer-lottery@v3 From dcd15ee6bac003aecd668943f3d4c93c1e0ee171 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Fri, 29 Dec 2023 12:40:21 +0100 Subject: [PATCH 178/238] Add rqt_JTC to docs (#950) --- joint_trajectory_controller/doc/userdoc.rst | 1 + .../doc/rqt_joint_trajectory_controller.png | Bin 0 -> 29746 bytes rqt_joint_trajectory_controller/doc/userdoc.rst | 12 ++++++++++++ 3 files changed, 13 insertions(+) create mode 100644 rqt_joint_trajectory_controller/doc/rqt_joint_trajectory_controller.png create mode 100644 rqt_joint_trajectory_controller/doc/userdoc.rst diff --git a/joint_trajectory_controller/doc/userdoc.rst b/joint_trajectory_controller/doc/userdoc.rst index 6a34185437..6fe2146802 100644 --- a/joint_trajectory_controller/doc/userdoc.rst +++ b/joint_trajectory_controller/doc/userdoc.rst @@ -193,6 +193,7 @@ Further information Trajectory Representation joint_trajectory_controller Parameters + rqt_joint_trajectory_controller <../../rqt_joint_trajectory_controller/doc/userdoc.rst> .. rubric:: Footnote diff --git a/rqt_joint_trajectory_controller/doc/rqt_joint_trajectory_controller.png b/rqt_joint_trajectory_controller/doc/rqt_joint_trajectory_controller.png new file mode 100644 index 0000000000000000000000000000000000000000..cb86f4620bcc091f87db272c7868d16966b091b6 GIT binary patch literal 29746 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 literal 0 HcmV?d00001 diff --git a/rqt_joint_trajectory_controller/doc/userdoc.rst b/rqt_joint_trajectory_controller/doc/userdoc.rst new file mode 100644 index 0000000000..197a7afb30 --- /dev/null +++ b/rqt_joint_trajectory_controller/doc/userdoc.rst @@ -0,0 +1,12 @@ +:github_url: https://github.com/ros-controls/ros2_controllers/blob/{REPOS_FILE_BRANCH}/rqt_joint_trajectory_controller/doc/userdoc.rst + +.. _rqt_joint_trajectory_controller_userdoc: + +rqt_joint_trajectory_controller +=============================== + +rqt_joint_trajectory_controller is a GUI plugin for rqt that allows to command a joint_trajectory_controller. + +.. image:: rqt_joint_trajectory_controller.png + :width: 400 + :alt: rqt_joint_trajectory_controller From d915497394710481a98cbaf7b6db8ef9a368aa3e Mon Sep 17 00:00:00 2001 From: Franz Rammerstorfer <60260174+franzrammerstorfer@users.noreply.github.com> Date: Sat, 30 Dec 2023 21:25:35 +0100 Subject: [PATCH 179/238] Fix ackermann steering odometry (#921) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix Ackermann steering odometry bug issue #878 --------- Co-authored-by: Christoph Fröhlich --- steering_controllers_library/CMakeLists.txt | 3 + .../src/steering_odometry.cpp | 4 +- .../test/test_steering_odometry.cpp | 110 ++++++++++++++++++ 3 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 steering_controllers_library/test/test_steering_odometry.cpp diff --git a/steering_controllers_library/CMakeLists.txt b/steering_controllers_library/CMakeLists.txt index b64ea204a8..63de42cf69 100644 --- a/steering_controllers_library/CMakeLists.txt +++ b/steering_controllers_library/CMakeLists.txt @@ -67,6 +67,9 @@ if(BUILD_TESTING) controller_interface hardware_interface ) + ament_add_gmock(test_steering_odometry test/test_steering_odometry.cpp) + target_link_libraries(test_steering_odometry steering_controllers_library) + endif() install( diff --git a/steering_controllers_library/src/steering_odometry.cpp b/steering_controllers_library/src/steering_odometry.cpp index bf254bfcfa..e2ced036ff 100644 --- a/steering_controllers_library/src/steering_odometry.cpp +++ b/steering_controllers_library/src/steering_odometry.cpp @@ -270,8 +270,8 @@ std::tuple, std::vector> SteeringOdometry::get_comma double denominator_first_member = 2 * wheelbase_ * std::cos(alpha); double denominator_second_member = wheel_track_ * std::sin(alpha); - double alpha_r = std::atan2(numerator, denominator_first_member - denominator_second_member); - double alpha_l = std::atan2(numerator, denominator_first_member + denominator_second_member); + double alpha_r = std::atan2(numerator, denominator_first_member + denominator_second_member); + double alpha_l = std::atan2(numerator, denominator_first_member - denominator_second_member); steering_commands = {alpha_r, alpha_l}; } return std::make_tuple(traction_commands, steering_commands); diff --git a/steering_controllers_library/test/test_steering_odometry.cpp b/steering_controllers_library/test/test_steering_odometry.cpp new file mode 100644 index 0000000000..173c76baef --- /dev/null +++ b/steering_controllers_library/test/test_steering_odometry.cpp @@ -0,0 +1,110 @@ +// Copyright (c) 2023, Virtual Vehicle Research GmbH +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "gmock/gmock.h" + +#include "steering_controllers_library/steering_odometry.hpp" + +TEST(TestSteeringOdometry, initialize) +{ + EXPECT_NO_THROW(steering_odometry::SteeringOdometry()); + + steering_odometry::SteeringOdometry odom(1); + odom.set_wheel_params(1., 2., 3.); + odom.set_odometry_type(steering_odometry::ACKERMANN_CONFIG); + EXPECT_DOUBLE_EQ(odom.get_heading(), 0.); + EXPECT_DOUBLE_EQ(odom.get_x(), 0.); + EXPECT_DOUBLE_EQ(odom.get_y(), 0.); +} + +TEST(TestSteeringOdometry, ackermann_fwd_kin_linear) +{ + steering_odometry::SteeringOdometry odom(1); + odom.set_wheel_params(1., 2., 1.); + odom.set_odometry_type(steering_odometry::ACKERMANN_CONFIG); + odom.update_open_loop(2., 0., 0.5); + EXPECT_DOUBLE_EQ(odom.get_linear(), 2.); + EXPECT_DOUBLE_EQ(odom.get_x(), 1.); + EXPECT_DOUBLE_EQ(odom.get_y(), 0.); +} + +TEST(TestSteeringOdometry, ackermann_fwd_kin_angular_left) +{ + steering_odometry::SteeringOdometry odom(1); + odom.set_wheel_params(1., 2., 1.); + odom.set_odometry_type(steering_odometry::ACKERMANN_CONFIG); + odom.update_open_loop(1., 1., 1.); + EXPECT_DOUBLE_EQ(odom.get_linear(), 1.); + EXPECT_DOUBLE_EQ(odom.get_angular(), 1.); + + EXPECT_GT(odom.get_x(), 0); // pos x + EXPECT_GT(odom.get_y(), 0); // pos y, ie. left +} + +TEST(TestSteeringOdometry, ackermann_fwd_kin_angular_right) +{ + steering_odometry::SteeringOdometry odom(1); + odom.set_wheel_params(1., 2., 1.); + odom.set_odometry_type(steering_odometry::ACKERMANN_CONFIG); + odom.update_open_loop(1., -1., 1.); + EXPECT_DOUBLE_EQ(odom.get_linear(), 1.); + EXPECT_DOUBLE_EQ(odom.get_angular(), -1.); + EXPECT_GT(odom.get_x(), 0); // pos x + EXPECT_LT(odom.get_y(), 0); // neg y ie. right +} + +TEST(TestSteeringOdometry, ackermann_back_kin_linear) +{ + steering_odometry::SteeringOdometry odom(1); + odom.set_wheel_params(1., 2., 1.); + odom.set_odometry_type(steering_odometry::ACKERMANN_CONFIG); + odom.update_open_loop(1., 0., 1.); + auto cmd = odom.get_commands(1., 0.); + auto cmd0 = std::get<0>(cmd); // vel + EXPECT_EQ(cmd0[0], cmd0[1]); // linear + EXPECT_GT(cmd0[0], 0); + auto cmd1 = std::get<1>(cmd); // steer + EXPECT_EQ(cmd1[0], cmd1[1]); // no steering + EXPECT_EQ(cmd1[0], 0); +} + +TEST(TestSteeringOdometry, ackermann_back_kin_left) +{ + steering_odometry::SteeringOdometry odom(1); + odom.set_wheel_params(1., 2., 1.); + odom.set_odometry_type(steering_odometry::ACKERMANN_CONFIG); + odom.update_from_position(0., 0.2, 1.); // assume already turn + auto cmd = odom.get_commands(1., 0.1); + auto cmd0 = std::get<0>(cmd); // vel + EXPECT_GT(cmd0[0], cmd0[1]); // right (outer) > left (inner) + EXPECT_GT(cmd0[0], 0); + auto cmd1 = std::get<1>(cmd); // steer + EXPECT_LT(cmd1[0], cmd1[1]); // right (outer) < left (inner) + EXPECT_GT(cmd1[0], 0); +} + +TEST(TestSteeringOdometry, ackermann_back_kin_right) +{ + steering_odometry::SteeringOdometry odom(1); + odom.set_wheel_params(1., 2., 1.); + odom.set_odometry_type(steering_odometry::ACKERMANN_CONFIG); + odom.update_from_position(0., -0.2, 1.); // assume already turn + auto cmd = odom.get_commands(1., -0.1); + auto cmd0 = std::get<0>(cmd); // vel + EXPECT_LT(cmd0[0], cmd0[1]); // right (inner) < left outer) + EXPECT_GT(cmd0[0], 0); + auto cmd1 = std::get<1>(cmd); // steer + EXPECT_GT(std::abs(cmd1[0]), std::abs(cmd1[1])); // abs right (inner) > abs left (outer) + EXPECT_LT(cmd1[0], 0); +} From f14396cc14d023a8b9d6bc9a38331e4af59f181e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Tue, 2 Jan 2024 16:14:10 +0100 Subject: [PATCH 180/238] [JTC] Cleanup includes (#943) --- .../joint_trajectory_controller.hpp | 18 +++--------------- .../joint_trajectory_controller/tolerances.hpp | 3 --- .../src/joint_trajectory_controller.cpp | 8 +------- .../test/test_trajectory_controller.cpp | 5 ----- .../test/test_trajectory_controller_utils.hpp | 1 - 5 files changed, 4 insertions(+), 31 deletions(-) diff --git a/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp b/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp index d16e4f8267..0ed2ce5688 100644 --- a/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp +++ b/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp @@ -16,10 +16,9 @@ #define JOINT_TRAJECTORY_CONTROLLER__JOINT_TRAJECTORY_CONTROLLER_HPP_ #include +#include // for std::reference_wrapper #include -#include #include -#include #include #include "control_msgs/action/follow_joint_trajectory.hpp" @@ -30,15 +29,15 @@ #include "hardware_interface/types/hardware_interface_type_values.hpp" #include "joint_trajectory_controller/interpolation_methods.hpp" #include "joint_trajectory_controller/tolerances.hpp" +#include "joint_trajectory_controller/trajectory.hpp" #include "joint_trajectory_controller/visibility_control.h" #include "rclcpp/duration.hpp" #include "rclcpp/subscription.hpp" #include "rclcpp/time.hpp" #include "rclcpp/timer.hpp" #include "rclcpp_action/server.hpp" -#include "rclcpp_action/types.hpp" -#include "rclcpp_lifecycle/lifecycle_publisher.hpp" #include "rclcpp_lifecycle/node_interfaces/lifecycle_node_interface.hpp" +#include "rclcpp_lifecycle/state.hpp" #include "realtime_tools/realtime_buffer.h" #include "realtime_tools/realtime_publisher.h" #include "realtime_tools/realtime_server_goal_handle.h" @@ -50,19 +49,8 @@ using namespace std::chrono_literals; // NOLINT -namespace rclcpp_action -{ -template -class ServerGoalHandle; -} // namespace rclcpp_action -namespace rclcpp_lifecycle -{ -class State; -} // namespace rclcpp_lifecycle - namespace joint_trajectory_controller { -class Trajectory; class JointTrajectoryController : public controller_interface::ControllerInterface { diff --git a/joint_trajectory_controller/include/joint_trajectory_controller/tolerances.hpp b/joint_trajectory_controller/include/joint_trajectory_controller/tolerances.hpp index b5e660be54..792938b96f 100644 --- a/joint_trajectory_controller/include/joint_trajectory_controller/tolerances.hpp +++ b/joint_trajectory_controller/include/joint_trajectory_controller/tolerances.hpp @@ -30,9 +30,6 @@ #ifndef JOINT_TRAJECTORY_CONTROLLER__TOLERANCES_HPP_ #define JOINT_TRAJECTORY_CONTROLLER__TOLERANCES_HPP_ -#include -#include -#include #include #include "control_msgs/action/follow_joint_trajectory.hpp" diff --git a/joint_trajectory_controller/src/joint_trajectory_controller.cpp b/joint_trajectory_controller/src/joint_trajectory_controller.cpp index c6a5169855..b1cca67547 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller.cpp +++ b/joint_trajectory_controller/src/joint_trajectory_controller.cpp @@ -14,12 +14,10 @@ #include "joint_trajectory_controller/joint_trajectory_controller.hpp" -#include #include #include #include -#include -#include + #include #include @@ -33,15 +31,11 @@ #include "lifecycle_msgs/msg/state.hpp" #include "rclcpp/event_handler.hpp" #include "rclcpp/logging.hpp" -#include "rclcpp/parameter.hpp" #include "rclcpp/qos.hpp" #include "rclcpp/time.hpp" #include "rclcpp_action/create_server.hpp" #include "rclcpp_action/server_goal_handle.hpp" -#include "rclcpp_lifecycle/lifecycle_node.hpp" -#include "rclcpp_lifecycle/node_interfaces/lifecycle_node_interface.hpp" #include "rclcpp_lifecycle/state.hpp" -#include "std_msgs/msg/header.hpp" namespace joint_trajectory_controller { diff --git a/joint_trajectory_controller/test/test_trajectory_controller.cpp b/joint_trajectory_controller/test/test_trajectory_controller.cpp index 05010c562c..72820c0295 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller.cpp +++ b/joint_trajectory_controller/test/test_trajectory_controller.cpp @@ -14,7 +14,6 @@ #include -#include #include #include #include @@ -30,7 +29,6 @@ #include "builtin_interfaces/msg/time.hpp" #include "controller_interface/controller_interface.hpp" #include "hardware_interface/resource_manager.hpp" -#include "joint_trajectory_controller/joint_trajectory_controller.hpp" #include "lifecycle_msgs/msg/state.hpp" #include "rclcpp/clock.hpp" #include "rclcpp/duration.hpp" @@ -44,9 +42,6 @@ #include "rclcpp/subscription.hpp" #include "rclcpp/time.hpp" #include "rclcpp/utilities.hpp" -#include "rclcpp_lifecycle/lifecycle_node.hpp" -#include "rclcpp_lifecycle/state.hpp" -#include "std_msgs/msg/header.hpp" #include "trajectory_msgs/msg/joint_trajectory.hpp" #include "trajectory_msgs/msg/joint_trajectory_point.hpp" diff --git a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp index 7b68d882ff..e636fad4b7 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp +++ b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp @@ -25,7 +25,6 @@ #include "hardware_interface/types/hardware_interface_type_values.hpp" #include "joint_trajectory_controller/joint_trajectory_controller.hpp" -#include "joint_trajectory_controller/trajectory.hpp" namespace { From 2b52f0b54168341b2afe94f0aeef92c5fd41381a Mon Sep 17 00:00:00 2001 From: Sai Kishor Kothakota Date: Thu, 4 Jan 2024 10:05:31 +0100 Subject: [PATCH 181/238] Add few warning flags to error (#961) * add conversion, unused-but-set-variable, format, and return-type warnings to error * Add fixes to the added flags * fix linters --- ackermann_steering_controller/CMakeLists.txt | 3 ++- admittance_controller/CMakeLists.txt | 3 ++- bicycle_steering_controller/CMakeLists.txt | 3 ++- diff_drive_controller/CMakeLists.txt | 2 +- effort_controllers/CMakeLists.txt | 3 ++- force_torque_sensor_broadcaster/CMakeLists.txt | 3 ++- forward_command_controller/CMakeLists.txt | 3 ++- gripper_controllers/CMakeLists.txt | 2 +- imu_sensor_broadcaster/CMakeLists.txt | 3 ++- joint_state_broadcaster/CMakeLists.txt | 3 ++- joint_trajectory_controller/CMakeLists.txt | 2 +- .../include/joint_trajectory_controller/tolerances.hpp | 2 +- pid_controller/CMakeLists.txt | 2 +- pid_controller/src/pid_controller.cpp | 4 ++-- position_controllers/CMakeLists.txt | 3 ++- range_sensor_broadcaster/CMakeLists.txt | 2 +- steering_controllers_library/CMakeLists.txt | 3 ++- tricycle_controller/CMakeLists.txt | 3 ++- tricycle_steering_controller/CMakeLists.txt | 3 ++- velocity_controllers/CMakeLists.txt | 3 ++- 20 files changed, 34 insertions(+), 21 deletions(-) diff --git a/ackermann_steering_controller/CMakeLists.txt b/ackermann_steering_controller/CMakeLists.txt index 6ad0e9485f..66f09c5f09 100644 --- a/ackermann_steering_controller/CMakeLists.txt +++ b/ackermann_steering_controller/CMakeLists.txt @@ -2,7 +2,8 @@ cmake_minimum_required(VERSION 3.16) project(ackermann_steering_controller LANGUAGES CXX) if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") - add_compile_options(-Wall -Wextra -Wpedantic -Wconversion) + add_compile_options(-Wall -Wextra -Wpedantic -Werror=conversion -Werror=unused-but-set-variable + -Werror=return-type -Werror=shadow -Werror=format) endif() # find dependencies diff --git a/admittance_controller/CMakeLists.txt b/admittance_controller/CMakeLists.txt index a8a8832fce..b2c10e0ba5 100644 --- a/admittance_controller/CMakeLists.txt +++ b/admittance_controller/CMakeLists.txt @@ -2,7 +2,8 @@ cmake_minimum_required(VERSION 3.16) project(admittance_controller LANGUAGES CXX) if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") - add_compile_options(-Wall -Wextra -Wpedantic -Wconversion) + add_compile_options(-Wall -Wextra -Wpedantic -Werror=conversion -Werror=unused-but-set-variable + -Werror=return-type -Werror=shadow -Werror=format) endif() set(THIS_PACKAGE_INCLUDE_DEPENDS diff --git a/bicycle_steering_controller/CMakeLists.txt b/bicycle_steering_controller/CMakeLists.txt index 5d662c1fec..7118e9a44d 100644 --- a/bicycle_steering_controller/CMakeLists.txt +++ b/bicycle_steering_controller/CMakeLists.txt @@ -2,7 +2,8 @@ cmake_minimum_required(VERSION 3.16) project(bicycle_steering_controller LANGUAGES CXX) if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") - add_compile_options(-Wall -Wextra -Wpedantic -Wconversion) + add_compile_options(-Wall -Wextra -Wpedantic -Werror=conversion -Werror=unused-but-set-variable + -Werror=return-type -Werror=shadow -Werror=format) endif() # find dependencies diff --git a/diff_drive_controller/CMakeLists.txt b/diff_drive_controller/CMakeLists.txt index b944ff1e88..436832c523 100644 --- a/diff_drive_controller/CMakeLists.txt +++ b/diff_drive_controller/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.16) project(diff_drive_controller LANGUAGES CXX) if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") - add_compile_options(-Wall -Wextra -Wconversion) + add_compile_options(-Wall -Wextra -Werror=conversion -Werror=unused-but-set-variable -Werror=return-type -Werror=shadow -Werror=format) endif() set(THIS_PACKAGE_INCLUDE_DEPENDS diff --git a/effort_controllers/CMakeLists.txt b/effort_controllers/CMakeLists.txt index ad97690655..eae8642fb6 100644 --- a/effort_controllers/CMakeLists.txt +++ b/effort_controllers/CMakeLists.txt @@ -2,7 +2,8 @@ cmake_minimum_required(VERSION 3.16) project(effort_controllers LANGUAGES CXX) if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") - add_compile_options(-Wall -Wextra -Wpedantic -Wconversion) + add_compile_options(-Wall -Wextra -Wpedantic -Werror=conversion -Werror=unused-but-set-variable + -Werror=return-type -Werror=shadow -Werror=format) endif() set(THIS_PACKAGE_INCLUDE_DEPENDS diff --git a/force_torque_sensor_broadcaster/CMakeLists.txt b/force_torque_sensor_broadcaster/CMakeLists.txt index 2af5500e21..38c984192e 100644 --- a/force_torque_sensor_broadcaster/CMakeLists.txt +++ b/force_torque_sensor_broadcaster/CMakeLists.txt @@ -2,7 +2,8 @@ cmake_minimum_required(VERSION 3.16) project(force_torque_sensor_broadcaster LANGUAGES CXX) if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") - add_compile_options(-Wall -Wextra -Wpedantic -Wconversion) + add_compile_options(-Wall -Wextra -Wpedantic -Werror=conversion -Werror=unused-but-set-variable + -Werror=return-type -Werror=shadow -Werror=format) endif() set(THIS_PACKAGE_INCLUDE_DEPENDS diff --git a/forward_command_controller/CMakeLists.txt b/forward_command_controller/CMakeLists.txt index 15ffe09750..4885c69c8a 100644 --- a/forward_command_controller/CMakeLists.txt +++ b/forward_command_controller/CMakeLists.txt @@ -2,7 +2,8 @@ cmake_minimum_required(VERSION 3.16) project(forward_command_controller LANGUAGES CXX) if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") - add_compile_options(-Wall -Wextra -Wpedantic -Wconversion) + add_compile_options(-Wall -Wextra -Wpedantic -Werror=conversion -Werror=unused-but-set-variable + -Werror=return-type -Werror=shadow -Werror=format) endif() set(THIS_PACKAGE_INCLUDE_DEPENDS diff --git a/gripper_controllers/CMakeLists.txt b/gripper_controllers/CMakeLists.txt index 8edaaf6386..676062f7a3 100644 --- a/gripper_controllers/CMakeLists.txt +++ b/gripper_controllers/CMakeLists.txt @@ -7,7 +7,7 @@ if(APPLE OR WIN32) endif() if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") - add_compile_options(-Wall -Wextra -Wconversion) + add_compile_options(-Wall -Wextra -Werror=conversion -Werror=unused-but-set-variable -Werror=return-type -Werror=shadow -Werror=format) endif() set(THIS_PACKAGE_INCLUDE_DEPENDS diff --git a/imu_sensor_broadcaster/CMakeLists.txt b/imu_sensor_broadcaster/CMakeLists.txt index 3b09d9e72e..6782012c65 100644 --- a/imu_sensor_broadcaster/CMakeLists.txt +++ b/imu_sensor_broadcaster/CMakeLists.txt @@ -2,7 +2,8 @@ cmake_minimum_required(VERSION 3.16) project(imu_sensor_broadcaster LANGUAGES CXX) if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") - add_compile_options(-Wall -Wextra -Wpedantic -Wconversion) + add_compile_options(-Wall -Wextra -Wpedantic -Werror=conversion -Werror=unused-but-set-variable + -Werror=return-type -Werror=shadow -Werror=format) endif() set(THIS_PACKAGE_INCLUDE_DEPENDS diff --git a/joint_state_broadcaster/CMakeLists.txt b/joint_state_broadcaster/CMakeLists.txt index cadc96b4e3..5c383897cc 100644 --- a/joint_state_broadcaster/CMakeLists.txt +++ b/joint_state_broadcaster/CMakeLists.txt @@ -2,7 +2,8 @@ cmake_minimum_required(VERSION 3.16) project(joint_state_broadcaster LANGUAGES CXX) if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") - add_compile_options(-Wall -Wextra -Wconversion) + add_compile_options(-Wall -Wextra -Wpedantic -Werror=conversion -Werror=unused-but-set-variable + -Werror=return-type -Werror=shadow -Werror=format) endif() set(THIS_PACKAGE_INCLUDE_DEPENDS diff --git a/joint_trajectory_controller/CMakeLists.txt b/joint_trajectory_controller/CMakeLists.txt index 88bb7891a3..5cddb1bf4d 100644 --- a/joint_trajectory_controller/CMakeLists.txt +++ b/joint_trajectory_controller/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.16) project(joint_trajectory_controller LANGUAGES CXX) if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") - add_compile_options(-Wall -Wextra -Wconversion) + add_compile_options(-Wall -Wextra -Werror=conversion -Werror=unused-but-set-variable -Werror=return-type -Werror=shadow -Werror=format) endif() set(THIS_PACKAGE_INCLUDE_DEPENDS diff --git a/joint_trajectory_controller/include/joint_trajectory_controller/tolerances.hpp b/joint_trajectory_controller/include/joint_trajectory_controller/tolerances.hpp index 792938b96f..2157fdf2a6 100644 --- a/joint_trajectory_controller/include/joint_trajectory_controller/tolerances.hpp +++ b/joint_trajectory_controller/include/joint_trajectory_controller/tolerances.hpp @@ -147,7 +147,7 @@ inline bool check_state_tolerance_per_joint( if (show_errors) { const auto logger = rclcpp::get_logger("tolerances"); - RCLCPP_ERROR(logger, "State tolerances failed for joint %d:", joint_idx); + RCLCPP_ERROR(logger, "State tolerances failed for joint %ld:", joint_idx); if (state_tolerance.position > 0.0 && abs(error_position) > state_tolerance.position) { diff --git a/pid_controller/CMakeLists.txt b/pid_controller/CMakeLists.txt index 81cbe6f006..15e903222a 100644 --- a/pid_controller/CMakeLists.txt +++ b/pid_controller/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.16) project(pid_controller LANGUAGES CXX) if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") - add_compile_options(-Wall -Wextra) + add_compile_options(-Wall -Wextra -Werror=conversion -Werror=unused-but-set-variable -Werror=return-type -Werror=shadow -Werror=format) endif() set(THIS_PACKAGE_INCLUDE_DEPENDS diff --git a/pid_controller/src/pid_controller.cpp b/pid_controller/src/pid_controller.cpp index 373e941d96..05fee986dd 100644 --- a/pid_controller/src/pid_controller.cpp +++ b/pid_controller/src/pid_controller.cpp @@ -171,10 +171,10 @@ controller_interface::CallbackReturn PidController::on_configure( if (params_.use_external_measured_states) { auto measured_state_callback = - [&](const std::shared_ptr msg) -> void + [&](const std::shared_ptr state_msg) -> void { // TODO(destogl): Sort the input values based on joint and interface names - measured_state_.writeFromNonRT(msg); + measured_state_.writeFromNonRT(state_msg); }; measured_state_subscriber_ = get_node()->create_subscription( "~/measured_state", subscribers_qos, measured_state_callback); diff --git a/position_controllers/CMakeLists.txt b/position_controllers/CMakeLists.txt index 54a4f94656..18f3cb313a 100644 --- a/position_controllers/CMakeLists.txt +++ b/position_controllers/CMakeLists.txt @@ -2,7 +2,8 @@ cmake_minimum_required(VERSION 3.16) project(position_controllers LANGUAGES CXX) if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") - add_compile_options(-Wall -Wextra -Wpedantic -Wconversion) + add_compile_options(-Wall -Wextra -Wpedantic -Werror=conversion -Werror=unused-but-set-variable + -Werror=return-type -Werror=shadow -Werror=format) endif() set(THIS_PACKAGE_INCLUDE_DEPENDS diff --git a/range_sensor_broadcaster/CMakeLists.txt b/range_sensor_broadcaster/CMakeLists.txt index 00da395db5..d7002d1b17 100644 --- a/range_sensor_broadcaster/CMakeLists.txt +++ b/range_sensor_broadcaster/CMakeLists.txt @@ -8,7 +8,7 @@ if(NOT CMAKE_CXX_STANDARD) endif() if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") - add_compile_options(-Wall -Wextra -Wpedantic) + add_compile_options(-Wall -Wextra -Wpedantic -Werror=unused-but-set-variable -Werror=return-type -Werror=shadow -Werror=format) endif() set(THIS_PACKAGE_INCLUDE_DEPENDS diff --git a/steering_controllers_library/CMakeLists.txt b/steering_controllers_library/CMakeLists.txt index 63de42cf69..88f24d304c 100644 --- a/steering_controllers_library/CMakeLists.txt +++ b/steering_controllers_library/CMakeLists.txt @@ -2,7 +2,8 @@ cmake_minimum_required(VERSION 3.16) project(steering_controllers_library LANGUAGES CXX) if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") - add_compile_options(-Wall -Wextra -Wpedantic -Wconversion) + add_compile_options(-Wall -Wextra -Wpedantic -Werror=conversion -Werror=unused-but-set-variable + -Werror=return-type -Werror=shadow -Werror=format) endif() # find dependencies diff --git a/tricycle_controller/CMakeLists.txt b/tricycle_controller/CMakeLists.txt index 291f08ad9f..4f6d064dc8 100644 --- a/tricycle_controller/CMakeLists.txt +++ b/tricycle_controller/CMakeLists.txt @@ -2,7 +2,8 @@ cmake_minimum_required(VERSION 3.16) project(tricycle_controller LANGUAGES CXX) if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") - add_compile_options(-Wall -Wextra -Wpedantic -Wconversion) + add_compile_options(-Wall -Wextra -Wpedantic -Werror=conversion -Werror=unused-but-set-variable + -Werror=return-type -Werror=shadow -Werror=format) endif() set(THIS_PACKAGE_INCLUDE_DEPENDS diff --git a/tricycle_steering_controller/CMakeLists.txt b/tricycle_steering_controller/CMakeLists.txt index 4c56d68185..02c9453ace 100644 --- a/tricycle_steering_controller/CMakeLists.txt +++ b/tricycle_steering_controller/CMakeLists.txt @@ -2,7 +2,8 @@ cmake_minimum_required(VERSION 3.16) project(tricycle_steering_controller LANGUAGES CXX) if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") - add_compile_options(-Wall -Wextra -Wpedantic -Wconversion) + add_compile_options(-Wall -Wextra -Wpedantic -Werror=conversion -Werror=unused-but-set-variable + -Werror=return-type -Werror=shadow -Werror=format) endif() # find dependencies diff --git a/velocity_controllers/CMakeLists.txt b/velocity_controllers/CMakeLists.txt index 3642ae1cb9..a39cd162fd 100644 --- a/velocity_controllers/CMakeLists.txt +++ b/velocity_controllers/CMakeLists.txt @@ -2,7 +2,8 @@ cmake_minimum_required(VERSION 3.16) project(velocity_controllers LANGUAGES CXX) if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)") - add_compile_options(-Wall -Wextra -Wpedantic -Wconversion) + add_compile_options(-Wall -Wextra -Wpedantic -Werror=conversion -Werror=unused-but-set-variable + -Werror=return-type -Werror=shadow -Werror=format) endif() set(THIS_PACKAGE_INCLUDE_DEPENDS From 7d0e1d1a38d902146bd3771a82f39ebaed51cb16 Mon Sep 17 00:00:00 2001 From: maurice Date: Sun, 7 Jan 2024 09:03:14 +0100 Subject: [PATCH 182/238] Update deprecated topic name (#964) --- joint_trajectory_controller/doc/userdoc.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/joint_trajectory_controller/doc/userdoc.rst b/joint_trajectory_controller/doc/userdoc.rst index 6fe2146802..af495ad14d 100644 --- a/joint_trajectory_controller/doc/userdoc.rst +++ b/joint_trajectory_controller/doc/userdoc.rst @@ -168,7 +168,7 @@ Subscriber [#f1]_ The topic interface is a fire-and-forget alternative. Use this interface if you don't care about execution monitoring. The goal tolerance specification is not used in this case, as there is no mechanism to notify the sender about tolerance violations. If state tolerances are violated, the trajectory is aborted and the current position is held. -Note that although some degree of monitoring is available through the ``~/query_state`` service and ``~/state`` topic it is much more cumbersome to realize than with the action interface. +Note that although some degree of monitoring is available through the ``~/query_state`` service and ``~/controller_state`` topic it is much more cumbersome to realize than with the action interface. Publishers From 30eb4b07d630f4b4b5be6080a6ae9469bdab2f18 Mon Sep 17 00:00:00 2001 From: Abishalini Sivaraman Date: Sun, 7 Jan 2024 01:04:35 -0700 Subject: [PATCH 183/238] Remove robot description param from admittance YAML (#963) --- .../src/admittance_controller_parameters.yaml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/admittance_controller/src/admittance_controller_parameters.yaml b/admittance_controller/src/admittance_controller_parameters.yaml index ee1efa67ab..315d0e70d2 100644 --- a/admittance_controller/src/admittance_controller_parameters.yaml +++ b/admittance_controller/src/admittance_controller_parameters.yaml @@ -147,11 +147,6 @@ admittance_controller: } # general settings - robot_description: { - type: string, - description: "Contains robot description in URDF format. The description is used for forward and inverse kinematics.", - read_only: true - } enable_parameter_update_without_reactivation: { type: bool, default_value: true, From d3c09c2b25a34c63f2f4a3e2426d7f394dac51c0 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Mon, 8 Jan 2024 10:21:56 +0000 Subject: [PATCH 184/238] Update changelogs --- ackermann_steering_controller/CHANGELOG.rst | 5 +++++ admittance_controller/CHANGELOG.rst | 6 ++++++ bicycle_steering_controller/CHANGELOG.rst | 5 +++++ diff_drive_controller/CHANGELOG.rst | 5 +++++ effort_controllers/CHANGELOG.rst | 5 +++++ force_torque_sensor_broadcaster/CHANGELOG.rst | 5 +++++ forward_command_controller/CHANGELOG.rst | 5 +++++ gripper_controllers/CHANGELOG.rst | 5 +++++ imu_sensor_broadcaster/CHANGELOG.rst | 5 +++++ joint_state_broadcaster/CHANGELOG.rst | 5 +++++ joint_trajectory_controller/CHANGELOG.rst | 9 +++++++++ pid_controller/CHANGELOG.rst | 5 +++++ position_controllers/CHANGELOG.rst | 5 +++++ range_sensor_broadcaster/CHANGELOG.rst | 5 +++++ ros2_controllers/CHANGELOG.rst | 3 +++ ros2_controllers_test_nodes/CHANGELOG.rst | 3 +++ rqt_joint_trajectory_controller/CHANGELOG.rst | 5 +++++ steering_controllers_library/CHANGELOG.rst | 7 +++++++ tricycle_controller/CHANGELOG.rst | 5 +++++ tricycle_steering_controller/CHANGELOG.rst | 5 +++++ velocity_controllers/CHANGELOG.rst | 5 +++++ 21 files changed, 108 insertions(+) diff --git a/ackermann_steering_controller/CHANGELOG.rst b/ackermann_steering_controller/CHANGELOG.rst index 975ecbf5a6..5496639fdb 100644 --- a/ackermann_steering_controller/CHANGELOG.rst +++ b/ackermann_steering_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package ackermann_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add few warning flags to error (`#961 `_) +* Contributors: Sai Kishor Kothakota + 4.2.0 (2023-12-12) ------------------ diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index 86ba49d92a..8c824a835a 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Remove robot description param from admittance YAML (`#963 `_) +* Add few warning flags to error (`#961 `_) +* Contributors: Abishalini Sivaraman, Sai Kishor Kothakota + 4.2.0 (2023-12-12) ------------------ diff --git a/bicycle_steering_controller/CHANGELOG.rst b/bicycle_steering_controller/CHANGELOG.rst index d7259fbc75..3bb6a9312c 100644 --- a/bicycle_steering_controller/CHANGELOG.rst +++ b/bicycle_steering_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package bicycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add few warning flags to error (`#961 `_) +* Contributors: Sai Kishor Kothakota + 4.2.0 (2023-12-12) ------------------ diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index eb40ec1db1..cb11b468cc 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add few warning flags to error (`#961 `_) +* Contributors: Sai Kishor Kothakota + 4.2.0 (2023-12-12) ------------------ diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index 6cd3b74a95..3e40d34d4c 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add few warning flags to error (`#961 `_) +* Contributors: Sai Kishor Kothakota + 4.2.0 (2023-12-12) ------------------ diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index a808f82c70..32702c02e5 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add few warning flags to error (`#961 `_) +* Contributors: Sai Kishor Kothakota + 4.2.0 (2023-12-12) ------------------ diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index 45e5a8081c..a1c9495f83 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add few warning flags to error (`#961 `_) +* Contributors: Sai Kishor Kothakota + 4.2.0 (2023-12-12) ------------------ diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index ff2046a41b..4382714914 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add few warning flags to error (`#961 `_) +* Contributors: Sai Kishor Kothakota + 4.2.0 (2023-12-12) ------------------ diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index e8be87d1f3..d816ae694a 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add few warning flags to error (`#961 `_) +* Contributors: Sai Kishor Kothakota + 4.2.0 (2023-12-12) ------------------ diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index 4e92131965..42c06fe201 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add few warning flags to error (`#961 `_) +* Contributors: Sai Kishor Kothakota + 4.2.0 (2023-12-12) ------------------ diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index 1b3559af58..c879d40a83 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,15 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Update deprecated topic name (`#964 `_) +* Add few warning flags to error (`#961 `_) +* [JTC] Cleanup includes (`#943 `_) +* Add rqt_JTC to docs (`#950 `_) +* [JTC] Add console output for tolerance checks (`#932 `_) +* Contributors: Christoph Fröhlich, Sai Kishor Kothakota, maurice + 4.2.0 (2023-12-12) ------------------ * Cleanup package.xml und clarify tests of JTC. (`#889 `_) diff --git a/pid_controller/CHANGELOG.rst b/pid_controller/CHANGELOG.rst index 5924bc6d94..11c341313c 100644 --- a/pid_controller/CHANGELOG.rst +++ b/pid_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package pid_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add few warning flags to error (`#961 `_) +* Contributors: Sai Kishor Kothakota + 4.2.0 (2023-12-12) ------------------ * 🚀 Add PID controller 🎉 (`#434 `_) diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index 2e1e38fa43..7b5c0683d6 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add few warning flags to error (`#961 `_) +* Contributors: Sai Kishor Kothakota + 4.2.0 (2023-12-12) ------------------ diff --git a/range_sensor_broadcaster/CHANGELOG.rst b/range_sensor_broadcaster/CHANGELOG.rst index c92b4867b5..aff21d74d3 100644 --- a/range_sensor_broadcaster/CHANGELOG.rst +++ b/range_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package range_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add few warning flags to error (`#961 `_) +* Contributors: Sai Kishor Kothakota + 4.2.0 (2023-12-12) ------------------ diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index 5839d43b68..3cda43afb5 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.2.0 (2023-12-12) ------------------ * 🚀 Add PID controller 🎉 (`#434 `_) diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index d7c37b2fee..770267b060 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.2.0 (2023-12-12) ------------------ diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index 67d9eb85df..c3252754bd 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add rqt_JTC to docs (`#950 `_) +* Contributors: Christoph Fröhlich + 4.2.0 (2023-12-12) ------------------ * Fix rqt jtc bugs for continuous joints and other minor bugs (`#890 `_) diff --git a/steering_controllers_library/CHANGELOG.rst b/steering_controllers_library/CHANGELOG.rst index fa8cd4ee2f..c6e0fd1864 100644 --- a/steering_controllers_library/CHANGELOG.rst +++ b/steering_controllers_library/CHANGELOG.rst @@ -2,6 +2,13 @@ Changelog for package steering_controllers_library ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add few warning flags to error (`#961 `_) +* Fix ackermann steering odometry (`#921 `_) +* Changing default int values to double in steering controller's yaml file (`#927 `_) +* Contributors: Franz Rammerstorfer, Reza Kermani, Sai Kishor Kothakota + 4.2.0 (2023-12-12) ------------------ diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index d7424ca31a..74ca0d6d84 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add few warning flags to error (`#961 `_) +* Contributors: Sai Kishor Kothakota + 4.2.0 (2023-12-12) ------------------ diff --git a/tricycle_steering_controller/CHANGELOG.rst b/tricycle_steering_controller/CHANGELOG.rst index 3d04f2ba8d..59f279a080 100644 --- a/tricycle_steering_controller/CHANGELOG.rst +++ b/tricycle_steering_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package tricycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add few warning flags to error (`#961 `_) +* Contributors: Sai Kishor Kothakota + 4.2.0 (2023-12-12) ------------------ diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index 98d6523639..a9496caa75 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add few warning flags to error (`#961 `_) +* Contributors: Sai Kishor Kothakota + 4.2.0 (2023-12-12) ------------------ From bdb7ad5bdcdfec0cd0b17bb05aaf3cac8229e7b5 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Mon, 8 Jan 2024 10:22:27 +0000 Subject: [PATCH 185/238] 4.3.0 --- ackermann_steering_controller/CHANGELOG.rst | 4 ++-- ackermann_steering_controller/package.xml | 2 +- admittance_controller/CHANGELOG.rst | 4 ++-- admittance_controller/package.xml | 2 +- bicycle_steering_controller/CHANGELOG.rst | 4 ++-- bicycle_steering_controller/package.xml | 2 +- diff_drive_controller/CHANGELOG.rst | 4 ++-- diff_drive_controller/package.xml | 2 +- effort_controllers/CHANGELOG.rst | 4 ++-- effort_controllers/package.xml | 2 +- force_torque_sensor_broadcaster/CHANGELOG.rst | 4 ++-- force_torque_sensor_broadcaster/package.xml | 2 +- forward_command_controller/CHANGELOG.rst | 4 ++-- forward_command_controller/package.xml | 2 +- gripper_controllers/CHANGELOG.rst | 4 ++-- gripper_controllers/package.xml | 2 +- imu_sensor_broadcaster/CHANGELOG.rst | 4 ++-- imu_sensor_broadcaster/package.xml | 2 +- joint_state_broadcaster/CHANGELOG.rst | 4 ++-- joint_state_broadcaster/package.xml | 2 +- joint_trajectory_controller/CHANGELOG.rst | 4 ++-- joint_trajectory_controller/package.xml | 2 +- pid_controller/CHANGELOG.rst | 4 ++-- pid_controller/package.xml | 2 +- position_controllers/CHANGELOG.rst | 4 ++-- position_controllers/package.xml | 2 +- range_sensor_broadcaster/CHANGELOG.rst | 4 ++-- range_sensor_broadcaster/package.xml | 2 +- ros2_controllers/CHANGELOG.rst | 4 ++-- ros2_controllers/package.xml | 2 +- ros2_controllers_test_nodes/CHANGELOG.rst | 4 ++-- ros2_controllers_test_nodes/package.xml | 2 +- ros2_controllers_test_nodes/setup.py | 2 +- rqt_joint_trajectory_controller/CHANGELOG.rst | 4 ++-- rqt_joint_trajectory_controller/package.xml | 2 +- rqt_joint_trajectory_controller/setup.py | 2 +- steering_controllers_library/CHANGELOG.rst | 4 ++-- steering_controllers_library/package.xml | 2 +- tricycle_controller/CHANGELOG.rst | 4 ++-- tricycle_controller/package.xml | 2 +- tricycle_steering_controller/CHANGELOG.rst | 4 ++-- tricycle_steering_controller/package.xml | 2 +- velocity_controllers/CHANGELOG.rst | 4 ++-- velocity_controllers/package.xml | 2 +- 44 files changed, 65 insertions(+), 65 deletions(-) diff --git a/ackermann_steering_controller/CHANGELOG.rst b/ackermann_steering_controller/CHANGELOG.rst index 5496639fdb..6d78ee3116 100644 --- a/ackermann_steering_controller/CHANGELOG.rst +++ b/ackermann_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ackermann_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.3.0 (2024-01-08) +------------------ * Add few warning flags to error (`#961 `_) * Contributors: Sai Kishor Kothakota diff --git a/ackermann_steering_controller/package.xml b/ackermann_steering_controller/package.xml index 20bfca8003..e8f07df68f 100644 --- a/ackermann_steering_controller/package.xml +++ b/ackermann_steering_controller/package.xml @@ -2,7 +2,7 @@ ackermann_steering_controller - 4.2.0 + 4.3.0 Steering controller for Ackermann kinematics. Rear fixed wheels are powering the vehicle and front wheels are steering it. Apache License 2.0 Bence Magyar diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index 8c824a835a..2de3ab97a7 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.3.0 (2024-01-08) +------------------ * Remove robot description param from admittance YAML (`#963 `_) * Add few warning flags to error (`#961 `_) * Contributors: Abishalini Sivaraman, Sai Kishor Kothakota diff --git a/admittance_controller/package.xml b/admittance_controller/package.xml index 478b10bb55..0f28ce3b50 100644 --- a/admittance_controller/package.xml +++ b/admittance_controller/package.xml @@ -2,7 +2,7 @@ admittance_controller - 4.2.0 + 4.3.0 Implementation of admittance controllers for different input and output interface. Denis Štogl Bence Magyar diff --git a/bicycle_steering_controller/CHANGELOG.rst b/bicycle_steering_controller/CHANGELOG.rst index 3bb6a9312c..44f32ac497 100644 --- a/bicycle_steering_controller/CHANGELOG.rst +++ b/bicycle_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package bicycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.3.0 (2024-01-08) +------------------ * Add few warning flags to error (`#961 `_) * Contributors: Sai Kishor Kothakota diff --git a/bicycle_steering_controller/package.xml b/bicycle_steering_controller/package.xml index 2573605890..45e3a54bc4 100644 --- a/bicycle_steering_controller/package.xml +++ b/bicycle_steering_controller/package.xml @@ -2,7 +2,7 @@ bicycle_steering_controller - 4.2.0 + 4.3.0 Steering controller with bicycle kinematics. Rear fixed wheel is powering the vehicle and front wheel is steering. Apache License 2.0 Bence Magyar diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index cb11b468cc..e247d39246 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.3.0 (2024-01-08) +------------------ * Add few warning flags to error (`#961 `_) * Contributors: Sai Kishor Kothakota diff --git a/diff_drive_controller/package.xml b/diff_drive_controller/package.xml index 5cacf41dad..af59483e24 100644 --- a/diff_drive_controller/package.xml +++ b/diff_drive_controller/package.xml @@ -1,7 +1,7 @@ diff_drive_controller - 4.2.0 + 4.3.0 Controller for a differential drive mobile base. Bence Magyar Jordan Palacios diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index 3e40d34d4c..1a3db666b3 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.3.0 (2024-01-08) +------------------ * Add few warning flags to error (`#961 `_) * Contributors: Sai Kishor Kothakota diff --git a/effort_controllers/package.xml b/effort_controllers/package.xml index e42456c828..5be3c321e6 100644 --- a/effort_controllers/package.xml +++ b/effort_controllers/package.xml @@ -1,7 +1,7 @@ effort_controllers - 4.2.0 + 4.3.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index 32702c02e5..943f493a83 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.3.0 (2024-01-08) +------------------ * Add few warning flags to error (`#961 `_) * Contributors: Sai Kishor Kothakota diff --git a/force_torque_sensor_broadcaster/package.xml b/force_torque_sensor_broadcaster/package.xml index 154e597c5f..1d9306c69b 100644 --- a/force_torque_sensor_broadcaster/package.xml +++ b/force_torque_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ force_torque_sensor_broadcaster - 4.2.0 + 4.3.0 Controller to publish state of force-torque sensors. Bence Magyar Denis Štogl diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index a1c9495f83..79f06844d1 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.3.0 (2024-01-08) +------------------ * Add few warning flags to error (`#961 `_) * Contributors: Sai Kishor Kothakota diff --git a/forward_command_controller/package.xml b/forward_command_controller/package.xml index 324ec1c5be..d410509a15 100644 --- a/forward_command_controller/package.xml +++ b/forward_command_controller/package.xml @@ -1,7 +1,7 @@ forward_command_controller - 4.2.0 + 4.3.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index 4382714914..fb07533cc8 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.3.0 (2024-01-08) +------------------ * Add few warning flags to error (`#961 `_) * Contributors: Sai Kishor Kothakota diff --git a/gripper_controllers/package.xml b/gripper_controllers/package.xml index ce981141a5..5e3cc15828 100644 --- a/gripper_controllers/package.xml +++ b/gripper_controllers/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> gripper_controllers - 4.2.0 + 4.3.0 The gripper_controllers package Bence Magyar diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index d816ae694a..08ddd07435 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.3.0 (2024-01-08) +------------------ * Add few warning flags to error (`#961 `_) * Contributors: Sai Kishor Kothakota diff --git a/imu_sensor_broadcaster/package.xml b/imu_sensor_broadcaster/package.xml index 48a26ead3f..56abba21b6 100644 --- a/imu_sensor_broadcaster/package.xml +++ b/imu_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ imu_sensor_broadcaster - 4.2.0 + 4.3.0 Controller to publish readings of IMU sensors. Bence Magyar Denis Štogl diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index 42c06fe201..d37f73736d 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.3.0 (2024-01-08) +------------------ * Add few warning flags to error (`#961 `_) * Contributors: Sai Kishor Kothakota diff --git a/joint_state_broadcaster/package.xml b/joint_state_broadcaster/package.xml index 300f8b2238..6dda848d42 100644 --- a/joint_state_broadcaster/package.xml +++ b/joint_state_broadcaster/package.xml @@ -1,7 +1,7 @@ joint_state_broadcaster - 4.2.0 + 4.3.0 Broadcaster to publish joint state Bence Magyar Denis Stogl diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index c879d40a83..81f33ebe66 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.3.0 (2024-01-08) +------------------ * Update deprecated topic name (`#964 `_) * Add few warning flags to error (`#961 `_) * [JTC] Cleanup includes (`#943 `_) diff --git a/joint_trajectory_controller/package.xml b/joint_trajectory_controller/package.xml index 1d0929b8b5..91b7a12c2d 100644 --- a/joint_trajectory_controller/package.xml +++ b/joint_trajectory_controller/package.xml @@ -1,7 +1,7 @@ joint_trajectory_controller - 4.2.0 + 4.3.0 Controller for executing joint-space trajectories on a group of joints Bence Magyar Dr. Denis Štogl diff --git a/pid_controller/CHANGELOG.rst b/pid_controller/CHANGELOG.rst index 11c341313c..2fe4dff9df 100644 --- a/pid_controller/CHANGELOG.rst +++ b/pid_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package pid_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.3.0 (2024-01-08) +------------------ * Add few warning flags to error (`#961 `_) * Contributors: Sai Kishor Kothakota diff --git a/pid_controller/package.xml b/pid_controller/package.xml index 7caa3f7856..2156dc3418 100644 --- a/pid_controller/package.xml +++ b/pid_controller/package.xml @@ -2,7 +2,7 @@ pid_controller - 4.2.0 + 4.3.0 Controller based on PID implememenation from control_toolbox package. Bence Magyar Denis Štogl diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index 7b5c0683d6..4fd9bf4f89 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.3.0 (2024-01-08) +------------------ * Add few warning flags to error (`#961 `_) * Contributors: Sai Kishor Kothakota diff --git a/position_controllers/package.xml b/position_controllers/package.xml index 8ed752c536..77ae11fa7b 100644 --- a/position_controllers/package.xml +++ b/position_controllers/package.xml @@ -1,7 +1,7 @@ position_controllers - 4.2.0 + 4.3.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/range_sensor_broadcaster/CHANGELOG.rst b/range_sensor_broadcaster/CHANGELOG.rst index aff21d74d3..b52bcc5a4c 100644 --- a/range_sensor_broadcaster/CHANGELOG.rst +++ b/range_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package range_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.3.0 (2024-01-08) +------------------ * Add few warning flags to error (`#961 `_) * Contributors: Sai Kishor Kothakota diff --git a/range_sensor_broadcaster/package.xml b/range_sensor_broadcaster/package.xml index 08e8fd9506..8dca5951a2 100644 --- a/range_sensor_broadcaster/package.xml +++ b/range_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ range_sensor_broadcaster - 4.2.0 + 4.3.0 Controller to publish readings of Range sensors. Bence Magyar Florent Chretien diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index 3cda43afb5..ac14d09a08 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.3.0 (2024-01-08) +------------------ 4.2.0 (2023-12-12) ------------------ diff --git a/ros2_controllers/package.xml b/ros2_controllers/package.xml index 793aea9140..4635d8f69a 100644 --- a/ros2_controllers/package.xml +++ b/ros2_controllers/package.xml @@ -1,7 +1,7 @@ ros2_controllers - 4.2.0 + 4.3.0 Metapackage for ROS2 controllers related packages Bence Magyar Jordan Palacios diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index 770267b060..df1ee3457e 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.3.0 (2024-01-08) +------------------ 4.2.0 (2023-12-12) ------------------ diff --git a/ros2_controllers_test_nodes/package.xml b/ros2_controllers_test_nodes/package.xml index 84ebaea6fa..9bd1172d0b 100644 --- a/ros2_controllers_test_nodes/package.xml +++ b/ros2_controllers_test_nodes/package.xml @@ -2,7 +2,7 @@ ros2_controllers_test_nodes - 4.2.0 + 4.3.0 Demo nodes for showing and testing functionalities of the ros2_control framework. Denis Štogl diff --git a/ros2_controllers_test_nodes/setup.py b/ros2_controllers_test_nodes/setup.py index b9aa443081..25ea77ddc6 100644 --- a/ros2_controllers_test_nodes/setup.py +++ b/ros2_controllers_test_nodes/setup.py @@ -20,7 +20,7 @@ setup( name=package_name, - version="4.2.0", + version="4.3.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index c3252754bd..5eab8a8a93 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.3.0 (2024-01-08) +------------------ * Add rqt_JTC to docs (`#950 `_) * Contributors: Christoph Fröhlich diff --git a/rqt_joint_trajectory_controller/package.xml b/rqt_joint_trajectory_controller/package.xml index 4e7c622798..195f5fb3a9 100644 --- a/rqt_joint_trajectory_controller/package.xml +++ b/rqt_joint_trajectory_controller/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> rqt_joint_trajectory_controller - 4.2.0 + 4.3.0 Graphical frontend for interacting with joint_trajectory_controller instances. Bence Magyar diff --git a/rqt_joint_trajectory_controller/setup.py b/rqt_joint_trajectory_controller/setup.py index 1e49983693..4b9a16dd3b 100644 --- a/rqt_joint_trajectory_controller/setup.py +++ b/rqt_joint_trajectory_controller/setup.py @@ -7,7 +7,7 @@ setup( name=package_name, - version="4.2.0", + version="4.3.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/steering_controllers_library/CHANGELOG.rst b/steering_controllers_library/CHANGELOG.rst index c6e0fd1864..668fb65a73 100644 --- a/steering_controllers_library/CHANGELOG.rst +++ b/steering_controllers_library/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package steering_controllers_library ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.3.0 (2024-01-08) +------------------ * Add few warning flags to error (`#961 `_) * Fix ackermann steering odometry (`#921 `_) * Changing default int values to double in steering controller's yaml file (`#927 `_) diff --git a/steering_controllers_library/package.xml b/steering_controllers_library/package.xml index 85398f1d90..6e22de993e 100644 --- a/steering_controllers_library/package.xml +++ b/steering_controllers_library/package.xml @@ -2,7 +2,7 @@ steering_controllers_library - 4.2.0 + 4.3.0 Package for steering robot configurations including odometry and interfaces. Apache License 2.0 Bence Magyar diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index 74ca0d6d84..bf386ddb4f 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.3.0 (2024-01-08) +------------------ * Add few warning flags to error (`#961 `_) * Contributors: Sai Kishor Kothakota diff --git a/tricycle_controller/package.xml b/tricycle_controller/package.xml index 4f131da79c..240badc7c5 100644 --- a/tricycle_controller/package.xml +++ b/tricycle_controller/package.xml @@ -2,7 +2,7 @@ tricycle_controller - 4.2.0 + 4.3.0 Controller for a tricycle drive mobile base Bence Magyar Tony Najjar diff --git a/tricycle_steering_controller/CHANGELOG.rst b/tricycle_steering_controller/CHANGELOG.rst index 59f279a080..8e2187d977 100644 --- a/tricycle_steering_controller/CHANGELOG.rst +++ b/tricycle_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package tricycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.3.0 (2024-01-08) +------------------ * Add few warning flags to error (`#961 `_) * Contributors: Sai Kishor Kothakota diff --git a/tricycle_steering_controller/package.xml b/tricycle_steering_controller/package.xml index f6eb3fff49..0ff0604886 100644 --- a/tricycle_steering_controller/package.xml +++ b/tricycle_steering_controller/package.xml @@ -2,7 +2,7 @@ tricycle_steering_controller - 4.2.0 + 4.3.0 Steering controller with tricycle kinematics. Rear fixed wheels are powering the vehicle and front wheel is steering. Apache License 2.0 Bence Magyar diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index a9496caa75..b1e807481d 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.3.0 (2024-01-08) +------------------ * Add few warning flags to error (`#961 `_) * Contributors: Sai Kishor Kothakota diff --git a/velocity_controllers/package.xml b/velocity_controllers/package.xml index 3d901585db..b57524bf21 100644 --- a/velocity_controllers/package.xml +++ b/velocity_controllers/package.xml @@ -1,7 +1,7 @@ velocity_controllers - 4.2.0 + 4.3.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios From 6e2736b0ed521e1b236dcf8ab2ede4ef565e97d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noel=20Jim=C3=A9nez=20Garc=C3=ADa?= Date: Thu, 11 Jan 2024 14:15:01 +0100 Subject: [PATCH 186/238] [JTC] Remove read_only from 'joints', 'state_interfaces' and 'command_interfaces' parameters (#967) --- .../src/joint_trajectory_controller_parameters.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml b/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml index 4981489d36..a6358d1015 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml +++ b/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml @@ -3,7 +3,6 @@ joint_trajectory_controller: type: string_array, default_value: [], description: "Names of joints used by the controller", - read_only: true, validation: { unique<>: null, } @@ -21,7 +20,6 @@ joint_trajectory_controller: type: string_array, default_value: [], description: "Names of command interfaces to claim", - read_only: true, validation: { unique<>: null, subset_of<>: [["position", "velocity", "acceleration", "effort",]], @@ -32,7 +30,6 @@ joint_trajectory_controller: type: string_array, default_value: [], description: "Names of state interfaces to claim", - read_only: true, validation: { unique<>: null, subset_of<>: [["position", "velocity", "acceleration",]], From fdd6142c5ff9eeea2788ffa5529419a834c960b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Thu, 11 Jan 2024 15:01:12 +0100 Subject: [PATCH 187/238] [JTC] Cancel goal in on_deactivate (#962) --- .../src/joint_trajectory_controller.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/joint_trajectory_controller/src/joint_trajectory_controller.cpp b/joint_trajectory_controller/src/joint_trajectory_controller.cpp index b1cca67547..4a2a801e51 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller.cpp +++ b/joint_trajectory_controller/src/joint_trajectory_controller.cpp @@ -975,6 +975,17 @@ controller_interface::CallbackReturn JointTrajectoryController::on_activate( controller_interface::CallbackReturn JointTrajectoryController::on_deactivate( const rclcpp_lifecycle::State &) { + const auto active_goal = *rt_active_goal_.readFromNonRT(); + if (active_goal) + { + rt_has_pending_goal_.writeFromNonRT(false); + auto action_res = std::make_shared(); + action_res->set__error_code(FollowJTrajAction::Result::INVALID_GOAL); + action_res->set__error_string("Current goal cancelled during deactivate transition."); + active_goal->setCanceled(action_res); + rt_active_goal_.writeFromNonRT(RealtimeGoalHandlePtr()); + } + for (size_t index = 0; index < dof_; ++index) { if (has_position_command_interface_) @@ -1445,7 +1456,6 @@ void JointTrajectoryController::preempt_active_goal() const auto active_goal = *rt_active_goal_.readFromNonRT(); if (active_goal) { - add_new_trajectory_msg(set_hold_position()); auto action_res = std::make_shared(); action_res->set__error_code(FollowJTrajAction::Result::INVALID_GOAL); action_res->set__error_string("Current goal cancelled due to new incoming action."); From 1b75446015f691b8c024aad297849c39a6245f4a Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Thu, 11 Jan 2024 15:21:09 +0000 Subject: [PATCH 188/238] Update changelogs --- ackermann_steering_controller/CHANGELOG.rst | 3 +++ admittance_controller/CHANGELOG.rst | 3 +++ bicycle_steering_controller/CHANGELOG.rst | 3 +++ diff_drive_controller/CHANGELOG.rst | 3 +++ effort_controllers/CHANGELOG.rst | 3 +++ force_torque_sensor_broadcaster/CHANGELOG.rst | 3 +++ forward_command_controller/CHANGELOG.rst | 3 +++ gripper_controllers/CHANGELOG.rst | 3 +++ imu_sensor_broadcaster/CHANGELOG.rst | 3 +++ joint_state_broadcaster/CHANGELOG.rst | 3 +++ joint_trajectory_controller/CHANGELOG.rst | 6 ++++++ pid_controller/CHANGELOG.rst | 3 +++ position_controllers/CHANGELOG.rst | 3 +++ range_sensor_broadcaster/CHANGELOG.rst | 3 +++ ros2_controllers/CHANGELOG.rst | 3 +++ ros2_controllers_test_nodes/CHANGELOG.rst | 3 +++ rqt_joint_trajectory_controller/CHANGELOG.rst | 3 +++ steering_controllers_library/CHANGELOG.rst | 3 +++ tricycle_controller/CHANGELOG.rst | 3 +++ tricycle_steering_controller/CHANGELOG.rst | 3 +++ velocity_controllers/CHANGELOG.rst | 3 +++ 21 files changed, 66 insertions(+) diff --git a/ackermann_steering_controller/CHANGELOG.rst b/ackermann_steering_controller/CHANGELOG.rst index 6d78ee3116..7c508abca5 100644 --- a/ackermann_steering_controller/CHANGELOG.rst +++ b/ackermann_steering_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ackermann_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.3.0 (2024-01-08) ------------------ * Add few warning flags to error (`#961 `_) diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index 2de3ab97a7..2af98eecd2 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.3.0 (2024-01-08) ------------------ * Remove robot description param from admittance YAML (`#963 `_) diff --git a/bicycle_steering_controller/CHANGELOG.rst b/bicycle_steering_controller/CHANGELOG.rst index 44f32ac497..e5ec7478a7 100644 --- a/bicycle_steering_controller/CHANGELOG.rst +++ b/bicycle_steering_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package bicycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.3.0 (2024-01-08) ------------------ * Add few warning flags to error (`#961 `_) diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index e247d39246..f4c725052e 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.3.0 (2024-01-08) ------------------ * Add few warning flags to error (`#961 `_) diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index 1a3db666b3..c054d6c880 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.3.0 (2024-01-08) ------------------ * Add few warning flags to error (`#961 `_) diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index 943f493a83..2db9d57256 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.3.0 (2024-01-08) ------------------ * Add few warning flags to error (`#961 `_) diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index 79f06844d1..4d325e02eb 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.3.0 (2024-01-08) ------------------ * Add few warning flags to error (`#961 `_) diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index fb07533cc8..8837059171 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.3.0 (2024-01-08) ------------------ * Add few warning flags to error (`#961 `_) diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index 08ddd07435..b6c744a204 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.3.0 (2024-01-08) ------------------ * Add few warning flags to error (`#961 `_) diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index d37f73736d..1a8fc07a84 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.3.0 (2024-01-08) ------------------ * Add few warning flags to error (`#961 `_) diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index 81f33ebe66..761470b7d3 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Cancel goal in on_deactivate (`#962 `_) +* Remove read_only from 'joints', 'state_interfaces' and 'command_interfaces' parameters (`#967 `_) +* Contributors: Christoph Fröhlich, Noel Jiménez García + 4.3.0 (2024-01-08) ------------------ * Update deprecated topic name (`#964 `_) diff --git a/pid_controller/CHANGELOG.rst b/pid_controller/CHANGELOG.rst index 2fe4dff9df..91f8e9c343 100644 --- a/pid_controller/CHANGELOG.rst +++ b/pid_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package pid_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.3.0 (2024-01-08) ------------------ * Add few warning flags to error (`#961 `_) diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index 4fd9bf4f89..c6bf03fd3a 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.3.0 (2024-01-08) ------------------ * Add few warning flags to error (`#961 `_) diff --git a/range_sensor_broadcaster/CHANGELOG.rst b/range_sensor_broadcaster/CHANGELOG.rst index b52bcc5a4c..e91f8b65f7 100644 --- a/range_sensor_broadcaster/CHANGELOG.rst +++ b/range_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package range_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.3.0 (2024-01-08) ------------------ * Add few warning flags to error (`#961 `_) diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index ac14d09a08..b69c108fc6 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.3.0 (2024-01-08) ------------------ diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index df1ee3457e..56451c00f0 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.3.0 (2024-01-08) ------------------ diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index 5eab8a8a93..5ff06b3bff 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.3.0 (2024-01-08) ------------------ * Add rqt_JTC to docs (`#950 `_) diff --git a/steering_controllers_library/CHANGELOG.rst b/steering_controllers_library/CHANGELOG.rst index 668fb65a73..de036d106a 100644 --- a/steering_controllers_library/CHANGELOG.rst +++ b/steering_controllers_library/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package steering_controllers_library ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.3.0 (2024-01-08) ------------------ * Add few warning flags to error (`#961 `_) diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index bf386ddb4f..43f672c3c6 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.3.0 (2024-01-08) ------------------ * Add few warning flags to error (`#961 `_) diff --git a/tricycle_steering_controller/CHANGELOG.rst b/tricycle_steering_controller/CHANGELOG.rst index 8e2187d977..a4dc4c1445 100644 --- a/tricycle_steering_controller/CHANGELOG.rst +++ b/tricycle_steering_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package tricycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.3.0 (2024-01-08) ------------------ * Add few warning flags to error (`#961 `_) diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index b1e807481d..c3d0ffe8d3 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.3.0 (2024-01-08) ------------------ * Add few warning flags to error (`#961 `_) From 6623cdd2b1078cf6b99ea6827e4c6b68dd39a903 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Thu, 11 Jan 2024 15:21:41 +0000 Subject: [PATCH 189/238] 4.4.0 --- ackermann_steering_controller/CHANGELOG.rst | 4 ++-- ackermann_steering_controller/package.xml | 2 +- admittance_controller/CHANGELOG.rst | 4 ++-- admittance_controller/package.xml | 2 +- bicycle_steering_controller/CHANGELOG.rst | 4 ++-- bicycle_steering_controller/package.xml | 2 +- diff_drive_controller/CHANGELOG.rst | 4 ++-- diff_drive_controller/package.xml | 2 +- effort_controllers/CHANGELOG.rst | 4 ++-- effort_controllers/package.xml | 2 +- force_torque_sensor_broadcaster/CHANGELOG.rst | 4 ++-- force_torque_sensor_broadcaster/package.xml | 2 +- forward_command_controller/CHANGELOG.rst | 4 ++-- forward_command_controller/package.xml | 2 +- gripper_controllers/CHANGELOG.rst | 4 ++-- gripper_controllers/package.xml | 2 +- imu_sensor_broadcaster/CHANGELOG.rst | 4 ++-- imu_sensor_broadcaster/package.xml | 2 +- joint_state_broadcaster/CHANGELOG.rst | 4 ++-- joint_state_broadcaster/package.xml | 2 +- joint_trajectory_controller/CHANGELOG.rst | 4 ++-- joint_trajectory_controller/package.xml | 2 +- pid_controller/CHANGELOG.rst | 4 ++-- pid_controller/package.xml | 2 +- position_controllers/CHANGELOG.rst | 4 ++-- position_controllers/package.xml | 2 +- range_sensor_broadcaster/CHANGELOG.rst | 4 ++-- range_sensor_broadcaster/package.xml | 2 +- ros2_controllers/CHANGELOG.rst | 4 ++-- ros2_controllers/package.xml | 2 +- ros2_controllers_test_nodes/CHANGELOG.rst | 4 ++-- ros2_controllers_test_nodes/package.xml | 2 +- ros2_controllers_test_nodes/setup.py | 2 +- rqt_joint_trajectory_controller/CHANGELOG.rst | 4 ++-- rqt_joint_trajectory_controller/package.xml | 2 +- rqt_joint_trajectory_controller/setup.py | 2 +- steering_controllers_library/CHANGELOG.rst | 4 ++-- steering_controllers_library/package.xml | 2 +- tricycle_controller/CHANGELOG.rst | 4 ++-- tricycle_controller/package.xml | 2 +- tricycle_steering_controller/CHANGELOG.rst | 4 ++-- tricycle_steering_controller/package.xml | 2 +- velocity_controllers/CHANGELOG.rst | 4 ++-- velocity_controllers/package.xml | 2 +- 44 files changed, 65 insertions(+), 65 deletions(-) diff --git a/ackermann_steering_controller/CHANGELOG.rst b/ackermann_steering_controller/CHANGELOG.rst index 7c508abca5..a314802327 100644 --- a/ackermann_steering_controller/CHANGELOG.rst +++ b/ackermann_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ackermann_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.4.0 (2024-01-11) +------------------ 4.3.0 (2024-01-08) ------------------ diff --git a/ackermann_steering_controller/package.xml b/ackermann_steering_controller/package.xml index e8f07df68f..6c318219b2 100644 --- a/ackermann_steering_controller/package.xml +++ b/ackermann_steering_controller/package.xml @@ -2,7 +2,7 @@ ackermann_steering_controller - 4.3.0 + 4.4.0 Steering controller for Ackermann kinematics. Rear fixed wheels are powering the vehicle and front wheels are steering it. Apache License 2.0 Bence Magyar diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index 2af98eecd2..826a7aa6be 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.4.0 (2024-01-11) +------------------ 4.3.0 (2024-01-08) ------------------ diff --git a/admittance_controller/package.xml b/admittance_controller/package.xml index 0f28ce3b50..fd7cf32401 100644 --- a/admittance_controller/package.xml +++ b/admittance_controller/package.xml @@ -2,7 +2,7 @@ admittance_controller - 4.3.0 + 4.4.0 Implementation of admittance controllers for different input and output interface. Denis Štogl Bence Magyar diff --git a/bicycle_steering_controller/CHANGELOG.rst b/bicycle_steering_controller/CHANGELOG.rst index e5ec7478a7..a1f79c922b 100644 --- a/bicycle_steering_controller/CHANGELOG.rst +++ b/bicycle_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package bicycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.4.0 (2024-01-11) +------------------ 4.3.0 (2024-01-08) ------------------ diff --git a/bicycle_steering_controller/package.xml b/bicycle_steering_controller/package.xml index 45e3a54bc4..2082124de6 100644 --- a/bicycle_steering_controller/package.xml +++ b/bicycle_steering_controller/package.xml @@ -2,7 +2,7 @@ bicycle_steering_controller - 4.3.0 + 4.4.0 Steering controller with bicycle kinematics. Rear fixed wheel is powering the vehicle and front wheel is steering. Apache License 2.0 Bence Magyar diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index f4c725052e..316cd9e52d 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.4.0 (2024-01-11) +------------------ 4.3.0 (2024-01-08) ------------------ diff --git a/diff_drive_controller/package.xml b/diff_drive_controller/package.xml index af59483e24..9f79dabea6 100644 --- a/diff_drive_controller/package.xml +++ b/diff_drive_controller/package.xml @@ -1,7 +1,7 @@ diff_drive_controller - 4.3.0 + 4.4.0 Controller for a differential drive mobile base. Bence Magyar Jordan Palacios diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index c054d6c880..54cdc18d69 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.4.0 (2024-01-11) +------------------ 4.3.0 (2024-01-08) ------------------ diff --git a/effort_controllers/package.xml b/effort_controllers/package.xml index 5be3c321e6..ee5504c672 100644 --- a/effort_controllers/package.xml +++ b/effort_controllers/package.xml @@ -1,7 +1,7 @@ effort_controllers - 4.3.0 + 4.4.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index 2db9d57256..58191c2f42 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.4.0 (2024-01-11) +------------------ 4.3.0 (2024-01-08) ------------------ diff --git a/force_torque_sensor_broadcaster/package.xml b/force_torque_sensor_broadcaster/package.xml index 1d9306c69b..be9fc21d16 100644 --- a/force_torque_sensor_broadcaster/package.xml +++ b/force_torque_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ force_torque_sensor_broadcaster - 4.3.0 + 4.4.0 Controller to publish state of force-torque sensors. Bence Magyar Denis Štogl diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index 4d325e02eb..e6f5e3d52f 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.4.0 (2024-01-11) +------------------ 4.3.0 (2024-01-08) ------------------ diff --git a/forward_command_controller/package.xml b/forward_command_controller/package.xml index d410509a15..c0827e9e20 100644 --- a/forward_command_controller/package.xml +++ b/forward_command_controller/package.xml @@ -1,7 +1,7 @@ forward_command_controller - 4.3.0 + 4.4.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index 8837059171..677d52f784 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.4.0 (2024-01-11) +------------------ 4.3.0 (2024-01-08) ------------------ diff --git a/gripper_controllers/package.xml b/gripper_controllers/package.xml index 5e3cc15828..9488804f1d 100644 --- a/gripper_controllers/package.xml +++ b/gripper_controllers/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> gripper_controllers - 4.3.0 + 4.4.0 The gripper_controllers package Bence Magyar diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index b6c744a204..821ef8b385 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.4.0 (2024-01-11) +------------------ 4.3.0 (2024-01-08) ------------------ diff --git a/imu_sensor_broadcaster/package.xml b/imu_sensor_broadcaster/package.xml index 56abba21b6..184f9f7dd7 100644 --- a/imu_sensor_broadcaster/package.xml +++ b/imu_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ imu_sensor_broadcaster - 4.3.0 + 4.4.0 Controller to publish readings of IMU sensors. Bence Magyar Denis Štogl diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index 1a8fc07a84..0650f4e762 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.4.0 (2024-01-11) +------------------ 4.3.0 (2024-01-08) ------------------ diff --git a/joint_state_broadcaster/package.xml b/joint_state_broadcaster/package.xml index 6dda848d42..70d0f7daca 100644 --- a/joint_state_broadcaster/package.xml +++ b/joint_state_broadcaster/package.xml @@ -1,7 +1,7 @@ joint_state_broadcaster - 4.3.0 + 4.4.0 Broadcaster to publish joint state Bence Magyar Denis Stogl diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index 761470b7d3..5eb851589c 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.4.0 (2024-01-11) +------------------ * Cancel goal in on_deactivate (`#962 `_) * Remove read_only from 'joints', 'state_interfaces' and 'command_interfaces' parameters (`#967 `_) * Contributors: Christoph Fröhlich, Noel Jiménez García diff --git a/joint_trajectory_controller/package.xml b/joint_trajectory_controller/package.xml index 91b7a12c2d..bc6e43a1d5 100644 --- a/joint_trajectory_controller/package.xml +++ b/joint_trajectory_controller/package.xml @@ -1,7 +1,7 @@ joint_trajectory_controller - 4.3.0 + 4.4.0 Controller for executing joint-space trajectories on a group of joints Bence Magyar Dr. Denis Štogl diff --git a/pid_controller/CHANGELOG.rst b/pid_controller/CHANGELOG.rst index 91f8e9c343..b492f15efa 100644 --- a/pid_controller/CHANGELOG.rst +++ b/pid_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package pid_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.4.0 (2024-01-11) +------------------ 4.3.0 (2024-01-08) ------------------ diff --git a/pid_controller/package.xml b/pid_controller/package.xml index 2156dc3418..dc7f9c13be 100644 --- a/pid_controller/package.xml +++ b/pid_controller/package.xml @@ -2,7 +2,7 @@ pid_controller - 4.3.0 + 4.4.0 Controller based on PID implememenation from control_toolbox package. Bence Magyar Denis Štogl diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index c6bf03fd3a..7c3392dae9 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.4.0 (2024-01-11) +------------------ 4.3.0 (2024-01-08) ------------------ diff --git a/position_controllers/package.xml b/position_controllers/package.xml index 77ae11fa7b..b714afc89f 100644 --- a/position_controllers/package.xml +++ b/position_controllers/package.xml @@ -1,7 +1,7 @@ position_controllers - 4.3.0 + 4.4.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/range_sensor_broadcaster/CHANGELOG.rst b/range_sensor_broadcaster/CHANGELOG.rst index e91f8b65f7..77a365009a 100644 --- a/range_sensor_broadcaster/CHANGELOG.rst +++ b/range_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package range_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.4.0 (2024-01-11) +------------------ 4.3.0 (2024-01-08) ------------------ diff --git a/range_sensor_broadcaster/package.xml b/range_sensor_broadcaster/package.xml index 8dca5951a2..d8213112da 100644 --- a/range_sensor_broadcaster/package.xml +++ b/range_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ range_sensor_broadcaster - 4.3.0 + 4.4.0 Controller to publish readings of Range sensors. Bence Magyar Florent Chretien diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index b69c108fc6..bdb3c388dd 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.4.0 (2024-01-11) +------------------ 4.3.0 (2024-01-08) ------------------ diff --git a/ros2_controllers/package.xml b/ros2_controllers/package.xml index 4635d8f69a..265adde781 100644 --- a/ros2_controllers/package.xml +++ b/ros2_controllers/package.xml @@ -1,7 +1,7 @@ ros2_controllers - 4.3.0 + 4.4.0 Metapackage for ROS2 controllers related packages Bence Magyar Jordan Palacios diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index 56451c00f0..eab2bcfcb3 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.4.0 (2024-01-11) +------------------ 4.3.0 (2024-01-08) ------------------ diff --git a/ros2_controllers_test_nodes/package.xml b/ros2_controllers_test_nodes/package.xml index 9bd1172d0b..f34838f5ff 100644 --- a/ros2_controllers_test_nodes/package.xml +++ b/ros2_controllers_test_nodes/package.xml @@ -2,7 +2,7 @@ ros2_controllers_test_nodes - 4.3.0 + 4.4.0 Demo nodes for showing and testing functionalities of the ros2_control framework. Denis Štogl diff --git a/ros2_controllers_test_nodes/setup.py b/ros2_controllers_test_nodes/setup.py index 25ea77ddc6..d9c72db506 100644 --- a/ros2_controllers_test_nodes/setup.py +++ b/ros2_controllers_test_nodes/setup.py @@ -20,7 +20,7 @@ setup( name=package_name, - version="4.3.0", + version="4.4.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index 5ff06b3bff..0558e15d49 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.4.0 (2024-01-11) +------------------ 4.3.0 (2024-01-08) ------------------ diff --git a/rqt_joint_trajectory_controller/package.xml b/rqt_joint_trajectory_controller/package.xml index 195f5fb3a9..29db146abc 100644 --- a/rqt_joint_trajectory_controller/package.xml +++ b/rqt_joint_trajectory_controller/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> rqt_joint_trajectory_controller - 4.3.0 + 4.4.0 Graphical frontend for interacting with joint_trajectory_controller instances. Bence Magyar diff --git a/rqt_joint_trajectory_controller/setup.py b/rqt_joint_trajectory_controller/setup.py index 4b9a16dd3b..02f32191d5 100644 --- a/rqt_joint_trajectory_controller/setup.py +++ b/rqt_joint_trajectory_controller/setup.py @@ -7,7 +7,7 @@ setup( name=package_name, - version="4.3.0", + version="4.4.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/steering_controllers_library/CHANGELOG.rst b/steering_controllers_library/CHANGELOG.rst index de036d106a..ec986caddc 100644 --- a/steering_controllers_library/CHANGELOG.rst +++ b/steering_controllers_library/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package steering_controllers_library ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.4.0 (2024-01-11) +------------------ 4.3.0 (2024-01-08) ------------------ diff --git a/steering_controllers_library/package.xml b/steering_controllers_library/package.xml index 6e22de993e..90cb82ac8e 100644 --- a/steering_controllers_library/package.xml +++ b/steering_controllers_library/package.xml @@ -2,7 +2,7 @@ steering_controllers_library - 4.3.0 + 4.4.0 Package for steering robot configurations including odometry and interfaces. Apache License 2.0 Bence Magyar diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index 43f672c3c6..a0dccedfe5 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.4.0 (2024-01-11) +------------------ 4.3.0 (2024-01-08) ------------------ diff --git a/tricycle_controller/package.xml b/tricycle_controller/package.xml index 240badc7c5..cebd332a60 100644 --- a/tricycle_controller/package.xml +++ b/tricycle_controller/package.xml @@ -2,7 +2,7 @@ tricycle_controller - 4.3.0 + 4.4.0 Controller for a tricycle drive mobile base Bence Magyar Tony Najjar diff --git a/tricycle_steering_controller/CHANGELOG.rst b/tricycle_steering_controller/CHANGELOG.rst index a4dc4c1445..3be8c9ec03 100644 --- a/tricycle_steering_controller/CHANGELOG.rst +++ b/tricycle_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package tricycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.4.0 (2024-01-11) +------------------ 4.3.0 (2024-01-08) ------------------ diff --git a/tricycle_steering_controller/package.xml b/tricycle_steering_controller/package.xml index 0ff0604886..ad1c07d396 100644 --- a/tricycle_steering_controller/package.xml +++ b/tricycle_steering_controller/package.xml @@ -2,7 +2,7 @@ tricycle_steering_controller - 4.3.0 + 4.4.0 Steering controller with tricycle kinematics. Rear fixed wheels are powering the vehicle and front wheel is steering. Apache License 2.0 Bence Magyar diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index c3d0ffe8d3..8cc9c869ef 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.4.0 (2024-01-11) +------------------ 4.3.0 (2024-01-08) ------------------ diff --git a/velocity_controllers/package.xml b/velocity_controllers/package.xml index b57524bf21..5319f55a97 100644 --- a/velocity_controllers/package.xml +++ b/velocity_controllers/package.xml @@ -1,7 +1,7 @@ velocity_controllers - 4.3.0 + 4.4.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios From 3809db7351fc06d1623e6d08400f8844d57662b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Mon, 15 Jan 2024 11:13:39 +0100 Subject: [PATCH 190/238] Update mergify.yml (#974) --- .github/mergify.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/mergify.yml b/.github/mergify.yml index 0a6e425a30..e2e225980f 100644 --- a/.github/mergify.yml +++ b/.github/mergify.yml @@ -32,13 +32,13 @@ pull_request_rules: - author=mergify[bot] actions: comment: - message: This pull request is in conflict. Could you fix it @bmagyar @dstogl @christophfroehlich? + message: This pull request is in conflict. Could you fix it @bmagyar @destogl @christophfroehlich? - name: development targets master branch conditions: - base!=master - author!=bmagyar - - author!=dstogl + - author!=destogl - author!=christophfroehlich - author!=mergify[bot] - author!=dependabot[bot] From d5f1eabb92bed62543f2223008963170b7542f19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Mon, 15 Jan 2024 18:29:23 +0100 Subject: [PATCH 191/238] [PID] Remove joint_jog include (#975) --- pid_controller/include/pid_controller/pid_controller.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/pid_controller/include/pid_controller/pid_controller.hpp b/pid_controller/include/pid_controller/pid_controller.hpp index a34dc9f87f..f7b8cc4491 100644 --- a/pid_controller/include/pid_controller/pid_controller.hpp +++ b/pid_controller/include/pid_controller/pid_controller.hpp @@ -35,7 +35,6 @@ #include "std_srvs/srv/set_bool.hpp" #include "control_msgs/msg/joint_controller_state.hpp" -#include "control_msgs/msg/joint_jog.hpp" #include "control_msgs/msg/pid_state.hpp" #include "trajectory_msgs/msg/joint_trajectory_point.hpp" From 2f7a7552bdd485b540b292d7e541e17519915166 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Jan 2024 07:41:18 +0000 Subject: [PATCH 192/238] Bump actions/upload-artifact from 4.0.0 to 4.1.0 (#976) --- .github/workflows/ci-coverage-build-humble.yml | 2 +- .github/workflows/ci-coverage-build-iron.yml | 2 +- .github/workflows/ci-coverage-build.yml | 2 +- .github/workflows/reusable-ros-tooling-source-build.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-coverage-build-humble.yml b/.github/workflows/ci-coverage-build-humble.yml index a1d159541d..4b52ea32a3 100644 --- a/.github/workflows/ci-coverage-build-humble.yml +++ b/.github/workflows/ci-coverage-build-humble.yml @@ -60,7 +60,7 @@ jobs: file: ros_ws/lcov/total_coverage.info flags: unittests name: codecov-umbrella - - uses: actions/upload-artifact@v4.0.0 + - uses: actions/upload-artifact@v4.1.0 with: name: colcon-logs-coverage-humble path: ros_ws/log diff --git a/.github/workflows/ci-coverage-build-iron.yml b/.github/workflows/ci-coverage-build-iron.yml index 08e6eafd82..0720291062 100644 --- a/.github/workflows/ci-coverage-build-iron.yml +++ b/.github/workflows/ci-coverage-build-iron.yml @@ -60,7 +60,7 @@ jobs: file: ros_ws/lcov/total_coverage.info flags: unittests name: codecov-umbrella - - uses: actions/upload-artifact@v4.0.0 + - uses: actions/upload-artifact@v4.1.0 with: name: colcon-logs-coverage-iron path: ros_ws/log diff --git a/.github/workflows/ci-coverage-build.yml b/.github/workflows/ci-coverage-build.yml index f785652989..c65ee8339b 100644 --- a/.github/workflows/ci-coverage-build.yml +++ b/.github/workflows/ci-coverage-build.yml @@ -60,7 +60,7 @@ jobs: file: ros_ws/lcov/total_coverage.info flags: unittests name: codecov-umbrella - - uses: actions/upload-artifact@v4.0.0 + - uses: actions/upload-artifact@v4.1.0 with: name: colcon-logs-coverage-rolling path: ros_ws/log diff --git a/.github/workflows/reusable-ros-tooling-source-build.yml b/.github/workflows/reusable-ros-tooling-source-build.yml index fcc1a297fd..9157fa6edb 100644 --- a/.github/workflows/reusable-ros-tooling-source-build.yml +++ b/.github/workflows/reusable-ros-tooling-source-build.yml @@ -63,7 +63,7 @@ jobs: https://raw.githubusercontent.com/ros2/ros2/${{ inputs.ros2_repo_branch }}/ros2.repos https://raw.githubusercontent.com/${{ github.repository }}/${{ github.sha }}/ros2_controllers.${{ inputs.ros_distro }}.repos?token=${{ secrets.GITHUB_TOKEN }} colcon-mixin-repository: https://raw.githubusercontent.com/colcon/colcon-mixin-repository/master/index.yaml - - uses: actions/upload-artifact@v4.0.0 + - uses: actions/upload-artifact@v4.1.0 with: name: colcon-logs-ubuntu-22.04 path: ros_ws/log From 833ed7fbf67f0443ca28a1d24e035a64c99f2640 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Tue, 23 Jan 2024 00:08:43 +0100 Subject: [PATCH 193/238] [JTC] Convert lambda to class functions (#945) * Convert lambdas to member functions * Make member function const * Add a test for compute_error function * Make reference_wrapper argument const * Iterate over error fields --- .../joint_trajectory_controller.hpp | 35 +++- .../tolerances.hpp | 2 +- .../src/joint_trajectory_controller.cpp | 70 +++---- .../test/test_trajectory_controller.cpp | 174 ++++++++++++++++++ .../test/test_trajectory_controller_utils.hpp | 24 +++ 5 files changed, 261 insertions(+), 44 deletions(-) diff --git a/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp b/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp index 0ed2ce5688..b9097b1ce3 100644 --- a/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp +++ b/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp @@ -209,6 +209,20 @@ class JointTrajectoryController : public controller_interface::ControllerInterfa void goal_accepted_callback( std::shared_ptr> goal_handle); + using JointTrajectoryPoint = trajectory_msgs::msg::JointTrajectoryPoint; + + /** + * Computes the error for a specific joint in the trajectory. + * + * @param[out] error The computed error for the joint. + * @param[in] index The index of the joint in the trajectory. + * @param[in] current The current state of the joints. + * @param[in] desired The desired state of the joints. + */ + JOINT_TRAJECTORY_CONTROLLER_PUBLIC + void compute_error_for_joint( + JointTrajectoryPoint & error, const size_t index, const JointTrajectoryPoint & current, + const JointTrajectoryPoint & desired) const; // fill trajectory_msg so it matches joints controlled by this controller // positions set to current position, velocities, accelerations and efforts to 0.0 JOINT_TRAJECTORY_CONTROLLER_PUBLIC @@ -217,7 +231,7 @@ class JointTrajectoryController : public controller_interface::ControllerInterfa // sorts the joints of the incoming message to our local order JOINT_TRAJECTORY_CONTROLLER_PUBLIC void sort_to_local_joint_order( - std::shared_ptr trajectory_msg); + std::shared_ptr trajectory_msg) const; JOINT_TRAJECTORY_CONTROLLER_PUBLIC bool validate_trajectory_msg(const trajectory_msgs::msg::JointTrajectory & trajectory) const; JOINT_TRAJECTORY_CONTROLLER_PUBLIC @@ -251,7 +265,6 @@ class JointTrajectoryController : public controller_interface::ControllerInterfa JOINT_TRAJECTORY_CONTROLLER_PUBLIC bool has_active_trajectory() const; - using JointTrajectoryPoint = trajectory_msgs::msg::JointTrajectoryPoint; JOINT_TRAJECTORY_CONTROLLER_PUBLIC void publish_state( const rclcpp::Time & time, const JointTrajectoryPoint & desired_state, @@ -283,6 +296,24 @@ class JointTrajectoryController : public controller_interface::ControllerInterfa trajectory_msgs::msg::JointTrajectoryPoint & point, size_t size); void resize_joint_trajectory_point_command( trajectory_msgs::msg::JointTrajectoryPoint & point, size_t size); + + /** + * @brief Assigns the values from a trajectory point interface to a joint interface. + * + * @tparam T The type of the joint interface. + * @param[out] joint_interface The reference_wrapper to assign the values to + * @param[in] trajectory_point_interface Containing the values to assign. + * @todo: Use auto in parameter declaration with c++20 + */ + template + void assign_interface_from_point( + const T & joint_interface, const std::vector & trajectory_point_interface) + { + for (size_t index = 0; index < dof_; ++index) + { + joint_interface[index].get().set_value(trajectory_point_interface[index]); + } + } }; } // namespace joint_trajectory_controller diff --git a/joint_trajectory_controller/include/joint_trajectory_controller/tolerances.hpp b/joint_trajectory_controller/include/joint_trajectory_controller/tolerances.hpp index 2157fdf2a6..c46b1c297f 100644 --- a/joint_trajectory_controller/include/joint_trajectory_controller/tolerances.hpp +++ b/joint_trajectory_controller/include/joint_trajectory_controller/tolerances.hpp @@ -147,7 +147,7 @@ inline bool check_state_tolerance_per_joint( if (show_errors) { const auto logger = rclcpp::get_logger("tolerances"); - RCLCPP_ERROR(logger, "State tolerances failed for joint %ld:", joint_idx); + RCLCPP_ERROR(logger, "State tolerances failed for joint %lu:", joint_idx); if (state_tolerance.position > 0.0 && abs(error_position) > state_tolerance.position) { diff --git a/joint_trajectory_controller/src/joint_trajectory_controller.cpp b/joint_trajectory_controller/src/joint_trajectory_controller.cpp index 4a2a801e51..a8c7562b2f 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller.cpp +++ b/joint_trajectory_controller/src/joint_trajectory_controller.cpp @@ -122,35 +122,6 @@ controller_interface::return_type JointTrajectoryController::update( } } - auto compute_error_for_joint = [&]( - JointTrajectoryPoint & error, size_t index, - const JointTrajectoryPoint & current, - const JointTrajectoryPoint & desired) - { - // error defined as the difference between current and desired - if (joints_angle_wraparound_[index]) - { - // if desired, the shortest_angular_distance is calculated, i.e., the error is - // normalized between -piupdate(*new_external_msg); } - // TODO(anyone): can I here also use const on joint_interface since the reference_wrapper is not - // changed, but its value only? - auto assign_interface_from_point = - [&](auto & joint_interface, const std::vector & trajectory_point_interface) - { - for (size_t index = 0; index < dof_; ++index) - { - joint_interface[index].get().set_value(trajectory_point_interface[index]); - } - }; - // current state update state_current_.time_from_start.set__sec(0); read_state_from_state_interfaces(state_current_); @@ -1191,6 +1151,34 @@ void JointTrajectoryController::goal_accepted_callback( std::bind(&RealtimeGoalHandle::runNonRealtime, rt_goal)); } +void JointTrajectoryController::compute_error_for_joint( + JointTrajectoryPoint & error, const size_t index, const JointTrajectoryPoint & current, + const JointTrajectoryPoint & desired) const +{ + // error defined as the difference between current and desired + if (joints_angle_wraparound_[index]) + { + // if desired, the shortest_angular_distance is calculated, i.e., the error is + // normalized between -pi trajectory_msg) const { @@ -1252,7 +1240,7 @@ void JointTrajectoryController::fill_partial_goal( } void JointTrajectoryController::sort_to_local_joint_order( - std::shared_ptr trajectory_msg) + std::shared_ptr trajectory_msg) const { // rearrange all points in the trajectory message based on mapping std::vector mapping_vector = mapping(trajectory_msg->joint_names, params_.joints); diff --git a/joint_trajectory_controller/test/test_trajectory_controller.cpp b/joint_trajectory_controller/test/test_trajectory_controller.cpp index 72820c0295..dce04bf43a 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller.cpp +++ b/joint_trajectory_controller/test/test_trajectory_controller.cpp @@ -461,6 +461,180 @@ TEST_P(TrajectoryControllerTestParameterized, hold_on_startup) // Floating-point value comparison threshold const double EPS = 1e-6; + +/** + * @brief check if calculated trajectory error is correct with angle wraparound=true + */ +TEST_P(TrajectoryControllerTestParameterized, compute_error_angle_wraparound_true) +{ + rclcpp::executors::MultiThreadedExecutor executor; + std::vector params = {}; + SetUpAndActivateTrajectoryController( + executor, params, true, 0.0, 1.0, true /* angle_wraparound */); + + size_t n_joints = joint_names_.size(); + + // send msg + constexpr auto FIRST_POINT_TIME = std::chrono::milliseconds(250); + builtin_interfaces::msg::Duration time_from_start{rclcpp::Duration(FIRST_POINT_TIME)}; + // *INDENT-OFF* + std::vector> points{ + {{3.3, 4.4, 6.6}}, {{7.7, 8.8, 9.9}}, {{10.10, 11.11, 12.12}}}; + std::vector> points_velocities{ + {{0.01, 0.01, 0.01}}, {{0.05, 0.05, 0.05}}, {{0.06, 0.06, 0.06}}}; + std::vector> points_accelerations{ + {{0.1, 0.1, 0.1}}, {{0.5, 0.5, 0.5}}, {{0.6, 0.6, 0.6}}}; + // *INDENT-ON* + + trajectory_msgs::msg::JointTrajectoryPoint error, current, desired; + current.positions = {points[0].begin(), points[0].end()}; + current.velocities = {points_velocities[0].begin(), points_velocities[0].end()}; + current.accelerations = {points_accelerations[0].begin(), points_accelerations[0].end()}; + traj_controller_->resize_joint_trajectory_point(error, n_joints); + + // zero error + desired = current; + for (size_t i = 0; i < n_joints; ++i) + { + traj_controller_->testable_compute_error_for_joint(error, i, current, desired); + EXPECT_NEAR(error.positions[i], 0., EPS); + if ( + traj_controller_->has_velocity_state_interface() && + (traj_controller_->has_velocity_command_interface() || + traj_controller_->has_effort_command_interface())) + { + // expect: error.velocities = desired.velocities - current.velocities; + EXPECT_NEAR(error.velocities[i], 0., EPS); + } + if ( + traj_controller_->has_acceleration_state_interface() && + traj_controller_->has_acceleration_command_interface()) + { + // expect: error.accelerations = desired.accelerations - current.accelerations; + EXPECT_NEAR(error.accelerations[i], 0., EPS); + } + } + + // angle wraparound of position error + desired.positions[0] += 3.0 * M_PI_2; + desired.velocities[0] += 1.0; + desired.accelerations[0] += 1.0; + traj_controller_->resize_joint_trajectory_point(error, n_joints); + for (size_t i = 0; i < n_joints; ++i) + { + traj_controller_->testable_compute_error_for_joint(error, i, current, desired); + if (i == 0) + { + EXPECT_NEAR( + error.positions[i], desired.positions[i] - current.positions[i] - 2.0 * M_PI, EPS); + } + else + { + EXPECT_NEAR(error.positions[i], desired.positions[i] - current.positions[i], EPS); + } + + if ( + traj_controller_->has_velocity_state_interface() && + (traj_controller_->has_velocity_command_interface() || + traj_controller_->has_effort_command_interface())) + { + // expect: error.velocities = desired.velocities - current.velocities; + EXPECT_NEAR(error.velocities[i], desired.velocities[i] - current.velocities[i], EPS); + } + if ( + traj_controller_->has_acceleration_state_interface() && + traj_controller_->has_acceleration_command_interface()) + { + // expect: error.accelerations = desired.accelerations - current.accelerations; + EXPECT_NEAR(error.accelerations[i], desired.accelerations[i] - current.accelerations[i], EPS); + } + } + + executor.cancel(); +} + +/** + * @brief check if calculated trajectory error is correct with angle wraparound=false + */ +TEST_P(TrajectoryControllerTestParameterized, compute_error_angle_wraparound_false) +{ + rclcpp::executors::MultiThreadedExecutor executor; + std::vector params = {}; + SetUpAndActivateTrajectoryController( + executor, params, true, 0.0, 1.0, false /* angle_wraparound */); + + size_t n_joints = joint_names_.size(); + + // send msg + constexpr auto FIRST_POINT_TIME = std::chrono::milliseconds(250); + builtin_interfaces::msg::Duration time_from_start{rclcpp::Duration(FIRST_POINT_TIME)}; + // *INDENT-OFF* + std::vector> points{ + {{3.3, 4.4, 6.6}}, {{7.7, 8.8, 9.9}}, {{10.10, 11.11, 12.12}}}; + std::vector> points_velocities{ + {{0.01, 0.01, 0.01}}, {{0.05, 0.05, 0.05}}, {{0.06, 0.06, 0.06}}}; + std::vector> points_accelerations{ + {{0.1, 0.1, 0.1}}, {{0.5, 0.5, 0.5}}, {{0.6, 0.6, 0.6}}}; + // *INDENT-ON* + + trajectory_msgs::msg::JointTrajectoryPoint error, current, desired; + current.positions = {points[0].begin(), points[0].end()}; + current.velocities = {points_velocities[0].begin(), points_velocities[0].end()}; + current.accelerations = {points_accelerations[0].begin(), points_accelerations[0].end()}; + traj_controller_->resize_joint_trajectory_point(error, n_joints); + + // zero error + desired = current; + for (size_t i = 0; i < n_joints; ++i) + { + traj_controller_->testable_compute_error_for_joint(error, i, current, desired); + EXPECT_NEAR(error.positions[i], 0., EPS); + if ( + traj_controller_->has_velocity_state_interface() && + (traj_controller_->has_velocity_command_interface() || + traj_controller_->has_effort_command_interface())) + { + // expect: error.velocities = desired.velocities - current.velocities; + EXPECT_NEAR(error.velocities[i], 0., EPS); + } + if ( + traj_controller_->has_acceleration_state_interface() && + traj_controller_->has_acceleration_command_interface()) + { + // expect: error.accelerations = desired.accelerations - current.accelerations; + EXPECT_NEAR(error.accelerations[i], 0., EPS); + } + } + + // no normalization of position error + desired.positions[0] += 3.0 * M_PI_4; + desired.velocities[0] += 1.0; + desired.accelerations[0] += 1.0; + traj_controller_->resize_joint_trajectory_point(error, n_joints); + for (size_t i = 0; i < n_joints; ++i) + { + traj_controller_->testable_compute_error_for_joint(error, i, current, desired); + EXPECT_NEAR(error.positions[i], desired.positions[i] - current.positions[i], EPS); + if ( + traj_controller_->has_velocity_state_interface() && + (traj_controller_->has_velocity_command_interface() || + traj_controller_->has_effort_command_interface())) + { + // expect: error.velocities = desired.velocities - current.velocities; + EXPECT_NEAR(error.velocities[i], desired.velocities[i] - current.velocities[i], EPS); + } + if ( + traj_controller_->has_acceleration_state_interface() && + traj_controller_->has_acceleration_command_interface()) + { + // expect: error.accelerations = desired.accelerations - current.accelerations; + EXPECT_NEAR(error.accelerations[i], desired.accelerations[i] - current.accelerations[i], EPS); + } + } + + executor.cancel(); +} + /** * @brief check if position error of revolute joints are angle_wraparound if not configured so */ diff --git a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp index e636fad4b7..f98fd3e286 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp +++ b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp @@ -107,6 +107,13 @@ class TestableJointTrajectoryController void trigger_declare_parameters() { param_listener_->declare_params(); } + void testable_compute_error_for_joint( + JointTrajectoryPoint & error, const size_t index, const JointTrajectoryPoint & current, + const JointTrajectoryPoint & desired) + { + compute_error_for_joint(error, index, current, desired); + } + trajectory_msgs::msg::JointTrajectoryPoint get_current_state_when_offset() const { return last_commanded_state_; @@ -154,6 +161,23 @@ class TestableJointTrajectoryController trajectory_msgs::msg::JointTrajectoryPoint get_state_reference() { return state_desired_; } trajectory_msgs::msg::JointTrajectoryPoint get_state_error() { return state_error_; } + /** + * a copy of the private member function + */ + void resize_joint_trajectory_point( + trajectory_msgs::msg::JointTrajectoryPoint & point, size_t size) + { + point.positions.resize(size, 0.0); + if (has_velocity_state_interface_) + { + point.velocities.resize(size, 0.0); + } + if (has_acceleration_state_interface_) + { + point.accelerations.resize(size, 0.0); + } + } + rclcpp::WaitSet joint_cmd_sub_wait_set_; }; From d69676709afe8f82bdeb44f665dad66eaca3d5da Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 23 Jan 2024 09:43:12 +0000 Subject: [PATCH 194/238] Bump actions/upload-artifact from 4.1.0 to 4.2.0 (#984) --- .github/workflows/ci-coverage-build-humble.yml | 2 +- .github/workflows/ci-coverage-build-iron.yml | 2 +- .github/workflows/ci-coverage-build.yml | 2 +- .github/workflows/reusable-ros-tooling-source-build.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-coverage-build-humble.yml b/.github/workflows/ci-coverage-build-humble.yml index 4b52ea32a3..a195702d8c 100644 --- a/.github/workflows/ci-coverage-build-humble.yml +++ b/.github/workflows/ci-coverage-build-humble.yml @@ -60,7 +60,7 @@ jobs: file: ros_ws/lcov/total_coverage.info flags: unittests name: codecov-umbrella - - uses: actions/upload-artifact@v4.1.0 + - uses: actions/upload-artifact@v4.2.0 with: name: colcon-logs-coverage-humble path: ros_ws/log diff --git a/.github/workflows/ci-coverage-build-iron.yml b/.github/workflows/ci-coverage-build-iron.yml index 0720291062..7febd4417c 100644 --- a/.github/workflows/ci-coverage-build-iron.yml +++ b/.github/workflows/ci-coverage-build-iron.yml @@ -60,7 +60,7 @@ jobs: file: ros_ws/lcov/total_coverage.info flags: unittests name: codecov-umbrella - - uses: actions/upload-artifact@v4.1.0 + - uses: actions/upload-artifact@v4.2.0 with: name: colcon-logs-coverage-iron path: ros_ws/log diff --git a/.github/workflows/ci-coverage-build.yml b/.github/workflows/ci-coverage-build.yml index c65ee8339b..c00f15e4a6 100644 --- a/.github/workflows/ci-coverage-build.yml +++ b/.github/workflows/ci-coverage-build.yml @@ -60,7 +60,7 @@ jobs: file: ros_ws/lcov/total_coverage.info flags: unittests name: codecov-umbrella - - uses: actions/upload-artifact@v4.1.0 + - uses: actions/upload-artifact@v4.2.0 with: name: colcon-logs-coverage-rolling path: ros_ws/log diff --git a/.github/workflows/reusable-ros-tooling-source-build.yml b/.github/workflows/reusable-ros-tooling-source-build.yml index 9157fa6edb..0f20551214 100644 --- a/.github/workflows/reusable-ros-tooling-source-build.yml +++ b/.github/workflows/reusable-ros-tooling-source-build.yml @@ -63,7 +63,7 @@ jobs: https://raw.githubusercontent.com/ros2/ros2/${{ inputs.ros2_repo_branch }}/ros2.repos https://raw.githubusercontent.com/${{ github.repository }}/${{ github.sha }}/ros2_controllers.${{ inputs.ros_distro }}.repos?token=${{ secrets.GITHUB_TOKEN }} colcon-mixin-repository: https://raw.githubusercontent.com/colcon/colcon-mixin-repository/master/index.yaml - - uses: actions/upload-artifact@v4.1.0 + - uses: actions/upload-artifact@v4.2.0 with: name: colcon-logs-ubuntu-22.04 path: ros_ws/log From 3ab375942e2c0086d086d1d83a470449ae25351f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Tue, 23 Jan 2024 10:50:42 +0100 Subject: [PATCH 195/238] Update mergify.yml (#982) --- .github/mergify.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/mergify.yml b/.github/mergify.yml index e2e225980f..39ee6b6bc0 100644 --- a/.github/mergify.yml +++ b/.github/mergify.yml @@ -46,5 +46,5 @@ pull_request_rules: comment: message: | @{{author}}, all pull requests must be targeted towards the `master` development branch. - Once merged into `master`, it is possible to backport to @{{base}}, but it must be in `master` + Once merged into `master`, it is possible to backport to `{{base}}`, but it must be in `master` to have these changes reflected into new distributions. From 0bcb77bf083894d8208d6bfe7ae560d7dbf90aab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Thu, 25 Jan 2024 18:19:27 +0100 Subject: [PATCH 196/238] [CI] debian + RHEL updates (#985) --- .github/workflows/humble-debian-build.yml | 30 +++++++++++++++++++ .../workflows/humble-rhel-binary-build.yml | 20 ++++++------- .github/workflows/iron-debian-build.yml | 30 +++++++++++++++++++ .github/workflows/iron-rhel-binary-build.yml | 18 +++++++---- .github/workflows/rolling-debian-build.yml | 30 +++++++++++++++++++ .../workflows/rolling-rhel-binary-build.yml | 18 +++++++---- 6 files changed, 123 insertions(+), 23 deletions(-) create mode 100644 .github/workflows/humble-debian-build.yml create mode 100644 .github/workflows/iron-debian-build.yml create mode 100644 .github/workflows/rolling-debian-build.yml diff --git a/.github/workflows/humble-debian-build.yml b/.github/workflows/humble-debian-build.yml new file mode 100644 index 0000000000..e8deb2caa5 --- /dev/null +++ b/.github/workflows/humble-debian-build.yml @@ -0,0 +1,30 @@ +name: Debian Humble Build +on: + workflow_dispatch: + pull_request: + branches: + - humble + schedule: + # Run every day to detect flakiness and broken dependencies + - cron: '03 1 * * *' + + +jobs: + humble_debian: + name: Humble debian build + runs-on: ubuntu-latest + env: + ROS_DISTRO: humble + container: ghcr.io/ros-controls/ros:humble-debian + steps: + - uses: actions/checkout@v4 + with: + path: src/ros2_controllers + - name: Build and test + shell: bash + run: | + source /opt/ros2_ws/install/setup.bash + vcs import src < src/ros2_controllers/ros2_controllers.${{ env.ROS_DISTRO }}.repos + colcon build --packages-skip rqt_controller_manager rqt_joint_trajectory_controller + colcon test --packages-skip rqt_controller_manager rqt_joint_trajectory_controller control_msgs controller_manager_msgs + colcon test-result --verbose diff --git a/.github/workflows/humble-rhel-binary-build.yml b/.github/workflows/humble-rhel-binary-build.yml index 9da6059892..cd9b85b2e1 100644 --- a/.github/workflows/humble-rhel-binary-build.yml +++ b/.github/workflows/humble-rhel-binary-build.yml @@ -1,19 +1,13 @@ -name: Humble RHEL Binary Build +name: RHEL Humble Binary Build on: workflow_dispatch: - branches: - - humble pull_request: branches: - humble - push: - branches: - - humble schedule: # Run every day to detect flakiness and broken dependencies - cron: '03 1 * * *' - jobs: humble_rhel_binary: name: Humble RHEL binary build @@ -25,9 +19,13 @@ jobs: - uses: actions/checkout@v4 with: path: src/ros2_controllers - - run: | + - name: Install dependencies + run: | rosdep update - rosdep install -iy --from-path src/ros2_controllers + rosdep install -iyr --from-path src/ros2_controllers || true + - name: Build and test + run: | source /opt/ros/${{ env.ROS_DISTRO }}/setup.bash - colcon build - colcon test + colcon build --packages-skip rqt_joint_trajectory_controller + colcon test --packages-skip rqt_joint_trajectory_controller + colcon test-result --verbose diff --git a/.github/workflows/iron-debian-build.yml b/.github/workflows/iron-debian-build.yml new file mode 100644 index 0000000000..09dbd051b2 --- /dev/null +++ b/.github/workflows/iron-debian-build.yml @@ -0,0 +1,30 @@ +name: Debian Iron Build +on: + workflow_dispatch: + pull_request: + branches: + - iron + schedule: + # Run every day to detect flakiness and broken dependencies + - cron: '03 1 * * *' + + +jobs: + iron_debian: + name: Iron debian build + runs-on: ubuntu-latest + env: + ROS_DISTRO: iron + container: ghcr.io/ros-controls/ros:iron-debian + steps: + - uses: actions/checkout@v4 + with: + path: src/ros2_controllers + - name: Build and test + shell: bash + run: | + source /opt/ros2_ws/install/setup.bash + vcs import src < src/ros2_controllers/ros2_controllers.${{ env.ROS_DISTRO }}.repos + colcon build --packages-skip rqt_controller_manager rqt_joint_trajectory_controller + colcon test --packages-skip rqt_controller_manager rqt_joint_trajectory_controller control_msgs controller_manager_msgs + colcon test-result --verbose diff --git a/.github/workflows/iron-rhel-binary-build.yml b/.github/workflows/iron-rhel-binary-build.yml index 5664d61768..0eb28b9673 100644 --- a/.github/workflows/iron-rhel-binary-build.yml +++ b/.github/workflows/iron-rhel-binary-build.yml @@ -1,7 +1,7 @@ -name: Iron RHEL Binary Build +name: RHEL Iron Binary Build on: workflow_dispatch: - push: + pull_request: branches: - iron schedule: @@ -20,9 +20,15 @@ jobs: - uses: actions/checkout@v4 with: path: src/ros2_controllers - - run: | + - name: Install dependencies + run: | rosdep update - rosdep install -iy --from-path src/ros2_controllers + rosdep install -iyr --from-path src/ros2_controllers || true + - name: Build and test + # source also underlay workspace with generate_parameter_library on rhel9 + run: | source /opt/ros/${{ env.ROS_DISTRO }}/setup.bash - colcon build - colcon test + source /opt/ros2_ws/install/setup.bash + colcon build --packages-skip rqt_joint_trajectory_controller + colcon test --packages-skip rqt_joint_trajectory_controller + colcon test-result --verbose diff --git a/.github/workflows/rolling-debian-build.yml b/.github/workflows/rolling-debian-build.yml new file mode 100644 index 0000000000..b6d0a4193a --- /dev/null +++ b/.github/workflows/rolling-debian-build.yml @@ -0,0 +1,30 @@ +name: Debian Rolling Build +on: + workflow_dispatch: + pull_request: + branches: + - master + schedule: + # Run every day to detect flakiness and broken dependencies + - cron: '03 1 * * *' + + +jobs: + rolling_debian: + name: Rolling debian build + runs-on: ubuntu-latest + env: + ROS_DISTRO: rolling + container: ghcr.io/ros-controls/ros:rolling-debian + steps: + - uses: actions/checkout@v4 + with: + path: src/ros2_controllers + - name: Build and test + shell: bash + run: | + source /opt/ros2_ws/install/setup.bash + vcs import src < src/ros2_controllers/ros2_controllers.${{ env.ROS_DISTRO }}.repos + colcon build --packages-skip rqt_controller_manager rqt_joint_trajectory_controller + colcon test --packages-skip rqt_controller_manager rqt_joint_trajectory_controller + colcon test-result --verbose diff --git a/.github/workflows/rolling-rhel-binary-build.yml b/.github/workflows/rolling-rhel-binary-build.yml index 04dc58775f..dece43b673 100644 --- a/.github/workflows/rolling-rhel-binary-build.yml +++ b/.github/workflows/rolling-rhel-binary-build.yml @@ -1,7 +1,7 @@ -name: Rolling RHEL Binary Build +name: RHEL Rolling Binary Build on: workflow_dispatch: - push: + pull_request: branches: - master schedule: @@ -20,9 +20,15 @@ jobs: - uses: actions/checkout@v4 with: path: src/ros2_controllers - - run: | + - name: Install dependencies + run: | rosdep update - rosdep install -iy --from-path src/ros2_controllers + rosdep install -iyr --from-path src/ros2_controllers || true + - name: Build and test + # source also underlay workspace with generate_parameter_library on rhel9 + run: | source /opt/ros/${{ env.ROS_DISTRO }}/setup.bash - colcon build - colcon test + source /opt/ros2_ws/install/setup.bash + colcon build --packages-skip rqt_joint_trajectory_controller + colcon test --packages-skip rqt_joint_trajectory_controller + colcon test-result --verbose From 9f7e9e916ce8ae1403f0f0f5d108c80ea0242a9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noel=20Jim=C3=A9nez=20Garc=C3=ADa?= Date: Thu, 25 Jan 2024 19:02:41 +0100 Subject: [PATCH 197/238] Revert "[JTC] Remove read_only from 'joints', 'state_interfaces' and 'command_interfaces' parameters (#967)" (#978) This reverts commit 6e2736b0ed521e1b236dcf8ab2ede4ef565e97d4. --- .../src/joint_trajectory_controller_parameters.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml b/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml index a6358d1015..4981489d36 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml +++ b/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml @@ -3,6 +3,7 @@ joint_trajectory_controller: type: string_array, default_value: [], description: "Names of joints used by the controller", + read_only: true, validation: { unique<>: null, } @@ -20,6 +21,7 @@ joint_trajectory_controller: type: string_array, default_value: [], description: "Names of command interfaces to claim", + read_only: true, validation: { unique<>: null, subset_of<>: [["position", "velocity", "acceleration", "effort",]], @@ -30,6 +32,7 @@ joint_trajectory_controller: type: string_array, default_value: [], description: "Names of state interfaces to claim", + read_only: true, validation: { unique<>: null, subset_of<>: [["position", "velocity", "acceleration",]], From 7fee9401d68302e27ffa78efe6d1dc82237c39e4 Mon Sep 17 00:00:00 2001 From: Sai Kishor Kothakota Date: Mon, 29 Jan 2024 18:55:33 +0100 Subject: [PATCH 198/238] Revert "[ForceTorqueSensorBroadcaster] Create ParamListener and get parameters on configure (#698)" (#988) This reverts commit 32aaef7552638826aba0b3f3a72b1c1453739afa. --- .../src/force_torque_sensor_broadcaster.cpp | 16 +++-- .../test_force_torque_sensor_broadcaster.cpp | 67 +++++++++---------- 2 files changed, 39 insertions(+), 44 deletions(-) diff --git a/force_torque_sensor_broadcaster/src/force_torque_sensor_broadcaster.cpp b/force_torque_sensor_broadcaster/src/force_torque_sensor_broadcaster.cpp index e9a173380b..9b570d353f 100644 --- a/force_torque_sensor_broadcaster/src/force_torque_sensor_broadcaster.cpp +++ b/force_torque_sensor_broadcaster/src/force_torque_sensor_broadcaster.cpp @@ -29,12 +29,6 @@ ForceTorqueSensorBroadcaster::ForceTorqueSensorBroadcaster() } controller_interface::CallbackReturn ForceTorqueSensorBroadcaster::on_init() -{ - return controller_interface::CallbackReturn::SUCCESS; -} - -controller_interface::CallbackReturn ForceTorqueSensorBroadcaster::on_configure( - const rclcpp_lifecycle::State & /*previous_state*/) { try { @@ -43,10 +37,18 @@ controller_interface::CallbackReturn ForceTorqueSensorBroadcaster::on_configure( } catch (const std::exception & e) { - fprintf(stderr, "Exception thrown during configure stage with message: %s \n", e.what()); + fprintf(stderr, "Exception thrown during init stage with message: %s \n", e.what()); return controller_interface::CallbackReturn::ERROR; } + return controller_interface::CallbackReturn::SUCCESS; +} + +controller_interface::CallbackReturn ForceTorqueSensorBroadcaster::on_configure( + const rclcpp_lifecycle::State & /*previous_state*/) +{ + params_ = param_listener_->get_params(); + const bool no_interface_names_defined = params_.interface_names.force.x.empty() && params_.interface_names.force.y.empty() && params_.interface_names.force.z.empty() && params_.interface_names.torque.x.empty() && diff --git a/force_torque_sensor_broadcaster/test/test_force_torque_sensor_broadcaster.cpp b/force_torque_sensor_broadcaster/test/test_force_torque_sensor_broadcaster.cpp index ce6a04ec1f..f06252d83a 100644 --- a/force_torque_sensor_broadcaster/test/test_force_torque_sensor_broadcaster.cpp +++ b/force_torque_sensor_broadcaster/test/test_force_torque_sensor_broadcaster.cpp @@ -113,12 +113,11 @@ TEST_F(ForceTorqueSensorBroadcasterTest, SensorName_InterfaceNames_Set) SetUpFTSBroadcaster(); // set the 'sensor_name' - fts_broadcaster_->get_node()->declare_parameter("sensor_name", sensor_name_); + fts_broadcaster_->get_node()->set_parameter({"sensor_name", sensor_name_}); // set the 'interface_names' - fts_broadcaster_->get_node()->declare_parameter("interface_names.force.x", "fts_sensor/force.x"); - fts_broadcaster_->get_node()->declare_parameter( - "interface_names.torque.z", "fts_sensor/torque.z"); + fts_broadcaster_->get_node()->set_parameter({"interface_names.force.x", "fts_sensor/force.x"}); + fts_broadcaster_->get_node()->set_parameter({"interface_names.torque.z", "fts_sensor/torque.z"}); // configure failed, both 'sensor_name' and 'interface_names' supplied ASSERT_EQ(fts_broadcaster_->on_configure(rclcpp_lifecycle::State()), NODE_ERROR); @@ -129,7 +128,7 @@ TEST_F(ForceTorqueSensorBroadcasterTest, SensorName_IsEmpty_InterfaceNames_NotSe SetUpFTSBroadcaster(); // set the 'sensor_name' empty - fts_broadcaster_->get_node()->declare_parameter("sensor_name", ""); + fts_broadcaster_->get_node()->set_parameter({"sensor_name", ""}); // configure failed, 'sensor_name' parameter empty ASSERT_EQ(fts_broadcaster_->on_configure(rclcpp_lifecycle::State()), NODE_ERROR); @@ -140,8 +139,8 @@ TEST_F(ForceTorqueSensorBroadcasterTest, InterfaceNames_IsEmpty_SensorName_NotSe SetUpFTSBroadcaster(); // set the 'interface_names' empty - fts_broadcaster_->get_node()->declare_parameter("interface_names.force.x", ""); - fts_broadcaster_->get_node()->declare_parameter("interface_names.torque.z", ""); + fts_broadcaster_->get_node()->set_parameter({"interface_names.force.x", ""}); + fts_broadcaster_->get_node()->set_parameter({"interface_names.torque.z", ""}); // configure failed, 'interface_name' parameter empty ASSERT_EQ(fts_broadcaster_->on_configure(rclcpp_lifecycle::State()), NODE_ERROR); @@ -152,10 +151,10 @@ TEST_F(ForceTorqueSensorBroadcasterTest, SensorName_Configure_Success) SetUpFTSBroadcaster(); // set the 'sensor_name' - fts_broadcaster_->get_node()->declare_parameter("sensor_name", sensor_name_); + fts_broadcaster_->get_node()->set_parameter({"sensor_name", sensor_name_}); // set the 'frame_id' - fts_broadcaster_->get_node()->declare_parameter("frame_id", frame_id_); + fts_broadcaster_->get_node()->set_parameter({"frame_id", frame_id_}); // configure passed ASSERT_EQ(fts_broadcaster_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); @@ -172,12 +171,11 @@ TEST_F(ForceTorqueSensorBroadcasterTest, InterfaceNames_Configure_Success) SetUpFTSBroadcaster(); // set the 'interface_names' - fts_broadcaster_->get_node()->declare_parameter("interface_names.force.x", "fts_sensor/force.x"); - fts_broadcaster_->get_node()->declare_parameter( - "interface_names.torque.z", "fts_sensor/torque.z"); + fts_broadcaster_->get_node()->set_parameter({"interface_names.force.x", "fts_sensor/force.x"}); + fts_broadcaster_->get_node()->set_parameter({"interface_names.torque.z", "fts_sensor/torque.z"}); // set the 'frame_id' - fts_broadcaster_->get_node()->declare_parameter("frame_id", frame_id_); + fts_broadcaster_->get_node()->set_parameter({"frame_id", frame_id_}); // configure passed ASSERT_EQ(fts_broadcaster_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); @@ -188,8 +186,8 @@ TEST_F(ForceTorqueSensorBroadcasterTest, SensorName_ActivateDeactivate_Success) SetUpFTSBroadcaster(); // set the params 'sensor_name' and 'frame_id' - fts_broadcaster_->get_node()->declare_parameter("sensor_name", sensor_name_); - fts_broadcaster_->get_node()->declare_parameter("frame_id", frame_id_); + fts_broadcaster_->get_node()->set_parameter({"sensor_name", sensor_name_}); + fts_broadcaster_->get_node()->set_parameter({"frame_id", frame_id_}); // configure and activate success ASSERT_EQ(fts_broadcaster_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); @@ -216,8 +214,8 @@ TEST_F(ForceTorqueSensorBroadcasterTest, SensorName_Update_Success) SetUpFTSBroadcaster(); // set the params 'sensor_name' and 'frame_id' - fts_broadcaster_->get_node()->declare_parameter("sensor_name", sensor_name_); - fts_broadcaster_->get_node()->declare_parameter("frame_id", frame_id_); + fts_broadcaster_->get_node()->set_parameter({"sensor_name", sensor_name_}); + fts_broadcaster_->get_node()->set_parameter({"frame_id", frame_id_}); ASSERT_EQ(fts_broadcaster_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); ASSERT_EQ(fts_broadcaster_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); @@ -232,10 +230,9 @@ TEST_F(ForceTorqueSensorBroadcasterTest, InterfaceNames_Success) SetUpFTSBroadcaster(); // set the params 'interface_names' and 'frame_id' - fts_broadcaster_->get_node()->declare_parameter("interface_names.force.x", "fts_sensor/force.x"); - fts_broadcaster_->get_node()->declare_parameter( - "interface_names.torque.z", "fts_sensor/torque.z"); - fts_broadcaster_->get_node()->declare_parameter("frame_id", frame_id_); + fts_broadcaster_->get_node()->set_parameter({"interface_names.force.x", "fts_sensor/force.x"}); + fts_broadcaster_->get_node()->set_parameter({"interface_names.torque.z", "fts_sensor/torque.z"}); + fts_broadcaster_->get_node()->set_parameter({"frame_id", frame_id_}); ASSERT_EQ(fts_broadcaster_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); ASSERT_EQ(fts_broadcaster_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); @@ -249,8 +246,8 @@ TEST_F(ForceTorqueSensorBroadcasterTest, SensorName_Publish_Success) SetUpFTSBroadcaster(); // set the params 'sensor_name' and 'frame_id' - fts_broadcaster_->get_node()->declare_parameter("sensor_name", sensor_name_); - fts_broadcaster_->get_node()->declare_parameter("frame_id", frame_id_); + fts_broadcaster_->get_node()->set_parameter({"sensor_name", sensor_name_}); + fts_broadcaster_->get_node()->set_parameter({"frame_id", frame_id_}); ASSERT_EQ(fts_broadcaster_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); ASSERT_EQ(fts_broadcaster_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); @@ -272,10 +269,9 @@ TEST_F(ForceTorqueSensorBroadcasterTest, InterfaceNames_Publish_Success) SetUpFTSBroadcaster(); // set the params 'interface_names' and 'frame_id' - fts_broadcaster_->get_node()->declare_parameter("interface_names.force.x", "fts_sensor/force.x"); - fts_broadcaster_->get_node()->declare_parameter( - "interface_names.torque.z", "fts_sensor/torque.z"); - fts_broadcaster_->get_node()->declare_parameter("frame_id", frame_id_); + fts_broadcaster_->get_node()->set_parameter({"interface_names.force.x", "fts_sensor/force.x"}); + fts_broadcaster_->get_node()->set_parameter({"interface_names.torque.z", "fts_sensor/torque.z"}); + fts_broadcaster_->get_node()->set_parameter({"frame_id", frame_id_}); ASSERT_EQ(fts_broadcaster_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); ASSERT_EQ(fts_broadcaster_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); @@ -297,16 +293,13 @@ TEST_F(ForceTorqueSensorBroadcasterTest, All_InterfaceNames_Publish_Success) SetUpFTSBroadcaster(); // set all the params 'interface_names' and 'frame_id' - fts_broadcaster_->get_node()->declare_parameter("interface_names.force.x", "fts_sensor/force.x"); - fts_broadcaster_->get_node()->declare_parameter("interface_names.force.y", "fts_sensor/force.y"); - fts_broadcaster_->get_node()->declare_parameter("interface_names.force.z", "fts_sensor/force.z"); - fts_broadcaster_->get_node()->declare_parameter( - "interface_names.torque.x", "fts_sensor/torque.x"); - fts_broadcaster_->get_node()->declare_parameter( - "interface_names.torque.y", "fts_sensor/torque.y"); - fts_broadcaster_->get_node()->declare_parameter( - "interface_names.torque.z", "fts_sensor/torque.z"); - fts_broadcaster_->get_node()->declare_parameter("frame_id", frame_id_); + fts_broadcaster_->get_node()->set_parameter({"interface_names.force.x", "fts_sensor/force.x"}); + fts_broadcaster_->get_node()->set_parameter({"interface_names.force.y", "fts_sensor/force.y"}); + fts_broadcaster_->get_node()->set_parameter({"interface_names.force.z", "fts_sensor/force.z"}); + fts_broadcaster_->get_node()->set_parameter({"interface_names.torque.x", "fts_sensor/torque.x"}); + fts_broadcaster_->get_node()->set_parameter({"interface_names.torque.y", "fts_sensor/torque.y"}); + fts_broadcaster_->get_node()->set_parameter({"interface_names.torque.z", "fts_sensor/torque.z"}); + fts_broadcaster_->get_node()->set_parameter({"frame_id", frame_id_}); ASSERT_EQ(fts_broadcaster_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); ASSERT_EQ(fts_broadcaster_->on_activate(rclcpp_lifecycle::State()), NODE_SUCCESS); From 8d732f1a3bc2879f89162e7d0ddae275180451c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Mon, 29 Jan 2024 18:58:52 +0100 Subject: [PATCH 199/238] [tricycle_controller] Use generate_parameter_library (#957) --- tricycle_controller/CMakeLists.txt | 13 +- tricycle_controller/doc/userdoc.rst | 10 +- .../tricycle_controller.hpp | 27 +--- tricycle_controller/package.xml | 1 + .../src/tricycle_controller.cpp | 151 +++++------------- .../src/tricycle_controller_parameter.yaml | 149 +++++++++++++++++ .../test/test_load_tricycle_controller.cpp | 9 +- .../test/test_tricycle_controller.cpp | 115 ++++++------- 8 files changed, 275 insertions(+), 200 deletions(-) create mode 100644 tricycle_controller/src/tricycle_controller_parameter.yaml diff --git a/tricycle_controller/CMakeLists.txt b/tricycle_controller/CMakeLists.txt index 4f6d064dc8..cdc69f182a 100644 --- a/tricycle_controller/CMakeLists.txt +++ b/tricycle_controller/CMakeLists.txt @@ -11,6 +11,7 @@ set(THIS_PACKAGE_INCLUDE_DEPENDS builtin_interfaces controller_interface geometry_msgs + generate_parameter_library hardware_interface nav_msgs pluginlib @@ -29,6 +30,10 @@ foreach(Dependency IN ITEMS ${THIS_PACKAGE_INCLUDE_DEPENDS}) find_package(${Dependency} REQUIRED) endforeach() +generate_parameter_library(tricycle_controller_parameters + src/tricycle_controller_parameter.yaml +) + add_library(tricycle_controller SHARED src/tricycle_controller.cpp src/odometry.cpp @@ -40,6 +45,7 @@ target_include_directories(tricycle_controller PUBLIC $ $ ) +target_link_libraries(tricycle_controller PUBLIC tricycle_controller_parameters) ament_target_dependencies(tricycle_controller PUBLIC ${THIS_PACKAGE_INCLUDE_DEPENDS}) pluginlib_export_plugin_description_file(controller_interface tricycle_controller.xml) @@ -50,8 +56,7 @@ if(BUILD_TESTING) find_package(ros2_control_test_assets REQUIRED) ament_add_gmock(test_tricycle_controller - test/test_tricycle_controller.cpp - ENV config_file=${CMAKE_CURRENT_SOURCE_DIR}/test/config/test_tricycle_controller.yaml) + test/test_tricycle_controller.cpp) target_link_libraries(test_tricycle_controller tricycle_controller ) @@ -66,8 +71,9 @@ if(BUILD_TESTING) tf2_msgs ) - ament_add_gmock(test_load_tricycle_controller + add_rostest_with_parameters_gmock(test_load_tricycle_controller test/test_load_tricycle_controller.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test/config/test_tricycle_controller.yaml ) target_link_libraries(test_load_tricycle_controller tricycle_controller @@ -85,6 +91,7 @@ install( install( TARGETS tricycle_controller + tricycle_controller_parameters EXPORT export_tricycle_controller RUNTIME DESTINATION bin ARCHIVE DESTINATION lib diff --git a/tricycle_controller/doc/userdoc.rst b/tricycle_controller/doc/userdoc.rst index d153aeacba..991627eca2 100644 --- a/tricycle_controller/doc/userdoc.rst +++ b/tricycle_controller/doc/userdoc.rst @@ -5,7 +5,8 @@ tricycle_controller ===================== -Controller for mobile robots with tricycle drive. +Controller for mobile robots with a single double-actuated wheel, including traction and steering. An example is a tricycle robot with the actuated wheel in the front and two trailing wheels on the rear axle. + Input for control are robot base_link twist commands which are translated to traction and steering commands for the tricycle drive base. Odometry is computed from hardware feedback and published. @@ -24,3 +25,10 @@ Other features Odometry publishing Velocity, acceleration and jerk limits Automatic stop after command timeout + +Parameters +-------------- + +This controller uses the `generate_parameter_library `_ to handle its parameters. + +.. generate_parameter_library_details:: ../src/tricycle_controller_parameter.yaml diff --git a/tricycle_controller/include/tricycle_controller/tricycle_controller.hpp b/tricycle_controller/include/tricycle_controller/tricycle_controller.hpp index cef90d026a..24aaf89de9 100644 --- a/tricycle_controller/include/tricycle_controller/tricycle_controller.hpp +++ b/tricycle_controller/include/tricycle_controller/tricycle_controller.hpp @@ -45,6 +45,9 @@ #include "tricycle_controller/traction_limiter.hpp" #include "tricycle_controller/visibility_control.h" +// auto-generated by generate_parameter_library +#include "tricycle_controller_parameters.hpp" + namespace tricycle_controller { using CallbackReturn = rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn; @@ -109,31 +112,14 @@ class TricycleController : public controller_interface::ControllerInterface double convert_trans_rot_vel_to_steering_angle(double v, double omega, double wheelbase); std::tuple twist_to_ackermann(double linear_command, double angular_command); - std::string traction_joint_name_; - std::string steering_joint_name_; + // Parameters from ROS for tricycle_controller + std::shared_ptr param_listener_; + Params params_; // HACK: put into vector to avoid initializing structs because they have no default constructors std::vector traction_joint_; std::vector steering_joint_; - struct WheelParams - { - double wheelbase = 0.0; - double radius = 0.0; - } wheel_params_; - - struct OdometryParams - { - bool open_loop = false; - bool enable_odom_tf = false; - bool odom_only_twist = false; // for doing the pose integration in separate node - std::string base_frame_id = "base_link"; - std::string odom_frame_id = "odom"; - std::array pose_covariance_diagonal; - std::array twist_covariance_diagonal; - } odom_params_; - - bool publish_ackermann_command_ = false; std::shared_ptr> ackermann_command_publisher_ = nullptr; std::shared_ptr> realtime_ackermann_command_publisher_ = nullptr; @@ -168,7 +154,6 @@ class TricycleController : public controller_interface::ControllerInterface SteeringLimiter limiter_steering_; bool is_halted = false; - bool use_stamped_vel_ = true; void reset_odometry( const std::shared_ptr request_header, diff --git a/tricycle_controller/package.xml b/tricycle_controller/package.xml index cebd332a60..cc50f0d58c 100644 --- a/tricycle_controller/package.xml +++ b/tricycle_controller/package.xml @@ -10,6 +10,7 @@ Tony Najjar ament_cmake + generate_parameter_library ackermann_msgs backward_ros diff --git a/tricycle_controller/src/tricycle_controller.cpp b/tricycle_controller/src/tricycle_controller.cpp index d6aeec0af1..07be8c2aae 100644 --- a/tricycle_controller/src/tricycle_controller.cpp +++ b/tricycle_controller/src/tricycle_controller.cpp @@ -52,41 +52,9 @@ CallbackReturn TricycleController::on_init() { try { - // with the lifecycle node being initialized, we can declare parameters - auto_declare("traction_joint_name", std::string()); - auto_declare("steering_joint_name", std::string()); - - auto_declare("wheelbase", wheel_params_.wheelbase); - auto_declare("wheel_radius", wheel_params_.radius); - - auto_declare("odom_frame_id", odom_params_.odom_frame_id); - auto_declare("base_frame_id", odom_params_.base_frame_id); - auto_declare>("pose_covariance_diagonal", std::vector()); - auto_declare>("twist_covariance_diagonal", std::vector()); - auto_declare("open_loop", odom_params_.open_loop); - auto_declare("enable_odom_tf", odom_params_.enable_odom_tf); - auto_declare("odom_only_twist", odom_params_.odom_only_twist); - - auto_declare("cmd_vel_timeout", static_cast(cmd_vel_timeout_.count())); - auto_declare("publish_ackermann_command", publish_ackermann_command_); - auto_declare("velocity_rolling_window_size", 10); - auto_declare("use_stamped_vel", use_stamped_vel_); - - auto_declare("traction.max_velocity", NAN); - auto_declare("traction.min_velocity", NAN); - auto_declare("traction.max_acceleration", NAN); - auto_declare("traction.min_acceleration", NAN); - auto_declare("traction.max_deceleration", NAN); - auto_declare("traction.min_deceleration", NAN); - auto_declare("traction.max_jerk", NAN); - auto_declare("traction.min_jerk", NAN); - - auto_declare("steering.max_position", NAN); - auto_declare("steering.min_position", NAN); - auto_declare("steering.max_velocity", NAN); - auto_declare("steering.min_velocity", NAN); - auto_declare("steering.max_acceleration", NAN); - auto_declare("steering.min_acceleration", NAN); + // Create the parameter listener and get the parameters + param_listener_ = std::make_shared(get_node()); + params_ = param_listener_->get_params(); } catch (const std::exception & e) { @@ -101,8 +69,8 @@ InterfaceConfiguration TricycleController::command_interface_configuration() con { InterfaceConfiguration command_interfaces_config; command_interfaces_config.type = interface_configuration_type::INDIVIDUAL; - command_interfaces_config.names.push_back(traction_joint_name_ + "/" + HW_IF_VELOCITY); - command_interfaces_config.names.push_back(steering_joint_name_ + "/" + HW_IF_POSITION); + command_interfaces_config.names.push_back(params_.traction_joint_name + "/" + HW_IF_VELOCITY); + command_interfaces_config.names.push_back(params_.steering_joint_name + "/" + HW_IF_POSITION); return command_interfaces_config; } @@ -110,8 +78,8 @@ InterfaceConfiguration TricycleController::state_interface_configuration() const { InterfaceConfiguration state_interfaces_config; state_interfaces_config.type = interface_configuration_type::INDIVIDUAL; - state_interfaces_config.names.push_back(traction_joint_name_ + "/" + HW_IF_VELOCITY); - state_interfaces_config.names.push_back(steering_joint_name_ + "/" + HW_IF_POSITION); + state_interfaces_config.names.push_back(params_.traction_joint_name + "/" + HW_IF_VELOCITY); + state_interfaces_config.names.push_back(params_.steering_joint_name + "/" + HW_IF_POSITION); return state_interfaces_config; } @@ -151,7 +119,7 @@ controller_interface::return_type TricycleController::update( double Ws_read = traction_joint_[0].velocity_state.get().get_value(); // in radians/s double alpha_read = steering_joint_[0].position_state.get().get_value(); // in radians - if (odom_params_.open_loop) + if (params_.open_loop) { odometry_.updateOpenLoop(linear_command, angular_command, period); } @@ -172,7 +140,7 @@ controller_interface::return_type TricycleController::update( { auto & odometry_message = realtime_odometry_publisher_->msg_; odometry_message.header.stamp = time; - if (!odom_params_.odom_only_twist) + if (!params_.odom_only_twist) { odometry_message.pose.pose.position.x = odometry_.getX(); odometry_message.pose.pose.position.y = odometry_.getY(); @@ -186,7 +154,7 @@ controller_interface::return_type TricycleController::update( realtime_odometry_publisher_->unlockAndPublish(); } - if (odom_params_.enable_odom_tf && realtime_odometry_transform_publisher_->trylock()) + if (params_.enable_odom_tf && realtime_odometry_transform_publisher_->trylock()) { auto & transform = realtime_odometry_transform_publisher_->msg_.transforms.front(); transform.header.stamp = time; @@ -239,7 +207,7 @@ controller_interface::return_type TricycleController::update( previous_commands_.emplace(ackermann_command); // Publish ackermann command - if (publish_ackermann_command_ && realtime_ackermann_command_publisher_->trylock()) + if (params_.publish_ackermann_command && realtime_ackermann_command_publisher_->trylock()) { auto & realtime_ackermann_command = realtime_ackermann_command_publisher_->msg_; // speed in AckermannDrive is defined desired forward speed (m/s) but we use it here as wheel @@ -258,74 +226,40 @@ CallbackReturn TricycleController::on_configure(const rclcpp_lifecycle::State & { auto logger = get_node()->get_logger(); - // update parameters - traction_joint_name_ = get_node()->get_parameter("traction_joint_name").as_string(); - steering_joint_name_ = get_node()->get_parameter("steering_joint_name").as_string(); - if (traction_joint_name_.empty()) + // update parameters if they have changed + if (param_listener_->is_old(params_)) { - RCLCPP_ERROR(logger, "'traction_joint_name' parameter was empty"); - return CallbackReturn::ERROR; + params_ = param_listener_->get_params(); + RCLCPP_INFO(logger, "Parameters were updated"); } - if (steering_joint_name_.empty()) - { - RCLCPP_ERROR(logger, "'steering_joint_name' parameter was empty"); - return CallbackReturn::ERROR; - } - - wheel_params_.wheelbase = get_node()->get_parameter("wheelbase").as_double(); - wheel_params_.radius = get_node()->get_parameter("wheel_radius").as_double(); - odometry_.setWheelParams(wheel_params_.wheelbase, wheel_params_.radius); - odometry_.setVelocityRollingWindowSize( - get_node()->get_parameter("velocity_rolling_window_size").as_int()); + odometry_.setWheelParams(params_.wheelbase, params_.wheel_radius); + odometry_.setVelocityRollingWindowSize(params_.velocity_rolling_window_size); - odom_params_.odom_frame_id = get_node()->get_parameter("odom_frame_id").as_string(); - odom_params_.base_frame_id = get_node()->get_parameter("base_frame_id").as_string(); - - auto pose_diagonal = get_node()->get_parameter("pose_covariance_diagonal").as_double_array(); - std::copy( - pose_diagonal.begin(), pose_diagonal.end(), odom_params_.pose_covariance_diagonal.begin()); - - auto twist_diagonal = get_node()->get_parameter("twist_covariance_diagonal").as_double_array(); - std::copy( - twist_diagonal.begin(), twist_diagonal.end(), odom_params_.twist_covariance_diagonal.begin()); - - odom_params_.open_loop = get_node()->get_parameter("open_loop").as_bool(); - odom_params_.enable_odom_tf = get_node()->get_parameter("enable_odom_tf").as_bool(); - odom_params_.odom_only_twist = get_node()->get_parameter("odom_only_twist").as_bool(); - - cmd_vel_timeout_ = - std::chrono::milliseconds{get_node()->get_parameter("cmd_vel_timeout").as_int()}; - publish_ackermann_command_ = get_node()->get_parameter("publish_ackermann_command").as_bool(); - use_stamped_vel_ = get_node()->get_parameter("use_stamped_vel").as_bool(); + cmd_vel_timeout_ = std::chrono::milliseconds{params_.cmd_vel_timeout}; + params_.publish_ackermann_command = + get_node()->get_parameter("publish_ackermann_command").as_bool(); + params_.use_stamped_vel = get_node()->get_parameter("use_stamped_vel").as_bool(); try { limiter_traction_ = TractionLimiter( - get_node()->get_parameter("traction.min_velocity").as_double(), - get_node()->get_parameter("traction.max_velocity").as_double(), - get_node()->get_parameter("traction.min_acceleration").as_double(), - get_node()->get_parameter("traction.max_acceleration").as_double(), - get_node()->get_parameter("traction.min_deceleration").as_double(), - get_node()->get_parameter("traction.max_deceleration").as_double(), - get_node()->get_parameter("traction.min_jerk").as_double(), - get_node()->get_parameter("traction.max_jerk").as_double()); + params_.traction.min_velocity, params_.traction.max_velocity, + params_.traction.min_acceleration, params_.traction.max_acceleration, + params_.traction.min_deceleration, params_.traction.max_deceleration, + params_.traction.min_jerk, params_.traction.max_jerk); } catch (const std::invalid_argument & e) { RCLCPP_ERROR(get_node()->get_logger(), "Error configuring traction limiter: %s", e.what()); return CallbackReturn::ERROR; } - try { limiter_steering_ = SteeringLimiter( - get_node()->get_parameter("steering.min_position").as_double(), - get_node()->get_parameter("steering.max_position").as_double(), - get_node()->get_parameter("steering.min_velocity").as_double(), - get_node()->get_parameter("steering.max_velocity").as_double(), - get_node()->get_parameter("steering.min_acceleration").as_double(), - get_node()->get_parameter("steering.max_acceleration").as_double()); + params_.steering.min_position, params_.steering.max_position, params_.steering.min_velocity, + params_.steering.max_velocity, params_.steering.min_acceleration, + params_.steering.max_acceleration); } catch (const std::invalid_argument & e) { @@ -347,7 +281,7 @@ CallbackReturn TricycleController::on_configure(const rclcpp_lifecycle::State & previous_commands_.emplace(empty_ackermann_drive); // initialize ackermann command publisher - if (publish_ackermann_command_) + if (params_.publish_ackermann_command) { ackermann_command_publisher_ = get_node()->create_publisher( DEFAULT_ACKERMANN_OUT_TOPIC, rclcpp::SystemDefaultsQoS()); @@ -357,7 +291,7 @@ CallbackReturn TricycleController::on_configure(const rclcpp_lifecycle::State & } // initialize command subscriber - if (use_stamped_vel_) + if (params_.use_stamped_vel) { velocity_command_subscriber_ = get_node()->create_subscription( DEFAULT_COMMAND_TOPIC, rclcpp::SystemDefaultsQoS(), @@ -409,8 +343,8 @@ CallbackReturn TricycleController::on_configure(const rclcpp_lifecycle::State & odometry_publisher_); auto & odometry_message = realtime_odometry_publisher_->msg_; - odometry_message.header.frame_id = odom_params_.odom_frame_id; - odometry_message.child_frame_id = odom_params_.base_frame_id; + odometry_message.header.frame_id = params_.odom_frame_id; + odometry_message.child_frame_id = params_.base_frame_id; // initialize odom values zeros odometry_message.twist = @@ -421,13 +355,12 @@ CallbackReturn TricycleController::on_configure(const rclcpp_lifecycle::State & { // 0, 7, 14, 21, 28, 35 const size_t diagonal_index = NUM_DIMENSIONS * index + index; - odometry_message.pose.covariance[diagonal_index] = odom_params_.pose_covariance_diagonal[index]; - odometry_message.twist.covariance[diagonal_index] = - odom_params_.twist_covariance_diagonal[index]; + odometry_message.pose.covariance[diagonal_index] = params_.pose_covariance_diagonal[index]; + odometry_message.twist.covariance[diagonal_index] = params_.twist_covariance_diagonal[index]; } // initialize transform publisher and message - if (odom_params_.enable_odom_tf) + if (params_.enable_odom_tf) { odometry_transform_publisher_ = get_node()->create_publisher( DEFAULT_TRANSFORM_TOPIC, rclcpp::SystemDefaultsQoS()); @@ -438,8 +371,8 @@ CallbackReturn TricycleController::on_configure(const rclcpp_lifecycle::State & // keeping track of odom and base_link transforms only auto & odometry_transform_message = realtime_odometry_transform_publisher_->msg_; odometry_transform_message.transforms.resize(1); - odometry_transform_message.transforms.front().header.frame_id = odom_params_.odom_frame_id; - odometry_transform_message.transforms.front().child_frame_id = odom_params_.base_frame_id; + odometry_transform_message.transforms.front().header.frame_id = params_.odom_frame_id; + odometry_transform_message.transforms.front().child_frame_id = params_.base_frame_id; } // Create odom reset service @@ -456,8 +389,8 @@ CallbackReturn TricycleController::on_activate(const rclcpp_lifecycle::State &) RCLCPP_INFO(get_node()->get_logger(), "On activate: Initialize Joints"); // Initialize the joints - const auto wheel_front_result = get_traction(traction_joint_name_, traction_joint_); - const auto steering_result = get_steering(steering_joint_name_, steering_joint_); + const auto wheel_front_result = get_traction(params_.traction_joint_name, traction_joint_); + const auto steering_result = get_steering(params_.steering_joint_name, steering_joint_); if (wheel_front_result == CallbackReturn::ERROR || steering_result == CallbackReturn::ERROR) { return CallbackReturn::ERROR; @@ -644,12 +577,12 @@ std::tuple TricycleController::twist_to_ackermann(double Vx, dou if (Vx == 0 && theta_dot != 0) { // is spin action alpha = theta_dot > 0 ? M_PI_2 : -M_PI_2; - Ws = abs(theta_dot) * wheel_params_.wheelbase / wheel_params_.radius; + Ws = abs(theta_dot) * params_.wheelbase / params_.wheel_radius; return std::make_tuple(alpha, Ws); } - alpha = convert_trans_rot_vel_to_steering_angle(Vx, theta_dot, wheel_params_.wheelbase); - Ws = Vx / (wheel_params_.radius * std::cos(alpha)); + alpha = convert_trans_rot_vel_to_steering_angle(Vx, theta_dot, params_.wheelbase); + Ws = Vx / (params_.wheel_radius * std::cos(alpha)); return std::make_tuple(alpha, Ws); } diff --git a/tricycle_controller/src/tricycle_controller_parameter.yaml b/tricycle_controller/src/tricycle_controller_parameter.yaml new file mode 100644 index 0000000000..68fc2202c2 --- /dev/null +++ b/tricycle_controller/src/tricycle_controller_parameter.yaml @@ -0,0 +1,149 @@ +tricycle_controller: + traction_joint_name: { + type: string, + default_value: "", + description: "Name of the traction joint", + validation: { + not_empty<>: [] + } + } + steering_joint_name: { + type: string, + default_value: "", + description: "Name of the steering joint", + validation: { + not_empty<>: [] + } + } + wheelbase: { + type: double, + default_value: 0.0, + description: "Shortest distance between the front wheel and the rear axle. If this parameter is wrong, the robot will not behave correctly in curves.", + } + wheel_radius: { + type: double, + default_value: 0.0, + description: "Radius of a wheel, i.e., wheels size, used for transformation of linear velocity into wheel rotations. If this parameter is wrong the robot will move faster or slower then expected.", + } + odom_frame_id: { + type: string, + default_value: "odom", + description: "Name of the frame for odometry. This frame is parent of ``base_frame_id`` when controller publishes odometry.", + } + base_frame_id: { + type: string, + default_value: "base_link", + description: "Name of the robot's base frame that is child of the odometry frame.", + } + pose_covariance_diagonal: { + type: double_array, + default_value: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + description: "Odometry covariance for the encoder output of the robot for the pose. These values should be tuned to your robot's sample odometry data, but these values are a good place to start: ``[0.001, 0.001, 0.001, 0.001, 0.001, 0.01]``.", + } + twist_covariance_diagonal: { + type: double_array, + default_value: [0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + description: "Odometry covariance for the encoder output of the robot for the speed. These values should be tuned to your robot's sample odometry data, but these values are a good place to start: ``[0.001, 0.001, 0.001, 0.001, 0.001, 0.01]``.", + } + open_loop: { + type: bool, + default_value: false, + description: "If set to true the odometry of the robot will be calculated from the commanded values and not from feedback.", + } + enable_odom_tf: { + type: bool, + default_value: false, + description: "Publish transformation between ``odom_frame_id`` and ``base_frame_id``.", + } + odom_only_twist: { + type: bool, + default_value: false, + description: "for doing the pose integration in separate node.", + } + cmd_vel_timeout: { + type: int, + default_value: 500, # milliseconds + description: "Timeout in milliseconds, after which input command on ``cmd_vel`` topic is considered staled.", + } + publish_ackermann_command: { + type: bool, + default_value: false, + description: "Publish limited commands.", + } + velocity_rolling_window_size: { + type: int, + default_value: 10, + description: "Size of the rolling window for calculation of mean velocity use in odometry.", + validation: { + gt<>: [0] + } + } + use_stamped_vel: { + type: bool, + default_value: true, + description: "Use stamp from input velocity message to calculate how old the command actually is.", + } + traction: + # "The positive limit will be applied to both directions. Setting different limits for positive " + # "and negative directions is not supported. Actuators are " + # "assumed to have the same constraints in both directions" + max_velocity: { + type: double, + default_value: .NAN, + } + min_velocity: { + type: double, + default_value: .NAN, + } + max_acceleration: { + type: double, + default_value: .NAN, + } + min_acceleration: { + type: double, + default_value: .NAN, + } + max_deceleration: { + type: double, + default_value: .NAN, + } + min_deceleration: { + type: double, + default_value: .NAN, + } + max_jerk: { + type: double, + default_value: .NAN, + } + min_jerk: { + type: double, + default_value: .NAN, + } + steering: + # "The positive limit will be applied to both directions. Setting different limits for positive " + # "and negative directions is not supported. Actuators are " + # "assumed to have the same constraints in both directions" + max_position: { + type: double, + default_value: .NAN, + } + min_position: { + type: double, + default_value: .NAN, + } + max_velocity: { + type: double, + default_value: .NAN, + } + min_velocity: { + type: double, + default_value: .NAN, + } + max_acceleration: { + type: double, + default_value: .NAN, + } + min_acceleration: { + type: double, + default_value: .NAN, + } diff --git a/tricycle_controller/test/test_load_tricycle_controller.cpp b/tricycle_controller/test/test_load_tricycle_controller.cpp index 9298fae574..245523c844 100644 --- a/tricycle_controller/test/test_load_tricycle_controller.cpp +++ b/tricycle_controller/test/test_load_tricycle_controller.cpp @@ -26,8 +26,6 @@ TEST(TestLoadTricycleController, load_controller) { - rclcpp::init(0, nullptr); - std::shared_ptr executor = std::make_shared(); @@ -39,6 +37,13 @@ TEST(TestLoadTricycleController, load_controller) ASSERT_NE( cm.load_controller("test_tricycle_controller", "tricycle_controller/TricycleController"), nullptr); +} +int main(int argc, char ** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + rclcpp::init(argc, argv); + int result = RUN_ALL_TESTS(); rclcpp::shutdown(); + return result; } diff --git a/tricycle_controller/test/test_tricycle_controller.cpp b/tricycle_controller/test/test_tricycle_controller.cpp index d8beedae42..018727e260 100644 --- a/tricycle_controller/test/test_tricycle_controller.cpp +++ b/tricycle_controller/test/test_tricycle_controller.cpp @@ -41,6 +41,12 @@ using lifecycle_msgs::msg::State; using testing::SizeIs; using testing::UnorderedElementsAre; +namespace +{ +const char traction_joint_name[] = "traction_joint"; +const char steering_joint_name[] = "steering_joint"; +} // namespace + class TestableTricycleController : public tricycle_controller::TricycleController { public: @@ -146,11 +152,28 @@ class TestTricycleController : public ::testing::Test controller_->assign_interfaces(std::move(command_ifs), std::move(state_ifs)); } + controller_interface::return_type InitController( + const std::string traction_joint_name_init = traction_joint_name, + const std::string steering_joint_name_init = steering_joint_name, + const std::vector & parameters = {}) + { + auto node_options = rclcpp::NodeOptions(); + std::vector parameter_overrides; + + parameter_overrides.push_back( + rclcpp::Parameter("traction_joint_name", rclcpp::ParameterValue(traction_joint_name_init))); + parameter_overrides.push_back( + rclcpp::Parameter("steering_joint_name", rclcpp::ParameterValue(steering_joint_name_init))); + + parameter_overrides.insert(parameter_overrides.end(), parameters.begin(), parameters.end()); + node_options.parameter_overrides(parameter_overrides); + + return controller_->init(controller_name, urdf_, 0, "", node_options); + } + const std::string controller_name = "test_tricycle_controller"; std::unique_ptr controller_; - const std::string traction_joint_name = "traction_joint"; - const std::string steering_joint_name = "steering_joint"; double position_ = 0.1; double velocity_ = 0.2; @@ -172,42 +195,24 @@ class TestTricycleController : public ::testing::Test const std::string urdf_ = ""; }; -TEST_F(TestTricycleController, configure_fails_without_parameters) +TEST_F(TestTricycleController, init_fails_without_parameters) { const auto ret = controller_->init(controller_name, urdf_, 0); - ASSERT_EQ(ret, controller_interface::return_type::OK); - ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), CallbackReturn::ERROR); + ASSERT_EQ(ret, controller_interface::return_type::ERROR); } -TEST_F(TestTricycleController, configure_fails_if_only_traction_or_steering_side_defined) +TEST_F(TestTricycleController, init_fails_if_only_traction_or_steering_side_defined) { - const auto ret = controller_->init(controller_name, urdf_, 0); - ASSERT_EQ(ret, controller_interface::return_type::OK); - - controller_->get_node()->set_parameter( - rclcpp::Parameter("traction_joint_name", rclcpp::ParameterValue(traction_joint_name))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("steering_joint_name", rclcpp::ParameterValue(std::string()))); - - ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), CallbackReturn::ERROR); - - controller_->get_node()->set_parameter( - rclcpp::Parameter("traction_joint_name", rclcpp::ParameterValue(std::string()))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("steering_joint_name", rclcpp::ParameterValue(steering_joint_name))); + ASSERT_EQ( + InitController(traction_joint_name, std::string()), controller_interface::return_type::ERROR); - ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), CallbackReturn::ERROR); + ASSERT_EQ( + InitController(std::string(), steering_joint_name), controller_interface::return_type::ERROR); } TEST_F(TestTricycleController, configure_succeeds_when_joints_are_specified) { - const auto ret = controller_->init(controller_name, urdf_, 0); - ASSERT_EQ(ret, controller_interface::return_type::OK); - - controller_->get_node()->set_parameter( - rclcpp::Parameter("traction_joint_name", rclcpp::ParameterValue(traction_joint_name))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("steering_joint_name", rclcpp::ParameterValue(steering_joint_name))); + ASSERT_EQ(InitController(), controller_interface::return_type::OK); ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), CallbackReturn::SUCCESS); @@ -215,26 +220,22 @@ TEST_F(TestTricycleController, configure_succeeds_when_joints_are_specified) auto cmd_if_conf = controller_->command_interface_configuration(); ASSERT_THAT(cmd_if_conf.names, SizeIs(2lu)); ASSERT_THAT( - cmd_if_conf.names, - UnorderedElementsAre(traction_joint_name + "/velocity", steering_joint_name + "/position")); + cmd_if_conf.names, UnorderedElementsAre( + std::string(traction_joint_name) + "/velocity", + std::string(steering_joint_name) + "/position")); EXPECT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); auto state_if_conf = controller_->state_interface_configuration(); ASSERT_THAT(state_if_conf.names, SizeIs(2lu)); ASSERT_THAT( - state_if_conf.names, - UnorderedElementsAre(traction_joint_name + "/velocity", steering_joint_name + "/position")); + state_if_conf.names, UnorderedElementsAre( + std::string(traction_joint_name) + "/velocity", + std::string(steering_joint_name) + "/position")); EXPECT_EQ(state_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); } TEST_F(TestTricycleController, activate_fails_without_resources_assigned) { - const auto ret = controller_->init(controller_name, urdf_, 0); - ASSERT_EQ(ret, controller_interface::return_type::OK); - - controller_->get_node()->set_parameter( - rclcpp::Parameter("traction_joint_name", rclcpp::ParameterValue(traction_joint_name))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("steering_joint_name", rclcpp::ParameterValue(steering_joint_name))); + ASSERT_EQ(InitController(), controller_interface::return_type::OK); ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), CallbackReturn::SUCCESS); ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), CallbackReturn::ERROR); @@ -242,15 +243,9 @@ TEST_F(TestTricycleController, activate_fails_without_resources_assigned) TEST_F(TestTricycleController, activate_succeeds_with_resources_assigned) { - const auto ret = controller_->init(controller_name, urdf_, 0); - ASSERT_EQ(ret, controller_interface::return_type::OK); + ASSERT_EQ(InitController(), controller_interface::return_type::OK); // We implicitly test that by default position feedback is required - controller_->get_node()->set_parameter( - rclcpp::Parameter("traction_joint_name", rclcpp::ParameterValue(traction_joint_name))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("steering_joint_name", rclcpp::ParameterValue(steering_joint_name))); - ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), CallbackReturn::SUCCESS); assignResources(); ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), CallbackReturn::SUCCESS); @@ -258,15 +253,11 @@ TEST_F(TestTricycleController, activate_succeeds_with_resources_assigned) TEST_F(TestTricycleController, cleanup) { - const auto ret = controller_->init(controller_name, urdf_, 0); - ASSERT_EQ(ret, controller_interface::return_type::OK); - - controller_->get_node()->set_parameter( - rclcpp::Parameter("traction_joint_name", rclcpp::ParameterValue(traction_joint_name))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("steering_joint_name", rclcpp::ParameterValue(steering_joint_name))); - controller_->get_node()->set_parameter(rclcpp::Parameter("wheelbase", 1.2)); - controller_->get_node()->set_parameter(rclcpp::Parameter("wheel_radius", 0.12)); + ASSERT_EQ( + InitController( + traction_joint_name, steering_joint_name, + {rclcpp::Parameter("wheelbase", 1.2), rclcpp::Parameter("wheel_radius", 0.12)}), + controller_interface::return_type::OK); rclcpp::executors::SingleThreadedExecutor executor; executor.add_node(controller_->get_node()->get_node_base_interface()); @@ -307,15 +298,11 @@ TEST_F(TestTricycleController, cleanup) TEST_F(TestTricycleController, correct_initialization_using_parameters) { - const auto ret = controller_->init(controller_name, urdf_, 0); - ASSERT_EQ(ret, controller_interface::return_type::OK); - - controller_->get_node()->set_parameter( - rclcpp::Parameter("traction_joint_name", rclcpp::ParameterValue(traction_joint_name))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("steering_joint_name", rclcpp::ParameterValue(steering_joint_name))); - controller_->get_node()->set_parameter(rclcpp::Parameter("wheelbase", 0.4)); - controller_->get_node()->set_parameter(rclcpp::Parameter("wheel_radius", 1.0)); + ASSERT_EQ( + InitController( + traction_joint_name, steering_joint_name, + {rclcpp::Parameter("wheelbase", 0.4), rclcpp::Parameter("wheel_radius", 1.0)}), + controller_interface::return_type::OK); rclcpp::executors::SingleThreadedExecutor executor; executor.add_node(controller_->get_node()->get_node_base_interface()); From ab6835144d9d60a38e778484039349ff44844f32 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Jan 2024 17:09:15 +0100 Subject: [PATCH 200/238] Bump ros-tooling/action-ros-ci from 0.3.5 to 0.3.6 (#994) Bumps [ros-tooling/action-ros-ci](https://github.com/ros-tooling/action-ros-ci) from 0.3.5 to 0.3.6. - [Release notes](https://github.com/ros-tooling/action-ros-ci/releases) - [Commits](https://github.com/ros-tooling/action-ros-ci/compare/0.3.5...0.3.6) --- updated-dependencies: - dependency-name: ros-tooling/action-ros-ci dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-coverage-build-humble.yml | 2 +- .github/workflows/ci-coverage-build-iron.yml | 2 +- .github/workflows/ci-coverage-build.yml | 2 +- .github/workflows/reusable-ros-tooling-source-build.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-coverage-build-humble.yml b/.github/workflows/ci-coverage-build-humble.yml index a195702d8c..cf98b2194e 100644 --- a/.github/workflows/ci-coverage-build-humble.yml +++ b/.github/workflows/ci-coverage-build-humble.yml @@ -21,7 +21,7 @@ jobs: with: required-ros-distributions: ${{ env.ROS_DISTRO }} - uses: actions/checkout@v4 - - uses: ros-tooling/action-ros-ci@0.3.5 + - uses: ros-tooling/action-ros-ci@0.3.6 with: target-ros2-distro: ${{ env.ROS_DISTRO }} import-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/ci-coverage-build-iron.yml b/.github/workflows/ci-coverage-build-iron.yml index 7febd4417c..41e40a5cb5 100644 --- a/.github/workflows/ci-coverage-build-iron.yml +++ b/.github/workflows/ci-coverage-build-iron.yml @@ -21,7 +21,7 @@ jobs: with: required-ros-distributions: ${{ env.ROS_DISTRO }} - uses: actions/checkout@v4 - - uses: ros-tooling/action-ros-ci@0.3.5 + - uses: ros-tooling/action-ros-ci@0.3.6 with: target-ros2-distro: ${{ env.ROS_DISTRO }} import-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/ci-coverage-build.yml b/.github/workflows/ci-coverage-build.yml index c00f15e4a6..7d12c7f2ad 100644 --- a/.github/workflows/ci-coverage-build.yml +++ b/.github/workflows/ci-coverage-build.yml @@ -21,7 +21,7 @@ jobs: with: required-ros-distributions: ${{ env.ROS_DISTRO }} - uses: actions/checkout@v4 - - uses: ros-tooling/action-ros-ci@0.3.5 + - uses: ros-tooling/action-ros-ci@0.3.6 with: target-ros2-distro: ${{ env.ROS_DISTRO }} import-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/reusable-ros-tooling-source-build.yml b/.github/workflows/reusable-ros-tooling-source-build.yml index 0f20551214..76c3a70781 100644 --- a/.github/workflows/reusable-ros-tooling-source-build.yml +++ b/.github/workflows/reusable-ros-tooling-source-build.yml @@ -32,7 +32,7 @@ jobs: - uses: actions/checkout@v4 with: ref: ${{ inputs.ref }} - - uses: ros-tooling/action-ros-ci@0.3.5 + - uses: ros-tooling/action-ros-ci@0.3.6 with: target-ros2-distro: ${{ inputs.ros_distro }} ref: ${{ inputs.ref }} From d375e4348347139b6dfce86fcda0a75ce24d0b7b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Jan 2024 17:09:25 +0100 Subject: [PATCH 201/238] Bump codecov/codecov-action from 3.1.4 to 3.1.5 (#993) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 3.1.4 to 3.1.5. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v3.1.4...v3.1.5) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-coverage-build-humble.yml | 2 +- .github/workflows/ci-coverage-build-iron.yml | 2 +- .github/workflows/ci-coverage-build.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-coverage-build-humble.yml b/.github/workflows/ci-coverage-build-humble.yml index cf98b2194e..f1a0941f20 100644 --- a/.github/workflows/ci-coverage-build-humble.yml +++ b/.github/workflows/ci-coverage-build-humble.yml @@ -55,7 +55,7 @@ jobs: } } colcon-mixin-repository: https://raw.githubusercontent.com/colcon/colcon-mixin-repository/master/index.yaml - - uses: codecov/codecov-action@v3.1.4 + - uses: codecov/codecov-action@v3.1.5 with: file: ros_ws/lcov/total_coverage.info flags: unittests diff --git a/.github/workflows/ci-coverage-build-iron.yml b/.github/workflows/ci-coverage-build-iron.yml index 41e40a5cb5..1d21f3b78b 100644 --- a/.github/workflows/ci-coverage-build-iron.yml +++ b/.github/workflows/ci-coverage-build-iron.yml @@ -55,7 +55,7 @@ jobs: } } colcon-mixin-repository: https://raw.githubusercontent.com/colcon/colcon-mixin-repository/master/index.yaml - - uses: codecov/codecov-action@v3.1.4 + - uses: codecov/codecov-action@v3.1.5 with: file: ros_ws/lcov/total_coverage.info flags: unittests diff --git a/.github/workflows/ci-coverage-build.yml b/.github/workflows/ci-coverage-build.yml index 7d12c7f2ad..e6a5b74d06 100644 --- a/.github/workflows/ci-coverage-build.yml +++ b/.github/workflows/ci-coverage-build.yml @@ -55,7 +55,7 @@ jobs: } } colcon-mixin-repository: https://raw.githubusercontent.com/colcon/colcon-mixin-repository/master/index.yaml - - uses: codecov/codecov-action@v3.1.4 + - uses: codecov/codecov-action@v3.1.5 with: file: ros_ws/lcov/total_coverage.info flags: unittests From 021ccab8c7a4a75392bd8903aafa1e7c9e23bc01 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 30 Jan 2024 17:09:34 +0100 Subject: [PATCH 202/238] Bump actions/upload-artifact from 4.2.0 to 4.3.0 (#992) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.2.0 to 4.3.0. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v4.2.0...v4.3.0) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-coverage-build-humble.yml | 2 +- .github/workflows/ci-coverage-build-iron.yml | 2 +- .github/workflows/ci-coverage-build.yml | 2 +- .github/workflows/reusable-ros-tooling-source-build.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-coverage-build-humble.yml b/.github/workflows/ci-coverage-build-humble.yml index f1a0941f20..c503e090ab 100644 --- a/.github/workflows/ci-coverage-build-humble.yml +++ b/.github/workflows/ci-coverage-build-humble.yml @@ -60,7 +60,7 @@ jobs: file: ros_ws/lcov/total_coverage.info flags: unittests name: codecov-umbrella - - uses: actions/upload-artifact@v4.2.0 + - uses: actions/upload-artifact@v4.3.0 with: name: colcon-logs-coverage-humble path: ros_ws/log diff --git a/.github/workflows/ci-coverage-build-iron.yml b/.github/workflows/ci-coverage-build-iron.yml index 1d21f3b78b..62ff5f34fe 100644 --- a/.github/workflows/ci-coverage-build-iron.yml +++ b/.github/workflows/ci-coverage-build-iron.yml @@ -60,7 +60,7 @@ jobs: file: ros_ws/lcov/total_coverage.info flags: unittests name: codecov-umbrella - - uses: actions/upload-artifact@v4.2.0 + - uses: actions/upload-artifact@v4.3.0 with: name: colcon-logs-coverage-iron path: ros_ws/log diff --git a/.github/workflows/ci-coverage-build.yml b/.github/workflows/ci-coverage-build.yml index e6a5b74d06..3f6dff5ab8 100644 --- a/.github/workflows/ci-coverage-build.yml +++ b/.github/workflows/ci-coverage-build.yml @@ -60,7 +60,7 @@ jobs: file: ros_ws/lcov/total_coverage.info flags: unittests name: codecov-umbrella - - uses: actions/upload-artifact@v4.2.0 + - uses: actions/upload-artifact@v4.3.0 with: name: colcon-logs-coverage-rolling path: ros_ws/log diff --git a/.github/workflows/reusable-ros-tooling-source-build.yml b/.github/workflows/reusable-ros-tooling-source-build.yml index 76c3a70781..2a3aa21325 100644 --- a/.github/workflows/reusable-ros-tooling-source-build.yml +++ b/.github/workflows/reusable-ros-tooling-source-build.yml @@ -63,7 +63,7 @@ jobs: https://raw.githubusercontent.com/ros2/ros2/${{ inputs.ros2_repo_branch }}/ros2.repos https://raw.githubusercontent.com/${{ github.repository }}/${{ github.sha }}/ros2_controllers.${{ inputs.ros_distro }}.repos?token=${{ secrets.GITHUB_TOKEN }} colcon-mixin-repository: https://raw.githubusercontent.com/colcon/colcon-mixin-repository/master/index.yaml - - uses: actions/upload-artifact@v4.2.0 + - uses: actions/upload-artifact@v4.3.0 with: name: colcon-logs-ubuntu-22.04 path: ros_ws/log From 99fadceed82918975e3471d615e897b3facd536e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Tue, 30 Jan 2024 17:44:14 +0100 Subject: [PATCH 203/238] [JTC] Invalidate empty trajectory messages (#902) --- .../src/joint_trajectory_controller.cpp | 6 +++ .../test/test_trajectory_controller.cpp | 42 ++++++++++++++++++- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/joint_trajectory_controller/src/joint_trajectory_controller.cpp b/joint_trajectory_controller/src/joint_trajectory_controller.cpp index a8c7562b2f..a22fe7f2d1 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller.cpp +++ b/joint_trajectory_controller/src/joint_trajectory_controller.cpp @@ -1363,6 +1363,12 @@ bool JointTrajectoryController::validate_trajectory_msg( } } + if (trajectory.points.empty()) + { + RCLCPP_ERROR(get_node()->get_logger(), "Empty trajectory received."); + return false; + } + if (!params_.allow_nonzero_velocity_at_trajectory_end) { for (size_t i = 0; i < trajectory.points.back().velocities.size(); ++i) diff --git a/joint_trajectory_controller/test/test_trajectory_controller.cpp b/joint_trajectory_controller/test/test_trajectory_controller.cpp index dce04bf43a..fbd6d7aea5 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller.cpp +++ b/joint_trajectory_controller/test/test_trajectory_controller.cpp @@ -1366,6 +1366,11 @@ TEST_P(TrajectoryControllerTestParameterized, invalid_message) traj_msg.joint_names = {"bad_name"}; EXPECT_FALSE(traj_controller_->validate_trajectory_msg(traj_msg)); + // empty message + traj_msg = good_traj_msg; + traj_msg.points.clear(); + EXPECT_FALSE(traj_controller_->validate_trajectory_msg(traj_msg)); + // No position data traj_msg = good_traj_msg; traj_msg.points[0].positions.clear(); @@ -1402,8 +1407,41 @@ TEST_P(TrajectoryControllerTestParameterized, invalid_message) EXPECT_FALSE(traj_controller_->validate_trajectory_msg(traj_msg)); } -/// With allow_integration_in_goal_trajectories parameter trajectory missing position or -/// velocities are accepted +/** + * @brief Test invalid velocity at trajectory end with parameter set to false + */ +TEST_P( + TrajectoryControllerTestParameterized, + expect_invalid_when_message_with_nonzero_end_velocity_and_when_param_false) +{ + rclcpp::Parameter nonzero_vel_parameters("allow_nonzero_velocity_at_trajectory_end", false); + rclcpp::executors::SingleThreadedExecutor executor; + SetUpAndActivateTrajectoryController(executor, {nonzero_vel_parameters}); + + trajectory_msgs::msg::JointTrajectory traj_msg; + traj_msg.joint_names = joint_names_; + traj_msg.header.stamp = rclcpp::Time(0); + + // empty message (no throw!) + ASSERT_NO_THROW(traj_controller_->validate_trajectory_msg(traj_msg)); + EXPECT_FALSE(traj_controller_->validate_trajectory_msg(traj_msg)); + + // Nonzero velocity at trajectory end! + traj_msg.points.resize(1); + traj_msg.points[0].time_from_start = rclcpp::Duration::from_seconds(0.25); + traj_msg.points[0].positions.resize(1); + traj_msg.points[0].positions = {1.0, 2.0, 3.0}; + traj_msg.points[0].velocities.resize(1); + traj_msg.points[0].velocities = {-1.0, -2.0, -3.0}; + EXPECT_FALSE(traj_controller_->validate_trajectory_msg(traj_msg)); +} + +/** + * @brief missing_positions_message_accepted Test mismatched joint and reference vector sizes + * + * @note With allow_integration_in_goal_trajectories parameter trajectory missing position or + * velocities are accepted + */ TEST_P(TrajectoryControllerTestParameterized, missing_positions_message_accepted) { rclcpp::Parameter allow_integration_parameters("allow_integration_in_goal_trajectories", true); From f375c698aa6b241b596a42c9d6e879708be4526f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Wed, 31 Jan 2024 21:35:22 +0100 Subject: [PATCH 204/238] Let sphinx add parameter description with nested structures to documentation (#652) --- admittance_controller/doc/userdoc.rst | 10 +- .../doc/parameters_context.yaml | 9 ++ diff_drive_controller/doc/userdoc.rst | 17 +- .../doc/parameters_context.yaml | 12 ++ .../doc/userdoc.rst | 26 ++- ..._torque_sensor_broadcaster_parameters.yaml | 3 +- gripper_controllers/doc/userdoc.rst | 17 +- imu_sensor_broadcaster/doc/userdoc.rst | 13 +- ...nt_state_broadcaster_parameter_context.yml | 46 ++++++ joint_state_broadcaster/doc/userdoc.rst | 71 ++------- .../joint_state_broadcaster_parameters.yaml | 11 ++ .../doc/parameters.rst | 148 ++---------------- .../doc/parameters_context.yaml | 13 ++ ...oint_trajectory_controller_parameters.yaml | 40 +++-- range_sensor_broadcaster/doc/userdoc.rst | 16 ++ 15 files changed, 204 insertions(+), 248 deletions(-) create mode 100644 diff_drive_controller/doc/parameters_context.yaml create mode 100644 force_torque_sensor_broadcaster/doc/parameters_context.yaml create mode 100644 joint_state_broadcaster/doc/joint_state_broadcaster_parameter_context.yml create mode 100644 joint_trajectory_controller/doc/parameters_context.yaml diff --git a/admittance_controller/doc/userdoc.rst b/admittance_controller/doc/userdoc.rst index 0e4469cd50..8056a017d7 100644 --- a/admittance_controller/doc/userdoc.rst +++ b/admittance_controller/doc/userdoc.rst @@ -17,10 +17,14 @@ ROS 2 interface of the controller Parameters ^^^^^^^^^^^ -The admittance controller's uses the `generate_parameter_library `_ to handle its parameters. -The parameter `definition file located in the src folder `_ contains descriptions for all the parameters used by the controller. -An example parameter file can be found in the `test folder of the controller `_ +The admittance controller uses the `generate_parameter_library `_ to handle its parameters. The parameter `definition file located in the src folder `_ contains descriptions for all the parameters used by the controller. +.. generate_parameter_library_details:: ../src/admittance_controller_parameters.yaml + +An example parameter file for this controller can be found in `the test folder `_: + +.. literalinclude:: ../test/test_params.yaml + :language: yaml Topics ^^^^^^^ diff --git a/diff_drive_controller/doc/parameters_context.yaml b/diff_drive_controller/doc/parameters_context.yaml new file mode 100644 index 0000000000..81e92806f5 --- /dev/null +++ b/diff_drive_controller/doc/parameters_context.yaml @@ -0,0 +1,9 @@ +linear.x: | + Joint limits structure for the linear ``x``-axis. + The limiter ignores position limits. + For details see ``joint_limits`` package from ros2_control repository. + +angular.z: | + Joint limits structure for the rotation about ``z``-axis. + The limiter ignores position limits. + For details see ``joint_limits`` package from ros2_control repository. diff --git a/diff_drive_controller/doc/userdoc.rst b/diff_drive_controller/doc/userdoc.rst index d2dd284cf3..70d0d7ca5c 100644 --- a/diff_drive_controller/doc/userdoc.rst +++ b/diff_drive_controller/doc/userdoc.rst @@ -64,17 +64,12 @@ Publishers Parameters ,,,,,,,,,,,, -Check `parameter definition file for details `_. +This controller uses the `generate_parameter_library `_ to handle its parameters. The parameter `definition file located in the src folder `_ contains descriptions for all the parameters used by the controller. -Note that the documentation on parameters for joint limits can be found in `their header file `_. -Those parameters are: +.. generate_parameter_library_details:: ../src/diff_drive_controller_parameter.yaml + parameters_context.yaml -linear.x [JointLimits structure] - Joint limits structure for the linear X-axis. - The limiter ignores position limits. - For details see ``joint_limits`` package from ros2_control repository. +An example parameter file for this controller can be found in `the test directory `_: -angular.z [JointLimits structure] - Joint limits structure for the rotation about Z-axis. - The limiter ignores position limits. - For details see ``joint_limits`` package from ros2_control repository. +.. literalinclude:: ../test/config/test_diff_drive_controller.yaml + :language: yaml diff --git a/force_torque_sensor_broadcaster/doc/parameters_context.yaml b/force_torque_sensor_broadcaster/doc/parameters_context.yaml new file mode 100644 index 0000000000..6991427316 --- /dev/null +++ b/force_torque_sensor_broadcaster/doc/parameters_context.yaml @@ -0,0 +1,12 @@ +interface_names: | + (optional) Defines custom, per axis interface names. + This is used if different prefixes, i.e., sensor name, or non-standard interface names are used. + It is sufficient that only one ``interface_name`` is defined. + This enables the broadcaster to use force sensing cells with less than six measuring axes. + An example definition is: + + .. code-block:: yaml + + interface_names: + force: + x: example_name/example_interface diff --git a/force_torque_sensor_broadcaster/doc/userdoc.rst b/force_torque_sensor_broadcaster/doc/userdoc.rst index 053723e8f0..df0430e3bb 100644 --- a/force_torque_sensor_broadcaster/doc/userdoc.rst +++ b/force_torque_sensor_broadcaster/doc/userdoc.rst @@ -12,25 +12,17 @@ The controller is a wrapper around ``ForceTorqueSensor`` semantic component (see Parameters ^^^^^^^^^^^ -The interfaces can be defined in two ways, using ``sensor_name`` or ``interface_names`` parameter. -Those two parameters can not be defined at the same time +This controller uses the `generate_parameter_library `_ to handle its parameters. The parameter `definition file located in the src folder `_ contains descriptions for all the parameters used by the controller. -frame_id (mandatory) - Frame in which the output message will be published. +The interfaces can be defined in two ways, using the ``sensor_name`` or the ``interface_names`` parameter: +Those two parameters cannot be defined at the same time. -sensor_name (optional) - Defines sensor name used as prefix for its interfaces. - If used standard interface names for a 6D FTS will be used: /force.x, ..., /torque.z. +Full list of parameters: -interface_names.[force|torque].[x|y|z] (optional) - Defines custom, per axis interface names. - This is used if different prefixes, i.e., sensor name, or non-standard interface names are used. - It is sufficient that only one ``interface_name`` is defined. - This enables broadcaster use for force sensing cells with less then six measuring axes. - Example definition is: +.. generate_parameter_library_details:: ../src/force_torque_sensor_broadcaster_parameters.yaml + parameters_context.yaml - .. code-block:: yaml +An example parameter file for this controller can be found in `the test directory `_: - interface_names: - force: - x: example_name/example_interface +.. literalinclude:: ../test/force_torque_sensor_broadcaster_params.yaml + :language: yaml diff --git a/force_torque_sensor_broadcaster/src/force_torque_sensor_broadcaster_parameters.yaml b/force_torque_sensor_broadcaster/src/force_torque_sensor_broadcaster_parameters.yaml index 68a85d9d8e..3e75ab6012 100644 --- a/force_torque_sensor_broadcaster/src/force_torque_sensor_broadcaster_parameters.yaml +++ b/force_torque_sensor_broadcaster/src/force_torque_sensor_broadcaster_parameters.yaml @@ -10,7 +10,8 @@ force_torque_sensor_broadcaster: sensor_name: { type: string, default_value: "", - description: "Name of the sensor used as prefix for interfaces if there are no individual interface names defined.", + description: "Name of the sensor used as prefix for interfaces if there are no individual interface names defined. + If used, standard interface names for a 6D FTS will be used: ``/force.x, ..., /torque.z``", } interface_names: force: diff --git a/gripper_controllers/doc/userdoc.rst b/gripper_controllers/doc/userdoc.rst index 28262e90f9..7f51c8f4ac 100644 --- a/gripper_controllers/doc/userdoc.rst +++ b/gripper_controllers/doc/userdoc.rst @@ -5,10 +5,23 @@ Gripper Action Controller -------------------------------- -Controller for executing a gripper command action for simple single-dof grippers. +Controllers for executing a gripper command action for simple single-dof grippers: + +- ``position_controllers/GripperActionController`` +- ``effort_controllers/GripperActionController`` Parameters ^^^^^^^^^^^ -This controller uses the `generate_parameter_library `_ to handle its parameters. +These controllers use the `generate_parameter_library `_ to handle its parameters. The parameter `definition file located in the src folder `_ contains descriptions for all the parameters used by the controller. + +List of parameters +========================= .. generate_parameter_library_details:: ../src/gripper_action_controller_parameters.yaml + + +An example parameter file +========================= + +.. generate_parameter_library_default:: + ../src/gripper_action_controller_parameters.yaml diff --git a/imu_sensor_broadcaster/doc/userdoc.rst b/imu_sensor_broadcaster/doc/userdoc.rst index 3b8ae172db..09b51a7ecb 100644 --- a/imu_sensor_broadcaster/doc/userdoc.rst +++ b/imu_sensor_broadcaster/doc/userdoc.rst @@ -11,6 +11,17 @@ The controller is a wrapper around ``IMUSensor`` semantic component (see ``contr Parameters ^^^^^^^^^^^ -This controller uses the `generate_parameter_library `_ to handle its parameters. +This controller uses the `generate_parameter_library `_ to handle its parameters. The parameter `definition file located in the src folder `_ contains descriptions for all the parameters used by the controller. +List of parameters +========================= .. generate_parameter_library_details:: ../src/imu_sensor_broadcaster_parameters.yaml + + +An example parameter file +========================= + +An example parameter file for this controller can be found in `the test directory `_: + +.. literalinclude:: ../test/imu_sensor_broadcaster_params.yaml + :language: yaml diff --git a/joint_state_broadcaster/doc/joint_state_broadcaster_parameter_context.yml b/joint_state_broadcaster/doc/joint_state_broadcaster_parameter_context.yml new file mode 100644 index 0000000000..c96f8301ae --- /dev/null +++ b/joint_state_broadcaster/doc/joint_state_broadcaster_parameter_context.yml @@ -0,0 +1,46 @@ +map_interface_to_joint_state: | + Optional parameter (map) providing mapping between custom interface names to standard fields in ``joint_states`` message. + Usecases: + + #. Hydraulics robots where feedback and commanded values often have an offset and reliance on open-loop control is common. + Typically one would map both values in separate interfaces in the framework. + To visualize those data multiple joint_state_broadcaster instances and robot_state_publishers would be used to visualize both values in RViz. + #. A robot provides multiple measuring techniques for its joint values which results in slightly different values. + Typically one would use separate interface for providing those values in the framework. + Using multiple joint_state_broadcaster instances we could publish and show both in RViz. + + Format (each line is optional): + + .. code-block:: yaml + + \tmap_interface_to_joint_state: + \t\tposition: + \t\tvelocity: + \t\teffort: + + + Examples: + + .. code-block:: yaml + + \tmap_interface_to_joint_state: + \t\tposition: kf_estimated_position + + + .. code-block:: yaml + + \tmap_interface_to_joint_state: + \t\tvelocity: derived_velocity + \t\teffort: derived_effort + + + .. code-block:: yaml + + \tmap_interface_to_joint_state: + \t\teffort: torque_sensor + + + .. code-block:: yaml + + \tmap_interface_to_joint_state: + \t\teffort: current_sensor diff --git a/joint_state_broadcaster/doc/userdoc.rst b/joint_state_broadcaster/doc/userdoc.rst index c9164ec723..c7bf4fa9a1 100644 --- a/joint_state_broadcaster/doc/userdoc.rst +++ b/joint_state_broadcaster/doc/userdoc.rst @@ -22,70 +22,19 @@ If none of the requested interface are not defined, the controller returns error Parameters ---------- +This controller uses the `generate_parameter_library `_ to handle its parameters. The parameter `definition file located in the src folder `_ contains descriptions for all the parameters used by the controller. -use_local_topics - Optional parameter (boolean; default: ``False``) defining if ``joint_states`` and ``dynamic_joint_states`` messages should be published into local namespace, e.g., ``/my_state_broadcaster/joint_states``. +List of parameters +,,,,,,,,,,,,,,,,,, -joints - Optional parameter (string array) to support broadcasting of only specific joints and interfaces. - It has to be used in combination with the ``interfaces`` parameter. - Joint state broadcaster asks for access to all defined interfaces on all defined joints. +.. generate_parameter_library_details:: + ../src/joint_state_broadcaster_parameters.yaml + joint_state_broadcaster_parameter_context.yml -interfaces - Optional parameter (string array) to support broadcasting of only specific joints and interfaces. - It has to be used in combination with the ``joints`` parameter. +An example parameter file +,,,,,,,,,,,,,,,,,,,,,,,,, - -extra_joints - Optional parameter (string array) with names of extra joints to be added to ``joint_states`` and ``dynamic_joint_states`` with state set to 0. - - -map_interface_to_joint_state - Optional parameter (map) providing mapping between custom interface names to standard fields in ``joint_states`` message. - Usecases: - - 1. Hydraulics robots where feedback and commanded values often have an offset and reliance on open-loop control is common. - Typically one would map both values in separate interfaces in the framework. - To visualize those data multiple joint_state_broadcaster instances and robot_state_publishers would be used to visualize both values in RViz. - - 1. A robot provides multiple measuring techniques for its joint values which results in slightly different values. - Typically one would use separate interface for providing those values in the framework. - Using multiple joint_state_broadcaster instances we could publish and show both in RViz. - - Format (each line is optional): - - .. code-block:: yaml - - map_interface_to_joint_state: - position: - velocity: - effort: - - - Examples: - - .. code-block:: yaml - - map_interface_to_joint_state: - position: kf_estimated_position - - - .. code-block:: yaml - - map_interface_to_joint_state: - velocity: derived_velocity - effort: derived_effort - - - .. code-block:: yaml - - map_interface_to_joint_state: - effort: torque_sensor - - - .. code-block:: yaml - - map_interface_to_joint_state: - effort: current_sensor +.. generate_parameter_library_default:: + ../src/joint_state_broadcaster_parameters.yaml diff --git a/joint_state_broadcaster/src/joint_state_broadcaster_parameters.yaml b/joint_state_broadcaster/src/joint_state_broadcaster_parameters.yaml index ba0d4f0051..8f0d4da6c5 100644 --- a/joint_state_broadcaster/src/joint_state_broadcaster_parameters.yaml +++ b/joint_state_broadcaster/src/joint_state_broadcaster_parameters.yaml @@ -2,18 +2,29 @@ joint_state_broadcaster: use_local_topics: { type: bool, default_value: false, + description: "Defining if ``joint_states`` and ``dynamic_joint_states`` messages should be published into local namespace, e.g., ``/my_state_broadcaster/joint_states``." } joints: { type: string_array, default_value: [], + description: "Parameter to support broadcasting of only specific joints and interfaces. + It has to be used in combination with the ``interfaces`` parameter. + If either ``joints`` or ``interfaces`` is left empty, all available state interfaces will be + published. + Joint state broadcaster asks for access to all defined interfaces on all defined joints." } extra_joints: { type: string_array, default_value: [], + description: "Names of extra joints to be added to ``joint_states`` and ``dynamic_joint_states`` with state set to 0." } interfaces: { type: string_array, default_value: [], + description: "Parameter to support broadcasting of only specific joints and interfaces. + It has to be used in combination with the ``joints`` parameter. + If either ``joints`` or ``interfaces`` is left empty, all available state interfaces will be + published." } map_interface_to_joint_state: position: { diff --git a/joint_trajectory_controller/doc/parameters.rst b/joint_trajectory_controller/doc/parameters.rst index 8ad2b406d6..dbb50fcbeb 100644 --- a/joint_trajectory_controller/doc/parameters.rst +++ b/joint_trajectory_controller/doc/parameters.rst @@ -5,146 +5,18 @@ Details about parameters ^^^^^^^^^^^^^^^^^^^^^^^^ -joints (list(string)) - Joint names to control and listen to. +This controller uses the `generate_parameter_library `_ to handle its parameters. The parameter `definition file located in the src folder `_ contains descriptions for all the parameters used by the controller. -command_joints (list(string)) - Joint names to control. This parameters is used if JTC is used in a controller chain where command and state interfaces don't have same names. -command_interface (list(string)) - Command interfaces provided by the hardware interface for all joints. +List of parameters +========================= - Values: [position | velocity | acceleration] (multiple allowed) +.. generate_parameter_library_details:: + ../src/joint_trajectory_controller_parameters.yaml + parameters_context.yaml -state_interfaces (list(string)) - State interfaces provided by the hardware for all joints. +An example parameter file +========================= - Values: position (mandatory) [velocity, [acceleration]]. - Acceleration interface can only be used in combination with position and velocity. - -action_monitor_rate (double) - Rate to monitor status changes when the controller is executing action (control_msgs::action::FollowJointTrajectory). - - Default: 20.0 - -allow_partial_joints_goal (boolean) - Allow joint goals defining trajectory for only some joints. - - Default: false - -allow_integration_in_goal_trajectories (boolean) - Allow integration in goal trajectories to accept goals without position or velocity specified - - Default: false - -interpolation_method (string) - The type of interpolation to use, if any. Can be "splines" or "none". - - Default: splines - -open_loop_control (boolean) - Use controller in open-loop control mode: - - * The controller ignores the states provided by hardware interface but using last commands as states for starting the trajectory interpolation. - * It deactivates the feedback control, see the ``gains`` structure. - - This is useful if hardware states are not following commands, i.e., an offset between those (typical for hydraulic manipulators). - - .. Note:: - If this flag is set, the controller tries to read the values from the command interfaces on activation. - If they have real numeric values, those will be used instead of state interfaces. - Therefore it is important set command interfaces to NaN (i.e., ``std::numeric_limits::quiet_NaN()``) or state values when the hardware is started. - - Default: false - -start_with_holding (bool) - If true, start with holding position after activation. Otherwise, no command will be sent until - the first trajectory is received. - - Default: true - -allow_nonzero_velocity_at_trajectory_end (boolean) - If false, the last velocity point has to be zero or the goal will be rejected. - - Default: false - -cmd_timeout (double) - Timeout after which the input command is considered stale. - Timeout is counted from the end of the trajectory (the last point). - ``cmd_timeout`` must be greater than ``constraints.goal_time``, - otherwise ignored. - - If zero, timeout is deactivated" - - Default: 0.0 - -constraints (structure) - Default values for tolerances if no explicit values are states in JointTrajectory message. - -constraints.stopped_velocity_tolerance (double) - Default value for end velocity deviation. - - Default: 0.01 - -constraints.goal_time (double) - Maximally allowed tolerance for not reaching the end of the trajectory in a predefined time. - If set to zero, the controller will wait a potentially infinite amount of time. - - Default: 0.0 (not checked) - -constraints..trajectory (double) - Maximally allowed deviation from the target trajectory for a given joint. - - Default: 0.0 (tolerance is not enforced) - -constraints..goal (double) - Maximally allowed deviation from the goal (end of the trajectory) for a given joint. - - Default: 0.0 (tolerance is not enforced) - -gains (structure) - Only relevant, if ``open_loop_control`` is not set. - - If ``velocity`` is the only command interface for all joints or an ``effort`` command interface is configured, PID controllers are used for every joint. - This structure contains the controller gains for every joint with the control law - - .. math:: - - u = k_{ff} v_d + k_p e + k_i \sum e dt + k_d (v_d - v) - - with the desired velocity :math:`v_d`, the measured velocity :math:`v`, the position error :math:`e` (definition see ``angle_wraparound`` below), - the controller period :math:`dt`, and the ``velocity`` or ``effort`` manipulated variable (control variable) :math:`u`, respectively. - -gains..p (double) - Proportional gain :math:`k_p` for PID - - Default: 0.0 - -gains..i (double) - Integral gain :math:`k_i` for PID - - Default: 0.0 - -gains..d (double) - Derivative gain :math:`k_d` for PID - - Default: 0.0 - -gains..i_clamp (double) - Integral clamp. Symmetrical in both positive and negative direction. - - Default: 0.0 - -gains..ff_velocity_scale (double) - Feed-forward scaling :math:`k_{ff}` of velocity - - Default: 0.0 - -gains..angle_wraparound (bool) - For joints that wrap around (without end stop, ie. are continuous), - where the shortest rotation to the target position is the desired motion. - If true, the position error :math:`e = normalize(s_d - s)` is normalized between :math:`-\pi, \pi`. - Otherwise :math:`e = s_d - s` is used, with the desired position :math:`s_d` and the measured - position :math:`s` from the state interface. - - Default: false +.. generate_parameter_library_default:: + ../src/joint_trajectory_controller_parameters.yaml diff --git a/joint_trajectory_controller/doc/parameters_context.yaml b/joint_trajectory_controller/doc/parameters_context.yaml new file mode 100644 index 0000000000..2ffe8aed36 --- /dev/null +++ b/joint_trajectory_controller/doc/parameters_context.yaml @@ -0,0 +1,13 @@ +constraints: + Default values for tolerances if no explicit values are set in the ``JointTrajectory`` message. + +gains: | + Only relevant, if ``open_loop_control`` is not set. + + If ``velocity`` is the only command interface for all joints or an ``effort`` command interface is configured, PID controllers are used for every joint. + This structure contains the controller gains for every joint with the control law + + .. math:: u = k_{ff} v_d + k_p e + k_i \sum e dt + k_d (v_d - v) + + with the desired velocity :math:`v_d`, the measured velocity :math:`v`, the position error :math:`e` (definition see ``angle_wraparound`` below), + the controller period :math:`dt`, and the ``velocity`` or ``effort`` manipulated variable (control variable) :math:`u`, respectively. diff --git a/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml b/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml index 4981489d36..ded5bb7ca3 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml +++ b/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml @@ -2,7 +2,7 @@ joint_trajectory_controller: joints: { type: string_array, default_value: [], - description: "Names of joints used by the controller", + description: "Joint names to control and listen to", read_only: true, validation: { unique<>: null, @@ -11,7 +11,7 @@ joint_trajectory_controller: command_joints: { type: string_array, default_value: [], - description: "Names of the commanding joints used by the controller", + description: "Joint names to control. This parameters is used if JTC is used in a controller chain where command and state interfaces don't have same names.", read_only: true, validation: { unique<>: null, @@ -20,7 +20,7 @@ joint_trajectory_controller: command_interfaces: { type: string_array, default_value: [], - description: "Names of command interfaces to claim", + description: "Command interfaces provided by the hardware interface for all joints", read_only: true, validation: { unique<>: null, @@ -31,7 +31,7 @@ joint_trajectory_controller: state_interfaces: { type: string_array, default_value: [], - description: "Names of state interfaces to claim", + description: "State interfaces provided by the hardware for all joints.", read_only: true, validation: { unique<>: null, @@ -42,12 +42,21 @@ joint_trajectory_controller: allow_partial_joints_goal: { type: bool, default_value: false, - description: "Goals with partial set of joints are allowed", + description: "Allow joint goals defining trajectory for only some joints.", } open_loop_control: { type: bool, default_value: false, - description: "Run the controller in open-loop, i.e., read hardware states only when starting controller. This is useful when robot is not exactly following the commanded trajectory.", + description: "Use controller in open-loop control mode + \n\n + * The controller ignores the states provided by hardware interface but using last commands as states for starting the trajectory interpolation.\n + * It deactivates the feedback control, see the ``gains`` structure. + \n\n + This is useful if hardware states are not following commands, i.e., an offset between those (typical for hydraulic manipulators). + \n\n + If this flag is set, the controller tries to read the values from the command interfaces on activation. + If they have real numeric values, those will be used instead of state interfaces. + Therefore it is important set command interfaces to NaN (i.e., ``std::numeric_limits::quiet_NaN()``) or state values when the hardware is started.\n", read_only: true, } allow_integration_in_goal_trajectories: { @@ -58,7 +67,7 @@ joint_trajectory_controller: action_monitor_rate: { type: double, default_value: 20.0, - description: "Rate status changes will be monitored", + description: "Rate to monitor status changes when the controller is executing action (control_msgs::action::FollowJointTrajectory)", read_only: true, validation: { gt_eq: [0.1] @@ -83,7 +92,7 @@ joint_trajectory_controller: default_value: 0.0, # seconds description: "Timeout after which the input command is considered stale. Timeout is counted from the end of the trajectory (the last point). - cmd_timeout must be greater than constraints.goal_time, otherwise ignored. + ``cmd_timeout`` must be greater than ``constraints.goal_time``, otherwise ignored. If zero, timeout is deactivated", } gains: @@ -91,17 +100,17 @@ joint_trajectory_controller: p: { type: double, default_value: 0.0, - description: "Proportional gain for PID" + description: "Proportional gain :math:`k_p` for PID" } i: { type: double, default_value: 0.0, - description: "Integral gain for PID" + description: "Integral gain :math:`k_i` for PID" } d: { type: double, default_value: 0.0, - description: "Derivative gain for PID" + description: "Derivative gain :math:`k_d` for PID" } i_clamp: { type: double, @@ -111,13 +120,16 @@ joint_trajectory_controller: ff_velocity_scale: { type: double, default_value: 0.0, - description: "Feed-forward scaling of velocity." + description: "Feed-forward scaling :math:`k_{ff}` of velocity" } angle_wraparound: { type: bool, default_value: false, - description: "For joints that wrap around (ie. are continuous). - Normalizes position-error to -pi to pi." + description: 'For joints that wrap around (without end stop, ie. are continuous), + where the shortest rotation to the target position is the desired motion. + If true, the position error :math:`e = normalize(s_d - s)` is normalized between :math:`-\pi, \pi`. + Otherwise :math:`e = s_d - s` is used, with the desired position :math:`s_d` and the measured + position :math:`s` from the state interface.' } constraints: stopped_velocity_tolerance: { diff --git a/range_sensor_broadcaster/doc/userdoc.rst b/range_sensor_broadcaster/doc/userdoc.rst index e35bec67ad..39fb98b3aa 100644 --- a/range_sensor_broadcaster/doc/userdoc.rst +++ b/range_sensor_broadcaster/doc/userdoc.rst @@ -11,5 +11,21 @@ The controller is a wrapper around ``RangeSensor`` semantic component (see ``con Parameters ^^^^^^^^^^^ +The Range Sensor Broadcaster uses the `generate_parameter_library `_ to handle its parameters. The parameter `definition file located in the src folder `_ contains descriptions for all the parameters used by the controller. + +List of parameters +========================= .. generate_parameter_library_details:: ../src/range_sensor_broadcaster_parameters.yaml + + +An example parameter file +========================= + +.. generate_parameter_library_default:: + ../src/range_sensor_broadcaster_parameters.yaml + +An example parameter file for this controller can be found in `the test directory `_: + +.. literalinclude:: ../test/range_sensor_broadcaster_params.yaml + :language: yaml From f2f36c0c65607659cb5961f1354a64b3d1a6866c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Wed, 31 Jan 2024 21:40:02 +0100 Subject: [PATCH 205/238] Add tests for `interface_configuration_type` consistently (#899) --- .../test_ackermann_steering_controller.cpp | 28 +++++++------- .../test_ackermann_steering_controller.hpp | 2 +- ...kermann_steering_controller_preceeding.cpp | 28 +++++++------- .../test/test_admittance_controller.cpp | 3 ++ .../test/test_bicycle_steering_controller.cpp | 22 +++++------ .../test/test_bicycle_steering_controller.hpp | 2 +- ...bicycle_steering_controller_preceeding.cpp | 22 +++++------ .../test/test_diff_drive_controller.cpp | 12 +++--- .../test_force_torque_sensor_broadcaster.cpp | 6 +++ .../test/test_forward_command_controller.cpp | 9 +++++ ...i_interface_forward_command_controller.cpp | 2 + .../test/test_imu_sensor_broadcaster.cpp | 6 +++ .../test/test_joint_state_broadcaster.cpp | 18 +++++++++ .../test/test_trajectory_controller.cpp | 12 +++--- pid_controller/test/test_pid_controller.cpp | 29 ++++++++------- .../test/test_pid_controller_preceding.cpp | 29 ++++++++------- .../test/test_range_sensor_broadcaster.cpp | 4 ++ .../test_steering_controllers_library.cpp | 28 +++++++------- .../test_steering_controllers_library.hpp | 2 +- .../test_tricycle_steering_controller.cpp | 37 ++++++++++--------- .../test_tricycle_steering_controller.hpp | 2 +- ...ricycle_steering_controller_preceeding.cpp | 34 +++++++++-------- 22 files changed, 198 insertions(+), 139 deletions(-) diff --git a/ackermann_steering_controller/test/test_ackermann_steering_controller.cpp b/ackermann_steering_controller/test/test_ackermann_steering_controller.cpp index 480e90e166..ef5454a16c 100644 --- a/ackermann_steering_controller/test/test_ackermann_steering_controller.cpp +++ b/ackermann_steering_controller/test/test_ackermann_steering_controller.cpp @@ -46,41 +46,43 @@ TEST_F(AckermannSteeringControllerTest, all_parameters_set_configure_success) ASSERT_EQ(controller_->ackermann_params_.rear_wheel_track, rear_wheel_track_); } -TEST_F(AckermannSteeringControllerTest, check_exported_intefaces) +TEST_F(AckermannSteeringControllerTest, check_exported_interfaces) { SetUpController(); ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); - auto command_intefaces = controller_->command_interface_configuration(); - ASSERT_EQ(command_intefaces.names.size(), joint_command_values_.size()); + auto cmd_if_conf = controller_->command_interface_configuration(); + ASSERT_EQ(cmd_if_conf.names.size(), joint_command_values_.size()); EXPECT_EQ( - command_intefaces.names[CMD_TRACTION_RIGHT_WHEEL], + cmd_if_conf.names[CMD_TRACTION_RIGHT_WHEEL], rear_wheels_names_[0] + "/" + traction_interface_name_); EXPECT_EQ( - command_intefaces.names[CMD_TRACTION_LEFT_WHEEL], + cmd_if_conf.names[CMD_TRACTION_LEFT_WHEEL], rear_wheels_names_[1] + "/" + traction_interface_name_); EXPECT_EQ( - command_intefaces.names[CMD_STEER_RIGHT_WHEEL], + cmd_if_conf.names[CMD_STEER_RIGHT_WHEEL], front_wheels_names_[0] + "/" + steering_interface_name_); EXPECT_EQ( - command_intefaces.names[CMD_STEER_LEFT_WHEEL], + cmd_if_conf.names[CMD_STEER_LEFT_WHEEL], front_wheels_names_[1] + "/" + steering_interface_name_); + EXPECT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); - auto state_intefaces = controller_->state_interface_configuration(); - ASSERT_EQ(state_intefaces.names.size(), joint_state_values_.size()); + auto state_if_conf = controller_->state_interface_configuration(); + ASSERT_EQ(state_if_conf.names.size(), joint_state_values_.size()); EXPECT_EQ( - state_intefaces.names[STATE_TRACTION_RIGHT_WHEEL], + state_if_conf.names[STATE_TRACTION_RIGHT_WHEEL], controller_->rear_wheels_state_names_[0] + "/" + traction_interface_name_); EXPECT_EQ( - state_intefaces.names[STATE_TRACTION_LEFT_WHEEL], + state_if_conf.names[STATE_TRACTION_LEFT_WHEEL], controller_->rear_wheels_state_names_[1] + "/" + traction_interface_name_); EXPECT_EQ( - state_intefaces.names[STATE_STEER_RIGHT_WHEEL], + state_if_conf.names[STATE_STEER_RIGHT_WHEEL], controller_->front_wheels_state_names_[0] + "/" + steering_interface_name_); EXPECT_EQ( - state_intefaces.names[STATE_STEER_LEFT_WHEEL], + state_if_conf.names[STATE_STEER_LEFT_WHEEL], controller_->front_wheels_state_names_[1] + "/" + steering_interface_name_); + EXPECT_EQ(state_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); // check ref itfsTIME auto reference_interfaces = controller_->export_reference_interfaces(); diff --git a/ackermann_steering_controller/test/test_ackermann_steering_controller.hpp b/ackermann_steering_controller/test/test_ackermann_steering_controller.hpp index a2849d5742..7c279d6323 100644 --- a/ackermann_steering_controller/test/test_ackermann_steering_controller.hpp +++ b/ackermann_steering_controller/test/test_ackermann_steering_controller.hpp @@ -62,7 +62,7 @@ class TestableAckermannSteeringController : public ackermann_steering_controller::AckermannSteeringController { FRIEND_TEST(AckermannSteeringControllerTest, all_parameters_set_configure_success); - FRIEND_TEST(AckermannSteeringControllerTest, check_exported_intefaces); + FRIEND_TEST(AckermannSteeringControllerTest, check_exported_interfaces); FRIEND_TEST(AckermannSteeringControllerTest, activate_success); FRIEND_TEST(AckermannSteeringControllerTest, update_success); FRIEND_TEST(AckermannSteeringControllerTest, deactivate_success); diff --git a/ackermann_steering_controller/test/test_ackermann_steering_controller_preceeding.cpp b/ackermann_steering_controller/test/test_ackermann_steering_controller_preceeding.cpp index 2d951588c5..1a16bed838 100644 --- a/ackermann_steering_controller/test/test_ackermann_steering_controller_preceeding.cpp +++ b/ackermann_steering_controller/test/test_ackermann_steering_controller_preceeding.cpp @@ -48,41 +48,43 @@ TEST_F(AckermannSteeringControllerTest, all_parameters_set_configure_success) ASSERT_EQ(controller_->ackermann_params_.rear_wheel_track, rear_wheel_track_); } -TEST_F(AckermannSteeringControllerTest, check_exported_intefaces) +TEST_F(AckermannSteeringControllerTest, check_exported_interfaces) { SetUpController(); ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); - auto command_intefaces = controller_->command_interface_configuration(); - ASSERT_EQ(command_intefaces.names.size(), joint_command_values_.size()); + auto cmd_if_conf = controller_->command_interface_configuration(); + ASSERT_EQ(cmd_if_conf.names.size(), joint_command_values_.size()); EXPECT_EQ( - command_intefaces.names[CMD_TRACTION_RIGHT_WHEEL], + cmd_if_conf.names[CMD_TRACTION_RIGHT_WHEEL], preceeding_prefix_ + "/" + rear_wheels_names_[0] + "/" + traction_interface_name_); EXPECT_EQ( - command_intefaces.names[CMD_TRACTION_LEFT_WHEEL], + cmd_if_conf.names[CMD_TRACTION_LEFT_WHEEL], preceeding_prefix_ + "/" + rear_wheels_names_[1] + "/" + traction_interface_name_); EXPECT_EQ( - command_intefaces.names[CMD_STEER_RIGHT_WHEEL], + cmd_if_conf.names[CMD_STEER_RIGHT_WHEEL], preceeding_prefix_ + "/" + front_wheels_names_[0] + "/" + steering_interface_name_); EXPECT_EQ( - command_intefaces.names[CMD_STEER_LEFT_WHEEL], + cmd_if_conf.names[CMD_STEER_LEFT_WHEEL], preceeding_prefix_ + "/" + front_wheels_names_[1] + "/" + steering_interface_name_); + EXPECT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); - auto state_intefaces = controller_->state_interface_configuration(); - ASSERT_EQ(state_intefaces.names.size(), joint_state_values_.size()); + auto state_if_conf = controller_->state_interface_configuration(); + ASSERT_EQ(state_if_conf.names.size(), joint_state_values_.size()); EXPECT_EQ( - state_intefaces.names[STATE_TRACTION_RIGHT_WHEEL], + state_if_conf.names[STATE_TRACTION_RIGHT_WHEEL], controller_->rear_wheels_state_names_[0] + "/" + traction_interface_name_); EXPECT_EQ( - state_intefaces.names[STATE_TRACTION_LEFT_WHEEL], + state_if_conf.names[STATE_TRACTION_LEFT_WHEEL], controller_->rear_wheels_state_names_[1] + "/" + traction_interface_name_); EXPECT_EQ( - state_intefaces.names[STATE_STEER_RIGHT_WHEEL], + state_if_conf.names[STATE_STEER_RIGHT_WHEEL], controller_->front_wheels_state_names_[0] + "/" + steering_interface_name_); EXPECT_EQ( - state_intefaces.names[STATE_STEER_LEFT_WHEEL], + state_if_conf.names[STATE_STEER_LEFT_WHEEL], controller_->front_wheels_state_names_[1] + "/" + steering_interface_name_); + EXPECT_EQ(state_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); // check ref itfs auto reference_interfaces = controller_->export_reference_interfaces(); diff --git a/admittance_controller/test/test_admittance_controller.cpp b/admittance_controller/test/test_admittance_controller.cpp index fe1d3214e0..6b03249df8 100644 --- a/admittance_controller/test/test_admittance_controller.cpp +++ b/admittance_controller/test/test_admittance_controller.cpp @@ -157,12 +157,15 @@ TEST_F(AdmittanceControllerTest, check_interfaces) auto command_interfaces = controller_->command_interface_configuration(); ASSERT_EQ(command_interfaces.names.size(), joint_command_values_.size()); + EXPECT_EQ( + command_interfaces.type, controller_interface::interface_configuration_type::INDIVIDUAL); ASSERT_EQ( controller_->command_interfaces_.size(), command_interface_types_.size() * joint_names_.size()); auto state_interfaces = controller_->state_interface_configuration(); ASSERT_EQ(state_interfaces.names.size(), joint_state_values_.size() + fts_state_values_.size()); + EXPECT_EQ(state_interfaces.type, controller_interface::interface_configuration_type::INDIVIDUAL); ASSERT_EQ( controller_->state_interfaces_.size(), diff --git a/bicycle_steering_controller/test/test_bicycle_steering_controller.cpp b/bicycle_steering_controller/test/test_bicycle_steering_controller.cpp index 06b0c7e846..3dcdc0b1db 100644 --- a/bicycle_steering_controller/test/test_bicycle_steering_controller.cpp +++ b/bicycle_steering_controller/test/test_bicycle_steering_controller.cpp @@ -44,29 +44,29 @@ TEST_F(BicycleSteeringControllerTest, all_parameters_set_configure_success) ASSERT_EQ(controller_->bicycle_params_.rear_wheel_radius, rear_wheels_radius_); } -TEST_F(BicycleSteeringControllerTest, check_exported_intefaces) +TEST_F(BicycleSteeringControllerTest, check_exported_interfaces) { SetUpController(); ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); - auto command_intefaces = controller_->command_interface_configuration(); - ASSERT_EQ(command_intefaces.names.size(), joint_command_values_.size()); + auto cmd_if_conf = controller_->command_interface_configuration(); + ASSERT_EQ(cmd_if_conf.names.size(), joint_command_values_.size()); EXPECT_EQ( - command_intefaces.names[CMD_TRACTION_WHEEL], - rear_wheels_names_[0] + "/" + traction_interface_name_); + cmd_if_conf.names[CMD_TRACTION_WHEEL], rear_wheels_names_[0] + "/" + traction_interface_name_); EXPECT_EQ( - command_intefaces.names[CMD_STEER_WHEEL], - front_wheels_names_[0] + "/" + steering_interface_name_); + cmd_if_conf.names[CMD_STEER_WHEEL], front_wheels_names_[0] + "/" + steering_interface_name_); + EXPECT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); - auto state_intefaces = controller_->state_interface_configuration(); - ASSERT_EQ(state_intefaces.names.size(), joint_state_values_.size()); + auto state_if_conf = controller_->state_interface_configuration(); + ASSERT_EQ(state_if_conf.names.size(), joint_state_values_.size()); EXPECT_EQ( - state_intefaces.names[STATE_TRACTION_WHEEL], + state_if_conf.names[STATE_TRACTION_WHEEL], controller_->rear_wheels_state_names_[0] + "/" + traction_interface_name_); EXPECT_EQ( - state_intefaces.names[STATE_STEER_AXIS], + state_if_conf.names[STATE_STEER_AXIS], controller_->front_wheels_state_names_[0] + "/" + steering_interface_name_); + EXPECT_EQ(state_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); // check ref itfsTIME auto reference_interfaces = controller_->export_reference_interfaces(); diff --git a/bicycle_steering_controller/test/test_bicycle_steering_controller.hpp b/bicycle_steering_controller/test/test_bicycle_steering_controller.hpp index 521506762b..6e84342bea 100644 --- a/bicycle_steering_controller/test/test_bicycle_steering_controller.hpp +++ b/bicycle_steering_controller/test/test_bicycle_steering_controller.hpp @@ -60,7 +60,7 @@ class TestableBicycleSteeringController : public bicycle_steering_controller::BicycleSteeringController { FRIEND_TEST(BicycleSteeringControllerTest, all_parameters_set_configure_success); - FRIEND_TEST(BicycleSteeringControllerTest, check_exported_intefaces); + FRIEND_TEST(BicycleSteeringControllerTest, check_exported_interfaces); FRIEND_TEST(BicycleSteeringControllerTest, activate_success); FRIEND_TEST(BicycleSteeringControllerTest, update_success); FRIEND_TEST(BicycleSteeringControllerTest, deactivate_success); diff --git a/bicycle_steering_controller/test/test_bicycle_steering_controller_preceeding.cpp b/bicycle_steering_controller/test/test_bicycle_steering_controller_preceeding.cpp index 875910ba23..bc3a182753 100644 --- a/bicycle_steering_controller/test/test_bicycle_steering_controller_preceeding.cpp +++ b/bicycle_steering_controller/test/test_bicycle_steering_controller_preceeding.cpp @@ -46,31 +46,31 @@ TEST_F(BicycleSteeringControllerTest, all_parameters_set_configure_success) ASSERT_EQ(controller_->bicycle_params_.rear_wheel_radius, rear_wheels_radius_); } -TEST_F(BicycleSteeringControllerTest, check_exported_intefaces) +TEST_F(BicycleSteeringControllerTest, check_exported_interfaces) { SetUpController(); ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); - auto command_intefaces = controller_->command_interface_configuration(); - ASSERT_EQ(command_intefaces.names.size(), joint_command_values_.size()); + auto cmd_if_conf = controller_->command_interface_configuration(); + ASSERT_EQ(cmd_if_conf.names.size(), joint_command_values_.size()); EXPECT_EQ( - command_intefaces.names[CMD_TRACTION_WHEEL], + cmd_if_conf.names[CMD_TRACTION_WHEEL], preceeding_prefix_ + "/" + rear_wheels_names_[0] + "/" + traction_interface_name_); - EXPECT_EQ( - command_intefaces.names[CMD_STEER_WHEEL], + cmd_if_conf.names[CMD_STEER_WHEEL], preceeding_prefix_ + "/" + front_wheels_names_[0] + "/" + steering_interface_name_); + EXPECT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); - auto state_intefaces = controller_->state_interface_configuration(); - ASSERT_EQ(state_intefaces.names.size(), joint_state_values_.size()); - + auto state_if_conf = controller_->state_interface_configuration(); + ASSERT_EQ(state_if_conf.names.size(), joint_state_values_.size()); EXPECT_EQ( - state_intefaces.names[STATE_TRACTION_WHEEL], + state_if_conf.names[STATE_TRACTION_WHEEL], controller_->rear_wheels_state_names_[0] + "/" + traction_interface_name_); EXPECT_EQ( - state_intefaces.names[STATE_STEER_AXIS], + state_if_conf.names[STATE_STEER_AXIS], controller_->front_wheels_state_names_[0] + "/" + steering_interface_name_); + EXPECT_EQ(state_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); // check ref itfs auto reference_interfaces = controller_->export_reference_interfaces(); diff --git a/diff_drive_controller/test/test_diff_drive_controller.cpp b/diff_drive_controller/test/test_diff_drive_controller.cpp index eb970d34a3..4ad293298f 100644 --- a/diff_drive_controller/test/test_diff_drive_controller.cpp +++ b/diff_drive_controller/test/test_diff_drive_controller.cpp @@ -249,12 +249,12 @@ TEST_F(TestDiffDriveController, configure_succeeds_when_wheels_are_specified) ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), CallbackReturn::SUCCESS); - ASSERT_THAT( - controller_->state_interface_configuration().names, - SizeIs(left_wheel_names.size() + right_wheel_names.size())); - ASSERT_THAT( - controller_->command_interface_configuration().names, - SizeIs(left_wheel_names.size() + right_wheel_names.size())); + auto state_if_conf = controller_->state_interface_configuration(); + ASSERT_THAT(state_if_conf.names, SizeIs(left_wheel_names.size() + right_wheel_names.size())); + EXPECT_EQ(state_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); + auto cmd_if_conf = controller_->command_interface_configuration(); + ASSERT_THAT(cmd_if_conf.names, SizeIs(left_wheel_names.size() + right_wheel_names.size())); + EXPECT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); } TEST_F(TestDiffDriveController, configure_succeeds_tf_test_prefix_false_no_namespace) diff --git a/force_torque_sensor_broadcaster/test/test_force_torque_sensor_broadcaster.cpp b/force_torque_sensor_broadcaster/test/test_force_torque_sensor_broadcaster.cpp index f06252d83a..8b994307fa 100644 --- a/force_torque_sensor_broadcaster/test/test_force_torque_sensor_broadcaster.cpp +++ b/force_torque_sensor_broadcaster/test/test_force_torque_sensor_broadcaster.cpp @@ -162,8 +162,10 @@ TEST_F(ForceTorqueSensorBroadcasterTest, SensorName_Configure_Success) // check interface configuration auto cmd_if_conf = fts_broadcaster_->command_interface_configuration(); ASSERT_THAT(cmd_if_conf.names, IsEmpty()); + ASSERT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::NONE); auto state_if_conf = fts_broadcaster_->state_interface_configuration(); ASSERT_THAT(state_if_conf.names, SizeIs(6lu)); + ASSERT_EQ(state_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); } TEST_F(ForceTorqueSensorBroadcasterTest, InterfaceNames_Configure_Success) @@ -196,8 +198,10 @@ TEST_F(ForceTorqueSensorBroadcasterTest, SensorName_ActivateDeactivate_Success) // check interface configuration auto cmd_if_conf = fts_broadcaster_->command_interface_configuration(); ASSERT_THAT(cmd_if_conf.names, IsEmpty()); + ASSERT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::NONE); auto state_if_conf = fts_broadcaster_->state_interface_configuration(); ASSERT_THAT(state_if_conf.names, SizeIs(6lu)); + ASSERT_EQ(state_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); // deactivate passed ASSERT_EQ(fts_broadcaster_->on_deactivate(rclcpp_lifecycle::State()), NODE_SUCCESS); @@ -205,8 +209,10 @@ TEST_F(ForceTorqueSensorBroadcasterTest, SensorName_ActivateDeactivate_Success) // check interface configuration cmd_if_conf = fts_broadcaster_->command_interface_configuration(); ASSERT_THAT(cmd_if_conf.names, IsEmpty()); + ASSERT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::NONE); state_if_conf = fts_broadcaster_->state_interface_configuration(); ASSERT_THAT(state_if_conf.names, SizeIs(6lu)); // did not change + ASSERT_EQ(state_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); } TEST_F(ForceTorqueSensorBroadcasterTest, SensorName_Update_Success) diff --git a/forward_command_controller/test/test_forward_command_controller.cpp b/forward_command_controller/test/test_forward_command_controller.cpp index 236cb14edd..937144b48c 100644 --- a/forward_command_controller/test/test_forward_command_controller.cpp +++ b/forward_command_controller/test/test_forward_command_controller.cpp @@ -137,6 +137,7 @@ TEST_F(ForwardCommandControllerTest, ConfigureParamsSuccess) ASSERT_THAT(cmd_if_conf.names, SizeIs(2lu)); auto state_if_conf = controller_->state_interface_configuration(); ASSERT_THAT(state_if_conf.names, IsEmpty()); + ASSERT_EQ(state_if_conf.type, controller_interface::interface_configuration_type::NONE); } TEST_F(ForwardCommandControllerTest, ActivateWithWrongJointsNamesFails) @@ -189,6 +190,7 @@ TEST_F(ForwardCommandControllerTest, ActivateSuccess) ASSERT_THAT(cmd_if_conf.names, SizeIs(joint_names_.size())); auto state_if_conf = controller_->state_interface_configuration(); ASSERT_THAT(state_if_conf.names, IsEmpty()); + ASSERT_EQ(state_if_conf.type, controller_interface::interface_configuration_type::NONE); ASSERT_EQ( controller_->on_activate(rclcpp_lifecycle::State()), @@ -197,8 +199,10 @@ TEST_F(ForwardCommandControllerTest, ActivateSuccess) // check interface configuration cmd_if_conf = controller_->command_interface_configuration(); ASSERT_THAT(cmd_if_conf.names, SizeIs(joint_names_.size())); + EXPECT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); state_if_conf = controller_->state_interface_configuration(); ASSERT_THAT(state_if_conf.names, IsEmpty()); + ASSERT_EQ(state_if_conf.type, controller_interface::interface_configuration_type::NONE); } TEST_F(ForwardCommandControllerTest, CommandSuccessTest) @@ -352,6 +356,7 @@ TEST_F(ForwardCommandControllerTest, ActivateDeactivateCommandsResetSuccess) EXPECT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); auto state_if_conf = controller_->state_interface_configuration(); ASSERT_THAT(state_if_conf.names, IsEmpty()); + EXPECT_EQ(state_if_conf.type, controller_interface::interface_configuration_type::NONE); node_state = controller_->get_node()->activate(); ASSERT_EQ(node_state.id(), lifecycle_msgs::msg::State::PRIMARY_STATE_ACTIVE); @@ -359,8 +364,10 @@ TEST_F(ForwardCommandControllerTest, ActivateDeactivateCommandsResetSuccess) // check interface configuration cmd_if_conf = controller_->command_interface_configuration(); ASSERT_THAT(cmd_if_conf.names, SizeIs(joint_names_.size())); + EXPECT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); state_if_conf = controller_->state_interface_configuration(); ASSERT_THAT(state_if_conf.names, IsEmpty()); + EXPECT_EQ(state_if_conf.type, controller_interface::interface_configuration_type::NONE); auto command_msg = std::make_shared(); command_msg->data = {10.0, 20.0, 30.0}; @@ -383,8 +390,10 @@ TEST_F(ForwardCommandControllerTest, ActivateDeactivateCommandsResetSuccess) // check interface configuration cmd_if_conf = controller_->command_interface_configuration(); ASSERT_THAT(cmd_if_conf.names, SizeIs(joint_names_.size())); // did not change + EXPECT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); state_if_conf = controller_->state_interface_configuration(); ASSERT_THAT(state_if_conf.names, IsEmpty()); + EXPECT_EQ(state_if_conf.type, controller_interface::interface_configuration_type::NONE); // command ptr should be reset (nullptr) after deactivation - same check as in `update` ASSERT_FALSE( diff --git a/forward_command_controller/test/test_multi_interface_forward_command_controller.cpp b/forward_command_controller/test/test_multi_interface_forward_command_controller.cpp index 2d3b61e211..f8f073c103 100644 --- a/forward_command_controller/test/test_multi_interface_forward_command_controller.cpp +++ b/forward_command_controller/test/test_multi_interface_forward_command_controller.cpp @@ -297,6 +297,7 @@ TEST_F(MultiInterfaceForwardCommandControllerTest, ActivateDeactivateCommandsRes EXPECT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); auto state_if_conf = controller_->state_interface_configuration(); ASSERT_THAT(state_if_conf.names, IsEmpty()); + EXPECT_EQ(state_if_conf.type, controller_interface::interface_configuration_type::NONE); // send command auto command_ptr = std::make_shared(); @@ -322,6 +323,7 @@ TEST_F(MultiInterfaceForwardCommandControllerTest, ActivateDeactivateCommandsRes EXPECT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); state_if_conf = controller_->state_interface_configuration(); ASSERT_THAT(state_if_conf.names, IsEmpty()); + EXPECT_EQ(state_if_conf.type, controller_interface::interface_configuration_type::NONE); // command ptr should be reset (nullptr) after deactivation - same check as in `update` ASSERT_FALSE( diff --git a/imu_sensor_broadcaster/test/test_imu_sensor_broadcaster.cpp b/imu_sensor_broadcaster/test/test_imu_sensor_broadcaster.cpp index 83edc044d3..62179a99ff 100644 --- a/imu_sensor_broadcaster/test/test_imu_sensor_broadcaster.cpp +++ b/imu_sensor_broadcaster/test/test_imu_sensor_broadcaster.cpp @@ -119,8 +119,10 @@ TEST_F(IMUSensorBroadcasterTest, SensorName_Configure_Success) // check interface configuration auto cmd_if_conf = imu_broadcaster_->command_interface_configuration(); ASSERT_THAT(cmd_if_conf.names, IsEmpty()); + EXPECT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::NONE); auto state_if_conf = imu_broadcaster_->state_interface_configuration(); ASSERT_THAT(state_if_conf.names, SizeIs(10lu)); + EXPECT_EQ(state_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); } TEST_F(IMUSensorBroadcasterTest, SensorName_Activate_Success) @@ -138,8 +140,10 @@ TEST_F(IMUSensorBroadcasterTest, SensorName_Activate_Success) // check interface configuration auto cmd_if_conf = imu_broadcaster_->command_interface_configuration(); ASSERT_THAT(cmd_if_conf.names, IsEmpty()); + EXPECT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::NONE); auto state_if_conf = imu_broadcaster_->state_interface_configuration(); ASSERT_THAT(state_if_conf.names, SizeIs(10lu)); + EXPECT_EQ(state_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); // deactivate passed ASSERT_EQ(imu_broadcaster_->on_deactivate(rclcpp_lifecycle::State()), NODE_SUCCESS); @@ -147,8 +151,10 @@ TEST_F(IMUSensorBroadcasterTest, SensorName_Activate_Success) // check interface configuration cmd_if_conf = imu_broadcaster_->command_interface_configuration(); ASSERT_THAT(cmd_if_conf.names, IsEmpty()); + EXPECT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::NONE); state_if_conf = imu_broadcaster_->state_interface_configuration(); ASSERT_THAT(state_if_conf.names, SizeIs(10lu)); // did not change + EXPECT_EQ(state_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); } TEST_F(IMUSensorBroadcasterTest, SensorName_Update_Success) diff --git a/joint_state_broadcaster/test/test_joint_state_broadcaster.cpp b/joint_state_broadcaster/test/test_joint_state_broadcaster.cpp index 3e45740bbc..c10f51aaa2 100644 --- a/joint_state_broadcaster/test/test_joint_state_broadcaster.cpp +++ b/joint_state_broadcaster/test/test_joint_state_broadcaster.cpp @@ -180,8 +180,10 @@ TEST_F(JointStateBroadcasterTest, ActivateEmptyTest) // check interface configuration auto cmd_if_conf = state_broadcaster_->command_interface_configuration(); ASSERT_THAT(cmd_if_conf.names, IsEmpty()); + EXPECT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::NONE); auto state_if_conf = state_broadcaster_->state_interface_configuration(); ASSERT_THAT(state_if_conf.names, IsEmpty()); + EXPECT_EQ(state_if_conf.type, controller_interface::interface_configuration_type::ALL); // publishers initialized ASSERT_TRUE(state_broadcaster_->realtime_joint_state_publisher_); @@ -227,8 +229,10 @@ TEST_F(JointStateBroadcasterTest, ActivateTestWithoutJointsParameter) // check interface configuration auto cmd_if_conf = state_broadcaster_->command_interface_configuration(); ASSERT_THAT(cmd_if_conf.names, IsEmpty()); + EXPECT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::NONE); auto state_if_conf = state_broadcaster_->state_interface_configuration(); ASSERT_THAT(state_if_conf.names, IsEmpty()); + EXPECT_EQ(state_if_conf.type, controller_interface::interface_configuration_type::ALL); // publishers initialized ASSERT_TRUE(state_broadcaster_->realtime_joint_state_publisher_); @@ -274,8 +278,10 @@ TEST_F(JointStateBroadcasterTest, ActivateTestWithoutInterfacesParameter) // check interface configuration auto cmd_if_conf = state_broadcaster_->command_interface_configuration(); ASSERT_THAT(cmd_if_conf.names, IsEmpty()); + EXPECT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::NONE); auto state_if_conf = state_broadcaster_->state_interface_configuration(); ASSERT_THAT(state_if_conf.names, IsEmpty()); + EXPECT_EQ(state_if_conf.type, controller_interface::interface_configuration_type::ALL); // publishers initialized ASSERT_TRUE(state_broadcaster_->realtime_joint_state_publisher_); @@ -321,8 +327,10 @@ TEST_F(JointStateBroadcasterTest, ActivateDeactivateTestTwoJointsOneInterface) // check interface configuration auto cmd_if_conf = state_broadcaster_->command_interface_configuration(); ASSERT_THAT(cmd_if_conf.names, IsEmpty()); + EXPECT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::NONE); auto state_if_conf = state_broadcaster_->state_interface_configuration(); ASSERT_THAT(state_if_conf.names, SizeIs(JOINT_NAMES.size() * IF_NAMES.size())); + EXPECT_EQ(state_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); // publishers initialized ASSERT_TRUE(state_broadcaster_->realtime_joint_state_publisher_); @@ -360,9 +368,11 @@ TEST_F(JointStateBroadcasterTest, ActivateDeactivateTestTwoJointsOneInterface) // check interface configuration cmd_if_conf = state_broadcaster_->command_interface_configuration(); ASSERT_THAT(cmd_if_conf.names, IsEmpty()); + EXPECT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::NONE); state_if_conf = state_broadcaster_->state_interface_configuration(); ASSERT_THAT( state_if_conf.names, SizeIs(JOINT_NAMES.size() * IF_NAMES.size())); // does not change + EXPECT_EQ(state_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); } TEST_F(JointStateBroadcasterTest, ActivateTestOneJointTwoInterfaces) @@ -381,8 +391,10 @@ TEST_F(JointStateBroadcasterTest, ActivateTestOneJointTwoInterfaces) // check interface configuration auto cmd_if_conf = state_broadcaster_->command_interface_configuration(); ASSERT_THAT(cmd_if_conf.names, IsEmpty()); + EXPECT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::NONE); auto state_if_conf = state_broadcaster_->state_interface_configuration(); ASSERT_THAT(state_if_conf.names, SizeIs(JOINT_NAMES.size() * IF_NAMES.size())); + EXPECT_EQ(state_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); // publishers initialized ASSERT_TRUE(state_broadcaster_->realtime_joint_state_publisher_); @@ -455,8 +467,10 @@ TEST_F(JointStateBroadcasterTest, ActivateTestTwoJointTwoInterfacesOneMissing) // check interface configuration auto cmd_if_conf = state_broadcaster_->command_interface_configuration(); ASSERT_THAT(cmd_if_conf.names, IsEmpty()); + EXPECT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::NONE); auto state_if_conf = state_broadcaster_->state_interface_configuration(); ASSERT_THAT(state_if_conf.names, SizeIs(JOINT_NAMES.size() * IF_NAMES.size())); + EXPECT_EQ(state_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); // publishers initialized ASSERT_TRUE(state_broadcaster_->realtime_joint_state_publisher_); @@ -504,8 +518,10 @@ TEST_F(JointStateBroadcasterTest, TestCustomInterfaceWithoutMapping) // check interface configuration auto cmd_if_conf = state_broadcaster_->command_interface_configuration(); ASSERT_THAT(cmd_if_conf.names, IsEmpty()); + EXPECT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::NONE); auto state_if_conf = state_broadcaster_->state_interface_configuration(); ASSERT_THAT(state_if_conf.names, SizeIs(JOINT_NAMES.size() * IF_NAMES.size())); + EXPECT_EQ(state_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); // joint state initialized const auto & joint_state_msg = state_broadcaster_->realtime_joint_state_publisher_->msg_; @@ -547,8 +563,10 @@ TEST_F(JointStateBroadcasterTest, TestCustomInterfaceMapping) // check interface configuration auto cmd_if_conf = state_broadcaster_->command_interface_configuration(); ASSERT_THAT(cmd_if_conf.names, IsEmpty()); + EXPECT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::NONE); auto state_if_conf = state_broadcaster_->state_interface_configuration(); ASSERT_THAT(state_if_conf.names, SizeIs(JOINT_NAMES.size() * IF_NAMES.size())); + EXPECT_EQ(state_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); // joint state initialized const auto & joint_state_msg = state_broadcaster_->realtime_joint_state_publisher_->msg_; diff --git a/joint_trajectory_controller/test/test_trajectory_controller.cpp b/joint_trajectory_controller/test/test_trajectory_controller.cpp index fbd6d7aea5..24988618bb 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller.cpp +++ b/joint_trajectory_controller/test/test_trajectory_controller.cpp @@ -120,13 +120,13 @@ TEST_P(TrajectoryControllerTestParameterized, activate) auto state = traj_controller_->get_node()->configure(); ASSERT_EQ(state.id(), State::PRIMARY_STATE_INACTIVE); - auto cmd_interface_config = traj_controller_->command_interface_configuration(); - ASSERT_EQ( - cmd_interface_config.names.size(), joint_names_.size() * command_interface_types_.size()); + auto cmd_if_conf = traj_controller_->command_interface_configuration(); + ASSERT_EQ(cmd_if_conf.names.size(), joint_names_.size() * command_interface_types_.size()); + EXPECT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); - auto state_interface_config = traj_controller_->state_interface_configuration(); - ASSERT_EQ( - state_interface_config.names.size(), joint_names_.size() * state_interface_types_.size()); + auto state_if_conf = traj_controller_->state_interface_configuration(); + ASSERT_EQ(state_if_conf.names.size(), joint_names_.size() * state_interface_types_.size()); + EXPECT_EQ(state_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); state = ActivateTrajectoryController(); ASSERT_EQ(state.id(), State::PRIMARY_STATE_ACTIVE); diff --git a/pid_controller/test/test_pid_controller.cpp b/pid_controller/test/test_pid_controller.cpp index 11f703a1a4..a44347f5f1 100644 --- a/pid_controller/test/test_pid_controller.cpp +++ b/pid_controller/test/test_pid_controller.cpp @@ -61,34 +61,36 @@ TEST_F(PidControllerTest, all_parameters_set_configure_success) ASSERT_FALSE(controller_->params_.use_external_measured_states); } -TEST_F(PidControllerTest, check_exported_intefaces) +TEST_F(PidControllerTest, check_exported_interfaces) { SetUpController(); ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); - auto command_interfaces = controller_->command_interface_configuration(); - ASSERT_EQ(command_interfaces.names.size(), dof_command_values_.size()); - for (size_t i = 0; i < command_interfaces.names.size(); ++i) + auto cmd_if_conf = controller_->command_interface_configuration(); + ASSERT_EQ(cmd_if_conf.names.size(), dof_command_values_.size()); + for (size_t i = 0; i < cmd_if_conf.names.size(); ++i) { - EXPECT_EQ(command_interfaces.names[i], dof_names_[i] + "/" + command_interface_); + EXPECT_EQ(cmd_if_conf.names[i], dof_names_[i] + "/" + command_interface_); } + EXPECT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); - auto state_intefaces = controller_->state_interface_configuration(); - ASSERT_EQ(state_intefaces.names.size(), dof_state_values_.size()); + auto state_if_conf = controller_->state_interface_configuration(); + ASSERT_EQ(state_if_conf.names.size(), dof_state_values_.size()); size_t si_index = 0; for (const auto & interface : state_interfaces_) { for (const auto & dof_name : dof_names_) { - EXPECT_EQ(state_intefaces.names[si_index], dof_name + "/" + interface); + EXPECT_EQ(state_if_conf.names[si_index], dof_name + "/" + interface); ++si_index; } } + EXPECT_EQ(state_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); // check ref itfs - auto reference_interfaces = controller_->export_reference_interfaces(); - ASSERT_EQ(reference_interfaces.size(), dof_state_values_.size()); + auto ref_if_conf = controller_->export_reference_interfaces(); + ASSERT_EQ(ref_if_conf.size(), dof_state_values_.size()); size_t ri_index = 0; for (const auto & interface : state_interfaces_) { @@ -96,10 +98,9 @@ TEST_F(PidControllerTest, check_exported_intefaces) { const std::string ref_itf_name = std::string(controller_->get_node()->get_name()) + "/" + dof_name + "/" + interface; - EXPECT_EQ(reference_interfaces[ri_index].get_name(), ref_itf_name); - EXPECT_EQ( - reference_interfaces[ri_index].get_prefix_name(), controller_->get_node()->get_name()); - EXPECT_EQ(reference_interfaces[ri_index].get_interface_name(), dof_name + "/" + interface); + EXPECT_EQ(ref_if_conf[ri_index].get_name(), ref_itf_name); + EXPECT_EQ(ref_if_conf[ri_index].get_prefix_name(), controller_->get_node()->get_name()); + EXPECT_EQ(ref_if_conf[ri_index].get_interface_name(), dof_name + "/" + interface); ++ri_index; } } diff --git a/pid_controller/test/test_pid_controller_preceding.cpp b/pid_controller/test/test_pid_controller_preceding.cpp index e0d3051226..3e17e69286 100644 --- a/pid_controller/test/test_pid_controller_preceding.cpp +++ b/pid_controller/test/test_pid_controller_preceding.cpp @@ -49,34 +49,36 @@ TEST_F(PidControllerTest, all_parameters_set_configure_success) ASSERT_EQ(controller_->params_.command_interface, command_interface_); } -TEST_F(PidControllerTest, check_exported_intefaces) +TEST_F(PidControllerTest, check_exported_interfaces) { SetUpController(); ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); - auto command_intefaces = controller_->command_interface_configuration(); - ASSERT_EQ(command_intefaces.names.size(), dof_command_values_.size()); - for (size_t i = 0; i < command_intefaces.names.size(); ++i) + auto cmd_if_conf = controller_->command_interface_configuration(); + ASSERT_EQ(cmd_if_conf.names.size(), dof_command_values_.size()); + for (size_t i = 0; i < cmd_if_conf.names.size(); ++i) { - EXPECT_EQ(command_intefaces.names[i], dof_names_[i] + "/" + command_interface_); + EXPECT_EQ(cmd_if_conf.names[i], dof_names_[i] + "/" + command_interface_); } + EXPECT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); - auto state_intefaces = controller_->state_interface_configuration(); - ASSERT_EQ(state_intefaces.names.size(), dof_state_values_.size()); + auto state_if_conf = controller_->state_interface_configuration(); + ASSERT_EQ(state_if_conf.names.size(), dof_state_values_.size()); size_t si_index = 0; for (const auto & interface : state_interfaces_) { for (const auto & dof_name : reference_and_state_dof_names_) { - EXPECT_EQ(state_intefaces.names[si_index], dof_name + "/" + interface); + EXPECT_EQ(state_if_conf.names[si_index], dof_name + "/" + interface); ++si_index; } } + EXPECT_EQ(state_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); // check ref itfs - auto reference_interfaces = controller_->export_reference_interfaces(); - ASSERT_EQ(reference_interfaces.size(), dof_state_values_.size()); + auto ref_if_conf = controller_->export_reference_interfaces(); + ASSERT_EQ(ref_if_conf.size(), dof_state_values_.size()); size_t ri_index = 0; for (const auto & interface : state_interfaces_) { @@ -84,10 +86,9 @@ TEST_F(PidControllerTest, check_exported_intefaces) { const std::string ref_itf_name = std::string(controller_->get_node()->get_name()) + "/" + dof_name + "/" + interface; - EXPECT_EQ(reference_interfaces[ri_index].get_name(), ref_itf_name); - EXPECT_EQ( - reference_interfaces[ri_index].get_prefix_name(), controller_->get_node()->get_name()); - EXPECT_EQ(reference_interfaces[ri_index].get_interface_name(), dof_name + "/" + interface); + EXPECT_EQ(ref_if_conf[ri_index].get_name(), ref_itf_name); + EXPECT_EQ(ref_if_conf[ri_index].get_prefix_name(), controller_->get_node()->get_name()); + EXPECT_EQ(ref_if_conf[ri_index].get_interface_name(), dof_name + "/" + interface); ++ri_index; } } diff --git a/range_sensor_broadcaster/test/test_range_sensor_broadcaster.cpp b/range_sensor_broadcaster/test/test_range_sensor_broadcaster.cpp index 7b8e6d0e02..64f68a7e7a 100644 --- a/range_sensor_broadcaster/test/test_range_sensor_broadcaster.cpp +++ b/range_sensor_broadcaster/test/test_range_sensor_broadcaster.cpp @@ -154,8 +154,10 @@ TEST_F(RangeSensorBroadcasterTest, ActivateDeactivate_RangeBroadcaster_Success) // check interface configuration auto cmd_if_conf = range_broadcaster_->command_interface_configuration(); ASSERT_THAT(cmd_if_conf.names, IsEmpty()); + ASSERT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::NONE); auto state_if_conf = range_broadcaster_->state_interface_configuration(); ASSERT_THAT(state_if_conf.names, SizeIs(1lu)); + ASSERT_EQ(state_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); ASSERT_EQ( range_broadcaster_->on_deactivate(rclcpp_lifecycle::State()), @@ -164,8 +166,10 @@ TEST_F(RangeSensorBroadcasterTest, ActivateDeactivate_RangeBroadcaster_Success) // check interface configuration cmd_if_conf = range_broadcaster_->command_interface_configuration(); ASSERT_THAT(cmd_if_conf.names, IsEmpty()); + ASSERT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::NONE); state_if_conf = range_broadcaster_->state_interface_configuration(); ASSERT_THAT(state_if_conf.names, SizeIs(1lu)); // did not change + ASSERT_EQ(state_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); } TEST_F(RangeSensorBroadcasterTest, Update_RangeBroadcaster_Success) diff --git a/steering_controllers_library/test/test_steering_controllers_library.cpp b/steering_controllers_library/test/test_steering_controllers_library.cpp index 81075d1082..0217567a26 100644 --- a/steering_controllers_library/test/test_steering_controllers_library.cpp +++ b/steering_controllers_library/test/test_steering_controllers_library.cpp @@ -28,41 +28,43 @@ class SteeringControllersLibraryTest }; // checking if all interfaces, command, state and reference are exported as expected -TEST_F(SteeringControllersLibraryTest, check_exported_intefaces) +TEST_F(SteeringControllersLibraryTest, check_exported_interfaces) { SetUpController(); ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); - auto command_intefaces = controller_->command_interface_configuration(); - ASSERT_EQ(command_intefaces.names.size(), joint_command_values_.size()); + auto cmd_if_conf = controller_->command_interface_configuration(); + ASSERT_EQ(cmd_if_conf.names.size(), joint_command_values_.size()); EXPECT_EQ( - command_intefaces.names[CMD_TRACTION_RIGHT_WHEEL], + cmd_if_conf.names[CMD_TRACTION_RIGHT_WHEEL], rear_wheels_names_[0] + "/" + traction_interface_name_); EXPECT_EQ( - command_intefaces.names[CMD_TRACTION_LEFT_WHEEL], + cmd_if_conf.names[CMD_TRACTION_LEFT_WHEEL], rear_wheels_names_[1] + "/" + traction_interface_name_); EXPECT_EQ( - command_intefaces.names[CMD_STEER_RIGHT_WHEEL], + cmd_if_conf.names[CMD_STEER_RIGHT_WHEEL], front_wheels_names_[0] + "/" + steering_interface_name_); EXPECT_EQ( - command_intefaces.names[CMD_STEER_LEFT_WHEEL], + cmd_if_conf.names[CMD_STEER_LEFT_WHEEL], front_wheels_names_[1] + "/" + steering_interface_name_); + EXPECT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); - auto state_intefaces = controller_->state_interface_configuration(); - ASSERT_EQ(state_intefaces.names.size(), joint_state_values_.size()); + auto state_if_conf = controller_->state_interface_configuration(); + ASSERT_EQ(state_if_conf.names.size(), joint_state_values_.size()); EXPECT_EQ( - state_intefaces.names[STATE_TRACTION_RIGHT_WHEEL], + state_if_conf.names[STATE_TRACTION_RIGHT_WHEEL], controller_->rear_wheels_state_names_[0] + "/" + traction_interface_name_); EXPECT_EQ( - state_intefaces.names[STATE_TRACTION_LEFT_WHEEL], + state_if_conf.names[STATE_TRACTION_LEFT_WHEEL], controller_->rear_wheels_state_names_[1] + "/" + traction_interface_name_); EXPECT_EQ( - state_intefaces.names[STATE_STEER_RIGHT_WHEEL], + state_if_conf.names[STATE_STEER_RIGHT_WHEEL], controller_->front_wheels_state_names_[0] + "/" + steering_interface_name_); EXPECT_EQ( - state_intefaces.names[STATE_STEER_LEFT_WHEEL], + state_if_conf.names[STATE_STEER_LEFT_WHEEL], controller_->front_wheels_state_names_[1] + "/" + steering_interface_name_); + EXPECT_EQ(state_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); // check ref itfsTIME auto reference_interfaces = controller_->export_reference_interfaces(); diff --git a/steering_controllers_library/test/test_steering_controllers_library.hpp b/steering_controllers_library/test/test_steering_controllers_library.hpp index 5caf347ac1..83e6054bd4 100644 --- a/steering_controllers_library/test/test_steering_controllers_library.hpp +++ b/steering_controllers_library/test/test_steering_controllers_library.hpp @@ -73,7 +73,7 @@ constexpr auto NODE_ERROR = controller_interface::CallbackReturn::ERROR; class TestableSteeringControllersLibrary : public steering_controllers_library::SteeringControllersLibrary { - FRIEND_TEST(SteeringControllersLibraryTest, check_exported_intefaces); + FRIEND_TEST(SteeringControllersLibraryTest, check_exported_interfaces); FRIEND_TEST(SteeringControllersLibraryTest, test_both_update_methods_for_ref_timeout); public: diff --git a/tricycle_steering_controller/test/test_tricycle_steering_controller.cpp b/tricycle_steering_controller/test/test_tricycle_steering_controller.cpp index 82ba924305..c555de53de 100644 --- a/tricycle_steering_controller/test/test_tricycle_steering_controller.cpp +++ b/tricycle_steering_controller/test/test_tricycle_steering_controller.cpp @@ -45,46 +45,47 @@ TEST_F(TricycleSteeringControllerTest, all_parameters_set_configure_success) ASSERT_EQ(controller_->tricycle_params_.wheel_track, wheel_track_); } -TEST_F(TricycleSteeringControllerTest, check_exported_intefaces) +TEST_F(TricycleSteeringControllerTest, check_exported_interfaces) { SetUpController(); ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); - auto command_intefaces = controller_->command_interface_configuration(); - ASSERT_EQ(command_intefaces.names.size(), joint_command_values_.size()); + auto cmd_if_conf = controller_->command_interface_configuration(); + ASSERT_EQ(cmd_if_conf.names.size(), joint_command_values_.size()); EXPECT_EQ( - command_intefaces.names[CMD_TRACTION_RIGHT_WHEEL], + cmd_if_conf.names[CMD_TRACTION_RIGHT_WHEEL], rear_wheels_names_[0] + "/" + traction_interface_name_); EXPECT_EQ( - command_intefaces.names[CMD_TRACTION_LEFT_WHEEL], + cmd_if_conf.names[CMD_TRACTION_LEFT_WHEEL], rear_wheels_names_[1] + "/" + traction_interface_name_); EXPECT_EQ( - command_intefaces.names[CMD_STEER_WHEEL], - front_wheels_names_[0] + "/" + steering_interface_name_); + cmd_if_conf.names[CMD_STEER_WHEEL], front_wheels_names_[0] + "/" + steering_interface_name_); + EXPECT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); - auto state_intefaces = controller_->state_interface_configuration(); - ASSERT_EQ(state_intefaces.names.size(), joint_state_values_.size()); + auto state_if_conf = controller_->state_interface_configuration(); + ASSERT_EQ(state_if_conf.names.size(), joint_state_values_.size()); EXPECT_EQ( - state_intefaces.names[STATE_TRACTION_RIGHT_WHEEL], + state_if_conf.names[STATE_TRACTION_RIGHT_WHEEL], controller_->rear_wheels_state_names_[0] + "/" + traction_interface_name_); EXPECT_EQ( - state_intefaces.names[STATE_TRACTION_LEFT_WHEEL], + state_if_conf.names[STATE_TRACTION_LEFT_WHEEL], controller_->rear_wheels_state_names_[1] + "/" + traction_interface_name_); EXPECT_EQ( - state_intefaces.names[STATE_STEER_AXIS], + state_if_conf.names[STATE_STEER_AXIS], controller_->front_wheels_state_names_[0] + "/" + steering_interface_name_); + EXPECT_EQ(state_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); - // check ref itfsTIME - auto reference_interfaces = controller_->export_reference_interfaces(); - ASSERT_EQ(reference_interfaces.size(), joint_reference_interfaces_.size()); + // check ref itfs + auto ref_if_conf = controller_->export_reference_interfaces(); + ASSERT_EQ(ref_if_conf.size(), joint_reference_interfaces_.size()); for (size_t i = 0; i < joint_reference_interfaces_.size(); ++i) { const std::string ref_itf_name = std::string(controller_->get_node()->get_name()) + "/" + joint_reference_interfaces_[i]; - EXPECT_EQ(reference_interfaces[i].get_name(), ref_itf_name); - EXPECT_EQ(reference_interfaces[i].get_prefix_name(), controller_->get_node()->get_name()); - EXPECT_EQ(reference_interfaces[i].get_interface_name(), joint_reference_interfaces_[i]); + EXPECT_EQ(ref_if_conf[i].get_name(), ref_itf_name); + EXPECT_EQ(ref_if_conf[i].get_prefix_name(), controller_->get_node()->get_name()); + EXPECT_EQ(ref_if_conf[i].get_interface_name(), joint_reference_interfaces_[i]); } } diff --git a/tricycle_steering_controller/test/test_tricycle_steering_controller.hpp b/tricycle_steering_controller/test/test_tricycle_steering_controller.hpp index c5f6985d4e..e97e2a45bd 100644 --- a/tricycle_steering_controller/test/test_tricycle_steering_controller.hpp +++ b/tricycle_steering_controller/test/test_tricycle_steering_controller.hpp @@ -61,7 +61,7 @@ class TestableTricycleSteeringController : public tricycle_steering_controller::TricycleSteeringController { FRIEND_TEST(TricycleSteeringControllerTest, all_parameters_set_configure_success); - FRIEND_TEST(TricycleSteeringControllerTest, check_exported_intefaces); + FRIEND_TEST(TricycleSteeringControllerTest, check_exported_interfaces); FRIEND_TEST(TricycleSteeringControllerTest, activate_success); FRIEND_TEST(TricycleSteeringControllerTest, update_success); FRIEND_TEST(TricycleSteeringControllerTest, deactivate_success); diff --git a/tricycle_steering_controller/test/test_tricycle_steering_controller_preceeding.cpp b/tricycle_steering_controller/test/test_tricycle_steering_controller_preceeding.cpp index dd72332875..6f2913aeb8 100644 --- a/tricycle_steering_controller/test/test_tricycle_steering_controller_preceeding.cpp +++ b/tricycle_steering_controller/test/test_tricycle_steering_controller_preceeding.cpp @@ -47,46 +47,48 @@ TEST_F(TricycleSteeringControllerTest, all_parameters_set_configure_success) ASSERT_EQ(controller_->tricycle_params_.wheel_track, wheel_track_); } -TEST_F(TricycleSteeringControllerTest, check_exported_intefaces) +TEST_F(TricycleSteeringControllerTest, check_exported_interfaces) { SetUpController(); ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), NODE_SUCCESS); - auto command_intefaces = controller_->command_interface_configuration(); - ASSERT_EQ(command_intefaces.names.size(), joint_command_values_.size()); + auto cmd_if_conf = controller_->command_interface_configuration(); + ASSERT_EQ(cmd_if_conf.names.size(), joint_command_values_.size()); EXPECT_EQ( - command_intefaces.names[CMD_TRACTION_RIGHT_WHEEL], + cmd_if_conf.names[CMD_TRACTION_RIGHT_WHEEL], preceeding_prefix_ + "/" + rear_wheels_names_[0] + "/" + traction_interface_name_); EXPECT_EQ( - command_intefaces.names[CMD_TRACTION_LEFT_WHEEL], + cmd_if_conf.names[CMD_TRACTION_LEFT_WHEEL], preceeding_prefix_ + "/" + rear_wheels_names_[1] + "/" + traction_interface_name_); EXPECT_EQ( - command_intefaces.names[CMD_STEER_WHEEL], + cmd_if_conf.names[CMD_STEER_WHEEL], preceeding_prefix_ + "/" + front_wheels_names_[0] + "/" + steering_interface_name_); + EXPECT_EQ(cmd_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); - auto state_intefaces = controller_->state_interface_configuration(); - ASSERT_EQ(state_intefaces.names.size(), joint_state_values_.size()); + auto state_if_conf = controller_->state_interface_configuration(); + ASSERT_EQ(state_if_conf.names.size(), joint_state_values_.size()); EXPECT_EQ( - state_intefaces.names[STATE_TRACTION_RIGHT_WHEEL], + state_if_conf.names[STATE_TRACTION_RIGHT_WHEEL], controller_->rear_wheels_state_names_[0] + "/" + traction_interface_name_); EXPECT_EQ( - state_intefaces.names[STATE_TRACTION_LEFT_WHEEL], + state_if_conf.names[STATE_TRACTION_LEFT_WHEEL], controller_->rear_wheels_state_names_[1] + "/" + traction_interface_name_); EXPECT_EQ( - state_intefaces.names[STATE_STEER_AXIS], + state_if_conf.names[STATE_STEER_AXIS], controller_->front_wheels_state_names_[0] + "/" + steering_interface_name_); + EXPECT_EQ(state_if_conf.type, controller_interface::interface_configuration_type::INDIVIDUAL); // check ref itfs - auto reference_interfaces = controller_->export_reference_interfaces(); - ASSERT_EQ(reference_interfaces.size(), joint_reference_interfaces_.size()); + auto ref_if_conf = controller_->export_reference_interfaces(); + ASSERT_EQ(ref_if_conf.size(), joint_reference_interfaces_.size()); for (size_t i = 0; i < joint_reference_interfaces_.size(); ++i) { const std::string ref_itf_name = std::string(controller_->get_node()->get_name()) + "/" + joint_reference_interfaces_[i]; - EXPECT_EQ(reference_interfaces[i].get_name(), ref_itf_name); - EXPECT_EQ(reference_interfaces[i].get_prefix_name(), controller_->get_node()->get_name()); - EXPECT_EQ(reference_interfaces[i].get_interface_name(), joint_reference_interfaces_[i]); + EXPECT_EQ(ref_if_conf[i].get_name(), ref_itf_name); + EXPECT_EQ(ref_if_conf[i].get_prefix_name(), controller_->get_node()->get_name()); + EXPECT_EQ(ref_if_conf[i].get_interface_name(), joint_reference_interfaces_[i]); } } From 2705ca8530ab9dae7bc77747541a7c35ceb4d1f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Wed, 31 Jan 2024 21:47:09 +0100 Subject: [PATCH 206/238] [diff_drive] Remove unused parameter and add simple validation #abi-breaking (#958) --- diff_drive_controller/CMakeLists.txt | 6 +- .../diff_drive_controller.hpp | 6 + .../src/diff_drive_controller.cpp | 16 +- .../src/diff_drive_controller_parameter.yaml | 15 +- .../config/test_diff_drive_controller.yaml | 3 +- .../test/test_diff_drive_controller.cpp | 306 +++++++----------- .../test/test_load_diff_drive_controller.cpp | 10 +- 7 files changed, 143 insertions(+), 219 deletions(-) diff --git a/diff_drive_controller/CMakeLists.txt b/diff_drive_controller/CMakeLists.txt index 436832c523..d67815b5e0 100644 --- a/diff_drive_controller/CMakeLists.txt +++ b/diff_drive_controller/CMakeLists.txt @@ -53,8 +53,7 @@ if(BUILD_TESTING) find_package(ros2_control_test_assets REQUIRED) ament_add_gmock(test_diff_drive_controller - test/test_diff_drive_controller.cpp - ENV config_file=${CMAKE_CURRENT_SOURCE_DIR}/test/config/test_diff_drive_controller.yaml) + test/test_diff_drive_controller.cpp) target_link_libraries(test_diff_drive_controller diff_drive_controller ) @@ -69,8 +68,9 @@ if(BUILD_TESTING) tf2_msgs ) - ament_add_gmock(test_load_diff_drive_controller + add_rostest_with_parameters_gmock(test_load_diff_drive_controller test/test_load_diff_drive_controller.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/test/config/test_diff_drive_controller.yaml ) ament_target_dependencies(test_load_diff_drive_controller controller_manager diff --git a/diff_drive_controller/include/diff_drive_controller/diff_drive_controller.hpp b/diff_drive_controller/include/diff_drive_controller/diff_drive_controller.hpp index 554bedba59..72b38f7d2d 100644 --- a/diff_drive_controller/include/diff_drive_controller/diff_drive_controller.hpp +++ b/diff_drive_controller/include/diff_drive_controller/diff_drive_controller.hpp @@ -110,6 +110,12 @@ class DiffDriveController : public controller_interface::ControllerInterface // Parameters from ROS for diff_drive_controller std::shared_ptr param_listener_; Params params_; + /* Number of wheels on each side of the robot. This is important to take the wheels slip into + * account when multiple wheels on each side are present. If there are more wheels then control + * signals for each side, you should enter number for control signals. For example, Husky has two + * wheels on each side, but they use one control signal, in this case '1' is the correct value of + * the parameter. */ + int wheels_per_side_; Odometry odometry_; diff --git a/diff_drive_controller/src/diff_drive_controller.cpp b/diff_drive_controller/src/diff_drive_controller.cpp index ea08aef89b..42b6cda8e1 100644 --- a/diff_drive_controller/src/diff_drive_controller.cpp +++ b/diff_drive_controller/src/diff_drive_controller.cpp @@ -149,7 +149,7 @@ controller_interface::return_type DiffDriveController::update( { double left_feedback_mean = 0.0; double right_feedback_mean = 0.0; - for (size_t index = 0; index < static_cast(params_.wheels_per_side); ++index) + for (size_t index = 0; index < static_cast(wheels_per_side_); ++index) { const double left_feedback = registered_left_wheel_handles_[index].feedback.get().get_value(); const double right_feedback = @@ -166,8 +166,8 @@ controller_interface::return_type DiffDriveController::update( left_feedback_mean += left_feedback; right_feedback_mean += right_feedback; } - left_feedback_mean /= static_cast(params_.wheels_per_side); - right_feedback_mean /= static_cast(params_.wheels_per_side); + left_feedback_mean /= static_cast(wheels_per_side_); + right_feedback_mean /= static_cast(wheels_per_side_); if (params_.position_feedback) { @@ -257,7 +257,7 @@ controller_interface::return_type DiffDriveController::update( (linear_command + angular_command * wheel_separation / 2.0) / right_wheel_radius; // Set wheels velocities: - for (size_t index = 0; index < static_cast(params_.wheels_per_side); ++index) + for (size_t index = 0; index < static_cast(wheels_per_side_); ++index) { registered_left_wheel_handles_[index].velocity.get().set_value(velocity_left); registered_right_wheel_handles_[index].velocity.get().set_value(velocity_right); @@ -286,12 +286,6 @@ controller_interface::CallbackReturn DiffDriveController::on_configure( return controller_interface::CallbackReturn::ERROR; } - if (params_.left_wheel_names.empty()) - { - RCLCPP_ERROR(logger, "Wheel names parameters are empty!"); - return controller_interface::CallbackReturn::ERROR; - } - const double wheel_separation = params_.wheel_separation_multiplier * params_.wheel_separation; const double left_wheel_radius = params_.left_wheel_radius_multiplier * params_.wheel_radius; const double right_wheel_radius = params_.right_wheel_radius_multiplier * params_.wheel_radius; @@ -320,7 +314,7 @@ controller_interface::CallbackReturn DiffDriveController::on_configure( } // left and right sides are both equal at this point - params_.wheels_per_side = params_.left_wheel_names.size(); + wheels_per_side_ = static_cast(params_.left_wheel_names.size()); if (publish_limited_velocity_) { diff --git a/diff_drive_controller/src/diff_drive_controller_parameter.yaml b/diff_drive_controller/src/diff_drive_controller_parameter.yaml index 0c0285e7c2..9720e068e1 100644 --- a/diff_drive_controller/src/diff_drive_controller_parameter.yaml +++ b/diff_drive_controller/src/diff_drive_controller_parameter.yaml @@ -2,23 +2,24 @@ diff_drive_controller: left_wheel_names: { type: string_array, default_value: [], - description: "Link names of the left side wheels", + description: "Names of the left side wheels' joints", + validation: { + not_empty<>: [] + } } right_wheel_names: { type: string_array, default_value: [], - description: "Link names of the right side wheels", + description: "Names of the right side wheels' joints", + validation: { + not_empty<>: [] + } } wheel_separation: { type: double, default_value: 0.0, description: "Shortest distance between the left and right wheels. If this parameter is wrong, the robot will not behave correctly in curves.", } - wheels_per_side: { - type: int, - default_value: 0, - description: "Number of wheels on each side of the robot. This is important to take the wheels slip into account when multiple wheels on each side are present. If there are more wheels then control signals for each side, you should enter number for control signals. For example, Husky has two wheels on each side, but they use one control signal, in this case '1' is the correct value of the parameter.", - } wheel_radius: { type: double, default_value: 0.0, diff --git a/diff_drive_controller/test/config/test_diff_drive_controller.yaml b/diff_drive_controller/test/config/test_diff_drive_controller.yaml index a2149eb6bc..bfbf8f2d19 100644 --- a/diff_drive_controller/test/config/test_diff_drive_controller.yaml +++ b/diff_drive_controller/test/config/test_diff_drive_controller.yaml @@ -2,7 +2,6 @@ test_diff_drive_controller: ros__parameters: left_wheel_names: ["left_wheels"] right_wheel_names: ["right_wheels"] - write_op_modes: ["motor_controller"] wheel_separation: 0.40 wheels_per_side: 1 # actually 2, but both are controlled by 1 signal @@ -21,7 +20,7 @@ test_diff_drive_controller: open_loop: true enable_odom_tf: true - cmd_vel_timeout: 500 # milliseconds + cmd_vel_timeout: 0.5 # seconds publish_limited_velocity: true velocity_rolling_window_size: 10 diff --git a/diff_drive_controller/test/test_diff_drive_controller.cpp b/diff_drive_controller/test/test_diff_drive_controller.cpp index 4ad293298f..43dae41a9b 100644 --- a/diff_drive_controller/test/test_diff_drive_controller.cpp +++ b/diff_drive_controller/test/test_diff_drive_controller.cpp @@ -36,6 +36,12 @@ using hardware_interface::LoanedStateInterface; using lifecycle_msgs::msg::State; using testing::SizeIs; +namespace +{ +const std::vector left_wheel_names = {"left_wheel_joint"}; +const std::vector right_wheel_names = {"right_wheel_joint"}; +} // namespace + class TestableDiffDriveController : public diff_drive_controller::DiffDriveController { public: @@ -166,11 +172,28 @@ class TestDiffDriveController : public ::testing::Test controller_->assign_interfaces(std::move(command_ifs), std::move(state_ifs)); } + controller_interface::return_type InitController( + const std::vector left_wheel_joints_init = left_wheel_names, + const std::vector right_wheel_joints_init = right_wheel_names, + const std::vector & parameters = {}, const std::string ns = "") + { + auto node_options = rclcpp::NodeOptions(); + std::vector parameter_overrides; + + parameter_overrides.push_back( + rclcpp::Parameter("left_wheel_names", rclcpp::ParameterValue(left_wheel_joints_init))); + parameter_overrides.push_back( + rclcpp::Parameter("right_wheel_names", rclcpp::ParameterValue(right_wheel_joints_init))); + + parameter_overrides.insert(parameter_overrides.end(), parameters.begin(), parameters.end()); + node_options.parameter_overrides(parameter_overrides); + + return controller_->init(controller_name, urdf_, 0, ns, node_options); + } + const std::string controller_name = "test_diff_drive_controller"; std::unique_ptr controller_; - const std::vector left_wheel_names = {"left_wheel_joint"}; - const std::vector right_wheel_names = {"right_wheel_joint"}; std::vector position_values_ = {0.1, 0.2}; std::vector velocity_values_ = {0.01, 0.02}; @@ -193,59 +216,31 @@ class TestDiffDriveController : public ::testing::Test const std::string urdf_ = ""; }; -TEST_F(TestDiffDriveController, configure_fails_without_parameters) +TEST_F(TestDiffDriveController, init_fails_without_parameters) { const auto ret = controller_->init(controller_name, urdf_, 0); - ASSERT_EQ(ret, controller_interface::return_type::OK); - - ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), CallbackReturn::ERROR); + ASSERT_EQ(ret, controller_interface::return_type::ERROR); } -TEST_F(TestDiffDriveController, configure_fails_with_only_left_or_only_right_side_defined) +TEST_F(TestDiffDriveController, init_fails_with_only_left_or_only_right_side_defined) { - const auto ret = controller_->init(controller_name, urdf_, 0); - ASSERT_EQ(ret, controller_interface::return_type::OK); - - controller_->get_node()->set_parameter( - rclcpp::Parameter("left_wheel_names", rclcpp::ParameterValue(left_wheel_names))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("right_wheel_names", rclcpp::ParameterValue(std::vector()))); - - ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), CallbackReturn::ERROR); - - controller_->get_node()->set_parameter( - rclcpp::Parameter("left_wheel_names", rclcpp::ParameterValue(std::vector()))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("right_wheel_names", rclcpp::ParameterValue(right_wheel_names))); + ASSERT_EQ(InitController(left_wheel_names, {}), controller_interface::return_type::ERROR); - ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), CallbackReturn::ERROR); + ASSERT_EQ(InitController({}, right_wheel_names), controller_interface::return_type::ERROR); } TEST_F(TestDiffDriveController, configure_fails_with_mismatching_wheel_side_size) { - const auto ret = controller_->init(controller_name, urdf_, 0); - ASSERT_EQ(ret, controller_interface::return_type::OK); - - controller_->get_node()->set_parameter( - rclcpp::Parameter("left_wheel_names", rclcpp::ParameterValue(left_wheel_names))); - - auto extended_right_wheel_names = right_wheel_names; - extended_right_wheel_names.push_back("extra_wheel"); - controller_->get_node()->set_parameter( - rclcpp::Parameter("right_wheel_names", rclcpp::ParameterValue(extended_right_wheel_names))); + ASSERT_EQ( + InitController(left_wheel_names, {right_wheel_names[0], "extra_wheel"}), + controller_interface::return_type::OK); ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), CallbackReturn::ERROR); } TEST_F(TestDiffDriveController, configure_succeeds_when_wheels_are_specified) { - const auto ret = controller_->init(controller_name, urdf_, 0); - ASSERT_EQ(ret, controller_interface::return_type::OK); - - controller_->get_node()->set_parameter( - rclcpp::Parameter("left_wheel_names", rclcpp::ParameterValue(left_wheel_names))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("right_wheel_names", rclcpp::ParameterValue(right_wheel_names))); + ASSERT_EQ(InitController(), controller_interface::return_type::OK); ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), CallbackReturn::SUCCESS); @@ -259,26 +254,18 @@ TEST_F(TestDiffDriveController, configure_succeeds_when_wheels_are_specified) TEST_F(TestDiffDriveController, configure_succeeds_tf_test_prefix_false_no_namespace) { - const auto ret = controller_->init(controller_name, urdf_, 0); - ASSERT_EQ(ret, controller_interface::return_type::OK); - std::string odom_id = "odom"; std::string base_link_id = "base_link"; std::string frame_prefix = "test_prefix"; - controller_->get_node()->set_parameter( - rclcpp::Parameter("left_wheel_names", rclcpp::ParameterValue(left_wheel_names))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("right_wheel_names", rclcpp::ParameterValue(right_wheel_names))); - - controller_->get_node()->set_parameter( - rclcpp::Parameter("tf_frame_prefix_enable", rclcpp::ParameterValue(false))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("tf_frame_prefix", rclcpp::ParameterValue(frame_prefix))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("odom_frame_id", rclcpp::ParameterValue(odom_id))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("base_frame_id", rclcpp::ParameterValue(base_link_id))); + ASSERT_EQ( + InitController( + left_wheel_names, right_wheel_names, + {rclcpp::Parameter("tf_frame_prefix_enable", rclcpp::ParameterValue(false)), + rclcpp::Parameter("tf_frame_prefix", rclcpp::ParameterValue(frame_prefix)), + rclcpp::Parameter("odom_frame_id", rclcpp::ParameterValue(odom_id)), + rclcpp::Parameter("base_frame_id", rclcpp::ParameterValue(base_link_id))}), + controller_interface::return_type::OK); ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), CallbackReturn::SUCCESS); @@ -292,26 +279,18 @@ TEST_F(TestDiffDriveController, configure_succeeds_tf_test_prefix_false_no_names TEST_F(TestDiffDriveController, configure_succeeds_tf_test_prefix_true_no_namespace) { - const auto ret = controller_->init(controller_name, urdf_, 0); - ASSERT_EQ(ret, controller_interface::return_type::OK); - std::string odom_id = "odom"; std::string base_link_id = "base_link"; std::string frame_prefix = "test_prefix"; - controller_->get_node()->set_parameter( - rclcpp::Parameter("left_wheel_names", rclcpp::ParameterValue(left_wheel_names))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("right_wheel_names", rclcpp::ParameterValue(right_wheel_names))); - - controller_->get_node()->set_parameter( - rclcpp::Parameter("tf_frame_prefix_enable", rclcpp::ParameterValue(true))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("tf_frame_prefix", rclcpp::ParameterValue(frame_prefix))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("odom_frame_id", rclcpp::ParameterValue(odom_id))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("base_frame_id", rclcpp::ParameterValue(base_link_id))); + ASSERT_EQ( + InitController( + left_wheel_names, right_wheel_names, + {rclcpp::Parameter("tf_frame_prefix_enable", rclcpp::ParameterValue(true)), + rclcpp::Parameter("tf_frame_prefix", rclcpp::ParameterValue(frame_prefix)), + rclcpp::Parameter("odom_frame_id", rclcpp::ParameterValue(odom_id)), + rclcpp::Parameter("base_frame_id", rclcpp::ParameterValue(base_link_id))}), + controller_interface::return_type::OK); ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), CallbackReturn::SUCCESS); @@ -327,26 +306,18 @@ TEST_F(TestDiffDriveController, configure_succeeds_tf_test_prefix_true_no_namesp TEST_F(TestDiffDriveController, configure_succeeds_tf_blank_prefix_true_no_namespace) { - const auto ret = controller_->init(controller_name, urdf_, 0); - ASSERT_EQ(ret, controller_interface::return_type::OK); - std::string odom_id = "odom"; std::string base_link_id = "base_link"; std::string frame_prefix = ""; - controller_->get_node()->set_parameter( - rclcpp::Parameter("left_wheel_names", rclcpp::ParameterValue(left_wheel_names))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("right_wheel_names", rclcpp::ParameterValue(right_wheel_names))); - - controller_->get_node()->set_parameter( - rclcpp::Parameter("tf_frame_prefix_enable", rclcpp::ParameterValue(true))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("tf_frame_prefix", rclcpp::ParameterValue(frame_prefix))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("odom_frame_id", rclcpp::ParameterValue(odom_id))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("base_frame_id", rclcpp::ParameterValue(base_link_id))); + ASSERT_EQ( + InitController( + left_wheel_names, right_wheel_names, + {rclcpp::Parameter("tf_frame_prefix_enable", rclcpp::ParameterValue(true)), + rclcpp::Parameter("tf_frame_prefix", rclcpp::ParameterValue(frame_prefix)), + rclcpp::Parameter("odom_frame_id", rclcpp::ParameterValue(odom_id)), + rclcpp::Parameter("base_frame_id", rclcpp::ParameterValue(base_link_id))}), + controller_interface::return_type::OK); ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), CallbackReturn::SUCCESS); @@ -363,26 +334,19 @@ TEST_F(TestDiffDriveController, configure_succeeds_tf_test_prefix_false_set_name { std::string test_namespace = "/test_namespace"; - const auto ret = controller_->init(controller_name, urdf_, 0, test_namespace); - ASSERT_EQ(ret, controller_interface::return_type::OK); - std::string odom_id = "odom"; std::string base_link_id = "base_link"; std::string frame_prefix = "test_prefix"; - controller_->get_node()->set_parameter( - rclcpp::Parameter("left_wheel_names", rclcpp::ParameterValue(left_wheel_names))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("right_wheel_names", rclcpp::ParameterValue(right_wheel_names))); - - controller_->get_node()->set_parameter( - rclcpp::Parameter("tf_frame_prefix_enable", rclcpp::ParameterValue(false))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("tf_frame_prefix", rclcpp::ParameterValue(frame_prefix))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("odom_frame_id", rclcpp::ParameterValue(odom_id))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("base_frame_id", rclcpp::ParameterValue(base_link_id))); + ASSERT_EQ( + InitController( + left_wheel_names, right_wheel_names, + {rclcpp::Parameter("tf_frame_prefix_enable", rclcpp::ParameterValue(false)), + rclcpp::Parameter("tf_frame_prefix", rclcpp::ParameterValue(frame_prefix)), + rclcpp::Parameter("odom_frame_id", rclcpp::ParameterValue(odom_id)), + rclcpp::Parameter("base_frame_id", rclcpp::ParameterValue(base_link_id))}, + test_namespace), + controller_interface::return_type::OK); ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), CallbackReturn::SUCCESS); @@ -398,26 +362,19 @@ TEST_F(TestDiffDriveController, configure_succeeds_tf_test_prefix_true_set_names { std::string test_namespace = "/test_namespace"; - const auto ret = controller_->init(controller_name, urdf_, 0, test_namespace); - ASSERT_EQ(ret, controller_interface::return_type::OK); - std::string odom_id = "odom"; std::string base_link_id = "base_link"; std::string frame_prefix = "test_prefix"; - controller_->get_node()->set_parameter( - rclcpp::Parameter("left_wheel_names", rclcpp::ParameterValue(left_wheel_names))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("right_wheel_names", rclcpp::ParameterValue(right_wheel_names))); - - controller_->get_node()->set_parameter( - rclcpp::Parameter("tf_frame_prefix_enable", rclcpp::ParameterValue(true))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("tf_frame_prefix", rclcpp::ParameterValue(frame_prefix))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("odom_frame_id", rclcpp::ParameterValue(odom_id))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("base_frame_id", rclcpp::ParameterValue(base_link_id))); + ASSERT_EQ( + InitController( + left_wheel_names, right_wheel_names, + {rclcpp::Parameter("tf_frame_prefix_enable", rclcpp::ParameterValue(true)), + rclcpp::Parameter("tf_frame_prefix", rclcpp::ParameterValue(frame_prefix)), + rclcpp::Parameter("odom_frame_id", rclcpp::ParameterValue(odom_id)), + rclcpp::Parameter("base_frame_id", rclcpp::ParameterValue(base_link_id))}, + test_namespace), + controller_interface::return_type::OK); ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), CallbackReturn::SUCCESS); @@ -435,26 +392,19 @@ TEST_F(TestDiffDriveController, configure_succeeds_tf_blank_prefix_true_set_name { std::string test_namespace = "/test_namespace"; - const auto ret = controller_->init(controller_name, urdf_, 0, test_namespace); - ASSERT_EQ(ret, controller_interface::return_type::OK); - std::string odom_id = "odom"; std::string base_link_id = "base_link"; std::string frame_prefix = ""; - controller_->get_node()->set_parameter( - rclcpp::Parameter("left_wheel_names", rclcpp::ParameterValue(left_wheel_names))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("right_wheel_names", rclcpp::ParameterValue(right_wheel_names))); - - controller_->get_node()->set_parameter( - rclcpp::Parameter("tf_frame_prefix_enable", rclcpp::ParameterValue(true))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("tf_frame_prefix", rclcpp::ParameterValue(frame_prefix))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("odom_frame_id", rclcpp::ParameterValue(odom_id))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("base_frame_id", rclcpp::ParameterValue(base_link_id))); + ASSERT_EQ( + InitController( + left_wheel_names, right_wheel_names, + {rclcpp::Parameter("tf_frame_prefix_enable", rclcpp::ParameterValue(true)), + rclcpp::Parameter("tf_frame_prefix", rclcpp::ParameterValue(frame_prefix)), + rclcpp::Parameter("odom_frame_id", rclcpp::ParameterValue(odom_id)), + rclcpp::Parameter("base_frame_id", rclcpp::ParameterValue(base_link_id))}, + test_namespace), + controller_interface::return_type::OK); ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), CallbackReturn::SUCCESS); @@ -469,13 +419,7 @@ TEST_F(TestDiffDriveController, configure_succeeds_tf_blank_prefix_true_set_name TEST_F(TestDiffDriveController, activate_fails_without_resources_assigned) { - const auto ret = controller_->init(controller_name, urdf_, 0); - ASSERT_EQ(ret, controller_interface::return_type::OK); - - controller_->get_node()->set_parameter( - rclcpp::Parameter("left_wheel_names", rclcpp::ParameterValue(left_wheel_names))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("right_wheel_names", rclcpp::ParameterValue(right_wheel_names))); + ASSERT_EQ(InitController(), controller_interface::return_type::OK); ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), CallbackReturn::SUCCESS); ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), CallbackReturn::ERROR); @@ -483,15 +427,9 @@ TEST_F(TestDiffDriveController, activate_fails_without_resources_assigned) TEST_F(TestDiffDriveController, activate_succeeds_with_pos_resources_assigned) { - const auto ret = controller_->init(controller_name, urdf_, 0); - ASSERT_EQ(ret, controller_interface::return_type::OK); + ASSERT_EQ(InitController(), controller_interface::return_type::OK); // We implicitly test that by default position feedback is required - controller_->get_node()->set_parameter( - rclcpp::Parameter("left_wheel_names", rclcpp::ParameterValue(left_wheel_names))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("right_wheel_names", rclcpp::ParameterValue(right_wheel_names))); - ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), CallbackReturn::SUCCESS); assignResourcesPosFeedback(); ASSERT_EQ(controller_->on_activate(rclcpp_lifecycle::State()), CallbackReturn::SUCCESS); @@ -499,15 +437,11 @@ TEST_F(TestDiffDriveController, activate_succeeds_with_pos_resources_assigned) TEST_F(TestDiffDriveController, activate_succeeds_with_vel_resources_assigned) { - const auto ret = controller_->init(controller_name, urdf_, 0); - ASSERT_EQ(ret, controller_interface::return_type::OK); - - controller_->get_node()->set_parameter( - rclcpp::Parameter("position_feedback", rclcpp::ParameterValue(false))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("left_wheel_names", rclcpp::ParameterValue(left_wheel_names))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("right_wheel_names", rclcpp::ParameterValue(right_wheel_names))); + ASSERT_EQ( + InitController( + left_wheel_names, right_wheel_names, + {rclcpp::Parameter("position_feedback", rclcpp::ParameterValue(false))}), + controller_interface::return_type::OK); ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), CallbackReturn::SUCCESS); assignResourcesVelFeedback(); @@ -516,15 +450,11 @@ TEST_F(TestDiffDriveController, activate_succeeds_with_vel_resources_assigned) TEST_F(TestDiffDriveController, activate_fails_with_wrong_resources_assigned_1) { - const auto ret = controller_->init(controller_name, urdf_, 0); - ASSERT_EQ(ret, controller_interface::return_type::OK); - - controller_->get_node()->set_parameter( - rclcpp::Parameter("position_feedback", rclcpp::ParameterValue(false))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("left_wheel_names", rclcpp::ParameterValue(left_wheel_names))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("right_wheel_names", rclcpp::ParameterValue(right_wheel_names))); + ASSERT_EQ( + InitController( + left_wheel_names, right_wheel_names, + {rclcpp::Parameter("position_feedback", rclcpp::ParameterValue(false))}), + controller_interface::return_type::OK); ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), CallbackReturn::SUCCESS); assignResourcesPosFeedback(); @@ -533,15 +463,11 @@ TEST_F(TestDiffDriveController, activate_fails_with_wrong_resources_assigned_1) TEST_F(TestDiffDriveController, activate_fails_with_wrong_resources_assigned_2) { - const auto ret = controller_->init(controller_name, urdf_, 0); - ASSERT_EQ(ret, controller_interface::return_type::OK); - - controller_->get_node()->set_parameter( - rclcpp::Parameter("position_feedback", rclcpp::ParameterValue(true))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("left_wheel_names", rclcpp::ParameterValue(left_wheel_names))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("right_wheel_names", rclcpp::ParameterValue(right_wheel_names))); + ASSERT_EQ( + InitController( + left_wheel_names, right_wheel_names, + {rclcpp::Parameter("position_feedback", rclcpp::ParameterValue(true))}), + controller_interface::return_type::OK); ASSERT_EQ(controller_->on_configure(rclcpp_lifecycle::State()), CallbackReturn::SUCCESS); assignResourcesVelFeedback(); @@ -550,15 +476,11 @@ TEST_F(TestDiffDriveController, activate_fails_with_wrong_resources_assigned_2) TEST_F(TestDiffDriveController, cleanup) { - const auto ret = controller_->init(controller_name, urdf_, 0); - ASSERT_EQ(ret, controller_interface::return_type::OK); - - controller_->get_node()->set_parameter( - rclcpp::Parameter("left_wheel_names", rclcpp::ParameterValue(left_wheel_names))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("right_wheel_names", rclcpp::ParameterValue(right_wheel_names))); - controller_->get_node()->set_parameter(rclcpp::Parameter("wheel_separation", 0.4)); - controller_->get_node()->set_parameter(rclcpp::Parameter("wheel_radius", 0.1)); + ASSERT_EQ( + InitController( + left_wheel_names, right_wheel_names, + {rclcpp::Parameter("wheel_separation", 0.4), rclcpp::Parameter("wheel_radius", 0.1)}), + controller_interface::return_type::OK); rclcpp::executors::SingleThreadedExecutor executor; executor.add_node(controller_->get_node()->get_node_base_interface()); @@ -599,15 +521,11 @@ TEST_F(TestDiffDriveController, cleanup) TEST_F(TestDiffDriveController, correct_initialization_using_parameters) { - const auto ret = controller_->init(controller_name, urdf_, 0); - ASSERT_EQ(ret, controller_interface::return_type::OK); - - controller_->get_node()->set_parameter( - rclcpp::Parameter("left_wheel_names", rclcpp::ParameterValue(left_wheel_names))); - controller_->get_node()->set_parameter( - rclcpp::Parameter("right_wheel_names", rclcpp::ParameterValue(right_wheel_names))); - controller_->get_node()->set_parameter(rclcpp::Parameter("wheel_separation", 0.4)); - controller_->get_node()->set_parameter(rclcpp::Parameter("wheel_radius", 1.0)); + ASSERT_EQ( + InitController( + left_wheel_names, right_wheel_names, + {rclcpp::Parameter("wheel_separation", 0.4), rclcpp::Parameter("wheel_radius", 1.0)}), + controller_interface::return_type::OK); rclcpp::executors::SingleThreadedExecutor executor; executor.add_node(controller_->get_node()->get_node_base_interface()); diff --git a/diff_drive_controller/test/test_load_diff_drive_controller.cpp b/diff_drive_controller/test/test_load_diff_drive_controller.cpp index 1eb8939031..983ec6d98f 100644 --- a/diff_drive_controller/test/test_load_diff_drive_controller.cpp +++ b/diff_drive_controller/test/test_load_diff_drive_controller.cpp @@ -21,8 +21,6 @@ TEST(TestLoadDiffDriveController, load_controller) { - rclcpp::init(0, nullptr); - std::shared_ptr executor = std::make_shared(); @@ -33,6 +31,14 @@ TEST(TestLoadDiffDriveController, load_controller) ASSERT_NE( cm.load_controller("test_diff_drive_controller", "diff_drive_controller/DiffDriveController"), nullptr); +} +int main(int argc, char ** argv) +{ + ::testing::InitGoogleTest(&argc, argv); + rclcpp::init(argc, argv); + int result = RUN_ALL_TESTS(); + rclcpp::shutdown(); rclcpp::shutdown(); + return result; } From 67dbf7b4128f75f8d907d8ca8d480e3108bf9bca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Wed, 31 Jan 2024 21:48:22 +0100 Subject: [PATCH 207/238] [JTC] Fill action error_strings (#887) --- .../src/joint_trajectory_controller.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/joint_trajectory_controller/src/joint_trajectory_controller.cpp b/joint_trajectory_controller/src/joint_trajectory_controller.cpp index a22fe7f2d1..b0e93b6ecd 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller.cpp +++ b/joint_trajectory_controller/src/joint_trajectory_controller.cpp @@ -294,6 +294,7 @@ controller_interface::return_type JointTrajectoryController::update( { auto result = std::make_shared(); result->set__error_code(FollowJTrajAction::Result::PATH_TOLERANCE_VIOLATED); + result->set__error_string("Aborted due to path tolerance violation"); active_goal->setAborted(result); // TODO(matthew-reynolds): Need a lock-free write here // See https://github.com/ros-controls/ros2_controllers/issues/168 @@ -310,9 +311,10 @@ controller_interface::return_type JointTrajectoryController::update( { if (!outside_goal_tolerance) { - auto res = std::make_shared(); - res->set__error_code(FollowJTrajAction::Result::SUCCESSFUL); - active_goal->setSucceeded(res); + auto result = std::make_shared(); + result->set__error_code(FollowJTrajAction::Result::SUCCESSFUL); + result->set__error_string("Goal successfully reached!"); + active_goal->setSucceeded(result); // TODO(matthew-reynolds): Need a lock-free write here // See https://github.com/ros-controls/ros2_controllers/issues/168 rt_active_goal_.writeFromNonRT(RealtimeGoalHandlePtr()); @@ -325,17 +327,19 @@ controller_interface::return_type JointTrajectoryController::update( } else if (!within_goal_time) { + const std::string error_string = "Aborted due to goal_time_tolerance exceeding by " + + std::to_string(time_difference) + " seconds"; + auto result = std::make_shared(); result->set__error_code(FollowJTrajAction::Result::GOAL_TOLERANCE_VIOLATED); + result->set__error_string(error_string); active_goal->setAborted(result); // TODO(matthew-reynolds): Need a lock-free write here // See https://github.com/ros-controls/ros2_controllers/issues/168 rt_active_goal_.writeFromNonRT(RealtimeGoalHandlePtr()); rt_has_pending_goal_.writeFromNonRT(false); - RCLCPP_WARN( - get_node()->get_logger(), "Aborted due goal_time_tolerance exceeding by %f seconds", - time_difference); + RCLCPP_WARN(get_node()->get_logger(), error_string.c_str()); traj_msg_external_point_ptr_.reset(); traj_msg_external_point_ptr_.initRT(set_hold_position()); From 08ea6cf3885bd286cfd17fb1b32b40a763afae61 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Wed, 31 Jan 2024 20:54:51 +0000 Subject: [PATCH 208/238] Update changelogs --- ackermann_steering_controller/CHANGELOG.rst | 5 +++++ admittance_controller/CHANGELOG.rst | 6 ++++++ bicycle_steering_controller/CHANGELOG.rst | 5 +++++ diff_drive_controller/CHANGELOG.rst | 7 +++++++ effort_controllers/CHANGELOG.rst | 3 +++ force_torque_sensor_broadcaster/CHANGELOG.rst | 7 +++++++ forward_command_controller/CHANGELOG.rst | 5 +++++ gripper_controllers/CHANGELOG.rst | 5 +++++ imu_sensor_broadcaster/CHANGELOG.rst | 6 ++++++ joint_state_broadcaster/CHANGELOG.rst | 6 ++++++ joint_trajectory_controller/CHANGELOG.rst | 10 ++++++++++ pid_controller/CHANGELOG.rst | 6 ++++++ position_controllers/CHANGELOG.rst | 3 +++ range_sensor_broadcaster/CHANGELOG.rst | 6 ++++++ ros2_controllers/CHANGELOG.rst | 3 +++ ros2_controllers_test_nodes/CHANGELOG.rst | 3 +++ rqt_joint_trajectory_controller/CHANGELOG.rst | 3 +++ steering_controllers_library/CHANGELOG.rst | 5 +++++ tricycle_controller/CHANGELOG.rst | 5 +++++ tricycle_steering_controller/CHANGELOG.rst | 5 +++++ velocity_controllers/CHANGELOG.rst | 3 +++ 21 files changed, 107 insertions(+) diff --git a/ackermann_steering_controller/CHANGELOG.rst b/ackermann_steering_controller/CHANGELOG.rst index a314802327..83e135693c 100644 --- a/ackermann_steering_controller/CHANGELOG.rst +++ b/ackermann_steering_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package ackermann_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add tests for `interface_configuration_type` consistently (`#899 `_) +* Contributors: Christoph Fröhlich + 4.4.0 (2024-01-11) ------------------ diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index 826a7aa6be..47f5d2ac30 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add tests for `interface_configuration_type` consistently (`#899 `_) +* Let sphinx add parameter description with nested structures to documentation (`#652 `_) +* Contributors: Christoph Fröhlich + 4.4.0 (2024-01-11) ------------------ diff --git a/bicycle_steering_controller/CHANGELOG.rst b/bicycle_steering_controller/CHANGELOG.rst index a1f79c922b..c44e1a9157 100644 --- a/bicycle_steering_controller/CHANGELOG.rst +++ b/bicycle_steering_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package bicycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add tests for `interface_configuration_type` consistently (`#899 `_) +* Contributors: Christoph Fröhlich + 4.4.0 (2024-01-11) ------------------ diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index 316cd9e52d..d3f89a9eea 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,6 +2,13 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* [diff_drive] Remove unused parameter and add simple validation #abi-breaking (`#958 `_) +* Add tests for `interface_configuration_type` consistently (`#899 `_) +* Let sphinx add parameter description with nested structures to documentation (`#652 `_) +* Contributors: Christoph Fröhlich + 4.4.0 (2024-01-11) ------------------ diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index 54cdc18d69..debb1f7717 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.4.0 (2024-01-11) ------------------ diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index 58191c2f42..5b0be8fdbe 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,13 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add tests for `interface_configuration_type` consistently (`#899 `_) +* Let sphinx add parameter description with nested structures to documentation (`#652 `_) +* Revert "[ForceTorqueSensorBroadcaster] Create ParamListener and get parameters on configure (`#698 `_)" (`#988 `_) +* Contributors: Christoph Fröhlich, Sai Kishor Kothakota + 4.4.0 (2024-01-11) ------------------ diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index e6f5e3d52f..6241e56ce1 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add tests for `interface_configuration_type` consistently (`#899 `_) +* Contributors: Christoph Fröhlich + 4.4.0 (2024-01-11) ------------------ diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index 677d52f784..5143c40545 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Let sphinx add parameter description with nested structures to documentation (`#652 `_) +* Contributors: Christoph Fröhlich + 4.4.0 (2024-01-11) ------------------ diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index 821ef8b385..4d3b88cbd9 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add tests for `interface_configuration_type` consistently (`#899 `_) +* Let sphinx add parameter description with nested structures to documentation (`#652 `_) +* Contributors: Christoph Fröhlich + 4.4.0 (2024-01-11) ------------------ diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index 0650f4e762..d9dc1645e2 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add tests for `interface_configuration_type` consistently (`#899 `_) +* Let sphinx add parameter description with nested structures to documentation (`#652 `_) +* Contributors: Christoph Fröhlich + 4.4.0 (2024-01-11) ------------------ diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index 5eb851589c..b6d85a29b5 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,16 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* [JTC] Fill action error_strings (`#887 `_) +* Add tests for `interface_configuration_type` consistently (`#899 `_) +* Let sphinx add parameter description with nested structures to documentation (`#652 `_) +* [JTC] Invalidate empty trajectory messages (`#902 `_) +* Revert "[JTC] Remove read_only from 'joints', 'state_interfaces' and 'command_interfaces' parameters (`#967 `_)" (`#978 `_) +* [JTC] Convert lambda to class functions (`#945 `_) +* Contributors: Christoph Fröhlich, Noel Jiménez García + 4.4.0 (2024-01-11) ------------------ * Cancel goal in on_deactivate (`#962 `_) diff --git a/pid_controller/CHANGELOG.rst b/pid_controller/CHANGELOG.rst index b492f15efa..c2a5e3a117 100644 --- a/pid_controller/CHANGELOG.rst +++ b/pid_controller/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package pid_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add tests for `interface_configuration_type` consistently (`#899 `_) +* [PID] Remove joint_jog include (`#975 `_) +* Contributors: Christoph Fröhlich + 4.4.0 (2024-01-11) ------------------ diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index 7c3392dae9..2268ccc082 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.4.0 (2024-01-11) ------------------ diff --git a/range_sensor_broadcaster/CHANGELOG.rst b/range_sensor_broadcaster/CHANGELOG.rst index 77a365009a..6d280dcd72 100644 --- a/range_sensor_broadcaster/CHANGELOG.rst +++ b/range_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package range_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add tests for `interface_configuration_type` consistently (`#899 `_) +* Let sphinx add parameter description with nested structures to documentation (`#652 `_) +* Contributors: Christoph Fröhlich + 4.4.0 (2024-01-11) ------------------ diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index bdb3c388dd..6f3c02f142 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.4.0 (2024-01-11) ------------------ diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index eab2bcfcb3..17033eae28 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.4.0 (2024-01-11) ------------------ diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index 0558e15d49..504366c761 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.4.0 (2024-01-11) ------------------ diff --git a/steering_controllers_library/CHANGELOG.rst b/steering_controllers_library/CHANGELOG.rst index ec986caddc..3483a6d388 100644 --- a/steering_controllers_library/CHANGELOG.rst +++ b/steering_controllers_library/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package steering_controllers_library ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add tests for `interface_configuration_type` consistently (`#899 `_) +* Contributors: Christoph Fröhlich + 4.4.0 (2024-01-11) ------------------ diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index a0dccedfe5..075b1f516e 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* [tricycle_controller] Use generate_parameter_library (`#957 `_) +* Contributors: Christoph Fröhlich + 4.4.0 (2024-01-11) ------------------ diff --git a/tricycle_steering_controller/CHANGELOG.rst b/tricycle_steering_controller/CHANGELOG.rst index 3be8c9ec03..184ffd20d5 100644 --- a/tricycle_steering_controller/CHANGELOG.rst +++ b/tricycle_steering_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package tricycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add tests for `interface_configuration_type` consistently (`#899 `_) +* Contributors: Christoph Fröhlich + 4.4.0 (2024-01-11) ------------------ diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index 8cc9c869ef..25bec1853d 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.4.0 (2024-01-11) ------------------ From fd8b91f74e9d6436b618f7b0daa252db55e90c73 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Wed, 31 Jan 2024 20:55:20 +0000 Subject: [PATCH 209/238] 4.5.0 --- ackermann_steering_controller/CHANGELOG.rst | 4 ++-- ackermann_steering_controller/package.xml | 2 +- admittance_controller/CHANGELOG.rst | 4 ++-- admittance_controller/package.xml | 2 +- bicycle_steering_controller/CHANGELOG.rst | 4 ++-- bicycle_steering_controller/package.xml | 2 +- diff_drive_controller/CHANGELOG.rst | 4 ++-- diff_drive_controller/package.xml | 2 +- effort_controllers/CHANGELOG.rst | 4 ++-- effort_controllers/package.xml | 2 +- force_torque_sensor_broadcaster/CHANGELOG.rst | 4 ++-- force_torque_sensor_broadcaster/package.xml | 2 +- forward_command_controller/CHANGELOG.rst | 4 ++-- forward_command_controller/package.xml | 2 +- gripper_controllers/CHANGELOG.rst | 4 ++-- gripper_controllers/package.xml | 2 +- imu_sensor_broadcaster/CHANGELOG.rst | 4 ++-- imu_sensor_broadcaster/package.xml | 2 +- joint_state_broadcaster/CHANGELOG.rst | 4 ++-- joint_state_broadcaster/package.xml | 2 +- joint_trajectory_controller/CHANGELOG.rst | 4 ++-- joint_trajectory_controller/package.xml | 2 +- pid_controller/CHANGELOG.rst | 4 ++-- pid_controller/package.xml | 2 +- position_controllers/CHANGELOG.rst | 4 ++-- position_controllers/package.xml | 2 +- range_sensor_broadcaster/CHANGELOG.rst | 4 ++-- range_sensor_broadcaster/package.xml | 2 +- ros2_controllers/CHANGELOG.rst | 4 ++-- ros2_controllers/package.xml | 2 +- ros2_controllers_test_nodes/CHANGELOG.rst | 4 ++-- ros2_controllers_test_nodes/package.xml | 2 +- ros2_controllers_test_nodes/setup.py | 2 +- rqt_joint_trajectory_controller/CHANGELOG.rst | 4 ++-- rqt_joint_trajectory_controller/package.xml | 2 +- rqt_joint_trajectory_controller/setup.py | 2 +- steering_controllers_library/CHANGELOG.rst | 4 ++-- steering_controllers_library/package.xml | 2 +- tricycle_controller/CHANGELOG.rst | 4 ++-- tricycle_controller/package.xml | 2 +- tricycle_steering_controller/CHANGELOG.rst | 4 ++-- tricycle_steering_controller/package.xml | 2 +- velocity_controllers/CHANGELOG.rst | 4 ++-- velocity_controllers/package.xml | 2 +- 44 files changed, 65 insertions(+), 65 deletions(-) diff --git a/ackermann_steering_controller/CHANGELOG.rst b/ackermann_steering_controller/CHANGELOG.rst index 83e135693c..3521258b1a 100644 --- a/ackermann_steering_controller/CHANGELOG.rst +++ b/ackermann_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ackermann_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.5.0 (2024-01-31) +------------------ * Add tests for `interface_configuration_type` consistently (`#899 `_) * Contributors: Christoph Fröhlich diff --git a/ackermann_steering_controller/package.xml b/ackermann_steering_controller/package.xml index 6c318219b2..366c5c31cf 100644 --- a/ackermann_steering_controller/package.xml +++ b/ackermann_steering_controller/package.xml @@ -2,7 +2,7 @@ ackermann_steering_controller - 4.4.0 + 4.5.0 Steering controller for Ackermann kinematics. Rear fixed wheels are powering the vehicle and front wheels are steering it. Apache License 2.0 Bence Magyar diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index 47f5d2ac30..ba1a25c0ab 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.5.0 (2024-01-31) +------------------ * Add tests for `interface_configuration_type` consistently (`#899 `_) * Let sphinx add parameter description with nested structures to documentation (`#652 `_) * Contributors: Christoph Fröhlich diff --git a/admittance_controller/package.xml b/admittance_controller/package.xml index fd7cf32401..d379438824 100644 --- a/admittance_controller/package.xml +++ b/admittance_controller/package.xml @@ -2,7 +2,7 @@ admittance_controller - 4.4.0 + 4.5.0 Implementation of admittance controllers for different input and output interface. Denis Štogl Bence Magyar diff --git a/bicycle_steering_controller/CHANGELOG.rst b/bicycle_steering_controller/CHANGELOG.rst index c44e1a9157..44d8e5051d 100644 --- a/bicycle_steering_controller/CHANGELOG.rst +++ b/bicycle_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package bicycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.5.0 (2024-01-31) +------------------ * Add tests for `interface_configuration_type` consistently (`#899 `_) * Contributors: Christoph Fröhlich diff --git a/bicycle_steering_controller/package.xml b/bicycle_steering_controller/package.xml index 2082124de6..cddfcf3975 100644 --- a/bicycle_steering_controller/package.xml +++ b/bicycle_steering_controller/package.xml @@ -2,7 +2,7 @@ bicycle_steering_controller - 4.4.0 + 4.5.0 Steering controller with bicycle kinematics. Rear fixed wheel is powering the vehicle and front wheel is steering. Apache License 2.0 Bence Magyar diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index d3f89a9eea..4a517f8a6d 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.5.0 (2024-01-31) +------------------ * [diff_drive] Remove unused parameter and add simple validation #abi-breaking (`#958 `_) * Add tests for `interface_configuration_type` consistently (`#899 `_) * Let sphinx add parameter description with nested structures to documentation (`#652 `_) diff --git a/diff_drive_controller/package.xml b/diff_drive_controller/package.xml index 9f79dabea6..4531a5337d 100644 --- a/diff_drive_controller/package.xml +++ b/diff_drive_controller/package.xml @@ -1,7 +1,7 @@ diff_drive_controller - 4.4.0 + 4.5.0 Controller for a differential drive mobile base. Bence Magyar Jordan Palacios diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index debb1f7717..2cb40f6e36 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.5.0 (2024-01-31) +------------------ 4.4.0 (2024-01-11) ------------------ diff --git a/effort_controllers/package.xml b/effort_controllers/package.xml index ee5504c672..ce2700ef01 100644 --- a/effort_controllers/package.xml +++ b/effort_controllers/package.xml @@ -1,7 +1,7 @@ effort_controllers - 4.4.0 + 4.5.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index 5b0be8fdbe..fc05235ade 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.5.0 (2024-01-31) +------------------ * Add tests for `interface_configuration_type` consistently (`#899 `_) * Let sphinx add parameter description with nested structures to documentation (`#652 `_) * Revert "[ForceTorqueSensorBroadcaster] Create ParamListener and get parameters on configure (`#698 `_)" (`#988 `_) diff --git a/force_torque_sensor_broadcaster/package.xml b/force_torque_sensor_broadcaster/package.xml index be9fc21d16..1ebd0c4a79 100644 --- a/force_torque_sensor_broadcaster/package.xml +++ b/force_torque_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ force_torque_sensor_broadcaster - 4.4.0 + 4.5.0 Controller to publish state of force-torque sensors. Bence Magyar Denis Štogl diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index 6241e56ce1..d0e32e8793 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.5.0 (2024-01-31) +------------------ * Add tests for `interface_configuration_type` consistently (`#899 `_) * Contributors: Christoph Fröhlich diff --git a/forward_command_controller/package.xml b/forward_command_controller/package.xml index c0827e9e20..cae9f877b7 100644 --- a/forward_command_controller/package.xml +++ b/forward_command_controller/package.xml @@ -1,7 +1,7 @@ forward_command_controller - 4.4.0 + 4.5.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index 5143c40545..9013897769 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.5.0 (2024-01-31) +------------------ * Let sphinx add parameter description with nested structures to documentation (`#652 `_) * Contributors: Christoph Fröhlich diff --git a/gripper_controllers/package.xml b/gripper_controllers/package.xml index 9488804f1d..348cf6dd93 100644 --- a/gripper_controllers/package.xml +++ b/gripper_controllers/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> gripper_controllers - 4.4.0 + 4.5.0 The gripper_controllers package Bence Magyar diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index 4d3b88cbd9..61d843c659 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.5.0 (2024-01-31) +------------------ * Add tests for `interface_configuration_type` consistently (`#899 `_) * Let sphinx add parameter description with nested structures to documentation (`#652 `_) * Contributors: Christoph Fröhlich diff --git a/imu_sensor_broadcaster/package.xml b/imu_sensor_broadcaster/package.xml index 184f9f7dd7..b6fc59d85c 100644 --- a/imu_sensor_broadcaster/package.xml +++ b/imu_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ imu_sensor_broadcaster - 4.4.0 + 4.5.0 Controller to publish readings of IMU sensors. Bence Magyar Denis Štogl diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index d9dc1645e2..cd80339155 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.5.0 (2024-01-31) +------------------ * Add tests for `interface_configuration_type` consistently (`#899 `_) * Let sphinx add parameter description with nested structures to documentation (`#652 `_) * Contributors: Christoph Fröhlich diff --git a/joint_state_broadcaster/package.xml b/joint_state_broadcaster/package.xml index 70d0f7daca..43dafb66b0 100644 --- a/joint_state_broadcaster/package.xml +++ b/joint_state_broadcaster/package.xml @@ -1,7 +1,7 @@ joint_state_broadcaster - 4.4.0 + 4.5.0 Broadcaster to publish joint state Bence Magyar Denis Stogl diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index b6d85a29b5..a41c70cbc7 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.5.0 (2024-01-31) +------------------ * [JTC] Fill action error_strings (`#887 `_) * Add tests for `interface_configuration_type` consistently (`#899 `_) * Let sphinx add parameter description with nested structures to documentation (`#652 `_) diff --git a/joint_trajectory_controller/package.xml b/joint_trajectory_controller/package.xml index bc6e43a1d5..030d91d3e9 100644 --- a/joint_trajectory_controller/package.xml +++ b/joint_trajectory_controller/package.xml @@ -1,7 +1,7 @@ joint_trajectory_controller - 4.4.0 + 4.5.0 Controller for executing joint-space trajectories on a group of joints Bence Magyar Dr. Denis Štogl diff --git a/pid_controller/CHANGELOG.rst b/pid_controller/CHANGELOG.rst index c2a5e3a117..40bfd292f5 100644 --- a/pid_controller/CHANGELOG.rst +++ b/pid_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package pid_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.5.0 (2024-01-31) +------------------ * Add tests for `interface_configuration_type` consistently (`#899 `_) * [PID] Remove joint_jog include (`#975 `_) * Contributors: Christoph Fröhlich diff --git a/pid_controller/package.xml b/pid_controller/package.xml index dc7f9c13be..4aa553f31a 100644 --- a/pid_controller/package.xml +++ b/pid_controller/package.xml @@ -2,7 +2,7 @@ pid_controller - 4.4.0 + 4.5.0 Controller based on PID implememenation from control_toolbox package. Bence Magyar Denis Štogl diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index 2268ccc082..e62920bf7f 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.5.0 (2024-01-31) +------------------ 4.4.0 (2024-01-11) ------------------ diff --git a/position_controllers/package.xml b/position_controllers/package.xml index b714afc89f..e6a98ef7d2 100644 --- a/position_controllers/package.xml +++ b/position_controllers/package.xml @@ -1,7 +1,7 @@ position_controllers - 4.4.0 + 4.5.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/range_sensor_broadcaster/CHANGELOG.rst b/range_sensor_broadcaster/CHANGELOG.rst index 6d280dcd72..09ce2703a7 100644 --- a/range_sensor_broadcaster/CHANGELOG.rst +++ b/range_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package range_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.5.0 (2024-01-31) +------------------ * Add tests for `interface_configuration_type` consistently (`#899 `_) * Let sphinx add parameter description with nested structures to documentation (`#652 `_) * Contributors: Christoph Fröhlich diff --git a/range_sensor_broadcaster/package.xml b/range_sensor_broadcaster/package.xml index d8213112da..c74acce857 100644 --- a/range_sensor_broadcaster/package.xml +++ b/range_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ range_sensor_broadcaster - 4.4.0 + 4.5.0 Controller to publish readings of Range sensors. Bence Magyar Florent Chretien diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index 6f3c02f142..8c96dc0ac0 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.5.0 (2024-01-31) +------------------ 4.4.0 (2024-01-11) ------------------ diff --git a/ros2_controllers/package.xml b/ros2_controllers/package.xml index 265adde781..d8477b3ccd 100644 --- a/ros2_controllers/package.xml +++ b/ros2_controllers/package.xml @@ -1,7 +1,7 @@ ros2_controllers - 4.4.0 + 4.5.0 Metapackage for ROS2 controllers related packages Bence Magyar Jordan Palacios diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index 17033eae28..ab8b17ea7a 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.5.0 (2024-01-31) +------------------ 4.4.0 (2024-01-11) ------------------ diff --git a/ros2_controllers_test_nodes/package.xml b/ros2_controllers_test_nodes/package.xml index f34838f5ff..4c99d9c18a 100644 --- a/ros2_controllers_test_nodes/package.xml +++ b/ros2_controllers_test_nodes/package.xml @@ -2,7 +2,7 @@ ros2_controllers_test_nodes - 4.4.0 + 4.5.0 Demo nodes for showing and testing functionalities of the ros2_control framework. Denis Štogl diff --git a/ros2_controllers_test_nodes/setup.py b/ros2_controllers_test_nodes/setup.py index d9c72db506..4c5afefe0a 100644 --- a/ros2_controllers_test_nodes/setup.py +++ b/ros2_controllers_test_nodes/setup.py @@ -20,7 +20,7 @@ setup( name=package_name, - version="4.4.0", + version="4.5.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index 504366c761..c143c7c6ad 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.5.0 (2024-01-31) +------------------ 4.4.0 (2024-01-11) ------------------ diff --git a/rqt_joint_trajectory_controller/package.xml b/rqt_joint_trajectory_controller/package.xml index 29db146abc..0929c2aaa3 100644 --- a/rqt_joint_trajectory_controller/package.xml +++ b/rqt_joint_trajectory_controller/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> rqt_joint_trajectory_controller - 4.4.0 + 4.5.0 Graphical frontend for interacting with joint_trajectory_controller instances. Bence Magyar diff --git a/rqt_joint_trajectory_controller/setup.py b/rqt_joint_trajectory_controller/setup.py index 02f32191d5..399ca590f9 100644 --- a/rqt_joint_trajectory_controller/setup.py +++ b/rqt_joint_trajectory_controller/setup.py @@ -7,7 +7,7 @@ setup( name=package_name, - version="4.4.0", + version="4.5.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/steering_controllers_library/CHANGELOG.rst b/steering_controllers_library/CHANGELOG.rst index 3483a6d388..8d67b186b6 100644 --- a/steering_controllers_library/CHANGELOG.rst +++ b/steering_controllers_library/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package steering_controllers_library ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.5.0 (2024-01-31) +------------------ * Add tests for `interface_configuration_type` consistently (`#899 `_) * Contributors: Christoph Fröhlich diff --git a/steering_controllers_library/package.xml b/steering_controllers_library/package.xml index 90cb82ac8e..66a968b71f 100644 --- a/steering_controllers_library/package.xml +++ b/steering_controllers_library/package.xml @@ -2,7 +2,7 @@ steering_controllers_library - 4.4.0 + 4.5.0 Package for steering robot configurations including odometry and interfaces. Apache License 2.0 Bence Magyar diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index 075b1f516e..289ff3e6b0 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.5.0 (2024-01-31) +------------------ * [tricycle_controller] Use generate_parameter_library (`#957 `_) * Contributors: Christoph Fröhlich diff --git a/tricycle_controller/package.xml b/tricycle_controller/package.xml index cc50f0d58c..d53e8473a1 100644 --- a/tricycle_controller/package.xml +++ b/tricycle_controller/package.xml @@ -2,7 +2,7 @@ tricycle_controller - 4.4.0 + 4.5.0 Controller for a tricycle drive mobile base Bence Magyar Tony Najjar diff --git a/tricycle_steering_controller/CHANGELOG.rst b/tricycle_steering_controller/CHANGELOG.rst index 184ffd20d5..4f8d2be9f4 100644 --- a/tricycle_steering_controller/CHANGELOG.rst +++ b/tricycle_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package tricycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.5.0 (2024-01-31) +------------------ * Add tests for `interface_configuration_type` consistently (`#899 `_) * Contributors: Christoph Fröhlich diff --git a/tricycle_steering_controller/package.xml b/tricycle_steering_controller/package.xml index ad1c07d396..0263f8f9fe 100644 --- a/tricycle_steering_controller/package.xml +++ b/tricycle_steering_controller/package.xml @@ -2,7 +2,7 @@ tricycle_steering_controller - 4.4.0 + 4.5.0 Steering controller with tricycle kinematics. Rear fixed wheels are powering the vehicle and front wheel is steering. Apache License 2.0 Bence Magyar diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index 25bec1853d..cbf4e9d068 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.5.0 (2024-01-31) +------------------ 4.4.0 (2024-01-11) ------------------ diff --git a/velocity_controllers/package.xml b/velocity_controllers/package.xml index 5319f55a97..94d61b8ae1 100644 --- a/velocity_controllers/package.xml +++ b/velocity_controllers/package.xml @@ -1,7 +1,7 @@ velocity_controllers - 4.4.0 + 4.5.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios From 2817f2779673e43d1c63ee0d8b35c8ed6f85410d Mon Sep 17 00:00:00 2001 From: Sai Kishor Kothakota Date: Thu, 1 Feb 2024 11:19:13 +0100 Subject: [PATCH 210/238] Fix tests for using new `get_node_options` API (#840) --- .../test/test_ackermann_steering_controller.hpp | 4 +++- .../test/test_bicycle_steering_controller.hpp | 4 +++- .../test/test_diff_drive_controller.cpp | 3 ++- doc/writing_new_controller.rst | 4 +++- .../test/test_joint_group_effort_controller.cpp | 3 ++- .../test/test_force_torque_sensor_broadcaster.cpp | 4 +++- .../test/test_forward_command_controller.cpp | 3 ++- .../test_multi_interface_forward_command_controller.cpp | 4 +++- gripper_controllers/test/test_gripper_controllers.cpp | 3 ++- .../test/test_imu_sensor_broadcaster.cpp | 3 ++- .../test/test_joint_state_broadcaster.cpp | 3 ++- .../test/test_trajectory_controller_utils.hpp | 9 ++++++++- pid_controller/test/test_pid_controller.hpp | 4 +++- .../test/test_joint_group_position_controller.cpp | 3 ++- .../test/test_range_sensor_broadcaster.cpp | 3 ++- .../test/test_steering_controllers_library.hpp | 4 +++- tricycle_controller/test/test_tricycle_controller.cpp | 3 ++- .../test/test_tricycle_steering_controller.hpp | 4 +++- .../test/test_joint_group_velocity_controller.cpp | 3 ++- 19 files changed, 52 insertions(+), 19 deletions(-) diff --git a/ackermann_steering_controller/test/test_ackermann_steering_controller.hpp b/ackermann_steering_controller/test/test_ackermann_steering_controller.hpp index 7c279d6323..a047186d14 100644 --- a/ackermann_steering_controller/test/test_ackermann_steering_controller.hpp +++ b/ackermann_steering_controller/test/test_ackermann_steering_controller.hpp @@ -147,7 +147,9 @@ class AckermannSteeringControllerFixture : public ::testing::Test protected: void SetUpController(const std::string controller_name = "test_ackermann_steering_controller") { - ASSERT_EQ(controller_->init(controller_name, "", 0), controller_interface::return_type::OK); + ASSERT_EQ( + controller_->init(controller_name, "", 0, "", controller_->define_custom_node_options()), + controller_interface::return_type::OK); if (position_feedback_ == true) { diff --git a/bicycle_steering_controller/test/test_bicycle_steering_controller.hpp b/bicycle_steering_controller/test/test_bicycle_steering_controller.hpp index 6e84342bea..5e21ff228c 100644 --- a/bicycle_steering_controller/test/test_bicycle_steering_controller.hpp +++ b/bicycle_steering_controller/test/test_bicycle_steering_controller.hpp @@ -144,7 +144,9 @@ class BicycleSteeringControllerFixture : public ::testing::Test protected: void SetUpController(const std::string controller_name = "test_bicycle_steering_controller") { - ASSERT_EQ(controller_->init(controller_name, "", 0), controller_interface::return_type::OK); + ASSERT_EQ( + controller_->init(controller_name, "", 0, "", controller_->define_custom_node_options()), + controller_interface::return_type::OK); if (position_feedback_ == true) { diff --git a/diff_drive_controller/test/test_diff_drive_controller.cpp b/diff_drive_controller/test/test_diff_drive_controller.cpp index 43dae41a9b..9ab3022a9f 100644 --- a/diff_drive_controller/test/test_diff_drive_controller.cpp +++ b/diff_drive_controller/test/test_diff_drive_controller.cpp @@ -218,7 +218,8 @@ class TestDiffDriveController : public ::testing::Test TEST_F(TestDiffDriveController, init_fails_without_parameters) { - const auto ret = controller_->init(controller_name, urdf_, 0); + const auto ret = + controller_->init(controller_name, urdf_, 0, "", controller_->define_custom_node_options()); ASSERT_EQ(ret, controller_interface::return_type::ERROR); } diff --git a/doc/writing_new_controller.rst b/doc/writing_new_controller.rst index 501c231def..1a9ffce714 100644 --- a/doc/writing_new_controller.rst +++ b/doc/writing_new_controller.rst @@ -42,7 +42,9 @@ The following is a step-by-step guide to create source files, basic tests, and c 5. Add a constructor without parameters and the following public methods overriding the ``ControllerInterface`` definition: ``on_init``, ``command_interface_configuration``, ``state_interface_configuration``, ``on_configure``, ``on_activate``, ``on_deactivate``, ``update``. For exact definitions check the ``controller_interface/controller_interface.hpp`` header or one of the controllers from `ros2_controllers `_. - 6. (optional) Often, controllers accept lists of joint names and interface names as parameters. + 6. (Optional) The NodeOptions of the LifecycleNode can be personalized by overriding the default method ``get_node_options``. + + 7. (Optional) Often, controllers accept lists of joint names and interface names as parameters. If so, you can add two protected string vectors to store those values. 4. **Adding definitions into source file (.cpp)** diff --git a/effort_controllers/test/test_joint_group_effort_controller.cpp b/effort_controllers/test/test_joint_group_effort_controller.cpp index f9d72ab202..200a1beda8 100644 --- a/effort_controllers/test/test_joint_group_effort_controller.cpp +++ b/effort_controllers/test/test_joint_group_effort_controller.cpp @@ -54,7 +54,8 @@ void JointGroupEffortControllerTest::TearDown() { controller_.reset(nullptr); } void JointGroupEffortControllerTest::SetUpController() { - const auto result = controller_->init("test_joint_group_effort_controller", "", 0); + const auto result = controller_->init( + "test_joint_group_effort_controller", "", 0, "", controller_->define_custom_node_options()); ASSERT_EQ(result, controller_interface::return_type::OK); std::vector command_ifs; diff --git a/force_torque_sensor_broadcaster/test/test_force_torque_sensor_broadcaster.cpp b/force_torque_sensor_broadcaster/test/test_force_torque_sensor_broadcaster.cpp index 8b994307fa..2412361352 100644 --- a/force_torque_sensor_broadcaster/test/test_force_torque_sensor_broadcaster.cpp +++ b/force_torque_sensor_broadcaster/test/test_force_torque_sensor_broadcaster.cpp @@ -55,7 +55,9 @@ void ForceTorqueSensorBroadcasterTest::TearDown() { fts_broadcaster_.reset(nullp void ForceTorqueSensorBroadcasterTest::SetUpFTSBroadcaster() { - const auto result = fts_broadcaster_->init("test_force_torque_sensor_broadcaster", "", 0); + const auto result = fts_broadcaster_->init( + "test_force_torque_sensor_broadcaster", "", 0, "", + fts_broadcaster_->define_custom_node_options()); ASSERT_EQ(result, controller_interface::return_type::OK); std::vector state_ifs; diff --git a/forward_command_controller/test/test_forward_command_controller.cpp b/forward_command_controller/test/test_forward_command_controller.cpp index 937144b48c..c31c8a964c 100644 --- a/forward_command_controller/test/test_forward_command_controller.cpp +++ b/forward_command_controller/test/test_forward_command_controller.cpp @@ -62,7 +62,8 @@ void ForwardCommandControllerTest::TearDown() { controller_.reset(nullptr); } void ForwardCommandControllerTest::SetUpController() { - const auto result = controller_->init("forward_command_controller", "", 0); + const auto result = controller_->init( + "forward_command_controller", "", 0, "", controller_->define_custom_node_options()); ASSERT_EQ(result, controller_interface::return_type::OK); std::vector command_ifs; diff --git a/forward_command_controller/test/test_multi_interface_forward_command_controller.cpp b/forward_command_controller/test/test_multi_interface_forward_command_controller.cpp index f8f073c103..7879d5c1d7 100644 --- a/forward_command_controller/test/test_multi_interface_forward_command_controller.cpp +++ b/forward_command_controller/test/test_multi_interface_forward_command_controller.cpp @@ -64,7 +64,9 @@ void MultiInterfaceForwardCommandControllerTest::TearDown() { controller_.reset( void MultiInterfaceForwardCommandControllerTest::SetUpController(bool set_params_and_activate) { - const auto result = controller_->init("multi_interface_forward_command_controller", "", 0); + const auto result = controller_->init( + "multi_interface_forward_command_controller", "", 0, "", + controller_->define_custom_node_options()); ASSERT_EQ(result, controller_interface::return_type::OK); std::vector command_ifs; diff --git a/gripper_controllers/test/test_gripper_controllers.cpp b/gripper_controllers/test/test_gripper_controllers.cpp index da9e15840e..9f7e024917 100644 --- a/gripper_controllers/test/test_gripper_controllers.cpp +++ b/gripper_controllers/test/test_gripper_controllers.cpp @@ -62,7 +62,8 @@ void GripperControllerTest::TearDown() template void GripperControllerTest::SetUpController() { - const auto result = controller_->init("gripper_controller", "", 0); + const auto result = + controller_->init("gripper_controller", "", 0, "", controller_->define_custom_node_options()); ASSERT_EQ(result, controller_interface::return_type::OK); std::vector command_ifs; diff --git a/imu_sensor_broadcaster/test/test_imu_sensor_broadcaster.cpp b/imu_sensor_broadcaster/test/test_imu_sensor_broadcaster.cpp index 62179a99ff..25a39a8b4d 100644 --- a/imu_sensor_broadcaster/test/test_imu_sensor_broadcaster.cpp +++ b/imu_sensor_broadcaster/test/test_imu_sensor_broadcaster.cpp @@ -55,7 +55,8 @@ void IMUSensorBroadcasterTest::TearDown() { imu_broadcaster_.reset(nullptr); } void IMUSensorBroadcasterTest::SetUpIMUBroadcaster() { - const auto result = imu_broadcaster_->init("test_imu_sensor_broadcaster", "", 0); + const auto result = imu_broadcaster_->init( + "test_imu_sensor_broadcaster", "", 0, "", imu_broadcaster_->define_custom_node_options()); ASSERT_EQ(result, controller_interface::return_type::OK); std::vector state_ifs; diff --git a/joint_state_broadcaster/test/test_joint_state_broadcaster.cpp b/joint_state_broadcaster/test/test_joint_state_broadcaster.cpp index c10f51aaa2..2faa55f467 100644 --- a/joint_state_broadcaster/test/test_joint_state_broadcaster.cpp +++ b/joint_state_broadcaster/test/test_joint_state_broadcaster.cpp @@ -69,7 +69,8 @@ void JointStateBroadcasterTest::SetUpStateBroadcaster( void JointStateBroadcasterTest::init_broadcaster_and_set_parameters( const std::vector & joint_names, const std::vector & interfaces) { - const auto result = state_broadcaster_->init("joint_state_broadcaster", "", 0); + const auto result = state_broadcaster_->init( + "joint_state_broadcaster", "", 0, "", state_broadcaster_->define_custom_node_options()); ASSERT_EQ(result, controller_interface::return_type::OK); state_broadcaster_->get_node()->set_parameter({"joints", joint_names}); diff --git a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp index f98fd3e286..6978d0e452 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp +++ b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp @@ -66,6 +66,8 @@ class TestableJointTrajectoryController return ret; } + rclcpp::NodeOptions define_custom_node_options() const override { return node_options_; } + /** * @brief wait_for_trajectory block until a new JointTrajectory is received. * Requires that the executor is not spinned elsewhere between the @@ -157,6 +159,8 @@ class TestableJointTrajectoryController double get_cmd_timeout() { return cmd_timeout_; } + void set_node_options(const rclcpp::NodeOptions & node_options) { node_options_ = node_options; } + trajectory_msgs::msg::JointTrajectoryPoint get_state_feedback() { return state_current_; } trajectory_msgs::msg::JointTrajectoryPoint get_state_reference() { return state_desired_; } trajectory_msgs::msg::JointTrajectoryPoint get_state_error() { return state_error_; } @@ -179,6 +183,7 @@ class TestableJointTrajectoryController } rclcpp::WaitSet joint_cmd_sub_wait_set_; + rclcpp::NodeOptions node_options_; }; class TrajectoryControllerTest : public ::testing::Test @@ -233,8 +238,10 @@ class TrajectoryControllerTest : public ::testing::Test parameter_overrides.push_back(rclcpp::Parameter("state_interfaces", state_interface_types_)); parameter_overrides.insert(parameter_overrides.end(), parameters.begin(), parameters.end()); node_options.parameter_overrides(parameter_overrides); + traj_controller_->set_node_options(node_options); - return traj_controller_->init(controller_name_, "", 0, "", node_options); + return traj_controller_->init( + controller_name_, "", 0, "", traj_controller_->define_custom_node_options()); } void SetPidParameters( diff --git a/pid_controller/test/test_pid_controller.hpp b/pid_controller/test/test_pid_controller.hpp index ab32f5cb48..1c356263e7 100644 --- a/pid_controller/test/test_pid_controller.hpp +++ b/pid_controller/test/test_pid_controller.hpp @@ -146,7 +146,9 @@ class PidControllerFixture : public ::testing::Test protected: void SetUpController(const std::string controller_name = "test_pid_controller") { - ASSERT_EQ(controller_->init(controller_name, "", 0), controller_interface::return_type::OK); + ASSERT_EQ( + controller_->init(controller_name, "", 0, "", controller_->define_custom_node_options()), + controller_interface::return_type::OK); std::vector command_ifs; command_itfs_.reserve(dof_names_.size()); diff --git a/position_controllers/test/test_joint_group_position_controller.cpp b/position_controllers/test/test_joint_group_position_controller.cpp index 3b4f00be12..60bff556db 100644 --- a/position_controllers/test/test_joint_group_position_controller.cpp +++ b/position_controllers/test/test_joint_group_position_controller.cpp @@ -54,7 +54,8 @@ void JointGroupPositionControllerTest::TearDown() { controller_.reset(nullptr); void JointGroupPositionControllerTest::SetUpController() { - const auto result = controller_->init("test_joint_group_position_controller", "", 0); + const auto result = controller_->init( + "test_joint_group_position_controller", "", 0, "", controller_->define_custom_node_options()); ASSERT_EQ(result, controller_interface::return_type::OK); std::vector command_ifs; diff --git a/range_sensor_broadcaster/test/test_range_sensor_broadcaster.cpp b/range_sensor_broadcaster/test/test_range_sensor_broadcaster.cpp index 64f68a7e7a..010f18c1a6 100644 --- a/range_sensor_broadcaster/test/test_range_sensor_broadcaster.cpp +++ b/range_sensor_broadcaster/test/test_range_sensor_broadcaster.cpp @@ -37,7 +37,8 @@ controller_interface::return_type RangeSensorBroadcasterTest::init_broadcaster( std::string broadcaster_name) { controller_interface::return_type result = controller_interface::return_type::ERROR; - result = range_broadcaster_->init(broadcaster_name, "", 0); + result = range_broadcaster_->init( + broadcaster_name, "", 0, "", range_broadcaster_->define_custom_node_options()); if (controller_interface::return_type::OK == result) { diff --git a/steering_controllers_library/test/test_steering_controllers_library.hpp b/steering_controllers_library/test/test_steering_controllers_library.hpp index 83e6054bd4..1284b72096 100644 --- a/steering_controllers_library/test/test_steering_controllers_library.hpp +++ b/steering_controllers_library/test/test_steering_controllers_library.hpp @@ -168,7 +168,9 @@ class SteeringControllersLibraryFixture : public ::testing::Test protected: void SetUpController(const std::string controller_name = "test_steering_controllers_library") { - ASSERT_EQ(controller_->init(controller_name, "", 0), controller_interface::return_type::OK); + ASSERT_EQ( + controller_->init(controller_name, "", 0, "", controller_->define_custom_node_options()), + controller_interface::return_type::OK); if (position_feedback_ == true) { diff --git a/tricycle_controller/test/test_tricycle_controller.cpp b/tricycle_controller/test/test_tricycle_controller.cpp index 018727e260..5280aaf244 100644 --- a/tricycle_controller/test/test_tricycle_controller.cpp +++ b/tricycle_controller/test/test_tricycle_controller.cpp @@ -197,7 +197,8 @@ class TestTricycleController : public ::testing::Test TEST_F(TestTricycleController, init_fails_without_parameters) { - const auto ret = controller_->init(controller_name, urdf_, 0); + const auto ret = + controller_->init(controller_name, urdf_, 0, "", controller_->define_custom_node_options()); ASSERT_EQ(ret, controller_interface::return_type::ERROR); } diff --git a/tricycle_steering_controller/test/test_tricycle_steering_controller.hpp b/tricycle_steering_controller/test/test_tricycle_steering_controller.hpp index e97e2a45bd..6a516691b8 100644 --- a/tricycle_steering_controller/test/test_tricycle_steering_controller.hpp +++ b/tricycle_steering_controller/test/test_tricycle_steering_controller.hpp @@ -146,7 +146,9 @@ class TricycleSteeringControllerFixture : public ::testing::Test protected: void SetUpController(const std::string controller_name = "test_tricycle_steering_controller") { - ASSERT_EQ(controller_->init(controller_name, "", 0), controller_interface::return_type::OK); + ASSERT_EQ( + controller_->init(controller_name, "", 0, "", controller_->define_custom_node_options()), + controller_interface::return_type::OK); if (position_feedback_ == true) { diff --git a/velocity_controllers/test/test_joint_group_velocity_controller.cpp b/velocity_controllers/test/test_joint_group_velocity_controller.cpp index 4cbf1b7342..a99ffaeebf 100644 --- a/velocity_controllers/test/test_joint_group_velocity_controller.cpp +++ b/velocity_controllers/test/test_joint_group_velocity_controller.cpp @@ -54,7 +54,8 @@ void JointGroupVelocityControllerTest::TearDown() { controller_.reset(nullptr); void JointGroupVelocityControllerTest::SetUpController() { - const auto result = controller_->init("test_joint_group_velocity_controller", "", 0); + const auto result = controller_->init( + "test_joint_group_velocity_controller", "", 0, "", controller_->define_custom_node_options()); ASSERT_EQ(result, controller_interface::return_type::OK); std::vector command_ifs; From 737a45b170e79c0f6bd033b37c0def6d00ab4adf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Mon, 5 Feb 2024 07:22:08 +0100 Subject: [PATCH 211/238] Use correct ref for scheduled workflows (#1013) --- .github/workflows/humble-debian-build.yml | 1 + .github/workflows/humble-rhel-binary-build.yml | 1 + .github/workflows/iron-debian-build.yml | 1 + .github/workflows/iron-rhel-binary-build.yml | 1 + .github/workflows/rolling-debian-build.yml | 2 ++ .github/workflows/rolling-rhel-binary-build.yml | 2 ++ 6 files changed, 8 insertions(+) diff --git a/.github/workflows/humble-debian-build.yml b/.github/workflows/humble-debian-build.yml index e8deb2caa5..426b935fa4 100644 --- a/.github/workflows/humble-debian-build.yml +++ b/.github/workflows/humble-debian-build.yml @@ -20,6 +20,7 @@ jobs: - uses: actions/checkout@v4 with: path: src/ros2_controllers + ref: ${{ github.event_name == 'schedule' && 'humble' || '' }} - name: Build and test shell: bash run: | diff --git a/.github/workflows/humble-rhel-binary-build.yml b/.github/workflows/humble-rhel-binary-build.yml index cd9b85b2e1..933486ba50 100644 --- a/.github/workflows/humble-rhel-binary-build.yml +++ b/.github/workflows/humble-rhel-binary-build.yml @@ -19,6 +19,7 @@ jobs: - uses: actions/checkout@v4 with: path: src/ros2_controllers + ref: ${{ github.event_name == 'schedule' && 'humble' || '' }} - name: Install dependencies run: | rosdep update diff --git a/.github/workflows/iron-debian-build.yml b/.github/workflows/iron-debian-build.yml index 09dbd051b2..c47fbe5cd9 100644 --- a/.github/workflows/iron-debian-build.yml +++ b/.github/workflows/iron-debian-build.yml @@ -20,6 +20,7 @@ jobs: - uses: actions/checkout@v4 with: path: src/ros2_controllers + ref: ${{ github.event_name == 'schedule' && 'iron' || '' }} - name: Build and test shell: bash run: | diff --git a/.github/workflows/iron-rhel-binary-build.yml b/.github/workflows/iron-rhel-binary-build.yml index 0eb28b9673..c3bc1e6def 100644 --- a/.github/workflows/iron-rhel-binary-build.yml +++ b/.github/workflows/iron-rhel-binary-build.yml @@ -20,6 +20,7 @@ jobs: - uses: actions/checkout@v4 with: path: src/ros2_controllers + ref: ${{ github.event_name == 'schedule' && 'iron' || '' }} - name: Install dependencies run: | rosdep update diff --git a/.github/workflows/rolling-debian-build.yml b/.github/workflows/rolling-debian-build.yml index b6d0a4193a..9169494b00 100644 --- a/.github/workflows/rolling-debian-build.yml +++ b/.github/workflows/rolling-debian-build.yml @@ -20,6 +20,8 @@ jobs: - uses: actions/checkout@v4 with: path: src/ros2_controllers + # default behavior is correct on master branch + # ref: ${{ github.event_name == 'schedule' && 'master' || '' }} - name: Build and test shell: bash run: | diff --git a/.github/workflows/rolling-rhel-binary-build.yml b/.github/workflows/rolling-rhel-binary-build.yml index dece43b673..98c02b72a3 100644 --- a/.github/workflows/rolling-rhel-binary-build.yml +++ b/.github/workflows/rolling-rhel-binary-build.yml @@ -20,6 +20,8 @@ jobs: - uses: actions/checkout@v4 with: path: src/ros2_controllers + # default behavior is correct on master branch + # ref: ${{ github.event_name == 'schedule' && 'master' || '' }} - name: Install dependencies run: | rosdep update From 8bf379b2726900adec452193a777d900ba152e89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Mon, 5 Feb 2024 09:38:34 +0100 Subject: [PATCH 212/238] Add test_depend on `hardware_interface_testing` (#1018) --- ackermann_steering_controller/package.xml | 1 + admittance_controller/package.xml | 1 + bicycle_steering_controller/package.xml | 1 + diff_drive_controller/test/test_load_diff_drive_controller.cpp | 3 +++ effort_controllers/package.xml | 2 ++ .../test/test_load_joint_group_effort_controller.cpp | 2 ++ force_torque_sensor_broadcaster/package.xml | 1 + forward_command_controller/package.xml | 1 + gripper_controllers/package.xml | 1 + .../test/test_load_gripper_action_controllers.cpp | 2 ++ imu_sensor_broadcaster/package.xml | 1 + joint_state_broadcaster/package.xml | 1 + joint_trajectory_controller/package.xml | 1 + pid_controller/package.xml | 1 + position_controllers/package.xml | 2 ++ .../test/test_load_joint_group_position_controller.cpp | 2 ++ range_sensor_broadcaster/package.xml | 2 +- tricycle_controller/package.xml | 1 + tricycle_controller/test/test_load_tricycle_controller.cpp | 2 ++ tricycle_steering_controller/package.xml | 2 +- velocity_controllers/package.xml | 1 + .../test/test_load_joint_group_velocity_controller.cpp | 2 ++ 22 files changed, 31 insertions(+), 2 deletions(-) diff --git a/ackermann_steering_controller/package.xml b/ackermann_steering_controller/package.xml index 366c5c31cf..fe22ca10b8 100644 --- a/ackermann_steering_controller/package.xml +++ b/ackermann_steering_controller/package.xml @@ -27,6 +27,7 @@ ament_cmake_gmock controller_manager + hardware_interface_testing hardware_interface ros2_control_test_assets diff --git a/admittance_controller/package.xml b/admittance_controller/package.xml index d379438824..e690330aa0 100644 --- a/admittance_controller/package.xml +++ b/admittance_controller/package.xml @@ -34,6 +34,7 @@ ament_cmake_gmock controller_manager + hardware_interface_testing kinematics_interface_kdl ros2_control_test_assets diff --git a/bicycle_steering_controller/package.xml b/bicycle_steering_controller/package.xml index cddfcf3975..8bb6ac79fa 100644 --- a/bicycle_steering_controller/package.xml +++ b/bicycle_steering_controller/package.xml @@ -28,6 +28,7 @@ ament_cmake_gmock controller_manager hardware_interface + hardware_interface_testing ros2_control_test_assets diff --git a/diff_drive_controller/test/test_load_diff_drive_controller.cpp b/diff_drive_controller/test/test_load_diff_drive_controller.cpp index 983ec6d98f..4c9d2f984f 100644 --- a/diff_drive_controller/test/test_load_diff_drive_controller.cpp +++ b/diff_drive_controller/test/test_load_diff_drive_controller.cpp @@ -16,6 +16,9 @@ #include #include "controller_manager/controller_manager.hpp" +#include "hardware_interface/resource_manager.hpp" +#include "rclcpp/executor.hpp" +#include "rclcpp/executors/single_threaded_executor.hpp" #include "rclcpp/utilities.hpp" #include "ros2_control_test_assets/descriptions.hpp" diff --git a/effort_controllers/package.xml b/effort_controllers/package.xml index ce2700ef01..279d5fbf43 100644 --- a/effort_controllers/package.xml +++ b/effort_controllers/package.xml @@ -17,6 +17,8 @@ ament_cmake_gmock controller_manager + hardware_interface_testing + hardware_interface ros2_control_test_assets diff --git a/effort_controllers/test/test_load_joint_group_effort_controller.cpp b/effort_controllers/test/test_load_joint_group_effort_controller.cpp index 61bb1ddf9a..52f1f9934a 100644 --- a/effort_controllers/test/test_load_joint_group_effort_controller.cpp +++ b/effort_controllers/test/test_load_joint_group_effort_controller.cpp @@ -17,7 +17,9 @@ #include "controller_manager/controller_manager.hpp" #include "hardware_interface/resource_manager.hpp" +#include "rclcpp/executor.hpp" #include "rclcpp/executors/single_threaded_executor.hpp" +#include "rclcpp/utilities.hpp" #include "ros2_control_test_assets/descriptions.hpp" TEST(TestLoadJointGroupVelocityController, load_controller) diff --git a/force_torque_sensor_broadcaster/package.xml b/force_torque_sensor_broadcaster/package.xml index 1ebd0c4a79..0791eb5d16 100644 --- a/force_torque_sensor_broadcaster/package.xml +++ b/force_torque_sensor_broadcaster/package.xml @@ -23,6 +23,7 @@ ament_cmake_gmock controller_manager + hardware_interface_testing ros2_control_test_assets diff --git a/forward_command_controller/package.xml b/forward_command_controller/package.xml index cae9f877b7..8950a9a3e9 100644 --- a/forward_command_controller/package.xml +++ b/forward_command_controller/package.xml @@ -22,6 +22,7 @@ ament_cmake_gmock controller_manager + hardware_interface_testing ros2_control_test_assets diff --git a/gripper_controllers/package.xml b/gripper_controllers/package.xml index 348cf6dd93..a35fce7894 100644 --- a/gripper_controllers/package.xml +++ b/gripper_controllers/package.xml @@ -27,6 +27,7 @@ ament_cmake_gmock controller_manager + hardware_interface_testing ros2_control_test_assets diff --git a/gripper_controllers/test/test_load_gripper_action_controllers.cpp b/gripper_controllers/test/test_load_gripper_action_controllers.cpp index 130b12e0bb..0ef5f0bcb2 100644 --- a/gripper_controllers/test/test_load_gripper_action_controllers.cpp +++ b/gripper_controllers/test/test_load_gripper_action_controllers.cpp @@ -17,7 +17,9 @@ #include "controller_manager/controller_manager.hpp" #include "hardware_interface/resource_manager.hpp" +#include "rclcpp/executor.hpp" #include "rclcpp/executors/single_threaded_executor.hpp" +#include "rclcpp/utilities.hpp" #include "ros2_control_test_assets/descriptions.hpp" TEST(TestLoadGripperActionControllers, load_controller) diff --git a/imu_sensor_broadcaster/package.xml b/imu_sensor_broadcaster/package.xml index b6fc59d85c..5694e1cee7 100644 --- a/imu_sensor_broadcaster/package.xml +++ b/imu_sensor_broadcaster/package.xml @@ -25,6 +25,7 @@ ament_lint_auto ament_lint_common controller_manager + hardware_interface_testing ros2_control_test_assets diff --git a/joint_state_broadcaster/package.xml b/joint_state_broadcaster/package.xml index 43dafb66b0..6dd8b4b61e 100644 --- a/joint_state_broadcaster/package.xml +++ b/joint_state_broadcaster/package.xml @@ -25,6 +25,7 @@ ament_cmake_gmock controller_manager + hardware_interface_testing hardware_interface rclcpp ros2_control_test_assets diff --git a/joint_trajectory_controller/package.xml b/joint_trajectory_controller/package.xml index 030d91d3e9..8cd2e5becc 100644 --- a/joint_trajectory_controller/package.xml +++ b/joint_trajectory_controller/package.xml @@ -28,6 +28,7 @@ ament_cmake_gmock controller_manager + hardware_interface_testing ros2_control_test_assets diff --git a/pid_controller/package.xml b/pid_controller/package.xml index 4aa553f31a..70c7bfa987 100644 --- a/pid_controller/package.xml +++ b/pid_controller/package.xml @@ -27,6 +27,7 @@ ament_cmake_gmock controller_manager + hardware_interface_testing ros2_control_test_assets diff --git a/position_controllers/package.xml b/position_controllers/package.xml index e6a98ef7d2..e67d3d8a46 100644 --- a/position_controllers/package.xml +++ b/position_controllers/package.xml @@ -17,6 +17,8 @@ ament_cmake_gmock controller_manager + hardware_interface_testing + hardware_interface ros2_control_test_assets diff --git a/position_controllers/test/test_load_joint_group_position_controller.cpp b/position_controllers/test/test_load_joint_group_position_controller.cpp index fe61039fdb..bc27b5e629 100644 --- a/position_controllers/test/test_load_joint_group_position_controller.cpp +++ b/position_controllers/test/test_load_joint_group_position_controller.cpp @@ -17,7 +17,9 @@ #include "controller_manager/controller_manager.hpp" #include "hardware_interface/resource_manager.hpp" +#include "rclcpp/executor.hpp" #include "rclcpp/executors/single_threaded_executor.hpp" +#include "rclcpp/utilities.hpp" #include "ros2_control_test_assets/descriptions.hpp" TEST(TestLoadJointGroupPositionController, load_controller) diff --git a/range_sensor_broadcaster/package.xml b/range_sensor_broadcaster/package.xml index c74acce857..2d865c1d7f 100644 --- a/range_sensor_broadcaster/package.xml +++ b/range_sensor_broadcaster/package.xml @@ -22,7 +22,7 @@ ament_cmake_gmock controller_manager - hardware_interface + hardware_interface_testing ros2_control_test_assets diff --git a/tricycle_controller/package.xml b/tricycle_controller/package.xml index d53e8473a1..4a8725810b 100644 --- a/tricycle_controller/package.xml +++ b/tricycle_controller/package.xml @@ -30,6 +30,7 @@ ament_cmake_gmock controller_manager + hardware_interface_testing ros2_control_test_assets diff --git a/tricycle_controller/test/test_load_tricycle_controller.cpp b/tricycle_controller/test/test_load_tricycle_controller.cpp index 245523c844..bd54459780 100644 --- a/tricycle_controller/test/test_load_tricycle_controller.cpp +++ b/tricycle_controller/test/test_load_tricycle_controller.cpp @@ -21,7 +21,9 @@ #include "controller_manager/controller_manager.hpp" #include "hardware_interface/resource_manager.hpp" +#include "rclcpp/executor.hpp" #include "rclcpp/executors/single_threaded_executor.hpp" +#include "rclcpp/utilities.hpp" #include "ros2_control_test_assets/descriptions.hpp" TEST(TestLoadTricycleController, load_controller) diff --git a/tricycle_steering_controller/package.xml b/tricycle_steering_controller/package.xml index 0263f8f9fe..16bfd522f7 100644 --- a/tricycle_steering_controller/package.xml +++ b/tricycle_steering_controller/package.xml @@ -29,7 +29,7 @@ ament_cmake_gmock controller_manager - hardware_interface + hardware_interface_testing ros2_control_test_assets diff --git a/velocity_controllers/package.xml b/velocity_controllers/package.xml index 94d61b8ae1..3e28f7736e 100644 --- a/velocity_controllers/package.xml +++ b/velocity_controllers/package.xml @@ -17,6 +17,7 @@ ament_cmake_gmock controller_manager + hardware_interface_testing hardware_interface ros2_control_test_assets diff --git a/velocity_controllers/test/test_load_joint_group_velocity_controller.cpp b/velocity_controllers/test/test_load_joint_group_velocity_controller.cpp index 1872b5f746..e426349f96 100644 --- a/velocity_controllers/test/test_load_joint_group_velocity_controller.cpp +++ b/velocity_controllers/test/test_load_joint_group_velocity_controller.cpp @@ -17,7 +17,9 @@ #include "controller_manager/controller_manager.hpp" #include "hardware_interface/resource_manager.hpp" +#include "rclcpp/executor.hpp" #include "rclcpp/executors/single_threaded_executor.hpp" +#include "rclcpp/utilities.hpp" #include "ros2_control_test_assets/descriptions.hpp" TEST(TestLoadJointGroupVelocityController, load_controller) From c786604f10516379d9c5460eb5356920d923ae03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Mon, 5 Feb 2024 11:04:49 +0100 Subject: [PATCH 213/238] Add test_depend on `hardware_interface_testing` also for diff_drive (#1021) --- diff_drive_controller/package.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/diff_drive_controller/package.xml b/diff_drive_controller/package.xml index 4531a5337d..e87ab85471 100644 --- a/diff_drive_controller/package.xml +++ b/diff_drive_controller/package.xml @@ -26,6 +26,7 @@ ament_cmake_gmock controller_manager + hardware_interface_testing ros2_control_test_assets From 5cde4fc9545fe5f14ad0fa59db67f022c476061e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Feb 2024 17:04:42 +0100 Subject: [PATCH 214/238] Bump codecov/codecov-action from 3.1.5 to 4.0.1 (#1023) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 3.1.5 to 4.0.1. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/v3.1.5...v4.0.1) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-coverage-build-humble.yml | 2 +- .github/workflows/ci-coverage-build-iron.yml | 2 +- .github/workflows/ci-coverage-build.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci-coverage-build-humble.yml b/.github/workflows/ci-coverage-build-humble.yml index c503e090ab..931a715a17 100644 --- a/.github/workflows/ci-coverage-build-humble.yml +++ b/.github/workflows/ci-coverage-build-humble.yml @@ -55,7 +55,7 @@ jobs: } } colcon-mixin-repository: https://raw.githubusercontent.com/colcon/colcon-mixin-repository/master/index.yaml - - uses: codecov/codecov-action@v3.1.5 + - uses: codecov/codecov-action@v4.0.1 with: file: ros_ws/lcov/total_coverage.info flags: unittests diff --git a/.github/workflows/ci-coverage-build-iron.yml b/.github/workflows/ci-coverage-build-iron.yml index 62ff5f34fe..06eadf320d 100644 --- a/.github/workflows/ci-coverage-build-iron.yml +++ b/.github/workflows/ci-coverage-build-iron.yml @@ -55,7 +55,7 @@ jobs: } } colcon-mixin-repository: https://raw.githubusercontent.com/colcon/colcon-mixin-repository/master/index.yaml - - uses: codecov/codecov-action@v3.1.5 + - uses: codecov/codecov-action@v4.0.1 with: file: ros_ws/lcov/total_coverage.info flags: unittests diff --git a/.github/workflows/ci-coverage-build.yml b/.github/workflows/ci-coverage-build.yml index 3f6dff5ab8..2fdbf677e7 100644 --- a/.github/workflows/ci-coverage-build.yml +++ b/.github/workflows/ci-coverage-build.yml @@ -55,7 +55,7 @@ jobs: } } colcon-mixin-repository: https://raw.githubusercontent.com/colcon/colcon-mixin-repository/master/index.yaml - - uses: codecov/codecov-action@v3.1.5 + - uses: codecov/codecov-action@v4.0.1 with: file: ros_ws/lcov/total_coverage.info flags: unittests From 89109a0809fe00e2fbb7fd420bbc4c288ebb3852 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 6 Feb 2024 17:05:48 +0100 Subject: [PATCH 215/238] Bump actions/upload-artifact from 4.3.0 to 4.3.1 (#1024) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.3.0 to 4.3.1. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v4.3.0...v4.3.1) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Dr. Denis --- .github/workflows/ci-coverage-build-humble.yml | 2 +- .github/workflows/ci-coverage-build-iron.yml | 2 +- .github/workflows/ci-coverage-build.yml | 2 +- .github/workflows/reusable-ros-tooling-source-build.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-coverage-build-humble.yml b/.github/workflows/ci-coverage-build-humble.yml index 931a715a17..357ee3dfa8 100644 --- a/.github/workflows/ci-coverage-build-humble.yml +++ b/.github/workflows/ci-coverage-build-humble.yml @@ -60,7 +60,7 @@ jobs: file: ros_ws/lcov/total_coverage.info flags: unittests name: codecov-umbrella - - uses: actions/upload-artifact@v4.3.0 + - uses: actions/upload-artifact@v4.3.1 with: name: colcon-logs-coverage-humble path: ros_ws/log diff --git a/.github/workflows/ci-coverage-build-iron.yml b/.github/workflows/ci-coverage-build-iron.yml index 06eadf320d..7914a1acb0 100644 --- a/.github/workflows/ci-coverage-build-iron.yml +++ b/.github/workflows/ci-coverage-build-iron.yml @@ -60,7 +60,7 @@ jobs: file: ros_ws/lcov/total_coverage.info flags: unittests name: codecov-umbrella - - uses: actions/upload-artifact@v4.3.0 + - uses: actions/upload-artifact@v4.3.1 with: name: colcon-logs-coverage-iron path: ros_ws/log diff --git a/.github/workflows/ci-coverage-build.yml b/.github/workflows/ci-coverage-build.yml index 2fdbf677e7..b96276ca5a 100644 --- a/.github/workflows/ci-coverage-build.yml +++ b/.github/workflows/ci-coverage-build.yml @@ -60,7 +60,7 @@ jobs: file: ros_ws/lcov/total_coverage.info flags: unittests name: codecov-umbrella - - uses: actions/upload-artifact@v4.3.0 + - uses: actions/upload-artifact@v4.3.1 with: name: colcon-logs-coverage-rolling path: ros_ws/log diff --git a/.github/workflows/reusable-ros-tooling-source-build.yml b/.github/workflows/reusable-ros-tooling-source-build.yml index 2a3aa21325..3d5bc1cf35 100644 --- a/.github/workflows/reusable-ros-tooling-source-build.yml +++ b/.github/workflows/reusable-ros-tooling-source-build.yml @@ -63,7 +63,7 @@ jobs: https://raw.githubusercontent.com/ros2/ros2/${{ inputs.ros2_repo_branch }}/ros2.repos https://raw.githubusercontent.com/${{ github.repository }}/${{ github.sha }}/ros2_controllers.${{ inputs.ros_distro }}.repos?token=${{ secrets.GITHUB_TOKEN }} colcon-mixin-repository: https://raw.githubusercontent.com/colcon/colcon-mixin-repository/master/index.yaml - - uses: actions/upload-artifact@v4.3.0 + - uses: actions/upload-artifact@v4.3.1 with: name: colcon-logs-ubuntu-22.04 path: ros_ws/log From 1266941cefcf02e2a409303a4e5f975e87e4d358 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Fri, 9 Feb 2024 11:51:38 +0100 Subject: [PATCH 216/238] [CI] Improvements and Cleanups (#1028) --- .github/workflows/ci-ros-lint.yml | 70 +++++++------------ .../workflows/humble-binary-build-main.yml | 2 - .../workflows/humble-binary-build-testing.yml | 2 - .github/workflows/humble-debian-build.yml | 25 ++----- .../workflows/humble-rhel-binary-build.yml | 25 ++----- .../humble-semi-binary-build-main.yml | 2 - .../humble-semi-binary-build-testing.yml | 2 - .github/workflows/humble-source-build.yml | 2 - .github/workflows/iron-binary-build-main.yml | 4 -- .../workflows/iron-binary-build-testing.yml | 4 -- .github/workflows/iron-debian-build.yml | 25 ++----- .github/workflows/iron-rhel-binary-build.yml | 27 ++----- .../workflows/iron-semi-binary-build-main.yml | 4 -- .../iron-semi-binary-build-testing.yml | 4 -- .github/workflows/iron-source-build.yml | 2 - .github/workflows/reusable-debian-build.yml | 63 +++++++++++++++++ .../reusable-industrial-ci-with-cache.yml | 4 +- .../workflows/reusable-rhel-binary-build.yml | 69 ++++++++++++++++++ .../workflows/rolling-binary-build-main.yml | 4 -- .../rolling-binary-build-testing.yml | 4 -- .github/workflows/rolling-debian-build.yml | 26 ++----- .../workflows/rolling-rhel-binary-build.yml | 28 ++------ .../rolling-semi-binary-build-main.yml | 4 -- .../rolling-semi-binary-build-testing.yml | 4 -- 24 files changed, 199 insertions(+), 207 deletions(-) create mode 100644 .github/workflows/reusable-debian-build.yml create mode 100644 .github/workflows/reusable-rhel-binary-build.yml diff --git a/.github/workflows/ci-ros-lint.yml b/.github/workflows/ci-ros-lint.yml index f6b9c027c9..df17d11dc4 100644 --- a/.github/workflows/ci-ros-lint.yml +++ b/.github/workflows/ci-ros-lint.yml @@ -2,6 +2,30 @@ name: ROS Lint on: pull_request: +env: + package-name: + ackermann_steering_controller + admittance_controller + bicycle_steering_controller + diff_drive_controller + effort_controllers + force_torque_sensor_broadcaster + forward_command_controller + gripper_controllers + imu_sensor_broadcaster + joint_state_broadcaster + joint_trajectory_controller + pid_controller + position_controllers + range_sensor_broadcaster + ros2_controllers + ros2_controllers_test_nodes + rqt_joint_trajectory_controller + steering_controllers_library + tricycle_controller + tricycle_steering_controller + velocity_controllers + jobs: ament_lint: name: ament_${{ matrix.linter }} @@ -19,28 +43,7 @@ jobs: with: distribution: rolling linter: ${{ matrix.linter }} - package-name: - ackermann_steering_controller - admittance_controller - bicycle_steering_controller - diff_drive_controller - effort_controllers - force_torque_sensor_broadcaster - forward_command_controller - gripper_controllers - imu_sensor_broadcaster - joint_state_broadcaster - joint_trajectory_controller - pid_controller - position_controllers - range_sensor_broadcaster - ros2_controllers - ros2_controllers_test_nodes - rqt_joint_trajectory_controller - steering_controllers_library - tricycle_controller - tricycle_steering_controller - velocity_controllers + package-name: ${{ env.package-name }} ament_lint_100: @@ -58,25 +61,4 @@ jobs: distribution: rolling linter: cpplint arguments: "--linelength=100 --filter=-whitespace/newline" - package-name: - ackermann_steering_controller - admittance_controller - bicycle_steering_controller - diff_drive_controller - effort_controllers - force_torque_sensor_broadcaster - forward_command_controller - gripper_controllers - imu_sensor_broadcaster - joint_state_broadcaster - joint_trajectory_controller - pid_controller - position_controllers - range_sensor_broadcaster - ros2_controllers - ros2_controllers_test_nodes - rqt_joint_trajectory_controller - steering_controllers_library - tricycle_controller - tricycle_steering_controller - velocity_controllers + package-name: ${{ env.package-name }} diff --git a/.github/workflows/humble-binary-build-main.yml b/.github/workflows/humble-binary-build-main.yml index 64d78f281a..9c634b372a 100644 --- a/.github/workflows/humble-binary-build-main.yml +++ b/.github/workflows/humble-binary-build-main.yml @@ -4,8 +4,6 @@ name: Humble Binary Build - main on: workflow_dispatch: - branches: - - humble pull_request: branches: - humble diff --git a/.github/workflows/humble-binary-build-testing.yml b/.github/workflows/humble-binary-build-testing.yml index 524cacd685..b662543959 100644 --- a/.github/workflows/humble-binary-build-testing.yml +++ b/.github/workflows/humble-binary-build-testing.yml @@ -4,8 +4,6 @@ name: Humble Binary Build - testing on: workflow_dispatch: - branches: - - humble pull_request: branches: - humble diff --git a/.github/workflows/humble-debian-build.yml b/.github/workflows/humble-debian-build.yml index 426b935fa4..c236aecf64 100644 --- a/.github/workflows/humble-debian-build.yml +++ b/.github/workflows/humble-debian-build.yml @@ -1,4 +1,4 @@ -name: Debian Humble Build +name: Debian Humble Source Build on: workflow_dispatch: pull_request: @@ -12,20 +12,9 @@ on: jobs: humble_debian: name: Humble debian build - runs-on: ubuntu-latest - env: - ROS_DISTRO: humble - container: ghcr.io/ros-controls/ros:humble-debian - steps: - - uses: actions/checkout@v4 - with: - path: src/ros2_controllers - ref: ${{ github.event_name == 'schedule' && 'humble' || '' }} - - name: Build and test - shell: bash - run: | - source /opt/ros2_ws/install/setup.bash - vcs import src < src/ros2_controllers/ros2_controllers.${{ env.ROS_DISTRO }}.repos - colcon build --packages-skip rqt_controller_manager rqt_joint_trajectory_controller - colcon test --packages-skip rqt_controller_manager rqt_joint_trajectory_controller control_msgs controller_manager_msgs - colcon test-result --verbose + uses: ./.github/workflows/reusable-debian-build.yml + with: + ros_distro: humble + upstream_workspace: ros2_controllers.humble.repos + ref_for_scheduled_build: humble + skip_packages: rqt_joint_trajectory_controller diff --git a/.github/workflows/humble-rhel-binary-build.yml b/.github/workflows/humble-rhel-binary-build.yml index 933486ba50..db503d1993 100644 --- a/.github/workflows/humble-rhel-binary-build.yml +++ b/.github/workflows/humble-rhel-binary-build.yml @@ -11,22 +11,9 @@ on: jobs: humble_rhel_binary: name: Humble RHEL binary build - runs-on: ubuntu-latest - env: - ROS_DISTRO: humble - container: ghcr.io/ros-controls/ros:humble-rhel - steps: - - uses: actions/checkout@v4 - with: - path: src/ros2_controllers - ref: ${{ github.event_name == 'schedule' && 'humble' || '' }} - - name: Install dependencies - run: | - rosdep update - rosdep install -iyr --from-path src/ros2_controllers || true - - name: Build and test - run: | - source /opt/ros/${{ env.ROS_DISTRO }}/setup.bash - colcon build --packages-skip rqt_joint_trajectory_controller - colcon test --packages-skip rqt_joint_trajectory_controller - colcon test-result --verbose + uses: ./.github/workflows/reusable-rhel-binary-build.yml + with: + ros_distro: humble + upstream_workspace: ros2_controllers.humble.repos + ref_for_scheduled_build: humble + skip_packages: rqt_joint_trajectory_controller diff --git a/.github/workflows/humble-semi-binary-build-main.yml b/.github/workflows/humble-semi-binary-build-main.yml index 863df79a22..bfe83392ea 100644 --- a/.github/workflows/humble-semi-binary-build-main.yml +++ b/.github/workflows/humble-semi-binary-build-main.yml @@ -3,8 +3,6 @@ name: Humble Semi-Binary Build - main on: workflow_dispatch: - branches: - - humble pull_request: branches: - humble diff --git a/.github/workflows/humble-semi-binary-build-testing.yml b/.github/workflows/humble-semi-binary-build-testing.yml index 6286636e1f..3a66c0b74d 100644 --- a/.github/workflows/humble-semi-binary-build-testing.yml +++ b/.github/workflows/humble-semi-binary-build-testing.yml @@ -3,8 +3,6 @@ name: Humble Semi-Binary Build - testing on: workflow_dispatch: - branches: - - humble pull_request: branches: - humble diff --git a/.github/workflows/humble-source-build.yml b/.github/workflows/humble-source-build.yml index ff0fd62e05..a40d53f8e3 100644 --- a/.github/workflows/humble-source-build.yml +++ b/.github/workflows/humble-source-build.yml @@ -1,8 +1,6 @@ name: Humble Source Build on: workflow_dispatch: - branches: - - humble push: branches: - humble diff --git a/.github/workflows/iron-binary-build-main.yml b/.github/workflows/iron-binary-build-main.yml index ef35397855..bb1997bd48 100644 --- a/.github/workflows/iron-binary-build-main.yml +++ b/.github/workflows/iron-binary-build-main.yml @@ -4,10 +4,6 @@ name: Iron Binary Build - main on: workflow_dispatch: - branches: - - iron - - '*feature*' - - '*feature/**' pull_request: branches: - iron diff --git a/.github/workflows/iron-binary-build-testing.yml b/.github/workflows/iron-binary-build-testing.yml index 25a693dc23..37e3524ccd 100644 --- a/.github/workflows/iron-binary-build-testing.yml +++ b/.github/workflows/iron-binary-build-testing.yml @@ -4,10 +4,6 @@ name: Iron Binary Build - testing on: workflow_dispatch: - branches: - - iron - - '*feature*' - - '*feature/**' pull_request: branches: - iron diff --git a/.github/workflows/iron-debian-build.yml b/.github/workflows/iron-debian-build.yml index c47fbe5cd9..58787a804c 100644 --- a/.github/workflows/iron-debian-build.yml +++ b/.github/workflows/iron-debian-build.yml @@ -1,4 +1,4 @@ -name: Debian Iron Build +name: Debian Iron Source Build on: workflow_dispatch: pull_request: @@ -12,20 +12,9 @@ on: jobs: iron_debian: name: Iron debian build - runs-on: ubuntu-latest - env: - ROS_DISTRO: iron - container: ghcr.io/ros-controls/ros:iron-debian - steps: - - uses: actions/checkout@v4 - with: - path: src/ros2_controllers - ref: ${{ github.event_name == 'schedule' && 'iron' || '' }} - - name: Build and test - shell: bash - run: | - source /opt/ros2_ws/install/setup.bash - vcs import src < src/ros2_controllers/ros2_controllers.${{ env.ROS_DISTRO }}.repos - colcon build --packages-skip rqt_controller_manager rqt_joint_trajectory_controller - colcon test --packages-skip rqt_controller_manager rqt_joint_trajectory_controller control_msgs controller_manager_msgs - colcon test-result --verbose + uses: ./.github/workflows/reusable-debian-build.yml + with: + ros_distro: iron + upstream_workspace: ros2_controllers.iron.repos + ref_for_scheduled_build: iron + skip_packages: rqt_joint_trajectory_controller diff --git a/.github/workflows/iron-rhel-binary-build.yml b/.github/workflows/iron-rhel-binary-build.yml index c3bc1e6def..90dac67a44 100644 --- a/.github/workflows/iron-rhel-binary-build.yml +++ b/.github/workflows/iron-rhel-binary-build.yml @@ -12,24 +12,9 @@ on: jobs: iron_rhel_binary: name: Iron RHEL binary build - runs-on: ubuntu-latest - env: - ROS_DISTRO: iron - container: ghcr.io/ros-controls/ros:iron-rhel - steps: - - uses: actions/checkout@v4 - with: - path: src/ros2_controllers - ref: ${{ github.event_name == 'schedule' && 'iron' || '' }} - - name: Install dependencies - run: | - rosdep update - rosdep install -iyr --from-path src/ros2_controllers || true - - name: Build and test - # source also underlay workspace with generate_parameter_library on rhel9 - run: | - source /opt/ros/${{ env.ROS_DISTRO }}/setup.bash - source /opt/ros2_ws/install/setup.bash - colcon build --packages-skip rqt_joint_trajectory_controller - colcon test --packages-skip rqt_joint_trajectory_controller - colcon test-result --verbose + uses: ./.github/workflows/reusable-rhel-binary-build.yml + with: + ros_distro: iron + upstream_workspace: ros2_controllers.iron.repos + ref_for_scheduled_build: iron + skip_packages: rqt_joint_trajectory_controller diff --git a/.github/workflows/iron-semi-binary-build-main.yml b/.github/workflows/iron-semi-binary-build-main.yml index 2224a59f0e..ed90a46ea8 100644 --- a/.github/workflows/iron-semi-binary-build-main.yml +++ b/.github/workflows/iron-semi-binary-build-main.yml @@ -3,10 +3,6 @@ name: Iron Semi-Binary Build - main on: workflow_dispatch: - branches: - - iron - - '*feature*' - - '*feature/**' pull_request: branches: - iron diff --git a/.github/workflows/iron-semi-binary-build-testing.yml b/.github/workflows/iron-semi-binary-build-testing.yml index c5ff430c89..d06a20443d 100644 --- a/.github/workflows/iron-semi-binary-build-testing.yml +++ b/.github/workflows/iron-semi-binary-build-testing.yml @@ -3,10 +3,6 @@ name: Iron Semi-Binary Build - testing on: workflow_dispatch: - branches: - - iron - - '*feature*' - - '*feature/**' pull_request: branches: - iron diff --git a/.github/workflows/iron-source-build.yml b/.github/workflows/iron-source-build.yml index 1e9d865c49..34372a4178 100644 --- a/.github/workflows/iron-source-build.yml +++ b/.github/workflows/iron-source-build.yml @@ -1,8 +1,6 @@ name: Iron Source Build on: workflow_dispatch: - branches: - - iron push: branches: - iron diff --git a/.github/workflows/reusable-debian-build.yml b/.github/workflows/reusable-debian-build.yml new file mode 100644 index 0000000000..b406fe6eaa --- /dev/null +++ b/.github/workflows/reusable-debian-build.yml @@ -0,0 +1,63 @@ +name: Reusable Debian Source Build +# Reusable action to simplify dealing with debian source builds +# author: Christoph Froehlich + +on: + workflow_call: + inputs: + ros_distro: + description: 'ROS2 distribution name' + required: true + type: string + ref_for_scheduled_build: + description: 'Reference on which the repo should be checkout for scheduled build. Usually is this name of a branch or a tag.' + default: '' + required: false + type: string + upstream_workspace: + description: 'Path to local .repos file.' + default: '' + required: false + type: string + skip_packages: + description: 'Packages to skip from build and test' + default: '' + required: false + type: string + + +jobs: + debian_source: + name: ${{ inputs.ros_distro }} debian build + runs-on: ubuntu-latest + env: + ROS_DISTRO: ${{ inputs.ros_distro }} + path: src/ros2_controllers + container: ghcr.io/ros-controls/ros:${{ inputs.ros_distro }}-debian + steps: + - name: Checkout default ref when build is not scheduled + if: ${{ github.event_name != 'schedule' }} + uses: actions/checkout@v4 + with: + path: ${{ env.path }} + - name: Checkout ${{ inputs.ref_for_scheduled_build }} on scheduled build + if: ${{ github.event_name == 'schedule' }} + uses: actions/checkout@v4 + with: + ref: ${{ inputs.ref_for_scheduled_build }} + path: ${{ env.path }} + - name: Build workspace + shell: bash + run: | + source /opt/ros2_ws/install/setup.bash + if [[ -n "${{ inputs.upstream_workspace }}" ]]; then + vcs import src < ${{ env.path }}/${{ inputs.upstream_workspace }} + fi + colcon build --packages-up-to $(colcon list --paths ${{ env.path }}/* --names-only) --packages-skip ${{ inputs.skip_packages }} + - name: Test workspace + shell: bash + continue-on-error: true + run: | + source /opt/ros2_ws/install/setup.bash + colcon test --packages-select $(colcon list --paths ${{ env.path }}/* --names-only) --packages-skip ${{ inputs.skip_packages }} + colcon test-result --verbose diff --git a/.github/workflows/reusable-industrial-ci-with-cache.yml b/.github/workflows/reusable-industrial-ci-with-cache.yml index acefeebfac..234ec27677 100644 --- a/.github/workflows/reusable-industrial-ci-with-cache.yml +++ b/.github/workflows/reusable-industrial-ci-with-cache.yml @@ -56,10 +56,10 @@ jobs: BASEDIR: ${{ github.workspace }}/${{ inputs.basedir }} CACHE_PREFIX: ${{ inputs.ros_distro }}-${{ inputs.upstream_workspace }}-${{ inputs.ros_repo }}-${{ github.job }} steps: - - name: Checkout ${{ inputs.ref }} when build is not scheduled + - name: Checkout default ref when build is not scheduled if: ${{ github.event_name != 'schedule' }} uses: actions/checkout@v4 - - name: Checkout ${{ inputs.ref }} on scheduled build + - name: Checkout ${{ inputs.ref_for_scheduled_build }} on scheduled build if: ${{ github.event_name == 'schedule' }} uses: actions/checkout@v4 with: diff --git a/.github/workflows/reusable-rhel-binary-build.yml b/.github/workflows/reusable-rhel-binary-build.yml new file mode 100644 index 0000000000..be4eabb76b --- /dev/null +++ b/.github/workflows/reusable-rhel-binary-build.yml @@ -0,0 +1,69 @@ +name: Reusable RHEL Binary Build +# Reusable action to simplify dealing with RHEL binary builds +# author: Christoph Froehlich + +on: + workflow_call: + inputs: + ros_distro: + description: 'ROS2 distribution name' + required: true + type: string + ref_for_scheduled_build: + description: 'Reference on which the repo should be checkout for scheduled build. Usually is this name of a branch or a tag.' + default: '' + required: false + type: string + upstream_workspace: + description: 'Path to local .repos file.' + default: '' + required: false + type: string + skip_packages: + description: 'Packages to skip from build and test' + default: '' + required: false + type: string + +jobs: + rhel_binary: + name: ${{ inputs.ros_distro }} RHEL binary build + runs-on: ubuntu-latest + env: + path: src/ros2_controllers + container: ghcr.io/ros-controls/ros:${{ inputs.ros_distro }}-rhel + steps: + - name: Checkout default ref when build is not scheduled + if: ${{ github.event_name != 'schedule' }} + uses: actions/checkout@v4 + with: + path: ${{ env.path }} + - name: Checkout ${{ inputs.ref_for_scheduled_build }} on scheduled build + if: ${{ github.event_name == 'schedule' }} + uses: actions/checkout@v4 + with: + ref: ${{ inputs.ref_for_scheduled_build }} + path: ${{ env.path }} + - name: Install dependencies + run: | + source /opt/ros/${{ inputs.ros_distro }}/setup.bash + source /opt/ros2_ws/install/local_setup.bash + if [[ -n "${{ inputs.upstream_workspace }}" ]]; then + vcs import src < ${{ env.path }}/${{ inputs.upstream_workspace }} + fi + rosdep update + rosdep install -iyr --from-path src || true + - name: Build workspace + # source also underlay workspace with generate_parameter_library on rhel9 + run: | + source /opt/ros/${{ inputs.ros_distro }}/setup.bash + source /opt/ros2_ws/install/local_setup.bash + colcon build --packages-up-to $(colcon list --paths ${{ env.path }}/* --names-only) --packages-skip ${{ inputs.skip_packages }} + - name: Test workspace + shell: bash + continue-on-error: true + run: | + source /opt/ros/${{ inputs.ros_distro }}/setup.bash + source /opt/ros2_ws/install/local_setup.bash + colcon test --packages-select $(colcon list --paths ${{ env.path }}/* --names-only) --packages-skip ${{ inputs.skip_packages }} + colcon test-result --verbose diff --git a/.github/workflows/rolling-binary-build-main.yml b/.github/workflows/rolling-binary-build-main.yml index 793db5d7e5..729d5e38ba 100644 --- a/.github/workflows/rolling-binary-build-main.yml +++ b/.github/workflows/rolling-binary-build-main.yml @@ -4,10 +4,6 @@ name: Rolling Binary Build - main on: workflow_dispatch: - branches: - - master - - '*feature*' - - '*feature/**' pull_request: branches: - master diff --git a/.github/workflows/rolling-binary-build-testing.yml b/.github/workflows/rolling-binary-build-testing.yml index 9b480d99c3..0596aeec56 100644 --- a/.github/workflows/rolling-binary-build-testing.yml +++ b/.github/workflows/rolling-binary-build-testing.yml @@ -4,10 +4,6 @@ name: Rolling Binary Build - testing on: workflow_dispatch: - branches: - - master - - '*feature*' - - '*feature/**' pull_request: branches: - master diff --git a/.github/workflows/rolling-debian-build.yml b/.github/workflows/rolling-debian-build.yml index 9169494b00..153f4df681 100644 --- a/.github/workflows/rolling-debian-build.yml +++ b/.github/workflows/rolling-debian-build.yml @@ -1,4 +1,4 @@ -name: Debian Rolling Build +name: Debian Rolling Source Build on: workflow_dispatch: pull_request: @@ -12,21 +12,9 @@ on: jobs: rolling_debian: name: Rolling debian build - runs-on: ubuntu-latest - env: - ROS_DISTRO: rolling - container: ghcr.io/ros-controls/ros:rolling-debian - steps: - - uses: actions/checkout@v4 - with: - path: src/ros2_controllers - # default behavior is correct on master branch - # ref: ${{ github.event_name == 'schedule' && 'master' || '' }} - - name: Build and test - shell: bash - run: | - source /opt/ros2_ws/install/setup.bash - vcs import src < src/ros2_controllers/ros2_controllers.${{ env.ROS_DISTRO }}.repos - colcon build --packages-skip rqt_controller_manager rqt_joint_trajectory_controller - colcon test --packages-skip rqt_controller_manager rqt_joint_trajectory_controller - colcon test-result --verbose + uses: ./.github/workflows/reusable-debian-build.yml + with: + ros_distro: rolling + upstream_workspace: ros2_controllers.rolling.repos + ref_for_scheduled_build: master + skip_packages: rqt_joint_trajectory_controller diff --git a/.github/workflows/rolling-rhel-binary-build.yml b/.github/workflows/rolling-rhel-binary-build.yml index 98c02b72a3..31c133ab69 100644 --- a/.github/workflows/rolling-rhel-binary-build.yml +++ b/.github/workflows/rolling-rhel-binary-build.yml @@ -12,25 +12,9 @@ on: jobs: rolling_rhel_binary: name: Rolling RHEL binary build - runs-on: ubuntu-latest - env: - ROS_DISTRO: rolling - container: ghcr.io/ros-controls/ros:rolling-rhel - steps: - - uses: actions/checkout@v4 - with: - path: src/ros2_controllers - # default behavior is correct on master branch - # ref: ${{ github.event_name == 'schedule' && 'master' || '' }} - - name: Install dependencies - run: | - rosdep update - rosdep install -iyr --from-path src/ros2_controllers || true - - name: Build and test - # source also underlay workspace with generate_parameter_library on rhel9 - run: | - source /opt/ros/${{ env.ROS_DISTRO }}/setup.bash - source /opt/ros2_ws/install/setup.bash - colcon build --packages-skip rqt_joint_trajectory_controller - colcon test --packages-skip rqt_joint_trajectory_controller - colcon test-result --verbose + uses: ./.github/workflows/reusable-rhel-binary-build.yml + with: + ros_distro: rolling + upstream_workspace: ros2_controllers.rolling.repos + ref_for_scheduled_build: master + skip_packages: rqt_joint_trajectory_controller diff --git a/.github/workflows/rolling-semi-binary-build-main.yml b/.github/workflows/rolling-semi-binary-build-main.yml index 8b395e5163..206ca8bd52 100644 --- a/.github/workflows/rolling-semi-binary-build-main.yml +++ b/.github/workflows/rolling-semi-binary-build-main.yml @@ -3,10 +3,6 @@ name: Rolling Semi-Binary Build - main on: workflow_dispatch: - branches: - - master - - '*feature*' - - '*feature/**' pull_request: branches: - master diff --git a/.github/workflows/rolling-semi-binary-build-testing.yml b/.github/workflows/rolling-semi-binary-build-testing.yml index 630881dc0a..b284c0b7d4 100644 --- a/.github/workflows/rolling-semi-binary-build-testing.yml +++ b/.github/workflows/rolling-semi-binary-build-testing.yml @@ -3,10 +3,6 @@ name: Rolling Semi-Binary Build - testing on: workflow_dispatch: - branches: - - master - - '*feature*' - - '*feature/**' pull_request: branches: - master From e0491baf97bebc8d0a4f01d39623246c30cc4092 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Sat, 10 Feb 2024 16:02:15 +0100 Subject: [PATCH 217/238] [JTC] Angle wraparound for first segment of trajectory (#796) --- .../joint_trajectory_controller.hpp | 3 +- .../trajectory.hpp | 26 ++++-- .../src/joint_trajectory_controller.cpp | 6 +- .../src/trajectory.cpp | 32 ++++++- .../test/test_trajectory.cpp | 56 ++++++++++++ .../test/test_trajectory_controller.cpp | 90 +++++++------------ 6 files changed, 148 insertions(+), 65 deletions(-) diff --git a/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp b/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp index b9097b1ce3..111837cc17 100644 --- a/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp +++ b/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp @@ -155,7 +155,8 @@ class JointTrajectoryController : public controller_interface::ControllerInterfa std::vector pids_; // Feed-forward velocity weight factor when calculating closed loop pid adapter's command std::vector ff_velocity_scale_; - // Configuration for every joint, if position error is wrapped around + // Configuration for every joint if it wraps around (ie. is continuous, position error is + // normalized) std::vector joints_angle_wraparound_; // reserved storage for result of the command when closed loop pid adapter is used std::vector tmp_command_; diff --git a/joint_trajectory_controller/include/joint_trajectory_controller/trajectory.hpp b/joint_trajectory_controller/include/joint_trajectory_controller/trajectory.hpp index 3bd4873a31..b00d79481c 100644 --- a/joint_trajectory_controller/include/joint_trajectory_controller/trajectory.hpp +++ b/joint_trajectory_controller/include/joint_trajectory_controller/trajectory.hpp @@ -44,14 +44,19 @@ class Trajectory const trajectory_msgs::msg::JointTrajectoryPoint & current_point, std::shared_ptr joint_trajectory); - /// Set the point before the trajectory message is replaced/appended - /// Example: if we receive a new trajectory message and it's first point is 0.5 seconds - /// from the current one, we call this function to log the current state, then - /// append/replace the current trajectory + /** + * Set the point before the trajectory message is replaced/appended + * Example: if we receive a new trajectory message and it's first point is 0.5 seconds + * from the current one, we call this function to log the current state, then + * append/replace the current trajectory + * \param joints_angle_wraparound Vector of boolean where true value corresponds to a joint that + * wrap around (ie. is continuous). + */ JOINT_TRAJECTORY_CONTROLLER_PUBLIC void set_point_before_trajectory_msg( const rclcpp::Time & current_time, - const trajectory_msgs::msg::JointTrajectoryPoint & current_point); + const trajectory_msgs::msg::JointTrajectoryPoint & current_point, + const std::vector & joints_angle_wraparound = std::vector()); JOINT_TRAJECTORY_CONTROLLER_PUBLIC void update(std::shared_ptr joint_trajectory); @@ -189,6 +194,17 @@ inline std::vector mapping(const T & t1, const T & t2) return mapping_vector; } +/** + * \param current_position The current position given from the controller, which will be adapted. + * \param next_position Next position from which to compute the wraparound offset, i.e., + * the first trajectory point + * \param joints_angle_wraparound Vector of boolean where true value corresponds to a joint that + * wrap around (ie. is continuous). + */ +void wraparound_joint( + std::vector & current_position, const std::vector next_position, + const std::vector & joints_angle_wraparound); + } // namespace joint_trajectory_controller #endif // JOINT_TRAJECTORY_CONTROLLER__TRAJECTORY_HPP_ diff --git a/joint_trajectory_controller/src/joint_trajectory_controller.cpp b/joint_trajectory_controller/src/joint_trajectory_controller.cpp index b0e93b6ecd..46544bf875 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller.cpp +++ b/joint_trajectory_controller/src/joint_trajectory_controller.cpp @@ -153,11 +153,13 @@ controller_interface::return_type JointTrajectoryController::update( first_sample = true; if (params_.open_loop_control) { - traj_external_point_ptr_->set_point_before_trajectory_msg(time, last_commanded_state_); + traj_external_point_ptr_->set_point_before_trajectory_msg( + time, last_commanded_state_, joints_angle_wraparound_); } else { - traj_external_point_ptr_->set_point_before_trajectory_msg(time, state_current_); + traj_external_point_ptr_->set_point_before_trajectory_msg( + time, state_current_, joints_angle_wraparound_); } } diff --git a/joint_trajectory_controller/src/trajectory.cpp b/joint_trajectory_controller/src/trajectory.cpp index fae4c41ff9..0ed7f2ff13 100644 --- a/joint_trajectory_controller/src/trajectory.cpp +++ b/joint_trajectory_controller/src/trajectory.cpp @@ -16,6 +16,7 @@ #include +#include "angles/angles.h" #include "hardware_interface/macros.hpp" #include "rclcpp/duration.hpp" #include "rclcpp/time.hpp" @@ -44,10 +45,39 @@ Trajectory::Trajectory( void Trajectory::set_point_before_trajectory_msg( const rclcpp::Time & current_time, - const trajectory_msgs::msg::JointTrajectoryPoint & current_point) + const trajectory_msgs::msg::JointTrajectoryPoint & current_point, + const std::vector & joints_angle_wraparound) { time_before_traj_msg_ = current_time; state_before_traj_msg_ = current_point; + + // Compute offsets due to wrapping joints + wraparound_joint( + state_before_traj_msg_.positions, trajectory_msg_->points[0].positions, + joints_angle_wraparound); +} + +void wraparound_joint( + std::vector & current_position, const std::vector next_position, + const std::vector & joints_angle_wraparound) +{ + double dist; + // joints_angle_wraparound is even empty, or has the same size as the number of joints + for (size_t i = 0; i < joints_angle_wraparound.size(); i++) + { + if (joints_angle_wraparound[i]) + { + dist = angles::shortest_angular_distance(current_position[i], next_position[i]); + + // Deal with singularity at M_PI shortest distance + if (std::abs(std::abs(dist) - M_PI) < 1e-9) + { + dist = next_position[i] > current_position[i] ? std::abs(dist) : -std::abs(dist); + } + + current_position[i] = next_position[i] - dist; + } + } } void Trajectory::update(std::shared_ptr joint_trajectory) diff --git a/joint_trajectory_controller/test/test_trajectory.cpp b/joint_trajectory_controller/test/test_trajectory.cpp index b52aa67a04..6e0c53ac77 100644 --- a/joint_trajectory_controller/test/test_trajectory.cpp +++ b/joint_trajectory_controller/test/test_trajectory.cpp @@ -821,3 +821,59 @@ TEST(TestTrajectory, skip_interpolation) } } } + +TEST(TestWrapAroundJoint, no_wraparound) +{ + const std::vector initial_position(3, 0.); + std::vector next_position(3, M_PI * 3. / 2.); + + std::vector current_position(initial_position); + std::vector joints_angle_wraparound(3, false); + joint_trajectory_controller::wraparound_joint( + current_position, next_position, joints_angle_wraparound); + EXPECT_EQ(current_position[0], initial_position[0]); + EXPECT_EQ(current_position[1], initial_position[1]); + EXPECT_EQ(current_position[2], initial_position[2]); +} + +TEST(TestWrapAroundJoint, wraparound_single_joint) +{ + const std::vector initial_position(3, 0.); + std::vector next_position(3, M_PI * 3. / 2.); + + std::vector current_position(initial_position); + std::vector joints_angle_wraparound{true, false, false}; + joint_trajectory_controller::wraparound_joint( + current_position, next_position, joints_angle_wraparound); + EXPECT_EQ(current_position[0], initial_position[0] + 2 * M_PI); + EXPECT_EQ(current_position[1], initial_position[1]); + EXPECT_EQ(current_position[2], initial_position[2]); +} + +TEST(TestWrapAroundJoint, wraparound_all_joints) +{ + const std::vector initial_position(3, 0.); + std::vector next_position(3, M_PI * 3. / 2.); + + std::vector current_position(initial_position); + std::vector joints_angle_wraparound(3, true); + joint_trajectory_controller::wraparound_joint( + current_position, next_position, joints_angle_wraparound); + EXPECT_EQ(current_position[0], initial_position[0] + 2 * M_PI); + EXPECT_EQ(current_position[1], initial_position[1] + 2 * M_PI); + EXPECT_EQ(current_position[2], initial_position[2] + 2 * M_PI); +} + +TEST(TestWrapAroundJoint, wraparound_all_joints_no_offset) +{ + const std::vector initial_position(3, 0.); + std::vector next_position(3, M_PI * 3. / 2.); + + std::vector current_position(next_position); + std::vector joints_angle_wraparound(3, true); + joint_trajectory_controller::wraparound_joint( + current_position, next_position, joints_angle_wraparound); + EXPECT_EQ(current_position[0], next_position[0]); + EXPECT_EQ(current_position[1], next_position[1]); + EXPECT_EQ(current_position[2], next_position[2]); +} diff --git a/joint_trajectory_controller/test/test_trajectory_controller.cpp b/joint_trajectory_controller/test/test_trajectory_controller.cpp index 24988618bb..2bfe6f150d 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller.cpp +++ b/joint_trajectory_controller/test/test_trajectory_controller.cpp @@ -636,14 +636,16 @@ TEST_P(TrajectoryControllerTestParameterized, compute_error_angle_wraparound_fal } /** - * @brief check if position error of revolute joints are angle_wraparound if not configured so + * @brief check if position error of revolute joints are wrapped around if not configured so */ TEST_P(TrajectoryControllerTestParameterized, position_error_not_angle_wraparound) { rclcpp::executors::MultiThreadedExecutor executor; constexpr double k_p = 10.0; std::vector params = {}; - SetUpAndActivateTrajectoryController(executor, params, true, k_p, 0.0, false); + bool angle_wraparound = false; + SetUpAndActivateTrajectoryController(executor, params, true, k_p, 0.0, angle_wraparound); + subscribeToState(); size_t n_joints = joint_names_.size(); @@ -653,10 +655,8 @@ TEST_P(TrajectoryControllerTestParameterized, position_error_not_angle_wraparoun // *INDENT-OFF* std::vector> points{ {{3.3, 4.4, 6.6}}, {{7.7, 8.8, 9.9}}, {{10.10, 11.11, 12.12}}}; - std::vector> points_velocities{ - {{0.01, 0.01, 0.01}}, {{0.05, 0.05, 0.05}}, {{0.06, 0.06, 0.06}}}; // *INDENT-ON* - publish(time_from_start, points, rclcpp::Time(), {}, points_velocities); + publish(time_from_start, points, rclcpp::Time()); traj_controller_->wait_for_trajectory(executor); updateControllerAsync(rclcpp::Duration(FIRST_POINT_TIME)); @@ -720,35 +720,24 @@ TEST_P(TrajectoryControllerTestParameterized, position_error_not_angle_wraparoun if (traj_controller_->has_effort_command_interface()) { - // use_closed_loop_pid_adapter_ - if (traj_controller_->use_closed_loop_pid_adapter()) - { - // we expect u = k_p * (s_d-s) for positions - EXPECT_NEAR( - k_p * (state_reference.positions[0] - INITIAL_POS_JOINTS[0]), joint_eff_[0], - k_p * COMMON_THRESHOLD); - EXPECT_NEAR( - k_p * (state_reference.positions[1] - INITIAL_POS_JOINTS[1]), joint_eff_[1], - k_p * COMMON_THRESHOLD); - EXPECT_NEAR( - k_p * (state_reference.positions[2] - INITIAL_POS_JOINTS[2]), joint_eff_[2], - k_p * COMMON_THRESHOLD); - } - else - { - // interpolated points_velocities only - // check command interface - EXPECT_LT(0.0, joint_eff_[0]); - EXPECT_LT(0.0, joint_eff_[1]); - EXPECT_LT(0.0, joint_eff_[2]); - } + // with effort command interface, use_closed_loop_pid_adapter is always true + // we expect u = k_p * (s_d-s) for positions + EXPECT_NEAR( + k_p * (state_reference.positions[0] - INITIAL_POS_JOINTS[0]), joint_eff_[0], + k_p * COMMON_THRESHOLD); + EXPECT_NEAR( + k_p * (state_reference.positions[1] - INITIAL_POS_JOINTS[1]), joint_eff_[1], + k_p * COMMON_THRESHOLD); + EXPECT_NEAR( + k_p * (state_reference.positions[2] - INITIAL_POS_JOINTS[2]), joint_eff_[2], + k_p * COMMON_THRESHOLD); } executor.cancel(); } /** - * @brief check if position error of revolute joints are angle_wraparound if configured so + * @brief check if position error of revolute joints are wrapped around if configured so */ TEST_P(TrajectoryControllerTestParameterized, position_error_angle_wraparound) { @@ -791,7 +780,7 @@ TEST_P(TrajectoryControllerTestParameterized, position_error_angle_wraparound) EXPECT_NEAR(points[0][1], state_reference.positions[1], COMMON_THRESHOLD); EXPECT_NEAR(points[0][2], state_reference.positions[2], COMMON_THRESHOLD); - // is error.positions[2] angle_wraparound? + // is error.positions[2] wrapped around? EXPECT_NEAR(state_error.positions[0], state_reference.positions[0] - INITIAL_POS_JOINTS[0], EPS); EXPECT_NEAR(state_error.positions[1], state_reference.positions[1] - INITIAL_POS_JOINTS[1], EPS); EXPECT_NEAR( @@ -810,15 +799,15 @@ TEST_P(TrajectoryControllerTestParameterized, position_error_angle_wraparound) // use_closed_loop_pid_adapter_ if (traj_controller_->use_closed_loop_pid_adapter()) { - // we expect u = k_p * (s_d-s) for positions[0] and positions[1] + // we expect u = k_p * (s_d-s) for joint0 and joint1 EXPECT_NEAR( k_p * (state_reference.positions[0] - INITIAL_POS_JOINTS[0]), joint_vel_[0], k_p * COMMON_THRESHOLD); EXPECT_NEAR( k_p * (state_reference.positions[1] - INITIAL_POS_JOINTS[1]), joint_vel_[1], k_p * COMMON_THRESHOLD); - // is error of positions[2] angle_wraparound? - EXPECT_GT(0.0, joint_vel_[2]); + // is error of positions[2] wrapped around? + EXPECT_GT(0.0, joint_vel_[2]); // direction change because of angle wrap EXPECT_NEAR( k_p * (state_reference.positions[2] - INITIAL_POS_JOINTS[2] - 2 * M_PI), joint_vel_[2], k_p * COMMON_THRESHOLD); @@ -835,30 +824,19 @@ TEST_P(TrajectoryControllerTestParameterized, position_error_angle_wraparound) if (traj_controller_->has_effort_command_interface()) { - // use_closed_loop_pid_adapter_ - if (traj_controller_->use_closed_loop_pid_adapter()) - { - // we expect u = k_p * (s_d-s) for positions[0] and positions[1] - EXPECT_NEAR( - k_p * (state_reference.positions[0] - INITIAL_POS_JOINTS[0]), joint_eff_[0], - k_p * COMMON_THRESHOLD); - EXPECT_NEAR( - k_p * (state_reference.positions[1] - INITIAL_POS_JOINTS[1]), joint_eff_[1], - k_p * COMMON_THRESHOLD); - // is error of positions[2] angle_wraparound? - EXPECT_GT(0.0, joint_eff_[2]); - EXPECT_NEAR( - k_p * (state_reference.positions[2] - INITIAL_POS_JOINTS[2] - 2 * M_PI), joint_eff_[2], - k_p * COMMON_THRESHOLD); - } - else - { - // interpolated points_velocities only - // check command interface - EXPECT_LT(0.0, joint_eff_[0]); - EXPECT_LT(0.0, joint_eff_[1]); - EXPECT_LT(0.0, joint_eff_[2]); - } + // with effort command interface, use_closed_loop_pid_adapter is always true + // we expect u = k_p * (s_d-s) for joint0 and joint1 + EXPECT_NEAR( + k_p * (state_reference.positions[0] - INITIAL_POS_JOINTS[0]), joint_eff_[0], + k_p * COMMON_THRESHOLD); + EXPECT_NEAR( + k_p * (state_reference.positions[1] - INITIAL_POS_JOINTS[1]), joint_eff_[1], + k_p * COMMON_THRESHOLD); + // is error of positions[2] wrapped around? + EXPECT_GT(0.0, joint_eff_[2]); + EXPECT_NEAR( + k_p * (state_reference.positions[2] - INITIAL_POS_JOINTS[2] - 2 * M_PI), joint_eff_[2], + k_p * COMMON_THRESHOLD); } executor.cancel(); From 9ab848a5a0f07a68b1cbf53c407fc162d0896a27 Mon Sep 17 00:00:00 2001 From: Silvio Traversaro Date: Sun, 11 Feb 2024 21:17:41 +0100 Subject: [PATCH 218/238] Fix usage of M_PI on Windows (#1036) --- joint_trajectory_controller/CMakeLists.txt | 2 ++ steering_controllers_library/CMakeLists.txt | 2 +- tricycle_controller/CMakeLists.txt | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/joint_trajectory_controller/CMakeLists.txt b/joint_trajectory_controller/CMakeLists.txt index 5cddb1bf4d..c92d61b3f3 100644 --- a/joint_trajectory_controller/CMakeLists.txt +++ b/joint_trajectory_controller/CMakeLists.txt @@ -58,6 +58,7 @@ if(BUILD_TESTING) ament_add_gmock(test_trajectory test/test_trajectory.cpp) target_link_libraries(test_trajectory joint_trajectory_controller) + target_compile_definitions(test_trajectory PRIVATE _USE_MATH_DEFINES) ament_add_gmock(test_trajectory_controller test/test_trajectory_controller.cpp) @@ -65,6 +66,7 @@ if(BUILD_TESTING) target_link_libraries(test_trajectory_controller joint_trajectory_controller ) + target_compile_definitions(joint_trajectory_controller PRIVATE _USE_MATH_DEFINES) ament_add_gmock(test_load_joint_trajectory_controller test/test_load_joint_trajectory_controller.cpp diff --git a/steering_controllers_library/CMakeLists.txt b/steering_controllers_library/CMakeLists.txt index 88f24d304c..106fdcc464 100644 --- a/steering_controllers_library/CMakeLists.txt +++ b/steering_controllers_library/CMakeLists.txt @@ -51,7 +51,7 @@ ament_target_dependencies(steering_controllers_library PUBLIC ${THIS_PACKAGE_INC # Causes the visibility macros to use dllexport rather than dllimport, # which is appropriate when building the dll but not consuming it. -target_compile_definitions(steering_controllers_library PRIVATE "STEERING_CONTROLLERS_BUILDING_DLL") +target_compile_definitions(steering_controllers_library PRIVATE "STEERING_CONTROLLERS_BUILDING_DLL" "_USE_MATH_DEFINES") if(BUILD_TESTING) find_package(ament_cmake_gmock REQUIRED) diff --git a/tricycle_controller/CMakeLists.txt b/tricycle_controller/CMakeLists.txt index cdc69f182a..94fba916b1 100644 --- a/tricycle_controller/CMakeLists.txt +++ b/tricycle_controller/CMakeLists.txt @@ -47,6 +47,7 @@ target_include_directories(tricycle_controller PUBLIC ) target_link_libraries(tricycle_controller PUBLIC tricycle_controller_parameters) ament_target_dependencies(tricycle_controller PUBLIC ${THIS_PACKAGE_INCLUDE_DEPENDS}) +target_compile_definitions(tricycle_controller PRIVATE _USE_MATH_DEFINES) pluginlib_export_plugin_description_file(controller_interface tricycle_controller.xml) From 1fb6100fb42a06d5e9d9f6efc600117b5a65a8de Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Mon, 12 Feb 2024 18:28:36 +0000 Subject: [PATCH 219/238] Update changelogs --- ackermann_steering_controller/CHANGELOG.rst | 6 ++++++ admittance_controller/CHANGELOG.rst | 5 +++++ bicycle_steering_controller/CHANGELOG.rst | 6 ++++++ diff_drive_controller/CHANGELOG.rst | 7 +++++++ effort_controllers/CHANGELOG.rst | 6 ++++++ force_torque_sensor_broadcaster/CHANGELOG.rst | 6 ++++++ forward_command_controller/CHANGELOG.rst | 6 ++++++ gripper_controllers/CHANGELOG.rst | 6 ++++++ imu_sensor_broadcaster/CHANGELOG.rst | 6 ++++++ joint_state_broadcaster/CHANGELOG.rst | 6 ++++++ joint_trajectory_controller/CHANGELOG.rst | 8 ++++++++ pid_controller/CHANGELOG.rst | 6 ++++++ position_controllers/CHANGELOG.rst | 6 ++++++ range_sensor_broadcaster/CHANGELOG.rst | 6 ++++++ ros2_controllers/CHANGELOG.rst | 3 +++ ros2_controllers_test_nodes/CHANGELOG.rst | 3 +++ rqt_joint_trajectory_controller/CHANGELOG.rst | 3 +++ steering_controllers_library/CHANGELOG.rst | 6 ++++++ tricycle_controller/CHANGELOG.rst | 7 +++++++ tricycle_steering_controller/CHANGELOG.rst | 6 ++++++ velocity_controllers/CHANGELOG.rst | 6 ++++++ 21 files changed, 120 insertions(+) diff --git a/ackermann_steering_controller/CHANGELOG.rst b/ackermann_steering_controller/CHANGELOG.rst index 3521258b1a..59fe46a94b 100644 --- a/ackermann_steering_controller/CHANGELOG.rst +++ b/ackermann_steering_controller/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package ackermann_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add test_depend on `hardware_interface_testing` (`#1018 `_) +* Fix tests for using new `get_node_options` API (`#840 `_) +* Contributors: Christoph Fröhlich, Sai Kishor Kothakota + 4.5.0 (2024-01-31) ------------------ * Add tests for `interface_configuration_type` consistently (`#899 `_) diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index ba1a25c0ab..099091e0db 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add test_depend on `hardware_interface_testing` (`#1018 `_) +* Contributors: Christoph Fröhlich + 4.5.0 (2024-01-31) ------------------ * Add tests for `interface_configuration_type` consistently (`#899 `_) diff --git a/bicycle_steering_controller/CHANGELOG.rst b/bicycle_steering_controller/CHANGELOG.rst index 44d8e5051d..196f9f9720 100644 --- a/bicycle_steering_controller/CHANGELOG.rst +++ b/bicycle_steering_controller/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package bicycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add test_depend on `hardware_interface_testing` (`#1018 `_) +* Fix tests for using new `get_node_options` API (`#840 `_) +* Contributors: Christoph Fröhlich, Sai Kishor Kothakota + 4.5.0 (2024-01-31) ------------------ * Add tests for `interface_configuration_type` consistently (`#899 `_) diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index 4a517f8a6d..c1ebd19d75 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,6 +2,13 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add test_depend on `hardware_interface_testing` also for diff_drive (`#1021 `_) +* Add test_depend on `hardware_interface_testing` (`#1018 `_) +* Fix tests for using new `get_node_options` API (`#840 `_) +* Contributors: Christoph Fröhlich, Sai Kishor Kothakota + 4.5.0 (2024-01-31) ------------------ * [diff_drive] Remove unused parameter and add simple validation #abi-breaking (`#958 `_) diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index 2cb40f6e36..2177f65ec5 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add test_depend on `hardware_interface_testing` (`#1018 `_) +* Fix tests for using new `get_node_options` API (`#840 `_) +* Contributors: Christoph Fröhlich, Sai Kishor Kothakota + 4.5.0 (2024-01-31) ------------------ diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index fc05235ade..bbee58772d 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add test_depend on `hardware_interface_testing` (`#1018 `_) +* Fix tests for using new `get_node_options` API (`#840 `_) +* Contributors: Christoph Fröhlich, Sai Kishor Kothakota + 4.5.0 (2024-01-31) ------------------ * Add tests for `interface_configuration_type` consistently (`#899 `_) diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index d0e32e8793..4ed48b8b94 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add test_depend on `hardware_interface_testing` (`#1018 `_) +* Fix tests for using new `get_node_options` API (`#840 `_) +* Contributors: Christoph Fröhlich, Sai Kishor Kothakota + 4.5.0 (2024-01-31) ------------------ * Add tests for `interface_configuration_type` consistently (`#899 `_) diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index 9013897769..6b8d40d81c 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add test_depend on `hardware_interface_testing` (`#1018 `_) +* Fix tests for using new `get_node_options` API (`#840 `_) +* Contributors: Christoph Fröhlich, Sai Kishor Kothakota + 4.5.0 (2024-01-31) ------------------ * Let sphinx add parameter description with nested structures to documentation (`#652 `_) diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index 61d843c659..b4f1948271 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add test_depend on `hardware_interface_testing` (`#1018 `_) +* Fix tests for using new `get_node_options` API (`#840 `_) +* Contributors: Christoph Fröhlich, Sai Kishor Kothakota + 4.5.0 (2024-01-31) ------------------ * Add tests for `interface_configuration_type` consistently (`#899 `_) diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index cd80339155..a95c23fa5c 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add test_depend on `hardware_interface_testing` (`#1018 `_) +* Fix tests for using new `get_node_options` API (`#840 `_) +* Contributors: Christoph Fröhlich, Sai Kishor Kothakota + 4.5.0 (2024-01-31) ------------------ * Add tests for `interface_configuration_type` consistently (`#899 `_) diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index a41c70cbc7..15e115f030 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,14 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Fix usage of M_PI on Windows (`#1036 `_) +* [JTC] Angle wraparound for first segment of trajectory (`#796 `_) +* Add test_depend on `hardware_interface_testing` (`#1018 `_) +* Fix tests for using new `get_node_options` API (`#840 `_) +* Contributors: Christoph Fröhlich, Sai Kishor Kothakota, Silvio Traversaro + 4.5.0 (2024-01-31) ------------------ * [JTC] Fill action error_strings (`#887 `_) diff --git a/pid_controller/CHANGELOG.rst b/pid_controller/CHANGELOG.rst index 40bfd292f5..e48ec5ef17 100644 --- a/pid_controller/CHANGELOG.rst +++ b/pid_controller/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package pid_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add test_depend on `hardware_interface_testing` (`#1018 `_) +* Fix tests for using new `get_node_options` API (`#840 `_) +* Contributors: Christoph Fröhlich, Sai Kishor Kothakota + 4.5.0 (2024-01-31) ------------------ * Add tests for `interface_configuration_type` consistently (`#899 `_) diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index e62920bf7f..d70b881e3d 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add test_depend on `hardware_interface_testing` (`#1018 `_) +* Fix tests for using new `get_node_options` API (`#840 `_) +* Contributors: Christoph Fröhlich, Sai Kishor Kothakota + 4.5.0 (2024-01-31) ------------------ diff --git a/range_sensor_broadcaster/CHANGELOG.rst b/range_sensor_broadcaster/CHANGELOG.rst index 09ce2703a7..526f303744 100644 --- a/range_sensor_broadcaster/CHANGELOG.rst +++ b/range_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package range_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add test_depend on `hardware_interface_testing` (`#1018 `_) +* Fix tests for using new `get_node_options` API (`#840 `_) +* Contributors: Christoph Fröhlich, Sai Kishor Kothakota + 4.5.0 (2024-01-31) ------------------ * Add tests for `interface_configuration_type` consistently (`#899 `_) diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index 8c96dc0ac0..e411c6e3f9 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.5.0 (2024-01-31) ------------------ diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index ab8b17ea7a..b397e2eb5c 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.5.0 (2024-01-31) ------------------ diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index c143c7c6ad..c0cd9c7743 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.5.0 (2024-01-31) ------------------ diff --git a/steering_controllers_library/CHANGELOG.rst b/steering_controllers_library/CHANGELOG.rst index 8d67b186b6..d51ddca848 100644 --- a/steering_controllers_library/CHANGELOG.rst +++ b/steering_controllers_library/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package steering_controllers_library ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Fix usage of M_PI on Windows (`#1036 `_) +* Fix tests for using new `get_node_options` API (`#840 `_) +* Contributors: Sai Kishor Kothakota, Silvio Traversaro + 4.5.0 (2024-01-31) ------------------ * Add tests for `interface_configuration_type` consistently (`#899 `_) diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index 289ff3e6b0..a366604985 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,6 +2,13 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Fix usage of M_PI on Windows (`#1036 `_) +* Add test_depend on `hardware_interface_testing` (`#1018 `_) +* Fix tests for using new `get_node_options` API (`#840 `_) +* Contributors: Christoph Fröhlich, Sai Kishor Kothakota, Silvio Traversaro + 4.5.0 (2024-01-31) ------------------ * [tricycle_controller] Use generate_parameter_library (`#957 `_) diff --git a/tricycle_steering_controller/CHANGELOG.rst b/tricycle_steering_controller/CHANGELOG.rst index 4f8d2be9f4..d08fb7c11c 100644 --- a/tricycle_steering_controller/CHANGELOG.rst +++ b/tricycle_steering_controller/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package tricycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add test_depend on `hardware_interface_testing` (`#1018 `_) +* Fix tests for using new `get_node_options` API (`#840 `_) +* Contributors: Christoph Fröhlich, Sai Kishor Kothakota + 4.5.0 (2024-01-31) ------------------ * Add tests for `interface_configuration_type` consistently (`#899 `_) diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index cbf4e9d068..a22b213dc5 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add test_depend on `hardware_interface_testing` (`#1018 `_) +* Fix tests for using new `get_node_options` API (`#840 `_) +* Contributors: Christoph Fröhlich, Sai Kishor Kothakota + 4.5.0 (2024-01-31) ------------------ From 088b69c91b5ddd1d5dce4734d3486e335548d9ff Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Mon, 12 Feb 2024 18:29:24 +0000 Subject: [PATCH 220/238] 4.6.0 --- ackermann_steering_controller/CHANGELOG.rst | 4 ++-- ackermann_steering_controller/package.xml | 2 +- admittance_controller/CHANGELOG.rst | 4 ++-- admittance_controller/package.xml | 2 +- bicycle_steering_controller/CHANGELOG.rst | 4 ++-- bicycle_steering_controller/package.xml | 2 +- diff_drive_controller/CHANGELOG.rst | 4 ++-- diff_drive_controller/package.xml | 2 +- effort_controllers/CHANGELOG.rst | 4 ++-- effort_controllers/package.xml | 2 +- force_torque_sensor_broadcaster/CHANGELOG.rst | 4 ++-- force_torque_sensor_broadcaster/package.xml | 2 +- forward_command_controller/CHANGELOG.rst | 4 ++-- forward_command_controller/package.xml | 2 +- gripper_controllers/CHANGELOG.rst | 4 ++-- gripper_controllers/package.xml | 2 +- imu_sensor_broadcaster/CHANGELOG.rst | 4 ++-- imu_sensor_broadcaster/package.xml | 2 +- joint_state_broadcaster/CHANGELOG.rst | 4 ++-- joint_state_broadcaster/package.xml | 2 +- joint_trajectory_controller/CHANGELOG.rst | 4 ++-- joint_trajectory_controller/package.xml | 2 +- pid_controller/CHANGELOG.rst | 4 ++-- pid_controller/package.xml | 2 +- position_controllers/CHANGELOG.rst | 4 ++-- position_controllers/package.xml | 2 +- range_sensor_broadcaster/CHANGELOG.rst | 4 ++-- range_sensor_broadcaster/package.xml | 2 +- ros2_controllers/CHANGELOG.rst | 4 ++-- ros2_controllers/package.xml | 2 +- ros2_controllers_test_nodes/CHANGELOG.rst | 4 ++-- ros2_controllers_test_nodes/package.xml | 2 +- ros2_controllers_test_nodes/setup.py | 2 +- rqt_joint_trajectory_controller/CHANGELOG.rst | 4 ++-- rqt_joint_trajectory_controller/package.xml | 2 +- rqt_joint_trajectory_controller/setup.py | 2 +- steering_controllers_library/CHANGELOG.rst | 4 ++-- steering_controllers_library/package.xml | 2 +- tricycle_controller/CHANGELOG.rst | 4 ++-- tricycle_controller/package.xml | 2 +- tricycle_steering_controller/CHANGELOG.rst | 4 ++-- tricycle_steering_controller/package.xml | 2 +- velocity_controllers/CHANGELOG.rst | 4 ++-- velocity_controllers/package.xml | 2 +- 44 files changed, 65 insertions(+), 65 deletions(-) diff --git a/ackermann_steering_controller/CHANGELOG.rst b/ackermann_steering_controller/CHANGELOG.rst index 59fe46a94b..3b77b7b78f 100644 --- a/ackermann_steering_controller/CHANGELOG.rst +++ b/ackermann_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ackermann_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.6.0 (2024-02-12) +------------------ * Add test_depend on `hardware_interface_testing` (`#1018 `_) * Fix tests for using new `get_node_options` API (`#840 `_) * Contributors: Christoph Fröhlich, Sai Kishor Kothakota diff --git a/ackermann_steering_controller/package.xml b/ackermann_steering_controller/package.xml index fe22ca10b8..512af88534 100644 --- a/ackermann_steering_controller/package.xml +++ b/ackermann_steering_controller/package.xml @@ -2,7 +2,7 @@ ackermann_steering_controller - 4.5.0 + 4.6.0 Steering controller for Ackermann kinematics. Rear fixed wheels are powering the vehicle and front wheels are steering it. Apache License 2.0 Bence Magyar diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index 099091e0db..65db88f462 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.6.0 (2024-02-12) +------------------ * Add test_depend on `hardware_interface_testing` (`#1018 `_) * Contributors: Christoph Fröhlich diff --git a/admittance_controller/package.xml b/admittance_controller/package.xml index e690330aa0..2c50dde2e7 100644 --- a/admittance_controller/package.xml +++ b/admittance_controller/package.xml @@ -2,7 +2,7 @@ admittance_controller - 4.5.0 + 4.6.0 Implementation of admittance controllers for different input and output interface. Denis Štogl Bence Magyar diff --git a/bicycle_steering_controller/CHANGELOG.rst b/bicycle_steering_controller/CHANGELOG.rst index 196f9f9720..16192d9f8a 100644 --- a/bicycle_steering_controller/CHANGELOG.rst +++ b/bicycle_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package bicycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.6.0 (2024-02-12) +------------------ * Add test_depend on `hardware_interface_testing` (`#1018 `_) * Fix tests for using new `get_node_options` API (`#840 `_) * Contributors: Christoph Fröhlich, Sai Kishor Kothakota diff --git a/bicycle_steering_controller/package.xml b/bicycle_steering_controller/package.xml index 8bb6ac79fa..bc560d9bf7 100644 --- a/bicycle_steering_controller/package.xml +++ b/bicycle_steering_controller/package.xml @@ -2,7 +2,7 @@ bicycle_steering_controller - 4.5.0 + 4.6.0 Steering controller with bicycle kinematics. Rear fixed wheel is powering the vehicle and front wheel is steering. Apache License 2.0 Bence Magyar diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index c1ebd19d75..1ec4329fca 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.6.0 (2024-02-12) +------------------ * Add test_depend on `hardware_interface_testing` also for diff_drive (`#1021 `_) * Add test_depend on `hardware_interface_testing` (`#1018 `_) * Fix tests for using new `get_node_options` API (`#840 `_) diff --git a/diff_drive_controller/package.xml b/diff_drive_controller/package.xml index e87ab85471..b0e818dd50 100644 --- a/diff_drive_controller/package.xml +++ b/diff_drive_controller/package.xml @@ -1,7 +1,7 @@ diff_drive_controller - 4.5.0 + 4.6.0 Controller for a differential drive mobile base. Bence Magyar Jordan Palacios diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index 2177f65ec5..ac47c3c2b3 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.6.0 (2024-02-12) +------------------ * Add test_depend on `hardware_interface_testing` (`#1018 `_) * Fix tests for using new `get_node_options` API (`#840 `_) * Contributors: Christoph Fröhlich, Sai Kishor Kothakota diff --git a/effort_controllers/package.xml b/effort_controllers/package.xml index 279d5fbf43..52165f6ec1 100644 --- a/effort_controllers/package.xml +++ b/effort_controllers/package.xml @@ -1,7 +1,7 @@ effort_controllers - 4.5.0 + 4.6.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index bbee58772d..c61f166b8e 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.6.0 (2024-02-12) +------------------ * Add test_depend on `hardware_interface_testing` (`#1018 `_) * Fix tests for using new `get_node_options` API (`#840 `_) * Contributors: Christoph Fröhlich, Sai Kishor Kothakota diff --git a/force_torque_sensor_broadcaster/package.xml b/force_torque_sensor_broadcaster/package.xml index 0791eb5d16..178a90d5cf 100644 --- a/force_torque_sensor_broadcaster/package.xml +++ b/force_torque_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ force_torque_sensor_broadcaster - 4.5.0 + 4.6.0 Controller to publish state of force-torque sensors. Bence Magyar Denis Štogl diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index 4ed48b8b94..54a428ec3f 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.6.0 (2024-02-12) +------------------ * Add test_depend on `hardware_interface_testing` (`#1018 `_) * Fix tests for using new `get_node_options` API (`#840 `_) * Contributors: Christoph Fröhlich, Sai Kishor Kothakota diff --git a/forward_command_controller/package.xml b/forward_command_controller/package.xml index 8950a9a3e9..9b6c2559f4 100644 --- a/forward_command_controller/package.xml +++ b/forward_command_controller/package.xml @@ -1,7 +1,7 @@ forward_command_controller - 4.5.0 + 4.6.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index 6b8d40d81c..76ea9418d2 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.6.0 (2024-02-12) +------------------ * Add test_depend on `hardware_interface_testing` (`#1018 `_) * Fix tests for using new `get_node_options` API (`#840 `_) * Contributors: Christoph Fröhlich, Sai Kishor Kothakota diff --git a/gripper_controllers/package.xml b/gripper_controllers/package.xml index a35fce7894..a6b83b43ec 100644 --- a/gripper_controllers/package.xml +++ b/gripper_controllers/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> gripper_controllers - 4.5.0 + 4.6.0 The gripper_controllers package Bence Magyar diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index b4f1948271..d906fb897f 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.6.0 (2024-02-12) +------------------ * Add test_depend on `hardware_interface_testing` (`#1018 `_) * Fix tests for using new `get_node_options` API (`#840 `_) * Contributors: Christoph Fröhlich, Sai Kishor Kothakota diff --git a/imu_sensor_broadcaster/package.xml b/imu_sensor_broadcaster/package.xml index 5694e1cee7..5a4ca12e87 100644 --- a/imu_sensor_broadcaster/package.xml +++ b/imu_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ imu_sensor_broadcaster - 4.5.0 + 4.6.0 Controller to publish readings of IMU sensors. Bence Magyar Denis Štogl diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index a95c23fa5c..1444f5f8ab 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.6.0 (2024-02-12) +------------------ * Add test_depend on `hardware_interface_testing` (`#1018 `_) * Fix tests for using new `get_node_options` API (`#840 `_) * Contributors: Christoph Fröhlich, Sai Kishor Kothakota diff --git a/joint_state_broadcaster/package.xml b/joint_state_broadcaster/package.xml index 6dd8b4b61e..0bf3db58dd 100644 --- a/joint_state_broadcaster/package.xml +++ b/joint_state_broadcaster/package.xml @@ -1,7 +1,7 @@ joint_state_broadcaster - 4.5.0 + 4.6.0 Broadcaster to publish joint state Bence Magyar Denis Stogl diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index 15e115f030..17b26ad551 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.6.0 (2024-02-12) +------------------ * Fix usage of M_PI on Windows (`#1036 `_) * [JTC] Angle wraparound for first segment of trajectory (`#796 `_) * Add test_depend on `hardware_interface_testing` (`#1018 `_) diff --git a/joint_trajectory_controller/package.xml b/joint_trajectory_controller/package.xml index 8cd2e5becc..5aad4cb86e 100644 --- a/joint_trajectory_controller/package.xml +++ b/joint_trajectory_controller/package.xml @@ -1,7 +1,7 @@ joint_trajectory_controller - 4.5.0 + 4.6.0 Controller for executing joint-space trajectories on a group of joints Bence Magyar Dr. Denis Štogl diff --git a/pid_controller/CHANGELOG.rst b/pid_controller/CHANGELOG.rst index e48ec5ef17..7d5d248576 100644 --- a/pid_controller/CHANGELOG.rst +++ b/pid_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package pid_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.6.0 (2024-02-12) +------------------ * Add test_depend on `hardware_interface_testing` (`#1018 `_) * Fix tests for using new `get_node_options` API (`#840 `_) * Contributors: Christoph Fröhlich, Sai Kishor Kothakota diff --git a/pid_controller/package.xml b/pid_controller/package.xml index 70c7bfa987..9cda85aa03 100644 --- a/pid_controller/package.xml +++ b/pid_controller/package.xml @@ -2,7 +2,7 @@ pid_controller - 4.5.0 + 4.6.0 Controller based on PID implememenation from control_toolbox package. Bence Magyar Denis Štogl diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index d70b881e3d..6c55f59602 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.6.0 (2024-02-12) +------------------ * Add test_depend on `hardware_interface_testing` (`#1018 `_) * Fix tests for using new `get_node_options` API (`#840 `_) * Contributors: Christoph Fröhlich, Sai Kishor Kothakota diff --git a/position_controllers/package.xml b/position_controllers/package.xml index e67d3d8a46..13e80f4d99 100644 --- a/position_controllers/package.xml +++ b/position_controllers/package.xml @@ -1,7 +1,7 @@ position_controllers - 4.5.0 + 4.6.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/range_sensor_broadcaster/CHANGELOG.rst b/range_sensor_broadcaster/CHANGELOG.rst index 526f303744..62c87c8717 100644 --- a/range_sensor_broadcaster/CHANGELOG.rst +++ b/range_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package range_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.6.0 (2024-02-12) +------------------ * Add test_depend on `hardware_interface_testing` (`#1018 `_) * Fix tests for using new `get_node_options` API (`#840 `_) * Contributors: Christoph Fröhlich, Sai Kishor Kothakota diff --git a/range_sensor_broadcaster/package.xml b/range_sensor_broadcaster/package.xml index 2d865c1d7f..3bbe1d2130 100644 --- a/range_sensor_broadcaster/package.xml +++ b/range_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ range_sensor_broadcaster - 4.5.0 + 4.6.0 Controller to publish readings of Range sensors. Bence Magyar Florent Chretien diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index e411c6e3f9..fc8ca62020 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.6.0 (2024-02-12) +------------------ 4.5.0 (2024-01-31) ------------------ diff --git a/ros2_controllers/package.xml b/ros2_controllers/package.xml index d8477b3ccd..10ae5427e9 100644 --- a/ros2_controllers/package.xml +++ b/ros2_controllers/package.xml @@ -1,7 +1,7 @@ ros2_controllers - 4.5.0 + 4.6.0 Metapackage for ROS2 controllers related packages Bence Magyar Jordan Palacios diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index b397e2eb5c..41a20f3841 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.6.0 (2024-02-12) +------------------ 4.5.0 (2024-01-31) ------------------ diff --git a/ros2_controllers_test_nodes/package.xml b/ros2_controllers_test_nodes/package.xml index 4c99d9c18a..fb5b3d8bcf 100644 --- a/ros2_controllers_test_nodes/package.xml +++ b/ros2_controllers_test_nodes/package.xml @@ -2,7 +2,7 @@ ros2_controllers_test_nodes - 4.5.0 + 4.6.0 Demo nodes for showing and testing functionalities of the ros2_control framework. Denis Štogl diff --git a/ros2_controllers_test_nodes/setup.py b/ros2_controllers_test_nodes/setup.py index 4c5afefe0a..9219fea906 100644 --- a/ros2_controllers_test_nodes/setup.py +++ b/ros2_controllers_test_nodes/setup.py @@ -20,7 +20,7 @@ setup( name=package_name, - version="4.5.0", + version="4.6.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index c0cd9c7743..cd4ae0809e 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.6.0 (2024-02-12) +------------------ 4.5.0 (2024-01-31) ------------------ diff --git a/rqt_joint_trajectory_controller/package.xml b/rqt_joint_trajectory_controller/package.xml index 0929c2aaa3..107d50681c 100644 --- a/rqt_joint_trajectory_controller/package.xml +++ b/rqt_joint_trajectory_controller/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> rqt_joint_trajectory_controller - 4.5.0 + 4.6.0 Graphical frontend for interacting with joint_trajectory_controller instances. Bence Magyar diff --git a/rqt_joint_trajectory_controller/setup.py b/rqt_joint_trajectory_controller/setup.py index 399ca590f9..8bcb07ac54 100644 --- a/rqt_joint_trajectory_controller/setup.py +++ b/rqt_joint_trajectory_controller/setup.py @@ -7,7 +7,7 @@ setup( name=package_name, - version="4.5.0", + version="4.6.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/steering_controllers_library/CHANGELOG.rst b/steering_controllers_library/CHANGELOG.rst index d51ddca848..e8288f1955 100644 --- a/steering_controllers_library/CHANGELOG.rst +++ b/steering_controllers_library/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package steering_controllers_library ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.6.0 (2024-02-12) +------------------ * Fix usage of M_PI on Windows (`#1036 `_) * Fix tests for using new `get_node_options` API (`#840 `_) * Contributors: Sai Kishor Kothakota, Silvio Traversaro diff --git a/steering_controllers_library/package.xml b/steering_controllers_library/package.xml index 66a968b71f..8212f58d91 100644 --- a/steering_controllers_library/package.xml +++ b/steering_controllers_library/package.xml @@ -2,7 +2,7 @@ steering_controllers_library - 4.5.0 + 4.6.0 Package for steering robot configurations including odometry and interfaces. Apache License 2.0 Bence Magyar diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index a366604985..cf2a599b20 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.6.0 (2024-02-12) +------------------ * Fix usage of M_PI on Windows (`#1036 `_) * Add test_depend on `hardware_interface_testing` (`#1018 `_) * Fix tests for using new `get_node_options` API (`#840 `_) diff --git a/tricycle_controller/package.xml b/tricycle_controller/package.xml index 4a8725810b..04995732f2 100644 --- a/tricycle_controller/package.xml +++ b/tricycle_controller/package.xml @@ -2,7 +2,7 @@ tricycle_controller - 4.5.0 + 4.6.0 Controller for a tricycle drive mobile base Bence Magyar Tony Najjar diff --git a/tricycle_steering_controller/CHANGELOG.rst b/tricycle_steering_controller/CHANGELOG.rst index d08fb7c11c..718df4e014 100644 --- a/tricycle_steering_controller/CHANGELOG.rst +++ b/tricycle_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package tricycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.6.0 (2024-02-12) +------------------ * Add test_depend on `hardware_interface_testing` (`#1018 `_) * Fix tests for using new `get_node_options` API (`#840 `_) * Contributors: Christoph Fröhlich, Sai Kishor Kothakota diff --git a/tricycle_steering_controller/package.xml b/tricycle_steering_controller/package.xml index 16bfd522f7..bed6e451fa 100644 --- a/tricycle_steering_controller/package.xml +++ b/tricycle_steering_controller/package.xml @@ -2,7 +2,7 @@ tricycle_steering_controller - 4.5.0 + 4.6.0 Steering controller with tricycle kinematics. Rear fixed wheels are powering the vehicle and front wheel is steering. Apache License 2.0 Bence Magyar diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index a22b213dc5..e6689b23a8 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.6.0 (2024-02-12) +------------------ * Add test_depend on `hardware_interface_testing` (`#1018 `_) * Fix tests for using new `get_node_options` API (`#840 `_) * Contributors: Christoph Fröhlich, Sai Kishor Kothakota diff --git a/velocity_controllers/package.xml b/velocity_controllers/package.xml index 3e28f7736e..ff403e178f 100644 --- a/velocity_controllers/package.xml +++ b/velocity_controllers/package.xml @@ -1,7 +1,7 @@ velocity_controllers - 4.5.0 + 4.6.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios From cb6884a64a6d1f5e22afd48bb9fe0d8bafc8fece Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Thu, 15 Feb 2024 11:35:15 +0100 Subject: [PATCH 221/238] Use reusable wfs from ros2_control_ci and use matrix strategy (#1040) --- .../workflows/humble-binary-build-testing.yml | 24 ----- ...build-main.yml => humble-binary-build.yml} | 9 +- .github/workflows/humble-debian-build.yml | 2 +- ....yml => humble-rhel-semi-binary-build.yml} | 2 +- .../humble-semi-binary-build-main.yml | 23 ----- ...sting.yml => humble-semi-binary-build.yml} | 9 +- .github/workflows/humble-source-build.yml | 2 +- .../workflows/iron-binary-build-testing.yml | 26 ----- ...y-build-main.yml => iron-binary-build.yml} | 9 +- .github/workflows/iron-debian-build.yml | 2 +- ...ld.yml => iron-rhel-semi-binary-build.yml} | 2 +- .../iron-semi-binary-build-testing.yml | 25 ----- ...ld-main.yml => iron-semi-binary-build.yml} | 9 +- .github/workflows/iron-source-build.yml | 2 +- .github/workflows/reusable-debian-build.yml | 63 ------------ .../reusable-industrial-ci-with-cache.yml | 96 ------------------- .../workflows/reusable-rhel-binary-build.yml | 69 ------------- .../reusable-ros-tooling-source-build.yml | 69 ------------- .../rolling-binary-build-testing.yml | 26 ----- ...uild-main.yml => rolling-binary-build.yml} | 9 +- .github/workflows/rolling-debian-build.yml | 2 +- ...yml => rolling-rhel-semi-binary-build.yml} | 7 +- .../rolling-semi-binary-build-testing.yml | 25 ----- ...main.yml => rolling-semi-binary-build.yml} | 9 +- .github/workflows/rolling-source-build.yml | 4 +- 25 files changed, 47 insertions(+), 478 deletions(-) delete mode 100644 .github/workflows/humble-binary-build-testing.yml rename .github/workflows/{humble-binary-build-main.yml => humble-binary-build.yml} (68%) rename .github/workflows/{humble-rhel-binary-build.yml => humble-rhel-semi-binary-build.yml} (82%) delete mode 100644 .github/workflows/humble-semi-binary-build-main.yml rename .github/workflows/{humble-semi-binary-build-testing.yml => humble-semi-binary-build.yml} (65%) delete mode 100644 .github/workflows/iron-binary-build-testing.yml rename .github/workflows/{iron-binary-build-main.yml => iron-binary-build.yml} (70%) rename .github/workflows/{iron-rhel-binary-build.yml => iron-rhel-semi-binary-build.yml} (82%) delete mode 100644 .github/workflows/iron-semi-binary-build-testing.yml rename .github/workflows/{iron-semi-binary-build-main.yml => iron-semi-binary-build.yml} (67%) delete mode 100644 .github/workflows/reusable-debian-build.yml delete mode 100644 .github/workflows/reusable-industrial-ci-with-cache.yml delete mode 100644 .github/workflows/reusable-rhel-binary-build.yml delete mode 100644 .github/workflows/reusable-ros-tooling-source-build.yml delete mode 100644 .github/workflows/rolling-binary-build-testing.yml rename .github/workflows/{rolling-binary-build-main.yml => rolling-binary-build.yml} (70%) rename .github/workflows/{rolling-rhel-binary-build.yml => rolling-rhel-semi-binary-build.yml} (70%) delete mode 100644 .github/workflows/rolling-semi-binary-build-testing.yml rename .github/workflows/{rolling-semi-binary-build-main.yml => rolling-semi-binary-build.yml} (67%) diff --git a/.github/workflows/humble-binary-build-testing.yml b/.github/workflows/humble-binary-build-testing.yml deleted file mode 100644 index b662543959..0000000000 --- a/.github/workflows/humble-binary-build-testing.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: Humble Binary Build - testing -# author: Denis Štogl -# description: 'Build & test all dependencies from released (binary) packages.' - -on: - workflow_dispatch: - pull_request: - branches: - - humble - push: - branches: - - humble - schedule: - # Run every morning to detect flakiness and broken dependencies - - cron: '03 1 * * *' - -jobs: - binary: - uses: ./.github/workflows/reusable-industrial-ci-with-cache.yml - with: - ros_distro: humble - ros_repo: testing - upstream_workspace: ros2_controllers-not-released.humble.repos - ref_for_scheduled_build: humble diff --git a/.github/workflows/humble-binary-build-main.yml b/.github/workflows/humble-binary-build.yml similarity index 68% rename from .github/workflows/humble-binary-build-main.yml rename to .github/workflows/humble-binary-build.yml index 9c634b372a..989805733f 100644 --- a/.github/workflows/humble-binary-build-main.yml +++ b/.github/workflows/humble-binary-build.yml @@ -1,4 +1,4 @@ -name: Humble Binary Build - main +name: Humble Binary Build # author: Denis Štogl # description: 'Build & test all dependencies from released (binary) packages.' @@ -16,9 +16,12 @@ on: jobs: binary: - uses: ./.github/workflows/reusable-industrial-ci-with-cache.yml + uses: ros-controls/ros2_control_ci/.github/workflows/reusable-industrial-ci-with-cache.yml@master + strategy: + matrix: + ROS_REPO: [main, testing] with: ros_distro: humble - ros_repo: main + ros_repo: ${{ matrix.ROS_REPO }} upstream_workspace: ros2_controllers-not-released.humble.repos ref_for_scheduled_build: humble diff --git a/.github/workflows/humble-debian-build.yml b/.github/workflows/humble-debian-build.yml index c236aecf64..db0a8456f8 100644 --- a/.github/workflows/humble-debian-build.yml +++ b/.github/workflows/humble-debian-build.yml @@ -12,7 +12,7 @@ on: jobs: humble_debian: name: Humble debian build - uses: ./.github/workflows/reusable-debian-build.yml + uses: ros-controls/ros2_control_ci/.github/workflows/reusable-debian-build.yml@master with: ros_distro: humble upstream_workspace: ros2_controllers.humble.repos diff --git a/.github/workflows/humble-rhel-binary-build.yml b/.github/workflows/humble-rhel-semi-binary-build.yml similarity index 82% rename from .github/workflows/humble-rhel-binary-build.yml rename to .github/workflows/humble-rhel-semi-binary-build.yml index db503d1993..ccf64a0246 100644 --- a/.github/workflows/humble-rhel-binary-build.yml +++ b/.github/workflows/humble-rhel-semi-binary-build.yml @@ -11,7 +11,7 @@ on: jobs: humble_rhel_binary: name: Humble RHEL binary build - uses: ./.github/workflows/reusable-rhel-binary-build.yml + uses: ros-controls/ros2_control_ci/.github/workflows/reusable-rhel-binary-build.yml@master with: ros_distro: humble upstream_workspace: ros2_controllers.humble.repos diff --git a/.github/workflows/humble-semi-binary-build-main.yml b/.github/workflows/humble-semi-binary-build-main.yml deleted file mode 100644 index bfe83392ea..0000000000 --- a/.github/workflows/humble-semi-binary-build-main.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: Humble Semi-Binary Build - main -# description: 'Build & test that compiles the main dependencies from source.' - -on: - workflow_dispatch: - pull_request: - branches: - - humble - push: - branches: - - humble - schedule: - # Run every morning to detect flakiness and broken dependencies - - cron: '33 1 * * *' - -jobs: - semi_binary: - uses: ./.github/workflows/reusable-industrial-ci-with-cache.yml - with: - ros_distro: humble - ros_repo: main - upstream_workspace: ros2_controllers.humble.repos - ref_for_scheduled_build: humble diff --git a/.github/workflows/humble-semi-binary-build-testing.yml b/.github/workflows/humble-semi-binary-build.yml similarity index 65% rename from .github/workflows/humble-semi-binary-build-testing.yml rename to .github/workflows/humble-semi-binary-build.yml index 3a66c0b74d..1d9d3bd1fb 100644 --- a/.github/workflows/humble-semi-binary-build-testing.yml +++ b/.github/workflows/humble-semi-binary-build.yml @@ -1,4 +1,4 @@ -name: Humble Semi-Binary Build - testing +name: Humble Semi-Binary Build # description: 'Build & test that compiles the main dependencies from source.' on: @@ -15,9 +15,12 @@ on: jobs: semi_binary: - uses: ./.github/workflows/reusable-industrial-ci-with-cache.yml + uses: ros-controls/ros2_control_ci/.github/workflows/reusable-industrial-ci-with-cache.yml@master + strategy: + matrix: + ROS_REPO: [main, testing] with: ros_distro: humble - ros_repo: testing + ros_repo: ${{ matrix.ROS_REPO }} upstream_workspace: ros2_controllers.humble.repos ref_for_scheduled_build: humble diff --git a/.github/workflows/humble-source-build.yml b/.github/workflows/humble-source-build.yml index a40d53f8e3..7b4427d6d6 100644 --- a/.github/workflows/humble-source-build.yml +++ b/.github/workflows/humble-source-build.yml @@ -10,7 +10,7 @@ on: jobs: source: - uses: ./.github/workflows/reusable-ros-tooling-source-build.yml + uses: ros-controls/ros2_control_ci/.github/workflows/reusable-ros-tooling-source-build.yml@master with: ros_distro: humble ref: humble diff --git a/.github/workflows/iron-binary-build-testing.yml b/.github/workflows/iron-binary-build-testing.yml deleted file mode 100644 index 37e3524ccd..0000000000 --- a/.github/workflows/iron-binary-build-testing.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: Iron Binary Build - testing -# author: Denis Štogl -# description: 'Build & test all dependencies from released (binary) packages.' - -on: - workflow_dispatch: - pull_request: - branches: - - iron - - '*feature*' - - '*feature/**' - push: - branches: - - iron - schedule: - # Run every morning to detect flakiness and broken dependencies - - cron: '03 1 * * *' - -jobs: - binary: - uses: ./.github/workflows/reusable-industrial-ci-with-cache.yml - with: - ros_distro: iron - ros_repo: testing - upstream_workspace: ros2_controllers-not-released.iron.repos - ref_for_scheduled_build: iron diff --git a/.github/workflows/iron-binary-build-main.yml b/.github/workflows/iron-binary-build.yml similarity index 70% rename from .github/workflows/iron-binary-build-main.yml rename to .github/workflows/iron-binary-build.yml index bb1997bd48..146d5a8c69 100644 --- a/.github/workflows/iron-binary-build-main.yml +++ b/.github/workflows/iron-binary-build.yml @@ -1,4 +1,4 @@ -name: Iron Binary Build - main +name: Iron Binary Build # author: Denis Štogl # description: 'Build & test all dependencies from released (binary) packages.' @@ -18,9 +18,12 @@ on: jobs: binary: - uses: ./.github/workflows/reusable-industrial-ci-with-cache.yml + uses: ros-controls/ros2_control_ci/.github/workflows/reusable-industrial-ci-with-cache.yml@master + strategy: + matrix: + ROS_REPO: [main, testing] with: ros_distro: iron - ros_repo: main + ros_repo: ${{ matrix.ROS_REPO }} upstream_workspace: ros2_controllers-not-released.iron.repos ref_for_scheduled_build: iron diff --git a/.github/workflows/iron-debian-build.yml b/.github/workflows/iron-debian-build.yml index 58787a804c..e56e8940ad 100644 --- a/.github/workflows/iron-debian-build.yml +++ b/.github/workflows/iron-debian-build.yml @@ -12,7 +12,7 @@ on: jobs: iron_debian: name: Iron debian build - uses: ./.github/workflows/reusable-debian-build.yml + uses: ros-controls/ros2_control_ci/.github/workflows/reusable-debian-build.yml@master with: ros_distro: iron upstream_workspace: ros2_controllers.iron.repos diff --git a/.github/workflows/iron-rhel-binary-build.yml b/.github/workflows/iron-rhel-semi-binary-build.yml similarity index 82% rename from .github/workflows/iron-rhel-binary-build.yml rename to .github/workflows/iron-rhel-semi-binary-build.yml index 90dac67a44..66ad427a98 100644 --- a/.github/workflows/iron-rhel-binary-build.yml +++ b/.github/workflows/iron-rhel-semi-binary-build.yml @@ -12,7 +12,7 @@ on: jobs: iron_rhel_binary: name: Iron RHEL binary build - uses: ./.github/workflows/reusable-rhel-binary-build.yml + uses: ros-controls/ros2_control_ci/.github/workflows/reusable-rhel-binary-build.yml@master with: ros_distro: iron upstream_workspace: ros2_controllers.iron.repos diff --git a/.github/workflows/iron-semi-binary-build-testing.yml b/.github/workflows/iron-semi-binary-build-testing.yml deleted file mode 100644 index d06a20443d..0000000000 --- a/.github/workflows/iron-semi-binary-build-testing.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: Iron Semi-Binary Build - testing -# description: 'Build & test that compiles the main dependencies from source.' - -on: - workflow_dispatch: - pull_request: - branches: - - iron - - '*feature*' - - '*feature/**' - push: - branches: - - iron - schedule: - # Run every morning to detect flakiness and broken dependencies - - cron: '33 1 * * *' - -jobs: - semi_binary: - uses: ./.github/workflows/reusable-industrial-ci-with-cache.yml - with: - ros_distro: iron - ros_repo: testing - upstream_workspace: ros2_controllers.iron.repos - ref_for_scheduled_build: iron diff --git a/.github/workflows/iron-semi-binary-build-main.yml b/.github/workflows/iron-semi-binary-build.yml similarity index 67% rename from .github/workflows/iron-semi-binary-build-main.yml rename to .github/workflows/iron-semi-binary-build.yml index ed90a46ea8..ab508dfc50 100644 --- a/.github/workflows/iron-semi-binary-build-main.yml +++ b/.github/workflows/iron-semi-binary-build.yml @@ -1,4 +1,4 @@ -name: Iron Semi-Binary Build - main +name: Iron Semi-Binary Build # description: 'Build & test that compiles the main dependencies from source.' on: @@ -17,9 +17,12 @@ on: jobs: semi_binary: - uses: ./.github/workflows/reusable-industrial-ci-with-cache.yml + uses: ros-controls/ros2_control_ci/.github/workflows/reusable-industrial-ci-with-cache.yml@master + strategy: + matrix: + ROS_REPO: [main, testing] with: ros_distro: iron - ros_repo: main + ros_repo: ${{ matrix.ROS_REPO }} upstream_workspace: ros2_controllers.iron.repos ref_for_scheduled_build: iron diff --git a/.github/workflows/iron-source-build.yml b/.github/workflows/iron-source-build.yml index 34372a4178..3609dcfc41 100644 --- a/.github/workflows/iron-source-build.yml +++ b/.github/workflows/iron-source-build.yml @@ -10,7 +10,7 @@ on: jobs: source: - uses: ./.github/workflows/reusable-ros-tooling-source-build.yml + uses: ros-controls/ros2_control_ci/.github/workflows/reusable-ros-tooling-source-build.yml@master with: ros_distro: iron ref: iron diff --git a/.github/workflows/reusable-debian-build.yml b/.github/workflows/reusable-debian-build.yml deleted file mode 100644 index b406fe6eaa..0000000000 --- a/.github/workflows/reusable-debian-build.yml +++ /dev/null @@ -1,63 +0,0 @@ -name: Reusable Debian Source Build -# Reusable action to simplify dealing with debian source builds -# author: Christoph Froehlich - -on: - workflow_call: - inputs: - ros_distro: - description: 'ROS2 distribution name' - required: true - type: string - ref_for_scheduled_build: - description: 'Reference on which the repo should be checkout for scheduled build. Usually is this name of a branch or a tag.' - default: '' - required: false - type: string - upstream_workspace: - description: 'Path to local .repos file.' - default: '' - required: false - type: string - skip_packages: - description: 'Packages to skip from build and test' - default: '' - required: false - type: string - - -jobs: - debian_source: - name: ${{ inputs.ros_distro }} debian build - runs-on: ubuntu-latest - env: - ROS_DISTRO: ${{ inputs.ros_distro }} - path: src/ros2_controllers - container: ghcr.io/ros-controls/ros:${{ inputs.ros_distro }}-debian - steps: - - name: Checkout default ref when build is not scheduled - if: ${{ github.event_name != 'schedule' }} - uses: actions/checkout@v4 - with: - path: ${{ env.path }} - - name: Checkout ${{ inputs.ref_for_scheduled_build }} on scheduled build - if: ${{ github.event_name == 'schedule' }} - uses: actions/checkout@v4 - with: - ref: ${{ inputs.ref_for_scheduled_build }} - path: ${{ env.path }} - - name: Build workspace - shell: bash - run: | - source /opt/ros2_ws/install/setup.bash - if [[ -n "${{ inputs.upstream_workspace }}" ]]; then - vcs import src < ${{ env.path }}/${{ inputs.upstream_workspace }} - fi - colcon build --packages-up-to $(colcon list --paths ${{ env.path }}/* --names-only) --packages-skip ${{ inputs.skip_packages }} - - name: Test workspace - shell: bash - continue-on-error: true - run: | - source /opt/ros2_ws/install/setup.bash - colcon test --packages-select $(colcon list --paths ${{ env.path }}/* --names-only) --packages-skip ${{ inputs.skip_packages }} - colcon test-result --verbose diff --git a/.github/workflows/reusable-industrial-ci-with-cache.yml b/.github/workflows/reusable-industrial-ci-with-cache.yml deleted file mode 100644 index 234ec27677..0000000000 --- a/.github/workflows/reusable-industrial-ci-with-cache.yml +++ /dev/null @@ -1,96 +0,0 @@ -name: Reusable industrial_ci Workflow with Cache -# Reusable action to simplify dealing with ROS/ROS2 industrial_ci builds with cache -# author: Denis Štogl - -on: - workflow_call: - inputs: - ref_for_scheduled_build: - description: 'Reference on which the repo should be checkout for scheduled build. Usually is this name of a branch or a tag.' - default: '' - required: false - type: string - - upstream_workspace: - description: 'UPSTREAM_WORKSPACE variable for industrial_ci. Usually path to local .repos file.' - required: true - type: string - ros_distro: - description: 'ROS_DISTRO variable for industrial_ci' - required: true - type: string - ros_repo: - description: 'ROS_REPO to run for industrial_ci. Possible values: "main", "testing"' - default: 'main' - required: false - type: string - os_code_name: - description: 'OS_CODE_NAME variable for industrial_ci' - default: '' - required: false - type: string - before_install_upstream_dependencies: - description: 'BEFORE_INSTALL_UPSTREAM_DEPENDENCIES variable for industrial_ci' - default: '' - required: false - type: string - - ccache_dir: - description: 'Local path to store cache (from "github.workspace"). For standard industrial_ci configuration do not have to be changed' - default: '.ccache' - required: false - type: string - basedir: - description: 'Local path to workspace base directory to cache (from "github.workspace"). For standard industrial_ci configuration do not have to be changed' - default: '.work' - required: false - type: string - - -jobs: - reusable_industrial_ci_with_cache: - name: ${{ inputs.ros_distro }} ${{ inputs.ros_repo }} ${{ inputs.os_code_name }} - runs-on: ubuntu-latest - env: - CCACHE_DIR: ${{ github.workspace }}/${{ inputs.ccache_dir }} - BASEDIR: ${{ github.workspace }}/${{ inputs.basedir }} - CACHE_PREFIX: ${{ inputs.ros_distro }}-${{ inputs.upstream_workspace }}-${{ inputs.ros_repo }}-${{ github.job }} - steps: - - name: Checkout default ref when build is not scheduled - if: ${{ github.event_name != 'schedule' }} - uses: actions/checkout@v4 - - name: Checkout ${{ inputs.ref_for_scheduled_build }} on scheduled build - if: ${{ github.event_name == 'schedule' }} - uses: actions/checkout@v4 - with: - ref: ${{ inputs.ref_for_scheduled_build }} - - name: cache target_ws - if: ${{ ! matrix.env.CCOV }} - uses: pat-s/always-upload-cache@v3.0.11 - with: - path: ${{ env.BASEDIR }}/target_ws - key: target_ws-${{ env.CACHE_PREFIX }}-${{ hashFiles('**/CMakeLists.txt', '**/package.xml') }}-${{ github.run_id }} - restore-keys: | - target_ws-${{ env.CACHE_PREFIX }}-${{ hashFiles('**/CMakeLists.txt', '**/package.xml') }} - - name: cache ccache - uses: pat-s/always-upload-cache@v3.0.11 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-${{ env.CACHE_PREFIX }}-${{ github.sha }}-${{ github.run_id }} - restore-keys: | - ccache-${{ env.CACHE_PREFIX }}-${{ github.sha }} - ccache-${{ env.CACHE_PREFIX }} - - uses: 'ros-industrial/industrial_ci@master' - env: - UPSTREAM_WORKSPACE: ${{ inputs.upstream_workspace }} - ROS_DISTRO: ${{ inputs.ros_distro }} - ROS_REPO: ${{ inputs.ros_repo }} - OS_CODE_NAME: ${{ inputs.os_code_name }} - BEFORE_INSTALL_UPSTREAM_DEPENDENCIES: ${{ inputs.before_install_upstream_dependencies }} - - name: prepare target_ws for cache - if: ${{ always() && ! matrix.env.CCOV }} - run: | - du -sh ${{ env.BASEDIR }}/target_ws - sudo find ${{ env.BASEDIR }}/target_ws -wholename '*/test_results/*' -delete - sudo rm -rf ${{ env.BASEDIR }}/target_ws/src - du -sh ${{ env.BASEDIR }}/target_ws diff --git a/.github/workflows/reusable-rhel-binary-build.yml b/.github/workflows/reusable-rhel-binary-build.yml deleted file mode 100644 index be4eabb76b..0000000000 --- a/.github/workflows/reusable-rhel-binary-build.yml +++ /dev/null @@ -1,69 +0,0 @@ -name: Reusable RHEL Binary Build -# Reusable action to simplify dealing with RHEL binary builds -# author: Christoph Froehlich - -on: - workflow_call: - inputs: - ros_distro: - description: 'ROS2 distribution name' - required: true - type: string - ref_for_scheduled_build: - description: 'Reference on which the repo should be checkout for scheduled build. Usually is this name of a branch or a tag.' - default: '' - required: false - type: string - upstream_workspace: - description: 'Path to local .repos file.' - default: '' - required: false - type: string - skip_packages: - description: 'Packages to skip from build and test' - default: '' - required: false - type: string - -jobs: - rhel_binary: - name: ${{ inputs.ros_distro }} RHEL binary build - runs-on: ubuntu-latest - env: - path: src/ros2_controllers - container: ghcr.io/ros-controls/ros:${{ inputs.ros_distro }}-rhel - steps: - - name: Checkout default ref when build is not scheduled - if: ${{ github.event_name != 'schedule' }} - uses: actions/checkout@v4 - with: - path: ${{ env.path }} - - name: Checkout ${{ inputs.ref_for_scheduled_build }} on scheduled build - if: ${{ github.event_name == 'schedule' }} - uses: actions/checkout@v4 - with: - ref: ${{ inputs.ref_for_scheduled_build }} - path: ${{ env.path }} - - name: Install dependencies - run: | - source /opt/ros/${{ inputs.ros_distro }}/setup.bash - source /opt/ros2_ws/install/local_setup.bash - if [[ -n "${{ inputs.upstream_workspace }}" ]]; then - vcs import src < ${{ env.path }}/${{ inputs.upstream_workspace }} - fi - rosdep update - rosdep install -iyr --from-path src || true - - name: Build workspace - # source also underlay workspace with generate_parameter_library on rhel9 - run: | - source /opt/ros/${{ inputs.ros_distro }}/setup.bash - source /opt/ros2_ws/install/local_setup.bash - colcon build --packages-up-to $(colcon list --paths ${{ env.path }}/* --names-only) --packages-skip ${{ inputs.skip_packages }} - - name: Test workspace - shell: bash - continue-on-error: true - run: | - source /opt/ros/${{ inputs.ros_distro }}/setup.bash - source /opt/ros2_ws/install/local_setup.bash - colcon test --packages-select $(colcon list --paths ${{ env.path }}/* --names-only) --packages-skip ${{ inputs.skip_packages }} - colcon test-result --verbose diff --git a/.github/workflows/reusable-ros-tooling-source-build.yml b/.github/workflows/reusable-ros-tooling-source-build.yml deleted file mode 100644 index 3d5bc1cf35..0000000000 --- a/.github/workflows/reusable-ros-tooling-source-build.yml +++ /dev/null @@ -1,69 +0,0 @@ -name: Reusable industrial_ci Workflow with Cache -# Reusable action to simplify dealing with ROS/ROS2 industrial_ci builds with cache -# author: Denis Štogl - -on: - workflow_call: - inputs: - ros_distro: - description: 'ROS2 distribution name' - required: true - type: string - ref: - description: 'Reference on which the repo should be checkout. Usually is this name of a branch or a tag.' - required: true - type: string - ros2_repo_branch: - description: 'Branch in the ros2/ros2 repozitory from which ".repos" should be used. Possible values: master (Rolling), humble.' - default: 'master' - required: false - type: string - -jobs: - reusable_ros_tooling_source_build: - name: ${{ inputs.ros_distro }} ubuntu-22.04 - runs-on: ubuntu-22.04 - strategy: - fail-fast: false - steps: - - uses: ros-tooling/setup-ros@0.7.1 - with: - required-ros-distributions: ${{ inputs.ros_distro }} - - uses: actions/checkout@v4 - with: - ref: ${{ inputs.ref }} - - uses: ros-tooling/action-ros-ci@0.3.6 - with: - target-ros2-distro: ${{ inputs.ros_distro }} - ref: ${{ inputs.ref }} - # build all packages listed in the meta package - package-name: - ackermann_steering_controller - admittance_controller - bicycle_steering_controller - diff_drive_controller - effort_controllers - force_torque_sensor_broadcaster - forward_command_controller - gripper_controllers - imu_sensor_broadcaster - joint_state_broadcaster - joint_trajectory_controller - position_controllers - range_sensor_broadcaster - ros2_controllers - ros2_controllers_test_nodes - rqt_joint_trajectory_controller - steering_controllers_library - tricycle_controller - tricycle_steering_controller - velocity_controllers - - vcs-repo-file-url: | - https://raw.githubusercontent.com/ros2/ros2/${{ inputs.ros2_repo_branch }}/ros2.repos - https://raw.githubusercontent.com/${{ github.repository }}/${{ github.sha }}/ros2_controllers.${{ inputs.ros_distro }}.repos?token=${{ secrets.GITHUB_TOKEN }} - colcon-mixin-repository: https://raw.githubusercontent.com/colcon/colcon-mixin-repository/master/index.yaml - - uses: actions/upload-artifact@v4.3.1 - with: - name: colcon-logs-ubuntu-22.04 - path: ros_ws/log diff --git a/.github/workflows/rolling-binary-build-testing.yml b/.github/workflows/rolling-binary-build-testing.yml deleted file mode 100644 index 0596aeec56..0000000000 --- a/.github/workflows/rolling-binary-build-testing.yml +++ /dev/null @@ -1,26 +0,0 @@ -name: Rolling Binary Build - testing -# author: Denis Štogl -# description: 'Build & test all dependencies from released (binary) packages.' - -on: - workflow_dispatch: - pull_request: - branches: - - master - - '*feature*' - - '*feature/**' - push: - branches: - - master - schedule: - # Run every morning to detect flakiness and broken dependencies - - cron: '03 1 * * *' - -jobs: - binary: - uses: ./.github/workflows/reusable-industrial-ci-with-cache.yml - with: - ros_distro: rolling - ros_repo: testing - upstream_workspace: ros2_controllers-not-released.rolling.repos - ref_for_scheduled_build: master diff --git a/.github/workflows/rolling-binary-build-main.yml b/.github/workflows/rolling-binary-build.yml similarity index 70% rename from .github/workflows/rolling-binary-build-main.yml rename to .github/workflows/rolling-binary-build.yml index 729d5e38ba..5831f0147f 100644 --- a/.github/workflows/rolling-binary-build-main.yml +++ b/.github/workflows/rolling-binary-build.yml @@ -1,4 +1,4 @@ -name: Rolling Binary Build - main +name: Rolling Binary Build # author: Denis Štogl # description: 'Build & test all dependencies from released (binary) packages.' @@ -18,9 +18,12 @@ on: jobs: binary: - uses: ./.github/workflows/reusable-industrial-ci-with-cache.yml + uses: ros-controls/ros2_control_ci/.github/workflows/reusable-industrial-ci-with-cache.yml@master + strategy: + matrix: + ROS_REPO: [main, testing] with: ros_distro: rolling - ros_repo: main + ros_repo: ${{ matrix.ROS_REPO }} upstream_workspace: ros2_controllers-not-released.rolling.repos ref_for_scheduled_build: master diff --git a/.github/workflows/rolling-debian-build.yml b/.github/workflows/rolling-debian-build.yml index 153f4df681..cecd67603f 100644 --- a/.github/workflows/rolling-debian-build.yml +++ b/.github/workflows/rolling-debian-build.yml @@ -12,7 +12,7 @@ on: jobs: rolling_debian: name: Rolling debian build - uses: ./.github/workflows/reusable-debian-build.yml + uses: ros-controls/ros2_control_ci/.github/workflows/reusable-debian-build.yml@master with: ros_distro: rolling upstream_workspace: ros2_controllers.rolling.repos diff --git a/.github/workflows/rolling-rhel-binary-build.yml b/.github/workflows/rolling-rhel-semi-binary-build.yml similarity index 70% rename from .github/workflows/rolling-rhel-binary-build.yml rename to .github/workflows/rolling-rhel-semi-binary-build.yml index 31c133ab69..a175d951b4 100644 --- a/.github/workflows/rolling-rhel-binary-build.yml +++ b/.github/workflows/rolling-rhel-semi-binary-build.yml @@ -1,4 +1,4 @@ -name: RHEL Rolling Binary Build +name: RHEL Rolling Semi-Binary Build on: workflow_dispatch: pull_request: @@ -10,9 +10,8 @@ on: jobs: - rolling_rhel_binary: - name: Rolling RHEL binary build - uses: ./.github/workflows/reusable-rhel-binary-build.yml + rolling_rhel: + uses: ros-controls/ros2_control_ci/.github/workflows/reusable-rhel-binary-build.yml@master with: ros_distro: rolling upstream_workspace: ros2_controllers.rolling.repos diff --git a/.github/workflows/rolling-semi-binary-build-testing.yml b/.github/workflows/rolling-semi-binary-build-testing.yml deleted file mode 100644 index b284c0b7d4..0000000000 --- a/.github/workflows/rolling-semi-binary-build-testing.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: Rolling Semi-Binary Build - testing -# description: 'Build & test that compiles the main dependencies from source.' - -on: - workflow_dispatch: - pull_request: - branches: - - master - - '*feature*' - - '*feature/**' - push: - branches: - - master - schedule: - # Run every morning to detect flakiness and broken dependencies - - cron: '33 1 * * *' - -jobs: - semi_binary: - uses: ./.github/workflows/reusable-industrial-ci-with-cache.yml - with: - ros_distro: rolling - ros_repo: testing - upstream_workspace: ros2_controllers.rolling.repos - ref_for_scheduled_build: master diff --git a/.github/workflows/rolling-semi-binary-build-main.yml b/.github/workflows/rolling-semi-binary-build.yml similarity index 67% rename from .github/workflows/rolling-semi-binary-build-main.yml rename to .github/workflows/rolling-semi-binary-build.yml index 206ca8bd52..edc55ebfb7 100644 --- a/.github/workflows/rolling-semi-binary-build-main.yml +++ b/.github/workflows/rolling-semi-binary-build.yml @@ -1,4 +1,4 @@ -name: Rolling Semi-Binary Build - main +name: Rolling Semi-Binary Build # description: 'Build & test that compiles the main dependencies from source.' on: @@ -17,9 +17,12 @@ on: jobs: semi_binary: - uses: ./.github/workflows/reusable-industrial-ci-with-cache.yml + uses: ros-controls/ros2_control_ci/.github/workflows/reusable-industrial-ci-with-cache.yml@master + strategy: + matrix: + ROS_REPO: [main, testing] with: ros_distro: rolling - ros_repo: main + ros_repo: ${{ matrix.ROS_REPO }} upstream_workspace: ros2_controllers.rolling.repos ref_for_scheduled_build: master diff --git a/.github/workflows/rolling-source-build.yml b/.github/workflows/rolling-source-build.yml index 40abcd1b0c..567b2c8ec6 100644 --- a/.github/workflows/rolling-source-build.yml +++ b/.github/workflows/rolling-source-build.yml @@ -1,8 +1,6 @@ name: Rolling Source Build on: workflow_dispatch: - branches: - - master push: branches: - master @@ -12,7 +10,7 @@ on: jobs: source: - uses: ./.github/workflows/reusable-ros-tooling-source-build.yml + uses: ros-controls/ros2_control_ci/.github/workflows/reusable-ros-tooling-source-build.yml@master with: ros_distro: rolling ref: master From 1c42c8ddcc79f8417afd87dbb9ed5821d58a3e83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Thu, 15 Feb 2024 17:48:14 +0100 Subject: [PATCH 222/238] [CI] reviewer lottery and fail-fast (#1047) --- .github/reviewer-lottery.yml | 33 ------------------- .github/workflows/humble-binary-build.yml | 1 + .../workflows/humble-semi-binary-build.yml | 1 + .github/workflows/iron-binary-build.yml | 1 + .github/workflows/iron-semi-binary-build.yml | 1 + .github/workflows/reviewer_lottery.yml | 1 + .github/workflows/rolling-binary-build.yml | 1 + .../workflows/rolling-semi-binary-build.yml | 1 + 8 files changed, 7 insertions(+), 33 deletions(-) delete mode 100644 .github/reviewer-lottery.yml diff --git a/.github/reviewer-lottery.yml b/.github/reviewer-lottery.yml deleted file mode 100644 index c6580eacd4..0000000000 --- a/.github/reviewer-lottery.yml +++ /dev/null @@ -1,33 +0,0 @@ -groups: - # Default reviewers for all pull requests. - # Usually, at least on of the maintainers should approve PR before merging. - # The best is if two maintainers do that. - - name: maintainers # name of the group - reviewers: 2 # how many reviewers do you want to assign? - internal_reviewers: 1 # how many reviewers do you want to assign when the PR author belongs to this group? - usernames: # github usernames of the reviewers - - bmagyar - - destogl - - # Reviewers group to get broader feedback. - - name: reviewers - reviewers: 5 - usernames: - - aprotyas - - arne48 - - bijoua29 - - christophfroehlich - - DasRoteSkelett - - duringhof - - erickisos - - fmauch - - jaron-l - - livanov93 - - mcbed - - moriarty - - olivier-stasse - - peterdavidfagan - - progtologist - - saikishor - - VanshGehlot - - VX792 diff --git a/.github/workflows/humble-binary-build.yml b/.github/workflows/humble-binary-build.yml index 989805733f..df449caecb 100644 --- a/.github/workflows/humble-binary-build.yml +++ b/.github/workflows/humble-binary-build.yml @@ -18,6 +18,7 @@ jobs: binary: uses: ros-controls/ros2_control_ci/.github/workflows/reusable-industrial-ci-with-cache.yml@master strategy: + fail-fast: false matrix: ROS_REPO: [main, testing] with: diff --git a/.github/workflows/humble-semi-binary-build.yml b/.github/workflows/humble-semi-binary-build.yml index 1d9d3bd1fb..aaed9c8ca2 100644 --- a/.github/workflows/humble-semi-binary-build.yml +++ b/.github/workflows/humble-semi-binary-build.yml @@ -17,6 +17,7 @@ jobs: semi_binary: uses: ros-controls/ros2_control_ci/.github/workflows/reusable-industrial-ci-with-cache.yml@master strategy: + fail-fast: false matrix: ROS_REPO: [main, testing] with: diff --git a/.github/workflows/iron-binary-build.yml b/.github/workflows/iron-binary-build.yml index 146d5a8c69..1510fac859 100644 --- a/.github/workflows/iron-binary-build.yml +++ b/.github/workflows/iron-binary-build.yml @@ -20,6 +20,7 @@ jobs: binary: uses: ros-controls/ros2_control_ci/.github/workflows/reusable-industrial-ci-with-cache.yml@master strategy: + fail-fast: false matrix: ROS_REPO: [main, testing] with: diff --git a/.github/workflows/iron-semi-binary-build.yml b/.github/workflows/iron-semi-binary-build.yml index ab508dfc50..38ca4fe490 100644 --- a/.github/workflows/iron-semi-binary-build.yml +++ b/.github/workflows/iron-semi-binary-build.yml @@ -19,6 +19,7 @@ jobs: semi_binary: uses: ros-controls/ros2_control_ci/.github/workflows/reusable-industrial-ci-with-cache.yml@master strategy: + fail-fast: false matrix: ROS_REPO: [main, testing] with: diff --git a/.github/workflows/reviewer_lottery.yml b/.github/workflows/reviewer_lottery.yml index ed28964e01..5784b2f836 100644 --- a/.github/workflows/reviewer_lottery.yml +++ b/.github/workflows/reviewer_lottery.yml @@ -12,3 +12,4 @@ jobs: - uses: uesteibar/reviewer-lottery@v3 with: repo-token: ${{ secrets.GITHUB_TOKEN }} + config: ros-controls/ros2_control_ci/.github/reviewer-lottery.yml diff --git a/.github/workflows/rolling-binary-build.yml b/.github/workflows/rolling-binary-build.yml index 5831f0147f..d0be23f076 100644 --- a/.github/workflows/rolling-binary-build.yml +++ b/.github/workflows/rolling-binary-build.yml @@ -20,6 +20,7 @@ jobs: binary: uses: ros-controls/ros2_control_ci/.github/workflows/reusable-industrial-ci-with-cache.yml@master strategy: + fail-fast: false matrix: ROS_REPO: [main, testing] with: diff --git a/.github/workflows/rolling-semi-binary-build.yml b/.github/workflows/rolling-semi-binary-build.yml index edc55ebfb7..4784654db8 100644 --- a/.github/workflows/rolling-semi-binary-build.yml +++ b/.github/workflows/rolling-semi-binary-build.yml @@ -19,6 +19,7 @@ jobs: semi_binary: uses: ros-controls/ros2_control_ci/.github/workflows/reusable-industrial-ci-with-cache.yml@master strategy: + fail-fast: false matrix: ROS_REPO: [main, testing] with: From d0987700e45782df54ae966e9a9bae251cde4a85 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 17 Feb 2024 15:26:56 +0100 Subject: [PATCH 223/238] Bump pre-commit/action from 3.0.0 to 3.0.1 (#1041) Bumps [pre-commit/action](https://github.com/pre-commit/action) from 3.0.0 to 3.0.1. - [Release notes](https://github.com/pre-commit/action/releases) - [Commits](https://github.com/pre-commit/action/compare/v3.0.0...v3.0.1) --- updated-dependencies: - dependency-name: pre-commit/action dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-format.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-format.yml b/.github/workflows/ci-format.yml index 9f090b48ca..824baf1b77 100644 --- a/.github/workflows/ci-format.yml +++ b/.github/workflows/ci-format.yml @@ -17,6 +17,6 @@ jobs: python-version: '3.10' - name: Install system hooks run: sudo apt install -qq clang-format-14 cppcheck - - uses: pre-commit/action@v3.0.0 + - uses: pre-commit/action@v3.0.1 with: extra_args: --all-files --hook-stage manual From f61e88b46744dd3a5231bbe94dd691ffcfd27365 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Sun, 18 Feb 2024 18:51:08 +0100 Subject: [PATCH 224/238] Update badges and add links to control.ros.org (#1050) --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4183b38fdc..7223ceae85 100644 --- a/README.md +++ b/README.md @@ -9,9 +9,9 @@ Commonly used and generalized controllers for ros2-control framework that are re ROS2 Distro | Branch | Build status | Documentation | Released packages :---------: | :----: | :----------: | :-----------: | :---------------: -**Rolling** | [`rolling`](https://github.com/ros-controls/ros2_controllers/tree/rolling) | [![Rolling Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-binary-build-main.yml?branch=master)
[![Rolling Semi-Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-semi-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-semi-binary-build-main.yml?branch=master) | | [ros2_controllers](https://index.ros.org/p/ros2_controllers/#rolling) -**Iron** | [`iron`](https://github.com/ros-controls/ros2_controllers/tree/iron) | [![Iron Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/iron-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/iron-binary-build-main.yml?branch=master)
[![Iron Semi-Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/iron-semi-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/iron-semi-binary-build-main.yml?branch=master) | | [ros2_controllers](https://index.ros.org/p/ros2_controllers/#iron) -**Humble** | [`humble`](https://github.com/ros-controls/ros2_controllers/tree/humble) | [![Humble Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-binary-build-main.yml?branch=master)
[![Humble Semi-Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-semi-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-semi-binary-build-main.yml?branch=master) | | [ros2_controllers](https://index.ros.org/p/ros2_controllers/#humble) +**Rolling** | [`rolling`](https://github.com/ros-controls/ros2_controllers/tree/rolling) | [![Rolling Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-binary-build.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-binary-build.yml?branch=master)
[![Rolling Semi-Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-semi-binary-build.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/rolling-semi-binary-build.yml?branch=master) | [control.ros.org](https://control.ros.org/master/doc/ros2_controllers/doc/controllers_index.html) | [ros2_controllers](https://index.ros.org/p/ros2_controllers/#rolling) +**Iron** | [`iron`](https://github.com/ros-controls/ros2_controllers/tree/iron) | [![Iron Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/iron-binary-build.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/iron-binary-build.yml?branch=master)
[![Iron Semi-Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/iron-semi-binary-build.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/iron-semi-binary-build.yml?branch=master) | [control.ros.org](https://control.ros.org/iron/doc/ros2_controllers/doc/controllers_index.html) | [ros2_controllers](https://index.ros.org/p/ros2_controllers/#iron) +**Humble** | [`humble`](https://github.com/ros-controls/ros2_controllers/tree/humble) | [![Humble Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-binary-build.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-binary-build.yml?branch=master)
[![Humble Semi-Binary Build](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-semi-binary-build.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_controllers/actions/workflows/humble-semi-binary-build.yml?branch=master) | [control.ros.org](https://control.ros.org/humble/doc/ros2_controllers/doc/controllers_index.html) | [ros2_controllers](https://index.ros.org/p/ros2_controllers/#humble) ### Explanation of different build types From f16554c0b70f61b8a139a04f593a90232eeb5a26 Mon Sep 17 00:00:00 2001 From: Silvio Traversaro Date: Mon, 19 Feb 2024 19:23:27 +0100 Subject: [PATCH 225/238] Fix usage of visibility macros (#1039) --- ackermann_steering_controller/CMakeLists.txt | 2 +- bicycle_steering_controller/CMakeLists.txt | 2 +- gripper_controllers/CMakeLists.txt | 4 ++++ pid_controller/CMakeLists.txt | 2 +- steering_controllers_library/CMakeLists.txt | 2 +- tricycle_controller/CMakeLists.txt | 4 +++- tricycle_steering_controller/CMakeLists.txt | 2 +- .../tricycle_steering_controller.hpp | 10 +++++----- 8 files changed, 17 insertions(+), 11 deletions(-) diff --git a/ackermann_steering_controller/CMakeLists.txt b/ackermann_steering_controller/CMakeLists.txt index 66f09c5f09..71d0cf5f80 100644 --- a/ackermann_steering_controller/CMakeLists.txt +++ b/ackermann_steering_controller/CMakeLists.txt @@ -44,7 +44,7 @@ ament_target_dependencies(ackermann_steering_controller PUBLIC ${THIS_PACKAGE_IN # Causes the visibility macros to use dllexport rather than dllimport, # which is appropriate when building the dll but not consuming it. -target_compile_definitions(ackermann_steering_controller PRIVATE "ACKERMANN_STEERING_CONTROLLER_BUILDING_DLL") +target_compile_definitions(ackermann_steering_controller PRIVATE "ACKERMANN_STEERING_CONTROLLER__VISIBILITY_BUILDING_DLL") pluginlib_export_plugin_description_file( controller_interface ackermann_steering_controller.xml) diff --git a/bicycle_steering_controller/CMakeLists.txt b/bicycle_steering_controller/CMakeLists.txt index 7118e9a44d..77d82ed874 100644 --- a/bicycle_steering_controller/CMakeLists.txt +++ b/bicycle_steering_controller/CMakeLists.txt @@ -44,7 +44,7 @@ ament_target_dependencies(bicycle_steering_controller PUBLIC ${THIS_PACKAGE_INCL # Causes the visibility macros to use dllexport rather than dllimport, # which is appropriate when building the dll but not consuming it. -target_compile_definitions(bicycle_steering_controller PRIVATE "ACKERMANN_STEERING_CONTROLLER_BUILDING_DLL") +target_compile_definitions(bicycle_steering_controller PRIVATE "BICYCLE_STEERING_CONTROLLER__VISIBILITY_BUILDING_DLL") pluginlib_export_plugin_description_file( controller_interface bicycle_steering_controller.xml) diff --git a/gripper_controllers/CMakeLists.txt b/gripper_controllers/CMakeLists.txt index 676062f7a3..c4a85dd453 100644 --- a/gripper_controllers/CMakeLists.txt +++ b/gripper_controllers/CMakeLists.txt @@ -45,6 +45,10 @@ target_link_libraries(gripper_action_controller PUBLIC ) ament_target_dependencies(gripper_action_controller PUBLIC ${THIS_PACKAGE_INCLUDE_DEPENDS}) +# Causes the visibility macros to use dllexport rather than dllimport, +# which is appropriate when building the dll but not consuming it. +target_compile_definitions(gripper_action_controller PRIVATE "GRIPPER_ACTION_CONTROLLER_BUILDING_DLL") + pluginlib_export_plugin_description_file(controller_interface ros_control_plugins.xml) if(BUILD_TESTING) diff --git a/pid_controller/CMakeLists.txt b/pid_controller/CMakeLists.txt index 15e903222a..6c9e00ef8b 100644 --- a/pid_controller/CMakeLists.txt +++ b/pid_controller/CMakeLists.txt @@ -45,7 +45,7 @@ ament_target_dependencies(pid_controller PUBLIC ${THIS_PACKAGE_INCLUDE_DEPENDS}) # Causes the visibility macros to use dllexport rather than dllimport, # which is appropriate when building the dll but not consuming it. -target_compile_definitions(pid_controller PRIVATE "PID_CONTROLLER_BUILDING_DLL") +target_compile_definitions(pid_controller PRIVATE "PID_CONTROLLER__VISIBILITY_BUILDING_DLL") pluginlib_export_plugin_description_file(controller_interface pid_controller.xml) diff --git a/steering_controllers_library/CMakeLists.txt b/steering_controllers_library/CMakeLists.txt index 106fdcc464..b79236e23e 100644 --- a/steering_controllers_library/CMakeLists.txt +++ b/steering_controllers_library/CMakeLists.txt @@ -51,7 +51,7 @@ ament_target_dependencies(steering_controllers_library PUBLIC ${THIS_PACKAGE_INC # Causes the visibility macros to use dllexport rather than dllimport, # which is appropriate when building the dll but not consuming it. -target_compile_definitions(steering_controllers_library PRIVATE "STEERING_CONTROLLERS_BUILDING_DLL" "_USE_MATH_DEFINES") +target_compile_definitions(steering_controllers_library PRIVATE "STEERING_CONTROLLERS__VISIBILITY_BUILDING_DLL" "_USE_MATH_DEFINES") if(BUILD_TESTING) find_package(ament_cmake_gmock REQUIRED) diff --git a/tricycle_controller/CMakeLists.txt b/tricycle_controller/CMakeLists.txt index 94fba916b1..ea1c4db3c1 100644 --- a/tricycle_controller/CMakeLists.txt +++ b/tricycle_controller/CMakeLists.txt @@ -47,7 +47,9 @@ target_include_directories(tricycle_controller PUBLIC ) target_link_libraries(tricycle_controller PUBLIC tricycle_controller_parameters) ament_target_dependencies(tricycle_controller PUBLIC ${THIS_PACKAGE_INCLUDE_DEPENDS}) -target_compile_definitions(tricycle_controller PRIVATE _USE_MATH_DEFINES) +# Causes the visibility macros to use dllexport rather than dllimport, +# which is appropriate when building the dll but not consuming it. +target_compile_definitions(tricycle_controller PRIVATE "TRICYCLE_CONTROLLER_BUILDING_DLL" "_USE_MATH_DEFINES") pluginlib_export_plugin_description_file(controller_interface tricycle_controller.xml) diff --git a/tricycle_steering_controller/CMakeLists.txt b/tricycle_steering_controller/CMakeLists.txt index 02c9453ace..21604df0c4 100644 --- a/tricycle_steering_controller/CMakeLists.txt +++ b/tricycle_steering_controller/CMakeLists.txt @@ -44,7 +44,7 @@ ament_target_dependencies(tricycle_steering_controller PUBLIC ${THIS_PACKAGE_INC # Causes the visibility macros to use dllexport rather than dllimport, # which is appropriate when building the dll but not consuming it. -target_compile_definitions(tricycle_steering_controller PRIVATE "ACKERMANN_STEERING_CONTROLLER_BUILDING_DLL") +target_compile_definitions(tricycle_steering_controller PRIVATE "TRICYCLE_STEERING_CONTROLLER__VISIBILITY_BUILDING_DLL") pluginlib_export_plugin_description_file( controller_interface tricycle_steering_controller.xml) diff --git a/tricycle_steering_controller/include/tricycle_steering_controller/tricycle_steering_controller.hpp b/tricycle_steering_controller/include/tricycle_steering_controller/tricycle_steering_controller.hpp index 607a684df5..559de6a223 100644 --- a/tricycle_steering_controller/include/tricycle_steering_controller/tricycle_steering_controller.hpp +++ b/tricycle_steering_controller/include/tricycle_steering_controller/tricycle_steering_controller.hpp @@ -45,14 +45,14 @@ class TricycleSteeringController : public steering_controllers_library::Steering public: TricycleSteeringController(); - STEERING_CONTROLLERS__VISIBILITY_PUBLIC controller_interface::CallbackReturn configure_odometry() - override; + TRICYCLE_STEERING_CONTROLLER__VISIBILITY_PUBLIC controller_interface::CallbackReturn + configure_odometry() override; - STEERING_CONTROLLERS__VISIBILITY_PUBLIC bool update_odometry( + TRICYCLE_STEERING_CONTROLLER__VISIBILITY_PUBLIC bool update_odometry( const rclcpp::Duration & period) override; - STEERING_CONTROLLERS__VISIBILITY_PUBLIC void initialize_implementation_parameter_listener() - override; + TRICYCLE_STEERING_CONTROLLER__VISIBILITY_PUBLIC void + initialize_implementation_parameter_listener() override; protected: std::shared_ptr tricycle_param_listener_; From 219a121bb0baa3d5d7278b6fab3c27d4a402dc36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Mon, 19 Feb 2024 19:25:03 +0100 Subject: [PATCH 226/238] Use reviewer lottery from ros2_control_ci (#1049) --- .github/workflows/reviewer_lottery.yml | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/.github/workflows/reviewer_lottery.yml b/.github/workflows/reviewer_lottery.yml index 5784b2f836..0584f4a7f3 100644 --- a/.github/workflows/reviewer_lottery.yml +++ b/.github/workflows/reviewer_lottery.yml @@ -1,15 +1,10 @@ name: Reviewer lottery +# pull_request_target takes the same events as pull_request, +# but it runs on the base branch instead of the head branch. on: pull_request_target: types: [opened, ready_for_review, reopened] jobs: - test: - runs-on: ubuntu-latest - if: github.actor != 'dependabot[bot]' && github.actor != 'mergify[bot]' - steps: - - uses: actions/checkout@v4 - - uses: uesteibar/reviewer-lottery@v3 - with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - config: ros-controls/ros2_control_ci/.github/reviewer-lottery.yml + assign_reviewers: + uses: ros-controls/ros2_control_ci/.github/workflows/reusable-reviewer-lottery.yml@master From 00172ab5dbd4948df78493e5acd40901a7227976 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Tue, 27 Feb 2024 20:07:21 +0100 Subject: [PATCH 227/238] [CI] Code coverage + pre-commit (#1057) --- .../workflows/ci-coverage-build-humble.yml | 66 ------------------- .github/workflows/ci-coverage-build-iron.yml | 66 ------------------- .github/workflows/ci-coverage-build.yml | 66 ------------------- .github/workflows/ci-format.yml | 22 ------- .github/workflows/ci-ros-lint.yml | 64 ------------------ .github/workflows/humble-coverage-build.yml | 17 +++++ .github/workflows/humble-pre-commit.yml | 14 ++++ .github/workflows/iron-coverage-build.yml | 17 +++++ .github/workflows/iron-pre-commit.yml | 14 ++++ .github/workflows/rolling-coverage-build.yml | 17 +++++ .github/workflows/rolling-pre-commit.yml | 14 ++++ .github/workflows/update-pre-commit.yml | 12 ++++ .pre-commit-config.yaml | 49 ++++++++------ .../joint_trajectory_controller.py | 8 +-- .../update_combo.py | 2 +- rqt_joint_trajectory_controller/setup.py | 14 ++++ 16 files changed, 153 insertions(+), 309 deletions(-) delete mode 100644 .github/workflows/ci-coverage-build-humble.yml delete mode 100644 .github/workflows/ci-coverage-build-iron.yml delete mode 100644 .github/workflows/ci-coverage-build.yml delete mode 100644 .github/workflows/ci-format.yml delete mode 100644 .github/workflows/ci-ros-lint.yml create mode 100644 .github/workflows/humble-coverage-build.yml create mode 100644 .github/workflows/humble-pre-commit.yml create mode 100644 .github/workflows/iron-coverage-build.yml create mode 100644 .github/workflows/iron-pre-commit.yml create mode 100644 .github/workflows/rolling-coverage-build.yml create mode 100644 .github/workflows/rolling-pre-commit.yml create mode 100644 .github/workflows/update-pre-commit.yml diff --git a/.github/workflows/ci-coverage-build-humble.yml b/.github/workflows/ci-coverage-build-humble.yml deleted file mode 100644 index 357ee3dfa8..0000000000 --- a/.github/workflows/ci-coverage-build-humble.yml +++ /dev/null @@ -1,66 +0,0 @@ -name: Coverage Build - Humble -on: - workflow_dispatch: - push: - branches: - - humble - pull_request: - branches: - - humble - -jobs: - coverage: - name: coverage build - runs-on: ubuntu-22.04 - strategy: - fail-fast: false - env: - ROS_DISTRO: humble - steps: - - uses: ros-tooling/setup-ros@0.7.1 - with: - required-ros-distributions: ${{ env.ROS_DISTRO }} - - uses: actions/checkout@v4 - - uses: ros-tooling/action-ros-ci@0.3.6 - with: - target-ros2-distro: ${{ env.ROS_DISTRO }} - import-token: ${{ secrets.GITHUB_TOKEN }} - # build all packages listed here - package-name: - ackermann_steering_controller - admittance_controller - bicycle_steering_controller - diff_drive_controller - effort_controllers - force_torque_sensor_broadcaster - forward_command_controller - gripper_controllers - imu_sensor_broadcaster - joint_state_broadcaster - joint_trajectory_controller - pid_controller - position_controllers - range_sensor_broadcaster - steering_controllers_library - tricycle_controller - tricycle_steering_controller - velocity_controllers - - vcs-repo-file-url: | - https://raw.githubusercontent.com/${{ github.repository }}/${{ github.sha }}/ros2_controllers.${{ env.ROS_DISTRO }}.repos?token=${{ secrets.GITHUB_TOKEN }} - colcon-defaults: | - { - "build": { - "mixin": ["coverage-gcc"] - } - } - colcon-mixin-repository: https://raw.githubusercontent.com/colcon/colcon-mixin-repository/master/index.yaml - - uses: codecov/codecov-action@v4.0.1 - with: - file: ros_ws/lcov/total_coverage.info - flags: unittests - name: codecov-umbrella - - uses: actions/upload-artifact@v4.3.1 - with: - name: colcon-logs-coverage-humble - path: ros_ws/log diff --git a/.github/workflows/ci-coverage-build-iron.yml b/.github/workflows/ci-coverage-build-iron.yml deleted file mode 100644 index 7914a1acb0..0000000000 --- a/.github/workflows/ci-coverage-build-iron.yml +++ /dev/null @@ -1,66 +0,0 @@ -name: Coverage Build - Iron -on: - workflow_dispatch: - push: - branches: - - iron - pull_request: - branches: - - iron - -jobs: - coverage: - name: coverage build - runs-on: ubuntu-22.04 - strategy: - fail-fast: false - env: - ROS_DISTRO: iron - steps: - - uses: ros-tooling/setup-ros@0.7.1 - with: - required-ros-distributions: ${{ env.ROS_DISTRO }} - - uses: actions/checkout@v4 - - uses: ros-tooling/action-ros-ci@0.3.6 - with: - target-ros2-distro: ${{ env.ROS_DISTRO }} - import-token: ${{ secrets.GITHUB_TOKEN }} - # build all packages listed here - package-name: - ackermann_steering_controller - admittance_controller - bicycle_steering_controller - diff_drive_controller - effort_controllers - force_torque_sensor_broadcaster - forward_command_controller - gripper_controllers - imu_sensor_broadcaster - joint_state_broadcaster - joint_trajectory_controller - pid_controller - position_controllers - range_sensor_broadcaster - steering_controllers_library - tricycle_controller - tricycle_steering_controller - velocity_controllers - - vcs-repo-file-url: | - https://raw.githubusercontent.com/${{ github.repository }}/${{ github.sha }}/ros2_controllers.${{ env.ROS_DISTRO }}.repos?token=${{ secrets.GITHUB_TOKEN }} - colcon-defaults: | - { - "build": { - "mixin": ["coverage-gcc"] - } - } - colcon-mixin-repository: https://raw.githubusercontent.com/colcon/colcon-mixin-repository/master/index.yaml - - uses: codecov/codecov-action@v4.0.1 - with: - file: ros_ws/lcov/total_coverage.info - flags: unittests - name: codecov-umbrella - - uses: actions/upload-artifact@v4.3.1 - with: - name: colcon-logs-coverage-iron - path: ros_ws/log diff --git a/.github/workflows/ci-coverage-build.yml b/.github/workflows/ci-coverage-build.yml deleted file mode 100644 index b96276ca5a..0000000000 --- a/.github/workflows/ci-coverage-build.yml +++ /dev/null @@ -1,66 +0,0 @@ -name: Coverage Build -on: - workflow_dispatch: - push: - branches: - - master - pull_request: - branches: - - master - -jobs: - coverage: - name: coverage build - runs-on: ubuntu-22.04 - strategy: - fail-fast: false - env: - ROS_DISTRO: rolling - steps: - - uses: ros-tooling/setup-ros@0.7.1 - with: - required-ros-distributions: ${{ env.ROS_DISTRO }} - - uses: actions/checkout@v4 - - uses: ros-tooling/action-ros-ci@0.3.6 - with: - target-ros2-distro: ${{ env.ROS_DISTRO }} - import-token: ${{ secrets.GITHUB_TOKEN }} - # build all packages listed here - package-name: - ackermann_steering_controller - admittance_controller - bicycle_steering_controller - diff_drive_controller - effort_controllers - force_torque_sensor_broadcaster - forward_command_controller - gripper_controllers - imu_sensor_broadcaster - joint_state_broadcaster - joint_trajectory_controller - pid_controller - position_controllers - range_sensor_broadcaster - steering_controllers_library - tricycle_controller - tricycle_steering_controller - velocity_controllers - - vcs-repo-file-url: | - https://raw.githubusercontent.com/${{ github.repository }}/${{ github.sha }}/ros2_controllers.${{ env.ROS_DISTRO }}.repos?token=${{ secrets.GITHUB_TOKEN }} - colcon-defaults: | - { - "build": { - "mixin": ["coverage-gcc"] - } - } - colcon-mixin-repository: https://raw.githubusercontent.com/colcon/colcon-mixin-repository/master/index.yaml - - uses: codecov/codecov-action@v4.0.1 - with: - file: ros_ws/lcov/total_coverage.info - flags: unittests - name: codecov-umbrella - - uses: actions/upload-artifact@v4.3.1 - with: - name: colcon-logs-coverage-rolling - path: ros_ws/log diff --git a/.github/workflows/ci-format.yml b/.github/workflows/ci-format.yml deleted file mode 100644 index 824baf1b77..0000000000 --- a/.github/workflows/ci-format.yml +++ /dev/null @@ -1,22 +0,0 @@ -# This is a format job. Pre-commit has a first-party GitHub action, so we use -# that: https://github.com/pre-commit/action - -name: Format - -on: - pull_request: - -jobs: - pre-commit: - name: Format - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5.0.0 - with: - python-version: '3.10' - - name: Install system hooks - run: sudo apt install -qq clang-format-14 cppcheck - - uses: pre-commit/action@v3.0.1 - with: - extra_args: --all-files --hook-stage manual diff --git a/.github/workflows/ci-ros-lint.yml b/.github/workflows/ci-ros-lint.yml deleted file mode 100644 index df17d11dc4..0000000000 --- a/.github/workflows/ci-ros-lint.yml +++ /dev/null @@ -1,64 +0,0 @@ -name: ROS Lint -on: - pull_request: - -env: - package-name: - ackermann_steering_controller - admittance_controller - bicycle_steering_controller - diff_drive_controller - effort_controllers - force_torque_sensor_broadcaster - forward_command_controller - gripper_controllers - imu_sensor_broadcaster - joint_state_broadcaster - joint_trajectory_controller - pid_controller - position_controllers - range_sensor_broadcaster - ros2_controllers - ros2_controllers_test_nodes - rqt_joint_trajectory_controller - steering_controllers_library - tricycle_controller - tricycle_steering_controller - velocity_controllers - -jobs: - ament_lint: - name: ament_${{ matrix.linter }} - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - linter: [cppcheck, copyright, lint_cmake] - env: - AMENT_CPPCHECK_ALLOW_SLOW_VERSIONS: true - steps: - - uses: actions/checkout@v4 - - uses: ros-tooling/setup-ros@0.7.1 - - uses: ros-tooling/action-ros-lint@v0.1 - with: - distribution: rolling - linter: ${{ matrix.linter }} - package-name: ${{ env.package-name }} - - - ament_lint_100: - name: ament_${{ matrix.linter }} - runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - linter: [cpplint] - steps: - - uses: actions/checkout@v4 - - uses: ros-tooling/setup-ros@master - - uses: ros-tooling/action-ros-lint@master - with: - distribution: rolling - linter: cpplint - arguments: "--linelength=100 --filter=-whitespace/newline" - package-name: ${{ env.package-name }} diff --git a/.github/workflows/humble-coverage-build.yml b/.github/workflows/humble-coverage-build.yml new file mode 100644 index 0000000000..0910572227 --- /dev/null +++ b/.github/workflows/humble-coverage-build.yml @@ -0,0 +1,17 @@ +name: Coverage Build - Humble +on: + workflow_dispatch: + push: + branches: + - humble + pull_request: + branches: + - humble + +jobs: + coverage_humble: + uses: ros-controls/ros2_control_ci/.github/workflows/reusable-build-coverage.yml@master + secrets: inherit + with: + ros_distro: humble + os_name: ubuntu-22.04 diff --git a/.github/workflows/humble-pre-commit.yml b/.github/workflows/humble-pre-commit.yml new file mode 100644 index 0000000000..be8c84b05b --- /dev/null +++ b/.github/workflows/humble-pre-commit.yml @@ -0,0 +1,14 @@ +name: Pre-Commit - Humble + +on: + workflow_dispatch: + pull_request: + branches: + - humble + +jobs: + pre-commit: + uses: ros-controls/ros2_control_ci/.github/workflows/reusable-pre-commit.yml@master + with: + ros_distro: humble + os_name: ubuntu-22.04 diff --git a/.github/workflows/iron-coverage-build.yml b/.github/workflows/iron-coverage-build.yml new file mode 100644 index 0000000000..d82c52bf51 --- /dev/null +++ b/.github/workflows/iron-coverage-build.yml @@ -0,0 +1,17 @@ +name: Coverage Build - Iron +on: + workflow_dispatch: + push: + branches: + - iron + pull_request: + branches: + - iron + +jobs: + coverage_iron: + uses: ros-controls/ros2_control_ci/.github/workflows/reusable-build-coverage.yml@master + secrets: inherit + with: + ros_distro: iron + os_name: ubuntu-22.04 diff --git a/.github/workflows/iron-pre-commit.yml b/.github/workflows/iron-pre-commit.yml new file mode 100644 index 0000000000..60ad26d073 --- /dev/null +++ b/.github/workflows/iron-pre-commit.yml @@ -0,0 +1,14 @@ +name: Pre-Commit - Iron + +on: + workflow_dispatch: + pull_request: + branches: + - iron + +jobs: + pre-commit: + uses: ros-controls/ros2_control_ci/.github/workflows/reusable-pre-commit.yml@master + with: + ros_distro: iron + os_name: ubuntu-22.04 diff --git a/.github/workflows/rolling-coverage-build.yml b/.github/workflows/rolling-coverage-build.yml new file mode 100644 index 0000000000..4d4750c54c --- /dev/null +++ b/.github/workflows/rolling-coverage-build.yml @@ -0,0 +1,17 @@ +name: Coverage Build - Rolling +on: + workflow_dispatch: + push: + branches: + - master + pull_request: + branches: + - master + +jobs: + coverage_rolling: + uses: ros-controls/ros2_control_ci/.github/workflows/reusable-build-coverage.yml@master + secrets: inherit + with: + ros_distro: rolling + os_name: ubuntu-22.04 diff --git a/.github/workflows/rolling-pre-commit.yml b/.github/workflows/rolling-pre-commit.yml new file mode 100644 index 0000000000..9c87311bd7 --- /dev/null +++ b/.github/workflows/rolling-pre-commit.yml @@ -0,0 +1,14 @@ +name: Pre-Commit - Rolling + +on: + workflow_dispatch: + pull_request: + branches: + - master + +jobs: + pre-commit: + uses: ros-controls/ros2_control_ci/.github/workflows/reusable-pre-commit.yml@master + with: + ros_distro: rolling + os_name: ubuntu-22.04 diff --git a/.github/workflows/update-pre-commit.yml b/.github/workflows/update-pre-commit.yml new file mode 100644 index 0000000000..8b9545dff1 --- /dev/null +++ b/.github/workflows/update-pre-commit.yml @@ -0,0 +1,12 @@ +name: Auto Update pre-commit +# Update pre-commit config and create PR if changes are detected +# author: Christoph Fröhlich + +on: + workflow_dispatch: + schedule: + - cron: '0 0 * * 0' # Run every Sunday at midnight + +jobs: + auto_update_and_create_pr: + uses: ros-controls/ros2_control_ci/.github/workflows/reusable-update-pre-commit.yml@master diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 32d194d73d..6da427c6ee 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,3 +1,4 @@ + # To use: # # pre-commit run -a @@ -15,7 +16,7 @@ repos: # Standard hooks - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.4.0 + rev: v4.5.0 hooks: - id: check-added-large-files - id: check-ast @@ -29,57 +30,57 @@ repos: - id: end-of-file-fixer - id: mixed-line-ending - id: trailing-whitespace + exclude_types: [rst] - id: fix-byte-order-marker + # Python hooks - repo: https://github.com/asottile/pyupgrade - rev: v3.3.1 + rev: v3.15.1 hooks: - id: pyupgrade args: [--py36-plus] - - repo: https://github.com/psf/black - rev: 22.12.0 - hooks: - - id: black - args: ["--line-length=99"] - # PyDocStyle - repo: https://github.com/PyCQA/pydocstyle - rev: 6.2.2 + rev: 6.3.0 hooks: - id: pydocstyle args: ["--ignore=D100,D101,D102,D103,D104,D105,D106,D107,D203,D212,D404"] + - repo: https://github.com/psf/black + rev: 24.2.0 + hooks: + - id: black + args: ["--line-length=99"] + - repo: https://github.com/pycqa/flake8 - rev: 6.0.0 + rev: 7.0.0 hooks: - id: flake8 - args: ["--ignore=E501"] + args: ["--extend-ignore=E501"] # CPP hooks - repo: https://github.com/pre-commit/mirrors-clang-format - rev: v14.0.6 + rev: v17.0.6 hooks: - id: clang-format + args: ['-fallback-style=none', '-i'] - repo: local hooks: - id: ament_cppcheck name: ament_cppcheck description: Static code analysis of C/C++ files. - stages: [commit] - entry: ament_cppcheck + entry: env AMENT_CPPCHECK_ALLOW_SLOW_VERSIONS=1 ament_cppcheck language: system files: \.(h\+\+|h|hh|hxx|hpp|cuh|c|cc|cpp|cu|c\+\+|cxx|tpp|txx)$ - # Maybe use https://github.com/cpplint/cpplint instead - repo: local hooks: - id: ament_cpplint name: ament_cpplint description: Static code analysis of C/C++ files. - stages: [commit] entry: ament_cpplint language: system files: \.(h\+\+|h|hh|hxx|hpp|cuh|c|cc|cpp|cu|c\+\+|cxx|tpp|txx)$ @@ -91,7 +92,6 @@ repos: - id: ament_lint_cmake name: ament_lint_cmake description: Check format of CMakeLists.txt files. - stages: [commit] entry: ament_lint_cmake language: system files: CMakeLists\.txt$ @@ -102,7 +102,6 @@ repos: - id: ament_copyright name: ament_copyright description: Check if copyright notice is available in all files. - stages: [commit] entry: ament_copyright language: system @@ -125,8 +124,18 @@ repos: # Spellcheck in comments and docs # skipping of *.svg files is not working... - repo: https://github.com/codespell-project/codespell - rev: v2.2.2 + rev: v2.2.6 hooks: - id: codespell - args: ['--write-changes', '--uri-ignore-words-list=ist'] + args: ['--write-changes', '--uri-ignore-words-list=ist', '-L manuel'] exclude: CHANGELOG\.rst|\.(svg|pyc|drawio)$ + + - repo: https://github.com/python-jsonschema/check-jsonschema + rev: 0.28.0 + hooks: + - id: check-github-workflows + args: ["--verbose"] + - id: check-github-actions + args: ["--verbose"] + - id: check-dependabot + args: ["--verbose"] diff --git a/rqt_joint_trajectory_controller/rqt_joint_trajectory_controller/joint_trajectory_controller.py b/rqt_joint_trajectory_controller/rqt_joint_trajectory_controller/joint_trajectory_controller.py index 162977cdfe..72c11625e4 100644 --- a/rqt_joint_trajectory_controller/rqt_joint_trajectory_controller/joint_trajectory_controller.py +++ b/rqt_joint_trajectory_controller/rqt_joint_trajectory_controller/joint_trajectory_controller.py @@ -214,9 +214,9 @@ def restore_settings(self, plugin_settings, instance_settings): try: idx = jtc_list.index(jtc_name) jtc_combo.setCurrentIndex(idx) - except (ValueError): + except ValueError: pass - except (ValueError): + except ValueError: pass # def trigger_configuration(self): @@ -427,7 +427,7 @@ def _update_cmd_cb(self): cmd = pos try: cmd = self._joint_pos[name]["command"] - except (KeyError): + except KeyError: pass max_vel = self._robot_joint_limits[name]["max_velocity"] dur.append(max(abs(cmd - pos) / max_vel, self._min_traj_dur)) @@ -445,7 +445,7 @@ def _update_joint_widgets(self): try: joint_pos = self._joint_pos[joint_name]["position"] joint_widgets[id].setValue(joint_pos) - except (KeyError): + except KeyError: pass # Can happen when first connected to controller def _joint_widgets(self): # TODO: Cache instead of compute every time? diff --git a/rqt_joint_trajectory_controller/rqt_joint_trajectory_controller/update_combo.py b/rqt_joint_trajectory_controller/rqt_joint_trajectory_controller/update_combo.py index f0b632322f..6f736910e2 100644 --- a/rqt_joint_trajectory_controller/rqt_joint_trajectory_controller/update_combo.py +++ b/rqt_joint_trajectory_controller/rqt_joint_trajectory_controller/update_combo.py @@ -36,7 +36,7 @@ def update_combo(combo, new_vals): selected_id = -1 try: selected_id = new_vals.index(selected_val) - except (ValueError): + except ValueError: combo.setCurrentIndex(-1) # Re-populate items diff --git a/rqt_joint_trajectory_controller/setup.py b/rqt_joint_trajectory_controller/setup.py index 8bcb07ac54..adb3f94668 100644 --- a/rqt_joint_trajectory_controller/setup.py +++ b/rqt_joint_trajectory_controller/setup.py @@ -1,5 +1,19 @@ #!/usr/bin/env python +# Copyright 2024 Apache License, Version 2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + from setuptools import setup from glob import glob From 7d38fb9a8c67bc996f12821280c3550c33069602 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Fri, 1 Mar 2024 10:37:43 +0100 Subject: [PATCH 228/238] Use CMake target for eigen (#1058) --- admittance_controller/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/admittance_controller/CMakeLists.txt b/admittance_controller/CMakeLists.txt index b2c10e0ba5..10ca5caa40 100644 --- a/admittance_controller/CMakeLists.txt +++ b/admittance_controller/CMakeLists.txt @@ -11,7 +11,6 @@ set(THIS_PACKAGE_INCLUDE_DEPENDS control_msgs control_toolbox controller_interface - Eigen3 generate_parameter_library geometry_msgs hardware_interface @@ -34,6 +33,7 @@ find_package(backward_ros REQUIRED) foreach(Dependency IN ITEMS ${THIS_PACKAGE_INCLUDE_DEPENDS}) find_package(${Dependency} REQUIRED) endforeach() +find_package(Eigen3 REQUIRED NO_MODULE) generate_parameter_library(admittance_controller_parameters src/admittance_controller_parameters.yaml @@ -49,6 +49,7 @@ target_include_directories(admittance_controller PUBLIC ) target_link_libraries(admittance_controller PUBLIC admittance_controller_parameters + Eigen3::Eigen ) ament_target_dependencies(admittance_controller PUBLIC ${THIS_PACKAGE_INCLUDE_DEPENDS}) From 61617b3f58a2d5915d9ea1121fb1cb362891a46e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Sat, 2 Mar 2024 20:55:12 +0100 Subject: [PATCH 229/238] [JTC] Parse URDF for continuous joints (#949) --- joint_trajectory_controller/CMakeLists.txt | 1 + .../doc/parameters_context.yaml | 7 +- .../joint_trajectory_controller.hpp | 3 + joint_trajectory_controller/package.xml | 1 + .../src/joint_trajectory_controller.cpp | 43 ++- ...oint_trajectory_controller_parameters.yaml | 7 +- .../test/test_assets.hpp | 278 ++++++++++++++++++ .../test/test_trajectory_controller.cpp | 28 +- .../test/test_trajectory_controller_utils.hpp | 24 +- 9 files changed, 360 insertions(+), 32 deletions(-) create mode 100644 joint_trajectory_controller/test/test_assets.hpp diff --git a/joint_trajectory_controller/CMakeLists.txt b/joint_trajectory_controller/CMakeLists.txt index c92d61b3f3..4b0ca82df8 100644 --- a/joint_trajectory_controller/CMakeLists.txt +++ b/joint_trajectory_controller/CMakeLists.txt @@ -19,6 +19,7 @@ set(THIS_PACKAGE_INCLUDE_DEPENDS rsl tl_expected trajectory_msgs + urdf ) find_package(ament_cmake REQUIRED) diff --git a/joint_trajectory_controller/doc/parameters_context.yaml b/joint_trajectory_controller/doc/parameters_context.yaml index 2ffe8aed36..4e4dacf202 100644 --- a/joint_trajectory_controller/doc/parameters_context.yaml +++ b/joint_trajectory_controller/doc/parameters_context.yaml @@ -9,5 +9,10 @@ gains: | .. math:: u = k_{ff} v_d + k_p e + k_i \sum e dt + k_d (v_d - v) - with the desired velocity :math:`v_d`, the measured velocity :math:`v`, the position error :math:`e` (definition see ``angle_wraparound`` below), + with the desired velocity :math:`v_d`, the measured velocity :math:`v`, the position error :math:`e` (definition see below), the controller period :math:`dt`, and the ``velocity`` or ``effort`` manipulated variable (control variable) :math:`u`, respectively. + + If the joint is of continuous type, the position error :math:`e = normalize(s_d - s)` is normalized between :math:`-\pi, \pi`, + i.e., the shortest rotation to the target position is the desired motion. + Otherwise :math:`e = s_d - s` is used, with the desired position :math:`s_d` and the measured + position :math:`s` from the state interface. diff --git a/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp b/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp index 111837cc17..ae370df0a6 100644 --- a/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp +++ b/joint_trajectory_controller/include/joint_trajectory_controller/joint_trajectory_controller.hpp @@ -43,6 +43,7 @@ #include "realtime_tools/realtime_server_goal_handle.h" #include "trajectory_msgs/msg/joint_trajectory.hpp" #include "trajectory_msgs/msg/joint_trajectory_point.hpp" +#include "urdf/model.h" // auto-generated by generate_parameter_library #include "joint_trajectory_controller_parameters.hpp" @@ -298,6 +299,8 @@ class JointTrajectoryController : public controller_interface::ControllerInterfa void resize_joint_trajectory_point_command( trajectory_msgs::msg::JointTrajectoryPoint & point, size_t size); + urdf::Model model_; + /** * @brief Assigns the values from a trajectory point interface to a joint interface. * diff --git a/joint_trajectory_controller/package.xml b/joint_trajectory_controller/package.xml index 5aad4cb86e..8457c02aeb 100644 --- a/joint_trajectory_controller/package.xml +++ b/joint_trajectory_controller/package.xml @@ -25,6 +25,7 @@ rsl tl_expected trajectory_msgs + urdf ament_cmake_gmock controller_manager diff --git a/joint_trajectory_controller/src/joint_trajectory_controller.cpp b/joint_trajectory_controller/src/joint_trajectory_controller.cpp index 46544bf875..6cae29e083 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller.cpp +++ b/joint_trajectory_controller/src/joint_trajectory_controller.cpp @@ -36,6 +36,7 @@ #include "rclcpp_action/create_server.hpp" #include "rclcpp_action/server_goal_handle.hpp" #include "rclcpp_lifecycle/state.hpp" +#include "urdf/model.h" namespace joint_trajectory_controller { @@ -46,6 +47,23 @@ JointTrajectoryController::JointTrajectoryController() controller_interface::CallbackReturn JointTrajectoryController::on_init() { + if (!urdf_.empty()) + { + if (!model_.initString(urdf_)) + { + RCLCPP_ERROR(get_node()->get_logger(), "Failed to parse URDF file"); + } + else + { + RCLCPP_DEBUG(get_node()->get_logger(), "Successfully parsed URDF file"); + } + } + else + { + // empty URDF is used for some tests + RCLCPP_DEBUG(get_node()->get_logger(), "No URDF file given"); + } + try { // Create the parameter listener and get the parameters @@ -684,12 +702,33 @@ controller_interface::CallbackReturn JointTrajectoryController::on_configure( update_pids(); } - // Configure joint position error normalization from ROS parameters (angle_wraparound) + // Configure joint position error normalization (angle_wraparound) joints_angle_wraparound_.resize(dof_); for (size_t i = 0; i < dof_; ++i) { const auto & gains = params_.gains.joints_map.at(params_.joints[i]); - joints_angle_wraparound_[i] = gains.angle_wraparound; + if (gains.angle_wraparound) + { + // TODO(christophfroehlich): remove this warning in a future release (ROS-J) + RCLCPP_WARN( + logger, + "[Deprecated] Parameter 'gains..angle_wraparound' is deprecated. The " + "angle_wraparound is now used if a continuous joint is configured in the URDF."); + joints_angle_wraparound_[i] = true; + } + + if (!urdf_.empty()) + { + auto urdf_joint = model_.getJoint(params_.joints[i]); + if (urdf_joint && urdf_joint->type == urdf::Joint::CONTINUOUS) + { + RCLCPP_DEBUG( + logger, "joint '%s' is of type continuous, use angle_wraparound.", + params_.joints[i].c_str()); + joints_angle_wraparound_[i] = true; + } + // do nothing if joint is not found in the URDF + } } if (params_.state_interfaces.empty()) diff --git a/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml b/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml index ded5bb7ca3..b17229cab8 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml +++ b/joint_trajectory_controller/src/joint_trajectory_controller_parameters.yaml @@ -125,11 +125,8 @@ joint_trajectory_controller: angle_wraparound: { type: bool, default_value: false, - description: 'For joints that wrap around (without end stop, ie. are continuous), - where the shortest rotation to the target position is the desired motion. - If true, the position error :math:`e = normalize(s_d - s)` is normalized between :math:`-\pi, \pi`. - Otherwise :math:`e = s_d - s` is used, with the desired position :math:`s_d` and the measured - position :math:`s` from the state interface.' + description: "[deprecated] For joints that wrap around (ie. are continuous). + Normalizes position-error to -pi to pi." } constraints: stopped_velocity_tolerance: { diff --git a/joint_trajectory_controller/test/test_assets.hpp b/joint_trajectory_controller/test/test_assets.hpp new file mode 100644 index 0000000000..ccdbaf4c8a --- /dev/null +++ b/joint_trajectory_controller/test/test_assets.hpp @@ -0,0 +1,278 @@ +// Copyright 2023 ros2_control Development Team +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef TEST_ASSETS_HPP_ +#define TEST_ASSETS_HPP_ + +#include + +namespace test_trajectory_controllers +{ +const auto urdf_rrrbot_revolute = + R"( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +)"; + +const auto urdf_rrrbot_continuous = + R"( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +)"; + +} // namespace test_trajectory_controllers + +#endif // TEST_ASSETS_HPP_ diff --git a/joint_trajectory_controller/test/test_trajectory_controller.cpp b/joint_trajectory_controller/test/test_trajectory_controller.cpp index 2bfe6f150d..67eb959df2 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller.cpp +++ b/joint_trajectory_controller/test/test_trajectory_controller.cpp @@ -45,6 +45,7 @@ #include "trajectory_msgs/msg/joint_trajectory.hpp" #include "trajectory_msgs/msg/joint_trajectory_point.hpp" +#include "test_assets.hpp" #include "test_trajectory_controller_utils.hpp" using lifecycle_msgs::msg::State; @@ -463,14 +464,15 @@ TEST_P(TrajectoryControllerTestParameterized, hold_on_startup) const double EPS = 1e-6; /** - * @brief check if calculated trajectory error is correct with angle wraparound=true + * @brief check if calculated trajectory error is correct (angle wraparound) for continuous joints */ TEST_P(TrajectoryControllerTestParameterized, compute_error_angle_wraparound_true) { rclcpp::executors::MultiThreadedExecutor executor; std::vector params = {}; SetUpAndActivateTrajectoryController( - executor, params, true, 0.0, 1.0, true /* angle_wraparound */); + executor, params, true, 0.0, 1.0, INITIAL_POS_JOINTS, INITIAL_VEL_JOINTS, INITIAL_ACC_JOINTS, + INITIAL_EFF_JOINTS, test_trajectory_controllers::urdf_rrrbot_continuous); size_t n_joints = joint_names_.size(); @@ -554,14 +556,15 @@ TEST_P(TrajectoryControllerTestParameterized, compute_error_angle_wraparound_tru } /** - * @brief check if calculated trajectory error is correct with angle wraparound=false + * @brief check if calculated trajectory error is correct (no angle wraparound) for revolute joints */ TEST_P(TrajectoryControllerTestParameterized, compute_error_angle_wraparound_false) { rclcpp::executors::MultiThreadedExecutor executor; std::vector params = {}; SetUpAndActivateTrajectoryController( - executor, params, true, 0.0, 1.0, false /* angle_wraparound */); + executor, params, true, 0.0, 1.0, INITIAL_POS_JOINTS, INITIAL_VEL_JOINTS, INITIAL_ACC_JOINTS, + INITIAL_EFF_JOINTS, test_trajectory_controllers::urdf_rrrbot_revolute); size_t n_joints = joint_names_.size(); @@ -636,15 +639,16 @@ TEST_P(TrajectoryControllerTestParameterized, compute_error_angle_wraparound_fal } /** - * @brief check if position error of revolute joints are wrapped around if not configured so + * @brief check if position error of revolute joints aren't wrapped around (state topic) */ TEST_P(TrajectoryControllerTestParameterized, position_error_not_angle_wraparound) { rclcpp::executors::MultiThreadedExecutor executor; constexpr double k_p = 10.0; std::vector params = {}; - bool angle_wraparound = false; - SetUpAndActivateTrajectoryController(executor, params, true, k_p, 0.0, angle_wraparound); + SetUpAndActivateTrajectoryController( + executor, params, true, k_p, 0.0, INITIAL_POS_JOINTS, INITIAL_VEL_JOINTS, INITIAL_ACC_JOINTS, + INITIAL_EFF_JOINTS, test_trajectory_controllers::urdf_rrrbot_revolute); subscribeToState(); size_t n_joints = joint_names_.size(); @@ -737,14 +741,16 @@ TEST_P(TrajectoryControllerTestParameterized, position_error_not_angle_wraparoun } /** - * @brief check if position error of revolute joints are wrapped around if configured so + * @brief check if position error of continuous joints are wrapped around (state topic) */ TEST_P(TrajectoryControllerTestParameterized, position_error_angle_wraparound) { rclcpp::executors::MultiThreadedExecutor executor; constexpr double k_p = 10.0; std::vector params = {}; - SetUpAndActivateTrajectoryController(executor, params, true, k_p, 0.0, true); + SetUpAndActivateTrajectoryController( + executor, params, true, k_p, 0.0, INITIAL_POS_JOINTS, INITIAL_VEL_JOINTS, INITIAL_ACC_JOINTS, + INITIAL_EFF_JOINTS, test_trajectory_controllers::urdf_rrrbot_continuous); size_t n_joints = joint_names_.size(); @@ -1844,7 +1850,7 @@ TEST_P(TrajectoryControllerTestParameterized, test_hw_states_has_offset_first_co std::vector initial_acc_cmd{3, std::numeric_limits::quiet_NaN()}; SetUpAndActivateTrajectoryController( - executor, {is_open_loop_parameters}, true, 0., 1., false, initial_pos_cmd, initial_vel_cmd, + executor, {is_open_loop_parameters}, true, 0., 1., initial_pos_cmd, initial_vel_cmd, initial_acc_cmd); // no call of update method, so the values should be read from state interfaces @@ -1888,7 +1894,7 @@ TEST_P(TrajectoryControllerTestParameterized, test_hw_states_has_offset_later_co initial_acc_cmd.push_back(0.02 + static_cast(i) / 10.0); } SetUpAndActivateTrajectoryController( - executor, {is_open_loop_parameters}, true, 0., 1., false, initial_pos_cmd, initial_vel_cmd, + executor, {is_open_loop_parameters}, true, 0., 1., initial_pos_cmd, initial_vel_cmd, initial_acc_cmd); // no call of update method, so the values should be read from command interfaces diff --git a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp index 6978d0e452..baa4111239 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp +++ b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp @@ -215,9 +215,10 @@ class TrajectoryControllerTest : public ::testing::Test } void SetUpTrajectoryController( - rclcpp::Executor & executor, const std::vector & parameters = {}) + rclcpp::Executor & executor, const std::vector & parameters = {}, + const std::string & urdf = "") { - auto ret = SetUpTrajectoryControllerLocal(parameters); + auto ret = SetUpTrajectoryControllerLocal(parameters, urdf); if (ret != controller_interface::return_type::OK) { FAIL(); @@ -226,7 +227,7 @@ class TrajectoryControllerTest : public ::testing::Test } controller_interface::return_type SetUpTrajectoryControllerLocal( - const std::vector & parameters = {}) + const std::vector & parameters = {}, const std::string & urdf = "") { traj_controller_ = std::make_shared(); @@ -241,11 +242,10 @@ class TrajectoryControllerTest : public ::testing::Test traj_controller_->set_node_options(node_options); return traj_controller_->init( - controller_name_, "", 0, "", traj_controller_->define_custom_node_options()); + controller_name_, urdf, 0, "", traj_controller_->define_custom_node_options()); } - void SetPidParameters( - double p_value = 0.0, double ff_value = 1.0, bool angle_wraparound_value = false) + void SetPidParameters(double p_value = 0.0, double ff_value = 1.0) { traj_controller_->trigger_declare_parameters(); auto node = traj_controller_->get_node(); @@ -258,20 +258,18 @@ class TrajectoryControllerTest : public ::testing::Test const rclcpp::Parameter k_d(prefix + ".d", 0.0); const rclcpp::Parameter i_clamp(prefix + ".i_clamp", 0.0); const rclcpp::Parameter ff_velocity_scale(prefix + ".ff_velocity_scale", ff_value); - const rclcpp::Parameter angle_wraparound( - prefix + ".angle_wraparound", angle_wraparound_value); - node->set_parameters({k_p, k_i, k_d, i_clamp, ff_velocity_scale, angle_wraparound}); + node->set_parameters({k_p, k_i, k_d, i_clamp, ff_velocity_scale}); } } void SetUpAndActivateTrajectoryController( rclcpp::Executor & executor, const std::vector & parameters = {}, bool separate_cmd_and_state_values = false, double k_p = 0.0, double ff = 1.0, - bool angle_wraparound = false, const std::vector initial_pos_joints = INITIAL_POS_JOINTS, const std::vector initial_vel_joints = INITIAL_VEL_JOINTS, const std::vector initial_acc_joints = INITIAL_ACC_JOINTS, - const std::vector initial_eff_joints = INITIAL_EFF_JOINTS) + const std::vector initial_eff_joints = INITIAL_EFF_JOINTS, + const std::string & urdf = "") { auto has_nonzero_vel_param = std::find_if( @@ -287,10 +285,10 @@ class TrajectoryControllerTest : public ::testing::Test parameters_local.emplace_back("allow_nonzero_velocity_at_trajectory_end", true); } // read-only parameters have to be set before init -> won't be read otherwise - SetUpTrajectoryController(executor, parameters_local); + SetUpTrajectoryController(executor, parameters_local, urdf); // set pid parameters before configure - SetPidParameters(k_p, ff, angle_wraparound); + SetPidParameters(k_p, ff); traj_controller_->get_node()->configure(); ActivateTrajectoryController( From 0b432919aca596fd66ae413a864500e94f64d5e3 Mon Sep 17 00:00:00 2001 From: Sai Kishor Kothakota Date: Mon, 4 Mar 2024 12:57:02 +0100 Subject: [PATCH 230/238] added conditioning to have rolling tags compilable in older versions (#1071) --- .../include/diff_drive_controller/odometry.hpp | 10 ++++++++++ .../src/joint_state_broadcaster.cpp | 1 - .../src/joint_trajectory_controller.cpp | 1 - .../test/test_trajectory_controller.cpp | 1 - pid_controller/src/pid_controller.cpp | 14 ++++++++++++++ .../src/range_sensor_broadcaster.cpp | 3 +++ .../test/test_range_sensor_broadcaster.cpp | 10 ++++++++++ .../steering_odometry.hpp | 16 ++++++++++++++-- .../src/steering_odometry.cpp | 4 ++-- .../include/tricycle_controller/odometry.hpp | 10 ++++++++++ 10 files changed, 63 insertions(+), 7 deletions(-) diff --git a/diff_drive_controller/include/diff_drive_controller/odometry.hpp b/diff_drive_controller/include/diff_drive_controller/odometry.hpp index 83ab270f72..edca431d3d 100644 --- a/diff_drive_controller/include/diff_drive_controller/odometry.hpp +++ b/diff_drive_controller/include/diff_drive_controller/odometry.hpp @@ -25,7 +25,12 @@ #include #include "rclcpp/time.hpp" +// \note The versions conditioning is added here to support the source-compatibility with Humble +#if RCPPUTILS_VERSION_MAJOR >= 2 && RCPPUTILS_VERSION_MINOR >= 6 #include "rcpputils/rolling_mean_accumulator.hpp" +#else +#include "rcppmath/rolling_mean_accumulator.hpp" +#endif namespace diff_drive_controller { @@ -50,7 +55,12 @@ class Odometry void setVelocityRollingWindowSize(size_t velocity_rolling_window_size); private: +// \note The versions conditioning is added here to support the source-compatibility with Humble +#if RCPPUTILS_VERSION_MAJOR >= 2 && RCPPUTILS_VERSION_MINOR >= 6 using RollingMeanAccumulator = rcpputils::RollingMeanAccumulator; +#else + using RollingMeanAccumulator = rcppmath::RollingMeanAccumulator; +#endif void integrateRungeKutta2(double linear, double angular); void integrateExact(double linear, double angular); diff --git a/joint_state_broadcaster/src/joint_state_broadcaster.cpp b/joint_state_broadcaster/src/joint_state_broadcaster.cpp index 3c2192d40e..a53fe2b3c4 100644 --- a/joint_state_broadcaster/src/joint_state_broadcaster.cpp +++ b/joint_state_broadcaster/src/joint_state_broadcaster.cpp @@ -24,7 +24,6 @@ #include "hardware_interface/types/hardware_interface_return_values.hpp" #include "hardware_interface/types/hardware_interface_type_values.hpp" #include "rclcpp/clock.hpp" -#include "rclcpp/event_handler.hpp" #include "rclcpp/qos.hpp" #include "rclcpp/time.hpp" #include "rclcpp_lifecycle/lifecycle_node.hpp" diff --git a/joint_trajectory_controller/src/joint_trajectory_controller.cpp b/joint_trajectory_controller/src/joint_trajectory_controller.cpp index 6cae29e083..5e3d9d1c7d 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller.cpp +++ b/joint_trajectory_controller/src/joint_trajectory_controller.cpp @@ -29,7 +29,6 @@ #include "hardware_interface/types/hardware_interface_type_values.hpp" #include "joint_trajectory_controller/trajectory.hpp" #include "lifecycle_msgs/msg/state.hpp" -#include "rclcpp/event_handler.hpp" #include "rclcpp/logging.hpp" #include "rclcpp/qos.hpp" #include "rclcpp/time.hpp" diff --git a/joint_trajectory_controller/test/test_trajectory_controller.cpp b/joint_trajectory_controller/test/test_trajectory_controller.cpp index 67eb959df2..f5e9cb7260 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller.cpp +++ b/joint_trajectory_controller/test/test_trajectory_controller.cpp @@ -32,7 +32,6 @@ #include "lifecycle_msgs/msg/state.hpp" #include "rclcpp/clock.hpp" #include "rclcpp/duration.hpp" -#include "rclcpp/event_handler.hpp" #include "rclcpp/executors/multi_threaded_executor.hpp" #include "rclcpp/executors/single_threaded_executor.hpp" #include "rclcpp/node.hpp" diff --git a/pid_controller/src/pid_controller.cpp b/pid_controller/src/pid_controller.cpp index 05fee986dd..19cebbde4e 100644 --- a/pid_controller/src/pid_controller.cpp +++ b/pid_controller/src/pid_controller.cpp @@ -30,10 +30,24 @@ namespace { // utility // Changed services history QoS to keep all so we don't lose any client service calls +// \note The versions conditioning is added here to support the source-compatibility with Humble +#if RCLCPP_VERSION_MAJOR >= 17 rclcpp::QoS qos_services = rclcpp::QoS(rclcpp::QoSInitialization(RMW_QOS_POLICY_HISTORY_KEEP_ALL, 1)) .reliable() .durability_volatile(); +#else +static const rmw_qos_profile_t qos_services = { + RMW_QOS_POLICY_HISTORY_KEEP_ALL, + 1, // message queue depth + RMW_QOS_POLICY_RELIABILITY_RELIABLE, + RMW_QOS_POLICY_DURABILITY_VOLATILE, + RMW_QOS_DEADLINE_DEFAULT, + RMW_QOS_LIFESPAN_DEFAULT, + RMW_QOS_POLICY_LIVELINESS_SYSTEM_DEFAULT, + RMW_QOS_LIVELINESS_LEASE_DURATION_DEFAULT, + false}; +#endif using ControllerCommandMsg = pid_controller::PidController::ControllerReferenceMsg; diff --git a/range_sensor_broadcaster/src/range_sensor_broadcaster.cpp b/range_sensor_broadcaster/src/range_sensor_broadcaster.cpp index b821da8c13..7c6d714be3 100644 --- a/range_sensor_broadcaster/src/range_sensor_broadcaster.cpp +++ b/range_sensor_broadcaster/src/range_sensor_broadcaster.cpp @@ -79,7 +79,10 @@ controller_interface::CallbackReturn RangeSensorBroadcaster::on_configure( realtime_publisher_->msg_.field_of_view = params_.field_of_view; realtime_publisher_->msg_.min_range = params_.min_range; realtime_publisher_->msg_.max_range = params_.max_range; +// \note The versions conditioning is added here to support the source-compatibility with Humble +#if SENSOR_MSGS_VERSION_MAJOR >= 5 realtime_publisher_->msg_.variance = params_.variance; +#endif realtime_publisher_->unlock(); RCLCPP_DEBUG(get_node()->get_logger(), "configure successful"); diff --git a/range_sensor_broadcaster/test/test_range_sensor_broadcaster.cpp b/range_sensor_broadcaster/test/test_range_sensor_broadcaster.cpp index 010f18c1a6..a23d5e3cde 100644 --- a/range_sensor_broadcaster/test/test_range_sensor_broadcaster.cpp +++ b/range_sensor_broadcaster/test/test_range_sensor_broadcaster.cpp @@ -203,7 +203,9 @@ TEST_F(RangeSensorBroadcasterTest, Publish_RangeBroadcaster_Success) EXPECT_THAT(range_msg.field_of_view, ::testing::FloatEq(field_of_view_)); EXPECT_THAT(range_msg.min_range, ::testing::FloatEq(min_range_)); EXPECT_THAT(range_msg.max_range, ::testing::FloatEq(max_range_)); +#if SENSOR_MSGS_VERSION_MAJOR >= 5 EXPECT_THAT(range_msg.variance, ::testing::FloatEq(variance_)); +#endif } TEST_F(RangeSensorBroadcasterTest, Publish_Bandaries_RangeBroadcaster_Success) @@ -224,7 +226,9 @@ TEST_F(RangeSensorBroadcasterTest, Publish_Bandaries_RangeBroadcaster_Success) EXPECT_THAT(range_msg.field_of_view, ::testing::FloatEq(field_of_view_)); EXPECT_THAT(range_msg.min_range, ::testing::FloatEq(min_range_)); EXPECT_THAT(range_msg.max_range, ::testing::FloatEq(max_range_)); +#if SENSOR_MSGS_VERSION_MAJOR >= 5 EXPECT_THAT(range_msg.variance, ::testing::FloatEq(variance_)); +#endif sensor_range_ = 4.0; subscribe_and_get_message(range_msg); @@ -235,7 +239,9 @@ TEST_F(RangeSensorBroadcasterTest, Publish_Bandaries_RangeBroadcaster_Success) EXPECT_THAT(range_msg.field_of_view, ::testing::FloatEq(field_of_view_)); EXPECT_THAT(range_msg.min_range, ::testing::FloatEq(min_range_)); EXPECT_THAT(range_msg.max_range, ::testing::FloatEq(max_range_)); +#if SENSOR_MSGS_VERSION_MAJOR >= 5 EXPECT_THAT(range_msg.variance, ::testing::FloatEq(variance_)); +#endif } TEST_F(RangeSensorBroadcasterTest, Publish_OutOfBandaries_RangeBroadcaster_Success) @@ -257,7 +263,9 @@ TEST_F(RangeSensorBroadcasterTest, Publish_OutOfBandaries_RangeBroadcaster_Succe EXPECT_THAT(range_msg.field_of_view, ::testing::FloatEq(field_of_view_)); EXPECT_THAT(range_msg.min_range, ::testing::FloatEq(min_range_)); EXPECT_THAT(range_msg.max_range, ::testing::FloatEq(max_range_)); +#if SENSOR_MSGS_VERSION_MAJOR >= 5 EXPECT_THAT(range_msg.variance, ::testing::FloatEq(variance_)); +#endif sensor_range_ = 6.0; subscribe_and_get_message(range_msg); @@ -269,7 +277,9 @@ TEST_F(RangeSensorBroadcasterTest, Publish_OutOfBandaries_RangeBroadcaster_Succe EXPECT_THAT(range_msg.field_of_view, ::testing::FloatEq(field_of_view_)); EXPECT_THAT(range_msg.min_range, ::testing::FloatEq(min_range_)); EXPECT_THAT(range_msg.max_range, ::testing::FloatEq(max_range_)); +#if SENSOR_MSGS_VERSION_MAJOR >= 5 EXPECT_THAT(range_msg.variance, ::testing::FloatEq(variance_)); +#endif } int main(int argc, char ** argv) diff --git a/steering_controllers_library/include/steering_controllers_library/steering_odometry.hpp b/steering_controllers_library/include/steering_controllers_library/steering_odometry.hpp index 95bcef7e63..e4a22f6d3b 100644 --- a/steering_controllers_library/include/steering_controllers_library/steering_odometry.hpp +++ b/steering_controllers_library/include/steering_controllers_library/steering_odometry.hpp @@ -24,7 +24,12 @@ #include "realtime_tools/realtime_buffer.h" #include "realtime_tools/realtime_publisher.h" +// \note The versions conditioning is added here to support the source-compatibility with Humble +#if RCPPUTILS_VERSION_MAJOR >= 2 && RCPPUTILS_VERSION_MINOR >= 6 #include "rcpputils/rolling_mean_accumulator.hpp" +#else +#include "rcppmath/rolling_mean_accumulator.hpp" +#endif namespace steering_odometry { @@ -229,6 +234,13 @@ class SteeringOdometry */ void reset_accumulators(); +// \note The versions conditioning is added here to support the source-compatibility with Humble +#if RCPPUTILS_VERSION_MAJOR >= 2 && RCPPUTILS_VERSION_MINOR >= 6 + using RollingMeanAccumulator = rcpputils::RollingMeanAccumulator; +#else + using RollingMeanAccumulator = rcppmath::RollingMeanAccumulator; +#endif + /// Current timestamp: rclcpp::Time timestamp_; @@ -256,8 +268,8 @@ class SteeringOdometry double traction_left_wheel_old_pos_; /// Rolling mean accumulators for the linear and angular velocities: size_t velocity_rolling_window_size_; - rcpputils::RollingMeanAccumulator linear_acc_; - rcpputils::RollingMeanAccumulator angular_acc_; + RollingMeanAccumulator linear_acc_; + RollingMeanAccumulator angular_acc_; }; } // namespace steering_odometry diff --git a/steering_controllers_library/src/steering_odometry.cpp b/steering_controllers_library/src/steering_odometry.cpp index e2ced036ff..aadd047f2e 100644 --- a/steering_controllers_library/src/steering_odometry.cpp +++ b/steering_controllers_library/src/steering_odometry.cpp @@ -324,8 +324,8 @@ void SteeringOdometry::integrate_exact(double linear, double angular) void SteeringOdometry::reset_accumulators() { - linear_acc_ = rcpputils::RollingMeanAccumulator(velocity_rolling_window_size_); - angular_acc_ = rcpputils::RollingMeanAccumulator(velocity_rolling_window_size_); + linear_acc_ = RollingMeanAccumulator(velocity_rolling_window_size_); + angular_acc_ = RollingMeanAccumulator(velocity_rolling_window_size_); } } // namespace steering_odometry diff --git a/tricycle_controller/include/tricycle_controller/odometry.hpp b/tricycle_controller/include/tricycle_controller/odometry.hpp index 62eb51d6cc..13d65a980a 100644 --- a/tricycle_controller/include/tricycle_controller/odometry.hpp +++ b/tricycle_controller/include/tricycle_controller/odometry.hpp @@ -22,7 +22,12 @@ #include #include "rclcpp/time.hpp" +// \note The versions conditioning is added here to support the source-compatibility with Humble +#if RCPPUTILS_VERSION_MAJOR >= 2 && RCPPUTILS_VERSION_MINOR >= 6 #include "rcpputils/rolling_mean_accumulator.hpp" +#else +#include "rcppmath/rolling_mean_accumulator.hpp" +#endif namespace tricycle_controller { @@ -45,7 +50,12 @@ class Odometry void setVelocityRollingWindowSize(size_t velocity_rolling_window_size); private: +// \note The versions conditioning is added here to support the source-compatibility with Humble +#if RCPPUTILS_VERSION_MAJOR >= 2 && RCPPUTILS_VERSION_MINOR >= 6 using RollingMeanAccumulator = rcpputils::RollingMeanAccumulator; +#else + using RollingMeanAccumulator = rcppmath::RollingMeanAccumulator; +#endif void integrateRungeKutta2(double linear, double angular); void integrateExact(double linear, double angular); From 28cb552903a9d17264594efeb148f8b04bda3039 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 11 Mar 2024 13:02:46 +0000 Subject: [PATCH 231/238] Bump version of pre-commit hooks (#1073) --- .pre-commit-config.yaml | 2 +- .../src/joint_trajectory_controller.cpp | 6 ++---- .../test/test_trajectory_controller_utils.hpp | 7 +++---- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6da427c6ee..dc3b3e837d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -62,7 +62,7 @@ repos: # CPP hooks - repo: https://github.com/pre-commit/mirrors-clang-format - rev: v17.0.6 + rev: v18.1.0 hooks: - id: clang-format args: ['-fallback-style=none', '-i'] diff --git a/joint_trajectory_controller/src/joint_trajectory_controller.cpp b/joint_trajectory_controller/src/joint_trajectory_controller.cpp index 5e3d9d1c7d..4a4b63cb75 100644 --- a/joint_trajectory_controller/src/joint_trajectory_controller.cpp +++ b/joint_trajectory_controller/src/joint_trajectory_controller.cpp @@ -444,8 +444,7 @@ bool JointTrajectoryController::read_state_from_command_interfaces(JointTrajecto auto interface_has_values = [](const auto & joint_interface) { return std::find_if( - joint_interface.begin(), joint_interface.end(), - [](const auto & interface) + joint_interface.begin(), joint_interface.end(), [](const auto & interface) { return std::isnan(interface.get().get_value()); }) == joint_interface.end(); }; @@ -515,8 +514,7 @@ bool JointTrajectoryController::read_commands_from_command_interfaces( auto interface_has_values = [](const auto & joint_interface) { return std::find_if( - joint_interface.begin(), joint_interface.end(), - [](const auto & interface) + joint_interface.begin(), joint_interface.end(), [](const auto & interface) { return std::isnan(interface.get().get_value()); }) == joint_interface.end(); }; diff --git a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp index baa4111239..f049bc65a9 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp +++ b/joint_trajectory_controller/test/test_trajectory_controller_utils.hpp @@ -273,10 +273,9 @@ class TrajectoryControllerTest : public ::testing::Test { auto has_nonzero_vel_param = std::find_if( - parameters.begin(), parameters.end(), - [](const rclcpp::Parameter & param) { - return param.get_name() == "allow_nonzero_velocity_at_trajectory_end"; - }) != parameters.end(); + parameters.begin(), parameters.end(), [](const rclcpp::Parameter & param) + { return param.get_name() == "allow_nonzero_velocity_at_trajectory_end"; }) != + parameters.end(); std::vector parameters_local = parameters; if (!has_nonzero_vel_param) From ab1e042585d42cb36745fbf84d66144d529c1158 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Mon, 18 Mar 2024 07:15:23 +0100 Subject: [PATCH 232/238] Remove action_msg dependency (#1077) --- joint_trajectory_controller/test/test_trajectory_actions.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/joint_trajectory_controller/test/test_trajectory_actions.cpp b/joint_trajectory_controller/test/test_trajectory_actions.cpp index 87d557df1b..332a30c53a 100644 --- a/joint_trajectory_controller/test/test_trajectory_actions.cpp +++ b/joint_trajectory_controller/test/test_trajectory_actions.cpp @@ -27,7 +27,6 @@ #include #include -#include "action_msgs/msg/goal_status_array.hpp" #include "control_msgs/action/detail/follow_joint_trajectory__struct.hpp" #include "controller_interface/controller_interface.hpp" #include "gtest/gtest.h" From 5a28a2aea9ef76cf32091e43cb7c72461f624ad4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 18 Mar 2024 06:23:52 +0000 Subject: [PATCH 233/238] Bump version of pre-commit hooks (#1079) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index dc3b3e837d..31ba833ba5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -49,7 +49,7 @@ repos: args: ["--ignore=D100,D101,D102,D103,D104,D105,D106,D107,D203,D212,D404"] - repo: https://github.com/psf/black - rev: 24.2.0 + rev: 24.3.0 hooks: - id: black args: ["--line-length=99"] @@ -62,7 +62,7 @@ repos: # CPP hooks - repo: https://github.com/pre-commit/mirrors-clang-format - rev: v18.1.0 + rev: v18.1.1 hooks: - id: clang-format args: ['-fallback-style=none', '-i'] From 0c2c458abc8c8e9d547f88661871e036b8eb2437 Mon Sep 17 00:00:00 2001 From: Chris Lalancette Date: Thu, 21 Mar 2024 02:27:53 -0400 Subject: [PATCH 234/238] Fix pid_controller build on ROS 2 Rolling on Ubuntu 24.04 (#1084) --- ackermann_steering_controller/package.xml | 1 + bicycle_steering_controller/package.xml | 1 + pid_controller/package.xml | 1 + pid_controller/src/pid_controller.cpp | 3 +++ tricycle_steering_controller/package.xml | 1 + 5 files changed, 7 insertions(+) diff --git a/ackermann_steering_controller/package.xml b/ackermann_steering_controller/package.xml index 512af88534..a3183af262 100644 --- a/ackermann_steering_controller/package.xml +++ b/ackermann_steering_controller/package.xml @@ -16,6 +16,7 @@ generate_parameter_library + backward_ros control_msgs controller_interface hardware_interface diff --git a/bicycle_steering_controller/package.xml b/bicycle_steering_controller/package.xml index bc560d9bf7..6507700a5d 100644 --- a/bicycle_steering_controller/package.xml +++ b/bicycle_steering_controller/package.xml @@ -16,6 +16,7 @@ generate_parameter_library + backward_ros control_msgs controller_interface hardware_interface diff --git a/pid_controller/package.xml b/pid_controller/package.xml index 9cda85aa03..c1106a0b23 100644 --- a/pid_controller/package.xml +++ b/pid_controller/package.xml @@ -14,6 +14,7 @@ generate_parameter_library angles + backward_ros control_msgs control_toolbox controller_interface diff --git a/pid_controller/src/pid_controller.cpp b/pid_controller/src/pid_controller.cpp index 19cebbde4e..b76926d5a0 100644 --- a/pid_controller/src/pid_controller.cpp +++ b/pid_controller/src/pid_controller.cpp @@ -26,6 +26,9 @@ #include "control_msgs/msg/single_dof_state.hpp" #include "controller_interface/helpers.hpp" +#include "rclcpp/rclcpp.hpp" +#include "rclcpp/version.h" + namespace { // utility diff --git a/tricycle_steering_controller/package.xml b/tricycle_steering_controller/package.xml index bed6e451fa..991aca2c05 100644 --- a/tricycle_steering_controller/package.xml +++ b/tricycle_steering_controller/package.xml @@ -18,6 +18,7 @@ generate_parameter_library + backward_ros control_msgs controller_interface hardware_interface From 3520e850feec4df94435ad27bd1ef92197f103f2 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Fri, 22 Mar 2024 12:26:17 +0000 Subject: [PATCH 235/238] Update changelogs --- ackermann_steering_controller/CHANGELOG.rst | 6 ++++++ admittance_controller/CHANGELOG.rst | 5 +++++ bicycle_steering_controller/CHANGELOG.rst | 6 ++++++ diff_drive_controller/CHANGELOG.rst | 5 +++++ effort_controllers/CHANGELOG.rst | 3 +++ force_torque_sensor_broadcaster/CHANGELOG.rst | 3 +++ forward_command_controller/CHANGELOG.rst | 3 +++ gripper_controllers/CHANGELOG.rst | 5 +++++ imu_sensor_broadcaster/CHANGELOG.rst | 3 +++ joint_state_broadcaster/CHANGELOG.rst | 5 +++++ joint_trajectory_controller/CHANGELOG.rst | 8 ++++++++ pid_controller/CHANGELOG.rst | 7 +++++++ position_controllers/CHANGELOG.rst | 3 +++ range_sensor_broadcaster/CHANGELOG.rst | 5 +++++ ros2_controllers/CHANGELOG.rst | 3 +++ ros2_controllers_test_nodes/CHANGELOG.rst | 3 +++ rqt_joint_trajectory_controller/CHANGELOG.rst | 5 +++++ steering_controllers_library/CHANGELOG.rst | 6 ++++++ tricycle_controller/CHANGELOG.rst | 6 ++++++ tricycle_steering_controller/CHANGELOG.rst | 6 ++++++ velocity_controllers/CHANGELOG.rst | 3 +++ 21 files changed, 99 insertions(+) diff --git a/ackermann_steering_controller/CHANGELOG.rst b/ackermann_steering_controller/CHANGELOG.rst index 3b77b7b78f..1ea0329f26 100644 --- a/ackermann_steering_controller/CHANGELOG.rst +++ b/ackermann_steering_controller/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package ackermann_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Fix pid_controller build on ROS 2 Rolling on Ubuntu 24.04 (`#1084 `_) +* Fix usage of visibility macros (`#1039 `_) +* Contributors: Chris Lalancette, Silvio Traversaro + 4.6.0 (2024-02-12) ------------------ * Add test_depend on `hardware_interface_testing` (`#1018 `_) diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index 65db88f462..a611753f0f 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Use CMake target for eigen (`#1058 `_) +* Contributors: Christoph Fröhlich + 4.6.0 (2024-02-12) ------------------ * Add test_depend on `hardware_interface_testing` (`#1018 `_) diff --git a/bicycle_steering_controller/CHANGELOG.rst b/bicycle_steering_controller/CHANGELOG.rst index 16192d9f8a..09cd7e7c6e 100644 --- a/bicycle_steering_controller/CHANGELOG.rst +++ b/bicycle_steering_controller/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package bicycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Fix pid_controller build on ROS 2 Rolling on Ubuntu 24.04 (`#1084 `_) +* Fix usage of visibility macros (`#1039 `_) +* Contributors: Chris Lalancette, Silvio Traversaro + 4.6.0 (2024-02-12) ------------------ * Add test_depend on `hardware_interface_testing` (`#1018 `_) diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index 1ec4329fca..63e4226d4f 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* added conditioning to have rolling tags compilable in older versions (`#1071 `_) +* Contributors: Sai Kishor Kothakota + 4.6.0 (2024-02-12) ------------------ * Add test_depend on `hardware_interface_testing` also for diff_drive (`#1021 `_) diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index ac47c3c2b3..e9cd8953da 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.6.0 (2024-02-12) ------------------ * Add test_depend on `hardware_interface_testing` (`#1018 `_) diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index c61f166b8e..0bae0e0cbc 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.6.0 (2024-02-12) ------------------ * Add test_depend on `hardware_interface_testing` (`#1018 `_) diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index 54a428ec3f..07f48d32e4 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.6.0 (2024-02-12) ------------------ * Add test_depend on `hardware_interface_testing` (`#1018 `_) diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index 76ea9418d2..9509b8858e 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Fix usage of visibility macros (`#1039 `_) +* Contributors: Silvio Traversaro + 4.6.0 (2024-02-12) ------------------ * Add test_depend on `hardware_interface_testing` (`#1018 `_) diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index d906fb897f..28e00cdfa2 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.6.0 (2024-02-12) ------------------ * Add test_depend on `hardware_interface_testing` (`#1018 `_) diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index 1444f5f8ab..2580a0f0e6 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* added conditioning to have rolling tags compilable in older versions (`#1071 `_) +* Contributors: Sai Kishor Kothakota + 4.6.0 (2024-02-12) ------------------ * Add test_depend on `hardware_interface_testing` (`#1018 `_) diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index 17b26ad551..2c0467fefb 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,14 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Remove action_msg dependency (`#1077 `_) +* Bump version of pre-commit hooks (`#1073 `_) +* Added conditioning to have rolling tags compilable in older versions (`#1071 `_) +* Parse URDF for continuous joints (`#949 `_) +* Contributors: Christoph Fröhlich, Sai Kishor Kothakota, github-actions[bot] + 4.6.0 (2024-02-12) ------------------ * Fix usage of M_PI on Windows (`#1036 `_) diff --git a/pid_controller/CHANGELOG.rst b/pid_controller/CHANGELOG.rst index 7d5d248576..7948c7f915 100644 --- a/pid_controller/CHANGELOG.rst +++ b/pid_controller/CHANGELOG.rst @@ -2,6 +2,13 @@ Changelog for package pid_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Fix pid_controller build on ROS 2 Rolling on Ubuntu 24.04 (`#1084 `_) +* Added conditioning to have rolling tags compilable in older versions (`#1071 `_) +* Fix usage of visibility macros (`#1039 `_) +* Contributors: Chris Lalancette, Sai Kishor Kothakota, Silvio Traversaro + 4.6.0 (2024-02-12) ------------------ * Add test_depend on `hardware_interface_testing` (`#1018 `_) diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index 6c55f59602..eb02c1f499 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.6.0 (2024-02-12) ------------------ * Add test_depend on `hardware_interface_testing` (`#1018 `_) diff --git a/range_sensor_broadcaster/CHANGELOG.rst b/range_sensor_broadcaster/CHANGELOG.rst index 62c87c8717..7d5dedab61 100644 --- a/range_sensor_broadcaster/CHANGELOG.rst +++ b/range_sensor_broadcaster/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package range_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* added conditioning to have rolling tags compilable in older versions (`#1071 `_) +* Contributors: Sai Kishor Kothakota + 4.6.0 (2024-02-12) ------------------ * Add test_depend on `hardware_interface_testing` (`#1018 `_) diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index fc8ca62020..bcb3d11572 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.6.0 (2024-02-12) ------------------ diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index 41a20f3841..a26663e26e 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.6.0 (2024-02-12) ------------------ diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index cd4ae0809e..cc6f7d1313 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* [CI] Code coverage + pre-commit (`#1057 `_) +* Contributors: Christoph Fröhlich + 4.6.0 (2024-02-12) ------------------ diff --git a/steering_controllers_library/CHANGELOG.rst b/steering_controllers_library/CHANGELOG.rst index e8288f1955..f05e310412 100644 --- a/steering_controllers_library/CHANGELOG.rst +++ b/steering_controllers_library/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package steering_controllers_library ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* added conditioning to have rolling tags compilable in older versions (`#1071 `_) +* Fix usage of visibility macros (`#1039 `_) +* Contributors: Sai Kishor Kothakota, Silvio Traversaro + 4.6.0 (2024-02-12) ------------------ * Fix usage of M_PI on Windows (`#1036 `_) diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index cf2a599b20..c37f7537a7 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* added conditioning to have rolling tags compilable in older versions (`#1071 `_) +* Fix usage of visibility macros (`#1039 `_) +* Contributors: Sai Kishor Kothakota, Silvio Traversaro + 4.6.0 (2024-02-12) ------------------ * Fix usage of M_PI on Windows (`#1036 `_) diff --git a/tricycle_steering_controller/CHANGELOG.rst b/tricycle_steering_controller/CHANGELOG.rst index 718df4e014..35dd1b27df 100644 --- a/tricycle_steering_controller/CHANGELOG.rst +++ b/tricycle_steering_controller/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package tricycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Fix pid_controller build on ROS 2 Rolling on Ubuntu 24.04 (`#1084 `_) +* Fix usage of visibility macros (`#1039 `_) +* Contributors: Chris Lalancette, Silvio Traversaro + 4.6.0 (2024-02-12) ------------------ * Add test_depend on `hardware_interface_testing` (`#1018 `_) diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index e6689b23a8..8c8970b704 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 4.6.0 (2024-02-12) ------------------ * Add test_depend on `hardware_interface_testing` (`#1018 `_) From d77a0011f200da524e1a19a2f4b3a4c0ff688809 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Fri, 22 Mar 2024 12:26:44 +0000 Subject: [PATCH 236/238] 4.7.0 --- ackermann_steering_controller/CHANGELOG.rst | 4 ++-- ackermann_steering_controller/package.xml | 2 +- admittance_controller/CHANGELOG.rst | 4 ++-- admittance_controller/package.xml | 2 +- bicycle_steering_controller/CHANGELOG.rst | 4 ++-- bicycle_steering_controller/package.xml | 2 +- diff_drive_controller/CHANGELOG.rst | 4 ++-- diff_drive_controller/package.xml | 2 +- effort_controllers/CHANGELOG.rst | 4 ++-- effort_controllers/package.xml | 2 +- force_torque_sensor_broadcaster/CHANGELOG.rst | 4 ++-- force_torque_sensor_broadcaster/package.xml | 2 +- forward_command_controller/CHANGELOG.rst | 4 ++-- forward_command_controller/package.xml | 2 +- gripper_controllers/CHANGELOG.rst | 4 ++-- gripper_controllers/package.xml | 2 +- imu_sensor_broadcaster/CHANGELOG.rst | 4 ++-- imu_sensor_broadcaster/package.xml | 2 +- joint_state_broadcaster/CHANGELOG.rst | 4 ++-- joint_state_broadcaster/package.xml | 2 +- joint_trajectory_controller/CHANGELOG.rst | 4 ++-- joint_trajectory_controller/package.xml | 2 +- pid_controller/CHANGELOG.rst | 4 ++-- pid_controller/package.xml | 2 +- position_controllers/CHANGELOG.rst | 4 ++-- position_controllers/package.xml | 2 +- range_sensor_broadcaster/CHANGELOG.rst | 4 ++-- range_sensor_broadcaster/package.xml | 2 +- ros2_controllers/CHANGELOG.rst | 4 ++-- ros2_controllers/package.xml | 2 +- ros2_controllers_test_nodes/CHANGELOG.rst | 4 ++-- ros2_controllers_test_nodes/package.xml | 2 +- ros2_controllers_test_nodes/setup.py | 2 +- rqt_joint_trajectory_controller/CHANGELOG.rst | 4 ++-- rqt_joint_trajectory_controller/package.xml | 2 +- rqt_joint_trajectory_controller/setup.py | 2 +- steering_controllers_library/CHANGELOG.rst | 4 ++-- steering_controllers_library/package.xml | 2 +- tricycle_controller/CHANGELOG.rst | 4 ++-- tricycle_controller/package.xml | 2 +- tricycle_steering_controller/CHANGELOG.rst | 4 ++-- tricycle_steering_controller/package.xml | 2 +- velocity_controllers/CHANGELOG.rst | 4 ++-- velocity_controllers/package.xml | 2 +- 44 files changed, 65 insertions(+), 65 deletions(-) diff --git a/ackermann_steering_controller/CHANGELOG.rst b/ackermann_steering_controller/CHANGELOG.rst index 1ea0329f26..f14bd8ba01 100644 --- a/ackermann_steering_controller/CHANGELOG.rst +++ b/ackermann_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ackermann_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.7.0 (2024-03-22) +------------------ * Fix pid_controller build on ROS 2 Rolling on Ubuntu 24.04 (`#1084 `_) * Fix usage of visibility macros (`#1039 `_) * Contributors: Chris Lalancette, Silvio Traversaro diff --git a/ackermann_steering_controller/package.xml b/ackermann_steering_controller/package.xml index a3183af262..771494e67f 100644 --- a/ackermann_steering_controller/package.xml +++ b/ackermann_steering_controller/package.xml @@ -2,7 +2,7 @@ ackermann_steering_controller - 4.6.0 + 4.7.0 Steering controller for Ackermann kinematics. Rear fixed wheels are powering the vehicle and front wheels are steering it. Apache License 2.0 Bence Magyar diff --git a/admittance_controller/CHANGELOG.rst b/admittance_controller/CHANGELOG.rst index a611753f0f..7dd8e0b321 100644 --- a/admittance_controller/CHANGELOG.rst +++ b/admittance_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package admittance_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.7.0 (2024-03-22) +------------------ * Use CMake target for eigen (`#1058 `_) * Contributors: Christoph Fröhlich diff --git a/admittance_controller/package.xml b/admittance_controller/package.xml index 2c50dde2e7..e9779eda4d 100644 --- a/admittance_controller/package.xml +++ b/admittance_controller/package.xml @@ -2,7 +2,7 @@ admittance_controller - 4.6.0 + 4.7.0 Implementation of admittance controllers for different input and output interface. Denis Štogl Bence Magyar diff --git a/bicycle_steering_controller/CHANGELOG.rst b/bicycle_steering_controller/CHANGELOG.rst index 09cd7e7c6e..de67c5bc72 100644 --- a/bicycle_steering_controller/CHANGELOG.rst +++ b/bicycle_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package bicycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.7.0 (2024-03-22) +------------------ * Fix pid_controller build on ROS 2 Rolling on Ubuntu 24.04 (`#1084 `_) * Fix usage of visibility macros (`#1039 `_) * Contributors: Chris Lalancette, Silvio Traversaro diff --git a/bicycle_steering_controller/package.xml b/bicycle_steering_controller/package.xml index 6507700a5d..97c12290df 100644 --- a/bicycle_steering_controller/package.xml +++ b/bicycle_steering_controller/package.xml @@ -2,7 +2,7 @@ bicycle_steering_controller - 4.6.0 + 4.7.0 Steering controller with bicycle kinematics. Rear fixed wheel is powering the vehicle and front wheel is steering. Apache License 2.0 Bence Magyar diff --git a/diff_drive_controller/CHANGELOG.rst b/diff_drive_controller/CHANGELOG.rst index 63e4226d4f..ae38961d10 100644 --- a/diff_drive_controller/CHANGELOG.rst +++ b/diff_drive_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package diff_drive_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.7.0 (2024-03-22) +------------------ * added conditioning to have rolling tags compilable in older versions (`#1071 `_) * Contributors: Sai Kishor Kothakota diff --git a/diff_drive_controller/package.xml b/diff_drive_controller/package.xml index b0e818dd50..5252803de9 100644 --- a/diff_drive_controller/package.xml +++ b/diff_drive_controller/package.xml @@ -1,7 +1,7 @@ diff_drive_controller - 4.6.0 + 4.7.0 Controller for a differential drive mobile base. Bence Magyar Jordan Palacios diff --git a/effort_controllers/CHANGELOG.rst b/effort_controllers/CHANGELOG.rst index e9cd8953da..306cc24ff6 100644 --- a/effort_controllers/CHANGELOG.rst +++ b/effort_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package effort_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.7.0 (2024-03-22) +------------------ 4.6.0 (2024-02-12) ------------------ diff --git a/effort_controllers/package.xml b/effort_controllers/package.xml index 52165f6ec1..9acfdd2ddc 100644 --- a/effort_controllers/package.xml +++ b/effort_controllers/package.xml @@ -1,7 +1,7 @@ effort_controllers - 4.6.0 + 4.7.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/force_torque_sensor_broadcaster/CHANGELOG.rst b/force_torque_sensor_broadcaster/CHANGELOG.rst index 0bae0e0cbc..f4cbbe1bec 100644 --- a/force_torque_sensor_broadcaster/CHANGELOG.rst +++ b/force_torque_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package force_torque_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.7.0 (2024-03-22) +------------------ 4.6.0 (2024-02-12) ------------------ diff --git a/force_torque_sensor_broadcaster/package.xml b/force_torque_sensor_broadcaster/package.xml index 178a90d5cf..dee37dd565 100644 --- a/force_torque_sensor_broadcaster/package.xml +++ b/force_torque_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ force_torque_sensor_broadcaster - 4.6.0 + 4.7.0 Controller to publish state of force-torque sensors. Bence Magyar Denis Štogl diff --git a/forward_command_controller/CHANGELOG.rst b/forward_command_controller/CHANGELOG.rst index 07f48d32e4..607ec25f23 100644 --- a/forward_command_controller/CHANGELOG.rst +++ b/forward_command_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package forward_command_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.7.0 (2024-03-22) +------------------ 4.6.0 (2024-02-12) ------------------ diff --git a/forward_command_controller/package.xml b/forward_command_controller/package.xml index 9b6c2559f4..1aed0d3c83 100644 --- a/forward_command_controller/package.xml +++ b/forward_command_controller/package.xml @@ -1,7 +1,7 @@ forward_command_controller - 4.6.0 + 4.7.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/gripper_controllers/CHANGELOG.rst b/gripper_controllers/CHANGELOG.rst index 9509b8858e..bb4d699bd0 100644 --- a/gripper_controllers/CHANGELOG.rst +++ b/gripper_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package gripper_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.7.0 (2024-03-22) +------------------ * Fix usage of visibility macros (`#1039 `_) * Contributors: Silvio Traversaro diff --git a/gripper_controllers/package.xml b/gripper_controllers/package.xml index a6b83b43ec..7183bc7ebd 100644 --- a/gripper_controllers/package.xml +++ b/gripper_controllers/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> gripper_controllers - 4.6.0 + 4.7.0 The gripper_controllers package Bence Magyar diff --git a/imu_sensor_broadcaster/CHANGELOG.rst b/imu_sensor_broadcaster/CHANGELOG.rst index 28e00cdfa2..6a9df05038 100644 --- a/imu_sensor_broadcaster/CHANGELOG.rst +++ b/imu_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package imu_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.7.0 (2024-03-22) +------------------ 4.6.0 (2024-02-12) ------------------ diff --git a/imu_sensor_broadcaster/package.xml b/imu_sensor_broadcaster/package.xml index 5a4ca12e87..3817b7a536 100644 --- a/imu_sensor_broadcaster/package.xml +++ b/imu_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ imu_sensor_broadcaster - 4.6.0 + 4.7.0 Controller to publish readings of IMU sensors. Bence Magyar Denis Štogl diff --git a/joint_state_broadcaster/CHANGELOG.rst b/joint_state_broadcaster/CHANGELOG.rst index 2580a0f0e6..9762bcb55c 100644 --- a/joint_state_broadcaster/CHANGELOG.rst +++ b/joint_state_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_state_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.7.0 (2024-03-22) +------------------ * added conditioning to have rolling tags compilable in older versions (`#1071 `_) * Contributors: Sai Kishor Kothakota diff --git a/joint_state_broadcaster/package.xml b/joint_state_broadcaster/package.xml index 0bf3db58dd..14f226450e 100644 --- a/joint_state_broadcaster/package.xml +++ b/joint_state_broadcaster/package.xml @@ -1,7 +1,7 @@ joint_state_broadcaster - 4.6.0 + 4.7.0 Broadcaster to publish joint state Bence Magyar Denis Stogl diff --git a/joint_trajectory_controller/CHANGELOG.rst b/joint_trajectory_controller/CHANGELOG.rst index 2c0467fefb..d008380af9 100644 --- a/joint_trajectory_controller/CHANGELOG.rst +++ b/joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.7.0 (2024-03-22) +------------------ * Remove action_msg dependency (`#1077 `_) * Bump version of pre-commit hooks (`#1073 `_) * Added conditioning to have rolling tags compilable in older versions (`#1071 `_) diff --git a/joint_trajectory_controller/package.xml b/joint_trajectory_controller/package.xml index 8457c02aeb..a44d55a731 100644 --- a/joint_trajectory_controller/package.xml +++ b/joint_trajectory_controller/package.xml @@ -1,7 +1,7 @@ joint_trajectory_controller - 4.6.0 + 4.7.0 Controller for executing joint-space trajectories on a group of joints Bence Magyar Dr. Denis Štogl diff --git a/pid_controller/CHANGELOG.rst b/pid_controller/CHANGELOG.rst index 7948c7f915..82e631a75c 100644 --- a/pid_controller/CHANGELOG.rst +++ b/pid_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package pid_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.7.0 (2024-03-22) +------------------ * Fix pid_controller build on ROS 2 Rolling on Ubuntu 24.04 (`#1084 `_) * Added conditioning to have rolling tags compilable in older versions (`#1071 `_) * Fix usage of visibility macros (`#1039 `_) diff --git a/pid_controller/package.xml b/pid_controller/package.xml index c1106a0b23..151862dc11 100644 --- a/pid_controller/package.xml +++ b/pid_controller/package.xml @@ -2,7 +2,7 @@ pid_controller - 4.6.0 + 4.7.0 Controller based on PID implememenation from control_toolbox package. Bence Magyar Denis Štogl diff --git a/position_controllers/CHANGELOG.rst b/position_controllers/CHANGELOG.rst index eb02c1f499..cdb4165691 100644 --- a/position_controllers/CHANGELOG.rst +++ b/position_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package position_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.7.0 (2024-03-22) +------------------ 4.6.0 (2024-02-12) ------------------ diff --git a/position_controllers/package.xml b/position_controllers/package.xml index 13e80f4d99..b56e3e154a 100644 --- a/position_controllers/package.xml +++ b/position_controllers/package.xml @@ -1,7 +1,7 @@ position_controllers - 4.6.0 + 4.7.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios diff --git a/range_sensor_broadcaster/CHANGELOG.rst b/range_sensor_broadcaster/CHANGELOG.rst index 7d5dedab61..89365b7754 100644 --- a/range_sensor_broadcaster/CHANGELOG.rst +++ b/range_sensor_broadcaster/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package range_sensor_broadcaster ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.7.0 (2024-03-22) +------------------ * added conditioning to have rolling tags compilable in older versions (`#1071 `_) * Contributors: Sai Kishor Kothakota diff --git a/range_sensor_broadcaster/package.xml b/range_sensor_broadcaster/package.xml index 3bbe1d2130..4cdae222a5 100644 --- a/range_sensor_broadcaster/package.xml +++ b/range_sensor_broadcaster/package.xml @@ -2,7 +2,7 @@ range_sensor_broadcaster - 4.6.0 + 4.7.0 Controller to publish readings of Range sensors. Bence Magyar Florent Chretien diff --git a/ros2_controllers/CHANGELOG.rst b/ros2_controllers/CHANGELOG.rst index bcb3d11572..2d7e5f08de 100644 --- a/ros2_controllers/CHANGELOG.rst +++ b/ros2_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.7.0 (2024-03-22) +------------------ 4.6.0 (2024-02-12) ------------------ diff --git a/ros2_controllers/package.xml b/ros2_controllers/package.xml index 10ae5427e9..fc2e40fb8a 100644 --- a/ros2_controllers/package.xml +++ b/ros2_controllers/package.xml @@ -1,7 +1,7 @@ ros2_controllers - 4.6.0 + 4.7.0 Metapackage for ROS2 controllers related packages Bence Magyar Jordan Palacios diff --git a/ros2_controllers_test_nodes/CHANGELOG.rst b/ros2_controllers_test_nodes/CHANGELOG.rst index a26663e26e..a77c2635e8 100644 --- a/ros2_controllers_test_nodes/CHANGELOG.rst +++ b/ros2_controllers_test_nodes/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_controllers_test_nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.7.0 (2024-03-22) +------------------ 4.6.0 (2024-02-12) ------------------ diff --git a/ros2_controllers_test_nodes/package.xml b/ros2_controllers_test_nodes/package.xml index fb5b3d8bcf..fef330a0c7 100644 --- a/ros2_controllers_test_nodes/package.xml +++ b/ros2_controllers_test_nodes/package.xml @@ -2,7 +2,7 @@ ros2_controllers_test_nodes - 4.6.0 + 4.7.0 Demo nodes for showing and testing functionalities of the ros2_control framework. Denis Štogl diff --git a/ros2_controllers_test_nodes/setup.py b/ros2_controllers_test_nodes/setup.py index 9219fea906..273957f688 100644 --- a/ros2_controllers_test_nodes/setup.py +++ b/ros2_controllers_test_nodes/setup.py @@ -20,7 +20,7 @@ setup( name=package_name, - version="4.6.0", + version="4.7.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/rqt_joint_trajectory_controller/CHANGELOG.rst b/rqt_joint_trajectory_controller/CHANGELOG.rst index cc6f7d1313..416c399cc6 100644 --- a/rqt_joint_trajectory_controller/CHANGELOG.rst +++ b/rqt_joint_trajectory_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package rqt_joint_trajectory_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.7.0 (2024-03-22) +------------------ * [CI] Code coverage + pre-commit (`#1057 `_) * Contributors: Christoph Fröhlich diff --git a/rqt_joint_trajectory_controller/package.xml b/rqt_joint_trajectory_controller/package.xml index 107d50681c..c7ec8d4666 100644 --- a/rqt_joint_trajectory_controller/package.xml +++ b/rqt_joint_trajectory_controller/package.xml @@ -4,7 +4,7 @@ schematypens="http://www.w3.org/2001/XMLSchema"?> rqt_joint_trajectory_controller - 4.6.0 + 4.7.0 Graphical frontend for interacting with joint_trajectory_controller instances. Bence Magyar diff --git a/rqt_joint_trajectory_controller/setup.py b/rqt_joint_trajectory_controller/setup.py index adb3f94668..0339f47b5a 100644 --- a/rqt_joint_trajectory_controller/setup.py +++ b/rqt_joint_trajectory_controller/setup.py @@ -21,7 +21,7 @@ setup( name=package_name, - version="4.6.0", + version="4.7.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/steering_controllers_library/CHANGELOG.rst b/steering_controllers_library/CHANGELOG.rst index f05e310412..43e3cc30da 100644 --- a/steering_controllers_library/CHANGELOG.rst +++ b/steering_controllers_library/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package steering_controllers_library ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.7.0 (2024-03-22) +------------------ * added conditioning to have rolling tags compilable in older versions (`#1071 `_) * Fix usage of visibility macros (`#1039 `_) * Contributors: Sai Kishor Kothakota, Silvio Traversaro diff --git a/steering_controllers_library/package.xml b/steering_controllers_library/package.xml index 8212f58d91..97d03dc809 100644 --- a/steering_controllers_library/package.xml +++ b/steering_controllers_library/package.xml @@ -2,7 +2,7 @@ steering_controllers_library - 4.6.0 + 4.7.0 Package for steering robot configurations including odometry and interfaces. Apache License 2.0 Bence Magyar diff --git a/tricycle_controller/CHANGELOG.rst b/tricycle_controller/CHANGELOG.rst index c37f7537a7..150a575260 100644 --- a/tricycle_controller/CHANGELOG.rst +++ b/tricycle_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package tricycle_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.7.0 (2024-03-22) +------------------ * added conditioning to have rolling tags compilable in older versions (`#1071 `_) * Fix usage of visibility macros (`#1039 `_) * Contributors: Sai Kishor Kothakota, Silvio Traversaro diff --git a/tricycle_controller/package.xml b/tricycle_controller/package.xml index 04995732f2..900f906a11 100644 --- a/tricycle_controller/package.xml +++ b/tricycle_controller/package.xml @@ -2,7 +2,7 @@ tricycle_controller - 4.6.0 + 4.7.0 Controller for a tricycle drive mobile base Bence Magyar Tony Najjar diff --git a/tricycle_steering_controller/CHANGELOG.rst b/tricycle_steering_controller/CHANGELOG.rst index 35dd1b27df..04e3bf43fe 100644 --- a/tricycle_steering_controller/CHANGELOG.rst +++ b/tricycle_steering_controller/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package tricycle_steering_controller ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.7.0 (2024-03-22) +------------------ * Fix pid_controller build on ROS 2 Rolling on Ubuntu 24.04 (`#1084 `_) * Fix usage of visibility macros (`#1039 `_) * Contributors: Chris Lalancette, Silvio Traversaro diff --git a/tricycle_steering_controller/package.xml b/tricycle_steering_controller/package.xml index 991aca2c05..ccb973be40 100644 --- a/tricycle_steering_controller/package.xml +++ b/tricycle_steering_controller/package.xml @@ -2,7 +2,7 @@ tricycle_steering_controller - 4.6.0 + 4.7.0 Steering controller with tricycle kinematics. Rear fixed wheels are powering the vehicle and front wheel is steering. Apache License 2.0 Bence Magyar diff --git a/velocity_controllers/CHANGELOG.rst b/velocity_controllers/CHANGELOG.rst index 8c8970b704..e15ecc94e7 100644 --- a/velocity_controllers/CHANGELOG.rst +++ b/velocity_controllers/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package velocity_controllers ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +4.7.0 (2024-03-22) +------------------ 4.6.0 (2024-02-12) ------------------ diff --git a/velocity_controllers/package.xml b/velocity_controllers/package.xml index ff403e178f..a6c28a3cd1 100644 --- a/velocity_controllers/package.xml +++ b/velocity_controllers/package.xml @@ -1,7 +1,7 @@ velocity_controllers - 4.6.0 + 4.7.0 Generic controller for forwarding commands. Bence Magyar Jordan Palacios From 689efe716fd97f4c79638689ececc65fe175b418 Mon Sep 17 00:00:00 2001 From: Sai Kishor Kothakota Date: Wed, 27 Mar 2024 19:23:54 +0100 Subject: [PATCH 237/238] add missing compiler definitions of RCPPUTILS_VERSION (#1089) --- ackermann_steering_controller/CMakeLists.txt | 2 ++ bicycle_steering_controller/CMakeLists.txt | 2 ++ diff_drive_controller/CMakeLists.txt | 2 ++ steering_controllers_library/CMakeLists.txt | 2 ++ tricycle_controller/CMakeLists.txt | 2 ++ tricycle_steering_controller/CMakeLists.txt | 2 ++ 6 files changed, 12 insertions(+) diff --git a/ackermann_steering_controller/CMakeLists.txt b/ackermann_steering_controller/CMakeLists.txt index 71d0cf5f80..a34be3c672 100644 --- a/ackermann_steering_controller/CMakeLists.txt +++ b/ackermann_steering_controller/CMakeLists.txt @@ -24,6 +24,8 @@ find_package(backward_ros REQUIRED) foreach(Dependency IN ITEMS ${THIS_PACKAGE_INCLUDE_DEPENDS}) find_package(${Dependency} REQUIRED) endforeach() +add_compile_definitions(RCPPUTILS_VERSION_MAJOR=${rcpputils_VERSION_MAJOR}) +add_compile_definitions(RCPPUTILS_VERSION_MINOR=${rcpputils_VERSION_MINOR}) generate_parameter_library(ackermann_steering_controller_parameters src/ackermann_steering_controller.yaml diff --git a/bicycle_steering_controller/CMakeLists.txt b/bicycle_steering_controller/CMakeLists.txt index 77d82ed874..6535a73260 100644 --- a/bicycle_steering_controller/CMakeLists.txt +++ b/bicycle_steering_controller/CMakeLists.txt @@ -24,6 +24,8 @@ find_package(backward_ros REQUIRED) foreach(Dependency IN ITEMS ${THIS_PACKAGE_INCLUDE_DEPENDS}) find_package(${Dependency} REQUIRED) endforeach() +add_compile_definitions(RCPPUTILS_VERSION_MAJOR=${rcpputils_VERSION_MAJOR}) +add_compile_definitions(RCPPUTILS_VERSION_MINOR=${rcpputils_VERSION_MINOR}) generate_parameter_library(bicycle_steering_controller_parameters src/bicycle_steering_controller.yaml diff --git a/diff_drive_controller/CMakeLists.txt b/diff_drive_controller/CMakeLists.txt index d67815b5e0..70a54e302c 100644 --- a/diff_drive_controller/CMakeLists.txt +++ b/diff_drive_controller/CMakeLists.txt @@ -25,6 +25,8 @@ find_package(backward_ros REQUIRED) foreach(Dependency IN ITEMS ${THIS_PACKAGE_INCLUDE_DEPENDS}) find_package(${Dependency} REQUIRED) endforeach() +add_compile_definitions(RCPPUTILS_VERSION_MAJOR=${rcpputils_VERSION_MAJOR}) +add_compile_definitions(RCPPUTILS_VERSION_MINOR=${rcpputils_VERSION_MINOR}) generate_parameter_library(diff_drive_controller_parameters src/diff_drive_controller_parameter.yaml diff --git a/steering_controllers_library/CMakeLists.txt b/steering_controllers_library/CMakeLists.txt index b79236e23e..e2bfdbab71 100644 --- a/steering_controllers_library/CMakeLists.txt +++ b/steering_controllers_library/CMakeLists.txt @@ -30,6 +30,8 @@ find_package(backward_ros REQUIRED) foreach(Dependency IN ITEMS ${THIS_PACKAGE_INCLUDE_DEPENDS}) find_package(${Dependency} REQUIRED) endforeach() +add_compile_definitions(RCPPUTILS_VERSION_MAJOR=${rcpputils_VERSION_MAJOR}) +add_compile_definitions(RCPPUTILS_VERSION_MINOR=${rcpputils_VERSION_MINOR}) generate_parameter_library(steering_controllers_library_parameters src/steering_controllers_library.yaml diff --git a/tricycle_controller/CMakeLists.txt b/tricycle_controller/CMakeLists.txt index ea1c4db3c1..e264c1f258 100644 --- a/tricycle_controller/CMakeLists.txt +++ b/tricycle_controller/CMakeLists.txt @@ -29,6 +29,8 @@ find_package(backward_ros REQUIRED) foreach(Dependency IN ITEMS ${THIS_PACKAGE_INCLUDE_DEPENDS}) find_package(${Dependency} REQUIRED) endforeach() +add_compile_definitions(RCPPUTILS_VERSION_MAJOR=${rcpputils_VERSION_MAJOR}) +add_compile_definitions(RCPPUTILS_VERSION_MINOR=${rcpputils_VERSION_MINOR}) generate_parameter_library(tricycle_controller_parameters src/tricycle_controller_parameter.yaml diff --git a/tricycle_steering_controller/CMakeLists.txt b/tricycle_steering_controller/CMakeLists.txt index 21604df0c4..92c2782092 100644 --- a/tricycle_steering_controller/CMakeLists.txt +++ b/tricycle_steering_controller/CMakeLists.txt @@ -24,6 +24,8 @@ find_package(backward_ros REQUIRED) foreach(Dependency IN ITEMS ${THIS_PACKAGE_INCLUDE_DEPENDS}) find_package(${Dependency} REQUIRED) endforeach() +add_compile_definitions(RCPPUTILS_VERSION_MAJOR=${rcpputils_VERSION_MAJOR}) +add_compile_definitions(RCPPUTILS_VERSION_MINOR=${rcpputils_VERSION_MINOR}) generate_parameter_library(tricycle_steering_controller_parameters src/tricycle_steering_controller.yaml From 9e97c00496c239bf4961dc043a3f461aae9b23b8 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Tue, 9 Apr 2024 11:39:54 +0200 Subject: [PATCH 238/238] [JTC] Remove unused test code (#1095) --- .../test/test_trajectory_controller.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/joint_trajectory_controller/test/test_trajectory_controller.cpp b/joint_trajectory_controller/test/test_trajectory_controller.cpp index f5e9cb7260..0b00bd5380 100644 --- a/joint_trajectory_controller/test/test_trajectory_controller.cpp +++ b/joint_trajectory_controller/test/test_trajectory_controller.cpp @@ -51,8 +51,6 @@ using lifecycle_msgs::msg::State; using test_trajectory_controllers::TrajectoryControllerTest; using test_trajectory_controllers::TrajectoryControllerTestParameterized; -void spin(rclcpp::executors::MultiThreadedExecutor * exe) { exe->spin(); } - TEST_P(TrajectoryControllerTestParameterized, configure_state_ignores_commands) { rclcpp::executors::MultiThreadedExecutor executor; @@ -60,8 +58,6 @@ TEST_P(TrajectoryControllerTestParameterized, configure_state_ignores_commands) traj_controller_->get_node()->set_parameter( rclcpp::Parameter("allow_nonzero_velocity_at_trajectory_end", true)); - // const auto future_handle_ = std::async(std::launch::async, spin, &executor); - const auto state = traj_controller_->get_node()->configure(); ASSERT_EQ(state.id(), State::PRIMARY_STATE_INACTIVE);