Rosanswers logo

Hi, I need to simulate multiple turtlebots in gazebo and visualize them in rviz and finally I succeed to add two robots into gazebo and rviz according to this but there are a few problems.

1.if I teleop one of the robot, even just rotate in place, the turtlebot will drift.

I checked this however when I look into the source file of gazebo_ros_kobuki.cpp(kobuki_gazebo_plugins) I find that this module is using the non-holonomic robot model. I am not sure what is the problem.

2.When I drive one robot toward the other and let these two robot collide, in the gazebo everything is ok but in rviz the moving robot just drive into the other one and pass through it, like the other one never exists. And also there is no output of bump cloud.

3.As you can see in the teleop launch file, I only publish velocity commands to one robot. But the actual result is that that turtlebot in gazebo works fine but in rviz both turtlebots react to the angular velocity. That means if I drive the robot, say robot1, linearly then only robot1 moves in rviz but when I sent angular velocity through keyboard then both robots will rotate in rviz.[this one is solved by change sensor names]

So I check the velocity topics related to both robots, it shows that only /robot1/command/velocity receives messages other velocity related topics have no message received. But still both robots rotate.

Here are related files: Gazebo related files Main launch file:

  <!-- gazebo world start -->
  <include file="$(find gazebo_ros)/launch/empty_world.launch">
    <arg name="use_sim_time" value="true"/>
    <arg name="debug" value="false"/>
    <arg name="world_name" value="$(find agents_gazebo)/worlds/empty.world"/>
    <arg name="gui" value="true"/>
  <!-- Map server -->
  <arg name="map_file" default="$(find agents_gazebo)/maps/willow-2010-02-18-0.10.yaml"/>
  <node name="map_server" pkg="map_server" type="map_server" args="$(arg map_file)" >
       <param name="frame_id" value="/map"/>
  <!-- include robots -->
  <include file="$(find agents_gazebo)/launch/includes/agents.launch.xml"/>

agents.launch.xml for multiple robots launch

  <arg name="base"      value="$(optenv TURTLEBOT_BASE kobuki)"/> 
  <arg name="battery"   value="$(optenv TURTLEBOT_BATTERY /proc/acpi/battery/BAT0)"/>  
  <arg name="stacks"    value="$(optenv TURTLEBOT_STACKS hexagons)"/>  
  <arg name="3d_sensor" value="$(optenv TURTLEBOT_3D_SENSOR kinect)"/>  

  <arg name="urdf_file" default="$(find xacro)/xacro.py '$(find turtlebot_description)/robots/$(arg base)_$(arg stacks)_$(arg 3d_sensor).urdf.xacro'" />
  <param name="robot_description" command="$(arg urdf_file)" />

  <!-- BEGIN ROBOT 1-->
  <group ns="robot1">
    <arg name="robot_name" value="robot1"/>
    <include file="$(find agents_gazebo)/launch/includes/agent.launch.xml" >
    <arg name="initial_pose_x" value="0" />
    <arg name="initial_pose_y" value="0" />
    <arg name="initial_pose_z" value="0" />
    <arg name="initial_pose_yaw" value="0" />
    <arg name="robot_name" value="$(arg robot_name)"/>

  <!-- BEGIN ROBOT 2-->
  <group ns="robot2">
    <arg name="robot_name" value="robot2"/>
    <include file="$(find agents_gazebo)/launch/includes/agent.launch.xml" >
    <arg name="initial_pose_x" value="1" />
    <arg name="initial_pose_y" value="0" />
    <arg name="initial_pose_z" value="0" />
    <arg name="initial_pose_yaw" value="3.1415926" />
      <arg name="robot_name" value="$(arg robot_name)"/>

agent.launch.xml for single robot launch

  <arg name="initial_pose_x" default="1" />
  <arg name="initial_pose_y" default="1" />
  <arg name="initial_pose_z" default="0" />
  <arg name="initial_pose_yaw" default="0" />
  <arg name="robot_name"/>

  <arg name="init_pose" value="-x $(arg initial_pose_x) -y $(arg initial_pose_y) -z $(arg initial_pose_z) -Y $(arg initial_pose_yaw)"/>
  <!-- Gazebo model spawner -->
  <node name="spawn_turtlebot_model" pkg="gazebo_ros" type="spawn_model"
        args="$(arg init_pose) -unpause -urdf -param /robot_description -model $(arg robot_name)"

  <!-- velocity mux nodelet -->
  <node pkg="nodelet" type="nodelet" name="nodelet_manager" args="manager"/>
  <node pkg="nodelet" type="nodelet" name="cmd_vel_mux"
        args="load yocs_cmd_vel_mux/CmdVelMuxNodelet nodelet_manager">
    <param name="yaml_cfg_file" value="$(find turtlebot_bringup)/param/mux.yaml" />
    <remap from="cmd_vel_mux/output" to="commands/velocity"/>

  <!-- bumper2pc.launch.xml -->
  <node pkg="nodelet" type="nodelet" name="bumper2pointcloud" args="load kobuki_bumper2pc/Bumper2PcNodelet nodelet_manager">
    <param name="pointcloud_radius" value="0.24"/>
    <remap from="bumper2pointcloud/pointcloud"   to="sensors/bumper_pointcloud"/>
    <remap from="bumper2pointcloud/core_sensors" to="sensors/core"/>

  <!-- robot_state_publisher  -->
  <node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher">
    <param name="publish_frequency" type="double" value="30.0" />
    <param name="tf_prefix" type="string" value="$(arg robot_name)" />

  <!-- fake lazer -->
  <node pkg="nodelet" type="nodelet" name="laserscan_nodelet_manager" args="manager"/>
  <node pkg="nodelet" type="nodelet" name="depthimage_to_laserscan"
        args="load depthimage_to_laserscan/DepthImageToLaserScanNodelet laserscan_nodelet_manager">
    <param name="scan_height" value="10"/>
    <param name="output_frame_id" value="$(arg robot_name)/camera_depth_frame"/>
    <param name="range_min" value="0.45"/>
    <remap from="image" to="camera/depth/image_raw"/>
    <remap from="scan" to="scan"/>

 <!-- Velocity smoother -->
  <node pkg="nodelet" type="nodelet" name="navigation_velocity_smoother" 
    args="load yocs_velocity_smoother/VelocitySmootherNodelet nodelet_manager">
    <rosparam file="$(find turtlebot_bringup)/param/defaults/smoother.yaml" command="load"/>
    <remap from="navigation_velocity_smoother/smooth_cmd_vel" to="cmd_vel_mux/input/navi"/>
    <remap from="navigation_velocity_smoother/odometry" to="odom"/>
    <remap from="navigation_velocity_smoother/robot_cmd_vel" to="commands/velocity"/>

  <!-- Safety controller-->
  <node pkg="nodelet" type="nodelet" name="kobuki_safety_controller" 
    args="load kobuki_safety_controller/SafetyControllerNodelet nodelet_manager">
    <remap from="kobuki_safety_controller/cmd_vel" to="cmd_vel_mux/input/safety_controller"/>
    <remap from="kobuki_safety_controller/events/bumper" to="events/bumper"/>
    <remap from="kobuki_safety_controller/events/cliff" to="events/cliff"/>
    <remap from="kobuki_safety_controller/events/wheel_drop" to="events/wheel_drop"/>

  <!--move base for amcl-->
  <node pkg="move_base" type="move_base" respawn="false" name="move_base">
    <rosparam file="$(find agents_gazebo)/param/costmap_common_params.yaml" command="load" ns="global_costmap" />
    <rosparam file="$(find agents_gazebo)/param/costmap_common_params.yaml" command="load" ns="local_costmap" />
    <rosparam file="$(find agents_gazebo)/param/local_costmap_params.yaml" command="load" />
    <rosparam file="$(find agents_gazebo)/param/global_costmap_params.yaml" command="load" />
    <rosparam file="$(find agents_gazebo)/param/move_base_params.yaml" command="load" />
    <rosparam file="$(find agents_gazebo)/param/base_local_planner_params.yaml" command="load"/>
    <param name="global_costmap/robot_base_frame" value="/$(arg robot_name)/base_footprint"/>
    <param name="local_costmap/robot_base_frame" value="/$(arg robot_name)/base_footprint"/>
    <param name="global_costmap/scan/topic" value="/$(arg robot_name)/scan"/>
    <param name="local_costmap/scan/topic" value="/$(arg robot_name)/scan"/>
    <remap from="odom" to="odom"/>
    <remap from="map" to="/map"/>
    <remap from="cmd_vel" to="navigation_velocity_smoother/raw_cmd_vel"/>

  <include file="$(find agents_gazebo)/launch/includes/amcl.launch.xml">
    <arg name="initial_pose_x" value="$(arg initial_pose_x)"/>
    <arg name="initial_pose_y" value="$(arg initial_pose_y)"/>
    <arg name="initial_pose_a" value="$(arg initial_pose_yaw)"/>
    <arg name="odom_frame_id" value="/$(arg robot_name)/odom"/>
    <arg name="base_frame_id" value="/$(arg robot_name)/base_footprint"/>
    <arg name="scan_topic"    value="/$(arg robot_name)/scan"/>


amcl.launch.xml for localization

  <arg name="use_map_topic"  default="false"/>
  <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="odom"/>
  <arg name="base_frame_id"  default="base_footprint"/>
  <arg name="scan_topic" default="scan" />

  <node pkg="amcl" type="amcl" name="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="/map" />
    <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="map" to="/map"/>
    <remap from="scan" to="$(arg scan_topic)"/>
    <remap from="static_map" to="/static_map" />
    <!--remap from="odom" to="odom"/-->

Keyop file for key board operation.

  <node pkg="kobuki_keyop" type="keyop" name="keyop" output="screen">
    <remap from="keyop/motor_power" to="/robot1/commands/motor_power"/>
    <remap from="keyop/cmd_vel" to="/robot1/commands/velocity"/>
    <param name="linear_vel_step"  value="0.05" type="double"/>
    <param name="linear_vel_max"   value="1.5"  type="double"/>
    <param name="angular_vel_step" value="0.33" type="double"/>
    <param name="angular_vel_max"  value="6.6"  type="double"/>
    <param name="wait_for_connection_" value="true" type="bool"/>

rviz file

  <node name="rviz" pkg="rviz" type="rviz" args="-d $(find view)/rviz/agents.rviz" />

By the way I change the following lines in gazebo_ros_kobuki.cpp.

Line 141   joint_state_pub_ = nh_.advertise<sensor_msgs::JointState>(node_name_ +"/joint_states", 1);
Line 198   odom_pub_ = nh_.advertise<nav_msgs::Odometry>(node_name_ +"/odom", 1);
Line 386   joint_state_.header.frame_id = node_name_+"/base_link";
Line 397   odom_.header.frame_id = node_name_+"/odom";
Line 398   odom_.child_frame_id = node_name_+"/base_footprint";

Please help me with the problems thank you very much!!

here is the tf frames topics are here

Originally posted by hjh on ROS Answers with karma: 58 on 2014-11-18

Post score: 3

Original comments

Comment by Ramez on 2015-07-02:
Hi can you please share the rviz file for multiple robots, i have it for one robot but i don't know what should i add or how to modify it. Thank you

Comment by hjh on 2015-07-27:
to run multiple robots you need to revise several files if it is ok i can send you some patch files to you but you have to give me your email address

Comment by webvenky on 2015-09-21:
@hjh I'm facing problems running controller manager in different namespaces for multi-robot simulation. Could you provide me with your patch files. It might help or give me some idea. You can send the files to [email protected]

Comment by 130s on 2015-09-21:
@hjh It would be the community's greatest benefit if you could share your files somewhere public (eg. adding their contents in your answer, or sharing the link to your repository).

Comment by hjh on 2015-09-21:
Sorry for the late reply I have uploaded my solution to github please visit https://github.com/applyhhj/ros_multi_robot_sim

Comment by webvenky on 2015-09-21:
@hjh Thanks.


1 Answer 1


Rosanswers logo

I managed to solve the problem in rotation. it seems that the kobuki plugin just generates one set of odom and other sensors and still it is the namespace problem. However I had another problem and I added it into the original question. Please do help me if you have any idea. Thanks!

Originally posted by hjh with karma: 58 on 2014-11-19

This answer was ACCEPTED on the original site

Post score: 1

Original comments

Comment by hjh on 2015-09-21:
Sorry for the late reply I have uploaded my solution to github please visit https://github.com/applyhhj/ros_multi_robot_sim


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.