Overview

You will learn: how to find optimized routes and directions for delivery and service vehicles with the ArcGIS Vehicle Routing service.

The ArcGIS Transportation Routing and Network Analytics Services can be used to solve transportation and routing problems such as finding the shortest path to locations, calculating drive times, and routing delivery vehicles to multiple destinations. One of the most powerful features is the SolveVehicleRoutingProblem function. This function allows you to solve complex multi-vehicle, multi-stop routing problems. For example, if you have a service center or fleet delivery center, you can determine the most optimum route and directions that each vehicle should take to visit all of the required stops each day. The function requires a number of inputs such as the stop locations, start and finish depots, number of vehicles, number of maximum stops, maximum time at each stop, and the maximum time allotted for each vehicle to complete each route. A wide range of other routing parameters and restrictions can be set as well. Once you have the results you can create delivery schedules, maps, and turn-by-turn directions for vehicles and drivers. To learn more about this service, please visit the documentation.

In this lab you will use the Vehicle Routing Problem service to find the optimized route and directions for two buses that need to drop off hikers at three trailheads in the Santa Monica Mountains area. The buses will depart from Santa Monica and each bus is required to complete their route in less than 2 hours.

Before you begin

Install Postman to execute HTTP requests. Go to this lab if you need an access token.

Steps

Create a request to the vehicle routing service

The vehicle routing service supports both synchronous and asynchronous requests. Since this is a long transaction, make an asynchronous request with the submitJob function. Learn more about synchronous and asynchronous requests here.

  1. Open Postman and click [+] in the tab bar to create a new request.

  2. In the new tab, set the following:

    • HTTP Method: POST
    • Request URL: https://logistics.arcgis.com/arcgis/rest/services/World/VehicleRoutingProblem/GPServer/SolveVehicleRoutingProblem/submitJob

Add parameters to define the depots, routes and orders

In this scenario, two buses will depart from a bus station located in Santa Monica. Each bus has a capacity of 20 people. Buses are not allowed to perform uturns. There are a total of three trailheads to stop at for a maximum of ten minutes at each stop. Each bus needs to return in 2 hrs and can only visit a maximum of two stops total. Follow the steps below to define these parameters.

  1. Click on Body > x-www-form-urlencoded and add the following Key/Value pairs:

    • f: json
    • token: Go to this lab if you need an access token.
    • populate_directions: true
    • uturn_policy: NO_UTURNS
    • depots: The start and return location for the buses.
      {
        "type":"features",
        "features" : [{
          "attributes" : {
              "Name" : "Santa Monica",
              "Description" : "Bus Station"
          },
          "geometry" : {
              "x" : -118.49614,
              "y" : 34.05315
          }
        }]
      }
      
    • routes: The routing attributes and restrictions for each bus.
      {
        "features": [{
            "attributes": {
                "Name": "Route 1",
                "Description": "Bus 1",
                "StartDepotName": "Santa Monica",
                "EndDepotName": "Santa Monica",
                "Capacities": "20",
                "MaxOrderCount": 2,
                "MaxTotalTime": 120,
              }
            },
            {
          "attributes": {
                "Name": "Route 2",
                "Description": "Bus 2",
                "StartDepotName": "Santa Monica",
                "EndDepotName": "Santa Monica",
                "Capacities": "20",
                "MaxOrderCount": 2,
                "MaxTotalTime": 120,
              }
            }
        ]
      }
      
    • orders: A list of the three trailheads to stop at and the service time allocated at each stop.
      {
        "type": "features",
        "features": [{
            "attributes": {
                "Name": "Los Leones Trail",
                "ServiceTime": 10
            },
            "geometry": {
                "x": -118.55978,
                "y": 34.04712
            }
        },
        {
            "attributes": {
                "Name": "Cii Debora Spur Trail",
                "ServiceTime": 10
            },
            "geometry": {
                "x": -118.54620,
                "y": 34.07628
            }
        },
        {
            "attributes": {
                "Name": "Temescal Canyon Trail",
                "ServiceTime": 10
            },
              "geometry": {
              "x": -118.52858,
              "y": 34.05315
            }
          }
        ]
      }
      

Execute the request

Make an asynchronous request to get the JobId. The JobID value will be used to create the remaining requests.

  1. Click Send to run the request.

  2. In the response window, change the view to JSON and it should look something like this since we are using asynchronous execution mode:

    {
        "JobId": <JobId>,
        "jobStatus": "esriJobSubmitted"
    }
    
  3. Make note of the JobId value as it will be used to make additional requests to the server.

Check the job status

Create a new request with the JobId to determine if the job is complete. Once the job is complete you can use the JobId to retrieve the results.

  1. In the tab bar, click [+] to create a new request. Set the following to check the job status:

    • HTTP Method: POST
    • Request URL: https://logistics.arcgis.com/arcgis/rest/services/World/VehicleRoutingProblem/GPServer/SolveVehicleRoutingProblem/jobs/<JobId> (Replace the <JobId> with yours)

    Click on Body and add the following Key/Value pairs:

    • f: json
    • token: <your token>

    Click Send to run the request. You may need to send it a few times until the job completes.

    In the response window, change the view to JSON and it should look something like this:

    {
        "JobId": "j97f35afbb1764a8da7767d3781ea41ff",
        "jobStatus": "esriJobSucceeded",
        "results": {
            "out_unassigned_stops": {
                "paramUrl": "results/out_unassigned_stops"
            },
            "out_stops": {
                "paramUrl": "results/out_stops"
            },
            "out_routes": {
                "paramUrl": "results/out_routes"
            },
            "out_directions": {
                "paramUrl": "results/out_directions"
            },
            "solve_succeeded": {
                "paramUrl": "results/solve_succeeded"
            },
            "out_network_analysis_layer": {
                "paramUrl": "results/out_network_analysis_layer"
            },
            "out_route_data": {
                "paramUrl": "results/out_route_data"
            }
        },
        "inputs": {
            "orders": {
                "paramUrl": "inputs/orders"
            },
            "depots": {
                "paramUrl": "inputs/depots"
            },
            "routes": {
                "paramUrl": "inputs/routes"
            },
            "breaks": {
                "paramUrl": "inputs/breaks"
            },
            "time_units": {
                "paramUrl": "inputs/time_units"
            },
            "distance_units": {
                "paramUrl": "inputs/distance_units"
            },
            "analysis_region": {
                "paramUrl": "inputs/analysis_region"
            },
            "default_date": {
                "paramUrl": "inputs/default_date"
            },
            "uturn_policy": {
                "paramUrl": "inputs/uturn_policy"
            },
            "time_window_factor": {
                "paramUrl": "inputs/time_window_factor"
            },
            "spatially_cluster_routes": {
                "paramUrl": "inputs/spatially_cluster_routes"
            },
            "route_zones": {
                "paramUrl": "inputs/route_zones"
            },
            "route_renewals": {
                "paramUrl": "inputs/route_renewals"
            },
            "order_pairs": {
                "paramUrl": "inputs/order_pairs"
            },
            "excess_transit_factor": {
                "paramUrl": "inputs/excess_transit_factor"
            },
            "point_barriers": {
                "paramUrl": "inputs/point_barriers"
            },
            "line_barriers": {
                "paramUrl": "inputs/line_barriers"
            },
            "polygon_barriers": {
                "paramUrl": "inputs/polygon_barriers"
            },
            "use_hierarchy_in_analysis": {
                "paramUrl": "inputs/use_hierarchy_in_analysis"
            },
            "restrictions": {
                "paramUrl": "inputs/restrictions"
            },
            "attribute_parameter_values": {
                "paramUrl": "inputs/attribute_parameter_values"
            },
            "populate_route_lines": {
                "paramUrl": "inputs/populate_route_lines"
            },
            "route_line_simplification_tolerance": {
                "paramUrl": "inputs/route_line_simplification_tolerance"
            },
            "populate_directions": {
                "paramUrl": "inputs/populate_directions"
            },
            "directions_language": {
                "paramUrl": "inputs/directions_language"
            },
            "directions_style_name": {
                "paramUrl": "inputs/directions_style_name"
            },
            "travel_mode": {
                "paramUrl": "inputs/travel_mode"
            },
            "impedance": {
                "paramUrl": "inputs/impedance"
            },
            "time_zone_usage_for_time_fields": {
                "paramUrl": "inputs/time_zone_usage_for_time_fields"
            },
            "save_output_layer": {
                "paramUrl": "inputs/save_output_layer"
            },
            "overrides": {
                "paramUrl": "inputs/overrides"
            },
            "save_route_data": {
                "paramUrl": "inputs/save_route_data"
            }
        },
        "messages": [
            {
                "type": "esriJobMessageTypeWarning",
                "description": "Network elements with avoid-restrictions are traversed in the output (restriction attribute names: \"Through Traffic Prohibited\").\n"
            }
        ]
    }
    
  2. In the JSON, explore the following results:

    • jobStatus: Indicates if the job was successful or not.
    • results: All of the results available.
      • out_xxx: Name of the result that can be retrieved.
      • paramUrl: The location of the result to be retrieved.
    • inputs: All of the input parameters (including the defaults) used to calculate the results.
    • messages: Feedback about the status of the route calculation including error messages.

Get the routes

Create a new request to get the route results. The routes include all of the optimized geometric paths each vehicle should take to complete the delivery route.

  1. In the tab bar, click [+] to create a new request. Set the following to retrieve the route results:

    • HTTP Method: POST
    • Request URL: https://logistics.arcgis.com/arcgis/rest/services/World/VehicleRoutingProblem/GPServer/SolveVehicleRoutingProblem/jobs/<JobId>/results/out_routes (Replace the <JobId> with yours)

    Click on Body and add the following Key/Value pairs:

    • f: json
    • token: <your token>

    Click Send to run the request.

  2. In the JSON response, use the find tool to explore the values of the following results:

    • geometryType: Usually esriGeometryPolyline, this indicates the type of geometry of the route.
    • fields: A list of the field types for each route.
    • features: An array that contains the attribute values and the line geometry for each route.

    How many route features were returned?

Get the stops

Create a new request to get the stops results. The stops include all of the ordered stops each vehicle should visit to complete each delivery route. This includes the start and finish stops from the depot.

  1. In the tab bar, click [+] to create a new request. Set the following to get the stop results:

    • HTTP Method: POST
    • Request URL: https://logistics.arcgis.com/arcgis/rest/services/World/VehicleRoutingProblem/GPServer/SolveVehicleRoutingProblem/jobs/<JobId>/results/out_stops (Replace the <JobId> with yours)

    Click on Body and add the following Key/Value pairs:

    • f: json
    • token: <your token>

    Click Send to run the request.

  2. In the JSON response, use the find tool to explore the following results:

    • RouteName: The name of the route that makes the stop.
    • Sequence: The relative sequence in which the assigned route visits the stop.
    • ArriveTime: The time of day when the route arrives at the stop. The time-of-day value for this attribute is in the time zone in which the stop is located.
    • DepartTime: The time of day when the route departs from the stop. The time-of-day value for this attribute is in the time zone in which the stop is located.

    How many stops were returned?

Get the directions

Create a new request to get the directions results. The directions include all of the line segments and turn-by-turn directions each vehicle should follow to complete each delivery route.

  1. In the tab bar, click [+] to create a new request. Set the following to get the direction results:

    • HTTP Method: POST
    • Request URL: https://logistics.arcgis.com/arcgis/rest/services/World/VehicleRoutingProblem/GPServer/SolveVehicleRoutingProblem/jobs/<JobId>/results/out_directions (Replace the <JobId> with yours)

    Click on Body and add the following Key/Value pairs:

    • f: json
    • token: <your token>

    Click Send to run the request.

  2. In the JSON response, use the find tool to explore the following results:

    • fields: A list of the attribute information available including turn-by-turn text.
    • features: An array of features representing each line segment with directions, time, and distance.

    How many lines with turn-by-turn directions were returned?

Congratulations, you're done!

You have successfully calculated the optimized routes for the buses to take hikers from the depot in Santa Monica to three trailhead stops and be back in less than two hours. If you want to see what the results look like on a map, open this web map solution that was created in the ArcGIS Online - Route multiple vehicles lab.

Challenge

Reduce the total route time per vehicle

Go back to Step 3 and change the MaxTotalTime to 60 minutes and then run all of the requests again.

How do the routing results differ from the first analysis? Why?

Add time windows to your orders

You can add time windows to orders to restrict the maximum time it can take to reach a stops location. Use the TimeWindowStart1, TimeWindowEnd1 and TimeWindowStart2, TimeWindowEnd2 attributes to set these values. To learn more, visit the Vehicle Routing Problem service documentation.