Radar: FIX heading flop every 180deg -- YawPitchRoll not EulerAngles (user-reported)

The radar map derived its rotation from EulerAngles(Quaternion), whose decomposition
is AMBIGUOUS for a yawing mech: as yaw sweeps past +/-pi the quaternion double-cover
flips it onto the pitch=roll=pi branch, so euler.yaw REVERSES -- the whole radar
counter-rotates the wrong way past 180deg (user: 'flops every 180 degrees'). Switched
both radar sites (view-matrix build + blip delta rotation) to YawPitchRoll, which
applies yaw first and yields a clean continuous 360deg heading -- the SAME fix the
compass HeadingPointer already uses (btl4gaug.cpp:2185). A/B verified live (BT_RADAR_LOG,
spinning madcat): euler.yaw folds (-0.30 vs true -2.84 rad) while ypr.yaw tracks clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
arcattack
2026-07-14 08:09:16 -05:00
co-authored by Claude Fable 5
parent c4c51545fc
commit b533725ae4
+26 -6
View File
@@ -697,9 +697,16 @@ void
// Top-down: keep heading only. Extract the yaw, build a
// yaw-only quaternion, SET the rotation block from it.
//
EulerAngles euler;
euler = *currentAngularPointer; // FUN_0040954c
Scalar heading = euler.yaw * HeadingHalf; // * 0.5f
YawPitchRoll euler; // FIX: YawPitchRoll (yaw-first),
euler = *currentAngularPointer; // not EulerAngles -- the latter folds
Scalar heading = (Scalar)euler.yaw * HeadingHalf; // at +/-pi under yaw. * 0.5f half-angle
if (getenv("BT_RADAR_LOG")) {
EulerAngles oldE; oldE = *currentAngularPointer; // old buggy path, A/B
static int s_rv = 0;
if ((s_rv++ % 20) == 0)
DEBUG_STREAM << "[radar-view] euler.yaw=" << (Scalar)oldE.yaw
<< " ypr.yaw=" << (Scalar)euler.yaw << " (rad)\n" << std::flush;
}
SinCosPair sc;
sc = Radian(heading); // FUN_00408328
Quaternion yaw(0.0f, sc.sine, 0.0f, sc.cosine); // FUN_00409948
@@ -965,12 +972,25 @@ void
Scalar sinH = 0.0f, cosH = 1.0f;
if (currentAngularPointer != NULL)
{
EulerAngles e;
e = *currentAngularPointer; // Quaternion -> EulerAngles (operator=)
// FIX (user-reported: radar rotation flops every 180deg): the MUNGA
// EulerAngles(Quaternion) decomposition is AMBIGUOUS for a yawing mech --
// as yaw sweeps past +/-pi the quaternion double-cover flips it onto a
// pitch=roll=pi branch, so euler.yaw REVERSES (the radar spins back).
// YawPitchRoll applies yaw FIRST -> a clean continuous 360deg heading.
// Same fix the compass HeadingPointer already uses (btl4gaug.cpp:2185).
YawPitchRoll ypr;
ypr = *currentAngularPointer;
SinCosPair scH;
scH = Radian(e.yaw); // FUN_00408328
scH = Radian((Scalar)ypr.yaw);
sinH = scH.sine;
cosH = scH.cosine;
if (getenv("BT_RADAR_LOG")) {
EulerAngles e; e = *currentAngularPointer; // old (buggy) path, for A/B
static int s_rn = 0;
if ((s_rn++ % 20) == 0)
DEBUG_STREAM << "[radar] euler.yaw=" << (Scalar)e.yaw
<< " ypr.yaw=" << (Scalar)ypr.yaw << " (rad)\n" << std::flush;
}
}
Scalar rx = delta.x * cosH + delta.z * sinH;
Scalar rz = -delta.x * sinH + delta.z * cosH;