mendhak / gpslogger

:satellite: Lightweight GPS Logging Application For Android.
https://gpslogger.app
Other
1.91k stars 598 forks source link

Problem with Ascent/Descent #1091

Closed EGruber01 closed 4 months ago

EGruber01 commented 11 months ago

Hello, I am new here and I would like to apologize if this is the wrong place to ask my question. I am using gpslogger since more than one year and I have a problem when showing my tracks on different viewers. I use a german site (https://www.gpswandern.de) and when I show my track the values for ascent and descent are not correct(I think). I have attached a gpx file and the corresponding web image and as you can see the values for ascent and descent cannot be correct. I started at about 1300m, went up to about 1600m and finally went down to about 950m. So ascent was about 300m and descent 650m. The displayed values (ascent 1326m, descent 1625m) are completely wrong in my opinion. Does anyone have an idea whats going wrong here? with kind regards Erhard 20230718.gpx.txt Heiligenblut_Mörtschach

EGruber01 commented 11 months ago

Additional Info: I now wrote a little program to calculate and sum up the differences between contiguous trackpoints and indeed, the sums are almost equal to the values in the picture above. But I am rather sure I didn't have so much ups and downs in between my hike. Could it be that the elevation accuracy is not so high? Or maybe the interval between points is set to small. I set logging interval to 90sec, distance filter to 30m, accuracy filter to 40m, duration to match accuracy to 60s and absolute time to GPS fix to 120s. Are these values ok? My smartphone is a Pixel 6 Pro. regards Erhard

mendhak commented 11 months ago

I tried a very straightforward approach with your file:

import gpxpy

with open('20230718.gpx', 'r') as gpx_file:
    gpx = gpxpy.parse(gpx_file)

track_points = []
for track in gpx.tracks:
    for segment in track.segments:
        track_points.extend(segment.points)

ascent = 0
descent = 0

for i in range(1, len(track_points)):
    elevation_diff = track_points[i].elevation - track_points[i - 1].elevation
    if elevation_diff > 0: #ascending
        ascent += elevation_diff
    else:
        descent += abs(elevation_diff)

print(f"Total ascent: {ascent} meters")
print(f"Total descent: {descent} meters")

I got the answers:

Total ascent: 1380.1978556642018 meters Total descent: 1679.6634870225648 meters

The reason you're seeing these values is because of all the little ups and downs in between, which the sites are adding up faithfully. It's possible the ups and downs were not very obvious over large distances. If you had a lot fewer points you'd get a much more direct value, as in, just measuring the lowest/highest points, but also potentially inaccurate.

I think what you're after is a bit more difficult (for me). There's a technique to filter out and smoothen these kinds of data where there's lots of noise (in this case the noise is the little ups and downs) and maybe it can apply here. It's called Savitzky Golay filter. I'm not a data scientist so I don't really understand it. But I did find code for it and slapped my keyboard till it did something:

import gpxpy
import numpy as np
from scipy.signal import savgol_filter

with open('20230718.gpx', 'r') as gpx_file:
    gpx = gpxpy.parse(gpx_file)

track_points = []
for track in gpx.tracks:
    for segment in track.segments:
        track_points.extend(segment.points)
    elevations = np.array([point.elevation for point in track_points])
# convert     
smoothed_elevations = savgol_filter(elevations, window_length=31, polyorder=2)

ascent = 0
descent = 0

for i in range(1, len(smoothed_elevations)):
    elevation_diff = smoothed_elevations[i] - smoothed_elevations[i - 1]
    if elevation_diff > 0:
        ascent += elevation_diff
    else:
        descent += abs(elevation_diff)

print(f"Total ascent: {ascent} meters")
print(f"Total descent: {descent} meters")

I got the answers

Total ascent: 365.3293488769491 meters Total descent: 664.7503639995823 meters

Which is closer to what you wanted. Note there's a lot of guesswork above, the window_length is how many points it takes at a time, I guess 31, and I don't know what polyorder means. Maybe play with those values.

But I don't think many sites do this probably because everyone will have a different meaning to ascent and descent.