Sunday, January 15, 2012

Converting pressure to altitude

Now that I have my GPS and barometric pressure sensor up and running, I can try calibrating the pressure data into altitude.  Given the properties of air molecules and the strength of gravity, and how much air there is in the atmosphere, there's a relationship between altitude and pressure.  Fortunately, the physics has already been worked out and can be found on wikipedia.  They are related to each other by a power law:

Altitude = A - A (Pressure/P0)^B

where A = T0/L, B = (RL)/(gM), T0 = temperature at sea level, L = temperature lapse rate, R = universal gas constant, g = acceleration due to gravity, M = molar mass of dry air.

The other parameter is P0 -- the pressure at sea level, which is really just a measure of how much air there is stacked up in the location you happen to be in.  There is a standard value for sea level pressure, but it varies depending on the weather.  The best thing to do is solve for it if you already know your altitude at the start.

I  took 4 minutes of data at home, where I can simply look up my altitude on a topo map (it's 312 m).  Then after plugging into the equations from wikipedia, I can look at how it compares to the GPS altitude.  Aside from noise (or changes in the weather) these data points should be all be the same.

Look how nice and stable the barometric altitude (blue points) looks compared to the GPS altitude (green points)!  Good thing I went through the trouble of installing that BMP085.  The standard deviation of the blue data points is 0.6m and the standard deviation of the green points is 3.5 meters.  So if you integrate for 240 seconds you can get your elevation to 0.6m, but only 3.5m with the GPS.  Not bad!

Why is the GPS altitude so poor?  I found a blog post on the topic which nicely addresses why the reported altitude is wrong.  This is because in order to report altitude above sea level, you have to make a model of the shape of Earth, which is assumed to be an ellipsoid (a flattened sphere - squished in at the poles).  This model generally gives the shape of the Earth, but it is not perfect in in most places on Earth.  So I think this explains the fact that on average, the GPS tells me I'm around 320 meters above sea level, but in fact I know I am at 312m.  This blog post also goes on to say that many GPS units return the correction factor between the ellipsoid model and the true sea level (unfortunately the EM-406 I'm using does not!).

That explains the overall discrepancy between measured and true altitude, but it doesn't explain why the GPS altitude drifts all over the place.  The latitude and longitude data are incredibly accurate - I can see what part of my house I am in when I overlay the data points in Google Earth, which is much better than the 3.6m standard deviation in altitude I see over 4 minutes.    In any case, including a pressure sensor in this device has solved the problem.

Here's my python code that I used to read in my data and do the calibration and conversion of pressure to altitude.

 import numpy  
 import pylab  
 def get_sea_level_pressure(p,alt):  
   T0 = 288.15  
   g = 9.80665  
   L = 0.0065  
   R = 8.31447  
   M = 0.0289644  
   return p/(1-L*alt/T0)**((g*M)/(R*L))  
 def pressure_to_altitude(p,p0):  
   T0 = 288.15  
   g = 9.80665  
   L = 0.0065  
   R = 8.31447  
   M = 0.0289644  
   A = (T0/L)  
   B = (R*L)/(g*M)  
   return A - A * (p/p0)**B  
 # The altitude where I started the log file  
 calibration_altitude = 312.12 # meters  
 time,lat,lon,gps_alt,pressure,temperature = numpy.genfromtxt("GPSLOG00.TXT",comments="#",unpack=True)  
 p0 = get_sea_level_pressure(pressure[0],calibration_altitude)  
 pylab.plot(pressure_to_altitude(pressure,p0),'o',label='Barometer')  
 pylab.plot(gps_alt,'o',label='GPS')  
 pylab.ylabel('Altitude (m)')  
 pylab.xlabel('Seconds')  
 pylab.legend()  
 pylab.show()  

No comments:

Post a Comment