辅助对象_质心

0 阅读3分钟

课程链接:www.bilibili.com/cheese/play…

代码链接:github.com/buglas/robo…

课程目标

  • 创建质心对象
  • 控制质心的可见性

1-质心的概念

质心本质是link 的惯性坐标系原点,即 中的。

<link name="base">
  <inertial>
    <origin rpy="0.0 0.0 0.0" xyz="0.0 0.0 0.0"/>
    <mass value="0.01"/>
    <inertia ixx="0.0001" ixy="0.0" ixz="0.0" iyy="0.0001" iyz="0.0" izz="0.0001"/>
  </inertial>
</link>

在将质心可视化时,通常会用球体表示质心,这样球心的位置即,而球体的半径可以用来表示的大小。

image-20260124195224439

球心的位置可以直接使用里的xyz 属性,而球体的半径则需要对里的value 做以下换算。

2-用mass 的换算球体的半径

mass 的换算不能是随意而为的球体半径,我们需要考虑半径的物理意义。

mass 的意思是质量,回归我们高中所学的质量的公式:

质量 = 密度 × 体积

球体的体积是:

image-20260125120452268

设球体的密度为p,球体的质量就是:

image-20260125115447880

计算球体的半径r:

image-20260125115505225

image-20260125115522683

通常,urdf 文件中并不会表明物体的密度,所以我会假设所有物体的材质都是铅,铅的密度就是11340 kg/m³

3-代码实现

在URDFLoader 中创建质心对象:

  • src/robot/URDFLoader.ts
// 铅的密度 kg/m3
const densityOfLead = 11340;
// 质心的材质与几何体
const massMaterial = new MeshStandardMaterial({
  color: 0x0ff00,
  depthTest: false,
  depthWrite: false,
  fog: false,
  toneMapped: false,
  transparent: true,
  opacity: 0.7,
});
const massGeometry = new SphereGeometry(1, 8, 6);

/* URDF加载器 */
class URDFLoader {
    //...
    /* 解析inertial 
      <inertial>
        <origin rpy="0.0 0.0 0.0" xyz="0.0 0.0 0.0"/>
        <mass value="0.01"/>
        <inertia ixx="0.0001" ixy="0.0" ixz="0.0" iyy="0.0001" iyz="0.0" izz="0.0001"/>
      </inertial>
   */
    function processInertial(
      inertialNode: Element,
      urdfLink: Group
    ) {
      // <link> 的name
      const linkName = urdfLink.name;
      // <inertial>子标签
      const inertialChildren = Array.from(inertialNode.children);

      let origin_rpy = [0, 0, 0];
      let origin_xyz = [0, 0, 0];
      let mass_value = 0;
      inertialChildren.forEach((node) => {
        switch (node.nodeName.toLowerCase()) {
          case "origin":
            origin_rpy = processTuple(node.getAttribute("rpy"));
            origin_xyz = processTuple(node.getAttribute("xyz"));
            break;
          case "mass":
            mass_value = parseFloat(node.getAttribute("value") || "0");
            break;
        }
      });

      /* 创建辅助对象-质心 */
      const radius = Math.cbrt((0.75 * mass_value) / (Math.PI * densityOfLead));
      const massHelper = new Mesh(massGeometry, massMaterial);
      massHelper.visible = false;
      const [x=0,y=0,z=0] = origin_xyz;
      massHelper.position.set(x,y,z);
      massHelper.scale.set(radius,radius,radius)
      Object.assign(massHelper.userData, {
        isURDFHelper: true,
        helperType: "massHelper",
      });
      urdfLink.add(massHelper);
      massMap.set(linkName, massHelper);
    }
}

效果如下:

image-20260125133659786

总结

像质心可视化这样需求,通常是由机器人操作系统的开发者提出来的。

机器人在Web前端的可视化一般是参考机器人操作系统(Robot OS)开发的。

所以,如果我们想要把机器人在Web前端的可视化做得更专业、更严谨,需要对ROS 2相关的东西有所了解。

ROS 2 是当前机器人操作系统的首选。

ROS 2中有一个rviz 可视化调试工具,它使用gazebo 组件对机器人、及其坐标系、碰撞体、质心、惯性矩阵等进行可视化。

比如,我可以在其源码中找到质心的半径算法:

  • examples/scripts/websocket_server/gz3d.js
radius = Math.cbrt((0.75 * inertialMass ) / (Math.PI * 11340));

如果可以的话,我们最好再具备一点物理基础。

若你知道物体的材质,你可以使用相应物体的密度计算质心的半径。

以下是常见机器人材质的密度:

材质密度(kg/m³)适用场景
塑料 / ABS1020~1050机器人外壳、轻量结构
铝合金(6061)2700机器人支架、关节(轻量化高强度)
钢 / 铁7850重负载部件、配重
11340高密度配重
钛合金4500高端轻量化部件
橡胶900~1300轮胎、缓冲部件

下一章,我们会说惯性矩的可视化。