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.
Vedi 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 delle polilinee 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 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 su un 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
. costPerKilometer
ecostPerHour
sono 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 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. Al veicolo deve comunque
essere assegnato un costPerHour
o un costPerKilometer
affinché lo strumento di ottimizzazione trovi un
itinerario ottimale (anziché un itinerario fattibile).