diff --git a/pyproject.toml b/pyproject.toml index aed846f43..585af6f4b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -175,6 +175,11 @@ video_benchmark = ["scikit-image>=0.23.2,<0.26.0", "pandas>=2.2.2,<2.4.0"] aloha = ["gym-aloha>=0.1.2,<0.2.0", "lerobot[scipy-dep]"] pusht = ["gym-pusht>=0.1.5,<0.2.0", "pymunk>=6.6.0,<7.0.0"] # TODO: Fix pymunk version in gym-pusht instead libero = ["lerobot[transformers-dep]", "hf-libero>=0.1.3,<0.2.0; sys_platform == 'linux'", "lerobot[scipy-dep]"] +libero_plus = [ + "lerobot[transformers-dep]", + "libero @ git+https://github.com/sylvestf/LIBERO-plus.git@main ; sys_platform == 'linux'", + "lerobot[scipy-dep]", +] metaworld = ["metaworld==3.0.0", "lerobot[scipy-dep]"] # All diff --git a/src/lerobot/envs/configs.py b/src/lerobot/envs/configs.py index d53337b0c..2a73dd272 100644 --- a/src/lerobot/envs/configs.py +++ b/src/lerobot/envs/configs.py @@ -346,6 +346,19 @@ class LiberoEnv(EnvConfig): return kwargs +@EnvConfig.register_subclass("libero_plus") +@dataclass +class LiberoPlusEnv(LiberoEnv): + """Alias config for LIBERO-plus benchmarks. + + LIBERO-plus keeps the same Python package/module names as LIBERO, so this + config reuses the existing LIBERO env implementation while making intent explicit + in experiment configs (`env.type=libero_plus`). + """ + + task: str = "libero_spatial" + + @EnvConfig.register_subclass("robocasa") @dataclass class RoboCasaEnv(EnvConfig): diff --git a/src/lerobot/envs/factory.py b/src/lerobot/envs/factory.py index 3de674f21..365f74088 100644 --- a/src/lerobot/envs/factory.py +++ b/src/lerobot/envs/factory.py @@ -20,7 +20,16 @@ import gymnasium as gym from gymnasium.envs.registration import registry as gym_registry from lerobot.configs.policies import PreTrainedConfig -from lerobot.envs.configs import AlohaEnv, EnvConfig, HubEnvConfig, IsaaclabArenaEnv, LiberoEnv, PushtEnv, RoboCasaEnv +from lerobot.envs.configs import ( + AlohaEnv, + EnvConfig, + HubEnvConfig, + IsaaclabArenaEnv, + LiberoEnv, + LiberoPlusEnv, + PushtEnv, + RoboCasaEnv, +) from lerobot.envs.utils import _call_make_env, _download_hub_file, _import_hub_module, _normalize_hub_result from lerobot.policies.xvla.configuration_xvla import XVLAConfig from lerobot.processor import ProcessorStep @@ -35,6 +44,8 @@ def make_env_config(env_type: str, **kwargs) -> EnvConfig: return PushtEnv(**kwargs) elif env_type == "libero": return LiberoEnv(**kwargs) + elif env_type == "libero_plus": + return LiberoPlusEnv(**kwargs) elif env_type == "robocasa": return RoboCasaEnv(**kwargs) else: @@ -72,7 +83,7 @@ def make_env_pre_post_processors( return make_xvla_libero_pre_post_processors() # For LIBERO environments, add the LiberoProcessorStep to preprocessor - if isinstance(env_cfg, LiberoEnv) or "libero" in env_cfg.type: + if isinstance(env_cfg, (LiberoEnv, LiberoPlusEnv)) or "libero" in env_cfg.type: preprocessor_steps.append(LiberoProcessorStep()) # For RoboCasa environments, add the RoboCasaProcessorStep to preprocessor diff --git a/src/lerobot/envs/libero.py b/src/lerobot/envs/libero.py index d20dae8ea..968b1e734 100644 --- a/src/lerobot/envs/libero.py +++ b/src/lerobot/envs/libero.py @@ -26,8 +26,14 @@ import gymnasium as gym import numpy as np import torch from gymnasium import spaces -from libero.libero import benchmark, get_libero_path -from libero.libero.envs import OffScreenRenderEnv + +try: + from libero.libero import benchmark, get_libero_path + from libero.libero.envs import OffScreenRenderEnv +except ImportError: + # LIBERO-plus may be installed from source with an extra nested package level. + from libero.libero.libero import benchmark, get_libero_path + from libero.libero.libero.envs import OffScreenRenderEnv from lerobot.processor import RobotObservation