@vuer-ai/mujoco-ts
v0.0.79
Published
[](https://www.npmjs.com/package/@vuer-ai/mujoco-ts)
Keywords
Readme
React MuJoCo Component
This component contains a MuJoCo 3.3.6 compiled against WebAssembly. I also added the required react hooks for using it in a Typescript React project.
Installation
npm install @vuer-ai/mujoco-tsUsage
import {MuJoCoModel, MuJoCoProvider} from "@vuer-ai/mujoco-ts";
// can present the MuJoCo instance via the following:
<MuJoCoModel
ref={modelRef}
speed={speed}
src={`agility_cassie/scene.xml`}
assets={[
"agility_cassie/cassie.xml",
"agility_cassie/assets/achilles-rod.obj",
"agility_cassie/assets/cassie-texture.png",
"agility_cassie/assets/foot-crank.obj",
"agility_cassie/assets/foot.obj",
"agility_cassie/assets/heel-spring.obj",
"agility_cassie/assets/hip-pitch.obj",
"agility_cassie/assets/hip-roll.obj",
"agility_cassie/assets/hip-yaw.obj",
"agility_cassie/assets/knee-spring.obj",
"agility_cassie/assets/knee.obj",
"agility_cassie/assets/pelvis.obj",
"agility_cassie/assets/plantar-rod.obj",
"agility_cassie/assets/shin.obj",
"agility_cassie/assets/tarsus.obj"
]}/>Notes on File Path
The src attribute is the path to the MuJoCo XML file. We use the
parent director of this entrypoint file as the root directory, and
reference all assets relative to this root directory.
Therefore during download, we remove the common prefix assets have
with the root directory, and use the remaining path as the target
location. For instance, in the example above, the scene.xml file
is the entrypoint. Therefore we will download agility_cassie/cassie.xml
into the same directory as scene.xml inside the virtual file system
of the WebAssembly runtime.
Force Application
MuJoCo-TS provides multiple ways to apply forces and torques to bodies in your simulation.
Coordinate Systems
MuJoCo and Three.js use different coordinate systems:
- MuJoCo: X-forward, Y-left, Z-up
- Three.js: X-right, Y-up, Z-backward
Use these conversion functions:
const toMujocoCoords = (vec: THREE.Vector3) => {
return new THREE.Vector3(vec.x, -vec.z, vec.y);
};
const fromMujocoCoords = (vec: THREE.Vector3) => {
return new THREE.Vector3(vec.x, vec.z, -vec.y);
};Force Application Methods
1. Direct Force Application
Apply forces and torques at specific points using sim.applyForce():
sim.applyForce(
fx, fy, fz, // Force vector in world coordinates (N)
tx, ty, tz, // Torque vector in world coordinates (Nm)
px, py, pz, // Application point in world coordinates (m)
bodyId // Body ID to apply force to
);
// Example: Apply 10N force at body center
const bodyId = 2;
const bodyPos = sim.xpos.slice(bodyId * 3, bodyId * 3 + 3);
sim.applyForce(10, 0, 0, 0, 0, 0, bodyPos[0], bodyPos[1], bodyPos[2], bodyId);2. Generalized Forces (qfrc_applied)
Apply forces/torques directly to degrees of freedom:
// Apply torque to a hinge joint
const jointId = 3;
const dofAddress = model.jnt_dofadr[jointId];
sim.qfrc_applied[dofAddress] = 5.0; // 5 Nm torque
// Multi-DoF joints (e.g., ball joint)
sim.qfrc_applied[dofAddress + 0] = 1.0; // Roll
sim.qfrc_applied[dofAddress + 1] = 2.0; // Pitch
sim.qfrc_applied[dofAddress + 2] = 3.0; // Yaw3. Body Wrenches (xfrc_applied)
Apply wrenches at body centers of mass:
// Apply force and torque to body 2
const bodyId = 2;
const baseIndex = bodyId * 6;
sim.xfrc_applied[baseIndex + 0] = 10; // fx
sim.xfrc_applied[baseIndex + 1] = 0; // fy
sim.xfrc_applied[baseIndex + 2] = 5; // fz
sim.xfrc_applied[baseIndex + 3] = 0; // tx
sim.xfrc_applied[baseIndex + 4] = 2; // ty
sim.xfrc_applied[baseIndex + 5] = 0; // tzReact Components
AnchorActuator Component
Provides a visual interface for applying forces:
import {AnchorActuator} from '@vuer-ai/mujoco-ts';
<AnchorActuator
bodyId={2}
enabled={true}
scale={20}
forceDestination={[1, 1, 1]}
showForceVector={true}
showForceText={true}
showPivotControls={true}
/>ForceManager Hook
Register custom force handlers that run every simulation step:
import {useForceManager} from '@vuer-ai/mujoco-ts';
const MyForceComponent = () => {
const [addForceUpdateHandler] = useForceManager();
useEffect(() => {
const applyMyForce = () => {
sim.applyForce(10, 0, 0, 0, 0, 0, 0, 0, 0, bodyId);
};
const removeHandler = addForceUpdateHandler(applyMyForce);
return removeHandler; // Cleanup on unmount
}, []);
};Working with Geoms
Forces are applied to bodies, not geoms. To apply force at a geom location:
// Get the body that owns this geom
const geomId = 5;
const bodyId = model.geom_bodyid[geomId];
// Get geom position
const geomPos = sim.xgeom.slice(geomId * 3, geomId * 3 + 3);
// Apply force at geom location
sim.applyForce(fx, fy, fz, 0, 0, 0, geomPos[0], geomPos[1], geomPos[2], bodyId);Best Practices
- Always convert coordinates between Three.js and MuJoCo systems
- Clear forces when not needed:
sim.qfrc_applied.fill(0) - Validate IDs before applying forces to avoid segfaults
- Consider timestep when calculating force magnitudes
- Use the appropriate method:
applyForce()for point forcesqfrc_appliedfor joint controlxfrc_appliedfor body-level wrenches
Dial Schema Generation
MuJoCo-TS uses dial annotations for generating UI control schemas. To regenerate schemas after modifying component props: Install the dial CLI globally:
npm install -g @vuer-ai/dial-cliand then you can generate the schemas
pnpm dialThis generates metadata/schema.dial from the @dial annotations in MuJoCo.tsx.
Credits
Built with ❤️ by Ge Yang, Yajvan Ravan, Marvin Luo, and Gio Huh at FortyFive labs.
