Posts

exponential filtering algorithm

Here I'll briefly describe the algorithm for filtering data with an exponential convolution. First, I'll define the following: n: an index for the point in the series. The first point is n = 1, the next n = 2, the next n = 3, etc. y n : the series of unfiltered points data values, for example altitudes. t n : the series of unfiltered points time values. Δt: the time separation of the data for uniformly spaced time points. Δt n : when time is not necessarily uniformly spaced, Δt n ‒Δt n‒1 . τ: the smoothing time constant. u n : normalized time values, t n / τ. Δu: Δt / τ (for uniformly spaced time points). Δu n : Δt n / τ. z n : the series of smoothed time points. So using these definitions, I want to convert from the unsmoothed series y n to the smoothed series z n . First, if an initial point is encountered, we start things rolling with the following: z 0 = y 0 Then assuming uniformly spaced data, a naive approach is the following: z n = z n‒1 exp...

smoothing Garmin altitude profiles for power estimation

Image
Recall that I was contemplating using power in lieu of speed for determining whether a Garmin FIT file contains motorized segments. The speed criterion was fairly simple: if the data indicate the user got 500 meters ahead of a 14 m/sec pace over any segment, that segment was judged to be a portion of motorized travel. The entire region between load/unload opportunities was thus tagged and pruned. While cyclists may be able to sustain a high speed for short periods, by requiring they get a certain distance ahead of a threshold pace requires they exceed that pace for an extended time, or vastly exceed it for a shorter time. Example of critical power model applied to more realistic curve In the power-time domain,the critical power model accounts for that ability to sustain high intensity for short times, but only a lower intensity for longer times. The critical power model is very similar to the criteria used for speed: it says a rider, given sufficient time, can do a given amoun...

Bike Nüt closed

Image
I heard today that Bike Nüt closed a few weeks ago. Sad news. I always enjoyed stopping there. It was a good destination for a long run, or a good place just to stop and say hello and see what new bike jewelery Huseyin, the owner, had inside his glass case. Plenty of shops sell high-end stuff to build up a bike to the highest standards of the boutique fashion weenies. The number of shops selling custom Seven, Parlee, or Serotta cycles in or near San Francisco is nothing short of staggering. Bike Nüt, however, didn't sell custom frames. Huseyin's philosophy was that frames are commodity: that the Taiwanese factories have produced a high, uniform standard, so save your dollars there. Instead you want to spend your money on good wheels and quality parts. On the frame area, until a year ago he was buying frames from Giant, then sending them out to have the paint stripped and clearcoat applied to reduce them to the raw, black bare carbon. In a way this seems silly: Gi...

Garmin FIT activity splitter to eliminate large time gaps

I've gotten useful code on my third project for processing FIT files using Kiyokazu Suto 's Garmin::FIT package for Perl. First, I described fit_to_cols , which extracted selected data from FIT files and formatted it in a space-delimited file. Next I described fit_filter_motor_segments which attempted to identify segments where the Garmin was accidently left running in a fast car or train. That project's still being refined, as I described last post. Here is perhaps the most useful of the three, fit_split_on_gaps , which finds gaps of some specified minimum duration (default 8 hours, or otherwise specified with the -tgap option) and splits the FIT data into multiple sub-files at any gaps found which meet or exceed this threshold. This and the other codes can be found here, on Google Docs . It's fairly common in my experience to forget to "reset" my Garmin between activities, despite having set it to warn me at the start of a ride if I have not. Gol...

adding altitude to motorized segment identification?

Image
A friend of mine, Brian, took his Garmin with him in his car, drove on local roads, did a run, got back in his car, and drove back home. He was careful never to drive much over 30 mph the whole time. He then loaded the data into my motorized FIT filter and..... nothing. It didn't identify any of the segments as motorized. The reason for this is the criterion I used, that the units must record progress which is at least 500 meters ahead of a 14 kph pace for some time interval, is designed to avoid tagging segments where a rider was descending a relatively fast mountain descent. Descending on a bike is faster than driving on local streets, so it would be relatively hopeless to expect, using crude speed measures only, that I'd be able to pick up local driving as suspicious. I was discussing this with Bill, another friend, when the idea came up of throwing altitude into the mix. Now this is hardly a new idea: it'd already been proposed on Strava forums that calculated...

Garmin FIT motorized segment filter in Perl

Finally, squeezing in work in my train commute between San Francisco and Mountain View (which unfortunately hasn't been a bike commute as much as I'd like due to the pressures of two big projects at work, but digression opportunities ate limited in the middle of a sentence), I've managed to finish a working draft of my "motorized segment filter" in Perl. Like the fit_to_cols code I described recently, this code uses Kiyokazu Suto 's Garmin::FIT package for Perl. Unlike fit_to_cols, this one needs to be able to write as well as read FIT data. The Garmin:FIT perl module allows this, but to figure out how you really need to dig into the provided example, fitsed . Fitsed is uncommented and does a lot more than just read and write FIT files: it also has a parser for selecting and/or changing fields in records. All good stuff, but a simple equivalent of hello.c , an example which minimally demonstrates writing FIT data, would have been useful. But I worked i...

a Perl Garmin-FIT to space-delimited table converter

I've been working on a code to filter motorized segments from FIT files, using Kiyokazu Suto 's Garmin::FIT package for Perl. However, to help with that work, I needed a way to quickly plot the data in a FIT file. So I wrote a script, fit_to_csv , to create a readable table from FIT data. The code produces a space-delimited file with each column describing a field either contained in the FIT file or derived from data in one or more fields of the FIT file. I have a series of scripts for handling such files and generating plots from them, or they can be trivially loaded into a spreadsheet like oocalc or even Excel , or almost any other plotting package, using the "CSV" format. When importing the CSV, make sure spaces and not commas are selected as the delimiter. The code's available here . On Linux, simply save the file, make sure it has executable permission, then run it in the standard Linux fashion. On Windows, well, you're on your own. I avoid Wi...