MicroDuck 机器鸭拆解:50Hz 控制闭环如何实现双足动态平衡
2026/9/20 5:23:34 网站建设 项目流程

1. 一只机器鸭凭什么值得拆解

第一次看到 MicroDuck 这个项目的时候,我正蹲在工作室里调一台四足平台的步态参数,屏幕上那条关节力矩曲线抖得像心电图。朋友甩过来一段视频,画面里一只巴掌大的双足机器鸭在桌面上原地踏步,动作谈不上优雅,但每一步落地都稳得出奇,没有那种廉价舵机常见的抽搐和过冲。更让我在意的是视频角落那行小字:控制回路跑在 50Hz。

50Hz 这个数字,在外行看来平平无奇,但凡是碰过机器人实时控制的人都会愣一下。现在主流的双足、四足平台,姿态控制环动辄跑到 500Hz 甚至 1kHz,IMU 采样、关节闭环、状态估计恨不得把 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); // 读 IMU,SPI 传输 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%。这个系数下,姿态角的静态精度不错,动态滞后也能接受。

控制律里的kpkd,就是前面说的比例和微分系数。注意这里我用了两个关节的目标角度,髋关节和膝关节。为什么要两个?因为单靠髋关节,机器人的姿态修正能力有限,加上膝关节可以形成更丰富的姿态调整空间。但膝关节的系数要比髋关节小,否则腿会乱蹬。我的经验值是膝关节系数取髋关节的 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 下,每一级滤波、每一个延迟,都会被放大成实实在在的振荡。所以能省的处理就省,能直接用的信号就直接用,别为了"看起来专业"去堆滤波器和状态估计。陀螺仪的角速度直接拿来当微分项,比你对姿态角做差分再滤波,效果好得多,也简单得多。

最后分享一个小技巧:调参的时候,把姿态角、目标角度、实际角度这三条曲线同时画出来,用串口传到电脑上看。三条线一对比,问题一目了然。是相位滞后、是增益不足、还是死区,曲线上一眼就能看出来。这个习惯帮我省了无数个小时的瞎调时间。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询