streetcomplete / StreetComplete

Easy to use OpenStreetMap editor for Android
https://streetcomplete.app
GNU General Public License v3.0
3.86k stars 352 forks source link

What form of traffic control is present at this intersection? #4934

Open 1ec5 opened 1 year ago

1ec5 commented 1 year ago

General

Affected tag(s) to be modified/added: highway=traffic_signals, highway=stop, highway=give_way, junction=uncontrolled Question asked: What form of traffic control is present at this intersection? Or maybe more naturally: How does traffic wait at this intersection?

This quest should be limited to the United States and probably Canada. In these countries, there is no concept of a priority road and virtually every intersection has traffic lights, stop signs, yield signs, or the equivalent markings (“intersection control devices”). It should be limited to intersections where these tags are absent (and not on a nearby node representing a stopping point).

Checklist

Checklist for quest suggestions (see guidelines):

Ideas for implementation

Element selection:

The wiki has an example query for road intersections. It’s a slow join over a large area with lots of roads, but over a smaller area, it should be possible to query for intersections in a more reasonable time.

The query should exclude any intersection node tagged highway=traffic_signals/stop/give_way or junction=uncontrolled. Due to the stop bar mapping style, it should also look for these tags on the adjacent nodes of inbound ways. Intersection control also applies to ramps and roundabout approaches, so there’s no need to exclude highway=*_link ways.

Intersections between dual carriageways could make it more difficult to distinguish between fully-tagged and undertagged intersection nodes. I’m also uncertain how to tag an all-way stop between dual carriageways, because of the preference for tagging the intersection nodes instead of the stop bars. Perhaps as a first iteration, the quest could conservatively omit any intersection involving two or more one-ways, or any closely-spaced pair of intersection nodes.

Metadata needed:

Proposed UI:

The quest’s icon could be a composition including a traffic light, stop sign, and yield sign.

The quest unfortunately requires multiple questions, because of how the global community prefers to model intersection control that doesn’t affect all inbound ways. The quest’s flow could look like this:

  1. Show the intersection and ask if there are: a) traffic lights (highway=traffic_signals), b) stop signs or markings (highway=stop), c) yield signs or markings (highway=give_way), or d) none of the above (junction=uncontrolled).
    1. If (a) or (d), tag the intersection node.[^intersection-node]
    2. If (b) or (c), ask if it is an all-way stop / all-way yield.
      1. If it is, show a map or diagram of the intersection and ask which inbound ways need to stop or yield. Tag or create a nearby node along each affected way, behind any highway=crossing node.[^stop-bar] Add stop=minor or give_way=minor and the appropriate direction.
      2. If it isn’t, tag the intersection node and add stop=all or give_way=all.

[^nebraska]: According to OSM, most counties in Nebraska lack any traffic lights. Or do they? (See comments.) [^intersection-node]: Or create a highway=traffic_signals node on each inbound way? Both styles are valid and supported to some extent by data consumers, but different mappers have different preferences. [^stop-bar]: How far back should it be? Would it be possible to ask the user where the stop bar or unmarked stopping point is? Or maybe that’s for an armchair mapper to deal with?

matkoniecz commented 1 year ago

Tag or create a nearby node along each affected way

That is a major obstacle, would require implementing completely new type of quest modifying geometry and editing multiple objects - not only queried one.

EDIT:

StreetComplete cannot really create new nodes which are part of existing geometry (node creation is possible for example in shop overlay but it creates standalone nodes for POIs, which are not part of any way or relation).

StreeComplete can handle way splitting but it is a special case and significant work would be needed to extend it if such edit would be coupled with placing tags.

Also, technically, nodes are created where POI deletion is reverted or when node splitting is reverted.

Helium314 commented 1 year ago

That is a major obstacle, would require implementing completely new type of quest modifying geometry and editing multiple objects - not only queried one.

See #4481 for difficulties with this. I hope at some point it should be done, but it's a lot of work...

nickrsan commented 1 year ago

I agree that this would be very useful.

I might be way off base here, so just let me know, but thinking of some other quests that have answers like "it varies along the way", would it be possible to avoid some of the nearby queries and object creation by adding responses for this quest like "it varies between travel directions" or "it's already mapped" (to cover the case where someone mapped two stop lines already, but nothing on the intersection node). That could then mitigate the need to do queries or tag nearby objects initially and just handle simple cases of all-way stops and all-way traffic signals.

1ec5 commented 1 year ago

Thanks, I was unaware that StreetComplete is unable to make multi-feature edits. That does seem like useful functionality, especially for attributes that can vary along the length of a road or path (requiring splitting).

Limiting the quest to all-way stops etc. would be better than nothing, but there would need to be a tag for affirming that an intersection was reviewed without being tagged. Otherwise, the user would be asked again and again about something they’ve already looked at.

In the old days, I used to tag two-way stops on the intersection node, using stop=minor to clarify that it only applies to the road with the lower classification. However, this approach doesn’t appear to be standard, and it frustrates routers when processing OSM data into a graph. It often failed because classification doesn’t necessarily correspond to intersection control – and this was actually the reason I stopped mapping stop signs in my city even as I continued to map traffic lights. (I live in a neighborhood where every street alternates between stopping for one cross street and not stopping for the next cross street in a lattice pattern. 🥧)

westnordost commented 1 year ago

This is unfortunately not possible to do and it is not feasible to make it possible. @matkoniecz and @Helium314 already wrote about it. In my own words and additional reasons:

  1. (as explained by @matkoniecz ): Only one element can be modified by StreetComplete and any answer the user can give must result in an edit being made. In this case, the edited element would be the intersection node. However, for the situation of a priority road / stop signs, not the intersection node but some other nodes would need to be tagged. As far as I know, there is no tag in OSM that one could set on an intersection node that would just denote "this is an intersection without traffic lights" (i.e. regardless of whether there are stop/yield signs or not).

  2. It is somewhat complex and probably ultimately fuzzy to find whether an intersection does not already have some kind of traffic lights mapping, as it is both valid tagging to put the traffic lights on the intersection node or separately at the actual position at which the cars must stop before the red light. I can imagine that the complexity involved here somewhat explodes for bigger (and/or micromapped) intersections

  3. (as explained by @Helium314 ): It may be possible in the future to have the ability to make modifications on several elements in one edit (I am still contemplating). A UI as you propose would then theoretically be possible. However, I do not think this is feasible because without a full view of the data (as you have in normal editors such as iD, JOSM,...) , the user will be prone to put the stop / yield signs at a wrong position - there is too much potentially going on on a (micromapped) intersection.

So, I'll close this as will not fix. The easiest solution here would be if all the situations of a road could be tagged on the intersection node itself where it would be valid to both tag it on the intersection node and separately. This does not seem to be the case.

1ec5 commented 1 year ago

However, for the situation of a priority road / stop signs, not the intersection node but some other nodes would need to be tagged. As far as I know, there is no tag in OSM that one could set on an intersection node that would just denote "this is an intersection without traffic lights" (i.e. regardless of whether there are stop/yield signs or not).

Since junction=uncontrolled indicates that there’s no form of control, I believe the full set of tags in this proposal cover all the possible scenarios, other than the fact that some of them are mapped away from the intersection. But if you really need a tag for saying that there are no traffic lights specifically, that would be not:highway=traffic_signals. This tag isn’t in use per se, but it’s a natural use of the not: prefix.

Note that this proposal is scoped to countries that do not have a concept of priority roads. I agree that it would be more difficult to implement in countries that do have priority roads.

It is somewhat complex and probably ultimately fuzzy to find whether an intersection does not already have some kind of traffic lights mapping, as it is both valid tagging to put the traffic lights on the intersection node or separately at the actual position at which the cars must stop before the red light. I can imagine that the complexity involved here somewhat explodes for bigger (and/or micromapped) intersections

Does this project require every quest to map a feature comprehensively? If not, I think this quest would still have a significant benefit even if the query is very conservative, filtering out any intersection within, say, 30 meters[^meters] of a highway=traffic_signals/stop/give_way node. Or perhaps any intersection between ways that don’t already have highway=traffic_signals/stop/give_way nodes along them. Or just any intersection between two minor roads (highway=residential or similar).

[^meters]: I based this number on the size of a very large conventional intersection in San José, California, but it could be as large as you want.

1ec5 commented 1 year ago

I hesitate to mention this because I’m not sure I like the tag, but highway=priority is also somewhat well-used for indicating a partially stop-controlled intersection (such as a two-way stop at a four-way intersection), where the highway=stop nodes are offset from the intersection.

westnordost commented 1 year ago

Sorry, are you saying that there was a misunderstanding? Let's say we will have the quest look like this:

Are there traffic lights for this intersection? [Yes] [No]

then it would be correct to tag

if the traffic signals (if any) haven't been mapped separately?


If this is the case, what exactly do you propose to find and thus exclude intersections that have the traffic signals mapped separately?

1ec5 commented 1 year ago

junction=uncontrolled on the intersection node if no regardless of whether it is an intersection with a priority road (give_way) or not

Intersections don’t quite work like this in the U.S. Just like highway=stop, we only map highway=give_way when there’s a triangular yield sign. If there’s no yield sign, vehicles go right on through without yielding, so we don’t map anything special along that street. Therefore, these are only the proposed outcomes after dealing with a previously untagged intersection:

I tried to be helpful by distilling this into a multi-step, wizard-like flow, but perhaps I was mistaken for thinking that a quest could have multiple steps. Showing all these options simultaneously would be just as correct.

If this is the case, what exactly do you propose to find and thus exclude intersections that have the traffic signals mapped separately?

This is indeed a challenge. There’s no standard tag to indicate that all the highway=traffic_signals nodes are at the stop bars instead of the intersection, and highway=priority isn’t necessarily mapped when highway=stop stop=minor is mapped at the relevant stop bars. But I’m quite certain that’s manageable – as long as StreetComplete isn’t taking an all-or-nothing approach, requiring all untagged intersections to turn up in the query. The Overpass API is more than capable of filtering out results based on proximity to some node.

Actually, I’m running into a more basic challenge of just identifying intersections in general. The wiki’s Overpass examples perform a slight of hand by including some filters that we wouldn’t be able to use here. The closest I have so far is this query, which would be suitable for this quest, except that it also needs to filter out any node that joins two roadways of the same name. Otherwise, it takes a conservative approach, avoiding any intersection that could potentially already be tagged at the stop bars. I’m also ignoring link roads and service roads, which often do have stop and yield signs, but not frequently enough to avoid spamming the user. With the default bbox in that query, you can see for instance that it correctly includes this untagged intersection, but not this tagged all-way stop or this two-way stop with nearby stop bars.

[^give_way]: Contrary to my original post, highway=give_way give_way=minor would probably be unnecessary, because an “all-way yield” would be equivalent to junction=uncontrolled. Roadgeeks have turned up one instance of a signposted all-way yield in Texas, but this is nonstandard, misleading, and not worth accounting for here.

1ec5 commented 1 year ago

The closest I have so far is this query, which would be suitable for this quest, except that it also needs to filter out any node that joins two roadways of the same name.

Here’s a query that only includes intersection nodes. I also updated the wiki with it as a better example for finding intersections. It takes about four times as long as the simpler query I posted earlier, but there’s probably room for optimization. I can get it to run within 25 seconds over a bounding box that covers a moderately dense city street grid about 2 km square.

matkoniecz commented 1 year ago

highway=stop stop=minor on some of the inbound ways, and highway=priority on the intersection node highway=give_way on some of the inbound ways, and highway=priority on the intersection node1

in such case is it helpful to tag solely highway=priority on the intersection node? Without highway=stop stop=minor / highway=give_way on any inbound ways?

matkoniecz commented 1 year ago

Really nice magical query!


There will be some additional filtering needed...

I guess that oneway split intersections like https://www.openstreetmap.org/node/262193741 ideally would be filtered out (should be doable in SC even if overpass cannot do this)

Also, probably roundabouts can be skipped? See https://www.openstreetmap.org/node/262193741 https://www.openstreetmap.org/node/262116931 https://www.openstreetmap.org/node/262116932 https://www.openstreetmap.org/node/262116933 https://www.openstreetmap.org/node/262116935 https://www.openstreetmap.org/node/262116936 https://www.openstreetmap.org/node/262116930 https://www.openstreetmap.org/node/1080043218

And cases where exactly two ways meet https://www.openstreetmap.org/node/1080043173 - before I fixed issue with bad name it was found as crossing, name change of straight road is not a crossing, for crossing you need meeting of three incoming roads* (way to the left used to be a separate way without name, see https://www.openstreetmap.org/changeset/134925517 and https://www.openstreetmap.org/way/93167141/history )

*in OSM it could be 2 incoming ways

1ec5 commented 1 year ago

in such case is it helpful to tag solely highway=priority on the intersection node? Without highway=stop stop=minor / highway=give_way on any inbound ways?

Maybe. I guess it would be a way of saying, “We know there’s a two-way stop or two-way yield situation here, but we don’t know in which direction.” highway=priority isn’t being used by anything at the moment, so there’s no risk of breakage.

To be clear, I’m not a huge fan of this tag. It’s too easy to confuse it with priority_road=yes or priority=yes, especially in countries that don’t have a concept of a priority road in the first place. But I don’t have any better naming ideas. I just brought it up in case it would help somehow, but there would probably be pushback about suddenly blanketing the map in these nodes, and I don’t think it’s strictly necessary for this quest anyways.

I guess that oneway split intersections like https://www.openstreetmap.org/node/262193741 ideally would be filtered out (should be doable in SC even if overpass cannot do this)

It is doable in Overpass, by checking whether the other street is a oneway=yes and the node is at position 1 within the way, but that might increase the query’s running time. These cases should be sparse enough that a client-side filter would be practical. If not, there’s probably no harm in tagging it as junction=uncontrolled.

Also, probably roundabouts can be skipped?

In the U.S., inbound ways are supposed to have yield signs and markings. Outbound ways would be handled the same as in your Rynek Kleparski / Ignacego Jana Paderewskiego example above.

There is a related concept of a “neighborhood roundabout” that’s more of like traffic calming furniture inside a two-way stop intersection. Some mappers model these as circular ways with junction=circular, while others simply tag junction=circular on the intersection node. Either way, it would be necessary to tag the two highway=stop nodes at the stop bars, so I think this query handles it correctly.

name change of straight road is not a crossing, for crossing you need meeting of three incoming roads

Indeed, this query will return mid-block name changes. It might be possible to account for these false positives in the query as well, by checking whether there are only two inbound ways and the node is at the beginning or end of both. This would be a more robust check than the name-based one I prototyped.[^classification] But I think it would be more straightforward to do on the client side, given the relative rarity of a mid-block name change.

[^classification]: More rigorously detecting intersections based on angle classification can get maddeningly complex.

matkoniecz commented 1 year ago

I just brought it up in case it would help somehow, but there would probably be pushback about suddenly blanketing the map in these nodes, and I don’t think it’s strictly necessary for this quest anyways.

In the current form we would need some set of tags that can be applied to the crossing node and covers all typical answers, without editing any other objects. Right now out of

highway=stop stop=minor on some of the inbound ways, and highway=priority on the intersection node

"highway=stop stop=minor on some of the inbound ways" is not doable, "highway=priority on the intersection node" is doable right now

The question is - does such tagging actually helps?

1ec5 commented 1 year ago

The question is - does such tagging actually helps?

I think the answer would depend on user expectations. Let’s suppose StreetComplete were to implement this quest without #4942: upon encountering a two-way stop at a four-way intersection, the user selects the “Two-Way Stop” option, which puts down a highway=priority node. Would it surprise the user that they didn’t end up mapping two stop signs? Maybe it would be necessary to set expectations by designing a less than obvious icon for that option.

The database would end up with a highway=priority node that implies the presence of stop signs somewhere. Routers wouldn’t be able to display cute stop sign icons on the map or count blocks just yet, but it wouldn’t be wrong, just awkward. Meanwhile, routers and renderers would benefit from all the other intersections that could be fully tagged.

westnordost commented 1 year ago

Meanwhile, routers and renderers would benefit from all the other intersections that could be fully tagged.

Which in this case would just be: those with traffic lights. Right?

So, the UI for this quest would look like:

How is the flow of traffic controlled at this intersection? ( ) traffic lights ( ) / one road is a priority road ( ) nothing, left yields to right

tagging, each,

and it would only be asked for intersections where there is no separately mapped stop sign, no yield sign, no traffic signals, etc. near.

Would you please post in the community forum whether tagging such things would be fine on ~many/all intersections? As you say, apparently specifically highway=priority doesn't seem to be used that often, especially when not also together separately mapped stop or yield signs.

1ec5 commented 1 year ago

Meanwhile, routers and renderers would benefit from all the other intersections that could be fully tagged.

Which in this case would just be: those with traffic lights. Right?

No, all-way stops can also be tagged. Those are very common too. So the answers would look something like this:

  1. 🚦 Traffic lights[^beacon]
  2. 🛑 Stop sign in every direction
  3. 🛑 Stop sign in some directions but not others
  4. 🔻 Yield sign in some directions but not others (does the same thing as 3)
  5. 🤞 No signs, signals, or markings

nothing, left yields to right

At least in California and Ohio, whoever gets to the intersection first has the right of way. Only if the two sides arrive at the same time do you yield to the right, but in practice you try to negotiate with the other driver through hand signals and you both confuse each other for a bit.

Would you please post in the community forum whether tagging such things would be fine on ~many/all intersections? As you say, apparently specifically highway=priority doesn't seem to be used that often, especially when not also together separately mapped stop or yield signs.

Here goes: Partially mapped two-way stops.

[^beacon]: This needs a 🚦 or 🚥 icon so people don’t use it for intersections that have a flashing beacon with just a single flashing red light, which is equivalent to a stop sign.

westnordost commented 1 year ago

Uhm, if the answer options are like that, what would be tagged in each case on the intersection node?

Remember, separate stop or yield signs will NOT be tagged with this quest. Even (now) that vertices can be added by SC, I personally think it is not worth it to implement a custom ui for placing these signs specifically for this quest, so the quest needs to work without.

Also, what is the reason it should only be active for the US?

1ec5 commented 1 year ago

Uhm, if the answer options are like that, what would be tagged in each case on the intersection node?

Answer Tags on the intersection node
🚦 Traffic lights highway=traffic_signals
🛑 Stop sign in every direction highway=stop stop=all
🛑 Stop sign in some directions but not others highway=priority
🔻 Yield sign in some directions but not others highway=priority
🤞 No signs, signals, or markings junction=uncontrolled

Remember, separate stop or yield signs will NOT be tagged with this quest. I have the feeling you didn't make that clear enough in the forum post.

That’s what the post is all about, from the title on down to the responses.

Also, what is the reason it should only be active for the US?

As stated in the original post, the U.S. has no concept of a priority road – here are 75 obvious tagging errors. Stop signs are very common, much more common than uncontrolled intersections. It’s my understanding that this differs markedly from other regions, where a similarly designed quest would be spammy and result in less useful data. Canada is in the same boat, if you’d like to expand this quest a little.

westnordost commented 1 year ago

Alright, I lost track of this ticket several times, but I think now all open questions have been solved.

1ec5 commented 1 year ago

Indeed, this query will return mid-block name changes.

As of drolbr/Overpass-API@87bc3264223a515bf940a64a1e6b86da0135d166 and Overpass v0.7.61, the way_link filter greatly simplifies the task of finding street intersections.

This improved query takes roughly 30% less time to complete, no longer misuses the around filter, and filters out L-intersections and r-intersections that are much less likely to have any traffic control devices.

westnordost commented 1 year ago

Hm okay, but StreetComplete does not use Overpass. The analyzing is done in code. (in OsmElementQuestType::getApplicableElements(mapData: MapDataWithGeometry): Iterable<Element>).

You are a swift programmer which is similar to kotlin, so maybe you want to take a shot at implementing this yourself instead of hoping someone else will show up to do this. Best start for this is usually just copying a quest that you think should work kind of similar and go from there, but Mateusz also wrote a kind of tutorial once that might be helpful (CONTRIBUTING_A_NEW_QUEST.md). AddKerbHeight (particularly what happens in findAllKerbNodes) is probably the most helpful one to start from (and also the most complex quest to date, I think). The filters are written heavily in a functional "stream" style. If you are interested, but need some (live) help, I am often in slack as you know.

1ec5 commented 1 year ago

Hm okay, but StreetComplete does not use Overpass. The analyzing is done in code.

Ah, I completely misunderstood from seeing references to Overpass in the documentation. Sorry for spamming this ticket in that case.

https://github.com/streetcomplete/StreetComplete/blob/8edbe342baec2c5edfb6f11ca1b95fbf7e826754/QUEST_GUIDELINES.md?plain=1#L28

You are a swift programmer which is similar to kotlin

Sort of like pretending I can speak Portuguese based on my command of Spanish. 😉 I certainly could figure it out even if I weren’t a Swift programmer, but unfortunately I won’t have time to contribute a quest for the time being. My comment was just meant to be informative rather than nagging.

westnordost commented 1 year ago

My comment was just meant to be informative rather than nagging.

Sure, wasn't understood as such, don't worry.