Inconsistent Behaviour of RoadAccess, RoadAccess.NO is ignored

With CountryRules we have the option to set RoadAccess for an edge. In theory we could set RoadAccess.NO (or other values) for certain ways using CountryRules.

However, I think there are a few issues with this right now:

  • RoadAccess is only used in the FastestWeighting right now and only catches RoadAccess.PRIVATE and RoadAccess.DESTINATION.
  • RoadAccess is stored independently of the vehicle. For example if there is a way with motorcycle=yes but with a CountryRule that returns RoadAccess.DESTINATION.
    • The MotorcycleFlagEncoder won’t set RoadAccess to YES.
    • If the MotorcycleFlagEncoder would set RoadAccess to YES that might be wrong for other motor vehicles like cars.
    • FastestWeighting only uses the RoadAccess so for example for bicycle routing, it could happen that the FastestRouting applies the destination penalty for RoadAccess.DESTINATION.
    • Every FlagEncoder has a boolean access encoded value, which is independent of the RoadAccess.

Therefore, I think RoadAccess should be stored per vehicle or per transportation type. IMHO all weightings should understand blocking RoadAccess values, like RoadAccess.NO and return Double.POSTIVE_INFINITY, which only works if we know for sure that the RoadAccess=NO is actually correct for the current vehicle. Maybe the FlagEncoder access should be even replaced with the RoadAccess values?

WDYT?

Probably this would be also required for custom models if different access criteria is required for different vehicles in combination with CustomAreas?

Yes, this needs to go in the direction you propose. E.g. bikes have different access values as well (highly related probably also to https://github.com/graphhopper/graphhopper/pull/2402 where I’m unsure if we should introduce this before thinking about your issue here). Also for node access this would solve a few issues.

1 Like

Thanks a lot for the feedback.

Should I create a PR that changes the access bit in FlagEncoders to RoadAccess (including also the implied changes like changes in EdgeFilters etc.) or should we keep the two separate but have one RoadAccess / TransportationMode?

One RoadAccess / Transportation mode probably makes more sense when thinking in an OSM way, as then we only set values as they are given in OSM and let the encoder decide how to handle the actual access. (Also the implementation will be easier as we don’t touch access bits :smiley:).

Since #2402 is only about dismounting, couldn’t this be introduced independently from access?

I think, we should first have a more clear picture of what we need. E.g. I do not think we need to have it dependent on the direction but the access flags are of course dependent on the direction. So we would have “<mode>.access_bit” and “<mode>.road_access”.

The other problem is that the values of <mode>.road_access dependent on the <mode> e.g. car has a DELIVERY value, which foot might not need (?) Or wheelchair has LIMITED.

Since #2402 is only about dismounting, couldn’t this be introduced independently from access?

Not sure yet :slight_smile: E.g. bike could get bike.road_access values YES, NO, WALK (for reverse one way, steps etc) …

I think we really need to decide what we need first :slight_smile:. For bike you mention that walk could be applied in reverse for a oneway (so direction would be relevant).

Yes indeed, do you think we should have different Enums / Mode?

Dismount is indeed a difficult topic. OSM uses it like an access value, so it is probably the easiest option to just apply our regular access logic to set access to dismount if it’s specified accordingly.


Right now I would argue, that it makes sense to store the access following the OSM access tags (or based on the CountryRules).

Storing it in one or both directions is more complicated. So far, both directions seem to be mostly a special case. With Taginfo I could find only a few examples like 1000-2000 for cars where this would be relevant. On the other hand, your oneway example (pushing in reverse direction), is a really good example where storing both ways would actually make a lot of sense.

Yes, indeed + interesting. So in the “correct” direction it would be YES and in the opposite WALK. I thought we get away with 2+x bits (access+road_access) instead of 2*x bits (2*road_access) per transportation mode. But maybe get_off_bike is also a separate value.

Yes indeed, do you think we should have different Enums / Mode?

Yes, I currently have not found a different solution.

With Taginfo I could find only a few examples like 1000-2000 for cars where this would be relevant. On the other hand, your oneway example (pushing in reverse direction), is a really good example where storing both ways would actually make a lot of sense.

yes and yes :smiley:

Yes I think the most correct version would be 2*x per transportation mode. If we can get around this by splitting get_off_bike, I think this would be a reasonable trade-off.

Do you think I should create a PR like this, with RoadAccess in one direction and with get_off_bike in two directions?

I would probably ignore get_off_bike for now.

But still not sure if everything is so clear to me for a PR :slight_smile:

IMO the goal should not only be to better model country rules, but to be able to create a basic vehicle profile where I can use access properties in my custom model to allow e.g. access of oneways in reverse direction like for police cars.

And, as previously mentioned, we also need to think about which values can be used. foot and car are definitely different. Now I mentioned LIMITED for wheelchair, but this isn’t really a property of wheelchair.road_access but should influence wheelchair.priority instead and access would be YES in that case. (Same argument is probably valid for get_off_bike too.)

So do we only have 2 types (?):

  • foot.road_access = YES, NO, PRIVATE
  • bike.road_access = same as foot?
  • wheelchair.road_access = same as foot?
  • car.road_access = YES, NO, PRIVATE, DELIVERY, DESTINATION, (CUSTOMERS?), FORESTRY, AGRICULTURE, (OTHER?) (would be nice to remove 1 value to have only 3 bits :slight_smile: )
  • motorcycle.road_access = same values as car?
  • hgv.road_access = same values as car?

Or should we reduce RoadAccess to only YES, NO (and use a separate instance for every vehicle) and move the other properties into separate encoded values like private=yes/true? Can it happen that car=private and bike=not_private?

Ah yes, OK, in this case we would need to store a oneway bit or have a RoadAccess for both directions.

I am not sure about wheelchair, but bicycle has properties like designated use_sidepath, destination (probably low prio for bikes), etc.

Quickly checked OSM, yes this seems to be quite common (I guess 500+ examples for Berlin). A few examples:

So, having more detailed RoadAccess for every vehicle is probably good.

For me that would be too broad. We should have at least a “maybe” value, like destination, customers, delivery, etc. So if we want to use only 2 bits, YES, NO, MAYBE, OTHER might work. I am not sure about OTHER maybe this should be something else, like DESIGNATED or PRIVATE (I always feel like private = no).

I am not sure about wheelchair, but bicycle has properties like designated use_sidepath, destination (probably low prio for bikes)

The designated is again a preference we should store in bike$priority. And also use_sidepath should be a different thing, because IMO in practise a road could be with private and still recommend “use sidepath”.

Quickly checked OSM, yes this seems to be quite common (I guess 500+ examples for Berlin). A few examples:

Thanks for those examples. I think still the idea of a separate private encoded value would work and there is no need for a separate private property for bike, because here the access for bike is yes and the road is still private=yes.

We should have at least a “maybe” value, like destination, customers, delivery, etc.

The intent would not be to remove those values but move them into separate encoded values as they are not vehicle- and direction-dependent and this information should not be duplicated.

Or, as we already have <vehicle>$access, maybe the question is: what needs to be done to replace RoadAccess with this vehicle-dependent BooleanEncodedValue? And once RoadAccess was replaced we need new encoded values like delivery, customers etc or put the info into a new enum (so basically a new RoadAccess without NO & YES).

1 Like

Ok, but what value would we set for cars? access=no?

What if we think about destination? If a road has access=destination, bicycle=yes then access for bikes is yes, destination=true, but what do we set for cars? Do we set access=yes? How do we know which vehicle is actually marked with destination?

If we only store a boolean access for an edge, then I think we don’t need to change anything :slight_smile: - we already have that :slight_smile:.

Ok sure that can be done, but these should be still vehicle specific right? For me especially the destination value would be critical.

Yes, access=no and private=yes. Or car$access=true&true (both directions) and road_reachability=private (or we just continue to use road_access)

What if we think about destination? If a road has access=destination, bicycle=yes then access for bikes is yes, destination=true, but what do we set for cars?

The idea would be to read destination tag while import and change bike$priority

If we only store a boolean access for an edge, then I think we don’t need to change anything :slight_smile: - we already have that :slight_smile:.

Yes, but the meaning would change: we would need to replace RoadAccess with the vehicle-specific BooleanEncodedValue xy$access.

Ok sure that can be done, but these should be still vehicle specific right?

Is “destination” vehicle specific? Isn’t delivery, customers etc all related to motorvehicle and private is a generic thing?

My intention here is not to argue against the tagging of OSM, but the tagging is often very inconsistent and not easily usable for our generic routing rules. E.g. if we would create car_road_access and bike_road_access encoded value etc and set it to YES or NO what is the real difference to car$access=true/false? And if there is no difference why allow this in the first place?

Not necessarily. The country_rule is already passed to the way that goes to FlagEncoder#handleWayTags. So you can call CountryRule#getAccess there and use the result (like RoadAccess=NO) to set the access flag for your motorcycle flag encoder in that country.

I am not sure if this can be generalised like this. My feeling is that most of the delivery, customers, destination values are related to motor vehicles. If we are fine with either ignoring these for bikes/foot or just change the priority then that would be a valid decision.

Yes I would say so :slight_smile:. So would not consider it for regular routing but might use it for special vehicles like police cars. All other vehicles just use their current access bits.

That is my point :slight_smile: - if we only have true/false, then there is nothing we need to change and we can just keep the current access bits we have. In addition we can introduce a few additional bits like vehicle$destination and private that we can set accordingly. That would allow us to remove RoadAccess-Enum and -Parser.

Thanks for the hint :slight_smile: - it’s not a problem I have at Kurviger, I saw the inconsistency when doing the 4.0 update at Kurviger and fixed it for Kurviger in the update process, but since I saw that there was an inconsistency I wanted to start a discussion how this could be improved.

Powered by Discourse