Skip to content

Commit bc1b90b

Browse files
noah-wardlowclaude
andcommitted
docs: clean up README and docs copy
- Replace "Bring Your Own" language with natural headings - Add useMujoco() hook documentation to README - Fix mujoco-js link to npm package page - Add demo header video to README and docs overview Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent ab2d336 commit bc1b90b

6 files changed

Lines changed: 85 additions & 128 deletions

File tree

README.md

Lines changed: 56 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -58,49 +58,9 @@ function App() {
5858
}
5959
```
6060

61-
## Architecture
62-
63-
Two ways to set up your scene:
64-
65-
### `<MujocoCanvas>`
66-
67-
Wraps R3F `<Canvas>` for you:
68-
69-
```
70-
<MujocoProvider> <- WASM module lifecycle
71-
<MujocoCanvas config={...}> <- R3F Canvas + physics context
72-
<SceneRenderer /> <- Syncs MuJoCo bodies to Three.js meshes
73-
<IkController config={..}> <- Opt-in controller plugin
74-
<IkGizmo />
75-
</IkController>
76-
<YourController /> <- Bring your own controller
77-
<YourLights /> <- You compose your own scene
78-
</MujocoCanvas>
79-
</MujocoProvider>
80-
```
61+
## Writing a Controller
8162

82-
### `<MujocoPhysics>`
83-
84-
Use inside your own `<Canvas>` for control over gl settings, post-processing, etc:
85-
86-
```
87-
<MujocoProvider>
88-
<Canvas shadows camera={...} gl={...}> <- Your Canvas, your settings
89-
<MujocoPhysics config={config}> <- Physics context only
90-
<SceneRenderer />
91-
<YourController />
92-
</MujocoPhysics>
93-
<OrbitControls />
94-
<EffectComposer>...</EffectComposer> <- Post-processing, etc.
95-
</Canvas>
96-
</MujocoProvider>
97-
```
98-
99-
The library handles WASM lifecycle, physics stepping, and body rendering. Controllers (IK, teleoperation, RL policies) are composable plugins you opt into or write yourself.
100-
101-
## Bring Your Own Controller
102-
103-
A controller is a React component that calls `useBeforePhysicsStep` to write `data.ctrl` each frame and returns `null`.
63+
A controller is a React component that calls `useBeforePhysicsStep` to write `data.ctrl` each frame:
10464

10565
```tsx
10666
import { useBeforePhysicsStep } from 'mujoco-react';
@@ -112,74 +72,68 @@ function MyController() {
11272
});
11373
return null;
11474
}
75+
```
76+
77+
Drop it into the tree alongside `<SceneRenderer />`:
11578

116-
// Drop it in:
79+
```tsx
11780
<MujocoCanvas config={config}>
11881
<SceneRenderer />
11982
<MyController />
12083
</MujocoCanvas>
12184
```
12285

123-
IK, teleoperation, RL policies, state machines all follow this same pattern.
124-
125-
### Bring Your Own IK
126-
127-
The built-in `<IkController>` uses a Damped Least-Squares solver. You can replace it with your own (analytical, learned, etc.):
86+
The `createController<TConfig>()` factory adds typed config and default merging for reusable plugins:
12887

12988
```tsx
130-
import type { IKSolveFn } from 'mujoco-react';
89+
import { createController, useBeforePhysicsStep } from 'mujoco-react';
13190

132-
const myIK: IKSolveFn = (pos, quat, currentQ) => {
133-
return myAnalyticalSolver(pos, currentQ); // return joint angles or null
134-
};
91+
export const MyController = createController<{ gain: number }>(
92+
{ name: 'MyController', defaultConfig: { gain: 1.0 } },
93+
({ config }) => {
94+
useBeforePhysicsStep((_model, data) => {
95+
data.ctrl[0] = config.gain * Math.sin(data.time);
96+
});
97+
return null;
98+
},
99+
);
135100

136-
<IkController config={{ siteName: 'tcp', numJoints: 7, ikSolveFn: myIK }}>
137-
<IkGizmo />
138-
</IkController>
101+
// <MyController config={{ gain: 2.0 }} />
139102
```
140103

141-
Or skip `<IkController>` entirely and solve IK yourself inside `useBeforePhysicsStep`:
104+
## Architecture
142105

143-
```tsx
144-
function MyIKController() {
145-
useBeforePhysicsStep((model, data) => {
146-
const joints = myCustomIKSolve(model, data);
147-
if (joints) {
148-
for (let i = 0; i < joints.length; i++) data.ctrl[i] = joints[i];
149-
}
150-
});
151-
return null;
152-
}
106+
`<MujocoCanvas>` wraps R3F `<Canvas>` and forwards all Canvas props (`camera`, `shadows`, `gl`, etc.). For full control over the Canvas, use `<MujocoPhysics>` inside your own:
107+
108+
```
109+
<MujocoProvider> <MujocoProvider>
110+
<MujocoCanvas config={...}> <Canvas shadows gl={...}>
111+
<SceneRenderer /> <MujocoPhysics config={...}>
112+
<IkController config={..}> <SceneRenderer />
113+
<IkGizmo /> </MujocoPhysics>
114+
</IkController> <EffectComposer>...</EffectComposer>
115+
<MyController /> </Canvas>
116+
</MujocoCanvas> </MujocoProvider>
117+
</MujocoProvider>
153118
```
154119

155-
### `createController<TConfig>()` Factory
120+
### Custom IK Solvers
156121

157-
For reusable controller plugins with typed config and default merging:
122+
The built-in `<IkController>` uses Damped Least-Squares. Pass `ikSolveFn` to swap in your own solver (analytical, learned, etc.):
158123

159124
```tsx
160-
import { createController, useBeforePhysicsStep } from 'mujoco-react';
161-
162-
interface MyConfig {
163-
gain: number;
164-
targetJoint: string;
165-
}
166-
167-
function MyControllerImpl({ config }: { config: MyConfig; children?: React.ReactNode }) {
168-
useBeforePhysicsStep((_model, data) => {
169-
data.ctrl[0] = config.gain * Math.sin(data.time);
170-
});
171-
return null;
172-
}
125+
import type { IKSolveFn } from 'mujoco-react';
173126

174-
export const MyController = createController<MyConfig>(
175-
{ name: 'MyController', defaultConfig: { gain: 1.0 } },
176-
MyControllerImpl,
177-
);
127+
const myIK: IKSolveFn = (pos, quat, currentQ) => {
128+
return myAnalyticalSolver(pos, currentQ); // return joint angles or null
129+
};
178130

179-
// Usage: <MyController config={{ gain: 2.0, targetJoint: 'shoulder' }} />
131+
<IkController config={{ siteName: 'tcp', numJoints: 7, ikSolveFn: myIK }}>
132+
<IkGizmo />
133+
</IkController>
180134
```
181135

182-
### Built-in `<IkController>`
136+
### `<IkController>`
183137

184138
The library includes one controller for interactive end-effector control:
185139

@@ -425,9 +379,23 @@ Plays back recorded qpos trajectories with scrubbing.
425379

426380
## Hooks
427381

382+
### `useMujoco()`
383+
384+
Access the WASM module lifecycle from any child of `<MujocoProvider>`:
385+
386+
```tsx
387+
const { mujoco, status, error } = useMujoco();
388+
```
389+
390+
| Field | Type | Description |
391+
|-------|------|-------------|
392+
| `mujoco` | `MujocoModule \| null` | The raw WASM module, or `null` while loading |
393+
| `status` | `'pending' \| 'error'` | Lifecycle state (absent once loaded) |
394+
| `error` | `string \| null` | Error message if loading failed |
395+
428396
### `useMujocoSim()`
429397

430-
Access the simulation API and internal refs:
398+
Access the simulation API and internal refs (must be inside `<MujocoCanvas>` or `<MujocoPhysics>`):
431399

432400
```tsx
433401
const { api, mjModelRef, mjDataRef } = useMujocoSim();

docs/architecture.mdx

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,18 @@ icon: "sitemap"
88

99
mujoco-react uses a layered provider pattern. Two setup options:
1010

11+
`MujocoCanvas` wraps R3F `<Canvas>` and forwards all Canvas props. `MujocoPhysics` provides just the physics context inside your own Canvas.
12+
1113
```
12-
Option A: MujocoCanvas (quick start)
13-
14-
MujocoProvider <- WASM module lifecycle
15-
└─ MujocoCanvas <- R3F Canvas + scene config
16-
└─ MujocoSimProvider <- Physics loop + API
17-
├─ SceneRenderer <- Body mesh sync
18-
├─ IkController <- Opt-in IK plugin
19-
│ └─ IkGizmo
14+
MujocoCanvas MujocoPhysics
15+
16+
MujocoProvider MujocoProvider
17+
└─ MujocoCanvas └─ Canvas
18+
└─ MujocoSimProvider └─ MujocoPhysics
19+
├─ SceneRenderer └─ MujocoSimProvider
20+
├─ IkController ├─ SceneRenderer
21+
│ └─ IkGizmo └─ YourComponents
2022
└─ YourComponents
21-
22-
Option B: MujocoPhysics (bring your own Canvas)
23-
24-
MujocoProvider <- WASM module lifecycle
25-
└─ Canvas <- Your R3F Canvas, your gl settings
26-
└─ MujocoPhysics <- Physics context (no Canvas wrapper)
27-
└─ MujocoSimProvider <- Physics loop + API
28-
├─ SceneRenderer
29-
└─ YourComponents
3023
```
3124

3225
### MujocoProvider
@@ -61,9 +54,9 @@ You don't use this directly. `MujocoCanvas` and `MujocoPhysics` create it. It:
6154
- Exposes the `MujocoSimAPI` via React context
6255
- Provides callback registration for `useBeforePhysicsStep`, `useAfterPhysicsStep`, and `resetCallbacks`
6356

64-
### Controller Plugins (Bring Your Own)
57+
### Controller Plugins
6558

66-
The core library has no built-in control logic. Controllers are React components that call `useBeforePhysicsStep` to write `data.ctrl`. The library ships `<IkController>` as one example, but the intended pattern is to write your own.
59+
Controllers are React components that call `useBeforePhysicsStep` to write `data.ctrl`. The library ships `<IkController>` as one example; the same pattern works for any control logic.
6760

6861
```tsx
6962
// This is a complete controller:

docs/guides/building-controllers.mdx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
title: "Building Controllers"
3-
description: "Write your own controller, bring your own IK, compose library hooks into robot-specific logic"
3+
description: "Custom controllers, IK solvers, and composing library hooks into robot-specific logic"
44
icon: "gamepad"
55
---
66

@@ -127,9 +127,9 @@ export function SO101Controller() {
127127
}
128128
```
129129

130-
## Bring Your Own IK
130+
## Custom IK Solvers
131131

132-
You have three options for IK:
132+
Three options for IK:
133133

134134
### 1. Use the built-in solver
135135

docs/introduction.mdx

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,17 @@ icon: "rocket"
66

77
# mujoco-react
88

9-
**mujoco-react** is a composable [React Three Fiber](https://r3f.docs.pmnd.rs/) wrapper around [mujoco-js](https://github.com/nicepkg/mujoco-js). It provides components for loading models, stepping physics, and rendering bodies. Controllers like IK are opt-in plugins.
9+
**mujoco-react** is a composable [React Three Fiber](https://r3f.docs.pmnd.rs/) wrapper around [mujoco-js](https://www.npmjs.com/package/mujoco-js). It provides components for loading models, stepping physics, and rendering bodies. Controllers like IK are opt-in plugins.
1010

1111
<CardGroup cols={2}>
1212
<Card title="Composable" icon="puzzle-piece">
1313
`<SceneRenderer />`, `<IkGizmo />`, `<Debug />` etc. are R3F children you add to your scene.
1414
</Card>
15-
<Card title="Bring Your Own Controller" icon="scale-balanced">
15+
<Card title="Controller Pattern" icon="scale-balanced">
1616
Controllers are React components that call `useBeforePhysicsStep`. Write your own or use the built-in ones.
1717
</Card>
18-
<Card title="Bring Your Own IK" icon="plug">
19-
Plug in any IK solver via `ikSolveFn`, or skip `IkController` entirely and solve IK yourself in `useBeforePhysicsStep`.
18+
<Card title="Pluggable IK" icon="plug">
19+
Swap in any IK solver via `ikSolveFn`, or skip `IkController` entirely and solve IK yourself in `useBeforePhysicsStep`.
2020
</Card>
2121
<Card title="Full MuJoCo" icon="atom">
2222
Contacts, sensors, tendons, flex bodies, raycasting, domain randomization. The full MuJoCo API via React hooks.
@@ -63,7 +63,7 @@ function App() {
6363

6464
This loads the Franka Panda from [DeepMind Menagerie](https://github.com/google-deepmind/mujoco_menagerie), renders all bodies, and adds an interactive IK gizmo on the end-effector.
6565

66-
## Bring Your Own Controller
66+
## Controllers
6767

6868
A controller is a React component that calls `useBeforePhysicsStep` to write `data.ctrl` each frame:
6969

@@ -103,27 +103,23 @@ mujoco-react follows the same pattern as [react-three-rapier](https://github.com
103103
- **Consumers compose everything else**: lights, grid, camera controls, UI, game logic
104104
- **All scene elements are R3F children**: no config objects for visual-only things
105105

106-
Two ways to set up your scene:
106+
`<MujocoCanvas>` wraps R3F `<Canvas>` and forwards all Canvas props. For full control over the Canvas (gl settings, post-processing, etc.), use `<MujocoPhysics>` inside your own:
107107

108108
<Tabs>
109-
<Tab title="MujocoCanvas (quick start)">
110-
Wraps R3F `<Canvas>` for you:
109+
<Tab title="MujocoCanvas">
111110
```tsx
112-
<MujocoCanvas config={config}>
111+
<MujocoCanvas config={config} shadows camera={...}>
113112
<SceneRenderer />
114-
<ContactMarkers />
115113
<IkController config={{ siteName: 'tcp', numJoints: 7 }}>
116114
<IkGizmo />
117115
</IkController>
118116
<OrbitControls />
119-
<ambientLight />
120117
</MujocoCanvas>
121118
```
122119
</Tab>
123-
<Tab title="MujocoPhysics (bring your own Canvas)">
124-
Use inside your own `<Canvas>` for full control over gl settings, post-processing, and R3F context:
120+
<Tab title="MujocoPhysics">
125121
```tsx
126-
<Canvas shadows camera={{ position: [2, 2, 2] }} gl={{ antialias: true }}>
122+
<Canvas shadows camera={...} gl={{ antialias: true }}>
127123
<MujocoPhysics config={config}>
128124
<SceneRenderer />
129125
<MyController />
@@ -139,7 +135,7 @@ Two ways to set up your scene:
139135

140136
<CardGroup cols={2}>
141137
<Card title="Building Controllers" icon="gamepad" href="/guides/building-controllers">
142-
Write your own controller, bring your own IK, use the `createController` factory
138+
Custom controllers, IK solvers, and the `createController` factory
143139
</Card>
144140
<Card title="Installation" icon="download" href="/installation">
145141
Peer dependencies, bundler setup, and WASM notes

docs/overview.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ import { MujocoProvider, MujocoCanvas, SceneRenderer } from 'mujoco-react';
3939

4040
<CardGroup cols={2}>
4141
<Card title="Building Controllers" icon="gamepad" href="/guides/building-controllers">
42-
Write your own controller, bring your own IK
42+
Custom controllers, IK solvers, and the createController factory
4343
</Card>
4444
<Card title="API Reference" icon="code" href="/api/simulation-control">
4545
Simulation control, state management, forces, model introspection

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)