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 +83 -43
- package/bin/mujoco-react.mjs +14 -2
- package/dist/index.d.ts +22 -1
- package/dist/index.js.map +1 -1
- package/dist/vite.d.ts +5 -4
- package/dist/vite.js +46 -7
- package/dist/vite.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +10 -0
- package/src/types.ts +27 -0
- package/src/vite.ts +69 -11
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.
|
package/bin/mujoco-react.mjs
CHANGED
|
@@ -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 };
|