Open droogmic opened 2 years ago
Thanks for this great writeup.
I talked to @supaplexosm when I saw your PR (before reading here). He had a few thoughts that I wanted to share
width
on a highway unreliable.
width:carriageway
is our best bet in our opinion since it has a clear definition that can be followed on the ground.
width:lanes
https://wiki.openstreetmap.org/wiki/Lanes
width:lanes:forward/backward=4.2
and width:lanes=3|1.5|4
in https://supaplexosm.github.io/strassenraumkarte-neukoelln/posts/2021-12-31-micromap-update I wonder, what good iterations on this topic might be…
For example, it could be easiest to start with just default/fallback values (per country?) and only respect the width values where they are explicitly attached to a lane (lane in the osm2lanes sense). That would be, only looking at width:lanes
, parking…width
, sidewalk…width
, cycleway…width
(plus maybe buffer=<widthvalue>
(Example) and such).
That makes the math and matrix involved a lot easier, doesn't it?
Awesome writeup -- I'm generally in favor of everything you wrote.
When a lane width has been inferred with no guarantee of correctness, it should be excluded from the proposed/normalized/roundtrip OSM tags.
I like this explicit representation of provenance. Just to state it, a simpler alternative: when roundtripping, never output any width tags. Ignore them for the sake of the unit test. If lanes->tags is used as part of a future OSM editor, just retain the width tags already mapped, and only consider updating other tags. But -- I'm in favor of the enum.
That makes the math and matrix involved a lot easier, doesn't it?
I agree this could be a simpler first step
About the roundtrip-section:
In https://github.com/a-b-street/osm2lanes/issues/80 > "Highway lanes", I am wondering if the "Locale" and "Default" values need to have an option to be based on other tags. In that case the value of the highway tag.
I am wondering if the "Locale" and "Default" values need to have an option to be based on other tags. In that case the value of the highway tag.
I think so. highway=primary
width is likely different than highway=residential
, given the same number of lanes and no other info.
Good discussions so far.
He considers width on a highway unreliable. ... Width between curbs / edges of the road without sidewalks, but with parked cars when they are on street ... My take is, to maybe not consider it at all since the effort to do so is high and the result, even after this high effort, is still likely wrong.
As an MVP, we could always ignore it and return a warning. In the future though, I think there are situations where a width
can give information, and is not kerb to kerb. Example: a way with bridge=yes
, sidewalk=both
, and width=12
. I think we can assume the width is that of the bridge, and the 4 lanes (foot, travel, travel, foot) fill that width, so 2m, 4m, 4m, 2m would be a good inference.
easiest to start with just default/fallback values (per country?) and only respect the width values where they are explicitl Agreed, let's start there.
But: I do want to attempt the refactor for implementation option 2, because I expect we will want the flexibility it provides in the future.
https://streetwidths.its.ucla.edu/data/ Slightly off-topic for where this issue wound up, but this is a possible source of locale-specific width estimates. It's unfortunate all the data collected isn't just upstreamed in OSM.
Some test cases:
cycleway:both:width
Each (non-separator) lane on an OSM way must have a width.
See: https://wiki.openstreetmap.org/wiki/Key:width#Width_of_streets
In the unlikely event that all of the relevant
width:carriageway
,cycleway:<side>:width
,parking:lane:<side>:width
,shoulder:width
,lanes:width
are specified, we could have a trivial implementation. This is rarely the case, so we must assume incomplete information.Locale
Locale (the region specific encoding of highway construction conventions) will be used to infer the width of each lane. As this is constant for a given road, we will treat this and the resulting widths as constant in our requirements and algorithms.
No Width
When no width is given, the locale is used to determine typical widths of the lanes in the road. If tags for certain lanes are provided (e.g.
cycleway:<side>:width
), the defaults can be replaced.Total Width:
width=*
orwidth:carriageway=*
When a total width is given, we have the strict requirement to fill that width. In the simple case, we could use the same method as above, and then scale all the lanes by the same factor to reach this requirement. However (depending on the locale) it is reasonable to imagine situations where this is insufficient. For example, bus lanes are unlikely to expand beyond a maximum width, shrinking footpaths will take precedence over shrinking travel lanes, there is a minimum size for a parallel parking bay, etc.
One proposal could be to model the following parameters per locale:
The lanes are still scaled together to meed the width, but will staurate at their minimum or maximum. In situations where the width constraints cannot be met, an error may be thrown. As more tags are provided (e.g.
cycleway:<side>:width
), the calculation above can be further constrained.Config
Consumers may not want osm2lanes to guess what the width should be, so this should be a config option.
Roundtrip
When a lane width has been inferred with no guarantee of correctness, it should be excluded from the proposed/normalized/roundtrip OSM tags.
This may require an internal representation of the data:
We ignore situations where the OSM tags are contradictory.
Implementation
The current implementation does a single direct assignment of the lanes (excluding separators) and all their parameters.
Options:
"Simple" Assign the default width first, and as a post processing step apply the above algorithm to mutate the widths. This has the downside that information from other tags cannot be added on the preceding step
"Builder" A
LaneBuilder
struct is passed around instead of aLane
, upon which properties like maximum and minimum widths may be set. At the end, aLaneBuilder.lane(self)
is called to return the APILane
. This would allow for more future flexibility when building lanes across multiple "passes". Downside: this will be a bit of work to rewrite the current implementation.