最近RaspberryPi沼にハマりかけているgoldear@goldear820です。
前回、ようやくGPSロガーとして形になりましたが、記録したCSVファイルではGoogleMapにインポートすることができません。
GPS情報をわざわざ記録するのは「地図に重ね合わせて楽しみたい」というものなので、このままでは非常に残念なCSVファイルだけが残ります。
今回はCSVファイルを、GoogleMapにインポートできる形式GPXファイルに変換していきます。またRaspberryPiは特に必要としないため、python実行環境であればWindows環境でもOKです。
目次
予備知識
CSV->GPX変換するにあたり、GPXフォーマットを知っておく必要があります。大まかなフォーマットは手持ちのGPXファイルをテキストエディタで開けば大体分かります。詳細仕様については以下を確認してください。
GPSで取得した位置情報はDMM(Degree Minute)でCSVに記録されますが、GPX形式ではDEG(Degree)で記述するため変換が必要です。以下のページが参考になり、分かりやすいです。
GPXファイルはXML記述されており、pythonに組み込まれている標準ライブラリを「ElementTree」を用いてGPXファイルを生成します。以下がpython公式のドキュメントになります。
ElementTreeでGPXファイルを生成すると改行が入らないため、書込みだけはpythonに組み込まれている標準ライブラリ「minidom」を用います。以下がpython公式のドキュメントになります。
実装
pythonプログラムの大まかな内容としては、CSVファイルを指定して、ファイル先頭から一行読み取り、経度緯度をtrkptの属性として付与し、高度・速度をサブ要素の値として記述します。これをCSVファイル末尾まで繰り返すことでGPXファイルに変換します。
CSVに保存したGPS情報群は第02回のソースコードに記載してあるので参考にどうぞ。
#!/usr/bin/env python3 # encoding: utf-8 ## common import os from datetime import datetime as dt import xml.etree.ElementTree as ET import xml.dom.minidom as md import re INPUT_CSV = "2024-01-01.csv" OUTPUT_GPX = "2024-01-01.gpx" GPX_VER = "1.1" CREATOR = "goldear - https://goldear.net" XMLNS_XSD = "https://www.w3.org/2001/XMLSchema" XMLNS_XSI = "https://www.w3.org/2001/XMLSchema-instance" XSI_SL = "http://www.topografix.com/GPX/1/1/gpx.xsd" #################################### # SUB FUNCTION def get_date(file): timestamp = os.path.getmtime(file) date = dt.fromtimestamp(timestamp) return date def dmm2deg(dmm_lat, dmm_lon): # Convert DMM(Degree Minute) -> DEG(Degree) ## Latitude: decimal -90.0 <= value <=90.0 d_lat = dmm_lat[0:2] int_m_lat = str(dmm_lat[3:5]) sub_m_lat = "." + str(dmm_lat[5:]) float_m_lat = float(int_m_lat + sub_m_lat) m2d_lat = float_m_lat/60 lat = float(d_lat) + m2d_lat deg_lat = str(lat) ## Longitude: decimal -180.0 <= value <=180.0 d_lon = dmm_lon[0:3] int_m_lon = str(dmm_lon[4:6]) sub_m_lon = "." + str(dmm_lon[6:]) float_m_lon = float(int_m_lon + sub_m_lon) m2d_lon = float_m_lon/60 lon = float(d_lon) + m2d_lon deg_lon = str(lon) return deg_lat, deg_lon #################################### # MAIN FUNCTION def csv2gpx(): ## Get time date = get_date(INPUT_CSV) s_date = date.strftime("%y-%m-%d") s_time = date.strftime("%H:%M:%S") ## Create ROOT root = ET.Element("gpx") root.set("version", GPX_VER) root.set("creator", CREATOR) root.set("xmlns:xsd", XMLNS_XSD) root.set("xmlns:xsi", XMLNS_XSI) root.set("xsi:schemaLocation", XSI_SL) ## Set Time l_time = ET.SubElement(root, "time") l_time.text = str("20" + s_date + "T" + s_time + "+09:00") ## Create truck l_trk = ET.SubElement(root, "trk") ## Create truck segment data l_trkseg = ET.SubElement(l_trk, "trkseg") ## Read Log 1-line with open(INPUT_CSV, mode="r", encoding="utf-8") as f_csv: while True: l_gpslog = f_csv.readline() if not l_gpslog: break else: ### split ls_gpslog = re.split("[,*]",l_gpslog) if ls_gpslog[2] == "." or ls_gpslog[4] == ".": continue ## Create truck point l_trkpt= ET.SubElement(l_trkseg, "trkpt") ## Convert DMM -> DEG lat, lon = dmm2deg(ls_gpslog[2], ls_gpslog[4]) l_trkpt.set("lat", lat[0:10] ) l_trkpt.set("lon", lon[0:11] ) ## Create Elevation l_ele = ET.SubElement(l_trkpt, "ele") l_ele.text = ls_gpslog[5] ## Create time l_tr_time = ET.SubElement(l_trkpt, "time") l_tr_time.text = ls_gpslog[7][0:20] ## Create speed l_speed = ET.SubElement(l_trkpt, "speed") l_speed.text = ls_gpslog[6] ## Organize XML XML = md.parseString(ET.tostring(root, "utf-8")) ## Write with open(OUTPUT_GPX, "w") as f: XML.writexml(f, encoding="utf-8", newl="\n", indent="", addindent=" ") if __name__ == "__main__": csv2gpx()
Google Map にインポートしてみる
テスト用に擬似位置情報を用いて、pythonコードを実行してCSVファイルをGPXファイルに変換してみます。
場所はぱらのま第02巻Line.07の描写を参考に抽出しました。
亀戸天神: 35.421017 139.491443
高円寺 : 35.421267 139.391011
有明 : 35.375419 139.473294
王子神社: 35.451306 139.441022
厳島神社: 35.373338 139.405905
2024-01-01 09:00:00,N,35.421017,E,139.491443,100,100,2024-01-01T00:00:00.000Z 2024-01-01 09:00:01,N,35.421267,E,139.391011,101,101,2024-01-01T00:00:01.000Z 2024-01-01 09:00:02,N,35.375419,E,139.473294,102,102,2024-01-01T00:00:02.000Z 2024-01-01 09:00:03,N,35.451306,E,139.441022,103,103,2024-01-01T00:00:03.000Z 2024-01-01 09:00:04,N,35.373338,E,139.405905,103,103,2024-01-01T00:00:03.000Z 2024-01-01 09:00:05,N,35.421017,E,139.491443,104,104,2024-01-01T00:00:04.000Z
変換したGPXファイルをGoogle Map にインポートしてみました。バッチリ変換できています。
GoogleMapへのインポート方法は以下にまとめてありますので参考にどうぞ。
まとめ
細かい部分(入出力ファイルを指定するなど)は改善の余地ありですが、CSV -> GPXファイル変換の基礎は完成しました。
次はGPSロガーの本体のケーシングやさらなる小型化を図っていきます。もしかすると Zero2 W ではなく Pico W で作り直すかもしれないです。
コメント