目录
1、前置知识
我都是跟着B站上赵虚左老师的ROS教学视频实现的单个差速移动机器人的建模与仿真,链接如下:
【赵虚左】《ROS理论与实践》第8、9章--ROS机器人操作系统_哔哩哔哩_bilibili
跟着这个课学完前八章即可完成差速移动机器人的建模。
2、ROS加载多机器人(rviz与gazebo显示)
下面介绍一下如何实现ROS的多机器人配置。
2.1 rviz和gazebo加载机器人模型
首先是在赵老师搭建的单个机器人仿真框架下,利用group为各个机器人分配一个命名空间,具体launch文件如下:
<launch>
<!-- 启动 gazebo -->
<include file="$(find gazebo_ros)/launch/empty_world.launch">
</include>
<!-- 第1个机器人 -->
<group ns="robot1">
<!-- 将模型文件写入参数服务器 -->
<param name="robot_description" command="$(find xacro)/xacro $(find mydiffcar_gazebo)/urdf/xacro/my_base_camera_laser.urdf.xacro ns:=robot1" />
<!-- 在 gazebo 中显示机器人模型 -->
<node pkg="gazebo_ros" type="spawn_model" name="robot1" args="-urdf -model robot1 -param robot_description -x 0.5"></node>
<!-- 关节以及机器人状态发布节点 -->
<node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" ></node>
<node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher" />
<!-- 坐标系变换,这个是跟着赵老师敲的,用来在rviz中正常显示深度相机点云数据 -->
<node pkg="tf2_ros" type="static_transform_publisher" name="static_transform_publisher" args="0 0 0 -1.57 0 -1.57 /robot1_support /robot1_support_depth" />
<!-- 设置一个全局坐标系map,这是rviz中显示多机器人的关键,将map坐标系作为机器人的odom坐标系的父亲,使得三个机器人能正常在rviz中显示 -->
<node pkg="tf2_ros" type="static_transform_publisher" name="static_transform_publisher1" args="0 0 0 0 0 0 /map /robot1_odom" />
</group>
<!-- 第2个机器人 -->
<group ns="robot2">
<!-- 将模型文件写入参数服务器 -->
<param name="robot_description" command="$(find xacro)/xacro $(find mydiffcar_gazebo)/urdf/xacro/my_base_camera_laser.urdf.xacro ns:=robot2" />
<!-- 在 gazebo 中显示机器人模型 -->
<node pkg="gazebo_ros" type="spawn_model" name="robot2" args="-urdf -model robot2 -param robot_description -x 1"></node>
<!-- 关节以及机器人状态发布节点 -->
<node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" ></node>
<node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher" />
<!-- 坐标系变换 -->
<node pkg="tf2_ros" type="static_transform_publisher" name="static_transform_publisher" args="0 0 0 -1.57 0 -1.57 /robot2_support /robot2_support_depth" />
<node pkg="tf2_ros" type="static_transform_publisher" name="static_transform_publisher1" args="0 0 0 0 0 0 /map /robot2_odom" />
</group>
<!-- 第3个机器人 -->
<group ns="robot3">
<!-- 将模型文件写入参数服务器 -->
<param name="robot_description" command="$(find xacro)/xacro $(find mydiffcar_gazebo)/urdf/xacro/my_base_camera_laser.urdf.xacro ns:=robot3" />
<!-- 在 gazebo 中显示机器人模型 -->
<node pkg="gazebo_ros" type="spawn_model" name="robot3" args="-urdf -model robot3 -param robot_description -x 1.5"></node>
<!-- 关节以及机器人状态发布节点 -->
<node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" ></node>
<node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher" />
<!-- 坐标系变换 -->
<node pkg="tf2_ros" type="static_transform_publisher" name="static_transform_publisher" args="0 0 0 -1.57 0 -1.57 /robot3_support /robot3_support_depth" />
<node pkg="tf2_ros" type="static_transform_publisher" name="static_transform_publisher1" args="0 0 0 0 0 0 /map /robot3_odom" />
</group>
<!-- 启动 rviz -->
<node pkg="rviz" type="rviz" name="rviz" args="-d $(find mydiffcar_gazebo)/config/multi_diffcar.rviz" />
<!-- <node pkg="rviz" type="rviz" name="rviz" /> -->
</launch>
重点:这个其实也是我参考了很多博客写的,里面有一段代码很多人没有提及,导致走了很多弯路,具体如下:
<!-- 设置一个全局坐标系map,这是rviz中显示多机器人的关键,将map坐标系作为机器人的odom坐标系的父亲,使得三个机器人能正常在rviz中显示 -->
<node pkg="tf2_ros" type="static_transform_publisher" name="static_transform_publisher1" args="0 0 0 0 0 0 /map /robot1_odom" />
</group>
这个每个group里面都设置的有,其目的就是创建一个根坐标系,将三个机器人的odom坐标系,都纳入其中,作为其子坐标系,这样才能在rviz中完整显示三个移动机器人。
2.2 控制单个机器人
还有一个比较重要的就是,在赵老师写的ROS仿真框架下,无论怎么改代码,都只有一个/cmd_vel话题,意味着就只能通过这个话题控制全部的机器人,最后发现,需要修改my_move.urdf.xacro文件中的差速驱动插件部分代码,需要将<robotNamespace>${ns}</robotNamespace>加上命名空间,ns是通过2.1中的launch文件设置的,<param name="robot_description" command="$(find xacro)/xacro $(find mydiffcar_gazebo)/urdf/xacro/my_base_camera_laser.urdf.xacro ns:=robot1" />,还有一种改法更简单,就是<robotNamespace></robotNamespace>,没错,就是啥也不加,下面是我更改后的代码:
<gazebo>
<!-- 差分小车控制插件 -->
<plugin name="differential_drive_controller" filename="libgazebo_ros_diff_drive.so">
<rosDebugLevel>Debug</rosDebugLevel>
<publishWheelTF>true</publishWheelTF>
<robotNamespace>${ns}</robotNamespace>
<publishTf>1</publishTf>
<publishWheelJointState>true</publishWheelJointState>
<alwaysOn>true</alwaysOn>
<updateRate>100.0</updateRate>
<legacyMode>true</legacyMode>
<leftJoint>${ns}_left_wheel2base_link</leftJoint> <!-- 左轮 -->
<rightJoint>${ns}_right_wheel2base_link</rightJoint> <!-- 右轮 -->
<wheelSeparation>${base_link_radius * 2}</wheelSeparation> <!-- 车轮间距 -->
<wheelDiameter>${wheel_radius * 2}</wheelDiameter> <!-- 车轮直径 -->
<broadcastTF>1</broadcastTF>
<wheelTorque>30</wheelTorque>
<wheelAcceleration>1.8</wheelAcceleration>
<commandTopic>cmd_vel</commandTopic> <!-- 运动控制话题 -->
<odometryFrame>${ns}_odom</odometryFrame>
<odometryTopic>odom</odometryTopic> <!-- 里程计话题 -->
<robotBaseFrame>${ns}_base_footprint</robotBaseFrame> <!-- 根坐标系 -->
</gazebo>
注:在赵老师原有的写法中是<robotNamespace>/</robotNamespace>,加了/意味着cmd_vel和odom为全局的,这样即使加了group也不会有ns属性。
3、编队仿真
上面配置完以后就可以显示多机器人,并且可以单独控制机器人了,运行launch文件后rviz中显示如下:
gazebo中显示如下:
rostopic list显示如下:
可以看出cmd_vel 和odom话题都加上了相应的命名空间属性。
4、开源代码
为方便大家学习,代码开源链接如下:
https://github.com/quyinsong/multi_diffcar_ws.git
# 1 拷贝源码与编译
git clone https://github.com/quyinsong/multi_diffcar_ws.git
cd multi_diffcar_ws
catkin_make
source devel/setup.bash
# 2 运行代码
运行多机器人仿真环境(gazebo与rviz):roslaunch mydiffcar_gazebo multi_diffcar_gazebo.launch
运行编队控制器:roslaunch nmpc_ctr test_formation.launch
# 3 rviz为领航车发布2D nav goal
5、小结
其实我的代码改的复杂了,主要是之前不知道怎么修改,概括出来的三个步骤就是:
(1)launch文件中利用group为机器人分组----避免重名
(2)在每个group中完成odom到map的坐标变换---便于rviz显示多机器人
(3)修改机器人控制插件,使其发布的cmd_vel话题不具备全局属性,即去掉话题前面的 / ----便于单个控制机器人