Files
Mujoco_WASM/Plan.md
T
chenlin 1eb05132f1
build / setup (compute matrix) (pull_request) Has been cancelled
build / ${{ matrix.label }} (pull_request) Has been cancelled
build / macos-15-arm64-studio (pull_request) Has been cancelled
build / ubuntu-24.04-clang-18-studio (pull_request) Has been cancelled
build / ubuntu-24.04-gcc-14-studio (pull_request) Has been cancelled
build / windows-2025-ninja-studio (pull_request) Has been cancelled
build / ubuntu-24.04-clang-18-wasm (pull_request) Has been cancelled
build / ubuntu-24.04-clang-18-mjx (pull_request) Has been cancelled
lint / pre-commit (pull_request) Has been cancelled
feat: add browser-based MuJoCo simulation platform
2026-08-20 15:12:08 +08:00

15 KiB
Raw Blame History

MuJoCo Web 仿真平台实施计划

计划状态 MVP 已实施并通过自动化验证
进度维护规则:实施时将阶段/任务复选框由 [ ] 更新为 [x],并同步“进度看板”中的状态、完成日期与备注。

Context

目标是在本仓库官方 wasm/ JavaScript/TypeScript 绑定和 Three.js 示例之上,建设一个纯浏览器 MuJoCo 仿真平台,支持模型工程上传、浏览器内文件组织、模型加载、三维展示、仿真控制和状态查看,交互布局参考 urdf.enkeebot.com

已确认的仓库基础:

  • wasm/dist/ 有本地构建的绑定产物,但当前 build/CMakeCache.txt 显示其启用了线程;MVP 因此使用同版本官方 @mujoco/mujoco 默认单线程入口。
  • wasm/demo_app/ 已有 Vite + TypeScript + Three.js 的最小示例,可作为加载、场景构建与逐帧同步的起点。
  • 官方绑定要求显式调用 .delete() 管理 Embind/C++ 对象生命周期。
  • 官方同时支持默认单线程入口与需要 COOP/COEP 的多线程入口;MVP 已确定使用默认单线程入口。

Scope / MVP 边界

  • 技术栈React + TypeScript + Zustand + Vite + TailwindCSS + Three.js。
  • 输入:单个 MJCF/XML、单个 URDF、保留相对路径的文件夹、ZIP 工程;关联 mesh/贴图随工程导入。
  • 编辑边界:首版只负责导入、查看和仿真,不提供 XML 编辑、热重载、工程保存或导出。
  • 物理执行:首版使用主线程、单线程 mujoco.wasm;模块边界保留未来迁移 Worker 的能力,但不在 MVP 实现 Worker。
  • 控制优先级:actuator 滑杆、关节拖动、外力施加,另含播放、暂停、单步、重置和速度控制。
  • 部署边界:桌面浏览器中的中文界面,通过本地静态 HTTP 服务器运行;无 PWA、账号、后端、云存储或分享服务,导入工程仅驻留当前浏览器会话内存。
  • 非目标URDF/MJCF 互转、Xacro 展开、控制脚本、轨迹编辑与多线程 WASM。

Approach

已采用 React + TypeScript + Vite + TailwindCSS + Three.js,在 wasm/web_platform/ 新增独立平台应用,复用官方 WASM 包和示例逻辑,未改动 MuJoCo 核心绑定或生成产物。

初步分层:

  1. UI / 工程层:工程导入、资源树、属性/控制面板、全局状态和错误展示。
  2. 应用服务层:工程文件规范化、入口模型识别、仿真会话生命周期、命令调度。
  3. 物理层:封装 MjModelMjData、step/reset/ctrl,并集中管理 .delete()
  4. 文件系统层:将上传文件按相对路径写入 Emscripten MEMFS,校验引用与加载错误。
  5. 渲染层:Three.js 场景、相机、灯光、MuJoCo primitive/mesh 映射和逐帧位姿同步。
  6. 交互控制层Three.js Raycaster 完成选择;关节拖动映射到 qpos 并调用 mj_forward,外力拖拽通过 MjvPerturb/mjv_applyPerturbForce 在 step 前施加。
  7. 线程边界:MVP 直接调用主线程单线程绑定,但通过 PhysicsAdapter 隔离 UI,未来可在不改 UI 的情况下迁移 Worker。

数据流、错误与生命周期

  • 数据流File/Directory/ZIP → 路径校验与入口识别 → MEMFS workspace → mj_loadXMLSimulationSessionmjv_updateScene/状态快照 → Three.js 与 Zustand UI。
  • 状态边界:Zustand 只保存可序列化的工程元数据、控制参数、选择和 UI 状态;MjModel/MjData/Three.js 实例由服务对象持有,避免 React 重渲染复制 WASM 视图。
  • 错误模型:按导入、ZIP、文件系统、模型编译、仿真、渲染分类,统一包含中文摘要、阶段、相关路径和原始错误;致命错误停止当前会话但保留工程树供排查。
  • 生命周期:新模型采用“先释放旧渲染资源和 Embind 对象 → 清理旧 workspace → 写入新工程 → 创建新会话”的串行切换;所有失败分支使用 finally 回收已创建对象。

Files to modify

  • Plan.md:计划与持续进度记录。
  • wasm/demo_app/app.ts:只读复用来源,原则上不直接扩建为平台。
  • wasm/package.jsonwasm/package-lock.json:加入 React、Zustand、TailwindCSS、fflate、Vitest、Playwright 及平台脚本。
  • wasm/web_platform/index.htmlwasm/web_platform/vite.config.ts:平台入口、WASM 静态资源定位和相对路径静态部署配置。
  • wasm/web_platform/src/app/:React 壳层、布局、全局错误边界与启动流程。
  • wasm/web_platform/src/stores/:Zustand 工程、仿真、选择和 UI 状态切片。
  • wasm/web_platform/src/project/:文件/目录/ZIP 导入、路径规范化、入口识别和 MEMFS 工作区。
  • wasm/web_platform/src/simulation/WASM 初始化、PhysicsAdapterSimulationSession、步进和控制命令。
  • wasm/web_platform/src/viewer/Three.js renderer、MuJoCo 场景适配、拾取、关节拖动和外力交互。
  • wasm/web_platform/src/**/*.test.ts(x)wasm/web_platform/e2e/wasm/web_platform/fixtures/:单测、浏览器测试与示例工程。
  • @mujoco/mujoco:作为默认单线程构建输入;wasm/dist/* 未手工修改。

Reuse

  • wasm/demo_app/app.ts:复用 loadMujoco() 初始化、mjv_updateScene 场景提取、Z-up 相机、固定仿真时长步进、矩阵同步和确定性释放思路;现有 getBufferGeometry 仅覆盖 plane/sphere/capsule/box/cylinder/ellipsoidmesh 与贴图需补齐,且不可直接复制其全局 app/DOM 写法。
  • wasm/demo_app/vite.demo.config.ts:复用 root、相对 base、独立输出目录和开发响应头模式;MVP 单线程不依赖 COOP/COEP。
  • wasm/tests/bindings_test.ts:复用 FS.writeFile/unlinkMjModel.mj_loadXML(path)MjVFS.addBuffer、带外部 OBJ 的加载测试以及 finally + .delete() 生命周期范式。
  • @mujoco/mujoco 类型:使用 MjModel/MjData typed-array 视图、named accessor、MjvPerturbmjv_applyPerturbForce 等 API;避开 bool typed-memory-view 的绑定限制,并显式删除 accessor。
  • doc/overview.rstdoc/modeling.rstdoc/APIreference/functions_override.rstMuJoCo 原生 mj_loadXML 可解析 MJCF 与 URDFVFS 可容纳 XML/include、STL、PNG 等资源,因此 URDF 不另做平台侧转换。
  • 参考站点仅复用信息架构理念:本地导入、3D 视口、关节树/属性与控制面板;MVP 不复刻其编辑、格式转换或云端工具能力。

Steps

进度看板

阶段 状态 完成度 完成日期 备注
0. 需求与架构定稿 🟢 已完成 100% 当前 产品边界、交互语义和架构已确认
1. 应用骨架与质量基线 🟢 已完成 100% 当前 typecheck、lint、Vitest、Playwright、build 通过
2. 工程导入与 MEMFS 🟢 已完成 100% 当前 单/多文件、目录、ZIP、安全限制与入口选择
3. MuJoCo 会话与仿真控制 🟢 已完成 100% 当前 主线程单线程、固定步进、控制与确定性释放
4. Three.js 可视化与交互 🟢 已完成 100% 当前 primitive/mesh/texture、拾取、关节与外力交互
5. 平台 UI 与状态管理 🟢 已完成 100% 当前 中文桌面布局、面板、属性和状态栏
6. 性能、健壮性与交付 🟢 已完成 100% 当前 预算保护、夹具/E2E、静态部署文档

0. 需求与架构定稿

  • 确认 React + Zustand,采用 Vitest + Playwright;仅支持桌面版 Chrome/Edge/Firefox 最新两个大版本。
  • 确认 MVP 输入格式为 MJCF/XML、URDF、文件夹和 ZIP;工程入口规则见后续步骤。
  • 确认 MVP 使用主线程、单线程 WASM,不实现 Worker/MT。
  • 明确参考站点只借鉴本地导入、工程树、中心视口、属性/控制面板的信息架构。
  • 输出模块边界、数据流、错误模型和资源生命周期设计。

1. 应用骨架与质量基线

  • 创建独立平台应用入口、Vite 配置、TailwindCSS 和基础布局。
  • 配置 TypeScript 严格检查、lint、单元测试与最小 E2E 测试。
  • 配置 WASM 静态资源定位及开发/生产构建路径,保持 base: './' 以支持任意静态子路径。
  • 验证本地静态 HTTP 服务器可正确提供 JS/CSS/WASM;不支持直接以 file:// 打开,也不注册 service worker。
  • 建立错误边界、加载状态、日志和中文可诊断错误展示。

2. 工程导入与 MEMFS

  • 定义 ProjectFile、虚拟路径、入口模型和资源清单模型。
  • 支持单文件、多文件和目录拖放/选择,保留 webkitRelativePath;使用 ZIP 库在浏览器内解包 .zip,拒绝加密包、目录穿越和超限压缩内容。
  • 统一 /workspace/<project-id>/... 虚拟根目录,规范化路径后通过 FS.mkdirTree/writeFile 写入 MEMFS;二进制文件保持 Uint8Array,文本 XML 使用 UTF-8。
  • 入口规则:单个 XML/URDF 自动选中;多候选优先根目录 model.xml/scene.xml/唯一 .urdf,否则弹窗选择且按根元素 <mujoco>/<robot>标识类型。
  • 使用 MjModel.mj_loadXML(entryPath) 让 MuJoCo 原生解析 MJCF/URDF 及相对资源;加载失败保留工程树并展示入口、资源路径和 MuJoCo 错误。
  • 切换工程前按逆序释放会话对象,再递归删除 MEMFS 工作区;对文件数、单文件、解压总量设置可配置上限。
  • 为 MJCF include + OBJ/STL/PNG、URDF + mesh、目录、ZIP、路径冲突和缺失资源添加测试夹具。

3. MuJoCo 会话与仿真控制

  • 封装 WASM 单例初始化和 SimulationSession 生命周期。
  • 创建/销毁 MjModelMjData,实现异常路径下的确定性释放。
  • 实现播放、暂停、单步、重置、时间倍率、固定步长累积器。
  • 实现 actuator 控件和 qpos/qvel/ctrl 等状态快照。
  • 实现同步 PhysicsAdapter 接口并保持 UI 不直接持有 Embind 对象;Worker/message protocol 仅记录为后续扩展点。

4. Three.js 可视化与交互

  • 复用官方 demo 的 primitive 构建与 mjv_updateScene 方法,抽离为可测试的场景适配器。
  • 支持 MuJoCo primitive;对 mesh 根据 mjvGeom.dataid 读取 mesh_vert/face/normal/texcoord 及地址/数量数组构建缓存的 BufferGeometry,并从 tex_data/width/height 创建纹理,覆盖材质和坐标/矩阵转换。
  • 每帧同步动态 body/geom 位姿,避免重复分配临时对象。
  • 实现 OrbitControls、相机复位、网格/坐标轴、灯光和 resize。
  • 用 Raycaster 实现对象拾取、选中高亮及与属性面板联动,并维护 Three.js object → MuJoCo body/geom id 映射。
  • 关节拖动仅对可直接编辑的 hinge/slide joint 开放:暂停仿真、按 joint axis 将拖动量写入对应 qpos、按 jnt_range 限位并执行 mj_forwardfree/ball joint MVP 只读。
  • 外力施加:选中动态 body 后以拖拽箭头显示方向/大小,在每个 mj_step 前通过 MjvPerturb/mjv_applyPerturbForce 施力,松开即清零,并提供强度刻度。
  • 在模型切换/卸载时释放 geometry、material、texture、Embind 临时 accessor/vector 和渲染循环资源。

5. 平台 UI 与状态管理

  • 搭建参考站点式布局:顶部工具栏、左侧工程树、中心视口、右侧属性/控制面板、底部状态区。
  • 实现 MJCF/XML、URDF、文件夹、ZIP 导入流程、入口选择、最近错误、加载进度与空状态。
  • 实现播放/暂停/单步/重置/速度控件、基于 actuator_ctrlrange 的 actuator 滑杆,以及 joint 拖动/外力模式开关。
  • 实现模型信息、body/joint/geom 属性检查器。
  • 针对桌面宽屏提供可调整/折叠面板、中文文案、键盘操作和基本无障碍语义;手机和平板不在 MVP 验收范围。

6. 性能、健壮性与交付

  • 建立 FPS、step 耗时、模型规模和内存趋势监控。
  • 验证大模型、资源缺失、无效 XML、重复加载和长时间运行。
  • 对主线程 step 设置每帧预算与最大追赶步数,超预算时显示性能警告而非无限追帧;Worker/SharedArrayBuffer 留作后续版本。
  • 完成生产构建、纯静态部署/离线使用说明、示例工程和用户文档。
  • 更新本计划进度看板并记录遗留项。

Implementation Result

  • 平台代码:wasm/web_platform/;使用 @mujoco/mujoco@3.11.0 默认单线程入口。
  • 自动化结果:TypeScript、ESLint、10 个 Vitest 测试、5 个 Chrome Playwright E2E、生产构建均通过。
  • E2E 覆盖:单文件 MJCF、MJCF include + OBJ/STL/PNG、URDF + OBJ、中等规模持续步进/重复加载、无效模型错误保留;另用完整 Go2W ZIP 实测 ROS package://、重复 material 和 DAE 降级后可编译。
  • 静态服务验证:Python HTTP server 对 HTML 与 WASM 均返回 200WASM MIME 为 application/wasm
  • 依赖审计:npm audit 0 vulnerabilities。

遗留验收项

  • Edge/Firefox 最新版本尚未在当前环境做人工交互验收。
  • 关节拖动、外力箭头与超大模型的视觉手感仍需结合真实机器人工程人工调参。
  • 当前构建有约 865 KiB JS chunk 的 Vite 体积警告;不影响 MVP,后续可按面板/Three.js 做代码分割。
  • E2E 的持续步进是秒级冒烟;发布前建议增加 30–60 分钟内存与稳定性 soak test。

Verification

  • 自动化:TypeScript 类型检查、单元测试、构建测试、浏览器 E2E 冒烟测试。
  • 导入:MJCF/URDF 与其 mesh/texture 相对引用可加载;缺失/冲突/非法路径给出可定位错误。
  • 物理:播放、暂停、单步、重置和 actuator 控制结果符合 MuJoCo 时间步;重复加载无悬挂循环。
  • 渲染:primitive/mesh 位姿与 xpos/xquat 一致,相机和选中交互稳定,窗口缩放正常。
  • 生命周期:连续切换模型和长时间仿真时,WASM/Three.js 资源无持续异常增长。
  • 浏览器:桌面版 Chrome、Edge、Firefox 最新两个大版本完成手工验收;不测试手机、平板和多线程模式。
  • 交付:生产构建可由本地静态 HTTP 服务器启动,.wasm MIME 与相对资源路径正确;明确 file:// 不受支持。

Confirmed Decisions

  1. React + Zustand。
  2. MVP 支持 MJCF/XML、URDF、文件夹、ZIPURDF 交由 MuJoCo 原生 loader 解析。
  3. 首版不做 XML 编辑、热重载和工程导出。
  4. 首版主线程单线程 WASM。
  5. 纯静态、离线应用,无后端和账号体系。
  6. 首版交互优先 actuator 滑杆、关节拖动、外力施加;关节拖动时暂停且仅支持 hinge/slide,外力拖拽期间持续施加、松开清零。
  7. 仅支持桌面浏览器,中文界面;多个入口由用户弹窗选择。
  8. 通过本地静态 HTTP 服务器运行,不实现 PWA。