main
从 ~/mujoco-web-spike 抽出 manip.html 的依赖闭包:
- manip.html + src/{manip,autograsp,scene-bridge,math}.js
- scenes/so101_pair(桌面并排两台 SO-101,默认)与 scenes/p7_bimanual(P7 双臂 + SO-101 夹爪)
—— 自包含 MJCF,网格已内联
- serve.py(COOP/COEP + no-store 的静态服务器)、start.sh、README
- tools/export_manip_scene.py 场景生成脚本(仅供参考,跑页面不需要)
快照对应 2026-08-31 的最后一次改动(自动抓取规划 autograsp.js 落地版)。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016tgfYxR5mWNRKQ67PKga4T
双臂操作沙盒(浏览器 WASM 版)
从 ~/mujoco-web-spike 抽出来的自包含子集:只含 manip.html 跑起来需要的文件。
物理引擎是 MuJoCo 的 WASM 构建,全部在浏览器里运行,服务器只负责发静态文件。
版本快照:2026-08-31 最后一次改动(自动抓取规划 autograsp.js 落地那一版)。
启动
tar xzf wasm-bimanual-grasp-20260901.tar.gz
cd wasm-bimanual-grasp-20260901
python3 serve.py 8000 # 或 ./start.sh 8000
然后用 Chrome / Edge 打开:
| 场景 | 地址 |
|---|---|
| 默认:桌面上并排两台 SO-101(5 自由度臂 + 二指夹爪) | http://127.0.0.1:8000/manip.html |
| P7 双臂工作站,末端换成 SO-101 夹爪(7 自由度臂) | http://127.0.0.1:8000/manip.html?scene=p7_bimanual |
首屏会依次显示「载入 MuJoCo WASM → 下载场景 → 编译 MJCF」,编译要几秒(网格已内联, so101_pair 1.8 MB / p7_bimanual 5.3 MB)。
环境要求
- Python 3(只用标准库
http.server,不需要 venv、不需要 pip 装任何东西) - 能上网:three.js 0.170.0 和
@mujoco/mujocoWASM 都从 jsDelivr CDN 拉,断网会白屏 - 桌面版 Chrome / Edge:页面用到 SharedArrayBuffer(多线程 WASM),
serve.py已经发好Cross-Origin-Opener-Policy/Cross-Origin-Embedder-Policy两个头
为什么不能直接 python3 -m http.server
可以起来,但页面会卡在「初始化 MuJoCo…」不报错也不动——
@mujoco/mujoco 是 pthread 构建,浏览器只在"跨源隔离"页面里放开 SharedArrayBuffer,
而 http.server 不发那两个头。serve.py 就是 http.server + 这两个头 + Cache-Control: no-store
(ES 模块缓存极死,改了 src/*.js 普通刷新照样跑旧代码,所以开发期一律不缓存)。
页面怎么用
- 拖动物体(鼠标直接拖桌上的易拉罐/瓶子/罐子/玩具琴/玩偶)→ 右侧实时出判定卡: 自动选哪只臂、下爪方向罗盘、左右两臂 IK 残差并排;两臂都够不着会明确给出「不可抓」
- 自动抓取 按钮:按判定结果执行 抵近 → 预收爪口 → 下探 → 合爪 → 抬升;中止 随时停
- 手动模式:选 左臂/右臂 →
X± Y± Z±步进末端 → 朝向约束(朝下/朝前/不约束)→ 张开/夹紧 - 物体面板可改位置和重量,点 应用 生效(运行时改
body_mass,不重编译) - 抓放记录:物体离抓取点 < 9 cm 且高于原位 5 cm 并保持 0.5 s = 抓取成功; 松手后静止落在台面 = 放置成功;掉到台下 = 失败
已知状态(08-31 实测)
- 判定侧 6/6 准确(含正确拒绝够不着的情况)
- 执行侧 3/5:立着的易拉罐、罐子、玩偶稳定成功;躺倒的瓶子和玩具琴还抓不住。
根因是二指爪全开时爪尖比爪中点低 2.6 cm,下探先顶到桌面;已加「按物体宽度预收爪口」
但仍不够,尝试过的三种夹持点选择策略都没救回来,细节见
src/autograsp.js顶部注释 - 切到别的标签页仿真会暂停(浏览器对后台标签的 rAF 节流),抓取过程中别切走
@mujoco/mujoco走的是 CDN 上的+esm最新版(打包时 jsDelivr latest = 3.12.0), 没有钉版本;如果哪天 CDN 升级后页面报xxx is not a function,先把manip.html里的@mujoco/mujoco/+esm改成@mujoco/mujoco@3.12.0/+esm试
文件
manip.html 页面 + 启动编排(渲染、UI、事件)
serve.py 静态服务器(COOP/COEP + no-store)
start.sh python3 serve.py 的包装,顺带打印地址
src/manip.js ArmController(阻尼最小二乘 IK、零空间次要目标)、GraspMonitor(抓放判定)
src/autograsp.js GraspPlanner:拖动后实时判定选臂/下爪方向,自动抓取状态机
src/scene-bridge.js MuJoCo mjModel/mjData → three.js 网格与每帧位姿
src/math.js 旋转矩阵 → 四元数
scenes/so101_pair/ 默认场景:model.xml(自包含 MJCF)+ meta.json(臂/爪/物体索引)
scenes/p7_bimanual/ P7 双臂场景,同上
tools/export_manip_scene.py ★ 仅供参考:生成上面两个场景的脚本,
依赖 ~/unitree_rl_mjlab/.venv(mujoco、numpy、tyro)+
linker-sim 资产库 + SO-101 MJCF,跑页面不需要它
完整项目(其它页面 arm/sort/policy/urdf 等)仍在 ~/mujoco-web-spike,本包只是双臂抓取这一条线。
Description
Languages
JavaScript
44.1%
HTML
31.9%
Python
23.7%
Shell
0.3%