1. 项目缘起:为什么我要做一只双足机器鸭
1.1 从“玩具”到“平台”的定位转变
最早动这个念头,其实特别朴素——我想做一个能在地上走来走去、看起来又不太像传统双足机器人的东西。市面上双足机器人不是没有,但要么是动辄几万块的科研平台,要么是只能做几个预设动作的玩具。我想要的是一台能跑控制算法、能实时闭环、结构还足够简单的小型双足平台,成本控制在千元级别,最好还能塞进一个看起来有点意思的外壳里。
MicroDuck 这个名字就是这么来的。鸭子的身体结构其实特别适合做双足实验:重心靠后、腿短、步幅小,天然就是一个低动态的行走模型。相比人形机器人那种高重心、大惯量的系统,机器鸭的容错率高得多,摔了也不心疼,调参的时候心理压力小很多。这一点很关键,我见过太多人做双足项目,第一步就被“怕摔”劝退了。
这个项目的核心目标有三个:第一,50Hz 的神经控制闭环,也就是控制频率稳定在每秒 50 次,这是整个系统的节拍器;第二,完整的感知-决策-执行链路,从 IMU 姿态解算到关节力矩输出,中间不能有断点;第三,可复现、可拆解,所有资料开源,别人拿到能自己搭一台出来。说白了,这不是一个炫技项目,是一个教学和实验平台。
1.2 50Hz 这个数字是怎么定下来的
很多人第一反应会问:为什么是 50Hz,不是 100Hz 或者 200Hz?这个问题我当初也纠结了很久,后来是这么算的。
双足行走的步态周期一般在 0.4 到 0.8 秒之间,取中间值 0.6 秒。一个步态周期里,关键的相位切换点大概有 4 到 6 个(抬腿、落地、重心转移、支撑切换)。如果控制频率是 50Hz,那么每个步态周期有 30 个控制节拍,平均每个相位切换点能分到 5 到 7 个节拍。这个分辨率足够捕捉相位变化,又不会让计算量爆炸。
再往上算,100Hz 意味着每个周期 60 个节拍,理论上更平滑,但对 MCU 的算力要求翻倍,而且 IMU 的噪声在更高频率下反而更容易被放大。50Hz 配合一个设计良好的50Hz 陷波器,刚好能把电机振动和机械共振压住,又不至于引入太大的相位滞后。实测下来,50Hz 的控制周期是 20ms,这个时间窗口里完成一次完整的“读传感器-算姿态-跑控制器-写 PWM”绰绰有余,留有余量给调试和日志输出。
提示:控制频率不是越高越好。频率越高,对传感器噪声越敏感,对滤波器设计要求越高。50Hz 是一个在响应速度和鲁棒性之间比较平衡的点,尤其适合这种小尺寸、低惯量的双足平台。
1.3 适合谁来参考这个项目
如果你是完全零基础的小白,这个项目会让你有点吃力,但也不是不能碰。我建议你先从理解“控制闭环”这个概念开始,把整个系统拆成感知、决策、执行三块,一块一块啃。如果你有单片机开发经验,或者玩过舵机云台、平衡车之类的项目,那上手会快很多。
对于做机器人方向的学生和工程师,MicroDuck 的价值在于它是一个完整的、可运行的闭环系统,不是那种只跑仿真的玩具。你可以拿它验证自己的步态算法、滤波器设计、状态估计方案,改坏了重新烧录就行。对于爱好者,它是一台能让你真正理解“控制周期”和“实时性”的实体设备,比看一百篇论文都管用。
2. 系统架构拆解:一只机器鸭的神经骨架
2.1 硬件选型:为什么不用现成的舵机方案
市面上大部分小型双足机器人用的是舵机,便宜、简单、扭矩还行。但我一开始就排除了舵机方案,原因有三个。
第一,舵机的控制接口是位置指令,内部自带一个闭环,你没法直接控制力矩。而双足行走的核心恰恰是力矩控制,尤其是在支撑相和摆动相切换的时候,力矩的平滑过渡决定了步态稳不稳。第二,舵机的响应带宽有限,50Hz 的控制频率下,舵机内部的 PID 往往跟不上,会出现明显的相位滞后。第三,舵机的反馈信息很少,你只知道它转到了哪个位置,不知道它用了多大力、电流多大、温度多高。
所以我选的是无刷电机加行星减速器的方案。具体来说,是 2208 无刷电机配 1:10 的行星减速箱,额定扭矩在 0.8 N·m 左右,峰值能到 1.5 N·m。这个扭矩对于一只体重 1.2kg 左右的机器鸭来说,做静态站立和低速行走完全够用。电机驱动器用的是支持 FOC 的板子,可以跑力矩模式,也能读回电流和位置。
IMU 选的是 MPU6050 的升级版,六轴,I2C 接口,输出频率能到 1kHz。虽然 50Hz 的控制周期只需要 20ms 读一次,但高频率采样配合滑动平均滤波,能把姿态解算的噪声压得很低。主控用的是 STM32F405,168MHz 主频,带 FPU,跑姿态解算和控制器绰绰有余。
| 部件 | 型号/规格 | 关键参数 | 选型理由 |
|---|---|---|---|
| 主控 | STM32F405 | 168MHz, FPU, 1MB Flash | 算力足够,生态成熟 |
| IMU | MPU6050 升级版 | 六轴, 1kHz 输出 | 成本低,资料多 |
| 电机 | 2208 无刷 | 1:10 减速, 0.8N·m | 力矩可控,反馈丰富 |
| 驱动器 | FOC 驱动板 | 支持力矩/速度/位置模式 | 闭环带宽高 |
| 电源 | 3S 锂电 | 11.1V, 1500mAh | 续航约 40 分钟 |
2.2 控制闭环的四个环节
整个控制闭环可以拆成四个环节,我用一个循环图来描述:传感器采集 → 状态估计 → 控制器计算 → 执行器输出,然后回到传感器采集。这个循环每 20ms 跑一次,雷打不动。
传感器采集环节,我读的是 IMU 的加速度和角速度,以及两个电机的编码器位置和电流。这里有个细节:IMU 的 I2C 读取不能阻塞太久,否则会打乱整个 20ms 的节拍。我的做法是把 I2C 配置成 DMA 模式,数据搬完了触发中断,主循环去取。这样读取时间从原来的 3ms 降到了 0.5ms 以内。
状态估计环节,用的是互补滤波。加速度计算倾角,陀螺仪积分算角速度,两者加权融合。互补滤波的系数我调了很久,最后定在 0.98 对陀螺仪、0.02 对加速度计。这个系数意味着我更信任陀螺仪的短期积分,但用加速度计来修正长期漂移。50Hz 下,这个滤波器跑起来很稳,姿态角波动在 ±0.5 度以内。
控制器计算环节,我用的是任务空间 PD 控制加前馈。简单说,就是先根据步态相位生成期望的足端轨迹,然后通过雅可比矩阵把足端力映射到关节力矩。PD 参数是分开调的,支撑相和摆动相用两套参数。支撑相要硬一点,保证承重;摆动相要软一点,保证落地不弹跳。
执行器输出环节,就是把算出来的力矩值通过 CAN 总线发给电机驱动器。这里要注意,力矩指令要做限幅,防止瞬间过流。我设的限幅是额定扭矩的 1.5 倍,超过就截断。
2.3 50Hz 陷波器的设计考量
电机转动的时候,减速箱的齿轮啮合会产生周期性的振动,频率大概在 45 到 55Hz 之间。这个振动会通过机身传到 IMU 上,如果不处理,姿态解算出来的角度会一直抖。我试过用低通滤波,但截止频率设低了会引入太大滞后,设高了又滤不干净。
最后用的是50Hz 双 T 型陷波滤波器。这个滤波器的特点是在 50Hz 附近有一个很深的陷波,但对其他频率的信号影响很小。设计的时候,我先用频谱分析仪测了电机振动的实际频率,发现峰值在 48Hz 左右,所以把陷波中心频率定在 48Hz,带宽设了 6Hz。这样既能压住振动,又不会把有用的步态信号滤掉。
双 T 型陷波器的传递函数是这样的:
# 双T型陷波滤波器系数计算 import numpy as np def notch_coeffs(f0, fs, Q): w0 = 2 * np.pi * f0 / fs alpha = np.sin(w0) / (2 * Q) b0 = 1 b1 = -2 * np.cos(w0) b2 = 1 a0 = 1 + alpha a1 = -2 * np.cos(w0) a2 = 1 - alpha # 归一化 b = [b0/a0, b1/a0, b2/a0] a = [1, a1/a0, a2/a0] return b, a b, a = notch_coeffs(48, 50, 5) print("b:", b) print("a:", a)这段代码算出来的系数直接烧进 MCU,每个控制周期对 IMU 的角速度做一次滤波。实测下来,电机全速运转时,姿态角的抖动从 ±3 度降到了 ±0.8 度,效果非常明显。
注意:陷波器的中心频率一定要根据实际测量来定,不能拍脑袋。不同批次的电机、不同的装配松紧度,振动频率都会有偏差。我建议先用手机上的频谱分析 App 粗测一下,再精调。
3. 实操过程:从零搭建一台 MicroDuck
3.1 机械结构的装配顺序与要点
装配顺序很重要,顺序错了后面要拆了重来。我的建议是:先装腿,再装身体,最后装外壳。
装腿的时候,先把髋关节的电机固定到骨盆板上,注意电机的出线方向要朝内,不然会跟另一条腿干涉。然后装大腿连杆,这里用的是碳纤维板,轻而且刚性够。膝关节的电机装在大腿末端,同样注意出线方向。最后装小腿和脚掌,脚掌上贴了一层硅胶垫,增加摩擦力的同时也能吸收落地冲击。
装身体的时候,先把主控板和驱动器用尼龙柱固定到底板上,然后装 IMU。IMU 的安装位置很关键,要尽量靠近机器人的重心,而且要用减震胶垫隔离,不然电机振动会直接传上去。我试过用硬连接,结果姿态噪声大了三倍,换成减震胶垫之后立刻好转。
装外壳的时候,鸭子的头和尾巴是 3D 打印的,用卡扣固定,方便拆装。外壳不只是为了好看,它还能保护内部的线缆,防止行走的时候被勾住。
3.2 固件烧录与参数配置
固件分两部分:主控固件和电机驱动器固件。主控固件用 Keil 或者 STM32CubeIDE 编译,烧录的时候注意选对芯片型号。电机驱动器固件一般厂家会提供,用它们的上位机工具烧录就行。
烧录完之后,第一步是校准 IMU。把机器鸭放在水平桌面上,静止不动,运行校准程序,采集 1000 个样本求平均,把零偏存到 Flash 里。这一步不做,姿态解算会一直漂。
第二步是配置电机参数。包括极对数、减速比、编码器分辨率、电流环 PID。这些参数厂家一般会给参考值,但最好自己再调一遍。我的做法是先用速度模式跑一下,看波形稳不稳,然后再切到力矩模式。
第三步是设置控制参数。包括控制频率(50Hz)、陷波器系数、互补滤波系数、PD 参数。这些参数我整理成了一个配置表,存在主控的 Flash 里,可以通过串口在线修改,不用每次重新烧录。
// 控制参数配置结构体 typedef struct { float control_freq; // 50.0 Hz float notch_f0; // 48.0 Hz float notch_Q; // 5.0 float comp_alpha; // 0.98 float kp_stance; // 支撑相Kp float kd_stance; // 支撑相Kd float kp_swing; // 摆动相Kp float kd_swing; // 摆动相Kd float torque_limit; // 1.5倍额定 } ControlConfig;3.3 步态生成与相位切换逻辑
步态生成我用的是有限状态机加轨迹插值。整个步态周期分成四个状态:左腿支撑、左腿摆动、右腿支撑、右腿摆动。每个状态持续 0.3 秒,加起来 0.6 秒一个完整周期。
状态切换的触发条件是时间,不是传感器。为什么?因为时间触发更稳定,不会因为传感器噪声导致误切换。但我会用足端接触传感器做一个安全校验:如果到了该切换的时间,但足端还没接触地面,就延迟 20ms 再切,防止踏空。
足端轨迹用的是贝塞尔曲线,摆动相的起点和终点都是支撑相的位置,中间抬高 3cm。这样生成的轨迹平滑,速度和加速度都连续,不会对电机造成冲击。
# 足端轨迹生成(简化版) def bezier_traj(p0, p1, p2, p3, t): # 三次贝塞尔曲线 x = (1-t)**3 * p0[0] + 3*(1-t)**2*t * p1[0] + 3*(1-t)*t**2 * p2[0] + t**3 * p3[0] y = (1-t)**3 * p0[1] + 3*(1-t)**2*t * p1[1] + 3*(1-t)*t**2 * p2[1] + t**3 * p3[1] return x, y # 摆动相轨迹:起点(0,0),控制点(0.02,0.04),控制点(0.06,0.04),终点(0.08,0) for i in range(30): # 50Hz下,0.6秒周期有30个点 t = i / 29.0 x, y = bezier_traj((0,0), (0.02,0.04), (0.06,0.04), (0.08,0), t) print(f"t={t:.2f}, x={x:.4f}, y={y:.4f}")3.4 实时调试与数据记录
调试的时候,我最依赖的是串口波形。主控每 20ms 发一帧数据出来,包括姿态角、关节角度、力矩指令、电流值。上位机用 Python 的 matplotlib 实时画出来,一眼就能看出哪里不对。
数据记录也很重要。我会把每次调试的数据存成 CSV,方便事后分析。有一次我发现机器鸭走几步就往左偏,查了数据才发现是左腿的电机零位偏了 2 度,重新校准之后就好了。如果没有数据记录,这种问题很难定位。
实操心得:调试的时候一定要一次只改一个参数。我见过有人一口气改五个参数,结果机器鸭行为变了,但不知道是哪个参数起的作用。改一个,测一次,记一次,这是最快的路径。
4. 常见问题与排查技巧实录
4.1 姿态解算漂移与振动问题
姿态漂移是最常见的问题,表现是机器鸭站着不动,但姿态角一直在缓慢变化。原因通常是 IMU 零偏没校准好,或者互补滤波系数不合适。我的排查步骤是:先看静止时的角速度输出,如果零偏超过 0.5 度/秒,就重新校准;如果零偏正常但角度还是漂,就把互补滤波的 alpha 调大一点,更信任陀螺仪。
振动问题更麻烦,表现是姿态角高频抖动。前面说的 50Hz 陷波器就是解决这个的。但如果陷波器调了还是抖,就要检查 IMU 的机械安装。我遇到过 IMU 没贴紧、螺丝松动的情况,重新固定之后抖动就消失了。
| 问题现象 | 可能原因 | 排查方法 | 解决方案 |
|---|---|---|---|
| 姿态角缓慢漂移 | IMU零偏未校准 | 静止时看角速度输出 | 重新校准零偏 |
| 姿态角高频抖动 | 电机振动传导 | 频谱分析找振动频率 | 调整陷波器参数 |
| 抖动依旧 | IMU安装松动 | 手动晃动IMU看输出 | 重新固定,加减震垫 |
| 步态不稳 | PD参数不匹配 | 看关节力矩波形 | 分支撑/摆动相调参 |
| 电机发热 | 力矩限幅过高 | 测电流有效值 | 降低限幅,检查摩擦 |
4.2 电机力矩控制异常排查
电机力矩控制异常的表现是:指令发下去,但电机不转,或者转得很奇怪。我遇到过几种情况。
一种是CAN 总线通信失败。CAN 的终端电阻一定要接,120 欧姆,两端各一个。我一开始没接,通信时好时坏,查了半天才发现是这个问题。另一种是电机零位不对。无刷电机的零位是电角度零点,如果校准不准,力矩输出会有一个正弦误差,表现为电机转起来一顿一顿的。解决办法是重新跑一遍零位校准,确保编码器读数和电角度对齐。
还有一种是电流环带宽不够。FOC 驱动器的电流环 PID 如果调得太软,力矩响应会滞后,50Hz 的控制周期下就会出问题。我的做法是把电流环带宽调到 1kHz 以上,这样力矩指令基本能实时跟踪。
4.3 步态相位切换失败的处理
相位切换失败的表现是:机器鸭走着走着突然停住,或者两条腿同时摆动导致摔倒。原因通常是状态机的切换条件没写好,或者足端接触检测不可靠。
我的处理方法是加超时保护。每个状态都有一个最大持续时间,比如支撑相最多 0.5 秒,摆动相最多 0.4 秒。如果超时了还没切换,就强制切换到下一个状态,同时记录一个错误标志。这样即使传感器出问题,机器鸭也不会卡死。
另外,足端接触检测我用了双重判断:一个是足底的压力传感器,一个是电机的电流。如果压力传感器有信号,或者电机电流超过阈值,就认为足端接触了。两个条件满足一个就行,提高了可靠性。
4.4 电源管理与续航优化
续航是个容易被忽视的问题。3S 1500mAh 的电池,理论上能跑 40 分钟,但实际用下来只有 25 分钟左右。原因是电机在支撑相的时候电流很大,峰值能到 3A。
优化方法有几个:一是降低站立高度,减少膝关节的力矩需求;二是优化步态,缩短摆动相时间,减少电机加速的次数;三是加一个大电容,在电机峰值电流的时候由电容供电,减轻电池负担。我加了一个 1000uF 的低 ESR 电容,续航提升到了 32 分钟。
提示:电池不要用到完全没电再充,锂电过放会永久损坏。我设的截止电压是 9.6V(3.2V每节),到了就报警,强制关机。
5. 仿真与实物联调:MicroDuck 在 MuJoCo 中的复现
5.1 为什么要在 MuJoCo 里先跑一遍
实物调试的成本很高,摔一次可能就要修半天。所以我在实物装配之前,先在 MuJoCo 里把整个控制链路跑通了。MuJoCo 的好处是物理仿真精度高,接触模型比较真实,而且支持实时查看器,能看到机器鸭在虚拟环境里走。
我的流程是:先在 MuJoCo 里建一个和实物尺寸一致的模型,包括质量、惯量、关节限位、摩擦系数。然后把控制代码移植过去,用 MuJoCo 的传感器接口替代真实的 IMU 和编码器。这样控制器代码几乎不用改,就能在仿真里跑。
仿真里调参比实物快得多,因为可以加速运行,也可以随时暂停、回放。我一般会在仿真里把 PD 参数调到差不多,然后再上实物微调。这样实物调试的时间能缩短一半以上。
5.2 MuJoCo 模型的关键参数配置
MuJoCo 模型的核心是 XML 文件,里面定义了机器鸭的几何、关节、执行器和传感器。我重点说几个容易出错的参数。
质量与惯量:一定要根据实物测量来填,不能随便估。我用厨房秤称了每个部件的质量,用游标卡尺量了尺寸,然后算的惯量。惯量填错了,仿真里的步态会和实物差很多。
关节阻尼:这个参数影响很大。填太小,仿真里关节会一直晃;填太大,步态会变得很僵硬。我试了好几次,最后定在 0.01 N·m·s/rad,和实物的减速箱阻尼比较接近。
接触参数:包括摩擦系数、接触刚度、接触阻尼。摩擦系数我设的 0.8,和硅胶垫的实际摩擦差不多。接触刚度设的 10000 N/m,阻尼设的 100 N·s/m。这些参数需要根据仿真表现微调,目标是让足端落地时不弹跳、不穿透。
<!-- MuJoCo 关节配置示例 --> <joint name="hip_left" type="hinge" axis="0 1 0" range="-1.2 1.2" damping="0.01" armature="0.001"/> <joint name="knee_left" type="hinge" axis="0 1 0" range="-2.0 0" damping="0.01" armature="0.001"/> <!-- 接触参数 --> <geom name="foot_left" type="box" size="0.04 0.02 0.01" friction="0.8 0.1 0.1" solref="0.01 1" solimp="0.9 0.95 0.001"/>5.3 仿真与实物的差异处理
仿真再准,和实物也有差异。我总结了几点主要的差异和应对方法。
传感器噪声:仿真里的 IMU 是理想的,没有噪声。实物有噪声,而且有振动。所以我在仿真里给 IMU 加了高斯噪声,模拟实物的噪声水平。这样调出来的滤波器参数,上实物才能用。
电机动态:仿真里的电机是理想力矩源,实物有电流环带宽限制、有摩擦、有齿隙。我在仿真里给力矩指令加了一阶低通,模拟电流环的滞后。齿隙比较难模拟,我是在实物调试的时候单独处理的。
通信延迟:仿真里没有通信延迟,实物有 CAN 总线的传输延迟,大概 1ms 左右。这个延迟在 50Hz 下影响不大,但如果控制频率提到 100Hz 就要考虑了。
5.4 仿真回放与数据对比
MuJoCo 的查看器支持重新播放,这个功能特别有用。我可以把一次仿真跑下来的数据存成轨迹文件,然后重新加载,一帧一帧地看机器鸭的动作。哪里不对,暂停下来,看关节角度、力矩、接触力,一目了然。
我还会把仿真数据和实物数据放在一起对比。比如关节角度曲线,仿真里是平滑的,实物里可能有抖动。抖动的来源就是前面说的振动和噪声。通过对比,我能判断是控制器的问题还是机械的问题。
实操心得:仿真里跑得再好,上实物也要做好摔的准备。我第一次上实物的时候,机器鸭走了三步就往前扑倒了。后来发现是重心位置和仿真里差了 5mm,重新调整电池位置就好了。仿真和实物的差距,往往就在这些细节上。
6. 拆解资料与二次开发建议
6.1 完整拆解清单与物料表
我把 MicroDuck 的拆解资料整理成了一份完整的物料表,包括每个部件的名称、规格、数量、采购渠道和参考价格。这份表我放在项目仓库里,别人可以直接照着买。
| 类别 | 部件 | 规格 | 数量 | 备注 |
|---|---|---|---|---|
| 结构 | 碳纤维板 | 2mm厚 | 1套 | 含骨盆、大腿、小腿 |
| 结构 | 3D打印件 | PLA | 1套 | 鸭头、鸭尾、外壳 |
| 驱动 | 无刷电机 | 2208 | 2个 | 带1:10减速箱 |
| 驱动 | FOC驱动器 | 支持CAN | 2个 | 力矩模式 |
| 控制 | 主控板 | STM32F405 | 1个 | 带FPU |
| 传感 | IMU | 六轴 | 1个 | I2C接口 |
| 电源 | 锂电池 | 3S 1500mAh | 1个 | 带保护板 |
| 紧固 | 螺丝/尼龙柱 | M2/M3 | 若干 | 含减震垫 |
6.2 二次开发的几个方向
MicroDuck 作为一个平台,可以往几个方向扩展。
步态算法验证:你可以把现在的有限状态机换成 CPG(中枢模式发生器),或者用强化学习训练一个步态策略。50Hz 的控制频率对强化学习来说有点低,但可以跑一些简单的策略网络。
状态估计升级:现在的互补滤波比较简单,你可以换成卡尔曼滤波或者粒子滤波,提高姿态估计的精度。IMU 也可以换成更高精度的型号,比如带磁力计的九轴 IMU。
感知扩展:加一个摄像头或者激光测距,让机器鸭能感知前方障碍物,做简单的避障。主控的算力有限,可以考虑加一个树莓派或者 Jetson Nano 做上层决策,主控只负责底层控制。
通信升级:现在的 CAN 总线带宽有限,如果要传图像或者大量数据,可以换成以太网或者 WiFi。但要注意,通信延迟会增加,控制闭环的实时性会受影响。
6.3 开源资料与社区协作
我把 MicroDuck 的所有资料都开源了,包括机械图纸、PCB 文件、固件源码、仿真模型、调试工具。仓库地址在项目主页上,有兴趣的可以自己去拿。
开源的好处是,别人可以帮你发现问题、改进设计。我收到过好几个有价值的反馈,比如有人发现膝关节的限位角度不够,有人建议把 IMU 的安装位置再降低一点。这些反馈我都采纳了,现在的版本比第一版稳定了很多。
如果你也想参与,我建议从复现开始。先照着资料搭一台出来,跑通基本步态,然后再改。改的时候,把你遇到的问题和解决方案记录下来,提交到仓库里。这样整个项目才能越做越好。
提示:复现的时候不要一上来就改设计。先按原版做,跑通了再改。我见过太多人一上来就改,结果出了问题不知道是原版的问题还是自己改的问题,浪费很多时间。
7. 个人实操体会与后续扩展思路
做 MicroDuck 这个项目,最大的体会是:控制闭环的稳定性,比算法的先进性重要得多。我试过很多花哨的算法,最后发现,只要 50Hz 的节拍稳、陷波器调好、PD 参数匹配,简单的控制律也能走出很稳的步态。反过来,算法再先进,如果控制周期抖动、传感器噪声大,照样走不好。
另一个体会是仿真和实物要交替迭代。纯仿真调参快,但容易忽略实物的非线性;纯实物调试慢,而且容易摔。我的做法是仿真里调个大概,实物上微调,然后再回到仿真里验证。这样来回几次,参数就收敛了。
后续我打算做几个扩展:一是加一个简单的视觉模块,让机器鸭能跟着人走;二是把控制频率提到 100Hz,看看步态会不会更平滑;三是做一个多机版本,让两只机器鸭能互相配合。这些都在计划中,做好了会继续开源。
最后分享一个小技巧:调试的时候,把控制周期的时间戳打出来。我一开始没打,后来发现偶尔会有周期抖动,查了半天发现是串口打印阻塞了主循环。把打印改成 DMA 之后,周期抖动从 ±2ms 降到了 ±0.1ms。这个细节很小,但对闭环稳定性影响很大。