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
| Verb | What 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 clockTimestamps 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
| Parameter | Default |
|---|---|
source | "sim" |
max_steps | 10000 |
fps | 30 |
record_video | True when render_mode="rgb_array", else False |
Roadmap
Not yet shipped:
record()context manager for mid-training loggingupload_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.