Altitude gain calculation may exhibit systematic error

75 views
Skip to first unread message

casper.murtonen

unread,
Sep 7, 2020, 6:51:31 AM9/7/20
to golden-cheetah-developers
The altitude gain is calculated like this in GC (awk code for testing):

awk -v hys=$1 '
{
    ele = $1

    if (NR == 1) {
        prev = ele
    } else if (ele > prev + hys) {
        gain += ele - prev
        prev  = ele
    } else if (ele < prev - hys) {
        loss += prev - ele
        prev  = ele
    }
}
END {
    printf "gain = %f loss = %f\n", gain, loss
}'

This will tend to underestimate the gain/loss as for each crest or dip as the gain/loss will only be increased if the current value of prev is exceeded by hys.  So for example if set to the default 3 metres a set of rollers 5 metres from crest to dip will only add 3 metres per roller.  Or more realistically you'll tend to lose on average 1.5 metres for every hill - which it seems can be around 15 % of the total elevation for some rides.

Here's a possible alternative algorithm:

awk -v hys=$1 '
{
    ele = $1

    if (NR == 1) {
        min = ele
        max = ele
    } else if (!init) {
        if (ele > min + hys) {
            max  = ele
            up   = 1
            init = 1
        } else if (ele < max - hys) {
            min  = ele
            up   = 0
            init = 1
        }
    } else if (up) {
        if (ele < max - hys) {
            gain += max - min
            min   = ele
            up    = 0
        } else if (ele > max) {
            max = ele
        }
    } else {
        if (ele > min + hys) {
            loss += max - min
            max   = ele
            up    = 1
        } else if (ele < min) {
            min = ele
        }
    }
}
END {
    if (init) {
        if (up)
            gain += max - min
        else
            loss += max - min
    }

    printf "gain = %f loss = %f\n", gain, loss
}'

For example my local ride yesterday (23 km), with an Edge 830 (inbuilt barometric altimeter):

GC algorithm, hysteresis = 3 m:  gain = 475.200000 loss = 478.200000
GC algorithm, hysteresis = 1 m: gain = 531.800000 loss = 535.600000
alternative algorithm, hysteresis = 3 m: gain = 551.000000 loss = 555.000000
alternative algorithm, hysteresis = 1 m: gain = 566.400000 loss = 570.400000
Edge 830: gain = 554, loss = 556

I also carried an etrex 20x (no barometer):

GC algorithm, hysteresis = 3 m: gain = 460.960000 loss = 476.820000
alternative algorithm, hysteresis = 3 m: gain = 507.100000 loss = 522.960000

I'm not sure if the algorithm should be changed given many users might be used to the underestimation, but unfortunately even for perfect altitude data I think the current algorithm will underestimate systematically, which is a pity.  I'm happy to commit a fix, if it's considered an issue.

casper.murtonen

unread,
Sep 7, 2020, 6:55:19 AM9/7/20
to golden-cheetah-developers
And I forgot to say that the GC app reports (with default hysteresis of 3 m) a gain of 475 m.
Message has been deleted

Ale Martinez - No direct email please

unread,
Sep 7, 2020, 11:29:09 AM9/7/20
to golden-cheetah-developers
Honestly I am not sure how relevant this could be, but in v3.5 you could to implement your algorithm as User Metrics which can be used in summaries and charts like the builtin ones but slower at metric refresh time, in v3.6 a vectorized version should be faster and the metrics can be shared on CloudDB: https://github.com/GoldenCheetah/GoldenCheetah/wiki/UG_Special-Topics_Creating-User-Metrics

casper.murtonen

unread,
Sep 7, 2020, 5:47:55 PM9/7/20
to golden-cheetah-developers
Yes it's true I could implement my own version of altitude gain, I didn't think of that.

But in my opinion the builtin metric is calculated incorrectly (class ElevationGain in BasicRideMetrics.cpp).  This is why the GC altitude gain differs significantly from that presented by Garmin, Strava, etc., and is probably why the ability to adjust the hysteresis value was added (although as you can see even with a value of 1 m it doesn't really "fix" the issue at hand).  Fix the algorithm and you could potentially remove the adjustable hysteresis value, and not have new users like me question the altitude gain accuracy as in the FAQ (https://github.com/GoldenCheetah/GoldenCheetah/wiki/FAQ-METRICS#Why-is-elevation-different-in-GoldenCheetah-to-my-other-training-software--website).  It may be telling that GC and Zwift disagree significantly for many virtual rides as well - and the elevation values from Zwift should be as near as perfect as it is possible for any device (apart from software bugs in the Zwift server).

On the other hand one man's bug is another man's feature, so I can understand if there is a preference to leave it as is.

Cheers, Casper

Ale Martinez - No direct email please

unread,
Sep 7, 2020, 6:35:45 PM9/7/20
to golden-cheetah-developers
El lunes, 7 de septiembre de 2020, 18:47:55 (UTC-3), casper.murtonen escribió:
Yes it's true I could implement my own version of altitude gain, I didn't think of that.

But in my opinion the builtin metric is calculated incorrectly (class ElevationGain in BasicRideMetrics.cpp).  This is why the GC altitude gain differs significantly from that presented by Garmin, Strava, etc., and is probably why the ability to adjust the hysteresis value was added (although as you can see even with a value of 1 m it doesn't really "fix" the issue at hand).  Fix the algorithm and you could potentially remove the adjustable hysteresis value, and not have new users like me question the altitude gain accuracy as in the FAQ (https://github.com/GoldenCheetah/GoldenCheetah/wiki/FAQ-METRICS#Why-is-elevation-different-in-GoldenCheetah-to-my-other-training-software--website).  It may be telling that GC and Zwift disagree significantly for many virtual rides as well - and the elevation values from Zwift should be as near as perfect as it is possible for any device (apart from software bugs in the Zwift server).

On the other hand one man's bug is another man's feature, so I can understand if there is a preference to leave it as is.

I'm not particularly invested in that formula, but it is a long standing feature and before to change it it would be preferable more testing in real conditions, a User Metric uploaded to CloudDB and posted to users forum could be a way to have feedback. 
Reply all
Reply to author
Forward
0 new messages