16 Gazebo Fortress 分拣产线仿真建模与 ROS2 Humble 适配基础
Gazebo Fortress 分拣产线仿真建模与 ROS2 Humble 适配基础
关联:索引
- 先修:已掌握 ROS2 Humble 基础环境配置、终端常用操作与工作空间概念(前置已覆盖);能在终端执行命令并阅读报错信息。
- 推荐系统:Ubuntu 22.04(与 ROS2 Humble 匹配)。
- 目标软件版本:Gazebo Fortress(对应 Ignition Gazebo 6 / ign-gazebo6)。
- 本默认:使用 SDF 作为世界与模型描述主线;URDF 作为机器人(UR5e)结构描述补充,强调“URDF 常用于机器人、SDF 更适合完整仿真世界”。
- 价值点(课程思政切入):仿真能减少试错次数、降低能耗与材料浪费,是“节能减耗”的工程方法;分拣产业升级离不开智能装备与软件生态,国产工业软件的进步需要工程师坚持规范、持续迭代。
1. Gazebo Fortress 的运行闭环(必须会说清)
把 Gazebo 理解为一台“仿真机器”,它主要做四件事:
- 读入世界与模型描述(SDF/.world/.sdf);
- 由物理引擎计算动力学与碰撞接触(ODE/PhysX 等在同一抽象接口下运行);
- 更新传感器与系统(相机、IMU、关节、插件逻辑);
- 渲染并提供交互(GUI、日志、状态检查)。
关键结论(学生必须记住):
- “世界文件”决定了场景里有什么与初始状态;
- “物理引擎参数”决定了能否稳定、是否打滑/穿透/抖动;
- “仿真时间”决定了 ROS2 节点怎么理解时间与频率;
- “资源路径”决定了模型能不能被找到(找不到就会加载失败)。
2. 物理引擎(ODE/PhysX)工作机制:你要关心的不是名字,是差异点
-
碰撞检测(Collision):几何体是否相交、接触点在哪里。
-
接触求解(Contact Solver):接触力如何计算,是否会抖动/穿透。
-
迭代与步长(Iterations/Step Size):一秒内算多少次、每次算多细,影响稳定性与速度。
-
摩擦与恢复(Friction/Restitution):打滑与弹跳的来源,影响传送带与物料交互。
-
经典、稳定、参数可调空间大;
-
低精度或错误参数下容易出现抖动、穿透、接触不稳定;
-
通过更小步长、更多迭代、合理摩擦等提升稳定性,但会变慢。
-
在某些接触场景性能与稳定性表现较好(依赖具体版本与插件实现);
-
需要注意与平台/驱动/版本的匹配;
-
参数体系可能与 ODE 不完全一致,迁移时要做“现象对齐”而不是“参数照抄”。
3. 仿真时间与 ROS2 时间:/clock 是关键连接点
在仿真中,Gazebo 会维护一套“仿真时间”(Sim Time)。ROS2 节点如果要以仿真时间为准,需要两步:
- Gazebo 发布
/clock(仿真时钟); - ROS2 节点设置参数
use_sim_time:=true,之后节点的时间 API 会读取/clock。
为什么重要:
- 你的节点频率、超时、滤波器时间戳都依赖时间基准;
- 如果仿真暂停(Pause),仿真时间停住,ROS2 节点也应同步停住;
- 做调参对比实验时,必须用统一时间基准,否则数据不可比。
0. 重要说明:命令前置条件
- 终端每次新开时,先确保 ROS2 环境可用(前置内容已学会)。
- 本的命令以 Ubuntu 22.04 为例;如使用容器或 WSL,请确保图形界面与 GPU/渲染能力可用,否则 GUI 可能无法打开。
sudo apt update
sudo apt install -y curl gnupg lsb-release
逐行解释:
apt update:刷新软件索引,避免安装到旧包或找不到包。curl gnupg lsb-release:用于添加软件源与签名,后续步骤会用到。
添加 Gazebo(OSRF)软件源并安装 Fortress:
# 可选命令,具体先执行后续安装指令,提示安装有问题时再来运行这个命令
sudo curl -sSL https://packages.osrfoundation.org/gazebo.gpg -o /usr/share/keyrings/pkgs-osrf-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/pkgs-osrf-archive-keyring.gpg] https://packages.osrfoundation.org/gazebo/ubuntu-stable $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/gazebo-stable.list > /dev/null
# 更新软件源
sudo apt update
# 安装gazebo fortress
sudo apt install -y gz-fortress
逐行解释:
- 第 1 行:下载并保存 OSRF 软件源签名密钥,保证包来源可信。
- 第 2 行:写入 Gazebo 稳定源(按系统架构与发行版代号匹配)。
- 第 3 行:更新索引,让系统能看到新源提供的软件包。
- 第 4 行:安装 Fortress 元包,通常会拉取
ign-gazebo6(仿真)等组件(命名迁移期,包名可能显示为gz-*或ign-*)。
安装验证:
ign
ign gazebo --versions
逐行解释:
ign:验证 Ignition 命令存在(Fortress 常用入口)。ign gazebo --versions:查看仿真与依赖库版本,用于截图留证与排错对齐。
常见问题自检(出现“找不到 ign/ign gazebo”时):
which ign
ign --version
echo $PATH
逐行解释:
which ign:查看命令路径,确认是否已安装或 PATH 是否缺失。ign --version:快速确认命令可执行且版本信息正常输出。echo $PATH:检查环境变量是否包含系统二进制路径。
2. 方式 B:源码安装(扩展选做,用于研究型同学/教师备课)
sudo apt update
sudo apt install -y git cmake build-essential pkg-config python3-pip
逐行解释:
- 安装编译所需基础工具链;源码编译成功与否高度依赖依赖项是否齐全。
建议做法:
- 按 Gazebo Fortress 官方安装指南逐个组件编译;
- 每编译一个组件就做一次
ign gazebo --versions或最小示例验证; - 编译完成后,使用
setup.sh脚本导出环境变量(资源路径、库路径)。
3. 环境变量:让 Gazebo 找得到你的模型与世界
Gazebo 加载模型会查找资源路径。你需要掌握两个变量(不同发行版命名可能不同):
GZ_SIM_RESOURCE_PATH:Gazebo Sim 资源路径(模型、世界、材质等)。IGN_GAZEBO_RESOURCE_PATH:旧命名(部分系统仍使用,二者可同时设置)。
示例:把你的模型目录加入资源路径(假设模型放在 ~/gazebo_models):
export GZ_SIM_RESOURCE_PATH=$GZ_SIM_RESOURCE_PATH:$HOME/gazebo_models
export IGN_GAZEBO_RESOURCE_PATH=$IGN_GAZEBO_RESOURCE_PATH:$HOME/gazebo_models
逐行解释:
export ...=$已有值:$新路径:在不覆盖原有路径的前提下追加新目录。- 同时设置两个变量:用于兼容不同版本/插件,减少“找不到模型”的坑。
验证变量是否生效:
echo $GZ_SIM_RESOURCE_PATH
4. 创建最小 world(SDF/.world)并运行
在任意工作目录下新建文件:minimal.world(注意:文件内容本质是 SDF)。
<?xml version="1.0" ?>
<sdf version="1.8">
<world name="minimal_world">
<physics name="default_physics" type="ode">
<max_step_size>0.001</max_step_size>
<real_time_factor>1.0</real_time_factor>
<real_time_update_rate>1000</real_time_update_rate>
</physics>
<gravity>0 0 -9.8</gravity>
<include>
<uri>https://fuel.gazebosim.org/1.0/OpenRobotics/models/Ground Plane</uri>
</include>
<include>
<uri>https://fuel.gazebosim.org/1.0/OpenRobotics/models/Sun</uri>
</include>
</world>
</sdf>
逐段解释:
<sdf version="1.8">:SDF 版本声明;写错可能导致解析失败或某些字段不生效。<world ...>:一个 world 就是一个仿真场景容器。<physics type="ode">:选择物理引擎(示例用 ODE),并设置关键参数:max_step_size:单步仿真步长(越小越精细,通常越稳定但更慢)。real_time_factor:期望仿真与真实时间的倍率(1.0 表示尽量实时)。real_time_update_rate:物理更新频率(与步长共同决定仿真精度/负载)。<gravity>:重力向量。<include><uri>...:从 Fuel 资源库加载地面与太阳光源,快速得到可视化世界。
运行最小 world:
ign gazebo -v 4 minimal.world
常见问题:虚拟机中 Gazebo 窗口闪烁/黑屏/画面撕裂(GUI 不稳定)
这类问题通常不是 world 文件语法导致,而是虚拟机图形栈(OpenGL/显卡驱动/桌面会话类型)导致 GUI 渲染不稳定。按“代价从小到大”的顺序排查:
- 确认 OpenGL 渲染器是否正常(建议先装工具):
sudo apt install -y mesa-utils
glxinfo -B | grep -E "OpenGL vendor|OpenGL renderer|OpenGL version"
逐行解释:
mesa-utils:提供glxinfo,用于查看 OpenGL 驱动与渲染器。OpenGL renderer若显示llvmpipe通常表示在用软件渲染(更稳定但可能更慢);若显示SVGA3D/VirGL/显卡型号说明在用虚拟/硬件加速。
- 优先检查虚拟机的 3D 加速与增强工具:
- VirtualBox:开启 Display -> Enable 3D Acceleration,并安装 Guest Additions;显存适当调大(例如 128MB 或更高)。
- VMware:开启 3D 图形加速,并安装 open-vm-tools/open-vm-tools-desktop。
- 尽量使用 Xorg 会话(部分 Wayland + 虚拟显卡组合容易闪烁):
echo $XDG_SESSION_TYPE
逐行解释:
- 输出
x11表示 Xorg,会话兼容性通常更好;若是wayland,可在登录界面选择 “Ubuntu on Xorg” 再重试。
- 作为兜底方案:强制软件渲染运行(稳定优先,性能次之):
LIBGL_ALWAYS_SOFTWARE=1 ign gazebo -v 4 minimal.world
逐行解释:
LIBGL_ALWAYS_SOFTWARE=1:强制使用 Mesa 软件渲染,常用于解决虚拟机/远程桌面下的闪烁与黑屏问题。
逐行解释:
-
ign gazebo:启动仿真(Fortress 常用入口)。 -
-v 4:提高日志详细度,便于排错(越大越详细)。 -
minimal.world:要加载的 world 文件。 -
终端
ign gazebo -v 4 minimal.world无 SDF 解析错误(截图); -
GUI 能看到地面与光源(截图);
-
GUI 中 Pause/Play 操作成功(截图)。
5. 参数对比实验:重力与摩擦(只做最小可观察现象)
把上面的 world 复制成 compare_physics.world,新增一个小方块并给它初速度,让它在地面上滑行。
<model name="box1">
<static>false</static>
<pose>0 0 0.5 0 0 0</pose>
<plugin
filename="ignition-gazebo-velocity-control-system"
name="gz::sim::systems::VelocityControl">
<initial_linear>1 0 0</initial_linear>
<initial_angular>0 0 0</initial_angular>
</plugin>
<link name="link">
<inertial>
<mass>1.0</mass>
</inertial>
<collision name="collision">
<geometry>
<box><size>0.2 0.2 0.2</size></box>
</geometry>
<surface>
<friction>
<ode>
<mu>0.2</mu>
<mu2>0.2</mu2>
</ode>
</friction>
</surface>
</collision>
<visual name="visual">
<geometry>
<box><size>0.2 0.2 0.2</size></box>
</geometry>
</visual>
</link>
</model>
逐段解释:
<model static>false</static>:可运动模型。<pose>:初始位姿(x y z roll pitch yaw),把盒子放在地面上方 0.5m。<plugin ... VelocityControl>:在 ign-gazebo6 环境下,通过系统插件设置初始线速度与角速度,更兼容,避免<velocity>被解析器忽略。<initial_linear>1 0 0</initial_linear>:给出 x 方向 1m/s 的初始线速度。<inertial><mass>:质量(越大惯性越大)。<surface><friction>:摩擦模型参数(示例给 ODE 参数mu/mu2)。
对比方法(学生必须做并记录):
- 把
mu/mu2从0.2改成1.0,观察盒子滑行距离的变化。 - 把
<gravity>0 0 -9.8</gravity>改成<gravity>0 0 -3.0</gravity>或<gravity>0 0 -15.0</gravity>,观察落地速度与接触稳定性的变化。
记录要求:
- 现象描述要包含“修改项→现象变化→你的解释(1 句话)”;
- 不允许只写“变了/没变”,必须指出“更滑/更慢/抖动更明显”等可验证描述。
- 快速回顾(举手回答):
max_step_size变小通常会带来什么变化?摩擦系数变大,盒子会更滑还是更粘?为什么我们强调要设置资源路径?
1. 分拣产线建模逻辑:先定坐标与布局,再定模型与参数
分拣产线仿真建模的顺序建议是:
- 定义世界坐标系:统一约定原点与轴向(建议:世界坐标系
W,x 向前、y 向左、z 向上)。 - 规划设备布局:传送带中心线、UR5e 安装基座、分拣箱位置、相机/传感器视野范围。
- 建立可复用模型库:传送带、工位框架、箱体、料块、机器人底座等用独立 model 文件管理。
- 再调物理参数:重力、摩擦、接触迭代、阻尼等从“能稳定运行”开始逐步提高精度。
- 原点在哪里?UR5e 的基座姿态如何定义?
- 传送带运动方向与世界坐标轴如何对应?
2. .world/.sdf 语法规范:你必须会读的 6 个结构
一份可维护的 world 文件建议包含:
-
<world>:场景容器(命名要语义化,如sorting_line_world)。 -
<physics>:物理引擎与时间参数(每次调参都要记录版本与参数组合)。 -
<gravity>:重力与方向(不要默认相信系统值)。 -
<include>:引用外部模型(优先 Fuel 或本地模型库)。 -
<model>:自定义模型(结构清晰、可复用、命名规范)。 -
<plugin>:系统/功能插件(用于传送带运动、ROS2 桥接、传感器等)。 -
world:
snake_case,如sorting_line_world; -
model:语义化+编号,如
conveyor_01、bin_grade_a; -
link/joint:结构化命名,如
base_link、belt_link、belt_joint。
3. URDF 与 SDF 的关系:如何复用机器人模型
工程中常见做法:
-
机器人本体结构(UR5e 的 link/joint)用 URDF(便于与 ROS2 生态对接,如 MoveIt2)。
-
仿真世界与非机器人设备(传送带、工位、箱体)用 SDF(便于描述物理、接触、传感器、插件)。
-
URDF 作为机器人“几何与关节定义”,需要仿真时再通过工具或插件转换/加载到 SDF 世界中;
-
输出 1:产线布局草图(A4),必须标注:
-
世界原点
W; -
传送带中心线方向;
-
UR5e 基座位置与朝向;
-
分拣箱 A/B/C 的位置;
-
相机(或传感器)安装点(可选)。
-
输出 2:物理参数调控优先级(写 3 条):
-
你们最先调哪些参数(例如步长、迭代、摩擦)?
-
每条参数对应的“预期现象”是什么?
-
说清原点与轴向;
-
说清传送带方向与抓取工作区;
-
说清 3 个参数与现象的对应关系。
1. 建一个“基础分拣产线”world(建议命名:sorting_line.world)
sorting_line_demo/
sorting_line.world
创建并编辑 sorting_line.world(复制即可运行):
mkdir -p sorting_line_demo
cd sorting_line_demo
nano sorting_line.world
逐行解释:
mkdir -p sorting_line_demo:创建练习目录,避免文件散落在桌面。cd sorting_line_demo:进入目录,后续运行命令更清晰。nano sorting_line.world:用文本编辑器创建并编辑 world 文件(也可用 VS Code)。
下面示例展示一个可维护的骨架结构:把设备尽量拆成可复用 model,再在 world 中 include 并摆放。
<?xml version="1.0" ?>
<sdf version="1.8">
<world name="sorting_line_world">
<physics name="fast_stable" type="ode">
<max_step_size>0.001</max_step_size>
<real_time_factor>1.0</real_time_factor>
<real_time_update_rate>1000</real_time_update_rate>
</physics>
<gravity>0 0 -9.8</gravity>
<include>
<uri>https://fuel.gazebosim.org/1.0/OpenRobotics/models/Ground%20Plane</uri>
</include>
<include>
<uri>https://fuel.gazebosim.org/1.0/OpenRobotics/models/Sun</uri>
</include>
<model name="conveyor_01">
<static>true</static>
<pose>0 0 0 0 0 0</pose>
<link name="belt_link">
<collision name="belt_collision">
<geometry>
<box><size>2.0 0.5 0.1</size></box>
</geometry>
<surface>
<friction>
<ode>
<mu>0.9</mu>
<mu2>0.9</mu2>
</ode>
</friction>
</surface>
</collision>
<visual name="belt_visual">
<geometry>
<box><size>2.0 0.5 0.1</size></box>
</geometry>
</visual>
</link>
</model>
<model name="bin_grade_a">
<static>true</static>
<pose>1.2 0.8 0.2 0 0 0</pose>
<link name="bin_link">
<collision name="bin_collision">
<geometry>
<box><size>0.4 0.4 0.4</size></box>
</geometry>
</collision>
<visual name="bin_visual">
<geometry>
<box><size>0.4 0.4 0.4</size></box>
</geometry>
</visual>
</link>
</model>
<model name="apple_01">
<static>false</static>
<pose>-0.8 0 0.25 0 0 0</pose>
<plugin
filename="ignition-gazebo-velocity-control-system"
name="gz::sim::systems::VelocityControl">
<initial_linear>0.8 0 0</initial_linear>
<initial_angular>0 0 0</initial_angular>
</plugin>
<link name="link">
<inertial><mass>0.2</mass></inertial>
<collision name="collision">
<geometry>
<sphere><radius>0.05</radius></sphere>
</geometry>
<surface>
<friction>
<ode>
<mu>0.6</mu>
<mu2>0.6</mu2>
</ode>
</friction>
</surface>
</collision>
<visual name="visual">
<geometry>
<sphere><radius>0.05</radius></sphere>
</geometry>
</visual>
</link>
</model>
</world>
</sdf>
逐段解释(对照“结构规范 6 件套”):
conveyor_01:这里用“简化传送带”为一个静态盒子,先把布局与接触稳定做对,再引入运动插件或关节速度。bin_grade_a:用一个箱体占位,后续可扩展为“无底箱/围栏”结构(由多个板拼装)。apple_01:用球体代替水果,减少几何复杂度,便于观察接触与摩擦现象;并通过VelocityControl插件给一个初始线速度,便于直观看到“物料沿 x 方向运动 + 摩擦导致减速”的现象。
运行:
ign gazebo -v 4 sorting_line.world
逐行解释:
ign gazebo:启动 Fortress 仿真。-v 4:输出更详细日志,便于定位模型加载与插件加载问题。sorting_line.world:你刚刚创建的 world 文件。
常见问题提示:
- 终端
ign gazebo -v 4 sorting_line.world无 SDF 解析错误(截图); - 苹果落到传送带上不会穿透(截图);
- 轻微抖动允许,但不能“爆炸式弹飞”(截图或录屏 5 秒二选一);
- GUI 中能选中
conveyor_01/apple_01/bin_grade_a并查看 pose/属性(截图)。
2. GUI 基础操作:模型编辑与状态监控(必须会)
- 暂停/继续/单步:用于对比实验与定位“接触抖动”发生的时刻。
- Entity Tree(实体树):快速定位
conveyor_01/apple_01/bin_grade_a。 - 选中与移动:检查布局是否符合草图,确认坐标统一是否生效。
- 物理状态观察:重点看模型是否穿透、是否漂浮、是否抖动。
- 日志查看:出现加载失败时,先看终端
-v 4的错误信息定位到具体 SDF 行或 URI。
3. 物理参数实时调测:从“现象”反推“参数”
- 稳定性(防穿透/防抖动):
- 方向:减小
max_step_size、提高迭代/更新率、降低初始速度或简化几何。
- 接触与摩擦(防打滑/更贴合):
- 方向:提高
mu/mu2,检查接触面是否正确设置在 collision 上而不是 visual 上。
- 真实性(速度/实时性权衡):
- 方向:在稳定后再逐步提高
real_time_factor,观察是否掉帧或不稳定。
记录模板(直接抄写):
- 修改前参数:____
- 修改后参数:____
- 现象变化:____
- 解释(1 句):____
4. 与 ROS2 Humble 适配基础:仿真时间接入与验证思路
本节只讲“最小适配闭环”:让 ROS2 节点能使用仿真时间,并给出验证证据链。
ROS2 侧设置使用仿真时间(以任意节点为例):
先确认目标节点名(任选其一):
ros2 node list
逐行解释:
ros2 node list:列出当前运行的 ROS2 节点,找到你要设置参数的节点名(例如/controller、/camera_node等)。
ros2 param set /你的节点名 use_sim_time true
逐行解释:
ros2 param set:给运行中的节点设置参数。use_sim_time true:让节点使用/clock作为时间来源(前提是系统里存在/clock)。
验证证据链(至少做 1 条):
ros2 topic list | grep clock
ros2 topic echo /clock --once
逐行解释:
- 第 1 条:确认系统里是否有
/clock。 - 第 2 条:读取一次时钟消息,证明仿真时间在发布。
说明:
- 与 ROS2 的数据互通通常通过桥接包实现(思路:Gazebo Transport ↔ ROS2 Topic),本课程后续章节会深入实现;本章只要求你理解“时间先通,数据再通”的工程顺序。
- 本章不要求完成 Gazebo↔ROS2 全量话题桥接与控制闭环,仅要求时间基准与 world/参数的可复现验证。
- 本章产出的 world 文件、参数对比记录与
/clock验证证据,将用于后续模块 5 的 Web 端状态展示与回放(先保证时间基准一致,再做状态/位姿同步)。
5. AI 协同排错:把“报错信息”变成“可行动的修改”
给 AI 的提示词模板 1:安装报错定位(可直接复制)
你是 Gazebo Fortress + ROS2 Humble 助教。我的系统是 Ubuntu 22.04。执行命令:
(粘贴你的命令)报错如下:(粘贴完整报错)。请给出:1)最可能的 3 个原因(按概率排序);2)每个原因对应的验证命令;3)最小修复步骤(避免大范围重装);4)修复后如何验证成功(给出可截图证据);5)回滚方式(若修复失败如何恢复)。
给 AI 的提示词模板 2:生成 world / SDF 模板并自检(可直接复制)
给 AI 的提示词模板 3:语法错误快速修复(可直接复制)
我有一段 SDF/URDF 片段(如下),Gazebo 报错:
(粘贴报错)。请你指出具体哪一行/哪一个标签可能导致解析失败,并给出“最小改动”的修复版本。修复后请解释每一处改动的原因。
- 安装验证与最小 world 运行:完成
ign --version、ign gazebo --versions、ign gazebo -v 4 minimal.world的验证证据(截图)。 - 参数对比实验:至少完成 1 组“参数→现象”对比(如摩擦或重力),保留修改前/修改后参数与现象描述(1–2 句话),并截图留证。
- 基础分拣产线 world 运行:运行
sorting_line.world,完成“无解析错误 + 关键现象 + GUI 选中查看属性”的证据链(截图或 5 秒录屏)。 - AI 协同排错或生成:完成 1 次 AI 交互(排错/生成模板二选一),保留提示词 + 关键输出 + 你最终采用的修改点 + 验证证据(截图)。
-
每组展示 1 张“参数对比”证据 + 1 张“world 运行”证据,口头说明:你改了什么、看到什么、如何验证。
-
抽查维度:world 文件结构规范(命名/pose/physics)、参数记录是否可复现、证据链是否完整(命令输出/GUI/现象描述)。
-
Gazebo 官方文档(概览):https://gazebosim.org/docs
-
SDF 规范与元素说明:https://sdformat.org/spec
-
ROS2 官方文档(Humble):https://docs.ros.org/en/humble/
-
OSRF 软件源与包(用于安装排错对照):https://packages.osrfoundation.org/