目的
MapboxのMap Matching APIを用いて、GPSデータを補正するツールを作成してみました。
Map Matching API
- MapboxのAPIのうち、Navigation serviceに分類されるMap Matching APIを使用しています。
- Map Matching APIは、誤差が含まれるGPSデータ(緯度、経度)を道路ネットワーク上にスナップし、確からしい位置に補正するAPIになります。
実行環境
- この記事ではPython3、MapboxのMap Matching APIを使用しています。
- MapboxのMap Matching APIを使用するには、Access Tokensが必要になります。
- Mapboxのサイトよりアカウントを登録すると、自動的に Access Tokens が発行されます。
- このAccess Tokensを使用し、各種APIをコールすることができます。
- Mapbox は、従量課金になるので詳しい料金体系についてはMapboxの Pricing ページをご確認ください。
- なお、毎月50,000リクエストまでは無料枠が設定されていますので、大量にリクエストしなければ課金されることはありません。
前提条件
使用データ
- 使用データは、マラソン大会走行時に手首に装着したGarminウォッチで取得したGPSデータを用います。
- GPSデータは、適宜、ご用意ください。
実行方法
入力設定
- 入力CSVファイルにGPSデータ(緯度、経度)を入力してください。
実行
- 入力CSVファイル、出力CSVファイル、api_token(Access Tokens)を入力してください。
- 「Map Matching API URL」は、変更しないでください。
- Pythonスクリプトを実行してください。
MapboxMapMatchingAPI.py
import os
import csv
import json
import datetime
import time
import configparser
import requests
# 入力CSVファイル指定
input_csvfile = "入力CSVファイルを入力してください。"
# 出力CSVファイル指定
output_csvfile = "出力CSVファイルを入力してください。"
# Map Matching API URL※変更しないでください。
api_url = "https://api.mapbox.com/matching/v5/mapbox/driving/"
# Mapbox Access token
api_token = "Access tokenを入力してください。"
# 作業用リスト
data = []
wklst = []
# 入力CSVファイルを作業用リストへセット
with open(input_csvfile) as f:
#ヘッダー行をスキップ
h = next(csv.reader(f))
for v in csv.reader(f):
data.append(v)
for i in range(len(data) -1):
wklst.append([data[i][0],data[i][1],data[i+1][0],data[i+1][1]])
# print(wklst)
# 出力CSVファイルの存在チェック(ヘッダー有無の判断)
if(os.path.exists(output_csvfile)):
header_flg = 0
else:
header_flg = 1
# 作業用リストよりMap Matching APIへリクエストし、結果を出力CSVファイルに書き込む
with open(output_csvfile, 'a', encoding='shift_jis') as output_csvfile_fp:
fieldnames = ['bef_lat','bef_lng','aft_lat','aft_lng']
csvfile_writer = csv.DictWriter(output_csvfile_fp, fieldnames=fieldnames,lineterminator='\n')
# 出力CSVファイル新規作成時、ヘッダー出力
if header_flg == 1:
csvfile_writer.writeheader()
header_flg == 0
print(len(wklst))
for i in range(len(wklst)):
# print(wklst[i])
# Map Matching APIのパラメータ生成
origins = wklst[i][1] + ','+ wklst[i][0]
destinations = wklst[i][3] + ','+ wklst[i][2]
params = {
'radiuses':'50;50',
'access_token': api_token
}
# Map Matching APIにリクエスト
raw_response = requests.get(api_url + origins + ';' + destinations, params)
parsed_response = json.loads(raw_response.text)
parsed_response_json = json.dumps(parsed_response, indent=4)
# print(parsed_response_json)
breakpoint
# JSONから要素を取り出す
if parsed_response['code'] == 'Ok':
lng1 = parsed_response['tracepoints'][0]['location'][0]
lat1 = parsed_response['tracepoints'][0]['location'][1]
lng2 = parsed_response['tracepoints'][1]['location'][0]
lat2 = parsed_response['tracepoints'][1]['location'][1]
else:
lng1 = None
lat1 = None
lng2 = None
lat2 = None
# 出力CSVファイルに書き込み
csvfile_writer.writerow({
'bef_lat': wklst[i][0],
'bef_lng': wklst[i][1],
'aft_lat': lat1,
'aft_lng': lng1
})
print(wklst[i][0],wklst[i][1],lat1,lng1)
print(u'処理終了')
実行結果
- 補正前のGPSデータ(緯度、経度)は、1列目と2列目になります。
- 補正後のGPSデータ(緯度、経度)は、3列目と4列目になります。
- 実行結果をQGISで可視化すると以下のようになります。
- 青いポイントが補正前のGPSデータ(緯度、経度)、赤いポイントが補正後のGPSデータ(緯度、経度)になります。
- 補正前は道路上から外れていた青いポイントが、補正後は道路上にスナップされ、確からしい位置(赤いポイント)に補正されています。
※背景地図には、国土地理院の地理院タイル(淡色地図)を使用しています。
留意事項
※無料枠を超えてAPIを使用すると課金されますのでご注意ください(>_<)