From 0584866f8509164c32d11ec3587cd9443f64899e Mon Sep 17 00:00:00 2001 From: CarolinePascal Date: Wed, 1 Jul 2026 20:09:09 +0200 Subject: [PATCH] fix(streaming dataset): extending support for depth units to streaming datasets --- src/lerobot/datasets/streaming_dataset.py | 25 +++++++++++++++++++++-- tests/datasets/test_depth.py | 8 ++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/lerobot/datasets/streaming_dataset.py b/src/lerobot/datasets/streaming_dataset.py index 7d63a618b..14d4a52a4 100644 --- a/src/lerobot/datasets/streaming_dataset.py +++ b/src/lerobot/datasets/streaming_dataset.py @@ -22,11 +22,11 @@ import numpy as np import torch from datasets import load_dataset -from lerobot.configs import DEFAULT_DEPTH_UNIT, DepthEncoderConfig +from lerobot.configs import DEFAULT_DEPTH_UNIT, DEPTH_METER_UNIT, DepthEncoderConfig from lerobot.utils.constants import HF_LEROBOT_HOME, LOOKAHEAD_BACKTRACKTABLE, LOOKBACK_BACKTRACKTABLE from .dataset_metadata import CODEBASE_VERSION, LeRobotDatasetMetadata -from .depth_utils import dequantize_depth +from .depth_utils import MM_PER_METRE, dequantize_depth from .feature_utils import get_delta_indices from .io_utils import item_to_torch from .utils import ( @@ -319,6 +319,13 @@ class StreamingLeRobotDataset(torch.utils.data.IterableDataset): for vid_key in self.meta.depth_keys } + # Input unit of each depth feature stored as raw images (dequantized separately from videos). + self._image_depth_units: dict[str, str | None] = { + key: (self.meta.features[key].get("info") or {}).get("depth_unit") + for key in self.meta.depth_keys + if key in self.meta.image_keys + } + self.delta_timestamps = None self.delta_indices = None @@ -349,6 +356,11 @@ class StreamingLeRobotDataset(torch.utils.data.IterableDataset): def fps(self): return self.meta.fps + @property + def depth_output_unit(self) -> str: + """Physical unit (``"m"`` or ``"mm"``) depth maps are returned in on read.""" + return self._depth_output_unit + @staticmethod def _iter_random_indices( rng: np.random.Generator, buffer_size: int, random_batch_size=100 @@ -531,6 +543,15 @@ class StreamingLeRobotDataset(torch.utils.data.IterableDataset): for update in updates: result.update(update) + # Convert raw-image depth features to the output unit (video depth is already converted). + for key, stored_unit in self._image_depth_units.items(): + if key in result and stored_unit is not None and stored_unit != self._depth_output_unit: + result[key] = ( + result[key] * MM_PER_METRE + if stored_unit == DEPTH_METER_UNIT + else result[key] / MM_PER_METRE + ) + result["task"] = self.meta.tasks.iloc[item["task_index"]].name yield result diff --git a/tests/datasets/test_depth.py b/tests/datasets/test_depth.py index d9c8d0774..5391cc558 100644 --- a/tests/datasets/test_depth.py +++ b/tests/datasets/test_depth.py @@ -326,3 +326,11 @@ class TestDepthUnitMetadata: if not use_videos: depth = read_dataset[0][DEPTH_KEY] assert torch.allclose(depth, torch.full_like(depth, expected)) + + from lerobot.datasets.streaming_dataset import StreamingLeRobotDataset + + stream_dataset = StreamingLeRobotDataset( + repo_id=DUMMY_REPO_ID, root=tmp_path / "ds", depth_output_unit=output_unit + ) + stream_depth = next(iter(stream_dataset))[DEPTH_KEY] + assert torch.allclose(stream_depth, torch.full_like(stream_depth, expected))