DEV Community

Elliott Jempty
Elliott Jempty

Posted on AI-assisted

How GPS taught my car-sickness app which way is down

I'm the developer of Perusa, a small Android app I build on my own. It puts dots along the edges of the screen that follow the car's real braking and turns, on top of whatever you're reading, for passengers who feel queasy reading in the car. This post is about the problem I spent last week on: knowing which way is down.

The problem

The phone's accelerometer measures everything at once: gravity plus the car's push. To show a passenger the braking and the turns, the app has to take gravity out, and for that it has to know where "down" is in the phone's frame.

On a straight road at constant speed that's easy: what's left in the accelerometer is gravity. Stop-and-go traffic is the hard case. The car doesnt stay steady long enough to check, and every correction the app had was switched off during maneuvers, which in stop-and-go is nearly all the time.

In one of my tests, a small knock on the phone in its holder, right as the car pulled away from a light, left "down" about 3.4° off. That sounds small, but it turns into roughly 0.55 m/s² of fake braking, and the dots sat crooked for about 45 seconds.

The idea: let GPS say how hard the car is pushing

GPS knows the speed. The change in speed between fixes gives the forward push (dv/dt), and speed times the gyro's turn rate gives the sideways push (v × ω). Take those out of the accelerometer and what's left is gravity, even in the middle of a turn.

In practice there were three catches:

  • GPS arrives late. On my S26 Ultra the lag is between 0.2 and 0.6 s. Comparing the accelerometer now with the speed from half a second ago ruins everything.
  • The holder is crooked. The phone is almost never lined up with the car; mine sits about 25° off.
  • Hands move. Picking the phone up, a tremor, a pothole: all of it looks like a push.

The fix was to learn the GPS lag and the holder angle together, every ride: for each candidate lag, I fit the rotation that best lines up the changes from one window of fixes to the next, and keep the pair that fits best. A fixed 0.4 s lag looked simpler, but it biased the angle. Before correcting anything, a row of guards gets suspicious: hands moving, tremor, a jolt, turning faster than a car can, the two halves of the window disagreeing. If someone rotates the phone in the holder, the app forgets the angle and keeps the lag.

Results

Across 44 recordings of real rides, the time with cue error above 0.5 m/s² dropped from 1523 s to 1070 s (about 30%), and phantom-motion time on calm roads went from 920 s to 740 s. Maneuvers still point the right way in 99.6% of cases. It shipped in version 0.5.1 on 21 Oct.

About the app (and 15 codes)

Perusa is for passengers only, never while driving. It's a comfort aid, not a medical device. No account, no ads, no subscription. Android 8 and up.

Since last week it's free to install with 3 hours of cues, then a one-time $1.99 unlock. Here are 15 unlock codes for anyone who wants to try it. If you take one, leave a comment saying which so others can skip it. No review required, enjoy!

  • U74G0EMB84FD5W2N0BFURUE
  • R9Z70NQWH6K7JBFTASDG6RV
  • UR4SEVEUMTBHT4B1S752LPR
  • CBLBD3YB7NM2FNR3C4TRX5N
  • CSRVGRYS6MPSS0GC8BXERNR
  • HE19CAFD7F2DH2FCFHYPF4L
  • HGVZEZ5R97TC2EJVUBLYQK6
  • 7LKQYBAXZQ2VD554AE0FYBT
  • VR7UNF95RTAG95Q9DN0LRUX
  • DXZ93VKWVCN34PXRV6ESUK3
  • 7WUMTV3PEY0UBKWUT9NWY4K
  • 4UMK0TFN05F6167DVAP9XZ6
  • MVYPM4ZZ1ERFAA1Y34TDLHM
  • VJ0ZPV9JJGMZGCPZ2THCWZR
  • DTCMKM8YNNNU76YRPJDCST9

To redeem: Play Store → profile picture → Payments & subscriptions → Redeem code. Or tap "Redeem a code" on Perusa's unlock screen.

Google Play: https://play.google.com/store/apps/details?id=com.perusa.app

Happy to answer questions about the sensor side. The lag fitting was the part I went back and forth on most.

Top comments (1)

Collapse
 
ahmedznouda profile image
Ahmed ZNOUDA •

Fitting the lag and the holder angle together on every ride is a nice answer to a problem most people would solve with a constant. The 3.4° → 0.55 m/s² example makes the stakes very clear.

A few things I'm curious about:

  • Tunnels and underground car parks: when GPS drops out for a minute, do you freeze the last "down" and lag, or fall back to the gyro-only path? And the first speed values after the fix comes back are often noisy. Do the guards treat "GPS just came back" as suspicious too?
  • Which speed do you use: the fused provider's, or Location.getSpeed() straight from GPS_PROVIDER? A fused value may be smoothed, which could hide part of the lag you're fitting.
  • Battery on a long ride: GPS plus sensors for three hours of cues. Have you measured what a typical trip costs?

Also good to see "comfort aid, not a medical device" spelled out. That wording matters on Play for anything close to health.