a-b-street / osm2streets

Convert OSM to street networks with detailed geometry
https://a-b-street.github.io/osm2streets
Apache License 2.0
102 stars 9 forks source link

Stop lines #165

Open dabreegster opened 1 year ago

dabreegster commented 1 year ago

Splitting out from #72. The representation:

pub struct Road {
    ...
    pub stop_line_start: StopLine,
    pub stop_line_end_: StopLine,
}

pub struct StopLine {
    /// Relative to the road's reference_line. Stop lines at the start of the road will have low
    /// values, and at the end will have values closer to the reference_line's length.
    pub vehicle_distance: Distance,
    /// If there is an advanced stop line for cyclists different than the vehicle position, this
    /// specifies it
    pub bike_distance: Option<Distance>,
    pub interruption: TrafficInterruption,
}

/// How a lane of travel is interrupted, as it meets another or ends.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
pub enum TrafficInterruption {
    Uninterrupted,
    Yield,
    Stop,
    Signal,
    DeadEnd,
}

As a first step, we can assign this based on heuristics and explicitly mapped things in OSM. An example heuristic could be figuring out that minor roads yield or stop and major roads are interrupted at uncontrolled intersections. We can then render it (necessary for debugging/development and also to improve visuals).

Is the representation what we want? I'm not sure what the distances should be relevant to... probably get_untrimmed_center_line like trim_start,end, not the reference line?

I'll add notes below as I figure out all the things in OSM that help us figure this out.

dabreegster commented 1 year ago

@matkoniecz, we're starting to represent different types of stop lines. Do you know of any other tags we should pay attention to? Thanks!

matkoniecz commented 1 year ago

I would take into account highway=crossing location

matkoniecz commented 1 year ago

But your list seems to find a lot of relevant stuff already

BudgieInWA commented 1 year ago

I like the proposed representation; it seems to cover all the cases I have thought of so far.

It's nice that the placement of the stop line is decoupled from the trim distance, so we have the freedom to independently set the trim distance as needed in order to understand intersections and their geometry.

I think the distance needs to be relative to the same thing that trim_{start,end} is relative to, so that when we have trimmed geometry, we can do road.stop_line_start.driving_distance - road.trim_start to figure out how far the stop line is from the start of the trimmed geometry.

dabreegster commented 1 year ago

I think the distance needs to be relative to the same thing that trim_{start,end} is relative to,

Yeah, makes sense.

I started playing with this idea yesterday and already hit conceptual difficulties related to #159. streets_reader is the place to scrape all the OSM tags, and in split_ways.rs, we can fill out stop line info. But what happens if later we update the reference line, and thus the untrimmed line, and all of the relative distances for stop lines need to change? How do we preserve them? Do we need to hold onto raw Pt2D positions and always find the closest point to a line + the distance along that line?

Where should we infer defaults for stop lines? I was tempted to put it in something like update_center_line, but again that would clobber anything explicitly found earlier.

And there's unclear dataflow between StopLine.interruption and an intersection's ControlType. When we find a cycleway=asl, we'd have to go check the intersection to see if it might be a traffic signal or not. So then we have to be sure and apply highway=traffic_signals with direction (tagged on roads, not at the intersection) first.