mujoco-react 10.6.0 → 10.7.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 CHANGED
@@ -372,28 +372,59 @@ function ResetButton() {
372
372
 
373
373
  ## Map Controls to Joints
374
374
 
375
- Use control groups when a robot's actuator order does not match a simple `qpos[0..n]` layout:
375
+ Use named controls when a controller should write actuator commands without
376
+ hard-coding `data.ctrl` offsets:
376
377
 
377
378
  ```tsx
378
- import { useRef } from "react";
379
- import { resolveControlGroup, ModelSites, useBeforePhysicsStep } from "mujoco-react";
380
- import type { ControlGroupInfo } from "mujoco-react";
379
+ import {
380
+ ModelActuators,
381
+ defineControls,
382
+ useBeforePhysicsStep,
383
+ useControls,
384
+ } from "mujoco-react";
381
385
 
382
- function HoldTcpPose() {
383
- const armRef = useRef<ControlGroupInfo | null>(null);
386
+ const arm = defineControls({
387
+ shoulder: ModelActuators.so101.shoulder_pan,
388
+ lift: ModelActuators.so101.shoulder_lift,
389
+ elbow: ModelActuators.so101.elbow_flex,
390
+ });
384
391
 
385
- useBeforePhysicsStep(({ model, data }) => {
386
- armRef.current ??= resolveControlGroup(model, { siteName: ModelSites.franka.tcp });
387
- if (!armRef.current) return;
392
+ function PolicyDriver({ action }: { action: number[] }) {
393
+ const controls = useControls(arm);
388
394
 
389
- armRef.current.writeCtrl(data, armRef.current.readQpos(data));
395
+ useBeforePhysicsStep(() => {
396
+ controls.write(action);
397
+ controls.patch({ elbow: 1.2 });
390
398
  });
391
399
 
392
400
  return null;
393
401
  }
394
402
  ```
395
403
 
396
- `resolveControlGroup()` accepts `{ siteName }`, `{ bodyName }`, `{ joints }`, or `{ actuators }`. Selectors can be a name, ordered name array, regex, or predicate.
404
+ `defineControls()` preserves the alias keys for `set()`, `patch()`, `get()`,
405
+ and `read()`, while `write()` accepts an ordered vector in the same order as the
406
+ object. The Vite plugin injects the generated register module automatically, so
407
+ application code imports generated names from `mujoco-react`, not from
408
+ `src/mujoco-register.gen.ts`.
409
+
410
+ Use lower-level control groups when a robot's actuator order does not match a
411
+ simple `qpos[0..n]` layout or you want actuator-name keys directly:
412
+
413
+ ```tsx
414
+ import { controlGroup, ModelActuators, useControlGroup } from "mujoco-react";
415
+
416
+ const gripper = controlGroup([ModelActuators.so101.gripper]);
417
+
418
+ function HoldGripper() {
419
+ const controls = useControlGroup(gripper);
420
+ controls.set(ModelActuators.so101.gripper, -0.17453);
421
+ return null;
422
+ }
423
+ ```
424
+
425
+ For selector-based introspection, `resolveControlGroup()` accepts `{ siteName }`,
426
+ `{ bodyName }`, `{ joints }`, or `{ actuators }`. Selectors can be a name,
427
+ ordered name array, regex, or predicate.
397
428
 
398
429
  ## Build Observations
399
430
 
package/dist/index.d.ts CHANGED
@@ -795,6 +795,9 @@ declare function useControlWriter(options: ControlWriterOptions): ControlWriterH
795
795
  * positional arrays, no `as const`, no owner bookkeeping.
796
796
  */
797
797
 
798
+ type StringKeyOf<T> = Extract<keyof T, string>;
799
+ type ControlDefinitionMap = Record<string, Actuators>;
800
+ type ControlValues<K extends string> = Partial<Record<K, number>>;
798
801
  /**
799
802
  * A typed description of a set of actuators, keyed by name. Create it once with
800
803
  * {@link controlGroup} and reuse it across controllers and scripts; the key
@@ -810,6 +813,12 @@ interface ControlGroup<K extends Actuators = Actuators> {
810
813
  * no `as const` required (the `const` type parameter captures them).
811
814
  */
812
815
  declare function controlGroup<const T extends readonly Actuators[]>(names: T): ControlGroup<T[number]>;
816
+ interface DefinedControls<TControls extends ControlDefinitionMap = ControlDefinitionMap> {
817
+ readonly controls: TControls;
818
+ readonly aliases: readonly StringKeyOf<TControls>[];
819
+ readonly keys: readonly TControls[StringKeyOf<TControls>][];
820
+ }
821
+ declare function defineControls<const TControls extends ControlDefinitionMap>(controls: TControls): DefinedControls<TControls>;
813
822
  interface ControlGroupSetOptions {
814
823
  /** Write even when another control writer owns one of these actuators. */
815
824
  force?: boolean;
@@ -817,8 +826,14 @@ interface ControlGroupSetOptions {
817
826
  interface ControlGroupHandle<K extends string> {
818
827
  /** The cooperative-ownership identity used for conflict detection. */
819
828
  owner: string;
829
+ /** Set a single actuator by name. Returns false if blocked by a conflict. */
830
+ set(name: K, value: number, options?: ControlGroupSetOptions): boolean;
820
831
  /** Set one or more actuators by name. Returns false if blocked by a conflict. */
821
- set(values: Partial<Record<K, number>>, options?: ControlGroupSetOptions): boolean;
832
+ patch(values: ControlValues<K>, options?: ControlGroupSetOptions): boolean;
833
+ /** Write values in the same order as the declared control group. */
834
+ write(values: ArrayLike<number>, options?: ControlGroupSetOptions): boolean;
835
+ /** Read one actuator value by name. */
836
+ get(name: K): number;
822
837
  /** Read the current control value of every actuator in the group, by name. */
823
838
  read(): Record<K, number>;
824
839
  /** Whether this group can currently write (no unresolved conflicts). */
@@ -827,10 +842,31 @@ interface ControlGroupHandle<K extends string> {
827
842
  release(): void;
828
843
  }
829
844
  type UseControlGroupOptions = Omit<ControlWriterOptions, 'owner' | 'selector'> & {
830
- /** Override the auto-generated owner id (useful for readable conflict logs). */
845
+ /** Human-readable conflict label. */
846
+ label?: string;
847
+ /** Override the generated conflict owner id. Prefer `label` for normal use. */
831
848
  owner?: string;
832
849
  };
850
+ interface ControlsHandle<TControls extends ControlDefinitionMap> {
851
+ /** The cooperative-ownership identity used for conflict detection. */
852
+ owner: string;
853
+ /** Set one alias by name. Returns false if blocked by a conflict. */
854
+ set(name: StringKeyOf<TControls>, value: number, options?: ControlGroupSetOptions): boolean;
855
+ /** Set one or more aliases by name. Returns false if blocked by a conflict. */
856
+ patch(values: ControlValues<StringKeyOf<TControls>>, options?: ControlGroupSetOptions): boolean;
857
+ /** Write values in the same order as the `defineControls()` object. */
858
+ write(values: ArrayLike<number>, options?: ControlGroupSetOptions): boolean;
859
+ /** Read one alias value by name. */
860
+ get(name: StringKeyOf<TControls>): number;
861
+ /** Read every alias value. */
862
+ read(): Record<StringKeyOf<TControls>, number>;
863
+ /** Whether this group can currently write (no unresolved conflicts). */
864
+ canWrite(): boolean;
865
+ /** Release this group's actuator ownership. */
866
+ release(): void;
867
+ }
833
868
  declare function useControlGroup<K extends Actuators>(group: ControlGroup<K>, options?: UseControlGroupOptions): ControlGroupHandle<K>;
869
+ declare function useControls<TControls extends ControlDefinitionMap>(definition: DefinedControls<TControls>, options?: UseControlGroupOptions): ControlsHandle<TControls>;
834
870
 
835
871
  /**
836
872
  * @license
@@ -1595,4 +1631,4 @@ interface CameraAnimationAPI {
1595
1631
  */
1596
1632
  declare function useCameraAnimation(): CameraAnimationAPI;
1597
1633
 
1598
- export { ActuatedJointInfo, ActuatorInfo, Actuators, type ApplyPolicyActionToControlsOptions, type ApplyPolicyActionToControlsResult, ArrayJointStateResult, Bodies, Body, BodyProps, BodyStateResult, type CameraAnimationAPI, CameraFrameCaptureAPI, CameraFrameCaptureOptions, CameraFrameCaptureSource, CameraFrameCaptureTensorOptions, type CameraFrameMountSelector, CameraFrameSequenceCamera, CameraFrameSequenceOptions, CameraFrameSequenceRecorderAPI, CameraFrameSequenceResult, CameraFrameTensorResult, type CameraStreamOptions, CameraView, type CameraViewProps, type CameraViewportOptions, Cameras, type ContactHistoryEntry, type ContactHistoryHandle, type ContactHistoryOptions, ContactInfo, ContactListener, ContactListenerProps, ContactMarkers, type ControlGroup, type ControlGroupHandle, ControlGroupInfo, ControlGroupSelector, type ControlGroupSetOptions, type ControlWriterConflict, type ControlWriterHandle, type ControlWriterOptions, type ControlWriterWriteOptions, type ControllerComponent, type ControllerOptions, type CreateMountedCameraFrameSequenceManifestOptions, type CreateMountedCameraFrameSequencePlanOptions, type CreatePolicyCameraFrameCapturePlanOptions, CtrlHandle, Debug, DebugProps, DragInteraction, DragInteractionProps, FlexRenderer, FrameCaptureAPI, FrameCaptureBlobResult, FrameCaptureOptions, FrameCaptureResult, FrameCaptureStatus, GenericIK, type GenericIKOptions, GeomInfo, Geoms, IkConfig, IkContextValue, IkGizmo, IkGizmoProps, ImagePointCoordinateSpace, ImagePointProjectionOptions, ImagePointProjectionResult, InstancedGeomRenderer, JointStateOptions, JointStateResult, Joints, KeyboardIkTargetConfig, KeyboardTeleopConfig, type MountedCameraFrameCaptureSource, type MountedCameraFrameSequenceCameraOptions, type MountedCameraFrameSequenceDefaults, type MountedCameraFrameSequenceManifest, MountedCameraFrameSequenceManifestStatus, type MountedCameraFrameSequencePlan, type MountedCameraFrameSequencePlanOptions, type MountedCameraFrameSequenceReadiness, MountedCameraFrameSequenceReadinessStatus, type MountedCameraFrameSequenceRecordOptions, type MountedCameraFrameSequenceRecordResult, type MountedCameraFrameSequenceRecorderTarget, type MountedCameraFrameSequenceSourceReadiness, type MountedCameraFrameSequenceStreamSummary, type MountedCameraFrameSourceSuggestion, MountedCameraFrameSourceSuggestionMatch, type MountedCameraSequencePlanOptions, type MountedCameraSequenceReadiness, type MountedCameraSequenceRecordOptions, type MountedCameraSequenceRecordResult, type MountedCameraSequenceRecorderAPI, type MountedPolicyCameraFrameCaptureAPI, type MountedPolicyCameraFrameCaptureOptions, type MountedPolicyCameraTensorOptions, MujocoCanvas, MujocoCanvasProps, MujocoContextValue, MujocoData, type MujocoLoader, type MujocoLoaderOptions, MujocoModel, MujocoModule, MujocoPhysics, type MujocoPhysicsProps, MujocoProvider, type MujocoProviderProps, MujocoSimAPI, MujocoSimProvider, type MujocoWasmVariant, type NamedCameraFrameResource, type NamedObservationField, type NamedObservationHandle, type NamedObservationInput, type NamedObservationLayoutItem, type NamedObservationMissing, type NamedObservationOptions, type NamedObservationResult, ObservationConfig, ObservationHandle, ObservationOutput, ObservationResult, PairedSplatEnvironmentConfig, PhysicsStepCallback, PlaybackState, PolicyAPI, PolicyCameraFrameCaptureAPI, PolicyCameraFrameCaptureOptions, type PolicyCameraFrameCapturePlan, PolicyCameraFrameCaptureResult, type PolicyCameraFrameCaptureTarget, type PolicyCameraFramePlanTarget, PolicyCameraFrameStream, type PolicyCameraFrameStreamOptions, type PolicyCameraTensorStream, type PolicyCameraTensorsAPI, type PolicyCameraTensorsOptions, type PolicyCameraTensorsResult, PolicyConfig, PolicyVector, type PoseReadout, type PoseResourceKind, ReadyCallbackInput, RemotePolicyAPI, RemotePolicyConfig, type ResolveMountedCameraFrameSourceOptions, type ResolvedMountedCameraFrameSource, ScalarJointStateResult, ScenarioLighting, ScenarioLightingPreset, ScenarioLightingProps, SceneConfig, SceneLights, SceneLightsProps, SelectionCallbackInput, SensorHandle, SensorInfo, Sensors, SitePositionResult, Sites, SplatCollisionPrimitive, SplatCollisionProxyConfig, type SplatCollisionProxyGeomPreview, type SplatCollisionProxyGeomsState, SplatCollisionProxyPreview, type SplatCollisionProxyPreviewProps, type SplatCollisionProxyPreviewStatus, type SplatCollisionProxyPreviewVector3, SplatEnvironment, SplatEnvironmentMetadata, SplatEnvironmentMetadataInput, SplatEnvironmentProps, SplatEnvironmentReadiness, SplatEnvironmentReadinessStatus, SplatFormat, SplatRendererKind, SplatSceneConfigInput, SplatSceneConfigState, SplatSceneInput, StepCallbackInput, TendonRenderer, TrajectoryFrame, TrajectoryInput, TrajectoryPlayer, TrajectoryPlayerProps, TrajectoryStateChangeInput, type UseControlGroupOptions, type UseSplatCollisionProxyGeomsOptions, VisualScenarioConfig, VisualScenarioEffects, VisualScenarioEffectsProps, VisualScenarioExecutionContext, VisualScenarioExecutionContextInput, applyPolicyActionToControls, bodyPositionField, buildObservation, canFetchSplatCollisionProxyXml, captureFrame, captureFrameBlob, capturePolicyCameraFrames, capturePolicyCameraFramesFromMountedStreams, clampPolicyActionValue, controlGroup, createContiguousControlGroup, createController, createControllerHook, createMountedCameraFrameSequenceManifest, createMountedCameraFrameSequencePlan, createMountedCameraFrameSequencePlanFromApi, createMountedCameraFrameSequenceReadiness, createMountedCameraFrameSourceSuggestions, createNamedObservationBuilder, createPairedSplatEnvironment, createPolicyCameraFrameCapturePlan, createPolicyCameraFrameCapturePlanFromApi, createSparkSplatViewerUrl, createSplatEnvironmentUserData, createSplatSceneConfig, createVisualScenarioExecutionContext, ctrlField, fetchSplatCollisionProxyXml, findActuatorByName, findBodyByName, findGeomByName, findJointByName, findKeyframeByName, findSensorByName, findSiteByName, findTendonByName, geomPositionField, getActuatedJoints, getCameraFrameCaptureSourceTarget, getControlMap, getMountedCameraFrameCaptureSource, getName, getScenarioBackground, getScenarioCameraPosition, getSplatEnvironmentReadiness, imagePointToNdc, isMountedCameraFrameCaptureSource, loadScene, parseSplatCollisionProxyGeoms, projectImagePointTo3D, qposField, qvelField, readNamedObservation, recordMountedCameraFrameSequence, resolveControlGroup, resolveMountedCameraFrameSource, sitePositionField, useActuators, useAfterPhysicsStep, useBeforePhysicsStep, useBodyMeshes, useBodyPose, useBodyState, useCameraAnimation, useCameraFrameCapture, useCameraSequenceRecorder, useCameraStream, useCameraViewport, useContactEvents, useContactHistory, useContacts, useControlGroup, useControlWriter, useCtrl, useCtrlNoise, useFrameCapture, useGamepad, useGeomPose, useGravityCompensation, useIkController, useJointState, useKeyboardIkTarget, useKeyboardTeleop, useMountedCameraSequenceRecorder, useMujoco, useMujocoWasm, useNamedObservation, useObservation, usePolicy, usePolicyCameraFrames, usePolicyCameraFramesFromMountedStreams, usePolicyCameraTensors, usePolicyCameraTensorsFromMountedStreams, useRemotePolicy, useSceneLights, useSelectionHighlight, useSensor, useSensors, useSitePose, useSitePosition, useSplatCollisionProxyGeoms, useSplatEnvironment, useSplatSceneConfig, useTrajectoryPlayer, useTrajectoryRecorder, useVideoRecorder, useVisualScenarioEffects, useVisualScenarioExecutionContext, withSplatEnvironment };
1634
+ export { ActuatedJointInfo, ActuatorInfo, Actuators, type ApplyPolicyActionToControlsOptions, type ApplyPolicyActionToControlsResult, ArrayJointStateResult, Bodies, Body, BodyProps, BodyStateResult, type CameraAnimationAPI, CameraFrameCaptureAPI, CameraFrameCaptureOptions, CameraFrameCaptureSource, CameraFrameCaptureTensorOptions, type CameraFrameMountSelector, CameraFrameSequenceCamera, CameraFrameSequenceOptions, CameraFrameSequenceRecorderAPI, CameraFrameSequenceResult, CameraFrameTensorResult, type CameraStreamOptions, CameraView, type CameraViewProps, type CameraViewportOptions, Cameras, type ContactHistoryEntry, type ContactHistoryHandle, type ContactHistoryOptions, ContactInfo, ContactListener, ContactListenerProps, ContactMarkers, type ControlGroup, type ControlGroupHandle, ControlGroupInfo, ControlGroupSelector, type ControlGroupSetOptions, type ControlWriterConflict, type ControlWriterHandle, type ControlWriterOptions, type ControlWriterWriteOptions, type ControllerComponent, type ControllerOptions, type ControlsHandle, type CreateMountedCameraFrameSequenceManifestOptions, type CreateMountedCameraFrameSequencePlanOptions, type CreatePolicyCameraFrameCapturePlanOptions, CtrlHandle, Debug, DebugProps, type DefinedControls, DragInteraction, DragInteractionProps, FlexRenderer, FrameCaptureAPI, FrameCaptureBlobResult, FrameCaptureOptions, FrameCaptureResult, FrameCaptureStatus, GenericIK, type GenericIKOptions, GeomInfo, Geoms, IkConfig, IkContextValue, IkGizmo, IkGizmoProps, ImagePointCoordinateSpace, ImagePointProjectionOptions, ImagePointProjectionResult, InstancedGeomRenderer, JointStateOptions, JointStateResult, Joints, KeyboardIkTargetConfig, KeyboardTeleopConfig, type MountedCameraFrameCaptureSource, type MountedCameraFrameSequenceCameraOptions, type MountedCameraFrameSequenceDefaults, type MountedCameraFrameSequenceManifest, MountedCameraFrameSequenceManifestStatus, type MountedCameraFrameSequencePlan, type MountedCameraFrameSequencePlanOptions, type MountedCameraFrameSequenceReadiness, MountedCameraFrameSequenceReadinessStatus, type MountedCameraFrameSequenceRecordOptions, type MountedCameraFrameSequenceRecordResult, type MountedCameraFrameSequenceRecorderTarget, type MountedCameraFrameSequenceSourceReadiness, type MountedCameraFrameSequenceStreamSummary, type MountedCameraFrameSourceSuggestion, MountedCameraFrameSourceSuggestionMatch, type MountedCameraSequencePlanOptions, type MountedCameraSequenceReadiness, type MountedCameraSequenceRecordOptions, type MountedCameraSequenceRecordResult, type MountedCameraSequenceRecorderAPI, type MountedPolicyCameraFrameCaptureAPI, type MountedPolicyCameraFrameCaptureOptions, type MountedPolicyCameraTensorOptions, MujocoCanvas, MujocoCanvasProps, MujocoContextValue, MujocoData, type MujocoLoader, type MujocoLoaderOptions, MujocoModel, MujocoModule, MujocoPhysics, type MujocoPhysicsProps, MujocoProvider, type MujocoProviderProps, MujocoSimAPI, MujocoSimProvider, type MujocoWasmVariant, type NamedCameraFrameResource, type NamedObservationField, type NamedObservationHandle, type NamedObservationInput, type NamedObservationLayoutItem, type NamedObservationMissing, type NamedObservationOptions, type NamedObservationResult, ObservationConfig, ObservationHandle, ObservationOutput, ObservationResult, PairedSplatEnvironmentConfig, PhysicsStepCallback, PlaybackState, PolicyAPI, PolicyCameraFrameCaptureAPI, PolicyCameraFrameCaptureOptions, type PolicyCameraFrameCapturePlan, PolicyCameraFrameCaptureResult, type PolicyCameraFrameCaptureTarget, type PolicyCameraFramePlanTarget, PolicyCameraFrameStream, type PolicyCameraFrameStreamOptions, type PolicyCameraTensorStream, type PolicyCameraTensorsAPI, type PolicyCameraTensorsOptions, type PolicyCameraTensorsResult, PolicyConfig, PolicyVector, type PoseReadout, type PoseResourceKind, ReadyCallbackInput, RemotePolicyAPI, RemotePolicyConfig, type ResolveMountedCameraFrameSourceOptions, type ResolvedMountedCameraFrameSource, ScalarJointStateResult, ScenarioLighting, ScenarioLightingPreset, ScenarioLightingProps, SceneConfig, SceneLights, SceneLightsProps, SelectionCallbackInput, SensorHandle, SensorInfo, Sensors, SitePositionResult, Sites, SplatCollisionPrimitive, SplatCollisionProxyConfig, type SplatCollisionProxyGeomPreview, type SplatCollisionProxyGeomsState, SplatCollisionProxyPreview, type SplatCollisionProxyPreviewProps, type SplatCollisionProxyPreviewStatus, type SplatCollisionProxyPreviewVector3, SplatEnvironment, SplatEnvironmentMetadata, SplatEnvironmentMetadataInput, SplatEnvironmentProps, SplatEnvironmentReadiness, SplatEnvironmentReadinessStatus, SplatFormat, SplatRendererKind, SplatSceneConfigInput, SplatSceneConfigState, SplatSceneInput, StepCallbackInput, TendonRenderer, TrajectoryFrame, TrajectoryInput, TrajectoryPlayer, TrajectoryPlayerProps, TrajectoryStateChangeInput, type UseControlGroupOptions, type UseSplatCollisionProxyGeomsOptions, VisualScenarioConfig, VisualScenarioEffects, VisualScenarioEffectsProps, VisualScenarioExecutionContext, VisualScenarioExecutionContextInput, applyPolicyActionToControls, bodyPositionField, buildObservation, canFetchSplatCollisionProxyXml, captureFrame, captureFrameBlob, capturePolicyCameraFrames, capturePolicyCameraFramesFromMountedStreams, clampPolicyActionValue, controlGroup, createContiguousControlGroup, createController, createControllerHook, createMountedCameraFrameSequenceManifest, createMountedCameraFrameSequencePlan, createMountedCameraFrameSequencePlanFromApi, createMountedCameraFrameSequenceReadiness, createMountedCameraFrameSourceSuggestions, createNamedObservationBuilder, createPairedSplatEnvironment, createPolicyCameraFrameCapturePlan, createPolicyCameraFrameCapturePlanFromApi, createSparkSplatViewerUrl, createSplatEnvironmentUserData, createSplatSceneConfig, createVisualScenarioExecutionContext, ctrlField, defineControls, fetchSplatCollisionProxyXml, findActuatorByName, findBodyByName, findGeomByName, findJointByName, findKeyframeByName, findSensorByName, findSiteByName, findTendonByName, geomPositionField, getActuatedJoints, getCameraFrameCaptureSourceTarget, getControlMap, getMountedCameraFrameCaptureSource, getName, getScenarioBackground, getScenarioCameraPosition, getSplatEnvironmentReadiness, imagePointToNdc, isMountedCameraFrameCaptureSource, loadScene, parseSplatCollisionProxyGeoms, projectImagePointTo3D, qposField, qvelField, readNamedObservation, recordMountedCameraFrameSequence, resolveControlGroup, resolveMountedCameraFrameSource, sitePositionField, useActuators, useAfterPhysicsStep, useBeforePhysicsStep, useBodyMeshes, useBodyPose, useBodyState, useCameraAnimation, useCameraFrameCapture, useCameraSequenceRecorder, useCameraStream, useCameraViewport, useContactEvents, useContactHistory, useContacts, useControlGroup, useControlWriter, useControls, useCtrl, useCtrlNoise, useFrameCapture, useGamepad, useGeomPose, useGravityCompensation, useIkController, useJointState, useKeyboardIkTarget, useKeyboardTeleop, useMountedCameraSequenceRecorder, useMujoco, useMujocoWasm, useNamedObservation, useObservation, usePolicy, usePolicyCameraFrames, usePolicyCameraFramesFromMountedStreams, usePolicyCameraTensors, usePolicyCameraTensorsFromMountedStreams, useRemotePolicy, useSceneLights, useSelectionHighlight, useSensor, useSensors, useSitePose, useSitePosition, useSplatCollisionProxyGeoms, useSplatEnvironment, useSplatSceneConfig, useTrajectoryPlayer, useTrajectoryRecorder, useVideoRecorder, useVisualScenarioEffects, useVisualScenarioExecutionContext, withSplatEnvironment };
package/dist/index.js CHANGED
@@ -6759,19 +6759,35 @@ function useControlWriter(options) {
6759
6759
  }
6760
6760
 
6761
6761
  // src/hooks/useControlGroup.ts
6762
+ function objectKeys(value) {
6763
+ return Object.keys(value);
6764
+ }
6765
+ function singleControlValue(name, value) {
6766
+ const values = {};
6767
+ values[name] = value;
6768
+ return values;
6769
+ }
6762
6770
  function controlGroup(names) {
6763
6771
  return { keys: names };
6764
6772
  }
6773
+ function defineControls(controls) {
6774
+ const aliases = objectKeys(controls);
6775
+ return {
6776
+ controls,
6777
+ aliases,
6778
+ keys: aliases.map((alias) => controls[alias])
6779
+ };
6780
+ }
6765
6781
  function useControlGroup(group, options = {}) {
6766
6782
  const generatedOwner = useId();
6767
- const owner = options.owner ?? `control-group:${generatedOwner}`;
6783
+ const owner = options.owner ?? options.label ?? `control-group:${generatedOwner}`;
6768
6784
  const { mjModelRef, mjDataRef, status } = useMujocoContext();
6769
6785
  const names = group.keys;
6770
6786
  const namesRef = useRef(names);
6771
6787
  namesRef.current = names;
6772
6788
  const namesKey = names.join("\0");
6773
6789
  const selector = useMemo(
6774
- () => ({ actuators: [...names] }),
6790
+ () => ({ actuators: names }),
6775
6791
  // eslint-disable-next-line react-hooks/exhaustive-deps
6776
6792
  [namesKey]
6777
6793
  );
@@ -6791,15 +6807,15 @@ function useControlGroup(group, options = {}) {
6791
6807
  return id;
6792
6808
  });
6793
6809
  }, [mjModelRef, status, namesKey]);
6794
- const set = useCallback(
6810
+ const patch = useCallback(
6795
6811
  (values, setOptions = {}) => {
6796
6812
  const data = mjDataRef.current;
6797
6813
  if (!data) return false;
6798
6814
  if (!setOptions.force && !canWrite()) return false;
6799
6815
  const groupNames = namesRef.current;
6800
6816
  const indices = indicesRef.current;
6801
- for (let i = 0; i < groupNames.length; i += 1) {
6802
- const value = values[groupNames[i]];
6817
+ for (const [i, name] of groupNames.entries()) {
6818
+ const value = values[name];
6803
6819
  if (value === void 0) continue;
6804
6820
  const adr = indices[i];
6805
6821
  if (adr >= 0) data.ctrl[adr] = value;
@@ -6808,20 +6824,87 @@ function useControlGroup(group, options = {}) {
6808
6824
  },
6809
6825
  [canWrite, mjDataRef]
6810
6826
  );
6827
+ const write = useCallback(
6828
+ (values, setOptions = {}) => {
6829
+ const data = mjDataRef.current;
6830
+ if (!data) return false;
6831
+ if (!setOptions.force && !canWrite()) return false;
6832
+ const groupNames = namesRef.current;
6833
+ const indices = indicesRef.current;
6834
+ for (let i = 0; i < Math.min(groupNames.length, values.length); i += 1) {
6835
+ const adr = indices[i];
6836
+ if (adr >= 0) data.ctrl[adr] = values[i];
6837
+ }
6838
+ return true;
6839
+ },
6840
+ [canWrite, mjDataRef]
6841
+ );
6842
+ const set = useCallback(
6843
+ (name, value, setOptions) => patch(singleControlValue(name, value), setOptions),
6844
+ [patch]
6845
+ );
6811
6846
  const read = useCallback(() => {
6812
6847
  const data = mjDataRef.current;
6813
6848
  const groupNames = namesRef.current;
6814
6849
  const indices = indicesRef.current;
6815
6850
  const result = {};
6816
- for (let i = 0; i < groupNames.length; i += 1) {
6851
+ for (const [i, name] of groupNames.entries()) {
6817
6852
  const adr = indices[i];
6818
- result[groupNames[i]] = data && adr >= 0 ? data.ctrl[adr] ?? 0 : 0;
6853
+ result[name] = data && adr >= 0 ? data.ctrl[adr] ?? 0 : 0;
6819
6854
  }
6820
6855
  return result;
6821
6856
  }, [mjDataRef]);
6857
+ const get = useCallback((name) => read()[name], [read]);
6822
6858
  return useMemo(
6823
- () => ({ owner, set, read, canWrite, release }),
6824
- [owner, set, read, canWrite, release]
6859
+ () => ({ owner, set, patch, write, get, read, canWrite, release }),
6860
+ [owner, set, patch, write, get, read, canWrite, release]
6861
+ );
6862
+ }
6863
+ function useControls(definition, options = {}) {
6864
+ const group = useControlGroup(controlGroup(definition.keys), options);
6865
+ const controlsRef = useRef(definition.controls);
6866
+ const aliasesRef = useRef(definition.aliases);
6867
+ controlsRef.current = definition.controls;
6868
+ aliasesRef.current = definition.aliases;
6869
+ const set = useCallback(
6870
+ (name, value, setOptions) => group.set(controlsRef.current[name], value, setOptions),
6871
+ [group]
6872
+ );
6873
+ const patch = useCallback(
6874
+ (values, setOptions) => {
6875
+ const next = {};
6876
+ for (const alias of aliasesRef.current) {
6877
+ const value = values[alias];
6878
+ if (value !== void 0) next[controlsRef.current[alias]] = value;
6879
+ }
6880
+ return group.patch(next, setOptions);
6881
+ },
6882
+ [group]
6883
+ );
6884
+ const get = useCallback(
6885
+ (name) => group.get(controlsRef.current[name]),
6886
+ [group]
6887
+ );
6888
+ const read = useCallback(() => {
6889
+ const values = group.read();
6890
+ const result = {};
6891
+ for (const alias of aliasesRef.current) {
6892
+ result[alias] = values[controlsRef.current[alias]] ?? 0;
6893
+ }
6894
+ return result;
6895
+ }, [group]);
6896
+ return useMemo(
6897
+ () => ({
6898
+ owner: group.owner,
6899
+ set,
6900
+ patch,
6901
+ write: group.write,
6902
+ get,
6903
+ read,
6904
+ canWrite: group.canWrite,
6905
+ release: group.release
6906
+ }),
6907
+ [group, set, patch, get, read]
6825
6908
  );
6826
6909
  }
6827
6910
  var geomNameCacheByModel2 = /* @__PURE__ */ new WeakMap();
@@ -8846,6 +8929,6 @@ function useCameraAnimation() {
8846
8929
  * useCameraAnimation — composable camera animation hook.
8847
8930
  */
8848
8931
 
8849
- export { Body, CameraView, ContactListener, ContactMarkers, Debug, DragInteraction, FlexRenderer, GenericIK, IkGizmo, InstancedGeomRenderer, MountedCameraFrameSequenceManifestStatus, MountedCameraFrameSequenceReadinessStatus, MountedCameraFrameSourceSuggestionMatch, MujocoCanvas, MujocoPhysics, MujocoProvider, MujocoSimProvider, SceneLights, SplatCollisionProxyPreview, TendonRenderer, TrajectoryPlayer, applyPolicyActionToControls, bodyPositionField, buildObservation, canFetchSplatCollisionProxyXml, captureFrame, captureFrameBlob, capturePolicyCameraFrames, capturePolicyCameraFramesFromMountedStreams, clampPolicyActionValue, controlGroup, createContiguousControlGroup, createController, createControllerHook, createMountedCameraFrameSequenceManifest, createMountedCameraFrameSequencePlan, createMountedCameraFrameSequencePlanFromApi, createMountedCameraFrameSequenceReadiness, createMountedCameraFrameSourceSuggestions, createNamedObservationBuilder, createPolicyCameraFrameCapturePlan, createPolicyCameraFrameCapturePlanFromApi, ctrlField, fetchSplatCollisionProxyXml, findActuatorByName, findBodyByName, findGeomByName, findJointByName, findKeyframeByName, findSensorByName, findSiteByName, findTendonByName, geomPositionField, getActuatedJoints, getCameraFrameCaptureSourceTarget, getControlMap, getMountedCameraFrameCaptureSource, getName, imagePointToNdc, isMountedCameraFrameCaptureSource, loadScene, parseSplatCollisionProxyGeoms, projectImagePointTo3D, qposField, qvelField, readNamedObservation, recordMountedCameraFrameSequence, resolveControlGroup, resolveMountedCameraFrameSource, sitePositionField, useActuators, useAfterPhysicsStep, useBeforePhysicsStep, useBodyMeshes, useBodyPose, useBodyState, useCameraAnimation, useCameraFrameCapture, useCameraSequenceRecorder, useCameraStream, useCameraViewport, useContactEvents, useContactHistory, useContacts, useControlGroup, useControlWriter, useCtrl, useCtrlNoise, useFrameCapture, useGamepad, useGeomPose, useGravityCompensation, useIkController, useJointState, useKeyboardIkTarget, useKeyboardTeleop, useMountedCameraSequenceRecorder, useMujoco, useMujocoWasm, useNamedObservation, useObservation, usePolicy, usePolicyCameraFrames, usePolicyCameraFramesFromMountedStreams, usePolicyCameraTensors, usePolicyCameraTensorsFromMountedStreams, useRemotePolicy, useSceneLights, useSelectionHighlight, useSensor, useSensors, useSitePose, useSitePosition, useSplatCollisionProxyGeoms, useTrajectoryPlayer, useTrajectoryRecorder, useVideoRecorder };
8932
+ export { Body, CameraView, ContactListener, ContactMarkers, Debug, DragInteraction, FlexRenderer, GenericIK, IkGizmo, InstancedGeomRenderer, MountedCameraFrameSequenceManifestStatus, MountedCameraFrameSequenceReadinessStatus, MountedCameraFrameSourceSuggestionMatch, MujocoCanvas, MujocoPhysics, MujocoProvider, MujocoSimProvider, SceneLights, SplatCollisionProxyPreview, TendonRenderer, TrajectoryPlayer, applyPolicyActionToControls, bodyPositionField, buildObservation, canFetchSplatCollisionProxyXml, captureFrame, captureFrameBlob, capturePolicyCameraFrames, capturePolicyCameraFramesFromMountedStreams, clampPolicyActionValue, controlGroup, createContiguousControlGroup, createController, createControllerHook, createMountedCameraFrameSequenceManifest, createMountedCameraFrameSequencePlan, createMountedCameraFrameSequencePlanFromApi, createMountedCameraFrameSequenceReadiness, createMountedCameraFrameSourceSuggestions, createNamedObservationBuilder, createPolicyCameraFrameCapturePlan, createPolicyCameraFrameCapturePlanFromApi, ctrlField, defineControls, fetchSplatCollisionProxyXml, findActuatorByName, findBodyByName, findGeomByName, findJointByName, findKeyframeByName, findSensorByName, findSiteByName, findTendonByName, geomPositionField, getActuatedJoints, getCameraFrameCaptureSourceTarget, getControlMap, getMountedCameraFrameCaptureSource, getName, imagePointToNdc, isMountedCameraFrameCaptureSource, loadScene, parseSplatCollisionProxyGeoms, projectImagePointTo3D, qposField, qvelField, readNamedObservation, recordMountedCameraFrameSequence, resolveControlGroup, resolveMountedCameraFrameSource, sitePositionField, useActuators, useAfterPhysicsStep, useBeforePhysicsStep, useBodyMeshes, useBodyPose, useBodyState, useCameraAnimation, useCameraFrameCapture, useCameraSequenceRecorder, useCameraStream, useCameraViewport, useContactEvents, useContactHistory, useContacts, useControlGroup, useControlWriter, useControls, useCtrl, useCtrlNoise, useFrameCapture, useGamepad, useGeomPose, useGravityCompensation, useIkController, useJointState, useKeyboardIkTarget, useKeyboardTeleop, useMountedCameraSequenceRecorder, useMujoco, useMujocoWasm, useNamedObservation, useObservation, usePolicy, usePolicyCameraFrames, usePolicyCameraFramesFromMountedStreams, usePolicyCameraTensors, usePolicyCameraTensorsFromMountedStreams, useRemotePolicy, useSceneLights, useSelectionHighlight, useSensor, useSensors, useSitePose, useSitePosition, useSplatCollisionProxyGeoms, useTrajectoryPlayer, useTrajectoryRecorder, useVideoRecorder };
8850
8933
  //# sourceMappingURL=index.js.map
8851
8934
  //# sourceMappingURL=index.js.map