从零开始构建可视机器人模型

目标 了解如何构建可在 Rviz 中查看的机器人可视化模型

辅导水平: 中级

时间 20 分钟

备注

本教程假定您知道如何编写格式规范的 XML 代码

在本教程中,我们将制作一个外形酷似 R2D2 的机器人视觉模型。在后面的教程中,您将学习如何 阐明模式, 加入一些物理特性使用 xacro 生成更整洁的代码但现在,我们要把重点放在正确的几何图形上。

在继续之前,请确保您有 联合国家出版商 软件包。如果您安装了 urdf_tutorial 二进制文件,情况应该已经如此。如果没有,请更新您的安装以包含该软件包(使用 rosdep 来检查)。

本教程中提到的所有机器人模型(以及源文件)都可以在 urdf_tutorial 包装

一种形状

首先,我们只探讨一个简单的形状。这是一个最简单的 urdf。 [来源:01-myfirst.urdf]

<?xml版本="1.0"?>;
机器人 名称"我的第一次";>;
  链接 名称"base_link";>;
    视觉效果
      <几何>;
        气缸 长度="0.6"; 半径="0.2";/>;
      </geometry>;
    </visual>;
  </link>;
</机器人>;

将 XML 翻译成英文,这是一个名为 我的第一,只包含一个链接(又称部件),其视觉组件只是一个长 0.6 米、半径 0.2 米的圆柱体。对于一个简单的 "hello world"(你好世界)类型的示例来说,这看起来似乎有很多外层标签,但它会变得更加复杂,相信我。

要检查模型,请启动 display.launch.py 锉刀

ros2 launch urdf_tutorial display.launch.py model:=urdf/01-myfirst.urdf

这样做有三个目的:

  • 加载指定的模型,并将其保存为 机器人状态发布者 节点。

  • 运行节点进行发布 sensor_msgs/msg/JointState 和变换(稍后详述)

  • 使用配置文件启动 Rviz

启动后 display.launch.py然后,RViz 就会向您显示以下内容:

我的第一张照片
需要注意的事项
  • 固定框架是网格中心所在的变换框架。在这里,它是由我们的一个链接(base_link)定义的框架。

  • 默认情况下,视觉元素(圆柱体)的原点位于其几何中心。因此,圆柱体的一半位于网格下方。

多种形状

现在我们来看看如何添加多个形状/链接。如果我们只是在 urdf 中添加更多链接元素,解析器将不知道把它们放在哪里。因此,我们必须添加关节。关节元素既可以指灵活的关节,也可以指不灵活的关节。我们先从不灵活或固定的关节开始。 [来源:02-multipleshapes.urdf]

<?xml版本="1.0"?>;
机器人 名称"多重形状";>;
  链接 名称"base_link";>;
    视觉效果
      <几何>;
        气缸 长度="0.6"; 半径="0.2";/>;
      </geometry>;
    </visual>;
  </link>;

  链接 名称"right_leg";>;
    视觉效果
      <几何>;
        <box size="0.6 0.1 0.2";/>;
      </geometry>;
    </visual>;
  </link>;

  <joint 名称"base_to_right_leg"; type="固定";>;
    <parent link="base_link";/>;
    孩子 link="right_leg";/>;
  </joint>;

</机器人>;
  • 请注意我们是如何定义 0.6 米 x 0.1 米 x 0.2 米方框的

  • 连接是以父节点和子节点来定义的。URDF 最终是一个只有一个根链接的树形结构。这意味着腿的位置取决于根链接的位置。

ros2 launch urdf_tutorial display.launch.py model:=urdf/02-multipleshapes.urdf
多种形状

这两个图形相互重叠,因为它们共享同一个原点。如果我们想让它们不重叠,就必须定义更多的原点。

起源

R2D2 的腿连接到躯干上半部分的侧面。因此,我们要在这里指定 JOINT 的原点。此外,R2D2 的腿并不是连接在中间,而是连接在上半部分,因此我们也必须偏移腿的原点。我们还可以旋转腿部,使其直立。 [来源:03-origins.urdf]

<?xml版本="1.0"?>;
机器人 名称"起源";>;
  链接 名称"base_link";>;
    视觉效果
      <几何>;
        气缸 长度="0.6"; 半径="0.2";/>;
      </geometry>;
    </visual>;
  </link>;

  链接 名称"right_leg";>;
    视觉效果
      <几何>;
        <box size="0.6 0.1 0.2";/>;
      </geometry>;
      原产地 rpy="0 1.57075 0"; xyz="0 0 -0.3";/>;
    </visual>;
  </link>;

  <joint 名称"base_to_right_leg"; type="固定";>;
    <parent link="base_link";/>;
    孩子 link="right_leg";/>;
    原产地 xyz="0 -0.22 0.25";/>;
  </joint>;

</机器人>;
  • 我们先来看看关节的原点。它是根据父参照系定义的。因此,我们在 y 方向的距离是-0.22 米(在我们的左侧,但相对于坐标轴是在右侧),在 z 方向的距离是 0.25 米(向上)。这意味着,无论子链接的视觉原点标签是什么,子链接的原点都将是向上和向右。由于我们没有指定 rpy(滚动俯仰偏航)属性,子帧将默认具有与父帧相同的方向。

  • 现在,我们来看看这条腿的视觉原点,它有 xyz 和 rpy 偏移。这定义了视觉元素相对于原点的中心位置。由于我们希望支腿连接在顶部,因此我们将 Z 偏移量设置为-0.3 米,从而将原点向下偏移。由于我们希望腿的长部分与 Z 轴平行,因此我们将视觉部分绕 Y 轴旋转 PI/2。

ros2 launch urdf_tutorial display.launch.py model:=urdf/03-origins.urdf
起源》截图
  • 启动文件运行的软件包将根据 URDF 为模型中的每个链接创建 TF 框架。Rviz 会使用这些信息来确定每个形状的显示位置。

  • 如果给定的 URDF 链路不存在 TF 帧,那么它将被置于白色的原点(参考文献)。 相关问题).

物质女孩

"好吧,"我听到你说。"这很可爱,但不是每个人都有 B21。我的机器人和 R2D2 都不是红色的!"说得好让我们来看看材料标签。 [来源:04-materials.urdf]

<?xml版本="1.0"?>;
机器人 名称"材料";>;

  材料 名称蓝色;>;
    颜色 rgba="0 0 0.8 1";/>;
  </material>;

  材料 名称"白色";>;
    颜色 rgba="1 1 1 1";/>;
  </material>;

  链接 名称"base_link";>;
    视觉效果
      <几何>;
        气缸 长度="0.6"; 半径="0.2";/>;
      </geometry>;
      材料 名称蓝色;/>;
    </visual>;
  </link>;

  链接 名称"right_leg";>;
    视觉效果
      <几何>;
        <box size="0.6 0.1 0.2";/>;
      </geometry>;
      原产地 rpy="0 1.57075 0"; xyz="0 0 -0.3";/>;
      材料 名称"白色";/>;
    </visual>;
  </link>;

  <joint 名称"base_to_right_leg"; type="固定";>;
    <parent link="base_link";/>;
    孩子 link="right_leg";/>;
    原产地 xyz="0 -0.22 0.25";/>;
  </joint>;

  链接 名称"左腿";>;
    视觉效果
      <几何>;
        <box size="0.6 0.1 0.2";/>;
      </geometry>;
      原产地 rpy="0 1.57075 0"; xyz="0 0 -0.3";/>;
      材料 名称"白色";/>;
    </visual>;
  </link>;

  <joint 名称"base_too_left_leg"; type="固定";>;
    <parent link="base_link";/>;
    孩子 link="左腿";/>;
    原产地 xyz="0 0.22 0.25";/>;
  </joint>;

</机器人>;
  • 身体现在是蓝色的。我们定义了一个名为 "蓝色 "的新材质,红色、绿色、蓝色和 alpha 通道分别定义为 0、0、0.8 和 1。所有值的范围都是 [0,1]。然后,base_link 的视觉元素就会引用该材质。白色材质的定义与此类似。

  • 你也可以在视觉元素中定义材质标签,甚至在其他链接中引用它。不过,如果你重新定义它,根本不会有人抱怨。

  • 您还可以使用纹理来指定用于为对象着色的图像文件

ros2 launch urdf_tutorial display.launch.py model:=urdf/04-materials.urdf
材料截图

完成模型

现在,我们再为模型添加一些形状:脚、轮子和头。最值得注意的是,我们添加了一个球体和一些网格。我们还将添加一些稍后会用到的其他部件。 [来源:05-visual.urdf]

<?xml版本="1.0"?>;
机器人 名称"视觉";>;

  材料 名称蓝色;>;
    颜色 rgba="0 0 0.8 1";/>;
  </material>;
  材料 名称"黑色";>;
    颜色 rgba="0 0 0 1";/>;
  </material>;
  材料 名称"白色";>;
    颜色 rgba="1 1 1 1";/>;
  </material>;

  链接 名称"base_link";>;
    视觉效果
      <几何>;
        气缸 长度="0.6"; 半径="0.2";/>;
      </geometry>;
      材料 名称蓝色;/>;
    </visual>;
  </link>;

  链接 名称"right_leg";>;
    视觉效果
      <几何>;
        <box size="0.6 0.1 0.2";/>;
      </geometry>;
      原产地 rpy="0 1.57075 0"; xyz="0 0 -0.3";/>;
      材料 名称"白色";/>;
    </visual>;
  </link>;

  <joint 名称"base_to_right_leg"; type="固定";>;
    <parent link="base_link";/>;
    孩子 link="right_leg";/>;
    原产地 xyz="0 -0.22 0.25";/>;
  </joint>;

  链接 名称"right_base";>;
    视觉效果
      <几何>;
        <box size="0.4 0.1 0.1";/>;
      </geometry>;
      材料 名称"白色";/>;
    </visual>;
  </link>;

  <joint 名称"right_base_joint"; type="固定";>;
    <parent link="right_leg";/>;
    孩子 link="right_base";/>;
    原产地 xyz="0 0 -0.6";/>;
  </joint>;

  链接 名称"right_front_wheel";>;
    视觉效果
      原产地 rpy="1.57075 0 0"; xyz="0 0 0";/>;
      <几何>;
        气缸 长度="0.1"; 半径="0.035";/>;
      </geometry>;
      材料 名称"黑色";/>;
    </visual>;
  </link>;
  <joint 名称"right_front_wheel_joint"; type="固定";>;
    <parent link="right_base";/>;
    孩子 link="right_front_wheel";/>;
    原产地 rpy="0 0 0"; xyz="0.133333333333 0 -0.085";/>;
  </joint>;

  链接 名称"right_back_wheel";>;
    视觉效果
      原产地 rpy="1.57075 0 0"; xyz="0 0 0";/>;
      <几何>;
        气缸 长度="0.1"; 半径="0.035";/>;
      </geometry>;
      材料 名称"黑色";/>;
    </visual>;
  </link>;
  <joint 名称"right_back_wheel_joint"; type="固定";>;
    <parent link="right_base";/>;
    孩子 link="right_back_wheel";/>;
    原产地 rpy="0 0 0"; xyz="-0.133333333333 0 -0.085";/>;
  </joint>;

  链接 名称"左腿";>;
    视觉效果
      <几何>;
        <box size="0.6 0.1 0.2";/>;
      </geometry>;
      原产地 rpy="0 1.57075 0"; xyz="0 0 -0.3";/>;
      材料 名称"白色";/>;
    </visual>;
  </link>;

  <joint 名称"base_too_left_leg"; type="固定";>;
    <parent link="base_link";/>;
    孩子 link="左腿";/>;
    原产地 xyz="0 0.22 0.25";/>;
  </joint>;

  链接 名称"left_base";>;
    视觉效果
      <几何>;
        <box size="0.4 0.1 0.1";/>;
      </geometry>;
      材料 名称"白色";/>;
    </visual>;
  </link>;

  <joint 名称"left_base_joint"; type="固定";>;
    <parent link="左腿";/>;
    孩子 link="left_base";/>;
    原产地 xyz="0 0 -0.6";/>;
  </joint>;

  链接 名称"left_front_wheel";>;
    视觉效果
      原产地 rpy="1.57075 0 0"; xyz="0 0 0";/>;
      <几何>;
        气缸 长度="0.1"; 半径="0.035";/>;
      </geometry>;
      材料 名称"黑色";/>;
    </visual>;
  </link>;
  <joint 名称"left_front_wheel_joint"; type="固定";>;
    <parent link="left_base";/>;
    孩子 link="left_front_wheel";/>;
    原产地 rpy="0 0 0"; xyz="0.133333333333 0 -0.085";/>;
  </joint>;

  链接 名称"left_back_wheel";>;
    视觉效果
      原产地 rpy="1.57075 0 0"; xyz="0 0 0";/>;
      <几何>;
        气缸 长度="0.1"; 半径="0.035";/>;
      </geometry>;
      材料 名称"黑色";/>;
    </visual>;
  </link>;
  <joint 名称"left_back_wheel_joint"; type="固定";>;
    <parent link="left_base";/>;
    孩子 link="left_back_wheel";/>;
    原产地 rpy="0 0 0"; xyz="-0.133333333333 0 -0.085";/>;
  </joint>;

  <joint 名称"gripper_extension"; type="固定";>;
    <parent link="base_link";/>;
    孩子 link="gripper_pole";/>;
    原产地 rpy="0 0 0"; xyz="0.19 0 0.2";/>;
  </joint>;

  链接 名称"gripper_pole";>;
    视觉效果
      <几何>;
        气缸 长度="0.2"; 半径="0.01";/>;
      </geometry>;
      原产地 rpy="0 1.57075 0 "; xyz="0.1 0 0";/>;
    </visual>;
  </link>;

  <joint 名称"left_gripper_joint"; type="固定";>;
    原产地 rpy="0 0 0"; xyz="0.2 0.01 0";/>;
    <parent link="gripper_pole";/>;
    孩子 link="left_gripper";/>;
  </joint>;

  链接 名称"left_gripper";>;
    视觉效果
      原产地 rpy="0.0 0.0"; xyz="0 0 0";/>;
      <几何>;
        <mesh filename="package://urdf_tutorial/meshes/l_finger.dae";/>;
      </geometry>;
    </visual>;
  </link>;

  <joint 名称"left_tip_joint"; type="固定";>;
    <parent link="left_gripper";/>;
    孩子 link=quot;left_tip";/>;
  </joint>;

  链接 名称quot;left_tip";>;
    视觉效果
      原产地 rpy="0.0 0.0"; xyz="0.09137 0.00495 0";/>;
      <几何>;
        <mesh filename="package://urdf_tutorial/meshes/l_finger_tip.dae";/>;
      </geometry>;
    </visual>;
  </link>;
  <joint 名称"right_gripper_joint"; type="固定";>;
    原产地 rpy="0 0 0"; xyz="0.2 -0.01 0";/>;
    <parent link="gripper_pole";/>;
    孩子 link="right_gripper";/>;
  </joint>;

  链接 名称"right_gripper";>;
    视觉效果
      原产地 rpy="-3.1415 0 0"; xyz="0 0 0";/>;
      <几何>;
        <mesh filename="package://urdf_tutorial/meshes/l_finger.dae";/>;
      </geometry>;
    </visual>;
  </link>;

  <joint 名称"right_tip_joint"; type="固定";>;
    <parent link="right_gripper";/>;
    孩子 link="right_tip";/>;
  </joint>;

  链接 名称"right_tip";>;
    视觉效果
      原产地 rpy="-3.1415 0 0"; xyz="0.09137 0.00495 0";/>;
      <几何>;
        <mesh filename="package://urdf_tutorial/meshes/l_finger_tip.dae";/>;
      </geometry>;
    </visual>;
  </link>;

  链接 名称"head";>;
    视觉效果
      <几何>;
        <sphere 半径="0.2";/>;
      </geometry>;
      材料 名称"白色";/>;
    </visual>;
  </link>;
  <joint 名称"head_swivel"; type="固定";>;
    <parent link="base_link";/>;
    孩子 link="head";/>;
    原产地 xyz="0 0 0.3";/>;
  </joint>;

  链接 名称"box";>;
    视觉效果
      <几何>;
        <box size="0.08 0.08 0.08";/>;
      </geometry>;
      材料 名称蓝色;/>;
    </visual>;
  </link>;

  <joint 名称"tobox"; type="固定";>;
    <parent link="head";/>;
    孩子 link="box";/>;
    原产地 xyz="0.1814 0 0.1414";/>;
  </joint>;
</机器人>;
ros2 launch urdf_tutorial display.launch.py model:=urdf/05-visual.urdf
视觉截图

如何添加球体应该不难解释:

链接 名称"head";>;
  视觉效果
    <几何>;
      <sphere 半径="0.2";/>;
    </geometry>;
    材料 名称"白色";/>;
  </visual>;
</link>;

这里的网格是从 PR2 中借用的。它们是独立的文件,需要指定路径。您应该使用 package://NAME_OF_PACKAGE/path 符号。本教程的网格位于 urdf_tutorial 包中名为 meshes 的文件夹。

链接 名称"left_gripper";>;
  视觉效果
    原产地 rpy="0.0 0.0"; xyz="0 0 0";/>;
    <几何>;
      <mesh filename="package://urdf_tutorial/meshes/l_finger.dae";/>;
    </geometry>;
  </visual>;
</link>;
  • 网格可以多种不同格式导入。STL 是比较常见的格式,但引擎也支持 DAE,它可以有自己的颜色数据,这意味着你不必指定颜色/材料。通常这些都是单独的文件。这些网格参照 .tif 文件也在网格文件夹中。

  • 也可以使用相对缩放参数或边界框尺寸来调整网格大小。

  • 我们也可以在完全不同的软件包中引用网格。

就是这样。一个类似 R2D2 的 URDF 模型。现在你可以继续下一步了、 使其移动.