开源 | Legbot Lab:基于 Isaac Lab 的四足机器人 PPO / MoE-CTS 训练与 Sim2Real 部署

项目名称:Legbot Lab

项目仓库:https://github.com/Robot-Nav/legbot_lab

默认分支:PPO

扩展分支:PPO-CTS-MOE

核心算法:PPO、非对称 Actor-Critic、历史观测、并发教师---学生学习、Mixture of Experts

仿真平台:NVIDIA Isaac Sim / Isaac Lab、MuJoCo

部署方式:TorchScript / ONNX、C++17、CycloneDDS、串口网关

开源许可证:Apache License 2.0

相关论文:Combining Teacher-Student with Representation Learning: A Concurrent Teacher-Student Reinforcement Learning Paradigm for Legged Locomotion

论文地址:https://arxiv.org/abs/2405.10830

https://robogauge.github.io/static/files/arxiv.pdf


1. 项目定位

Legbot Lab 是一套面向自研四足机器人的强化学习运动控制工程。它并不是单独的 PPO 训练脚本,而是把机器人模型、并行仿真、奖励设计、域随机化、策略导出、MuJoCo 复现、C++ 控制器、DDS 通信和实物串口网关串成了一条完整链路。

项目主要解决三个问题。

第一,四足机器人在真实环境中很难准确获得完整状态。基座线速度、地形高度、足端接触力和实际关节力矩在仿真中容易获取,但在实物上往往需要额外传感器或复杂估计器。项目通过非对称 Actor-Critic 和教师---学生结构,使训练阶段可以利用特权信息,部署阶段只依赖 IMU、关节编码器、速度命令和历史观测。

第二,仿真模型与真实机器人存在差异。质量、质心、惯量、地面摩擦、编码器零位、电机响应、控制延迟和通信周期都会影响策略迁移。项目通过域随机化、电机力矩---速度曲线、摩擦模型、动作延迟和 Sim2Sim 检查降低 Sim2Real 风险。

第三,强化学习策略需要进入真实控制系统。项目没有停留在 Python 推理,而是提供 ONNX/TorchScript 导出、C++ 控制器、有限状态机、安全限制、DDS 抽象层和串口协议网关,使同一套高层控制逻辑能够连接 MuJoCo 或真实机器人。


2. 两个分支分别包含什么

2.1 PPO 分支

PPO 是默认分支,重点是完整工程闭环。

其核心内容包括:

  • 基于 Isaac Lab 和 RSL-RL 的速度跟踪 PPO 训练;
  • 10 帧历史观测与非对称 Actor-Critic;
  • 质量、惯量、质心、摩擦、PD 增益、零位偏移和推扰随机化;
  • TorchScript、ONNX 与 deploy.yaml 导出;
  • C++ 有限状态机和 ONNX Runtime 推理;
  • MuJoCo DDS 仿真器;
  • serial_dds_gateway 串口---DDS 网关;
  • 控制器与仿真器、真实机器人共用 DDS 接口。

从工程角度看,这个分支更适合研究"怎样把训练策略可靠地放到真实四足机器人上"。

2.2 PPO-CTS-MOE 分支

该分支在 PPO 基础上加入并发教师---学生学习和专家混合网络,重点是提高仅依赖本体感知时的地形适应能力。

其核心内容包括:

  • 教师环境与学生环境并行采样;
  • 教师编码器使用特权观测;
  • 学生编码器只使用可部署观测;
  • 学生侧使用 8 个专家网络及门控网络;
  • 教师、学生共享 Actor 与 Critic;
  • PPO 损失、潜变量蒸馏损失和专家负载均衡损失联合训练;
  • 导出时仅保留学生编码器和 Actor;
  • 提供 MuJoCo 平地、楼梯、箱体和坡道场景验证。

这个分支更适合研究"如何利用仿真特权信息训练出只依赖本体传感器的实物策略"。

2.3 为什么需要分开说明

两个分支的主要差异如下。

项目 PPO 分支 PPO-CTS-MOE 分支
任务名称 Unitree-Legbot-Velocity RobotLab-Legbot-v0
核心算法 PPO PPO + CTS + MoE
训练源码 legbot_rl_lab/source/unitree_rl_lab source/robot_labsource/rsl_rl
策略输入 10 帧历史观测 历史观测进入学生编码器,Actor 还拼接单帧观测
部署重点 C++、DDS、串口网关、实物闭环 Python MuJoCo Sim2Sim 与学生策略导出
典型依赖 Isaac Lab 2.2.0、RSL-RL 2.3.1 Isaac Lab 2.3.2.post1、自定义 RSL-RL
策略导出 ONNX、TorchScript、部署 YAML 学生分支 TorchScript/ONNX,内部维护历史缓存

3. 项目总体架构

完整系统可分为训练层、策略层、仿真验证层和硬件执行层。

3.1 训练层

Isaac Lab 负责物理仿真、并行环境、传感器、地形和 MDP 管理。RSL-RL 负责 PPO 采样、GAE、策略更新、模型保存和日志记录。

训练时默认创建 4096 个并行环境。物理仿真步长为 0.005 s,即 200 Hz;decimation=4,每 4 个物理步调用一次策略,因此策略控制频率为:

f p o l i c y = 1 0.005 × 4 = 50 H z f_{\mathrm{policy}}=\frac{1}{0.005\times4}=50\ \mathrm{Hz} fpolicy=0.005×41=50 Hz

这里需要注意,仓库部分注释把 4 倍降采样写成了"80 ms",但根据 sim.dt=0.005decimation=4 计算,实际控制周期是 0.02 s,即 20 ms。

3.2 策略层

策略网络接收机器人本体观测和速度命令,输出 12 维关节动作。动作不是直接力矩,而是相对于默认关节角的偏移量。

策略输出经过动作缩放后得到目标关节角,再由 PD 控制器计算关节力矩。训练中的电机模型进一步加入力矩---速度限幅、摩擦和延迟。

3.3 验证层

策略在 Isaac Lab 中完成训练后,需要在另一套物理引擎中验证。项目使用 MuJoCo 进行 Sim2Sim 测试,主要检查:

  • URDF/MJCF 关节顺序是否一致;
  • 四元数顺序和坐标系是否一致;
  • 默认关节角与动作缩放是否一致;
  • 策略频率、PD 频率和物理仿真频率是否一致;
  • 地面接触模型变化后策略是否仍能稳定运行;
  • ONNX/TorchScript 推理结果是否与 Python 训练端一致。

3.4 硬件层

默认 PPO 分支在实物端使用 Orange Pi 6。控制器运行有限状态机和策略推理,串口网关负责 RobStride 电机和自制 IMU 协议,再通过 DDS 与控制器交换低层状态和命令。

控制器与硬件之间通过通信抽象层解耦,便于将 MuJoCo 对端替换为真实串口网关。


4. 目录结构与模块职责

4.1 PPO 分支主要目录

text 复制代码
legbot_lab/
├── env_cfg.py
├── legbot/
├── legbot_rl_lab/
│   ├── source/unitree_rl_lab/
│   │   └── unitree_rl_lab/
│   │       ├── assets/robots/
│   │       ├── tasks/locomotion/
│   │       │   ├── agents/
│   │       │   ├── mdp/
│   │       │   └── robots/legbot/
│   │       └── utils/
│   ├── scripts/rsl_rl/
│   ├── deploy/
│   └── unitree_ros/
├── simulate/
├── serial_dds_gateway/
├── terrain_tool/
├── unitree_sdk2/
├── sim2real要求.md
└── 项目详解.md

其中:

  • env_cfg.py:根目录汇总环境配置,包含场景、观测、动作、奖励、随机化、课程和终止条件;
  • assets/robots:机器人 URDF、关节参数和执行器模型;
  • tasks/locomotion/agents:PPO 网络与训练超参数;
  • tasks/locomotion/mdp:奖励、观测、命令、课程和事件函数;
  • tasks/locomotion/robots/legbot:Legbot 任务配置;
  • scripts/rsl_rl/train.py:训练入口;
  • scripts/rsl_rl/play.py:推理、模型加载和策略导出;
  • deploy:C++ 控制器、FSM、安全限制和 ONNX Runtime 推理;
  • simulate:MuJoCo 与 DDS 桥接仿真器;
  • serial_dds_gateway:真实电机和 IMU 的协议转换;
  • terrain_tool:地形生成工具;
  • legbot:另一套独立的 NumPy/MuJoCo 任务实验代码,不是主 PPO 训练入口。

4.2 PPO-CTS-MOE 分支主要目录

text 复制代码
legbot_lab/
├── scripts/rsl_rl/
├── source/
│   ├── robot_lab/
│   │   └── robot_lab/
│   │       ├── assets/
│   │       └── tasks/
│   │           ├── go2/
│   │           └── legbot/
│   └── rsl_rl/
│       └── rsl_rl/
│           ├── algorithms/moe_cts.py
│           ├── modules/actor_critic_moe_cts.py
│           ├── networks/moe.py
│           ├── runners/on_policy_runner_cts.py
│           ├── storage/rollout_storage_cts.py
│           └── utils/exporter_cts.py
├── deploy/deploy_mujoco/
├── resources/legbot/
├── src/
└── TECHNICAL_DOC_zh.md

关键文件作用如下。

文件 作用
moe_cts.py PPO 与学生蒸馏的联合优化
actor_critic_moe_cts.py 教师编码器、学生编码器、Actor 和 Critic 组合
moe.py 专家网络、门控网络和专家加权
on_policy_runner_cts.py 采样、回报计算、更新和保存
rollout_storage_cts.py 区分教师与学生样本的轨迹存储
exporter_cts.py 导出仅保留学生侧的部署策略
env_cfg.py 观测、动作、奖励、随机化和地形配置
rsl_rl_cfg.py 网络结构、教师比例、专家数和 PPO 超参数
deploy_legbot.py MuJoCo 推理与 PD 控制循环

5. Legbot 机器人模型

5.1 自由度和关节结构

Legbot 为 12 自由度四足机器人,每条腿包含 3 个关节:

  • Hip:髋关节侧摆;
  • Thigh:大腿关节前后摆;
  • Calf:小腿关节屈伸。

四条腿按前左、前右、后左、后右排列。不同分支和不同模型文件中可能采用 FL/FR/RL/RRFR/FL/RR/RL 顺序,因此部署前必须以导出的关节映射为准,不能仅依靠文件名猜测。

默认站立关节角通常为:

q d e f a u l t = 0 , 0.9 , − 1.8 × 4 q_{\mathrm{default}}= 0,\\ 0.9,\\ -1.8\times4 qdefault=0, 0.9, −1.8×4

即每条腿的 Hip、Thigh、Calf 分别为 0、0.9 和 -1.8 rad。

5.2 机器人参数

默认 PPO 分支 README 给出的当前模型参数包括:

参数 数值
总质量 约 14 kg
基座质量 6.584 kg
自由度 12
大腿长度 0.1985 m
小腿长度 0.214 m
足端半径 0.021 m
髋/大腿峰值力矩 约 ±16 N·m
小腿峰值力矩 约 ±32 N·m
板载计算机 Orange Pi 6
控制器频率 1 kHz
串口网关频率 500 Hz

5.3 惯量和质心为什么重要

四足机器人策略对质心和惯量十分敏感。基座质心偏差会改变支撑多边形中的重力投影位置,惯量偏差会改变相同关节动作对应的机身角加速度。

若仿真中质心偏前,而实物质心偏后,策略可能表现为:

  • 启动时前腿下压;
  • 前髋关节长期输出较大力矩;
  • 后腿摆动幅度不足;
  • 加速和刹停时俯仰振荡;
  • 平地可运行,但楼梯或推扰下迅速失稳。

因此,Sim2Real 前应重新测量整机质量、各连杆质量、基座质心和主要惯量,并在 URDF、MJCF、Isaac Lab 资产和部署配置中保持一致。


6. 强化学习任务的 MDP 建模

四足速度跟踪可写成部分可观测马尔可夫决策过程。完整系统状态记为 s t s_t st,实物能够获得的观测记为 o t o_t ot,动作记为 a t a_t at,奖励记为 r t r_t rt。

策略目标是最大化期望折扣回报:

J ( θ ) = E π θ ∑ t = 0 ∞ γ t r t J(\theta)=\mathbb{E}{\pi\theta}\left\\sum_{t=0}\^{\\infty}\\gamma\^t r_t\\right J(θ)=Eπθt=0∑∞γtrt

其中 γ \gamma γ 为折扣因子。

6.1 为什么是部分可观测问题

实物通常不能直接获得以下状态:

  • 精确的基座世界系线速度;
  • 脚下地形高度图;
  • 足端真实接触力;
  • 每个关节的真实输出力矩;
  • 精确的摩擦系数、负载和电机温度状态。

但策略可以从一段历史观测中推断部分隐状态。例如,连续 10 帧 IMU 和关节状态可以反映身体加速度、支撑相变化和地形冲击。因此项目在 Actor 侧使用历史观测,缓解单帧观测的不可观问题。


7. PPO 算法原理

PPO 是一种 on-policy Actor-Critic 算法。它先用当前策略采集轨迹,再使用这批数据更新策略。旧数据在策略明显变化后不再反复使用。

7.1 概率比

旧策略为 π θ o l d \pi_{\theta_{\mathrm{old}}} πθold,新策略为 π θ \pi_\theta πθ。同一动作在新旧策略下的概率比为:

r t ( θ ) = π θ ( a t ∣ o t ) π θ o l d ( a t ∣ o t ) r_t(\theta)= \frac{\pi_\theta(a_t|o_t)} {\pi_{\theta_{\mathrm{old}}}(a_t|o_t)} rt(θ)=πθold(at∣ot)πθ(at∣ot)

当 r t > 1 r_t>1 rt>1 时,新策略更倾向于选择该动作;当 r t < 1 r_t<1 rt<1 时,新策略降低了该动作的概率。

7.2 裁剪代理目标

PPO 使用裁剪限制单次更新幅度:

L C L I P ( θ ) = E t min ⁡ ( r t ( θ ) A \^ t , clip ⁡ ( r t ( θ ) , 1 − ϵ , 1 + ϵ ) A \^ t ) L^{\mathrm{CLIP}}(\theta)= \mathbb{E}_t \left \\min \\left( r_t(\\theta)\\hat A_t,\\ \\operatorname{clip} \\left( r_t(\\theta),1-\\epsilon,1+\\epsilon \\right)\\hat A_t \\right) \\right LCLIP(θ)=Etmin(rt(θ)A\^t, clip(rt(θ),1−ϵ,1+ϵ)A\^t)

项目常用:

ϵ = 0.2 \epsilon=0.2 ϵ=0.2

优势为正时,策略希望提高该动作概率;优势为负时,策略希望降低该动作概率。裁剪项避免概率比偏离 1 过远,从而降低训练崩溃概率。

7.3 TD 残差

值函数 V ϕ ( s t ) V_\phi(s_t) Vϕ(st) 估计从当前状态出发的期望回报。单步 TD 残差为:

δ t = r t + γ V ϕ ( s t + 1 ) − V ϕ ( s t ) \delta_t= r_t+\gamma V_\phi(s_{t+1})-V_\phi(s_t) δt=rt+γVϕ(st+1)−Vϕ(st)

7.4 广义优势估计

项目使用 GAE 平衡偏差与方差:

A ^ t = ∑ l = 0 T − t − 1 ( γ λ ) l δ t + l \hat A_t= \sum_{l=0}^{T-t-1} (\gamma\lambda)^l\delta_{t+l} A^t=l=0∑T−t−1(γλ)lδt+l

其中:

γ = 0.99 , λ = 0.95 \gamma=0.99,\qquad \lambda=0.95 γ=0.99,λ=0.95

7.5 目标回报

R ^ t = A ^ t + V ϕ ( s t ) \hat R_t=\hat A_t+V_\phi(s_t) R^t=A^t+Vϕ(st)

7.6 价值函数损失

L V F ( ϕ ) = E t ( V ϕ ( s t ) − R \^ t ) 2 L^{\mathrm{VF}}(\phi)= \mathbb{E}_t \left \\left( V_\\phi(s_t)-\\hat R_t \\right)\^2 \\right LVF(ϕ)=Et(Vϕ(st)−R\^t)2

RSL-RL 还可使用裁剪值函数损失,限制新旧价值估计变化。

7.7 策略熵

高斯策略的熵用于保持探索:

H π θ = − E a ∼ π θ log ⁡ π θ ( a ∣ o ) H\\pi_\\theta= -\mathbb{E}{a\sim\pi\theta} \left \\log \\pi_\\theta(a\|o) \\right Hπθ=−Ea∼πθlogπθ(a∣o)

7.8 总损失

训练时最小化的损失可写为:

L = − L C L I P + c v L V F − c e H π θ L= -L^{\mathrm{CLIP}} +c_v L^{\mathrm{VF}} -c_e H\\pi_\\theta L=−LCLIP+cvLVF−ceHπθ

典型参数为:

c v = 1.0 , c e = 0.01 c_v=1.0,\qquad c_e=0.01 cv=1.0,ce=0.01

7.9 一次迭代包含多少数据

默认并行环境数量为 4096,每个环境采集 24 个控制步,因此一次 rollout 包含:

N s a m p l e = 4096 × 24 = 98304 N_{\mathrm{sample}}=4096\times24=98304 Nsample=4096×24=98304

这些样本被分成 4 个 mini-batch,并训练 5 个 epoch。需要区分三个概念:

  • rollout:用当前策略采集一批数据;
  • mini-batch:一次梯度计算使用的数据子集;
  • epoch:对同一批 rollout 数据完整遍历一次。

8. 非对称 Actor-Critic

项目的 Actor 和 Critic 使用不同观测。

8.1 Actor 观测

单帧策略观测共 45 维:

观测项 维度 典型缩放 典型噪声
基座角速度 3 0.25 U ( − 0.2 , 0.2 ) U(-0.2,0.2) U(−0.2,0.2)
投影重力 3 1.0 U ( − 0.05 , 0.05 ) U(-0.05,0.05) U(−0.05,0.05)
速度命令 3 1.0
相对默认关节位置 12 1.0 U ( − 0.03 , 0.03 ) U(-0.03,0.03) U(−0.03,0.03)
关节速度 12 0.05 U ( − 2 , 2 ) U(-2,2) U(−2,2)
上一动作 12 1.0

PPO 分支设置 10 帧历史并展平,因此 Actor 输入为:

45 × 10 = 450 45\times10=450 45×10=450

历史观测能够帮助策略隐式推断线速度、接触状态、动作延迟和地形变化。

8.2 Critic 特权观测

Critic 在训练阶段额外使用:

  • 基座线速度;
  • 关节加速度;
  • 关节力矩;
  • 足端接触力;
  • 地形高度扫描。

Critic 不加观测噪声,有利于稳定价值估计。部署时 Critic 不参与动作输出,因此这些特权信息不需要在实物端提供。

8.3 投影重力

世界坐标系重力方向为:

g w = 0 0 − 1 T g_w= \begin{bmatrix} 0&0&-1 \end{bmatrix}^{\mathrm T} gw=00−1T

利用基座旋转矩阵 R w b R_{wb} Rwb,重力在机体系中的表示为:

g b = R w b T g w g_b=R_{wb}^{\mathrm T}g_w gb=RwbTgw

当机身水平时, g b g_b gb 接近 0 , 0 , − 1 T 0,0,-1^{\mathrm T} 0,0,−1T。其 x x x 和 y y y 分量能够反映俯仰和横滚倾斜。


9. 动作空间与底层 PD 控制

策略输出 12 维动作:

a t ∈ R 12 a_t\in\mathbb{R}^{12} at∈R12

动作映射到目标关节角:

q d e s = q d e f a u l t + s a a t q_{\mathrm{des}}= q_{\mathrm{default}}+ s_a a_t qdes=qdefault+saat

其中动作缩放:

s a = 0.25 r a d s_a=0.25\ \mathrm{rad} sa=0.25 rad

因此,当策略输出为 1 时,对应关节目标相对默认角增加 0.25 rad。

PD 控制器计算力矩:

τ P D = K p ( q d e s − q ) + K d ( q ˙ d e s − q ˙ ) \tau_{\mathrm{PD}}= K_p(q_{\mathrm{des}}-q) + K_d(\dot q_{\mathrm{des}}-\dot q) τPD=Kp(qdes−q)+Kd(q˙des−q˙)

位置策略通常令:

q ˙ d e s = 0 \dot q_{\mathrm{des}}=0 q˙des=0

不同配置文件中训练增益和部署站立增益不完全相同。当前 README 中常见设置包括训练 K p = 50 K_p=50 Kp=50、 K d = 3 K_d=3 Kd=3,FixStand 状态使用 K p = 60 K_p=60 Kp=60、 K d = 4 K_d=4 Kd=4。实际部署必须读取导出的配置和 C++ 控制器参数,不能只参考文章中的示例值。


10. 电机模型

仅用理想 PD 力矩会高估真实电机能力。项目在仿真中加入摩擦、力矩---速度曲线和延迟。

10.1 摩擦模型

实际力矩可写为:

τ a c t u a l = τ P D − F s tanh ⁡ ( q ˙ V a ) − F d q ˙ \tau_{\mathrm{actual}}= \tau_{\mathrm{PD}} -F_s\tanh\left(\frac{\dot q}{V_a}\right) -F_d\dot q τactual=τPD−Fstanh(Vaq˙)−Fdq˙

其中:

  • F s F_s Fs:库仑摩擦幅值;
  • F d F_d Fd:粘性摩擦系数;
  • V a V_a Va:零速附近的平滑过渡参数。

双曲正切函数避免符号函数在零速度附近不连续。

10.2 力矩---速度限幅

低速时电机可输出接近峰值力矩,速度超过拐点后,允许力矩逐渐下降。简化表达为:

τ max ⁡ ( ω ) = { Y , ∣ ω ∣ < X 1 Y X 2 − ∣ ω ∣ X 2 − X 1 , X 1 ≤ ∣ ω ∣ ≤ X 2 0 , ∣ ω ∣ > X 2 \tau_{\max}(\omega)= \begin{cases} Y, & |\omega|<X_1 \\ Y\dfrac{X_2-|\omega|}{X_2-X_1}, & X_1\le|\omega|\le X_2 \\ 0, & |\omega|>X_2 \end{cases} τmax(ω)=⎩ ⎨ ⎧Y,YX2−X1X2−∣ω∣,0,∣ω∣<X1X1≤∣ω∣≤X2∣ω∣>X2

PPO-CTS-MOE 分支 README 给出的 Go2 HV 示例参数为:

参数 数值
X 1 X_1 X1 13.5 rad/s
X 2 X_2 X2 30 rad/s
Y 1 Y_1 Y1 20.2 N·m
Y 2 Y_2 Y2 23.4 N·m

10.3 电机延迟

电机层设置 0~4 个控制步延迟。控制周期为 20 ms 时,对应:

T d e l a y ∈ 0 , 80 m s T_{\mathrm{delay}}\in0,80\ \mathrm{ms} Tdelay∈0,80 ms

需要确认延迟究竟施加在策略动作、目标位置还是执行器内部。仓库说明该延迟位于电机模型层,而不是简单地对策略输出做全局延迟。


11. 奖励函数设计

总奖励为多项加权和:

r t = ∑ i w i r i , t r_t=\sum_i w_i r_{i,t} rt=i∑wiri,t

奖励设计并不是奖励项越多越好。每个奖励项都在塑造运动风格,多个项可能相互冲突。

11.1 线速度跟踪

r l i n = exp ⁡ ( − ∥ v c m d x y − v b a s e x y ∥ 2 σ 2 ) r_{\mathrm{lin}}= \exp \left( -\frac{ \left\| v_{\mathrm{cmd}}^{xy} -v_{\mathrm{base}}^{xy} \right\|^2 }{\sigma^2} \right) rlin=exp(−σ2∥vcmdxy−vbasexy∥2)

项目常用:

σ = 0.5 \sigma=0.5 σ=0.5

指数核在误差较小时给出较高奖励,误差增大后奖励快速下降。

11.2 偏航角速度跟踪

r y a w = exp ⁡ ( − ( ω c m d z − ω b a s e z ) 2 σ 2 ) r_{\mathrm{yaw}}= \exp \left( -\frac{ (\omega_{\mathrm{cmd}}^z-\omega_{\mathrm{base}}^z)^2 }{\sigma^2} \right) ryaw=exp(−σ2(ωcmdz−ωbasez)2)

11.3 垂直速度惩罚

r v z = − ( v b a s e z ) 2 r_{v_z}= -\left(v_{\mathrm{base}}^z\right)^2 rvz=−(vbasez)2

用于抑制机身上下跳动。

11.4 横滚和俯仰角速度惩罚

r ω x y = − ∥ ω b a s e x y ∥ 2 r_{\omega_{xy}}= -\left\| \omega_{\mathrm{base}}^{xy} \right\|^2 rωxy=−∥ωbasexy∥2

11.5 关节力矩惩罚

r τ = − ∑ i τ i 2 r_{\tau}= -\sum_i\tau_i^2 rτ=−i∑τi2

11.6 关节功率惩罚

r p o w e r = − ∑ i ∣ τ i q ˙ i ∣ r_{\mathrm{power}}= -\sum_i \left| \tau_i\dot q_i \right| rpower=−i∑∣τiq˙i∣

该项比单独惩罚力矩更直接地约束机械功率。

11.7 动作变化率

r Δ a = − ∥ a t − a t − 1 ∥ 2 r_{\Delta a}= -\left\| a_t-a_{t-1} \right\|^2 rΔa=−∥at−at−1∥2

11.8 二阶动作平滑

r s m o o t h = − ∥ a t − 2 a t − 1 + a t − 2 ∥ 2 r_{\mathrm{smooth}}=-\left\|a_t-2a_{t-1}+a_{t-2} \right\|^2 rsmooth=−∥at−2at−1+at−2∥2

该项抑制动作的高频变化,减少电机抖动。

11.9 基座高度

基座高度不直接使用世界系 z z z,而是利用高度扫描估计局部地面:

h b a s e = z b a s e − mean ⁡ ( z r a y h i t ) h_{\mathrm{base}}=z_{\mathrm{base}} -\operatorname{mean}(z_{\mathrm{rayhit}}) hbase=zbase−mean(zrayhit)

高度惩罚为:

r h = − ( h b a s e − h t a r g e t ) 2 r_h= -\left( h_{\mathrm{base}}-h_{\mathrm{target}} \right)^2 rh=−(hbase−htarget)2

目标高度约为:

h t a r g e t = 0.28 m h_{\mathrm{target}}=0.28\ \mathrm m htarget=0.28 m

11.10 足端调节

项目参考 CTS 论文加入足端调节项,使摆腿不总是贴地走最短路径。一个常见表达为:

r f o o t = − ∑ i ∥ v i x y ∥ 2 exp ⁡ ( − h i k h h t a r g e t ) r_{\mathrm{foot}}= -\sum_i \left\| v_{i}^{xy} \right\|^2 \exp \left( -\frac{h_i} {k_h h_{\mathrm{target}}} \right) rfoot=−i∑∥vixy∥2exp(−khhtargethi)

当足端高度较低时,水平滑动受到更强惩罚;足端抬高后,水平运动惩罚减弱,从而形成更合理的摆腿轨迹。

11.11 当前分支常见权重

奖励项 典型权重 作用
线速度跟踪 +1.0~+1.5 跟踪前后和横向速度
偏航角速度跟踪 +0.5~+0.75 跟踪转向命令
垂直速度 -2.0,课程可趋近 0 抑制上下振荡
横滚/俯仰角速度 -0.05 抑制机身摆动
基座高度 -1.0 到 -10.0 保持目标高度
关节加速度 -1e-7 抑制高频关节变化
关节功率 -2e-5 降低能耗
关节力矩 -1e-4 防止大力矩
动作变化率 -0.01 平滑控制
二阶动作平滑 -0.01 抑制动作抖动
不期望接触 -1.0 防止大腿和小腿撞地
关节限位 -2.0 避免越界
足端调节 -0.05 抑制低高度滑动

奖励权重在仓库不同提交中有变化。复现实验时应以训练日志保存的 Hydra 配置为准,而不是以 README 表格为唯一依据。


12. 域随机化

域随机化的目标不是让仿真"更乱",而是在合理范围内覆盖真实系统的不确定性。

12.1 质量和惯量

参数 模式 范围
基座附加质量 startup − 1 , 1 -1,1 −1,1 kg
其他连杆质量 startup 标称值的 0.9~1.1 倍
转动惯量 startup 标称值的 0.9~1.1 倍
基座质心 startup 各方向厘米级偏移

质量和惯量应联动更新。若只改变质量而不重算惯量,随机模型可能不符合真实刚体分布。

12.2 摩擦和恢复系数

项目对静摩擦、动摩擦和碰撞恢复系数进行随机化,以覆盖地砖、地毯、木板和粗糙地面等差异。

摩擦下界设为 0 会产生接近无摩擦的极端环境。若策略训练长期不稳定,可先将下界提高,再逐步放宽。

12.3 执行器参数

  • K p K_p Kp 和 K d K_d Kd 缩放;
  • 编码器零位偏移;
  • 电机力矩上限;
  • 关节摩擦;
  • 电机延迟。

零位偏移随机化能够模拟装配误差和编码器标定误差,但范围过大时会改变默认站姿。应保证随机姿态仍在机械限位内。

12.4 初始状态

每个 episode 重置时随机化:

  • 基座平面位置;
  • 偏航角;
  • 基座线速度和角速度;
  • 关节位置;
  • 关节速度;
  • 基座高度。

随机初始状态能够提高恢复能力,但若初始姿态过于困难,策略会在早期大量摔倒,导致有效采样不足。

12.5 周期性推扰

项目每隔约 4 s 给机器人施加速度扰动,典型范围为:

Δ v x y ∈ − 0.4 , 0.4 m / s \Delta v_{xy}\in-0.4,0.4\ \mathrm{m/s} Δvxy∈−0.4,0.4 m/s

Δ ω ∈ − 0.6 , 0.6 r a d / s \Delta\omega\in-0.6,0.6\ \mathrm{rad/s} Δω∈−0.6,0.6 rad/s

推扰训练能提高抗冲击能力,但不能替代准确的动力学建模。

12.6 观测噪声

Actor 侧加入 IMU 和关节观测噪声,Critic 侧保持无噪声。这样既训练传感器鲁棒性,又避免价值网络估计过度抖动。


13. 课程学习

一次性把机器人放到最复杂地形和最大速度范围,容易导致训练早期全是失败样本。项目使用课程学习逐步增加难度。

13.1 地形课程

根据机器人在当前地形中的移动距离调整地形等级:

  • 移动距离超过地形长度的一半,提高难度;
  • 移动距离明显低于目标距离,降低难度;
  • 平地、坡面、粗糙地形、楼梯和离散障碍按等级组织。

13.2 奖励权重课程

例如:

  • 垂直速度惩罚从 -2.0 逐渐变到 0;
  • 基座高度惩罚从 -1.0 逐渐增强到 -10.0。

这样可以让策略先学会移动,再逐步收紧姿态和高度要求。

13.3 命令范围课程

速度范围随训练迭代扩大。PPO-CTS-MOE 分支文档给出的示例为:

text 复制代码
20,000 次迭代:
lin_vel_x = [-1, 1]
lin_vel_y = [-1, 1]
ang_vel_z = [-1.5, 1.5]

50,000 次迭代:
lin_vel_x = [-2, 2]
lin_vel_y = [-1, 1]
ang_vel_z = [-2, 2]

实际自研机器人能否达到该速度取决于腿长、电机能力、减速比、供电和机械强度。不能因为训练命令允许 2 m/s,就直接在实物上给出同样命令。


14. MoE-CTS 算法

14.1 传统两阶段教师---学生方法

传统做法通常分两步:

  1. 教师策略使用特权信息训练;
  2. 固定教师,再用监督学习训练学生模仿教师动作。

问题是学生训练阶段不会继续影响教师,教师也无法适应学生的表示能力。两阶段训练还需要分别保存、加载和调试两套过程。

14.2 并发教师---学生

CTS 把并行环境分成教师组和学生组。项目中教师环境比例为 0.75,学生环境比例为 0.25。

教师潜变量:

z t = L2Norm ⁡ ( E t ( o c r i t i c ) ) z_t= \operatorname{L2Norm} \left( E_t(o_{\mathrm{critic}}) \right) zt=L2Norm(Et(ocritic))

学生潜变量:

z s = L2Norm ⁡ ( E s ( o h i s t o r y ) ) z_s= \operatorname{L2Norm} \left( E_s(o_{\mathrm{history}}) \right) zs=L2Norm(Es(ohistory))

教师和学生共享同一个 Actor:

a ∼ π θ ( a ∣ z , o s i n g l e ) a\sim\pi_\theta \left( a\midz,o_{\\mathrm{single}} \right) a∼πθ(a∣z,osingle)

Critic 使用特权观测估值:

V = V ϕ ( z d e t a c h , o c r i t i c ) V= V_\phi \left( z_{\\mathrm{detach}},o_{\\mathrm{critic}} \right) V=Vϕ(zdetach,ocritic)

潜变量在进入 Critic 时停止梯度,可避免价值损失直接改变编码器表示。

14.3 潜变量蒸馏

学生编码器逼近教师编码器输出:

L l a t e n t = ∥ z s − stopgrad ⁡ ( z t ) ∥ 2 2 L_{\mathrm{latent}}= \left\| z_s- \operatorname{stopgrad}(z_t) \right\|_2^2 Llatent=∥zs−stopgrad(zt)∥22

stopgrad 表示教师输出作为监督目标,不通过该损失反向更新教师编码器。

14.4 Mixture of Experts

学生编码器使用多个专家。门控网络输出专家权重:

g = Softmax ⁡ ( G ( o h i s t o r y ) ) g= \operatorname{Softmax} \left( G(o_{\mathrm{history}}) \right) g=Softmax(G(ohistory))

第 i i i 个专家输出:

e i = E i ( B ( o h i s t o r y ) ) e_i= E_i \left( B(o_{\mathrm{history}}) \right) ei=Ei(B(ohistory))

学生潜变量为:

z s = L2Norm ⁡ ( ∑ i = 1 N g i e i ) z_s= \operatorname{L2Norm} \left( \sum_{i=1}^{N}g_i e_i \right) zs=L2Norm(i=1∑Ngiei)

项目设置:

N = 8 N=8 N=8

不同专家可以分别对平地、坡面、楼梯、冲击恢复或不同运动模式形成差异化响应。门控不是硬切换,而是对专家输出进行连续加权。

14.5 专家负载均衡

如果门控长期只使用一个专家,其余专家将无法学习。项目加入负载均衡损失:

L b a l a n c e = ∥ mean ⁡ ( g ) − 1 N 1 ∥ 2 2 L_{\mathrm{balance}}=\left\|\operatorname{mean}(g) -\frac{1}{N}\mathbf 1 \right\|_2^2 Lbalance= mean(g)−N11 22

学生总损失:

L s t u d e n t = L l a t e n t + α L b a l a n c e L_{\mathrm{student}}= L_{\mathrm{latent}} + \alpha L_{\mathrm{balance}} Lstudent=Llatent+αLbalance

其中:

α = 0.01 \alpha=0.01 α=0.01

14.6 联合优化目标

MoE-CTS 的总优化可概括为:

L t o t a l = L P P O + λ s L s t u d e n t L_{\mathrm{total}}= L_{\mathrm{PPO}} + \lambda_s L_{\mathrm{student}} Ltotal=LPPO+λsLstudent

PPO 负责提高任务回报,蒸馏损失负责让学生从本体历史观测中恢复教师潜变量。

14.7 部署时保留什么

部署阶段不保留:

  • 教师编码器;
  • Critic;
  • 特权观测;
  • 地形高度扫描;
  • 仿真中的真实线速度和接触力。

部署阶段保留:

  • 观测归一化;
  • 历史缓存;
  • 学生 MoE 编码器;
  • Actor;
  • 动作缩放和关节映射。

15. 训练超参数

15.1 PPO 分支常用参数

参数 数值
并行环境数 4096
每环境 rollout 步数 24
PPO epoch 5
mini-batch 数 4
学习率 1 × 10 − 3 1 \times 10^{-3} 1×10−3
折扣因子 γ \gamma γ 0.99
GAE 参数 λ \lambda λ 0.95
裁剪参数 ϵ \epsilon ϵ 0.2
熵系数 0.01
价值损失系数 1.0
最大梯度范数 1.0
目标 KL 0.01
物理步长 0.005 s
控制降采样 4
策略频率 50 Hz
Episode 时长 25 s

15.2 MoE-CTS 扩展参数

参数 数值
教师环境比例 0.75
学生环境比例 0.25
专家数量 8
潜变量维度 32
历史长度 10
学生编码器学习率 1 × 10 − 3 1 \times 10^{-3} 1×10−3
负载均衡系数 0.01
最大训练迭代 300000
模型保存间隔 500

16. 软件依赖

16.1 PPO 分支

仓库 README 给出的主要版本为:

类别 依赖
操作系统 Linux,推荐 Ubuntu
Python 与 Isaac Lab 2.2.0 环境一致
仿真 Isaac Sim 5.0.0
训练框架 Isaac Lab 2.2.0
强化学习 RSL-RL 2.3.1
深度学习 PyTorch + CUDA
配置 Hydra、YAML
模型导出 TorchScript、ONNX
C++ 推理 ONNX Runtime 1.22.0
编译 CMake、C++17
通信 CycloneDDS、Unitree SDK2
Sim2Sim MuJoCo
实物接口 USB-CAN、USB 串口、自制 IMU 协议

Python 工程中还会使用:

  • NumPy;
  • SciPy;
  • Gymnasium;
  • Matplotlib;
  • PyYAML;
  • tqdm;
  • psutil;
  • trimesh;
  • h5py;
  • prettytable。

这些名称在仓库 pyproject.toml 的代码检查配置中出现,但并不等同于完整的固定版本依赖清单。以 Isaac Lab 环境和包内 setup.py 为准。

16.2 PPO-CTS-MOE 分支

该分支 README 给出的安装组合为:

bash 复制代码
conda create -n legbot_lab python=3.11
conda activate legbot_lab

pip install --upgrade pip

pip install isaaclab[isaacsim,all]==2.3.2.post1 \
  --extra-index-url https://pypi.nvidia.com

pip install -U torch==2.7.0 torchvision==0.22.0 \
  --index-url https://download.pytorch.org/whl/cu128

python -m pip install -e source/robot_lab
python -m pip install -e source/rsl_rl

pip install mujoco pygame

这组版本与 PPO 分支不同。切换分支时建议单独创建 Conda 环境,避免 Isaac Lab、PyTorch、CUDA 和自定义 RSL-RL 相互覆盖。

16.3 C++ 侧常见系统库

实物部署通常还需要:

bash 复制代码
sudo apt update
sudo apt install -y \
  build-essential \
  cmake \
  git \
  pkg-config \
  libyaml-cpp-dev

CycloneDDS、Unitree SDK2 和 ONNX Runtime 的安装位置需要与 CMake 配置一致。aarch64 板载计算机必须使用 aarch64 版本的 ONNX Runtime,不能复制 x86_64 动态库。


17. PPO 分支运行步骤

17.1 获取代码

bash 复制代码
git clone https://github.com/Robot-Nav/legbot_lab.git
cd legbot_lab
git checkout PPO

确认分支:

bash 复制代码
git branch --show-current

输出应为:

text 复制代码
PPO

17.2 激活 Isaac Lab 环境

bash 复制代码
conda activate env_isaaclab

检查 Python:

bash 复制代码
which python
python --version

17.3 安装训练包

在仓库根目录执行:

bash 复制代码
pip install -e legbot_rl_lab/source/unitree_rl_lab

检查任务是否注册:

bash 复制代码
python legbot_rl_lab/scripts/rsl_rl/train.py --help

17.4 启动训练

bash 复制代码
python legbot_rl_lab/scripts/rsl_rl/train.py \
  --task Unitree-Legbot-Velocity \
  --headless \
  --num_envs 4096 \
  --max_iterations 50000

显存不足时先降低环境数:

bash 复制代码
python legbot_rl_lab/scripts/rsl_rl/train.py \
  --task Unitree-Legbot-Velocity \
  --headless \
  --num_envs 1024 \
  --max_iterations 50000

17.5 指定随机种子

bash 复制代码
python legbot_rl_lab/scripts/rsl_rl/train.py \
  --task Unitree-Legbot-Velocity \
  --headless \
  --seed 42

正式对比实验至少使用 3~5 个随机种子,并报告均值和标准差。

17.6 恢复训练

自动恢复最新运行:

bash 复制代码
python legbot_rl_lab/scripts/rsl_rl/train.py \
  --task Unitree-Legbot-Velocity \
  --resume \
  --headless

手动指定:

bash 复制代码
python legbot_rl_lab/scripts/rsl_rl/train.py \
  --task Unitree-Legbot-Velocity \
  --resume \
  --load_run 2026-06-25_17-11-16 \
  --checkpoint model_108.pt \
  --headless

17.7 推理与导出

bash 复制代码
python legbot_rl_lab/scripts/rsl_rl/play.py \
  --task Unitree-Legbot-Velocity

典型导出目录:

text 复制代码
logs/rsl_rl/unitree_legbot_velocity/<run_name>/exported/
├── policy.pt
├── policy.onnx
└── deploy.yaml

17.8 编译串口网关

bash 复制代码
cd serial_dds_gateway
mkdir -p build
cd build

cmake -S .. -B .
cmake --build . -j$(nproc)

17.9 编译控制器

bash 复制代码
cd legbot_rl_lab/deploy/robots/legbot
mkdir -p build
cd build

cmake -S .. -B .
cmake --build . -j$(nproc)

17.10 启动实物通信

终端 1:

bash 复制代码
cd serial_dds_gateway

./build/dds_to_serial_gateway \
  --serial-port-a /dev/myttyCAN0 \
  --serial-port-b /dev/myttyCAN1 \
  --imu-port /dev/myttyIMU \
  --network lo \
  --tick-hz 500 \
  --joint-bias-load-file config/joint_prone_bias.fatu.txt \
  --send-disable-on-exit

终端 2:

bash 复制代码
cd legbot_rl_lab/deploy/robots/legbot

./build/legbot_ctrl --network lo

17.11 FSM 状态切换

项目状态机大致为:

text 复制代码
Passive --LT+A--> FixStand --Start--> Velocity
   ^                 ^                  |
   |                 |                  |
   +------ LT+B -----+------ LT+B ------+

建议严格按以下顺序:

  1. 悬空或支撑状态检查电机方向;
  2. 进入 Passive,确认阻尼有效;
  3. 进入 FixStand,确认默认站姿与关节零位;
  4. 小幅速度命令测试;
  5. 再进入完整 RL 速度控制。

18. PPO-CTS-MOE 分支运行步骤

18.1 切换分支

bash 复制代码
git checkout PPO-CTS-MOE
git branch --show-current

18.2 建立独立环境

bash 复制代码
conda create -n legbot_moe_cts python=3.11
conda activate legbot_moe_cts

18.3 安装 Isaac Lab 和 PyTorch

bash 复制代码
pip install --upgrade pip

pip install isaaclab[isaacsim,all]==2.3.2.post1 \
  --extra-index-url https://pypi.nvidia.com

pip install -U torch==2.7.0 torchvision==0.22.0 \
  --index-url https://download.pytorch.org/whl/cu128

CUDA 版本必须与显卡驱动兼容。安装前可检查:

bash 复制代码
nvidia-smi

18.4 安装本地包

bash 复制代码
python -m pip install -e source/robot_lab
python -m pip install -e source/rsl_rl

18.5 训练

bash 复制代码
python scripts/rsl_rl/train.py \
  --task=RobotLab-Legbot-v0 \
  --headless

自定义参数:

bash 复制代码
python scripts/rsl_rl/train.py \
  --task=RobotLab-Legbot-v0 \
  --headless \
  --num_envs 4096 \
  --max_iterations 300000 \
  --experiment_name legbot_moe_cts \
  --run_name seed42

18.6 评估和导出

bash 复制代码
python scripts/rsl_rl/play.py \
  --task=RobotLab-Legbot-v0 \
  --checkpoint logs/rsl_rl/legbot_moe_cts/<run_name>/model_<iter>.pt

导出的学生策略内部维护历史缓存,因此部署端只需要持续输入当前单帧观测。

18.7 MuJoCo Sim2Sim

安装:

bash 复制代码
pip install mujoco pygame

在配置中设置策略路径:

yaml 复制代码
policy_path: "{ROOT_DIR}/logs/rsl_rl/legbot_moe_cts/<timestamp>/exported/policy.pt"

运行:

bash 复制代码
python deploy/deploy_mujoco/deploy_legbot.py

切换场景可修改:

yaml 复制代码
xml_path: "{ROOT_DIR}/resources/legbot/flat.xml"

可选场景包括:

text 复制代码
flat.xml
stairs.xml
boxes.xml
stairs_and_slope.xml

19. Sim2Real 数据链路

19.1 训练端输出

训练端需要导出:

  • 网络权重;
  • 观测归一化参数;
  • 观测顺序;
  • 历史长度;
  • 动作缩放;
  • 默认关节角;
  • 关节映射;
  • 策略控制周期;
  • 动作和观测裁剪范围。

缺少任何一项,都可能导致部署端输入与训练端不一致。

19.2 部署端输入构造

部署端单帧观测应严格按训练顺序拼接:

text 复制代码
base_ang_vel
projected_gravity
velocity_commands
joint_pos_rel
joint_vel_rel
last_action

关节位置应使用:

q r e l = q − q d e f a u l t q_{\mathrm{rel}}=q-q_{\mathrm{default}} qrel=q−qdefault

关节速度应乘训练时相同缩放。投影重力必须采用相同四元数顺序和旋转方向。

19.3 历史缓存

对于 10 帧历史,部署端要明确:

  • 新观测放在缓存头部还是尾部;
  • 初始缓存填零还是重复第一帧;
  • episode 重置时是否清空;
  • 输入展平顺序是"按时间"还是"按特征";
  • ONNX 导出是否已在模型内部维护缓存。

PPO-CTS-MOE 导出器说明策略内部维护历史,而 PPO 分支通常需要依据部署配置确认。

19.4 动作输出

推理输出需要经过:

  1. 动作裁剪;
  2. 动作缩放;
  3. 默认关节角偏置;
  4. 关节顺序映射;
  5. 机械限位;
  6. PD 控制;
  7. 电机侧力矩和速度限制。

20. 安全保护

真实机器人不能只依赖策略奖励约束。项目提供 FSM 和多级安全限制。

建议至少包含:

20.1 关节位置限制

q i min ⁡ ≤ q i ≤ q i max ⁡ q_i^{\min}\le q_i\le q_i^{\max} qimin≤qi≤qimax

20.2 关节速度限制

∣ q ˙ i ∣ ≤ q ˙ i max ⁡ |\dot q_i|\le \dot q_i^{\max} ∣q˙i∣≤q˙imax

20.3 力矩限制

∣ τ i ∣ ≤ τ i max ⁡ ( q ˙ i ) |\tau_i|\le \tau_i^{\max}(\dot q_i) ∣τi∣≤τimax(q˙i)

20.4 姿态保护

当横滚或俯仰超过阈值时,退出 RL 状态并进入阻尼或失能状态。

20.5 通信超时

若连续若干周期未收到新状态,应停止发送运动命令,不能继续复用旧动作。

20.6 温度、电压和电流保护

真实电机应监测:

  • 绕组或驱动器温度;
  • 母线电压;
  • 电流;
  • 通信错误码;
  • 编码器异常。

20.7 急停

硬件急停必须独立于 RL、DDS 和主控软件,能够直接切断使能或进入安全阻尼。


21. 常见问题与排查方法

21.1 训练一启动就摔倒

重点检查:

  • 默认关节角是否与模型一致;
  • 重力方向和坐标系;
  • 关节正方向;
  • 初始基座高度;
  • 足端碰撞体;
  • 电机增益;
  • 动作缩放;
  • 关节顺序。

21.2 训练奖励增长,但机器人只抖动

可能原因:

  • 跟踪奖励过大,平滑惩罚过小;
  • 策略通过高频动作利用物理引擎误差;
  • 控制频率与动作延迟不匹配;
  • 关节加速度惩罚权重过小;
  • 电机模型过于理想;
  • 接触参数不合理。

21.3 Isaac Lab 能走,MuJoCo 不能走

依次检查:

  1. 关节顺序;
  2. 默认角;
  3. 动作缩放;
  4. PD 增益;
  5. 控制频率;
  6. 四元数顺序;
  7. IMU 坐标系;
  8. 质量和惯量;
  9. 足端摩擦;
  10. 策略输入归一化。

21.4 MuJoCo 能走,实物前倾

常见原因:

  • 实物质心与 URDF 不一致;
  • 前后腿电机零位不同;
  • 小腿减速比映射错误;
  • IMU 安装姿态未补偿;
  • 实物电机力矩不足;
  • 电池电压下降;
  • 通信延迟大于训练随机化范围。

21.5 ONNX Runtime 找不到动态库

先查找:

bash 复制代码
find /usr /usr/local /opt "$HOME" \
  -name "libonnxruntime.so*" 2>/dev/null

临时加入:

bash 复制代码
export LD_LIBRARY_PATH=/path/to/onnxruntime/lib:$LD_LIBRARY_PATH

长期配置可写入 /etc/ld.so.conf.d/onnxruntime.conf 后执行:

bash 复制代码
sudo ldconfig

必须确认架构:

bash 复制代码
file /path/to/libonnxruntime.so
uname -m

aarch64 系统不能加载 x86-64 动态库。

21.6 显存不足

降低:

  • --num_envs
  • 相机或高度扫描分辨率;
  • 地形数量;
  • 渲染开销;
  • 网络宽度;
  • 历史长度。

训练时使用 --headless

21.7 训练速度异常慢

检查:

  • 是否误启用渲染;
  • GPU Pipeline 是否启用;
  • 环境数是否过少;
  • CPU 是否成为地形生成瓶颈;
  • 日志写盘是否过于频繁;
  • 高度扫描射线数量是否过大;
  • 是否在每步执行 Python 循环。

22. 配置修改入口

22.1 修改机器人模型

PPO 分支:

text 复制代码
legbot_rl_lab/source/unitree_rl_lab/unitree_rl_lab/assets/robots/
legbot_rl_lab/unitree_ros/robots/legbot_description/

PPO-CTS-MOE 分支:

text 复制代码
source/robot_lab/robot_lab/assets/
resources/legbot/
legbot_description/

22.2 修改观测和动作

查找:

text 复制代码
ObservationsCfg
ActionsCfg
JointPositionActionCfg
history_length

22.3 修改奖励

查找:

text 复制代码
RewardsCfg
rewards.py
track_lin_vel
action_rate
base_height
feet_regulation

22.4 修改域随机化

查找:

text 复制代码
EventCfg
randomize_rigid_body_mass
randomize_rigid_body_com
randomize_actuator_gains
push
friction

22.5 修改 PPO 参数

查找:

text 复制代码
rsl_rl_ppo_cfg.py
rsl_rl_cfg.py
num_steps_per_env
num_learning_epochs
num_mini_batches
clip_param
desired_kl

22.6 修改 MoE-CTS

查找:

text 复制代码
teacher_env_ratio
expert_num
latent_dim
load_balance_coef
student_encoder_lr

22.7 修改部署

PPO 分支重点文件:

text 复制代码
deploy/robots/legbot/config/config.yaml
State_RLBase.cpp
Types.h
deploy_safety.h
serial_dds_gateway/

PPO-CTS-MOE 分支重点文件:

text 复制代码
deploy/deploy_mujoco/configs/legbot.yaml
deploy_legbot.py
exporter_cts.py

23. 项目价值

23.1 对算法研究的价值

项目覆盖了四足强化学习中的关键问题:

  • PPO 的并行采样与稳定更新;
  • 历史观测下的隐状态推断;
  • 非对称 Actor-Critic;
  • 教师---学生蒸馏;
  • Mixture of Experts;
  • 课程学习;
  • 域随机化;
  • 真实电机模型;
  • Sim2Sim 和 Sim2Real。

23.2 对工程落地的价值

很多开源项目只提供训练环境,Legbot Lab 进一步提供:

  • 策略导出;
  • C++ 推理;
  • 状态机;
  • DDS 接口;
  • 串口网关;
  • 真实电机和 IMU 接入;
  • 安全保护;
  • 日志与诊断。

这使其更接近一套机器人控制系统,而不是单纯的强化学习示例。

23.3 对自研四足平台的参考意义

自研机器人最困难的部分往往不是训练 PPO,而是统一以下内容:

  • URDF 与实物质量;
  • 仿真和实物关节顺序;
  • 电机方向和减速比;
  • IMU 安装坐标;
  • 控制周期;
  • 通信延迟;
  • 默认关节角;
  • PD 增益;
  • 动作和观测缩放。

该项目的主要参考价值正是在这些接口层。


24. 可继续改进的方向

24.1 统一配置体系

text 复制代码
algorithm:
  type: ppo | moe_cts

deployment:
  backend: onnx_cpp | torchscript_python

这样能共享机器人模型、奖励、域随机化和部署接口。

24.2 加入自动一致性检查

训练导出时自动生成:

  • 观测维度哈希;
  • 关节顺序哈希;
  • 默认角;
  • 缩放系数;
  • 控制周期;
  • 网络输入输出维度;
  • 模型质量和惯量摘要。

部署启动时进行校验,不一致则拒绝进入 RL 状态。

24.3 增加多随机种子评估

至少统计:

  • 平均速度跟踪误差;
  • 摔倒率;
  • 推扰存活率;
  • 单位距离能耗;
  • 足端滑移;
  • 峰值力矩;
  • 不同摩擦和负载下的成功率。

24.4 加入实物系统辨识

可对以下参数做离线或在线辨识:

  • 电机摩擦;
  • 力矩常数;
  • 延迟;
  • 关节零位;
  • 基座质心;
  • 足地摩擦;
  • IMU 偏置。

辨识结果用于缩小域随机化范围,提高策略有效容量。

24.5 MoE 专家可解释性

记录不同地形下门控权重:

g 1 , ... , g 8 g_1,\ldots,g_8 g1,...,g8

分析是否存在专家塌缩,以及某些专家是否与楼梯、坡面、推扰恢复等状态相关。

24.6 安全策略外壳

在 RL 动作外增加安全过滤器,例如:

  • 关节可达性约束;
  • 力矩---速度约束;
  • 基座姿态预测;
  • 控制屏障函数;
  • 异常动作变化率检测。

25. 参考资料

  1. Robot-Nav, legbot_lab

    https://github.com/Robot-Nav/legbot_lab

  2. Hongxi Wang, Haoxiang Luo, Wei Zhang, Hua Chen, Combining Teacher-Student with Representation Learning: A Concurrent Teacher-Student Reinforcement Learning Paradigm for Legged Locomotion

    https://arxiv.org/abs/2405.10830

  3. John Schulman et al., Proximal Policy Optimization Algorithms

    https://arxiv.org/abs/1707.06347

  4. Nikita Rudin et al., Learning to Walk in Minutes Using Massively Parallel Deep Reinforcement Learning

    https://proceedings.mlr.press/v164/rudin22a.html

  5. NVIDIA, Isaac Lab Documentation

    https://isaac-sim.github.io/IsaacLab/

  6. leggedrobotics, rsl_rl

    https://github.com/leggedrobotics/rsl_rl

  7. Google DeepMind, MuJoCo

    https://github.com/google-deepmind/mujoco

  8. Eclipse Foundation, Cyclone DDS

    https://github.com/eclipse-cyclonedds/cyclonedds

  9. wty-yy Tianyang Wu, 开源大佬

    https://github.com/wty-yy/go2_rl_gym


26. 总结

Legbot Lab 的核心意义不只在于"用 PPO 训练四足机器人走路",而在于建立一条可复现的工程链路:

text 复制代码
机器人建模
→ MDP 定义
→ 4096 环境并行训练
→ 历史观测与特权信息
→ 域随机化与课程学习
→ TorchScript/ONNX 导出
→ MuJoCo Sim2Sim
→ C++ FSM 与 DDS
→ 串口电机和 IMU
→ 实物安全运行

默认 PPO 分支更强调部署闭环,PPO-CTS-MOE 分支进一步利用并发教师---学生和专家混合网络,在训练阶段使用完整状态,在部署阶段只依赖可获得的本体观测。

相关推荐
闲研随记17 天前
【文献阅读】BunnyFinder:探寻以太坊共识机制中的激励机制漏洞
区块链·agent·漏洞·以太坊·ppo·incentive flaws
Robot_Nav1 个月前
Franka Panda 机械臂PPO强化学习项目 — 技术文档(已开源)
机械臂·开源项目·ppo·franka panda
Robot_Nav3 个月前
Unitree_RL_Gym项目(1): Legged Gym 项目深度技术解析
ppo·unitree rl·isaac gym
litble3 个月前
如何速成LLM以伪装成一个AI研究者(4)——PPO,GRPO,DAPO,GSPO
人工智能·llm·ppo·grpo·gspo·dapo
星马梦缘3 个月前
强化学习实战8——用PPO打赢星际争霸【整合版】
强化学习·ppo·星际争霸·sc2·starcraft2·sb3
非社会人士3 个月前
RL 系统 Infra 笔记:区分不同模型
强化学习·rlhf·rl·ppo·verl·infra
@BangBang4 个月前
Hyper-Diffusion-Planner(1): 论文解读
自动驾驶·ppo
大傻^5 个月前
强化学习与大模型融合:从理论到机器人实践全解析
机器人·llm·大语言模型·强化学习·urdf·ppo·奖励设计
njsgcs6 个月前
ppo可以不需要提取特征,直接训练ac吗。ppo不知道自己现在在第几步吗
人工智能·ppo