| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| FROM huggingface/lerobot-gpu:latest |
|
|
| ENV NVIDIA_DRIVER_CAPABILITIES=all \ |
| VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/nvidia_icd.json \ |
| ROBOTWIN_ROOT=/opt/robotwin |
|
|
| |
| |
| USER root |
| |
| |
| ARG ROBOTWIN_SHA=0aeea2d669c0f8516f4d5785f0aa33ba812c14b4 |
| RUN apt-get update \ |
| && apt-get install -y --no-install-recommends \ |
| cuda-nvcc-12-8 cuda-cudart-dev-12-8 \ |
| libvulkan1 vulkan-tools \ |
| && mkdir -p /usr/share/vulkan/icd.d \ |
| && echo '{"file_format_version":"1.0.0","ICD":{"library_path":"libGLX_nvidia.so.0","api_version":"1.3.0"}}' \ |
| > /usr/share/vulkan/icd.d/nvidia_icd.json \ |
| && git clone https://github.com/RoboTwin-Platform/RoboTwin.git ${ROBOTWIN_ROOT} \ |
| && git -C ${ROBOTWIN_ROOT} checkout ${ROBOTWIN_SHA} \ |
| && chown -R user_lerobot:user_lerobot ${ROBOTWIN_ROOT} \ |
| && apt-get clean && rm -rf /var/lib/apt/lists/* |
| USER user_lerobot |
|
|
| # RoboTwin runtime deps (av is already in the base via [av-dep]). |
| RUN uv pip install --no-cache \ |
| "sapien==3.0.0b1" "mplib==0.2.1" "transforms3d==0.4.2" "trimesh==4.4.3" \ |
| "open3d==0.19.0" "imageio==2.34.2" termcolor zarr pydantic h5py |
|
|
| # pytorch3d has no universal wheel; must be built from source (~10 min, cached). |
| RUN uv pip install --no-cache --no-build-isolation \ |
| "git+https://github.com/facebookresearch/pytorch3d.git@stable" |
|
|
| # CuRobo — NVlabs motion generator; TORCH_CUDA_ARCH_LIST must be set or the |
| # build aborts on an empty arch list. RoboTwin's own installer pins v0.7.8, |
| # which still exposes the v1 API (`curobo.types.math`) that RoboTwin imports. |
| ARG CUROBO_REF=v0.7.8 |
| RUN cd ${ROBOTWIN_ROOT}/envs \ |
| && git clone --branch ${CUROBO_REF} --depth 1 https://github.com/NVlabs/curobo.git \ |
| && cd curobo \ |
| && TORCH_CUDA_ARCH_LIST="7.0;7.5;8.0;8.6;8.9;9.0" \ |
| uv pip install -e . --no-build-isolation --no-cache |
|
|
| # Upstream patches (mirror RoboTwin's script/_install.sh). |
| # These patches target the exact versions pinned above; re-check when upgrading. |
| # mplib==0.2.1: drop a broken `or collide` clause in planner.py. |
| # Safe to remove once mplib > 0.2.1 ships with the fix upstream. |
| # sapien==3.0.0b1: fix URDF loader encoding + .srdf extension check. |
| # Safe to remove once sapien > 3.0.0b1 ships with the fix upstream. |
| RUN python - <<'EOF' |
| import pathlib, re, site |
| for d in site.getsitepackages(): |
| p = pathlib.Path(d) / "mplib" / "planner.py" |
| if p.exists(): |
| p.write_text(re.sub(r"\bor collide\b", "", p.read_text(), count=1)) |
| print(f"mplib patch applied: {p}") |
| p = pathlib.Path(d) / "sapien" / "wrapper" / "urdf_loader.py" |
| if p.exists(): |
| src = p.read_text().replace( |
| "with open(srdf_path) as f:", 'with open(srdf_path, encoding="utf-8") as f:' |
| ).replace('"srdf"', '".srdf"') |
| p.write_text(src) |
| print(f"sapien patch applied: {p}") |
| EOF |
|
|
| # Simulation assets from TianxingChen/RoboTwin2.0: embodiments (~220 MB) + |
| # objects (~3.74 GB). background_texture (~11 GB) is intentionally skipped. |
| # The dataset is public — no auth token needed. |
| RUN python - <<'EOF' |
| import os, pathlib, zipfile |
| from huggingface_hub import hf_hub_download |
|
|
| assets_dir = pathlib.Path(os.environ["ROBOTWIN_ROOT"]) / "assets" |
| assets_dir.mkdir(parents=True, exist_ok=True) |
| for fname in ("embodiments.zip", "objects.zip"): |
| local = hf_hub_download( |
| repo_id="TianxingChen/RoboTwin2.0", |
| repo_type="dataset", |
| filename=fname, |
| local_dir=str(assets_dir), |
| ) |
| with zipfile.ZipFile(local, "r") as z: |
| z.extractall(str(assets_dir)) |
| pathlib.Path(local).unlink() |
| EOF |
|
|
| WORKDIR ${ROBOTWIN_ROOT} |
| RUN python script/update_embodiment_config_path.py |
|
|
| ENV PYTHONPATH="${ROBOTWIN_ROOT}" |
|
|
| # Fail the image build early if the CuRobo package layout regresses. Importing |
| # RoboTwin's planner here is too eager because CuRobo constructs CUDA-backed |
| # defaults at import time, while Docker builds don't have access to an NVIDIA |
| # driver. |
| RUN python - <<'EOF' |
| from pathlib import Path |
|
|
| from curobo.types.math import Pose |
|
|
| planner_src = (Path("/opt/robotwin/envs/robot/planner.py")).read_text() |
| assert "from curobo.types.math import Pose as CuroboPose" in planner_src |
|
|
| print("CuRobo import OK:", Pose.__name__) |
| print("RoboTwin planner import references curobo.types.math") |
| EOF |
|
|
| # Return to the lerobot source directory (set by base image) before overlaying. |
| WORKDIR /lerobot |
|
|
| # Overlay the PR's source code on top of the nightly image. |
| COPY --chown=user_lerobot:user_lerobot . . |
|
|
| CMD ["/bin/bash"] |
|
|