Questo scenario ottimizza l'ordine delle fermate assegnate a un veicolo con parametri di costo semplici. Questa è la modalità più semplice di operazione di ottimizzazione del percorso e garantisce che tutte le fermate vengano visitate entro il periodo di tempo specificato.
L'esempio seguente illustra uno scenario di base con un veicolo e tre spedizioni, tutte provenienti da un'unica sede chiamata depot.
Visualizza un esempio di richiesta
{ "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 } ] } }
Campi della richiesta di ottimizzazione del percorso
Come indicato nella Panoramica, le proprietà più importanti della richiesta di ottimizzazione del percorso sono vehicles
e shipments
.
Oltre a un veicolo e alle spedizioni, la richiesta include i seguenti campi:
Polilinee
populatePolylines
e populateTransitionPolylines
specificano se ottimizzazione percorso deve restituire polilinee.
Il servizio codifica le polilinee utilizzando il codec Maps JS, che rappresenta i dati delle polilinee binarie utilizzando caratteri ASCII stampabili. Puoi utilizzare la utilità Interactive Polyline Encoder per visualizzare i percorsi calcolati dall'ottimizzazione del percorso. L'esempio in questa guida imposta populatePolylines
e
populateTransitionPolylines
su true, ma altre guide li impostano su false per
ridurre le dimensioni della risposta.
Per una descrizione del formato di codifica, consulta Formato dell'algoritmo Polyline codificato.
Limitazioni di tempo globali
model.globalStartTime
e model.globalEndTime
sono impostati su un periodo arbitrario di 24 ore. In questo modo, i timestamp di output sono più facili da interpretare.
Visitare le sedi
La richiesta di esempio utilizza solo model.shipments[].pickups[].arrivalLocation
e
model.shipments[].deliveries[].arrivalLocation
. Esiste anche una proprietà departureLocation
per le situazioni in cui il veicolo parte da un punto diverso da quello in cui arriva, ad esempio un complesso di parcheggi con un ingresso su un lato dell'edificio e un'uscita su un altro. In questa guida e nelle successive, si presume che i punti di arrivo e di partenza siano gli stessi.
Le opzioni di arrivo e partenza waypoint
sono disponibili anche come alternativa a latLng
.
I campi Waypoint
supportano l'utilizzo degli ID luogo di Google come alternativa a LatLng
e possono anche specificare le tracce del veicolo. Per ulteriori dettagli, consulta la documentazione di riferimento
(REST, gRPC).
Vincoli nell'esempio
Questo scenario limita l'ottimizzatore in diversi modi:
- Tutte le attività devono essere completate tra l'ora di inizio e quella di fine globali. In questo scenario, le ore di inizio e di fine sono un vincolo molto lasco, data la vicinanza delle spedizioni e l'ampia finestra temporale globale.
- Tutte le spedizioni devono essere completate. Questo è il comportamento predefinito quando i costi delle penalità non sono specificati in
shipments
. costPerKilometer
ecostPerHour
sono impostati sul veicolo.
I costi sono trattati in Parametri del modello di costo.
Proprietà della risposta di Route Optimization
Visualizza una risposta alla richiesta di esempio
{ "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 risposta di ottimizzazione del percorso include un campo routes
di primo livello che rappresenta i percorsi proposti, con un percorso per veicolo. Poiché la richiesta di esempio in questa guida specifica un solo veicolo, routes
include un messaggio ShipmentRoute
.
ShipmentRoute
strutture
Le due proprietà più importanti per il tipo di messaggio ShipmentRoute
sono
visits
e transitions
.
Ogni Visit
rappresenta il completamento di un ritiro o di una consegna da uno dei VisitRequest
del messaggio di richiesta. Una visita è un'attività assegnata a un veicolo da completare in un determinato luogo e momento.
Ogni Transition
rappresenta il veicolo che si sposta da una località all'altra. Le transizioni possono avvenire tra una coppia di punti di partenza del veicolo, una località di visita e il punto di arrivo del veicolo.
Per ricostruire il percorso completo del veicolo, è necessario combinare visits
e
transitions
di ShipmentRoute
. La combinazione di campi in una progressione di attività del veicolo è la seguente:
request.vehicles[0].startLocation -> transitions[0] -> visits[0] ->
transitions[1] -> visits[1] -> transitions[2] -> ... -> visits[3] ->
transitions[4] -> request.vehicles[0].endLocation
Un ShipmentRoute
ha sempre un transitions
in più rispetto a visits
, poiché il veicolo deve viaggiare dalla posizione di partenza alla prima visita all'inizio del percorso e dall'ultima visita alla posizione di destinazione alla fine del percorso. Se al veicolo manca una posizione di partenza o di arrivo, ce ne sarà comunque una
in più rispetto a transitions
perché la posizione della prima o dell'ultima visita viene
utilizzata rispettivamente come posizione di partenza o di arrivo del veicolo.visits
In questo esempio, le prime tre visite di ritiro hanno transizioni tra loro con distanza e durata pari a zero perché tutti e tre i ritiri condividono la stessa posizione nella richiesta.
Per ulteriori dettagli, consulta la documentazione di riferimento di ShipmentRoute
(REST, gRPC).
Ottimizzazione semplice dell'ordine dei punti di passaggio
Come dimostra questo esempio, i modelli di ottimizzazione del percorso modellano le visite come proprietà delle spedizioni e non hanno una nozione di waypoint o fermate come entità indipendente. Tuttavia, è possibile rappresentare fermate o waypoint come spedizioni con esattamente un VisitRequest
come ritiro o consegna. Al veicolo deve comunque essere assegnato un costPerHour
o un costPerKilometer
affinché l'ottimizzatore trovi un percorso ottimale (anziché un percorso fattibile).