From 52e47775c784ce4acb36b6310a850d443c50a15a Mon Sep 17 00:00:00 2001 From: Gonglitian Date: Sat, 8 Nov 2025 17:10:59 -0800 Subject: [PATCH 1/4] fix: fix(robomimic): unify config loading logic and add JSON support to avoid FileNotFoundError in training --- scripts/imitation_learning/robomimic/train.py | 23 +++++++++++-------- .../isaaclab_tasks/utils/parse_cfg.py | 13 ++++++++--- src/nvidia-curobo | 1 + 3 files changed, 24 insertions(+), 13 deletions(-) create mode 160000 src/nvidia-curobo diff --git a/scripts/imitation_learning/robomimic/train.py b/scripts/imitation_learning/robomimic/train.py index 718a18bcbca..eaf7ca2c15b 100644 --- a/scripts/imitation_learning/robomimic/train.py +++ b/scripts/imitation_learning/robomimic/train.py @@ -86,6 +86,7 @@ import isaaclab_tasks # noqa: F401 import isaaclab_tasks.manager_based.locomanipulation.pick_place # noqa: F401 import isaaclab_tasks.manager_based.manipulation.pick_place # noqa: F401 +from isaaclab_tasks.utils.parse_cfg import load_cfg_from_registry def normalize_hdf5_actions(config: Config, log_dir: str) -> str: @@ -361,17 +362,19 @@ def main(args: argparse.Namespace): print(f"Loading configuration for task: {task_name}") print(gym.envs.registry.keys()) print(" ") - cfg_entry_point_file = gym.spec(task_name).kwargs.pop(cfg_entry_point_key) - # check if entry point exists - if cfg_entry_point_file is None: - raise ValueError( - f"Could not find configuration for the environment: '{task_name}'." - f" Please check that the gym registry has the entry point: '{cfg_entry_point_key}'." + + # use the unified configuration loading utility (supports YAML, JSON, and Python classes) + ext_cfg = load_cfg_from_registry(task_name, cfg_entry_point_key) + + # ensure the configuration is a dictionary (robomimic expects JSON/YAML dict format) + if not isinstance(ext_cfg, dict): + raise TypeError( + f"Expected robomimic configuration to be a dictionary, but got {type(ext_cfg)}." + " Please ensure the configuration file is in JSON or YAML format." ) - - with open(cfg_entry_point_file) as f: - ext_cfg = json.load(f) - config = config_factory(ext_cfg["algo_name"]) + + # create robomimic config from the loaded dictionary + config = config_factory(ext_cfg["algo_name"]) # update config with external json - this will throw errors if # the external config has keys not present in the base algo config with config.values_unlocked(): diff --git a/source/isaaclab_tasks/isaaclab_tasks/utils/parse_cfg.py b/source/isaaclab_tasks/isaaclab_tasks/utils/parse_cfg.py index b4f788a9bcb..5d5e34c91f2 100644 --- a/source/isaaclab_tasks/isaaclab_tasks/utils/parse_cfg.py +++ b/source/isaaclab_tasks/isaaclab_tasks/utils/parse_cfg.py @@ -80,20 +80,27 @@ def load_cfg_from_registry(task_name: str, entry_point_key: str) -> dict | objec f"{msg if agents else ''}" ) # parse the default config file - if isinstance(cfg_entry_point, str) and cfg_entry_point.endswith(".yaml"): + if isinstance(cfg_entry_point, str) and (cfg_entry_point.endswith(".yaml") or cfg_entry_point.endswith(".json")): if os.path.exists(cfg_entry_point): # absolute path for the config file config_file = cfg_entry_point else: # resolve path to the module location mod_name, file_name = cfg_entry_point.split(":") - mod_path = os.path.dirname(importlib.import_module(mod_name).__file__) + mod = importlib.import_module(mod_name) + if mod.__file__ is None: + raise ValueError(f"Could not determine file path for module: {mod_name}") + mod_path = os.path.dirname(mod.__file__) # obtain the configuration file path config_file = os.path.join(mod_path, file_name) # load the configuration print(f"[INFO]: Parsing configuration from: {config_file}") with open(config_file, encoding="utf-8") as f: - cfg = yaml.full_load(f) + if cfg_entry_point.endswith(".yaml"): + cfg = yaml.full_load(f) + else: # .json + import json + cfg = json.load(f) else: if callable(cfg_entry_point): # resolve path to the module location diff --git a/src/nvidia-curobo b/src/nvidia-curobo new file mode 160000 index 00000000000..ebb71702f3f --- /dev/null +++ b/src/nvidia-curobo @@ -0,0 +1 @@ +Subproject commit ebb71702f3f70e767f40fd8e050674af0288abe8 From d8a396e7c9b7e08d8f219e812bc110441f68f647 Mon Sep 17 00:00:00 2001 From: Gonglitian Date: Sat, 8 Nov 2025 17:36:26 -0800 Subject: [PATCH 2/4] formatted using pre-commit hooks --- scripts/imitation_learning/robomimic/train.py | 6 +++--- source/isaaclab_tasks/isaaclab_tasks/utils/parse_cfg.py | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/scripts/imitation_learning/robomimic/train.py b/scripts/imitation_learning/robomimic/train.py index eaf7ca2c15b..23852625c3e 100644 --- a/scripts/imitation_learning/robomimic/train.py +++ b/scripts/imitation_learning/robomimic/train.py @@ -362,17 +362,17 @@ def main(args: argparse.Namespace): print(f"Loading configuration for task: {task_name}") print(gym.envs.registry.keys()) print(" ") - + # use the unified configuration loading utility (supports YAML, JSON, and Python classes) ext_cfg = load_cfg_from_registry(task_name, cfg_entry_point_key) - + # ensure the configuration is a dictionary (robomimic expects JSON/YAML dict format) if not isinstance(ext_cfg, dict): raise TypeError( f"Expected robomimic configuration to be a dictionary, but got {type(ext_cfg)}." " Please ensure the configuration file is in JSON or YAML format." ) - + # create robomimic config from the loaded dictionary config = config_factory(ext_cfg["algo_name"]) # update config with external json - this will throw errors if diff --git a/source/isaaclab_tasks/isaaclab_tasks/utils/parse_cfg.py b/source/isaaclab_tasks/isaaclab_tasks/utils/parse_cfg.py index 5d5e34c91f2..374ae6b2228 100644 --- a/source/isaaclab_tasks/isaaclab_tasks/utils/parse_cfg.py +++ b/source/isaaclab_tasks/isaaclab_tasks/utils/parse_cfg.py @@ -100,6 +100,7 @@ def load_cfg_from_registry(task_name: str, entry_point_key: str) -> dict | objec cfg = yaml.full_load(f) else: # .json import json + cfg = json.load(f) else: if callable(cfg_entry_point): From 169c688db5d0aa5596180b7491174e13f5e47577 Mon Sep 17 00:00:00 2001 From: Gonglitian Date: Sat, 8 Nov 2025 17:43:39 -0800 Subject: [PATCH 3/4] add name to CONTRIBUTORS.md --- CONTRIBUTORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 8491f2647a4..5d99c35f5f0 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -89,6 +89,7 @@ Guidelines for modifications: * Kourosh Darvish * Kousheek Chakraborty * Lionel Gulich +* Litian Gong * Lotus Li * Louis Le Lay * Lorenz Wellhausen From 551d4e43070f5200baad404ace5485780b8df7b7 Mon Sep 17 00:00:00 2001 From: Gonglitian Date: Sat, 8 Nov 2025 18:13:27 -0800 Subject: [PATCH 4/4] remove curobo repo which is unused and unrelated --- src/nvidia-curobo | 1 - 1 file changed, 1 deletion(-) delete mode 160000 src/nvidia-curobo diff --git a/src/nvidia-curobo b/src/nvidia-curobo deleted file mode 160000 index ebb71702f3f..00000000000 --- a/src/nvidia-curobo +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ebb71702f3f70e767f40fd8e050674af0288abe8