Sample the stall, not the calm before it

The raw step lengths came back immaculate - 1.02918, 1.03069, 1.03186,
monotonic to a tenth of a percent - in the very window that counted
sixteen stalls. Both readings are correct. The twelve printed steps were
the FIRST twelve of the window and the sixteen stalls were among the other
two hundred and thirty nine, so the trace sampled a calm quarter second
and said nothing whatever about the tick.

That also disposes of the alternation theory it was built to test: where
the pod moves steadily the steps are steady, and no high-low beat exists
to find.

Keep the last sixteen steps rolling instead, and freeze a copy the instant
a stall is seen, along with the ratio that triggered it and the dead
reckoner blend fraction at that moment. What prints is then the run-up to
an actual tick with the tick last in the list - the shape at the event
rather than the shape near it.

The stationary-pod windows remain ratio noise and stay discounted: steps
of a few tenths of a millimetre make every ratio meaningless, which is why
the capture requires a full sixteen-step history behind it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-08-11 10:38:42 -05:00
co-authored by Claude Opus 5
parent 3c49bc4fd1
commit da7c35cac1
+58 -19
View File
@@ -727,8 +727,13 @@ void
static Scalar max_percent = 0.0f;
static Scalar worst_error = 0.0f;
static Scalar last_distance = 0.0f;
static Scalar samples[12];
static int sample_count = 0;
static Scalar recent[16];
static Scalar frozen[16];
static int recent_next = 0;
static int recent_count = 0;
static Logical captured = False;
static Scalar captured_ratio = 0.0f;
static Scalar captured_percent = 0.0f;
static int seq_stalls = 0;
static int seq_spikes = 0;
@@ -754,26 +759,45 @@ void
//
if (distance < 50.0f)
{
//
// Keep the last sixteen steps rolling, and freeze a
// copy the moment a stall is seen.
//
// The first version of this printed the first twelve
// steps of each window and they came back immaculate
// - 1.029, 1.031, 1.032, monotonic to a tenth of a
// percent - while the same window counted sixteen
// stalls among the other two hundred and thirty
// nine. Sampling a calm quarter second says nothing
// about a tick that happens elsewhere. The sample
// has to be triggered BY the event.
//
recent[recent_next] = distance;
recent_next = (recent_next + 1) % 16;
if (recent_count < 16) { recent_count++; }
if (last_distance > 0.001f)
{
Scalar sequential = distance / last_distance;
if (sequential < 0.4f) { ++seq_stalls; }
if (sequential < 0.4f)
{
++seq_stalls;
if (!captured && recent_count == 16)
{
captured = True;
captured_ratio = sequential;
captured_percent = gLastPercent;
for (int c = 0; c < 16; c++)
{
frozen[c] = recent[(recent_next + c) % 16];
}
}
}
else if (sequential > 2.5f) { ++seq_spikes; }
}
last_distance = distance;
//
// And keep a few consecutive steps verbatim, so the
// shape can be READ rather than inferred from
// counters. Twelve steps is a quarter second at
// 50Hz - long enough to show a beat, short enough
// to fit one line.
//
if (sample_count < 12)
{
samples[sample_count++] = distance;
}
}
if (distance > 50.0f)
@@ -810,10 +834,25 @@ void
DEBUG_STREAM << "CamLog: replicant sequence - "
<< seq_stalls << " stall(s), " << seq_spikes
<< " spike(s) against the PREVIOUS step; steps:";
for (int s = 0; s < sample_count; s++)
<< " spike(s) against the PREVIOUS step";
if (captured)
{
DEBUG_STREAM << " " << samples[s];
//
// The fifteen steps leading into a stall and the
// stall itself, last in the list.
//
DEBUG_STREAM << "; at a stall (ratio "
<< captured_ratio << ", percent "
<< captured_percent << "):";
for (int s = 0; s < 16; s++)
{
DEBUG_STREAM << " " << frozen[s];
}
}
else
{
DEBUG_STREAM << "; no stall caught this window";
}
DEBUG_STREAM << "\n" << std::flush;
@@ -839,7 +878,7 @@ void
min_percent = 1.0f;
max_percent = 0.0f;
worst_error = 0.0f;
sample_count = 0;
captured = False;
seq_stalls = 0;
seq_spikes = 0;
}