Env & EnvGroup¶
Env and EnvGroup are the components responsible for managing environment interactions in RLightning. Env provides a unified interface to different simulation backends (MuJoCo, ManiSkill, Isaac Sim, real robots, etc.), while EnvGroup manages multiple Env instances as a single unit for batched, parallel data collection.
A typical interaction cycle works as follows:
Environments are initialized and reset to produce initial observations (
EnvRet).Policy workers receive observations and produce actions (
PolicyResponse).EnvGroup distributes actions to each Env, which steps the underlying simulator.
EnvGroup collects the results and returns them as batched data (
BatchedData).The cycle repeats; collected data flows to the Data Buffer for training.
Env¶
Env is a unified wrapper around different simulation backends. All
implementations inherit from BaseEnv and expose the same step() /
reset() interface regardless of the underlying simulator.
flowchart TB
Base["BaseEnv"] --> Mujoco["MujocoEnv"]
Base --> Maniskill["ManiskillEnv"]
Base --> ALE["ALEEnv"]
Base --> Isaac["IsaacEnv"]
Base --> Custom["YourCustomEnv"]
Data Interface
The step() method follows a consistent flow across all backends:
Input: receives a
PolicyResponseobject.Preprocessing: extracts the
actionfrom thePolicyResponsevia a configurable preprocessing function.Backend execution: passes the action to the simulator’s native
step()method.Output: wraps the results (observation, reward, terminated, truncated, info) as an
EnvRetobject and returns it.
Users can implement custom environments by subclassing BaseEnv and
implementing reset() and step().
Built-in Backends
Backend |
Description |
|---|---|
|
MuJoCo physics environments (Ant, HalfCheetah, Hopper, Humanoid, etc.) |
|
ManiSkill manipulation environments (supports vectorized envs) |
|
Arcade Learning Environment (Atari games) |
|
NVIDIA Isaac Sim environments (supports vectorized envs) |
|
NVIDIA Isaac Lab MARL-style environments (supports vectorized envs) |
|
Piper real robot environments |
|
Remote environment via ZMQ (for distributed setups) |
EnvGroup¶
EnvGroup manages multiple Env instances as a single unit. Users interact with EnvGroup rather than individual Envs — it handles batching, dispatching, and result collection.
flowchart TB
EG["EnvGroup"] --> E1["Env 1"]
EG --> E2["Env 2"]
EG --> E3["..."]
EG --> EN["Env n"]
EnvGroup supports two stepping modes:
Synchronous:
step()— blocks until all environments return.Asynchronous:
step_async()+collect_async()— non-blocking, returns results as they become available.
Design Highlights¶
Standardized interface — All environments expose the same
step()andreset()interface with unified input (PolicyResponse) and output (EnvRet), regardless of whether the underlying backend is MuJoCo, ManiSkill, Isaac Sim, or a real robot.Backend abstraction — Switching between simulation backends, or between simulation and real hardware, requires only a configuration change. Your training loop code stays the same.
Batched execution — EnvGroup provides a unified
stepinterface for parallel interaction with multiple environments. You interact with EnvGroup as if it were a single environment.Asynchronous stepping —
step_asyncandcollect_asyncseparate environment computation from result collection, enabling overlap between environment steps and policy inference to maximize throughput.Automatic reset — The
auto_resetcontext manager automatically resets environments when they reach a maximum step count, simplifying control flow in multi-environment rollout loops.
Configuration¶
The environment is configured through the envs section of the
experiment configuration file. Each item in the list defines one type of
environment.
envs:
- name: "halfcheetah"
backend: "mujoco"
task: "HalfCheetah-v5"
num_workers: 4
The full set of configuration fields is described below.
name(str) [required]A user-defined name for this environment entry. Recommended format:
backend_task.backend(str) [required]Simulator backend type. Supported values:
"mujoco","maniskill","ale","isaac_manager_based","isaac_marl","piper","env_server".task(str) [required]Task or environment name within the backend (e.g.,
"HalfCheetah-v5","StackCube-v1").num_workers(int)Number of independent environment worker instances to create. In distributed mode each worker runs as a separate Ray actor with its own process and resource allocation. Defaults to
1.num_envs(int)Number of vectorized sub-environments within each worker instance. Only supported by
maniskill,isaac_manager_based, andisaac_marl. Defaults to1.max_episode_steps(int | None)Maximum steps per episode. Used by the
auto_resetcontext manager. Defaults toNone(no limit).num_cpus(int)CPUs allocated per environment worker (remote execution only). Defaults to
1.num_gpus(float)GPUs allocated per environment worker (remote execution only). Defaults to
0.0.env_kwargs(dict)Backend-specific configuration passed to the environment constructor.
Multi-task example
Multiple environment types can be combined for multi-task training:
envs:
- name: "stack_cube_task"
backend: "maniskill"
task: "StackCube-v1"
num_workers: 2
num_envs: 1
max_episode_steps: 100
- name: "pick_cube_task"
backend: "maniskill"
task: "PickCube-v1"
num_workers: 1
num_envs: 2
max_episode_steps: 50
num_gpus: 0.1
Note
In this configuration, EnvGroup creates 3 independent worker instances
in total (num_workers sum: 2 + 1). Each instance is assigned a unique
identifier at initialization. num_envs defines the number of
vectorized sub-environments within each worker instance.
Usage¶
Creating an EnvGroup¶
Use build_env_group to create an EnvGroup from configuration:
from rlightning.env import build_env_group
env_group = build_env_group(config.envs, preprocess_fn=env_preprocess_fn)
The preprocess_fn parameter controls how PolicyResponse is
converted to an action before being passed to the simulator:
Default (
default_env_preprocess_fn): extracts theactionfield from thePolicyResponse.Single function: applied to all Env instances.
List of functions: one per Env instance (must match the total number of environments).
Initializing¶
env_metas = env_group.init()
init() initializes all Env instances and returns a list of EnvMeta
objects, each containing env_id, observation_space,
action_space, and num_envs. For consistency checks, the current
implementation validates only action_space shape compatibility.
Synchronous Step & Reset¶
The standard synchronous loop resets all environments, then alternates between policy rollout and environment stepping:
batched_env_ret, _ = env_group.reset(seed=0)
for _ in range(max_rollout_steps):
batched_policy_resp = policy_group.rollout_batch(batched_env_ret)
buffer.add_batched_transition(batched_env_ret, batched_policy_resp)
batched_env_ret, _ = env_group.step(batched_policy_resp)
reset()resets all environments and returns(BatchedData, truncations).step()dispatches eachPolicyResponseto its corresponding Env byenv_idand returns(BatchedData, truncations). Each Env instance is assigned a unique identifier (UUID + worker index) at initialization.reset(seed=...)accepts anintseed (for example,seed=0).reset()always returnsList[bool]fortruncations(default allFalse).step()returnsNonefortruncationsoutsideauto_reset; insideauto_resetit returnsList[bool].
Asynchronous Step & Reset¶
Asynchronous stepping separates triggering environment computation from collecting results:
env_group.step_async(batched_policy_resp)
batched_env_ret, truncations = env_group.collect_async()
step_async()triggers environment steps without blocking.collect_async()returns results from environments that have finished, blocks until at least one result is ready, then returns available results.collect_async(timeout=0.1)usestimeoutas an additional collection window after the first ready result arrives, to gather more completed results.collect_async(wait_all=True)blocks until all environments finish.
Tip
Async stepping avoids idle time. Policy inference can begin as soon as any environment returns, rather than waiting for all environments to finish.
Auto Reset¶
with env_group.auto_reset(max_episode_steps=100):
for _ in range(total_steps):
env_group.step_async(batched_policy_resp)
batched_env_ret, truncations = env_group.collect_async()
# truncations indicates which environments were auto-reset
Context manager that auto-resets environments reaching the maximum step count.
max_episode_stepsaccepts a positiveintapplied uniformly to all environments. If omitted (None), each environment uses its ownmax_episode_stepsfrom config (raisesValueErrorif any env has it unset).Inside the context,
step/step_asyncautomatically check and reset environments at the step limit.In this context,
step()returnsList[bool]fortruncations(instead ofNone), andcollect_async()returns per-result truncation flags (instead of allFalse).
Inspecting the EnvGroup¶
len(env_group) # Number of environments
env_group.size() # Number of local env instances
env = env_group[env_id] # Get a specific Env by ID
env_group.get_observation_spaces() # List of observation spaces
env_group.get_action_spaces() # List of action spaces
env_group.get_stats() # Throughput statistics
env_group.print_timing_summary() # Print timing info
len(env_group)counts local env instances +env_serverentries.env_group.size()counts only local env instances (excludesenv_serverentries).