File writers#

A file writer records sampled data to disk. Pass one as the rec_options argument of scene.add_recorder, and the recorder manager samples your data function on schedule and writes each sample to the file. See Recording and playback for the recording workflow and the shared options (hz, buffer_size, save_on_reset) that every writer inherits.

gs.recorders.NPZFile#

Writes samples to a NumPy .npz archive. Best for numeric arrays you load back with numpy.load.

class genesis.options.recorders.NPZFile(*, hz: float | None = None, buffer_size: int = 0, buffer_full_wait_time: float = 0.1, filename: str) None[source]#

Buffers all data and writes to a .npz file at cleanup.

Can handle any numeric or array-like or dict[str, array-like] data, e.g. from sensors.

Parameters:

filename (str) – The name of the .npz file to save the data.

class genesis.recorders.file_writers.NPZFileWriter(manager: RecorderManager, options: RecorderOptions, data_func: Callable[[], T])[source]#

Bases: BaseFileWriter

build()[source]#

Build the recorder, e.g. by initializing variables and creating widgets or file handles.

process(data, cur_time)[source]#

Process each incoming data sample.

Parameters:
  • data (Any) – The data to be processed.

  • cur_time (float) – The current time of the simulation.

cleanup()[source]#

Cleanup all resources, e.g. by closing widgets or files.

This method is called when recording is stopped by scene.stop_recording().

property run_in_thread: bool#

Whether to run the recorder in a background thread.

Running in a background thread allows for processing data without blocking the main thread, so this is encouraged for most recorders (simply return True), but implementers should check that the recorder is thread-safe on all devices (threading on macOS tends to be less supported).

gs.recorders.CSVFile#

Writes samples as rows in a .csv file. Best for scalar or low-dimensional data you inspect in a spreadsheet.

class genesis.options.recorders.CSVFile(*, hz: float | None = None, buffer_size: int = 0, buffer_full_wait_time: float = 0.1, filename: str, header: tuple[str, ...] | None = None, save_every_write: bool = False) None[source]#

Writes to a .csv file using csv.writer.

Can handle any array-like or dict[str, array-like] output, e.g. from sensors. Values must be N-dimensional tensors, arrays or scalars (np.generic, int, float, str) If the data or header is a dict, it cannot be further nested. Values are processed in order.

Parameters:
  • filename (str) – The name of the CSV file to save the data.

  • header (tuple[str] | None, optional) – Column headers for the CSV file. It should match the format of the incoming data, where each scalar value has an associated header. If the data is a dict, the header should match the total length of the number of values after flattening the values.

  • save_every_write (bool, optional) – Whether to flush the data to disk as soon as new data is recieved. Defaults to False.

class genesis.recorders.file_writers.CSVFileWriter(manager: RecorderManager, options: RecorderOptions, data_func: Callable[[], T])[source]#

Bases: BaseFileWriter

process(data, cur_time)[source]#

Process each incoming data sample.

Parameters:
  • data (Any) – The data to be processed.

  • cur_time (float) – The current time of the simulation.

cleanup()[source]#

Cleanup all resources, e.g. by closing widgets or files.

This method is called when recording is stopped by scene.stop_recording().

property run_in_thread: bool#

Whether to run the recorder in a background thread.

Running in a background thread allows for processing data without blocking the main thread, so this is encouraged for most recorders (simply return True), but implementers should check that the recorder is thread-safe on all devices (threading on macOS tends to be less supported).

gs.recorders.VideoFile#

Encodes a stream of image frames to a video file. Pair it with a data function that returns a rendered frame.

class genesis.options.recorders.VideoFile(*, hz: float | None = None, buffer_size: int = 0, buffer_full_wait_time: float = 0.1, filename: str, fps: int | None = None, name: str = '', codec: str = '', bitrate: float = 1.0, codec_options: dict[str, str] = <factory>) None[source]#

Stream video frames to file using PyAV.

The PyAV writer streams data directly to the file instead of buffering it in memory. Incoming data should either be grayscale [H, W] or color [H, W, RGB] where values are uint8 (0, 255).

Parameters:
  • filename (str) – The path of the output video file ending in “.mp4”.

  • name (str) – The name of the video. Note that it may be different from filename. If empty, then filename will be used as a fallback. Default to “”.

  • fps (int, optional) – Frames per second for the video. Defaults to the data collection Hz (“real-time”).

  • codec (str, optional) – The codec to use for the video file. Defaults to “libx264”.

  • bitrate (float) – The bitrate of the video. This higher the better the quality of the video. Defaults to 1.0.

  • codec_options (dict[str, str]) – Additional low-level codec options that will be pass to ffmpeg. Empty by default.

class genesis.recorders.file_writers.VideoFileWriter(manager: RecorderManager, options: RecorderOptions, data_func: Callable[[], T])[source]#

Bases: BaseFileWriter

encoder: VideoEncoder | None#
build()[source]#

Build the recorder, e.g. by initializing variables and creating widgets or file handles.

process(data, cur_time)[source]#

Process each incoming data sample.

Parameters:
  • data (Any) – The data to be processed.

  • cur_time (float) – The current time of the simulation.

cleanup()[source]#

Cleanup all resources, e.g. by closing widgets or files.

This method is called when recording is stopped by scene.stop_recording().

property run_in_thread: bool#

Whether to run the recorder in a background thread.

Running in a background thread allows for processing data without blocking the main thread, so this is encouraged for most recorders (simply return True), but implementers should check that the recorder is thread-safe on all devices (threading on macOS tends to be less supported).

gs.recorders.TrajectoryFile#

Records the state of the scene itself, one frame per step, to a .gstraj file. Register it with scene.start_recording, which takes the options alone since the scene is the data source, and open the file with gs.Scene.load_trajectory to seek and replay it. See Checkpoints and simulation state for the workflow.

class genesis.options.recorders.TrajectoryFile(*, hz: float | None = None, buffer_size: int = 0, buffer_full_wait_time: float = 0.1, filename: str, exact: bool | None = None, chunk_size: int = 64, max_size: int | None = 2147483648) None[source]#

Record the scene state at every sampled step into a ‘.gstraj’ file, which ‘Scene.load_trajectory’ opens to seek and replay. Recording starts with the build and stops with ‘Scene.stop_recording’.

The file contains the scene as ‘Scene.export’ writes it, then one frame per sampled step, the last being the state the recording stopped at. Every frame is kept: the recorder runs on the stepping thread and compresses and writes each completed chunk on a thread of its own while the simulation steps on. A chunk waits for the write of the previous one, so recording slows the simulation only when the disk cannot keep up, and a crash keeps every completed chunk.

Exact mode records everything a step reads or writes: replay is bit-for-bit and the simulation resumes from any frame. Compressed mode records the model parameters, configuration, velocities, accelerations, control inputs, contacts and constraint forces. Its file is several times smaller, which matters for batched scenes, and a load recomputes the poses of links and geoms, which may differ at the last bits.

Parameters:
  • filename (str) – The ‘.gstraj’ file to write.

  • exact (bool, optional) – Whether to record in exact mode. If None, resolved based on the number of environments: exact for a single environment, compressed for a batched scene, with a warning. Defaults to None.

  • chunk_size (int, optional) – Frames per chunk. Larger chunks compress better and seek slower, and a crash loses at most one. Defaults to 64.

  • max_size (int, optional) – Bytes the file may grow to. A record that would pass it is dropped, the file is closed as a valid log, and the next step raises, so a run left recording fills the disk by at most this much. Raise it for a long run whose size is planned. If None, the file grows with the run. Defaults to 2 GiB.

class genesis.recorders.trajectory.TrajectoryFileWriter(manager: RecorderManager, options: RecorderOptions, data_func: Callable[[], T])[source]#

Bases: BaseFileWriter

Write the frames of a scene to a trajectory file (see TrajectoryFile), one chunk at a time.

Each frame captures the state a step starts from, control inputs included, since it is read before the step. Within a chunk the writer stores each frame as its XOR with the previous frame. Unchanged bytes thus become zeros for zlib to remove, and an unchanged info array costs nothing. The frames are appended on the stepping thread; a completed chunk is compressed and written by a thread of its own, one chunk in flight at a time, so memory use is the open chunk and the one being written, whatever the file size.

build()[source]#

Build the recorder, e.g. by initializing variables and creating widgets or file handles.

step(global_step: int)[source]#

Record the step when the sampling rate selects it, raising what the background thread reported.

process(data, cur_time)[source]#

Process each incoming data sample.

Parameters:
  • data (Any) – The data to be processed.

  • cur_time (float) – The current time of the simulation.

cleanup()[source]#

Cleanup all resources, e.g. by closing widgets or files.

This method is called when recording is stopped by scene.stop_recording().

property run_in_thread: bool#

Whether to run the recorder in a background thread.

Running in a background thread allows for processing data without blocking the main thread, so this is encouraged for most recorders (simply return True), but implementers should check that the recorder is thread-safe on all devices (threading on macOS tends to be less supported).

class genesis.recorders.trajectory.Trajectory(path: str | PathLike, scene: Scene | None = None, show_viewer: bool = False, viewer_options: ViewerOptions | None = None, vis_options: VisOptions | None = None, renderer: RendererOptions | None = None)[source]#

A recorded trajectory and the built scene it plays in (see ‘Scene.load_trajectory’).

Frame i is the state the scene stood in after i steps, and the last frame is the state the recording stopped at, whole: every array but the static configs and constants (see CHECKPOINT_FILE_KINDS).

Parameters:
  • path (str or os.PathLike) – The file to read, as written by recording with ‘TrajectoryFile’ or by ‘Scene.save_checkpoint’.

  • scene (Scene, optional) – A built scene to play the trajectory in, from the same description and environment layout as the recorded one. If None, the recorded scene is created and built. Defaults to None.

  • show_viewer (bool, optional) – Whether the created scene opens an interactive viewer. Defaults to False.

  • viewer_options (ViewerOptions, optional) – Viewer options replacing the recorded ones in the created scene. If None, the recorded ones stand.

  • vis_options (VisOptions, optional) – Visualizer options replacing the recorded ones in the created scene. If None, the recorded ones stand.

  • renderer (RendererOptions, optional) – Renderer replacing the recorded one in the created scene. If None, the recorded one stands.

property scene: Scene#

The built scene the trajectory plays in.

property is_exact: bool#

Whether the frames hold everything a step reads or writes, or the state alone (see TrajectoryFile).

property n_envs: int#

The number of environments the scene was recorded with.

frame(index: int, kinds: frozenset[genesis.utils.array_class.DataKind] = frozenset({DataKind.CONFIG, DataKind.CONSTANT, DataKind.INFO, DataKind.STATE, DataKind.WARMSTART, DataKind.DERIVED, DataKind.SCRATCH})) dict[str, numpy.ndarray][source]#

Return the arrays of frame ‘index’ of the given kinds by name, shaped as the scene holds them. A negative ‘index’ counts from the end.

time(index: int) ndarray[source]#

The simulated time of each environment at frame ‘index’, in seconds, as ‘Scene.get_time’ reports it.

seek(index: int) None[source]#

Put the scene in the state of frame ‘index’, counted from the end when negative.

An exact frame puts back everything a step reads or writes, so the scene steps on from there bit-for-bit. A compressed frame puts back the state and recomputes the link and geom poses by forward kinematics. The scratch a checkpoint file also holds is for inspection: its shape follows the backend of the recording.

play(loop: bool = False) None[source]#

Seek every frame in turn, which redraws the scene at each and plays the run in the viewer at its pace.

With ‘loop’, the run starts over until the interactive viewer is closed, so the scene must have one.

See also#