Monday, February 1, 2010

combining GPS and barometric altimetry: generating random altitude data

I'll now describe the model I used for the various altitude signals. This is probably a bit more elaborate than it needed to be, I admit. But I like realism.

First, the altitude versus time, as this was the most complicated. I started with Fourier coefficients generated using normal random magnitudes each chosen with an rms value proportional to a Lorentzian factor 1 / [1 + (s / λ)²], where λ is a reference distance of 10 km, describing the approximate length of a typical climb. This distribution is nice because it keeps enough of the high-frequency component for things to be interesting, but while allowing the low-frequency components to generate nice continuous climbs. The phase for each component was then randomized from 0 to 360 degrees.

But this doesn't represent a realistic profile, since the random Fourier components yield peaks and valleys of the same shape. So I transformed the altitude using the following:

z → (50 meters) ln [ 1 + exp(z / 50 meters) ],

which you can see if z is suffiently positive, simply uses z, but if z is negative, makes z a small positive number. This generates rolling valleys mixed in with tall peaks, which is more realistic.

It's still not as good as I'd like, however. Real roads are built to a certain design grade. If the hill gets steeper than this, the road traverses, with switchbacks if necessary, to bring the grade down to the design limit. This tends to result in climbs which maintain close to a steady grade for long segments. To account for this, I applied a transformation to local road grades:

grade → grade / [ ( grade / grademax )4 + 1 ]1/4,

which is easy to see clips the magnitude of grade at grademax. I applied this grade transformation by stretching the road length relative to that generated by the transformed Fourier composition.

Now, if I really wanted to get fancy, I could recognize different roads tend to have different grades, and roads tend to change at the bottom of descents and sometimes at the top of climbs, so I could mix up the maximum grade. Enough, already, though! I left it at this, with a maximum grade of 10%. Maybe I'll take it further if I ever were to write a course generator for, for example, the Pedal Force Simulator.

So the parameters I ended up using to generate the road amplitude was a characteristic length of 10 km and a maximum grade of 10%.

Then I needed to map this altitude as a function of distance to an altitude as a function of time, which is what altimeters measure. So for that, I used a simple model based on the bicycle power-speed equations. I assumed the following parameters:

v0 = 9 meters/sec,
vam0 = 0.35 meters/sec,
acc0 = 2 meters/sec²,
Crr = 0.5%,

where v0 is speed on the flats (without rolling resistance), vam0 is the maximum climbing rate (without wind or rolling resistance), acc0 is the acceleration on level ground (without rolling or wind resistance), and Crr is the coefficient of rolling resistance.

Then starting with an initial condition of velocity (v) = 0, I calculated for each point in the route, I calculated from a basic power-speed equation the rate of acceleration based on the grade and the present speed. The simplified equation of motion is the following (easier than mucking about with the traditional power-speed equation):

∂v / ∂t = g (vam0 / v) [1 ‒ ( v / v0 )³ ‒ (grade + Crr) v / vam0],

where I exploit the fact that the maximum climbing rate is related to acceleration by a factor g, the gravitational acceleration. This doesn't do well for exploding off the line, where power is typically higher, but it for the rest of it it works nicely. I then cap acceleration at a maximum value using

∂v / ∂t → 1 / [ (1 / ∂v / ∂t)² + (1 / amax)² ]½

I then integrated this acceleration twice to get the position as a function of time, using a single pass. Then I evaluated the altitude to get the altitude as a function of time. This worked fairly well.

That was altitude. Now I had to construct signals for the errors of the GPS and barometric altimetry components, and also for how the GPS signal tends to drop out for awhile, then come back. For this, I created three additional data sets, each constructed using randomized Fourier components with Gaussian (as opposed to exponential) envelopes. Each of these signals was generated as a function of time, not position or altitude. I assume barometric errors are due to changes in the meterological conditions, while GPS errors are due to air density fluctuations, neither of which care if the rider is moving or not. Here they are:
  1. GPS error: a broad-spectrum (time constant = 5 seconds), low amplitude error between the GPS reported altitude and the actual altitude. This moves around quickly (time constant 5 seconds), never straying more than a few meters from zero
  2. barometric error: a deviation of the barometric altimeter from the actual altitude. This varies slowly (time constant = 20 minutes), with a much larger amplitude.
  3. GPS valid signal: This varies with a time constant of 30 seconds, the the range of approximately ±1. If it exceeds 0.2, I consider the GPS signal to be invalid. As a result, the GPS signal tends to drop out fairly often, typically for up to a few minutes at a time.

An important point is that errors in both the barometric altimeter and in the GPS altitude tend to be a fixed difference (measured in meters), not proportional to altitude (measured in %). Neither barometry nor GPS location triangulation has any idea of what "zero altitude" means. Pressure is proportional to the exponential of altitude, and therefore a fractional error in pressure produces a fixed error in altitude. Similarly, with GPS, you're triangulating position based on the delays of signals from satellites. If an atmospheric perturbation, for example, changes the relative delay in an unpredictable fashion, then this produces a fixed error in position. It doesn't matter if you're at sea level or 100 meter altitude: a 1 meter error is a 1 meter error. So I model errors in both the GPS and in the barometric altitude with an offset, not a multiplicative factor. Another way of looking at this is there's no "preferred" altitude. Physics doesn't recognize sea level as special Well, it does, once you get far enough below sea level that the gravitational force starts dropping, but I assume altitude changes are small in comparison to the 6.4 Mm radius of the Earth.

Here's the second hour of a multi-hour ride simulation I constructed in this way, showing the actual altitude and then the altitude reported by the barometic altimeter and the GPS:

portion of randomly generate altitude data

You can see how the barometric altimeter smoothly tracks the actual altitude but with a large offset. On the other hand, the GPS altitude is always close to the actual altitude, but jumps around a lot, and the signal disappears for extended periods. The goal is to construct an aggregate signal which exploits the smoothness and reliability of the barometric altitude, but also the accuracy of the GPS signal.

I'll describe how I combine the barometric and GPS signals next time.


djconnel said...

My initial plot of altitude was in error (max climbing rate was 1 m/sec instead of the desired 0.35 m/sec). I fixed this.

BTW, sharp-eyed observers will note the equation of motion is not constant power: the acceleration is wrong, the max speed is too low given the climbing rate. However, the intent was an equation describing typical behavior. I intentionally boosted the power when climbing because that's what a lot of riders do (more payback from higher power on climbs), and the acceleration was intentionally heuristic to avoid the zero-speed singularity of a constant power assumption (not based on constant power).

djconnel said...

Okay -- I fixed the non-physical acceleration. It was bugging me the whole time I was in the dentist chair this morning getting a cleaning. Totally immaterial to the subject of altitude analysis :).

TnA said...

You should think about adding a term that accounts for stagnation pressure effects at the barometric sensor that's proportional to the speed. I've found that most bike mounted barometric altimeters suffer from this problem, where the altitude reported is offset lower than reality the faster you go...I've seen this with both Polar and Garmin bike units.

djconnel said...

Do you have a model for this? It's an interesting idea! It seems it would be very sensitive to mount location.

For example, you wouldn't want to mount your altimeter on the top of a wing, where the occupants of the vessel are relying on reduced pressure for their survival! Yet even airplanes manage to measure altitude barometrically.

In the case of the present application, I think GoldenEmbed is typically going into water bottles. However, the goal is to make a mount which can be tucked someplace unobtrusive.

TnA said... might be mount specific. Both of my examples were with the unit mounted on the handlebars. As I chose to do in the example I link to below, you might want to allow the user to specify a % of free stream velocity that's converted to static pressure. Just a thought...

djconnel said...

That is really cool! Okay, so I can tell right off the effect of this. It depends on how speed fluctuates. Since my solution is to smooth the barometric and GPS signals with a cosine-squared convolution function with full-width-half-maximum (FWHM) = 100 seconds, if speed fluctuates over significantly less than this time, the error will leak through. My time constant was based on the assumption the primary source of variability is uncompensated atmospheric pressure variations (static pressure), and these typically occur over more than 100 seconds, a time suitably long to smooth out the noise from the GPS signal. However, if speed varies more quickly than this, you're sort of stuck. My speed in the model is a strong function of road grade: I assume no motivational noise :).

A nicer combination, I feel, is a GPS with a "smart" gradiometer, for example iBike. Maybe iBike will be GPS enabled this year.

TnA said...

In a previous job, I was exposed to a bunch of really smart guys who where working on inertial nav systems. It seemed that in situations like this, they tended to rely on a Kalman filter to make good estimates of system's state from a bunch of noisy measurements...I'm not smart enough to know if something like that would be of use in this application, with the measurements being GPS altitude, barometric pressure, and speed?

djconnel said...

Well, I'm not sure about Kalman filters, but I am intrigued by the intro on

The Kalman filter uses a system's dynamics model (i.e. physical laws of motion)...

The broader message is "don't analyze data without exploiting knowledge of the underlying physics". With that in mind a simple approach to the stagnation problem would be to evaluate a correlation between altitude difference (between GPS and barometer) and speed-squared (the functional form of dynamic pressure. Since the goal of this is archived data, not real-time display, this could be done globally on the entire ride file. This correlation could then be subtracted from the data, point-by-point, IF a speed number was available, which GPS should provide (at least when the signal's available). GoldenEmbed is primarily an ANT+ sniffer, so there may be another trusted ANT+ speed signal available when GPS is unavailable.

So there are possibilities. More chance to hack my script.

TnA said...

Well...if the intent is to use this for any sort of VE testing (i.e. as an "actual" elevation for AeroLab), then I'd HIGHLY recommend a separate ANT+ wheel speed sensor to be added into the mix. After all, the largest potential source of error in the VE calculation is error in the speed measurement :-)

I like where you're going with this...if there's one thing that bugs the crap out of me is the HORRIBLE estimate of altitude that the 705 outputs, even though it has GPS AND barometric pressure.