ITSkillsCenter
Business Digital

Optimiser les tournées de livraison avec OSRM : tutoriel 2026

12 min de lecture

📍 Article principal : Stack logistique PME 2026

Introduction

Une PME de livraison à Ouagadougou observait que ses coursiers parcouraient en moyenne 85 km par jour pour effectuer 25 livraisons, soit 3,4 km par livraison. Une analyse manuelle des trajets a révélé qu’avec un ordre optimal des destinations et un regroupement intelligent par zone, la même charge de travail aurait pu être faite en 52 km, soit une économie de 33 km par jour et par coursier. Multipliée par 12 coursiers et 30 jours, cela représente près de 12 000 km par mois économisés, soit environ 1 000 litres de carburant à 700 FCFA le litre — 700 000 FCFA mensuels d’économies, plus le temps gagné qui permet d’effectuer 30 % de courses supplémentaires sans recruter. Ce tutoriel décrit l’installation d’OSRM avec les données OpenStreetMap d’Afrique de l’Ouest, le calcul de matrices de distances, et la résolution du problème du voyageur de commerce (TSP) pour optimiser les tournées en temps réel.

Prérequis

  • VPS Hetzner Cloud (CX22 ou CX32 selon la zone géographique couverte)
  • 20-50 Go d’espace disque pour les données OSM
  • Docker installé pour faciliter le déploiement OSRM
  • Backend logistique fonctionnel qui gère les courses
  • Niveau : intermédiaire avancé — Temps : 3 heures

Étape 1 — Installer OSRM avec Docker

OSRM se déploie facilement via une image Docker officielle qui inclut le serveur de routing et les outils de pré-traitement des données OSM. Le processus en trois étapes : télécharger le fichier OSM de la région cible (extrait Geofabrik d’Afrique de l’Ouest), pré-traiter avec l’algorithme MLD ou CH selon les besoins, lancer le serveur qui expose l’API HTTP.

mkdir -p /srv/osrm/data
cd /srv/osrm/data

# Télécharger l'extrait Afrique de l'Ouest depuis Geofabrik (3-5 Go)
wget https://download.geofabrik.de/africa/west-africa-latest.osm.pbf

# Pré-traitement avec algorithme MLD (Multi-Level Dijkstra)
docker run -t -v /srv/osrm/data:/data ghcr.io/project-osrm/osrm-backend osrm-extract -p /opt/car.lua /data/west-africa-latest.osm.pbf
docker run -t -v /srv/osrm/data:/data ghcr.io/project-osrm/osrm-backend osrm-partition /data/west-africa-latest.osrm
docker run -t -v /srv/osrm/data:/data ghcr.io/project-osrm/osrm-backend osrm-customize /data/west-africa-latest.osrm

# Lancer le serveur
docker run -t -i -p 5000:5000 -v /srv/osrm/data:/data ghcr.io/project-osrm/osrm-backend osrm-routed --algorithm mld /data/west-africa-latest.osrm

Le pré-traitement complet prend 30 à 60 minutes sur un CX22 selon la zone. Pour la majorité des PME ouest-africaines opérant dans une seule ville, on peut utiliser un extrait plus petit (par exemple un fichier régional) pour accélérer le pré-traitement et réduire l’empreinte mémoire. Pour Abidjan seul, un extrait régional fait moins de 500 Mo et le pré-traitement prend 5-10 minutes. Pour servir Dakar, Bamako, Niamey simultanément, prendre l’extrait pays complet ou multi-pays selon le périmètre.

Étape 2 — Exploiter l’API OSRM depuis Hono

Une fois OSRM démarré, il expose une API REST sur le port 5000 avec quatre endpoints principaux : route (calcul d’itinéraire entre deux points), table (matrice de distances entre N points), match (alignement de coordonnées GPS bruitées sur le réseau routier), trip (résolution du voyageur de commerce avec ordonnancement). Pour notre cas d’usage logistique, l’endpoint trip est le plus important car il résout directement le problème d’optimisation des tournées.

// Service OSRM côté backend Hono
const OSRM_URL = 'http://localhost:5000';

interface Point { id: string; lat: number; lng: number; }

export async function optimiserTournee(points: Point[], debut: Point) {
  const tousLesPoints = [debut, ...points];
  const coords = tousLesPoints.map(p => `${p.lng},${p.lat}`).join(';');

  const url = `${OSRM_URL}/trip/v1/driving/${coords}?source=first&roundtrip=false`;
  const r = await fetch(url);
  if (!r.ok) throw new Error('OSRM trip failed: ' + r.status);
  const data = await r.json();

  // L'index waypoint_index donne le nouvel ordre optimal
  const ordre = data.waypoints.map((w: any, i: number) => ({
    pointOriginal: tousLesPoints[i],
    positionDansTournee: w.waypoint_index
  })).sort((a: any, b: any) => a.positionDansTournee - b.positionDansTournee);

  return {
    ordre,
    distanceTotaleM: data.trips[0].distance,
    dureeEstimeeS: data.trips[0].duration,
    geometrie: data.trips[0].geometry
  };
}

Le paramètre source=first impose que le coursier démarre depuis son point actuel (premier de la liste). Le paramètre roundtrip=false indique qu’on ne revient pas au point de départ — utile quand le coursier termine sa tournée chez lui ou continue vers une autre zone. Pour des tournées avec retour au siège, mettre roundtrip=true.

Étape 3 — Matrice de distances pour assignation

Pour optimiser non seulement l’ordre mais aussi l’assignation des courses aux coursiers, on utilise l’endpoint table qui retourne la matrice de distances entre tous les points. Cette matrice permet d’appliquer des algorithmes d’optimisation plus avancés (Vehicle Routing Problem, VRP) qui déterminent quel coursier prend quelle course en fonction de leurs positions actuelles et des destinations.

// Calcul matrice complete
async function matriceDistances(points: Point[]) {
  const coords = points.map(p => `${p.lng},${p.lat}`).join(';');
  const url = `${OSRM_URL}/table/v1/driving/${coords}?annotations=duration,distance`;
  const r = await fetch(url);
  const data = await r.json();
  return {
    durations: data.durations, // matrice NxN en secondes
    distances: data.distances  // matrice NxN en mètres
  };
}

Avec cette matrice, on peut implémenter un algorithme VRP simple : pour chaque nouvelle course, calculer le coût d’insertion dans la tournée de chaque coursier disponible, choisir le coursier qui minimise l’augmentation de la distance totale. Cette heuristique gloutonne donne des résultats proches de l’optimum sur des problèmes de taille raisonnable (sous 50 courses simultanées) avec un coût computationnel négligeable.

Étape 4 — Algorithme TSP local pour gros volumes

Pour les tournées avec plus de 30-40 destinations, l’API trip d’OSRM peut devenir lente (plusieurs secondes). Une alternative : récupérer la matrice via l’endpoint table, puis appliquer un algorithme TSP local en JavaScript. L’heuristique nearest neighbor suivie de 2-opt donne des résultats à 5-10 % de l’optimum en quelques millisecondes pour 50 points.

function tspNearestNeighbor(matrix: number[][], depart: number = 0): number[] {
  const n = matrix.length;
  const visited = new Set([depart]);
  const ordre = [depart];
  let courant = depart;

  while (visited.size < n) {
    let plusProche = -1;
    let distMin = Infinity;
    for (let i = 0; i < n; i++) {
      if (!visited.has(i) && matrix[courant][i] < distMin) {
        distMin = matrix[courant][i];
        plusProche = i;
      }
    }
    visited.add(plusProche);
    ordre.push(plusProche);
    courant = plusProche;
  }
  return ordre;
}

// Amélioration 2-opt
function twoOpt(ordre: number[], matrix: number[][]): number[] {
  let amelioration = true;
  while (amelioration) {
    amelioration = false;
    for (let i = 1; i < ordre.length - 1; i++) {
      for (let j = i + 1; j < ordre.length; j++) {
        const avant = matrix[ordre[i-1]][ordre[i]] + matrix[ordre[j]][ordre[(j+1) % ordre.length]];
        const apres = matrix[ordre[i-1]][ordre[j]] + matrix[ordre[i]][ordre[(j+1) % ordre.length]];
        if (apres < avant) {
          ordre.splice(i, j - i + 1, ...ordre.slice(i, j + 1).reverse());
          amelioration = true;
        }
      }
    }
  }
  return ordre;
}

Cette combinaison nearest neighbor plus 2-opt donne typiquement 95-98 % de l’optimum théorique en moins de 100 ms pour 50 points. Pour les besoins d’une PME logistique ouest-africaine, c’est largement suffisant et permet de recalculer dynamiquement les tournées quand de nouvelles courses arrivent en cours de journée.

Étape 5 — Gérer les contraintes spécifiques

Les tournées réelles ont des contraintes que le TSP basique n’intègre pas. Trois contraintes courantes en logistique ouest-africaine. Premièrement, les fenêtres de temps : un destinataire n’est disponible qu’entre 14h et 17h. Le système doit ordonner les courses pour respecter ces contraintes ou alerter quand c’est impossible. Deuxièmement, les capacités véhicule : un coursier en moto ne peut pas transporter plus de 5 colis simultanément. Le système doit grouper les ramassages et livraisons pour respecter cette limite. Troisièmement, les zones interdites : pendant la saison des pluies, certaines rues d’Adjamé deviennent impraticables. La carte OSRM peut être annotée pour exclure ces zones.

Pour ces contraintes, un solveur VRP open-source comme VROOM ou Or-Tools de Google donne des résultats supérieurs au TSP simple. VROOM s’installe également en Docker à côté d’OSRM et gère les fenêtres de temps, capacités, et compétences (par exemple, courses nécessitant un véhicule réfrigéré). Pour une PME qui dépasse 100 livraisons par jour avec contraintes complexes, l’investissement dans VROOM (une journée d’intégration) se rentabilise rapidement.

Erreurs fréquentes

Erreur Cause Solution
OSRM retourne « no route found » Coordonnées GPS hors zone OSM Vérifier que les coordonnées sont bien dans la zone couverte
Pré-traitement OOM RAM insuffisante pour gros extrait Utiliser un extrait plus petit ou CX32 plus de RAM
Distances incohérentes vs réalité Données OSM obsolètes Mettre à jour mensuellement et contribuer à OSM localement
Tournées identiques d’un jour à l’autre Pas de re-optimisation à chaque ajout Recalculer à chaque nouvelle course intégrée
API OSRM lente Algorithme CH au lieu de MLD pour gros volumes Préférer MLD pour les opérations table fréquentes

Adaptation au contexte ouest-africain

Trois aspects pratiques. Premièrement, les données OSM en Afrique de l’Ouest ont une qualité variable selon les villes — excellente à Dakar et Abidjan grâce à des contributeurs actifs, plus lacunaire à Niamey ou Bobo-Dioulasso. Pour les zones moins couvertes, contribuer activement à OSM (cartographier les rues manquantes, ajouter les adresses, marquer les commerces) améliore les calculs OSRM et profite à toute la communauté locale. C’est un investissement collectif qui paye sur la durée. Deuxièmement, pour les optimisations qui prennent en compte les conditions de trafic réelles (heures de pointe à Cocody, embouteillages chroniques sur le pont Houphouët-Boigny), on enrichit le profil OSRM avec des données de vitesse moyenne par segment et par heure. Cette personnalisation demande du travail mais améliore significativement la précision des estimations de temps. Troisièmement, l’intégration avec les APIs trafic (Google Maps Traffic API ou TomTom) reste possible mais coûteuse — pour une PME, OSRM avec données OSM enrichies localement donne 90 % du bénéfice à 0 % du coût.

Pour le coût total d’opération de la solution OSRM auto-hébergée, on tient sous 10 euros par mois (VPS CX22 dédié) pour servir une PME entière. Les calculs sont faits en local, aucune donnée client ne quitte l’infrastructure de l’entreprise — argument de souveraineté apprécié par les clients institutionnels.

Tutoriels frères

Pour aller plus loin

FAQ

Combien de RAM faut-il pour OSRM en Afrique de l’Ouest ?
Pour l’extrait complet de la sous-région, environ 4-6 Go en utilisation. Un VPS CX22 (4 Go RAM) gère un pays seul ; CX32 (8 Go) couvre plusieurs pays.

Faut-il préférer OSRM, GraphHopper, ou Valhalla ?
Les trois sont valables. OSRM est le plus rapide pour les calculs simples. GraphHopper a une meilleure UX et plus de fonctionnalités. Valhalla est plus moderne mais plus lourd. Pour une PME qui démarre, OSRM est le plus pragmatique.

Comment mettre à jour les données OSM ?
Re-télécharger l’extrait Geofabrik et relancer le pré-traitement chaque mois. Automatisable via un cron + script.

Peut-on personnaliser le profil de routing pour les motos ?
Oui via les fichiers Lua de profil OSRM. Le profil moto autorise plus de routes que voiture (pistes, raccourcis non-revêtus). Plusieurs profils communautaires sont disponibles sur GitHub.

VROOM pour les contraintes complexes

VROOM (Vehicle Routing Open-source Optimization Machine) est un solveur OSS qui complète OSRM pour les cas d’optimisation avec contraintes multiples. Il accepte un fichier JSON décrivant les véhicules (avec leurs capacités et compétences), les jobs (avec leurs fenêtres temporelles et requirements), et les distances (calculées par OSRM en amont). Il retourne en quelques secondes l’assignation optimale et l’ordre des étapes pour chaque véhicule. Pour une PME logistique avec 10 coursiers et 100 livraisons quotidiennes incluant des fenêtres horaires (livraison entre 14h et 16h), VROOM trouve l’ordonnancement optimal en moins de 5 secondes — humainement impossible à reproduire manuellement.

L’intégration de VROOM dans une stack Hono se fait via son API HTTP exposée par un container Docker dédié. L’orchestration est simple : le backend collecte les courses du jour, les coursiers disponibles avec leurs positions, lance VROOM, récupère le plan optimisé, et le distribue aux apps coursier. Cette orchestration tourne typiquement chaque matin à 6h ou en temps réel à chaque nouvelle course majeure. Le bénéfice mesuré sur une PME ivoirienne après mise en place : 28 % de courses supplémentaires effectuées avec la même flotte, économies essence de 22 %.

Recalcul dynamique en cours de journée

Au-delà du planning matinal, le système doit s’adapter en cours de journée aux imprévus : nouvelle course urgente arrive en milieu de matinée, un coursier tombe en panne, un client annule au dernier moment. Le pattern dynamique recalcule le plan optimal toutes les 15-30 minutes en intégrant l’état actuel (positions des coursiers, courses déjà effectuées, courses restantes, nouvelles courses entrantes). Cette adaptation permanente maintient l’efficacité même face aux aléas du terrain.

Pour la performance, ce recalcul tient sous 1-2 secondes même avec 50 courses et 10 coursiers grâce aux algorithmes heuristiques modernes. Le coût computationnel est négligeable face aux gains opérationnels. Le seul piège à éviter : ne pas faire osciller les assignations entre coursiers (un coursier voit sa course X retirée et redonnée 5 minutes plus tard). On stabilise via un coût fixe d’inertie qui pénalise les changements d’assignation, donnant au système une préférence légère pour la continuité.

Besoin d'un site web ?

Confiez-nous la Création de Votre Site Web

Site vitrine, e-commerce ou application web — nous transformons votre vision en réalité digitale. Accompagnement personnalisé de A à Z.

À partir de 250.000 FCFA
Parlons de Votre Projet
Publicité