Source code for ouster.sdk.bag.bag_frame_set_source
from typing import Iterator, List, Optional, Union
import numpy as np
import copy
from ouster.sdk.core import LidarFrame, FrameSet
from ouster.sdk.core import SensorInfo, FrameBatcher
from ouster.sdk.util import resolve_field_types # type: ignore
from .bag_packet_source import BagPacketSource
from ouster.sdk._bindings.client import FrameSetSource
[docs]
class BagFrameSetSource(FrameSetSource):
"""Implements FrameSetSource protocol for pcap files with multiple sensors."""
_source: BagPacketSource
def __init__(
self,
file_path: Union[str, List[str]],
*,
extrinsics_file: Optional[str] = None,
raw_headers: bool = False,
raw_fields: bool = False,
soft_id_check: bool = False,
meta: Optional[List[str]] = None,
field_names: Optional[List[str]] = None,
extrinsics: List[np.ndarray] = [],
**kwargs
) -> None:
"""
Args:
file_path: OSF filename as frames source
raw_headers: if True, include raw headers in decoded LidarFrames
raw_fields: if True, include raw fields in decoded LidarFrames
soft_id_check: if True, don't skip packets on init_id/serial_num mismatch
meta: optional list of metadata files to load, if not provided metadata
is loaded from the bag instead
field_names: list of fields to decode into a LidarFrame, if not provided
decodes all default fields
"""
FrameSetSource.__init__(self)
# initialize the attribute so close works correctly if we fail out
self._source = None # type: ignore
try:
self._source = BagPacketSource(file_path, soft_id_check=soft_id_check,
meta=meta, extrinsics_file=extrinsics_file,
extrinsics=extrinsics)
except Exception:
self._source = None # type: ignore
raise
# generate the field types per sensor with flags/raw_fields if specified
self._field_types = resolve_field_types(self._source.sensor_info,
raw_headers=raw_headers,
raw_fields=raw_fields,
field_names=field_names)
# copy sensor info for decoding so it cant get messed with
self._orig_sensor_info = [copy.copy(si) for si in self._source.sensor_info]
@property
def is_live(self) -> bool:
return False
@property
def sensor_info(self) -> List[SensorInfo]:
return self._source.sensor_info
@property
def id_error_count(self) -> int:
return self._source.id_error_count # type: ignore
@property
def size_error_count(self) -> int:
return self._source.size_error_count # type: ignore
def __length_hint__(self):
return self._source.__length_hint__()
def __iter__(self) -> Iterator[FrameSet]:
batchers = []
frames: List[Optional[LidarFrame]] = []
for m in self._orig_sensor_info:
batchers.append(FrameBatcher(m))
frames.append(None)
for idx, packet in self._source:
frame = frames[idx]
if not frame:
frame = LidarFrame(self._orig_sensor_info[idx], self._field_types[idx])
frames[idx] = frame
if batchers[idx].batch(packet, frame):
frame.sensor_info = self._source.sensor_info[idx]
yield FrameSet([frame])
frames[idx] = None
# yield any remaining frames
# todo maybe do this in time order
for idx, frame in enumerate(frames):
if frame is not None:
# dont output frames that got no packets
if batchers[idx].batched_packets() == 0:
frames[idx] = None
continue
frame.sensor_info = self._source.sensor_info[idx]
yield FrameSet([frame])
frames[idx] = None
[docs]
def close(self):
return
def __len__(self) -> int:
raise TypeError("len is not supported on non-indexed source")