昨年から自転車で遠出をする機会が増えて、走ったルートを Garmin Edge で記録していた。Garmin Edge の記録は Garmin Connect や Strava 等の Web サービスで可視化できる
記録が増えてくると 過去の記録を全部重ね合わせた1枚の地図 を作ったらおもしろいんじゃね?という疑問がでてきた。 自分の知る限りでは複数回の走行記録を表示できるサービスはないようなので自作した
(追記)
Strava で有料プランを使うとよいっぽい。後からみつかるんだよな。こういうの〜〜
Python + folium がよいかんじ
いろいろ試行錯誤してみたところ Python の folium というライブラリを使うことで 期待に沿った地図がつくれた
過去に記録した緯度・経度をプロットするだけで こんな地図になる。花弁のように青く広がっている線が、私が過去に走行した全軌跡
地図は HTML + JS で生成されていて、移動やズームできる
繰り返し通ったルートは多重の線で判別できる
画像タイルサーバーと、プロットする線の色・透明度を変更すると情報の見え方が変わる。 濃淡 によってよく通る道が表現される
昨年度に夏季休暇に秋田から仙台まで、今年は東京から仙台まで縦断旅行したが、そのような時系列も軌跡として辿ることができる (注: 私にとっては思い入れのある 夏の軌跡 も、第三者には 鍋底に張り付いたスパゲティの茹でクズ のように見えることだろう 🍝 )
赤色で箱根の峠道をプロットすると毛細血管のよう見えてグロテスク 💀 色の選択は大事だね
世界 is 広い
… とこんな地図が folium のパワーで作れる
マップのつくりかた
GitHub にコードをあげておいた。
GPX のデータがあれば以下のような手順で作れるはず
$ git clone https://github.com/hiboma/gpx-overlay $ cd gpx-overlay $ pip install -r requirements.txt # activities.zip は strava から取得する $ unzip -d activities activities.zip $ bin/overlay.py $ open overlay.html
間違い・more better な方法があれば教えていただきたい
1. GPX を用意する
自転車に限らず 緯度・経度のデータがあればなんでもよい。データが必要だ。
Garmin ユーザーであれば Garmin Connect から過去の記録を GPX
でエクスポートして、緯度経度を抜き出すことができる。Garmmin Connect では 1個ずつ手動でポチポチしないと エクスポートできないみたいで、量が多い場合はひじょーに面倒
便利: Strava で一括エクスポートする
Strava と連携していれば一括エクスポートが可能で楽ちん
2. 地図の作成
folium で地図に線を描くインタフェースは下記のような感じで提供されている
import folium # 緯度・経度 locations= [[35.335545, 139.547333], [35.335533, 139.547348], ... ] line = folium.PolyLine(locations=locations) osm = folium.Map() osm.add_child(line) osm.save('/path/to/map.html')
緯度経度を list で渡すだけ。これだけでインタラクティブな HTMLが生成される (注: よりよい感じにするために 描画の色や透明度、デフォルト表示の緯度経度の指定など詰めていく必要があろう)
性能の評価
GPX のサイズが 285 MB、1031173 件の 緯度\t経度
のリストを扱ったが、初回のHTML生成に要する時間は MacBook Pro (Retina 13-inch、Early 2015)
だと 下記の水準
./bin/overlay.py 32.61s user 0.93s system 83% cpu 40.024 total
XML をパースする部分が足を引っ張っていたようなので 2回目以降は pickle 化したキャッシュを使うようにすると そこそこ速くなった。繰り返し作業しててもギリギリストレスにならないレベル
./bin/overlay.py 12.25s user 0.57s system 91% cpu 14.062 total
/usr/bin/time -l
で 最大 RSS を取ると下記のような結果 300MB ちょい?
14.25 real 12.40 user 0.55 sys 320937984 maximum resident set size 🍣 0 average shared memory size 0 average unshared data size 0 average unshared stack size 106449 page reclaims 0 page faults 0 swaps 0 block input operations 5 block output operations 0 messages sent 0 messages received 0 signals received 1215 voluntary context switches 35781 involuntary context switches
Web サービスにするならリソースの扱いに一工夫いりそうだが、個人のローカル環境で楽しむ用途なら問題ないだろう
成果物の評価
タイルサーバーにはデフォルトで OpenStreetMap を利用しているらしい。OSM については過去に調べていた
js のライブラリは Leaflet を使っているらしい。フロントエンドには疎いので、どういう素性のものかググって調べた程度しか分からない
感想
- 自転車に限らず散歩、ランニング、自動車の走行記録からも同様の地図は作れるだろう
- 他の人のデータと重ね合わせるのも楽しそう
- 作ってみて分かったが、個人の行動がよく分かるセンシティブなデータでもある
- Google Photo 等の写真の EXIF から緯度経度を抜き出し、写真へのリンクを貼れると よりたのしい地図になるだろう
- GPX には緯度経度以外のデータ( 高さ、時刻 ) も付いているが、このスクリプトでは利用できていないので、これらを使った別の表現方法は考えうるだろう
- 生成したデータを地図化して Garmin にインポートすることで 「自分が過去に通ったルート・よく通るルート」 という地図や簡易のナビを作れるだろうか? これは楽しそう
- 時系列で線の色を分けると、違った特徴が観察できる地図になるだろう (例: 2016年は山によく行っていた、2017年は海にいっていた etc)
プライバシー
自宅周辺の緯度経度が密にプロットされていることもあり、生成した HTML は一般公開はしないので ご了承を 😲