Skip to content

Commit

Permalink
Tweak Wrapper implementation (openai#291)
Browse files Browse the repository at this point in the history
* Tweak README and don't use __new__ for wrapper

The extra 'env' argument means that Wrapper authors with a custom
__init__ need to think about the parent signature anyway, so there's
not as much benefit to adding the more surprising __new__.

* Add support for registering wrappers for the official environment
  • Loading branch information
gdb authored Aug 14, 2016
1 parent 30cdc4d commit 09082c9
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 25 deletions.
34 changes: 16 additions & 18 deletions gym/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ def configure(self, *args, **kwargs):
else:
raise

def build(self):
def build(self, extra_wrappers=None):
"""[EXPERIMENTAL: may be removed in a later version of Gym] Builds an
environment by applying any provided wrappers, with the
outmost wrapper supplied first. This method is automatically
Expand All @@ -259,12 +259,19 @@ class FooEnv(gym.Env):
Calling 'env.build' will return 'Wrapper1(Wrapper2(env))'.
Args:
extra_wrappers (Optional[list]): Any extra wrappers to apply to the wrapped instance
Returns:
gym.Env: A potentially wrapped environment instance.
"""
wrappers = self.metadata.get('wrappers', [])
if extra_wrappers:
wrappers = wrappers + extra_wrappers

wrapped = self
for wrapper in reversed(self.metadata.get('wrappers', [])):
for wrapper in reversed(wrappers):
wrapped = wrapper(wrapped)
return wrapped

Expand Down Expand Up @@ -314,23 +321,14 @@ def from_jsonable(self, sample_n):
return sample_n

class Wrapper(Env):

def __new__(cls, env, *args, **kwargs):
# We use __new__ since we want the wrapper author to be able to
# override __init__ without remembering to call super.
wrapper = super(Wrapper, cls).__new__(cls)
wrapper.env = env
wrapper.metadata = env.metadata
wrapper.action_space = env.action_space
wrapper.observation_space = env.observation_space
wrapper.reward_range = env.reward_range
wrapper.spec = env.spec
wrapper._unwrapped = env.unwrapped
return wrapper

# Overridable
def __init__(self, env):
pass
self.env = env
self.metadata = env.metadata
self.action_space = env.action_space
self.observation_space = env.observation_space
self.reward_range = env.reward_range
self.spec = env.spec
self._unwrapped = env.unwrapped

def _step(self, action):
return self.env.step(action)
Expand Down
5 changes: 3 additions & 2 deletions gym/envs/registration.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class EnvSpec(object):
trials (int): The number of trials run in official evaluation
"""

def __init__(self, id, entry_point=None, timestep_limit=1000, trials=100, reward_threshold=None, local_only=False, kwargs=None, nondeterministic=False):
def __init__(self, id, entry_point=None, timestep_limit=1000, trials=100, reward_threshold=None, local_only=False, kwargs=None, nondeterministic=False, wrappers=None):
self.id = id
# Evaluation parameters
self.timestep_limit = timestep_limit
Expand All @@ -52,6 +52,7 @@ def __init__(self, id, entry_point=None, timestep_limit=1000, trials=100, reward
self._entry_point = entry_point
self._local_only = local_only
self._kwargs = {} if kwargs is None else kwargs
self._wrappers = wrappers

def make(self):
"""Instantiates an instance of the environment with appropriate kwargs"""
Expand All @@ -63,7 +64,7 @@ def make(self):

# Make the enviroment aware of which spec it came from.
env.spec = self
env = env.build()
env = env.build(extra_wrappers=self._wrappers)

return env

Expand Down
13 changes: 8 additions & 5 deletions gym/wrappers/README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
# Wrappers
# Wrappers (experimental)

These are the wrappers to customize environments. Note that we may later
restructure any of the files, but will keep the wrappers available
at the relevant package's top-level. So for example, you should access
`MyWrapper` as follows:
This is a placeholder for now: we will likely soon start adding
standardized wrappers for environments. (Only stable and
general-purpose wrappers will be accepted into gym core.)

Note that we may later restructure any of the files, but will keep the
wrappers available at the relevant package's top-level. So for
example, you should access `MyWrapper` as follows:

```
# Will be supported in future releases
Expand Down

0 comments on commit 09082c9

Please sign in to comment.