课程链接:www.bilibili.com/cheese/play…
课程目标
- 创建质心对象
- 控制质心的可见性
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>
在将质心可视化时,通常会用球体表示质心,这样球心的位置即,而球体的半径可以用来表示的大小。
球心的位置可以直接使用里的xyz 属性,而球体的半径则需要对里的value 做以下换算。
2-用mass 的换算球体的半径
mass 的换算不能是随意而为的球体半径,我们需要考虑半径的物理意义。
mass 的意思是质量,回归我们高中所学的质量的公式:
质量 = 密度 × 体积
球体的体积是:
设球体的密度为p,球体的质量就是:
计算球体的半径r:
通常,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);
}
}
效果如下:
总结
像质心可视化这样需求,通常是由机器人操作系统的开发者提出来的。
机器人在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³) | 适用场景 |
|---|---|---|
| 塑料 / ABS | 1020~1050 | 机器人外壳、轻量结构 |
| 铝合金(6061) | 2700 | 机器人支架、关节(轻量化高强度) |
| 钢 / 铁 | 7850 | 重负载部件、配重 |
| 铅 | 11340 | 高密度配重 |
| 钛合金 | 4500 | 高端轻量化部件 |
| 橡胶 | 900~1300 | 轮胎、缓冲部件 |
下一章,我们会说惯性矩的可视化。