Source code for go2.modules.video.frame_result

import numpy as np
from enum import Enum, auto
from collections.abc import Iterator
from typing import Dict, List, Optional
from dataclasses import dataclass


[docs] class FrameStatus(Enum): """Describes the state of a :class:`FrameResult` object.""" OK = auto() #: Frame data is present and usable PENDING = auto() #: Source initialised but no frame was currently available in a frame buffer
[docs] @dataclass class FrameResult: """Holds one captured moment from a single camera source.""" status: FrameStatus = FrameStatus.PENDING color: Optional[np.ndarray] = None #: BGR color image (H, W, 3). Always present for color/RGB cameras. depth: Optional[np.ndarray] = None #: Depth image (H, W) in uint16. Only present for depth cameras.
[docs] @classmethod def color_only(cls, color: np.ndarray) -> "FrameResult": """ Source is RGB-only; depth will never be present. Notes ----- Static factory method for internal use only. Should not be called by the user. """ return cls(status=FrameStatus.OK, color=color)
[docs] @classmethod def depth_only(cls, depth: np.ndarray) -> "FrameResult": """ Source is depth-only; color will never be present. Notes ----- Static factory method for internal use only. Should not be called by the user. """ return cls(status=FrameStatus.OK, depth=depth)
[docs] @classmethod def color_and_depth(cls, color: np.ndarray, depth: np.ndarray) -> "FrameResult": """ Source provides both channels (e.g. RealSense aligned frames). Notes ----- Static factory method for internal use only. Should not be called by the user. """ return cls(status=FrameStatus.OK, color=color, depth=depth)
[docs] @classmethod def pending(cls) -> "FrameResult": """ Source is initialised but the capture buffer hasn't filled yet. Notes ----- Static factory method for internal use only. Should not be called by the user. """ return cls(status=FrameStatus.PENDING)
[docs] def is_fully_valid(self) -> bool: """True only when status is OK and all channels are present.""" return self.status is FrameStatus.OK and (self.color is not None and self.depth is not None)
[docs] def has_color(self) -> bool: """True if a valid rgb frame is present.""" return self.color is not None
[docs] def has_depth(self) -> bool: """True if a valid depth frame is present.""" return self.depth is not None
[docs] @dataclass class MultiFrameResult: """Holds frame results from a group of named cameras.""" frames: Dict[str, FrameResult] #: Maps camera name to its latest FrameResult, or an empty FrameResult if that camera had no frame ready this cycle. def __getitem__(self, key: str) -> FrameResult: """ Direct access by camera name. Raises ------ KeyError If camera of 'key' name is not in group. """ return self.frames[key] def __iter__(self) -> Iterator[str]: return iter(self.frames)
[docs] def valid_frames(self) -> dict[str, FrameResult]: """Only slots whose FrameResult.is_valid is True.""" return {name: fr for name, fr in self.frames.items() if fr.is_fully_valid}
[docs] def is_fully_valid(self) -> bool: """True only when every slot has all valid frames""" return all(fr.is_fully_valid for fr in self.frames.values())
[docs] def pending_slots(self) -> list[str]: """Slots that are initialised but haven't produced a frame yet.""" return [ name for name, fr in self.frames.items() if fr.status is FrameStatus.PENDING ]