Routing Tutorial – Part 1: Introduction to Routing

Intro

In this tutorial I'll show you how to set up a local instance of Open Source Routing Machine (OSRM) server using Docker.

If you don't know what Docker is or how to install it, please refer to the documentation.

Example

Setting up OSRM in Ubuntu using Docker

Using Bash, navigate to a directory where you have permissions to read and write.

# create a directory for the data, sudo su for superuser credentials
mkdir -p data/osrm/malta
cd /data/osrm/malta

# download the OSM data for Malta
wget https://download.geofabrik.de/europe/malta-latest.osm.pbf

# run the osrm-extract command to extract the data from the PBF file
docker run -t -v $(pwd):/data osrm/osrm-backend osrm-extract -p /opt/car.lua /data/malta-latest.osm.pbf

# run the osrm-partition command to partition the graph for faster routing
docker run -t -v $(pwd):/data osrm/osrm-backend osrm-partition /data/malta-latest.osrm

# run the osrm-customize command
docker run -t -v $(pwd):/data osrm/osrm-backend osrm-customize /data/malta-latest.osrm

# run the container
docker run -t -i -p 5000:5000 -v $(pwd):/data osrm/osrm-backend osrm-routed --algorithm mld /data/malta-latest.osrm

Setting up OSRM in Windows

Please be sure that Docker is installed. Installing Docker in Windows systems may not be so straight-forward as installing it in Linux-based environments. In Windows, you'll also need to be running Docker Desktop.

Using PowerShell, navigate to a directory where you have permissions to read and write.

We'll be using Open Street Map data for the country of Malta, provided by Geofabrik as a PBF file. Download the file and place it in the directory you're working in.

md -Force  C:\Users\guillermo\Documents\data\osrm\malta

cd C:\Users\guillermo\Documents\data\osrm\malta

curl.exe -O https://download.geofabrik.de/europe/malta-latest.osm.pbf

Now, we'll run the osrm-extract and several other commands to extract the data from the PBF file, generate the data for OSRM and partition it for faster routing. The graph will be generated using the car routing profile, there are other profiles available, but we'll stick with the default for now.

# osrm-extract
docker run -t -v "$(pwd):/data" osrm/osrm-backend osrm-extract -p /opt/car.lua /data/malta-latest.osm.pbf

# osrm-partition
docker run -t -v "$(pwd):/data" osrm/osrm-backend osrm-partition /data/malta-latest.osrm

# osrm-customize
docker run -t -v "$(pwd):/data" osrm/osrm-backend osrm-customize /data/malta-latest.osrm

We're now ready to run the docker run command to start the OSRM server. We'll use the -p flag to expose port 5000 on the host machine, and the -v flag to mount the current directory as /data inside the container.

# run the container
docker run -t -i -p 5000:5000 -v "$(pwd):/data" osrm/osrm-backend osrm-routed --algorithm mld /data/malta-latest.osrm

Since the exposed port is the 5000, you can check if the service is up by visiting this URL in your browser: [http://127.0.0.1:5000/]Duck Duck Go.

You should see this message:

{"message":"URL string malformed close to position 1: \"\/\"","code":"InvalidUrl"}

A proper query for testing would be something like this: http://127.0.0.1:5000/route/v1/driving/14.5035,35.8976;14.5144,35.8989?overview=full&geometries=geojson

The response is a JSON dictionary, that contains the calculated fastest route between the two input pair of coordinates, among other things.

You can also send a request to the server using curl:

curl "http://127.0.0.1:5000/route/v1/driving/14.5035,35.8976;14.5144,35.8989?overview=full&geometries=geojson"

You can visualize this in QGIS, using the following pyQGIS code, executed for the Python console:

from qgis.core import (
    QgsProject, 
    QgsVectorLayer, 
    QgsFeature, 
    QgsGeometry, 
    QgsPointXY
)
import json
import urllib.request

URL = "http://127.0.0.1:5000/route/v1/driving/14.5035,35.8976;14.5144,35.8989?overview=full&geometries=geojson"


def load_route_from_osrm(url):
    """Fetch route from OSRM server and create a QGIS line layer"""  
    try:
        with urllib.request.urlopen(url) as response:
            data = json.loads(response.read().decode('utf-8'))

        if data.get('code') != 'Ok' or not data.get('routes'):
            print("Error: No valid route found in response")
            return None

        # Extract coordinates from the first route
        coordinates = data['routes'][0]['geometry']['coordinates']

        # Create memory layer
        layer = QgsVectorLayer("LineString?crs=EPSG:4326", "OSRM Route", "memory")
        provider = layer.dataProvider()

        # Create and add feature
        feature = QgsFeature()
        points = [QgsPointXY(lon, lat) for lon, lat in coordinates]
        feature.setGeometry(QgsGeometry.fromPolylineXY(points))
        provider.addFeature(feature)

        # Add to project and zoom
        QgsProject.instance().addMapLayer(layer)
        iface.mapCanvas().setExtent(layer.extent())
        iface.mapCanvas().refresh()

        print(f"Route loaded with {len(points)} points")
        return layer

    except Exception as e:
        print(f"Error: {str(e)}")
        return None

# Run the function
load_route_from_osrm(URL)

Example result:

malta

Conclusion

Now you have you own instance of OSRM! In the follow-up, will work on how to send queries and get responses using Python.

References

Ruteo de alta perfomance con OSRM

Project OSRM

Comments

There are no comments yet.

  • captcha