From 700373dba3fe0016408acad140a4e559530f1613 Mon Sep 17 00:00:00 2001
From: Kallinteris Andreas
<30759571+Kallinteris-Andreas@users.noreply.github.com>
Date: Sun, 24 Mar 2024 13:10:24 +0200
Subject: [PATCH 01/26] Update humanoid_v5.py
---
gymnasium/envs/mujoco/humanoid_v5.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gymnasium/envs/mujoco/humanoid_v5.py b/gymnasium/envs/mujoco/humanoid_v5.py
index b6b324b47e..2b87c81f4c 100644
--- a/gymnasium/envs/mujoco/humanoid_v5.py
+++ b/gymnasium/envs/mujoco/humanoid_v5.py
@@ -38,7 +38,7 @@ class HumanoidEnv(MujocoEnv, utils.EzPickle):
:name: humanoid
```
- The action space is a `Box(-1, 1, (17,), float32)`. An action represents the torques applied at the hinge joints.
+ The action space is a `Box(-0.4, 0.4, (17,), float32)`. An action represents the torques applied at the hinge joints.
| Num | Action | Control Min | Control Max | Name (in corresponding XML file) | Joint | Type (Unit) |
| --- | ---------------------------------------------------------------------------------- | ----------- | ----------- | -------------------------------- | ----- | ------------ |
From e169b8fc8b5ae3f5006dfddeb856cebc3fdd927b Mon Sep 17 00:00:00 2001
From: Kallinteris Andreas
<30759571+Kallinteris-Andreas@users.noreply.github.com>
Date: Sun, 24 Mar 2024 13:14:53 +0200
Subject: [PATCH 02/26] Update humanoidstandup_v5.py
---
gymnasium/envs/mujoco/humanoidstandup_v5.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gymnasium/envs/mujoco/humanoidstandup_v5.py b/gymnasium/envs/mujoco/humanoidstandup_v5.py
index 8477ec0ca4..6666274f7a 100644
--- a/gymnasium/envs/mujoco/humanoidstandup_v5.py
+++ b/gymnasium/envs/mujoco/humanoidstandup_v5.py
@@ -32,7 +32,7 @@ class HumanoidStandupEnv(MujocoEnv, utils.EzPickle):
:name: humanoid
```
- The action space is a `Box(-1, 1, (17,), float32)`. An action represents the torques applied at the hinge joints.
+ The action space is a `Box(-0.4, 0.4, (17,), float32)`. An action represents the torques applied at the hinge joints.
| Num | Action | Control Min | Control Max | Name (in corresponding XML file) | Joint | Type (Unit) |
| --- | ---------------------------------------------------------------------------------- | ----------- | ----------- | -------------------------------- | ----- | ------------ |
From 2f656e3bd6deedd78440dc1805ace78a923ef42c Mon Sep 17 00:00:00 2001
From: Kallinteris Andreas
<30759571+Kallinteris-Andreas@users.noreply.github.com>
Date: Thu, 23 May 2024 09:41:36 +0300
Subject: [PATCH 03/26] Update mujoco_env.py
---
gymnasium/envs/mujoco/mujoco_env.py | 199 ++++++++++++----------------
1 file changed, 83 insertions(+), 116 deletions(-)
diff --git a/gymnasium/envs/mujoco/mujoco_env.py b/gymnasium/envs/mujoco/mujoco_env.py
index 5f2fa6396a..70a7aaf155 100644
--- a/gymnasium/envs/mujoco/mujoco_env.py
+++ b/gymnasium/envs/mujoco/mujoco_env.py
@@ -34,19 +34,22 @@ def expand_model_path(model_path: str) -> str:
return fullpath
-class BaseMujocoEnv(gym.Env[NDArray[np.float64], NDArray[np.float32]]):
- """Superclass for all MuJoCo environments."""
+class MujocoEnv(BaseMujocoEnv):
+ """Superclass for MuJoCo based environments."""
def __init__(
self,
- model_path,
- frame_skip,
+ model_path: str,
+ frame_skip: int,
observation_space: Optional[Space],
render_mode: Optional[str] = None,
width: int = DEFAULT_SIZE,
height: int = DEFAULT_SIZE,
camera_id: Optional[int] = None,
camera_name: Optional[str] = None,
+ default_camera_config: Optional[Dict[str, Union[float, int]]] = None,
+ max_geom: int = 1000,
+ visual_options: Dict[int, bool] = {},
):
"""Base abstract class for mujoco based environments.
@@ -59,6 +62,9 @@ def __init__(
height: The height of the render window.
camera_id: The camera ID used.
camera_name: The name of the camera used (can not be used in conjunction with `camera_id`).
+ default_camera_config: configuration for rendering camera.
+ max_geom: max number of rendered geometries.
+ visual_options: render flag options.
Raises:
OSError: when the `model_path` does not exist.
@@ -93,48 +99,79 @@ def __init__(
self.camera_name = camera_name
self.camera_id = camera_id
+ from gymnasium.envs.mujoco.mujoco_rendering import MujocoRenderer
+
+ self.mujoco_renderer = MujocoRenderer(
+ self.model,
+ self.data,
+ default_camera_config,
+ self.width,
+ self.height,
+ max_geom,
+ camera_id,
+ camera_name,
+ visual_options,
+ )
+
def _set_action_space(self):
bounds = self.model.actuator_ctrlrange.copy().astype(np.float32)
low, high = bounds.T
self.action_space = spaces.Box(low=low, high=high, dtype=np.float32)
return self.action_space
- # methods to override:
- # ----------------------------
- def step(
- self, action: NDArray[np.float32]
- ) -> Tuple[NDArray[np.float64], np.float64, bool, bool, Dict[str, np.float64]]:
- raise NotImplementedError
-
- def reset_model(self) -> NDArray[np.float64]:
+ def _initialize_simulation(
+ self,
+ ) -> Tuple["mujoco.MjModel", "mujoco.MjData"]:
"""
- Reset the robot degrees of freedom (qpos and qvel).
- Implement this in each subclass.
+ Initialize MuJoCo simulation data structures `mjModel` and `mjData`.
"""
- raise NotImplementedError
+ model = mujoco.MjModel.from_xml_path(self.fullpath)
+ # MjrContext will copy model.vis.global_.off* to con.off*
+ model.vis.global_.offwidth = self.width
+ model.vis.global_.offheight = self.height
+ data = mujoco.MjData(model)
+ return model, data
- def _initialize_simulation(self) -> Tuple[Any, Any]:
- """
- Initialize MuJoCo simulation data structures mjModel and mjData.
+ def set_state(self, qpos, qvel):
+ """Set the joints position qpos and velocity qvel of the model.
+
+ Note: `qpos` and `qvel` is not the full physics state for all mujoco models/environments https://mujoco.readthedocs.io/en/stable/APIreference/APItypes.html#mjtstate
"""
- raise NotImplementedError
+ assert qpos.shape == (self.model.nq,) and qvel.shape == (self.model.nv,)
+ self.data.qpos[:] = np.copy(qpos)
+ self.data.qvel[:] = np.copy(qvel)
+ if self.model.na == 0:
+ self.data.act[:] = None
+ mujoco.mj_forward(self.model, self.data)
- def _step_mujoco_simulation(self, ctrl, n_frames) -> None:
+ def _step_mujoco_simulation(self, ctrl, n_frames):
"""
Step over the MuJoCo simulation.
"""
- raise NotImplementedError
+ self.data.ctrl[:] = ctrl
- def render(self) -> Union[NDArray[np.float64], None]:
+ mujoco.mj_step(self.model, self.data, nstep=n_frames)
+
+ # As of MuJoCo 2.0, force-related quantities like cacc are not computed
+ # unless there's a force sensor in the model.
+ # See https://github.com/openai/gym/issues/1541
+ mujoco.mj_rnePostConstraint(self.model, self.data)
+
+ def render(self):
"""
Render a frame from the MuJoCo simulation as specified by the render_mode.
"""
- raise NotImplementedError
+ return self.mujoco_renderer.render(self.render_mode)
+
+ def close(self):
+ """Close rendering contexts processes."""
+ if self.mujoco_renderer is not None:
+ self.mujoco_renderer.close()
+
+ def get_body_com(self, body_name):
+ """Return the cartesian position of a body frame."""
+ return self.data.body(body_name).xpos
- # -----------------------------
- def _get_reset_info(self) -> Dict[str, float]:
- """Function that generates the `info` that is returned during a `reset()`."""
- return {}
def reset(
self,
@@ -168,99 +205,29 @@ def do_simulation(self, ctrl, n_frames) -> None:
)
self._step_mujoco_simulation(ctrl, n_frames)
- def close(self):
- """Close all processes like rendering contexts"""
- raise NotImplementedError
-
- def get_body_com(self, body_name) -> NDArray[np.float64]:
- """Return the cartesian position of a body frame"""
- raise NotImplementedError
-
def state_vector(self) -> NDArray[np.float64]:
- """Return the position and velocity joint states of the model"""
+ """Return the position and velocity joint states of the model.
+
+ Note: `qpos` and `qvel` does not constitute the full physics state for all `mujoco` environments see https://mujoco.readthedocs.io/en/stable/computation/index.html#the-state.
+ """
return np.concatenate([self.data.qpos.flat, self.data.qvel.flat])
+ # methods to override:
+ # ----------------------------
+ def step(
+ self, action: NDArray[np.float32]
+ ) -> Tuple[NDArray[np.float64], np.float64, bool, bool, Dict[str, np.float64]]:
+ raise NotImplementedError
-class MujocoEnv(BaseMujocoEnv):
- """Superclass for MuJoCo environments."""
-
- def __init__(
- self,
- model_path,
- frame_skip,
- observation_space: Optional[Space],
- render_mode: Optional[str] = None,
- width: int = DEFAULT_SIZE,
- height: int = DEFAULT_SIZE,
- camera_id: Optional[int] = None,
- camera_name: Optional[str] = None,
- default_camera_config: Optional[Dict[str, Union[float, int]]] = None,
- max_geom: int = 1000,
- visual_options: Dict[int, bool] = {},
- ):
- super().__init__(
- model_path,
- frame_skip,
- observation_space,
- render_mode,
- width,
- height,
- camera_id,
- camera_name,
- )
-
- from gymnasium.envs.mujoco.mujoco_rendering import MujocoRenderer
-
- self.mujoco_renderer = MujocoRenderer(
- self.model,
- self.data,
- default_camera_config,
- self.width,
- self.height,
- max_geom,
- camera_id,
- camera_name,
- visual_options,
- )
-
- def _initialize_simulation(
- self,
- ) -> Tuple["mujoco._structs.MjModel", "mujoco._structs.MjData"]:
- model = mujoco.MjModel.from_xml_path(self.fullpath)
- # MjrContext will copy model.vis.global_.off* to con.off*
- model.vis.global_.offwidth = self.width
- model.vis.global_.offheight = self.height
- data = mujoco.MjData(model)
- return model, data
-
- def set_state(self, qpos, qvel):
- """Set the joints position qpos and velocity qvel of the model.
-
- Note: `qpos` and `qvel` is not the full physics state for all mujoco models/environments https://mujoco.readthedocs.io/en/stable/APIreference/APItypes.html#mjtstate
+ def reset_model(self) -> NDArray[np.float64]:
"""
- assert qpos.shape == (self.model.nq,) and qvel.shape == (self.model.nv,)
- self.data.qpos[:] = np.copy(qpos)
- self.data.qvel[:] = np.copy(qvel)
- if self.model.na == 0:
- self.data.act[:] = None
- mujoco.mj_forward(self.model, self.data)
-
- def _step_mujoco_simulation(self, ctrl, n_frames):
- self.data.ctrl[:] = ctrl
-
- mujoco.mj_step(self.model, self.data, nstep=n_frames)
-
- # As of MuJoCo 2.0, force-related quantities like cacc are not computed
- # unless there's a force sensor in the model.
- # See https://github.com/openai/gym/issues/1541
- mujoco.mj_rnePostConstraint(self.model, self.data)
-
- def render(self):
- return self.mujoco_renderer.render(self.render_mode)
+ Reset the robot degrees of freedom (qpos and qvel).
+ Implement this in each environment subclass.
+ """
+ raise NotImplementedError
- def close(self):
- if self.mujoco_renderer is not None:
- self.mujoco_renderer.close()
+ def _get_reset_info(self) -> Dict[str, float]:
+ """Function that generates the `info` that is returned during a `reset()`."""
+ return {}
- def get_body_com(self, body_name):
- return self.data.body(body_name).xpos
+ # -----------------------------
From 13f67fe44cc3ff0f3874f2059e102691e6e07868 Mon Sep 17 00:00:00 2001
From: Kallinteris Andreas
<30759571+Kallinteris-Andreas@users.noreply.github.com>
Date: Thu, 23 May 2024 09:42:59 +0300
Subject: [PATCH 04/26] Update test_mujoco_v5.py
---
tests/envs/mujoco/test_mujoco_v5.py | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/tests/envs/mujoco/test_mujoco_v5.py b/tests/envs/mujoco/test_mujoco_v5.py
index afba1da473..c7a5fb0c01 100644
--- a/tests/envs/mujoco/test_mujoco_v5.py
+++ b/tests/envs/mujoco/test_mujoco_v5.py
@@ -600,10 +600,7 @@ def test_model_object_count(version: str):
else:
assert env.model.nbvh == 18
assert env.model.njnt == 11
- if version == "v4":
- assert env.model.ngeom == 21
- else:
- assert env.model.ngeom == 20
+ assert env.model.ngeom == 21
assert env.model.ntendon == 0
env = gym.make(f"Reacher-{version}").unwrapped
From 93d8a0cd5ec2b931111982b9cc36f3ffbde39626 Mon Sep 17 00:00:00 2001
From: Kallinteris Andreas
<30759571+Kallinteris-Andreas@users.noreply.github.com>
Date: Sat, 1 Jun 2024 08:40:16 +0000
Subject: [PATCH 05/26] `pre-commit`
---
gymnasium/envs/mujoco/mujoco_env.py | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/gymnasium/envs/mujoco/mujoco_env.py b/gymnasium/envs/mujoco/mujoco_env.py
index 70a7aaf155..2f3e530503 100644
--- a/gymnasium/envs/mujoco/mujoco_env.py
+++ b/gymnasium/envs/mujoco/mujoco_env.py
@@ -1,5 +1,5 @@
from os import path
-from typing import Any, Dict, Optional, Tuple, Union
+from typing import Dict, Optional, Tuple, Union
import numpy as np
from numpy.typing import NDArray
@@ -34,7 +34,7 @@ def expand_model_path(model_path: str) -> str:
return fullpath
-class MujocoEnv(BaseMujocoEnv):
+class MujocoEnv(gym.Env):
"""Superclass for MuJoCo based environments."""
def __init__(
@@ -172,7 +172,6 @@ def get_body_com(self, body_name):
"""Return the cartesian position of a body frame."""
return self.data.body(body_name).xpos
-
def reset(
self,
*,
@@ -207,7 +206,7 @@ def do_simulation(self, ctrl, n_frames) -> None:
def state_vector(self) -> NDArray[np.float64]:
"""Return the position and velocity joint states of the model.
-
+
Note: `qpos` and `qvel` does not constitute the full physics state for all `mujoco` environments see https://mujoco.readthedocs.io/en/stable/computation/index.html#the-state.
"""
return np.concatenate([self.data.qpos.flat, self.data.qvel.flat])
From 5ca94b43b89f67cf72970fe15a3c9d5de5c073b3 Mon Sep 17 00:00:00 2001
From: Kallinteris Andreas
<30759571+Kallinteris-Andreas@users.noreply.github.com>
Date: Sat, 1 Jun 2024 11:48:11 +0300
Subject: [PATCH 06/26] Update test_mujoco_v5.py
---
tests/envs/mujoco/test_mujoco_v5.py | 50 ++++++++++++++---------------
1 file changed, 25 insertions(+), 25 deletions(-)
diff --git a/tests/envs/mujoco/test_mujoco_v5.py b/tests/envs/mujoco/test_mujoco_v5.py
index c7a5fb0c01..bf9c639e4a 100644
--- a/tests/envs/mujoco/test_mujoco_v5.py
+++ b/tests/envs/mujoco/test_mujoco_v5.py
@@ -6,7 +6,7 @@
import pytest
import gymnasium as gym
-from gymnasium.envs.mujoco.mujoco_env import BaseMujocoEnv, MujocoEnv
+from gymnasium.envs.mujoco.mujoco_env import MujocoEnv
from gymnasium.envs.mujoco.mujoco_py_env import BaseMujocoPyEnv
from gymnasium.envs.mujoco.utils import check_mujoco_reset_state
from gymnasium.error import Error
@@ -90,7 +90,7 @@ def test_verify_info_y_position(env_id: str):
def test_verify_info_x_velocity(env_name: str, version: str):
"""Asserts that the environment `info['x_velocity']` is properly assigned."""
env = gym.make(f"{env_name}-{version}").unwrapped
- assert isinstance(env, (BaseMujocoEnv, BaseMujocoPyEnv))
+ assert isinstance(env, (MujocoEnv, BaseMujocoPyEnv))
env.reset()
old_x = env.data.qpos[0]
@@ -107,7 +107,7 @@ def test_verify_info_x_velocity(env_name: str, version: str):
def test_verify_info_y_velocity(env_id: str):
"""Asserts that the environment `info['y_velocity']` is properly assigned."""
env = gym.make(env_id).unwrapped
- assert isinstance(env, (BaseMujocoEnv, BaseMujocoPyEnv))
+ assert isinstance(env, (MujocoEnv, BaseMujocoPyEnv))
env.reset()
old_y = env.data.qpos[1]
@@ -123,7 +123,7 @@ def test_verify_info_y_velocity(env_id: str):
def test_verify_info_xy_velocity_xpos(env_id: str):
"""Asserts that the environment `info['x/y_velocity']` is properly assigned, for the ant environment which uses kinmatics for the velocity."""
env = gym.make(env_id).unwrapped
- assert isinstance(env, (BaseMujocoEnv, BaseMujocoPyEnv))
+ assert isinstance(env, (MujocoEnv, BaseMujocoPyEnv))
env.reset()
old_xy = env.get_body_com("torso")[:2].copy()
@@ -146,7 +146,7 @@ def mass_center(model, data):
return (np.sum(mass * xpos, axis=0) / np.sum(mass))[0:2].copy()
env = gym.make(env_id).unwrapped
- assert isinstance(env, (BaseMujocoEnv, BaseMujocoPyEnv))
+ assert isinstance(env, (MujocoEnv, BaseMujocoPyEnv))
env.reset()
old_xy = mass_center(env.model, env.data)
@@ -178,7 +178,7 @@ def mass_center(model, data):
def test_verify_reward_survive(env_name: str, version: str):
"""Assert that `reward_survive` is 0 on `terminal` states and not 0 on non-`terminal` states."""
env = gym.make(f"{env_name}-{version}", reset_noise_scale=0).unwrapped
- assert isinstance(env, (BaseMujocoEnv, BaseMujocoPyEnv))
+ assert isinstance(env, (MujocoEnv, BaseMujocoPyEnv))
env.reset(seed=0)
env.action_space.seed(1)
@@ -361,7 +361,7 @@ def test_ant_com(version: str):
"""Verify the kinmatic behaviour of the ant."""
# `env` contains `data : MjData` and `model : MjModel`
env = gym.make(f"Ant-{version}").unwrapped
- assert isinstance(env, (BaseMujocoEnv, BaseMujocoPyEnv))
+ assert isinstance(env, (MujocoEnv, BaseMujocoPyEnv))
env.reset() # randomly initlizies the `data.qpos` and `data.qvel`, calls mujoco.mj_forward(env.model, env.data)
x_position_before = env.data.qpos[0]
@@ -382,7 +382,7 @@ def test_ant_com(version: str):
def test_set_state(version: str):
"""Simple Test to verify that `mujocoEnv.set_state()` works correctly."""
env = gym.make(f"Hopper-{version}").unwrapped
- assert isinstance(env, (BaseMujocoEnv, BaseMujocoPyEnv))
+ assert isinstance(env, (MujocoEnv, BaseMujocoPyEnv))
env.reset()
new_qpos = np.array(
[0.00136962, 1.24769787, -0.00459026, -0.00483472, 0.0031327, 0.00412756]
@@ -405,7 +405,7 @@ def test_set_state(version: str):
def test_distance_from_origin_info(env_id: str):
"""Verify that `info"distance_from_origin"` is correct."""
env = gym.make(env_id).unwrapped
- assert isinstance(env, (BaseMujocoEnv, BaseMujocoPyEnv))
+ assert isinstance(env, (MujocoEnv, BaseMujocoPyEnv))
env.reset()
_, _, _, _, info = env.step(env.action_space.sample())
@@ -487,7 +487,7 @@ def test_reset_info(env_name: str, version: str):
def test_inverted_double_pendulum_max_height(version: str):
"""Verify the max height of Inverted Double Pendulum."""
env = gym.make(f"InvertedDoublePendulum-{version}", reset_noise_scale=0).unwrapped
- assert isinstance(env, (BaseMujocoEnv, BaseMujocoPyEnv))
+ assert isinstance(env, (MujocoEnv, BaseMujocoPyEnv))
env.reset()
y = env.data.site_xpos[0][2]
@@ -498,7 +498,7 @@ def test_inverted_double_pendulum_max_height(version: str):
def test_inverted_double_pendulum_max_height_old(version: str):
"""Verify the max height of Inverted Double Pendulum (v4 does not have `reset_noise_scale` argument)."""
env = gym.make(f"InvertedDoublePendulum-{version}").unwrapped
- assert isinstance(env, (BaseMujocoEnv, BaseMujocoPyEnv))
+ assert isinstance(env, (MujocoEnv, BaseMujocoPyEnv))
env.set_state(env.init_qpos, env.init_qvel)
y = env.data.site_xpos[0][2]
@@ -510,7 +510,7 @@ def test_inverted_double_pendulum_max_height_old(version: str):
def test_model_object_count(version: str):
"""Verify that all the objects of the model are loaded, mostly useful for using non-mujoco simulator."""
env = gym.make(f"Ant-{version}").unwrapped
- assert isinstance(env, (BaseMujocoEnv, BaseMujocoPyEnv))
+ assert isinstance(env, (MujocoEnv, BaseMujocoPyEnv))
assert env.model.nq == 15
assert env.model.nv == 14
assert env.model.nu == 8
@@ -521,7 +521,7 @@ def test_model_object_count(version: str):
assert env.model.ntendon == 0
env = gym.make(f"HalfCheetah-{version}").unwrapped
- assert isinstance(env, (BaseMujocoEnv, BaseMujocoPyEnv))
+ assert isinstance(env, (MujocoEnv, BaseMujocoPyEnv))
assert env.model.nq == 9
assert env.model.nv == 9
assert env.model.nu == 6
@@ -532,7 +532,7 @@ def test_model_object_count(version: str):
assert env.model.ntendon == 0
env = gym.make(f"Hopper-{version}").unwrapped
- assert isinstance(env, (BaseMujocoEnv, BaseMujocoPyEnv))
+ assert isinstance(env, (MujocoEnv, BaseMujocoPyEnv))
assert env.model.nq == 6
assert env.model.nv == 6
assert env.model.nu == 3
@@ -543,7 +543,7 @@ def test_model_object_count(version: str):
assert env.model.ntendon == 0
env = gym.make(f"Humanoid-{version}").unwrapped
- assert isinstance(env, (BaseMujocoEnv, BaseMujocoPyEnv))
+ assert isinstance(env, (MujocoEnv, BaseMujocoPyEnv))
assert env.model.nq == 24
assert env.model.nv == 23
assert env.model.nu == 17
@@ -554,7 +554,7 @@ def test_model_object_count(version: str):
assert env.model.ntendon == 2
env = gym.make(f"HumanoidStandup-{version}").unwrapped
- assert isinstance(env, (BaseMujocoEnv, BaseMujocoPyEnv))
+ assert isinstance(env, (MujocoEnv, BaseMujocoPyEnv))
assert env.model.nq == 24
assert env.model.nv == 23
assert env.model.nu == 17
@@ -565,7 +565,7 @@ def test_model_object_count(version: str):
assert env.model.ntendon == 2
env = gym.make(f"InvertedDoublePendulum-{version}").unwrapped
- assert isinstance(env, (BaseMujocoEnv, BaseMujocoPyEnv))
+ assert isinstance(env, (MujocoEnv, BaseMujocoPyEnv))
assert env.model.nq == 3
assert env.model.nv == 3
assert env.model.nu == 1
@@ -576,7 +576,7 @@ def test_model_object_count(version: str):
assert env.model.ntendon == 0
env = gym.make(f"InvertedPendulum-{version}").unwrapped
- assert isinstance(env, (BaseMujocoEnv, BaseMujocoPyEnv))
+ assert isinstance(env, (MujocoEnv, BaseMujocoPyEnv))
assert env.model.nq == 2
assert env.model.nv == 2
assert env.model.nu == 1
@@ -588,7 +588,7 @@ def test_model_object_count(version: str):
if not (version == "v4" and mujoco.__version__ >= "3.0.0"):
env = gym.make(f"Pusher-{version}").unwrapped
- assert isinstance(env, (BaseMujocoEnv, BaseMujocoPyEnv))
+ assert isinstance(env, (MujocoEnv, BaseMujocoPyEnv))
assert env.model.nq == 11
assert env.model.nv == 11
assert env.model.nu == 7
@@ -604,7 +604,7 @@ def test_model_object_count(version: str):
assert env.model.ntendon == 0
env = gym.make(f"Reacher-{version}").unwrapped
- assert isinstance(env, (BaseMujocoEnv, BaseMujocoPyEnv))
+ assert isinstance(env, (MujocoEnv, BaseMujocoPyEnv))
assert env.model.nq == 4
assert env.model.nv == 4
assert env.model.nu == 2
@@ -616,7 +616,7 @@ def test_model_object_count(version: str):
assert env.model.ntendon == 0
env = gym.make(f"Swimmer-{version}").unwrapped
- assert isinstance(env, (BaseMujocoEnv, BaseMujocoPyEnv))
+ assert isinstance(env, (MujocoEnv, BaseMujocoPyEnv))
assert env.model.nq == 5
assert env.model.nv == 5
assert env.model.nu == 2
@@ -628,7 +628,7 @@ def test_model_object_count(version: str):
assert env.model.ntendon == 0
env = gym.make(f"Walker2d-{version}").unwrapped
- assert isinstance(env, (BaseMujocoEnv, BaseMujocoPyEnv))
+ assert isinstance(env, (MujocoEnv, BaseMujocoPyEnv))
assert env.model.nq == 9
assert env.model.nv == 9
assert env.model.nu == 6
@@ -666,8 +666,8 @@ def test_dt():
env_b = gym.make(
"Ant-v5", include_cfrc_ext_in_observation=False, frame_skip=1
).unwrapped
- assert isinstance(env_a, BaseMujocoEnv)
- assert isinstance(env_b, BaseMujocoEnv)
+ assert isinstance(env_a, MujocoEnv)
+ assert isinstance(env_b, MujocoEnv)
env_b.model.opt.timestep = 0.05
assert env_a.dt == env_b.dt
@@ -702,7 +702,7 @@ def test_dt():
)
def test_reset_noise_scale(env_id):
"""Checks that when `reset_noise_scale=0` we have deterministic initialization."""
- env: BaseMujocoEnv = gym.make(env_id, reset_noise_scale=0).unwrapped
+ env = gym.make(env_id, reset_noise_scale=0).unwrapped
env.reset()
assert np.all(env.data.qpos == env.init_qpos)
From 52c04fb4aae4cb70ff034cccc1e88b73d03b9c04 Mon Sep 17 00:00:00 2001
From: Kallinteris Andreas
<30759571+Kallinteris-Andreas@users.noreply.github.com>
Date: Wed, 5 Jun 2024 08:10:16 +0000
Subject: [PATCH 07/26] Trigger Build
From 0df947382e613972cfdc59f1478a8995dd4f495b Mon Sep 17 00:00:00 2001
From: Kallinteris Andreas
<30759571+Kallinteris-Andreas@users.noreply.github.com>
Date: Wed, 5 Jun 2024 11:25:03 +0300
Subject: [PATCH 08/26] Update test_mujoco_v5.py
---
tests/envs/mujoco/test_mujoco_v5.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/tests/envs/mujoco/test_mujoco_v5.py b/tests/envs/mujoco/test_mujoco_v5.py
index bf9c639e4a..e3ce08b119 100644
--- a/tests/envs/mujoco/test_mujoco_v5.py
+++ b/tests/envs/mujoco/test_mujoco_v5.py
@@ -600,7 +600,10 @@ def test_model_object_count(version: str):
else:
assert env.model.nbvh == 18
assert env.model.njnt == 11
- assert env.model.ngeom == 21
+ if version == "v4":
+ assert env.model.ngeom == 21
+ else:
+ assert env.model.ngeom == 20
assert env.model.ntendon == 0
env = gym.make(f"Reacher-{version}").unwrapped
From e8943b65de0db2d877170a660c1bb595e00da5fe Mon Sep 17 00:00:00 2001
From: Kallinteris Andreas
<30759571+Kallinteris-Andreas@users.noreply.github.com>
Date: Wed, 5 Jun 2024 09:21:29 +0000
Subject: [PATCH 09/26] `pre-commit`
---
tests/envs/mujoco/test_mujoco_v5.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/envs/mujoco/test_mujoco_v5.py b/tests/envs/mujoco/test_mujoco_v5.py
index e3ce08b119..c7277d10b7 100644
--- a/tests/envs/mujoco/test_mujoco_v5.py
+++ b/tests/envs/mujoco/test_mujoco_v5.py
@@ -603,7 +603,7 @@ def test_model_object_count(version: str):
if version == "v4":
assert env.model.ngeom == 21
else:
- assert env.model.ngeom == 20
+ assert env.model.ngeom == 20
assert env.model.ntendon == 0
env = gym.make(f"Reacher-{version}").unwrapped
From 63177ceba425bbecce43b063784025fb72fd4ff3 Mon Sep 17 00:00:00 2001
From: Kallinteris Andreas
<30759571+Kallinteris-Andreas@users.noreply.github.com>
Date: Wed, 25 Sep 2024 16:15:52 +0300
Subject: [PATCH 10/26] Update run-pytest.yml
---
.github/workflows/run-pytest.yml | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/run-pytest.yml b/.github/workflows/run-pytest.yml
index 7ded820638..823726c7b2 100644
--- a/.github/workflows/run-pytest.yml
+++ b/.github/workflows/run-pytest.yml
@@ -10,10 +10,10 @@ jobs:
strategy:
fail-fast: true
matrix:
- python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
+ python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']
numpy-version: ['>=1.21,<2.0', '>=2.0']
exclude:
- - python-version: '3.8' # numpy>=2.0 requires Python>=3.9
+ - python-version: '3.9' # numpy>=2.0 requires Python>=3.9
numpy-version: '>=2.0'
steps:
- uses: actions/checkout@v4
@@ -35,7 +35,7 @@ jobs:
- uses: actions/checkout@v4
- run: |
docker build -f bin/necessary-py.Dockerfile \
- --build-arg PYTHON_VERSION='3.10' \
+ --build-arg PYTHON_VERSION='3.13' \
--tag gymnasium-necessary-docker .
- name: Run tests
run: |
From 6115ccc3a096c4799e6fa598578a3537e51291e4 Mon Sep 17 00:00:00 2001
From: Kallinteris Andreas
<30759571+Kallinteris-Andreas@users.noreply.github.com>
Date: Wed, 25 Sep 2024 16:17:13 +0300
Subject: [PATCH 11/26] Update pyproject.toml
---
pyproject.toml | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/pyproject.toml b/pyproject.toml
index 61d5221ec5..e83807c340 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -13,7 +13,7 @@ authors = [{ name = "Farama Foundation", email = "contact@farama.org" }]
license = { text = "MIT License" }
keywords = ["Reinforcement Learning", "game", "RL", "AI", "gymnasium"]
classifiers = [
- "Development Status :: 4 - Beta", # change to `5 - Production/Stable` when ready
+ "Development Status :: 5 - Production/Stable",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
@@ -21,6 +21,7 @@ classifiers = [
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
+ "Programming Language :: Python :: 3.15",
'Intended Audience :: Science/Research',
'Topic :: Scientific/Engineering :: Artificial Intelligence',
]
From 7fc3ffe7f484db5269e7f7586fee0288c5111d39 Mon Sep 17 00:00:00 2001
From: Kallinteris Andreas
<30759571+Kallinteris-Andreas@users.noreply.github.com>
Date: Wed, 25 Sep 2024 16:18:54 +0300
Subject: [PATCH 12/26] Update pyproject.toml
---
pyproject.toml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pyproject.toml b/pyproject.toml
index e83807c340..365c67a845 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -21,7 +21,7 @@ classifiers = [
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
- "Programming Language :: Python :: 3.15",
+ "Programming Language :: Python :: 3.13",
'Intended Audience :: Science/Research',
'Topic :: Scientific/Engineering :: Artificial Intelligence',
]
From aeb1aab1013404b54991c37f1dfc8a3007107f3e Mon Sep 17 00:00:00 2001
From: Kallinteris Andreas
<30759571+Kallinteris-Andreas@users.noreply.github.com>
Date: Wed, 25 Sep 2024 16:19:06 +0300
Subject: [PATCH 13/26] Update pyproject.toml
---
pyproject.toml | 1 -
1 file changed, 1 deletion(-)
diff --git a/pyproject.toml b/pyproject.toml
index 365c67a845..784f1bd216 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -16,7 +16,6 @@ classifiers = [
"Development Status :: 5 - Production/Stable",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
- "Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
From 5451d84cdcec4d9acdffb5df35376172d159f4c6 Mon Sep 17 00:00:00 2001
From: Kallinteris Andreas
<30759571+Kallinteris-Andreas@users.noreply.github.com>
Date: Wed, 25 Sep 2024 16:21:33 +0300
Subject: [PATCH 14/26] Update README.md
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index ff2d9bb9b3..6c6cc9be7d 100644
--- a/README.md
+++ b/README.md
@@ -28,7 +28,7 @@ To install the base Gymnasium library, use `pip install gymnasium`
This does not include dependencies for all families of environments (there's a massive number, and some can be problematic to install on certain systems). You can install these dependencies for one family like `pip install "gymnasium[atari]"` or use `pip install "gymnasium[all]"` to install all dependencies.
-We support and test for Python 3.8, 3.9, 3.10, 3.11 and 3.12 on Linux and macOS. We will accept PRs related to Windows, but do not officially support it.
+We support and test for Linux and macOS. We will accept PRs related to Windows, but do not officially support it.
## API
From ceb897a58bcd9aa8b034615120e9a5c54c913f77 Mon Sep 17 00:00:00 2001
From: Kallinteris Andreas
<30759571+Kallinteris-Andreas@users.noreply.github.com>
Date: Tue, 1 Oct 2024 15:38:59 +0300
Subject: [PATCH 15/26] Update run-pytest.yml
---
.github/workflows/run-pytest.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/run-pytest.yml b/.github/workflows/run-pytest.yml
index 823726c7b2..888eb1e7da 100644
--- a/.github/workflows/run-pytest.yml
+++ b/.github/workflows/run-pytest.yml
@@ -35,7 +35,7 @@ jobs:
- uses: actions/checkout@v4
- run: |
docker build -f bin/necessary-py.Dockerfile \
- --build-arg PYTHON_VERSION='3.13' \
+ --build-arg PYTHON_VERSION='3.12' \
--tag gymnasium-necessary-docker .
- name: Run tests
run: |
From be728b1108cc7767cb61842764e599af9a9d2a4b Mon Sep 17 00:00:00 2001
From: Kallinteris Andreas
<30759571+Kallinteris-Andreas@users.noreply.github.com>
Date: Wed, 2 Oct 2024 12:37:42 +0300
Subject: [PATCH 16/26] Update run-pytest.yml
---
.github/workflows/run-pytest.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/run-pytest.yml b/.github/workflows/run-pytest.yml
index 888eb1e7da..823726c7b2 100644
--- a/.github/workflows/run-pytest.yml
+++ b/.github/workflows/run-pytest.yml
@@ -35,7 +35,7 @@ jobs:
- uses: actions/checkout@v4
- run: |
docker build -f bin/necessary-py.Dockerfile \
- --build-arg PYTHON_VERSION='3.12' \
+ --build-arg PYTHON_VERSION='3.13' \
--tag gymnasium-necessary-docker .
- name: Run tests
run: |
From b3092cc44b4f3dba19d80646481c48bd140ada70 Mon Sep 17 00:00:00 2001
From: Kallinteris Andreas
<30759571+Kallinteris-Andreas@users.noreply.github.com>
Date: Wed, 2 Oct 2024 12:41:16 +0300
Subject: [PATCH 17/26] Update run-pytest.yml
---
.github/workflows/run-pytest.yml | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/run-pytest.yml b/.github/workflows/run-pytest.yml
index 823726c7b2..4304166b32 100644
--- a/.github/workflows/run-pytest.yml
+++ b/.github/workflows/run-pytest.yml
@@ -10,7 +10,7 @@ jobs:
strategy:
fail-fast: true
matrix:
- python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']
+ python-version: ['3.9', '3.10', '3.11', '3.12', '3.13-rc']
numpy-version: ['>=1.21,<2.0', '>=2.0']
exclude:
- python-version: '3.9' # numpy>=2.0 requires Python>=3.9
@@ -35,7 +35,7 @@ jobs:
- uses: actions/checkout@v4
- run: |
docker build -f bin/necessary-py.Dockerfile \
- --build-arg PYTHON_VERSION='3.13' \
+ --build-arg PYTHON_VERSION='3.12' \
--tag gymnasium-necessary-docker .
- name: Run tests
run: |
From 0be7f34c393284d00d5d11969289c474d99778f2 Mon Sep 17 00:00:00 2001
From: Kallinteris Andreas
<30759571+Kallinteris-Andreas@users.noreply.github.com>
Date: Tue, 8 Oct 2024 02:27:56 +0300
Subject: [PATCH 18/26] Update run-pytest.yml
---
.github/workflows/run-pytest.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/run-pytest.yml b/.github/workflows/run-pytest.yml
index 4304166b32..888eb1e7da 100644
--- a/.github/workflows/run-pytest.yml
+++ b/.github/workflows/run-pytest.yml
@@ -10,7 +10,7 @@ jobs:
strategy:
fail-fast: true
matrix:
- python-version: ['3.9', '3.10', '3.11', '3.12', '3.13-rc']
+ python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']
numpy-version: ['>=1.21,<2.0', '>=2.0']
exclude:
- python-version: '3.9' # numpy>=2.0 requires Python>=3.9
From e6f4109d10327335b94b2c497f6d3a40a7c30962 Mon Sep 17 00:00:00 2001
From: Kallinteris Andreas
<30759571+Kallinteris-Andreas@users.noreply.github.com>
Date: Wed, 23 Oct 2024 14:39:11 +0300
Subject: [PATCH 19/26] Update pyproject.toml
---
pyproject.toml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pyproject.toml b/pyproject.toml
index dd9fd7b146..d6ecb2e4ea 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -8,7 +8,7 @@ build-backend = "setuptools.build_meta"
name = "gymnasium"
description = "A standard API for reinforcement learning and a diverse set of reference environments (formerly Gym)."
readme = "README.md"
-requires-python = ">= 3.8"
+requires-python = ">= 3.9"
authors = [{ name = "Farama Foundation", email = "contact@farama.org" }]
license = { text = "MIT License" }
keywords = ["Reinforcement Learning", "game", "RL", "AI", "gymnasium"]
From 299055616423bf29620ef5d4bccc925336f14925 Mon Sep 17 00:00:00 2001
From: Kallinteris Andreas
<30759571+Kallinteris-Andreas@users.noreply.github.com>
Date: Wed, 23 Oct 2024 14:39:59 +0300
Subject: [PATCH 20/26] Update .pre-commit-config.yaml
---
.pre-commit-config.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 58954ef886..44fcf4bf94 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -38,7 +38,7 @@ repos:
rev: v3.17.0
hooks:
- id: pyupgrade
- args: ["--py38-plus"]
+ args: ["--py39-plus"]
- repo: https://github.com/PyCQA/isort
rev: 5.13.2
hooks:
From dfa349b5ad317a8e6b1bc773eca16bad7ed1318d Mon Sep 17 00:00:00 2001
From: Kallinteris Andreas
<30759571+Kallinteris-Andreas@users.noreply.github.com>
Date: Wed, 4 Dec 2024 00:02:41 +0200
Subject: [PATCH 21/26] Update README.md
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 56aabde589..92ad7e1fd2 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@