Aller au contenu

Routage et dist_excess

Cette page décrit l'étape optionnelle qui prépare puis applique un calcul routé de dist_excess_m. Elle prolonge l'approche spatiale historique sans appeler Google Maps par défaut.

Rôle analytique

dist_excess_m vise à mesurer une distance additionnelle dans la zone finale de la leg voiture. Il compare :

  • la longueur observée sur la portion finale de la leg voiture après entrée dans le rayon de 1 000 m autour de la fin de leg, exportée sous spatial_search_distance_m ;
  • une distance routée de référence entre le point d'entrée dans ce rayon et la fin de la leg voiture.

Le calcul ne route donc pas la leg complète. La leg complète contient le trajet d'accès ordinaire à la destination. Le détour pertinent pour la recherche de stationnement est isolé sur la section finale située dans le rayon autour du stationnement supposé.

Avec le paramètre actuel destination_buffer_m: 1000, la distribution de spatial_search_distance_m présente mécaniquement beaucoup de valeurs proches ou supérieures à 1 km : quand la trace coupe le cercle, le point d'entrée est à 1 km à vol d'oiseau de la fin de leg, et la longueur parcourue sur la trace est généralement supérieure ou égale à cette distance. Ce n'est pas un seuil minimal de cruising. Les distances de cruising plus courtes ne sont pas filtrées par une règle à 1 km ; elles ne sont simplement pas mesurées directement par cette variable de fenêtre finale. Pour les impacts opérationnels, il faut donc distinguer :

  • spatial_search_distance_m : longueur de trace dans la fenêtre finale ;
  • dist_excess_positive_m : excès de distance par rapport au chemin routé de référence, plus proche d'une distance additionnelle.

Méthode historique reprise

Dans l'archive spatiale, le notebook WP2_WP3.ipynb procédait ainsi :

  1. extraire la dernière leg voiture avant l'activité de destination ;
  2. construire un buffer métrique autour de la destination, historiquement 1 000 m ;
  3. extraire la portion de leg après la dernière entrée dans ce buffer ;
  4. stocker le premier point de cette portion comme point_entry_buffer ;
  5. appeler Google Directions entre point_entry_buffer et destination en mode driving ;
  6. décoder la polyline retournée comme shortest_path ;
  7. calculer dist_excess = dist_buffer - shortest_path_length ;
  8. qualifier les cas dist_excess > 200 m comme suspects.

Le nouveau pipeline reprend les points 1 à 4 dans les étapes 22 et 23. Les colonnes préparées sont :

Colonne actuelle Rôle
spatial_affected_geometry_wkb_2056 portion finale observée dans le rayon spatial
spatial_entry_point_wkb_2056 origine du futur routage
destination_wkb_2056 destination du futur routage
spatial_search_distance_m longueur de portion observée depuis l'entrée dans le rayon final

Implémentation actuelle

Le routage est désormais préparé par trois scripts optionnels :

PYTHONPATH=src .venv-parking-search/bin/python scripts/25_prepare_routing_candidates.py --config config/default.yaml

Cette commande écrit :

  • Output/data/routing_candidates.parquet ;
  • Output/reports/routing_candidates.csv ;
  • Output/data/routing_candidates_xyt_payload.jsonl ;
  • Output/reports/routing_candidates_summary.json.

Le fichier JSONL contient une requête par ligne, au format attendu par xyt_routing :

{"route_id":"declic:...","origin":[6.14,46.20],"destination":[6.15,46.21],"mode":"car","weighting":"distance","geometry":true}

Une fois xyt_routing lancé localement, le routage peut être exécuté :

PYTHONPATH=src .venv-parking-search/bin/python scripts/26_route_dist_excess_xyt.py --config config/default.yaml

Par défaut, si Output/data/routing_results.parquet existe déjà et contient tous les route_id préparés, le script recharge ce cache et ne renvoie aucune requête au routeur. Pour forcer un nouveau calcul :

PYTHONPATH=src .venv-parking-search/bin/python scripts/26_route_dist_excess_xyt.py --config config/default.yaml --force

Puis les distances routées peuvent être fusionnées dans les sorties spatiales :

PYTHONPATH=src .venv-parking-search/bin/python scripts/27_apply_routing_dist_excess.py --config config/default.yaml

Cette dernière étape écrit notamment :

  • Output/data/routing_candidates_with_results.parquet ;
  • Output/data/routing_geometry_correspondence.parquet ;
  • Output/data/spatial_declic_candidates_routed.parquet ;
  • Output/data/pl23_spatial_candidates_routed.parquet ;
  • Output/maps/routing_geometry_comparison.html ;
  • Output/reports/routing_dist_excess_summary.json.

Par défaut, l'étape 27 refuse de fusionner un cache partiel. C'est volontaire : un smoke test lancé avec --max-requests ne doit pas être interprété comme un résultat final. Le paramètre routing.allow_partial_results: true existe uniquement pour un diagnostic manuel.

Routeur recommandé

Le choix recommandé est xyt_routing local avec OSRM distance sur le graphe régional ch_extended_200km. La version de réseau attendue pour cette itération est osm-ch_extended_200km-1418d8a09b76af1b.

cd /Users/marc-ed/BAS-local/repos/xyt_routing
docker compose --profile road-ch-extended-200km up -d \
  osrm-car-ch-extended-200km \
  osrm-car-distance-ch-extended-200km
XYT_ROUTING_SERVICE_CONFIG=configs/service.ch_extended_200km.yaml .venv/bin/xyt-routing-api

Puis, depuis ce dépôt :

PYTHONPATH=src .venv-parking-search/bin/python scripts/26_route_dist_excess_xyt.py --config config/default.yaml

Les coordonnées envoyées sont toujours en [longitude, latitude], EPSG:4326. Le paramètre routing.mode: car_ch_extended_200km force l'usage du graphe régional transfrontalier. Le paramètre weighting: distance demande le graphe voiture optimisé en distance lorsque celui-ci est disponible dans xyt_routing.

Ce choix remplace l'ancien routage partitionné DACH/France. Une leg dont l'origine et la destination sont de part et d'autre de la frontière doit être routée sur un graphe unique ; concaténer une route DACH et une route France imposerait un point de passage arbitraire et ne garantirait pas le plus court chemin.

Pourquoi pas Google par défaut

Google Maps peut être utile pour un audit ponctuel ou pour comparer un résultat commercial à OSRM local. L'API Routes dispose d'une option requestedReferenceRoutes: ["SHORTER_DISTANCE"], qui demande une route plus courte en distance pour l'ensemble du trajet. Cette option n'est pas équivalente à un graphe routier local versionné :

  • la facturation dépend des requêtes et des fonctionnalités activées ;
  • le graphe routier et les règles de choix d'itinéraire ne sont pas versionnés dans le projet ;
  • les résultats peuvent varier lorsque Google met à jour son réseau ou ses paramètres ;
  • l'exécution dépend d'une clé API et d'un quota.

Le coût Google n'est pas proportionnel à la distance routée. Le coût dépend d'abord des événements facturables, des SKU et des fonctionnalités activées. Router le tronçon dans le buffer plutôt que la leg complète ne vise donc pas principalement à économiser des crédits ; c'est surtout le bon choix analytique pour isoler la recherche de stationnement.

Si Google est utilisé plus tard, il doit produire le même contrat de sortie : route_id, routed_distance_m, routed_duration_seconds, routing_status, error_code, error_message, version ou date du provider, et éventuellement géométrie routée.

Sorties et interprétation

Après fusion, les principaux champs sont :

Champ Interprétation
routed_distance_m distance routée de référence
routed_duration_seconds durée routée de référence
dist_excess_m spatial_search_distance_m - routed_distance_m
dist_excess_positive_m partie positive de dist_excess_m
spatial_suspicious_dist_excess dist_excess_m > suspicious_dist_excess_m
spatial_candidate_routed règle conservatrice ou dist_excess suspect

La table routing_geometry_correspondence.parquet sert au contrôle et à l'export géométrique. Elle contient notamment :

Champ Interprétation
route_id clé stable de correspondance routage
leg_id identifiant de leg source
source_dataset declic ou pl23
observed_geometry_wkb_2056 portion GPS observée dans le buffer, EPSG:2056
routed_geometry_geojson géométrie routée retournée par xyt_routing, EPSG:4326
routed_geometry_wkb_2056 même géométrie routée projetée en EPSG:2056
observed_geometry_length_m longueur métrique de la géométrie observée
routed_geometry_length_m_2056 longueur métrique de la géométrie routée
network_version version du graphe routier local

La carte routing_geometry_comparison.html affiche un échantillon de cas avec :

  • segment GPS observé dans le buffer ;
  • route OSRM distance entre entrée buffer et destination ;
  • point d'entrée buffer ;
  • destination / fin de leg.

Un dist_excess_m négatif ou très faible n'implique pas nécessairement une absence de recherche de place. Il peut aussi venir d'une géométrie observée tronquée, d'un point d'entrée mal localisé, d'un routage non comparable ou d'un stationnement avant la destination déclarée.

Statut

La préparation des paires de routage est implémentée et testée. Le run courant utilise xyt_routing avec le graphe régional osm-ch_extended_200km-1418d8a09b76af1b. Le cache complet contient 36 949 routes valides sur 36 950 paires préparées. L'échec résiduel et les valeurs extrêmes de dist_excess_m doivent encore être audités avant de figer une Base 3 officielle.