Базовая оптимизация стоп-заявок для самовывоза и доставки

Этот сценарий оптимизирует порядок остановок, назначенных транспортному средству с простыми параметрами стоимости. Это самый простой режим работы Route Optimization, который гарантирует, что все остановки будут посещены в течение указанного периода времени.

Следующий пример иллюстрирует базовый сценарий с одним транспортным средством и тремя грузами, все из которых отправляются из одного места, называемого складом .

Посмотреть пример запроса

      {
        "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
            }
          ]
        }
      }
    

Поля запроса оптимизации маршрута

Как упоминалось в Обзоре , наиболее важными свойствами запроса на оптимизацию маршрута являются vehicles и shipments .

Помимо транспортного средства и груза, запрос включает в себя следующие поля:

Полилинии

populatePolylines и populateTransitionPolylines указывают, должна ли функция оптимизации маршрута возвращать полилинии.

Служба кодирует полилинии с помощью кодека полилиний Maps JS, который представляет двоичные данные полилиний с помощью печатных символов ASCII. Вы можете использовать Interactive Polyline Encoder Utility для визуализации путей, вычисленных Route Optimization. Пример в этом руководстве устанавливает populatePolylines и populateTransitionPolylines в значение true, но другие руководства устанавливают их в значение false, чтобы уменьшить размер ответа.

Описание формата кодирования см. в разделе Формат алгоритма кодированной полилинии .

Глобальные временные ограничения

model.globalStartTime и model.globalEndTime устанавливаются на произвольный 24-часовой период. Это упрощает интерпретацию временных меток вывода.

Посетите места

В примере запроса используются только model.shipments[].pickups[].arrivalLocation и model.shipments[].deliveries[].arrivalLocation . Также есть свойство departureLocation для ситуаций, когда транспортное средство отправляется из другой точки, чем прибывает, например, парковочный комплекс со входом с одной стороны здания и выходом с другой. В этом и последующих руководствах предполагается, что точки прибытия и отправления одинаковы.

waypoint прибытия и отправления также существуют как альтернатива latLng . Поля точек Waypoint поддерживают использование идентификаторов Google Place в качестве альтернативы LatLng , а также могут указывать направления движения транспортных средств. Подробнее см. в справочной документации ( REST , gRPC ).

Ограничения в примере

Этот сценарий ограничивает оптимизатор несколькими способами:

  1. Все действия должны быть завершены между глобальным временем начала и окончания . В этом сценарии время начала и окончания является очень слабым ограничением, учитывая близость поставок и широкое глобальное временное окно.
  2. Все поставки должны быть завершены . Это поведение по умолчанию, когда штрафные расходы не указаны в shipments .
  3. Для транспортного средства устанавливаются costPerKilometer и costPerHour .

Затраты рассматриваются в параметрах модели затрат .

Свойства ответа оптимизации маршрута

См. ответ на пример запроса

    {
      "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
        }
      }
    }
    

Ответ Route Optimization включает поле routes верхнего уровня, которое представляет предлагаемые маршруты, с одним маршрутом на транспортное средство. Поскольку в примере запроса в этом руководстве указано только одно транспортное средство, routes включают одно сообщение ShipmentRoute .

Свойства ShipmentRoute

Двумя наиболее важными свойствами для типа сообщения ShipmentRoute являются visits и transitions .

Каждый Visit представляет собой завершение забора или доставки из одного из сообщений-запросов VisitRequest s. Визит фактически является назначенной работой, которая должна быть выполнена транспортным средством в определенном месте и в определенное время.

Каждый Transition представляет собой транспортное средство, движущееся из одного места в другое. Переходы могут происходить между парой начальной точки транспортного средства, местом посещения и конечной точкой транспортного средства.

Для реконструкции полного маршрута транспортного средства необходимо объединить visits и transitions ShipmentRoute . Объединение полей в прогрессию активности транспортного средства выглядит следующим образом:

request.vehicles[0].startLocation -> transitions[0] -> visits[0] ->
transitions[1] -> visits[1] -> transitions[2] -> ... -> visits[3] ->
transitions[4] -> request.vehicles[0].endLocation

ShipmentRoute всегда имеет на один transitions больше, чем visits , поскольку транспортное средство должно проехать от своего начального местоположения до своего первого посещения в начале маршрута и от своего последнего посещения до своего конечного местоположения в конце маршрута. Если у транспортного средства нет начального или конечного местоположения, все равно будет на один transitions больше, чем visits поскольку местоположение первого или последнего посещения используется как начальное или конечное местоположение транспортного средства соответственно.

В этом примере первые три посещения пункта самовывоза имеют переходы между ними с нулевым расстоянием и продолжительностью, поскольку все три пункта самовывоза имеют одно и то же местоположение в запросе.

Более подробную информацию см. в справочной документации ShipmentRoute ( REST , gRPC ).

Простая оптимизация порядка точек маршрута

Как показывает этот пример, Route Optimization моделирует посещения как свойства отправлений и не имеет понятия промежуточных точек или остановок как независимой сущности. Однако можно представить остановки или промежуточные точки как отправления с ровно одним VisitRequest как пикап или доставка. Транспортному средству по-прежнему должны быть назначены costPerHour или costPerKilometer для оптимизатора, чтобы найти оптимальный маршрут (в отличие от поиска любого возможного маршрута).