Orthrus · Technical Design Document

四足机器人 Go2 的全栈控制:动力学模型、数学控制器设计与验证

浮基动力学 → 单刚体化简 → Convex MPC 的二次规划构建 → RL 的 MDP 形式化与域随机化 → MPC+RL 混合仲裁的状态机 —— 以及把它们全部置于同一套推力恢复协议下的量化对比。

Unitree Go2(MJCF,常数程序化提取) MuJoCo 3.13 · MJX · Brax 修订 2026-09-20 github.com/weiwei-gu/Orthrus
94%混合控制器推力恢复率
68/72决赛通过试验数
0.66 s平均恢复时间
0GPU(全程 CPU)

0系统总览与严格工作流

本项目的核心方法论是一条纪律:每个控制器组件都必须先有形式化定义、再有一个 量化验收协议,协议通过之前不进入下一个组件。没有度量就没有组件。

0.1 严格工作流

┌──────────────────────────────────────────────────────────────────────┐ │ W1 模型审计 从 MJCF 程序化提取全部物理常数(§1.4 表 1), │ │ 常数表与控制器实现共享同一来源,禁止手抄 │ │ W2 形式化定义 先写数学(状态/动力学/约束/接口),后写代码 │ │ W3 验收协议 每个组件绑定一个可执行判据(下表),不通过不合并 │ │ W4 基线先行 任何改动先有基线数字,单变量迭代,A/B 有记录 │ │ W5 sim2sim 双引擎 MJX 训练 ↔ MuJoCo 部署是两级独立的物理引擎, │ │ 迁移性以 MuJoCo 实测为准,训练侧指标只做参考 │ │ W6 快照边界映射 训练链全程留快照,在部署引擎上逐点测绘迁移曲线 │ │ W7 负结果归档 被证伪的方案全部留档(§5.4),防止重蹈 │ └──────────────────────────────────────────────────────────────────────┘
组件工件(代码)验收判据实测结果
MPC 全栈convex_mpc.py + run_go2_mpc.py16 s 剧本:站立 4 s 内 roll/pitch 误差 < 0.2°,trot 4 s 稳定,0.5 m/s 前进 8 s 不摔通过;速度跟踪 100%
推力套件test_push_recovery.py无推力对照组 100% 通过(防误报)三方均通过
RL 环境train_go2_rl.py--smoke 368k 步管线验证:奖励上升、obs 结构 (47,) 与部署端逐维一致通过
BC 初始化collect_demos.py + bc_bootstrap.pyMSE 收敛 + MuJoCo sim2sim 复现步态极限环MSE 0.00042,步态复现
混合仲裁run_go2_hybrid.py--no-push 对照:全程 0 次误交棒;有推力时恰在推力时刻交棒通过(1 次交棒恰在推力时刻)
决赛统一套件入口72 试验全表 + 对照组§5.2

0.2 控制架构总览

┌────────────── 仲裁器(§4, 500 Hz)──────────────┐ 速度指令 ──────────┤ MPC 模式(常态) RL 模式(危机) │ │ ┌──────────────────┐ ┌────────────────┐ │ │ │ 100 Hz Convex MPC │ │ 50 Hz PPO 策略 │ │ │ │ 单刚体 QP (§2) │ │ MLP π(a|o) (§3) │ │ │ │ 足端接触力 f_i │ │ 关节位置目标 │ │ │ └────────┬─────────┘ └───────┬────────┘ │ │ 500 Hz 低层 (§2.7) │ 40 ms 交叉淡化 │ │ τ = −Jᵀf + PD + 重力/科氏前馈 │ │ │ τ→位置代数转换 (§4.1) ────────────┤ │ └──────────────────────────────────┬─────────────┘ ▼ 12 × 位置伺服 τ = k_p(q*−q) − k_d·q̇ (k_p=50, k_d=0.5, §1.4)

三种控制器(MPC、RL、混合)输出统一到同一执行器接口,因此可以被同一套推力协议(§5)逐格对表。

视频 1 · 混合控制器演示实录(26 s,record_video.py 离屏渲染,剧本可复现; 模型 Unitree Go2,mujoco_menagerie)。 机身橙红 = 仲裁器交棒 RL 救援(§4),原色 = MPC 行驶;三脚 18/20/22 N·s 全部救回,零摔倒,共 6 次换脑决策:

1动力学模型构建

同一台机器人需要三个层次的模型:全量浮基动力学(仿真真值与低层前馈)、 单刚体(SRB)化简(MPC 的决策模型)、执行器与接触模型(两条栈共用的底层约定)。

1.1 全量浮基动力学(仿真真值)

广义坐标 \(q \in \mathbb{R}^{19}\)(自由基 7 + 关节 12),广义速度 \(v \in \mathbb{R}^{18}\), 关节力矩 \(\tau \in \mathbb{R}^{12}\)。含接触的运动方程:

$$M(q)\dot{v} + C(q,v)\,v + g(q) = S^\top \tau + \sum_{i \in \mathcal{C}(q)} J_i(q)^\top \lambda_i$$

其中 \(\mathcal{C}\) 为当前接触集(足端球与地面),\(J_i\) 是接触点雅可比,\(\lambda_i\) 接触冲量, \(S \in \mathbb{R}^{12 \times 18}\) 关节选择矩阵。MuJoCo 以半隐式欧拉(\(q_{t+h} = q_t + h\,v_{t+h}\))积分, 接触为软约束(solimp/solref 参数化的弹簧-阻尼近似刚性)。MJX 是同一模型在 XLA 上的 逐元素重实现——两者共享 MJCF,但接触求解的实现路径不同,这正是本项目把 MuJoCo 实测 作为迁移判据的原因(工作流 W5)。

1.2 SRB 化简(MPC 的决策模型)

convex MPC 把机器人压缩为单刚体,决策状态取 \(x = [\,\theta,\; p,\; \omega,\; v\,]^\top \in \mathbb{R}^{12}\): \(\theta\) 为机身 ZYX 欧拉角(world),\(p\) 质心位置(world),\(\omega\) 角速度(body),\(v\) 质心速度(world)。 化简假设与实际影响如实列出:

假设内容Go2 上的真实误差
A1 复合惯量冻结惯量取 home 姿态下全机复合惯量,视为常数腿占总质量 55%(8.28/15.21 kg),摆腿时惯量时变——SRB 对 Go2 是粗近似
A2 忽略陀螺项\(\omega \times I\omega\) 不进角动力学小角速度下二阶小量
A3 点接触每足接触简化为足端球一点 3 维力足端球半径仅 0.022 m,合理

A1 的误差部分被低层补偿:500 Hz 内层使用全量模型的重力+科氏前馈 (MuJoCo qfrc_bias,逐关节精确),SRB 只负责净力/净力矩的分配(§2.7)。 连续时间 SRB 动力学:

$$\dot\theta = R_z(\psi)\,\omega, \qquad \dot p = v, \qquad \dot\omega = I_w^{-1} \sum_{i \in \text{stance}} r_i \times f_i, \qquad \dot v = g + \frac{1}{m}\sum_{i \in \text{stance}} f_i$$

其中 \(r_i = p_i^{\text{foot}} - p\) 是足到质心矢径,\(I_w = R_z(\psi)\, I\, R_z(\psi)^\top\), \(f_i \in \mathbb{R}^3\) 为 world 系足端接触力(决策变量)。旋转部分做 yaw 线性化:\(R_z\) 取当前偏航角处的常值旋转——这是"凸化"的关键, 动力学对 \(f_i\) 保持严格线性,QP 因此成立。

1.3 离散化与堆叠预测

结点间隔 \(h = 0.02\) s,前向欧拉离散化(实现使用显式欧拉而非矩阵指数, 一阶精度换取 15 步预测的构造简单性):

$$x_{k+1} = A\,x_k + B_k\,u_k + c, \qquad A = \begin{bmatrix} I_3 & 0 & h\,R_z(\psi) & 0 \\ 0 & I_3 & 0 & h\,I_3 \\ 0 & 0 & I_3 & 0 \\ 0 & 0 & 0 & I_3 \end{bmatrix}, \quad c = h\,[\,0,\,0,\,0,\,g\,]^\top$$ $$B_k\text{ 的第 } i \text{ 足块:}\quad \begin{bmatrix} 0 \\ 0 \\ h\,I_w^{-1}\,\mathrm{skew}(r_i) \\ \tfrac{h}{m} I_3 \end{bmatrix}, \qquad u_k = [f_1^\top, f_2^\top, f_3^\top, f_4^\top]^\top \in \mathbb{R}^{12}$$

堆叠 \(N = 15\) 步预测(行块 \(k\) 对应状态 \(x_{k+1}\)):

$$X = S\,x_0 + G\,U + d, \qquad S_k = A^{k+1}, \quad G_{k,j} = A^{\,k-j}\,B_j \;\; (j \le k), \quad d_k = \sum_{j \le k} A^{\,k-j}\, c$$
实现注记(负结果入档):堆叠矩阵的索引曾经写成 Apow[k-1-j], 在 \(k=0\) 时 Python 负索引取到 \(A^{-1}\to A^{N}\)(列表环绕),静态站立时垂直力只达体重的 40% 而无任何报错。教训:预测矩阵必须用从 \(I\) 起的显式幂表 Apow=[I, A, A², …], 并用"站立时 \(\sum f_z = mg\)"做单元断言。

1.4 平台常数表(程序化提取)

下表全部常数由脚本从 MJCF 与 MuJoCo 模型运行时提取(非手抄),是三条控制栈的 唯一事实来源:

常数值来源/用途
全机质量 \(m\)15.206 kg复合惯量计算(home 姿态)
躯干质量6.921 kg(腿占 55%)SRB 假设 A1 的量化背景
复合惯量对角 \(I\)(0.2554, 0.4826, 0.4513) kg·m²关于总质心,world 系,home 姿态
广义坐标\(n_q = 19\), \(n_v = 18\), \(n_u = 12\)浮基 + 每腿 3 关节(外展/大腿/小腿)×4
腿几何大腿 = 小腿 = 0.213 m;大腿体原点 y = ±0.142 m;足端球半径 0.022 mIK 与落脚点参考(§2.5/2.6)
home 关节角\((0,\, 0.9,\, -1.8)\) × 4,站立高度 0.27 mkeyframe 0;RL 默认姿态同源
执行器(MPC 栈)直力矩,限幅 ±23.7 N·mgo2_mpc_scene.xml
执行器(RL/混合栈)位置伺服 \(k_p = 50\), \(k_d = 0.5\)(rad 域)scene_mjx.xml / hybrid_scene.xml
接触摩擦足端滑动摩擦 0.8,地面 1.0;QP 取 \(\mu = 0.4\)(§2.2 余量)geom_friction
仿真步长2 ms(MuJoCo 与 MJX 同);MPC 重解 10 ms;RL 训练策略周期 8 ms、部署 20 ms(§3.7)opt.timestep
接触硬度(MPC/混合栈)足端 solimp 覆写 (0.9, 0.95, 0.001),近刚性;RL 栈保持 menagerie 默认软接触两栈有意不同,见 §3.7 注记

2Convex MPC 的数学设计

决策模型为 §1.2 的 SRB。整个控制器 = 一个滚动时域 QP(100 Hz)+ 步态机与摆动轨迹生成 + Raibert 落脚点 + 数值 IK + 500 Hz 力矩内层。

2.1 QP 形式化

决策变量 \(U = [u_0; \dots; u_{N-1}] \in \mathbb{R}^{12N}\)(\(N = 15\) 个结点上四足 × 3 维力, 时域 0.3 s)。目标:

$$\min_U \;\; (X - X^{\text{ref}})^\top \bar{Q} (X - X^{\text{ref}}) \; + \; U^\top \bar{R}\, U \qquad \text{s.t.} \quad X = S x_0 + G U + d, \;\; \text{接触约束(下)}$$

展开为 OSQP 标准形 \(\min \tfrac12 U^\top P U + q^\top U\): \(P = 2(G^\top \bar Q G + \bar R)\),\(q = 2\,G^\top \bar Q\,(S x_0 + d - X^{\text{ref}})\)。 权重(逐结点状态对角阵,末结点放大 3 倍近似终端代价):

状态分量权重(rpy, p, ω, v 逐项)设计含义
姿态 \(Q_{\theta}\)(60, 120, 15)俯仰权重最高——前向行走的主要不稳定模式
位置 \(Q_p\)(12, 12, 100)水平 12 是推力恢复实测调优值(原始 2 太弱,位移后不回拉);高度 100
角速度 \(Q_\omega\)(2, 2, 0.5)阻尼
线速度 \(Q_v\)(6, 6, 8)速度跟踪
力正则 \(\bar R\)\(2\times10^{-5} I\)最小范数倾向,保证 QP 严格凸

接触约束(对每足 \(i\)、每结点 \(k\);摆动足 \(f_{i,k} = 0\) 为等式约束):

$$|f_x| \le \mu f_z, \quad |f_y| \le \mu f_z, \quad 0 \le f_z \le f_{\max}, \qquad \mu = 0.4,\;\; f_{\max} = 130\,\text{N}$$

摩擦约束采用外接金字塔线性化(4 面体近似二阶锥,角点处可超真实锥 \(\sqrt2\) 倍), \(\mu = 0.4\) 对仿真真实摩擦 0.8~1.0 留出的余量同时吸收线性化误差与实现误差 (实测:贴真实摩擦边缘取 \(\mu\) 时,支撑足在姿态修正中滑出 14 cm)。 求解器 OSQP(eps_abs/rel 1e-3,max_iter 2000,adaptive_rho,不 polish); 求解失败时回退为支撑足平摊体重的静态分配。每 10 ms 重解,取首结点力 \(u_0\) 执行。

2.2 参考轨迹

位置参考锚点 \(p_{\text{cmd}}\) 按指令速度积分推进,指令变化瞬间重锚到当前质心 (接受阶跃、不做长时回拉);第 \(k\) 结点参考:

$$x_k^{\text{ref}} = [\,0,\, 0,\, \psi_{\text{cmd}};\;\; p_{\text{cmd}} + v_{\text{cmd}}\,t_k,\; z_{\text{des}};\;\; 0;\;\; v_{\text{cmd}}\,]$$

其中 \(z_{\text{des}} = 0.27\) m 与 home 高度一致,\(\psi_{\text{cmd}}\) 锁定初始偏航 (本项目不测试转向机动)。步态预测矩阵 stance_pred[k][i] 由 §2.3 的相位函数 向前展开生成,喂给 QP 的约束切换。

2.3 步态调度(对角小跑)

相位 \(\phi \in [0,1)\) 以周期 \(T = 0.6\) s 推进(\(\phi \gets (\phi + h/T) \bmod 1\))。 对角组 \(\mathcal{A} = \{\text{FL}, \text{RR}\}\)、\(\mathcal{B} = \{\text{FR}, \text{RL}\}\), 摆动占比 \(s_f = 0.4\),占空比 0.6:

$$\text{swing}(\mathcal{A}) \Leftrightarrow \phi \in [0,\, s_f), \qquad \text{swing}(\mathcal{B}) \Leftrightarrow \phi \in [0.5,\, 0.5 + s_f)$$

摆动进度 \(s \in [0,1) = \phi / s_f\)(组内归一)。两个设计不变量: (i) \(s_f < 0.5\) 保证存在四足全支撑重叠窗(\([0.4,0.5) \cup [0.9,1)\), 每窗 0.06 s)——纯 50% 占空比时任意时刻仅两足着地,绕对角轴的力矩不可控; (ii) 摆动窗必须设上界——无上界时进度外插 \(s > 1\),足端目标被规划进地面以下。

原地模式的自适应恢复时序(迟滞状态机):倾角 > 18° 进入恢复模式, < 10° 退出;恢复模式且仅原地时:有足在摆动则 1.8× 加速落地,已停住(\(\|v\| < 0.5\)) 且仍大倾角则冻结步态保持四足。行走中冻结步态被数据证伪并禁用(§5.4)。

2.4 摆动轨迹

起摆点 \(p_0\) → 落点 \(p_1\),水平面用五次多项式平滑步 \(\sigma(s) = 6s^5 - 15s^4 + 10s^3\)(\(\sigma'\)、\(\sigma''\) 在端点为 0); 高度用 \(\sin^3\) 拱线并带提前触地停等:

$$p_{\text{foot}}(s) = p_0 + \sigma(s)\,(p_1 - p_0), \qquad z(s) = (1-\sigma)\,p_{0z} + \sigma\,p_{1z} + h\,\sin^3\!\big(\pi \min(s/0.9,\, 1)\big)$$

高度 \(h = 0.05\) m。剖面选择的依据是端点导数性质:摆动腿对机身的反作用力 由 z 剖面端点加速度决定(SRB 未建模此项)—— \(\sin(\pi s)\) 端点速度非零(触地垂直速度达峰 1.26 m/s,等于命令摆动足砸向地面); \(\sin^2\) 端点加速度达 ~4g(把机身周期性踹沉);\(\sin^3\) 的端点速度与加速度同时为零 (\(\sin^3 x \sim x^3\) 在 0 处二阶平坦)。\(s/0.9\) 的截断使足端在 \(s = 0.9\) 即到地面等待, 足端因重力超前于剖面时目标已在地面等它。

2.5 落脚点:Raibert 启发式 + 捕获修正

标称落点(Raibert 1986):

$$p^{\text{land}} = p_{\text{hip}} + \tfrac{T_{\text{st}}}{2}\, v_{\text{cmd}} + k\,(v - v_{\text{cmd}}), \qquad T_{\text{st}} = T(1 - s_f) = 0.36\,\text{s},\;\; k = 0.18$$

\(p_{\text{hip}}\) 取大腿体原点(y = ±0.142 m,腿实际悬挂处)而非髋关节锚点 (y = ±0.0465 m)——用错参考点会把落点内收 9.5 cm,四腿在机身下交叉导致侧翻。 \(k\) 从 0.05 提到 0.18 是本项目 MPC 从 18% 到 40% 恢复率的主要单项贡献: 被推后主要靠"迈步接住"(capture stepping)而非力微调恢复(Raibert 1986 的经典结论)。

仅原地模式且大倾角时叠加倾角捕获项(向倾倒方向跨步):

$$\Delta x = \mathrm{clip}\big(0.20\,(\theta_p + 0.15\,\omega_y),\, \pm 0.15\big), \quad \Delta y = \mathrm{clip}\big(-0.30\,(\theta_r + 0.15\,\omega_x),\, \pm 0.15\big)$$

侧向落点半宽夹在 \([0.10, 0.24]\) m(工作空间边界),总落点偏移限幅 0.28 m—— 无夹幅时原始捕获位移可达 0.5 m,超出工作空间后 IK 钳位到关节极限,伸直的腿撑地 反而加速倾倒。行走中的捕获步被数据证伪并默认关闭(§5.4)。

2.6 腿部逆运动学(阻尼最小二乘)

每腿 3 连杆解析 IK 存在但本实现选择与模型解耦的数值 DLS 解 (独立 MjData 做正运动学,不污染仿真状态):

$$q^{(j+1)} = \mathrm{clip}\!\big(q^{(j)} + J^\top (J J^\top + \lambda^2 I_3)^{-1} e,\;\; q_{\min},\, q_{\max}\big), \qquad e = p^{\text{target}} - p^{\text{foot}}(q^{(j)}),\;\; \lambda = 0.01$$

\(J \in \mathbb{R}^{3\times3}\) 为足端对腿 3 关节的雅可比(mj_jacGeom), 支撑腿迭代 3 次、摆动腿 4 次,收敛阈 1e-5 m,全程关节限位内夹持。

2.7 500 Hz 力矩内层

支撑腿(虚功原理:足端外力 \(f\) 与关节力矩 \(\tau\) 对任意虚位移做功相等 \(\Rightarrow \tau = -J^\top f\),负号因 \(f\) 是足端受到的外力):

$$\tau_{\text{stance}} = -J^\top f^{\text{MPC}} + k_p^{\text{st}} (q_{\text{ref}} - q) - k_d^{\text{st}}\, \dot q + \tau_{\text{bias}}$$

其中 \(q_{\text{ref}}\) 为"钉地"构型(IK 解向触地时刻记录的钉地点,随机身运动连续更新), 弱 PD(\(k_p^{\text{st}}=30\), \(k_d^{\text{st}}=1.5\))锚定该构型; \(\tau_{\text{bias}}\) = MuJoCo qfrc_bias 的腿块——全量模型的重力+科氏项, 逐关节精确,这就是 §1.2 假设 A1 误差的低层补偿。

摆动腿:

$$\tau_{\text{swing}} = k_p^{\text{sw}} (q_{\text{ref}} - q) + k_d^{\text{sw}} (\dot q_{\text{ref}} - \dot q) + \tau_{\text{bias}}, \qquad k_p^{\text{sw}} = 80,\; k_d^{\text{sw}} = 4$$

近地阻尼:足端进入地面 3 cm 内时附加 \(-J^\top K_{\text{cart}}\, v_{\text{foot}}\)(\(K_{\text{cart}} = 40\) N·s/m), 直接耗散足端垂直动量,打断"足端超前剖面撞地→弹飞机身"的冲击环。 惯性前馈 \(M\ddot q_{\text{ref}}\) 经 A/B 测试无收益,置 0(§5.4)。 全部力矩裁剪至 ±23.7 N·m 执行器限幅。

3强化学习控制器的形式化

RL 栈把同一个 MJCF 交给 MJX 做批量物理,控制器是 MLP 策略 \(\pi_\theta(a \mid o)\),PPO 训练。BC(行为克隆)提供初始化, 域随机化提供迁移性。

3.1 MDP 形式化

观察 \(o \in \mathbb{R}^{47}\)(全本体感知,无全局真值,无视觉):

块维定义
步态时钟2\([\sin 2\pi\phi_c,\; \cos 2\pi\phi_c]\),\(\phi_c\) 以 \(T_c = 0.6\) s 推进(与 MPC 步态周期同源),随机初相
重力方向3\(R^\top [0,0,1]\)(机体系上方向量;直立时 z ≈ 1)
速度指令3\([c_x, c_y, c_\omega]\),每回合采样一次
机身角速度3\(\omega\)(body 系)
关节角偏差12\(q - q_{\text{def}}\)(默认姿态 (0, 0.9, −1.8)×4)
关节角速度12\(\dot q\)
上一动作12\(a_{t-1}\)(一阶动力学记忆)
设计决定:观察中没有基座线速度。这是有意的本体感知极简主义 (真机上没有干净的速度传感器),代价是速度指令跟踪天然偏弱(实测 +0.07 m/s vs 指令 +0.5, §5.2),收益是不依赖速度估计器。混合架构(§4)正是用 MPC 补速度跟踪的答案。

动作 \(a \in \mathbb{R}^{12}\),部署控制律(与训练环境同式):

$$q^* = q_{\text{def}} + 0.4 \cdot \mathrm{clip}(a, \pm 1.5), \qquad \tau = k_p (q^* - q) - k_d \dot q, \;\; k_p = 50,\, k_d = 0.5$$

奖励(全部显式项,逐项与代码一致):

$$r_t = r_{\text{vel}} + r_{\text{ang}} + r_z + r_{\text{att}} + 0.2 + c_{\text{act}} + c_{\dot q} + c_{\text{dev}} - 5\,\mathbb{1}[\text{done}]$$ $$r_{\text{vel}} = 2.5\,e^{-\frac{(v_x^b - c_x)^2}{0.12}} + 0.5\,e^{-\frac{(v_y^b - c_y)^2}{0.12}} + 0.5\,\mathrm{clip}(1 - |v_x^b - c_x|, 0, 1)$$ $$r_{\text{ang}} = 0.25\,e^{-\frac{(\omega_z - c_\omega)^2}{0.25}}, \quad r_z = 0.35\,e^{-100 (z - 0.28)^2}, \quad r_{\text{att}} = 0.5\,e^{-10 (g_x^2 + g_y^2)}$$ $$c_{\text{act}} = -0.01 \textstyle\sum_j (a_j - a_{j,t-1})^2, \quad c_{\dot q} = -2\times10^{-4} \textstyle\sum_j \dot q_j^2, \quad c_{\text{dev}} = -0.02 \textstyle\sum_j (q_j - q_{\text{def},j})^2$$

\(v^b = R^\top v^{\text{world}}\)(机体系线速度,由四元数显式展开计算)。 速度项用"高斯核 + 线性远场项"双结构:高斯核提供近目标稠密梯度,线性项保证 远处仍有梯度。存活奖励 0.2/步。终止(done):

$$z < 0.16 \;\;\lor\;\; z > 0.45 \;\;\lor\;\; g_z < 0.5 \;(\text{倾斜} > 60°)$$

回合随机化(训练分布,reset 抽样):初始位置 xy ±0.1 m、z +[0.01, 0.05] m、 姿态四元数 σ0.02、关节 σ0.15 rad;初速基座 σ0.2 m/s、关节 σ0.3 rad/s; 指令 \(c_x \sim U(-0.3, 1.0)\)、\(c_y \sim U(-0.3, 0.3)\)、\(c_\omega \sim U(-0.8, 0.8)\); 观察加性噪声 σ0.02; 速度冲量推力:每 \(U[100, 250]\) 步对基座 xy 加 \(\Delta v \sim U[-v_p, v_p]^2\) (课程决定 \(v_p\),与 §5 协议的 N·s 同标度:\(m \Delta v = J\))。

3.2 PPO 训练目标与超参

标准 PPO 截断代理目标 + 价值回归 + 熵正则(Brax v2 实现):

$$L(\theta) = \mathbb{E}\big[\min\big(\rho_t A_t,\; \mathrm{clip}(\rho_t, 1\pm\epsilon) A_t\big)\big] - c_v \big(V_\theta(o_t) - \hat V_t\big)^2 + c_e\, \mathbb{H}[\pi_\theta(\cdot \mid o_t)]$$

\(\rho_t = \pi_\theta / \pi_{\text{old}}\),GAE(λ=0.95) 计算优势并归一化。 网络:策略 MLP (128, 128) tanh,价值 MLP (256, 256);观察用运行统计(Welford) 标准化(\(o \gets (o - \mu) / \sigma\),在训练前向内部完成)。超参与课程:

参数从头训练BC 后温柔精调
并行环境 / 回合长度512 / 1000 步同
unroll / minibatch / 每批更新20 / 32 / 4(每次更新的数据量 ×4 以降梯度噪声)
折扣 γ / GAE λ / 截断 ε0.97 / 0.95 / 0.3
学习率2e-45e-5
熵代价2e-31e-4
物理域随机化开(每回合重抽样,§3.4)

课程(STAGES):s1 12M 步(指令域 \(c_x \in [0.4, 1.0]\) 逼出行走,无推力)→ s2 15M 步(全指令域,无推力)→ s3 8M 步(推力 \(\Delta v \le 0.9\) m/s,间隔 5~10 s)→ s4 8M 步(推力 \(\Delta v \le 1.8\) m/s,间隔 3~7 s)。BC 链跳过 s1 直接从 bc_init 进 s2。 推力课程的依据是实测负结果:一上来就用目标难度会让策略陷进"蹲下保命"局部最优 (速度奖励低于站立基线)。

3.3 BC 初始化(蒸馏 MPC)

示范:MPC 控制器在 MuJoCo 中跑 12 回合,采 13,190 个 \((o, a)\) 对 (采集时 MPC 步态相位锁定到部署时钟,保证相位确定对应)。 BC 目标是分布众数的 MSE(确定性复现):

$$\mathcal{L}_{\text{BC}}(\theta) = \big\| \mathrm{mode}(\pi_\theta(o)) - a_{\text{demo}} \big\|^2, \qquad \text{Adam } 10^{-3},\; \text{batch } 256,\; 150 \text{ epochs}$$

收敛 MSE 0.00042(动作尺度 0.4 rad 下 ~0.01 rad 级)。 相位时钟必要性(形式化):步态目标映射 \(a(o, \varphi)\) 是未观察相位 \(\varphi\) 的周期函数;无时钟时,MSE 最优预测器是条件期望 \(a^*(o) = \mathbb{E}[a \mid o] = \int a(o, \varphi)\, dP(\varphi \mid o) \mathrm{d}\varphi\) ——对相位取平均把周期解坍缩为相位均值姿态(≈静止)。 观察加入 \((\sin 2\pi\varphi, \cos 2\pi\varphi)\) 后映射对 \(\varphi\) 可逆,极限环可复现。

价值网预训练:对示范回报(return-to-go \(R_t^{\to} = \sum_{t' \ge t} \gamma^{t'-t} r_{t'}\)) 做 MSE 监督(Adam 1e-3,100 epochs)。动机:随机初始化的价值网让 PPO 早期的优势 估计系统性错误,第一步大更新就摧毁 BC 精度——实测首轮精调(熵 2e-3、lr 2e-4、无价值预训) 即把克隆步态完全打散。产出 \((\text{统计}, \pi, V)\) 三元组直接作为 PPO restore 起点。

3.4 物理域随机化(关闭 sim2sim 漂移的关键)

每回合 reset 抽样一次缩放系数,step 内以 sys.replace 重建 brax 物理系统 (System 是 flax PyTreeNode,纯函数替换):

物理量分布(相对标称缩放)作用面
滑动摩擦\(\times\, U[0.6, 1.4]\)(标量)geom_friction[:, 0]
连杆质量\(\times\, U[0.85, 1.15]\)(逐 body 独立)body_mass
关节阻尼\(\times\, U[0.7, 1.3]\)(逐 DoF 独立)dof_damping
电机强度\(\times\, U[0.7, 1.3]\)(标量,\(k_p, k_d\) 同乘)actuator gainprm/biasprm

连同 §3.1 的初始状态/观察噪声/冲量推力三类随机化,训练分布覆盖 "物理参数不定"这一 sim2real 的主要现实。机理:物理定值时策略可以过拟合 单一引擎的接触细节(本项目实测:无 DR 精调越过 11.8M 步甜点后 MuJoCo 迁移性单调退化,18M 最终策略 4 s 翻倒,§5.3);物理随机后过拟合不再有收益, 策略被迫收敛到对参数族鲁棒的行为。

3.5 实现注记(如实记录)

4Orthrus:MPC+RL 混合仲裁的数学构建

三方各持一角(§5.2):MPC 强在速度跟踪,RL-BC 强在抗扰。 混合 = MPC 常态驾驶 + RL 危机接管 + 仲裁器决定每个瞬间谁在开车。

4.1 接口统一:力矩 → 位置目标的代数转换

两脑必须驱动同一组位置伺服(\(\tau = k_p(q^* - q) - k_d \dot q\))。MPC 输出的是力矩, 令伺服输出等于 MPC 力矩,解出位置目标:

$$k_p\,(q^* - q) - k_d \dot q = \tau_{\text{MPC}} \;\;\Longrightarrow\;\; q^* = q + \frac{\tau_{\text{MPC}} + k_d\,\dot q}{k_p}, \qquad k_p = 50,\; k_d = 0.5$$

一行公式把力控栈嵌入位置伺服,MPC 全栈零改动。代价:位置伺服的 ctrlrange 是关节 位置域,MPC 原有的力矩限幅(±23.7)在该域被误用——实现中禁用 MPC 侧力矩裁剪, 统一在位置域夹持。

4.2 仲裁状态机

状态集 \(\{\text{MPC}, \text{RL}\}\),逐 2 ms 步评估。记 \(\mathrm{tilt} = \max(|\theta_r|, |\theta_p|)\), \(\mathrm{dv} = \|v_{xy} - \tilde v_{\text{cmd}}\|_2\) (\(\tilde v_{\text{cmd}}\) 为斜坡滤波后的指令,见下),\(z\) 为质心高度。

交棒(MPC → RL):

$$z < 0.17 \;\;\lor\;\; \Big( t - t_{\text{hb}} > 0.6\,\text{s} \;\land\; \big(\mathrm{dv} > 0.45 \;\lor\; \mathrm{tilt} > 14° \;\lor\; z < 0.19 \big) \Big)$$

接回(RL → MPC)(救援时长 \(t_r\)):

$$t_r \ge 0.8\,\text{s} \;\land\; \Big( \underbrace{\big(\mathrm{tilt} < 15° \,\land\, z > 0.20 \,\land\, \|v_{xy}\| < 0.40\big)_{\text{持续} \ge 0.3\,\text{s}}}_{\text{脱离危机}} \;\lor\; \underbrace{(t_r > 2.5\,\text{s} \,\land\, z > 0.19)}_{\text{超时强制}} \Big)$$

指令斜坡滤波(仅用于 dv 的参考,不改变 MPC 实际指令):每步沿指令误差方向 推进至多 \(0.8 \times 0.002\) m/s:

$$\tilde v \gets \tilde v + \min\Big(1,\, \frac{0.8\,h}{\|v_{\text{cmd}} - \tilde v\|}\Big)\,(v_{\text{cmd}} - \tilde v)$$

存在性证明式的实测教训决定了每条阈值:

4.3 交叉淡化与接回重锚

输出为两脑位置目标的凸组合,混合系数 \(\alpha\) 每步(2 ms)向目标推进 0.05 (全过渡 40 ms):

$$\alpha \gets \mathrm{clip}(\alpha^{*} - \alpha, \pm 0.05) + \alpha, \qquad u = \alpha\, q^*_{\text{MPC}} + (1 - \alpha)\, q^*_{\text{RL}}$$

RL 策略全程影子运行(50 Hz obs-action 链保持连续),交棒时无观察跳变。 接回时重锚 MPC 内部状态:步态相位清零、钉地点重新触地检测、位置参考锚到当前质心 (不往回拽),恢复模式标志复位。

5验证协议与实测结果

5.1 推力恢复协议(三方共用的同一把尺子)

每次试验:keyframe 复位并抬高基座使足端恰好触地 → 站立 4 s → 进入工况 → 在窗口内随机时刻对基座施加 0.1 s 水平脉冲力 \(\to\) 观察至终点。

参数取值
冲量 \(J = \|f\| \cdot 0.1\text{s}\)\(\{10, 20, 30\}\) N·s ⇒ \(\Delta v = J/m = \{0.66, 1.32, 1.97\}\) m/s
方向8 个(0°~315°,步进 45°)
工况trot(原地小跑;推力窗 5.5~6.5 s,观察至 11 s;种子 {1,2});walk(0.5 m/s 行走;推力窗 10~11 s,观察至 14 s;种子 {3})
总试验数3 冲量 × 8 方向 × (2 + 1) 种子 × 2 工况 = 72
摔倒判定任意时刻 \(z < 0.16\) m
通过判定无摔倒 ∧ 终点 \(z > 0.20\) ∧ \(|\theta_r|, |\theta_p| < 20°\)
恢复时间推力结束后 \(\|v_{xy}\| < 0.15\) 且 \(|\theta_r|, |\theta_p| < 15°\) 持续 0.2 s 的时刻
对照组无推力必须 100% 通过且混合版 0 次交棒(防仲裁误报)

5.2 决赛结果(72 试验恢复率)

工况 / 冲量MPCRL-BCOrthrus 混合
trot 10 N·s88%88%100%
trot 20 N·s44%56%100%
trot 30 N·s12%25%81%
walk 10 N·s62%88%100%
walk 20 N·s0%75%100%
walk 30 N·s13%38%88%
总恢复率40%60%94%(68/72)

读法:逐格支配——混合在每一格都不劣于两个父母,多数格严格更优; 平均恢复时间 0.66 s 与单控制器持平(无代价);对照组零误报。 剩余 4 个失败全部是 30 N·s 纯侧向(±90°):2 m/s 侧向捕获点超出单步工作空间, 是单步捕获架构的物理天花板,由双方父母共同继承(§6)。 速度跟踪:MPC 单独 0.5 m/s 跟踪 100%;混合版 ~0.3 m/s;RL-BC ~0.07 m/s(观察无 线速度的代价,§3.1)。

5.3 sim2sim 漂移与域随机化的判决(实验进行中)

无 DR 精调链(物理定值)在 MuJoCo 上的迁移曲线——训练侧指标全程向好, 部署侧从 11.8M 起单调退化:

训练步数MJX 评估奖励MuJoCo 实测(无 DR)MuJoCo 实测(带 DR)
0(BC 起点)1103✅ 走,净速 −0.06 m/s—
11.8M(无 DR 峰值)1604✅ 走,净速 +0.14 m/s✅ 走,+0.07,姿态有界
3.93M / 5.9M / 9.8M1532(早期峰)健康区(未逐点测)✅ 全部存活:−0.06 / +0.04 / +0.09
13.76M1414⚠️ 走,净速 −0.14 m/s✅ +0.17 m/s(本项目最佳 RL 步行者)
15.73M1103⚠️ 走,净速 −0.20 m/s✅ +0.12 m/s
17.7M(最终)1334❌ 4 s 内翻倒✅ 存活行走,−0.04,姿态有界
s3 推力 0.9 m/s(0→8.85M)950~1080❌ 最终躺平(z=0.079)❌ 9/9 检查点全部趴地(z=0.081)
s4 推力 1.8 m/s(0→8.85M)768❌ 最终躺平❌ 全部检查点含最终趴地(roll 178°)

终局判定(链 15:29→17:39 完成):域随机化的判决是分裂的。

5.4 负结果(全部留档)

尝试结果处置
从零 PPO 40M 步回合长度 2→800 但净位移始终为零("站立"是奖励结构下的近最优解)转向 BC 引导
首轮精调(熵 2e-3,lr 2e-4,无价值预训)克隆步态被 PPO 第一步更新打散温柔配方(1e-4 / 5e-5 / 价值预训)
MPC:0.5 s 更长视野 + 摆动中落点重规划 + 倾角捕获步 + 角速度触发推力测试零收益甚至负收益(walk@10N·s 5/8→0/8)全部回退,仅保留原地模式自适应时序
摆动惯性前馈 \(M\ddot q_{\text{ref}}\)(A/B)无收益置 0
无 DR 精调越过甜点继续训练sim2sim 单调退化(上表)域随机化重训(本节)

6已知局限(全部如实列出)

7复现指南与文件地图

git clone https://github.com/weiwei-gu/Orthrus && cd Orthrus
python3 -m venv .venv && .venv/bin/pip install mujoco "jax==0.9.2" mujoco-mjx brax osqp

# 交互演示(变橙红 = RL 接管救场)
.venv/bin/mjpython show_go2_hybrid.py

# 复现三方决赛(各 ~15 分钟)
.venv/bin/python run_go2_hybrid.py --push                        # 混合: 94%
.venv/bin/python test_push_recovery.py                            # MPC: 40%
.venv/bin/python eval_go2_rl.py policies/bc_init.pkl --push      # RL-BC: 60%

# 重训 RL 脑(含 §3.4 域随机化,约 3 小时 CPU)
bash run_gentle_finetune.sh
文件本文档对应章节作用
convex_mpc.py§1.2–1.3, §2.1SRB 模型、堆叠预测、QP 构建与求解
go2_utils.py§2.3–2.6步态相位机、sin³ 摆动轨迹、Raibert 落脚点、DLS IK
run_go2_mpc.py§2.2, §2.7MPC 全栈(参考轨迹、500 Hz 内层、自适应时序)
train_go2_rl.py§3.1–3.4MJX 环境(obs/奖励/DR)+ PPO 课程训练
collect_demos.py / bc_bootstrap.py§3.3MPC 示范采集 → BC + 价值网预训练
eval_go2_rl.py§3.5, §5.1RL 策略的 MuJoCo sim2sim 评估(行走 + 推力套件)
run_go2_hybrid.py§4混合仲裁器 + 决赛入口
test_push_recovery.py§5.172 试验协议(三方共用的尺子)
results/*.json§5全部试验原始数据,负结果也在
models/go2/§1.4vendor 的 MJCF(场景 ×3 + 完整模型)
record_video.py§0演示视频离屏渲染录制(→ docs/demo.mp4,剧本可复现)
docs/claude-history.txt—7,800 行完整开发会话记录