Body Stage 1 collapse root-caused + fixed: NaN in torso servo math (GetAngle = 2*acos(W) at W=1.0000001), not solver stacking
- BodyMath.RotationError: atan2-based shortest-arc error (no NaN, no GetAxis gain collapse inside 0.16 deg); used by PhysicsTorso orientation servo and PhysicsHands rotation lock - BodyMath.ResetIfNonFinite escape hatch on torso + hands - PhysicsHands.Drive extracted (static) so spikes run the real hand chase - CollapseSpike: deterministic repro (slow yaw drift across a parked chest, 7/40 NaN on old code) + solver-stacking scenarios (seated chest in table, two-hand-welded 50 kg anvil, real PropShop) — 49/49 clean after fix, x3; all other spikes PASS x3 - Failure brief RESOLUTION section; HANDOFF/AGENTS updated Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ce1e0e3b0c
commit
cb518999e5
9 files changed
+466
-47
No files matched your search
+12
-7
@@ -88,6 +88,8 @@ public partial class PhysicsHands : Node
|
||||
{
|
||||
if (body == null)
|
||||
return;
|
||||
if (BodyMath.ResetIfNonFinite(body, controller.GlobalTransform, "PhysicsHands"))
|
||||
return;
|
||||
int hand = _left == controller ? 0 : 1;
|
||||
Vector3 target = controller.GlobalPosition;
|
||||
|
||||
@@ -121,18 +123,21 @@ public partial class PhysicsHands : Node
|
||||
return;
|
||||
}
|
||||
}
|
||||
Vector3 desiredVelocity = (target - body.GlobalPosition) / delta;
|
||||
Drive(body, controller.GlobalTransform, delta);
|
||||
}
|
||||
|
||||
// The hand chase itself — public so headless spikes drive their stand-ins with the real code.
|
||||
public static void Drive(RigidBody3D body, Transform3D target, float delta)
|
||||
{
|
||||
Vector3 desiredVelocity = (target.Origin - body.GlobalPosition) / delta;
|
||||
Vector3 dv = desiredVelocity - body.LinearVelocity;
|
||||
Vector3 force = dv / delta * body.Mass;
|
||||
if (force.Length() > HandMaxForce)
|
||||
force = force.Normalized() * HandMaxForce;
|
||||
body.LinearVelocity += force / body.Mass * delta;
|
||||
|
||||
Basis deltaBasis = controller.GlobalTransform.Basis * body.GlobalTransform.Basis.Inverse();
|
||||
Quaternion q = deltaBasis.GetRotationQuaternion();
|
||||
Vector3 spin = q.GetAxis() * (q.GetAngle() / delta);
|
||||
if (spin.Length() > HandMaxSpin)
|
||||
spin = spin.Normalized() * HandMaxSpin;
|
||||
body.AngularVelocity = spin;
|
||||
Vector3 rotErr = BodyMath.RotationError(target.Basis.GetRotationQuaternion(),
|
||||
body.GlobalTransform.Basis.GetRotationQuaternion());
|
||||
body.AngularVelocity = (rotErr / delta).LimitLength(HandMaxSpin);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user