Author SHA1 Message Date
dodox a1e0acf2c9 Replace all links to temporary docs hosting with final ones 2024-02-10 13:18:51 +01:00
18 changed files with 30 additions and 155 deletions
-40
View File
@@ -1,40 +0,0 @@
name: Deploy static docs to Pages
on:
push:
branches: ["release"]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
# Single deploy job since we're just deploying
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Pages
uses: actions/configure-pages@v4
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: 'docs/build/html'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
+8 -8
View File
@@ -10,25 +10,25 @@ Built upon the foundation of [Gymnasium](https://gymnasium.farama.org) (a mainta
**Key Features**:
- **New Challenging Environments**: `fancy_gym` includes several new environments ([Panda Box Pushing](https://dominik-roth.eu/fancy/envs/fancy/mujoco.html#box-pushing), [Table Tennis](https://dominik-roth.eu/fancy/envs/fancy/mujoco.html#table-tennis), [etc.](https://dominik-roth.eu/fancy/envs/fancy/index.html)) that present a higher degree of difficulty, pushing the boundaries of reinforcement learning research.
- **New Challenging Environments**: `fancy_gym` includes several new environments ([Panda Box Pushing](https://alrhub.github.io/fancy_gym/envs/fancy/mujoco.html#box-pushing), [Table Tennis](https://alrhub.github.io/fancy_gym/envs/fancy/mujoco.html#table-tennis), [etc.](https://alrhub.github.io/fancy_gym/envs/fancy/index.html)) that present a higher degree of difficulty, pushing the boundaries of reinforcement learning research.
- **Support for Movement Primitives**: `fancy_gym` supports a range of movement primitives (MPs), including Dynamic Movement Primitives (DMPs), Probabilistic Movement Primitives (ProMP), and Probabilistic Dynamic Movement Primitives (ProDMP).
- **Upgrade to Movement Primitives**: With our framework, its straightforward to transform standard Gymnasium environments into environments that support movement primitives.
- **Benchmark Suite Compatibility**: `fancy_gym` makes it easy to access renowned benchmark suites such as [DeepMind Control](dominik-roth.eu/fancy/envs/dmc.html)
and [Metaworld](https://dominik-roth.eu/fancy/envs/meta.html), whether you want to use them in the regular step-based setting or using MPs.
- **Contribute Your Own Environments**: If youre inspired to create custom gym environments, both step-based and with movement primitives, this [guide](https://dominik-roth.eu/fancy/guide/upgrading_envs.html) will assist you. We encourage and highly appreciate submissions via PRs to integrate these environments into `fancy_gym`.
- **Benchmark Suite Compatibility**: `fancy_gym` makes it easy to access renowned benchmark suites such as [DeepMind Control](https://alrhub.github.io/fancy_gym/envs/dmc.html)
and [Metaworld](https://alrhub.github.io/fancy_gym/envs/meta.html), whether you want to use them in the regular step-based setting or using MPs.
- **Contribute Your Own Environments**: If youre inspired to create custom gym environments, both step-based and with movement primitives, this [guide](https://alrhub.github.io/fancy_gym/guide/upgrading_envs.html) will assist you. We encourage and highly appreciate submissions via PRs to integrate these environments into `fancy_gym`.
## Quickstart Guide
| ⚠ We recommend installing `fancy_gym` into a virtual environment as provided by [venv](https://docs.python.org/3/library/venv.html), [Poetry](https://python-poetry.org/) or [Conda](https://docs.conda.io/en/latest/). |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
Install via pip [or use an alternative installation method](https://dominik-roth.eu/fancy/guide/installation.html)
Install via pip [or use an alternative installation method](https://alrhub.github.io/fancy_gym/guide/installation.html)
```bash
pip install 'fancy_gym[all]'
```
Try out one of our step-based environments [or explore our other envs](https://dominik-roth.eu/fancy/envs/fancy/index.html)
Try out one of our step-based environments [or explore our other envs](https://alrhub.github.io/fancy_gym/envs/fancy/index.html)
```python
import gymnasium as gym
@@ -48,7 +48,7 @@ Try out one of our step-based environments [or explore our other envs](https://d
observation, info = env.reset()
```
Explore the MP-based variant [or learn more about Movement Primitives (MPs)](https://dominik-roth.eu/fancy/guide/episodic_rl.html)
Explore the MP-based variant [or learn more about Movement Primitives (MPs)](https://alrhub.github.io/fancy_gym/guide/episodic_rl.html)
```python
import gymnasium as gym
@@ -66,7 +66,7 @@ Explore the MP-based variant [or learn more about Movement Primitives (MPs)](htt
## Documentation
Documentation for `fancy_gym` can be found [here](https://dominik-roth.eu/fancy); Usage Examples can be found [here](https://dominik-roth.eu/fancy/examples/general.html).
Documentation for `fancy_gym` can be found [here](https://alrhub.github.io/fancy_gym/); Usage Examples can be found [here](https://alrhub.github.io/fancy_gym/examples/general.html).
## Citing the Project
@@ -115,7 +115,6 @@ class AntJumpEnv(AntEnvCustomXML):
contact_force_range=contact_force_range,
reset_noise_scale=reset_noise_scale,
exclude_current_positions_from_observation=exclude_current_positions_from_observation, **kwargs)
self.render_active = False
def step(self, action):
self.current_step += 1
@@ -154,15 +153,8 @@ class AntJumpEnv(AntEnvCustomXML):
}
truncated = False
if self.render_active and self.render_mode=='human':
self.render()
return obs, reward, terminated, truncated, info
def render(self):
self.render_active = True
return super().render()
def _get_obs(self):
return np.append(super()._get_obs(), self.goal)
+1 -9
View File
@@ -44,7 +44,6 @@ class BeerPongEnv(MujocoEnv, utils.EzPickle):
}
def __init__(self, **kwargs):
utils.EzPickle.__init__(self)
self._steps = 0
# Small Context -> Easier. Todo: Should we do different versions?
# self.xml_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "assets", "beerpong_wo_cup.xml")
@@ -90,7 +89,7 @@ class BeerPongEnv(MujocoEnv, utils.EzPickle):
observation_space=self.observation_space,
**kwargs
)
self.render_active = False
utils.EzPickle.__init__(self)
@property
def start_pos(self):
@@ -170,15 +169,8 @@ class BeerPongEnv(MujocoEnv, utils.EzPickle):
truncated = False
if self.render_active and self.render_mode=='human':
self.render()
return ob, reward, terminated, truncated, infos
def render(self):
self.render_active = True
return super().render()
def _get_obs(self):
theta = self.data.qpos.flat[:7].copy()
theta_dot = self.data.qvel.flat[:7].copy()
@@ -4,7 +4,6 @@ import numpy as np
from gymnasium import utils, spaces
from gymnasium.envs.mujoco import MujocoEnv
from fancy_gym.envs.mujoco.box_pushing.box_pushing_utils import rot_to_quat, get_quaternion_error, rotation_distance
from fancy_gym.envs.mujoco.box_pushing.box_pushing_utils import rot_to_quat, get_quaternion_error, rotation_distance
from fancy_gym.envs.mujoco.box_pushing.box_pushing_utils import q_max, q_min, q_dot_max, q_torque_max
from fancy_gym.envs.mujoco.box_pushing.box_pushing_utils import desired_rod_quat
@@ -61,7 +60,6 @@ class BoxPushingEnvBase(MujocoEnv, utils.EzPickle):
frame_skip=self.frame_skip,
observation_space=self.observation_space, **kwargs)
self.action_space = spaces.Box(low=-1, high=1, shape=(7,))
self.render_active = False
def step(self, action):
action = 10 * np.clip(action, self.action_space.low, self.action_space.high)
@@ -110,15 +108,8 @@ class BoxPushingEnvBase(MujocoEnv, utils.EzPickle):
terminated = episode_end and infos['is_success']
truncated = episode_end and not infos['is_success']
if self.render_active and self.render_mode=='human':
self.render()
return obs, reward, terminated, truncated, infos
def render(self):
self.render_active = True
return super().render()
def reset_model(self):
# rest box to initial position
self.set_state(self.init_qpos_box_pushing, self.init_qvel_box_pushing)
@@ -60,11 +60,7 @@ class HalfCheetahEnvCustomXML(HalfCheetahEnv):
default_camera_config=DEFAULT_CAMERA_CONFIG,
**kwargs,
)
self.render_active = False
def render(self):
self.render_active = True
return super().render()
class HalfCheetahJumpEnv(HalfCheetahEnvCustomXML):
"""
@@ -124,9 +120,6 @@ class HalfCheetahJumpEnv(HalfCheetahEnvCustomXML):
'max_height': self.max_height
}
if self.render_active and self.render_mode=='human':
self.render()
return observation, reward, terminated, truncated, info
def _get_obs(self):
@@ -88,12 +88,6 @@ class HopperEnvCustomXML(HopperEnv):
**kwargs,
)
self.render_active = False
def render(self):
self.render_active = True
return super().render()
class HopperJumpEnv(HopperEnvCustomXML):
"""
@@ -207,10 +201,6 @@ class HopperJumpEnv(HopperEnvCustomXML):
healthy=self.is_healthy,
contact_dist=self.contact_dist or 0
)
if self.render_active and self.render_mode=='human':
self.render()
return observation, reward, terminated, truncated, info
def _get_obs(self):
@@ -140,9 +140,6 @@ class HopperJumpOnBoxEnv(HopperEnvCustomXML):
truncated = self.current_step >= self.max_episode_steps and not terminated
if self.render_active and self.render_mode=='human':
self.render()
return observation, reward, terminated, truncated, info
def _get_obs(self):
@@ -61,8 +61,6 @@ class HopperThrowEnv(HopperEnvCustomXML):
exclude_current_positions_from_observation=exclude_current_positions_from_observation,
**kwargs)
self.render_active = False
def step(self, action):
self.current_step += 1
self.do_simulation(action, self.frame_skip)
@@ -96,15 +94,8 @@ class HopperThrowEnv(HopperEnvCustomXML):
}
truncated = False
if self.render_active and self.render_mode=='human':
self.render()
return observation, reward, terminated, truncated, info
def render(self):
self.render_active = True
return super().render()
def _get_obs(self):
return np.append(super()._get_obs(), self.goal)
@@ -68,7 +68,6 @@ class HopperThrowInBasketEnv(HopperEnvCustomXML):
reset_noise_scale=reset_noise_scale,
exclude_current_positions_from_observation=exclude_current_positions_from_observation,
**kwargs)
self.render_active = False
def step(self, action):
@@ -119,15 +118,8 @@ class HopperThrowInBasketEnv(HopperEnvCustomXML):
}
truncated = False
if self.render_active and self.render_mode=='human':
self.render()
return observation, reward, terminated, truncated, info
def render(self):
self.render_active = True
return super().render()
def _get_obs(self):
return np.append(super()._get_obs(), self.basket_x)
-9
View File
@@ -47,8 +47,6 @@ class ReacherEnv(MujocoEnv, utils.EzPickle):
**kwargs
)
self.render_active = False
def step(self, action):
self._steps += 1
@@ -79,15 +77,8 @@ class ReacherEnv(MujocoEnv, utils.EzPickle):
goal=self.goal if hasattr(self, "goal") else None
)
if self.render_active and self.render_mode=='human':
self.render()
return ob, reward, terminated, truncated, info
def render(self):
self.render_active = True
return super().render()
def distance_reward(self):
vec = self.get_body_com("fingertip") - self.get_body_com("target")
return -self._reward_weight * np.linalg.norm(vec)
@@ -71,8 +71,6 @@ class TableTennisEnv(MujocoEnv, utils.EzPickle):
observation_space=self.observation_space,
**kwargs)
self.render_active = False
if ctxt_dim == 2:
self.context_bounds = CONTEXT_BOUNDS_2DIMS
elif ctxt_dim == 4:
@@ -160,15 +158,8 @@ class TableTennisEnv(MujocoEnv, utils.EzPickle):
terminated, truncated = self._terminated, False
if self.render_active and self.render_mode=='human':
self.render()
return self._get_obs(), reward, terminated, truncated, info
def render(self):
self.render_active = True
return super().render()
def _contact_checker(self, id_1, id_2):
for coni in range(0, self.data.ncon):
con = self.data.contact[coni]
@@ -79,8 +79,6 @@ class Walker2dEnvCustomXML(Walker2dEnv):
**kwargs,
)
self.render_active = False
class Walker2dJumpEnv(Walker2dEnvCustomXML):
"""
@@ -147,15 +145,8 @@ class Walker2dJumpEnv(Walker2dEnvCustomXML):
}
truncated = False
if self.render_active and self.render_mode=='human':
self.render()
return observation, reward, terminated, truncated, info
def render(self):
self.render_active = True
return super().render()
def _get_obs(self):
return np.append(super()._get_obs(), self.goal)
@@ -3,14 +3,14 @@ import fancy_gym
def example_run_replanning_env(env_name="fancy_ProDMP/BoxPushingDenseReplan-v0", seed=1, iterations=1, render=False):
env = gym.make(env_name, render_mode='human' if render else None)
env = gym.make(env_name)
env.reset(seed=seed)
for i in range(iterations):
while True:
ac = env.action_space.sample()
obs, reward, terminated, truncated, info = env.step(ac)
if render:
env.render()
env.render(mode="human")
if terminated or truncated:
env.reset()
break
@@ -38,13 +38,13 @@ def example_custom_replanning_envs(seed=0, iteration=100, render=True):
'replanning_schedule': lambda pos, vel, obs, action, t: t % 25 == 0,
'condition_on_desired': True}
base_env = gym.make(base_env_id, render_mode='human' if render else None)
base_env = gym.make(base_env_id)
env = fancy_gym.make_bb(env=base_env, wrappers=wrappers, black_box_kwargs=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()
env.render(mode="human")
obs = env.reset()
+5 -5
View File
@@ -17,7 +17,7 @@ def example_dmc(env_id="dm_control/fish-swim", seed=1, iterations=1000, render=T
Returns:
"""
env = gym.make(env_id, render_mode='human' if render else None)
env = gym.make(env_id)
rewards = 0
obs = env.reset(seed=seed)
print("observation shape:", env.observation_space.shape)
@@ -26,7 +26,7 @@ def example_dmc(env_id="dm_control/fish-swim", seed=1, iterations=1000, render=T
for i in range(iterations):
ac = env.action_space.sample()
if render:
env.render()
env.render(mode="human")
obs, reward, terminated, truncated, info = env.step(ac)
rewards += reward
@@ -84,7 +84,7 @@ def example_custom_dmc_and_mp(seed=1, iterations=1, render=True):
# basis_generator_kwargs = {'basis_generator_type': 'rbf',
# 'num_basis': 5
# }
base_env = gym.make(base_env_id, render_mode='human' if render else None)
base_env = gym.make(base_env_id)
env = fancy_gym.make_bb(env=base_env, 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,
@@ -96,7 +96,7 @@ def example_custom_dmc_and_mp(seed=1, iterations=1, render=True):
# It is also possible to change them mode multiple times when
# e.g. only every nth trajectory should be displayed.
if render:
env.render()
env.render(mode="human")
rewards = 0
obs = env.reset()
@@ -115,7 +115,7 @@ def example_custom_dmc_and_mp(seed=1, iterations=1, render=True):
env.close()
del env
def main(render = False):
def main(render = True):
# # Standard DMC Suite tasks
example_dmc("dm_control/fish-swim", seed=10, iterations=1000, render=render)
#
+2 -2
View File
@@ -21,7 +21,7 @@ def example_general(env_id="Pendulum-v1", seed=1, iterations=1000, render=True):
"""
env = gym.make(env_id, render_mode='human' if render else None)
env = gym.make(env_id)
rewards = 0
obs = env.reset(seed=seed)
print("Observation shape: ", env.observation_space.shape)
@@ -85,7 +85,7 @@ def example_async(env_id="fancy/HoleReacher-v0", n_cpu=4, seed=int('533D', 16),
# do not return values above threshold
return *map(lambda v: np.stack(v)[:n_samples], buffer.values()),
def main(render = False):
def main(render = True):
# Basic gym task
example_general("Pendulum-v1", seed=10, iterations=200, render=render)
+7 -5
View File
@@ -2,7 +2,7 @@ import gymnasium as gym
import fancy_gym
def example_meta(env_id="metaworld/button-press-v2", seed=1, iterations=1000, render=True):
def example_meta(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
@@ -18,7 +18,7 @@ def example_meta(env_id="metaworld/button-press-v2", seed=1, iterations=1000, re
Returns:
"""
env = gym.make(env_id, render_mode='human' if render else None)
env = gym.make(env_id)
rewards = 0
obs = env.reset(seed=seed)
print("observation shape:", env.observation_space.shape)
@@ -27,7 +27,9 @@ def example_meta(env_id="metaworld/button-press-v2", seed=1, iterations=1000, re
for i in range(iterations):
ac = env.action_space.sample()
if render:
env.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, terminated, truncated, info = env.step(ac)
rewards += reward
if terminated or truncated:
@@ -79,7 +81,7 @@ def example_custom_meta_and_mp(seed=1, iterations=1, render=True):
basis_generator_kwargs = {'basis_generator_type': 'rbf',
'num_basis': 5
}
base_env = gym.make(base_env_id, render_mode='human' if render else None)
base_env = gym.make(base_env_id)
env = fancy_gym.make_bb(env=base_env, 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,
@@ -91,7 +93,7 @@ def example_custom_meta_and_mp(seed=1, iterations=1, render=True):
# It is also possible to change them mode multiple times when
# e.g. only every nth trajectory should be displayed.
if render:
env.render()
env.render(mode="human")
rewards = 0
obs = env.reset(seed=seed)
+3 -1
View File
@@ -13,13 +13,15 @@ def example_mp(env_name, seed=1, render=True):
Returns:
"""
env = gym.make(env_name, render_mode='human' if render else None)
env = gym.make(env_name)
returns = 0
obs = env.reset(seed=seed)
# 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()
ac = env.action_space.sample()
obs, reward, terminated, truncated, info = env.step(ac)