辅助对象_质心

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

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

课程目标

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

1-质心的概念

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

ini 复制代码
<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>

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

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

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

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

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

质量 = 密度 × 体积

球体的体积是:

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

计算球体的半径r:

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

3-代码实现

在URDFLoader 中创建质心对象:

  • src/robot/URDFLoader.ts
ini 复制代码
// 铅的密度 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);
    }
}

效果如下:

总结

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

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

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

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

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

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

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

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

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

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

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

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

相关推荐
卸任18 小时前
Vibe coding工具使用心得
前端·ai编程
brien919 小时前
为什么模型标称 1M,Google Antigravity 聊到 256K 却突然失忆?我们给它做了个原生行内监控圆环
前端
用户157415681653419 小时前
让「大肥鱼」在群里开口说话:NapCat + AstrBot + GPT-SoVITS 语音机器人搭建实录
机器人·aigc
修炼的dance19 小时前
录屏关键帧间隔多少合适?六档实测,2秒到10秒小了75.6%
前端
Lank_M19 小时前
关键帧从1秒拉到10秒,录屏小87.3%,摄像头小10.8%
前端
补码缩写19 小时前
用 ffprobe 拆录屏,八成字节在 29 个关键帧上
前端
百思不得小李19 小时前
一个复杂的动态表单是如何实现的
前端·设计模式
陈随易19 小时前
Cmder 停更 17 个月,2.0 支持 Windows Terminal
前端·后端·程序员
风骏时光牛马19 小时前
前沿视界
前端
kyriewen19 小时前
我扫了 814 个依赖,97 个还敢要 Node 10
前端·javascript·程序员