第二章 仿真环境搭建:ROS + Gazebo 环境安装、创建简单障碍物场景、配置机器人模型与传感器插件
好,咱们正式开始动手了。这一章要解决一个很实际的问题——怎么把仿真环境搭起来。说实话,我见过太多人算法写得飞起,结果一跑仿真就崩,最后发现是环境没配好。所以这一章,咱们稳扎稳打,把地基打牢。
2.1 ROS + Gazebo 环境安装
ROS 和 Gazebo 的关系,说白了就是「大脑」和「身体」。ROS 负责通信、决策,Gazebo 负责物理模拟、传感器数据生成。我个人习惯用 ROS Noetic + Gazebo 11 的组合,稳定,坑少。
推荐版本组合:
- Ubuntu 20.04 LTS
- ROS Noetic Ninjemys
- Gazebo 11(与 ROS Noetic 官方兼容)
安装其实就几条命令,但我建议你一步步来,别复制粘贴一整段。我在项目中遇到过有人因为源没换,装了一整天没装上的情况。
# 1. 设置 sources.list
sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list'
# 2. 设置密钥
sudo apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654
# 3. 更新并安装完整桌面版
sudo apt update
sudo apt install ros-noetic-desktop-full
# 4. 初始化 rosdep
sudo rosdep init
rosdep update
# 5. 设置环境变量
echo "source /opt/ros/noetic/setup.bash" >> ~/.bashrc
source ~/.bashrc
# 6. 安装 Gazebo 11(通常已包含在 desktop-full 中)
sudo apt install gazebo11 gazebo11-plugin-base
小技巧:安装完成后,先跑一下 roscore 和 gazebo 两个命令,看看能不能正常启动。如果 Gazebo 启动后一片漆黑,别慌,可能是显卡驱动问题,装个 nvidia-driver-470 一般能解决。
2.2 创建简单障碍物场景
环境搭好了,接下来咱们得有个「试验场」。你想想看,避障算法总得有东西可避吧?我一般不会一上来就用复杂地图,而是先搭一个简单的障碍物场景,方便调试。
Gazebo 里建场景有两种方式:一是用 GUI 手动拖拽,二是写 .world 文件。我个人更推荐后者,因为可复现、可版本控制。
下面是一个最简单的障碍物场景,包含地面、一面墙和几个柱子:
<?xml version="1.0" ?>
<sdf version="1.6">
<world name="simple_obstacle_world">
<include>
<uri>model://sun</uri>
</include>
<include>
<uri>model://ground_plane</uri>
</include>
<!-- 一面墙 -->
<model name="wall">
<pose>2.0 0.0 0.5 0 0 0</pose>
<link name="body">
<collision name="collision">
<geometry>
<box>
<size>0.2 3.0 1.0</size>
</box>
</geometry>
</collision>
<visual name="visual">
<geometry>
<box>
<size>0.2 3.0 1.0</size>
</box>
</geometry>
<material>
<ambient>0.8 0.2 0.2 1</ambient>
</material>
</visual>
</link>
</model>
<!-- 两个柱子 -->
<model name="pillar1">
<pose>1.0 1.5 0.5 0 0 0</pose>
<link name="body">
<collision name="collision">
<geometry>
<cylinder>
<radius>0.2</radius>
<length>1.0</length>
</cylinder>
</geometry>
</collision>
<visual name="visual">
<geometry>
<cylinder>
<radius>0.2</radius>
<length>1.0</length>
</cylinder>
</geometry>
</visual>
</link>
</model>
<model name="pillar2">
<pose>1.0 -1.5 0.5 0 0 0</pose>
<link name="body">
<collision name="collision">
<geometry>
<cylinder>
<radius>0.2</radius>
<length>1.0</length>
</cylinder>
</geometry>
</collision>
<visual name="visual">
<geometry>
<cylinder>
<radius>0.2</radius>
<length>1.0</length>
</cylinder>
</geometry>
</visual>
</link>
</model>
</world>
</sdf>
注意:我曾经在写 .world 文件时,把 <pose> 的坐标写反了,结果墙直接插到了地里。建议你每次修改后,先用 gazebo --verbose my_world.world 检查一下,看看有没有报错。
2.3 配置机器人模型(差速轮 / 全向轮)
场景有了,该让主角登场了。机器人模型用 URDF 或 SDF 描述。我习惯用 URDF,因为 ROS 生态对 URDF 支持更好。
先说说差速轮模型。差速轮说白了就是两个主动轮 + 一个万向轮,靠左右轮的速度差实现转向。下面是一个极简的差速轮 URDF:
<robot name="diff_drive_robot">
<link name="base_link">
<visual>
<geometry>
<box size="0.4 0.3 0.1"/>
</geometry>
</visual>
</link>
<!-- 左轮 -->
<link name="left_wheel">
<visual>
<geometry>
<cylinder radius="0.05" length="0.04"/>
</geometry>
</visual>
</link>
<!-- 右轮 -->
<link name="right_wheel">
<visual>
<geometry>
<cylinder radius="0.05" length="0.04"/>
</geometry>
</visual>
</link>
<joint name="left_wheel_joint" type="continuous">
<parent link="base_link"/>
<child link="left_wheel"/>
<origin xyz="-0.15 0.2 0" rpy="0 0 0"/>
<axis xyz="0 0 1"/>
</joint>
<joint name="right_wheel_joint" type="continuous">
<parent link="base_link"/>
<child link="right_wheel"/>
<origin xyz="-0.15 -0.2 0" rpy="0 0 0"/>
<axis xyz="0 0 1"/>
</joint>
</robot>
全向轮稍微复杂一点。它通常用三个或四个麦克纳姆轮,每个轮子可以独立控制。我建议初学者先从差速轮入手,因为控制逻辑更直观。全向轮虽然运动灵活,但调参时容易让人抓狂——我在项目里就吃过这个亏,全向轮在瓷砖地面上打滑,定位直接飘了。
2.4 传感器仿真插件配置
机器人要感知环境,离不开传感器。Gazebo 里传感器是通过插件实现的。最常用的两个:激光雷达(Lidar)和深度相机。
下面是一个激光雷达插件的配置示例,直接加到 URDF 里就行:
<gazebo reference="laser_link">
<sensor type="ray" name="head_laser">
<pose>0 0 0.1 0 0 0</pose>
<visualize>true</visualize>
<update_rate>10</update_rate>
<ray>
<scan>
<horizontal>
<samples>360</samples>
<resolution>1</resolution>
<min_angle>-3.14159</min_angle>
<max_angle>3.14159</max_angle>
</horizontal>
</scan>
<range>
<min>0.1</min>
<max>10.0</max>
<resolution>0.01</resolution>
</range>
</ray>
<plugin name="laser_controller" filename="libgazebo_ros_ray_sensor.so">
<topicName>/scan</topicName>
<frameName>laser_link</frameName>
</plugin>
</sensor>
</gazebo>
经验之谈:update_rate 别设太高,10Hz 就够用。我见过有人设到 100Hz,结果 CPU 直接拉满,仿真跑得比乌龟还慢。另外,visualize 设为 true 可以在 Gazebo 里看到激光射线,调试时很有用。
深度相机的配置类似,用 depth_camera 插件。这里不展开,后面章节会专门讲传感器融合。
2.5 本章知识体系总览
为了让你对整个流程有个全局认识,我画了一张图。这张图展示了从环境安装到传感器配置的完整链路:
嗯,这张图基本概括了咱们这一章要做的事。从安装环境开始,到创建场景、配置机器人、挂载传感器,最后启动仿真验证。每一步都有坑,但只要你按顺序来,就不会出大问题。
好了,这一章的内容就到这儿。下一章咱们会正式进入避障算法的核心——如何让机器人「看到」障碍物并做出反应。到时候见。
本章要点回顾:
- ROS Noetic + Gazebo 11 是当前最稳定的组合
- 障碍物场景推荐用
.world文件编写,方便复用 - 差速轮模型适合初学者,全向轮运动灵活但调参复杂
- 传感器插件配置时注意
update_rate不要过高 - 每次修改后先跑
gazebo --verbose检查错误