Spaces:
Sleeping
Sleeping
Fix: fetch mujoco_menagerie for directly-built envs (snow gait crashed on a fresh container)
#13
by arminfg - opened
- app.py +5 -0
- g1_getup.py +1 -0
- render_worker.py +13 -1
- snow_gait.py +5 -0
app.py
CHANGED
|
@@ -170,8 +170,13 @@ def build_envs():
|
|
| 170 |
if ENVS:
|
| 171 |
return ENVS["env"], ENVS["eval_env"], ENVS["randomization_fn"]
|
| 172 |
from mujoco_playground import registry
|
|
|
|
| 173 |
|
| 174 |
STATE["status"] = "building env"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 175 |
if TASK == "getup":
|
| 176 |
import g1_getup
|
| 177 |
log("task: getup (fall recovery) -- flat ground, full-collision G1")
|
|
|
|
| 170 |
if ENVS:
|
| 171 |
return ENVS["env"], ENVS["eval_env"], ENVS["randomization_fn"]
|
| 172 |
from mujoco_playground import registry
|
| 173 |
+
from mujoco_playground._src import mjx_env
|
| 174 |
|
| 175 |
STATE["status"] = "building env"
|
| 176 |
+
# registry.load() clones mujoco_menagerie on demand; the snow-gait and get-up
|
| 177 |
+
# envs are constructed directly, which skips that, so a fresh container fails
|
| 178 |
+
# with "Error opening file ... left_hip_pitch_link.STL".
|
| 179 |
+
mjx_env.ensure_menagerie_exists()
|
| 180 |
if TASK == "getup":
|
| 181 |
import g1_getup
|
| 182 |
log("task: getup (fall recovery) -- flat ground, full-collision G1")
|
g1_getup.py
CHANGED
|
@@ -102,6 +102,7 @@ class G1Getup(g1_base.G1Env):
|
|
| 102 |
) -> None:
|
| 103 |
# G1Env.__init__ compiles from an XML path; this task needs the generated
|
| 104 |
# full-collision model instead, so set the model up here and skip it.
|
|
|
|
| 105 |
mjx_env.MjxEnv.__init__(self, config, config_overrides)
|
| 106 |
scene, assets = build_scene()
|
| 107 |
self._model_assets = assets
|
|
|
|
| 102 |
) -> None:
|
| 103 |
# G1Env.__init__ compiles from an XML path; this task needs the generated
|
| 104 |
# full-collision model instead, so set the model up here and skip it.
|
| 105 |
+
mjx_env.ensure_menagerie_exists() # registry.load() would do this for us
|
| 106 |
mjx_env.MjxEnv.__init__(self, config, config_overrides)
|
| 107 |
scene, assets = build_scene()
|
| 108 |
self._model_assets = assets
|
render_worker.py
CHANGED
|
@@ -15,13 +15,25 @@ def main(mjb, qpos_path, out, fps, width, height, camera):
|
|
| 15 |
model = mujoco.MjModel.from_binary_path(mjb)
|
| 16 |
data = mujoco.MjData(model)
|
| 17 |
qpos = np.load(qpos_path)
|
| 18 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
with mujoco.Renderer(model, height=int(height), width=int(width)) as r, \
|
| 20 |
imageio.get_writer(out, fps=float(fps), codec="libx264", quality=7,
|
| 21 |
macro_block_size=None) as w:
|
| 22 |
for q in qpos:
|
| 23 |
data.qpos[:] = q
|
| 24 |
mujoco.mj_forward(model, data)
|
|
|
|
|
|
|
| 25 |
r.update_scene(data, camera=cam)
|
| 26 |
w.append_data(r.render())
|
| 27 |
|
|
|
|
| 15 |
model = mujoco.MjModel.from_binary_path(mjb)
|
| 16 |
data = mujoco.MjData(model)
|
| 17 |
qpos = np.load(qpos_path)
|
| 18 |
+
|
| 19 |
+
# "follow" is a free camera kept above and behind the robot. The scene's own
|
| 20 |
+
# "track" camera sits 0.35 m above the centre of mass, which ends up inside
|
| 21 |
+
# the hillside on sloped terrain and renders the ground black.
|
| 22 |
+
follow = camera == "follow"
|
| 23 |
+
if follow:
|
| 24 |
+
cam = mujoco.MjvCamera()
|
| 25 |
+
cam.azimuth, cam.elevation, cam.distance = 140.0, -15.0, 6.0
|
| 26 |
+
else:
|
| 27 |
+
cam = camera if mujoco.mj_name2id(model, mujoco.mjtObj.mjOBJ_CAMERA, camera) >= 0 else -1
|
| 28 |
+
|
| 29 |
with mujoco.Renderer(model, height=int(height), width=int(width)) as r, \
|
| 30 |
imageio.get_writer(out, fps=float(fps), codec="libx264", quality=7,
|
| 31 |
macro_block_size=None) as w:
|
| 32 |
for q in qpos:
|
| 33 |
data.qpos[:] = q
|
| 34 |
mujoco.mj_forward(model, data)
|
| 35 |
+
if follow:
|
| 36 |
+
cam.lookat[:] = data.qpos[:3]
|
| 37 |
r.update_scene(data, camera=cam)
|
| 38 |
w.append_data(r.render())
|
| 39 |
|
snow_gait.py
CHANGED
|
@@ -34,6 +34,7 @@ import jax.numpy as jp
|
|
| 34 |
from ml_collections import config_dict
|
| 35 |
from mujoco import mjx
|
| 36 |
|
|
|
|
| 37 |
from mujoco_playground._src.locomotion.g1 import joystick as g1_joystick
|
| 38 |
|
| 39 |
# Defaults, all overridable from the Space (see app.py).
|
|
@@ -73,6 +74,10 @@ class G1SnowGait(g1_joystick.Joystick):
|
|
| 73 |
config: Optional[config_dict.ConfigDict] = None,
|
| 74 |
config_overrides: Optional[Dict[str, Union[str, int, list[Any]]]] = None,
|
| 75 |
) -> None:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
super().__init__(task=task, config=config or snow_gait_config(),
|
| 77 |
config_overrides=config_overrides)
|
| 78 |
self._pelvis_body_id = self._mj_model.body("pelvis").id
|
|
|
|
| 34 |
from ml_collections import config_dict
|
| 35 |
from mujoco import mjx
|
| 36 |
|
| 37 |
+
from mujoco_playground._src import mjx_env
|
| 38 |
from mujoco_playground._src.locomotion.g1 import joystick as g1_joystick
|
| 39 |
|
| 40 |
# Defaults, all overridable from the Space (see app.py).
|
|
|
|
| 74 |
config: Optional[config_dict.ConfigDict] = None,
|
| 75 |
config_overrides: Optional[Dict[str, Union[str, int, list[Any]]]] = None,
|
| 76 |
) -> None:
|
| 77 |
+
# Playground clones mujoco_menagerie inside registry.load(); this class is
|
| 78 |
+
# built directly, so fetch the meshes here or the model compiler fails on
|
| 79 |
+
# a machine that has not downloaded them yet.
|
| 80 |
+
mjx_env.ensure_menagerie_exists()
|
| 81 |
super().__init__(task=task, config=config or snow_gait_config(),
|
| 82 |
config_overrides=config_overrides)
|
| 83 |
self._pelvis_body_id = self._mj_model.body("pelvis").id
|