Lite3 强化学习策略迁移:训练迁移 + Sim-to-Sim + ONNX 部署(面向开发者的可执行流程)

本文目标:把“Lite3 强化学习策略从源仓迁移到 OrcaGym 并在 gRPC 仿真里稳定运行”的工作,整理成可按步骤执行的开发者流程。重点是“怎么开始迁移、怎么推进到可验收”,而不是展开每个实现细节。

术语约定(全文统一用法):

相关主仓(用于读者快速定位项目背景):openverse-orca/OrcaGym


1) 选材:为什么选择这套 Lite3 仓库来做 RL 迁移入门

适合做“入门迁移教学”的仓库,通常要满足以下条件:

本例的选材结构正好满足:

对初级开发者的建议:不要从“重新训练”开始,而是从“跑通已有模型并保持行为稳定”开始。能稳定跑通,才能判断“需要调参还是需要再训练”。


2) 如何在仓库里定位“强化学习在哪里”

仓库再大,强化学习相关内容通常都围绕同一条链路组织:

命令(cmd) → 观测(obs) → 策略推理(policy) → 动作(action) → 控制(PD/伺服) → 仿真步进(sim)

定位步骤建议按“从产物到接口”的顺序推进:

2.1 先找策略产物(最快定位 RL 的入口)

检查是否存在以下任意一种“策略产物”:

只要定位到“模型文件 + 加载方式”,基本就能反推观测维度、动作维度、推理频率以及控制层接口。

2.2 再找观测与动作“数据契约”(迁移最关键)

数据契约通常会明确写出:

迁移成败高度依赖这里:只要观测/动作契约不一致,策略行为往往会呈现“能跑但像随机抖动 / 一动就倒 / 方向反了”。

2.3 最后找“控制层”:策略输出如何变成关节力矩

腿式机器人策略多数不是直接输出力矩,而是输出“目标关节位置偏移”,再用 PD 控制生成力矩。定位点包括:

这一步能把“策略在训练时假设了什么控制接口”固定下来,也就确定了迁移端必须复现什么接口。


3) 迁移成功率:先定义“成功”的档位,再估计可预期程度

“迁移成功率”建议按可验收的行为档位定义。不同档位对应不同工作量与可预期程度。

3.1 迁移成功的 4 个档位(从易到难)

3.2 可预期程度(即“成功率”表达方式)

在不改策略权重的前提下:

这套分档的意义是:迁移推进时,先把目标锁定在 S1(可验收、可迭代),避免一开始就以 S3 的标准评估,从而误判“迁移失败”。


4) 迁移流程(主体):按阶段推进,每阶段都有明确产出与验收标准

以下流程把迁移拆成 4 个阶段。每一阶段都有“输入、产出、验收、常见卡点”,以便初级开发者按清单推进。

4.1 阶段 A:把数据契约固化成“迁移合同”

输入:

产出(可整理为单页“迁移合同”):

验收标准:

常见卡点:

4.2 阶段 B:闭环跑起来(S1):离线推理 → gRPC 仿真闭环

输入:

产出:

验收标准(可固定为三步):

常见卡点:

4.2.1 代码怎么写:最小可跑闭环的 5 个模块(可按该结构落地)

迁移实现本质上是在新工程里复刻一条固定的数据链路:

命令(cmd) → 观测(obs, 45) → 策略推理(policy, 12) → 动作适配(action) → 环境 step/render

建议把代码拆成 5 个模块,每个模块只做一件事,便于调试与复用。

模块 1:配置(Config)

职责:把“迁移合同”落成可读的配置对象/字典,至少包含:

关键点:关节顺序必须与 XML 定义一致;policy default 与 neutral 不是同一组角度,不能混用。

模块 2:观测构建(Obs Builder)

职责:从环境/agent 的状态拼出 45 维观测,保持顺序与缩放一致。

实现建议:

模块 3:策略推理封装(Policy Wrapper)

职责:屏蔽 onnxruntime 的输入输出细节,提供一个可调用对象 policy(obs)->action12

实现建议:

模块 4:动作适配(Action Adapter)

职责:把策略输出的 12 维动作转换成环境可接受的 action(通常是归一化后的 [-1, 1])。

典型计算链路:

模块 5:主循环(Runner Loop)

职责:串起 cmd/obs/policy/action/step/render,并控制运行频率。

实现建议:

4.3 阶段 C:sim-to-sim 对齐(S2):先数据 → 再时序 → 再动力学

本阶段的关键是“不要同时改多项”。推荐按三层顺序推进:

验收标准:

常见卡点:

4.4 阶段 D:训练迁移(面向 S3 或定制化需求):重新训练并回灌部署(持续迭代)

当目标从“跑通已有策略”升级到“适配新场景/新动力学/更强鲁棒性”,才进入训练迁移。

输入:

产出:

验收标准:

常见卡点:


5) 附录:

5.1 当前对齐状态(示例:迁移端相对源实现的对齐/差异说明)

已对齐(迁移端与源实现一致或已明确修复):

  1. 左右移动对称性:A 键与 D 键使用完整速度(±0.3 m/s),归一化后为 ±1.0
  2. kd:已对齐为 1.0
  3. 初始高度:已上调约 10cm(示例:0.101 m)
  4. 前进速度:0.5 m/s
  5. 转向速度:±0.785 rad/s

保留差异(有意为之;需明确差异原因与预期影响):

  1. 后退速度:示例中使用 50% 速度(-0.25 m/s)以改善策略对负值命令的响应(如需严格复现,可还原为 -0.5 m/s)
  2. 命令平滑:示例中加入指数移动平均(α=0.3)降低命令突变导致的抖动(进行 sim-to-sim 对齐时,可先关闭平滑,稳定后再逐步打开)
  3. action_scale:示例中统一为 0.25(源实现可能对不同关节采用不同 scale;如出现明显行为差异,可优先回到“关节级 action_scale”对齐)

5.2 频率与控制参数对比(复制文本)

仿真频率对比(节选)

参数 原项目 当前版本 说明
物理时间步长 0.001s (1ms) 0.001s (1ms) ✅ 一致
物理仿真频率 1000 Hz 1000 Hz ✅ 一致
FRAME_SKIP 5 5 ✅ 一致
ACTION_SKIP 4 4 ✅ 一致
策略更新频率 50 Hz 50 Hz ✅ 一致
策略更新时间步 0.02s (20ms) 0.02s (20ms) ✅ 一致

控制循环频率(节选)

参数 原项目 当前版本 说明
PD控制频率 200 Hz 200 Hz FRAME_SKIP=5, 1000/5=200Hz
策略推理频率 50 Hz 50 Hz ACTION_SKIP=4, 200/4=50Hz
实时控制频率 50 Hz 50 Hz 使用 REALTIME_STEP 控制

键盘控制速度(节选)

控制类型 原项目配置 当前配置 实际速度值 归一化后 状态
前进 (W) 0.5 m/s 0.5 m/s 0.5 m/s 1.0 ✅ 一致
后退 (S) -0.5 m/s -0.5 m/s -0.25 m/s -0.5 ⚠️ 降低50%
左移 (A) 0.3 m/s 0.3 m/s 0.3 m/s 1.0 ✅ 一致
右移 (D) -0.3 m/s -0.3 m/s -0.3 m/s -1.0 ✅ 一致
转向速度 (Q/E) ±0.785 rad/s ±0.785 rad/s ±0.785 rad/s ±1.0 ✅ 一致
Turbo倍数 3.0x 3.0x 3.0x - ✅ 一致

保留的差异(设计选择,节选)

差异项 原项目 当前版本 影响
后退速度缩放 -0.5 m/s -0.25 m/s(50%) 降低后退速度
action_scale 不同关节不同 所有关节相同(0.25) 简化处理
地形 terrain_test_usda terrain_ellipsoid_low_usda 无障碍物
命令平滑 指数移动平均(α=0.3) 减少命令突变

5.3 迁移检查清单与架构对比

核心架构对比(节选)

当前架构:

Python仿真 (mujoco_simulation.py) ↕ UDP (端口20001/30010) C++控制器 (rl_deploy) → StateMachine → RLControlStateONNX → PolicyRunner (ONNX Runtime)

目标架构:

Isaac Gym环境 (Lite3类) → compute_observations() (45维) → ONNX Policy / PyTorch Policy → pre_physics_step() (PD控制)

迁移检查清单(节选)

  1. 模型转换
    • MJCF → URDF转换
    • URDF放置在 legged_gym/resources/robots/Lite3/
    • 关节命名和顺序验证
  2. 观测空间
    • 维度:45维
    • 缩放参数:omega_scale=0.25, dof_vel_scale=0.05
    • 顺序:[ang_vel, gravity, cmd, pos, vel, last_action]
  3. 动作空间
    • 维度:12维
    • 缩放:action_scale
    • 默认位置:default_dof_pos
  4. PD控制器
    • kp = 30.0
    • kd = 1.0
    • 控制公式:τ = kp(q_d-q) + kd(dq_d-dq)
  5. 策略模型
    • ONNX模型路径正确
    • 输入维度:45维
    • 输出维度:12维
    • 推理结果验证
  6. 控制频率
    • 物理步长:1ms(DT=0.001)
    • PD 控制频率:( f_{pd} = 1 / (DT \times FRAME_SKIP) )
    • 策略推理频率:( f_{policy} = f_{pd} / ACTION_SKIP )
    • 建议:把这些频率写进“迁移合同”,并在代码里打印出来做自检,避免“表里写 50Hz,实际跑成别的频率”