mujoco-react 6.0.1 → 7.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 +84 -46
- package/dist/index.d.ts +88 -57
- package/dist/index.js +372 -243
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/Body.tsx +102 -0
- package/src/components/ContactMarkers.tsx +2 -2
- package/src/components/Debug.tsx +2 -2
- package/src/components/DragInteraction.tsx +2 -2
- package/src/components/FlexRenderer.tsx +2 -2
- package/src/components/IkGizmo.tsx +7 -11
- package/src/components/SceneRenderer.tsx +9 -6
- package/src/components/TendonRenderer.tsx +2 -2
- package/src/core/MujocoSimProvider.tsx +87 -6
- package/src/core/createController.tsx +54 -2
- package/src/hooks/useActuators.ts +2 -2
- package/src/hooks/useBodyState.ts +2 -2
- package/src/hooks/useContacts.ts +2 -2
- package/src/hooks/useCtrl.ts +2 -2
- package/src/hooks/useCtrlNoise.ts +2 -2
- package/src/hooks/useGamepad.ts +2 -2
- package/src/hooks/useIkController.ts +242 -0
- package/src/hooks/useJointState.ts +2 -2
- package/src/hooks/useKeyboardTeleop.ts +2 -2
- package/src/hooks/usePolicy.ts +2 -2
- package/src/hooks/useSceneLights.ts +2 -2
- package/src/hooks/useSensor.ts +3 -3
- package/src/hooks/useSitePosition.ts +2 -2
- package/src/hooks/useTrajectoryPlayer.ts +2 -2
- package/src/hooks/useTrajectoryRecorder.ts +2 -2
- package/src/index.ts +5 -4
- package/src/types.ts +30 -0
- package/src/components/IkController.tsx +0 -262
- package/src/core/IkContext.tsx +0 -40
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import loadMujoco from 'mujoco-js';
|
|
2
|
-
import { createContext, forwardRef, useEffect, useContext, useState, useRef, useCallback, useMemo } from 'react';
|
|
2
|
+
import { createContext, forwardRef, useEffect, useContext, useState, useRef, useCallback, useMemo, useLayoutEffect } from 'react';
|
|
3
3
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
4
4
|
import { Canvas, useThree, useFrame } from '@react-three/fiber';
|
|
5
5
|
import * as THREE11 from 'three';
|
|
@@ -508,7 +508,7 @@ function scanDependencies(xmlString, currentFile, parser, downloaded, queue) {
|
|
|
508
508
|
});
|
|
509
509
|
}
|
|
510
510
|
function SceneRenderer(props) {
|
|
511
|
-
const { mjModelRef, mjDataRef, mujocoRef, onSelectionRef, status } =
|
|
511
|
+
const { mjModelRef, mjDataRef, mujocoRef, onSelectionRef, hiddenBodiesRef, status } = useMujocoContext();
|
|
512
512
|
const groupRef = useRef(null);
|
|
513
513
|
const bodyRefs = useRef([]);
|
|
514
514
|
const prevModelRef = useRef(null);
|
|
@@ -530,10 +530,13 @@ function SceneRenderer(props) {
|
|
|
530
530
|
for (let i = 0; i < model.nbody; i++) {
|
|
531
531
|
const bodyGroup = new THREE11.Group();
|
|
532
532
|
bodyGroup.userData.bodyID = i;
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
if (
|
|
533
|
+
const bodyName = getName(model, model.name_bodyadr[i]);
|
|
534
|
+
if (!hiddenBodiesRef.current.has(bodyName)) {
|
|
535
|
+
for (let g = 0; g < model.ngeom; g++) {
|
|
536
|
+
if (model.geom_bodyid[g] === i) {
|
|
537
|
+
const mesh = geomBuilder.create(model, g);
|
|
538
|
+
if (mesh) bodyGroup.add(mesh);
|
|
539
|
+
}
|
|
537
540
|
}
|
|
538
541
|
}
|
|
539
542
|
group.add(bodyGroup);
|
|
@@ -647,14 +650,51 @@ var _rayGeomId = new Int32Array(1);
|
|
|
647
650
|
var _projRaycaster = new THREE11.Raycaster();
|
|
648
651
|
var _projNdc = new THREE11.Vector2();
|
|
649
652
|
var MujocoSimContext = createContext(null);
|
|
650
|
-
function
|
|
653
|
+
function useMujocoContext() {
|
|
651
654
|
const ctx = useContext(MujocoSimContext);
|
|
652
655
|
if (!ctx)
|
|
653
656
|
throw new Error("useMujoco must be used inside <MujocoSimProvider>");
|
|
654
657
|
return ctx;
|
|
655
658
|
}
|
|
659
|
+
function useMujoco() {
|
|
660
|
+
const ctx = useMujocoContext();
|
|
661
|
+
if (ctx.status === "ready") {
|
|
662
|
+
return {
|
|
663
|
+
status: "ready",
|
|
664
|
+
isPending: false,
|
|
665
|
+
isReady: true,
|
|
666
|
+
isError: false,
|
|
667
|
+
error: null,
|
|
668
|
+
api: ctx.api,
|
|
669
|
+
mjModelRef: ctx.mjModelRef,
|
|
670
|
+
mjDataRef: ctx.mjDataRef
|
|
671
|
+
};
|
|
672
|
+
}
|
|
673
|
+
if (ctx.status === "error") {
|
|
674
|
+
return {
|
|
675
|
+
status: "error",
|
|
676
|
+
isPending: false,
|
|
677
|
+
isReady: false,
|
|
678
|
+
isError: true,
|
|
679
|
+
error: ctx.errorRef.current ?? "Unknown error",
|
|
680
|
+
api: null,
|
|
681
|
+
mjModelRef: null,
|
|
682
|
+
mjDataRef: null
|
|
683
|
+
};
|
|
684
|
+
}
|
|
685
|
+
return {
|
|
686
|
+
status: "loading",
|
|
687
|
+
isPending: true,
|
|
688
|
+
isReady: false,
|
|
689
|
+
isError: false,
|
|
690
|
+
error: null,
|
|
691
|
+
api: null,
|
|
692
|
+
mjModelRef: null,
|
|
693
|
+
mjDataRef: null
|
|
694
|
+
};
|
|
695
|
+
}
|
|
656
696
|
function useBeforePhysicsStep(callback) {
|
|
657
|
-
const { beforeStepCallbacks } =
|
|
697
|
+
const { beforeStepCallbacks } = useMujocoContext();
|
|
658
698
|
const callbackRef = useRef(callback);
|
|
659
699
|
callbackRef.current = callback;
|
|
660
700
|
useEffect(() => {
|
|
@@ -666,7 +706,7 @@ function useBeforePhysicsStep(callback) {
|
|
|
666
706
|
}, [beforeStepCallbacks]);
|
|
667
707
|
}
|
|
668
708
|
function useAfterPhysicsStep(callback) {
|
|
669
|
-
const { afterStepCallbacks } =
|
|
709
|
+
const { afterStepCallbacks } = useMujocoContext();
|
|
670
710
|
const callbackRef = useRef(callback);
|
|
671
711
|
callbackRef.current = callback;
|
|
672
712
|
useEffect(() => {
|
|
@@ -710,6 +750,10 @@ function MujocoSimProvider({
|
|
|
710
750
|
const beforeStepCallbacks = useRef(/* @__PURE__ */ new Set());
|
|
711
751
|
const afterStepCallbacks = useRef(/* @__PURE__ */ new Set());
|
|
712
752
|
const resetCallbacks = useRef(/* @__PURE__ */ new Set());
|
|
753
|
+
const errorRef = useRef(null);
|
|
754
|
+
const bodyRegistryRef = useRef(/* @__PURE__ */ new Map());
|
|
755
|
+
const hiddenBodiesRef = useRef(/* @__PURE__ */ new Set());
|
|
756
|
+
const bodyReloadTimerRef = useRef(null);
|
|
713
757
|
configRef.current = config;
|
|
714
758
|
useEffect(() => {
|
|
715
759
|
pausedRef.current = paused ?? false;
|
|
@@ -734,11 +778,22 @@ function MujocoSimProvider({
|
|
|
734
778
|
if (!model?.opt) return;
|
|
735
779
|
model.opt.timestep = timestep;
|
|
736
780
|
}, [timestep]);
|
|
781
|
+
function buildMergedConfig(baseConfig) {
|
|
782
|
+
if (bodyRegistryRef.current.size === 0) return baseConfig;
|
|
783
|
+
const registeredNames = new Set(bodyRegistryRef.current.keys());
|
|
784
|
+
const baseObjects = (baseConfig.sceneObjects ?? []).filter((o) => !registeredNames.has(o.name));
|
|
785
|
+
const registeredBodies = Array.from(bodyRegistryRef.current.values()).map((e) => e.definition);
|
|
786
|
+
hiddenBodiesRef.current.clear();
|
|
787
|
+
for (const [name, entry] of bodyRegistryRef.current) {
|
|
788
|
+
if (entry.hasCustomChildren) hiddenBodiesRef.current.add(name);
|
|
789
|
+
}
|
|
790
|
+
return { ...baseConfig, sceneObjects: [...baseObjects, ...registeredBodies] };
|
|
791
|
+
}
|
|
737
792
|
useEffect(() => {
|
|
738
793
|
let disposed = false;
|
|
739
794
|
(async () => {
|
|
740
795
|
try {
|
|
741
|
-
const result = await loadScene(mujoco, config);
|
|
796
|
+
const result = await loadScene(mujoco, buildMergedConfig(config));
|
|
742
797
|
if (disposed) {
|
|
743
798
|
result.mjModel.delete();
|
|
744
799
|
result.mjData.delete();
|
|
@@ -757,8 +812,10 @@ function MujocoSimProvider({
|
|
|
757
812
|
setStatus("ready");
|
|
758
813
|
} catch (e) {
|
|
759
814
|
if (!disposed) {
|
|
815
|
+
const err = e instanceof Error ? e : new Error(String(e));
|
|
816
|
+
errorRef.current = err.message;
|
|
760
817
|
setStatus("error");
|
|
761
|
-
onError?.(
|
|
818
|
+
onError?.(err);
|
|
762
819
|
}
|
|
763
820
|
}
|
|
764
821
|
})();
|
|
@@ -1225,10 +1282,18 @@ function MujocoSimProvider({
|
|
|
1225
1282
|
setStatus("ready");
|
|
1226
1283
|
} catch (e) {
|
|
1227
1284
|
if (gen !== loadGenRef.current) return;
|
|
1285
|
+
errorRef.current = e instanceof Error ? e.message : String(e);
|
|
1228
1286
|
setStatus("error");
|
|
1229
1287
|
throw e;
|
|
1230
1288
|
}
|
|
1231
1289
|
}, [mujoco]);
|
|
1290
|
+
const requestBodyReload = useCallback(() => {
|
|
1291
|
+
if (bodyReloadTimerRef.current) clearTimeout(bodyReloadTimerRef.current);
|
|
1292
|
+
bodyReloadTimerRef.current = setTimeout(() => {
|
|
1293
|
+
bodyReloadTimerRef.current = null;
|
|
1294
|
+
loadSceneApi(buildMergedConfig(configRef.current));
|
|
1295
|
+
}, 0);
|
|
1296
|
+
}, [loadSceneApi]);
|
|
1232
1297
|
const getCanvasSnapshot = useCallback(
|
|
1233
1298
|
(width, height, mimeType = "image/jpeg") => {
|
|
1234
1299
|
if (width && height) {
|
|
@@ -1411,9 +1476,13 @@ function MujocoSimProvider({
|
|
|
1411
1476
|
beforeStepCallbacks,
|
|
1412
1477
|
afterStepCallbacks,
|
|
1413
1478
|
resetCallbacks,
|
|
1479
|
+
errorRef,
|
|
1480
|
+
bodyRegistryRef,
|
|
1481
|
+
hiddenBodiesRef,
|
|
1482
|
+
requestBodyReload,
|
|
1414
1483
|
status
|
|
1415
1484
|
}),
|
|
1416
|
-
[api, status]
|
|
1485
|
+
[api, status, requestBodyReload]
|
|
1417
1486
|
);
|
|
1418
1487
|
return /* @__PURE__ */ jsxs(MujocoSimContext.Provider, { value: contextValue, children: [
|
|
1419
1488
|
/* @__PURE__ */ jsx(SceneRenderer, {}),
|
|
@@ -1519,13 +1588,24 @@ function createController(options, Impl) {
|
|
|
1519
1588
|
Controller.defaultConfig = options.defaultConfig ?? {};
|
|
1520
1589
|
return Controller;
|
|
1521
1590
|
}
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1591
|
+
function createControllerHook(options, useImpl) {
|
|
1592
|
+
const useController = (config) => {
|
|
1593
|
+
const configObj = config;
|
|
1594
|
+
const stableRef = useRef(configObj);
|
|
1595
|
+
if (configObj && stableRef.current) {
|
|
1596
|
+
if (!shallowEqual(stableRef.current, configObj)) {
|
|
1597
|
+
stableRef.current = configObj;
|
|
1598
|
+
}
|
|
1599
|
+
} else {
|
|
1600
|
+
stableRef.current = configObj;
|
|
1601
|
+
}
|
|
1602
|
+
const mergedConfig = useMemo(
|
|
1603
|
+
() => stableRef.current ? { ...options.defaultConfig, ...stableRef.current } : null,
|
|
1604
|
+
[stableRef.current]
|
|
1605
|
+
);
|
|
1606
|
+
return useImpl(mergedConfig);
|
|
1607
|
+
};
|
|
1608
|
+
return useController;
|
|
1529
1609
|
}
|
|
1530
1610
|
|
|
1531
1611
|
// src/core/GenericIK.ts
|
|
@@ -1753,6 +1833,8 @@ function solve6x6(A, b, x) {
|
|
|
1753
1833
|
x[row] = sum / a[row * N + row];
|
|
1754
1834
|
}
|
|
1755
1835
|
}
|
|
1836
|
+
|
|
1837
|
+
// src/hooks/useIkController.ts
|
|
1756
1838
|
var _syncMat4 = new THREE11.Matrix4();
|
|
1757
1839
|
function syncGizmoToSite(data, siteId, target) {
|
|
1758
1840
|
if (siteId === -1) return;
|
|
@@ -1779,206 +1861,272 @@ function syncGizmoToSite(data, siteId, target) {
|
|
|
1779
1861
|
);
|
|
1780
1862
|
target.quaternion.setFromRotationMatrix(_syncMat4);
|
|
1781
1863
|
}
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
})
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
return;
|
|
1808
|
-
}
|
|
1809
|
-
siteIdRef.current = findSiteByName(model, config.siteName);
|
|
1810
|
-
const data = mjDataRef.current;
|
|
1811
|
-
if (data && ikTargetRef.current) {
|
|
1812
|
-
syncGizmoToSite(data, siteIdRef.current, ikTargetRef.current);
|
|
1813
|
-
}
|
|
1814
|
-
}, [config.siteName, status, mjModelRef, mjDataRef]);
|
|
1815
|
-
const ikSolveFn = useCallback(
|
|
1816
|
-
(pos, quat, currentQ) => {
|
|
1817
|
-
if (config.ikSolveFn) return config.ikSolveFn(pos, quat, currentQ);
|
|
1864
|
+
var useIkController = createControllerHook(
|
|
1865
|
+
{ defaultConfig: { damping: 0.01, maxIterations: 50 } },
|
|
1866
|
+
function useIkControllerImpl(config) {
|
|
1867
|
+
const { mjModelRef, mjDataRef, mujocoRef, resetCallbacks, status } = useMujocoContext();
|
|
1868
|
+
const ikEnabledRef = useRef(false);
|
|
1869
|
+
const ikCalculatingRef = useRef(false);
|
|
1870
|
+
const ikTargetRef = useRef(new THREE11.Group());
|
|
1871
|
+
const siteIdRef = useRef(-1);
|
|
1872
|
+
const genericIkRef = useRef(new GenericIK(mujocoRef.current));
|
|
1873
|
+
const firstIkEnableRef = useRef(true);
|
|
1874
|
+
const needsInitialSync = useRef(true);
|
|
1875
|
+
const gizmoAnimRef = useRef({
|
|
1876
|
+
active: false,
|
|
1877
|
+
startPos: new THREE11.Vector3(),
|
|
1878
|
+
endPos: new THREE11.Vector3(),
|
|
1879
|
+
startRot: new THREE11.Quaternion(),
|
|
1880
|
+
endRot: new THREE11.Quaternion(),
|
|
1881
|
+
startTime: 0,
|
|
1882
|
+
duration: 1e3
|
|
1883
|
+
});
|
|
1884
|
+
useEffect(() => {
|
|
1885
|
+
if (!config) {
|
|
1886
|
+
siteIdRef.current = -1;
|
|
1887
|
+
return;
|
|
1888
|
+
}
|
|
1818
1889
|
const model = mjModelRef.current;
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
model,
|
|
1823
|
-
data,
|
|
1824
|
-
siteIdRef.current,
|
|
1825
|
-
config.numJoints,
|
|
1826
|
-
pos,
|
|
1827
|
-
quat,
|
|
1828
|
-
currentQ,
|
|
1829
|
-
{
|
|
1830
|
-
damping: config.damping,
|
|
1831
|
-
maxIterations: config.maxIterations
|
|
1832
|
-
}
|
|
1833
|
-
);
|
|
1834
|
-
},
|
|
1835
|
-
[config.ikSolveFn, config.numJoints, config.damping, config.maxIterations, mjModelRef, mjDataRef]
|
|
1836
|
-
);
|
|
1837
|
-
const ikSolveFnRef = useRef(ikSolveFn);
|
|
1838
|
-
ikSolveFnRef.current = ikSolveFn;
|
|
1839
|
-
useFrame(() => {
|
|
1840
|
-
if (needsInitialSync.current && siteIdRef.current !== -1) {
|
|
1841
|
-
const data = mjDataRef.current;
|
|
1842
|
-
if (data && ikTargetRef.current) {
|
|
1843
|
-
syncGizmoToSite(data, siteIdRef.current, ikTargetRef.current);
|
|
1844
|
-
needsInitialSync.current = false;
|
|
1890
|
+
if (!model || status !== "ready") {
|
|
1891
|
+
siteIdRef.current = -1;
|
|
1892
|
+
return;
|
|
1845
1893
|
}
|
|
1846
|
-
|
|
1847
|
-
const ga = gizmoAnimRef.current;
|
|
1848
|
-
const target = ikTargetRef.current;
|
|
1849
|
-
if (!ga.active || !target) return;
|
|
1850
|
-
const now = performance.now();
|
|
1851
|
-
const elapsed = now - ga.startTime;
|
|
1852
|
-
const t = Math.min(elapsed / ga.duration, 1);
|
|
1853
|
-
const ease = 1 - Math.pow(1 - t, 3);
|
|
1854
|
-
target.position.lerpVectors(ga.startPos, ga.endPos, ease);
|
|
1855
|
-
target.quaternion.slerpQuaternions(ga.startRot, ga.endRot, ease);
|
|
1856
|
-
if (t >= 1) ga.active = false;
|
|
1857
|
-
});
|
|
1858
|
-
useBeforePhysicsStep((model, data) => {
|
|
1859
|
-
if (!ikEnabledRef.current) {
|
|
1860
|
-
ikCalculatingRef.current = false;
|
|
1861
|
-
return;
|
|
1862
|
-
}
|
|
1863
|
-
const target = ikTargetRef.current;
|
|
1864
|
-
if (!target) return;
|
|
1865
|
-
ikCalculatingRef.current = true;
|
|
1866
|
-
const numJoints = config.numJoints;
|
|
1867
|
-
const currentQ = [];
|
|
1868
|
-
for (let i = 0; i < numJoints; i++) currentQ.push(data.qpos[i]);
|
|
1869
|
-
const solution = ikSolveFnRef.current(target.position, target.quaternion, currentQ);
|
|
1870
|
-
if (solution) {
|
|
1871
|
-
for (let i = 0; i < numJoints; i++) data.ctrl[i] = solution[i];
|
|
1872
|
-
}
|
|
1873
|
-
});
|
|
1874
|
-
useEffect(() => {
|
|
1875
|
-
const cb = () => {
|
|
1894
|
+
siteIdRef.current = findSiteByName(model, config.siteName);
|
|
1876
1895
|
const data = mjDataRef.current;
|
|
1877
1896
|
if (data && ikTargetRef.current) {
|
|
1878
1897
|
syncGizmoToSite(data, siteIdRef.current, ikTargetRef.current);
|
|
1879
1898
|
}
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1899
|
+
}, [config?.siteName, status, mjModelRef, mjDataRef, config]);
|
|
1900
|
+
const ikSolveFn = useCallback(
|
|
1901
|
+
(pos, quat, currentQ) => {
|
|
1902
|
+
if (!config) return null;
|
|
1903
|
+
if (config.ikSolveFn) return config.ikSolveFn(pos, quat, currentQ);
|
|
1904
|
+
const model = mjModelRef.current;
|
|
1905
|
+
const data = mjDataRef.current;
|
|
1906
|
+
if (!model || !data || siteIdRef.current === -1) return null;
|
|
1907
|
+
return genericIkRef.current.solve(
|
|
1908
|
+
model,
|
|
1909
|
+
data,
|
|
1910
|
+
siteIdRef.current,
|
|
1911
|
+
config.numJoints,
|
|
1912
|
+
pos,
|
|
1913
|
+
quat,
|
|
1914
|
+
currentQ,
|
|
1915
|
+
{ damping: config.damping, maxIterations: config.maxIterations }
|
|
1916
|
+
);
|
|
1917
|
+
},
|
|
1918
|
+
[config, mjModelRef, mjDataRef]
|
|
1919
|
+
);
|
|
1920
|
+
const ikSolveFnRef = useRef(ikSolveFn);
|
|
1921
|
+
ikSolveFnRef.current = ikSolveFn;
|
|
1922
|
+
useFrame(() => {
|
|
1923
|
+
if (!config) return;
|
|
1924
|
+
if (needsInitialSync.current && siteIdRef.current !== -1) {
|
|
1925
|
+
const data = mjDataRef.current;
|
|
1926
|
+
if (data && ikTargetRef.current) {
|
|
1927
|
+
syncGizmoToSite(data, siteIdRef.current, ikTargetRef.current);
|
|
1928
|
+
needsInitialSync.current = false;
|
|
1929
|
+
}
|
|
1897
1930
|
}
|
|
1898
|
-
|
|
1899
|
-
[mjDataRef]
|
|
1900
|
-
);
|
|
1901
|
-
const syncTargetToSiteApi = useCallback(() => {
|
|
1902
|
-
const data = mjDataRef.current;
|
|
1903
|
-
const target = ikTargetRef.current;
|
|
1904
|
-
if (data && target) syncGizmoToSite(data, siteIdRef.current, target);
|
|
1905
|
-
}, [mjDataRef]);
|
|
1906
|
-
const solveIK = useCallback(
|
|
1907
|
-
(pos, quat, currentQ) => {
|
|
1908
|
-
return ikSolveFnRef.current(pos, quat, currentQ);
|
|
1909
|
-
},
|
|
1910
|
-
[]
|
|
1911
|
-
);
|
|
1912
|
-
const moveTarget = useCallback(
|
|
1913
|
-
(pos, duration = 0) => {
|
|
1914
|
-
if (!ikEnabledRef.current) setIkEnabled(true);
|
|
1931
|
+
const ga = gizmoAnimRef.current;
|
|
1915
1932
|
const target = ikTargetRef.current;
|
|
1916
|
-
if (!target) return;
|
|
1917
|
-
const
|
|
1918
|
-
const
|
|
1919
|
-
|
|
1920
|
-
);
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
ga.duration = duration;
|
|
1930
|
-
} else {
|
|
1931
|
-
gizmoAnimRef.current.active = false;
|
|
1932
|
-
target.position.copy(targetPos);
|
|
1933
|
-
target.quaternion.copy(targetRot);
|
|
1933
|
+
if (!ga.active || !target) return;
|
|
1934
|
+
const now = performance.now();
|
|
1935
|
+
const elapsed = now - ga.startTime;
|
|
1936
|
+
const t = Math.min(elapsed / ga.duration, 1);
|
|
1937
|
+
const ease = 1 - Math.pow(1 - t, 3);
|
|
1938
|
+
target.position.lerpVectors(ga.startPos, ga.endPos, ease);
|
|
1939
|
+
target.quaternion.slerpQuaternions(ga.startRot, ga.endRot, ease);
|
|
1940
|
+
if (t >= 1) ga.active = false;
|
|
1941
|
+
});
|
|
1942
|
+
useBeforePhysicsStep((model, data) => {
|
|
1943
|
+
if (!config || !ikEnabledRef.current) {
|
|
1944
|
+
ikCalculatingRef.current = false;
|
|
1945
|
+
return;
|
|
1934
1946
|
}
|
|
1935
|
-
},
|
|
1936
|
-
[setIkEnabled]
|
|
1937
|
-
);
|
|
1938
|
-
const getGizmoStats = useCallback(
|
|
1939
|
-
() => {
|
|
1940
1947
|
const target = ikTargetRef.current;
|
|
1941
|
-
if (!
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1948
|
+
if (!target) return;
|
|
1949
|
+
ikCalculatingRef.current = true;
|
|
1950
|
+
const numJoints = config.numJoints;
|
|
1951
|
+
const currentQ = [];
|
|
1952
|
+
for (let i = 0; i < numJoints; i++) currentQ.push(data.qpos[i]);
|
|
1953
|
+
const solution = ikSolveFnRef.current(target.position, target.quaternion, currentQ);
|
|
1954
|
+
if (solution) {
|
|
1955
|
+
for (let i = 0; i < numJoints; i++) data.ctrl[i] = solution[i];
|
|
1956
|
+
}
|
|
1957
|
+
});
|
|
1958
|
+
useEffect(() => {
|
|
1959
|
+
if (!config) return;
|
|
1960
|
+
const cb = () => {
|
|
1961
|
+
const data = mjDataRef.current;
|
|
1962
|
+
if (data && ikTargetRef.current) {
|
|
1963
|
+
syncGizmoToSite(data, siteIdRef.current, ikTargetRef.current);
|
|
1964
|
+
}
|
|
1965
|
+
gizmoAnimRef.current.active = false;
|
|
1966
|
+
firstIkEnableRef.current = true;
|
|
1967
|
+
ikEnabledRef.current = false;
|
|
1968
|
+
needsInitialSync.current = true;
|
|
1945
1969
|
};
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1970
|
+
resetCallbacks.current.add(cb);
|
|
1971
|
+
return () => {
|
|
1972
|
+
resetCallbacks.current.delete(cb);
|
|
1973
|
+
};
|
|
1974
|
+
}, [resetCallbacks, mjDataRef, config]);
|
|
1975
|
+
const setIkEnabled = useCallback(
|
|
1976
|
+
(enabled) => {
|
|
1977
|
+
ikEnabledRef.current = enabled;
|
|
1978
|
+
const data = mjDataRef.current;
|
|
1979
|
+
if (enabled && data && !gizmoAnimRef.current.active && ikTargetRef.current) {
|
|
1980
|
+
syncGizmoToSite(data, siteIdRef.current, ikTargetRef.current);
|
|
1981
|
+
firstIkEnableRef.current = false;
|
|
1982
|
+
}
|
|
1983
|
+
},
|
|
1984
|
+
[mjDataRef]
|
|
1985
|
+
);
|
|
1986
|
+
const syncTargetToSiteApi = useCallback(() => {
|
|
1987
|
+
const data = mjDataRef.current;
|
|
1988
|
+
const target = ikTargetRef.current;
|
|
1989
|
+
if (data && target) syncGizmoToSite(data, siteIdRef.current, target);
|
|
1990
|
+
}, [mjDataRef]);
|
|
1991
|
+
const solveIK = useCallback(
|
|
1992
|
+
(pos, quat, currentQ) => {
|
|
1993
|
+
return ikSolveFnRef.current(pos, quat, currentQ);
|
|
1994
|
+
},
|
|
1995
|
+
[]
|
|
1996
|
+
);
|
|
1997
|
+
const moveTarget = useCallback(
|
|
1998
|
+
(pos, duration = 0) => {
|
|
1999
|
+
if (!ikEnabledRef.current) setIkEnabled(true);
|
|
2000
|
+
const target = ikTargetRef.current;
|
|
2001
|
+
if (!target) return;
|
|
2002
|
+
const targetPos = pos.clone();
|
|
2003
|
+
const targetRot = new THREE11.Quaternion().setFromEuler(
|
|
2004
|
+
new THREE11.Euler(Math.PI, 0, 0)
|
|
2005
|
+
);
|
|
2006
|
+
if (duration > 0) {
|
|
2007
|
+
const ga = gizmoAnimRef.current;
|
|
2008
|
+
ga.active = true;
|
|
2009
|
+
ga.startPos.copy(target.position);
|
|
2010
|
+
ga.endPos.copy(targetPos);
|
|
2011
|
+
ga.startRot.copy(target.quaternion);
|
|
2012
|
+
ga.endRot.copy(targetRot);
|
|
2013
|
+
ga.startTime = performance.now();
|
|
2014
|
+
ga.duration = duration;
|
|
2015
|
+
} else {
|
|
2016
|
+
gizmoAnimRef.current.active = false;
|
|
2017
|
+
target.position.copy(targetPos);
|
|
2018
|
+
target.quaternion.copy(targetRot);
|
|
2019
|
+
}
|
|
2020
|
+
},
|
|
2021
|
+
[setIkEnabled]
|
|
2022
|
+
);
|
|
2023
|
+
const getGizmoStats = useCallback(
|
|
2024
|
+
() => {
|
|
2025
|
+
const target = ikTargetRef.current;
|
|
2026
|
+
if (!ikCalculatingRef.current || !target) return null;
|
|
2027
|
+
return {
|
|
2028
|
+
pos: target.position.clone(),
|
|
2029
|
+
rot: new THREE11.Euler().setFromQuaternion(target.quaternion)
|
|
2030
|
+
};
|
|
2031
|
+
},
|
|
2032
|
+
[]
|
|
2033
|
+
);
|
|
2034
|
+
const contextValue = useMemo(
|
|
2035
|
+
() => ({
|
|
2036
|
+
ikEnabledRef,
|
|
2037
|
+
ikCalculatingRef,
|
|
2038
|
+
ikTargetRef,
|
|
2039
|
+
siteIdRef,
|
|
2040
|
+
setIkEnabled,
|
|
2041
|
+
moveTarget,
|
|
2042
|
+
syncTargetToSite: syncTargetToSiteApi,
|
|
2043
|
+
solveIK,
|
|
2044
|
+
getGizmoStats
|
|
2045
|
+
}),
|
|
2046
|
+
[setIkEnabled, moveTarget, syncTargetToSiteApi, solveIK, getGizmoStats]
|
|
2047
|
+
);
|
|
2048
|
+
if (!config) return null;
|
|
2049
|
+
return contextValue;
|
|
2050
|
+
}
|
|
1974
2051
|
);
|
|
2052
|
+
function Body({
|
|
2053
|
+
name,
|
|
2054
|
+
type,
|
|
2055
|
+
size,
|
|
2056
|
+
position = [0, 0, 0],
|
|
2057
|
+
rgba = [0.5, 0.5, 0.5, 1],
|
|
2058
|
+
mass,
|
|
2059
|
+
freejoint,
|
|
2060
|
+
friction,
|
|
2061
|
+
solref,
|
|
2062
|
+
solimp,
|
|
2063
|
+
condim,
|
|
2064
|
+
children
|
|
2065
|
+
}) {
|
|
2066
|
+
const { bodyRegistryRef, hiddenBodiesRef, requestBodyReload, mjDataRef, mjModelRef, status } = useMujocoContext();
|
|
2067
|
+
const bodyIdRef = useRef(-1);
|
|
2068
|
+
const groupRef = useRef(null);
|
|
2069
|
+
const initialLoadRef = useRef(true);
|
|
2070
|
+
const hasChildren = children != null;
|
|
2071
|
+
useLayoutEffect(() => {
|
|
2072
|
+
const definition = {
|
|
2073
|
+
name,
|
|
2074
|
+
type,
|
|
2075
|
+
size,
|
|
2076
|
+
position,
|
|
2077
|
+
rgba,
|
|
2078
|
+
mass,
|
|
2079
|
+
freejoint,
|
|
2080
|
+
friction,
|
|
2081
|
+
solref,
|
|
2082
|
+
solimp,
|
|
2083
|
+
condim
|
|
2084
|
+
};
|
|
2085
|
+
bodyRegistryRef.current.set(name, { definition, hasCustomChildren: hasChildren });
|
|
2086
|
+
if (hasChildren) {
|
|
2087
|
+
hiddenBodiesRef.current.add(name);
|
|
2088
|
+
}
|
|
2089
|
+
return () => {
|
|
2090
|
+
bodyRegistryRef.current.delete(name);
|
|
2091
|
+
hiddenBodiesRef.current.delete(name);
|
|
2092
|
+
if (!initialLoadRef.current) {
|
|
2093
|
+
requestBodyReload();
|
|
2094
|
+
}
|
|
2095
|
+
};
|
|
2096
|
+
}, [name, type, size, position, rgba, mass, freejoint, friction, solref, solimp, condim, hasChildren, bodyRegistryRef, hiddenBodiesRef, requestBodyReload]);
|
|
2097
|
+
useEffect(() => {
|
|
2098
|
+
if (status !== "ready") return;
|
|
2099
|
+
const model = mjModelRef.current;
|
|
2100
|
+
if (!model) return;
|
|
2101
|
+
bodyIdRef.current = findBodyByName(model, name);
|
|
2102
|
+
initialLoadRef.current = false;
|
|
2103
|
+
}, [status, name, mjModelRef]);
|
|
2104
|
+
useFrame(() => {
|
|
2105
|
+
if (!hasChildren) return;
|
|
2106
|
+
const data = mjDataRef.current;
|
|
2107
|
+
const id = bodyIdRef.current;
|
|
2108
|
+
const group = groupRef.current;
|
|
2109
|
+
if (!data || id < 0 || !group) return;
|
|
2110
|
+
const i3 = id * 3;
|
|
2111
|
+
const i4 = id * 4;
|
|
2112
|
+
group.position.set(data.xpos[i3], data.xpos[i3 + 1], data.xpos[i3 + 2]);
|
|
2113
|
+
group.quaternion.set(
|
|
2114
|
+
data.xquat[i4 + 1],
|
|
2115
|
+
data.xquat[i4 + 2],
|
|
2116
|
+
data.xquat[i4 + 3],
|
|
2117
|
+
data.xquat[i4]
|
|
2118
|
+
);
|
|
2119
|
+
});
|
|
2120
|
+
if (!hasChildren) return null;
|
|
2121
|
+
return /* @__PURE__ */ jsx("group", { ref: groupRef, children });
|
|
2122
|
+
}
|
|
1975
2123
|
var _mat4 = new THREE11.Matrix4();
|
|
1976
2124
|
var _pos = new THREE11.Vector3();
|
|
1977
2125
|
var _quat = new THREE11.Quaternion();
|
|
1978
2126
|
var _scale = new THREE11.Vector3(1, 1, 1);
|
|
1979
|
-
function IkGizmo({ siteName, scale = 0.18, onDrag }) {
|
|
1980
|
-
const { mjModelRef, mjDataRef, status } =
|
|
1981
|
-
const { ikTargetRef, siteIdRef, ikEnabledRef, setIkEnabled } =
|
|
2127
|
+
function IkGizmo({ controller, siteName, scale = 0.18, onDrag }) {
|
|
2128
|
+
const { mjModelRef, mjDataRef, status } = useMujocoContext();
|
|
2129
|
+
const { ikTargetRef, siteIdRef, ikEnabledRef, setIkEnabled } = controller;
|
|
1982
2130
|
const wrapperRef = useRef(null);
|
|
1983
2131
|
const pivotRef = useRef(null);
|
|
1984
2132
|
const draggingRef = useRef(false);
|
|
@@ -2075,7 +2223,7 @@ function ContactMarkers({
|
|
|
2075
2223
|
visible = true,
|
|
2076
2224
|
...groupProps
|
|
2077
2225
|
} = {}) {
|
|
2078
|
-
const { mjDataRef, status } =
|
|
2226
|
+
const { mjDataRef, status } = useMujocoContext();
|
|
2079
2227
|
const meshRef = useRef(null);
|
|
2080
2228
|
useFrame(() => {
|
|
2081
2229
|
const mesh = meshRef.current;
|
|
@@ -2119,7 +2267,7 @@ function DragInteraction({
|
|
|
2119
2267
|
showArrow = true,
|
|
2120
2268
|
...groupProps
|
|
2121
2269
|
}) {
|
|
2122
|
-
const { mjDataRef, mujocoRef, mjModelRef, status } =
|
|
2270
|
+
const { mjDataRef, mujocoRef, mjModelRef, status } = useMujocoContext();
|
|
2123
2271
|
const { gl, camera, scene, controls } = useThree();
|
|
2124
2272
|
const draggingRef = useRef(false);
|
|
2125
2273
|
const bodyIdRef = useRef(-1);
|
|
@@ -2277,7 +2425,7 @@ function DragInteraction({
|
|
|
2277
2425
|
return /* @__PURE__ */ jsx("group", { ...groupProps, ref: groupRef });
|
|
2278
2426
|
}
|
|
2279
2427
|
function useSceneLights(intensity = 1) {
|
|
2280
|
-
const { mjModelRef, status } =
|
|
2428
|
+
const { mjModelRef, status } = useMujocoContext();
|
|
2281
2429
|
const { scene } = useThree();
|
|
2282
2430
|
const lightsRef = useRef([]);
|
|
2283
2431
|
const targetsRef = useRef([]);
|
|
@@ -2398,7 +2546,7 @@ function Debug({
|
|
|
2398
2546
|
showTendons = false,
|
|
2399
2547
|
...groupProps
|
|
2400
2548
|
}) {
|
|
2401
|
-
const { mjModelRef, mjDataRef, status } =
|
|
2549
|
+
const { mjModelRef, mjDataRef, status } = useMujocoContext();
|
|
2402
2550
|
const { scene } = useThree();
|
|
2403
2551
|
const groupRef = useRef(null);
|
|
2404
2552
|
const debugGeometry = useMemo(() => {
|
|
@@ -2668,7 +2816,7 @@ var DEFAULT_TENDON_COLOR = new THREE11.Color(0.3, 0.3, 0.8);
|
|
|
2668
2816
|
var DEFAULT_TENDON_WIDTH = 2e-3;
|
|
2669
2817
|
new THREE11.Vector3();
|
|
2670
2818
|
function TendonRenderer(props) {
|
|
2671
|
-
const { mjModelRef, mjDataRef, status } =
|
|
2819
|
+
const { mjModelRef, mjDataRef, status } = useMujocoContext();
|
|
2672
2820
|
const groupRef = useRef(null);
|
|
2673
2821
|
const meshesRef = useRef([]);
|
|
2674
2822
|
const curvesRef = useRef([]);
|
|
@@ -2772,7 +2920,7 @@ function TendonRenderer(props) {
|
|
|
2772
2920
|
return /* @__PURE__ */ jsx("group", { ...props, ref: groupRef });
|
|
2773
2921
|
}
|
|
2774
2922
|
function FlexRenderer(props) {
|
|
2775
|
-
const { mjModelRef, mjDataRef, status } =
|
|
2923
|
+
const { mjModelRef, mjDataRef, status } = useMujocoContext();
|
|
2776
2924
|
const groupRef = useRef(null);
|
|
2777
2925
|
const meshesRef = useRef([]);
|
|
2778
2926
|
useEffect(() => {
|
|
@@ -2852,7 +3000,7 @@ function getGeomNameCached(model, geomId) {
|
|
|
2852
3000
|
return name;
|
|
2853
3001
|
}
|
|
2854
3002
|
function useContacts(bodyName, callback) {
|
|
2855
|
-
const { mjModelRef, status } =
|
|
3003
|
+
const { mjModelRef, status } = useMujocoContext();
|
|
2856
3004
|
const contactsRef = useRef([]);
|
|
2857
3005
|
const bodyIdRef = useRef(-1);
|
|
2858
3006
|
const bodyResolvedRef = useRef(false);
|
|
@@ -2951,7 +3099,7 @@ function ContactListener({
|
|
|
2951
3099
|
return null;
|
|
2952
3100
|
}
|
|
2953
3101
|
function useTrajectoryPlayer(trajectory, options = {}) {
|
|
2954
|
-
const { mjModelRef, mjDataRef, mujocoRef, pausedRef } =
|
|
3102
|
+
const { mjModelRef, mjDataRef, mujocoRef, pausedRef } = useMujocoContext();
|
|
2955
3103
|
const fps = options.fps ?? 30;
|
|
2956
3104
|
const loop = options.loop ?? false;
|
|
2957
3105
|
const playingRef = useRef(false);
|
|
@@ -3054,7 +3202,7 @@ function TrajectoryPlayer({
|
|
|
3054
3202
|
return null;
|
|
3055
3203
|
}
|
|
3056
3204
|
function useActuators() {
|
|
3057
|
-
const { mjModelRef, status } =
|
|
3205
|
+
const { mjModelRef, status } = useMujocoContext();
|
|
3058
3206
|
return useMemo(() => {
|
|
3059
3207
|
if (status !== "ready") return [];
|
|
3060
3208
|
const model = mjModelRef.current;
|
|
@@ -3073,7 +3221,7 @@ function useActuators() {
|
|
|
3073
3221
|
}
|
|
3074
3222
|
var _mat42 = new THREE11.Matrix4();
|
|
3075
3223
|
function useSitePosition(siteName) {
|
|
3076
|
-
const { mjModelRef, mjDataRef, status } =
|
|
3224
|
+
const { mjModelRef, mjDataRef, status } = useMujocoContext();
|
|
3077
3225
|
const siteIdRef = useRef(-1);
|
|
3078
3226
|
const positionRef = useRef(new THREE11.Vector3());
|
|
3079
3227
|
const quaternionRef = useRef(new THREE11.Quaternion());
|
|
@@ -3130,7 +3278,7 @@ function useGravityCompensation(enabled = true) {
|
|
|
3130
3278
|
});
|
|
3131
3279
|
}
|
|
3132
3280
|
function useSensor(name) {
|
|
3133
|
-
const { mjModelRef, mjDataRef, status } =
|
|
3281
|
+
const { mjModelRef, mjDataRef, status } = useMujocoContext();
|
|
3134
3282
|
const sensorIdRef = useRef(-1);
|
|
3135
3283
|
const sensorAdrRef = useRef(0);
|
|
3136
3284
|
const sensorDimRef = useRef(0);
|
|
@@ -3160,7 +3308,7 @@ function useSensor(name) {
|
|
|
3160
3308
|
return { value: valueRef, size: sensorDimRef.current };
|
|
3161
3309
|
}
|
|
3162
3310
|
function useSensors() {
|
|
3163
|
-
const { mjModelRef, status } =
|
|
3311
|
+
const { mjModelRef, status } = useMujocoContext();
|
|
3164
3312
|
return useMemo(() => {
|
|
3165
3313
|
const model = mjModelRef.current;
|
|
3166
3314
|
if (!model || status !== "ready") return [];
|
|
@@ -3197,7 +3345,7 @@ function useSensors() {
|
|
|
3197
3345
|
}, [mjModelRef, status]);
|
|
3198
3346
|
}
|
|
3199
3347
|
function useJointState(name) {
|
|
3200
|
-
const { mjModelRef, mjDataRef, status } =
|
|
3348
|
+
const { mjModelRef, mjDataRef, status } = useMujocoContext();
|
|
3201
3349
|
const jointIdRef = useRef(-1);
|
|
3202
3350
|
const qposAdrRef = useRef(0);
|
|
3203
3351
|
const dofAdrRef = useRef(0);
|
|
@@ -3257,7 +3405,7 @@ function useJointState(name) {
|
|
|
3257
3405
|
return { position: positionRef, velocity: velocityRef };
|
|
3258
3406
|
}
|
|
3259
3407
|
function useBodyState(name) {
|
|
3260
|
-
const { mjModelRef, status } =
|
|
3408
|
+
const { mjModelRef, status } = useMujocoContext();
|
|
3261
3409
|
const bodyIdRef = useRef(-1);
|
|
3262
3410
|
const position = useRef(new THREE11.Vector3());
|
|
3263
3411
|
const quaternion = useRef(new THREE11.Quaternion());
|
|
@@ -3289,7 +3437,7 @@ function useBodyState(name) {
|
|
|
3289
3437
|
return { position, quaternion, linearVelocity, angularVelocity };
|
|
3290
3438
|
}
|
|
3291
3439
|
function useCtrl(name) {
|
|
3292
|
-
const { mjModelRef, mjDataRef, status } =
|
|
3440
|
+
const { mjModelRef, mjDataRef, status } = useMujocoContext();
|
|
3293
3441
|
const actuatorIdRef = useRef(-1);
|
|
3294
3442
|
const valueRef = useRef(0);
|
|
3295
3443
|
useEffect(() => {
|
|
@@ -3306,7 +3454,7 @@ function useCtrl(name) {
|
|
|
3306
3454
|
return [valueRef, setValue];
|
|
3307
3455
|
}
|
|
3308
3456
|
function useKeyboardTeleop(config) {
|
|
3309
|
-
const { mjModelRef, mjDataRef, status } =
|
|
3457
|
+
const { mjModelRef, mjDataRef, status } = useMujocoContext();
|
|
3310
3458
|
const pressedRef = useRef(/* @__PURE__ */ new Set());
|
|
3311
3459
|
const toggleStateRef = useRef(/* @__PURE__ */ new Map());
|
|
3312
3460
|
const enabledRef = useRef(config.enabled ?? true);
|
|
@@ -3369,7 +3517,7 @@ function useKeyboardTeleop(config) {
|
|
|
3369
3517
|
});
|
|
3370
3518
|
}
|
|
3371
3519
|
function usePolicy(config) {
|
|
3372
|
-
const { mjModelRef } =
|
|
3520
|
+
const { mjModelRef } = useMujocoContext();
|
|
3373
3521
|
const lastActionTimeRef = useRef(0);
|
|
3374
3522
|
const lastActionRef = useRef(null);
|
|
3375
3523
|
const isRunningRef = useRef(true);
|
|
@@ -3403,7 +3551,7 @@ function usePolicy(config) {
|
|
|
3403
3551
|
};
|
|
3404
3552
|
}
|
|
3405
3553
|
function useTrajectoryRecorder(options = {}) {
|
|
3406
|
-
const { mjModelRef } =
|
|
3554
|
+
const { mjModelRef } = useMujocoContext();
|
|
3407
3555
|
const recordingRef = useRef(false);
|
|
3408
3556
|
const framesRef = useRef([]);
|
|
3409
3557
|
const fields = options.fields ?? ["qpos"];
|
|
@@ -3479,7 +3627,7 @@ function useTrajectoryRecorder(options = {}) {
|
|
|
3479
3627
|
};
|
|
3480
3628
|
}
|
|
3481
3629
|
function useGamepad(config) {
|
|
3482
|
-
const { mjModelRef, status } =
|
|
3630
|
+
const { mjModelRef, status } = useMujocoContext();
|
|
3483
3631
|
const configRef = useRef(config);
|
|
3484
3632
|
configRef.current = config;
|
|
3485
3633
|
const axisCacheRef = useRef(/* @__PURE__ */ new Map());
|
|
@@ -3575,7 +3723,7 @@ function useVideoRecorder(options = {}) {
|
|
|
3575
3723
|
};
|
|
3576
3724
|
}
|
|
3577
3725
|
function useCtrlNoise(config = {}) {
|
|
3578
|
-
const { mjModelRef } =
|
|
3726
|
+
const { mjModelRef } = useMujocoContext();
|
|
3579
3727
|
const configRef = useRef(config);
|
|
3580
3728
|
configRef.current = config;
|
|
3581
3729
|
const noiseRef = useRef(null);
|
|
@@ -3726,25 +3874,6 @@ function useCameraAnimation() {
|
|
|
3726
3874
|
* @license
|
|
3727
3875
|
* SPDX-License-Identifier: Apache-2.0
|
|
3728
3876
|
*/
|
|
3729
|
-
/**
|
|
3730
|
-
* @license
|
|
3731
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
3732
|
-
*
|
|
3733
|
-
* createController — typed factory for BYOC (Bring Your Own Controller) plugins.
|
|
3734
|
-
*/
|
|
3735
|
-
/**
|
|
3736
|
-
* @license
|
|
3737
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
3738
|
-
*
|
|
3739
|
-
* IkContext — React context for the IK controller plugin.
|
|
3740
|
-
*/
|
|
3741
|
-
/**
|
|
3742
|
-
* @license
|
|
3743
|
-
* SPDX-License-Identifier: Apache-2.0
|
|
3744
|
-
*
|
|
3745
|
-
* IkController — composable IK controller plugin.
|
|
3746
|
-
* Extracts all IK logic from MujocoSimProvider into an opt-in component.
|
|
3747
|
-
*/
|
|
3748
3877
|
/**
|
|
3749
3878
|
* @license
|
|
3750
3879
|
* SPDX-License-Identifier: Apache-2.0
|
|
@@ -3908,6 +4037,6 @@ function useCameraAnimation() {
|
|
|
3908
4037
|
* useCameraAnimation — composable camera animation hook.
|
|
3909
4038
|
*/
|
|
3910
4039
|
|
|
3911
|
-
export { ContactListener, ContactMarkers, Debug, DragInteraction, FlexRenderer,
|
|
4040
|
+
export { Body, ContactListener, ContactMarkers, Debug, DragInteraction, FlexRenderer, IkGizmo, MujocoCanvas, MujocoPhysics, MujocoProvider, MujocoSimProvider, SceneLights, TendonRenderer, TrajectoryPlayer, createController, findActuatorByName, findBodyByName, findGeomByName, findJointByName, findKeyframeByName, findSensorByName, findSiteByName, findTendonByName, getContact, getName, loadScene, useActuators, useAfterPhysicsStep, useBeforePhysicsStep, useBodyMeshes, useBodyState, useCameraAnimation, useContactEvents, useContacts, useCtrl, useCtrlNoise, useGamepad, useGravityCompensation, useIkController, useJointState, useKeyboardTeleop, useMujoco, useMujocoWasm, usePolicy, useSceneLights, useSelectionHighlight, useSensor, useSensors, useSitePosition, useTrajectoryPlayer, useTrajectoryRecorder, useVideoRecorder };
|
|
3912
4041
|
//# sourceMappingURL=index.js.map
|
|
3913
4042
|
//# sourceMappingURL=index.js.map
|