Android: How to get accurate altitude?
There are two issues with using altitude of a smartphone / tablet GPS:
- The altitude is the altitude above the WGS84 reference ellipsoid. It is not the altitude above ground level or sea level. Here is more detail on that: http://www.gpspassion.com/forumsen/topic.asp?TOPIC_ID=10915. This error can be corrected; here is a description how to do that by hand: http://www.unavco.org/edu_outreach/tutorial/geoidcorr.html. The web article links to a calculator to get the Geoid height for correction; I do not know if there is also a web service available for this computation.
- The GPS altitude is terribly inaccurate for relatively cheap GPS receivers. Here is an article on that: http://gpsinformation.net/main/altitude.htm. One method to cope with this kind of inaccuracy is to filter the altitude data. I used a circular array data structure to remember the last few (I used 4) altitude readings and compute the average. This sufficed to get a relatively accurate reading of vertical speed for my application.
Another way would be parsing NMEA strings. The $GPGGA sentence already contains the corrected altitude data above sea level.
So, simply create a listener to NMEA-strings for your LocationManager and parse the messages:
private GpsStatus.NmeaListener mNmeaListener = new GpsStatus.NmeaListener() {
@Override
public void onNmeaReceived(long timestamp, String nmea) {
parseNmeaString(nmea);
}
};
public void registerLocationManager(Context context) {
mLocationManager = (LocationManager) mContext.getSystemService(LOCATION_SERVICE);
mLocationManager.addNmeaListener(mNmeaListener);
}
private void parseNmeaString(String line) {
if (line.startsWith("$")) {
String[] tokens = line.split(",");
String type = tokens[0];
// Parse altitude above sea level, Detailed description of NMEA string here http://aprs.gids.nl/nmea/#gga
if (type.startsWith("$GPGGA")) {
if (!tokens[9].isEmpty()) {
mLastMslAltitude = Double.parseDouble(tokens[9]);
}
}
}
}
You can either replace the altitude of the last Location object received through a location listener, or parse the whole new location through NMEA.