The replicant says how hard each update moves it
A tick a few times a second survived render interpolation, and it would: interpolation smooths WITHIN a fixed step, and this is a discontinuity in the stepped values themselves. Between updates a replicant is dead-reckoned from updateOrigin over (lastPerformance - lastUpdate); when the next update lands the basis is replaced and the position jumps by however far the prediction had drifted. A few updates a second is a tick a few times a second. So Entity::ReadUpdateRecord now measures the correction before applying it: how many arrived in the last five seconds, and the mean and worst distance between where we had the entity and where the update says it was. Replicants only, behind RP412CAMLOG, on a clock so a busy race cannot bury the log. If that reads a few per second at tens of centimetres, the tick is named and the fix is to damp the correction in rather than apply it instantly - which is a real piece of work and worth sizing on evidence. If the corrections are tiny, the tick is something else and this rules it out. Also worth recording: RP412GAUGEDIAG is blind on a camera station. It only reports when a full display sweep completes, and the missing-MFD bail resets that counter every cycle, so the gauge theory could not be tested that way. The camera's own symptom description did the work instead. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -435,6 +435,61 @@ void
|
||||
//-----------------------
|
||||
//
|
||||
UpdateRecord *update = (UpdateRecord*)record;
|
||||
|
||||
//
|
||||
// RP412CAMLOG: how hard does an arriving update MOVE this
|
||||
// entity, and how often?
|
||||
//
|
||||
// Between updates a replicant is dead-reckoned from
|
||||
// updateOrigin over (lastPerformance - lastUpdate). When the
|
||||
// next one lands the basis is replaced, so the drawn position
|
||||
// jumps by however far the prediction had drifted. Render
|
||||
// interpolation cannot hide that: it smooths within a step,
|
||||
// and this is a discontinuity in the stepped values
|
||||
// themselves. If the interval is a few per second and the
|
||||
// correction is tens of centimetres, that is a tick a few
|
||||
// times a second - which is the symptom being chased.
|
||||
//
|
||||
// Reported per entity, on a five second clock, so a busy race
|
||||
// does not bury the log.
|
||||
//
|
||||
if (RPCameraLog() && GetInstance() == ReplicantInstance)
|
||||
{
|
||||
static Scalar next_say = 0.0f;
|
||||
static int corrections = 0;
|
||||
static Scalar worst = 0.0f;
|
||||
static Scalar total = 0.0f;
|
||||
|
||||
Vector3D drift;
|
||||
drift.Subtract(
|
||||
update->localOrigin.linearPosition,
|
||||
localOrigin.linearPosition
|
||||
);
|
||||
Scalar distance = drift.Length();
|
||||
++corrections;
|
||||
total += distance;
|
||||
if (distance > worst)
|
||||
{
|
||||
worst = distance;
|
||||
}
|
||||
|
||||
if ((Scalar) Now() >= next_say)
|
||||
{
|
||||
if (next_say > 0.0f && corrections > 0)
|
||||
{
|
||||
DEBUG_STREAM << "CamLog: replicant corrections - "
|
||||
<< corrections << " in 5s ("
|
||||
<< (corrections / 5) << "/s), mean "
|
||||
<< (total / corrections) << "m, worst "
|
||||
<< worst << "m\n" << std::flush;
|
||||
}
|
||||
next_say = ((Scalar) Now()) + 5.0f;
|
||||
corrections = 0;
|
||||
worst = 0.0f;
|
||||
total = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
updateOrigin = update->localOrigin;
|
||||
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user