一、什么是urdf文件
URDF 文件:机器人建模的标准描述格式
URDF(Unified Robot Description Format) 是一种用于描述机器人模型的 XML 格式文件,由 ROS(机器人操作系统)社区开发,主要用于定义机器人的几何结构、运动学特性、惯性参数等。它如同机器人的 “数字蓝图”,能被 ROS 系统解析并用于仿真、控制或可视化。urdf文件的后缀名可以是.urdf,也可以是.xml
二、怎么写urdf文件
我们以一个自己创建的极其简单的六自由度机器人urdf文件为例介绍urdf文件的撰写方式,下面是创建的机器人文件robot.xml代码:
<?xml version="1.0"?>
<robot name="simple_robot">
<!--自己创建的简单的六自由度机械臂-->
<!-- 基座 -->
<link name="base_link">
<visual>
<geometry>
<box size="0.2 0.2 0.1"/>
</geometry>
<material name="gray">
<color rgba="0.7 0.7 0.7 1"/>
</material>
</visual>
<collision>
<geometry>
<box size="0.2 0.2 0.1"/>
</geometry>
</collision>
<inertial>
<mass value="5.0"/>
<inertia ixx="0.01" ixy="0" ixz="0" iyy="0.01" iyz="0" izz="0.005"/>
</inertial>
</link>
<!-- 关节1 - 旋转基座 -->
<joint name="joint1" type="revolute">
<parent link="base_link"/>
<child link="link1"/>
<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.5"/>
</joint>
<!-- 连杆1 -->
<link name="link1">
<visual>
<geometry>
<box size="0.1 0.1 0.3"/>
</geometry>
<material name="blue">
<color rgba="0 0 0.8 1"/>
</material>
</visual>
<collision>
<geometry>
<box size="0.1 0.1 0.3"/>
</geometry>
</collision>
<inertial>
<mass value="3.0"/>
<inertia ixx="0.03" ixy="0" ixz="0" iyy="0.03" iyz="0" izz="0.005"/>
</inertial>
</link>
<!-- 关节2 - 肩部俯仰 -->
<joint name="joint2" type="revolute">
<parent link="link1"/>
<child link="link2"/>
<origin xyz="0 0 0.3" rpy="0 1.5708 0"/>
<axis xyz="0 1 0"/>
<limit lower="-1.57" upper="1.0" effort="100" velocity="1.5"/>
</joint>
<!-- 连杆2 -->
<link name="link2">
<visual>
<geometry>
<box size="0.08 0.08 0.4"/>
</geometry>
<material name="blue">
<color rgba="0 0 0.8 1"/>
</material>
</visual>
<collision>
<geometry>
<box size="0.08 0.08 0.4"/>
</geometry>
</collision>
<inertial>
<mass value="2.5"/>
<inertia ixx="0.02" ixy="0" ixz="0" iyy="0.02" iyz="0" izz="0.003"/>
</inertial>
</link>
<!-- 关节3 - 肘部俯仰 -->
<joint name="joint3" type="revolute">
<parent link="link2"/>
<child link="link3"/>
<origin xyz="0 0 0.4" rpy="0 1.5708 0"/>
<axis xyz="0 1 0"/>
<limit lower="-2.0" upper="0.5" effort="80" velocity="1.5"/>
</joint>
<!-- 连杆3 -->
<link name="link3">
<visual>
<geometry>
<box size="0.06 0.06 0.35"/>
</geometry>
<material name="blue">
<color rgba="0 0 0.8 1"/>
</material>
</visual>
<collision>
<geometry>
<box size="0.06 0.06 0.35"/>
</geometry>
</collision>
<inertial>
<mass value="2.0"/>
<inertia ixx="0.015" ixy="0" ixz="0" iyy="0.015" iyz="0" izz="0.002"/>
</inertial>
</link>
<!-- 关节4 - 腕部旋转 -->
<joint name="joint4" type="revolute">
<parent link="link3"/>
<child link="link4"/>
<origin xyz="0 0 0.35" rpy="0 0 0"/>
<axis xyz="0 0 1"/>
<limit lower="-3.14" upper="3.14" effort="50" velocity="2.0"/>
</joint>
<!-- 连杆4 -->
<link name="link4">
<visual>
<geometry>
<box size="0.05 0.05 0.2"/>
</geometry>
<material name="blue">
<color rgba="0 0 0.8 1"/>
</material>
</visual>
<collision>
<geometry>
<box size="0.05 0.05 0.2"/>
</geometry>
</collision>
<inertial>
<mass value="1.0"/>
<inertia ixx="0.005" ixy="0" ixz="0" iyy="0.005" iyz="0" izz="0.001"/>
</inertial>
</link>
<!-- 关节5 - 腕部俯仰 -->
<joint name="joint5" type="revolute">
<parent link="link4"/>
<child link="link5"/>
<origin xyz="0 0 0.2" rpy="1.5708 0 0"/>
<axis xyz="1 0 0"/>
<limit lower="-1.57" upper="1.57" effort="50" velocity="2.0"/>
</joint>
<!-- 连杆5 -->
<link name="link5">
<visual>
<geometry>
<box size="0.05 0.05 0.15"/>
</geometry>
<material name="blue">
<color rgba="0 0 0.8 1"/>
</material>
</visual>
<collision>
<geometry>
<box size="0.05 0.05 0.15"/>
</geometry>
</collision>
<inertial>
<mass value="0.8"/>
<inertia ixx="0.003" ixy="0" ixz="0" iyy="0.003" iyz="0" izz="0.0005"/>
</inertial>
</link>
<!-- 关节6 - 腕部偏航 -->
<joint name="joint6" type="revolute">
<parent link="link5"/>
<child link="end_effector_link"/>
<origin xyz="0 0 0.15" rpy="0 0 0"/>
<axis xyz="0 0 1"/>
<limit lower="-3.14" upper="3.14" effort="30" velocity="2.5"/>
</joint>
<!-- 末端执行器连接座 -->
<link name="end_effector_link">
<visual>
<geometry>
<box size="0.06 0.06 0.05"/>
</geometry>
<material name="red">
<color rgba="0.8 0 0 1"/>
</material>
</visual>
<collision>
<geometry>
<box size="0.06 0.06 0.05"/>
</geometry>
</collision>
<inertial>
<mass value="0.5"/>
<inertia ixx="0.001" ixy="0" ixz="0" iyy="0.001" iyz="0" izz="0.0005"/>
</inertial>
</link>
</robot>
下面是创建urdf机械臂在pybullet里面的可视化:
2.1 <robot>标签:文件根节点
每个 URDF 文件以<robot name="机器人名称">
开头,定义机器人的整体名称,并包含所有连杆和关节的定义。
<robot name="simple_robot">
<!-- 机器人的所有组件定义 -->
</robot>
2.2 <link>标签:定义机器人连杆
描述机器人的刚体部件(如基座、手臂),包含可视化、碰撞检测和惯性参数:
<link name="base_link">
<!-- 可视化模型:定义外观 -->
<visual>
<geometry><box size="0.2 0.2 0.1"/></geometry>
<material name="gray"><color rgba="0.7 0.7 0.7 1"/></material>
</visual>
<!-- 碰撞模型:定义物理碰撞体积 -->
<collision>
<geometry><box size="0.2 0.2 0.1"/></geometry>
</collision>
<!-- 惯性参数:质量和转动惯量 -->
<inertial>
<mass value="5.0"/>
<inertia ixx="0.01" ixy="0" ixz="0" iyy="0.01" iyz="0" izz="0.005"/>
</inertial>
</link>
- 可视化与碰撞模型:通常使用相同的几何形状,但碰撞模型可简化以提高性能。
- 惯性矩阵:需根据连杆质量和尺寸计算(见教程后文)。
2.3 <joint>标签:定义关节连接
描述连杆之间的连接方式和运动特性:
<joint name="joint1" type="revolute">
<parent link="base_link"/> <!-- 父连杆名称 -->
<child link="link1"/> <!-- 子连杆名称 -->
<origin xyz="0 0 0.1" rpy="0 0 0"/> <!-- 关节在父连杆坐标系中的位置和姿态 -->
<axis xyz="0 0 1"/> <!-- 旋转轴(revolute类型)或平移方向(prismatic类型) -->
<limit lower="-3.14" upper="3.14" effort="100" velocity="1.5"/> <!-- 运动范围和限制 -->
</joint>
- 关节类型:
revolute
:旋转关节(如肩关节)prismatic
:平移关节(如滑块)fixed
:固定连接(无自由度)continuous
:无限制旋转关节floating
:浮动关节(6 自由度)
- origin 参数:
xyz
:位置偏移(米)rpy
:姿态偏移(弧度,按 Roll/Pitch/Yaw 顺序)
2.4 <material>标签:定义材质
为连杆指定颜色或纹理:
<material name="gray">
<color rgba="0.7 0.7 0.7 1"/> <!-- RGB颜色值(0-1)和透明度 -->
</material>
- 材质可在多个连杆中复用。
2.5 计算惯性矩阵(<inertia>标签)
惯性参数需根据连杆质量和几何形状计算。对于立方体(边长:lx
, ly
, lz
,质量:m
):
<inertial>
<mass value="m"/>
<inertia
ixx="m*(ly²+lz²)/12"
ixy="0"
ixz="0"
iyy="m*(lx²+lz²)/12"
iyz="0"
izz="m*(lx²+ly²)/12"
/>
</inertial>
示例:边长为0.1 0.1 0.3
、质量为 3.0kg 的连杆:
<inertia ixx="0.03" ixy="0" ixz="0" iyy="0.03" iyz="0" izz="0.005"/>
2.6 坐标系与关节链设计
-
- URDF 默认使用右手坐标系(X 前、Y 左、Z 上)。
<origin>
标签定义子坐标系相对于父坐标系的变换。
关节链规则:
- 从基座开始,按顺序定义连杆和关节。
- 每个关节连接一个父连杆和一个子连杆,形成树形结构。
2.7 最佳实践
(1)模块化设计:
- 按功能分组连杆和关节(如基座、大臂、小臂)。
- 使用注释分隔不同模块:
<!-- 基座部分 -->
<link name="base_link">...</link>
<joint name="joint1">...</joint>
<!-- 大臂部分 -->
<link name="link1">...</link>
<joint name="joint2">...</joint>
(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 进阶技巧
合并重复定义:
若多个连杆使用相同材质,可将<material>
定义移至文件顶部复用。使用 Xacro 扩展:
Xacro(XML 宏)可简化 URDF 编写,支持变量、数学运算和代码复用:
<!-- Xacro示例:定义可复用的立方体连杆 -->
<xacro:macro name="box_link" params="name size mass color">
<link name="${name}">
<visual>
<geometry><box size="${size}"/></geometry>
<material name="${color}"/>
</visual>
<!-- 其他属性 -->
</link>
</xacro:macro>
2.9 验证与调试
(1)可视化检查:
使用 RViz 查看机器人模型:
roslaunch urdf_tutorial display.launch model:=your_robot.urdf
(2)动力学仿真:
在 Gazebo 中测试机器人运动:
roslaunch gazebo_ros empty_world.launch
rosrun gazebo_ros spawn_model -file your_robot.urdf -urdf -model my_robot
三、在pybullet中加载urdf文件
下面是main文件代码,使用 PyBullet 物理引擎实现了一个机器人的仿真控制。首先,它初始化了物理环境,设置重力并加载平面和机器人模型,然后调整相机视角以便观察。代码会打印机器人的关节信息并验证关节数量,接着通过关节名称获取目标关节的索引。之后设置了关节控制参数,包括目标位置和最大驱动力,并将关节初始化为指定位置。在主循环中,代码实现了周期性运动演示:前两个关节会随时间做正弦运动,其他关节保持固定位置,同时按照 240Hz 的频率进行仿真步进,让用户能直观看到机器人的运动状态。
import pybullet as p
import pybullet_data
import math
import 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_data
import os
# 获取panda.urdf文件的路径
panda_urdf_path = os.path.join(pybullet_data.getDataPath(), "franka_panda/panda.urdf")
# 打印文件路径
print(panda_urdf_path)
在控制台就可以看到路径了
下面是打开的franka panda机械臂的urdf文件
<?xml version="1.0" ?>
<!-- =================================================================================== -->
<!-- | This document was autogenerated by xacro from panda_arm_hand.urdf.xacro | -->
<!-- | EDITING THIS FILE BY HAND IS NOT RECOMMENDED | -->
<!-- =================================================================================== -->
<robot name="panda" xmlns:xacro="http://www.ros.org/wiki/xacro">
<link name="panda_link0">
<inertial>
<origin rpy="0 0 0" xyz="0 0 0.05"/>
<mass value="2.9"/>
<inertia ixx="0.1" ixy="0" ixz="0" iyy="0.1" iyz="0" izz="0.1"/>
</inertial>
<visual>
<geometry>
<mesh filename="package://meshes/collision/link0.obj"/>
</geometry>
<material name="panda_white">
<color rgba="1. 1. 1. 1."/>
</material>
</visual>
<collision>
<geometry>
<mesh filename="package://meshes/collision/link0.obj"/>
</geometry>
<material name="panda_white"/>
</collision>
</link>
<link name="panda_link1">
<inertial>
<origin rpy="0 0 0" xyz="0 -0.04 -0.05"/>
<mass value="2.7"/>
<inertia ixx="0.1" ixy="0" ixz="0" iyy="0.1" iyz="0" izz="0.1"/>
</inertial>
<visual>
<geometry>
<mesh filename="package://meshes/visual/link1.obj"/>
</geometry>
<material name="panda_white"/>
</visual>
<collision>
<geometry>
<mesh filename="package://meshes/collision/link1.obj"/>
</geometry>
<material name="panda_white"/>
</collision>
</link>
<joint name="panda_joint1" type="revolute">
<safety_controller k_position="100.0" k_velocity="40.0" soft_lower_limit="-2.8973" soft_upper_limit="2.8973"/>
<origin rpy="0 0 0" xyz="0 0 0.333"/>
<parent link="panda_link0"/>
<child link="panda_link1"/>
<axis xyz="0 0 1"/>
<limit effort="87" lower="-2.9671" upper="2.9671" velocity="2.1750"/>
</joint>
<link name="panda_link2">
<inertial>
<origin rpy="0 0 0" xyz="0 -0.04 0.06"/>
<mass value="2.73"/>
<inertia ixx="0.1" ixy="0" ixz="0" iyy="0.1" iyz="0" izz="0.1"/>
</inertial>
<visual>
<geometry>
<mesh filename="package://meshes/visual/link2.obj"/>
</geometry>
<material name="panda_white"/>
</visual>
<collision>
<geometry>
<mesh filename="package://meshes/collision/link2.obj"/>
</geometry>
<material name="panda_white"/>
</collision>
</link>
<joint name="panda_joint2" type="revolute">
<safety_controller k_position="100.0" k_velocity="40.0" soft_lower_limit="-1.7628" soft_upper_limit="1.7628"/>
<origin rpy="-1.57079632679 0 0" xyz="0 0 0"/>
<parent link="panda_link1"/>
<child link="panda_link2"/>
<axis xyz="0 0 1"/>
<limit effort="87" lower="-1.8326" upper="1.8326" velocity="2.1750"/>
</joint>
<link name="panda_link3">
<inertial>
<origin rpy="0 0 0" xyz="0.01 0.01 -0.05"/>
<mass value="2.04"/>
<inertia ixx="0.1" ixy="0" ixz="0" iyy="0.1" iyz="0" izz="0.1"/>
</inertial>
<visual>
<geometry>
<mesh filename="package://meshes/visual/link3.obj"/>
</geometry>
<material name="panda_red">
<color rgba="1. 1. 1. 1."/>
</material>
</visual>
<collision>
<geometry>
<mesh filename="package://meshes/collision/link3.obj"/>
</geometry>
</collision>
</link>
<joint name="panda_joint3" type="revolute">
<safety_controller k_position="100.0" k_velocity="40.0" soft_lower_limit="-2.8973" soft_upper_limit="2.8973"/>
<origin rpy="1.57079632679 0 0" xyz="0 -0.316 0"/>
<parent link="panda_link2"/>
<child link="panda_link3"/>
<axis xyz="0 0 1"/>
<limit effort="87" lower="-2.9671" upper="2.9671" velocity="2.1750"/>
</joint>
<link name="panda_link4">
<inertial>
<origin rpy="0 0 0" xyz="-0.03 0.03 0.02"/>
<mass value="2.08"/>
<inertia ixx="0.1" ixy="0" ixz="0" iyy="0.1" iyz="0" izz="0.1"/>
</inertial>
<visual>
<geometry>
<mesh filename="package://meshes/visual/link4.obj"/>
</geometry>
<material name="panda_white"/>
</visual>
<collision>
<geometry>
<mesh filename="package://meshes/collision/link4.obj"/>
</geometry>
<material name="panda_white"/>
</collision>
</link>
<joint name="panda_joint4" type="revolute">
<safety_controller k_position="100.0" k_velocity="40.0" soft_lower_limit="-3.0718" soft_upper_limit="-0.0698"/>
<origin rpy="1.57079632679 0 0" xyz="0.0825 0 0"/>
<parent link="panda_link3"/>
<child link="panda_link4"/>
<axis xyz="0 0 1"/>
<limit effort="87" lower="-3.1416" upper="0.0" velocity="2.1750"/>
</joint>
<link name="panda_link5">
<inertial>
<origin rpy="0 0 0" xyz="0 0.04 -0.12"/>
<mass value="3"/>
<inertia ixx="0.1" ixy="0" ixz="0" iyy="0.1" iyz="0" izz="0.1"/>
</inertial>
<visual>
<geometry>
<mesh filename="package://meshes/visual/link5.obj"/>
</geometry>
<material name="panda_white"/>
</visual>
<collision>
<geometry>
<mesh filename="package://meshes/collision/link5.obj"/>
</geometry>
<material name="panda_white"/>
</collision>
</link>
<joint name="panda_joint5" type="revolute">
<safety_controller k_position="100.0" k_velocity="40.0" soft_lower_limit="-2.8973" soft_upper_limit="2.8973"/>
<origin rpy="-1.57079632679 0 0" xyz="-0.0825 0.384 0"/>
<parent link="panda_link4"/>
<child link="panda_link5"/>
<axis xyz="0 0 1"/>
<limit effort="12" lower="-2.9671" upper="2.9671" velocity="2.6100"/>
</joint>
<link name="panda_link6">
<inertial>
<origin rpy="0 0 0" xyz="0.04 0 0"/>
<mass value="1.3"/>
<inertia ixx="0.1" ixy="0" ixz="0" iyy="0.1" iyz="0" izz="0.1"/>
</inertial>
<visual>
<geometry>
<mesh filename="package://meshes/visual/link6.obj"/>
</geometry>
<material name="panda_white"/>
</visual>
<collision>
<geometry>
<mesh filename="package://meshes/collision/link6.obj"/>
</geometry>
<material name="panda_white"/>
</collision>
</link>
<joint name="panda_joint6" type="revolute">
<safety_controller k_position="100.0" k_velocity="40.0" soft_lower_limit="-0.0175" soft_upper_limit="3.7525"/>
<origin rpy="1.57079632679 0 0" xyz="0 0 0"/>
<parent link="panda_link5"/>
<child link="panda_link6"/>
<axis xyz="0 0 1"/>
<limit effort="12" lower="-0.0873" upper="3.8223" velocity="2.6100"/>
</joint>
<link name="panda_link7">
<inertial>
<origin rpy="0 0 0" xyz="0 0 0.08"/>
<mass value=".2"/>
<inertia ixx="0.1" ixy="0" ixz="0" iyy="0.1" iyz="0" izz="0.1"/>
</inertial>
<visual>
<geometry>
<mesh filename="package://meshes/collision/link7.obj"/>
</geometry>
<material name="panda_white"/>
</visual>
<collision>
<geometry>
<mesh filename="package://meshes/collision/link7.obj"/>
</geometry>
<material name="panda_white"/>
</collision>
</link>
<joint name="panda_joint7" type="revolute">
<safety_controller k_position="100.0" k_velocity="40.0" soft_lower_limit="-2.8973" soft_upper_limit="2.8973"/>
<origin rpy="1.57079632679 0 0" xyz="0.088 0 0"/>
<parent link="panda_link6"/>
<child link="panda_link7"/>
<axis xyz="0 0 1"/>
<limit effort="12" lower="-2.9671" upper="2.9671" velocity="2.6100"/>
</joint>
<link name="panda_link8">
<inertial>
<origin rpy="0 0 0" xyz="0 0 0"/>
<mass value="0.0"/>
<inertia ixx="0.1" ixy="0" ixz="0" iyy="0.1" iyz="0" izz="0.1"/>
</inertial>
</link>
<joint name="panda_joint8" type="fixed">
<origin rpy="0 0 0" xyz="0 0 0.107"/>
<parent link="panda_link7"/>
<child link="panda_link8"/>
<axis xyz="0 0 0"/>
</joint>
<joint name="panda_hand_joint" type="fixed">
<parent link="panda_link8"/>
<child link="panda_hand"/>
<origin rpy="0 0 -0.785398163397" xyz="0 0 0"/>
</joint>
<link name="panda_hand">
<inertial>
<origin rpy="0 0 0" xyz="0 0 0.04"/>
<mass value=".81"/>
<inertia ixx="0.1" ixy="0" ixz="0" iyy="0.1" iyz="0" izz="0.1"/>
</inertial>
<visual>
<geometry>
<mesh filename="package://meshes/visual/hand.obj"/>
</geometry>
<material name="panda_white"/>
</visual>
<collision>
<geometry>
<mesh filename="package://meshes/collision/hand.obj"/>
</geometry>
<material name="panda_white"/>
</collision>
</link>
<link name="panda_leftfinger">
<contact>
<friction_anchor/>
<stiffness value="30000.0"/>
<damping value="1000.0"/>
<spinning_friction value="0.1"/>
<lateral_friction value="1.0"/>
</contact>
<inertial>
<origin rpy="0 0 0" xyz="0 0.01 0.02"/>
<mass value="0.1"/>
<inertia ixx="0.1" ixy="0" ixz="0" iyy="0.1" iyz="0" izz="0.1"/>
</inertial>
<visual>
<geometry>
<mesh filename="package://meshes/visual/finger.obj"/>
</geometry>
<material name="panda_white"/>
</visual>
<collision>
<geometry>
<mesh filename="package://meshes/collision/finger.obj"/>
</geometry>
<material name="panda_white"/>
</collision>
</link>
<link name="panda_rightfinger">
<contact>
<friction_anchor/>
<stiffness value="30000.0"/>
<damping value="1000.0"/>
<spinning_friction value="0.1"/>
<lateral_friction value="1.0"/>
</contact>
<inertial>
<origin rpy="0 0 0" xyz="0 -0.01 0.02"/>
<mass value="0.1"/>
<inertia ixx="0.1" ixy="0" ixz="0" iyy="0.1" iyz="0" izz="0.1"/>
</inertial>
<visual>
<origin rpy="0 0 3.14159265359" xyz="0 0 0"/>
<geometry>
<mesh filename="package://meshes/visual/finger.obj"/>
</geometry>
<material name="panda_white"/>
</visual>
<collision>
<origin rpy="0 0 3.14159265359" xyz="0 0 0"/>
<geometry>
<mesh filename="package://meshes/collision/finger.obj"/>
</geometry>
<material name="panda_white"/>
</collision>
</link>
<joint name="panda_finger_joint1" type="prismatic">
<parent link="panda_hand"/>
<child link="panda_leftfinger"/>
<origin rpy="0 0 0" xyz="0 0 0.0584"/>
<axis xyz="0 1 0"/>
<limit effort="20" lower="0.0" upper="0.04" velocity="0.2"/>
</joint>
<joint name="panda_finger_joint2" type="prismatic">
<parent link="panda_hand"/>
<child link="panda_rightfinger"/>
<origin rpy="0 0 0" xyz="0 0 0.0584"/>
<axis xyz="0 -1 0"/>
<limit effort="20" lower="0.0" upper="0.04" velocity="0.2"/>
<mimic joint="panda_finger_joint1"/>
</joint>
<link name="panda_grasptarget">
<inertial>
<origin rpy="0 0 0" xyz="0 0 0"/>
<mass value="0.0"/>
<inertia ixx="0.1" ixy="0" ixz="0" iyy="0.1" iyz="0" izz="0.1"/>
</inertial>
</link>
<joint name="panda_grasptarget_hand" type="fixed">
<parent link="panda_hand"/>
<child link="panda_grasptarget"/>
<origin rpy="0 0 0" xyz="0 0 0.105"/>
</joint>
</robot>
Franka机械臂的urdf文件中大部分内容和我们在上面介绍过的知识都差不多,唯一不太相同的就是创建几何形状时的代码,不再是<box size="0.2 0.2 0.1"/>形式,因为这里的连杆不再是简单的长方体了,因此使用<mesh>子标签来导入外部网格模型作为连杆的几何形状。
<geometry>
<mesh filename="package://meshes/collision/link0.obj"/>
</geometry>
(1)<mesh>
子标签:
用于导入外部网格模型作为连杆的几何形状,主要参数:
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
。
还有一个不同的就是设置了关节安全控制约束,<safety_controller>
是 URDF(Unified Robot Description Format)中用于描述关节安全控制参数的标签。
<safety_controller k_position="100.0" k_velocity="40.0" soft_lower_limit="-2.8973" soft_upper_limit="2.8973"/>
其属性含义如下:
k_position
:用于说明位置和速度之间的关系,一旦某个关节要接近极限位置的时候,它能对同向位置施加的同向速度便更小,而对阻碍它运动的异向速度则可以更大。k_velocity
:用于说明力和速度之间的关系,一旦某个方向的关节速度过大,则能对同向速度施加的同向扭矩便更小,而对阻碍它运动的扭矩(即异向扭矩)则可以更大。soft_lower_limit
:指定了关节安全控制边界的下界,是关节安全控制的起始限制点,这个值需要大于<limit>
标签中的lower
值。soft_upper_limit
:指定了关节安全控制边界的上界,是关节安全控制的起始限制点,这个值需要小于<limit>
标签中的upper
值。