Render API (#2671)

* add pygame GUI for frozen_lake.py env

* add new line at EOF

* pre-commit reformat

* improve graphics

* new images and dynamic window size

* darker tile borders and fix ICC profile

* pre-commit hook

* adjust elf and stool size

* Update frozen_lake.py

* reformat

* fix #2600

* #2600

* add rgb_array support

* reformat

* test render api change on FrozenLake

* add render support for reset on frozenlake

* add clock on pygame render

* new render api for blackjack

* new render api for cliffwalking

* new render api for Env class

* update reset method, lunar and Env

* fix wrapper

* fix reset lunar

* new render api for box2d envs

* new render api for mujoco envs

* fix bug

* new render api for classic control envs

* fix tests

* add render_mode None for CartPole

* new render api for test fake envs

* pre-commit hook

* fix FrozenLake

* fix FrozenLake

* more render_mode to super - frozenlake

* remove kwargs from frozen_lake new

* pre-commit hook

* add deprecated render method

* add backwards compatibility

* fix test

* add _render

* move pygame.init() (avoid pygame dependency on init)

* fix pygame dependencies

* remove collect_render() maintain multi-behaviours .render()

* add type hints

* fix renderer

* don't call .render() with None

* improve docstring

* add single_rgb_array to all envs

* remove None from metadata["render_modes"]

* add type hints to test_env_checkers

* fix lint

* add comments to renderer

* add comments to single_depth_array and single_state_pixels

* reformat

* add deprecation warnings and env.render_mode declaration

* fix lint

* reformat

* fix tests

* add docs

* fix car racing determinism

* remove warning test envs, customizable modes on renderer

* remove commments and add todo for env_checker

* fix car racing

* replace render mode check with assert

* update new mujoco

* reformat

* reformat

* change metaclass definition

* fix tests

* implement mark suggestions (test, docs, sets)

* check_render

Co-authored-by: J K Terry <jkterry0@gmail.com>
This commit is contained in:
Omar Younis
2022-06-08 00:20:56 +02:00
committed by GitHub
parent 66c431d4b3
commit 9acf9cd367
58 changed files with 950 additions and 304 deletions

View File

@@ -1,6 +1,16 @@
"""Core API for Environment, Wrapper, ActionWrapper, RewardWrapper and ObservationWrapper."""
import sys
from typing import Generic, Optional, SupportsFloat, Tuple, TypeVar, Union
from typing import (
Any,
Dict,
Generic,
List,
Optional,
SupportsFloat,
Tuple,
TypeVar,
Union,
)
from gym import spaces
from gym.logger import deprecation, warn
@@ -14,6 +24,44 @@ if sys.version_info == (3, 6):
ObsType = TypeVar("ObsType")
ActType = TypeVar("ActType")
RenderFrame = TypeVar("RenderFrame")
class _EnvDecorator(type): # TODO: remove with gym 1.0
"""Metaclass used for adding deprecation warning to the mode kwarg in the render method."""
def __new__(cls, name, bases, attr):
if "render" in attr.keys():
attr["render"] = _EnvDecorator._deprecate_mode(attr["render"])
return super().__new__(cls, name, bases, attr)
@staticmethod
def _deprecate_mode(render_func): # type: ignore
render_return = Optional[Union[RenderFrame, List[RenderFrame]]]
def render(
self: object, *args: Tuple[Any], **kwargs: Dict[str, Any]
) -> render_return:
if "mode" in kwargs.keys():
deprecation(
"The argument mode in render method is deprecated; "
"use render_mode during environment initialization instead.\n"
"See here for more information: https://www.gymlibrary.ml/content/api/"
)
elif self.spec is not None and "render_mode" not in self.spec.kwargs.keys(): # type: ignore
deprecation(
"You are calling render method, "
"but you didn't specified the argument render_mode at environment initialization. "
"To maintain backward compatibility, the environment will render in human mode.\n"
"If you want to render in human mode, initialize the environment in this way: "
"gym.make('EnvName', render_mode='human') and don't call the render method.\n"
"See here for more information: https://www.gymlibrary.ml/content/api/"
)
return render_func(self, *args, **kwargs)
return render
class Env(Generic[ObsType, ActType]):
@@ -43,8 +91,11 @@ class Env(Generic[ObsType, ActType]):
Note: a default reward range set to :math:`(-\infty,+\infty)` already exists. Set it if you want a narrower range.
"""
__metaclass__ = _EnvDecorator
# Set this in SOME subclasses
metadata = {"render_modes": []}
render_mode = None # define render_mode if your environment supports rendering
reward_range = (-float("inf"), float("inf"))
spec = None
@@ -130,42 +181,34 @@ class Env(Generic[ObsType, ActType]):
if seed is not None:
self._np_random, seed = seeding.np_random(seed)
def render(self, mode="human"):
"""Renders the environment.
# TODO: remove kwarg mode with gym 1.0
def render(self, mode="human") -> Optional[Union[RenderFrame, List[RenderFrame]]]:
"""Compute the render frames as specified by render_mode attribute during initialization of the environment.
A set of supported modes varies per environment. (And some
The set of supported modes varies per environment. (And some
third-party environments may not support rendering at all.)
By convention, if mode is:
By convention, if render_mode is:
- human: render to the current display or terminal and
return nothing. Usually for human consumption.
- rgb_array: Return a numpy.ndarray with shape (x, y, 3),
representing RGB values for an x-by-y pixel image, suitable
for turning into a video.
- ansi: Return a string (str) or StringIO.StringIO containing a
terminal-style text representation. The text can include newlines
and ANSI escape sequences (e.g. for colors).
- None (default): no render is computed.
- human: render return None.
The environment is continuously rendered in the current display or terminal. Usually for human consumption.
- single_rgb_array: return a single frame representing the current state of the environment.
A frame is a numpy.ndarray with shape (x, y, 3) representing RGB values for an x-by-y pixel image.
- rgb_array: return a list of frames representing the states of the environment since the last reset.
Each frame is a numpy.ndarray with shape (x, y, 3), as with single_rgb_array.
- ansi: Return a list of strings (str) or StringIO.StringIO containing a
terminal-style text representation for each time step.
The text can include newlines and ANSI escape sequences (e.g. for colors).
Note:
Rendering computations is performed internally even if you don't call render().
To avoid this, you can set render_mode = None and, if the environment supports it,
call render() specifying the argument 'mode'.
Note:
Make sure that your class's metadata 'render_modes' key includes
the list of supported modes. It's recommended to call super()
in implementations to use the functionality of this method.
Example:
>>> import numpy as np
>>> class MyEnv(Env):
... metadata = {'render_modes': ['human', 'rgb_array']}
...
... def render(self, mode='human'):
... if mode == 'rgb_array':
... return np.array(...) # return RGB frame suitable for video
... elif mode == 'human':
... ... # pop up a window and render
... else:
... super().render(mode=mode) # just raise an exception
Args:
mode: the mode to render with, valid modes are `env.metadata["render_modes"]`
"""
raise NotImplementedError