mujoco-react 8.10.0 → 8.11.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 +65 -28
- package/dist/chunk-SEWQULWO.js +400 -0
- package/dist/chunk-SEWQULWO.js.map +1 -0
- package/dist/index.d.ts +82 -14
- package/dist/index.js +289 -17
- package/dist/index.js.map +1 -1
- package/dist/spark.d.ts +24 -3
- package/dist/spark.js +91 -6
- package/dist/spark.js.map +1 -1
- package/dist/{types-FFW7ykBu.d.ts → types-BmneHLBM.d.ts} +59 -5
- package/package.json +1 -1
- package/src/components/Body.tsx +3 -1
- package/src/components/VisualScenario.tsx +343 -6
- package/src/core/MujocoCanvas.tsx +8 -1
- package/src/core/SceneLoader.ts +182 -3
- package/src/hooks/useFrameCapture.ts +206 -0
- package/src/hooks/usePolicy.ts +12 -8
- package/src/index.ts +25 -0
- package/src/spark.tsx +138 -4
- package/src/types.ts +69 -4
- package/dist/chunk-KGFRKPLS.js +0 -186
- package/dist/chunk-KGFRKPLS.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import { M as MujocoContextValue, a as MujocoCanvasProps, b as MujocoSimAPI, S as SceneConfig, c as MujocoModule, P as PhysicsStepCallback, d as MujocoModel, e as MujocoData, C as ControlGroupInfo, A as ActuatedJointInfo, f as ControlGroupSelector, O as ObservationConfig, g as ObservationResult, I as IkConfig, h as IkContextValue, B as BodyProps, i as IkGizmoProps, D as DragInteractionProps, j as SceneLightsProps, k as ScenarioLightingProps, l as SplatEnvironmentProps, m as
|
|
3
|
-
export {
|
|
2
|
+
import { M as MujocoContextValue, a as MujocoCanvasProps, b as MujocoSimAPI, S as SceneConfig, c as MujocoModule, P as PhysicsStepCallback, d as MujocoModel, e as MujocoData, C as ControlGroupInfo, A as ActuatedJointInfo, f as ControlGroupSelector, O as ObservationConfig, g as ObservationResult, I as IkConfig, h as IkContextValue, B as BodyProps, i as IkGizmoProps, D as DragInteractionProps, j as SceneLightsProps, k as ScenarioLightingProps, l as SplatEnvironmentProps, V as VisualScenarioEffectsProps, m as VisualScenarioConfig, n as SplatRendererKind, o as PairedSplatEnvironmentConfig, p as SplatFormat, q as SplatCollisionProxyConfig, r as SplatCollisionPrimitive, s as ScenarioLightingPreset, t as SplatEnvironmentMetadataInput, u as SplatEnvironmentMetadata, v as SplatSceneInput, w as DebugProps, G as GeomInfo, x as ContactListenerProps, T as TrajectoryPlayerProps, y as ActuatorInfo, z as Sites, E as SitePositionResult, F as Sensors, H as SensorHandle, J as SensorInfo, K as Joints, L as JointStateResult, N as Bodies, Q as BodyStateResult, R as Actuators, U as CtrlHandle, W as ContactInfo, X as KeyboardTeleopConfig, Y as PolicyConfig, Z as PolicyVector, _ as ObservationHandle, $ as TrajectoryInput, a0 as PlaybackState, a1 as TrajectoryFrame } from './types-BmneHLBM.js';
|
|
3
|
+
export { a2 as BodyInfo, a3 as ControlJointInfo, a4 as Geoms, a5 as IKSolveFn, a6 as JointInfo, a7 as KeyBinding, a8 as Keyframes, a9 as ModelOptions, aa as MujocoContact, ab as MujocoContactArray, ac as ObservationLayoutItem, ad as ObservationOutput, ae as PhysicsConfig, af as PolicyActionInput, ag as PolicyInferenceInput, ah as PolicyObservationInput, ai as RayHit, aj as Register, ak as RegisteredRobotMap, al as ResourceSelector, am as RobotActuators, an as RobotBodies, ao as RobotGeoms, ap as RobotJoints, aq as RobotKeyframes, ar as RobotResource, as as RobotResources, at as RobotSensors, au as RobotSites, av as Robots, aw as ScenarioCameraConfig, ax as ScenarioMaterialConfig, ay as SceneMarker, az as SceneObject, aA as SensorResult, aB as SiteInfo, aC as SplatAssetConfig, aD as SplatScenarioConfig, aE as StateSnapshot, aF as TrajectoryData, aG as XmlPatch, aH as getContact, aI as registerRobotResources } from './types-BmneHLBM.js';
|
|
4
4
|
import * as React$1 from 'react';
|
|
5
|
+
import React__default from 'react';
|
|
5
6
|
import { ThreeElements } from '@react-three/fiber';
|
|
6
7
|
import * as THREE from 'three';
|
|
7
8
|
|
|
@@ -300,7 +301,7 @@ declare const useIkController: (config: IkConfig | null) => IkContextValue | nul
|
|
|
300
301
|
* runs before the provider's loadScene useEffect). Bodies added/removed after
|
|
301
302
|
* the initial load trigger a debounced scene reload.
|
|
302
303
|
*/
|
|
303
|
-
declare function Body({ name, type, size, position, rgba, mass, freejoint, friction, solref, solimp, condim, children, }: BodyProps): react_jsx_runtime.JSX.Element | null;
|
|
304
|
+
declare function Body({ name, type, size, position, rgba, mass, freejoint, friction, solref, solimp, condim, group, children, }: BodyProps): react_jsx_runtime.JSX.Element | null;
|
|
304
305
|
|
|
305
306
|
/**
|
|
306
307
|
* IkGizmo — drei PivotControls that tracks a MuJoCo site.
|
|
@@ -363,6 +364,8 @@ declare function SceneLights({ intensity }: SceneLightsProps): null;
|
|
|
363
364
|
declare function ScenarioLighting({ preset, castShadow, intensity, }: ScenarioLightingProps): react_jsx_runtime.JSX.Element;
|
|
364
365
|
declare function getScenarioBackground(preset: ScenarioLightingPreset | undefined, fallback?: string): string;
|
|
365
366
|
declare function getScenarioCameraPosition(basePosition: readonly [number, number, number], scenario?: Pick<VisualScenarioConfig, 'camera'>): [number, number, number];
|
|
367
|
+
declare function VisualScenarioEffects(props: VisualScenarioEffectsProps): null;
|
|
368
|
+
declare function useVisualScenarioEffects({ scenario, enabled, applyBackground, applyFog, applyRenderer, applyMaterials, background, fogNear, fogFar, materialFilter, }: VisualScenarioEffectsProps): void;
|
|
366
369
|
/**
|
|
367
370
|
* Renderer-agnostic Gaussian splat environment boundary.
|
|
368
371
|
*
|
|
@@ -370,8 +373,29 @@ declare function getScenarioCameraPosition(basePosition: readonly [number, numbe
|
|
|
370
373
|
* Spark/GaussianSplats3D object as `children` once the app chooses a renderer,
|
|
371
374
|
* and pass MuJoCo/MJCF collision proxy visuals via `collisionProxy`.
|
|
372
375
|
*/
|
|
373
|
-
declare function SplatEnvironment({ environment, src, format, collisionProxy, collisionProxyMetadata, children, showPlaceholder, ...groupProps }: SplatEnvironmentProps): react_jsx_runtime.JSX.Element;
|
|
374
|
-
declare function useSplatEnvironment({ environment, src, format, collisionProxy, }: SplatEnvironmentMetadataInput): SplatEnvironmentMetadata;
|
|
376
|
+
declare function SplatEnvironment({ environment, scenario, renderer, src, format, collisionProxy, collisionProxyMetadata, children, showPlaceholder, ...groupProps }: SplatEnvironmentProps): react_jsx_runtime.JSX.Element;
|
|
377
|
+
declare function useSplatEnvironment({ environment, scenario, renderer, src, format, collisionProxy, }: SplatEnvironmentMetadataInput): SplatEnvironmentMetadata;
|
|
378
|
+
/**
|
|
379
|
+
* Convert a generic visual scenario splat block into a paired visual/physics
|
|
380
|
+
* environment config. Returns undefined until both the splat asset and MJCF
|
|
381
|
+
* collision proxy are present.
|
|
382
|
+
*/
|
|
383
|
+
declare function createPairedSplatEnvironment(scenario: Pick<VisualScenarioConfig, 'id' | 'label' | 'environment' | 'splat'>, options?: {
|
|
384
|
+
id?: string;
|
|
385
|
+
label?: string;
|
|
386
|
+
description?: string;
|
|
387
|
+
renderer?: SplatRendererKind;
|
|
388
|
+
}): PairedSplatEnvironmentConfig | undefined;
|
|
389
|
+
/**
|
|
390
|
+
* Compose a MuJoCo scene config with a paired splat collision proxy.
|
|
391
|
+
*
|
|
392
|
+
* This keeps the common hybrid setup declarative:
|
|
393
|
+
* robot XML remains `sceneFile`, the `.spz` remains a visual-only layer, and
|
|
394
|
+
* the paired MJCF collision proxy is added to `environmentFiles`.
|
|
395
|
+
*/
|
|
396
|
+
declare function withSplatEnvironment(sceneConfig: SceneConfig, input: SplatSceneInput, options?: {
|
|
397
|
+
renderer?: SplatRendererKind;
|
|
398
|
+
}): SceneConfig;
|
|
375
399
|
declare function createSplatEnvironmentUserData({ environment, src, format, collisionProxy, }: {
|
|
376
400
|
environment?: PairedSplatEnvironmentConfig;
|
|
377
401
|
src?: string;
|
|
@@ -587,13 +611,6 @@ declare function useContactEvents(bodyName: Bodies, handlers: {
|
|
|
587
611
|
*/
|
|
588
612
|
declare function useKeyboardTeleop(config: KeyboardTeleopConfig): void;
|
|
589
613
|
|
|
590
|
-
/**
|
|
591
|
-
* @license
|
|
592
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
593
|
-
*
|
|
594
|
-
* usePolicy — policy decimation loop hook (spec 10.1)
|
|
595
|
-
*/
|
|
596
|
-
|
|
597
614
|
/**
|
|
598
615
|
* Framework-agnostic policy execution hook.
|
|
599
616
|
*
|
|
@@ -608,7 +625,8 @@ declare function usePolicy(config: PolicyConfig): {
|
|
|
608
625
|
readonly isRunning: boolean;
|
|
609
626
|
start: () => void;
|
|
610
627
|
stop: () => void;
|
|
611
|
-
readonly lastObservation:
|
|
628
|
+
readonly lastObservation: PolicyVector | null;
|
|
629
|
+
readonly lastAction: Float64Array<ArrayBufferLike> | Float32Array<ArrayBufferLike> | number[] | null;
|
|
612
630
|
};
|
|
613
631
|
|
|
614
632
|
/**
|
|
@@ -733,6 +751,56 @@ declare function useVideoRecorder(options?: VideoRecorderOptions): {
|
|
|
733
751
|
readonly recording: boolean;
|
|
734
752
|
};
|
|
735
753
|
|
|
754
|
+
/**
|
|
755
|
+
* @license
|
|
756
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
757
|
+
*
|
|
758
|
+
* useFrameCapture — still-frame capture for canvas-backed MuJoCo/R3F scenes.
|
|
759
|
+
*/
|
|
760
|
+
|
|
761
|
+
type FrameCaptureStatus = 'idle' | 'capturing' | 'captured' | 'error';
|
|
762
|
+
type FrameCaptureTarget = HTMLCanvasElement | HTMLElement | null | undefined;
|
|
763
|
+
type FrameCaptureTargetRef = React__default.RefObject<HTMLCanvasElement | HTMLElement | null>;
|
|
764
|
+
interface FrameCaptureOptions {
|
|
765
|
+
target?: FrameCaptureTarget | FrameCaptureTargetRef;
|
|
766
|
+
type?: string;
|
|
767
|
+
quality?: number;
|
|
768
|
+
waitForAnimationFrame?: boolean;
|
|
769
|
+
}
|
|
770
|
+
interface FrameCaptureResult {
|
|
771
|
+
canvas: HTMLCanvasElement;
|
|
772
|
+
dataUrl: string;
|
|
773
|
+
type: string;
|
|
774
|
+
}
|
|
775
|
+
interface FrameCaptureBlobResult {
|
|
776
|
+
canvas: HTMLCanvasElement;
|
|
777
|
+
blob: Blob;
|
|
778
|
+
type: string;
|
|
779
|
+
}
|
|
780
|
+
interface FrameCaptureAPI {
|
|
781
|
+
status: FrameCaptureStatus;
|
|
782
|
+
error: Error | null;
|
|
783
|
+
isCapturing: boolean;
|
|
784
|
+
capture: (options?: FrameCaptureOptions) => Promise<FrameCaptureResult>;
|
|
785
|
+
captureBlob: (options?: FrameCaptureOptions) => Promise<FrameCaptureBlobResult>;
|
|
786
|
+
reset: () => void;
|
|
787
|
+
}
|
|
788
|
+
/**
|
|
789
|
+
* Capture the current canvas frame as a data URL.
|
|
790
|
+
*
|
|
791
|
+
* For WebGL scenes, create the renderer with `preserveDrawingBuffer: true`
|
|
792
|
+
* when you need deterministic captures after the frame has presented.
|
|
793
|
+
*/
|
|
794
|
+
declare function captureFrame(options: FrameCaptureOptions): Promise<FrameCaptureResult>;
|
|
795
|
+
/**
|
|
796
|
+
* Capture the current canvas frame as a Blob.
|
|
797
|
+
*/
|
|
798
|
+
declare function captureFrameBlob(options: FrameCaptureOptions): Promise<FrameCaptureBlobResult>;
|
|
799
|
+
/**
|
|
800
|
+
* React state wrapper around `captureFrame` and `captureFrameBlob`.
|
|
801
|
+
*/
|
|
802
|
+
declare function useFrameCapture(defaultOptions?: FrameCaptureOptions): FrameCaptureAPI;
|
|
803
|
+
|
|
736
804
|
/**
|
|
737
805
|
* @license
|
|
738
806
|
* SPDX-License-Identifier: Apache-2.0
|
|
@@ -828,4 +896,4 @@ interface CameraAnimationAPI {
|
|
|
828
896
|
*/
|
|
829
897
|
declare function useCameraAnimation(): CameraAnimationAPI;
|
|
830
898
|
|
|
831
|
-
export { ActuatedJointInfo, ActuatorInfo, Actuators, Bodies, Body, BodyProps, BodyStateResult, type CameraAnimationAPI, ContactInfo, ContactListener, ContactListenerProps, ContactMarkers, ControlGroupInfo, ControlGroupSelector, type ControllerComponent, type ControllerOptions, CtrlHandle, Debug, DebugProps, DragInteraction, DragInteractionProps, FlexRenderer, GeomInfo, IkConfig, IkContextValue, IkGizmo, IkGizmoProps, InstancedGeomRenderer, JointStateResult, Joints, KeyboardTeleopConfig, MujocoCanvas, MujocoCanvasProps, MujocoContextValue, MujocoData, type MujocoLoader, type MujocoLoaderOptions, MujocoModel, MujocoModule, MujocoPhysics, type MujocoPhysicsProps, MujocoProvider, type MujocoProviderProps, MujocoSimAPI, MujocoSimProvider, type MujocoWasmVariant, ObservationConfig, ObservationHandle, ObservationResult, PairedSplatEnvironmentConfig, PhysicsStepCallback, PlaybackState, PolicyConfig, ScenarioLighting, ScenarioLightingPreset, ScenarioLightingProps, SceneConfig, SceneLights, SceneLightsProps, SensorHandle, SensorInfo, Sensors, SitePositionResult, Sites, SplatCollisionPrimitive, SplatCollisionProxyConfig, SplatEnvironment, SplatEnvironmentMetadata, SplatEnvironmentMetadataInput, SplatEnvironmentProps, SplatFormat, SplatRendererKind, TendonRenderer, TrajectoryFrame, TrajectoryInput, TrajectoryPlayer, TrajectoryPlayerProps, VisualScenarioConfig, buildObservation, createContiguousControlGroup, createController, createControllerHook, createSparkSplatViewerUrl, createSplatEnvironmentUserData, findActuatorByName, findBodyByName, findGeomByName, findJointByName, findKeyframeByName, findSensorByName, findSiteByName, findTendonByName, getActuatedJoints, getControlMap, getName, getScenarioBackground, getScenarioCameraPosition, 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, useSplatEnvironment, useTrajectoryPlayer, useTrajectoryRecorder, useVideoRecorder };
|
|
899
|
+
export { ActuatedJointInfo, ActuatorInfo, Actuators, Bodies, Body, BodyProps, BodyStateResult, type CameraAnimationAPI, ContactInfo, ContactListener, ContactListenerProps, ContactMarkers, ControlGroupInfo, ControlGroupSelector, type ControllerComponent, type ControllerOptions, CtrlHandle, Debug, DebugProps, DragInteraction, DragInteractionProps, FlexRenderer, type FrameCaptureAPI, type FrameCaptureBlobResult, type FrameCaptureOptions, type FrameCaptureResult, type FrameCaptureStatus, type FrameCaptureTarget, type FrameCaptureTargetRef, GeomInfo, IkConfig, IkContextValue, IkGizmo, IkGizmoProps, InstancedGeomRenderer, JointStateResult, Joints, KeyboardTeleopConfig, MujocoCanvas, MujocoCanvasProps, MujocoContextValue, MujocoData, type MujocoLoader, type MujocoLoaderOptions, MujocoModel, MujocoModule, MujocoPhysics, type MujocoPhysicsProps, MujocoProvider, type MujocoProviderProps, MujocoSimAPI, MujocoSimProvider, type MujocoWasmVariant, ObservationConfig, ObservationHandle, ObservationResult, PairedSplatEnvironmentConfig, PhysicsStepCallback, PlaybackState, PolicyConfig, PolicyVector, ScenarioLighting, ScenarioLightingPreset, ScenarioLightingProps, SceneConfig, SceneLights, SceneLightsProps, SensorHandle, SensorInfo, Sensors, SitePositionResult, Sites, SplatCollisionPrimitive, SplatCollisionProxyConfig, SplatEnvironment, SplatEnvironmentMetadata, SplatEnvironmentMetadataInput, SplatEnvironmentProps, SplatFormat, SplatRendererKind, SplatSceneInput, TendonRenderer, TrajectoryFrame, TrajectoryInput, TrajectoryPlayer, TrajectoryPlayerProps, VisualScenarioConfig, VisualScenarioEffects, VisualScenarioEffectsProps, buildObservation, captureFrame, captureFrameBlob, createContiguousControlGroup, createController, createControllerHook, createPairedSplatEnvironment, createSparkSplatViewerUrl, createSplatEnvironmentUserData, findActuatorByName, findBodyByName, findGeomByName, findJointByName, findKeyframeByName, findSensorByName, findSiteByName, findTendonByName, getActuatedJoints, getControlMap, getName, getScenarioBackground, getScenarioCameraPosition, loadScene, resolveControlGroup, useActuators, useAfterPhysicsStep, useBeforePhysicsStep, useBodyMeshes, useBodyState, useCameraAnimation, useContactEvents, useContacts, useCtrl, useCtrlNoise, useFrameCapture, useGamepad, useGravityCompensation, useIkController, useJointState, useKeyboardTeleop, useMujoco, useMujocoWasm, useObservation, usePolicy, useSceneLights, useSelectionHighlight, useSensor, useSensors, useSitePosition, useSplatEnvironment, useTrajectoryPlayer, useTrajectoryRecorder, useVideoRecorder, useVisualScenarioEffects, withSplatEnvironment };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { ScenarioLighting, SplatEnvironment, createSparkSplatViewerUrl, createSplatEnvironmentUserData, getScenarioBackground, getScenarioCameraPosition, useSplatEnvironment } from './chunk-
|
|
1
|
+
export { ScenarioLighting, SplatEnvironment, VisualScenarioEffects, createPairedSplatEnvironment, createSparkSplatViewerUrl, createSplatEnvironmentUserData, getScenarioBackground, getScenarioCameraPosition, useSplatEnvironment, useVisualScenarioEffects, withSplatEnvironment } from './chunk-SEWQULWO.js';
|
|
2
2
|
import loadMujoco from '@mujoco/mujoco';
|
|
3
3
|
import defaultMujocoWasmUrl from '@mujoco/mujoco/mujoco.wasm?url';
|
|
4
4
|
import { createContext, forwardRef, useEffect, useContext, useState, useRef, useCallback, useMemo, useLayoutEffect } from 'react';
|
|
@@ -776,7 +776,8 @@ function sceneObjectToXml(obj) {
|
|
|
776
776
|
const solref = obj.solref ? ` solref="${obj.solref}"` : "";
|
|
777
777
|
const solimp = obj.solimp ? ` solimp="${obj.solimp}"` : "";
|
|
778
778
|
const condim = obj.condim ? ` condim="${obj.condim}"` : "";
|
|
779
|
-
|
|
779
|
+
const group = obj.group !== void 0 ? ` group="${obj.group}"` : "";
|
|
780
|
+
return `<body name="${obj.name}" pos="${pos}">${joint}<geom type="${obj.type}" size="${size}" rgba="${rgba}" contype="1" conaffinity="1"${mass}${friction}${solref}${solimp}${condim}${group}/></body>`;
|
|
780
781
|
}
|
|
781
782
|
function ensureDir(mujoco, fname) {
|
|
782
783
|
const dirParts = fname.split("/");
|
|
@@ -816,6 +817,20 @@ function normalizeVfsPath(path) {
|
|
|
816
817
|
function localFilePath(file) {
|
|
817
818
|
return normalizeVfsPath(file.webkitRelativePath || file.name);
|
|
818
819
|
}
|
|
820
|
+
function dirname(path) {
|
|
821
|
+
const normalized = normalizeVfsPath(path);
|
|
822
|
+
const idx = normalized.lastIndexOf("/");
|
|
823
|
+
return idx === -1 ? "" : normalized.slice(0, idx + 1);
|
|
824
|
+
}
|
|
825
|
+
function relativeVfsPath(fromDir, targetPath) {
|
|
826
|
+
const from = normalizeVfsPath(fromDir).split("/").filter(Boolean);
|
|
827
|
+
const target = normalizeVfsPath(targetPath).split("/").filter(Boolean);
|
|
828
|
+
while (from.length && target.length && from[0] === target[0]) {
|
|
829
|
+
from.shift();
|
|
830
|
+
target.shift();
|
|
831
|
+
}
|
|
832
|
+
return [...from.map(() => ".."), ...target].join("/") || ".";
|
|
833
|
+
}
|
|
819
834
|
function inferSceneFile(files, options) {
|
|
820
835
|
if (options?.sceneFile) return normalizeVfsPath(options.sceneFile);
|
|
821
836
|
const paths = files.map(localFilePath);
|
|
@@ -834,12 +849,120 @@ function createSceneConfigFromFiles(files, options = {}) {
|
|
|
834
849
|
src: "",
|
|
835
850
|
sceneFile: inferSceneFile(fileArray, options),
|
|
836
851
|
files: fileArray,
|
|
852
|
+
environmentFiles: options.environmentFiles?.map(normalizeVfsPath),
|
|
837
853
|
homeJoints: options.homeJoints,
|
|
838
854
|
xmlPatches: options.xmlPatches,
|
|
839
855
|
sceneObjects: options.sceneObjects,
|
|
840
856
|
onReset: options.onReset
|
|
841
857
|
};
|
|
842
858
|
}
|
|
859
|
+
var ENVIRONMENT_MERGE_SECTIONS = [
|
|
860
|
+
"asset",
|
|
861
|
+
"worldbody",
|
|
862
|
+
"contact",
|
|
863
|
+
"equality",
|
|
864
|
+
"tendon",
|
|
865
|
+
"sensor",
|
|
866
|
+
"keyframe",
|
|
867
|
+
"custom",
|
|
868
|
+
"extension"
|
|
869
|
+
];
|
|
870
|
+
function directChild(parent, tagName) {
|
|
871
|
+
const lower = tagName.toLowerCase();
|
|
872
|
+
for (const child of Array.from(parent.children)) {
|
|
873
|
+
if (child.tagName.toLowerCase() === lower) return child;
|
|
874
|
+
}
|
|
875
|
+
return null;
|
|
876
|
+
}
|
|
877
|
+
function ensureTopLevelSection(doc, tagName) {
|
|
878
|
+
const root = doc.documentElement;
|
|
879
|
+
const existing = directChild(root, tagName);
|
|
880
|
+
if (existing) return existing;
|
|
881
|
+
const section = doc.createElement(tagName);
|
|
882
|
+
if (tagName === "asset") {
|
|
883
|
+
const worldbody = directChild(root, "worldbody");
|
|
884
|
+
if (worldbody) root.insertBefore(section, worldbody);
|
|
885
|
+
else root.appendChild(section);
|
|
886
|
+
} else {
|
|
887
|
+
root.appendChild(section);
|
|
888
|
+
}
|
|
889
|
+
return section;
|
|
890
|
+
}
|
|
891
|
+
function readCompilerDirs(doc) {
|
|
892
|
+
const compiler = directChild(doc.documentElement, "compiler");
|
|
893
|
+
const assetDir = compiler?.getAttribute("assetdir") || "";
|
|
894
|
+
return {
|
|
895
|
+
meshDir: compiler?.getAttribute("meshdir") || assetDir,
|
|
896
|
+
textureDir: compiler?.getAttribute("texturedir") || assetDir
|
|
897
|
+
};
|
|
898
|
+
}
|
|
899
|
+
function isExternalPath(path) {
|
|
900
|
+
return /^[a-z]+:\/\//i.test(path) || path.startsWith("package://") || path.startsWith("/");
|
|
901
|
+
}
|
|
902
|
+
function fileReferencePrefix(el, compilerDirs) {
|
|
903
|
+
const tag = el.tagName.toLowerCase();
|
|
904
|
+
if (tag === "mesh") return compilerDirs.meshDir ? compilerDirs.meshDir + "/" : "";
|
|
905
|
+
if (tag === "texture" || tag === "hfield") return compilerDirs.textureDir ? compilerDirs.textureDir + "/" : "";
|
|
906
|
+
return "";
|
|
907
|
+
}
|
|
908
|
+
function rewriteFileReferencesForMerge(node, sourceFile, targetFile, sourceDoc) {
|
|
909
|
+
const sourceDir = dirname(sourceFile);
|
|
910
|
+
const targetDir = dirname(targetFile);
|
|
911
|
+
const compilerDirs = readCompilerDirs(sourceDoc);
|
|
912
|
+
node.querySelectorAll("[file], [filename]").forEach((el) => {
|
|
913
|
+
const attr = el.hasAttribute("file") ? "file" : "filename";
|
|
914
|
+
const value = el.getAttribute(attr);
|
|
915
|
+
if (!value || isExternalPath(value)) return;
|
|
916
|
+
const sourceRelativePath = normalizeVfsPath(fileReferencePrefix(el, compilerDirs) + value);
|
|
917
|
+
const resolvedPath = normalizeVfsPath(sourceDir + sourceRelativePath);
|
|
918
|
+
el.setAttribute(attr, relativeVfsPath(targetDir, resolvedPath));
|
|
919
|
+
});
|
|
920
|
+
}
|
|
921
|
+
function hasParseError(doc) {
|
|
922
|
+
return doc.getElementsByTagName("parsererror").length > 0;
|
|
923
|
+
}
|
|
924
|
+
function composeEnvironmentXml(sceneXml, config, parser, environmentXmlByPath) {
|
|
925
|
+
const environmentFiles = config.environmentFiles?.map(normalizeVfsPath) ?? [];
|
|
926
|
+
if (!environmentFiles.length) return sceneXml;
|
|
927
|
+
const sceneDoc = parser.parseFromString(sceneXml, "text/xml");
|
|
928
|
+
if (hasParseError(sceneDoc)) {
|
|
929
|
+
console.warn(`Could not compose environments: failed to parse ${config.sceneFile}`);
|
|
930
|
+
return sceneXml;
|
|
931
|
+
}
|
|
932
|
+
for (const environmentFile of environmentFiles) {
|
|
933
|
+
const environmentXml = environmentXmlByPath.get(environmentFile);
|
|
934
|
+
if (!environmentXml) {
|
|
935
|
+
console.warn(`Environment XML not found: ${environmentFile}`);
|
|
936
|
+
continue;
|
|
937
|
+
}
|
|
938
|
+
const environmentDoc = parser.parseFromString(environmentXml, "text/xml");
|
|
939
|
+
if (hasParseError(environmentDoc)) {
|
|
940
|
+
console.warn(`Skipping environment XML with parse errors: ${environmentFile}`);
|
|
941
|
+
continue;
|
|
942
|
+
}
|
|
943
|
+
for (const sectionName of ENVIRONMENT_MERGE_SECTIONS) {
|
|
944
|
+
const environmentSection = directChild(environmentDoc.documentElement, sectionName);
|
|
945
|
+
if (!environmentSection?.children.length) continue;
|
|
946
|
+
const targetSection = ensureTopLevelSection(sceneDoc, sectionName);
|
|
947
|
+
for (const child of Array.from(environmentSection.children)) {
|
|
948
|
+
const imported = sceneDoc.importNode(child, true);
|
|
949
|
+
rewriteFileReferencesForMerge(imported, environmentFile, config.sceneFile, environmentDoc);
|
|
950
|
+
targetSection.appendChild(imported);
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
return new XMLSerializer().serializeToString(sceneDoc);
|
|
955
|
+
}
|
|
956
|
+
function findTextByConfiguredPath(textByPath, configuredPath) {
|
|
957
|
+
const normalized = normalizeVfsPath(configuredPath);
|
|
958
|
+
const direct = textByPath.get(normalized);
|
|
959
|
+
if (direct) return direct;
|
|
960
|
+
const suffix = "/" + normalized;
|
|
961
|
+
for (const [path, text] of textByPath) {
|
|
962
|
+
if (path.endsWith(suffix) || path === normalized.split("/").pop()) return text;
|
|
963
|
+
}
|
|
964
|
+
return void 0;
|
|
965
|
+
}
|
|
843
966
|
function applyXmlPatches(text, fname, config) {
|
|
844
967
|
let result = text;
|
|
845
968
|
for (const patch of config.xmlPatches ?? []) {
|
|
@@ -902,10 +1025,21 @@ async function loadSceneFromFiles(mujoco, config, onProgress) {
|
|
|
902
1025
|
if (isModelTextFile(path)) {
|
|
903
1026
|
const text = applyXmlPatches(await file.text(), path, config);
|
|
904
1027
|
textByPath.set(path, text);
|
|
905
|
-
mujoco.FS.writeFile(`/working/${path}`, text);
|
|
906
1028
|
} else {
|
|
907
1029
|
mujoco.FS.writeFile(`/working/${path}`, new Uint8Array(await file.arrayBuffer()));
|
|
1030
|
+
written.add(path);
|
|
908
1031
|
}
|
|
1032
|
+
}
|
|
1033
|
+
const environmentXmlByPath = /* @__PURE__ */ new Map();
|
|
1034
|
+
for (const environmentFile of config.environmentFiles?.map(normalizeVfsPath) ?? []) {
|
|
1035
|
+
const environmentXml = findTextByConfiguredPath(textByPath, environmentFile);
|
|
1036
|
+
if (environmentXml) environmentXmlByPath.set(environmentFile, environmentXml);
|
|
1037
|
+
}
|
|
1038
|
+
for (const [path, text] of textByPath) {
|
|
1039
|
+
const composedText = path === config.sceneFile ? composeEnvironmentXml(text, config, parser, environmentXmlByPath) : text;
|
|
1040
|
+
textByPath.set(path, composedText);
|
|
1041
|
+
ensureDir(mujoco, path);
|
|
1042
|
+
mujoco.FS.writeFile(`/working/${path}`, composedText);
|
|
909
1043
|
written.add(path);
|
|
910
1044
|
}
|
|
911
1045
|
for (const [path, text] of textByPath) {
|
|
@@ -954,6 +1088,17 @@ async function loadScene(mujoco, config, onProgress) {
|
|
|
954
1088
|
} catch {
|
|
955
1089
|
}
|
|
956
1090
|
const baseUrl = config.src.endsWith("/") ? config.src : config.src + "/";
|
|
1091
|
+
const environmentXmlByPath = /* @__PURE__ */ new Map();
|
|
1092
|
+
const environmentFiles = config.environmentFiles?.map(normalizeVfsPath) ?? [];
|
|
1093
|
+
for (const environmentFile of environmentFiles) {
|
|
1094
|
+
onProgress?.(`Downloading ${environmentFile}...`);
|
|
1095
|
+
const res = await fetch(baseUrl + environmentFile);
|
|
1096
|
+
if (!res.ok) {
|
|
1097
|
+
console.warn(`Failed to fetch environment XML ${environmentFile}: ${res.status} ${res.statusText}`);
|
|
1098
|
+
continue;
|
|
1099
|
+
}
|
|
1100
|
+
environmentXmlByPath.set(environmentFile, applyXmlPatches(await res.text(), environmentFile, config));
|
|
1101
|
+
}
|
|
957
1102
|
const downloaded = /* @__PURE__ */ new Set();
|
|
958
1103
|
const xmlQueue = [config.sceneFile];
|
|
959
1104
|
const assetFiles = [];
|
|
@@ -972,7 +1117,8 @@ async function loadScene(mujoco, config, onProgress) {
|
|
|
972
1117
|
console.warn(`Failed to fetch ${fname}: ${res.status} ${res.statusText}`);
|
|
973
1118
|
continue;
|
|
974
1119
|
}
|
|
975
|
-
const
|
|
1120
|
+
const patchedText = applyXmlPatches(await res.text(), fname, config);
|
|
1121
|
+
const text = fname === config.sceneFile ? composeEnvironmentXml(patchedText, config, parser, environmentXmlByPath) : patchedText;
|
|
976
1122
|
ensureDir(mujoco, fname);
|
|
977
1123
|
mujoco.FS.writeFile(`/working/${fname}`, text);
|
|
978
1124
|
scanDependencies(text, fname, parser, downloaded, xmlQueue);
|
|
@@ -2209,6 +2355,7 @@ var MujocoCanvas = forwardRef(
|
|
|
2209
2355
|
paused,
|
|
2210
2356
|
speed,
|
|
2211
2357
|
interpolate,
|
|
2358
|
+
loadingFallback,
|
|
2212
2359
|
children,
|
|
2213
2360
|
...canvasProps
|
|
2214
2361
|
}, ref) {
|
|
@@ -2218,7 +2365,10 @@ var MujocoCanvas = forwardRef(
|
|
|
2218
2365
|
onError(new Error(wasmError ?? "WASM load failed"));
|
|
2219
2366
|
}
|
|
2220
2367
|
}, [wasmStatus, wasmError, onError]);
|
|
2221
|
-
if (wasmStatus === "
|
|
2368
|
+
if (wasmStatus === "loading" || !mujoco) {
|
|
2369
|
+
return loadingFallback ? /* @__PURE__ */ jsx(Canvas, { ...canvasProps, children: loadingFallback }) : null;
|
|
2370
|
+
}
|
|
2371
|
+
if (wasmStatus === "error") {
|
|
2222
2372
|
return null;
|
|
2223
2373
|
}
|
|
2224
2374
|
return /* @__PURE__ */ jsx(Canvas, { ...canvasProps, children: /* @__PURE__ */ jsx(
|
|
@@ -2860,6 +3010,7 @@ function Body({
|
|
|
2860
3010
|
solref,
|
|
2861
3011
|
solimp,
|
|
2862
3012
|
condim,
|
|
3013
|
+
group,
|
|
2863
3014
|
children
|
|
2864
3015
|
}) {
|
|
2865
3016
|
const { bodyRegistryRef, hiddenBodiesRef, requestBodyReload, mjDataRef, mjModelRef, status } = useMujocoContext();
|
|
@@ -2879,7 +3030,8 @@ function Body({
|
|
|
2879
3030
|
friction,
|
|
2880
3031
|
solref,
|
|
2881
3032
|
solimp,
|
|
2882
|
-
condim
|
|
3033
|
+
condim,
|
|
3034
|
+
group
|
|
2883
3035
|
};
|
|
2884
3036
|
bodyRegistryRef.current.set(name, { definition, hasCustomChildren: hasChildren });
|
|
2885
3037
|
if (hasChildren) {
|
|
@@ -2892,7 +3044,7 @@ function Body({
|
|
|
2892
3044
|
requestBodyReload();
|
|
2893
3045
|
}
|
|
2894
3046
|
};
|
|
2895
|
-
}, [name, type, size, position, rgba, mass, freejoint, friction, solref, solimp, condim, hasChildren, bodyRegistryRef, hiddenBodiesRef, requestBodyReload]);
|
|
3047
|
+
}, [name, type, size, position, rgba, mass, freejoint, friction, solref, solimp, condim, group, hasChildren, bodyRegistryRef, hiddenBodiesRef, requestBodyReload]);
|
|
2896
3048
|
useEffect(() => {
|
|
2897
3049
|
if (status !== "ready") return;
|
|
2898
3050
|
const model = mjModelRef.current;
|
|
@@ -2904,12 +3056,12 @@ function Body({
|
|
|
2904
3056
|
if (!hasChildren) return;
|
|
2905
3057
|
const data = mjDataRef.current;
|
|
2906
3058
|
const id = bodyIdRef.current;
|
|
2907
|
-
const
|
|
2908
|
-
if (!data || id < 0 || !
|
|
3059
|
+
const group2 = groupRef.current;
|
|
3060
|
+
if (!data || id < 0 || !group2) return;
|
|
2909
3061
|
const i3 = id * 3;
|
|
2910
3062
|
const i4 = id * 4;
|
|
2911
|
-
|
|
2912
|
-
|
|
3063
|
+
group2.position.set(data.xpos[i3], data.xpos[i3 + 1], data.xpos[i3 + 2]);
|
|
3064
|
+
group2.quaternion.set(
|
|
2913
3065
|
data.xquat[i4 + 1],
|
|
2914
3066
|
data.xquat[i4 + 2],
|
|
2915
3067
|
data.xquat[i4 + 3],
|
|
@@ -4584,22 +4736,25 @@ function useKeyboardTeleop(config) {
|
|
|
4584
4736
|
});
|
|
4585
4737
|
}
|
|
4586
4738
|
function usePolicy(config) {
|
|
4587
|
-
const { mjModelRef } = useMujocoContext();
|
|
4588
4739
|
const lastActionTimeRef = useRef(0);
|
|
4740
|
+
const lastObservationRef = useRef(null);
|
|
4589
4741
|
const lastActionRef = useRef(null);
|
|
4590
|
-
const isRunningRef = useRef(true);
|
|
4742
|
+
const isRunningRef = useRef(config.enabled ?? true);
|
|
4591
4743
|
const configRef = useRef(config);
|
|
4592
4744
|
configRef.current = config;
|
|
4745
|
+
isRunningRef.current = config.enabled ?? isRunningRef.current;
|
|
4593
4746
|
useBeforePhysicsStep((model, data) => {
|
|
4594
4747
|
if (!isRunningRef.current) return;
|
|
4595
4748
|
const cfg = configRef.current;
|
|
4596
4749
|
model.opt?.timestep ?? 2e-3;
|
|
4597
4750
|
const interval = 1 / cfg.frequency;
|
|
4598
4751
|
if (data.time - lastActionTimeRef.current >= interval) {
|
|
4599
|
-
const
|
|
4600
|
-
cfg.
|
|
4752
|
+
const observation = cfg.onObservation({ model, data });
|
|
4753
|
+
const action = cfg.infer ? cfg.infer({ observation, model, data }) : observation;
|
|
4754
|
+
cfg.onAction({ action, observation, model, data });
|
|
4601
4755
|
lastActionTimeRef.current = data.time;
|
|
4602
|
-
|
|
4756
|
+
lastObservationRef.current = observation;
|
|
4757
|
+
lastActionRef.current = action;
|
|
4603
4758
|
}
|
|
4604
4759
|
});
|
|
4605
4760
|
return {
|
|
@@ -4613,6 +4768,9 @@ function usePolicy(config) {
|
|
|
4613
4768
|
isRunningRef.current = false;
|
|
4614
4769
|
},
|
|
4615
4770
|
get lastObservation() {
|
|
4771
|
+
return lastObservationRef.current;
|
|
4772
|
+
},
|
|
4773
|
+
get lastAction() {
|
|
4616
4774
|
return lastActionRef.current;
|
|
4617
4775
|
}
|
|
4618
4776
|
};
|
|
@@ -4809,6 +4967,114 @@ function useVideoRecorder(options = {}) {
|
|
|
4809
4967
|
}
|
|
4810
4968
|
};
|
|
4811
4969
|
}
|
|
4970
|
+
function isTargetRef(target) {
|
|
4971
|
+
return Boolean(target && typeof target === "object" && "current" in target);
|
|
4972
|
+
}
|
|
4973
|
+
function resolveCanvasTarget(target) {
|
|
4974
|
+
const resolvedTarget = isTargetRef(target) ? target.current : target;
|
|
4975
|
+
if (!resolvedTarget) {
|
|
4976
|
+
throw new Error("No frame capture target is available.");
|
|
4977
|
+
}
|
|
4978
|
+
if (resolvedTarget instanceof HTMLCanvasElement) {
|
|
4979
|
+
return resolvedTarget;
|
|
4980
|
+
}
|
|
4981
|
+
const canvas = resolvedTarget.querySelector("canvas");
|
|
4982
|
+
if (!canvas) {
|
|
4983
|
+
throw new Error("Frame capture target does not contain a canvas.");
|
|
4984
|
+
}
|
|
4985
|
+
return canvas;
|
|
4986
|
+
}
|
|
4987
|
+
function waitForNextAnimationFrame() {
|
|
4988
|
+
return new Promise((resolve) => {
|
|
4989
|
+
requestAnimationFrame(() => resolve());
|
|
4990
|
+
});
|
|
4991
|
+
}
|
|
4992
|
+
async function captureFrame(options) {
|
|
4993
|
+
const type = options.type ?? "image/png";
|
|
4994
|
+
const canvas = resolveCanvasTarget(options.target);
|
|
4995
|
+
if (options.waitForAnimationFrame ?? true) {
|
|
4996
|
+
await waitForNextAnimationFrame();
|
|
4997
|
+
}
|
|
4998
|
+
return {
|
|
4999
|
+
canvas,
|
|
5000
|
+
dataUrl: canvas.toDataURL(type, options.quality),
|
|
5001
|
+
type
|
|
5002
|
+
};
|
|
5003
|
+
}
|
|
5004
|
+
async function captureFrameBlob(options) {
|
|
5005
|
+
const type = options.type ?? "image/png";
|
|
5006
|
+
const canvas = resolveCanvasTarget(options.target);
|
|
5007
|
+
if (options.waitForAnimationFrame ?? true) {
|
|
5008
|
+
await waitForNextAnimationFrame();
|
|
5009
|
+
}
|
|
5010
|
+
const blob = await new Promise((resolve, reject) => {
|
|
5011
|
+
canvas.toBlob(
|
|
5012
|
+
(nextBlob) => {
|
|
5013
|
+
if (nextBlob) {
|
|
5014
|
+
resolve(nextBlob);
|
|
5015
|
+
} else {
|
|
5016
|
+
reject(new Error("Canvas frame capture did not produce a Blob."));
|
|
5017
|
+
}
|
|
5018
|
+
},
|
|
5019
|
+
type,
|
|
5020
|
+
options.quality
|
|
5021
|
+
);
|
|
5022
|
+
});
|
|
5023
|
+
return { canvas, blob, type };
|
|
5024
|
+
}
|
|
5025
|
+
function useFrameCapture(defaultOptions = {}) {
|
|
5026
|
+
const [status, setStatus] = useState("idle");
|
|
5027
|
+
const [error, setError] = useState(null);
|
|
5028
|
+
const reset = useCallback(() => {
|
|
5029
|
+
setStatus("idle");
|
|
5030
|
+
setError(null);
|
|
5031
|
+
}, []);
|
|
5032
|
+
const capture = useCallback(
|
|
5033
|
+
async (options = {}) => {
|
|
5034
|
+
setStatus("capturing");
|
|
5035
|
+
setError(null);
|
|
5036
|
+
try {
|
|
5037
|
+
const result = await captureFrame({ ...defaultOptions, ...options });
|
|
5038
|
+
setStatus("captured");
|
|
5039
|
+
return result;
|
|
5040
|
+
} catch (nextError) {
|
|
5041
|
+
const error2 = nextError instanceof Error ? nextError : new Error("Unable to capture the current canvas frame.");
|
|
5042
|
+
setError(error2);
|
|
5043
|
+
setStatus("error");
|
|
5044
|
+
throw error2;
|
|
5045
|
+
}
|
|
5046
|
+
},
|
|
5047
|
+
[defaultOptions]
|
|
5048
|
+
);
|
|
5049
|
+
const captureBlob = useCallback(
|
|
5050
|
+
async (options = {}) => {
|
|
5051
|
+
setStatus("capturing");
|
|
5052
|
+
setError(null);
|
|
5053
|
+
try {
|
|
5054
|
+
const result = await captureFrameBlob({
|
|
5055
|
+
...defaultOptions,
|
|
5056
|
+
...options
|
|
5057
|
+
});
|
|
5058
|
+
setStatus("captured");
|
|
5059
|
+
return result;
|
|
5060
|
+
} catch (nextError) {
|
|
5061
|
+
const error2 = nextError instanceof Error ? nextError : new Error("Unable to capture the current canvas frame.");
|
|
5062
|
+
setError(error2);
|
|
5063
|
+
setStatus("error");
|
|
5064
|
+
throw error2;
|
|
5065
|
+
}
|
|
5066
|
+
},
|
|
5067
|
+
[defaultOptions]
|
|
5068
|
+
);
|
|
5069
|
+
return {
|
|
5070
|
+
status,
|
|
5071
|
+
error,
|
|
5072
|
+
isCapturing: status === "capturing",
|
|
5073
|
+
capture,
|
|
5074
|
+
captureBlob,
|
|
5075
|
+
reset
|
|
5076
|
+
};
|
|
5077
|
+
}
|
|
4812
5078
|
function useCtrlNoise(config = {}) {
|
|
4813
5079
|
const { mjModelRef } = useMujocoContext();
|
|
4814
5080
|
const configRef = useRef(config);
|
|
@@ -5094,6 +5360,12 @@ function useCameraAnimation() {
|
|
|
5094
5360
|
*
|
|
5095
5361
|
* useVideoRecorder — canvas video recording hook (spec 13.3)
|
|
5096
5362
|
*/
|
|
5363
|
+
/**
|
|
5364
|
+
* @license
|
|
5365
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5366
|
+
*
|
|
5367
|
+
* useFrameCapture — still-frame capture for canvas-backed MuJoCo/R3F scenes.
|
|
5368
|
+
*/
|
|
5097
5369
|
/**
|
|
5098
5370
|
* @license
|
|
5099
5371
|
* SPDX-License-Identifier: Apache-2.0
|
|
@@ -5124,6 +5396,6 @@ function useCameraAnimation() {
|
|
|
5124
5396
|
* useCameraAnimation — composable camera animation hook.
|
|
5125
5397
|
*/
|
|
5126
5398
|
|
|
5127
|
-
export { Body, ContactListener, ContactMarkers, Debug, DragInteraction, FlexRenderer, IkGizmo, InstancedGeomRenderer, MujocoCanvas, MujocoPhysics, MujocoProvider, MujocoSimProvider, RobotActuators, RobotBodies, RobotGeoms, RobotJoints, RobotKeyframes, RobotResources, RobotSensors, RobotSites, SceneLights, TendonRenderer, TrajectoryPlayer, buildObservation, createContiguousControlGroup, createController, createControllerHook, findActuatorByName, findBodyByName, findGeomByName, findJointByName, findKeyframeByName, findSensorByName, findSiteByName, findTendonByName, getActuatedJoints, getContact, getControlMap, getName, loadScene, registerRobotResources, 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 };
|
|
5399
|
+
export { Body, ContactListener, ContactMarkers, Debug, DragInteraction, FlexRenderer, IkGizmo, InstancedGeomRenderer, MujocoCanvas, MujocoPhysics, MujocoProvider, MujocoSimProvider, RobotActuators, RobotBodies, RobotGeoms, RobotJoints, RobotKeyframes, RobotResources, RobotSensors, RobotSites, SceneLights, TendonRenderer, TrajectoryPlayer, buildObservation, captureFrame, captureFrameBlob, createContiguousControlGroup, createController, createControllerHook, findActuatorByName, findBodyByName, findGeomByName, findJointByName, findKeyframeByName, findSensorByName, findSiteByName, findTendonByName, getActuatedJoints, getContact, getControlMap, getName, loadScene, registerRobotResources, resolveControlGroup, useActuators, useAfterPhysicsStep, useBeforePhysicsStep, useBodyMeshes, useBodyState, useCameraAnimation, useContactEvents, useContacts, useCtrl, useCtrlNoise, useFrameCapture, useGamepad, useGravityCompensation, useIkController, useJointState, useKeyboardTeleop, useMujoco, useMujocoWasm, useObservation, usePolicy, useSceneLights, useSelectionHighlight, useSensor, useSensors, useSitePosition, useTrajectoryPlayer, useTrajectoryRecorder, useVideoRecorder };
|
|
5128
5400
|
//# sourceMappingURL=index.js.map
|
|
5129
5401
|
//# sourceMappingURL=index.js.map
|