mujoco-react 8.6.0 → 8.7.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
@@ -18,6 +18,72 @@ Composable [React Three Fiber](https://docs.pmnd.rs/react-three-fiber) wrapper a
18
18
  npm install mujoco-react three @react-three/fiber @react-three/drei
19
19
  ```
20
20
 
21
+ ## Vite Plugin and Type-Safe Names
22
+
23
+ Use the Vite plugin to generate TanStack-style declaration merging for actuator, sensor, body, joint, site, geom, and keyframe names:
24
+
25
+ ```ts
26
+ // vite.config.ts
27
+ import { defineConfig } from "vite";
28
+ import { mujocoReact } from "mujoco-react/vite";
29
+
30
+ export default defineConfig({
31
+ plugins: [
32
+ mujocoReact({
33
+ models: {
34
+ franka: "models/panda/scene.xml",
35
+ spot: "models/spot/scene.xml",
36
+ },
37
+ }),
38
+ ],
39
+ });
40
+ ```
41
+
42
+ The plugin writes `src/mujoco-register.gen.d.ts` during dev and build. Commit that generated file:
43
+
44
+ ```ts
45
+ // src/mujoco-register.gen.d.ts
46
+ // Auto-generated by mujoco-react. Do not edit.
47
+
48
+ import "mujoco-react";
49
+
50
+ declare module "mujoco-react" {
51
+ interface Register {
52
+ robots: {
53
+ franka: {
54
+ actuators: "joint1" | "joint2" | "joint3" | "gripper";
55
+ sensors: "force_sensor" | "torque_sensor";
56
+ bodies: "link0" | "link1" | "hand";
57
+ joints: "joint1" | "joint2" | "joint3";
58
+ sites: "tcp";
59
+ geoms: "floor";
60
+ keyframes: "home";
61
+ };
62
+ spot: {
63
+ actuators: "fl_hx" | "fl_hy" | "fl_kn";
64
+ sensors: never;
65
+ bodies: "body" | "fl_hip" | "fl_uleg";
66
+ joints: "fl_hx" | "fl_hy" | "fl_kn";
67
+ sites: never;
68
+ geoms: "floor";
69
+ keyframes: "home";
70
+ };
71
+ };
72
+ actuators: "joint1" | "joint2" | "joint3" | "gripper" | "fl_hx" | "fl_hy" | "fl_kn";
73
+ sensors: "force_sensor" | "torque_sensor";
74
+ bodies: "link0" | "link1" | "hand" | "body" | "fl_hip" | "fl_uleg";
75
+ }
76
+ }
77
+ ```
78
+
79
+ Once generated, hooks like `useCtrl`, `useSensor`, `useBodyState`, and API methods like `setCtrl`, `applyForce`, `getSensorData` accept the global union. For robot-scoped reusable code, use helpers such as `RobotActuators<"franka">`, `RobotSites<"franka">`, and `RobotBodies<"franka">`. When no `Register` augmentation is present, names fall back to `string`.
80
+
81
+ Non-Vite projects can generate the same file with:
82
+
83
+ ```bash
84
+ npx mujoco-react codegen franka=models/panda/scene.xml spot=models/spot/scene.xml
85
+ ```
86
+
21
87
  ## Load a Model
22
88
 
23
89
  ```tsx
@@ -87,6 +153,23 @@ function MyController() {
87
153
 
88
154
  Controllers are just React children that read sensors, write `data.ctrl`, apply forces, or call the `MujocoSimAPI` at physics-step time.
89
155
 
156
+ With generated resource types, reusable controllers can be scoped to one robot. Configure stable robot keys in the Vite plugin, then use those keys in helper types:
157
+
158
+ ```tsx
159
+ import { useCtrl, useIkController } from "mujoco-react";
160
+ import type { RobotActuators, RobotSites } from "mujoco-react";
161
+
162
+ const frankaGripper = "gripper" satisfies RobotActuators<"franka">;
163
+ const frankaTcp = "tcp" satisfies RobotSites<"franka">;
164
+
165
+ function FrankaTypedControls() {
166
+ const gripper = useCtrl(frankaGripper);
167
+ const ik = useIkController({ siteName: frankaTcp });
168
+
169
+ return null;
170
+ }
171
+ ```
172
+
90
173
  ## Use the Sim API
91
174
 
92
175
  ```tsx
@@ -304,49 +387,6 @@ const gripperIk = useIkController({
304
387
  });
305
388
  ```
306
389
 
307
- ## Type-Safe Resource Names
308
-
309
- Use the Vite plugin to generate TanStack-style declaration merging for actuator, sensor, body, joint, site, geom, and keyframe names:
310
-
311
- ```ts
312
- // vite.config.ts
313
- import { defineConfig } from "vite";
314
- import { mujocoReact } from "mujoco-react/vite";
315
-
316
- export default defineConfig({
317
- plugins: [
318
- mujocoReact({
319
- models: "models/panda/scene.xml",
320
- }),
321
- ],
322
- });
323
- ```
324
-
325
- The plugin writes `src/mujoco-register.gen.d.ts` during dev and build. Commit that generated file:
326
-
327
- ```ts
328
- // src/mujoco-register.gen.d.ts
329
- // Auto-generated by mujoco-react. Do not edit.
330
-
331
- import "mujoco-react";
332
-
333
- declare module "mujoco-react" {
334
- interface Register {
335
- actuators: "joint1" | "joint2" | "joint3" | "gripper";
336
- sensors: "force_sensor" | "torque_sensor";
337
- bodies: "link0" | "link1" | "hand";
338
- }
339
- }
340
- ```
341
-
342
- Once generated, hooks like `useCtrl`, `useSensor`, `useBodyState`, and API methods like `setCtrl`, `applyForce`, `getSensorData` will only accept the declared names. When no `Register` augmentation is present, names fall back to `string`.
343
-
344
- Non-Vite projects can generate the same file with:
345
-
346
- ```bash
347
- npx mujoco-react codegen models/panda/scene.xml
348
- ```
349
-
350
390
  ## Loading Models
351
391
 
352
392
  The loader fetches `src + sceneFile`, parses the XML for dependencies (meshes, textures, includes), recursively fetches those too, and writes everything to MuJoCo's in-memory WASM filesystem.
@@ -6,13 +6,14 @@ import { generateMujocoRegister } from '../dist/vite.js';
6
6
  const usage = `
7
7
  Usage:
8
8
  mujoco-react codegen <scene.xml> [...more.xml] [--out src/mujoco-register.gen.d.ts] [--watch]
9
+ mujoco-react codegen franka=models/panda/scene.xml spot=models/spot/scene.xml
9
10
 
10
11
  Vite users usually do not need this command. Prefer:
11
12
 
12
13
  import { mujocoReact } from "mujoco-react/vite";
13
14
 
14
15
  export default defineConfig({
15
- plugins: [mujocoReact({ models: "models/panda/scene.xml" })],
16
+ plugins: [mujocoReact({ models: { franka: "models/panda/scene.xml" } })],
16
17
  });
17
18
  `;
18
19
 
@@ -39,6 +40,7 @@ const models = commandArgs.filter((arg, index) => {
39
40
  const previous = commandArgs[index - 1];
40
41
  return previous !== '--out' && previous !== '--module';
41
42
  });
43
+ const modelInput = parseModels(models);
42
44
 
43
45
  if (!models.length) {
44
46
  console.error(usage.trim());
@@ -69,7 +71,7 @@ if (shouldWatch) {
69
71
 
70
72
  async function generate() {
71
73
  const result = await generateMujocoRegister({
72
- models,
74
+ models: modelInput,
73
75
  out,
74
76
  moduleName,
75
77
  root: process.cwd(),
@@ -79,6 +81,16 @@ async function generate() {
79
81
  console.log(`[mujoco-react] generated ${path.relative(process.cwd(), result.out)} (${total} names)`);
80
82
  }
81
83
 
84
+ function parseModels(values) {
85
+ if (values.every((value) => value.includes('='))) {
86
+ return Object.fromEntries(values.map((value) => {
87
+ const index = value.indexOf('=');
88
+ return [value.slice(0, index), value.slice(index + 1)];
89
+ }));
90
+ }
91
+ return values;
92
+ }
93
+
82
94
  function valueAfter(values, flag) {
83
95
  const index = values.indexOf(flag);
84
96
  if (index === -1) return undefined;
package/dist/index.d.ts CHANGED
@@ -16,6 +16,13 @@ import * as THREE from 'three';
16
16
  * ```ts
17
17
  * declare module 'mujoco-react' {
18
18
  * interface Register {
19
+ * robots: {
20
+ * panda: {
21
+ * actuators: 'joint1' | 'joint2' | 'gripper';
22
+ * sensors: 'force_sensor' | 'torque_sensor';
23
+ * bodies: 'link0' | 'link1' | 'hand';
24
+ * };
25
+ * };
19
26
  * actuators: 'joint1' | 'joint2' | 'gripper';
20
27
  * sensors: 'force_sensor' | 'torque_sensor';
21
28
  * bodies: 'link0' | 'link1' | 'hand';
@@ -27,6 +34,20 @@ import * as THREE from 'three';
27
34
  */
28
35
  interface Register {
29
36
  }
37
+ type RegisteredRobotMap = Register extends {
38
+ robots: infer T extends Record<string, Record<string, string>>;
39
+ } ? T : never;
40
+ type Robots = [RegisteredRobotMap] extends [never] ? string : Extract<keyof RegisteredRobotMap, string>;
41
+ type RobotResource<TRobot extends string, TKey extends string> = [
42
+ RegisteredRobotMap
43
+ ] extends [never] ? string : TRobot extends keyof RegisteredRobotMap ? TKey extends keyof RegisteredRobotMap[TRobot] ? RegisteredRobotMap[TRobot][TKey] : string : never;
44
+ type RobotActuators<TRobot extends string> = RobotResource<TRobot, 'actuators'>;
45
+ type RobotSensors<TRobot extends string> = RobotResource<TRobot, 'sensors'>;
46
+ type RobotBodies<TRobot extends string> = RobotResource<TRobot, 'bodies'>;
47
+ type RobotJoints<TRobot extends string> = RobotResource<TRobot, 'joints'>;
48
+ type RobotSites<TRobot extends string> = RobotResource<TRobot, 'sites'>;
49
+ type RobotGeoms<TRobot extends string> = RobotResource<TRobot, 'geoms'>;
50
+ type RobotKeyframes<TRobot extends string> = RobotResource<TRobot, 'keyframes'>;
30
51
  type Actuators = Register extends {
31
52
  actuators: infer T extends string;
32
53
  } ? T : string;
@@ -1483,4 +1504,4 @@ interface CameraAnimationAPI {
1483
1504
  */
1484
1505
  declare function useCameraAnimation(): CameraAnimationAPI;
1485
1506
 
1486
- export { type ActuatedJointInfo, type ActuatorInfo, type Actuators, type Bodies, Body, type BodyInfo, type BodyProps, type BodyStateResult, type CameraAnimationAPI, type ContactInfo, ContactListener, type ContactListenerProps, ContactMarkers, type ControlGroupInfo, type ControlGroupSelector, type ControlJointInfo, 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, InstancedGeomRenderer, 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 MujocoLoader, type MujocoLoaderOptions, type MujocoModel, type MujocoModule, MujocoPhysics, type MujocoPhysicsProps, MujocoProvider, type MujocoProviderProps, type MujocoSimAPI, MujocoSimProvider, type MujocoWasmVariant, type ObservationConfig, type ObservationHandle, type ObservationLayoutItem, type ObservationOutput, type ObservationResult, type PhysicsConfig, type PhysicsStepCallback, type PlaybackState, type PolicyConfig, type RayHit, type Register, type ResourceSelector, 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, buildObservation, createContiguousControlGroup, createController, createControllerHook, findActuatorByName, findBodyByName, findGeomByName, findJointByName, findKeyframeByName, findSensorByName, findSiteByName, findTendonByName, getActuatedJoints, getContact, getControlMap, getName, loadScene, resolveControlGroup, useActuators, useAfterPhysicsStep, useBeforePhysicsStep, useBodyMeshes, useBodyState, useCameraAnimation, useContactEvents, useContacts, useCtrl, useCtrlNoise, useGamepad, useGravityCompensation, useIkController, useJointState, useKeyboardTeleop, useMujoco, useMujocoWasm, useObservation, usePolicy, useSceneLights, useSelectionHighlight, useSensor, useSensors, useSitePosition, useTrajectoryPlayer, useTrajectoryRecorder, useVideoRecorder };
1507
+ export { type ActuatedJointInfo, type ActuatorInfo, type Actuators, type Bodies, Body, type BodyInfo, type BodyProps, type BodyStateResult, type CameraAnimationAPI, type ContactInfo, ContactListener, type ContactListenerProps, ContactMarkers, type ControlGroupInfo, type ControlGroupSelector, type ControlJointInfo, 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, InstancedGeomRenderer, 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 MujocoLoader, type MujocoLoaderOptions, type MujocoModel, type MujocoModule, MujocoPhysics, type MujocoPhysicsProps, MujocoProvider, type MujocoProviderProps, type MujocoSimAPI, MujocoSimProvider, type MujocoWasmVariant, type ObservationConfig, type ObservationHandle, type ObservationLayoutItem, type ObservationOutput, type ObservationResult, type PhysicsConfig, type PhysicsStepCallback, type PlaybackState, type PolicyConfig, type RayHit, type Register, type RegisteredRobotMap, type ResourceSelector, type RobotActuators, type RobotBodies, type RobotGeoms, type RobotJoints, type RobotKeyframes, type RobotResource, type RobotSensors, type RobotSites, type Robots, 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, buildObservation, createContiguousControlGroup, createController, createControllerHook, findActuatorByName, findBodyByName, findGeomByName, findJointByName, findKeyframeByName, findSensorByName, findSiteByName, findTendonByName, getActuatedJoints, getContact, getControlMap, getName, loadScene, resolveControlGroup, useActuators, useAfterPhysicsStep, useBeforePhysicsStep, useBodyMeshes, useBodyState, useCameraAnimation, useContactEvents, useContacts, useCtrl, useCtrlNoise, useGamepad, useGravityCompensation, useIkController, useJointState, useKeyboardTeleop, useMujoco, useMujocoWasm, useObservation, usePolicy, useSceneLights, useSelectionHighlight, useSensor, useSensors, useSitePosition, useTrajectoryPlayer, useTrajectoryRecorder, useVideoRecorder };