#
Introduction #
Bienvenue dans le guide d'utilisation de notre API de calcul d'itinéraires et de planification !
La version 1.1 a ajouté la prise en charge des modèles d'itinéraire
v1.2 : ajout de la prise en charge de la configuration flexible de la capacité des véhicules
Notre API est conçue pour optimiser la planification des itinéraires et la gestion des horaires des flottes de véhicules, en tenant compte des contraintes essentielles telles que les créneaux horaires de service, les limites de capacité et les conditions de circulation. En tirant parti de notre API, les entreprises peuvent améliorer considérablement l'efficacité de leurs livraisons, réduire leurs coûts opérationnels et gagner un temps précieux grâce à des solutions optimisées de planification d'itinéraires et de gestion des horaires.
Fondamentalement, l'API résout le problème du routage de véhicules (VRP) avec enlèvement et livraison. Ce problème consiste à calculer les itinéraires les plus efficaces pour qu'une flotte se rende à plusieurs endroits afin d'effectuer des opérations d'enlèvement et de livraison, tout en respectant des contraintes telles que les créneaux horaires, la capacité des véhicules et leur disponibilité.
De plus, notre API prend en charge les ajustements dynamiques ou la réoptimisation des plannings. Si vous devez modifier un planning existant — que ce soit en raison de nouvelles commandes, d'annulations ou d'autres changements —, vous pouvez fournir une version mise à jour de votre planning en précisant le statut des missions et la position des véhicules. L'API réoptimisera alors le planning pour tenir compte de ces changements, garantissant ainsi une efficacité constante de vos opérations.
Pour savoir comment vous lancer rapidement et commencer à utiliser l'API, consultez la section « Pour commencer ». Plusieurs tutoriels rapides sont également disponibles dans la section « Tutoriels ».
Commencer #
L'API propose deux méthodes principales pour gérer l'optimisation du routage et de la planification :
Optimisation POST – Utilisez cette méthode pour soumettre un problème d'optimisation d'itinéraire et de planification. Après avoir envoyé une requête POST, vous recevrez un identifiant de référence unique.
Optimisation GET – Utilisez cette méthode pour récupérer le statut d'un problème soumis à l'aide de l'identifiant de référence unique obtenu lors de la requête POST. Si la solution d'optimisation est prête, vous pouvez récupérer la solution du problème d'optimisation.
Méthode POST d'optimisation #
POST : https://iq.ui.scheduledroutes.ddswireless.net
Utilisez cette méthode pour soumettre votre problème d'optimisation d'itinéraire et de planification à l'API. Une fois la requête POST d'optimisation envoyée avec succès, l'API renverra un identifiant de référence unique dans la réponse d'accusé de réception. Utilisez cet identifiant unique pour récupérer la solution à l'aide de la méthode GET d'optimisation ( voir la section suivante).
Exemple d'envoi d'un problème d'optimisation via la méthode POST, à l'aide d'un jeton et d'une charge utile d'exemple :
curl -X POST "https://iq.scheduledroutes.ddswireless.net/raas/optimization"
-H "Content-Type: application/json"
-H "Authorization: Bearer fgJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJhZWU2MDQyZC0zN2E3LTQxNDYtODRlYy04YWU3M2ViODQ4YTgiLCJmaXJzdE5hbWUiOiJUZWMiLCJsYXN0TmFtZSI6IlRyYW5zaXQiLCJzZXF1ZW5jZU51bWJlciI6MSwicm9sZU5hbWVzIjpbImFkbWluIl0sInByb3ZpZGVyTmFtZXMiOlsiQUxMIl0sInVzZXJUZW5hbnRzIjpbMl0sInBlcm1pc3Npb25zIjpbMCwxNjYsMTcwLDE4MSwxODYsMTkxLDIwMCwxLDIsMyw0LDUsNiw3LDgsOSwxMCwxMSwxMiwxMywxNCwxNSwxNiwxNywxOCwxOSwyMCwyMSwyMiwyMywyNCwyNSwyNiwyNywyOCwxNTgsMTU5LDE2MywxNjgsMTgyLDE4OSwxNTcsMTE4LDExOSwxMjAsMTIxLDEyMiwxMjMsMTc1LDE3NiwxOTcsMTk1LDIwNSwyMDIsMjAzLDIwNiwyMTcsMjE5LDE5NiwyMDcsMTk0LDIxNCwyMTgsMjIwLDI5LDMwLDMxLDMyLDMzLDM0LDM1LDM2LDM3LDM4LDM5LDQwLDQxLDQyLDQzLDQ0LDQ1LDQ2LDQ3LDQ4LDQ5LDUwLDUxLDUyLDUzLDU0LDU1LDU2LDU3LDU4LDU5LDYwLDYxLDYzLDY0LDY1LDY2LDY3LDY4LDY5LDcwLDcxLDcyLDczLDc0LDc1LDc2LDc3LDgyLDgzLDg2LDg3LDg4LDg5LDkxLDkyLDkzLDk0LDk1LDk2LDEwMCwxMDEsMTAyLDEwMywxMDQsMTA1LDEwNiwxMDcsMTA4LDEwOSwxMTAsMTExLDExMiwxMTMsMTE0LDExNSwxMTYsMTE3LDEyNCwxMjUsMTI2LDEyNywxMjgsMTI5LDEzMCwxMzEsMTMyLDEzMywxMzQsMTM1LDEzNiwxMzcsMTM4LDEzOSwxNDAsMTQxLDE0MiwxNDMsMTQ0LDE0NSwxNDYsMTQ3LDE0OCwxNDksMTUwLDE1MSwxNTIsMTUzLDE1NCwxNTUsMTU2LDE2MiwxNjUsMTcxLDE4NCwxODcsMTkyLDE5OSwxNzMsMTk4LDE2MCwxNjEsMTY5LDE4MywxODgsODQsOTcsOTgsOTksMTY3LDE3MiwxODAsMTg1LDE5MCwxOTMsMTc0LDE2NCwyMDQsMjE1XSwicGFzc3dvcmRVcGRhdGVkQXQiOiIiLCJ0ZW5hbnQiOnsiaWQiOjIsIm5hbWUiOiJ0ZWNUcmFuc2l0Iiwic2l0ZUlkIjoiOTQiLCJ0aW1lem9uZSI6IkFtZXJpY2EvTG9zX0FuZ2VsZXMiLCJ0eXBlIjoiUmFhUyIsInNlc1VybCI6Imh0dHA6Ly9zdHJhdGVneS1lbmdpbmUtbXVsdGktdGVuYW50LTM6MTYwMDAiLCJkaXNwbGF5TmFtZSI6IlRlYyBUcmFuc2l0In0sInJvbGVzIjpbMjBdLCJpYXQiOjE3NDE5MDU2ODIsImV4cCI6MTc0NDQ5NzY4MiwiaXNzIjoiaXEuc2NoZWR1bGVkcm91dGVzLmRkc3dpcmVsZXNzLm5ldCJ9.fmdXyIylp604DCewvtuKCqLGhh-GFPfJNC9p2v4D-kHxhN2ZmRkHfknpTjiWZOZnB7AnWTUAh6BfZztNR_KLpQDPXcEpNL01lrw7ypIuwIf6CwA3Kwh916mNX-kgvPsyRQvAnvkyd-YO8M6zd_lsVD8oRnb-g07Vta3s3U-Y5uyWnQzv9PEeRf2IizflzlMkM7f1q472_3FQAEmomqMrSreK-YwUP9YxzD-QOW4GaaIUK5pgnzFYgEH2DFNU8KtDPeRdEk1cXL8aACFeawZnYzndvNcuv5fxd-9r-Y4-Tr8NiUwerdhRX3CuD5L5E6JVQdYOUJMFtSVpCbV7smaOJa"
-d @payload.json
Dans l'exemple ci-dessus, nous avons supposé que le problème d'entrée se trouve dans un fichier nommé payload.json. Vous devez remplacer le jeton d'exemple <strong>fgJhbGciOiJSUzI1N</strong>..... avec votre propre jeton. Le schéma du problème d'entrée est défini dans la section « Problème ».
Une fois la requête POST envoyée, vous recevrez un message de réponse au format suivant :
Schéma de réponse pour la méthode POST :
{
"id": "string",
"message": "string",
"status": "string",
"error" : "string"
}
Si la soumission aboutit, le status sera « 202 », avec le message avec la mention « accepté » et le id qui correspond au numéro de référence unique de l'opération asynchrone. Cet identifiant sert à suivre l'état de l'opération et à récupérer les résultats ultérieurement. En cas d'erreur, le status affichera un code d'erreur, le id sera nul ou vide, le message sera un « échec » et le error décrira l'erreur. Pour plus de détails, veuillez vous reporter aux codes d'état POST ci-dessous.
Exemple POST (Windows PowerShell) :
Le script ci-dessous montre comment effectuer une requête POST à l'aide d'une charge utile d'exemple dans Windows PowerShell. Il part du principe que la charge utile d'entrée est stockée dans un fichier nommé payload.json, et le jeton d'accès à l'API est enregistré dans token.txt. Lors de l'exécution, l'identifiant généré est enregistré dans id.txt. Pour lancer PowerShell, il suffit de taper « PowerShell » dans le menu Démarrer ou dans la ligne de commande.
$token = Get-Content token.txt -Raw
$headers = @{
Authorization = "Bearer $token"
"Content-Type" = "application/json"
}
$body = Get-Content payload.json -Raw
$response = Invoke-RestMethod -Uri "https://iq.scheduledroutes.ddswireless.net/raas/optimization" -Method Post -Headers $headers -Body $body
$response.id | Out-File -Encoding utf8 id.txt
Write-Output $response
Codes d'état POST #
| Code de réponse | Description | Remarques supplémentaires |
|---|---|---|
| 202 | La demande a été acceptée pour traitement. | Un identifiant de référence vous est fourni ; vous pouvez l'utiliser dans une requête GET pour récupérer la solution dès qu'elle est prête. |
| 400 | Échec de la validation des données saisies (erreur de requête). | Paramètre manquant ou non valide, ou type de valeur incorrect. Vérifiez les données saisies et réessayez. |
| 403 | Demande non autorisée. | Cela se produit lorsque l'authentification échoue. |
| 404 | Chemin d'accès demandé introuvable. | Cela se produit lorsqu'un chemin d'accès incorrect est utilisé. |
| 429 | Trop de demandes. | Limite de débit dépassée (nombre de requêtes par minute ou quota atteint). |
| 500 | Erreur interne du service. | Problème de notre côté. Contactez support@ddswireless.com. |
Optimisation de la méthode GET #
GET: https://iq.ui.scheduledroutes.ddswireless.net/{id}
Utilisez cette méthode pour récupérer la solution optimisée correspondant aux tâches d'optimisation créées à l'aide de la méthode POST d'optimisation. Pour ce faire, vous devez indiquer l'identifiant de référence reçu lors de l'appel de la méthode POST.
Exemple permettant d'obtenir la réponse de l'API à l'aide de la méthode GET avec un identifiant :
curl -X GET "https://iq.scheduledroutes.ddswireless.net/raas/optimization/ID"
-H "Content-Type: application/json"
-H "Authorization: Bearer fgkhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJhZWU2MDQyZC0zN2E3LTQxNDYtODRlYy04YWU3M2ViODQ4YTgiLCJmaXJzdE5hbWUiOiJUZWMiLCJsYXN0TmFtZSI6IlRyYW5zaXQiLCJzZXF1ZW5jZU51bWJlciI6MSwicm9sZU5hbWVzIjpbImFkbWluIl0sInByb3ZpZGVyTmFtZXMiOlsiQUxMIl0sInVzZXJUZW5hbnRzIjpbMl0sInBlcm1pc3Npb25zIjpbMCwxNjYsMTcwLDE4MSwxODYsMTkxLDIwMCwxLDIsMyw0LDUsNiw3LDgsOSwxMCwxMSwxMiwxMywxNCwxNSwxNiwxNywxOCwxOSwyMCwyMSwyMiwyMywyNCwyNSwyNiwyNywyOCwxNTgsMTU5LDE2MywxNjgsMTgyLDE4OSwxNTcsMTE4LDExOSwxMjAsMTIxLDEyMiwxMjMsMTc1LDE3NiwxOTcsMTk1LDIwNSwyMDIsMjAzLDIwNiwyMTcsMjE5LDE5NiwyMDcsMTk0LDIxNCwyMTgsMjIwLDI5LDMwLDMxLDMyLDMzLDM0LDM1LDM2LDM3LDM4LDM5LDQwLDQxLDQyLDQzLDQ0LDQ1LDQ2LDQ3LDQ4LDQ5LDUwLDUxLDUyLDUzLDU0LDU1LDU2LDU3LDU4LDU5LDYwLDYxLDYzLDY0LDY1LDY2LDY3LDY4LDY5LDcwLDcxLDcyLDczLDc0LDc1LDc2LDc3LDgyLDgzLDg2LDg3LDg4LDg5LDkxLDkyLDkzLDk0LDk1LDk2LDEwMCwxMDEsMTAyLDEwMywxMDQsMTA1LDEwNiwxMDcsMTA4LDEwOSwxMTAsMTExLDExMiwxMTMsMTE0LDExNSwxMTYsMTE3LDEyNCwxMjUsMTI2LDEyNywxMjgsMTI5LDEzMCwxMzEsMTMyLDEzMywxMzQsMTM1LDEzNiwxMzcsMTM4LDEzOSwxNDAsMTQxLDE0MiwxNDMsMTQ0LDE0NSwxNDYsMTQ3LDE0OCwxNDksMTUwLDE1MSwxNTIsMTUzLDE1NCwxNTUsMTU2LDE2MiwxNjUsMTcxLDE4NCwxODcsMTkyLDE5OSwxNzMsMTk4LDE2MCwxNjEsMTY5LDE4MywxODgsODQsOTcsOTgsOTksMTY3LDE3MiwxODAsMTg1LDE5MCwxOTMsMTc0LDE2NCwyMDQsMjE1XSwicGFzc3dvcmRVcGRhdGVkQXQiOiIiLCJ0ZW5hbnQiOnsiaWQiOjIsIm5hbWUiOiJ0ZWNUcmFuc2l0Iiwic2l0ZUlkIjoiOTQiLCJ0aW1lem9uZSI6IkFtZXJpY2EvTG9zX0FuZ2VsZXMiLCJ0eXBlIjoiUmFhUyIsInNlc1VybCI6Imh0dHA6Ly9zdHJhdGVneS1lbmdpbmUtbXVsdGktdGVuYW50LTM6MTYwMDAiLCJkaXNwbGF5TmFtZSI6IlRlYyBUcmFuc2l0In0sInJvbGVzIjpbMjBdLCJpYXQiOjE3NDE5MDU2ODIsImV4cCI6MTc0NDQ5NzY4MiwiaXNzIjoiaXEuc2NoZWR1bGVkcm91dGVzLmRkc3dpcmVsZXNzLm5ldCJ9.fmdXyIylp604DCewvtuKCqLGhh-GFPfJNC9p2v4D-kHxhN2ZmRkHfknpTjiWZOZnB7AnWTUAh6BfZztNR_KLpQDPXcEpNL01lrw7ypIuwIf6CwA3Kwh916mNX-kgvPsyRQvAnvkyd-YO8M6zd_lsVD8oRnb-g07Vta3s3U-Y5uyWnQzv9PEeRf2IizflzlMkM7f1q472_3FQAEmomqMrSreK-YwUP9YxzD-QOW4GaaIUK5pgnzFYgEH2DFNU8KtDPeRdEk1cXL8aACFeawZnYzndvNcuv5fxd-9r-Y4-Tr8NiUwerdhRX3CuD5L5E6JVQdYOUJMFtSVpCbV7smaOJs"
Dans l'exemple ci-dessus, remplacez ID dans l'URL avec l'URL obtenue via la méthode POST. Par exemple, si ID est égal à 5, utilisez ceci :
curl -X GET "https://iq.scheduledroutes.ddswireless.net/raas/optimization/5"
-H "Content-Type: application/json"
-H "Authorization: Bearer fgkhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiJhZWU2MDQyZC0zN2E3LTQxNDYtODRlYy04YWU3M2ViODQ4YTgiLCJmaXJzdE5hbWUiOiJUZWMiLCJsYXN0TmFtZSI6IlRyYW5zaXQiLCJzZXF1ZW5jZU51bWJlciI6MSwicm9sZU5hbWVzIjpbImFkbWluIl0sInByb3ZpZGVyTmFtZXMiOlsiQUxMIl0sInVzZXJUZW5hbnRzIjpbMl0sInBlcm1pc3Npb25zIjpbMCwxNjYsMTcwLDE4MSwxODYsMTkxLDIwMCwxLDIsMyw0LDUsNiw3LDgsOSwxMCwxMSwxMiwxMywxNCwxNSwxNiwxNywxOCwxOSwyMCwyMSwyMiwyMywyNCwyNSwyNiwyNywyOCwxNTgsMTU5LDE2MywxNjgsMTgyLDE4OSwxNTcsMTE4LDExOSwxMjAsMTIxLDEyMiwxMjMsMTc1LDE3NiwxOTcsMTk1LDIwNSwyMDIsMjAzLDIwNiwyMTcsMjE5LDE5NiwyMDcsMTk0LDIxNCwyMTgsMjIwLDI5LDMwLDMxLDMyLDMzLDM0LDM1LDM2LDM3LDM4LDM5LDQwLDQxLDQyLDQzLDQ0LDQ1LDQ2LDQ3LDQ4LDQ5LDUwLDUxLDUyLDUzLDU0LDU1LDU2LDU3LDU4LDU5LDYwLDYxLDYzLDY0LDY1LDY2LDY3LDY4LDY5LDcwLDcxLDcyLDczLDc0LDc1LDc2LDc3LDgyLDgzLDg2LDg3LDg4LDg5LDkxLDkyLDkzLDk0LDk1LDk2LDEwMCwxMDEsMTAyLDEwMywxMDQsMTA1LDEwNiwxMDcsMTA4LDEwOSwxMTAsMTExLDExMiwxMTMsMTE0LDExNSwxMTYsMTE3LDEyNCwxMjUsMTI2LDEyNywxMjgsMTI5LDEzMCwxMzEsMTMyLDEzMywxMzQsMTM1LDEzNiwxMzcsMTM4LDEzOSwxNDAsMTQxLDE0MiwxNDMsMTQ0LDE0NSwxNDYsMTQ3LDE0OCwxNDksMTUwLDE1MSwxNTIsMTUzLDE1NCwxNTUsMTU2LDE2MiwxNjUsMTcxLDE4NCwxODcsMTkyLDE5OSwxNzMsMTk4LDE2MCwxNjEsMTY5LDE4MywxODgsODQsOTcsOTgsOTksMTY3LDE3MiwxODAsMTg1LDE5MCwxOTMsMTc0LDE2NCwyMDQsMjE1XSwicGFzc3dvcmRVcGRhdGVkQXQiOiIiLCJ0ZW5hbnQiOnsiaWQiOjIsIm5hbWUiOiJ0ZWNUcmFuc2l0Iiwic2l0ZUlkIjoiOTQiLCJ0aW1lem9uZSI6IkFtZXJpY2EvTG9zX0FuZ2VsZXMiLCJ0eXBlIjoiUmFhUyIsInNlc1VybCI6Imh0dHA6Ly9zdHJhdGVneS1lbmdpbmUtbXVsdGktdGVuYW50LTM6MTYwMDAiLCJkaXNwbGF5TmFtZSI6IlRlYyBUcmFuc2l0In0sInJvbGVzIjpbMjBdLCJpYXQiOjE3NDE5MDU2ODIsImV4cCI6MTc0NDQ5NzY4MiwiaXNzIjoiaXEuc2NoZWR1bGVkcm91dGVzLmRkc3dpcmVsZXNzLm5ldCJ9.fmdXyIylp604DCewvtuKCqLGhh-GFPfJNC9p2v4D-kHxhN2ZmRkHfknpTjiWZOZnB7AnWTUAh6BfZztNR_KLpQDPXcEpNL01lrw7ypIuwIf6CwA3Kwh916mNX-kgvPsyRQvAnvkyd-YO8M6zd_lsVD8oRnb-g07Vta3s3U-Y5uyWnQzv9PEeRf2IizflzlMkM7f1q472_3FQAEmomqMrSreK-YwUP9YxzD-QOW4GaaIUK5pgnzFYgEH2DFNU8KtDPeRdEk1cXL8aACFeawZnYzndvNcuv5fxd-9r-Y4-Tr8NiUwerdhRX3CuD5L5E6JVQdYOUJMFtSVpCbV7smaOJs"
N'oubliez pas non plus d'utiliser votre propre jeton d'accès à l'API.
Schéma de réponse pour la méthode GET :
{
status: "string",
message: "string",
error: "string",
"solution": {
"statistics": {},
"routes": []
"unassigned": [],
}
}
Si la solution est prête, statistics, routes, et unassignedsera renseigné en fonction de la solution obtenue. Sinon, comme pour la méthode POST, status, message, et erroraffichera le statut ou l'erreur. Le schéma de la solution de sortie est défini dans la section « Solution ».
Exemple GET (Windows PowerShell) :
Le script ci-dessous montre comment effectuer une requête GET à l'aide d'un identifiant généré par la méthode POST dans Windows PowerShell. Il part du principe que cet identifiant est stocké dans un fichier nommé id.txt, et le jeton d'accès à l'API est enregistré dans token.txt. Une fois l'exécution terminée, la réponse générée est enregistrée dans response.txt. Pour lancer PowerShell, il suffit de taper « PowerShell » dans le menu Démarrer ou dans la ligne de commande.
$token = Get-Content token.txt -Raw
$id = Get-Content id.txt -Raw
$headers = @{
Authorization = "Bearer $token"
"Content-Type" = "application/json"
}
$url = "https://iq.scheduledroutes.ddswireless.net/raas/optimization/$id"
$response = Invoke-RestMethod -Uri $url -Method Get -Headers $headers
$response | ConvertTo-Json -Depth 10 | Out-File -Encoding utf8 response.txt
Codes d'état GET #
| Code de réponse | Description | Remarques supplémentaires |
|---|---|---|
| 200 | La requête a abouti. | La solution est renvoyée via statistics, routes, et unassigned. |
| 202 | La demande a été acceptée, mais n'a pas encore été traitée. | Le statut est « en attente ». Veuillez revenir plus tard pour vérifier si une solution est disponible. |
| 400 | Impossible de traiter la requête (erreur de requête). | Aucune solution viable n'a pu être générée en raison d'une entrée ou de paramètres non valides. |
| 401 | Demande non autorisée. | Une authentification de l'utilisateur est requise. Aucune information d'identification valide n'a été reçue. |
| 500 | Erreur interne du service. | Une erreur s'est produite de notre côté. Contactez-nous support@ddswireless.com. Des champs tels que statistics, routes, et unassigned sera vide. |
Concepts #
Pour résoudre un problème d'optimisation des itinéraires et des horaires pour une flotte de véhicules, procédez comme suit :
-
Définissez le problème : commencez par décrire votre problème en suivant le format indiqué dans la section « Problème ».
-
Envoyer le problème : utilisez la méthode POST, comme décrit dans la section « Pour commencer », pour envoyer votre problème à l'API.
-
Récupérer la solution : accédez à la solution de votre problème d'optimisation en utilisant la méthode GET décrite dans la section « Pour commencer ». Le format de la solution est présenté dans la section « Solution ».
Pour en savoir plus sur les différents termes utilisés dans l'API, consultez la section « Glossaire ». Pour consulter la liste des questions fréquemment posées, consultez la section « FAQ ».
Problème n°
Le Problème Cette entité correspond à un problème de routage et d'ordonnancement. Comme le montre la figure suivante, elle se compose de quatre éléments principaux : fleet, jobs, objective, et configuration. Parmi ces quatre éléments, fleet et jobs, sont obligatoires alors que objective et configuration sont facultatifs.

Pour indiquer un lieu ou une adresse dans l'API, utilisez les coordonnées géographiques WGS84 avec au moins 5 décimales pour garantir la précision.
Par exemple, si vous avez une adresse telle que « 1600 Amphitheatre Parkway, Mountain View, Californie », ses coordonnées géographiques correspondantes seraient la latitude
37.423021 et la longitude -122.083739. Par conséquent, vous devez le spécifier sous l'une des formes suivantes :
"location": {"lat": 37.423021, "lng": -122.083739} ou [37.423021, -122.083739].
Remarque :
L'API utilise le format ISO 8601 pour les horodatages, y compris les informations de fuseau horaire, afin de définir l'heure locale de la zone pour laquelle vous avez besoin d'un calcul d'itinéraire et d'une planification optimisés.
Exemple :
2024-07-31T14:45:30-08:00 correspond au 31 juillet 2024, à 14 h 45 min 30 s PST, soit 8 heures de retard par rapport au temps universel coordonné (UTC).
De plus, dans la charge utile de l'API d'entrée, vous devez utiliser systématiquement le même fuseau horaire local. Si plusieurs fuseaux horaires sont détectés, l'API renverra une erreur. Les heures des arrêts programmés dans la réponse de sortie seront fournies dans le même format que celui spécifié dans la charge utile de l'API d'entrée.
Exemple :
Si vous indiquez 2024-07-31T14:45:30-08:00 dans votre charge utile d'entrée, les temps de trajet optimisés dans la sortie seront également exprimés en 2024-07-31T14:45:30-08:00 format.
Si vous utilisez 2024-07-31T14:45:30+05:30 si l'entrée est en 2024-07-31T14:45:30+05:30.
Remarque :
Tous les attributs facultatifs peuvent être omis dans le corps du message. Les tableaux vides (par exemple []) peut également être utilisé pour les attributs facultatifs qui acceptent un tableau.
Remarque :
Veillez à ce qu'aucune information confidentielle ou personnelle ne figure dans les données envoyées à l'API. Évitez par exemple d'utiliser des identifiants réels, tels que des numéros d'immatriculation, comme identifiant de véhicule ou comme identifiant de mission/tâche.
Nous allons maintenant vous présenter une description détaillée de chacun de ces éléments :
fleet: [obligatoire] il s'agit d'une liste de véhicules accompagnée des informations correspondantes, telles que les horaires de travail, les lieux de départ et d'arrivée, les pauses, les capacités et les compétences.
Pour chaque véhicule, vous pouvez définir un ou plusieurs horaires de travail en précisant les heures de début et de fin, ainsi que les lieux correspondants. Pour identifier ces lieux, vous devrez fournir leurs coordonnées géographiques, qui comprennent la latitude et la longitude.
Chaque véhicule peut avoir une ou plusieurs pauses. Pour chaque pause, vous pouvez définir une plage horaire pendant laquelle elle peut être prise, ainsi que le lieu et la durée de la pause.
Pour chaque véhicule, vous pouvez définir un ou plusieurs types de capacité ainsi que les unités disponibles pour chaque type. La capacité d'un véhicule peut être représentée à l'aide d'unités de mesure multidimensionnelles, telles que le volume, la masse ou la taille.
Pour chaque véhicule, vous pouvez spécifier une ou plusieurs compétences qui lui permettent d'effectuer certaines tâches. Par exemple, vous pouvez attribuer « machine à souder » et « bouteille d’oxygène » comme compétences à un véhicule, et « élévateur » comme compétence à un autre véhicule. Si une tâche nécessite un élévateur, seul le véhicule doté de cette compétence pourra l’effectuer. Vous pouvez également définir des limites pour chaque véhicule, telles que le nombre maximal d’arrêts et la distance maximale parcourue (en kilomètres).
jobs: [obligatoire] il s'agit d'une liste des missions que doivent effectuer les véhicules mentionnés dans le fleet objet. Chaque mission peut comprendre une série de tâches, qui peuvent concerner uniquement des enlèvements, uniquement des livraisons, ou à la fois des enlèvements et des livraisons. Pour les missions de « visite » où nous devons nous rendre sur place pour effectuer une intervention (par exemple, des réparations, l'installation d'un modem, etc.), vous pouvez les considérer comme une tâche de livraison avec ou sans exigence de capacité. Pour chaque tâche, vous pouvez définir divers attributs tels que son emplacement, ses créneaux horaires, sa durée, ses exigences en matière de capacité et les compétences requises.
Pour préciser l'emplacement d'une tâche, vous devez fournir ses coordonnées géographiques, qui comprennent la latitude et la longitude.
Si vous définissez une plage horaire de service pour une tâche, l'optimiseur planifiera la tâche de manière à ce qu'elle s'exécute au cours de cette période. En d'autres termes, l'heure d'arrivée estimée (ETA) de la tâche indiquée dans la réponse de l'API se situera dans la plage horaire spécifiée. Si l'optimiseur ne parvient pas à trouver une ETA appropriée pour une tâche dans la plage horaire spécifiée, la tâche restera non attribuée. Pour les tâches flexibles ou non urgentes, vous pouvez spécifier une plage horaire plus large, d'une durée maximale de 24 heures. L'API utilise les horodatages ISO comme décrit précédemment.
Vous pouvez spécifier une durée (en secondes) pour chaque tâche. Il s'agit du temps passé à un emplacement donné pour charger ou décharger un article ou pour effectuer la tâche.
Vous pouvez spécifier les exigences de capacité pour chaque tâche à l'aide d'unités de mesure multidimensionnelles, telles que le volume, la masse ou la taille. De plus, vous pouvez créer des noms personnalisés pour vos types de capacité, tels que « siège », « conteneur », « palette » ou « bac ». Pour chaque type de capacité, vous pouvez également définir la quantité exacte nécessaire pour effectuer la tâche.
Vous pouvez également définir une liste de compétences requises pour chaque tâche. Seuls les véhicules disposant d’un ensemble de compétences correspondant seront éligibles pour effectuer cette tâche. Par exemple, si vous spécifiez « poste à souder » et « bouteille d’oxygène » comme compétences requises pour une tâche, seuls les véhicules équipés de ces compétences seront sélectionnés pour effectuer la tâche.
objective: [facultatif] il définit l'objectif ou la stratégie d'optimisation. Actuellement, l'API prend en charge les trois objectifs suivants :
Réduire au minimum le temps de trajet total : il s'agit de la stratégie d'optimisation par défaut, qui vise à réduire au minimum le temps de trajet total de la flotte tout en effectuant les missions spécifiées.
Minimiser le nombre d'itinéraires : cette stratégie d'optimisation vise à réduire le nombre de véhicules nécessaires pour effectuer les tâches spécifiées. Cependant, cela peut entraîner une augmentation de la durée totale de trajet de la flotte ou une charge de travail plus importante pour chaque véhicule.
Répartir la charge de travail entre les itinéraires : cette stratégie d'optimisation vise à répartir équitablement la charge de travail entre tous les véhicules de la flotte. Cependant, cet équilibre peut entraîner une augmentation de la durée totale de trajet de la flotte.
configuration: [facultatif] via la configuration, vous pouvez ajuster les paramètres de l'API ou modifier les options par défaut. Par exemple, vous pouvez choisir d'inclure ou non dans la réponse de l'API un résumé des statistiques d'optimisation (telles que la durée totale du trajet et la distance) ou une liste des tâches non attribuées.
Schéma de la requête d'entrée : #
Le schéma de la requête d'entrée permettant de résoudre un problème d'optimisation d'itinéraire est le suivant :
"problem": {
"fleet": required
[
"shifts": [optional]
"capacities": [required]
"limits": {optional}
"skills" : [optional]
"id": required
"routeTemplateId" : optional
"maxInstances": optional
],
"jobs": required
[
"pickups": [...]
"deliveries": [...]
"id" : required
]
"objective": optional
"configuration": {optional}
"version": optional
}
Pour envoyer une requête via l'API, celle-ci doit être intégrée à la méthode POST, comme indiqué dans la section « Pour commencer ».
Dans un problème d'optimisation d'itinéraires, une flotte de véhicules cherche à effectuer efficacement un ensemble de missions. Le schéma ci-dessus permet aux utilisateurs de définir leur flotte et leurs missions. Dans la version actuelle de l'API, chaque mission peut être :
-
Tâches de collecte uniquement: ces tâches consistent à récupérer des articles le long du parcours et à les livrer au point d'arrivée de celui-ci.
-
Tâches de livraison uniquement: ces tâches consistent à livrer des articles chargés dans le véhicule au début du parcours.
-
Tâches combinées d'enlèvement et de livraison (P/D): ces tâches associent à la fois l'enlèvement et la livraison. Elles consistent à aller chercher un article à un endroit donné pour l'apporter à un autre endroit.
Au moins une mission et un véhicule doivent être fournis pour le problème.
Pour les missions de « déplacement » qui nécessitent de se rendre sur place (par exemple, réparations, installations de modems, etc.), considérez-les comme des missions de livraison — avec ou sans exigence de capacité.
De plus :
-
Si seul l'objet « enlèvements » est fourni pour une commande, celle-ci est considérée comme une commande avec enlèvement uniquement.
-
Si seul l'objet « livraisons » est fourni pour une tâche, celle-ci est considérée comme une tâche de livraison uniquement.
-
Lorsqu'une mission comprend à la fois un « enlèvement » et une « livraison », elle est classée dans la catégorie des missions d'enlèvement et de livraison.
L'API permet pas prendre en charge les tâches comportant plusieurs enlèvements et plusieurs livraisons.
En d'autres termes, si vous souhaitez définir une mission de « collecte et livraison »:
- Le
"pickups"Le tableau ne doit contenir que un tâche de ramassage. - Le
"deliveries"Le tableau ne doit contenir que un tâche de livraison.
L'API ne prend pas non plus en charge les missions sans enlèvement ni livraison.
Règles de classification :
- Si seulement
"pickups"une fois défini, le poste est classé comme un fixé au pick-up emploi. - Si seulement
"deliveries"une fois défini, le poste est classé comme un basé sur la livraison emploi. - Si l'enlèvement et la livraison sont tous deux définis, le point d'ancrage est celui qui comprend une plage horaire de service.
- Si tant l'enlèvement que la livraison ont des plages horaires, la mission est considérée comme étant centrée sur l'enlèvement.
Pour chaque mission, divers attributs et contraintes peuvent être définis, tels que les exigences en matière de capacité, les créneaux horaires de service et les compétences requises. Les tâches de visite, pour lesquelles il faut se rendre à des endroits précis afin d’effectuer des tâches (par exemple, des réparations), peuvent en effet être considérées comme une forme spécialisée de tâches de livraison (avec ou sans exigences de capacité). Les tâches sont attribuées à des véhicules dont les capacités ou les compétences correspondent aux exigences de la tâche. Par exemple, si une tâche nécessite une nacelle ou une échelle, seuls les véhicules équipés d’une nacelle ou d’une échelle seront utilisés pour effectuer cette tâche.
Voyons maintenant en détail chaque élément de la charge utile de l'API d'entrée.
problème [obligatoire] : il spécifie le problème d'optimisation de routage et d'ordonnancement que vous souhaitez résoudre. Il comprend les attributs suivants :
flotte [obligatoire] : définit les informations relatives à la flotte. Il s'agit d'un tableau d'objets de flotte. Chaque objet de flotte comprend les attributs suivants :
id: [obligatoire] identifiant unique (entier) du véhicule.
shifts: [facultatif] tableau d'objets « shift » ; chaque objet « shift » contient les données relatives aux lieux et heures de début et de fin du service, ainsi qu'un tableau d'objets « breaks » contenant chacun les lieux et heures de début et de fin des pauses. Il est possible de définir plusieurs objets « shift », mais ceux-ci doivent être disjoints. Éléments de chaque objet « shift » :
start: l'heure et le lieu de prise de service
time: [facultatif]. Il permet de définir l'heure de début du service. Si ce paramètre n'est pas spécifié, la valeur par défaut est 00:00:00 (minuit) de la date du jour.
location: [facultatif]. Il indique les coordonnées géographiques (latitude et longitude) du point de départ. Vous pouvez les indiquer sous forme de tableau, par exemple [A,B] dans lequel A correspond à la latitude et B correspond à la longitude. Vous pouvez également la spécifier sous la forme {"lat": A,"lng": B}.
end: l'heure de fin du service et le lieu de fin
time: [facultatif]. Il indique l'heure de fin du service. Si ce paramètre n'est pas spécifié, la valeur par défaut est 23 h 59 min 00 s de la date du jour.
location: [facultatif]. Il permet de définir les coordonnées géographiques (latitude et longitude) du point d'arrivée. Vous pouvez les indiquer sous forme de tableau, par exemple [A,B] dans lequel A correspond à la latitude et B correspond à la longitude. Vous pouvez également la spécifier sous la forme {"lat": A,"lng": B}.
breaks: [facultatif] un tableau d'objets « break »
serviceWindow: [obligatoire si l'option « breaks » est utilisée] : la période pendant laquelle la pause peut avoir lieu
duration: [obligatoire si l'on utilise « breaks »] : un nombre entier définissant la durée de la pause en secondes
location: [facultatif] : l'emplacement de la coupure. Vous pouvez le spécifier sous forme de tableau, par exemple [A,B] dans lequel A correspond à la latitude et B correspond à la longitude. Vous pouvez également la spécifier sous la forme {"lat": A,"lng": B}.L'emplacement est facultatif. Si l'emplacement n'est pas indiqué, la pause est « flexible », ce qui signifie qu'elle peut être prise n'importe où, selon la convenance du conducteur.
Exemple :
"shifts": [{
"start": {
"time": "2020-07-04T09:00:00-08:00",
"location": {"lat": 52.46642, "lng": 13.28124}
},
"end": {
"time": "2020-07-04T18:00:00-08:00",
"location": [54.21981, 14.01237]
},
"breaks": [
{
"serviceWindow": ["2020-07-04T12:00:05-08:00","2020-07-04T14:05:05-08:00"],
"duration": 1200,
"location": {"lat": 53.70645, "lng": 12.34156}
},
{
"serviceWindow": ["2020-07-04T16:00:00-08:00","2020-07-04T16:45:00-08:00"],
"duration": 600,
"location": {"lat": 51.46642, "lng": 12.28124}
}
]
}]
capacités: [obligatoire] un tableau d'objets de capacité. Chaque objet de capacité est un objet clé-valeur défini avec les clés suivantes :
name: [obligatoire] une chaîne de caractères indiquant le nom du type de capacité (par exemple « fauteuil roulant », « coffre », « siège », « bac »)
units: [obligatoire] un nombre entier indiquant le nombre d'unités disponibles pour ce type de capacité
Par exemple, si un véhicule peut transporter 2 passagers et 20 colis, vous pouvez définir sa capacité comme suit :
"capacities": [
{
"name": "seat",
"units": 2,
},
{
"name": "package",
"units": 20,
}
]
compétences: [facultatif] une liste des compétences ou de l'équipement des véhicules, chacun étant représenté par une chaîne de caractères arbitraire propre à votre application. Cela vous permet de personnaliser les capacités de vos véhicules afin qu'elles correspondent aux exigences des missions qu'ils doivent accomplir. Exemple :
"skills": ["lift","fridge","oxygen tank"]
limites: [facultatif] précise les contraintes appliquées au véhicule
maxDistance: [facultatif] un nombre entier indiquant la distance maximale autorisée pour le véhicule, en miles
maxStops: [facultatif] un nombre entier indiquant le nombre maximal d'arrêts (missions de collecte ou de livraison) que le véhicule peut effectuer au cours d'une même journée de travail
lifoDepth: [facultatif] un nombre entier définissant la profondeur LIFO (dernier entré, premier sorti) du véhicule
"limits": {
"lifoDepth" : 1,
"maxDistance": 3000,
"maxStops" : 20,
}
lastKnownLocation : [facultatif, utilisé uniquement pour la réoptimisation] Indique la dernière position connue du véhicule à l'heure spécifiée. Cette information est essentielle pour réoptimiser un itinéraire en cours afin de tenir compte des nouveaux changements, tels que les pannes de véhicules, les missions en retard, les nouvelles missions ou les missions annulées. L'API utilise ces données pour réoptimiser efficacement le plan. Par conséquent, lors de la réoptimisation d'un planning existant, vous devez fournir la position de tous les véhicules concernés.
Exemple :
"lastKnownLocation": {
"location": {"lat":53.45612, "lng":12.65421},
"time" : "2020-07-04T12:00:05-08:00"
}
routeTemplateId : [facultatif] Il s'agit d'un identifiant unique utilisé pour définir un modèle d'itinéraire. L'API prend en charge le concept de « modèles d'itinéraire », qui vous permet de définir les spécifications d'un type de véhicule particulier et de demander à l'API de générer un nombre spécifique de ces véhicules à des fins d'optimisation des itinéraires et de la planification. Un modèle d'itinéraire contient les mêmes informations qu'un itinéraire ou un véhicule, mais vous pouvez lui attribuer un paramètre de « taille » appelé maxInstances. Par exemple, supposons que vous disposiez de 100 véhicules. Vous pourriez définir 2 ou 3 modèles d'itinéraire :
- Quart de travail de 6 h à 18 h, capacité : 4, taille = 60
- Service de 13 h à 1 h, capacité : 4, taille = 50
- Quart de travail de 6 h à 20 h, capacité : 10 personnes, taille = 35
Cela signifie que l'API peut créer automatiquement jusqu'à 60 véhicules à l'aide du modèle 1 selon les besoins, 5 à l'aide du modèle 2 et 35 à l'aide du modèle 3.
maxInstances : [facultatif] Si routeTemplateId est fourni, maxInstances indique le nombre de modèles de route à générer à partir du modèle de route spécifié.
Les règles suivantes s'appliquent lors de la configuration des routes à l'aide de
id, routeTemplateId, et maxInstances:
Exactement un de id ou routeTemplateId Il faut choisir l'un ou l'autre, mais jamais les deux.
id et maxInstances ne peut pas être utilisés ensemble.
Si les deux routeTemplateId et maxInstances sont fournis, l'API utilise le modèle de route pour générer des itinéraires.
jobs: un tableau d'objets de tâche [au moins une tâche est requise] :
id : [obligatoire] identifiant unique (entier) de la mission
pickups: [ facultatif] tableau d'objets Task, chacun définissant une tâche d'enlèvement
deliveries: [facultatif] tableau d'objets Task, chacun définissant une tâche de livraison (ou de dépôt)
L'API impose des règles strictes concernant la configuration de la collecte et de la livraison des tâches :
- L'API ne prend pas en charge les commandes comportant plusieurs points d'enlèvement et plusieurs livraisons.
- L'API ne prend pas en charge les missions sans enlèvement ni livraison.
- Si seulement
"pickups"si ce paramètre est spécifié, la tâche est classée comme emploi lié à la collecte. - Si seulement
"deliveries"si ce paramètre est spécifié, la tâche est classée comme poste axé sur la prestation. - Si une mission comprend à la fois un enlèvement et une livraison, le point de référence est déterminé par la tâche qui définit une plage horaire.
- Si les deux tâches ont des plages horaires, le travail est considéré comme un travail ancré sur un ramassage.
Chaque objet « Tâche » comprend les attributs suivants :
id: [obligatoire] un identifiant unique (entier) pour la tâche
lieu: [obligatoire] Il s'agit d'un objet clé-valeur qui spécifie les coordonnées géographiques (latitude et longitude) du lieu où la tâche doit être effectuée. Vous pouvez le spécifier sous la forme d'un tableau, par exemple [A,B] dans lequel A correspond à la latitude et B correspond à la longitude. Vous pouvez également la spécifier sous la forme {"lat": A,"lng": B}.
Exemple :
"location": {"lat": 52.46642, "lng": 13.28124}
"location": [52.46642, 13.28124]
serviceWindows: [facultatif ou obligatoire selon le cas d'utilisation ; voir la définition des enlèvements et des livraisons ci-dessus] Il définit la plage horaire de service pour l'exécution de la tâche. La plage horaire de service est un tableau au format suivant : [A, B] où A et B correspondent respectivement à l'heure de début et à l'heure de fin de la plage horaire de service. L'API tentera de calculer une heure d'arrivée prévue (ETA) dans la plage horaire de service spécifiée pour cette tâche. Si cela s'avère impossible, la tâche sera répertoriée comme non attribuée. En d'autres termes, les heures « A » et « B » définissent les heures la plus tôt et la plus tard auxquelles une tâche doit être effectuée par un véhicule. Pour les tâches flexibles ou non urgentes, utilisez une fenêtre de service aussi large que possible (24 heures maximum) afin de donner à l'API plus de flexibilité dans la planification des autres tâches. La version actuelle de l'API ne prend en charge qu'une seule fenêtre de service par tâche.
Pour les tâches concernant uniquement les enlèvements ou uniquement les livraisons, il est nécessaire de préciser la plage horaire. Exemple :
"serviceWindows": ["2024-08-30T09:00:00-08:00",
"2024-08-30T21:00:00-08:00"]
durée: [obligatoire] Indique la durée de la tâche en secondes. Il peut s'agir soit d'un nombre entier, soit d'un objet clé-valeur comportant les clés suivantes :
"fixed": la durée fixe (en secondes) de la tâche (par exemple, pour trouver une place de stationnement, faire descendre l'ascenseur, etc.)
"service": la durée (en secondes) nécessaire à l'exécution de la tâche.
Exemples :
"duration": 1950
OR
"duration": {"fixed":150, "service": 1800}
demande: [ facultatif] un tableau contenant les demandes de capacité pour la tâche. La structure de chaque objet « demande » est identique à celle de l'objet « capacité » de l'entité « flotte » définie ci-dessus. Chaque élément de capacité se compose d'un nom (chaîne de caractères) et du nombre d'unités disponibles (entier). Les noms indiqués doivent correspondre à ceux définis dans l'objet « capacité » de l'entité « flotte ». Par exemple, si une tâche nécessite une capacité de deux places et 20 colis, vous définirez la demande comme suit :
"demand": [
{
"name": "seat",
"units": 2,
},
{
"name": "package",
"units": 20,
}
]
compétences: [facultatif] un tableau de compétences ou d'équipements requis pour accomplir la tâche, chacun étant représenté par une chaîne de caractères arbitraire spécifique à votre application. Seuls les véhicules dont l'ensemble de compétences correspond à celui de la tâche seront pris en compte pour l'exécution de celle-ci. Ces compétences sont mises en correspondance avec celles définies dans l'entité « flotte » décrite ci-dessus. Exemple :
"skills": ["lift", "ladder", "welding machine"]
statut: [facultatif, utilisé uniquement pour la réoptimisation] Il s'agit d'une chaîne de caractères qui spécifie l'état de la tâche ; elle peut prendre l'une des valeurs suivantes : "pending", "in_progress", "performed". Ces informations sont essentielles pour réoptimiser un itinéraire en cours afin de tenir compte des nouveaux changements, tels que les véhicules en panne, les missions en retard, les nouvelles missions ou les missions annulées. L'API utilise ces données pour réoptimiser efficacement le plan. Par conséquent, lors de la réoptimisation d'un planning existant, vous devez spécifier la valeur de cet attribut. Pour les nouvelles tâches ou celles qui n'ont pas encore été exécutées, définissez-le sur "pending". Si la tâche a déjà été effectuée, définissez-la sur "performed". Si le véhicule est déjà arrivé sur le lieu d'intervention et que la tâche est en cours, réglez-le sur "in_progress". La valeur par défaut est "pending".
Exemple : "status": "pending"
vehicleId: [facultatif, utilisé uniquement pour la réoptimisation], il spécifie l'identifiant du véhicule (entier) attribué aux tâches déjà planifiées. Cette information est essentielle pour réoptimiser un itinéraire en cours afin de tenir compte des nouveaux changements, tels que les pannes de véhicules, les retards, les nouvelles missions ou les missions annulées. L'API utilise ces données pour réoptimiser efficacement le plan. Par conséquent, lors de la réoptimisation d'un planning existant, vous devez spécifier la valeur de cet attribut. La valeur par défaut est zéro. Pour les nouvelles tâches, définissez-la sur zéro. Pour les tâches existantes déjà attribuées à un véhicule, définissez cet attribut sur l'ID du véhicule attribué.
Exemple : "vehicleId": 12
eta: [facultatif, utilisé uniquement pour la réoptimisation], il indique l'heure d'arrivée estimée (ETA) actuelle pour les missions déjà planifiées. Cette information est essentielle pour réoptimiser un itinéraire en cours afin de tenir compte des nouveaux changements, tels que les véhicules en panne, les missions en retard, les nouvelles missions ou les missions annulées. L'API utilise ces données pour réoptimiser efficacement le plan. Par conséquent, lors de la réoptimisation d'un planning existant, vous devez spécifier la valeur de cet attribut. La valeur par défaut est 0. Pour les tâches nouvelles ou déjà effectuées, définissez-la sur 0, mais pour les tâches en attente existantes, définissez-la sur l'ETA existante.
Exemple : "eta": "2021-07-04T12:13:00-08:00"
objectif: [ facultatif] un entier indiquant l'objectif d'optimisation (stratégie) : (valeur par défaut = 1)
1: Réduire au minimum la durée totale du trajet [par défaut]
2: Réduire au minimum le nombre d'itinéraires
3: Répartir la charge de travail entre les itinéraires
Exemple : "objective": 1
configuration : [ facultatif] permet de définir certains paramètres ou configurations supplémentaires :
type de polyligne : [facultatif] Il permet de spécifier le type de polyligne de sortie pouvant être renvoyé pour chaque itinéraire planifié. Il s'agit d'une chaîne de caractères correspondant à l'une des options suivantes : "none", "plain", "encoded". Si "none"est sélectionné, aucune polyligne ne sera incluse dans la réponse de l'API. Si "plain" est spécifié, une liste ordonnée des intersections que nous devons emprunter entre chaque paire d'arrêts consécutifs sera renvoyée sous forme de polyligne. Si "encoded" est utilisée, la polyligne est compressée au format chaîne de caractères que les utilisateurs peuvent fournir à des API de navigation tierces, telles que Google Maps, afin d'obtenir des instructions étape par étape. La valeur par défaut est "none".
unassignedTasks : [facultatif] il s'agit d'un indicateur qui détermine si les tâches non attribuées doivent être incluses dans la réponse ou non. La valeur par défaut est False. Si, pour une raison quelconque, l'API ne parvient pas à attribuer une tâche à un itinéraire, elle l'indiquera comme non attribuée.
statistiques : [ facultatif] indicateur permettant de déterminer si les statistiques d'optimisation doivent être incluses dans la solution finale. La valeur par défaut est True.
unités : [facultatif] il permet de définir les unités utilisées pour les statistiques de sortie ainsi que celles des limites de la flotte. Il peut s'agir soit de "metric" ou "imperial". La valeur par défaut est "metric".
maxRideTable : [facultatif] Il définit la durée maximale de trajet pour toutes les missions. Elle est définie par un tableau statique dont chaque ligne est un tableau contenant trois valeurs temporelles (en minutes) : [A, B, C]. Cela signifie que si la durée directe du trajet pour une mission se situe entre A et B, la durée maximale de trajet est égale à « rideTime+C ». Voici, par exemple, un tableau simple comportant deux lignes : "maxRideTable":[[0, 10, 30], [11, 20, 40]]. La valeur par défaut est [[0, 300, 720]]. Les chevauchements et les lacunes ne sont pas autorisés dans ce tableau. De plus, la granularité est exprimée en minutes.
Capacités des véhicules : [facultatif] Les définitions de capacité des véhicules peuvent être nommées puis utilisées dans la section « Flotte ». Cela s'avère particulièrement utile pour les définitions complexes, lorsqu'un véhicule peut présenter de nombreuses configurations. Par exemple, si un véhicule peut accueillir soit (10 passagers « valides » et 0 passagers « en fauteuil roulant ») SOIT (8 passagers « valides » et 1 passager « en fauteuil roulant »), vous pourriez définir "vehicleCapacities":{"flexBus": [[{"name": "ambulatory", "units": 10}], [{"name": "ambulatory", "units": 8},{"name":"wheelchair", "units": 1}]]}. Ensuite, dans les propriétés de la flotte, vous pouvez utiliser fleet[<index>].capacities: "flexBus" pour chaque flexBus de la flotte. Les capacités nominales des véhicules peuvent également être enregistrées dans votre profil client personnel, où elles deviennent disponibles sans que vous ayez à les redéfinir dans la section de configuration. Si une capacité nominale de véhicule figure à la fois dans votre profil personnel et dans la charge utile, c'est la définition de la charge utile qui prévaut.
freezeWindowLength : [facultatif] Durée de la fenêtre de gel en minutes. Une fenêtre de gel est un concept qui s'applique uniquement à l'optimisation le jour même et qui est utile lors de la réoptimisation d'un problème. Par exemple, si vous avez déjà optimisé un problème mais que vous souhaitez apporter des modifications en cours de journée, vous pouvez renvoyer le problème (avec un task.status approprié pour refléter ce qui a déjà été fait) et définir une fenêtre de gel de 60 minutes. Cela indiquera à l'optimiseur que la période s'étendant sur 60 minutes à partir de « maintenant » est hors limites. Aucune tâche ne peut être ajoutée/supprimée d'un itinéraire quelconque pendant la fenêtre de gel.
Capacités soumises à la méthode LIFO : [facultatif] Un tableau de types de capacité soumis à la contrainte LIFO (dernier entré, premier sorti). Exemple : "lifoConstrainedCapacities": ['wheelchair', 'scooter']
Exemple :
"configuration":
{
"polylineType": "plain",
"unassignedTasks": False,
"statistics": True,
}
version: [ facultatif] : indique la version de l'API. La valeur par défaut est 1.0.
Pour voir divers exemples d'un
Problem et découvrez comment utiliser l'API dans différents cas d'utilisation (par exemple, la réoptimisation), voir Tutoriels.Remarque :
1. Identifiants uniques
-
- Toutes les tâches doivent avoir un identifiant unique.
- Toutes les tâches doivent avoir un identifiant unique.
- Tous les véhicules doivent être dotés d'un identifiant unique.
- Un travail peut partager son identifiant avec une tâche ou un véhicule — cela est autorisé.
2. Contraintes de temps
Chaque problème peut comporter plusieurs éléments liés au temps, tels que les plages horaires des interventions et les rotations des véhicules.
L'API détermine la durée minimale parmi toutes les valeurs. Par exemple, si la durée minimale est :
2024-09-18T04:32:00-08:00La valeur maximale est calculée comme suit :
- Déterminer l'heure de minuit du jour où le minimum est atteint.
- Ajouter 33 heures à cette date et heure.
Dans cet exemple, la durée maximale autorisée est donc :
2024-09-19T09:00:00-08:00Si, à un moment quelconque, la durée d'un problème (par exemple, un changement de véhicule ou une fenêtre de tâche) dépasse cette limite, l'API renverra un 400 erreur.
Solution n°
Comme expliqué dans la section « Pour commencer », une fois que vous avez soumis un problème via la méthode POST, vous recevez un identifiant de référence unique. Vous pouvez utiliser cet identifiant de référence avec la méthode GET pour récupérer le statut du problème soumis. Si la solution d'optimisation est prête, vous pouvez y accéder dans le "solution" entité de la réponse reçue. Comme le montre la figure suivante, le "solution" Cette entité se compose de trois parties principales :
"statistics": il comprend diverses statistiques (indicateurs) qui offrent une vue d'ensemble de la solution dans son intégralité, tous itinéraires confondus, vous permettant ainsi d'évaluer son efficacité. Ces indicateurs comprennent, par exemple, la distance totale parcourue pour tous les itinéraires optimisés. En analysant ces statistiques, vous pouvez mesurer la qualité et l'efficacité de la solution obtenue. Ces informations permettent de mieux comprendre les performances et l'impact du processus d'optimisation.
"routes": il contient les itinéraires optimisés, ainsi que leurs arrêts et leur heure d'arrivée estimée (ETA). Il peut également inclure le tracé de chaque itinéraire.
"unassigned": elle contient la liste des tâches non attribuées. Si l'API ne parvient pas à attribuer une tâche à un itinéraire au cours du processus d'optimisation, celle-ci sera répertoriée comme non attribuée. De plus, elle peut indiquer les raisons pour lesquelles chaque tâche reste non attribuée, fournissant ainsi des informations sur les contraintes ou les problèmes potentiels qui ont empêché leur attribution.

Schéma de la solution de sortie : #
Le modèle de la solution du problème d'optimisation fourni dans la réponse de sortie de l'API se présente comme suit :
"solution": {
"statistics": {},
"routes": []
"unassigned": [],
}
Le "solution" Cette entité représente la solution du problème d'optimisation d'itinéraire et comprend les attributs suivants :
statistiques: il contient les statistiques de l'ensemble de la solution et comprend les propriétés suivantes :
«distance» :
« totalDistance » : la distance totale parcourue par l'ensemble de la flotte. Cette mesure comprend la distance entre le point de départ et le point d'arrivée de chaque véhicule.
«revenueDistance» : la distance totale parcourue par l'ensemble de la flotte générant des revenus. Cette mesure inclut la distance entre le premier arrêt et le dernier arrêt pour chaque véhicule. Elle n'inclut pas la distance entre le point de départ du véhicule et le premier arrêt, ni la distance entre le dernier arrêt et le point d'arrivée du véhicule.
«véhicules» :
«utilisés» : nombre de véhicules utilisés dans le cadre de la solution pour effectuer les travaux/tâches programmés.
«non utilisés» : le nombre de véhicules non utilisés
«emplois» :
«scheduledTasks» : le nombre de tâches planifiées
«unassignedTasks» : le nombre de tâches non attribuées
«fois» :
«totalHours» : le nombre total d'heures de trajet pour l'ensemble de la flotte. Ce chiffre comprend le temps passé à se déplacer entre le point de départ et le point d'arrivée de chaque véhicule.
«revenueHours» : le nombre total d'heures de service de l'ensemble de la flotte. Cet indicateur prend en compte le temps écoulé entre le premier et le dernier arrêt pour chaque véhicule. Il n'inclut pas le temps passé à se rendre du point de départ du véhicule au premier arrêt, ni celui passé à se rendre du dernier arrêt au point d'arrivée du véhicule.
Exemple :
"statistics": {
"distance": {
"totalDistance": 42,
"revenueDistance": 25
},
"vehicles": {
"used": 2,
"unused": 0
},
"jobs": {
"scheduledTasks": 3,
"unassignedTasks": 0
},
"times": {
"totalHours": 11.6,
"revenueHours": 10.8
}
}
itinéraires: il fournit un tableau contenant l'itinéraire prévu pour chaque véhicule. Chaque itinéraire prévu contient les données suivantes :
«vehicleId» : un nombre entier qui indique l'identifiant du véhicule attribué
«shifts» : un tableau d'objets « shift ». Notez que l'API prend en charge plusieurs quarts de travail pour chaque véhicule. Chaque objet « shift » comprend les éléments suivants :
«index» : l'indice du décalage (entier)
« arrêts » : cette section fournit une liste de tous les arrêts que le véhicule doit effectuer au cours de ce service. Chaque arrêt présente les propriétés suivantes :
«ordinal» : la position de l'arrêt dans l'horaire, représentée par son index (nombre entier).
«jobId» : l'identifiant de la tâche associée à cet arrêt (entier)
«taskId» : l'identifiant de la tâche associée à cet arrêt (entier)
«type» : le type (chaîne de caractères) de la tâche à effectuer à cet arrêt (« enlèvement » ou « livraison »)
«emplacement» : les coordonnées géographiques de l'emplacement de l'arrêt
«eta» : l'heure d'arrivée prévue (ETA) pour l'arrêt (dans le même fuseau horaire que la charge utile d'entrée)
« timeToNext » : ils'agit du temps de trajet jusqu'au prochain arrêt. Par exemple, si vous déposez un passager à 9 h et que votre prochaine course est prévue à 10 h, cette statistique vous indique que le temps de trajet entre l'arrêt actuel et le prochain arrêt est de 20 minutes.
« distanceToNext » : il s'agit de la distance à parcourir en voiture jusqu'à l'arrêt suivant. Selon les unités sélectionnées dans la « configuration », cette valeur peut être exprimée en miles ou en mètres.
« waitTime » : le temps d'attente indique combien de temps le conducteur devra attendre au prochain arrêt s'il démarre maintenant.
«polyline» : la polyligne reliant l'arrêt à l'arrêt précédent. Si une polyligne « simple » est spécifiée dans la « configuration », la polyligne correspond à une liste ordonnée des intersections que l'on doit emprunter entre l'arrêt précédent et l'arrêt actuel. Si une polyligne « codée » est spécifiée dans la « configuration », la polyligne simple est codée et renvoyée sous forme de chaîne codée.
«break» : si l'arrêt programmé correspond à une pause, cet élément représente l'identifiant de la pause. Les autres arrêts ne comportent pas cet élément. L'API n'impose pas que les pauses (ou les tâches) soient répertoriées par ordre chronologique.
Exemple :
"routes": [
{
"vehicleId": 1,
"shifts": [
{
"index": 1,
"stops": [
{
"break": 1,
"start": "2023-10-01T10:00:00-08:00",
"end": "2023-10-01T10:15:00-08:00",
"timeToNext": 15,
"distanceToNext": 7.3,
"waitTime": 0,
"polyline": null,
"ordinal": 1
},
{
"jobId": 4,
"taskId": 5,
"type": "pickup",
"location": [
50.70816,
-120.37796
],
"eta": "2023-10-01T10:30:00-08:00",
"timeToNext": 13,
"distanceToNext": 5.6,
"waitTime": 112,
"polyline": null,
"ordinal": 2
},
{
"jobId": 4,
"taskId": 6,
"type": "delivery",
"location": [
50.66559,
-120.36924
],
"eta": "2023-10-01T12:45:00-08:00",
"timeToNext": 4,
"distanceToNext": 1.7,
"waitTime": 71,
"polyline": null,
"ordinal": 3
},
{
"break": 2,
"start": "2023-10-01T14:00:00-08:00",
"end": "2023-10-01T14:15:00-08:00",
"timeToNext": 7,
"distanceToNext": 3.2,
"waitTime": 217,
"polyline": null,
"ordinal": 4
}
]
}
]
},
{
"vehicleId": 2,
"shifts": [
{
"index": 1,
"stops": [
{
"break": 1,
"start": "2023-10-01T11:00:00-08:00",
"end": "2023-10-01T11:15:00-08:00",
"timeToNext": 3,
"distanceToNext": 1.2,
"waitTime": 267,
"polyline": null,
"ordinal": 1
},
{
"jobId": 10,
"taskId": 11,
"type": "pickup",
"location": [
50.65187,
-120.40052
],
"eta": "2023-10-01T15:45:00-08:00",
"timeToNext": 12,
"distanceToNext": 6.4,
"waitTime": 0,
"polyline": null,
"ordinal": 2
},
{
"jobId": 10,
"taskId": 12,
"type": "delivery",
"location": [
50.69262,
-120.35412
],
"eta": "2023-10-01T16:22:00-08:00",
"timeToNext": 6,
"distanceToNext": 2.7,
"waitTime": 91,
"polyline": null,
"ordinal": 3
}
]
}
]
}
]
Non attribué: la liste facultative des tâches non attribuées contient les tâches qui ne peuvent être attribuées en raison de contraintes spécifiques. Chaque élément comprend un identifiant de travail, un identifiant de tâche et, le cas échéant, les motifs de non-attribution (un code accompagné d'une description) :
«id» :
«job» : l'identifiant (entier) de la tâche non attribuée
«task» : l'identifiant (entier) de la tâche non attribuée
«raison» : un tableau contenant les raisons possibles pour lesquelles les tâches n'ont pas été attribuées
«code» : le code (entier) correspondant à la raison possible
«description» : la description (chaîne de caractères) de la raison possible
{
"unassigned": [
{
"id": {
"job": 2,
"task": 1
},
"reason": [
{
"code": 2,
"description": "Not enough capacity for this job"
}
]
},
{
"id": {
"job": "31",
"task": "2"
},
"reason": [
{
"code": 5,
"description": "The service time of the job is out of the shift hours"
}
]
}
]
}
Glossaire n°
|
|---|
Tutoriels #
Sur cette page, vous trouverez divers exemples illustrant comment utiliser l'API dans différents cas de figure. L'API prend principalement en charge deux cas d'utilisation principaux :
-
Planification et ordonnancement: génère un planning optimisé pour les tournées d'une flotte, en tenant compte des contraintes liées aux missions et aux véhicules.
-
Réoptimisation: modification d'un planning existant ou en cours afin de tenir compte de changements tels que de nouvelles missions, des annulations ou des pannes de véhicules.
Consultez les exemples fournis pour découvrir comment ces cas d'utilisation sont mis en œuvre :
Exemple 1 : Planification d'un scénario simple d'enlèvement et de livraison (dépôt)
Exemple 2 : un scénario simple de réoptimisation visant à ajouter de nouvelles tâches à un planning existant
Exemple 3 : Réoptimisation avec des tâches annulées
Exemple 4 : Réoptimisation avec des véhicules hors service
Les lieux mentionnés dans les exemples suivants sont fictifs et générés aléatoirement ; ils ne correspondent à aucun lieu réel.
Exemple 1 : Planification d'un scénario simple d'enlèvement et de livraison #
Dans cet exemple, notre flotte se compose de deux véhicules et nous avons trois missions d'enlèvement et de livraison qui doivent être effectuées par ces deux véhicules. Voici les détails pour chaque véhicule :
Véhicule 1 :
Détails du service : Le service commence le 1er octobre 2024 à 8 h 00 (heure du Pacifique) au point de repère (50.67293, -120.34195) et se termine à 18 h 00 au même endroit. Notez que le fuseau horaire est le PST ; l'heure de début sera donc enregistrée comme 2024-10-01T08:00:00-08:00, et l'heure de fin sera 2024-10-01T18:00:00-08:00.
Pauses : Le véhicule prévoit deux pauses de 15 minutes chacune :
Première pause : entre 10 h 00 et 10 h 30 au point (50.6531, -120.38393).
Deuxième pause : entre 14 h 00 et 14 h 30 au point (50.6531, -120.38393).
Capacité : 15 places et 5 places pour le fret.
Caractéristiques : Équipé d'un ascenseur et de la climatisation.
Véhicule 2 :
Détails du service : Le service commence le 01/10/2024 à 8 h 00 (heure du Pacifique) au point de repère (50.7117, -120.39286) et se termine à 18 h 00 au point de repère (50.67698, -120.32012).
Pauses : Le véhicule dispose d'une pause de 15 minutes :
Pause : entre 11 h et 11 h 30 au point de repère (50.6531, -120.38393).
Capacité : 10 places et 8 bagages.
Capacités : Équipé uniquement d'un ascenseur.
Nous proposons également trois missions de « collecte et livraison » à Kamloops, en Colombie-Britannique (Canada). Voici les détails de chaque mission :
Poste n° 1 :
Prise en charge : Coordonnées (50.65391, -120.37365)
Plage horaire : de 9 h à 9 h 30 (la mission est liée à un enlèvement, qui doit avoir lieu pendant cette plage horaire)
Durée : 10 minutes
Exigences : 1 place assise, 2 places de chargement, véhicule équipé d'un hayon élévateur
Livraison : Coordonnées (50.69409, -120.35425)
Durée : 5 minutes
Job 2 :
Prise en charge : Coordonnées (50.70816, -120.37796)
Durée : 5 minutes
Conditions requises : 1 place, véhicule équipé d'un élévateur et de la climatisation
Livraison : Coordonnées (50.66559, -120.36924)
Plage horaire : de 12 h 45 à 13 h 30 (la tâche est liée à une livraison, qui doit être effectuée pendant cette plage horaire)
Durée : 5 minutes
Job 3 :
Prise en charge : Coordonnées (50.70393, -120.37263)
Plage horaire : de 14 h à 14 h 30 (la mission est liée à un enlèvement, qui doit avoir lieu pendant cette plage horaire)
Durée : 10 minutes
Exigences : 1 place assise, 3 colis, aucun équipement spécifique n'est requis
Livraison : Coordonnées (50.69028, -120.39028)
Durée : 5 minutes
Notre objectif est d'attribuer ces missions aux véhicules définis de manière à minimiser la durée totale du trajet. En d'autres termes, notre objectif d'optimisation sera égal à 1. Formulons maintenant notre problème comme suit :
Problème d'entrée (charge utile) :
{
"problem": {
"fleet": [
{
"id": 1,
"shifts": [
{
"start": {
"time": "2023-10-01T08:00:00-08:00",
"location": {
"lat": 50.67293,
"lng": -120.34195
}
},
"end": {
"time": "2023-10-01T18:00:00-08:00",
"location": {
"lat": 50.67293,
"lng": -120.34195
}
},
"breaks": [
{
"serviceWindow": [
"2023-10-01T10:00:00-08:00",
"2023-10-01T10:30:00-08:00"
],
"duration": 900,
"location": {
"lat": 50.6531,
"lng": -120.38393
}
},
{
"serviceWindow": [
"2023-10-01T14:00:00-08:00",
"2023-10-01T14:30:00-08:00"
],
"duration": 900,
"location": {
"lat": 50.6531,
"lng": -120.38393
}
}
]
}
],
"capacities": [
{
"name": "seat",
"units": 15
},
{
"name": "cargo",
"units": 5
}
],
"skills": [
"lift",
"air_conditioner"
]
},
{
"id": 2,
"shifts": [
{
"start": {
"time": "2023-10-01T08:00:00-08:00",
"location": {
"lat": 50.7117,
"lng": -120.39286
}
},
"end": {
"time": "2023-10-01T18:00:00-08:00",
"location": {
"lat": 50.67698,
"lng": -120.32012
}
},
"breaks": [
{
"serviceWindow": [
"2023-10-01T11:00:00-08:00",
"2023-10-01T11:30:00-08:00"
],
"duration": 900,
"location": {
"lat": 50.6531,
"lng": -120.38393
}
}
]
}
],
"capacities": [
{
"name": "seat",
"units": 10
},
{
"name": "cargo",
"units": 8
}
],
"skills": [
"lift"
]
}
],
"jobs": [
{
"id": 1,
"pickups": [
{
"id": 2,
"location": [
50.65391,
-120.37365
],
"serviceWindows": [
[
"2023-10-01T09:00:00-08:00",
"2023-10-01T09:30:00-08:00"
]
],
"duration": 600,
"demand": [
{
"name": "seat",
"units": 1
},
{
"name": "cargo",
"units": 2
}
],
"skills": [
"lift"
]
}
],
"deliveries": [
{
"id": 3,
"location": [
50.69409,
-120.35425
],
"duration": 300,
"demand": [
{
"name": "seat",
"units": 1
},
{
"name": "cargo",
"units": 2
}
],
"skills": [
"lift"
]
}
]
},
{
"id": 4,
"pickups": [
{
"id": 5,
"location": [
50.70816,
-120.37796
],
"duration": 300,
"demand": [
{
"name": "seat",
"units": 1
}
],
"skills": [
"lift",
"air_conditioner"
]
}
],
"deliveries": [
{
"id": 6,
"location": [
50.66559,
-120.36924
],
"serviceWindows": [
[
"2023-10-01T12:45:00-08:00",
"2023-10-01T13:30:00-08:00"
]
],
"duration": 300,
"demand": [
{
"name": "seat",
"units": 1
}
],
"skills": [
"lift",
"air_conditioner"
]
}
]
},
{
"id": 7,
"pickups": [
{
"id": 8,
"location": [
50.70393,
-120.37263
],
"serviceWindows": [
[
"2023-10-01T14:00:00-08:00",
"2023-10-01T14:30:00-08:00"
]
],
"duration": 600,
"demand": [
{
"name": "seat",
"units": 1
},
{
"name": "cargo",
"units": 3
}
]
}
],
"deliveries": [
{
"id": 9,
"location": [
50.69028,
-120.39028
],
"duration": 300,
"demand": [
{
"name": "seat",
"units": 1
},
{
"name": "cargo",
"units": 3
}
]
}
]
}
],
"objective": 1,
"configuration": {
"polylineType": "none",
"unassignedTasks": true,
"units": "imperial",
"statistics": true
}
}
}
Après avoir soumis ce problème à l'aide de la méthode POST (comme décrit dans la section « Pour commencer »), nous obtenons la solution suivante à l'aide de la méthode GET :
Solution :
{
"id": 8193,
"status": 200,
"solution": {
"statistics": {
"distance": {
"totalDistance": 54,
"revenueDistance": 36
},
"vehicles": {
"used": 2,
"unused": 0
},
"jobs": {
"scheduledTasks": 3,
"unassignedTasks": 0
},
"times": {
"totalHours": 9.4,
"revenueHours": 8.7
}
},
"routes": [
{
"vehicleId": 1,
"shifts": [
{
"index": 1,
"stops": [
{
"jobId": 1,
"taskId": 2,
"type": "pickup",
"location": [
50.65391,
-120.37365
],
"eta": "2023-10-01T09:00:00-08:00",
"timeToNext": 10,
"distanceToNext": 4.9,
"waitTime": 0,
"polyline": null,
"ordinal": 1
},
{
"jobId": 1,
"taskId": 3,
"type": "delivery",
"location": [
50.69409,
-120.35425
],
"eta": "2023-10-01T09:25:00-08:00",
"timeToNext": 10,
"distanceToNext": 5.4,
"waitTime": 25,
"polyline": null,
"ordinal": 2
},
{
"break": 1,
"start": "2023-10-01T10:00:00-08:00",
"end": "2023-10-01T10:15:00-08:00",
"timeToNext": 15,
"distanceToNext": 7.3,
"waitTime": 0,
"polyline": null,
"ordinal": 3
},
{
"jobId": 4,
"taskId": 5,
"type": "pickup",
"location": [
50.70816,
-120.37796
],
"eta": "2023-10-01T10:30:00-08:00",
"timeToNext": 13,
"distanceToNext": 5.6,
"waitTime": 112,
"polyline": null,
"ordinal": 4
},
{
"jobId": 4,
"taskId": 6,
"type": "delivery",
"location": [
50.66559,
-120.36924
],
"eta": "2023-10-01T12:45:00-08:00",
"timeToNext": 4,
"distanceToNext": 1.7,
"waitTime": 71,
"polyline": null,
"ordinal": 5
},
{
"break": 2,
"start": "2023-10-01T14:00:00-08:00",
"end": "2023-10-01T14:15:00-08:00",
"timeToNext": 7,
"distanceToNext": 3.2,
"waitTime": 217,
"polyline": null,
"ordinal": 6
}
]
}
]
},
{
"vehicleId": 2,
"shifts": [
{
"index": 1,
"stops": [
{
"break": 1,
"start": "2023-10-01T11:00:00-08:00",
"end": "2023-10-01T11:15:00-08:00",
"timeToNext": 13,
"distanceToNext": 6.6,
"waitTime": 152,
"polyline": null,
"ordinal": 1
},
{
"jobId": 7,
"taskId": 8,
"type": "pickup",
"location": [
50.70393,
-120.37263
],
"eta": "2023-10-01T14:00:00-08:00",
"timeToNext": 14,
"distanceToNext": 4.6,
"waitTime": 0,
"polyline": null,
"ordinal": 2
},
{
"jobId": 7,
"taskId": 9,
"type": "delivery",
"location": [
50.69028,
-120.39028
],
"eta": "2023-10-01T14:29:00-08:00",
"timeToNext": 13,
"distanceToNext": 3.9,
"waitTime": 197,
"polyline": null,
"ordinal": 3
}
]
}
]
}
],
"unassigned": []
},
"message": "success"
}
Exemple 2 : Un scénario simple de réoptimisation pour ajouter de nouvelles tâches à un planning existant #
Reprenons maintenant l'exemple précédent. Supposons que vous ayez commencé à exécuter le planning établi dès ce matin, qu'il soit actuellement 11 h 36 min 34 s et que vous receviez un nouvel ordre de travail comme suit :
Emploi n° 4 : ( un nouvel emploi)
Prise en charge : Coordonnées (50.65187, -120.40052)
Plage horaire : de 15 h 45 à 16 h 15 (mission avec point d'ancrage au point de ramassage)
Durée : 15 minutes
Configuration requise : 1 siège, 1 compartiment de chargement
Livraison : Coordonnées (50.69262, -120.35412)
Durée : 10 minutes
Au fait, vous avez déjà terminé la tâche n° 1, mais les tâches n° 2 et n° 3 sont toujours en cours, avec les détails suivants :
Tâche n° 1 : (réalisée)
Job 2 : (en cours)
Prise en charge :
Numéro d'identification actuel du véhicule : 1
Heure d'arrivée prévue : 10 h 30
Livraison :
Numéro d'identification actuel du véhicule : 1
Heure d'arrivée prévue : 12 h 45
Job 3 : (en cours)
Prise en charge :
Numéro d'identification actuel du véhicule : 2
Heure d'arrivée prévue : 14 h
Livraison :
Numéro d'identification actuel du véhicule : 2
Heure d'arrivée prévue : 14 h 29
Notez que, puisque les tâches 2 et 3 sont en cours d'exécution, elles sont associées à un identifiant de véhicule et à une heure d'arrivée prévue. Pour réoptimiser votre planning afin d'y inclure la nouvelle tâche (c'est-à-dire la tâche 4), vous devrez fournir une vue actualisée de votre planning actuel via l'API. Celle-ci doit inclure les informations suivantes concernant vos tâches :
Poste n° 1 : Pour cette commande, puisqu'elle a déjà été traitée, vous pouvez définir le statut des tâches d'enlèvement et de livraison pour cette commande sur "status":"performed" . Notez que vous n'avez pas besoin d'indiquer l'identifiant actuel du véhicule ni l'heure d'arrivée prévue pour ces tâches, car elles ont déjà été effectuées et vous ne pouvez plus les modifier.
Tâche 2 : cette tâche est toujours en cours et a été attribuée au véhicule 2, avec une heure d'arrivée prévue pour l'enlèvement à 10 h 30 et une heure d'arrivée prévue pour la livraison à 12 h 45. Vous devez donc inclure l'objet suivant pour la tâche d'enlèvement :
"status": "in_progress",
"vehicleId": 1,
"eta": "2024-10-01T10:30:00-08:00"
Vous devez également inclure l'objet suivant pour sa tâche de livraison :
"status": "in_progress",
"vehicleId": 1,
"eta": "2024-10-01T12:45:00-08:00"
"status": "in_progress",
"vehicleId": 2,
"eta": "2024-10-01T14:00:00-08:00"
Vous devez également inclure l'objet suivant pour sa tâche de livraison :
"status": "in_progress",
"vehicleId": 2,
"eta": "2024-10-01T14:29:00-08:00"
Job 4 : Comme il s'agit d'une nouvelle tâche qui n'est pas encore planifiée, il vous suffit de définir son statut sur "status":"pending". Vous n'avez pas besoin d'indiquer un identifiant de véhicule ni une heure d'arrivée prévue pour cette mission, car celle-ci n'est pas encore planifiée et vous ne disposez pas de ces informations. Une fois la réoptimisation effectuée, vous obtiendrez un identifiant de véhicule et une heure d'arrivée prévue pour chaque tâche de cette mission.
De plus, vous devez fournir la dernière position connue de vos véhicules afin que l'API puisse disposer d'une image actualisée de votre planning actuel et effectuer l'optimisation de manière efficace. Supposons que la dernière position connue de vos véhicules à 11 h 36 min 34 s (c'est-à-dire l'heure à laquelle nous souhaitons procéder à une nouvelle optimisation) soit la suivante :
- Véhicule 1 : ( 50,66692, -120,35293)
- Véhicule 2 : ( 50,65324, -120,37398)
Pour cela, vous devez inclure l'objet suivant pour le véhicule 1 :
"lastKnownLocation":{
"location":[50.66692,-120.35293],
"time":"2024-10-01T11:36:34-08:00"
}
De même, vous devez inclure l'objet suivant pour le véhicule 2 :
"lastKnownLocation":{
"location":[50.65324,-120.37398],
"time":"2024-10-01T11:36:34-08:00"
}
Pour procéder à une nouvelle optimisation, vous pouvez désormais soumettre votre nouveau problème d'optimisation comme suit :
{
"problem": {
"fleet": [
{
"id": 1,
"shifts": [
{
"start": {
"time": "2023-10-01T08:00:00-08:00",
"location": {
"lat": 50.67293,
"lng": -120.34195
}
},
"end": {
"time": "2023-10-01T18:00:00-08:00",
"location": {
"lat": 50.67293,
"lng": -120.34195
}
},
"breaks": [
{
"serviceWindow": [
"2023-10-01T10:00:00-08:00",
"2023-10-01T10:30:00-08:00"
],
"duration": 900,
"location": {
"lat": 50.6531,
"lng": -120.38393
}
},
{
"serviceWindow": [
"2023-10-01T14:00:00-08:00",
"2023-10-01T14:30:00-08:00"
],
"duration": 900,
"location": {
"lat": 50.6531,
"lng": -120.38393
}
}
]
}
],
"capacities": [
{
"name": "seat",
"units": 15
},
{
"name": "cargo",
"units": 5
}
],
"skills": [
"lift",
"air_conditioner"
],
"lastKnownLocation":{
"location":[50.66692,-120.35293],
"time":"2024-10-01T11:36:34-08:00"
}
},
{
"id": 2,
"shifts": [
{
"start": {
"time": "2023-10-01T08:00:00-08:00",
"location": {
"lat": 50.7117,
"lng": -120.39286
}
},
"end": {
"time": "2023-10-01T18:00:00-08:00",
"location": {
"lat": 50.67698,
"lng": -120.32012
}
},
"breaks": [
{
"serviceWindow": [
"2023-10-01T11:00:00-08:00",
"2023-10-01T11:30:00-08:00"
],
"duration": 900,
"location": {
"lat": 50.6531,
"lng": -120.38393
}
}
]
}
],
"capacities": [
{
"name": "seat",
"units": 10
},
{
"name": "cargo",
"units": 8
}
],
"skills": [
"lift"
],
"lastKnownLocation":{
"location":[50.65324,-120.37398],
"time":"2024-10-01T11:36:34-08:00"
}
}
],
"jobs": [
{
"id": 1,
"pickups": [
{
"id": 2,
"location": [
50.65391,
-120.37365
],
"serviceWindows": [
[
"2023-10-01T09:00:00-08:00",
"2023-10-01T09:30:00-08:00"
]
],
"duration": 600,
"demand": [
{
"name": "seat",
"units": 1
},
{
"name": "cargo",
"units": 2
}
],
"skills": [
"lift"
],
"status": "performed"
}
],
"deliveries": [
{
"id": 3,
"location": [
50.69409,
-120.35425
],
"duration": 300,
"demand": [
{
"name": "seat",
"units": 1
},
{
"name": "cargo",
"units": 2
}
],
"skills": [
"lift"
],
"status": "performed"
}
]
},
{
"id": 4,
"pickups": [
{
"id": 5,
"location": [
50.70816,
-120.37796
],
"duration": 300,
"demand": [
{
"name": "seat",
"units": 1
}
],
"skills": [
"lift",
"air_conditioner"
],
"status": "in_progress",
"vehicleId": 1,
"eta": "2023-10-01T10:30:00-08:00"
}
],
"deliveries": [
{
"id": 6,
"location": [
50.66559,
-120.36924
],
"serviceWindows": [
[
"2023-10-01T12:45:00-08:00",
"2023-10-01T13:30:00-08:00"
]
],
"duration": 300,
"demand": [
{
"name": "seat",
"units": 1
}
],
"skills": [
"lift",
"air_conditioner"
],
"status": "in_progress",
"vehicleId": 1,
"eta": "2023-10-01T12:45:00-08:00"
}
]
},
{
"id": 7,
"pickups": [
{
"id": 8,
"location": [
50.70393,
-120.37263
],
"serviceWindows": [
[
"2023-10-01T14:00:00-08:00",
"2023-10-01T14:30:00-08:00"
]
],
"duration": 600,
"demand": [
{
"name": "seat",
"units": 1
},
{
"name": "cargo",
"units": 3
}
],
"status": "in_progress",
"vehicleId": 2,
"eta": "2023-10-01T14:00:00-08:00"
}
],
"deliveries": [
{
"id": 9,
"location": [
50.69028,
-120.39028
],
"duration": 300,
"demand": [
{
"name": "seat",
"units": 1
},
{
"name": "cargo",
"units": 3
}
],
"status": "in_progress",
"vehicleId": 2,
"eta": "2023-10-01T14:29:00-08:00"
}
]
},
{
"id": 10,
"pickups": [
{
"id": 11,
"location": [
50.65187,
-120.40052
],
"serviceWindows": [
[
"2023-10-01T15:45:00-08:00",
"2023-10-01T16:15:00-08:00"
]
],
"duration": 900,
"demand": [
{
"name": "seat",
"units": 1
},
{
"name": "cargo",
"units": 1
}
],
"status": "pending"
}
],
"deliveries": [
{
"id": 12,
"location": [
50.69262,
-120.35412
],
"duration": 600,
"demand": [
{
"name": "seat",
"units": 1
},
{
"name": "cargo",
"units": 1
}
],
"status": "pending"
}
]
}
],
"objective": 1,
"configuration": {
"polylineType": "none",
"unassignedTasks": true,
"units": "imperial",
"statistics": true
}
}
}
Exemple 3 : Réoptimisation avec des tâches annulées #
Si vous avez soumis un problème d'optimisation pour un ensemble de tâches et que vous disposez déjà d'un planning, mais que certaines tâches ont été annulées, vous pouvez réoptimiser votre planning en retirant les tâches annulées du problème. Pour ce faire, vous devez :
- Fournissez un aperçu actualisé de vos missions en cours et des dernières positions connues de vos véhicules, comme dans l'exemple 2.
- Créez et soumettez une version révisée du problème tenant compte de ces modifications.
Une fois la demande envoyée, vous recevrez un nouveau planning tenant compte des missions mises à jour et de l'état de la flotte.
Exemple 4 : Réoptimisation avec des véhicules en panne #
Imaginons qu'il soit 8 h et que vous utilisiez l'API pour générer un planning optimisé pour vos missions avec 10 véhicules. Vous commencez à mettre ce planning en œuvre, mais à 9 h 14, vous apprenez qu'un de vos véhicules est tombé en panne et ne peut plus effectuer les missions qui lui ont été attribuées.
Pour réoptimiser le planning, procédez comme suit :
-
Mise à jour des informations sur la flotte: supprimez le véhicule hors service de votre objet « flotte ».
-
Indiquez la position des véhicules: indiquez les dernières positions connues des véhicules restants, comme dans l'exemple 2.
-
Mettre à jour le statut de la tâche:
-
Indiquez l'état d'avancement de toutes les tâches. Vous devez préciser quelles tâches ont déjà été réalisées, lesquelles sont en cours et lesquelles sont nouvelles ou en attente (pas encore planifiées).
-
Pour les interventions en cours, veuillez indiquer le numéro d'identification du véhicule concerné et l'heure d'arrivée prévue (ETA).
-
-
Gérer les opérations liées au véhicule en panne:
-
Modifiez le statut de toutes les tâches précédemment attribuées au véhicule en panne pour le mettre sur « en attente ». Cela permet à l'API de les réattribuer à d'autres véhicules disponibles et de recalculer leurs heures d'arrivée prévues.
-
-
Soumettre pour une nouvelle optimisation: soumettre le problème mis à jour à l'API afin d'obtenir un nouveau planning optimisé.
Comment tester les itinéraires planifiés ? #
Étape 1 : Générer un jeton d'accès
Commencez par envoyer une requête POST à l'URL suivante afin d'obtenir un jeton d'accès pour Vancouver (Tenant 2) en utilisant les identifiants suivants :
URL de l'article : https://iq.aiqwhite.ddsdeploytest.com/sso/auth-token
Requête POST – Corps du message pour Vancouver (Tenant2) :
{
"plugin": "internal;basic",
"internal": {
"email": "tenant2@ddswireless.com",
"password": "AdM5I0N09ToS$IlJ",
"tenantId": 2
},
"basic": {
"username": "tenant2@ddswireless.com",
"password": "AdM5I0N09ToS$IlJ",
"tenantId": 2
}
}
Requête POST – Corps du message pour la Finlande (Tenant3) :
{
"plugin": "internal;basic",
"internal": {
"email": "tenant3@ddswireless.com",
"password": "AdM5I0N09ToS$IlJ",
"tenantId": 3
},
"basic": {
"username": "tenant3@ddswireless.com",
"password": "AdM5I0N09ToS$IlJ",
"tenantId": 3
}
}
Copiez ensuite le jeton généré. Voici une capture d'écran illustrant cette étape :

Étape 2 : Envoyer une charge utile (problème d'optimisation) à l'API
Pour envoyer une charge utile d'entrée à l'API et obtenir un identifiant de référence, insérez le jeton généré dans la partie « Authorization » de la requête POST suivante, et insérez la charge utile d'entrée dans la partie « Body » de la requête :
URL de l'article : https://iq.aiqwhite.ddsdeploytest.com/raas/optimization
Exemple de charge utile d'entrée :
{
"problem": {
"fleet": [
{
"id": 1,
"shifts": [
{
"start": {
"time": "2023-10-01T08:00:00-08:00",
"location": { "lat": 50.67293, "lng": -120.34195 }
},
"end": {
"time": "2023-10-01T18:00:00-08:00",
"location": { "lat": 50.67293, "lng": -120.34195 }
},
"breaks": [
{
"serviceWindow": ["2023-10-01T10:00:00-08:00", "2023-10-01T10:30:00-08:00"],
"duration": 900,
"location": { "lat": 50.6531, "lng": -120.38393 }
},
{
"serviceWindow": ["2023-10-01T14:00:00-08:00", "2023-10-01T14:30:00-08:00"],
"duration": 900,
"location": { "lat": 50.6531, "lng": -120.38393 }
}
]
}
],
"capacities": [
{
"name": "seat",
"units": 15
},
{
"name": "baggage",
"units": 5
}
],
"skills": ["lift", "air_conditioner"]
},
{
"id": 2,
"shifts": [
{
"start": {
"time": "2023-10-01T08:00:00-08:00",
"location": { "lat": 50.7117, "lng": -120.39286 }
},
"end": {
"time": "2023-10-01T18:00:00-08:00",
"location": { "lat": 50.67698, "lng": -120.32012 }
},
"breaks": [
{
"serviceWindow": ["2023-10-01T11:00:00-08:00", "2023-10-01T11:30:00-08:00"],
"duration": 900,
"location": { "lat": 50.6531, "lng": -120.38393 }
}
]
}
],
"capacities": [
{
"name": "seat",
"units": 10
},
{
"name": "baggage",
"units": 8
}
],
"skills": ["lift"]
}
],
"jobs": [
{
"id": 1,
"pickups": [
{
"id": 2,
"location": [50.65391, -120.37365],
"serviceWindows": [["2023-10-01T09:00:00-08:00", "2023-10-01T09:30:00-08:00"]],
"duration": 600,
"demand": [
{
"name": "seat",
"units": 1
},
{
"name": "baggage",
"units": 2
}
],
"skills": ["lift"]
}
],
"deliveries": [
{
"id": 3,
"location": [50.69409, -120.35425],
"duration": 300,
"demand": [
{
"name": "seat",
"units": 1
},
{
"name": "baggage",
"units": 2
}
],
"skills": ["lift"]
}
]
},
{
"id": 4,
"pickups": [
{
"id": 5,
"location": [50.70816, -120.37796],
"duration": 300,
"demand": [
{
"name": "seat",
"units": 1
}
],
"skills": ["lift", "air_conditioner"]
}
],
"deliveries": [
{
"id": 6,
"location": [50.66559, -120.36924],
"serviceWindows": [["2023-10-01T12:45:00-08:00", "2023-10-01T13:30:00-08:00"]],
"duration": 300,
"demand": [
{
"name": "seat",
"units": 1
}
],
"skills": ["lift", "air_conditioner"]
}
]
},
{
"id": 7,
"pickups": [
{
"id": 8,
"location": [50.70393, -120.37263],
"serviceWindows": [["2023-10-01T14:00:00-08:00", "2023-10-01T14:30:00-08:00"]],
"duration": 600,
"demand": [
{
"name": "seat",
"units": 1
},
{
"name": "baggage",
"units": 3
}
]
}
],
"deliveries": [
{
"id": 9,
"location": [50.69028, -120.39028],
"duration": 300,
"demand": [
{
"name": "seat",
"units": 1
},
{
"name": "baggage",
"units": 3
}
]
}
]
}
],
"objective": 1,
"configuration": {
"polylineType": "none",
"unassignedTasks": true,
"units" : "imperial",
"statistics" : true
}
}
}
Si la méthode POST aboutit, vous obtenez un identifiant de référence qui vous permet de récupérer la réponse de l'appel API via la méthode GET. Voici une capture d'écran illustrant cette étape :

Étape 3 : Récupérer la réponse générée par l'appel de l'API
Pour obtenir la réponse de l'appel API à l'aide de l'ID de référence reçu, insérez le jeton d'accès dans la partie « Authorization » de la requête GET suivante, et incluez l'ID de référence dans l'URL comme suit :
GET URL: https://iq.aiqwhite.ddsdeploytest.com/raas/optimization/{ID}
Voici une capture d'écran de cette étape :

Erreurs API #
Comme indiqué dans la section « Pour commencer », l'API prend en charge les méthodes POST et GET. Selon la méthode utilisée, elle renvoie un code d'état dans la réponse. Vous trouverez ici la description des différents codes d'état associés à ces deux méthodes.
Codes d'état POST #
|
|---|
Codes d'état GET #
|
|---|
FAQ n°
|