URDF和机器人模型(二)
在上一篇文章中,我们使用URDF建立了R2D2机器人的模型。 但那仅仅是一个视图模型,虽然也描述了机器人的Link和Joint,但Joint是固定的(fixed),整个机器人是不能动的。对于我们来说,一个不能动的机器人是不好玩的。 在本文中,我们将介绍另外三种Joint,它们可以赋予机器人运动的能力。
我们知道对于一个机器人的建模不仅仅是用一个3D引擎把机器人的样子渲染出来,为了仿真和控制机器人我们还需要描述机器人的碰撞模型、物理属性,用于建模分析和规划运算。 这些模型在URDF中就是各种标签而已,本文做简单的介绍。
1. Joint
现在,我们来查看一个具有运动功能的机器人。仍然通过urdf_tutorial中的display.launch工具来查看模型06-flexible.urdf。我们可以将之与05-visual.urdf对比, 查看两者之间的不同。这里我们只关注其中的三个关节:head_swivel, left_gripper_joint, gripper_extension。
$ roscd urdf_tutorial
$ roslaunch urdf_tutorial display.launch model:=urdf/06-flexible.urdf gui:=true
在运行display.launch的时候,我们增加了一个gui的参数,它就是用来打开一个GUI工具栏。拖动工具栏中的各个关节的滑动条,我们可以看到对应关节发生转动。
接下来,让我们来看一下关节"head_swivel",它的描述如下:
<joint name="head_swivel" type="continuous">
<parent link="base_link"/>
<child link="head"/>
<axis xyz="0 0 1"/>
<origin xyz="0 0 0.3"/>
</joint>
head_swivel是连接头和躯干的关节,其类型被定义为continuous,这意味着它的值可以从负无穷变化到正无穷,是一种旋转的关节。一般轮子也会定义称这种关节,
这样它就可以正向或者反向无限的转动下去。但GUI工具栏不能描述\([-\infty, +\infty]\)的区间,它只是在\([-\pi,\pi]\)转动。
在描述关节转动时,我们还需要指定一个转轴,它是通过标签axis来描述的。axis描述的转轴的方向向量,这里R2D2的脑袋是绕着Z轴旋转的,所以我们定义xyz="0 0 1"。 因为通常我们对一个轮子的期望就是一直转,所以一般不用给continuous类型的关节添加什么约束。
left_gripper_joint也是一种旋转的关节,它被定义为revolute。revolute与continuous相比就是一定要有一个约束项,它通过limit标签来描述。 这里的约束是指该关节可以转动的位置最小为0弧度,最大为0.548弧度,最大转速为0.5弧度每秒,作用力小于1000。
<joint name="left_gripper_joint" type="revolute">
<axis xyz="0 0 1"/>
<limit effort="1000.0" lower="0.0" upper="0.548" velocity="0.5"/>
<origin rpy="0 0 0" xyz="0.2 0.01 0"/>
<parent link="gripper_pole"/>
<child link="left_gripper"/>
</joint>
grippe_extension则是一种直线运动的关节,其类型为prismatic。与revolute和continuous不同的是,prismatic并不是绕着指定轴转动,它是沿着指定轴进行直线的移动。 对其约束的描述也是用limit标签来实现的,但它的量纲为米。
<joint name="gripper_extension" type="prismatic">
<axis xyz="1 0 0"/>
<parent link="base_link"/>
<child link="gripper_pole"/>
<limit effort="1000.0" lower="-0.38" upper="0" velocity="0.5"/>
<origin rpy="0 0 0" xyz="0.19 0 0.2"/>
</joint>
理论上,通过这三种关节的形式,我们可以描述任何类型的机械运动结构。但ROS还提供了一些其它类型的Joint,比如一个plannar关节可以在一个平面上移动,一个floating的关节则没有什么约束, 可以在空间中随意移动。由于这些关节的状态都不能够通过一个变量来表示,而且理论上它们可以通过上述三种类型的关节组合得到,所以我们在这里不对它们做更多的介绍。
我们在移动GUI的滑动条的时候,Rviz中模型会跟着移动,这是怎么实现的呢?首先GUI的程序中有一个解析器用来解析URDF,并找出其中所有非固定的关节以及它们的约束。 接着,GUI发布一个sensor_msgs/JointState的消息。这个消息将被robot_state_publisher节点用于计算机器人各个部分的坐标变换关系。变换后的结果就被Rviz用来更新模型的显示。
2. 碰撞模型
到目前为止,我们只是描述了机器人模型的可视化信息。但使用Gazebo做仿真的时候,我们还需要用到碰撞模型。下面是一个添加了碰撞描述的base_link:
<link name="base_link">
<visual>
<geometry>
<cylinder length="0.6" radius="0.2"/>
</geometry>
<material name="blue">
<color rgba="0 0 .8 1"/>
</material>
</visual>
<collision>
<geometry>
<cylinder length="0.6" radius="0.2"/>
</geometry>
</collision>
</link>
碰撞描述是用collision标签来描述的,它是link标签下与visual同级的一个标签。在collision中,与visual一样建立了一个几何体来描述机器人的形状和尺寸。
实际上这个几何形状可以不与visual中的一样,我们完全可以建一个长方体,只要仿真的时候合理就可以了。同样我们也可以添加坐标系的描述。这些都是根据实际需要,仿真效果、计算量综合考量后的结果。
3. 物理属性
在仿真中除了可视化和碰撞模型之外,我们往往还需要描述一些物理属性的。下面是一个描述机器人质量的模型:
<inertial>
<mass value="10"/>
<inertia ixx="0.4" ixy="0.0" ixz="0.0" iyy="0.4" iyz="0.0" izz="0.2"/>
</inertial>
它也就是一个inertial标签,与碰撞模型和可视化模型是一个级的。其中的mass描述了质量,inertia则描述了惯量矩阵。
由于惯量矩阵是一个对称矩阵所以这里只用了6个变量来描述\(\begin{bmatrix} ixx & ixy & ixz \\ ixy & iyy & iyz \\ ixz & iyz & izz \end{bmatrix}\)。
此外,我们还可以在碰撞模型collision标签下添加一些子标签来描述表面的摩擦系数、阻尼系数、刚度等表面的物理特性。对于关节我们还可以添加摩擦和阻尼两个属性。 关于这些物理特性,我们在以后关于仿真的教程中如果用到的话再做详细的介绍。
4. 总结
机器人模型的关节有continuous, revolute和prismatic三种基本的类型,基本上所有的机械运动都可以归结为这些关节的组合。
此外,我们可以通过collision和inertial标签来描述碰撞模型和Link的质量,惯性张量等物理属性,它们是进行仿真的重要参数。