本文在Ubuntu18.04 + ROS melodic环境下完成,其他ROS版本类似。

gazebo plugins为urdf模型提供了更大的功能,并且可以将ROS消息和服务调用捆绑在一起以用于传感器输出和电动机输入。 在本教程中,我们将介绍如何设置现有插件以及如何创建可以与ROS一起使用的自定义插件。

一、先决条件

确保您学习了urdf模型解析教程,并根据教程设置好了RRBot。同样,请确保您已理解urdf描述中<gazebo>元素的用法。

二、插件类型

gazebo支持几种插件类型,并且所有插件类型都可以连接到ROS,但是只能通过urdf文件引用几种类型:

1、添加一个ModelPlugin

简而言之,将ModelPlugin插入到<robot>元素内,它放置在<gazebo>元素内,以指示传递给gazebo的信息。例如:

<robot>
  ... robot description ...
  <gazebo>
    <plugin name="differential_drive_controller" filename="libdiffdrive_plugin.so">
      ... plugin parameters ...
    </plugin>
  </gazebo>
  ... robot description ...
</robot>

在gazebo中加载机器人模型后,diffdrive_plugin代码将获得对模型本身的引用,从而可以对其进行操作。另外,它还将提供对自身sdf元素的引用,以读取传递给它的插件参数。

2、添加一个SensorPlugin

gazebo中的传感器应连接到连杆(link),因此描述该传感器的<gazebo>元素的reference=""必须指向对应连杆。 例如:

<robot>
  ... robot description ...
  <link name="sensor_link">
    ... link description ...
  </link>

  <gazebo reference="sensor_link">
    <sensor type="camera" name="camera1">
      ... sensor parameters ...
      <plugin name="camera_controller" filename="libgazebo_ros_camera.so">
        ... plugin parameters ..
      </plugin>
    </sensor>
  </gazebo>

</robot>

在将机器人模型加载到gazebo中后,camera_controller代码将获得对传感器的引用,从而可以访问其API。 另外,它还将提供对自身sdf元素的引用,以读取传递给它的插件参数。

3、gazebo_plugins中可用的插件

接下来,各节介绍了gazebo_plugins中可用的所有插件。建议您按顺序学习它们,因为前几个插件介绍了更多细节,并且您可以从各种插件的文档中学习一些概念。

插件列表:

每个部分的名称都是从插件类名称派生的。例如“Block Laser”来自GazeboRosBlockLaser类,可以在文件gazebo_plugins/src/gazebo_ros_block_laser.cpp中找到。

如果某些部分为空白,则意味着该作者已经厌倦了记录每个插件,如果您具有有关如何使用特定插件的知识和示例,则填写在该区域。

三、Camera

提供ROS接口,用于仿真摄像头,例如wge100_camera通过发布CameraInfo和Image ROS消息。

在本节中,我们将介绍一个安装在RRBot摆臂末端的简单RGB相机。您可以查看rrbot.xacro内的内容。该块的第一个元素是额外的连杆和关节,已添加到代表摄像机的urdf文件中。 尽管通常可以使用mesh文件来更好地表示,但我们只是使用一个简单的红色框来表示摄像机。

<joint name="camera_joint" type="fixed">
  <axis xyz="0 1 0" />
  <origin xyz="${camera_link} 0 ${height3 - axel_offset*2}" rpy="0 0 0"/>
  <parent link="link3"/>
  <child link="camera_link"/>
</joint>

<!-- Camera -->
<link name="camera_link">
  <collision>
    <origin xyz="0 0 0" rpy="0 0 0"/>
    <geometry>
  <box size="${camera_link} ${camera_link} ${camera_link}"/>
    </geometry>
  </collision>

  <visual>
    <origin xyz="0 0 0" rpy="0 0 0"/>
    <geometry>
  <box size="${camera_link} ${camera_link} ${camera_link}"/>
    </geometry>
    <material name="red"/>
  </visual>

  <inertial>
    <mass value="1e-5" />
    <origin xyz="0 0 0" rpy="0 0 0"/>
    <inertia ixx="1e-6" ixy="0" ixz="0" iyy="1e-6" iyz="0" izz="1e-6" />
  </inertial>
</link>

一个xacro宏在文件开头被定义:

<xacro:property name="camera_link" value="0.05" /> <!-- Size of square 'camera' box -->

您应该能够启动RRBot并看到附在手臂末端的红色框。

接下来,我们将回顾gazebo插件,该插件为我们提供了摄像头功能,并将图像发布到ROS消息中。在RRBot中,我们一直遵循将gazebo元素放在rrbot.gazebo文件中的约定:

<!-- camera -->
<gazebo reference="camera_link">
  <sensor type="camera" name="camera1">
    <update_rate>30.0</update_rate>
    <camera name="head">
      <horizontal_fov>1.3962634</horizontal_fov>
      <image>
        <width>800</width>
        <height>800</height>
        <format>R8G8B8</format>
      </image>
      <clip>
        <near>0.02</near>
        <far>300</far>
      </clip>
      <noise>
        <type>gaussian</type>
        <!-- Noise is sampled independently per pixel on each frame.
             That pixel's noise value is added to each of its color
             channels, which at that point lie in the range [0,1]. -->
        <mean>0.0</mean>
        <stddev>0.007</stddev>
      </noise>
    </camera>
    <plugin name="camera_controller" filename="libgazebo_ros_camera.so">
      <alwaysOn>true</alwaysOn>
      <updateRate>0.0</updateRate>
      <cameraName>rrbot/camera1</cameraName>
      <imageTopicName>image_raw</imageTopicName>
      <cameraInfoTopicName>camera_info</cameraInfoTopicName>
      <frameName>camera_link</frameName>
      <hackBaseline>0.07</hackBaseline>
      <distortionK1>0.0</distortionK1>
      <distortionK2>0.0</distortionK2>
      <distortionK3>0.0</distortionK3>
      <distortionT1>0.0</distortionT1>
      <distortionT2>0.0</distortionT2>
    </plugin>
  </sensor>
</gazebo>

接着,我们了解一下这个插件的一些属性。

  • 连杆名称“camera_link”必须与我们添加到xacro的连杆的名称匹配。
<gazebo reference="camera_link">
  • 传感器名称必须是唯一的,不能重名。
<sensor type="camera" name="camera1">
  • update_rate为每秒摄像头拍摄的次数,这是传感器在仿真过程中的最大更新速率,但是如果物理仿真的运行速度快于传感器生成的速度,则它可能会落后于该目标速率。
<update_rate>30.0</update_rate>
  • 填写以下这些值以匹配物理相机硬件上制造商的规格。要注意的一件事是,假定像素为正方形。此外,近片段(clip)和远片段是特定于仿真的参数,为摄像机可以看到仿真中的对象的距离提供了上限和下限。 这是在相机的验光框中指定的。
  • <horizontal_fov>1.3962634</horizontal_fov>
    <image>
      <width>800</width>
      <height>800</height>
      <format>R8G8B8</format>
    </image>
    <clip>
      <near>0.02</near>
      <far>300</far>
    </clip>
  • 这是实际的gazebo_ros/gazebo_ros_camera.cpp文件作为共享对象链接到的位置。
  • <plugin name="camera_controller" filename="libgazebo_ros_camera.so">
  • 在这里,我们为图像主题和照相机信息主题定义了将要发布到摄影机的rostopic。
<cameraName>rrbot/camera1</cameraName>
<imageTopicName>image_raw</imageTopicName>
<cameraInfoTopicName>camera_info</cameraInfoTopicName>

对于RRBot,您应该订阅:

/rrbot/camera1/image_raw
/rrbot/camera1/camera_info
  • 图像在tf树中发布的坐标框架。
<frameName>camera_link</frameName>

接下来,让我们运行一下RRBot案例。保存rrbot.xacro和rrbot.gazebo后,应该可以在单独的终端中同时启动rviz和gazebo:

$ roslaunch rrbot_gazebo rrbot_world.launch
$ roslaunch rrbot_description rrbot_rviz.launch

在rviz中,添加“Camera”插件,然后在“Image Topic”下将其设置为/rrbot/camera1/ image_raw。

您应该会看到gazebo环境的摄像机视图。在以下两张图片中,易拉罐已添加到环境中,以获得更好的视觉效果。

添加易拉罐:

连杆垂下后的相应摄像机视图:

四、Multicamera

多个相机同时开启,以便它们将图像一起发布。通常用于立体摄像机,接口与Camera插件非常相似。目前仅支持立体摄像机,具体使用教程请查看github

代码实例(在此代码示例中,有左右两个摄像头:):

<gazebo reference="left_camera_frame">
  <sensor type="multicamera" name="stereo_camera">
    <update_rate>30.0</update_rate>
    <camera name="left">
      <horizontal_fov>1.3962634</horizontal_fov>
      <image>
        <width>800</width>
        <height>800</height>
        <format>R8G8B8</format>
      </image>
      <clip>
        <near>0.02</near>
        <far>300</far>
      </clip>
      <noise>
        <type>gaussian</type>
        <mean>0.0</mean>
        <stddev>0.007</stddev>
      </noise>
    </camera>
    <camera name="right">
      <pose>0 -0.07 0 0 0 0</pose>
      <horizontal_fov>1.3962634</horizontal_fov>
      <image>
        <width>800</width>
        <height>800</height>
        <format>R8G8B8</format>
      </image>
      <clip>
        <near>0.02</near>
        <far>300</far>
      </clip>
      <noise>
        <type>gaussian</type>
        <mean>0.0</mean>
        <stddev>0.007</stddev>
      </noise>
    </camera>
    <plugin name="stereo_camera_controller" filename="libgazebo_ros_multicamera.so">
      <alwaysOn>true</alwaysOn>
      <updateRate>0.0</updateRate>
      <cameraName>multisense_sl/camera</cameraName>
      <imageTopicName>image_raw</imageTopicName>
      <cameraInfoTopicName>camera_info</cameraInfoTopicName>
      <frameName>left_camera_optical_frame</frameName>
      <!--<rightFrameName>right_camera_optical_frame</rightFrameName>-->
      <hackBaseline>0.07</hackBaseline>
      <distortionK1>0.0</distortionK1>
      <distortionK2>0.0</distortionK2>
      <distortionK3>0.0</distortionK3>
      <distortionT1>0.0</distortionT1>
      <distortionT2>0.0</distortionT2>
    </plugin>
  </sensor>
</gazebo>

五、Depth Camera

模拟类似Kinect的传感器,该传感器在Kinect插件中是重复的,将来可能会合并。您可以在使用带有ROS的gazebo深度摄像头中找到有关配置深度摄像头的详细说明

六、Openni Kinect

模拟Microsoft Kinect,并发布与Microsoft kinect相应的ROS驱动程序相同的主题,具体使用教程请查看wiki

<gazebo reference="${link_name}">
  <sensor name="${link_name}_camera" type="depth">
    <update_rate>20</update_rate>
    <camera>
      <horizontal_fov>1.047198</horizontal_fov>
      <image>
        <width>640</width>
        <height>480</height>
        <format>R8G8B8</format>
      </image>
      <clip>
        <near>0.05</near>
        <far>3</far>
      </clip>
    </camera>
    <plugin name="${link_name}_controller" filename="libgazebo_ros_openni_kinect.so">
      <baseline>0.2</baseline>
      <alwaysOn>true</alwaysOn>
      <updateRate>1.0</updateRate>
      <cameraName>${camera_name}_ir</cameraName>
      <imageTopicName>/${camera_name}/color/image_raw</imageTopicName>
      <cameraInfoTopicName>/${camera_name}/color/camera_info</cameraInfoTopicName>
      <depthImageTopicName>/${camera_name}/depth/image_raw</depthImageTopicName>
      <depthImageInfoTopicName>/${camera_name}/depth/camera_info</depthImageInfoTopicName>
      <pointCloudTopicName>/${camera_name}/depth/points</pointCloudTopicName>
      <frameName>${frame_name}</frameName>
      <pointCloudCutoff>0.5</pointCloudCutoff>
      <pointCloudCutoffMax>3.0</pointCloudCutoffMax>
      <distortionK1>0.00000001</distortionK1>
      <distortionK2>0.00000001</distortionK2>
      <distortionK3>0.00000001</distortionK3>
      <distortionT1>0.00000001</distortionT1>
      <distortionT2>0.00000001</distortionT2>
      <CxPrime>0</CxPrime>
      <Cx>0</Cx>
      <Cy>0</Cy>
      <focalLength>0</focalLength>
      <hackBaseline>0</hackBaseline>
    </plugin>
  </sensor>
</gazebo>

gazebo中:

rviz中(可以发现Stereo Camera与普通Camera显示的图片是不一样的):

七、GPU Laser

通过广播LaserScan消息来模拟激光测距传感器。 请参阅《Hokuyo激光扫描仪参考文档》

以RRBot为例,在查看本示例之前,请参阅RRBot示例以将摄像机添加到RRBot。 与添加摄像机类似,我们将向RRBot的xacro中添加新的连杆接和关节。这次,我们将使用网格,而不是仅将可视化为矩形。

向rrbot.xacro中添加以下内容(最新的rrbot功能包已经包含以下内容,无需再添加):

<joint name="hokuyo_joint" type="fixed">
  <axis xyz="0 1 0" />
  <origin xyz="0 0 ${height3 - axel_offset/2}" rpy="0 0 0"/>
  <parent link="link3"/>
  <child link="hokuyo_link"/>
</joint>

<!-- Hokuyo Laser -->
<link name="hokuyo_link">
  <collision>
    <origin xyz="0 0 0" rpy="0 0 0"/>
    <geometry>
  <box size="0.1 0.1 0.1"/>
    </geometry>
  </collision>

  <visual>
    <origin xyz="0 0 0" rpy="0 0 0"/>
    <geometry>
      <mesh filename="package://rrbot_description/meshes/hokuyo.dae"/>
    </geometry>
  </visual>

  <inertial>
    <mass value="1e-5" />
    <origin xyz="0 0 0" rpy="0 0 0"/>
    <inertia ixx="1e-6" ixy="0" ixz="0" iyy="1e-6" iyz="0" izz="1e-6" />
  </inertial>
 </link>

现在,再次将信息添加到rrbot.gazebo中,就像我们在Camera示例所做的那样:

<!-- hokuyo -->
 <gazebo reference="hokuyo_link">
  <sensor type="gpu_ray" name="head_hokuyo_sensor">
    <pose>0 0 0 0 0 0</pose>
    <visualize>false</visualize>
    <update_rate>40</update_rate>
    <ray>
      <scan>
        <horizontal>
          <samples>720</samples>
          <resolution>1</resolution>
          <min_angle>-1.570796</min_angle>
          <max_angle>1.570796</max_angle>
        </horizontal>
      </scan>
      <range>
        <min>0.10</min>
        <max>30.0</max>
        <resolution>0.01</resolution>
      </range>
      <noise>
        <type>gaussian</type>
        <!-- Noise parameters based on published spec for Hokuyo laser
             achieving "+-30mm" accuracy at range < 10m.  A mean of 0.0m and
             stddev of 0.01m will put 99.7% of samples within 0.03m of the true
             reading. -->
        <mean>0.0</mean>
        <stddev>0.01</stddev>
      </noise>
    </ray>
    <plugin name="gazebo_ros_head_hokuyo_controller" filename="libgazebo_ros_gpu_laser.so">
      <topicName>/rrbot/laser/scan</topicName>
      <frameName>hokuyo_link</frameName>
    </plugin>
  </sensor>
</gazebo>

大多数属性是不言自明的,但是我们将在下面进行回顾:

<visualize>false</visualize>

如果<visualize>为true,则在gpu激光的扫描区域内可以看到半透明的激光射线,如下图所示。这可能是信息丰富的可视化,也可能是令人讨厌的事情。

将这些设置为激光扫描即将要发布到的ROS主题名称,以及您希望TF使用的转换框架:<topicName>/rrbot/laser/scan</topicName>
<frameName>hokuyo_link</frameName>

保存rrbot.xacro和rrbot.gazebo后,同样地在单独的终端中同时启动rviz和gazebo。

$ roslaunch rrbot_gazebo rrbot.launch
$ roslaunch rrbot_description rrbot_rviz.launch

在rviz中,添加“ LaserScan”显示,并在“Topic”下将其设置为/rrbot/laser/scan。

您应该在gazebo环境中看到一条微弱的激光扫描线。当连杆摆动时,您还应该看到激光扫描的摆动。 如果扫描太微弱,则可以在rviz中的LaserScan显示器的属性中增大激光扫描的大小,将设为1m。 在以下两张图片中,向环境中添加了一些物体,以提供更好的视觉效果。

gazebo中:

rviz中:

红色部分即为激光扫描仪扫描到的物体轮廓边缘(左边的4个为汽车轮胎,中间的1个为喷泉,右边的为房子,连杆上端出现的红色矩形是因为扫描到了rrbot机器人自身的连杆,别忘了它在gazebo中是下垂的状态)

八、Laser

非GPU版本的GPU Laser,但本质上使用相同的代码。 有关文档,请参见GPU Laser。

要与RRBot一起运行,请打开rrbot.gazebo并更改以下两行:

将:

<sensor type="gpu_ray" name="head_hokuyo_sensor">

替换为:

 <sensor type="ray" name="head_hokuyo_sensor">

还有,将:

<plugin name="gazebo_ros_head_hokuyo_controller" filename="libgazebo_ros_gpu_laser.so">

替换为:

<plugin name="gazebo_ros_head_hokuyo_controller" filename="libgazebo_ros_laser.so">

保存,然后启动与GPU Laser相同的启动文件。

九、Block Laser

提供网格样式的激光测距仪模拟(例如Velodyne)。

十、F3D (Force Feedback Ground Truth)

通过WrenchStamped消息在模拟中广播身体上的外力。

十一、Force

ROS接口,用于在仿真中在身体上应用扭矩。

十二、IMU (GazeboRosImu)

模拟IMU传感器。测量是由ROS插件而不是gazebo计算的。有关实现,请参见下面的用法摘要示例。

<robot>
  ...
  <gazebo>
    <plugin name="imu_plugin" filename="libgazebo_ros_imu.so">
      <alwaysOn>true</alwaysOn>
      <bodyName>base_footprint</bodyName>
      <topicName>imu</topicName>
      <serviceName>imu_service</serviceName>
      <gaussianNoise>0.0</gaussianNoise>
      <updateRate>20.0</updateRate>
    </plugin>
  </gazebo>
</robot>

十三、IMU sensor (GazeboRosImuSensor)

模拟一个惯性运动单位传感器,它与IMU(GazeboRosIMU)的主要区别是:从SensorPlugin继承而不是ModelPlugin;测量是由gazebo ImuSensor 给出的,而不是由ros插件计算的;重力包括在惯性测量中;将initialOrientationAsReference设置为false遵守了REP 145协议。

<gazebo reference="imu_link">
  <gravity>true</gravity>
  <sensor name="imu_sensor" type="imu">
    <always_on>true</always_on>
    <update_rate>100</update_rate>
    <visualize>true</visualize>
    <topic>__default_topic__</topic>
    <plugin filename="libgazebo_ros_imu_sensor.so" name="imu_plugin">
      <topicName>imu</topicName>
      <bodyName>imu_link</bodyName>
      <updateRateHZ>10.0</updateRateHZ>
      <gaussianNoise>0.0</gaussianNoise>
      <xyzOffset>0 0 0</xyzOffset>
      <rpyOffset>0 0 0</rpyOffset>
      <frameName>imu_link</frameName>
      <initialOrientationAsReference>false</initialOrientationAsReference>
    </plugin>
    <pose>0 0 0 0 0 0</pose>
  </sensor>
</gazebo>

十四、Joint Pose Trajectory

监听关节轨迹动作并播放关节位置集。将关节组设置为精确位置,而不考虑模拟物理场和力。

十五、P3D (3D Position Interface for Ground Truth)

通过里程表消息广播模拟中任何身体的惯性姿势。

十六、Projector

从光源向外投射静态纹理,例如与PR2的原始头部摄像头传感器一起使用。 有关更多信息,请参见API文档。。

十七、Prosilica Camera

模拟ROS Prosilica相机暴露的接口。这是一个URDF Xacro宏示例。

十八、Bumper

通过ContactsState Message提供连接反馈。

<gazebo>
  <plugin name="${name}_gazebo_ros_bumper_controller" filename="libgazebo_ros_bumper.so">
    <alwaysOn>true</alwaysOn>
    <updateRate>${update_rate}</updateRate>
    <bumperTopicName>${name}_bumper</bumperTopicName>
    <frameName>world</frameName>
  </plugin>
</gazebo>

十九、Differential Drive

model plugin,为gazebo中的差动驱动机器人提供基本控制器。您需要一个定义明确的差动驱动器机器人才能使用此插件。

<gazebo>
  <plugin name="differential_drive_controller" filename="libgazebo_ros_diff_drive.so">

    <!-- Plugin update rate in Hz -->
    <updateRate>${update_rate}</updateRate>

    <!-- Name of left joint, defaults to `left_joint` -->
    <leftJoint>base_link_left_wheel_joint</leftJoint>

    <!-- Name of right joint, defaults to `right_joint` -->
    <rightJoint>base_link_right_wheel_joint</rightJoint>

    <!-- The distance from the center of one wheel to the other, in meters, defaults to 0.34 m -->
    <wheelSeparation>0.5380</wheelSeparation>

    <!-- Diameter of the wheels, in meters, defaults to 0.15 m -->
    <wheelDiameter>0.2410</wheelDiameter>

    <!-- Wheel acceleration, in rad/s^2, defaults to 0.0 rad/s^2 -->
    <wheelAcceleration>1.0</wheelAcceleration>

    <!-- Maximum torque which the wheels can produce, in Nm, defaults to 5 Nm -->
    <wheelTorque>20</wheelTorque>

    <!-- Topic to receive geometry_msgs/Twist message commands, defaults to `cmd_vel` -->
    <commandTopic>cmd_vel</commandTopic>

    <!-- Topic to publish nav_msgs/Odometry messages, defaults to `odom` -->
    <odometryTopic>odom</odometryTopic>

    <!-- Odometry frame, defaults to `odom` -->
    <odometryFrame>odom</odometryFrame>

    <!-- Robot frame to calculate odometry from, defaults to `base_footprint` -->
    <robotBaseFrame>base_footprint</robotBaseFrame>

    <!-- Odometry source, 0 for ENCODER, 1 for WORLD, defaults to WORLD -->
    <odometrySource>1</odometrySource>

    <!-- Set to true to publish transforms for the wheel links, defaults to false -->
    <publishWheelTF>true</publishWheelTF>

    <!-- Set to true to publish transforms for the odometry, defaults to true -->
    <publishOdom>true</publishOdom>

    <!-- Set to true to publish sensor_msgs/JointState on /joint_states for the wheel joints, defaults to false -->
    <publishWheelJointState>true</publishWheelJointState>

    <!-- Set to true to swap right and left wheels, defaults to true -->
    <legacyMode>false</legacyMode>
  </plugin>
</gazebo>

二十、Skid Steering Drive

model plugin,为gazebo中的防滑转向驱动机器人提供基本控制器(例如Pioneer 3AT)。

<gazebo>
  <plugin name="skid_steer_drive_controller" filename="libgazebo_ros_skid_steer_drive.so">
    <updateRate>100.0</updateRate>
    <robotNamespace>/</robotNamespace>
    <leftFrontJoint>front_left_wheel_joint</leftFrontJoint>
    <rightFrontJoint>front_right_wheel_joint</rightFrontJoint>
    <leftRearJoint>back_left_wheel_joint</leftRearJoint>
    <rightRearJoint>back_right_wheel_joint</rightRearJoint>
    <wheelSeparation>0.4</wheelSeparation>
    <wheelDiameter>0.215</wheelDiameter>
    <robotBaseFrame>base_link</robotBaseFrame>
    <torque>20</torque>
    <topicName>cmd_vel</topicName>
    <broadcastTF>false</broadcastTF>
  </plugin>
</gazebo>

二十一、Video Plugin

visual plugin,可在gazebo内的OGRE Texture上显示ROS图像流。该插件不会修改现有连杆表面的纹理,但会在其顶部创建一个新纹理。纹理将在XY平面上创建,从+ Z侧可见。该插件在构造纹理时需要一个像素大小,并且将调整传入的ROS图像消息的大小以使其匹配(如果它们的大小不同)。

<gazebo reference="display_screen_link">
  <visual>
    <plugin name="display_video_controller" filename="libgazebo_ros_video.so">
      <topicName>image</topicName>
      <height>120</height>
      <width>160</width>
    </plugin>
  </visual>
</gazebo>

二十二、Planar Move Plugin

model plugin,该插件允许使用geometry_msgs/Twist消息沿水平面移动任意对象(例如立方体,球体和圆柱体)。该插件通过在每个周期将线性速度(XY)和角速度(Z)赋予对象来工作。

这是一个完整的urdf示例,演示了如何使用此插件,使用不同的可视元素和碰撞元素来控制gazebo内部的浮动框。注意:对象需要具有足够的惯性,以防止发生不希望的运动,这种运动可能是对所提供的速度的反作用。您可以尝试增加惯性,直到对象按需要移动为止。同时,使质心靠近地面。

<robot name="test_model">

  <!-- root link, on the ground just below the model origin -->
  <link name="base_footprint">
   <visual>
      <origin xyz="0 0 0" rpy="0 0 0" />
      <geometry>
        <box size="0.001 0.001 0.001" />
      </geometry>
    </visual>
  </link>

  <joint name="base_link_joint" type="fixed">
    <origin xyz="0.0 0 1.25" rpy="0 0 0" />
    <parent link="base_footprint"/>
    <child link="base_link" />
  </joint>

  <!-- the model -->
  <link name="base_link">
    <inertial>
      <mass value="50" />
      <origin xyz="0 0 -1.25" />
      <inertia ixx="50.0" ixy="0.0" ixz="0.0"
        iyy="50.0" iyz="0.0"
        izz="50.0" />
    </inertial>
    <visual>
      <geometry>
        <box size="0.5 0.5 1.0" /> <!-- does not need to match collision -->
      </geometry>
    </visual>
    <collision>
      <origin xyz="0 0 -1.0" />
      <geometry>
        <cylinder length="0.5" radius="0.25" />
      </geometry>
    </collision>
  </link>

  <gazebo>
    <plugin name="object_controller" filename="libgazebo_ros_planar_move.so">
      <commandTopic>cmd_vel</commandTopic>
      <odometryTopic>odom</odometryTopic>
      <odometryFrame>odom</odometryFrame>
      <odometryRate>20.0</odometryRate>
      <robotBaseFrame>base_footprint</robotBaseFrame>
    </plugin>
  </gazebo>

</robot>