声明:以下内容参考了其他博主的文章,在自行理解的基础上加以修改并整合,以便大家学习,若有不便之处望告知,侵权则删除。

gazebo是一款免费的机器人仿真软件,其提供高保真度的物理模拟,一整套传感器模型,以及对用户和程序非常友好的交互方式。能够在复杂的室内和室外环境中准确高效地模拟机器人工作的功能,通常与ROS联合使用,为开发者提供了优异的仿真环境。

gazebo支持urdf/sdf格式文件,后文会提及两者的区别,它们均用于描述仿真环境,官方也提供了一些集成好的常用的模型模块,可以直接导入使用。

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

一、向gazebo导入模型库

打开gazebo的时候,默认是没有模型的,需要手动下载配置。

1、下载模型文件

github链接:

https://link.zhihu.com/?target=https%3A//github.com/osrf/gazebo_models

该库包含许多常用模型,将其下载为压缩包格式。

2、创建models文件夹

$ cd ~/.gazebo/
$ mkdir -p models

./gazebo文件夹默认被隐藏,需要按下“Ctrl+H”才能看到被隐藏的文件。

3、拷贝模型文件

最后,将下载好的压缩包拷贝至新建的models文件夹下并解压。再次打开gazebo便可以加载我们下载好的models了。

4、测试

打开gazebo,在“insert”面板中选择模型导入,查看效果。

$ gazebo

二、gazebo GUI简介

这节将对gazebo图形用户界面进行介绍。我们将学习到一些基本操作,例如按钮的功能以及如何在场景中导航。

启动gazebo后,你将看到这个界面:

gazebo交互界面由许多组成部分,接下来将逐一介绍。

1、场景(Scene)

场景是模拟器的主要部分,是仿真模型显示的地方,你可以在这操作仿真对象,使其与环境进行交互。

2、面板(Panels)

面板分为左右两侧,可以把两侧的面板设置为显示、隐藏或调整它的大小。

(1)左侧面板

启动gazebo时,默认情况下会显示左侧面板。面板中有三个选项卡:

  • WORLD: 该选项卡显示当前场景中的模型,并允许您查看和修改模型参数,例如它们的姿势。您也可以通过展开“GUI”选项并调整相机姿势来更改相机视角。
  • INSERT: 该选项卡是向仿真场景中添加新对象(模型)。要查看模型列表,需要单击箭头展开文件夹。单击(并释放)要插入的模型,然后在场景中再次单击以添加它。
  • LAYERS: 该选项卡组织并显示仿真中可用的不同可视化组(如果有)。一个图层可以包含一个或多个模型。打开或关闭图层将显示或隐藏该图层中的模型。这是一个可选功能,因此在大多数情况下,此选项卡将为空。

(2)右侧面板

默认情况下,右侧面板处于隐藏状态。单击并拖动该栏以将其打开。右面板可用于与选定模型的移动部件(关节)交互。如果场景中没有选择模型,面板将不显示任何信息。

3、工具栏(Toolbars)

gazebo界面有两个工具栏。一个位于场景上方,另一个位于下方。

(1)顶部工具栏

顶部工具栏为主工具栏,包含一些与模拟器交互时最常用的选项,如按钮:选择、移动、旋转和缩放;创建简单形状(例如立方体、球体、圆柱体)以及复制/粘贴。

  • 选择模型(Select mode):在场景中做标注;
  • 转换模式(Translate mode):选择要移动的模型;
  • 旋转模式(Rotate mode):选择要旋转的模型;
  • 缩放模式(Scale mode):选择要缩放的模型;
  • 撤消/重做(Undo/Redo):撤消/重做场景中的操作;
  • 灯光(Lights):将灯光添加到场景;
  • 复制/粘贴(Copy/Paste):复制/粘贴场景中的模型;
  • 对齐(Align):将模型彼此对齐;
  • 捕捉(Snap):将一个模型捕捉到另一个模型;
  • 更改视图(Change view):从不同角度查看场景。

(2)底部工具栏

底部工具栏显示有关仿真的数据,如仿真时间(Simulation time)及其与真实时间(Real time)的关系。

“仿真时间”是指当仿真运行时,时间在仿真环境中过得有多快。仿真可以比真实时间慢或快,具体取决于运行仿真所需的计算量。

“真实时间”是指在仿真环境中运行时实际经过的时间。仿真时间和真实时间的比率称为实时因子。

世界状态每迭代一次就更新一次。您可以在底部工具栏的右侧看到迭代次数。每次迭代都会将仿真推进一个固定的秒数,称为步长。默认情况下,步长为1ms。您可以按“暂停”按钮暂停仿真,并使用“步长”按键一次执行多个步长。

(3)菜单栏

像大多数应用程序一样,gazebo顶部有一个应用程序菜单。某些菜单选项会显示工具栏中。在场景中,右键单击上下文菜单选项,可查看各种菜单。注意:有些Linux桌面会隐藏应用程序菜单。如果看不到菜单,请将光标移到应用程序窗口的顶部,菜单就会出现。

4、鼠标(Mouse Controls)

鼠标在场景中导航时非常有用。强烈建议使用带滚轮的鼠标。下面是在场景中导航和更改视角的基本鼠标操作。右键单击模型将打开一个包含各种选项的上下文菜单。

三、urdf与sdf

1、urdf是什么?

统一机器人描述格式urdf)是ROS用于描述机器人的所有元素的XML文件格式。要在gazebo中使用urdf文件,必须添加一些特定用于仿真的标签才能与gazebo一起正常使用。

尽管urdf在ROS中是一种有用且标准化的格式,但它们缺少许多功能,并且尚未进行更新以应对机器人技术的不断发展的需求。urdf只能单独指定单个机器人的运动学和动力学特性,无法指定世界中机器人本身的姿势。它也不是通用的描述格式,因为它不能指定关节环(平行连接),并且缺乏摩擦和其他特性。此外,它不能指定非机器人,例如灯光,高度图等。

在实现方面,urdf语法大量使用XML属性破坏了正确的格式设置,这反过来又使urdf更加不灵活。

2、sdf是什么?

为了解决此问题,创建了一种称为仿真描述格式(sdf)的新格式 ,供gazebo使用,以解决urdf的缺点。sdf是从世界级到机器人级的所有内容的完整描述,能够描述机器人、静态和动态物体、照明、地形甚至物理学的各方面的信息。sdf可以精确描述机器人的各类性质,除了传统的运动学特性之外,还可以为机器人定义传感器、表面属性、纹理、关节摩擦等;sdf还提供了定义各种环境的方法。包括环境光照、地形等。

sdf也使用XML格式进行描述。

总结而言,sdf是urdf的进化版,能够更好的描述真实的模拟条件。

3、使用哪种格式?

尽管目前有一些sdf与urdf的之间的转换方法(见下文),但往往十分复杂且易出错。因此,建议刚开始就根据自己的需求选择最合适的模型格式。

  • 必须使用urdf的情况:要使用rviz进行可视化操作。
  • 必须使用sdf的情况:研究并联机器人,或机器人中存在封闭链结构。
  • 建议使用urdf的情况:要尽快做出仿真用以演示效果;使用Solidworks建模,想方便地导出ROS三维模型。
  • 建议使用sdf的情况:想深入研究ROS-gazebo仿真,使仿真的动力学特性更加真实;想开发自己专用的Gazebo仿真插件。

4、urdf和sdf格式转换(引用自小明工坊,侵权删)

在一些特殊情况中,只能使用urdf或sdf格式的模型。这时候,如果我们已有的模型格式不符要求,就需要转换。但值得注意的是,由于urdf和sdf的元素并不完全对应,因此下面列出的转换过程或多或少存在一些问题。对于刚开始搭建模型的小伙伴们,还是建议直接选用合适的格式,用xacro或rsdf参数化和模块化方法建模,而非使用转换功能。

(1)urdf转sdf

由于sdf是gazebo的原生格式,因此urdf转sdf是比较简单的。采用的方法一般是:使用常规方法将*.urdf加载到gazebo中后,再将其另存为一个单独的*.world文件。此时sdf格式的模型就完整地保存在*.world文件的<model>元素下了。

另外,gazebo官方还提供了另一种命令行方法,也可将实现urdf转sdf。在urdf所在目录下打开终端,执行如下命令:

$ gz sdf -p my_model.urdf > my_model.sdf

(2)sdf转urdf

虽然官方没有给出将sdf转为urdf的方法,但好在有大佬自己开发了可行的工具——pysdf功能包,github链接:

https://link.zhihu.com/?target=https%3A//github.com/andreasBihlmaier/pysdf

该包的版本过老,在ubuntu18.04和ros melodic上直接运行报错,对其做了一些细微的修改后可用:

https://link.zhihu.com/?target=https%3A//github.com/chenjm1109/pysdf

该功能包使用起来也很简单,分为4个步骤:

  • 在github中下载pysdf功能包,放到ROS工作空间(以catkin_ws为例)下的src目录下;
  • 编译工作空间
  • $ cd ~/catkin_ws/
    $ catkin_make
  • 从待转换的sdf模型文件所在的目录打开终端,执行如下命令
$ rosrun pysdf sdf2urdf.py my_model.sdf result_model.urdf

注意事项:

  • sdf2urdf.py是python可执行文件,如果报错[rosrun] Couldn't find executable named sdf2urdf below...,就需要先通过chmod +x *指令为其赋予可执行权限,这是使用所有ROS-python可执行文件时都要注意的事情。
  • sdf文件中不要有插件,也不要有ball关节等urdf无法识别的关节类型。
  • 转换完成后可使用check_urdf工具检查urdf的合法性,命令如下:
$ sudo apt-get install liburdfdom-tools
$ check_urdf result_model.rudf

四、自定义模型并导入gazebo

本小节将使用sdf文件格式创建了一个两轮移动机器人,该机器人使用差动驱动机构进行运动。

1、配置模型目录

自己创建的模型必须遵循gazebo模型数据库目录结构的格式设置规则。有关模型描述格式的详细信息,请参考SDF格式指南

  • 创建一个模型目录
$ mkdir -p ~/.gazebo/models/my_robot
  • 创建一个模型配置文件
$ gedit ~/.gazebo/models/my_robot/model.config
  • 粘贴以下内容
  • <?xml version="1.0"?>
    <model>
      <name>My Robot</name>
      <version>1.0</version>
      <sdf version='1.4'>model.sdf</sdf>
    
      <author>
       <name>My Name</name>
       <email>me@my.email</email>
      </author>
    
      <description>
        My awesome robot.
      </description>
    </model>
    • 创建sdf文件
    $ gedit ~/.gazebo/models/my_robot/model.sdf
    • 粘贴以下内容
  • <?xml version='1.0'?>
    <sdf version='1.4'>
      <model name="my_robot">
      </model>
    </sdf>
  • 至此,我们已经有了模型的基本内容。model.config文件描述了机器人的元数据,model.sdf文件包含必要的标记,以使用链接到SDF 1.4版的名为my_robot的模型。

    2、建立模型的结构

    此步骤将创建一个带有两个轮子的矩形底座。

    从简单开始并逐步建立模型非常重要。 第一步是布置模型的基本形状。 为此,我们将模型设为静态,这意味着将忽略它的物理引擎。 结果,模型将停留在一个位置,并允许我们正确对齐所有组件。

    • 在sdf文件中添加<static>元素使模型静态
  • <?xml version='1.0'?>
    <sdf version='1.4'>
      <model name="my_robot">
      <static>true</static>
      </model>
    </sdf>
  • 添加矩形底座
<?xml version='1.0'?>
<sdf version='1.4'>
  <model name="my_robot">
  <static>true</static>
    <link name='chassis'>
      <pose>0 0 .1 0 0 0</pose>

      <collision name='collision'>
        <geometry>
          <box>
            <size>.4 .2 .1</size>
          </box>
        </geometry>
      </collision>

      <visual name='visual'>
        <geometry>
          <box>
            <size>.4 .2 .1</size>
          </box>
        </geometry>
      </visual>
    </link>
  </model>
</sdf>

在这里,我们创建了一个尺寸为0.4 x 0.2 x 0.1m的<box>。<collision>元素指定碰撞检测引擎使用的形状。<visual>元素指定渲染引擎使用的形状。在大多数情况下,<collision>和<visual>元素是相同的。 对于不同的碰撞和视觉元素,最常见的用途是使简化的碰撞元素与使用复杂网格物体的视觉元素配对。 这将有助于提高性能。

  • 导入模型

运行gazebo并通过GUI上的“Insert”面板导入模型来查看模型,可以看到一个白盒子漂浮在离地面0.1米的地方。

  • 向机器人添加脚轮

脚轮是无摩擦的球体。 这种脚轮比添加带万向节的轮子更好,因为它对物理引擎的约束更少。

<?xml version='1.0'?>
<sdf version='1.4'>
  <model name="my_robot">
  <static>true</static>
    <link name='chassis'>
      <pose>0 0 .1 0 0 0</pose>

      <collision name='collision'>
        <geometry>
          <box>
            <size>.4 .2 .1</size>
          </box>
        </geometry>
      </collision>

      <visual name='visual'>
        <geometry>
          <box>
            <size>.4 .2 .1</size>
          </box>
        </geometry>
      </visual>

      <collision name='caster_collision'>
        <pose>-0.15 0 -0.05 0 0 0</pose>
        <geometry>
            <sphere>
            <radius>.05</radius>
          </sphere>
        </geometry>

        <surface>
          <friction>
            <ode>
              <mu>0</mu>
              <mu2>0</mu2>
              <slip1>1.0</slip1>
              <slip2>1.0</slip2>
            </ode>
          </friction>
        </surface>
      </collision>

      <visual name='caster_visual'>
        <pose>-0.15 0 -0.05 0 0 0</pose>
        <geometry>
          <sphere>
            <radius>.05</radius>
          </sphere>
        </geometry>
      </visual>

    </link>
  </model>
</sdf>

试用您的模型,以确保脚轮出现在机器人的末端。 在gazebo中生成它以查看(无需重新启动gazebo,删除原有模型再插入,它都会重新加载修改后的模型):

  • 添加左轮和右轮
  • <?xml version='1.0'?>
    <sdf version='1.4'>
      <model name="my_robot">
      <static>true</static>
        <link name='chassis'>
          <pose>0 0 .1 0 0 0</pose>
    
          <collision name='collision'>
            <geometry>
              <box>
                <size>.4 .2 .1</size>
              </box>
            </geometry>
          </collision>
    
          <visual name='visual'>
            <geometry>
              <box>
                <size>.4 .2 .1</size>
              </box>
            </geometry>
          </visual>
    
          <collision name='caster_collision'>
            <pose>-0.15 0 -0.05 0 0 0</pose>
            <geometry>
                <sphere>
                <radius>.05</radius>
              </sphere>
            </geometry>
    
            <surface>
              <friction>
                <ode>
                  <mu>0</mu>
                  <mu2>0</mu2>
                  <slip1>1.0</slip1>
                  <slip2>1.0</slip2>
                </ode>
              </friction>
            </surface>
          </collision>
    
          <visual name='caster_visual'>
            <pose>-0.15 0 -0.05 0 0 0</pose>
            <geometry>
              <sphere>
                <radius>.05</radius>
              </sphere>
            </geometry>
          </visual>
        </link>
    
        <link name="left_wheel">
          <pose>0.1 0.13 0.1 0 1.5707 1.5707</pose>
    
          <collision name="collision">
            <geometry>
              <cylinder>
                <radius>.1</radius>
                <length>.05</length>
              </cylinder>
            </geometry>
          </collision>
    
          <visual name="visual">
            <geometry>
              <cylinder>
                <radius>.1</radius>
                <length>.05</length>
              </cylinder>
            </geometry>
          </visual>
        </link>
    
        <link name="right_wheel">
          <pose>0.1 -0.13 0.1 0 1.5707 1.5707</pose>
    
          <collision name="collision">
            <geometry>
              <cylinder>
                <radius>.1</radius>
                <length>.05</length>
              </cylinder>
            </geometry>
          </collision>
    
          <visual name="visual">
            <geometry>
              <cylinder>
                <radius>.1</radius>
                <length>.05</length>
              </cylinder>
            </geometry>
          </visual>
        </link>
    
      </model>
    </sdf>
  • 此时,机器人应具有一个矩形地盘带一个脚轮和两个车轮。
    • 使模型变为动态

    将<static>设置为false,并为左右车轮添加两个铰链关节。两个关节绕y轴(<xyz> 0 1 0 </ xyz>)旋转,并将每个车轮连接到底盘(<child>和<parent>标签)。

  • <?xml version='1.0'?>
    <sdf version='1.4'>
      <model name="my_robot">
      <static>false</static>
        <link name='chassis'>
          <pose>0 0 .1 0 0 0</pose>
    
          <collision name='collision'>
            <geometry>
              <box>
                <size>.4 .2 .1</size>
              </box>
            </geometry>
          </collision>
    
          <visual name='visual'>
            <geometry>
              <box>
                <size>.4 .2 .1</size>
              </box>
            </geometry>
          </visual>
    
          <collision name='caster_collision'>
            <pose>-0.15 0 -0.05 0 0 0</pose>
            <geometry>
                <sphere>
                <radius>.05</radius>
              </sphere>
            </geometry>
    
            <surface>
              <friction>
                <ode>
                  <mu>0</mu>
                  <mu2>0</mu2>
                  <slip1>1.0</slip1>
                  <slip2>1.0</slip2>
                </ode>
              </friction>
            </surface>
          </collision>
    
          <visual name='caster_visual'>
            <pose>-0.15 0 -0.05 0 0 0</pose>
            <geometry>
              <sphere>
                <radius>.05</radius>
              </sphere>
            </geometry>
          </visual>
        </link>
    
        <link name="left_wheel">
          <pose>0.1 0.13 0.1 0 1.5707 1.5707</pose>
    
          <collision name="collision">
            <geometry>
              <cylinder>
                <radius>.1</radius>
                <length>.05</length>
              </cylinder>
            </geometry>
          </collision>
    
          <visual name="visual">
            <geometry>
              <cylinder>
                <radius>.1</radius>
                <length>.05</length>
              </cylinder>
            </geometry>
          </visual>
        </link>
    
        <link name="right_wheel">
          <pose>0.1 -0.13 0.1 0 1.5707 1.5707</pose>
    
          <collision name="collision">
            <geometry>
              <cylinder>
                <radius>.1</radius>
                <length>.05</length>
              </cylinder>
            </geometry>
          </collision>
    
          <visual name="visual">
            <geometry>
              <cylinder>
                <radius>.1</radius>
                <length>.05</length>
              </cylinder>
            </geometry>
          </visual>
        </link>
    
        <joint type="revolute" name="left_wheel_hinge">
          <pose>0 0 -0.03 0 0 0</pose>
          <child>left_wheel</child>
          <parent>chassis</parent>
          <axis>
            <xyz>0 1 0</xyz>
          </axis>
        </joint>
    
        <joint type="revolute" name="right_wheel_hinge">
          <pose>0 0 0.03 0 0 0</pose>
          <child>right_wheel</child>
          <parent>chassis</parent>
          <axis>
            <xyz>0 1 0</xyz>
          </axis>
        </joint>
    
      </model>
    </sdf>
  • 启动gazebo,然后插入最新的模型。单击屏幕右侧的点并将其拖动到左侧(即隐藏的右侧面板)。此时会出现一个新窗口,其中包含每个关节的各种控制器(请确保已选择要控制的模型)。
  • 在“Force”选项卡下,将施加到每个关节的力增加到约0.1N。 机器人应四处移动,那么恭喜,您现在有了一个基本的移动机器人。