Chassis Lateral Load
Algorithm imu-1.0.0+mount-1.0.0 · source engine/src/dtta/engine/imu/{conventions,filters,mount,body,gyro}.py,
engine/src/dtta/engine/pipeline/imu.py.
What an accelerometer measures
An accelerometer measures specific force : its own acceleration minus gravity. At rest it
reads along the up direction ( m/s²); in free fall it reads zero. GoPro's
GRAV stream is the up unit vector in camera coordinates (verified on stationary data: RMS error
0.016–0.036 g after a fixed axis permutation). Raw accelerometer magnitude on a dirt car is dominated by
vibration (99th percentile 46–59 m/s², occasional ±8 g sensor clipping) and is never shown as a G number.
Frames and rotation convention
| frame | axes |
|---|---|
| C — camera | = up at rest; complete a right-handed frame (lens direction not assumed) |
| V — vehicle (ISO 8855) | forward, left, up; yaw positive turning left |
| E — earth | east, north, up |
| P — path | along the horizontal velocity, left of travel, up |
maps vector components from the camera frame to the vehicle frame; its rows are the vehicle axes expressed in camera coordinates. Quaternions use the Hamilton convention. Closed-form cases S1–S5 (stationary level, parked on a slope, steady banked turn, straight-line acceleration with pitch, free fall) are unit tests with tolerance 1e-9.
The channel
- : camera-frame specific force after (1) replacing samples at the ±8 g rail by an
imu_hampel_window(11)-sample rolling median (imu_replace_clipped), (2) a zero-phase Butterworth low-pass, order 4 in second-order sections, cutoffimu_cutoff_hz= 5 Hz, per contiguous run, and (3) decimation toimu_decimate_hz= 50 Hz. The statistical Hampel filter is disabled (imu_hampel_nsigma= None): Phase 8 showed it replaced 1–9 % of racing samples and injected up to 0.12 g RMS of low-band error. - =
accel_sign: +1 on every fixture (GoPro reports , not ; the handedness test would flip it and warn otherwise). - Positive = load toward the left of the car.
In a steady turn with horizontal centripetal acceleration (= Cornering G) and lean (bank + body roll, positive leaning into a left turn):
Banking reduces felt lateral load. Chassis Load ≠ Cornering G on a banked track is physics, not an error, and the difference is reported as a lean diagnostic:
(undefined below 8 m/s; low-passed at lean_lowpass_hz when used elsewhere). On the Hamilton County
fixture the chassis leans out by ~7° relative to its parked attitude in the corners, and Chassis Load
reads 0.08–0.14 g more than Cornering G — both instruments agree, so it is reported, not corrected.
Mount calibration
Automatic, per session:
- = mean up vector over stationary periods (speed <
stationary_speed_max_ms, ≥stationary_min_seconds= 30 s; else the low-passed over the session with confidence 0.6). When stationary runs disagree by more thanstationary_up_spread_max_deg(3°) the pre-race run is used and a note is recorded. - Lateral axis first (ovals have almost no straight-line braking windows): the horizontal specific force
is fitted by least squares onto the GPS path accelerations on racing samples;
is the lateral direction, .
corr_lat(0.90–0.96 on the fixtures) is the primary quality,corr_long(0.53–0.77) a diagnostic. - GPS lag: the GPS-derived channels are shifted by
gps_lag_s(cross-correlation of the low-passed with , ±2.5 s) before any comparison. - Handedness: in left turns (
handedness_min_lat_ms2) the lateral sign agreement must be ≥handedness_agreement_min(95 %), the net rotation over the racing samples must be positive with the GPS sign and exceed half a turn, and the yaw sign must agree in ≥ 60 % of corner samples. - Confidence = min(stationary 1.0/0.6, correlation 1.0/0.7/0.4 at
calib_corr_good0.8 /calib_corr_ok0.6, handedness 1.0/0.3/0.7); methodautoat ≥ 0.8, elseauto_low_confidence.
Manual override (engineer): lens facing forward/rearward/left/right, upside-down, roll, pitch → a
deterministic with method = manual, confidence 0.75, full provenance.
Priority (never silent): 1 automatic ≥ 0.8 → 2 automatic 0.5–0.8 (shown with a warning) → 3 manual → 4 hidden. Vehicle-frame channels (Chassis Load, body-yaw lateral, lean) are shown only at priority ≤ 3; Cornering G needs no IMU and is always available. The same rule gates the chassis columns of the segment table.
Mount drift: per lap, the angle between the gyro-propagated up vector (complementary filter,
complementary_tau_s = 15 s) and the calibrated is reported; laps above mount_drift_max_deg
(10°) are flagged mount_moved and their vehicle-frame values are marked unreliable. This caught a camera
whose mount rotated 38° during a heat.
Sustained value (per segment)
Same definition as Cornering G: maximum 1 s sliding mean of (sustained_window_s).
Limitations
- Requires a rigid mount. A flexing pole mount (I-35 "facing out" HERO9) gives 0.21 g RMS disagreement
with the driver camera and is classified
auto_low_confidence(0.3) → hidden. - Only bank + roll relative to the parked attitude is observable; parking on a slope shifts by the slope (the I-35 camera showed 4.9° between two stationary runs for that reason).
- The longitudinal axis carries from pitch and braking-in-corner content: it is an engineer diagnostic, never the driver's longitudinal number.
Verified
Phase 8 (docs/proofs/phase-08/REPORT.md): stationary and $|f| = 1.00 \pm
0.02,g_0$; handedness pass on the three rigid cameras; R3 closed (GoPro GRAV tracks true vertical
mid-corner to 1–3°); two same-car cameras agree on the gyro lateral to 0.08–0.10 g RMS. Tests:
engine/tests/unit/test_imu_conventions.py, synthetic banked turn at 0/8/15° lean (Chassis Load within
0.02 g, lean within 0.5°), vibration + 5 g spike, mounted rearward/left/right/upside-down recovered within 2°.