Source code for pettingzoo.utils.wrappers.clip_out_of_bounds
from __future__ import annotations
import numpy as np
from gymnasium.spaces import Box
from pettingzoo.utils.env import AECEnv
from pettingzoo.utils.env_logger import EnvLogger
from pettingzoo.utils.wrappers.base import BaseWrapper
[docs]
class ClipOutOfBoundsWrapper(BaseWrapper):
"""Clips the input action to fit in the continuous action space (emitting a warning if it does so).
Applied to continuous environments in pettingzoo.
"""
def __init__(self, env: AECEnv):
super().__init__(env)
assert isinstance(
env, AECEnv
), "ClipOutOfBoundsWrapper is only compatible with AEC environments."
assert all(
isinstance(self.action_space(agent), Box)
for agent in getattr(self, "possible_agents", [])
), "should only use ClipOutOfBoundsWrapper for Box spaces"
def step(self, action: np.ndarray | None) -> None:
space = self.action_space(self.agent_selection)
if not (
action is None
and (
self.terminations[self.agent_selection]
or self.truncations[self.agent_selection]
)
) and not space.contains(action):
if action is None or np.isnan(action).any():
EnvLogger.error_nan_action()
assert (
space.shape
== action.shape # pyright: ignore[reportOptionalMemberAccess]
), f"action should have shape {space.shape}, has shape {action.shape}" # pyright: ignore[reportOptionalMemberAccess]
EnvLogger.warn_action_out_of_bound(
action=action, action_space=space, backup_policy="clipping to space"
)
action = np.clip(
action, # pyright: ignore[reportGeneralTypeIssues]
space.low, # pyright: ignore[reportGeneralTypeIssues]
space.high, # pyright: ignore[reportGeneralTypeIssues]
)
super().step(action)
def __str__(self) -> str:
return str(self.env)