Showcase
Architecture
Unlike Python Gymnasium, gymnasia separates simulation from rendering and uses pure-Rust dependencies only — no C bindings, no SDL2, no system library installation.
| Layer | What it does | Feature gate |
|---|---|---|
Env trait |
Pure physics — step(), reset() |
Always compiled |
Renderable trait |
Produces a DrawList (backend-agnostic draw commands) |
Always compiled |
Wrapper trait |
Composable behavior wrappers (TimeLimit, NormalizeObservation, etc.) |
Always compiled |
Screen |
Translates DrawList into graphics calls (macroquad) |
render feature |
RenderEnv<E> |
Wraps Env + Renderable with a Screen — implements Env |
render feature |
Design decisions
Envhas zero supertraits — noClone + Debug + Serialize. Wrappers with closures work.- Wrappers own their data — no info dict.
RecordEpisodeStatisticsexposesepisode_return(),TimeLimitexposessteps_remaining(). BoxSpace<B: Bounded>— generic over the bounds representation. ImplementBoundedon your own types.Flattenis opt-in — bidirectionalflatten()/unflatten()for ML pipelines. Not required byEnv.StepResultusesf64reward —O64stays internal.
Quick Start
Headless by default — no graphics dependencies. To enable rendering:
Development
Headless
use Env;
use CartPoleEnv;
let mut env = new;
env.reset;
let result = env.step; // 0 = left, 1 = right
println!;
With wrappers
use Env;
use CartPoleEnv;
use ;
let env = new;
let env = new;
let mut env = new;
// Type: RecordEpisodeStatistics<TimeLimit<CartPoleEnv>>
let obs = env.reset;
let result = env.step;
// Typed access to wrapper data:
println!;
println!;
Flatten for ML
use ;
use CartPoleEnv;
let mut env = new;
let obs = env.reset;
let flat: = obs.flatten; // [x, x_dot, theta, theta_dot]
assert_eq!;
With rendering
use Env;
use ;
use CartPoleEnv;
async
Custom environment
use ;
use ;
// 1. Define your observation type
// 2. Implement Bounded so it works with BoxSpace
// 3. Implement Env
Full API documentation is available on docs.rs.
Wrappers
Wrappers are generic structs that implement Env by delegating to an inner environment. Stack them to compose behaviors:
| Wrapper | Category | What it does |
|---|---|---|
TimeLimit |
Common | Truncates after N steps |
OrderEnforcing |
Common | Panics if step() before reset() |
Autoreset |
Common | Auto-resets on termination |
RecordEpisodeStatistics |
Common | Tracks cumulative reward and episode length |
ClipReward |
Reward | Clamps reward to [min, max] |
NormalizeReward |
Reward | Running mean/variance normalization |
TransformReward |
Reward | Apply custom Fn(f64) -> f64 |
ClipAction |
Action | Clamps to action space bounds |
RescaleAction |
Action | Affine rescaling of f64 actions |
TransformAction |
Action | Apply custom function, may change type |
FlattenObservation |
Observation | Flattens via Flatten trait to Vec<f64> |
NormalizeObservation |
Observation | Running mean/variance normalization |
TransformObservation |
Observation | Apply custom function, may change type |
Wrappers that track metadata expose it via typed methods on the wrapper itself — there is no dynamic info dict.
Spaces
| Space | Element | Description |
|---|---|---|
BoxSpace<B: Bounded> |
B |
Continuous bounded space. Generic over bounds type. |
Discrete |
i64 |
{start, ..., start+n-1}. Supports action masking. |
MultiDiscrete |
Vec<i64> |
Cartesian product of discrete spaces. |
MultiBinary |
Vec<u8> |
{0, 1}^n. |
Implement Bounded on any type to use it with BoxSpace. We ship implementations for f64, f32, and Tensor (flat Vec<f64> with shape metadata for high-dimensional spaces like images).
Feature Flags
| Feature | Default | Description |
|---|---|---|
render |
No | macroquad-based window rendering and pixel capture |
Benchmarks
| Benchmark | Time (median) |
|---|---|
cartpole/step |
~26 ns |
cartpole/reset |
~21 ns |
cartpole/episode |
~248 ns |
mountain_car/step |
~25 ns |
mountain_car/reset |
~15 ns |
mountain_car/episode |
~4.6 us |
Apple M3 Pro —
cargo benchvia Criterion. Runcargo benchto reproduce.
Migrating from v2
See CHANGELOG.md for the full list. Key changes:
| v2 | v3 |
|---|---|
ActionReward<T, E> |
StepResult<O> |
reward: O64 |
reward: f64 |
info: Option<E> |
removed — wrappers own their data |
reset(seed, return_info, options) |
reset(seed, options) returns Observation |
BoxR<T> |
BoxSpace<B: Bounded> |
Observation: Into<Vec<f64>> required |
Flatten trait (opt-in) |
Clone + Debug + Serialize on Env |
no supertraits |
Discrete(usize) |
Discrete { n, start } with i64 element |
DiscreteRange |
merged into Discrete::with_start() |
RenderEnv doesn't impl Env |
RenderEnv implements Env |
| No wrappers | 13 composable wrappers |
use gymnasia::render::RenderEnv |
use gymnasia::render::RenderEnv |
use gymnasia::utils::renderer::RenderMode |
use gymnasia::render::renderer::RenderMode |
History
Gymnasia is a fork of MathisWellmann/gym-rs, which is no longer actively maintained. OpenAI Gym itself has since evolved into Gymnasium — gymnasia tracks that direction for Rust. See docs/roadmap.md for feature parity status.
Contributing
Contributions are welcome. See CONTRIBUTING.md for guidelines.
Agent Skill
This repo's conventions are available as portable agent skills in skills/.
License
Licensed under Apache 2.0.