GuidesAPI Reference
Guides

How to create your optimized tours

You must create a problem definition JSON file and pass it to the Tour Planning API. A problem consists of the fleet, jobs, and configuration. For more information, see Vehicle Routing Problem.

The time window and weight are defined in the shipment data, so you will formulate a capacitated vehicle routing problem with time windows in this example. For an introduction to VRP types, see Introduction.

This topic addresses the following elements:

Define your fleet

Your fleet may include a variety of vehicles, and having visibility into which vehicles are included in your fleet is critical for job planning. For example, vehicles that are equipped with onboard refrigeration are the only vehicles that should be selected to fulfill jobs containing perishable goods, while other vehicles may have to forego larger jobs due to limited capacity.

Fleet considerations include:

  • Vehicle type - Car, truck, scooter, and so on
  • Number - How many vehicles in the fleet
  • Demand and capacity - How much a vehicle can carry
  • Unique skills - Such as refrigerated trucks for carrying fresh or perishable goods
  • Cost - What is the cost per vehicle and is it a fixed cost or cost per km/mile?
  • Shift location - Start and end points for each vehicle
  • Shift times - Start and end times for each job

Create JSON file

You create your fleet definition in JSON and add it to the problem definition JSON, as outlined in the Create your fleet tours topic.

The example below outlines a fleet that consists of the following elements:

  • Ten vehicles are available of one vehicle type.
  • A shift is defined with times and start/end locations.
  • The capacity dimension used reflects the weight of the shipments added further down in the jobs.
  • The vehicle uses routing profile "car".
{
  "fleet": {
    "types": [{
      "id": "car_1",
      "profile": "car_1",
      "costs": {
        "fixed": 5.0,
        "distance": 0.007,
        "time": 0.002
      },
      "shifts": [{
        "start": {
          "time": "2023-06-30T07:00:00Z",
          "location": {
            "lat": 52.520008,
            "lng": 13.404954
          }
        },
        "end": {
          "time": "2023-06-30T17:00:00Z",
          "location": {
            "lat": 52.520008,
            "lng": 13.404954
          }
        }
      }],
      "capacity": [
        500
      ],
      "amount": 10
    }],
    "profiles": [{
      "type": "car",
      "name": "car_1"
    }]
  }
}
📘

Note

To learn how to define other routing profiles, see VRP with Heterogenous Fleet.

For more advanced routing options, see Preferred Routes with the Avoid Option.

Define your jobs

Your fleet may contain anywhere from 1 to 20,000 vehicles, and each vehicle may need to perform up to 150 deliveries and pickups per day. With a potential for three million jobs a day, it is critical to have an organized list of your fleet's jobs in order to process the jobs as efficiently as possible.

In the following example, the jobs of a fleet are processed using the Geocoding & Search v7 service to retrieve a series of coordinates outlining the deliveries and pickups for each vehicle in the fleet. The delivery time window is specified. The weight is reflected as demand.

{
  "plan": {
    "jobs": [{
      "id": "job_1",
      "tasks": {
        "deliveries": [{
          "places": [{
            "location": {
              "lat": 52.53086,
              "lng": 13.38469
            },
            "times": [[
              "2023-06-30T14:00:00Z",
              "2023-06-30T16:00:00Z"
            ]],
            "duration": 600
          }],
          "demand": [
            10
          ]
        }]
      }
    }, {
      "id": "job_2",
      "tasks": {
        "deliveries": [{
          "places": [{
            "location": {
              "lat": 52.508923,
              "lng": 13.3722855
            },
            "times": [[
              "2023-06-30T12:00:00Z",
              "2023-06-30T14:00:00Z"
            ]],
            "duration": 600
          }],
          "demand": [
            5
          ]
        }]
      }
    }]
  }
}

Create your fleet tours

Before you call the Tour Planning API, you must construct the full problem definition JSON from the fleet and job definitions outlined above. In the following example, a fleet's jobs and defined vehicles are used as input parameters to create a series of tours that provide an optimized fleet tour plan.

{
  "fleet": {
    "types": [{
      "id": "car_1",
      "profile": "car_1",
      "costs": {
        "fixed": 5.0,
        "distance": 0.007,
        "time": 0.002
      },
      "shifts": [{
        "start": {
          "time": "2023-06-30T07:00:00Z",
          "location": {
            "lat": 52.520008,
            "lng": 13.404954
          }
        },
        "end": {
          "time": "2023-06-30T17:00:00Z",
          "location": {
            "lat": 52.520008,
            "lng": 13.404954
          }
        }
      }],
      "capacity": [
        500
      ],
      "amount": 10
    }],
    "profiles": [{
      "type": "car",
      "name": "car_1"
    }]
  },
  "plan": {
    "jobs": [{
      "id": "job_1",
      "tasks": {
        "deliveries": [{
          "places": [{
            "location": {
              "lat": 52.53086,
              "lng": 13.38469
            },
            "times": [[
              "2023-06-30T14:00:00Z",
              "2023-06-30T16:00:00Z"
            ]],
            "duration": 600
          }],
          "demand": [
            10
          ]
        }]
      }
    }, {
      "id": "job_2",
      "tasks": {
        "deliveries": [{
          "places": [{
            "location": {
              "lat": 52.508923,
              "lng": 13.3722855
            },
            "times": [[
              "2023-06-30T12:00:00Z",
              "2023-06-30T14:00:00Z"
            ]],
            "duration": 600
          }],
          "demand": [
            5
          ]
        }]
      }
    }]
  }
}

Request

Save the JSON above as problem.json, and call the Tour Planning API:

curl -X POST -H "Content-Type: application/json" -d @problem.json "https://tourplanning.hereapi.com/v3/problems?apiKey={YOUR_API_KEY}"

Response

The following is an example of a response containing one tour delivering both jobs according to the defined time windows and reflecting demands:

{
  "statistic": {
    "cost": 75.311,
    "distance": 9313,
    "duration": 2560,
    "times": {
      "driving": 1360,
      "serving": 1200,
      "waiting": 0,
      "break": 0
    }
  },
  "tours": [
    {
      "vehicleId": "car_1_5",
      "typeId": "car_1",
      "stops": [
        {
          "location": {
            "lat": 52.520008,
            "lng": 13.404954
          },
          "time": {
            "arrival": "2023-06-30T07:00:00Z",
            "departure": "2023-06-30T13:35:02Z"
          },
          "load": [
            15
          ],
          "activities": [
            {
              "jobId": "departure",
              "type": "departure",
              "location": {
                "lat": 52.520008,
                "lng": 13.404954
              },
              "time": {
                "start": "2023-06-30T07:00:00Z",
                "end": "2023-06-30T13:35:02Z"
              }
            }
          ],
          "distance": 0
        },
        {
          "location": {
            "lat": 52.508923,
            "lng": 13.3722855
          },
          "time": {
            "arrival": "2023-06-30T13:42:43Z",
            "departure": "2023-06-30T13:52:43Z"
          },
          "load": [
            10
          ],
          "activities": [
            {
              "jobId": "job_2",
              "type": "delivery",
              "location": {
                "lat": 52.508923,
                "lng": 13.3722855
              },
              "time": {
                "start": "2023-06-30T13:42:43Z",
                "end": "2023-06-30T13:52:43Z"
              }
            }
          ],
          "distance": 3350
        },
        {
          "location": {
            "lat": 52.53086,
            "lng": 13.38469
          },
          "time": {
            "arrival": "2023-06-30T14:00:00Z",
            "departure": "2023-06-30T14:10:00Z"
          },
          "load": [
            0
          ],
          "activities": [
            {
              "jobId": "job_1",
              "type": "delivery",
              "location": {
                "lat": 52.53086,
                "lng": 13.38469
              },
              "time": {
                "start": "2023-06-30T14:00:00Z",
                "end": "2023-06-30T14:10:00Z"
              }
            }
          ],
          "distance": 6871
        },
        {
          "location": {
            "lat": 52.520008,
            "lng": 13.404954
          },
          "time": {
            "arrival": "2023-06-30T14:17:42Z",
            "departure": "2023-06-30T14:17:42Z"
          },
          "load": [
            0
          ],
          "activities": [
            {
              "jobId": "arrival",
              "type": "arrival",
              "location": {
                "lat": 52.520008,
                "lng": 13.404954
              },
              "time": {
                "start": "2023-06-30T14:17:42Z",
                "end": "2023-06-30T14:17:42Z"
              }
            }
          ],
          "distance": 9313
        }
      ],
      "statistic": {
        "cost": 75.311,
        "distance": 9313,
        "duration": 2560,
        "times": {
          "driving": 1360,
          "serving": 1200,
          "waiting": 0,
          "break": 0
        }
      },
      "shiftIndex": 0
    }
  ]
}