Saturday, February 5, 2011

filtering motorized ride segments with power estimation: finally done (for now)

I implemented the biexponential filter, along with power filtering, in my motorized segments detection code. This program, along with my other Garmin Perl codes, can be found here.

I made a few changes from previous descriptions. One is I changed the anaerobic time constant to 120. This is more the upper end, rather than the median, of typical numbers. This may provide a bit more margin against falsely identifying a segment as motorized.

The other change I made was to separate the altitude-smoothing time constant from the anaerobic time constant. Oversmoothing of altitude can result in the overprediction of power when a rider descends small dips. I set the default to 30 seconds. I also added some speed smoothing but only 5 seconds. Without any speed smoothing and there's too much effect from when the Garmin occasionally spits out a single point with ridiculously high speed. But too much longer than 5 seconds and I lost more of the train segments in Italy where the train was making frequent stops and passing through tunnels:

effect of VAM on smoothing
partial tagging of train travel in Italy

Impressive how the train maintains speed constant to the precision of the Garmin...

With these parameter settings, of all the rides I tested segments which tagged as motorized with a speed threshold of 14 m/sec also did so with a power threshold of 6.5 W/kg, and vice-versa. This isn't too surprising, as I've not taken motorized transport up any significant climbs with my Garmin running (if I take motorized transport on my own, it's almost always a train, and the train well exceeds 14 m/sec). Were I to drive up a winding road like Old La Honda, the power criterion would make a difference. Even a car is unlikely to average 14 m/sec up the road, but on the other hand even a pro cyclist with unrestricted pharmacutical access wouldn't be able to exceed 7.4 meters/second.

Back to altitude filtering: here's some examples of the biexpontial filter I so painfully described. First that trainer ride:

Garmin trainer data with smoothing
Garmin Edge 500 data from riding a trainer, with smoothing

Here you can see that the 30-second smoothing doesn't do as good of a job as the 90-second smoothing, but still not too bad: the early rapid jumps in altitude result in around a peak artificial grade of 0.5%, which corresponds to an extra 0.5 W/kg which results in a VAM of increase of around 120 meters/hour from these data, or around 0.36 W/kg for less than 30 seconds given reasonable assumptions about bike mass to body mass ratio.

And here's another ride, where I show the result of applying different time constants to the resulting VAM:

effect of VAM on smoothing
VAM from an outdoor ride, with different biexponential time constants.

Of course, the resulting power estimation knows nothing about cross-winds, head-winds, rough versus smooth roads, drafting, or mass changes. But the goal here is to simply identify "extraordinarily high" power. For that purpose I think it does fairly well.

P.S. It would be fairly easy to modify the code to add an estimated "Power" field to a FIT file for rides where you want power but didn't have a power meter. However, I'll pass on this one, as I don't think power estimation from speed & altitude is good enough: it would just result in data contamination.


gregclimbs said...

I can think of another application for this...

For filtering walking while riding a ss mtb...

but looking the other direction... speed <5mph and power==0



djconnel said...

Excellent! :)

I need a filter to red-flag me laming out and walking descents on my mountain bike. That's more challenging. Maybe you need to put shear sensors under the brake pads.

P.S. I'm glad to see this series of posts hasn't scared away everyone from this blog... it's not been the most focused discussion...