pub fn segment_settled(segment: &[CaptureImage], tol: f32) -> boolExpand description
Whether segment’s last frame is close enough to its asymptote for
frames_to_settle to mean anything — the question that function cannot
answer about itself (Plan 0038 Phase 7).
Why this is needed at all. frames_to_settle normalizes against the
segment’s own last frame. When that frame is still travelling, the measured
total is short and every threshold is crossed early — and the returned frame
count is a plausible-looking number rather than an obvious failure, because
normalizing against the last frame guarantees the threshold is reached
inside the segment. So frames_to_settle(seg, f) < seg.len() is a tautology,
not a check, and a caller has no way to tell settled at frame k from still
moving at frame k. Plan 0038 Phase 3 read a truncated window as a shape
difference between two orderings on exactly this basis; see ADR-0040’s
Outcome.
The rule. A settling response’s change per unit time decays
geometrically, so the tail beyond the last frame can be extrapolated without
knowing the time constant. Sample three points at equal spacing h — the
first frame A, the midpoint B, the last C — and for an exponential
approach |C - B| / |B - A| is exp(-h/tau), whatever tau is. The travel
still to come after C is then |C - B| * rho / (1 - rho). Settled means
that estimate is under tol of the change measured so far.
The three points are spread across the whole segment on purpose, not taken
from the end. Captures are 8-bit, and a response slow enough to outrun its
window moves by less than one code value per frame near the end — the
residual is large but each individual step is sub-quantum, so consecutive
frames decode as identical and any estimator reading adjacent deltas concludes
“flat, therefore settled” precisely in the case worth catching. Half a segment
of travel is always far above the quantum. (Measured while building this: at
tau = 2 s over a 2 s window the per-frame step is ~0.003 linear against a
~0.004 quantum at that brightness, and the adjacent-frame version of this
function reported the response settled with 37 % of its travel left.)
Assumes a monotone approach, which every one-pole in this engine is — a response that overshoots is outside what this can judge.
This deliberately does not change frames_to_settle or
step_response, whose numbers shot --report publishes for the whole
shipped library. Use it as the gate before trusting one of those numbers.