4. 搭建你的第一个仿真世界:创建地面、添加墙壁、放置障碍物、保存世界文件

好,咱们现在开始动手了。

前面几章我们把 Gazebo 的界面、模型库、插件这些概念捋了一遍。说实话,光看不练容易忘。我自己的习惯是,学一个新工具,第一件事就是搭一个能跑起来的场景。哪怕只是一个地面加几堵墙,也比看十遍文档强。

这一章,我们就来亲手搭建第一个仿真世界。目标很明确:创建地面、添加墙壁、放置障碍物,最后把这个世界保存成文件。你想想看,以后每次启动 Gazebo 都能直接加载你设计的场景,是不是挺有成就感的?

4.1 创建地面:仿真世界的基石

地面是仿真世界的基础。没有地面,机器人一启动就会「掉入虚空」。嗯,这里要注意,Gazebo 默认启动时其实自带一个地面,但我们自己搭建世界时,通常要显式地添加它,方便后续调整纹理、尺寸等属性。

操作步骤:

  1. 启动 Gazebo(空世界模式):gazebo --verbose worlds/empty.world
  2. 点击左侧面板的「Insert」选项卡。
  3. 在模型列表中,找到 Ground Plane,拖拽到仿真视口中。
  4. 或者,你也可以通过菜单栏:Edit → Insert Model → Ground Plane。
💡 我的小技巧: 我个人习惯用 Building Editor 来创建地面,但初学者直接用拖拽的方式更直观。拖进去之后,地面会自动吸附到 y=0 平面,不用手动调整位置。

如果你想让地面看起来更真实一点,可以右键地面,选择 Edit Model,然后在 Visual 标签页里修改材质(Material)。比如改成草地纹理或者水泥纹理。我在项目中遇到过,仿真环境的地面纹理太滑,导致轮式机器人打滑,后来换成粗糙纹理才解决。

4.2 添加墙壁:给你的世界画个边界

地面有了,接下来要加墙壁。墙壁的作用不只是好看——它能让机器人知道「边界在哪里」。我曾经见过一个新手,没加墙壁,机器人直接跑出视野,然后撞到 Gazebo 的「世界边界」上,物理引擎直接报错。

添加墙壁的方法有两种:

方法 说明 适用场景
拖拽模型 从模型库拖拽 Wall 或 Box 模型 快速搭建原型
手动创建 SDF 编写 .sdf 文件定义墙壁尺寸和位置 精确控制、批量生成

我们先讲第一种,拖拽方式:

  1. 在「Insert」面板中,找到 Wall 模型(如果没有,可以用 Box 代替)。
  2. 拖拽到场景中,调整位置和朝向。
  3. 右键墙壁 → Edit Model,可以修改长宽高。

第二种方式,用 SDF 文件。我个人更推荐这种方式,因为可重复性高。比如你要搭一个 10m×10m 的方形围墙,手动拖拽四个墙壁太慢了,而且对齐很麻烦。用代码写,几行就搞定。

<?xml version="1.0" ?>
<sdf version="1.6">
  <model name="wall_north">
    <static>true</static>
    <link name="link">
      <collision name="collision">
        <geometry>
          <box>
            <size>10.0 0.2 1.0</size>
          </box>
        </geometry>
      </collision>
      <visual name="visual">
        <geometry>
          <box>
            <size>10.0 0.2 1.0</size>
          </box>
        </geometry>
        <material>
          <ambient>0.8 0.8 0.8 1.0</ambient>
        </material>
      </visual>
    </link>
    <pose>0.0 5.0 0.5 0 0 0</pose>
  </model>
</sdf>
⚠️ 关键点: 墙壁一定要设置 <static>true</static>。否则机器人一撞,墙壁就飞了。我刚开始做仿真时忘了加这个,结果机器人轻轻碰了一下墙壁,墙壁直接弹到天上去了……嗯,那画面挺滑稽的。

4.3 放置障碍物:让世界有点挑战

光有墙壁还不够,我们得放点障碍物。障碍物可以是箱子、圆柱、球体,甚至是一些复杂的形状。说白了,就是给机器人制造一些「麻烦」,测试它的避障能力。

常用障碍物类型:

  • 箱子(Box):最常用,适合模拟货架、石块等。
  • 圆柱(Cylinder):模拟柱子、树干。
  • 球体(Sphere):模拟石头、路障。
  • 自定义模型:用 .stl 或 .dae 文件导入复杂形状。

放置障碍物的操作和墙壁类似。我建议你试试拖拽一个 Box 到场景中,然后右键编辑它的尺寸和颜色。比如,把箱子涂成红色,方便视觉识别。

<!-- 一个红色箱子的 SDF 示例 -->
<model name="red_box">
  <static>false</static>
  <link name="link">
    <collision name="collision">
      <geometry>
        <box>
          <size>0.5 0.5 0.5</size>
        </box>
      </geometry>
    </collision>
    <visual name="visual">
      <geometry>
        <box>
          <size>0.5 0.5 0.5</size>
        </box>
      </geometry>
      <material>
        <ambient>1.0 0.0 0.0 1.0</ambient>
      </material>
    </visual>
    <pose>2.0 0.0 0.25 0 0 0</pose>
  </link>
</model>
🚨 避坑指南: 我曾经把障碍物的 <static> 设成 false,结果机器人一碰,箱子就滚走了。如果你希望障碍物固定不动,记得设成 true。但如果你想要可推动的障碍物(比如测试机器人推力),就设成 false。

4.4 保存世界文件:把你的劳动成果存下来

场景搭好了,不保存等于白干。Gazebo 的世界文件是 .world 格式,本质上是一个 SDF 文件,里面包含了所有模型、灯光、物理参数等信息。

保存方法:

  1. 在 Gazebo 菜单栏中,点击 File → Save World As...。
  2. 选择保存路径,输入文件名,比如 my_first_world.world。
  3. 点击保存。

保存后,你可以用文本编辑器打开这个文件看看。里面记录了所有你添加的模型、它们的位置、颜色、物理属性等。以后启动 Gazebo 时,直接加载这个文件:

gazebo --verbose my_first_world.world
💡 我的习惯: 我会把世界文件放在 ROS 工作区的 worlds/ 目录下,方便管理。比如 ~/catkin_ws/src/my_robot/worlds/。这样在 launch 文件中引用也很方便。

另外,保存时要注意:如果你在场景中修改了模型(比如调整了尺寸),Gazebo 会把这些修改记录到世界文件中。但如果你修改的是模型库里的原始模型,那不会影响世界文件。嗯,这里要区分清楚。

4.5 本章知识体系

为了让你更直观地理解这一章的内容结构,我画了一张流程图。它展示了从零开始搭建一个仿真世界的完整路径。

搭建仿真世界核心流程 创建地面 添加墙壁 放置障碍物 保存世界文件 拖拽模型 / SDF文件 拖拽模型 / SDF文件 箱子/圆柱/球体/自定义 File → Save World As... 💡 核心原则:先搭骨架(地面+墙壁),再填充内容(障碍物) 最后保存为 .world 文件,方便重复加载

你看,整个流程其实很线性。从地面开始,到墙壁,到障碍物,最后保存。每一步都有两种实现方式:拖拽(适合快速验证)和 SDF 文件(适合精确控制)。我个人建议你两种都试试,先拖拽感受一下,再用 SDF 文件写一遍,这样理解更深。

好了,这一章的内容就到这里。你搭建的第一个仿真世界已经可以跑起来了。接下来,你可以试着往里面加更多模型,或者调整物理参数,看看效果有什么不同。

可可精品资料库