Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Features integration joint limits #19

Open
wants to merge 108 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
108 commits
Select commit Hold shift + click to select a range
5d81a98
Added controller parameters structures and movement interfaces.
destogl Sep 17, 2021
aa004a3
Added joint limiter plugins.
destogl Sep 18, 2021
bbd9d59
Debug Ruckig JointLimiter.
destogl Sep 24, 2021
ee7faf2
Modify simple joint limiting plugin (same as changes to moveit2 filte…
destogl Feb 9, 2023
a07c7ac
Remove all Ruckig-limiter files.
destogl Mar 16, 2023
5260724
Merge branch 'master' into add-simple-joint-limiter
destogl Mar 16, 2023
6675e7d
Merge branch 'master' into add-simple-joint-limiter
destogl Mar 23, 2023
ceb3beb
Merge branch 'master' into add-simple-joint-limiter
destogl Apr 13, 2023
f939193
Apply suggestions from code review
destogl Apr 13, 2023
d7db070
Remove definition of movement interface because the concept is not us…
destogl Apr 13, 2023
4054b04
Polish out some stuff using "GH Programming"
destogl Apr 13, 2023
456c715
Polish out some stuff using "GH Programming"
destogl Apr 13, 2023
8b33153
Add SimpleJointLimiter as plugin into controllers.
destogl Apr 24, 2023
cbfc06a
Version with deceleration for simple joint limiter.
destogl May 4, 2023
2777c61
Merge branch 'master' into add-simple-joint-limiter
destogl May 9, 2023
b401169
Formatting and comment to check.
destogl May 12, 2023
e6f52d7
Added test of joint_limiter
gwalck Jun 7, 2023
7bfc94e
Fixed deceleration limit application
gwalck Jun 7, 2023
c338b8c
Updated authorship
gwalck Jun 9, 2023
6e0e6c5
Split test, apply review changes, add future tests
gwalck Jun 9, 2023
cfc8fe5
Applied review comment, added 2 tests & fixed typo
gwalck Jun 12, 2023
186c66e
Improved close to limit trigger
gwalck Jun 12, 2023
d6db2a1
Merge branch 'master' into add-simple-joint-limiter
destogl Jun 13, 2023
1e393f3
Merge branch 'master' into add-simple-joint-limiter
destogl Jun 27, 2023
1749f6d
Update joint_limits/src/simple_joint_limiter.cpp
destogl Jun 27, 2023
e254294
Fix formatting.
destogl Jun 29, 2023
21944b3
Added temporary pseudo-code
gwalck Jul 7, 2023
7530ba8
Updated pseudo-code
gwalck Jul 7, 2023
27e3304
Refactored to match pseudo-code
gwalck Jul 7, 2023
d5892e8
Adapted tests
gwalck Jul 7, 2023
d848a7d
lint
gwalck Jul 7, 2023
8c771cf
Cleanup debug helpers
gwalck Jul 7, 2023
7e8e4cd
Removed pseudo-code
gwalck Jul 7, 2023
c7fdd46
Merge branch 'master' into add-simple-joint-limiter
destogl Jul 13, 2023
098a431
Merge branch 'master' into add-simple-joint-limiter
destogl Aug 3, 2023
c184da8
Merge branch 'master' into add-simple-joint-limiter
destogl Aug 30, 2023
345370a
Apply suggestions from code review
destogl Sep 4, 2023
c99eb86
Apply suggestions from code review
destogl Sep 4, 2023
5a9985c
Unify how joints were limits are reached are stored.
destogl Sep 4, 2023
9c2bba7
Fix formatting.
destogl Sep 4, 2023
6ca6594
Fix unstable limiter because velocity is caculated from position when…
destogl Sep 12, 2023
40228d9
fix formatting.
destogl Sep 12, 2023
d6b0628
Merge branch 'master' into add-simple-joint-limiter
destogl Nov 1, 2023
5d164b1
Fix unstable limiter because velocity is caculated from position when…
destogl Sep 12, 2023
e99fca2
Make acceleration more stable in limiter.
destogl Sep 14, 2023
96bed7c
Enable dynamic update of limits from parameters.
destogl Nov 1, 2023
47389fd
Fix formatting.
destogl Nov 1, 2023
af5e004
Debug position limiting in the simiple joint limiter.
destogl Nov 16, 2023
4f868b1
Update tests after changes.
destogl Nov 21, 2023
72b1ea7
Merge branch 'master' into add-simple-joint-limiter
destogl Nov 21, 2023
47d073d
Merge branch 'master' into add-simple-joint-limiter
destogl Nov 30, 2023
94da997
Fixup shadowing variable.
destogl Dec 7, 2023
9ed9b01
Merge branch 'master' into add-simple-joint-limiter
destogl Dec 7, 2023
bcf42aa
rename to JointSaturationLimiter
mamueluth Dec 8, 2023
fde4814
rename files as well
mamueluth Dec 11, 2023
15b9255
add effort limits
mamueluth Dec 13, 2023
8e032f4
if move limit efforts to seperate function
mamueluth Dec 14, 2023
5d4e7e4
Merge branch 'master' into add-simple-joint-limiter
destogl Dec 18, 2023
0c75f46
Merge branch 'master' into add-simple-joint-limiter
destogl Dec 18, 2023
9a40a75
add generic enforce method
mamueluth Jan 8, 2024
92d0468
Merge branch 'master' into add-simple-joint-limiter
destogl Jan 13, 2024
18f0ec0
Merge branch 'master' into add-simple-joint-limiter
destogl Jan 17, 2024
7e27edc
Interface cleanup and small optimizations from reviewers' comments.
destogl Jan 18, 2024
bd25f6e
Merge branch 'master' into add-simple-joint-limiter
destogl Jan 18, 2024
56dd00f
Added package to CI
destogl Jan 22, 2024
5c50bd6
Merge branch 'master' into add-simple-joint-limiter
destogl Jan 22, 2024
ed2f374
Merge branch 'master' into add-simple-joint-limiter
destogl Jan 25, 2024
fdc4e05
Merge branch 'master' into add-simple-joint-limiter
destogl Jan 25, 2024
f96f8da
Merge branch 'master' into add-simple-joint-limiter
destogl Feb 8, 2024
284437a
Correct sorting of packages.
destogl Feb 8, 2024
d3838fd
Small fixes of calculation when differnet set of inputs are provided.
destogl Feb 8, 2024
1939558
move creation of stateinterfaces to systeminterface
mamueluth Dec 7, 2023
efcc376
store description in state_interface and provide functions for
mamueluth Dec 8, 2023
b76b869
return correct name for InterfaceDescription
mamueluth Dec 11, 2023
5635631
move parsing of interface description to component parser
mamueluth Dec 11, 2023
5d61eaf
adjusted actuator- and sensor_interface as well
mamueluth Dec 12, 2023
79d0068
add first tests
mamueluth Dec 18, 2023
f40fdcf
adjust sensor_interface getting/setting and add tests
mamueluth Dec 18, 2023
4533df9
add more tests
mamueluth Dec 18, 2023
667892d
first steps towards variants and storing of value in handle, missing:
mamueluth Dec 19, 2023
62300d7
add variant support
mamueluth Dec 19, 2023
617c542
adjusted resource manager to work with shared_ptr adapt actuator,sensor
mamueluth Dec 20, 2023
e4ee06d
cleanup
mamueluth Dec 20, 2023
c7e2c1a
fix failing tests
mamueluth Dec 20, 2023
57ecbc7
change rest of component_interface test and mark what should be removed
mamueluth Dec 21, 2023
56e8be3
code review suggestions and:
mamueluth Jan 23, 2024
4ae546a
undo prefix_ -> prefix (HWInfo) and Command-/StateIntefaceSharedPtr
mamueluth Jan 26, 2024
cc1f975
merge parser functions
mamueluth Jan 26, 2024
ab00a06
export_interfaces_2() virtual for custom interface export
mamueluth Jan 29, 2024
219544a
use unordered map and adjust tests
mamueluth Jan 29, 2024
8d431f0
make states and commands of component interfaces private
mamueluth Feb 1, 2024
4b2328a
add migration guide for
mamueluth Apr 10, 2024
1612802
update writing a hardware component
mamueluth Apr 11, 2024
b9a4b9c
Fix RST syntax and some typos (#18)
christophfroehlich Apr 18, 2024
476d44b
add changes for chainable controllers (epxport of rerference interfaces)
mamueluth Apr 22, 2024
80a80d5
add key-value storage to the IntefaceInfo, parameters can now be defi…
mamueluth Feb 27, 2024
52e5571
[HACK] MimicAttribute::FALSE -> MimicAttribute::NO_MIMIC, MimicAttrib…
muritane May 31, 2024
a18bbc2
revert mimic joints
mamueluth Jun 3, 2024
cbe0340
stop on nan in generic system
mamueluth Jun 3, 2024
f097085
Merge remote-tracking branch 'origin/master' into add-simple-joint-li…
destogl Jun 11, 2024
2a79458
[pr #971] merge commit, add saturation joint limiter
muritane Jun 13, 2024
c21de1f
Add joint limiter interface plugins to enforce limits defined in the …
saikishor Apr 7, 2024
b123aec
remove fixing of JointlimitsStateDataType
mamueluth Jul 5, 2024
eb6c3cc
Joint limits resource manager integration
saikishor Apr 23, 2024
8dcfff1
functional integration of joint limiter in resource manager
mamueluth Jul 8, 2024
9d1db8d
enable moving out of position limit if velocity is in "right" direction
mamueluth Jul 8, 2024
7e3fc6e
Make list controller and list hardware componets immedaitelly visuali…
destogl Jul 8, 2024
2d792a9
warn everytime we reach the limit
mamueluth Jul 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
#ifndef CONTROLLER_INTERFACE__CHAINABLE_CONTROLLER_INTERFACE_HPP_
#define CONTROLLER_INTERFACE__CHAINABLE_CONTROLLER_INTERFACE_HPP_

#include <memory>
#include <string>
#include <unordered_map>
#include <vector>

#include "controller_interface/controller_interface_base.hpp"
Expand Down Expand Up @@ -56,7 +59,8 @@ class ChainableControllerInterface : public ControllerInterfaceBase
bool is_chainable() const final;

CONTROLLER_INTERFACE_PUBLIC
std::vector<hardware_interface::CommandInterface> export_reference_interfaces() final;
std::vector<std::shared_ptr<hardware_interface::CommandInterface>> export_reference_interfaces()
final;

CONTROLLER_INTERFACE_PUBLIC
bool set_chained_mode(bool chained_mode) final;
Expand Down Expand Up @@ -115,7 +119,11 @@ class ChainableControllerInterface : public ControllerInterfaceBase
const rclcpp::Time & time, const rclcpp::Duration & period) = 0;

/// Storage of values for reference interfaces
// BEGIN (Handle export change): for backward compatibility
std::vector<double> reference_interfaces_;
// END
std::unordered_map<std::string, std::shared_ptr<hardware_interface::CommandInterface>>
reference_interfaces_ptrs_;

private:
/// A flag marking if a chainable controller is currently preceded by another controller.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ class ControllerInterface : public controller_interface::ControllerInterfaceBase
* \returns empty list.
*/
CONTROLLER_INTERFACE_PUBLIC
std::vector<hardware_interface::CommandInterface> export_reference_interfaces() final;
std::vector<std::shared_ptr<hardware_interface::CommandInterface>> export_reference_interfaces()
final;

/**
* Controller is not chainable, therefore no chained mode can be set.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,8 @@ class ControllerInterfaceBase : public rclcpp_lifecycle::node_interfaces::Lifecy
* \returns list of command interfaces for preceding controllers.
*/
CONTROLLER_INTERFACE_PUBLIC
virtual std::vector<hardware_interface::CommandInterface> export_reference_interfaces() = 0;
virtual std::vector<std::shared_ptr<hardware_interface::CommandInterface>>
export_reference_interfaces() = 0;

/**
* Set chained mode of a chainable controller. This method triggers internal processes to switch
Expand Down
59 changes: 39 additions & 20 deletions controller_interface/src/chainable_controller_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,44 +44,63 @@ return_type ChainableControllerInterface::update(
return ret;
}

std::vector<hardware_interface::CommandInterface>
std::vector<std::shared_ptr<hardware_interface::CommandInterface>>
ChainableControllerInterface::export_reference_interfaces()
{
auto reference_interfaces = on_export_reference_interfaces();
std::vector<std::shared_ptr<hardware_interface::CommandInterface>> reference_interfaces_ptrs_vec;
reference_interfaces_ptrs_vec.reserve(reference_interfaces.size());

// BEGIN (Handle export change): for backward compatibility
// check if the "reference_interfaces_" variable is resized to number of interfaces
if (reference_interfaces_.size() != reference_interfaces.size())
{
// TODO(destogl): Should here be "FATAL"? It is fatal in terms of controller but not for the
// framework
RCLCPP_FATAL(
get_node()->get_logger(),
"The internal storage for reference values 'reference_interfaces_' variable has size '%zu', "
"but it is expected to have the size '%zu' equal to the number of exported reference "
"interfaces. No reference interface will be exported. Please correct and recompile "
"the controller with name '%s' and try again.",
reference_interfaces_.size(), reference_interfaces.size(), get_node()->get_name());
reference_interfaces.clear();
std::string error_msg =
"The internal storage for reference values 'reference_interfaces_' variable has size '" +
std::to_string(reference_interfaces_.size()) + "', but it is expected to have the size '" +
std::to_string(reference_interfaces.size()) +
"' equal to the number of exported reference interfaces. Please correct and recompile the "
"controller with name '" +
get_node()->get_name() + "' and try again.";
throw std::runtime_error(error_msg);
}
// END

// check if the names of the reference interfaces begin with the controller's name
for (const auto & interface : reference_interfaces)
const auto ref_interface_size = reference_interfaces.size();
for (auto & interface : reference_interfaces)
{
if (interface.get_prefix_name() != get_node()->get_name())
{
RCLCPP_FATAL(
get_node()->get_logger(),
"The name of the interface '%s' does not begin with the controller's name. This is "
"mandatory "
" for reference interfaces. No reference interface will be exported. Please correct and "
"recompile the controller with name '%s' and try again.",
interface.get_name().c_str(), get_node()->get_name());
reference_interfaces.clear();
break;
std::string error_msg = "The name of the interface " + interface.get_name() +
" does not begin with the controller's name. This is mandatory for "
"reference interfaces. Please "
"correct and recompile the controller with name " +
get_node()->get_name() + " and try again.";
throw std::runtime_error(error_msg);
}

std::shared_ptr<hardware_interface::CommandInterface> interface_ptr =
std::make_shared<hardware_interface::CommandInterface>(std::move(interface));
reference_interfaces_ptrs_vec.push_back(interface_ptr);
reference_interfaces_ptrs_.insert(std::make_pair(interface_ptr->get_name(), interface_ptr));
}

if (reference_interfaces_ptrs_.size() != ref_interface_size)
{
std::string error_msg =
"The internal storage for reference ptrs 'reference_interfaces_ptrs_' variable has size '" +
std::to_string(reference_interfaces_ptrs_.size()) +
"', but it is expected to have the size '" + std::to_string(ref_interface_size) +
"' equal to the number of exported reference interfaces. Please correct and recompile the "
"controller with name '" +
get_node()->get_name() + "' and try again.";
throw std::runtime_error(error_msg);
}

return reference_interfaces;
return reference_interfaces_ptrs_vec;
}

bool ChainableControllerInterface::set_chained_mode(bool chained_mode)
Expand Down
3 changes: 2 additions & 1 deletion controller_interface/src/controller_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ ControllerInterface::ControllerInterface() : ControllerInterfaceBase() {}

bool ControllerInterface::is_chainable() const { return false; }

std::vector<hardware_interface::CommandInterface> ControllerInterface::export_reference_interfaces()
std::vector<std::shared_ptr<hardware_interface::CommandInterface>>
ControllerInterface::export_reference_interfaces()
{
return {};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ TEST_F(ChainableControllerInterfaceTest, export_reference_interfaces)
auto reference_interfaces = controller.export_reference_interfaces();

ASSERT_EQ(reference_interfaces.size(), 1u);
EXPECT_EQ(reference_interfaces[0].get_prefix_name(), TEST_CONTROLLER_NAME);
EXPECT_EQ(reference_interfaces[0].get_interface_name(), "test_itf");
EXPECT_EQ(reference_interfaces[0]->get_prefix_name(), TEST_CONTROLLER_NAME);
EXPECT_EQ(reference_interfaces[0]->get_interface_name(), "test_itf");

EXPECT_EQ(reference_interfaces[0].get_value(), INTERFACE_VALUE);
EXPECT_EQ(reference_interfaces[0]->get_value(), INTERFACE_VALUE);
}

TEST_F(ChainableControllerInterfaceTest, reference_interfaces_storage_not_correct_size)
Expand Down Expand Up @@ -103,7 +103,7 @@ TEST_F(ChainableControllerInterfaceTest, setting_chained_mode)
EXPECT_FALSE(controller.is_in_chained_mode());

// Fail setting chained mode
EXPECT_EQ(reference_interfaces[0].get_value(), INTERFACE_VALUE);
EXPECT_EQ(reference_interfaces[0]->get_value(), INTERFACE_VALUE);

EXPECT_FALSE(controller.set_chained_mode(true));
EXPECT_FALSE(controller.is_in_chained_mode());
Expand All @@ -112,7 +112,7 @@ TEST_F(ChainableControllerInterfaceTest, setting_chained_mode)
EXPECT_FALSE(controller.is_in_chained_mode());

// Success setting chained mode
reference_interfaces[0].set_value(0.0);
reference_interfaces[0]->set_value(0.0);

EXPECT_TRUE(controller.set_chained_mode(true));
EXPECT_TRUE(controller.is_in_chained_mode());
Expand Down
26 changes: 20 additions & 6 deletions controller_manager/src/controller_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -740,13 +740,27 @@ controller_interface::return_type ControllerManager::configure_controller(
get_logger(),
"Controller '%s' is chainable. Interfaces are being exported to resource manager.",
controller_name.c_str());
auto interfaces = controller->export_reference_interfaces();
if (interfaces.empty())

std::vector<std::shared_ptr<hardware_interface::CommandInterface>> interfaces;
try
{
// TODO(destogl): Add test for this!
RCLCPP_ERROR(
get_logger(), "Controller '%s' is chainable, but does not export any reference interfaces.",
controller_name.c_str());
interfaces = controller->export_reference_interfaces();
if (interfaces.empty())
{
// TODO(destogl): Add test for this!
RCLCPP_ERROR(
get_logger(),
"Controller '%s' is chainable, but does not export any reference interfaces. Did you "
"override the on_export_method() correctly?",
controller_name.c_str());
return controller_interface::return_type::ERROR;
}
}
catch (const std::runtime_error & e)
{
RCLCPP_FATAL(
get_logger(), "Creation of the reference interfaces failed with following error: %s",
e.what());
return controller_interface::return_type::ERROR;
}
resource_manager_->import_controller_reference_interfaces(controller_name, interfaces);
Expand Down
140 changes: 140 additions & 0 deletions doc/migration/Iron.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
Iron to Jazzy
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

component parser
*****************
Changes from `(PR #1256) <https://github.com/ros-controls/ros2_control/pull/1256>`__

* All ``joints`` defined in the ``<ros2_control>``-tag have to be present in the URDF received :ref:`by the controller manager <doc/ros2_control/controller_manager/doc/userdoc:subscribers>`, otherwise a ``std::runtime_error`` is thrown. This is to ensure that the URDF and the ``<ros2_control>``-tag are consistent. E.g., for configuration ports use ``gpio`` tags instead.
* The syntax for mimic joints is changed to the `official URDF specification <https://wiki.ros.org/urdf/XML/joint>`__. The parameters within the ``ros2_control`` tag are not supported any more. Instead of

.. code-block:: xml

<ros2_control name="GazeboSystem" type="system">
<joint name="right_finger_joint">
<command_interface name="position"/>
<state_interface name="position">
<param name="initial_value">0.15</param>
</state_interface>
<state_interface name="velocity"/>
<state_interface name="effort"/>
</joint>
<joint name="left_finger_joint">
<param name="mimic">right_finger_joint</param>
<param name="multiplier">1</param>
<command_interface name="position"/>
<state_interface name="position"/>
<state_interface name="velocity"/>
<state_interface name="effort"/>
</joint>
</ros2_control>

define your mimic joints directly in the joint definitions:

.. code-block:: xml

<joint name="right_finger_joint" type="prismatic">
<axis xyz="0 1 0"/>
<origin xyz="0.0 -0.48 1" rpy="0.0 0.0 0.0"/>
<parent link="base"/>
<child link="finger_right"/>
<limit effort="1000.0" lower="0" upper="0.38" velocity="10"/>
</joint>
<joint name="left_finger_joint" type="prismatic">
<mimic joint="right_finger_joint" multiplier="1" offset="0"/>
<axis xyz="0 1 0"/>
<origin xyz="0.0 0.48 1" rpy="0.0 0.0 3.1415926535"/>
<parent link="base"/>
<child link="finger_left"/>
<limit effort="1000.0" lower="0" upper="0.38" velocity="10"/>
</joint>

Adaption of Command-/StateInterfaces
***************************************
Changes from `(PR #1240) <https://github.com/ros-controls/ros2_control/pull/1240>`__

* ``Command-/StateInterfaces`` are now created and exported automatically by the framework via the ``on_export_command_interfaces()`` or ``on_export_state_interfaces()`` methods based on the interfaces defined in the ``ros2_control`` XML-tag, which gets parsed and the ``InterfaceDescription`` is created accordingly (check the `hardware_info.hpp <https://github.com/ros-controls/ros2_control/tree/{REPOS_FILE_BRANCH}/hardware_interface/include/hardware_interface/hardware_info.hpp>`__).
* The memory for storing the value of a ``Command-/StateInterfaces`` is no longer allocated in the hardware but instead in the ``Command-/StateInterfaces`` itself.
* To access the automatically created ``Command-/StateInterfaces`` we provide the ``std::unordered_map<std::string, InterfaceDescription>``, where the string is the fully qualified name of the interface and the ``InterfaceDescription`` is the configuration of the interface. The ``std::unordered_map<>`` are divided into ``type_state_interfaces_`` and ``type_command_interfaces_`` where type can be: ``joint``, ``sensor``, ``gpio`` and ``unlisted``. E.g. the ``CommandInterfaces`` for all joints can be found in the ``joint_command_interfaces_`` map. The ``unlisted`` includes all interfaces not listed in the ``ros2_control`` XML-tag but were created by overriding the ``export_command_interfaces_2()`` or ``export_state_interfaces_2()`` function by creating some custom ``Command-/StateInterfaces``.

Migration of Command-/StateInterfaces
-------------------------------------
To adapt to the new way of creating and exporting ``Command-/StateInterfaces`` follow those steps:

1. Delete the ``std::vector<hardware_interface::CommandInterface> export_command_interfaces() override`` and ``std::vector<hardware_interface::StateInterface> export_state_interfaces() override``.
2. Delete allocated memory for any ``Command-/StateInterfaces``, e.g.:

* If you have a ``std::vector<double> hw_commands_;`` for joints' ``CommandInterfaces`` delete the definition and any usage/appearance.
* Wherever you iterated over a state/command or accessed commands like this:

.. code-block:: c++

// states
for (uint i = 0; i < hw_states_.size(); i++)
{
hw_states_[i] = 0;
auto some_state = hw_states_[i];
}

// commands
for (uint i = 0; i < hw_commands_.size(); i++)
{
hw_commands_[i] = 0;
auto some_command = hw_commands_[i];
}

// specific state/command
hw_commands_[x] = hw_states_[y];

replace it with

.. code-block:: c++

// states replace with this
for (const auto & [name, descr] : joint_state_interfaces_)
{
set_state(name, 0.0);
auto some_state = get_state(name);
}

//commands replace with this
for (const auto & [name, descr] : joint_commands_interfaces_)
{
set_command(name, 0.0);
auto some_command = get_command(name);
}

// replace specific state/command, for this you need to store the names which are std::strings
// somewhere or know them. However be careful since the names are fully qualified names which
// means that the prefix is included for the name: E.g.: prefix/joint_1/velocity
set_command(name_of_command_interface_x, get_state(name_of_state_interface_y));

Migration of unlisted Command-/StateInterfaces not defined in ``ros2_control`` XML-tag
--------------------------------------------------------------------------------------
If you want some unlisted ``Command-/StateInterfaces`` not included in the ``ros2_control`` XML-tag you can follow those steps:

1. Override the ``virtual std::vector<hardware_interface::InterfaceDescription> export_command_interfaces_2()`` or ``virtual std::vector<hardware_interface::InterfaceDescription> export_state_interfaces_2()``
2. Create the InterfaceDescription for each of the interfaces you want to create in the override ``export_command_interfaces_2()`` or ``export_state_interfaces_2()`` function, add it to a vector and return the vector:

.. code-block:: c++

std::vector<hardware_interface::InterfaceDescription> my_unlisted_interfaces;

InterfaceInfo unlisted_interface;
unlisted_interface.name = "some_unlisted_interface";
unlisted_interface.min = "-5.0";
unlisted_interface.data_type = "double";
my_unlisted_interfaces.push_back(InterfaceDescription(info_.name, unlisted_interface));

return my_unlisted_interfaces;

3. The unlisted interface will then be stored in either the ``unlisted_command_interfaces_`` or ``unlisted_state_interfaces_`` map depending in which function they are created.
4. You can access it like any other interface with the ``get_state(name)``, ``set_state(name, value)``, ``get_command(name)`` or ``set_command(name, value)``. E.g. ``get_state("some_unlisted_interface")``.

Custom exportation of Command-/StateInterfaces
----------------------------------------------
In case the default implementation (``on_export_command_interfaces()`` or ``on_export_state_interfaces()`` ) for exporting the ``Command-/StateInterfaces`` is not enough you can override them. You should however consider the following things:

* If you want to have unlisted interfaces available you need to call the ``export_command_interfaces_2()`` or ``export_state_interfaces_2()`` and add them to the ``unlisted_command_interfaces_`` or ``unlisted_state_interfaces_``.
* Don't forget to store the created ``Command-/StateInterfaces`` internally as you only return ``shared_ptrs`` and the resource manager will not provide access to the created ``Command-/StateInterfaces`` for the hardware. So you must take care of storing them yourself.
* Names must be unique!
5 changes: 5 additions & 0 deletions hardware_interface/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ if(BUILD_TESTING)

ament_add_gmock(test_component_interfaces test/test_component_interfaces.cpp)
target_link_libraries(test_component_interfaces hardware_interface)
ament_target_dependencies(test_component_interfaces ros2_control_test_assets)

ament_add_gmock(test_component_interfaces_custom_export test/test_component_interfaces_custom_export.cpp)
target_link_libraries(test_component_interfaces_custom_export hardware_interface)
ament_target_dependencies(test_component_interfaces_custom_export ros2_control_test_assets)

ament_add_gmock(test_component_parser test/test_component_parser.cpp)
target_link_libraries(test_component_parser hardware_interface)
Expand Down
Loading
Loading