From e12cea3919b735cca3cb5b86d7af8827bd92a571 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 May 2023 14:38:43 +0100 Subject: [PATCH 01/40] Bump ros-tooling/setup-ros from 0.6.1 to 0.6.2 (#1039) --- .github/workflows/ci-coverage-build.yml | 2 +- .github/workflows/ci-ros-lint.yml | 4 ++-- .github/workflows/reusable-ros-tooling-source-build.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-coverage-build.yml b/.github/workflows/ci-coverage-build.yml index 9c3a1378ee..1df5175f10 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 67d1b2c5e9..57fe01c1a4 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 @@ -36,7 +36,7 @@ jobs: linter: [cpplint] 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 5a715fd503..777d193c69 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 bdf7e4437328e1998f3a75e22f5cee978825fe75 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 29 May 2023 14:39:56 +0100 Subject: [PATCH 02/40] Bump actions/setup-python from 4.6.0 to 4.6.1 (#1040) --- .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 83fe361f4d..4cf7330f56 100644 --- a/.github/workflows/ci-format.yml +++ b/.github/workflows/ci-format.yml @@ -13,7 +13,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 0637782ea436decbe46a1a42d582bd60fe8d51ef Mon Sep 17 00:00:00 2001 From: Sai Kishor Kothakota Date: Tue, 30 May 2023 09:05:26 +0200 Subject: [PATCH 03/40] enable ReflowComments to also use ColumnLimit on comments (#1037) * enable ReflowComments to also use ColumnLimit on comments * apply the formatting changes of clang format : ReflowComments --------- Co-authored-by: Bence Magyar --- .clang-format | 2 +- .../chainable_controller_interface.hpp | 7 +- .../controller_interface_base.hpp | 19 ++- .../include/controller_interface/helpers.hpp | 26 +-- .../controller_manager/controller_manager.hpp | 13 +- .../hardware_interface/actuator_interface.hpp | 30 ++-- .../hardware_interface/component_parser.hpp | 8 +- .../hardware_interface/resource_manager.hpp | 5 +- .../hardware_interface/sensor_interface.hpp | 8 +- .../hardware_interface/system_interface.hpp | 30 ++-- hardware_interface/src/component_parser.cpp | 18 +-- .../test/test_components/test_actuator.cpp | 2 +- .../joint_limits/joint_limits_rosparam.hpp | 51 +++--- .../joint_limits_interface.hpp | 41 ++--- .../joint_limits_urdf.hpp | 4 +- .../differential_transmission.hpp | 50 +++--- .../four_bar_linkage_transmission.hpp | 151 +++++++++--------- .../simple_transmission.hpp | 37 +++-- .../transmission_interface/transmission.hpp | 42 ++--- 19 files changed, 289 insertions(+), 255 deletions(-) diff --git a/.clang-format b/.clang-format index 9c21e1e17c..698bda7da8 100644 --- a/.clang-format +++ b/.clang-format @@ -10,6 +10,6 @@ ConstructorInitializerIndentWidth: 0 ContinuationIndentWidth: 2 DerivePointerAlignment: false PointerAlignment: Middle -ReflowComments: false +ReflowComments: true IncludeBlocks: Preserve ... diff --git a/controller_interface/include/controller_interface/chainable_controller_interface.hpp b/controller_interface/include/controller_interface/chainable_controller_interface.hpp index 37b784011c..2bdccefdc5 100644 --- a/controller_interface/include/controller_interface/chainable_controller_interface.hpp +++ b/controller_interface/include/controller_interface/chainable_controller_interface.hpp @@ -41,7 +41,8 @@ class ChainableControllerInterface : public ControllerInterfaceBase virtual ~ChainableControllerInterface() = default; /** - * Control step update. Command interfaces are updated based on on reference inputs and current states. + * Control step update. Command interfaces are updated based on on reference inputs and current + * states. * **The method called in the (real-time) control loop.** * * \param[in] time The time at the start of this control loop iteration @@ -83,7 +84,9 @@ class ChainableControllerInterface : public ControllerInterfaceBase * * \param[in] flag marking a switch to or from chained mode. * - * \returns true if controller successfully switched between "chained" and "external" mode. \default returns true so the method don't have to be overridden if controller can always switch chained mode. + * \returns true if controller successfully switched between "chained" and "external" mode. + * \default returns true so the method don't have to be overridden if controller can always switch + * chained mode. */ virtual bool on_set_chained_mode(bool chained_mode); diff --git a/controller_interface/include/controller_interface/controller_interface_base.hpp b/controller_interface/include/controller_interface/controller_interface_base.hpp index fdaffac06f..05ee0c8830 100644 --- a/controller_interface/include/controller_interface/controller_interface_base.hpp +++ b/controller_interface/include/controller_interface/controller_interface_base.hpp @@ -74,15 +74,13 @@ class ControllerInterfaceBase : public rclcpp_lifecycle::node_interfaces::Lifecy /// Get configuration for controller's required command interfaces. /** - * Method used by the controller_manager to get the set of command interfaces used by the controller. - * Each controller can use individual method to determine interface names that in simples case - * have the following format: `/`. - * The method is called only in `inactive` or `active` state, i.e., `on_configure` has to be - * called first. - * The configuration is used to check if controller can be activated and to claim interfaces from - * hardware. - * The claimed interfaces are populated in the - * \ref ControllerInterfaceBase::command_interfaces_ "command_interfaces_" member. + * Method used by the controller_manager to get the set of command interfaces used by the + * controller. Each controller can use individual method to determine interface names that in + * simples case have the following format: `/`. The method is called only in + * `inactive` or `active` state, i.e., `on_configure` has to be called first. The configuration is + * used to check if controller can be activated and to claim interfaces from hardware. The claimed + * interfaces are populated in the \ref ControllerInterfaceBase::command_interfaces_ + * "command_interfaces_" member. * * \returns configuration of command interfaces. */ @@ -131,7 +129,8 @@ class ControllerInterfaceBase : public rclcpp_lifecycle::node_interfaces::Lifecy virtual CallbackReturn on_init() = 0; /** - * Control step update. Command interfaces are updated based on on reference inputs and current states. + * Control step update. Command interfaces are updated based on on reference inputs and current + * states. * **The method called in the (real-time) control loop.** * * \param[in] time The time at the start of this control loop iteration diff --git a/controller_interface/include/controller_interface/helpers.hpp b/controller_interface/include/controller_interface/helpers.hpp index 45b048fc72..b571751f55 100644 --- a/controller_interface/include/controller_interface/helpers.hpp +++ b/controller_interface/include/controller_interface/helpers.hpp @@ -23,19 +23,19 @@ namespace controller_interface { /// Reorder interfaces with references according to joint names or full interface names. /** - * Method to reorder and check if all expected interfaces are provided for the joint. - * Fill `ordered_interfaces` with references from `unordered_interfaces` in the same order as in - * `ordered_names`. - * - * \param[in] unordered_interfaces vector with loaned unordered state or command interfaces. - * \param[in] ordered_names vector with ordered names to order \p unordered_interfaces. - * The valued inputs are list of joint names or interface full names. - * If joint names are used for ordering, \p interface_type specifies valid interface. - * If full interface names are used for ordering, \p interface_type should be empty string (""). - * \param[in] interface_type used for ordering interfaces with respect to joint names. - * \param[out] ordered_interfaces vector with ordered interfaces. - * \return true if all interfaces or joints in \p ordered_names are found, otherwise false. - */ + * Method to reorder and check if all expected interfaces are provided for the joint. + * Fill `ordered_interfaces` with references from `unordered_interfaces` in the same order as in + * `ordered_names`. + * + * \param[in] unordered_interfaces vector with loaned unordered state or command interfaces. + * \param[in] ordered_names vector with ordered names to order \p unordered_interfaces. + * The valued inputs are list of joint names or interface full names. + * If joint names are used for ordering, \p interface_type specifies valid interface. + * If full interface names are used for ordering, \p interface_type should be empty string (""). + * \param[in] interface_type used for ordering interfaces with respect to joint names. + * \param[out] ordered_interfaces vector with ordered interfaces. + * \return true if all interfaces or joints in \p ordered_names are found, otherwise false. + */ template bool get_ordered_interfaces( std::vector & unordered_interfaces, const std::vector & ordered_names, diff --git a/controller_manager/include/controller_manager/controller_manager.hpp b/controller_manager/include/controller_manager/controller_manager.hpp index 537f0447be..582cbc5f24 100644 --- a/controller_manager/include/controller_manager/controller_manager.hpp +++ b/controller_manager/include/controller_manager/controller_manager.hpp @@ -318,8 +318,8 @@ class ControllerManager : public rclcpp::Node const std::string & command_interface); /** - * Clear request lists used when switching controllers. The lists are shared between "callback" and - * "control loop" threads. + * Clear request lists used when switching controllers. The lists are shared between "callback" + * and "control loop" threads. */ void clear_requests(); @@ -428,7 +428,8 @@ class ControllerManager : public rclcpp::Node * lists match and returns a reference to it * This referenced list can be modified safely until switch_updated_controller_list() * is called, at this point the RT thread may start using it at any time - * \param[in] guard Guard needed to make sure the caller is the only one accessing the unused by rt list + * \param[in] guard Guard needed to make sure the caller is the only one accessing the unused by + * rt list */ std::vector & get_unused_list( const std::lock_guard & guard); @@ -436,7 +437,8 @@ class ControllerManager : public rclcpp::Node /// get_updated_list Returns a const reference to the most updated list. /** * \warning May or may not being used by the realtime thread, read-only reference for safety - * \param[in] guard Guard needed to make sure the caller is the only one accessing the unused by rt list + * \param[in] guard Guard needed to make sure the caller is the only one accessing the unused by + * rt list */ const std::vector & get_updated_list( const std::lock_guard & guard) const; @@ -444,7 +446,8 @@ class ControllerManager : public rclcpp::Node /** * switch_updated_list Switches the "updated" and "outdated" lists, and waits * until the RT thread is using the new "updated" list. - * \param[in] guard Guard needed to make sure the caller is the only one accessing the unused by rt list + * \param[in] guard Guard needed to make sure the caller is the only one accessing the unused by + * rt list */ void switch_updated_list(const std::lock_guard & guard); diff --git a/hardware_interface/include/hardware_interface/actuator_interface.hpp b/hardware_interface/include/hardware_interface/actuator_interface.hpp index 64c81b0a34..abfd8eb45a 100644 --- a/hardware_interface/include/hardware_interface/actuator_interface.hpp +++ b/hardware_interface/include/hardware_interface/actuator_interface.hpp @@ -35,8 +35,9 @@ namespace hardware_interface /** * The typical examples are conveyors or motors. * - * Methods return values have type rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn - * with the following meaning: + * Methods return values have type + * rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn with the following + * meaning: * * \returns CallbackReturn::SUCCESS method execution was successful. * \returns CallbackReturn::FAILURE method execution has failed and and can be called again. @@ -46,7 +47,8 @@ namespace hardware_interface * The hardware ends after each method in a state with the following meaning: * * UNCONFIGURED (on_init, on_cleanup): - * Hardware is initialized but communication is not started and therefore no interface is available. + * Hardware is initialized but communication is not started and therefore no interface is + * available. * * INACTIVE (on_configure, on_deactivate): * Communication with the hardware is started and it is configured. @@ -126,12 +128,12 @@ class ActuatorInterface : public rclcpp_lifecycle::node_interfaces::LifecycleNod * * \note This is a non-realtime evaluation of whether a set of command interface claims are * possible, and call to start preparing data structures for the upcoming switch that will occur. - * \note All starting and stopping interface keys are passed to all components, so the function should - * return return_type::OK by default when given interface keys not relevant for this component. - * \param[in] start_interfaces vector of string identifiers for the command interfaces starting. - * \param[in] stop_interfaces vector of string identifiers for the command interfacs stopping. - * \return return_type::OK if the new command interface combination can be prepared, - * or if the interface key is not relevant to this system. Returns return_type::ERROR otherwise. + * \note All starting and stopping interface keys are passed to all components, so the function + * should return return_type::OK by default when given interface keys not relevant for this + * component. \param[in] start_interfaces vector of string identifiers for the command interfaces + * starting. \param[in] stop_interfaces vector of string identifiers for the command interfacs + * stopping. \return return_type::OK if the new command interface combination can be prepared, or + * if the interface key is not relevant to this system. Returns return_type::ERROR otherwise. */ virtual return_type prepare_command_mode_switch( const std::vector & /*start_interfaces*/, @@ -145,11 +147,11 @@ class ActuatorInterface : public rclcpp_lifecycle::node_interfaces::LifecycleNod * Perform the mode-switching for the new command interface combination. * * \note This is part of the realtime update loop, and should be fast. - * \note All starting and stopping interface keys are passed to all components, so the function should - * return return_type::OK by default when given interface keys not relevant for this component. - * \param[in] start_interfaces vector of string identifiers for the command interfaces starting. - * \param[in] stop_interfaces vector of string identifiers for the command interfacs stopping. - * \return return_type::OK if the new command interface combination can be switched to, + * \note All starting and stopping interface keys are passed to all components, so the function + * should return return_type::OK by default when given interface keys not relevant for this + * component. \param[in] start_interfaces vector of string identifiers for the command interfaces + * starting. \param[in] stop_interfaces vector of string identifiers for the command interfacs + * stopping. \return return_type::OK if the new command interface combination can be switched to, * or if the interface key is not relevant to this system. Returns return_type::ERROR otherwise. */ virtual return_type perform_command_mode_switch( diff --git a/hardware_interface/include/hardware_interface/component_parser.hpp b/hardware_interface/include/hardware_interface/component_parser.hpp index 9f81a2a863..5112f7927e 100644 --- a/hardware_interface/include/hardware_interface/component_parser.hpp +++ b/hardware_interface/include/hardware_interface/component_parser.hpp @@ -26,10 +26,10 @@ namespace hardware_interface { /// Search XML snippet from URDF for information about a control component. /** - * \param[in] urdf string with robot's URDF - * \return vector filled with information about robot's control resources - * \throws std::runtime_error if a robot attribute or tag is not found - */ + * \param[in] urdf string with robot's URDF + * \return vector filled with information about robot's control resources + * \throws std::runtime_error if a robot attribute or tag is not found + */ HARDWARE_INTERFACE_PUBLIC std::vector parse_control_resources_from_urdf(const std::string & urdf); diff --git a/hardware_interface/include/hardware_interface/resource_manager.hpp b/hardware_interface/include/hardware_interface/resource_manager.hpp index a5113380e1..4d2f995756 100644 --- a/hardware_interface/include/hardware_interface/resource_manager.hpp +++ b/hardware_interface/include/hardware_interface/resource_manager.hpp @@ -188,8 +188,9 @@ class HARDWARE_INTERFACE_PUBLIC ResourceManager /** * Return list of cached controller names that use the hardware with name \p hardware_name. * - * \param[in] hardware_name the name of the hardware for which cached controllers should be returned. - * \returns list of cached controller names that depend on hardware with name \p hardware_name. + * \param[in] hardware_name the name of the hardware for which cached controllers should be + * returned. \returns list of cached controller names that depend on hardware with name \p + * hardware_name. */ std::vector get_cached_controllers_to_hardware(const std::string & hardware_name); diff --git a/hardware_interface/include/hardware_interface/sensor_interface.hpp b/hardware_interface/include/hardware_interface/sensor_interface.hpp index 2b2a4ce7cb..14a59e4588 100644 --- a/hardware_interface/include/hardware_interface/sensor_interface.hpp +++ b/hardware_interface/include/hardware_interface/sensor_interface.hpp @@ -35,8 +35,9 @@ namespace hardware_interface /** * The typical examples are Force-Torque Sensor (FTS), Interial Measurement Unit (IMU). * - * Methods return values have type rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn - * with the following meaning: + * Methods return values have type + * rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn with the following + * meaning: * * \returns CallbackReturn::SUCCESS method execution was successful. * \returns CallbackReturn::FAILURE method execution has failed and and can be called again. @@ -46,7 +47,8 @@ namespace hardware_interface * The hardware ends after each method in a state with the following meaning: * * UNCONFIGURED (on_init, on_cleanup): - * Hardware is initialized but communication is not started and therefore no interface is available. + * Hardware is initialized but communication is not started and therefore no interface is + * available. * * INACTIVE (on_configure, on_deactivate): * Communication with the hardware is started and it is configured. diff --git a/hardware_interface/include/hardware_interface/system_interface.hpp b/hardware_interface/include/hardware_interface/system_interface.hpp index 75e1a1bc29..e5c6f2f542 100644 --- a/hardware_interface/include/hardware_interface/system_interface.hpp +++ b/hardware_interface/include/hardware_interface/system_interface.hpp @@ -36,8 +36,9 @@ namespace hardware_interface * The common examples for these types of hardware are multi-joint systems with or without sensors * such as industrial or humanoid robots. * - * Methods return values have type rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn - * with the following meaning: + * Methods return values have type + * rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn with the following + * meaning: * * \returns CallbackReturn::SUCCESS method execution was successful. * \returns CallbackReturn::FAILURE method execution has failed and and can be called again. @@ -47,7 +48,8 @@ namespace hardware_interface * The hardware ends after each method in a state with the following meaning: * * UNCONFIGURED (on_init, on_cleanup): - * Hardware is initialized but communication is not started and therefore no interface is available. + * Hardware is initialized but communication is not started and therefore no interface is + * available. * * INACTIVE (on_configure, on_deactivate): * Communication with the hardware is started and it is configured. @@ -127,12 +129,12 @@ class SystemInterface : public rclcpp_lifecycle::node_interfaces::LifecycleNodeI * * \note This is a non-realtime evaluation of whether a set of command interface claims are * possible, and call to start preparing data structures for the upcoming switch that will occur. - * \note All starting and stopping interface keys are passed to all components, so the function should - * return return_type::OK by default when given interface keys not relevant for this component. - * \param[in] start_interfaces vector of string identifiers for the command interfaces starting. - * \param[in] stop_interfaces vector of string identifiers for the command interfacs stopping. - * \return return_type::OK if the new command interface combination can be prepared, - * or if the interface key is not relevant to this system. Returns return_type::ERROR otherwise. + * \note All starting and stopping interface keys are passed to all components, so the function + * should return return_type::OK by default when given interface keys not relevant for this + * component. \param[in] start_interfaces vector of string identifiers for the command interfaces + * starting. \param[in] stop_interfaces vector of string identifiers for the command interfacs + * stopping. \return return_type::OK if the new command interface combination can be prepared, or + * if the interface key is not relevant to this system. Returns return_type::ERROR otherwise. */ virtual return_type prepare_command_mode_switch( const std::vector & /*start_interfaces*/, @@ -146,11 +148,11 @@ class SystemInterface : public rclcpp_lifecycle::node_interfaces::LifecycleNodeI * Perform the mode-switching for the new command interface combination. * * \note This is part of the realtime update loop, and should be fast. - * \note All starting and stopping interface keys are passed to all components, so the function should - * return return_type::OK by default when given interface keys not relevant for this component. - * \param[in] start_interfaces vector of string identifiers for the command interfaces starting. - * \param[in] stop_interfaces vector of string identifiers for the command interfacs stopping. - * \return return_type::OK if the new command interface combination can be switched to, + * \note All starting and stopping interface keys are passed to all components, so the function + * should return return_type::OK by default when given interface keys not relevant for this + * component. \param[in] start_interfaces vector of string identifiers for the command interfaces + * starting. \param[in] stop_interfaces vector of string identifiers for the command interfacs + * stopping. \return return_type::OK if the new command interface combination can be switched to, * or if the interface key is not relevant to this system. Returns return_type::ERROR otherwise. */ virtual return_type perform_command_mode_switch( diff --git a/hardware_interface/src/component_parser.cpp b/hardware_interface/src/component_parser.cpp index 305c7ff7aa..1338489a07 100644 --- a/hardware_interface/src/component_parser.cpp +++ b/hardware_interface/src/component_parser.cpp @@ -304,11 +304,11 @@ hardware_interface::InterfaceInfo parse_interfaces_from_xml( /// Search XML snippet from URDF for information about a control component. /** - * \param[in] component_it pointer to the iterator where component - * info should be found - * \return ComponentInfo filled with information about component - * \throws std::runtime_error if a component attribute or tag is not found - */ + * \param[in] component_it pointer to the iterator where component + * info should be found + * \return ComponentInfo filled with information about component + * \throws std::runtime_error if a component attribute or tag is not found + */ ComponentInfo parse_component_from_xml(const tinyxml2::XMLElement * component_it) { ComponentInfo component; @@ -417,10 +417,10 @@ ActuatorInfo parse_transmission_actuator_from_xml(const tinyxml2::XMLElement * e /// Search XML snippet from URDF for information about a transmission. /** - * \param[in] transmission_it pointer to the iterator where transmission info should be found - * \return TransmissionInfo filled with information about transmission - * \throws std::runtime_error if an attribute or tag is not found - */ + * \param[in] transmission_it pointer to the iterator where transmission info should be found + * \return TransmissionInfo filled with information about transmission + * \throws std::runtime_error if an attribute or tag is not found + */ TransmissionInfo parse_transmission_from_xml(const tinyxml2::XMLElement * transmission_it) { TransmissionInfo transmission; diff --git a/hardware_interface/test/test_components/test_actuator.cpp b/hardware_interface/test/test_components/test_actuator.cpp index 8fec418dcf..5f9c09e95e 100644 --- a/hardware_interface/test/test_components/test_actuator.cpp +++ b/hardware_interface/test/test_components/test_actuator.cpp @@ -40,7 +40,7 @@ class TestActuator : public ActuatorInterface * if (info_.joints[0].command_interfaces.size() != 1) {return CallbackReturn::ERROR;} * // can only give feedback state for position and velocity * if (info_.joints[0].state_interfaces.size() != 2) {return CallbackReturn::ERROR;} - */ + */ return CallbackReturn::SUCCESS; } diff --git a/joint_limits/include/joint_limits/joint_limits_rosparam.hpp b/joint_limits/include/joint_limits/joint_limits_rosparam.hpp index 5d1fd6a1f7..2f32d49271 100644 --- a/joint_limits/include/joint_limits/joint_limits_rosparam.hpp +++ b/joint_limits/include/joint_limits/joint_limits_rosparam.hpp @@ -28,11 +28,11 @@ namespace // utilities { /// Declare and initialize a parameter with a type. /** - * - * Wrapper function for templated node's declare_parameter() which checks if - * parameter is already declared. - * For use in all components that inherit from ControllerInterface - */ + * + * Wrapper function for templated node's declare_parameter() which checks if + * parameter is already declared. + * For use in all components that inherit from ControllerInterface + */ template auto auto_declare( const rclcpp::node_interfaces::NodeParametersInterface::SharedPtr & param_itf, @@ -149,10 +149,9 @@ inline bool declare_parameters(const std::string & joint_name, const rclcpp::Nod } /** - * Declare JointLimits and SoftJointLimits parameters for joint with joint_name for the lifecycle_node - * object. - * This is a convenience function. - * For parameters structure see the underlying `declare_parameters` function. + * Declare JointLimits and SoftJointLimits parameters for joint with joint_name for the + * lifecycle_node object. This is a convenience function. For parameters structure see the + * underlying `declare_parameters` function. * * \param[in] joint_name name of the joint for which parameters will be declared. * \param[in] lifecycle_node lifecycle node for parameters should be declared. @@ -217,10 +216,12 @@ inline bool declare_parameters( * \param[in] joint_name Name of joint whose limits are to be fetched, e.g., "foo_joint". * \param[in] param_itf node parameters interface of the node where parameters are specified. * \param[in] logging_itf node logging interface to provide log errors. - * \param[out] limits Where joint limit data gets written into. Limits specified in the parameter server will overwrite - * existing values. Values in \p limits not specified in the parameter server remain unchanged. + * \param[out] limits Where joint limit data gets written into. Limits specified in the parameter + * server will overwrite existing values. Values in \p limits not specified in the parameter server + * remain unchanged. * - * \returns True if a limits specification is found (i.e., the \p joint_limits/joint_name parameter exists in \p node), false otherwise. + * \returns True if a limits specification is found (i.e., the \p joint_limits/joint_name parameter + * exists in \p node), false otherwise. */ inline bool get_joint_limits( const std::string & joint_name, @@ -385,8 +386,9 @@ inline bool get_joint_limits( * * \param[in] joint_name Name of joint whose limits are to be fetched. * \param[in] node Node object for which parameters should be fetched. - * \param[out] limits Where joint limit data gets written into. Limits specified in the parameter server will overwrite - * existing values. Values in \p limits not specified in the parameter server remain unchanged. + * \param[out] limits Where joint limit data gets written into. Limits specified in the parameter + * server will overwrite existing values. Values in \p limits not specified in the parameter server + * remain unchanged. * * \returns True if a limits specification is found, false otherwise. */ @@ -404,8 +406,9 @@ inline bool get_joint_limits( * * \param[in] joint_name Name of joint whose limits are to be fetched. * \param[in] lifecycle_node Lifecycle node object for which parameters should be fetched. - * \param[out] limits Where joint limit data gets written into. Limits specified in the parameter server will overwrite - * existing values. Values in \p limits not specified in the parameter server remain unchanged. + * \param[out] limits Where joint limit data gets written into. Limits specified in the parameter + * server will overwrite existing values. Values in \p limits not specified in the parameter server + * remain unchanged. * * \returns True if a limits specification is found, false otherwise. */ @@ -445,10 +448,10 @@ inline bool get_joint_limits( * \param[in] joint_name Name of joint whose limits are to be fetched, e.g., "foo_joint". * \param[in] param_itf node parameters interface of the node where parameters are specified. * \param[in] logging_itf node logging interface to provide log errors. - * \param[out] soft_limits Where soft joint limit data gets written into. Limits specified in the parameter server will overwrite - * existing values. - * \return True if a complete soft limits specification is found (ie. if all \p k_position, \p k_velocity, \p soft_lower_limit and - * \p soft_upper_limit exist in \p joint_limits/joint_name namespace), false otherwise. + * \param[out] soft_limits Where soft joint limit data gets written into. Limits specified in the + * parameter server will overwrite existing values. \return True if a complete soft limits + * specification is found (ie. if all \p k_position, \p k_velocity, \p soft_lower_limit and \p + * soft_upper_limit exist in \p joint_limits/joint_name namespace), false otherwise. */ inline bool get_joint_limits( const std::string & joint_name, @@ -512,8 +515,8 @@ inline bool get_joint_limits( * * \param[in] joint_name Name of joint whose limits are to be fetched. * \param[in] node Node object for which parameters should be fetched. - * \param[out] soft_limits Where soft joint limit data gets written into. Limits specified in the parameter server will overwrite - * existing values. + * \param[out] soft_limits Where soft joint limit data gets written into. Limits specified in the + * parameter server will overwrite existing values. * * \returns True if a soft limits specification is found, false otherwise. */ @@ -533,8 +536,8 @@ inline bool get_joint_limits( * * \param[in] joint_name Name of joint whose limits are to be fetched. * \param[in] lifecycle_node Lifecycle node object for which parameters should be fetched. - * \param[out] soft_limits Where soft joint limit data gets written into. Limits specified in the parameter server will overwrite - * existing values. + * \param[out] soft_limits Where soft joint limit data gets written into. Limits specified in the + * parameter server will overwrite existing values. * * \returns True if a soft limits specification is found, false otherwise. */ diff --git a/joint_limits_interface/include/joint_limits_interface/joint_limits_interface.hpp b/joint_limits_interface/include/joint_limits_interface/joint_limits_interface.hpp index 3f17ceea78..db553948d1 100644 --- a/joint_limits_interface/include/joint_limits_interface/joint_limits_interface.hpp +++ b/joint_limits_interface/include/joint_limits_interface/joint_limits_interface.hpp @@ -144,8 +144,8 @@ class JointSoftLimitsHandle : public JointLimitHandle joint_limits_interface::SoftJointLimits soft_limits_; }; -/** A handle used to enforce position and velocity limits of a position-controlled joint that does not have - soft limits. */ +/** A handle used to enforce position and velocity limits of a position-controlled joint that does + not have soft limits. */ class PositionJointSaturationHandle : public JointLimitHandle { public: @@ -170,8 +170,8 @@ class PositionJointSaturationHandle : public JointLimitHandle /// Enforce position and velocity limits for a joint that is not subject to soft limits. /** - * \param[in] period Control period. - */ + * \param[in] period Control period. + */ void enforce_limits(const rclcpp::Duration & period) { if (std::isnan(prev_pos_)) @@ -209,9 +209,9 @@ class PositionJointSaturationHandle : public JointLimitHandle /// A handle used to enforce position and velocity limits of a position-controlled joint. /** - * This class implements a very simple position and velocity limits enforcing policy, and tries to impose the least - * amount of requisites on the underlying hardware platform. - * This lowers considerably the entry barrier to use it, but also implies some limitations. + * This class implements a very simple position and velocity limits enforcing policy, and tries to + * impose the least amount of requisites on the underlying hardware platform. This lowers + * considerably the entry barrier to use it, but also implies some limitations. * * Requisites * - Position (for non-continuous joints) and velocity limits specification. @@ -219,21 +219,22 @@ class PositionJointSaturationHandle : public JointLimitHandle * * Open loop nature * - * Joint position and velocity limits are enforced in an open-loop fashion, that is, the command is checked for - * validity without relying on the actual position/velocity values. + * Joint position and velocity limits are enforced in an open-loop fashion, that is, the command is + * checked for validity without relying on the actual position/velocity values. * - * - Actual position values are \e not used because in some platforms there might be a substantial lag - * between sending a command and executing it (propagate command to hardware, reach control objective, - * read from hardware). + * - Actual position values are \e not used because in some platforms there might be a substantial + * lag between sending a command and executing it (propagate command to hardware, reach control + * objective, read from hardware). * - * - Actual velocity values are \e not used because of the above reason, and because some platforms might not expose - * trustworthy velocity measurements, or none at all. + * - Actual velocity values are \e not used because of the above reason, and because some platforms + * might not expose trustworthy velocity measurements, or none at all. * - * The downside of the open loop behavior is that velocity limits will not be enforced when recovering from large - * position tracking errors. Only the command is guaranteed to comply with the limits specification. + * The downside of the open loop behavior is that velocity limits will not be enforced when + * recovering from large position tracking errors. Only the command is guaranteed to comply with the + * limits specification. * - * \note: This handle type is \e stateful, ie. it stores the previous position command to estimate the command - * velocity. + * \note: This handle type is \e stateful, ie. it stores the previous position command to estimate + * the command velocity. */ // TODO(anyone): Leverage %Reflexxes Type II library for acceleration limits handling? @@ -553,8 +554,8 @@ class VelocityJointSaturationHandle : public JointLimitHandle /** * A handle used to enforce position, velocity, and acceleration limits of a - * velocity-controlled joint. - */ + * velocity-controlled joint. + */ class VelocityJointSoftLimitsHandle : public JointSoftLimitsHandle { public: diff --git a/joint_limits_interface/include/joint_limits_interface/joint_limits_urdf.hpp b/joint_limits_interface/include/joint_limits_interface/joint_limits_urdf.hpp index 6f26a997ee..80cf7f0ed4 100644 --- a/joint_limits_interface/include/joint_limits_interface/joint_limits_urdf.hpp +++ b/joint_limits_interface/include/joint_limits_interface/joint_limits_urdf.hpp @@ -27,8 +27,8 @@ namespace joint_limits_interface /** * Populate a JointLimits instance from URDF joint data. * \param[in] urdf_joint URDF joint. - * \param[out] limits Where URDF joint limit data gets written into. Limits in \e urdf_joint will overwrite existing - * values. Values in \e limits not present in \e urdf_joint remain unchanged. + * \param[out] limits Where URDF joint limit data gets written into. Limits in \e urdf_joint will + * overwrite existing values. Values in \e limits not present in \e urdf_joint remain unchanged. * \return True if \e urdf_joint has a valid limits specification, false otherwise. */ inline bool getJointLimits(urdf::JointConstSharedPtr urdf_joint, JointLimits & limits) diff --git a/transmission_interface/include/transmission_interface/differential_transmission.hpp b/transmission_interface/include/transmission_interface/differential_transmission.hpp index 6bc89ab893..2002f6f9d7 100644 --- a/transmission_interface/include/transmission_interface/differential_transmission.hpp +++ b/transmission_interface/include/transmission_interface/differential_transmission.hpp @@ -30,9 +30,8 @@ namespace transmission_interface /// Implementation of a differential transmission. /** * - * This transmission relates two actuators and two joints through a differential mechanism, as illustrated - * below. - * \image html differential_transmission.png + * This transmission relates two actuators and two joints through a differential + * mechanism, as illustrated below. \image html differential_transmission.png * *
* @@ -76,28 +75,33 @@ namespace transmission_interface * *
* \f{eqnarray*}{ - * x_{a_1} & = & n_{a_1} \left[ n_{j_1} (x_{j_1} - x_{off_1}) + n_{j_2} (x_{j_2} - x_{off_2}) \right] \\[2.5em] - * x_{a_2} & = & n_{a_2} \left[ n_{j_1} (x_{j_1} - x_{off_1}) - n_{j_2} (x_{j_2} - x_{off_2}) \right] - * \f} + * x_{a_1} & = & n_{a_1} \left[ n_{j_1} (x_{j_1} - x_{off_1}) + n_{j_2} (x_{j_2} - x_{off_2}) + * \right] \\[2.5em] x_{a_2} & = & n_{a_2} \left[ n_{j_1} (x_{j_1} - x_{off_1}) - n_{j_2} (x_{j_2} - + * x_{off_2}) \right] \f} *
*
* * where: - * - \f$ x \f$, \f$ \dot{x} \f$ and \f$ \tau \f$ are position, velocity and effort variables, respectively. - * - Subindices \f$ _a \f$ and \f$ _j \f$ are used to represent actuator-space and joint-space variables, respectively. - * - \f$ x_{off}\f$ represents the offset between motor and joint zeros, expressed in joint position coordinates - * (cf. SimpleTransmission class documentation for a more detailed description of this variable). - * - \f$ n \f$ represents a transmission ratio. Reducers/amplifiers are allowed on both the actuator and joint sides - * (depicted as timing belts in the figure). - * A transmission ratio can take any real value \e except zero. In particular: - * - If its absolute value is greater than one, it's a velocity reducer / effort amplifier, while if its absolute - * value lies in \f$ (0, 1) \f$ it's a velocity amplifier / effort reducer. - * - Negative values represent a direction flip, ie. input and output move in opposite directions. - * - Important: Use transmission ratio signs to match this class' convention of positive actuator/joint - * directions with a given mechanical design, as they will in general not match. + * - \f$ x \f$, \f$ \dot{x} \f$ and \f$ \tau \f$ are position, velocity and effort variables, + * respectively. + * - Subindices \f$ _a \f$ and \f$ _j \f$ are used to represent actuator-space and joint-space + * variables, respectively. + * - \f$ x_{off}\f$ represents the offset between motor and joint zeros, expressed in joint position + * coordinates (cf. SimpleTransmission class documentation for a more detailed description of this + * variable). + * - \f$ n \f$ represents a transmission ratio. Reducers/amplifiers are allowed on both the actuator + * and joint sides (depicted as timing belts in the figure). A transmission ratio can take any real + * value \e except zero. In particular: + * - If its absolute value is greater than one, it's a velocity reducer / effort amplifier, + * while if its absolute value lies in \f$ (0, 1) \f$ it's a velocity amplifier / effort reducer. + * - Negative values represent a direction flip, ie. input and output move in opposite + * directions. + * - Important: Use transmission ratio signs to match this class' convention of positive + * actuator/joint directions with a given mechanical design, as they will in general not match. * - * \note This implementation currently assumes a specific layout for location of the actuators and joint axes which is - * common in robotic mechanisms. Please file an enhancement ticket if your use case does not adhere to this layout. + * \note This implementation currently assumes a specific layout for location of the actuators and + * joint axes which is common in robotic mechanisms. Please file an enhancement ticket if your use + * case does not adhere to this layout. * * \ingroup transmission_types */ @@ -126,14 +130,16 @@ class DifferentialTransmission : public Transmission /// Transform variables from actuator to joint space. /** * \pre Actuator and joint vectors must have size 2 and point to valid data. - * To call this method it is not required that all other data vectors contain valid data, and can even remain empty. + * To call this method it is not required that all other data vectors contain valid data, and can + * even remain empty. */ void actuator_to_joint() override; /// Transform variables from joint to actuator space. /** * \pre Actuator and joint vectors must have size 2 and point to valid data. - * To call this method it is not required that all other data vectors contain valid data, and can even remain empty. + * To call this method it is not required that all other data vectors contain valid data, and can + * even remain empty. */ void joint_to_actuator() override; diff --git a/transmission_interface/include/transmission_interface/four_bar_linkage_transmission.hpp b/transmission_interface/include/transmission_interface/four_bar_linkage_transmission.hpp index b8eb05e8d3..39f5df6f61 100644 --- a/transmission_interface/include/transmission_interface/four_bar_linkage_transmission.hpp +++ b/transmission_interface/include/transmission_interface/four_bar_linkage_transmission.hpp @@ -29,77 +29,80 @@ namespace transmission_interface { /// Implementation of a four-bar-linkage transmission. /** -* -* This transmission relates two actuators and two joints through a mechanism in which the state of the -* first joint only depends on the first actuator, while the second joint depends on both actuators, as -* illustrated below. -* Although the class name makes specific reference to the four-bar-linkage, there are other mechanical layouts -* that yield the same behavior, such as the remote actuation example also depicted below. -* \image html four_bar_linkage_transmission.png -* -*
-* -* -* -* -* -* -* -* -* -* -*
Effort
Velocity
Position
-* Actuator to joint -* -* \f{eqnarray*}{ -* \tau_{j_1} & = & n_{j_1} n_{a_1} \tau_{a_1} \\ -* \tau_{j_2} & = & n_{j_2} (n_{a_2} \tau_{a_2} - n_{j_1} n_{a_1} \tau_{a_1}) -* \f} -* -* \f{eqnarray*}{ -* \dot{x}_{j_1} & = & \frac{ \dot{x}_{a_1} }{ n_{j_1} n_{a_1} } \\ -* \dot{x}_{j_2} & = & \frac{ \dot{x}_{a_2} / n_{a_2} - \dot{x}_{a_1} / (n_{j_1} n_{a_1}) }{ n_{j_2} } -* \f} -* -* \f{eqnarray*}{ -* x_{j_1} & = & \frac{ x_{a_1} }{ n_{j_1} n_{a_1} } + x_{off_1} \\ -* x_{j_2} & = & \frac{ x_{a_2} / n_{a_2} - x_{a_1} / (n_{j_1} n_{a_1}) }{ n_{j_2} } + x_{off_2} -* \f} -*
-* Joint to actuator -* -* \f{eqnarray*}{ -* \tau_{a_1} & = & \tau_{j_1} / (n_{j_1} n_{a_1}) \\ -* \tau_{a_2} & = & \frac{ \tau_{j_1} + \tau_{j_2} / n_{j_2} }{ n_{a_2} } -* \f} -* -* \f{eqnarray*}{ -* \dot{x}_{a_1} & = & n_{j_1} n_{a_1} \dot{x}_{j_1} \\ -* \dot{x}_{a_2} & = & n_{a_2} (\dot{x}_{j_1} + n_{j_2} \dot{x}_{j_2}) -* \f} -* -* \f{eqnarray*}{ -* x_{a_1} & = & n_{j_1} n_{a_1} (x_{j_1} - x_{off_1}) \\ -* x_{a_2} & = & n_{a_2} \left[(x_{j_1} - x_{off_1}) + n_{j_2} (x_{j_2} - x_{off_2})\right] -* \f} -*
-*
-* -* where: -* - \f$ x \f$, \f$ \dot{x} \f$ and \f$ \tau \f$ are position, velocity and effort variables, respectively. -* - Subindices \f$ _a \f$ and \f$ _j \f$ are used to represent actuator-space and joint-space variables, respectively. -* - \f$ x_{off}\f$ represents the offset between motor and joint zeros, expressed in joint position coordinates. -* (cf. SimpleTransmission class documentation for a more detailed description of this variable). -* - \f$ n \f$ represents a transmission ratio (reducers/amplifiers are depicted as timing belts in the figure). -* A transmission ratio can take any real value \e except zero. In particular: -* - If its absolute value is greater than one, it's a velocity reducer / effort amplifier, while if its absolute -* value lies in \f$ (0, 1) \f$ it's a velocity amplifier / effort reducer. -* - Negative values represent a direction flip, ie. input and output move in opposite directions. -* - Important: Use transmission ratio signs to match this class' convention of positive actuator/joint -* directions with a given mechanical design, as they will in general not match. -* -* \ingroup transmission_types -*/ + * + * This transmission relates two actuators and two joints through a mechanism in which + * the state of the first joint only depends on the first actuator, while the second joint depends + * on both actuators, as illustrated below. Although the class name makes specific reference to the + * four-bar-linkage, there are other mechanical layouts that yield the same behavior, such as the + * remote actuation example also depicted below. \image html four_bar_linkage_transmission.png + * + *
+ * + * + * + * + * + * + * + * + * + * + *
Effort
Velocity
Position
+ * Actuator to joint + * + * \f{eqnarray*}{ + * \tau_{j_1} & = & n_{j_1} n_{a_1} \tau_{a_1} \\ + * \tau_{j_2} & = & n_{j_2} (n_{a_2} \tau_{a_2} - n_{j_1} n_{a_1} \tau_{a_1}) + * \f} + * + * \f{eqnarray*}{ + * \dot{x}_{j_1} & = & \frac{ \dot{x}_{a_1} }{ n_{j_1} n_{a_1} } \\ + * \dot{x}_{j_2} & = & \frac{ \dot{x}_{a_2} / n_{a_2} - \dot{x}_{a_1} / (n_{j_1} n_{a_1}) }{ n_{j_2} + * } \f} + * + * \f{eqnarray*}{ + * x_{j_1} & = & \frac{ x_{a_1} }{ n_{j_1} n_{a_1} } + x_{off_1} \\ + * x_{j_2} & = & \frac{ x_{a_2} / n_{a_2} - x_{a_1} / (n_{j_1} n_{a_1}) }{ n_{j_2} } + x_{off_2} + * \f} + *
+ * Joint to actuator + * + * \f{eqnarray*}{ + * \tau_{a_1} & = & \tau_{j_1} / (n_{j_1} n_{a_1}) \\ + * \tau_{a_2} & = & \frac{ \tau_{j_1} + \tau_{j_2} / n_{j_2} }{ n_{a_2} } + * \f} + * + * \f{eqnarray*}{ + * \dot{x}_{a_1} & = & n_{j_1} n_{a_1} \dot{x}_{j_1} \\ + * \dot{x}_{a_2} & = & n_{a_2} (\dot{x}_{j_1} + n_{j_2} \dot{x}_{j_2}) + * \f} + * + * \f{eqnarray*}{ + * x_{a_1} & = & n_{j_1} n_{a_1} (x_{j_1} - x_{off_1}) \\ + * x_{a_2} & = & n_{a_2} \left[(x_{j_1} - x_{off_1}) + n_{j_2} (x_{j_2} - x_{off_2})\right] + * \f} + *
+ *
+ * + * where: + * - \f$ x \f$, \f$ \dot{x} \f$ and \f$ \tau \f$ are position, velocity and effort variables, + * respectively. + * - Subindices \f$ _a \f$ and \f$ _j \f$ are used to represent actuator-space and joint-space + * variables, respectively. + * - \f$ x_{off}\f$ represents the offset between motor and joint zeros, expressed in joint position + * coordinates. (cf. SimpleTransmission class documentation for a more detailed description of this + * variable). + * - \f$ n \f$ represents a transmission ratio (reducers/amplifiers are depicted as timing belts in + * the figure). A transmission ratio can take any real value \e except zero. In particular: + * - If its absolute value is greater than one, it's a velocity reducer / effort amplifier, + * while if its absolute value lies in \f$ (0, 1) \f$ it's a velocity amplifier / effort reducer. + * - Negative values represent a direction flip, ie. input and output move in opposite + * directions. + * - Important: Use transmission ratio signs to match this class' convention of positive + * actuator/joint directions with a given mechanical design, as they will in general not match. + * + * \ingroup transmission_types + */ class FourBarLinkageTransmission : public Transmission { public: @@ -125,14 +128,16 @@ class FourBarLinkageTransmission : public Transmission /// Transform variables from actuator to joint space. /** * \pre Actuator and joint vectors must have size 2 and point to valid data. - * To call this method it is not required that all other data vectors contain valid data, and can even remain empty. + * To call this method it is not required that all other data vectors contain valid data, and can + * even remain empty. */ void actuator_to_joint() override; /// Transform variables from joint to actuator space. /** * \pre Actuator and joint vectors must have size 2 and point to valid data. - * To call this method it is not required that all other data vectors contain valid data, and can even remain empty. + * To call this method it is not required that all other data vectors contain valid data, and can + * even remain empty. */ void joint_to_actuator() override; diff --git a/transmission_interface/include/transmission_interface/simple_transmission.hpp b/transmission_interface/include/transmission_interface/simple_transmission.hpp index a74cc3dddd..809472ab75 100644 --- a/transmission_interface/include/transmission_interface/simple_transmission.hpp +++ b/transmission_interface/include/transmission_interface/simple_transmission.hpp @@ -28,9 +28,9 @@ namespace transmission_interface { /// Implementation of a simple reducer transmission. /** - * This transmission relates one actuator and one joint through a reductor (or amplifier). - * Timing belts and gears are examples of this transmission type, and are illustrated below. - * \image html simple_transmission.png + * This transmission relates one actuator and one joint through a reductor (or + * amplifier). Timing belts and gears are examples of this transmission type, and are illustrated + * below. \image html simple_transmission.png * *
* @@ -63,17 +63,20 @@ namespace transmission_interface * * * where: - * - \f$ x \f$, \f$ \dot{x} \f$ and \f$ \tau \f$ are position, velocity and effort variables, respectively. - * - Subindices \f$ _a \f$ and \f$ _j \f$ are used to represent actuator-space and joint-space variables, respectively. - * - \f$ x_{off}\f$ represents the offset between motor and joint zeros, expressed in joint position coordinates. - * - \f$ n \f$ is the transmission ratio, and can be computed as the ratio between the output and input pulley - * radii for the timing belt; or the ratio between output and input teeth for the gear system. - * The transmission ratio can take any real value \e except zero. In particular: - * - If its absolute value is greater than one, it's a velocity reducer / effort amplifier, while if its absolute - * value lies in \f$ (0, 1) \f$ it's a velocity amplifier / effort reducer. - * - Negative values represent a direction flip, ie. actuator and joint move in opposite directions. For example, - * in timing belts actuator and joint move in the same direction, while in single-stage gear systems actuator and - * joint move in opposite directions. + * - \f$ x \f$, \f$ \dot{x} \f$ and \f$ \tau \f$ are position, velocity and effort variables, + * respectively. + * - Subindices \f$ _a \f$ and \f$ _j \f$ are used to represent actuator-space and joint-space + * variables, respectively. + * - \f$ x_{off}\f$ represents the offset between motor and joint zeros, expressed in joint position + * coordinates. + * - \f$ n \f$ is the transmission ratio, and can be computed as the ratio between the output and + * input pulley radii for the timing belt; or the ratio between output and input teeth for the gear + * system. The transmission ratio can take any real value \e except zero. In particular: + * - If its absolute value is greater than one, it's a velocity reducer / effort amplifier, + * while if its absolute value lies in \f$ (0, 1) \f$ it's a velocity amplifier / effort reducer. + * - Negative values represent a direction flip, ie. actuator and joint move in opposite + * directions. For example, in timing belts actuator and joint move in the same direction, while in + * single-stage gear systems actuator and joint move in opposite directions. * * \ingroup transmission_types */ @@ -102,14 +105,16 @@ class SimpleTransmission : public Transmission /// Transform variables from actuator to joint space. /** * This method operates on the handles provided when configuring the transmission. - * To call this method it is not required that all supported interface types are provided, e.g. one can supply only velocity handles + * To call this method it is not required that all supported interface types are provided, e.g. + * one can supply only velocity handles */ void actuator_to_joint() override; /// Transform variables from joint to actuator space. /** * This method operates on the handles provided when configuring the transmission. - * To call this method it is not required that all supported interface types are provided, e.g. one can supply only velocity handles + * To call this method it is not required that all supported interface types are provided, e.g. + * one can supply only velocity handles */ void joint_to_actuator() override; diff --git a/transmission_interface/include/transmission_interface/transmission.hpp b/transmission_interface/include/transmission_interface/transmission.hpp index 8ca0196c4c..697e1a4eb7 100644 --- a/transmission_interface/include/transmission_interface/transmission.hpp +++ b/transmission_interface/include/transmission_interface/transmission.hpp @@ -26,21 +26,23 @@ namespace transmission_interface { /// Abstract base class for representing mechanical transmissions. /** - * Mechanical transmissions transform effort/flow variables such that their product (power) remains constant. - * Effort variables for linear and rotational domains are \e force and \e torque; while the flow variables are - * respectively linear velocity and angular velocity. + * Mechanical transmissions transform effort/flow variables such that their product (power) remains + * constant. Effort variables for linear and rotational domains are \e force and \e torque; while + * the flow variables are respectively linear velocity and angular velocity. * - * In robotics it is customary to place transmissions between actuators and joints. This interface adheres to this - * naming to identify the input and output spaces of the transformation. - * The provided interfaces allow bidirectional mappings between actuator and joint spaces for effort, velocity and - * position. Position is not a power variable, but the mappings can be implemented using the velocity map plus an - * integration constant representing the offset between actuator and joint zeros. + * In robotics it is customary to place transmissions between actuators and joints. This interface + * adheres to this naming to identify the input and output spaces of the transformation. The + * provided interfaces allow bidirectional mappings between actuator and joint spaces for effort, + * velocity and position. Position is not a power variable, but the mappings can be implemented + * using the velocity map plus an integration constant representing the offset between actuator and + * joint zeros. * * \par Credit - * This interface was inspired by similar existing implementations by PAL Robotics, S.L. and Willow Garage Inc. + * This interface was inspired by similar existing implementations by PAL Robotics, S.L. and Willow + * Garage Inc. * - * \note Implementations of this interface must take care of realtime-safety if the code is to be run in realtime - * contexts, as is often the case in robot control. + * \note Implementations of this interface must take care of realtime-safety if the code is to be + * run in realtime contexts, as is often the case in robot control. */ class Transmission { @@ -55,20 +57,20 @@ class Transmission /** * \param[in] act_data Actuator-space variables. * \param[out] jnt_data Joint-space variables. - * \pre All non-empty vectors must contain valid data and their size should be consistent with the number of - * transmission actuators and joints. - * Data vectors not used in this map can remain empty. + * \pre All non-empty vectors must contain valid data and their size should be consistent with the + * number of transmission actuators and joints. Data vectors not used in this map can remain + * empty. */ virtual void actuator_to_joint() = 0; /// Transform \e effort variables from joint to actuator space. /** - * \param[in] jnt_data Joint-space variables. - * \param[out] act_data Actuator-space variables. - * \pre All non-empty vectors must contain valid data and their size should be consistent with the number of - * transmission actuators and joints. - * Data vectors not used in this map can remain empty. - */ + * \param[in] jnt_data Joint-space variables. + * \param[out] act_data Actuator-space variables. + * \pre All non-empty vectors must contain valid data and their size should be consistent with the + * number of transmission actuators and joints. Data vectors not used in this map can remain + * empty. + */ virtual void joint_to_actuator() = 0; /** \return Number of actuators managed by transmission, From 3b8616e1298d352408aa17458b1c5693651858a2 Mon Sep 17 00:00:00 2001 From: Alex Moriarty Date: Fri, 2 Jun 2023 09:44:57 -0300 Subject: [PATCH 04/40] [EOL] Foxy & Galactic (#1044) * [EOL] Foxy & Galactic - Foxy EOL date is May 2023 - Galactic EOL date was Dec 9 2022 https://docs.ros.org/en/rolling/Releases.html Signed-off-by: Alex Moriarty * fix typo --------- Signed-off-by: Alex Moriarty Co-authored-by: Bence Magyar --- .github/ISSUE_TEMPLATE/good-first-issue.md | 4 +-- .github/mergify.yml | 20 +---------- .github/workflows/README.md | 2 -- .github/workflows/foxy-abi-compatibility.yml | 20 ----------- .github/workflows/foxy-binary-build-main.yml | 26 --------------- .../workflows/foxy-semi-binary-build-main.yml | 25 -------------- .../workflows/galactic-abi-compatibility.yml | 20 ----------- .../workflows/galactic-binary-build-main.yml | 26 --------------- .../workflows/galactic-rhel-binary-build.yml | 33 ------------------- .../galactic-semi-binary-build-main.yml | 22 ------------- .github/workflows/prerelease-check.yml | 4 --- .../reusable-ros-tooling-source-build.yml | 2 +- README.md | 2 -- ros2_control-not-released.foxy.repos | 1 - ros2_control-not-released.galactic.repos | 1 - ros2_control.foxy.repos | 9 ----- ros2_control.galactic.repos | 9 ----- 17 files changed, 4 insertions(+), 222 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-semi-binary-build-main.yml 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-rhel-binary-build.yml delete mode 100644 .github/workflows/galactic-semi-binary-build-main.yml delete mode 100644 ros2_control-not-released.foxy.repos delete mode 100644 ros2_control-not-released.galactic.repos delete mode 100644 ros2_control.foxy.repos delete mode 100644 ros2_control.galactic.repos diff --git a/.github/ISSUE_TEMPLATE/good-first-issue.md b/.github/ISSUE_TEMPLATE/good-first-issue.md index a4f155ffda..5ff89fff5a 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/galactic/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_control`, [here is a guide that you can follow](https://guides.github.com/activities/forking/) (You will have to remove or empty the existing `ros2_control` 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/galactic/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 e62f958961..49d2acedfa 100644 --- a/.github/mergify.yml +++ b/.github/mergify.yml @@ -2,30 +2,12 @@ pull_request_rules: - name: Backport to humble at reviewers discretion conditions: - base=master - - "label=humble-galactic" + - "label=backport-humble" actions: backport: branches: - humble - - 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 - - "label=backport-foxy" - actions: - backport: - branches: - - foxy - - name: Ask to resolve conflict conditions: - conflict diff --git a/.github/workflows/README.md b/.github/workflows/README.md index e784883593..36caf0256f 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -3,5 +3,3 @@ ROS2 Distro | Branch | Build status | Documentation | Released packages :---------: | :----: | :----------: | :-----------: | :---------------: **Rolling** | [`master`](https://github.com/ros-controls/ros2_control/tree/master) | [![Rolling Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/rolling-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_control/actions/workflows/rolling-binary-build-main.yml?branch=master)
[![Rolling Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/rolling-binary-build-testing.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_control/actions/workflows/rolling-binary-build-testing.yml?branch=master)
[![Rolling Semi-Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/rolling-semi-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_control/actions/workflows/rolling-semi-binary-build-main.yml?branch=master)
[![Rolling Semi-Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/rolling-semi-binary-build-testing.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_control/actions/workflows/rolling-semi-binary-build-testing.yml?branch=master)
[![Rolling Source Build](https://github.com/ros-controls/ros2_control/actions/workflows/rolling-source-build.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_control/actions/workflows/rolling-source-build.yml?branch=master) | [Documentation](https://control.ros.org/master/index.html)
[API Reference](https://control.ros.org/master/doc/api/index.html) | [ros2_control](https://index.ros.org/p/ros2_control/#rolling) **Humble** | [`humble`](https://github.com/ros-controls/ros2_control/tree/humble) | [![Humble Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/humble-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_control/actions/workflows/humble-binary-build-main.yml?branch=master)
[![Humble Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/humble-binary-build-testing.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_control/actions/workflows/humble-binary-build-testing.yml?branch=master)
[![Humble Semi-Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/humble-semi-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_control/actions/workflows/humble-semi-binary-build-main.yml?branch=master)
[![Humble Semi-Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/humble-semi-binary-build-testing.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_control/actions/workflows/humble-semi-binary-build-testing.yml?branch=master)
[![Humble Source Build](https://github.com/ros-controls/ros2_control/actions/workflows/humble-source-build.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_control/actions/workflows/humble-source-build.yml?branch=master) | [Documentation](https://control.ros.org/humble/index.html)
[API Reference](https://control.ros.org/humble/doc/api/index.html) | [ros2_control](https://index.ros.org/p/ros2_control/#humble) -**Galactic** | [`galactic`](https://github.com/ros-controls/ros2_control/tree/galactic) | [![Galactic Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/galactic-binary-build-main.yml/badge.svg?branch=galactic)](https://github.com/ros-controls/ros2_control/actions/workflows/galactic-binary-build-main.yml?branch=galactic)
[![Galactic Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/galactic-binary-build-testing.yml/badge.svg?branch=galactic)](https://github.com/ros-controls/ros2_control/actions/workflows/galactic-binary-build-testing.yml?branch=galactic)
[![Galactic Semi-Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/galactic-semi-binary-build-main.yml/badge.svg?branch=galactic)](https://github.com/ros-controls/ros2_control/actions/workflows/galactic-semi-binary-build-main.yml?branch=galactic)
[![Galactic Semi-Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/galactic-semi-binary-build-testing.yml/badge.svg?branch=galactic)](https://github.com/ros-controls/ros2_control/actions/workflows/galactic-semi-binary-build-testing.yml?branch=galactic) | [Documentation](https://control.ros.org/galactic/index.html)
[API Reference](https://control.ros.org/galactic/doc/api/index.html) | [ros2_control](https://index.ros.org/p/ros2_control/#galactic) -**Foxy** | [`foxy`](https://github.com/ros-controls/ros2_control/tree/foxy) | [![Foxy Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/foxy-binary-build-main.yml/badge.svg?branch=foxy)](https://github.com/ros-controls/ros2_control/actions/workflows/foxy-binary-build-main.yml?branch=foxy)
[![Foxy Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/foxy-binary-build-testing.yml/badge.svg?branch=foxy)](https://github.com/ros-controls/ros2_control/actions/workflows/foxy-binary-build-testing.yml?branch=foxy)
[![Foxy Semi-Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/foxy-semi-binary-build-main.yml/badge.svg?branch=foxy)](https://github.com/ros-controls/ros2_control/actions/workflows/foxy-semi-binary-build-main.yml?branch=foxy)
[![Foxy Semi-Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/foxy-semi-binary-build-testing.yml/badge.svg?branch=foxy)](https://github.com/ros-controls/ros2_control/actions/workflows/foxy-semi-binary-build-testing.yml?branch=foxy) | [Documentation](https://control.ros.org/foxy/index.html)
[API Reference](https://control.ros.org/foxy/doc/api/index.html) | [ros2_control](https://index.ros.org/p/ros2_control/#foxy) 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 0d74ce64e4..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_control-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 68e709cc00..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_control.foxy.repos - ref_for_scheduled_build: 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 f50c773444..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_control-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 ca0b30382a..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_control - - run: | - rosdep update - rosdep install -iy --from-path src/ros2_control - 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 0578366a45..0000000000 --- a/.github/workflows/galactic-semi-binary-build-main.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: Galactic Semi-Binary Build - main -# description: 'Build & test that compiles the main dependencies from source.' - -on: - workflow_dispatch: - 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_control.galactic.repos - ref_for_scheduled_build: galactic diff --git a/.github/workflows/prerelease-check.yml b/.github/workflows/prerelease-check.yml index b9460bda47..5e7326e510 100644 --- a/.github/workflows/prerelease-check.yml +++ b/.github/workflows/prerelease-check.yml @@ -9,8 +9,6 @@ on: default: 'rolling' type: choice options: - - foxy - - galactic - humble - rolling branch: @@ -19,8 +17,6 @@ on: default: 'master' 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 777d193c69..46b998c326 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 repository 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 276ffb9e6a..e5ba217d35 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,6 @@ ROS2 Distro | Branch | Build status | Documentation | Released packages :---------: | :----: | :----------: | :-----------: | :---------------: **Rolling** | [`master`](https://github.com/ros-controls/ros2_control/tree/master) | [![Rolling Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/rolling-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_control/actions/workflows/rolling-binary-build-main.yml?branch=master)
[![Rolling Semi-Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/rolling-semi-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_control/actions/workflows/rolling-semi-binary-build-main.yml?branch=master) | [Documentation](https://control.ros.org/master/index.html)
[API Reference](https://control.ros.org/master/doc/api/index.html) | [ros2_control](https://index.ros.org/p/ros2_control/#rolling) **Humble** | [`humble`](https://github.com/ros-controls/ros2_control/tree/humble) | [![Humble Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/humble-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_control/actions/workflows/humble-binary-build-main.yml?branch=master)
[![Humble Semi-Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/humble-semi-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_control/actions/workflows/humble-semi-binary-build-main.yml?branch=master) | [Documentation](https://control.ros.org/humble/index.html)
[API Reference](https://control.ros.org/humble/doc/api/index.html) | [ros2_control](https://index.ros.org/p/ros2_control/#humble) -**Galactic** | [`galactic`](https://github.com/ros-controls/ros2_control/tree/galactic) | [![Galactic Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/galactic-binary-build-main.yml/badge.svg?branch=galactic)](https://github.com/ros-controls/ros2_control/actions/workflows/galactic-binary-build-main.yml?branch=galactic)
[![Galactic Semi-Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/galactic-semi-binary-build-main.yml/badge.svg?branch=galactic)](https://github.com/ros-controls/ros2_control/actions/workflows/galactic-semi-binary-build-main.yml?branch=galactic) | [Documentation](https://control.ros.org/galactic/index.html)
[API Reference](https://control.ros.org/galactic/doc/api/index.html) | [ros2_control](https://index.ros.org/p/ros2_control/#galactic) -**Foxy** | [`foxy`](https://github.com/ros-controls/ros2_control/tree/foxy) | [![Foxy Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/foxy-binary-build-main.yml/badge.svg?branch=foxy)](https://github.com/ros-controls/ros2_control/actions/workflows/foxy-binary-build-main.yml?branch=foxy)
[![Foxy Semi-Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/foxy-semi-binary-build-main.yml/badge.svg?branch=foxy)](https://github.com/ros-controls/ros2_control/actions/workflows/foxy-semi-binary-build-main.yml?branch=foxy) | [Documentation](https://control.ros.org/foxy/index.html)
[API Reference](https://control.ros.org/foxy/doc/api/index.html) | [ros2_control](https://index.ros.org/p/ros2_control/#foxy) [Detailed build status](.github/workflows/README.md) diff --git a/ros2_control-not-released.foxy.repos b/ros2_control-not-released.foxy.repos deleted file mode 100644 index 56f46b6f79..0000000000 --- a/ros2_control-not-released.foxy.repos +++ /dev/null @@ -1 +0,0 @@ -repositories: diff --git a/ros2_control-not-released.galactic.repos b/ros2_control-not-released.galactic.repos deleted file mode 100644 index 56f46b6f79..0000000000 --- a/ros2_control-not-released.galactic.repos +++ /dev/null @@ -1 +0,0 @@ -repositories: diff --git a/ros2_control.foxy.repos b/ros2_control.foxy.repos deleted file mode 100644 index a52f653b54..0000000000 --- a/ros2_control.foxy.repos +++ /dev/null @@ -1,9 +0,0 @@ -repositories: - ros-controls/realtime_tools: - type: git - url: https://github.com/ros-controls/realtime_tools.git - version: foxy-devel - ros-controls/control_msgs: - type: git - url: https://github.com/ros-controls/control_msgs.git - version: foxy-devel diff --git a/ros2_control.galactic.repos b/ros2_control.galactic.repos deleted file mode 100644 index afb1cbf640..0000000000 --- a/ros2_control.galactic.repos +++ /dev/null @@ -1,9 +0,0 @@ -repositories: - ros-controls/realtime_tools: - type: git - url: https://github.com/ros-controls/realtime_tools.git - version: foxy-devel - ros-controls/control_msgs: - type: git - url: https://github.com/ros-controls/control_msgs.git - version: galactic-devel From e89fbe7804c317d182995db3e19457ead836c94f Mon Sep 17 00:00:00 2001 From: "Felix Exner (fexner)" Date: Sat, 3 Jun 2023 22:48:30 +0200 Subject: [PATCH 05/40] Added workflows, badges and repos file for ROS Iron (#1034) Since ros2_control is also released for iron, it would make sense to add workflows for iron. --- .github/workflows/README.md | 1 + .github/workflows/iron-abi-compatibility.yml | 20 ++++++++++++ .github/workflows/iron-binary-build-main.yml | 26 +++++++++++++++ .../workflows/iron-binary-build-testing.yml | 26 +++++++++++++++ .github/workflows/iron-rhel-binary-build.yml | 32 +++++++++++++++++++ .../workflows/iron-semi-binary-build-main.yml | 25 +++++++++++++++ .../iron-semi-binary-build-testing.yml | 25 +++++++++++++++ .github/workflows/iron-source-build.yml | 19 +++++++++++ .github/workflows/prerelease-check.yml | 2 ++ README.md | 1 + ros2_control-not-released.iron.repos | 1 + ros2_control.iron.repos | 9 ++++++ 12 files changed, 187 insertions(+) create mode 100644 .github/workflows/iron-abi-compatibility.yml create mode 100644 .github/workflows/iron-binary-build-main.yml create mode 100644 .github/workflows/iron-binary-build-testing.yml create mode 100644 .github/workflows/iron-rhel-binary-build.yml create mode 100644 .github/workflows/iron-semi-binary-build-main.yml create mode 100644 .github/workflows/iron-semi-binary-build-testing.yml create mode 100644 .github/workflows/iron-source-build.yml create mode 100644 ros2_control-not-released.iron.repos create mode 100644 ros2_control.iron.repos diff --git a/.github/workflows/README.md b/.github/workflows/README.md index 36caf0256f..5e8c8ef0fd 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -2,4 +2,5 @@ ROS2 Distro | Branch | Build status | Documentation | Released packages :---------: | :----: | :----------: | :-----------: | :---------------: **Rolling** | [`master`](https://github.com/ros-controls/ros2_control/tree/master) | [![Rolling Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/rolling-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_control/actions/workflows/rolling-binary-build-main.yml?branch=master)
[![Rolling Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/rolling-binary-build-testing.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_control/actions/workflows/rolling-binary-build-testing.yml?branch=master)
[![Rolling Semi-Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/rolling-semi-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_control/actions/workflows/rolling-semi-binary-build-main.yml?branch=master)
[![Rolling Semi-Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/rolling-semi-binary-build-testing.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_control/actions/workflows/rolling-semi-binary-build-testing.yml?branch=master)
[![Rolling Source Build](https://github.com/ros-controls/ros2_control/actions/workflows/rolling-source-build.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_control/actions/workflows/rolling-source-build.yml?branch=master) | [Documentation](https://control.ros.org/master/index.html)
[API Reference](https://control.ros.org/master/doc/api/index.html) | [ros2_control](https://index.ros.org/p/ros2_control/#rolling) +**Iron** | [`master`](https://github.com/ros-controls/ros2_control/tree/master) | [![Iron Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/iron-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_control/actions/workflows/iron-binary-build-main.yml?branch=master)
[![Iron Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/iron-binary-build-testing.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_control/actions/workflows/iron-binary-build-testing.yml?branch=master)
[![Iron Semi-Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/iron-semi-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_control/actions/workflows/iron-semi-binary-build-main.yml?branch=master)
[![Iron Semi-Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/iron-semi-binary-build-testing.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_control/actions/workflows/iron-semi-binary-build-testing.yml?branch=master)
[![Iron Source Build](https://github.com/ros-controls/ros2_control/actions/workflows/iron-source-build.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_control/actions/workflows/iron-source-build.yml?branch=master) | [Documentation](https://control.ros.org/master/index.html)
[API Reference](https://control.ros.org/master/doc/api/index.html) | [ros2_control](https://index.ros.org/p/ros2_control/#iron) **Humble** | [`humble`](https://github.com/ros-controls/ros2_control/tree/humble) | [![Humble Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/humble-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_control/actions/workflows/humble-binary-build-main.yml?branch=master)
[![Humble Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/humble-binary-build-testing.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_control/actions/workflows/humble-binary-build-testing.yml?branch=master)
[![Humble Semi-Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/humble-semi-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_control/actions/workflows/humble-semi-binary-build-main.yml?branch=master)
[![Humble Semi-Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/humble-semi-binary-build-testing.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_control/actions/workflows/humble-semi-binary-build-testing.yml?branch=master)
[![Humble Source Build](https://github.com/ros-controls/ros2_control/actions/workflows/humble-source-build.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_control/actions/workflows/humble-source-build.yml?branch=master) | [Documentation](https://control.ros.org/humble/index.html)
[API Reference](https://control.ros.org/humble/doc/api/index.html) | [ros2_control](https://index.ros.org/p/ros2_control/#humble) diff --git a/.github/workflows/iron-abi-compatibility.yml b/.github/workflows/iron-abi-compatibility.yml new file mode 100644 index 0000000000..f92166b0c1 --- /dev/null +++ b/.github/workflows/iron-abi-compatibility.yml @@ -0,0 +1,20 @@ +name: Iron - ABI Compatibility Check +on: + workflow_dispatch: + branches: + - master + pull_request: + branches: + - master + +jobs: + abi_check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: ros-industrial/industrial_ci@master + env: + ROS_DISTRO: iron + ROS_REPO: main + ABICHECK_URL: github:${{ github.repository }}#${{ github.base_ref }} + NOT_TEST_BUILD: true diff --git a/.github/workflows/iron-binary-build-main.yml b/.github/workflows/iron-binary-build-main.yml new file mode 100644 index 0000000000..be225cc0e1 --- /dev/null +++ b/.github/workflows/iron-binary-build-main.yml @@ -0,0 +1,26 @@ +name: Iron Binary Build - main +# author: Denis Štogl +# description: 'Build & test all dependencies from released (binary) packages.' + +on: + workflow_dispatch: + branches: + - master + pull_request: + branches: + - master + 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: iron + ros_repo: main + upstream_workspace: ros2_control-not-released.iron.repos + ref_for_scheduled_build: master diff --git a/.github/workflows/iron-binary-build-testing.yml b/.github/workflows/iron-binary-build-testing.yml new file mode 100644 index 0000000000..c44786c7e2 --- /dev/null +++ b/.github/workflows/iron-binary-build-testing.yml @@ -0,0 +1,26 @@ +name: Iron Binary Build - testing +# author: Denis Štogl +# description: 'Build & test all dependencies from released (binary) packages.' + +on: + workflow_dispatch: + branches: + - master + pull_request: + branches: + - master + 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: iron + ros_repo: testing + upstream_workspace: ros2_control-not-released.iron.repos + ref_for_scheduled_build: master diff --git a/.github/workflows/iron-rhel-binary-build.yml b/.github/workflows/iron-rhel-binary-build.yml new file mode 100644 index 0000000000..afcdf332d4 --- /dev/null +++ b/.github/workflows/iron-rhel-binary-build.yml @@ -0,0 +1,32 @@ +name: Iron RHEL Binary Build +on: + workflow_dispatch: + branches: + - iron +# pull_request: +# branches: +# - iron +# push: +# branches: +# - iron +# schedule: +# # Run every day to detect flakiness and broken dependencies +# - cron: '03 1 * * *' + +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@v3 + with: + path: src/ros2_control + - run: | + rosdep update + rosdep install -iy --from-path src/ros2_control + source /opt/ros/${{ env.ROS_DISTRO }}/setup.bash + colcon build + colcon test diff --git a/.github/workflows/iron-semi-binary-build-main.yml b/.github/workflows/iron-semi-binary-build-main.yml new file mode 100644 index 0000000000..1d72d06149 --- /dev/null +++ b/.github/workflows/iron-semi-binary-build-main.yml @@ -0,0 +1,25 @@ +name: Iron Semi-Binary Build - main +# description: 'Build & test that compiles the main dependencies from source.' + +on: + workflow_dispatch: + branches: + - master + pull_request: + branches: + - master + 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: iron + ros_repo: main + upstream_workspace: ros2_control.iron.repos + ref_for_scheduled_build: master diff --git a/.github/workflows/iron-semi-binary-build-testing.yml b/.github/workflows/iron-semi-binary-build-testing.yml new file mode 100644 index 0000000000..48707cd914 --- /dev/null +++ b/.github/workflows/iron-semi-binary-build-testing.yml @@ -0,0 +1,25 @@ +name: Iron Semi-Binary Build - testing +# description: 'Build & test that compiles the main dependencies from source.' + +on: + workflow_dispatch: + branches: + - master + pull_request: + branches: + - master + 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: iron + ros_repo: testing + upstream_workspace: ros2_control.iron.repos + ref_for_scheduled_build: master diff --git a/.github/workflows/iron-source-build.yml b/.github/workflows/iron-source-build.yml new file mode 100644 index 0000000000..31eccd1bef --- /dev/null +++ b/.github/workflows/iron-source-build.yml @@ -0,0 +1,19 @@ +name: Iron Source Build +on: + workflow_dispatch: + branches: + - master + push: + branches: + - master + 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: iron + ref: master + ros2_repo_branch: iron diff --git a/.github/workflows/prerelease-check.yml b/.github/workflows/prerelease-check.yml index 5e7326e510..eefb15ae87 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/README.md b/README.md index e5ba217d35..7981031a13 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ For more, please check the [documentation](https://ros-controls.github.io/contro ROS2 Distro | Branch | Build status | Documentation | Released packages :---------: | :----: | :----------: | :-----------: | :---------------: **Rolling** | [`master`](https://github.com/ros-controls/ros2_control/tree/master) | [![Rolling Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/rolling-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_control/actions/workflows/rolling-binary-build-main.yml?branch=master)
[![Rolling Semi-Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/rolling-semi-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_control/actions/workflows/rolling-semi-binary-build-main.yml?branch=master) | [Documentation](https://control.ros.org/master/index.html)
[API Reference](https://control.ros.org/master/doc/api/index.html) | [ros2_control](https://index.ros.org/p/ros2_control/#rolling) +**Iron** | [`master`](https://github.com/ros-controls/ros2_control/tree/master) | [![Iron Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/iron-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_control/actions/workflows/iron-binary-build-main.yml?branch=master)
[![Iron Semi-Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/iron-semi-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_control/actions/workflows/iron-semi-binary-build-main.yml?branch=master) | [Documentation](https://control.ros.org/master/index.html)
[API Reference](https://control.ros.org/master/doc/api/index.html) | [ros2_control](https://index.ros.org/p/ros2_control/#iron) **Humble** | [`humble`](https://github.com/ros-controls/ros2_control/tree/humble) | [![Humble Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/humble-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_control/actions/workflows/humble-binary-build-main.yml?branch=master)
[![Humble Semi-Binary Build](https://github.com/ros-controls/ros2_control/actions/workflows/humble-semi-binary-build-main.yml/badge.svg?branch=master)](https://github.com/ros-controls/ros2_control/actions/workflows/humble-semi-binary-build-main.yml?branch=master) | [Documentation](https://control.ros.org/humble/index.html)
[API Reference](https://control.ros.org/humble/doc/api/index.html) | [ros2_control](https://index.ros.org/p/ros2_control/#humble) [Detailed build status](.github/workflows/README.md) diff --git a/ros2_control-not-released.iron.repos b/ros2_control-not-released.iron.repos new file mode 100644 index 0000000000..56f46b6f79 --- /dev/null +++ b/ros2_control-not-released.iron.repos @@ -0,0 +1 @@ +repositories: diff --git a/ros2_control.iron.repos b/ros2_control.iron.repos new file mode 100644 index 0000000000..c93d8f4ef6 --- /dev/null +++ b/ros2_control.iron.repos @@ -0,0 +1,9 @@ +repositories: + ros-controls/realtime_tools: + type: git + url: https://github.com/ros-controls/realtime_tools.git + version: master + ros-controls/control_msgs: + type: git + url: https://github.com/ros-controls/control_msgs.git + version: master From bc8052a6d48bc786eb7ffe17cfca9af92f583332 Mon Sep 17 00:00:00 2001 From: "Dr. Denis" Date: Sun, 4 Jun 2023 20:25:36 +0200 Subject: [PATCH 06/40] [MockHardware] Enable disabling of command to simulate HW failures. (#1027) --- .../doc/mock_components_userdoc.rst | 5 ++ .../mock_components/generic_system.hpp | 2 + .../src/mock_components/generic_system.cpp | 19 ++++++ .../mock_components/test_generic_system.cpp | 67 +++++++++++++++++++ 4 files changed, 93 insertions(+) diff --git a/hardware_interface/doc/mock_components_userdoc.rst b/hardware_interface/doc/mock_components_userdoc.rst index 7fd50fc9c8..f143ea816c 100644 --- a/hardware_interface/doc/mock_components_userdoc.rst +++ b/hardware_interface/doc/mock_components_userdoc.rst @@ -27,6 +27,11 @@ Features: Parameters ,,,,,,,,,, +disable_commands (optional; boolean; default: false) + Disables mirroring commands to states. + This option is helpful to simulate an erroneous connection to the hardware when nothing breaks, but suddenly there is no feedback from a hardware interface. + Or it can help you to test your setup when the hardware is running without feedback, i.e., in open loop configuration. + mock_sensor_commands (optional; boolean; default: false) Creates fake command interfaces for faking sensor measurements with an external command. Those interfaces are usually used by a :ref:`forward controller ` to provide access from ROS-world. diff --git a/hardware_interface/include/mock_components/generic_system.hpp b/hardware_interface/include/mock_components/generic_system.hpp index 9506139c4a..c244ee1254 100644 --- a/hardware_interface/include/mock_components/generic_system.hpp +++ b/hardware_interface/include/mock_components/generic_system.hpp @@ -114,6 +114,8 @@ class HARDWARE_INTERFACE_PUBLIC GenericSystem : public hardware_interface::Syste double position_state_following_offset_; std::string custom_interface_with_following_offset_; size_t index_custom_interface_with_following_offset_; + + bool command_propagation_disabled_; }; typedef GenericSystem GenericRobot; diff --git a/hardware_interface/src/mock_components/generic_system.cpp b/hardware_interface/src/mock_components/generic_system.cpp index d490784dbd..13a5a8b679 100644 --- a/hardware_interface/src/mock_components/generic_system.cpp +++ b/hardware_interface/src/mock_components/generic_system.cpp @@ -119,6 +119,18 @@ CallbackReturn GenericSystem::on_init(const hardware_interface::HardwareInfo & i } } + // check if there is parameter that disables commands + // this way we simulate disconnected driver + it = info_.hardware_parameters.find("disable_commands"); + if (it != info.hardware_parameters.end()) + { + command_propagation_disabled_ = hardware_interface::parse_bool(it->second); + } + else + { + command_propagation_disabled_ = false; + } + // process parameters about state following position_state_following_offset_ = 0.0; custom_interface_with_following_offset_ = ""; @@ -359,6 +371,13 @@ std::vector GenericSystem::export_command_ return_type GenericSystem::read(const rclcpp::Time & /*time*/, const rclcpp::Duration & /*period*/) { + if (command_propagation_disabled_) + { + RCUTILS_LOG_WARN_NAMED( + "mock_generic_system", "Command propagation is disabled - no values will be returned!"); + return return_type::OK; + } + auto mirror_command_to_state = [](auto & states_, auto commands_, size_t start_index = 0) { for (size_t i = start_index; i < states_.size(); ++i) diff --git a/hardware_interface/test/mock_components/test_generic_system.cpp b/hardware_interface/test/mock_components/test_generic_system.cpp index e82d7d1fb2..8e78ade7fb 100644 --- a/hardware_interface/test/mock_components/test_generic_system.cpp +++ b/hardware_interface/test/mock_components/test_generic_system.cpp @@ -483,6 +483,24 @@ class TestGenericSystem : public ::testing::Test )"; + + disabled_commands_ = + R"( + + + fake_components/GenericSystem + True + + + + + + 3.45 + + + + +)"; } std::string hardware_robot_2dof_; @@ -503,6 +521,7 @@ class TestGenericSystem : public ::testing::Test std::string valid_urdf_ros2_control_system_robot_with_gpio_mock_command_True_; std::string sensor_with_initial_value_; std::string gpio_with_initial_value_; + std::string disabled_commands_; }; // Forward declaration @@ -1604,3 +1623,51 @@ TEST_F(TestGenericSystem, gpio_with_initial_value) ASSERT_EQ(1, state.get_value()); } + +TEST_F(TestGenericSystem, disabled_commands_flag_is_active) +{ + auto urdf = + ros2_control_test_assets::urdf_head + disabled_commands_ + ros2_control_test_assets::urdf_tail; + TestableResourceManager rm(urdf); + // Activate components to get all interfaces available + activate_components(rm); + + // Check interfaces + EXPECT_EQ(1u, rm.system_components_size()); + ASSERT_EQ(2u, rm.state_interface_keys().size()); + EXPECT_TRUE(rm.state_interface_exists("joint1/position")); + EXPECT_TRUE(rm.state_interface_exists("joint1/velocity")); + + ASSERT_EQ(2u, rm.command_interface_keys().size()); + EXPECT_TRUE(rm.command_interface_exists("joint1/position")); + EXPECT_TRUE(rm.command_interface_exists("joint1/velocity")); + + // Check initial values + hardware_interface::LoanedStateInterface j1p_s = rm.claim_state_interface("joint1/position"); + hardware_interface::LoanedStateInterface j1v_s = rm.claim_state_interface("joint1/velocity"); + hardware_interface::LoanedCommandInterface j1p_c = rm.claim_command_interface("joint1/position"); + + ASSERT_EQ(3.45, j1p_s.get_value()); + ASSERT_EQ(0.0, j1v_s.get_value()); + ASSERT_TRUE(std::isnan(j1p_c.get_value())); + + // set some new values in commands + j1p_c.set_value(0.11); + + // State values should not be changed + ASSERT_EQ(3.45, j1p_s.get_value()); + ASSERT_EQ(0.0, j1v_s.get_value()); + ASSERT_EQ(0.11, j1p_c.get_value()); + + // write() does not change values + rm.write(TIME, PERIOD); + ASSERT_EQ(3.45, j1p_s.get_value()); + ASSERT_EQ(0.0, j1v_s.get_value()); + ASSERT_EQ(0.11, j1p_c.get_value()); + + // read() also does not change values + rm.read(TIME, PERIOD); + ASSERT_EQ(3.45, j1p_s.get_value()); + ASSERT_EQ(0.0, j1v_s.get_value()); + ASSERT_EQ(0.11, j1p_c.get_value()); +} From d87ab20417dbf9400bcbf9f012fe4e4b479f8dff Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Jun 2023 15:49:47 +0200 Subject: [PATCH 07/40] Bump uesteibar/reviewer-lottery from 2 to 3 (#1048) Bumps [uesteibar/reviewer-lottery](https://github.com/uesteibar/reviewer-lottery) from 2 to 3. - [Release notes](https://github.com/uesteibar/reviewer-lottery/releases) - [Commits](https://github.com/uesteibar/reviewer-lottery/compare/v2...v3) --- updated-dependencies: - dependency-name: uesteibar/reviewer-lottery 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/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 50ad772ab2f57225a37ab2df3adf1baa384ca8a8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Jun 2023 15:50:10 +0200 Subject: [PATCH 08/40] Bump ros-tooling/action-ros-ci from 0.3.0 to 0.3.2 (#1047) Bumps [ros-tooling/action-ros-ci](https://github.com/ros-tooling/action-ros-ci) from 0.3.0 to 0.3.2. - [Release notes](https://github.com/ros-tooling/action-ros-ci/releases) - [Commits](https://github.com/ros-tooling/action-ros-ci/compare/0.3.0...0.3.2) --- 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.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 1df5175f10..97f5b4373b 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 46b998c326..faadc4e9d9 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.0 + - uses: ros-tooling/action-ros-ci@0.3.2 with: target-ros2-distro: ${{ inputs.ros_distro }} # build all packages listed in the meta package From d299208e8e2c6b927adbf27391f68aced974892c Mon Sep 17 00:00:00 2001 From: Manuel Muth Date: Wed, 7 Jun 2023 23:12:26 +0200 Subject: [PATCH 09/40] =?UTF-8?q?[CM]=20Use=20`robot=5Fdescription`=20topi?= =?UTF-8?q?c=20instead=20of=20parameter=20and=20don't=20crash=20on=20empty?= =?UTF-8?q?=20URDF=20=F0=9F=A6=BF=20(#940)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * on startup wait for robot description, however allow receiving later --------- Co-authored-by: Dr. Denis --- controller_manager/CMakeLists.txt | 11 +++ .../controller_manager/controller_manager.hpp | 8 ++ controller_manager/package.xml | 1 + controller_manager/src/controller_manager.cpp | 58 +++++++++++- .../test/controller_manager_test_common.hpp | 57 +++++++++--- .../test_controller_manager_urdf_passing.cpp | 88 +++++++++++++++++++ .../doc/mock_components_userdoc.rst | 2 +- .../hardware_interface/resource_manager.hpp | 12 +++ hardware_interface/src/resource_manager.cpp | 3 + .../test/test_resource_manager.cpp | 28 ++++++ 10 files changed, 253 insertions(+), 15 deletions(-) create mode 100644 controller_manager/test/test_controller_manager_urdf_passing.cpp diff --git a/controller_manager/CMakeLists.txt b/controller_manager/CMakeLists.txt index 1d9b062efa..1118856e48 100644 --- a/controller_manager/CMakeLists.txt +++ b/controller_manager/CMakeLists.txt @@ -14,6 +14,7 @@ set(THIS_PACKAGE_INCLUDE_DEPENDS pluginlib rclcpp realtime_tools + std_msgs ) find_package(ament_cmake REQUIRED) @@ -143,6 +144,16 @@ if(BUILD_TESTING) ament_target_dependencies(test_controller_manager_srvs controller_manager_msgs ) + ament_add_gmock(test_controller_manager_urdf_passing + test/test_controller_manager_urdf_passing.cpp + ) + target_link_libraries(test_controller_manager_urdf_passing + controller_manager + ros2_control_test_assets::ros2_control_test_assets + ) + ament_target_dependencies(test_controller_manager_urdf_passing + controller_manager_msgs + ) add_library(test_controller_with_interfaces SHARED test/test_controller_with_interfaces/test_controller_with_interfaces.cpp diff --git a/controller_manager/include/controller_manager/controller_manager.hpp b/controller_manager/include/controller_manager/controller_manager.hpp index 582cbc5f24..631d5173aa 100644 --- a/controller_manager/include/controller_manager/controller_manager.hpp +++ b/controller_manager/include/controller_manager/controller_manager.hpp @@ -51,6 +51,8 @@ #include "rclcpp/node_interfaces/node_logging_interface.hpp" #include "rclcpp/node_interfaces/node_parameters_interface.hpp" #include "rclcpp/parameter.hpp" +#include "rclcpp/rclcpp.hpp" +#include "std_msgs/msg/string.hpp" namespace controller_manager { @@ -82,6 +84,9 @@ class ControllerManager : public rclcpp::Node CONTROLLER_MANAGER_PUBLIC virtual ~ControllerManager() = default; + CONTROLLER_MANAGER_PUBLIC + void robot_description_callback(const std_msgs::msg::String & msg); + CONTROLLER_MANAGER_PUBLIC void init_resource_manager(const std::string & robot_description); @@ -316,6 +321,7 @@ class ControllerManager : public rclcpp::Node std::vector get_controller_names(); std::pair split_command_interface( const std::string & command_interface); + void subscribe_to_robot_description_topic(); /** * Clear request lists used when switching controllers. The lists are shared between "callback" @@ -504,6 +510,8 @@ class ControllerManager : public rclcpp::Node std::vector activate_command_interface_request_, deactivate_command_interface_request_; + rclcpp::Subscription::SharedPtr robot_description_subscription_; + struct SwitchParams { bool do_switch = {false}; diff --git a/controller_manager/package.xml b/controller_manager/package.xml index 246bf5f9d4..c9dd319577 100644 --- a/controller_manager/package.xml +++ b/controller_manager/package.xml @@ -26,6 +26,7 @@ ros2_control_test_assets ros2param ros2run + std_msgs ament_cmake_gmock ros2_control_test_assets diff --git a/controller_manager/src/controller_manager.cpp b/controller_manager/src/controller_manager.cpp index 6b6efb0a5c..69a3bbb5f3 100644 --- a/controller_manager/src/controller_manager.cpp +++ b/controller_manager/src/controller_manager.cpp @@ -151,13 +151,20 @@ ControllerManager::ControllerManager( } std::string robot_description = ""; + // TODO(destogl): remove support at the end of 2023 get_parameter("robot_description", robot_description); if (robot_description.empty()) { - throw std::runtime_error("Unable to initialize resource manager, no robot description found."); + subscribe_to_robot_description_topic(); + } + else + { + RCLCPP_WARN( + get_logger(), + "[Deprecated] Passing the robot description parameter directly to the control_manager node " + "is deprecated. Use '~/robot_description' topic from 'robot_state_publisher' instead."); + init_resource_manager(robot_description); } - - init_resource_manager(robot_description); diagnostics_updater_.setHardwareID("ros2_control"); diagnostics_updater_.add( @@ -183,12 +190,55 @@ ControllerManager::ControllerManager( { RCLCPP_WARN(get_logger(), "'update_rate' parameter not set, using default value."); } + + subscribe_to_robot_description_topic(); + diagnostics_updater_.setHardwareID("ros2_control"); diagnostics_updater_.add( "Controllers Activity", this, &ControllerManager::controller_activity_diagnostic_callback); init_services(); } +void ControllerManager::subscribe_to_robot_description_topic() +{ + // set QoS to transient local to get messages that have already been published + // (if robot state publisher starts before controller manager) + RCLCPP_INFO( + get_logger(), "Subscribing to '~/robot_description' topic for robot description file."); + robot_description_subscription_ = create_subscription( + "~/robot_description", rclcpp::QoS(1).transient_local(), + std::bind(&ControllerManager::robot_description_callback, this, std::placeholders::_1)); +} + +void ControllerManager::robot_description_callback(const std_msgs::msg::String & robot_description) +{ + RCLCPP_INFO(get_logger(), "Received robot description file."); + RCLCPP_DEBUG( + get_logger(), "'Content of robot description file: %s", robot_description.data.c_str()); + // TODO(Manuel): errors should probably be caught since we don't want controller_manager node + // to die if a non valid urdf is passed. However, should maybe be fine tuned. + try + { + if (resource_manager_->is_urdf_already_loaded()) + { + RCLCPP_WARN( + get_logger(), + "ResourceManager has already loaded an urdf file. Ignoring attempt to reload a robot " + "description file."); + return; + } + init_resource_manager(robot_description.data.c_str()); + } + catch (std::runtime_error & e) + { + RCLCPP_ERROR_STREAM( + get_logger(), + "The published robot description file (urdf) seems not to be genuine. The following error " + "was caught:" + << e.what()); + } +} + void ControllerManager::init_resource_manager(const std::string & robot_description) { // TODO(destogl): manage this when there is an error - CM should not die because URDF is wrong... @@ -199,7 +249,7 @@ void ControllerManager::init_resource_manager(const std::string & robot_descript std::vector configure_components_on_start = std::vector({}); if (get_parameter("configure_components_on_start", configure_components_on_start)) { - RCLCPP_WARN_STREAM( + RCLCPP_WARN( get_logger(), "[Deprecated]: Usage of parameter \"configure_components_on_start\" is deprecated. Use " "hardware_spawner instead."); diff --git a/controller_manager/test/controller_manager_test_common.hpp b/controller_manager/test/controller_manager_test_common.hpp index b6e6acac0e..78c3fcb06b 100644 --- a/controller_manager/test/controller_manager_test_common.hpp +++ b/controller_manager/test/controller_manager_test_common.hpp @@ -22,15 +22,20 @@ #include #include #include +#include #include #include "controller_interface/controller_interface.hpp" #include "controller_manager/controller_manager.hpp" +#include "controller_manager_msgs/srv/list_hardware_interfaces.hpp" #include "controller_manager_msgs/srv/switch_controller.hpp" +#include "rclcpp/rclcpp.hpp" #include "rclcpp/utilities.hpp" +#include "std_msgs/msg/string.hpp" + #include "ros2_control_test_assets/descriptions.hpp" #include "test_controller_failed_init/test_controller_failed_init.hpp" @@ -60,21 +65,51 @@ template class ControllerManagerFixture : public ::testing::Test { public: + explicit ControllerManagerFixture( + const std::string & robot_description = ros2_control_test_assets::minimal_robot_urdf, + const bool & pass_urdf_as_parameter = false) + : robot_description_(robot_description), pass_urdf_as_parameter_(pass_urdf_as_parameter) + { + executor_ = std::make_shared(); + // We want to be able to create a ResourceManager where no urdf file has been passed to + if (robot_description_.empty()) + { + cm_ = std::make_shared( + std::make_unique(), executor_, TEST_CM_NAME); + } + else + { + // can be removed later, needed if we want to have the deprecated way of passing the robot + // description file to the controller manager covered by tests + if (pass_urdf_as_parameter_) + { + cm_ = std::make_shared( + std::make_unique(robot_description_, true, true), + executor_, TEST_CM_NAME); + } + else + { + // TODO(Manuel) : passing via topic not working in test setup, tested cm does + // not receive msg. Have to check this... + + // this is just a workaround to skip passing + cm_ = std::make_shared( + std::make_unique(), executor_, TEST_CM_NAME); + // mimic topic call + auto msg = std_msgs::msg::String(); + msg.data = robot_description_; + cm_->robot_description_callback(msg); + } + } + } + static void SetUpTestCase() { rclcpp::init(0, nullptr); } static void TearDownTestCase() { rclcpp::shutdown(); } - void SetUp() - { - executor_ = std::make_shared(); - cm_ = std::make_shared( - std::make_unique( - ros2_control_test_assets::minimal_robot_urdf, true, true), - executor_, TEST_CM_NAME); - run_updater_ = false; - } + void SetUp() override { run_updater_ = false; } - void TearDown() { stopCmUpdater(); } + void TearDown() override { stopCmUpdater(); } void startCmUpdater() { @@ -120,6 +155,8 @@ class ControllerManagerFixture : public ::testing::Test std::thread updater_; bool run_updater_; + const std::string robot_description_; + const bool pass_urdf_as_parameter_; }; class TestControllerManagerSrvs diff --git a/controller_manager/test/test_controller_manager_urdf_passing.cpp b/controller_manager/test/test_controller_manager_urdf_passing.cpp new file mode 100644 index 0000000000..102cbdfbd4 --- /dev/null +++ b/controller_manager/test/test_controller_manager_urdf_passing.cpp @@ -0,0 +1,88 @@ +// Copyright 2020 Open Source Robotics Foundation, Inc. +// +// 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 +#include +#include + +#include "controller_manager/controller_manager.hpp" +#include "controller_manager_test_common.hpp" + +#include "ros2_control_test_assets/descriptions.hpp" + +class TestControllerManagerWithTestableCM; + +class TestableControllerManager : public controller_manager::ControllerManager +{ + friend TestControllerManagerWithTestableCM; + + FRIEND_TEST(TestControllerManagerWithTestableCM, initial_no_load_urdf_called); + FRIEND_TEST(TestControllerManagerWithTestableCM, load_urdf_called_after_callback); + FRIEND_TEST(TestControllerManagerWithTestableCM, load_urdf_called_after_invalid_urdf_passed); + FRIEND_TEST(TestControllerManagerWithTestableCM, load_urdf_called_after_callback); + FRIEND_TEST(TestControllerManagerWithTestableCM, load_urdf_called_after_callback); + +public: + TestableControllerManager( + std::unique_ptr resource_manager, + std::shared_ptr executor, + const std::string & manager_node_name = "controller_manager", + const std::string & namespace_ = "") + : controller_manager::ControllerManager( + std::move(resource_manager), executor, manager_node_name, namespace_) + { + } +}; + +class TestControllerManagerWithTestableCM +: public ControllerManagerFixture, + public testing::WithParamInterface +{ +public: + // create cm with no urdf + TestControllerManagerWithTestableCM() + : ControllerManagerFixture("", false) + { + } +}; + +TEST_P(TestControllerManagerWithTestableCM, initial_no_load_urdf_called) +{ + ASSERT_FALSE(cm_->resource_manager_->is_urdf_already_loaded()); +} + +TEST_P(TestControllerManagerWithTestableCM, load_urdf_called_after_callback) +{ + ASSERT_FALSE(cm_->resource_manager_->is_urdf_already_loaded()); + // mimic callback + auto msg = std_msgs::msg::String(); + msg.data = ros2_control_test_assets::minimal_robot_urdf; + cm_->robot_description_callback(msg); + ASSERT_TRUE(cm_->resource_manager_->is_urdf_already_loaded()); +} + +TEST_P(TestControllerManagerWithTestableCM, load_urdf_called_after_invalid_urdf_passed) +{ + ASSERT_FALSE(cm_->resource_manager_->is_urdf_already_loaded()); + // mimic callback + auto msg = std_msgs::msg::String(); + msg.data = ros2_control_test_assets::minimal_robot_missing_command_keys_urdf; + cm_->robot_description_callback(msg); + ASSERT_TRUE(cm_->resource_manager_->is_urdf_already_loaded()); +} + +INSTANTIATE_TEST_SUITE_P( + test_best_effort, TestControllerManagerWithTestableCM, testing::Values(best_effort)); diff --git a/hardware_interface/doc/mock_components_userdoc.rst b/hardware_interface/doc/mock_components_userdoc.rst index f143ea816c..573037a58d 100644 --- a/hardware_interface/doc/mock_components_userdoc.rst +++ b/hardware_interface/doc/mock_components_userdoc.rst @@ -28,7 +28,7 @@ Parameters ,,,,,,,,,, disable_commands (optional; boolean; default: false) - Disables mirroring commands to states. + Disables mirroring commands to states. This option is helpful to simulate an erroneous connection to the hardware when nothing breaks, but suddenly there is no feedback from a hardware interface. Or it can help you to test your setup when the hardware is running without feedback, i.e., in open loop configuration. diff --git a/hardware_interface/include/hardware_interface/resource_manager.hpp b/hardware_interface/include/hardware_interface/resource_manager.hpp index 4d2f995756..4ea3ae9a5f 100644 --- a/hardware_interface/include/hardware_interface/resource_manager.hpp +++ b/hardware_interface/include/hardware_interface/resource_manager.hpp @@ -90,6 +90,16 @@ class HARDWARE_INTERFACE_PUBLIC ResourceManager */ void load_urdf(const std::string & urdf, bool validate_interfaces = true); + /** + * @brief if the resource manager load_urdf(...) function has been called this returns true. + * We want to permit to load the urdf later on but we currently don't want to permit multiple + * calls to load_urdf (reloading/loading different urdf). + * + * @return true if resource manager's load_urdf() has been already called. + * @return false if resource manager's load_urdf() has not been yet called. + */ + bool is_urdf_already_loaded() const; + /// Claim a state interface given its key. /** * The resource is claimed as long as being in scope. @@ -413,6 +423,8 @@ class HARDWARE_INTERFACE_PUBLIC ResourceManager // Structure to store read and write status so it is not initialized in the real-time loop HardwareReadWriteStatus read_write_status; + + bool is_urdf_loaded__ = false; }; } // namespace hardware_interface diff --git a/hardware_interface/src/resource_manager.cpp b/hardware_interface/src/resource_manager.cpp index 2e23c34d94..f32d24f890 100644 --- a/hardware_interface/src/resource_manager.cpp +++ b/hardware_interface/src/resource_manager.cpp @@ -703,6 +703,7 @@ ResourceManager::ResourceManager( // CM API: Called in "callback/slow"-thread void ResourceManager::load_urdf(const std::string & urdf, bool validate_interfaces) { + is_urdf_loaded__ = true; const std::string system_type = "system"; const std::string sensor_type = "sensor"; const std::string actuator_type = "actuator"; @@ -741,6 +742,8 @@ void ResourceManager::load_urdf(const std::string & urdf, bool validate_interfac resource_storage_->systems_.size()); } +bool ResourceManager::is_urdf_already_loaded() const { return is_urdf_loaded__; } + // CM API: Called in "update"-thread LoanedStateInterface ResourceManager::claim_state_interface(const std::string & key) { diff --git a/hardware_interface/test/test_resource_manager.cpp b/hardware_interface/test/test_resource_manager.cpp index e1b9e240e7..aedf2b862d 100644 --- a/hardware_interface/test/test_resource_manager.cpp +++ b/hardware_interface/test/test_resource_manager.cpp @@ -212,6 +212,34 @@ TEST_F(ResourceManagerTest, initialization_with_urdf_unclaimed) } } +TEST_F(ResourceManagerTest, no_load_urdf_function_called) +{ + TestableResourceManager rm; + ASSERT_FALSE(rm.is_urdf_already_loaded()); +} + +TEST_F(ResourceManagerTest, load_urdf_called_if_urdf_is_invalid) +{ + TestableResourceManager rm; + EXPECT_THROW( + rm.load_urdf(ros2_control_test_assets::minimal_robot_missing_state_keys_urdf), std::exception); + ASSERT_TRUE(rm.is_urdf_already_loaded()); +} + +TEST_F(ResourceManagerTest, load_urdf_called_if_urdf_is_valid) +{ + TestableResourceManager rm(ros2_control_test_assets::minimal_robot_urdf); + ASSERT_TRUE(rm.is_urdf_already_loaded()); +} + +TEST_F(ResourceManagerTest, can_load_urdf_later) +{ + TestableResourceManager rm; + ASSERT_FALSE(rm.is_urdf_already_loaded()); + rm.load_urdf(ros2_control_test_assets::minimal_robot_urdf); + ASSERT_TRUE(rm.is_urdf_already_loaded()); +} + TEST_F(ResourceManagerTest, resource_claiming) { TestableResourceManager rm(ros2_control_test_assets::minimal_robot_urdf); From 1b83a5b5c06fa491a96f67ac338a0c16a8112987 Mon Sep 17 00:00:00 2001 From: gwalck Date: Tue, 13 Jun 2023 16:57:37 +0200 Subject: [PATCH 10/40] Add -Wconversion flag to protect future developments (#1053) --- controller_interface/CMakeLists.txt | 2 +- controller_manager/CMakeLists.txt | 2 +- hardware_interface/CMakeLists.txt | 2 +- hardware_interface/src/component_parser.cpp | 6 ++++-- joint_limits/CMakeLists.txt | 2 +- transmission_interface/CMakeLists.txt | 2 +- transmission_interface/test/random_generator_utils.hpp | 2 +- 7 files changed, 10 insertions(+), 8 deletions(-) diff --git a/controller_interface/CMakeLists.txt b/controller_interface/CMakeLists.txt index 034556d19f..88a54d5c7a 100644 --- a/controller_interface/CMakeLists.txt +++ b/controller_interface/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.16) project(controller_interface 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/controller_manager/CMakeLists.txt b/controller_manager/CMakeLists.txt index 1118856e48..77ba823e1f 100644 --- a/controller_manager/CMakeLists.txt +++ b/controller_manager/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.16) project(controller_manager 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/hardware_interface/CMakeLists.txt b/hardware_interface/CMakeLists.txt index 77eec3ec86..6548d6186c 100644 --- a/hardware_interface/CMakeLists.txt +++ b/hardware_interface/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.16) project(hardware_interface 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/hardware_interface/src/component_parser.cpp b/hardware_interface/src/component_parser.cpp index 1338489a07..8e9b6bf16b 100644 --- a/hardware_interface/src/component_parser.cpp +++ b/hardware_interface/src/component_parser.cpp @@ -367,7 +367,8 @@ ComponentInfo parse_complex_component_from_xml(const tinyxml2::XMLElement * comp component.command_interfaces.push_back(parse_interfaces_from_xml(command_interfaces_it)); component.command_interfaces.back().data_type = parse_data_type_attribute(command_interfaces_it); - component.command_interfaces.back().size = parse_size_attribute(command_interfaces_it); + component.command_interfaces.back().size = + static_cast(parse_size_attribute(command_interfaces_it)); command_interfaces_it = command_interfaces_it->NextSiblingElement(kCommandInterfaceTag); } @@ -377,7 +378,8 @@ ComponentInfo parse_complex_component_from_xml(const tinyxml2::XMLElement * comp { component.state_interfaces.push_back(parse_interfaces_from_xml(state_interfaces_it)); component.state_interfaces.back().data_type = parse_data_type_attribute(state_interfaces_it); - component.state_interfaces.back().size = parse_size_attribute(state_interfaces_it); + component.state_interfaces.back().size = + static_cast(parse_size_attribute(state_interfaces_it)); state_interfaces_it = state_interfaces_it->NextSiblingElement(kStateInterfaceTag); } diff --git a/joint_limits/CMakeLists.txt b/joint_limits/CMakeLists.txt index 9ec9221220..82467514a3 100644 --- a/joint_limits/CMakeLists.txt +++ b/joint_limits/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.16) project(joint_limits 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/transmission_interface/CMakeLists.txt b/transmission_interface/CMakeLists.txt index 8ae2cc224c..d4674366e9 100644 --- a/transmission_interface/CMakeLists.txt +++ b/transmission_interface/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.16) project(transmission_interface 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/transmission_interface/test/random_generator_utils.hpp b/transmission_interface/test/random_generator_utils.hpp index e6088f1b2f..fbacd1ba3b 100644 --- a/transmission_interface/test/random_generator_utils.hpp +++ b/transmission_interface/test/random_generator_utils.hpp @@ -31,7 +31,7 @@ struct RandomDoubleGenerator public: RandomDoubleGenerator(double min_val, double max_val) : min_val_(min_val), max_val_(max_val) { - srand(time(nullptr)); + srand(static_cast(time(nullptr))); } double operator()() { From af6d8e2c9af76710bb1e4a68ebf5636b034576d3 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Wed, 14 Jun 2023 19:28:39 +0100 Subject: [PATCH 11/40] Update changelogs --- controller_interface/CHANGELOG.rst | 6 ++++++ controller_manager/CHANGELOG.rst | 9 +++++++++ controller_manager_msgs/CHANGELOG.rst | 3 +++ hardware_interface/CHANGELOG.rst | 11 +++++++++++ joint_limits/CHANGELOG.rst | 6 ++++++ ros2_control/CHANGELOG.rst | 3 +++ ros2_control_test_assets/CHANGELOG.rst | 5 +++++ ros2controlcli/CHANGELOG.rst | 5 +++++ rqt_controller_manager/CHANGELOG.rst | 3 +++ transmission_interface/CHANGELOG.rst | 6 ++++++ 10 files changed, 57 insertions(+) diff --git a/controller_interface/CHANGELOG.rst b/controller_interface/CHANGELOG.rst index 29f69150d2..a63c8594b2 100644 --- a/controller_interface/CHANGELOG.rst +++ b/controller_interface/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package controller_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add -Wconversion flag to protect future developments (`#1053 `_) +* enable ReflowComments to also use ColumnLimit on comments (`#1037 `_) +* Contributors: Sai Kishor Kothakota, gwalck + 3.13.0 (2023-05-18) ------------------- diff --git a/controller_manager/CHANGELOG.rst b/controller_manager/CHANGELOG.rst index d663cd3b32..9b5106c794 100644 --- a/controller_manager/CHANGELOG.rst +++ b/controller_manager/CHANGELOG.rst @@ -2,6 +2,15 @@ Changelog for package controller_manager ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add -Wconversion flag to protect future developments (`#1053 `_) +* [CM] Use `robot_description` topic instead of parameter and don't crash on empty URDF 🦿 (`#940 `_) +* enable ReflowComments to also use ColumnLimit on comments (`#1037 `_) +* Docs: Use branch name substitution for all links (`#1031 `_) +* Add text to assertions references (`#1023 `_) +* Contributors: Christoph Fröhlich, Felix Exner (fexner), Manuel Muth, Sai Kishor Kothakota, gwalck + 3.13.0 (2023-05-18) ------------------- * Add class for thread management of async hw interfaces (`#981 `_) diff --git a/controller_manager_msgs/CHANGELOG.rst b/controller_manager_msgs/CHANGELOG.rst index 66c0285a44..92f836c269 100644 --- a/controller_manager_msgs/CHANGELOG.rst +++ b/controller_manager_msgs/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package controller_manager_msgs ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.13.0 (2023-05-18) ------------------- diff --git a/hardware_interface/CHANGELOG.rst b/hardware_interface/CHANGELOG.rst index 245ae211e5..e3c52c0e1c 100644 --- a/hardware_interface/CHANGELOG.rst +++ b/hardware_interface/CHANGELOG.rst @@ -2,6 +2,17 @@ Changelog for package hardware_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add -Wconversion flag to protect future developments (`#1053 `_) +* [CM] Use `robot_description` topic instead of parameter and don't crash on empty URDF 🦿 (`#940 `_) +* [MockHardware] Enable disabling of command to simulate HW failures. (`#1027 `_) +* enable ReflowComments to also use ColumnLimit on comments (`#1037 `_) +* Docs: Use branch name substitution for all links (`#1031 `_) +* [URDF Parser] Allow empty urdf tag, e.g., parameter (`#1017 `_) +* Use consequently 'mock' instead of 'fake'. (`#1026 `_) +* Contributors: Christoph Fröhlich, Dr. Denis, Felix Exner (fexner), Manuel Muth, Sai Kishor Kothakota, gwalck + 3.13.0 (2023-05-18) ------------------- * Add class for thread management of async hw interfaces (`#981 `_) diff --git a/joint_limits/CHANGELOG.rst b/joint_limits/CHANGELOG.rst index 211828a28b..e713a772bf 100644 --- a/joint_limits/CHANGELOG.rst +++ b/joint_limits/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package joint_limits ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add -Wconversion flag to protect future developments (`#1053 `_) +* enable ReflowComments to also use ColumnLimit on comments (`#1037 `_) +* Contributors: Sai Kishor Kothakota, gwalck + 3.13.0 (2023-05-18) ------------------- diff --git a/ros2_control/CHANGELOG.rst b/ros2_control/CHANGELOG.rst index d6e3effbb0..bf2fbc3b8a 100644 --- a/ros2_control/CHANGELOG.rst +++ b/ros2_control/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_control ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.13.0 (2023-05-18) ------------------- diff --git a/ros2_control_test_assets/CHANGELOG.rst b/ros2_control_test_assets/CHANGELOG.rst index e5b824a921..040695bdb4 100644 --- a/ros2_control_test_assets/CHANGELOG.rst +++ b/ros2_control_test_assets/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package ros2_control_test_assets ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* [URDF Parser] Allow empty urdf tag, e.g., parameter (`#1017 `_) +* Contributors: Felix Exner (fexner) + 3.13.0 (2023-05-18) ------------------- diff --git a/ros2controlcli/CHANGELOG.rst b/ros2controlcli/CHANGELOG.rst index 0af749a91a..fecf6f29fb 100644 --- a/ros2controlcli/CHANGELOG.rst +++ b/ros2controlcli/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package ros2controlcli ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Docs: Use branch name substitution for all links (`#1031 `_) +* Contributors: Christoph Fröhlich + 3.13.0 (2023-05-18) ------------------- * Fix github links on control.ros.org (`#1019 `_) diff --git a/rqt_controller_manager/CHANGELOG.rst b/rqt_controller_manager/CHANGELOG.rst index f57aa7fcbd..a2f416e9eb 100644 --- a/rqt_controller_manager/CHANGELOG.rst +++ b/rqt_controller_manager/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package rqt_controller_manager ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.13.0 (2023-05-18) ------------------- diff --git a/transmission_interface/CHANGELOG.rst b/transmission_interface/CHANGELOG.rst index 7dded27cc1..537ccf36ac 100644 --- a/transmission_interface/CHANGELOG.rst +++ b/transmission_interface/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package transmission_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add -Wconversion flag to protect future developments (`#1053 `_) +* enable ReflowComments to also use ColumnLimit on comments (`#1037 `_) +* Contributors: Sai Kishor Kothakota, gwalck + 3.13.0 (2023-05-18) ------------------- From 99deef8b0e7eb96eafc88d6be2d017d43c1a95df Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Wed, 14 Jun 2023 19:29:21 +0100 Subject: [PATCH 12/40] 3.14.0 --- controller_interface/CHANGELOG.rst | 4 ++-- controller_interface/package.xml | 2 +- controller_manager/CHANGELOG.rst | 4 ++-- controller_manager/package.xml | 2 +- controller_manager_msgs/CHANGELOG.rst | 4 ++-- controller_manager_msgs/package.xml | 2 +- hardware_interface/CHANGELOG.rst | 4 ++-- hardware_interface/package.xml | 2 +- joint_limits/CHANGELOG.rst | 4 ++-- joint_limits/package.xml | 2 +- ros2_control/CHANGELOG.rst | 4 ++-- ros2_control/package.xml | 2 +- ros2_control_test_assets/CHANGELOG.rst | 4 ++-- ros2_control_test_assets/package.xml | 2 +- ros2controlcli/CHANGELOG.rst | 4 ++-- ros2controlcli/package.xml | 2 +- ros2controlcli/setup.py | 2 +- rqt_controller_manager/CHANGELOG.rst | 4 ++-- rqt_controller_manager/package.xml | 2 +- rqt_controller_manager/setup.py | 2 +- transmission_interface/CHANGELOG.rst | 4 ++-- transmission_interface/package.xml | 2 +- 22 files changed, 32 insertions(+), 32 deletions(-) diff --git a/controller_interface/CHANGELOG.rst b/controller_interface/CHANGELOG.rst index a63c8594b2..d938aa8234 100644 --- a/controller_interface/CHANGELOG.rst +++ b/controller_interface/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package controller_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.14.0 (2023-06-14) +------------------- * Add -Wconversion flag to protect future developments (`#1053 `_) * enable ReflowComments to also use ColumnLimit on comments (`#1037 `_) * Contributors: Sai Kishor Kothakota, gwalck diff --git a/controller_interface/package.xml b/controller_interface/package.xml index f20eccd9eb..aedd5cf2f5 100644 --- a/controller_interface/package.xml +++ b/controller_interface/package.xml @@ -2,7 +2,7 @@ controller_interface - 3.13.0 + 3.14.0 Description of controller_interface Bence Magyar Denis Štogl diff --git a/controller_manager/CHANGELOG.rst b/controller_manager/CHANGELOG.rst index 9b5106c794..3a3447e908 100644 --- a/controller_manager/CHANGELOG.rst +++ b/controller_manager/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package controller_manager ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.14.0 (2023-06-14) +------------------- * Add -Wconversion flag to protect future developments (`#1053 `_) * [CM] Use `robot_description` topic instead of parameter and don't crash on empty URDF 🦿 (`#940 `_) * enable ReflowComments to also use ColumnLimit on comments (`#1037 `_) diff --git a/controller_manager/package.xml b/controller_manager/package.xml index c9dd319577..c08f12cb16 100644 --- a/controller_manager/package.xml +++ b/controller_manager/package.xml @@ -2,7 +2,7 @@ controller_manager - 3.13.0 + 3.14.0 Description of controller_manager Bence Magyar Denis Štogl diff --git a/controller_manager_msgs/CHANGELOG.rst b/controller_manager_msgs/CHANGELOG.rst index 92f836c269..d0dd4d6233 100644 --- a/controller_manager_msgs/CHANGELOG.rst +++ b/controller_manager_msgs/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package controller_manager_msgs ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.14.0 (2023-06-14) +------------------- 3.13.0 (2023-05-18) ------------------- diff --git a/controller_manager_msgs/package.xml b/controller_manager_msgs/package.xml index 38b24b6b26..186ecab6c4 100644 --- a/controller_manager_msgs/package.xml +++ b/controller_manager_msgs/package.xml @@ -2,7 +2,7 @@ controller_manager_msgs - 3.13.0 + 3.14.0 Messages and services for the controller manager. Bence Magyar Denis Štogl diff --git a/hardware_interface/CHANGELOG.rst b/hardware_interface/CHANGELOG.rst index e3c52c0e1c..8acb46a46e 100644 --- a/hardware_interface/CHANGELOG.rst +++ b/hardware_interface/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package hardware_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.14.0 (2023-06-14) +------------------- * Add -Wconversion flag to protect future developments (`#1053 `_) * [CM] Use `robot_description` topic instead of parameter and don't crash on empty URDF 🦿 (`#940 `_) * [MockHardware] Enable disabling of command to simulate HW failures. (`#1027 `_) diff --git a/hardware_interface/package.xml b/hardware_interface/package.xml index a024ad4a27..54618f05c9 100644 --- a/hardware_interface/package.xml +++ b/hardware_interface/package.xml @@ -1,7 +1,7 @@ hardware_interface - 3.13.0 + 3.14.0 ros2_control hardware interface Bence Magyar Denis Štogl diff --git a/joint_limits/CHANGELOG.rst b/joint_limits/CHANGELOG.rst index e713a772bf..c0e9c1cc43 100644 --- a/joint_limits/CHANGELOG.rst +++ b/joint_limits/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_limits ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.14.0 (2023-06-14) +------------------- * Add -Wconversion flag to protect future developments (`#1053 `_) * enable ReflowComments to also use ColumnLimit on comments (`#1037 `_) * Contributors: Sai Kishor Kothakota, gwalck diff --git a/joint_limits/package.xml b/joint_limits/package.xml index 7bcf465d24..0a4990667e 100644 --- a/joint_limits/package.xml +++ b/joint_limits/package.xml @@ -1,6 +1,6 @@ joint_limits - 3.13.0 + 3.14.0 Interfaces for handling of joint limits for controllers or hardware. Bence Magyar diff --git a/ros2_control/CHANGELOG.rst b/ros2_control/CHANGELOG.rst index bf2fbc3b8a..fd2b295eb9 100644 --- a/ros2_control/CHANGELOG.rst +++ b/ros2_control/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_control ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.14.0 (2023-06-14) +------------------- 3.13.0 (2023-05-18) ------------------- diff --git a/ros2_control/package.xml b/ros2_control/package.xml index ddc9ae5edd..a45fbc7c99 100644 --- a/ros2_control/package.xml +++ b/ros2_control/package.xml @@ -1,7 +1,7 @@ ros2_control - 3.13.0 + 3.14.0 Metapackage for ROS2 control related packages Bence Magyar Denis Štogl diff --git a/ros2_control_test_assets/CHANGELOG.rst b/ros2_control_test_assets/CHANGELOG.rst index 040695bdb4..1ae3a3c626 100644 --- a/ros2_control_test_assets/CHANGELOG.rst +++ b/ros2_control_test_assets/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_control_test_assets ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.14.0 (2023-06-14) +------------------- * [URDF Parser] Allow empty urdf tag, e.g., parameter (`#1017 `_) * Contributors: Felix Exner (fexner) diff --git a/ros2_control_test_assets/package.xml b/ros2_control_test_assets/package.xml index 00c489b6a2..8a3c6abf22 100644 --- a/ros2_control_test_assets/package.xml +++ b/ros2_control_test_assets/package.xml @@ -2,7 +2,7 @@ ros2_control_test_assets - 3.13.0 + 3.14.0 The package provides shared test resources for ros2_control stack Bence Magyar diff --git a/ros2controlcli/CHANGELOG.rst b/ros2controlcli/CHANGELOG.rst index fecf6f29fb..6724a9b175 100644 --- a/ros2controlcli/CHANGELOG.rst +++ b/ros2controlcli/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2controlcli ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.14.0 (2023-06-14) +------------------- * Docs: Use branch name substitution for all links (`#1031 `_) * Contributors: Christoph Fröhlich diff --git a/ros2controlcli/package.xml b/ros2controlcli/package.xml index ca01cbe271..f8b8caa615 100644 --- a/ros2controlcli/package.xml +++ b/ros2controlcli/package.xml @@ -2,7 +2,7 @@ ros2controlcli - 3.13.0 + 3.14.0 The ROS 2 command line tools for ROS2 Control. diff --git a/ros2controlcli/setup.py b/ros2controlcli/setup.py index b916f1a2af..6f6a49199a 100644 --- a/ros2controlcli/setup.py +++ b/ros2controlcli/setup.py @@ -19,7 +19,7 @@ setup( name=package_name, - version="3.13.0", + version="3.14.0", packages=find_packages(exclude=["test"]), data_files=[ ("share/" + package_name, ["package.xml"]), diff --git a/rqt_controller_manager/CHANGELOG.rst b/rqt_controller_manager/CHANGELOG.rst index a2f416e9eb..30df32e8fd 100644 --- a/rqt_controller_manager/CHANGELOG.rst +++ b/rqt_controller_manager/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package rqt_controller_manager ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.14.0 (2023-06-14) +------------------- 3.13.0 (2023-05-18) ------------------- diff --git a/rqt_controller_manager/package.xml b/rqt_controller_manager/package.xml index acd6496e8d..0bb93f0838 100644 --- a/rqt_controller_manager/package.xml +++ b/rqt_controller_manager/package.xml @@ -2,7 +2,7 @@ rqt_controller_manager - 3.13.0 + 3.14.0 Graphical frontend for interacting with the controller manager. Bence Magyar Denis Štogl diff --git a/rqt_controller_manager/setup.py b/rqt_controller_manager/setup.py index 7d12c68e1f..1dd0977c7a 100644 --- a/rqt_controller_manager/setup.py +++ b/rqt_controller_manager/setup.py @@ -6,7 +6,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/transmission_interface/CHANGELOG.rst b/transmission_interface/CHANGELOG.rst index 537ccf36ac..cdc7b97801 100644 --- a/transmission_interface/CHANGELOG.rst +++ b/transmission_interface/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package transmission_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.14.0 (2023-06-14) +------------------- * Add -Wconversion flag to protect future developments (`#1053 `_) * enable ReflowComments to also use ColumnLimit on comments (`#1037 `_) * Contributors: Sai Kishor Kothakota, gwalck diff --git a/transmission_interface/package.xml b/transmission_interface/package.xml index 99d864bf6a..bce59f3a4a 100644 --- a/transmission_interface/package.xml +++ b/transmission_interface/package.xml @@ -2,7 +2,7 @@ transmission_interface - 3.13.0 + 3.14.0 transmission_interface contains data structures for representing mechanical transmissions, methods for propagating values between actuator and joint spaces and tooling to support this. Bence Magyar Denis Štogl From dc01ae33df33fae6a0f3a142cd2613208e3b78d4 Mon Sep 17 00:00:00 2001 From: "Dr. Denis" Date: Tue, 20 Jun 2023 21:21:35 +0200 Subject: [PATCH 13/40] [CM] Improve output when using robot description topic and give output about correct topic even remapped. (#1059) --- controller_manager/src/controller_manager.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/controller_manager/src/controller_manager.cpp b/controller_manager/src/controller_manager.cpp index 69a3bbb5f3..83604cd249 100644 --- a/controller_manager/src/controller_manager.cpp +++ b/controller_manager/src/controller_manager.cpp @@ -203,16 +203,17 @@ void ControllerManager::subscribe_to_robot_description_topic() { // set QoS to transient local to get messages that have already been published // (if robot state publisher starts before controller manager) - RCLCPP_INFO( - get_logger(), "Subscribing to '~/robot_description' topic for robot description file."); robot_description_subscription_ = create_subscription( "~/robot_description", rclcpp::QoS(1).transient_local(), std::bind(&ControllerManager::robot_description_callback, this, std::placeholders::_1)); + RCLCPP_INFO( + get_logger(), "Subscribing to '%s' topic for robot description.", + robot_description_subscription_->get_topic_name()); } void ControllerManager::robot_description_callback(const std_msgs::msg::String & robot_description) { - RCLCPP_INFO(get_logger(), "Received robot description file."); + RCLCPP_INFO(get_logger(), "Received robot description from topic."); RCLCPP_DEBUG( get_logger(), "'Content of robot description file: %s", robot_description.data.c_str()); // TODO(Manuel): errors should probably be caught since we don't want controller_manager node From e14497e9f581197a70ba8bf50fd2efac8c603281 Mon Sep 17 00:00:00 2001 From: "Dr. Denis" Date: Tue, 20 Jun 2023 22:07:36 +0200 Subject: [PATCH 14/40] Improve list hardware components output and code for better readability. (#1060) --- .../ros2controlcli/verb/list_hardware_components.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ros2controlcli/ros2controlcli/verb/list_hardware_components.py b/ros2controlcli/ros2controlcli/verb/list_hardware_components.py index 54dff21bb6..8a5884f2cb 100644 --- a/ros2controlcli/ros2controlcli/verb/list_hardware_components.py +++ b/ros2controlcli/ros2controlcli/verb/list_hardware_components.py @@ -40,7 +40,7 @@ def main(self, *, args): for idx, component in enumerate(hardware_components.component): print( - f"Hardware Component {idx}\n\tname: {component.name}\n\ttype: {component.type}" + f"Hardware Component {idx+1}\n\tname: {component.name}\n\ttype: {component.type}" ) if hasattr(component, "plugin_name"): plugin_name = component.plugin_name @@ -48,7 +48,9 @@ def main(self, *, args): plugin_name = f"{bcolors.WARNING}plugin name missing!{bcolors.ENDC}" print( - f"\tplugin name: {plugin_name}\n\tstate: id={component.state.id} label={component.state.label}\n\tcommand interfaces" + f"\tplugin name: {plugin_name}\n" + f"\tstate: id={component.state.id} label={component.state.label}\n" + f"\tcommand interfaces" ) for cmd_interface in component.command_interfaces: if cmd_interface.is_available: From db34dfaf2d79fc8afcd460d9ae16f02c43265a2a Mon Sep 17 00:00:00 2001 From: Olivier Stasse Date: Wed, 21 Jun 2023 09:34:49 +0200 Subject: [PATCH 15/40] Ensure instantiation of hardware classes work for python bindings (#1058) --- hardware_interface/CMakeLists.txt | 4 +++ .../include/hardware_interface/system.hpp | 2 ++ .../test/test_inst_hardwares.cpp | 34 +++++++++++++++++++ 3 files changed, 40 insertions(+) create mode 100644 hardware_interface/test/test_inst_hardwares.cpp diff --git a/hardware_interface/CMakeLists.txt b/hardware_interface/CMakeLists.txt index 6548d6186c..2d6c72ffae 100644 --- a/hardware_interface/CMakeLists.txt +++ b/hardware_interface/CMakeLists.txt @@ -80,6 +80,10 @@ if(BUILD_TESTING) target_include_directories(test_macros PRIVATE include) ament_target_dependencies(test_macros rcpputils) + ament_add_gmock(test_inst_hardwares test/test_inst_hardwares.cpp) + target_link_libraries(test_inst_hardwares hardware_interface) + ament_target_dependencies(test_inst_hardwares rcpputils) + ament_add_gmock(test_joint_handle test/test_handle.cpp) target_link_libraries(test_joint_handle hardware_interface) ament_target_dependencies(test_joint_handle rcpputils) diff --git a/hardware_interface/include/hardware_interface/system.hpp b/hardware_interface/include/hardware_interface/system.hpp index 4c9ae67ae2..ece14f814d 100644 --- a/hardware_interface/include/hardware_interface/system.hpp +++ b/hardware_interface/include/hardware_interface/system.hpp @@ -35,6 +35,8 @@ class SystemInterface; class System final { public: + System() = default; + HARDWARE_INTERFACE_PUBLIC explicit System(std::unique_ptr impl); diff --git a/hardware_interface/test/test_inst_hardwares.cpp b/hardware_interface/test/test_inst_hardwares.cpp new file mode 100644 index 0000000000..ddd3aea0ad --- /dev/null +++ b/hardware_interface/test/test_inst_hardwares.cpp @@ -0,0 +1,34 @@ +// Copyright 2023 LAAS CNRS +// +// 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 "hardware_interface/actuator.hpp" +#include "hardware_interface/actuator_interface.hpp" +#include "hardware_interface/sensor.hpp" +#include "hardware_interface/sensor_interface.hpp" +#include "hardware_interface/system.hpp" +#include "hardware_interface/system_interface.hpp" + +class TestInstantiationHardwares : public ::testing::Test +{ +protected: + static void SetUpTestCase() {} +}; + +TEST_F(TestInstantiationHardwares, build_actuator) { hardware_interface::Actuator anActuator; } + +TEST_F(TestInstantiationHardwares, build_sensor) { hardware_interface::Sensor aSensor; } + +TEST_F(TestInstantiationHardwares, build_system) { hardware_interface::System aSystem; } From cf4448d92d6644c04f060452e309d362ebbd118b Mon Sep 17 00:00:00 2001 From: "Dr. Denis" Date: Fri, 23 Jun 2023 20:23:46 +0200 Subject: [PATCH 16/40] Enable setting of initial state in HW compoments (#1046) --- controller_manager/doc/userdoc.rst | 28 ++-- controller_manager/src/controller_manager.cpp | 98 +++++++++++--- .../test/test_hardware_management_srvs.cpp | 126 +++++++++++++----- .../hardware_interface/resource_manager.hpp | 15 +-- hardware_interface/src/resource_manager.cpp | 21 --- 5 files changed, 191 insertions(+), 97 deletions(-) diff --git a/controller_manager/doc/userdoc.rst b/controller_manager/doc/userdoc.rst index de42850b6b..a05f6a3afc 100644 --- a/controller_manager/doc/userdoc.rst +++ b/controller_manager/doc/userdoc.rst @@ -39,21 +39,27 @@ The limits will be applied after you log out and in again. Parameters ----------- -activate_components_on_start (optional; list; default: empty) - Define which hardware components should be activated when controller manager is started. +hardware_components_initial_state + Map of parameters for controlled lifecycle management of hardware components. The names of the components are defined as attribute of ````-tag in ``robot_description``. - All other components will stay ``UNCONFIGURED``. - If this and ``configure_components_on_start`` are empty, all available components will be activated. - If this or ``configure_components_on_start`` are not empty, any component not in either list will be in unconfigured state. + Hardware components found in ``robot_description``, but without explicit state definition will be immediately activated. + Detailed explanation of each parameter is given below. + The full structure of the map is given in the following example: +.. code-block:: yaml -configure_components_on_start (optional; list; default: empty) - Define which hardware components should be configured when controller manager is started. - The names of the components are defined as attribute of ````-tag in ``robot_description``. - All other components will stay ``UNCONFIGURED``. - If this and ``activate_components_on_start`` are empty, all available components will be activated. - If this or ``activate_components_on_start`` are not empty, any component not in either list will be in unconfigured state. + hardware_components_initial_state: + unconfigured: + - "arm1" + - "arm2" + inactive: + - "base3" + +hardware_components_initial_state.unconfigured (optional; list; default: empty) + Defines which hardware components will be only loaded immediately when controller manager is started. +hardware_components_initial_state.inactive (optional; list; default: empty) + Defines which hardware components will be configured immediately when controller manager is started. robot_description (mandatory; string) String with the URDF string as robot description. diff --git a/controller_manager/src/controller_manager.cpp b/controller_manager/src/controller_manager.cpp index 83604cd249..58f91a786d 100644 --- a/controller_manager/src/controller_manager.cpp +++ b/controller_manager/src/controller_manager.cpp @@ -245,30 +245,85 @@ void ControllerManager::init_resource_manager(const std::string & robot_descript // TODO(destogl): manage this when there is an error - CM should not die because URDF is wrong... resource_manager_->load_urdf(robot_description); + // Get all components and if they are not defined in parameters activate them automatically + auto components_to_activate = resource_manager_->get_components_status(); + using lifecycle_msgs::msg::State; + auto set_components_to_state = + [&](const std::string & parameter_name, rclcpp_lifecycle::State state) + { + std::vector components_to_set = std::vector({}); + if (get_parameter(parameter_name, components_to_set)) + { + for (const auto & component : components_to_set) + { + if (component.empty()) + { + continue; + } + if (components_to_activate.find(component) == components_to_activate.end()) + { + RCLCPP_WARN( + get_logger(), "Hardware component '%s' is unknown, therefore not set in '%s' state.", + component.c_str(), state.label().c_str()); + } + else + { + RCLCPP_INFO( + get_logger(), "Setting component '%s' to '%s' state.", component.c_str(), + state.label().c_str()); + resource_manager_->set_component_state(component, state); + components_to_activate.erase(component); + } + } + } + }; + + // unconfigured (loaded only) + set_components_to_state( + "hardware_components_initial_state.unconfigured", + rclcpp_lifecycle::State( + State::PRIMARY_STATE_UNCONFIGURED, hardware_interface::lifecycle_state_names::UNCONFIGURED)); + + // inactive (configured) + // BEGIN: Keep old functionality on for backwards compatibility (Remove at the end of 2023) std::vector configure_components_on_start = std::vector({}); - if (get_parameter("configure_components_on_start", configure_components_on_start)) + get_parameter("configure_components_on_start", configure_components_on_start); + if (!configure_components_on_start.empty()) { RCLCPP_WARN( get_logger(), - "[Deprecated]: Usage of parameter \"configure_components_on_start\" is deprecated. Use " - "hardware_spawner instead."); - rclcpp_lifecycle::State inactive_state( - State::PRIMARY_STATE_INACTIVE, hardware_interface::lifecycle_state_names::INACTIVE); - for (const auto & component : configure_components_on_start) - { - resource_manager_->set_component_state(component, inactive_state); - } + "Parameter 'configure_components_on_start' is deprecated. " + "Use 'hardware_interface_state_after_start.inactive' instead, to set component's initial " + "state to 'inactive'. Don't use this parameters in combination with the new " + "'hardware_interface_state_after_start' parameter structure."); + set_components_to_state( + "configure_components_on_start", + rclcpp_lifecycle::State( + State::PRIMARY_STATE_INACTIVE, hardware_interface::lifecycle_state_names::INACTIVE)); + } + // END: Keep old functionality on humble backwards compatibility (Remove at the end of 2023) + else + { + set_components_to_state( + "hardware_components_initial_state.inactive", + rclcpp_lifecycle::State( + State::PRIMARY_STATE_INACTIVE, hardware_interface::lifecycle_state_names::INACTIVE)); } + // BEGIN: Keep old functionality on for backwards compatibility (Remove at the end of 2023) std::vector activate_components_on_start = std::vector({}); - if (get_parameter("activate_components_on_start", activate_components_on_start)) + get_parameter("activate_components_on_start", activate_components_on_start); + rclcpp_lifecycle::State active_state( + State::PRIMARY_STATE_ACTIVE, hardware_interface::lifecycle_state_names::ACTIVE); + if (!activate_components_on_start.empty()) { - RCLCPP_WARN_STREAM( + RCLCPP_WARN( get_logger(), - "[Deprecated]: Usage of parameter \"activate_components_on_start\" is deprecated. Use " - "hardware_spawner instead."); + "Parameter 'activate_components_on_start' is deprecated. " + "Components are activated per default. Don't use this parameters in combination with the new " + "'hardware_interface_state_after_start' parameter structure."); rclcpp_lifecycle::State active_state( State::PRIMARY_STATE_ACTIVE, hardware_interface::lifecycle_state_names::ACTIVE); for (const auto & component : activate_components_on_start) @@ -276,15 +331,16 @@ void ControllerManager::init_resource_manager(const std::string & robot_descript resource_manager_->set_component_state(component, active_state); } } - // if both parameter are empty or non-existing preserve behavior where all components are - // activated per default - if (configure_components_on_start.empty() && activate_components_on_start.empty()) + // END: Keep old functionality on humble for backwards compatibility (Remove at the end of 2023) + else { - RCLCPP_WARN_STREAM( - get_logger(), - "[Deprecated]: Automatic activation of all hardware components will not be supported in the " - "future anymore. Use hardware_spawner instead."); - resource_manager_->activate_all_components(); + // activate all other components + for (const auto & [component, state] : components_to_activate) + { + rclcpp_lifecycle::State active_state( + State::PRIMARY_STATE_ACTIVE, hardware_interface::lifecycle_state_names::ACTIVE); + resource_manager_->set_component_state(component, active_state); + } } } diff --git a/controller_manager/test/test_hardware_management_srvs.cpp b/controller_manager/test/test_hardware_management_srvs.cpp index 273e09d6a2..0fc7a2f27e 100644 --- a/controller_manager/test/test_hardware_management_srvs.cpp +++ b/controller_manager/test/test_hardware_management_srvs.cpp @@ -35,6 +35,7 @@ using hardware_interface::lifecycle_state_names::ACTIVE; using hardware_interface::lifecycle_state_names::FINALIZED; using hardware_interface::lifecycle_state_names::INACTIVE; using hardware_interface::lifecycle_state_names::UNCONFIGURED; +using hardware_interface::lifecycle_state_names::UNKNOWN; using ros2_control_test_assets::TEST_ACTUATOR_HARDWARE_COMMAND_INTERFACES; using ros2_control_test_assets::TEST_ACTUATOR_HARDWARE_NAME; @@ -69,9 +70,11 @@ class TestControllerManagerHWManagementSrvs : public TestControllerManagerSrvs cm_->set_parameter( rclcpp::Parameter("robot_description", ros2_control_test_assets::minimal_robot_urdf)); cm_->set_parameter(rclcpp::Parameter( - "activate_components_on_start", std::vector({TEST_ACTUATOR_HARDWARE_NAME}))); + "hardware_components_initial_state.unconfigured", + std::vector({TEST_SYSTEM_HARDWARE_NAME}))); cm_->set_parameter(rclcpp::Parameter( - "configure_components_on_start", std::vector({TEST_SENSOR_HARDWARE_NAME}))); + "hardware_components_initial_state.inactive", + std::vector({TEST_SENSOR_HARDWARE_NAME}))); std::string robot_description = ""; cm_->get_parameter("robot_description", robot_description); @@ -199,36 +202,6 @@ class TestControllerManagerHWManagementSrvs : public TestControllerManagerSrvs } }; -class TestControllerManagerHWManagementSrvsWithoutParams -: public TestControllerManagerHWManagementSrvs -{ -public: - void SetUp() override - { - executor_ = std::make_shared(); - cm_ = std::make_shared( - std::make_unique(), executor_, TEST_CM_NAME); - run_updater_ = false; - - // TODO(destogl): separate this to init_tests method where parameter can be set for each test - // separately - cm_->set_parameter( - rclcpp::Parameter("robot_description", ros2_control_test_assets::minimal_robot_urdf)); - - std::string robot_description = ""; - cm_->get_parameter("robot_description", robot_description); - if (robot_description.empty()) - { - throw std::runtime_error( - "Unable to initialize resource manager, no robot description found."); - } - - cm_->init_resource_manager(robot_description); - - SetUpSrvsCMExecutor(); - } -}; - TEST_F(TestControllerManagerHWManagementSrvs, list_hardware_components) { // Default status after start: @@ -386,6 +359,36 @@ TEST_F(TestControllerManagerHWManagementSrvs, selective_activate_deactivate_comp })); } +class TestControllerManagerHWManagementSrvsWithoutParams +: public TestControllerManagerHWManagementSrvs +{ +public: + void SetUp() override + { + executor_ = std::make_shared(); + cm_ = std::make_shared( + std::make_unique(), executor_, TEST_CM_NAME); + run_updater_ = false; + + // TODO(destogl): separate this to init_tests method where parameter can be set for each test + // separately + cm_->set_parameter( + rclcpp::Parameter("robot_description", ros2_control_test_assets::minimal_robot_urdf)); + + std::string robot_description = ""; + cm_->get_parameter("robot_description", robot_description); + if (robot_description.empty()) + { + throw std::runtime_error( + "Unable to initialize resource manager, no robot description found."); + } + + cm_->init_resource_manager(robot_description); + + SetUpSrvsCMExecutor(); + } +}; + TEST_F(TestControllerManagerHWManagementSrvsWithoutParams, test_default_activation_of_all_hardware) { // "configure_components_on_start" and "activate_components_on_start" are not set (empty) @@ -409,3 +412,62 @@ TEST_F(TestControllerManagerHWManagementSrvsWithoutParams, test_default_activati {{false, false, false, false}, {false, false, false, false, false, false, false}}, // system })); } + +// BEGIN: Remove at the end of 2023 +class TestControllerManagerHWManagementSrvsOldParameters +: public TestControllerManagerHWManagementSrvs +{ +public: + void SetUp() override + { + executor_ = std::make_shared(); + cm_ = std::make_shared( + std::make_unique(), executor_, TEST_CM_NAME); + run_updater_ = false; + + cm_->set_parameter( + rclcpp::Parameter("robot_description", ros2_control_test_assets::minimal_robot_urdf)); + cm_->set_parameter(rclcpp::Parameter( + "activate_components_on_start", std::vector({TEST_ACTUATOR_HARDWARE_NAME}))); + cm_->set_parameter(rclcpp::Parameter( + "configure_components_on_start", std::vector({TEST_SENSOR_HARDWARE_NAME}))); + + std::string robot_description = ""; + cm_->get_parameter("robot_description", robot_description); + if (robot_description.empty()) + { + throw std::runtime_error( + "Unable to initialize resource manager, no robot description found."); + } + + cm_->init_resource_manager(robot_description); + + SetUpSrvsCMExecutor(); + } +}; + +TEST_F(TestControllerManagerHWManagementSrvsOldParameters, list_hardware_components) +{ + // Default status after start: + // checks if "configure_components_on_start" and "activate_components_on_start" are correctly read + + list_hardware_components_and_check( + // actuator, sensor, system + std::vector( + {LFC_STATE::PRIMARY_STATE_ACTIVE, LFC_STATE::PRIMARY_STATE_INACTIVE, + LFC_STATE::PRIMARY_STATE_UNCONFIGURED}), + std::vector({ACTIVE, INACTIVE, UNCONFIGURED}), + std::vector>>({ + // is available + {{true, true}, {true, true, true}}, // actuator + {{}, {true}}, // sensor + {{false, false, false, false}, {false, false, false, false, false, false, false}}, // system + }), + std::vector>>({ + // is claimed + {{false, false}, {false, false, false}}, // actuator + {{}, {false}}, // sensor + {{false, false, false, false}, {false, false, false, false, false, false, false}}, // system + })); +} +// END: Remove at the end of 2023 diff --git a/hardware_interface/include/hardware_interface/resource_manager.hpp b/hardware_interface/include/hardware_interface/resource_manager.hpp index 4ea3ae9a5f..92bde14817 100644 --- a/hardware_interface/include/hardware_interface/resource_manager.hpp +++ b/hardware_interface/include/hardware_interface/resource_manager.hpp @@ -66,8 +66,7 @@ class HARDWARE_INTERFACE_PUBLIC ResourceManager * \param[in] validate_interfaces boolean argument indicating whether the exported * interfaces ought to be validated. Defaults to true. * \param[in] activate_all boolean argument indicating if all resources should be immediately - * activated. Currently used only in tests. In typical applications use parameters - * "autostart_components" and "autoconfigure_components" instead. + * activated. Currently used only in tests. */ explicit ResourceManager( const std::string & urdf, bool validate_interfaces = true, bool activate_all = false, @@ -374,7 +373,7 @@ class HARDWARE_INTERFACE_PUBLIC ResourceManager * Reads from all active hardware components. * * Part of the real-time critical update loop. - * It is realtime-safe if used hadware interfaces are implemented adequately. + * It is realtime-safe if used hardware interfaces are implemented adequately. */ HardwareReadWriteStatus read(const rclcpp::Time & time, const rclcpp::Duration & period); @@ -383,18 +382,10 @@ class HARDWARE_INTERFACE_PUBLIC ResourceManager * Writes to all active hardware components. * * Part of the real-time critical update loop. - * It is realtime-safe if used hadware interfaces are implemented adequately. + * It is realtime-safe if used hardware interfaces are implemented adequately. */ HardwareReadWriteStatus write(const rclcpp::Time & time, const rclcpp::Duration & period); - /// Activates all available hardware components in the system. - /** - * All available hardware components int the ros2_control framework are activated. - * This is used to preserve default behavior from previous versions where all hardware components - * are activated per default. - */ - void activate_all_components(); - /// Checks whether a command interface is registered under the given key. /** * \param[in] key string identifying the interface to check. diff --git a/hardware_interface/src/resource_manager.cpp b/hardware_interface/src/resource_manager.cpp index f32d24f890..96c87f5806 100644 --- a/hardware_interface/src/resource_manager.cpp +++ b/hardware_interface/src/resource_manager.cpp @@ -1356,25 +1356,4 @@ void ResourceManager::validate_storage( // END: private methods -// Temporary method to keep old interface and reduce framework changes in the PRs -void ResourceManager::activate_all_components() -{ - using lifecycle_msgs::msg::State; - rclcpp_lifecycle::State active_state( - State::PRIMARY_STATE_ACTIVE, hardware_interface::lifecycle_state_names::ACTIVE); - - for (auto & component : resource_storage_->actuators_) - { - set_component_state(component.get_name(), active_state); - } - for (auto & component : resource_storage_->sensors_) - { - set_component_state(component.get_name(), active_state); - } - for (auto & component : resource_storage_->systems_) - { - set_component_state(component.get_name(), active_state); - } -} - } // namespace hardware_interface From f7664086781cc7cf06066a1e710a8448f85e3256 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Fri, 23 Jun 2023 21:24:03 +0100 Subject: [PATCH 17/40] Update changelogs --- controller_interface/CHANGELOG.rst | 3 +++ controller_manager/CHANGELOG.rst | 6 ++++++ controller_manager_msgs/CHANGELOG.rst | 3 +++ hardware_interface/CHANGELOG.rst | 6 ++++++ joint_limits/CHANGELOG.rst | 3 +++ ros2_control/CHANGELOG.rst | 3 +++ ros2_control_test_assets/CHANGELOG.rst | 3 +++ ros2controlcli/CHANGELOG.rst | 5 +++++ rqt_controller_manager/CHANGELOG.rst | 3 +++ transmission_interface/CHANGELOG.rst | 3 +++ 10 files changed, 38 insertions(+) diff --git a/controller_interface/CHANGELOG.rst b/controller_interface/CHANGELOG.rst index d938aa8234..07f167b8fa 100644 --- a/controller_interface/CHANGELOG.rst +++ b/controller_interface/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package controller_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.14.0 (2023-06-14) ------------------- * Add -Wconversion flag to protect future developments (`#1053 `_) diff --git a/controller_manager/CHANGELOG.rst b/controller_manager/CHANGELOG.rst index 3a3447e908..a4a15f9f79 100644 --- a/controller_manager/CHANGELOG.rst +++ b/controller_manager/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package controller_manager ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Enable setting of initial state in HW compoments (`#1046 `_) +* [CM] Improve output when using robot description topic and give output about correct topic even remapped. (`#1059 `_) +* Contributors: Dr. Denis + 3.14.0 (2023-06-14) ------------------- * Add -Wconversion flag to protect future developments (`#1053 `_) diff --git a/controller_manager_msgs/CHANGELOG.rst b/controller_manager_msgs/CHANGELOG.rst index d0dd4d6233..0652ca745c 100644 --- a/controller_manager_msgs/CHANGELOG.rst +++ b/controller_manager_msgs/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package controller_manager_msgs ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.14.0 (2023-06-14) ------------------- diff --git a/hardware_interface/CHANGELOG.rst b/hardware_interface/CHANGELOG.rst index 8acb46a46e..be94f14cce 100644 --- a/hardware_interface/CHANGELOG.rst +++ b/hardware_interface/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package hardware_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Enable setting of initial state in HW compoments (`#1046 `_) +* Ensure instantiation of hardware classes work for python bindings (`#1058 `_) +* Contributors: Dr. Denis, Olivier Stasse + 3.14.0 (2023-06-14) ------------------- * Add -Wconversion flag to protect future developments (`#1053 `_) diff --git a/joint_limits/CHANGELOG.rst b/joint_limits/CHANGELOG.rst index c0e9c1cc43..25aa8e70e0 100644 --- a/joint_limits/CHANGELOG.rst +++ b/joint_limits/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package joint_limits ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.14.0 (2023-06-14) ------------------- * Add -Wconversion flag to protect future developments (`#1053 `_) diff --git a/ros2_control/CHANGELOG.rst b/ros2_control/CHANGELOG.rst index fd2b295eb9..03643f091d 100644 --- a/ros2_control/CHANGELOG.rst +++ b/ros2_control/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_control ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.14.0 (2023-06-14) ------------------- diff --git a/ros2_control_test_assets/CHANGELOG.rst b/ros2_control_test_assets/CHANGELOG.rst index 1ae3a3c626..c72e5715aa 100644 --- a/ros2_control_test_assets/CHANGELOG.rst +++ b/ros2_control_test_assets/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_control_test_assets ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.14.0 (2023-06-14) ------------------- * [URDF Parser] Allow empty urdf tag, e.g., parameter (`#1017 `_) diff --git a/ros2controlcli/CHANGELOG.rst b/ros2controlcli/CHANGELOG.rst index 6724a9b175..130a20df7d 100644 --- a/ros2controlcli/CHANGELOG.rst +++ b/ros2controlcli/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package ros2controlcli ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Improve list hardware components output and code for better readability. (`#1060 `_) +* Contributors: Dr. Denis + 3.14.0 (2023-06-14) ------------------- * Docs: Use branch name substitution for all links (`#1031 `_) diff --git a/rqt_controller_manager/CHANGELOG.rst b/rqt_controller_manager/CHANGELOG.rst index 30df32e8fd..073e787c51 100644 --- a/rqt_controller_manager/CHANGELOG.rst +++ b/rqt_controller_manager/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package rqt_controller_manager ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.14.0 (2023-06-14) ------------------- diff --git a/transmission_interface/CHANGELOG.rst b/transmission_interface/CHANGELOG.rst index cdc7b97801..8e9e8ffd46 100644 --- a/transmission_interface/CHANGELOG.rst +++ b/transmission_interface/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package transmission_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.14.0 (2023-06-14) ------------------- * Add -Wconversion flag to protect future developments (`#1053 `_) From cc1667b4f4ccbf6152d435c7f2bb04998b8b3b74 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Fri, 23 Jun 2023 21:24:53 +0100 Subject: [PATCH 18/40] 3.15.0 --- controller_interface/CHANGELOG.rst | 4 ++-- controller_interface/package.xml | 2 +- controller_manager/CHANGELOG.rst | 4 ++-- controller_manager/package.xml | 2 +- controller_manager_msgs/CHANGELOG.rst | 4 ++-- controller_manager_msgs/package.xml | 2 +- hardware_interface/CHANGELOG.rst | 4 ++-- hardware_interface/package.xml | 2 +- joint_limits/CHANGELOG.rst | 4 ++-- joint_limits/package.xml | 2 +- ros2_control/CHANGELOG.rst | 4 ++-- ros2_control/package.xml | 2 +- ros2_control_test_assets/CHANGELOG.rst | 4 ++-- ros2_control_test_assets/package.xml | 2 +- ros2controlcli/CHANGELOG.rst | 4 ++-- ros2controlcli/package.xml | 2 +- ros2controlcli/setup.py | 2 +- rqt_controller_manager/CHANGELOG.rst | 4 ++-- rqt_controller_manager/package.xml | 2 +- rqt_controller_manager/setup.py | 2 +- transmission_interface/CHANGELOG.rst | 4 ++-- transmission_interface/package.xml | 2 +- 22 files changed, 32 insertions(+), 32 deletions(-) diff --git a/controller_interface/CHANGELOG.rst b/controller_interface/CHANGELOG.rst index 07f167b8fa..475ecc1b32 100644 --- a/controller_interface/CHANGELOG.rst +++ b/controller_interface/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package controller_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.15.0 (2023-06-23) +------------------- 3.14.0 (2023-06-14) ------------------- diff --git a/controller_interface/package.xml b/controller_interface/package.xml index aedd5cf2f5..9f6d3c5cb6 100644 --- a/controller_interface/package.xml +++ b/controller_interface/package.xml @@ -2,7 +2,7 @@ controller_interface - 3.14.0 + 3.15.0 Description of controller_interface Bence Magyar Denis Štogl diff --git a/controller_manager/CHANGELOG.rst b/controller_manager/CHANGELOG.rst index a4a15f9f79..31bec20a0c 100644 --- a/controller_manager/CHANGELOG.rst +++ b/controller_manager/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package controller_manager ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.15.0 (2023-06-23) +------------------- * Enable setting of initial state in HW compoments (`#1046 `_) * [CM] Improve output when using robot description topic and give output about correct topic even remapped. (`#1059 `_) * Contributors: Dr. Denis diff --git a/controller_manager/package.xml b/controller_manager/package.xml index c08f12cb16..4e885f59cf 100644 --- a/controller_manager/package.xml +++ b/controller_manager/package.xml @@ -2,7 +2,7 @@ controller_manager - 3.14.0 + 3.15.0 Description of controller_manager Bence Magyar Denis Štogl diff --git a/controller_manager_msgs/CHANGELOG.rst b/controller_manager_msgs/CHANGELOG.rst index 0652ca745c..7299338c57 100644 --- a/controller_manager_msgs/CHANGELOG.rst +++ b/controller_manager_msgs/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package controller_manager_msgs ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.15.0 (2023-06-23) +------------------- 3.14.0 (2023-06-14) ------------------- diff --git a/controller_manager_msgs/package.xml b/controller_manager_msgs/package.xml index 186ecab6c4..2de7f5ee2f 100644 --- a/controller_manager_msgs/package.xml +++ b/controller_manager_msgs/package.xml @@ -2,7 +2,7 @@ controller_manager_msgs - 3.14.0 + 3.15.0 Messages and services for the controller manager. Bence Magyar Denis Štogl diff --git a/hardware_interface/CHANGELOG.rst b/hardware_interface/CHANGELOG.rst index be94f14cce..1a2d480216 100644 --- a/hardware_interface/CHANGELOG.rst +++ b/hardware_interface/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package hardware_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.15.0 (2023-06-23) +------------------- * Enable setting of initial state in HW compoments (`#1046 `_) * Ensure instantiation of hardware classes work for python bindings (`#1058 `_) * Contributors: Dr. Denis, Olivier Stasse diff --git a/hardware_interface/package.xml b/hardware_interface/package.xml index 54618f05c9..16d86dc985 100644 --- a/hardware_interface/package.xml +++ b/hardware_interface/package.xml @@ -1,7 +1,7 @@ hardware_interface - 3.14.0 + 3.15.0 ros2_control hardware interface Bence Magyar Denis Štogl diff --git a/joint_limits/CHANGELOG.rst b/joint_limits/CHANGELOG.rst index 25aa8e70e0..00f6f6f868 100644 --- a/joint_limits/CHANGELOG.rst +++ b/joint_limits/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_limits ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.15.0 (2023-06-23) +------------------- 3.14.0 (2023-06-14) ------------------- diff --git a/joint_limits/package.xml b/joint_limits/package.xml index 0a4990667e..a532d59fb4 100644 --- a/joint_limits/package.xml +++ b/joint_limits/package.xml @@ -1,6 +1,6 @@ joint_limits - 3.14.0 + 3.15.0 Interfaces for handling of joint limits for controllers or hardware. Bence Magyar diff --git a/ros2_control/CHANGELOG.rst b/ros2_control/CHANGELOG.rst index 03643f091d..e31c44e4eb 100644 --- a/ros2_control/CHANGELOG.rst +++ b/ros2_control/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_control ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.15.0 (2023-06-23) +------------------- 3.14.0 (2023-06-14) ------------------- diff --git a/ros2_control/package.xml b/ros2_control/package.xml index a45fbc7c99..9f7b7f8e4e 100644 --- a/ros2_control/package.xml +++ b/ros2_control/package.xml @@ -1,7 +1,7 @@ ros2_control - 3.14.0 + 3.15.0 Metapackage for ROS2 control related packages Bence Magyar Denis Štogl diff --git a/ros2_control_test_assets/CHANGELOG.rst b/ros2_control_test_assets/CHANGELOG.rst index c72e5715aa..d5ae3c2304 100644 --- a/ros2_control_test_assets/CHANGELOG.rst +++ b/ros2_control_test_assets/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_control_test_assets ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.15.0 (2023-06-23) +------------------- 3.14.0 (2023-06-14) ------------------- diff --git a/ros2_control_test_assets/package.xml b/ros2_control_test_assets/package.xml index 8a3c6abf22..67e7be2e53 100644 --- a/ros2_control_test_assets/package.xml +++ b/ros2_control_test_assets/package.xml @@ -2,7 +2,7 @@ ros2_control_test_assets - 3.14.0 + 3.15.0 The package provides shared test resources for ros2_control stack Bence Magyar diff --git a/ros2controlcli/CHANGELOG.rst b/ros2controlcli/CHANGELOG.rst index 130a20df7d..06dd3441d7 100644 --- a/ros2controlcli/CHANGELOG.rst +++ b/ros2controlcli/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2controlcli ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.15.0 (2023-06-23) +------------------- * Improve list hardware components output and code for better readability. (`#1060 `_) * Contributors: Dr. Denis diff --git a/ros2controlcli/package.xml b/ros2controlcli/package.xml index f8b8caa615..8fe8ddfa90 100644 --- a/ros2controlcli/package.xml +++ b/ros2controlcli/package.xml @@ -2,7 +2,7 @@ ros2controlcli - 3.14.0 + 3.15.0 The ROS 2 command line tools for ROS2 Control. diff --git a/ros2controlcli/setup.py b/ros2controlcli/setup.py index 6f6a49199a..d003a71365 100644 --- a/ros2controlcli/setup.py +++ b/ros2controlcli/setup.py @@ -19,7 +19,7 @@ setup( name=package_name, - version="3.14.0", + version="3.15.0", packages=find_packages(exclude=["test"]), data_files=[ ("share/" + package_name, ["package.xml"]), diff --git a/rqt_controller_manager/CHANGELOG.rst b/rqt_controller_manager/CHANGELOG.rst index 073e787c51..cdf03f67f7 100644 --- a/rqt_controller_manager/CHANGELOG.rst +++ b/rqt_controller_manager/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package rqt_controller_manager ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.15.0 (2023-06-23) +------------------- 3.14.0 (2023-06-14) ------------------- diff --git a/rqt_controller_manager/package.xml b/rqt_controller_manager/package.xml index 0bb93f0838..b5e82f3a99 100644 --- a/rqt_controller_manager/package.xml +++ b/rqt_controller_manager/package.xml @@ -2,7 +2,7 @@ rqt_controller_manager - 3.14.0 + 3.15.0 Graphical frontend for interacting with the controller manager. Bence Magyar Denis Štogl diff --git a/rqt_controller_manager/setup.py b/rqt_controller_manager/setup.py index 1dd0977c7a..7096280cd0 100644 --- a/rqt_controller_manager/setup.py +++ b/rqt_controller_manager/setup.py @@ -6,7 +6,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/transmission_interface/CHANGELOG.rst b/transmission_interface/CHANGELOG.rst index 8e9e8ffd46..ec7e028687 100644 --- a/transmission_interface/CHANGELOG.rst +++ b/transmission_interface/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package transmission_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.15.0 (2023-06-23) +------------------- 3.14.0 (2023-06-14) ------------------- diff --git a/transmission_interface/package.xml b/transmission_interface/package.xml index bce59f3a4a..ac00e7afd5 100644 --- a/transmission_interface/package.xml +++ b/transmission_interface/package.xml @@ -2,7 +2,7 @@ transmission_interface - 3.14.0 + 3.15.0 transmission_interface contains data structures for representing mechanical transmissions, methods for propagating values between actuator and joint spaces and tooling to support this. Bence Magyar Denis Štogl From 87c91990c870e55e8956f7811fb6d7c237373dd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Sat, 1 Jul 2023 18:57:57 +0200 Subject: [PATCH 19/40] Add CI workflow to check docs (#1069) --- .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..90a822aa72 --- /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_CONTROL_PR: ${{ github.ref }} From 185fbeafc97334eb9b09fde74e70b9eed30616d2 Mon Sep 17 00:00:00 2001 From: "Dr. Denis" Date: Sun, 2 Jul 2023 19:00:03 +0200 Subject: [PATCH 20/40] Create doc file for chained controllers (#985) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bence Magyar Co-authored-by: Christoph Fröhlich --- .../doc/controller_chaining.rst | 119 ++++++++++++++++++ .../doc/images/chaining_example2.png | Bin 0 -> 37092 bytes doc/index.rst | 6 +- 3 files changed, 122 insertions(+), 3 deletions(-) create mode 100644 controller_manager/doc/controller_chaining.rst create mode 100644 controller_manager/doc/images/chaining_example2.png diff --git a/controller_manager/doc/controller_chaining.rst b/controller_manager/doc/controller_chaining.rst new file mode 100644 index 0000000000..437cb70509 --- /dev/null +++ b/controller_manager/doc/controller_chaining.rst @@ -0,0 +1,119 @@ +:github_url: https://github.com/ros-controls/ros2_control/blob/{REPOS_FILE_BRANCH}/controller_manager/doc/controller_chaining.rst + +.. _controller_chaining: + +Controller Chaining / Cascade Control +====================================== + +This document proposes a minimal-viable-implementation of serial controller chaining as described in `Chaining Controllers design document `__. +Cascade control is a specific type of controller chaining. + + +Scope of the Document and Background Knowledge +------------------------------------------------------- + +This approach focuses only on serial chaining of controllers and tries to reuse existing mechanisms for it. +It focuses on `inputs and outputs of a controller `__ and their management in the controller manager. +The concept of `controller groups `__ will be introduced only for clarity reasons, and its only meaning is that controllers in that group can be updated in arbitrary order. +This doesn't mean that the controller groups as described `in the controller chaining document `__ will not be introduced and used in the future. +Nevertheless, the author is convinced that this would add only unnecessary complexity at this stage, although in the long term they *could* provide clearer structure and interfaces. + +Motivation, Purpose and Use +--------------------------------- + +To describe the intent of this document, lets focus on the simple yet sufficient example `Example 2 from 'controllers_chaining' design docs `__: + +.. image:: images/chaining_example2.png + :alt: Example2 + + +In this example, we want to chain 'position_tracking' controller with 'diff_drive_controller' and two PID controllers. +Let's now imagine a use-case where we don't only want to run all those controllers as a group, but also flexibly add preceding steps. +This means the following: + + 1. When a robot is started, we want to check if motor velocity control is working properly and therefore only PID controllers are activated. + At this stage we can control the input of PID controller also externally using topics. + However, these controllers also provide virtual interfaces, so we can chain them. + 2. Then "diff_drive_controller" is activated and attaches itself to the virtual input interfaces of PID controllers. + PID controllers also get informed that they are working in chained mode and therefore disable their external interface through subscriber. + Now we check if kinematics of differential robot is running properly. + 3. After that, "position_tracking" can be activated and attached to "diff_drive_controller" that disables its external interfaces. + 4. If any of the controllers is deactivated, also all preceding controllers are deactivated. + + +Implementation +-------------- + +A Controller Base-Class: ChainableController +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A ``ChainableController`` extends ``ControllerInterface`` class with ``virtual InterfaceConfiguration input_interface_configuration() const = 0`` method. +This method should implement for each controller that **can be preceded** by another controller exporting all the input interfaces. +For simplicity reasons, it is assumed for now that controller's all input interfaces are used. +Therefore, do not try to implement any exclusive combinations of input interfaces, but rather write multiple controllers if you need exclusivity. + +The ``ChainableController`` base class implements ``void set_chained_mode(bool activate)`` that sets an internal flag that a controller is used by another controller (in chained mode) and calls ``virtual void on_set_chained_mode(bool activate) = 0`` that implements controller's specific actions when chained modes is activated or deactivated, e.g., deactivating subscribers. + +As an example, PID controllers export one virtual interface ``pid_reference`` and stop their subscriber ``/pid_reference`` when used in chained mode. 'diff_drive_controller' controller exports list of virtual interfaces ``/v_x``, ``/v_y``, and ``/w_z``, and stops subscribers from topics ``/cmd_vel`` and ``/cmd_vel_unstamped``. Its publishers can continue running. + +Inner Resource Management +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +After configuring a chainable controller, controller manager calls ``input_interface_configuration`` method and takes ownership over controller's input interfaces. +This is the same process as done by ``ResourceManager`` and hardware interfaces. +Controller manager maintains "claimed" status of interface in a vector (the same as done in ``ResourceManager``). + +Activation and Deactivation Chained Controllers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Controller Manager has an additional parameter that describes how controllers are chained. +In the first version, the parameter-structure would have some semantic meaning embedded into it, as follows: + + +.. code-block:: yaml + + controller_manager: + ros__parameters: + chained_controllers: + + - parallel_group_1: + - controller1_1 + - controller1_2 + + - parallel_group_2: + - controller2_1 + + - parallel_group_3: + - controller3_1 + - controller3_2 + - controller3_3 + + ... + + - parallel_group_N: + - controllerN_1 + - ... + - controllerN_M + + + +This structure is motivated by ``filter_chain`` structure from `ros/filters repository `__, see `this file for implementation `__. + +This structure is stored internally by controller manager into an ordered map (``std::map>``) with group name as key. +When a controller should be deactivated, the controller manager deactivates all the controllers in the preceding groups first. +All other controllers from the group stay active, as well as all controllers in the following groups. +NOTE: In the future this could be done more intelligently, i.e., deactivate only controllers in the preceding groups that actually precede the controller that should be deactivated. + +On the other hand, the controller should be manually activated in the reverse order, i.e., from the those closer to the hardware toward those preceding them. + + +Debugging outputs +---------------------------- + +Flag ``unavailable`` on reference interface does not provide much information about anything at the moment. So don't get confused by it. The reason we have it are internal implementation reasons irelevant for the usage. + + +Closing remarks +---------------------------- + +- Maybe addition of the new controller's type ``ChainableController`` is not necessary. It would also be feasible to add implementation of ``input_interface_configuration()`` method into ``ControllerInterface`` class with default result ``interface_configuration_type::NONE``. diff --git a/controller_manager/doc/images/chaining_example2.png b/controller_manager/doc/images/chaining_example2.png new file mode 100644 index 0000000000000000000000000000000000000000..1ba49a116edcba1f365d76d4b52b3464f316a118 GIT binary patch literal 37092 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 literal 0 HcmV?d00001 diff --git a/doc/index.rst b/doc/index.rst index 196ea93285..91f965d601 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -6,6 +6,8 @@ ros2_control ################# +This is the documentation of the ros2_control framework core. + `GitHub Repository `_ ================= @@ -14,15 +16,12 @@ API Documentation API documentation is parsed by doxygen and can be found `here <../../api/index.html>`_ - - ========= Features ========= * :ref:`Command Line Interface (CLI) ` - ======== Concepts ======== @@ -31,5 +30,6 @@ Concepts :titlesonly: Controller Manager <../controller_manager/doc/userdoc.rst> + Controller Chaining / Cascade Control <../controller_manager/doc/controller_chaining.rst> Hardware Components <../hardware_interface/doc/hardware_components_userdoc.rst> Mock Components <../hardware_interface/doc/mock_components_userdoc.rst> From d39ddcdb2a6cf423530f93587646f2ce502b85d4 Mon Sep 17 00:00:00 2001 From: Sai Kishor Kothakota Date: Tue, 4 Jul 2023 21:32:56 +0200 Subject: [PATCH 21/40] Fix equal and higher controller update rate (#1070) --- controller_manager/src/controller_manager.cpp | 17 ++- .../test/test_controller/test_controller.hpp | 2 +- .../test/test_controller_manager.cpp | 121 +++++++++++++++++- 3 files changed, 131 insertions(+), 9 deletions(-) diff --git a/controller_manager/src/controller_manager.cpp b/controller_manager/src/controller_manager.cpp index 58f91a786d..cb875f25de 100644 --- a/controller_manager/src/controller_manager.cpp +++ b/controller_manager/src/controller_manager.cpp @@ -610,6 +610,18 @@ controller_interface::return_type ControllerManager::configure_controller( controller_name, std::make_unique(controller, update_rate_)); } + const auto controller_update_rate = controller->get_update_rate(); + const auto cm_update_rate = get_update_rate(); + if (controller_update_rate > cm_update_rate) + { + RCLCPP_WARN( + get_logger(), + "The controller : %s update rate : %d Hz should be less than or equal to controller " + "manager's update rate : %d Hz!. The controller will be updated at controller_manager's " + "update rate.", + controller_name.c_str(), controller_update_rate, cm_update_rate); + } + // CHAINABLE CONTROLLERS: get reference interfaces from chainable controllers if (controller->is_chainable()) { @@ -1873,8 +1885,9 @@ controller_interface::return_type ControllerManager::update( { const auto controller_update_rate = loaded_controller.c->get_update_rate(); - bool controller_go = - controller_update_rate == 0 || ((update_loop_counter_ % controller_update_rate) == 0); + bool controller_go = controller_update_rate == 0 || + ((update_loop_counter_ % controller_update_rate) == 0) || + (controller_update_rate >= update_rate_); RCLCPP_DEBUG( get_logger(), "update_loop_counter: '%d ' controller_go: '%s ' controller_name: '%s '", update_loop_counter_, controller_go ? "True" : "False", diff --git a/controller_manager/test/test_controller/test_controller.hpp b/controller_manager/test/test_controller/test_controller.hpp index 1b070ab302..f73f592037 100644 --- a/controller_manager/test/test_controller/test_controller.hpp +++ b/controller_manager/test/test_controller/test_controller.hpp @@ -65,7 +65,7 @@ class TestController : public controller_interface::ControllerInterface CONTROLLER_MANAGER_PUBLIC void set_state_interface_configuration(const controller_interface::InterfaceConfiguration & cfg); - size_t internal_counter = 0; + unsigned int internal_counter = 0; bool simulate_cleanup_failure = false; // Variable where we store when cleanup was called, pointer because the controller // is usually destroyed after cleanup diff --git a/controller_manager/test/test_controller_manager.cpp b/controller_manager/test/test_controller_manager.cpp index 22221b6e21..5a452bb0b1 100644 --- a/controller_manager/test/test_controller_manager.cpp +++ b/controller_manager/test/test_controller_manager.cpp @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include +#include #include #include #include @@ -27,13 +27,13 @@ using ::testing::_; using ::testing::Return; -class TestControllerManager +class TestControllerManagerWithStrictness : public ControllerManagerFixture, public testing::WithParamInterface { }; -TEST_P(TestControllerManager, controller_lifecycle) +TEST_P(TestControllerManagerWithStrictness, controller_lifecycle) { const auto test_param = GetParam(); auto test_controller = std::make_shared(); @@ -159,7 +159,7 @@ TEST_P(TestControllerManager, controller_lifecycle) controller_interface::return_type::OK, cm_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01))); EXPECT_GE(test_controller->internal_counter, 1u); - auto last_internal_counter = test_controller->internal_counter; + size_t last_internal_counter = test_controller->internal_counter; // Stop controller, will take effect at the end of the update function start_controllers = {}; @@ -196,7 +196,7 @@ TEST_P(TestControllerManager, controller_lifecycle) EXPECT_EQ(1, test_controller.use_count()); } -TEST_P(TestControllerManager, per_controller_update_rate) +TEST_P(TestControllerManagerWithStrictness, per_controller_update_rate) { auto strictness = GetParam().strictness; auto test_controller = std::make_shared(); @@ -254,4 +254,113 @@ TEST_P(TestControllerManager, per_controller_update_rate) } INSTANTIATE_TEST_SUITE_P( - test_strict_best_effort, TestControllerManager, testing::Values(strict, best_effort)); + test_strict_best_effort, TestControllerManagerWithStrictness, + testing::Values(strict, best_effort)); + +class TestControllerManagerWithUpdateRates +: public ControllerManagerFixture, + public testing::WithParamInterface +{ +}; + +TEST_P(TestControllerManagerWithUpdateRates, per_controller_equal_and_higher_update_rate) +{ + const auto strictness = controller_manager_msgs::srv::SwitchController::Request::STRICT; + const unsigned int ctrl_update_rate = GetParam(); + auto test_controller = std::make_shared(); + + auto last_internal_counter = 0u; + RCLCPP_INFO( + rclcpp::get_logger("test_controller_manager"), "Testing update rate : %u Hz", ctrl_update_rate); + { + ControllerManagerRunner cm_runner(this); + cm_->add_controller( + test_controller, test_controller::TEST_CONTROLLER_NAME, + test_controller::TEST_CONTROLLER_CLASS_NAME); + } + EXPECT_EQ(1u, cm_->get_loaded_controllers().size()); + EXPECT_EQ(2, test_controller.use_count()); + EXPECT_EQ( + controller_interface::return_type::OK, + cm_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01))); + EXPECT_EQ(last_internal_counter, test_controller->internal_counter) + << "Update should not reach an unconfigured controller"; + + EXPECT_EQ( + lifecycle_msgs::msg::State::PRIMARY_STATE_UNCONFIGURED, test_controller->get_state().id()); + + rclcpp::Parameter update_rate_parameter("update_rate", static_cast(ctrl_update_rate)); + test_controller->get_node()->set_parameter(update_rate_parameter); + // configure controller + cm_->configure_controller(test_controller::TEST_CONTROLLER_NAME); + EXPECT_EQ( + controller_interface::return_type::OK, + cm_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01))); + EXPECT_EQ(last_internal_counter, test_controller->internal_counter) + << "Controller is not started"; + EXPECT_EQ(lifecycle_msgs::msg::State::PRIMARY_STATE_INACTIVE, test_controller->get_state().id()); + + // Start controller, will take effect at the end of the update function + std::vector start_controllers = {test_controller::TEST_CONTROLLER_NAME}; + std::vector stop_controllers = {}; + auto switch_future = std::async( + std::launch::async, &controller_manager::ControllerManager::switch_controller, cm_, + start_controllers, stop_controllers, strictness, true, rclcpp::Duration(0, 0)); + + ASSERT_EQ(std::future_status::timeout, switch_future.wait_for(std::chrono::milliseconds(100))) + << "switch_controller should be blocking until next update cycle"; + + EXPECT_EQ( + controller_interface::return_type::OK, + cm_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01))); + EXPECT_EQ(last_internal_counter, test_controller->internal_counter) + << "Controller is started at the end of update"; + { + ControllerManagerRunner cm_runner(this); + EXPECT_EQ(controller_interface::return_type::OK, switch_future.get()); + } + + EXPECT_EQ(lifecycle_msgs::msg::State::PRIMARY_STATE_ACTIVE, test_controller->get_state().id()); + + const auto pre_internal_counter = test_controller->internal_counter; + rclcpp::Rate loop_rate(cm_->get_update_rate()); + for (size_t i = 0; i < 2 * cm_->get_update_rate(); i++) + { + EXPECT_EQ( + controller_interface::return_type::OK, + cm_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01))); + loop_rate.sleep(); + } + // if we do 2 times of the controller_manager update rate, the internal counter should be + // similarly incremented + EXPECT_EQ(test_controller->internal_counter, pre_internal_counter + (2 * cm_->get_update_rate())); + EXPECT_EQ(test_controller->get_update_rate(), ctrl_update_rate); + + auto deactivate_future = std::async( + std::launch::async, &controller_manager::ControllerManager::switch_controller, cm_, + stop_controllers, start_controllers, strictness, true, rclcpp::Duration(0, 0)); + + ASSERT_EQ(std::future_status::timeout, deactivate_future.wait_for(std::chrono::milliseconds(100))) + << "switch_controller should be blocking until next update cycle"; + + EXPECT_EQ( + controller_interface::return_type::OK, + cm_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01))) + << "Controller is stopped at the end of update, so it should have done one more update"; + { + ControllerManagerRunner cm_runner(this); + EXPECT_EQ(controller_interface::return_type::OK, deactivate_future.get()); + } + auto unload_future = std::async( + std::launch::async, &controller_manager::ControllerManager::unload_controller, cm_, + test_controller::TEST_CONTROLLER_NAME); + ASSERT_EQ(std::future_status::timeout, unload_future.wait_for(std::chrono::milliseconds(100))) + << "unload_controller should be blocking until next update cycle"; + ControllerManagerRunner cm_runner(this); + EXPECT_EQ(controller_interface::return_type::OK, unload_future.get()); + last_internal_counter = test_controller->internal_counter; +} + +INSTANTIATE_TEST_SUITE_P( + per_controller_equal_and_higher_update_rate, TestControllerManagerWithUpdateRates, + testing::Values(100, 232, 400)); From ca33bcc57d3f7138f7263011315c826da30c8a49 Mon Sep 17 00:00:00 2001 From: "Dr. Denis" Date: Wed, 5 Jul 2023 17:46:13 +0200 Subject: [PATCH 22/40] [CM] Make error message after trying to active controller more informative. (#1066) --- controller_manager/src/controller_manager.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/controller_manager/src/controller_manager.cpp b/controller_manager/src/controller_manager.cpp index cb875f25de..c4887db15a 100644 --- a/controller_manager/src/controller_manager.cpp +++ b/controller_manager/src/controller_manager.cpp @@ -1399,8 +1399,11 @@ void ControllerManager::activate_controllers( if (new_state.id() != lifecycle_msgs::msg::State::PRIMARY_STATE_ACTIVE) { RCLCPP_ERROR( - get_logger(), "After activating, controller '%s' is in state '%s', expected Active", - controller->get_node()->get_name(), new_state.label().c_str()); + get_logger(), + "After activation, controller '%s' is in state '%s' (%d), expected '%s' (%d).", + controller->get_node()->get_name(), new_state.label().c_str(), new_state.id(), + hardware_interface::lifecycle_state_names::ACTIVE, + lifecycle_msgs::msg::State::PRIMARY_STATE_ACTIVE); } if (controller->is_async()) From 09c6da4a170f56c39f57e22cf59d2d0927eeb6f3 Mon Sep 17 00:00:00 2001 From: Sai Kishor Kothakota Date: Fri, 7 Jul 2023 07:42:46 +0200 Subject: [PATCH 23/40] added controller manager runner to have update cycles (#1075) --- controller_manager/test/test_spawner_unspawner.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/controller_manager/test/test_spawner_unspawner.cpp b/controller_manager/test/test_spawner_unspawner.cpp index c9ba0e6355..d67ae8a7d1 100644 --- a/controller_manager/test/test_spawner_unspawner.cpp +++ b/controller_manager/test/test_spawner_unspawner.cpp @@ -96,6 +96,7 @@ TEST_F(TestLoadController, spawner_test_type_in_param) { cm_->set_parameter(rclcpp::Parameter("ctrl_1.type", test_controller::TEST_CONTROLLER_CLASS_NAME)); + ControllerManagerRunner cm_runner(this); EXPECT_EQ(call_spawner("ctrl_1 -c test_controller_manager"), 0); ASSERT_EQ(cm_->get_loaded_controllers().size(), 1ul); From c7df155882494e382852c1468f0c13b26a3748fa Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Sun, 9 Jul 2023 21:27:54 +0100 Subject: [PATCH 24/40] Update changelogs --- controller_interface/CHANGELOG.rst | 3 +++ controller_manager/CHANGELOG.rst | 8 ++++++++ controller_manager_msgs/CHANGELOG.rst | 3 +++ hardware_interface/CHANGELOG.rst | 3 +++ joint_limits/CHANGELOG.rst | 3 +++ ros2_control/CHANGELOG.rst | 3 +++ ros2_control_test_assets/CHANGELOG.rst | 3 +++ ros2controlcli/CHANGELOG.rst | 3 +++ rqt_controller_manager/CHANGELOG.rst | 3 +++ transmission_interface/CHANGELOG.rst | 3 +++ 10 files changed, 35 insertions(+) diff --git a/controller_interface/CHANGELOG.rst b/controller_interface/CHANGELOG.rst index 475ecc1b32..cd33e9924d 100644 --- a/controller_interface/CHANGELOG.rst +++ b/controller_interface/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package controller_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.15.0 (2023-06-23) ------------------- diff --git a/controller_manager/CHANGELOG.rst b/controller_manager/CHANGELOG.rst index 31bec20a0c..ad4ecd285f 100644 --- a/controller_manager/CHANGELOG.rst +++ b/controller_manager/CHANGELOG.rst @@ -2,6 +2,14 @@ Changelog for package controller_manager ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* added controller manager runner to have update cycles (`#1075 `_) +* [CM] Make error message after trying to active controller more informative. (`#1066 `_) +* Fix equal and higher controller update rate (`#1070 `_) +* Create doc file for chained controllers (`#985 `_) +* Contributors: Dr. Denis, Sai Kishor Kothakota + 3.15.0 (2023-06-23) ------------------- * Enable setting of initial state in HW compoments (`#1046 `_) diff --git a/controller_manager_msgs/CHANGELOG.rst b/controller_manager_msgs/CHANGELOG.rst index 7299338c57..7d59153f73 100644 --- a/controller_manager_msgs/CHANGELOG.rst +++ b/controller_manager_msgs/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package controller_manager_msgs ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.15.0 (2023-06-23) ------------------- diff --git a/hardware_interface/CHANGELOG.rst b/hardware_interface/CHANGELOG.rst index 1a2d480216..210bf8ec43 100644 --- a/hardware_interface/CHANGELOG.rst +++ b/hardware_interface/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package hardware_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.15.0 (2023-06-23) ------------------- * Enable setting of initial state in HW compoments (`#1046 `_) diff --git a/joint_limits/CHANGELOG.rst b/joint_limits/CHANGELOG.rst index 00f6f6f868..e63dff0077 100644 --- a/joint_limits/CHANGELOG.rst +++ b/joint_limits/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package joint_limits ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.15.0 (2023-06-23) ------------------- diff --git a/ros2_control/CHANGELOG.rst b/ros2_control/CHANGELOG.rst index e31c44e4eb..5d8a6ee37e 100644 --- a/ros2_control/CHANGELOG.rst +++ b/ros2_control/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_control ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.15.0 (2023-06-23) ------------------- diff --git a/ros2_control_test_assets/CHANGELOG.rst b/ros2_control_test_assets/CHANGELOG.rst index d5ae3c2304..5a136fe913 100644 --- a/ros2_control_test_assets/CHANGELOG.rst +++ b/ros2_control_test_assets/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_control_test_assets ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.15.0 (2023-06-23) ------------------- diff --git a/ros2controlcli/CHANGELOG.rst b/ros2controlcli/CHANGELOG.rst index 06dd3441d7..563176978e 100644 --- a/ros2controlcli/CHANGELOG.rst +++ b/ros2controlcli/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2controlcli ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.15.0 (2023-06-23) ------------------- * Improve list hardware components output and code for better readability. (`#1060 `_) diff --git a/rqt_controller_manager/CHANGELOG.rst b/rqt_controller_manager/CHANGELOG.rst index cdf03f67f7..1feeb20dec 100644 --- a/rqt_controller_manager/CHANGELOG.rst +++ b/rqt_controller_manager/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package rqt_controller_manager ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.15.0 (2023-06-23) ------------------- diff --git a/transmission_interface/CHANGELOG.rst b/transmission_interface/CHANGELOG.rst index ec7e028687..87710f8070 100644 --- a/transmission_interface/CHANGELOG.rst +++ b/transmission_interface/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package transmission_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.15.0 (2023-06-23) ------------------- From e4aa23842e42f57f5a186a335095c3ba8d2b6972 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Sun, 9 Jul 2023 21:29:00 +0100 Subject: [PATCH 25/40] 3.16.0 --- controller_interface/CHANGELOG.rst | 4 ++-- controller_interface/package.xml | 2 +- controller_manager/CHANGELOG.rst | 4 ++-- controller_manager/package.xml | 2 +- controller_manager_msgs/CHANGELOG.rst | 4 ++-- controller_manager_msgs/package.xml | 2 +- hardware_interface/CHANGELOG.rst | 4 ++-- hardware_interface/package.xml | 2 +- joint_limits/CHANGELOG.rst | 4 ++-- joint_limits/package.xml | 2 +- ros2_control/CHANGELOG.rst | 4 ++-- ros2_control/package.xml | 2 +- ros2_control_test_assets/CHANGELOG.rst | 4 ++-- ros2_control_test_assets/package.xml | 2 +- ros2controlcli/CHANGELOG.rst | 4 ++-- ros2controlcli/package.xml | 2 +- ros2controlcli/setup.py | 2 +- rqt_controller_manager/CHANGELOG.rst | 4 ++-- rqt_controller_manager/package.xml | 2 +- rqt_controller_manager/setup.py | 2 +- transmission_interface/CHANGELOG.rst | 4 ++-- transmission_interface/package.xml | 2 +- 22 files changed, 32 insertions(+), 32 deletions(-) diff --git a/controller_interface/CHANGELOG.rst b/controller_interface/CHANGELOG.rst index cd33e9924d..c0325027a4 100644 --- a/controller_interface/CHANGELOG.rst +++ b/controller_interface/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package controller_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.16.0 (2023-07-09) +------------------- 3.15.0 (2023-06-23) ------------------- diff --git a/controller_interface/package.xml b/controller_interface/package.xml index 9f6d3c5cb6..a060a01054 100644 --- a/controller_interface/package.xml +++ b/controller_interface/package.xml @@ -2,7 +2,7 @@ controller_interface - 3.15.0 + 3.16.0 Description of controller_interface Bence Magyar Denis Štogl diff --git a/controller_manager/CHANGELOG.rst b/controller_manager/CHANGELOG.rst index ad4ecd285f..d78eaec6a7 100644 --- a/controller_manager/CHANGELOG.rst +++ b/controller_manager/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package controller_manager ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.16.0 (2023-07-09) +------------------- * added controller manager runner to have update cycles (`#1075 `_) * [CM] Make error message after trying to active controller more informative. (`#1066 `_) * Fix equal and higher controller update rate (`#1070 `_) diff --git a/controller_manager/package.xml b/controller_manager/package.xml index 4e885f59cf..33255fc700 100644 --- a/controller_manager/package.xml +++ b/controller_manager/package.xml @@ -2,7 +2,7 @@ controller_manager - 3.15.0 + 3.16.0 Description of controller_manager Bence Magyar Denis Štogl diff --git a/controller_manager_msgs/CHANGELOG.rst b/controller_manager_msgs/CHANGELOG.rst index 7d59153f73..3c481827d2 100644 --- a/controller_manager_msgs/CHANGELOG.rst +++ b/controller_manager_msgs/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package controller_manager_msgs ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.16.0 (2023-07-09) +------------------- 3.15.0 (2023-06-23) ------------------- diff --git a/controller_manager_msgs/package.xml b/controller_manager_msgs/package.xml index 2de7f5ee2f..93af7dc706 100644 --- a/controller_manager_msgs/package.xml +++ b/controller_manager_msgs/package.xml @@ -2,7 +2,7 @@ controller_manager_msgs - 3.15.0 + 3.16.0 Messages and services for the controller manager. Bence Magyar Denis Štogl diff --git a/hardware_interface/CHANGELOG.rst b/hardware_interface/CHANGELOG.rst index 210bf8ec43..14dc8b8744 100644 --- a/hardware_interface/CHANGELOG.rst +++ b/hardware_interface/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package hardware_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.16.0 (2023-07-09) +------------------- 3.15.0 (2023-06-23) ------------------- diff --git a/hardware_interface/package.xml b/hardware_interface/package.xml index 16d86dc985..a329215218 100644 --- a/hardware_interface/package.xml +++ b/hardware_interface/package.xml @@ -1,7 +1,7 @@ hardware_interface - 3.15.0 + 3.16.0 ros2_control hardware interface Bence Magyar Denis Štogl diff --git a/joint_limits/CHANGELOG.rst b/joint_limits/CHANGELOG.rst index e63dff0077..d89b2981e9 100644 --- a/joint_limits/CHANGELOG.rst +++ b/joint_limits/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_limits ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.16.0 (2023-07-09) +------------------- 3.15.0 (2023-06-23) ------------------- diff --git a/joint_limits/package.xml b/joint_limits/package.xml index a532d59fb4..d72273844a 100644 --- a/joint_limits/package.xml +++ b/joint_limits/package.xml @@ -1,6 +1,6 @@ joint_limits - 3.15.0 + 3.16.0 Interfaces for handling of joint limits for controllers or hardware. Bence Magyar diff --git a/ros2_control/CHANGELOG.rst b/ros2_control/CHANGELOG.rst index 5d8a6ee37e..7befead368 100644 --- a/ros2_control/CHANGELOG.rst +++ b/ros2_control/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_control ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.16.0 (2023-07-09) +------------------- 3.15.0 (2023-06-23) ------------------- diff --git a/ros2_control/package.xml b/ros2_control/package.xml index 9f7b7f8e4e..a445ed27ff 100644 --- a/ros2_control/package.xml +++ b/ros2_control/package.xml @@ -1,7 +1,7 @@ ros2_control - 3.15.0 + 3.16.0 Metapackage for ROS2 control related packages Bence Magyar Denis Štogl diff --git a/ros2_control_test_assets/CHANGELOG.rst b/ros2_control_test_assets/CHANGELOG.rst index 5a136fe913..bcd91a1b55 100644 --- a/ros2_control_test_assets/CHANGELOG.rst +++ b/ros2_control_test_assets/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_control_test_assets ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.16.0 (2023-07-09) +------------------- 3.15.0 (2023-06-23) ------------------- diff --git a/ros2_control_test_assets/package.xml b/ros2_control_test_assets/package.xml index 67e7be2e53..8c8edff772 100644 --- a/ros2_control_test_assets/package.xml +++ b/ros2_control_test_assets/package.xml @@ -2,7 +2,7 @@ ros2_control_test_assets - 3.15.0 + 3.16.0 The package provides shared test resources for ros2_control stack Bence Magyar diff --git a/ros2controlcli/CHANGELOG.rst b/ros2controlcli/CHANGELOG.rst index 563176978e..bbb52f9821 100644 --- a/ros2controlcli/CHANGELOG.rst +++ b/ros2controlcli/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2controlcli ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.16.0 (2023-07-09) +------------------- 3.15.0 (2023-06-23) ------------------- diff --git a/ros2controlcli/package.xml b/ros2controlcli/package.xml index 8fe8ddfa90..c72388c597 100644 --- a/ros2controlcli/package.xml +++ b/ros2controlcli/package.xml @@ -2,7 +2,7 @@ ros2controlcli - 3.15.0 + 3.16.0 The ROS 2 command line tools for ROS2 Control. diff --git a/ros2controlcli/setup.py b/ros2controlcli/setup.py index d003a71365..5eb29039cc 100644 --- a/ros2controlcli/setup.py +++ b/ros2controlcli/setup.py @@ -19,7 +19,7 @@ setup( name=package_name, - version="3.15.0", + version="3.16.0", packages=find_packages(exclude=["test"]), data_files=[ ("share/" + package_name, ["package.xml"]), diff --git a/rqt_controller_manager/CHANGELOG.rst b/rqt_controller_manager/CHANGELOG.rst index 1feeb20dec..660dedfeb0 100644 --- a/rqt_controller_manager/CHANGELOG.rst +++ b/rqt_controller_manager/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package rqt_controller_manager ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.16.0 (2023-07-09) +------------------- 3.15.0 (2023-06-23) ------------------- diff --git a/rqt_controller_manager/package.xml b/rqt_controller_manager/package.xml index b5e82f3a99..3dac59a834 100644 --- a/rqt_controller_manager/package.xml +++ b/rqt_controller_manager/package.xml @@ -2,7 +2,7 @@ rqt_controller_manager - 3.15.0 + 3.16.0 Graphical frontend for interacting with the controller manager. Bence Magyar Denis Štogl diff --git a/rqt_controller_manager/setup.py b/rqt_controller_manager/setup.py index 7096280cd0..30117e7fe2 100644 --- a/rqt_controller_manager/setup.py +++ b/rqt_controller_manager/setup.py @@ -6,7 +6,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/transmission_interface/CHANGELOG.rst b/transmission_interface/CHANGELOG.rst index 87710f8070..a124333b85 100644 --- a/transmission_interface/CHANGELOG.rst +++ b/transmission_interface/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package transmission_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.16.0 (2023-07-09) +------------------- 3.15.0 (2023-06-23) ------------------- diff --git a/transmission_interface/package.xml b/transmission_interface/package.xml index ac00e7afd5..9d2839198c 100644 --- a/transmission_interface/package.xml +++ b/transmission_interface/package.xml @@ -2,7 +2,7 @@ transmission_interface - 3.15.0 + 3.16.0 transmission_interface contains data structures for representing mechanical transmissions, methods for propagating values between actuator and joint spaces and tooling to support this. Bence Magyar Denis Štogl From aea4efee3744a14290cdd37da2b71e1fa031fde9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Jul 2023 17:41:33 +0200 Subject: [PATCH 26/40] Bump actions/setup-python from 4.6.1 to 4.7.0 (#1077) Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4.6.1 to 4.7.0. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v4.6.1...v4.7.0) --- updated-dependencies: - dependency-name: actions/setup-python 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-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 4cf7330f56..9b91657851 100644 --- a/.github/workflows/ci-format.yml +++ b/.github/workflows/ci-format.yml @@ -13,7 +13,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 6cd8191550b59fcf940227583168dab9674adb13 Mon Sep 17 00:00:00 2001 From: "Dr. Denis" Date: Tue, 18 Jul 2023 17:39:53 +0200 Subject: [PATCH 27/40] Add checks if hardware is initialized. (#1054) --- hardware_interface/src/resource_manager.cpp | 86 +++++++++++++++++---- 1 file changed, 70 insertions(+), 16 deletions(-) diff --git a/hardware_interface/src/resource_manager.cpp b/hardware_interface/src/resource_manager.cpp index 96c87f5806..73daddd23d 100644 --- a/hardware_interface/src/resource_manager.cpp +++ b/hardware_interface/src/resource_manager.cpp @@ -514,9 +514,18 @@ class ResourceStorage { check_for_duplicates(hardware_info); load_hardware(hardware_info, actuator_loader_, container); - initialize_hardware(hardware_info, container.back()); - import_state_interfaces(container.back()); - import_command_interfaces(container.back()); + if (initialize_hardware(hardware_info, container.back())) + { + import_state_interfaces(container.back()); + import_command_interfaces(container.back()); + } + else + { + RCUTILS_LOG_WARN_NAMED( + "resource_manager", + "Actuator hardware component '%s' from plugin '%s' failed to initialize.", + hardware_info.name.c_str(), hardware_info.hardware_plugin_name.c_str()); + } }; if (hardware_info.is_async) @@ -535,8 +544,17 @@ class ResourceStorage { check_for_duplicates(hardware_info); load_hardware(hardware_info, sensor_loader_, container); - initialize_hardware(hardware_info, container.back()); - import_state_interfaces(container.back()); + if (initialize_hardware(hardware_info, container.back())) + { + import_state_interfaces(container.back()); + } + else + { + RCUTILS_LOG_WARN_NAMED( + "resource_manager", + "Sensor hardware component '%s' from plugin '%s' failed to initialize.", + hardware_info.name.c_str(), hardware_info.hardware_plugin_name.c_str()); + } }; if (hardware_info.is_async) @@ -555,9 +573,18 @@ class ResourceStorage { check_for_duplicates(hardware_info); load_hardware(hardware_info, system_loader_, container); - initialize_hardware(hardware_info, container.back()); - import_state_interfaces(container.back()); - import_command_interfaces(container.back()); + if (initialize_hardware(hardware_info, container.back())) + { + import_state_interfaces(container.back()); + import_command_interfaces(container.back()); + } + else + { + RCUTILS_LOG_WARN_NAMED( + "resource_manager", + "System hardware component '%s' from plugin '%s' failed to initialize.", + hardware_info.name.c_str(), hardware_info.hardware_plugin_name.c_str()); + } }; if (hardware_info.is_async) @@ -576,9 +603,18 @@ class ResourceStorage auto init_actuators = [&](auto & container) { container.emplace_back(Actuator(std::move(actuator))); - initialize_hardware(hardware_info, container.back()); - import_state_interfaces(container.back()); - import_command_interfaces(container.back()); + if (initialize_hardware(hardware_info, container.back())) + { + import_state_interfaces(container.back()); + import_command_interfaces(container.back()); + } + else + { + RCUTILS_LOG_WARN_NAMED( + "resource_manager", + "Actuator hardware component '%s' from plugin '%s' failed to initialize.", + hardware_info.name.c_str(), hardware_info.hardware_plugin_name.c_str()); + } }; if (hardware_info.is_async) @@ -597,8 +633,17 @@ class ResourceStorage auto init_sensors = [&](auto & container) { container.emplace_back(Sensor(std::move(sensor))); - initialize_hardware(hardware_info, container.back()); - import_state_interfaces(container.back()); + if (initialize_hardware(hardware_info, container.back())) + { + import_state_interfaces(container.back()); + } + else + { + RCUTILS_LOG_WARN_NAMED( + "resource_manager", + "Sensor hardware component '%s' from plugin '%s' failed to initialize.", + hardware_info.name.c_str(), hardware_info.hardware_plugin_name.c_str()); + } }; if (hardware_info.is_async) @@ -617,9 +662,18 @@ class ResourceStorage auto init_systems = [&](auto & container) { container.emplace_back(System(std::move(system))); - initialize_hardware(hardware_info, container.back()); - import_state_interfaces(container.back()); - import_command_interfaces(container.back()); + if (initialize_hardware(hardware_info, container.back())) + { + import_state_interfaces(container.back()); + import_command_interfaces(container.back()); + } + else + { + RCUTILS_LOG_WARN_NAMED( + "resource_manager", + "System hardware component '%s' from plugin '%s' failed to initialize.", + hardware_info.name.c_str(), hardware_info.hardware_plugin_name.c_str()); + } }; if (hardware_info.is_async) From 6dec7e9cb765a7b777ecd9034783f415c8d92695 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Mon, 24 Jul 2023 19:18:36 +0200 Subject: [PATCH 28/40] Fix links to control.ros.org (#1083) --- .docker/README.md | 4 ++-- .github/ISSUE_TEMPLATE/good-first-issue.md | 4 ++-- CONTRIBUTING.md | 2 +- README.md | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.docker/README.md b/.docker/README.md index b79ca69449..238e261b7b 100644 --- a/.docker/README.md +++ b/.docker/README.md @@ -3,7 +3,7 @@ Meant to provide basic docker containers for CI or development purposes. To use them, make sure you have [Docker](https://docs.docker.com/get-docker/) installed. You then can pull the latest source or build image or build any version and run the image by following tag specific commands as described below: ## Source folder and tag -Downloads and builds ros2_controls into a workspace for development use exactly as is found [here](https://ros-controls.github.io/control.ros.org/getting_started.html#compiling). This is primarily used for development and CI of ros2_control and related packages. +Downloads and builds ros2_controls into a workspace for development use exactly as is found [here](https://control.ros.org/master/doc/getting_started/getting_started.html#building-from-source). This is primarily used for development and CI of ros2_control and related packages. You can pull a prebuilt image with this docker tag: `ghcr.io/ros-controls/ros2_control_source`. @@ -30,7 +30,7 @@ docker run -it --mount type=volume,source=name-of-volume,destination=/root/ws_ro Note: this is probably the preferred solution as changes persist across rebuilds of container and doesn't require you to pull all repositories that you want to edit as they'll already be in the container. ## Release folder and tag -Installs ros2_control in the base ros2 docker container as mentioned [here](https://ros-controls.github.io/control.ros.org/getting_started.html#getting-started). This is mainly intended for development of external packages that rely on ros2_control. +Installs ros2_control in the base ros2 docker container as mentioned [here](https://control.ros.org/master/doc/getting_started/getting_started.html#building-from-source). This is mainly intended for development of external packages that rely on ros2_control. You can pull a prebuilt image using the following tag: `ghcr.io/ros2-controls/ros2_control_release`. diff --git a/.github/ISSUE_TEMPLATE/good-first-issue.md b/.github/ISSUE_TEMPLATE/good-first-issue.md index 5ff89fff5a..57779881d2 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 Step 3 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_control`, [here is a guide that you can follow](https://guides.github.com/activities/forking/) (You will have to remove or empty the existing `ros2_control` 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/CONTRIBUTING.md b/CONTRIBUTING.md index 9cb5781b56..d9cdc27041 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -21,7 +21,7 @@ Please try to include as much information as you can. Details like these are inc ## Contributing via Pull Requests -The following guidance should be up-to-date, but the documentation as found [here](https://ros-controls.github.io/control.ros.org/contributing.html#pull-requests) should prove as the final say. +The following guidance should be up-to-date, but the documentation as found [here](https://control.ros.org/master/doc/contributing/contributing.html#pull-requests) should prove as the final say. Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: diff --git a/README.md b/README.md index 7981031a13..b68c11705c 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) This package is a part of the ros2_control framework. -For more, please check the [documentation](https://ros-controls.github.io/control.ros.org/). +For more, please check the [documentation](https://control.ros.org/). ## Build status From 04ed2c292d000a5d737148a912bd665d2f26b8b6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Jul 2023 18:18:55 +0100 Subject: [PATCH 29/40] Bump ros-tooling/action-ros-ci from 0.3.2 to 0.3.3 (#1086) --- .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 97f5b4373b..9a549fdaf3 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 faadc4e9d9..ffe1cb1c3d 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 }} # build all packages listed in the meta package From 757ccd45b7a70d226e902e2dcbba0ff96f31ace2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Jul 2023 18:20:10 +0100 Subject: [PATCH 30/40] Bump ros-tooling/setup-ros from 0.6.2 to 0.7.0 (#1085) --- .github/workflows/ci-coverage-build.yml | 2 +- .github/workflows/ci-ros-lint.yml | 4 ++-- .github/workflows/reusable-ros-tooling-source-build.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci-coverage-build.yml b/.github/workflows/ci-coverage-build.yml index 9a549fdaf3..b339b45e66 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 57fe01c1a4..6428cd18a7 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.2 + - uses: ros-tooling/setup-ros@0.7.0 - uses: ros-tooling/action-ros-lint@v0.1 with: distribution: rolling @@ -36,7 +36,7 @@ jobs: linter: [cpplint] 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 ffe1cb1c3d..6cd59ce5f9 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 a53b2e064d0c76e4b8384603e8228f8f5dd9c950 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Wed, 2 Aug 2023 15:03:29 +0200 Subject: [PATCH 31/40] [CI] Bump ubuntu version of ament_lint jobs (#1092) --- .github/workflows/ci-ros-lint.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-ros-lint.yml b/.github/workflows/ci-ros-lint.yml index 6428cd18a7..37c371ce83 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.7.0 @@ -29,7 +31,7 @@ jobs: ament_lint_100: name: ament_${{ matrix.linter }} - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest strategy: fail-fast: false matrix: From bed7c66460d987f338ffc52d0282554b276eb076 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Sun, 6 Aug 2023 23:09:13 +0200 Subject: [PATCH 32/40] Fix deprecation warning (#1093) --- controller_manager/src/controller_manager.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/controller_manager/src/controller_manager.cpp b/controller_manager/src/controller_manager.cpp index c4887db15a..b492c52e3a 100644 --- a/controller_manager/src/controller_manager.cpp +++ b/controller_manager/src/controller_manager.cpp @@ -295,9 +295,9 @@ void ControllerManager::init_resource_manager(const std::string & robot_descript RCLCPP_WARN( get_logger(), "Parameter 'configure_components_on_start' is deprecated. " - "Use 'hardware_interface_state_after_start.inactive' instead, to set component's initial " + "Use 'hardware_components_initial_state.inactive' instead, to set component's initial " "state to 'inactive'. Don't use this parameters in combination with the new " - "'hardware_interface_state_after_start' parameter structure."); + "'hardware_components_initial_state' parameter structure."); set_components_to_state( "configure_components_on_start", rclcpp_lifecycle::State( @@ -323,7 +323,7 @@ void ControllerManager::init_resource_manager(const std::string & robot_descript get_logger(), "Parameter 'activate_components_on_start' is deprecated. " "Components are activated per default. Don't use this parameters in combination with the new " - "'hardware_interface_state_after_start' parameter structure."); + "'hardware_components_initial_state' parameter structure."); rclcpp_lifecycle::State active_state( State::PRIMARY_STATE_ACTIVE, hardware_interface::lifecycle_state_names::ACTIVE); for (const auto & component : activate_components_on_start) From ad70c9abdc72bad1838530081799e56b63d9d3fc Mon Sep 17 00:00:00 2001 From: Sai Kishor Kothakota Date: Mon, 7 Aug 2023 08:21:06 +0200 Subject: [PATCH 33/40] [CM] Fixes the issue with individual controller's update rate (#1082) * added parameterized test for the controller's update rate check * added warning for the update rate to be a perfect factor * fix the issue with the period when the controller update rate is higher than the controller manager --- controller_manager/src/controller_manager.cpp | 23 ++++- .../test/test_controller_manager.cpp | 89 ++++++++++++++++++- 2 files changed, 105 insertions(+), 7 deletions(-) diff --git a/controller_manager/src/controller_manager.cpp b/controller_manager/src/controller_manager.cpp index b492c52e3a..62311bd068 100644 --- a/controller_manager/src/controller_manager.cpp +++ b/controller_manager/src/controller_manager.cpp @@ -621,6 +621,19 @@ controller_interface::return_type ControllerManager::configure_controller( "update rate.", controller_name.c_str(), controller_update_rate, cm_update_rate); } + else if (controller_update_rate != 0 && cm_update_rate % controller_update_rate != 0) + { + // NOTE: The following computation is done to compute the approx controller update that can be + // achieved w.r.t to the CM's update rate. This is done this way to take into account the + // unsigned integer division. + const auto act_ctrl_update_rate = cm_update_rate / (cm_update_rate / controller_update_rate); + RCLCPP_WARN( + get_logger(), + "The controller : %s update rate : %d Hz is not a perfect divisor of the controller " + "manager's update rate : %d Hz!. The controller will be updated with nearest divisor's " + "update rate which is : %d Hz.", + controller_name.c_str(), controller_update_rate, cm_update_rate, act_ctrl_update_rate); + } // CHAINABLE CONTROLLERS: get reference interfaces from chainable controllers if (controller->is_chainable()) @@ -1887,10 +1900,12 @@ controller_interface::return_type ControllerManager::update( if (!loaded_controller.c->is_async() && is_controller_active(*loaded_controller.c)) { const auto controller_update_rate = loaded_controller.c->get_update_rate(); + const auto controller_update_factor = + (controller_update_rate == 0) || (controller_update_rate >= update_rate_) + ? 1u + : update_rate_ / controller_update_rate; - bool controller_go = controller_update_rate == 0 || - ((update_loop_counter_ % controller_update_rate) == 0) || - (controller_update_rate >= update_rate_); + bool controller_go = ((update_loop_counter_ % controller_update_factor) == 0); RCLCPP_DEBUG( get_logger(), "update_loop_counter: '%d ' controller_go: '%s ' controller_name: '%s '", update_loop_counter_, controller_go ? "True" : "False", @@ -1899,7 +1914,7 @@ controller_interface::return_type ControllerManager::update( if (controller_go) { auto controller_ret = loaded_controller.c->update( - time, (controller_update_rate != update_rate_ && controller_update_rate != 0) + time, (controller_update_factor != 1u) ? rclcpp::Duration::from_seconds(1.0 / controller_update_rate) : period); diff --git a/controller_manager/test/test_controller_manager.cpp b/controller_manager/test/test_controller_manager.cpp index 5a452bb0b1..6db4cfd1b2 100644 --- a/controller_manager/test/test_controller_manager.cpp +++ b/controller_manager/test/test_controller_manager.cpp @@ -246,9 +246,13 @@ TEST_P(TestControllerManagerWithStrictness, per_controller_update_rate) EXPECT_EQ(lifecycle_msgs::msg::State::PRIMARY_STATE_ACTIVE, test_controller->get_state().id()); - EXPECT_EQ( - controller_interface::return_type::OK, - cm_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01))); + // As the controller frequency is 4Hz, it needs to pass 25 iterations for 1 update cycle + for (size_t i = 0; i < 25; i++) + { + EXPECT_EQ( + controller_interface::return_type::OK, + cm_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01))); + } EXPECT_GE(test_controller->internal_counter, 1u); EXPECT_EQ(test_controller->get_update_rate(), 4u); } @@ -364,3 +368,82 @@ TEST_P(TestControllerManagerWithUpdateRates, per_controller_equal_and_higher_upd INSTANTIATE_TEST_SUITE_P( per_controller_equal_and_higher_update_rate, TestControllerManagerWithUpdateRates, testing::Values(100, 232, 400)); + +class TestControllerUpdateRates +: public ControllerManagerFixture, + public testing::WithParamInterface +{ +}; + +TEST_P(TestControllerUpdateRates, check_the_controller_update_rate) +{ + const unsigned int ctrl_update_rate = GetParam(); + auto test_controller = std::make_shared(); + cm_->add_controller( + test_controller, test_controller::TEST_CONTROLLER_NAME, + test_controller::TEST_CONTROLLER_CLASS_NAME); + EXPECT_EQ(1u, cm_->get_loaded_controllers().size()); + EXPECT_EQ(2, test_controller.use_count()); + + EXPECT_EQ( + lifecycle_msgs::msg::State::PRIMARY_STATE_UNCONFIGURED, test_controller->get_state().id()); + + test_controller->get_node()->set_parameter({"update_rate", static_cast(ctrl_update_rate)}); + // configure controller + cm_->configure_controller(test_controller::TEST_CONTROLLER_NAME); + EXPECT_EQ( + controller_interface::return_type::OK, + cm_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01))); + EXPECT_EQ(0u, test_controller->internal_counter) << "Controller is not started"; + + EXPECT_EQ(lifecycle_msgs::msg::State::PRIMARY_STATE_INACTIVE, test_controller->get_state().id()); + + // Start controller, will take effect at the end of the update function + const auto strictness = controller_manager_msgs::srv::SwitchController::Request::STRICT; + std::vector start_controllers = {test_controller::TEST_CONTROLLER_NAME}; + std::vector stop_controllers = {}; + auto switch_future = std::async( + std::launch::async, &controller_manager::ControllerManager::switch_controller, cm_, + start_controllers, stop_controllers, strictness, true, rclcpp::Duration(0, 0)); + + ASSERT_EQ(std::future_status::timeout, switch_future.wait_for(std::chrono::milliseconds(100))) + << "switch_controller should be blocking until next update cycle"; + + EXPECT_EQ( + controller_interface::return_type::OK, + cm_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01))); + EXPECT_EQ(0u, test_controller->internal_counter) << "Controller is started at the end of update"; + { + ControllerManagerRunner cm_runner(this); + EXPECT_EQ(controller_interface::return_type::OK, switch_future.get()); + } + + EXPECT_EQ(lifecycle_msgs::msg::State::PRIMARY_STATE_ACTIVE, test_controller->get_state().id()); + + EXPECT_EQ(test_controller->get_update_rate(), ctrl_update_rate); + const auto cm_update_rate = cm_->get_update_rate(); + const auto controller_update_rate = test_controller->get_update_rate(); + const auto controller_factor = (cm_update_rate / controller_update_rate); + const auto expected_controller_update_rate = + static_cast(std::round(cm_update_rate / static_cast(controller_factor))); + + const auto initial_counter = test_controller->internal_counter; + for (size_t update_counter = 1; update_counter <= 10 * cm_update_rate; ++update_counter) + { + EXPECT_EQ( + controller_interface::return_type::OK, + cm_->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01))); + + if (update_counter % cm_update_rate == 0) + { + const auto no_of_secs_passed = update_counter / cm_update_rate; + EXPECT_EQ( + test_controller->internal_counter - initial_counter, + (expected_controller_update_rate * no_of_secs_passed)); + } + } +} + +INSTANTIATE_TEST_SUITE_P( + per_controller_update_rate_check, TestControllerUpdateRates, + testing::Values(10, 12, 16, 23, 37, 40, 50, 63, 71, 85, 98)); From bda73375343cdfde6bb5feded74439982522c937 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Mon, 7 Aug 2023 12:51:07 +0200 Subject: [PATCH 34/40] Add info where the pdf is saved to view_controller_chains (#1094) --- ros2controlcli/doc/userdoc.rst | 12 +++++++++++- .../ros2controlcli/verb/view_controller_chains.py | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/ros2controlcli/doc/userdoc.rst b/ros2controlcli/doc/userdoc.rst index dba173cfbf..5880c054cb 100644 --- a/ros2controlcli/doc/userdoc.rst +++ b/ros2controlcli/doc/userdoc.rst @@ -268,4 +268,14 @@ view_controller_chains $ ros2 control view_controller_chains -h usage: ros2 view_controller_chains - Creates a graphviz image from loaded controllers. + Generates a diagram of the loaded chained controllers into /tmp/controller_diagram.gv.pdf + + options: + -h, --help show this help message and exit + --spin-time SPIN_TIME + Spin time in seconds to wait for discovery (only applies when not using an already running daemon) + -s, --use-sim-time Enable ROS simulation time + -c CONTROLLER_MANAGER, --controller-manager CONTROLLER_MANAGER + Name of the controller manager ROS node + --include-hidden-nodes + Consider hidden nodes as well diff --git a/ros2controlcli/ros2controlcli/verb/view_controller_chains.py b/ros2controlcli/ros2controlcli/verb/view_controller_chains.py index fbd999192e..f838a96e1c 100644 --- a/ros2controlcli/ros2controlcli/verb/view_controller_chains.py +++ b/ros2controlcli/ros2controlcli/verb/view_controller_chains.py @@ -195,7 +195,7 @@ def parse_response(list_controllers_response, list_hardware_response, visualize= class ViewControllerChainsVerb(VerbExtension): - """Generates a diagram of the loaded chained controllers.""" + """Generates a diagram of the loaded chained controllers into /tmp/controller_diagram.gv.pdf.""" def add_arguments(self, parser, cli_name): add_arguments(parser) From a037e37ce56d53c565314e3cb674ea44d8b00aa7 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Mon, 7 Aug 2023 18:46:28 +0100 Subject: [PATCH 35/40] Update changelogs --- controller_interface/CHANGELOG.rst | 3 +++ controller_manager/CHANGELOG.rst | 6 ++++++ controller_manager_msgs/CHANGELOG.rst | 3 +++ hardware_interface/CHANGELOG.rst | 5 +++++ joint_limits/CHANGELOG.rst | 3 +++ ros2_control/CHANGELOG.rst | 3 +++ ros2_control_test_assets/CHANGELOG.rst | 3 +++ ros2controlcli/CHANGELOG.rst | 5 +++++ rqt_controller_manager/CHANGELOG.rst | 3 +++ transmission_interface/CHANGELOG.rst | 3 +++ 10 files changed, 37 insertions(+) diff --git a/controller_interface/CHANGELOG.rst b/controller_interface/CHANGELOG.rst index c0325027a4..e86a8dab94 100644 --- a/controller_interface/CHANGELOG.rst +++ b/controller_interface/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package controller_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.16.0 (2023-07-09) ------------------- diff --git a/controller_manager/CHANGELOG.rst b/controller_manager/CHANGELOG.rst index d78eaec6a7..e6fb21f749 100644 --- a/controller_manager/CHANGELOG.rst +++ b/controller_manager/CHANGELOG.rst @@ -2,6 +2,12 @@ Changelog for package controller_manager ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* [CM] Fixes the issue with individual controller's update rate (`#1082 `_) +* Fix deprecation warning (`#1093 `_) +* Contributors: Christoph Fröhlich, Sai Kishor Kothakota + 3.16.0 (2023-07-09) ------------------- * added controller manager runner to have update cycles (`#1075 `_) diff --git a/controller_manager_msgs/CHANGELOG.rst b/controller_manager_msgs/CHANGELOG.rst index 3c481827d2..a90467b02a 100644 --- a/controller_manager_msgs/CHANGELOG.rst +++ b/controller_manager_msgs/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package controller_manager_msgs ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.16.0 (2023-07-09) ------------------- diff --git a/hardware_interface/CHANGELOG.rst b/hardware_interface/CHANGELOG.rst index 14dc8b8744..f23efa4d8c 100644 --- a/hardware_interface/CHANGELOG.rst +++ b/hardware_interface/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package hardware_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add checks if hardware is initialized. (`#1054 `_) +* Contributors: Dr. Denis + 3.16.0 (2023-07-09) ------------------- diff --git a/joint_limits/CHANGELOG.rst b/joint_limits/CHANGELOG.rst index d89b2981e9..7b4d064aad 100644 --- a/joint_limits/CHANGELOG.rst +++ b/joint_limits/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package joint_limits ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.16.0 (2023-07-09) ------------------- diff --git a/ros2_control/CHANGELOG.rst b/ros2_control/CHANGELOG.rst index 7befead368..f2964fe89e 100644 --- a/ros2_control/CHANGELOG.rst +++ b/ros2_control/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_control ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.16.0 (2023-07-09) ------------------- diff --git a/ros2_control_test_assets/CHANGELOG.rst b/ros2_control_test_assets/CHANGELOG.rst index bcd91a1b55..3ad83539e7 100644 --- a/ros2_control_test_assets/CHANGELOG.rst +++ b/ros2_control_test_assets/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_control_test_assets ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.16.0 (2023-07-09) ------------------- diff --git a/ros2controlcli/CHANGELOG.rst b/ros2controlcli/CHANGELOG.rst index bbb52f9821..a8b36ac289 100644 --- a/ros2controlcli/CHANGELOG.rst +++ b/ros2controlcli/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package ros2controlcli ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Add info where the pdf is saved to view_controller_chains (`#1094 `_) +* Contributors: Christoph Fröhlich + 3.16.0 (2023-07-09) ------------------- diff --git a/rqt_controller_manager/CHANGELOG.rst b/rqt_controller_manager/CHANGELOG.rst index 660dedfeb0..43092df3bd 100644 --- a/rqt_controller_manager/CHANGELOG.rst +++ b/rqt_controller_manager/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package rqt_controller_manager ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.16.0 (2023-07-09) ------------------- diff --git a/transmission_interface/CHANGELOG.rst b/transmission_interface/CHANGELOG.rst index a124333b85..fa5a153978 100644 --- a/transmission_interface/CHANGELOG.rst +++ b/transmission_interface/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package transmission_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.16.0 (2023-07-09) ------------------- From 036640fe100fc9b5bb112a222618425db1cfd933 Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Mon, 7 Aug 2023 18:46:53 +0100 Subject: [PATCH 36/40] 3.17.0 --- controller_interface/CHANGELOG.rst | 4 ++-- controller_interface/package.xml | 2 +- controller_manager/CHANGELOG.rst | 4 ++-- controller_manager/package.xml | 2 +- controller_manager_msgs/CHANGELOG.rst | 4 ++-- controller_manager_msgs/package.xml | 2 +- hardware_interface/CHANGELOG.rst | 4 ++-- hardware_interface/package.xml | 2 +- joint_limits/CHANGELOG.rst | 4 ++-- joint_limits/package.xml | 2 +- ros2_control/CHANGELOG.rst | 4 ++-- ros2_control/package.xml | 2 +- ros2_control_test_assets/CHANGELOG.rst | 4 ++-- ros2_control_test_assets/package.xml | 2 +- ros2controlcli/CHANGELOG.rst | 4 ++-- ros2controlcli/package.xml | 2 +- ros2controlcli/setup.py | 2 +- rqt_controller_manager/CHANGELOG.rst | 4 ++-- rqt_controller_manager/package.xml | 2 +- rqt_controller_manager/setup.py | 2 +- transmission_interface/CHANGELOG.rst | 4 ++-- transmission_interface/package.xml | 2 +- 22 files changed, 32 insertions(+), 32 deletions(-) diff --git a/controller_interface/CHANGELOG.rst b/controller_interface/CHANGELOG.rst index e86a8dab94..bd2d30f543 100644 --- a/controller_interface/CHANGELOG.rst +++ b/controller_interface/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package controller_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.17.0 (2023-08-07) +------------------- 3.16.0 (2023-07-09) ------------------- diff --git a/controller_interface/package.xml b/controller_interface/package.xml index a060a01054..c0d8c271bd 100644 --- a/controller_interface/package.xml +++ b/controller_interface/package.xml @@ -2,7 +2,7 @@ controller_interface - 3.16.0 + 3.17.0 Description of controller_interface Bence Magyar Denis Štogl diff --git a/controller_manager/CHANGELOG.rst b/controller_manager/CHANGELOG.rst index e6fb21f749..3deafc5565 100644 --- a/controller_manager/CHANGELOG.rst +++ b/controller_manager/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package controller_manager ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.17.0 (2023-08-07) +------------------- * [CM] Fixes the issue with individual controller's update rate (`#1082 `_) * Fix deprecation warning (`#1093 `_) * Contributors: Christoph Fröhlich, Sai Kishor Kothakota diff --git a/controller_manager/package.xml b/controller_manager/package.xml index 33255fc700..1d9b7821aa 100644 --- a/controller_manager/package.xml +++ b/controller_manager/package.xml @@ -2,7 +2,7 @@ controller_manager - 3.16.0 + 3.17.0 Description of controller_manager Bence Magyar Denis Štogl diff --git a/controller_manager_msgs/CHANGELOG.rst b/controller_manager_msgs/CHANGELOG.rst index a90467b02a..57bb1595ff 100644 --- a/controller_manager_msgs/CHANGELOG.rst +++ b/controller_manager_msgs/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package controller_manager_msgs ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.17.0 (2023-08-07) +------------------- 3.16.0 (2023-07-09) ------------------- diff --git a/controller_manager_msgs/package.xml b/controller_manager_msgs/package.xml index 93af7dc706..f55673871c 100644 --- a/controller_manager_msgs/package.xml +++ b/controller_manager_msgs/package.xml @@ -2,7 +2,7 @@ controller_manager_msgs - 3.16.0 + 3.17.0 Messages and services for the controller manager. Bence Magyar Denis Štogl diff --git a/hardware_interface/CHANGELOG.rst b/hardware_interface/CHANGELOG.rst index f23efa4d8c..6ca31d134a 100644 --- a/hardware_interface/CHANGELOG.rst +++ b/hardware_interface/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package hardware_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.17.0 (2023-08-07) +------------------- * Add checks if hardware is initialized. (`#1054 `_) * Contributors: Dr. Denis diff --git a/hardware_interface/package.xml b/hardware_interface/package.xml index a329215218..fbe85e48e8 100644 --- a/hardware_interface/package.xml +++ b/hardware_interface/package.xml @@ -1,7 +1,7 @@ hardware_interface - 3.16.0 + 3.17.0 ros2_control hardware interface Bence Magyar Denis Štogl diff --git a/joint_limits/CHANGELOG.rst b/joint_limits/CHANGELOG.rst index 7b4d064aad..313a4d83ed 100644 --- a/joint_limits/CHANGELOG.rst +++ b/joint_limits/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_limits ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.17.0 (2023-08-07) +------------------- 3.16.0 (2023-07-09) ------------------- diff --git a/joint_limits/package.xml b/joint_limits/package.xml index d72273844a..52e4bb82d1 100644 --- a/joint_limits/package.xml +++ b/joint_limits/package.xml @@ -1,6 +1,6 @@ joint_limits - 3.16.0 + 3.17.0 Interfaces for handling of joint limits for controllers or hardware. Bence Magyar diff --git a/ros2_control/CHANGELOG.rst b/ros2_control/CHANGELOG.rst index f2964fe89e..b400547e27 100644 --- a/ros2_control/CHANGELOG.rst +++ b/ros2_control/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_control ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.17.0 (2023-08-07) +------------------- 3.16.0 (2023-07-09) ------------------- diff --git a/ros2_control/package.xml b/ros2_control/package.xml index a445ed27ff..74b1bc46cc 100644 --- a/ros2_control/package.xml +++ b/ros2_control/package.xml @@ -1,7 +1,7 @@ ros2_control - 3.16.0 + 3.17.0 Metapackage for ROS2 control related packages Bence Magyar Denis Štogl diff --git a/ros2_control_test_assets/CHANGELOG.rst b/ros2_control_test_assets/CHANGELOG.rst index 3ad83539e7..fc362d9f3a 100644 --- a/ros2_control_test_assets/CHANGELOG.rst +++ b/ros2_control_test_assets/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_control_test_assets ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.17.0 (2023-08-07) +------------------- 3.16.0 (2023-07-09) ------------------- diff --git a/ros2_control_test_assets/package.xml b/ros2_control_test_assets/package.xml index 8c8edff772..a2ce000ccd 100644 --- a/ros2_control_test_assets/package.xml +++ b/ros2_control_test_assets/package.xml @@ -2,7 +2,7 @@ ros2_control_test_assets - 3.16.0 + 3.17.0 The package provides shared test resources for ros2_control stack Bence Magyar diff --git a/ros2controlcli/CHANGELOG.rst b/ros2controlcli/CHANGELOG.rst index a8b36ac289..1a8b32b1d3 100644 --- a/ros2controlcli/CHANGELOG.rst +++ b/ros2controlcli/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2controlcli ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.17.0 (2023-08-07) +------------------- * Add info where the pdf is saved to view_controller_chains (`#1094 `_) * Contributors: Christoph Fröhlich diff --git a/ros2controlcli/package.xml b/ros2controlcli/package.xml index c72388c597..1af234dcf3 100644 --- a/ros2controlcli/package.xml +++ b/ros2controlcli/package.xml @@ -2,7 +2,7 @@ ros2controlcli - 3.16.0 + 3.17.0 The ROS 2 command line tools for ROS2 Control. diff --git a/ros2controlcli/setup.py b/ros2controlcli/setup.py index 5eb29039cc..49d96a5eb6 100644 --- a/ros2controlcli/setup.py +++ b/ros2controlcli/setup.py @@ -19,7 +19,7 @@ setup( name=package_name, - version="3.16.0", + version="3.17.0", packages=find_packages(exclude=["test"]), data_files=[ ("share/" + package_name, ["package.xml"]), diff --git a/rqt_controller_manager/CHANGELOG.rst b/rqt_controller_manager/CHANGELOG.rst index 43092df3bd..1b79cea368 100644 --- a/rqt_controller_manager/CHANGELOG.rst +++ b/rqt_controller_manager/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package rqt_controller_manager ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.17.0 (2023-08-07) +------------------- 3.16.0 (2023-07-09) ------------------- diff --git a/rqt_controller_manager/package.xml b/rqt_controller_manager/package.xml index 3dac59a834..8ccf0bc2c1 100644 --- a/rqt_controller_manager/package.xml +++ b/rqt_controller_manager/package.xml @@ -2,7 +2,7 @@ rqt_controller_manager - 3.16.0 + 3.17.0 Graphical frontend for interacting with the controller manager. Bence Magyar Denis Štogl diff --git a/rqt_controller_manager/setup.py b/rqt_controller_manager/setup.py index 30117e7fe2..d46d1afeb7 100644 --- a/rqt_controller_manager/setup.py +++ b/rqt_controller_manager/setup.py @@ -6,7 +6,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/transmission_interface/CHANGELOG.rst b/transmission_interface/CHANGELOG.rst index fa5a153978..e3e1d776f0 100644 --- a/transmission_interface/CHANGELOG.rst +++ b/transmission_interface/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package transmission_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.17.0 (2023-08-07) +------------------- 3.16.0 (2023-07-09) ------------------- diff --git a/transmission_interface/package.xml b/transmission_interface/package.xml index 9d2839198c..8b0687f6d7 100644 --- a/transmission_interface/package.xml +++ b/transmission_interface/package.xml @@ -2,7 +2,7 @@ transmission_interface - 3.16.0 + 3.17.0 transmission_interface contains data structures for representing mechanical transmissions, methods for propagating values between actuator and joint spaces and tooling to support this. Bence Magyar Denis Štogl From 4045e127241ecc69e24dcde14748cba1efb921b6 Mon Sep 17 00:00:00 2001 From: Sai Kishor Kothakota Date: Fri, 11 Aug 2023 14:16:16 +0200 Subject: [PATCH 37/40] Controller sorting and proper execution in a chain (Fixes #853) (#1063) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Added test for the reordering controllers case * Perform controller sorting at the end of switch_controller * fix the list_chained_controllers_srv test case for the new controller sorting * move the logic to a separate function * Apply suggestions from code review Co-authored-by: Christoph Fröhlich * remove obsolete TODO comments in the controller chaining tests * Add a test case to sort 6 controllers in chained mode * Added a method to retrieve the following controller names given a controller name * Update the controller_sorting method to support progressive chaining ability * Added test case to sort chained controllers with branching * Added a method to retrieve the preceding controller names given a controller name * Added logic to controller_sorting to support sorting branched controller chains * Added some documentation to the newly added functions * Add debug print of reordered controllers list once they are sorted * Add the condition to skip the non-configured controllers * remove logging for every command interface * Improve the complex chain test case checking * added a test case to sort independent chains * Added fixes for the independent chains sorting * better randomization in independent chains testing * Fix minor logic issues * Add 3rd chain for better complex testing * Apply suggestions from code review - Denis Co-authored-by: Dr. Denis * address pull request review comments --------- Co-authored-by: Christoph Fröhlich Co-authored-by: Dr. Denis Co-authored-by: Bence Magyar --- .../controller_manager/controller_manager.hpp | 23 + controller_manager/src/controller_manager.cpp | 224 +++++++ .../test/test_controller_manager_srvs.cpp | 601 +++++++++++++++++- ...llers_chaining_with_controller_manager.cpp | 134 +++- 4 files changed, 969 insertions(+), 13 deletions(-) diff --git a/controller_manager/include/controller_manager/controller_manager.hpp b/controller_manager/include/controller_manager/controller_manager.hpp index 631d5173aa..2850b2be80 100644 --- a/controller_manager/include/controller_manager/controller_manager.hpp +++ b/controller_manager/include/controller_manager/controller_manager.hpp @@ -389,6 +389,29 @@ class ControllerManager : public rclcpp::Node const std::vector & controllers, int strictness, const ControllersListIterator controller_it); + /// A method to be used in the std::sort method to sort the controllers to be able to + /// execute them in a proper order + /** + * Compares the controllers ctrl_a and ctrl_b and then returns which comes first in the sequence + * + * @note The following conditions needs to be handled while ordering the controller list + * 1. The controllers that do not use any state or command interfaces are updated first + * 2. The controllers that use only the state system interfaces only are updated next + * 3. The controllers that use any of an another controller's reference interface are updated + * before the preceding controller + * 4. The controllers that use the controller's estimated interfaces are updated after the + * preceding controller + * 5. The controllers that only use the hardware command interfaces are updated last + * 6. All inactive controllers go at the end of the list + * + * \param[in] controllers list of controllers to compare their names to interface's prefix. + * + * @return true, if ctrl_a needs to execute first, else false + */ + bool controller_sorting( + const ControllerSpec & ctrl_a, const ControllerSpec & ctrl_b, + const std::vector & controllers); + void controller_activity_diagnostic_callback(diagnostic_updater::DiagnosticStatusWrapper & stat); diagnostic_updater::Updater diagnostics_updater_; diff --git a/controller_manager/src/controller_manager.cpp b/controller_manager/src/controller_manager.cpp index 62311bd068..062d813f0d 100644 --- a/controller_manager/src/controller_manager.cpp +++ b/controller_manager/src/controller_manager.cpp @@ -118,6 +118,123 @@ bool command_interface_is_reference_interface_of_controller( return true; } +/** + * A method to retrieve the names of all it's following controllers given a controller name + * For instance, for the following case + * A -> B -> C -> D + * When called with B, returns C and D + * NOTE: A -> B signifies that the controller A is utilizing the reference interfaces exported from + * the controller B (or) the controller B is utilizing the expected interfaces exported from the + * controller A + * + * @param controller_name - Name of the controller for checking the tree + * \param[in] controllers list of controllers to compare their names to interface's prefix. + * @return list of controllers that are following the given controller in a chain. If none, return + * empty. + */ +std::vector get_following_controller_names( + const std::string controller_name, + const std::vector & controllers) +{ + std::vector following_controllers; + auto controller_it = std::find_if( + controllers.begin(), controllers.end(), + std::bind(controller_name_compare, std::placeholders::_1, controller_name)); + if (controller_it == controllers.end()) + { + RCLCPP_DEBUG( + rclcpp::get_logger("ControllerManager::utils"), + "Required controller : '%s' is not found in the controller list ", controller_name.c_str()); + + return following_controllers; + } + // If the controller is not configured, return empty + if (!(is_controller_active(controller_it->c) || is_controller_inactive(controller_it->c))) + return following_controllers; + const auto cmd_itfs = controller_it->c->command_interface_configuration().names; + for (const auto & itf : cmd_itfs) + { + controller_manager::ControllersListIterator ctrl_it; + if (command_interface_is_reference_interface_of_controller(itf, controllers, ctrl_it)) + { + RCLCPP_DEBUG( + rclcpp::get_logger("ControllerManager::utils"), + "The interface is a reference interface of controller : %s", ctrl_it->info.name.c_str()); + following_controllers.push_back(ctrl_it->info.name); + const std::vector ctrl_names = + get_following_controller_names(ctrl_it->info.name, controllers); + for (const std::string & controller : ctrl_names) + { + if ( + std::find(following_controllers.begin(), following_controllers.end(), controller) == + following_controllers.end()) + { + // Only add to the list if it doesn't exist + following_controllers.push_back(controller); + } + } + } + } + return following_controllers; +} + +/** + * A method to retrieve the names of all it's preceding controllers given a controller name + * For instance, for the following case + * A -> B -> C -> D + * When called with C, returns A and B + * NOTE: A -> B signifies that the controller A is utilizing the reference interfaces exported from + * the controller B (or) the controller B is utilizing the expected interfaces exported from the + * controller A + * + * @param controller_name - Name of the controller for checking the tree + * \param[in] controllers list of controllers to compare their names to interface's prefix. + * @return list of controllers that are preceding the given controller in a chain. If none, return + * empty. + */ +std::vector get_preceding_controller_names( + const std::string controller_name, + const std::vector & controllers) +{ + std::vector preceding_controllers; + auto controller_it = std::find_if( + controllers.begin(), controllers.end(), + std::bind(controller_name_compare, std::placeholders::_1, controller_name)); + if (controller_it == controllers.end()) + { + RCLCPP_DEBUG( + rclcpp::get_logger("ControllerManager::utils"), + "Required controller : '%s' is not found in the controller list ", controller_name.c_str()); + return preceding_controllers; + } + for (const auto & ctrl : controllers) + { + // If the controller is not configured, return empty + if (!(is_controller_active(ctrl.c) || is_controller_inactive(ctrl.c))) + return preceding_controllers; + auto cmd_itfs = ctrl.c->command_interface_configuration().names; + for (const auto & itf : cmd_itfs) + { + if (itf.find(controller_name) != std::string::npos) + { + preceding_controllers.push_back(ctrl.info.name); + auto ctrl_names = get_preceding_controller_names(ctrl.info.name, controllers); + for (const std::string & controller : ctrl_names) + { + if ( + std::find(preceding_controllers.begin(), preceding_controllers.end(), controller) == + preceding_controllers.end()) + { + // Only add to the list if it doesn't exist + preceding_controllers.push_back(controller); + } + } + } + } + } + return preceding_controllers; +} + } // namespace namespace controller_manager @@ -1116,6 +1233,20 @@ controller_interface::return_type ControllerManager::switch_controller( controller.info.claimed_interfaces.clear(); } } + + // Reordering the controllers + std::sort( + to.begin(), to.end(), + std::bind( + &ControllerManager::controller_sorting, this, std::placeholders::_1, std::placeholders::_2, + to)); + + RCLCPP_DEBUG(get_logger(), "Reordered controllers list is:"); + for (const auto & ctrl : to) + { + RCLCPP_DEBUG(this->get_logger(), "\t%s", ctrl.info.name.c_str()); + } + // switch lists rt_controllers_wrapper_.switch_updated_list(guard); // clear unused list @@ -2280,6 +2411,99 @@ controller_interface::return_type ControllerManager::check_preceeding_controller } } return controller_interface::return_type::OK; +} + +bool ControllerManager::controller_sorting( + const ControllerSpec & ctrl_a, const ControllerSpec & ctrl_b, + const std::vector & controllers) +{ + // If the controllers are not active, then should be at the end of the list + if (!is_controller_active(ctrl_a.c) || !is_controller_active(ctrl_b.c)) + { + if (is_controller_active(ctrl_a.c)) return true; + return false; + } + + const std::vector cmd_itfs = ctrl_a.c->command_interface_configuration().names; + const std::vector state_itfs = ctrl_a.c->state_interface_configuration().names; + if (cmd_itfs.empty() || !ctrl_a.c->is_chainable()) + { + // The case of the controllers that don't have any command interfaces. For instance, + // joint_state_broadcaster + return true; + } + else + { + auto following_ctrls = get_following_controller_names(ctrl_a.info.name, controllers); + if (following_ctrls.empty()) return false; + // If the ctrl_b is any of the following controllers of ctrl_a, then place ctrl_a before ctrl_b + if ( + std::find(following_ctrls.begin(), following_ctrls.end(), ctrl_b.info.name) != + following_ctrls.end()) + return true; + else + { + auto ctrl_a_preceding_ctrls = get_preceding_controller_names(ctrl_a.info.name, controllers); + // This is to check that the ctrl_b is in the preceding controllers list of ctrl_a - This + // check is useful when there is a chained controller branching, but they belong to same + // branch + if ( + std::find(ctrl_a_preceding_ctrls.begin(), ctrl_a_preceding_ctrls.end(), ctrl_b.info.name) != + ctrl_a_preceding_ctrls.end()) + { + return false; + } + + // This is to handle the cases where, the parsed ctrl_a and ctrl_b are not directly related + // but might have a common parent - happens in branched chained controller + auto ctrl_b_preceding_ctrls = get_preceding_controller_names(ctrl_b.info.name, controllers); + std::sort(ctrl_a_preceding_ctrls.begin(), ctrl_a_preceding_ctrls.end()); + std::sort(ctrl_b_preceding_ctrls.begin(), ctrl_b_preceding_ctrls.end()); + std::list intersection; + std::set_intersection( + ctrl_a_preceding_ctrls.begin(), ctrl_a_preceding_ctrls.end(), + ctrl_b_preceding_ctrls.begin(), ctrl_b_preceding_ctrls.end(), + std::back_inserter(intersection)); + if (!intersection.empty()) + { + // If there is an intersection, then there is a common parent controller for both ctrl_a and + // ctrl_b + return true; + } + + // If there is no common parent, then they belong to 2 different sets + auto following_ctrls_b = get_following_controller_names(ctrl_b.info.name, controllers); + if (following_ctrls_b.empty()) return true; + auto find_first_element = [&](const auto & controllers_list) + { + auto it = std::find_if( + controllers.begin(), controllers.end(), + std::bind(controller_name_compare, std::placeholders::_1, controllers_list.back())); + if (it != controllers.end()) + { + int dist = std::distance(controllers.begin(), it); + return dist; + } + }; + const int ctrl_a_chain_first_controller = find_first_element(following_ctrls); + const int ctrl_b_chain_first_controller = find_first_element(following_ctrls_b); + if (ctrl_a_chain_first_controller < ctrl_b_chain_first_controller) return true; + } + + // If the ctrl_a's state interface is the one exported by the ctrl_b then ctrl_b should be + // infront of ctrl_a + // TODO(saikishor): deal with the state interface chaining in the sorting algorithm + auto state_it = std::find_if( + state_itfs.begin(), state_itfs.end(), + [ctrl_b](auto itf) { return (itf.find(ctrl_b.info.name) != std::string::npos); }); + if (state_it != state_itfs.end()) + { + return false; + } + + // The rest of the cases, basically end up at the end of the list + return false; + } }; void ControllerManager::controller_activity_diagnostic_callback( diff --git a/controller_manager/test/test_controller_manager_srvs.cpp b/controller_manager/test/test_controller_manager_srvs.cpp index adb227d6fe..583480d494 100644 --- a/controller_manager/test/test_controller_manager_srvs.cpp +++ b/controller_manager/test/test_controller_manager_srvs.cpp @@ -289,19 +289,19 @@ TEST_F(TestControllerManagerSrvs, list_chained_controllers_srv) controller_manager_msgs::srv::SwitchController::Request::STRICT, true, rclcpp::Duration(0, 0)); // get controller list after activate result = call_service_and_wait(*client, request, srv_executor); - // check chainable controller - ASSERT_EQ(result->controller[0].state, "active"); - ASSERT_EQ(result->controller[0].claimed_interfaces.size(), 1u); - ASSERT_EQ(result->controller[0].is_chained, true); // check test controller + ASSERT_EQ(result->controller[0].state, "active"); + ASSERT_EQ(result->controller[0].claimed_interfaces.size(), 3u); + // check chainable controller ASSERT_EQ(result->controller[1].state, "active"); - ASSERT_EQ(result->controller[1].claimed_interfaces.size(), 3u); + ASSERT_EQ(result->controller[1].claimed_interfaces.size(), 1u); + ASSERT_EQ(result->controller[1].is_chained, true); ASSERT_EQ( test_chainable_controller::TEST_CONTROLLER_NAME, - result->controller[1].chain_connections[0].name); - ASSERT_EQ(2u, result->controller[1].chain_connections[0].reference_interfaces.size()); - ASSERT_EQ("joint1/position", result->controller[1].chain_connections[0].reference_interfaces[0]); - ASSERT_EQ("joint1/velocity", result->controller[1].chain_connections[0].reference_interfaces[1]); + result->controller[0].chain_connections[0].name); + ASSERT_EQ(2u, result->controller[0].chain_connections[0].reference_interfaces.size()); + ASSERT_EQ("joint1/position", result->controller[0].chain_connections[0].reference_interfaces[0]); + ASSERT_EQ("joint1/velocity", result->controller[0].chain_connections[0].reference_interfaces[1]); } TEST_F(TestControllerManagerSrvs, reload_controller_libraries_srv) @@ -480,3 +480,586 @@ TEST_F(TestControllerManagerSrvs, configure_controller_srv) lifecycle_msgs::msg::State::PRIMARY_STATE_INACTIVE, cm_->get_loaded_controllers()[0].c->get_state().id()); } + +TEST_F(TestControllerManagerSrvs, list_sorted_chained_controllers) +{ + /// The simulated controller chaining is: + /// test_controller_name -> chain_ctrl_5 -> chain_ctrl_4 -> chain_ctrl_3 -> chain_ctrl_2 -> + /// chain_ctrl_1 + /// + /// NOTE: A -> B signifies that the controller A is utilizing the reference interfaces exported + /// from the controller B (or) the controller B is utilizing the expected interfaces exported from + /// the controller A + + // create server client and request + rclcpp::executors::SingleThreadedExecutor srv_executor; + rclcpp::Node::SharedPtr srv_node = std::make_shared("srv_client"); + srv_executor.add_node(srv_node); + rclcpp::Client::SharedPtr client = + srv_node->create_client("test_controller_manager/list_controllers"); + auto request = std::make_shared(); + + // create set of chained controllers + static constexpr char TEST_CHAINED_CONTROLLER_1[] = "test_chainable_controller_name_1"; + static constexpr char TEST_CHAINED_CONTROLLER_2[] = "test_chainable_controller_name_2"; + static constexpr char TEST_CHAINED_CONTROLLER_3[] = "test_chainable_controller_name_3"; + static constexpr char TEST_CHAINED_CONTROLLER_4[] = "test_chainable_controller_name_4"; + static constexpr char TEST_CHAINED_CONTROLLER_5[] = "test_chainable_controller_name_5"; + auto test_chained_controller_1 = std::make_shared(); + controller_interface::InterfaceConfiguration chained_cmd_cfg = { + controller_interface::interface_configuration_type::INDIVIDUAL, {"joint1/position"}}; + controller_interface::InterfaceConfiguration chained_state_cfg = { + controller_interface::interface_configuration_type::INDIVIDUAL, + {"joint1/position", "joint1/velocity"}}; + test_chained_controller_1->set_command_interface_configuration(chained_cmd_cfg); + test_chained_controller_1->set_state_interface_configuration(chained_state_cfg); + test_chained_controller_1->set_reference_interface_names({"joint1/position", "joint1/velocity"}); + + auto test_chained_controller_2 = std::make_shared(); + chained_cmd_cfg = { + controller_interface::interface_configuration_type::INDIVIDUAL, + {std::string(TEST_CHAINED_CONTROLLER_1) + "/joint1/position"}}; + test_chained_controller_2->set_command_interface_configuration(chained_cmd_cfg); + test_chained_controller_2->set_state_interface_configuration(chained_state_cfg); + test_chained_controller_2->set_reference_interface_names({"joint1/position", "joint1/velocity"}); + + auto test_chained_controller_3 = std::make_shared(); + chained_cmd_cfg = { + controller_interface::interface_configuration_type::INDIVIDUAL, + {std::string(TEST_CHAINED_CONTROLLER_2) + "/joint1/position"}}; + test_chained_controller_3->set_command_interface_configuration(chained_cmd_cfg); + test_chained_controller_3->set_state_interface_configuration(chained_state_cfg); + test_chained_controller_3->set_reference_interface_names({"joint1/position", "joint1/velocity"}); + + auto test_chained_controller_4 = std::make_shared(); + chained_cmd_cfg = { + controller_interface::interface_configuration_type::INDIVIDUAL, + {std::string(TEST_CHAINED_CONTROLLER_3) + "/joint1/position"}}; + test_chained_controller_4->set_command_interface_configuration(chained_cmd_cfg); + test_chained_controller_4->set_state_interface_configuration(chained_state_cfg); + test_chained_controller_4->set_reference_interface_names({"joint1/position", "joint1/velocity"}); + + auto test_chained_controller_5 = std::make_shared(); + chained_cmd_cfg = { + controller_interface::interface_configuration_type::INDIVIDUAL, + {std::string(TEST_CHAINED_CONTROLLER_4) + "/joint1/position"}}; + test_chained_controller_5->set_command_interface_configuration(chained_cmd_cfg); + test_chained_controller_5->set_state_interface_configuration(chained_state_cfg); + test_chained_controller_5->set_reference_interface_names({"joint1/position", "joint1/velocity"}); + + // create non-chained controller + auto test_controller = std::make_shared(); + controller_interface::InterfaceConfiguration cmd_cfg = { + controller_interface::interface_configuration_type::INDIVIDUAL, + {std::string(TEST_CHAINED_CONTROLLER_5) + "/joint1/position", + std::string(TEST_CHAINED_CONTROLLER_5) + "/joint1/velocity", "joint2/velocity"}}; + controller_interface::InterfaceConfiguration state_cfg = { + controller_interface::interface_configuration_type::INDIVIDUAL, + {"joint1/position", "joint1/velocity"}}; + test_controller->set_command_interface_configuration(cmd_cfg); + test_controller->set_state_interface_configuration(state_cfg); + // add controllers + cm_->add_controller( + test_chained_controller_4, TEST_CHAINED_CONTROLLER_4, + test_chainable_controller::TEST_CONTROLLER_CLASS_NAME); + cm_->add_controller( + test_chained_controller_1, TEST_CHAINED_CONTROLLER_1, + test_chainable_controller::TEST_CONTROLLER_CLASS_NAME); + cm_->add_controller( + test_chained_controller_3, TEST_CHAINED_CONTROLLER_3, + test_chainable_controller::TEST_CONTROLLER_CLASS_NAME); + cm_->add_controller( + test_chained_controller_5, TEST_CHAINED_CONTROLLER_5, + test_chainable_controller::TEST_CONTROLLER_CLASS_NAME); + cm_->add_controller( + test_chained_controller_2, TEST_CHAINED_CONTROLLER_2, + test_chainable_controller::TEST_CONTROLLER_CLASS_NAME); + cm_->add_controller( + test_controller, test_controller::TEST_CONTROLLER_NAME, + test_controller::TEST_CONTROLLER_CLASS_NAME); + // get controller list before configure + auto result = call_service_and_wait(*client, request, srv_executor); + // check chainable controller + ASSERT_EQ(6u, result->controller.size()); + ASSERT_EQ(result->controller[0].name, TEST_CHAINED_CONTROLLER_4); + ASSERT_EQ(result->controller[1].name, TEST_CHAINED_CONTROLLER_1); + ASSERT_EQ(result->controller[2].name, TEST_CHAINED_CONTROLLER_3); + ASSERT_EQ(result->controller[3].name, TEST_CHAINED_CONTROLLER_5); + ASSERT_EQ(result->controller[4].name, TEST_CHAINED_CONTROLLER_2); + // check test controller + ASSERT_EQ(result->controller[5].name, "test_controller_name"); + + // configure controllers + for (const auto & controller : + {TEST_CHAINED_CONTROLLER_4, TEST_CHAINED_CONTROLLER_3, TEST_CHAINED_CONTROLLER_5, + TEST_CHAINED_CONTROLLER_2, TEST_CHAINED_CONTROLLER_1, + test_controller::TEST_CONTROLLER_NAME}) + cm_->configure_controller(controller); + + // get controller list after configure + result = call_service_and_wait(*client, request, srv_executor); + ASSERT_EQ(6u, result->controller.size()); + + // activate controllers + cm_->switch_controller( + {TEST_CHAINED_CONTROLLER_1}, {}, + controller_manager_msgs::srv::SwitchController::Request::STRICT, true, rclcpp::Duration(0, 0)); + cm_->switch_controller( + {TEST_CHAINED_CONTROLLER_3, TEST_CHAINED_CONTROLLER_5, TEST_CHAINED_CONTROLLER_2, + TEST_CHAINED_CONTROLLER_4}, + {}, controller_manager_msgs::srv::SwitchController::Request::STRICT, true, + rclcpp::Duration(0, 0)); + cm_->switch_controller( + {test_controller::TEST_CONTROLLER_NAME}, {}, + controller_manager_msgs::srv::SwitchController::Request::STRICT, true, rclcpp::Duration(0, 0)); + // get controller list after activate + result = call_service_and_wait(*client, request, srv_executor); + + ASSERT_EQ(6u, result->controller.size()); + // reordered controllers + ASSERT_EQ(result->controller[0].name, "test_controller_name"); + ASSERT_EQ(result->controller[1].name, TEST_CHAINED_CONTROLLER_5); + ASSERT_EQ(result->controller[2].name, TEST_CHAINED_CONTROLLER_4); + ASSERT_EQ(result->controller[3].name, TEST_CHAINED_CONTROLLER_3); + ASSERT_EQ(result->controller[4].name, TEST_CHAINED_CONTROLLER_2); + ASSERT_EQ(result->controller[5].name, TEST_CHAINED_CONTROLLER_1); + RCLCPP_ERROR(srv_node->get_logger(), "Check successful!"); +} + +TEST_F(TestControllerManagerSrvs, list_sorted_complex_chained_controllers) +{ + /// The simulated controller chain branching is: + /// test_controller_name -> chain_ctrl_7 -> chain_ctrl_6 -> chain_ctrl_2 -> chain_ctrl_1 + /// & + /// chain_ctrl_6 -> chain_ctrl_5 -> chain_ctrl_4 -> chain_ctrl_3 + /// + /// NOTE: A -> B signifies that the controller A is utilizing the reference interfaces exported + /// from the controller B (or) the controller B is utilizing the expected interfaces exported from + /// the controller A + + // create server client and request + rclcpp::executors::SingleThreadedExecutor srv_executor; + rclcpp::Node::SharedPtr srv_node = std::make_shared("srv_client"); + srv_executor.add_node(srv_node); + rclcpp::Client::SharedPtr client = + srv_node->create_client("test_controller_manager/list_controllers"); + auto request = std::make_shared(); + + // create set of chained controllers + static constexpr char TEST_CHAINED_CONTROLLER_1[] = "test_chainable_controller_name_1"; + static constexpr char TEST_CHAINED_CONTROLLER_2[] = "test_chainable_controller_name_2"; + static constexpr char TEST_CHAINED_CONTROLLER_3[] = "test_chainable_controller_name_3"; + static constexpr char TEST_CHAINED_CONTROLLER_4[] = "test_chainable_controller_name_4"; + static constexpr char TEST_CHAINED_CONTROLLER_5[] = "test_chainable_controller_name_5"; + static constexpr char TEST_CHAINED_CONTROLLER_6[] = "test_chainable_controller_name_6"; + static constexpr char TEST_CHAINED_CONTROLLER_7[] = "test_chainable_controller_name_7"; + auto test_chained_controller_1 = std::make_shared(); + controller_interface::InterfaceConfiguration chained_cmd_cfg = { + controller_interface::interface_configuration_type::INDIVIDUAL, {"joint1/position"}}; + controller_interface::InterfaceConfiguration chained_state_cfg = { + controller_interface::interface_configuration_type::INDIVIDUAL, + {"joint1/position", "joint1/velocity", "joint2/velocity"}}; + test_chained_controller_1->set_command_interface_configuration(chained_cmd_cfg); + test_chained_controller_1->set_state_interface_configuration(chained_state_cfg); + test_chained_controller_1->set_reference_interface_names({"joint1/position", "joint1/velocity"}); + + auto test_chained_controller_2 = std::make_shared(); + chained_cmd_cfg = { + controller_interface::interface_configuration_type::INDIVIDUAL, + {std::string(TEST_CHAINED_CONTROLLER_1) + "/joint1/position"}}; + test_chained_controller_2->set_command_interface_configuration(chained_cmd_cfg); + test_chained_controller_2->set_state_interface_configuration(chained_state_cfg); + test_chained_controller_2->set_reference_interface_names({"joint1/position", "joint1/velocity"}); + + auto test_chained_controller_3 = std::make_shared(); + chained_cmd_cfg = { + controller_interface::interface_configuration_type::INDIVIDUAL, {"joint2/velocity"}}; + test_chained_controller_3->set_command_interface_configuration(chained_cmd_cfg); + test_chained_controller_3->set_state_interface_configuration(chained_state_cfg); + test_chained_controller_3->set_reference_interface_names({"joint2/velocity"}); + + auto test_chained_controller_4 = std::make_shared(); + chained_cmd_cfg = { + controller_interface::interface_configuration_type::INDIVIDUAL, + {std::string(TEST_CHAINED_CONTROLLER_3) + "/joint2/velocity"}}; + test_chained_controller_4->set_command_interface_configuration(chained_cmd_cfg); + test_chained_controller_4->set_state_interface_configuration(chained_state_cfg); + test_chained_controller_4->set_reference_interface_names({"joint2/velocity"}); + + auto test_chained_controller_5 = std::make_shared(); + chained_cmd_cfg = { + controller_interface::interface_configuration_type::INDIVIDUAL, + {std::string(TEST_CHAINED_CONTROLLER_4) + "/joint2/velocity"}}; + test_chained_controller_5->set_command_interface_configuration(chained_cmd_cfg); + test_chained_controller_5->set_state_interface_configuration(chained_state_cfg); + test_chained_controller_5->set_reference_interface_names({"joint2/velocity"}); + + auto test_chained_controller_6 = std::make_shared(); + chained_cmd_cfg = { + controller_interface::interface_configuration_type::INDIVIDUAL, + {std::string(TEST_CHAINED_CONTROLLER_2) + "/joint1/position", + std::string(TEST_CHAINED_CONTROLLER_5) + "/joint2/velocity"}}; + test_chained_controller_6->set_command_interface_configuration(chained_cmd_cfg); + test_chained_controller_6->set_state_interface_configuration(chained_state_cfg); + test_chained_controller_6->set_reference_interface_names({"joint1/position", "joint2/velocity"}); + + auto test_chained_controller_7 = std::make_shared(); + chained_cmd_cfg = { + controller_interface::interface_configuration_type::INDIVIDUAL, + {std::string(TEST_CHAINED_CONTROLLER_6) + "/joint1/position", + std::string(TEST_CHAINED_CONTROLLER_6) + "/joint2/velocity"}}; + test_chained_controller_7->set_command_interface_configuration(chained_cmd_cfg); + test_chained_controller_7->set_state_interface_configuration(chained_state_cfg); + test_chained_controller_7->set_reference_interface_names({"joint1/position", "joint2/velocity"}); + + // create non-chained controller + auto test_controller = std::make_shared(); + controller_interface::InterfaceConfiguration cmd_cfg = { + controller_interface::interface_configuration_type::INDIVIDUAL, + {std::string(TEST_CHAINED_CONTROLLER_7) + "/joint1/position", + std::string(TEST_CHAINED_CONTROLLER_7) + "/joint2/velocity"}}; + controller_interface::InterfaceConfiguration state_cfg = { + controller_interface::interface_configuration_type::INDIVIDUAL, + {"joint1/position", "joint2/velocity"}}; + test_controller->set_command_interface_configuration(cmd_cfg); + test_controller->set_state_interface_configuration(state_cfg); + // add controllers + cm_->add_controller( + test_chained_controller_4, TEST_CHAINED_CONTROLLER_4, + test_chainable_controller::TEST_CONTROLLER_CLASS_NAME); + cm_->add_controller( + test_chained_controller_1, TEST_CHAINED_CONTROLLER_1, + test_chainable_controller::TEST_CONTROLLER_CLASS_NAME); + cm_->add_controller( + test_chained_controller_3, TEST_CHAINED_CONTROLLER_3, + test_chainable_controller::TEST_CONTROLLER_CLASS_NAME); + cm_->add_controller( + test_chained_controller_5, TEST_CHAINED_CONTROLLER_5, + test_chainable_controller::TEST_CONTROLLER_CLASS_NAME); + cm_->add_controller( + test_chained_controller_6, TEST_CHAINED_CONTROLLER_6, + test_chainable_controller::TEST_CONTROLLER_CLASS_NAME); + cm_->add_controller( + test_chained_controller_2, TEST_CHAINED_CONTROLLER_2, + test_chainable_controller::TEST_CONTROLLER_CLASS_NAME); + cm_->add_controller( + test_controller, test_controller::TEST_CONTROLLER_NAME, + test_controller::TEST_CONTROLLER_CLASS_NAME); + cm_->add_controller( + test_chained_controller_7, TEST_CHAINED_CONTROLLER_7, + test_chainable_controller::TEST_CONTROLLER_CLASS_NAME); + // get controller list before configure + auto result = call_service_and_wait(*client, request, srv_executor); + // check chainable controller + ASSERT_EQ(8u, result->controller.size()); + ASSERT_EQ(result->controller[0].name, TEST_CHAINED_CONTROLLER_4); + ASSERT_EQ(result->controller[1].name, TEST_CHAINED_CONTROLLER_1); + ASSERT_EQ(result->controller[2].name, TEST_CHAINED_CONTROLLER_3); + ASSERT_EQ(result->controller[3].name, TEST_CHAINED_CONTROLLER_5); + ASSERT_EQ(result->controller[4].name, TEST_CHAINED_CONTROLLER_6); + ASSERT_EQ(result->controller[5].name, TEST_CHAINED_CONTROLLER_2); + // check test controller + ASSERT_EQ(result->controller[6].name, "test_controller_name"); + ASSERT_EQ(result->controller[7].name, TEST_CHAINED_CONTROLLER_7); + + // configure controllers + for (const auto & controller : + {TEST_CHAINED_CONTROLLER_4, TEST_CHAINED_CONTROLLER_3, TEST_CHAINED_CONTROLLER_5, + TEST_CHAINED_CONTROLLER_7, TEST_CHAINED_CONTROLLER_2, TEST_CHAINED_CONTROLLER_1, + TEST_CHAINED_CONTROLLER_6, test_controller::TEST_CONTROLLER_NAME}) + cm_->configure_controller(controller); + + // get controller list after configure + result = call_service_and_wait(*client, request, srv_executor); + ASSERT_EQ(8u, result->controller.size()); + + // activate controllers + cm_->switch_controller( + {TEST_CHAINED_CONTROLLER_1}, {}, + controller_manager_msgs::srv::SwitchController::Request::STRICT, true, rclcpp::Duration(0, 0)); + cm_->switch_controller( + {TEST_CHAINED_CONTROLLER_3}, {}, + controller_manager_msgs::srv::SwitchController::Request::STRICT, true, rclcpp::Duration(0, 0)); + cm_->switch_controller( + {TEST_CHAINED_CONTROLLER_6, TEST_CHAINED_CONTROLLER_5, TEST_CHAINED_CONTROLLER_2, + TEST_CHAINED_CONTROLLER_4, TEST_CHAINED_CONTROLLER_7}, + {}, controller_manager_msgs::srv::SwitchController::Request::STRICT, true, + rclcpp::Duration(0, 0)); + cm_->switch_controller( + {test_controller::TEST_CONTROLLER_NAME}, {}, + controller_manager_msgs::srv::SwitchController::Request::STRICT, true, rclcpp::Duration(0, 0)); + // get controller list after activate + result = call_service_and_wait(*client, request, srv_executor); + + ASSERT_EQ(8u, result->controller.size()); + // reordered controllers + ASSERT_EQ(result->controller[0].name, "test_controller_name"); + ASSERT_EQ(result->controller[1].name, TEST_CHAINED_CONTROLLER_7); + ASSERT_EQ(result->controller[2].name, TEST_CHAINED_CONTROLLER_6); + + auto get_ctrl_pos = [result](const std::string & controller_name) -> int + { + auto it = std::find_if( + result->controller.begin(), result->controller.end(), + [controller_name](auto itf) + { return (itf.name.find(controller_name) != std::string::npos); }); + return std::distance(result->controller.begin(), it); + }; + auto ctrl_1_pos = get_ctrl_pos(TEST_CHAINED_CONTROLLER_1); + auto ctrl_2_pos = get_ctrl_pos(TEST_CHAINED_CONTROLLER_2); + auto ctrl_3_pos = get_ctrl_pos(TEST_CHAINED_CONTROLLER_3); + auto ctrl_4_pos = get_ctrl_pos(TEST_CHAINED_CONTROLLER_4); + auto ctrl_5_pos = get_ctrl_pos(TEST_CHAINED_CONTROLLER_5); + auto ctrl_6_pos = get_ctrl_pos(TEST_CHAINED_CONTROLLER_6); + + // Extra check to see that they are index only after their parent controller (ctrl_6) + ASSERT_GT(ctrl_3_pos, ctrl_6_pos); + ASSERT_GT(ctrl_1_pos, ctrl_6_pos); + + // first branch + ASSERT_GT(ctrl_2_pos, ctrl_6_pos); + ASSERT_GT(ctrl_1_pos, ctrl_2_pos); + + // second branch + ASSERT_GT(ctrl_5_pos, ctrl_6_pos); + ASSERT_GT(ctrl_4_pos, ctrl_5_pos); + ASSERT_GT(ctrl_3_pos, ctrl_4_pos); +} + +TEST_F(TestControllerManagerSrvs, list_sorted_independent_chained_controllers) +{ + /// The simulated controller chaining is: + /// test_controller_name_1 -> chain_ctrl_3 -> chain_ctrl_2 -> chain_ctrl_1 + /// && + /// test_controller_name_2 -> chain_ctrl_6 -> chain_ctrl_5 -> chain_ctrl_4 + /// && + /// test_controller_name_7 -> test_controller_name_8 + /// + /// NOTE: A -> B signifies that the controller A is utilizing the reference interfaces exported + /// from the controller B (or) the controller B is utilizing the expected interfaces exported from + /// the controller A + + // create server client and request + rclcpp::executors::SingleThreadedExecutor srv_executor; + rclcpp::Node::SharedPtr srv_node = std::make_shared("srv_client"); + srv_executor.add_node(srv_node); + rclcpp::Client::SharedPtr client = + srv_node->create_client("test_controller_manager/list_controllers"); + auto request = std::make_shared(); + + // create set of chained controllers + static constexpr char TEST_CHAINED_CONTROLLER_1[] = "test_chainable_controller_name_1"; + static constexpr char TEST_CHAINED_CONTROLLER_2[] = "test_chainable_controller_name_2"; + static constexpr char TEST_CHAINED_CONTROLLER_3[] = "test_chainable_controller_name_3"; + static constexpr char TEST_CHAINED_CONTROLLER_4[] = "test_chainable_controller_name_4"; + static constexpr char TEST_CHAINED_CONTROLLER_5[] = "test_chainable_controller_name_5"; + static constexpr char TEST_CHAINED_CONTROLLER_6[] = "test_chainable_controller_name_6"; + static constexpr char TEST_CHAINED_CONTROLLER_7[] = "test_chainable_controller_name_7"; + static constexpr char TEST_CHAINED_CONTROLLER_8[] = "test_chainable_controller_name_8"; + static constexpr char TEST_CONTROLLER_1[] = "test_controller_name_1"; + static constexpr char TEST_CONTROLLER_2[] = "test_controller_name_2"; + + // First chain + auto test_chained_controller_1 = std::make_shared(); + controller_interface::InterfaceConfiguration chained_cmd_cfg = { + controller_interface::interface_configuration_type::INDIVIDUAL, {"joint1/position"}}; + controller_interface::InterfaceConfiguration chained_state_cfg = { + controller_interface::interface_configuration_type::INDIVIDUAL, + {"joint1/position", "joint1/velocity"}}; + test_chained_controller_1->set_command_interface_configuration(chained_cmd_cfg); + test_chained_controller_1->set_state_interface_configuration(chained_state_cfg); + test_chained_controller_1->set_reference_interface_names({"joint1/position", "joint1/velocity"}); + + auto test_chained_controller_2 = std::make_shared(); + chained_cmd_cfg = { + controller_interface::interface_configuration_type::INDIVIDUAL, + {std::string(TEST_CHAINED_CONTROLLER_1) + "/joint1/position"}}; + test_chained_controller_2->set_command_interface_configuration(chained_cmd_cfg); + test_chained_controller_2->set_state_interface_configuration(chained_state_cfg); + test_chained_controller_2->set_reference_interface_names({"joint1/position", "joint1/velocity"}); + + auto test_chained_controller_3 = std::make_shared(); + chained_cmd_cfg = { + controller_interface::interface_configuration_type::INDIVIDUAL, + {std::string(TEST_CHAINED_CONTROLLER_2) + "/joint1/position"}}; + test_chained_controller_3->set_command_interface_configuration(chained_cmd_cfg); + test_chained_controller_3->set_state_interface_configuration(chained_state_cfg); + test_chained_controller_3->set_reference_interface_names({"joint1/position", "joint1/velocity"}); + + auto test_controller_1 = std::make_shared(); + controller_interface::InterfaceConfiguration cmd_cfg = { + controller_interface::interface_configuration_type::INDIVIDUAL, + {std::string(TEST_CHAINED_CONTROLLER_3) + "/joint1/position", + std::string(TEST_CHAINED_CONTROLLER_3) + "/joint1/velocity"}}; + controller_interface::InterfaceConfiguration state_cfg = { + controller_interface::interface_configuration_type::INDIVIDUAL, + {"joint1/position", "joint1/velocity"}}; + test_controller_1->set_command_interface_configuration(cmd_cfg); + test_controller_1->set_state_interface_configuration(state_cfg); + + // Second chain + auto test_chained_controller_4 = std::make_shared(); + chained_cmd_cfg = { + controller_interface::interface_configuration_type::INDIVIDUAL, {"joint2/velocity"}}; + test_chained_controller_4->set_command_interface_configuration(chained_cmd_cfg); + test_chained_controller_4->set_state_interface_configuration(chained_state_cfg); + test_chained_controller_4->set_reference_interface_names({"joint2/velocity"}); + + auto test_chained_controller_5 = std::make_shared(); + chained_cmd_cfg = { + controller_interface::interface_configuration_type::INDIVIDUAL, + {std::string(TEST_CHAINED_CONTROLLER_4) + "/joint2/velocity"}}; + test_chained_controller_5->set_command_interface_configuration(chained_cmd_cfg); + test_chained_controller_5->set_state_interface_configuration(chained_state_cfg); + test_chained_controller_5->set_reference_interface_names({"joint2/velocity"}); + + auto test_chained_controller_6 = std::make_shared(); + chained_cmd_cfg = { + controller_interface::interface_configuration_type::INDIVIDUAL, + {std::string(TEST_CHAINED_CONTROLLER_5) + "/joint2/velocity"}}; + test_chained_controller_6->set_command_interface_configuration(chained_cmd_cfg); + test_chained_controller_6->set_state_interface_configuration(chained_state_cfg); + test_chained_controller_6->set_reference_interface_names({"joint2/velocity"}); + + auto test_controller_2 = std::make_shared(); + cmd_cfg = { + controller_interface::interface_configuration_type::INDIVIDUAL, + {std::string(TEST_CHAINED_CONTROLLER_6) + "/joint2/velocity"}}; + state_cfg = {controller_interface::interface_configuration_type::INDIVIDUAL, {"joint2/velocity"}}; + test_controller_2->set_command_interface_configuration(cmd_cfg); + test_controller_2->set_state_interface_configuration(state_cfg); + + // Third chain + auto test_chained_controller_7 = std::make_shared(); + chained_cmd_cfg = { + controller_interface::interface_configuration_type::INDIVIDUAL, {"joint3/velocity"}}; + test_chained_controller_7->set_command_interface_configuration(chained_cmd_cfg); + test_chained_controller_7->set_state_interface_configuration(chained_state_cfg); + test_chained_controller_7->set_reference_interface_names({"joint3/velocity"}); + + auto test_chained_controller_8 = std::make_shared(); + chained_cmd_cfg = { + controller_interface::interface_configuration_type::INDIVIDUAL, + {std::string(TEST_CHAINED_CONTROLLER_7) + "/joint3/velocity"}}; + test_chained_controller_8->set_command_interface_configuration(chained_cmd_cfg); + test_chained_controller_8->set_state_interface_configuration(chained_state_cfg); + test_chained_controller_8->set_reference_interface_names({"joint3/velocity"}); + + // add controllers + /// @todo add controllers in random order + /// For now, adding the ordered case to see that current sorting doesn't change order + cm_->add_controller( + test_chained_controller_2, TEST_CHAINED_CONTROLLER_2, + test_chainable_controller::TEST_CONTROLLER_CLASS_NAME); + cm_->add_controller( + test_chained_controller_6, TEST_CHAINED_CONTROLLER_6, + test_chainable_controller::TEST_CONTROLLER_CLASS_NAME); + cm_->add_controller( + test_chained_controller_1, TEST_CHAINED_CONTROLLER_1, + test_chainable_controller::TEST_CONTROLLER_CLASS_NAME); + cm_->add_controller( + test_chained_controller_7, TEST_CHAINED_CONTROLLER_7, + test_chainable_controller::TEST_CONTROLLER_CLASS_NAME); + cm_->add_controller( + test_controller_1, TEST_CONTROLLER_1, test_controller::TEST_CONTROLLER_CLASS_NAME); + cm_->add_controller( + test_chained_controller_5, TEST_CHAINED_CONTROLLER_5, + test_chainable_controller::TEST_CONTROLLER_CLASS_NAME); + cm_->add_controller( + test_chained_controller_3, TEST_CHAINED_CONTROLLER_3, + test_chainable_controller::TEST_CONTROLLER_CLASS_NAME); + cm_->add_controller( + test_chained_controller_4, TEST_CHAINED_CONTROLLER_4, + test_chainable_controller::TEST_CONTROLLER_CLASS_NAME); + cm_->add_controller( + test_controller_2, TEST_CONTROLLER_2, test_controller::TEST_CONTROLLER_CLASS_NAME); + cm_->add_controller( + test_chained_controller_8, TEST_CHAINED_CONTROLLER_8, + test_chainable_controller::TEST_CONTROLLER_CLASS_NAME); + + // get controller list before configure + auto result = call_service_and_wait(*client, request, srv_executor); + + // check chainable controller + ASSERT_EQ(10u, result->controller.size()); + EXPECT_EQ(result->controller[0].name, TEST_CHAINED_CONTROLLER_2); + EXPECT_EQ(result->controller[1].name, TEST_CHAINED_CONTROLLER_6); + EXPECT_EQ(result->controller[2].name, TEST_CHAINED_CONTROLLER_1); + EXPECT_EQ(result->controller[3].name, TEST_CHAINED_CONTROLLER_7); + EXPECT_EQ(result->controller[4].name, TEST_CONTROLLER_1); + + EXPECT_EQ(result->controller[5].name, TEST_CHAINED_CONTROLLER_5); + EXPECT_EQ(result->controller[6].name, TEST_CHAINED_CONTROLLER_3); + EXPECT_EQ(result->controller[7].name, TEST_CHAINED_CONTROLLER_4); + EXPECT_EQ(result->controller[8].name, TEST_CONTROLLER_2); + EXPECT_EQ(result->controller[9].name, TEST_CHAINED_CONTROLLER_8); + + // configure controllers + auto ctrls_order = {TEST_CHAINED_CONTROLLER_3, TEST_CHAINED_CONTROLLER_5, + TEST_CHAINED_CONTROLLER_1, TEST_CONTROLLER_1, + TEST_CHAINED_CONTROLLER_4, TEST_CONTROLLER_2, + TEST_CHAINED_CONTROLLER_2, TEST_CHAINED_CONTROLLER_6, + TEST_CHAINED_CONTROLLER_7, TEST_CHAINED_CONTROLLER_8}; + for (const auto & controller : ctrls_order) cm_->configure_controller(controller); + + // get controller list after configure + result = call_service_and_wait(*client, request, srv_executor); + ASSERT_EQ(10u, result->controller.size()); + + // activate controllers + cm_->switch_controller( + {TEST_CHAINED_CONTROLLER_1}, {}, + controller_manager_msgs::srv::SwitchController::Request::STRICT, true, rclcpp::Duration(0, 0)); + cm_->switch_controller( + {TEST_CHAINED_CONTROLLER_4}, {}, + controller_manager_msgs::srv::SwitchController::Request::STRICT, true, rclcpp::Duration(0, 0)); + cm_->switch_controller( + {TEST_CHAINED_CONTROLLER_7}, {}, + controller_manager_msgs::srv::SwitchController::Request::STRICT, true, rclcpp::Duration(0, 0)); + cm_->switch_controller( + {TEST_CHAINED_CONTROLLER_3, TEST_CHAINED_CONTROLLER_5, TEST_CHAINED_CONTROLLER_2, + TEST_CHAINED_CONTROLLER_6, TEST_CHAINED_CONTROLLER_8}, + {}, controller_manager_msgs::srv::SwitchController::Request::STRICT, true, + rclcpp::Duration(0, 0)); + cm_->switch_controller( + {TEST_CONTROLLER_1, TEST_CONTROLLER_2}, {}, + controller_manager_msgs::srv::SwitchController::Request::STRICT, true, rclcpp::Duration(0, 0)); + // get controller list after activate + result = call_service_and_wait(*client, request, srv_executor); + + ASSERT_EQ(10u, result->controller.size()); + + auto get_ctrl_pos = [result](const std::string & controller_name) -> int + { + auto it = std::find_if( + result->controller.begin(), result->controller.end(), + [controller_name](auto itf) + { return (itf.name.find(controller_name) != std::string::npos); }); + return std::distance(result->controller.begin(), it); + }; + auto ctrl_chain_1_pos = get_ctrl_pos(TEST_CHAINED_CONTROLLER_1); + auto ctrl_chain_2_pos = get_ctrl_pos(TEST_CHAINED_CONTROLLER_2); + auto ctrl_chain_3_pos = get_ctrl_pos(TEST_CHAINED_CONTROLLER_3); + auto ctrl_chain_4_pos = get_ctrl_pos(TEST_CHAINED_CONTROLLER_4); + auto ctrl_chain_5_pos = get_ctrl_pos(TEST_CHAINED_CONTROLLER_5); + auto ctrl_chain_6_pos = get_ctrl_pos(TEST_CHAINED_CONTROLLER_6); + auto ctrl_chain_7_pos = get_ctrl_pos(TEST_CHAINED_CONTROLLER_7); + auto ctrl_chain_8_pos = get_ctrl_pos(TEST_CHAINED_CONTROLLER_8); + + auto ctrl_1_pos = get_ctrl_pos(TEST_CONTROLLER_1); + auto ctrl_2_pos = get_ctrl_pos(TEST_CONTROLLER_2); + + // Extra check to see that they are indexed after their parent controller + // first chain + ASSERT_GT(ctrl_chain_1_pos, ctrl_chain_2_pos); + ASSERT_GT(ctrl_chain_2_pos, ctrl_chain_3_pos); + ASSERT_GT(ctrl_chain_3_pos, ctrl_1_pos); + + // second tree + ASSERT_GT(ctrl_chain_4_pos, ctrl_chain_5_pos); + ASSERT_GT(ctrl_chain_5_pos, ctrl_chain_6_pos); + ASSERT_GT(ctrl_chain_6_pos, ctrl_2_pos); + + // third tree + ASSERT_GT(ctrl_chain_7_pos, ctrl_chain_8_pos); +} diff --git a/controller_manager/test/test_controllers_chaining_with_controller_manager.cpp b/controller_manager/test/test_controllers_chaining_with_controller_manager.cpp index 62babe998d..16ba39d953 100644 --- a/controller_manager/test/test_controllers_chaining_with_controller_manager.cpp +++ b/controller_manager/test/test_controllers_chaining_with_controller_manager.cpp @@ -52,6 +52,8 @@ class TestableTestChainableController : public test_chainable_controller::TestCh FRIEND_TEST( TestControllerChainingWithControllerManager, test_chained_controllers_deactivation_error_handling); + FRIEND_TEST( + TestControllerChainingWithControllerManager, test_chained_controllers_adding_in_random_order); }; class TestableControllerManager : public controller_manager::ControllerManager @@ -84,6 +86,8 @@ class TestableControllerManager : public controller_manager::ControllerManager FRIEND_TEST( TestControllerChainingWithControllerManager, test_chained_controllers_deactivation_error_handling); + FRIEND_TEST( + TestControllerChainingWithControllerManager, test_chained_controllers_adding_in_random_order); public: TestableControllerManager( @@ -975,10 +979,132 @@ TEST_P( lifecycle_msgs::msg::State::PRIMARY_STATE_ACTIVE, diff_drive_controller->get_state().id()); } -// TODO(destogl): Add test case with controllers added in "random" order -// -// new value: "START_DOWNSTREAM_CTRLS" --> start "downstream" controllers in a controllers chain -// +TEST_P(TestControllerChainingWithControllerManager, test_chained_controllers_adding_in_random_order) +{ + SetupControllers(); + + // add all controllers in random order to test the sorting + cm_->add_controller( + pid_left_wheel_controller, PID_LEFT_WHEEL, + test_chainable_controller::TEST_CONTROLLER_CLASS_NAME); + cm_->add_controller( + pid_right_wheel_controller, PID_RIGHT_WHEEL, + test_chainable_controller::TEST_CONTROLLER_CLASS_NAME); + cm_->add_controller( + position_tracking_controller, POSITION_TRACKING_CONTROLLER, + test_chainable_controller::TEST_CONTROLLER_CLASS_NAME); + cm_->add_controller( + diff_drive_controller, DIFF_DRIVE_CONTROLLER, + test_chainable_controller::TEST_CONTROLLER_CLASS_NAME); + cm_->add_controller( + diff_drive_controller_two, DIFF_DRIVE_CONTROLLER_TWO, + test_chainable_controller::TEST_CONTROLLER_CLASS_NAME); + + CheckIfControllersAreAddedCorrectly(); + + ConfigureAndCheckControllers(); + + SetToChainedModeAndMakeReferenceInterfacesAvailable( + pid_left_wheel_controller, PID_LEFT_WHEEL, PID_LEFT_WHEEL_REFERENCE_INTERFACES); + SetToChainedModeAndMakeReferenceInterfacesAvailable( + pid_right_wheel_controller, PID_RIGHT_WHEEL, PID_RIGHT_WHEEL_REFERENCE_INTERFACES); + SetToChainedModeAndMakeReferenceInterfacesAvailable( + diff_drive_controller, DIFF_DRIVE_CONTROLLER, DIFF_DRIVE_REFERENCE_INTERFACES); + + EXPECT_THROW( + cm_->resource_manager_->make_controller_reference_interfaces_available( + POSITION_TRACKING_CONTROLLER), + std::out_of_range); + + // Set ControllerManager into Debug-Mode output to have detailed output on updating controllers + cm_->get_logger().set_level(rclcpp::Logger::Level::Debug); + + // activate controllers - CONTROLLERS HAVE TO ADDED REVERSE EXECUTION ORDER + // (otherwise, interface will be missing) + ActivateAndCheckController( + pid_left_wheel_controller, PID_LEFT_WHEEL, PID_LEFT_WHEEL_CLAIMED_INTERFACES, 1u); + ActivateAndCheckController( + pid_right_wheel_controller, PID_RIGHT_WHEEL, PID_RIGHT_WHEEL_CLAIMED_INTERFACES, 1u); + ASSERT_EQ(pid_left_wheel_controller->internal_counter, 3u); + + // Diff-Drive Controller claims the reference interfaces of PID controllers + ActivateAndCheckController( + diff_drive_controller, DIFF_DRIVE_CONTROLLER, DIFF_DRIVE_CLAIMED_INTERFACES, 1u); + ASSERT_EQ(pid_right_wheel_controller->internal_counter, 3u); + ASSERT_EQ(pid_left_wheel_controller->internal_counter, 5u); + + // Position-Tracking Controller uses reference interfaces of Diff-Drive Controller + ActivateAndCheckController( + position_tracking_controller, POSITION_TRACKING_CONTROLLER, + POSITION_CONTROLLER_CLAIMED_INTERFACES, 1u); + // 'rot_z' reference interface is not claimed + for (const auto & interface : {"diff_drive_controller/rot_z"}) + { + EXPECT_TRUE(cm_->resource_manager_->command_interface_exists(interface)); + EXPECT_TRUE(cm_->resource_manager_->command_interface_is_available(interface)); + EXPECT_FALSE(cm_->resource_manager_->command_interface_is_claimed(interface)); + } + ASSERT_EQ(diff_drive_controller->internal_counter, 3u); + ASSERT_EQ(pid_right_wheel_controller->internal_counter, 5u); + ASSERT_EQ(pid_left_wheel_controller->internal_counter, 7u); + + // update controllers + std::vector reference = {32.0, 128.0}; + + // update 'Position Tracking' controller + for (auto & value : diff_drive_controller->reference_interfaces_) + { + ASSERT_EQ(value, 0.0); // default reference values are 0.0 + } + position_tracking_controller->external_commands_for_testing_[0] = reference[0]; + position_tracking_controller->external_commands_for_testing_[1] = reference[1]; + position_tracking_controller->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)); + ASSERT_EQ(position_tracking_controller->internal_counter, 2u); + + ASSERT_EQ(diff_drive_controller->reference_interfaces_[0], reference[0]); // position_controller + ASSERT_EQ(diff_drive_controller->reference_interfaces_[1], reference[1]); // is pass-through + + // update 'Diff Drive' Controller + diff_drive_controller->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)); + ASSERT_EQ(diff_drive_controller->internal_counter, 4u); + // default reference values are 0.0 - they should be changed now + EXP_LEFT_WHEEL_REF = chained_ctrl_calculation(reference[0], EXP_LEFT_WHEEL_HW_STATE); // 32-0 + EXP_RIGHT_WHEEL_REF = chained_ctrl_calculation(reference[1], EXP_RIGHT_WHEEL_HW_STATE); // 128-0 + ASSERT_EQ(pid_left_wheel_controller->reference_interfaces_[0], EXP_LEFT_WHEEL_REF); + ASSERT_EQ(pid_right_wheel_controller->reference_interfaces_[0], EXP_RIGHT_WHEEL_REF); + + // update PID controllers that are writing to hardware + pid_left_wheel_controller->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)); + ASSERT_EQ(pid_left_wheel_controller->internal_counter, 8u); + pid_right_wheel_controller->update(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)); + ASSERT_EQ(pid_right_wheel_controller->internal_counter, 6u); + + // update hardware ('read' is sufficient for test hardware) + cm_->resource_manager_->read(rclcpp::Time(0), rclcpp::Duration::from_seconds(0.01)); + // 32 - 0 + EXP_LEFT_WHEEL_CMD = chained_ctrl_calculation(EXP_LEFT_WHEEL_REF, EXP_LEFT_WHEEL_HW_STATE); + // 32 / 2 + EXP_LEFT_WHEEL_HW_STATE = hardware_calculation(EXP_LEFT_WHEEL_CMD); + ASSERT_EQ(pid_left_wheel_controller->command_interfaces_[0].get_value(), EXP_LEFT_WHEEL_CMD); + ASSERT_EQ(pid_left_wheel_controller->state_interfaces_[0].get_value(), EXP_LEFT_WHEEL_HW_STATE); + // DiffDrive uses the same state + ASSERT_EQ(diff_drive_controller->state_interfaces_[0].get_value(), EXP_LEFT_WHEEL_HW_STATE); + + // 128 - 0 + EXP_RIGHT_WHEEL_CMD = chained_ctrl_calculation(EXP_RIGHT_WHEEL_REF, EXP_RIGHT_WHEEL_HW_STATE); + // 128 / 2 + EXP_RIGHT_WHEEL_HW_STATE = hardware_calculation(EXP_RIGHT_WHEEL_CMD); + ASSERT_EQ(pid_right_wheel_controller->command_interfaces_[0].get_value(), EXP_RIGHT_WHEEL_CMD); + ASSERT_EQ(pid_right_wheel_controller->state_interfaces_[0].get_value(), EXP_RIGHT_WHEEL_HW_STATE); + // DiffDrive uses the same state + ASSERT_EQ(diff_drive_controller->state_interfaces_[1].get_value(), EXP_RIGHT_WHEEL_HW_STATE); + + // update all controllers at once and see that all have expected values --> also checks the order + // of controller execution + + reference = {1024.0, 4096.0}; + UpdateAllControllerAndCheck(reference, 3u); +} INSTANTIATE_TEST_SUITE_P( test_strict_best_effort, TestControllerChainingWithControllerManager, From bcdc5bb25c30caa2398895d04c3b9abc44c7527b Mon Sep 17 00:00:00 2001 From: flochre <39066045+flochre@users.noreply.github.com> Date: Tue, 15 Aug 2023 08:01:23 +0200 Subject: [PATCH 38/40] add a broadcaster for range sensor (#1091) --- .../semantic_components/range_sensor.hpp | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 controller_interface/include/semantic_components/range_sensor.hpp diff --git a/controller_interface/include/semantic_components/range_sensor.hpp b/controller_interface/include/semantic_components/range_sensor.hpp new file mode 100644 index 0000000000..baa9022c75 --- /dev/null +++ b/controller_interface/include/semantic_components/range_sensor.hpp @@ -0,0 +1,60 @@ +// 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. + +#ifndef SEMANTIC_COMPONENTS__RANGE_SENSOR_HPP_ +#define SEMANTIC_COMPONENTS__RANGE_SENSOR_HPP_ + +#include +#include +#include + +#include "semantic_components/semantic_component_interface.hpp" +#include "sensor_msgs/msg/range.hpp" + +namespace semantic_components +{ +class RangeSensor : public SemanticComponentInterface +{ +public: + explicit RangeSensor(const std::string & name) : SemanticComponentInterface(name, 1) + { + interface_names_.emplace_back(name_ + "/" + "range"); + } + + virtual ~RangeSensor() = default; + + /** + * Return Range reported by a sensor + * + * \return value of the range in meters + */ + float get_range() { return state_interfaces_[0].get().get_value(); } + + /// Return Range message with range in meters + /** + * Constructs and return a Range message from the current values. + * \return Range message from values; + */ + bool get_values_as_message(sensor_msgs::msg::Range & message) + { + // update the message values + message.range = get_range(); + + return true; + } +}; + +} // namespace semantic_components + +#endif // SEMANTIC_COMPONENTS__RANGE_SENSOR_HPP_ From 43d86bbb5a1b53f2b204ea4a6b8d18647c78c0db Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Thu, 17 Aug 2023 13:37:02 +0100 Subject: [PATCH 39/40] Update changelogs --- controller_interface/CHANGELOG.rst | 5 +++++ controller_manager/CHANGELOG.rst | 5 +++++ controller_manager_msgs/CHANGELOG.rst | 3 +++ hardware_interface/CHANGELOG.rst | 3 +++ joint_limits/CHANGELOG.rst | 3 +++ ros2_control/CHANGELOG.rst | 3 +++ ros2_control_test_assets/CHANGELOG.rst | 3 +++ ros2controlcli/CHANGELOG.rst | 3 +++ rqt_controller_manager/CHANGELOG.rst | 3 +++ transmission_interface/CHANGELOG.rst | 3 +++ 10 files changed, 34 insertions(+) diff --git a/controller_interface/CHANGELOG.rst b/controller_interface/CHANGELOG.rst index bd2d30f543..5136fd4aa2 100644 --- a/controller_interface/CHANGELOG.rst +++ b/controller_interface/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package controller_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* add a broadcaster for range sensor (`#1091 `_) +* Contributors: flochre + 3.17.0 (2023-08-07) ------------------- diff --git a/controller_manager/CHANGELOG.rst b/controller_manager/CHANGELOG.rst index 3deafc5565..81b38daf71 100644 --- a/controller_manager/CHANGELOG.rst +++ b/controller_manager/CHANGELOG.rst @@ -2,6 +2,11 @@ Changelog for package controller_manager ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- +* Controller sorting and proper execution in a chain (Fixes `#853 `_) (`#1063 `_) +* Contributors: Sai Kishor Kothakota, Christoph Fröhlich, Dr Denis, Bence Magyar + 3.17.0 (2023-08-07) ------------------- * [CM] Fixes the issue with individual controller's update rate (`#1082 `_) diff --git a/controller_manager_msgs/CHANGELOG.rst b/controller_manager_msgs/CHANGELOG.rst index 57bb1595ff..e2ea36bdff 100644 --- a/controller_manager_msgs/CHANGELOG.rst +++ b/controller_manager_msgs/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package controller_manager_msgs ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.17.0 (2023-08-07) ------------------- diff --git a/hardware_interface/CHANGELOG.rst b/hardware_interface/CHANGELOG.rst index 6ca31d134a..c368c0eb64 100644 --- a/hardware_interface/CHANGELOG.rst +++ b/hardware_interface/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package hardware_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.17.0 (2023-08-07) ------------------- * Add checks if hardware is initialized. (`#1054 `_) diff --git a/joint_limits/CHANGELOG.rst b/joint_limits/CHANGELOG.rst index 313a4d83ed..8c74220aa4 100644 --- a/joint_limits/CHANGELOG.rst +++ b/joint_limits/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package joint_limits ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.17.0 (2023-08-07) ------------------- diff --git a/ros2_control/CHANGELOG.rst b/ros2_control/CHANGELOG.rst index b400547e27..4e1f14d790 100644 --- a/ros2_control/CHANGELOG.rst +++ b/ros2_control/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_control ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.17.0 (2023-08-07) ------------------- diff --git a/ros2_control_test_assets/CHANGELOG.rst b/ros2_control_test_assets/CHANGELOG.rst index fc362d9f3a..75715f5a73 100644 --- a/ros2_control_test_assets/CHANGELOG.rst +++ b/ros2_control_test_assets/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2_control_test_assets ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.17.0 (2023-08-07) ------------------- diff --git a/ros2controlcli/CHANGELOG.rst b/ros2controlcli/CHANGELOG.rst index 1a8b32b1d3..14048154ee 100644 --- a/ros2controlcli/CHANGELOG.rst +++ b/ros2controlcli/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package ros2controlcli ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.17.0 (2023-08-07) ------------------- * Add info where the pdf is saved to view_controller_chains (`#1094 `_) diff --git a/rqt_controller_manager/CHANGELOG.rst b/rqt_controller_manager/CHANGELOG.rst index 1b79cea368..99f8f6d91f 100644 --- a/rqt_controller_manager/CHANGELOG.rst +++ b/rqt_controller_manager/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package rqt_controller_manager ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.17.0 (2023-08-07) ------------------- diff --git a/transmission_interface/CHANGELOG.rst b/transmission_interface/CHANGELOG.rst index e3e1d776f0..6d1d67a2d9 100644 --- a/transmission_interface/CHANGELOG.rst +++ b/transmission_interface/CHANGELOG.rst @@ -2,6 +2,9 @@ Changelog for package transmission_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Forthcoming +----------- + 3.17.0 (2023-08-07) ------------------- From 33e77b8d28cc5a29780b0a13f669934c564a5d8c Mon Sep 17 00:00:00 2001 From: Bence Magyar Date: Thu, 17 Aug 2023 13:37:18 +0100 Subject: [PATCH 40/40] 3.18.0 --- controller_interface/CHANGELOG.rst | 4 ++-- controller_interface/package.xml | 2 +- controller_manager/CHANGELOG.rst | 4 ++-- controller_manager/package.xml | 2 +- controller_manager_msgs/CHANGELOG.rst | 4 ++-- controller_manager_msgs/package.xml | 2 +- hardware_interface/CHANGELOG.rst | 4 ++-- hardware_interface/package.xml | 2 +- joint_limits/CHANGELOG.rst | 4 ++-- joint_limits/package.xml | 2 +- ros2_control/CHANGELOG.rst | 4 ++-- ros2_control/package.xml | 2 +- ros2_control_test_assets/CHANGELOG.rst | 4 ++-- ros2_control_test_assets/package.xml | 2 +- ros2controlcli/CHANGELOG.rst | 4 ++-- ros2controlcli/package.xml | 2 +- ros2controlcli/setup.py | 2 +- rqt_controller_manager/CHANGELOG.rst | 4 ++-- rqt_controller_manager/package.xml | 2 +- rqt_controller_manager/setup.py | 2 +- transmission_interface/CHANGELOG.rst | 4 ++-- transmission_interface/package.xml | 2 +- 22 files changed, 32 insertions(+), 32 deletions(-) diff --git a/controller_interface/CHANGELOG.rst b/controller_interface/CHANGELOG.rst index 5136fd4aa2..aaa2667a06 100644 --- a/controller_interface/CHANGELOG.rst +++ b/controller_interface/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package controller_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.18.0 (2023-08-17) +------------------- * add a broadcaster for range sensor (`#1091 `_) * Contributors: flochre diff --git a/controller_interface/package.xml b/controller_interface/package.xml index c0d8c271bd..d960bdf28a 100644 --- a/controller_interface/package.xml +++ b/controller_interface/package.xml @@ -2,7 +2,7 @@ controller_interface - 3.17.0 + 3.18.0 Description of controller_interface Bence Magyar Denis Štogl diff --git a/controller_manager/CHANGELOG.rst b/controller_manager/CHANGELOG.rst index 81b38daf71..2a9e348b8e 100644 --- a/controller_manager/CHANGELOG.rst +++ b/controller_manager/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package controller_manager ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.18.0 (2023-08-17) +------------------- * Controller sorting and proper execution in a chain (Fixes `#853 `_) (`#1063 `_) * Contributors: Sai Kishor Kothakota, Christoph Fröhlich, Dr Denis, Bence Magyar diff --git a/controller_manager/package.xml b/controller_manager/package.xml index 1d9b7821aa..adb6769d9c 100644 --- a/controller_manager/package.xml +++ b/controller_manager/package.xml @@ -2,7 +2,7 @@ controller_manager - 3.17.0 + 3.18.0 Description of controller_manager Bence Magyar Denis Štogl diff --git a/controller_manager_msgs/CHANGELOG.rst b/controller_manager_msgs/CHANGELOG.rst index e2ea36bdff..8072652c55 100644 --- a/controller_manager_msgs/CHANGELOG.rst +++ b/controller_manager_msgs/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package controller_manager_msgs ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.18.0 (2023-08-17) +------------------- 3.17.0 (2023-08-07) ------------------- diff --git a/controller_manager_msgs/package.xml b/controller_manager_msgs/package.xml index f55673871c..f7b9eb5642 100644 --- a/controller_manager_msgs/package.xml +++ b/controller_manager_msgs/package.xml @@ -2,7 +2,7 @@ controller_manager_msgs - 3.17.0 + 3.18.0 Messages and services for the controller manager. Bence Magyar Denis Štogl diff --git a/hardware_interface/CHANGELOG.rst b/hardware_interface/CHANGELOG.rst index c368c0eb64..0428cf4f8e 100644 --- a/hardware_interface/CHANGELOG.rst +++ b/hardware_interface/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package hardware_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.18.0 (2023-08-17) +------------------- 3.17.0 (2023-08-07) ------------------- diff --git a/hardware_interface/package.xml b/hardware_interface/package.xml index fbe85e48e8..e3a2f4f71e 100644 --- a/hardware_interface/package.xml +++ b/hardware_interface/package.xml @@ -1,7 +1,7 @@ hardware_interface - 3.17.0 + 3.18.0 ros2_control hardware interface Bence Magyar Denis Štogl diff --git a/joint_limits/CHANGELOG.rst b/joint_limits/CHANGELOG.rst index 8c74220aa4..46acee3f8d 100644 --- a/joint_limits/CHANGELOG.rst +++ b/joint_limits/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package joint_limits ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.18.0 (2023-08-17) +------------------- 3.17.0 (2023-08-07) ------------------- diff --git a/joint_limits/package.xml b/joint_limits/package.xml index 52e4bb82d1..f1c0365cfd 100644 --- a/joint_limits/package.xml +++ b/joint_limits/package.xml @@ -1,6 +1,6 @@ joint_limits - 3.17.0 + 3.18.0 Interfaces for handling of joint limits for controllers or hardware. Bence Magyar diff --git a/ros2_control/CHANGELOG.rst b/ros2_control/CHANGELOG.rst index 4e1f14d790..272c2d3fe4 100644 --- a/ros2_control/CHANGELOG.rst +++ b/ros2_control/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_control ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.18.0 (2023-08-17) +------------------- 3.17.0 (2023-08-07) ------------------- diff --git a/ros2_control/package.xml b/ros2_control/package.xml index 74b1bc46cc..15a379933a 100644 --- a/ros2_control/package.xml +++ b/ros2_control/package.xml @@ -1,7 +1,7 @@ ros2_control - 3.17.0 + 3.18.0 Metapackage for ROS2 control related packages Bence Magyar Denis Štogl diff --git a/ros2_control_test_assets/CHANGELOG.rst b/ros2_control_test_assets/CHANGELOG.rst index 75715f5a73..d633c415d1 100644 --- a/ros2_control_test_assets/CHANGELOG.rst +++ b/ros2_control_test_assets/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2_control_test_assets ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.18.0 (2023-08-17) +------------------- 3.17.0 (2023-08-07) ------------------- diff --git a/ros2_control_test_assets/package.xml b/ros2_control_test_assets/package.xml index a2ce000ccd..c77b828276 100644 --- a/ros2_control_test_assets/package.xml +++ b/ros2_control_test_assets/package.xml @@ -2,7 +2,7 @@ ros2_control_test_assets - 3.17.0 + 3.18.0 The package provides shared test resources for ros2_control stack Bence Magyar diff --git a/ros2controlcli/CHANGELOG.rst b/ros2controlcli/CHANGELOG.rst index 14048154ee..a5a153faf1 100644 --- a/ros2controlcli/CHANGELOG.rst +++ b/ros2controlcli/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package ros2controlcli ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.18.0 (2023-08-17) +------------------- 3.17.0 (2023-08-07) ------------------- diff --git a/ros2controlcli/package.xml b/ros2controlcli/package.xml index 1af234dcf3..92eba51b62 100644 --- a/ros2controlcli/package.xml +++ b/ros2controlcli/package.xml @@ -2,7 +2,7 @@ ros2controlcli - 3.17.0 + 3.18.0 The ROS 2 command line tools for ROS2 Control. diff --git a/ros2controlcli/setup.py b/ros2controlcli/setup.py index 49d96a5eb6..aa2b19b830 100644 --- a/ros2controlcli/setup.py +++ b/ros2controlcli/setup.py @@ -19,7 +19,7 @@ setup( name=package_name, - version="3.17.0", + version="3.18.0", packages=find_packages(exclude=["test"]), data_files=[ ("share/" + package_name, ["package.xml"]), diff --git a/rqt_controller_manager/CHANGELOG.rst b/rqt_controller_manager/CHANGELOG.rst index 99f8f6d91f..9996ff5a85 100644 --- a/rqt_controller_manager/CHANGELOG.rst +++ b/rqt_controller_manager/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package rqt_controller_manager ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.18.0 (2023-08-17) +------------------- 3.17.0 (2023-08-07) ------------------- diff --git a/rqt_controller_manager/package.xml b/rqt_controller_manager/package.xml index 8ccf0bc2c1..4888459d49 100644 --- a/rqt_controller_manager/package.xml +++ b/rqt_controller_manager/package.xml @@ -2,7 +2,7 @@ rqt_controller_manager - 3.17.0 + 3.18.0 Graphical frontend for interacting with the controller manager. Bence Magyar Denis Štogl diff --git a/rqt_controller_manager/setup.py b/rqt_controller_manager/setup.py index d46d1afeb7..318cf556d2 100644 --- a/rqt_controller_manager/setup.py +++ b/rqt_controller_manager/setup.py @@ -6,7 +6,7 @@ setup( name=package_name, - version="3.17.0", + version="3.18.0", packages=[package_name], data_files=[ ("share/ament_index/resource_index/packages", ["resource/" + package_name]), diff --git a/transmission_interface/CHANGELOG.rst b/transmission_interface/CHANGELOG.rst index 6d1d67a2d9..c45b040c1b 100644 --- a/transmission_interface/CHANGELOG.rst +++ b/transmission_interface/CHANGELOG.rst @@ -2,8 +2,8 @@ Changelog for package transmission_interface ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Forthcoming ------------ +3.18.0 (2023-08-17) +------------------- 3.17.0 (2023-08-07) ------------------- diff --git a/transmission_interface/package.xml b/transmission_interface/package.xml index 8b0687f6d7..9e2b2fded2 100644 --- a/transmission_interface/package.xml +++ b/transmission_interface/package.xml @@ -2,7 +2,7 @@ transmission_interface - 3.17.0 + 3.18.0 transmission_interface contains data structures for representing mechanical transmissions, methods for propagating values between actuator and joint spaces and tooling to support this. Bence Magyar Denis Štogl