diff options
author | typebrook <typebrook@gmail.com> | 2019-12-05 16:41:38 +0800 |
---|---|---|
committer | typebrook <typebrook@gmail.com> | 2019-12-05 16:41:38 +0800 |
commit | 5913313627a13930dad13102ea79915e7f48bf58 (patch) | |
tree | 3425ae2aaada2546b2034e8ea1aec28219bc85d3 /scripts | |
parent | 9244e2ff62956b7563b06ac561ce84c10b8ca064 (diff) |
update
Diffstat (limited to 'scripts')
-rwxr-xr-x | scripts/match-road.sh | 51 |
1 files changed, 32 insertions, 19 deletions
diff --git a/scripts/match-road.sh b/scripts/match-road.sh index d59064a..6c2f242 100755 --- a/scripts/match-road.sh +++ b/scripts/match-road.sh | |||
@@ -20,15 +20,15 @@ set -e | |||
20 | # put yout Mapbox token here | 20 | # put yout Mapbox token here |
21 | ACCESS_TOKEN=$(cat ~/settings/tokens/mapbox) | 21 | ACCESS_TOKEN=$(cat ~/settings/tokens/mapbox) |
22 | # number of coordinates for each Mapbox Map Matching API request, Maximum value is 100 | 22 | # number of coordinates for each Mapbox Map Matching API request, Maximum value is 100 |
23 | LIMIT=10 | 23 | LIMIT=50 |
24 | # define the lowest confidence of accepted matched points | 24 | # define the lowest confidence of accepted matched points |
25 | THRESHOLD=0.9 | 25 | THRESHOLD=0.7 |
26 | 26 | ||
27 | ORIGIN_DATA=/tmp/$(basename $1).origin | 27 | ORIGIN_DATA=/tmp/$(basename $1).origin |
28 | RESPONSE=$(basename $1).response | 28 | MATCHED=/tmp/$(basename $1).matched |
29 | 29 | ||
30 | # extract data from the given gpx file, dump coordindate and time with the following format: | 30 | # extract data from the given gpx file, dump data with format [coordindate] [time_to_second], like: |
31 | # [121.0179739,14.5515336] 1984-01-01T08:00:46.234 | 31 | # [121.0179739,14.5515336] 1984-01-01T08:00:46 |
32 | function get_data() { | 32 | function get_data() { |
33 | sed -nr '/<trkpt /, /<\/trkpt>/ {H; /<\/trkpt>/ {x; s/\n/ /g; p; s/.*//; x}}' $1 |\ | 33 | sed -nr '/<trkpt /, /<\/trkpt>/ {H; /<\/trkpt>/ {x; s/\n/ /g; p; s/.*//; x}}' $1 |\ |
34 | sed -nr 'h; s/.*lon="([^"]+).*/\1/; H; g | 34 | sed -nr 'h; s/.*lon="([^"]+).*/\1/; H; g |
@@ -43,23 +43,40 @@ function get_data() { | |||
43 | awk '!_[$2]++' | 43 | awk '!_[$2]++' |
44 | } | 44 | } |
45 | 45 | ||
46 | # Read data like the following to make GeoJSON object for Map Matching API: | 46 | # Output GeoJSON object for Map Matching API from STDIN with format [coordinate] [time], like: |
47 | # [121.0179739,14.5515336] 1984-01-01T08:00:46.234 | 47 | # [121.0179739,14.5515336] 1984-01-01T08:00:46 |
48 | function make_geojson() { | 48 | function make_geojson() { |
49 | # change input to format like: [[lon, lat], time] | 49 | # change input to format like: [[lon, lat], time] |
50 | awk '{printf("[%s,\"%s\"]\n", $1, $2)}' |\ | 50 | awk '{printf("[%s,\"%s\"]\n", $1, $2)}' |\ |
51 | jq '[inputs] | {type: "Feature", properties: {coordTimes: (map(.[1]))}, geometry: {type: "LineString", coordinates: map(.[0])}}' | 51 | jq '[inputs] | {type: "Feature", properties: {coordTimes: (map(.[1]))}, geometry: {type: "LineString", coordinates: map(.[0])}}' |
52 | } | 52 | } |
53 | 53 | ||
54 | # Read GeoJSON body from input, and return result from Mapbox Map Matching API | 54 | # Read GeoJSON body from STDIN, and return result from Mapbox Map Matching API |
55 | function query_matched_road() { | 55 | function query_matched_road() { |
56 | curl -X POST -s --data @- \ | 56 | curl -X POST -s --data @- \ |
57 | --header "Content-Type:application/json" \ | 57 | --header "Content-Type:application/json" \ |
58 | https://api.mapbox.com/matching/v4/mapbox.driving.json?access_token=$ACCESS_TOKEN | 58 | https://api.mapbox.com/matching/v4/mapbox.driving.json?access_token=$ACCESS_TOKEN |
59 | } | 59 | } |
60 | 60 | ||
61 | # Get valid data from Map Matching API response | ||
62 | # output format is [coordinates] [index-of-original-data], like: | ||
63 | # [121.0179739,14.5515336] 35 | ||
64 | # If the point is newly added, the index would be -1, like | ||
65 | # [121.0189339,14.5525931] -1 | ||
61 | function get_valid_data() { | 66 | function get_valid_data() { |
62 | jq ".features[] | select(.properties.confidence >= $THRESHOLD)" | 67 | VALID_DATA=$(jq ".features[] | select(.properties.confidence >= $THRESHOLD)") |
68 | |||
69 | echo $VALID_DATA |\ | ||
70 | jq -cr '.properties | [.matchedPoints, (.indices | map(.+1))] | transpose[] | "\(.[0]) \(.[1])"' > $MATCHED | ||
71 | |||
72 | echo $VALID_DATA | jq -c '.geometry.coordinates[]' |\ | ||
73 | while read point; do | ||
74 | if head -1 $MATCHED| grep -F $point; then | ||
75 | sed -i 1d $MATCHED | ||
76 | else | ||
77 | echo $point | ||
78 | fi | ||
79 | done | ||
63 | } | 80 | } |
64 | 81 | ||
65 | get_data $1 > $ORIGIN_DATA | 82 | get_data $1 > $ORIGIN_DATA |
@@ -67,29 +84,25 @@ get_data $1 > $ORIGIN_DATA | |||
67 | # Consume raw data with serveral request | 84 | # Consume raw data with serveral request |
68 | while [ -s $ORIGIN_DATA ]; do | 85 | while [ -s $ORIGIN_DATA ]; do |
69 | 86 | ||
70 | head -$LIMIT $ORIGIN_DATA | make_geojson | query_matched_road > $RESPONSE | 87 | head -$LIMIT $ORIGIN_DATA | make_geojson | query_matched_road | get_valid_data |
71 | cat $RESPONSE | get_valid_data | ||
72 | exit 0 | 88 | exit 0 |
73 | |||
74 | # Put existing timestamps to matched points, and interpolate new timestamps into new points | 89 | # Put existing timestamps to matched points, and interpolate new timestamps into new points |
75 | join -a1 \ | ||
76 | <(jq -c '.features[0].geometry.coordinates[]' $RESPONSE) \ | ||
77 | <(jq -cr '.features[0].properties | [.matchedPoints, (.indices | map(.+1))] | transpose[] | "\(.[0]) \(.[1])"' $RESPONSE) |\ | ||
78 | sed '/ / !s/$/ -1/' |\ | ||
79 | while read coor index; do | 90 | while read coor index; do |
80 | if [ $index -gt -1 ]; then | 91 | if [ $index -gt -1 ]; then |
81 | echo $coor $(sed -n "$index p" $ORIGIN_DATA | cut -d' ' -f1 | date -f - +%s) | 92 | echo $coor $(sed -n "$index p" $ORIGIN_DATA | cut -d' ' -f2 | date -f - +%s) |
82 | else | 93 | else |
83 | echo $coor $index | 94 | echo $coor $index |
84 | fi | 95 | fi |
85 | done |\ | 96 | done |
97 | exit 0 | ||
98 | # interpolate timestamps to newly added points | ||
86 | 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)}}}' |\ | 99 | 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)}}}' |\ |
87 | while read coor unix_time; do | 100 | while read coor unix_time; do |
88 | # Transform unix timestamp into human readable time format, like following: | 101 | # Transform unix timestamp into human readable time format, like following: |
89 | # Transform [121.018088,14.5516] 18.50 | 102 | # Transform [121.018088,14.5516] 18.50 |
90 | # Into [121.018088,14.5516] 1970-01-01T08:00:18.50Z | 103 | # Into [121.018088,14.5516] 1970-01-01T08:00:18.50Z |
91 | echo $coor $(date -d @$unix_time +'%Y-%m-%dT%H:%M:%S.%2NZ') | 104 | echo $coor $(date -d @$unix_time +'%Y-%m-%dT%H:%M:%S.%2NZ') |
92 | done | tee /dev/tty | 105 | done |
93 | 106 | ||
94 | # Remove processed raw data | 107 | # Remove processed raw data |
95 | sed -i "1,$LIMIT d" $ORIGIN_DATA | 108 | sed -i "1,$LIMIT d" $ORIGIN_DATA |