mujoco-react 8.9.1 → 8.10.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 +47 -22
- package/bin/mujoco-react.mjs +1 -1
- package/dist/chunk-KGFRKPLS.js +186 -0
- package/dist/chunk-KGFRKPLS.js.map +1 -0
- package/dist/index.d.ts +37 -735
- package/dist/index.js +41 -19
- package/dist/index.js.map +1 -1
- package/dist/spark.d.ts +32 -0
- package/dist/spark.js +150 -0
- package/dist/spark.js.map +1 -0
- package/dist/types-FFW7ykBu.d.ts +817 -0
- package/dist/vite.d.ts +9 -0
- package/dist/vite.js +4 -0
- package/dist/vite.js.map +1 -1
- package/package.json +15 -2
- package/src/components/VisualScenario.tsx +229 -0
- package/src/hooks/useSceneLights.ts +49 -18
- package/src/index.ts +23 -0
- package/src/spark.tsx +202 -0
- package/src/types.ts +92 -1
- package/src/vite.ts +8 -0
package/README.md
CHANGED
|
@@ -32,7 +32,6 @@ export default defineConfig({
|
|
|
32
32
|
mujocoReact({
|
|
33
33
|
models: {
|
|
34
34
|
franka: "models/panda/scene.xml",
|
|
35
|
-
spot: "models/spot/scene.xml",
|
|
36
35
|
},
|
|
37
36
|
}),
|
|
38
37
|
],
|
|
@@ -57,15 +56,6 @@ const generatedRobotResources = {
|
|
|
57
56
|
geoms: { floor: "floor" },
|
|
58
57
|
keyframes: { home: "home" },
|
|
59
58
|
},
|
|
60
|
-
spot: {
|
|
61
|
-
actuators: { fl_hx: "fl_hx", fl_hy: "fl_hy", fl_kn: "fl_kn" },
|
|
62
|
-
sensors: {},
|
|
63
|
-
bodies: { body: "body", fl_hip: "fl_hip", fl_uleg: "fl_uleg" },
|
|
64
|
-
joints: { fl_hx: "fl_hx", fl_hy: "fl_hy", fl_kn: "fl_kn" },
|
|
65
|
-
sites: {},
|
|
66
|
-
geoms: { floor: "floor" },
|
|
67
|
-
keyframes: { home: "home" },
|
|
68
|
-
},
|
|
69
59
|
};
|
|
70
60
|
|
|
71
61
|
registerRobotResources(generatedRobotResources);
|
|
@@ -82,19 +72,10 @@ declare module "mujoco-react" {
|
|
|
82
72
|
geoms: "floor";
|
|
83
73
|
keyframes: "home";
|
|
84
74
|
};
|
|
85
|
-
spot: {
|
|
86
|
-
actuators: "fl_hx" | "fl_hy" | "fl_kn";
|
|
87
|
-
sensors: never;
|
|
88
|
-
bodies: "body" | "fl_hip" | "fl_uleg";
|
|
89
|
-
joints: "fl_hx" | "fl_hy" | "fl_kn";
|
|
90
|
-
sites: never;
|
|
91
|
-
geoms: "floor";
|
|
92
|
-
keyframes: "home";
|
|
93
|
-
};
|
|
94
75
|
};
|
|
95
|
-
actuators: "joint1" | "joint2" | "joint3" | "gripper"
|
|
76
|
+
actuators: "joint1" | "joint2" | "joint3" | "gripper";
|
|
96
77
|
sensors: "force_sensor" | "torque_sensor";
|
|
97
|
-
bodies: "link0" | "link1" | "hand"
|
|
78
|
+
bodies: "link0" | "link1" | "hand";
|
|
98
79
|
}
|
|
99
80
|
}
|
|
100
81
|
```
|
|
@@ -104,7 +85,7 @@ Once generated, hooks like `useCtrl`, `useSensor`, `useBodyState`, and API metho
|
|
|
104
85
|
Non-Vite projects can generate the same file with:
|
|
105
86
|
|
|
106
87
|
```bash
|
|
107
|
-
npx mujoco-react codegen franka=models/panda/scene.xml
|
|
88
|
+
npx mujoco-react codegen franka=models/panda/scene.xml
|
|
108
89
|
```
|
|
109
90
|
|
|
110
91
|
## Load a Model
|
|
@@ -160,6 +141,50 @@ Use it as a child of `<MujocoCanvas>`:
|
|
|
160
141
|
</MujocoCanvas>
|
|
161
142
|
```
|
|
162
143
|
|
|
144
|
+
## Gaussian Splat Environments
|
|
145
|
+
|
|
146
|
+
Gaussian splats are visual context; MuJoCo XML remains the source of physics, contacts, and task fixtures. Pair each splat asset with collision proxy metadata so scene variants, rollouts, and datasets preserve both sides of the environment.
|
|
147
|
+
|
|
148
|
+
Use the renderer-agnostic boundary from the main package:
|
|
149
|
+
|
|
150
|
+
```tsx
|
|
151
|
+
import { SplatEnvironment } from "mujoco-react";
|
|
152
|
+
|
|
153
|
+
<SplatEnvironment
|
|
154
|
+
src="/models/lab/scene.spz"
|
|
155
|
+
format="spz"
|
|
156
|
+
collisionProxyMetadata={{
|
|
157
|
+
xmlPath: "/models/lab/collision.xml",
|
|
158
|
+
status: "validated",
|
|
159
|
+
primitives: ["plane", "box"],
|
|
160
|
+
}}
|
|
161
|
+
/>;
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
For first-class Spark rendering, install Spark and import the optional adapter:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
npm install @sparkjsdev/spark
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
```tsx
|
|
171
|
+
import { SparkSplatEnvironment } from "mujoco-react/spark";
|
|
172
|
+
|
|
173
|
+
<MujocoCanvas config={sceneConfig} gl={{ preserveDrawingBuffer: true }}>
|
|
174
|
+
<SparkSplatEnvironment
|
|
175
|
+
src="/models/lab/scene.spz"
|
|
176
|
+
format="spz"
|
|
177
|
+
collisionProxyMetadata={{
|
|
178
|
+
xmlPath: "/models/lab/collision.xml",
|
|
179
|
+
status: "validated",
|
|
180
|
+
primitives: ["plane", "box"],
|
|
181
|
+
}}
|
|
182
|
+
hideGroundMeshes
|
|
183
|
+
onStatusChange={(status) => console.log(status)}
|
|
184
|
+
/>
|
|
185
|
+
</MujocoCanvas>;
|
|
186
|
+
```
|
|
187
|
+
|
|
163
188
|
## Write Controllers
|
|
164
189
|
|
|
165
190
|
```tsx
|
package/bin/mujoco-react.mjs
CHANGED
|
@@ -6,7 +6,7 @@ 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.ts] [--watch]
|
|
9
|
-
mujoco-react codegen franka=models/panda/scene.xml
|
|
9
|
+
mujoco-react codegen franka=models/panda/scene.xml
|
|
10
10
|
|
|
11
11
|
Vite users usually do not need this command. Prefer:
|
|
12
12
|
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import * as THREE from 'three';
|
|
3
|
+
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
// src/components/VisualScenario.tsx
|
|
6
|
+
var DEFAULT_BACKGROUND = "#181a1f";
|
|
7
|
+
function ScenarioLighting({
|
|
8
|
+
preset = "studio",
|
|
9
|
+
castShadow = true,
|
|
10
|
+
intensity = 1
|
|
11
|
+
}) {
|
|
12
|
+
if (preset === "warehouse") {
|
|
13
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
14
|
+
/* @__PURE__ */ jsx("ambientLight", { intensity: 0.18 * intensity }),
|
|
15
|
+
/* @__PURE__ */ jsx(
|
|
16
|
+
"directionalLight",
|
|
17
|
+
{
|
|
18
|
+
position: [3.5, -2, 5],
|
|
19
|
+
intensity: 2.2 * intensity,
|
|
20
|
+
castShadow
|
|
21
|
+
}
|
|
22
|
+
),
|
|
23
|
+
/* @__PURE__ */ jsx("directionalLight", { position: [-2, 1.5, 2.5], intensity: 0.25 * intensity })
|
|
24
|
+
] });
|
|
25
|
+
}
|
|
26
|
+
if (preset === "low-light") {
|
|
27
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
28
|
+
/* @__PURE__ */ jsx("ambientLight", { intensity: 0.08 * intensity }),
|
|
29
|
+
/* @__PURE__ */ jsx(
|
|
30
|
+
"directionalLight",
|
|
31
|
+
{
|
|
32
|
+
position: [2, -2, 3],
|
|
33
|
+
intensity: 0.75 * intensity,
|
|
34
|
+
castShadow
|
|
35
|
+
}
|
|
36
|
+
),
|
|
37
|
+
/* @__PURE__ */ jsx("pointLight", { position: [-0.5, -0.8, 1.3], intensity: 0.6 * intensity })
|
|
38
|
+
] });
|
|
39
|
+
}
|
|
40
|
+
if (preset === "splat") {
|
|
41
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
42
|
+
/* @__PURE__ */ jsx("ambientLight", { intensity: 0.42 * intensity }),
|
|
43
|
+
/* @__PURE__ */ jsx(
|
|
44
|
+
"directionalLight",
|
|
45
|
+
{
|
|
46
|
+
position: [1.8, -2.4, 3.5],
|
|
47
|
+
intensity: 1.2 * intensity,
|
|
48
|
+
castShadow
|
|
49
|
+
}
|
|
50
|
+
),
|
|
51
|
+
/* @__PURE__ */ jsx("pointLight", { position: [0.4, 0.2, 1.4], intensity: 0.35 * intensity })
|
|
52
|
+
] });
|
|
53
|
+
}
|
|
54
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
55
|
+
/* @__PURE__ */ jsx("ambientLight", { intensity: 0.35 * intensity }),
|
|
56
|
+
/* @__PURE__ */ jsx(
|
|
57
|
+
"directionalLight",
|
|
58
|
+
{
|
|
59
|
+
position: [2.5, -3, 4],
|
|
60
|
+
intensity: 1.6 * intensity,
|
|
61
|
+
castShadow
|
|
62
|
+
}
|
|
63
|
+
)
|
|
64
|
+
] });
|
|
65
|
+
}
|
|
66
|
+
function getScenarioBackground(preset, fallback = DEFAULT_BACKGROUND) {
|
|
67
|
+
if (preset === "warehouse") return "#20242b";
|
|
68
|
+
if (preset === "low-light") return "#0f1115";
|
|
69
|
+
if (preset === "splat") return "#1b1f24";
|
|
70
|
+
return fallback;
|
|
71
|
+
}
|
|
72
|
+
function getScenarioCameraPosition(basePosition, scenario) {
|
|
73
|
+
const [x, y, z] = basePosition;
|
|
74
|
+
const jitter = scenario?.camera?.jitter ?? 0;
|
|
75
|
+
return [
|
|
76
|
+
Number((x + jitter * 0.6).toFixed(3)),
|
|
77
|
+
Number((y - jitter * 0.4).toFixed(3)),
|
|
78
|
+
Number((z + jitter * 0.25).toFixed(3))
|
|
79
|
+
];
|
|
80
|
+
}
|
|
81
|
+
function SplatEnvironment({
|
|
82
|
+
environment,
|
|
83
|
+
src,
|
|
84
|
+
format,
|
|
85
|
+
collisionProxy,
|
|
86
|
+
collisionProxyMetadata,
|
|
87
|
+
children,
|
|
88
|
+
showPlaceholder = true,
|
|
89
|
+
...groupProps
|
|
90
|
+
}) {
|
|
91
|
+
const metadata = useSplatEnvironment({
|
|
92
|
+
environment,
|
|
93
|
+
src,
|
|
94
|
+
format,
|
|
95
|
+
collisionProxy: collisionProxyMetadata
|
|
96
|
+
});
|
|
97
|
+
const existingUserData = typeof groupProps.userData === "object" && groupProps.userData !== null ? groupProps.userData : {};
|
|
98
|
+
return /* @__PURE__ */ jsxs(
|
|
99
|
+
"group",
|
|
100
|
+
{
|
|
101
|
+
...groupProps,
|
|
102
|
+
userData: {
|
|
103
|
+
...existingUserData,
|
|
104
|
+
...metadata.userData
|
|
105
|
+
},
|
|
106
|
+
children: [
|
|
107
|
+
children,
|
|
108
|
+
children || !showPlaceholder ? null : /* @__PURE__ */ jsx(SplatPlaceholder, {}),
|
|
109
|
+
collisionProxy
|
|
110
|
+
]
|
|
111
|
+
}
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
function useSplatEnvironment({
|
|
115
|
+
environment,
|
|
116
|
+
src,
|
|
117
|
+
format,
|
|
118
|
+
collisionProxy
|
|
119
|
+
}) {
|
|
120
|
+
const resolvedSrc = src ?? environment?.splat.src;
|
|
121
|
+
const resolvedFormat = format ?? environment?.splat.format ?? "spz";
|
|
122
|
+
const resolvedCollisionProxy = collisionProxy ?? environment?.collisionProxy;
|
|
123
|
+
return useMemo(
|
|
124
|
+
() => ({
|
|
125
|
+
src: resolvedSrc,
|
|
126
|
+
format: resolvedFormat,
|
|
127
|
+
collisionProxy: resolvedCollisionProxy,
|
|
128
|
+
userData: createSplatEnvironmentUserData({
|
|
129
|
+
environment,
|
|
130
|
+
src: resolvedSrc,
|
|
131
|
+
format: resolvedFormat,
|
|
132
|
+
collisionProxy: resolvedCollisionProxy
|
|
133
|
+
})
|
|
134
|
+
}),
|
|
135
|
+
[environment, resolvedSrc, resolvedFormat, resolvedCollisionProxy]
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
function createSplatEnvironmentUserData({
|
|
139
|
+
environment,
|
|
140
|
+
src,
|
|
141
|
+
format = "spz",
|
|
142
|
+
collisionProxy
|
|
143
|
+
}) {
|
|
144
|
+
return {
|
|
145
|
+
role: "splat-environment",
|
|
146
|
+
environmentId: environment?.id,
|
|
147
|
+
environmentLabel: environment?.label,
|
|
148
|
+
splatSrc: src,
|
|
149
|
+
splatFormat: format,
|
|
150
|
+
splatRenderer: environment?.splat.renderer,
|
|
151
|
+
collisionProxyStatus: collisionProxy?.status ?? "missing",
|
|
152
|
+
collisionProxyXmlPath: collisionProxy?.xmlPath,
|
|
153
|
+
collisionProxyPrimitives: collisionProxy?.primitives ?? []
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
function createSparkSplatViewerUrl({
|
|
157
|
+
viewerUrl,
|
|
158
|
+
splatSrc
|
|
159
|
+
}) {
|
|
160
|
+
const url = new URL(viewerUrl, "http://mujoco-react.local");
|
|
161
|
+
url.searchParams.set("splat", splatSrc);
|
|
162
|
+
return viewerUrl.startsWith("http") ? url.toString() : `${url.pathname}${url.search}`;
|
|
163
|
+
}
|
|
164
|
+
function SplatPlaceholder() {
|
|
165
|
+
return /* @__PURE__ */ jsx("group", { children: /* @__PURE__ */ jsxs("mesh", { position: [0, 0, 1.2], children: [
|
|
166
|
+
/* @__PURE__ */ jsx("boxGeometry", { args: [2.4, 2.4, 2.4] }),
|
|
167
|
+
/* @__PURE__ */ jsx(
|
|
168
|
+
"meshBasicMaterial",
|
|
169
|
+
{
|
|
170
|
+
color: "#8b8b8b",
|
|
171
|
+
transparent: true,
|
|
172
|
+
opacity: 0.06,
|
|
173
|
+
wireframe: true,
|
|
174
|
+
side: THREE.DoubleSide
|
|
175
|
+
}
|
|
176
|
+
)
|
|
177
|
+
] }) });
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* @license
|
|
181
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
182
|
+
*/
|
|
183
|
+
|
|
184
|
+
export { ScenarioLighting, SplatEnvironment, createSparkSplatViewerUrl, createSplatEnvironmentUserData, getScenarioBackground, getScenarioCameraPosition, useSplatEnvironment };
|
|
185
|
+
//# sourceMappingURL=chunk-KGFRKPLS.js.map
|
|
186
|
+
//# sourceMappingURL=chunk-KGFRKPLS.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/VisualScenario.tsx"],"names":[],"mappings":"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","file":"chunk-KGFRKPLS.js","sourcesContent":["/**\n * @license\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { ThreeElements } from '@react-three/fiber';\nimport type { ReactNode } from 'react';\nimport { useMemo } from 'react';\nimport * as THREE from 'three';\nimport type {\n PairedSplatEnvironmentConfig,\n SplatCollisionProxyConfig,\n SplatEnvironmentMetadata,\n SplatEnvironmentMetadataInput,\n SplatFormat,\n ScenarioLightingPreset,\n ScenarioLightingProps,\n SplatEnvironmentProps,\n VisualScenarioConfig,\n} from '../types';\n\nconst DEFAULT_BACKGROUND = '#181a1f';\n\nexport function ScenarioLighting({\n preset = 'studio',\n castShadow = true,\n intensity = 1,\n}: ScenarioLightingProps) {\n if (preset === 'warehouse') {\n return (\n <>\n <ambientLight intensity={0.18 * intensity} />\n <directionalLight\n position={[3.5, -2, 5]}\n intensity={2.2 * intensity}\n castShadow={castShadow}\n />\n <directionalLight position={[-2, 1.5, 2.5]} intensity={0.25 * intensity} />\n </>\n );\n }\n\n if (preset === 'low-light') {\n return (\n <>\n <ambientLight intensity={0.08 * intensity} />\n <directionalLight\n position={[2, -2, 3]}\n intensity={0.75 * intensity}\n castShadow={castShadow}\n />\n <pointLight position={[-0.5, -0.8, 1.3]} intensity={0.6 * intensity} />\n </>\n );\n }\n\n if (preset === 'splat') {\n return (\n <>\n <ambientLight intensity={0.42 * intensity} />\n <directionalLight\n position={[1.8, -2.4, 3.5]}\n intensity={1.2 * intensity}\n castShadow={castShadow}\n />\n <pointLight position={[0.4, 0.2, 1.4]} intensity={0.35 * intensity} />\n </>\n );\n }\n\n return (\n <>\n <ambientLight intensity={0.35 * intensity} />\n <directionalLight\n position={[2.5, -3, 4]}\n intensity={1.6 * intensity}\n castShadow={castShadow}\n />\n </>\n );\n}\n\nexport function getScenarioBackground(\n preset: ScenarioLightingPreset | undefined,\n fallback = DEFAULT_BACKGROUND\n) {\n if (preset === 'warehouse') return '#20242b';\n if (preset === 'low-light') return '#0f1115';\n if (preset === 'splat') return '#1b1f24';\n return fallback;\n}\n\nexport function getScenarioCameraPosition(\n basePosition: readonly [number, number, number],\n scenario?: Pick<VisualScenarioConfig, 'camera'>\n): [number, number, number] {\n const [x, y, z] = basePosition;\n const jitter = scenario?.camera?.jitter ?? 0;\n\n return [\n Number((x + jitter * 0.6).toFixed(3)),\n Number((y - jitter * 0.4).toFixed(3)),\n Number((z + jitter * 0.25).toFixed(3)),\n ];\n}\n\n/**\n * Renderer-agnostic Gaussian splat environment boundary.\n *\n * This component intentionally does not import a specific 3DGS renderer. Pass a\n * Spark/GaussianSplats3D object as `children` once the app chooses a renderer,\n * and pass MuJoCo/MJCF collision proxy visuals via `collisionProxy`.\n */\nexport function SplatEnvironment({\n environment,\n src,\n format,\n collisionProxy,\n collisionProxyMetadata,\n children,\n showPlaceholder = true,\n ...groupProps\n}: SplatEnvironmentProps) {\n const metadata = useSplatEnvironment({\n environment,\n src,\n format,\n collisionProxy: collisionProxyMetadata,\n });\n const existingUserData =\n typeof groupProps.userData === 'object' && groupProps.userData !== null\n ? groupProps.userData\n : {};\n\n return (\n <group\n {...groupProps}\n userData={{\n ...existingUserData,\n ...metadata.userData,\n }}\n >\n {children}\n {children || !showPlaceholder ? null : <SplatPlaceholder />}\n {collisionProxy}\n </group>\n );\n}\n\nexport function useSplatEnvironment({\n environment,\n src,\n format,\n collisionProxy,\n}: SplatEnvironmentMetadataInput): SplatEnvironmentMetadata {\n const resolvedSrc = src ?? environment?.splat.src;\n const resolvedFormat = format ?? environment?.splat.format ?? 'spz';\n const resolvedCollisionProxy = collisionProxy ?? environment?.collisionProxy;\n\n return useMemo(\n () => ({\n src: resolvedSrc,\n format: resolvedFormat,\n collisionProxy: resolvedCollisionProxy,\n userData: createSplatEnvironmentUserData({\n environment,\n src: resolvedSrc,\n format: resolvedFormat,\n collisionProxy: resolvedCollisionProxy,\n }),\n }),\n [environment, resolvedSrc, resolvedFormat, resolvedCollisionProxy]\n );\n}\n\nexport function createSplatEnvironmentUserData({\n environment,\n src,\n format = 'spz',\n collisionProxy,\n}: {\n environment?: PairedSplatEnvironmentConfig;\n src?: string;\n format?: SplatFormat;\n collisionProxy?: SplatCollisionProxyConfig;\n}) {\n return {\n role: 'splat-environment',\n environmentId: environment?.id,\n environmentLabel: environment?.label,\n splatSrc: src,\n splatFormat: format,\n splatRenderer: environment?.splat.renderer,\n collisionProxyStatus: collisionProxy?.status ?? 'missing',\n collisionProxyXmlPath: collisionProxy?.xmlPath,\n collisionProxyPrimitives: collisionProxy?.primitives ?? [],\n };\n}\n\nexport function createSparkSplatViewerUrl({\n viewerUrl,\n splatSrc,\n}: {\n viewerUrl: string;\n splatSrc: string;\n}) {\n const url = new URL(viewerUrl, 'http://mujoco-react.local');\n url.searchParams.set('splat', splatSrc);\n return viewerUrl.startsWith('http') ? url.toString() : `${url.pathname}${url.search}`;\n}\n\nfunction SplatPlaceholder() {\n return (\n <group>\n <mesh position={[0, 0, 1.2]}>\n <boxGeometry args={[2.4, 2.4, 2.4]} />\n <meshBasicMaterial\n color=\"#8b8b8b\"\n transparent\n opacity={0.06}\n wireframe\n side={THREE.DoubleSide}\n />\n </mesh>\n </group>\n );\n}\n\nexport type SplatCollisionProxy = ReactNode | ThreeElements['group'];\n"]}
|