Skip to main content
Provides handle-based read/write access to a single actuator’s control value by name.

Signature

useCtrl(name: Actuators): CtrlHandle

Usage

import { useCtrl } from "mujoco-react";

function GripperControl() {
  const gripper = useCtrl("gripper");

  return (
    <div>
      <button onClick={() => gripper.write(0.04)}>Open</button>
      <button onClick={() => gripper.write(0.0)}>Close</button>
    </div>
  );
}

Reading in useFrame

function GripperDisplay() {
  const gripper = useCtrl("gripper");
  const textRef = useRef<any>(null);

  useFrame(() => {
    if (textRef.current) {
      textRef.current.text = `Gripper: ${gripper.read().toFixed(3)}`;
    }
  });

  return <Text ref={textRef} position={[0, 0.5, 0]} />;
}

Inside useBeforePhysicsStep

function MyController() {
  const shoulder = useCtrl("shoulder");
  const elbow = useCtrl("elbow");
  const force = useSensor("force_sensor");

  useBeforePhysicsStep(() => {
    shoulder.write(Math.sin(Date.now() / 1000));
    elbow.write(force.read()[0] * -0.5);
  });
  return null;
}

Return Value

interface CtrlHandle {
  read(): number;
  write(value: number): void;
  name: Actuators;
  range: [number, number];
}
FieldTypeDescription
read()() => numberRead the current control value from data.ctrl
write()(v: number) => voidWrite a control value directly to data.ctrl
nameActuatorsActuator name
range[number, number]Control range [min, max] from actuator_ctrlrange

Notes

  • read() and write() operate directly on data.ctrl — no re-renders
  • For setting multiple actuators at once, use api.setCtrl({ name: value, ... })
  • The actuator index is resolved once on mount
  • The name parameter accepts string by default, or a union type if you’ve declared a Register augmentation