Datenqualität
Kürzlich bin ich auf einen interessanten Blog-Beitrag von Christopher Mace gestoßen, der nicht nur tiefe Einblicke in die Struktur von GPS-Dateien gewährt, sondern auch die Schwierigkeiten beleuchtet, welche unvermeidliche Fehler bei den verschiedenen Arten der Höhenmessung mit sich bringen.
Selbst die Streckenmessung ist aufgrund der ellipsoiden Form der Erde tückisch, wenn auch die Abweichung in der Praxis nicht so gravierend ist wie bei der Höhenbestimmung. Im Kontext meiner zahlreichen MTB-Touren vergrößert sich das Problem exakter Daten durch einen oft schlechten GPS-Empfang in Wäldern oder tiefen Tälern. Die normalerweise gute barometrische Höhenmessung meines Garmin-Gerätes versagt manchmal bei einem Wetterumschwung oder auch gerne zu Beginn einer Tour während der Suche nach GPS-Empfangssignalen.

Bei einer Tour vor einigen Wochen waren wir noch nicht richtig vom Parkplatz in Bad Reichenhall gestartet, als sich die gemessene Höhe innerhalb weniger Sekunden um fast 100m erhöhte! Bei einer Rundtour müssten die Gesamtsteigung und das Gesamtgefälle eigentlich auch übereinstimmen – in der Praxis ist das aber fast nie der Fall.

Man könnte versuchen, für die Messdaten eine Fehlerkorrektur durchzuführen und sie damit zu „glätten“ oder die gemessenen Höhen durch amtliche Daten wie z.B. SRTM zu ersetzen. Doch auch diese beruhen auf einem mehr oder weniger groben Raster und auf einem ausgesetzten Singletrail kann links und rechts davon in kurzer Entferung die Höhe erheblich differieren. Daher ist man letztlich gezwungen, die selbst gemessenen Daten auf grobe Ausreiser zu prüfen und ansonsten darauf zu hoffen, dass sich Fehler in jeder Richtung in etwa ausgleichen, um das Gesamtresultat als ungefähren Schätzwert zu akzeptieren.
Pausenzeiten
Ein anderes Thema, das Christopher Mace ebenfalls behandelt, dreht sich um die Unterscheidung zwischen Aktivitäts- und Pausen-Zeiten.
Während die Gesamtzeit einer Tour aus dem GPX-Track sehr exakt aus der Differenz von Startzeit und Endzeit berechnet werden kann, lässt sich die Pausenzeit schwerer ermitteln.
Naiv gesprochen lässt sich die Pausenzeit leicht als Zeit ohne Bewegung definieren, d.h. zwischen zwei oder mehreren gemessenen Ortspunkten ist kein oder nur ein minimaler Distanz-Unterschied feststellbar.
Doch selbst ein stationäres GPS-Gerät kann durch die inhärente Ungenauigkeit des Messvorgangs im Zeitverlauf voneinander abweichende Ortsdaten ermitteln. Daher werden bei den meisten Algorithmen zur Pausenerkennung die Ruhezeiten über Schwellwerte bei der Geschwindigkeitsmessung bestimmt. Doch welche Grenzwerte sind dafür anzusetzen und sollten diese bei verschiedenen Aktivitäten nicht auch angepasst werden? Die meisten bekannten Tools wie z.B. komoot, gpx.studio oder GPXSee weisen (unterschiedliche) Pausenzeiten separat aus, wobei deren Ermittlung kaum dokumentiert und meist nicht konfigurierbar ist.


Wenigstens bei GPXSee lässt sich die Pausenerkennung konfigurieren, wobei mich das Ergebnis in der Praxis nicht überzeugen kann.

Auch das Garmin-Gerät selbst bietet eine (undokumentierte) Funktion zur Pausenerkennung an, die es veranlasst, unterhalb einer bestimmten Geschwindigkeit Messpunkte nicht im GPX-Track zu speichern.
Die minimale Geschwindigkeit beträgt bei meinem Gerät allerdings 2,43km/Std und ist damit nur bedingt tauglich für MTB-Touren in sehr steilem Gelände. Ich lasse sie daher meist ausgeschaltet.

So schwer die Ermittlung von Ruhezeiten technisch gesehen zu sein scheint, so leicht sind längere Pausen in einem GPX-Track als Punktewolken optisch zu erkennen.

Man könnte sich nun komplizierte Algorithmen ausdenken, die solche Punktewolken entdecken und entsprechend als Pausenzeiten deklarieren. Allerdings habe ich festgestellt, dass ein Schwellwert von 0,1m/Sek (entspricht ca. 0,36km/Std) bei der üblichen Berechnung über die Mindestgeschwindigkeit den tatsächlichen Pausen zumindest bei meinen Touren sehr nahe kommt! Dementsprechend habe ich diesen Wert für mein gpxstats-Programm (siehe unten) als Voreinstellung eingebaut. Selbstverständlich kann der Parameter optional verändert werden.
Steigungen
Ein Thema, das Christopher Mace in seinem Blog nicht behandelt, ist für mich als Mountainbiker allerdings von größtem Interesse – das Steigungsprofil einer geplanten Tour.
Auch hier bekleckern sich die bekannten GPX-Programme und Online-Browser nicht mit Ruhm, was sich in stark voneinander abweichenden Werten niederschlägt. Dabei ist die Formel zur Steigungs-Berechnung simpel:
Steigung in % = Höhendifferenz / Wegstrecke * 100
Damit sind wir wieder bei der Wurzel des Problems mit der unzuverlässigen Höhenmessung angelangt. Und nicht nur das – auch die Festlegung der Wegstrecke kann sich auf die Steigungsberechnung störend auswirken, wie man in der Grafik unten unschwer erkennen kann!

Vielmehr müssen Umkehrpunkte zwischen Steigung und Gefälle entdeckt und getrennt als %Steigung und %Gefälle berechnet werden. Dazu sollte eine Mindeststrecke zwischen zwei Umkehrpunkten definierbar sein. Ansonsten gerät die Berechnung zum Glücksrad, denn die GPS-Genauigkeit liegt im ungünstigsten Fall bei nur 10m. Der voreingestellte Mindestabstand beträgt daher 20m und ist konfigurierbar.
Vor einem Umkehrpunkt können auch verschieden steile Streckenabschnitte auftreten. Diese sollten daher streng genommen separat ausgewiesen werden. Vorerst präferiere ich allerdings einen einfacheren Algorithmus, der Steigungen bzw. Gefälle lediglich zwischen Umkehrpunkten berechnet. Sonst wird die Berechnung unter Berücksichtigung der oben genannten Mindeststrecke womöglich zu kleinteilig.
Das Programm
Die Anforderungen
Bevor ich auf die Implementierung eingehe, skizziere ich kurz die Anforderungen an die Software bzw. grundsätzliche Design-Entscheidungen:
- das Programm soll zur Verarbeitung einer oder mehrerer GPX-Dateien Batch-fähig sein. Dazu soll es Betriebssystem-unabhängig von der Kommandozeile aufrufbar sein und die üblichen wildcard Parameter verarbeiten können. Darüberhinaus soll es optional dazu rekursiv Verzeichnisstrukturen durchsuchen können.
- grundlegende voreingestellte Werte sollen optional durch Parameter veränderbar sein, wobei unplausible Werte abgewiesen werden. Dazu gehören:
- die Zeitzone für die zeitlichen Berechnungen von Start- und Endzeit.
- die Mindestgeschwindigkeit, unterhalb der von Pausenzeiten ausgegangen wird.
- eine Mindestdistanz für die Berechnungen von Steigung und Gefälle.
- die Angabe, ob für Distanzberechnungen ein simples 2D- oder exakteres 3D-Verfahren angewandt wird.
- eine optionale Ausgabe der ermittelten Daten in ein CSV-Format für z.B. MS-Excel.
- alternativ können die pro GPX-Datei ermittelten Daten summarisch aggregiert ausgegeben werden.
- es soll eine moderne und gängige Programmiersprache zum Einsatz kommen, die insbesondere bei der Verarbeitung von GPX-Dateien komfortable Bibliotheken zur Verfügung stellt.
- für die Implementierung soll eine ebenfalls komfortable und weit verbreitete kostenlose Entwicklungsumgebung (IDE) zum Einsatz kommen.
- das entstehende Programm soll auf github als OPEN SOURCE gehostet werden können.
- für einen größeren Nutzerkreis sollen die Ausgaben in englischer Sprache erfolgen. Eine Erweiterung für Mehrsprachigkeit ist möglich, aber derzeit nicht vorgesehen.
- die ausgegebenen Werte sollen gleichwohl an das metrische System angepasst sein.
- die interne und externe Dokumentation soll auf englisch erfolgen. Damit ist die Software für die internationale Entwicklergemeinde leichter zugänglich.
- die Benutzung des Programms soll möglichst ohne komplizierte Installation von zusätzlicher Software out of the box durchführbar sein.
GPXSTATS
Implementierung
Da der Blog von Christopher Mace mein Ausgangspunkt war, lag es nahe, als Programmiersprache ebenfalls Python samt der gut gewarteten gpxpy-Bibliothek zu nutzen.
Die entstandene Software habe ich auf https://github.com/peter-m-kuehn/gpxstats als OPEN SOURCE veröffentlicht. Sie kann daher frei genutzt und/oder weiterentwickelt werden.
Zur bequemen Nutzung des Programms kann es als Binärprogrammpaket einfach heruntergeladen und ausgeführt werden. Hierzu wurde von mir pyinstaller verwendet.
Für die Entwicklung habe ich das kostenlose Visual Studio Code von Microsoft verwendet, eine traumhaft komfortable KI-gestützte Entwicklungsumgebung mit direkter github-Anbindung. Damit wurde das Programmieren fast zum Kinderspiel 🤗
Der Codeumfang ist relativ gering (<700 Zeilen) und das Programm selbst einigermaßen modular aufgebaut, so dass ich hier nicht weiter auf technische Details zur Implementation eingehen möchte. Lediglich die Steigungsberechnungen sind durch die Berücksichtigung der Umkehrpunkte und Mindestdistanzen etwas komplizierter im Ablauf, dafür aber (hoffentlich) ausreichend kommentiert und übersichtlich strukturiert.
Anwendung
In Anlehnung an einen bekannten Spruch hier ein paar Anwendungs-Beispiele aus meinem persönlichen Fundus:
Ich möchte etwas über die Handhabung von gpxstats erfahren:
n:\windos\garmin oregon 700\Tracks\gefahrene tracks\2026>gpxstats -h
usage: gpxstats [-h] (-f FILES [FILES ...] | -d DIRECTORY) [-r] [-m MINMPS] [-md MINDISTANCEFORSLOPECALCULATION]
[-t TIMEZONE] [-g {2d,3d,2D,3D}] [-c CSV] [-s] [-v]
options:
-h, --help show this help message and exit
-f, --files FILES [FILES ...]
gpx file(s) to process
-d, --directory DIRECTORY
directory containing gpx files to process
-r, --recursive search for gpx files recursively in subdirectories
-m, --MinMPS MINMPS minimum meters per second for moving time calculation (default: 0.1 m/s)
-md, --MinDistanceForSlopeCalculation MINDISTANCEFORSLOPECALCULATION
minimum distance in meters to consider for slope calculations (default: 20.0 m)
-t, --timezone TIMEZONE
timezone for date/time calculations (default: Europe/Berlin)
-g, --geodesic_calc_method {2d,3d,2D,3D}
method for geodesic distance calculation: '2d' or '3d' (default: 3d)
-c, --csv CSV output results to CSV file
-s, --sumTotal sum total results only, without individual file results
-v, --verbose display verbose output
Ich möchte gleichzeitig die Auswertungsdaten meiner letzten Tour (mit relativ großen Steigungs-/Gefäll-Strecken wegen des umfangreichen HIKE-Anteils) sowie die Werte der voreingestellten Parameter sehen:
n:\windos\garmin oregon 700\Tracks\gefahrene tracks\2026>gpxstats -v -f "2026-09-30 16.37.19.gpx"
Options:
files: ['2026-09-30 16.37.19.gpx']
directory: None
recursive: False
min_mps: 0.1
timezone: Europe/Berlin
geodesic_calc_method: 3d
MinDistanceForSlopeCalculation: 20.0
csv: None
verbose: True
sumTotal: False
Processing file: 2026-09-30 16.37.19.gpx...
Processing track: 2026-09-30 16:37:19...
1.GPX-File: 2026-09-30 16.37.19.gpx
1.Track: 2026-09-30 16:37:19
Distance (km): 22.67
Start Time: 2026-09-30 09:05:04+02:00
End Time: 2026-09-30 16:37:18+02:00
Activity Time: 7:32:14
Moving Time: 5:49:05
Break Time: 1:43:09
Max Speed (km/h): 88.38
Avg Speed (km/h): 3.85
Elevation Gain (m): 1518.00
Elevation Loss (m): -1394.90
Max Height (m): 2362.20
Distance (km) Slope > 25%: 1.52 (6.69%)
Distance (km) Slope > 20%: 0.27 (1.20%)
Distance (km) Slope > 15%: 0.73 (3.23%)
Distance (km) Slope > 10%: 2.95 (13.03%)
Distance (km) Slope 0-10%: 6.73 (29.69%)
Distance (km) Slope < 0%: 5.14 (22.69%)
Distance (km) Slope < -10%: 3.66 (16.15%)
Distance (km) Slope < -20%: 0.82 (3.64%)
Distance (km) Slope < -30%: 0.83 (3.68%)
Ich möchte eine summarische Auswertung aller meiner bisher in 2026 durchgeführten Touren sehen:
n:\windos\garmin oregon 700\Tracks\gefahrene tracks\2026>gpxstats -s -f "2026*.gpx"
Total Results:
GPX File count: 72.00
Track count: 72.00
Total distance (km): 3156.87
Total minimum start time: 07:56:06
Total maximum end time: 20:44:28
Total activity time: 26 days 19:50:07
Total moving time: 14 days 16:08:57
Total break time: 12 days 03:41:10
Total maximum speed (km/h): 92.92
Total average speed (km/h): 8.97
Total elevation gain (m): 79807.65
Total elevation loss (m): -75938.63
Total maximum height (m): 2362.20
Total distance (km) Slope > 25% 13.10
Total distance (km) Slope > 20% 14.13
Total distance (km) Slope > 15% 50.93
Total distance (km) Slope > 10% 163.10
Total distance (km) Slope 0-10% 1553.11
Total distance (km) Slope < 0% 1130.01
Total distance (km) Slope < -10% 188.11
Total distance (km) Slope < -20% 36.78
Total distance (km) Slope < -30% 7.61
Das soll vorerst genügen – viel Spaß beim Benutzen und Weiterentwickeln!
ps: gerne auch mit Feedback😃