← 返回文章库

足式机器人的关节电机:准直驱、力控和那个容易踩的换算坑

最后更新 2026-08-23
⏱ 约 14 分钟 🟡 涉接线/强电
你将学到
  • 说清足式机器人为什么不能用普通舵机,准直驱方案解决了什么问题
  • 看懂 kp、kd、q、dq、tau 这组指令,理解它们合起来构成的控制律
  • 记住转子侧与输出侧的换算关系,避开这个会让关节剧烈抖动的坑

做过舵机小车的人,第一次看足式机器人的关节控制指令会有点懵。

舵机的接口简单到极致:给一个角度,它转过去。而足式机器人给关节发的一条指令里,塞了五个参数——目标位置、目标速度、力矩、还有两个叫 kp 和 kd 的东西。

为什么要这么复杂?这篇从 unitree_actuator_sdk 的指令结构讲起,把足式机器人关节控制的门道拆开。这些概念不是某一家的私有设计,你在任何做力控关节的项目里都会遇到。

按惯例说明边界:本文基于该仓库公开的 README 与代码结构,我手上没有这类电机,不会有任何实测描述,涉及具体行为的部分以官方文档的说法为准。

先看那条指令长什么样

README 里给了一段赋值示例,结构大致是这样:

cmd.motorType = MotorType::A1;
cmd.mode  = queryMotorMode(MotorType::A1, MotorMode::FOC);
cmd.id    = 0;
cmd.kp    = 0.0;
cmd.kd    = 2;
cmd.q     = 0.0;
cmd.dq    = -6.28 * queryGearRatio(MotorType::A1);
cmd.tau   = 0.0;
serial.sendRecv(&cmd, &data);

五个控制量:kpkdqdqtau。它们合起来实现的是一条控制律,形式大致是:

输出力矩 = tau
         + kp × (q目标 - q当前)
         + kd × (dq目标 - dq当前)

翻译成人话:最终给出的力矩,等于你直接指定的前馈力矩,加上位置偏差的比例项,加上速度偏差的阻尼项。

这个式子眼熟吗?它就是一个 PD 控制器加前馈。如果你跟着PID 控制那篇做过小车,这里的 kp、kd 和你调过的是同一类东西。

关键在于这条控制律跑在电机驱动器里,不是跑在你的主控上。你只需要按控制周期把这五个数发下去。

五个参数怎么用:三种模式其实是一种

理解这条控制律之后,一件很漂亮的事情出现了——位置控制、速度控制、力矩控制这三种模式,其实是同一条式子的三种特例:

纯位置控制:kp 给大值、kd 给适中值、tau 给 0。关节会努力到达目标角度,kp 越大越"硬"。这就是舵机的行为。

纯力矩控制:kp 和 kd 都给 0,只给 tau。关节不管自己在哪,只按你要求的力矩输出。上面那段示例里 kp 是 0、kd 是 2、tau 是 0,就是一个只有阻尼的配置——不主动去任何位置,只是"转起来有阻力"。

阻抗控制:三者混合。这是足式机器人真正常用的模式。

阻抗控制这个词值得单独解释。你给了 kp 和 kd,等于告诉关节:表现得像一根弹簧加一个阻尼器。kp 是弹簧的刚度,kd 是阻尼系数。

  • kp 大、kd 大 → 关节又硬又黏,接近位置控制
  • kp 小、kd 小 → 关节软,你用手就能推动
  • kp 小、tau 给值 → 关节"顺从",但持续输出一个力

这就是足式机器人能适应地形的物理基础。 一台纯位置控制的四足踩到石头上,位置环发现到不了目标角度,会拼命加大电流去纠正,结果要么把自己弹飞,要么烧电机。而阻抗控制下,腿"软"着落地,石头把脚顶高了它就顺着让开,同时依然输出着支撑身体所需的力。

真实的行走过程中,同一条腿在不同阶段的参数是不一样的:摆动相时腿在空中,用较高的 kp 精确摆到落脚点;支撑相时腿承重,切到低 kp 高力矩,让身体平稳。这个切换是控制器在每个周期里动态做的。

那个必踩的坑:转子侧还是输出侧

README 里有一段提示,藏着这个 SDK 最容易出事的地方:

指令都是转子侧的,但我们通常计算的是输出侧的,赋值时需要考虑两者的换算。

这是什么意思?

电机的转子转得快、力矩小;经过减速器之后,输出轴转得慢、力矩大。假设减速比是 r,那么转子转 r 圈,输出轴才转 1 圈。

所以同一个物理动作,用两种坐标描述出来的数字差了 r 倍:

q_转子  = q_输出  × r
dq_转子 = dq_输出 × r
tau_转子 = tau_输出 / r

上面那段示例里 cmd.dq = -6.28 * queryGearRatio(...) 就是在做这件事——把输出侧的目标速度乘上减速比,换算到转子侧。6.28 大约是 2π,也就是输出轴每秒转一圈。

而 kp 和 kd 的换算更容易出错。README 给出的关系是:

kp_转子 = kp_输出 / r²
kd_转子 = kd_输出 / r²

注意是除以 r 的平方,不是 r。

为什么是平方?因为 kp 是"力矩除以角度偏差"这个量纲。换到转子侧,分子上的力矩要除以 r,分母上的角度偏差要乘以 r,两个效应叠在一起就是除以 r²。

这个坑的可怕之处在于它不会报错。你把输出侧的 kp 直接填进去,程序照跑不误,但实际刚度被放大了 r² 倍——减速比几倍的话就是几十倍的刚度。结果是关节剧烈抖动甚至自激振荡。

仓库里同时提供了 example_a1_motor.cppexample_a1_motor_output.cpp 两个示例,一个转子侧一个输出侧,就是为了把这件事讲明白。

通用教训:任何跨越了减速机构的控制系统,都要先确认"这个数字是哪一侧的"。 这个问题在机械臂、云台、AGV 轮组上同样存在。

为什么足式机器人要用准直驱

上面讲的力控,普通的舵机做不到。原因在减速比。

我们熟悉的舵机,为了用小电机输出大力矩,通常带着几百比一的高减速比齿轮箱。这带来两个致命问题:

第一,摩擦大到力矩不可控。 高减速比齿轮箱内部摩擦很大,你想让输出轴出 1 单位力矩,实际有多少被摩擦吃掉了,你不知道。力矩控制的精度就无从谈起。

第二,反向驱动困难。 外力推动输出轴时,力要反向穿过整个齿轮箱才能传到转子。高减速比下这几乎不可能——舵机被外力顶住时是"硬顶",不会顺从。而足式机器人落地时的冲击,恰恰需要关节能被反向推动来卸力。

准直驱(quasi-direct drive)就是针对这两点的方案:用一个力矩密度高的大直径电机,配一个低减速比的减速器。牺牲一部分力矩放大能力,换来低摩擦和良好的反向驱动性。这样一来,力矩既能被精确控制,也能被感知。

顺带说,力矩感知是另一个隐藏的好处。低减速比下,电机的电流和输出力矩有近乎线性的对应关系。这意味着不需要额外装力传感器,靠读电流就能估算关节受了多大力——足端有没有触地、承了多少重,都能这样判断出来。这对状态估计来说是关键信息。

这和我们在电机类型那篇里讲的选型逻辑是一脉相承的:没有万能的电机,只有匹配场景的取舍。

从 SDK 结构看工程细节

unitree_actuator_sdk 的目录不大,但每一块都对应一个真实问题:

include/serialPort/     —— 串口通信
include/IOPort/         —— IO 端口抽象
include/crc/            —— crc32、crc_ccitt 两种校验
include/unitreeMotor/   —— 电机消息定义
    motor_msg_A1B1.h
    motor_msg_GO-M8010-6.h
example/                —— C++ 示例,含 changeID
python/                 —— Python 示例
motor_tools/            —— 电机工具(改 ID、固件相关)
lib/                    —— 预编译库,含 Python 扩展

几个值得说的点:

通信走串口。 关节电机不接以太网,走的是串口总线——多个电机挂在同一条总线上,靠 ID 区分。这也解释了为什么 example/ 里有一个 changeID.cpp新电机出厂 ID 相同,装到机器人上之前必须逐个改成不同的 ID,否则总线上会打架。这是装配环节的实际操作,不是可选步骤。

两种 CRC 校验并存。 crc32crc_ccitt 同时存在,说明不同型号电机的协议帧格式不一样。这也印证了 motor_msg_A1B1.hmotor_msg_GO-M8010-6.h 分开定义——协议是跟着硬件代际走的。校验码这件事在串口通信里是刚需,电机指令传错一位的后果是物理性的。想动手算一下的话,站内有CRC/Modbus 校验工具可以直接试。

示例要用 sudo 运行。 README 明确写了这一点。原因是访问串口设备需要权限,同时实时程序往往需要内存锁定。

motor_tools/ 里有固件相关的工具。 这类工具的存在提醒你:电机不是一个纯粹的机械件,它里面跑着固件,有 bootloader,可以升级也可能刷坏。

SDK 的 README 提到支持的电机型号包括 GO-M8010-6、A1 motor、B1 motor,环境要求上对 x86 与 ARM 平台的 gcc 版本各有下限(以官方仓库当前文档为准)。注意:型号名之外的任何参数——力矩、转速、减速比具体数值——事实源里没有,我不会替它编。 要选型请查官方规格书。

三条可以带走的结论

第一,位置、速度、力矩三种控制模式,本质是同一条控制律的三种参数配置。 想通这一点,关节控制就不再是三套要分别记忆的东西。

第二,kp 和 kd 描述的是"关节有多硬",不是"控制得多准"。 把它们理解成弹簧刚度和阻尼,你才知道该往哪个方向调。

第三,跨减速机构的量都要确认是哪一侧的,kp/kd 换算是 r² 而不是 r。 这个坑不报错,只让硬件抖。

想动手实践的话,机器人与具身智能卷里从舵机驱动起步是最省钱的路径——先用舵机把位置控制跑通,你会更直观地感受到"硬"到底是什么意思,再来理解力控为什么必要。想看这些关节在整机上是怎么被调度的,可以读高层控制与低层控制的边界

📄 来源 / 自校链接

本文为公开资料整理,非亲测。关键参数与代码请结合实物与下列官方来源验证。

内容有错、看不懂、或想看下一期?告诉我们 →

本文为公开资料的学习整理,非亲测。涉接线/花钱/合规的步骤请结合实物与官方最新资料验证,风险自负。见免责声明