Instructions to use lukasskellijs/env_assembly_bench with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- LeRobot
How to use lukasskellijs/env_assembly_bench with LeRobot:
- Notebooks
- Google Colab
- Kaggle
| """HUD environment that loads assembly_bench from EnvHub (Hub download path). | |
| Standard HUD robot flow: ``env.gym(make_env)`` derives the contract/capability | |
| and serves over the robot WebSocket. ``make_env`` pulls this repo from the Hub | |
| (the same way LeRobot EnvHub does), then builds the Isaac Lab Arena sim. | |
| Serve (isaac conda, GPU):: | |
| OMNI_KIT_ACCEPT_EULA=YES ACCEPT_EULA=Y PRIVACY_CONSENT=Y \\ | |
| python -m hud.environment.server hud_env.py --port 8765 | |
| Scene config is the factory signature (``variant`` / ``num_envs`` / …); episodic | |
| args (seed) go through ``sim.reset``. | |
| """ | |
| from __future__ import annotations | |
| import importlib.util | |
| import os | |
| import sys | |
| from pathlib import Path | |
| from types import SimpleNamespace | |
| from hud import Environment | |
| HUB = os.environ.get("ASSEMBLY_BENCH_HUB", "lukasskellijs/env_assembly_bench") | |
| # Authored contract next to this file (absolute — cwd-relative would silently drift). | |
| _CONTRACT = Path(__file__).absolute().parent / "contract.json" | |
| def make_env( | |
| variant: str = "peg_round_M1_loose", | |
| num_envs: int = int(os.environ.get("ASSEMBLY_NUM_ENVS", "1")), | |
| embodiment: str = os.environ.get("ASSEMBLY_EMBODIMENT", "droid_abs_joint_pos_softmimic"), | |
| reward: str = os.environ.get("ASSEMBLY_REWARD", "none"), | |
| ): | |
| """Download EnvHub package (if needed) and return the vectorized Arena env.""" | |
| from huggingface_hub import snapshot_download | |
| # Fresh-enough Hub snapshot; local checkout of this repo also works when | |
| # ASSEMBLY_BENCH_HUB points at a path... snapshot always hits the Hub id. | |
| root = snapshot_download(repo_id=HUB) | |
| env_py = Path(root) / "env.py" | |
| if not env_py.is_file(): | |
| raise FileNotFoundError(f"Hub repo {HUB} missing env.py (got {root})") | |
| # Prefer Hub package over any editable/local assembly_bench install. | |
| if root in sys.path: | |
| sys.path.remove(root) | |
| sys.path.insert(0, root) | |
| for name in list(sys.modules): | |
| if name == "assembly_bench" or name.startswith("assembly_bench."): | |
| del sys.modules[name] | |
| spec = importlib.util.spec_from_file_location("env_assembly_bench_hub_env", env_py) | |
| module = importlib.util.module_from_spec(spec) | |
| assert spec.loader is not None | |
| spec.loader.exec_module(module) | |
| # IsaaclabArenaEnv-shaped config (no lerobot import required in the isaac env). | |
| cfg = SimpleNamespace( | |
| environment="assembly_bench", | |
| embodiment=embodiment, | |
| object=None, | |
| mimic=False, | |
| teleop_device=None, | |
| seed=42, | |
| device=os.environ.get("ASSEMBLY_DEVICE", "cuda:0"), | |
| disable_fabric=False, | |
| enable_cameras=True, | |
| headless=True, | |
| enable_pinocchio=False, | |
| episode_length=300, # hub make_env replaces 300 with variant duration | |
| state_dim=15, | |
| action_dim=8, | |
| camera_height=720, | |
| camera_width=1280, | |
| video=False, | |
| video_length=100, | |
| video_interval=200, | |
| state_keys="joint_pos,gripper_pos,eef_pos,eef_quat", | |
| camera_keys="front_cam_rgb,wrist_camera_rgb", | |
| task=None, # filled from variants.instruction | |
| variant=variant, | |
| reward=reward, | |
| hdr="asm_machine_shop", | |
| light_intensity=1500.0, | |
| ) | |
| suites = module.make_env(n_envs=num_envs, use_async_envs=False, cfg=cfg) | |
| # {suite: {task_id: VectorEnv}} → the live vectorized env | |
| return next(iter(next(iter(suites.values())).values())) | |
| env = Environment(name="assembly-bench") | |
| sim = env.gym( | |
| make_env, | |
| contract=_CONTRACT, | |
| variant="peg_round_M1_loose", | |
| ) | |
| async def assembly( | |
| variant: str = "peg_round_M1_loose", | |
| seed: int = 0, | |
| num_envs: int | None = None, | |
| embodiment: str | None = None, | |
| reward: str | None = None, | |
| ): | |
| """One assembly episode. Env-defining args rebuild the scene when they change.""" | |
| reset_kw: dict = {"variant": variant, "seed": seed} | |
| if num_envs is not None: | |
| reset_kw["num_envs"] = num_envs | |
| if embodiment is not None: | |
| reset_kw["embodiment"] = embodiment | |
| if reward is not None: | |
| reset_kw["reward"] = reward | |
| ep = await sim.reset(**reset_kw) | |
| yield {"prompt": ep["prompt"], "robot": {"token": ep["token"]}} | |
| yield await sim.result(token=ep["token"]) | |