Use the PettingZoo adapter¶
Wrap OrbitalGymEnv as a pettingzoo.ParallelEnv for multi-agent
RL training where every vehicle is a separate agent.
Recipe¶
import numpy as np
from orbitalgym import OrbitalGymEnv, make_pursuit_evasion
from orbitalgym.adapters.pettingzoo import PettingZooAdapter
cfg = make_pursuit_evasion()
env = PettingZooAdapter(OrbitalGymEnv(cfg), seed=0)
obs_dict, info_dict = env.reset(seed=0)
total = {agent: 0.0 for agent in env.agents}
while env.agents:
actions = {
agent: np.zeros(env.action_space(agent).shape, dtype=np.float32)
for agent in env.agents
}
obs_dict, reward_dict, term_dict, trunc_dict, info_dict = env.step(actions)
for agent, r in reward_dict.items():
total[agent] += r
Agent IDs¶
Each vehicle is <side>_<index>. For 1v1: ['guard_0', 'bandit_0'].
For n_guards=2, n_bandits=1: ['guard_0', 'guard_1', 'bandit_0'].
Per-agent observations¶
Each channel returns a per-pair tensor of shape (N_self, N_total, m).
The adapter takes row i for agent <side>_i and concatenates across
channels: agent i sees only the i-th observer's view of every tracked
entity, flattened to a 1-D vector. Different agents on the same side
see different observations.
For per-vehicle channels like OnboardGPSObservation this gives each
vehicle its own GPS reading. For broadcast channels like
FullObservation every observer's row is identical, so all agents on
a side end up with the same vector — consistent with the channel's
semantics.
See In depth → Observations for the shape diagrams.
Termination¶
When episode_done fires, every agent has terminated=True
simultaneously and the adapter sets self.agents = [] — the Parallel
API signal for "loop is done." Call reset() to restart.