Single-page Vue 3 + Vuetify app that runs a MuJoCo WebAssembly scene in the
browser and drives it with an ONNX policy. The default setup loads the G1
scene, policy, and motion clips from public/examples.
Demos: Humanoid Policy Viewer, GentleHumanoid Web Demo
npm install
npm run devsrc/views/Demo.vue- UI controls for the live demosrc/simulation/main.js- bootstraps MuJoCo, Three.js renderer, and policy loopsrc/simulation/mujocoUtils.js- scene/policy loading utilities and filesystem preloadingsrc/simulation/policyRunner.js- ONNX inference wrapper and observation pipelinenode_modules/mujoco-js/- MuJoCo wasm runtime (npm package)public/examples/scenes/- MJCF files + meshes staged into MuJoCo's MEMFSpublic/examples/checkpoints/- policy config JSON, ONNX file, and motion clips
-
Add your MJCF + assets.
- Create
public/examples/scenes/<robot>/. - Put your MJCF as
public/examples/scenes/<robot>/<robot>.xml. - Add all meshes/textures used by the MJCF into the same folder.
- Append every file path to
public/examples/scenes/files.jsonso the loader can preload them into/working/in the wasm filesystem.
- Create
-
Add your policy config and ONNX.
- Create
public/examples/checkpoints/<robot>/tracking_policy.json. - Place the ONNX model at
public/examples/checkpoints/<robot>/tracking_policy.onnx. - In the JSON, make sure these fields are correct:
onnx.pathpoints to your ONNX file (example:./examples/checkpoints/<robot>/tracking_policy.onnx)policy_joint_namesmatches the joint names in your MJCF actuatorsobs_configuses observation names that exist insrc/simulation/observationHelpers.jsaction_scale,stiffness,damping, anddefault_joint_poslengths matchpolicy_joint_names
- You need to adapt the observation helper functions in
src/simulation/observationHelpers.jsif your policy uses different observations than the built-in ones, and modifysrc/simulation/policyRunner.jsto control the robot.
- Create
-
(Optional) Add tracking motions.
- Add an index at
public/examples/checkpoints/<robot>/motions.json. - Put per-motion clips in
public/examples/checkpoints/<robot>/motions/. - In
tracking_policy.json, settracking.motions_pathto the index file. - The app downloads all motion clips listed in the index when the policy loads.
- The index uses this shape:
format:tracking-motion-index-v1base_path: relative path to the motions folder (example:./motions)motions: list of{ name, file }entries
- Each motion clip file must include a
defaultclip overall and each clip contains:joint_pos(orjointPos): per-frame joint arraysroot_pos(orrootPos): per-frame root positionsroot_quat(orrootQuat): per-frame root quaternions (w, x, y, z)
- Add an index at
-
Point the app to your robot and policy.
- Update
src/simulation/main.js:this.currentPolicyPath = './examples/checkpoints/<robot>/tracking_policy.json'await this.reloadScene('<robot>/<robot>.xml')await this.reloadPolicy('./examples/checkpoints/<robot>/tracking_policy.json')
- Update
If you want to keep multiple robots around, you can expose a selector in
src/views/Demo.vue and call demo.reloadScene(...) and demo.reloadPolicy(...)
from there.