
7.2 电源设计要求
• 按多舵机同时起动和堵转瞬态选择线径、连接器与保险丝
• 主干尽量短,避免细线菊花链造成远端压降
• 主控5 V电源要能承受舵机动作造成的输入扰动
• 所有模块共地
• 首次上电使用限流电源,不直接插电池
• 预留物理急停或一拉即断的总电源插头
• 连接器必须防反插
• 电池应使用带保护的可靠成品包和适配充电器
运行时通过舵机报告值估计母线电压,台架阶段仍应测量稳态电压、启动瞬态和动态压降。
若实际母线与RL的6.5–8.2 V建模范围不同,应修改执行器模型并重新训练、验证策略。
7.3 总线物理层
当前官方基线:
• 接口:TTL 半双工
• 数据线:单线
• 数据逻辑:3.3 V TTL(ROBOTIS 标注 5 V tolerant)
• 协议:Dynamixel Protocol 2.0
• 速率:1,000,000 baud
• 端口:/dev/ttyS2
这里的 3.3 V 指数据线逻辑电平,不是舵机供电电压。不要用普通USB-UART的TX、RX两线直接并在一起。需要正确的半双工收发或自动方向电路,并确认高阻态、上拉和电平兼容。
7.4 台架顺序
1.不接舵机,只看串口是否空闲
2.接一颗舵机,读取型号、ID、位置、电压和温度
3.设置唯一ID
4.验证1 Mbps
5.增加第二颗并做sync_read
6.扩展到一条腿
7.扩展到15颗
8.最后加入 ID 200 的 IMU 板
每次只增加一个变量。重复ID会让回复碰撞,看起来很像电源或串口噪声。
8. IMU到Dynamixel桥接
行走策略除了关节位置,还必须知道机器人正在向哪边倾斜。Microduck没有让主控通过另一条USB或I²C路径单独读取运动IMU,而是把 IMU 包装成一个Dynamixel从设备,与舵机共用同一条总线。
如果直接使用官方兼容板,本章用于理解它的接口;如果需要自制替代板,则必须复现ID、寄存器布局、采样频率和坐标方向。
8.1 运行时接口
imu_to_dxl v2 作为ID 200的Dynamixel从设备,与15个舵机在同一次 sync_read 中返回数据。控制环从地址124开始读取12字节,源码以半开区间124–136表示,末地址136本身不属于数据块。
当前v2路径使用LSM6DSV16的SFLP姿态融合,12字节块包含三轴陀螺和压缩的四元数分量。
| 字节 | 编码 |
|---|---|
| 0..6 | gyro x/y/z,三个小端有符号 i16,量程 ±500 dps,17.5 mdps/LSB;运行时转为 rad/s |
| 6..12 | SFLP 四元数 x/y/z,三个 IEEE fp16;运行时按单位四元数恢复 `w |
当前运行时默认把传感器原始轴映射为躯干轴 [+raw_z, +raw_y, -raw_x],并等待至少25个有效融合姿态样本后才把IMU标为就绪,约相当于100 Hz下的0.25 s。替代板若安装方向不同,应修改安装四元数或固件映射,而不是在策略输入端临时交换数组槽位。
8.2 兼容板功能框图

8.3 验收条件
• 1 Mbps下连续运行至少一小时无CRC/超时错误
• 50 Hz下每个样本都更新
• 静止时陀螺零偏稳定
• 旋转方向与仿真坐标系一致
• 直立时projected_gravity接近运行时期望
• 四元数归一化且无 NaN
• 翻转和跨越四元数符号时不产生突跳
• 上电后在姿态融合尚未稳定时明确报告“未就绪”,不要伪造零姿态
如果暂时无法实现这块板,可以先在台架上用FakeIo或修改后的传感器后端验证软件,但这不代表真机策略已经可用。基本行走不能长期依赖与训练模型不匹配的USB IMU临时方案。
9.主控、Linux与运行时
硬件总线稳定后,再把控制权交给 Radxa Zero 3W 上的官方 Rust 运行时。主控板负责启动系统服务、独占 UART、读取设备、运行 ONNX,并向上层应用提供控制接口。
本阶段先验证操作系统和守护进程,不加载真实行走策略。这样可以把 Linux 配置问题与机器人动力学问题分开。
9.1 开发板路径
官方开发文档当前要求在Radxa Zero 3上使用Armbian 26.2.1 Minimal。官方roadmap记录了 Radxa Zero 3W上的实际行走bring-up。
由于官方安装文档和发布系统仍在演进,第三方复刻者应先阅读当前仓库中的:
docs/robot/install-dev.md
docs/robot/cheatsheet.md
docs/design/architecture.md
docs/design/robotd-design.md
不要只执行旧教程里的安装命令。开发构建可能涉及签名密钥、发布通道和官方板卡假设。
9.2 刷写并配置开发板
用 Armbian Imager (https://www.armbian.com/radxa-zero-3/) 选择 Radxa Zero 3 和 Armbian 26.2.1 Minimal。
为了与下面的命令和默认路径一致,建议在Imager的profile 中把用户名设为 radxa,并填入Wi-Fi和密码。如果选择其他用户名,后文所有radxa和/home/radxa都要相应替换。
首次启动并接入网络后,从电脑写入SSH 公钥:
ssh-copy-id radxa@<开发板_IP>
下面的脚本必须从电脑上的 microduck 仓库根目录运行,不要在开发板上运行:
./scripts/provision-board.sh \--pause-btd-on-pair \--name <机器人名称> \radxa@<开发板_IP>
脚本会通过SSH传送开发密钥、配置系统、处理重启并在最后执行健康检查。--pause-btd-on-pair用于规避部分AIC8800无线模块在手柄首次配对时的冲突。如果不使用手柄,它不影响基础行走闭环。仓库公开时通常不需要DUCK_TOKEN。
配置结束后登录开发板并确认版本与服务状态:
ssh radxa@<开发板_IP> robotctl version robotctl health
9.3 UART2 登录控制台冲突
Armbian 默认可能在 /dev/ttyS2 启动serial-getty,占住舵机串口。官方文档明确记录了这个问题。
先检查:
sudo fuser -v /dev/ttyS2
若确认为登录控制台占用,再禁用:
sudo systemctl mask --now serial-getty@ttyS2.service
不要在不知道占用者是谁时盲目停止系统服务。
9.4 总线独占
robotd、旧runtime、调试脚本和USB适配器不能同时控制同一条串口。两个进程交错发送包会表现为随机硬件故障。
调试原则:
• 运行robotd时关闭其他舵机工具
• 用独立初始化命令前先停止守护进程
• 不要让系统登录控制台重新启用
• 所有维护脚本都应显式获取独占权
9.5 无策略或假硬件验证
官方当前代码提供fake/无策略路径用于测试,先确认:
• 服务能启动
• Unix socket正常
• robotctl health能给出可理解的状态
• 控制环达到目标频率
• 没有摄像头或ToF时,电机服务仍然独立工作
完成这些后再连接真实总线。
10. 舵机编号、零位与整机校准
同一份策略只有在仿真和真机共享同一套“零点与正方向”时才有意义。校准不是让机器人看起来大致站直,而是建立舵机编码器读数、机械安装角和MJCF关节角之间的准确对应。
建议从单颗舵机开始,再校准一条腿,最后处理完整的15设备总线。任何方向错误都应在低幅度、无负载状态下发现。
10.1 单颗舵机配置
一颗一颗接入,设置和记录:
• ID
• 波特率
• return delay
• 驱动模式
• 位置范围
• 正方向
• 零位偏移
• 当前固件版本
官方控制层会检查若干EEPROM/RAM参数。被恢复出厂设置的舵机可能带来额外返回延迟或不同PID默认值,使整条16设备总线无法稳定达到50 Hz。
10.2 无负载方向测试
不要装上完整连杆后才发现左右符号相反
对每个关节执行很小的正向命令,核对:
• 仿真中正方向
• 真实舵机正方向
• 编码器读数方向
• home pose
• 机械限位
• 左右镜像关系
10.3 home pose
home pose 是策略输出的参考中心:
target = home_pose + action_scale × action
如果某个关节零位偏5°,策略看到的是“我在正确位置”,真实机械却已偏离。它会用其他关节补偿,常见结果是抖动、歪站、膝盖过热或一迈步就倒。
10.4 整机缓慢回到 home pose
机器人必须先固定在吊架或支架上。确认15个舵机和 IMU 状态正常后,用官方命令给关节上电,并在约两秒内渐变到home pose:
sudo robotctl robot init
这条命令会移动所有关节,而且不需要加载策略。若方向、零位或机械干涉有任何异常,立即断电。完成检查后,用下面的命令解除扭矩:
sudo robotctl robot relax --yes
relax后机器人会失去支撑并倒下,所以必须先由支架或手稳妥承重。这两条命令都通过 robotd访问总线,不要同时运行另一个舵机调试程序。
10.5 校准验收
• 断电后手动摆到home pose,左右结构应对称
• 读取的14维关节位置应接近训练定义
• 所有关节在小范围运动时无碰撞
• 嘴部ID 34可单独运动,不影响策略索引
• 15 颗舵机温度、电压和位置都能读到
• IMU ID 200的样本连续更新
• 总线50 Hz连续运行一小时无持续丢包
11. 训练、导出与部署策略
机械质量、舵机、电压和控制频率与模型对齐后,才能把仿真策略迁移到真机。
训练得到的checkpoint不能直接交给Rust运行时。需要通过官方导出脚本转换为包含观测归一化的ONNX文件。
我们需要完成同一个ONNX 能在CPU MuJoCo中正确复演,并满足真机运行时的输入、输出和延迟要求。
11.1 选择匹配的模型
第一版应尽量保持:
• XL330执行器
• 相同的14关节顺序
• 相近质量和惯量
• 相同关节限位
• 相同控制频率
• 相同动作缩放和运行时后处理
• 相同IMU坐标系和观测单位
11.2 sim-to-real 配置
官方项目还包括:
• BAM M6的XL330电压级执行器模型
• 反电动势
• Coulomb、Stribeck和负载相关摩擦
• 电池电压随机化
• 负载压降
• 命令延迟
• 摩擦随机化
• 编码器偏差和IMU误差
• 可选的±1°回差模型
• 观测噪声与NaN防护
删掉这些内容,仿真里的策略可能更漂亮,但真机迁移通常更差。
11.3 检查训练结果
uv run play \Mjlab-Velocity-Flat-MicroDuck \--wandb-run-path
不要只看“会不会向前”,还要观察:
• 足底是否持续打滑
• 头部是否用作不合理的配重
• 是否通过撞地获取奖
• 关节是否长期贴限位
• 动作是否高频抖动
• 碰撞是否依赖被简化掉的模型区域
11.4 ONNX CPU 复演
uv run scripts/infer_policy.py --walking output.onnx
这一步使用部署用ONNX,而不是训练checkpoint,可提前发现导出、归一化和命令布局错误。
11.5 把 ONNX 放到机器人上
先从电脑把策略复制到开发板:
scp output.onnx radxa@<开发板_IP>:/home/radxa/my_walking.onnxssh radxa@<开发板_IP>
在开发板上运行交互式配置工具:
sudo robotctl configure
将 policy.walk 指向新文件。写入 /etc/robot/robotd.toml 后,对应配置应为:
[policy]walk = "/home/radxa/my_walking.onnx"
保存时接受工具给出的 robotd 重启建议,也可以退出后显式重启并检查:
sudo systemctl restart robotdrobotctl version robotctl health robotctl monitor
如果模型路径错误、ONNX无法加载或输入输出宽度不是61/14,robotctl health 会报告异常。修复前不要给机器人上扭矩。再次运行sudo robotctl configure,在policy.walk上按u恢复默认值,即可重新使用随官方release提供的策略。robotctl monitor会持续显示实时状态,按 Ctrl+C 退出。
11.6 部署检查
• ONNX 输入 [1,61]
• ONNX 输出 [1,14]
• 由官方导出脚本生成
• 观测归一化器已烘入
• 14 个动作顺序正确
• 嘴部槽位不会吞掉右腿 action 9
• home pose 与真机零位一致
• action scale 与策略版本一
• 运行时滤波与训练/官方配置匹配
• 推理 warm-up 成功
• 单次推理稳定小于控制周期预算
• 任何 NaN 或非有限目标都会被拒绝
策略本身不内嵌动作EMA,头部和腿部低通位于运行时后处理链。
12. 分级真机调试
第一次真机测试的目标不是行走,而是逐层排除错误。先验证一颗舵机,再验证一条腿、完整总线、IMU、home pose和离地策略。只有前一级结果正确,才让机器人承担更多重量和自由度。
把“接线错误、索引错误、零位错误和策略不匹配”分开处理,避免整机摔倒后只能猜测原因。
12.1 十级调试顺序
任一级出现方向、限位、供电、温升、时序或通信异常,都应停在该级修复,不要带着已知问题进入下一阶段。
推荐顺序:
Test 1:单舵机
读取位置、速度、电压、温度,做 ±5° 小运动。
Test 2:一条腿
卸载或悬空,验证五关节顺序、方向和限位。
Test 3:15 舵机在线但扭矩关闭
确认每个 ID 唯一,状态读取稳定。
Test 4:加入IMU
确认16个设备一次 sync_read能稳定运行,姿态方向正确。
Test 5:缓慢回 home pose
机器人固定在吊架上,使用缓慢插值,观察是否有反向或干涉。
Test 6:脚离地运行策略
检查动作顺序、幅度和对称性。此时不能判断平衡性能,但能发现严重映射错误。
Test 7:双脚接触、外部扶持
只加载站立策略,逐步增加支撑负载。
Test 8:保护绳下独立站立
地面铺软垫,急停在手边,先测试 5–10 秒。
Test 9:扶持行走
小速度命令,记录IMU、关节、action、目标和总线时序。
Test 10:短距离自由行走
从 0.2 m 开始,不以“一米”作为第一次目标。
12.2 调试日志
先用 robotctl monitor 观察实时状态;需要保存机器可读日志时,可以使用:
robotctl monitor --json --hz 50 > run.jsonl
最少记录:
• 61 维 observation
• 14 维 action
• 15 个目标位置
• 15 个实测位置和速
• IMU 原始块与投影重力
• 母线电压
• 各舵机温度
• 控制周期、读写耗时和丢包
• 视频
没有日志的摔倒只能重看视频猜,有日志的摔倒可以与MuJoCo同步对比。
13. 硬件变化与重新训练
强化学习策略会适应训练模型中的重量、惯量、摩擦、回差和执行器响应。更换舵机、加厚外壳或改变电池位置,不只是机械层面的修改,也改变了策略面对的动力学系统。
小改动先实测并回填模型,当质量、质心或执行器特性明显变化时,应重新训练,而不是只靠增大动作幅度补偿。
以下变化通常会破坏现成策略的迁移条件:
• 换成不同型号舵机
• 关节减速比、速度或力矩曲线变化
• 关节回差变化
• 舵机通信延迟变化
• 整机增重或质心移动
• 腿长、足底形状或摩擦改变
• IMU 安装角度变化
• 控制频率改变
• 位置增益或动作滤波改变
• 电池电压范围改变
正确做法不是只调 action_scale,还要:
1.测量新硬件
2.更新MJCF,质量、惯量、几何、限位
3.辨识执行器,摩擦、回差、延迟
4.更新domain randomization
5.smoke test
6.重新训练
7.导出 ONNX
8.CPU 复演
9.真机扶持测试
14. 常见故障排查
排查时先判断问题属于哪一层:设备是否在线、控制周期是否稳定、关节映射是否正确、仿真与真机是否一致。一次只改变一个变量,并保存修改前后的日志。
下面的表格按“现象 → 高概率原因 → 第一项检查”组织,可作为台架和真机测试时的快速索引。
| 现象 | 高概率原因 | 优先检查 |
|---|---|---|
| 所有舵机都不可见 | /dev/ttyS2被登录控制台占用、未供电、物理层错误 | fuser、母线电压、半双工接口 |
| 单颗舵机偶尔掉线 | 连接器、线径、重复 ID、return delay、压降 | 单颗台架、ID 表、示波器 |
| 16 设备时达不到 50 Hz | 返回延迟、总线错误、第二写入者、IMU 响应慢 | EEPROM、独占端口、时序日志 |
| 姿态静止不动但总线无报错 | IMU 样本冻结 | 样本计数、连续块是否完全相同 |
| 一上扭矩就猛烈撞限位 | 关节方向、零位、动作映射或单位错误 | 单关节小运动、home pose、action 顺序 |
| 左腿正常、右腿乱动 | 嘴部 index 9 插入错误或右腿映射错一位 | 14 动作到 15 槽目标的映射 |
| 仿真正常,ONNX CPU 复演异常 | 导出或观测归一化器错误 | 只用官方scripts/export.py |
| CPU 复演正常,真机立即倒 | 质量/质心、IMU 坐标、零位、滤波、执行器模型不匹配 | 与仿真逐项对齐日志 |
| 站立正常,迈步就掉电重启 | 电源瞬态、线阻、稳压器余量不足 | 示波器测舵机母线和 5 V |
| 关节持续发热 | 零位偏差、结构卡滞、增益或摩擦不匹配 | 无负载电流、机械手感、目标-实测误差 |
| ToF 服务慢或影响系统 | I²C 配置、固件加载、错误地放进控制环 | 独立运行tofd,不要阻塞robotd |
| 更新后行为变了但版本看似正确 | 守护进程未重启、策略和二进制不匹配、配置覆盖 | robotctl version、health、策略路径 |
15.项目验收清单
不要只用“走起来了”来判断项目是否完成。按下面的清单逐项验收,可以保证仿真、机械、电气、软件和真机结果都能够重复,而不是偶然成功一次。
| 分类 | 验收项 |
|---|---|
| 仿真与训练 | ☐ uv run list-envs 正常 |
| ☐ CPU 测试通过 | |
| ☐ 64 个环境 / 5 次迭代的冒烟测试通过 | |
| ☐ 策略可在仿真查看器中运行 | |
| ☐ ONNX 由官方脚本导出 | |
| ☐ ONNX CPU 复演正常 | |
| 机械 | ☐ 关节树和轴线与 MJCF 一致 |
| ☐ 15 个刚体组与分色装配图、零件对照表.json 一致 | |
| ☐ 在 CAD 中重建了 joint pos、axis 和 range,没有把定位 STL 当作可运动装配 | |
| ☐ 单关节测试件通过 | |
| ☐ 左右腿方向和限位正确 | |
| ☐ 全行程干涉、线束运动包络和工具拆装空间已检查 | |
| ☐ 每个总成已称重 | |
| ☐ 质心和整机质量已记录 | |
| ☐ 线束在全行程不拉扯、不夹线 | |
| 电气 | ☐ 电源有限流、保险和物理急停 |
| ☐ 实测舵机母线在所购舵机的数据手册范围内,未依据第三方推测直连 2S | |
| ☐ 主控 5 V 在舵机动作时稳定 | |
| ☐ 15 个舵机 ID 唯一 | |
| ☐ 1 Mbps 总线稳定 | |
| ☐ ID 200 IMU 连续更新 | |
| ☐ 50 Hz 运行一小时无持续错误 | |
| 软件与校准 | ☐ UART2 无第二占用者 |
| ☐ home pose 与实物零位一致未错位 | |
| ☐ 关节方向、单位和范围一致 | |
| ☐ robotctl health 可读 | |
| ☐ 策略输入输出形状正确 | |
| ☐ 观测归一化器、action scale 和滤波匹配 | |
| 真机 | ☐ 吊架下回 home pose |
| ☐ 离地运行策略无异常 | |
| ☐ 扶持站立稳定 | |
| ☐ 保护绳下独立站立 | |
| ☐ 小速度扶持行走 | |
| ☐ 短距离自由行走 | |
| ☐ 每次测试有日志和视频 |
本文原作者:yishanyishan。











ONNX部署那段很关键,之前差点直接把checkpoint转了就上机,幸好看到了导出路径的要求。
从仿真到真机这个流程梳理得很系统,特别是分级调试那段,每一步都有明确的验收标准。
那个故障排查表太实用了,上次调舵机掉线折腾了一整天,早知道先查repeat ID了。
电源树这部分写得很清楚,之前一直搞不懂舵机供电和主控供电为什么要分开,看完终于明白了。