玩转Microduck 机器鸭,有关命令、目录、换模型和排障

2026-10-26 16:57:18 158阅读

把鸭子跑起来只是开头。真正折腾人的在后面:想让它走快点、想换个自己训的步态、开机发现舵机不响、SSH 突然连不上、一通电就往前栽。这些事不会写在装机步骤里,但几乎每个复现的人都会碰到。

这篇只讲「已经能走了之后」:常用的几条命令、目录里哪些能动哪些别动、行走模型怎么替换、想把自己的卡做成发布镜像该怎么做,还有五类最常见的故障——每一类都说清为什么会这样,以及按什么顺序排除。命令和默认值都对着 AI-FanGe 那个 MIT 协议的 Microduck-build-tutorial 核过,飞特线的实机经验取自 kissqy 的复刻记录。

一只手从侧面扶着站在木地板上的 Microduck 机器鸭,背景是红沙发和绿植

命令都在开发电脑上敲,make 只是把一串动作包起来

先说个最容易搞混的前提:这些 make 命令不是在鸭子身上敲的,是在你自己电脑上、进了 microduck 目录之后敲的。make 不神秘,它就是把「同步代码过去」和「在那台机器上执行某条命令」捆成一条。

Microduck 机器鸭站在木质书桌上,背后是键盘和笔筒

make sync 是把本地部署代码同步到 Pi 的 ~/microduck 目录。改完代码、换了模型文件之后用它,只搬文件不动环境。

make setup 比 sync 多一步,同步完在 Pi 上执行 uv sync --frozen,按锁文件装依赖。只有改了依赖才用它,平时别拿它当 sync——慢,还会真的改动那台机器上的环境。

make run 同步并启动控制循环,这是最常用的一条。

make stop 停控制循环,程序卡住、终端关了但进程还在的时候用它;make shutdown 是安全关机,别直接拔电,原因在最后安全那节。

make imu 看 IMU 和陀螺仪的数据。这条是排查「为什么一启动就倒」的第一把工具,因为机器不知道自己装歪了,只有你从数据里看出来。

make voltage 看舵机电压,make voltage ID=2 看指定 ID 那只的电压。整机一起掉压和单只掉压是两种毛病,这个参数就是用来把它们分开的。

make gamepad-headless-enable 和 make gamepad-headless-disable 是装、卸无头手柄服务,让你不开 SSH 也能用手柄启动。改过服务文件要重新 enable 一次。

SSH 已经登进去的话,这几件事也有手敲的等价写法,不用回电脑:

cd ~/microduck && PYTHONPATH=src .venv/bin/python src/main.py

这条干三件事:进目录、把 PYTHONPATH 指到 src 让它找得到模块、用虚拟环境的解释器跑主程序。少一段都报模块找不到。

cd ~/microduck && PYTHONPATH=src .venv/bin/python src/stop.py

主程序还占着终端的时候,另开一个窗口用这条停。按 q 是软退出,这条是兜底。

sudo shutdown -h now

关机。敲完等十到十五秒,再关电源开关。

目录结构:哪几个文件夹是你的,哪几个别碰

仓库根目录下只有两大块:microduck 跑在 Pi 上,mjlab_microduck 是训练那边的。两块别混,改错地方的表现是「改了半天没反应」。

microduck 里,Makefile 是那堆命令的定义——想知道 make run 到底执行了什么,打开它看就是了,这是最诚实的文档。src 下面是主程序:main.py 把各部件接起来,scheduler.py 管调度,robot_controller.py 管舵机,imu_reader.py 读姿态。agents 目录里就一个 walk.onnx,行走模型。moves 里 walk.py 是动作逻辑。systemd 放服务定义,docs 是文档。

哪些能动:agents/walk.onnx(换模型就是换它)、moves/walk.py、systemd 里的服务定义、docs。哪些尽量别动:main.py、scheduler.py、robot_controller.py、imu_reader.py 是骨架,改错往往不报错,只表现为「程序起来了但鸭子行为怪」,这种毛病最难往回查。.venv 更别手改,那是 uv 按锁文件装出来的,弄坏了删掉重跑 make setup 比修它快。

另外 mjlab_microduck/logs 会一直变大,训练多轮攒得很快,卡空间不够先看这里;清之前确认没有还想复用的 checkpoint。

换行走模型:文件名是写死的,生效只要一条命令

行走模型就是一个 ONNX 文件,训练仓导出来之后放到 microduck/src/agents/walk.onnx 这个路径上。名字不能改——程序加载的就是这个固定路径,你放个 walk_v2.onnx 进去它不认。

放好之后在电脑上进 microduck 目录执行 make sync,下一次运行就加载新的,不用重装环境也不用重启服务。

白底渲染图,Microduck 机器鸭迈步时一条腿抬起

两个容易忽略的地方。一是训练仓和实机是两套东西:训练可以不连鸭子跑,仿真里走得好不等于装上就能走,装配、标定、动力学和供电都有差异。二是模型得跟固件和标定对上。kissqy 那条飞特线的记录里,训练中控和机器人中控是两个独立工具,换模型之前先核对固件标识和策略的约定;飞特线镜像预装 control.40,用随包固件升到 control.43,这两个数字分别代表镜像内容和当前稳定运行的固件,对不上别急着上实机。

换完模型走得比原来还差,先别怀疑模型。把旧文件挪到 agents 目录外面留一份,换回去对比一次,能立刻分清是模型的问题还是这台机器本来就有标定问题。

自己做一张发布镜像:什么时候值得,八步里最容易漏的是清理

什么情况下需要自己重做一张?三种:在 Pi 上装了系统级的东西,想让第二台机器直接复制;要把卡发给别人;怕哪天卡坏了想留个能跑的备份。只是换模型、改代码不用做镜像,make sync 就够了。

流程不复杂,难在清理。作者给的顺序是:先用现在这张卡实机跑一遍 make run 或者手柄无头运行,确认能用;关机,卡插回电脑;把整张卡克隆成本地 .img 文件;只在副本里清敏感信息——Wi-Fi 配置、SSH host keys、用户的 SSH key、/etc/machine-id、cloud-init 状态、shell history、日志、apt 缓存;把 bootfs/network-config 重置成占位模板;确认 ~/microduck/src/agents/walk.onnx、.venv、microduck-gamepad.service 三样都在;用 PiShrink 压成 microduck.img.xz;最后算一遍 SHA256,把校验值写进 README 或 Release 说明。

为什么非清不可。SSH host keys 和 machine-id 相当于这台机器的身份证,每台必须唯一——同一张卡克隆十份发出去,十台身份证一样,SSH 和系统服务都会互相打架。Wi-Fi 配置和用户的 SSH key 是私人物品,跟着镜像发出去等于把家里网络和登录凭据一起送人。cloud-init 状态、history、日志、apt 缓存是用过的痕迹,留着会让新卡首次启动的行为变得不可预测。

清理一定要在副本里做,别在原卡上清——原卡还要用,顺序反了代价是重新装一遍。

五类故障:先分清是哪一层断了

排查最省时间的做法不是背下所有修法,而是先判断断在哪一层。这套系统从上到下是:你的电脑、Wi-Fi 和蓝牙、Pi 上的系统和服务、USB 串口、舵机总线、机械结构。同一句「没反应」落在不同层,处理方式完全不同。

找不到 microduck.local

microduck.local 是 mDNS 名字,能不能被解析取决于三件事同时成立:鸭子开机进系统了、它连上 Wi-Fi 了、你的电脑和它在同一网段而且系统认 mDNS。任何一条不成立,这名字就是空的。

所以顺序是:先等一到三分钟,小板子首次开机或刚重启,服务起得比你想象的慢;再确认频段——AI-FanGe 这套镜像要求连 2.4GHz(飞特线反过来要 5GHz,见后面手柄那节,两条线别照搬);如果当初是在电脑上直接改 SD 卡里的 network-config,回头看一眼那个 YAML 的缩进有没有被动过,缩进错一格整段就废,而且它不报错,只会静默连不上;如果当初是用 HDMI 加键盘在 Pi 上配的,就登进去看它到底连上没有:

nmcli device wifi list

这条列出附近的 Wi-Fi,用来确认它真连上没有、连的是哪一个。

hostname -I

这条打印它拿到的 IP。有 IP 就说明网通了,剩下的只是名字解析的问题。

都过一遍还找不到,别跟 mDNS 较劲:进路由器后台找这台设备的 IP,直接用 ssh 用户名@IP 连过去。名字解析是方便,不是必需品。

SSH 报 host key changed

这个报错看着吓人,其实是好事,它在提醒你「对面这台机器的身份证换了,你确定还是它吗」。发布镜像每次首次启动都会重新生成 SSH host keys,所以你换了一张卡、或把一张卡重刷了一遍,同一个 microduck.local 背后的 key 就变了,而你电脑里记着的是上一张卡的。

确认过确实是自己刚刷的卡,把旧记录清掉就行:

ssh-keygen -R microduck.local

之前如果是用 IP 连的,把 IP 也清一次。清完重连,它会重新问你要不要接受新指纹。

但这里要留个心眼:这个报错同时也是中间人攻击的典型信号。如果你没刷过卡、也没换过镜像,突然冒出这句话,先别急着清记录,去确认那台设备到底是不是你的。

舵机不动,或者一动就报通信错误

舵机这条链上有六个地方会出问题,症状都是「不动」,必须有固定顺序,不然就是瞎试。

第一看电。电压不够舵机根本带不动,make voltage 看整机,make voltage ID=2 看单只。整机都低是电池或供电压降,只有某一只低是那只的线或接头。

第二看供电和地。OpenRB-150、舵机总线、树莓派三者的供电和 GND 必须共地。少一根地线,数据发得出去但回不来,表现就是通信错误。

第三看串口有没有被认出来。OpenRB-150 是走 USB 接过去的,系统里认不到这个串口设备,后面的检查全是白做。

第四看 ID。舵机 ID 必须跟装配表一致。两只撞同一个 ID,表现往往不是「两只都坏」,而是整条总线都乱——Dynamixel 是菊花链,一个节点把总线搅了,后面的全不吭声。撞 ID 最容易被误判成「舵机烧了」。

第五看波特率。这套用的是 1Mbps,波特率不对,能通电、能亮灯、就是不通话。

第六才是线序、分线和插头方向。放最后不是因为它少见,而是前五个能靠命令和数据判断,线序只能靠眼睛和万用表。

还有一个容易漏的:扭矩。程序启动时才打开舵机扭矩,只是上电没跑程序的话,舵机是软的,这时候「掰得动掰不动」不能当判断依据。

手柄连上之后 SSH 断了

先说结论:多数情况这不是故障,是无头模式的设计。镜像里那个 microduck-gamepad.service 在手柄连上之后会主动关掉 Wi-Fi,把 2.4GHz 让给蓝牙,让手柄连得更稳。所以手柄一配对、SSH 掉线是预期行为,关掉手柄 Wi-Fi 会自动回来。

但有一种是真的干扰,要分清。kissqy 那条飞特线的实机记录里,Radxa ZERO 3W 用 2.4GHz Wi-Fi 时会跟手柄的 2.4GHz 无线通信互相干扰,出现断网、SSH 超时、甚至完全连不上。他们的做法是把 ZERO 连到路由器的 5GHz 频段,避免跟手柄抢同一个频段。这里有个细节:连接名里带「5G」不等于真的连在 5GHz,要在 ZERO 上查实际频段:

nmcli -f IN-USE,SSID,FREQ,SIGNAL device wifi list

看 IN-USE 那列打了星号的那条,FREQ 才是它现在真正在用的频段。

还有一句得记住:SSH 超时本身不能证明是无线干扰。要结合三件事判断——ZERO 有没有重启过、网络是不是还保持着、实际连的是哪个频段。只看超时就下结论,容易把供电问题误判成无线问题。

一启动就容易倒

这一类最值得讲机理:「倒」是结果,原因有四五种,而且能从现象上区分开。

先理解程序启动时干了什么:它打开舵机扭矩,平滑地把身体回到 neutral pose,再读输入,再加载 walk.onnx。也就是说,它开始走之前先强行把姿态拉到它认为的零位。如果这个零位和你这台机器的实际装配对不上,它一回零位就已经把自己推歪了,后面怎么走都是倒。

按这个逻辑排。先手扶着跑一遍——这不是安慰性建议,是最快的分层方法:扶着能走、松手就倒,问题在平衡或标定;扶着也乱动、关节方向明显不对,问题在 ID 或方向。

再查左右腿舵机 ID 有没有装反。装反的典型表现是它想抬左腿结果抬了右腿,一走就侧翻。

再查膝盖 offset 跟实际装配对不对。offset 是「程序认为的零位」和「机械实际的零位」之间的差值,装配时螺丝孔位差一点,这个值就不对。

再查 IMU 安装方向。IMU 是它的内耳,装反了它以为的「上」和你看到的「上」不是一回事,它会努力把自己「扶正」到一个歪的姿态。

最后确认 walk.onnx 是当前这套硬件对应的模型。别人训的、或者给别的版本硬件用的模型,动作幅度和关节映射都可能不一样,硬套上去就是原地挣扎。

这四条都对,再回头看两个物理因素:电池电压不够,扭矩不足,站都站不稳,更别说走;地面太滑或者不平,脚掌抓不住,程序算得再对也没用。飞特线还有一条实机经验值得抄:不要用增大力度去掩盖方向或者装配错误,那只会把错误变成更快的摔倒。

安全提示:这些动作会伤机器,也会伤手

第一次运行一定要扶住。不是程序不靠谱,而是它一上来就回零位,那一下的幅度你预料不到,鸭子从桌上栽下去,脚掌和舵机输出轴最先受力。也不要在桌边或高处测试——「就试一下」是最常见的翻车起点。

不要在电池低电压时长时间运行。电压掉下去之后,舵机为维持位置会持续吃大电流,发热、堵转,最后烧的不是电池是舵机。

不要直接断电,先 make shutdown,或者用手柄的安全关机(同时按住左右扳机两秒),关机后等十到十五秒再关电源开关。原因很实在:系统还在往卡里写东西的时候断电,坏的是卡。

扭矩开着的时候别用手硬掰关节。关节这时被舵机锁住了,你掰的是电机齿轮,坏的是舵机不是你的手。要手动摆姿势,先停程序。搬动时抓躯干,别抓腿和脚掌,腿是舵机输出轴那一级,整机最脆的地方就在这里。

一只手握住机器鸭躯干把它抱在身侧,两条腿自然垂下

充电和上电之前检查短路、极性和焊点绝缘。这条在自制线材上尤其重要,反接一次可能就带走一块板子。

飞特线还有一条:舵机全功率输出的瞬时负载会让 ZERO 重启,原因是总进电口缺缓冲电容。他们的做法是在总进电口正负极之间并联一只 1000µF 电容,靠近进电口装、线尽量短,有极性电容正极接正极、负极接 GND,断电后接线;按那套大约 7.3V 的供电选 16V 耐压的。这只是缓冲,不能代替足够输出能力的电池和线材。

收个尾

这五类覆盖不了全部,但覆盖了绝大多数「卡住」的场景。真解决不了,反馈前先把信息理清楚:硬件和接口版本、机器人中控版本、实际固件标识、做了哪几步、看到什么现象、有没有日志或视频。按连不上、服务起不来、通信异常、运动异常四类分开写,别人一眼就能对上号。

命令和默认值出自 AI-FanGe 的 Microduck-build-tutorial(MIT 协议),飞特版的排障经验取自 kissqy 的复刻记录(个人非商业许可,商用要先取得书面授权)。别人踩过的坑,能绕就绕。


作者:开源复现员
链接:https://www.aiddithome.com/p/14a715c38573b6.html
本作版权归作者所有,未经允许请勿转载。若存在违规行为,您可以点击 “举报”。


登录 后发表评论
0条评论
还没有人评论过~