Traits for training and testing environments in RelayRL.
VecEnv and parallel stepping
The framework may run many logical environments in parallel (array-of-structs / one
[ScalarEnvironment] per worker) or a single batched simulator that implements
[VectorEnvironment]. Both paths share the base [Environment] contract for observation
building and optional high-level loops.
[ScalarEnvironment]
Use when each sub-environment is its own object with a scalar (observation, step_info) step.
A parallel runner typically holds Vec<Arc<dyn ScalarEnvironment<...>>> (or concrete handles),
assigns one stable [EnvironmentUuid] per sub-env, and calls step on each worker. Types
are Send + Sync so implementations often use interior mutability (for example Mutex or
atomics) if physical simulation state mutates across calls.
[VectorEnvironment]
Use when one implementation can apply a batch of actions keyed by [EnvironmentUuid] in a
single call (GPU batching, vectorized physics, remote batched service, etc.). Callers should
treat identities as opaque: the same uuid must be used for one logical env across step and
any routing in the runtime.
Contracts (implementors)
- Ordering: Unless documented otherwise by your concrete type, callers should not assume
that output order matches input order for [
VectorEnvironment::step]; they should key by [EnvironmentUuid]. - Errors: [
EnvironmentError] is returned for the whole operation; partial success is not expressed in the type system. If you need per-env errors, document that on your concrete type or surface it inside [StepInfo] / [ResetInfo]. - Observations: [
Environment::build_observation] is intentionally type-erased ([std::any::Any]) for framework integration; pair it with a documented convention for downcasting where the runtime requires a concrete layout.