mirror of
https://github.com/huggingface/lerobot.git
synced 2026-05-24 21:19:53 +00:00
Update reachy2_cameras depth + CameraManager
This commit is contained in:
@@ -23,7 +23,7 @@ class Reachy2CameraConfig(CameraConfig):
|
|||||||
"""Configuration class for Reachy 2 camera devices.
|
"""Configuration class for Reachy 2 camera devices.
|
||||||
|
|
||||||
This class provides configuration options for Reachy 2 cameras,
|
This class provides configuration options for Reachy 2 cameras,
|
||||||
supporting both the teleop and torso cameras. It includes settings
|
supporting both the teleop and depth cameras. It includes settings
|
||||||
for resolution, frame rate, color mode, and the selection of the cameras.
|
for resolution, frame rate, color mode, and the selection of the cameras.
|
||||||
|
|
||||||
Example configurations:
|
Example configurations:
|
||||||
@@ -41,9 +41,9 @@ class Reachy2CameraConfig(CameraConfig):
|
|||||||
```
|
```
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
name: Name of the camera device. Can be "teleop" or "torso".
|
name: Name of the camera device. Can be "teleop" or "depth".
|
||||||
image_type: Type of image stream. For "teleop" camera, can be "left" or "right".
|
image_type: Type of image stream. For "teleop" camera, can be "left" or "right".
|
||||||
For "torso" camera, can be "rgb" or "depth". (depth is not supported yet)
|
For "depth" camera, can be "rgb" or "depth". (depth is not supported yet)
|
||||||
fps: Requested frames per second for the color stream.
|
fps: Requested frames per second for the color stream.
|
||||||
width: Requested frame width in pixels for the color stream.
|
width: Requested frame width in pixels for the color stream.
|
||||||
height: Requested frame height in pixels for the color stream.
|
height: Requested frame height in pixels for the color stream.
|
||||||
@@ -63,15 +63,15 @@ class Reachy2CameraConfig(CameraConfig):
|
|||||||
# use_depth: bool = False
|
# use_depth: bool = False
|
||||||
|
|
||||||
def __post_init__(self):
|
def __post_init__(self):
|
||||||
if self.name not in ["teleop", "torso"]:
|
if self.name not in ["teleop", "depth"]:
|
||||||
raise ValueError(f"`name` is expected to be 'teleop' or 'torso', but {self.name} is provided.")
|
raise ValueError(f"`name` is expected to be 'teleop' or 'depth', but {self.name} is provided.")
|
||||||
if (
|
if (
|
||||||
(self.name == "teleop" and self.image_type not in ["left", "right"])
|
(self.name == "teleop" and self.image_type not in ["left", "right"])
|
||||||
or (self.name == "torso")
|
or (self.name == "depth")
|
||||||
and self.image_type not in ["rgb", "depth"]
|
and self.image_type not in ["rgb", "depth"]
|
||||||
):
|
):
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"`image_type` is expected to be 'left' or 'right' for teleop camera, and 'rgb' or 'depth' for torso camera, but {self.image_type} is provided."
|
f"`image_type` is expected to be 'left' or 'right' for teleop camera, and 'rgb' or 'depth' for depth camera, but {self.image_type} is provided."
|
||||||
)
|
)
|
||||||
|
|
||||||
if self.color_mode not in ["rgb", "bgr"]:
|
if self.color_mode not in ["rgb", "bgr"]:
|
||||||
|
|||||||
@@ -68,6 +68,8 @@ class Reachy2Camera(Camera):
|
|||||||
self.fps = config.fps
|
self.fps = config.fps
|
||||||
self.color_mode = config.color_mode
|
self.color_mode = config.color_mode
|
||||||
|
|
||||||
|
self.cam_manager: CameraManager | None = None
|
||||||
|
|
||||||
self.thread: Thread | None = None
|
self.thread: Thread | None = None
|
||||||
self.stop_event: Event | None = None
|
self.stop_event: Event | None = None
|
||||||
self.frame_lock: Lock = Lock()
|
self.frame_lock: Lock = Lock()
|
||||||
@@ -80,11 +82,12 @@ class Reachy2Camera(Camera):
|
|||||||
@property
|
@property
|
||||||
def is_connected(self) -> bool:
|
def is_connected(self) -> bool:
|
||||||
"""Checks if the camera is currently connected and opened."""
|
"""Checks if the camera is currently connected and opened."""
|
||||||
return (
|
if self.config.name == "teleop":
|
||||||
(self.cam_manager.teleop is not None and self.cam_manager.depth is not None)
|
return self.cam_manager._grpc_connected and self.cam_manager.teleop if self.cam_manager else False
|
||||||
if self.cam_manager is not None
|
elif self.config.name == "depth":
|
||||||
else False
|
return self.cam_manager._grpc_connected and self.cam_manager.depth if self.cam_manager else False
|
||||||
)
|
else:
|
||||||
|
raise ValueError(f"Invalid camera name '{self.config.name}'. Expected 'teleop' or 'depth'.")
|
||||||
|
|
||||||
def connect(self, warmup: bool = True):
|
def connect(self, warmup: bool = True):
|
||||||
"""
|
"""
|
||||||
@@ -94,7 +97,6 @@ class Reachy2Camera(Camera):
|
|||||||
self.cam_manager.initialize_cameras()
|
self.cam_manager.initialize_cameras()
|
||||||
|
|
||||||
logger.info(f"{self} connected.")
|
logger.info(f"{self} connected.")
|
||||||
print(f"{self} connected.")
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def find_cameras(ip_address: str = "localhost", port: int = 50065) -> list[dict[str, Any]]:
|
def find_cameras(ip_address: str = "localhost", port: int = 50065) -> list[dict[str, Any]]:
|
||||||
@@ -152,22 +154,25 @@ class Reachy2Camera(Camera):
|
|||||||
|
|
||||||
frame = None
|
frame = None
|
||||||
|
|
||||||
if self.config.name == "teleop" and hasattr(self.cam_manager, "teleop"):
|
if self.cam_manager is None:
|
||||||
if self.config.image_type == "left":
|
raise DeviceNotConnectedError(f"{self} is not connected.")
|
||||||
frame = self.cam_manager.teleop.get_frame(CameraView.LEFT, size=(640, 480))[0]
|
else:
|
||||||
elif self.config.image_type == "right":
|
if self.config.name == "teleop" and hasattr(self.cam_manager, "teleop"):
|
||||||
frame = self.cam_manager.teleop.get_frame(CameraView.RIGHT, size=(640, 480))[0]
|
if self.config.image_type == "left":
|
||||||
elif self.config.name == "depth" and hasattr(self.cam_manager, "depth"):
|
frame = self.cam_manager.teleop.get_frame(CameraView.LEFT, size=(640, 480))[0]
|
||||||
if self.config.image_type == "depth":
|
elif self.config.image_type == "right":
|
||||||
frame = self.cam_manager.depth.get_depth_frame()[0]
|
frame = self.cam_manager.teleop.get_frame(CameraView.RIGHT, size=(640, 480))[0]
|
||||||
elif self.config.image_type == "rgb":
|
elif self.config.name == "depth" and hasattr(self.cam_manager, "depth"):
|
||||||
frame = self.cam_manager.depth.get_frame(size=(640, 480))[0]
|
if self.config.image_type == "depth":
|
||||||
|
frame = self.cam_manager.depth.get_depth_frame()[0]
|
||||||
|
elif self.config.image_type == "rgb":
|
||||||
|
frame = self.cam_manager.depth.get_frame(size=(640, 480))[0]
|
||||||
|
|
||||||
if frame is None:
|
if frame is None:
|
||||||
return np.empty((0, 0, 3), dtype=np.uint8)
|
return np.empty((0, 0, 3), dtype=np.uint8)
|
||||||
|
|
||||||
if self.config.color_mode == "rgb":
|
if self.config.color_mode == "rgb":
|
||||||
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
||||||
|
|
||||||
read_duration_ms = (time.perf_counter() - start_time) * 1e3
|
read_duration_ms = (time.perf_counter() - start_time) * 1e3
|
||||||
logger.debug(f"{self} read took: {read_duration_ms:.1f}ms")
|
logger.debug(f"{self} read took: {read_duration_ms:.1f}ms")
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
from lerobot.cameras.reachy2_camera import Reachy2Camera, Reachy2CameraConfig
|
|
||||||
|
|
||||||
camera_config = Reachy2CameraConfig(name="teleop", image_type="left")
|
|
||||||
camera = Reachy2Camera(camera_config)
|
|
||||||
|
|
||||||
camera.connect()
|
|
||||||
|
|
||||||
frame = camera.read()
|
|
||||||
print(frame)
|
|
||||||
|
|
||||||
frame_async = camera.async_read()
|
|
||||||
print(frame_async)
|
|
||||||
Reference in New Issue
Block a user