Vehicle properties
- Vehicle or courier ID
- Vehicle or courier capacity
- Vehicle properties
- Load handling time at depot
- Vehicle started not from the depot
- Start from one of several depot
- Additional loading at an intermediate depot
- Return to a depot at the end of the route or run
- Start or end of the route as close to the depot as possible
- Vehicle or courier shifts
- Multiple courier runs per day
- Limit the number of stops per shift
- Maximum shift duration
- Maximum mileage per shift
- Route grouping
- Vehicle or courier cost
- Advanced cost settings
- Calculation of the courier's payout
- Vehicle tags
- Order incompatibility
- Geofences
- Transportation method
- Courier working hours
- Planned route
- Fixed part of the route
- Adjusting the vehicle's travel time
- Adjusting handling time
- Prompt delivery
- Trailers
- Minimum order weight for a vehicle
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. The ID must be unique within a single service request. This identifier is used as the courier's username 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.
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
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
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 the depot, specify one of the following parameters:
— depot_id
to link orders to the 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
Start from one of several depot
A courier can start from one of several depots. These depots have to be listed in the depot_id
field (depots that the courier can visit) or starting_depot_id
(depots from which the courier can start their route). These lists can overlap. 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
You can't specify both regular depots and cross dockings in the vehicle.depot_id
and vehicle.starting_depot_id
fields. The courier may visit either regular depots or cross dockings in a single route.
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.
You can additionally set the allow_different_depots_in_route
and max_middle_depots
parameters for a courier. For more information, see Choosing the optimal depot to start from.
Additional loading at an intermediate depot
For a courier to be able to visit additional depots for reloading orders while following the route, set the allow_different_depots_in_route
= true
parameter. These depots have to be listed in the depot_id
field (depots that the courier can visit) or middle_depot_id
(depots for reloading). Depot lists can overlap. If there are orders in several depots, the algorithm will select the optimal depot for reloading.
Alert
You can't specify both regular depots and cross dockings in the vehicle.depot_id
and vehicle.middle_depot_id
fields. The courier may visit either regular depots or cross dockings in a single route.
If the courier can stop at intermediate depots for reloading only at the beginning of the route (before completing the first order), set depots_only_at_run_beginning
= true
(the default is false
).
You can additionally set the max_middle_depots
parameter for a courier. For more information, see Visiting an additional depot.
Return 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 visit several depots along the route, set allow_different_depots_in_route
= true
. In this case, the courier can end the route at a depot other than the first one.
Depots where a courier can end their route are specified in the depot_id
field (depots that the courier can visit) or ending_depot_id
field (depots from which the courier can complete their route). These lists can overlap. If there are several depots, the algorithm will choose the optimal depot to complete the route at.
Alert
You can't specify both regular depots and cross dockings in the vehicle.depot_id
and vehicle.ending_depot_id
fields. The courier may visit either regular depots or cross dockings in a single route.
To have the courier end the route at the same depot where they started, set finish_route_in_starting_depot
= true
(the default is false
). If the courier starts the route not from a depot (visit_depot_at_start
= false
), they are to return to the depot they stopped at during the second run of the route.
To have the courier end each run at the same depot where that run started, set finish_run_in_starting_depot
= true
(the default is false
). To allow the courier to change depots between runs, set can_change_depot_between_runs
= true
(see Start of a new run from a different depot).
Note
Parameters finish_route_in_starting_depot
= true
and finish_run_in_starting_depot
= true
are only viable if allow_different_depots_in_route
= true
.
If the courier doesn't have to return to the depot after all the orders are completed, use the return_to_depot
= false
option.
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 the route at the same depot where they started (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
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
: Soft time window corresponding to the vehicle's operating hours. -
shifts.0.hard_window
: Hard time window flag. 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 time 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, end it preferably before 15:00, or before 18:00, if necessary, but strictly no later than that (this parameter combination corresponds to |
|
We recommend making the work interval no more than 6 hours, preferably between 9:00 and 18:00 |
|
Start the work strictly at 9:00, preferably end it before 15:00, or before 18:00, if necessary, and preferably not later than that (this parameter combination corresponds to |
|
Can start the work later than 9:00, preferably end the work before 18:00, preferably make work no longer than 10 hours |
|
Start the work strictly at 9:00, preferably end the work before 18:00, and preferably no later than 19:00 (this parameter combination corresponds to |
|
This combination of parameters won't let you plan a 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
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
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 limit 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
Route grouping
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 grouping. For more information about this option, see Grouped 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 insufficient route grouping.
Other ways to group orders geographically
- You can use the
global_proximity_factor
option to build grouped 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. The geofence restriction can't be violated. In contrast, the route grouping 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 grouped. 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 the HTTP request.
Keywords for route parameters
Group |
Keyword and explanation |
Runs |
|
Shifts |
|
Orders and stops |
|
Duration |
|
Distance |
To set the preferred area of work for a vehicle so that the route includes orders near a certain location, use the |
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 walking parts depends on 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
is calculated based on other data received when solving the problem (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 |
+, -, *, / |
Brackets |
(…) |
Mathematical functions |
|
Logical functions |
|
Comparison operations |
<, >, = |
Logical operations |
|
Functions |
|
Function conditions |
The following functions can only be used inside the
|
Expression examples
500 + 500 * has_location(in_zone('West'))
: If the route has a stop in theWest
zone, the expression returns 1000. Otherwise, it returns 500.450 * location_count(in_zone('West') | in_zone('North'))
: Counts the number of stops in at least one of the two zones (West
andNorth
) 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 the vehicle or courier have advanced cost settings set, you'll see the following fields in the solution metrics:
run_custom_cost
: The cost of the run calculated using thecost.run
formula.shift_custom_cost
: The cost of the shift calculated using thecost.shift
formula. Shown only for the first run of the shift.shift_total_custom_cost
: The total cost of the shift. It includes the cost of the shift calculated using the formula plus the cost of all the shift's runs. Shown only for the first run of the shift.route_custom_cost
: The cost of the route calculated using thecost.route
formula. Shown only for the first run of the route.total_custom_cost
: The full cost of the route, including the cost of the route calculated using the formula plus the cost of all the shifts. Shown only for the first run of the route, the other runs have it as 0.
Example 1
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 2
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 |
6000 |
No more than 450 km |
530 |
7000 |
No more than 750 km |
550 |
8500 |
More than 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
- The 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 of 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 3
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 4
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 5
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')))*100,000,000
You can't assign incompatible order types here, because compatibility restrictions only apply within one geofence.
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. Tags can be separated by commas in strings. 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 the 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 customers 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 is the same at all points — 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
in vehicle 2 is prohibited, 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 delivery 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 are prohibited from making 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 assigning orders, the algorithm takes into account geofence incompatibilities — both set by the global option and specified for individual couriers. When planning routes, you can also cancel all geofence restrictions.
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:
Courier username |
**Allowed geofences ** ( |
Forbidden geofences ( |
Vehicle 1 |
|
|
Vehicle 2 |
Geofences not defined |
|
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 zones 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 delivery (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, you can set the list of such zones 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.
Alert
When planning in Excel, for the global zone incompatibility restriction not to apply to the courier, put a space in the incompatible_zones.N
cells for them (it corresponds to an empty list).
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
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 options.routing_mode
routing option.
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.
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
Courier working hours
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 mode, use the vehicle.rest_schedule.breaks
object. You can describe simple or complex patterns of rest and maintenance breaks and other activities.
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.
-
Restrictions 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 limit 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 separately for each courier or create templates for multiple couriers. 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 the template, add the rest_schedule_id
parameter to vehicles
and specify id
of the schedule template from options
in it.
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 the time range (from and to). You can set the break start in several ways that are indicated in the table below.
Parameter |
Value |
Example |
|
Working hours from the start of the route. Includes: travel time, waiting time, and handling time at order locations and at the depots. The presence and duration of other breaks don't matter. |
Start the break no earlier than 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 at order locations and at the depots. |
Start the break no earlier than 2 hours and no later than 4 hours after the start of the shift (including arrival at the depot, handling time, and 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 the periods of waiting and travel and not counting handling time at order locations and at 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 2 hours and no 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 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. |
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.
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 start of the route. |
|
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). |
Combining breaks conditions
Parameter |
Value |
Example |
|
The possibility to combine 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 to combinу 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 with which break types you can combine the specified break. You can only use it in combination with |
You can combine this break with a lunch or a sleep break. |
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. 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). |
Example
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
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: |
|
|
Order or depot parameter. Determines whether this break can overlap with the handling time of this order or depot. Default value: |
|
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 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.
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 |
How to 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. |
|
A 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. |
|
A 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. It can only be used for the last break in the chain. |
The break will be repeated before the shift end. |
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
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 5
As in example 4, but the route lasts several days, and breaks are set for sleep 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 6
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 7
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.
API request (JSON) ⋅ API response ⋅ View on map
Example 8
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
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 starting and ending depots based on the courier settings, see sections Start from one of several depot and Return 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 unassigned). 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 |
|
Courier shift ID 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 travel time
To calculate the speed of the vehicle when building a route, RouteQ uses Yandex Maps data about traffic and the speed specified in the request. Although the 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:
It's added to the truck carrying capacity. |
|
The trailer carrying capacity in custom units of measurement. It's set in the
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 the trailer has both the size and volume specified, then |
|
The maximum difference in the load of a trailer and a 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 go. |
|
The maximum permissible difference in the loaded number of custom units between 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:
It's added to the truck cost 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 rolling* of cargo from the trailer to the truck. * Rolling means moving orders from a trailer to a truck to deliver them to non-accessible locations (See Using a trailer). |
|
The time to roll cargo from a trailer to a truck is 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.
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 deliver 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
Default value.