forked from tangger/lerobot
refactor(cameras): add warm-up, fix defaul args, remove width and height from find_cameras utils
This commit is contained in:
@@ -33,7 +33,7 @@ class Cv2Rotation(Enum):
|
||||
ROTATE_270 = -90
|
||||
|
||||
|
||||
@dataclass
|
||||
@dataclass(kw_only=True)
|
||||
class CameraConfig(draccus.ChoiceRegistry, abc.ABC):
|
||||
fps: int | None = None
|
||||
width: int | None = None
|
||||
|
||||
@@ -336,6 +336,10 @@ class RealSenseCamera(Camera):
|
||||
|
||||
logger.debug(f"Validating stream configuration for {self.serial_number}...")
|
||||
self._validate_capture_settings()
|
||||
|
||||
logger.debug(f"Reading a warm-up frame for {self.serial_number}...")
|
||||
self.read() # NOTE(Steven): For now we just read one frame, we could also loop for X secs
|
||||
|
||||
logger.info(f"Camera {self.serial_number} connected and configured successfully.")
|
||||
|
||||
def _validate_fps(self, stream) -> None:
|
||||
@@ -396,7 +400,7 @@ class RealSenseCamera(Camera):
|
||||
|
||||
def read(
|
||||
self, color_mode: ColorMode | None = None, timeout_ms: int = 5000
|
||||
) -> Union[np.ndarray, Tuple[np.ndarray, np.ndarray]]:
|
||||
) -> np.ndarray | Tuple[np.ndarray, np.ndarray]:
|
||||
"""
|
||||
Reads a single frame (color and optionally depth) synchronously from the camera.
|
||||
|
||||
|
||||
@@ -205,6 +205,10 @@ class OpenCVCamera(Camera):
|
||||
|
||||
logger.debug(f"Successfully opened camera {self.index_or_path}. Applying configuration...")
|
||||
self._configure_capture_settings()
|
||||
|
||||
logger.debug(f"Reading a warm-up frame for {self.serial_number}...")
|
||||
self.read() # NOTE(Steven): For now we just read one frame, we could also loop for X secs\
|
||||
|
||||
logger.debug(f"Camera {self.index_or_path} connected and configured successfully.")
|
||||
|
||||
def _validate_fps(self) -> None:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from dataclasses import dataclass, field
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
|
||||
from ..configs import CameraConfig, ColorMode, Cv2Rotation
|
||||
@@ -18,9 +18,7 @@ class OpenCVCameraConfig(CameraConfig):
|
||||
```
|
||||
"""
|
||||
|
||||
index_or_path: int | Path = field(
|
||||
default=...,
|
||||
)
|
||||
index_or_path: int | Path
|
||||
color_mode: ColorMode = ColorMode.RGB
|
||||
channels: int = 3 # NOTE(Steven): Why is this a config?
|
||||
rotation: Cv2Rotation = Cv2Rotation.NO_ROTATION
|
||||
|
||||
@@ -157,28 +157,21 @@ def create_camera_instance(cam_meta: Dict[str, Any]) -> Optional[Dict[str, Any]]
|
||||
"""Create and connect to a camera instance based on metadata."""
|
||||
cam_type = cam_meta.get("type")
|
||||
cam_id = cam_meta.get("id")
|
||||
default_profile = cam_meta.get("default_stream_profile")
|
||||
width = default_profile.get("width")
|
||||
height = default_profile.get("height")
|
||||
instance = None
|
||||
|
||||
logger.info(f"Preparing {cam_type} ID {cam_id} with profile: Width={width}, Height={height}")
|
||||
logger.info(f"Preparing {cam_type} ID {cam_id} with default profile")
|
||||
|
||||
try:
|
||||
if cam_type == "OpenCV":
|
||||
cv_config = OpenCVCameraConfig(
|
||||
index_or_path=cam_id,
|
||||
color_mode=ColorMode.RGB,
|
||||
width=width,
|
||||
height=height,
|
||||
)
|
||||
instance = OpenCVCamera(cv_config)
|
||||
elif cam_type == "RealSense":
|
||||
rs_config = RealSenseCameraConfig(
|
||||
serial_number=str(cam_id),
|
||||
color_mode=ColorMode.RGB,
|
||||
width=width,
|
||||
height=height,
|
||||
)
|
||||
instance = RealSenseCamera(rs_config)
|
||||
else:
|
||||
@@ -270,6 +263,7 @@ def save_images_from_all_cameras(
|
||||
logger.info(f"Starting image capture for {record_time_s} seconds from {len(cameras_to_use)} cameras.")
|
||||
start_time = time.perf_counter()
|
||||
|
||||
# NOTE(Steven): This seems like an overkill to me
|
||||
with concurrent.futures.ThreadPoolExecutor(max_workers=len(cameras_to_use) * 2) as executor:
|
||||
try:
|
||||
while time.perf_counter() - start_time < record_time_s:
|
||||
|
||||
Reference in New Issue
Block a user