From 7d7ca5d2e9236cec89cb862e84c2ba6200e34596 Mon Sep 17 00:00:00 2001 From: Cam Mazzacane Date: Thu, 15 Oct 2026 22:00:36 -0400 Subject: [PATCH] Check all six IMU axes for saturation The saturated flag compared only gyro x and accelerometer z with their unclipped values. Clipping on the other four axes cleared the flag, so the measurement-saturated warning never fired for them. The flag now checks every axis of both vectors. Clipping itself is unchanged. Only the browser IMU device reads the flag. The headless state-sensor backend emits no sensor warning events at all (measurement-saturated, sample-dropped, gnss-outage), so headless runs still never warn. The browser devices and the headless backend wrap the same measurement functions in separate code. The differences between the two paths should be investigated in a later change. Co-Authored-By: Claude Opus 5.5 --- app/autonomy/LocalizationMeasurements.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/app/autonomy/LocalizationMeasurements.js b/app/autonomy/LocalizationMeasurements.js index d5156419..e3c93814 100644 --- a/app/autonomy/LocalizationMeasurements.js +++ b/app/autonomy/LocalizationMeasurements.js @@ -238,16 +238,18 @@ export function buildImuMeasurement(snapshot, sensorConfig, rng, state = {}) { nextDrift.acceleration, ); - const measuredAngular = saturateVector({ + const rawAngular = { x: angularVelocity.x + angularNoise.x, y: angularVelocity.y + angularNoise.y, z: angularVelocity.z + angularNoise.z, - }, sensorConfig.calibration.angularVelocitySaturation); - const measuredAcceleration = saturateVector({ + }; + const rawAcceleration = { x: specificForce.x + accelerationNoise.x, y: specificForce.y + accelerationNoise.y, z: specificForce.z + accelerationNoise.z, - }, sensorConfig.calibration.linearAccelerationSaturation); + }; + const measuredAngular = saturateVector(rawAngular, sensorConfig.calibration.angularVelocitySaturation); + const measuredAcceleration = saturateVector(rawAcceleration, sensorConfig.calibration.linearAccelerationSaturation); return { measurement: { @@ -261,8 +263,8 @@ export function buildImuMeasurement(snapshot, sensorConfig, rng, state = {}) { turnOnBias, drift: nextDrift, lastCaptureTimeNs: snapshot.captureTimeNs, - saturated: measuredAngular.x !== angularVelocity.x + angularNoise.x - || measuredAcceleration.z !== specificForce.z + accelerationNoise.z, + saturated: ["x", "y", "z"].some((axis) => measuredAngular[axis] !== rawAngular[axis] + || measuredAcceleration[axis] !== rawAcceleration[axis]), }, }; }