Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
| Beide Seiten der vorigen Revision Vorhergehende Überarbeitung Nächste Überarbeitung | Vorhergehende Überarbeitung | ||
|
osrm [2026/03/29 03:59] jango [WSL] |
osrm [2026/04/04 12:09] (aktuell) admin [Datenbasis] |
||
|---|---|---|---|
| Zeile 1: | Zeile 1: | ||
| - | Open Source Routing Machine. Siehe auch [[OpenStreetMap]] | + | OSRM (Open Source Routing Machine) ist eine Open-Source Routing-Engine für Straßennetze auf Basis von [[OpenStreetMap]]-Daten (OSM). Das Projekt ist in C++ implementiert und auf sehr schnelle Routenberechnung ausgelegt. Im Unterschied zu Geocodern wie [[Nominatim]] übersetzt OSRM keine Adressen in Koordinaten, |
| + | |||
| + | OSRM kann sowohl als HTTP-Dienst betrieben als auch als Bibliothek genutzt werden. Die offizielle Dokumentation beschreibt dafür eine HTTP-API, eine C++ Bibliothek namens libosrm sowie einen Node.js Wrapper. | ||
| Demo [[https:// | Demo [[https:// | ||
| + | |||
| + | <code python> | ||
| + | import requests | ||
| + | |||
| + | def get_route(start_lon: | ||
| + | url = ( | ||
| + | f" | ||
| + | f" | ||
| + | ) | ||
| + | params = { | ||
| + | " | ||
| + | " | ||
| + | } | ||
| + | |||
| + | response = requests.get(url, | ||
| + | response.raise_for_status() | ||
| + | return response.json() | ||
| + | |||
| + | |||
| + | result = get_route(16.37208, | ||
| + | |||
| + | route = result[" | ||
| + | print(" | ||
| + | print(" | ||
| + | </ | ||
| + | |||
| + | =====Datenbasis===== | ||
| + | OSRM verarbeitet OpenStreetMap-Daten in einem Vorbereitungsprozess und erzeugt daraus speziell optimierte Routing-Datenstrukturen. Laut Projektseite unterstützt OSRM den Import von OSM-Daten (siehe [[PBF]]), ist für sehr große Netze ausgelegt und bietet vorkonfigurierte Profile für Auto, Fahrrad und Fußweg. Das Routing-Verhalten kann über Profile angepasst werden. | ||
| + | |||
| + | Für die Datenvorbereitung werden Werkzeuge wie osrm-extract, | ||
| + | |||
| + | =====API-Endpunkte===== | ||
| + | |||
| + | Die HTTP-API von OSRM verwendet in Version 5.x das Protokoll v1. Die zentralen Dienste sind: | ||
| + | |||
| + | * route | ||
| + | * nearest | ||
| + | * table | ||
| + | * match | ||
| + | * trip | ||
| + | * tile | ||
| + | |||
| + | ====Route==== | ||
| + | |||
| + | Der Dienst [[https:// | ||
| + | |||
| + | Beispiel: | ||
| + | |||
| + | / | ||
| + | |||
| + | ====Nearest==== | ||
| + | |||
| + | Der Dienst [[https:// | ||
| + | |||
| + | ====Table==== | ||
| + | |||
| + | Der Dienst [[https:// | ||
| + | |||
| + | ====Match==== | ||
| + | |||
| + | Der Dienst [[https:// | ||
| + | |||
| + | ====Trip==== | ||
| + | |||
| + | Der Dienst [[https:// | ||
| + | |||
| + | ====Tile==== | ||
| + | |||
| + | Der Dienst [[https:// | ||
| + | |||
| + | =====Profile===== | ||
| + | |||
| + | Das Routing-Verhalten von OSRM wird durch Lua-Profile bestimmt. Das Profil wird bereits bei der Datenaufbereitung festgelegt und definiert, welche Straßen befahrbar sind und wie Geschwindigkeiten, | ||
| + | |||
| + | Dadurch lässt sich OSRM an verschiedene Einsatzszenarien anpassen, etwa für klassische Autonavigation, | ||
| =====Setup===== | =====Setup===== | ||
| - | ====WSL==== | + | * Disk > 15GB |
| + | * RAM > 8GB | ||
| + | ====WSL Demo==== | ||
| + | Non persistent | ||
| <code bash> | <code bash> | ||
| # | # | ||
| Zeile 197: | Zeile 277: | ||
| </ | </ | ||
| - | ====Ubuntu | + | ====Ubuntu |
| + | |||
| + | < | ||
| + | curl " | ||
| + | </ | ||
| + | |||
| + | <code bash> | ||
| + | # | ||
| + | set -euo pipefail | ||
| + | |||
| + | COMMAND=" | ||
| + | PBF_PATH=" | ||
| + | PROFILE=" | ||
| + | |||
| + | PORT=" | ||
| + | CONTAINER_NAME=" | ||
| + | WORKDIR=" | ||
| + | IMAGE=" | ||
| + | |||
| + | need_root() { | ||
| + | if [[ " | ||
| + | echo "Bitte mit sudo starten." | ||
| + | echo " | ||
| + | echo " | ||
| + | echo " | ||
| + | exit 1 | ||
| + | fi | ||
| + | } | ||
| + | |||
| + | usage() { | ||
| + | cat << | ||
| + | Verwendung: | ||
| + | sudo bash osrm-manager.sh build / | ||
| + | sudo bash osrm-manager.sh start / | ||
| + | sudo bash osrm-manager.sh stop | ||
| + | sudo bash osrm-manager.sh restart / | ||
| + | sudo bash osrm-manager.sh status | ||
| + | sudo bash osrm-manager.sh logs | ||
| + | sudo bash osrm-manager.sh url [car|bike|foot] | ||
| + | |||
| + | Umgebungsvariablen: | ||
| + | PORT=5000 | ||
| + | CONTAINER_NAME=osrm-demo | ||
| + | WORKDIR=/ | ||
| + | IMAGE=osrm/ | ||
| + | |||
| + | Hinweis: | ||
| + | Für jedes Profil werden eigene Daten verwendet: | ||
| + | / | ||
| + | / | ||
| + | / | ||
| + | EOF | ||
| + | } | ||
| + | |||
| + | check_profile() { | ||
| + | case " | ||
| + | car) | ||
| + | LUA_PROFILE="/ | ||
| + | SERVICE_MODE=" | ||
| + | ;; | ||
| + | bike) | ||
| + | LUA_PROFILE="/ | ||
| + | SERVICE_MODE=" | ||
| + | ;; | ||
| + | foot) | ||
| + | LUA_PROFILE="/ | ||
| + | SERVICE_MODE=" | ||
| + | ;; | ||
| + | *) | ||
| + | echo " | ||
| + | exit 1 | ||
| + | ;; | ||
| + | esac | ||
| + | |||
| + | export LUA_PROFILE SERVICE_MODE | ||
| + | } | ||
| + | |||
| + | install_docker_if_missing() { | ||
| + | if command -v docker >/ | ||
| + | echo " | ||
| + | return | ||
| + | fi | ||
| + | |||
| + | echo " | ||
| + | |||
| + | apt-get update | ||
| + | apt-get install -y ca-certificates curl | ||
| + | |||
| + | install -m 0755 -d / | ||
| + | curl -fsSL https:// | ||
| + | chmod a+r / | ||
| + | |||
| + | . / | ||
| + | echo \ | ||
| + | "deb [arch=$(dpkg --print-architecture) signed-by=/ | ||
| + | > / | ||
| + | |||
| + | apt-get update | ||
| + | apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin | ||
| + | |||
| + | systemctl enable docker || true | ||
| + | systemctl start docker || true | ||
| + | |||
| + | if [[ -n " | ||
| + | usermod -aG docker " | ||
| + | fi | ||
| + | } | ||
| + | |||
| + | start_docker_if_needed() { | ||
| + | if docker info >/ | ||
| + | echo " | ||
| + | return | ||
| + | fi | ||
| + | |||
| + | echo " | ||
| + | systemctl enable docker || true | ||
| + | systemctl start docker || true | ||
| + | |||
| + | for _ in $(seq 1 20); do | ||
| + | if docker info >/ | ||
| + | echo " | ||
| + | return | ||
| + | fi | ||
| + | sleep 1 | ||
| + | done | ||
| + | |||
| + | echo " | ||
| + | exit 1 | ||
| + | } | ||
| + | |||
| + | check_pbf_arg() { | ||
| + | if [[ -z " | ||
| + | echo " | ||
| + | exit 1 | ||
| + | fi | ||
| + | |||
| + | if [[ ! -f " | ||
| + | echo " | ||
| + | exit 1 | ||
| + | fi | ||
| + | } | ||
| + | |||
| + | prepare_paths() { | ||
| + | check_pbf_arg | ||
| + | |||
| + | PBF_ABS=" | ||
| + | PBF_BASENAME=" | ||
| + | PBF_NAME=" | ||
| + | |||
| + | PROFILE_DIR=" | ||
| + | DATASET_FILE=" | ||
| + | OSRM_BASE=" | ||
| + | PROFILE_CONTAINER_NAME=" | ||
| + | |||
| + | mkdir -p " | ||
| + | |||
| + | export PBF_ABS PBF_BASENAME PBF_NAME PROFILE_DIR DATASET_FILE OSRM_BASE PROFILE_CONTAINER_NAME | ||
| + | } | ||
| + | |||
| + | require_prepared_dataset() { | ||
| + | local missing=0 | ||
| + | local required=( | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | " | ||
| + | ) | ||
| + | |||
| + | for f in " | ||
| + | if [[ ! -f " | ||
| + | echo " | ||
| + | missing=1 | ||
| + | fi | ||
| + | done | ||
| + | |||
| + | if [[ " | ||
| + | echo | ||
| + | echo " | ||
| + | echo " | ||
| + | echo " | ||
| + | exit 1 | ||
| + | fi | ||
| + | } | ||
| + | |||
| + | remove_container_if_exists() { | ||
| + | if docker ps -a --format ' | ||
| + | echo " | ||
| + | docker rm -f " | ||
| + | fi | ||
| + | } | ||
| + | |||
| + | copy_input_if_needed() { | ||
| + | if [[ -f " | ||
| + | local src_size dst_size | ||
| + | src_size=" | ||
| + | dst_size=" | ||
| + | |||
| + | if [[ " | ||
| + | echo " | ||
| + | return | ||
| + | fi | ||
| + | fi | ||
| + | |||
| + | echo " | ||
| + | cp -f " | ||
| + | } | ||
| + | |||
| + | cleanup_previous_dataset_files() { | ||
| + | echo " | ||
| + | find " | ||
| + | \( -name " | ||
| + | -print -delete || true | ||
| + | } | ||
| + | |||
| + | build_dataset() { | ||
| + | echo " | ||
| + | docker pull " | ||
| + | |||
| + | copy_input_if_needed | ||
| + | cleanup_previous_dataset_files | ||
| + | |||
| + | echo " | ||
| + | docker run --rm -t \ | ||
| + | -v " | ||
| + | " | ||
| + | osrm-extract -p " | ||
| + | |||
| + | echo " | ||
| + | docker run --rm -t \ | ||
| + | -v " | ||
| + | " | ||
| + | osrm-partition "/ | ||
| + | |||
| + | echo " | ||
| + | docker run --rm -t \ | ||
| + | -v " | ||
| + | " | ||
| + | osrm-customize "/ | ||
| + | |||
| + | echo " | ||
| + | } | ||
| + | |||
| + | start_container() { | ||
| + | require_prepared_dataset | ||
| + | remove_container_if_exists | ||
| + | |||
| + | echo " | ||
| + | docker run -d \ | ||
| + | --restart unless-stopped \ | ||
| + | --name " | ||
| + | -p " | ||
| + | -v " | ||
| + | " | ||
| + | osrm-routed --algorithm mld "/ | ||
| + | |||
| + | echo | ||
| + | echo " | ||
| + | echo " | ||
| + | echo " | ||
| + | } | ||
| + | |||
| + | stop_container() { | ||
| + | local found=0 | ||
| + | for p in car bike foot; do | ||
| + | local name=" | ||
| + | if docker ps -a --format ' | ||
| + | echo " | ||
| + | docker rm -f " | ||
| + | found=1 | ||
| + | fi | ||
| + | done | ||
| + | |||
| + | if [[ " | ||
| + | echo "Kein passender Container gefunden." | ||
| + | fi | ||
| + | } | ||
| + | |||
| + | show_status() { | ||
| + | echo " | ||
| + | systemctl is-active docker || true | ||
| + | echo | ||
| + | |||
| + | echo " | ||
| + | docker ps -a --filter " | ||
| + | |||
| + | echo | ||
| + | echo " | ||
| + | for p in car bike foot; do | ||
| + | local dir=" | ||
| + | if [[ -d " | ||
| + | echo "--- $dir" | ||
| + | ls -1 " | ||
| + | fi | ||
| + | done | ||
| + | } | ||
| + | |||
| + | show_logs() { | ||
| + | local found=0 | ||
| + | for p in car bike foot; do | ||
| + | local name=" | ||
| + | if docker ps -a --format ' | ||
| + | found=1 | ||
| + | echo " | ||
| + | docker logs --tail 100 " | ||
| + | echo | ||
| + | fi | ||
| + | done | ||
| + | |||
| + | if [[ " | ||
| + | echo "Kein passender Container gefunden." | ||
| + | fi | ||
| + | } | ||
| + | |||
| + | print_url() { | ||
| + | check_profile | ||
| + | echo " | ||
| + | } | ||
| + | |||
| + | main() { | ||
| + | need_root | ||
| + | |||
| + | case " | ||
| + | build) | ||
| + | check_profile | ||
| + | install_docker_if_missing | ||
| + | start_docker_if_needed | ||
| + | prepare_paths | ||
| + | build_dataset | ||
| + | ;; | ||
| + | start) | ||
| + | check_profile | ||
| + | install_docker_if_missing | ||
| + | start_docker_if_needed | ||
| + | prepare_paths | ||
| + | start_container | ||
| + | ;; | ||
| + | restart) | ||
| + | check_profile | ||
| + | install_docker_if_missing | ||
| + | start_docker_if_needed | ||
| + | prepare_paths | ||
| + | remove_container_if_exists | ||
| + | start_container | ||
| + | ;; | ||
| + | stop) | ||
| + | install_docker_if_missing | ||
| + | start_docker_if_needed | ||
| + | stop_container | ||
| + | ;; | ||
| + | status) | ||
| + | install_docker_if_missing | ||
| + | start_docker_if_needed | ||
| + | show_status | ||
| + | ;; | ||
| + | logs) | ||
| + | install_docker_if_missing | ||
| + | start_docker_if_needed | ||
| + | show_logs | ||
| + | ;; | ||
| + | url) | ||
| + | print_url | ||
| + | ;; | ||
| + | *) | ||
| + | usage | ||
| + | exit 1 | ||
| + | ;; | ||
| + | esac | ||
| + | } | ||
| + | |||
| + | main " | ||
| + | </ | ||
| + | |||
| + | < | ||
| + | sudo bash setup-osrm.sh build / | ||
| + | sudo bash setup-osrm.sh start / | ||
| + | sudo bash setup-osrm.sh status | ||
| + | sudo bash osrm-manager.sh stop | ||
| + | sudo bash osrm-manager.sh logs | ||
| + | </ | ||
| ====Ubuntu==== | ====Ubuntu==== | ||