Gymnasium adapter

Runs a Gymnasium environment loop and packs the result into RoboTrace artifacts (sensors.npz, actions.npz, optional video.mp4). This is the first runtime adapter - unlike ROS 2 or LeRobot, there is no on-disk format to import. You pass a live env and a policy callable.

import gymnasium as gym
from robotrace.adapters import gymnasium as rt_gym
 
env = gym.make("CartPole-v1", render_mode="rgb_array")
 
rt_gym.upload_rollout(
    env,
    policy=lambda obs, info: 1,
    policy_version="cartpole-v1",
    env_version="cartpole-v1",
    seed=42,
)

MuJoCo and other sims work through Gymnasium env ids once you install their optional deps (gymnasium[mujoco], etc.) - no separate MuJoCo adapter is required for most teams.

Install

# Observations + actions only (no video).
pip install 'robotrace-dev[gymnasium]==0.1.0a11'
 
# With env.render() → MP4 encoding.
pip install 'robotrace-dev[gymnasium,video]==0.1.0a11'

[gymnasium] pulls in gymnasium and numpy. [video] adds opencv-python for mp4 encoding from env.render().

Classic-control envs like CartPole also need pygame for rendering:

pip install 'gymnasium[classic-control]'

The three verbs

VerbWhat it does
gymnasium.scan_env(env)Read-only introspection. Returns an EnvSummary with space shapes, render modes, and whether video recording is possible. No rollout, no network.
gymnasium.encode_rollout(env, out, policy=...)Runs one episode, writes artifacts into out. Returns an EncodedRollout. No network.
gymnasium.upload_rollout(env, policy=...)One-shot: rollout → encode to a tempdir → start_episode + upload_* + finalize. Returns the finalized Episode.

Start with scan_env to confirm spaces and render capability before uploading:

summary = rt_gym.scan_env(env)
print(summary.report())
# CartPole-v1
#   observation_space: Box(4,)
#   action_space: Discrete()
#   active_render_mode: rgb_array
#   video: yes (env.render() → mp4, needs [video] extra)

Policy callable

The adapter expects a standard Gymnasium policy:

def my_policy(obs, info):
    # obs shape matches env.observation_space
    # return an action valid for env.action_space
    return env.action_space.sample()

Pass it to encode_rollout or upload_rollout:

rt_gym.upload_rollout(
    env,
    policy=my_policy,
    policy_version="pick-v3",
    env_version="warehouse-v2",
    git_sha="abc1234",
    seed=8124,
)

Video from env.render()

Video comes from env.render() only. Create the env with render_mode="rgb_array":

env = gym.make("HalfCheetah-v4", render_mode="rgb_array")

Pass record_video=False to skip mp4 encoding and log sensors/actions only. When record_video=True (the default when render_mode is rgb_array), the adapter requires the [video] extra.

NPZ layout

Observations land in sensors.npz, actions in actions.npz, using the same namespaced layout as the ROS 2 and LeRobot adapters:

observation/value          float32[T, obs_dim]   # Box observation
observation.state/value    float32[T, K]         # Dict observation key
action/value               float32[T, action_dim]
observation/_t_ns          int64[T]              # synthetic step clock

Timestamps are derived from step index and fps (default 30). Real-time sim drift is not captured in v1.

Episode metadata

The encoder merges Gymnasium run facts into episode metadata:

{
  "adapter": "gymnasium",
  "gymnasium_env_id": "CartPole-v1",
  "total_reward": 200.0,
  "steps": 200,
  "terminated": true,
  "truncated": false,
  "render_mode": "rgb_array"
}

Reproducibility fields (policy_version, env_version, git_sha, seed) come from the caller, same as other adapters.

Supported spaces (v1)

Box, Discrete, MultiDiscrete, MultiBinary, Dict, and Tuple observation and action spaces. Exotic spaces (Graph, Sequence, …) raise ConfigurationError with the unsupported type name.

Defaults

ParameterDefault
source"sim"
max_steps10000
fps30
record_videoTrue when render_mode="rgb_array", else False

Roadmap

Not yet shipped:

  • record() context manager for mid-training logging
  • upload_rollouts() batch helper for RL training loops
  • Observation-image fallback when render is unavailable

See also: log_episode for raw NumPy logging, ROS 2 adapter, LeRobot adapter.