Skip to content

Latest commit

 

History

13 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Orthrus · 双头犬

一条狗,两个脑:MPC 管"怎么走",RL 管"摔了怎么办"。

📖 技术设计文档:动力学模型、数学控制器设计与验证工作流 —— 全部公式与常数和代码逐项一致(SRB 动力学、QP 形式化、MDP/奖励、仲裁状态机、72 试验协议)。开发全过程记录见 docs/claude-history.txt。

🎬 演示视频(26 s):Orthrus 混合控制器实录 —— MPC 行走 → 被踹变橙红(RL 脑接管救援)→ 变回原色继续走,三脚 18/20/22 N·s 全部救回,零摔倒。由 record_video.py 离屏渲染录制,可复现。

Unitree Go2 四足机器人运动控制项目(MuJoCo 仿真,全程在一台 MacBook Pro 的 CPU 上完成)。 从零实现了三种控制范式,用同一套 72 试验推力恢复测试套件正面对比,最终融合为双脑混合控制器:

控制器 总恢复率 行走速度(指令 +0.5 m/s)
Convex MPC(MIT Cheetah 风格) 40% (29/72) +0.42~0.50 m/s
RL 行为克隆(MPC 步态蒸馏,bc_init) 60% (43/72) -0.06 m/s
RL 温柔精调(11.8M 甜点快照) 51% (37/72) +0.14 m/s
RL 域随机化精调(DR 链 13.76M 甜点) 35% (25/72) +0.17 m/s(项目最快)
Orthrus 混合(MPC 行走 + RL 救援) 94% (68/72) ~+0.3 m/s

推力 = 0.1s 脉冲冲量,10/20/30 N·s ≈ 轻推 / 中踢 / 重踹(8 方向 × 3 档 × trot/walk 两工况)。 混合控制器在每一个格子都不输给两个"父母"——walk@20 N·s 从 MPC 的 0% 提到 100%。

为什么叫 Orthrus

Orthrus(俄耳托斯)是希腊神话中的双头犬。这个项目的最终形态正是如此: MPC 是理性脑——单刚体模型 + 凸优化 + 滚动时域,管标称行走的速度跟踪与约束; RL 是反射脑——MPC 步态蒸馏出的神经网络,管被踹后的极限恢复; 仲裁器决定每个瞬间谁在"开车"。救援时机身变色(橙红),接回后恢复原色。

架构

                ┌──────────────── 仲裁器 (500 Hz) ────────────────┐
 速度指令 ──┬──▶│ 速度偏差>0.45 m/s / 倾角>14° / 高度<0.19 → 交棒 RL │
            │    │ 安静 0.3s 且救援≥0.8s → 接回 MPC (重锚步态/钉地点)  │
            │    │ 接回后 0.6s 宽限期防抖; 指令斜坡滤波防阶跃误判      │
            │    └───────────────────────────────────────────────┘
            │              │ 位置目标空间 40ms 交叉淡化, RL 全程影子运行
  ┌─────────▼──────┐  ┌────▼──────────────────┐
  │ MPC 脑          │  │ RL 脑 (bc_init)       │
  │ 100Hz convex QP │  │ 50Hz MLP (128×2)     │
  │ (OSQP, 0.3s 时域)│  │ MPC 步态行为克隆       │
  │ 500Hz τ=-Jᵀ·f   │  │ 12 维关节位置目标      │
  │ Raibert + trot  │  │ 47 维本体感知观察      │
  │ sin³ 摆动 + IK  │  │ (含步态时钟 sin/cos)  │
  └───────┬────────┘  └────┬────────────────┘
          └── τ→q_des 代数转换: q_des = q + (τ + kd·qd)/kp ──┘
                          (位置伺服 kp=50, MPC 全栈一行不改)

目录结构

control/
├── convex_mpc.py          单刚体 convex MPC(12 维状态 QP,OSQP)
├── go2_utils.py           trot 步态调度 / sin³ 摆动轨迹 / Raibert 落脚点 / 腿部 IK
├── run_go2_mpc.py         MPC 主控制器(站立 / 原地 trot / 前进,500Hz 力矩)
├── train_go2_rl.py        RL 训练(MJX + Brax PPO,4 阶段指令/推力课程)
├── collect_demos.py       MPC 示范采集(含 return-to-go,供价值网预训练)
├── bc_bootstrap.py        行为克隆 + 价值网预训练 → 产出 RL 脑
├── eval_go2_rl.py         RL 策略 sim2sim 评估(MuJoCo 验证 + 推力套件入口)
├── run_go2_hybrid.py      ★ 混合控制器(MPC+RL 仲裁)+ 推力套件入口
├── test_push_recovery.py  推力恢复测试套件(72 试验,三方共用同一判定)
├── compare_push.py        两版结果对比
├── show_go2_mpc.py        演示:MPC 行走(交互窗口)
├── show_go2_rl.py         演示:RL 边走边挨踹 / 纯行走(镜头跟随)
├── show_go2_hybrid.py     演示:★ 混合控制器(机身变色 = 换脑)
├── record_video.py        演示视频离屏渲染录制(→ docs/demo.mp4,可复现)
├── run_gentle_finetune.sh RL 精调链(采集 → BC → 三阶段 PPO)
├── policies/              核心策略 pkl(bc_init = RL 救援脑 60%;rl_walk_sweet_spot = 无DR甜点;
│                         rl_walk_dr_fast = DR 最快步行者 13.76M/+0.17;bc_demos = 示范数据;
│                         archive_20260920/ = 全部历史快照与死产物,本地留档不入库)
├── results/               试验数据(push_recovery_*.json / rl_train_log_*.json / dr_finetune_verdict.json)
├── archive/               调试脚本与已废弃训练链(留档)
├── TODO.md                后续实验方向(接触参数 DR / 部署归一化修复 / 多步侧向恢复 / 真机…)
├── docs/                  技术设计文档(index.html,GitHub Pages 发布)+ 演示视频(demo.mp4)+ 会话历史(claude-history.txt)
└── models/go2/            Go2 模型(vendor 自 mujoco_menagerie 的 unitree_go2,含本项目两个自建场景)

快速开始

# 所有命令在项目根目录执行(Go2 模型已内置 models/go2/,克隆即用)

# ① 看冠军表演:MPC 牵狗走 → 被随机踹 → 变色(橙红)换 RL 脑救场 → 变回原色继续走
.venv/bin/mjpython show_go2_hybrid.py

# ② 复现决赛数据(各 ~15 分钟)
.venv/bin/python run_go2_hybrid.py --push                          # 混合: 94%
.venv/bin/python run_go2_mpc.py                                    # MPC 单独 (行走 16s 测试)
.venv/bin/python eval_go2_rl.py policies/bc_init.pkl --push       # RL 单独: 60%

# ③ 其他演示
.venv/bin/mjpython show_go2_mpc.py        # MPC 行走(最快,0.5 m/s 小跑)
.venv/bin/mjpython show_go2_rl.py         # RL 版(默认 bc_init + 随机踹踢)
.venv/bin/mjpython show_go2_rl.py policies/rl_walk_sweet_spot.pkl --no-kicks  # 无DR精调纯行走
.venv/bin/mjpython show_go2_rl.py policies/rl_walk_dr_fast.pkl --no-kicks    # DR 最快步行者(+0.17 m/s)

# ④ (可选)重新训练 RL 脑:MPC 示范 → BC → 温柔精调,CPU 约 3 小时
bash run_gentle_finetune.sh

结果明细(results/push_recovery_hybrid.json 等)

工况 / 冲量 MPC RL-BC 混合
trot 10 N·s 88% 88% 100%
trot 20 N·s 44% 56% 100%
trot 30 N·s 12% 25% 81%
walk 10 N·s 62% 88% 100%
walk 20 N·s 0% 75% 100%
walk 30 N·s 13% 38% 88%

混合版恢复时间均值 0.66s,与单控制器持平(融合无代价);无扰动对照 2/2 通过(零误报)。

技术要点(都写进了代码注释,防重蹈)

  • BC 引导三要素:步态时钟进观察(sin/cos 相位,否则 MSE 最优解是"相位平均 = 静止")、 示范步态相位与部署时钟锁定、动作钳位到 tanh 可达域 ±1
  • 从零 PPO 发现不了步态:"站着"是近最优解(本机 CPU 40M 步无效); 用自己写的 MPC 当老师蒸馏,一步跨过步态发现难关——学生还在推力恢复上赢了老师
  • 温柔精调三剂药(修上轮"精调毁步态"):entropy 1e-4 / lr 5e-5 / 价值网示范预训练
  • sim2sim 漂移的两面(DR 终局判决):物理参数定值训练越过 ~12M 步后 MuJoCo 迁移性单调退化; 加物理域随机化(摩擦/质量/阻尼/电机)后行走段漂移被关闭(9 个检查点全存活,13.76M 快照 +0.17 m/s 创项目最快)。但推力训练段(s3/s4)18 个检查点在 MuJoCo 仍全部趴地,死法与无 DR 版 一致——缺口在 MJX/MuJoCo 的接触求解器差异(solref/solimp 不在 DR 范围内), 故 RL 救援脑最终仍采用纯 BC 的 bc_init。原始数据:results/dr_finetune_verdict.json
  • 力矩→位置接口:q_des = q + (τ + kd·qd)/kp 让 MPC 力控栈一行不改地驱动位置伺服
  • 仲裁阈值全部高于 MPC 标称瞬态(行走俯仰 512° → 触发线 14°), 救援退出判据用"脱离危机"而非"完美姿态"(bc_init 标称俯仰即有 512°)

已知局限与下一步

  • 混合版行走 ~0.3 m/s(MPC 单独 0.5):go2_mjx 足端半径较小(0.0175 vs 0.022),步态参数待适配
  • 30 N·s 纯侧向(±90°)4 个失败:捕获点超出工作空间,突破需多步恢复规划
  • DR 终局判决:行走段 sim2sim 漂移已关闭,但推力训练策略的转移死亡未解(接触求解器层缺口)—— 下一轮方向:solref/solimp 进 DR、部署侧接触适配、或推力训练加 MuJoCo 快照准入门槛
  • 部署管线两处已知失配(实测可容忍,留档未修):策略频率训练 125 Hz vs 部署 50 Hz;部署端观察未做运行统计归一化
  • 状态直接用仿真真值,无 IMU 噪声模型与状态估计器
  • 技能仅有运动控制:挥手/作揖等技能需另训(MPC+IK 脚本化或 RL 技能配方)

许可

  • 本项目代码与文档:MIT License(见 LICENSE)
  • models/go2/:mujoco_menagerie 的 unitree_go2 模型,版权归 Unitree Robotics, 遵循其原始许可(见 models/go2/LICENSE),MIT 不覆盖该目录

模型:Unitree Go2(mujoco_menagerie)· 仿真:MuJoCo 3.13 · 训练:JAX 0.9.2 + Brax 0.14 + MJX

About

四足机器人 Go2 全栈控制:Convex MPC · RL(BC/PPO/域随机化)· 混合仲裁,同一套 72 试验推力协议下恢复率 94% —— 全程 CPU 训练,附与代码逐项一致的数学设计文档

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages