Traffic networks with google elevation api
Integrating traffic networks with google elevation api for an area in Melbourne. Then calculate the shortest path which accounts for grade impedance.
- Get a network and add elevation to its nodes
- Calculate several stats
- Shortest paths account for grade impedance
import os
import numpy as np
import geopandas as gpd
import osmnx as ox
ELEVATION_API = os.environ.get('GCP_ELEVATION_API')
GMB = ox.graph_from_place("Greater Melbourne, Victoria, Australia", network_type='all')
len(GMB.nodes), len(GMB.edges)
GM = ox.graph_from_place("City of Monash, Victoria, Australia", network_type='all')
len(GM.nodes), len(GM.edges)
place = "Oakleigh"
place_query = "Oakleigh, the city of Monash, Victoria, 3166, Australia"
G = ox.graph_from_place(place_query, network_type='bike')
len(G.nodes), len(G.edges)
fig, ax = ox.plot_graph(G)
G = ox.add_node_elevations(G, api_key=ELEVATION_API)
G = ox.add_edge_grades(G)
edge_grades = [data['grade_abs'] for u, v, k, data in ox.get_undirected(G).edges(keys=True, data=True)]
avg_grade = np.mean(edge_grades)
print('Average street grade in {} is {:.1f}%'.format(place, avg_grade*100))
med_grade = np.median(edge_grades)
print('Median street grade in {} is {:.1f}%'.format(place, med_grade*100))
nc = ox.plot.get_node_colors_by_attr(G, 'elevation', cmap='plasma')
fig, ax = ox.plot_graph(G, node_color=nc, node_size=5, edge_color='#333333', bgcolor='k')
ec = ox.plot.get_edge_colors_by_attr(G, 'grade_abs', cmap='plasma', num_bins=5, equal_size=True)
fig, ax = ox.plot_graph(G, edge_color=ec, edge_linewidth=0.5, node_size=0, bgcolor='k')
from shapely.geometry import Polygon, Point
orig = (-37.8943, 145.0900)
dest = (-37.9059, 145.1030)
# Check the distance
Point(orig).distance(Point(dest))
orig = ox.get_nearest_node(G, orig)
dest = ox.get_nearest_node(G, dest)
bbox = ox.utils_geo.bbox_from_point((-37.9001, 145.0965), dist=1500)
def impedance(length, grade):
penalty = grade ** 2
return length * penalty
def impedance_2(length, grade):
penalty = length * (np.abs(grade) ** 3)
return penalty
for u, v, k, data in G.edges(keys=True, data=True):
# data['impedance'] = impedance(data['length'], data['grade_abs'])
data['impedance'] = impedance_2(data['length'], data['grade'])
data['rise'] = data['length'] * data['grade']
route_by_length = ox.shortest_path(G, orig, dest, weight='length')
fig, ax = ox.plot_graph_route(G, route_by_length, node_size=0)
route_by_impedance = ox.shortest_path(G, orig, dest, weight='impedance')
fig, ax = ox.plot_graph_route(G, route_by_impedance, node_size=0)
def print_route_stats(route):
route_grades = ox.utils_graph.get_route_edge_attributes(G, route, 'grade_abs')
msg = 'The average grade is {:.1f}% and the max is {:.1f}%'
print(msg.format(np.mean(route_grades)*100, np.max(route_grades)*100))
route_rises = ox.utils_graph.get_route_edge_attributes(G, route, 'rise')
ascent = np.sum([rise for rise in route_rises if rise >= 0])
descent = np.sum([rise for rise in route_rises if rise < 0])
msg = 'Total elevation change is {:.1f} meters: a {:.0f} meter ascent and a {:.0f} meter descent'
print(msg.format(np.sum(route_rises), ascent, abs(descent)))
route_lengths = ox.utils_graph.get_route_edge_attributes(G, route, 'length')
print('Total trip distance: {:,.0f} meters'.format(np.sum(route_lengths)))
print_route_stats(route_by_length)
print_route_stats(route_by_impedance)