ROS2学习CH4 Urdf,Xacro与Sdf
urdf与xacro
URDF: Unified Robot Description Format,一种用于描述机器人模型的XML格式。
urdf主要的作用:
- 描述机器人模型的结构和属性,包括关节、连杆、传感器等,这部分方便去建立机器人的tf树。
- 提供机器人模型的可视化和仿真支持。
- 支持机器人运动学和动力学计算。
urdf中的主要元素
link: 描述刚体部分,一个机器人通常是由多个link结合组成的
对于link,有几个子属性可以设置
name: link的名称,必须唯一visual: 描述link的外观,包括geometry和material等属性collision: 描述link的碰撞模型,包括geometry和material等属性
即对于一个link,其外表和实际的碰撞模型可以不同,visual用于可视化,collision用于碰撞检测inertial: 描述link的惯性属性,包括质量、质心位置和惯性矩阵等属性
joint: 描述link之间的连接关系,定义了link之间的运动约束和自由度
对于joint,其也有几个子属性可以设置
-
name: joint的名称,必须唯一 -
type: joint的类型,包括continuous、prismatic、fixed(固定)d等 -
parent link: joint连接的父link -
child link: joint连接的子link这里即表述child link连接到parent link上
-
axis: joint的旋转轴或平移轴 -
origin: joint在世界坐标系中的位置和方向(相对于父link的x,y,z和roll,pitch,yaw)
编写URDF与Xacro文件
下面是一个简单的urdf例子。
<?xml version="1.0"?>
<!-- 上面定义了本文件是一个xml文件以及声明版本 -->
<robot name="sam_bot">
<link name="base_link">
<visual>
<geometry>
<box size="${base_length} ${base_width} ${base_height}"/>
</geometry>
<material name="Cyan">
<color rgba="0 1.0 1.0 1.0"/>
<!-- rgba参考jpg,a即为透明度 -->
</material>
<!-- Cyan:自定义的材料名称 -->
</visual>
</link>
</robot>
可以看到整体的结构可以如下所示
robot(机器人:sam_bot)
└── link(连杆:base_link)
└── visual(可视化外观)
├── geometry(几何形状)
│ └── box(长方体)
│ └── size:${base_length} ${base_width} ${base_height}
└── material(材质:Cyan)
└── color(颜色)
└── rgba:0 1.0 1.0 1.0
也就是说,urdf文件的结构是层级化的,每个元素都有自己的属性和子元素,通过这种方式可以描述机器人的各个部分及其关系。
上面的例子中,使用urdf描述了一个机器人的主体部分(base_link),他现在只有一个正方形的身体,如果后续给他添加轮子,那么就需要添加一个轮子的link以及添加一个在base_link和轮子link之间的joint,来描述轮子和主体之间的连接关系。
<link name="left_wheel_link">
<visual>
<geometry>
<cylinder radius="${wheel_radius}" length="${wheel_width}"/>
</geometry>
<material name="Black">
<color rgba="0 0 0 1.0"/>
</material>
</visual>
</link>
<!-- 上面定义了一个左侧轮子的link描述 -->
<joint name="left_wheel_joint" type="continuous">
<parent link="base_link"/>
<child link="left_wheel_link"/>
<origin xyz="${left_wheel_x} ${left_wheel_y} ${left_wheel_z}" rpy="0 0 0"/>
<axis xyz="0 1 0"/>
</joint>
<!-- 上面定义了一个左侧轮子的joint描述,将左侧轮子连接到主体上 -->
显然对于有两个轮子的机器人,我们需要重复的添加一个右侧轮子的link和joint描述。此时我们可以使用xacro来简化这个过程,xacro是一个宏语言,可以在urdf中使用变量和宏定义,从而减少重复代码。
要想在urdf中使用xacro,需要在文件开头添加
xmlns:xacro="http://www.ros.org/wiki/xacro"的声明,说明在此xml文件中可以使用xacro的语法。
一些xacro的语法示例:
- 定义:
<!-- 1. 定义一个名为wheel_radius的变量,其值为0.1 -->
<xacro:property name="wheel_radius" value="0.1"/>
<!-- 2. 引用变量 -->
radius="${wheel_radius}"
<!-- 3. 定义宏函数 -->
<xacro:macro name="wheel" params="name wheel_radius wheel_width">
<!-- 在这里可以使用urdf描述定义宏函数的具体内容,使用${name}或者${wheel_radius}等变量 -->
</xacro:macro>
<!-- 上面相当于定义了 wheel(name, wheel_radius, wheel_width)这样一个函数 -->
<!-- 4. 调用宏函数 -->
<xacro:wheel name="left_wheel" wheel_radius="${wheel_radius}" wheel_width="${wheel_width}"/>
<!-- 即使用宏名加参数调用宏函数 -->
这样的话,我们就可以使用xacro来定义一个轮子的宏函数,然后在urdf中调用这个宏函数来生成左轮和右轮的link和joint,从而减少重复代码。
<!-- Wheels -->
<xacro:macro name="wheel" params="prefix x_reflect y_reflect">
<link name="${prefix}_link">
<visual>
<origin xyz="0 0 0" rpy="${pi/2} 0 0"/>
<geometry>
<cylinder radius="${wheel_radius}" length="${wheel_width}"/>
</geometry>
<material name="Gray">
<color rgba="0.5 0.5 0.5 1.0"/>
</material>
</visual>
</link>
<joint name="${prefix}_joint" type="continuous">
<parent link="base_link"/>
<child link="${prefix}_link"/>
<origin xyz="${x_reflect*wheel_xoff} ${y_reflect*(base_width/2+wheel_ygap)} ${-wheel_zoff}" rpy="0 0 0"/>
<axis xyz="0 1 0"/>
</joint>
</xacro:macro>
上面的描述通过控制x_reflect和y_reflect的值来控制轮子的位置,从而可以生成左轮和右轮的link和joint。
最后贴上一个完整的xacro文件示例:
点击展开 URDF / Xacro 代码
<?xml version="1.0"?>
<robot name="sam_bot" xmlns:xacro="http://ros.org/wiki/xacro">
<!-- urdf的根元素就是一个robot,其他的元素用来描述(discription)这个robot -->
<!-- xmlns:xacro="http://ros.org/wiki/xacro", 类比与C++中的namespace,这里也是
声明xml文件使用了xmlns命名空间下的xacro -->
<!-- Define robot constants -->
<xacro:property name="base_width" value="0.31"/>
<xacro:property name="base_length" value="0.42"/>
<xacro:property name="base_height" value="0.18"/>
<xacro:property name="wheel_radius" value="0.10"/>
<xacro:property name="wheel_width" value="0.04"/>
<xacro:property name="wheel_ygap" value="0.025"/>
<xacro:property name="wheel_zoff" value="0.05"/>
<xacro:property name="wheel_xoff" value="0.12"/>
<xacro:property name="caster_xoff" value="0.14"/>
<!-- 上面使用了xacro的property标签来定义常量,以后使用
这些常量需要通过${常量名}语法来引用 -->
<!-- Robot Base -->
<link name="base_link">
<visual>
<geometry>
<box size="${base_length} ${base_width} ${base_height}"/>
</geometry>
<material name="Cyan">
<color rgba="0 1.0 1.0 1.0"/>
</material>
<!-- Cyan:自定义的材料名称 -->
</visual>
</link>
<!-- Robot Footprint -->
<link name="base_footprint"/>
<joint name="base_joint" type="fixed">
<parent link="base_link"/>
<child link="base_footprint"/>
<origin xyz="0.0 0.0 ${-(wheel_radius+wheel_zoff)}" rpy="0 0 0"/>
</joint>
<!-- Wheels -->
<xacro:macro name="wheel" params="prefix x_reflect y_reflect">
<link name="${prefix}_link">
<visual>
<origin xyz="0 0 0" rpy="${pi/2} 0 0"/>
<geometry>
<cylinder radius="${wheel_radius}" length="${wheel_width}"/>
</geometry>
<material name="Gray">
<color rgba="0.5 0.5 0.5 1.0"/>
</material>
</visual>
</link>
<joint name="${prefix}_joint" type="continuous">
<parent link="base_link"/>
<child link="${prefix}_link"/>
<origin xyz="${x_reflect*wheel_xoff} ${y_reflect*(base_width/2+wheel_ygap)} ${-wheel_zoff}" rpy="0 0 0"/>
<axis xyz="0 1 0"/>
</joint>
</xacro:macro>
<!-- 上面展示了如何使用xacro宏来定义部件 -->
<!-- <xacro:macro name="wheel" params="prefix x_reflect y_reflect">
相当于定义了一个函数 wheel(prefix, x_reflect, y_reflect),以后可以使用
xacro:wheel prefix="", x_reflect="", y_reflect="" 去调用这个宏 -->
<!-- 下面使用刚才的宏描述机器人的左右两个轮子 -->
<xacro:wheel prefix="drivewhl_l" x_reflect="-1" y_reflect="1" />
<xacro:wheel prefix="drivewhl_r" x_reflect="-1" y_reflect="-1" />
<!-- Caster Wheel(机器人前下的万向轮) -->
<link name="front_caster">
<visual>
<geometry>
<sphere radius="${(wheel_radius+wheel_zoff-(base_height/2))}"/>
</geometry>
<material name="Cyan">
<color rgba="0 1.0 1.0 1.0"/>
</material>
</visual>
</link>
<joint name="caster_joint" type="fixed">
<parent link="base_link"/>
<child link="front_caster"/>
<origin xyz="${caster_xoff} 0.0 ${-(base_height/2)}" rpy="0 0 0"/>
</joint>
</robot>
但是需要注意的是,Xacro与Urdf并无本质关系,Xacro只是xml文件支持的宏语言,通过使用Xacro的宏展开功能,可以减少Urdf文件的重复代码,提高可读性和可维护性,所以Xacro只是Urdf的一个辅助工具。
编写完带有xacro的urdf文件后,需要执行xacro相关的命令去宏展开得到最终的urdf文件,才能被ros2使用。
xacro path/to/your_robot.xacro
该命令会将宏展开的结果输出到终端,如果想将结果保存到文件中,可以使用重定向:
xacro path/to/your_robot.xacro > path/to/your_robot.urdf
当然不难看出,,我们一直在混淆xacro和urdf的格式,由于两者都是xml格式,所以即使后缀是.urdf的文件,也可以使用xacro的语法,只要在文件开头声明了xacro的命名空间即可,而且可以使用xacro命令去宏展开得到最终的urdf文件。但是为了明晰,建议将带有xacro语法的文件命名为.xacro后缀,而将宏展开后的文件命名为.urdf后缀。
sdf
sdf: Simulation Description Format,一种用于描述机器人模型的XML格式。不同于urdf,sdf不仅可以描述机器人模型,还可以描述仿真环境的模型以及添加仿真插件等。
我们可以使用sdf来复现上面使用urdf描述的机器人模型,sdf的语法与urdf类似,但是有一些不同之处。
点击展开 Sdf 代码
<?xml version="1.0"?>
<sdf version="1.8" xmlns:xacro="http://ros.org/wiki/xacro">
<model name="sam_bot">
<!-- 依旧使用xacro去定义一些变量 -->
<xacro:property name="base_width" value="0.31"/>
<xacro:property name="base_length" value="0.42"/>
<xacro:property name="base_height" value="0.18"/>
<xacro:property name="wheel_radius" value="0.10"/>
<xacro:property name="wheel_width" value="0.04"/>
<xacro:property name="wheel_ygap" value="0.025"/>
<xacro:property name="wheel_zoff" value="0.05"/>
<xacro:property name="wheel_xoff" value="0.12"/>
<xacro:property name="caster_xoff" value="0.14"/>
<!-- Robot Base -->
<link name="base_link">
<must_be_base_link>true</must_be_base_link>
<visual name="base_link_visual">
<geometry>
<box>
<size>${base_length} ${base_width} ${base_height}</size>
</box>
</geometry>
<material>
<ambient>0 1 1 1</ambient>
<diffuse>0 1 1 1</diffuse>
</material>
</visual>
</link>
<!-- Robot Footprint -->
<link name="base_footprint">
<pose relative_to="base_joint"/>
</link>
<joint name="base_joint" type="fixed">
<parent>base_link</parent>
<child>base_footprint</child>
<pose relative_to="base_link">0.0 0.0 ${-(wheel_radius+wheel_zoff)} 0 0 0</pose>
</joint>
<!-- Wheels -->
<xacro:macro name="wheel" params="prefix x_reflect y_reflect">
<link name="${prefix}_link">
<pose relative_to="${prefix}_joint"/>
<visual name="${prefix}_link_visual">
<pose relative_to="${prefix}_link">0 0 0 ${pi/2} 0 0</pose>
<geometry>
<cylinder>
<radius>${wheel_radius}</radius>
<length>${wheel_width}</length>
</cylinder>
</geometry>
<material>
<ambient>0.3 0.3 0.3 1.0</ambient>
<diffuse>0.7 0.7 0.7 1.0</diffuse>
</material>
</visual>
</link>
<joint name="${prefix}_joint" type="revolute">
<parent>base_link</parent>
<child>${prefix}_link</child>
<pose relative_to="base_link">
${x_reflect*wheel_xoff} ${y_reflect*(base_width/2+wheel_ygap)} ${-wheel_zoff} 0 0 0
</pose>
<axis>
<xyz>0 1 0</xyz>
<limit>
<lower>-inf</lower>
<upper>inf</upper>
</limit>
</axis>
</joint>
</xacro:macro>
<xacro:wheel prefix="drivewhl_l" x_reflect="-1" y_reflect="1"/>
<xacro:wheel prefix="drivewhl_r" x_reflect="-1" y_reflect="-1"/>
<!-- Front caster -->
<link name="front_caster">
<pose relative_to="caster_joint"/>
<visual name="front_caster_visual">
<geometry>
<sphere>
<radius>${(wheel_radius+wheel_zoff-(base_height/2))}</radius>
</sphere>
</geometry>
<material>
<ambient>0 1 1 1</ambient>
<diffuse>0 1 1 1</diffuse>
</material>
</visual>
</link>
<joint name="caster_joint" type="fixed">
<parent>base_link</parent>
<child>front_caster</child>
<pose relative_to="base_link">${caster_xoff} 0.0 ${-(base_height/2)} 0 0 0</pose>
</joint>
</model>
</sdf>
大部分的标签都是自然语言直接能看懂的。介绍几个新增的标签
<sdf>
- 包含
version属性,以及<model>、<world>等元素。 - 作用:作为 SDF 文件的根标签,指定使用的 SDF 版本。
-
<model>- 包含
<link>、<joint>等元素。 - 作用:描述一个完整的机器人或模型。
- 包含
-
<must_be_base_link>- 内容为
true或false。 - 作用:指定当前 link 是否作为模型的基础 link。
- 内容为
-
<pose>- 包含:
x y z roll pitch yaw - 可带
relative_to属性。 - 作用:描述当前元素的位置和姿态。
- 包含:
-
relative_to- 写在
<pose>标签中,例如:<pose relative_to="base_link"> - 作用:指定当前 pose 是相对于哪个坐标系定义的。
- 写在
-
<visual name="...">- 包含
<pose>、<geometry>、<material>等元素。 - 作用:描述 link 的外观和显示位置。
- 包含
-
<ambient>- 包含
R G B A四个数值。 - 作用:设置材质在环境光下的颜色。
- 包含
-
<diffuse>- 包含
R G B A四个数值。 - 作用:设置材质受到光照后的漫反射颜色。
- 包含
-
<axis>- 包含
<xyz>、<limit>等元素。 - 作用:描述旋转关节的旋转轴以及运动范围。
- 包含
-
<limit>- 包含
<lower>、<upper>等元素。 - 作用:限制关节允许运动的范围。
- 包含
当然,上面的sdf以及urdf/xacro文件中仅仅只是描述了机器人的外观和结构,并没有描述机器人的动力学特性以及传感器等信息,这些信息可以通过描述碰撞标签(collision)以及引入插件(plugin)来实现。

浙公网安备 33010602011771号