2. 仿真环境搭建:Gazebo与PyBullet对比、安装配置、URDF模型导入

做四足机器人,仿真这一步绕不开。说白了,你不可能每次改个参数就直接往实物上烧程序——摔几次电机就废了。我个人习惯是先跑通仿真,再往实物迁移。这一章我们就聊聊两个主流的仿真器:Gazebo 和 PyBullet。

2.1 Gazebo vs PyBullet:怎么选?

先给结论:两个都能用,但场景不同。Gazebo 更接近真实物理,PyBullet 更轻量、更适合算法快速迭代。我刚开始做四足的时候,两个都试过,踩了不少坑。

对比维度 Gazebo PyBullet
物理引擎 ODE / Bullet / DART / Simbody Bullet(自带)
渲染能力 OGRE 3D,支持传感器仿真 OpenGL 基础渲染
ROS 集成 原生支持,ros_control 无缝对接 需手动桥接
安装复杂度 较高,依赖多 pip install 即可
仿真速度 较慢,尤其多机器人场景 快,适合强化学习训练
适用阶段 实物部署前的整机验证 算法原型、RL 训练

我的建议:如果你做足式机器人运动控制算法,先用 PyBullet 快速迭代;等算法稳定了,再搬到 Gazebo 做整机联合仿真。我在项目里就是这么干的——PyBullet 跑 1000 次训练,Gazebo 只做最后 10 次验证。

2.2 Gazebo 安装与配置

Gazebo 的安装,嗯,这里要注意版本匹配。ROS 1 配 Gazebo 9/11,ROS 2 配 Gazebo 11+。我见过太多人装错版本,折腾一整天。

2.2.1 安装步骤(Ubuntu 20.04 + ROS Noetic)

# 1. 安装 ROS Noetic(略,假设已装好)
# 2. 安装 Gazebo 11
sudo apt-get install gazebo11
sudo apt-get install libgazebo11-dev

# 3. 安装 ROS-Gazebo 桥接包
sudo apt-get install ros-noetic-gazebo-ros-pkgs
sudo apt-get install ros-noetic-gazebo-ros-control

# 4. 验证安装
gazebo --version
# 输出应包含 Gazebo multi-robot simulator, version 11.x

我曾经踩过的坑:装完 Gazebo 后直接 roslaunch,结果黑屏。后来发现是显卡驱动问题。如果你用虚拟机,记得开启 3D 加速;如果是双显卡笔记本,用 prime-select 切到独显。

2.2.2 启动测试

# 启动空世界
gazebo --verbose worlds/empty.world

# 或者通过 ROS launch
roslaunch gazebo_ros empty_world.launch

启动后你应该看到一个灰色网格地面。这时候可以手动插入模型测试。我个人习惯先放一个方盒子,看看物理效果是否正常。

2.3 PyBullet 安装与配置

PyBullet 就简单多了。你想想看,一个 pip 命令搞定,多省心。

# 安装
pip install pybullet

# 验证
python -c "import pybullet as p; print(p.__version__)"

装完就能跑。我经常在笔记本上开个 PyBullet 调算法,连 GPU 都不需要。

2.3.1 快速启动一个四足机器人仿真

import pybullet as p
import pybullet_data
import time

# 连接物理引擎
p.connect(p.GUI)
p.setAdditionalSearchPath(pybullet_data.getDataPath())

# 加载地面和机器人
p.loadURDF("plane.urdf")
robot = p.loadURDF("quadruped/quadruped.urdf", [0, 0, 0.5])

# 设置重力
p.setGravity(0, 0, -9.81)

# 仿真循环
for i in range(10000):
    p.stepSimulation()
    time.sleep(1/240.)

小技巧:PyBullet 默认的 time.sleep 是实时仿真。如果你做强化学习训练,用 p.setRealTimeSimulation(0) 关闭实时模式,然后自己控制步进频率,速度能快几十倍。

2.4 URDF 模型导入——核心环节

不管用哪个仿真器,URDF 都是绕不开的。URDF 就是机器人的「身份证」,描述了关节、连杆、惯量、碰撞模型等信息。

2.4.1 URDF 基本结构

<robot name="my_quadruped">
  <link name="base_link">
    <visual>
      <geometry>
        <box size="0.3 0.2 0.05"/>
      </geometry>
      <origin xyz="0 0 0" rpy="0 0 0"/>
    </visual>
    <collision>
      <geometry>
        <box size="0.3 0.2 0.05"/>
      </geometry>
    </collision>
    <inertial>
      <mass value="2.0"/>
      <inertia ixx="0.01" ixy="0" ixz="0"
               iyy="0.01" iyz="0"
               izz="0.02"/>
    </inertial>
  </link>

  <joint name="hip_joint" type="revolute">
    <parent link="base_link"/>
    <child link="hip_link"/>
    <origin xyz="0.15 0.1 0" rpy="0 0 0"/>
    <axis xyz="0 0 1"/>
    <limit effort="10" velocity="5" lower="-1.57" upper="1.57"/>
  </joint>
</robot>

关键点:URDF 里 <collision> 和 <visual> 可以不同。仿真器用碰撞模型做物理计算,用视觉模型做显示。我一般把碰撞模型简化成圆柱或长方体,能大幅提升仿真速度。

2.4.2 在 Gazebo 中导入 URDF

<!-- 在 URDF 中增加 Gazebo 标签 -->
<gazebo>
  <plugin name="gazebo_ros_control" filename="libgazebo_ros_control.so">
    <robotNamespace>/quadruped</robotNamespace>
  </plugin>
</gazebo>

<gazebo reference="base_link">
  <material>Gazebo/Blue</material>
</gazebo>

然后在 launch 文件中加载:

<launch>
  <!-- 启动 Gazebo 世界 -->
  <include file="$(find gazebo_ros)/launch/empty_world.launch"/>

  <!-- 加载机器人模型 -->
  <param name="robot_description"
         textfile="$(find my_quadruped)/urdf/quadruped.urdf"/>

  <node name="spawn_urdf"
        pkg="gazebo_ros"
        type="spawn_model"
        args="-param robot_description
              -urdf
              -model quadruped
              -x 0 -y 0 -z 0.5"/>
</launch>

2.4.3 在 PyBullet 中导入 URDF

PyBullet 更直接,一行代码搞定:

robot_id = p.loadURDF("quadruped.urdf",
                      basePosition=[0, 0, 0.5],
                      useFixedBase=False,
                      flags=p.URDF_USE_SELF_COLLISION)

注意:PyBullet 默认不开启自碰撞检测。如果你的四足机器人腿会互相穿透,记得加上 flags=p.URDF_USE_SELF_COLLISION。我曾经因为这个原因,仿真里机器人走路姿势看着正常,但实际物理上腿已经交叉了——浪费了两周训练时间。

2.5 知识体系总览

下面这张图概括了本章的核心逻辑:

仿真环境搭建知识体系 仿真环境搭建核心流程 选择仿真器 Gazebo PyBullet 安装 + 启动测试 pip install + 快速验证 URDF 模型导入 link / joint / inertial / collision 仿真运行 → 算法验证 → 实物部署 💡 我的工作流 PyBullet 快速迭代 → Gazebo 整机验证

2.6 常见问题与避坑

  • Gazebo 启动后黑屏:检查显卡驱动,或者用 export SVGA_VGPU10=0 临时解决。
  • URDF 加载后机器人塌陷:惯性参数设置不合理。检查 <inertial> 里的质量是否为正数,惯量矩阵是否正定。
  • PyBullet 仿真速度慢:关闭实时模式,减少 time.sleep 调用,或者用 p.setPhysicsEngineParameter(numSubSteps=4) 调整子步数。
  • 关节限位不生效:URDF 里 <limit> 标签的 lower 和 upper 必须写对。我遇到过单位搞错——弧度写成了角度,结果机器人腿直接反关节。

最后一个小建议:不管用哪个仿真器,先把 URDF 在 rviz 里可视化一遍。如果 rviz 里显示正常,再往仿真器里导。这样能快速定位是模型问题还是仿真器配置问题。