### Install and Run Git Hooks Source: https://github.com/openai/gym/blob/master/CONTRIBUTING.md Install and manage Git hooks for the project using pre-commit. Hooks run automatically on commit, or can be run manually. Skipping hooks is not recommended. ```bash pre-commit install ``` ```bash pre-commit run --all-files ``` ```bash git commit --no-verify ``` -------------------------------- ### Vectorized Environments: SyncVectorEnv Example Source: https://context7.com/openai/gym/llms.txt Demonstrates creating and interacting with multiple environments sequentially in a single process using SyncVectorEnv. Useful for batching observations, rewards, and done signals. ```python import gym import numpy as np # Create 4 CartPole environments with different seeds env = gym.vector.SyncVectorEnv([ lambda: gym.make("CartPole-v1"), lambda: gym.make("CartPole-v1"), lambda: gym.make("CartPole-v1"), lambda: gym.make("CartPole-v1"), ]) print(env.num_envs) # 4 print(env.observation_space.shape) # (4, 4) — batched print(env.action_space.shape) # (4,) obs, infos = env.reset(seed=42) print(obs.shape) # (4, 4) — 4 envs, 4-dim observation each for _ in range(100): actions = env.action_space.sample() # shape (4,) obs, rewards, terminateds, truncateds, infos = env.step(actions) print(f"rewards: {rewards}, terminated: {terminateds}") env.close() ``` -------------------------------- ### Vectorized Environments: AsyncVectorEnv Example Source: https://context7.com/openai/gym/llms.txt Shows how to run multiple environments in parallel using separate processes with AsyncVectorEnv. This is beneficial for compute-heavy environments and can be accelerated with shared_memory=True. ```python import gym import numpy as np # 4 parallel Ant environments using separate processes env = gym.vector.AsyncVectorEnv([ lambda: gym.make("CartPole-v1"), lambda: gym.make("CartPole-v1"), lambda: gym.make("CartPole-v1"), lambda: gym.make("CartPole-v1"), ], shared_memory=True) # shared_memory=True for faster large observations obs, infos = env.reset(seed=0) print(obs.shape) # (4, 4) for step in range(200): actions = env.action_space.sample() obs, rewards, terminateds, truncateds, infos = env.step(actions) # Environments auto-reset internally when terminated/truncated if np.any(terminateds | truncateds): # info["final_observation"] holds the last obs before auto-reset for i, done in enumerate(terminateds | truncateds): if done: final_obs = infos.get("final_observation", {}) env.close() ``` -------------------------------- ### MultiBinary Space Examples Source: https://context7.com/openai/gym/llms.txt Demonstrates the usage of MultiBinary for creating multi-dimensional binary spaces. ```python from gym.spaces import MultiBinary # 1-D flags: 8 binary switches flags = MultiBinary(5) print(flags.sample()) # e.g. array([0, 1, 0, 1, 0], dtype=int8) # 2-D binary tensor matrix_flags = MultiBinary([3, 2]) print(matrix_flags.sample()) # array([[0, 0], # [0, 1], # [1, 1]], dtype=int8) ``` -------------------------------- ### Observation Wrapper Usage Example Source: https://github.com/openai/gym/wiki/Feature-suggestion:-Observation-wrappers Demonstrates how to use the proposed observation_wrapper utility to apply a chain of observation transformations to an environment. This includes picking specific elements from a tuple observation, downscaling an image, and joining transformed observations. ```python pick_first = observation_wrapper.pick_tuple(0) pick_second = observation_wrapper.pick_tuple(1) downscale = observation_wrapper.downscale(shape=(84, 84)) join = observation_wrapper.join([pick_first, downscale], [pick_second]) # join two ob. chains # phi_4(x) := (phi_2(phi_1(x)), phi_3(x)) where phi_1 = pick_first # phi_2 = downscale # phi_3 = pick_second # phi_4 = join env = observation_wrapper(env, join) # returns observation' := phi_4(observation) ``` -------------------------------- ### Environment Validation: check_env Example Source: https://context7.com/openai/gym/llms.txt Demonstrates how to use `gym.utils.env_checker.check_env` to validate a custom environment against the Gym API. This checks spaces, reset/step return types, shapes, and seeding reproducibility. ```python import gym from gym import spaces from gym.utils.env_checker import check_env import numpy as np class MyEnv(gym.Env): def __init__(self): self.observation_space = spaces.Box(0.0, 1.0, shape=(4,), dtype=np.float32) self.action_space = spaces.Discrete(2) def reset(self, *, seed=None, options=None): super().reset(seed=seed) return self.observation_space.sample(), {} def step(self, action): obs = self.observation_space.sample() reward = float(action) return obs, reward, False, False, {} env = MyEnv() try: check_env(env) print("Environment passes all checks!") except AssertionError as e: print(f"Environment check failed: {e}") # If the env is correct: "Environment passes all checks!" env.close() ``` -------------------------------- ### gym.spaces.Discrete Source: https://context7.com/openai/gym/llms.txt Defines a finite integer space representing a set of integers starting from `start` up to `start + n - 1`. Typically used for discrete actions like button presses. ```APIDOC ### `gym.spaces.Discrete` — Finite Integer Space Represents a finite set `{start, start+1, ..., start+n-1}`. The most common action space for tasks like button presses or turn-based choices. ### Parameters - **n** (int) - The number of discrete actions available. Actions will be integers from `0` to `n-1`. - **start** (int, optional) - The starting value of the discrete set. Defaults to `0`. ### Example ```python from gym.spaces import Discrete import numpy as np # Default: {0, 1, 2, 3} action_space = Discrete(4) print(action_space.sample()) # e.g. 2 print(3 in action_space) # True print(4 in action_space) # False # Shifted range: {-1, 0, 1} signed_space = Discrete(3, start=-1) print(signed_space.sample()) # e.g. 0 # Masked sampling — only allow actions 0 and 2 mask = np.array([1, 0, 1, 0], dtype=np.int8) masked_action = action_space.sample(mask=mask) print(masked_action) # 0 or 2 ``` ``` -------------------------------- ### Applying a Wrapper to an Environment Source: https://github.com/openai/gym/blob/master/gym/wrappers/README.md Demonstrates how to wrap an existing Gym environment with a custom wrapper. Ensure the wrapper class is correctly imported. ```python env = gym.make('Pong-v0') env = MyWrapper(env) ``` -------------------------------- ### `gym.make` — Creating Registered Environments Source: https://context7.com/openai/gym/llms.txt Instantiates a fully wrapped environment by its ID, automatically applying standard wrappers. Supports overriding configuration like `max_episode_steps`. ```APIDOC ## `gym.make` — Creating Registered Environments ### `gym.make(id, **kwargs)` — Instantiate an Environment by ID `gym.make` looks up the global registry and returns a fully wrapped environment instance. It automatically applies `PassiveEnvChecker`, `OrderEnforcing`, and `TimeLimit` wrappers as configured in the env spec. ```python import gym # Create a built-in environment env = gym.make("CartPole-v1", render_mode="rgb_array") obs, info = env.reset(seed=0) print(env.observation_space) # Box([-4.8 -inf -0.42 -inf], [4.8 inf 0.42 inf], (4,), float32) print(env.action_space) # Discrete(2) # Run one episode total_reward = 0.0 for step in range(500): action = env.action_space.sample() obs, reward, terminated, truncated, info = env.step(action) total_reward += reward if terminated or truncated: print(f"Episode ended at step {step + 1}, total reward: {total_reward}") break env.close() # Override max episode steps env_short = gym.make("CartPole-v1", max_episode_steps=50) obs, info = env_short.reset(seed=1) for _ in range(100): _, _, terminated, truncated, _ = env_short.step(env_short.action_space.sample()) if terminated or truncated: # truncated=True will fire after 50 steps regardless of pole angle break env_short.close() ``` ``` -------------------------------- ### Core Environment API: gym.Env Source: https://context7.com/openai/gym/llms.txt Demonstrates the implementation of a custom environment inheriting from `gym.Env`, including `__init__`, `reset`, `step`, `render`, and `close` methods. ```APIDOC ## `gym.Env` — Base Environment Class All Gym environments inherit from `gym.Env`. Subclasses must define `action_space`, `observation_space`, and implement `step()` and `reset()`. The `render()` and `close()` methods are optional but recommended. ```python import gym from gym import spaces import numpy as np class GridWorldEnv(gym.Env): """A minimal custom 1-D grid environment.""" metadata = {"render_modes": ["human", "rgb_array"], "render_fps": 4} def __init__(self, size: int = 5, render_mode=None): super().__init__() self.size = size self.render_mode = render_mode # Observation: agent position (0..size-1) self.observation_space = spaces.Box( low=0, high=size - 1, shape=(1,), dtype=np.int64 ) # Action: 0 = left, 1 = right self.action_space = spaces.Discrete(2) def reset(self, *, seed=None, options=None): super().reset(seed=seed) # seeds self.np_random self._agent_pos = self.np_random.integers(0, self.size) self._target_pos = self.size - 1 obs = np.array([self._agent_pos]) info = {"target": self._target_pos} return obs, info def step(self, action): if action == 0: self._agent_pos = max(0, self._agent_pos - 1) else: self._agent_pos = min(self.size - 1, self._agent_pos + 1) terminated = int(self._agent_pos) == self._target_pos reward = 1.0 if terminated else -0.01 truncated = False obs = np.array([self._agent_pos]) info = {} return obs, reward, terminated, truncated, info def render(self): grid = [".." for _ in range(self.size)] grid[self._agent_pos] = "A" grid[self._target_pos] = "T" print("".join(grid)) def close(self): pass # Usage env = GridWorldEnv(size=10, render_mode="human") obs, info = env.reset(seed=42) print(f"Initial obs: {obs}, info: {info}") # Initial obs: [7], info: {'target': 9} for _ in range(20): action = env.action_space.sample() obs, reward, terminated, truncated, info = env.step(action) env.render() if terminated or truncated: obs, info = env.reset() break env.close() ``` -------------------------------- ### Instantiate and Run CartPole-v1 Environment in Python Source: https://context7.com/openai/gym/llms.txt Creates a CartPole-v1 environment using gym.make and runs a single episode with random actions. Demonstrates observation and action spaces and episode termination. ```python import gym # Create a built-in environment env = gym.make("CartPole-v1", render_mode="rgb_array") obs, info = env.reset(seed=0) print(env.observation_space) # Box([-4.8 -inf -0.42 -inf], [4.8 inf 0.42 inf], (4,), float32) print(env.action_space) # Discrete(2) # Run one episode total_reward = 0.0 for step in range(500): action = env.action_space.sample() obs, reward, terminated, truncated, info = env.step(action) total_reward += reward if terminated or truncated: print(f"Episode ended at step {step + 1}, total reward: {total_reward}") break env.close() # Override max episode steps env_short = gym.make("CartPole-v1", max_episode_steps=50) obs, info = env_short.reset(seed=1) for _ in range(100): _, _, terminated, truncated, _ = env_short.step(env_short.action_space.sample()) if terminated or truncated: # truncated=True will fire after 50 steps regardless of pole angle break env_short.close() ``` -------------------------------- ### RecordVideo Wrapper for Saving Rollouts Source: https://context7.com/openai/gym/llms.txt Records RGB frames during training and saves them as MP4 files. It supports episode-trigger and step-trigger scheduling for selective recording. Specify the video folder and a naming prefix. ```python import gym from gym.wrappers import RecordVideo env = gym.make("LunarLander-v2", render_mode="rgb_array") env = RecordVideo( env, video_folder="./videos", episode_trigger=lambda ep: ep % 10 == 0, # record every 10th episode name_prefix="lunarlander", ) for episode in range(30): obs, info = env.reset(seed=episode) done = False while not done: action = env.action_space.sample() obs, reward, terminated, truncated, info = env.step(action) done = terminated or truncated env.close() # Files saved as ./videos/lunarlander-episode-{0,10,20}.mp4 ``` -------------------------------- ### TimeLimit Wrapper for Episode Capping Source: https://context7.com/openai/gym/llms.txt Demonstrates how to use the TimeLimit wrapper to cap episode length and signal truncation. ```python import gym from gym.wrappers import TimeLimit env = gym.make("CartPole-v1", disable_env_checker=True) env = TimeLimit(env, max_episode_steps=10) obs, info = env.reset(seed=0) for step in range(20): obs, reward, terminated, truncated, info = env.step(env.action_space.sample()) if truncated: print(f"Truncated at step {step + 1}") # Truncated at step 10 break env.close() ``` -------------------------------- ### Interact with a Gym Environment Source: https://github.com/openai/gym/blob/master/README.md Demonstrates basic interaction with a Gym environment, including creation, stepping through actions, and resetting. Ensure the environment is closed after use. ```python import gym env = gym.make("CartPole-v1") observation, info = env.reset(seed=42) for _ in range(1000): action = env.action_space.sample() observation, reward, terminated, truncated, info = env.step(action) if terminated or truncated: observation, info = env.reset() env.close() ``` -------------------------------- ### Register and Use a Custom Environment in Gym Source: https://context7.com/openai/gym/llms.txt Register a custom environment with a namespace and version for use with `gym.make`. Supports setting `max_episode_steps`, `reward_threshold`, and default constructor arguments. ```python import gym from gym import spaces import numpy as np class SimpleEnv(gym.Env): def __init__(self, n=4): self.action_space = spaces.Discrete(n) self.observation_space = spaces.Box(0, 1, shape=(n,), dtype=np.float32) def reset(self, *, seed=None, options=None): super().reset(seed=seed) self._state = self.np_random.random(self.action_space.n).astype(np.float32) return self._state, {} def step(self, action): reward = float(self._state[action]) self._state = self.np_random.random(self.action_space.n).astype(np.float32) return self._state, reward, False, False, {} # Register with a namespace and version gym.register( id="myproject/SimpleEnv-v1", entry_point=SimpleEnv, # can also be "mymodule:SimpleEnv" max_episode_steps=200, reward_threshold=0.9, kwargs={"n": 8}, # default constructor kwargs ) env = gym.make("myproject/SimpleEnv-v1") obs, info = env.reset(seed=7) print(env.spec.id) # myproject/SimpleEnv-v1 print(env.spec.max_episode_steps) # 200 obs, reward, term, trunc, info = env.step(env.action_space.sample()) env.close() ``` -------------------------------- ### gym.register Source: https://context7.com/openai/gym/llms.txt Registers a custom environment with the Gym registry, making it available for creation via `gym.make`. You can specify optional parameters like `max_episode_steps`, `reward_threshold`, and default constructor arguments. ```APIDOC ## `gym.register(id, entry_point, ...)` — Add an Environment to the Global Registry Registers a custom environment so it can be created with `gym.make`. Supports optional `max_episode_steps`, `reward_threshold`, and additional kwargs forwarded to the constructor. ### Parameters - **id** (string) - The unique identifier for the environment (e.g., "myproject/SimpleEnv-v1"). - **entry_point** (string or callable) - The entry point to the environment class (e.g., `SimpleEnv` or `"mymodule:SimpleEnv"`). - **max_episode_steps** (int, optional) - The maximum number of steps allowed per episode. - **reward_threshold** (float, optional) - The reward threshold to consider the environment solved. - **kwargs** (dict, optional) - Default keyword arguments to pass to the environment's constructor. ### Example ```python import gym from gym import spaces import numpy as np class SimpleEnv(gym.Env): def __init__(self, n=4): self.action_space = spaces.Discrete(n) self.observation_space = spaces.Box(0, 1, shape=(n,), dtype=np.float32) def reset(self, *, seed=None, options=None): super().reset(seed=seed) self._state = self.np_random.random(self.action_space.n).astype(np.float32) return self._state, {} def step(self, action): reward = float(self._state[action]) self._state = self.np_random.random(self.action_space.n).astype(np.float32) return self._state, reward, False, False, {} # Register with a namespace and version gym.register( id="myproject/SimpleEnv-v1", entry_point=SimpleEnv, # can also be "mymodule:SimpleEnv" max_episode_steps=200, reward_threshold=0.9, kwargs={"n": 8}, # default constructor kwargs ) env = gym.make("myproject/SimpleEnv-v1") obs, info = env.reset(seed=7) print(env.spec.id) # myproject/SimpleEnv-v1 print(env.spec.max_episode_steps) # 200 obs, reward, term, trunc, info = env.step(env.action_space.sample()) env.close() ``` ``` -------------------------------- ### Register New Environment in Gym Source: https://github.com/openai/gym/wiki/Environments Use this code to register a new custom environment with a unique ID and entry point. Ensure the entry point correctly points to your environment class. ```python register( id='MyEnv-v0', entry_point='gym.envs.my_collection:MyEnv', ) ``` -------------------------------- ### Import Wrappers and Time Source: https://github.com/openai/gym/wiki/FAQ Import necessary modules for environment wrapping and timestamp generation. ```python from gym import wrappers from time import time # just to have timestamps in the files ``` -------------------------------- ### Record Environment Video Source: https://github.com/openai/gym/wiki/FAQ Wrap an environment with `RecordVideo` to save gameplay to MP4 files in a specified directory. Timestamps are used to create unique video directories. ```python env = gym.make(ENV_NAME) env = wrappers.RecordVideo(env, './videos/' + str(time()) + '/') ``` -------------------------------- ### gym.vector.SyncVectorEnv Source: https://context7.com/openai/gym/llms.txt Runs multiple independent environment instances sequentially in a single process, batching their observations, rewards, and done signals. ```APIDOC ## gym.vector.SyncVectorEnv ### Description Runs multiple independent environment instances sequentially in a single process, batching their observations, rewards, and done signals. ### Usage ```python import gym import numpy as np # Create 4 CartPole environments with different seeds env = gym.vector.SyncVectorEnv([ lambda: gym.make("CartPole-v1"), lambda: gym.make("CartPole-v1"), lambda: gym.make("CartPole-v1"), lambda: gym.make("CartPole-v1"), ]) print(env.num_envs) # 4 print(env.observation_space.shape) # (4, 4) — batched print(env.action_space.shape) # (4,) obs, infos = env.reset(seed=42) print(obs.shape) # (4, 4) — 4 envs, 4-dim observation each for _ in range(100): actions = env.action_space.sample() # shape (4,) obs, rewards, terminateds, truncateds, infos = env.step(actions) print(f"rewards: {rewards}, terminated: {terminateds}") env.close() ``` ``` -------------------------------- ### gym.vector.AsyncVectorEnv Source: https://context7.com/openai/gym/llms.txt Runs environment instances in separate processes using `multiprocessing`, enabling true parallelism especially beneficial for compute-heavy environments. ```APIDOC ## gym.vector.AsyncVectorEnv ### Description Runs environment instances in separate processes using `multiprocessing`, enabling true parallelism especially beneficial for compute-heavy environments. ### Usage ```python import gym import numpy as np # 4 parallel Ant environments using separate processes env = gym.vector.AsyncVectorEnv([ lambda: gym.make("CartPole-v1"), lambda: gym.make("CartPole-v1"), lambda: gym.make("CartPole-v1"), lambda: gym.make("CartPole-v1"), ], shared_memory=True) # shared_memory=True for faster large observations obs, infos = env.reset(seed=0) print(obs.shape) # (4, 4) for step in range(200): actions = env.action_space.sample() obs, rewards, terminateds, truncateds, infos = env.step(actions) # Environments auto-reset internally when terminated/truncated if np.any(terminateds | truncateds): # info["final_observation"] holds the last obs before auto-reset for i, done in enumerate(terminateds | truncateds): if done: final_obs = infos.get("final_observation", {}) env.close() ``` ``` -------------------------------- ### Run Pyright Type Checker Source: https://github.com/openai/gym/blob/master/CONTRIBUTING.md Execute the pyright type checker for the project. This can be done via the pre-commit process or directly using the pyright command. ```bash pre-commit run --all-files ``` ```bash pyright --project=pyproject.toml ``` ```bash pyright ``` -------------------------------- ### Create Custom GridWorld Environment in Python Source: https://context7.com/openai/gym/llms.txt Defines a minimal custom 1-D grid environment inheriting from gym.Env. Requires implementing action_space, observation_space, step(), and reset(). ```python import gym from gym import spaces import numpy as np class GridWorldEnv(gym.Env): """A minimal custom 1-D grid environment.""" metadata = {"render_modes": ["human", "rgb_array"], "render_fps": 4} def __init__(self, size: int = 5, render_mode=None): super().__init__() self.size = size self.render_mode = render_mode # Observation: agent position (0..size-1) self.observation_space = spaces.Box( low=0, high=size - 1, shape=(1,), dtype=np.int64 ) # Action: 0 = left, 1 = right self.action_space = spaces.Discrete(2) def reset(self, *, seed=None, options=None): super().reset(seed=seed) # seeds self.np_random self._agent_pos = self.np_random.integers(0, self.size) self._target_pos = self.size - 1 obs = np.array([self._agent_pos]) info = {"target": self._target_pos} return obs, info def step(self, action): if action == 0: self._agent_pos = max(0, self._agent_pos - 1) else: self._agent_pos = min(self.size - 1, self._agent_pos + 1) terminated = int(self._agent_pos) == self._target_pos reward = 1.0 if terminated else -0.01 truncated = False obs = np.array([self._agent_pos]) info = {} return obs, reward, terminated, truncated, info def render(self): grid = [".." for _ in range(self.size)] grid[self._agent_pos] = "A" grid[self._target_pos] = "T" print("".join(grid)) def close(self): pass # Usage env = GridWorldEnv(size=10, render_mode="human") obs, info = env.reset(seed=42) print(f"Initial obs: {obs}, info: {info}") # Initial obs: [7], info: {'target': 9} for _ in range(20): action = env.action_space.sample() obs, reward, terminated, truncated, info = env.step(action) env.render() if terminated or truncated: obs, info = env.reset() break env.close() ``` -------------------------------- ### Custom Observation, Reward, and Action Wrappers Source: https://context7.com/openai/gym/llms.txt Defines and stacks custom wrappers for clipping observations and rewards, and for transforming actions. ```python import gym import numpy as np from gym import ObservationWrapper, RewardWrapper, ActionWrapper from gym.spaces import Box, Discrete # --- ObservationWrapper: clip observations to [-5, 5] --- class ClipObservation(ObservationWrapper): def __init__(self, env, low=-5.0, high=5.0): super().__init__(env) self.observation_space = Box( low=low, high=high, shape=env.observation_space.shape, dtype=env.observation_space.dtype, ) def observation(self, obs): return np.clip(obs, self.observation_space.low, self.observation_space.high) # --- RewardWrapper: clip rewards to [-1, 1] --- class ClipReward(RewardWrapper): def reward(self, reward): return np.clip(reward, -1.0, 1.0) # --- ActionWrapper: map discrete {0,1,2,3} to continuous velocity vectors --- class DiscreteToBox(ActionWrapper): _MOVES = {0: [0, 1], 1: [0, -1], 2: [1, 0], 3: [-1, 0]} def __init__(self, env): super().__init__(env) self.action_space = Discrete(4) def action(self, act): return np.array(self._MOVES[int(act)], dtype=np.float32) # Stack wrappers env = gym.make("Pendulum-v1") env = ClipObservation(env, low=-5.0, high=5.0) env = ClipReward(env) print(env) # >>> print(env.unwrapped) # base Pendulum env obs, info = env.reset(seed=0) obs, reward, terminated, truncated, info = env.step(env.action_space.sample()) print(f"Clipped reward: {reward}") # value in [-1, 1] env.close() ``` -------------------------------- ### Importing a Custom Wrapper Source: https://github.com/openai/gym/blob/master/gym/wrappers/README.md Shows the correct way to import a custom wrapper class from the gym.wrappers module. This is necessary before applying the wrapper to an environment. ```python from gym.wrappers import MyWrapper ``` -------------------------------- ### Frame Stacking Observation Wrapper Logic Source: https://github.com/openai/gym/wiki/Feature-suggestion:-Observation-wrappers Illustrates the conceptual logic for a frame stacking observation wrapper, which combines the current observation with previous ones. It shows how the observation space might change to accommodate the stacked frames. ```python phi(x_t) = (x_{t-3}, x_{t-2}, x_{t-1}, x_t), where x_k = zeros_like(x_t) for k < 0, or x_k = x_t, for k < 0. ``` -------------------------------- ### RescaleAction Wrapper for Continuous Actions Source: https://context7.com/openai/gym/llms.txt Linearly rescales the continuous action space from a desired range (e.g., [-1, 1]) to the environment's native range. This allows algorithms to output actions on a normalized scale, simplifying learning. The original action space bounds are printed for comparison. ```python import gym from gym.wrappers import RescaleAction import numpy as np env = gym.make("Pendulum-v1") print(env.action_space) # Box(-2.0, 2.0, (1,), float32) # Rescale so the agent outputs in [-1, 1] env = RescaleAction(env, min_action=-1.0, max_action=1.0) print(env.action_space) # Box(-1.0, 1.0, (1,), float32) obs, info = env.reset(seed=0) ``` -------------------------------- ### Inspect Gym Environment Specifications Source: https://context7.com/openai/gym/llms.txt Retrieve an environment's specification using `gym.spec` to access metadata like `id`, `max_episode_steps`, `reward_threshold`, and `entry_point`. Lists all registered environments and filters for specific types. ```python import gym spec = gym.spec("LunarLander-v2") print(spec.id) # LunarLander-v2 print(spec.max_episode_steps) # 1000 print(spec.reward_threshold) # 200.0 print(spec.nondeterministic) # False print(spec.entry_point) # gym.envs.box2d.lunar_lander:LunarLander # List all registered environments all_env_ids = list(gym.envs.registration.registry.keys()) print(f"Total registered envs: {len(all_env_ids)}") mujoco_envs = [e for e in all_env_ids if "Ant" in e or "Hopper" in e] print(mujoco_envs) # ['Ant-v2', 'Ant-v3', 'Ant-v4', 'Hopper-v2', 'Hopper-v3', 'Hopper-v4'] ``` -------------------------------- ### Dict Space for Structured Observations Source: https://context7.com/openai/gym/llms.txt Shows how to use Dict space to create structured observations with named components. ```python from gym.spaces import Box, Dict, Discrete import numpy as np obs_space = Dict({ "image": Box(low=0, high=255, shape=(64, 64, 3), dtype=np.uint8), "position": Box(low=-10.0, high=10.0, shape=(2,), dtype=np.float32), "has_key": Discrete(2), }) sample = obs_space.sample() print(sample.keys()) # odict_keys(['has_key', 'image', 'position']) print(sample["image"].shape) # (64, 64, 3) print(sample["position"]) # e.g. [-3.14 7.89] print(sample["has_key"]) # e.g. 1 print(obs_space.contains(sample)) # True ``` -------------------------------- ### gym.wrappers.TimeLimit Source: https://context7.com/openai/gym/llms.txt The TimeLimit wrapper adds a `truncated=True` signal after a specified number of steps, effectively capping the episode length and preventing infinite episodes. ```APIDOC ## gym.wrappers.TimeLimit ### Description Episode Length Capping. Adds a `truncated=True` signal after `max_episode_steps` steps, preventing infinite episodes. ### Usage ```python import gym from gym.wrappers import TimeLimit env = gym.make("CartPole-v1", disable_env_checker=True) env = TimeLimit(env, max_episode_steps=10) obs, info = env.reset(seed=0) for step in range(20): obs, reward, terminated, truncated, info = env.step(env.action_space.sample()) if truncated: print(f"Truncated at step {step + 1}") # Truncated at step 10 break env.close() ``` ``` -------------------------------- ### Register Custom Environment Variant Source: https://github.com/openai/gym/wiki/FAQ Create a new environment ID with modified parameters like `max_episode_steps` to make an existing environment easier. This custom environment will only be recognized by your code. ```python gym.envs.register( id='MountainCarMyEasyVersion-v0', entry_point='gym.envs.classic_control:MountainCarEnv', max_episode_steps=250, # MountainCar-v0 uses 200 reward_threshold=-110.0, ) env = gym.make('MountainCarMyEasyVersion-v0') ``` -------------------------------- ### NormalizeObservation Wrapper for Online Normalization Source: https://context7.com/openai/gym/llms.txt Shows how to apply the NormalizeObservation wrapper for online mean and variance normalization of observations. ```python import gym from gym.wrappers import NormalizeObservation env = gym.make("HalfCheetah-v4") env = NormalizeObservation(env) obs, info = env.reset(seed=0) for _ in range(1000): obs, reward, terminated, truncated, info = env.step(env.action_space.sample()) if terminated or truncated: obs, info = env.reset() # After warm-up, observations are approximately zero-mean, unit-variance print(f"Obs mean ≈ {obs.mean():.3f}, std ≈ {obs.std():.3f}") env.close() ``` -------------------------------- ### gym.Wrapper / ObservationWrapper / RewardWrapper / ActionWrapper Source: https://context7.com/openai/gym/llms.txt Base classes for creating custom wrappers. Wrappers transparently decorate an existing environment, forwarding calls unless overridden. Specific subclasses allow intercepting only observations, rewards, or actions. ```APIDOC ## gym.Wrapper / ObservationWrapper / RewardWrapper / ActionWrapper ### Description Base Wrapper Classes. Wrappers transparently decorate an existing environment, forwarding all calls unless overridden. Use the typed subclasses to intercept only observations, rewards, or actions respectively. ### Custom Wrapper Example (ClipObservation) ```python import gym import numpy as np from gym import ObservationWrapper, RewardWrapper, ActionWrapper from gym.spaces import Box, Discrete # --- ObservationWrapper: clip observations to [-5, 5] --- class ClipObservation(ObservationWrapper): def __init__(self, env, low=-5.0, high=5.0): super().__init__(env) self.observation_space = Box( low=low, high=high, shape=env.observation_space.shape, dtype=env.observation_space.dtype, ) def observation(self, obs): return np.clip(obs, self.observation_space.low, self.observation_space.high) # --- RewardWrapper: clip rewards to [-1, 1] --- class ClipReward(RewardWrapper): def reward(self, reward): return np.clip(reward, -1.0, 1.0) # --- ActionWrapper: map discrete {0,1,2,3} to continuous velocity vectors --- class DiscreteToBox(ActionWrapper): _MOVES = {0: [0, 1], 1: [0, -1], 2: [1, 0], 3: [-1, 0]} def __init__(self, env): super().__init__(env) self.action_space = Discrete(4) def action(self, act): return np.array(self._MOVES[int(act)], dtype=np.float32) # Stack wrappers env = gym.make("Pendulum-v1") env = ClipObservation(env, low=-5.0, high=5.0) env = ClipReward(env) print(env) # >>> print(env.unwrapped) # base Pendulum env obs, info = env.reset(seed=0) obs, reward, terminated, truncated, info = env.step(env.action_space.sample()) print(f"Clipped reward: {reward}") # value in [-1, 1] env.close() ``` ```