Google ODRD: Routes Preferred ComputeRoutes API

The first Google Mobility API we'll look at is Routes Preferred which is actually two separate APIs - ComputeRoutes, which we will look at in detail here and ComputeRouteMatrix, which we will touch on in the next post.

Part 1: Google Mobility: An introduction to Google ODRD, LMFS and Cloud Fleet Routing APIs
Part 2: Google ODRD: Routes Preferred ComputeRoutes API (this article)
Part 3: Google LMFS: Routes Preferred ComputeRouteMatrix API
Part 4: Google Cloud Fleet Routing: OptimizeTours API
Part 5: Google ODRD: Navigation SDK

Think of ComputeRoutes as an enhanced version of the Google Directions API. Like the Directions API, it calculates the best route from a start point to an end point, including any waypoints along the way. However, ComputeRoutes offers numerous performance enhancements compared to Directions. It's typically faster, provides more precise estimated times of arrival (ETAs), and employs field masks (through the X-Goog-FieldMask header) to reduces latency by allowing you to specify which fields you want the API to return.

💡
To use the ComputeRoutes API you need a valid Routes Preferred API key. Right now, availability is limited to larger enterprise customers. Please contact a Google Maps Partner for access. Once approved, follow this guide to retrieve your API key.

Initially bundled with On Demand Rides and Deliveries (ODRD), the ComputeRoutes API can now be used on its own or in combination with other Google Mobility APIs.

ODRD / Routes Preferred ComputeRoutes example

We'll start with a simple example of a point to point route from East Vancouver (circle marker) to Vancouver Airport (stop 1).

A route created using the Route Preferred ComputeRoutes API

Endpoint POST https://routespreferred.googleapis.com/v1:computeRoutes

Headers
Content-Type: application/json
X-Goog-Api-Key: YOUR_API_KEY (contact a Google Maps Partner for access)
X-Goog-FieldMask: routes.duration, routes.distanceMeters, routes.polyline

Body

{
	"origin": {
		"location": {
			"latLng": {
				"latitude": 49.2806962,
				"longitude": -123.0828679
			}
		}
	},
	"destination": {
		"location": {
			"latLng": {
				"latitude": 49.1951165,
				"longitude": -123.1814231
			}
		}
	},
	"travelMode": "DRIVE",
	"polylineQuality": "OVERVIEW",
	"departureTime": "2023-09-25T15:00:00Z"
}

origin.location.latLng are the coordinates of the route's start location.

destination.location.latLng are the coordinates of the route's end location.

travelMode refers to the mode of transport ("DRIVE", "WALK", "TRANSIT" or "BICYCLE"). Different modes use different routes (e.g. choosing "BICYCLE" means that the route chosen will prioritize bike paths), have different travel speeds and as such, result in different ETAs.

routingPreference offers three choices: "TRAFFIC_UNAWARE," "TRAFFIC_AWARE," and "TRAFFIC_AWARE_OPTIMAL." When you select "TRAFFIC_AWARE," the routing algorithm factors in real-time traffic conditions when calculating routes. On the other hand, "TRAFFIC_AWARE_OPTIMAL" also considers traffic but prioritizes speed over absolute precision, resulting in faster route calculations (although slightly less accuracy) due to certain optimizations designed to reduce latency. If you opt for "TRAFFIC_UNAWARE," the routing relies solely on posted speed limits, which means this option is suitable for deliveries in rural areas or cities where traffic congestion is rarely an issue.

polylineQuality lets you specify the resolution of the encoded polyline e.g. " used to draw the route on a map."HIGH_QUALITY" returns a polyline with a large number of points at the expense of speed while "OVERVIEW" returns one with less points but is much faster. Generally speaking, if you are just drawing the route on a static map and not allowing the user to zoom in, the "OVERVIEW" option works just fine. You can use Google's polyline decoding tool to view the encoded polyline string on the map.

departureTime , when combined with routingPreference: "TRAFFIC_AWARE", is probably the single most important field in the input. It allows you to specify the start time of the route as a datetime string in RFC3339 UTC "Zulu" format e.g. "2023-09-25T15:00:00Z" so that the travel time duration returned by the API takes predicted "real time" traffic into account. The "Z" in the string stands for "Zulu" (GMT +0). Since our route is in Vancouver which is on Pacific Standard Time (GMT +7), "2023-09-25T15:00:00Z" resolves to 8 am on 25th September, 2023.

Note: If departureTime is left empty, it defaults to the time that the request was made. Also, if you set this value to a time in the past, then the request fails.

🌎
This is a collection of what I feel are the most important fields to use when making a ComputeRoutes call. The official documentation for Routes Preferred / Compute Routes has the complete list.

The above API call returns the following:

Output

{
    "routes": [
        {
            "distanceMeters": 16797,
            "duration": "1802s",
            "polyline": {
                "encodedPolyline": "ecxkH|rfnV?sAfARl@TpBpAz@Rh@F`CHr@ClCDBgChBBJo`@hSHjNJf@Bb@JhELnD@tAKPIzPJtGHPHvNRhGIdIB~@Yj@g@R[Vm@h@}A\\k@j@e@r@Qn@ChUZlD@tF@|@F`HNxCBpFFVMd`@ZRNxIDvBL^FNGdEp@bBLxCJ~E@nIJZP`FHCzH?jFFTSrn@Kb@GtOEjOFj@Ol^Gb@S~Y?lDi@~j@IdGMrGUfQbEJtOPvSRjBHh\\d@ra@f@rMPxQ\\LBt@EzCxIPVxB~GFl@nB`GbDrKxDpLnCdJj@|Bj@lBfApCb@xA\\nBNRz@xCzB`Hj@vAj@`AbAfAt@h@xAh@zBp@LJbG~A`PvElAj@v@f@pAxA`A|Ax@pBh@lBJd@`AhIxC|XxBvTz@zHNjBNnDTtETlHBrBBvLEny@EtXGpBSdCQbAk@vBi@xAmCfGWhAe@nGa@vH@tBN`Cd@~CPb@DF"
            }
        }
    ]
}

The response from the API is simple enough to understand. routes contains a single object with distanceMeters, the total distance travelled, duration, the total time in seconds taken to complete the route (the ETA at the end point is simply the start time (2023-09-25T15:00:00Z is 08:00:00 Vancouver time which when added to the 1802 seconds duration , which gives you an ETA of 08:30:02).

Finally, the encoded polyline from the polyline.encodedPolyline field can be used with the Google Maps Geometry Library to draw the route on a map like so:

Drawing the route polyline on Google Maps

Starting with a basic HTML template with a map <div/>, import the Geometry library.

/* routeMap.html */
<html>
  <head>
    <title>Draw Route</title>
    <script src="https://maps.googleapis.com/maps/api/js?key=GOOGLE_API_KEY&v=3.exp&libraries=geometry&callback=Function.prototype"></script>
  </head>
  <body>
    <div id="map" style="height: 600px; width: 100%;"></div>
    
  </body>
</html>

Next, inside a script tag next to the map <div/>, create a Google base map and center it at the desired location. The code below calls initMap() to create the map and bind it to a div with "map" as its ID.

/* routeMap.html */
<script>
var map;

function initMap() {
	map = new google.maps.Map(document.getElementById('map'), {
		center: {
			lat: 49.2578182,
			lng: -123.206304
		},
		zoom: 12 // Adjust the zoom level as needed
	});
}

initMap();
</script>

Add two markers, one for the origin and the other for the destination. This code should be added after the call to initMap().

/* routeMap.html */
<script>
var startMarker = new google.maps.Marker({
	position: {
		lat: 49.2806962,
		lng: -123.0828679
	},
	map: map,
	title: 'Start'
});

var endMarker = new google.maps.Marker({
	position: {
		lat: 49.1951165,
		lng: -123.1814231
	},
	map: map,
	title: 'End'
});
</script>

Lastly, decode the polyline string, style it, and add it to the map.

/* routeMap.html */
<script>
var decodedPath = google.maps.geometry.encoding.decodePath("ecxkH|rfnV?sAfARl@TpBpAz@Rh@F`CHr@ClCDBgChBBJo`@hSHjNJf@Bb@JhELnD@tAKPIzPJtGHPHvNRhGIdIB~@Yj@g@R[Vm@h@}A\\k@j@e@r@Qn@ChUZlD@tF@|@F`HNxCBpFFVMd`@ZRNxIDvBL^FNGdEp@bBLxCJ~E@nIJZP`FHCzH?jFFTSrn@Kb@GtOEjOFj@Ol^Gb@S~Y?lDi@~j@IdGMrGUfQbEJtOPvSRjBHh\\d@ra@f@rMPxQ\\LBt@EzCxIPVxB~GFl@nB`GbDrKxDpLnCdJj@|Bj@lBfApCb@xA\\nBNRz@xCzB`Hj@vAj@`AbAfAt@h@xAh@zBp@LJbG~A`PvElAj@v@f@pAxA`A|Ax@pBh@lBJd@`AhIxC|XxBvTz@zHNjBNnDTtETlHBrBBvLEny@EtXGpBSdCQbAk@vBi@xAmCfGWhAe@nGa@vH@tBN`Cd@~CPb@DF");

var polyline = new google.maps.Polyline({
	path: decodedPath,
	geodesic: true,
	strokeColor: '#4285F4', // Adjust the color as needed
	strokeOpacity: 0.9,
	strokeWeight: 3 // Adjust the line thickness as needed
});

polyline.setMap(map);
</script>

If everything worked correctly you should see the route clearly displayed on the map, with a marker at the start and end locations (full source code).

The route polyline returned by the Google Routes Preferred ComputeRoutes API

This concludes my introduction to the Routes Preferred ComputeRoutes API. In the next post, we'll look at another popular Routes Preferred API, ComputeRouteMatrix, which is used to generate travel time matrices with real time traffic.

👋 As always, if you have any questions or suggestions for me, please reach out or say hello on LinkedIn.

Next: Part 3: Google LMFS: Routes Preferred ComputeRouteMatrix API