Is Android's GPS altitude incorrect due to not including geoid height?

17,015

Solution 1

The answers to all three of your questions are yes.

The altitude you get from GPS is the height above the WGS84 ellipsoid in metres, which is an approximation of the earth's surface. I know that because I've been developing Android software to use it.

A correction has to be applied to convert the figure to height above mean sea level, or altitude as it is usually known. Note that this may differ from the altitude reported by an altimeter set to the current pressure at mean sea level because an altimeter actually measures air pressure, but air pressure is not just a function of height; it is also a function of air density and temperature, so an altimeter shows an approximation. This effect is not seen with GPS.

The Earth Gravitational Model 2008 (EGM2008) maps the difference in mean sea level with the ellipsoid as a function of longitude and latitude. Details are here:

http://earth-info.nga.mil/GandG/wgs84/gravitymod/egm2008/egm08_wgs84.html

A less accurate model that uses less data called EGM96 is also available. Google both of these to understand these better.

Solution 2

It's not quite that simple -- the Android API has either changed or has bugs. I have two Android devices -- a 'generic' phone (Android 2.3.6) and a Nexus 7 (Android 4.x).

On the phone, getAltitude() gives an answer consistent with my actual altitude AMSL (i.e., corrected for geoid). On the Nexus 7, the altitude returned is uncorrected. The documentation for the API does not specify which is returned -- so in some sense both are 'correct'.

Both devices seem to have decent GPS modules -- the $GPGGA NMEA message shows both the correct altitute and the geoid correction. So it looks as though one has to parse the messages oneself to get the correct altitude, and the getAltitude() method is untrustworthy.

Solution 3

Errors in the altitude may well not be down to the GPS and geoid altitude separation.

The altitude value returned by any GPS receiver is always the least accurate value. I have often seen my office building report that it is moving in altitude between -200 and +750 metres. One fundamental reason is that it is impossible to get an even spread of satellites in the altitude direction; they are always going to be above you, and if there is any obscuration of the sky at low elevations, they will be located in a cone above you. In the X and Y directions there will always, assuming a good sky view, be satellites spread left and right; in front and behind the receiver. This spread enhances the accuracy of the position solution.

Share:
17,015
Admin
Author by

Admin

Updated on August 13, 2022

Comments

  • Admin
    Admin over 1 year

    I'm testing an Android app that records the location (lat/long/alt). I'm running the app on a Samsung GTS5830 phone running Android 2.2.1

    I read here and there that GPS altitude is often incorrect due to the earth not being perfectly spherical. At my location, for example, the geoid's height is 52 meters.

    My understanding is that this height would be substracted from a "pure" GPS altitude. This would make sense for my location as:

     - altitude from GPS phone: 535 m
     - geoid altitude: 52 m 
     - altitude from phone's GPS minus geoid height: 482m
    
     - correct atlitude: 478 m 
    

    482 is close enough to the real thing for me to track elevation when hiking

    1. Is the above formula of the GPS height minus the geoid's height correct?
    2. Am I correct to assume that android is not factoring in the geoid's height when returning the GPS altitude?
    3. If the above is true, does it hold for all versions of Android?

    Here is the code I use to obtain the GPS coordinates:

    public class HelloAndroid extends Activity {
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            Log.d("main", "onCreate");
            setupGps();
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
        }
    
        LocationListener locationListener;
        LocationManager lm;
    
        void setupGps() {
            Log.d("gps", "Setting up GPS...");
            locationListener = new MyLocationListener();
            lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
            lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 20000, 5,
                    locationListener);
    
            Log.d("gps",
                    "GPS supports altitude: "
                            + lm.getProvider(LocationManager.GPS_PROVIDER)
                                    .supportsAltitude());
            Log.d("gps", "Finished setting up GPS.");
        }
    
        static class MyLocationListener implements LocationListener {
    
            public void onLocationChanged(Location location) {
                Log.d("gps", "long: " + location.getLongitude() + ", lat: "
                        + location.getLatitude() + ", alt: "
                        + location.getAltitude());
            }
        }
    }