From 9a674e92418f148e3c07191496f6f7b7cecf316f Mon Sep 17 00:00:00 2001 From: Cyd Date: Tue, 11 Aug 2026 07:53:44 -0500 Subject: [PATCH] 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) --- MUNGA/CAMSHIP.cpp | 64 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/MUNGA/CAMSHIP.cpp b/MUNGA/CAMSHIP.cpp index 567cf0e..1c78814 100644 --- a/MUNGA/CAMSHIP.cpp +++ b/MUNGA/CAMSHIP.cpp @@ -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; } }