MP: tighten peer re-anchor -- error-proportional absorption (residual snap, task #50)

Chasing the ~2.9u residual snap: instrumented BT_MIRDIV and isolated it to the
PEER side (master send-mirror error is accurate, mean 0.39u < 0.55u threshold;
peer drifted 3-11u from received authority).  Root: the master models the peer
with the BODY channel but the peer moves with the LEG channel -- slightly
different travel/frame -- so the master deadband does not fire exactly when the
peer drifts, and the fixed ~1/3s offset decay bled slower than accel/decel drift
accumulated.  A hard ground-snap (authentic FUN_004ab1c8:14985) popped instead
(records not perfectly dense on the one-box relay).

FIX: error-proportional absorption -- bleed the offset to updateOrigin at a rate
that scales with the error (k 0.15..0.6/frame): small steady offset absorbed
gently (no foot-pop), large speed-change drift caught in a few frames.

Measured (through-zero sweep): peer drift 11u->2.1u, maxStep 2.9u->1.77u, ratio
1.043->1.036.  Remaining <=1.8u snaps are the leg-vs-body channel-shape mismatch;
fully closing needs a leg-channel send-mirror (second instance) -- deferred.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
arcattack
2026-07-14 21:41:30 -05:00
co-authored by Claude Opus 4.8
parent 47771ba256
commit 38fed81d8a
+53 -11
View File
@@ -2145,23 +2145,26 @@ void
// (reverse clips return negative travel; master dir==1.0 in SM mode).
if (!s_drPos)
{
// POSE-SYNC OFFSET DECAY (authentic FUN_004ab1c8 motionEventVector
// mechanism): a record does NOT snap the body -- the correction offset
// is absorbed over ~1/3s while the clip's root motion keeps driving, so
// the feet never pop and the position converges to authority.
static Vector3D s_rmErr[2]; // per-instance would be a member; one replicant per node in practice
Vector3D &rmErr = s_rmErr[0];
if (poseSyncLatch)
// POSE-SYNC ERROR-PROPORTIONAL ABSORPTION: track the error to the
// received authority (updateOrigin) and bleed it into localOrigin at a
// rate that scales with the error, so a small steady offset is absorbed
// gently (no foot-pop) while a large speed-change drift is caught fast.
// The residual snap came from two sources: (a) a fixed slow ~1/3s decay
// let drift reach 3-11u during accel/decel; (b) a hard ground snap popped
// because records are not perfectly dense on this relay. Error-scaled
// absorption is the stable middle: k grows from ~0.15/frame at small
// error toward ~0.6 at large error. (Records re-measure the error every
// frame they arrive, so this converges to authority within a few frames.)
{
Vector3D rmErr;
rmErr.Subtract(updateOrigin.linearPosition, localOrigin.linearPosition);
poseSyncLatch = 0;
}
{
Scalar k = dt * 3.0f; if (k > 1.0f) k = 1.0f; // ~1/3s absorption
const float eMag = (float)rmErr.Length();
float k = 0.15f + eMag * 0.15f; // error-proportional catch-up
if (k > 0.6f) k = 0.6f;
localOrigin.linearPosition.x += rmErr.x * k;
localOrigin.linearPosition.y += rmErr.y * k;
localOrigin.linearPosition.z += rmErr.z * k;
rmErr.x -= rmErr.x * k; rmErr.y -= rmErr.y * k; rmErr.z -= rmErr.z * k;
}
if (replLegAdv != 0.0f)
{
@@ -2177,6 +2180,24 @@ void
localToWorld = localOrigin; // refresh with the coupled position
}
// PEER-DRIFT probe (BT_MIRDIV, 1s max): how far the peer's coupled
// position wanders from the last-received authority (updateOrigin)
// before a record re-anchors it -- the other end of the snap.
if (getenv("BT_MIRDIV"))
{
static float s_pdAcc = 0.0f, s_pdMax = 0.0f;
Vector3D d; d.Subtract(localOrigin.linearPosition, updateOrigin.linearPosition);
const float dl = (float)d.Length();
if (dl > s_pdMax) s_pdMax = dl;
s_pdAcc += dt;
if (s_pdAcc >= 1.0f)
{
DEBUG_STREAM << "[peerdrift] maxDriftFromAuthority=" << s_pdMax
<< " replLegAdv=" << replLegAdv << "\n" << std::flush;
s_pdAcc = 0.0f; s_pdMax = 0.0f;
}
}
// GAIT-EVENNESS probe (BT_GAITEV, 1s stats): the metric of the VISIBLE
// speed-change glitch -- per-frame leg-clip advance regularity + leg-state
// transition (flap) rate on the peer. Position dead-reckons smoothly
@@ -3772,6 +3793,27 @@ void
error.Subtract(
projectedOrigin.linearPosition,
localOrigin.linearPosition);
// MIRROR-DIVERGENCE probe (BT_MIRDIV, 1s max): how far the master's
// send-mirror (projectedOrigin, body-channel gait) drifts from the true
// localOrigin (leg-channel gait) BEFORE a send fires. This is the source
// of the peer's residual snap -- quantifies the leg-vs-body channel shape
// mismatch. posDb (~0.55u) is the send threshold; anything the mirror
// over/under-shoots beyond it is the channel divergence.
if (getenv("BT_MIRDIV"))
{
static float s_mdAcc = 0.0f, s_mdMax = 0.0f, s_mdAdvB = 0.0f, s_mdAdvL = 0.0f;
const float e = (float)error.Length();
if (e > s_mdMax) s_mdMax = e;
s_mdAdvB += (float)(mirrorBodyAdv < 0 ? -mirrorBodyAdv : mirrorBodyAdv);
s_mdAcc += dt;
if (s_mdAcc >= 1.0f)
{
DEBUG_STREAM << "[mirdiv] maxErr=" << s_mdMax
<< " bodyTravel/s=" << s_mdAdvB
<< " bodyTgtSpd=" << bodyTargetSpeed << "\n" << std::flush;
s_mdAcc = 0.0f; s_mdMax = 0.0f; s_mdAdvB = 0.0f; s_mdAdvL = 0.0f;
}
}
Quaternion angular_deviation;
angular_deviation.Subtract(
projectedOrigin.angularPosition,