Skip to main content

Engineering notes

The head unit reports zero speed while the car does 60

Location.hasSpeed() returns true and the value is 0.0 — forever. Why this is so common on aftermarket Android units, and how the app detects it.

On a desk, reading speed from Android is one line of code. On an aftermarket head unit, it is the first thing that breaks.

The cause is in the NMEA sentences

A GPS module talks to the operating system in NMEA sentences. Position comes in $GPGGA; speed and heading come in $GPRMC. Plenty of cheap modules parse only $GPGGA — enough to put a dot on a map, which is enough for most apps.

What makes it worse: the driver still declares the speed field valid. location.hasSpeed() returns true and location.speed returns 0.0f. No exception is thrown, no error flag is set. An app that trusts the number ends up with a speedometer frozen forever — on precisely the most common class of device.

You cannot simply test for 'speed is zero'

A car waiting at a red light also reports zero. What is needed is a signal that separates 'stationary' from 'broken driver', and that signal is the distance between consecutive fixes: a moving car produces fixes tens of metres apart, whatever the driver claims.

What the app does

SpeedEstimator runs two sources side by side:

  • The driver sourcelocation.speed, taken as given.
  • The derived source — distance between two fixes divided by the time between them.

Normally the driver source is used, because it is smoother. But each time the derived source shows the car clearly moving while the driver still reports zero, the app counts a sample. After about eight such samples it concludes the driver is broken and switches to the derived source permanently for that session.

Why eight rather than two: a single noisy fix can manufacture a false distance. Eight consecutive ones cannot.

What the driver sees

Once it has switched, the screen shows 'speed computed from GPS'. That is not an error message — it tells the driver what the number rests on, so that speed lagging slightly behind reality has an explanation. On many head units this is simply the normal state.