diff --git a/MUNGA/MOVER.cpp b/MUNGA/MOVER.cpp index 64d3d8e..e54cbba 100644 --- a/MUNGA/MOVER.cpp +++ b/MUNGA/MOVER.cpp @@ -1148,12 +1148,20 @@ void // nextUpdate = Now(); Scalar diff = nextUpdate - lastUpdate; + Scalar anchorInterval = (Scalar) 0; if (diff < 10.0f) { if (UseMedianPrediction()) { Scalar predicted = PredictUpdateInterval(diff); + // + // Anchor the projection to the SENDER's timeline, below, + // once Entity::ReadUpdateRecord has moved lastUpdate to + // the sampling moment RP412NETCLOCK worked out. + // + anchorInterval = predicted; + // // Score the previous prediction against the gap that // actually just elapsed - a true one-step-ahead error, @@ -1173,8 +1181,6 @@ void if (diff > widestGap) { widestGap = diff; } if (diff > kLongGapThreshold) { longGapCount++; } if (diff < kQueuedGapThreshold) { queuedGapCount++; } - - nextUpdate += predicted; } else { @@ -1299,6 +1305,35 @@ void // Entity::ReadUpdateRecord(record); + // + // Put the projection deadline on the SENDER's timeline. + // + // The dead reckoner projects to updateOrigin + velocity * + // (nextUpdate - lastUpdate), so that difference is a DISTANCE + // once multiplied by speed - and a pod at 52 m/s turns every + // millisecond in it into 52mm of target. + // + // lastUpdate is the sampling moment RP412NETCLOCK computed, on + // the sender's clock. Setting nextUpdate from Now() measured the + // gap between two different timelines, so it came out as the + // interval PLUS however late this particular packet happened to + // be. Fifteen milliseconds of ordinary jitter became three + // quarters of a metre of target error, which is enough to + // collapse a one metre step to a third - and only on the packets + // that ran late, which is exactly the intermittent tick that was + // reported. + // + // Anchored to lastUpdate the difference is the predicted + // interval exactly, so the target depends on what the sender + // said and how fast it is going, and not at all on the route the + // packet took to reach us. + // + if (anchorInterval > (Scalar) 0) + { + nextUpdate = lastUpdate; + nextUpdate += anchorInterval; + } + // //----------------------- // Update the motion data