Solving the "N" Value
Calculating Geoid Undulation on Android
To send valid MSL altitude to ArduPilot, we must solve for $N$ (Geoid Undulation) locally on the phone.
1. Legacy Approach: NMEA Parsing
Older Android devices expose raw NMEA sentences ($GPGGA) via OnNmeaMessageListener.
- The Fix: The
$GPGGAsentence contains the MSL altitude directly (calculated by the GNSS chip's firmware). - The Problem: Not all phones expose NMEA, and parsing strings at 10Hz is CPU intensive.
2. The GeographicLib Approach (EGM96)
We embed a compressed binary grid of the EGM96 (Earth Gravitational Model 1996) dataset within the app.
- Input: Latitude, Longitude (from Android Location).
- Process: Look up the N-value from the grid using bilinear interpolation.
- Output: $N$ (in meters).
- Calculation:
Altitude_MAVLink = Location.getAltitude() - N
This guarantees consistent altitude regardless of the phone manufacturer's GNSS implementation.
3. Android 14: AltitudeConverter
API Level 34 introduced android.location.altitude.AltitudeConverter.
- Feature: A native system class that adds MSL altitude to a
Locationobject. - Mechanism: It presumably uses a system-level Geoid model (likely EGM2008 or similar) to perform the conversion efficiently.
- Adoption: MAVLink GPS uses this API when available, falling back to our internal EGM96 grid for older devices.
Why Accuracy Matters
An error of 5 meters in X/Y is annoying. An error of 5 meters in Z (Altitude) causes a crash.
By ensuring the N-value is subtracted correctly before the data hits the wire, we ensure the drone's barometer and the GPS agree on where "Zero" is.
Source Code Reference
- Android API:
AltitudeConverterdocumentation.