Questo scenario ottimizza l'ordine delle fermate assegnate a un veicolo con semplici parametri di costo. È la modalità più semplice 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, tutti provenienti da un'unica sede denominata depot.
Visualizza una richiesta di esempio
{ "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 per la richiesta di ottimizzazione del percorso
Come menzionato nella Panoramica, le proprietà più importanti per le richieste di ottimizzazione delle route
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
della route deve restituire le polilinee.
Il servizio codifica le polilinee utilizzando il codec polilinea JS di Maps, che rappresenta i dati delle polilinee binarie utilizzando caratteri ASCII stampabili. Puoi utilizzare
l'Utilità encoder Polyline interattiva per visualizzare i percorsi calcolati
dall'ottimizzazione delle route. L'esempio in questa guida imposta populatePolylines
e
populateTransitionPolylines
su true, ma altre guide le impostano su false per
ridurre le dimensioni della risposta.
Consulta Formato dell'algoritmo polilinea codificato per una descrizione del formato di codifica.
Limiti di tempo globali
model.globalStartTime
e model.globalEndTime
sono impostati su un periodo di 24 ore arbitrario. Ciò semplifica l'interpretazione dei timestamp di output.
Visita le sedi
La richiesta di esempio utilizza solo model.shipments[].pickups[].arrivalLocation
e
model.shipments[].deliveries[].arrivalLocation
. Esiste anche una proprietà departureLocation
per situazioni in cui il veicolo parte da un punto diverso da quello di arrivo, ad esempio un complesso di parcheggi con un ingresso da un lato dell'edificio e un'uscita su un altro. In questa guida e in quelle successive, si presume che i punti di arrivo e di partenza siano uguali.
Il giorno di arrivo e di partenza waypoint
sono disponibili anche in alternativa a latLng
.
I campi Waypoint
supportano l'utilizzo di ID luogo di Google in alternativa a LatLng
e possono anche specificare intestazioni di veicoli. Per ulteriori dettagli, 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 l'ora di fine globali. In questo scenario, gli orari di inizio e di fine sono un vincolo molto rigido data la vicinanza delle spedizioni e l'ampia finestra temporale globale.
- Tutte le spedizioni devono essere completate. Questo è il comportamento predefinito quando i costi di penalità non sono specificati in
shipments
. costPerKilometer
ecostPerHour
sono impostati sul veicolo.
I costi sono indicati in Parametri del modello di costo.
Proprietà della risposta di ottimizzazione del percorso
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
.
Ciascun Visit
rappresenta il completamento di un ritiro o una consegna da uno dei VisitRequest
dei messaggi di richiesta. Una visita è un lavoro che deve
essere completato da un veicolo in un luogo e in un orario specifici.
Ciascun Transition
rappresenta il veicolo che si sposta da una località all'altra. Le transizioni possono avvenire tra una coppia del punto di partenza del veicolo, una visita
e il punto finale del veicolo.
Per ricostruire l'itinerario completo del veicolo, è necessario combinare visits
e transitions
di ShipmentRoute
. La combinazione di campi in un'avanzamento
dell'attività dei veicoli è 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 uno transitions
in più rispetto a visits
, perché il veicolo deve viaggiare dalla posizione di partenza alla prima visita all'inizio del percorso e dalla sua ultima visita alla sua posizione di fine alla fine del percorso. Se il veicolo non ha una posizione di partenza o di arrivo, ci sarà comunque uno
più transitions
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, le prime tre visite a ritiro presentano transizioni tra di loro con distanza e durata pari a zero, perché tutti e tre i ritiri condividono la stessa località nella richiesta.
Per ulteriori dettagli, consulta la documentazione di riferimento di ShipmentRoute
(REST, gRPC).
Ottimizzazione dell'ordine dei waypoint semplice
Come dimostra questo esempio, l'ottimizzazione del percorso modella le visite come proprietà delle spedizioni e non ha un concetto di tappe o fermate come entità indipendente. Tuttavia, è possibile rappresentare le fermate o le tappe 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é qualsiasi percorso fattibile).