수령 및 배달에 관한 기본적인 주문 중단 주문 최적화

이 시나리오에서는 간단한 비용 매개변수를 사용하여 차량에 할당된 정류장의 순서를 최적화합니다. 이는 가장 간단한 경로 최적화 작업 모드이며, 지정된 시간 내에 모든 정류장을 방문하도록 보장합니다.

다음 예는 차량 1대와 배송 3건이 모두 depot라는 단일 위치에서 출발하는 기본 시나리오를 보여줍니다.

요청 예 보기

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

경로 최적화 요청 필드

개요에서 언급했듯이 가장 중요한 경로 최적화 요청 속성은 vehiclesshipments입니다.

차량 및 배송 외에도 요청에는 다음 필드가 포함됩니다.

다중선

populatePolylinespopulateTransitionPolylines는 경로 최적화에서 다중선을 반환해야 하는지 여부를 지정합니다.

이 서비스는 인쇄 가능한 ASCII 문자를 사용하여 바이너리 다중선 데이터를 나타내는 지도 JS 다중선 코덱을 사용하여 다중선을 인코딩합니다. 대화형 다중선 인코더 유틸리티를 사용하여 경로 최적화에서 계산된 경로를 시각화할 수 있습니다. 이 가이드의 예시에서는 populatePolylinespopulateTransitionPolylines를 true로 설정하지만 다른 가이드에서는 응답 크기를 줄이기 위해 이를 false로 설정합니다.

인코딩 형식에 대한 설명은 인코딩된 다중선 알고리즘 형식을 참고하세요.

전 세계 시간 제한

model.globalStartTimemodel.globalEndTime는 임의의 24시간 기간으로 설정됩니다. 이렇게 하면 출력 타임스탬프를 더 쉽게 해석할 수 있습니다.

매장 방문

요청 예에서는 model.shipments[].pickups[].arrivalLocationmodel.shipments[].deliveries[].arrivalLocation만 사용합니다. 건물의 한쪽에는 입구가 있고 다른 쪽에는 출구가 있는 주차장 단지와 같이 차량이 도착하는 위치와 다른 장소에서 출발하는 상황을 위한 departureLocation 속성도 있습니다. 이 가이드와 후속 가이드에서는 도착 지점과 출발 지점이 동일한 것으로 가정합니다.

latLng 대신 도착 및 출발 waypoint도 이용할 수 있습니다. Waypoint 필드는 LatLng의 대안으로 Google 장소 ID를 사용할 수 있도록 지원하며, 차량 제목을 지정할 수도 있습니다. 자세한 내용은 참조 문서(REST, gRPC)를 확인하세요.

예시의 제약조건

이 시나리오에서는 여러 가지 방법으로 옵티마이저를 제한합니다.

  1. 모든 활동은 전역 시작 시간과 종료 시간 사이에 완료되어야 합니다. 이 시나리오에서는 배송 물품의 근접성 및 넓은 글로벌 기간을 고려할 때 시작 및 종료 시간이 매우 느슨합니다.
  2. 모든 배송이 완료되어야 합니다. 이는 shipments에 페널티 비용이 지정되지 않은 경우의 기본 동작입니다.
  3. 차량에 costPerKilometercostPerHour가 설정되어 있습니다.

비용은 비용 모델 매개변수에서 다룹니다.

경로 최적화 응답 속성

예시 요청에 대한 응답 보기

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

경로 최적화 응답에는 차량당 하나의 경로와 함께 제안된 경로를 나타내는 최상위 routes 필드가 포함됩니다. 이 가이드의 요청 예에서는 하나의 차량만 지정하므로 routes에는 하나의 ShipmentRoute 메시지가 포함됩니다.

숙박 시설 ShipmentRoute

ShipmentRoute 메시지 유형에서 가장 중요한 두 가지 속성은 visitstransitions입니다.

Visit는 요청 메시지의 VisitRequest 중 하나에서 픽업 또는 배달이 완료되었음을 나타냅니다. 방문은 특정 장소와 시간에 차량이 완료할 작업을 실질적으로 할당합니다.

Transition는 한 위치에서 다음 위치로 이동하는 차량을 나타냅니다. 전환은 한 쌍의 차량 출발지, 방문 위치 및 차량의 엔드포인트 사이에서 발생할 수 있습니다.

차량의 전체 경로를 재구성하려면 ShipmentRoutevisitstransitions를 결합해야 합니다. 차량 활동 진행에 대한 필드 조합은 다음과 같습니다.

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

ShipmentRoute에는 항상 visits보다 하나 이상의 transitions가 있습니다. 차량이 경로의 시작 위치에서 첫 번째 방문까지, 마지막 방문에서 경로 끝의 종료 위치까지 이동해야 하기 때문입니다. 차량에 출발 위치 또는 종료 위치가 없는 경우에도 첫 번째 또는 마지막 방문 위치가 각각 차량의 시작 또는 종료 위치로 사용되므로 visits보다 transitions가 하나 더 많습니다.

이 예에서 처음 세 개의 승차 방문은 요청에서 3개의 승차가 모두 동일한 위치를 공유하기 때문에 3개의 승차 방문은 거리와 시간이 0인 승차 방문 간에 전환됩니다.

자세한 내용은 ShipmentRoute 참조 문서 (REST, gRPC)를 확인하세요.

간단한 경유지 순서 최적화

이 예에서 알 수 있듯이 경로 최적화는 방문을 배송의 속성으로 모델링하며 경유지나 정류장을 독립적인 항목으로 사용하지 않습니다. 그러나 정류장 또는 경유지를 정확히 하나의 VisitRequest를 수령 또는 배달로 사용하여 배송으로 표시할 수 있습니다. 옵티마이저가 가능한 경로를 찾는 대신 최적의 경로를 찾으려면 여전히 차량에 costPerHour 또는 costPerKilometer가 할당되어야 합니다.