Este cenário otimiza a ordem das paradas atribuídas a um veículo com parâmetros de custo simples. Esse é o modo mais simples de otimização do trajeto e garante que todas as paradas sejam visitadas dentro do período especificado.
O exemplo a seguir ilustra um cenário básico com um veículo e três remessas, todas partindo de um único local chamado depósito.
Confira um exemplo de solicitação
{ "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 } ] } }
Campos da solicitação do Route Optimization
Conforme mencionado na Visão geral, as propriedades mais importantes da solicitação de otimização de rota são vehicles
e shipments
.
Além de um veículo e fretes, a solicitação inclui os seguintes campos:
Polilinhas
populatePolylines
e populateTransitionPolylines
especificam se a otimização de trajeto precisa retornar polilinhas.
O serviço codifica polilinhas usando o codec de polilinha JS do Maps, que representa dados de polilinha binários usando caracteres ASCII para impressão. Você pode usar o utilitário interativo de codificação de polilinhas para ver os caminhos calculados pela otimização de rota. O exemplo neste guia define populatePolylines
e
populateTransitionPolylines
como verdadeiros, mas outros guias os definem como falsos para
reduzir o tamanho da resposta.
Consulte Formato de algoritmo de polilinhas codificadas para ver uma descrição do formato de codificação.
Restrições de tempo globais
model.globalStartTime
e model.globalEndTime
são definidos como um período arbitrário de 24 horas. Isso facilita a interpretação dos carimbos de data/hora de saída.
Visitar locais
O exemplo de solicitação usa apenas model.shipments[].pickups[].arrivalLocation
e
model.shipments[].deliveries[].arrivalLocation
. Há também uma propriedade departureLocation
para situações em que o veículo sai de um ponto diferente daquele de chegada, como um complexo de estacionamento com entrada em um lado do edifício e uma saída em outro. Neste e nos outros guias, presume-se que os pontos de chegada e partida sejam os mesmos.
Os waypoint
de chegada e partida também existem como uma alternativa a latLng
.
Os campos Waypoint
aceitam o uso de IDs de lugar do Google como alternativa a LatLng
e também podem especificar cabeçalhos de veículos. Consulte a documentação de referência
(REST, gRPC) para saber mais.
Restrições no exemplo
Este cenário restringe o otimizador de várias maneiras:
- Todas as atividades precisam ser concluídas entre os horários globais de início e término. Nesse cenário, os horários de início e término são uma restrição muito flexível, dada a proximidade das remessas e a ampla janela de tempo global.
- Todas as remessas precisam ser concluídas. Esse é o comportamento padrão quando
os custos de penalidade não são especificados em
shipments
. costPerKilometer
ecostPerHour
são definidos no veículo.
Os custos são abordados em Parâmetros do modelo de custo.
Propriedades de resposta da otimização de rotas
Veja uma resposta ao exemplo de solicitação
{ "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 } } }
A resposta da otimização de trajetos inclui um campo routes
de nível superior que representa os trajetos propostos, com um trajeto por veículo. Como o exemplo de solicitação neste guia especifica apenas um veículo, routes
inclui uma mensagem ShipmentRoute
.
ShipmentRoute
propriedades
As duas propriedades mais importantes do tipo de mensagem ShipmentRoute
são
visits
e transitions
.
Cada Visit
representa a conclusão de uma retirada ou entrega de um dos
VisitRequest
s da mensagem de solicitação. Uma visita é efetivamente atribuído a um trabalho
a ser concluído por um veículo em algum lugar e horário.
Cada Transition
representa o veículo que viaja de um local para o
próximo. As transições podem ocorrer entre um par do ponto de partida do veículo, um local de visita e o endpoint do veículo.
Para reconstruir o trajeto completo do veículo, o visits
e o transitions
do ShipmentRoute
precisam ser combinados. A combinação de campos em uma progressão de atividade do veículo tem esta aparência:
request.vehicles[0].startLocation -> transitions[0] -> visits[0] ->
transitions[1] -> visits[1] -> transitions[2] -> ... -> visits[3] ->
transitions[4] -> request.vehicles[0].endLocation
Um ShipmentRoute
sempre tem um transitions
a mais do que visits
, já que o veículo precisa se deslocar do local de partida até a primeira visita no início do trajeto e da última visita ao local final no fim do trajeto. Se o veículo não tiver um local de partida ou de término, ainda haverá um transitions
a mais do que visits
porque o local da primeira ou da última visita é usado como o local de início ou término do veículo, respectivamente.
Neste exemplo, as três primeiras visitas de retirada têm transições entre elas com distância e duração zero, porque todas as três retiradas compartilham o mesmo local na solicitação.
Consulte a documentação de referência do ShipmentRoute
(REST, gRPC) para saber mais.
Otimização simples da ordem dos waypoints
Como mostrado no exemplo, a Otimização de trajetos modela as visitas como propriedades de embarcações e não tem uma noção de waypoints ou paradas como uma entidade independente. No entanto, é possível representar paradas ou waypoints como envios
com exatamente um VisitRequest
como retirada ou entrega. O veículo ainda precisa receber um costPerHour
ou costPerKilometer
para que o otimizador encontre uma rota ideal, em vez de encontrar um trajeto viável.