Questo scenario ottimizza l'ordine delle fermate assegnate a un veicolo con parametri di costo semplici. Questa è la modalità più semplice di funzionamento dell'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 località chiamata deposito.
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à della richiesta di ottimizzazione del percorso più importanti sono vehicles e shipments.
Oltre a un veicolo e alle spedizioni, la richiesta include i seguenti campi:
Polilinee
populatePolylines e populateTransitionPolylines specificano se l'ottimizzazione
del percorso deve restituire polilinee.
Il servizio codifica le polilinee utilizzando il codec polilinea di Maps JavaScript, che rappresenta
i dati binari della polilinea utilizzando caratteri ASCII stampabili. Puoi utilizzare l'utilità di codifica polilinee interattiva per visualizzare i percorsi calcolati da Ottimizzazione percorso. L'esempio in questa guida imposta populatePolylines e
populateTransitionPolylines su true, ma altre guide le impostano su false per
ridurre le dimensioni della risposta.
Per una descrizione del formato di codifica, consulta Formato dell'algoritmo di polilinea codificata.
Vincoli di tempo globali
model.globalStartTime e model.globalEndTime sono impostate su un periodo arbitrario di 24 ore. In questo modo, i timestamp dell'output sono più facili da interpretare.
Visita 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 di arrivo, ad esempio un complesso di parcheggi con un ingresso
su un lato dell'edificio e un'uscita sull'altro. In questa e nelle guide successive, si presume che i punti di partenza e di arrivo siano gli stessi.
Arrivo e partenza waypoint esistono 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 direzioni del veicolo. Per saperne di più, consulta la documentazione di riferimento
(REST, gRPC).
Vincoli nell'esempio
Questo scenario vincola l'ottimizzatore in diversi modi:
- Tutte le attività devono essere completate tra l'ora di inizio e di fine globali. In questo scenario, gli orari di inizio e di fine sono un vincolo molto blando, data la vicinanza delle spedizioni e l'ampia finestra temporale globale.
- Tutte le spedizioni devono essere completate. Questo è il comportamento predefinito quando
i costi per le penalità non sono specificati su
shipments. costPerKilometerecostPerHoursono impostati sul veicolo.
I costi sono trattati in Parametri del modello di costi.
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 orario.
Ogni Transition rappresenta il veicolo che si sposta da una posizione all'altra. Le transizioni possono verificarsi tra una coppia di punti di partenza del veicolo, una posizione di visita e il punto di arrivo del veicolo.
Per ricostruire l'itinerario completo del veicolo, è necessario combinare ShipmentRoute, visits e
transitions. La combinazione di campi in una progressione di
attività del veicolo è simile alla 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 un visits, poiché il
veicolo deve spostarsi dalla posizione di partenza alla prima visita all'inizio
del percorso e dall'ultima visita alla posizione di arrivo alla fine del
percorso. Se il veicolo non ha una posizione di partenza o di arrivo, ci sarà comunque un
transitions in più rispetto a visits perché la posizione della prima o dell'ultima visita viene
utilizzata rispettivamente come posizione di partenza o di arrivo del veicolo.
In questo esempio, i primi tre ritiri 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).
Semplice ottimizzazione dell'ordine dei waypoint
Come dimostra questo esempio, i modelli di ottimizzazione del percorso considerano le visite come proprietà delle spedizioni e non hanno una nozione di waypoint o fermate come entità indipendente. Tuttavia, è possibile rappresentare fermate o tappe intermedie come spedizioni
con esattamente un VisitRequest come ritiro o consegna. Il veicolo deve comunque
avere un costPerHour o un costPerKilometer affinché l'ottimizzatore trovi un
itinerario ottimale (anziché un itinerario fattibile).