机器人模型文件urdf介绍

发布于:2025-06-14 ⋅ 阅读:(25) ⋅ 点赞:(0)

一、什么是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>标签)

惯性参数需根据连杆质量和几何形状计算。对于立方体(边长:lxlylz,质量: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)避免常见错误: 

  • 确保关节的parentchild名称与已定义的连杆匹配。
  • 惯性矩阵需满足物理约束(如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 值。