自由帳

とりとめのない学習メモです。主に Web サービスのシステム基盤や運用に関することを書いています

OSRM Frontend, Backend を使って、ローカルでマップを表示されてルート検索をやってみた

はじめに

オープンデータの地理情報を作るプロジェクトである OSM(OpenStreetMap) のデータをもとに、ルートの検索を行うためのエンジンである OSRM (Open Source Routing Machine) がどんなものかを浅く理解するために、ちょっと動かしてみた。

OSRM(Open Source Routing Machine)

OSRM は OpenStreetMap (OSM) プロジェクトのマップデータをもとにルート検索を行える C++のルーティングエンジンらしい。

OSRMのプロジェクトとしていくつかアプリケーションが公開されていて、そのうちの以下の 2 つを利用する。

OSRM Backend は C++ のルーティングエンジンで、HTTP API も組み込まれているので、API 経由で結果を取得できる。OSRM Frontendは、Web View で Backend と組み合わせて結果をブラウザ上に表示されたマップから確認できる。

どちらも Docker で利用可能になっているので、簡単に起動できる。

試す環境

macOS で試す。

% sw_vers
ProductName:    macOS
ProductVersion: 12.6.2
% docker version
Client:
 Cloud integration: v1.0.29
 Version:           20.10.21
 API version:       1.41
 Go version:        go1.18.7
 Git commit:        baeda1f
 Built:             Tue Oct 25 18:01:18 2022
 OS/Arch:           darwin/amd64
 Context:           default
 Experimental:      true

Server: Docker Desktop 4.14.0 (91374)
 Engine:
  Version:          20.10.21
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.18.7
  Git commit:       3056208
  Built:            Tue Oct 25 18:00:19 2022
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.6.9
  GitCommit:        1c90a442489720eec95342e1789ee8a5e1b9536f
 runc:
  Version:          1.1.4
  GitCommit:        v1.1.4-0-g5fd4c4d
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

構築

前述の通り Docker イメージが利用可能なので、それを利用する。

Backend の方は「QuickStart」の項目をベースに実施する。

Frontend の方は「Using Docker」の項目をベースに実施する。

実施内容についてのもう少し細かい記載が下記にある。

作業ディレクトリの作成

適当に作業ディレクトリを作成して移動する。

% mkdir osrm-work

% cd osrm-work

OSM マップデータの取得

OSM のマップデータを取得する。いろんな地域のマップデータがあって、範囲が広いとサイズも大きい。ここでは関東エリアのマップを取得する。

$ wget https://download.geofabrik.de/asia/japan/kanto-latest.osm.pbf

OSRM Backend の構築

OSRM Backend を構築する。Docker Desktop に割り当てるメモリリソースが 4 GB くらいは割り当ててないと、後続処理が失敗する。

まず、 OSM のデータファイルはいろんな情報が含まれているため、ルート検索用の形式で抽出する。

% docker run -t -v "${PWD}:/data" ghcr.io/project-osrm/osrm-backend osrm-extract -p /opt/car.lua /data/kanto-latest.osm.pbf

以下のようなファイルが生成される。

% ls                                                                                                                                                                                                                  [osrm]
kanto-latest.osm.pbf                kanto-latest.osrm.edges             kanto-latest.osrm.names             kanto-latest.osrm.tld
kanto-latest.osrm               kanto-latest.osrm.enw               kanto-latest.osrm.nbg_nodes         kanto-latest.osrm.tls
kanto-latest.osrm.cnbg              kanto-latest.osrm.fileIndex         kanto-latest.osrm.properties            kanto-latest.osrm.turn_duration_penalties
kanto-latest.osrm.cnbg_to_ebg           kanto-latest.osrm.geometry          kanto-latest.osrm.ramIndex          kanto-latest.osrm.turn_penalties_index
kanto-latest.osrm.ebg               kanto-latest.osrm.icd               kanto-latest.osrm.restrictions          kanto-latest.osrm.turn_weight_penalties
kanto-latest.osrm.ebg_nodes         kanto-latest.osrm.maneuver_overrides        kanto-latest.osrm.timestamp

% ls  | wc -l
      23

.osrm のファイルに対して、再帰的にセル分割する処理を実行する。(詳しくわかっていない)

% docker run -t -v "${PWD}:/data" ghcr.io/project-osrm/osrm-backend osrm-partition /data/kanto-latest.osrm

kanto-latest.osrm.cellskanto-latest.osrm.partition の2つのファイルが追加で生成される。

% ls
kanto-latest.osm.pbf                kanto-latest.osrm.edges             kanto-latest.osrm.nbg_nodes         kanto-latest.osrm.tls
kanto-latest.osrm               kanto-latest.osrm.enw               kanto-latest.osrm.partition         kanto-latest.osrm.turn_duration_penalties
kanto-latest.osrm.cells             kanto-latest.osrm.fileIndex         kanto-latest.osrm.properties            kanto-latest.osrm.turn_penalties_index
kanto-latest.osrm.cnbg              kanto-latest.osrm.geometry          kanto-latest.osrm.ramIndex          kanto-latest.osrm.turn_weight_penalties
kanto-latest.osrm.cnbg_to_ebg           kanto-latest.osrm.icd               kanto-latest.osrm.restrictions
kanto-latest.osrm.ebg               kanto-latest.osrm.maneuver_overrides        kanto-latest.osrm.timestamp
kanto-latest.osrm.ebg_nodes         kanto-latest.osrm.names             kanto-latest.osrm.tld

% ls | wc -l
      25

ルート毎のウェイトを計算してセルをカスタマイズする処理を実行する。(詳しくわかっていない)

% docker run -t -v "${PWD}:/data" ghcr.io/project-osrm/osrm-backend osrm-customize /data/kanto-latest.osrm

さらに追加で kanto-latest.osrm.mldgr, kanto-latest.osrm.cell_metrics, kanto-latest.osrm.datasource_names の3つのファイルが生成される。

% ls
kanto-latest.osm.pbf                kanto-latest.osrm.ebg               kanto-latest.osrm.maneuver_overrides        kanto-latest.osrm.restrictions
kanto-latest.osrm               kanto-latest.osrm.ebg_nodes         kanto-latest.osrm.mldgr             kanto-latest.osrm.timestamp
kanto-latest.osrm.cell_metrics          kanto-latest.osrm.edges             kanto-latest.osrm.names             kanto-latest.osrm.tld
kanto-latest.osrm.cells             kanto-latest.osrm.enw               kanto-latest.osrm.nbg_nodes         kanto-latest.osrm.tls
kanto-latest.osrm.cnbg              kanto-latest.osrm.fileIndex         kanto-latest.osrm.partition         kanto-latest.osrm.turn_duration_penalties
kanto-latest.osrm.cnbg_to_ebg           kanto-latest.osrm.geometry          kanto-latest.osrm.properties            kanto-latest.osrm.turn_penalties_index
kanto-latest.osrm.datasource_names      kanto-latest.osrm.icd               kanto-latest.osrm.ramIndex          kanto-latest.osrm.turn_weight_penalties

% ls | wc -l
      28

OSRM API 用の HTTP server を起動する。

% % docker run -t -i -p 5000:5000 -v "${PWD}:/data" ghcr.io/project-osrm/osrm-backend osrm-routed --algorithm mld /data/kanto-latest.osrm

正常に起動すれば以下のような出力がなされる。

[info] starting up engines, v5.26.0
[info] Threads: 2
[info] IP address: 0.0.0.0
[info] IP port: 5000
[info] http 1.1 compression handled by zlib version 1.2.8
[info] Listening on: 0.0.0.0:5000
[info] running and waiting for requests

OSRM Backend の構築はこれで完了。

OSRM Frontend の構築

続いて OSRM の Frontend を起動する。ポートはドキュメント通り 9966 としている。

% docker run -p 9966:9966 ghcr.io/project-osrm/osrm-frontend 

以下のような出力がなされて起動する。

> osrm-frontend@0.4.0 start /src
> npm run build && npm run start-index


> osrm-frontend@0.4.0 build /src
> npm run replace && npm run compile && cp node_modules/leaflet/dist/leaflet.css css/leaflet.css


> osrm-frontend@0.4.0 replace /src
> node ./scripts/replace.js


> osrm-frontend@0.4.0 compile /src
> browserify -d src/index.js -s osrm > bundle.raw.js && uglifyjs bundle.raw.js -c -m --source-map=bundle.js.map -o bundle.js

この状態でマップを表示させた場合、初期表示が ワシントンD.C とかになっているので、変更する。 デフォルトのイメージをそのまま使っているので、とりあえずDocker コンテナに入ってファイルを変更する。

% docker exec -it 8be8fe263398 /bin/sh

ファイル編集用に vim をインストールする。

# apk update

# apk add vim

/src/src/leaflet_options.js というファイルがあるので、下記の箇所を修正する。 下記の内容だと東京駅付近がデフォルト表示となる。

Frontend 側から呼び出される Backend の API はデフォルトではルート検索用の http://localhost:5000/route/v1 が利用されるようになっている。

--- src/leaflet_options.js.bak
+++ src/leaflet_options.js
@@ -21,7 +21,7 @@

 module.exports = {
   defaultState: {
-    center: L.latLng(38.8995,-77.0269),
+    center: L.latLng(35.679767,139.768429),
     zoom: 13,
     waypoints: [],
     language: 'en',

これでとりあえず Front の方も構築完了となる。

表示

http://localhost:9966 へアクセスする。 画面左下の設定項目で、「openstreetmap.org」を選択すると以下のような画面が表示される。

適当にマップ上をクリックするとピンが落ち、任意の地点を2つ選択すると、ルートが表示される。 デフォルトだと車道のルートになっていると思われる。

まとめ

OSRM Frontend, Backend を使って、ローカルでルート検索マップを表示させてみた。 Frontend と組み合わせることで手軽にマップを表示させてルート検索を試せて面白い。Google Map とかはこういった仕組みを使って一瞬で経路を返しているんだろうなと思った。

まだあんまり触っていないけど Backend は色々 API が用意されているので、それらの API を使うことで色々なことがやれそうだった。