You're reading the documentation for a development version. For the latest released version, please have a look at Iron.
Iron to Jazzy
controller_interface
The changes from (PR #1694) will affect how the controllers will be loading the parameters. Defining parameters in a single yaml file and loading it to the controller_manager node alone will no longer work. In order to load the parameters to the controllers properly, it is needed to use
--param-file
option from the spawner. This is because the controllers will now setuse_global_arguments
from NodeOptions to false, to avoid getting influenced by global arguments.With (#1683) the
rclcpp_lifecycle::State & get_state()
andvoid set_state(const rclcpp_lifecycle::State & new_state)
are replaced byrclcpp_lifecycle::State & get_lifecycle_state()
andvoid set_lifecycle_state(const rclcpp_lifecycle::State & new_state)
. This change affects controllers and hardware. This is related to (#1240) as variant support introducesget_state
andset_state
methods for setting/getting state of handles.
controller_manager
Rename
class_type
toplugin_name
(#780)CM now subscribes to
robot_description
topic instead of~/robot_description
(#1410). As a consequence, when using multiple controller managers, you have to remap the topic within the launch file, an example for a python launch file:remappings=[ ('/robot_description', '/custom_1/robot_description'), ]
Changes from (PR #1256)
All
joints
defined in the<ros2_control>
-tag have to be present in the URDF received by the controller manager, otherwise the following error is shown:The published robot description file (URDF) seems not to be genuine. The following error was caught: <unknown_joint> not found in URDF.
This is to ensure that the URDF and the
<ros2_control>
-tag are consistent. E.g., for configuration ports usegpio
interface types instead.The syntax for mimic joints is changed to the official URDF specification. The parameters within the
ros2_control
tag are not supported any more. Instead of<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:
<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>
The support for the
description
parameter for loading the URDF was removed (#1358). Userobot_description
topic instead, e.g., you can use the robot_state_publisher. For an example, see this PR where the change was applied to the demo repository.
hardware_interface
test_components
was moved to its own package. Update the dependencies if you are using them. (#1325)With (#1683) the
rclcpp_lifecycle::State & get_state()
andvoid set_state(const rclcpp_lifecycle::State & new_state)
are replaced byrclcpp_lifecycle::State & get_lifecycle_state()
andvoid set_lifecycle_state(const rclcpp_lifecycle::State & new_state)
. This change affects controllers and hardware. This is related to (#1240) as variant support introducesget_state
andset_state
methods for setting/getting state of handles.
Adaption of Command-/StateInterfaces
Command-/StateInterfaces
are now created and exported automatically by the framework via theon_export_command_interfaces()
oron_export_state_interfaces()
methods based on the interfaces defined in theros2_control
XML-tag, which get parsed and theInterfaceDescription
is created accordingly (check the hardware_info.hpp). The memory is now allocated in the handle itself.
Migration of Command-/StateInterfaces
To adapt to the new way of creating and exporting Command-/StateInterfaces
follow those steps:
Delete the
std::vector<hardware_interface::CommandInterface> export_command_interfaces() override
andstd::vector<hardware_interface::StateInterface> export_state_interfaces() override
.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:
// 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
// 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 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:
Override the
virtual std::vector<hardware_interface::InterfaceDescription> export_unlisted_command_interfaces()
orvirtual std::vector<hardware_interface::InterfaceDescription> export_unlisted_state_interfaces()
Create the InterfaceDescription for each of the interfaces you want to create in the override
export_unlisted_command_interfaces()
orexport_unlisted_state_interfaces()
function, add it to a vector and return the vector:
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;
The unlisted interface will then be stored in either the
unlisted_command_interfaces_
orunlisted_state_interfaces_
map depending in which function they are created.You can access it like any other interface with the
get_state(name)
,set_state(name, value)
,get_command(name)
orset_command(name, value)
. E.g.get_state("some_unlisted_interface")
.
Custom export 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_unlisted_command_interfaces()
orexport_unlisted_state_interfaces()
and add them to theunlisted_command_interfaces_
orunlisted_state_interfaces_
.Don’t forget to store the created
Command-/StateInterfaces
internally as you only returnstd::shared_ptr
and the resource manager will not provide access to the createdCommand-/StateInterface
for the hardware. So you must take care of storing them yourself.Names must be unique!