Speed-source arbitration and GPS quality reporting #19

Closed
opened 2026-08-31 17:14:41 +02:00 by robert · 1 comment
robert commented 2026-08-31 17:14:41 +02:00 (Migrated from git.butzei.de)

Goal

Pick the best available speed source and tell the watch which one is live.

Acceptance criteria

  • Wheel sensor preferred when it has reported within the last 3 s, GPS otherwise
  • SPEED_SOURCE sent to the watch: 0 none, 1 GPS, 2 wheel sensor
  • GPS_QUALITY derived from fix accuracy and age, 0-3
  • Switching sources does not produce a visible jump or a distance discontinuity
  • With no source at all the watch shows a clear no-signal state rather than a stale number

Files

  • companion/.../location/SpeedSourceArbiter.kt
## Goal Pick the best available speed source and tell the watch which one is live. ## Acceptance criteria - [ ] Wheel sensor preferred when it has reported within the last 3 s, GPS otherwise - [ ] `SPEED_SOURCE` sent to the watch: 0 none, 1 GPS, 2 wheel sensor - [ ] `GPS_QUALITY` derived from fix accuracy and age, 0-3 - [ ] Switching sources does not produce a visible jump or a distance discontinuity - [ ] With no source at all the watch shows a clear no-signal state rather than a stale number ## Files - `companion/.../location/SpeedSourceArbiter.kt`
Owner

Closed by PR #102 (merged): resolved the 3s-vs-5s wheel-live-window discrepancy properly \u2014 traced back to D4's original 3s wording, which #69 quietly diverged from with an unreasoned 5s default; corrected to 3s, amended D35 transparently rather than silently. SPEED_SOURCE/GPS_QUALITY wire keys already existed from #7 with matching numbering, no reconciliation needed there. New deriveGpsQuality() (accuracy tier vs. age tier, worse-of) and a SpeedReport.Live/NoSignal type so a dead source reports honestly instead of freezing the last value (D44 principle).\n\nReal bug caught and fixed: onGpsFix's accuracy gate ran before the wheel-live check, so a poor-accuracy fix arriving while the wheel was live got rejected outright instead of refreshing the position baseline \u2014 a sustained bad patch (bridge, urban canyon) with a wheel sensor also live left the baseline stale, and the next good fix after the wheel quieted computed distance against it, producing an unbounded spike. Fixed by checking wheel-liveness first; proven with a regression test (~50m expected vs. the ~95m the bug produced).\n\nVerified for real: :companion:core:test (19+6 new tests), :companion:pebble:test (6 new), :companion:assembleDebug \u2014 all green.

Closed by PR #102 (merged): resolved the 3s-vs-5s wheel-live-window discrepancy properly \u2014 traced back to D4's original 3s wording, which #69 quietly diverged from with an unreasoned 5s default; corrected to 3s, amended D35 transparently rather than silently. SPEED_SOURCE/GPS_QUALITY wire keys already existed from #7 with matching numbering, no reconciliation needed there. New deriveGpsQuality() (accuracy tier vs. age tier, worse-of) and a SpeedReport.Live/NoSignal type so a dead source reports honestly instead of freezing the last value (D44 principle).\n\n**Real bug caught and fixed**: onGpsFix's accuracy gate ran before the wheel-live check, so a poor-accuracy fix arriving while the wheel was live got rejected outright instead of refreshing the position baseline \u2014 a sustained bad patch (bridge, urban canyon) with a wheel sensor also live left the baseline stale, and the next good fix after the wheel quieted computed distance against it, producing an unbounded spike. Fixed by checking wheel-liveness first; proven with a regression test (~50m expected vs. the ~95m the bug produced).\n\nVerified for real: :companion:core:test (19+6 new tests), :companion:pebble:test (6 new), :companion:assembleDebug \u2014 all green.
Sign in to join this conversation.
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference
robert/PedalPebble#19
No description provided.