mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-11-14 18:58:49 -05:00
46 lines
1.8 KiB
Python
46 lines
1.8 KiB
Python
"""Shared causal 10 Hz sampling for recorded and live video."""
|
|
import math
|
|
|
|
|
|
def decision_frames(frames):
|
|
"""Yield decision time, latest past image, and its actual capture timestamp.
|
|
|
|
Sampling every third/fourth decoded frame leaves holes at rates such as 25
|
|
FPS. A fixed grid covers each 100ms command interval exactly once. A frame
|
|
after the decision can release the pending tick, but is never its input.
|
|
"""
|
|
previous = None
|
|
previous_time = None
|
|
tick = None
|
|
for frame in frames:
|
|
if frame.pts is None:
|
|
raise ValueError('Video frame has no timestamp')
|
|
stamp = float(frame.pts * frame.time_base) * 1000
|
|
if not math.isfinite(stamp) or (previous_time is not None and stamp < previous_time):
|
|
raise ValueError('Invalid/nonmonotonic video timestamps')
|
|
if tick is None:
|
|
tick = stamp
|
|
while tick < stamp - .01:
|
|
# Do not synthesize observations over missing/stalled video. History
|
|
# selection will reject a temporal gap until fresh history exists.
|
|
if previous is not None and tick - previous_time <= 200:
|
|
yield tick, previous, previous_time
|
|
elif stamp - tick > 200:
|
|
tick += max(1, math.floor((stamp - tick) / 100)) * 100
|
|
continue
|
|
tick += 100
|
|
if abs(stamp - tick) <= .01:
|
|
yield tick, frame, stamp
|
|
tick += 100
|
|
previous, previous_time = frame, stamp
|
|
|
|
|
|
def history_frames(history, stamp):
|
|
selected = []
|
|
for offset in (900, 600, 300, 0):
|
|
candidates = [row for row in history if row[0] <= stamp - offset + .01]
|
|
if not candidates or stamp - offset - candidates[-1][0] > 200:
|
|
return []
|
|
selected.append(candidates[-1])
|
|
return selected
|