gazebo_ros2_control: different namespace
Hi, I am running ros2 humble and I have detected some problems when spawning multiple entities of the same type. I have created a toy problem, to avoid ambiguities with duplication names. In particular I want to control two robots, each being just a revolute joint controlled in velocity. The robots are "pinocchio", associated to /r1/r1controller (and yes, there is a double r1, just to make sure there is no ambiguity/problem with the namespace: I have patched the code so instead of having a hard-coded "controllermanager" I have the namespace + "controllermanager", but please neglect that it doesn't change the result) and "geppetto", associated to /r2/r2controller. See the attached picture.C:\fakepath\markers.png. Notice that in order to have two different controller managers I had to apply what suggested in here (which to my understanding it is not yet merged ). So all in all, after launching the following launch script all the nodes are in place (robot state publisher, controller manager, and the entity - robot - to be controlled). At that point I manually trigger the controllers (one for each robot) instantiation:
ros2 control load_controller --set-state -c "/r2/r2controller_manager" geppetto
[gzserver-1] [INFO] [1684332993.826170124] [r2.r2controller_manager]: Loading controller 'geppetto'
[gzserver-1] [ERROR] [1684332993.901249319] [r2.geppetto]: 'joints' parameter was empty
[gzserver-1] [INFO] [1684332993.845766414] [r2.r2controller_manager]: Setting use_sim_time=True for geppetto to match controller manager (see ros2_control#325 for details)
[gzserver-1] [INFO] [1684332993.901068783] [r2.r2controller_manager]: Configuring controller 'geppetto'
[gzserver-1] [ERROR] [1684332993.901249319] [r2.geppetto]: 'joints' parameter was empty
[gzserver-1] [WARN] [1684332993.901323149] []: Error occurred while doing error handling.
[gzserver-1] [ERROR] [1684332993.901347966] [r2.r2controller_manager]: After configuring, controller 'geppetto' is in state 'unconfigured' , expected inactive.
This is confirmed by dumpling the parameter for geppetto:
ros2 param dump /r2/geppetto
/r2/geppetto:
ros__parameters:
interface_name: velocity
joints: []
qos_overrides:
/clock:
subscription:
depth: 1
durability: volatile
history: keep_last
reliability: best_effort
update_rate: 0
use_sim_time: true
while instead for the other robot we have:
ros2 param dump /r1/pinocchio
/r1/pinocchio:
ros__parameters:
command_interfaces:
- velocity
interface_name: velocity
joints:
- r1rollingBar_to_Tablet
qos_overrides:
/clock:
subscription:
depth: 1
durability: volatile
history: keep_last
reliability: best_effort
state_interfaces:
- position
- velocity
update_rate: 0
use_sim_time: true
Notice that I can control only one (but not always the same, I guess the parameters of one somehow override the ones of the second, see below for details on why I use the term "override") robot(i.e. joint). At the same time if I spawn only a robot, removing either ga1 or ga2 from the following file, I can control either of them without any issue.
This is the launch file I use:
import os
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch.actions import ExecuteProcess, IncludeLaunchDescription, RegisterEventHandler
from launch.event_handlers import OnProcessExit
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch_ros.actions import Node
from launch.actions import DeclareLaunchArgument, ExecuteProcess
from launch.substitutions import EnvironmentVariable, LaunchConfiguration, PathJoinSubstitution
import xacro
from launch.actions import GroupAction
from launch_ros.actions import PushRosNamespace
def generate_launch_description():
gazebo = IncludeLaunchDescription(
PythonLaunchDescriptionSource([os.path.join(
get_package_share_directory('gazebo_ros'), 'launch'), '/gazebo.launch.py']),
)
gzserver = ExecuteProcess(
cmd=['gzserver',
'-s', 'libgazebo_ros_init.so',
'-s', 'libgazebo_ros_factory.so',
'extra-gazebo-args', '--ros-args'],
output='screen',
)
# Gazebo client
gzclient = ExecuteProcess(
cmd=['gzclient'],
output='screen',
)
gazebo_ros2_control_demos_path = os.path.join(
get_package_share_directory('gazebo_ros2_control_demos'))
xacro_file1 = os.path.join(gazebo_ros2_control_demos_path,
'urdf',
'with_namespace.xacro.urdf')
generic_namespace = 'r1'
doc1 = xacro.process_file(xacro_file1, mappings={'genns':generic_namespace})
params1 = {'robot_description': doc1.toxml()}
node_robot_state_publisher1 = Node(
package='robot_state_publisher',
executable='robot_state_publisher', name=generic_namespace+'rsp',
output='screen',
parameters=[params1]
)
xacro_file2 = os.path.join(gazebo_ros2_control_demos_path,
'urdf',
'with_namespace.xacro.urdf')
generic_namespace = 'r2'
doc2 = xacro.process_file(xacro_file2, mappings={'genns':generic_namespace})
params2 = {'robot_description': doc2.toxml()}
node_robot_state_publisher2 = Node(
package='robot_state_publisher', name=generic_namespace+'rsp',
executable='robot_state_publisher',
output='screen',
parameters=[params2]
)
spawn_entity1 = Node(package='gazebo_ros', executable='spawn_entity.py',
arguments=['-topic', '/r1/robot_description',
'-entity', 'cartpole1',
'-y', '2',
'-x', '1'],
output='screen')
spawn_entity2 = Node(package='gazebo_ros', executable='spawn_entity.py',
arguments=['-topic', '/r2/robot_description',
'-entity', 'cartpole2',
'-y', '-2',
'-x', '-1'],
output='screen')
ga1 = GroupAction(actions = [PushRosNamespace('/r1'),
node_robot_state_publisher1,
spawn_entity1])
ga2 = GroupAction(actions = [PushRosNamespace('/r2'),
node_robot_state_publisher2,
spawn_entity2])
return LaunchDescription([
gazebo,
ga1,
ga2
])
With the xacro file being:
<?xml version="1.0" ?>
<robot name="cartopole" xmlns:xacro="http://ros.org/wiki/xacro">
<xacro:include filename="$(find gazebo_ros2_control_demos)/urdf/load_controller.xacro.urdf" />
<xacro:arg name="genns" default="caffa" />
<xacro:property name="genns" value="$(arg genns)"/>
<link name="world"/>
<gazebo reference="${genns}rollingBar">
<material>Gazebo/Wood</material>
</gazebo>
<link name="${genns}rollingBar">
<visual>
<geometry>
<box size="1 0.05 0.05"/>
</geometry>
<origin xyz="0 0 0"/>
<material name="green">
<color rgba="0 0.8 .8 1"/>
</material>
</visual>
<inertial>
<mass value="100"/>
<inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
</inertial>
</link>
<gazebo reference="${genns}tablet">
<material>marker_with_frame</material>
</gazebo>
<link name="${genns}tablet">
<visual>
<geometry>
<box size="1.0 1.0 0.05"/>
</geometry>
<origin xyz="0 0 0"/>
<material name="red">
<color rgba="1 0 0.1 1"/>
</material>
</visual>
<inertial>
<mass value="1"/>
<inertia ixx="1.0" ixy="0.0" ixz="0.0" iyy="1.0" iyz="0.0" izz="1.0"/>
</inertial>
</link>
<joint name="${genns}world_to_rolling_bar" type="fixed">
<origin rpy="0 0 0" xyz="0 0 1"/>
<parent link="world"/>
<child link="${genns}rollingBar"/>
</joint>
<joint name="${genns}rollingBar_to_Tablet" type="revolute">
<axis xyz="1 0 0"/>
<origin xyz="0.0 0.0 0.0"/>
<parent link="${genns}rollingBar"/>
<child link="${genns}tablet"/>
<limit effort="1000.0" lower="-15" upper="15" velocity="30"/>
<dynamics damping="0.0" friction="0.0"/>
</joint>
<ros2_control name="${genns}GazeboSystem" type="system">
<hardware>
<plugin>gazebo_ros2_control/GazeboSystem</plugin>
</hardware>
<joint name="${genns}rollingBar_to_Tablet">
<command_interface name="velocity">
<param name="min">-10</param>
<param name="max">10</param>
</command_interface>
<state_interface name="position"/>
<state_interface name="velocity"/>
<state_interface name="effort"/>
</joint>
</ros2_control>
<gazebo>
<plugin filename="libgazebo_ros2_control.so" name="gazebo_ros2_control">
<ros>
<namespace>/${genns}</namespace>
<remapping>/tf:=/${genns}/tf</remapping>
</ros>
<parameters>$(find gazebo_ros2_control_demos)/config/${genns}/${genns}_controller.yaml</parameters>
<robot_param_node>${genns}rsp</robot_param_node>
</plugin>
</gazebo>
</robot>
And with the controller yaml files (may be I have a problem in here? ) file being:
r1:
r1controller_manager:
ros__parameters:
update_rate: 30 # Hz
pinocchio:
type: velocity_controllers/JointGroupVelocityController
joint_state_broadcaster:
type: joint_state_broadcaster/JointStateBroadcaster
r1:
pinocchio:
ros__parameters:
joints:
- r1rollingBar_to_Tablet
command_interfaces:
- velocity
state_interfaces:
- position
- velocity
and
r2:
r2controller_manager:
ros__parameters:
update_rate: 30 # Hz
geppetto:
type: velocity_controllers/JointGroupVelocityController
joint_state_broadcaster:
type: joint_state_broadcaster/JointStateBroadcaster
r2:
geppetto:
ros__parameters:
joints:
- r2rollingBar_to_Tablet
command_interfaces:
- velocity
state_interfaces:
- position
- velocity
Finally, I don't get any problem if instead of using loadcontroller, I instead use the controllermanager spawner: with the following 2 commands I am able to control both robots (and see both tf/joints etc being correctly published) by publishing on the respective [pinocchio|geppetto]/commands topics:
ros2 run controller_manager spawner -c "/r2/r2controller_manager" --namespace "r2" -p ./gazebo_ros2_control_demos/config/r2/geppetto.yaml -t velocity_controllers/JointGroupVelocityController geppetto
ros2 run controller_manager spawner -c "/r1/r1controller_manager" --namespace "r1" -p ./gazebo_ros2_control/gazebo_ros2_control_demos/config/r1/pinocchio.yaml -t velocity_controllers/JointGroupVelocityController pinocchio
where the configuration file for the controllers are a little bit different from the yaml files from above:
pinocchio yaml file:
r1/pinocchio:
ros__parameters:
joints:
- r1rollingBar_to_Tablet
command_interfaces:
- velocity
state_interfaces:
- position
- velocity
geppetto yaml file:
r2/geppetto:
ros__parameters:
joints:
- r2rollingBar_to_Tablet
command_interfaces:
- velocity
state_interfaces:
- position
- velocity
I could not spot on the fly the problem for the load_controller node, but may be anyone has some ideas where to look for? Also should we setup and merge a test which takes into account a similar example so we cover the case with different namespaces? Does it sound good to you?
Thanks
Asked by maurizio on 2023-05-22 08:37:26 UTC
Comments