I had a chance to work on a taxi ordering service with a low budget. While working on in I found two most expensive parts in the solutions:

  • Reverse geocoding (Translating address to coordinate)
  • Finding distance between two coordinates. (Correct one using route network, cabs can't fly. Yet)

In this blog post I will talk about solving one of two problems - finding distance and route between two coordinates and predicting trip time.

Initially we thought, Google has an API for that. And while this is true, Google Directions API is pricey. It cost quite a lot. So we went to look for alternatives. And we found OSRM - Open Source Routing Machine.

OSRM is a project which provides a REST API to get directions. What is best - it doesn't need any external database, only OpenStreetMap data file for your country with some preprocessing.

Starting with it is quite simple, they even have a Docker image for it.

Instructions on their GitHub page is simple:

Download OpenStreetMap extracts for example from Geofabrik

wget http://download.geofabrik.de/europe/germany/berlin-latest.osm.pbf

Pre-process the extract with the car profile and start a routing engine HTTP server on port 5000

docker run -t -v "${PWD}:/data" osrm/osrm-backend osrm-extract -p /opt/car.lua /data/berlin-latest.osm.pbf

The flag -v "${PWD}:/data" creates the directory /data inside the docker container and makes the current working directory "${PWD}" available there. The file /data/berlin-latest.osm.pbf inside the container is referring to "${PWD}/berlin-latest.osm.pbf" on the host.

docker run -t -v "${PWD}:/data" osrm/osrm-backend osrm-partition /data/berlin-latest.osrm
docker run -t -v "${PWD}:/data" osrm/osrm-backend osrm-customize /data/berlin-latest.osrm

Note that berlin-latest.osrm has a different file extension.

docker run -t -i -p 5000:5000 -v "${PWD}:/data" osrm/osrm-backend osrm-routed --algorithm mld /data/berlin-latest.osrm

Make requests against the HTTP server

curl "http://127.0.0.1:5000/route/v1/driving/13.388860,52.517037;13.385983,52.496891?steps=true"

Optionally start a user-friendly frontend on port 9966, and open it up in your browser

docker run -p 9966:9966 osrm/osrm-frontend
xdg-open 'http://127.0.0.1:9966'

What we did different?

  • We made a Docker image with pre-processed data for our country:
FROM osrm/osrm-backend
RUN apt update && apt install -y curl
EXPOSE 5000
RUN mkdir -p /data
RUN curl -sSL --output /data/extract.pbf http://download.geofabrik.de/europe/lithuania-latest.osm.pbf && \
    osrm-extract -p /opt/car.lua /data/extract.pbf && \
    osrm-partition /data/extract.osrm && \
    osrm-customize /data/extract.osrm && \
    rm -f /data/extract.pbf
ENTRYPOINT ["osrm-routed", "--algorithm", "mld", "/data/extract.osrm"]
Dockerfile
  • Created a pipeline to generate new image and deploy a new version periodically.