Files
Mujoco_WASM/context.md
T
chenlin deead17a9a
web-platform-ci / TypeScript, lint, unit, build (push) Has been cancelled
web-platform-ci / Playwright E2E (push) Has been cancelled
feat(training): release V0.8 自调参 Agent
2026-09-02 13:49:34 +08:00

13 KiB
Raw Blame History

Code Context

Files Retrieved

  1. wasm/web_platform/src/simulation/SimulationSession.tslines 1-107)- 仿真步进、控制器生命周期、模型名称解析和 mj_step 前控制写入的核心集成点。
  2. wasm/web_platform/src/simulation/PhysicsAdapter.tslines 12-110- UI 与 session 的稳定门面;模型切换、资源释放和 Go2-W URDF 增强发生于此。
  3. wasm/web_platform/src/app/App.tsxlines 37-78, 100-105- 工程导入、控制器状态、错误反馈、右侧栏 wiring。
  4. wasm/web_platform/src/app/components/SidebarPanel.tsxlines 19-35- 当前“控制”tab 仅嵌入 Python 控制器,是 ONNX 面板的最小 UI 插槽。
  5. wasm/web_platform/src/controller/PythonControllerRuntime.tslines 30-120)- 可复用的控制器生命周期/状态设计;同时揭示现有控制回调必须同步。
  6. wasm/web_platform/src/controller/types.tslines 1-42)- 当前状态被写死为 language:'python',且 step API 可读关节、sensor、body quaternion。
  7. wasm/web_platform/src/project/importer.tslines 1-48, 184-223- 所有二进制文件已原样进入 manifest,ONNX 无需进入模型 entry 发现逻辑。
  8. wasm/web_platform/src/project/types.tslines 1-41- ProjectFile/大小上限;单文件允许 128 MiB、工程 512 MiB。
  9. wasm/package.jsonscripts/dependencies- 已有 Vitest/Playwright,尚无 onnxruntime-web
  10. wasm/web_platform/vite.config.tslines 1-27- Pyodide 本地资产复制是 ORT wasm 离线资产处理的直接范例。
  11. wasm/src/go2_w_balance.pylines 1-约480- 仓库已有 Go2-W 手写 200 Hz 平衡/轮速控制,可作模型命名、IMU 和安全回退参考,但不是 RL 策略。
  12. /home/cen/Embodied_Workspace/unitree_rl_mjlab/deploy/robots/go2/config/policy/velocity/v0/params/deploy.yamllines 1-56)- 部署时序、动作变换及精确 observation 顺序。
  13. /home/cen/Embodied_Workspace/unitree_rl_mjlab/deploy/robots/go2/src/State_RLBase.cpplines 6-31- 部署约定为 params/deploy.yaml + exported/policy.onnx,输出经 action manager 处理后按 joint map 下发。
  14. /home/cen/Embodied_Workspace/unitree_rl_mjlab/src/tasks/velocity/config/go2/env_cfgs.pylines 1-约160- flat 任务移除 height scanGo2 base 为 base_link

Key Code

已有正确插入顺序

SimulationSession.singleStep/advance 均执行:控制器 → 外力 → mj_stepSimulationSession.ts:46-57)。ONNX 动作必须沿用该位置,而不能在 React frame snapshot 后直接写 ctrl,否则会引入一物理步延迟和不稳定的渲染帧时序。

参考部署契约

Go2 deploy YAML 定义:

  • step_dt: 0.02,即策略 50 Hz;仿真步可保持 0.002 s,动作 hold 10 步。
  • observation 串接顺序和维数:base_ang_vel(3), projected_gravity(3), velocity_commands(3), gait_phase(2), joint_pos_rel(12), joint_vel_rel(12), last_action(12),总计 47 float32
  • action 为 12 维位置目标:processed = raw * 0.25 + default_joint_pos;默认位姿见 YAML lines 3-5/18-20。
  • joint 顺序不能取 MuJoCo ID 偶然顺序;部署 joint_ids_map=[3,4,5,0,1,2,9,10,11,6,7,8] 表示 RL 顺序与硬件/模型顺序存在显式重排。
  • ONNX 与参数是配套件:params/deploy.yaml + exported/policy.onnxState_RLBase.cpp:12-16)。仅导入 .onnx 无法可靠解释 observation/action。

最小文件级实现方案(建议,不修改)

  1. 新增独立策略层src/policy/types.ts, OnnxPolicyRuntime.ts, Go2VelocityTask.ts
    • OnnxPolicyRuntime 只负责 ORT session、输入/输出名称与 shape 校验、generation cancellation、dispose。
    • Go2VelocityTask 固化首个 task 的 47→12 契约、命令/phase/lastAction、名称到 joint/actuator 的显式映射、PD 目标或 position actuator 输出。
    • 不应把 ONNX 逻辑塞入 PythonControllerRuntime;其 Pyodide proxy 与同步函数假设完全不同。
  2. SimulationSession.ts:将单一 pythonController 最小泛化为互斥 controller slot,或新增 onnxPolicy 并在同一个 runController() 中互斥调度;load/remove/reset/dispose 复用 generation 防模型切换竞态。添加只读 observation helpers(按 joint/body/sensor 名称解析),避免 UI 从 snapshot 拼向量。禁用/异常时必须 ctrl.fill(0)、暂停并保留错误。
  3. 异步风险处理onnxruntime-websession.run() 返回 Promise,不能直接 await 于当前同步 advance() while loop。最小侵入方案是“最新完成动作 hold”:到 50 Hz 时复制 observation 发起一次推理(仅允许一个 in-flight),后续物理步继续持有上次动作,完成后原子替换;首帧保持安全默认位姿而非零力矩。状态须显示 inference latency/overrun。若要求训练等价的严格每 20 ms 动作,则需把物理 loop 改为异步/worker,已非最小侵入。
  4. PhysicsAdapter.ts:接口新增 loadOnnxPolicy(policyBytes, config), setPolicyEnabled, setVelocityCommand, removePolicyMainThread adapter 只转发,模型 releaseCurrent() 自动 dispose。不要把 policy 写入 MuJoCo MEMFSORT 可直接吃 Uint8Array
  5. 项目导入importer.ts 已保留任意扩展名,ZIP/目录中的 .onnx/.yaml 会存在 manifest.files;无需修改 discoverEntries(它只应发现模型)。在 App 中按配套目录约定寻找 exported/policy.onnxparams/deploy.yaml,首版更稳妥的是新增浏览器可直接解析的 JSON policy manifest;不要为 YAML 引入重量解析器后猜测任意训练配置。独立单文件导入应沿用 Python 的 upsert 流程,但 accept 改 .onnx 并施加专用上限。
  6. 依赖/构建wasm/package.jsononnxruntime-webvite.config.ts 仿照 Pyodide 将 ORT wasm 文件复制到固定相对目录并设置 ort.env.wasm.wasmPaths,否则离线 base:'./' 构建容易 404。首版使用 wasm CPU 单线程,避免 WebGPU/COOP-COEP 扩大范围。
  7. UI:新增 PolicyPanel.tsx,插在 SidebarPanel.tsx:32 的控制 tab,与 Python 控制器并列;展示模型/config、47×12 shape、50 Hz、启停、速度 x/y/yaw、推理耗时/错误。App.tsx:40,55,72-77,104 按现有 controller 状态模式增加 policy 状态及 callbacks;加载另一控制器时明确移除/禁用前一个,不能二者同时写 ctrl。
  8. 首个 Go2-W 任务边界:参考仓库提供的是 Go2 12-DOF velocity policy,不是 Go2-W policyGo2-W 多四个轮关节。首版可把 12 个腿关节按该 policy 控制、轮 actuator 固定阻尼/零速,仅称“Go2-W 腿式站立/速度实验”,不能宣称与训练分布一致。真正轮式平衡/速度需要 Go2-W 专属训练导出(observation/action 很可能含轮速和 16 维动作)。

Architecture

浏览器文件 → ProjectManifest.files(二进制 ONNX 已保留)→ App 选择配套 policy/config → PhysicsAdapterSimulationSession 拥有 policy runtime。每个 MuJoCo 子步前 task 从 MjData 组 observation;每 0.02 s 异步提交 ONNX,完成输出经 scale/offset、显式 joint mapping 和限幅后成为 held action;物理 loop 每步应用 held action。snapshot 仅向 UI报告状态,不作为 observation 数据源。

观测/动作风险与严重度

  • blocker:参考资产无 Go2-W ONNX,且仓库参考目录下 Go2 velocity 的 exported/policy.onnx 实际不存在;不能验证 input/output 名或数值一致性。
  • blockerGo2 12-DOF policy 与 Go2-W 16 actuator 拓扑不匹配。若按 model.njnt/nactuator 顺序拼接会 shape 错误或静默错控。
  • highprojected_gravity 必须是重力单位向量由世界系旋到 body/IMU 局部系。MuJoCo xquat 为 wxyz;符号、quat inverse、IMU 安装姿态任一错误都会使策略立刻摔倒。加速度计并不等价于无噪声 projected gravity。
  • highbase_ang_vel 需 body/local frame;直接使用 free joint qvel[3:6] 或 gyro sensor前必须确认 MuJoCo sensor frame与训练定义一致。
  • highjoint_pos_rel = q-defaultjoint_vel 和 action 都必须是 YAML 的 RL 顺序;四足 FL/FR/RL/RR 次序在当前手写 Go2-W controller 与 deploy map 中并不天然一致。
  • high:输出是 normalized action,不是 torque;必须 scale+offset 后交给 position actuator/PD。当前 setActuator 只写 ctrlURDF 自动生成的是 motorPhysicsAdapter.ts:68),因此若直接写位置值会被当 N·m。需要 task 内 PD torque,或为该 task 构造 position actuator。
  • mediumgait phase 是 0.6 s 周期的 sin/cos,但应确认零点、sin/cos 顺序以及站立零命令时是否冻结;YAML 没编码完整函数语义。
  • medium:异步 ORT latency 若超过 20 ms 会跳过策略 tick;必须统计 dropped/late inference,且避免并发堆积。
  • mediumreset 应同时清 lastAction、phase、in-flight generation 和 held action;否则旧 Promise 可污染新 episode。
  • medium:导入不可信 ONNX 可能造成大内存/计算消耗;现有 128 MiB 文件上限不足以约束 tensor shape/运行时内存。

测试建议

  1. src/policy/Go2VelocityTask.test.ts:固定 qpos/qvel/quaternion/command,逐元素断言 47 维顺序、dtype、projected gravity、phase、joint reorder;固定 raw action 断言 *0.25+offset 和 actuator 映射。
  2. src/policy/OnnxPolicyRuntime.test.tsmock ORT,覆盖 input/output shape/name 错误、NaN/Inf、single-flight、超时/overrun、generation cancellation、dispose;用极小 identity ONNX fixture 做一次真实 wasm smoke test。
  3. 新增 SimulationSession.test.ts(当前该核心类无测试):mock MainModule 验证 controller 在 mj_step 前执行、50 Hz decimation、held action、reset/disable/error 清 ctrl、Python/ONNX 互斥、模型切换后旧推理无效。
  4. PhysicsAdapter contract testload/remove/dispose 转发及失败后 workspace/runtime 都释放。
  5. importer.test.tsZIP/目录保留 .onnx 与 config、路径规范化、重复/超限拒绝;entry discovery 不把 ONNX 当模型。
  6. PolicyPanel.test.tsx + SidebarPanel 测试:导入、启停、命令范围、shape/错误展示、另一控制器启用时互斥。
  7. Playwright:导入 Go2-W 工程+fixture policy,启用后推进若干秒,断言页面不崩、policy 状态与命令变化;数值验收应另做离线 golden trajectory(相同初态前 N 次 observation/action 与 Python/ORT reference 对齐),容差逐元素约 1e-5,并检查 base height/倾角安全阈值。
  8. 常规命令:npm run typecheck:platform, npm run lint:platform, npm run test:platform, npm run build:platform, 最后 npm run test:e2e:platform

Start Here

先打开 wasm/web_platform/src/simulation/SimulationSession.ts:44-93:这是唯一能保证 observation 采样、控制输出和 mj_step 顺序正确,并统一 reset/error/dispose 语义的位置。

Residual Risks

  • 未获得 Go2-W 专属 ONNX 与导出 metadata,无法完成真实 shape/name/golden 验证。
  • unitree_rl_mjlab 的 YAML 说明字段顺序与缩放,但 gait phase、frame convention 等函数语义仍需用实际导出/运行器确认。
  • 主线程异步 inference 的 held-action 方案是最小侵入折衷,不提供硬实时或训练环境严格等价。
{
  "criteriaSatisfied": [
    {
      "id": "criterion-1",
      "status": "satisfied",
      "evidence": "已给出 SimulationSession、PhysicsAdapter、App/Sidebar、导入与测试结构的具体文件/行范围方案,并按 blocker/high/medium 列出观测动作风险。"
    }
  ],
  "changedFiles": [],
  "testsAddedOrUpdated": [],
  "commandsRun": [
    {
      "command": "find/grep/read/nl(只读仓库与 unitree_rl_mjlab 参考配置)",
      "result": "passed",
      "summary": "确认现有控制步序、项目导入行为、测试布局及 Go2 deploy 的 47维观测/12维动作约定。"
    }
  ],
  "validationOutput": [
    "参考 deploy.yaml: step_dt=0.02,观测 3+3+3+2+12+12+12=47,动作 12scale=0.25。",
    "参考部署约定为 params/deploy.yaml + exported/policy.onnx;当前 Go2 目录未发现实际 ONNX。",
    "当前仓库 package dependencies 未包含 onnxruntime-web。"
  ],
  "residualRisks": [
    "缺少 Go2-W 专属 ONNX/metadata,参考仅为 Go2 12-DOF。",
    "异步浏览器 ORT 与同步物理 loop 存在时序折衷。",
    "projected gravity、角速度 frame、joint mapping 必须做 golden 对齐。"
  ],
  "noStagedFiles": true,
  "diffSummary": "只读分析;未修改仓库文件,仅写入指定 context.md 报告。",
  "reviewFindings": [
    "blocker: /home/cen/Embodied_Workspace/unitree_rl_mjlab/deploy/robots/go2 - 未发现 Go2 velocity policy.onnx,无法验证模型 I/O。",
    "blocker: deploy.yaml:1-56 - 参考策略为 12-DOF Go2,与 Go2-W 16 actuator 不匹配。",
    "high: wasm/web_platform/src/simulation/SimulationSession.ts:49-57 - 同步物理 while loop 无法直接 await ORT Promise。",
    "high: wasm/web_platform/src/simulation/PhysicsAdapter.ts:68-70 - URDF 自动生成 motornormalized position action 不可直接写 ctrl。"
  ],
  "manualNotes": "报告已写入权威路径;除 context.md 外未改动项目。"
}