Skip to content

Replacing "global" with "local" coordinate system #833

@pseudo-rnd-thoughts

Description

@pseudo-rnd-thoughts

Hi,

I'm one of the developers on OpenAI Gym and Gymnasium (a fork of Gym).
In the recent Mujoco 2.3.4 release, the first point mentions the "global" setting being removed from the coordinate system.

Rerunning our CI with the latest MuJoCo version, we found that one of our models, Hopper, uses the global coordinate system. I have experimented with just changing this to "local" however, in testing, does not produce the same output, critical for backward compatibility.

I can't find the PR that introduced this change nor any documentation on how to update to this.
Could you recommend how we update our models such that the same global model is produced?

Here is a model which explains my question:

<mujoco model="hopper">
  <compiler angle="degree" coordinate="global" inertiafromgeom="true"/>
  <default>
    <joint armature="1" damping="1" limited="true"/>
    <geom conaffinity="1" condim="1" contype="1" margin="0.001" material="geom" rgba="0.8 0.6 .4 1" solimp=".8 .8 .01" solref=".02 1"/>
    <motor ctrllimited="true" ctrlrange="-.4 .4"/>
  </default>
  <option integrator="RK4" timestep="0.002"/>
  <visual>
    <map znear="0.02"/>
  </visual>
  <worldbody>
    <light cutoff="100" diffuse="1 1 1" dir="-0 0 -1.3" directional="true" exponent="1" pos="0 0 1.3" specular=".1 .1 .1"/>
    <geom conaffinity="1" condim="3" name="floor" pos="0 0 0" rgba="0.8 0.9 0.8 1" size="20 20 .125" type="plane" material="MatPlane"/>
    <body name="torso" pos="0 0 1.25">
      <camera name="track" mode="trackcom" pos="0 -3 1" xyaxes="1 0 0 0 0 1"/>
      <joint armature="0" axis="1 0 0" damping="0" limited="false" name="rootx" pos="0 0 0" stiffness="0" type="slide"/>
      <joint armature="0" axis="0 0 1" damping="0" limited="false" name="rootz" pos="0 0 0" ref="1.25" stiffness="0" type="slide"/>
      <joint armature="0" axis="0 1 0" damping="0" limited="false" name="rooty" pos="0 0 1.25" stiffness="0" type="hinge"/>
      <geom friction="0.9" fromto="0 0 1.45 0 0 1.05" name="torso_geom" size="0.05" type="capsule"/>
      <body name="thigh" pos="0 0 1.05">
        <joint axis="0 -1 0" name="thigh_joint" pos="0 0 1.05" range="-150 0" type="hinge"/>
        <geom friction="0.9" fromto="0 0 1.05 0 0 0.6" name="thigh_geom" size="0.05" type="capsule"/>
        <body name="leg" pos="0 0 0.35">
          <joint axis="0 -1 0" name="leg_joint" pos="0 0 0.6" range="-150 0" type="hinge"/>
          <geom friction="0.9" fromto="0 0 0.6 0 0 0.1" name="leg_geom" size="0.04" type="capsule"/>
          <body name="foot" pos="0.13 0 0">
            <joint axis="0 -1 0" name="foot_joint" pos="0 0 0.1" range="-45 45" type="hinge"/>
            <geom friction="2.0" fromto="-0.13 0 0.1 0.26 0 0.1" name="foot_geom" size="0.06" type="capsule"/>
          </body>
        </body>
      </body>
    </body>
  </worldbody>
  <actuator>
    <motor ctrllimited="true" ctrlrange="-1.0 1.0" gear="200.0" joint="thigh_joint"/>
    <motor ctrllimited="true" ctrlrange="-1.0 1.0" gear="200.0" joint="leg_joint"/>
    <motor ctrllimited="true" ctrlrange="-1.0 1.0" gear="200.0" joint="foot_joint"/>
  </actuator>
    <asset>
        <texture type="skybox" builtin="gradient" rgb1=".4 .5 .6" rgb2="0 0 0"
            width="100" height="100"/>
        <texture builtin="flat" height="1278" mark="cross" markrgb="1 1 1" name="texgeom" random="0.01" rgb1="0.8 0.6 0.4" rgb2="0.8 0.6 0.4" type="cube" width="127"/>
        <texture builtin="checker" height="100" name="texplane" rgb1="0 0 0" rgb2="0.8 0.8 0.8" type="2d" width="100"/>
        <material name="MatPlane" reflectance="0.5" shininess="1" specular="1" texrepeat="60 60" texture="texplane"/>
        <material name="geom" texture="texgeom" texuniform="true"/>
    </asset>
</mujoco>

This is the basic environment equivalences that I have done, I have copied the hopper.xml and replaced global with local on line 2 and copied the hopper_v4.py to hopper_local_v4 and changed the XML filename on line 208.

from numpy.testing import assert_array_equal

from gymnasium.envs.mujoco.hopper_v4 import HopperEnv as HopperGlobal
from gymnasium.envs.mujoco.hopper_local_v4 import HopperEnv as HopperLocal

global_env = HopperGlobal()
local_env = HopperLocal()

SEED = 123
NUM_STEPS = 1000


initial_obs_1, initial_info_1 = global_env.reset(seed=SEED)
initial_obs_2, initial_info_2 = local_env.reset(seed=SEED)
assert_array_equal(initial_obs_1, initial_obs_2)

global_env.action_space.seed(SEED)

for time_step in range(NUM_STEPS):
    # We don't evaluate the determinism of actions
    action = global_env.action_space.sample()

    obs_1, rew_1, terminated_1, truncated_1, info_1 = global_env.step(action)
    obs_2, rew_2, terminated_2, truncated_2, info_2 = local_env.step(action)

    assert_array_equal(obs_1, obs_2, f"[{time_step}] ")
    assert global_env.observation_space.contains(
        obs_1
    )  # obs_2 verified by previous assertion

    assert rew_1 == rew_2, f"[{time_step}] reward 1={rew_1}, reward 2={rew_2}"
    assert (
        terminated_1 == terminated_2
    ), f"[{time_step}] done 1={terminated_1}, done 2={terminated_2}"
    assert (
        truncated_1 == truncated_2
    ), f"[{time_step}] done 1={truncated_1}, done 2={truncated_2}"
    # assert_equals(info_1, info_2, f"[{time_step}] ")

    if (
        terminated_1 or truncated_1
    ):  # terminated_2, truncated_2 verified by previous assertion
        global_env.reset(seed=SEED)
        local_env.reset(seed=SEED)

global_env.close()
local_env.close()

Metadata

Metadata

Assignees

No one assigned

    Labels

    questionRequest for help or information

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions