# 60 · URDF 机器人模型(完全指南)
> **目标**:能读懂 URDF,能从零写一个 6-DoF 机械臂 URDF,理解 link / joint / xacro / 物理参数,会校验 + 可视化。
---
## 目录
- [1. URDF 是什么](#1-urdf-是什么)
- [2. URDF 三大元素](#2-urdf-三大元素)
- [3. 完整 6-DoF 机械臂示例](#3-完整-6-dof-机械臂示例)
- [4. xacro:模板化 URDF](#4-xacro模板化-urdf)
- [5. 坐标约定 REP-103 / REP-105](#5-坐标约定-rep-103--rep-105)
- [6. ros2_control 集成(加 transmission)](#6-ros2_control-集成加-transmission)
- [7. Gazebo 集成(加 gazebo 标签)](#7-gazebo-集成加-gazebo-标签)
- [8. 校验 + 可视化](#8-校验--可视化)
- [9. 工具链总结](#9-工具链总结)
- [10. MoveIt2 SRDF(规划组)](#10-moveit2-srdf规划组)
- [11. 在本仓库里跑](#11-在本仓库里跑)
- [12. 进阶:6-DoF 真机械臂 URDF 实战](#12-进阶6-dof-真机械臂-urdf-实战)
---
## 1. URDF 是什么
**URDF** (Unified Robot Description Format) = 用 XML 描述机器人:
- 有哪些**刚体段**(``)
- 刚体之间怎么连(``)
- 视觉 / 碰撞几何(`` / ``)
- 物理参数(质量、惯性,``)
URDF 通过 `robot_state_publisher` 翻译成 TF tree,被 MoveIt2 / Gazebo / RViz 读取。
---
## 2. URDF 三大元素
### 2.1 `` — 刚体段
| 子标签 | 用途 | 必填 |
|---|---|---|
| `` | 视觉几何(RViz / Gazebo 显示) | 推荐 |
| `` | 碰撞几何(物理仿真) | 推荐 |
| `` | 质量 + 转动惯量(动力学仿真必填) | 仿真必填 |
| `` | 视觉颜色 | 否 |
```xml
```
#### 几何类型
```xml
```
#### 颜色 / 材质
```xml
```
### 2.2 `` — 关节
| type | 含义 | DoF |
|---|---|---|
| `revolute` | 转动(有限位) | 1 |
| `continuous` | 转动(无限位) | 1 |
| `prismatic` | 滑动 | 1 |
| `fixed` | 固定连接 | 0 |
| `floating` | 6 DoF | 6 |
| `planar` | 平面 3 DoF | 3 |
```xml
effort="100" velocity="1.0"/>
```
**重要约定**:
- `axis` 在 **parent link 系**下定义
- `origin` 是 **child 相对 parent** 的偏移
- 关节运动绕 `axis` 旋转(或沿 axis 平移)
### 2.3 `` 根
- `name`:机器人名字,在 ROS 工具中显示
- 必须包含所有 `` 和 ``
### 2.4 最小 URDF 示例
```xml
```
---
## 3. 完整 6-DoF 机械臂示例
模拟 6-DoF 工业机械臂(类似 UR5 / xArm 6):
```xml
```
**约定**:
- x = 前进
- y = 左
- z = 上
- joint1 绕 z 轴,旋转"底盘朝向"
- joint2/joint3 绕 y 轴,"肩膀/肘部俯仰"
- joint4/joint5/joint6 腕部 3 DoF
- 总长度约 0.4 m,可伸展约 0.5 m
---
## 4. xacro:模板化 URDF
URDF 重复内容多(左右轮、对称连杆)。**xacro** 提供宏、变量、数学。
### 4.1 安装
xacro 通常自带 ROS2:
```bash
sudo apt install ros-humble-xacro
```
### 4.2 xacro 基础语法
```xml
```
### 4.3 编译 xacro → URDF
```bash
xacro arm.xacro > arm.urdf
# 或 ros2 launch 时直接传 xacro 输出:
ros2 run robot_state_publisher robot_state_publisher \
--ros-args -p robot_description:="$(xacro /path/to/arm.xacro)"
```
---
## 5. 坐标约定 REP-103 / REP-105
ROS2 的标准约定,**违反会导致 MoveIt2 / Gazebo 算错**:
### 5.1 REP-103(单位 + 坐标轴方向)
- 长度单位:**米**(m)
- 角度单位:**弧度**(rad)
- 右手系:
- **x** = 前进
- **y** = 左
- **z** = 上
### 5.2 REP-105(坐标系语义)
| frame | 含义 |
|---|---|
| `world` | 全局参考(通常不动) |
| `map` | SLAM 输出的地图 |
| `odom` | 里程计 / AMCL 定位 |
| `base_link` | 机器人底盘中心(刚体) |
| `base_footprint` | 底盘在地面的投影(2D 导航) |
关系:
- `world → map → odom → base_link` 是固定链
- `world → map` 由 SLAM 提供(变化)
- `map → odom` 由 AMCL / 里程计提供
- `odom → base_link` 由编码器 / IMU 提供
---
## 6. ros2_control 集成(加 transmission)
`ros2_control` 需要每个关节加 `` 标签:
```xml
transmission_interface/SimpleTransmission
hardware_interface/PositionJointInterface
hardware_interface/PositionJointInterface
1
```
`` 描述:
- 哪个 joint
- 用哪个 hardware interface(Position / Velocity / Effort)
- 减速比(`mechanicalReduction`)
---
## 7. Gazebo 集成(加 gazebo 标签)
Gazebo Sim / ros_gz 加载 URDF 时需要 `` 标签 + ``(已经加)。
```xml
$(find my_arm)/config/controllers.yaml
Gazebo/Red
```
---
## 8. 校验 + 可视化
### 8.1 校验
```bash
sudo apt install liburdfdom-tools
# 检查 URDF 合法性
check_urdf my_arm.urdf
# 输出 OK 即合法,会打印 link / joint 树结构
```
### 8.2 生成 PDF/PNG 图
```bash
sudo apt install liburdfdom-tools python3-urdfdom-py
urdf_to_graphiz my_arm.urdf # 生成 .pdf
# 或
urdf_to_graphiz my_arm.urdf -o my_arm.pdf
```
### 8.3 RViz 可视化
```bash
ros2 launch urdf_tutorial display.launch.py
# 或自己写 launch:
ros2 run rviz2 rviz2
# 在 RViz:
# Fixed Frame → base_link
# Add → RobotModel ← 显示 URDF
# Add → TF ← 显示 TF tree
```
### 8.4 joint_state_publisher_gui(手动调关节)
```bash
ros2 run joint_state_publisher_gui joint_state_publisher_gui
# 弹出 GUI,拖滑块调关节角,看机械臂在 RViz 里动
```
---
## 9. 工具链总结
```
xacro .xacro ───> .urdf (用 xacro 编译)
│
├──> check_urdf (校验)
├──> urdf_to_graphiz (可视化)
│
├──> robot_state_publisher
│ │
│ │ 读 URDF + /joint_states → 算 TF → /tf
│ │
│ └──> tf2::Buffer (其他节点订阅)
│
├──> MoveIt2 (规划)
│ │
│ │ 读 URDF + SRDF → 算 IK / path
│ │
│ └──> trajectory_msgs/JointTrajectory
│
└──> Gazebo Sim (仿真)
│
│ 读 URDF + gazebo 标签 → 物理仿真
```
---
## 10. MoveIt2 SRDF(规划组)
URDF 描述"机器人长啥样",SRDF 加 MoveIt2 需要的规划信息:
- **虚拟关节**:base_link → world(让 MoveIt2 把臂放在世界系)
- **规划组**(Planning Group):哪些关节一起动
- **末端执行器**:夹爪
- **预设位姿**(Pose):home / ready / extended
### 10.1 用 MoveIt Setup Assistant 生成
```bash
ros2 launch moveit_setup_assistant setup_assistant.launch.py
```
GUI 里:
1. Load URDF
2. Add Virtual Joint(base_link → world)
3. Add Planning Group("arm",含 6 joint)
4. Add End Effector(gripper)
5. Add Poses(home / ready / up)
6. **Generate** SRDF + MoveIt config
### 10.2 SRDF 简例
```xml
...
...
```
---
## 11. 在本仓库里跑
### 11.1 启 3 关节机械臂 demo
```bash
docker exec ros2_dev bash -lc "source /root/ros2_ws/install/setup.bash && ros2 launch bringup robot_launch.py"
```
节点(launch 重命名后是 `joint_state_publisher` / `tf2_listener`,executable 名带 `_cpp`):
- `joint_state_publisher_cpp` (本包,executable 名)
- `robot_state_publisher` (系统包)
- `tf2_listener_cpp` (本包,executable 名)
### 11.2 校验本仓库 URDF
```bash
docker exec ros2_dev bash -lc "check_urdf /root/ros2_ws/install/cpp_robot_tf2/share/cpp_robot_tf2/urdf/simple_arm.urdf"
```
### 11.3 源码
- URDF: [`src/cpp_robot_tf2/urdf/simple_arm.urdf`](../src/cpp_robot_tf2/urdf/simple_arm.urdf)
- launch: [`src/cpp_robot_tf2/launch/robot_tf2_launch.py`](../src/cpp_robot_tf2/launch/robot_tf2_launch.py)
### 11.4 端到端日志
[`docker/robot_e2e.log`](../docker/robot_e2e.log)
---
## 12. 进阶:6-DoF 真机械臂 URDF 实战
### 12.1 找开源 URDF
| 机械臂 | URDF 来源 |
|---|---|
| Franka Panda | `ros-planning/moveit_resources/panda` |
| UR5 / UR10 | `ros-industrial/universal_robot` |
| Ufactory xArm 6 | `xArm-Robotics/xarm_ros2` |
| Aloha | `tonyzhaozh/aerial_manipulation` |
### 12.2 URDF 适配本仓库
把开源 URDF 拷到 `src//urdf/`:
```bash
cp -r /franka_description/urdf src/my_arm/urdf/
# 加 transmission(ros2_control 必填)
# 已经在开源版本里有,但要确认 hardwareInterface 是 PositionJointInterface
```
### 12.3 加 ros2_control 配置
`src/my_arm/config/controllers.yaml`:
```yaml
controller_manager:
ros__parameters:
update_rate: 100
joint_state_broadcaster:
type: joint_state_broadcaster/JointStateController
arm_controller:
type: position_controllers/JointGroupPositionController
arm_controller:
ros__parameters:
joints:
- joint1
- joint2
- joint3
- joint4
- joint5
- joint6
```
### 12.4 加 launch
`src/my_arm/launch/arm_bringup.launch.py`:
```python
from launch import LaunchDescription
from launch_ros.actions import Node
from ament_index_python.packages import get_package_share_directory
import os
def generate_launch_description():
pkg = get_package_share_directory('my_arm')
urdf = os.path.join(pkg, 'urdf', 'arm.urdf')
controllers = os.path.join(pkg, 'config', 'controllers.yaml')
with open(urdf, 'r') as f: urdf_content = f.read()
return LaunchDescription([
# 1) robot_state_publisher
Node(package='robot_state_publisher', executable='robot_state_publisher',
parameters=[{'robot_description': urdf_content}]),
# 2) ros2_control_node
Node(package='controller_manager', executable='ros2_control_node',
parameters=[{'robot_description': urdf_content,
'update_rate': 100}],
output='screen'),
# 3) spawn joint_state_broadcaster
Node(package='controller_manager', executable='spawner',
arguments=['joint_state_broadcaster', '-c', '/controller_manager']),
# 4) spawn arm_controller
Node(package='controller_manager', executable='spawner',
arguments=['arm_controller', '-c', '/controller_manager']),
])
```
### 12.5 加 MoveIt2
```bash
sudo apt install ros-humble-moveit
# 用 MoveIt Setup Assistant 加载你的 URDF 生成 SRDF
ros2 launch moveit_setup_assistant setup_assistant.launch.py
```
详见 [`99-embodied-ai.md`](99-embodied-ai.md) 阶段 2。
---
## 接下来读
| 主题 | 文档 |
|---|---|
| TF 坐标变换 | [`50-tf2.md`](50-tf2.md) |
| ros2_control + MoveIt2 | [`99-embodied-ai.md`](99-embodied-ai.md) 阶段 2 |
| launch 文件 | [`70-launch.md`](70-launch.md) |
| 三机部署 | [`100-embedded-deployment.md`](100-embedded-deployment.md) |
---
---
## 📖 阅读路径导航
> 💡 这是仓库 `doc/` 下所有文档的推荐阅读顺序。[返回 README 总导航](../README.md#-23-篇文档怎么读)
>
> ⏱ **本文预计阅读时间**: 60 分钟
> 📍 **当前位置**: 第 17 / 24 篇
- ⏮ **上一篇**: [坐标变换](50-tf2.md)
- ⏭ **下一篇**: [launch 文件系统](70-launch.md)