The camera measures its own smoothness

The last instrument was mis-specified: it compared an arriving update
against our current position, but those are at different times, so most of
the 0.40 m it reported was latency times speed rather than prediction
error. It could not have shown a visual jump even if one existed. The
follow trace agreed - per-step motion stayed tight at 1.36 to 1.68 m and
tracked speed, with no outliers riding on top.

It did settle one thing: corrections arrive 43 times a second, near the
50 Hz step rate, so whatever ticks a few times a second is not one per
correction.

So measure the symptom instead of a theory about its cause. A visible tick
IS a step that moves much further, or much less, than the steps around it,
and that is now counted directly: spikes above 2.5x a short running mean,
stalls below 0.4x, judged against the mean rather than an absolute distance
because a pod at 75 m/s moves 1.5 m per step and one against a wall moves
nothing. Respawns are counted and excluded - they teleport hundreds of
metres and are meant to be discontinuities.

Stated in advance, so the result cannot be read to taste: spikes at a few
per second confirms the tick is in entity motion and gives its rate; spikes
and stalls near zero refutes it, and points at frame delivery or the
newly-active map raster instead.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-08-11 07:53:44 -05:00
co-authored by Claude Opus 5
parent 5c7e218c98
commit 9a674e9241
+64
View File
@@ -349,6 +349,30 @@ void
static int moved = 0;
static Scalar biggest = 0.0f;
//
// A visible tick IS a step that moves much further, or much less,
// than the steps around it. Measuring that directly beats measuring
// anything about where the number came from: it does not care
// whether the cause is the network, the catch-up rule, or something
// nobody has thought of yet.
//
// Judged against a short running mean rather than an absolute
// distance, because a pod at 75 m/s moves 1.5 m per step and one
// sitting against a wall moves nothing - a fixed threshold would
// call every acceleration a spike.
//
// What confirms: spikes running at a few per second. That is the
// reported tick, and its rate is in the count.
// What refutes: spikes and stalls near zero. Then entity motion is
// smooth and the tick is not in the simulation at all, which points
// at frame delivery or the map raster instead.
//
static Scalar mean_step = 0.0f;
static int spikes = 0;
static int stalls = 0;
static int respawns = 0;
static Scalar worst_ratio = 0.0f;
++steps;
if (have_last)
{
@@ -363,6 +387,38 @@ void
{
biggest = distance;
}
//
// A respawn teleports hundreds of metres and is MEANT to be a
// discontinuity. Counted, excluded, and the mean restarted so
// one does not brand the following steps as stalls.
//
if (distance > 50.0f)
{
++respawns;
mean_step = 0.0f;
}
else if (mean_step > 0.01f)
{
Scalar ratio = distance / mean_step;
if (ratio > 2.5f)
{
++spikes;
if (ratio > worst_ratio)
{
worst_ratio = ratio;
}
}
else if (ratio < 0.4f)
{
++stalls;
}
mean_step = mean_step * 0.9f + distance * 0.1f;
}
else
{
mean_step = distance;
}
}
last_target = target;
have_last = True;
@@ -374,11 +430,19 @@ void
DEBUG_STREAM << "CamLog: follow - " << steps << " steps, "
<< moved << " moved, biggest jump " << biggest
<< "m, " << gCameraCuts << " cut(s)\n" << std::flush;
DEBUG_STREAM << "CamLog: smoothness - " << spikes
<< " spike(s), " << stalls << " stall(s), "
<< respawns << " respawn(s), worst " << worst_ratio
<< "x the running mean of " << mean_step << "m\n" << std::flush;
}
next_say = ((Scalar) Now()) + 5.0f;
steps = 0;
moved = 0;
biggest = 0.0f;
spikes = 0;
stalls = 0;
respawns = 0;
worst_ratio = 0.0f;
gCameraCuts = 0;
}
}