Skip to content
Merged
Show file tree
Hide file tree
Changes from 73 commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
8a6412b
refactor(cameras): init abc class + config
Apr 21, 2025
0b5b438
refactor(cameras): opencv camera init
Apr 21, 2025
3297c7e
refactor(cameras): realsense camera init
Apr 21, 2025
720a637
chore(dependencies): add pyrealsense2 for macos + cleanup init camera…
Apr 21, 2025
6348f0f
refactor(cameras): improvements opencv cam v0.1
imstevenpmwork Apr 28, 2025
35c4b01
test(cameras): add minimal opencv test
imstevenpmwork Apr 30, 2025
15b5d28
refactor(cameras): improvements realsense cam v0.1
imstevenpmwork May 2, 2025
b089c6d
test(cameras): add minimal realsense test
imstevenpmwork May 5, 2025
2af8edc
chore(cameras): delete unused files
imstevenpmwork May 6, 2025
3416036
chore(cameras): set timeout to 0 in tests
imstevenpmwork May 6, 2025
7f34e1a
refactor(cameras): improvements utils functionalities v0.1
imstevenpmwork May 7, 2025
ddd8fd3
refactor(cameras): improvements utils functionalities v0.2
imstevenpmwork May 9, 2025
904bc61
refactor(cameras): fps, width and height are optional at camera level…
imstevenpmwork May 12, 2025
dbce247
refactor(cameras): homogeneous depth processing in realsense camera
imstevenpmwork May 12, 2025
4675b3c
refactor(cameras): add warm-up, fix defaul args, remove width and hei…
imstevenpmwork May 12, 2025
81c49ce
[skip ci] refactor(cameras): add warmup read + images different size …
imstevenpmwork May 13, 2025
57c2181
refactor(cameras): add read_depth() for realsense + new compressed bag
imstevenpmwork May 13, 2025
2d86812
refactor(cameras): width, fps and height is mandatory to have a value…
imstevenpmwork May 13, 2025
27bb7c4
chore(cameras): remove compressed files + filename better managed in …
imstevenpmwork May 14, 2025
d6d8f29
fix(cameras): correct imports for camera config in scripts
imstevenpmwork May 14, 2025
dae5f7c
chore(tests): explicit cameras artefacts in gitattributes
imstevenpmwork May 14, 2025
cca6473
fix(tests): kill thread when camera async_read tests fail
imstevenpmwork May 14, 2025
859a369
chore(docs): adress notes + add docs in camera code
imstevenpmwork May 14, 2025
6797e1d
fix(cameras): correct validate_width_height logic
imstevenpmwork May 15, 2025
5daf552
fix(cameras): realsense depth post_process channel check
imstevenpmwork May 15, 2025
f27f5f8
Apply suggestions from code review 1
imstevenpmwork May 20, 2025
295b96c
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 20, 2025
1f2cfd3
Apply suggestions from code review camera_realsense.py
imstevenpmwork May 20, 2025
05d8825
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 20, 2025
3890c38
Apply suggestions from code review camera_opencv
imstevenpmwork May 20, 2025
3a08edd
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 20, 2025
41179d0
chore(cameras): address review comments + make test pass again
imstevenpmwork May 20, 2025
85b0dd0
chore(tests): delete fakecam images
imstevenpmwork May 20, 2025
9812f2d
chore(cameras): rename intel -> realsense
imstevenpmwork May 20, 2025
525cd68
chore(cameras): fix imports renamed folder + add camera configs in ut…
imstevenpmwork May 20, 2025
ab7565a
chore(cameras): refactor utility function dictionary fetching style
imstevenpmwork May 20, 2025
efd2849
chore(tests): add ids to parametrize
imstevenpmwork May 20, 2025
99ea24d
chore(cameras): move connect under is_connected
imstevenpmwork May 20, 2025
39f908e
chore(cameras): move if check out of _validate functions
imstevenpmwork May 20, 2025
b3dafcf
docs(cameras): update depth related example
imstevenpmwork May 20, 2025
39a93a7
docs(cameras): update arg in class doc
imstevenpmwork May 20, 2025
18b56e1
refactor(cameras): realsense config arg serial_number_or_name
imstevenpmwork May 20, 2025
7a4b9f0
chore(cameras): rename prerotated_ to capture_ var names
imstevenpmwork May 20, 2025
eb2d967
docs(cameras): add explanation of warmup arg in connect
imstevenpmwork May 20, 2025
a653210
chore(cameras): move _stop_thread under _start_thread methods
imstevenpmwork May 20, 2025
91a5faf
feat(cameras): add check for fps, height and width in realsenseconfig…
imstevenpmwork May 20, 2025
33b8559
refactor(cameras): move find_cameras to the base class
imstevenpmwork May 20, 2025
a36536d
Apply suggestions from code review 3
imstevenpmwork May 20, 2025
1c90cd1
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 20, 2025
76f661f
chore(robots): fix pre-commit
imstevenpmwork May 20, 2025
7f7c431
docs(cameras): update find_cameras instructions
imstevenpmwork May 21, 2025
f8c7e59
test(cameras): use fixture for realsense patching + depth read test
imstevenpmwork May 21, 2025
73bb970
chore(cameras): remove 14 logs
imstevenpmwork May 21, 2025
95a9518
Merge branch 'user/aliberts/2025_02_25_refactor_robots' into refactor…
imstevenpmwork May 21, 2025
625bb9c
chore(cameras): try import rs protect
imstevenpmwork May 21, 2025
95f3e53
chore(test): try import rs protect
imstevenpmwork May 21, 2025
47d5008
chore(cameras): address unresolved conversations
imstevenpmwork May 21, 2025
4d9825b
fix(ci): change default opencv backend
imstevenpmwork May 21, 2025
0c411a6
[skip ci] doc(tests): add comment related to test duration
imstevenpmwork May 21, 2025
65ad065
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 21, 2025
5857952
fix(cameras): remove rs from signatures
imstevenpmwork May 21, 2025
22e98a6
Apply suggestions from code review (logging statements)
imstevenpmwork May 22, 2025
bf09993
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] May 22, 2025
96d9c40
chore(cameras): address PR comments 2
imstevenpmwork May 22, 2025
2429b80
chore(cameras): remove wrmup arg none check realsense
imstevenpmwork May 22, 2025
e556c97
chore(cameras): dir path find_cameras
imstevenpmwork May 22, 2025
0a997d9
Apply suggestions from code review tests+utils
imstevenpmwork May 22, 2025
efe9553
[skip-ci] fix(cameras): find camera utils arg name
imstevenpmwork May 22, 2025
c050a07
Merge branch 'user/aliberts/2025_02_25_refactor_robots' into refactor…
imstevenpmwork May 22, 2025
0fcaf21
chore(cameras): remove unused utils function
imstevenpmwork May 23, 2025
2bf433a
chore(cameras): remove rmtree in find_cameras
imstevenpmwork May 23, 2025
fb3b45b
chore(cameras): remove width and height settings validation
imstevenpmwork May 23, 2025
1c6b349
refactor(cameras): move from Queue to Lock for read_async()
imstevenpmwork May 23, 2025
96ee1c6
Apply suggestions from code review round 3
imstevenpmwork May 23, 2025
c009136
chore(cameras): remove try/except in read_async()
imstevenpmwork May 23, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@
# 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.

*.memmap filter=lfs diff=lfs merge=lfs -text
*.stl filter=lfs diff=lfs merge=lfs -text
*.safetensors filter=lfs diff=lfs merge=lfs -text
*.mp4 filter=lfs diff=lfs merge=lfs -text
*.arrow filter=lfs diff=lfs merge=lfs -text
*.json !text !filter !merge !diff
tests/artifacts/cameras/*.png filter=lfs diff=lfs merge=lfs -text
*.bag filter=lfs diff=lfs merge=lfs -text
3 changes: 2 additions & 1 deletion lerobot/calibrate.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@

import draccus

from lerobot.common.cameras import intel, opencv # noqa: F401
from lerobot.common.cameras.opencv.configuration_opencv import OpenCVCameraConfig # noqa: F401
from lerobot.common.cameras.realsense.configuration_realsense import RealSenseCameraConfig # noqa: F401
from lerobot.common.robots import ( # noqa: F401
Robot,
RobotConfig,
Expand Down
16 changes: 15 additions & 1 deletion lerobot/common/cameras/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
# 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.

from .camera import Camera
from .configs import CameraConfig
from .configs import CameraConfig, ColorMode, Cv2Rotation
from .utils import make_cameras_from_configs
109 changes: 102 additions & 7 deletions lerobot/common/cameras/camera.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,120 @@
#!/usr/bin/env python

# 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.

import abc
from typing import Any, Dict, List

import numpy as np

from .configs import CameraConfig, ColorMode


class Camera(abc.ABC):
"""Base class for camera implementations.

Defines a standard interface for camera operations across different backends.
Subclasses must implement all abstract methods.

Manages basic camera properties (FPS, resolution) and core operations:
- Connection/disconnection
- Frame capture (sync/async)

Attributes:
fps (int | None): Configured frames per second
width (int | None): Frame width in pixels
height (int | None): Frame height in pixels

Example:
class MyCamera(Camera):
def __init__(self, config): ...
@property
def is_connected(self) -> bool: ...
def connect(self, warmup=True): ...
# Plus other required methods
"""

def __init__(self, config: CameraConfig):
"""Initialize the camera with the given configuration.

Args:
config: Camera configuration containing FPS and resolution.
"""
self.fps: int | None = config.fps
self.width: int | None = config.width
self.height: int | None = config.height

@property
@abc.abstractmethod
def connect(self):
def is_connected(self) -> bool:
"""Check if the camera is currently connected.

Returns:
bool: True if the camera is connected and ready to capture frames,
False otherwise.
"""
pass

@staticmethod
@abc.abstractmethod
def read(self, temporary_color: str | None = None) -> np.ndarray:
def find_cameras() -> List[Dict[str, Any]]:
"""Detects available cameras connected to the system.
Returns:
List[Dict[str, Any]]: A list of dictionaries,
where each dictionary contains information about a detected camera.
"""
pass

@abc.abstractmethod
def async_read(self) -> np.ndarray:
def connect(self, warmup: bool = True) -> None:
"""Establish connection to the camera.

Args:
warmup: If True (default), captures a warmup frame before returning. Useful
for cameras that require time to adjust capture settings.
If False, skips the warmup frame.
"""
pass

@abc.abstractmethod
def read(self, color_mode: ColorMode | None = None) -> np.ndarray:
"""Capture and return a single frame from the camera.

Args:
color_mode: Desired color mode for the output frame. If None,
uses the camera's default color mode.

Returns:
np.ndarray: Captured frame as a numpy array.
"""
pass

@abc.abstractmethod
def disconnect(self):
def async_read(self, timeout_ms: float = ...) -> np.ndarray:
"""Asynchronously capture and return a single frame from the camera.

Args:
timeout_ms: Maximum time to wait for a frame in milliseconds.
Defaults to implementation-specific timeout.

Returns:
np.ndarray: Captured frame as a numpy array.
"""
pass

def __del__(self):
if getattr(self, "is_connected", False):
self.disconnect()
@abc.abstractmethod
def disconnect(self) -> None:
"""Disconnect from the camera and release resources."""
pass
35 changes: 34 additions & 1 deletion lerobot/common/cameras/configs.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,44 @@
#!/usr/bin/env python

# 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.

import abc
from dataclasses import dataclass
from enum import Enum

import draccus


@dataclass
class ColorMode(str, Enum):
RGB = "rgb"
BGR = "bgr"


class Cv2Rotation(int, Enum):
NO_ROTATION = 0
ROTATE_90 = 90
ROTATE_180 = 180
ROTATE_270 = -90


@dataclass(kw_only=True)
class CameraConfig(draccus.ChoiceRegistry, abc.ABC):
fps: int | None = None
width: int | None = None
height: int | None = None

@property
def type(self) -> str:
return self.get_choice_name(self.__class__)
4 changes: 0 additions & 4 deletions lerobot/common/cameras/intel/__init__.py

This file was deleted.

Loading
Loading