35
37

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

目指せGISマスター #1 OpenStreetMapから道路NWを抽出する

Posted at

スマホのGPSの精度にはまだまだ不満がある

スマホでも手軽にGPSロギングができるようになった昨今ですが、
やはりというか、誤差は結構あります。

以下はMyTracks(もう使えない?)による車両走行軌跡。
mytracks.png

人が見ればどこを走ったかは分かりますが、なんとか綺麗な軌跡にできないもんか・・・
とは言え、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の面積を出せるのは便利です。今後も使いそうです。
area.png

POLYGONで指定した面積がおよそ500平方kmであることが算出できます。
PostGISの関数を使いたいだけなので select ~で計算だけさせれば良いです。

とりあえず道路NWデータの抽出は出来る

今回はOSMのデータベースから道路NWの抽出を行いました。
しかし、マップマッチングと言っている以上、この抽出データとGPSデータをマッチングさせる必要があります。

どうやろう・・・
片っ端から距離計算するという手もあるが、さすがに時間がかかりすぎるだろうなぁ・・・

つ R-Tree

ということで次回はR-Treeを使って"高速に"GPSとOSMの道路NWをマッチングさせていきます。

俺たちの戦いははじまったばかりだ

35
37
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
35
37

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?