当前位置: 首页 > article >正文

【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文件会显示如下图内容:

图中会以树形结构显示link与joint的关系

注意:该工具以前名为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它的代码实现更为精简、高效且易读。


http://www.kler.cn/a/469805.html

相关文章:

  • 【GOOD】A Survey of Deep Graph Learning under Distribution Shifts
  • PyTorch 自动混合精度AMP Grad Scaler 源码解析:_unscale_grads_ 与 unscale_ 函数
  • 统计字符【2】(PTA)C语言
  • SpringMVC的消息转换器
  • .NET 9.0 WebApi 发布到 IIS 详细步骤
  • jenkins入门9--参数化构建
  • 【SOC 芯片设计 DFT 学习专栏 -- ATE 测试中 at-speed 测试】
  • SQL-leetcode-262. 行程和用户
  • Android Studio 下载安装教程(2024 更新版),附详细图文
  • (CICD)自动化构建打包、部署(Jenkins + maven+ gitlab+tomcat)
  • 解决报错net.sf.jsqlparser.statement.select.SelectBody
  • Git revert回滚
  • 网络安全应急响应技术原理与应用
  • 同步与并发:Java的同步舞蹈
  • 修改 Redis 中键的字段值:string和hash类型的区别
  • DevSecOps:在不断变化的威胁环境中加强移动应用安全
  • GESP2023年12月认证C++五级( 第三部分编程题(1)小杨的幸运数)
  • leetcode739.每日温度
  • C++二十三种设计模式之原型模式
  • 浏览器解析过程
  • Python中超过15位小数的高精度计算
  • springCloudGateWay使用总结
  • 【操作系统】课程 4调度与死锁 同步测练 章节测验
  • C语言:枚举类型
  • Markdown编辑器——Typora(Picgo+Github图床)
  • 【归一化】RMSNorm