Files
Mujoco_WASM/plans/map-v3-design.md
T
chenlin a9b07e0abf
web-platform-ci / TypeScript, lint, unit, build (push) Has been cancelled
web-platform-ci / Playwright E2E (push) Has been cancelled
feat(web-platform): release V0.8.1 常规地图优化
2026-09-03 13:18:35 +08:00

206 lines
8.3 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. 编辑交互
地图面板提供统一的“场景 · 资产库”,工程地图源、认证资产和系统程序地形都遵循同一条交互链路:点击或拖放到画布、进入轻量草稿、在场景树选择/删除,最后一次应用。三类卡片共享一种受校验的拖放载荷,画布落点统一按 0.1 m 归一化,任何一种来源的增删都不会隐式触发 MuJoCo 编译。
地图源与场景实例分离。同一工程地图源可创建多个拥有独立 XY/绕 Z 位姿的引用实例;物理层、视觉层和出生点使用同一个实例变换。编辑 `authoring` 内容属于源编辑,会同步影响引用该 descriptor 的实例,界面必须明确提示这一影响范围,不能伪装成实例级覆盖。
当前没有可编辑地图时,首个认证资产会创建临时 `map.json`、空物理层和创作层骨架,切换到新场景并作为未应用草稿进入 Three.js 预览;此阶段不调用 MuJoCo。“放弃场景更改”必须同时撤销临时实例、创作草稿和这三份临时工程文件,下一次创建可以复用同一场景 ID。用户点击“应用并重新编译”后才生成并事务提交实际物理层。
React 中的 `MapEditSession` 是草稿唯一来源。Three.js 预览层只负责:
- 草稿原语显示;
- 射线拾取和高亮;
- 世界坐标平移;
- 绕世界 Z 轴旋转;
- 原语尺寸缩放;
- 出生点预览;
- 操纵器和临时资源生命周期。
交互规则:
- `W`:移动;
- `E`:旋转;
- `S`:缩放;
- `Delete`/`Backspace`:删除;
- `Escape`:取消选择;
- `Ctrl+Z`:撤销;
- `Ctrl+Y``Ctrl+Shift+Z`:重做。
拖动 TransformControls 操纵轴期间禁用 OrbitControls;在画布空白区域按住鼠标左键仍可旋转相机。连续拖动只在 `mouseUp` 时提交一次历史记录。缩放必须写回原语参数,不能把 Three.js 节点 scale 作为持久数据。`locked` 的准确语义是“锁定位姿”:禁止位置、旋转和视口变换,但仍允许编辑名称、尺寸、摩擦和颜色。
“自动落位(重力)”通过统一地图表面查询器沿世界 `-Z` 求最高承载面。查询器与物理合成共用确定性程序几何,支持有限平地、坡道、楼梯、障碍物、坑/沟壑和高度场,并应用地图实例变换;因此认证资产可正确落到系统程序地形上,而不是始终假设 `z=0`
## 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. 事务边界
地图实例增删、工程地图实例变换、程序地图参数和认证资产源编辑共享同一个应用基线。普通模型入口切换或 URDF 模式重载只能使用上一次成功应用的地图基线,不能静默提交当前场景草稿。应用编辑草稿或转换地图时,顺序固定为:
1. 生成候选创作层;
2. 确定性生成候选物理层;
3. 创建候选 manifest
4. 在新的 MEMFS 工作区编译 MuJoCo
5. Viewer 成功 attach 新会话;
6. 最后提交 manifest、地图选择和编辑状态;
7. 推进地图实例与创作文档的统一应用基线;
8. 释放旧会话和旧工作区。
任一步失败都必须恢复旧仿真和旧工程状态,同时保留完整用户草稿。编译期间禁用所有草稿写入口;提交完成时只清除本次提交的文档版本,不能丢掉晚到修改。系统程序地形会替换无限地面 plane,避免其填平沟壑、深坑和高度场负高度。
## 10. 导出
浏览器导入文件不保证可写,因此不直接覆盖源目录。地图通过 ZIP 导出,包含:
- `map.json`
- 物理层及其显式 asset
- 可选视觉层;
- 可选创作层。
ZIP 内路径保持工程相对结构,并继续执行路径安全校验。
## 11. 验证重点
- Schema V1/V2 兼容性;
- 路径穿越和协议绕过拒绝;
- 地图物理合成和命名空间隔离;
- GLB 自包含校验及资源释放;
- 编辑文档严格校验;
- 确定性 MJCF 输出;
- Undo/Redo 和视口变换写回;
- 只读转换的白名单与整体拒绝;
- 编译或 Viewer attach 失败后的事务回滚;
- 地图 ZIP 资产完整性;
- 三类地图来源的统一拖放、场景树和单次提交边界;
- 普通模型重载不提交场景草稿,应用失败后草稿仍可放弃或重试;
- 工程地图实例物理/视觉/出生点变换一致;
- 首个认证资产临时场景的完整放弃;
- 认证资产在程序地形上的重力落位,以及坑洞不被无限平面填平。