MicroDuck 机器鸭拆解:50Hz 控制闭环如何实现双足动态平衡
发布时间:2026/9/20 5:23:46 作者:尧图编辑部 阅读量:1,286

1. 一只机器鸭凭什么值得拆解第一次看到 MicroDuck 这个项目的时候我正蹲在工作室里调一台四足平台的步态参数屏幕上那条关节力矩曲线抖得像心电图。朋友甩过来一段视频画面里一只巴掌大的双足机器鸭在桌面上原地踏步动作谈不上优雅但每一步落地都稳得出奇没有那种廉价舵机常见的抽搐和过冲。更让我在意的是视频角落那行小字控制回路跑在 50Hz。50Hz 这个数字在外行看来平平无奇但凡是碰过机器人实时控制的人都会愣一下。现在主流的双足、四足平台姿态控制环动辄跑到 500Hz 甚至 1kHzIMU 采样、关节闭环、状态估计恨不得把 CPU 榨干。一只机器鸭凭什么敢用 50Hz 就把双足平衡做出来这背后要么是硬件选型极其克制要么是控制架构做了非常聪明的取舍要么两者兼有。我花了大概两周时间把 MicroDuck 的公开资料、拆解记录、仿真回放流程捋了一遍又自己动手复现了它的核心控制思路踩了不少坑也摸到了一些门道。这篇东西写给谁看如果你正在做小型双足、仿生机器人或者你手上有舵机、IMU、一块单片机想搞明白低频率控制环到底能不能撑起动态平衡那这篇就是给你准备的。我会把 MicroDuck 的整体设计思路、50Hz 控制闭环的来龙去脉、仿真回放怎么用、拆解时要注意什么全部摊开讲。不吹不黑只讲我实际验证过的东西。先说结论性的判断MicroDuck 的价值不在于它多先进而在于它把够用就好这四个字做到了极致。它用 50Hz 的控制频率、相对廉价的执行器、一套轻量级的状态反馈硬是把双足动态平衡跑通了。这种降维打击式的工程取舍恰恰是很多新手最缺的——大家一上来就想堆算力、堆频率结果连最基本的站立都调不稳。2. 整体设计思路与 50Hz 的取舍逻辑2.1 为什么是双足而不是四足或者轮式先聊一个根本问题为什么有人要做双足机器鸭而不是更稳的四足或者更简单的轮式我一开始也觉得这是自找麻烦。双足系统本质上是一个倒立摆天生不稳定你不控制它就倒。四足静态稳定轮式更是随便跑。但双足有一个四足和轮式都给不了的东西它对动态平衡这件事的暴露是最彻底的。你调四足很多时候靠的是静态余量腿随便摆一摆重心落在支撑多边形里就完事了控制环频率低一点也看不出来。但双足不行双足每一步都是要倒不倒的临界状态控制环稍微慢一点、相位稍微偏一点立刻就是摔倒。所以双足是检验控制架构最狠的试金石。MicroDuck 选双足我理解就是想用最小的硬件成本去验证一套极简控制闭环到底能扛到什么程度。而且鸭子的形态有个天然优势身体短、腿短、重心低。重心低意味着倒立摆的固有频率低对控制带宽的要求就跟着降低。这是一个非常关键的物理事实。倒立摆的固有角频率大致和 sqrt(g/L) 成正比L 是重心到支撑点的高度。你把 L 做小系统本身就慢下来了50Hz 的控制环才有可能够用。如果换成一个人形机器人重心高度一米多50Hz 根本压不住。所以 MicroDuck 选鸭子形态不是卖萌是物理上的必然选择。2.2 50Hz 控制闭环到底意味着什么很多人对控制频率有个误解觉得频率越高越好。理论上没错但工程上频率是要花钱的。频率翻倍意味着你的传感器采样要更快、通信总线要更快、计算要更快功耗和成本全线上涨。50Hz 意味着控制周期是 20 毫秒。在这 20 毫秒里系统要完成读取 IMU 姿态、读取关节角度、计算状态误差、算出目标力矩或目标角度、下发给执行器。听起来时间很充裕对吧但问题在于20 毫秒的延迟在动态平衡里是相当可观的。我实测过一个重心高度 8 厘米左右的小型双足它的跌倒时间常数大概在 150 到 250 毫秒量级。也就是说如果你完全不控制它从直立到倒下大概需要两三百毫秒。20 毫秒的控制周期相当于在这个跌倒过程里你能介入十几次。这个介入次数是够的但前提是你的控制律不能有太大的相位滞后。这就是为什么 MicroDuck 的控制架构必须做得非常直接——它大概率用的是基于姿态误差的直接反馈而不是那种需要多级滤波、多级状态估计的复杂架构。每多一级滤波就多一份相位滞后50Hz 下这份滞后会被放大成致命的振荡。提示判断一个低频控制环能不能用关键不是看频率数字而是看控制周期 / 系统跌倒时间常数这个比值。比值小于 1/10 基本就够用MicroDuck 大概在 1/10 到 1/12 之间属于刚好卡在及格线上。2.3 执行器选型背后的克制哲学MicroDuck 用的执行器从拆解资料看是小型数字舵机或者带位置反馈的减速电机。这里有个取舍舵机便宜、集成度高、自带位置闭环但带宽低、响应慢、还有死区无刷电机加驱动器性能好但成本高、需要自己做电流环和位置环。MicroDuck 选前者逻辑很清楚——它的控制环只有 50Hz舵机的响应速度完全跟得上用无刷电机反而是浪费。我自己的经验是舵机在 50Hz 控制下的表现其实比很多人想象的好。舵机内部有自己的位置闭环通常跑在几百赫兹你从外面给它一个目标角度它自己会去追。你外部控制环要做的只是决定目标角度是多少。这种外环慢、内环快的分层结构正好和 50Hz 的外环匹配。如果你非要用无刷电机那你就得自己实现内环工作量翻好几倍收益在 50Hz 下几乎看不出来。这里有个细节值得说舵机的死区和回差在双足平衡里是会被放大的。因为双足对关节角度的精度要求其实不低死区大了控制环会一直在死区边缘来回抖。MicroDuck 能跑通说明它在选舵机时对死区做了筛选或者在控制律里做了死区补偿。这一点在复现时特别容易翻车后面讲排查的时候我会细说。3. 核心细节解析与实操要点3.1 状态反馈IMU 和关节角度的最小组合MicroDuck 的状态反馈非常克制核心就是两样东西IMU 给的躯干姿态角以及关节角度。没有力传感器没有足底压力传感器没有视觉。这个组合能撑起双足平衡吗能但前提是你对姿态角的处理要足够干净。IMU 给的是加速度和角速度要得到姿态角通常用互补滤波或者卡尔曼滤波融合。这里有个坑滤波器的截止频率如果设得太低姿态角会很平滑但滞后大设得太高噪声又压不住。在 50Hz 控制环下我建议互补滤波的系数让加速度计权重在 0.02 到 0.05 之间这样姿态角的相位滞后大概在几毫秒量级可以接受。我自己试过用纯陀螺仪积分短时间很准但几十秒后漂移就出来了双足平衡撑不了那么久所以纯积分也不是不能用但风险大。关节角度这块如果你用的是舵机很多舵机支持位置回读但回读的精度和刷新率参差不齐。我实测过几款常见的小舵机位置回读的刷新率大概在 50 到 100Hz精度在 1 到 2 度。这个精度对双足来说偏粗但 MicroDuck 能跑通说明它对关节角度的依赖没有想象中那么重——它更多是靠躯干姿态来维持平衡关节角度只是辅助。这个思路很重要不要试图用低精度传感器去做高精度控制而是设计一个对精度不敏感的控制律。3.2 控制律直接姿态反馈为什么够用MicroDuck 的控制律从行为上看大概率是姿态误差映射到关节目标角度的直接反馈。具体来说躯干前倾了就让支撑腿往后蹬一点躯干后仰了就让支撑腿往前伸一点。这个逻辑简单到可以用一句话说清楚但它背后是有控制理论支撑的。这本质上是一种虚拟模型控制的简化版。你把躯干姿态误差当成一个虚拟力这个虚拟力作用在髋关节上产生一个目标角度修正。比例系数决定了修正的力度微分系数决定了阻尼。在 50Hz 下微分项要特别小心因为差分对噪声极其敏感。我的做法是对角速度直接用陀螺仪读数而不是对姿态角做差分这样能避开差分放大噪声的问题。陀螺仪本身就有角速度直接拿来当微分项用干净得多。比例系数怎么定我一般从临界稳定开始试。先把微分项设为零慢慢加大比例项直到系统开始等幅振荡记下这个临界值然后取它的 0.4 到 0.6 倍作为工作值再加上微分项压振荡。这个过程在仿真里做最快MicroDuck 提供了 MuJoCo 的仿真环境正好可以用来干这个。实机上调的话一定要把机器人吊起来让脚离地先看关节响应对不对再放下去试站立。3.3 50Hz 陷波器被热词带火的一个细节最近50Hz 陷波器这个词和 MicroDuck 绑在一起被搜得很多我猜是因为有人在拆解或者复现时发现 IMU 数据里有个 50Hz 的干扰需要用陷波滤波器干掉它。这个现象太常见了我自己就遇到过无数次。50Hz 干扰从哪来最常见的是电源工频干扰尤其是你用市电供电、电源滤波做得不好的时候。IMU 的模拟部分如果和电源共地不干净50Hz 就会串进来。另一个来源是舵机或者电机的 PWM 驱动某些 PWM 频率的谐波正好落在 50Hz 附近通过电源或者地线耦合到 IMU。陷波器的设计核心是三个参数中心频率、带宽、深度。中心频率就是 50Hz这个没得说。带宽决定了陷波器影响的范围太窄了压不住频率漂移太宽了会把有用信号也吃掉。我一般取 2 到 5Hz 带宽。深度就是在这个频率上衰减多少通常要 20dB 以上才有效。双 T 型陷波滤波器是模拟电路里常用的结构数字域里可以用双二阶滤波器实现计算量很小50Hz 控制环完全跑得动。注意陷波器会引入相位滞后中心频率附近的滞后尤其明显。如果你的控制环本来就卡在 50Hz 的及格线上加陷波器之前一定要重新评估相位余量。我的做法是能通过硬件解决比如给 IMU 单独供电、加屏蔽、改地线布局就绝不加陷波器实在没办法才上数字滤波。3.4 仿真回放MuJoCo Viewer 的正确打开方式MicroDuck 用 MuJoCo 做仿真这个选择很务实。MuJoCo 的接触求解在小型双足上表现不错计算量也小普通笔记本就能实时跑。Viewer 的回放功能是调参阶段最值钱的东西。很多人用 Viewer 就是看一眼模型动没动这太浪费了。我的用法是把实机跑出来的关节角度序列和 IMU 姿态序列录下来导入仿真里回放对比仿真模型在相同输入下的表现。如果仿真和实机对不上说明你的模型参数质量、惯量、摩擦、舵机延迟有偏差先把模型校准了再调控制参数。这个流程能省掉大量实机试错的时间。回放时有个细节MuJoCo 的时间步长和你的控制周期要匹配。控制周期 20 毫秒仿真步长建议设成 1 毫秒或者更小这样每个控制周期内有 20 个仿真步接触求解才稳定。如果你把仿真步长也设成 20 毫秒接触会穿透机器人会抖得没法看。这个坑我踩过调了半天控制参数最后发现是仿真步长的问题。4. 实操过程与核心环节实现4.1 硬件搭建从零到能站起来的清单复现 MicroDuck 的硬件门槛不高但选型有讲究。下面是我实际用过的配置以及每个选择的理由。部件选型建议关键参数选择理由主控带 FPU 的 32 位 MCU主频 100MHz 以上50Hz 控制环计算量不大但浮点运算和滤波需要 FPU否则定点数转换很烦IMU六轴SPI 或 I2C 接口陀螺仪量程 ±500dps加速度 ±4g量程不用太大小量程分辨率更高接口速度要够50Hz 下 I2C 标准模式勉强够舵机数字舵机带位置回读扭矩 2kg·cm 以上死区小于 1 度数字舵机响应快、死区小位置回读用于状态反馈电源锂电池 LDO输出纹波小于 20mV纹波大直接污染 IMU这是 50Hz 干扰的主要来源之一结构件3D 打印重心尽量低重心低降低倒立摆固有频率是 50Hz 能用的物理前提主控这块我要多说一句。很多人一上来就上树莓派或者 Jetson觉得算力越大越好。但 MicroDuck 这种项目MCU 反而更合适。原因有三一是实时性MCU 的中断响应是确定的Linux 系统做不到二是功耗MCU 功耗低电池能撑更久三是简单没有操作系统这层控制环的时序你完全可控。我用 STM32 系列的 MCU 跑这个控制环CPU 占用率不到 20%余量很大。4.2 控制环的代码结构控制环的代码结构我建议分成三层采集层、计算层、输出层。采集层负责读 IMU 和舵机位置计算层负责滤波和控制律输出层负责下发舵机目标角度。三层在同一个定时器中断里顺序执行中断周期 20 毫秒。// 50Hz 控制中断服务函数伪代码 void control_isr(void) { // 采集层 imu_read(accel, gyro); // 读 IMUSPI 传输 servo_read_positions(positions); // 读舵机位置回读 // 计算层 attitude_update(accel, gyro, dt); // 互补滤波更新姿态 float pitch get_pitch(); float pitch_rate gyro.y; // 直接用陀螺仪角速度 // 控制律姿态误差映射到关节目标角度 float target_hip kp * pitch kd * pitch_rate; float target_knee kp_knee * pitch kd_knee * pitch_rate; // 输出层 servo_set_target(LEFT_HIP, target_hip); servo_set_target(RIGHT_HIP, target_hip); servo_set_target(LEFT_KNEE, target_knee); servo_set_target(RIGHT_KNEE, target_knee); }这段代码里dt是控制周期固定 0.02 秒。互补滤波的系数我一般设成 0.03也就是每次更新时加速度计占 3%陀螺仪积分占 97%。这个系数下姿态角的静态精度不错动态滞后也能接受。控制律里的kp和kd就是前面说的比例和微分系数。注意这里我用了两个关节的目标角度髋关节和膝关节。为什么要两个因为单靠髋关节机器人的姿态修正能力有限加上膝关节可以形成更丰富的姿态调整空间。但膝关节的系数要比髋关节小否则腿会乱蹬。我的经验值是膝关节系数取髋关节的 0.3 到 0.5 倍。4.3 参数整定的实操流程参数整定是这类项目最耗时间的环节我把它拆成四步每步都有明确的通过标准。第一步静态标定。把机器人固定住读 IMU 的原始数据确认静止时加速度计读数是 (0, 0, g)陀螺仪读数是 (0, 0, 0)。如果有偏差先做零偏校准。这一步不过后面全是白搭。第二步吊装测试。把机器人吊起来脚离地给一个小的姿态扰动比如用手轻轻推一下躯干观察关节响应。通过标准是关节朝着抵抗扰动的方向动而且动完能回到中位不持续振荡。如果关节动反了说明控制律符号错了改符号。第三步仿真整定。在 MuJoCo 里跑从 kp 小值开始逐步加大找到临界振荡点取 0.5 倍作为工作值再加 kd 压振荡。通过标准是机器人能站立 10 秒以上不摔姿态角波动在 ±3 度以内。第四步实机站立。把机器人放到桌面上从低 kp 开始逐步加到仿真整定值的 0.7 倍左右观察实际表现。实机的 kp 通常要比仿真小因为实机有舵机延迟、有摩擦、有传感器噪声这些在仿真里都不完全准确。通过标准是能站立 5 秒以上然后逐步延长。提示实机整定时一定要在桌面上铺一层软垫摔下来不至于把结构件摔断。我第一版结构件摔断了三次后来学乖了先铺垫子再调参。4.4 50Hz 陷波器的数字实现如果硬件上实在压不住 50Hz 干扰就得在数字域加陷波器。双二阶陷波器的差分方程长这样// 50Hz 数字陷波器采样率 50Hz 时中心频率不能是 50Hz // 注意采样率必须远高于陷波中心频率否则无效 // 这里假设 IMU 采样率是 500Hz控制环 50Hz 做降采样 float notch_filter(float input) { // 系数根据中心频率 50Hz、带宽 4Hz、采样率 500Hz 计算 static float x1 0, x2 0, y1 0, y2 0; float b0 0.978, b1 -1.732, b2 0.978; float a1 -1.732, a2 0.956; float output b0 * input b1 * x1 b2 * x2 - a1 * y1 - a2 * y2; x2 x1; x1 input; y2 y1; y1 output; return output; }这里有个极其重要的前提陷波器的采样率必须远高于中心频率。如果你直接在 50Hz 控制环里对 50Hz 信号做陷波那是无效的因为采样定理要求采样率至少是信号频率的两倍而且实际工程里要五倍以上才有效。所以正确做法是让 IMU 以 500Hz 采样在 500Hz 域做陷波然后再降采样到 50Hz 给控制环用。这个流程我踩过坑一开始直接在 50Hz 域做怎么调都没效果后来才反应过来是采样率的问题。5. 常见问题与排查技巧实录5.1 站立时高频抖动像在发抖这是最常见的问题几乎每个复现的人都会遇到。抖动通常来自三个源头IMU 噪声、舵机死区、控制环增益过高。排查顺序先把 kd 降到零看抖动是否消失。如果消失说明是微分项放大了噪声解决办法是对陀螺仪读数做低通滤波或者降低 kd。如果抖动还在把 kp 降到一半看是否改善。如果改善说明增益过高系统在临界振荡附近。如果降增益也没用那就是舵机死区的问题需要换死区更小的舵机或者在控制律里加死区补偿。我遇到过一次特别诡异的抖动最后发现是 IMU 的安装螺丝没拧紧振动导致 IMU 读数里混进了机械共振。所以排查时别忘了检查机械安装。5.2 机器人往一个方向持续偏最后摔倒这是零偏问题。IMU 的陀螺仪零偏、加速度计零偏或者舵机中位没校准都会导致这个现象。排查方法是把机器人固定住读姿态角如果静止时姿态角不是零那就是零偏。解决办法是上电时做一次零偏校准取前 100 个采样点的平均值作为零偏后续读数都减去这个值。舵机中位校准也重要。舵机上电后先给一个中位角度看机械结构是不是真的在中位。如果不是要么调机械安装要么在软件里加偏移量。5.3 仿真能站实机站不住这个太常见了原因通常是仿真模型和实机的差异。主要差异点舵机延迟仿真里通常没建模、摩擦仿真里的摩擦系数是猜的、质量分布3D 打印件的实际质量和 CAD 模型有偏差、传感器噪声仿真里通常很干净。解决办法是逐项校准。舵机延迟可以用阶跃响应测出来加到仿真模型里。质量分布可以用秤称每个部件更新模型。摩擦系数比较难测但可以通过对比仿真和实机的自由摆动衰减来估计。传感器噪声可以在仿真里加高斯噪声模拟。我的经验是仿真整定出来的 kp实机用 0.6 到 0.8 倍比较稳妥。实机的 kd 反而可以比仿真大一点因为实机噪声大需要更多阻尼。5.4 常见问题速查表现象可能原因排查方法解决方向高频抖动kd 过大、IMU 噪声、舵机死区逐个降增益观察滤波、降增益、换舵机持续偏向IMU 零偏、舵机中位偏静止读姿态角零偏校准、中位校准仿真实机不一致模型参数偏差对比关节轨迹校准质量、延迟、摩擦50Hz 干扰电源纹波、PWM 耦合频谱分析硬件滤波优先数字陷波兜底站立时间短控制增益不足逐步加 kp重新整定检查相位余量关节动反控制律符号错吊装测试改符号5.5 拆解时的注意事项MicroDuck 的拆解资料网上有一些但我要提醒几点。第一拆之前先拍照每个连接器的位置、每根线的走向都拍清楚装回去的时候能省很多事。第二舵机的输出轴和结构件的连接通常有花键或者 D 型轴拆的时候不要硬撬容易把轴撬弯。第三IMU 通常是贴片焊接或者用双面胶固定拆的时候注意不要损伤焊盘。第四电池拆下来后要单独存放避免短路。我拆过一台类似的机器鸭最大的教训是没拍照装回去的时候发现有两根舵机线长度一样分不清哪个是左哪个是右最后只能上电试结果接反了舵机直接堵转烧了一个。所以拍照这件事怎么强调都不过分。6. 我对这套方案的真实体会MicroDuck 这套 50Hz 神经控制闭环说到底是一个用物理换算力的典型案例。它把重心做低把系统固有频率降下来然后用一个极简的控制律和克制的硬件配置把双足平衡跑通了。这个思路对做小型机器人的朋友特别有参考价值——不是所有项目都需要 1kHz 的控制环也不是所有项目都需要昂贵的执行器和传感器。先想清楚你的物理系统有多快再决定你的控制环要多快这个顺序不能反。我自己复现下来最大的收获是对相位滞后这四个字有了切身体会。50Hz 下每一级滤波、每一个延迟都会被放大成实实在在的振荡。所以能省的处理就省能直接用的信号就直接用别为了看起来专业去堆滤波器和状态估计。陀螺仪的角速度直接拿来当微分项比你对姿态角做差分再滤波效果好得多也简单得多。最后分享一个小技巧调参的时候把姿态角、目标角度、实际角度这三条曲线同时画出来用串口传到电脑上看。三条线一对比问题一目了然。是相位滞后、是增益不足、还是死区曲线上一眼就能看出来。这个习惯帮我省了无数个小时的瞎调时间。