本指南將說明 loadDemands
和 loadLimits
,以及這兩者之間的關聯。
如「取貨和送達時間限制」一文所述,OptimizeToursRequest
訊息 (REST、gRPC) 包含多個屬性,可針對要最佳化的問題指定限制。數個 OptimizeToursRequest
屬性代表「載入限制」。
車輛和貨運具有實體屬性,在規劃路線時必須考慮這些屬性。
- 車輛:
loadLimits
屬性代表車輛可處理的最大負載量。請參閱Vehicle
訊息 (REST、gRPC) 說明文件。 - 出貨:
loadDemands
屬性會指定特定運送作業的負載量。請參閱Shipment
訊息 (REST、gRPC) 說明文件。
只要結合這兩個限制,最佳化工具就能根據機群容量和運送需求,適當地指派貨運給車輛。
本文件其餘部分會深入探討 loadLimits
和 loadDemands
。
負載需求和限制:類型
您可以按照「類型」表達每個載入需求和限制。
您可以提供自己的載入類型組合,例如:
- 權重
- 磁碟區
- 線性測量
- 運輸項目或設備的名稱
本指南使用 weightKg
做為範例類型。
Shipment.loadDemands
和 Vehicle.loadLimits
都使用通訊協定緩衝區 map
類型,其中 string
金鑰代表載入類型。
Shipment.loadDemands
值會使用 Load
訊息 (REST、gRPC)。Load
訊息有單一 amount
屬性,代表在指定類型中完成運送所需的容量。
Vehicle.loadLimits
值使用 LoadLimit
訊息 (REST、gRPC)。LoadLimit
訊息有多個屬性,其中 maxLoad
代表指定類型的車輛最大負載量。
只有當兩者的載入類型鍵相符時,運送的 loadDemands
才會耗用獲派車輛的 loadLimits
。例如,運送商品的 loadDemands
如下:
"loadDemands": {
"weightKg": {
"amount": 50
}
}
需要 weightKg
類型中的 50 個載入單元才能完成運送。loadLimits
的車輛:
"loadLimits": {
"weightKg": {
"maxLoad": 100
}
}
可以完成運送,因為 weightKg
類型中的車輛 maxLoad
大於或等於運送 weightKg
類型中的 loadDemands
。但是,有 loadLimits
的車輛屬於:
"loadLimits": {
"equipmentRackStorage": {
"maxLoad": 10
}
}
由於 weightKg
負載限制沒有 weightKg
,因此車輛的容量無上限,因此車輛不受運送的重量需求限制。
移轉貨運和車輛之間的負載
貨運人員領取並遞送貨物時,貨物與車輛之間的 loadDemand
會轉移。您可以在特定車輛的 OptimizeToursResponse
訊息 (REST、gRPC) routes.transitions
項目中查看車輛的載入量。順序如下:
- 將運送所需的負載量定義為
loadDemand
。 - 貨物由指定車輛領取,且車輛的
vehicleLoads
會增加運輸的loadDemand
。這項移轉作業會在回應訊息中以「正面」visits.loadDemands
表示。 - 車輛交付貨物,車輛的
vehicleLoads
會減少交付商品的loadDemand
數量。這項移轉作業會在回應訊息中以「負數」visits.loadDemands
表示。
車輛的 vehicleLoads
一律不得超過路線上的指定 loadLimits
。
有載入需求和限制的完整範例
查看包含負載需求和限制的要求範例
{ "populatePolylines": false, "populateTransitionPolylines": false, "model": { "globalStartTime": "2023-01-13T16:00:00Z", "globalEndTime": "2023-01-14T16:00:00Z", "shipments": [ { "deliveries": [ { "arrivalLocation": { "latitude": 37.789456, "longitude": -122.390192 }, "duration": "250s" } ], "pickups": [ { "arrivalLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "duration": "150s" } ], "penaltyCost": 100.0, "loadDemands": { "weightKg": { "amount": 50 } } }, { "deliveries": [ { "arrivalLocation": { "latitude": 37.789116, "longitude": -122.395080 }, "duration": "250s" } ], "pickups": [ { "arrivalLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "duration": "150s" } ], "penaltyCost": 15.0, "loadDemands": { "weightKg": { "amount": 10 } } }, { "deliveries": [ { "arrivalLocation": { "latitude": 37.795242, "longitude": -122.399347 }, "duration": "250s" } ], "pickups": [ { "arrivalLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "duration": "150s" } ], "penaltyCost": 50.0, "loadDemands": { "weightKg": { "amount": 80 } } } ], "vehicles": [ { "endLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "startLocation": { "latitude": 37.794465, "longitude": -122.394839 }, "costPerHour": 40.0, "costPerKilometer": 10.0, "loadLimits": { "weightKg": { "maxLoad": 100 } } } ] } }
要求範例包含多個與載入相關的參數:
shipments[0]
的載入需求為 50weightKg
。shipments[1]
的載入需求為 10weightKg
。shipments[2]
的載入需求為 80weightKg
。vehicles[0]
的載入上限為 100weightKg
。
查看要求的回應 (包含載入需求和限制)
{ "routes": [ { "vehicleStartTime": "2023-01-13T16:00:00Z", "vehicleEndTime": "2023-01-13T16:43:27Z", "visits": [ { "isPickup": true, "startTime": "2023-01-13T16:00:00Z", "detour": "0s", "loadDemands": { "weightKg": { "amount": "50" } } }, { "shipmentIndex": 1, "isPickup": true, "startTime": "2023-01-13T16:02:30Z", "detour": "150s", "loadDemands": { "weightKg": { "amount": "10" } } }, { "startTime": "2023-01-13T16:08:55Z", "detour": "150s", "loadDemands": { "weightKg": { "amount": "-50" } } }, { "shipmentIndex": 1, "startTime": "2023-01-13T16:16:37Z", "detour": "343s", "loadDemands": { "weightKg": { "amount": "-10" } } }, { "shipmentIndex": 2, "isPickup": true, "startTime": "2023-01-13T16:27:07Z", "detour": "1627s", "loadDemands": { "weightKg": { "amount": "80" } } }, { "shipmentIndex": 2, "startTime": "2023-01-13T16:36:26Z", "detour": "0s", "loadDemands": { "weightKg": { "amount": "-80" } } } ], "transitions": [ { "travelDuration": "0s", "waitDuration": "0s", "totalDuration": "0s", "startTime": "2023-01-13T16:00:00Z", "vehicleLoads": { "weightKg": {} } }, { "travelDuration": "0s", "waitDuration": "0s", "totalDuration": "0s", "startTime": "2023-01-13T16:02:30Z", "vehicleLoads": { "weightKg": { "amount": "50" } } }, { "travelDuration": "235s", "travelDistanceMeters": 795, "waitDuration": "0s", "totalDuration": "235s", "startTime": "2023-01-13T16:05:00Z", "vehicleLoads": { "weightKg": { "amount": "60" } } }, { "travelDuration": "212s", "travelDistanceMeters": 791, "waitDuration": "0s", "totalDuration": "212s", "startTime": "2023-01-13T16:13:05Z", "vehicleLoads": { "weightKg": { "amount": "10" } } }, { "travelDuration": "380s", "travelDistanceMeters": 1190, "waitDuration": "0s", "totalDuration": "380s", "startTime": "2023-01-13T16:20:47Z", "vehicleLoads": { "weightKg": {} } }, { "travelDuration": "409s", "travelDistanceMeters": 1371, "waitDuration": "0s", "totalDuration": "409s", "startTime": "2023-01-13T16:29:37Z", "vehicleLoads": { "weightKg": { "amount": "80" } } }, { "travelDuration": "171s", "travelDistanceMeters": 665, "waitDuration": "0s", "totalDuration": "171s", "startTime": "2023-01-13T16:40:36Z", "vehicleLoads": { "weightKg": {} } } ], "metrics": { "performedShipmentCount": 3, "travelDuration": "1407s", "waitDuration": "0s", "delayDuration": "0s", "breakDuration": "0s", "visitDuration": "1200s", "totalDuration": "2607s", "travelDistanceMeters": 4812, "maxLoads": { "weightKg": { "amount": "80" } } }, "routeCosts": { "model.vehicles.cost_per_kilometer": 48.12, "model.vehicles.cost_per_hour": 28.966666666666665 }, "routeTotalCost": 77.086666666666659 } ], "metrics": { "aggregatedRouteMetrics": { "performedShipmentCount": 3, "travelDuration": "1407s", "waitDuration": "0s", "delayDuration": "0s", "breakDuration": "0s", "visitDuration": "1200s", "totalDuration": "2607s", "travelDistanceMeters": 4812, "maxLoads": { "weightKg": { "amount": "80" } } }, "usedVehicleCount": 1, "earliestVehicleStartTime": "2023-01-13T16:00:00Z", "latestVehicleEndTime": "2023-01-13T16:43:27Z", "totalCost": 77.086666666666659, "costs": { "model.vehicles.cost_per_hour": 28.966666666666665, "model.vehicles.cost_per_kilometer": 48.12 } } }
新增的載入限制會影響 visits
的順序:
shipment[0]
已抵達shipment[1]
已抵達- 已送達
shipment[0]
- 已送達
shipment[1]
shipment[2]
已抵達- 已送達
shipment[2]
此訂單說明車輛無法同時完成三件運送,因為其總 loadDemands
超過車輛的 loadLimits
。
每個 visits
項目都包含從 Visit
完成產生的車輛負載變化。正負載值代表運送載入中,負值則代表運送卸載。
每個 transitions
項目都包含 Transition
期間的車輛載入總量。舉例來說,transitions[2]
的 weightKg
負載為 60,代表 shipment[0]
和 shipment[1]
的加總載入量。
指標物件 routes[0].metrics
和 metrics.aggregatedRouteMetrics
包含 maxLoads
屬性。weightKg
類型的值為 80,代表車輛路線中將 shipments[2]
傳輸至交貨地點的部分。
軟負載限制限制
如同「取貨和送達時間限制」一文所述,負載限制具有硬性和軟性變化版本。LoadLimit
訊息的 maxLoad
屬性表示硬性限制:車輛不得攜帶超過指定類型 maxLoad
值的負載。屬性 softMaxLoad
和 costPerUnitAboveSoftMax
表示軟性限制,而每個超過 softMaxLoad
單位都會產生 costPerUnitAboveSoftMax
費用。
軟負載限制有以下幾種用途:
- 在符合成本效益的情況下
- 表示司機對特定路線上 能夠安心取貨和送達的物品數量
- 將車輛載入低於其實體容量上限,以減少佩戴及降低維護成本
硬負載限制和軟負載限制可以搭配使用。舉例來說,硬負載限制可能表示車輛可安全承載的最高重量或單一車輛可容納的物品數量上限,軟負載限制可能是因駕駛人能夠容納所有車輛的能力而計算的重量上限或數量。