nvkartik commited on
Commit
e302003
·
1 Parent(s): d9c7360
Files changed (1) hide show
  1. env.py +25 -44
env.py CHANGED
@@ -24,10 +24,8 @@ import logging
24
  import os
25
  import sys
26
  from pathlib import Path
27
- from typing import Any
28
 
29
  import gymnasium as gym
30
- import yaml
31
 
32
  from lerobot.envs.configs import EnvConfig
33
 
@@ -39,39 +37,38 @@ DEFAULT_CONFIG_FILE = "configs/config.yaml"
39
  def _download_and_import(filename: str):
40
  """Download file from Hub and import as module."""
41
  from huggingface_hub import hf_hub_download
 
42
  local_path = hf_hub_download(repo_id=HUB_REPO_ID, filename=filename)
43
  module_dir = os.path.dirname(local_path)
44
-
45
  # Add directory to sys.path so modules can import each other
46
  if module_dir not in sys.path:
47
  sys.path.insert(0, module_dir)
48
-
49
  module_name = filename.replace(".py", "")
50
-
51
  # Read file content and replace relative imports with absolute imports
52
- with open(local_path, "r") as f:
53
  content = f.read()
54
-
55
  # Replace relative imports (e.g., "from .errors" -> "from errors")
56
  content = content.replace("from .errors import", "from errors import")
57
  content = content.replace("from .isaaclab_env_wrapper import", "from isaaclab_env_wrapper import")
58
-
59
  # Create module and execute modified content
60
- module = importlib.util.module_from_spec(
61
- importlib.util.spec_from_file_location(module_name, local_path)
62
- )
63
  sys.modules[module_name] = module
64
-
65
  # Compile and execute the modified code
66
  code = compile(content, local_path, "exec")
67
- exec(code, module.__dict__)
68
-
69
  return module
70
 
71
 
72
  try:
73
- from .isaaclab_env_wrapper import IsaacLabEnvWrapper, cleanup_isaaclab
74
  from .errors import IsaacLabArenaCameraKeyError, IsaacLabArenaStateKeyError
 
75
  except ImportError:
76
  _errors = _download_and_import("errors.py")
77
  _isaaclab_wrapper = _download_and_import("isaaclab_env_wrapper.py")
@@ -151,7 +148,7 @@ ENVIRONMENT_ALIASES: dict[str, str] = {
151
  "kitchen_pnp": (
152
  f"{ISAACLAB_ARENA_ENV_MODULE}.kitchen_pick_and_place_environment.KitchenPickAndPlaceEnvironment"
153
  ),
154
- "press_button": (f"{ISAACLAB_ARENA_ENV_MODULE}.press_button_environment.PressButtonEnvironment"),
155
  }
156
 
157
 
@@ -175,8 +172,6 @@ def _find_config_file(config_path: str | Path | None = None) -> Path | None:
175
  Returns:
176
  Path to config file, or None if not found (uses defaults).
177
  """
178
- module_dir = Path(__file__).parent
179
-
180
  search_paths = []
181
 
182
  # Explicit path from argument
@@ -204,6 +199,7 @@ def _find_config_file(config_path: str | Path | None = None) -> Path | None:
204
  # This is needed when env.py is loaded from HF cache (only env.py is downloaded)
205
  try:
206
  from huggingface_hub import hf_hub_download
 
207
  logging.info(f"Downloading config from Hub: {HUB_REPO_ID}/{DEFAULT_CONFIG_FILE}")
208
  hub_config_path = hf_hub_download(
209
  repo_id=HUB_REPO_ID,
@@ -215,6 +211,7 @@ def _find_config_file(config_path: str | Path | None = None) -> Path | None:
215
 
216
  raise FileNotFoundError("config.yaml not found and no configuration provided.")
217
 
 
218
  def _create_isaaclab_env(config: dict, n_envs: int) -> dict[str, dict[int, gym.vector.VectorEnv]]:
219
  """Create IsaacLab Arena environment from configuration.
220
 
@@ -270,9 +267,11 @@ def _create_isaaclab_env(config: dict, n_envs: int) -> dict[str, dict[int, gym.v
270
  camera_keys = tuple(k.strip() for k in (config.get("camera_keys") or "").split(",") if k.strip())
271
  try:
272
  validate_config(
273
- raw_env, state_keys, camera_keys,
 
 
274
  config.get("state_dim", 54),
275
- config.get("action_dim", 36)
276
  )
277
  except (IsaacLabArenaCameraKeyError, IsaacLabArenaStateKeyError, ValueError) as e:
278
  logging.error(f"Validation failed: {e}")
@@ -303,9 +302,8 @@ def _create_isaaclab_env(config: dict, n_envs: int) -> dict[str, dict[int, gym.v
303
 
304
  def make_env(
305
  n_envs: int = 1,
306
- use_async_envs: bool = False,
307
  cfg: EnvConfig | None = None,
308
- # **kwargs: Any,
309
  ) -> dict[str, dict[int, gym.vector.VectorEnv]]:
310
  """Create IsaacLab Arena environments (EnvHub-compatible API).
311
 
@@ -316,7 +314,7 @@ def make_env(
316
  Args:
317
  n_envs: Number of parallel environments (default: 1).
318
  use_async_envs: Ignored for IsaacLab (GPU-based batched execution).
319
- **kwargs: Configuration parameters passed directly. Required keys:
320
  - environment: Environment name or alias (e.g., "gr1_microwave")
321
  - headless: Whether to run headless (default: True)
322
  - enable_cameras: Enable camera rendering (default: False)
@@ -338,7 +336,7 @@ def make_env(
338
  if n_envs < 1:
339
  raise ValueError("`n_envs` must be at least 1")
340
 
341
- if not hasattr(cfg, 'environment') or cfg.environment is None:
342
  raise ValueError(
343
  "No 'environment' specified. Pass it via kwargs or create "
344
  "configs/config.yaml with environment settings."
@@ -370,25 +368,8 @@ def make_env(
370
  "camera_keys": cfg.camera_keys or "", # Pass empty string for no cameras
371
  "task": cfg.task,
372
  }
373
- # else:
374
- # # Fallback to YAML for local development
375
- # yaml_path = _find_config_file(kwargs.get("config_path"))
376
- # if yaml_path is not None:
377
- # logging.info(f"Loading config from: {yaml_path}")
378
- # with open(yaml_path) as f:
379
- # config = yaml.safe_load(f) or {}
380
- # else:
381
- # config = {}
382
-
383
- # Apply any runtime overrides (highest priority)
384
- # config.update(kwargs)
385
-
386
- logging.info(
387
- f"EnvHub make_env: environment={config.get('environment')}, n_envs={n_envs}"
388
- )
389
- logging.info(
390
- f"Config: headless={config.get('headless')}, "
391
- f"enable_cameras={config.get('enable_cameras')}"
392
- )
393
 
394
  return _create_isaaclab_env(config, n_envs)
 
24
  import os
25
  import sys
26
  from pathlib import Path
 
27
 
28
  import gymnasium as gym
 
29
 
30
  from lerobot.envs.configs import EnvConfig
31
 
 
37
  def _download_and_import(filename: str):
38
  """Download file from Hub and import as module."""
39
  from huggingface_hub import hf_hub_download
40
+
41
  local_path = hf_hub_download(repo_id=HUB_REPO_ID, filename=filename)
42
  module_dir = os.path.dirname(local_path)
43
+
44
  # Add directory to sys.path so modules can import each other
45
  if module_dir not in sys.path:
46
  sys.path.insert(0, module_dir)
47
+
48
  module_name = filename.replace(".py", "")
49
+
50
  # Read file content and replace relative imports with absolute imports
51
+ with open(local_path) as f:
52
  content = f.read()
53
+
54
  # Replace relative imports (e.g., "from .errors" -> "from errors")
55
  content = content.replace("from .errors import", "from errors import")
56
  content = content.replace("from .isaaclab_env_wrapper import", "from isaaclab_env_wrapper import")
57
+
58
  # Create module and execute modified content
59
+ module = importlib.util.module_from_spec(importlib.util.spec_from_file_location(module_name, local_path))
 
 
60
  sys.modules[module_name] = module
61
+
62
  # Compile and execute the modified code
63
  code = compile(content, local_path, "exec")
64
+ exec(code, module.__dict__) # noqa: S102
65
+
66
  return module
67
 
68
 
69
  try:
 
70
  from .errors import IsaacLabArenaCameraKeyError, IsaacLabArenaStateKeyError
71
+ from .isaaclab_env_wrapper import IsaacLabEnvWrapper, cleanup_isaaclab
72
  except ImportError:
73
  _errors = _download_and_import("errors.py")
74
  _isaaclab_wrapper = _download_and_import("isaaclab_env_wrapper.py")
 
148
  "kitchen_pnp": (
149
  f"{ISAACLAB_ARENA_ENV_MODULE}.kitchen_pick_and_place_environment.KitchenPickAndPlaceEnvironment"
150
  ),
151
+ "press_button": f"{ISAACLAB_ARENA_ENV_MODULE}.press_button_environment.PressButtonEnvironment",
152
  }
153
 
154
 
 
172
  Returns:
173
  Path to config file, or None if not found (uses defaults).
174
  """
 
 
175
  search_paths = []
176
 
177
  # Explicit path from argument
 
199
  # This is needed when env.py is loaded from HF cache (only env.py is downloaded)
200
  try:
201
  from huggingface_hub import hf_hub_download
202
+
203
  logging.info(f"Downloading config from Hub: {HUB_REPO_ID}/{DEFAULT_CONFIG_FILE}")
204
  hub_config_path = hf_hub_download(
205
  repo_id=HUB_REPO_ID,
 
211
 
212
  raise FileNotFoundError("config.yaml not found and no configuration provided.")
213
 
214
+
215
  def _create_isaaclab_env(config: dict, n_envs: int) -> dict[str, dict[int, gym.vector.VectorEnv]]:
216
  """Create IsaacLab Arena environment from configuration.
217
 
 
267
  camera_keys = tuple(k.strip() for k in (config.get("camera_keys") or "").split(",") if k.strip())
268
  try:
269
  validate_config(
270
+ raw_env,
271
+ state_keys,
272
+ camera_keys,
273
  config.get("state_dim", 54),
274
+ config.get("action_dim", 36),
275
  )
276
  except (IsaacLabArenaCameraKeyError, IsaacLabArenaStateKeyError, ValueError) as e:
277
  logging.error(f"Validation failed: {e}")
 
302
 
303
  def make_env(
304
  n_envs: int = 1,
305
+ use_async_envs: bool = False, # noqa: ARG001
306
  cfg: EnvConfig | None = None,
 
307
  ) -> dict[str, dict[int, gym.vector.VectorEnv]]:
308
  """Create IsaacLab Arena environments (EnvHub-compatible API).
309
 
 
314
  Args:
315
  n_envs: Number of parallel environments (default: 1).
316
  use_async_envs: Ignored for IsaacLab (GPU-based batched execution).
317
+ cfg: Configuration object with environment parameters. Required keys:
318
  - environment: Environment name or alias (e.g., "gr1_microwave")
319
  - headless: Whether to run headless (default: True)
320
  - enable_cameras: Enable camera rendering (default: False)
 
336
  if n_envs < 1:
337
  raise ValueError("`n_envs` must be at least 1")
338
 
339
+ if not hasattr(cfg, "environment") or cfg.environment is None:
340
  raise ValueError(
341
  "No 'environment' specified. Pass it via kwargs or create "
342
  "configs/config.yaml with environment settings."
 
368
  "camera_keys": cfg.camera_keys or "", # Pass empty string for no cameras
369
  "task": cfg.task,
370
  }
371
+
372
+ logging.info(f"EnvHub make_env: environment={config.get('environment')}, n_envs={n_envs}")
373
+ logging.info(f"Config: headless={config.get('headless')}, enable_cameras={config.get('enable_cameras')}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
374
 
375
  return _create_isaaclab_env(config, n_envs)