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:
- 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
- barometric error: a deviation of the barometric altimeter from the actual altitude. This varies slowly (time constant = 20 minutes), with a much larger amplitude.
- 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:
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.