机器人模型文件urdf介绍
一、什么是urdf文件
URDF 文件:机器人建模的标准描述格式
URDF(Unified Robot Description Format) 是一种用于描述机器人模型的 XML 格式文件,由 ROS(机器人操作系统)社区开发,主要用于定义机器人的几何结构、运动学特性、惯性参数等。它如同机器人的 “数字蓝图”,能被 ROS 系统解析并用于仿真、控制或可视化。urdf文件的后缀名可以是.urdf,也可以是.xml
二、怎么写urdf文件
我们以一个自己创建的极其简单的六自由度机器人urdf文件为例介绍urdf文件的撰写方式,下面是创建的机器人文件robot.xml代码:
下面是创建urdf机械臂在pybullet里面的可视化:
2.1 标签:文件根节点
每个 URDF 文件以开头,定义机器人的整体名称,并包含所有连杆和关节的定义。
2.2 标签:定义机器人连杆
描述机器人的刚体部件(如基座、手臂),包含可视化、碰撞检测和惯性参数:
- 可视化与碰撞模型:通常使用相同的几何形状,但碰撞模型可简化以提高性能。
- 惯性矩阵:需根据连杆质量和尺寸计算(见教程后文)。
2.3 标签:定义关节连接
描述连杆之间的连接方式和运动特性:
- 关节类型:
revolute
:旋转关节(如肩关节)prismatic
:平移关节(如滑块)fixed
:固定连接(无自由度)continuous
:无限制旋转关节floating
:浮动关节(6 自由度)
- origin 参数:
xyz
:位置偏移(米)rpy
:姿态偏移(弧度,按 Roll/Pitch/Yaw 顺序)
2.4 标签:定义材质
为连杆指定颜色或纹理:
- 材质可在多个连杆中复用。
2.5 计算惯性矩阵(标签)
惯性参数需根据连杆质量和几何形状计算。对于立方体(边长:lx
, ly
, lz
,质量:m
):
示例:边长为0.1 0.1 0.3
、质量为 3.0kg 的连杆:
2.6 坐标系与关节链设计
-
- URDF 默认使用右手坐标系(X 前、Y 左、Z 上)。
标签定义子坐标系相对于父坐标系的变换。
-
关节链规则:
- 从基座开始,按顺序定义连杆和关节。
- 每个关节连接一个父连杆和一个子连杆,形成树形结构。
2.7 最佳实践
(1)模块化设计:
- 按功能分组连杆和关节(如基座、大臂、小臂)。
- 使用注释分隔不同模块:
............
(2)参数校验:
- 使用
check_urdf
工具验证语法:
check_urdf your_robot.urdf
- 使用
urdf_to_graphiz
生成可视化结构图:
urdf_to_graphiz your_robot.urdf
(3)避免常见错误:
- 确保关节的
parent
和child
名称与已定义的连杆匹配。 - 惯性矩阵需满足物理约束(如
ixx + iyy > izz
)。
2.8 进阶技巧
-
合并重复定义:
若多个连杆使用相同材质,可将定义移至文件顶部复用。
-
使用 Xacro 扩展:
Xacro(XML 宏)可简化 URDF 编写,支持变量、数学运算和代码复用:
2.9 验证与调试
(1)可视化检查:
使用 RViz 查看机器人模型:
roslaunch urdf_tutorial display.launch model:=your_robot.urdf
(2)动力学仿真:
在 Gazebo 中测试机器人运动:
roslaunch gazebo_ros empty_world.launchrosrun gazebo_ros spawn_model -file your_robot.urdf -urdf -model my_robot
三、在pybullet中加载urdf文件
下面是main文件代码,使用 PyBullet 物理引擎实现了一个机器人的仿真控制。首先,它初始化了物理环境,设置重力并加载平面和机器人模型,然后调整相机视角以便观察。代码会打印机器人的关节信息并验证关节数量,接着通过关节名称获取目标关节的索引。之后设置了关节控制参数,包括目标位置和最大驱动力,并将关节初始化为指定位置。在主循环中,代码实现了周期性运动演示:前两个关节会随时间做正弦运动,其他关节保持固定位置,同时按照 240Hz 的频率进行仿真步进,让用户能直观看到机器人的运动状态。
import pybullet as pimport pybullet_dataimport mathimport time# 连接物理引擎physicsClient = p.connect(p.GUI)p.setAdditionalSearchPath(pybullet_data.getDataPath())p.setGravity(0, 0, -9.81)# 加载平面和机器人(确保文件名正确)planeId = p.loadURDF(\"plane.urdf\")robotId = p.loadURDF( \"robot.xml\", # 确保文件名与实际一致 basePosition=[0, 0, 0], baseOrientation=p.getQuaternionFromEuler([0, 0, 0]), useFixedBase=True)# 设置相机视角p.resetDebugVisualizerCamera( cameraDistance=1.5, cameraYaw=45, cameraPitch=-30, cameraTargetPosition=[0, 0, 0.3])# 打印关节信息print(\"机器人关节信息:\")for joint_idx in range(p.getNumJoints(robotId)): joint_info = p.getJointInfo(robotId, joint_idx) joint_name = joint_info[1].decode(\"utf-8\") joint_type = joint_info[2] print(f\"关节 {joint_idx}: {joint_name}, 类型: {joint_type}\")# 验证关节数量total_joints = p.getNumJoints(robotId)print(f\"机器人总关节数: {total_joints}\")# 通过关节名称获取索引(更可靠)joint_names = [\"joint1\", \"joint2\", \"joint3\", \"joint4\", \"joint5\", \"joint6\"]control_joints = []for name in joint_names: found = False for joint_idx in range(total_joints): joint_info = p.getJointInfo(robotId, joint_idx) if joint_info[1].decode(\"utf-8\") == name: control_joints.append(joint_idx) found = True break if not found: print(f\"警告: 未找到关节 \'{name}\'\")print(f\"控制的关节索引: {control_joints}\")# 关节控制参数target_positions = [0, 0.5, -1.0, 0, 0.5, 0] # 目标关节角度(弧度)max_forces = [50, 50, 30, 20, 10, 5] # 最大驱动力# 设置关节初始位置for i, joint_idx in enumerate(control_joints): p.resetJointState(robotId, joint_idx, target_positions[i])# 主循环while p.isConnected(): # 周期性运动演示 t = time.time() for i, joint_idx in enumerate(control_joints): # 关节1和2做周期性运动,其他关节保持固定 if i < 2: target_pos = 0.5 * math.sin(t * 0.5) + target_positions[i] else: target_pos = target_positions[i] p.setJointMotorControl2( bodyUniqueId=robotId, jointIndex=joint_idx, controlMode=p.POSITION_CONTROL, targetPosition=target_pos, force=max_forces[i] ) p.stepSimulation() time.sleep(1. / 240.) # 240Hz仿真频率
其中加载urdf文件的代码是这一段:
robotId = p.loadURDF( \"robot.xml\", # 确保文件名与实际一致 basePosition=[0, 0, 0], baseOrientation=p.getQuaternionFromEuler([0, 0, 0]), useFixedBase=True)
p.loadURDF()
参数:
-
fileName
:URDF 文件路径。 -
basePosition
:机器人基座的初始位置。 -
baseOrientation
:机器人基座的初始朝向(四元数表示)。 -
useFixedBase
:是否固定基座(如机械臂需固定,移动机器人则不需要)。
四、查看Franka Panda机械臂的urdf文件
我们查看一下franka panda机械臂的urdf文件。只要在pycharm里面安装了pybullet库,就会自动有franka panda的urdf文件,如果想到找到panda的urdf文件路径,可以运行下面代码获得
import pybullet_dataimport os# 获取panda.urdf文件的路径panda_urdf_path = os.path.join(pybullet_data.getDataPath(), \"franka_panda/panda.urdf\")# 打印文件路径print(panda_urdf_path)
在控制台就可以看到路径了
下面是打开的franka panda机械臂的urdf文件
Franka机械臂的urdf文件中大部分内容和我们在上面介绍过的知识都差不多,唯一不太相同的就是创建几何形状时的代码,不再是形式,因为这里的连杆不再是简单的长方体了,因此使用子标签来导入外部网格模型作为连杆的几何形状。
(1)
子标签:
用于导入外部网格模型作为连杆的几何形状,主要参数:
-
filename
:模型文件路径,使用 ROS 的package://
语法。
(2)package://
路径语法:
ROS 中特有的路径表示方式,格式为:
package:///
在本urdf文件中,package://meshes/collision/link0.obj
表示:
- 从名为
meshes
的 ROS 包中查找collision/link0.obj
文件。 - 实际物理路径可能是:
~/catkin_ws/src/meshes/collision/link0.obj
。
还有一个不同的就是设置了关节安全控制约束,
是 URDF(Unified Robot Description Format)中用于描述关节安全控制参数的标签。
其属性含义如下:
k_position
:用于说明位置和速度之间的关系,一旦某个关节要接近极限位置的时候,它能对同向位置施加的同向速度便更小,而对阻碍它运动的异向速度则可以更大。k_velocity
:用于说明力和速度之间的关系,一旦某个方向的关节速度过大,则能对同向速度施加的同向扭矩便更小,而对阻碍它运动的扭矩(即异向扭矩)则可以更大。soft_lower_limit
:指定了关节安全控制边界的下界,是关节安全控制的起始限制点,这个值需要大于标签中的
lower
值。soft_upper_limit
:指定了关节安全控制边界的上界,是关节安全控制的起始限制点,这个值需要小于标签中的
upper
值。