Ladeanforderungen und -limits

Entwickler im Europäischen Wirtschaftsraum (EWR)

In diesem Leitfaden werden loadDemands und loadLimits sowie ihr Zusammenhang beschrieben.

Wie unter Zeitfensterbeschränkungen für Abholung und Lieferung beschrieben, enthält die OptimizeToursRequest-Nachricht (REST, gRPC) eine Reihe von Attributen, die Einschränkungen für das zu optimierende Problem angeben. Mehrere OptimizeToursRequest-Attribute stellen Ladebeschränkungen dar.

Fahrzeuge und Sendungen haben physische Eigenschaften, die bei der Planung einer Route berücksichtigt werden müssen.

  • Fahrzeuge: Das Attribut loadLimits gibt die maximale Last an, die das Fahrzeug bewältigen kann. Weitere Informationen finden Sie in der Dokumentation zur Vehicle-Nachricht (REST, gRPC).
  • Sendungen: Mit der Property loadDemands wird angegeben, wie viel Ladung eine bestimmte Sendung beansprucht. Weitere Informationen finden Sie in der Dokumentation zur Shipment-Nachricht (REST, gRPC).

Durch diese beiden Einschränkungen kann der Optimierer Sendungen Fahrzeugen auf eine Weise zuweisen, die am besten zu Ihrer Flottenkapazität und den Anforderungen an Sendungen passt.

Im weiteren Verlauf dieses Dokuments werden loadLimits und loadDemands ausführlich behandelt.

Lastanforderungen und ‑limits: Typen

Sie drücken jede Lastanforderungs- und Grenzbeschränkung als Typ aus.

Sie können eigene Lasttypen angeben, z. B.:

  • Gewicht
  • Volume
  • Lineare Messungen
  • Namen der transportierten Gegenstände oder Geräte

In diesem Leitfaden wird weightKg als Beispieltyp verwendet.

Sowohl Shipment.loadDemands als auch Vehicle.loadLimits verwenden den Protocol Buffers-Typ map mit string-Schlüsseln, die die Arten von Last darstellen.

Shipment.loadDemands-Werte verwenden die Load-Nachricht (REST, gRPC). Die Load-Nachricht hat ein einzelnes amount-Attribut, das angibt, wie viel Kapazität für den Versand des Produkts im angegebenen Typ erforderlich ist.

Vehicle.loadLimits-Werte verwenden die LoadLimit-Nachricht (REST, gRPC). Die LoadLimit-Nachricht hat mehrere Attribute. maxLoad steht für die maximale Ladekapazität des Fahrzeugs im angegebenen Typ.

Bei einer Sendung wird die loadLimits des zugewiesenen Fahrzeugs nur dann verbraucht, wenn die beiden übereinstimmende Schlüssel für den Ladungstyp haben.loadDemands Beispiel: Eine Sendung mit loadDemands von:

"loadDemands": {
  "weightKg": {
    "amount": 50
  }
}

Für den Abschluss der Sendung sind 50 Ladeeinheiten vom Typ weightKg erforderlich. Ein Fahrzeug mit loadLimits:

"loadLimits": {
  "weightKg": {
    "maxLoad": 100
  }
}

Möglicherweise kann die Sendung abgeschlossen werden, da die maxLoad des Fahrzeugs vom Typ weightKg größer oder gleich der loadDemands der Sendung vom Typ weightKg ist. Ein Fahrzeug mit loadLimits von:

"loadLimits": {
  "equipmentRackStorage": {
    "maxLoad": 10
  }
}

hat aufgrund des fehlenden weightKg-Ladelimits implizit eine unbegrenzte weightKg-Kapazität, sodass das Fahrzeug nicht durch die Gewichtsanforderungen der Sendung eingeschränkt wird.

Lastübertragung zwischen Sendungen und Fahrzeugen

Da Sendungen von Fahrzeugen abgeholt und zugestellt werden, wird die loadDemand der Sendung zwischen der Sendung und dem Fahrzeug übertragen. Die Ladungen des Fahrzeugs finden Sie im Eintrag routes.transitions der OptimizeToursResponse-Nachricht (REST, gRPC) für ein bestimmtes Fahrzeug. Die Reihenfolge ist wie folgt:

  1. Die erforderliche Ladekapazität wird für die Sendung als loadDemand definiert.
  2. Die Sendung wird vom zugewiesenen Fahrzeug abgeholt und die vehicleLoads des Fahrzeugs erhöht sich um die loadDemand der Sendung. Diese Übertragung wird in der Antwortnachricht durch positive visits.loadDemands dargestellt.
  3. Das Fahrzeug liefert die Sendung aus und die vehicleLoads des Fahrzeugs verringert sich um die loadDemand der ausgelieferten Sendung. Diese Übertragung wird in der Antwortnachricht durch negative visits.loadDemands dargestellt.

Die vehicleLoads eines Fahrzeugs darf an keinem Punkt auf der Route die angegebene loadLimits überschreiten.

Vollständiges Beispiel mit Lastanforderungen und ‑limits

Beispielanfrage mit Lastanforderungen und ‑limits

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

Die Beispielanfrage enthält mehrere lastbezogene Parameter:

  • shipments[0] hat einen Lastbedarf von 50 weightKg.
  • shipments[1] hat einen Lastbedarf von 10 weightKg.
  • shipments[2] hat einen Lastbedarf von 80 weightKg.
  • vehicles[0] hat ein Ladelimit von 100 weightKg.

Eine Antwort auf die Anfrage mit Lastanforderungen und ‑limits ansehen

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

Die hinzugefügten Ladebeschränkungen wirken sich auf die Reihenfolge von visits aus:

  1. shipment[0] wird abgeholt
  2. shipment[1] wird abgeholt
  3. shipment[0] wird ausgeliefert
  4. shipment[1] wird ausgeliefert
  5. shipment[2] wird abgeholt
  6. shipment[2] wird ausgeliefert

Diese Bestellung zeigt, dass drei Sendungen nicht gleichzeitig vom Fahrzeug abgeschlossen werden können, da ihr Gesamt-loadDemands die loadLimits des Fahrzeugs überschreitet.

Jeder visits-Eintrag enthält die Änderung der Fahrzeugladung, die sich aus dem Abschluss von Visit ergibt. Positive Werte für die Ladung stehen für das Beladen von Sendungen, negative Werte für das Entladen von Sendungen.

Jeder transitions-Eintrag enthält die Gesamtlast des Fahrzeugs während des Transition. transitions[2] hat beispielsweise eine weightKg-Last von 60, die die kombinierten Lasten von shipment[0] und shipment[1] darstellt.

Die Messwertobjekte routes[0].metrics und metrics.aggregatedRouteMetrics enthalten das Attribut maxLoads. Der Wert für den Typ weightKg ist 80. Er steht für den Teil der Fahrzeugroute, auf dem shipments[2] zum Lieferort transportiert wurde.

Einschränkungen für weiche Ladelimits

Wie bei den Zeitfenstern, die unter Einschränkungen für Zeitfenster für Abholung und Lieferung beschrieben werden, gibt es für Ladegrenzen-Einschränkungen harte und weiche Varianten. Die maxLoad-Eigenschaft der LoadLimit-Nachricht gibt eine harte Einschränkung an: Das Fahrzeug darf niemals eine Last transportieren, die den maxLoad-Wert für den angegebenen Typ überschreitet. Die Properties softMaxLoad und costPerUnitAboveSoftMax stellen eine weiche Einschränkung dar. Für jede Einheit, die softMaxLoad überschreitet, fallen Kosten in Höhe von costPerUnitAboveSoftMax an.

Einschränkungen für weiche Lastlimits haben mehrere Anwendungsbereiche, z. B.:

  • Sendungen auf mehr Fahrzeuge als die erforderliche Mindestanzahl verteilen, wenn dies kosteneffizient ist
  • die Präferenz des Fahrers für die Anzahl der Artikel, die er auf einer bestimmten Route bequem abholen und liefern kann
  • Fahrzeuge unter ihrer maximalen physischen Kapazität beladen, um den Verschleiß zu begrenzen und die Wartungskosten zu senken

Einschränkungen für harte und weiche Lastlimits können zusammen verwendet werden. Ein hartes Ladungsgewichtslimit kann beispielsweise das maximale Gewicht der Ladung angeben, die ein Fahrzeug sicher transportieren kann, oder die maximale Anzahl von Artikeln, die gleichzeitig in ein Fahrzeug passen. Ein weiches Ladungsgewichtslimit kann das maximale Gewicht oder die maximale Anzahl von Artikeln angeben, die den Fahrer überfordern würden, alles in das Fahrzeug zu passen.