You're reading the documentation for a development version. For the latest released version, please have a look at Kilted.

topic_based_hardware_interfaces

Joint State Topic Based System

The Joint State Topic Based System implements a ros2_control hardware_interface::SystemInterface supporting command and state interfaces through the ROS topic communication layer.

ros2_control urdf tag

The joint_state_topic_hardware_interface has a few ros2_control urdf tags to customize its behavior.

Parameters

  • joint_commands_topic: (default: “/robot_joint_commands”). Example: <param name="joint_commands_topic">/my_topic_joint_commands</param>.

  • joint_states_topic: (default: “/robot_joint_states”). Example: <param name="joint_states_topic">/my_topic_joint_states</param>.

  • trigger_joint_command_threshold: (default: 1e-5). Used to avoid spamming the joint command topic when the difference between the current joint state and the joint command is smaller than this value, set to -1 to always send the joint command. Example: <param name="trigger_joint_command_threshold">0.001</param>.

  • sum_wrapped_joint_states: (default: “false”). Used to track the total rotation for joint states the values reported on the joint_states_topic wrap from 2pi to -2pi when rotating in the positive direction. (Isaac Sim only reports joint states from 2pi to -2pi) Example: <param name="sum_wrapped_joint_states">true</param>.

Per-joint Parameters

  • mimic: Defined name of the joint to mimic. This is often used concept with parallel grippers. Example: <param name="mimic">joint1</param>.

  • multiplier: Multiplier of values for mimicking joint defined in mimic parameter. Example: <param name="multiplier">-2</param>.

Modifying the urdf ros2_control tag for new robots

If your robot description support mock_components you simply add an if-else statement to switch between it and <plugin>joint_state_topic_hardware_interface/JointStateTopicSystem</plugin>, make sure to add the joint_commands_topic and joint_states_topic to point to the correct topics.

        <ros2_control name="name" type="system">
            <hardware>
              <xacro:if value="${mock_hardware}">
                <plugin>mock_components/GenericSystem</plugin>
                <param name="fake_sensor_commands">false</param>
                <param name="state_following_offset">0.0</param>
                <param name="calculate_dynamics">true</param>
              </xacro:if>
              <xacro:unless value="${mock_hardware}">
                <plugin>joint_state_topic_hardware_interface/JointStateTopicSystem</plugin>
                <param name="joint_commands_topic">/topic_based_joint_commands</param>
                <param name="joint_states_topic">/topic_based_joint_states</param>
                <param name="sum_wrapped_joint_states">true</param>
              </xacro:if>
            </hardware>
            <joint name="joint_1">
                <command_interface name="position"/>
                <state_interface name="position">
                  <param name="initial_value">0.0</param>
                </state_interface>
                <state_interface name="velocity"/>
            </joint>
            ...
            <joint name="joint_n">
                <command_interface name="position"/>
                <state_interface name="position">
                  <param name="initial_value">0.0</param>
                </state_interface>
                <state_interface name="velocity"/>
            </joint>
            ...
            <joint name="mimic_joint_1">
                <param name="mimic">joint_k</param>
                <param name="multiplier">1</param>
                <command_interface name="position" />
                <state_interface name="position">
                  <param name="initial_value">0.0</param>
                </state_interface>
                <state_interface name="velocity"/>
            </joint>
            ...
            <joint name="mimic_joint_n">
                <param name="mimic">joint_kn</param>
                <param name="multiplier">1</param>
                <command_interface name="position" />
                <state_interface name="position">
                  <param name="initial_value">0.0</param>
                </state_interface>
                <state_interface name="velocity"/>
            </joint>
        </ros2_control>

joint_command_topic_hardware_interface

Joint Command Topic Based System

The Joint Command Topic Based System implements a ros2_control hardware_interface::SystemInterface supporting command and state interfaces through the ROS topic communication layer. It publishes commands as control_msgs/JointCommand messages, one topic per interface type. Only position, velocity and effort command interfaces are supported, anything else is ignored with a warning.

Joint command ros2_control urdf tag

The joint_command_topic_hardware_interface has a few ros2_control urdf tags to customize its behavior.

Joint command parameters
  • joint_commands_topic: (default: “/robot_joint_commands”). Base topic for the joint command topics. Example: <param name="joint_commands_topic">/my_topic_joint_commands</param>.

  • joint_states_topic: (default: “/robot_joint_states”). Example: <param name="joint_states_topic">/my_topic_joint_states</param>.

  • trigger_joint_command_threshold: (default: 1e-5). Used to avoid spamming the joint command topic when the difference between the current joint state and the joint command is smaller than this value, set to -1 to always send the joint command. Example: <param name="trigger_joint_command_threshold">0.001</param>.

  • sum_wrapped_joint_states: (default: “false”). Used to track the total rotation when the position values reported on the joint_states_topic wrap from 2pi to -2pi when rotating in the positive direction. (Isaac Sim only reports joint states from 2pi to -2pi) Only position states are affected. Example: <param name="sum_wrapped_joint_states">true</param>.

Mimic joints

Often used with parallel grippers. The relation is declared in the URDF, not with ros2_control params:

<joint name="joint2" type="revolute">
    <mimic joint="joint1" multiplier="-2" offset="0"/>
    ...
</joint>

Then mark the joint with mimic="true" and give it state interfaces only. Its states come from the mimicked joint instead of the joint_states_topic:

<joint name="joint2" mimic="true">
    <state_interface name="position"/>
    <state_interface name="velocity"/>
</joint>

offset only applies to position. velocity and acceleration use multiplier alone.

Example

        <ros2_control name="name" type="system">
            <hardware>
              <plugin>joint_command_topic_hardware_interface/JointCommandTopicSystem</plugin>
              <param name="joint_commands_topic">/topic_based_joint_commands</param>
              <param name="joint_states_topic">/topic_based_joint_states</param>
            </hardware>
            <joint name="joint_1">
                <command_interface name="position"/>
                <command_interface name="velocity"/>
                <state_interface name="position">
                  <param name="initial_value">0.0</param>
                </state_interface>
                <state_interface name="velocity"/>
            </joint>
            ...
        </ros2_control>

Topics

Each write() publishes one control_msgs/JointCommand per interface type, on topics derived from joint_commands_topic:

  • <joint_commands_topic>/position: joints with a driven position command.

  • <joint_commands_topic>/velocity: joints with a driven velocity command.

  • <joint_commands_topic>/effort: joints with a driven effort command.

joint_names and values line up, interface_name repeats the interface. With the defaults, a joint with position and velocity commands publishes to /robot_joint_commands/position and /robot_joint_commands/velocity.

Command interfaces that no controller writes to hold NaN. Those joints are dropped from the message, and if nothing drives an interface type at all its topic stays quiet. Declaring a command interface is not enough to get traffic on the matching topic.

Nothing is published while the summed state-command difference stays at or below trigger_joint_command_threshold, which is the normal case once a controller has converged. Set it to -1 to publish every cycle.

QoS

Command publishers are reliable with a depth of 1, so don’t count on them to buffer.

The joint_states_topic subscription uses SensorDataQoS (best effort, depth 5), which any joint state publisher can match.

cm_topic_hardware_component

The controller_manager topic System implements a ros2_control hardware_interface::SystemInterface that subscribes to topics of type pal_statistics_msgs::msg::StatisticsNames and pal_statistics_msgs::msg::StatisticsValues, and sets its state interface to the received values (if present).

Per default, the ros2_control controller manager publishes these topics to /controller_manager/introspection_data/names and /controller_manager/introspection_data/values.

This component serves as a possibility to replay ROS bags and inject the states from a hardware component into the ros2_control stack. For example, use ros2bag CLI to extract these two topics via

ros2 bag play <bag_file> \
  --topics /controller_manager/introspection_data/names /controller_manager/introspection_data/values \
  --remap /controller_manager/introspection_data/names:=/<hardware_component_name>/names\
          /controller_manager/introspection_data/values:=/<hardware_component_name>/values

Note that with this setup the current time of your OS is used and not published from the ROS bag. If you want to control the speed of playback, run

  • your ros2_control_node with --ros-args -p --use_sim_time:=true

  • and the --rate and --clock options, for example

    ros2 bag play <bag_file> --rate 2.0 --clock 100 \
      --topics /controller_manager/introspection_data/names /controller_manager/introspection_data/values \
      --remap /controller_manager/introspection_data/names:=/<hardware_component_name>/names\
              /controller_manager/introspection_data/values:=/<hardware_component_name>/values
    

ROS subscribers

  • /<hardware_component_name>/names: pal_statistics_msgs::msg::StatisticsNames

  • /<hardware_component_name>/values: pal_statistics_msgs::msg::StatisticsValues

ros2_control section in URDF

<ros2_control name="hardware_component_name" type="system">
  <hardware>
    <plugin>cm_topic_hardware_component/CMTopicSystem</plugin>
  </hardware>
  <joint name="joint_1">
    <command_interface name="position"/>
    <state_interface name="position">
      <param name="initial_value">0.2</param>
    </state_interface>
    <state_interface name="velocity"/>
  </joint>
  <joint name="joint_2">
    <command_interface name="position"/>
    <state_interface name="position">
      <param name="initial_value">0.3</param>
    </state_interface>
    <state_interface name="velocity"/>
  </joint>
  <joint name="joint_3">
    <command_interface name="position"/>
    <state_interface name="position">
      <param name="initial_value">0.1</param>
    </state_interface>
    <state_interface name="velocity"/>
  </joint>
</ros2_control>