スマホのGPSの精度にはまだまだ不満がある
スマホでも手軽にGPSロギングができるようになった昨今ですが、
やはりというか、誤差は結構あります。
以下はMyTracks(もう使えない?)による車両走行軌跡。
人が見ればどこを走ったかは分かりますが、なんとか綺麗な軌跡にできないもんか・・・
とは言え、Gセンサとか操舵とかのデータは取れていないですし、あってもそこから補正するのは素人には難しそうなので
マップマッチング的なことで何とかしたいなぁと思ったわけです。
では、地図データはどこから手に入れたらよいでしょう・・・?
作っておいてよかったOSM
上図でも使っているOpenStreetMap。
自前で地図サーバが欲しいということで構築しておいたのですが(構築方法はいずれ投稿するかも)、
タイルサーバとしては頻繁に使っていたものの、データ自体は見ておりませんでした。
ところが、なんという宝の山!これを今まで使わなかったなんて。。。
道路ネットワークもあれば、(多く無いですが)POI情報もあれば、建物のポリゴンもある。
精度うんぬんの問題はあるでしょうが、何十mもずれることはない(と信じている。少なくともスマホのGPSよりましなはず。)ので、
宝を掘り起こしていきたいと思います。
OpenStreetMapから道路NWを抽出することができるか?チャレンジしてみた。
そもそもOSMのデータにアクセスしようと思ったのは
Overpass APIというものがあると教えてもらったのがきっかけです。
http://wiki.openstreetmap.org/wiki/JA:Overpass_API
確かに独自形式だがのクエリを投げると道路NWなどが表示される!
ということは自前で構築済みのOSMサーバからも同じようにデータがとれるはず!
と考えました。
構築時にPostgresql、PostGISを入れた記憶があったので、
地図サーバのPostgresqlにアクセス。
あるある!それっぽいテーブルが!
テーブルのスキーマを見るとOverpassAPIにあったようにhighwayなどの属性がある。
これはいける。と確信。
スキーマは以下などが参考になります。。
http://wiki.openstreetmap.org/wiki/JA:Osm2pgsql/schema
→道路NWを取るならplanet_osm_line テーブルから取るようです。
今回はこのテーブルですね。
また車が走行する道路のみが欲しいのでhighwayの属性にどのようなものがあるかは確認が必要です。
以下が参考になります。
http://wiki.openstreetmap.org/wiki/Key:highway
footwayなど、歩道もデータには含まれています。
実際に取ってみた
スキーマを見るとwayカラムが実際に位置情報を持っているようですが、
型が"geometry(~~)"となっており、単純に取得しても人間には読めません。
理解するにはgeometry型をPostGISで変換する必要があります。
ST_Astext(ST_Transform(way,4326))
→4326はProjectionのコード。これもいろいろ種類があるようですが、世界測地系は4326で良さそう。
上記を踏まえて例として甲州街道という文言がnameカラムに含まれるデータをSQLで抽出します。
select osm_id,name,highway,z_order,ST_Astext(ST_Transform(way,4326)),way_area from planet_osm_line where name like '%甲州街道%';
少し時間がかかりますが、
141147784 | 甲州街道 | trunk | 8 | LINESTRING(138.089114228403 36.0716119850332,138.088936900966 36.0716665145095,・・・
というようにデータが取れました。パチパチパチパチw
でも、nameは入っていないデータの方が多いので取得条件には工夫が必要。。。
まとめてごっそり取りたい。
緯度経度の四角を指定して、そこに含まれるデータだけ取りたい。
最終的にはPOLYGONで指定した範囲で取りたい。
手間がかかりそうな気がしましたが、
考えてみればOverpass APIだとbboxで見えている範囲で取っているのでできるはずなのです。
調べてみたところ、当然ですができます。
指定したPOLYGONの中に”wayの最初のpointが含まれる"という条件が以下で実現できます。
これをwhere句に入れればOKです。
ST_Within( ST_StartPoint( ST_Transform(way,4326)) , ST_GeomFromText ( 'POLYGON(( 位置1,位置2,位置3, ... ,位置1))' ,4326) )
POLYGONの位置は「lon1 lat1,lon2 lat2・・・」というようにスペース区切りで緯度経度のペアを生成し、
カンマ区切りで位置を数珠つなぎにします。最後に位置1も記述し、輪になるようにする必要があります。
これを使うと都道府県などのPOLYGONデータを持っているのであれば、”都道府県別に取得”ということもできるはずです。
PostGISはいろいろな機能がある
使いこなすにはまだまだほど遠いですが、便利な機能が結構ありますね。
特にPOLYGONの面積を出せるのは便利です。今後も使いそうです。
POLYGONで指定した面積がおよそ500平方kmであることが算出できます。
PostGISの関数を使いたいだけなので select ~で計算だけさせれば良いです。
とりあえず道路NWデータの抽出は出来る
今回はOSMのデータベースから道路NWの抽出を行いました。
しかし、マップマッチングと言っている以上、この抽出データとGPSデータをマッチングさせる必要があります。
どうやろう・・・
片っ端から距離計算するという手もあるが、さすがに時間がかかりすぎるだろうなぁ・・・
つ R-Tree
ということで次回はR-Treeを使って"高速に"GPSとOSMの道路NWをマッチングさせていきます。
俺たちの戦いははじまったばかりだ