Skip to content

Repository files navigation

xArm7 MuJoCo + IK(浏览器仿真)

在浏览器中运行 MuJoCo 物理仿真,加载 mujoco_menagerie 的 xArm7 模型,并用 Three.js 渲染。逆运动学(IK)来自同级仓库 mujoco-wasm-ik:minc + DAQP 编进同一份 mujoco.wasm,支持拖拽末端目标、关节限位与速度约束。

本仓库是应用,不含 MuJoCo 源码与 WASM 编译树。

功能概览

  • MuJoCo WASM 物理步进(mj_step
  • Three.js 将 mjvScene 同步为 THREE.Mesh 渲染(见 docs/rendering-pipeline.md
  • xArm7 + 地面 + 可抓取物体(球 / 盒)
  • 基于 minc 的微分 IK:FrameTask + PostureTask + solveIK
  • TransformControls 拖拽橙色目标球控制末端位姿

快速开始

前置条件

依赖 用途
Node.js ≥ 18 前端开发与 WASM 测试脚本
pnpm 包管理(亦可用 npm)
同级目录 ../mujoco-wasm-ik 带 IK 的 MuJoCo WASM npm 包

目录布局:

mujoco-project/
├── mujoco-wasm-ik/     # 库:WASM + IK API
└── vite-project/       # 本应用

package.json 通过 "mujoco-wasm-ik": "file:../mujoco-wasm-ik" 引用。库内已有预编译 dist/仅运行前端无需安装 Emscripten

安装与运行

pnpm install
pnpm dev

浏览器打开 Vite 提示的本地地址(默认 http://localhost:5173)。

操作说明

操作 按键 / 方式
暂停 / 继续仿真 Space 或 HUD「Pause」
重置场景 Backspace 或 HUD「Reset」
开关 IK HUD「IK: On/Off」
显示 / 隐藏接触点 C 或 HUD「Show Contacts」
平移 IK 目标 拖拽橙色球,或 T 切换平移模式
旋转 IK 目标 R 切换旋转模式
旋转视角 鼠标拖拽(OrbitControls)

项目目录

vite-project/
├── index.html              # 页面入口与 HUD
├── vite.config.js          # 允许读取同级 mujoco-wasm-ik
├── package.json
├── src/
│   ├── main.js             # 仿真主循环、模型加载、Three.js 渲染、IK 交互
│   └── arm-ik.js           # IK 任务 / 限位封装(FrameTask、PostureTask 等)
├── scripts/
│   ├── xarm7_smoke.mjs
│   └── xarm7_collision_smoke.mjs
├── public/
│   └── models/
│       ├── ufactory_xarm7/ # 机械臂 MJCF + STL
│       └── grasp_objects/  # 可拾取物体(OBJ/PNG + 物体 MJCF)
└── docs/
    ├── load-model.md
    ├── rendering-pipeline.md
    ├── add-grasp-object.md
    └── import-usd-grasp-object.md

关键路径说明

路径 说明
src/main.js 应用入口:VFS 挂载模型 → MjModel → 仿真循环 → Three.js 绘制
src/arm-ik.js xArm7 专用:7 轴 ctrl、夹爪、DofFreezingTask
public/models/ufactory_xarm7/scene.xml 场景入口:地面、机械臂、抓取物体
../mujoco-wasm-ik WASM + IkConfiguration / solveIK(机械臂无关)

WASM / IK 库

物理与 IK 在同一份 mujoco.wasm 里,由 mujoco-wasm-ik 提供:

import loadMujoco from "mujoco-wasm-ik";

本应用只写手臂 7 轴 ctrl[0..6],夹爪走 ctrl[7],不对仿真 mjDataintegrateInplace

改 IK 绑定、minc、DAQP 或 MuJoCo 本体时,到 mujoco-wasm-ik 按该仓库 README 的构建 SOP 重编(默认 -DMUJOCO_WASM_THREADS=OFF)。只改 src/arm-ik.js / src/main.js 时刷新页面即可。

验证:

# 库:通用 IK smoke
cd ../mujoco-wasm-ik && npm run smoke

# 本应用:xArm7
pnpm run smoke:xarm7
pnpm run smoke:collision

架构简述

scene.xml ──► MjModel + MjData
                  │
         mj_step │  mjv_updateScene
                  ▼
            mjvScene.geoms ──► THREE.Mesh(Three.js 渲染)
                  │
         solveIK │  写 ctrl(不要 integrateInplace)
                  ▼
              qpos / ctrl ──► 物理仿真
  • 物理与可视化抽象:MuJoCo WASM(mujoco-wasm-ik
  • 像素绘制:Three.js(灯光、相机、材质均为 Three 侧)
  • IK 求解:minc + DAQP,经库的 ik_bindings.cc 暴露给 JavaScript

详细架构方案

浏览器里只有一份 WASM。它同时做物理步进和微分 IK;Three.js 只负责把 mjvGeom 画出来。JS 不另开 IK 进程,也不对仿真 mjData 调用 integrateInplace

1. 分层

flowchart TB
  subgraph ui [浏览器 UI]
    HUD[index.html HUD]
    Keys[键盘 WASD / 夹爪]
    Orbit[OrbitControls]
  end

  subgraph js [JavaScript]
    Main[src/main.js]
    ArmIk[src/arm-ik.js]
  end

  subgraph wasm [mujoco.wasm 同一模块]
    Physics[mj_step 接触 重力]
    Viz[mjv_updateScene]
    IK[minc + DAQP solveIK]
    VFS[MEMFS /working]
  end

  subgraph three [Three.js]
    Mesh[THREE.Mesh]
    Light[灯光 相机]
    GPU[WebGLRenderer]
  end

  HUD --> Main
  Keys --> Main
  Orbit --> Light
  Main --> ArmIk
  ArmIk -->|写 data.ctrl 0..6| Physics
  Main -->|写 data.ctrl 7 夹爪| Physics
  Main -->|fetch XML/OBJ/STL/PNG| VFS
  VFS --> Physics
  Physics --> Viz
  Viz -->|mjvGeom 列表| Mesh
  Mesh --> GPU
  Light --> GPU
Loading
职责 不负责
main.js 加载模型、键盘/HUD、每帧调度、Three 网格与贴图 不解 QP、不算接触
arm-ik.js 组 IK 任务/限位,把 solveIK 速度积成 7 轴 ctrl 不改夹爪、不挪桌上物体
MuJoCo mj_step 伺服、接触、摩擦;mjv_updateScene 出绘制指令 不画像素
minc/DAQP 在同一 WASM 内求关节速度 不直接改 qpos
Three.js Mesh、灯光、相机、DataTexture 不参与物理

2. 启动:资源如何进仿真

机械臂与可拾取物体目录分开。MJCF 在浏览器里不能读磁盘,必须先写入 WASM 虚拟文件系统。

flowchart LR
  subgraph disk [public/models]
    ArmXML[ufactory_xarm7/scene.xml]
    ArmSTL[assets/*.stl]
    ObjXML[grasp_objects/*/物体.xml]
    ObjMesh[*.obj *.png]
  end

  subgraph vfs [VFS /working]
    WScene[scene.xml]
    WArm[xarm7.xml + assets]
    WObj[grasp_objects/...]
  end

  disk -->|XARM7_FILES| vfs
  disk -->|GRASP_OBJECT_FILES| vfs
  WScene -->|include| WArm
  WScene -->|include| WObj
  vfs -->|MjModel.from_xml_path| Model[MjModel + MjData]
Loading
  • 入口:scene.xml include 臂本体 + 各物体包(物体包不要<compiler meshdir>,以免覆盖臂的 assets/)。
  • Reset 时 home keyframe 不含桌上 freejoint,由 GRASP_OBJECT_POSES 写回 qpos
  • 当前 WASM 不能加载 USD;物体网格用 OBJ/STL,贴图必须 PNG。

3. 每帧控制回路

requestAnimationFrameupdate()render()。未 Pause 时顺序固定:先改目标与 ctrl,再 mj_step,最后同步画面。

sequenceDiagram
  participant User as 用户
  participant Main as main.js
  participant IK as solveIK
  participant Phys as mj_step
  participant Viz as mjv_updateScene
  participant Three as Three.js

  User->>Main: 键盘改 targetMesh / 夹爪
  alt IK On
    Main->>IK: 目标位姿 + FrameTask + PostureTask
    Note over IK: DofFreezingTask 冻住非 joint1-7
    IK-->>Main: 7 轴速度
    Main->>Phys: 只写 data.ctrl 0..6
  end
  Main->>Phys: data.ctrl 7 夹爪
  Phys->>Phys: 位置伺服 + 接触 + 重力
  Phys-->>Viz: 更新后的 qpos
  Viz-->>Main: mjvGeom 列表
  Main->>Three: 几何 / 贴图 / 世界矩阵
  Three->>User: WebGL 画面
Loading

关键约束:

  1. IK 只写手臂 7 轴 ctrl,不写 qpos,不对仿真 mjDataintegrateInplace
  2. 夹爪走腱驱动 ctrl[7][ 开 / ] 合),IK 不碰。
  3. 桌上物体freejoint,物理里自由;IK 里被 DofFreezingTask 冻住,避免 QP 把方块当关节挪走。
  4. 碰撞与夹取交给接触力,不再挂 CollisionAvoidanceLimit

4. IK 任务结构

flowchart TB
  Target[targetMesh 位姿] --> EE[FrameTask site link_tcp]
  Posture[PostureTask 弱正则]
  Freeze[DofFreezingTask 非臂 DOF]
  Lim[ConfigurationLimit + VelocityLimit]

  EE --> QP[solveIK DAQP]
  Posture --> QP
  Freeze --> QP
  Lim --> QP
  QP --> Vel[nv 维速度]
  Vel --> Ctrl["ctrl[i] = qpos + vel * dt"]
  Ctrl --> Act[actuator 位置伺服]
Loading

目标球是 JS 里的 targetMesh(可隐藏),不是地上的 grasp_sphere

5. 渲染:MuJoCo 指令 → Three.js

不使用 mjr_rendermjv_updateScene 产出要画的 geom;Three 侧建 BufferGeometry + MeshPhongMaterial,每帧只更新世界矩阵。

flowchart LR
  Data[mjData] --> Update[mjv_updateScene]
  Update --> Geom[mjvGeom]
  Geom -->|type/size/dataid| Geo[BufferGeometry]
  Geom -->|texid + tex_data| Tex[DataTexture]
  Geom -->|mat + pos| Mat4[mesh.matrix]
  Geo --> Mesh[THREE.Mesh]
  Tex --> Mesh
  Mat4 --> Mesh
  Lights[Ambient Point Spot] --> GPU[WebGLRenderer]
  Mesh --> GPU
Loading
  • 灯光、相机、阴影在 Three 侧;XML 里的 <light> 不照亮画面。
  • geomgroup[3]=0 隐藏夹爪 collision pad。
  • Mesh UV 按面展开(OBJ 的 vt 常多于 v);贴图从 mjModel.tex_data 拷出,WASM 的宽高/偏移需转成 Number

6. 模块与文件

flowchart TB
  subgraph app [本应用]
    index[index.html]
    main[src/main.js]
    ikjs[src/arm-ik.js]
  end

  subgraph assets [静态资源]
    scene[scene.xml]
    xarm[xarm7.xml]
    grasp[grasp_objects]
  end

  subgraph lib [mujoco-wasm-ik]
    dist[dist/mujoco.js]
    bind[codegen/generated/bindings.cc]
    ikcc[overlay/ik_bindings.cc]
    minc[minc + daqp + eigen]
  end

  index --> main
  main --> ikjs
  main -->|import mujoco-wasm-ik| dist
  main --> scene
  scene --> xarm
  scene --> grasp
  dist --> bind
  dist --> ikcc
  ikcc --> minc
Loading
文件 角色
vite.config.js 允许读取同级 mujoco-wasm-ik,把 .wasm 当静态资源
src/main.js VFS、主循环、键盘、Three 同步、Reset
src/arm-ik.js xArm7 IK 封装;导出 createArmIk / applyArmIkToCtrl
public/models/ufactory_xarm7/ 臂 + 地面场景,不含物体 mesh
public/models/grasp_objects/ 每物体一目录:xml + obj + png
../mujoco-wasm-ik/overlay/ik_bindings.cc 库侧唯一允许改的 IK Embind;勿改官方 bindings.cc

更多细节:


开发与构建命令

pnpm dev              # 启动 Vite 开发服务器
pnpm build            # 生产构建(输出到 dist/)
pnpm preview          # 预览生产构建
pnpm lint             # ESLint
pnpm run smoke:xarm7  # xArm7 IK smoke

上游项目与许可

组件 来源
mujoco-wasm-ik 同级库仓库(Apache-2.0;上游见该仓库 NOTICE)
xArm7 模型 mujoco_menagerie / ufactory_xarm7

About

在浏览器中运行 MuJoCo 物理仿真,加载 mujoco_menagerie 的 xArm7 模型,并用 Three.js 渲染

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages