mujoco-react 8.4.0 → 8.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +40 -64
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -18,113 +18,89 @@ Composable [React Three Fiber](https://docs.pmnd.rs/react-three-fiber) wrapper a
18
18
  npm install mujoco-react three @react-three/fiber @react-three/drei
19
19
  ```
20
20
 
21
- ## Quick Start
21
+ ## Load a Model
22
22
 
23
23
  ```tsx
24
- import {
25
- MujocoProvider,
26
- MujocoCanvas,
27
- useIkController,
28
- IkGizmo,
29
- } from "mujoco-react";
24
+ import { MujocoProvider, MujocoCanvas } from "mujoco-react";
30
25
  import type { SceneConfig } from "mujoco-react";
31
- import { OrbitControls } from "@react-three/drei";
32
26
 
33
- const config: SceneConfig = {
27
+ const panda: SceneConfig = {
34
28
  src: "https://raw.githubusercontent.com/google-deepmind/mujoco_menagerie/main/franka_emika_panda/",
35
29
  sceneFile: "scene.xml",
36
30
  homeJoints: [1.707, -1.754, 0.003, -2.702, 0.003, 0.951, 2.490],
37
31
  };
38
32
 
39
- function Scene() {
40
- const ik = useIkController({ siteName: "tcp" });
41
- return (
42
- <>
43
- <OrbitControls enableDamping makeDefault />
44
- {ik && <IkGizmo controller={ik} />}
45
- <ambientLight intensity={0.7} />
46
- <directionalLight position={[1, 2, 5]} intensity={1.2} castShadow />
47
- </>
48
- );
49
- }
50
-
51
- function App() {
33
+ export function App() {
52
34
  return (
53
35
  <MujocoProvider>
54
36
  <MujocoCanvas
55
- config={config}
37
+ config={panda}
56
38
  camera={{ position: [2, -1.5, 2.5], up: [0, 0, 1], fov: 45 }}
57
- shadows
58
39
  style={{ width: "100%", height: "100vh" }}
59
- >
60
- <Scene />
61
- </MujocoCanvas>
40
+ />
62
41
  </MujocoProvider>
63
42
  );
64
43
  }
65
44
  ```
66
45
 
67
- ## `useMujoco()`
68
-
69
- Inside `<MujocoCanvas>` or `<MujocoPhysics>`, `useMujoco()` gives you the simulation API, refs to the live model/data, and status:
46
+ ## Add Scene Tools
70
47
 
71
48
  ```tsx
72
- import { useMujoco } from "mujoco-react";
73
-
74
- function MyComponent() {
75
- const { isPending, isError, error, api, mjModelRef } = useMujoco();
49
+ import { OrbitControls } from "@react-three/drei";
50
+ import { IkGizmo, useIkController } from "mujoco-react";
76
51
 
77
- if (isPending) return <span>Loading...</span>;
78
- if (isError) return <span>Error: {error}</span>;
52
+ function PandaTools() {
53
+ const ik = useIkController({ siteName: "tcp" });
79
54
 
80
55
  return (
81
- <button onClick={() => api.reset()}>
82
- Reset ({mjModelRef.current?.nq} joints)
83
- </button>
56
+ <>
57
+ <OrbitControls makeDefault />
58
+ {ik && <IkGizmo controller={ik} />}
59
+ <ambientLight intensity={0.7} />
60
+ <directionalLight position={[1, 2, 5]} intensity={1.2} />
61
+ </>
84
62
  );
85
63
  }
86
64
  ```
87
65
 
88
- ## Writing a Controller
89
-
90
- A controller is a hook that reads sensors and writes actuators each physics step:
66
+ Use it as a child of `<MujocoCanvas>`:
91
67
 
92
68
  ```tsx
93
- import { useCtrl, useSensor, useBeforePhysicsStep } from "mujoco-react";
69
+ <MujocoCanvas config={panda}>
70
+ <PandaTools />
71
+ </MujocoCanvas>
72
+ ```
94
73
 
95
- function useMyController(gain: number) {
96
- const shoulder = useCtrl("shoulder");
97
- const elbow = useCtrl("elbow");
98
- const force = useSensor("force_sensor");
74
+ ## Write Controllers
99
75
 
100
- useBeforePhysicsStep(() => {
101
- shoulder.write(gain * Math.sin(Date.now() / 1000));
102
- elbow.write(force.read()[0] * -0.5);
76
+ ```tsx
77
+ import { useBeforePhysicsStep } from "mujoco-react";
78
+
79
+ function MyController() {
80
+ useBeforePhysicsStep((_model, data) => {
81
+ data.ctrl[0] = Math.sin(data.time);
103
82
  });
83
+
84
+ return null;
104
85
  }
105
86
  ```
106
87
 
107
- ### Applying Forces
88
+ Controllers are just React children that read sensors, write `data.ctrl`, apply forces, or call the `MujocoSimAPI` at physics-step time.
108
89
 
109
- Write directly to `xfrc_applied` in a physics callback for per-frame forces. The layout is `[torque_x, torque_y, torque_z, force_x, force_y, force_z]` per body:
90
+ ## Use the Sim API
110
91
 
111
92
  ```tsx
112
- import { useBeforePhysicsStep } from "mujoco-react";
93
+ import { useMujoco } from "mujoco-react";
113
94
 
114
- function useSpringForce(bodyId: number, target: [number, number, number], stiffness = 100) {
115
- useBeforePhysicsStep((_model, data) => {
116
- const i3 = bodyId * 3;
117
- const i6 = bodyId * 6;
118
- data.xfrc_applied[i6 + 3] = (target[0] - data.xpos[i3]) * stiffness;
119
- data.xfrc_applied[i6 + 4] = (target[1] - data.xpos[i3 + 1]) * stiffness;
120
- data.xfrc_applied[i6 + 5] = (target[2] - data.xpos[i3 + 2]) * stiffness;
121
- });
95
+ function ResetButton() {
96
+ const sim = useMujoco();
97
+ if (!sim.isReady) return null;
98
+
99
+ return <button onClick={() => sim.api.reset()}>Reset</button>;
122
100
  }
123
101
  ```
124
102
 
125
- The `api.applyForce(bodyName, force)` convenience method also works for one-off interactions (e.g. button clicks) but does a name lookup each call.
126
-
127
- ### WebSocket Control
103
+ ## WebSocket Control
128
104
 
129
105
  Stream actuator commands over a WebSocket and send simulation state back. Use a schema validator such as Zod at this boundary because socket messages are untrusted app input (`npm install zod` for this example):
130
106
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mujoco-react",
3
- "version": "8.4.0",
3
+ "version": "8.4.1",
4
4
  "description": "Composable React Three Fiber building blocks for MuJoCo WASM simulations",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",