diff --git a/src/backend/services/camera.py b/src/backend/services/camera.py index 06a9d26..6cd08e7 100644 --- a/src/backend/services/camera.py +++ b/src/backend/services/camera.py @@ -151,6 +151,8 @@ class RealSenseD435: self._raw: Optional[FrameAcquisition[RawFrameset]] = None self._aligned: Optional[FrameAcquisition[CameraFrame]] = None self._last_aligned_raw_seq = 0 + # The frame get_rgb/get_depth/cached_frame share for frame_cache_ms (see _cached_or_capture()). + self._cached: Optional[CameraFrame] = None self._color_available: bool = True self._color_format = rs.format.bgr8 self._usb_type: str = "unknown" @@ -364,6 +366,7 @@ class RealSenseD435: for thread in threads: thread.join(STOP_JOIN_S) self.device_index = None + self._cached = None logger.info("RealSense camera closed") def _start_acquisition(self) -> None: @@ -554,13 +557,19 @@ class RealSenseD435: return CameraFrame(rgb=rgb, depth=depth_mm, timestamp=time.time()) def _cached_or_capture(self) -> Optional[CameraFrame]: - """The latest ALIGNED frame if younger than frame_cache_ms, else the next one.""" - aligned = self._aligned - if aligned is not None: - _, last = aligned.latest() - if last is not None and (time.time() - last.timestamp) * 1000.0 < self._frame_cache_ms: - return last - return self.capture() + """The frame the cached readers share if younger than frame_cache_ms, else the next aligned one. + + Only these readers renew it: a capture() in between (e.g. /api/capture + from another client) does not move it, so /api/rgb then /api/depth + within frame_cache_ms return color and depth of ONE frame. + """ + cached = self._cached + if cached is not None and (time.time() - cached.timestamp) * 1000.0 < self._frame_cache_ms: + return cached + frame = self.capture() + if frame is not None: + self._cached = frame + return frame def cached_frame(self) -> Optional[CameraFrame]: """Like get_rgb()/get_depth(), but the whole frame (so its encodings can be shared)."""