OpenStreetMapのデータをもとにルート検索を行える、OSSのルート検索エンジンの1つに、OSRM (Open Source Routing Machine, http://project-osrm.org/) がある。今回は、PC上にOSRMのサーバを用意して、ルート検索を行う。
環境
- OS: Ubuntu 20.04 LTS (Windows 11 Home: 21H2のWSL2にインストール)
- Docker Engine: 20.10.7 (上記のUbuntuにインストールしたCommunity Edition)
- OSRM: 5.26.0
ルート検索の準備
OSRMのサーバをPC上に立てる。OSRMのサービスを構成する複数のソフトウェアがGithubで公開されているが、今回はそのなかからルート検索エンジンの本体にあたるosrm-backendを使う。osrm-backendのリポジトリのQuick StartにDockerコンテナを用いたサーバ構築手順が書かれており、その流れに沿って作業をする。
はじめにGeofabrikからOpenStreetMapのデータを取得する。Quick Startの手順ではベルリンのデータをダウンロードしているが、ここでは日本の関東地方のデータをダウンロードする。
$ wget https://download.geofabrik.de/asia/japan/kanto-latest.osm.pbf
次に、ダウンロードしたOpenStreetMapのデータを加工する。OSRMでは、ルート検索の計算プロセスとして「Contraction Hierarchies (CH)」と「Multi-Level Dijkstra (MLD)」の2種類が用意されている。どちらの計算プロセスを選択しても、ルート検索の処理速度を向上させるために事前にデータ加工を行う必要がある。Quick Startには、巨大な距離行列 (どの程度の大きさか具体的な指標は書かれていないが) を扱うような場合を除いて、基本的にMLDを使うのがおすすめと書かれている。Quick Startの手順もMLDを使ったものになっているので、ここでもMLDを使うことにする。
先ほどダウンロードしたOpenStreetMapのデータの置かれているディレクトリで、以下のMLD用のデータ加工のコマンドを実行する。
$ docker run -t -v "${PWD}:/data" osrm/osrm-backend osrm-extract -p /opt/car.lua /data/kanto-latest.osm.pbf $ docker run -t -v "${PWD}:/data" osrm/osrm-backend osrm-partition /data/kanto-latest.osrm $ docker run -t -v "${PWD}:/data" osrm/osrm-backend osrm-customize /data/kanto-latest.osrm
実行結果として、以下のファイルが生成される。
$ ls kanto-latest.osrm* kanto-latest.osrm kanto-latest.osrm.enw kanto-latest.osrm.properties kanto-latest.osrm.cell_metrics kanto-latest.osrm.fileIndex kanto-latest.osrm.ramIndex kanto-latest.osrm.cells kanto-latest.osrm.geometry kanto-latest.osrm.restrictions kanto-latest.osrm.cnbg kanto-latest.osrm.icd kanto-latest.osrm.timestamp kanto-latest.osrm.cnbg_to_ebg kanto-latest.osrm.maneuver_overrides kanto-latest.osrm.tld kanto-latest.osrm.datasource_names kanto-latest.osrm.mldgr kanto-latest.osrm.tls kanto-latest.osrm.ebg kanto-latest.osrm.names kanto-latest.osrm.turn_duration_penalties kanto-latest.osrm.ebg_nodes kanto-latest.osrm.nbg_nodes kanto-latest.osrm.turn_penalties_index kanto-latest.osrm.edges kanto-latest.osrm.partition kanto-latest.osrm.turn_weight_penalties
OSRMのサービスを5000番ポートで起動すれば、ルート検索を実行できるようになる。
$ docker run -t -i -p 5000:5000 -v "${PWD}:/data" osrm/osrm-backend osrm-routed --algorithm mld /data/kanto-latest.osrm
ルート検索の実行
OSRMのサーバが用意できたので、ルート検索を試してみる。検索対象は、東京駅の八重洲口から羽田空港の第1ターミナルまでの道のりとする。
OSRMのサーバの使い方は、OSRMのAPIドキュメント(2022/07/28時点でドキュメントのバージョンはv5.24.0)に書かれている。OSRMのサーバは複数のサービスを提供しており、今回はそのなかから、2点間の最速ルートを探すRoute serviceを使う。APIドキュメントのRoute serviceの箇所を参照して、OSRMのサーバに送るリクエストを準備する。
Route serviceのリクエストは、出発地点と到着地点それぞれの緯度経度が必須のパラメータとなる。出発・到着地点の緯度経度の取得方法として、OpenStreetMapのWebサイトで提供されている地物検索の機能を使い、それぞれの地点付近の適当なノードを探すアプローチをとる。
出発地点の東京駅八重洲口は、ID: 6397151768のノードの緯度経度35.6798851, 139.7681482を設定する。
到着地点となる羽田空港第1ターミナルは、ID: 2206530973のノードの緯度経度35.5491518, 139.7845835を設定する。
また、ルート検索結果を地図上に可視化するときなどにデータの扱いが便利になるため、以下のオプションをリクエストに付与する。
- 検索結果のルートのジオメトリをgeojson形式で取得するための
geometries=geojson
- 検索結果のルートのジオメトリを詳細な部分まで取得するための
overview=full
出発・到着地点の緯度経度 (「経度,緯度」の順番にする必要がある点に注意) と追加のオプションを設定したリクエストを、自身のPC上で起動したOSRMサーバに送る。
$ curl "http://127.0.0.1:5000/route/v1/driving/139.7681482,35.6798851;139.7845835,35.5491518?geometries=geojson&overview=full"
以下のようなレスポンスが返ってくれば、ルート検索が実行できている。
{"code":"Ok","routes":[{"geometry":{"coordinates":[[139.768429,35.679767],[139.768491,35.679864],[139.768635,35.68016], ...省略... [139.784681,35.549197]],"type":"LineString"},"legs":[{"steps":[],"distance":21800,"duration":1230.7,"summary":"","weight":1230.7}],"distance":21800,"duration":1230.7,"weight_name":"routability","weight":1230.7}],"waypoints":[{"hint":"SwJCgP___3-0AAAA0gAAAAAAAABVAAAAL4OWQkw1QkEAAAAAQ1YNQrQAAADSAAAAAAAAAFUAAADvAwAAbbJUCBduIAJUsVQIjW4gAgAAvwHZCL3c","distance":28.611262,"name":"","location":[139.768429,35.679767]},{"hint":"bjgzgP___38RAAAARgAAAAAAAAAAAAAAigmZQbnlaUIAAAAAAAAAABEAAABGAAAAAAAAAAAAAADvAwAA6fFUCA1wHgKI8VQI4G8eAgAArxTZCL3c","distance":10.116086,"name":"","location":[139.784681,35.549197]}]}