From 906b585826c0e34235a347554abfb94e0d65484b Mon Sep 17 00:00:00 2001 From: Khalil Meftah Date: Tue, 2 Jun 2026 19:25:13 +0200 Subject: [PATCH 1/4] fix(datasets): default `private` to `None` in `push_to_hub` to respect Hub org visibility settings (#3713) --- src/lerobot/configs/dataset.py | 4 ++-- src/lerobot/datasets/lerobot_dataset.py | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/lerobot/configs/dataset.py b/src/lerobot/configs/dataset.py index d5c6fa312..c40c0fae2 100644 --- a/src/lerobot/configs/dataset.py +++ b/src/lerobot/configs/dataset.py @@ -41,8 +41,8 @@ class DatasetRecordConfig: video: bool = True # Upload dataset to Hugging Face hub. push_to_hub: bool = True - # Upload on private repository on the Hugging Face hub. - private: bool = False + # If True, upload as private; if None, defer to the org default on the Hub (only affects orgs). + private: bool | None = None # Add tags to your dataset on the hub. tags: list[str] | None = None # Number of subprocesses handling the saving of frames as PNG. Set to 0 to use threads only; diff --git a/src/lerobot/datasets/lerobot_dataset.py b/src/lerobot/datasets/lerobot_dataset.py index 9734bcc74..d0dcf087d 100644 --- a/src/lerobot/datasets/lerobot_dataset.py +++ b/src/lerobot/datasets/lerobot_dataset.py @@ -524,7 +524,7 @@ class LeRobotDataset(torch.utils.data.Dataset): license: str | None = "apache-2.0", tag_version: bool = True, push_videos: bool = True, - private: bool = False, + private: bool | None = None, allow_patterns: list[str] | str | None = None, upload_large_folder: bool = False, **card_kwargs, @@ -543,7 +543,8 @@ class LeRobotDataset(torch.utils.data.Dataset): tag_version: If ``True``, create a Git tag for the current codebase version. push_videos: If ``False``, skip uploading the ``videos/`` directory. - private: If ``True``, create a private repository. + private: If ``True``, create a private repository. If ``None`` + (default), defer to the org default on the Hub (only affects orgs). allow_patterns: Glob pattern(s) restricting which files to upload. upload_large_folder: If ``True``, use ``upload_large_folder`` instead of ``upload_folder`` for very large datasets. From 19fe315971079e116b917ed4d482bfbf3c93bbbe Mon Sep 17 00:00:00 2001 From: Haoming Song Date: Wed, 3 Jun 2026 17:46:35 +0800 Subject: [PATCH 2/4] fix(train): enable relative action overrides for pretrained processors (#3711) * fix(train): enable relative action overrides for pretrained processors Keep pretrained processor pipelines when use_relative_actions is enabled and apply relative/absolute action processor settings through overrides. Rename the relative action processor registry key to relative_actions_processor. * fix(config): reject rename_map without pretrained checkpoint Fail fast when rename_map is set during fresh initialization, since fresh configs derive feature names from the current dataset and no rename is applied. --------- Co-authored-by: Pepijn <138571049+pkooij@users.noreply.github.com> --- src/lerobot/configs/train.py | 6 ++++ .../processor/relative_action_processor.py | 2 +- src/lerobot/scripts/lerobot_train.py | 29 ++++++++----------- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/lerobot/configs/train.py b/src/lerobot/configs/train.py index 55498d3ac..bac1a946b 100644 --- a/src/lerobot/configs/train.py +++ b/src/lerobot/configs/train.py @@ -177,6 +177,12 @@ class TrainPipelineConfig(HubMixin): ) active_cfg = self.trainable_config + if self.rename_map and active_cfg.pretrained_path is None: + raise ValueError( + "`rename_map` requires a pretrained policy checkpoint. " + "Fresh initialization derives feature names from the current dataset, so no rename is applied." + ) + if not self.job_name: if self.env is None: self.job_name = f"{active_cfg.type}" diff --git a/src/lerobot/processor/relative_action_processor.py b/src/lerobot/processor/relative_action_processor.py index e1e65acb1..5b1039291 100644 --- a/src/lerobot/processor/relative_action_processor.py +++ b/src/lerobot/processor/relative_action_processor.py @@ -81,7 +81,7 @@ def to_absolute_actions(actions: Tensor, state: Tensor, mask: Sequence[bool]) -> return actions -@ProcessorStepRegistry.register("delta_actions_processor") +@ProcessorStepRegistry.register("relative_actions_processor") @dataclass class RelativeActionsProcessorStep(ProcessorStep): """Converts absolute actions to relative actions (action -= state) for masked dimensions. diff --git a/src/lerobot/scripts/lerobot_train.py b/src/lerobot/scripts/lerobot_train.py index 463668eb2..4ddef3105 100644 --- a/src/lerobot/scripts/lerobot_train.py +++ b/src/lerobot/scripts/lerobot_train.py @@ -292,19 +292,8 @@ def train(cfg: TrainPipelineConfig, accelerator: "Accelerator | None" = None): active_cfg = cfg.trainable_config processor_pretrained_path = active_cfg.pretrained_path - if ( - getattr(active_cfg, "use_relative_actions", False) - and processor_pretrained_path is not None - and not cfg.resume - ): - logging.warning( - "use_relative_actions=true with pretrained processors can skip relative transforms if " - "the checkpoint processors do not define them. Building processors from current policy config." - ) - processor_pretrained_path = None processor_kwargs = {} - postprocessor_kwargs = {} if (processor_pretrained_path and not cfg.resume) or not processor_pretrained_path: processor_kwargs["dataset_stats"] = dataset.meta.stats @@ -312,24 +301,31 @@ def train(cfg: TrainPipelineConfig, accelerator: "Accelerator | None" = None): processor_kwargs["dataset_meta"] = dataset.meta if not cfg.is_reward_model_training and processor_pretrained_path is not None: - processor_kwargs["preprocessor_overrides"] = { + preprocessor_overrides = { "device_processor": {"device": device.type}, "normalizer_processor": { "stats": dataset.meta.stats, "features": {**policy.config.input_features, **policy.config.output_features}, "norm_map": policy.config.normalization_mapping, }, + "rename_observations_processor": {"rename_map": cfg.rename_map}, } - processor_kwargs["preprocessor_overrides"]["rename_observations_processor"] = { - "rename_map": cfg.rename_map - } - postprocessor_kwargs["postprocessor_overrides"] = { + postprocessor_overrides = { "unnormalizer_processor": { "stats": dataset.meta.stats, "features": policy.config.output_features, "norm_map": policy.config.normalization_mapping, }, } + if getattr(active_cfg, "use_relative_actions", False): + preprocessor_overrides["relative_actions_processor"] = { + "enabled": True, + "exclude_joints": getattr(active_cfg, "relative_exclude_joints", []), + "action_names": getattr(active_cfg, "action_feature_names", None), + } + postprocessor_overrides["absolute_actions_processor"] = {"enabled": True} + processor_kwargs["preprocessor_overrides"] = preprocessor_overrides + processor_kwargs["postprocessor_overrides"] = postprocessor_overrides if cfg.is_reward_model_training: preprocessor, postprocessor = make_reward_pre_post_processors( @@ -341,7 +337,6 @@ def train(cfg: TrainPipelineConfig, accelerator: "Accelerator | None" = None): policy_cfg=cfg.policy, pretrained_path=processor_pretrained_path, **processor_kwargs, - **postprocessor_kwargs, ) if is_main_process: From 741c2d0a3939ba54d6cf47f29a7fbbba3766a600 Mon Sep 17 00:00:00 2001 From: Nikodem Bartnik <39432165+NikodemBartnik@users.noreply.github.com> Date: Wed, 3 Jun 2026 14:22:05 +0200 Subject: [PATCH 3/4] Docs/add lelab (#3707) * first text draft (no images) * simplified docs * fix formatting * add youtube video * add a tip about compatibility * fix broken link --- docs/source/_toctree.yml | 2 ++ docs/source/lelab.mdx | 29 +++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 docs/source/lelab.mdx diff --git a/docs/source/_toctree.yml b/docs/source/_toctree.yml index a216548d8..ce36fad5d 100644 --- a/docs/source/_toctree.yml +++ b/docs/source/_toctree.yml @@ -9,6 +9,8 @@ - sections: - local: il_robots title: Imitation Learning for Robots + - local: lelab + title: LeLab - Lerobot GUI - local: bring_your_own_policies title: Adding a Policy - local: integrate_hardware diff --git a/docs/source/lelab.mdx b/docs/source/lelab.mdx new file mode 100644 index 000000000..a9f28e57b --- /dev/null +++ b/docs/source/lelab.mdx @@ -0,0 +1,29 @@ +# LeLab - LeRobot Guide + +LeLab is a graphical user interface built on top of the LeRobot library, designed to make robotics accessible without needing to memorize CLI commands. From a single app you can configure your robot, teleoperate it, collect datasets, train policies locally or on cloud GPUs via HF Jobs, and deploy trained models back onto your robot. It's the easiest way to go from an unboxed SO-101 to a working policy, and a great companion for anyone learning the LeRobot workflow. Source code and issues live on GitHub: [huggingface/leLab](https://github.com/huggingface/leLab). + +> [!TIP] +> For now LeLab is compatible only with SO-ARM101 + + + +### Installation + +Requires [`uv`](https://docs.astral.sh/uv/getting-started/installation/). Install and launch in one command: + +``` +uv tool install git+https://github.com/huggingface/leLab.git && lelab +``` + +After install, run `lelab` from your terminal anytime to start the app. + +### Features + +- **Add robots** — Select arm type (leader/follower), calibrate each joint from the middle position, and attach cameras. +- **Teleoperation** — Control the follower arm with the leader and see a live 3D visualization of the arms. +- **Dataset recording** — Define a task description, number of episodes, and episode/reset durations. Press spacebar to advance between episodes. 30+ episodes recommended. +- **Local training** — Train a policy directly on your own machine with a selected dataset, policy type, batch size, and step count. +- **Cloud training with HF Jobs** — Train on powerful GPUs via [HF Jobs](https://huggingface.co/docs/huggingface_hub/en/guides/jobs) with transparent pricing. Run `hf auth login` first. See the [Compute HW Guide](hardware_guide) for hardware/batch size tips. +- **Training visualization** — Watch progress live in the app, with checkpoints saved automatically. +- **Run trained policies** — Pick any model from your jobs list and run inference on your robot with one click. +- **Use community datasets** — Provide any Hugging Face dataset ID to train on datasets you didn't record yourself. From d1b1c5c8cff5e1f637495e1667a1d6c7c5258f3b Mon Sep 17 00:00:00 2001 From: Jaimin Date: Wed, 3 Jun 2026 08:48:19 -0400 Subject: [PATCH 4/4] docs: fix broken dataset script paths (datasets/v30 -> scripts) (#3695) The docs pointed at src/lerobot/datasets/v30/, which does not exist. Both scripts actually live in src/lerobot/scripts/: - convert_dataset_v21_to_v30.py - augment_dataset_quantile_stats.py Updated the four references (one python -m module path and three file-path invocations) to the correct location, matching each script's own usage docstring. --- docs/source/lerobot-dataset-v3.mdx | 2 +- docs/source/molmoact2.mdx | 2 +- docs/source/pi05.mdx | 2 +- docs/source/porting_datasets_v3.mdx | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/source/lerobot-dataset-v3.mdx b/docs/source/lerobot-dataset-v3.mdx index c23677d8c..21cb232d3 100644 --- a/docs/source/lerobot-dataset-v3.mdx +++ b/docs/source/lerobot-dataset-v3.mdx @@ -275,7 +275,7 @@ A converter aggregates per‑episode files into larger shards and writes episode pip install "https://github.com/huggingface/lerobot/archive/33cad37054c2b594ceba57463e8f11ee374fa93c.zip" # Convert an existing v2.1 dataset hosted on the Hub: -python -m lerobot.datasets.v30.convert_dataset_v21_to_v30 --repo-id= +python -m lerobot.scripts.convert_dataset_v21_to_v30 --repo-id= ``` **What it does** diff --git a/docs/source/molmoact2.mdx b/docs/source/molmoact2.mdx index ddd178acd..c6ae24e9e 100644 --- a/docs/source/molmoact2.mdx +++ b/docs/source/molmoact2.mdx @@ -238,7 +238,7 @@ your dataset has not been converted with quantile statistics, you can add them with: ```bash -python src/lerobot/datasets/v30/augment_dataset_quantile_stats.py \ +python src/lerobot/scripts/augment_dataset_quantile_stats.py \ --repo-id=your_dataset ``` diff --git a/docs/source/pi05.mdx b/docs/source/pi05.mdx index f99ad3286..127a2adc7 100644 --- a/docs/source/pi05.mdx +++ b/docs/source/pi05.mdx @@ -91,7 +91,7 @@ lerobot-train \ If your dataset is not converted with `quantiles`, you can convert it with the following command: ```bash -python src/lerobot/datasets/v30/augment_dataset_quantile_stats.py \ +python src/lerobot/scripts/augment_dataset_quantile_stats.py \ --repo-id=your_dataset \ ``` diff --git a/docs/source/porting_datasets_v3.mdx b/docs/source/porting_datasets_v3.mdx index 46793265e..b2c3c15a0 100644 --- a/docs/source/porting_datasets_v3.mdx +++ b/docs/source/porting_datasets_v3.mdx @@ -300,7 +300,7 @@ This replaces the old episode-per-file structure with efficient, optimally-sized If you have existing datasets in v2.1 format, use the migration tool: ```bash -python src/lerobot/datasets/v30/convert_dataset_v21_to_v30.py \ +python src/lerobot/scripts/convert_dataset_v21_to_v30.py \ --repo-id your_id/existing_dataset ```