Files
Mujoco_WASM/plans/map-v3-design.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

194 lines
6.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# MuJoCo Web 地图导入与编辑设计
> 状态:V1/V2 与 V3 地图编辑能力已实现。当前阶段只聚焦地图导入、可视化、受约束编辑、事务应用和地图包导出。
## 1. 目标
平台在不修改 `@mujoco/mujoco` WASM 内核的前提下,支持:
1. 内置 MJCF 物理地图:平地、坡道、楼梯和随机障碍物。
2. 工程地图包:`map.json`、简化 MJCF 碰撞层、可选自包含 GLB 视觉层和出生点。
3. Schema V2 创作层:通过 `map.scene.json` 编辑受支持的静态原语。
4. 将完全可识别的只读静态 MJCF 显式转换为可编辑副本。
5. 在浏览器中事务式重新编译,并导出独立地图 ZIP。
当前阶段不扩展机器人运动控制或其他地图上层应用。
## 2. 坐标与分层
所有地图统一使用:
- 米制;
- Z-up
- 右手坐标系;
- `+X` 前方;
- 物理层、视觉层、创作层和出生点共享世界原点。
地图拆分为三类资产:
- `physics/world.xml`:MuJoCo 使用的简化静态碰撞层;
- `visuals/scene.glb`:Three.js 使用的高精度视觉层;
- `authoring/map.scene.json`:编辑器的规范源。
高面数视觉模型不得直接作为大型地图碰撞网格。
## 3. 地图包结构
```text
maps/warehouse/
├── map.json
├── physics/
│ ├── world.xml
│ └── meshes/*.obj
├── visuals/
│ └── scene.glb
└── authoring/
└── map.scene.json
```
Schema V1 支持物理层、视觉层和出生点。Schema V2 增加创作层:
```json
{
"schemaVersion": 2,
"id": "warehouse",
"name": "仓库",
"coordinateSystem": { "units": "m", "up": "Z", "forward": "+X" },
"physics": { "source": "physics/world.xml" },
"visual": { "source": "visuals/scene.glb" },
"authoring": { "source": "authoring/map.scene.json" },
"spawnPoints": [
{ "id": "main", "name": "主入口", "position": [0, 0, 0.35], "yawDeg": 0 }
]
}
```
声明 `authoring.source` 时必须同时声明 `physics.source`
## 4. 安全导入
所有地图文件必须进入 `ProjectManifest``MemfsWorkspace`,禁止运行时直接读取任意主机路径。
资源引用必须拒绝:
- HTTP/HTTPS 和其他协议;
- 绝对路径、UNC、盘符路径;
- NUL、编码绕过和路径穿越;
- 不存在的工程资源;
- 重复路径及超出导入配额的文件。
视觉层仅支持自包含 GLB 2.0。暂不支持外部 glTF 依赖、Draco、KTX2 或视觉层隐藏坐标修正。
## 5. 物理地图约束
工程物理层只允许静态 `worldbody` 和必要的基础 asset。拒绝:
- joint 和动态 body
- mocap
- actuator、sensor、tendon、equality
- include
- default class
- 依赖不兼容 compiler 角度语义的姿态;
- 无法安全重写的资源路径。
地图碰撞 geom 使用 `group="2"`,并通过稳定命名空间 `__platform_map_<mapId>_...` 与机器人隔离。
## 6. 创作文档
`map.scene.json` 是唯一编辑规范源,支持:
- box
- cylinder
- capsule
- ramp
- stairs
- 出生点。
每个对象包含稳定 ID、名称、类型、世界位姿、原语参数、摩擦、颜色和启用状态。对象不超过 2,000 个,出生点不超过 500 个,生成 geom 不超过 10,000 个。
`MapDocumentCompiler` 根据创作文档确定性生成 `physics/world.xml`。生成结果只使用 quaternion,不依赖 Euler 角。
## 7. 编辑交互
地图面板提供“场景 · 资产库 → 认证资产”入口。用户可以点击添加,或把资产卡片拖到画布的 XY 平面落位;落点按 0.1 m 归一化并根据原语尺寸自动贴地。当前没有可编辑地图时,首个资产会立即创建 `map.json`、空物理层和创作层骨架,切换到新场景并作为未应用草稿进入 Three.js 预览;此阶段不调用 MuJoCo。用户点击“应用并重新编译”后才生成并事务提交实际物理层。
React 中的 `MapEditSession` 是草稿唯一来源。Three.js 预览层只负责:
- 草稿原语显示;
- 射线拾取和高亮;
- 世界坐标平移;
- 绕世界 Z 轴旋转;
- 原语尺寸缩放;
- 出生点预览;
- 操纵器和临时资源生命周期。
交互规则:
- `W`:移动;
- `E`:旋转;
- `S`:缩放;
- `Delete`/`Backspace`:删除;
- `Escape`:取消选择;
- `Ctrl+Z`:撤销;
- `Ctrl+Y``Ctrl+Shift+Z`:重做。
拖动 TransformControls 操纵轴期间禁用 OrbitControls;在画布空白区域按住鼠标左键仍可旋转相机。连续拖动只在 `mouseUp` 时提交一次历史记录。缩放必须写回原语参数,不能把 Three.js 节点 scale 作为持久数据。
## 8. 只读地图转换
外部 MJCF 默认只读。只有完全可逆的静态原语地图可显式创建可编辑副本。
允许转换:
- box
- cylinder
- capsule
- 由嵌套静态 body 组成的世界位姿;
- pos、quat、size、friction、rgba 和出生点。
遇到下列内容必须整体拒绝,禁止静默丢弃:
- plane、mesh、heightfield
- asset、材质和碰撞过滤扩展;
- joint、site、light 或其他未知结构;
- euler、axisangle、xyaxes、zaxis、fromto
- 不能确认无损的 compiler 配置。
## 9. 事务边界
应用编辑草稿或转换地图时,顺序固定为:
1. 生成候选创作层;
2. 确定性生成候选物理层;
3. 创建候选 manifest
4. 在新的 MEMFS 工作区编译 MuJoCo
5. Viewer 成功 attach 新会话;
6. 最后提交 manifest、地图选择和编辑状态;
7. 释放旧会话和旧工作区。
任一步失败都必须恢复旧仿真和旧工程状态,同时保留用户草稿。
## 10. 导出
浏览器导入文件不保证可写,因此不直接覆盖源目录。地图通过 ZIP 导出,包含:
- `map.json`
- 物理层及其显式 asset
- 可选视觉层;
- 可选创作层。
ZIP 内路径保持工程相对结构,并继续执行路径安全校验。
## 11. 验证重点
- Schema V1/V2 兼容性;
- 路径穿越和协议绕过拒绝;
- 地图物理合成和命名空间隔离;
- GLB 自包含校验及资源释放;
- 编辑文档严格校验;
- 确定性 MJCF 输出;
- Undo/Redo 和视口变换写回;
- 只读转换的白名单与整体拒绝;
- 编译或 Viewer attach 失败后的事务回滚;
- 地图 ZIP 资产完整性。