-
Notifications
You must be signed in to change notification settings - Fork 3.5k
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
support relations in lua profiles #482
Comments
If it is really urgent you could try to replace the highway-tag-values of those way that are related to the routes, by for example 'greenroute' in the OSM-file. And next prioritize the highway type 'greenroute' in the OSRM speedprofile... |
you're right, that would be a potential work-around. but i would rather discuss what a more solid solution would look like :-) |
two ideas:
a preprocessing step could be used for other things as well, like adding synthetic ways for connecting train lines and platforms that are part of stop_area relations, or for adding ways across squares. |
i implemented parsing of routes in this branch: https://github.com/ibikecph/Project-OSRM/tree/parse_routes the lua way_function gets a list of the relation the way segment is part of, and can read the various relation tags. this way it's straightforward to modify setting on (for example) national cycle routes. however, the ability to modify speed and impedance separately is still lacking, leaving you basically no other option than to change the speed, at the cost of getting unrealistic travel times. to see it in action run: cucumber -t @route |
i tried processing data for Denmark (110M pbf), where it increased extraction time by a few seconds only. i guess it doesn't affect ram usage a lot either, since there are few relations compared to ways and nodes. |
there are some problem with how data is read using threads. on real world data it seems some ways are parsed before relations. still experimental.. |
another solution would be to use the denormalized data produced by the waysplit tool |
the branch https://github.com/ibikecph/Project-OSRM/tree/parse_routes works correctly now |
Emil Tin notifications@github.com writes:
i think using the denormalize relations on ways approach would be |
how would you handle a way being part of two similar types of way relations? you would have to use an akward tagging scheme. it would also be akward to handle route member roles. |
Emil Tin notifications@github.com writes:
at the moment all key value tags of all relations a way is member of are rel[0]:key1 val1 |
thanks. you can see the relation object approach at https://github.com/DennisOSRM/Project-OSRM/blob/experimental/route_relations/profiles/bicycle.lua. i think it's more straightforward to pass the route objects themselves, instead of having to copy all the tags to all the involves ways. it might also be faster, since you don't need to store new tags, just keep pointers to the relation objects? did you do any performance test on your code? for Denmark, the object approach adds a few percent of processing time, if i recall correctly. btw, your scheme above doesn't mention the member roles. for example, some parts of routes are only forward or backward. |
Emil Tin notifications@github.com writes:
nice
no, didn't do any benchmark specific to that part
will take a look at that your solution is just fine the motivation of my approach was/is:
all the best ¹ splitting ways at way intersections |
Jens Thiele karme@karme.de writes:
i now preserve the member role do you have an example where the role is relevant for the routing? |
it's relevant when a route follow different ways in each direction, for example, due to oneways. on bike you might not want to prioritize pushing a bike against oneways, even though the section is part of a route (but in the wrong direction) |
i think your tagging scheme is getting a bit wild :-) |
Emil Tin notifications@github.com writes:
oh i had a misconception of role here, thanks! |
just listing roles is not enough, when there is more than one relation, you need to know which tags belong to which relation/role way --> roles --> relations i think it's really simpler to just provide the role/relation objects, rather than try to cram it all into tags on the way |
Emil Tin notifications@github.com writes:
sorry but i don't just list roles i wrote a small function to convert my tags to your objects demo (pure lua): -- fake a way with some tags -- function to show equivalence to: -- demo but hey, if you don't like it, you don't like it ;-)
don't know |
@emiltin: This looks really promising. Very much looking forward to this being included in core. One query: the tests say "Testbot multiplies the speed gain of overlapping routes". Is this right? If a route is (for example) part of NCN 8 and NCN 42, that shouldn't mean it's twice as good for cycling as it would be if it were just NCN 8. Or have I misunderstood? |
thanks. i think dennis might be doing some planet-size test to see if performance is still good. you can use the routes to setup weights any way you like. testbot is just a profile that's used for testing, which is why is set it up to multiply. but you don't have to do that in car or bike profile. |
any news on this? i see you're working on osmium-based import. |
Yep, that's going to be the basis once it's stable |
ok cool. will that affect relation parsing? |
we still miss the ability to process relations. the use case for our ibikecph.dk service is being able to prioritise cycle routes. |
hi, if you have osm data in a postgis DB via --slim parameter, this shell script will create a lua script then just (and probably change of course, native osrm code would be nicer.. |
I just want to add another use case to this issue. I'm doing research on public transit using historical GPS data from transit agencies. I'm trying to map-match transit services to the street network, with the understanding that vehicles don't always complete their posted route and/or may turn back, detour around an obstruction, etc. I suspect it would improve the quality of my results if I could prioritize known routes (tagged with relations as type=route,route=bus), while still allowing for occasional deviation. I hope there will be some work on this issue in the near future! In the meantime, I may have to try this postgis workaround. |
Route relation support would also unblock the following use cases:
#482 (comment) suggests that it might be feasible to pass around references to the relation itself. If it isn’t, would it be feasible to implement route relation support by copying relation tags (and roles) onto the member ways in a preprocessing step reminiscent of rewrite-exit-destination-signage? |
yes, the implementation i did passing relation objects worked very well and had little impact om processing time. example use in a profile can we been at https://github.com/Project-OSRM/osrm-backend/blob/experimental/route_relations/profiles/bicycle.lua#L335 |
As discussed with @AlexanderMatveenko and @deniskoronchik another possibility to process relations will be processing nodes and ways before relations and processing relations in lua callbacks for registered relation types. The relation-processing callback function will have non-constant access to indexed extracted nodes and ways. Such approach will generalize relations processing with different types that can have nodes and ways with different roles. For example, restrictions handler can be moved into a profile callback that will fill Relations processing also can be done in-memory to recurse down superrelations like https://www.openstreetmap.org/relation/7204541 /cc @TheMarex |
The main problem with parsing ways before relations is that we need to keep the concept of a way until we finished processing all relations. Right now ways are really transient objects that only exist for the duration of: Parse (libosmium) -> Process (lua) -> Split into edges (ExtractorCallbacks). Changing that to Parse (libosmium) -> Process (lua) -> Cache, Cache -> Process Restrictions -> Split into edges would have some downsides. The main problem I see is that it would need a lot of data to keep both the lua result and the libosmium data round. The control flow I would propose is the following:
function process_relation(relation, result):
if relation.get_value_by_key("restriction") then
-- calls to current C++ handler
result.restriction = parse_restriction(relation)
end
if relation.get_value_by_key("route") then
-- the way that is marked with role "east" will get additional data "name"
-- in its invocation of process_way
result.roles["east"].data["name"] = relation.get_value_by_key("name")
end
end
function process_way(way, result, location_data, relations):
if relations.roles["east"] then
result.name = relations.roles["east"][0].name .. " East"
end
end That way we only need to keep the minimal amount of data we need for the processing around. |
The main idea, that we could use such pipeline: When processing relations, we just need to save in memory function process_relation(relation):
if relation.get_type() == 'any type':
-- change ways and nodes that are members of relation
-- relation.get_members_by_role('any role') to get set of members and change them if we need
-- because they have ExtractionWay, ExtractionNode types.
end
end Also this way allows to work with relations, that has another relations as members, because they cached in memory. Restrictions also can be made with this approach, via function This approach just increase memory usage for caching relations (but it can be made very efficient if memory is a bottleneck). @update There are some advantages of this approach:
|
Capturing from a slack conversation with @deniskoronchik we are probably going to go with parsing relations first to avoid caching ways and nodes. ScopeThe goal is to be able to support the following use case for now:
What we do not need to support:
Lua API changes
Architectural changes
ExamplesThis profile is a sketch of the API above that show-cases some of the use-cases. function process_relation(profile, relation, result)
local t = relation:get_value_by_key("type")
local name = relation:get_value_by_key("name")
if t == "restriction" then
result.restriction = true
else if t == "route" and relation:get_value_by_key("route") == "road" then
for member in relation.members() do
if member:role() == "north" then
result.data[member:ref()]["direction"] = "North"
end
if name then
result.data[memer:ref()]["name"] = name
end
end
else if t == "traffic_signals" then
-- lua has no way of counting number of table entries
local count = 0
for member in relation.members() do
count = count + 1
end
for member in relation:members() do
result.data[memer:ref()]["synchron_signals"] = count
end
end
end
function process_node(profile, node, result, relation_data)
local highway = node:get_value_by_key("highway")
-- Example application: Lessen traffic light penalties for synchronus signals.
if highway == "traffic_signal" then
result.penalty = profile.traffic_light_penalty
local synchron_signals = 1
for lights in relation_data["traffic_signals"] do
synchron_signals = lights["synchron_signals"]
end
result.penalty = result.penalty / synchron_signals
end
end
function process_way(profile, way, result, relation_data)
local name_postfix = ""
local route_name = ""
for route in relation_data["route"] do
if route.data["direction"] then
name_postfix = route.data["direction"]
end
if route.data["name"] then
route_name = route.data["name"]
end
end
result.name = way:get_value_by_key("name")
-- Example application: Remove ceremonial names
if route_name ~= "" then
result.name = route_name
end
-- Example application: Add directional post-fixes
if name_postfix ~= "" then
result.name = result.name .. " " .. name_postfix
end
end
|
There were some strange relations found:
Will update with a strange relations |
Just a heads-up to whomever is going to implement this: There is lots of code in libosmium that can help with storing relations or matching up relations with their members etc. But its not that easy to understand how it all fits together and what makes sense to use in which case. I'd be happy to advise if that's wanted. |
Looks like a couple ways were unintentionally added to the superrelation instead of child relations. Unfortunately, it isn’t difficult to make this mistake, but it’s something that a validation tool could catch.
This is another tagging error; the child relations should have |
can be closed, since relations are now supported in lua profiles? |
I’ll defer to the others here, but note that #4434 is the next step for route relation support. |
Yeah, this can be closed - OSRM know nows how to pass relevant relations to the |
for our bike router we need to prioritize certain ways that are part of routes; green routes, regional routes, etc. the routes are marked in OSM using relations.
maybe the way function could get a list of relations that the way is part of?
this issue is a follow up on #300 by @karme.
The text was updated successfully, but these errors were encountered: