From 65d3a7c5890f5a83020c50e8d68f440078e6334e Mon Sep 17 00:00:00 2001 From: Simon Alibert Date: Mon, 21 Apr 2025 16:11:37 +0200 Subject: [PATCH] refactor(cameras): init abc class + config --- lerobot/common/cameras/camera.py | 12 ++++++------ lerobot/common/cameras/configs.py | 6 ++++++ .../common/cameras/opencv/configuration_opencv.py | 15 ++++++++------- .../robots/stretch3/configuration_stretch3.py | 2 +- 4 files changed, 21 insertions(+), 14 deletions(-) diff --git a/lerobot/common/cameras/camera.py b/lerobot/common/cameras/camera.py index 5d9ac509..a5198b99 100644 --- a/lerobot/common/cameras/camera.py +++ b/lerobot/common/cameras/camera.py @@ -4,8 +4,12 @@ import numpy as np class Camera(abc.ABC): + @abc.abstractproperty + def is_connected(self) -> bool: + pass + @abc.abstractmethod - def connect(self): + def connect(self) -> None: pass @abc.abstractmethod @@ -17,9 +21,5 @@ class Camera(abc.ABC): pass @abc.abstractmethod - def disconnect(self): + def disconnect(self) -> None: pass - - def __del__(self): - if getattr(self, "is_connected", False): - self.disconnect() diff --git a/lerobot/common/cameras/configs.py b/lerobot/common/cameras/configs.py index 4c796a03..15fe4334 100644 --- a/lerobot/common/cameras/configs.py +++ b/lerobot/common/cameras/configs.py @@ -1,9 +1,15 @@ import abc from dataclasses import dataclass +from enum import Enum import draccus +class ColorMode(Enum): + RGB = 0 + BGR = 1 + + @dataclass class CameraConfig(draccus.ChoiceRegistry, abc.ABC): @property diff --git a/lerobot/common/cameras/opencv/configuration_opencv.py b/lerobot/common/cameras/opencv/configuration_opencv.py index 983199bf..d2855250 100644 --- a/lerobot/common/cameras/opencv/configuration_opencv.py +++ b/lerobot/common/cameras/opencv/configuration_opencv.py @@ -1,6 +1,7 @@ from dataclasses import dataclass +from pathlib import Path -from ..configs import CameraConfig +from ..configs import CameraConfig, ColorMode @CameraConfig.register_subclass("opencv") @@ -17,22 +18,22 @@ class OpenCVCameraConfig(CameraConfig): ``` """ - camera_index: int + index_or_path: int | Path fps: int | None = None width: int | None = None height: int | None = None - color_mode: str = "rgb" - channels: int | None = None + color_mode: ColorMode = ColorMode.RGB + channels: int = 3 rotation: int | None = None - mock: bool = False def __post_init__(self): - if self.color_mode not in ["rgb", "bgr"]: + if self.color_mode not in [ColorMode.RGB, ColorMode.BGR]: raise ValueError( f"`color_mode` is expected to be 'rgb' or 'bgr', but {self.color_mode} is provided." ) - self.channels = 3 + if self.channels != 3: + raise NotImplementedError(f"Unsupported number of channels: {self.channels}") if self.rotation not in [-90, None, 90, 180]: raise ValueError(f"`rotation` must be in [-90, None, 90, 180] (got {self.rotation})") diff --git a/lerobot/common/robots/stretch3/configuration_stretch3.py b/lerobot/common/robots/stretch3/configuration_stretch3.py index 47ddb54b..e80993a8 100644 --- a/lerobot/common/robots/stretch3/configuration_stretch3.py +++ b/lerobot/common/robots/stretch3/configuration_stretch3.py @@ -19,7 +19,7 @@ class Stretch3RobotConfig(RobotConfig): cameras: dict[str, CameraConfig] = field( default_factory=lambda: { "navigation": OpenCVCameraConfig( - camera_index="/dev/hello-nav-head-camera", + index_or_path="/dev/hello-nav-head-camera", fps=10, width=1280, height=720,