From 765241e3a7d522f805681024ddd7c64262497b92 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 1 Jun 2024 13:26:23 +0200 Subject: [PATCH 1/7] Bump version of pre-commit hooks (#1556) * Bump version of pre-commit hooks * Fix codespell and satisfy linter --------- Co-authored-by: christophfroehlich <3367244+christophfroehlich@users.noreply.github.com> Co-authored-by: Christoph Froehlich --- .pre-commit-config.yaml | 6 +++--- controller_manager/test/test_spawner_unspawner.cpp | 3 ++- .../include/hardware_interface/actuator_interface.hpp | 4 ++-- .../include/hardware_interface/resource_manager.hpp | 2 +- .../include/hardware_interface/system_interface.hpp | 4 ++-- joint_limits/include/joint_limits/joint_limits.hpp | 9 ++++++--- 6 files changed, 16 insertions(+), 12 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e039dd7ebb..8e604b2f7f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -62,7 +62,7 @@ repos: # CPP hooks - repo: https://github.com/pre-commit/mirrors-clang-format - rev: v18.1.4 + rev: v18.1.5 hooks: - id: clang-format args: ['-fallback-style=none', '-i'] @@ -125,14 +125,14 @@ repos: # Spellcheck in comments and docs # skipping of *.svg files is not working... - repo: https://github.com/codespell-project/codespell - rev: v2.2.6 + rev: v2.3.0 hooks: - id: codespell args: ['--write-changes', '--uri-ignore-words-list=ist', '-L manuel'] exclude: CHANGELOG\.rst|\.(svg|pyc|drawio)$ - repo: https://github.com/python-jsonschema/check-jsonschema - rev: 0.28.2 + rev: 0.28.4 hooks: - id: check-github-workflows args: ["--verbose"] diff --git a/controller_manager/test/test_spawner_unspawner.cpp b/controller_manager/test/test_spawner_unspawner.cpp index d65689c6f2..a5dd8fcda3 100644 --- a/controller_manager/test/test_spawner_unspawner.cpp +++ b/controller_manager/test/test_spawner_unspawner.cpp @@ -315,7 +315,8 @@ TEST_F(TestLoadController, unload_on_kill) // Launch spawner with unload on kill // timeout command will kill it after the specified time with signal SIGINT std::stringstream ss; - ss << "timeout --signal=INT 5 " << "ros2 run controller_manager spawner " + ss << "timeout --signal=INT 5 " + << "ros2 run controller_manager spawner " << "ctrl_3 -c test_controller_manager -t " << std::string(test_controller::TEST_CONTROLLER_CLASS_NAME) << " --unload-on-kill"; diff --git a/hardware_interface/include/hardware_interface/actuator_interface.hpp b/hardware_interface/include/hardware_interface/actuator_interface.hpp index 556d7a2047..1ae05aa5f7 100644 --- a/hardware_interface/include/hardware_interface/actuator_interface.hpp +++ b/hardware_interface/include/hardware_interface/actuator_interface.hpp @@ -131,7 +131,7 @@ class ActuatorInterface : public rclcpp_lifecycle::node_interfaces::LifecycleNod * \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 + * starting. \param[in] stop_interfaces vector of string identifiers for the command interfaces * 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. */ @@ -150,7 +150,7 @@ class ActuatorInterface : public rclcpp_lifecycle::node_interfaces::LifecycleNod * \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 + * starting. \param[in] stop_interfaces vector of string identifiers for the command interfaces * 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. */ diff --git a/hardware_interface/include/hardware_interface/resource_manager.hpp b/hardware_interface/include/hardware_interface/resource_manager.hpp index 91a98d1e96..31def4598b 100644 --- a/hardware_interface/include/hardware_interface/resource_manager.hpp +++ b/hardware_interface/include/hardware_interface/resource_manager.hpp @@ -353,7 +353,7 @@ class HARDWARE_INTERFACE_PUBLIC ResourceManager * \note it is assumed that `prepare_command_mode_switch` is called just before this method * with the same input arguments. * \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. + * \param[in] stop_interfaces vector of string identifiers for the command interfaces stopping. * \return true if switch is performed, false if a component rejects switching. */ bool perform_command_mode_switch( diff --git a/hardware_interface/include/hardware_interface/system_interface.hpp b/hardware_interface/include/hardware_interface/system_interface.hpp index 0a7421531a..6b2c38b915 100644 --- a/hardware_interface/include/hardware_interface/system_interface.hpp +++ b/hardware_interface/include/hardware_interface/system_interface.hpp @@ -132,7 +132,7 @@ class SystemInterface : public rclcpp_lifecycle::node_interfaces::LifecycleNodeI * \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 + * starting. \param[in] stop_interfaces vector of string identifiers for the command interfaces * 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. */ @@ -151,7 +151,7 @@ class SystemInterface : public rclcpp_lifecycle::node_interfaces::LifecycleNodeI * \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 + * starting. \param[in] stop_interfaces vector of string identifiers for the command interfaces * 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. */ diff --git a/joint_limits/include/joint_limits/joint_limits.hpp b/joint_limits/include/joint_limits/joint_limits.hpp index f9944a85b1..809bfd777b 100644 --- a/joint_limits/include/joint_limits/joint_limits.hpp +++ b/joint_limits/include/joint_limits/joint_limits.hpp @@ -128,11 +128,14 @@ struct SoftJointLimits { std::stringstream ss_output; - ss_output << " soft position limits: " << "[" << min_position << ", " << max_position << "]\n"; + ss_output << " soft position limits: " + << "[" << min_position << ", " << max_position << "]\n"; - ss_output << " k-position: " << "[" << k_position << "]\n"; + ss_output << " k-position: " + << "[" << k_position << "]\n"; - ss_output << " k-velocity: " << "[" << k_velocity << "]\n"; + ss_output << " k-velocity: " + << "[" << k_velocity << "]\n"; return ss_output.str(); } From 9c84eb7e7a6550001e43543b04a172398f0ac587 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Sun, 2 Jun 2024 17:01:43 +0200 Subject: [PATCH 2/7] Reactivate generate_version_header (#1544) --- joint_limits/CMakeLists.txt | 3 +-- joint_limits/package.xml | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/joint_limits/CMakeLists.txt b/joint_limits/CMakeLists.txt index 316a1ec7a2..3e296cd584 100644 --- a/joint_limits/CMakeLists.txt +++ b/joint_limits/CMakeLists.txt @@ -62,5 +62,4 @@ install(TARGETS joint_limits ament_export_targets(export_joint_limits HAS_LIBRARY_TARGET) ament_export_dependencies(${THIS_PACKAGE_INCLUDE_DEPENDS}) ament_package() -# TODO(anyone) uncomment if https://github.com/ament/ament_cmake/pull/526 is merged -# ament_generate_version_header(${PROJECT_NAME}) +ament_generate_version_header(${PROJECT_NAME}) diff --git a/joint_limits/package.xml b/joint_limits/package.xml index aec1c44b76..29b32e9819 100644 --- a/joint_limits/package.xml +++ b/joint_limits/package.xml @@ -13,8 +13,7 @@ https://github.com/ros-controls/ros2_control ament_cmake - - + ament_cmake_gen_version_h rclcpp rclcpp_lifecycle From e122f717109b2bb069ac2ed2418f36755d2e54c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Sun, 2 Jun 2024 21:07:12 +0200 Subject: [PATCH 3/7] Add doc page about joint kinematics (#1497) --------- Co-authored-by: Sai Kishor Kothakota --- doc/index.rst | 7 +- hardware_interface/doc/joints_userdoc.rst | 132 ++++++++++++++++++++++ 2 files changed, 133 insertions(+), 6 deletions(-) create mode 100644 hardware_interface/doc/joints_userdoc.rst diff --git a/doc/index.rst b/doc/index.rst index 91f965d601..b1d8e21c7d 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -16,12 +16,6 @@ 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 +25,6 @@ Concepts Controller Manager <../controller_manager/doc/userdoc.rst> Controller Chaining / Cascade Control <../controller_manager/doc/controller_chaining.rst> + Joint Kinematics <../hardware_interface/doc/joints_userdoc.rst> Hardware Components <../hardware_interface/doc/hardware_components_userdoc.rst> Mock Components <../hardware_interface/doc/mock_components_userdoc.rst> diff --git a/hardware_interface/doc/joints_userdoc.rst b/hardware_interface/doc/joints_userdoc.rst new file mode 100644 index 0000000000..af88c8825f --- /dev/null +++ b/hardware_interface/doc/joints_userdoc.rst @@ -0,0 +1,132 @@ +:github_url: https://github.com/ros-controls/ros2_control/blob/{REPOS_FILE_BRANCH}/hardware_interface/doc/joints_userdoc.rst + +.. _joints_userdoc: + + +Joint Kinematics for ros2_control +--------------------------------------------------------- + +This page should give an overview of the joint kinematics in the context of ros2_control. It is intended to give a brief introduction to the topic and to explain the current implementation in ros2_control. + +Nomenclature +############ + +Degrees of Freedom (DoF) + From `wikipedia `__: + + In physics, the degrees of freedom (DoF) of a mechanical system is the number of independent parameters that define its configuration or state. + +Joint + A joint is a connection between two links. In the ROS ecosystem, three types are more typical: Revolute (A hinge joint with position limits), Continuous (A continuous hinge without any position limits) or Prismatic (A sliding joint that moves along the axis). + + In general, a joint can be actuated or non-actuated, also called passive. Passive joints are joints that do not have their own actuation mechanism but instead allow movement by external forces or by being passively moved by other joints. A passive joint can have a DoF of one, such as a pendulum, or it can be part of a parallel kinematic mechanism with zero DoF. + +Serial Kinematics + Serial kinematics refers to the arrangement of joints in a robotic manipulator where each joint is independent of the others, and the number of joints is equal to the DoF of the kinematic chain. + + A typical example is an industrial robot with six revolute joints, having 6-DoF. Each joint can be actuated independently, and the end-effector can be moved to any position and orientation in the workspace. + +Kinematic Loops + On the other hand, kinematic loops, also known as closed-loop mechanisms, involve several joints that are connected in a kinematic chain and being actuated together. This means that the joints are coupled and cannot be moved independently: In general, the number of DoFs is smaller than the number of joints. + This structure is typical for parallel kinematic mechanisms, where the end-effector is connected to the base by several kinematic chains. + + An example is the four-bar linkage, which consists of four links and four joints. It can have one or two actuators and consequently one or two DoFs, despite having four joints. Furthermore, we can say that we have one (two) actuated joint and three (two) passive joints, which must satisfy the kinematic constraints of the mechanism. + +URDF +############# + +URDF is the default format to describe robot kinematics in ROS. However, only serial kinematic chains are supported, except for the so-called mimic joints. See the `URDF specification `__ for more details. + +Mimic joints can be defined in the following way in the URDF + + .. code-block:: xml + + + + + + + + + + + + + + + + + +Mimic joints are an abstraction of the real world. For example, they can be used to describe + +* simple closed-loop kinematics with linear dependencies of the joint positions and velocities +* links connected with belts, like belt and pulley systems or telescope arms +* a simplified model of passive joints, e.g. a pendulum at the end-effector always pointing downwards +* abstract complex groups of actuated joints, where several joints are directly controlled by low-level control loops and move synchronously. Without giving a real-world example, this could be several motors with their individual power electronics but commanded with the same setpoint. + +Mimic joints defined in the URDF are parsed from the resource manager and stored in a class variable of type ``HardwareInfo``, which can be accessed by the hardware components. The mimic joints must not have command interfaces but can have state interfaces. + +.. code-block:: xml + + + + + + + + + + + + + + + +From the officially released packages, the following packages are already using this information: + +* :ref:`mock_components (generic system) ` +* :ref:`gazebo_ros2_control ` +* :ref:`gz_ros2_control ` + +As the URDF specifies only the kinematics, the mimic tag has to be independent of the hardware interface type used in ros2_control. This means that we interpret this info in the following way: + +* **position = multiplier * other_joint_position + offset** +* **velocity = multiplier * other_joint_velocity** + +If someone wants to deactivate the mimic joint behavior for whatever reason without changing the URDF, it can be done by setting the attribute ``mimic=false`` of the joint tag in the ```` section of the XML. + +.. code-block:: xml + + + + + + + +Transmission Interface +####################### +Mechanical transmissions transform effort/flow variables such that their product (power) remains constant. Effort variables for linear and rotational domains are force and 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. + +The ``transmission_interface`` provides a base class and some implementations for plugins, which can be integrated and loaded by custom hardware components. They are not automatically loaded by any hardware component or the gazebo plugins, each hardware component is responsible for loading the appropriate transmission interface to map the actuator readings to joint readings. + +Currently the following implementations are available: + +* ``SimpleTransmission``: A simple transmission with a constant reduction ratio and no additional dynamics. +* ``DifferentialTransmission``: A differential transmission with two actuators and two joints. +* ``FourBarLinkageTransmission``: A four-bar-linkage transmission with two actuators and two joints. + +For more information, see :ref:`example_8 ` or the `transmission_interface `__ documentation. + +Simulating Closed-Loop Kinematic Chains +####################################### +Depending on the simulation plugin, different approaches can be used to simulate closed-loop kinematic chains. The following list gives an overview of the available simulation plugins and their capabilities: + +gazebo_ros2_control: + * mimic joints + * closed-loop kinematics are supported with ```` tags in the URDF, see, e.g., `here `__. + +gz_ros2_control: + * mimic joints + * closed-loop kinematics are not directly supported yet, but can be implemented by using a ``DetachableJoint`` via custom plugins. Follow `this issue `__ for updates on this topic. From 1ed61efcf82dd19e0946bb199a113429df96c507 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Mon, 3 Jun 2024 13:09:32 +0200 Subject: [PATCH 4/7] Fix update `period` for the first update after activation (#1551) --- controller_manager/src/controller_manager.cpp | 17 +++++++++++------ .../test/test_controller/test_controller.cpp | 2 +- .../test/test_controller/test_controller.hpp | 2 +- .../test/test_controller_manager.cpp | 19 ++++++++++++++----- 4 files changed, 27 insertions(+), 13 deletions(-) diff --git a/controller_manager/src/controller_manager.cpp b/controller_manager/src/controller_manager.cpp index 41fe1ad95d..3b84fc07e4 100644 --- a/controller_manager/src/controller_manager.cpp +++ b/controller_manager/src/controller_manager.cpp @@ -2147,6 +2147,17 @@ controller_interface::return_type ControllerManager::update( run_controller_at_cm_rate ? period : rclcpp::Duration::from_seconds((1.0 / controller_update_rate)); + if ( + *loaded_controller.next_update_cycle_time == + rclcpp::Time(0, 0, this->get_node_clock_interface()->get_clock()->get_clock_type())) + { + // it is zero after activation + RCLCPP_DEBUG( + get_logger(), "Setting next_update_cycle_time to %fs for the controller : %s", + time.seconds(), loaded_controller.info.name.c_str()); + *loaded_controller.next_update_cycle_time = time; + } + bool controller_go = (time == rclcpp::Time(0, 0, this->get_node_clock_interface()->get_clock()->get_clock_type())) || @@ -2182,12 +2193,6 @@ controller_interface::return_type ControllerManager::update( controller_ret = controller_interface::return_type::ERROR; } - if ( - *loaded_controller.next_update_cycle_time == - rclcpp::Time(0, 0, this->get_node_clock_interface()->get_clock()->get_clock_type())) - { - *loaded_controller.next_update_cycle_time = time; - } *loaded_controller.next_update_cycle_time += controller_period; if (controller_ret != controller_interface::return_type::OK) diff --git a/controller_manager/test/test_controller/test_controller.cpp b/controller_manager/test/test_controller/test_controller.cpp index df41ebf34e..8f120bbd47 100644 --- a/controller_manager/test/test_controller/test_controller.cpp +++ b/controller_manager/test/test_controller/test_controller.cpp @@ -62,7 +62,7 @@ controller_interface::InterfaceConfiguration TestController::state_interface_con controller_interface::return_type TestController::update( const rclcpp::Time & /*time*/, const rclcpp::Duration & period) { - update_period_ = period.seconds(); + update_period_ = period; ++internal_counter; // set value to hardware to produce and test different behaviors there diff --git a/controller_manager/test/test_controller/test_controller.hpp b/controller_manager/test/test_controller/test_controller.hpp index 14ad753803..368aeae4a8 100644 --- a/controller_manager/test/test_controller/test_controller.hpp +++ b/controller_manager/test/test_controller/test_controller.hpp @@ -80,7 +80,7 @@ class TestController : public controller_interface::ControllerInterface // enables external setting of values to command interfaces - used for simulation of hardware // errors double set_first_command_interface_value_to; - double update_period_ = 0; + rclcpp::Duration update_period_ = rclcpp::Duration::from_seconds(0.); }; } // namespace test_controller diff --git a/controller_manager/test/test_controller_manager.cpp b/controller_manager/test/test_controller_manager.cpp index e88b41f222..3e2f91e91a 100644 --- a/controller_manager/test/test_controller_manager.cpp +++ b/controller_manager/test/test_controller_manager.cpp @@ -374,9 +374,12 @@ TEST_P(TestControllerManagerWithUpdateRates, per_controller_equal_and_higher_upd controller_interface::return_type::OK, cm_->update(time_, rclcpp::Duration::from_seconds(0.01))); // In case of a non perfect divisor, the update period should respect the rule - // [controller_update_rate, 2*controller_update_rate) - ASSERT_GE(test_controller->update_period_, 1.0 / cm_update_rate); - ASSERT_LT(test_controller->update_period_, 2.0 / cm_update_rate); + // [cm_update_rate, 2*cm_update_rate) + EXPECT_THAT( + test_controller->update_period_, + testing::AllOf( + testing::Ge(rclcpp::Duration::from_seconds(1.0 / cm_update_rate)), + testing::Lt(rclcpp::Duration::from_seconds(2.0 / cm_update_rate)))); loop_rate.sleep(); } // if we do 2 times of the controller_manager update rate, the internal counter should be @@ -445,6 +448,7 @@ TEST_P(TestControllerUpdateRates, check_the_controller_update_rate) 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 + time_ = test_controller->get_node()->now(); // set to something nonzero const auto strictness = controller_manager_msgs::srv::SwitchController::Request::STRICT; std::vector start_controllers = {test_controller::TEST_CONTROLLER_NAME}; std::vector stop_controllers = {}; @@ -472,6 +476,7 @@ TEST_P(TestControllerUpdateRates, check_the_controller_update_rate) const auto controller_update_rate = test_controller->get_update_rate(); const auto initial_counter = test_controller->internal_counter; + // don't start with zero to check if the period is correct if controller is activated anytime rclcpp::Time time = time_; for (size_t update_counter = 0; update_counter <= 10 * cm_update_rate; ++update_counter) { @@ -480,8 +485,12 @@ TEST_P(TestControllerUpdateRates, check_the_controller_update_rate) cm_->update(time, rclcpp::Duration::from_seconds(0.01))); // In case of a non perfect divisor, the update period should respect the rule // [controller_update_rate, 2*controller_update_rate) - ASSERT_GE(test_controller->update_period_, 1.0 / controller_update_rate); - ASSERT_LT(test_controller->update_period_, 2.0 / controller_update_rate); + EXPECT_THAT( + test_controller->update_period_, + testing::AllOf( + testing::Ge(rclcpp::Duration::from_seconds(1.0 / controller_update_rate)), + testing::Lt(rclcpp::Duration::from_seconds(2.0 / controller_update_rate)))) + << "update_counter: " << update_counter; time += rclcpp::Duration::from_seconds(0.01); if (update_counter % cm_update_rate == 0) From d61abcdf593330839d698c32b3c7745f9515d06a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Fr=C3=B6hlich?= Date: Thu, 6 Jun 2024 07:09:34 +0200 Subject: [PATCH 5/7] Fix link to gazebosim.org (#1563) --- hardware_interface/doc/joints_userdoc.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hardware_interface/doc/joints_userdoc.rst b/hardware_interface/doc/joints_userdoc.rst index af88c8825f..f4332410d5 100644 --- a/hardware_interface/doc/joints_userdoc.rst +++ b/hardware_interface/doc/joints_userdoc.rst @@ -125,7 +125,7 @@ Depending on the simulation plugin, different approaches can be used to simulate gazebo_ros2_control: * mimic joints - * closed-loop kinematics are supported with ```` tags in the URDF, see, e.g., `here `__. + * closed-loop kinematics are supported with ```` tags in the URDF, see, e.g., `here `__. gz_ros2_control: * mimic joints From 01bc0f4119f05f39be34c400ee5c5379d91b0bc8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Jun 2024 18:23:54 +0100 Subject: [PATCH 6/7] Bump docker/build-push-action from 5 to 6 (#1572) --- .github/workflows/docker.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index f5015d8a90..70366d4033 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -42,7 +42,7 @@ jobs: type=semver,pattern={{major}}.{{minor}} - name: Build and push Docker image - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6 with: context: . push: true @@ -82,7 +82,7 @@ jobs: type=semver,pattern={{major}}.{{minor}} - name: Build and push Docker image - uses: docker/build-push-action@v5 + uses: docker/build-push-action@v6 with: context: . push: true From fbb893bdaa645216c1e11d0d6e2cf3dd60f5939d Mon Sep 17 00:00:00 2001 From: "Dr. Denis" Date: Wed, 19 Jun 2024 20:17:34 +0100 Subject: [PATCH 7/7] Small improvements to the error output in component parser to make debugging easier. (#1580) * Small improvements to the error output in component parser to make debugging easier. * Correct formatting. --- hardware_interface/src/component_parser.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/hardware_interface/src/component_parser.cpp b/hardware_interface/src/component_parser.cpp index ef585c971b..815b6d7e10 100644 --- a/hardware_interface/src/component_parser.cpp +++ b/hardware_interface/src/component_parser.cpp @@ -797,11 +797,13 @@ std::vector parse_control_resources_from_urdf(const std::string & tinyxml2::XMLDocument doc; if (!doc.Parse(urdf.c_str()) && doc.Error()) { - throw std::runtime_error("invalid URDF passed in to robot parser"); + throw std::runtime_error( + "invalid URDF passed in to robot parser: " + std::string(doc.ErrorStr())); } if (doc.Error()) { - throw std::runtime_error("invalid URDF passed in to robot parser"); + throw std::runtime_error( + "invalid URDF passed in to robot parser: " + std::string(doc.ErrorStr())); } // Find robot tag @@ -875,7 +877,7 @@ std::vector parse_control_resources_from_urdf(const std::string & auto urdf_joint = model.getJoint(joint.name); if (!urdf_joint) { - throw std::runtime_error("Joint " + joint.name + " not found in URDF"); + throw std::runtime_error("Joint '" + joint.name + "' not found in URDF"); } if (!urdf_joint->mimic && joint.is_mimic == MimicAttribute::TRUE) {