Skip to content
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ If you use this in your research, please cite:
author = {Rodrigo de Lazcano and Kallinteris Andreas and Jun Jet Tai and Seungjae Ryan Lee and Jordan Terry},
title = {Gymnasium Robotics},
url = {http://github.com/Farama-Foundation/Gymnasium-Robotics},
version = {1.2.0},
version = {1.2.3},
year = {2023},
}
```
4 changes: 4 additions & 0 deletions docs/_scripts/gen_envs_display.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import os
import re

import gymnasium as gym
from tqdm import tqdm
Expand Down Expand Up @@ -31,6 +32,9 @@
env_type = split_entrypoint[-1]
env_name = split_entrypoint[-1]

# Remove file version from env_name
env_name = re.sub(r"(?:_v(?P<version>\d+))", "", env_name)

if env_type not in filtered_envs_by_type:
filtered_envs_by_type[env_type] = [env_name]
elif env_name not in filtered_envs_by_type[env_type]:
Expand Down
7 changes: 5 additions & 2 deletions docs/_scripts/gen_mds.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

from importlib import import_module
from utils import trim
import re


# REWRITE: generate md's for new environments that don't belong to Fetch or Shadow Hand
Expand Down Expand Up @@ -43,8 +44,6 @@
docstring = trim(docstring)

split_entrypoint = module.split(".")
title_env_name = split_entrypoint[-1].replace("_", " ").title()

if len(split_entrypoint) == 4:
env_type = split_entrypoint[-2]
env_name = split_entrypoint[-1]
Expand All @@ -53,6 +52,10 @@
env_type = split_entrypoint[-1]
env_name = split_entrypoint[-1]

# Remove file version from env_name
env_name = re.sub(r"(?:_v(?P<version>\d+))", "", env_name)
title_env_name = env_name.replace("_", " ").title()

v_path = os.path.join(
os.path.dirname(__file__),
"..",
Expand Down
Binary file modified docs/_static/videos/maze/ant_maze.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/_static/videos/maze/point_maze.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"sphinx.ext.githubpages",
"sphinx.ext.viewcode",
"myst_parser",
"sphinx_github_changelog",
]

source_suffix = {
Expand Down
3 changes: 2 additions & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ envs/MaMuJoCo/index
```{toctree}
:hidden:
:caption: Development
release_notes

Github <https://github.com/Farama-Foundation/Gymnasium-Robotics>
release_notes/index
```

```{project-logo} _static/img/robotics-text.png
Expand Down
8 changes: 8 additions & 0 deletions docs/release_notes/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Release Notes

```{eval-rst}
.. changelog::
:github: https://github.com/Farama-Foundation/Gymnasium-Robotics/releases
:pypi: https://pypi.org/project/gymnasium-robotics/
:changelog-url:
```
2 changes: 1 addition & 1 deletion gymnasium_robotics/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1239,7 +1239,7 @@ def _merge(a, b):
)


__version__ = "1.2.2"
__version__ = "1.2.3"


try:
Expand Down
10 changes: 5 additions & 5 deletions gymnasium_robotics/envs/franka_kitchen/kitchen_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,8 @@ def compute_reward(
desired_goal: "dict[str, np.ndarray]",
info: "dict[str, Any]",
):
for task in info["tasks_to_complete"]:
self.step_task_completions.clear()
for task in self.tasks_to_complete:
distance = np.linalg.norm(achieved_goal[task] - desired_goal[task])
complete = distance < BONUS_THRESH
if complete:
Expand Down Expand Up @@ -394,7 +395,6 @@ def _get_obs(self, robot_obs):
def step(self, action):
robot_obs, _, terminated, truncated, info = self.robot_env.step(action)
obs = self._get_obs(robot_obs)
info = {"tasks_to_complete": list(self.tasks_to_complete)}

reward = self.compute_reward(obs["achieved_goal"], self.goal, info)

Expand All @@ -405,13 +405,13 @@ def step(self, action):
for element in self.step_task_completions
]

info = {"tasks_to_complete": list(self.tasks_to_complete)}
info["step_task_completions"] = self.step_task_completions.copy()

for task in self.step_task_completions:
if task not in self.episode_task_completions:
self.episode_task_completions.append(task)
info["episode_task_completions"] = self.episode_task_completions
self.step_task_completions.clear()
if self.terminate_on_tasks_completed:
# terminate if there are no more tasks to complete
terminated = len(self.episode_task_completions) == len(self.goal.keys())
Expand All @@ -423,9 +423,9 @@ def reset(self, *, seed: Optional[int] = None, **kwargs):
self.episode_task_completions.clear()
robot_obs, _ = self.robot_env.reset(seed=seed)
obs = self._get_obs(robot_obs)
self.task_to_complete = set(self.goal.keys())
self.tasks_to_complete = set(self.goal.keys())
info = {
"tasks_to_complete": self.task_to_complete,
"tasks_to_complete": list(self.tasks_to_complete),
"episode_task_completions": [],
"step_task_completions": [],
}
Expand Down
7 changes: 5 additions & 2 deletions gymnasium_robotics/envs/maze/ant_maze_v4.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,8 @@ class AntMazeEnv(MazeEnv, EzPickle):
### Arguments

* `maze_map` - Optional argument to initialize the environment with a custom maze map.
* `continuing_task` - If set to `True` the episode won't be terminated when reaching the goal, instead a new goal location will be generated. If `False` the environment is terminated when the ant reaches the final goal.
* `continuing_task` - If set to `True` the episode won't be terminated when reaching the goal, instead a new goal location will be generated (unless `reset_target` argument is `True`). If `False` the environment is terminated when the ant reaches the final goal.
* `reset_target` - If set to `True` and the argument `continuing_task` is also `True`, when the ant reaches the target goal the location of the goal will be kept the same and no new goal location will be generated. If `False` a new goal will be generated when reached.
* `use_contact_forces` - If `True` contact forces of the ant are included in the `observation`.

Note that, the maximum number of timesteps before the episode is `truncated` can be increased or decreased by specifying the `max_episode_steps` argument at initialization. For example,
Expand Down Expand Up @@ -216,6 +217,7 @@ def __init__(
maze_map: List[List[Union[str, int]]] = U_MAZE,
reward_type: str = "sparse",
continuing_task: bool = True,
reset_target: bool = False,
**kwargs,
):
# Get the ant.xml path from the Gymnasium package
Expand All @@ -229,6 +231,7 @@ def __init__(
maze_height=0.5,
reward_type=reward_type,
continuing_task=continuing_task,
reset_target=reset_target,
**kwargs,
)
# Create the MuJoCo environment, include position observation of the Ant for GoalEnv
Expand All @@ -255,13 +258,13 @@ def __init__(
)

self.render_mode = render_mode

EzPickle.__init__(
self,
render_mode,
maze_map,
reward_type,
continuing_task,
reset_target,
**kwargs,
)

Expand Down
14 changes: 7 additions & 7 deletions gymnasium_robotics/envs/maze/maze.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,10 +215,10 @@ def reset(
else:
if "goal_cell" in options and options["goal_cell"] is not None:
# assert that goal cell is valid
assert self.maze.map_length > options["goal_cell"][1]
assert self.maze.map_width > options["goal_cell"][0]
assert self.maze.map_length > options["goal_cell"][0]
assert self.maze.map_width > options["goal_cell"][1]
assert (
self.maze.maze_map[options["goal_cell"][1]][options["goal_cell"][0]]
self.maze.maze_map[options["goal_cell"][0]][options["goal_cell"][1]]
!= 1
), f"Goal can't be placed in a wall cell, {options['goal_cell']}"

Expand All @@ -231,11 +231,11 @@ def reset(

if "reset_cell" in options and options["reset_cell"] is not None:
# assert that goal cell is valid
assert self.maze.map_length > options["reset_cell"][1]
assert self.maze.map_width > options["reset_cell"][0]
assert self.maze.map_length > options["reset_cell"][0]
assert self.maze.map_width > options["reset_cell"][1]
assert (
self.maze.maze_map[options["reset_cell"][1]][
options["reset_cell"][0]
self.maze.maze_map[options["reset_cell"][0]][
options["reset_cell"][1]
]
!= 1
), f"Reset can't be placed in a wall cell, {options['reset_cell']}"
Expand Down
33 changes: 26 additions & 7 deletions gymnasium_robotics/envs/maze/maze_v4.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,15 @@ def make_maze(
# If there are no given "r", "g" or "c" cells in the maze data structure,
# any empty cell can be a reset or goal location at initialization.
maze._combined_locations = empty_locations
elif not maze._unique_reset_locations and not maze._combined_locations:
# If there are no given "r" or "c" cells in the maze data structure,
# any empty cell can be a reset location at initialization.
maze._unique_reset_locations = empty_locations
elif not maze._unique_goal_locations and not maze._combined_locations:
# If there are no given "g" or "c" cells in the maze data structure,
# any empty cell can be a gaol location at initialization.
maze._unique_goal_locations = empty_locations

maze._unique_goal_locations += maze._combined_locations
maze._unique_reset_locations += maze._combined_locations

Expand All @@ -238,6 +247,7 @@ def __init__(
agent_xml_path: str,
reward_type: str = "dense",
continuing_task: bool = True,
reset_target: bool = True,
maze_map: List[List[Union[int, str]]] = U_MAZE,
maze_size_scaling: float = 1.0,
maze_height: float = 0.5,
Expand All @@ -247,6 +257,7 @@ def __init__(

self.reward_type = reward_type
self.continuing_task = continuing_task
self.reset_target = reset_target
self.maze, self.tmp_xml_file_path = Maze.make_maze(
agent_xml_path, maze_map, maze_size_scaling, maze_height
)
Expand Down Expand Up @@ -282,6 +293,12 @@ def reset(
seed: Optional[int] = None,
options: Optional[Dict[str, Optional[np.ndarray]]] = None,
):
"""Reset the maze simulation.

Args:
options (dict[str, np.ndarray]): the options dictionary can contain two items, "goal_cell" and "reset_cell" that will set the initial goal and reset location (i,j) in the self.maze.map list of list maze structure.

"""
super().reset(seed=seed)

if options is None:
Expand All @@ -292,10 +309,10 @@ def reset(
else:
if "goal_cell" in options and options["goal_cell"] is not None:
# assert that goal cell is valid
assert self.maze.map_length > options["goal_cell"][1]
assert self.maze.map_width > options["goal_cell"][0]
assert self.maze.map_length > options["goal_cell"][0]
assert self.maze.map_width > options["goal_cell"][1]
assert (
self.maze.maze_map[options["goal_cell"][1]][options["goal_cell"][0]]
self.maze.maze_map[options["goal_cell"][0]][options["goal_cell"][1]]
!= 1
), f"Goal can't be placed in a wall cell, {options['goal_cell']}"

Expand All @@ -309,11 +326,11 @@ def reset(

if "reset_cell" in options and options["reset_cell"] is not None:
# assert that goal cell is valid
assert self.maze.map_length > options["reset_cell"][1]
assert self.maze.map_width > options["reset_cell"][0]
assert self.maze.map_length > options["reset_cell"][0]
assert self.maze.map_width > options["reset_cell"][1]
assert (
self.maze.maze_map[options["reset_cell"][1]][
options["reset_cell"][0]
self.maze.maze_map[options["reset_cell"][0]][
options["reset_cell"][1]
]
!= 1
), f"Reset can't be placed in a wall cell, {options['reset_cell']}"
Expand Down Expand Up @@ -373,8 +390,10 @@ def compute_terminated(

def update_goal(self, achieved_goal: np.ndarray) -> None:
"""Update goal position if continuing task and within goal radius."""

if (
self.continuing_task
and self.reset_target
and bool(np.linalg.norm(achieved_goal - self.goal) <= 0.45)
and len(self.maze.unique_goal_locations) > 1
):
Expand Down
4 changes: 4 additions & 0 deletions gymnasium_robotics/envs/maze/point_maze.py
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ class PointMazeEnv(MazeEnv, EzPickle):

* `maze_map` - Optional argument to initialize the environment with a custom maze map.
* `continuing_task` - If set to `True` the episode won't be terminated when reaching the goal, instead a new goal location will be generated. If `False` the environment is terminated when the ball reaches the final goal.
* `reset_target` - If set to `True` and the argument `continuing_task` is also `True`, when the ant reaches the target goal the location of the goal will be kept the same and no new goal location will be generated. If `False` a new goal will be generated when reached.

Note that, the maximum number of timesteps before the episode is `truncated` can be increased or decreased by specifying the `max_episode_steps` argument at initialization. For example,
to increase the total number of timesteps to 100 make the environment as follows:
Expand Down Expand Up @@ -309,6 +310,7 @@ def __init__(
render_mode: Optional[str] = None,
reward_type: str = "sparse",
continuing_task: bool = True,
reset_target: bool = False,
**kwargs,
):
point_xml_file_path = path.join(
Expand All @@ -321,6 +323,7 @@ def __init__(
maze_height=0.4,
reward_type=reward_type,
continuing_task=continuing_task,
reset_target=reset_target,
**kwargs,
)

Expand Down Expand Up @@ -356,6 +359,7 @@ def __init__(
render_mode,
reward_type,
continuing_task,
reset_target,
**kwargs,
)

Expand Down
Loading