如何在Gazebo中实现多机器人仿真

4978
35
2020年3月1日 19时38分

gazebo是一款功能强大的三维物理仿真平台,具备强大的物理引擎、高质量的图形渲染、方便的编程与图形接口,最重要的是其开源免费的特性。gazebo中的机器人模型与rviz使用的模型相同,但是需要在模型中加入机器人和周围环境的物理属性,例如质量、摩擦系数、弹性系数等。机器人的传感器信息也可以通过插件的形式加入仿真环境,以可视化的方式进行显示。

 

在ros学习及研发过程中,经常需要使用gazebo来进行3D仿真,对模型的各种物理参数、控制代码等进行实物前的操练。在多智能体协同控制的研究中,需要在gazebo中添加多个机器人用于仿真,那么,应该如何将一个乃至多个机器人,放入gazebo仿真环境中呢?

 

1.单机器人仿真

在gazebo中放入机器人的操作通常用launch文件实现,步骤可归纳为:

 

设置launch文件参数-运行gazebo仿真环境-加载机器人模型描述参数-加载机器人模型

 

其中有关于urdf模型的构建可以参考古月学院的课程《一起从零手写URDF模型》和前面小伙伴的帖子《URDF物理参数解释及生成》

 

在我的仿真任务中代码如下:

<launch>

    <!-- 设置launch文件的参数 -->
    <arg name="world_name" value="$(find ares_gazebo)/worlds/playground.world"/>
    <arg name="paused" default="false"/>
    <arg name="use_sim_time" default="true"/>
    <arg name="gui" default="true"/>
    <arg name="headless" default="false"/>
    <arg name="debug" default="false"/>

    <!-- 运行gazebo仿真环境 -->
    <include file="$(find gazebo_ros)/launch/empty_world.launch">
        <arg name="world_name" value="$(arg world_name)" />
        <arg name="debug" value="$(arg debug)" />
        <arg name="gui" value="$(arg gui)" />
        <arg name="paused" value="$(arg paused)"/>
        <arg name="use_sim_time" value="$(arg use_sim_time)"/>
        <arg name="headless" value="$(arg headless)"/>
    </include>

    <!-- 加载机器人模型描述参数 -->
    <param name="robot_description" command="$(find xacro)/xacro --inorder '$(find ares_description)/urdf/ares_laser.xacro'" /> 

    <!-- 运行joint_state_publisher节点,发布机器人的关节状态  -->
    <node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" ></node> 

    <!-- 运行robot_state_publisher节点,发布tf  -->
    <node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher"  output="screen" >
        <param name="publish_frequency" type="double" value="50.0" />
    </node>

    <!-- 在gazebo中加载机器人模型-->
    <node name="urdf_spawner" pkg="gazebo_ros" type="spawn_model" respawn="false" output="screen"
          args="-urdf -model ares -param robot_description"/> 

</launch>

 

如何在Gazebo中实现多机器人仿真插图

 

2.多机器人仿真

相比于单机器人,多机器人仿真需要在原基础上加入<group>标签,做到用同样的descripion配置文件加载多个独立的机器人。

 

<group>具有ns属性,可以将节点组推送到单独的命名空间中。

 

在前面的基础上,在launch文件中改写成以下内容:

<group ns="命名空间">
    <param name="robot_description" command="$(find xacro)/xacro --inorder '$(find ares_description)/urdf/ares_laser.xacro' ns:= 命名空间" /> 
    	<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"  output="screen" >
     <param name="publish_frequency" type="double" value="50.0" />
</node>
    	<node name="urdf_spawner" pkg="gazebo_ros" type="spawn_model" respawn="false" output="screen"
    args="-urdf -model 命名空间 -param robot_description -x 0"/>   
</group>

 

命名空间根据工程定义,在我的仿真中为ares1、ares2、ares3;“-x 0”为机器人在gazebo中的初始位置。

 

将原本有关机器人状态的节点以及机器人模型放在<group>标签内,这样被<group>标签包围的节点、话题、参数、服务,都会在前面加入<命名空间>的前缀,如 /ares2/joint_state_publisher

image001

图1 在命名空间为ares2下的节点、话题等

 

这样便可以加入独立的多个机器人模型,效果如下:

image003

图2 多机器人仿真效果

 

当<group>及命名空间使用正确时,机器人的输入输出都应独立,如下图中三车搭载的摄像头所看的图像正确,无相互影响:

如何在Gazebo中实现多机器人仿真插图(3)

图3 ares1、ares2、ares3视角图像

3.多机器人运动控制

在加入多个机器人后,再做一下键盘对其的简单控制。

 

1)同时控制多个机器人

这里我使用的方法,是在机器人配置文件控制驱动插件代码中设置全局名称/cmd_vel

<gazebo>
    <plugin name="mecanum_controller" filename="libgazebo_ros_planar_move.so">
	<commandTopic>/cmd_vel</commandTopic>
	<odometryTopic>/odom</odometryTopic>
	<odometryFrame>odom</odometryFrame> 	<leftFrontJoint>wheel_lf_joint</leftFrontJoint>
	<rightFrontJoint>wheel_rf_joint</rightFrontJoint>
	<leftRearJoint>wheel_lb_joint</leftRearJoint>
	<rightRearJoint>wheel_rb_joint</rightRearJoint>
	<odometryRate>20.0</odometryRate>
	<robotBaseFrame>base_link</robotBaseFrame>
     </plugin>
</gazebo>

 

然后在键盘控制节点中发布全局名称/cmd_vel,这样就可以简单地做到多机器人同时接收一致的控制指令:

vel_pub = rospy.Publisher('/cmd_vel', Twist, queue_size=1)

 

image011

图6 整体控制时的rqt_graph

 

如何在Gazebo中实现多机器人仿真插图(5)

图7 整体控制时的效果

 

2)单独控制一个机器人

与前面相对,在这里我们将发布和接收的cmd_vel全部设置为相对名称(相对名称的典型特征是它缺少全局名称带有的前斜杠“/”),在我们设置的命名空间内发布后,ROS将当前命名空间的名称加在相对名称的前面,从而将相对名解析为全局名称。

 

即做以下修改:

<commandTopic>cmd_vel</commandTopic>

vel_pub = rospy.Publisher('cmd_vel', Twist, queue_size=1)

 

在终端启动键盘控制节点时加上命名空间,即可实现对单个机器人的控制:

$ ROS_NAMESPACE=ares1 rosrun ares_teleop ares_teleop.py

 

image014图8 单独控制时的rqt_graph

 

如何在Gazebo中实现多机器人仿真插图(7)

如何在Gazebo中实现多机器人仿真插图(8)

图9、10 单独控制时的效果

 

在命名空间下,还有经常使用的重映射<remap>操作,这里就不在赘述,感兴趣的小伙伴可以参考古月君的文章《ROS探索总结(五十六)—— launch文件》

 

在gazebo中加载多机器人仅仅是多智能体协同控制研究的第一步,之后还有大量的研究要做,我写的也只是个人总结 ,一定有很多不足之处,欢迎大家一起留言讨论。引用古月君的话作为总结,“怕什么真理无穷,进一寸有一寸的欢喜”,共勉!

 

完整代码:

<launch> 
    <!-- 设置launch文件的参数 --> 
    <arg name="world_name" value="$(find ares_gazebo)/worlds/playground.world"/> 
    <arg name="paused" default="false"/> 
    <arg name="use_sim_time" default="true"/> 
    <arg name="gui" default="true"/> 
    <arg name="headless" default="false"/> 
    <arg name="debug" default="false"/> 
 
    <!-- 运行gazebo仿真环境 --> 
    <include file="$(find gazebo_ros)/launch/empty_world.launch"> 
        <arg name="world_name" value="$(arg world_name)" /> 
        <arg name="debug" value="$(arg debug)" /> 
        <arg name="gui" value="$(arg gui)" /> 
        <arg name="paused" value="$(arg paused)"/> 
        <arg name="use_sim_time" value="$(arg use_sim_time)"/> 
        <arg name="headless" value="$(arg headless)"/> 
    </include> 
 
	 
    <!-- 加载机器人模型描述参数 --> 
	<!-- begin robot1 --> 
	<group ns="ares1"> 
    	<param name="robot_description" command="$(find xacro)/xacro --inorder '$(find ares_description)/urdf/ares_laser.xacro' ns:=ares1" />  
 
    	<!-- 运行joint_state_publisher节点,发布机器人的关节状态  --> 
    	<node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" ></node>  
 
    	<!-- 运行robot_state_publisher节点,发布tf  --> 
   		<node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher"  output="screen" > 
        <param name="publish_frequency" type="double" value="50.0" /> 
		</node> 
	 
	<!-- node name="ares_teleop"       pkg="ares_teleop" type="ares_teleop.py"       output="screen" /--> 
 
    	<!-- 在gazebo中加载机器人模型--> 
    	<node name="urdf_spawner" pkg="gazebo_ros" type="spawn_model" respawn="false" output="screen" 
          	args="-urdf -model ares1 -param robot_description -x 0"/>  
   		 
	</group> 
	<!-- begin robot2 --> 
	<group ns="ares2"> 
    	<param name="robot_description" command="$(find xacro)/xacro --inorder '$(find ares_description)/urdf/ares_laser.xacro' ns:=ares2" />  
 
    	<!-- 运行joint_state_publisher节点,发布机器人的关节状态  --> 
    	<node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" ></node>  
 
    	<!-- 运行robot_state_publisher节点,发布tf  --> 
   		<node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher"  output="screen" > 
        <param name="publish_frequency" type="double" value="50.0" /> 
		</node> 
    	<!-- 在gazebo中加载机器人模型--> 
    	<node name="urdf_spawner" pkg="gazebo_ros" type="spawn_model" respawn="false" output="screen" 
          	args="-urdf -model ares2 -param robot_description -x 0.8"/>  
	</group> 
	<!-- begin robot3 --> 
	<group ns="ares3"> 
    	<param name="robot_description" command="$(find xacro)/xacro --inorder '$(find ares_description)/urdf/ares_laser.xacro' ns:=ares3" />  
    	<!-- 运行joint_state_publisher节点,发布机器人的关节状态  --> 
    	<node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" ></node>  
    	<!-- 运行robot_state_publisher节点,发布tf  --> 
   		<node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher"  output="screen" > 
        <param name="publish_frequency" type="double" value="50.0" />
		</node>
    	<!-- 在gazebo中加载机器人模型--> 
    	<node name="urdf_spawner" pkg="gazebo_ros" type="spawn_model" respawn="false" output="screen" 
          	args="-urdf -model ares3 -param robot_description -y 0.8"/> 
	</group>
</launch>

 

发表评论

后才能评论

评论列表(35条)

  • 付雷雷 2020年8月4日 下午1:21

    大家有问题也可以移步古月居论坛-多机器人专区讨论,避免重复问题https://www.guyuehome.com/forum/%e6%96%b9%e6%a1%88%e5%ba%94%e7%94%a8/%e5%a4%9a%e6%9c%ba%e5%99%a8%e4%ba%ba

  • L. 2020年7月30日 下午3:21

    为什么我换了一个自己的模型就无法加载出来啊 就是黑屏 如果单独加载我的模型就可以 但是group就会黑屏 求大佬帮帮忙

    • 付雷雷 回复 L. 2020年8月4日 下午1:23

      黑屏的意思是无法加载模型,还是地图都无法加载呢?

    • L. 回复 付雷雷 2020年8月14日 下午2:59

      全都无法加载

  • xq453_0317 2020年7月22日 下午8:54

    机器人配置文件控制驱动插件代码中设置全局名称/cmd_vel, 是指哪个文件啊

  • idx2k_2654 2020年6月6日 上午9:44

    您好,我想请教一个问题,在我的仿真里,把cmd_vel前的/去掉,在终端启动键盘控制节点时加上命名空间时,仿真机器人不动,去掉/后,三个机器人一起动,想问问可能是什么原因

    • idx2k_2654 回复 idx2k_2654 2020年6月8日 上午9:12

      单独控制一个机器人的时候,从rqt_graph中显示键盘控制节点已经和ares1在统一命名空间下了,但是小车和节点之间没有/ares1/cml_vel话题,这可能是什么原因呢

    • 付雷雷 回复 idx2k_2654 2020年6月18日 下午1:10

      检查一下机器人的底盘配置文件,其中的运动控制插件里的/cmd_vel也需要去掉/

  • thuur_8070 2020年6月3日 下午2:14

    请问是开源的项目吗?可以参考下完整的工程嘛?

    • 古月 回复 thuur_8070 2020年6月3日 下午9:21

      是开源项目的,正在整理,近期会在古月居的“项目中心”开放出来

    • thuur_8070 回复 古月 2020年6月4日 下午2:34

      好的,谢谢,期待中…..

    • thuur_8070 回复 古月 2020年6月21日 上午12:47

      古月老师,请问这个开源项目整理完毕了吗?在项目中心还未找到

  • dplyr_8316 2020年5月5日 下午4:14

    写的超级好,谢谢老师解决了困扰了我一个星期的问题

  • 付雷雷 2020年4月20日 下午9:03

    我的qq是1347268191,有问题的欢迎加我一起探讨(备注请说明来意!无事勿扰!)

  • 张无忌 2020年4月14日 下午11:01

    老师您好!我想尝试在原先一个机器人控制程序的基础上扩展为多个机器人控制。于是我就先在机器人的launch文件当中增加了的标签,当我用rqt_graph检查节点的时候发现键盘节点不能和下的节点进行通信了。;查找资料之后发现需要进行重映射,于是我将原先的通信话题/mavros/state在启动键盘控制的launch中进行重映射为/uav1/mavros/state,却发现还是不能进行通信,rostopic查看当中还是有原先的/mavros/state。请问我可能是哪部分知识点理解出错了啊,希望老师能够提供一些解决问题的思路,谢谢!

    • 付雷雷 回复 张无忌 2020年4月20日 下午9:04

      是需要分别控制还是一起控制呢?

    • 付雷雷 回复 张无忌 2020年4月20日 下午9:06

      一起控制可以直接设为全局变量/cmd_vel。分别控制可以分别启动三个带有具体ns的键盘控制节点

  • Goodwood 2020年3月28日 下午10:32

    您好老师,想请问下怎样能使gazebo中robot_state_publisher节点发布的tf信息给link附加上namespace?按教程正常启动,rostopic pub后也能控制三个或某一个小车正常移动。我rqt_graph_tree的时候发现,只有一个base_link,没有显示namespace,(按理应该有三个,例如ares1/base_link,ares2/base_link,ares3/base_link)。而且base_link连接的这些关节是混在一起的,图中:base->wheel_rb_link的broadcaster显示是ares2/robot_state_publisher,而base->laser_link的broadcaster显示是ares3/robot_state_publisher。谢谢!

    • 付雷雷 回复 Goodwood 2020年4月20日 下午9:01

      tf关系是不能靠命名空间的。在你的robot_state_publisher节点内加上

    • 付雷雷 回复 付雷雷 2020年4月20日 下午9:02

      param name=”tf_prefix” value=”ares1″

  • 若言 2020年3月25日 下午8:43

    胡老师,您好,请问如何在Gazebo环境中添加动态障碍物,从而实现动态避障仿真呢?,希望老师多多指点一下

    • 古月 回复 若言 2020年3月28日 上午11:04

      gazebo的离线模型中,本身带有一些动态模型的(比如运动的人),可以作为障碍物;如果需要控制,也可以加入另外一个机器人作为障碍物

    • c8z93_6051 回复 若言 2020年4月22日 下午3:52

      请问你找到了吗?

  • 临风 2020年3月25日 下午2:23

    请问下。moveit中实现多机器人仿真也是这样吗,尝试了一下,好像不成功

    • 古月 回复 临风 2020年3月25日 下午8:27

      也是类似的,可以参考ROS中的双臂系统,比如PR2

    • 临风 回复 古月 2020年3月26日 下午1:50

      我想的是同时加载多个不同的urdf来协同仿真,pr2机器人只是双臂,当还是在同一个urdf下把

  • 隹之 2020年3月13日 上午11:59

    你好请问一下,我在多机仿真的时候,会一直卡在
    [ INFO] [1584070654.593217651, 0.004000000]: gazebo_ros_control plugin is waiting for model URDF in parameter [robot_description] on the ROS param server.
    不知道是什么原因?
    单机是没有问题的。

    • 付雷雷 回复 隹之 2020年4月1日 下午2:48

      建议检查一下launch文件中关于和命名空间的部分有没有问题,这应该是找不到对应的urdf文件

    • Yuheng Zhang 回复 付雷雷 2020年6月2日 下午1:36

      您是加载的相同的机器人,gazebo中能加载不同的机器人吗

    • Yuheng Zhang 回复 Yuheng Zhang 2020年6月2日 下午1:43

      我刚才又试了一下加载不同的机器人,突然就加载成功了,很神奇

    • Yuheng Zhang 回复 隹之 2020年6月2日 下午1:34

      我用gazebo中加载不同的机器人也会卡在这

  • qu5ci_7862 2020年3月4日 下午1:05

    你好,能否请教一下麦轮小车在仿真过程中该如何配置

    • 古月 回复 qu5ci_7862 2020年3月4日 下午9:45

      可以参考这门课程,里边有麦轮小车:https://class.guyuehome.com/detail/p_5e32dce7906e0_6TqS7BwX/6

    • 安好 回复 古月 2020年5月19日 下午2:53

      古月老师你好 我用 如何从Solidworks导出URDF模型 · 古月 课程中的ares小车 添加libgazebo_ros_planar_move.so插件 运动时小车翻车 这个是什么原因阿