Como usar a API Python OpenRouteService?
- Carlos Silva
- 16 de out. de 2022
- 3 min de leitura
Atualizado: 19 de mar. de 2024
Muitas vezes eu preciso fazer consultas rápidas de distância e em quantidades inviáveis de fazer no Google Maps uma a uma. É uma demanda de informação recorrente para planejamento operacional e estratégico já que transportar coisas tem alto custo. Por isso achei a solução do OpenRouteService muito interessante pra resolver esse problema.
O primeiro passo é criar uma conta e criar uma chave no openrouteservice.org, a documentação é boa ao ponto de eu não querer entrar em detalhes aqui, basicamente você faz um login (pode ser com sua conta do github) e vai na aba Dashboard para criar uma chave. Na aba API Playground também mostra muita coisa interessante.
Fazendo uma uma requisição através da API Python OpenRouteService
Você pode encontrar mais detalhes sobre alguns parâmetros na documentação do github e mais sobre os tipos de roteamento aqui. Aqui estou fazendo uma consulta de Ponta Grossa - PR até o porto de Paranaguá - PR, que é uma rota logística convencional para escoamento de produtos industriais.
key='Sua chave aqui' #Chave da API
client = openrouteservice.Client(key) #Fazendo a conexão com o serviço
coords = ((-50.184777 , -25.122125),(-48.519270 , -25.503800)) #Coordenadas de origem e destino, pode ter coordenadas intermediárias
routes = client.directions(coordinates=coords,
profile='driving-hgv', #Tipo de rota, nesse caso , transporte logístico e afins
format='geojson', #Formato de saída
validate=False,
radiuses=5000, #Raio em metros de busca de trechos de estrada
extra_info=["waycategory", #Categoria de caminho
"waytype", #Tipo de caminho
"surface"] #Tipo de superfície
)
#Salvando os resultados em um json
import json
with open('data.json', 'w') as f:
json.dump(routes, f)
Geometria e a distância.
Dentro desse arquivo geojson existe muitas coisas, porém vou ressaltar duas, a geometria e a distância.
# A quantidade de quilômetros da rota e as coordenadas que compõem a geometria da linha
dist = str(round(routes['features'][0]['properties']['summary']['distance']/1000,2))+" km"
print(dist)
LineString(routes['features'][0]['geometry']['coordinates'])

Também é possível ver atributos extras da rota, mas tem que indicar no momento da requisição que você deseja eles, veja aqui na documentação.
routes['features'][0]['properties']['extras']

Se verificarmos o tipo de superfície encontramos o tipo 3 e 1, que são asfalto e pavimentada respectivamente.
routes['features'][0]['properties']['extras']['surface']['summary']

Dando uma olhada com o folium percebe-se que ele prefere ir pelo anel rodoviário de Curitiba, que não é a rota mais curta porém é recomendado para o tipo de transporte que foi parametrizado.

E se eu quiser saber a rota de várias origens e destinos de uma vez só?
Primeiro vou montar um DataFrame com as origens e destinos.
DataTable = {'Rota': ['Imbaú, PR - Ponta Grossa, PR', 'Ponta Grossa, PR - Curitiba, PR'],
'OrigemLong':[-50.7516409,-50.2396862],
'OrigemLat':[-24.4603571,-25.0622996],
'DestinoLong':[-50.2396862,-49.337566],
'DestinoLat':[-25.0622996,-25.431829],
}
df = pd.DataFrame(data=DataTable)
Com a função abaixo eu consigo pegar as informações desse DataFrame e pedir para extrair do serviço a informação da distância e da geometria e criar um GeoDataFrame com as rotas, a lógica das informações é igual a anterior, só que vou linha a linha capturando as informações e fazendo as solicitações e depois adiciono elas como novas colunas no GeoDataFrame.
def openrouteservice_dist(df, #DataFrame
OrigemLong, #Longitude da origem
OrigemLat, #Latitude da origem
DestinoLong, #Longitude do destino
DestinoLat, #Latitude do destino
key, #Chave da API
radiuses=5000, #Raio de busca de estradas
profile='driving-hgv', #Tipo ded roteamento
printprocess=False): #Printar em que linha está roteando
dist = []
geo = []
for i in df.index:
coords = ((df[OrigemLong][i],df[OrigemLat][i]),(df[DestinoLong][i],df[DestinoLat][i]))
client = openrouteservice.Client(key=key)
routes = client.directions(coordinates=coords,
profile=profile,
format='geojson',
validate=False,
radiuses=radiuses)
dist.append(round(routes['features'][0]['properties']['summary']['distance']/1000,2))
geo.append(LineString(routes['features'][0]['geometry']['coordinates']))
time.sleep(2)
if printprocess:
print(i)
df['Dist'] = dist
df['geometry']=geo
df = gp.GeoDataFrame(df)
return df
df = openrouteservice_dist(df,'OrigemLong','OrigemLat','DestinoLong','DestinoLat',
key, radiuses=5000, profile='driving-hgv')
#Criando uma Shapefile das rotas geradas
df.set_crs(epsg=4326).to_file('routes.shp')

Bonûs
Também posso ter resultados parecidos fazendo requests sem ter que usar a API Python do OpenRouteService.
import requests
body = {"locations":[[9.70093,48.477473],[9.207916,49.153868],[37.573242,55.801281],[115.663757,38.106467]],"metrics":["distance"],"units": "km"}
headers = {
'Accept': 'application/json, application/geo+json, application/gpx+xml, img/png; charset=utf-8',
'Authorization': 'Sua chave aqui',
'Content-Type': 'application/json; charset=utf-8'
}
call = requests.post('https://api.openrouteservice.org/v2/matrix/driving-hgv', json=body, headers=headers)
print(call.status_code, call.reason)
print(call.text)
Considerações finais
O resultado das consultas é detalhado e bem parametrizável.
Existe um limite de consultas do plano gratuito (2000/Dia e 40/min), porém é um projeto Open Source, e existe uma documentação de instalação.
É uma solução mais rápida, detalhada e de melhor desempenho do que a do meu último post sobre roteamento, você pode dar uma olhada nele aqui.
Comments