预计完成时间:15 分钟
你已经创建了第一个只有单一元素的机器人模型,也就是一个连杆。那么,一个连杆由哪些部分组成呢?
每个连杆都必须包含以下属性:
它包含 质量(kg)、原点(m) 和 惯性矩阵(kg·m²)。
<inertial>
<mass value="10" />
<origin
xyz="0 0 0.3"
rpy="0 0 0" />
<inertia
ixx="1.5417"
ixy="0"
ixz="0"
iyy="3.467"
iyz="0"
izz="4.742" />
</inertial>
在这个例子中,collision 和 visual 看起来是相同的,但它们的用途不同。模拟器使用 collision 来计算连杆之间的物理交互;visual 仅用于渲染显示,不会影响连杆与其他对象的交互方式。
如果你的可视网格非常复杂,但又不希望在物理交互上做不必要的高强度计算,或者想节省算力,就可以让 collision 和 visual 使用不同的几何定义。
<collision>
<geometry>
<box size="2 1.3 0.4" />
</geometry>
</collision>
<visual>
<geometry>
<box size="2 1.3 0.4" />
</geometry>
</visual>
关节用于连接各个连杆,并在它们之间建立运动关系。在本单元中,你要构建的是移动机器人,因此接下来要给你创建的底盘加上一只车轮。
继续在 robot.urdf 文件中,在 </link> 结束标签之后添加以下代码:
复制并粘贴
<!-- Joint - chassis / left wheel -->
<joint name="joint_chassis_left_wheel" type="continuous">
<origin rpy="0 0 0" xyz="-0.5 0.65 0" />
<child link="link_left_wheel" />
<parent link="link_chassis" />
<axis rpy="0 0 0" xyz="0 1 0" />
<limit effort="10000" velocity="1000" />
<joint_properties damping="1.0" friction="1.0" />
</joint>
<!-- Link - left wheel -->
<link name="link_left_wheel">
<inertial>
<mass value="1" />
<origin xyz="0 0 0" rpy="0 0 0" />
<inertia ixx="0.002526666666667" ixy="0" ixz="0" iyy="0.002526666666667" iyz="0" izz="0.005"/>
</inertial>
<collision>
<origin rpy="0 0 1.5707" xyz="0 0.18 0" />
<geometry>
<cylinder length="0.12" radius="0.4"/>
</geometry>
</collision>
<visual>
<origin rpy="0 0 1.5707" xyz="0 0.18 0" />
<geometry>
<cylinder length="0.12" radius="0.4"/>
</geometry>
</visual>
<collision>
<origin rpy="0 0 1.5707" xyz="0 0.06 0" />
<geometry>
<cylinder length="0.12" radius="0.08"/>
</geometry>
</collision>
<visual>
<origin rpy="0 0 1.5707" xyz="0 0.06 0" />
<geometry>
<cylinder length="0.12" radius="0.08"/>
</geometry>
</visual>
</link>
这里你有两组 collision 和 visual 标签,它们各自对应不同的部分。一个连杆中可以包含多组这样的标签,数量并不受限。它们都会按照关节的位置关系显示出来。
在这个例子里,你分别为车轮本体和它的轮轴创建了一组可视与碰撞定义。
重新启动 rviz.launch.py 文件。
在 Web Shell 1 中执行
cd /workspace; colcon build --packages-select robot_description; source install/setup.bash
ros2 launch robot_description rviz.launch.py
你应该得到如下结果:

但是等等……车轮去哪了?这里发生了什么?
这是因为你当前只运行了 Robot State Publisher 和 RViz。这个节点只会发布机器人固定关节的状态(这里是底盘),不会发布可动关节的状态(例如车轮)。如果想把这些可动关节显示出来,你还需要一个能够提供关节状态的节点,这就是 Joint State Publisher GUI 的作用。
要启动 Joint State Publisher GUI,请在一个新的 web shell 中运行以下命令:
提示: 如果系统提示找不到 joint_state_publisher_gui,请先执行:
sudo apt install ros-humble-joint-state-publisher-gui
在 Web Shell 2 中执行
ros2 run joint_state_publisher_gui joint_state_publisher_gui
现在你会看到类似下面的界面:

注意,现在你已经可以通过滑块来控制车轮旋转了。
当然,这还不是车轮期望的安装位置或旋转方式。那么问题出在哪里呢?
来看一下关节定义:
<joint name="joint_chassis_left_wheel" type="continuous">
<origin rpy="0 0 0" xyz="-0.5 0.88 0" />
<child link="link_left_wheel" />
<parent link="link_chassis" />
<axis rpy="0 0 0" xyz="0 1 0" />
<limit effort="10000" velocity="1000" />
<joint_properties damping="1.0" friction="1.0" />
</joint>
第一个属性 type 用来定义该连杆能够进行哪一种运动。常见类型包括 continuous、revolute、prismatic 和 fixed。除此之外还有其他类型,你可以在这里查看完整参考:http://wiki.ros.org/urdf/XML/joint。
origin 属性用于定义关节相对于底盘的位置。底盘连杆起始于 0 0 0,长度为 2 米,宽度为 1.3 米。底盘会向两侧延伸,因此它的侧边界位于 1.3/2,也就是 0.65 米 的位置。
接着,需要定义 child 和 parent 连杆。再比如 axis,它用来指定转动轴。你还可以通过 limit 设置最大力矩和速度,不过现在这部分并不是重点。当前阶段你主要是在设计机器人的几何结构,而与运动动力学相关的 joint properties 会在后续再讨论。
最后来看 axis 定义。这里决定该连杆绕哪一个坐标轴旋转。在这个例子中,你希望它绕 Y 轴旋转,这个设置是正确的。
问题在于,你的这个 link 圆柱几何体(长度和半径)是按照 Z 轴方向定义的,因此需要绕 X 轴旋转一下才能修正。
回到左轮的连杆定义,把 collision 和 visual 标签中的 origin 属性改成绕 X 轴旋转 90 度:
<link name="link_left_wheel">
...
<collision>
<origin rpy="1.5707 0 0" xyz="0 0.18 0" />
<geometry>
<cylinder length="0.12" radius="0.4"/>
</geometry>
</collision>
<visual>
<origin rpy="1.5707 0 0" xyz="0 0.18 0" />
<geometry>
<cylinder length="0.12" radius="0.4"/>
</geometry>
</visual>
<collision>
<origin rpy="1.5707 0 0" xyz="0 0.06 0" />
<geometry>
<cylinder length="0.12" radius="0.08"/>
</geometry>
</collision>
<visual>
<origin rpy="1.5707 0 0" xyz="0 0.06 0" />
<geometry>
<cylinder length="0.12" radius="0.08"/>
</geometry>
</visual>
...
重新启动 rviz.launch,并同时运行 Joint State Publisher GUI。
在 Web Shell 1 中执行
cd /workspace; colcon build --packages-select robot_description; source install/setup.bash
ros2 launch robot_description rviz.launch.py
在 Web Shell 2 中执行
ros2 run joint_state_publisher_gui joint_state_publisher_gui

查看下图中的机器人尺寸,你会更容易理解为什么 XML 定义里使用的是这些数值:

完善当前模型并把它补全!
在这个练习中,再补充以下几个部分,让机器人更完整:

请参考下图来创建脚轮的固定关节以及可视部件。

注意: 当前 ROS2 RVIZ2 中存在一个 Bug:URDF 中父连杆的颜色会传递到子连杆上,因此 RVIZ 中显示的颜色可能与 URDF 文件中的定义并不完全一致。更多信息请参考 RVIZ2 的颜色 Bug。
