第4章 · Gazebo仿真器从入门到上手

Gazebo 这东西,说白了就是 SLAM 工程师的「虚拟试车场」。你想想看,真机跑一次 SLAM 成本多高?撞坏了雷达、电机烧了,都是真金白银。我刚开始做 SLAM 那会儿,有一次在实验室用差速小车跑图,结果轮子卡在地缝里,里程计直接飞了…… 后来我学乖了,先在 Gazebo 里把算法调稳了再上真车。这一章,我就带你彻底搞懂 Gazebo 世界文件、模型文件,还有传感器插件怎么配。

Gazebo 仿真核心 🌍 世界文件 .world 光照 · 物理引擎 · 地面 模型引用 · 场景参数 🤖 模型 .sdf / .urdf link · joint · 碰撞 · 惯性 可视化网格 · 传动 📡 传感器插件 IMU · 激光雷达 · 相机 噪声模型 · 更新率 仿真联调 → 完整 SLAM 系统

4.1 世界文件 .world —— 仿真舞台的剧本

每个 Gazebo 仿真场景都从一个 .world 文件开始。它定义了「世界」长什么样:重力、光照、地面纹理、物理参数,还有你要加载哪些模型。我个人习惯把 .world 看作舞台的灯光师和场务——它不演戏,但没它不行。

一个典型 world 文件的结构骨架:

<?xml version="1.0" ?>
<sdf version="1.6">
  <world name="my_slam_world">
    <physics type="ode">
      <real_time_update_rate>1000</real_time_update_rate>
      <max_step_size>0.001</max_step_size>
    </physics>
    <scene>
      <ambient>0.4 0.4 0.4 1</ambient>
      <sky>0.7 0.8 0.9</sky>
    </scene>
    <include>
      <uri>model://ground_plane</uri>
    </include>
    <include>
      <uri>model://my_robot</uri>
      <pose>0 0 0.2 0 0 0</pose>
    </include>
  </world>
</sdf>

这里我特别想提一下 <physics> 标签。做 SLAM 仿真时,max_step_size 我一般设 0.001~0.002,太大容易导致碰撞穿透,太小又跑不动。嗯,这个值你可以在后期调,但一开始别超过 0.005。

4.2 模型文件解析 —— .sdf 与 .urdf 到底用哪个?

很多新手会纠结:到底用 SDF 还是 URDF?我直接说结论:URDF 是 ROS 原生格式,适合描述机器人运动学;SDF 是 Gazebo 的亲儿子,支持更多物理特性。 我在项目中通常用 URDF 描述机器人本体,然后通过 gazebo_ros_control 插件转成 SDF 加载。但如果你只做纯 Gazebo 仿真,直接用 SDF 更省事。

我的个人经验: 如果你要加传感器插件(比如 IMU、激光雷达),SDF 的标签更直观。URDF 里也能加 <gazebo> 扩展标签,但写起来啰嗦。下面给一个 SDF 模型的核心片段:

<model name="diff_drive_robot">
  <link name="base_link">
    <inertial>
      <mass>2.0</mass>
      <inertia>
        <ixx>0.02</ixx><iyy>0.02</iyy><izz>0.03</izz>
      </inertia>
    </inertial>
    <collision name="base_collision">
      <geometry><box><size>0.4 0.3 0.2</size></box></geometry>
    </collision>
    <visual name="base_visual">
      <geometry><box><size>0.4 0.3 0.2</size></box></geometry>
      <material><ambient>0.8 0.2 0.2 1</ambient></material>
    </visual>
  </link>
  <joint name="left_wheel_joint" type="revolute">
    <parent>base_link</parent>
    <child>left_wheel</child>
    <axis><xyz>0 1 0</xyz></axis>
  </joint>
</model>

注意 <inertia> 的值——我曾经偷懒随便填,结果仿真里机器人原地打转,查了半天才发现惯性矩给小了。你想想看,物理引擎是根据惯性算运动的,填错了整个动力学都崩。

4.3 传感器插件配置 —— 给机器人装上「感官」

Gazebo 的传感器通过插件实现。说白了,插件就是一段 C++ 代码,编译成 .so 库,然后在模型文件里声明一下就能用。我最常用的三个传感器:IMU、激光雷达、相机。下面逐个说。

4.3.1 IMU 插件

IMU 提供角速度和线加速度。Gazebo 自带的 libgazebo_ros_imu_sensor.so 很好用。配置时注意设置噪声参数,否则仿真数据太干净,算法在真机上会炸。

<plugin name="imu_plugin" filename="libgazebo_ros_imu_sensor.so">
  <ros>
    <namespace>/robot</namespace>
    <argument>imu/data</argument>
  </ros>
  <update_rate>200</update_rate>
  <noise>
    <type>gaussian</type>
    <mean>0.0</mean>
    <stddev>0.001</stddev>
  </noise>
</plugin>

⚠️ 我曾经踩过的坑: 忘记给 IMU 加 <frame_name> 标签,结果发布的坐标系是空的,导致 EKF 融合直接崩溃。记得加上 <frame_name>imu_link</frame_name>。

4.3.2 激光雷达 (Lidar) 插件

激光雷达是 SLAM 的主力传感器。Gazebo 的 libgazebo_ros_ray_sensor.so 可以模拟单线或多线雷达。我一般设置 360° 扫描,720 个采样点,更新率 10Hz。

<plugin name="lidar_plugin" filename="libgazebo_ros_ray_sensor.so">
  <ros>
    <namespace>/robot</namespace>
    <argument>scan</argument>
  </ros>
  <update_rate>10</update_rate>
  <ray>
    <scan>
      <horizontal>
        <samples>720</samples>
        <resolution>1</resolution>
        <min_angle>-3.14159</min_angle>
        <max_angle>3.14159</max_angle>
      </horizontal>
    </scan>
    <range>
      <min>0.1</min>
      <max>30.0</max>
    </range>
    <noise>
      <type>gaussian</type>
      <mean>0.0</mean>
      <stddev>0.01</stddev>
    </noise>
  </ray>
</plugin>

这里 <resolution> 我习惯设 1,表示每个采样点只发一条射线。如果你想要更真实的模拟,可以设成 2 或 3,但计算量会翻倍。

4.3.3 相机插件

视觉 SLAM 离不开相机。Gazebo 的相机插件基于 libgazebo_ros_camera.so。配置分辨率、帧率、畸变参数即可。

<plugin name="camera_plugin" filename="libgazebo_ros_camera.so">
  <ros>
    <namespace>/robot</namespace>
    <argument>camera/image_raw</argument>
  </ros>
  <update_rate>30</update_rate>
  <camera>
    <horizontal_fov>1.047</horizontal_fov>
    <image>
      <width>640</width>
      <height>480</height>
      <format>R8G8B8</format>
    </image>
    <clip>
      <near>0.1</near>
      <far>100</far>
    </clip>
  </camera>
</plugin>

对了,如果你做 VIO 或 ORB-SLAM,记得把 <distortion> 加上,否则仿真图像没有畸变,算法迁移到真机时精度会掉一截。

4.4 传感器插件对比速查

传感器插件库关键参数常见坑点
IMUlibgazebo_ros_imu_sensor.soupdate_rate, noise缺少 frame_name
激光雷达libgazebo_ros_ray_sensor.sosamples, range, noise分辨率过高导致卡顿
相机libgazebo_ros_camera.sowidth, height, fov未设置畸变参数

小结一下: 世界文件搭舞台,模型文件定角色,传感器插件给角色装上感官。这三样东西配齐了,你的仿真 SLAM 系统就能跑起来了。