RでOSRMで経路検索

R
Docker
作者

伊東宏樹

公開

2025年5月16日

更新日

2025年5月17日

Rを使って、OSRMで経路検索をやってみました。Macだと、はまりそうなポイントもあったのでメモしておきます。

はじめに

OSRMは、オープンソースの経路検索エンジンです。Kanazawa.R #3NONONOexeさんの発表を見て、自分でもやってみようと思い立ちました。

準備

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レシーバーをオフにする

AirPlayレシーバーをオフにする

AirPlayレシーバーが必要な場合は、OSRMのポートを変更すればいいのかもしれません。

また、ほかのマシンから接続する場合には、ファイアーウォールでポートを開けておく必要があります。

OpenStreetMapのダウンロードとデータの準備

次に、OpenStreetMapのデータをダウンロードして、OSRM用に加工します。このあたりの過程は、「OSRMのサーバを立ち上げてルート検索を行う」を参考にしました。

まずは中部地方のデータをダウンロードします。

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

つづいてデータを加工します。地図データをダウンロードしたディレクトリで以下のコマンドを実行します。最初のコマンドの-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.osrm
docker 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 \
  osrm-routed --algorithm mld /data/chubu-latest.osrm

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には、兼六園の経度と緯度をそれぞれベクトルの形でいれておきます。

kanazawa_eki <- c(136.647893, 36.577984)
kenrokuen <- c(136.662603, 36.562085)

osrmRoute関数で経路検索を実行します。

(route <- osrmRoute(src = kanazawa_eki, dst = kenrokuen))
## 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,
          (kanazawa_eki[2] + kenrokuen[2]) / 2,
          zoom = 15) |>
  addPolylines(data = route) |>
  addMarkers(kanazawa_eki[1], kanazawa_eki[2]) |>
  addMarkers(kenrokuen[1], kenrokuen[2]) |>
  mapview::mapshot(file = "figures/kenrokuen.png")

出力された地図です。

金沢駅から兼六園までの経路

等時線(isochrone)を描く

osrmパッケージにはosrmIsochroneという関数があって、これは、ある地点から一定の時間内で到達できる範囲を描くもののようです。

金沢駅から徒歩で5、10、20分で到達できる範囲を描いてみました。

isochrone <- osrmIsochrone(kanazawa_eki, breaks = c(5, 10, 20))
leaflet() |>
  addTiles() |>
  setView(kanazawa_eki[1], kanazawa_eki[2],
          zoom = 14) |>
  addPolylines(data = isochrone) |>
  mapview::mapshot(file = "figures/kanazawaeki_isochrone.png")

このようになりました。

金沢駅からの等時線(isochrone)

金沢駅からの等時線(isochrone)