Repository: Farama-Foundation/Gymnasium
Pull request #1329: Fix MuJoCo add_markers for mujoco>=3.2
Author: login: amacati
Created: 2025-03-06T16:29:36Z | Merged: 2025-03-18T18:17:25Z

# Description

This PR fixes the `add_markers` function for mujoco's `BaseRender`. The API had a breaking change in between 3.1.x and 3.2. We now check the mujoco version on import and set a feature flag that switches between legacy behaviour and new (standard) behaviour.

Fixes #1326

## Type of change

Please delete options that are not relevant.

- [x] Bug fix (non-breaking change which fixes an issue)

## Dependencies
This fix adds `packaging` as dependency. This is required to compare against all possible versions that comply with [PEP 440](https://peps.python.org/pep-0440/).

>**Note:** It also bumps the required mujoco version to 2.3.6. Prior versions fail all unit tests because gymnasium uses type annotations that did not exist prior to 2.3.6.

>**WARNING:** The test suite still fails for `tests/envs/mujoco/test_mujoco_v5.py::test_model_object_count[v5]` with mujoco<3.1.4. To get all tests to pass, the mujoco version would have to be raised to at least 3.1.4. Since this restriction is more severe then the slight version bump to 2.3.6 and only concerns a single test case, it is omitted in this PR. **_These errors are unrelated to the current PR and exist in the current version._**

# Checklist:

- [x] I have run the [`pre-commit` checks](https://pre-commit.com/) with `pre-commit run --all-files` (see `CONTRIBUTING.md` instructions to set it up)
- [x] I have commented my code, particularly in hard-to-understand areas
- [x] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my feature works
- [x] New and existing unit tests pass locally with my changes


Linked issue #1326: [Bug Report] MuJoCo viewer add_marker is broken for mujoco>=3.0
### Describe the bug

MuJoCo offers the option to add markers to the simulation for visualization purposes. This functionality is exposed through `MujocoEnv.mujoco_renderer.viewer.add_marker` and is broken for MuJoCo >=3.0 due to an API change.

You can reproduce this with the latest Gymnasium versions and using a recent MuJoCo version. The problem can be fixed by adapting the function to the current API.

### Code example

```python
import gymnasium
import mujoco
import numpy as np


def patch_viewer():
    from gymnasium.envs.mujoco.mujoco_rendering import BaseRender

    def _add_marker_to_scene(self: BaseRender, marker: dict):
        if self.scn.ngeom >= self.scn.maxgeom:
            raise RuntimeError(f"Ran out of geoms. maxgeom: {self.scn.maxgeom}")
        geom_type = marker.get("type", mujoco.mjtGeom.mjGEOM_SPHERE)
        size = marker.get("size", np.array([0.01, 0.01, 0.01]))
        pos = marker.get("pos", np.array([0, 0, 0]))
        mat = marker.get("mat", np.eye(3).flatten())
        rgba = marker.get("rgba", np.array([1, 1, 1, 1]))
        mujoco.mjv_initGeom(
            self.scn.geoms[self.scn.ngeom], geom_type, size=size, pos=pos, mat=mat, rgba=rgba
        )
        self.scn.ngeom += 1

    BaseRender._add_marker_to_scene = _add_marker_to_scene


def main():
    env = gymnasium.make("Ant-v5", render_mode="human")
    obs, info = env.reset(seed=0)
    # patch_viewer()  # <-- Enabling this line will let the script run just fine

    while True:
        _, _, terminated, truncated, _ = env.step(np.zeros(env.action_space.shape))
        env.unwrapped.mujoco_renderer.viewer.add_marker(
            type=mujoco.mjtGeom.mjGEOM_BOX,
            size=np.ones(3) * 0.3,
            pos=np.zeros(3),
            mat=np.eye(3).flatten(),
            rgba=np.array([1, 0, 0, 1]),
        )
        env.render()  # AttributeError: 'mujoco._structs.MjvGeom' object has no attribute 'texid'
        if terminated or truncated:
            break
    env.close()


if __name__ == "__main__":
    main()
```

### System info

Gymnasium install from source
Version 1.0.0
MuJoCo 3.2.7
Ubuntu 20.04
Python 3.12

### Additional context

Replacing `_add_marker_to_scene` with the patched version from the example is trivial. However, this would break the `add_marker` function for older MuJoCo versions. If we want `gymnasium` to continue its support for MuJoCo < 3.0, we would need to introduce a version check and keep both functions.

Any thoughts @pseudo-rnd-thoughts ?

### Checklist

- [x] I have checked that there is no similar [issue](https://github.com/Farama-Foundation/Gymnasium/issues) in the repo

Linked issue comments: user: login: pseudo-rnd-thoughts
created_at: 2025-03-05T16:05:13Z
body: @Kallinteris-Andreas is our MuJoCo expert
author_association: MEMBER
user: login: Kallinteris-Andreas
created_at: 2025-03-05T16:13:44Z
body: We want to keep support for old versions of MuJoCo for reproducibility.
So having a version check in the function is probably the best solution
author_association: COLLABORATOR
user: login: amacati
created_at: 2025-03-05T17:02:20Z
body: Alright, should I open a PR then?
author_association: CONTRIBUTOR
user: login: Kallinteris-Andreas
created_at: 2025-03-05T17:22:31Z
body: Please do.
author_association: COLLABORATOR
user: login: amacati
created_at: 2025-03-10T09:49:08Z
body: @pseudo-rnd-thoughts @Kallinteris-Andreas I have added the PR. There are some other, unrelated version issues with MuJoCo that I uncovered during testing, which may be interesting for the team. Would be cool if you could have a look.
author_association: CONTRIBUTOR
user: login: pseudo-rnd-thoughts
created_at: 2025-03-11T13:21:22Z
body: @amacati thanks I'll have a look at the PR.
You mentioned that you found other interesting things, could you list them out to give us an idea of what to look at
author_association: MEMBER
user: login: amacati
created_at: 2025-03-11T13:25:00Z
body: It's in the PR. In short, the minimum required mujoco version is higher than advertised due to import failures for typing. And even though the test suite passes most tests with older mujoco versions, one environment test fails on all mujoco versions before 3.1.4
author_association: CONTRIBUTOR

Diff:
diff --git a/gymnasium/envs/mujoco/mujoco_rendering.py b/gymnasium/envs/mujoco/mujoco_rendering.py
index 7427a1499e..82fdc6bee1 100644
--- a/gymnasium/envs/mujoco/mujoco_rendering.py
+++ b/gymnasium/envs/mujoco/mujoco_rendering.py
@@ -6,10 +6,16 @@
 import imageio
 import mujoco
 import numpy as np
+from packaging.version import Version
 
 from gymnasium.logger import warn
 
 
+# The marker API changed in MuJoCo 3.2.0, so we check the mujoco version and set a flag that
+# determines which function we use when adding markers to the scene.
+_MUJOCO_MARKER_LEGACY_MODE = Version(mujoco.__version__) < Version("3.2.0")
+
+
 def _import_egl(width, height):
     from mujoco.egl import GLContext
 
@@ -88,8 +94,37 @@ def add_marker(self, **marker_params):
 
     def _add_marker_to_scene(self, marker: dict):
         if self.scn.ngeom >= self.scn.maxgeom:
-            raise RuntimeError("Ran out of geoms. maxgeom: %d" % self.scn.maxgeom)
+            raise RuntimeError(f"Ran out of geoms. maxgeom: {self.scn.maxgeom}")
+
+        if _MUJOCO_MARKER_LEGACY_MODE:  # Old API for markers requires special handling
+            self._legacy_add_marker_to_scene(marker)
+        else:
+            geom_type = marker.get("type", mujoco.mjtGeom.mjGEOM_SPHERE)
+            size = marker.get("size", np.array([0.01, 0.01, 0.01]))
+            pos = marker.get("pos", np.array([0.0, 0.0, 0.0]))
+            mat = marker.get("mat", np.eye(3).flatten())
+            rgba = marker.get("rgba", np.array([1.0, 1.0, 1.0, 1.0]))
+            mujoco.mjv_initGeom(
+                self.scn.geoms[self.scn.ngeom],
+                geom_type,
+                size=size,
+                pos=pos,
+                mat=mat,
+                rgba=rgba,
+            )
+
+        self.scn.ngeom += 1
 
+    def _legacy_add_marker_to_scene(self, marker: dict):
+        """Add a marker to the scene compatible with older versions of MuJoCo.
+
+        MuJoCo 3.2 introduced breaking changes to the visual geometries API. To maintain
+        compatibility with older versions, we use the legacy API when an older version of MuJoCo is
+        detected.
+
+        Args:
+            marker: A dictionary containing the marker parameters.
+        """
         g = self.scn.geoms[self.scn.ngeom]
         # default values.
         g.dataid = -1
@@ -130,8 +165,6 @@ def _add_marker_to_scene(self, marker: dict):
             else:
                 raise ValueError("mjtGeom doesn't have field %s" % key)
 
-        self.scn.ngeom += 1
-
     def close(self):
         """Override close in your rendering subclass to perform any necessary cleanup
         after env.close() is called.
diff --git a/pyproject.toml b/pyproject.toml
index f7af86ade9..6fa14fef72 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -41,7 +41,7 @@ classic-control = ["pygame >=2.1.3"]
 classic_control = ["pygame >=2.1.3"]  # kept for backward compatibility
 mujoco-py = ["mujoco-py >=2.1,<2.2", "cython<3"]
 mujoco_py = ["mujoco-py >=2.1,<2.2", "cython<3"]  # kept for backward compatibility
-mujoco = ["mujoco >=2.1.5", "imageio >=2.14.1"]
+mujoco = ["mujoco >=2.1.5", "imageio >=2.14.1", "packaging >=23.0"]
 toy-text = ["pygame >=2.1.3"]
 toy_text = ["pygame >=2.1.3"]  # kept for backward compatibility
 jax = ["jax >=0.4.16", "jaxlib >=0.4.16", "flax >=0.5.0"]
@@ -64,6 +64,7 @@ all = [
     # mujoco
     "mujoco >=2.1.5",
     "imageio >=2.14.1",
+    "packaging >=23.0",
     # toy-text
     "pygame >=2.1.3",
     # jax
diff --git a/tests/envs/mujoco/test_mujoco_rendering.py b/tests/envs/mujoco/test_mujoco_rendering.py
index bf32a64c6f..70185c72d7 100644
--- a/tests/envs/mujoco/test_mujoco_rendering.py
+++ b/tests/envs/mujoco/test_mujoco_rendering.py
@@ -117,6 +117,28 @@ def test_max_geom_attribute(
     viewer.close()
 
 
+@pytest.mark.parametrize(
+    "render_mode", ["human", "rgb_array", "depth_array", "rgbd_tuple"]
+)
+def test_add_markers(model: mujoco.MjModel, data: mujoco.MjData, render_mode: str):
+    """Test that the add_markers function works correctly."""
+    # initialize renderer
+    renderer = ExposedViewerRenderer(
+        model, data, width=DEFAULT_SIZE, height=DEFAULT_SIZE, max_geom=10
+    )
+    # initialize viewer via render
+    viewer = renderer.get_viewer(render_mode)
+    viewer.add_marker(
+        pos=np.array([0, 0, 0]),
+        size=np.array([1, 1, 1]),
+        rgba=np.array([1, 0, 0, 1]),
+    )
+    args = tuple() if render_mode == "human" else (render_mode,)
+    viewer.render(*args)  # We need to render to trigger the marker addition in MuJoCo
+    # close viewer after usage
+    viewer.close()
+
+
 @pytest.mark.parametrize(
     "render_mode", ["human", "rgb_array", "depth_array", "rgbd_tuple"]
 )


Reviews:
user: login: pseudo-rnd-thoughts
body: Implementation looks good, thanks for the PR @amacati 
@Kallinteris-Andreas could you have a look before it's merged?
state: APPROVED
author_association: MEMBER
submitted_at: 2025-03-11T13:24:09Z
user: login: Kallinteris-Andreas
state: CHANGES_REQUESTED
author_association: COLLABORATOR
submitted_at: 2025-03-12T09:41:17Z
user: login: amacati
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T12:08:18Z
user: login: amacati
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T12:10:47Z
user: login: amacati
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T12:52:47Z
user: login: Kallinteris-Andreas
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-16T11:16:32Z
user: login: pseudo-rnd-thoughts
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-17T12:10:18Z
user: login: amacati
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-17T15:22:48Z
user: login: Kallinteris-Andreas
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-17T18:36:42Z
user: login: amacati
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-17T22:12:35Z
user: login: Kallinteris-Andreas
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-18T11:31:44Z
user: login: amacati
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-18T13:54:14Z
user: login: Kallinteris-Andreas
body: Sorry for the slow respones (and some not properly researched ones), i do not currently have access to a proper development environment

The PR looks good
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-03-18T18:14:28Z

Review comments:
diff_hunk: @@ -41,7 +41,7 @@ classic-control = ["pygame >=2.1.3"]
 classic_control = ["pygame >=2.1.3"]  # kept for backward compatibility
 mujoco-py = ["mujoco-py >=2.1,<2.2", "cython<3"]
 mujoco_py = ["mujoco-py >=2.1,<2.2", "cython<3"]  # kept for backward compatibility
-mujoco = ["mujoco >=2.1.5", "imageio >=2.14.1"]
+mujoco = ["mujoco >=2.3.6", "imageio >=2.14.1", "packaging >=23.0"]
path: pyproject.toml
user: login: Kallinteris-Andreas
body: Why change mujoco minimum, also we do not need to use `packaging` instead `mujoco__version__()`, 
created_at: 2025-03-12T07:43:59Z
author_association: COLLABORATOR
diff_hunk: @@ -130,8 +156,6 @@ def _add_marker_to_scene(self, marker: dict):
             else:
                 raise ValueError("mjtGeom doesn't have field %s" % key)
 
-        self.scn.ngeom += 1
path: gymnasium/envs/mujoco/mujoco_rendering.py
user: login: Kallinteris-Andreas
body: Why.was this here (if you can tell)
created_at: 2025-03-12T07:46:54Z
author_association: COLLABORATOR
diff_hunk: @@ -88,8 +94,28 @@ def add_marker(self, **marker_params):
 
     def _add_marker_to_scene(self, marker: dict):
         if self.scn.ngeom >= self.scn.maxgeom:
-            raise RuntimeError("Ran out of geoms. maxgeom: %d" % self.scn.maxgeom)
+            raise RuntimeError(f"Ran out of geoms. maxgeom: {self.scn.maxgeom}")
+
+        if _MUJOCO_MARKER_LEGACY_MODE:
+            self._legacy_add_marker_to_scene(marker)
+        else:
+            geom_type = marker.get("type", mujoco.mjtGeom.mjGEOM_SPHERE)
+            size = marker.get("size", np.array([0.01, 0.01, 0.01]))
+            pos = marker.get("pos", np.array([0.0, 0.0, 0.0]))
+            mat = marker.get("mat", np.eye(3).flatten())
+            rgba = marker.get("rgba", np.array([1.0, 1.0, 1.0, 1.0]))
+            mujoco.mjv_initGeom(
+                self.scn.geoms[self.scn.ngeom],
+                geom_type,
+                size=size,
+                pos=pos,
+                mat=mat,
+                rgba=rgba,
+            )
 
+        self.scn.ngeom += 1
+
+    def _legacy_add_marker_to_scene(self, marker: dict):
path: gymnasium/envs/mujoco/mujoco_rendering.py
user: login: Kallinteris-Andreas
body: This needs a doc string at the very least
created_at: 2025-03-12T07:51:07Z
author_association: COLLABORATOR
diff_hunk: @@ -41,7 +41,7 @@ classic-control = ["pygame >=2.1.3"]
 classic_control = ["pygame >=2.1.3"]  # kept for backward compatibility
 mujoco-py = ["mujoco-py >=2.1,<2.2", "cython<3"]
 mujoco_py = ["mujoco-py >=2.1,<2.2", "cython<3"]  # kept for backward compatibility
-mujoco = ["mujoco >=2.1.5", "imageio >=2.14.1"]
+mujoco = ["mujoco >=2.3.6", "imageio >=2.14.1", "packaging >=23.0"]
path: pyproject.toml
user: login: amacati
body: As explained in the PR:

Note: It also bumps the required mujoco version to 2.3.6. Prior versions fail all unit tests because gymnasium uses type annotations that did not exist prior to 2.3.6.

I guess nobody ever tested for mujoco versions below that.

Packaging is required to have meaningful version comparisons that work for all version numbers covered by [PEP 440](https://peps.python.org/pep-0440/). If mujoco adds additional identifiers (and I'm not sure they guarantee they don't for local build versions or something like that), then the string comparison could fail.
created_at: 2025-03-12T12:08:18Z
author_association: CONTRIBUTOR
diff_hunk: @@ -130,8 +156,6 @@ def _add_marker_to_scene(self, marker: dict):
             else:
                 raise ValueError("mjtGeom doesn't have field %s" % key)
 
-        self.scn.ngeom += 1
path: gymnasium/envs/mujoco/mujoco_rendering.py
user: login: amacati
body: This is required to keep track of the growing number of `ngeoms`. We still do that, just in the `_add_marker_to_scene` function (see line 116). Regardless of legacy or standard mode, this counter still gets bumped. Git just did not realize line 116 and 133 remained the same
created_at: 2025-03-12T12:10:47Z
author_association: CONTRIBUTOR
diff_hunk: @@ -88,8 +94,28 @@ def add_marker(self, **marker_params):
 
     def _add_marker_to_scene(self, marker: dict):
         if self.scn.ngeom >= self.scn.maxgeom:
-            raise RuntimeError("Ran out of geoms. maxgeom: %d" % self.scn.maxgeom)
+            raise RuntimeError(f"Ran out of geoms. maxgeom: {self.scn.maxgeom}")
+
+        if _MUJOCO_MARKER_LEGACY_MODE:
+            self._legacy_add_marker_to_scene(marker)
+        else:
+            geom_type = marker.get("type", mujoco.mjtGeom.mjGEOM_SPHERE)
+            size = marker.get("size", np.array([0.01, 0.01, 0.01]))
+            pos = marker.get("pos", np.array([0.0, 0.0, 0.0]))
+            mat = marker.get("mat", np.eye(3).flatten())
+            rgba = marker.get("rgba", np.array([1.0, 1.0, 1.0, 1.0]))
+            mujoco.mjv_initGeom(
+                self.scn.geoms[self.scn.ngeom],
+                geom_type,
+                size=size,
+                pos=pos,
+                mat=mat,
+                rgba=rgba,
+            )
 
+        self.scn.ngeom += 1
+
+    def _legacy_add_marker_to_scene(self, marker: dict):
path: gymnasium/envs/mujoco/mujoco_rendering.py
user: login: amacati
body: Yes, I think that would make sense. I was assuming we don't need one since the original function also had no docstrings, but given the new complexity it would definitely be useful.
created_at: 2025-03-12T12:52:47Z
author_association: CONTRIBUTOR
diff_hunk: @@ -41,7 +41,7 @@ classic-control = ["pygame >=2.1.3"]
 classic_control = ["pygame >=2.1.3"]  # kept for backward compatibility
 mujoco-py = ["mujoco-py >=2.1,<2.2", "cython<3"]
 mujoco_py = ["mujoco-py >=2.1,<2.2", "cython<3"]  # kept for backward compatibility
-mujoco = ["mujoco >=2.1.5", "imageio >=2.14.1"]
+mujoco = ["mujoco >=2.3.6", "imageio >=2.14.1", "packaging >=23.0"]
path: pyproject.toml
user: login: Kallinteris-Andreas
body: It is fine for type annotations to fail, older library versions

@pseudo-rnd-thoughts do you have any objections to adding the `package` dependecy
created_at: 2025-03-16T11:16:32Z
author_association: COLLABORATOR
diff_hunk: @@ -41,7 +41,7 @@ classic-control = ["pygame >=2.1.3"]
 classic_control = ["pygame >=2.1.3"]  # kept for backward compatibility
 mujoco-py = ["mujoco-py >=2.1,<2.2", "cython<3"]
 mujoco_py = ["mujoco-py >=2.1,<2.2", "cython<3"]  # kept for backward compatibility
-mujoco = ["mujoco >=2.1.5", "imageio >=2.14.1"]
+mujoco = ["mujoco >=2.3.6", "imageio >=2.14.1", "packaging >=23.0"]
path: pyproject.toml
user: login: pseudo-rnd-thoughts
body: Thanks for asking, yeah that is good with me. Looking at the repo (https://pypi.org/project/packaging/), I think it is a fairly common package that is well-maintained
created_at: 2025-03-17T12:10:18Z
author_association: MEMBER
diff_hunk: @@ -41,7 +41,7 @@ classic-control = ["pygame >=2.1.3"]
 classic_control = ["pygame >=2.1.3"]  # kept for backward compatibility
 mujoco-py = ["mujoco-py >=2.1,<2.2", "cython<3"]
 mujoco_py = ["mujoco-py >=2.1,<2.2", "cython<3"]  # kept for backward compatibility
-mujoco = ["mujoco >=2.1.5", "imageio >=2.14.1"]
+mujoco = ["mujoco >=2.3.6", "imageio >=2.14.1", "packaging >=23.0"]
path: pyproject.toml
user: login: amacati
body: @Kallinteris-Andreas Do you want me to revert the `mujoco` version change? I'm not sure why it would be fine to fail due to type annotations, but I don't think it has a huge impact either way since `mujoco<3` is hopefully barely being used anymore.
created_at: 2025-03-17T15:22:47Z
author_association: CONTRIBUTOR
diff_hunk: @@ -41,7 +41,7 @@ classic-control = ["pygame >=2.1.3"]
 classic_control = ["pygame >=2.1.3"]  # kept for backward compatibility
 mujoco-py = ["mujoco-py >=2.1,<2.2", "cython<3"]
 mujoco_py = ["mujoco-py >=2.1,<2.2", "cython<3"]  # kept for backward compatibility
-mujoco = ["mujoco >=2.1.5", "imageio >=2.14.1"]
+mujoco = ["mujoco >=2.3.6", "imageio >=2.14.1", "packaging >=23.0"]
path: pyproject.toml
user: login: Kallinteris-Andreas
body: It is still being used for reproducabiliy
created_at: 2025-03-17T18:36:42Z
author_association: COLLABORATOR
diff_hunk: @@ -41,7 +41,7 @@ classic-control = ["pygame >=2.1.3"]
 classic_control = ["pygame >=2.1.3"]  # kept for backward compatibility
 mujoco-py = ["mujoco-py >=2.1,<2.2", "cython<3"]
 mujoco_py = ["mujoco-py >=2.1,<2.2", "cython<3"]  # kept for backward compatibility
-mujoco = ["mujoco >=2.1.5", "imageio >=2.14.1"]
+mujoco = ["mujoco >=2.3.6", "imageio >=2.14.1", "packaging >=23.0"]
path: pyproject.toml
user: login: amacati
body: I have reverted the version bump 👍 
created_at: 2025-03-17T22:12:35Z
author_association: CONTRIBUTOR
diff_hunk: @@ -117,6 +117,28 @@ def test_max_geom_attribute(
     viewer.close()
 
 
+@pytest.mark.parametrize(
+    "render_mode", ["human", "rgb_array", "depth_array", "rgbd_tuple"]
+)
+def test_add_markers(model: mujoco.MjModel, data: mujoco.MjData, render_mode: str):
path: tests/envs/mujoco/test_mujoco_rendering.py
user: login: Kallinteris-Andreas
body: I could be wrong here but from my understanding this will not run since `render_mode`is being parameterized but `data` and  `model` do have valued
created_at: 2025-03-18T11:31:44Z
author_association: COLLABORATOR
diff_hunk: @@ -117,6 +117,28 @@ def test_max_geom_attribute(
     viewer.close()
 
 
+@pytest.mark.parametrize(
+    "render_mode", ["human", "rgb_array", "depth_array", "rgbd_tuple"]
+)
+def test_add_markers(model: mujoco.MjModel, data: mujoco.MjData, render_mode: str):
path: tests/envs/mujoco/test_mujoco_rendering.py
user: login: amacati
body: The file has module-scoped fixtures at the top that are used for all tests. That's where model and data come from, see https://github.com/Farama-Foundation/Gymnasium/blob/a0086c6cdf6822e615d293677597a12c562bcbeb/tests/envs/mujoco/test_mujoco_rendering.py#L25-L37

I followed the pattern of the existing tests for the new one, so I assumed using these module fixtures would be fine. It's impossible for the tests to fail silently, pytest will complain if it cannot find fixtures for function arguments.
created_at: 2025-03-18T13:54:13Z
author_association: CONTRIBUTOR

PR comments:
user: login: amacati
created_at: 2025-03-06T16:52:57Z
body: @Kallinteris-Andreas Here's the PR we talked about yesterday. There are a few general issues unrelated to this PR around version numbers that I found during testing with various mujoco versions. The current changes are as small as possible while fixing most of it. If you want the whole test suite to pass with the minimal mujoco version, you'd have to fix `test_model_object_count` in a separate PR though.
author_association: CONTRIBUTOR
user: login: amacati
created_at: 2025-03-17T22:13:53Z
body: I have reverted the version bump of mujoco as discussed with @Kallinteris-Andreas . Does this now look good to you?
author_association: CONTRIBUTOR
user: login: amacati
created_at: 2025-03-18T21:48:33Z
body: No worries. Thanks for reviewing!
author_association: CONTRIBUTOR