Robotics StackExchange | Archived questions

How do I assign joint state publisher nodes to the correct namespaces?

I am trying to have multiple turtlebots navigate on a shared map. I used template codes from The Construct live class #64 along with my own gazebo launch file that spawns the three turtlebots. When I launch my navigation file, I get the following error:

RLException: roslaunch file contains multiple nodes named [/robot_state_publisher].
Please check all <node> 'name' attributes to make sure they are unique.
Also check that $(anon id) use different ids.
The traceback for the exception was written to the log file

I thought I could avoid this error by specifying a "multirobotname" as an argument in the launch file, but I still got the error. Here is the navigation launch file I tried to run. I am using ROS Melodic. Many thanks if someone knows how to correct this!

<launch> 
  <!-- Arguments -->
  <arg name="model" default="$(env TURTLEBOT3_MODEL)" doc="model type [burger, waffle, waffle_pi]"/>
  <arg name="open_rviz" default="true"/>
  <arg name="multi_robot_name" default=""/>
  <arg name="move_forward_only" default="false"/>

  <param name="/use_sim_time" value="true"/>

  <!-- Run the map server -->
  <node name="map_server" pkg="map_server" type="map_server" args="/home/in/sandbox.yaml">
    <param name="frame_id" value="map" />
  </node>



 <!-- Properties of each robot      -->
<include file="$(find turtlebot3_bringup)/launch/turtlebot3_remote.launch">
    <arg name="multi_robot_name" value="robot1/" />
    <arg name="model" value="waffle_pi" />
  </include>
  <include file="$(find turtlebot3_bringup)/launch/turtlebot3_remote.launch">
    <arg name="multi_robot_name" value="robot2/" />
    <arg name="model" value="waffle_pi" />
  </include>
  <include file="$(find turtlebot3_bringup)/launch/turtlebot3_remote.launch">
    <arg name="multi_robot_name" value="robot3/" />
    <arg name="model" value="burger" />
  </include>

  <!-- AMCL      -->
    <include file="$(find MoveOneOfThree)/launch/amcl_robot1.launch"/>
    <include file="$(find MoveOneOfThree)/launch/amcl_robot2.launch"/>
    <include file="$(find MoveOneOfThree)/launch/amcl_robot3.launch"/>

<!-- MOVE_BASE-->
    <include file="$(find MoveOneOfThree)/launch/move_base_1.launch" />
    <include file="$(find MoveOneOfThree)/launch/move_base_2.launch" />
    <include file="$(find MoveOneOfThree)/launch/move_base_3.launch" />

Here is one of the three AMCL files:

<launch>

  <arg name="use_map_topic"   default="false"/>
  <arg name="scan_topic"      default="/robot1/scan"/>
  <arg name="initial_pose_x"  default="0.0"/>
  <arg name="initial_pose_y"  default="0.0"/>
  <arg name="initial_pose_a"  default="0.0"/>
  <arg name="odom_frame_id"   default="/robot1/odom"/>
  <arg name="base_frame_id"   default="/robot1/base_footprint"/>
  <arg name="global_frame_id" default="map"/>

  <node pkg="amcl" type="amcl" name="robot1_amcl">
    <param name="use_map_topic"             value="$(arg use_map_topic)"/>
    <!-- Publish scans from best pose at a max of 10 Hz -->
    <param name="odom_model_type"           value="diff"/>
    <param name="odom_alpha5"               value="0.1"/>
    <param name="gui_publish_rate"          value="10.0"/>
    <param name="laser_max_beams"             value="60"/>
    <param name="laser_max_range"           value="12.0"/>
    <param name="min_particles"             value="500"/>
    <param name="max_particles"             value="2000"/>
    <param name="kld_err"                   value="0.05"/>
    <param name="kld_z"                     value="0.99"/>
    <param name="odom_alpha1"               value="0.2"/>
    <param name="odom_alpha2"               value="0.2"/>
    <!-- translation std dev, m -->
    <param name="odom_alpha3"               value="0.2"/>
    <param name="odom_alpha4"               value="0.2"/>
    <param name="laser_z_hit"               value="0.5"/>
    <param name="laser_z_short"             value="0.05"/>
    <param name="laser_z_max"               value="0.05"/>
    <param name="laser_z_rand"              value="0.5"/>
    <param name="laser_sigma_hit"           value="0.2"/>
    <param name="laser_lambda_short"        value="0.1"/>
    <param name="laser_model_type"          value="likelihood_field"/>
    <!-- <param name="laser_model_type" value="beam"/> -->
    <param name="laser_likelihood_max_dist" value="2.0"/>
    <param name="update_min_d"              value="0.25"/>
    <param name="update_min_a"              value="0.2"/>
    <param name="odom_frame_id"             value="$(arg odom_frame_id)"/>
    <param name="base_frame_id"             value="$(arg base_frame_id)"/>
    <param name="global_frame_id"           value="$(arg global_frame_id)"/>
    <param name="resample_interval"         value="1"/>
    <!-- Increase tolerance because the computer can get quite busy -->
    <param name="transform_tolerance"       value="1.0"/>
    <param name="recovery_alpha_slow"       value="0.0"/>
    <param name="recovery_alpha_fast"       value="0.0"/>
    <param name="initial_pose_x"            value="$(arg initial_pose_x)"/>
    <param name="initial_pose_y"            value="$(arg initial_pose_y)"/>
    <param name="initial_pose_a"            value="$(arg initial_pose_a)"/>
    <remap from="scan"                      to="$(arg scan_topic)"/>
    <remap from="initialpose"               to="/robot1/initialpose"/>
    <remap from="amcl_pose"                 to="/robot1/amcl_pose"/>
    <remap from="particlecloud"             to="/robot1/particlecloud"/>

  </node>

</launch>

Here is one of the three move_base files:

<!--
    ROS navigation stack with velocity smoother and safety (reactive) controller - had to remove these because file is not downloaded? see move_base_1.txt in downloads folder for original version. Also had to remove global planner params and navfn global planner params. 
-->
<launch>

  <arg name="model" default="$(env TURTLEBOt3_MODEL" doc="waffle_pi"/>
  <arg name="cmd_vel_topic" default="/robot1/cmd_vel" />
  <arg name="odom_frame_id"   default="robot1/odom"/>
  <arg name="base_frame_id"   default="robot1/base_footprint"/>
  <arg name="global_frame_id" default="map"/>
  <arg name="odom_topic" default="/robot1/odom" />
  <arg name="laser_topic" default="/robot1/scan" />
  <arg name="custom_param_file" default="/home/in/sandbox.yaml"/>
  <arg name="move_forward_only" default="false"/>

  <node pkg="move_base" type="move_base" respawn="false" name="move_base1" output="screen">
    <param name="base_local_planner" value="dwa_local_planner/DWAPlannerROS" />
    <rosparam file="$(find turtlebot3_navigation)/param/costmap_common_params_waffle_pi.yaml" command="load" ns="global_costmap" />
    <rosparam file="$(find turtlebot3_navigation)/param/costmap_common_params_waffle_pi.yaml" command="load" ns="local_costmap" />
    <rosparam file="$(find turtlebot3_navigation)/param/local_costmap_params.yaml" command="load" />
    <rosparam file="$(find turtlebot3_navigation)/param/global_costmap_params.yaml" command="load" />
    <rosparam file="$(find turtlebot3_navigation)/param/move_base_params.yaml" command="load" />
    <rosparam file="$(find turtlebot3_navigation)/param/dwa_local_planner_params_waffle_pi.yaml" command="load" />
    <rosparam file="$(find turtlebot3_navigation)/param/move_base_params.yaml" command="load" />
    <!-- external params file that could be loaded into the move_base namespace -->
    <rosparam file="$(arg custom_param_file)" command="load" />

    <!-- reset frame_id parameters using user input data -->
    <param name="global_costmap/global_frame" value="$(arg global_frame_id)"/>
    <param name="global_costmap/robot_base_frame" value="$(arg base_frame_id)"/>
    <param name="local_costmap/global_frame" value="$(arg odom_frame_id)"/>
    <param name="local_costmap/robot_base_frame" value="$(arg base_frame_id)"/>
    <param name="DWAPlannerROS/global_frame_id" value="$(arg odom_frame_id)"/>

    <remap from="cmd_vel" to="/robot1/cmd_vel"/>
    <remap from="odom" to="$(arg odom_topic)"/>
    <remap from="scan" to="$(arg laser_topic)"/>
    <remap from="map" to="/map" />
    <remap from="/move_base/DWAPlannerROS/global_plan"                             to="/robot1/move_base/DWAPlannerROS/global_plan" />
    <remap from="/move_base/DWAPlannerROS/local_plan"                              to="/robot1/move_base/DWAPlannerROS/local_plan" />
    <remap from="/move_base/NavfnROS/plan"                                         to="/robot1/move_base/NavfnROS/plan" />
    <remap from="/move_base_simple/goal"                                           to="/robot1/move_base_simple/goal" />
    <remap from="/move_base/TebLocalPlannerROS/global_plan"                        to="/robot1/move_base/TebLocalPlannerROS/global_plan" />
    <remap from="/move_base/TebLocalPlannerROS/local_plan"                         to="/robot1/move_base/TebLocalPlannerROS/local_plan" />
    <remap from="/move_base/TebLocalPlannerROS/teb_markers"                        to="/robot1/move_base/TebLocalPlannerROS/teb_markers" />
    <remap from="/move_base/TebLocalPlannerROS/teb_markers_array"                  to="/robot1/move_base/TebLocalPlannerROS/teb_markers_array" />
    <remap from="/move_base/TebLocalPlannerROS/teb_poses"                          to="/robot1/move_base/TebLocalPlannerROS/teb_poses" />
    <remap from="/move_base/global_costmap/costmap"                                to="/robot1/move_base/global_costmap/costmap" />
    <remap from="/move_base/global_costmap/costmap_updates"                        to="/robot1/move_base/global_costmap/costmap_updates" />
    <remap from="/move_base/local_costmap/costmap"                                 to="/robot1/move_base/local_costmap/costmap" />
    <remap from="/move_base/local_costmap/costmap_updates"                         to="/robot1/move_base/local_costmap/costmap_updates" />
    <remap from="/move_base/local_costmap/footprint"                               to="/robot1/move_base/local_costmap/footprint" />

    <remap from="/move_base/GlobalPlanner/parameter_descriptions"                  to="/robot1/move_base/GlobalPlanner/parameter_descriptions" />
    <remap from="/move_base/GlobalPlanner/parameter_updates"                       to="/robot1/move_base/GlobalPlanner/parameter_updates" />
    <remap from="/move_base/GlobalPlanner/plan"                                    to="/robot1/move_base/GlobalPlanner/plan" />
    <remap from="/move_base/GlobalPlanner/potential"                               to="/robot1/move_base/GlobalPlanner/potential" />
    <remap from="/move_base/TebLocalPlannerROS/obstacles"                          to="/robot1/move_base/TebLocalPlannerROS/obstacles" />
    <remap from="/move_base/TebLocalPlannerROS/parameter_descriptions"             to="/robot1/move_base/TebLocalPlannerROS/parameter_descriptions" />
    <remap from="/move_base/TebLocalPlannerROS/parameter_updates"                  to="/robot1/move_base/TebLocalPlannerROS/parameter_updates" />
    <remap from="/move_base/cancel"                                                to="/robot1/move_base/cancel" />
    <remap from="/move_base/current_goal"                                          to="/robot1/move_base/current_goal" />
    <remap from="/move_base/feedback"                                              to="/robot1/move_base/feedback" />
    <remap from="/move_base/global_costmap/footprint"                              to="/robot1/move_base/global_costmap/footprint" />
    <remap from="/move_base/global_costmap/inflation_layer/parameter_descriptions" to="/robot1/move_base/global_costmap/inflation_layer/parameter_descriptions" />
    <remap from="/move_base/global_costmap/inflation_layer/parameter_updates"      to="/robot1/move_base/global_costmap/inflation_layer/parameter_updates" />
    <remap from="/move_base/global_costmap/obstacle_layer/clearing_endpoints"      to="/robot1/move_base/global_costmap/obstacle_layer/clearing_endpoints" />
    <remap from="/move_base/global_costmap/obstacle_layer/parameter_descriptions"  to="/robot1/move_base/global_costmap/obstacle_layer/parameter_descriptions" />
    <remap from="/move_base/global_costmap/obstacle_layer/parameter_updates"       to="/robot1/move_base/global_costmap/obstacle_layer/parameter_updates" />
    <remap from="/move_base/global_costmap/parameter_descriptions"                 to="/robot1/move_base/global_costmap/parameter_descriptions" />
    <remap from="/move_base/global_costmap/parameter_updates"                      to="/robot1/move_base/global_costmap/parameter_updates" />
    <remap from="/move_base/global_costmap/static_layer/parameter_descriptions"    to="/robot1/move_base/global_costmap/static_layer/parameter_descriptions" />
    <remap from="/move_base/global_costmap/static_layer/parameter_updates"         to="/robot1/move_base/global_costmap/static_layer/parameter_updates" />
    <remap from="/move_base/goal"                                                  to="/robot1/move_base/goal" />
    <remap from="/move_base/local_costmap/obstacle_layer/parameter_descriptions"   to="/robot1/move_base/local_costmap/obstacle_layer/parameter_descriptions" />
    <remap from="/move_base/local_costmap/obstacle_layer/parameter_updates"        to="/robot1/move_base/local_costmap/obstacle_layer/parameter_updates" />
    <remap from="/move_base/local_costmap/parameter_descriptions"                  to="/robot1/move_base/local_costmap/parameter_descriptions" />
    <remap from="/move_base/local_costmap/parameter_updates"                       to="/robot1/move_base/local_costmap/parameter_updates" />
    <remap from="/move_base/local_costmap/static_layer/parameter_descriptions"     to="/robot1/move_base/local_costmap/static_layer/parameter_descriptions" />
    <remap from="/move_base/local_costmap/static_layer/parameter_updates"          to="/robot1/move_base/local_costmap/static_layer/parameter_updates" />
    <remap from="/move_base/parameter_descriptions"                                to="/robot1/move_base/parameter_descriptions" />
    <remap from="/move_base/parameter_updates"                                     to="/robot1/move_base/parameter_updates" />
    <remap from="/move_base/result"                                                to="/robot1/move_base/result" />
    <remap from="/move_base/status"                                                to="/robot1/move_base/status" />
    <remap from="/move_base_simple/goal"                                           to="/robot1/move_base_simple/goal" />
  </node>


</launch>

Here is the turtlebot3_remote.launch file:

<launch>
  <arg name="model" default="$(env TURTLEBOT3_MODEL)" doc="model type [burger, waffle, waffle_pi]"/>
  <arg name="multi_robot_name" default=""/>

  <include file="$(find turtlebot3_bringup)/launch/includes/description.launch.xml">
    <arg name="model" value="$(arg model)" />
  </include>

  <node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher">
    <param name="publish_frequency" type="double" value="50.0" />
    <param name="tf_prefix" value="$(arg multi_robot_name)"/>
  </node>
</launch>

Asked by JustinPMaio on 2022-03-04 10:00:02 UTC

Comments

Answers

To get past that first error you have to change node names to make them unique, given they are all in the same namespace:

<node pkg="robot_state_publisher" type="robot_state_publisher" name="$(arg model)_robot_state_publisher">

Depending on what is in the description.launch there could be any number of additional node name collisions, unless that launch file already uses model as to alter every node name.

Or you could launch each turtlebot3_remote.launch in a separate namespace

...
<include file="$(find turtlebot3_bringup)/launch/turtlebot3_remote.launch" ns="model3">

But then necessary topics connections could get broken- or topics that are commingled between robots will get separated, so the distinct namespace is the better option.

Asked by lucasw on 2022-03-08 08:21:32 UTC

Comments

Lucas, your answer helped me take a few steps forward but now I've also taken a few steps back. I cannot get the map to transform data over TF. Will publish new question momentarily. Thank you!

Asked by JustinPMaio on 2022-03-11 18:21:03 UTC