4. 机器人建模与URDF详解
各位同学,今天我们来聊聊机器人建模。说实话,URDF这东西,看着简单,但坑不少。我最早接触它的时候,以为就是写几个XML标签,结果在真实机器人上跑起来,关节乱转、碰撞检测失效,折腾了一整晚。嗯,从那以后,我养成了一个习惯——先在Rviz里把模型看透了,再往真机上搬。
4.1 URDF文件结构:link、joint、transmission
URDF,全称是Unified Robot Description Format。说白了,就是用一种标准化的方式,告诉机器人「你长什么样」。它由三个核心元素组成:link、joint、transmission。
4.1.1 link——机器人的「骨头」
每个link代表一个刚体部件。比如机械臂的基座、大臂、小臂、末端执行器。每个link需要定义:
- 视觉属性(visual):在Rviz里看到的样子。可以用STL或DAE网格文件,也可以用简单的几何体(box、cylinder、sphere)。我个人习惯先用几何体快速验证,最后再替换成精细的网格模型。
- 碰撞属性(collision):用于物理引擎和碰撞检测。注意,碰撞模型可以比视觉模型简单。我在项目中遇到过,用精细网格做碰撞检测,仿真直接卡成PPT。后来我把碰撞模型简化成圆柱体和长方体,速度提升了好几倍。
- 惯性属性(inertial):质量、质心、惯性张量。这个最容易出错。我曾经因为惯性参数随便填,导致仿真里的机械臂像面条一样软塌塌的。真实机器人的惯性参数,最好从CAD软件里导出,或者用实验辨识的方法获取。
<link name="base_link">
<visual>
<geometry>
<mesh filename="package://my_robot/meshes/base.stl"/>
</geometry>
<origin xyz="0 0 0" rpy="0 0 0"/>
</visual>
<collision>
<geometry>
<box size="0.3 0.3 0.1"/>
</geometry>
</collision>
<inertial>
<mass value="5.0"/>
<inertia ixx="0.1" ixy="0" ixz="0" iyy="0.1" iyz="0" izz="0.1"/>
</inertial>
</link>
4.1.2 joint——机器人的「关节」
joint连接两个link,定义了它们之间的相对运动关系。常见的类型有:
- revolute:旋转关节,像人的肘关节。需要指定旋转轴和角度范围。
- prismatic:平移关节,像抽屉的滑动。需要指定移动轴和行程范围。
- fixed:固定关节,两个link之间没有相对运动。比如基座和地面之间。
- continuous:无限旋转关节,比如车轮。
每个joint必须指定parent link和child link。这构成了机器人的运动学树。你想想看,如果parent和child搞反了,整个机器人的运动逻辑就全乱了。我刚开始学的时候,就犯过这个错——把大臂设成了小臂的parent,结果仿真里小臂带着大臂转,画面相当诡异。
<joint name="shoulder_joint" type="revolute">
<parent link="base_link"/>
<child link="shoulder_link"/>
<origin xyz="0 0 0.1" rpy="0 0 0"/>
<axis xyz="0 0 1"/>
<limit lower="-3.14" upper="3.14" effort="100" velocity="1.0"/>
</joint>
4.1.3 transmission——从关节到执行器
transmission定义了关节和实际执行器(电机、液压缸)之间的传动关系。比如减速比、机械效率等。这个在纯仿真里可以省略,但如果你要迁移到真实机器人,就必须加上。
为什么?因为真实电机有减速器,关节转1度,电机可能转了50度。如果不定义transmission,ROS的控制器会以为关节和电机是1:1的关系,控制精度会差很多。我在做六轴机械臂迁移时,就因为这个参数没配好,末端定位误差达到了5毫米。
<transmission name="shoulder_trans">
<type>transmission_interface/SimpleTransmission</type>
<joint name="shoulder_joint">
<hardwareInterface>hardware_interface/PositionJointInterface</hardwareInterface>
</joint>
<actuator name="shoulder_motor">
<mechanicalReduction>50</mechanicalReduction>
</actuator>
</transmission>
4.2 使用SolidWorks导出URDF
手动写URDF?对于简单模型还行。但一个真实的六轴机械臂,光link就有十几个,关节参数几十个,手写容易疯掉。所以,我推荐用SolidWorks导出。
步骤其实不复杂:
- 安装SW2URDF插件。这个插件是开源的,在ROS Wiki上可以找到。注意版本匹配,我遇到过SolidWorks 2020和插件不兼容的情况,折腾了半天。
- 在SolidWorks里定义坐标系。每个关节处都要建立一个坐标系,坐标系的Z轴指向关节旋转轴方向。这是最容易出错的地方。我记得有一次,坐标系Z轴方向反了,导出的URDF里关节旋转方向全是反的。
- 设置关节类型和范围。在插件界面里,为每个关节选择类型(revolute、prismatic等),并填入运动范围。
- 导出URDF和网格文件。插件会自动生成URDF文件和STL网格。导出的文件结构一般是:一个URDF文件,一个meshes文件夹放STL,一个config文件夹放配置。
4.3 在Rviz中可视化验证模型
URDF写好了,怎么知道对不对?Rviz就是你的「照妖镜」。我每次建完模型,第一件事就是在Rviz里打开看看。
启动方法很简单:
roslaunch urdf_tutorial display.launch model:=path/to/your.urdf
或者用更通用的方法:
rosrun rviz rviz
# 在Rviz中,添加RobotModel显示,并设置URDF参数为你的文件路径
在Rviz里,你需要重点检查几件事:
- 模型外观是否正确。各个link的位置、方向对不对?有没有奇怪的偏移或旋转?
- 关节运动是否正常。在Rviz的Joint State Publisher面板里,拖动关节滑块,看看运动是否流畅,方向是否正确。
- 碰撞模型是否合理。把显示模式切换到碰撞模型,看看有没有重叠或间隙过大的地方。
我曾经遇到过一个案例:导出的URDF在Rviz里显示正常,但一加载到Gazebo仿真里,机器人就塌了。后来发现,是惯性参数里惯性张量的值填错了。所以,Rviz验证只是第一步,物理仿真验证才是关键。
4.4 本章知识体系
下面这张图,是我自己整理的URDF建模知识体系。你可以把它当作一个检查清单,每次建模时对照着来。
好了,这一章的内容就到这里。URDF建模是仿真迁移的基础,你花时间把它搞扎实了,后面的路会顺很多。记住,先在Rviz里把模型看透了,再往真机上搬——这是我用无数次加班换来的教训。
核心要点回顾:
- link定义机器人的「骨头」,包括视觉、碰撞、惯性三个属性
- joint定义关节类型和运动关系,parent/child不能搞反
- transmission连接关节和执行器,真实机器人迁移时必须配置
- SolidWorks导出URDF可以大幅提高效率,但导出后要检查坐标
- Rviz是验证模型的第一道关卡,一定要养成习惯
可可精品资料库