4. 关节与执行器
各位同学,欢迎来到第四章。前几章我们把四足机器人的躯干和腿的几何模型搭好了,但你会发现——它现在还是一堆「死」的几何体,动不了。
想让机器人动起来,核心就两个东西:关节(Joint)和执行器(Actuator)。关节决定了运动自由度,执行器提供动力。今天我们就来彻底搞懂它们。
4.1 关节(Joint)的本质
在 MuJoCo 里,关节就是连接两个 body 的「运动副」。它定义了子 body 相对于父 body 的运动方式。说白了,没有关节,所有 body 都是焊死的。
MuJoCo 支持三种基础关节类型,我整理了一张表,方便你对比:
| 关节类型 | 自由度 | 运动方式 | 典型用途 |
|---|---|---|---|
hinge |
1 | 绕固定轴旋转 | 四足机器人髋关节、膝关节 |
slide |
1 | 沿固定轴平移 | 直线导轨、活塞 |
free |
6 | 空间自由运动(3平移+3旋转) | 机器人躯干与世界的连接 |
关键点:四足机器人的躯干必须使用 free 关节与世界连接,否则它会被钉死在原地,无法移动和旋转。
我个人习惯把 free 关节想象成「把机器人扔进虚拟世界」的那个关节。没有它,你的机器人就像被胶水粘在桌上,四条腿再怎么动也跑不起来。
4.2 关节的 XML 语法
关节定义在 <body> 内部,通过 <joint> 元素声明。来看一个最简单的例子:
<body name="torso">
<joint name="root" type="free"/>
<geom type="box" size="0.3 0.15 0.1" rgba="0.8 0.2 0.2 1"/>
</body>
这里我给躯干加了一个 free 关节,命名为 root。这样躯干就能在仿真世界里自由移动了。
但今天我们的重点是旋转关节。假设我想在躯干上额外加一个旋转部件,比如一个雷达或者机械臂基座,那就需要 hinge 关节:
<body name="torso">
<joint name="root" type="free"/>
<geom type="box" size="0.3 0.15 0.1" rgba="0.8 0.2 0.2 1"/>
<body name="rotator" pos="0 0 0.15">
<joint name="turntable" type="hinge" axis="0 0 1"/>
<geom type="cylinder" size="0.1 0.05" rgba="0.2 0.6 0.8 1"/>
</body>
</body>
注意看 axis="0 0 1",这表示旋转轴是 Z 轴(朝上)。如果你想让关节绕 X 轴或 Y 轴转,改成 1 0 0 或 0 1 0 就行。
小技巧:定义 hinge 关节时,axis 向量会被自动归一化,所以你不需要担心长度问题。但方向一定要写对,否则关节会朝奇怪的方向转。
4.3 执行器(Actuator)——给关节注入灵魂
关节定义了「能怎么动」,执行器定义了「用什么力动」。MuJoCo 支持多种执行器类型,最常用的是 motor(电机)和 position(位置伺服)。
执行器定义在 <worldbody> 之外,通常在 <actuator> 块里:
<actuator>
<motor name="turntable_motor" joint="turntable" ctrlrange="-1 1" ctrllimited="true"/>
</actuator>
这里我绑定了 turntable 关节,给它一个电机执行器。ctrlrange="-1 1" 表示控制输入范围是 -1 到 1,对应电机的最大反向和正向扭矩。
我曾经在项目里犯过一个低级错误:给关节绑定了执行器,但忘了设置 ctrllimited="true"。结果仿真一跑,电机直接输出无穷大的扭矩,机器人瞬间飞到了天上去……嗯,从那以后我再也不敢漏掉这个参数了。
4.4 完整示例:带旋转关节的躯干
把上面的代码拼起来,就是一个完整的、带旋转关节的躯干模型:
<mujoco model="torso_with_rotator">
<compiler angle="radian"/>
<worldbody>
<body name="torso">
<joint name="root" type="free"/>
<geom type="box" size="0.3 0.15 0.1" rgba="0.8 0.2 0.2 1"/>
<body name="rotator" pos="0 0 0.15">
<joint name="turntable" type="hinge" axis="0 0 1"/>
<geom type="cylinder" size="0.1 0.05" rgba="0.2 0.6 0.8 1"/>
</body>
</body>
</worldbody>
<actuator>
<motor name="turntable_motor" joint="turntable" ctrlrange="-1 1" ctrllimited="true"/>
</actuator>
</mujoco>
把这个文件保存为 torso_with_joint.xml,用 MuJoCo 的 simulate 工具打开。你会看到躯干自由悬浮在空中,上面有一个蓝色圆柱。在仿真窗口里找到控制面板,把 turntable_motor 的滑块拖到 0.5,圆柱就会开始旋转。
注意:如果你看不到控制滑块,检查一下 ctrlrange 是否设置正确,以及执行器的 joint 名称是否与关节名称完全匹配。MuJoCo 对名称大小写敏感。
4.5 关节参数进阶
除了基本的 type 和 axis,关节还有一些常用参数,我列出来供你参考:
| 参数 | 作用 | 示例 |
|---|---|---|
pos |
关节在父 body 中的位置 | pos="0 0 0.1" |
axis |
旋转轴或平移方向 | axis="0 1 0" |
range |
关节运动范围(弧度或米) | range="-1.57 1.57" |
limited |
是否启用范围限制 | limited="true" |
damping |
关节阻尼系数 | damping="0.1" |
stiffness |
关节刚度(用于弹簧关节) | stiffness="10" |
你想想看,如果给四足机器人的膝关节加上 range="-2.0 0.0" 和 limited="true",就能防止腿向后弯折成反关节。这在真实机器人上可是致命的机械损伤。
4.6 知识结构图
下面这张 SVG 图梳理了本章的核心概念和它们之间的关系:
4.7 避坑指南
最后,分享几个我踩过的坑,希望能帮你省点时间:
- 关节名称冲突:同一个模型里,关节名称不能重复。我习惯用
body名称_joint的命名方式,比如hip_left_joint,这样一目了然。 - 执行器绑定错误:执行器的
joint属性必须与关节的name完全一致。少写一个字母,MuJoCo 就会报错。 - 忘记设置
limited:如果不设limited="true",range参数会被忽略,关节可以无限旋转。这在仿真里可能不会报错,但会让你的机器人做出各种反物理动作。 - 轴方向搞反:定义
hinge关节时,axis的正方向决定了旋转的正方向。如果你发现关节朝反方向转,把axis取反就行。