Features

Custom matrices

A how-to guide for implementing custom custom with vehicle routing.

This feature is only available for Platform. You can find a list of all available features here.

This how-to guide assumes you already completed the get started with vehicle routing tutorial.

Using duration matrices (either derived from haversine and speed or a road network) may not always represent the real world drive times good enough, depending on the region where you operate or the time of the day (rush hours).

Following, we will make use of two concepts in our vehicle routing engine that help you mitigate these issues:

  • Expression scaling
  • Time dependent expressions

Expression scaling can be used to make drive times between stops slower or faster by a given factor. Whilst time dependent duration expressions introduce a concept of time to an otherwise fixed drive time. This means that you can specify multiple duration matrices along with the information at what time of the day they should be used. In the exmaple below we will combine both concepts.

Example

Let's say you are generally happy with the drive times that are calculated through haversine and a constant speed. But you want to adhere to rush hours in the morning and evening.

First, create a haversine travel duration expression which will be used as a default for the whole day and scale it to represent slower driving during rush hour:

haversineExpression := nextroute.NewHaversineExpression()
defaultDurationExpression := nextroute.NewTravelDurationExpression(
	haversineExpression,
	common.NewSpeed(10, common.MetersPerSecond),
)

slowDurationExpression := nextroute.NewScaledDurationExpression(defaultDurationExpression, 2.0)
Copy

Of cource, you can use any other travel duration expressions as your default. You could, for example, use a custom duration matrix or map data.

Next, create a time dependent duration expression. We will create this expression using the default expression we created before:

timeDependentExpression, err := nextroute.NewTimeDependentDurationExpression(
	model,
	defaultDurationExpression,
)
Copy

Add the time slots when you expect the rush hour to start and end to the time dependent duration expression using the slower travel duration expression:

s1 := time.Date(2023, 1, 1, 6, 30, 0, 0, time.UTC)
e1 := time.Date(2023, 1, 1, 9, 30, 0, 0, time.UTC)

err = timeDependentExpression.SetExpression(
	s1,
	e1,
	slowDurationExpression,
)
if err != nil {
	return runSchema.Output{}, err
}

s2 := time.Date(2023, 1, 1, 17, 30, 0, 0, time.UTC)
e2 := time.Date(2023, 1, 1, 19, 30, 0, 0, time.UTC)

err = timeDependentExpression.SetExpression(
	s2,
	e2,
	slowDurationExpression,
)
if err != nil {
	return runSchema.Output{}, err
}
Copy

And finally, update the model and add the time dependent duration expression to every vehicle type:

for _, v := range model.Vehicles() {
	err := v.VehicleType().SetTravelDurationExpression(timeDependentExpression)
	if err != nil {
		return runSchema.Output{}, err
	}
}
Copy

Make sure that the times for the time slots must go hand in hand with the start and end times of your vehicles. Here is an example input.json that we created to work with the code snippets above:

{
  "defaults": {
    "vehicles": {
      "speed": 20,
      "start_time": "2023-01-01T06:00:00-06:00",
      "end_time": "2023-01-01T10:00:00-06:00"
    }
  },
  "stops": [
    {
      "id": "Fushimi Inari Taisha",
      "location": { "lon": 135.772695, "lat": 34.967146 }
    },
    {
      "id": "Kiyomizu-dera",
      "location": { "lon": 135.78506, "lat": 34.994857 }
    },
    {
      "id": "Nijō Castle",
      "location": { "lon": 135.748134, "lat": 35.014239 }
    },
    {
      "id": "Kyoto Imperial Palace",
      "location": { "lon": 135.762057, "lat": 35.025431 }
    },
    {
      "id": "Gionmachi",
      "location": { "lon": 135.775682, "lat": 35.002457 }
    },
    {
      "id": "Kinkaku-ji",
      "location": { "lon": 135.728898, "lat": 35.039705 }
    },
    {
      "id": "Arashiyama Bamboo Forest",
      "location": { "lon": 135.672009, "lat": 35.017209 }
    }
  ],
  "vehicles": [
    {
      "id": "v1",
      "start_location": { "lon": 135.672009, "lat": 35.017209 }
    },
    {
      "id": "v2",
      "start_location": { "lon": 135.728898, "lat": 35.039705 }
    }
  ]
}
Copy

To avoid hard-coding the start and end times of rush hours, you can levarage custom data in your input.json.

Page last updated

Go to on-page nav menu