This quickstart shows how to solve the VRP example by sending a gRPC request to the Cloud Fleet Routing service using the Cloud Client Libraries for Python. This example uses the Distance Matrix API.
Before you begin
To send requests to the API using the Python Client, you need to download the Cloud Fleet Routing Python Client from Cloud Storage. To do so, enter the following command:
gcloud storage cp gs://api-client-staging/cloudoptimization-python-v1-20211110.tar.gz SAVE_TO_LOCATION
Please change SAVE_TO_LOCATION
to the location where you'd like to put your SDK in.
Install pip
Install pip, the Python package installer:
sudo apt-get install python-pip
python3 -m pip install --user --upgrade pip
pip install --upgrade pip
Make sure your pip version is at least pip-21:
pip --version
Install the Cloud Fleet Routing API Client Library
After you have downloaded the API client tarball, install the API client with the following commands:
python3 -m venv fleet-env
source fleet-env/bin/activate
pip install cloudoptimization-python-v1-20211110.tar.gz
Synchronous API requests
The following script sends an API request to the Cloud Fleet Routing service to synchronously generate routes.
import json import sys from google.cloud.optimization_v1.services.fleet_routing.client import FleetRoutingClient from google.cloud.optimization_v1.types.fleet_routing import OptimizeToursRequest def main(request_file_name): # Use the default credentials for the environment. fleet_routing_client = FleetRoutingClient() # Get the data. with open(request_file_name, 'r') as f: # The request must include the `parent` field with the value set to # 'projects/{YOUR_GCP_PROJECT_ID}'. fleet_routing_request = OptimizeToursRequest.from_json(f.read()) # Send the request and print the response. # Cloud Fleet Routing will return a response by the earliest of the `timeout` field # in the request payload and the gRPC timeout specified below. fleet_routing_response = fleet_routing_client.optimize_tours( fleet_routing_request, timeout=100) print(fleet_routing_response) # If you want to format the response to JSON, you can do the following: # from google.protobuf.json_format import MessageToJson # json_obj = MessageToJson(fleet_routing_response._pb) if __name__ == '__main__': if len(sys.argv) > 1: main(sys.argv[1]) else: print('You must include the request file as an argument.')
{ "parent": "projects/${YOUR_GCP_PROJECT_ID}", "model": { "shipments": [ { "deliveries": [ { "arrivalLocation": { "latitude": 48.880942, "longitude": 2.323866 }, "duration": "250s", "timeWindows": [ { "endTime": "1970-01-01T01:06:40Z", "startTime": "1970-01-01T00:50:00Z" } ] } ], "loadDemands": { "weight": { "amount": "10" } }, "pickups": [ { "arrivalLocation": { "latitude": 48.874507, "longitude": 2.30361 }, "duration": "150s", "timeWindows": [ { "endTime": "1970-01-01T00:33:20Z", "startTime": "1970-01-01T00:16:40Z" } ] } ] }, { "deliveries": [ { "arrivalLocation": { "latitude": 48.88094, "longitude": 2.323844 }, "duration": "251s", "timeWindows": [ { "endTime": "1970-01-01T01:06:41Z", "startTime": "1970-01-01T00:50:01Z" } ] } ], "loadDemands": { "weight": { "amount": "20" } }, "pickups": [ { "arrivalLocation": { "latitude": 48.880943, "longitude": 2.323867 }, "duration": "151s", "timeWindows": [ { "endTime": "1970-01-01T00:33:21Z", "startTime": "1970-01-01T00:16:41Z" } ] } ] } ], "vehicles": [ { "loadLimits": { "weight": { "maxLoad": 50 } }, "endLocation": { "latitude": 48.86311, "longitude": 2.341205 }, "startLocation": { "latitude": 48.863102, "longitude": 2.341204 }, "costPerTraveledHour": 3600 }, { "loadLimits": { "weight": { "maxLoad": 60 } }, "endLocation": { "latitude": 48.86312, "longitude": 2.341215 }, "startLocation": { "latitude": 48.863112, "longitude": 2.341214 }, "costPerTraveledHour": 3600 } ] } }
Run the code
To run the Python code for synchronous requests:
- Save the code sample as
api_client_send_request.py
, and save the JSON file asrequest.json
in the same directory. - Authenticate your environment using the instructions in the "Before you begin" page.
- Replace
${YOUR_GCP_PROJECT_ID}
with your Google Cloud project ID in therequest.json
file. - Replace
${YOUR_MAPS_API_KEY}
in therequest.json
file with your API key for Google Maps Platform that you generated in the "Before you begin" section. - At the command line, navigate to the directory containing the files and enter
python api_client_send_request.py request.json
Response
The following is the response to the request.
routes { vehicle_start_time { seconds: 35 } vehicle_end_time { seconds: 4302 } visits { is_pickup: true start_time { seconds: 1000 } demands { type: "weight" value: 10 } detour { } arrival_loads { type: "weight" } load_demands { key: "weight" value { amount: 10 } } } visits { shipment_index: 1 is_pickup: true start_time { seconds: 1660 } demands { type: "weight" value: 20 } detour { seconds: 756 } arrival_loads { type: "weight" value: 10 } load_demands { key: "weight" value { amount: 20 } } } visits { start_time { seconds: 3000 } demands { type: "weight" value: -10 } detour { seconds: 1340 } arrival_loads { type: "weight" value: 30 } load_demands { key: "weight" value { amount: -10 } } } visits { shipment_index: 1 start_time { seconds: 3250 } demands { type: "weight" value: -20 } detour { seconds: 1439 } arrival_loads { type: "weight" value: 20 } load_demands { key: "weight" value { amount: -20 } } } transitions { travel_duration { seconds: 965 } travel_distance_meters: 4244.0 total_duration { seconds: 965 } start_time { seconds: 35 } vehicle_loads { key: "weight" value { } } } transitions { travel_duration { seconds: 510 } travel_distance_meters: 2479.0 total_duration { seconds: 510 } start_time { seconds: 1150 } vehicle_loads { key: "weight" value { amount: 10 } } } transitions { travel_duration { } wait_duration { seconds: 1189 } total_duration { seconds: 1189 } start_time { seconds: 1811 } vehicle_loads { key: "weight" value { amount: 30 } } } transitions { travel_duration { } total_duration { } start_time { seconds: 3250 } vehicle_loads { key: "weight" value { amount: 20 } } } transitions { travel_duration { seconds: 801 } travel_distance_meters: 3111.0 total_duration { seconds: 801 } start_time { seconds: 3501 } vehicle_loads { key: "weight" value { } } } metrics { performed_shipment_count: 2 travel_duration { seconds: 2276 } wait_duration { seconds: 1189 } delay_duration { } break_duration { } visit_duration { seconds: 802 } total_duration { seconds: 4267 } travel_distance_meters: 9834.0 max_loads { key: "weight" value { amount: 30 } } } end_loads { type: "weight" } travel_steps { duration { seconds: 965 } distance_meters: 4244.0 } travel_steps { duration { seconds: 510 } distance_meters: 2479.0 } travel_steps { duration { } } travel_steps { duration { } } travel_steps { duration { seconds: 801 } distance_meters: 3111.0 } vehicle_detour { seconds: 4267 } } routes { vehicle_index: 1 } metrics { aggregated_route_metrics { performed_shipment_count: 2 travel_duration { seconds: 2276 } wait_duration { seconds: 1189 } delay_duration { } break_duration { } visit_duration { seconds: 802 } total_duration { seconds: 4267 } travel_distance_meters: 9834.0 max_loads { key: "weight" value { amount: 30 } } } used_vehicle_count: 1 earliest_vehicle_start_time { seconds: 35 } latest_vehicle_end_time { seconds: 4302 } }
For a description of the response, see Response to the request.
Asynchronous API requests
The asynchronous method performs the same operations as the synchronous version, except it immediately returns an asynchronous object that you can use to get the status of the operation. If a route request results is unsuccessful, the status of the operation will include the error. Upon task completion, the model solution is uploaded to Cloud Storage for each successful route. One or more routes can be optimized in a single asynchronous request.
The following script sends an API request to the Cloud Fleet Routing service to asynchronously generate routes.
import json import sys from google.cloud.optimization_v1.services.fleet_routing.client import FleetRoutingClient from google.cloud.optimization_v1.types.fleet_routing import BatchOptimizeToursRequest def main(request_file_name): # Use the default credentials for the environment to authenticate the client. fleet_routing_client = FleetRoutingClient() # Get the data. with open(request_file_name, 'r') as f: # The request must include the "parent" field with the value set to # "projects/{YOUR_GCP_PROJECT_ID}". fleet_routing_request = BatchOptimizeToursRequest.from_json(f.read()) # The timeout argument for the gRPC call is independent from the `timeout` # field in the request's OptimizeToursRequest message(s). print(fleet_routing_request) operation = fleet_routing_client.batch_optimize_tours(fleet_routing_request) try: # Block to wait for the job to finish. result = operation.result() # Do you stuff. except GoogleAPICallError: print(operation.operation.error) if __name__ == '__main__': if len(sys.argv) > 1: main(sys.argv[1]) else: print('You must include the request file as an argument.')
{ "parent": "projects/${YOUR_GCP_PROJECT_ID}", "model_configs":[ { "input_config":{ "gcs_source":{ "uri":"${REQUEST_MODEL_GCS_PATH}" }, "data_format":"JSON" }, "output_config":{ "gcs_destination":{ "uri":"${MODEL_SOLUTION_GCS_PATH}" }, "data_format":"JSON" } }, { "input_config":{ "gcs_source":{ "uri":"${REQUEST_MODEL_GCS_PATH}" }, "data_format":"JSON" }, "output_config":{ "gcs_destination":{ "uri":"${MODEL_SOLUTION_GCS_PATH}" }, "data_format":"JSON" } }, { "input_config":{ "gcs_source":{ "uri":"${REQUEST_MODEL_GCS_PATH}" }, "data_format":"JSON" }, "output_config":{ "gcs_destination":{ "uri":"${MODEL_SOLUTION_GCS_PATH}" }, "data_format":"JSON" } } ] }
{ "parent":"${YOUR_GCP_PROJECT_ID}", "allowLargeDeadlineDespiteInterruptionRisk":true, "model":{ "shipments":[ { "deliveries":[ { "arrivalLocation":{ "latitude":48.880941999999997, "longitude":2.3238660000000002 }, "duration":"250s", "timeWindows":[ { "endTime":"1970-01-01T01:06:40Z", "startTime":"1970-01-01T00:50:00Z" } ] } ], "loadDemands": { "weight": { "amount": "10" } }, "pickups":[ { "arrivalLocation":{ "latitude":48.874507000000001, "longitude":2.3036099999999999 }, "duration":"150s", "timeWindows":[ { "endTime":"1970-01-01T00:33:20Z", "startTime":"1970-01-01T00:16:40Z" } ] } ] }, { "deliveries":[ { "arrivalLocation":{ "latitude":48.880940000000002, "longitude":2.3238439999999998 }, "duration":"251s", "timeWindows":[ { "endTime":"1970-01-01T01:06:41Z", "startTime":"1970-01-01T00:50:01Z" } ] } ], "loadDemands": { "weight": { "amount": "20" } }, "pickups":[ { "arrivalLocation":{ "latitude":48.880943000000002, "longitude":2.3238669999999999 }, "duration":"151s", "timeWindows":[ { "endTime":"1970-01-01T00:33:21Z", "startTime":"1970-01-01T00:16:41Z" } ] } ] } ], "vehicles":[ { "loadLimits": { "weight": { "maxLoad": 50 } }, "endLocation":{ "latitude":48.863109999999999, "longitude":2.341205 }, "startLocation":{ "latitude":48.863101999999998, "longitude":2.3412039999999998 } }, { "loadLimits": { "weight": { "maxLoad": 60 } }, "endLocation":{ "latitude":48.863120000000002, "longitude":2.341215 }, "startLocation":{ "latitude":48.863112000000001, "longitude":2.3412139999999999 } } ] } }
Run the code
To run the Python code:
- Save the script as
api_client_send_request.py
- Authenticate your environment using the instructions in "Before you begin".
- Create three files in a Cloud Storage bucket with each one containing the content of
request_model.json
above. Replace${YOUR_GCP_PROJECT_NAME}
in that file with your Google Cloud project name. - Create a JSON file called
request.json
in the same directory asapi_client_send_request.py
. Replace${REQUEST_MODEL_GCS_PATH}
with paths of files you just created on Cloud Storage. Replace${MODEL_SOLUTION_GCS_PATH}
with the three different paths for the three model solutions. - At the command line, navigate to the directory containing the files and type the following command:
python api_client_send_request.py request.json
Note that the command passes the name of the request file as an argument.
Response
Long-running operations return a JSON with an operation ID that you can use to get the status of the operation.
After each route is optimized, the solutions are uploaded to the Cloud Storage paths
that you specified in the BatchOptimizeRequest
request payload. If at least one of
BatchOptimizeRequest
inputs results in an error, it is returned directly in a
JSON response for the operation's status.
For example, you should see an operation status similar to the following JSON for a completed
successful :batchOptimizeTours
request.
name: "projects/${YOUR_GCP_PROJECT_NAME}/operations/${OPERATION_ID}" done: true response { type_url: "type.googleapis.com/google.cloud.optimization.v1.BatchOptimizeToursResponse" }
For a description of the response, see Response to the request in the VRP example page.