Vehicle properties
- Vehicle or courier ID
- Transportation method
- Vehicle or courier capacity
- Minimum order weight for a vehicle
- Vehicle properties
- Load handling time at depot
- Start of a loaded vehicle
- Vehicle started not from the depot
- Making stops at multiple depots
- Return to any location at the end of the route
- Start or end of the route as close to the depot as possible
- Multiple courier runs per day
- Limit the number of stops per shift
- Maximum shift duration
- Maximum mileage per shift
- Limit the mileage and number of stops per run
- Route density
- Vehicle or courier cost
- Advanced cost settings
- Calculation of the courier's payout
- Vehicle tags
- Order incompatibility
- Geofences
- Vehicle or courier shifts
- Courier working mode
- Planned route
- Fixed part of the route
- Adjusting the vehicle's moving time
- Adjusting handling time
- Prompt delivery
- Trailers
Orders in RouteQ can be delivered by regular vehicles or couriers traveling on foot or by public transit. Vehicle and courier have a common set of properties.
The vehicles
field is used in the request to determine the vehicle or courier.
Vehicle or courier ID
Each vehicle or courier must have a unique numeric or string ID set in the id
field. IDs must be unique within a single service request. They will be used as the usernames of the couriers when exporting data to Track & Trace.
You can also specify the vehicle's or the courier's numeric or string ID from your tracking system in the ref
field and the courier's mobile phone number in the phone
field so that they can be contacted from Track & Trace.
Transportation method
When building routes, it is assumed by default that a courier uses a passenger car for delivery (load capacity less than 2.5 tons). To specify delivery on foot, by truck, or by public transit, use the vehicle.routing_mode
parameter. If all couriers have the same delivery method, you can use the routing option options.routing_mode
.
Note
The vehicle.routing_mode
parameter has a higher priority than the options.routing_mode
parameter.
Possible values:
-
driving
: The default method, routing for vehicles whose load capacity is less than 2.5 tons. -
truck
: Routing for trucks whose default load capacity starts at 2.5 tons. You can specify additional parameters in vehicle properties. When planning for this transportation method, the algorithm considers road signs with cargo vehicle restrictions and the Moscow cargo frame restrictions. -
walking
: A pedestrian route. The route uses only roads that can be walked. -
transit
: A route that includes traveling by public transit and walking from the public transit stop to the delivery location. The real public transit timetable isn't taken into account, but it's considered that:-
Getting to the destination by public transit is possible.
-
The courier arrives at the stop and immediately gets into the transport.
-
For couriers who use bicycles or scooters, specify the transportation method as on foot (routing_mode
= walking
) and use the speed adjustment factor (travel_time_multiplier
). We recommend personalizing adjustment factors for each individual courier. For example, using the Plan/Fact report, you can compare the actual delivery time for a courier on a bicycle or scooter with the planned walking time.
Example 1
The example below uses the transit
transportation method for all couriers. As a result, couriers deliver orders using public transit with optimal order allocation.
API request (JSON) ⋅ API response ⋅ View on map
Note
For the built routes, the mileage is specified only for the distances that couriers walk. The distances traveled by public transit are taken into account for optimization purposes, but are not counted in metrics.
Example 2
The example below uses the transit
transportation method for one courier and the driving
method for another courier. Orders are distributed among couriers so that the vehicle delivers to locations situated further away from public transit stops or from each other.
API request (JSON) ⋅ API response ⋅ View on map
Vehicle or courier capacity
In RouteQ you can define the vehicle capacity in terms of the maximum weight or cargo the vehicle/courier can transport over a single route.
To determine the vehicle or courier carrying capacity, use the capacity
field (you can specify just one option):
-
capacity.units
: Number of units (pallets, boxes, kegs). -
capacity.weight_kg
: Weight in kilograms or bulk weight. -
capacity.volume
: The volume, which is measured in cubic meters and set as the product of dimensions:-
capacity.volume.width_m
: Width in meters. -
capacity.volume.depth_m
: Depth in meters. -
capacity.volume.height_m
: Height in meters.
If values are unknown, use
capacity.volume_cbm
. -
-
capacity.volume_cbm
: Volume in cubic meters.
If the vehicle has both size and volume specified, capacity.volume
defines the dimensions and capacity.volume_cbm
defines the carrying capacity.
For more information about weight determination, see Weight and volume.
Note
Please note that if the order weight is set in kilograms or as a volume weight, the vehicle capacity must be set in the same units. Similarly, if the order weight is set as the number of units, the vehicle capacity must specify the maximum number of units in each vehicle.
Additionally, you can set the maximum load of a vehicle as a percentage of the specified load capacity. To do this, use the limits
request field:
-
limits.volume_perc
: A percentage of the value specified incapacity.volume.width_m
*capacity.volume.depth_m
*capacity.volume.height_m
. -
limits.weight_perc
: A percentage of the value specified incapacity.weight_kg
. -
limits.volume_perc
: A percentage of the value specified incapacity.volume
.
To indicate that overload is allowed relative to a given value, specify a value greater than 100. To leave spare load capacity, for example, to allow for the inaccurate estimation of order dimensions, specify a value less than 100. For example, a value of 110 allows for 10% overload and a value of 90 allows for a maximum load of 90% of the specified load capacity.
The vehicle capacity (based on the limits
) is a hard restriction that won't be violated. Note that, when calculating the vehicle load, the system takes into account the orders for pickup and delivery. For more information, see Pickup and delivery.
Note
You can use the vehicle capacity to indirectly manage the number of orders that should be added to it. For example, if you set the volume per order to 1 unit (regardless of the actual size of the order) and the vehicle capacity to 10 units, then each vehicle will be assigned no more than 10 orders.
Example
There are two vehicles with a load capacity of 1.5 tons (Vehicle 1) and 3 tons (Vehicle 2) and three orders for delivery with a weight of 1 ton, 1.2 tons, and 1.4 tons, respectively.
When optimizing routes, the 1.2-ton order is placed in Vehicle 1 and the 1-ton and 1.4-ton orders are placed in Vehicle 2.
API request (JSON) ⋅ API response ⋅ View on map
Custom capacity units
A custom unit restricts the capacity of the vehicle according to the custom unit of measurement specified for orders.
You can set several custom capacity units for vehicles. Each of them should have its own ordinal number N
(numbering starts from 0). Each unit is described by two parameters:
-
capacity.custom.N.name
: Name of the custom unit. -
capacity.custom.N.size
: Vehicle capacity in custom units.
By default, the capacity is not limited by the parameter capacity.custom.N.size
.
Alert
The name of the custom capacity unit for the vehicle should match the one given for the order.
If custom capacity units are specified for orders or explicitly specified for some vehicles, but not for others, then the vehicles with unspecified units will be taken to have unlimited carrying capacity in custom units.
Example of filling in Excel file sheets for a custom price
parameter (order cost):
Order cost
|
|
|
100 |
Total order cost
|
|
|
1000 |
Example 1.1
4 vehicles deliver 16 orders. Weight, volume, and load capacity (number of units) are specified for the vehicles. Custom units have been set for orders (to limit the cost, location.shipment_size.custom.0
) and for the vehicles (to limit the total cost of transported orders, vehicle.capacity.custom.0
).
There are 2 vehicles transporting 1 order each. However, their weight, volume, and number of units is small, because the order cost is approaching the vehicle's limit.
API request (JSON) ⋅ API response ⋅ View on map
Example 1.2
The same as example 1.1, but the maximum number of orders that the vehicle can transport is also specified. The restriction is set using the location.shipment_size.custom.1
and vehicle.capacity.custom.1
parameters. Each vehicle can now carry no more than 5 orders.
The number of orders in three vehicles has changed. Now one vehicle carries one order, and orders cannot be added due to the total cost limit. For the rest, maximum utilization by total cost in each vehicle was achieved, and it was possible to maintain the limit on the number of orders.
API request (JSON) ⋅ API response ⋅ View on map
Example 2
Two vehicles deliver 20 orders. Orders have different lengths. This property is described by two custom units:
- Unit
Length5
(location.shipment_size.custom.0
) is 1 for orders with a length of 5 meters (these are orders from 10 to 15) and 0 for all other orders. - Unit
Length6
(location.shipment_size.custom.1
) is 1 for orders with a length of 6 meters (these are orders from 16 to 20) and 0 for all other orders. Orders from 1 to 9 have a length of less than 5 meters. For them, both custom unitsLength5
andLength6
are 0.
Vehicles have the same load capacity, but different body lengths:
- Vehicle6 has a body length of 6 meters and can transport any orders. For this vehicle,
vehicle.capacity.custom.0
andvehicle.capacity.custom.1
are both 10 (taking into account the weight of the orders and the vehicle's load capacity). - Vehicle5 has a body length of 5 meters and can't transport orders with a length of 6 meters. For this vehicle,
vehicle.capacity.custom.0
= 10, whilevehicle.capacity.custom.1
= 0.
In the planned solution, Vehicle5 transports orders that are 5 meters long or less, while Vehicle6 transports orders that are 6 meters long, 5 meters long, or less than 5 meters long.
API request (JSON) ⋅ API response ⋅ View on map
Minimum order weight for a vehicle
To prevent a heavy truck from carrying a single small order across town, use the min_stop_weight
parameter. Using this parameter, you can specify the minimum total weight that a vehicle will deliver to a single location. This is relevant when planning freight transportation by vehicles of different capacity.
The restriction is soft: the algorithm may violate it. Penalties are set in the fields:
-
penalty.min_stop_weight.fixed
: A penalty for violating the minimum total weight for all orders in a single location (1000 by default). -
penalty.min_stop_weight.kg
: A penalty for each kilogram that the total order weight delivered to a single location (50 by default) is short.
For more information about using vehicles with different capacity, see Transport with different load capacities.
Example 1
Two vehicles with capacities of 1500 and 10,000 kg are delivering orders weighing 100, 500, 900, and 9000 kg. The large truck gets both light and heavy orders.
API request (JSON) ⋅ API response ⋅ View on map
Example 2
For a vehicle with a capacity of 10,000 kg, the specified value of min_stop_weight
is 1000. As a result, the larger vehicle only gets the order weighing 9000 kg.
API request (JSON) ⋅ API response ⋅ View on map
Vehicle properties
You can specify vehicle properties in the vehicle.specs
field. The following parameters can be specified:
-
width
: Vehicle width in meters. -
height
: Vehicle height in meters. -
length
: Vehicle length in meters. -
max_weight
: Maximum vehicle weight in tons. -
max_weight_kg
: Maximum vehicle weight in kilograms (rounded up to the ton when addressing the planning task).
Note
If you set the vehicle.specs.max_weight
and vehicle.specs.max_weight_kg
parameters simultaneously in the planning task, the solution will use vehicle.specs.max_weight
.
The minimum value is 0 for all the listed properties.
Alert
You can specify these parameters only for trucks (routing_mode
= truck
).
Load handling time at depot
The loading or unloading time at the depot may depend both on orders and vehicle properties (for example, dimensions or equipment).
To specify the amount of additional time required for loading at the depot, use the vehicle.depot_extra_service_duration_s
parameter. The time is set in seconds.
Note
The time assigned in the vehicle.depot_extra_service_duration_s
parameter is summed up with the depot handling time.
Example
2 vehicles with the same load capacity are delivering 13 large orders. The handling time at the depot depot.service_duration_s
is 5 minutes (300 seconds). Additional time is set for loading orders into a vehicle at the depot vehicle.depot_extra_service_duration_s
: 30 minutes (1800 seconds). As a result of planning, each vehicle will spend 35 minutes at the depot before starting their routes.
API request (JSON) ⋅ API response ⋅ View on map
Start of a loaded vehicle
If a vehicle is loaded in advance and there is no need to spend time loading it at the beginning of the shift, use the starts_loaded
= true
vehicle property. The handling time before the first run will then be ignored for this vehicle during route planning.
Example
Two vehicles deliver orders: the first one is loaded in advance, and the second one has to be loaded at the start of the shift. The handling time depot.service_duration_s
is 10 minutes (600 seconds).
As a result of planning, the first vehicle will immediately start the route, and the second vehicle will spend 10 minutes at the depot before departing.
API request (JSON) ⋅ API response ⋅ View on map
Vehicle started not from the depot
By default, vehicles and couriers start from the depot. However, sometimes they need to start the route from another point (for example, from their home or parking spot). That's a usual task in the case of sales representatives, service engineers, and other specialists who don't deliver goods, but provide services.
You can implement this requirement using the property vehicle.start_at
. In this case, the courier or vehicle will start their route from the specified point with the type garage
, rather than from the depot.
Visiting the depot before the start of the working day
At the beginning of the working day, couriers may need to visit the depot to get their orders there. Use the property vehicle.visit_depot_at_start
to enable this. If you specify true
, the courier or the vehicle must visit the depot before starting the delivery (this is default behavior). Otherwise, they can immediately start delivering orders. For more information, see Start or end of the route at an arbitrary point.
If couriers start from a garage
location, but they need to pick up some orders at the depot, enable the option Can visit the depot at the beginning of the route (can_visit_depot_at_start
in the API, false
by default). This option only works for couriers that have the parameter visit_depot_at_start
= false
. For orders that need to be picked up from a depot, specify one of the following parameters:
— depot_id
to link the order to a depot.
— depot_ready_time
, the time when the order is ready at the depot.
— depot_expiring_time
, the deadline for picking up the order from the depot.
You can also implicitly allow couriers to visit the depot at the beginning of the route with the can_visit_depot_at_start
option disabled by explicitly specifying the depot in planned_route
, fixed part of the route, or during additional planning.
Example 1
Three vehicles deliver orders: The first one starts the delivery from the depot. The second one starts and ends the route without visiting the depot. The starting point for the courier is order 6, which has the garage
type. The third one starts the route not from the depot, but from order 4 (the garage
type), but must visit the depot before starting the delivery.
API request (JSON) ⋅ API response ⋅ View on map
Example 2
Three vehicles deliver orders: The first one starts the delivery from the depot. The second and the third vehicles start and end the route without visiting the depot. Orders 1 and 7 have the pickup
type, and the algorithm selects them as the first route points.
Three separate routes are planned in the solution because of the orders' priorities.
API request (JSON) ⋅ API response ⋅ View on map
Example 3
Two vehicles deliver orders (visit_depot_at_start
= false
and can_visit_depot_at_start
= true
). The first one starts from a garage
location and visits the depot to pick up order 1 at the beginning of the route. The second vehicle's route doesn't include a visit to the depot, it goes straight to the delivery.
API request (JSON) ⋅ API response ⋅ View on map
Making stops at multiple depots
Couriers can stop at multiple depots along their routes. This is helpful when items are stored in different depots or when the route needs to end at a specific depot.
Specify depots using one of these methods:
- On the Vehicles sheet in the Depots that the courier can visit field (
vehicle.depot_id
in the API), you can specify the depots that the courier is allowed to visit while following the route. They have a higher priority, so the algorithm can assign them as start, intermediate, or end depots. - In the fields:
- Depots to start from (
vehicle.starting_depot_id
in the API): The depots where the courier starts their route. - Depots for additional loading (
vehicle.middle_depot_id
in the API): The intermediate depots to pick up additional orders along the route. - Depots to end the route at (
vehicle.ending_depot_id
in the API): The depots where the courier completes the route.
Note
The depot_id
field has a higher priority than starting_depot_id
, middle_depot_id
, and ending_depot_id
. If a depot is specified in the depot_id
field, values in other depot fields are ignored.
Example 1
There are 9 orders in the planning task. Three depots are specified on the Vehicles sheet in the depot_id
field: Depot 1, Depot 2, and Depot 3. The courier is allowed to stop at multiple depots along the route.
As a result of planning, the courier:
- Starts the route from Depot 2, because it is located next to the first order location.
- Ends the route at Depot 3, because the last order location is next to it.
API request (JSON) ⋅ API response ⋅ View on map
Example 2
The courier must deliver 9 orders. Planning involves 2 depots:
- Depot 2: a start (
starting_depot_id
=2
) and end (ending_depot_id
=2
) depot. - Depot 1: an intermediate depot (
middle_depot_id
=1
).
As a result of planning, the courier starts the route at Depot 2 and delivers 4 orders. Then the courier stops at Depot 1 for reloading, delivers the remaining orders, and ends the route at Depot 2.
API request (JSON) ⋅ API response ⋅ View on map
Example 3
The courier must deliver 9 orders. Planning involves 3 depots:
- Depot 1: a start depot (
starting_depot_id
=1
). - Depot 2: an intermediate depot (
middle_depot_id
=2
). - Depot 3: an end depot (
ending_depot_id
=3
).
The courier is allowed to visit the intermediate depot for reloading at the beginning of the route only (vehicle.depots_only_at_run_beginning
= true
). As a result of planning, the courier starts from Depot 1, then stops at Depot 2 for reloading, and starts delivering orders. Ends the route at Depot 3.
API request (JSON) ⋅ API response ⋅ View on map
Start from one of several depots
To allow the courier to start from one of multiple depots, list them in the Depots that the courier can visit (vehicle.depot_id
in the API) or Depots to start from field (vehicle.starting_depot_id
in the API). If there are several depots, the algorithm will choose the optimal depot to start from. If the fields depot_id
and starting_depot_id
are not entered for a courier, they start from the first depot in the depots
list.
Alert
On the Vehicles sheet in the Depots that the courier can visit (depot_id
) and Depots for loading (starting_depot_id
) fields, you can't specify both regular and cross-docking depots at once. In a single route, a courier may only visit either regular depots or cross docks.
If you use the delivery from one of several depots functionality, a courier will be able to pick up orders from any depot they can visit.
For the courier, you can also set the parameters Allowed to visit multiple depots in one route (vehicle.allow_different_depots_in_route
in the API) and Maximum number of depots for additional loading in one route (vehicle.max_middle_depots
in the API). For more information, see Choosing the optimal depot to start from.
Additional loading at an intermediate depot
For the courier to be able to visit additional depots for reloading along the route, set the Allowed to visit multiple depots in one route (vehicle.allow_different_depots_in_route
in the API) parameter to true
. Specify depots for reloading in the field Depots that the courier can visit (vehicle.depot_id
in the API) or Intermediate depots (vehicle.middle_depot_id
in the API). If there are orders in several depots, the algorithm will select the optimal depot for reloading.
Alert
On the Vehicles sheet in the Depots that the courier can visit (depot_id
) and Intermediate depots (middle_depot_id
) fields, you can't specify both regular and cross-docking depots at once. On a single route, a courier may only visit either regular depots or cross docks.
If the courier can stop at intermediate depots for additional loading at the beginning of the route only (before completing the first order), set the vehicle.depots_only_at_run_beginning
parameter to true
(by default, it's set to false
).
For the courier, you can also set the Maximum number of depots for additional loading in one route parameter (vehicle.max_middle_depots
in the API). For more information, see Visiting an additional depot.
Returning to a depot at the end of the route or run
By default, the courier completes the route at the depot where they started. To allow the courier to stop at multiple depots along the route, set the Allowed to visit multiple depots in one route parameter (vehicle.allow_different_depots_in_route
in the API) to true
. In this case, the courier can end the route at a depot other than the first one.
Specify the depots where the courier can complete the route in the Depots that the courier can visit (vehicle.depot_id
in the API) or Depots to end the route at field (vehicle.ending_depot_id
in the API). If there are several depots, the algorithm will choose the optimal depot to complete the route at.
Alert
On the Vehicles sheet in the Depots that the courier can visit (depot_id
) and Depots to end the route at (ending_depot_id
) fields, you can't specify both regular and cross-docking depots at once. On a single route, a courier may only visit either regular depots or cross docks.
If you want the courier to end the route at the same depot where they started it, set the vehicle.finish_route_in_starting_depot
parameter to true
(by default, it's set to false
). In this case, if the courier's starting location is not a depot (vehicle.visit_depot_at_start
= false
), they will need to return to the depot where they started the second run of the route.
If you want the courier to end each run at the same depot where it was started, set the vehicle.finish_run_in_starting_depot
parameter to true
(by default, it's set to false
). To allow the courier to change depots between runs, set the vehicle.can_change_depot_between_runs
parameter to true
. For more information, see Start of a new run from a different depot.
Note
It only makes sense to set the vehicle.finish_route_in_starting_depot
and vehicle.finish_run_in_starting_depot
parameters to true
if the vehicle.allow_different_depots_in_route
parameter is also set to true
.
If the courier doesn't have to return to the depot after completing all orders, set Return to depot at the end of the shift (vehicle.return_to_depot
in the API) to false
.
Example 1.1
Two couriers are to deliver two orders: one is a delivery
order that needs to be picked up from Depot 1, and the other one is a pickup
order to be delivered to Depot 2. The couriers can only make 1 run each, starting at any depot and ending the route at any depot. Both couriers are allowed to stop at different depots during one run, but they cannot stop at intermediate depots.
The solution uses only one courier: they leave Depot 1 after picking up the delivery
order, deliver it, pick up the pickup
order, and deliver it to Depot 2, where they end the route.
API request (JSON) ⋅ API response ⋅ View on map
Example 1.2
The same as in example 1.1, but the couriers need to end routes at the same depot where they started them (vehicle.finish_route_in_starting_depot
= true
).
The solution uses both couriers. Courier 1 leaves Depot 1 after picking up the delivery
order, delivers it, and returns to Depot 1. The second courier leaves Depot 2, picks up the pickup
order, and returns with it to Depot 2.
API request (JSON) ⋅ API response ⋅ View on map
Return to any location at the end of the route
If your work scenario needs to take into account the distance of the last order from the courier's parking spot (or home address, for example), you can implement it as follows:
-
Create a point with the
garage
type (thelocations.type
field). This point will only be used to end the routes. -
For a courier who needs to return home or to the parking spot at the end of their working day, enter the ID of this point in the
vehicle.finish_at
field.
In the solution, all vehicles or couriers that have the finish_at
property specified return to the specified point. If the option to return to the depot is enabled (vehicle.return_to_depot
= true
), the route will first go the depot and then to the parking spot.
Example
The example below uses two vehicles with different load capacities and four orders with different weights. Two vehicles are used for delivery because of the weight restrictions. Vehicle 2 doesn't have to return to the depot after it delivers the last order.
Note
Note that in the RouteQ response, vehicle 2 completes the route at the last order location.
API request (JSON) ⋅ API response ⋅ View on map
Start or end of the route as close to the depot as possible
You can plan a route so that the courier starts or finishes on the order that is closest to or furthest from the depot. For example, if you expect to get new orders in the morning, then it would be better to start the route with the orders closest to the depot. That way, it will be easier for the courier to return to the depot to pick them up. On the other hand, by starting the route with the farthest order, the courier would finish closer to the depot in the evening.
If you are not using advanced cost settings, set the following parameters:
-
first_edges_penalty_factor
: A penalty for the distance from the depot to the first order, the default is 0. If the value is greater than 0, the algorithm minimizes this distance, and if the value is less than 0, it maximizes the distance. -
last_edges_penalty_factor
: A penalty for the distance from the depot to the last order, the default is 0. If the value is greater than 0, the algorithm minimizes this distance, and if the value is less than 0, it maximizes the distance.
Penalties are calculated similarly to the duration and length of route segments (see the Travel between route points group under Advanced cost settings).
If penalty values are high, routes may be suboptimal in terms of mileage. If penalty values are low, then the first or last order of a route may be selected in violation of any requirements provided it saves on mileage.
If you use advanced cost settings, use the keywords from the Travel from or to the depot group.
Example
In the example below, there is 1 courier and 10 orders. Two penalties are set: first_edges_penalty_factor
= 2 and last_edges_penalty_factor
= -2. Planning produces a route that begins with the order closest to the depot and ends with the furthest order.
API request (JSON) ⋅ API response ⋅ View on map
Multiple courier runs per day
By default, a courier starts and ends their route at a depot, that is they complete exactly one route during a working day (shift).
If a courier can return to the depot anytime during the work shift to reload additional orders, you can limit the number of runs using one of the parameters:
-
vehicle.shifts.N.max_runs
: The maximum number of runs per shift. The default is 1. -
vehicle.max_runs
: The maximum number of runs for all the courier's shifts summed up (for example, the courier can perform all the runs in one shift). The number of courier runs can be lower than the number of shifts. The default is 1. -
If none of the parameters are specified, the courier can make as many runs as they have shifts (one run per shift).
Note
You can use vehicle.max_runs
or vehicle.shifts.N.max_runs
in the planning task, but not both parameters at the same time.
At least one shift should be set for the courier.
Example
The example below uses one vehicle with the limited carrying capacity of 2 tons and three orders with a weight of 0.8 tons. The vehicle is allowed to do two runs. This means that after completing two orders, the vehicle can return to the depot to pick up and deliver another order.
API request (JSON) ⋅ API response ⋅ View on map
Break between runs
You can set a break between a courier's runs with the parameter vehicles.extra_service_time_before_last_run_s
. Mind the following:
-
The break is scheduled before the last run in the shift.
-
Break time is added to the handling time of the depot that follows this run.
Parameter |
Value |
Example |
|
Break duration in seconds. |
Break time is 45 minutes (2700 seconds). |
Example
A courier has two scheduled runs. A one-hour break and a 45-minute break are scheduled between these runs (extra_service_time_before_last_run_s
= 2700
).
As a result, two breaks are scheduled:
- 60 minutes in the first run.
- 45 minutes before the start of the second run. This time will be added to the handling time of the second depot.
API request (JSON) ⋅ API response ⋅ View on map
Limit the number of stops per shift
When planning a route, you can specify the minimum and maximum number of stops in the route. This can be useful, for example, to limit the maximum courier workload per day or, on the contrary, make sure that the courier gets on the route with a certain minimum number of stops.
For this, RouteQ uses the minimal_stops
and maximal_stops
shift parameters. You can set the number of stops for each courier.
The restriction is not strict and may be violated. If the limit on the minimum number of stops is violated, a penalty applies. The penalty is specified in the following shift fields: penalty.stop_lack.fixed
(for making fewer stops than the minimum number) and penalty.stop_lack.per_stop
(for each stop missing under the minimum number).
In the same way, if the limit on the maximum number of stops is violated, a penalty applies. The penalty is specified in the following shift fields: penalty.stop_excess.fixed
(for making more stops than the maximum number) and penalty.stop_excess.per_stop
(for each stop above the maximum number).
Note
Usually when you restrict the number of stops, the solution metrics degrade since the solution favors restrictions at the cost of the optimal route.
Unique stops
When using the minimal_stops
parameter, orders with matching coordinates are considered different stops if they aren't consecutive in the route. For the minimal_stops
condition to be fulfilled, the algorithm may plan the route to have the courier visit the same address multiple times.
To avoid repeat visits, use the minimal_unique_stops
parameter and penalty.unique_stop_lack.fixed
and penalty.unique_stop_lack.per_stop
penalties instead of minimal_stops
.
The minimal_unique_stops
parameter considers only orders with unique coordinates, so there won't be any repeat visits planned for the courier. However, orders to the same address may be assigned to different couriers, because such stops are considered different in this case, and the algorithm can use this to enforce the minimal_unique_stops
limit.
It makes sense to use the minimal_unique_stops
limit if the route has a lot of multi-orders.
Stops for non-active couriers
By default, the minimal_stops
and minimal_unique_stops
limits apply to all assigned couriers. When you specify more couriers than necessary, and the penalty.stop_lack
or penalty.unique_stop_lack
penalty value is too high, this can result in suboptimal planning.
To set the minimum number of stops in a shift and build an effective route at the same time, use the option ignore_min_stops_for_unused
(see Counting the minimum number of stops for active vehicles only).
Example 1
In the example, the route is built for 3 couriers who deliver to 15 points. Since there are no restrictions for the route, the route is built the usual way.
API request (JSON) ⋅ API response ⋅ View on map
Example 2
This example has the same conditions as example 1, but sets the limit of 4 minimum stops per courier. As a result, the routes changed so that each courier visited at least 4 delivery locations.
API request (JSON) ⋅ API response ⋅ View on map
Example 3
This example has the same conditions as example 1, but sets the limit of 5 maximum stops per courier. As a result, orders are distributed evenly among all couriers, even though several orders are located next to each other and can be completed by one courier.
API request (JSON) ⋅ API response ⋅ View on map
Maximum shift duration
Sometimes you may need to extend the courier's working hours. But you also need to limit the maximum shift length and set the window you want to fit into. For example, there's a specific 14-hour time window during which couriers can make deliveries: from 8:00 to 22:00. However, the duration of each courier's shift must not exceed 10 hours (max_duration_s
), and there should be no more than 8 working hours per shift (max_working_duration_s
).
RouteQ helps you schedule shifts with hard time windows and preferred lengths. In this case, the courier's shift length doesn't affect the work start time. It only affects the time that they spend completing orders.
The maximum shift length can be set as a soft restriction shifts.N.max_duration_s
that can be violated for a penalty or as a hard restriction shifts.N.hard_max_duration_s
that can't be violated:
-
When planning with a soft restriction, the workload that doesn't fit into one courier's preferred shift is distributed among others or to the same courier, but with penalties for violating the shift length. All orders that can't be completed in
max_duration_s
are added to the route with the penalty specified in theshift.penalty.late
field (if applicable) or in theshift.penalty.out_of_time
field all other times. The total route penalty for violating the maximum shift length is shown in the API response in theovertime_penalty
field. If the estimated order cost including penalties is higher than the cost of completing the order by another courier, the order is handed over to another courier. -
When planning with a hard restriction, the courier's shift never exceeds the
hard_max_duration_s
value.
The maximum working time per shift can also be defined by a soft restriction shifts.N.max_working_duration_s
or hard restriction shifts.N.hard_max_working_duration_s
.
-
If the courier violates a soft restriction, the workload is redistributed to other couriers or given back to the same courier, but with penalties. Orders that are not completed within the shift's working time
max_working_duration_s
will be added to the route with a penaltyworking_overtime
:-
shifts.N.penalty.working_overtime.fixed
: Penalty for exceeding the maximum working time per shift. -
shifts.N.penalty.working_overtime.minute
: Penalty for each minute of such overtime.
If the penalty value isn't specified, the penalty for violating the time window
shift.penalty.out_of_time
will be applied to the orders. You can find the total penalty amount in theworking_overtime_penalty
field of the API response. The order will be transferred to another courier if the estimated cost of the order (including penalties) exceeds the cost of completing the order with another courier. -
-
When planning with a hard restriction, the maximum duration of working time per shift never exceeds the value specified in
hard_max_working_duration_s
.
If you use both soft and hard restrictions for max_duration_s
and max_working_duration_s
, the hard one can't be lower than the soft one. By default, max_duration_s
and max_working_duration_s
are set to 2 days, while hard_max_duration_s
and hard_max_working_duration_s
are set to 30 days.
Example 1
Let's say the shift window shifts.N.time_window
is from 8:00 to 23:00. By default, routes will be built to use the minimum number of couriers.
If you specify max_duration_s
= 14400, the load is distributed between couriers, and each of them works for approximately 4 hours (the shift length is set in seconds). Some couriers may still work more than 4 hours, because it's less costly to pay for extra hours than to hand over the order to another courier.
As a result of planning, orders are distributed among three couriers. One courier's shift went over 4 hours. The penalty amount is shown in the API response in the overtime_penalty
field.
API request (JSON) ⋅ API response ⋅ View on map
Example 2
The same as in Example 1, but with hard restrictions on the maximum shift length: hard_max_duration_s
= 14400. When planning, all couriers are given shifts that are 4 hours or less. As a result, the number of couriers increased to 4.
API request (JSON) ⋅ API response ⋅ View on map
Example 3
Three couriers are delivering 26 orders. The shift window shifts.N.time_window
is 8:00 to 23:00. Penalties are set for exceeding the maximum working time per shift: shifts.N.penalty.working_overtime.fixed
for overtime, and shifts.N.penalty.working_overtime.minute
for overtime per minute.
If you specify shifts.0.max_working_duration_s
= 14,400, each courier will work for approximately 4 hours. The restriction is soft, and one courier worked overtime.
As a result of the planning, all orders are distributed among couriers, and the total penalty amount for overtime is indicated in the field working_overtime_penalty
of the API response.
API request (JSON) ⋅ API response ⋅ View on map
Example 4
Same as in Example 3, but with a hard restriction on the maximum working time per shift shifts.N.hard_max_working_duration_s
= 14,400.
As a result of planning, all couriers are busy and work for a maximum of 4 hours. However, one of the orders remains unassigned.
API request (JSON) ⋅ API response ⋅ View on map
Maximum mileage per shift
In some cases, you need to limit the mileage per vehicle. For example:
-
The planning includes hired cars, and their rate implies limited mileage.
-
You can assign specific vehicles for far-away points. Then you can limit the mileage for other vehicles.
The shifts.max_mileage_km
parameter determines the maximum vehicle mileage per shift. The entire mileage is taken into account, including:
-
Traveling from the depot or starting point to the first point from the order list.
-
Returning to the depot or end point of the route from the last point in the order list.
The restriction is soft: the algorithm may violate it. Penalties are set in the fields:
-
shifts.penalty.max_mileage.fixed
: A fixed penalty for exceeding the maximum mileage (1000 by default). -
shifts.penalty.max_mileage.km
: A penalty per each kilometer in excess of the maximum mileage (100 by default).
If the maximum mileage per run is critical to you, and the vehicle can do several runs per shift, you can create multiple identical shifts (see Example 2).
If the courier uses public transit, only the walking part of the route is returned as the mileage.
Example 1
The mileage limit per courier is 50 km, with a big penalty for violating this restriction. In the result, the planned mileage on any route doesn't exceed 50 km.
API request (JSON) ⋅ API response ⋅ View on map
Example 2
There's one courier and each of their runs should be no more than 50 km. To achieve this, the courier has several shifts with the same time windows and mileage restrictions. The result includes 3 routes, each one less than 50 km long.
API request (JSON) ⋅ API response ⋅ View on map
Limit the mileage and number of stops per run
Sometimes you might need to restrict the mileage and number of stops for a specific run in the route.
To set a mileage limit, go to the Vehicles sheet and specify the maximum allowed mileage per run in kilometers in the shifts.N.run_restrictions.max_mileage_km.value
field. If necessary, add penalties for exceeding the limit using the following fields:
-
shifts.N.run_restrictions.max_mileage_km.penalty.fixed
: The penalty for exceeding the maximum mileage (defaults to 1000). -
shifts.N.run_restrictions.max_mileage_km.penalty.km
: The penalty for each kilometer in excess of the maximum mileage (defaults to 100).
To limit the number of stops in the run, specify values for the following parameters on the Vehicles sheet:
-
shifts.N.run_restrictions.maximal_stops.value
: The maximum number of stops. -
shifts.N.run_restrictions.minimal_stops.value
: The minimum number of stops.
Penalties can be imposed for violating the limit on the number of stops. If necessary, specify penalty values in the following fields:
-
shifts.N.run_restrictions.maximal_stops.penalty.fixed
: The penalty for exceeding the maximum number of stops (defaults to 1000). -
shifts.N.run_restrictions.maximal_stops.penalty.per_stop
: The penalty for each extra stop (defaults to 100). -
shifts.N.run_restrictions.minimal_stops.penalty.fixed
: The penalty for violating the minimum number of stops (defaults to 1000). -
shifts.N.run_restrictions.minimal_stops.penalty.per_stop
: The penalty for each missing stop (defaults to 100).
Example 1
A courier must deliver 10 orders. There are no restrictions on the mileage and number of stops in the run.
As a result, the courier delivers all the orders in 1 run.
API request (JSON) ⋅ API response ⋅ View on map
Example 2
Same as example 1 except for the first shift runs, where the following restrictions on the maximum number of stops are set:
shifts.0.run_restrictions.maximal_stops.value
= 1shifts.0.run_restrictions.maximal_stops.penalty.fixed
= 1 000 000shifts.0.run_restrictions.maximal_stops.penalty.per_stop
= 1 000
The penalties are so high that it's unprofitable to violate the stop restrictions. As a result, the courier delivers the orders in 2 runs. In the first run they deliver order 8, and in the second run they deliver all the remaining orders.
API request (JSON) ⋅ API response ⋅ View on map
Example 3
Same as example 2 except for the first shift runs, where the penalties for exceeding the maximum number of stops (shifts.0.run_restrictions.maximal_stops.penalty.fixed
and shifts.0.run_restrictions.maximal_stops.penalty.per_stop
) are no longer used. The run has the following restriction: shifts.0.run_restrictions.maximal_stops.value
= 1.
Plus, the cost of one run (3000) is added to the cost.run
field.
As a result, the courier delivers all the orders in 1 run. Under the given conditions, it's more profitable to violate the restriction and get a penalty than to split the orders into several runs. The penalty amount is 1100, where 1000 is the default value for shifts.0.run_restrictions.maximal_stops.penalty.fixed
and 100 is the default value for shifts.0.run_restrictions.maximal_stops.penalty.per_stop
.
API request (JSON) ⋅ API response ⋅ View on map
Route density
To set the preferred area of work for a vehicle so that the route includes orders near a certain location, use the global_proximity_attraction_point
parameter. In the parameter value, specify the location id
with the garage
type. This is used as a hotspot: the algorithm aims to reduce the total distance between orders on the route and this location.
The density of routes around the hotspot is determined by the options.global_proximity_factor
option: the greater its value, the denser the routes are. For more information about this option, see Dense routes.
The maximum distance from the route locations to the hotspot is stored in the max_distance_to_attraction_point_m
parameter, which can be used to calculate the cost of the route. The total sum of distances from all orders to the hotspot on the route affects the penalty for inadequate route grouping.
Other ways to group orders geographically
- You can use the
global_proximity_factor
option to build dense routes without setting a “hotspot”. This option only works for vehicles that don't have theglobal_proximity_attraction_point
parameter set. - By using geofences for vehicles, you can set restrictions on delivery zones. While geofence restriction can't be violated, route density settings are a more flexible tool.
Example 1
Three vehicles have to deliver 15 orders. The route is calculated based on the order weight and vehicle capacity. There are no other restrictions on the route.
API request (JSON) ⋅ API response ⋅ View on map
Example 2
The same as in example 1, but each courier has a set hotspot that shows their preferred area of work. As a result, the routes are more dense. The maximum distance from the order to the hotspot on the route is 20,663 m.
API request (JSON) ⋅ API response ⋅ View on map
Example 3
The same as in example 2, but one of the couriers has a different hotspot. Because orders are regrouped, the location of routes on the map has changed. The maximum distance from the order to the hotspot increased to 28,528 m.
API request (JSON) ⋅ API response ⋅ View on map
Vehicle or courier cost
You can specify different cost-of-use components for each vehicle in the query to RouteQ. To set the cost-of-use for the vehicle or courier, use the optional vehicle.cost
field.
RouteQ lets you define the following main cost components:
-
cost.fixed
: The fixed cost-of-use for the vehicle. -
cost.hour
: The cost per hour of work. -
cost.km
: The cost per kilometer of mileage. -
cost.location
: The cost per visit of one order. -
cost.run
: The cost per run. -
cost.tonne_km
: The cost per ton-kilometer of transport work.
In this case, the cost at which the algorithm selects the optimal routing option is used. That's not the actual rate for using the vehicle, but rather the algorithm's settings.
You can also set the cost-of-use for the vehicle or courier as an arithmetic expression. For more information, see Advanced cost settings.
Cost values
Please note that some components of vehicle cost are already set by default:
-
cost.fixed
= 3000 -
cost.hour
= 100 -
cost.km
= 8
They apply in the following cases:
-
If you use Excel and leave these fields blank.
-
If you make an API request and don't fill in the
vehicle.cost
field.
The default values often need to be adjusted. For example, adjust them in the following business cases:
Note
Always set cost.hour
and cost.km
to values other than 0, otherwise, the routes will be chaotic. That happens because the algorithm optimizes the total cost. If the cost per hour or kilometer equals 0, the route will cost the same with any mileage.
If you want to minimize the route cost, the cost.hour
and cost.km
values need to be above 0.
The cost of a ton-kilometer of transport work
Heavily loaded vehicles use more fuel and wear out faster. That's why routes for transporting heavy goods need to be built in such a way that the vehicle travels the minimal possible distance while heavily loaded.
RouteQ uses the cost.tonne_km
property to do this. It determines the cost of one kilometer for each ton of cargo in the vehicle. Default value: 0.
The total amount of transport work in ton-kilometers is returned to the total_transport_work_tonne_km
field of the API response, and its total cost is in the total_transport_work_cost
field.
Example 1
You need to deliver 3 cargos weighing 100, 200, and 2000 kg. The cost.tonne_km
cost per ton-kilometer is set to zero. As a result, the heaviest order was delivered last: the vehicle load wasn't taken into account when building the route, and based on other criteria, this option was optimal.
API request (JSON) ⋅ API response ⋅ View on map
Example 2
The source data is the same, but cost.tonne_km
= 8. The resulting solution is optimized, taking the load into account: the heaviest order is unloaded first.
API request (JSON) ⋅ API response ⋅ View on map
Advanced cost settings
You can set the cost-of-use for the vehicle or courier as an arithmetic expression. When planning, you can calculate the cost with one expression in the vehicles.cost
field or use multiple expressions in nested fields:
cost.route
: For a route.cost.shift
: For a shift.cost.run
: For a run.
Alert
If the vehicle.cost
field has formulas, then the algorithm calculates the cost-of-use for the vehicle or courier based only on these formulas. Standard cost components are included in the calculation only if they are explicitly specified in the formulas.
The expression can use keywords and mathematical notation given in the tables below. To check the expression, use an HTTP request.
Keywords for route parameters
Group |
Keyword and explanation |
Runs |
|
Shifts |
|
Orders and stop |
|
Duration |
|
Distance |
To set the preferred area of work for a vehicle so that the route includes orders near a certain location, use the The cost of courier's work For example, the formula can be as follows: |
Transport work |
|
Depots |
|
Start and end of the route |
|
Travel between route points |
For the purposes of calculating the distance and travel duration between route points, the These parameters are used to implement the same scenarios as those found in penalties for the start or end of the route as close to the depot as possible. |
Travel with and without orders |
|
Capacity |
|
Trailer |
|
Walking routes |
|
Route metrics are calculated using the following formulas:
- total route duration
transit_duration_h
=walking_transit_duration_h
+driving_transit_duration_h
- total route length
distance_km
=walking_distance_km
+driving_distance_km
The calculation of variables that are used in routes with on-foot sections is influenced by the transportation method:
walking
: The entire route is traveled on foot, and the distancedriving_distance_km
and durationdriving_transit_duration_h
equal 0.transit
:driving_distance_km
= 0: It's assumed that the courier visited all orders on foot (there isn't enough data to calculate the distance traveled by public transport).driving_transit_duration_h
: calculated based on other data received when solving the task (it may be non-zero).
Mathematical notations and functions
Mathematical notations |
Explanation |
Numbers |
Integers (positive, negative), rational. Use a dot as a separator for decimals. |
Arithmetic operations |
+, -, *, / |
Parentheses |
(…) |
Mathematical functions |
|
Logical functions |
|
Comparison operations |
<, >, = |
Logical operations |
|
Functions |
|
Function conditions |
The following functions can only be used inside the
|
Examples of expressions
500 + 500 * has_location(in_zone('West'))
: If the route has a stop in theWest
zone, then the expression will return 1000, otherwise, 500.450 * location_count(in_zone('West') | in_zone('North'))
: Counts the number of stops in at least one of the two zones (West
,North
) and returns that number multiplied by 450.1000 + has_location(in_zone('West') & has_load_type('Frozen')) * 500
: If the route has at least one stop in theWest
zone and has theFrozen
load type, the expression returns 1500. Otherwise, it returns 1000.100 * (has_location(in_zone('West')) & has_location(in_zone('North')))
: If the route has at least one stop in theWest
zone and at least one stop in theNorth
zone (it can be one stop in both zones or two different stops), the expression returns 100.100 * has_location(in_zone('West') & in_zone('North'))
: If there's a stop that falls into bothWest
andNorth
, the expression returns 100.100 * location_count(is_pickup() & in_zone('West') & !has_tag('Return'))
: The expression counts the number ofpickup
orders that are in theWest
zone and don't have theReturn
tag, and returns their number multiplied by 100.
Solution metrics
If advanced cost settings are specified for the vehicle or courier, you'll see the following fields in the solution metrics (note these fields may be displayed for the first run only):
total_custom_cost
: The total route cost. It includes the route cost calculated using the formula and the cost of all shifts.route_custom_cost
: The cost of the route calculated using thecost.route
formula.shift_total_custom_cost
: The total cost of the shift. It includes the shift cost calculated using the formula and the cost of all runs in the shift.shift_custom_cost
: The cost of the shift calculated using thecost.shift
formula.run_custom_cost
: The cost of the run calculated using thecost.run
formula.total_cost
: The cost of the run in the total courier cost (vehicles.cost
).total_penalty
: The total cost of all penalties for the run.total_cost_with_penalty
: The sum of thetotal_cost
andtotal_penalty
values.
The fields you see depend on how the courier cost is calculated. There are 2 ways to do that:
- With one expression using a simple formula.
- With a compound expression that includes values in nested fields.
Metrics for a simple formula
When the courier cost is calculated with one expression, a simple formula is used. For example:
vehicles.cost = duration_h * 100 + distance_km * 8
In that case:
-
The total route cost is displayed in the
total_custom_cost
field for the first run. This field isn't displayed for the subsequent runs. -
The
total_cost
field for each run displays the value calculated by the following formula:total_cost = total_custom_cost * (<number_of_orders_in_run> / <number_of_orders_in_route>)
-
In the
total_cost_with_penalty
field for each run, the sum of thetotal_cost
andtotal_penalty
values is displayed.
For more information on calculating the courier cost using a simple formula, see this example.
Metrics for a compound formula
The courier cost can include several values in the nested fields (cost.route
, cost.shift
, and cost.run
) and be calculated using a compound formula. For example:
vehicles.cost = 10000 + 1000 + locations * 100
, where:
cost.route
= 10000.cost.shift
= 1000.cost.run
=locations * 100
.locations
is the number of orders (in a route, shift, or run).
In this case:
-
The total route cost is displayed in the
total_custom_cost
field for the first run. This field isn't displayed for the subsequent runs. -
The value obtained for
cost.route
is displayed in theroute_custom_cost
field for the first run. Theroute_custom_cost
field isn't displayed for the subsequent runs. -
The value obtained for
cost.shift
is displayed in theshift_custom_cost
field for the first run. Theshift_custom_cost
field isn't displayed for the subsequent runs. -
The value obtained for
cost.run
is displayed in therun_custom_cost
field for each run. -
In the
shift_total_custom_cost
field for the first run, the value calculated using this formula is displayed:shift_total_custom_cost = cost.shift + <sum_of_cost.run_of_all_runs_per_shift>
This field isn't displayed for the subsequent runs.
-
The
total_cost
field for each run displays the value calculated by the following formula:total_cost = run_custom_cost + (shift_custom_cost * <number_of_orders_in_run> / <number_of_orders_in_shift>) + (route_custom_cost * <number_of_orders_in_run> / <number_of_orders_in_route>)
-
In the
total_cost_with_penalty
field for each run, the sum of thetotal_cost
andtotal_penalty
values is displayed.
For more information on calculating the courier cost using a compound formula, see this example.
Example 1
The courier cost is calculated using this simple formula:
vehicles.cost = duration_h * 10 + 1000
.
The shift lasts 10 hours (duration_h
= 10). The first run has 2 orders and the second run has 3 orders.
In this case:
- In the
total_custom_cost
field for the first run, the total route cost is displayed:10 * 10 + 1000
= 1100. - In the
total_cost
field for the first run, the following value is displayed:1100 + 2 / 5
= 440. - In the
total_cost
field for the second run, the following value is displayed:1100 + 3 / 5
= 660.
Example 2
The courier cost is calculated using the compound formula:
vehicles.cost = 7000 + 1000 + locations * 100
, where:
cost.route
= 7000.cost.shift
= 1000.cost.run
=locations * 100
.locations
is the number of orders (in a route, shift, or run).
The route has 2 shifts. There are 2 runs in the first shift, and each run has 2 orders. In the second shift, there are 3 runs with 1 order each. In total, the route has 7 orders: 4 orders in the first shift and 3 orders in the second shift.
In this case:
- In the
total_custom_cost
field for the first run, the total route cost is displayed:7000 + 1000 + 700
= 8700. - The
route_custom_cost
field for the first run displays this value: 7000. - The
shift_custom_cost
field for the first run displays this value: 1000. - The value obtained for
cost.run
is displayed in therun_custom_cost
field for each run.- For runs 1 and 2:
run_custom_cost
= 200. - For runs 3, 4, and 5:
run_custom_cost
= 100.
- For runs 1 and 2:
- In the
shift_total_custom_cost
field for the first run, you'll see a value equal to1000 + 700
= 1700. - In the
total_cost
field for each run, the following value is displayed:- For runs 1 and 2:
200 + (1000 * 2 / 4) + (7000 * 2 / 7)
= 2700. - For runs 3, 4, and 5:
100 + (1000 * 1 / 3) + (7000 * 1 / 7)
= 1433.33.
- For runs 1 and 2:
Example 3
The task uses the following pricing plan:
-
The basic cost of one multi-order is 170 units.
-
The cost of a multi-order increases by 20 units every 100 kilometers.
-
The courier receives at least 4000 units per shift even if the number of orders is insufficient.
This pricing corresponds to the following cost: 100 * duration_h + 8 * distance_km + max(4000, (170 + 20 * Floor(distance_km / 100)) * unique_stops)
.
As a result, the cost of using each vehicle is at least 4000
. The cost in excess of the shift payment (or delivered orders) is formed based on the total time and route length.
API request (JSON) ⋅ API response ⋅ View on map
Example 4
You need to plan a route, provided that the cost depends on the mileage and is determined using the formula:
<vehicle cost> = maximum {<minimum route cost>, <number of locations on the route> * <cost of delivery to the location>}
The minimum route cost and cost of delivery to the point are indicated in the table:
Mileage |
The cost of one multi-order (rubles) |
The minimum route cost (rubles) |
no more than 150 km |
510 |
6,000 |
no more than 450 km |
530 |
7,000 |
no more than 750 km |
550 |
8,500 |
over 750 km |
570 |
11,000 |
When planning, the vehicle cost is calculated using the formula:
max(6000 + (distance_km > 150)*1000 + (distance_km > 450)*1500 + (distance_km > 750)*2500
, stops
*(510 + min(60, Ceil(max(0, distance_km - 150)/300)*20))
)
More about the calculation formula
- Minimum route cost:
6000 + (distance_km > 150)*1000 + (distance_km > 450)*1500 + (distance_km > 750)*2500
. - The number of points on the route is determined using the
stops
parameter. - The cost of delivery to the point is determined as follows. The minimum multi-order cost is
510
, the maximum possible addition to it is570 - 510 = 60
. It's important that the cost of multi-orders increases uniformly in increments 20 for every 300 km of mileage. This can be represented using the formulaCeil(max(0, distance_km - 150)/300)*20
. Then the cost of delivery to the point, based on the data from the table, is equal to510 + min(60, Ceil(max(0, distance_km - 150)/300)*20))
.
As a result, vehicle 1 has a route length of more than 150 km, the number of stops is 18 (1 multi-order). The final cost is 9540. Vehicle 2 has a route length of no more than 150 km, the number of stops is 21 (1 multi-order). The total cost is 10,710.
API request (JSON) ⋅ API response ⋅ View on map
Example 5
You need to plan the route so as to minimize underloading the vehicle. To do this, you can set an additional vehicle cost in the formula, provided that its load is below a certain limit. For example, when planning vehicles with a load capacity of 3000 kg, load them by at least 80%. Note that we assume that the remaining cost (per hour, per km, for the fact of use) will be set by default. The vehicle cost is calculated using the formula:
3000 + duration_h*100 + distance_km*8 + max(0, 2400 - utilization_kg) * 100
More about the calculation formula
3000, 100, 8 in the first three summands are default values of the cost per use, per hour, and per kilometer, respectively. The formula adds the cost of 100 units for each underloaded kilogram from 2400:
As a result, the algorithm will aim to load all vehicles by at least 80% (if possible).
API request (JSON) ⋅ API response ⋅ View on map
Example 6
You need to plan a route, which includes some retail chains that open earlier. The task uses the following pricing plan:
-
The base cost of the route is made up of the time spent and the distance traveled.
-
Routes should be started earlier to avoid morning traffic. To encourage this, a penalty for departing after 8 AM is added to the cost calculation formula.
This pricing corresponds to the following cost:
100 * duration_h + 8 * distance_km + 50 * (start_route_time_s > 28800)
As a result of planning, all vehicles arrive at the depot before 8 AM.
API request (JSON) ⋅ API response ⋅ View on map
Example 7
You need to plan routes within the city, and it's not possible to transport light and heavy orders in one vehicle at the same time. The planning task has the City
geofence specified, and all orders are tagged Light
or Heavy
based on their weight.
These inputs correspond to the following cost:
(has_location(in_zone('City')) & has_location(has_tag('Light')) & has_location(has_tag('Heavy')))*100000000
You can't assign incompatible order types here, because compatibility restrictions only apply within one geofence.
API request (JSON) ⋅ API response ⋅ View on map
Example 8
The cost of courier's work is calculated using the same formula as in example 3, but the vehicles.proximity_edge_cost.hour
and vehicles.proximity_edge_cost.km
parameters are used to specify the cost per hour of work and the cost per kilometer of mileage:
...
"vehicles": [
...
{
...
"cost": "3000 + duration_h*10000 + distance_km*800 + max(0, 2400 - utilization_kg) * 100",
"proximity_edge_cost": {
"hour": 10000,
"km": 800
},
},
...
},
...
As a result, proximity_edge_cost.hour
and proximity_edge_cost.km
(not cost.hour
and cost.km
) are used to calculate the cost of courier's work.
API request (JSON) ⋅ API response ⋅ View on map
Calculation of the courier's payout
Use the payout
field to calculate what payment the courier will receive for completing the route. During planning, you can calculate payouts using one expression in the vehicle.payout
field or use multiple expressions in nested fields:
payout.route
: For a route.payout.shift
: For a shift.payout.run
: For a run.
In the expressions, you can use the same keywords and mathematical notation you use to calculate the cost of the route for the company (the vehicle.cost
field).
Note
The vehicle.payout
field doesn't affect the route optimization, it's calculated after the planning task has been solved.
If the courier has the vehicle.payout
field set, you'll see the following fields in the solution metrics:
run_payout
: Payout for the run calculated using thepayout.run
formula.shift_payout
: Payout for the shift calculated using thepayout.shift
formula. Shown only for the first run of the shift.shift_total_payout
: Total payout for the shift. It includes the payout for the shift calculated using the formula plus the payout for all the shift's runs. Shown only for the first run of the shift.route_payout
: Payout for the route calculated using thepayout.route
formula. Shown only for the first run of the route.total_payout
: Full payout for the route, including the payout for the route calculated using the formula plus the payout for all the shifts. Shown only for the first run of the route, the other runs have it as 0.
If the payout
field is set for at least one courier, the planning results also have the total_payout
metric, which is the total amount to be paid to couriers.
Example 1
Two couriers are delivering 40 orders, each courier makes 2 runs. The couriers' cost for the company is set by the expression in the cost
field. For courier 1, the payout for the completed route is calculated using the expression in the payout
field: this amount is displayed in the metrics of the first run and is equal to 5000 units. For Courier 2, the payout is not calculated, so the total_payout
amount is also equal to 5000 units.
API request (JSON) ⋅ API response ⋅ View on map
Example 2
Two couriers are delivering 40 orders. For Courier 1, the payout calculation is set as follows: starting the shift — 3000 units, each kilometer of the route — 10 units, each delivered order — 50 units. If they deliver more than 10 orders during the shift, they receive a bonus of 500 units. For Courier 2, the payout is not calculated.
As a result of planning, Courier 1 makes two runs and delivers 20 orders. For each run, run_payout
is applied (1232 and 1053 units), as well as shift_total_payout
for the shift (2785 units, including the shift_payout
bonus of 500 units) and route_payout
for the route (3000 units). In total, the courier gets total_payout
of 5785 units.
API request (JSON) ⋅ API response ⋅ View on map
Vehicle tags
When you set up a vehicle or courier in a request to RouteQ, you can define the rules (or tags) for its compatibility with orders.
Compatibility rules may be required if a vehicle has special equipment that's necessary to fulfil a particular order, like an isothermal van for transporting food.
Vehicle and order compatibility rules (vehicle tags) are set in the following fields:
-
vehicle.tags
: The vehicle properties that can partially match the properties required to fulfill the order. -
vehicle.excluded_tags
: The vehicle properties that must not match the properties required to fulfill the order.
To set the order tags, use the location.required_tags
field in the request.
Alert
The order tags identify the vehicle characteristics that an order requires, whereas vehicle tags define the actual rules for compatibility of a particular vehicle with different orders.
Vehicle tags can be set as strings or regular expressions. Multiple string tags can be separated by commas. In this case, the vehicle can deliver the order if at least one of the listed vehicle tags matches the order tag or if the order has no tags. Regular expressions are used to describe the more complex logic and vehicle/order compatibility rules.
RouteQ uses POSIX Extended regular expression syntax. You can test your regular expressions at Regex101.
Let's look at some real-life cases of using tags.
Example 1
Let's take a use case when a transportation company delivers food and drinks in small bulk quantities. Some foodstuff must be delivered in isothermal trucks only. At the same time, all drinks and some foodstuff can be delivered without refrigerators. In addition, some clients can only accept a cargo if a vehicle is equipped with a tail lift.
To set these order restrictions, specify the following tags in the location.required_tags
field:
-
TAIL_LIFT
: For orders that can only be unloaded if a vehicle is equipped with a tail lift. -
ISOTHERMAL_TRUCK
: For orders containing goods that require temperature-controlled transportation. -
NORMAL_TRUCK
: For orders that do not require special conditions of transportation.
To set vehicle features, use the following tags in the vehicle.tags
field:
-
TAIL_LIFT
: For vehicles equipped with a tail lift. -
ISOTHERMAL_TRUCK
: For isothermal vehicles. -
NORMAL_TRUCK
: For regular vehicles without an isothermal van.
Note
A vehicle may have one or more tags, or it may not have any at all, depending on its actual configuration. The same rule applies to order tags.
API request (JSON) ⋅ API response ⋅ View on map
Example 2
Let's take a use case when some orders have a restriction on the vehicle body height due to different height of unloading zones.
For example, there are orders with the restriction on body height of 2 meters, 2.3 meters, and 2.5 meters. Then they should have the appropriate tags: Max_200
, Max_230
, and Max_250
.
For the vehicles, tags are set in a more complex way, since a vehicle up to 2 meters high can deliver any orders, whereas a vehicle up to 2.8 meters high can only deliver some orders. That is, if you only use tags
, then at a vehicle's height:
-
Up to 2 meters, the
vehicle.tags
field will contain allMax_200
,Max_230
, andMax_250
values. -
From 2 to 2.3 meters, the
vehicle.tags
field will contain theMax_230
andMax_250
values. -
From 2 to 2.3 meters, the
vehicle.tags
field will contain theMax_250
value. -
More than 2.5 meters, the
vehicle.required_tags
field will be empty.
API request (JSON) ⋅ API response ⋅ View on map
Example 3
Let's take a use case when some orders have a restriction on the arrival of vehicles with a certain load capacity (the OR condition applies when any of the corresponding vehicles is suitable).
For example, there are vehicles with different load capacity: 1, 3, 9, and 15 tons. Let's fix these characteristics using vehicle.tags
tags. Because you have to combine these tags when describing orders, let's set them using regular expressions: .*1TON.*
, .*3TON.*
, .*9TON.*
and .*15TON.*
(.*
means any substring).
The vehicle load capacity limit for some orders is from 1 to 15 tons, from 3 to 9 tons, and from 1 to 3 tons. This limit is set for the order by a string with a regular expression that includes tags of all suitable vehicles. That is, the location.required_tags
field will contain the following regular expressions at the required load capacity:
- From 1 to 15 tons:
##1TON##3TON##9TON##15TON##
. - From 3 to 9 tons:
##3TON##9TON##
. - From 1 to 3 tons:
##1TON##3TON##
.
Note
The order tags in example 2 are set by a simple list, because the vehicle must have all the listed tags (AND condition). You have to set at least one of the order tags (OR condition) for the vehicle in example 3. To do this, you can use regular expressions or create separate tags for each possible combination of OR conditions.
API request (JSON) ⋅ API response ⋅ View on map
Optional tags
When planning, you may sometimes need to consider which vehicles are best to use (or avoid) for certain orders. For example, it's better to give VIP orders to specially trained couriers.
For such requirements, there are optional tags. They're listed in the location.optional_tags
field. If preferences can't be met, they may be violated (for example, because of weight restrictions or delivery time). That's the difference between optional tags and required vehicle characteristics.
Note
If you'd prefer to have vehicles used in a certain zone, set optional geofences for them.
You can use the location.optional_tags.value
tag weight to prioritize your preferences. Its value can be positive or negative. When planning, the optional tag is compared to the tags of the vehicle that is delivering the order. If the tag from location.optional_tags
matches a vehicle tag from the following lists:
-
vehicle.tags
:value
is deducted from the route cost. -
vehicle.excluded_tags
:value
is added to the route cost.
The value that optional tags add to the route cost is returned in the result.routes.metrics.total_optional_tags_cost
field (it can be negative).
Example
You need to deliver 10 orders, some of them have the following optional tags:
vip
: 6 orders. Its weight varies from 100 to 350 at different points.morning
: 3 orders. Its weight at all points is the same — 500.
One of the vehicles has vip
and morning
tags specified in the vehicle.excluded_tags
field. This means that it's best not to give vip
-tagged and morning
-tagged orders to this courier due to the late start time of the route.
As a result, in most cases the requirements aren't violated: five out of six vip orders are delivered by the courier that doesn't have any limits on the vip
tag. There are no violations related to the morning
tag.
But one vip order is scheduled for a vehicle with the vip
tag in excluded_tags
due to capacity restrictions. 100 is returned in the total_optional_tags_cost
field for this route: using an "unsuitable" vehicle increased the cost by 100 units. The preference was violated for the order with the lowest location.optional_tags.value
weight.
API request (JSON) ⋅ API response ⋅ View on map
Order incompatibility
Orders may have incompatible types, which you can set using the following parameters:
-
options.incompatible_load_types
: Sets order incompatibility for all vehicles in the same way. For more information, see the Order incompatibility section. -
vehicle.incompatible_load_types
: Sets order incompatibility for a specific vehicle by enabling you to take vehicle features into account. -
vehicle.onboard_incompatible_load_types
: When this is set tofalse
(by default), order incompatibility remains in effect throughout the entire run, and when the value istrue
, then only while the orders are in the vehicle.
Note
The vehicle.incompatible_load_types
parameter has a higher priority and completely redefines the options.incompatible_load_types
parameters for this vehicle.
For example, different temperature modes are required to transport milk and ice cream. If the vehicle has one compartment, it can transport either milk or ice cream. If the vehicle has two compartments with different temperature modes, it can transport milk and ice cream at the same time in different compartments. In this case, specify the order incompatibility vehicle.incompatible_load_types
for vehicles with one compartment. Don't use this parameter for vehicles with two compartments and don't specify incompatible types options.incompatible_load_types
for orders in general.
If orders are incompatible for reasons other than vehicle characteristics, set vehicle.onboard_incompatible_load_types
= true
. For example, if orders from competing companies shouldn't be transported at the same time, the courier will pick up and deliver each company's orders separately without stopping at a depot. This reduces mileage and time en route.
Example 1
The delivery consists of 4 addresses with the following order types:
-
Order 1 (
id
= 1):flowers
. -
Order 2 (
id
= 2):flowers
. -
Order 3 (
id
= 3):flowers
,sweets
. -
Order 4 (
id
= 4):flowers
,ice-cream
.
Flowers
and sweets
are incompatible for delivery in the same vehicle. Moreover, simultaneous delivery of flowers
and ice-cream
is prohibited for vehicle 2, but simultaneous delivery of flowers
and sweets
is permitted. Then the solution will contain delivery of orders 2 and 4 in the first vehicle and delivery of orders 1 and 3 in the second vehicle.
API request (JSON) ⋅ API response ⋅ View on map
Example 2.1
You need to have 3 orders from different companies picked up and delivered. Orders 1 and 2 and orders 2 and 3 cannot be delivered together, because they belong to competing companies.
As a result of planning, the courier picks up and delivers orders 1 and 3, then returns to the depot to load and deliver order 2 as part of a new run.
API request (JSON) ⋅ API response ⋅ View on map
Example 2.2
The same as in example 2.1, but vehicle.onboard_incompatible_load_types
= true
.
As a result of planning, the courier picks up and delivers order 2, and then picks up and delivers orders 1 and 3 without visiting the depot. This means less mileage and time en route.
API request (JSON) ⋅ API response ⋅ View on map
Geofences
You can set limits for vehicles by delivery zones. You can set geofences within which the vehicle can deliver orders in the Allowed geofences field on the Vehicles sheet (vehicles.allowed_zones
in the API):
-
The vehicle can deliver orders within any geofences specified in this field.
-
If you don't specify allowed geofences, the courier can deliver orders without restrictions.
-
The order can't be delivered if all couriers have allowed geofences specified and the order location doesn't fall within any of them.
Geofences restricted for delivery are set in the field Forbidden geofences (vehicle.forbidden_zones
in the API). The courier can't deliver orders to within geofences specified in this field.
Note
If an order is located in an area that overlaps both allowed and forbidden geofences, it can't be delivered, because the Forbidden geofences field values (forbidden_zones
) take priority over Allowed geofences field values (allowed_zones
).
If certain geofences are forbidden for all couriers, use the global option options.avoid_zones
. Couriers can't make deliveries within geofences specified in vehicle.forbidden_zones
, but they can travel through them. On the contrary, couriers are restricted from even entering the geofences specified in options.avoid_zones
. For more information, see Excluded geofences.
When orders are being assigned, geofence incompatibility is taken into account: both the global option and the values set for individual couriers. When planning routes, you can also cancel all limits related to geofences.
Example
The example features 4 orders, 2 vehicles, and 4 geofences specified in the interface. Coordinates automatically determine how orders pertain to geofences:
-
Order 1 — simultaneously in
zone1
andzone2
. -
Order 2 — in
zone1
. -
Order 3 — simultaneously in
zone2
andzone3
. -
Order 4 — in
zone4
.
The availability of geofences for vehicles determined:
The courier's username. |
Allowed geofences ( |
Forbidden geofences ( |
Vehicle 1 |
|
|
Vehicle 2 |
Geofences not determined |
|
As a result, Vehicle 1 delivers Orders 1 and 2, Vehicle 2 delivers Order 4. And Order 3 remains unassigned, because its address is located in the geofences forbidden for both vehicles.
API request (JSON) ⋅ API response ⋅ View on map
Optional geofences
When assigning orders to vehicles, you can make use of optional geofences, which have bonuses or penalties associated with visiting them. You can set one or more such geofences for each vehicle.
Optional geofences represent a soft restriction. They help designate zones that are preferred for visiting (high-priority and low-priority).
Optional geofences are set using the vehicle.optional_zones
array:
optional_zones.N.zone
: Name of the geofence.optional_zones.N.value
: If the value is greater than 0, the vehicle receives a bonus for visiting the specified geofence (the value of the parameter is deducted from the route cost), and if it's less than 0, a penalty (the value is added to the route cost).
Example 1
You need to deliver 10 orders with two vehicles. For the first vehicle, the South
optional geofence is set, and for the second one, North
. Visiting these geofences carries a bonus of 1000 units. As a result, the first vehicle delivers orders in the south, and the second one, in the north. Order 5 is an exception: it belongs to the South
geofence, but was delivered by the Courier north
vehicle.
API request (JSON) ⋅ API response ⋅ View on map
Example 2
4 couriers have to deliver 27 orders. The city is divided into 4 optional geofences: Northwest
, Northeast
, Southwest
, and Southeast
. Each courier has been set one high-priority zone that carries a bonus, two low-priority zones, and one zone that carries a penalty. As a result of planning, couriers end up delivering orders in their high-priority zones. The exceptions are orders 18, 20, and 23 due to vehicle capacity limitations.
API request (JSON) ⋅ API response ⋅ View on map
Incompatible geofences
You can set geofence incompatibility in order to prevent orders belonging to different delivery zones from ending up part of the same courier run.
Using the vehicles.incompatible_zones parameter, the list of such zones can be set both for the entire solution
and for a specific courier. Incompatible zones defined for the courier take precedence over globally defined zones. In order for the global restriction options.incompatible_zones
not to apply to the courier, set an empty list in the vehicles.incompatible_zones
field.
Example
Each of the three couriers must deliver 4 orders to different parts of the city: northwest, southwest, northeast, and southeast. These areas correspond to the following geofences defined during planning: Northwest
, Southwest
, Northeast
, Southeast
.
Global geofence incompatibility has been set: southern zones (Southwest
and Southeast
) are incompatible with the northern ones (Northwest
and Northeast
). Additionally, two couriers have the vehicles.incompatible_zones
parameter set for them: for the first courier, it contains an empty list, and for the second, it makes the western zones (Northwest
and Southwest
) incompatible with the eastern ones (Northeast
and Southeast
).
As a result of planning:
Courier 1
is unaffected by the global incompatibility, and all the 4 orders from different zones get included in their run.Courier 2
is subject to the zone incompatibility restrictions set for them in thevehicles.incompatible_zones
parameter: one run includes orders to the eastern zones, and the other, to the western ones.Courier 3
is subject to the global restrictions: orders to the southern and northern zones get assigned to different runs.
API request (JSON) ⋅ API response ⋅ View on map
Vehicle or courier shifts
You can define one or more work shifts for a vehicle. Use the vehicle.shifts
field to define the shifts.
A shift is a time range when the vehicle is allowed to operate. Shift time includes the loading time at the depot, travel time, and handling time at order locations, as well as unloading time at the depot (if the vehicle returns to the depot).
To use one or more shifts in Excel, define the following fields:
-
shifts.0.time_window
: A soft time window corresponding to the vehicle's operating hours. -
shifts.0.hard_window
: Flag indicating a hard time window. If the time window is hard, the algorithm can't go outside the specified interval. -
shifts.0.service_duration_s
: Time between shifts (in seconds). For example, it can be the time needed to replace the driver or exchange documents.
You can also restrict the maximum shift duration (shifts.N.max_duration_s
and shifts.N.hard_max_duration_s)
.
In the case of a soft time window, you can set additional penalties:
-
For time window violation:
shifts.0.penalty.out_of_time.fixed
: A fixed penalty for one-time violation of the shift's time window.shifts.0.penalty.out_of_time.minute
: A penalty per minute of the shift's time window violation.
-
For early departure:
shifts.0.penalty.early.fixed
: A fixed penalty for one-time start of work before the shift's time window.shifts.0.penalty.early.minute
: A penalty per minute of work start before the shift's time window.
-
For late arrival:
shifts.0.penalty.late.fixed
: A fixed penalty for one-time work completion later than the shift's time window.shifts.0.penalty.late.minute
: A penalty per minute of work end after the shift's time window.
To limit permissible violations of the shift's time window, you can set a hard window around a soft one.
Start, end, and duration of shift
Let's say a shift's time_window
is from 9:00 to 18:00. The properties used are hard time window (hard_window
), maximum shift duration (max_duration_s
), and flexible start time from the depot (depot.flexible_start_time
).
How to plan courier's work |
Parameters |
We recommend making the work interval no more than 6 hours, strictly between 9:00 and 18:00 |
|
Start the work strictly at 9:00, preferably end it before 15:00 and strictly not later than 18:00 (this parameter combination corresponds to |
|
We recommend setting a work interval that won't last longer than 6 hours, preferably between 9:00 and 18:00 |
|
Start the work strictly at 9:00, preferably end it before 15:00 and preferably not later than 18:00 (this parameter combination corresponds to |
|
You may start work later than 9:00, finish preferably before 18:00, preferably work no longer than 10 hours |
|
Start the work strictly at 9:00, finish preferably before 18:00, but preferably no later than 19:00 (this combination of parameters corresponds to |
|
With this combination of parameters, you won't be able to plan the solution |
|
Note
Note that to define multiple shifts, you need multiple Excel fields with an increasing numeric index.
For example. shifts.0.time_window
refers to the first shift, and shifts.1.time_window
refers to the second one.
Example
The request to RouteQ includes one vehicle with three shifts (morning, afternoon, and evening) and three orders, of which one order has a delivery time in the morning, and two others in the evening.
Note
Note that the RouteQ response will only use the morning and evening shifts, since there are no delivery orders for the day shift.
API request (JSON) ⋅ API response ⋅ View on map
Courier working mode
By default, the service plans a route only with stops that are necessary for cargo delivery. However, couriers often can't work without stopping: they need to have lunch breaks, and you must take these into account when you build routes. Moreover, on long-distance runs, drivers are required to make stops at certain intervals to meet the work and rest requirements.
To control the couriers' working hours, use the vehicle.rest_schedule.breaks
object. You can set simple or complex schemes to schedule breaks for rest, maintenance, or other activities.
- For couriers, use the
vehicles.rest_schedule.breaks
object. - For shifts, use the
vehicles.shifts.N.rest_schedule.breaks
object. Shift-level breaks have priority over courier-level ones.
Example
There are two shifts for couriers:
- The morning shift includes one 45-minute break (
rest_duration_s
= 2700). - The afternoon shift has no break set.
A break of 1.5 hours is provided for couriers (rest_duration_s
= 5400).
As a result of planning:
- There's a 45-minute break scheduled for the morning shift.
- There's a 1.5-hour break scheduled for the afternoon shift.
API request (JSON) ⋅ API response ⋅ View on map
Break presets
You can set a courier's working hours using the parameter vehicles.rest_schedule_preset
, which contains a set of settings you can use right away:
-
The courier will take a 45-minute break no later than 4.5 hours of work.
-
Limits will be applied to the shift duration (excluding breaks):
-
Soft: 9 hours.
-
Hard: 10 hours.
-
Possible values for the rest_schedule_preset
parameter:
-
public_transport
: You can divide the break into multiple parts, each at least 10 minutes. -
private_transport
: You can divide the break into two parts: 15 and 30 minutes. -
multiday_private_transport
: Theprivate_transport
mode for multi-day routes. Besides regular breaks, you can also add:- Daily break: the last 11 hours of each weekday.
- Weekly break: the last 45 hours of each week.
A route break will be divided into parts if the following conditions are met:
-
There's not enough time between orders for a full break.
-
There are waiting times between orders, where you can fit breaks.
You can also prohibit couriers from splitting breaks. To do this, use the option can_split_preset_work_breaks
= false
(by default it's can_split_preset_work_breaks
= true
).
Example 1
The courier has working hours rest_schedule_preset
= private_transport
. They contain a break that can be split into two parts. There's an interval between orders that a full break can fit into. As a result, a single break of 45 minutes is scheduled.
API request (JSON) ⋅ API response ⋅ View on map
Example 2
The courier has working hours rest_schedule_preset
= public_transport
. They contain a break that can be split into multiple parts. There's not enough time between orders for a full break. There's also a waiting time that can accommodate the part of the break. As a result, 2 breaks are scheduled: 32 and 12 minutes.
API request (JSON) ⋅ API response ⋅ View on map
Example 3
The courier has working hours rest_schedule_preset
= public_transport
. The courier has 14 orders. The shift duration has a hard restriction of 10 hours. As a result, one order remained undelivered because it would have required the courier to work more than 10 hours to deliver it.
API request (JSON) ⋅ API response ⋅ View on map
Example 4
The courier has working hours rest_schedule_preset
= multiday_private_transport
. They have to deliver one order to a remote location. As a result, the courier delivers the order on the following day. They start at 8:00 and make three stops along the way:
- A 45-minute break after 1 hour and 15 minutes of travel.
- An 11-hour break from the end of the workday to 8:00 the next day.
- A 45-minute break after 4 hours and 30 minutes of travel.
API request (JSON) ⋅ API response ⋅ View on map
Schedule templates
You can describe breaks for each courier separately or create templates for multiple couriers or for a shift. Moreover, you can combine individual and template schedules.
To create a template, add the template_rest_schedules
parameter to options
and specify an array of schedules in it: [{"id": string, "breaks": [...]}]
.
To use a courier-level template, add the rest_schedule_id
parameter to vehicles
and specify the id
of the schedule template from options
in that parameter. To use a shift-level template, add the mentioned parameter to vehicles.shifts.N
.
Break duration
You can set the break duration using the rest_duration_s
parameter mandatory for every break.
Parameter |
Value |
Example |
|
Break duration in seconds. |
The break should last 10 minutes (600 seconds). |
Break start conditions
The break start is indicated by a time range (from and to). If there are multiple breaks, each range specifies the working range after the end of the previous break. For example, if the first break is 04:00–05:00
and the second break is 02:00–03:00
, the first break must start between 4 and 5 hours after work starts, and the second break must start between 2 and 3 hours after the end of the first break.
You can set the conditions for starting a break in several ways, which are described below.
Parameter |
Value |
Example |
|
Soft time window for a break. |
|
|
Hard time window for a break. |
|
|
Preferred time until break.
|
|
Break types
Additional time intervals affect the start of the break that's set using time windows or the desired_work_duration
parameter. For example, the courier should work for several hours before they can rest. To take additional time into account, specify the value of the break_type
parameter.
Value |
Description |
|
Working hours from the start of the route. Includes travel time, waiting time, and handling time for orders and depots. |
|
Default value. |
|
Travel time and waiting time from the start of the route. Handling time is not taken into account. |
|
Travel time and waiting time from the completion of the previous order. Handling time is not taken into account. |
|
Travel time from the start of the route. Waiting time and handling time are not taken into account. |
|
Break start time. The break can't be repeated. |
You can set the break_type
and penalty
values in break schedule templates (rest_schedule.break_type
, rest_schedule.penalty
), as well as in the settings of each break (rest_schedule.breaks.break_type
, rest_schedule.breaks.penalty
).
If break_type
is specified in the break schedule templates, then the break_type
value in the settings of this break:
- Must be the same.
- May be not specified. In this case, the settings from the schedule templates will apply to the break.
If break_type
is not specified in the schedule templates, you can set different break_type
values for different breaks in their settings.
Example
A courier needs to deliver eight orders during his shift from 09:00 to 17:00. There are two breaks.
The first break is scheduled from 11:00 to 12:00. It started two hours after the courier started his work, which corresponds to the hard time window hard_time_range
= 1:30 – 3:30
. The first break is planned from the start of the shift.
The second break is scheduled after the first one from 13:35 to 14:45, which also fits within the constraints of the hard time window hard_time_range
= 1:00 – 2:00
.
At the same time, the working interval between the first break and the second one got as close as possible to the desired duration (desired_work_duration
= 1:45
) and amounted to 1 hour and 35 minutes.
API request (JSON) ⋅ API response ⋅ View on map
Using different break types
You can set different break types (break_type
) in a single schedule. Other breaks and their duration don't affect the breaks scheduled from the start of the route (from_start
) and at a specific time (exact
).
Example
A courier must deliver 11 orders. There are three breaks:
- The first one lasts 15 minutes and starts after two hours of work (
from_last
=02:00 - 02:15
). - The second one starts after four hours of work (
from_start
=04:00 - 04:15
). - The third one is a fixed break from 13:30 to 14:00 (
exact
=13:30 - 14:00
).
API request (JSON) ⋅ API response ⋅ View on map
Splitting breaks
You can split the break into smaller parts if needed. For example, if there's not enough time between orders for a full break. To do this, specify the parameter can_be_split
= true
in the breaks
schedule.
You can also specify additional parameters for the split break:
Parameter |
Value |
Example |
|
The parameter determines how many parts the break will be split into. By default, it's 2 parts. |
You can split the break into 5 parts. |
|
The minimum duration of a single part of the break. Set in seconds. By default, it's 10 minutes. |
You can split the break into parts with a minimum duration of 20 minutes (1200 seconds). |
|
The parameter specifies the minimum duration of the first part of the break. Set in seconds. By default, this is 1/3 of the total break duration. |
The first part of the break should last at least 30 minutes (1800 seconds). |
|
The parameter specifies the minimum duration of the final part of the break. It is set in seconds. By default, this is 2/3 of the total break duration. |
The final part of the break should be at least 40 minutes (2400 seconds). |
The sum of the parts of a split break can exceed its total duration.
The maximum number of parts is specified in the max_split_parts
parameter. Their duration must meet the conditions:
- The first part is no less than
min_first_split_part_duration_s
. - The last part is no less than
min_last_split_part_duration_s
. - Each part is no less than
min_split_part_duration_s
.
When splitting, initial break time decreases. It may turn out that the remainder for allocating the last part of the break will be less than specified in min_last_split_part_duration_s
. In this case, the minimum necessary value that's needed to comply with the min_last_split_part_duration_s
restriction will be automatically added to it.
Example 1
For the courier, one break of 2 hours is provided: "rest_duration_s": 7200
. The first three orders have narrow time windows, so you can fill the waiting time between them with breaks. Since there isn't enough time between orders for a full break, it's split into 3 parts.
API request (JSON) ⋅ API response ⋅ View on map
Example 2
The total break duration rest_duration_s
is two hours (rest_duration_s
= 7200). It's split into two parts (max_split_parts
= 2). At the same time:
min_split_part_duration_s
= 2400 (40 minutes).min_first_split_part_duration_s
= 4800 (1 hour 20 minutes).min_last_split_part_duration_s
= 2400 (40 minutes).
The first part (1 hour 20 minutes) is split from the total break time. 40 minutes of the initial break remain. The second part (40 minutes) is split from them.
As a result, the sum of the break parts will not exceed its total duration and will amount to two hours (7200 seconds).
API request (JSON) ⋅ API response ⋅ View on map
Example 3
The same as in example 2, but the duration of the second part of the break is increased by 5 minutes (min_last_split_part_duration_s
= 2700).
The first part (1 hour and 20 minutes) is split from the total break time. 40 minutes of the initial break remain. The second part must be split from the remaining 40 minutes, but min_last_split_part_duration_s
= 2700 (45 minutes). The remaining time can't be negative, so the duration of the second part will be increased to 45 minutes to minimally comply with the condition min_last_split_part_duration_s
= 2700.
As a result, the sum of the duration of the break parts will exceed the initially set duration by 5 minutes, amounting to 2 hours and 5 minutes (7500 seconds).
API request (JSON) ⋅ API response ⋅ View on map
Breaks during order handling
Parameter |
Value |
Example |
|
Break parameter. Determines whether this break can overlap with the handling time of the order or the depot. Default value is |
|
|
Order or depot parameter. Determines whether this break can overlap with the handling time of this order or depot. Default value is |
|
By default, breaks can overlap with the handling time of an order or depot. In routes, these breaks are indicated before the order or depot. The start time arrival_time_s
and end time departure_time_s
of the break coincide with the arrival_time_s
and departure_time_s
of the order or depot. Inside this overall interval, the handling time duration is determined by the parameter service_duration_s
. In the response for such an order or depot, the field is_after_service_work_break
= true
is added to indicate that handling starts after the break.
If can_rest_during_service
= true
, the break can be scheduled as the first location in the shift. For regular breaks that don't overlap with the handling time, this is impossible.
To prevent breaks from overlapping with the handling time, set can_have_rest_during_service
to false
for the order or depot and can_rest_during_service
to false
for the break.
Example 1
A 50-minute break should be scheduled 1.5 hours after the start of the route. There are 2 orders in the route, with a handling time of 1 hour and the parameter can_have_rest_during_service
= true
. The break overlaps with the handling time for the first order, for which the courier arrives 1 hour and 8 minutes after the start of the route and leaves 2 hours and 20 minutes later.
API request (JSON) ⋅ API response ⋅ View on map
Example 2
The same as in example 1, but orders have the parameter can_have_rest_during_service
= false
. The break is scheduled at the first order's location, but before handling the order and too early: just 1 hour and 9 minutes after the start of the route.
API request (JSON) ⋅ API response ⋅ View on map
Break chains
The rest_schedule
can contain many independent breaks
break chains. Each chain can contain many breaks with special conditions. The start of a break in every chain depends only on the built route. It doesn't depend on breaks in other chains.
Example |
Explanation |
Can be set |
Chain 1: Rest for 15 minutes after every 3 hours of transit. Chain 2: Rest for 6 hours 8 hours after the shift started. |
Breaks in chain 2 depend only on the shift start. They don't depend on the transit and rest schedule in chain 1. |
|
Chain 1: Rest for 15 minutes after every 3 hours of transit. Chain 2: Rest for 6 hours after every 8 hours of transit. |
The start of the break in chain 2 depends on the transit and rest schedule in chain 1. |
|
The order of chains doesn't matter, but you must specify breaks in one chain sequentially.
If the route is completed before the stop (for example, the route is completed in 3 hours, and the stop is scheduled after 4 hours), all the unmade stops are reset.
Example
The route is built with 30-minute rest breaks after 4–4.5 hours of work. 15 hours after the start of the route, a sleep break is planned. As a result, a sleep break is scheduled 1.5 hours after a rest break.
API request (JSON) ⋅ API response ⋅ View on map
Penalties
In some cases, RouteQ can plan routes that violate the rest window. To apply penalties for such violations, use the fields penalty.late
and penalty.early
. If the penalty is higher than the savings resulting from the window violation, the route is planned without violations.
Parameter |
Value |
Example |
|
Penalty for an early break start. |
Sets a penalty of 1000 for an early break. |
|
Penalty for every minute of an early break. |
Sets a penalty of 17 for every minute of an early break. |
|
Penalty for a late break. |
Sets a penalty of 1000 for a late break. |
|
Penalty for every minute of a late break. |
Sets a penalty of 17 for every minute of a late break. |
Repeat conditions
Parameter |
Value |
Example |
|
The parameter specifies that the break should be repeated. The quantity and order of repeated breaks within a shift can vary. First, the algorithm allocates all the breaks from the schedule. After that, it repeats them in the same order in which they were planned. |
The break will be repeated before the shift end. |
Example 1
The courier delivers orders to a neighboring city and periodic breaks. Breaks are set every 60–80 minutes of the route (travel_time_range
) using the repeat condition repeatable
. As a result, the algorithm scheduled two breaks.
API request (JSON) ⋅ API response ⋅ View on map
Example 2
Same as in example 1, but the route extends over several days, with sleep breaks scheduled every 12 hours:
-
The repeat condition
repeatable
is used. -
The minimum and maximum route duration before rest
travel_time_range
:"12:00–12:00"
.
API request (JSON) ⋅ API response ⋅ View on map
Example 3
A courier delivers orders containing chemicals, so they need to take a 30-minute break every two hours.
As a result, three breaks are scheduled:
-
Two breaks lasting 30 minutes every two hours of the route set with the
repeatable
condition (hard_time_range
). -
One-hour lunch break.
API request (JSON) ⋅ API response ⋅ View on map
Support discontinued
Break place
Parameter |
Value |
Example |
|
An option to have a break in a location with the |
All breaks will take place in locations with the |
The courier can't visit break locations that are situated within the geofences that are restricted for them.
You can set requirements for visiting a break location with the rest_place
type using the incompatible_load_types
parameter (see Order incompatibility). For example, a courier is delivering an order with the load_type
= ice-cream
type, and the rest_place
location's type is load_type
= no-refrigerator
. To restrict the courier from visiting this location for a break, set ice-cream
as incompatible with no-refrigerator
on the Incompatible_load_types sheet.
Example
Two couriers have 19 orders scheduled for them. The first courier should rest every 2–3 hours, and the second should rest every 3–4 hours. Both couriers have the same rest location specified for them: type rest_place
.
The first courier starts the route at 7:00 and arrives to the rest location at 9:48, where they rest for 30 minutes before continuing on the route. The second courier starts their route at 8:00 and manages to complete all of their orders before 12 without stopping to rest.
API request (JSON) ⋅ API response ⋅ View on map
Combining breaks conditions
Parameter |
Value |
Example |
|
The possibility of combining a break with other breaks before the first order. The break can only be combined with the breaks whose types are specified in |
The break will be combined with the last break before the first location where the break type is specified in |
|
The possibility of combining a break with other breaks after the last order. The break can only be combined with the breaks whose types are specified in |
The break will be combined with the first break after the last location where the break type is specified in |
|
Break type. |
A lunch break. |
|
The parameter sets which break types can be combined with the specified break. You can only use it in combination with |
You can combine this break with a lunch or a sleep break. |
Break planning conditions
You can specify additional parameters: make a break mandatory or set the minimum working time for the break start.
Parameter |
Value |
Example |
|
The time from the start of the route after which a break must be made. Set in seconds. |
Be sure to start the break after 4 hours (14,400 seconds) have passed from the route start. |
|
The parameter sets the minimum working time at which a break should be scheduled. If the total working time is less, a break isn't scheduled. Set in seconds. |
Start the break only if the route lasts at least 4 hours (14,400 seconds). |
Break start conditions
The conditions set in the old format are incompatible with the new conditions. For example, you can't simultaneously specify the values of the work_time_range_till_rest
and soft_time_range
fields.
Parameter |
Value |
Example |
|
Working hours from the start of the route. Includes travel time, waiting time, and handling time for orders and depots. The presence and duration of other breaks are not taken into account. |
Start the break no earlier than in 1 hour and no later than 3 hours after the start of the route. |
|
Working hours from the last break (or from the start of the route if it's the first break). Includes travel time, waiting time, and handling time for orders and depots. |
Start the break no earlier than 2 hours and no later than 4 hours after the shift start (including arrival at the depot, handling time, periods of travel and waiting). |
|
Travel time and waiting time from the start of the route. Handling time is not taken into account. |
Start the break no earlier than 1 hour and no later than 3 hours after the start of the route, taking into account periods and travel and waiting and without taking into account handling time at order locations and at the depots. |
|
Travel time and waiting time from the completion of the previous order. Handling time is not taken into account. |
Start the break no earlier than in 2 hours and not later than after 3 hours of continuous travel. |
|
Travel time from the start of the route. Waiting time and handling time are not taken into account. |
Start the break no earlier than 1 hour and no later than 3 hours from the start of the continuous travel. |
|
Break start time. The break can't be repeated. The work start time, the presence and duration of other breaks don't matter. The break won't start if the route ends before the break start time. |
Start a break from 17:00 to 20:00. |
Example 1
We built a route with a lunch break after 4–5 hours of work in this example. As a result, the algorithm schedules a lunch stop for a courier.
API request (JSON) ⋅ API response ⋅ View on map
Example 2
In this example, a route is built between Moscow and St. Petersburg with the first break after 4-4.5 hours, and then with breaks every 2 hours. The algorithm scheduled two breaks.
API request (JSON) ⋅ API response ⋅ View on map
Example 3
For two couriers a break is set with the work_time_range_from_start
condition in 3–4 hours after the start of work, but only if the total duration route_duration_s
is at least 6 hours. The first courier finishes work in 5 hours, so they work without rest. The second courier works for more than 6 hours, so they get one break.
API request (JSON) ⋅ API response ⋅ View on map
Example 4
10-minute breaks are set for every 55–60 minutes of continuous traveling continuous_travel_time_range
. As a result, a break is scheduled only between points where the travel time is more than 55 minutes.
API request (JSON) ⋅ API response ⋅ View on map
Example 5
For couriers, two breaks with the break start condition work_time_range_till_rest
are scheduled for 2–3 hours after the last break or start of work if this is the first break.
-
The first break is 20 minutes.
-
The second break is 30 minutes.
The first courier finishes work earlier and gets only the first break. The second courier works longer and gets both breaks.
Planned route
The user can specify which courier should deliver particular orders. This is useful:
-
For additional planning when you have pre-planned routes.
-
When the order requires a specific courier.
To specify pre-planned orders for the courier, use the vehicle.planned_route
option. This option has the following properties:
-
When planning, all orders that you specify in
vehicle.planned_route
can't become unassigned, even if strict restrictions are violated, such as vehicle capacity or time windows for whichhard_window
=true
. -
By default, the order sequence set in
planned_route
isn't fixed. When re-planning, orders can be arranged in a new sequence. -
If you need to save the route that's specified in
planned_route
without saving changes (sequence changes and adding new orders), usevehicle.fixed_planned_route
=true
.
For each order in planned_route
, be sure to specify the vehicle shift (even if the vehicle only has 1 shift).
If in planned_route
several shifts are specified, you can lock orders for shifts using the fix_planned_shifts
= true
option. By default, the value is false
.
If a courier arrives too early, delivery time of the order is determined by the vehicle.wait_if_early
parameter:
true
: The courier waits for the order time window to start (default value).false
: The courier handles the order as soon as they arrive.
Alert
If there is a hard time window for an order location.hard_window
= true
, the vehicle.wait_if_early
parameter value is true
.
If the courier needs to visit depots for reloading while following the route, specify them in the middle_depot_id
field. They may be the same as the depots the courier visits at the start or at the end of the route.
If the courier needs to visit depots for reloading in planned_route
, set is_middle_depot
= true
(it's false
by default). If you set is_middle_depot
= true
for all depots, the algorithm will plan the start and end depots based on the courier settings (see sections Start from one of several depots and Returning to a depot at the end of the route or run).
Example 1
Both couriers had pre-planned orders in planned_route
. As a result, these orders were given to these two couriers.
API request (JSON) ⋅ API response ⋅ View on map
Example 2
This example involves 1 vehicle that has orders linked to it via planned_route
. The total weight of the orders exceeds the vehicle capacity, but the route is still being planned (because orders specified in this option can't be unallocated). But the ask status is UNFEASIBLE
.
API request (JSON) ⋅ API response ⋅ View on map
Example 3
Theoretically, 2 couriers could deliver all 20 orders without overload and without being late. But a fixed sequence is specified for courier 1 using the vehicle.fixed_planned_route
= true
parameter, so they'll only deliver orders from this sequence. Courier 2 isn't limited by a strict plan, so they'll take as many orders as they can carry. Several orders will remain in the depot, despite the fact that courier 1 has the space and time.
API request (JSON) ⋅ API response ⋅ View on map
Example 4.1
2 couriers need to deliver 15 orders in 2 shifts. Using the planned_route
option, orders 1-8 are assigned to courier 1, and orders 9-15 to courier 2. At the same time, it's indicated that orders 1-4 and 9-12 must be delivered during the first shift, and orders 5-8 and 13-15 during the second shift. Since fix_planned_shifts
= false
and couriers manage to deliver all orders within one shift, the distribution of orders by shifts is not taken into account.
API request (JSON) ⋅ API response ⋅ View on map
Example 4.2
The conditions are the same as in example 4.1, but the option fix_planned_shifts
= true
. This means the shifts during which orders have to be delivered are taken into account.
API request (JSON) ⋅ API response ⋅ View on map
Loaded orders
If the order is already in the vehicle, the courier can immediately start delivery. To run this scenario, specify the parameters in the planned_route
field:
Parameter |
Description |
Value |
|
List of order |
|
|
All orders loaded to the vehicle should be serviced during the same run before the vehicle returns to the depot. |
|
|
The vehicle will visit all depots in Use if:
|
|
* Specified for depots and orders of the garage
type.
Example
Several orders were loaded in the courier's vehicle last night. The courier doesn't have to pick them up at the depot. Therefore, the point of the garage
type is specified in the place where the courier will go.
The loaded_orders
parameter shows that orders 1 and 2 have been loaded. The courier can immediately deliver them to the destination.
The following parameters are also set in the conditions:
-
planned_runs_first
=true
. -
delivery_in_current_run
=true
for depot and garage.
The courier starts from the garage and immediately delivers orders 1 and 2. They then go to the depot to pick up orders 3 and 4, which they must deliver immediately after loading. After these two deliveries, the courier returns to the depot to pick up orders 5 and 6 and follows the route further.
API request (JSON) ⋅ API response ⋅ View on map
Fixed part of the route
The visited_locations
feature is useful if:
-
The beginning of route must follow a particular path.
-
You need to change the start point when doing additional planning.
The route must be fixed for each courier individually.
To do this, specify the visited_locations
array in vehicles
and describe the points of the fixed route using the following parameters.
Parameter |
Description |
|
Order ID from |
|
ID of the courier shift from |
|
The time of departure from the point. If the first point of a fixed part of the route:
You can specify this parameter for several orders, so that the visit time is calculated according to the time specified in |
|
The need to wait for the start of the time window in case of early arrival.
|
* Required parameter
Example 1
There are 5 orders in this example. The sequence of orders 1, 2, 3 is fixed in visited_locations
. Orders 4 and 5 can be delivered in any sequence.
API request (JSON) ⋅ API response ⋅ View on map
Example 2
In visited_locations
, it's specified that the route must start with order 2 at 10:00.
API request (JSON) ⋅ API response ⋅ View on map
Example 3
The order sequence 1, 2, 3 is set as in example 1. It's also specified that departure from order 1 must be at 08:20 and from order 3 at 11:00.
API request (JSON) ⋅ API response ⋅ View on map
Example 4
There are 8 orders in this example. The specified sequence is orders 1, 2, 3, then the depot, then order 4. The courier may deliver the remaining orders in any sequence.
API request (JSON) ⋅ API response ⋅ View on map
Adjusting the vehicle's moving time
To calculate the speed of a vehicle when building a route, RouteQ uses Yandex Maps data about traffic and the speed factor specified in the request. Although trucks usually move slower in traffic jams, some drivers drive more aggressively and arrive earlier than the calculated timeframes.
To compensate for such deviations, RouteQ has the travel_time_multiplier
option where you can specify a fractional value. If the value is 1, the calculation is made for the vehicle with the expected average speed. At smaller values (for example, 0.8), the calculation accounts for faster vehicles. At higher values (for example, 1.2), the calculation accounts for slower vehicles.
Note
The travel_time_multiplier
parameter only affects the vehicle speed. The handover time at the delivery point remains the same.
Example 1
In the example below, the routing request is sent without adjusting the transit time. As a result, the vehicle delivers the order in 4 hours and 20 minutes, with 3 hours and 40 minutes spent moving between the points.
API request (JSON) ⋅ API response ⋅ View on map
Example 2
The same as in example 1, but with the travel_time_multiplier
parameter set to 0.5. In the resulting route, the courier delivers the order in 2 hours and 25 minutes, spending 1 hour and 45 minutes moving between the points. However, time spent on parking and handover remains unchanged.
API request (JSON) ⋅ API response ⋅ View on map
Example 3
The same as in example 1, but with the travel_time_multiplier
parameter set to 2. In the resulting route, the courier delivers the order in 7 hours and 58 minutes, spending 7 hours and 18 minutes moving between the points. Traveling the route takes more than twice as long as in example 1, because part of the route occurs at peak hours, and the vehicle can't drive at the maximum speed. Time spent on parking and handover remains unchanged.
API request (JSON) ⋅ API response ⋅ View on map
Adjusting handling time
To the courier needs some time to hand over the order on arrival. This time includes parking, riding the elevator, handing over the delivery, and paperwork. RouteQ ensures that by using the order's service_duration
and shared_service_duration
fields. However, some couriers deliver goods faster than others. For example:
-
In the case of parallel planning for vehicles and couriers using public transport, couriers who travel by public transport don't have to spend time parking. As a result, they need lower handling time.
-
Some couriers are faster than others. Experienced couriers usually spend less time handing over orders.
To compensate for the difference in courier time, RouteQ has the service_duration_multiplier
and shared_service_duration_multiplier
options that affect the handling time for a specific courier. If the value is 1, the handling time is the same as in service_duration
or shared_service_duration
. If the value is less than 1, the handling time is lower. If the value is greater than 1, the handling time is higher.
Note
The service_duration_multiplier
and shared_service_duration_multiplier
parameters only affect the handling time. The transit time between the points remains the same.
Example 1
In the example below, the routing request is sent without adjusting the handling time.
API request (JSON) ⋅ API response ⋅ View on map
Example 2
In the example below, the same request is sent to RouteQ as in example 1, but with the service_duration_multiplier
parameter set to 0.5. The calculated service order is half the time specified in example 1.
API request (JSON) ⋅ API response ⋅ View on map
Example 3
In the example below, the same request is sent to RouteQ as in example 1, but with the service_duration_multiplier
parameter set to 2. Handling time is twice as long as in example 1.
API request (JSON) ⋅ API response ⋅ View on map
Prompt delivery
To build an optimal route, the algorithm minimizes the wait time between route points. But there are cases when it's useful to shift delivery to an earlier time. For example:
- You have to minimize the risk of late arrival.
- It's more comfortable for the courier to travel in the daytime.
To deliver goods as early as possible, use the penalty.arrival_after_start
penalty, which consists of two parameters:
average_h
: Sets the penalty amount for the average arrival time after the start of the time window. When using the option, we always recommend specifying this value.as_soon_as_possible
: Determines whether to start the route as early as possible. The parameter takes the valuetrue
orfalse
(by default). It is specified in addition toaverage_h
.
Note
The algorithm can shift the start and arrival time of a vehicle only if the flexible start time is enabled for the depot.
If you don't use the penalty.arrival_after_start
penalty, the route will be built with the minimal wait time between points and the latest possible start time from the depot.
When using the penalty, the algorithm will build routes to start them earlier, provided it doesn't reduce quality.
If the route must start as early as possible (even if it causes additional waiting), specify penalty.arrival_after_start.as_soon_as_possible
= true
.
Example 1
The route includes 4 orders with different time windows. The earliest start of the time window for order 5 is 08:00. The courier starts from the depot at 11:02 and arrives at the first delivery point at 11:40. Order 5 is delivered at 12:59.
API request (JSON) ⋅ API response ⋅ View on map
Example 2
The same data is used as in example 1, but the penalty is set for the average arrival time after the start of the time window using the penalty.arrival_after_start.average_h
parameter. The courier starts from the depot at 06:59, waits for 8 minutes, and then delivers the earliest order (order 5) at 08:00.
API request (JSON) ⋅ API response ⋅ View on map
Example 3
The same data is used as in example 2, but the penalty.arrival_after_start.as_soon_as_possible
= true
parameter is additionally set. The courier starts from the depot at 06:00, waits for 1 hour and 7 minutes, and delivers the earliest order (order 5) at 08:00.
API request (JSON) ⋅ API response ⋅ View on map
Trailers
A trailer is a truck with a trailer attached. Orders can be placed in both the truck and trailer. An order can be partially loaded in the truck and in the trailer.
To describe the trailer, use the trailer
object.
Field |
Description |
|
The trailer carrying capacity is described by the fields:
Added to the truck's carrying capacity. |
|
Amount of custom units a trailer can carry. Carrying capacity in custom units is set in
If the unit name is present in deliveries or other vehicles, but not in this one, the capacity is assumed to be unlimited. |
|
The trailer loading limit is described by the fields:
|
|
The trailer dimensions are described by the fields:
The values are expressed in meters. * Required parameter |
|
Trailer volume in cubic meters. If both metric dimensions and volume are specified for the trailer, then |
|
The maximum difference in the load of the trailer and the truck is described by the following fields:
If one of the fields is omitted, there are no restrictions on it. There are physical limitations to the difference between the trailer load and the truck load. If the truck is empty and the trailer is heavy, the vehicle becomes uncontrollable and can't be driven. |
|
The maximum allowable difference in the quantity of custom units loaded in the trailer and the truck. The permissible difference in custom units is set in
If the unit name is present in deliveries or other vehicles, but not in this one, there is no restriction. |
|
The trailer cost is described by the fields:
Added to the cost of the truck if the trailer is used. |
|
Time to decouple the trailer in seconds. Only for orders with the |
|
Time to couple the trailer in seconds. Only for orders with the |
|
Penalty for each reloading* of cargo from the trailer to the truck. * Reloading means moving orders from a trailer to the truck to deliver them to non-accessible locations (see Using a trailer). |
|
The time for reloading cargo from the trailer to the truck, set in seconds. It can be described by the following fields:
If multiple time types are specified, use the one that spends the most time. If no type is specified, use only the fixed time.
|
Sample trailer description in a request:
{
"trailer": {
"capacity": {
"weight_kg": 10000,
"units": 200
},
"max_capacity_difference": {
"units": 10,
"weight_kg": 0
},
"cost": {
"fixed": 1000,
"km": 10
},
"decoupling_time_s": 300,
"coupling_time_s": 300,
"rolling_time": {
"fixed_time_s": 3000
}
}
}
For more information about using a truck with a trailer, see Using a trailer.
Default value.