Project-OSRM / osrm-backend

Open Source Routing Machine - C++ backend
http://map.project-osrm.org
BSD 2-Clause "Simplified" License
6.39k stars 3.39k forks source link

Include railways in the car.lua profile #3720

Closed Martin-Kotrulev closed 7 years ago

Martin-Kotrulev commented 7 years ago

Hello, I have a question concerning the railways. I'm using the osrm-backend for route drawing and building purposes. So far the capabilities of car.lua profile for the roads suits me very well, but I also need a way to include the railways, because I'm building routes for public transport. Is there a way to include in some way the railways in the car.lua profile? Any help will be deeply appreciated. Thank you.

daniel-j-h commented 7 years ago

Take a look at the profile: in the way function you can parse railway way tags and set speeds accordingly. They probably won't be connected to the road network, though. And you don't get any time tables out of OpenStreetMap. But for simply generating and drawing a route it should be good enough.

cc @duizendnegen who worked with railways before in the context of OSRM if I remember correctly

duizendnegen commented 7 years ago

@Martin-Kotrulev I did exactly this; wrote a separate train.lua to index those, extracting the stations as start points with their geo-coordinates. End result:

train-route

The biggest hindrance is that the optimal route from A to B might not be the route that public transport takes. Consider for example the Hamburg - Munich train: there's two services, one direct over Hannover/Frankfurt, one over Berlin/Leipzig. Unifying public transport schedules with routing has my strong interest, so I'd be happy to brainstorm on this some more. I tried to mine from http://wiki.openstreetmap.org/wiki/Train_routes first but got stuck in partially parsing routes - Groningen - Rotterdam worked, but Groningen - Assen didn't (as it's a partial route).

The train.lua I am currently using (ripped largely from car.lua):

local ipairs = ipairs

function find_access_tag(source,access_tags_hierarchy)
    for i,v in ipairs(access_tags_hierarchy) do
        local tag = source:get_value_by_key(v)
        if tag and tag ~= '' then
            return tag
        end
    end
    return ""
end

mainline_speed = 120
electrified_speed = 110
non_electrified_speed = 80
default_speed = 80
service_speed = 50

properties.traffic_signal_penalty        = 0
properties.u_turn_penalty                = 0
properties.use_turn_restrictions         = true
properties.continue_straight_at_waypoint = false

function way_function(way, result)
    local railway = way:get_value_by_key("railway")
    local service = way:get_value_by_key("service")
    local usage = way:get_value_by_key("usage")
    local maxspeed = way:get_value_by_key("maxspeed")
    local electrified = way:get_value_by_key("electrified")

    -- route only actual railways, no subways or disused pieces
    if (not railway or railway ~= 'rail') then
      return
    end

    result.forward_mode = mode.train
    result.backward_mode = mode.train

    result.type = 1
    result.name = 'rail'

    result.forward_speed = default_speed
    result.backward_speed = default_speed

    local maxspeed_as_number = 0
    if maxspeed then
      maxspeed_as_number = tonumber(maxspeed:match("%d*"))
      if maxspeed_as_number then
        if string.match(maxspeed, "mph") or string.match(maxspeed, "mp/h") then
          maxspeed_as_number = (maxspeed_as_number*1609)/1000
        end
      end
    end

    if maxspeed_as_number and maxspeed_as_number ~= 0 then
      result.forward_speed = maxspeed_as_number
      result.backward_speed = maxspeed_as_number
    elseif service then
      result.forward_speed = service_speed
      result.backward_speed = service_speed
    elseif (usage and usage == 'main') then
      result.forward_speed = mainline_speed
      result.backward_speed = mainline_speed
    elseif (electrified and electrified == "contact line") then
      result.forward_speed = electrified_speed
      result.backward_speed = electrified_speed
    elseif (electrified and electrified == "no") then
      result.forward_speed = non_electrified_speed
      result.backward_speed = non_electrified_speed
    else
      result.forward_speed = default_speed
      result.backward_speed = default_speed
    end

    return
end

function turn_function(angle)
  return (angle * 2)
  -- TODO permit angles more leniently in stations
end
Martin-Kotrulev commented 7 years ago

Thank you very much for the quick answer @daniel-j-h and @duizendnegen. I modified the car profile and now the railways are included in the route, but the routing works only for short distances. If the distance is greater sometimes I get "Segmentation fault" and at other times unreal big "spaghetti" route on the whole map. Are there some other properties that must be checked?

TheMarex commented 7 years ago

@Martin-Kotrulev that sounds like data corruption. Did you re-run the whole toolchain again? You need to re-run both osrm-extract and osrm-contract after doing a profile change.

Martin-Kotrulev commented 7 years ago

@TheMarex thanks man! I owe you big time! I completely forgot about the osrm-contract step. Now everything is working perfect for my needs. Thanks again!

daniel-j-h commented 7 years ago

Unifying public transport schedules with routing has my strong interest, so I'd be happy to brainstorm on this some more. I tried to mine from http://wiki.openstreetmap.org/wiki/Train_routes first but got stuck in partially parsing routes - Groningen - Rotterdam worked, but Groningen - Assen didn't (as it's a partial route).

Here's another idea: get stop locations from GTFS feeds, ingest the railway network via a custom profile. Then do Map Matching to get back the most likely train route once you have your route's stops.

Martin-Kotrulev commented 7 years ago

Thank you @daniel-j-h for your suggestion! The thing is that, in my case, the stop locations, routes and basically all the GEO capabilities will be managed from administrators, manually. So all that I needed was a way to make the app really easy to work with, when it comes to drawing and persisting routes.