aboutsummaryrefslogtreecommitdiffhomepage
path: root/scripts/match-road.sh
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/match-road.sh')
-rwxr-xr-xscripts/match-road.sh148
1 files changed, 0 insertions, 148 deletions
diff --git a/scripts/match-road.sh b/scripts/match-road.sh
deleted file mode 100755
index d9beaae..0000000
--- a/scripts/match-road.sh
+++ /dev/null
@@ -1,148 +0,0 @@
1#!/usr/bin/env bash
2#
3# Author: Pham
4#
5# This script accepts a single GPX file as parameter and
6# output the processed GPX body to STDOUT, using Mapbox Map Matching API v4.
7# read doc at: https://docs.mapbox.com/api/legacy/map-matching-v4/
8#
9# Example:
10#
11# match-road.sh raw.gpx > new.gpx
12#
13# Hint:
14#
15# Remember to put Mapbox Access Token at the top!
16
17#set -x
18set -e
19
20# put yout Mapbox token here
21ACCESS_TOKEN=$(cat ~/settings/tokens/mapbox)
22# number of coordinates for each Mapbox Map Matching API request, Maximum value is 100
23LIMIT=100
24# define the lowest confidence of accepted matched points
25THRESHOLD=0.0001
26
27if [[ -z $1 ]]; then echo "You need to give a gpx file!"; exit 1; fi
28ORIGIN_DATA=/tmp/$(basename $1).origin
29RESPONSES=/tmp/$(basename $1).responses && true > $RESPONSES
30MATCHED=/tmp/$(basename $1).matched
31
32# extract data from the given gpx file
33# only keep first point and remove the rest which in the same "second"
34# input: [gpx format]
35# output: [121.0179739,14.5515336] 1984-01-01T08:00:46
36get_data() {
37 sed -nr '/<trkpt /, /<\/trkpt>/ {H; /<\/trkpt>/ {x; s/\n/ /g; p; s/.*//; x}}' $1 |
38 sed -nr 'h; s/.*lon="([^"]+).*/\1/; H; g
39 s/.*lat="([^"]+).*/\1/; H; g
40 # If trkpt has no time, leave it blank
41 /time/ {
42 s/.*<time>([^.]+).*<\/time>.*/\1/
43 H; g
44 }
45 s/^[^\n]+\n//; s/\n/ /g; p' |
46 sed -r 's/^([^ ]+) ([^ ]+)/[\1,\2]/' |
47 awk '!_[$2]++'
48}
49
50# Output GeoJSON object for Map Matching API
51# input: [121.0179739,14.5515336] 1984-01-01T08:00:46
52# output: {type: "Feature", properties: {coordTimes: [...]}, geometry: {type: "LineString", coordinates: [...]}}
53make_geojson() {
54 # change input to format like: [[lon, lat], time]
55 awk '{printf("[%s,\"%s\"]\n", $1, $2)}' |
56 jq '[inputs] | {type: "Feature", geometry: {type: "LineString", coordinates: map(.[0])}, properties: {coordTimes: (map(.[1]))}}'
57}
58
59# Read GeoJSON body from STDIN, and return result from Mapbox Map Matching API
60query_matched_points() {
61 curl -X POST -s --data @- \
62 --header "Content-Type:application/json" \
63 https://api.mapbox.com/matching/v4/mapbox.driving.json?access_token=$ACCESS_TOKEN
64}
65
66# Get valid data from Map Matching API response
67# output format is [coordinates] [index-of-original-data], like:
68# [121.0179739,14.5515336] 35
69# If the point is newly added, the index would be -1, like
70# [121.0189339,14.5525931] -1
71validate_matched_points() {
72 VALID_DATA=$(jq ".features[] | if(.properties.confidence < $THRESHOLD) then .geometry.coordinates=(.properties.indices|map(.+1)) else . end")
73
74 echo $VALID_DATA |
75 jq -cr '.properties | [.matchedPoints, (.indices | map(.+1))] | transpose[] | "\(.[0]) \(.[1])"' > $MATCHED
76
77 echo $VALID_DATA | jq -c '.geometry.coordinates[]' |
78 while read point; do
79 if [[ ${point:0:1} != '[' ]]; then
80 echo $(sed -n "$point p" $ORIGIN_DATA) | while read coor time; do echo $coor $(date -d $time +%s); done
81 sed -i 1d $MATCHED
82 elif head -1 $MATCHED | grep -F $point > /dev/null; then
83 index=$(head -1 $MATCHED | cut -d' ' -f2)
84 echo $point $(sed -n "$index p" $ORIGIN_DATA | cut -d' ' -f2 | date -f - +%s)
85 sed -i 1d $MATCHED
86 else
87 echo $point -1
88 fi
89 done
90}
91
92# Put existing timestamps to matched points, and interpolate new timestamps into new points
93complete_data() {
94 # interpolate timestamps to newly added points
95 awk '{COOR[NR][0]=$1; N++; COOR[NR][1]=$2} END{for (i=1; i<=N; i++) {printf COOR[i][0]; if (COOR[i][1] != -1) {print " "COOR[i][1]; LAST=i} else {while(COOR[i+n][1] == -1) n++; print " "COOR[LAST][1]+(COOR[i+n][1]-COOR[LAST][1])*(i-LAST)/(i+n-LAST)}}}' |
96 while read coor unix_time; do
97 # Transform unix timestamp into human readable time format, like following:
98 # Transform [121.018088,14.5516] 18.50
99 # Into [121.018088,14.5516] 1970-01-01T08:00:18.50Z
100 echo $coor $(date -d @$unix_time +'%Y-%m-%dT%H:%M:%S.%2NZ')
101 done
102}
103
104# Make GPX format for output
105# Take input with format: [lon,lat] [time]
106make_gpx() {
107 sed -E 's/\[([^,]+),([^,]+)\] (.*)/ <trkpt lon="\1" lat="\2"><time>\3<\/time><\/trkpt>/' |
108 sed "1i \
109<gpx version=\"1.1\" creator=\"Garmin Connect\"\n\
110 xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.garmin.com/xmlschemas/GpxExtensions/v3 http://www.garmin.com/xmlschemas/GpxExtensionsv3.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v1 http://www.garmin.com/xmlschemas/TrackPointExtensionv1.xsd\"\n\
111 xmlns=\"http://www.topografix.com/GPX/1/1\"\n\
112 xmlns:gpxtpx=\"http://www.garmin.com/xmlschemas/TrackPointExtension/v1\"\n\
113 xmlns:gpxx=\"http://www.garmin.com/xmlschemas/GpxExtensions/v3\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n\
114 <trk>\n <trkseg>" |
115 sed "\$a \ \ \ \ <\/trkseg>\n <\/trk>\n<\/gpx>"
116}
117
118get_data $1 > $ORIGIN_DATA
119
120#RAW_REQUEST=$(basename $1 | tr '.' '_')_request.geojson
121#cat $ORIGIN_DATA | make_geojson | jq '.properties.stroke="#ff0000"' > $RAW_REQUEST
122
123# Consume raw data with serveral request
124while [ -s $ORIGIN_DATA ]; do
125 # Take original data by limited points for each time: [121.0179739,14.5515336] 1984-01-01T08:00:46
126 # Make geojson body: {type: "Feature", properties: {coordTimes: [...]}, geometry: {type: "LineString", coordinates: [...]}}
127 # Call Mapbox Map Matching API: {geometry: {coordinates: [...]}, properties: {confidence: 0.9, matching: [...], indices: [...]}}
128 # Get valid point and index by confidence value: [121.0179739,14.5515336] 5
129 # complete_data
130 head -$LIMIT $ORIGIN_DATA |
131 make_geojson |
132 query_matched_points |
133 tee -a $RESPONSES |
134 validate_matched_points |
135 complete_data
136
137 # Remove processed raw data
138 sed -i "1,$LIMIT d" $ORIGIN_DATA
139done | make_gpx
140#make_geojson > test.geojson
141
142#RAW_RESPONSE=$(basename $1 | tr '.' '_')_response.geojson
143#MATCHED_POINTS=$(basename $1 | tr '.' '_')_matched.geojson
144#jq . $RESPONSES | jq -s '.[0].features=[.[]|.features[]] | .[0] | del(.code) | .features=(.features|map(.properties.stroke="#00ff00"))' > $RAW_RESPONSE
145#jq ".features=(.features|map(select(.properties.confidence>=$THRESHOLD).geometry.coordinates=.properties.matchedPoints)|map(.properties.stroke=\"#0000ff\"))" $RAW_RESPONSE > $MATCHED_POINTS
146#
147#DEBUG=$(basename $1 | tr '.' '_')_total.geojson
148#cat $RAW_REQUEST $RAW_RESPONSE $MATCHED_POINTS | jq -s '{type: "FeatureCollection", features: ([.[0]] + .[1].features + .[2].features)}' > $DEBUG