ROS2与Gazebo11入门教程-三角网格的惯性参数
说明:
- 介绍三角网格的惯性参数
概述
精确的仿真需要合理的物理惯性参数:质量、质心位置以及所有链接的惯性矩矩阵。
本节教程将指导您完成获取和设置这些参数的整个过程,如果您有一些链接的3D模型的话。
在均质体(均质密度)假设条件下,这里将会说明如何使用免费软件MeshLab来获得惯性数据。
如果您希望跳过设置而仅计算模型的体积、质心或惯性属性,或快速清洗模型,则可以使用网格清洗器(Mesh Cleaner),该工具会在内部运行MeshLab来完成这个目的。
也可以使用商业产品SolidWorks来计算这些信息。
有关使用SolidWorks的指南,请参阅answer.ros.org网站上的这个提问。
惯性参数概要
质量(Mass),通过称量物体可以最容易地测量物体的质量。在Gazebo中,质量是一个具有默认单位的标量,其单位为千克(kg)。对于一个均匀的3D网格,可以通过计算其几何体积[length3]并乘以其密度[mass / length3]来计算其质量。
质心(Center of Mass),质心是加权质量矩之和为零的点。均质物体的质心等于其几何质心。质心参数是一个具有位置[length]单位的三维矢量(Vector3)。
惯性矩矩阵(Moment of Inertia Matrix),惯性矩代表一个刚体中质量的空间分布。惯性矩取决于物体的质量、尺寸和形状,其单位为[质量*长度2]。惯性矩可以表示为一个对称正定3×3矩阵的分量,有3个对角元素和3个唯一的非对角元素。每个惯性矩阵都是相对于一个坐标系或一组轴来定义的。对该矩阵进行对角线化会产生其主惯性矩(特征值)及其主轴方向(特征向量)。
惯性矩与质量成正比,但这是一种相对于尺寸的非线性正比关系。另外,对主惯性矩的相对值存在约束,这使得估算惯性矩通常要比估算质量或质心位置困难得多。这种困难促使人们使用软件工具来计算惯性矩。
如果您对惯性矩阵背后的数学原理感到好奇,或者只是想要一种简单的方法来计算简单形状的张量,那么这个Wikipedia条目是一个很好的资源。
准备工作
- 即安装MeshLab软件。该软件的安装应该很简单, 从官方网站下载MeshLab并将其安装在您的计算机上。
- 安装好该软件后,您就可以在MeshLab中浏览您的网格(同时支持DAE和STL格式,Gazebo/ROS也支持这些文件格式)。
计算惯性参数
计算球体的惯性参数
在MeshLab中打开网格文件。本示例将会使用一个sphere.dae网格。
要计算其惯性参数,首先需要显示层(Layers)对话框,即从“视图(View)”->“显示层对话框(Show Layer Dialog)”菜单打开该对话框。
窗口右侧会打开一个面板,该面板被分成上下两半——我们对包含文本输出的下半部分感兴趣。
接下来,命令MeshLab计算惯性参数。
从菜单中选择“过滤器(Filters)”->“质量度量和计算(Quality Measure and Compuatations)”->“计算几何度量(Compute Geometric Measures)”。
现在,层对话框的下半部分应该会显示一些有关惯性度量的信息。
该球体会给出以下输出:
Mesh Bounding Box Size 2.000000 2.000000 2.000000
Mesh Bounding Box Diag 3.464102
Mesh Volume is 4.094867
Mesh Surface is 12.425012
Thin shell barycenter -0.000000 -0.000000 -0.000000
Center of Mass is -0.000000 0.000000 -0.000000
Inertia Tensor is :
| 1.617916 -0.000000 0.000000 |
| -0.000000 1.604620 -0.000000 |
| 0.000000 -0.000000 1.617916 |
Principal axes are :
| 0.000000 1.000000 0.000000 |
| -0.711101 -0.000000 0.703089 |
| -0.703089 0.000000 -0.711101 |
axis momenta are :
| 1.604620 1.617916 1.617916 |
半径
- 该球体的边界框是边长为2.0的立方体,这意味着该球体的半径为1.0。
体积
- 半径为1.0的球体的体积应该为4/3 * PI(即4.189),接近于计算值4.095。由于它是一个三角近似值,因此并不精确。
表面积
- 表面积应该为4 * PI(即12.566),这也接近于计算值12.425。
质心
- 质心被计算为原点(0,0,0)。
惯性矩阵
由于球体半径=1,球体的惯性矩阵(也称为惯性张量)应该为对角矩阵,其主惯性矩为质量的2/5倍。在输出中并未明确说明,但质量是等于体积的(隐式使用密度为1),因此可以预计对角矩阵的对角线元素纸应为8/15 * PI(即1.676)。
对于给定的精度,计算出的惯性张量看起来是对角矩阵,其主惯性矩的大小范围为[1.604,1.618],接近预计值。
重复的面(Duplicate faces)
- 要记住的一点就是,网格内重复的面会影响体积和惯性矩的计算。
- 例如,以另一个球体网格ball.dae为例,Meshlab对该网格的输出为:
Mesh Bounding Box Size 1.923457 1.990389 1.967965
Mesh Bounding Box Diag 3.396207
Mesh Volume is 7.690343
Mesh Surface is 23.967396
Thin shell barycenter 0.000265 0.000185 0.000255
Center of Mass is 0.000257 0.000195 0.000292
Inertia Tensor is :
| 2.912301 0.001190 0.000026 |
| 0.001190 2.903731 0.002124 |
| 0.000026 0.002124 2.906963 |
Principal axes are :
| 0.108262 -0.895479 0.431738 |
| -0.120000 0.419343 0.899862 |
| 0.986853 0.149229 0.062058 |
axis momenta are :
| 2.902563 2.907949 2.912483 |
该网格的尺寸与前一个的大致相同,其边界框的尺寸在[1.92,1.99]范围内,但是其惯性参数计算结果相差近一倍:
体积:7.69对4.09
主惯性矩:[2.90,2.91]对[1.60,1.62]
当查看球体的顶点和面的数量(在 MeshLab窗口底部列出)时,会看到一个两者的差异之处:
sphere.dae:有382个顶点,760个面
ball.dae:有362个顶点,1440个面
这两个网格具有相似数量的顶点,但是ball.dae的面大约是sphere.dae的两倍。运行命令“过滤器(Filters)”->“清洗和维修(Cleaning and Repairing)”->“删除重复的面(Remove Duplicate Faces)”,可以将ball.dae中的面数量减少到720,这样就可以计算出更合理的体积值(3.84)和主惯性矩值(1.45)。由于其边界框相比sphere.dae的也要略小,因此这些参数值略小是有道理的
通过缩放来提高参数数值精度
- Meshlab目前以6位定点精度打印几何信息。
- 如果您的网格太小,则可能会严重限制惯性张量的精度,例如:
Mesh Bounding Box Size 0.044000 0.221000 0.388410
Mesh Bounding Box Diag 0.449043
Mesh Volume is 0.001576
Mesh Surface is 0.136169
Thin shell barycenter -0.021954 0.008976 0.012835
Center of Mass is -0.021993 0.001259 0.001489
Inertia Tensor is :
| 0.000008 -0.000000 -0.000000 |
| -0.000000 0.000001 -0.000000 |
| -0.000000 -0.000000 0.000007 |
Principal axes are :
| 0.999999 0.000166 0.001241 |
| -0.000113 0.999104 -0.042310 |
| -0.001247 0.042310 0.999104 |
axis momenta are :
| 0.000008 0.000001 0.000007 |
该输出中似乎有我们想要的东西。但是,当您仔细看时,会发现一件不好的事情——输出最多只能有6个小数位。结果就是会失去惯性张量中的大部分有价值的信息。
为了解决惯性张量中缺乏精度的问题,可以按比例放大模型,从而增大惯性。可以使用“过滤器(Filters)”->“法线、曲率和方向(Normals, Curvatures and Orientation)”->“变换:缩放(Transform: Scale)”菜单来缩放模型。 在对话框中输入缩放比例,然后单击“应用(Apply)”即可实现模型缩放。
要确定合适的缩放比例因子s,请回想一下MeshLab会用体积代表质量,这样质量就会随s3的变化而变化。而且,惯性还会随长度的平方(length2)变化而变化,因此惯性矩将会随s5变化而变化。由于惯性矩对s的依赖性如此之大,因此按比例缩放10倍或100倍可能就足够了。
现在,指示MeshLab再次重新计算几何度量值,这样惯性张量参数Inertia Tensor值就应该会有更高的精度。然后将惯性张量乘以1/s5以撤消缩放带来的影响。
获得质心
MeshLab并不总是使用与您想要的长度单位相同的单位(Gazebo的长度单位为米)。但是,通过查看“网格边界框大小(Mesh Bounding Box Size)”条目,可以轻松分辨出MeshLab单位与所需单位的比率。例如,您可以以您想要的单位计算边界框的大小,然后与MeshLab的边界框大小进行比较。
将质心参数乘以计算出的比率,就可以得到网格的质心坐标。但是,如果您要建模的链接不是均质的,则必须使用其他方法(最可能是通过实际实验)来计算其质心。
重新缩放惯性矩值
- 正如必须将质心位置的比例缩放到正确的单位一样,也应该对惯性矩进行这种缩放,但是该缩放比例因子因惯性矩与length2成正比而应是平方关系。此外,应将惯性乘以测得的质量参数值,然后再除以文本输出中计算出的体积。
将惯性参数值填入URDF或SDF的标签中
下一步是将计算出的惯性参数值记录到含有机器人的URDF或SDF文件中(假定您已经有机器人模型;如果没有,请按照 “制作模型”教程制作您的机器人模型)。
每个链接中都应该有
标签。该标签看起来应该如下所示(在SDF中):
<link name='antenna'>
<inertial>
<pose>-0.022 0.0203 0.02917 0 0 0</pose>
<mass>0.56</mass>
<inertia>
<ixx>0.004878</ixx>
<ixy>-6.2341e-07</ixy>
<ixz>-7.4538e-07</ixz>
<iyy>0.00090164</iyy>
<iyz>-0.00014394</iyz>
<izz>0.0042946</izz>
</inertia>
</inertial>
<collision name='antenna_collision'>
...
</collision>
<visual name='antenna_visual'>
...
</visual>
...
</link>
- 或者像下面这样(在URDF中):
<link name="antenna">
<inertial>
<origin rpy="0 0 0" xyz="-0.022 0.0203 0.02917"/>
<mass value="0.56"/>
<inertia ixx="0.004878" ixy="-6.2341e-07" ixz="-7.4538e-07" iyy="0.00090164" iyz="-0.00014394" izz="0.0042946"/>
</inertial>
<visual>
...
</visual>
<collision>
...
</collision>
标签
应以千克为单位输入质量参数值,您必须通过实验(或从规格中)找到质量参数值。 标签
或 用于输入质心位置(相对于链接的原点;尤其不是相对于链接的视觉或碰撞原点)。旋转元素可以定义与惯性矩轴不同的坐标。如果您通过实验找到了质心,请填写该质心值,否则请填写由MeshLab计算的正确缩放过的质心值。 标签
包含您在上一步中计算出的惯性张量。由于该矩阵是对称的,因此只需要6个数字就足以表示它。来自MeshLab的输出映射关系如下:
| ixx ixy ixz |
| ixy iyy iyz |
| ixz iyz izz |
为了快速检查该惯性矩阵是否合理,可以使用以下规则:对角线元素值应具有最大值并且为正,而非对角线元素值应或多或少地接近于零。
准确来说,惯性矩阵必须是正定的(使用您喜欢的数学工具进行验证)。它的对角线元素值还必须满足三角形不等式,即
ixx + iyy >= izz
,ixx + izz >= iyy
和iyy + izz> = ixx
。
在Gazebo中检查
可以用Gazebo的GUI客户端来检查是否所有事情都做正确了。
独立使用Gazebo
运行Gazebo
gazebo
- 生成您的机器人
gz model -f my_robot.sdf
- ROS与Gazebo一起使用
- 运行Gazebo
roslaunch gazebo_ros empty_world.launch
生成您的机器人(用您的机器人软件包/机器人名称替代my_robot,my_robot_description和MyRobot):
若为SDF模型,运行以下命令:
rosrun gazebo_ros spawn_model -sdf -file `rospack find my_robot_description`/urdf/my_robot.sdf -model MyRobot
- 若为URDF模型,则运行这个命令:
rosrun gazebo_ros spawn_model -urdf -file `rospack find my_robot_description`/urdf/my_robot.urdf -model MyRobot
模型载入后,立即暂停世界并删除ground_plane(这不是必需的,但这通常会使调试更加容易)。
进入到Gazebo的菜单栏,然后选择“视图(View)”->“惯性(Inertia)”菜单。现在,每个链接应该会显示一个带有绿色轴的紫色方盒。每个方盒的中心与其链接的指定质心对齐。方盒的大小和方向对应于具有与其相应链接相同的惯性行为的单位质量盒子。这对于调试惯性参数很有用,但是可以做更多事情来进一步简化调试。
可以将所有链接质量临时设置为1.0(通过编辑URDF或SDF文件)。然后所有紫色方盒就应该会具有与其链接的边界框大致相同的形状。这样,您可以轻松地检测到诸如重心位置错误或惯性矩阵旋转错误之类的问题。完成调试后,请不要忘记输入正确的质量。
为修复错误旋转的惯性矩阵(实际上经常发生该错误),只需交换模型文件中的ixx,iyy,izz元素的位置,直到紫色方盒与其链接对齐为止。那么显然您还必须正确地变换ixy,ixz和iyz之值(当交换ixx <-> iyy时,则应对ixy取负并交换ixz <-> iyz)。
进一步改进
简化模型
- MeshLab仅计算闭合形状的正确惯性参数。如果您的链接是开放的形状,或者其形状非常复杂或呈凹形,那么在计算惯性参数之前简化模型(例如在Blender中)可能是个好主意。或者,如果您有模型的碰撞形状,则请使用这些碰撞形状来代替全分辨率模型。
非均质体
对于高度非均质的物体,本节教程可能不起作用。原因在于存在以下两个问题:第一个问题是MeshLab会假设物体是密度均匀的。另一个问题是MeshLab计算的是相对于计算出的质心的惯性张量。但是,对于高度非均质物体,计算出的质心将会远离真实的质心,因此,计算出的惯性张量可能只是错误的。
一种解决方案是将您的链接细分为更均匀的部件,并使用固定类型的关节将它们连接起来,但这并不总是可行的。唯一的其他解决方案应该就是通过实验找出惯性张量,这肯定会花费大量时间和精力。
参考:
获取最新文章: 扫一扫右上角的二维码加入“创客智造”公众号