URDF创建
1、URDF基本语法
URDF 文件是一个标准的 XML 文件,XML文件定义了一系列的标签用于描述机器人模型,机器人模型可能较为复杂,但URDF 中机器人的组成却是较为简单,可以主要简化为两部分:连杆(link标签) 与关节(joint标签),接下来我们就通过案例了解一下 URDF 中的不同标签:
1.1 robot 根标签
urdf 中为了保证 xml 语法的完整性,使用了robot
标签作为根标签,所有的 link 和 joint 以及其他标签都必须包含在 robot 标签内,在该标签内可以通过 name 属性设置机器人模型的名称
(1)属性
name: 指定机器人模型的名称
(2)子标签
其他标签都是子级标签
1.2 link 连杆标签
urdf 中的 link 标签用于描述机器人某个部件(也即刚体部分)的外观和物理属性,比如: 机器人底座、轮子、激光雷达、摄像头…每一个部件都对应一个 link, 在 link 标签内,可以设计该部件的形状、尺寸、颜色、惯性矩阵、碰撞参数等一系列属性
(1)属性
- name —> 为连杆命名
(2)子标签
-
visual —> 描述外观(对应的数据是可视的)
-
-
geometry 设置连杆的形状
-
-
标签1: box(盒状)
-
- 属性:size=长(x) 宽(y) 高(z)
-
标签2: cylinder(圆柱)
-
- 属性:radius=半径 length=高度
-
标签3: sphere(球体)
-
- 属性:radius=半径
-
标签4: mesh(为连杆添加皮肤)
-
- 属性: filename=资源路径(格式:package:///
/文件 )
- 属性: filename=资源路径(格式:package:///
-
-
origin 设置偏移量与倾斜弧度
-
- 属性1: xyz=x偏移 y偏移 z偏移
- 属性2: rpy=x翻滚 y俯仰 z偏航 (单位是弧度)
-
metrial 设置材料属性(颜色)
-
-
属性: name
-
标签: color
-
- 属性: rgba=红绿蓝权重值与透明度 (每个权重值以及透明度取值[0,1])
-
-
-
collision —> 连杆的碰撞属性
-
Inertial —> 连杆的惯性矩阵
表格式:
1.3 joint 关节标签
urdf 中的 joint 标签用于描述机器人关节的运动学和动力学属性,还可以指定关节运动的安全极限,机器人的两个部件(分别称之为 parent link 与 child link)以"关节"的形式相连接,不同的关节有不同的运动形式: 旋转、滑动、固定、旋转速度、旋转角度限制…,比如:安装在底座上的轮子可以360度旋转,而摄像头则可能是完全固定在底座上。
注意:joint标签对应的数据在模型中是不可见的,joint的具体样式如下:
(1)属性
-
name —> 为关节命名
-
type —> 关节运动形式
-
- continuous: 旋转关节,可以绕单轴无限旋转
- revolute: 旋转关节,类似于 continues,但是有旋转角度限制
- prismatic: 滑动关节,沿某一轴线移动的关节,有位置极限
- planer: 平面关节,允许在平面正交方向上平移或旋转
- floating: 浮动关节,允许进行平移、旋转运动
- fixed: 固定关节,不允许运动的特殊关节
(2)子标签
-
parent(必需的)
parent link的名字是一个强制的属性: -
- link:父级连杆的名字,是这个link在机器人结构树中的名字。
-
child(必需的)
child link的名字是一个强制的属性: -
- link:子级连杆的名字,是这个link在机器人结构树中的名字。
-
origin
-
- 属性: xyz=各轴线上的偏移量 rpy=各轴线上的偏移弧度。
-
axis
-
- 属性: xyz用于设置围绕哪个关节轴运动。
-
collision —> 连杆的碰撞属性
-
Inertial —> 连杆的惯性矩阵
2、URDF创建
URDF 文件是一个标准的 XML 文件,使用xml语言实现,这是一种标记语言,可以简单的理解为:
<xxx参数开始>
xxx参数内容
</xxx参数结束>
通过参数左右的标识,来让其他程序读取某些参数。xml语言是一种树形结构,也就是某些参数里面,可以包含其他的内容的参数。
2.1 基础的模型结构
1 <robot name="learn_urdf">
2 <link name="link1" />
3 <link name="link2" />
4 <joint name="joint1" type="fixed">
5 <parent link="link1"/>
6 <child link="link2"/>
7 </joint>
8 </robot>
为了方便观察,我对上述代码做了合理的缩进,当然你写代码的时候也应该养成这种习惯。
-
第1行
robot
元素的name为learn_urdf,即我们所创建的机器人名字为learn_urdf。 -
第2~4行均为
robot
的子元素,分别是link1
、link2
、joint1
。 -
joint1
还有一个参数type,即joint1的类型为fixed
,这个后面讲。joint有两个子元素(第5~6行),分别是parent
和child
,且该两元素分别指向了一个link
。**提示:**机器人的组成是
parent-link
——joint
——child-link
,可理解为人体的腿部,腿分为大腿和小腿,大腿和小腿又是通过关节连接起来的,可将parent-link
看成是大腿,joint
看成是关节,child-link
看成是小腿,大概就是这么个意思!
2.2 简单模型构造
上述只是一个基础的模型结构,实际应用中,我们需要为其添加更多的细节,如下面程序所示。
1<?xml version="1.0"?>
2<robot name="visualize_urdf">
3
4 <link name="base_link">
5 <visual>
6 <geometry>
7 <box size="1 1 1"/>
8 </geometry>
9 <origin rpy="0 0 0" xyz="0 0 0"/>
10 </visual>
11 </link>
12
13 <link name="head">
14 <visual>
15 <geometry>
16 <box size="0.5 0.5 0.5"/>
17 </geometry>
18 <origin rpy="0 0 0" xyz="0 0 0.75"/>
19 </visual>
20 </link>
21
22 <joint name="neck" type="fixed">
23 <parent link="base_link"/>
24 <child link="head"/>
25 </joint>
26
27</robot>
现在,link
里多了一些尺寸参数,后面会讲它们的作用。得益于xml
的特性,我们可以大概知道我们两个link
间的参数含义:
- **< link>与< /link>**之间的内容,用来设置连杆(link)的参数
- < visual>与</ visual> 之间的内容,用来描述外观(对应的数据是可视的)
- **< geometry>与< /geometry>**之间的内容,用来设置连杆的形状;此处,
<box size="1 1 1"/>
是指尺寸为长(x) 宽(y) 高(z)全为1m的box(盒状)物体。 - orgin属性: xyz=各轴线上的偏移量 rpy=各轴线上的偏移弧度
- **< joint>与< /joint>**之间的内容,用来设置关节(joint)的参数
- type: 表示关节的运动形式
- fixed: 固定关节,不允许运动的特殊关节
- parent link的名字是一个强制的属性:父级连杆的名字,是这个link在机器人结构树中的名字
- child link的名字是一个强制的属性:子级连杆的名字,是这个link在机器人结构树中的名字
运行结果:
2.2 base_link
在建立URDF文件的时候,我们首先要建立一个参考杆件即base_link
,base_link
是极为特殊的一种link
,因为机器人的坐标变换或其他操作等需要指定一个参考点,那么就得规定,每个机器人必须包含一个固定名称的节点。于是产生了base_link
,可以将其理解为根节点。注意:base_link
与其它link
参数相同,但有且仅有一个。
举个例子,如为一个四轮小车建URDF时,一般情况下,我们会选择车身为base_link,即以车身为参考,先建立车身,然后参考车位的位置建立后续的link,即四个轮子。
1 <link name="base_link">
2
3 <visual>
4 <geometry>
5 <box size="1 1 1"/>
6 </geometry>
7 <origin rpy="0 0 0" xyz="0 0 0"/>
8 </visual>
9
10 </link>
分析:
- **< link>与< /link>**之间的内容,用来设置连杆(link)的参数
- < visual>与</ visual> 之间的内容,用来描述外观(对应的数据是可视的)
- **< geometry>与< /geometry>**之间的内容,用来设置连杆的形状。此处,
<box size="1 1 1"/>
是指尺寸为长(x) 宽(y) 高(z)全为1m的box(盒状)物体。 - orgin属性: xyz=各轴线上的偏移量 ;rpy=各轴线上的偏移弧度
2.5 link
link如下图红框框圈起来的部分所示:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210525105018742.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTEwMTc2OTQ=,size_16,color_FFFFFF,t_70)
1 <link name="my_link">
2
3 <inertial>
4 <origin xyz="0 0 0.5" rpy="0 0 0"/>
5 <mass value="1"/>
6 <inertia ixx="100" ixy="0" ixz="0" iyy="100" iyz="0" izz="100" />
7 </inertial>
8
9 <visual>
10 <origin xyz="0 0 0" rpy="0 0 0" />
11 <geometry>
12 <box size="1 1 1" />
13 </geometry>
14 <material name="Cyan">
15 <color rgba="0 1.0 1.0 1.0"/>
16 </material>
17 </visual>
18
19 <collision>
20 <origin xyz="0 0 0" rpy="0 0 0"/>
21 <geometry>
22 <cylinder radius="1" length="0.5"/>
23 </geometry>
24 </collision>
25
26 </link>
分析:
-
**< link>与< /link>**之间的内容,用来设置连杆(link)的参数
-
**< inertial>与< /inertial>**之间的内容,是连杆的惯性矩阵
- origin:xyz=各轴线上的偏移量 ;rpy=各轴线上的偏移弧度 。即沿z轴向上偏移0.5m,其它轴不动; 各轴线上的偏移弧度全为0。
- **mass:**表示
my_link
的质量为1kg。 - inertia:
-
< visual>与</ visual> 之间的内容,用来描述外观(对应的数据是可视的)
-
**< geometry>与< /geometry>**之间的内容,用来设置连杆的形状
-
orgin属性: xyz=各轴线上的偏移量 rpy=各轴线上的偏移弧度
-
**< joint>与< /joint>**之间的内容,用来设置关节(joint)的参数
-
type: 表示关节的运动形式
-
fixed: 固定关节,不允许运动的特殊关节
2.6 joint
joint如下图杆件Parent link和Child link之间的连接部分所示:
1<joint name="my_joint" type="floating">
2
3 <origin xyz="0 0 1" rpy="0 0 3.1416"/>
4 <parent link="link1"/>
5 <child link="link2"/>
6
7 <calibration rising="0.0"/>
8 <dynamics damping="0.0" friction="0.0"/>
9 <limit effort="30" velocity="1.0" lower="-2.2" upper="0.7" />
10 <safety_controller k_velocity="10" k_position="15" soft_lower_limit="-2.0" soft_upper_limit="0.5" />
11
12</joint>
分析:
3、以倒立摆小车为例:
注意:
在创建urdf的时候,杆件link默认位置为原点,在建立杆件link的时候,不必将其建到目标位置,而是在创建joint时,确定其最终位置。
即创建步骤:①创建杆件的基本形状;②通过joint确定其最终位置。
倒立摆小车URDF代码分析
倒立摆小车共有三个部分组成:车身、一个杆子、四个轮子。
第一步:建立机器人,此处选用车身为参考,为车身添加形状、偏移量、颜色、碰撞及惯性等属性,代码及其解释如下:
<?xml version="1.0"?>
<!--机器人的名称-->
<robot name="cartpole">
<!--base_link 机器人的坐标变换或其他操作的参考点-->
<link name="base_cart">
<!--可视化标签-->
<visual>
<!--1、形状-->
<geometry>
<!--立方体-->
<box size="0.5 1 0.15"/>
</geometry>
<!--2、偏移量和弧度-->
<!--
xyz设置机器人模型在xyz上的偏移量
rpy设置倾斜弧度 x:翻滚 y:俯仰 z:偏航
-->
<origin xyz="0 0 0" rpy="1.57 0 1.57"/>
<!--3、颜色-->
<!--
rgba: r=red g=green b=blue a=透明度
都在0-1之间
-->
<material name="cart_mat">
<color rgba="0.3 0.5 0.7 1"/>
</material>
</visual>
<!--2、 连杆的碰撞属性-->
<collision>
<geometry>
<box size="0.5 1 0.15"/>
</geometry>
</collision>
<!--2、连杆的惯性矩阵-->
<inertial>
<!--连杆的重量-->
<mass value="20"/>
</inertial>
</link>
第二步:建立link–杆子
<link name="pole">
<visual>
<geometry>
<box size="0.04 0.06 1.12"/>
</geometry>
<origin xyz="0 0 0.47 "/>
<material name="pole_mat">
<color rgba="0.1 0.1 0.3 1"/>
</material>
</visual>
<collision>
<geometry>
<box size="0.04 0.06 1.0"/>
</geometry>
<origin xyz="0 0 0.47"/>
<box size="0.04 0.06 1.12"/>
</collision>
<box size="0.04 0.06 1.12"/>
<inertial>
<mass value="2"/>
<origin xyz="0 0 0.47"/>
</inertial>
</link>
第三步:建立杆件–四个轮子,四个轮子分别为pre_wheel_left、pre_wheel_right、post_wheel_left、post_wheel_right
<link name="pre_wheel_left">
<visual>
<geometry>
<cylinder radius="0.15" length="0.1"/>
</geometry>
<origin xyz="0 0 0" rpy="0 -1.57 0" />
<material name="red">
<color rgba="0 0 1 0.5" />
</material>
</visual>
<collision>
<geometry>
<cylinder radius="0.15" length="0.1"/>
</geometry>
<origin xyz="0 0 0" rpy="0 -1.57 0" />
</collision>
<inertial>
<mass value="5"/>
</inertial>
</link>
<link name="pre_wheel_right">
<visual>
<geometry>
<cylinder radius="0.15" length="0.1"/>
</geometry>
<origin xyz="0 0 0" rpy="0 -1.57 0" />
<material name="red">
<color rgba="0 0 1 0.5" />
</material>
</visual>
<collision>
<geometry>
<cylinder radius="0.15" length="0.1"/>
</geometry>
<origin xyz="0 0 0" rpy="0 -1.57 0" />
</collision>
<inertial>
<mass value="5"/>
</inertial>
</link>
<link name="post_wheel_left">
<visual>
<geometry>
<cylinder radius="0.15" length="0.1"/>
</geometry>
<origin xyz="0 0 0" rpy="0 1.57 0" />
<material name="red">
<color rgba="0 0 1 0.5" />
</material>
</visual>
<collision>
<geometry>
<cylinder radius="0.15" length="0.1"/>
</geometry>
<origin xyz="0 0 0" rpy="0 1.57 0" />
</collision>
<inertial>
<mass value="5"/>
</inertial>
</link>
<link name="post_wheel_right">
<visual>
<geometry>
<cylinder radius="0.15" length="0.1"/>
</geometry>
<origin xyz="0 0 0" rpy="0 -1.57 0" />
<material name="red">
<color rgba="0 0 1 0.5" />
</material>
</visual>
<collision>
<geometry>
<cylinder radius="0.15" length="0.1"/>
</geometry>
<origin xyz="0 0 0" rpy="0 -1.57 0" />
</collision>
<inertial>
<mass value="5"/>
</inertial>
</link>
第四步:将link与link之间通过joint连接起来
在此示例中,车身作为base_link,其连接了四个轮子与杆件。parent link为父节点,child link为子节点
<joint name="pre_wheelLeft_to_cart" type="continuous">
<parent link="base_cart"/>
<child link="pre_wheel_left"/>
<origin xyz="0.3 0.5 0" rpy="0 0 0"/>
<axis xyz="1 0 0"/>
</joint>
<joint name="pre_wheelRight_to_cart" type="continuous">
<axis xyz="1 0 0"/>
<origin xyz="-0.3 0.5 0" rpy="0 0 0"/>
<parent link="base_cart"/>
<child link="pre_wheel_right"/>
</joint>
<joint name="post_wheelLeft_to_cart" type="continuous">
<parent link="base_cart"/>
<child link="post_wheel_left"/>
<origin xyz="0.3 -0.5 0" rpy="0 0 0"/>
<axis xyz="1 0 0"/>
</joint>
<joint name="post_wheelRight_to_cart" type="continuous">
<axis xyz="1 0 0"/>
<origin xyz="-0.3 -0.5 0" rpy="0 0 0"/>
<parent link="base_cart"/>
<child link="post_wheel_right"/>
</joint>
<joint name="cart_to_pole" type="continuous">
<axis xyz="1 0 0"/>
<origin xyz="0 -0.4 0"/>
<parent link="base_cart"/>
<child link="pole"/>
</joint>
上图倒立摆小车的URDF完整代码如下:
<?xml version="1.0"?>
<!--机器人的名称-->
<robot name="cartpole">
<!--base_link 机器人的坐标变换或其他操作的参考点-->
<link name="base_cart">
<!--可视化标签-->
<visual>
<!--1、形状-->
<geometry>
<!--立方体-->
<box size="0.5 1 0.15"/>
</geometry>
<!--2、偏移量和弧度-->
<!--
xyz设置机器人模型在xyz上的偏移量
rpy设置倾斜弧度 x:翻滚 y:俯仰 z:偏航
-->
<origin xyz="0 0 0" rpy="1.57 0 1.57"/>
<!--3、颜色-->
<!--
rgba: r=red g=green b=blue a=透明度
都在0-1之间
-->
<material name="cart_mat">
<color rgba="0.3 0.5 0.7 1"/>
</material>
</visual>
<!--2、 连杆的碰撞属性-->
<collision>
<geometry>
<box size="0.5 1 0.15"/>
</geometry>
</collision>
<!--2、连杆的惯性矩阵-->
<inertial>
<!--连杆的重量-->
<mass value="20"/>
</inertial>
</link>
<link name="pole">
<visual>
<geometry>
<box size="0.04 0.06 1.12"/>
</geometry>
<origin xyz="0 0 0.47 "/>
<material name="pole_mat">
<color rgba="0.1 0.1 0.3 1"/>
</material>
</visual>
<collision>
<geometry>
<box size="0.04 0.06 1.0"/>
</geometry>
<origin xyz="0 0 0.47"/>
<box size="0.04 0.06 1.12"/>
</collision>
<box size="0.04 0.06 1.12"/>
<inertial>
<mass value="2"/>
<origin xyz="0 0 0.47"/>
</inertial>
</link>
<link name="pre_wheel_left">
<visual>
<geometry>
<cylinder radius="0.15" length="0.1"/>
</geometry>
<origin xyz="0 0 0" rpy="0 -1.57 0" />
<material name="red">
<color rgba="0 0 1 0.5" />
</material>
</visual>
<collision>
<geometry>
<cylinder radius="0.15" length="0.1"/>
</geometry>
<origin xyz="0 0 0" rpy="0 -1.57 0" />
</collision>
<inertial>
<mass value="5"/>
</inertial>
</link>
<link name="pre_wheel_right">
<visual>
<geometry>
<cylinder radius="0.15" length="0.1"/>
</geometry>
<origin xyz="0 0 0" rpy="0 -1.57 0" />
<material name="red">
<color rgba="0 0 1 0.5" />
</material>
</visual>
<collision>
<geometry>
<cylinder radius="0.15" length="0.1"/>
</geometry>
<origin xyz="0 0 0" rpy="0 -1.57 0" />
</collision>
<inertial>
<mass value="5"/>
</inertial>
</link>
<link name="post_wheel_left">
<visual>
<geometry>
<cylinder radius="0.15" length="0.1"/>
</geometry>
<origin xyz="0 0 0" rpy="0 1.57 0" />
<material name="red">
<color rgba="0 0 1 0.5" />
</material>
</visual>
<collision>
<geometry>
<cylinder radius="0.15" length="0.1"/>
</geometry>
<origin xyz="0 0 0" rpy="0 1.57 0" />
</collision>
<inertial>
<mass value="5"/>
</inertial>
</link>
<link name="post_wheel_right">
<visual>
<geometry>
<cylinder radius="0.15" length="0.1"/>
</geometry>
<origin xyz="0 0 0" rpy="0 -1.57 0" />
<material name="red">
<color rgba="0 0 1 0.5" />
</material>
</visual>
<collision>
<geometry>
<cylinder radius="0.15" length="0.1"/>
</geometry>
<origin xyz="0 0 0" rpy="0 -1.57 0" />
</collision>
<inertial>
<mass value="5"/>
</inertial>
</link>
<joint name="pre_wheelLeft_to_cart" type="continuous">
<parent link="base_cart"/>
<child link="pre_wheel_left"/>
<origin xyz="0.3 0.5 0" rpy="0 0 0"/>
<axis xyz="1 0 0"/>
</joint>
<joint name="pre_wheelRight_to_cart" type="continuous">
<axis xyz="1 0 0"/>
<origin xyz="-0.3 0.5 0" rpy="0 0 0"/>
<parent link="base_cart"/>
<child link="pre_wheel_right"/>
</joint>
<joint name="post_wheelLeft_to_cart" type="continuous">
<parent link="base_cart"/>
<child link="post_wheel_left"/>
<origin xyz="0.3 -0.5 0" rpy="0 0 0"/>
<axis xyz="1 0 0"/>
</joint>
<joint name="post_wheelRight_to_cart" type="continuous">
<axis xyz="1 0 0"/>
<origin xyz="-0.3 -0.5 0" rpy="0 0 0"/>
<parent link="base_cart"/>
<child link="post_wheel_right"/>
</joint>
<joint name="cart_to_pole" type="continuous">
<axis xyz="1 0 0"/>
<origin xyz="0 -0.4 0"/>
<parent link="base_cart"/>
<child link="pole"/>
</joint>
</robot>