wget https://download.geofabrik.de/asia/japan/chubu-latest.osm.pbf
Rを使って、OSRMで経路検索をやってみました。Macだと、はまりそうなポイントもあったのでメモしておきます。
はじめに
OSRMは、オープンソースの経路検索エンジンです。Kanazawa.R #3のNONONOexeさんの発表を見て、自分でもやってみようと思い立ちました。
準備
Dockerコンテナを使ってOSRMサーバーを立ち上げ
OSRMのデモサイトには負荷をかけられないということで、Dockerコンテナを使ってローカルにOSRMサーバーを立ち上げるのが一般的なようです。
ということで、Docker Hubにある、osrm/osrm-backendのイメージをとってきたのですが、MacBook Pro (Apple M1)ではうまく動作しません。どうもarm64には対応していないようです。
それならと、IntelのMacBook Proの方でDockerコンテナを動かしてみるとこちらはうまく動作しました。
Macの場合はもうひとつ、OSRMで使用する5000番ポートがmacOSのAirPlayレシーバーで使われているという問題があります。なので、システム設定>一般>AirDropとHandoffで、AirPlayレシーバーを切っておきました。
AirPlayレシーバーが必要な場合は、OSRMのポートを変更すればいいのかもしれません。
また、ほかのマシンから接続する場合には、ファイアーウォールでポートを開けておく必要があります。
OpenStreetMapのダウンロードとデータの準備
次に、OpenStreetMapのデータをダウンロードして、OSRM用に加工します。このあたりの過程は、「OSRMのサーバを立ち上げてルート検索を行う」を参考にしました。
まずは中部地方のデータをダウンロードします。
つづいてデータを加工します。地図データをダウンロードしたディレクトリで以下のコマンドを実行します。最初のコマンドの-p
オプションでは、歩行のプロファイル(foot.lua
)を指定しています。
docker run -t -v "${PWD}:/data" osrm/osrm-backend osrm-extract \
-p /opt/foot.lua /data/chubu-latest.osm.pbf
docker run -t -v "${PWD}:/data" osrm/osrm-backend osrm-partition \
/data/chubu-latest.osrmdocker run -t -v "${PWD}:/data" osrm/osrm-backend osrm-customize \
/data/chubu-latest.osrm
OSRMの起動
ここまで来たら、OSRMを起動します。
docker run -t -i -p 5000:5000 -v "${PWD}:/data" osrm/osrm-backend \
--algorithm mld /data/chubu-latest.osrm osrm-routed
Rから経路検索の実行
準備ができたので、Rから経路検索をおこないます。RからOSRMを利用するにはosrmパッケージを使用します。オプションのosrm.server
でOSRMサーバーのIPアドレスとポートを指定します。今回は、Rが動いているマシンとは別のIntel MacBook ProでOSRMサーバーが立ち上がっているので、そのマシンのIPアドレスを指定しています。同じマシンならlocalhost (127.0.0.1)となります。osrm.profile
は、データ加工の設定と同じく"foot"
を指定しています。
library(osrm)
## Data: (c) OpenStreetMap contributors, ODbL 1.0 - http://www.openstreetmap.org/copyright
## Routing: OSRM - http://project-osrm.org/
library(leaflet)
options(osrm.server = "http://192.168.1.62:5000/",
osrm.profile = "foot")
金沢駅から兼六園までの徒歩による経路を検索します。kanazawa_eki
には、金沢駅の経度と緯度を、kenrokuen
には、兼六園の経度と緯度をそれぞれベクトルの形でいれておきます。
<- c(136.647893, 36.577984)
kanazawa_eki <- c(136.662603, 36.562085) kenrokuen
osrmRoute関数で経路検索を実行します。
<- osrmRoute(src = kanazawa_eki, dst = kenrokuen))
(route ## Simple feature collection with 1 feature and 4 fields
## Geometry type: LINESTRING
## Dimension: XY
## Bounding box: xmin: 136.6482 ymin: 36.56208 xmax: 136.6628 ymax: 36.57813
## Geodetic CRS: WGS 84
## src dst duration distance geometry
## src_dst src dst 33.815 2.7416 LINESTRING (136.6482 36.577...
経路が検索されました。所要時間は33.8分、距離は2.7 kmとのことです。
地図出力
検索された経路を地図に出力します。これにはleafletを使用しました。
leaflet() |>
addTiles() |>
setView((kanazawa_eki[1] + kenrokuen[1]) / 2,
2] + kenrokuen[2]) / 2,
(kanazawa_eki[zoom = 15) |>
addPolylines(data = route) |>
addMarkers(kanazawa_eki[1], kanazawa_eki[2]) |>
addMarkers(kenrokuen[1], kenrokuen[2]) |>
::mapshot(file = "figures/kenrokuen.png") mapview
出力された地図です。
等時線(isochrone)を描く
osrmパッケージにはosrmIsochrone
という関数があって、これは、ある地点から一定の時間内で到達できる範囲を描くもののようです。
金沢駅から徒歩で5、10、20分で到達できる範囲を描いてみました。
<- osrmIsochrone(kanazawa_eki, breaks = c(5, 10, 20))
isochrone leaflet() |>
addTiles() |>
setView(kanazawa_eki[1], kanazawa_eki[2],
zoom = 14) |>
addPolylines(data = isochrone) |>
::mapshot(file = "figures/kanazawaeki_isochrone.png") mapview
このようになりました。