Skip to content

Correct the compass with the error measured against the GPS course - #104

Open
rodrigohpalmeirim wants to merge 1 commit into
mainfrom
t3code/compass-offset-calibration
Open

Correct the compass with the error measured against the GPS course#104
rodrigohpalmeirim wants to merge 1 commit into
mainfrom
t3code/compass-offset-calibration

Conversation

@rodrigohpalmeirim

@rodrigohpalmeirim rodrigohpalmeirim commented Sep 9, 2026

Copy link
Copy Markdown
Member

The compass takes over the heading when we stop, but it's often off by tens of degrees and sometimes reversed outright (uncalibrated magnetometer, steel of the bike and mount). While riding we have a trusted heading from the GPS course, so this measures the compass error along the current leg and takes it out when the compass has the say.

Offset estimator (src/lib/compass-offset.ts)

  • Every raw compass reading (before the 2° / 200 ms throttle) and every fix course at ≥2 m/s is fed to the estimator; the course is only paired with the compass if it held steady (within 8°) over the previous 2 s, since the GPS course lags the compass by about a fix and pairing them mid-turn is meaningless
  • The offset is a circular exponentially weighted mean (~10 s memory) of course − compass, using the compass average over the stability window to shed jitter
  • Applied only once ≥3 samples agree closely (resultant length ≥ 0.95, roughly 18° of scatter); a phone held at a random angle to the bike never gets past that gate, and a reversed compass is corrected like any other offset
  • Reset on any visibilitychange: the screen is kept awake during a trip, so it going dark means the phone was pocketed, where it points anywhere but forward. What was learned before doesn't hold in there, and what's learned in there doesn't hold once it's out

Wiring (location.ts, compass.ts)

  • Only the fix's own heading is used as a calibration reference, never the anchor-derived bearing between fixes
  • On compass takeover currentHeading receives the corrected value, which also lands close to the last GPS course so the marker no longer snaps at the handover

Test plan

  • npm run check, eslint on touched files, vitest run (9 new tests for the estimator; full suite passes)
  • On-bike testing: correction should kick in a few seconds after stopping, marker shouldn't snap at takeover
  • Pocket the phone mid-trip, take it out at a stop: heading should be uncorrected raw compass until riding again

The compass is often off by tens of degrees, sometimes reversed, so the
heading it provided at stops was frequently wrong. While riding, pair each
gps course with the steady compass reading of the previous two seconds and
keep a short-memory circular mean of the difference; apply it when the
compass takes over after the course goes stale. The estimate is only used
once a few samples agree, and is dropped whenever the screen visibility
changes, since a dark screen mid-trip means the phone went into a pocket.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant