renaming to fancy_gym

This commit is contained in:
Fabian
2022-07-13 15:10:43 +02:00
parent d412fb229c
commit 8d1c1b44bf
179 changed files with 332 additions and 361 deletions
View File
+137
View File
@@ -0,0 +1,137 @@
import fancy_gym
def example_dmc(env_id="dmc:fish-swim", seed=1, iterations=1000, render=True):
"""
Example for running a DMC based env in the step based setting.
The env_id has to be specified as `domain_name:task_name` or
for manipulation tasks as `domain_name:manipulation-environment_name`
Args:
env_id: Either `domain_name-task_name` or `manipulation-environment_name`
seed: seed for deterministic behaviour
iterations: Number of rollout steps to run
render: Render the episode
Returns:
"""
env = fancy_gym.make(env_id, seed)
rewards = 0
obs = env.reset()
print("observation shape:", env.observation_space.shape)
print("action shape:", env.action_space.shape)
for i in range(iterations):
ac = env.action_space.sample()
if render:
env.render(mode="human")
obs, reward, done, info = env.step(ac)
rewards += reward
if done:
print(env_id, rewards)
rewards = 0
obs = env.reset()
env.close()
del env
def example_custom_dmc_and_mp(seed=1, iterations=1, render=True):
"""
Example for running a custom movement primitive based environments.
Our already registered environments follow the same structure.
Hence, this also allows to adjust hyperparameters of the movement primitives.
Yet, we recommend the method above if you are just interested in chaining those parameters for existing tasks.
We appreciate PRs for custom environments (especially MP wrappers of existing tasks)
for our repo: https://github.com/ALRhub/fancy_gym/
Args:
seed: seed for deterministic behaviour
iterations: Number of rollout steps to run
render: Render the episode
Returns:
"""
# Base DMC name, according to structure of above example
base_env_id = "dmc:ball_in_cup-catch"
# Replace this wrapper with the custom wrapper for your environment by inheriting from the RawInterfaceWrapper.
# You can also add other gym.Wrappers in case they are needed.
wrappers = [fancy_gym.dmc.suite.ball_in_cup.MPWrapper]
# # For a ProMP
trajectory_generator_kwargs = {'trajectory_generator_type': 'promp'}
phase_generator_kwargs = {'phase_generator_type': 'linear'}
controller_kwargs = {'controller_type': 'motor',
"p_gains": 1.0,
"d_gains": 0.1,}
basis_generator_kwargs = {'basis_generator_type': 'zero_rbf',
'num_basis': 5,
'num_basis_zero_start': 1
}
# For a DMP
# trajectory_generator_kwargs = {'trajectory_generator_type': 'dmp'}
# phase_generator_kwargs = {'phase_generator_type': 'exp',
# 'alpha_phase': 2}
# controller_kwargs = {'controller_type': 'motor',
# "p_gains": 1.0,
# "d_gains": 0.1,
# }
# basis_generator_kwargs = {'basis_generator_type': 'rbf',
# 'num_basis': 5
# }
env = fancy_gym.make_bb(env_id=base_env_id, wrappers=wrappers, black_box_kwargs={},
traj_gen_kwargs=trajectory_generator_kwargs, controller_kwargs=controller_kwargs,
phase_kwargs=phase_generator_kwargs, basis_kwargs=basis_generator_kwargs,
seed=seed)
# This renders the full MP trajectory
# It is only required to call render() once in the beginning, which renders every consecutive trajectory.
# Resetting to no rendering, can be achieved by render(mode=None).
# It is also possible to change them mode multiple times when
# e.g. only every nth trajectory should be displayed.
if render:
env.render(mode="human")
rewards = 0
obs = env.reset()
# number of samples/full trajectories (multiple environment steps)
for i in range(iterations):
ac = env.action_space.sample()
obs, reward, done, info = env.step(ac)
rewards += reward
if done:
print(base_env_id, rewards)
rewards = 0
obs = env.reset()
env.close()
del env
if __name__ == '__main__':
# Disclaimer: DMC environments require the seed to be specified in the beginning.
# Adjusting it afterwards with env.seed() is not recommended as it does not affect the underlying physics.
# For rendering DMC
# export MUJOCO_GL="osmesa"
render = True
# # Standard DMC Suite tasks
example_dmc("dmc:fish-swim", seed=10, iterations=1000, render=render)
#
# # Manipulation tasks
# # Disclaimer: The vision versions are currently not integrated and yield an error
example_dmc("dmc:manipulation-reach_site_features", seed=10, iterations=250, render=render)
#
# # Gym + DMC hybrid task provided in the MP framework
example_dmc("dmc_ball_in_cup-catch_promp-v0", seed=10, iterations=1, render=render)
# Custom DMC task # Different seed, because the episode is longer for this example and the name+seed combo is
# already registered above
example_custom_dmc_and_mp(seed=11, iterations=1, render=render)
+100
View File
@@ -0,0 +1,100 @@
from collections import defaultdict
import gym
import numpy as np
import fancy_gym
def example_general(env_id="Pendulum-v1", seed=1, iterations=1000, render=True):
"""
Example for running any env in the step based setting.
This also includes DMC environments when leveraging our custom make_env function.
Args:
env_id: OpenAI/Custom gym task id or either `domain_name-task_name` or `manipulation-environment_name` for DMC tasks
seed: seed for deterministic behaviour
iterations: Number of rollout steps to run
render: Render the episode
Returns:
"""
env = fancy_gym.make(env_id, seed)
rewards = 0
obs = env.reset()
print("Observation shape: ", env.observation_space.shape)
print("Action shape: ", env.action_space.shape)
# number of environment steps
for i in range(iterations):
obs, reward, done, info = env.step(env.action_space.sample())
rewards += reward
if render:
env.render()
if done:
print(rewards)
rewards = 0
obs = env.reset()
def example_async(env_id="HoleReacher-v0", n_cpu=4, seed=int('533D', 16), n_samples=800):
"""
Example for running any env in a vectorized multiprocessing setting to generate more samples faster.
This also includes DMC and DMP environments when leveraging our custom make_env function.
Be aware, increasing the number of environments reduces the total length of the individual episodes.
Args:
env_id: OpenAI/Custom gym task id or either `domain_name-task_name` or `manipulation-environment_name` for DMC tasks
seed: seed for deterministic behaviour
n_cpu: Number of cpus cores to use in parallel
n_samples: number of samples generated in total by all environments.
Returns: Tuple of (obs, reward, done, info) with type np.ndarray
"""
env = gym.vector.AsyncVectorEnv([fancy_gym.make_rank(env_id, seed, i) for i in range(n_cpu)])
# OR
# envs = gym.vector.AsyncVectorEnv([make_env(env_id, seed + i) for i in range(n_cpu)])
# for plotting
rewards = np.zeros(n_cpu)
buffer = defaultdict(list)
obs = env.reset()
# this would generate more samples than requested if n_samples % num_envs != 0
repeat = int(np.ceil(n_samples / env.num_envs))
for i in range(repeat):
obs, reward, done, info = env.step(env.action_space.sample())
buffer['obs'].append(obs)
buffer['reward'].append(reward)
buffer['done'].append(done)
buffer['info'].append(info)
rewards += reward
if np.any(done):
print(f"Reward at iteration {i}: {rewards[done]}")
rewards[done] = 0
# do not return values above threshold
return *map(lambda v: np.stack(v)[:n_samples], buffer.values()),
if __name__ == '__main__':
render = True
# Basic gym task
example_general("Pendulum-v1", seed=10, iterations=200, render=render)
# Mujoco task from framework
example_general("Reacher5d-v0", seed=10, iterations=200, render=render)
# # OpenAI Mujoco task
example_general("HalfCheetah-v2", seed=10, render=render)
# Vectorized multiprocessing environments
# example_async(env_id="HoleReacher-v0", n_cpu=2, seed=int('533D', 16), n_samples=2 * 200)
+134
View File
@@ -0,0 +1,134 @@
import fancy_gym
def example_dmc(env_id="fish-swim", seed=1, iterations=1000, render=True):
"""
Example for running a MetaWorld based env in the step based setting.
The env_id has to be specified as `task_name-v2`. V1 versions are not supported and we always
return the observable goal version.
All tasks can be found here: https://arxiv.org/pdf/1910.10897.pdf or https://meta-world.github.io/
Args:
env_id: `task_name-v2`
seed: seed for deterministic behaviour (TODO: currently not working due to an issue in MetaWorld code)
iterations: Number of rollout steps to run
render: Render the episode
Returns:
"""
env = fancy_gym.make(env_id, seed)
rewards = 0
obs = env.reset()
print("observation shape:", env.observation_space.shape)
print("action shape:", env.action_space.shape)
for i in range(iterations):
ac = env.action_space.sample()
if render:
# THIS NEEDS TO BE SET TO FALSE FOR NOW, BECAUSE THE INTERFACE FOR RENDERING IS DIFFERENT TO BASIC GYM
# TODO: Remove this, when Metaworld fixes its interface.
env.render(False)
obs, reward, done, info = env.step(ac)
rewards += reward
if done:
print(env_id, rewards)
rewards = 0
obs = env.reset()
env.close()
del env
def example_custom_dmc_and_mp(seed=1, iterations=1, render=True):
"""
Example for running a custom movement primitive based environments.
Our already registered environments follow the same structure.
Hence, this also allows to adjust hyperparameters of the movement primitives.
Yet, we recommend the method above if you are just interested in chaining those parameters for existing tasks.
We appreciate PRs for custom environments (especially MP wrappers of existing tasks)
for our repo: https://github.com/ALRhub/fancy_gym/
Args:
seed: seed for deterministic behaviour (TODO: currently not working due to an issue in MetaWorld code)
iterations: Number of rollout steps to run
render: Render the episode (TODO: currently not working due to an issue in MetaWorld code)
Returns:
"""
# Base MetaWorld name, according to structure of above example
base_env_id = "metaworld:button-press-v2"
# Replace this wrapper with the custom wrapper for your environment by inheriting from the RawInterfaceWrapper.
# You can also add other gym.Wrappers in case they are needed.
wrappers = [fancy_gym.meta.goal_object_change_mp_wrapper.MPWrapper]
# # For a ProMP
# trajectory_generator_kwargs = {'trajectory_generator_type': 'promp'}
# phase_generator_kwargs = {'phase_generator_type': 'linear'}
# controller_kwargs = {'controller_type': 'metaworld'}
# basis_generator_kwargs = {'basis_generator_type': 'zero_rbf',
# 'num_basis': 5,
# 'num_basis_zero_start': 1
# }
# For a DMP
trajectory_generator_kwargs = {'trajectory_generator_type': 'dmp'}
phase_generator_kwargs = {'phase_generator_type': 'exp',
'alpha_phase': 2}
controller_kwargs = {'controller_type': 'metaworld'}
basis_generator_kwargs = {'basis_generator_type': 'rbf',
'num_basis': 5
}
env = fancy_gym.make_bb(env_id=base_env_id, wrappers=wrappers, black_box_kwargs={},
traj_gen_kwargs=trajectory_generator_kwargs, controller_kwargs=controller_kwargs,
phase_kwargs=phase_generator_kwargs, basis_kwargs=basis_generator_kwargs,
seed=seed)
# This renders the full MP trajectory
# It is only required to call render() once in the beginning, which renders every consecutive trajectory.
# Resetting to no rendering, can be achieved by render(mode=None).
# It is also possible to change them mode multiple times when
# e.g. only every nth trajectory should be displayed.
if render:
raise ValueError("Metaworld render interface bug does not allow to render() fixes its interface. "
"A temporary workaround is to alter their code in MujocoEnv render() from "
"`if not offscreen` to `if not offscreen or offscreen == 'human'`.")
# TODO: Remove this, when Metaworld fixes its interface.
# env.render(mode="human")
rewards = 0
obs = env.reset()
# number of samples/full trajectories (multiple environment steps)
for i in range(iterations):
ac = env.action_space.sample()
obs, reward, done, info = env.step(ac)
rewards += reward
if done:
print(base_env_id, rewards)
rewards = 0
obs = env.reset()
env.close()
del env
if __name__ == '__main__':
# Disclaimer: MetaWorld environments require the seed to be specified in the beginning.
# Adjusting it afterwards with env.seed() is not recommended as it may not affect the underlying behavior.
# For rendering it might be necessary to specify your OpenGL installation
# export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libGLEW.so
render = False
# # Standard Meta world tasks
example_dmc("metaworld:button-press-v2", seed=10, iterations=500, render=render)
# # MP + MetaWorld hybrid task provided in the our framework
example_dmc("ButtonPressProMP-v2", seed=10, iterations=1, render=render)
#
# # Custom MetaWorld task
example_custom_dmc_and_mp(seed=10, iterations=1, render=render)
@@ -0,0 +1,169 @@
import fancy_gym
def example_mp(env_name="HoleReacherProMP-v0", seed=1, iterations=1, render=True):
"""
Example for running a black box based environment, which is already registered
Args:
env_name: Black box env_id
seed: seed for deterministic behaviour
iterations: Number of rollout steps to run
render: Render the episode
Returns:
"""
# Equivalent to gym, we have a make function which can be used to create environments.
# It takes care of seeding and enables the use of a variety of external environments using the gym interface.
env = fancy_gym.make(env_name, seed)
returns = 0
# env.render(mode=None)
obs = env.reset()
# number of samples/full trajectories (multiple environment steps)
for i in range(iterations):
if render and i % 2 == 0:
# This renders the full MP trajectory
# It is only required to call render() once in the beginning, which renders every consecutive trajectory.
# Resetting to no rendering, can be achieved by render(mode=None).
# It is also possible to change the mode multiple times when
# e.g. only every second trajectory should be displayed, such as here
# Just make sure the correct mode is set before executing the step.
env.render(mode="human")
else:
env.render(mode=None)
# Now the action space is not the raw action but the parametrization of the trajectory generator,
# such as a ProMP
ac = env.action_space.sample()
# This executes a full trajectory and gives back the context (obs) of the last step in the trajectory, or the
# full observation space of the last step, if replanning/sub-trajectory learning is used. The 'reward' is equal
# to the return of a trajectory. Default is the sum over the step-wise rewards.
obs, reward, done, info = env.step(ac)
# Aggregated returns
returns += reward
if done:
print(reward)
obs = env.reset()
def example_custom_mp(env_name="Reacher5dProMP-v0", seed=1, iterations=1, render=True):
"""
Example for running a movement primitive based environment, which is already registered
Args:
env_name: DMP env_id
seed: seed for deterministic behaviour
iterations: Number of rollout steps to run
render: Render the episode
Returns:
"""
# Changing the arguments of the black box env is possible by providing them to gym as with all kwargs.
# E.g. here for way to many basis functions
env = fancy_gym.make(env_name, seed, basis_generator_kwargs={'num_basis': 1000})
# env = fancy_gym.make(env_name, seed)
# mp_dict.update({'black_box_kwargs': {'learn_sub_trajectories': True}})
# mp_dict.update({'black_box_kwargs': {'do_replanning': lambda pos, vel, t: lambda t: t % 100}})
returns = 0
obs = env.reset()
# This time rendering every trajectory
if render:
env.render(mode="human")
# number of samples/full trajectories (multiple environment steps)
for i in range(iterations):
ac = env.action_space.sample()
obs, reward, done, info = env.step(ac)
returns += reward
if done:
print(i, reward)
obs = env.reset()
return obs
def example_fully_custom_mp(seed=1, iterations=1, render=True):
"""
Example for running a custom movement primitive based environments.
Our already registered environments follow the same structure.
Hence, this also allows to adjust hyperparameters of the movement primitives.
Yet, we recommend the method above if you are just interested in changing those parameters for existing tasks.
We appreciate PRs for custom environments (especially MP wrappers of existing tasks)
for our repo: https://github.com/ALRhub/fancy_gym/
Args:
seed: seed
iterations: Number of rollout steps to run
render: Render the episode
Returns:
"""
base_env_id = "HoleReacher-v0"
# Replace this wrapper with the custom wrapper for your environment by inheriting from the RawInterfaceWrapper.
# You can also add other gym.Wrappers in case they are needed.
wrappers = [fancy_gym.envs.classic_control.hole_reacher.MPWrapper]
# # For a ProMP
# trajectory_generator_kwargs = {'trajectory_generator_type': 'promp',
# 'weight_scale': 2}
# phase_generator_kwargs = {'phase_generator_type': 'linear'}
# controller_kwargs = {'controller_type': 'velocity'}
# basis_generator_kwargs = {'basis_generator_type': 'zero_rbf',
# 'num_basis': 5,
# 'num_basis_zero_start': 1
# }
# For a DMP
trajectory_generator_kwargs = {'trajectory_generator_type': 'dmp',
'weight_scale': 500}
phase_generator_kwargs = {'phase_generator_type': 'exp',
'alpha_phase': 2.5}
controller_kwargs = {'controller_type': 'velocity'}
basis_generator_kwargs = {'basis_generator_type': 'rbf',
'num_basis': 5
}
env = fancy_gym.make_bb(env_id=base_env_id, wrappers=wrappers, black_box_kwargs={},
traj_gen_kwargs=trajectory_generator_kwargs, controller_kwargs=controller_kwargs,
phase_kwargs=phase_generator_kwargs, basis_kwargs=basis_generator_kwargs,
seed=seed)
if render:
env.render(mode="human")
rewards = 0
obs = env.reset()
# number of samples/full trajectories (multiple environment steps)
for i in range(iterations):
ac = env.action_space.sample()
obs, reward, done, info = env.step(ac)
rewards += reward
if done:
print(rewards)
rewards = 0
obs = env.reset()
if __name__ == '__main__':
render = True
# DMP
example_mp("HoleReacherDMP-v0", seed=10, iterations=5, render=render)
#
# # ProMP
example_mp("HoleReacherProMP-v0", seed=10, iterations=5, render=render)
# Altered basis functions
obs1 = example_custom_mp("Reacher5dProMP-v0", seed=10, iterations=5, render=render)
# Custom MP
example_fully_custom_mp(seed=10, iterations=1, render=render)
+37
View File
@@ -0,0 +1,37 @@
import fancy_gym
def example_mp(env_name, seed=1, render=True):
"""
Example for running a movement primitive based version of a OpenAI-gym environment, which is already registered.
For more information on movement primitive specific stuff, look at the traj_gen examples.
Args:
env_name: ProMP env_id
seed: seed
render: boolean
Returns:
"""
# While in this case gym.make() is possible to use as well, we recommend our custom make env function.
env = fancy_gym.make(env_name, seed)
returns = 0
obs = env.reset()
# number of samples/full trajectories (multiple environment steps)
for i in range(10):
if render and i % 2 == 0:
env.render(mode="human")
else:
env.render(mode=None)
ac = env.action_space.sample()
obs, reward, done, info = env.step(ac)
returns += reward
if done:
print(returns)
obs = env.reset()
if __name__ == '__main__':
example_mp("ReacherProMP-v2")
@@ -0,0 +1,69 @@
from collections import OrderedDict
import numpy as np
from matplotlib import pyplot as plt
import fancy_gym
# This might work for some environments, however, please verify either way the correct trajectory information
# for your environment are extracted below
SEED = 1
env_id = "Reacher5dProMP-v0"
env = fancy_gym.make(env_id, seed=SEED, controller_kwargs={'p_gains': 0.05, 'd_gains': 0.05}).env
env.action_space.seed(SEED)
# Plot difference between real trajectory and target MP trajectory
env.reset()
w = env.action_space.sample()
pos, vel = env.get_trajectory(w)
base_shape = env.env.action_space.shape
actual_pos = np.zeros((len(pos), *base_shape))
actual_vel = np.zeros((len(pos), *base_shape))
act = np.zeros((len(pos), *base_shape))
plt.ion()
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
img = ax.imshow(env.env.render(mode="rgb_array"))
fig.show()
for t, pos_vel in enumerate(zip(pos, vel)):
actions = env.tracking_controller.get_action(pos_vel[0], pos_vel[1], env.current_vel, env.current_pos)
actions = np.clip(actions, env.env.action_space.low, env.env.action_space.high)
_, _, _, _ = env.env.step(actions)
if t % 15 == 0:
img.set_data(env.env.render(mode="rgb_array"))
fig.canvas.draw()
fig.canvas.flush_events()
act[t, :] = actions
# TODO verify for your environment
actual_pos[t, :] = env.current_pos
actual_vel[t, :] = env.current_vel
plt.figure(figsize=(15, 5))
plt.subplot(131)
plt.title("Position")
p1 = plt.plot(actual_pos, c='C0', label="true")
p2 = plt.plot(pos, c='C1', label="MP")
plt.xlabel("Episode steps")
handles, labels = plt.gca().get_legend_handles_labels()
by_label = OrderedDict(zip(labels, handles))
plt.legend(by_label.values(), by_label.keys())
plt.subplot(132)
plt.title("Velocity")
plt.plot(actual_vel, c='C0', label="true")
plt.plot(vel, c='C1', label="MP")
plt.xlabel("Episode steps")
plt.subplot(133)
plt.title(f"Actions {np.std(act, axis=0)}")
plt.plot(act, c="C0"),
plt.xlabel("Episode steps")
plt.show()