MAVLINKGPS

The Lumpy Earth: Ellipsoid vs. Geoid

Why is my Drone Flying into the Ceiling?

A common "First Flight" problem with Virtual GPS is altitude error. You hover the phone at 1 meter, but Mission Planner reports -25 meters or +40 meters. This is not a bug; it is a Geodetic Reference Frame mismatch.

To understand why, we must look at the mathematical shape of the Earth.

The Two Shapes of Earth

1. The Ellipsoid (WGS84)

GPS satellites orbit the center of mass. They "see" the Earth as a perfect mathematical shape called an Oblate Spheroid. This surface is smooth and defined by the WGS84 standard.

  • Altitude ($h$): Height above this mathematical surface.
  • Android API: Older versions of Location.getAltitude() return this raw Ellipsoid height.

2. The Geoid (EGM96 / MSL)

The Earth is not smooth. Mountains have mass; trenches have voids. This uneven mass distribution creates "lumps" in the gravity field.
The Geoid is an equipotential gravitational surface—essentially, where water would settle if it covered the entire planet (Mean Sea Level).

  • Altitude ($H$): Height above this gravity surface. This is what barometers measure and what humans consider "Altitude".

The Fundamental Equation

The relationship between these two frames is defined by the Geoid Undulation ($N$):

$$ h = H + N $$

Where:

  • $h$: Ellipsoid Height (Raw GPS).
  • $H$: Orthometric Height (MSL / Geoid).
  • $N$: Geoid Undulation (The separation between the two surfaces).

The "N" Value

Depending on where you are on Earth, $N$ varies significantly.

  • New York: $N \approx -32m$.
  • London: $N \approx 47m$.
  • India: $N \approx -100m$.

Use Case: The "30-Meter Drop"

Imagine you are flying in a warehouse in Chicago ($N \approx -34m$).

  1. The Mistake: Your app sends raw Ellipsoid height ($h$) to ArduPilot. Let's say $h = 200m$.
  2. The Interpretation: ArduPilot expects MSL ($H$). It assumes the $200m$ it received is MSL.
  3. The Reality: The actual MSL height is $H = h - N = 200 - (-34) = 234m$.
  4. The Crash: There is a 34-meter vertical discrepancy between the GPS frame and the Barometer frame. When the EKF attempts to fuse these, it may aggressively dive or climb to reconcile the conflicting data, leading to a crash into the ceiling or floor.

The ArduPilot Requirement

ArduPilot's navigation logic (EKF) explicitly expects MSL (Geoid) Altitude for the alt field in the MAVLink GPS_INPUT message. It does not perform the EGM96 conversion itself for MAVLink-injected data.

Therefore, the Android application MUST subtract $N$ before sending the packet:
$$ \text{MAVLink}{alt} = \text{Android}{raw} - N_{local} $$

Source Code Reference