mujoco-react 0.2.0 → 0.3.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/dist/index.d.ts CHANGED
@@ -8,6 +8,28 @@ import * as react from 'react';
8
8
  * SPDX-License-Identifier: Apache-2.0
9
9
  */
10
10
 
11
+ /**
12
+ * A single MuJoCo contact from the WASM module.
13
+ * Accessed via `data.contact.get(i)`.
14
+ */
15
+ interface MujocoContact {
16
+ geom1: number;
17
+ geom2: number;
18
+ pos: Float64Array;
19
+ frame: Float64Array;
20
+ dist: number;
21
+ }
22
+ /**
23
+ * WASM contact array — supports indexed access via `.get(i)`.
24
+ */
25
+ interface MujocoContactArray {
26
+ get(i: number): MujocoContact | undefined;
27
+ }
28
+ /**
29
+ * Read a single contact from the WASM contact array.
30
+ * Returns undefined if the access fails (WASM heap issue, bad index, etc.).
31
+ */
32
+ declare function getContact(data: MujocoData, i: number): MujocoContact | undefined;
11
33
  /**
12
34
  * Minimal interface for MuJoCo Model to avoid 'any'.
13
35
  */
@@ -45,11 +67,14 @@ interface MujocoModel {
45
67
  body_geomnum: Int32Array;
46
68
  body_geomadr: Int32Array;
47
69
  body_inertia: Float64Array;
70
+ qpos0: Float64Array;
48
71
  jnt_qposadr: Int32Array;
49
72
  jnt_dofadr: Int32Array;
50
73
  jnt_type: Int32Array;
51
74
  jnt_range: Float64Array;
52
75
  jnt_bodyid: Int32Array;
76
+ jnt_pos: Float64Array;
77
+ jnt_axis: Float64Array;
53
78
  jnt_limited: Uint8Array;
54
79
  geom_group: Int32Array;
55
80
  geom_type: Int32Array;
@@ -135,7 +160,7 @@ interface MujocoData {
135
160
  site_xmat: Float64Array;
136
161
  sensordata: Float64Array;
137
162
  ncon: number;
138
- contact: unknown;
163
+ contact: MujocoContactArray;
139
164
  cvel: Float64Array;
140
165
  cfrc_ext: Float64Array;
141
166
  ten_length: Float64Array;
@@ -212,12 +237,27 @@ interface SceneConfig {
212
237
  sceneFile: string;
213
238
  baseUrl?: string;
214
239
  sceneObjects?: SceneObject[];
215
- tcpSiteName?: string;
216
- gripperActuatorName?: string;
217
- numArmJoints?: number;
218
240
  homeJoints?: number[];
219
241
  xmlPatches?: XmlPatch[];
220
242
  onReset?: (model: MujocoModel, data: MujocoData) => void;
243
+ /** @deprecated Use IkController config.siteName instead. */
244
+ tcpSiteName?: string;
245
+ /** @deprecated Use your own gripper control logic instead. */
246
+ gripperActuatorName?: string;
247
+ /** @deprecated Use IkController config.numJoints instead. */
248
+ numArmJoints?: number;
249
+ }
250
+ interface IkConfig {
251
+ /** MuJoCo site name for IK target. */
252
+ siteName: string;
253
+ /** Number of joints to solve for. */
254
+ numJoints: number;
255
+ /** Custom IK solver. When omitted, uses built-in Damped Least-Squares solver. */
256
+ ikSolveFn?: IKSolveFn;
257
+ /** DLS damping. Default: 0.01. */
258
+ damping?: number;
259
+ /** Max solver iterations. Default: 50. */
260
+ maxIterations?: number;
221
261
  }
222
262
  interface SceneMarker {
223
263
  id: number;
@@ -407,14 +447,6 @@ interface MujocoSimAPI {
407
447
  getKeyframeNames(): string[];
408
448
  getKeyframeCount(): number;
409
449
  loadScene(newConfig: SceneConfig): Promise<void>;
410
- setIkEnabled(enabled: boolean): void;
411
- moveTarget(pos: THREE.Vector3, duration?: number): void;
412
- syncTargetToSite(): void;
413
- solveIK(pos: THREE.Vector3, quat: THREE.Quaternion, currentQ: number[]): number[] | null;
414
- getGizmoStats(): {
415
- pos: THREE.Vector3;
416
- rot: THREE.Euler;
417
- } | null;
418
450
  getCanvasSnapshot(width?: number, height?: number, mimeType?: string): string;
419
451
  project2DTo3D(x: number, y: number, cameraPos: THREE.Vector3, lookAt: THREE.Vector3): {
420
452
  point: THREE.Vector3;
@@ -424,11 +456,6 @@ interface MujocoSimAPI {
424
456
  setBodyMass(name: string, mass: number): void;
425
457
  setGeomFriction(name: string, friction: [number, number, number]): void;
426
458
  setGeomSize(name: string, size: [number, number, number]): void;
427
- getCameraState(): {
428
- position: THREE.Vector3;
429
- target: THREE.Vector3;
430
- };
431
- moveCameraTo(position: THREE.Vector3, target: THREE.Vector3, durationMs: number): Promise<void>;
432
459
  readonly mjModelRef: React.RefObject<MujocoModel | null>;
433
460
  readonly mjDataRef: React.RefObject<MujocoData | null>;
434
461
  }
@@ -477,6 +504,8 @@ interface JointStateResult {
477
504
  declare function useMujoco(): MujocoContextValue;
478
505
  interface MujocoProviderProps {
479
506
  wasmUrl?: string;
507
+ /** Timeout in ms for WASM module load. Default: 30000. */
508
+ timeout?: number;
480
509
  children: React.ReactNode;
481
510
  onError?: (error: Error) => void;
482
511
  }
@@ -484,7 +513,7 @@ interface MujocoProviderProps {
484
513
  * MujocoProvider — WASM / module lifecycle.
485
514
  * Loads the MuJoCo WASM module on mount and provides it to children via context.
486
515
  */
487
- declare function MujocoProvider({ wasmUrl, children, onError }: MujocoProviderProps): react_jsx_runtime.JSX.Element;
516
+ declare function MujocoProvider({ wasmUrl, timeout, children, onError }: MujocoProviderProps): react_jsx_runtime.JSX.Element;
488
517
 
489
518
  /**
490
519
  * MujocoCanvas — thin R3F Canvas wrapper for MuJoCo scenes.
@@ -495,83 +524,19 @@ declare function MujocoProvider({ wasmUrl, children, onError }: MujocoProviderPr
495
524
  */
496
525
  declare const MujocoCanvas: react.ForwardRefExoticComponent<Omit<MujocoCanvasProps, "ref"> & react.RefAttributes<MujocoSimAPI>>;
497
526
 
498
- /**
499
- * @license
500
- * SPDX-License-Identifier: Apache-2.0
501
- */
502
-
503
- interface GenericIKOptions {
504
- maxIterations: number;
505
- damping: number;
506
- tolerance: number;
507
- epsilon: number;
508
- posWeight: number;
509
- rotWeight: number;
510
- }
511
- /**
512
- * Generic Damped Least-Squares IK solver.
513
- * Uses finite-difference Jacobian via MuJoCo's mj_forward.
514
- * Works for any MuJoCo model — no robot-specific parameters.
515
- */
516
- declare class GenericIK {
517
- private mujoco;
518
- constructor(mujoco: MujocoModule);
519
- /**
520
- * Solve IK for a target 6-DOF pose.
521
- * @param model MuJoCo model
522
- * @param data MuJoCo data (qpos will be temporarily modified, then restored)
523
- * @param siteId Index of the end-effector site to control
524
- * @param numJoints Number of arm joints (assumes qpos[0..numJoints-1])
525
- * @param targetPos Target position in world frame
526
- * @param targetQuat Target orientation in world frame
527
- * @param currentQ Current joint angles (length = numJoints)
528
- * @param opts Optional solver parameters
529
- * @returns Joint angles array, or null if solver diverged
530
- */
531
- solve(model: MujocoModel, data: MujocoData, siteId: number, numJoints: number, targetPos: THREE.Vector3, targetQuat: THREE.Quaternion, currentQ: number[], opts?: Partial<GenericIKOptions>): number[] | null;
532
- }
533
-
534
527
  interface MujocoSimContextValue {
535
528
  api: MujocoSimAPI;
536
529
  mjModelRef: React.RefObject<MujocoModel | null>;
537
530
  mjDataRef: React.RefObject<MujocoData | null>;
538
531
  mujocoRef: React.RefObject<MujocoModule>;
539
532
  configRef: React.RefObject<SceneConfig>;
540
- siteIdRef: React.RefObject<number>;
541
- gripperIdRef: React.RefObject<number>;
542
- ikEnabledRef: React.RefObject<boolean>;
543
- ikCalculatingRef: React.RefObject<boolean>;
544
533
  pausedRef: React.RefObject<boolean>;
545
534
  speedRef: React.RefObject<number>;
546
535
  substepsRef: React.RefObject<number>;
547
- ikTargetRef: React.RefObject<THREE.Group>;
548
- genericIkRef: React.RefObject<GenericIK>;
549
- ikSolveFnRef: React.RefObject<IKSolveFn>;
550
- firstIkEnableRef: React.RefObject<boolean>;
551
- gizmoAnimRef: React.RefObject<{
552
- active: boolean;
553
- startPos: THREE.Vector3;
554
- endPos: THREE.Vector3;
555
- startRot: THREE.Quaternion;
556
- endRot: THREE.Quaternion;
557
- startTime: number;
558
- duration: number;
559
- }>;
560
- cameraAnimRef: React.RefObject<{
561
- active: boolean;
562
- startPos: THREE.Vector3;
563
- endPos: THREE.Vector3;
564
- startRot: THREE.Quaternion;
565
- endRot: THREE.Quaternion;
566
- startTarget: THREE.Vector3;
567
- endTarget: THREE.Vector3;
568
- startTime: number;
569
- duration: number;
570
- resolve: (() => void) | null;
571
- }>;
572
536
  onSelectionRef: React.RefObject<((bodyId: number, name: string) => void) | undefined>;
573
537
  beforeStepCallbacks: React.RefObject<Set<PhysicsStepCallback>>;
574
538
  afterStepCallbacks: React.RefObject<Set<PhysicsStepCallback>>;
539
+ resetCallbacks: React.RefObject<Set<() => void>>;
575
540
  status: 'loading' | 'ready' | 'error';
576
541
  }
577
542
  declare function useMujocoSim(): MujocoSimContextValue;
@@ -647,6 +612,81 @@ interface LoadResult {
647
612
  */
648
613
  declare function loadScene(mujoco: MujocoModule, config: SceneConfig, onProgress?: (msg: string) => void): Promise<LoadResult>;
649
614
 
615
+ /**
616
+ * @license
617
+ * SPDX-License-Identifier: Apache-2.0
618
+ *
619
+ * createController — typed factory for BYOC (Bring Your Own Controller) plugins.
620
+ */
621
+ interface ControllerOptions<TConfig> {
622
+ /** Unique name for this controller (used as displayName). */
623
+ name: string;
624
+ /** Default values merged under user-supplied config. */
625
+ defaultConfig?: Partial<TConfig>;
626
+ }
627
+ type ControllerComponent<TConfig> = React.FC<{
628
+ config?: Partial<TConfig>;
629
+ children?: React.ReactNode;
630
+ }> & {
631
+ controllerName: string;
632
+ defaultConfig: Partial<TConfig>;
633
+ };
634
+ /**
635
+ * Factory that produces a typed controller component.
636
+ *
637
+ * Controllers are React components that plug into the MuJoCo simulation tree.
638
+ * Inside `Impl`, use any hooks (`useMujocoSim`, `useBeforePhysicsStep`, etc.)
639
+ * to interact with the physics engine.
640
+ *
641
+ * @example
642
+ * ```tsx
643
+ * const MyController = createController<{ speed: number }>(
644
+ * { name: 'my-controller', defaultConfig: { speed: 1.0 } },
645
+ * function MyControllerImpl({ config }) {
646
+ * useBeforePhysicsStep((_model, data) => {
647
+ * data.ctrl[0] = config.speed;
648
+ * });
649
+ * return null;
650
+ * },
651
+ * );
652
+ *
653
+ * // Usage:
654
+ * <MyController config={{ speed: 2.0 }} />
655
+ * ```
656
+ */
657
+ declare function createController<TConfig>(options: ControllerOptions<TConfig>, Impl: React.FC<{
658
+ config: TConfig;
659
+ children?: React.ReactNode;
660
+ }>): ControllerComponent<TConfig>;
661
+
662
+ declare const IkController: ControllerComponent<IkConfig>;
663
+
664
+ interface IkContextValue {
665
+ ikEnabledRef: React.RefObject<boolean>;
666
+ ikCalculatingRef: React.RefObject<boolean>;
667
+ ikTargetRef: React.RefObject<THREE.Group>;
668
+ siteIdRef: React.RefObject<number>;
669
+ setIkEnabled(enabled: boolean): void;
670
+ moveTarget(pos: THREE.Vector3, duration?: number): void;
671
+ syncTargetToSite(): void;
672
+ solveIK(pos: THREE.Vector3, quat: THREE.Quaternion, currentQ: number[]): number[] | null;
673
+ getGizmoStats(): {
674
+ pos: THREE.Vector3;
675
+ rot: THREE.Euler;
676
+ } | null;
677
+ }
678
+ /**
679
+ * Access the IK controller context.
680
+ *
681
+ * - `useIk()` — throws if no `<IkController>` ancestor (use inside `<IkController>`)
682
+ * - `useIk({ optional: true })` — returns `null` if no ancestor (use in components
683
+ * that optionally interact with IK, e.g. keyboard controllers that disable IK)
684
+ */
685
+ declare function useIk(): IkContextValue;
686
+ declare function useIk(options: {
687
+ optional: true;
688
+ }): IkContextValue | null;
689
+
650
690
  /**
651
691
  * @license
652
692
  * SPDX-License-Identifier: Apache-2.0
@@ -660,19 +700,14 @@ declare function SceneRenderer(): react_jsx_runtime.JSX.Element;
660
700
  /**
661
701
  * IkGizmo — drei PivotControls that tracks a MuJoCo site.
662
702
  *
703
+ * Must be rendered inside an `<IkController>`.
704
+ *
663
705
  * Props:
664
- * - `siteName` — MuJoCo site to track. Defaults to `SceneConfig.tcpSiteName`.
706
+ * - `siteName` — MuJoCo site to track. Defaults to the IkController's configured site.
665
707
  * - `scale` — Gizmo handle scale. Default: 0.18.
666
708
  * - `onDrag` — Custom drag callback `(pos, quat) => void`.
667
- * When omitted, dragging enables IK and writes to the provider's IK target.
709
+ * When omitted, dragging enables IK and writes to the IK target.
668
710
  * When provided, the consumer handles what happens during drag.
669
- *
670
- * Multiple gizmos can be rendered — each tracks its own site.
671
- * Zero gizmos is fine — programmatic IK control works via the provider API.
672
- *
673
- * Uses a tiny invisible mesh as child instead of axesHelper — PivotControls
674
- * computes an anchor offset from children's bounding box, and axesHelper's
675
- * (0→0.15) bounds would shift the handles away from the TCP origin.
676
711
  */
677
712
  declare function IkGizmo({ siteName, scale, onDrag }: IkGizmoProps): react_jsx_runtime.JSX.Element | null;
678
713
 
@@ -688,9 +723,9 @@ declare function IkGizmo({ siteName, scale, onDrag }: IkGizmoProps): react_jsx_r
688
723
  interface ContactMarkersProps {
689
724
  /** Maximum contacts to render. Default: 100. */
690
725
  maxContacts?: number;
691
- /** Sphere radius. Default: 0.005. */
726
+ /** Sphere radius. Default: 0.008. */
692
727
  radius?: number;
693
- /** Color. Default: '#4f46e5'. */
728
+ /** Color. Default: '#22d3ee'. */
694
729
  color?: string;
695
730
  /** Show markers. Default: true. */
696
731
  visible?: boolean;
@@ -1080,4 +1115,49 @@ interface CtrlNoiseConfig {
1080
1115
  */
1081
1116
  declare function useCtrlNoise(config?: CtrlNoiseConfig): void;
1082
1117
 
1083
- export { type ActuatorInfo, type BodyInfo, type BodyStateResult, type ContactInfo, ContactListener, type ContactListenerProps, ContactMarkers, Debug, type DebugProps, DragInteraction, type DragInteractionProps, FlexRenderer, type GeomInfo, type IKSolveFn, IkGizmo, type IkGizmoProps, type JointInfo, type JointStateResult, type KeyBinding, type KeyboardTeleopConfig, type ModelOptions, MujocoCanvas, type MujocoCanvasProps, type MujocoContextValue, type MujocoData, type MujocoModel, type MujocoModule, MujocoProvider, type MujocoSimAPI, MujocoSimProvider, type PhysicsConfig, type PhysicsStepCallback, type PolicyConfig, type RayHit, type SceneConfig, SceneLights, type SceneLightsProps, type SceneMarker, type SceneObject, SceneRenderer, SelectionHighlight, type SelectionHighlightProps, type SensorInfo, type SensorResult, type SiteInfo, type SitePositionResult, type StateSnapshot, TendonRenderer, type TrajectoryData, type TrajectoryFrame, TrajectoryPlayer, type TrajectoryPlayerProps, type XmlPatch, findActuatorByName, findBodyByName, findGeomByName, findJointByName, findKeyframeByName, findSensorByName, findSiteByName, findTendonByName, getName, loadScene, useActuators, useAfterPhysicsStep, useBeforePhysicsStep, useBodyState, useContactEvents, useContacts, useCtrl, useCtrlNoise, useGamepad, useGravityCompensation, useJointState, useKeyboardTeleop, useMujoco, useMujocoSim, usePolicy, useSensor, useSensors, useSitePosition, useTrajectoryPlayer, useTrajectoryRecorder, useVideoRecorder };
1118
+ /**
1119
+ * @license
1120
+ * SPDX-License-Identifier: Apache-2.0
1121
+ *
1122
+ * useSelectionHighlight — hook form of SelectionHighlight (spec 6.5)
1123
+ *
1124
+ * Applies emissive highlight to all meshes belonging to a body.
1125
+ * Restores original emissive when bodyId changes or hook unmounts.
1126
+ */
1127
+ declare function useSelectionHighlight(bodyId: number | null, options?: {
1128
+ color?: string;
1129
+ emissiveIntensity?: number;
1130
+ }): void;
1131
+
1132
+ /**
1133
+ * @license
1134
+ * SPDX-License-Identifier: Apache-2.0
1135
+ *
1136
+ * useSceneLights — hook form of SceneLights (spec 6.3)
1137
+ *
1138
+ * Auto-creates Three.js lights from MJCF <light> elements.
1139
+ */
1140
+ declare function useSceneLights(intensity?: number): void;
1141
+
1142
+ /**
1143
+ * @license
1144
+ * SPDX-License-Identifier: Apache-2.0
1145
+ *
1146
+ * useCameraAnimation — composable camera animation hook.
1147
+ */
1148
+
1149
+ interface CameraAnimationAPI {
1150
+ getCameraState(): {
1151
+ position: THREE.Vector3;
1152
+ target: THREE.Vector3;
1153
+ };
1154
+ moveCameraTo(position: THREE.Vector3, target: THREE.Vector3, durationMs: number): Promise<void>;
1155
+ }
1156
+ /**
1157
+ * Standalone hook for animated camera transitions.
1158
+ *
1159
+ * Manages its own `useFrame` callback — drop it into any component inside `<Canvas>`.
1160
+ */
1161
+ declare function useCameraAnimation(): CameraAnimationAPI;
1162
+
1163
+ export { type ActuatorInfo, type BodyInfo, type BodyStateResult, type CameraAnimationAPI, type ContactInfo, ContactListener, type ContactListenerProps, ContactMarkers, type ControllerComponent, type ControllerOptions, Debug, type DebugProps, DragInteraction, type DragInteractionProps, FlexRenderer, type GeomInfo, type IKSolveFn, type IkConfig, type IkContextValue, IkController, IkGizmo, type IkGizmoProps, type JointInfo, type JointStateResult, type KeyBinding, type KeyboardTeleopConfig, type ModelOptions, MujocoCanvas, type MujocoCanvasProps, type MujocoContact, type MujocoContactArray, type MujocoContextValue, type MujocoData, type MujocoModel, type MujocoModule, MujocoProvider, type MujocoSimAPI, MujocoSimProvider, type PhysicsConfig, type PhysicsStepCallback, type PolicyConfig, type RayHit, type SceneConfig, SceneLights, type SceneLightsProps, type SceneMarker, type SceneObject, SceneRenderer, SelectionHighlight, type SelectionHighlightProps, type SensorInfo, type SensorResult, type SiteInfo, type SitePositionResult, 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, useBodyState, useCameraAnimation, useContactEvents, useContacts, useCtrl, useCtrlNoise, useGamepad, useGravityCompensation, useIk, useJointState, useKeyboardTeleop, useMujoco, useMujocoSim, usePolicy, useSceneLights, useSelectionHighlight, useSensor, useSensors, useSitePosition, useTrajectoryPlayer, useTrajectoryRecorder, useVideoRecorder };