This is a simple command line tool that helps to extract data for statistical analysis out of *.gpx
and *.tcx
files. You might want to use this program to extract data like Distance
, ElevationGain
or AverageSpeed
from a bunch of *.gpx
or *.tcx
files and store this data in a *.csv or *.json file for further analysis.
Some documentation and examples about gpsa usage.
Download the latest release executable from GitHub Release according to your operation system and copy the file to a empty folder.
On Linux, open a command line and set the file executable:
chmod 770 ./gpsa
# You may want to get the programs help
./gpsa -help
On Windows, open the command window in this folder and execute the program (may with the -help flag):
.\gpsa.exe -help
Below you can find some kind of user manual for this program.
You might want to call -help
to find out how to use the program.
~$ ./gpsa -help
./bin/gpsa: Reads in GPS track files, and writes out basic statistic data found in the track as a report
Program Version: 2.3.6-4142b3b
Usage: ./bin/gpsa [options] [files]
files
One or more track files of the following type: *.tcx, *.gpx,
Options:
-correction string
Define how to correct the elevation data read in from the track. Possible values are [steps linear none ] (default "steps")
-depth string
Define the way the program should analyse the files. Possible values are [segment file track ] (default "track")
-dont-panic
Decide if the program will exit with panic or with negative exit code in error cases. Possible values are [true false] (default true)
-help
Print help message and exit
-license
Print license information of the program and exit
-minimal-moving-speed float
The minimal speed. Distances traveled with less speed are not counted. In [m/s] (default 0.3)
-minimal-step-hight float
The minimal step hight. Only in use when "steps" elevation correction is used. In [m] (default 10)
-out-file string
Decide where to write the output. StdOut is used when not explicitly set. Supported file endings are: *.json, *.csv, . The format will be set according the given ending.
-print-csv-header
Print out a csv header line. Possible values are [true false] (default true)
-print-elevation-over-distance
Tell if "ElevationOverDistance.csv" should be created for each track. The files will be locate in tmp dir.
-skip-error-exit
Don't exit the program on track file processing errors
-std-out-format string
The output format when stdout is the used output. Ignored when out-file is given. Possible values are [JSON CSV ] (default "CSV")
-summary string
Tell if you want to get a summary report. Possible values are [only additional none ] (default "none")
-suppress-duplicate-out-put
Suppress the output of duplicate lines. Duplicates are detected by timestamps. Output with non valid time data may still contains duplicates.
-time-format string
Tell how the csv output formater should format times. Possible values are ["Mon Jan _2 15:04:05 MST 2006" "Monday, 02-Jan-06 15:04:05 MST" "2006-01-02T15:04:05Z07:00" ] (default "Monday, 02-Jan-06 15:04:05 MST")
-verbose
Run the program with verbose output
-version
Print version of the program and exit
It is also possible to pipe track file names or track file content into
Examples:
./gpsa my/test/file.gpx
./gpsa -verbose -out-file=gps-statistics.csv my/test/*.gpx
find ./testdata/valid-gpx -name "*.gpx" | ./bin/gpsa -summary=additional -out-file=./test.json
cat 01.gpx 01.tcx 03.tcx 02.gpx | ./bin/gpsa -out-file=./test.json
Simple call with one file:
~$ ./gpsa my/test/file.gpx
Name; StartTime; EndTime; TrackTime (xxhxxmxxs); Distance (km); HorizontalDistance (km); AltitudeRange (m); MinimumAltitude (m); MaximumAltitude (m); ElevationGain (m); ElevationLose (m); UpwardsDistance (km); DownwardsDistance (km); MovingTime (xxhxxmxxs); UpwardsTime (xxhxxmxxs); DownwardsTime (xxhxxmxxs); AverageSpeed (km/h); UpwardsSpeed (km/h); DownwardsSpeed (km/h);
my/test/file.gpx: 2020-01-29 09:28:06;2020-01-29T08:28:10Z; 2020-01-29T13:48:07Z; 5h19m53s; 94.75; 90.25; 1188.37; 821.61; 2009.98; 10659.34; -10884.50; 43.47; 51.00; 4h1m44s; 2h8m49s; 1h52m55s; 23.52; 20.25; 27.10;
Simple call with multiple files:
~$ ./gpsa my/test/01.gpx my/test/02.tcx my/test/03.gpx
Name; StartTime; EndTime; TrackTime (xxhxxmxxs); Distance (km); HorizontalDistance (km); AltitudeRange (m); MinimumAltitude (m); MaximumAltitude (m); ElevationGain (m); ElevationLose (m); UpwardsDistance (km); DownwardsDistance (km); MovingTime (xxhxxmxxs); UpwardsTime (xxhxxmxxs); DownwardsTime (xxhxxmxxs); AverageSpeed (km/h); UpwardsSpeed (km/h); DownwardsSpeed (km/h);
03.gpx: Tulln - Wien; not valid; not valid; not valid; 37.64; 36.12; 48.00; 158.00; 206.00; 52.00; -26.00; 17.52; 14.06; not valid; not valid; not valid; not valid; not valid; not valid;
02.gpx: 2019-08-18 11:07:40; 2019-08-18T09:11:01Z; 2019-08-18T15:47:34Z; 1h35m40s; 37.82; 37.23; 104.09; 347.02; 451.11; 263.88; -251.43;17.86; 19.76; 1h33m20s; 47m54s; 44m56s; 24.32; 22.37; 26.39;
Get statistics for a number of files into a csv output:
~$ ./gpsa -out-file=gps-statistics.csv my/test/*.gpx
Get statistics for a number of files into a csv output, with verbose comandline output:
~$ ./gpsa -verbose -out-file=gps-statistics.csv my/test/*.gpx
Call: ./gpsa -verbose -out-file=gps-statistics.csv my/test/01.gpx my/test/02.gpx my/test/03.gpx
Version: 2.0.1+7b79520
Read file: my/test/01.gpx
Read file: my/test/02.gpx
Read file: my/test/03.gpx
3 of 3 files process successfull
Get only the summary report out of a bunch of files
./bin/gpsa -summary=only my/test/*.gpx
Name; StartTime; EndTime; TrackTime (hh:mm:ss); Distance (km); HorizontalDistance (km); AltitudeRange (m); MinimumAltitude (m); MaximumAltitude (m); ElevationGain (m); ElevationLose (m); UpwardsDistance (km); DownwardsDistance (km); MovingTime (hh:mm:ss); UpwardsTime (hh:mm:ss); DownwardsTime (hh:mm:ss); AverageSpeed (km/h); UpwardsSpeed (km/h); DownwardsSpeed (km/h);
Sum:; -; -; 54:8:43.442; 775.00; 770.48; -; -; -; 7033.35; -6989.57; 309.34; 359.75; 32:47:16.514; 14:19:21.328; 13:33:19.262; -; -; -;
Average:; -; -; 2:15:21.810083333; 32.29; 32.10; 134.81; -; -; 293.06; -291.23; 12.89; 14.99; 1:21:58.188083333; 35:48.388666666; 33:53.302583333; 23.78; 21.86; 26.65;
Minimum:; Sunday, 01-Mar-20 09:27:27 UTC; Sunday, 01-Mar-20 15:11:19 UTC; 53:3; 21.13; 21.07; 63.72; 287.46; 359.73; 159.59; -141.38; 7.92; 8.79; 51:18.444; 21:56.828; 18:22.126; 21.28; 17.73; 23.75;
Maximum:; Saturday, 31-Oct-20 13:01:16 UTC; Saturday, 31-Oct-20 14:31:42 UTC; 6:4:25; 68.74; 66.54; 801.99; 486.48; 1288.47; 1747.38; -1754.86; 26.45; 34.71; 3:13:47.838; 1:29:31.416; 1:20:40.686; 25.58; 23.78; 28.73;
Get statistics from a file as json on stdout
./bin/gpsa -std-out-format=json my/test/02.gpx
{
"Statistics": [
{
"Name": "my/test/02.gpx: 2019-08-18 11:07:40",
"Data": {
"Distance": 37823.344979382266,
"HorizontalDistance": 37741.53944560436,
"MinimumAltitude": 347.02,
"MaximumAltitude": 451.11,
"ElevationGain": 263.88007,
"ElevationLose": -251.43008,
"UpwardsDistance": 17858.070360985712,
"DownwardsDistance": 19761.009730234404,
"TimeDataValid": true,
"StartTime": "2019-08-18T09:11:01Z",
"EndTime": "2019-08-18T15:47:34Z",
"MovingTime": 5600000000000,
"UpwardsTime": 2874000000000,
"DownwardsTime": 2696000000000,
"Duration": 23793000000000,
"AverageSpeed": 6.754168746318261,
"UpwardsSpeed": 6.213664008693707,
"DownwardsSpeed": 7.3297513836181025,
"AltitudeRange": 104.08999633789062
}
}
],
"Summary": null
It is also possible to pipe in some file names instead of using the file names as input parameter
find ./testdata/valid-gpx -name "*.gpx" | ./bin/gpsa -summary=additional -out-file=./test.json
And you can pipe in file contents as well
cat 01.gpx 01.tcx 03.tcx 02.gpx | ./bin/gpsa -out-file=./test.json
Below is a list of the output values and what they mean:
Name
: The name of the output line. Either read from the file, or if no name tag is set in the file it will be calculated out of the filename and the file hierarchy.StartTime
: The time the track started. not valid in case we detect no or invalid time data.EndTime
: The time the track ended. not valid in case we detect no or invalid time data.TrackTime
: The time betweenStartTime
andEndTime
. not valid in case we detect no or invalid time data.- Formatted as
hh:mm:ss
in case of csv output - Measured in
ns
(nano seconds) in case of json output
- Formatted as
Distance
: The distance of the track measured inkm
.HorizontalDistance
: The horizontal distance of the track measured inkm
. This value ignores the vertical component of the distance like most GPS tools do.AltitudeRange
: The range between the highest and the lowest point. Measured inm
.MinimumAltitude
: The altitude of the lowest point. Measured inm
.MaximumAltitude
: The altitude of the highest point. Measured inm
.ElevationGain
: The total sum of all upwards vertical distance. Measured inm
.ElevationLose
: The total sum of all downwards vertical distance. Measured inm
.UpwardsDistance
: The total sum of all distance moved upwards. Measured inkm
.DownwardsDistance
: The total sum of all distance moved downwards. Measured inkm
.MovingTime
: The time spend moving. not valid in case we detect no or invalid time data.- Formatted as
hh:mm:ss
in case of csv output - Measured in
ns
(nano seconds) in case of json output
- Formatted as
UpwardsTime
: The time spend moving upwards. not valid in case we detect no or invalid time data.- Formatted as
hh:mm:ss
in case of csv output - Measured in
ns
(nano seconds) in case of json output
- Formatted as
DownwardsTime
: The time spend downwards. not valid in case we detect no or invalid time data.- Formatted as
hh:mm:ss
in case of csv output - Measured in
ns
(nano seconds) in case of json output
- Formatted as
AverageSpeed
: The average speed. Calculated fromDistance
andMovingTime
. not valid in case we detect no or invalid time data.- Measured in
km/h
in case of csv output - Measured in
m/s
in case of json output
- Measured in
UpwardsSpeed
: The average speed during upwards movement . not valid in case we detect no or invalid time data.- Measured in
km/h
in case of csv output - Measured in
m/s
in case of json output
- Measured in
DownwardsSpeed
: The average speed during downwards movement . not valid in case we detect no or invalid time data.- Measured in
km/h
in case of csv output - Measured in
m/s
in case of json output
- Measured in
The statistic summary report will include -
(in case of csv output) or 0.0000
(in case of json output) for statistic values that make no sense. For example it will not calculate a sum out of speed values or the average out of time stamps.
To develop this software install Go v1.17 on your machine.
Use the mage base build script to build and test the project.
./build.sh build # build the project
./build.sh build test # build and run the tests for the project
./build.sh test # test the project
Remark: On Windows replace ./build.sh
with .\build.bat
If you use VS Code for GO development, you might find the following example settings useful.
The tasks.json
:
{
"version": "2.0.0",
"tasks": [
{
"label": "Build",
"type": "shell",
"command": "${workspaceRoot}/build.sh build test",
"group": {
"kind": "build",
"isDefault": true
}
},
{
"label": "Test",
"type": "shell",
"command": "${workspaceRoot}/build.sh test",
"group": {
"kind": "test",
"isDefault": true
}
}
]
}
The launch.json
:
{
"version": "0.2.0",
"configurations": [
{
"name": "debug",
"type": "go",
"request": "launch",
"mode": "debug",
"program": "${workspaceRoot}/src/tobi.backfrak.de/cmd/gpsa/main.go",
"cwd": "${workspaceRoot}",
"args": [
// "-dont-panic=false",
"-out-file=/dev/shm/test.csv",
"${workspaceRoot}/testdata/valid-gpx/02.gpx"
]
}
]
}
The settings.json
:
{
"go.gopath": "${env:GOPATH}:${workspaceFolder}",
}
The Geografic calculations are done with the haversine formula
as described here. My implementation will ignore altitude differences for distances bigger than 33km by checking the angular distance which in this case then is bigger than 0.3°. For smaller distances the program will add the altitude difference using the pythagoras theorem
.
gpsa is licensed under the Apache License, Version 2.0. May got some testfiles and ideas from gpxgo