mujoco-react 12.1.1 → 12.2.0

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.
package/README.md CHANGED
@@ -16,19 +16,6 @@ Composable [React Three Fiber](https://docs.pmnd.rs/react-three-fiber) wrapper a
16
16
  npm install mujoco-react three @react-three/fiber @react-three/drei
17
17
  ```
18
18
 
19
- ## Running policies and simulation workloads
20
-
21
- Use `const runtime = await api.createRuntime()` after `onReady`, then await
22
- `runtime.observe()` and `runtime.advance({ steps, controls })`. Physics runs in a
23
- dedicated worker; commands reject when busy instead of accumulating. The runtime
24
- supports cancellation, reset, full snapshots, synchronized camera observations,
25
- and separate physics/capture timing. Use `<CameraView>` for GPU-only previews.
26
-
27
- The viewer has an 8 ms / 100-step per-frame budget. Equivalent inline scene
28
- configs preserve the loaded model. See the [simulation runtime guide](https://dadd.mintlify.app/guides/simulation-runtime)
29
- for ownership, VLA loops, bundling, and performance limits, or try the
30
- [worker demo](https://mujoco-react-example.pages.dev/?demo=runtime).
31
-
32
19
  ## Vite Plugin and Type-Safe Names
33
20
 
34
21
  Use the Vite plugin to generate declaration merging for actuator, sensor, body, joint, site, geom, and keyframe names:
@@ -156,173 +143,6 @@ Use it as a child of `<MujocoCanvas>`:
156
143
  </MujocoCanvas>
157
144
  ```
158
145
 
159
- ## Gaussian Splat Environments
160
-
161
- Gaussian splats are visual context; MuJoCo XML remains the source of physics, contacts, and task fixtures. Use visual-only splats when you only need rendered environment context, and add collision proxy metadata when a workflow needs simplified contact geometry.
162
-
163
- Use `VisualScenarioEffects` when the same MuJoCo task should render under
164
- different camera exposure, fog/background, and deterministic material variants:
165
-
166
- ```tsx
167
- import { ScenarioLighting, VisualScenarioEffects } from "mujoco-react";
168
-
169
- <MujocoCanvas config={sceneConfig}>
170
- <VisualScenarioEffects
171
- scenario={scenario}
172
- materialFilter={({ object }) => object.name.startsWith("prop_")}
173
- />
174
- <ScenarioLighting preset={scenario.lighting} />
175
- </MujocoCanvas>;
176
- ```
177
-
178
- Use the renderer-agnostic boundary from the main package. If your app stores
179
- visual scenarios as data, pass the scenario directly; the component resolves the
180
- splat asset and any paired MJCF collision proxy metadata for you. Visual-only
181
- splats are valid, and readiness tells you whether a collision proxy is required
182
- for your training/physics handoff.
183
-
184
- ```tsx
185
- import { MujocoCanvas, SplatEnvironment, useSplatSceneConfig } from "mujoco-react";
186
-
187
- const splat = useSplatSceneConfig({ sceneConfig, scenario });
188
-
189
- <MujocoCanvas config={splat.sceneConfig}>
190
- {splat.environment ? (
191
- <SplatEnvironment environment={splat.environment} renderer="custom">
192
- <MySplatRenderer src={splat.environment.splat.src} />
193
- </SplatEnvironment>
194
- ) : null}
195
- </MujocoCanvas>;
196
- ```
197
-
198
- When a splat scenario includes paired MJCF collision proxy metadata, render a
199
- generic wireframe preview from that XML with `SplatCollisionProxyPreview`. The
200
- component parses MJCF primitives such as planes, boxes, spheres, capsules, and
201
- mesh placeholders from any fetchable proxy XML; the tabletop example is just one
202
- possible environment.
203
-
204
- ```tsx
205
- import {
206
- SplatCollisionProxyPreview,
207
- SplatEnvironment,
208
- useSplatCollisionProxyGeoms,
209
- useSplatSceneConfig,
210
- } from "mujoco-react";
211
-
212
- const splat = useSplatSceneConfig({ sceneConfig, scenario });
213
- const proxy = splat.environment?.collisionProxy;
214
-
215
- <SplatEnvironment
216
- environment={splat.environment}
217
- collisionProxy={
218
- proxy ? <SplatCollisionProxyPreview collisionProxy={proxy} /> : undefined
219
- }
220
- />;
221
- ```
222
-
223
- Use `useSplatCollisionProxyGeoms()` when your app wants to inspect or style the
224
- proxy primitives itself:
225
-
226
- ```tsx
227
- const proxyPreview = useSplatCollisionProxyGeoms({
228
- collisionProxy: splat.environment?.collisionProxy,
229
- });
230
-
231
- proxyPreview.geoms.map((geom) => geom.type);
232
- ```
233
-
234
- Use `splat.readiness` or `getSplatEnvironmentReadiness(scenario)` to gate
235
- authoring and import flows. The status distinguishes disabled scenarios,
236
- missing visual assets, missing collision proxies, unsupported renderer formats,
237
- and ready environments.
238
-
239
- Use `createSplatSceneConfig()` when the same scene composition needs to run
240
- outside React, such as codegen, import validation, backend handoff metadata, or
241
- tests:
242
-
243
- ```tsx
244
- import { createSplatSceneConfig } from "mujoco-react";
245
-
246
- const splat = createSplatSceneConfig({
247
- sceneConfig,
248
- scenario,
249
- renderer: "spark",
250
- });
251
- ```
252
-
253
- Use `createVisualScenarioExecutionContext()` or
254
- `useVisualScenarioExecutionContext()` when recording rollouts or exporting
255
- LeRobot/HF Jobs handoff artifacts. It resolves the scenario seed, camera
256
- exposure/noise/blur/jitter, material randomization, splat source, collision
257
- proxy, and readiness into one serializable object.
258
-
259
- ```tsx
260
- import { createVisualScenarioExecutionContext } from "mujoco-react";
261
-
262
- const visualContext = createVisualScenarioExecutionContext({
263
- scenario,
264
- renderer: "spark",
265
- variantId,
266
- });
267
-
268
- writeEpisodeManifest({
269
- task,
270
- visualExecutionContext: visualContext,
271
- });
272
- ```
273
-
274
- For MuJoCo + 3DGS composition, derive the optional collision environment from
275
- the same splat metadata and pass the resulting config to `<MujocoCanvas>`:
276
-
277
- ```tsx
278
- const sceneConfig = withSplatEnvironment(
279
- {
280
- src: "/models/xlerobot/",
281
- sceneFile: "xlerobot.xml",
282
- },
283
- kitchenScenario
284
- );
285
- ```
286
-
287
- For first-class Spark rendering, install Spark and import the optional adapter:
288
-
289
- ```bash
290
- npm install @sparkjsdev/spark
291
- ```
292
-
293
- ```tsx
294
- import {
295
- SparkSplatEnvironment,
296
- useSparkSplatEnvironment,
297
- } from "mujoco-react/spark";
298
-
299
- function Scene() {
300
- const splat = useSparkSplatEnvironment({ sceneConfig, scenario });
301
-
302
- return (
303
- <MujocoCanvas config={splat.sceneConfig} gl={{ preserveDrawingBuffer: true }}>
304
- {splat.environment ? (
305
- <SparkSplatEnvironment hideGroundMeshes {...splat.props} />
306
- ) : null}
307
- <StatusBadge status={splat.lifecycle.status} error={splat.lifecycle.error} />
308
- </MujocoCanvas>
309
- );
310
- }
311
- ```
312
-
313
- `SparkSplatEnvironment` currently renders `.spz` assets. Use the renderer-agnostic
314
- `SplatEnvironment` for `.ply`/`.splat` metadata or when wiring a different renderer.
315
- Tune live rendering and snapshots separately with `renderTuning` and
316
- `captureTuning`:
317
-
318
- ```tsx
319
- <SparkSplatEnvironment
320
- {...splat.props}
321
- renderTuning={{ lodSplatScale: 0.75, minSortIntervalMs: 50 }}
322
- captureTuning={{ lodSplatScale: 1.4, lodRenderScale: 0.45, maxWarmupFrames: 6 }}
323
- />
324
- ```
325
-
326
146
  ## Write Controllers
327
147
 
328
148
  ```tsx
@@ -470,6 +290,34 @@ function PolicyDriver() {
470
290
 
471
291
  Use `output: "float64"` when a downstream model expects double precision. Named resources are skipped when absent, so `obs.layout` is the source of truth for the current model.
472
292
 
293
+ ## Metric RGB-D Capture
294
+
295
+ Capture aligned RGB and metric depth for browser robotics observations, including
296
+ LIBERO. Use a camera name from your MJCF:
297
+
298
+ ```tsx
299
+ const capture = useCameraFrameCapture({
300
+ cameraName: "agentview",
301
+ width: 256,
302
+ height: 256,
303
+ mujocoCameraCompatibility: true,
304
+ });
305
+ const frame = await capture.captureRGBD();
306
+ // frame.rgb: Uint8Array, sRGB RGB bytes, top-left origin
307
+ // frame.depth: Float32Array, meters along camera -Z, Infinity for background
308
+ ```
309
+
310
+ Also available as `api.captureCameraRGBD(options)`, the standalone
311
+ `captureCameraRGBD(renderer, scene, camera, options)`, and
312
+ `session.captureRGBD(options)` on reusable camera capture sessions. One render
313
+ produces both arrays; each result owns its buffers and camera matrix snapshots.
314
+ Scene coordinates must be meters. Custom renderers, logarithmic depth, and
315
+ reversed depth fail explicitly. The example app's `?demo=rgbd` route shows
316
+ reference objects and aligned RGB/depth previews.
317
+
318
+ See [camera capture docs](docs/hooks/use-camera-frame-capture.mdx#metric-rgb-d-capture)
319
+ for projection metadata, moving-camera sessions, and coordinate conventions.
320
+
473
321
  ## WebSocket Control
474
322
 
475
323
  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):
@@ -1405,6 +1253,173 @@ function ClickSelectOverlay() {
1405
1253
 
1406
1254
  See [Click-to-Select](https://dadd.mintlify.app/guides/click-to-select) for the full implementation.
1407
1255
 
1256
+ ## Gaussian Splat Environments
1257
+
1258
+ Gaussian splats are visual context; MuJoCo XML remains the source of physics, contacts, and task fixtures. Use visual-only splats when you only need rendered environment context, and add collision proxy metadata when a workflow needs simplified contact geometry.
1259
+
1260
+ Use `VisualScenarioEffects` when the same MuJoCo task should render under
1261
+ different camera exposure, fog/background, and deterministic material variants:
1262
+
1263
+ ```tsx
1264
+ import { ScenarioLighting, VisualScenarioEffects } from "mujoco-react";
1265
+
1266
+ <MujocoCanvas config={sceneConfig}>
1267
+ <VisualScenarioEffects
1268
+ scenario={scenario}
1269
+ materialFilter={({ object }) => object.name.startsWith("prop_")}
1270
+ />
1271
+ <ScenarioLighting preset={scenario.lighting} />
1272
+ </MujocoCanvas>;
1273
+ ```
1274
+
1275
+ Use the renderer-agnostic boundary from the main package. If your app stores
1276
+ visual scenarios as data, pass the scenario directly; the component resolves the
1277
+ splat asset and any paired MJCF collision proxy metadata for you. Visual-only
1278
+ splats are valid, and readiness tells you whether a collision proxy is required
1279
+ for your training/physics handoff.
1280
+
1281
+ ```tsx
1282
+ import { MujocoCanvas, SplatEnvironment, useSplatSceneConfig } from "mujoco-react";
1283
+
1284
+ const splat = useSplatSceneConfig({ sceneConfig, scenario });
1285
+
1286
+ <MujocoCanvas config={splat.sceneConfig}>
1287
+ {splat.environment ? (
1288
+ <SplatEnvironment environment={splat.environment} renderer="custom">
1289
+ <MySplatRenderer src={splat.environment.splat.src} />
1290
+ </SplatEnvironment>
1291
+ ) : null}
1292
+ </MujocoCanvas>;
1293
+ ```
1294
+
1295
+ When a splat scenario includes paired MJCF collision proxy metadata, render a
1296
+ generic wireframe preview from that XML with `SplatCollisionProxyPreview`. The
1297
+ component parses MJCF primitives such as planes, boxes, spheres, capsules, and
1298
+ mesh placeholders from any fetchable proxy XML; the tabletop example is just one
1299
+ possible environment.
1300
+
1301
+ ```tsx
1302
+ import {
1303
+ SplatCollisionProxyPreview,
1304
+ SplatEnvironment,
1305
+ useSplatCollisionProxyGeoms,
1306
+ useSplatSceneConfig,
1307
+ } from "mujoco-react";
1308
+
1309
+ const splat = useSplatSceneConfig({ sceneConfig, scenario });
1310
+ const proxy = splat.environment?.collisionProxy;
1311
+
1312
+ <SplatEnvironment
1313
+ environment={splat.environment}
1314
+ collisionProxy={
1315
+ proxy ? <SplatCollisionProxyPreview collisionProxy={proxy} /> : undefined
1316
+ }
1317
+ />;
1318
+ ```
1319
+
1320
+ Use `useSplatCollisionProxyGeoms()` when your app wants to inspect or style the
1321
+ proxy primitives itself:
1322
+
1323
+ ```tsx
1324
+ const proxyPreview = useSplatCollisionProxyGeoms({
1325
+ collisionProxy: splat.environment?.collisionProxy,
1326
+ });
1327
+
1328
+ proxyPreview.geoms.map((geom) => geom.type);
1329
+ ```
1330
+
1331
+ Use `splat.readiness` or `getSplatEnvironmentReadiness(scenario)` to gate
1332
+ authoring and import flows. The status distinguishes disabled scenarios,
1333
+ missing visual assets, missing collision proxies, unsupported renderer formats,
1334
+ and ready environments.
1335
+
1336
+ Use `createSplatSceneConfig()` when the same scene composition needs to run
1337
+ outside React, such as codegen, import validation, backend handoff metadata, or
1338
+ tests:
1339
+
1340
+ ```tsx
1341
+ import { createSplatSceneConfig } from "mujoco-react";
1342
+
1343
+ const splat = createSplatSceneConfig({
1344
+ sceneConfig,
1345
+ scenario,
1346
+ renderer: "spark",
1347
+ });
1348
+ ```
1349
+
1350
+ Use `createVisualScenarioExecutionContext()` or
1351
+ `useVisualScenarioExecutionContext()` when recording rollouts or exporting
1352
+ LeRobot/HF Jobs handoff artifacts. It resolves the scenario seed, camera
1353
+ exposure/noise/blur/jitter, material randomization, splat source, collision
1354
+ proxy, and readiness into one serializable object.
1355
+
1356
+ ```tsx
1357
+ import { createVisualScenarioExecutionContext } from "mujoco-react";
1358
+
1359
+ const visualContext = createVisualScenarioExecutionContext({
1360
+ scenario,
1361
+ renderer: "spark",
1362
+ variantId,
1363
+ });
1364
+
1365
+ writeEpisodeManifest({
1366
+ task,
1367
+ visualExecutionContext: visualContext,
1368
+ });
1369
+ ```
1370
+
1371
+ For MuJoCo + 3DGS composition, derive the optional collision environment from
1372
+ the same splat metadata and pass the resulting config to `<MujocoCanvas>`:
1373
+
1374
+ ```tsx
1375
+ const sceneConfig = withSplatEnvironment(
1376
+ {
1377
+ src: "/models/xlerobot/",
1378
+ sceneFile: "xlerobot.xml",
1379
+ },
1380
+ kitchenScenario
1381
+ );
1382
+ ```
1383
+
1384
+ For first-class Spark rendering, install Spark and import the optional adapter:
1385
+
1386
+ ```bash
1387
+ npm install @sparkjsdev/spark
1388
+ ```
1389
+
1390
+ ```tsx
1391
+ import {
1392
+ SparkSplatEnvironment,
1393
+ useSparkSplatEnvironment,
1394
+ } from "mujoco-react/spark";
1395
+
1396
+ function Scene() {
1397
+ const splat = useSparkSplatEnvironment({ sceneConfig, scenario });
1398
+
1399
+ return (
1400
+ <MujocoCanvas config={splat.sceneConfig} gl={{ preserveDrawingBuffer: true }}>
1401
+ {splat.environment ? (
1402
+ <SparkSplatEnvironment hideGroundMeshes {...splat.props} />
1403
+ ) : null}
1404
+ <StatusBadge status={splat.lifecycle.status} error={splat.lifecycle.error} />
1405
+ </MujocoCanvas>
1406
+ );
1407
+ }
1408
+ ```
1409
+
1410
+ `SparkSplatEnvironment` currently renders `.spz` assets. Use the renderer-agnostic
1411
+ `SplatEnvironment` for `.ply`/`.splat` metadata or when wiring a different renderer.
1412
+ Tune live rendering and snapshots separately with `renderTuning` and
1413
+ `captureTuning`:
1414
+
1415
+ ```tsx
1416
+ <SparkSplatEnvironment
1417
+ {...splat.props}
1418
+ renderTuning={{ lodSplatScale: 0.75, minSortIntervalMs: 50 }}
1419
+ captureTuning={{ lodSplatScale: 1.4, lodRenderScale: 0.45, maxWarmupFrames: 6 }}
1420
+ />
1421
+ ```
1422
+
1408
1423
  ## useFrame Priority
1409
1424
 
1410
1425
  | Priority | Owner | Purpose |
@@ -1434,3 +1449,8 @@ Apache-2.0
1434
1449
  ## Contacts and plasticity
1435
1450
 
1436
1451
  Use MJCF speculative contacts for fast rigid objects and yielding springs for permanent deformation. The existing model/data interface exposes enable flags and plastic state; full snapshots preserve plastic history. See the [guide](docs/guides/engine-features.mdx) and [interactive demos](https://mujoco-react-example.pages.dev/?demo=speculative).
1452
+
1453
+ Live splat camera streams use background sorting and reuse prepared splats, so
1454
+ robot motion does not force a splat rebuild on every preview frame. IK gizmos
1455
+ remain visible in the main view and excluded from captures. One-off and policy
1456
+ captures keep snapshot behavior; `renderMode: 'snapshot'` opts a stream into it.