How to optimize a delivery route with Route Planner API

Delivery route optimization is probably one of the well-known and frequent of optimization tasks. But this doesn't make it simple and easy to solve.

It's not enough to distribute items and calculate the shortest path for all your vehicles. Often you have to consider many requirements and limitations. For example, customers may have availability times, couriers need to take a break in the mid of the day, goods may require special conditions, and more.

We make our Route Planner API flexible and powerful to be able to describe and solve delivery optimization tasks, including very complex ones. In this article, we would like to provide you scenarios and ways to solve them to help you build a custom solution and optimize your delivery services.

Playground: Delivery and pickup jobs optimization

We've created a playground that generates a delivery optimization task for the visible on the map area. We emulate the following scenario:

Three couriers need to serve 50 locations within 3 hours. At every location, a courier needs to deliver shipments and pick up returns. Each location can have up to 3 items to deliver and up to 2 items to pick up. Items have different pickup and delivery duration times.

The shipments are stored in the Warehouse, the pickup items should be returned to the Warehouse too.

Locations, numbers of items to deliver/pickup, and duration are chosen randomly.

So the generated task has the following input:

  • 1 warehouse
  • 3 vehicles with different starting positions
  • 50 locations to serve
  • a random number of shipments

The solution shows optimized courier routes. You can show/hide separate routes and get hints for each stop by hovering it. Try to generate the task for different visible areas.

Describing the task in terms of Route Planner API

Now, let's describe the scenario described above in terms of Route Planner API:

  • agents - couriers or vehicles, that time need to be optimized;
  • mode - transportation or travel mode for agents. Could be "drive", "truck", "walk", or "bicycle";
  • shipments - describe items that need to be picked up from one location and delivered to another location;

How to describe a Warehouse or Storage?

You do not need to describe a warehouse location particularly. The shipment items have the information on where they are located initially and where they should be picked up. However, the Route Planner API have locations input parameter that help to create a reference for a location that is repeated, so you can create a reference for a warehouse location and use it instead of longitude and latitude coordinates in the shipments input.

How to add Time Windows?

The Route Planner API has several options to set time windows:

  • Set time windows for agent objects - specify when the agent is available or has working hours. In addition, you can specify breaks for each agent.
  • Set delivery and pickup time windows for shipment objects - specify when an item can be delivered/picked up.

How to transport bulky, dangerous, and other special goods?

The shipment objects can have requirements and agent object capabilities. This allows adding special requests for delivery and pickup jobs.

For example, you can add the "xxx-large" requirement to a shipment and the "xxx-large" capability to agents that can transport xxx-large items. The algorithm will assign the shipment only to agents that have the required capability.

The requirements and capabilities can have any string values - "bulky", "dangerous", "FJHZT8TRZX1DDFSDA4SAS6LL3BB".

How to assign a shipment to the exact agent?

The requirements and capabilities objects can be used to assign the exact agent to the shipment. For example, you can add "agentA" as a capability to an agent and "agentA" as a requirement to the shipment.

This also can be useful when you need to partially recalculate the results. For example, when you add a new shipment or after a manual edit.

Solve the Delivery Route Optimization task and visualize results

The Route Planner API works via HTTP POST. So it's cross-platform and can be used with any programming language. Learn more about Route Planner API specification on the API documentation page >>

We've prepared JavaScript code samples for you to help you implement a solution.

Here is a JSFiddle containing the code samples.

Build a request object

The Delivery Optimization task input is a JSON object, that contain agents and shipments objects, mode, and optionally locations:

const deliveryOptimizationInput = {
  mode: "drive",
  agents: [
    {
      start_location: [9.172755637709471, 48.77966025],
      time_windows: [[0, 10800]],
    },
    {
      start_location: [9.175432904901374, 48.7814951],
      time_windows: [[0, 10800]],
    },
    { start_location: [9.1801828, 48.7821022], time_windows: [[0, 10800]] },
  ],
  shipments: [
    {
      id: "order_1",
      pickup: { location_index: 0, duration: 120 },
      delivery: {
        location: [9.166594392161663, 48.7714641],
        duration: 120,
      },
    },
    ...{
      id: "order_76",
      pickup: { location_index: 0, duration: 120 },
      delivery: {
        location: [9.18948154795877, 48.7754963],
        duration: 300,
      },
    },
  ],
  locations: [{ id: "warehouse-0", location: [9.1780335, 48.779639] }],
};

Call Route Planner API

Make a POST call with "Content-Type=application/json" header:

fetch(`https://api.geoapify.com/v1/routeplanner?apiKey=${myAPIKey}`, {
  method: "post",
  headers: {
    "Content-Type": "application/json",
  },
  body: JSON.stringify(deliveryOptimizationInput),
})
  .then((res) => res.json())
  .then((res) => console.log(res));

Analyze results

The Route Planner API result contains an extended by properties GeoJSON.FeatureCollection object where every feature represents an agent.

The feature properties contain information that describes the agent waypoints and way legs, route time and distance, as well as delivery/pickups actions:

  • action - single operations. For example, "pickup item 0", "deliver item 22":
{
  "index": 1,
  "type": "pickup",
  "start_time": 108,
  "duration": 120,
  "shipment_index": 51,
  "shipment_id": "order_52",
  "location_index": 0,
  "location_id": "warehouse-0",
  "waypoint_index": 1
}
  • waypoints - route stops, required to perform one or multiple actions:
{
  "original_location": [
    9.165804110078732,
    48.78057285
  ],
  "location": [
    9.165804,
    48.780573
  ],
  "start_time": 2675,
  "duration": 120,
  "actions": [
    {
      "index": 21,
      "type": "pickup",
      "start_time": 2675,
      "duration": 120,
      "shipment_index": 5,
      "shipment_id": "order_6",
      "waypoint_index": 2
    }
  ],
  "prev_leg_index": 1,
  "next_leg_index": 2
}
  • legs - routes between waypoints:
{
  "time": 167,
  "distance": 1509,
  "from_waypoint_index": 1,
  "to_waypoint_index": 2,
  "steps": [
    {
      "from_index": 0,
      "to_index": 1,
      "time": 167,
      "distance": 1509
    }
  ]
}

Besides, the FeatureCollection object is enriched by the "properties" object, that contains the input parameters and may contain issues that appeared by solving the task - unassigned agents and unassigned shipments.

Visualize the results with MapLibre GL (an open-source fork of Mapbox GL)

Here is a JSFiddle that shows how to visualize the results with MapLibre GL map library:

What's next

Optimize logistic processes with Route Planner API

Start now for Free and upgrade when you need it!