はじめに
経路探索やルート最適化を扱うとき、単純なユークリッド距離(直線距離)ではなく、
実際の「道路距離」や「所要時間」を使いたいケースが多くあります。
例えば以下のような場面です:
- 配送ルートの最適化
- 観光ルートの提案
- 移動時間のシミュレーション
このような現実的な距離・時間を取得できるオープンソースのルーティングエンジンが
OSRM(Open Source Routing Machine) です。
OSRM は OpenStreetMap のデータを利用し、
REST API として距離や所要時間を簡単に取得できるようになります。
本記事では、Windows 11 環境を例に以下の手順をハンズオン形式で実施します:
- Docker と OSM データを準備する
- OSRM の前処理を実行する
- OSRM サーバを起動して API を確認する
- Folium でルートを可視化する
これにより、「道路距離・所要時間を扱える環境」をローカルに構築し、
地図上にルートを描画して確認する ことがゴールとなります。
環境準備
本記事では以下の環境を前提とします:
- Windows 11
- Docker Desktop(インストール済み)
- Git Bash(コマンド実行に使用)
- Python(インストール済み、後半で可視化に使用)
Docker Desktop のインストール手順や動作確認(hello-world)は本記事では省略します。
インストールがまだの場合は、公式サイト を参照してください。
OSMデータの取得
OSRM を動かすには、OpenStreetMap (OSM) の地図データが必要です。
これは Geofabrik から地域ごとに入手できます。
データの選択
- 日本全体のデータもありますが、サイズが大きく処理に時間がかかります。
- まずは軽量で扱いやすい 関東地方のデータ を使用します。
ダウンロード先:
Geofabrik - Kanto
ファイル名:
kanto-latest.osm.pbf
保存先ディレクトリ
本記事では以下のディレクトリに保存したとします:
例:
project_dir/osrm/kanto-latest.osm.pbf
これで OSM データの準備が整いました。
OSRMの前処理
OSM データをそのままでは利用できないため、
OSRM で使える形式に変換する「前処理」を行います。
この処理は以下の 3 ステップです:
- extract:OSM データを抽出
- partition:データを分割
- customize:探索用の重み付けを設定
前処理コマンド(Git Bash)
作業ディレクトリ:project_dir
保存先:project_dir/osrm/kanto-latest.osm.pbf
# OSRM イメージを取得(初回のみ)
docker pull osrm/osrm-backend
# extract
WINPWD="$(pwd -W)"
MSYS_NO_PATHCONV=1 docker run --rm -t \
-v "$WINPWD/osrm:/data" \
osrm/osrm-backend \
osrm-extract -p /opt/car.lua /data/kanto-latest.osm.pbf
# partition
MSYS_NO_PATHCONV=1 docker run --rm -t \
-v "$WINPWD/osrm:/data" \
osrm/osrm-backend \
osrm-partition /data/kanto-latest.osrm
# customize
MSYS_NO_PATHCONV=1 docker run --rm -t \
-v "$WINPWD/osrm:/data" \
osrm/osrm-backend \
osrm-customize /data/kanto-latest.osrm
※ Git Bash ではパスの自動変換を防ぐため、先頭に
MSYS_NO_PATHCONV=1
を付けています。
生成されるファイル
処理が完了すると、project_dir/osrm/
配下に以下のようなファイルが生成されます。
kanto-latest.osrm
kanto-latest.osrm.partition
kanto-latest.osrm.cells
- その他、補助ファイル(
.geometry
など)
これらが揃っていれば、OSRM サーバを起動できる状態になっています。
サーバ起動とAPI確認
前処理が完了したら、OSRM サーバを起動して API が利用できるか確認します。
サーバの起動
以下のコマンドで OSRM サーバを起動します。
標準ではポート 5000
を使用します。
WINPWD="$(pwd -W)"
MSYS_NO_PATHCONV=1 docker run --rm -t \
-p 5000:5000 \
-v "$WINPWD/osrm:/data" \
osrm/osrm-backend \
osrm-routed --algorithm mld /data/kanto-latest.osrm
ターミナルに running and waiting for requests
のようなメッセージが表示されれば、
OSRM サーバは起動中です。
API の確認
別のターミナルを開いて、curl
コマンドで API を叩いてみます。
curl "http://127.0.0.1:5000/route/v1/driving/139.7671,35.6812;139.7020,35.6896?overview=false"
返ってきた JSON に distance
(距離, メートル単位)や
duration
(所要時間, 秒単位)が含まれていれば成功です。
レスポンス確認
東京駅 → 渋谷駅を例に実行すると、以下のようなレスポンスが返る:
{"code":"Ok","routes":[{"legs":[{"steps":[],"distance":7045.2,"duration":475.8}],"distance":7045.2,"duration":475.8}],"waypoints":[...]}
このように、直線距離ではなく「実際の道路距離」と「所要時間」を取得できることが確認できます。
Foliumでルート可視化
OSRM の API から取得した経路を、Folium(Leaflet ベースの Python ライブラリ)で HTML 地図に描画して確認します。
Foliumスクリプト(距離・時間をポリラインに表示)
- 東京駅 → 渋谷駅の 2 点を固定
- 返ってきた GeoJSON 形状(
[lon, lat]
)を Folium 用[lat, lon]
に変換 - 距離(km)と所要時間(分)を 線のツールチップ に表示
- 地図上のマーカーは開始(緑)・終了(赤)のみ
import requests
import folium
# --- 地点 ---
points = [(35.6812, 139.7671), (35.6896, 139.7020)] # 東京駅 → 渋谷駅
# --- OSRMサーバ設定 ---
server = "http://127.0.0.1:5000"
profile = "driving"
coords = ";".join(f"{lon},{lat}" for lat, lon in points)
url = f"{server}/route/v1/{profile}/{coords}?overview=full&geometries=geojson"
resp = requests.get(url)
resp.raise_for_status()
data = resp.json()
route = data["routes"][0]
geometry = route["geometry"]["coordinates"]
line = [(lat, lon) for lon, lat in geometry]
distance_km = round(route["distance"] / 1000, 2)
duration_min = round(route["duration"] / 60, 1)
# --- Foliumで地図作成 ---
m = folium.Map(location=points[0], zoom_start=13)
# 経路ポリラインに情報を付与
folium.PolyLine(
line,
color="blue",
weight=5,
opacity=0.8,
tooltip=f"距離: {distance_km} km / 所要時間: {duration_min} 分"
).add_to(m)
# 開始・終了点のマーカー
folium.Marker(points[0], popup="Start: 東京駅", icon=folium.Icon(color="green")).add_to(m)
folium.Marker(points[-1], popup="End: 渋谷駅", icon=folium.Icon(color="red")).add_to(m)
m.save("osrm_route_min.html")
print(f"[OK] 保存しました → osrm_route.html")
実行結果
- カレントディレクトリに HTML(例:
osrm_route.html
)が生成される - ブラウザで開くと、ルートが描画され、線をホバーすると距離・時間が確認できる
まとめ
ここまでの手順で以下を実施しました:
- OSM データを取得(関東地方のデータを使用)
- OSRM の前処理(extract → partition → customize)
- OSRM サーバを起動して API から道路距離・所要時間を取得
- Folium でルートを可視化
これにより、「道路距離・所要時間を扱える環境」 がローカルで構築できました。
次のステップとしては以下のような発展が考えられます:
-
/table
エンドポイントを利用して 距離・時間の行列 を取得 - Python で TSP(巡回セールスマン問題)やルート最適化 に応用
- Web アプリ(Flask / Streamlit など)と組み合わせて インタラクティブなルート検索ツール を作成