Ce scénario optimise l'ordre des arrêts attribués à un véhicule avec des paramètres de coût simples. Il s'agit du mode de fonctionnement le plus simple de l'optimisation d'itinéraire. Il garantit que tous les arrêts sont visités dans le délai spécifié.
L'exemple suivant illustre un scénario de base avec un véhicule et trois expéditions, tous provenant d'un même lieu appelé dépôt.
Voir un exemple de demande
{ "populatePolylines": true, "populateTransitionPolylines": true, "model": { "globalStartTime": "2023-01-13T16:00:00-08:00", "globalEndTime": "2023-01-14T16:00:00-08:00", "shipments": [ { "deliveries": [ { "arrivalLocation": { "latitude": 37.789456, "longitude": -122.390192 }, "duration": "250s" } ], "pickups": [ { "arrivalLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "duration": "150s" } ] }, { "deliveries": [ { "arrivalLocation": { "latitude": 37.789116, "longitude": -122.395080 }, "duration": "250s" } ], "pickups": [ { "arrivalLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "duration": "150s" } ] }, { "deliveries": [ { "arrivalLocation": { "latitude": 37.795242, "longitude": -122.399347 }, "duration": "250s" } ], "pickups": [ { "arrivalLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "duration": "150s" } ] } ], "vehicles": [ { "endLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "startLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "costPerKilometer": 10.0, "costPerHour": 40.0 } ] } }
Champs de la demande d'optimisation des routes
Comme indiqué dans la présentation, les propriétés de requête d'optimisation des itinéraires les plus importantes sont vehicles
et shipments
.
En plus d'un véhicule et d'expéditions, la requête inclut les champs suivants :
Polylignes
populatePolylines
et populateTransitionPolylines
indiquent si RouteOptimization doit renvoyer des polylignes.
Le service encode les polylignes à l'aide du codec de polylignes Maps JS, qui représente les données binaires des polylignes à l'aide de caractères ASCII imprimables. Vous pouvez utiliser l'utilitaire d'encodage interactif des polylignes pour visualiser les itinéraires calculés par l'optimisation des itinéraires. L'exemple de ce guide définit populatePolylines
et populateTransitionPolylines
sur "true", mais d'autres guides les définissent sur "false" pour réduire la taille de la réponse.
Pour obtenir une description du format d'encodage, consultez Format d'algorithme des polylignes encodées.
Contraintes de temps globales
model.globalStartTime
et model.globalEndTime
sont définis sur une période arbitraire de 24 heures. Cela facilite l'interprétation des codes temporels de sortie.
Visiter des lieux
L'exemple de requête n'utilise que model.shipments[].pickups[].arrivalLocation
et model.shipments[].deliveries[].arrivalLocation
. Il existe également une propriété departureLocation
pour les situations où le véhicule part d'un point différent de celui où il arrive, comme un parking avec une entrée d'un côté du bâtiment et une sortie de l'autre. Dans ce guide et les suivants, nous partons du principe que les points d'arrivée et de départ sont identiques.
Les champs "arrival" et "departure" waypoint
sont également disponibles comme alternative à latLng
.
Les champs Waypoint
sont compatibles avec les ID de lieu Google en tant qu'alternative à LatLng
et peuvent également spécifier les cap de véhicules. Pour en savoir plus, consultez la documentation de référence (REST, gRPC).
Contraintes dans l'exemple
Ce scénario contraint l'optimiseur de plusieurs manières :
- Toutes les activités doivent être effectuées entre les heures de début et de fin globales. Dans ce scénario, les heures de début et de fin sont une contrainte très souple compte tenu de la proximité des expéditions et de la large plage horaire mondiale.
- Toutes les expéditions doivent être effectuées. Il s'agit du comportement par défaut lorsque les coûts de pénalité ne sont pas spécifiés dans
shipments
. costPerKilometer
etcostPerHour
sont définis sur le véhicule.
Les coûts sont abordés dans Paramètres du modèle de coûts.
Propriétés de la réponse Route Optimization
Voir une réponse à l'exemple de requête
{ "routes": [ { "vehicleStartTime": "2023-01-14T00:00:00Z", "vehicleEndTime": "2023-01-14T00:36:41Z", "visits": [ { "shipmentIndex": 2, "isPickup": true, "startTime": "2023-01-14T00:00:00Z", "detour": "0s" }, { "shipmentIndex": 1, "isPickup": true, "startTime": "2023-01-14T00:02:30Z", "detour": "150s" }, { "isPickup": true, "startTime": "2023-01-14T00:05:00Z", "detour": "300s" }, { "startTime": "2023-01-14T00:11:25Z", "detour": "0s" }, { "shipmentIndex": 1, "startTime": "2023-01-14T00:19:29Z", "detour": "503s" }, { "shipmentIndex": 2, "startTime": "2023-01-14T00:29:02Z", "detour": "1324s" } ], "transitions": [ { "travelDuration": "0s", "waitDuration": "0s", "totalDuration": "0s", "startTime": "2023-01-14T00:00:00Z", "routePolyline": {} }, { "travelDuration": "0s", "waitDuration": "0s", "totalDuration": "0s", "startTime": "2023-01-14T00:02:30Z", "routePolyline": {} }, { "travelDuration": "0s", "waitDuration": "0s", "totalDuration": "0s", "startTime": "2023-01-14T00:05:00Z", "routePolyline": {} }, { "travelDuration": "235s", "travelDistanceMeters": 795, "waitDuration": "0s", "totalDuration": "235s", "startTime": "2023-01-14T00:07:30Z", "routePolyline": { "points": "kvteFtfjVAA?C?C@C?A?C@AFMj@s@JKb@k@Zc@LSjA}ARWDGdAxAdAvAXa@@k@AsA\\c@FKp@_A\\c@Ze@fA{ALSFGd@o@rAgBB{BZc@" } }, { "travelDuration": "234s", "travelDistanceMeters": 793, "waitDuration": "0s", "totalDuration": "234s", "startTime": "2023-01-14T00:15:35Z", "routePolyline": { "points": "cwseFti_jVRWj@w@x@eAHLNRHJbApAHLX\\V^?@hA~AT\\PVFFDHDFJNp@~@NRLNNTFFUZIJY^Y^g@p@[`@KP{@fAEFSXe@l@c@h@WZY\\?BELk@v@MNa@l@" } }, { "travelDuration": "323s", "travelDistanceMeters": 1204, "waitDuration": "0s", "totalDuration": "323s", "startTime": "2023-01-14T00:23:39Z", "routePolyline": { "points": "cuseFhjVSTY`@Yb@GHEDIJEF]f@IJi@r@oAbBeCfDKLaApAKNQVIPKPCDQJIBIBM@iAJeALqBVC@C?A?QBYDI@C?_@Dc@FO@a@FDp@HfAHvABVDl@Dj@PpCQDiALsALAQASKwAOgBEe@COCYEa@Es@Eg@" } }, { "travelDuration": "209s", "travelDistanceMeters": 665, "waitDuration": "0s", "totalDuration": "209s", "startTime": "2023-01-14T00:33:12Z", "routePolyline": { "points": "{zteFxbajV?CAYEc@AMC_@AOAK?E?CCWAOAKCe@CY?WScDEm@d@EFA\\ENCB?XEVC^E`@EhBUVCNEB?@?\\Er@IMUe@k@k@w@AAMQa@i@SWQWMQi@u@AC?A" } } ], "routePolyline": { "points": "kvteFtfjVAA?C?C@C?A?C@AFMj@s@JKb@k@Zc@LSjA}ARWDGdAxAdAvAXa@@k@AsA\\c@FKp@_A\\c@Ze@fA{ALSFGd@o@rAgBB{BZc@RWj@w@x@eAHLNRHJbApAHLX\\V^?@hA~AT\\PVFFDHDFJNp@~@NRLNNTFFUZIJY^Y^g@p@[@KP{@fAEFSXe@l@c@h@WZY\\?BELk@v@MNa@l@STY@Yb@GHEDIJEF]f@IJi@r@oAbBeCfDKLaApAKNQVIPKPCDQJIBIBM@iAJeALqBVC@C?A?QBYDI@C?_@Dc@FO@a@FDp@HfAHvABVDl@Dj@PpCQDiALsALAQASKwAOgBEe@COCYEa@Es@Eg@?CAYEc@AMC_@AOAK?E?CCWAOAKCe@CY?WScDEm@d@EFA\\ENCB?XEVC^E`@EhBUVCNEB?@?\\Er@IMUe@k@k@w@AAMQa@i@SWQWMQi@u@AC?A" }, "metrics": { "performedShipmentCount": 3, "travelDuration": "1001s", "waitDuration": "0s", "delayDuration": "0s", "breakDuration": "0s", "visitDuration": "1200s", "totalDuration": "2201s", "travelDistanceMeters": 3457 }, "travelSteps": [ { "duration": "0s", "routePolyline": {} }, { "duration": "0s", "routePolyline": {} }, { "duration": "0s", "routePolyline": {} }, { "duration": "227s", "distanceMeters": 794, "routePolyline": { "points": "kvteFtfjVAA?C?C@C?A?C@AFMj@s@JKb@k@Zc@LSjA}ARWDGdAxAdAvAXa@@k@AsA\\c@FKp@_A\\c@Ze@fA{ALSFGd@o@rAgBB{BZc@" } }, { "duration": "233s", "distanceMeters": 791, "routePolyline": { "points": "cwseFti_jVRWj@w@x@eAHLNRHJbApAHLX\\V^?@hA~AT\\PVFFDHDFJNp@~@NRLNNTFFUZIJY^Y^g@p@[`@KP{@fAEFSXe@l@c@h@WZY\\?BELk@v@MNa@l@" } }, { "duration": "322s", "distanceMeters": 1205, "routePolyline": { "points": "cuseFhjVSTY`@Yb@GHEDIJEF]f@IJi@r@oAbBeCfDKLaApAKNQVIPKPCDQJIBIBM@iAJeALqBVC@C?A?QBYDI@C?_@Dc@FO@a@FDp@HfAHvABVDl@Dj@PpCQDiALsALAQASKwAOgBEe@COCYEa@Es@Eg@" } }, { "duration": "208s", "distanceMeters": 666, "routePolyline": { "points": "{zteFxbajV?CAYEc@AMC_@AOAK?E?CCWAOAKCe@CY?WScDEm@d@EFA\\ENCB?XEVC^E`@EhBUVCNEB?@?\\Er@IMUe@k@k@w@AAMQa@i@SWQWMQi@u@AC?A" } } ], "vehicleDetour": "2201s", "routeCosts": { "model.vehicles.cost_per_hour": 24.455555555555556, "model.vehicles.cost_per_kilometer": 34.57 }, "routeTotalCost": 59.025555555555556 } ], "totalCost": 59.025555555555556, "metrics": { "aggregatedRouteMetrics": { "performedShipmentCount": 3, "travelDuration": "1001s", "waitDuration": "0s", "delayDuration": "0s", "breakDuration": "0s", "visitDuration": "1200s", "totalDuration": "2201s", "travelDistanceMeters": 3457 }, "usedVehicleCount": 1, "earliestVehicleStartTime": "2023-01-14T00:00:00Z", "latestVehicleEndTime": "2023-01-14T00:36:41Z", "totalCost": 59.025555555555556, "costs": { "model.vehicles.cost_per_kilometer": 34.57, "model.vehicles.cost_per_hour": 24.455555555555556 } } }
La réponse de l'optimisation d'itinéraire inclut un champ routes
de premier niveau qui représente les itinéraires proposés, avec un itinéraire par véhicule. Étant donné que l'exemple de requête de ce guide ne spécifie qu'un seul véhicule, routes
inclut un message ShipmentRoute
.
ShipmentRoute
établissements
Les deux propriétés les plus importantes pour le type de message ShipmentRoute
sont visits
et transitions
.
Chaque Visit
représente la fin d'un retrait ou d'une livraison à partir de l'un des VisitRequest
du message de requête. Une visite est une tâche à effectuer par un véhicule à un endroit et à un moment donnés.
Chaque Transition
représente le véhicule se déplaçant d'un lieu à un autre. Des transitions peuvent se produire entre une paire de points de départ, un lieu de visite et le point d'arrivée du véhicule.
Pour reconstruire l'itinéraire complet du véhicule, les visits
et transitions
de ShipmentRoute
doivent être combinés. La combinaison des champs dans une progression de l'activité du véhicule se présente comme suit :
request.vehicles[0].startLocation -> transitions[0] -> visits[0] ->
transitions[1] -> visits[1] -> transitions[2] -> ... -> visits[3] ->
transitions[4] -> request.vehicles[0].endLocation
Un ShipmentRoute
comporte toujours un transitions
de plus que de visits
, car le véhicule doit se rendre de son point de départ à sa première visite au début de l'itinéraire, et de sa dernière visite à son point d'arrivée à la fin de l'itinéraire. Si le véhicule n'a pas de lieu de départ ni d'arrivée, il y aura toujours une transitions
de plus que de visits
, car le lieu de la première ou de la dernière visite est utilisé comme lieu de départ ou d'arrivée du véhicule, respectivement.
Dans cet exemple, les trois premières visites de retrait ont des transitions entre elles avec une distance et une durée nulles, car les trois retraits partagent le même emplacement dans la requête.
Pour en savoir plus, consultez la documentation de référence de ShipmentRoute
(REST, gRPC).
Optimisation simple de l'ordre des waypoints
Comme le montre cet exemple, les modèles d'optimisation des itinéraires considèrent les visites comme des propriétés des expéditions et ne disposent pas de la notion de points de passage ou d'arrêts en tant qu'entité indépendante. Toutefois, il est possible de représenter des arrêts ou des points de cheminement sous forme d'expéditions avec exactement un VisitRequest
comme point de collecte ou de livraison. Le véhicule doit toujours être associé à un costPerHour
ou un costPerKilometer
pour que l'optimiseur puisse trouver un itinéraire optimal (et non un itinéraire possible).