26 DemoRobot-URDF-Xacro与Gazebo Fortress联调

DemoRobot URDF/Xacro 建模与 Gazebo Fortress+ ros_gz + gz_ros2_control 联调

关联:索引

0. 环境自检:先确认“命令在”

ros2 --version
ign gazebo --versions
ros2 pkg list | grep -E "ros_gz|gz_ros2_control|ros2_control|ros2_controllers|xacro" || true

逐行解释:

sudo apt update
sudo apt install -y \
  ros-humble-xacro \
  ros-humble-robot-state-publisher \
  ros-humble-joint-state-publisher \
  ros-humble-rviz2 \
  ros-humble-ros-gz \
  ros-humble-gz-ros2-control \
  ros-humble-ros2-control \
  ros-humble-ros2-controllers

逐行解释:


目标:把“能跑起来的 Xacro”变成“RViz 里看得见的 RobotModel”。
关键结论:RViz 看见 RobotModel 的前提不是 Gazebo,而是 robot_description + TF

1) 本章代码结构:demo_robot_description 是一个“描述包”

目录位置:05_demo_robot_sim/ros2_ws/src/demo_robot_description
你需要先建立整体地图(不要一上来就改代码):

本章的组装入口是:
urdf/demo_robot/demo_robot.urdf.xacro:通过 xacro:include 引入底盘、轮子、传感器、插件等,再用宏调用把它们实例化。

3) RViz 展示链路:robot_state_publisher 做了什么

RViz 的 RobotModel 需要:

你只要把 robot_state_publisher 跑起来,TF 树就成立;RobotModel 只是 TF 的“可视化结果之一”。

0) 构建工作空间

假设你的工作空间是 ~/ros2_ws,并且 src 下已有 demo_robot_description

cd ~/ros2_ws
colcon build --symlink-install
source install/setup.bash

逐行解释:

1) 先跑“最小机器人”:URDF 演示机器人(用于理解 Xacro)

本包提供了两个版本:

启动 RViz 展示(推荐使用 Xacro 文件):

ros2 launch demo_robot_description display_robot.launch.py \
  model:=$(ros2 pkg prefix demo_robot_description)/share/demo_robot_description/urdf/urdf_demo_robot.urdf.xacro

逐段解释:

2) 证据链自检:确认 TF 与 RobotModel 成功

ros2 topic list | grep -E "^/tf$|^/tf_static$|^/joint_states$"

解释:

可选更强自检(看 TF 帧名是否符合预期):

ros2 topic echo /tf --once

解释:

四、练习(至少 2 题,含提示)

  1. 练习 1:改一个参数,看 RobotModel 变化
    要求:在 urdf/urdf_demo_robot.urdf.xacro 中,把 <xacro:base_link length="0.12" radius="0.1" />length 改为 0.18,重新启动 RViz。
    提示:Xacro 的参数变化会直接改变最终 URDF 的 <cylinder length="...">
  2. 练习 2:增加一个 IMU 实例,理解“宏复用”
    要求:在 urdf/urdf_demo_robot.urdf.xacro 中再添加一个 <xacro:imu_link imu_name="imu_left" .../>,位置放到 0.05 0.05 0.02,并验证 TF 帧名出现 imu_left_link
    提示:宏的 imu_name 会拼接进 link/joint 名字;重复命名会报错(URDF 不允许同名 link/joint)。
  1. 打开 urdf/demo_robot/demo_robot.urdf.xacro,列出 include 顺序(base、sensor、actuator、plugins、ros2_control)。
  2. 对照每个子文件(base/wheel/caster/imu/laser/camera),整理它们新增的 link/joint 名称。

七、大模型任务(给 AI 的指令模板 + 期望输出 + 校验点)

指令模板(直接复制给 AI):

Xacro 文件路径与关键片段如下:

期望输出:

校验点(你必须自己验证,不盲信 AI):

八、小结与常见错误


目标:把“RViz 里看得见的机器人”推进到“Gazebo 里跑得动、ROS2 里拿得到数据”。
关键结论:Gazebo Fortress(Gazebo Sim)里动起来常见两条路:

  1. Gazebo 原生运动插件 + ros_gz_bridge:Gazebo 内部接收 Gazebo Transport 的速度指令(需要桥接 Gazebo Transport 话题,工程复杂度更高)。
  2. gz_ros2_control + ROS2 控制器(本章主线):Gazebo Sim 作为“硬件接口”,ROS2 的 DiffDriveController 原生订阅其私有速度话题(例如 ~/cmd_vel_unstamped),并发布 ~/odom/tf。为让学生统一使用标准话题,本工程在 launch 中增加了一个 topic relay:把 /cmd_vel 转发到控制器话题(见第三部分自检命令)。

1) 仿真链路总览:从 robot_description 到控制器

本章启动文件:launch/gazebo_sim.launch.py(简化描述为 6 步):

  1. Xacro 展开 → 生成 robot_description(参数)
  2. 设置 Gazebo 资源路径(IGN_GAZEBO_RESOURCE_PATH / GZ_SIM_RESOURCE_PATH)并启动 Gazebo Fortress(内部命令是 ign gazebo,由 ros_gz_simgz_sim.launch.py 拉起)加载 world
  3. ros_gz_sim create 从 ROS 参数 robot_description 生成并插入实体 demo_robot(launch 内部对应 -param robot_description
  4. URDF 中的 <plugin filename="gz_ros2_control-system" ...> 启动 controller_manager(运行在 Gazebo 进程内)
  5. controller_manager spawner 激活控制器(JointStateBroadcaster、DiffDriveController)
  6. 用 ROS2 发布 /cmd_vel,验证机器人在 Gazebo 中运动

补充说明(为什么要设置资源路径):

你需要记住的“证据点”:

2) ros2_control 配置文件:YAML 与 URDF 插件如何对应

本章配置文件:config/demo_robot_ros2_controller.yaml
关键结构分两层:

3) 传感器插件:Gazebo 内部传感器 → ROS2 消息

本目录的传感器配置采用“Gazebo 传感器原生输出 + ros_gz_bridge 桥接”的思路:

0) 启动仿真

cd ~/ros2_ws
source install/setup.bash
ros2 launch demo_robot_description gazebo_sim.launch.py

逐行解释:

1) 自检 1:实体是否生成(Gazebo 可视化 + ROS2 侧证据)

Gazebo GUI 侧:应能在场景里看到 demo_robot。
ROS2 侧建议先看节点列表:

ros2 node list | grep -E "ros_gz|controller_manager|robot_state_publisher" || true

解释:

2) 自检 2:控制器是否激活

ros2 control list_controllers

解释:

ros2 topic pub -r 10 /cmd_vel geometry_msgs/msg/Twist \
  "{linear: {x: 0.2, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 0.0}}"

逐段解释:

停止方法(两种任选其一):

4) 自检 4:至少跑通 1 个传感器话题(推荐 /demo_robot/scan)

ros2 topic list | grep -E "^/demo_robot/scan$|^/demo_robot/imu$|camera|image" || true
ros2 topic echo /demo_robot/scan --once

解释:

四、练习(至少 2 题,含提示)

  1. 练习 1:控制器参数对现象的影响(轮距/半径)
    要求:在 config/demo_robot_ros2_controller.yaml 中把 wheel_separation 改大(例如 0.17 → 0.22),让机器人原地转圈(angular.z=0.5)观察转向半径变化。
    提示:轮距变大通常会导致同样角速度下转向表现变化;你要记录“参数→现象”的证据。
  2. 练习 2:传感器频率与噪声对数据的影响(Laser)
    要求:在 urdf/demo_robot/plugins/gazebo_sensor_plugin.xacro 中把激光 <update_rate>10 调到 15,并在 ros2 topic hz /demo_robot/scan(可选)观察频率变化。
    提示:先确保 /demo_robot/scan 能正常输出,再做频率实验;不要在“还没跑通”时调参。

工坊主题:完成一次“可控可感知”的闭环联调,并修复 2 个工程常见坑

工坊 A(推荐,全班做):核对 RViz 配置文件路径是否正确

工坊 B(进阶,小组挑战):做一次“可审计的 Xacro 展开 + 控制器/桥接最小联调”

  1. xacro ... > /tmp/demo_robot.urdf 成功落盘
  2. ros2 control list_controllers 显示 active
  3. ros2 topic echo /clock --once 有输出
  4. ros2 topic echo /demo_robot/scan --once 有输出

用于自检的展开命令(把 Xacro 输出成 URDF 纯文本):

xacro $(ros2 pkg prefix demo_robot_description)/share/demo_robot_description/urdf/demo_robot/demo_robot.urdf.xacro > /tmp/demo_robot.urdf
head -n 20 /tmp/demo_robot.urdf

逐行解释:

七、大模型任务(给 AI 的指令模板 + 期望输出 + 校验点)

指令模板(直接复制给 AI):

你是 ROS2 Humble + Gazebo Fortress(ign gazebo)联调专家。请审计下面的 URDF/Xacro 设计,给出“最小修改方案”,让它满足:

  1. xacro 能在 ROS2 Humble 下展开(路径替换正确)
  2. gz_ros2_control 插件能读取控制器 YAML
  3. 至少 /demo_robot/scan 能发布到 ROS2
    请输出:修改后的关键片段(只贴需要改的段落),并解释每一处修改为什么必要、会影响什么证据点(topic/node/controller)。
    输入文件:

期望输出:

校验点(你必须自己验证,不盲信 AI):

八、小结与常见错误(按排查优先级排序)

  1. xacro 解析失败(最常见、也最该先解决)
    症状:launch 日志里出现 “xacro: error …” 或 robot_description 为空。
    排查顺序:
  1. Gazebo 启动成功但没有 demo_robot 实体
    症状:world 有,机器人没有。
    排查:
  1. 控制器加载失败
    症状:ros2 control list_controllers 看不到控制器或状态非 active。
    排查:
  1. /demo_robot/scan 或 /demo_robot/imu 不发布
    症状:话题不存在或 echo 无输出。
    排查:

课后作业


参考与延伸(官方/通用资料)


自检清单(交付前必做)

Markdown 自检(本已执行)

命令与代码自检(基于本目录内容的静态核对)