What is fleet routing?
Fleet routing, also known as a vehicle routing problem (VRP), is the process of determining the most effective routes for a set of vehicles that need to visit a set of locations. It creates the overall minimum transportation cost.
You can use fleet routing to build applications such as:
- A large furniture store might deliver goods from a central warehouse location.
- A specialized grease recycling company might route trucks from a facility to pick up used grease from restaurants.
- A health department might schedule daily inspection visits for each of its health inspectors.
- A health care provider might want to find best routes to transport people from their homes to different hospitals for medical appointments.
The goal of the fleet routing service is to find what orders should be serviced by each vehicle and in what sequence the orders should be visited. The service can take into account many additional business constraints such as:
- Matching vehicle capacities with order quantities.
- Providing a high level of customer service by honoring any time windows on orders.
- Pairing orders so they are serviced by the same route.
- Giving breaks to drivers.
How fleet routing works
The typical workflow for determining fleet routes is to:
- Define the locations to visit (orders).
- Define the start and end location for vehicles (depots).
- Define the travel mode (driving a car or truck).
- Use the service to find the best routes and directions for all vehicles.
URL requests
You can perform fleet routing by making an HTTPS request to the Fleet Routing service execute
operation or by using client APIs. Specify the orders, depots, routes, and optionally, additional parameters such as the travel mode used when finding routes or if you need to generate driving directions.
Request limits
Limit | Direct | Job |
---|---|---|
Maximum number of orders: | 100 | 2,000 |
Maximum number of routes: | 2 | 100 |
Maximum number of orders per route: | 100 | 200 |
Maximum transaction time: | 5 minutes | 4 hours |
Maximum number of point barriers: | 250 | 250 |
Maximum number of street features intersected by polyline barriers: | 500 | 500 |
Maximum number of street features intersected by polygon barriers: | 2,000 | 2,000 |
Maximum straight-line distance for the walking travel mode: (If the straight-line distance between any orders or depots is greater than this limit, the analysis will fail when the walking restriction is used.) | 27 miles (43.45 kilometers) | 27 miles (43.45 kilometers) |
Force hierarchy beyond a straight-line distance of: (If the straight-line distance between any orders or depots is greater than the limit shown here, the analysis uses hierarchy, even if the travel defines not to use hierarchy.) | 50 miles (80.46 kilometers) | 50 miles (80.46 kilometers) |
Maximum snap tolerance: (If the distance between an input point and its nearest traversable street is greater than the distance specified here, the point is excluded from the analysis.) | 12.42 miles (20 kilometers) | 12.42 miles (20 kilometers) |
Maximum number of directions features that can be returned: | 10,000 | 200,000 |
Required parameters
Direct
Use for shorter transactions that complete in less than 5 minutes and optimize up to 2 routes and 100 orders.
https://logistics.arcgis.com/arcgis/rest/services/World/VehicleRoutingProblemSync/GPServer/EditVehicleRoutingProblem/execute?<parameters>
Key parameters
Name (Direct) | Description |
---|---|
orders |
A list of locations to visit with attributes such as the order name or the time required to complete the delivery at each order. |
depots |
The start and the return location for the vehicles. |
routes |
The characteristics and constraints for each vehicle. For example, the start and the return depot name, the maximum number of orders a vehicle is allowed to visit, and the total time the vehicle is allowed to operate. |
travel |
The mode of transportation such as driving a car or a truck. |
default |
The date on which all of your routes start. |
populate |
Generate driving directions for the routes. |
Additional parameters: Solve complex fleet routing scenarios by specifying additional inputs such as route
, order
, breaks
, route
or setting additional constraints when finding routes using time
, excess
, spatially
.
Job
Use for longer transactions that can take up to 4 hours and optimize up to 100 routes and 2,000 orders.
https://logistics.arcgis.com/arcgis/rest/services/World/VehicleRoutingProblem/GPServer/SolveVehicleRoutingProblem/submitJob?<parameters>
Key parameters
Name (Job) | Description |
---|---|
orders |
A list of locations to visit with attributes such as the order name or the time required to complete the delivery at each order. |
depots |
The start and the return location for the vehicles. |
routes |
The characteristics and constraints for each vehicle. For example, the start and the return depot name, the maximum number of orders a vehicle is allowed to visit, and the total time the vehicle is allowed to operate. |
travel |
The mode of transportation such as driving a car or a truck. |
default |
The date on which all of your routes start. |
populate |
Generate driving directions for the routes. |
Additional parameters: Solve complex fleet routing scenarios by specifying additional inputs such as route
, order
, breaks
, route
or setting additional constraints when finding routes using time
, excess
, spatially
.
Code examples
Direct: Multi-vehicle routing and delivery
In this example, use the fleet routing service to find optimized routes and directions for an appliance delivery company using two vehicles which start from a warehouse and return to the same location at the end of the working day.
In this scenario, two vehicles will depart from a warehouse located in Santa Monica, California. Each vehicle has a capacity of four appliances. There are a total of six restaurants to visit and it takes ten minutes at complete the delivery at each restaurant. Each vehicle needs to return in one hour and can only visit a maximum of three restaurants in total.
The response contains a list of results describing various outputs such as:
- Set of stops that shows the route assignment.
- Set of routes that shows the overall time and distance.
- Set of directions for each route (if you requested to populate directions).
APIs
const geoprocessorUrl = "https://logistics.arcgis.com/arcgis/rest/services/World/VehicleRoutingProblemSync/GPServer/EditVehicleRoutingProblem"
const params = {
orders, // Feature Set
depots, // Feature Set
routes, // Feature Set
populate_directions: true // "Generate driving directions for the routes"
};
const { results } = await geoprocessor.execute(geoprocessorUrl, params);
const outStops = results[1].value.features; // Graphics[]
const outRoutes = results[2].value.features; // Graphics[]
showStops(outStops);
showRoutes(outRoutes);
}
REST API
curl https://logistics.arcgis.com/arcgis/rest/services/World/VehicleRoutingProblemSync/GPServer/EditVehicleRoutingProblem/execute? \
-d "f=json" \
-d "token=<ACCESS_TOKEN>" \
-d "orders={'type':'features','features':[{'attributes':{'Name':'Father\'s Office','ServiceTime':10},'geometry':{'x':-118.498406,'y':34.029445}},{'attributes':{'Name':'R+D Kitchen','ServiceTime':10},'geometry':{'x':-118.495788,'y':34.032339}},{'attributes':{'Name':'Pono Burger','ServiceTime':10},'geometry':{'x':-118.489469,'y':34.019000}},{'attributes':{'Name':'Il Ristorante di Giorgio Baldi','ServiceTime':10},'geometry':{'x':-118.518787,'y':34.028508}},{'attributes':{'Name':'Milo + Olive','ServiceTime':10},'geometry':{'x':-118.476026,'y':34.037572}},{'attributes':{'Name':'Dialogue','ServiceTime':10},'geometry':{'x':-118.495814,'y':34.017042}}]}" \
-d "depots={'type':'features','features':[{'attributes':{'Name':'Bay Cities Kitchens and Appliances'},'geometry':{'x':-118.469630,'y':34.037555}}]}" \
-d "routes={'features':[{'attributes':{'Name':'Route 1','Description':'vehicle 1','StartDepotName':'Bay Cities Kitchens and Appliances','EndDepotName':'Bay Cities Kitchens and Appliances','Capacities':'4','MaxOrderCount':3,'MaxTotalTime':60,}},{'attributes':{'Name':'Route 2','Description':'vehicle 2','StartDepotName':'Bay Cities Kitchens and Appliances','EndDepotName':'Bay Cities Kitchens and Appliances','Capacities':'4','MaxOrderCount':3,'MaxTotalTime':60,}}]}" \
-d "populate_directions=true"
Job: Goods delivery
In this example, you will find the best routes for a fleet of three vehicles, operated by a distribution company, to deliver goods from a distribution center to a set of nine grocery stores. Each store has a specific quantity of demand for the goods, and each truck has a limited capacity for carrying the goods. The main objective is to assign trucks in the fleet a subset of the stores to service and to sequence the deliveries in a way that minimizes the overall transportation costs.
In this scenario, specify the stores as orders
, the distribution center as depots
, and the three trucks as routes
.
-
For the
orders
parameter, specify the following attributes:- The store name as the
Name
attribute. - The service time as the
Service
attribute.Time - The total weight of goods to be delivered as the
Delivery
attribute.Quantities - The time range in which the store accepts deliveries as the
Time
andWindow Start1 Time
attributes.Window End1 - Since the time windows should not be violated, specify 0 as the value for the
Max
attribute.Violation Time1
- The store name as the
-
For the
depots
parameter, specify the following attributes:- The depot name as the
Name
attribute. - The depot operating time as the
Time
andWindow Start1 Time
attributes.Window End1
- The depot name as the
-
For the
routes
parameter, specify the following attributes:-
The name for each truck as the
Name
attribute. -
The depot name from where the trucks operate as the
Start
andDepot Name End
attributes.Depot Name -
The time required to fully load the truck with goods as
Start
attribute.Depot Service Time -
The trucks can start operating as soon as the depot opens, so you specify the
Earliest
andStart Time Latest
attributes to have the same values as theStart Time Time
attribute for theWindow Start1 depots
parameter. -
The maximum carrying capacity of each truck as the
Capacities
attribute. -
The wage of the truck driver as the
Cost
attribute.Per Unit Time -
The average dollar amount spent per mile on fuel consumption, truck depreciation, and maintenance as the
Cost
parameter.Per Unit Distance -
The maximum number of stores that can be serviced by a truck as the
Max
attribute.Order Count -
The maximum duration of the work shift for the drivers according to the workday constraints as the
Max
attribute.Total Time -
The maximum time a truck can spend driving on the streets as the
Max
attribute. This considers the need to satisfy the workday constraints and still be able to serve a reasonable number of stores while taking into account the service time needed at a store.Travel Time -
The maximum distance a truck can travel that balances the daily fuel and maintenance costs among the fleet as the
Max
attribute.Total Distance
-
-
Since your time-based attribute values, such as
Service
,Time Cost
, andPer Unit Time Max
are in minutes, you can use the default value (which is minutes) for theTotal Time time
parameter. Similarly, your distance-based attributes values, such as_units Cost
andPer Unit Distance Max
, are in miles, you can use the default value (which is miles) for theTotal Distance distance
parameter._units -
Since we are finding routes for delivery trucks, we need to make sure we follow the rules that pertain to driving trucks. These include, not driving on streets that are restricted for trucks and do not require making any U-turns since it is difficult for these delivery trucks to make them. So we specify the
travel
parameter to a value that defines a trucking time travel mode._mode -
You need to generate driving directions in English for each route, so set the
populate
parameter to_directions true
and thedirections
parameter to_language en
. -
Since we are generating driving directions, the shape of the output routes can be obtained from the directions output. So as a performance improvement and to reduce the size of the response we need to fetch, we will not populate any shape for the output routes by setting
populate
to_route _lines false
. -
Since you have time windows on orders and depots, you need to specify the
default
parameter._date
The default values for all the remaining parameters are valid for this problem, and therefore you will not pass those parameters in your request.
APIs
const url = "https://logistics.arcgis.com/arcgis/rest/services/World/VehicleRoutingProblem/GPServer/SolveVehicleRoutingProblem";
const geoprocessingOptions = {
outSpatialReference: view.spatialReference
};
const jobInfo = await geoprocessor.submitJob(url, params, geoprocessingOptions);
const options = {
statusCallback: (jobInfo) => {
const timestamp = new Date().toLocaleTimeString();
const message = jobInfo.messages[jobInfo.messages.length - 1];
console.log(`${timestamp}: ${message.description}`);
}
};
await jobInfo.waitForJobCompletion(options);
const [directionsResult, routesResult, stopsResult] = await Promise.all([
jobInfo.fetchResultData("out_directions"),
jobInfo.fetchResultData("out_routes"),
jobInfo.fetchResultData("out_stops")
]);
return {
directions: directionsResult.value.features,
routes: routesResult.value.features,
stops: stopsResult.value.features
};
}
REST API
Unlike Direct request type which allows you to make a request and get back all the results in the response, when working with a Job request type, you need to follow a three step workflow:
- Make the
submit
request with the appropriate request parameters to get a job id.Job - Using the job id, check the job status to see if the job completed successfully.
- Use the job id to get one or more results.
Request
curl https://logistics.arcgis.com/arcgis/rest/services/World/VehicleRoutingProblem/GPServer/SolveVehicleRoutingProblem/submitJob? \
-d "f=json" \
-d "token=<ACCESS_TOKEN>" \
-d "orders={'features':[{'geometry':{'x':-122.51,'y':37.7724},'attributes':{'DeliveryQuantities':1706,'Name':'Store_1','ServiceTime':25,'TimeWindowStart1':1608051600000,'TimeWindowEnd1':1608080400000,'MaxViolationTime1':0}},{'geometry':{'x':-122.4889,'y':37.7538},'attributes':{'DeliveryQuantities':1533,'Name':'Store_2','ServiceTime':23,'TimeWindowStart1':1608051600000,'TimeWindowEnd1':1608080400000,'MaxViolationTime1':0}},{'geometry':{'x':-122.4649,'y':37.7747},'attributes':{'DeliveryQuantities':1580,'Name':'Store_3','ServiceTime':24,'TimeWindowStart1':1608051600000,'TimeWindowEnd1':1608080400000,'MaxViolationTime1':0}},{'geometry':{'x':-122.4739,'y':37.7432},'attributes':{'DeliveryQuantities':1289,'Name':'Store_4','ServiceTime':20,'TimeWindowStart1':1608051600000,'TimeWindowEnd1':1608080400000,'MaxViolationTime1':0}},{'geometry':{'x':-122.4493,'y':37.7315},'attributes':{'DeliveryQuantities':1302,'Name':'Store_5','ServiceTime':21,'TimeWindowStart1':1608051600000,'TimeWindowEnd1':1608080400000,'MaxViolationTime1':0}},{'geometry':{'x':-122.4917,'y':37.6493},'attributes':{'DeliveryQuantities':1775,'Name':'Store_6','ServiceTime':26,'TimeWindowStart1':1608051600000,'TimeWindowEnd1':1608080400000,'MaxViolationTime1':0}},{'geometry':{'x':-122.4832,'y':37.7012},'attributes':{'DeliveryQuantities':1014,'Name':'Store_7','ServiceTime':17,'TimeWindowStart1':1608051600000,'TimeWindowEnd1':1608080400000,'MaxViolationTime1':0}},{'geometry':{'x':-122.5301,'y':37.8935},'attributes':{'DeliveryQuantities':1761,'Name':'Store_8','ServiceTime':26,'TimeWindowStart1':1608051600000,'TimeWindowEnd1':1608080400000,'MaxViolationTime1':0}},{'geometry':{'x':-122.2875,'y':37.8909},'attributes':{'DeliveryQuantities':1815,'Name':'Store_9','ServiceTime':27,'TimeWindowStart1':1608051600000,'TimeWindowEnd1':1608080400000,'MaxViolationTime1':0}}]}" \
-d "depots={'features':[{'geometry':{'x':-122.3943,'y':37.7967},'attributes':{'Name':'San Francisco','TimeWindowStart1':1608048000000,'TimeWindowEnd1':1608080400000}}]}" \
-d "routes={'features':[{'attributes':{'Name':'Truck_1','StartDepotName':'San Francisco','EndDepotName':'San Francisco','StartDepotServiceTime':60,'EarliestStartTime':1608048000000,'LatestStartTime':1608048000000,'Capacities':'15000','CostPerUnitTime':0.2,'CostPerUnitDistance':1.5,'MaxOrderCount':3,'MaxTotalTime':360,'MaxTotalTravelTime':180,'MaxTotalDistance':100}},{'attributes':{'Name':'Truck_2','StartDepotName':'San Francisco','EndDepotName':'San Francisco','StartDepotServiceTime':60,'EarliestStartTime':1608048000000,'LatestStartTime':1608048000000,'Capacities':'15000','CostPerUnitTime':0.2,'CostPerUnitDistance':1.5,'MaxOrderCount':3,'MaxTotalTime':360,'MaxTotalTravelTime':180,'MaxTotalDistance':100}},{'attributes':{'Name':'Truck_3','StartDepotName':'San Francisco','EndDepotName':'San Francisco','StartDepotServiceTime':60,'EarliestStartTime':1608048000000,'LatestStartTime':1608048000000,'Capacities':'15000','CostPerUnitTime':0.2,'CostPerUnitDistance':1.5,'MaxOrderCount':3,'MaxTotalTime':360,'MaxTotalTravelTime':180,'MaxTotalDistance':100}}]}" \
-d "time_units=Minutes" \
-d "distance_units=Miles" \
-d "travel_mode={'attributeParameterValues':[{'attributeName':'Use Preferred Truck Routes','parameterName':'Restriction Usage','value':'PREFER_HIGH'},{'attributeName':'Avoid Unpaved Roads','parameterName':'Restriction Usage','value':'AVOID_HIGH'},{'attributeName':'Avoid Private Roads','parameterName':'Restriction Usage','value':'AVOID_MEDIUM'},{'attributeName':'Driving a Truck','parameterName':'Restriction Usage','value':'PROHIBITED'},{'attributeName':'Roads Under Construction Prohibited','parameterName':'Restriction Usage','value':'PROHIBITED'},{'attributeName':'Avoid Gates','parameterName':'Restriction Usage','value':'AVOID_MEDIUM'},{'attributeName':'Avoid Express Lanes','parameterName':'Restriction Usage','value':'PROHIBITED'},{'attributeName':'Avoid Carpool Roads','parameterName':'Restriction Usage','value':'PROHIBITED'},{'attributeName':'Avoid Truck Restricted Roads','parameterName':'Restriction Usage','value':'AVOID_HIGH'},{'attributeName':'TruckTravelTime','parameterName':'Vehicle Maximum Speed (km/h)','value':0}],'description':'Models basic truck travel by preferring designated truck routes, and finds solutions that optimize travel time. Routes must obey one-way roads, avoid illegal turns, and so on. When you specify a start time, dynamic travel speeds based on traffic are used where it is available, up to the legal truck speed limit.','distanceAttributeName':'Kilometers','id':'ZzzRtYcPLjXFBKwr','impedanceAttributeName':'TruckTravelTime','name':'Trucking Time','restrictionAttributeNames':['Avoid Carpool Roads','Avoid Express Lanes','Avoid Gates','Avoid Private Roads','Avoid Truck Restricted Roads','Avoid Unpaved Roads','Driving a Truck','Roads Under Construction Prohibited','Use Preferred Truck Routes'],'simplificationTolerance':10,'simplificationToleranceUnits':'esriMeters','timeAttributeName':'TruckTravelTime','type':'TRUCK','useHierarchy':true,'uturnAtJunctions':'esriNFSBNoBacktrack'}" \
-d "populate_directions=true" \
-d "directions_language=en" \
-d "populate_route_lines=false" \
-d "default_date=1608051600000"
Response (JSON)
{
"jobId": "jfd7f78c3a9174d0ba0933c022b38a37e",
"jobStatus": "esriJobSubmitted"
}