mujoco-react 8.11.0 → 9.0.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 +17 -17
- package/dist/{chunk-SEWQULWO.js → chunk-33CV6HSV.js} +3 -3
- package/dist/chunk-33CV6HSV.js.map +1 -0
- package/dist/index.d.ts +13 -13
- package/dist/index.js +50 -38
- package/dist/index.js.map +1 -1
- package/dist/spark.d.ts +1 -1
- package/dist/spark.js +1 -1
- package/dist/{types-BmneHLBM.d.ts → types-izZlUweI.d.ts} +52 -13
- package/package.json +1 -1
- package/src/components/DragInteraction.tsx +1 -1
- package/src/components/IkGizmo.tsx +2 -2
- package/src/components/SceneRenderer.tsx +1 -1
- package/src/components/TrajectoryPlayer.tsx +4 -1
- package/src/components/VisualScenario.tsx +1 -1
- package/src/core/MujocoPhysics.tsx +10 -4
- package/src/core/MujocoSimProvider.tsx +15 -12
- package/src/core/createController.tsx +2 -2
- package/src/hooks/useBodyState.ts +1 -1
- package/src/hooks/useContacts.ts +1 -1
- package/src/hooks/useCtrlNoise.ts +1 -1
- package/src/hooks/useGamepad.ts +1 -1
- package/src/hooks/useGravityCompensation.ts +1 -1
- package/src/hooks/useIkController.ts +22 -13
- package/src/hooks/useJointState.ts +1 -1
- package/src/hooks/useKeyboardTeleop.ts +1 -1
- package/src/hooks/usePolicy.ts +1 -1
- package/src/hooks/useSensor.ts +1 -1
- package/src/hooks/useTrajectoryPlayer.ts +4 -4
- package/src/hooks/useTrajectoryRecorder.ts +1 -1
- package/src/index.ts +10 -0
- package/src/types.ts +60 -18
- package/dist/chunk-SEWQULWO.js.map +0 -1
package/README.md
CHANGED
|
@@ -154,7 +154,7 @@ import { ScenarioLighting, VisualScenarioEffects } from "mujoco-react";
|
|
|
154
154
|
<MujocoCanvas config={sceneConfig}>
|
|
155
155
|
<VisualScenarioEffects
|
|
156
156
|
scenario={scenario}
|
|
157
|
-
materialFilter={(object) => object.name.startsWith("prop_")}
|
|
157
|
+
materialFilter={({ object }) => object.name.startsWith("prop_")}
|
|
158
158
|
/>
|
|
159
159
|
<ScenarioLighting preset={scenario.lighting} />
|
|
160
160
|
</MujocoCanvas>;
|
|
@@ -216,7 +216,7 @@ function Scene() {
|
|
|
216
216
|
import { useBeforePhysicsStep } from "mujoco-react";
|
|
217
217
|
|
|
218
218
|
function MyController() {
|
|
219
|
-
useBeforePhysicsStep((
|
|
219
|
+
useBeforePhysicsStep(({ data }) => {
|
|
220
220
|
data.ctrl[0] = Math.sin(data.time);
|
|
221
221
|
});
|
|
222
222
|
|
|
@@ -284,7 +284,7 @@ import type { ControlGroupInfo } from "mujoco-react";
|
|
|
284
284
|
function HoldTcpPose() {
|
|
285
285
|
const armRef = useRef<ControlGroupInfo | null>(null);
|
|
286
286
|
|
|
287
|
-
useBeforePhysicsStep((model, data) => {
|
|
287
|
+
useBeforePhysicsStep(({ model, data }) => {
|
|
288
288
|
armRef.current ??= resolveControlGroup(model, { siteName: RobotSites.franka.tcp });
|
|
289
289
|
if (!armRef.current) return;
|
|
290
290
|
|
|
@@ -305,7 +305,7 @@ Build policy-ready observation vectors from common MuJoCo state without hard-cod
|
|
|
305
305
|
import { buildObservation, useBeforePhysicsStep } from "mujoco-react";
|
|
306
306
|
|
|
307
307
|
function PolicyDriver() {
|
|
308
|
-
useBeforePhysicsStep((model, data) => {
|
|
308
|
+
useBeforePhysicsStep(({ model, data }) => {
|
|
309
309
|
const obs = buildObservation(model, data, {
|
|
310
310
|
qpos: true,
|
|
311
311
|
qvel: true,
|
|
@@ -361,7 +361,7 @@ function useWebSocketControls(url: string) {
|
|
|
361
361
|
}, [url]);
|
|
362
362
|
|
|
363
363
|
// Apply incoming actuator controls each physics step.
|
|
364
|
-
useBeforePhysicsStep((model, data) => {
|
|
364
|
+
useBeforePhysicsStep(({ model, data }) => {
|
|
365
365
|
const ctrl = latestCtrlRef.current;
|
|
366
366
|
if (!ctrl) return;
|
|
367
367
|
for (let i = 0; i < Math.min(ctrl.length, model.nu); i++) {
|
|
@@ -370,7 +370,7 @@ function useWebSocketControls(url: string) {
|
|
|
370
370
|
});
|
|
371
371
|
|
|
372
372
|
// Send simulation feedback back after physics.
|
|
373
|
-
useAfterPhysicsStep((
|
|
373
|
+
useAfterPhysicsStep(({ data }) => {
|
|
374
374
|
const ws = wsRef.current;
|
|
375
375
|
if (!ws || ws.readyState !== WebSocket.OPEN) return;
|
|
376
376
|
|
|
@@ -433,8 +433,8 @@ The built-in `useIkController()` uses Damped Least-Squares. Pass `ikSolveFn` to
|
|
|
433
433
|
import { RobotSites } from "mujoco-react";
|
|
434
434
|
import type { IKSolveFn } from "mujoco-react";
|
|
435
435
|
|
|
436
|
-
const myIK: IKSolveFn = (
|
|
437
|
-
return myAnalyticalSolver(
|
|
436
|
+
const myIK: IKSolveFn = ({ position, currentQ }) => {
|
|
437
|
+
return myAnalyticalSolver(position, currentQ); // return joint angles or null
|
|
438
438
|
};
|
|
439
439
|
|
|
440
440
|
const ik = useIkController({ siteName: RobotSites.franka.tcp, ikSolveFn: myIK });
|
|
@@ -526,7 +526,7 @@ interface SceneConfig {
|
|
|
526
526
|
sceneObjects?: SceneObject[]; // Objects injected into scene XML at load time
|
|
527
527
|
homeJoints?: number[]; // Initial joint positions
|
|
528
528
|
xmlPatches?: XmlPatch[]; // Patches applied to XML files during loading
|
|
529
|
-
onReset?: (model, data) => void; // Called during reset after mj_resetData
|
|
529
|
+
onReset?: ({ model, data }) => void; // Called during reset after mj_resetData
|
|
530
530
|
}
|
|
531
531
|
```
|
|
532
532
|
|
|
@@ -636,10 +636,10 @@ Thin wrapper around R3F `<Canvas>`. Accepts all R3F Canvas props plus:
|
|
|
636
636
|
| Prop | Type | Description |
|
|
637
637
|
|------|------|-------------|
|
|
638
638
|
| `config` | `SceneConfig` | **Required.** Scene/robot configuration |
|
|
639
|
-
| `onReady` | `(api
|
|
639
|
+
| `onReady` | `({ api }) => void` | Fires when model is loaded |
|
|
640
640
|
| `onError` | `(error: Error) => void` | Fires on scene load failure |
|
|
641
|
-
| `onStep` | `(time
|
|
642
|
-
| `onSelection` | `(bodyId
|
|
641
|
+
| `onStep` | `({ time, model, data }) => void` | Called each physics step |
|
|
642
|
+
| `onSelection` | `({ bodyId, name }) => void` | Called on double-click |
|
|
643
643
|
| `gravity` | `[number, number, number]` | Override model gravity |
|
|
644
644
|
| `timestep` | `number` | Override model.opt.timestep |
|
|
645
645
|
| `substeps` | `number` | mj_step calls per frame |
|
|
@@ -664,10 +664,10 @@ Physics provider for use inside your own R3F `<Canvas>`. Same physics props as `
|
|
|
664
664
|
| Prop | Type | Description |
|
|
665
665
|
|------|------|-------------|
|
|
666
666
|
| `config` | `SceneConfig` | **Required.** Scene/robot configuration |
|
|
667
|
-
| `onReady` | `(api
|
|
667
|
+
| `onReady` | `({ api }) => void` | Fires when model is loaded |
|
|
668
668
|
| `onError` | `(error: Error) => void` | Fires on scene load failure |
|
|
669
|
-
| `onStep` | `(time
|
|
670
|
-
| `onSelection` | `(bodyId
|
|
669
|
+
| `onStep` | `({ time, model, data }) => void` | Called each physics step |
|
|
670
|
+
| `onSelection` | `({ bodyId, name }) => void` | Called on double-click |
|
|
671
671
|
| `gravity` | `[number, number, number]` | Override model gravity |
|
|
672
672
|
| `timestep` | `number` | Override model.opt.timestep |
|
|
673
673
|
| `substeps` | `number` | mj_step calls per frame |
|
|
@@ -715,7 +715,7 @@ drei PivotControls gizmo that tracks a MuJoCo site and drives IK on drag. Requir
|
|
|
715
715
|
| `controller` | `IkContextValue` | **required** | Controller from `useIkController()` |
|
|
716
716
|
| `siteName` | `string?` | controller's site | MuJoCo site to track |
|
|
717
717
|
| `scale` | `number?` | `0.18` | Gizmo handle scale |
|
|
718
|
-
| `onDrag` | `(
|
|
718
|
+
| `onDrag` | `({ position, quaternion }) => void` | -- | Custom drag handler (disables auto-IK) |
|
|
719
719
|
|
|
720
720
|
### `<DragInteraction />`
|
|
721
721
|
|
|
@@ -826,7 +826,7 @@ if (mujoco) {
|
|
|
826
826
|
Run logic **before** `mj_step` each frame. Write to `data.ctrl`, apply forces, drive automation.
|
|
827
827
|
|
|
828
828
|
```tsx
|
|
829
|
-
useBeforePhysicsStep((
|
|
829
|
+
useBeforePhysicsStep(({ data }) => {
|
|
830
830
|
data.ctrl[0] = Math.sin(data.time);
|
|
831
831
|
});
|
|
832
832
|
```
|
|
@@ -341,7 +341,7 @@ function applyScenarioMaterials(scene, scenario, snapshots, materialFilter) {
|
|
|
341
341
|
for (const material of normalizeMaterials(object.material)) {
|
|
342
342
|
const mutable = getMutableScenarioMaterial(material);
|
|
343
343
|
if (!mutable) continue;
|
|
344
|
-
if (materialFilter && !materialFilter(object, material)) continue;
|
|
344
|
+
if (materialFilter && !materialFilter({ object, material })) continue;
|
|
345
345
|
if (!snapshots.has(material)) {
|
|
346
346
|
snapshots.set(material, {
|
|
347
347
|
color: mutable.color.clone(),
|
|
@@ -396,5 +396,5 @@ function clamp01(value) {
|
|
|
396
396
|
*/
|
|
397
397
|
|
|
398
398
|
export { ScenarioLighting, SplatEnvironment, VisualScenarioEffects, createPairedSplatEnvironment, createSparkSplatViewerUrl, createSplatEnvironmentUserData, getScenarioBackground, getScenarioCameraPosition, useSplatEnvironment, useVisualScenarioEffects, withSplatEnvironment };
|
|
399
|
-
//# sourceMappingURL=chunk-
|
|
400
|
-
//# sourceMappingURL=chunk-
|
|
399
|
+
//# sourceMappingURL=chunk-33CV6HSV.js.map
|
|
400
|
+
//# sourceMappingURL=chunk-33CV6HSV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/VisualScenario.tsx"],"names":[],"mappings":"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","file":"chunk-33CV6HSV.js","sourcesContent":["/**\n * @license\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { useThree } from '@react-three/fiber';\nimport type { ThreeElements } from '@react-three/fiber';\nimport type { ReactNode } from 'react';\nimport { useEffect, useMemo } from 'react';\nimport * as THREE from 'three';\nimport type {\n PairedSplatEnvironmentConfig,\n ScenarioMaterialConfig,\n SceneConfig,\n SplatCollisionProxyConfig,\n SplatEnvironmentMetadata,\n SplatEnvironmentMetadataInput,\n SplatFormat,\n SplatRendererKind,\n SplatSceneInput,\n ScenarioLightingPreset,\n ScenarioLightingProps,\n SplatEnvironmentProps,\n VisualScenarioConfig,\n VisualScenarioEffectsProps,\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\nexport function VisualScenarioEffects(props: VisualScenarioEffectsProps) {\n useVisualScenarioEffects(props);\n return null;\n}\n\nexport function useVisualScenarioEffects({\n scenario,\n enabled = true,\n applyBackground = true,\n applyFog = true,\n applyRenderer = true,\n applyMaterials = true,\n background,\n fogNear,\n fogFar,\n materialFilter,\n}: VisualScenarioEffectsProps) {\n const { gl, scene, invalidate } = useThree();\n\n useEffect(() => {\n if (!enabled || !scenario) {\n return undefined;\n }\n\n const previousExposure = gl.toneMappingExposure;\n const previousBackground = scene.background;\n const previousFog = scene.fog;\n const materialSnapshots = new Map<\n THREE.Material,\n {\n color?: THREE.Color;\n roughness?: number;\n metalness?: number;\n }\n >();\n\n if (applyRenderer) {\n gl.toneMappingExposure = scenario.camera?.exposure ?? 1;\n }\n\n if (applyBackground) {\n scene.background = new THREE.Color(\n background ?? getScenarioBackground(scenario.lighting)\n );\n }\n\n if (applyFog) {\n scene.fog = createScenarioFog(scenario, background, fogNear, fogFar);\n }\n\n if (applyMaterials && scenario.materials) {\n applyScenarioMaterials(scene, scenario, materialSnapshots, materialFilter);\n }\n\n invalidate();\n\n return () => {\n gl.toneMappingExposure = previousExposure;\n scene.background = previousBackground;\n scene.fog = previousFog;\n\n for (const [material, snapshot] of materialSnapshots) {\n const mutable = getMutableScenarioMaterial(material);\n if (!mutable) continue;\n if (snapshot.color) mutable.color.copy(snapshot.color);\n if (typeof snapshot.roughness === 'number') {\n mutable.roughness = snapshot.roughness;\n }\n if (typeof snapshot.metalness === 'number') {\n mutable.metalness = snapshot.metalness;\n }\n mutable.needsUpdate = true;\n }\n\n invalidate();\n };\n }, [\n applyBackground,\n applyFog,\n applyMaterials,\n applyRenderer,\n background,\n enabled,\n fogFar,\n fogNear,\n gl,\n invalidate,\n materialFilter,\n scenario,\n scene,\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 scenario,\n renderer,\n src,\n format,\n collisionProxy,\n collisionProxyMetadata,\n children,\n showPlaceholder = true,\n ...groupProps\n}: SplatEnvironmentProps) {\n const metadata = useSplatEnvironment({\n environment,\n scenario,\n renderer,\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 scenario,\n renderer,\n src,\n format,\n collisionProxy,\n}: SplatEnvironmentMetadataInput): SplatEnvironmentMetadata {\n const scenarioEnvironment = useMemo(\n () =>\n environment ??\n (scenario\n ? createPairedSplatEnvironment(scenario, { renderer })\n : undefined),\n [environment, renderer, scenario]\n );\n const resolvedSrc = src ?? scenarioEnvironment?.splat.src ?? scenario?.splat?.src;\n const resolvedFormat =\n format ??\n scenarioEnvironment?.splat.format ??\n scenario?.splat?.format ??\n 'spz';\n const resolvedCollisionProxy =\n collisionProxy ??\n scenarioEnvironment?.collisionProxy ??\n scenario?.splat?.collisionProxy ??\n undefined;\n\n return useMemo(\n () => ({\n src: resolvedSrc,\n format: resolvedFormat,\n collisionProxy: resolvedCollisionProxy,\n userData: createSplatEnvironmentUserData({\n environment: scenarioEnvironment,\n src: resolvedSrc,\n format: resolvedFormat,\n collisionProxy: resolvedCollisionProxy,\n }),\n }),\n [scenarioEnvironment, resolvedSrc, resolvedFormat, resolvedCollisionProxy]\n );\n}\n\n/**\n * Convert a generic visual scenario splat block into a paired visual/physics\n * environment config. Returns undefined until both the splat asset and MJCF\n * collision proxy are present.\n */\nexport function createPairedSplatEnvironment(\n scenario: Pick<VisualScenarioConfig, 'id' | 'label' | 'environment' | 'splat'>,\n options: {\n id?: string;\n label?: string;\n description?: string;\n renderer?: SplatRendererKind;\n } = {}\n): PairedSplatEnvironmentConfig | undefined {\n const splat = scenario.splat;\n const collisionProxy = splat?.collisionProxy;\n\n if (!splat?.enabled || !splat.src || !collisionProxy?.xmlPath) {\n return undefined;\n }\n\n return {\n id: options.id ?? scenario.id ?? 'splat-environment',\n label: options.label ?? scenario.label ?? 'Gaussian splat environment',\n description:\n options.description ??\n (scenario.environment\n ? `Visual ${scenario.environment} splat paired with MJCF collision proxy.`\n : undefined),\n splat: {\n src: splat.src,\n format: splat.format ?? 'spz',\n renderer: options.renderer,\n },\n collisionProxy: {\n ...collisionProxy,\n xmlPath: collisionProxy.xmlPath,\n },\n };\n}\n\nfunction isPairedSplatEnvironment(input: SplatSceneInput): input is PairedSplatEnvironmentConfig {\n return !!input && 'collisionProxy' in input && 'splat' in input;\n}\n\nfunction sceneRelativePath(sceneConfig: SceneConfig, path: string): string {\n const src = sceneConfig.src;\n if (!src) return path;\n\n const base = src.endsWith('/') ? src : src + '/';\n if (path.startsWith(base)) return path.slice(base.length);\n return path;\n}\n\nfunction uniquePaths(paths: readonly string[]): string[] {\n const seen = new Set<string>();\n const result: string[] = [];\n for (const path of paths) {\n if (seen.has(path)) continue;\n seen.add(path);\n result.push(path);\n }\n return result;\n}\n\n/**\n * Compose a MuJoCo scene config with a paired splat collision proxy.\n *\n * This keeps the common hybrid setup declarative:\n * robot XML remains `sceneFile`, the `.spz` remains a visual-only layer, and\n * the paired MJCF collision proxy is added to `environmentFiles`.\n */\nexport function withSplatEnvironment(\n sceneConfig: SceneConfig,\n input: SplatSceneInput,\n options: { renderer?: SplatRendererKind } = {}\n): SceneConfig {\n const environment = isPairedSplatEnvironment(input)\n ? input\n : input\n ? createPairedSplatEnvironment(input, options)\n : undefined;\n const xmlPath = environment?.collisionProxy.xmlPath;\n if (!xmlPath) return sceneConfig;\n\n return {\n ...sceneConfig,\n environmentFiles: uniquePaths([\n ...(sceneConfig.environmentFiles ?? []),\n sceneRelativePath(sceneConfig, xmlPath),\n ]),\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\nfunction createScenarioFog(\n scenario: VisualScenarioConfig,\n background: THREE.ColorRepresentation | undefined,\n fogNear: number | undefined,\n fogFar: number | undefined\n) {\n if (scenario.lighting === 'low-light') {\n return new THREE.Fog(\n background ?? getScenarioBackground(scenario.lighting),\n fogNear ?? 2.5,\n fogFar ?? 9\n );\n }\n\n if (scenario.lighting === 'warehouse') {\n return new THREE.Fog(\n background ?? getScenarioBackground(scenario.lighting),\n fogNear ?? 5,\n fogFar ?? 16\n );\n }\n\n return null;\n}\n\nfunction applyScenarioMaterials(\n scene: THREE.Scene,\n scenario: VisualScenarioConfig,\n snapshots: Map<\n THREE.Material,\n {\n color?: THREE.Color;\n roughness?: number;\n metalness?: number;\n }\n >,\n materialFilter: VisualScenarioEffectsProps['materialFilter']\n) {\n const materials = scenario.materials;\n if (!materials) return;\n\n scene.traverse((object) => {\n if (!(object instanceof THREE.Mesh)) {\n return;\n }\n\n for (const material of normalizeMaterials(object.material)) {\n const mutable = getMutableScenarioMaterial(material);\n if (!mutable) continue;\n if (materialFilter && !materialFilter({ object, material })) continue;\n\n if (!snapshots.has(material)) {\n snapshots.set(material, {\n color: mutable.color.clone(),\n roughness: mutable.roughness,\n metalness: mutable.metalness,\n });\n }\n\n applyScenarioMaterial(mutable, object, scenario, materials);\n }\n });\n}\n\nfunction applyScenarioMaterial(\n material: THREE.MeshStandardMaterial | THREE.MeshPhysicalMaterial,\n object: THREE.Object3D,\n scenario: VisualScenarioConfig,\n materials: ScenarioMaterialConfig\n) {\n const seed = scenario.seed ?? 0;\n const objectKey = `${scenario.id ?? 'scenario'}:${object.name}:${material.name}:${seed}`;\n const variation = hashToUnitInterval(objectKey);\n\n if (materials.randomizeObjectColors) {\n material.color.setHSL(variation, 0.38, 0.42);\n }\n\n if (materials.randomizeTableMaterial) {\n material.roughness = clamp01(\n materials.roughness ?? 0.35 + variation * 0.45\n );\n material.metalness = clamp01(\n materials.metalness ?? variation * 0.12\n );\n }\n\n material.needsUpdate = true;\n}\n\nfunction normalizeMaterials(\n material: THREE.Material | THREE.Material[]\n): THREE.Material[] {\n return Array.isArray(material) ? material : [material];\n}\n\nfunction getMutableScenarioMaterial(\n material: THREE.Material\n): THREE.MeshStandardMaterial | THREE.MeshPhysicalMaterial | null {\n if (\n material instanceof THREE.MeshStandardMaterial ||\n material instanceof THREE.MeshPhysicalMaterial\n ) {\n return material;\n }\n\n return null;\n}\n\nfunction hashToUnitInterval(value: string) {\n let hash = 2166136261;\n for (let index = 0; index < value.length; index += 1) {\n hash ^= value.charCodeAt(index);\n hash = Math.imul(hash, 16777619);\n }\n return (hash >>> 0) / 4294967295;\n}\n\nfunction clamp01(value: number) {\n return Math.max(0, Math.min(1, value));\n}\n\nexport type SplatCollisionProxy = ReactNode | ThreeElements['group'];\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
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,
|
|
3
|
-
export {
|
|
2
|
+
import { M as MujocoContextValue, a as MujocoCanvasProps, b as MujocoSimAPI, S as SceneConfig, R as ReadyCallbackInput, c as StepCallbackInput, d as SelectionCallbackInput, e as MujocoModule, P as PhysicsStepCallback, f as MujocoModel, g as MujocoData, C as ControlGroupInfo, A as ActuatedJointInfo, h as ControlGroupSelector, O as ObservationConfig, i as ObservationResult, I as IkConfig, j as IkContextValue, B as BodyProps, k as IkGizmoProps, D as DragInteractionProps, l as SceneLightsProps, m as ScenarioLightingProps, n as SplatEnvironmentProps, V as VisualScenarioEffectsProps, o as VisualScenarioConfig, p as SplatRendererKind, q as PairedSplatEnvironmentConfig, r as SplatFormat, s as SplatCollisionProxyConfig, t as SplatCollisionPrimitive, u as ScenarioLightingPreset, v as SplatEnvironmentMetadataInput, w as SplatEnvironmentMetadata, x as SplatSceneInput, y as DebugProps, G as GeomInfo, z as ContactListenerProps, T as TrajectoryPlayerProps, E as ActuatorInfo, F as Sites, H as SitePositionResult, J as Sensors, K as SensorHandle, L as SensorInfo, N as Joints, Q as JointStateResult, U as Bodies, W as BodyStateResult, X as Actuators, Y as CtrlHandle, Z as ContactInfo, _ as KeyboardTeleopConfig, $ as PolicyConfig, a0 as PolicyVector, a1 as ObservationHandle, a2 as TrajectoryInput, a3 as TrajectoryStateChangeInput, a4 as PlaybackState, a5 as TrajectoryFrame } from './types-izZlUweI.js';
|
|
3
|
+
export { a6 as BodyInfo, a7 as ControlJointInfo, a8 as Geoms, a9 as IKSolveFn, aa as IkGizmoDragInput, ab as IkSolveInput, ac as JointInfo, ad as KeyBinding, ae as Keyframes, af as ModelOptions, ag as MujocoContact, ah as MujocoContactArray, ai as ObservationLayoutItem, aj as ObservationOutput, ak as PhysicsConfig, al as PhysicsStepInput, am as PolicyActionInput, an as PolicyInferenceInput, ao as PolicyObservationInput, ap as RayHit, aq as Register, ar as RegisteredRobotMap, as as ResetCallbackInput, at as ResourceSelector, au as RobotActuators, av as RobotBodies, aw as RobotGeoms, ax as RobotJoints, ay as RobotKeyframes, az as RobotResource, aA as RobotResources, aB as RobotSensors, aC as RobotSites, aD as Robots, aE as ScenarioCameraConfig, aF as ScenarioMaterialConfig, aG as SceneMarker, aH as SceneObject, aI as SensorResult, aJ as SiteInfo, aK as SplatAssetConfig, aL as SplatScenarioConfig, aM as StateSnapshot, aN as TrajectoryData, aO as TrajectoryFrameCallbackInput, aP as VisualScenarioMaterialFilterInput, aQ as XmlPatch, aR as getContact, aS as registerRobotResources } from './types-izZlUweI.js';
|
|
4
4
|
import * as React$1 from 'react';
|
|
5
5
|
import React__default from 'react';
|
|
6
6
|
import { ThreeElements } from '@react-three/fiber';
|
|
@@ -56,13 +56,13 @@ interface MujocoPhysicsProps {
|
|
|
56
56
|
/** Scene/robot configuration. */
|
|
57
57
|
config: SceneConfig;
|
|
58
58
|
/** Fires when model is loaded and API is ready. */
|
|
59
|
-
onReady?: (
|
|
59
|
+
onReady?: (input: ReadyCallbackInput) => void;
|
|
60
60
|
/** Fires on scene load failure. */
|
|
61
61
|
onError?: (error: Error) => void;
|
|
62
62
|
/** Called each physics step. */
|
|
63
|
-
onStep?: (
|
|
63
|
+
onStep?: (input: StepCallbackInput) => void;
|
|
64
64
|
/** Called on body double-click selection. */
|
|
65
|
-
onSelection?: (
|
|
65
|
+
onSelection?: (input: SelectionCallbackInput) => void;
|
|
66
66
|
/** Override model gravity. */
|
|
67
67
|
gravity?: [number, number, number];
|
|
68
68
|
/** Override model.opt.timestep. */
|
|
@@ -133,10 +133,10 @@ interface MujocoSimProviderProps {
|
|
|
133
133
|
mujoco: MujocoModule;
|
|
134
134
|
config: SceneConfig;
|
|
135
135
|
apiRef?: React.ForwardedRef<MujocoSimAPI>;
|
|
136
|
-
onReady?: (
|
|
136
|
+
onReady?: (input: ReadyCallbackInput) => void;
|
|
137
137
|
onError?: (error: Error) => void;
|
|
138
|
-
onStep?: (
|
|
139
|
-
onSelection?: (
|
|
138
|
+
onStep?: (input: StepCallbackInput) => void;
|
|
139
|
+
onSelection?: (input: SelectionCallbackInput) => void;
|
|
140
140
|
gravity?: [number, number, number];
|
|
141
141
|
timestep?: number;
|
|
142
142
|
substeps?: number;
|
|
@@ -243,7 +243,7 @@ type ControllerComponent<TConfig> = React.FC<{
|
|
|
243
243
|
* const MyController = createController<{ speed: number }>(
|
|
244
244
|
* { name: 'my-controller', defaultConfig: { speed: 1.0 } },
|
|
245
245
|
* function MyControllerImpl({ config }) {
|
|
246
|
-
* useBeforePhysicsStep((
|
|
246
|
+
* useBeforePhysicsStep(({ data }) => {
|
|
247
247
|
* data.ctrl[0] = config.speed;
|
|
248
248
|
* });
|
|
249
249
|
* return null;
|
|
@@ -270,7 +270,7 @@ declare function createController<TConfig>(options: ControllerOptions<TConfig>,
|
|
|
270
270
|
* { name: 'useMyController', defaultConfig: { gain: 1.0 } },
|
|
271
271
|
* function useMyControllerImpl(config) {
|
|
272
272
|
* // config is MyConfig | null — hooks must be called unconditionally
|
|
273
|
-
* useBeforePhysicsStep((
|
|
273
|
+
* useBeforePhysicsStep(({ data }) => {
|
|
274
274
|
* if (!config) return;
|
|
275
275
|
* data.ctrl[0] = config.gain * Math.sin(data.time);
|
|
276
276
|
* });
|
|
@@ -312,7 +312,7 @@ declare function Body({ name, type, size, position, rgba, mass, freejoint, frict
|
|
|
312
312
|
* - `controller` — IkContextValue from `useIkController()`.
|
|
313
313
|
* - `siteName` — MuJoCo site to track. Defaults to the controller's configured site.
|
|
314
314
|
* - `scale` — Gizmo handle scale. Default: 0.18.
|
|
315
|
-
* - `onDrag` — Custom drag callback `(
|
|
315
|
+
* - `onDrag` — Custom drag callback `({ position, quaternion }) => void`.
|
|
316
316
|
* When omitted, dragging enables IK and writes to the IK target.
|
|
317
317
|
* When provided, the consumer handles what happens during drag.
|
|
318
318
|
*/
|
|
@@ -655,7 +655,7 @@ interface TrajectoryPlayerOptions {
|
|
|
655
655
|
loop?: boolean;
|
|
656
656
|
mode?: 'kinematic' | 'physics';
|
|
657
657
|
onComplete?: () => void;
|
|
658
|
-
onStateChange?: (
|
|
658
|
+
onStateChange?: (input: TrajectoryStateChangeInput) => void;
|
|
659
659
|
}
|
|
660
660
|
/**
|
|
661
661
|
* Play back a trajectory, overriding simulation state.
|
|
@@ -896,4 +896,4 @@ interface CameraAnimationAPI {
|
|
|
896
896
|
*/
|
|
897
897
|
declare function useCameraAnimation(): CameraAnimationAPI;
|
|
898
898
|
|
|
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 };
|
|
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, ReadyCallbackInput, ScenarioLighting, ScenarioLightingPreset, ScenarioLightingProps, SceneConfig, SceneLights, SceneLightsProps, SelectionCallbackInput, SensorHandle, SensorInfo, Sensors, SitePositionResult, Sites, SplatCollisionPrimitive, SplatCollisionProxyConfig, SplatEnvironment, SplatEnvironmentMetadata, SplatEnvironmentMetadataInput, SplatEnvironmentProps, SplatFormat, SplatRendererKind, SplatSceneInput, StepCallbackInput, TendonRenderer, TrajectoryFrame, TrajectoryInput, TrajectoryPlayer, TrajectoryPlayerProps, TrajectoryStateChangeInput, 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, VisualScenarioEffects, createPairedSplatEnvironment, createSparkSplatViewerUrl, createSplatEnvironmentUserData, getScenarioBackground, getScenarioCameraPosition, useSplatEnvironment, useVisualScenarioEffects, withSplatEnvironment } from './chunk-
|
|
1
|
+
export { ScenarioLighting, SplatEnvironment, VisualScenarioEffects, createPairedSplatEnvironment, createSparkSplatViewerUrl, createSplatEnvironmentUserData, getScenarioBackground, getScenarioCameraPosition, useSplatEnvironment, useVisualScenarioEffects, withSplatEnvironment } from './chunk-33CV6HSV.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';
|
|
@@ -1285,7 +1285,7 @@ function SceneRenderer(props) {
|
|
|
1285
1285
|
const model = mjModelRef.current;
|
|
1286
1286
|
if (model && bodyID < model.nbody && onSelectionRef.current) {
|
|
1287
1287
|
const name = getName(model, model.name_bodyadr[bodyID]);
|
|
1288
|
-
onSelectionRef.current(bodyID, name);
|
|
1288
|
+
onSelectionRef.current({ bodyId: bodyID, name });
|
|
1289
1289
|
}
|
|
1290
1290
|
}
|
|
1291
1291
|
}
|
|
@@ -1420,7 +1420,7 @@ function useBeforePhysicsStep(callback) {
|
|
|
1420
1420
|
const callbackRef = useRef(callback);
|
|
1421
1421
|
callbackRef.current = callback;
|
|
1422
1422
|
useEffect(() => {
|
|
1423
|
-
const wrapped = (
|
|
1423
|
+
const wrapped = (input) => callbackRef.current(input);
|
|
1424
1424
|
beforeStepCallbacks.current.add(wrapped);
|
|
1425
1425
|
return () => {
|
|
1426
1426
|
beforeStepCallbacks.current.delete(wrapped);
|
|
@@ -1432,7 +1432,7 @@ function useAfterPhysicsStep(callback) {
|
|
|
1432
1432
|
const callbackRef = useRef(callback);
|
|
1433
1433
|
callbackRef.current = callback;
|
|
1434
1434
|
useEffect(() => {
|
|
1435
|
-
const wrapped = (
|
|
1435
|
+
const wrapped = (input) => callbackRef.current(input);
|
|
1436
1436
|
afterStepCallbacks.current.add(wrapped);
|
|
1437
1437
|
return () => {
|
|
1438
1438
|
afterStepCallbacks.current.delete(wrapped);
|
|
@@ -1576,7 +1576,7 @@ function MujocoSimProvider({
|
|
|
1576
1576
|
useEffect(() => {
|
|
1577
1577
|
if (status === "ready") {
|
|
1578
1578
|
const api2 = apiRef.current;
|
|
1579
|
-
if (onReady) onReady(api2);
|
|
1579
|
+
if (onReady) onReady({ api: api2 });
|
|
1580
1580
|
if (externalApiRef) {
|
|
1581
1581
|
if (typeof externalApiRef === "function") {
|
|
1582
1582
|
externalApiRef(api2);
|
|
@@ -1596,7 +1596,7 @@ function MujocoSimProvider({
|
|
|
1596
1596
|
data.qfrc_applied[i] = 0;
|
|
1597
1597
|
}
|
|
1598
1598
|
for (const cb of beforeStepCallbacks.current) {
|
|
1599
|
-
cb(model, data);
|
|
1599
|
+
cb({ model, data });
|
|
1600
1600
|
}
|
|
1601
1601
|
const numSubsteps = substepsRef.current;
|
|
1602
1602
|
if (!interpolateRef.current) {
|
|
@@ -1647,14 +1647,14 @@ function MujocoSimProvider({
|
|
|
1647
1647
|
interpolationStateRef.current.alpha = Math.min(Math.max(physicsAccumulatorRef.current / stepDt, 0), 1);
|
|
1648
1648
|
interpolationStateRef.current.valid = true;
|
|
1649
1649
|
if (!stepped) {
|
|
1650
|
-
onStepRef.current?.(data.time);
|
|
1650
|
+
onStepRef.current?.({ time: data.time, model, data });
|
|
1651
1651
|
return;
|
|
1652
1652
|
}
|
|
1653
1653
|
}
|
|
1654
1654
|
for (const cb of afterStepCallbacks.current) {
|
|
1655
|
-
cb(model, data);
|
|
1655
|
+
cb({ model, data });
|
|
1656
1656
|
}
|
|
1657
|
-
onStepRef.current?.(data.time);
|
|
1657
|
+
onStepRef.current?.({ time: data.time, model, data });
|
|
1658
1658
|
}, -1);
|
|
1659
1659
|
function ensureInterpolationBuffers(model) {
|
|
1660
1660
|
const state = interpolationStateRef.current;
|
|
@@ -1685,7 +1685,7 @@ function MujocoSimProvider({
|
|
|
1685
1685
|
}
|
|
1686
1686
|
}
|
|
1687
1687
|
}
|
|
1688
|
-
configRef.current.onReset?.(model, data);
|
|
1688
|
+
configRef.current.onReset?.({ model, data });
|
|
1689
1689
|
mujoco.mj_forward(model, data);
|
|
1690
1690
|
for (const cb of resetCallbacks.current) {
|
|
1691
1691
|
cb();
|
|
@@ -2841,9 +2841,9 @@ var useIkController = createControllerHook(
|
|
|
2841
2841
|
}
|
|
2842
2842
|
}, [config?.siteName, config?.numJoints, config?.joints, config?.actuators, status, mjModelRef, mjDataRef, config]);
|
|
2843
2843
|
const ikSolveFn = useCallback(
|
|
2844
|
-
(
|
|
2844
|
+
({ position, quaternion, currentQ, context }) => {
|
|
2845
2845
|
if (!config) return null;
|
|
2846
|
-
if (config.ikSolveFn) return config.ikSolveFn(
|
|
2846
|
+
if (config.ikSolveFn) return config.ikSolveFn({ position, quaternion, currentQ, context });
|
|
2847
2847
|
const model = mjModelRef.current;
|
|
2848
2848
|
const data = mjDataRef.current;
|
|
2849
2849
|
const controlGroup = controlGroupRef.current;
|
|
@@ -2853,8 +2853,8 @@ var useIkController = createControllerHook(
|
|
|
2853
2853
|
data,
|
|
2854
2854
|
siteIdRef.current,
|
|
2855
2855
|
controlGroup.qposAdr,
|
|
2856
|
-
|
|
2857
|
-
|
|
2856
|
+
position,
|
|
2857
|
+
quaternion,
|
|
2858
2858
|
currentQ,
|
|
2859
2859
|
{ damping: config.damping, maxIterations: config.maxIterations }
|
|
2860
2860
|
);
|
|
@@ -2883,7 +2883,7 @@ var useIkController = createControllerHook(
|
|
|
2883
2883
|
target.quaternion.slerpQuaternions(ga.startRot, ga.endRot, ease);
|
|
2884
2884
|
if (t >= 1) ga.active = false;
|
|
2885
2885
|
});
|
|
2886
|
-
useBeforePhysicsStep((model, data) => {
|
|
2886
|
+
useBeforePhysicsStep(({ model, data }) => {
|
|
2887
2887
|
if (!config || !ikEnabledRef.current) {
|
|
2888
2888
|
ikCalculatingRef.current = false;
|
|
2889
2889
|
return;
|
|
@@ -2894,12 +2894,21 @@ var useIkController = createControllerHook(
|
|
|
2894
2894
|
const controlGroup = controlGroupRef.current;
|
|
2895
2895
|
if (!controlGroup) return;
|
|
2896
2896
|
const currentQ = Array.from(controlGroup.readQpos(data));
|
|
2897
|
-
const solution = config.ikSolveFn ? config.ikSolveFn(
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2897
|
+
const solution = config.ikSolveFn ? config.ikSolveFn({
|
|
2898
|
+
position: target.position,
|
|
2899
|
+
quaternion: target.quaternion,
|
|
2900
|
+
currentQ,
|
|
2901
|
+
context: {
|
|
2902
|
+
model,
|
|
2903
|
+
data,
|
|
2904
|
+
siteId: siteIdRef.current,
|
|
2905
|
+
controlGroup
|
|
2906
|
+
}
|
|
2907
|
+
}) : ikSolveFnRef.current({
|
|
2908
|
+
position: target.position,
|
|
2909
|
+
quaternion: target.quaternion,
|
|
2910
|
+
currentQ
|
|
2911
|
+
});
|
|
2903
2912
|
if (solution) {
|
|
2904
2913
|
controlGroup.writeCtrl(data, solution);
|
|
2905
2914
|
}
|
|
@@ -2938,8 +2947,8 @@ var useIkController = createControllerHook(
|
|
|
2938
2947
|
if (data && target) syncGizmoToSite(data, siteIdRef.current, target);
|
|
2939
2948
|
}, [mjDataRef]);
|
|
2940
2949
|
const solveIK = useCallback(
|
|
2941
|
-
(
|
|
2942
|
-
return ikSolveFnRef.current(
|
|
2950
|
+
(input) => {
|
|
2951
|
+
return ikSolveFnRef.current(input);
|
|
2943
2952
|
},
|
|
2944
2953
|
[]
|
|
2945
2954
|
);
|
|
@@ -3153,7 +3162,7 @@ function IkGizmo({ controller, siteName, scale = 0.18, onDrag }) {
|
|
|
3153
3162
|
onDrag: (_l, _dl, world) => {
|
|
3154
3163
|
world.decompose(_pos, _quat, _scale);
|
|
3155
3164
|
if (onDrag) {
|
|
3156
|
-
onDrag(_pos.clone(), _quat.clone());
|
|
3165
|
+
onDrag({ position: _pos.clone(), quaternion: _quat.clone() });
|
|
3157
3166
|
} else {
|
|
3158
3167
|
const target = ikTargetRef.current;
|
|
3159
3168
|
if (target) {
|
|
@@ -3327,7 +3336,7 @@ function DragInteraction({
|
|
|
3327
3336
|
window.removeEventListener("pointercancel", onPointerUp);
|
|
3328
3337
|
};
|
|
3329
3338
|
}, [gl, camera, scene, controls, mjDataRef]);
|
|
3330
|
-
useBeforePhysicsStep((model, data) => {
|
|
3339
|
+
useBeforePhysicsStep(({ model, data }) => {
|
|
3331
3340
|
if (!draggingRef.current || bodyIdRef.current <= 0) return;
|
|
3332
3341
|
const bid = bodyIdRef.current;
|
|
3333
3342
|
const mujoco = mujocoRef.current;
|
|
@@ -4118,7 +4127,7 @@ function useContacts(bodyName, callback) {
|
|
|
4118
4127
|
bodyIdRef.current = findBodyByName(model, bodyName);
|
|
4119
4128
|
bodyResolvedRef.current = true;
|
|
4120
4129
|
}, [bodyName, status, mjModelRef]);
|
|
4121
|
-
useAfterPhysicsStep((model, data) => {
|
|
4130
|
+
useAfterPhysicsStep(({ model, data }) => {
|
|
4122
4131
|
if (bodyName && !bodyResolvedRef.current) {
|
|
4123
4132
|
bodyIdRef.current = findBodyByName(model, bodyName);
|
|
4124
4133
|
bodyResolvedRef.current = true;
|
|
@@ -4224,7 +4233,7 @@ function useTrajectoryPlayer(trajectory, options = {}) {
|
|
|
4224
4233
|
const setState = useCallback((next) => {
|
|
4225
4234
|
if (stateRef.current === next) return;
|
|
4226
4235
|
stateRef.current = next;
|
|
4227
|
-
optionsRef.current.onStateChange?.(next);
|
|
4236
|
+
optionsRef.current.onStateChange?.({ state: next });
|
|
4228
4237
|
}, []);
|
|
4229
4238
|
const play = useCallback(() => {
|
|
4230
4239
|
const traj = trajectoryRef.current;
|
|
@@ -4306,7 +4315,7 @@ function useTrajectoryPlayer(trajectory, options = {}) {
|
|
|
4306
4315
|
}
|
|
4307
4316
|
}
|
|
4308
4317
|
});
|
|
4309
|
-
useBeforePhysicsStep((model, data) => {
|
|
4318
|
+
useBeforePhysicsStep(({ model, data }) => {
|
|
4310
4319
|
if (stateRef.current !== "playing") return;
|
|
4311
4320
|
if ((optionsRef.current.mode ?? "kinematic") !== "physics") return;
|
|
4312
4321
|
const traj = trajectoryRef.current;
|
|
@@ -4391,7 +4400,10 @@ function TrajectoryPlayer({
|
|
|
4391
4400
|
const currentFrame = player.frame;
|
|
4392
4401
|
if (currentFrame !== lastReportedFrameRef.current && player.playing) {
|
|
4393
4402
|
lastReportedFrameRef.current = currentFrame;
|
|
4394
|
-
onFrameRef.current(
|
|
4403
|
+
onFrameRef.current({
|
|
4404
|
+
frameIndex: currentFrame,
|
|
4405
|
+
frame: trajectory[currentFrame]
|
|
4406
|
+
});
|
|
4395
4407
|
}
|
|
4396
4408
|
});
|
|
4397
4409
|
return null;
|
|
@@ -4465,7 +4477,7 @@ function useSitePosition(siteName) {
|
|
|
4465
4477
|
|
|
4466
4478
|
// src/hooks/useGravityCompensation.ts
|
|
4467
4479
|
function useGravityCompensation(enabled = true) {
|
|
4468
|
-
useBeforePhysicsStep((model, data) => {
|
|
4480
|
+
useBeforePhysicsStep(({ model, data }) => {
|
|
4469
4481
|
if (!enabled) return;
|
|
4470
4482
|
for (let i = 0; i < model.nv; i++) {
|
|
4471
4483
|
data.qfrc_applied[i] += data.qfrc_bias[i];
|
|
@@ -4492,7 +4504,7 @@ function useSensor(name) {
|
|
|
4492
4504
|
}
|
|
4493
4505
|
sensorIdRef.current = -1;
|
|
4494
4506
|
}, [name, status, mjModelRef]);
|
|
4495
|
-
useAfterPhysicsStep((
|
|
4507
|
+
useAfterPhysicsStep(({ data }) => {
|
|
4496
4508
|
if (sensorIdRef.current < 0) return;
|
|
4497
4509
|
const adr = sensorAdrRef.current;
|
|
4498
4510
|
const dim = sensorDimRef.current;
|
|
@@ -4589,7 +4601,7 @@ function useJointState(name) {
|
|
|
4589
4601
|
}
|
|
4590
4602
|
jointIdRef.current = -1;
|
|
4591
4603
|
}, [name, status, mjModelRef]);
|
|
4592
|
-
useAfterPhysicsStep((
|
|
4604
|
+
useAfterPhysicsStep(({ data }) => {
|
|
4593
4605
|
if (jointIdRef.current < 0) return;
|
|
4594
4606
|
const qa = qposAdrRef.current;
|
|
4595
4607
|
const da = dofAdrRef.current;
|
|
@@ -4619,7 +4631,7 @@ function useBodyState(name) {
|
|
|
4619
4631
|
if (!model || status !== "ready") return;
|
|
4620
4632
|
bodyIdRef.current = findBodyByName(model, name);
|
|
4621
4633
|
}, [name, status, mjModelRef]);
|
|
4622
|
-
useAfterPhysicsStep((
|
|
4634
|
+
useAfterPhysicsStep(({ data }) => {
|
|
4623
4635
|
const bid = bodyIdRef.current;
|
|
4624
4636
|
if (bid < 0) return;
|
|
4625
4637
|
const i3 = bid * 3;
|
|
@@ -4715,7 +4727,7 @@ function useKeyboardTeleop(config) {
|
|
|
4715
4727
|
window.removeEventListener("keyup", onKeyUp);
|
|
4716
4728
|
};
|
|
4717
4729
|
}, []);
|
|
4718
|
-
useBeforePhysicsStep((
|
|
4730
|
+
useBeforePhysicsStep(({ data }) => {
|
|
4719
4731
|
if (!enabledRef.current) return;
|
|
4720
4732
|
const bindings = bindingsRef.current;
|
|
4721
4733
|
const cache = actuatorCacheRef.current;
|
|
@@ -4743,7 +4755,7 @@ function usePolicy(config) {
|
|
|
4743
4755
|
const configRef = useRef(config);
|
|
4744
4756
|
configRef.current = config;
|
|
4745
4757
|
isRunningRef.current = config.enabled ?? isRunningRef.current;
|
|
4746
|
-
useBeforePhysicsStep((model, data) => {
|
|
4758
|
+
useBeforePhysicsStep(({ model, data }) => {
|
|
4747
4759
|
if (!isRunningRef.current) return;
|
|
4748
4760
|
const cfg = configRef.current;
|
|
4749
4761
|
model.opt?.timestep ?? 2e-3;
|
|
@@ -4800,7 +4812,7 @@ function useTrajectoryRecorder(options = {}) {
|
|
|
4800
4812
|
const recordingRef = useRef(false);
|
|
4801
4813
|
const framesRef = useRef([]);
|
|
4802
4814
|
const fields = options.fields ?? ["qpos"];
|
|
4803
|
-
useAfterPhysicsStep((
|
|
4815
|
+
useAfterPhysicsStep(({ data }) => {
|
|
4804
4816
|
if (!recordingRef.current) return;
|
|
4805
4817
|
const frame = {
|
|
4806
4818
|
time: data.time,
|
|
@@ -4889,7 +4901,7 @@ function useGamepad(config) {
|
|
|
4889
4901
|
buttonCacheRef.current.set(Number(idx), findActuatorByName(model, name));
|
|
4890
4902
|
}
|
|
4891
4903
|
}, [config.axes, config.buttons, status, mjModelRef]);
|
|
4892
|
-
useBeforePhysicsStep((
|
|
4904
|
+
useBeforePhysicsStep(({ data }) => {
|
|
4893
4905
|
const cfg = configRef.current;
|
|
4894
4906
|
if (cfg.enabled === false) return;
|
|
4895
4907
|
const gamepads = navigator.getGamepads?.();
|
|
@@ -5080,7 +5092,7 @@ function useCtrlNoise(config = {}) {
|
|
|
5080
5092
|
const configRef = useRef(config);
|
|
5081
5093
|
configRef.current = config;
|
|
5082
5094
|
const noiseRef = useRef(null);
|
|
5083
|
-
useBeforePhysicsStep((
|
|
5095
|
+
useBeforePhysicsStep(({ data }) => {
|
|
5084
5096
|
const cfg = configRef.current;
|
|
5085
5097
|
if (cfg.enabled === false) return;
|
|
5086
5098
|
const rate = cfg.rate ?? 0.01;
|