Using R with Routino to provide road network paths between random Tweets and an iconic Smiths landmark

Routino is an open source road network routing library (based on OpenStreetMap data) which runs under both Linux and OSX. For details about how to install the library under OSX see the following blog post.

It is entirely possible to create a wrapper for Routino in R, and indeed, I may well do this if I get time; however, in order to get started right away, it is possible for R to call the library using the “system” function.

In this example, a transport network route is calculated between two random Tweets that were geolocated within 20 miles of Manchester and the Salford Lads Club. For [Smiths]fans(, this can be found at (53.476485,-2.274704).

There is no particular reason for these rather arbitrary locations, other than the extra benefit of some code which shows how to extract locations from Twitter; do some routing using Routino; and then plot the results on top of a google map.

Get two random Tweet locations to act as example start points

# Load Packages

In addition to the twitteR package, the a further package RJSONIO is needed to prevent an error that occurs occasionally when running the function “lookupUsers” - this sometimes returns the error: (Error in .self$twFromJSON(out) : Error: Malformed response from server, was not JSON)


The next stage is to run a search query with a radius of 20 miles - the example here will not be reproducible exactly as a different set of Tweets will be returned. I am also amusing that you will get at least two tweets with latitude and longitude.

# Do a twitter search for 20 miles around centre manchester
tweets <- searchTwitter("", n = 500, geocode = "53.482,-2.249,20mi")

# Extract the screen names from each of the tweets
l <- length(tweets)
tweeter <- vector(mode = "character", length = l)
for (i in 1:l) tweeter[i] <- tweets[[i]]$getScreenName()

# Remove duplicate tweeters to reduce api load
tweeter <- unique(tweeter)
users <- lookupUsers(tweeter[1:length(tweeter)], includeNA = TRUE)
l <- length(users)
locs <- NULL

# Get the locations
for (i in 1:length(users)) {
    users.locations <- users[[i]]$location
    locs <- c(locs, users.locations)

# Extract those locations with lat lon
install.packages("stringr", dependencies = TRUE)
locs_2 <- str_extract(locs, "(\\-?\\d+(\\.\\d+)?),\\s*(\\-?\\d+(\\.\\d+)?)$")
locs_2 <- locs_2[!]

# Pick two random locations
start_end <- sample(locs_2, 2)

Preparing to run a Routino query

Before running a Routino query, you will need to ensure this library is installed. I have detailed how to do this under OSX on my blog here.

The first stage in running a Routino query is to load some OpenStreetMap data. Subsets can be downloaded from:

*Cloudmade -
*Geofabrik -

In this example, a GB data set is loaded.

On the terminal in OSX, you need to run the following code to load the OSM data. This assumes that the Routino files and the OSM data are found on your desktop:


planetsplitter --prefix=gb --max-iterations=10 /Users/alex/Desktop/great_britain.osm --tagging=/Users/alex/Desktop/routino-2.3.2/web/data/tagging.xml

Running a Routino query from within R

In the following example, the Salford Lads Club and Twitter latitude longitude locations are sent to the terminal as part of a Routino “Router” query. The distance traveled from the route is then output to the terminal. No error checking is implemented here to see if the quickest-all.txt is returned - in more extensive applications this is however necessary as this is only created for valid routes.

fileloc <- "/Users/alex/Desktop/quickest-all.txt"  #This is the default working directory

# Split lat / lon into a list
start_end <- strsplit(start_end, ",")

for (i in 1:length(start_end)) {
    # Get the lat / lon
    lat <- start_end[[i]][1]
    lon <- start_end[[i]][2]

    router <- paste("router --transport=motorcar --prefix=gb --quickest  --lon1=", 
        lon, " --lat1=", lat, " --lon2=-2.274704   --lat2=53.476485  --output-text-all  --quiet --output-gpx-track --translations=/Users/alex/Desktop/routino-2.3.2/xml/routino-translations.xml --profiles=/Users/alex/Desktop/routino-2.3.2/xml/routino-profiles.xml --dir=/Users/alex/Desktop/routino-2.3.2/", 
        sep = "")

    system(router, wait = TRUE)  # Send the routing command

    # Read in the txt instructions to extract the network distance
    routeresults <- read.delim(fileloc, header = FALSE, sep = "\t", skip = 4)

    # Print the distance of the route
    km <- max(as.numeric(routeresults$V7))/1000
    print(paste(km, "km"))

    # Remove the route
    system(" rm /Users/alex/quickest-all.txt", wait = TRUE)

## [1] "0.062 km"
## [1] "0.131 km"

Another file that can be returned from Routino is a .GPX, which unlike the text file from the above example (waypoints), contains turn by turn lat lon locations of the route. The following example will create a basic map of the first route returned.

# Setup GPX file location
fileloc <- "/Users/alex/Desktop/quickest-track.gpx"

# Get some libraries

# Set the record to extract
i <- 1

# Get the lat / lon
lat <- start_end[[i]][1]
lon <- start_end[[i]][2]

# Specify the router query
router <- paste("router --transport=motorcar --prefix=gb --quickest  --lon1=", 
    lon, " --lat1=", lat, " --lon2=-2.2327780723571777   --lat2=53.46523734631251  --output-text-all --quiet --profiles=/Users/alex/Desktop/routino-2.3.2/xml/routino-profiles.xml --dir=/Users/alex/Desktop/routino-2.3.2/", 
    sep = "")

system(router, wait = TRUE)  # Send the routing command

# Read in the GPX
routeresults <- readOGR(fileloc, layer = "track_points")
routeresults@data$lon <- coordinates(routeresults)[, 1]
routeresults@data$lat <- coordinates(routeresults)[, 2]
# Map the results - this shows a map for central Machester at zoom level
# 13
Manc <- get_map(c(lon = -2.274704, lat = 53.476485), zoom = 13, source = "google", 
    maptype = "terrain", color = "bw")
Manc <- ggmap(Manc)
Manc <- Manc + geom_path(data = routeresults@data, aes(x = routeresults@data$lon, 
    y = routeresults@data$lat), colour = "red", alpha = 0.6, size = 1.5)

plot of chunk map