mujoco-react 8.0.0 → 8.1.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
@@ -24,18 +24,18 @@ import {
24
24
  MujocoCanvas,
25
25
  useIkController,
26
26
  IkGizmo,
27
- } from 'mujoco-react';
28
- import type { SceneConfig } from 'mujoco-react';
29
- import { OrbitControls } from '@react-three/drei';
27
+ } from "mujoco-react";
28
+ import type { SceneConfig } from "mujoco-react";
29
+ import { OrbitControls } from "@react-three/drei";
30
30
 
31
31
  const config: SceneConfig = {
32
- src: 'https://raw.githubusercontent.com/google-deepmind/mujoco_menagerie/main/franka_emika_panda/',
33
- sceneFile: 'scene.xml',
32
+ src: "https://raw.githubusercontent.com/google-deepmind/mujoco_menagerie/main/franka_emika_panda/",
33
+ sceneFile: "scene.xml",
34
34
  homeJoints: [1.707, -1.754, 0.003, -2.702, 0.003, 0.951, 2.490],
35
35
  };
36
36
 
37
37
  function Scene() {
38
- const ik = useIkController({ siteName: 'tcp', numJoints: 7 });
38
+ const ik = useIkController({ siteName: "tcp", numJoints: 7 });
39
39
  return (
40
40
  <>
41
41
  <OrbitControls enableDamping makeDefault />
@@ -53,7 +53,7 @@ function App() {
53
53
  config={config}
54
54
  camera={{ position: [2, -1.5, 2.5], up: [0, 0, 1], fov: 45 }}
55
55
  shadows
56
- style={{ width: '100%', height: '100vh' }}
56
+ style={{ width: "100%", height: "100vh" }}
57
57
  >
58
58
  <Scene />
59
59
  </MujocoCanvas>
@@ -67,7 +67,7 @@ function App() {
67
67
  Inside `<MujocoCanvas>` or `<MujocoPhysics>`, `useMujoco()` gives you the simulation API, refs to the live model/data, and status:
68
68
 
69
69
  ```tsx
70
- import { useMujoco } from 'mujoco-react';
70
+ import { useMujoco } from "mujoco-react";
71
71
 
72
72
  function MyComponent() {
73
73
  const { isPending, isError, error, api, mjModelRef } = useMujoco();
@@ -88,15 +88,16 @@ function MyComponent() {
88
88
  A controller is a React component that uses handle-based hooks for type-safe actuator and sensor access:
89
89
 
90
90
  ```tsx
91
- import { useCtrl, useSensor, useBeforePhysicsStep } from 'mujoco-react';
91
+ import { useCtrl, useSensor, useBeforePhysicsStep } from "mujoco-react";
92
92
 
93
93
  function MyController() {
94
- const joint1 = useCtrl('joint1');
95
- const force = useSensor('force_sensor');
94
+ const shoulder = useCtrl("shoulder");
95
+ const elbow = useCtrl("elbow");
96
+ const force = useSensor("force_sensor");
96
97
 
97
98
  useBeforePhysicsStep(() => {
98
- joint1.write(Math.sin(Date.now() / 1000));
99
- joint1.write(force.read()[0] * -0.5);
99
+ shoulder.write(Math.sin(Date.now() / 1000));
100
+ elbow.write(force.read()[0] * -0.5);
100
101
  });
101
102
  return null;
102
103
  }
@@ -113,10 +114,10 @@ Drop it into the tree:
113
114
  The `createController<TConfig>()` factory adds typed config and default merging for reusable plugins:
114
115
 
115
116
  ```tsx
116
- import { createController, useBeforePhysicsStep } from 'mujoco-react';
117
+ import { createController, useBeforePhysicsStep } from "mujoco-react";
117
118
 
118
119
  export const MyController = createController<{ gain: number }>(
119
- { name: 'MyController', defaultConfig: { gain: 1.0 } },
120
+ { name: "MyController", defaultConfig: { gain: 1.0 } },
120
121
  ({ config }) => {
121
122
  useBeforePhysicsStep((_model, data) => {
122
123
  data.ctrl[0] = config.gain * Math.sin(data.time);
@@ -148,13 +149,13 @@ export const MyController = createController<{ gain: number }>(
148
149
  The built-in `useIkController()` uses Damped Least-Squares. Pass `ikSolveFn` to swap in your own solver (analytical, learned, etc.):
149
150
 
150
151
  ```tsx
151
- import type { IKSolveFn } from 'mujoco-react';
152
+ import type { IKSolveFn } from "mujoco-react";
152
153
 
153
154
  const myIK: IKSolveFn = (pos, quat, currentQ) => {
154
155
  return myAnalyticalSolver(pos, currentQ); // return joint angles or null
155
156
  };
156
157
 
157
- const ik = useIkController({ siteName: 'tcp', numJoints: 7, ikSolveFn: myIK });
158
+ const ik = useIkController({ siteName: "tcp", numJoints: 7, ikSolveFn: myIK });
158
159
  ```
159
160
 
160
161
  ### `useIkController(config | null)`
@@ -162,7 +163,7 @@ const ik = useIkController({ siteName: 'tcp', numJoints: 7, ikSolveFn: myIK });
162
163
  Hook for interactive end-effector control. Pass `null` to disable IK (safe to call unconditionally):
163
164
 
164
165
  ```tsx
165
- const ik = useIkController({ siteName: 'tcp', numJoints: 7 });
166
+ const ik = useIkController({ siteName: "tcp", numJoints: 7 });
166
167
  return ik ? <IkGizmo controller={ik} /> : null;
167
168
  ```
168
169
 
@@ -184,11 +185,11 @@ Use TypeScript module augmentation to get autocomplete and type checking for act
184
185
 
185
186
  ```ts
186
187
  // e.g. in src/mujoco-register.d.ts
187
- declare module 'mujoco-react' {
188
+ declare module "mujoco-react" {
188
189
  interface Register {
189
- actuators: 'joint1' | 'joint2' | 'joint3' | 'gripper';
190
- sensors: 'force_sensor' | 'torque_sensor';
191
- bodies: 'link0' | 'link1' | 'hand';
190
+ actuators: "joint1" | "joint2" | "joint3" | "gripper";
191
+ sensors: "force_sensor" | "torque_sensor";
192
+ bodies: "link0" | "link1" | "hand";
192
193
  }
193
194
  }
194
195
  ```
@@ -202,14 +203,14 @@ The loader fetches `src + sceneFile`, parses the XML for dependencies (meshes, t
202
203
  ```tsx
203
204
  // MuJoCo Menagerie
204
205
  const franka: SceneConfig = {
205
- src: 'https://raw.githubusercontent.com/google-deepmind/mujoco_menagerie/main/franka_emika_panda/',
206
- sceneFile: 'scene.xml',
206
+ src: "https://raw.githubusercontent.com/google-deepmind/mujoco_menagerie/main/franka_emika_panda/",
207
+ sceneFile: "scene.xml",
207
208
  };
208
209
 
209
210
  // Any URL
210
211
  const custom: SceneConfig = {
211
- src: 'http://localhost:3000/models/my_model/',
212
- sceneFile: 'model.xml',
212
+ src: "http://localhost:3000/models/my_model/",
213
+ sceneFile: "model.xml",
213
214
  };
214
215
  ```
215
216
 
@@ -218,7 +219,7 @@ const custom: SceneConfig = {
218
219
  ```ts
219
220
  interface SceneConfig {
220
221
  src: string; // Base URL for model files
221
- sceneFile: string; // Entry XML file, e.g. 'scene.xml'
222
+ sceneFile: string; // Entry XML file, e.g. "scene.xml"
222
223
  sceneObjects?: SceneObject[]; // Objects injected into scene XML at load time
223
224
  homeJoints?: number[]; // Initial joint positions
224
225
  xmlPatches?: XmlPatch[]; // Patches applied to XML files during loading
@@ -230,12 +231,12 @@ interface SceneConfig {
230
231
 
231
232
  ```tsx
232
233
  const config: SceneConfig = {
233
- src: 'https://raw.githubusercontent.com/google-deepmind/mujoco_menagerie/main/franka_emika_panda/',
234
- sceneFile: 'scene.xml',
234
+ src: "https://raw.githubusercontent.com/google-deepmind/mujoco_menagerie/main/franka_emika_panda/",
235
+ sceneFile: "scene.xml",
235
236
  sceneObjects: [
236
- { name: 'ball', type: 'sphere', size: [0.03, 0.03, 0.03],
237
+ { name: "ball", type: "sphere", size: [0.03, 0.03, 0.03],
237
238
  position: [0.5, 0, 0.1], rgba: [1, 0, 0, 1], mass: 0.1, freejoint: true },
238
- { name: 'platform', type: 'box', size: [0.2, 0.2, 0.01],
239
+ { name: "platform", type: "box", size: [0.2, 0.2, 0.01],
239
240
  position: [0.4, 0.3, 0], rgba: [0.5, 0.5, 0.5, 1] },
240
241
  ],
241
242
  };
@@ -245,10 +246,10 @@ const config: SceneConfig = {
245
246
 
246
247
  ```tsx
247
248
  xmlPatches: [{
248
- target: 'panda.xml',
249
- replace: ['name="actuator8"', 'name="gripper"'],
250
- inject: '<site name="tcp" pos="0 0 0.1" size="0.01"/>',
251
- injectAfter: '<body name="hand"',
249
+ target: "panda.xml",
250
+ replace: ["name=\"actuator8\"", "name=\"gripper\""],
251
+ inject: "<site name=\"tcp\" pos=\"0 0 0.1\" size=\"0.01\"/>",
252
+ injectAfter: "<body name=\"hand\"",
252
253
  }]
253
254
  ```
254
255
 
@@ -372,7 +373,7 @@ InstancedMesh showing MuJoCo contact points for debugging.
372
373
  |------|------|---------|-------------|
373
374
  | `maxContacts` | `number?` | `100` | Max contacts to display |
374
375
  | `radius` | `number?` | `0.005` | Marker sphere radius |
375
- | `color` | `string?` | `'#4f46e5'` | Marker color |
376
+ | `color` | `string?` | `"#4f46e5"` | Marker color |
376
377
  | `visible` | `boolean?` | `true` | Toggle visibility |
377
378
 
378
379
  ### `<SceneLights />`
@@ -392,10 +393,10 @@ Visualization overlays:
392
393
  | `showCOM` | `boolean?` | `false` | Center of mass markers |
393
394
  | `showInertia` | `boolean?` | `false` | Inertia ellipsoids |
394
395
  | `showTendons` | `boolean?` | `false` | Tendon paths |
395
- | `geomColor` | `string?` | `'#00ff00'` | Color for wireframe geoms |
396
- | `siteColor` | `string?` | `'#ff00ff'` | Color for site markers |
397
- | `contactColor` | `string?` | `'#ff4444'` | Color for contact force arrows |
398
- | `comColor` | `string?` | `'#ff0000'` | Color for COM markers |
396
+ | `geomColor` | `string?` | `"#00ff00"` | Color for wireframe geoms |
397
+ | `siteColor` | `string?` | `"#ff00ff"` | Color for site markers |
398
+ | `contactColor` | `string?` | `"#ff4444"` | Color for contact force arrows |
399
+ | `comColor` | `string?` | `"#ff0000"` | Color for COM markers |
399
400
 
400
401
  ### `<TendonRenderer />`
401
402
 
@@ -412,8 +413,8 @@ Component wrapper for contact events:
412
413
  ```tsx
413
414
  <ContactListener
414
415
  body="block_1"
415
- onContactEnter={(info) => console.log('contact!', info)}
416
- onContactExit={(info) => console.log('released', info)}
416
+ onContactEnter={(info) => console.log("contact!", info)}
417
+ onContactExit={(info) => console.log("released", info)}
417
418
  />
418
419
  ```
419
420
 
@@ -439,12 +440,12 @@ if (sim.isReady) {
439
440
  Access the raw WASM module lifecycle from any child of `<MujocoProvider>`. Most users won't need this — `useMujoco()` and hooks like `useBeforePhysicsStep` handle the model/data lifecycle for you.
440
441
 
441
442
  ```tsx
442
- import { useMujocoWasm } from 'mujoco-react';
443
+ import { useMujocoWasm } from "mujoco-react";
443
444
 
444
445
  const { mujoco, status } = useMujocoWasm();
445
446
 
446
447
  if (mujoco) {
447
- const model = mujoco.MjModel.loadFromXML('/path/to/scene.xml');
448
+ const model = mujoco.MjModel.loadFromXML("/path/to/scene.xml");
448
449
  const data = new mujoco.MjData(model);
449
450
  mujoco.mj_step(model, data);
450
451
  console.log(data.qpos); // joint positions after one step
@@ -489,8 +490,8 @@ await moveCameraTo(
489
490
  Read sensor values by name. Returns a `SensorHandle` with `read()`, `dim`, and `name`:
490
491
 
491
492
  ```tsx
492
- const force = useSensor('force_sensor_1');
493
- // force.read() Float64Array, force.dim number
493
+ const force = useSensor("force_sensor_1");
494
+ // force.read() -> Float64Array, force.dim -> number
494
495
  ```
495
496
 
496
497
  ### `useBodyState(name)`
@@ -498,7 +499,7 @@ const force = useSensor('force_sensor_1');
498
499
  Position, quaternion, linear/angular velocity of a body (ref-based):
499
500
 
500
501
  ```tsx
501
- const { position, quaternion, linearVelocity, angularVelocity } = useBodyState('block_1');
502
+ const { position, quaternion, linearVelocity, angularVelocity } = useBodyState("block_1");
502
503
  ```
503
504
 
504
505
  ### `useJointState(name)`
@@ -506,7 +507,7 @@ const { position, quaternion, linearVelocity, angularVelocity } = useBodyState('
506
507
  Joint position and velocity:
507
508
 
508
509
  ```tsx
509
- const { position, velocity } = useJointState('joint1');
510
+ const { position, velocity } = useJointState("joint1");
510
511
  ```
511
512
 
512
513
  ### `useCtrl(name)`
@@ -514,8 +515,8 @@ const { position, velocity } = useJointState('joint1');
514
515
  Read/write actuator control by name. Returns a `CtrlHandle` with `read()`, `write()`, `name`, and `range`:
515
516
 
516
517
  ```tsx
517
- const gripper = useCtrl('gripper');
518
- // gripper.read() number, gripper.write(0.04), gripper.range [min, max]
518
+ const gripper = useCtrl("gripper");
519
+ // gripper.read() -> number, gripper.write(0.04), gripper.range -> [min, max]
519
520
  ```
520
521
 
521
522
  ### `useContacts(bodyName?)` / `useContactEvents(bodyName, handlers)`
@@ -523,9 +524,9 @@ const gripper = useCtrl('gripper');
523
524
  Query contacts or subscribe to enter/exit events:
524
525
 
525
526
  ```tsx
526
- useContactEvents('block_1', {
527
- onEnter: (info) => console.log('contact!', info),
528
- onExit: (info) => console.log('released', info),
527
+ useContactEvents("block_1", {
528
+ onEnter: (info) => console.log("contact!", info),
529
+ onExit: (info) => console.log("released", info),
529
530
  });
530
531
  ```
531
532
 
@@ -536,9 +537,9 @@ Map keyboard keys to actuators:
536
537
  ```tsx
537
538
  useKeyboardTeleop({
538
539
  bindings: {
539
- 'w': { actuator: 'forward', delta: 0.1 },
540
- 's': { actuator: 'forward', delta: -0.1 },
541
- 'v': { actuator: 'gripper', toggle: [0, 0.04] },
540
+ "w": { actuator: "forward", delta: 0.1 },
541
+ "s": { actuator: "forward", delta: -0.1 },
542
+ "v": { actuator: "gripper", toggle: [0, 0.04] },
542
543
  },
543
544
  });
544
545
  ```
@@ -549,8 +550,8 @@ Map gamepad axes/buttons to actuators:
549
550
 
550
551
  ```tsx
551
552
  useGamepad({
552
- axes: { 0: 'joint1', 1: 'joint2' },
553
- buttons: { 0: 'gripper' },
553
+ axes: { 0: "joint1", 1: "joint2" },
554
+ buttons: { 0: "gripper" },
554
555
  deadzone: 0.1,
555
556
  });
556
557
  ```
@@ -572,11 +573,23 @@ const { step, isRunning } = usePolicy({
572
573
  Record and play back simulation trajectories:
573
574
 
574
575
  ```tsx
575
- const recorder = useTrajectoryRecorder({ fields: ['qpos', 'qvel', 'ctrl'] });
576
- // recorder.start(), recorder.stop(), recorder.downloadJSON(), recorder.downloadCSV()
576
+ // Record
577
+ const recorder = useTrajectoryRecorder({ fields: ["qpos", "ctrl"] });
578
+ recorder.start();
579
+ // ... interact with simulation ...
580
+ recorder.stop();
577
581
 
578
- const player = useTrajectoryPlayer(trajectory, { fps: 30, loop: true });
579
- // player.play(), player.pause(), player.seek(frameIdx)
582
+ // Play back recorded frames directly (no conversion needed)
583
+ const player = useTrajectoryPlayer(recorder.frames, {
584
+ fps: 30,
585
+ speed: 1.0, // 0.5x, 1x, 2x, etc.
586
+ loop: true,
587
+ mode: "kinematic", // or "physics" to replay ctrl through the sim
588
+ onComplete: () => console.log("done"),
589
+ });
590
+ // player.play(), player.pause(), player.seek(42), player.setSpeed(2)
591
+ // player.state → "idle" | "playing" | "paused" | "completed"
592
+ // player.progress → 0-1
580
593
  ```
581
594
 
582
595
  ### `useVideoRecorder(config)`
@@ -584,7 +597,7 @@ const player = useTrajectoryPlayer(trajectory, { fps: 30, loop: true });
584
597
  Record the canvas as video:
585
598
 
586
599
  ```tsx
587
- const video = useVideoRecorder({ fps: 30, mimeType: 'video/webm' });
600
+ const video = useVideoRecorder({ fps: 30, mimeType: "video/webm" });
588
601
  // video.start(), video.stop() -> returns Blob
589
602
  ```
590
603
 
@@ -623,7 +636,7 @@ const meshes = useBodyMeshes(selectedBodyId);
623
636
  Convenience wrapper around `useBodyMeshes` that applies an emissive highlight:
624
637
 
625
638
  ```tsx
626
- useSelectionHighlight(selectedBodyId, { color: '#00ff00', emissiveIntensity: 0.5 });
639
+ useSelectionHighlight(selectedBodyId, { color: "#00ff00", emissiveIntensity: 0.5 });
627
640
  ```
628
641
 
629
642
  ### `useSceneLights(intensity?)`
package/dist/index.d.ts CHANGED
@@ -403,6 +403,7 @@ interface TrajectoryData {
403
403
  frames: TrajectoryFrame[];
404
404
  fps: number;
405
405
  }
406
+ type PlaybackState = 'idle' | 'playing' | 'paused' | 'completed';
406
407
  interface KeyBinding {
407
408
  actuator: Actuators;
408
409
  delta?: number;
@@ -441,12 +442,17 @@ interface SceneLightsProps {
441
442
  /** Override intensity for all MJCF lights. Default: 1.0. */
442
443
  intensity?: number;
443
444
  }
445
+ type TrajectoryInput = TrajectoryFrame[] | number[][];
444
446
  interface TrajectoryPlayerProps {
445
- trajectory: number[][];
447
+ trajectory: TrajectoryInput;
446
448
  fps?: number;
449
+ speed?: number;
447
450
  loop?: boolean;
448
451
  playing?: boolean;
452
+ mode?: 'kinematic' | 'physics';
449
453
  onFrame?: (frameIdx: number) => void;
454
+ onComplete?: () => void;
455
+ onStateChange?: (state: PlaybackState) => void;
450
456
  }
451
457
  interface ContactListenerProps {
452
458
  body: Bodies;
@@ -898,7 +904,7 @@ declare function ContactListener({ body, onContactEnter, onContactExit, }: Conta
898
904
  * Component wrapper for useTrajectoryPlayer.
899
905
  * Provides declarative trajectory playback controlled via props.
900
906
  */
901
- declare function TrajectoryPlayer({ trajectory, fps, loop, playing, onFrame, }: TrajectoryPlayerProps): null;
907
+ declare function TrajectoryPlayer({ trajectory, fps, speed, loop, playing, mode, onFrame, onComplete, onStateChange, }: TrajectoryPlayerProps): null;
902
908
 
903
909
  /**
904
910
  * @license
@@ -1070,24 +1076,38 @@ declare function usePolicy(config: PolicyConfig): {
1070
1076
  *
1071
1077
  * useTrajectoryPlayer — trajectory playback/scrubbing (spec 13.2)
1072
1078
  */
1079
+
1073
1080
  interface TrajectoryPlayerOptions {
1074
1081
  fps?: number;
1082
+ speed?: number;
1075
1083
  loop?: boolean;
1084
+ mode?: 'kinematic' | 'physics';
1085
+ onComplete?: () => void;
1086
+ onStateChange?: (state: PlaybackState) => void;
1076
1087
  }
1077
1088
  /**
1078
- * Play back a sequence of qpos frames, overriding simulation state.
1089
+ * Play back a trajectory, overriding simulation state.
1090
+ *
1091
+ * Accepts either `TrajectoryFrame[]` (from useTrajectoryRecorder) or
1092
+ * `number[][]` (raw qpos arrays).
1093
+ *
1094
+ * In `kinematic` mode (default), the simulation is paused and qpos is
1095
+ * set directly each frame with mj_forward for rendering.
1079
1096
  *
1080
- * When playing, the simulation is effectively paused and qpos is set
1081
- * from the trajectory each render frame at the specified FPS.
1097
+ * In `physics` mode, the simulation keeps running and ctrl values from
1098
+ * the trajectory are applied each physics step via useBeforePhysicsStep.
1082
1099
  */
1083
- declare function useTrajectoryPlayer(trajectory: number[][], options?: TrajectoryPlayerOptions): {
1100
+ declare function useTrajectoryPlayer(trajectory: TrajectoryInput, options?: TrajectoryPlayerOptions): {
1084
1101
  play: () => void;
1085
1102
  pause: () => void;
1086
1103
  seek: (frameIdx: number) => void;
1087
1104
  reset: () => void;
1105
+ setSpeed: (s: number) => void;
1106
+ readonly state: PlaybackState;
1088
1107
  readonly frame: number;
1089
1108
  readonly playing: boolean;
1090
1109
  readonly totalFrames: number;
1110
+ readonly progress: number;
1091
1111
  };
1092
1112
 
1093
1113
  /**
@@ -1254,4 +1274,4 @@ interface CameraAnimationAPI {
1254
1274
  */
1255
1275
  declare function useCameraAnimation(): CameraAnimationAPI;
1256
1276
 
1257
- export { type ActuatorInfo, type Actuators, type Bodies, Body, type BodyInfo, type BodyProps, type BodyStateResult, type CameraAnimationAPI, type ContactInfo, ContactListener, type ContactListenerProps, ContactMarkers, type ControllerComponent, type ControllerOptions, type CtrlHandle, Debug, type DebugProps, DragInteraction, type DragInteractionProps, FlexRenderer, type GeomInfo, type Geoms, type IKSolveFn, type IkConfig, type IkContextValue, IkGizmo, type IkGizmoProps, type JointInfo, type JointStateResult, type Joints, type KeyBinding, type KeyboardTeleopConfig, type Keyframes, type ModelOptions, MujocoCanvas, type MujocoCanvasProps, type MujocoContact, type MujocoContactArray, type MujocoContextValue, type MujocoData, type MujocoModel, type MujocoModule, MujocoPhysics, type MujocoPhysicsProps, MujocoProvider, type MujocoSimAPI, MujocoSimProvider, type PhysicsConfig, type PhysicsStepCallback, type PolicyConfig, type RayHit, type Register, type SceneConfig, SceneLights, type SceneLightsProps, type SceneMarker, type SceneObject, type SensorHandle, type SensorInfo, type SensorResult, type Sensors, type SiteInfo, type SitePositionResult, type Sites, type StateSnapshot, TendonRenderer, type TrajectoryData, type TrajectoryFrame, TrajectoryPlayer, type TrajectoryPlayerProps, type XmlPatch, createController, findActuatorByName, findBodyByName, findGeomByName, findJointByName, findKeyframeByName, findSensorByName, findSiteByName, findTendonByName, getContact, getName, loadScene, useActuators, useAfterPhysicsStep, useBeforePhysicsStep, useBodyMeshes, useBodyState, useCameraAnimation, useContactEvents, useContacts, useCtrl, useCtrlNoise, useGamepad, useGravityCompensation, useIkController, useJointState, useKeyboardTeleop, useMujoco, useMujocoWasm, usePolicy, useSceneLights, useSelectionHighlight, useSensor, useSensors, useSitePosition, useTrajectoryPlayer, useTrajectoryRecorder, useVideoRecorder };
1277
+ export { type ActuatorInfo, type Actuators, type Bodies, Body, type BodyInfo, type BodyProps, type BodyStateResult, type CameraAnimationAPI, type ContactInfo, ContactListener, type ContactListenerProps, ContactMarkers, type ControllerComponent, type ControllerOptions, type CtrlHandle, Debug, type DebugProps, DragInteraction, type DragInteractionProps, FlexRenderer, type GeomInfo, type Geoms, type IKSolveFn, type IkConfig, type IkContextValue, IkGizmo, type IkGizmoProps, type JointInfo, type JointStateResult, type Joints, type KeyBinding, type KeyboardTeleopConfig, type Keyframes, type ModelOptions, MujocoCanvas, type MujocoCanvasProps, type MujocoContact, type MujocoContactArray, type MujocoContextValue, type MujocoData, type MujocoModel, type MujocoModule, MujocoPhysics, type MujocoPhysicsProps, MujocoProvider, type MujocoSimAPI, MujocoSimProvider, type PhysicsConfig, type PhysicsStepCallback, type PlaybackState, type PolicyConfig, type RayHit, type Register, type SceneConfig, SceneLights, type SceneLightsProps, type SceneMarker, type SceneObject, type SensorHandle, type SensorInfo, type SensorResult, type Sensors, type SiteInfo, type SitePositionResult, type Sites, type StateSnapshot, TendonRenderer, type TrajectoryData, type TrajectoryFrame, type TrajectoryInput, TrajectoryPlayer, type TrajectoryPlayerProps, type XmlPatch, createController, findActuatorByName, findBodyByName, findGeomByName, findJointByName, findKeyframeByName, findSensorByName, findSiteByName, findTendonByName, getContact, getName, loadScene, useActuators, useAfterPhysicsStep, useBeforePhysicsStep, useBodyMeshes, useBodyState, useCameraAnimation, useContactEvents, useContacts, useCtrl, useCtrlNoise, useGamepad, useGravityCompensation, useIkController, useJointState, useKeyboardTeleop, useMujoco, useMujocoWasm, usePolicy, useSceneLights, useSelectionHighlight, useSensor, useSensors, useSitePosition, useTrajectoryPlayer, useTrajectoryRecorder, useVideoRecorder };