Open dabreegster opened 2 years ago
I actually already allow busway + either bus:lanes or lanes:bus in https://github.com/a-b-street/osm2lanes/pull/134/files#diff-22ad929b7a488fd33b93d20054e80bb72678cebda592203907bb58188c8608b7
allowing for both bus:lanes and lanes:bus may be possible, but we have yet to implement lanes:bus, so it doesn't really matter yet
Each scheme describes a slightly different aspect of the road, and they should be reconciled. I think the XScheme
types in #111 allow for this reconciliation to be implemented in a sensible way. If the tags don't agree with each other, then they are invalid and we have to decide which tags to ignore, which we could do simply by preferring one schema over another, or we could get as fancy as we like. I feel like a valuable usecase for osm2lanes is detecting these incompatibilities and suggesting the simplest fix, so maybe we do end up getting pretty fancy about it in the long run.
The situation is exactly the same with lanes
and lanes:{forward,backward}
: If forward
and backward
are provided, lanes
is redundant, but it is convention to include it for less sophisticated consumers. If the tags disagree, we would have to choose one tag to ignore in order to produce an answer.
lanes:bus
is the lanes
tag narrowed in scope to just buses, so "how many bus lanes are there". (On a twoway road, I would expect lanes:bus:{forward,backward}
instead).bus:lanes
is the bus
access tag, but on a per lane basis, so "what is the access of each lane, left to right". (Again, in my experience on a twoway road, I would expect bus:lanes:{forward,backward}
instead).busway
is an older scheme that is ambiguous to the number of lanes in each direction and the position of those lanes. I would discourage it's use in lanes_to_tags
unless the user specifically requests it.busway:left=lane
means "a bus lane on the left" which implies lanes:bus:forward
of at least 1 and bus:lanes:forward
to have designated
at least once.bus:lanes:forward=designated|
implies lanes:forward=2
because the list is of length 2 (there is an empty element after the |
, meaning "default"), lanes:bus:forward=1
because designated
is in the list once.access:lanes:backward=no
in the linked example means that nothing is allowed in the single backward lane, and bus:lanes:backward=yes
overrides that for buses. Because only buses are allowed, this implies lanes:bus:backward=1
.
bus:lanes:backward=designated
.oneway=no
would be technically correct (I think), but it seems like mappers prefer oneway=yes
in this situation, because they drive cars and they want a oneway arrow to appear on openstreetmap.org. I don't know how widespread this convention is, or how supported by data consumers it is.lanes
to the total number or vehicle lanes.oneway=yes
, otherwise add lanes:forward
and lanes:backward
.|
separated list with empty elements for "default" lanes, using <tag>:lanes:<dir>
(where <dir>
is omitted for oneway roads). e.g. bus:lanes:forward=designated||
access
: no
for lanes where only one thing is allowed (tag that thing next)bus
: designated
for lanes signed as bus, no
for lanes that buses aren't allowed in, empty for normal lanespsv
: same, but for "public service vehicle" (buses and taxis together)turn
for turn markings, etc.lanes:bus
instead of access:lanes
and bus:lanes
.I had a slightly different strategy in mind, given that busway < lanes:bus < bus:lanes
lanes
, lanes:*
and access lists like bus:lanes
, psv:lanes
and access:lanes
bus:lanes
and similar per laneI had a slightly different strategy in mind, given that busway < lanes:bus < bus:lanes
- start with no lanes
- add lanes...
I like following that process to reconcile, check for inconsistencies, and come up with likely guesses, all at once.
I guess that means that parsing the individual schemes independently should be done ignoring potentially conflicting tags, (but using dependencies like oneway
), and producing Infer::Default
s, not Infer::Guess
es. That process can be the one that looks at the full context and makes Guess
es.
e.g. When it gets to the lanes
schema, if the tags are missing then the scheme will be lanes: Infer::Default(2)
. Because it is the default we add those 2 lanes (because that is the guess we make), and set lanes = Infer::Guessed(road.num_lanes)
(if num_lanes
isn't 2). I like it.
That works as well, maybe slightly clearer overall with less implicit knowledge of individual tagging schemes
By far the most common problem I'm seeing with real data is more than one bus lanes scheme used. One example is https://www.openstreetmap.org/way/679636490. Glancing at this, I can't help feeling like though it uses two schemes, they both agree -- there's exactly 1 backwards lane and it's bus-only.
For #71, I'll probably be tactical in the short-term, detect these cases, and just arbitrarilyish rip out keys for one of the schemes. But I had another idea -- if we could parse each bus scheme independently, clone the road builder, and "try out" both schemes, then we could check if the results match. If so, just a warning about redundant tags could suffice -- no need to totally give up?