Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OSRM bicycle routing returns same as driving profile #246

Closed
cgthigpen opened this issue Apr 3, 2018 · 6 comments
Closed

OSRM bicycle routing returns same as driving profile #246

cgthigpen opened this issue Apr 3, 2018 · 6 comments

Comments

@cgthigpen
Copy link

Thank you for developing such a useful package for transport planners and researchers. I last looked at this package a few months ago, and a lot of functionality has been added that has lured me in to test the waters.

I have encountered an issue with the routes returned by the route_osrm function when I specify "bicycling". I have compared the bicycle routes with what is returned for the driving profile, and it's identical. In particular, this is troublesome when the bicycle routes that get returned are on freeways...

I've attached a toy example that replicates my issue. As you can hopefully recreate, the bicycle route is identical to the driving route. Is this because I'm using the wrong term for the bicycle profile? Or does this seem to be a OSM problem rather than a stplanr problem, if the freeways are not notated in OSM as restricted-access?

As a side note, in the making of this toy example, I noticed that the default plotting cuts off parts of the routes. This also seems like a sp problem, rather than a stplanr issue, but I thought I'd bring it up in any case.

Again, thanks for a great package, and please let me know if I omitted any necessary information.

## Load packages #####
library(stplanr)
library(sp)
library(rgdal)
library(rgeos)

## Example for stplanr OSRM bike routing issue #####
ex_od <- data.frame("orig" = c(1,2,3),
                    "dest" = c(3,1,2),
                    "count" = c(5,10,2))
ex_zones = SpatialPointsDataFrame(coords = cbind(c(-111.989644, -111.961749, -111.892221),
                                                 c(33.450718, 33.430735, 33.406685)),
                               proj4string = CRS("+init=epsg:4326"),
                               data = data.frame("id" = c(1,2,3)))

# Create OD desire lines for example
ex_travel_network <- od2line(flow = ex_od, zones = ex_zones, 
                          zone_code = "id", origin_code = "orig", dest_code = "dest")

# plot(ex_travel_network)

# Convert OD desire lines to routes for driving
ex_routes_drive <- line2route(travel_network, 
                                route_fun = route_osrm,
                                profile = "driving")
proj4string(ex_routes_drive) <- CRS("+init=epsg:4326")

# Convert OD desire lines to routes for bicycling
ex_routes_bike <- line2route(travel_network, 
                             route_fun = route_osrm,
                             profile = "bike") # "bicycle", "bicycling"...
proj4string(ex_routes_bike) <- CRS("+init=epsg:4326")

# Plot driving route
plot(ex_routes_drive) 

# Discovered why plot looked strange - parts of routes were being cut off
plot(ex_routes_drive, ylim = c(33.38, 33.46), axes = TRUE)
plot(ex_zones, add = TRUE)

# Plot bicycling route
plot(ex_routes_bike)
plot(ex_routes_bike, ylim = c(33.38, 33.46), axes = TRUE)
plot(ex_zones, add = TRUE)
@Robinlovelace
Copy link
Member

Thanks for this - it's because the publicly available OSRM routing is for cars only. I do not know of a publicly available instance for cycling. Any ideas @mpadge (who mentioned investment in public OSRM routing - that would be a logical next step - multi-modal routing)?

@cgthigpen
Copy link
Author

Ah, I see. Then what I reported is entirely consistent with what you would expect.

What I'm aiming for are the shortest-distance routes by bicycle. I know graphhopper offers bicycle routing, and it seems like they have a "weighting" parameter that you can adjust to specify the shortest route (https://graphhopper.com/api/1/docs/routing/). But I don't see that parameter being passed in to stplanr's route_graphhopper, so I'm curious: what is the default weighting for route_graphhopper in stplanr? Is it returning the shortest routes from graphhopper, or the routes that also optimize for other route attributes relevant to bicycling?

My study area is in the US, so I don't think cyclestreets will work, unfortunately...

@mpadge
Copy link
Member

mpadge commented Apr 3, 2018

Yeah, the front-facing OSRM instance only has "car" implemented, even though the documentation semi-misleadingly suggests that other profiles are available (see here). A test:

> url_base <- 'http://router.project-osrm.org/route/v1/'
> prfs <- c ("car", "bike", "foot")
> sapply (prfs, function (i)
        {
            url <- paste0 (url_base, 'foot/1,51;2,52')
            d <- httr::GET (url) %>% httr::content (encoding = "UTF-8")
            d$routes [[1]]$distance
        })
   car   bike   foot 
248851 248851 248851

I'd suggest it'd be more informative to return some kind of error for non-car profiles instead of what they obviously do which is quietly use car profiles regardless. The phrase, "prepare the data using osrm-extract", applies to those who set up their own API instance, and only implicitly reveals that multi-modal routing just ain't possible at the front end. Their front end recognises all of these profiles, but obviously only holds one global profile for cars. There will be a new, improved public instance of OSRM soon, but it'll likely still only be single-mode, because each additional mode requires a completely separate instance of the planet file with distances weighted for that mode. Each server for a single mode needs to be replicated for each additional mode desired, making multi-modal routing a hugely expensive endeavour (in the OSRM framework).

I'll leave it to you guys to confirm that graphhopper does actually implement multi-modal API calls - I'm pretty sure they do, and note @cgthigpen that the vehicle parameter is appropriately passed to the graphhopper API call.

This whole issue is one of the things the osmdata + dodgr workflow is intended to address, by allowing highly customised profiles to be applied only to desired areas, rather than the whole planet. @cgthigpen open issues on respective repos if you want to go down that line.


@Robinlovelace This of course makes the "profile" arg in all stplanr::osrmfunctions functions effectively useless. It's obviously useful to leave it for more flexible usage such as passing an osmurl pointing to a local instance, but would be useful to document the reality that profile will be ignored in any and all direct calls to the default osmrurl="https://router.project-osrm.org".

@cgthigpen
Copy link
Author

That was a very thorough, helpful summary, @mpadge, thank you.

Following up on your points, graphhopper does implement multi-modal API calls. I was able to get route directions use "bike" and "racingbike" as vehicles (though the latter is only available if you have a paid graphhopper account) through stplanr. It might be worth updating the docs for route_graphhopper to indicate that paid graphhopper accounts can access more than "bike", "car", and "foot" (and by the way, "bike2" seems to be deprecated and should probably be removed from the vehicle list).

Though I'll need to follow up with the folks at graphhopper, it appears that "racingbike" is at least very close to the shortest route on links accessible by bike (e.g. almost everything but freeways), so I think I'll be able to avoid the more complex options you outlined toward the end. dodgr looks very impressive, should I need to go that direction.

@Robinlovelace
Copy link
Member

Thanks for the input - I see the action points to resolve this issue as:

  • Clarify that the public osrm servers only route for cars
  • Update documentation for route_graphhopper()

I the longer-term I think using dodgr as a back-end for routing will address many issues although you'll also likely be able to do that in dodgr (or a routing-specific spin-off of it) at some point. What stplanr can do usefully I think is provide a consistent route_*() function for many kinds of services.

Sound good? Should have some time to work on this next week.

@mpadge
Copy link
Member

mpadge commented Apr 6, 2018

Note that I firmly believe the stplanr::route_*() functions are enormously useful, and can not be replaced by dodgr functionality at all. The former are single(-ish) usage, and can be applied to much longer routes than dodgr. The latter is really only optimised for (massively-)multiple applications to small areas (individual cities).

Robinlovelace added a commit to Robinlovelace/stplanr that referenced this issue Apr 8, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants