osrm
Interface between R and the OpenStreetMap-based routing service OSRM
Description
OSRM is a routing service based on OpenStreetMap data. See http://project-osrm.org/ for more information. This package enables the computation of routes, trips, isochrones and travel distances matrices (travel time and kilometric distance) with R.
This package relies on the usage of a running OSRM service (tested with v6.0.0 of OSRM).
You can run your own instance of OSRM following guidelines provided
here. A simple solution
is to use docker
containers
and you can find and exemple of building a European-wide OSRM Server
here.
Alternatively, you can use
osrm.backend, an R package
that installs and controls OSRM executables to prepare routing data and
run/stop a local server.
⚠ You must be careful using the OSRM demo server and read the about page of the service:
Features
osrmTable()uses the table service to query time/distance matrices,osrmRoute()uses the route service to query routes,osrmTrip()uses the trip service to query trips,osrmNearest()uses the nearest service to query the nearest point(s) on the street network,osrmIsochrone()andosrmIsodistance()use multipleosrmTable()calls to create isochrones or isodistances polygons.
Demo
This is a short overview of the main features of osrm. The dataset
used here is shipped with the package, it is a sample of 100 random
pharmacies in Berlin (© OpenStreetMap
contributors) stored in a
geopackage file.
Time / distance matrices
osrmTable() gives access to the table OSRM service. In this example
we use this function to get the median time needed to access any
pharmacy from any other pharmacy.
library(osrm)
library(sf)
pharmacy <- st_read(system.file("gpkg/apotheke.gpkg", package = "osrm"),
quiet = TRUE)
travel_time <- osrmTable(loc = pharmacy)
travel_time$durations[1:5,1:5]## 1 2 3 4 5
## 1 0.0 21.1 33.4 21.2 12.6
## 2 22.1 0.0 42.3 16.1 20.2
## 3 33.0 43.0 0.0 30.5 27.4
## 4 20.1 15.3 29.7 0.0 12.7
## 5 10.2 20.3 26.8 12.3 0.0diag(travel_time$durations) <- NA
median(travel_time$durations, na.rm = TRUE)## [1] 21.4The median time needed to access any pharmacy from any other pharmacy is 21.4 minutes.
Routes
osrmRoute() is used to compute the shortest route between two points.
Here we compute the shortest route between the two first pharmacies.
(route <- osrmRoute(src = pharmacy[1, ], dst = pharmacy[2, ]))## Simple feature collection with 1 feature and 4 fields
## Geometry type: LINESTRING
## Dimension: XY
## Bounding box: xmin: -13177 ymin: 5837172 xmax: -3875.06 ymax: 5841047
## Projected CRS: WGS 84 / UTM zone 34N
## src dst duration distance geometry
## 1_2 1 2 21.68333 12.5251 LINESTRING (-13170.51 58410...This route is 12.5 kilometers long and it takes 21.7 minutes to drive through it.
plot(st_geometry(route), main = "Route")
plot(st_geometry(pharmacy[1:2,]), pch = 20, add = T, cex = 1.5)Travelling salesman problem
osrmTrip() can be used to resolve the travelling salesman problem, it
gives the shortest trip between a set of unordered points. In this
example we want to obtain the shortest trip between the first five
pharmacies.
(trips <- osrmTrip(loc = pharmacy[1:5, ], overview = "full"))## [[1]]
## [[1]]$trip
## Simple feature collection with 5 features and 4 fields
## Geometry type: LINESTRING
## Dimension: XY
## Bounding box: xmin: -13431.44 ymin: 5837172 xmax: -3875.322 ymax: 5856333
## Projected CRS: WGS 84 / UTM zone 34N
## start end duration distance geometry
## 1 1 2 21.68333 12.5251 LINESTRING (-13170.77 58410...
## 2 2 4 16.26667 8.4495 LINESTRING (-3875.322 58379...
## 3 4 3 30.04667 18.1690 LINESTRING (-7444.513 58427...
## 4 3 5 27.85167 16.4466 LINESTRING (-8024.73 585621...
## 5 5 1 9.80000 4.2308 LINESTRING (-11716.82 58435...
##
## [[1]]$summary
## [[1]]$summary$duration
## [1] 105.6483
##
## [[1]]$summary$distance
## [1] 59.821The shortest trip between these pharmacies takes 105.6 minutes and is 59.8 kilometers long. The steps of the trip are described in the “trip” sf object (point 1 > point 2 > point 4 > point 3 > point 5 > point 1).
par(mar = c(0,0,3,0))
mytrip <- trips[[1]]$trip
# Display the trip
plot(st_geometry(mytrip), col = c("black", "grey"), lwd = 2, main = "Trip")
plot(st_geometry(pharmacy[1:5, ]), cex = 1.5, pch = 21, add = TRUE)
text(st_coordinates(pharmacy[1:5,]), labels = row.names(pharmacy[1:5,]),
pos = 2)Point(s) on the street network
osrmNearest() returns the nearest point(s) on the street network from
any point. Here we will get the nearest point on the network from a
couple of coordinates.
pt_not_on_street_network <- c(13.40, 52.47)
(pt_on_street_network <- osrmNearest(loc = pt_not_on_street_network))## Simple feature collection with 1 feature and 2 fields
## Geometry type: POINT
## Dimension: XY
## Bounding box: xmin: 13.39671 ymin: 52.46661 xmax: 13.39671 ymax: 52.46661
## Geodetic CRS: WGS 84
## id distance geometry
## loc loc 439 POINT (13.39671 52.46661)The distance from the input point to the nearest point on the street network is of 439 meters
Isochrones
osrmIsochrone() computes areas that are reachable within a given time
span from a point and returns the reachable regions as polygons. These
areas of equal travel time are called isochrones. Here we compute the
isochrones from a specific point defined by its longitude and latitude.
(iso <- osrmIsochrone(loc = c(13.43,52.47), breaks = seq(0,12,2), n = 1000, smooth = F))## Simple feature collection with 5 features and 3 fields
## Geometry type: MULTIPOLYGON
## Dimension: XY
## Bounding box: xmin: 13.32727 ymin: 52.41842 xmax: 13.50226 ymax: 52.51358
## Geodetic CRS: WGS 84
## id isomin isomax geometry
## 1 1 0 4 MULTIPOLYGON (((13.4315 52....
## 2 2 4 6 MULTIPOLYGON (((13.44048 52...
## 3 3 6 8 MULTIPOLYGON (((13.44946 52...
## 4 4 8 10 MULTIPOLYGON (((13.4315 52....
## 5 5 10 12 MULTIPOLYGON (((13.44048 52...bks <- sort(unique(c(iso$isomin, iso$isomax)))
pals <- hcl.colors(n = length(bks) - 1, palette = "Light Grays", rev = TRUE)
plot(iso["isomax"], breaks = bks, pal = pals,
main = "Isochrones (in minutes)", reset = FALSE)
points(x = 13.43, y = 52.47, pch = 4, lwd = 2, cex = 1.5)Installation
You can install the released version of osrm from
CRAN with:
install.packages("osrm")Alternatively, you can install the development version of osrm (the
dev branch) from r-universe
with:
install.packages("osrm", repos = "https://riatelab.r-universe.dev")Community Guidelines
One can contribute to the package through pull requests and report issues or ask questions here. See the CONTRIBUTING.md file for detailed instructions.
Acknowledgements
Many thanks to the editor (@elbeejay) and reviewers (@JosiahParry,
@mikemahoney218 and @wcjochem) of the JOSS article.
This publication has led to a significant improvement in the code base
and documentation of the package.