mirror of
https://github.com/huggingface/lerobot.git
synced 2026-05-14 16:19:45 +00:00
e699e52388
* feat(envs): add RoboCasa365 benchmark integration Add RoboCasa365 (arXiv:2603.04356) as a new simulation benchmark with 365 everyday kitchen manipulation tasks across 2,500 diverse environments. New files: - src/lerobot/envs/robocasa.py: gym.Env wrapper with deferred env creation, flat 12D action / 16D state vectors, 3-camera support - docs/source/robocasa.mdx: user-facing documentation - docker/Dockerfile.benchmark.robocasa: CI benchmark image Modified files: - src/lerobot/envs/configs.py: RoboCasaEnv config (--env.type=robocasa) - pyproject.toml: robocasa optional dependency group - docs/source/_toctree.yml: sidebar entry - .github/workflows/benchmark_tests.yml: integration test job Refs: https://arxiv.org/abs/2603.04356, https://robocasa.ai Related: huggingface/lerobot#321 * fix(docker): use uv pip to install robocasa in benchmark image The huggingface/lerobot-gpu base image uses `uv` with a venv at /lerobot/.venv — `pip` is not on PATH, so `pip install` fails with "pip: not found". Switch to `uv pip install` which installs into the existing venv. Also drop the @v1.0.0 tag pin from the robocasa git URL since the upstream repo may not have that tag; use default branch instead. * fix(robocasa): editable install + switch to lerobot/smolvla_robocasa - pip install from git omits data files like box_links_assets.json (not declared in package_data). Clone and install editable so the source tree is used at runtime. - Download only tex + fixtures_lw asset types (smoke test doesn't need objaverse/aigen objects). Pipe 'y' to auto-accept download prompt. - Switch CI policy from pepijn223/smolvla_robocasa to lerobot/smolvla_robocasa. * fix(docker): re-install lerobot editably after COPY The nightly huggingface/lerobot-gpu image predates the RoboCasaEnv registration — so `lerobot-eval --env.type=robocasa` fails at argparse with "invalid choice" even after COPY . . overlays the new source. Force an editable reinstall so the venv picks up the current configs.py. * fix(ci): add rename_map for robocasa eval (image* -> camera*) Policy lerobot/smolvla_robocasa expects observation.images.camera1/2/3, but RoboCasaEnv produces observation.images.image/image2/image3. * fix(robocasa): override RoboCasaGymEnv default split (test -> all) RoboCasaGymEnv defaults split="test", but create_env only accepts {None, "all", "pretrain", "target"}, so the out-of-the-box default crashes with ValueError. Always pass "all" when split is None. * fix(docker): also download objs_lw (lightwheel objects) for robocasa Kitchen tasks (e.g. CloseFridge) reference lightwheel object meshes like Stool022/model.xml. fixtures_lw alone isn't enough — we also need objs_lw. Still skipping objaverse/aigen to keep image size down. Made-with: Cursor * feat(robocasa): raw camera names + benchmark-group task shortcuts Align the LeRobot env with RoboCasa's native conventions so policies trained on the upstream datasets don't need a --rename_map at eval time, and expose the standard task groups as first-class --env.task values. - Preserve raw RoboCasa camera names (e.g. robot0_agentview_left) as observation.images.<name> end-to-end. Drops camera_name_mapping and DEFAULT_CAMERA_NAME_MAPPING; features/features_map are now built dynamically from the parsed camera list. - Accept benchmark-group names as --env.task: atomic_seen, composite_seen, composite_unseen, pretrain50/100/200/300. Expanded lazily via robocasa.utils.dataset_registry and auto-sets the split ("target" | "pretrain"). - Update CI smoke-eval rename_map to map raw cam names to the camera1/2/3 keys expected by lerobot/smolvla_robocasa. * docs(robocasa): single-task smolvla train+eval recipe on pepijn223/robocasa_CloseFridge - Rewrite observation section to use raw RoboCasa camera keys (observation.images.robot0_agentview_{left,right}, observation.images.robot0_eye_in_hand). - Add a "Training on a single task" section with a full smolvla training command on pepijn223/robocasa_CloseFridge, plus matching single-task eval command. - Document benchmark-group task shortcuts (atomic_seen, composite_seen, composite_unseen, pretrain50/100/200/300) as valid --env.task values. * fix(robocasa): restrict obj_registries to lightwheel by default CloseFridge (and most kitchen tasks) crashed at reset with `ValueError: Probabilities contain NaN` coming out of `sample_kitchen_object_helper`. RoboCasa's upstream default `obj_registries=("objaverse", "lightwheel")` normalizes per-registry candidate counts as probabilities; when a sampled category has zero mjcf paths in every configured registry (because the objaverse asset pack isn't on disk — ~30GB, skipped by our Docker build), the 0/0 divide yields NaNs and `rng.choice` raises. - Add `obj_registries: list[str] = ["lightwheel"]` to `RoboCasaEnv` config; thread it through `create_robocasa_envs`, `_make_env_fns`, and the gym.Env wrapper to the underlying `RoboCasaGymEnv` (which forwards to `create_env` → `robosuite.make` → kitchen env). - Default matches what `download_kitchen_assets --type objs_lw` actually ships, so the env works out of the box without a 30GB objaverse download. - Document the override (`--env.obj_registries='[objaverse,lightwheel]'`) for users who have downloaded the full asset set. * fix(docker): also download tex_generative for robocasa benchmark RoboCasa's lightwheel kitchen fixtures embed references to `generative_textures/wall/tex*.png` directly in their MuJoCo XML, so `MjModel.from_xml_string` errors out at reset time with "No such file or directory" even when the env is constructed with `generative_textures=None`. The generative textures live under a separate asset registry key (`tex_generative`) in `download_kitchen_assets`, distinct from the base `tex` pack we were already fetching. - Add `tex_generative` to the download list so the fixture XMLs resolve. - Document the remaining omissions (objaverse/aigen, ~30GB) and how the runtime side pairs this with obj_registries=["lightwheel"] to avoid sampling from categories whose assets aren't on disk. * ci(robocasa): smoke-eval 10 atomic tasks instead of 1 Broader coverage in the benchmark CI job: evaluate SmolVLA on ten fixture-centric atomic RoboCasa tasks (one episode each) instead of just CloseFridge. The tasks are all drawn from TARGET_TASKS.atomic_seen and selected to avoid object-manipulation categories that would require the objaverse/aigen asset packs (we only ship objs_lw in the Docker image, paired with obj_registries=["lightwheel"] on the runtime side). Tasks: CloseFridge, OpenCabinet, OpenDrawer, TurnOnMicrowave, TurnOffStove, CloseToasterOvenDoor, SlideDishwasherRack, TurnOnSinkFaucet, NavigateKitchen, TurnOnElectricKettle. `scripts/ci/parse_eval_metrics.py` already handles multi-task output via the `overall` key, so no parser changes needed. Bumped the metrics artifact's task label to `atomic_smoke_10` to reflect the grouping. * fix(pyproject): drop unresolvable robocasa extra robocasa's upstream setup.py hardcodes `lerobot==0.3.3` in install_requires. Exposing it as the `lerobot[robocasa]` extra made uv's dep resolver cycle: `lerobot[robocasa]` -> robocasa -> lerobot (a different version) -> unsolvable. This broke every `uv sync` — even invocations with an unrelated extra like `--extra test` — because uv validates the whole lockfile graph. - Remove the `robocasa` extra from pyproject.toml. Installation instructions in docs/source/robocasa.mdx now walk users through the manual `git clone` + `pip install --no-deps` flow, which matches what the Docker image already does and sidesteps the cyclic dep entirely. - Dockerfile: `uv pip install -e ~/robocasa --no-deps` so the shadowed lerobot==0.3.3 never lands in the image; install robocasa's actual runtime deps (numpy, numba, scipy, mujoco, tianshou, etc.) explicitly. * docs(robocasa): align page with adding_benchmarks template Rework docs/source/robocasa.mdx to follow the standard benchmark doc structure: intro + links + available tasks (with family breakdown and first-class benchmark-group shortcuts) + installation + eval + recommended episodes + policy I/O + training + reproducing results. - Fix the paper link (was pointing at a non-existent arxiv ID). - Surface lerobot/smolvla_robocasa and pepijn223/robocasa_CloseFridge in the top-of-page links so they're findable without reading the training section. - Add an explicit "Object registries" subsection explaining the `--env.obj_registries=[objaverse,lightwheel]` override path. - Add an explicit "Reproducing published results" section pointing at the CI smoke eval. * fix: integrate PR #3375 review feedback - envs(robocasa): hoist the duplicated `_parse_camera_names` helper out of `libero.py` and `robocasa.py` into `envs/utils.py` as the public `parse_camera_names`; call sites updated. - envs(robocasa): give each factory a distinct `episode_index` (`0..n_envs-1`) and derive a per-worker seed series in `reset()` so n_envs workers don't all roll the same scene under a shared outer seed. - envs(robocasa): drop the unused `**kwargs` on `_make_env`; declare `visualization_height` / `visualization_width` on both the wrapper and the `RoboCasaEnv` config + propagate via `gym_kwargs`. - envs(robocasa): emit `info["final_info"]` on termination (matching MetaWorld) so downstream vector-env auto-reset keeps the terminal task/success flags. - docs(robocasa): add `--rename_map` (robot0_agentview_left/ eye_in_hand/agentview_right → camera1/2/3) plus CI-parity flags to all three eval snippets. - docker(robocasa): pin robocasa + robosuite git SHAs and the pip dep versions (pygame, Pillow, opencv-python, pyyaml, pynput, tqdm, termcolor, imageio, h5py, lxml, hidapi, gymnasium) for reproducible benchmark images. - ci(robocasa): update the workflow comment — there is no `lerobot[robocasa]` extra; robocasa/robosuite are installed manually because upstream's `lerobot==0.3.3` pin shadows ours. * docs(robocasa): add benchmark banner image * fix(envs): preserve AsyncVectorEnv metadata/unwrapped in lazy eval envs Port of #3416 onto this branch. Also threads the cached metadata through the RoboCasa factory so async eval on `--env.type=robocasa` keeps the same improvement. * fix: integrate PR #3375 review feedback (round 2) - envs(robocasa): when the caller passes `seed=None` to `reset()`, fall back to `self.episode_index` for the inner env seed so each worker still samples a distinct trajectory instead of all workers inheriting the same global RNG state. - envs(robocasa): replace the two module-level `print()` calls in `create_robocasa_envs` with `logger.info(...)` via a module-level `logger = logging.getLogger(__name__)`. - ci(robocasa): run `scripts/ci/extract_task_descriptions.py` after the eval so `metrics.json` carries per-task natural-language labels, matching LIBERO / MetaWorld / VLABench jobs. Added a `_robocasa_descriptions()` extractor that splits CamelCase task names into word-level labels keyed by `<task>_0`.
470 lines
16 KiB
TOML
470 lines
16 KiB
TOML
# Copyright 2024 The HuggingFace Inc. team. All rights reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
[build-system]
|
|
requires = ["setuptools"]
|
|
build-backend = "setuptools.build_meta"
|
|
|
|
[project.urls]
|
|
homepage = "https://huggingface.co/lerobot"
|
|
documentation = "https://huggingface.co/docs/lerobot/index"
|
|
source = "https://github.com/huggingface/lerobot"
|
|
issues = "https://github.com/huggingface/lerobot/issues"
|
|
discord = "https://discord.gg/s3KuuzsPFb"
|
|
|
|
[project]
|
|
name = "lerobot"
|
|
version = "0.5.2"
|
|
description = "🤗 LeRobot: State-of-the-art Machine Learning for Real-World Robotics in Pytorch"
|
|
dynamic = ["readme"]
|
|
license = { text = "Apache-2.0" }
|
|
requires-python = ">=3.12"
|
|
authors = [
|
|
{ name = "Rémi Cadène", email = "re.cadene@gmail.com" },
|
|
{ name = "Simon Alibert", email = "alibert.sim@gmail.com" },
|
|
{ name = "Alexander Soare", email = "alexander.soare159@gmail.com" },
|
|
{ name = "Quentin Gallouédec", email = "quentin.gallouedec@ec-lyon.fr" },
|
|
{ name = "Steven Palma", email = "imstevenpmwork@ieee.org" },
|
|
{ name = "Pepijn Kooijmans", email = "pepijnkooijmans@outlook.com"},
|
|
{ name = "Michel Aractingi", email = "michel.aractingi@gmail.com"},
|
|
{ name = "Adil Zouitine", email = "adilzouitinegm@gmail.com" },
|
|
{ name = "Dana Aubakirova", email = "danaaubakirova17@gmail.com"},
|
|
{ name = "Caroline Pascal", email = "caroline8.pascal@gmail.com"},
|
|
{ name = "Martino Russi", email = "nopyeps@gmail.com"},
|
|
{ name = "Thomas Wolf", email = "thomaswolfcontact@gmail.com" },
|
|
]
|
|
classifiers = [
|
|
"Development Status :: 3 - Alpha",
|
|
"Intended Audience :: Developers",
|
|
"Intended Audience :: Education",
|
|
"Intended Audience :: Science/Research",
|
|
"License :: OSI Approved :: Apache Software License",
|
|
"Programming Language :: Python :: 3.12",
|
|
"Programming Language :: Python :: 3.13",
|
|
"Topic :: Software Development :: Build Tools",
|
|
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
]
|
|
keywords = ["lerobot", "huggingface", "robotics", "machine learning", "artificial intelligence"]
|
|
|
|
dependencies = [
|
|
# Core ML
|
|
"torch>=2.7,<2.11.0",
|
|
"torchvision>=0.22.0,<0.26.0",
|
|
"numpy>=2.0.0,<2.3.0", # NOTE: Explicitly listing numpy helps the resolver converge faster. Upper bound imposed by opencv-python-headless.
|
|
"opencv-python-headless>=4.9.0,<4.14.0",
|
|
"Pillow>=10.0.0,<13.0.0",
|
|
"einops>=0.8.0,<0.9.0",
|
|
|
|
# Config & Hub
|
|
"draccus==0.10.0", # TODO: Relax version constraint
|
|
"huggingface-hub>=1.0.0,<2.0.0",
|
|
"requests>=2.32.0,<3.0.0",
|
|
|
|
# Environments
|
|
# NOTE: gymnasium is used in lerobot.envs (lerobot-train, lerobot-eval), policies/factory,
|
|
# and robots/unitree. Moving it to an optional extra would require import guards across many
|
|
# tightly-coupled modules. Candidate for a future refactor to decouple envs from the core.
|
|
"gymnasium>=1.1.1,<2.0.0",
|
|
|
|
# Serialization & checkpointing
|
|
"safetensors>=0.4.3,<1.0.0",
|
|
|
|
# Lightweight utilities
|
|
"packaging>=24.2,<26.0",
|
|
"termcolor>=2.4.0,<4.0.0",
|
|
"tqdm>=4.66.0,<5.0.0",
|
|
|
|
# Build tools (required by opencv-python-headless on some platforms)
|
|
"cmake>=3.29.0.1,<4.2.0",
|
|
"setuptools>=71.0.0,<81.0.0",
|
|
]
|
|
|
|
# Optional dependencies
|
|
[project.optional-dependencies]
|
|
|
|
# ── Feature-scoped extras ──────────────────────────────────
|
|
dataset = [
|
|
"datasets>=4.0.0,<5.0.0",
|
|
"pandas>=2.0.0,<3.0.0", # NOTE: Transitive dependency of datasets
|
|
"pyarrow>=21.0.0,<30.0.0", # NOTE: Transitive dependency of datasets
|
|
"lerobot[av-dep]",
|
|
"torchcodec>=0.3.0,<0.11.0; sys_platform != 'win32' and (sys_platform != 'linux' or (platform_machine != 'aarch64' and platform_machine != 'arm64' and platform_machine != 'armv7l')) and (sys_platform != 'darwin' or platform_machine != 'x86_64')", # NOTE: Windows support starts at version 0.7 (needs torch==2.8), ffmpeg>=8 support starts at version 0.8.1 (needs torch==2.9), system-wide ffmpeg support starts at version 0.10 (needs torch==2.10).
|
|
"jsonlines>=4.0.0,<5.0.0",
|
|
]
|
|
training = [
|
|
"lerobot[dataset]",
|
|
"accelerate>=1.10.0,<2.0.0",
|
|
"wandb>=0.24.0,<0.25.0",
|
|
]
|
|
hardware = [
|
|
"lerobot[pynput-dep]",
|
|
"lerobot[pyserial-dep]",
|
|
"lerobot[deepdiff-dep]",
|
|
]
|
|
viz = [
|
|
"rerun-sdk>=0.24.0,<0.27.0",
|
|
]
|
|
# ── User-facing composite extras (map to CLI scripts) ─────
|
|
# lerobot-record, lerobot-replay, lerobot-calibrate, lerobot-teleoperate, etc.
|
|
core_scripts = ["lerobot[dataset]", "lerobot[hardware]", "lerobot[viz]"]
|
|
# lerobot-eval -- base evaluation framework. You also need the policy's extra (e.g., lerobot[pi])
|
|
# and the environment's extra (e.g., lerobot[pusht]) if evaluating in simulation.
|
|
evaluation = ["lerobot[av-dep]"]
|
|
# lerobot-dataset-viz, lerobot-imgtransform-viz
|
|
dataset_viz = ["lerobot[dataset]", "lerobot[viz]"]
|
|
|
|
# Common
|
|
av-dep = ["av>=15.0.0,<16.0.0"]
|
|
pygame-dep = ["pygame>=2.5.1,<2.7.0"]
|
|
placo-dep = ["placo>=0.9.6,<0.9.17"]
|
|
transformers-dep = ["transformers==5.3.0"] # TODO(Steven): https://github.com/huggingface/lerobot/pull/3249
|
|
grpcio-dep = ["grpcio==1.73.1", "protobuf>=6.31.1,<6.32.0"]
|
|
can-dep = ["python-can>=4.2.0,<5.0.0"]
|
|
peft-dep = ["peft>=0.18.0,<1.0.0"]
|
|
scipy-dep = ["scipy>=1.14.0,<2.0.0"]
|
|
diffusers-dep = ["diffusers>=0.27.2,<0.36.0"]
|
|
qwen-vl-utils-dep = ["qwen-vl-utils>=0.0.11,<0.1.0"]
|
|
matplotlib-dep = ["matplotlib>=3.10.3,<4.0.0", "contourpy>=1.3.0,<2.0.0"] # NOTE: Explicitly listing contourpy helps the resolver converge faster.
|
|
pyserial-dep = ["pyserial>=3.5,<4.0"]
|
|
deepdiff-dep = ["deepdiff>=7.0.1,<9.0.0"]
|
|
pynput-dep = ["pynput>=1.7.8,<1.9.0"]
|
|
pyzmq-dep = ["pyzmq>=26.2.1,<28.0.0"]
|
|
|
|
# Motors
|
|
feetech = ["feetech-servo-sdk>=1.0.0,<2.0.0", "lerobot[pyserial-dep]", "lerobot[deepdiff-dep]"]
|
|
dynamixel = ["dynamixel-sdk>=3.7.31,<3.9.0", "lerobot[pyserial-dep]", "lerobot[deepdiff-dep]"]
|
|
damiao = ["lerobot[can-dep]"]
|
|
robstride = ["lerobot[can-dep]"]
|
|
|
|
# Robots
|
|
openarms = ["lerobot[damiao]"]
|
|
gamepad = ["lerobot[pygame-dep]", "hidapi>=0.14.0,<0.15.0"]
|
|
hopejr = ["lerobot[feetech]", "lerobot[pygame-dep]"]
|
|
lekiwi = ["lerobot[feetech]", "lerobot[pyzmq-dep]"]
|
|
unitree_g1 = [
|
|
# "unitree-sdk2==1.0.1",
|
|
"lerobot[pyzmq-dep]",
|
|
"lerobot[pyserial-dep]",
|
|
"onnxruntime>=1.16.0,<2.0.0",
|
|
"onnx>=1.16.0,<2.0.0",
|
|
"meshcat>=0.3.0,<0.4.0",
|
|
"lerobot[matplotlib-dep]",
|
|
"lerobot[pygame-dep]",
|
|
]
|
|
reachy2 = ["reachy2_sdk>=1.0.15,<1.1.0"]
|
|
kinematics = ["lerobot[placo-dep]"]
|
|
intelrealsense = [
|
|
"pyrealsense2>=2.55.1.6486,<2.57.0 ; sys_platform != 'darwin'",
|
|
"pyrealsense2-macosx>=2.54,<2.57.0 ; sys_platform == 'darwin'",
|
|
]
|
|
phone = ["hebi-py>=2.8.0,<2.12.0", "teleop>=0.1.0,<0.2.0", "fastapi<1.0", "lerobot[scipy-dep]"]
|
|
|
|
# Policies
|
|
diffusion = ["lerobot[diffusers-dep]"]
|
|
wallx = [
|
|
"lerobot[transformers-dep]",
|
|
"lerobot[peft-dep]",
|
|
"lerobot[scipy-dep]",
|
|
"torchdiffeq>=0.2.4,<0.3.0",
|
|
"lerobot[qwen-vl-utils-dep]",
|
|
]
|
|
pi = ["lerobot[transformers-dep]", "lerobot[scipy-dep]"]
|
|
smolvla = ["lerobot[transformers-dep]", "num2words>=0.5.14,<0.6.0", "accelerate>=1.7.0,<2.0.0"]
|
|
multi_task_dit = ["lerobot[transformers-dep]", "lerobot[diffusers-dep]"]
|
|
groot = [
|
|
"lerobot[transformers-dep]",
|
|
"lerobot[peft-dep]",
|
|
"lerobot[diffusers-dep]",
|
|
"dm-tree>=0.1.8,<1.0.0",
|
|
"timm>=1.0.0,<1.1.0",
|
|
"decord>=0.6.0,<1.0.0; (platform_machine == 'AMD64' or platform_machine == 'x86_64')",
|
|
"ninja>=1.11.1,<2.0.0",
|
|
"flash-attn>=2.5.9,<3.0.0 ; sys_platform != 'darwin'"
|
|
]
|
|
sarm = ["lerobot[transformers-dep]", "pydantic>=2.0.0,<3.0.0", "faker>=33.0.0,<35.0.0", "lerobot[matplotlib-dep]", "lerobot[qwen-vl-utils-dep]"]
|
|
xvla = ["lerobot[transformers-dep]"]
|
|
hilserl = ["lerobot[transformers-dep]", "gym-hil>=0.1.13,<0.2.0", "lerobot[grpcio-dep]", "lerobot[placo-dep]"]
|
|
|
|
# Features
|
|
async = ["lerobot[grpcio-dep]", "lerobot[matplotlib-dep]"]
|
|
peft = ["lerobot[transformers-dep]", "lerobot[peft-dep]"]
|
|
|
|
# Development
|
|
dev = ["pre-commit>=3.7.0,<5.0.0", "debugpy>=1.8.1,<1.9.0", "lerobot[grpcio-dep]", "grpcio-tools==1.73.1", "mypy>=1.19.1", "ruff>=0.14.1", "lerobot[notebook]"]
|
|
notebook = ["jupyter>=1.0.0,<2.0.0", "ipykernel>=6.0.0,<7.0.0"]
|
|
test = ["pytest>=8.1.0,<9.0.0", "pytest-timeout>=2.4.0,<3.0.0", "pytest-cov>=5.0.0,<8.0.0", "mock-serial>=0.0.1,<0.1.0 ; sys_platform != 'win32'"]
|
|
video_benchmark = ["scikit-image>=0.23.2,<0.26.0", "pandas>=2.2.2,<2.4.0"]
|
|
|
|
# Simulation
|
|
# NOTE: Explicitly listing scipy helps flatten the dependecy tree.
|
|
aloha = ["lerobot[dataset]", "gym-aloha>=0.1.2,<0.2.0", "lerobot[scipy-dep]"]
|
|
pusht = ["lerobot[dataset]", "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[dataset]", "lerobot[transformers-dep]", "hf-libero>=0.1.3,<0.2.0; sys_platform == 'linux'", "lerobot[scipy-dep]"]
|
|
metaworld = ["lerobot[dataset]", "metaworld==3.0.0", "lerobot[scipy-dep]"]
|
|
# NOTE: robocasa is NOT exposed as a `lerobot` extra. Its setup.py pins
|
|
# `lerobot==0.3.3` in install_requires, which cyclically shadows our own
|
|
# workspace `lerobot` and makes the graph unsolvable under any resolver
|
|
# (uv, pip). Install it manually alongside robosuite — see
|
|
# docs/source/robocasa.mdx for the recipe.
|
|
|
|
# All
|
|
all = [
|
|
# Feature-scoped extras
|
|
"lerobot[dataset]",
|
|
"lerobot[training]",
|
|
"lerobot[hardware]",
|
|
"lerobot[viz]",
|
|
# NOTE(resolver hint): scipy is pulled in transitively via lerobot[scipy-dep] through
|
|
# multiple extras (aloha, metaworld, pi, wallx, phone). Listing it explicitly
|
|
# helps pip's resolver converge by constraining scipy early, before it encounters
|
|
# the loose scipy requirements from transitive deps like dm-control and metaworld.
|
|
"scipy>=1.14.0,<2.0.0",
|
|
"lerobot[dynamixel]",
|
|
"lerobot[feetech]",
|
|
"lerobot[damiao]",
|
|
"lerobot[robstride]",
|
|
"lerobot[gamepad]",
|
|
"lerobot[hopejr]",
|
|
"lerobot[lekiwi]",
|
|
"lerobot[openarms]",
|
|
"lerobot[reachy2]",
|
|
"lerobot[kinematics]",
|
|
"lerobot[intelrealsense]",
|
|
"lerobot[diffusion]",
|
|
"lerobot[multi_task_dit]",
|
|
"lerobot[wallx]",
|
|
"lerobot[pi]",
|
|
"lerobot[smolvla]",
|
|
# "lerobot[groot]", TODO(Steven): Gr00t requires specific installation instructions for flash-attn
|
|
"lerobot[xvla]",
|
|
"lerobot[hilserl]",
|
|
"lerobot[async]",
|
|
"lerobot[dev]",
|
|
"lerobot[test]",
|
|
"lerobot[video_benchmark]",
|
|
"lerobot[aloha]",
|
|
"lerobot[pusht]",
|
|
"lerobot[phone]",
|
|
"lerobot[libero]; sys_platform == 'linux'",
|
|
"lerobot[metaworld]",
|
|
"lerobot[sarm]",
|
|
"lerobot[peft]",
|
|
# "lerobot[unitree_g1]", TODO: Unitree requires specific installation instructions for unitree_sdk2
|
|
]
|
|
|
|
[project.scripts]
|
|
lerobot-calibrate="lerobot.scripts.lerobot_calibrate:main"
|
|
lerobot-find-cameras="lerobot.scripts.lerobot_find_cameras:main"
|
|
lerobot-find-port="lerobot.scripts.lerobot_find_port:main"
|
|
lerobot-record="lerobot.scripts.lerobot_record:main"
|
|
lerobot-replay="lerobot.scripts.lerobot_replay:main"
|
|
lerobot-setup-motors="lerobot.scripts.lerobot_setup_motors:main"
|
|
lerobot-teleoperate="lerobot.scripts.lerobot_teleoperate:main"
|
|
lerobot-eval="lerobot.scripts.lerobot_eval:main"
|
|
lerobot-train="lerobot.scripts.lerobot_train:main"
|
|
lerobot-train-tokenizer="lerobot.scripts.lerobot_train_tokenizer:main"
|
|
lerobot-dataset-viz="lerobot.scripts.lerobot_dataset_viz:main"
|
|
lerobot-info="lerobot.scripts.lerobot_info:main"
|
|
lerobot-find-joint-limits="lerobot.scripts.lerobot_find_joint_limits:main"
|
|
lerobot-imgtransform-viz="lerobot.scripts.lerobot_imgtransform_viz:main"
|
|
lerobot-edit-dataset="lerobot.scripts.lerobot_edit_dataset:main"
|
|
lerobot-setup-can="lerobot.scripts.lerobot_setup_can:main"
|
|
|
|
# ---------------- Tool Configurations ----------------
|
|
[tool.setuptools.package-data]
|
|
lerobot = ["envs/*.json"]
|
|
|
|
[tool.setuptools.packages.find]
|
|
where = ["src"]
|
|
|
|
[tool.ruff]
|
|
target-version = "py312"
|
|
line-length = 110
|
|
exclude = ["tests/artifacts/**/*.safetensors", "*_pb2.py", "*_pb2_grpc.py"]
|
|
|
|
[tool.ruff.lint]
|
|
# E, W: pycodestyle errors and warnings
|
|
# F: PyFlakes
|
|
# I: isort
|
|
# UP: pyupgrade
|
|
# B: flake8-bugbear (good practices, potential bugs)
|
|
# C4: flake8-comprehensions (more concise comprehensions)
|
|
# A: flake8-builtins (shadowing builtins)
|
|
# SIM: flake8-simplify
|
|
# RUF: Ruff-specific rules
|
|
# D: pydocstyle (for docstring style/formatting)
|
|
# S: flake8-bandit (some security checks, complements Bandit)
|
|
# T20: flake8-print (discourage print statements in production code)
|
|
# N: pep8-naming
|
|
# TODO: Uncomment rules when ready to use
|
|
select = [
|
|
"E", "W", "F", "I", "B", "C4", "T20", "N", "UP", "SIM" #, "A", "S", "D", "RUF"
|
|
]
|
|
ignore = [
|
|
"E501", # Line too long
|
|
"T201", # Print statement found
|
|
"T203", # Pprint statement found
|
|
"B008", # Perform function call in argument defaults
|
|
]
|
|
|
|
[tool.ruff.lint.per-file-ignores]
|
|
"__init__.py" = ["F401", "F403", "E402"]
|
|
# E402: conditional-import guards (TYPE_CHECKING / is_package_available) must precede the imports they protect
|
|
"src/lerobot/scripts/convert_dataset_v21_to_v30.py" = ["E402"]
|
|
"src/lerobot/policies/wall_x/**" = ["N801", "N812", "SIM102", "SIM108", "SIM210", "SIM211", "B006", "B007", "SIM118"] # Supprese these as they are coming from original Qwen2_5_vl code TODO(pepijn): refactor original
|
|
|
|
[tool.ruff.lint.isort]
|
|
combine-as-imports = true
|
|
known-first-party = ["lerobot"]
|
|
|
|
[tool.ruff.lint.pydocstyle]
|
|
convention = "google"
|
|
|
|
[tool.ruff.format]
|
|
quote-style = "double"
|
|
indent-style = "space"
|
|
skip-magic-trailing-comma = false
|
|
line-ending = "auto"
|
|
docstring-code-format = true
|
|
|
|
[tool.bandit]
|
|
exclude_dirs = [
|
|
"tests",
|
|
"benchmarks",
|
|
"src/lerobot/datasets/push_dataset_to_hub",
|
|
]
|
|
skips = ["B101", "B311", "B404", "B603", "B615"]
|
|
|
|
[tool.typos]
|
|
default.extend-ignore-re = [
|
|
"(?Rm)^.*(#|//)\\s*spellchecker:disable-line$", # spellchecker:disable-line
|
|
"(?s)(#|//)\\s*spellchecker:off.*?\\n\\s*(#|//)\\s*spellchecker:on", # spellchecker:<on|off>
|
|
]
|
|
default.extend-ignore-identifiers-re = [
|
|
# Add individual words here to ignore them
|
|
"2nd",
|
|
"pn",
|
|
"ser",
|
|
"ein",
|
|
"thw",
|
|
"inpt",
|
|
"ROBOTIS",
|
|
"OT_VALUE"
|
|
]
|
|
|
|
# TODO: Uncomment when ready to use
|
|
# [tool.interrogate]
|
|
# ignore-init-module = true
|
|
# ignore-init-method = true
|
|
# ignore-nested-functions = false
|
|
# ignore-magic = false
|
|
# ignore-semiprivate = false
|
|
# ignore-private = false
|
|
# ignore-property-decorators = false
|
|
# ignore-module = false
|
|
# ignore-setters = false
|
|
# fail-under = 80
|
|
# output-format = "term-missing"
|
|
# color = true
|
|
# paths = ["src/lerobot"]
|
|
|
|
# TODO: Enable mypy gradually module by module across multiple PRs
|
|
# Uncomment [tool.mypy] first, then uncomment individual module overrides as they get proper type annotations
|
|
|
|
[tool.mypy]
|
|
python_version = "3.12"
|
|
ignore_missing_imports = true
|
|
follow_imports = "skip"
|
|
# warn_return_any = true
|
|
# warn_unused_configs = true
|
|
# strict = true
|
|
# disallow_untyped_defs = true
|
|
# disallow_incomplete_defs = true
|
|
# check_untyped_defs = true
|
|
|
|
[[tool.mypy.overrides]]
|
|
module = "lerobot.*"
|
|
ignore_errors = true
|
|
|
|
[[tool.mypy.overrides]]
|
|
module = "lerobot.envs.*"
|
|
ignore_errors = false
|
|
|
|
|
|
# [[tool.mypy.overrides]]
|
|
# module = "lerobot.utils.*"
|
|
# ignore_errors = false
|
|
|
|
[[tool.mypy.overrides]]
|
|
module = "lerobot.configs.*"
|
|
ignore_errors = false
|
|
|
|
# extra strictness for configs
|
|
disallow_untyped_defs = true
|
|
disallow_incomplete_defs = true
|
|
check_untyped_defs = true
|
|
|
|
[[tool.mypy.overrides]]
|
|
module = "lerobot.optim.*"
|
|
ignore_errors = false
|
|
|
|
[[tool.mypy.overrides]]
|
|
module = "lerobot.model.*"
|
|
ignore_errors = false
|
|
|
|
# [[tool.mypy.overrides]]
|
|
# module = "lerobot.processor.*"
|
|
# ignore_errors = false
|
|
|
|
# [[tool.mypy.overrides]]
|
|
# module = "lerobot.datasets.*"
|
|
# ignore_errors = false
|
|
|
|
[[tool.mypy.overrides]]
|
|
module = "lerobot.cameras.*"
|
|
ignore_errors = false
|
|
|
|
[[tool.mypy.overrides]]
|
|
module = "lerobot.motors.*"
|
|
ignore_errors = false
|
|
|
|
# [[tool.mypy.overrides]]
|
|
# module = "lerobot.robots.*"
|
|
# ignore_errors = false
|
|
|
|
# [[tool.mypy.overrides]]
|
|
# module = "lerobot.teleoperators.*"
|
|
# ignore_errors = false
|
|
|
|
# [[tool.mypy.overrides]]
|
|
# module = "lerobot.policies.*"
|
|
# ignore_errors = false
|
|
|
|
# [[tool.mypy.overrides]]
|
|
# module = "lerobot.rl.*"
|
|
# ignore_errors = false
|
|
|
|
|
|
# [[tool.mypy.overrides]]
|
|
# module = "lerobot.async_inference.*"
|
|
# ignore_errors = false
|
|
|
|
[[tool.mypy.overrides]]
|
|
module = "lerobot.transport.*"
|
|
ignore_errors = false
|
|
|
|
# [[tool.mypy.overrides]]
|
|
# module = "lerobot.scripts.*"
|
|
# ignore_errors = false
|