【ROS2】☆URDF语法
一、简介
URDF是 Unified Robot Description Format 的首字母缩写,直译为统一(标准化)机器人描述格式,可以以一种 XML 的方式描述机器人的部分结构,比如:底盘、摄像头、激光雷达、机械臂以及不同关节的自由度等,该文件可以被 C++ 内置的解释器转换成 rviz 或仿真环境中的可视化机器人模型。
二、URDF语法
2.1 robot 根标签
urdf 中为了保证 xml 语法的完整性,使用了robot
标签作为根标签,所有的 link 和 joint 以及其他标签都必须包含在 robot 标签内,在该标签内可以通过 name 属性设置机器人模型的名称。
属性:name:主文件必须具有名称属性, name 属性在被包含的文件中是可选的。
如果在被包含文件中指定了属性名称,则它必须具有与主文件中相同的值。
示例:
<robot name="mycar">
</robot>
2.2 link 标签
urdf 中的 link 标签用于描述机器人某个部件(也即刚体部分)的外观和物理属性,比如: 机器人底座、轮子、激光雷达、摄像头...每一个部件都对应一个 link, 在 link 标签内,可以设计该部件的形状、尺寸、颜色、惯性矩阵、碰撞参数等一系列属性。<link>标签用于定义一个链接,name属性指定链接的名称。
属性: name(必填):为连杆命名
<link name="link_name">
......
</link>
link下子标签:
1. <visual>标签定义链接的可视化属性,包括形状、相对偏移量、旋转角度和材质。
<!-- 可视化属性 -->
<visual>
<geometry>
<!-- 立方体 -->
<box size="length width height"/>
<!-- 圆柱 -->
<cylinder radius="radius" length="length"/>
<!-- 球体 -->
<sphere radius="radius"/>
<!-- 网格 -->
<mesh filename="package://<packagename>/<path>"/>
</geometry>
<!-- 相对偏移量及旋转角度 -->
<origin xyz="x y z" rpy="roll pitch yaw"/>
<!-- 材质 -->
<material name="material_name">
<color rgba="red green blue alpha"/>
<texture filename="texture_file_path"/>
</material>
</visual>
2. <collision>标签定义链接的碰撞属性,可以与可视化属性一致或不同,用于仿真环境中的碰撞检测。
<!-- 碰撞属性 -->
<collision name="collision_name">
<geometry>
<!-- 立方体 -->
<box size="length width height"/>
<!-- 圆柱 -->
<cylinder radius="radius" length="length"/>
<!-- 球体 -->
<sphere radius="radius"/>
<!-- 网格 -->
<mesh filename="package://<packagename>/<path>"/>
</geometry>
<!-- 相对偏移量及旋转角度 -->
<origin xyz="x y z" rpy="roll pitch yaw"/>
</collision>
3. <inertial>标签用于设置链接的质量、质心位置和中心惯性特性,这些属性在仿真环境中非常重要,用于计算动力学行为。
<!-- 质量、质心位置和中心惯性特性 -->
<inertial>
<!-- 质心位置及方向 -->
<origin xyz="x y z" rpy="roll pitch yaw"/>
<!-- 质量 -->
<mass value="mass_value"/>
<!-- 惯性矩 -->
<inertia ixx="ixx" ixy="ixy" ixz="ixz" iyy="iyy" iyz="iyz" izz="izz"/>
</inertial>
注意:<collision> 和 <inertial> 在仿真环境下才需要使用到,如果只是在 rviz2 中集成 urdf,那么不必须为 link 定义这两个标签。
完整示例: 分别生成长方体、圆柱与球体的机器人部件。
实现:功能包 cpp06_urdf 的 urdf/urdf 目录下,新建 urdf 文件 demo02_link.urdf,并编辑文件,输入如下内容:
<robot name="link_demo">
<!-- 定义颜色 -->
<material name="yellow">
<color rgba="0.7 0.7 0 0.8" />
</material>
<link name="base_link">
<visual>
<!-- 形状 -->
<geometry>
<!-- 长方体的长宽高 -->
<box size="0.5 0.3 0.1" />
<!-- 圆柱,半径和长度 -->
<!-- <cylinder radius="0.5" length="1.0" /> -->
<!-- 球体,半径-->
<!-- <sphere radius="0.3" /> -->
</geometry>
<!-- xyz坐标 rpy翻滚俯仰与偏航角度(3.14=180度) -->
<origin xyz="0 0 0" rpy="0 0 0" />
<!-- 调用已定义的颜色 -->
<material name="yellow"/>
</visual>
</link>
</robot>
编译后,工作空间终端下调用如下命令执行:
ros2 launch cpp06_urdf display.launch.py model:=`ros2 pkg prefix --share cpp06_urdf`/urdf/urdf/demo02_link.urdf
rviz2 中可以根据 geometry 标签中的设置显示对应形状的机器人。
2.3 joint
urdf 中的 joint 标签用于描述机器人关节的运动学和动力学属性,还可以指定关节运动的安全极限,机器人的两个部件(分别称之为 parent link 与 child link)以”关节“的形式相连接,不同的关节有不同的运动形式: 旋转、滑动、固定、旋转速度、旋转角度限制....,比如:安装在底座上的轮子可以360度旋转,而摄像头则可能是完全固定在底座上。
属性:
name(必填):为关节命名,名称需要唯一。
type(必填):设置关节类型,可用类型如下:
continuous:旋转关节,可以绕单轴无限旋转。
revolute:旋转关节,类似于 continues,但是有旋转角度限制。
prismatic:滑动关节,沿某一轴线移动的关节,有位置极限。
planer:平面关节,允许在平面正交方向上平移或旋转。
floating:浮动关节,允许进行平移、旋转运动。
fixed:固定关节,不允许运动的特殊关节。
子标签:
<parent>(必填):指定父级link。
link(必填):父级link的名字,是这个link在机器人结构树中的名字。
<child>(必填):指定子级link。
link(必填):子级link的名字,是这个link在机器人结构树中的名字。
<origin>(可选):这是从父link到子link的转换,关节位于子link的原点。
xyz:各轴线上的偏移量。
rpy:各轴线上的偏移弧度。
<axis>(可选):如不设置,默认值为(1,0,0)。
xyz:用于设置围绕哪个关节轴运动。
<calibration>(可选):关节的参考位置,用于校准关节的绝对位置。
rising(可选):当关节向正方向移动时,该参考位置将触发上升沿。
falling(可选):当关节向正方向移动时,该参考位置将触发下降沿。
<dynamics>(可选):指定接头物理特性的元素。这些值用于指定关节的建模属性,对仿真较为有用。
damping(可选):关节的物理阻尼值,默认为0。
friction(可选):关节的物理静摩擦值,默认为0。
<limit>(关节类型是revolute或prismatic时为必须的):
lower(可选):指定关节下限的属性(旋转关节以弧度为单位,棱柱关节以米为单位)。如果关节是连续的,则省略。
upper(可选):指定关节上限的属性(旋转关节以弧度为单位,棱柱关节以米为单位)。如果关节是连续的,则省略。
effort(必填):指定关节可受力的最大值。
velocity(必填):用于设置最大关节速度(旋转关节以弧度每秒 [rad/s] 为单位,棱柱关节以米每秒 [m/s] 为单位)。
<mimic>(可选):此标签用于指定定义的关节模仿另一个现有关节。该关节的值可以计算为value = multiplier * other_joint_value + offset。
joint(必填):指定要模拟的关节的名称。
multiplier(可选):指定上述公式中的乘法因子。
offset(可选):指定要在上述公式中添加的偏移量,默认为 0(旋转关节的单位是弧度,棱柱关节的单位是米)。
<safety_controller>(可选):安全控制器。
soft_lower_limit(可选):指定安全控制器开始限制关节位置的下关节边界,此限制需要大于joint下限。
soft_upper_limit(可选):指定安全控制器开始限制关节位置的关节上边界的属性,此限制需要小于joint上限。
k_position(可选):指定位置和速度限制之间的关系。
k_velocity(必填):指定力和速度限制之间的关系。
示例:
创建机器人模型,底盘为长方体,在长方体的前面添加一摄像头,摄像头可以沿着 Z 轴 360 度旋转。新建 urdf 文件 demo03_joint.urdf,并编辑文件,输入如下内容:
<!--
需求:创建机器人模型,底盘为长方体,
在长方体的前面添加一摄像头,
摄像头可以沿着 Z 轴 360 度旋转
-->
<robot name="joint_demo">
<!-- 定义颜色 -->
<material name="yellow">
<color rgba="0.7 0.7 0 0.8" />
</material>
<material name="red">
<color rgba="0.8 0.1 0.1 0.8" />
</material>
<link name="base_link">
<visual>
<!-- 形状 -->
<geometry>
<box size="0.5 0.3 0.1" />
</geometry>
<origin xyz="0 0 0" rpy="0 0 0" />
<material name="yellow"/>
</visual>
</link>
<!-- 摄像头 -->
<link name="camera">
<visual>
<geometry>
<box size="0.02 0.05 0.05" />
</geometry>
<origin xyz="0 0 0" rpy="0 0 0" />
<material name="red" />
</visual>
</link>
<!-- 关节 -->
<joint name="camera2baselink" type="continuous">
<parent link="base_link"/>
<child link="camera" />
<!-- 需要计算两个 link 的物理中心之间的偏移量 -->
<origin xyz="0.2 0 0.075" rpy="0 0 0" />
<axis xyz="0 0 1" />
</joint>
</robot>
编译后,工作空间终端下调用如下命令执行,执行指令后,在 rviz2 中会显示机器人模型。
ros2 launch cpp06_urdf display.launch.py model:=`ros2 pkg prefix --share cpp06_urdf`/urdf/urdf/demo03_joint.urdf
然后再新建终端,执行如下命令:
ros2 run joint_state_publisher_gui joint_state_publisher_gui
执行指令后,会弹出一个新的窗口,在该窗口中有一个”进度条“,通过拖拽进度条可以控制相机旋转。
使用base_footprint优化urdf
前面实现的机器人模型是半沉到地下的,因为默认情况下: 底盘的中心点位于地图原点上,所以会导致这种情况产生,可以使用的优化策略,将初始 link 设置为一个尺寸极小的 link(比如半径为 0.001m 的球体,或边长为 0.001m 的立方体),然后再在初始 link 上添加底盘等刚体,这样实现,虽然仍然存在初始link半沉的现象,但是基本可以忽略了,这个初始 link 一般称之为 base_footprint。
新建 urdf 文件 demo04_basefootprint.urdf,并编辑文件,输入如下内容:
<!--
需求:为机器人模型添加 base_footprint
-->
<robot name="base_footprint_demo">
<!-- 定义颜色 -->
<material name="yellow">
<color rgba="0.7 0.7 0 0.8" />
</material>
<material name="red">
<color rgba="0.8 0.1 0.1 0.8" />
</material>
<link name="base_footprint">
<visual>
<geometry>
<sphere radius="0.001"/>
</geometry>
</visual>
</link>
<link name="base_link">
<visual>
<!-- 形状 -->
<geometry>
<box size="0.5 0.3 0.1" />
</geometry>
<origin xyz="0 0 0" rpy="0 0 0" />
<material name="yellow"/>
</visual>
</link>
<joint name="baselink2basefootprint" type="fixed">
<parent link="base_footprint"/>
<child link="base_link"/>
<origin xyz="0.0 0.0 0.05"/>
</joint>
<!-- 摄像头 -->
<link name="camera">
<visual>
<geometry>
<box size="0.02 0.05 0.05" />
</geometry>
<origin xyz="0 0 0" rpy="0 0 0" />
<material name="red" />
</visual>
</link>
<!-- 关节 -->
<joint name="camera2baselink" type="fixed">
<parent link="base_link"/>
<child link="camera" />
<!-- 需要计算两个 link 的物理中心之间的偏移量 -->
<origin xyz="0.2 0 0.075" rpy="0 0 0" />
<axis xyz="0 0 1" />
</joint>
</robot>
编译后,工作空间终端下调用如下命令执行:
ros2 launch cpp06_urdf display.launch.py model:=`ros2 pkg prefix --share cpp06_urdf`/urdf/urdf/demo04_basefootprint.urdf
执行指令后,在 rviz2 将Fixed Frame设置为base_footprint,机器人模型将正常显示在”地面“上。
三、URDF练习
创建一个四轮机器人模型,机器人参数如下:底盘为长方体状,长20cm宽12cm高7cm,车轮半径为2.5cm,车轮厚度为2cm,底盘离地间距为 1.5cm。
新建 urdf 文件 demo05_exercise.urdf,并编辑文件,输入如下内容:
<!--
练习:编写四轮差速机器人的底盘模型
参数:
长 0.2m
宽 0.12m
高 0.07m
离地 0.015m
车轮半径:0.025m
车轮厚度:0.02m
-->
<robot name="exercise_demo">
<!-- 定义颜色 -->
<material name="yellow">
<color rgba="0.7 0.7 0 0.8" />
</material>
<material name="red">
<color rgba="0.8 0.1 0.1 0.8" />
</material>
<material name="gray">
<color rgba="0.2 0.2 0.2 0.8" />
</material>
<link name="base_footprint">
<visual>
<geometry>
<sphere radius="0.001"/>
</geometry>
</visual>
</link>
<!-- 车体 -->
<link name="base_link">
<visual>
<!-- 形状 -->
<geometry>
<box size="0.2 0.12 0.07" />
</geometry>
<origin xyz="0 0 0" rpy="0 0 0" />
<material name="yellow"/>
</visual>
</link>
<joint name="baselink2basefootprint" type="fixed">
<parent link="base_footprint"/>
<child link="base_link"/>
<origin xyz="0.0 0.0 0.05"/>
</joint>
<!-- ==============车轮================= -->
<!-- 左前轮 -->
<link name="front_left_wheel">
<visual>
<geometry>
<cylinder radius="0.025" length="0.02"/>
</geometry>
<origin xyz="0 0 0" rpy="1.57 0 0" />
<material name="gray" />
</visual>
</link>
<!-- 左前轮关节 -->
<joint name="frontleftwheel2baselink" type="continuous">
<parent link="base_link"/>
<child link="front_left_wheel" />
<!-- 需要计算两个 link 的物理中心之间的偏移量 -->
<origin xyz="0.075 0.06 -0.025" rpy="0 0 0" />
<axis xyz="0 1 0" />
</joint>
<!-- 右前轮 -->
<link name="front_right_wheel">
<visual>
<geometry>
<cylinder radius="0.025" length="0.02"/>
</geometry>
<origin xyz="0 0 0" rpy="1.57 0 0" />
<material name="gray" />
</visual>
</link>
<!-- 右前轮关节 -->
<joint name="frontrightwheel2baselink" type="continuous">
<parent link="base_link"/>
<child link="front_right_wheel" />
<!-- 需要计算两个 link 的物理中心之间的偏移量 -->
<origin xyz="0.075 -0.06 -0.025" rpy="0 0 0" />
<axis xyz="0 1 0" />
</joint>
<!-- 左后轮 -->
<link name="back_left_wheel">
<visual>
<geometry>
<cylinder radius="0.025" length="0.02"/>
</geometry>
<origin xyz="0 0 0" rpy="1.57 0 0" />
<material name="gray" />
</visual>
</link>
<!-- 左后轮关节 -->
<joint name="backleftwheel2baselink" type="continuous">
<parent link="base_link"/>
<child link="back_left_wheel" />
<!-- 需要计算两个 link 的物理中心之间的偏移量 -->
<origin xyz="-0.075 0.06 -0.025" rpy="0 0 0" />
<axis xyz="0 1 0" />
</joint>
<!-- 右后轮 -->
<link name="back_right_wheel">
<visual>
<geometry>
<cylinder radius="0.025" length="0.02"/>
</geometry>
<origin xyz="0 0 0" rpy="1.57 0 0" />
<material name="gray" />
</visual>
</link>
<!-- 右后轮关节 -->
<joint name="backrightwheel2baselink" type="continuous">
<parent link="base_link"/>
<child link="back_right_wheel" />
<!-- 需要计算两个 link 的物理中心之间的偏移量 -->
<origin xyz="-0.075 -0.06 -0.025" rpy="0 0 0" />
<axis xyz="0 1 0" />
</joint>
</robot>
编译后,工作空间终端下调用如下命令执行:
ros2 launch cpp06_urdf display.launch.py model:=`ros2 pkg prefix --share cpp06_urdf`/urdf/urdf/demo05_exercise.urdf
命令执行后,rviz2 中可以显示与需求类似的机器人模型。
四、URDF工具
在 ROS2 中,提供了一些URDF文件相关的工具,比如:
check_urdf命令可以检查复杂的 urdf 文件是否存在语法问题;
urdf_to_graphviz命令可以查看 urdf 模型结构,显示不同 link 的层级关系。
当然,要使用工具之前,请先安装,安装命令:sudo apt install liburdfdom-tools
。
4.1 check_urdf 语法检查
进入urdf文件所属目录,调用:check_urdf urdf文件
,如果不抛出异常,说明文件合法,否则非法。示例,终端下进入功能包 cpp06_urdf 的 urdf/urdf 目录,执行如下命令:
check_urdf demo05_exercise.urdf
urdf 文件如无异常,将显示urdf中link的层级关系,如下图所示:
4.2 urdf_to_graphviz 结构查看
进入urdf文件所属目录,调用:urdf_to_graphviz urdf文件
,当前目录下会生成 pdf 文件。示例,终端下进入功能包 cpp06_urdf 的 urdf/urdf 目录,执行如下命令:
urdf_to_graphviz demo05_exercise.urdf
当前目录下,将生成以urdf中robot名称命名的.pdf和.gv文件,打开pdf文件会显示如下图内容:
注意:该工具以前名为urdf_to_graphiz
现建议使用urdf_to_graphviz
替代。
五、URDF优化之 xacro
Xacro 是 XML Macros 的缩写,Xacro 是一种 XML 宏语言,是可编程的 XML。Xacro 可以声明变量,可以通过数学运算求解;可以使用流程控制控制执行顺序;还可以通过宏封装、复用功能,从而提高代码复用率以及程序的安全性。较之于纯粹的 URDF 实现,可以编写更安全、精简、易读性更强的机器人模型文件,且可以提高编写效率。
5.1 xacro_使用语法
xacro 提供了可编程接口,类似于计算机语言,包括变量声明调用、函数声明与调用等语法实现。在使用 xacro 生成 urdf 时,根标签robot
中必须包含命名空间声明:xmlns:xacro="http://wiki.ros.org/xacro"
。
5.1.1 变量与算数运算
变量用于封装 URDF 中的一些字段,比如: PAI 值,小车的尺寸,轮子半径 ....,变量的基本使用语法包括变量定义、变量调用、变量运算等。
1.1 变量定义
语法格式:
<xacro:property name="变量名" value="变量值" />
示例:
<xacro:property name="PI" value="3.1416"/>
<xacro:property name="wheel_radius" value="0.025"/>
<xacro:property name="wheel_length" value="0.02"/>
1.2 变量调用
语法格式:
${变量名}
示例:
<geometry>
<cylinder radius="${wheel_radius}" length="${wheel_length}" />
</geometry>
1.3变量运算
语法格式:
${数学表达式}
示例:
<origin xyz="0 0 0" rpy="${PI / 2} 0 0" />
5.1.2 宏
类似于函数实现,提高代码复用率,优化代码结构,提高安全性。宏的基本使用语法包括宏的定义与调用。
2.1 宏定义
语法格式:
<xacro:macro name="宏名称" params="参数列表(多参数之间使用空格分隔)">
.....
参数调用格式: ${参数名}
</xacro:macro>
示例:
<xacro:macro name="wheel_func" params="wheel_name" >
<link name="${wheel_name}_wheel">
<visual>
<geometry>
<cylinder radius="${wheel_radius}" length="${wheel_length}" />
</geometry>
<origin xyz="0 0 0" rpy="${PI / 2} 0 0" />
<material name="wheel_color">
<color rgba="0 0 0 0.3" />
</material>
</visual>
</link>
</xacro:macro>
2.2 宏调用
语法格式:
<xacro:宏名称 参数1=xxx 参数2=xxx/>
示例:
<xacro:wheel_func wheel_name="left_front"/>
<xacro:wheel_func wheel_name="left_back"/>
<xacro:wheel_func wheel_name="right_front"/>
<xacro:wheel_func wheel_name="right_back"/>
5.1.3 文件包含
机器人由多部件组成,不同部件可能封装为单独的 xacro 文件,最后再将不同的文件集成,组合为完整机器人,可以使用文件包含实现。
语法格式:
<xacro:include filename="其他xacro文件" />
示例:
<robot name="car" xmlns:xacro="http://wiki.ros.org/xacro">
<xacro:include filename="car_base.xacro" />
<xacro:include filename="car_camera.xacro" />
<xacro:include filename="car_laser.xacro" />
</robot>
5.2 xacro_练习
使用xacro创建一个四轮机器人模型,该模型底盘可以参考上面案例的实现,并且在底盘之上添加了相机与激光雷达。相机与激光雷达的尺寸参数、安装位置可自定义。
需求中的机器人模型是由底盘、摄像头和雷达三部分组成的,那么可以将每一部分都封装进一个xacro文件,最后再通过xacro文件包含组织成一个完整的机器人模型。
功能包cpp06_urdf的urdf/xacro目录下,新建多个xacro文件,分别为:
car.urdf.xacro:用于包含不同机器人部件对应的xacro文件;
car_base.urdf.xacro:描述机器人底盘的xacro文件;
car_camera.urdf.xacro:描述摄像头的xacro文件;
car_laser.urdf.xacro:描述雷达的xacro文件。
编辑car.urdf.xacro文件,输入如下内容:
<robot name="car" xmlns:xacro="http://wiki.ros.org/xacro">
<xacro:include filename="car_base.urdf.xacro"/>
<xacro:include filename="car_camera.urdf.xacro"/>
<xacro:include filename="car_laser.urdf.xacro"/>
</robot>
编辑car_base.urdf.xacro文件,输入如下内容:
<robot xmlns:xacro="http://wiki.ros.org/xacro">
<!-- PI 值 -->
<xacro:property name="PI" value="3.1416"/>
<!-- 定义车辆参数 -->
<!-- 车体长宽高 -->
<xacro:property name="base_link_x" value="0.2"/>
<xacro:property name="base_link_y" value="0.12"/>
<xacro:property name="base_link_z" value="0.07"/>
<!-- 离地间距 -->
<xacro:property name="distance" value="0.015"/>
<!-- 车轮半径 宽度 -->
<xacro:property name="wheel_radius" value="0.025"/>
<xacro:property name="wheel_length" value="0.02"/>
<!-- 定义颜色 -->
<material name="yellow">
<color rgba="0.7 0.7 0 0.8" />
</material>
<material name="red">
<color rgba="0.8 0.1 0.1 0.8" />
</material>
<material name="gray">
<color rgba="0.2 0.2 0.2 0.95" />
</material>
<!-- 定义 base_footprint -->
<link name="base_footprint">
<visual>
<geometry>
<sphere radius="0.001"/>
</geometry>
</visual>
</link>
<!-- 定义 base_link -->
<link name="base_link">
<visual>
<!-- 形状 -->
<geometry>
<box size="${base_link_x} ${base_link_y} ${base_link_z}" />
</geometry>
<origin xyz="0 0 0" rpy="0 0 0" />
<material name="yellow"/>
</visual>
</link>
<joint name="baselink2basefootprint" type="fixed">
<parent link="base_footprint"/>
<child link="base_link"/>
<origin xyz="0.0 0.0 ${distance + base_link_z / 2}"/>
</joint>
<!-- 车轮宏定义 -->
<xacro:macro name="wheel_func" params="wheel_name is_front is_left" >
<link name="${wheel_name}_wheel">
<visual>
<geometry>
<cylinder radius="${wheel_radius}" length="${wheel_length}" />
</geometry>
<origin xyz="0 0 0" rpy="${PI / 2} 0 0" />
<material name="gray"/>
</visual>
</link>
<joint name="${wheel_name}2baselink" type="continuous">
<parent link="base_link" />
<child link="${wheel_name}_wheel" />
<origin xyz="${(base_link_x / 2 - wheel_radius) * is_front} ${base_link_y / 2 * is_left} ${(base_link_z / 2 + distance - wheel_radius) * -1}" rpy="0 0 0" />
<axis xyz="0 1 0" />
</joint>
</xacro:macro>
<!-- 车轮宏调用 -->
<xacro:wheel_func wheel_name="left_front" is_front="1" is_left="1" />
<xacro:wheel_func wheel_name="left_back" is_front="-1" is_left="1" />
<xacro:wheel_func wheel_name="right_front" is_front="1" is_left="-1" />
<xacro:wheel_func wheel_name="right_back" is_front="-1" is_left="-1" />
</robot>
编辑car_camera.urdf.xacro文件,输入如下内容:
<!-- 摄像头相关的 xacro 文件 -->
<robot xmlns:xacro="http://wiki.ros.org/xacro">
<!-- 摄像头属性 -->
<xacro:property name="camera_x" value="0.012" /> <!-- 摄像头长度(x) -->
<xacro:property name="camera_y" value="0.05" /> <!-- 摄像头宽度(y) -->
<xacro:property name="camera_z" value="0.01" /> <!-- 摄像头高度(z) -->
<xacro:property name="camera_joint_x" value="${base_link_x / 2 - camera_x / 2}" /> <!-- 摄像头安装的x坐标 -->
<xacro:property name="camera_joint_y" value="0.0" /> <!-- 摄像头安装的y坐标 -->
<xacro:property name="camera_joint_z" value="${base_link_z / 2 + camera_z / 2}" /> <!-- 摄像头安装的z坐标:底盘高度 / 2 + 摄像头高度 / 2 -->
<!-- 摄像头关节以及link -->
<link name="camera">
<visual>
<geometry>
<box size="${camera_x} ${camera_y} ${camera_z}" />
</geometry>
<origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0" />
<material name="red" />
</visual>
</link>
<joint name="camera2baselink" type="fixed">
<parent link="base_link" />
<child link="camera" />
<origin xyz="${camera_joint_x} ${camera_joint_y} ${camera_joint_z}" />
</joint>
</robot>
编辑car_laser.urdf.xacro文件,输入如下内容:
<!--
小车底盘添加雷达
-->
<robot xmlns:xacro="http://wiki.ros.org/xacro">
<material name="blue">
<color rgba="0.0 0.0 0.4 0.95" />
</material>
<!-- 雷达属性 -->
<xacro:property name="laser_length" value="0.03" /> <!-- 雷达长度 -->
<xacro:property name="laser_radius" value="0.03" /> <!-- 雷达半径 -->
<xacro:property name="laser_joint_x" value="0.0" /> <!-- 雷达安装的x坐标 -->
<xacro:property name="laser_joint_y" value="0.0" /> <!-- 雷达安装的y坐标 -->
<xacro:property name="laser_joint_z" value="${base_link_z / 2 + laser_length / 2}" /> <!-- 雷达安装的z坐标:车体高度 / 2 + 雷达高度 / 2 -->
<!-- 雷达关节以及link -->
<link name="laser">
<visual>
<geometry>
<cylinder radius="${laser_radius}" length="${laser_length}" />
</geometry>
<origin xyz="0.0 0.0 0.0" rpy="0.0 0.0 0.0" />
<material name="blue" />
</visual>
</link>
<joint name="laser2baselink" type="fixed">
<parent link="base_link" />
<child link="laser" />
<origin xyz="${laser_joint_x} ${laser_joint_y} ${laser_joint_z}" />
</joint>
</robot>
编译后,工作空间终端下调用如下命令执行:
ros2 launch cpp06_urdf display.launch.py model:=`ros2 pkg prefix --share cpp06_urdf`/urdf/xacro/car.urdf.xacro
命令执行后,rviz2 中可以显示与需求类似的机器人模型。
六、总结
URDF是用于描述机器人模型的xml文件,可以使用具有不同含义的标签描述机器人的各种属性,URDF文件编写完毕后,集成进rviz2即可显示机器人模型。另外鉴于URDF编写机器人模型代码冗余,在ROS2中还提供了xacro,xacro是可编程的URDF,可以以变量的方式封装机器人参数,以宏的方式实现代码复用,较之于URDF它的代码实现更为精简、高效且易读。