Skip to main content
Record simulation trajectories (qpos, qvel, ctrl, sensordata) for playback, analysis, or export.

Signature

useTrajectoryRecorder(options?: {
  fields?: ("qpos" | "qvel" | "ctrl" | "sensordata")[];
}): {
  start: () => void;
  stop: () => TrajectoryFrame[];
  recording: boolean;
  frameCount: number;
  frames: TrajectoryFrame[];
  downloadJSON: () => void;
  downloadCSV: () => void;
}

Usage

import { useTrajectoryRecorder } from "mujoco-react";

function RecordButton() {
  const recorder = useTrajectoryRecorder({
    fields: ["qpos", "qvel", "ctrl"],
  });

  return (
    <div>
      {recorder.recording ? (
        <button onClick={() => {
          const frames = recorder.stop();
          console.log(`Recorded ${frames.length} frames`);
        }}>
          Stop ({recorder.frameCount} frames)
        </button>
      ) : (
        <button onClick={recorder.start}>Record</button>
      )}
      <button onClick={recorder.downloadJSON}>Export JSON</button>
      <button onClick={recorder.downloadCSV}>Export CSV</button>
    </div>
  );
}

Options

FieldTypeDefaultDescription
fieldsstring[]['qpos', 'qvel', 'ctrl', 'sensordata']Which fields to record each frame

Return Value

FieldTypeDescription
start() => voidBegin recording
stop() => TrajectoryFrame[]Stop recording and return frames
recordingbooleanWhether currently recording
frameCountnumberNumber of frames recorded so far
framesTrajectoryFrame[]Recorded frames (grows during recording)
downloadJSON() => voidDownload trajectory as JSON file
downloadCSV() => voidDownload qpos as CSV file

TrajectoryFrame

interface TrajectoryFrame {
  time: number;
  qpos: Float64Array;
  qvel?: Float64Array;
  ctrl?: Float64Array;
  sensordata?: Float64Array;
}

Notes

  • Recording happens in useAfterPhysicsStep — one frame per physics step
  • Each frame is a snapshot (arrays are copied, not referenced)
  • JSON export includes all recorded fields; CSV includes qpos only
  • For playback, pass recorder.frames directly to useTrajectoryPlayer or <TrajectoryPlayer> — no format conversion needed