URDF 机器人建模完全指南

ROS
4.5k 词

从零掌握 URDF 建模:基础结构、xacro 宏、Transmission、Fusion360 导出及常见问题。

一、URDF 基础结构

一个 link 包含三个核心标签:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<link name="car_link">
<!-- 可视化:在图形界面中显示 -->
<visual>
<geometry>
<box size="2.0 1.0 0.5"/>
</geometry>
</visual>

<!-- 碰撞检测:传感器和物理引擎使用 -->
<collision>
<geometry>
<box size="2.0 1.0 0.5"/>
</geometry>
</collision>

<!-- 惯性:物理引擎需要(Gazebo 中极其重要) -->
<inertial>
<origin xyz="0 0 0" rpy="0 0 0"/>
<mass value="1.0"/>
<inertia ixx="0.02" ixy="0" ixz="0" iyy="0.02" iyz="0" izz="0.02"/>
</inertial>
</link>
标签 作用 缺失后果
visual 图形界面显示 看不到模型
collision 传感器/碰撞检测 激光雷达穿透、不碰撞
inertial 物理引擎驱动 Gazebo 中无法驱动

geometry 支持的类型

1
2
3
4
<box size="x y z"/>           <!-- 立方体 -->
<cylinder radius="r" length="l"/> <!-- 圆柱 -->
<sphere radius="r"/> <!-- 球体 -->
<mesh filename="package://pkg/meshes/model.stl"/> <!-- 自定义模型 -->

自定义 STL 文件时,尽量用碰撞箱包裹——STL 碰撞面复杂得多,严重影响仿真性能。

1
2
3
4
5
6
7
<joint name="joint_name" type="revolute">
<origin xyz="0 0 0.1" rpy="0 0 0"/>
<parent link="base_link"/>
<child link="child_link"/>
<axis xyz="0 0 1"/>
<limit lower="-1.57" upper="1.57" effort="10" velocity="3.14"/>
</joint>

Joint 类型:

type 说明 自由度
fixed 固定连接 0
revolute 旋转关节(有角度限制) 1
continuous 连续旋转(无限制) 1
prismatic 滑动关节 1
floating 6 自由度浮动 6

三、xacro 宏:消除重复

当有多个相同部件(如四个轮子),使用 xacro 宏:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<xacro:macro name="wheel" params="name prefix">
<link name="${prefix}_${name}_wheel">
<inertial>
<mass value="0.5"/>
<inertia ixx="0.001" ixy="0" ixz="0" iyy="0.001" iyz="0" izz="0.001"/>
</inertial>
<visual>
<geometry>
<cylinder radius="0.05" length="0.02"/>
</geometry>
</visual>
</link>
</xacro:macro>

<!-- 使用 -->
<xacro:wheel name="front_left" prefix="my_robot"/>
<xacro:wheel name="front_right" prefix="my_robot"/>

四、Transmission:连接驱动与仿真

Transmission 是 URDF 和 ros_control 之间的桥梁——当物理引擎中驱动设备动作时,ROS 知道哪个 TF 需要变化。

1
2
3
4
5
6
7
8
9
10
<transmission name="wheel_trans">
<type>transmission_interface/SimpleTransmission</type>
<joint name="wheel_joint">
<hardwareInterface>EffortJointInterface</hardwareInterface>
</joint>
<actuator name="wheel_motor">
<mechanicalReduction>50</mechanicalReduction>
<hardwareInterface>EffortJointInterface</hardwareInterface>
</actuator>
</transmission>

控制器与硬件接口对应:

接口 控制器
EffortJointInterface joint_effort_controller
VelocityJointInterface joint_velocity_controller
PositionJointInterface joint_position_controller
Joint State joint_state_controller

还需在 URDF 中添加 ros_control 插件:

1
2
3
4
5
<gazebo>
<plugin name="gazebo_ros_control" filename="libgazebo_ros_control.so">
<robotNamespace>/my_robot</robotNamespace>
</plugin>
</gazebo>

五、手动建模要点

当脚本无法处理复杂模型时,需要手动编写 URDF:

属性设置顺序

1
link(inertial) → joint → link(visual/collision) → 子 link...

关键注意事项

  1. base_link 位置:排除轮子后车体的质心位置
  2. 惯性矩换算:Fusion360 给出的值需 ×10⁻⁹(如 689.2 → 6.892E-07)
  3. 质心 vs 原点:选择相对于质心的惯性,而非相对于原点的
  4. 碰撞简化:用碰撞箱代替 STL,STL 碰撞面复杂会导致仿真卡顿
  5. STL 缩放:若机械给的是米制 STL,需 scale="0.001 0.001 0.001";毫米制则不需要
  6. 单个 STL 小于 2MB:过大文件严重影响运行

六、Fusion360 脚本导出

使用 fusion2urdf 脚本自动导出。

建模规范

  • 一个零部件只能包含一个实体,不能有内部零部件
  • 零部件命名只能字母或数字(Gazebo 要求)
  • 不允许快速联接,只允许刚体/旋转/滑动联接
  • 联接时按子-父顺序,不能弄反
  • 不要鼠标拖动位置——用参数精确设置
  • 必须有一个零部件命名为 base_link

常见问题

RViz 报错 “root link has inertia”:

1
2
The root link base_link has an inertia specified in the URDF, 
but KDL does not support a root link with an inertia.

解法:添加一个空属性的虚拟 link:

1
2
3
4
5
<link name="dummy"></link>
<joint name="dummy_joint" type="fixed">
<parent link="dummy"/>
<child link="base_link"/>
</joint>

模型灰白无色:

检查是否安装 joint_state_publisher

1
sudo apt-get install ros-noetic-joint-state-publisher

Controller Spawner 找不到 controller_manager:

把 launch 文件中的 spawner 换成 controller_manager

1
2
3
4
5
<!-- 改前 -->
<node name="controller_spawner" pkg="controller_manager" type="spawner" .../>

<!-- 改后 -->
<node name="controller_manager" pkg="controller_manager" type="controller_manager" .../>