mujoco-react 9.1.0 → 9.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/README.md +121 -17
- package/dist/{chunk-33CV6HSV.js → chunk-T3GVZJ4F.js} +222 -8
- package/dist/chunk-T3GVZJ4F.js.map +1 -0
- package/dist/index.d.ts +198 -6
- package/dist/index.js +1109 -216
- package/dist/index.js.map +1 -1
- package/dist/spark.d.ts +24 -2
- package/dist/spark.js +89 -3
- package/dist/spark.js.map +1 -1
- package/dist/{types-C5gTvR7b.d.ts → types-oxbxOkAx.d.ts} +190 -2
- package/dist/vite.d.ts +1 -1
- package/dist/vite.js +6 -3
- package/dist/vite.js.map +1 -1
- package/package.json +1 -1
- package/src/components/VisualScenario.tsx +178 -1
- package/src/core/MujocoSimProvider.tsx +473 -11
- package/src/core/SceneLoader.ts +13 -0
- package/src/core/createController.tsx +6 -2
- package/src/hooks/useCameraFrameCapture.ts +94 -0
- package/src/hooks/useCameraSequenceRecorder.ts +59 -0
- package/src/hooks/useMountedCameraSequenceRecorder.ts +107 -0
- package/src/index.ts +67 -0
- package/src/rendering/cameraFrameCapture.ts +353 -0
- package/src/rendering/cameraFrameSource.ts +375 -0
- package/src/spark.tsx +144 -0
- package/src/types.ts +212 -2
- package/src/vite.ts +5 -2
- package/dist/chunk-33CV6HSV.js.map +0 -1
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*
|
|
5
|
+
* React state wrapper around MuJoCo/R3F offscreen camera-frame capture.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { useCallback, useState } from 'react';
|
|
9
|
+
import { useMujoco } from '../core/MujocoSimProvider';
|
|
10
|
+
import type {
|
|
11
|
+
CameraFrameCaptureAPI,
|
|
12
|
+
CameraFrameCaptureOptions,
|
|
13
|
+
FrameCaptureStatus,
|
|
14
|
+
} from '../types';
|
|
15
|
+
|
|
16
|
+
export function useCameraFrameCapture(
|
|
17
|
+
defaultOptions: CameraFrameCaptureOptions = {}
|
|
18
|
+
): CameraFrameCaptureAPI {
|
|
19
|
+
const mujoco = useMujoco();
|
|
20
|
+
const [status, setStatus] = useState<FrameCaptureStatus>('idle');
|
|
21
|
+
const [error, setError] = useState<Error | null>(null);
|
|
22
|
+
|
|
23
|
+
const reset = useCallback(() => {
|
|
24
|
+
setStatus('idle');
|
|
25
|
+
setError(null);
|
|
26
|
+
}, []);
|
|
27
|
+
|
|
28
|
+
const capture = useCallback(
|
|
29
|
+
async (options: CameraFrameCaptureOptions = {}) => {
|
|
30
|
+
if (!mujoco.api) {
|
|
31
|
+
throw new Error('MuJoCo scene is not ready for camera frame capture.');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
setStatus('capturing');
|
|
35
|
+
setError(null);
|
|
36
|
+
|
|
37
|
+
try {
|
|
38
|
+
const result = await mujoco.api.captureCameraFrame({
|
|
39
|
+
...defaultOptions,
|
|
40
|
+
...options,
|
|
41
|
+
});
|
|
42
|
+
setStatus('captured');
|
|
43
|
+
return result;
|
|
44
|
+
} catch (nextError) {
|
|
45
|
+
const error =
|
|
46
|
+
nextError instanceof Error
|
|
47
|
+
? nextError
|
|
48
|
+
: new Error('Unable to capture the requested camera frame.');
|
|
49
|
+
setError(error);
|
|
50
|
+
setStatus('error');
|
|
51
|
+
throw error;
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
[defaultOptions, mujoco.api]
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
const captureBlob = useCallback(
|
|
58
|
+
async (options: CameraFrameCaptureOptions = {}) => {
|
|
59
|
+
if (!mujoco.api) {
|
|
60
|
+
throw new Error('MuJoCo scene is not ready for camera frame capture.');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
setStatus('capturing');
|
|
64
|
+
setError(null);
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
const result = await mujoco.api.captureCameraFrameBlob({
|
|
68
|
+
...defaultOptions,
|
|
69
|
+
...options,
|
|
70
|
+
});
|
|
71
|
+
setStatus('captured');
|
|
72
|
+
return result;
|
|
73
|
+
} catch (nextError) {
|
|
74
|
+
const error =
|
|
75
|
+
nextError instanceof Error
|
|
76
|
+
? nextError
|
|
77
|
+
: new Error('Unable to capture the requested camera frame.');
|
|
78
|
+
setError(error);
|
|
79
|
+
setStatus('error');
|
|
80
|
+
throw error;
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
[defaultOptions, mujoco.api]
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
status,
|
|
88
|
+
error,
|
|
89
|
+
isCapturing: status === 'capturing',
|
|
90
|
+
capture,
|
|
91
|
+
captureBlob,
|
|
92
|
+
reset,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*
|
|
5
|
+
* React state wrapper around fixed-camera simulation sequence recording.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { useCallback, useState } from 'react';
|
|
9
|
+
import { useMujoco } from '../core/MujocoSimProvider';
|
|
10
|
+
import type {
|
|
11
|
+
CameraFrameSequenceOptions,
|
|
12
|
+
CameraFrameSequenceRecorderAPI,
|
|
13
|
+
FrameCaptureStatus,
|
|
14
|
+
} from '../types';
|
|
15
|
+
|
|
16
|
+
export function useCameraSequenceRecorder(): CameraFrameSequenceRecorderAPI {
|
|
17
|
+
const mujoco = useMujoco();
|
|
18
|
+
const [status, setStatus] = useState<FrameCaptureStatus>('idle');
|
|
19
|
+
const [error, setError] = useState<Error | null>(null);
|
|
20
|
+
|
|
21
|
+
const reset = useCallback(() => {
|
|
22
|
+
setStatus('idle');
|
|
23
|
+
setError(null);
|
|
24
|
+
}, []);
|
|
25
|
+
|
|
26
|
+
const record = useCallback(
|
|
27
|
+
async (options: CameraFrameSequenceOptions) => {
|
|
28
|
+
if (!mujoco.api) {
|
|
29
|
+
throw new Error('MuJoCo scene is not ready for camera sequence recording.');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
setStatus('capturing');
|
|
33
|
+
setError(null);
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
const result = await mujoco.api.recordCameraSequence(options);
|
|
37
|
+
setStatus('captured');
|
|
38
|
+
return result;
|
|
39
|
+
} catch (nextError) {
|
|
40
|
+
const error =
|
|
41
|
+
nextError instanceof Error
|
|
42
|
+
? nextError
|
|
43
|
+
: new Error('Unable to record the requested camera sequence.');
|
|
44
|
+
setError(error);
|
|
45
|
+
setStatus('error');
|
|
46
|
+
throw error;
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
[mujoco.api]
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
return {
|
|
53
|
+
status,
|
|
54
|
+
error,
|
|
55
|
+
isRecording: status === 'capturing',
|
|
56
|
+
record,
|
|
57
|
+
reset,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
*
|
|
5
|
+
* React state wrapper for named MuJoCo camera/site/body sequence recording.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { useCallback, useState } from 'react';
|
|
9
|
+
import { useMujoco } from '../core/MujocoSimProvider';
|
|
10
|
+
import {
|
|
11
|
+
createMountedCameraFrameSequencePlanFromApi,
|
|
12
|
+
recordMountedCameraFrameSequence,
|
|
13
|
+
type MountedCameraFrameSequencePlan,
|
|
14
|
+
type MountedCameraFrameSequencePlanOptions,
|
|
15
|
+
type MountedCameraFrameSequenceRecordOptions,
|
|
16
|
+
type MountedCameraFrameSequenceRecordResult,
|
|
17
|
+
} from '../rendering/cameraFrameSource';
|
|
18
|
+
import type {
|
|
19
|
+
CameraFrameSequenceRecorderAPI,
|
|
20
|
+
FrameCaptureStatus,
|
|
21
|
+
} from '../types';
|
|
22
|
+
|
|
23
|
+
export type MountedCameraSequencePlanOptions =
|
|
24
|
+
MountedCameraFrameSequencePlanOptions;
|
|
25
|
+
export type MountedCameraSequenceRecordOptions =
|
|
26
|
+
MountedCameraFrameSequenceRecordOptions;
|
|
27
|
+
export type MountedCameraSequenceRecordResult =
|
|
28
|
+
MountedCameraFrameSequenceRecordResult;
|
|
29
|
+
|
|
30
|
+
export interface MountedCameraSequenceRecorderAPI
|
|
31
|
+
extends Omit<CameraFrameSequenceRecorderAPI, 'record'> {
|
|
32
|
+
createPlan: (
|
|
33
|
+
cameraKeys: readonly string[],
|
|
34
|
+
options?: MountedCameraSequencePlanOptions
|
|
35
|
+
) => MountedCameraFrameSequencePlan;
|
|
36
|
+
record: (
|
|
37
|
+
options: MountedCameraSequenceRecordOptions
|
|
38
|
+
) => Promise<MountedCameraSequenceRecordResult>;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function useMountedCameraSequenceRecorder(
|
|
42
|
+
defaultOptions: MountedCameraSequencePlanOptions = {}
|
|
43
|
+
): MountedCameraSequenceRecorderAPI {
|
|
44
|
+
const mujoco = useMujoco();
|
|
45
|
+
const [status, setStatus] = useState<FrameCaptureStatus>('idle');
|
|
46
|
+
const [error, setError] = useState<Error | null>(null);
|
|
47
|
+
|
|
48
|
+
const reset = useCallback(() => {
|
|
49
|
+
setStatus('idle');
|
|
50
|
+
setError(null);
|
|
51
|
+
}, []);
|
|
52
|
+
|
|
53
|
+
const createPlan = useCallback(
|
|
54
|
+
(
|
|
55
|
+
cameraKeys: readonly string[],
|
|
56
|
+
options: MountedCameraSequencePlanOptions = {}
|
|
57
|
+
) => {
|
|
58
|
+
if (!mujoco.api) {
|
|
59
|
+
throw new Error('MuJoCo scene is not ready for mounted camera sequence planning.');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return createMountedCameraFrameSequencePlanFromApi(mujoco.api, cameraKeys, {
|
|
63
|
+
...defaultOptions,
|
|
64
|
+
...options,
|
|
65
|
+
});
|
|
66
|
+
},
|
|
67
|
+
[defaultOptions, mujoco.api]
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
const record = useCallback(
|
|
71
|
+
async (options: MountedCameraSequenceRecordOptions) => {
|
|
72
|
+
if (!mujoco.api) {
|
|
73
|
+
throw new Error('MuJoCo scene is not ready for mounted camera sequence recording.');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
setStatus('capturing');
|
|
77
|
+
setError(null);
|
|
78
|
+
|
|
79
|
+
try {
|
|
80
|
+
const result = await recordMountedCameraFrameSequence(mujoco.api, {
|
|
81
|
+
...defaultOptions,
|
|
82
|
+
...options,
|
|
83
|
+
});
|
|
84
|
+
setStatus('captured');
|
|
85
|
+
return result;
|
|
86
|
+
} catch (nextError) {
|
|
87
|
+
const error =
|
|
88
|
+
nextError instanceof Error
|
|
89
|
+
? nextError
|
|
90
|
+
: new Error('Unable to record the requested mounted camera sequence.');
|
|
91
|
+
setError(error);
|
|
92
|
+
setStatus('error');
|
|
93
|
+
throw error;
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
[defaultOptions, mujoco.api]
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
return {
|
|
100
|
+
status,
|
|
101
|
+
error,
|
|
102
|
+
isRecording: status === 'capturing',
|
|
103
|
+
createPlan,
|
|
104
|
+
record,
|
|
105
|
+
reset,
|
|
106
|
+
};
|
|
107
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -48,9 +48,11 @@ export {
|
|
|
48
48
|
createPairedSplatEnvironment,
|
|
49
49
|
createSparkSplatViewerUrl,
|
|
50
50
|
createSplatEnvironmentUserData,
|
|
51
|
+
getSplatEnvironmentReadiness,
|
|
51
52
|
getScenarioBackground,
|
|
52
53
|
getScenarioCameraPosition,
|
|
53
54
|
useSplatEnvironment,
|
|
55
|
+
useSplatSceneConfig,
|
|
54
56
|
useVisualScenarioEffects,
|
|
55
57
|
withSplatEnvironment,
|
|
56
58
|
} from './components/VisualScenario';
|
|
@@ -82,6 +84,49 @@ export {
|
|
|
82
84
|
captureFrameBlob,
|
|
83
85
|
useFrameCapture,
|
|
84
86
|
} from './hooks/useFrameCapture';
|
|
87
|
+
export { useCameraFrameCapture } from './hooks/useCameraFrameCapture';
|
|
88
|
+
export { useCameraSequenceRecorder } from './hooks/useCameraSequenceRecorder';
|
|
89
|
+
export { useMountedCameraSequenceRecorder } from './hooks/useMountedCameraSequenceRecorder';
|
|
90
|
+
export type {
|
|
91
|
+
MountedCameraSequencePlanOptions,
|
|
92
|
+
MountedCameraSequenceRecorderAPI,
|
|
93
|
+
MountedCameraSequenceRecordOptions,
|
|
94
|
+
MountedCameraSequenceRecordResult,
|
|
95
|
+
} from './hooks/useMountedCameraSequenceRecorder';
|
|
96
|
+
export {
|
|
97
|
+
captureCameraFrame,
|
|
98
|
+
captureCameraFrameBlob,
|
|
99
|
+
createCameraFrameCaptureSession,
|
|
100
|
+
renderCameraFrameToCanvas,
|
|
101
|
+
} from './rendering/cameraFrameCapture';
|
|
102
|
+
export {
|
|
103
|
+
createMountedCameraFrameSequenceReadiness,
|
|
104
|
+
MountedCameraFrameSequenceReadinessStatus,
|
|
105
|
+
createMountedCameraFrameSequencePlanFromApi,
|
|
106
|
+
createMountedCameraFrameSequencePlan,
|
|
107
|
+
getCameraFrameCaptureSourceTarget,
|
|
108
|
+
getMountedCameraFrameCaptureSource,
|
|
109
|
+
isMountedCameraFrameCaptureSource,
|
|
110
|
+
recordMountedCameraFrameSequence,
|
|
111
|
+
resolveMountedCameraFrameSource,
|
|
112
|
+
} from './rendering/cameraFrameSource';
|
|
113
|
+
export type {
|
|
114
|
+
CameraFrameMountSelector,
|
|
115
|
+
CreateMountedCameraFrameSequencePlanOptions,
|
|
116
|
+
MountedCameraFrameCaptureSource,
|
|
117
|
+
MountedCameraFrameSequencePlanOptions,
|
|
118
|
+
MountedCameraFrameSequenceRecorderTarget,
|
|
119
|
+
MountedCameraFrameSequenceCameraOptions,
|
|
120
|
+
MountedCameraFrameSequenceDefaults,
|
|
121
|
+
MountedCameraFrameSequencePlan,
|
|
122
|
+
MountedCameraFrameSequenceReadiness,
|
|
123
|
+
MountedCameraFrameSequenceRecordOptions,
|
|
124
|
+
MountedCameraFrameSequenceRecordResult,
|
|
125
|
+
MountedCameraFrameSequenceSourceReadiness,
|
|
126
|
+
NamedCameraFrameResource,
|
|
127
|
+
ResolveMountedCameraFrameSourceOptions,
|
|
128
|
+
ResolvedMountedCameraFrameSource,
|
|
129
|
+
} from './rendering/cameraFrameSource';
|
|
85
130
|
export { useCtrlNoise } from './hooks/useCtrlNoise';
|
|
86
131
|
export { useBodyMeshes } from './hooks/useBodyMeshes';
|
|
87
132
|
export { useSelectionHighlight } from './hooks/useSelectionHighlight';
|
|
@@ -123,6 +168,7 @@ export type {
|
|
|
123
168
|
SiteInfo,
|
|
124
169
|
ActuatorInfo,
|
|
125
170
|
SensorInfo,
|
|
171
|
+
CameraInfo,
|
|
126
172
|
// Contacts
|
|
127
173
|
ContactInfo,
|
|
128
174
|
// Raycast
|
|
@@ -165,8 +211,11 @@ export type {
|
|
|
165
211
|
SplatScenarioConfig,
|
|
166
212
|
SplatCollisionProxyConfig,
|
|
167
213
|
PairedSplatEnvironmentConfig,
|
|
214
|
+
SplatEnvironmentReadiness,
|
|
168
215
|
SplatEnvironmentMetadataInput,
|
|
169
216
|
SplatEnvironmentMetadata,
|
|
217
|
+
SplatSceneConfigInput,
|
|
218
|
+
SplatSceneConfigState,
|
|
170
219
|
SplatSceneInput,
|
|
171
220
|
VisualScenarioConfig,
|
|
172
221
|
ScenarioLightingProps,
|
|
@@ -181,6 +230,21 @@ export type {
|
|
|
181
230
|
// API
|
|
182
231
|
MujocoSimAPI,
|
|
183
232
|
MujocoFrameCaptureOptions,
|
|
233
|
+
CameraFrameCaptureAPI,
|
|
234
|
+
CameraFrameCaptureBlobResult,
|
|
235
|
+
CameraFrameCaptureOptions,
|
|
236
|
+
CameraFrameCaptureQuaternion,
|
|
237
|
+
CameraFrameCaptureResult,
|
|
238
|
+
CameraFrameCaptureSource,
|
|
239
|
+
CameraFrameCaptureVector3,
|
|
240
|
+
CameraFrameSequenceCamera,
|
|
241
|
+
CameraFrameSequenceCameraSummary,
|
|
242
|
+
CameraFrameSequenceFrame,
|
|
243
|
+
CameraFrameSequenceOptions,
|
|
244
|
+
CameraFrameSequenceRecorderAPI,
|
|
245
|
+
CameraFrameSequenceResult,
|
|
246
|
+
CameraFrameSequenceSampleInput,
|
|
247
|
+
CameraFrameSequenceStepInput,
|
|
184
248
|
MujocoCanvasProps,
|
|
185
249
|
MujocoContextValue,
|
|
186
250
|
// Hook return types
|
|
@@ -209,6 +273,7 @@ export type {
|
|
|
209
273
|
Sites,
|
|
210
274
|
Geoms,
|
|
211
275
|
Keyframes,
|
|
276
|
+
Cameras,
|
|
212
277
|
} from './types';
|
|
213
278
|
|
|
214
279
|
export {
|
|
@@ -221,6 +286,8 @@ export {
|
|
|
221
286
|
RobotSites,
|
|
222
287
|
RobotGeoms,
|
|
223
288
|
RobotKeyframes,
|
|
289
|
+
RobotCameras,
|
|
290
|
+
SplatEnvironmentReadinessStatus,
|
|
224
291
|
} from './types';
|
|
225
292
|
|
|
226
293
|
// Re-export MuJoCo types for convenience
|