上一章: ROS多机器人协同建图
一、环境配置
参考turtlebot3-多机交互程序:多机交互-创客智造
上位机和小车的基本通信配置见:静态IP+host/master设置
主体代码可访问github:ros-multi-robot
git clone https://github.com/shunyiwang/ROS_MULTI/MULTI_ROBOT.git
小车:
- Ubuntu-mate16.04+ROSkinetic;
- 必要的bringup.launch文件(包括雷达信息、IMU、编码器信息、电器驱动),详情见bringup详解。
上位机:
- Ubuntu16.04+ROSkinetic
- 安装多机地图合并软件包ros-kinetic-multirobot-map-merge:
sudo apt-get install ros-kinetic-multirobot-map-merge
- 安装turtlebot3源码:turtlebot3源码安装;
- 需添加turbot3源码:
git clone https://github.com/ROBOTIS-GIT/turbot3.git
cd ~/catkin_ws && catkin_make
二、主要命令
- 开启小车底盘和雷达(小车端),其他小车同理:
roslaunch clbrobot robot.launch robot_name:="robot1"
- 启动地图服务程序(以下均在上位机端运行):
roslaunch multi_navigation navigation_multi_map.launch map_file:=$HOME/tan/catkin_ws/src/multi_robot/map/map.yaml
- 开启小车导航navigation并设定初始位姿:
roslaunch multi_navigation navigation_multirobot.launch robot_name:="robot1"
- 开启rviz:
roslaunch multi_navigation navigation_rviz.launch
- 发布目标位置:
rostopic pub /robot1/move_base_simple/goal geometry_msgs/PoseStamped '{header: {stamp: now, frame_id: "map"}, pose: {position: {x: 0.5, y: 0.0, z: 0.0}, orientation: {w: 1.0}}}'
三、模块分析
navigation_multi_map.launch 代码如下:
<launch>
<!-- Map server -->
<arg name="map_file" default="/home/catkin_ws/src/multi_robot/map/map.yaml"/>
<node name="map_server" pkg="map_server" type="map_server" args="$(arg map_file)">
</node>
</launch>
navigation_multirobot.launch 代码如下:
<launch>
<arg name="robot_name" default="" />
<!-- robot_model -->
<include file="$(find robot_model)/model_robot.launch">
<arg name="robot_name" value="$(arg robot_name)"/>
</include>
<group ns="$(arg robot_name)">
<!-- AMCL -->
<arg name="custom_amcl_launch_file" default="$(find multi_navigation)/launch/amcl.multi.launch.xml"/>
<arg name="robot_x_pos" default="0.0"/>
<arg name="robot_y_pos" default="0.0"/>
<arg name="robot_a_pos" default="0.0"/>
<include file="$(arg custom_amcl_launch_file)">
<arg name="global_frame_id" value="/map"/>
<arg name="odom_frame_id" value="$(arg robot_name)/odom"/>
<arg name="base_frame_id" value="$(arg robot_name)/base_footprint"/>
<arg name="initial_pose_x" value="$(arg robot_x_pos)"/>
<arg name="initial_pose_y" value="$(arg robot_y_pos)"/>
<arg name="initial_pose_a" value="$(arg robot_a_pos)"/>
</include>
<!-- move_base -->
<arg name="custom_param_file" default="$(find multi_navigation)/param/dummy.yaml"/>
<include file="$(find multi_navigation)/launch/move_base_robot.launch.xml">
<arg name="global_frame_id" value="/map"/>
<arg name="odom_frame_id" value="/$(arg robot_name)/odom"/>
<arg name="base_frame_id" value="/$(arg robot_name)/base_footprint"/>
<arg name="odom_topic" value="/$(arg robot_name)/odom" />
<arg name="laser_topic" value="/$(arg robot_name)/scan" />
<arg name="cmd_topic" value="/$(arg robot_name)/cmd_vel" />
<arg name="custom_param_file" value="$(arg custom_param_file)"/>
</include>
</group>
</launch>
amcl.multi.launch.xml 代码如下:
<launch>
<arg name="robot_name" default="" />
<arg name="use_map_topic" default="true"/>
<arg name="scan_topic" default="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="odom"/>
<arg name="base_frame_id" default="base_footprint"/>
<arg name="global_frame_id" default="/map"/>
<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.25"/>
<param name="odom_alpha2" value="0.25"/>
<!-- translation std dev, m -->
<param name="odom_alpha3" value="0.25"/>
<param name="odom_alpha4" value="0.25"/>
<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.2"/>
<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.25"/>
<param name="recovery_alpha_slow" value="0.001"/>
<param name="recovery_alpha_fast" value="0.1"/>
<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="static_map" to="/static_map" />
<remap from="map" to="/map" />
</node>
</launch>
move_base_robot.launch.xml 代码如下:
<launch>
<arg name="odom_frame_id" default="odom"/>
<arg name="base_frame_id" default="base_footprint"/>
<arg name="global_frame_id" default="/map"/>
<arg name="odom_topic" default="odom" />
<arg name="laser_topic" default="scan" />
<arg name="cmd_topic" default="cmd_vel" />
<arg name="custom_param_file" default="$(find multi_navigation)/param/dummy.yaml"/>
<node pkg="move_base" type="move_base" respawn="false" name="move_base" output="screen">
<rosparam file="$(find multi_navigation)/param/tank/costmap_common_params.yaml" command="load" ns="global_costmap" />
<rosparam file="$(find multi_navigation)/param/tank/costmap_common_params.yaml" command="load" ns="local_costmap" />
<rosparam file="$(find multi_navigation)/param/tank/local_costmap_params.yaml" command="load" />
<rosparam file="$(find multi_navigation)/param/tank/global_costmap_params.yaml" command="load" />
<rosparam file="$(find multi_navigation)/param/tank/move_base_params.yaml" command="load" />
<rosparam file="$(find multi_navigation)/param/tank/base_local_planner_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 global_frame_id)"/>
<param name="local_costmap/robot_base_frame" value="$(arg base_frame_id)"/>
<param name="global_costmap/obstacle_layer/scan/topic" value="$(arg laser_topic)"/>
<param name="local_costmap/obstacle_layer/scan/topic" value="$(arg laser_topic)"/>
<remap from="cmd_vel" to="$(arg cmd_topic)"/>
<remap from="odom" to="$(arg odom_topic)"/>
<remap from="scan" to="$(arg laser_topic)"/>
</node>
</launch>