Open source routing: Exploring Open route service (OSR)

4 minute read

Published:

After trying out OpenTripPlanner and OSRM, we continue to 3rd opensource option which is Open route service (OSR). OSR is efficient routing engine thanks to underlying code in Java and offers typical routing engine in addition to Isochrones and matrix service exposed as HTTP endpoints. One can already try the global server. It is released under GNU General Public License v3.0, and has over 1.1k stars on GitHub with regular commits. Moreover, documentation page is quite thorough. Currently, it supports directions (planning a route), isochrones (finding regions where one can reach from a given location) and matrix api (up to many-to-many routes for any mode of transport).

Setup a local server

As suggested (and also as desired), we will use the docker based solution. Therefore, a prerequisite is to have a docker and docker-compose installed on your system. In this tutorial, I will be using Powershell on windows and will provide possible commands for linux as well. Entire setup to getting started is made super easy by OSR team thanks to docker-compose. We create a new directory (called osr here) and running all commands from this directory:

Invoke-WebRequest https://raw.githubusercontent.com/GIScience/openrouteservice/master/docker-compose.yml -OutFile docker-compose.yml 

Alternatively, on linux:

curl –o docker-compose.yml https://raw.githubusercontent.com/GIScience/openrouteservice/master/docker-compose.yml 

By default, server comes with Heidelberg region’s graph for usage. But, in our case, we would like to use same OSM data of Amsterdam region which we’re using throughout this series. For the same, we first need to download the pbf file and keep that in the same folder.

Invoke-WebRequest https://download.geofabrik.de/europe/netherlands/noord-holland-latest.osm.pbf -OutFile noord-holland-latest.osm.pbf 

Alternatively, on linux:

curl -o  noord-holland-latest.osm.pbf  https://download.geofabrik.de/europe/netherlands/noord-holland-latest.osm.pbf 

Once, we have the desired pbf data then we need to modify the docker-compose.yml to map this pbf file as ` /home/ors/ors-core/data/osm_file.pbf. It can be achieved by uncommenting a line or adding a new in the volume section. In our case, simply add a new line in volume section - ./noord-holland-latest.osm.pbf:/home/ors/ors-core/data/osm_file.pbf. We will restrict our setup to this, however, you can find more information on other options [on the official documentation]( https://giscience.github.io/openrouteservice/installation/Running-with-Docker.html). As a next step, we can run the container with docker-compose up. It will automatically use the docker-compose.yml file and do all mounting. We can send this process to background with -d` option, however, at first trial, let’s observe the results. Upon successful completion, following is screenshot and it took around 2.5 minutes on my system (without SSD) after pulling the docker images. You can learn more about the folder and their usage from here;.

img

To verify if everything is installed, we can directly visit any of this end point from browser of via curl or via Invoke-WebRequest: http://localhost:8080/ors/v2/directions; http://localhost:8080/ors/v2/isochrones and http://localhost:8080/ors/v2/matrix. We can also check http://localhost:8080/ors/v2/health for its status if it is ready or not.

As usual, we will use Python based Jupyter notebook to make same queries as trials with OSRM. There already exist an python package called openrouteservice. However, we will use routingpy as we did in previous blog and its capability to abstract various routing engines.

Jupyter notebook

Following example is based on routingpy and taken from official guide. One can use openroutingservice python package as well, however, in this series, we’re using same abstraction via routingpy which supports many other routing engines.

# Install following requirements (by uncommenting)
# ! pip install routingpy folium
from routingpy.routers import ORS
import folium
# Coordinates for direction query
coordinates = [(4.840713,52.342610),( 4.841656,52.371995),(4.824203,52.384809),(4.774909,52.392150),(4.841184,52.455866)]
# API Server where we've hosted ORS (see blog to setup)
api = ORS(base_url = 'http://localhost:8080/ors')
%%timeit
route = api.directions(locations=coordinates, profile='driving-car')
13.5 ms ± 1.12 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)

Visualize the queried coordinates and provided route in the folium map

my_map = folium.Map(location=coordinates[0][::-1], zoom_start=12, tiles="Stamen Terrain")

# Add all coordinates to the map as marker
for idx, coord in enumerate(coordinates):
    folium.Marker(coord[::-1], tooltip=f"coord-{idx}").add_to(my_map)

# Plot direction as line
folium.PolyLine([coord[::-1] for coord in route.geometry], tooltip="Directions").add_to(my_map)

# Display the map
my_map
Make this Notebook Trusted to load map: File -> Trust Notebook
# Optional to convert data into a geopandas df
# ! pip install routingpy folium shapely geopandas contextily polyline
#from shapely.geometry import LineString, Point
#import geopandas as gpd
#start_end = gpd.GeoDataFrame(geometry=[Point(x,y) for x,y in coordinates], crs="EPSG:4326").to_crs("EPSG:3857")
#route_line = gpd.GeoDataFrame(geometry=[LineString(route.geometry)], crs="EPSG:4326").to_crs("EPSG:3857")

Here, we observe for same query, it takes around 13.5 ms, which is quite fast. This conclude the OSR.

Connect with me on LinkedIn for any questions! "Buy Me A Coffee"