Skip to content

Commit

Permalink
Update: support one-liner gym.make
Browse files Browse the repository at this point in the history
  • Loading branch information
zuoxingdong committed Oct 18, 2019
1 parent e16048a commit 425d407
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 47 deletions.
17 changes: 11 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,22 @@ pip install -e .
```

# Getting started
Converting the environment from `dm_control` to `gym` can be as simple as:
One liner to create the environment:
```python
from dm_control import suite
from dm2gym import DMControlEnv

env = suite.load('cheetah', 'run')
env = DMControlEnv(env)
import gym
env = gym.make('dm2gym:CheetahRun-v0')
```

More examples to specify the environment:
```python
env = gym.make('dm2gym:FishSwim-v0', environment_kwargs={'flat_observation': True})
env = gym.make('dm2gym:HopperHop-v0', visualize_reward=True)
```

# What's new
- 2019-10-18 (v0.2.0)
- Sync to the latest API of DeepMind Control Suite
- Support gym registration: create all `dm_control` environments via `gym.make`

- 2019-04-14 (v0.1.0)
- Initial release
Expand Down
12 changes: 10 additions & 2 deletions dm2gym/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,10 @@
from .dm_control_env import DMControlEnv
from .opencv_image_viewer import OpenCVImageViewer
from gym.envs import register
from dm_control import suite


for domain_name, task_name in suite.ALL_TASKS:
ID = f'{domain_name.capitalize()}{task_name.capitalize()}-v0'
register(id=ID,
entry_point='dm2gym.envs:DMSuiteEnv',
kwargs={'domain_name': domain_name, 'task_name': task_name},
max_episode_steps=1000)
2 changes: 2 additions & 0 deletions dm2gym/envs/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from .dm_suite_env import DMSuiteEnv
from .opencv_image_viewer import OpenCVImageViewer
58 changes: 25 additions & 33 deletions dm2gym/dm_control_env.py → dm2gym/envs/dm_suite_env.py
Original file line number Diff line number Diff line change
@@ -1,45 +1,42 @@
from collections import OrderedDict

import numpy as np

import gym
from gym import spaces
from gym.envs.registration import EnvSpec

from dm_control.rl.specs import ArraySpec
from dm_control.rl.specs import BoundedArraySpec
from dm_control import suite
from dm_env import specs


def convert_dm_control_to_gym_space(dm_control_space):
r"""Convert dm_control space to gym space. """
if isinstance(dm_control_space, BoundedArraySpec):
if isinstance(dm_control_space, specs.BoundedArray):
space = spaces.Box(low=dm_control_space.minimum,
high=dm_control_space.maximum,
dtype=dm_control_space.dtype)
assert space.shape == dm_control_space.shape
return space
elif isinstance(dm_control_space, ArraySpec) and not isinstance(dm_control_space, BoundedArraySpec):
elif isinstance(dm_control_space, specs.Array) and not isinstance(dm_control_space, specs.BoundedArray):
space = spaces.Box(low=-float('inf'),
high=float('inf'),
shape=dm_control_space.shape,
dtype=dm_control_space.dtype)
return space
elif isinstance(dm_control_space, OrderedDict):
space = spaces.Dict(OrderedDict([(key, convert_dm_control_to_gym_space(value))
for key, value in dm_control_space.items()]))
elif isinstance(dm_control_space, dict):
space = spaces.Dict({key: convert_dm_control_to_gym_space(value)
for key, value in dm_control_space.items()})
return space


class DMControlEnv(gym.Env):
def __init__(self, env):
self.env = env

class DMSuiteEnv(gym.Env):
def __init__(self, domain_name, task_name, task_kwargs=None, environment_kwargs=None, visualize_reward=False):
self.env = suite.load(domain_name,
task_name,
task_kwargs=task_kwargs,
environment_kwargs=environment_kwargs,
visualize_reward=visualize_reward)
self.metadata = {'render.modes': ['human', 'rgb_array'],
'video.frames_per_second': int(np.round(1.0/self.env.control_timestep()))}
'video.frames_per_second': round(1.0/self.env.control_timestep())}

self.observation_space = convert_dm_control_to_gym_space(env.observation_spec())
self.action_space = convert_dm_control_to_gym_space(env.action_spec())
max_episode_steps = None if env._step_limit == float('inf') else int(env._step_limit)
self.spec = EnvSpec('DM-v0', max_episode_steps=max_episode_steps)
self.observation_space = convert_dm_control_to_gym_space(self.env.observation_spec())
self.action_space = convert_dm_control_to_gym_space(self.env.action_spec())
self.viewer = None

def seed(self, seed):
Expand All @@ -57,25 +54,20 @@ def reset(self):
timestep = self.env.reset()
return timestep.observation

def render(self, mode='human', *, render_window_mode='gym', **kwargs):
def render(self, mode='human', **kwargs):
if 'camera_id' not in kwargs:
# Tracking camera
kwargs['camera_id'] = 0
# Verify render window mode
assert render_window_mode in ['gym', 'opencv'],\
"Invalid value for render_window_mode: {}".format(
render_window_mode
)
kwargs['camera_id'] = 0 # Tracking camera
use_opencv_renderer = kwargs.pop('use_opencv_renderer', False)

img = self.env.physics.render(**kwargs)
if mode == 'rgb_array':
return img
elif mode == "human":
elif mode == 'human':
if self.viewer is None:
# Open viewer
if render_window_mode == 'gym':
if not use_opencv_renderer:
from gym.envs.classic_control import rendering
self.viewer = rendering.SimpleImageViewer(maxwidth=1024)
elif render_window_mode == 'opencv':
else:
from dm2gym import OpenCVImageViewer
self.viewer = OpenCVImageViewer()
self.viewer.imshow(img)
Expand Down
File renamed without changes.
11 changes: 5 additions & 6 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,25 @@
long_description = f.read()

# Minimal requried dependencies
install_requires = ['numpy',
'gym',
'opencv-python']
install_requires = ['numpy',
'gym']
tests_require = ['pytest',
'flake8',
'sphinx',
'sphinx_rtd_theme']

setup(name='dm2gym',
version='0.1.1',
version='0.2.0',
author='Xingdong Zuo',
author_email='[email protected]',
description='dm2gym: convert DeepMind Control Suite to OpenAI gym environments.',
description='dm2gym: Convert DeepMind Control Suite to OpenAI gym environments.',
long_description=long_description,
long_description_content_type='text/markdown',
url='https://github.com/zuoxingdong/dm2gym',
install_requires=install_requires,
tests_require=tests_require,
python_requires='>=3',
# List all lagom packages (folder with __init__.py), useful to distribute a release
# List all packages (folder with __init__.py), useful to distribute a release
packages=find_packages(),
# tell pip some metadata (e.g. Python version, OS etc.)
classifiers=['Programming Language :: Python :: 3',
Expand Down

0 comments on commit 425d407

Please sign in to comment.