Benutzer-Werkzeuge

Webseiten-Werkzeuge


osrm

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

Beide Seiten der vorigen Revision Vorhergehende Überarbeitung
Nächste Überarbeitung
Vorhergehende Überarbeitung
osrm [2026/03/29 00:46]
jango
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, sondern berechnet Wege zwischen bereits bekannten Koordinaten auf dem zugrunde liegenden Straßennetz. 
 + 
 +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://router.project-osrm.org/route/v1/driving/16.3725,48.2082;16.3738,48.2100?overview=false]] Demo [[https://router.project-osrm.org/route/v1/driving/16.3725,48.2082;16.3738,48.2100?overview=false]]
 +
 +<code python>
 +import requests
 +
 +def get_route(start_lon: float, start_lat: float, end_lon: float, end_lat: float) -> dict:
 +    url = (
 +        f"http://localhost:5000/route/v1/driving/"
 +        f"{start_lon},{start_lat};{end_lon},{end_lat}"
 +    )
 +    params = {
 +        "overview": "false",
 +        "steps": "true"
 +    }
 +
 +    response = requests.get(url, params=params, timeout=10)
 +    response.raise_for_status()
 +    return response.json()
 +
 +
 +result = get_route(16.37208, 48.20849, 16.37382, 48.20672)
 +
 +route = result["routes"][0]
 +print("Distanz in Metern:", route["distance"])
 +print("Dauer in Sekunden:", route["duration"])
 +</code>
 +
 +=====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, osrm-contract, osrm-partition und osrm-customize verwendet. Welche Schritte nötig sind, hängt vom gewählten Routing-Algorithmus ab. Die Dokumentation und projektnahen Quellen unterscheiden dabei insbesondere zwischen CH (Contraction Hierarchies) und MLD (Multi-Level Dijkstra).
 +
 +=====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://project-osrm.org/docs/v5.24.0/api/#route-service|route]] berechnet die schnellste Route zwischen Koordinaten auf Basis des gewählten Profils, zum Beispiel driving, bike oder foot. Er liefert unter anderem Distanz, Dauer und auf Wunsch Geometrien und Turn-by-Turn-Informationen.
 +
 +Beispiel:
 +
 +/route/v1/driving/16.37208,48.20849;16.37382,48.20672?overview=false
 +
 +====Nearest====
 +
 +Der Dienst [[https://project-osrm.org/docs/v5.24.0/api/#nearest-service|nearest]] ordnet eine Koordinate dem nächstgelegenen Straßensegment zu. Das ist nützlich, um GPS-Punkte auf das Routing-Netz zu „snappen“.
 +
 +====Table====
 +
 +Der Dienst [[https://project-osrm.org/docs/v5.24.0/api/#table-service|table]] berechnet eine Matrix aus Fahrzeiten oder Distanzen zwischen mehreren Koordinaten. Laut API-Dokumentation liefert table bei Distanzen nicht die Luftlinie, sondern die Distanzen der jeweils schnellsten Routen im Straßennetz.
 +
 +====Match====
 +
 +Der Dienst [[https://project-osrm.org/docs/v5.24.0/api/#match-service|match]] dient dem Map-Matching. Dabei werden GPS-Spuren auf wahrscheinliche Straßenverläufe abgebildet. Das ist besonders für Tracking- oder Flottenanwendungen relevant.
 +
 +====Trip====
 +
 +Der Dienst [[https://project-osrm.org/docs/v5.24.0/api/#trip-service|trip]] berechnet eine sinnvolle Reihenfolge für mehrere Wegpunkte. Das Problem ist verwandt mit dem Traveling-Salesman-Problem und eignet sich für einfache Tourenplanung.
 +
 +====Tile====
 +
 +Der Dienst [[https://project-osrm.org/docs/v5.24.0/api/#tile-service|tile]] stellt Kachelinformationen für Debugging und Visualisierung bereit.
 +
 +=====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, Einschränkungen oder Präferenzen behandelt werden. Die offiziellen Beispiele nennen insbesondere car, bike und foot.
 +
 +Dadurch lässt sich OSRM an verschiedene Einsatzszenarien anpassen, etwa für klassische Autonavigation, Fahrrad-Routing oder Fußwege. Eigene Profile sind möglich, wenn projektspezifische Regeln benötigt werden. Diese Schlussfolgerung ergibt sich aus der dokumentierten Profil-Logik und der Lua-basierten Konfiguration.
  
 =====Setup===== =====Setup=====
  
-====WSL====+  * Disk > 15GB 
 +  * RAM > 8GB
  
 +====WSL Demo====
 +Non persistent
 <code bash> <code bash>
 #!/usr/bin/env bash #!/usr/bin/env bash
Zeile 197: Zeile 277:
 </code> </code>
  
 +====Ubuntu Setup Manager====
 +
 +<code>
 +curl "https://download.geofabrik.de/europe/austria-latest.osm.pbf" -o austria-latest.osm.pbf
 +</code>
 +
 +<code bash>
 +#!/usr/bin/env bash
 +set -euo pipefail
 +
 +COMMAND="${1:-}"
 +PBF_PATH="${2:-}"
 +PROFILE="${3:-car}"
 +
 +PORT="${PORT:-5000}"
 +CONTAINER_NAME="${CONTAINER_NAME:-osrm-demo}"
 +WORKDIR="${WORKDIR:-/var/lib/osrm}"
 +IMAGE="${IMAGE:-osrm/osrm-backend}"
 +
 +need_root() {
 +  if [[ "${EUID}" -ne 0 ]]; then
 +    echo "Bitte mit sudo starten."
 +    echo "Beispiele:"
 +    echo "  sudo bash osrm-manager.sh build /pfad/austria-latest.osm.pbf car"
 +    echo "  sudo bash osrm-manager.sh start /pfad/austria-latest.osm.pbf car"
 +    exit 1
 +  fi
 +}
 +
 +usage() {
 +  cat <<EOF
 +Verwendung:
 +  sudo bash osrm-manager.sh build  /pfad/datei.osm.pbf [car|bike|foot]
 +  sudo bash osrm-manager.sh start  /pfad/datei.osm.pbf [car|bike|foot]
 +  sudo bash osrm-manager.sh stop
 +  sudo bash osrm-manager.sh restart /pfad/datei.osm.pbf [car|bike|foot]
 +  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=/var/lib/osrm
 +  IMAGE=osrm/osrm-backend
 +
 +Hinweis:
 +  Für jedes Profil werden eigene Daten verwendet:
 +    /var/lib/osrm/car
 +    /var/lib/osrm/bike
 +    /var/lib/osrm/foot
 +EOF
 +}
 +
 +check_profile() {
 +  case "$PROFILE" in
 +    car)
 +      LUA_PROFILE="/opt/car.lua"
 +      SERVICE_MODE="driving"
 +      ;;
 +    bike)
 +      LUA_PROFILE="/opt/bicycle.lua"
 +      SERVICE_MODE="cycling"
 +      ;;
 +    foot)
 +      LUA_PROFILE="/opt/foot.lua"
 +      SERVICE_MODE="walking"
 +      ;;
 +    *)
 +      echo "Fehler: Unbekanntes Profil '$PROFILE'. Erlaubt: car | bike | foot"
 +      exit 1
 +      ;;
 +  esac
 +
 +  export LUA_PROFILE SERVICE_MODE
 +}
 +
 +install_docker_if_missing() {
 +  if command -v docker >/dev/null 2>&1; then
 +    echo "Docker vorhanden: $(docker --version || true)"
 +    return
 +  fi
 +
 +  echo "==> Docker wird installiert"
 +
 +  apt-get update
 +  apt-get install -y ca-certificates curl
 +
 +  install -m 0755 -d /etc/apt/keyrings
 +  curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
 +  chmod a+r /etc/apt/keyrings/docker.asc
 +
 +  . /etc/os-release
 +  echo \
 +    "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu ${UBUNTU_CODENAME:-$VERSION_CODENAME} stable" \
 +    > /etc/apt/sources.list.d/docker.list
 +
 +  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 "${SUDO_USER:-}" ]]; then
 +    usermod -aG docker "$SUDO_USER" || true
 +  fi
 +}
 +
 +start_docker_if_needed() {
 +  if docker info >/dev/null 2>&1; then
 +    echo "Docker läuft."
 +    return
 +  fi
 +
 +  echo "==> Docker-Daemon wird gestartet"
 +  systemctl enable docker || true
 +  systemctl start docker || true
 +
 +  for _ in $(seq 1 20); do
 +    if docker info >/dev/null 2>&1; then
 +      echo "Docker läuft."
 +      return
 +    fi
 +    sleep 1
 +  done
 +
 +  echo "Fehler: Docker ist installiert, aber der Daemon läuft nicht."
 +  exit 1
 +}
 +
 +check_pbf_arg() {
 +  if [[ -z "$PBF_PATH" ]]; then
 +    echo "Fehler: Bitte Pfad zur .osm.pbf angeben."
 +    exit 1
 +  fi
 +
 +  if [[ ! -f "$PBF_PATH" ]]; then
 +    echo "Fehler: Datei nicht gefunden: $PBF_PATH"
 +    exit 1
 +  fi
 +}
 +
 +prepare_paths() {
 +  check_pbf_arg
 +
 +  PBF_ABS="$(readlink -f "$PBF_PATH")"
 +  PBF_BASENAME="$(basename "$PBF_ABS")"
 +  PBF_NAME="${PBF_BASENAME%.osm.pbf}"
 +
 +  PROFILE_DIR="${WORKDIR}/${PROFILE}"
 +  DATASET_FILE="${PROFILE_DIR}/${PBF_BASENAME}"
 +  OSRM_BASE="${PROFILE_DIR}/${PBF_NAME}.osrm"
 +  PROFILE_CONTAINER_NAME="${CONTAINER_NAME}-${PROFILE}"
 +
 +  mkdir -p "$PROFILE_DIR"
 +
 +  export PBF_ABS PBF_BASENAME PBF_NAME PROFILE_DIR DATASET_FILE OSRM_BASE PROFILE_CONTAINER_NAME
 +}
 +
 +require_prepared_dataset() {
 +  local missing=0
 +  local required=(
 +    "${OSRM_BASE}"
 +    "${OSRM_BASE}.ramIndex"
 +    "${OSRM_BASE}.fileIndex"
 +    "${OSRM_BASE}.edges"
 +    "${OSRM_BASE}.geometry"
 +    "${OSRM_BASE}.turn_weight_penalties"
 +    "${OSRM_BASE}.turn_duration_penalties"
 +    "${OSRM_BASE}.datasource_names"
 +    "${OSRM_BASE}.names"
 +    "${OSRM_BASE}.properties"
 +    "${OSRM_BASE}.icd"
 +  )
 +
 +  for f in "${required[@]}"; do
 +    if [[ ! -f "$f" ]]; then
 +      echo "Fehlt: $f"
 +      missing=1
 +    fi
 +  done
 +
 +  if [[ "$missing" -ne 0 ]]; then
 +    echo
 +    echo "Fehler: OSRM-Datensatz unvollständig."
 +    echo "Führe zuerst aus:"
 +    echo "  sudo bash osrm-manager.sh build \"$PBF_ABS\" \"$PROFILE\""
 +    exit 1
 +  fi
 +}
 +
 +remove_container_if_exists() {
 +  if docker ps -a --format '{{.Names}}' | grep -qx "$PROFILE_CONTAINER_NAME"; then
 +    echo "==> Entferne alten Container: $PROFILE_CONTAINER_NAME"
 +    docker rm -f "$PROFILE_CONTAINER_NAME" >/dev/null 2>&1 || true
 +  fi
 +}
 +
 +copy_input_if_needed() {
 +  if [[ -f "$DATASET_FILE" ]]; then
 +    local src_size dst_size
 +    src_size="$(stat -c '%s' "$PBF_ABS")"
 +    dst_size="$(stat -c '%s' "$DATASET_FILE" 2>/dev/null || echo 0)"
 +
 +    if [[ "$src_size" == "$dst_size" ]]; then
 +      echo "==> PBF bereits vorhanden: $DATASET_FILE"
 +      return
 +    fi
 +  fi
 +
 +  echo "==> Kopiere Eingabedatei nach $PROFILE_DIR"
 +  cp -f "$PBF_ABS" "$DATASET_FILE"
 +}
 +
 +cleanup_previous_dataset_files() {
 +  echo "==> Entferne alte OSRM-Dateien für $PBF_NAME in $PROFILE_DIR"
 +  find "$PROFILE_DIR" -maxdepth 1 -type f \
 +    \( -name "${PBF_NAME}.osrm*" -o -name "${PBF_NAME}.timestamp" \) \
 +    -print -delete || true
 +}
 +
 +build_dataset() {
 +  echo "==> Image laden"
 +  docker pull "$IMAGE"
 +
 +  copy_input_if_needed
 +  cleanup_previous_dataset_files
 +
 +  echo "==> osrm-extract ($PROFILE)"
 +  docker run --rm -t \
 +    -v "$PROFILE_DIR:/data" \
 +    "$IMAGE" \
 +    osrm-extract -p "$LUA_PROFILE" "/data/$PBF_BASENAME"
 +
 +  echo "==> osrm-partition"
 +  docker run --rm -t \
 +    -v "$PROFILE_DIR:/data" \
 +    "$IMAGE" \
 +    osrm-partition "/data/${PBF_NAME}.osrm"
 +
 +  echo "==> osrm-customize"
 +  docker run --rm -t \
 +    -v "$PROFILE_DIR:/data" \
 +    "$IMAGE" \
 +    osrm-customize "/data/${PBF_NAME}.osrm"
 +
 +  echo "==> Build abgeschlossen"
 +}
 +
 +start_container() {
 +  require_prepared_dataset
 +  remove_container_if_exists
 +
 +  echo "==> Starte Container $PROFILE_CONTAINER_NAME auf Port $PORT"
 +  docker run -d \
 +    --restart unless-stopped \
 +    --name "$PROFILE_CONTAINER_NAME" \
 +    -p "$PORT:5000" \
 +    -v "$PROFILE_DIR:/data" \
 +    "$IMAGE" \
 +    osrm-routed --algorithm mld "/data/${PBF_NAME}.osrm" >/dev/null
 +
 +  echo
 +  echo "Läuft."
 +  echo "Test-URL:"
 +  echo "  http://localhost:${PORT}/route/v1/${SERVICE_MODE}/16.3725,48.2082;16.3738,48.2100?overview=false"
 +}
 +
 +stop_container() {
 +  local found=0
 +  for p in car bike foot; do
 +    local name="${CONTAINER_NAME}-${p}"
 +    if docker ps -a --format '{{.Names}}' | grep -qx "$name"; then
 +      echo "==> Stoppe und entferne $name"
 +      docker rm -f "$name" >/dev/null 2>&1 || true
 +      found=1
 +    fi
 +  done
 +
 +  if [[ "$found" -eq 0 ]]; then
 +    echo "Kein passender Container gefunden."
 +  fi
 +}
 +
 +show_status() {
 +  echo "==> Docker"
 +  systemctl is-active docker || true
 +  echo
 +
 +  echo "==> Container"
 +  docker ps -a --filter "name=^${CONTAINER_NAME}-" --format 'table {{.Names}}\t{{.Status}}\t{{.Ports}}'
 +
 +  echo
 +  echo "==> Datensätze"
 +  for p in car bike foot; do
 +    local dir="${WORKDIR}/${p}"
 +    if [[ -d "$dir" ]]; then
 +      echo "--- $dir"
 +      ls -1 "$dir" | sed 's/^/  /' || true
 +    fi
 +  done
 +}
 +
 +show_logs() {
 +  local found=0
 +  for p in car bike foot; do
 +    local name="${CONTAINER_NAME}-${p}"
 +    if docker ps -a --format '{{.Names}}' | grep -qx "$name"; then
 +      found=1
 +      echo "==> Logs: $name"
 +      docker logs --tail 100 "$name"
 +      echo
 +    fi
 +  done
 +
 +  if [[ "$found" -eq 0 ]]; then
 +    echo "Kein passender Container gefunden."
 +  fi
 +}
 +
 +print_url() {
 +  check_profile
 +  echo "http://localhost:${PORT}/route/v1/${SERVICE_MODE}/16.3725,48.2082;16.3738,48.2100?overview=false"
 +}
 +
 +main() {
 +  need_root
 +
 +  case "$COMMAND" in
 +    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 "$@"
 +</code>
 +
 +<code>
 +sudo bash setup-osrm.sh build /home/austria-latest.osm.pbf foot
 +sudo bash setup-osrm.sh start /home/austria-latest.osm.pbf foot
 +sudo bash setup-osrm.sh status
 +sudo bash osrm-manager.sh stop
 +sudo bash osrm-manager.sh logs
 +</code>
 ====Ubuntu==== ====Ubuntu====
  
osrm.1774741601.txt.gz · Zuletzt geändert: 2026/03/29 00:46 von jango