mujoco-react 8.0.0 → 8.1.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.
- package/README.md +77 -64
- package/dist/index.d.ts +27 -7
- package/dist/index.js +191 -76
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/TrajectoryPlayer.tsx +16 -2
- package/src/core/SceneLoader.ts +77 -51
- package/src/hooks/useTrajectoryPlayer.ts +152 -29
- package/src/index.ts +2 -0
- package/src/types.ts +9 -1
package/README.md
CHANGED
|
@@ -24,18 +24,18 @@ import {
|
|
|
24
24
|
MujocoCanvas,
|
|
25
25
|
useIkController,
|
|
26
26
|
IkGizmo,
|
|
27
|
-
} from
|
|
28
|
-
import type { SceneConfig } from
|
|
29
|
-
import { OrbitControls } from
|
|
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:
|
|
33
|
-
sceneFile:
|
|
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:
|
|
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:
|
|
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
|
|
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
|
|
91
|
+
import { useCtrl, useSensor, useBeforePhysicsStep } from "mujoco-react";
|
|
92
92
|
|
|
93
93
|
function MyController() {
|
|
94
|
-
const
|
|
95
|
-
const
|
|
94
|
+
const shoulder = useCtrl("shoulder");
|
|
95
|
+
const elbow = useCtrl("elbow");
|
|
96
|
+
const force = useSensor("force_sensor");
|
|
96
97
|
|
|
97
98
|
useBeforePhysicsStep(() => {
|
|
98
|
-
|
|
99
|
-
|
|
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
|
|
117
|
+
import { createController, useBeforePhysicsStep } from "mujoco-react";
|
|
117
118
|
|
|
118
119
|
export const MyController = createController<{ gain: number }>(
|
|
119
|
-
{ name:
|
|
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
|
|
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:
|
|
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:
|
|
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
|
|
188
|
+
declare module "mujoco-react" {
|
|
188
189
|
interface Register {
|
|
189
|
-
actuators:
|
|
190
|
-
sensors:
|
|
191
|
-
bodies:
|
|
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:
|
|
206
|
-
sceneFile:
|
|
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:
|
|
212
|
-
sceneFile:
|
|
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.
|
|
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:
|
|
234
|
-
sceneFile:
|
|
234
|
+
src: "https://raw.githubusercontent.com/google-deepmind/mujoco_menagerie/main/franka_emika_panda/",
|
|
235
|
+
sceneFile: "scene.xml",
|
|
235
236
|
sceneObjects: [
|
|
236
|
-
{ name:
|
|
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:
|
|
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:
|
|
249
|
-
replace: [
|
|
250
|
-
inject:
|
|
251
|
-
injectAfter:
|
|
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?` | `
|
|
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?` | `
|
|
396
|
-
| `siteColor` | `string?` | `
|
|
397
|
-
| `contactColor` | `string?` | `
|
|
398
|
-
| `comColor` | `string?` | `
|
|
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(
|
|
416
|
-
onContactExit={(info) => console.log(
|
|
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
|
|
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(
|
|
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(
|
|
493
|
-
// force.read()
|
|
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(
|
|
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(
|
|
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(
|
|
518
|
-
// gripper.read()
|
|
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(
|
|
527
|
-
onEnter: (info) => console.log(
|
|
528
|
-
onExit: (info) => console.log(
|
|
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
|
-
|
|
540
|
-
|
|
541
|
-
|
|
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:
|
|
553
|
-
buttons: { 0:
|
|
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
|
-
|
|
576
|
-
|
|
576
|
+
// Record
|
|
577
|
+
const recorder = useTrajectoryRecorder({ fields: ["qpos", "ctrl"] });
|
|
578
|
+
recorder.start();
|
|
579
|
+
// ... interact with simulation ...
|
|
580
|
+
recorder.stop();
|
|
577
581
|
|
|
578
|
-
|
|
579
|
-
|
|
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:
|
|
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:
|
|
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:
|
|
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
|
|
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
|
-
*
|
|
1081
|
-
*
|
|
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:
|
|
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 };
|