osm2lanes

12 March 2022, FOSSGIS OSM-Samstag

Dustin Carlino & Michael Droogleever

Intro

About Dustin

About Michael

Talk Outline

  1. Background
  2. How it works today
  3. Complications
  4. Next steps / contributing

Part 1: Background

A/B Street

  • a bunch of tools to explore less cars in cities
  • all work off a heavily processed map representation
    • road and intersection geometry
    • driveways between buildings and roads, parking lot capacity
    • turn restrictions, traffic signal timing, routing

Edit Roads

Simulate Traffic

Plan Bike Networks

bike.abstreet.org

Low-traffic Neighborhoods

ltn.abstreet.org

Sharing Code

Why’s this hard?

Why does it have to be hard?

From left to right:

[
  { type=sidewalk, surface_color=black },
  { curb },
  { type=cycle, direction=forward, surface_color=red, est_width=1.5 },
  { curb },
  { type=travel, surface_color=black, direction=forward, allow taxi },
  { type=travel, surface_color=black, direction=backward, allow taxi },
  { curb },
  { type=cycle, direction=forward, surface_color=red, est_width=1.5 },
  { curb },
  { type=sidewalk, surface_color=black },
]
  • Arguments for mapping as separate ways
    • geometry: doesn’t help
    • per-lane detail: yes!

End-user Stories

Part 2: How it works today

Web demo: https://a-b-street.github.io/osm2lanes

Input

  • An OSM way’s tags
  • A locale (country / region code), for inferring if not explicitly defined, for example
    • tag meaning
    • left- or right-handed driving
    • lane widths
    • lane separator styles

Output

https://www.openstreetmap.org/way/22760280

{
  "Ok": {
    "road": {
      "lanes": [
        {
          "type": "travel",
          "direction": "backward",
          "designated": "bicycle",
          "width": 2.0
        },
        {
          "type": "separator",
          "markings": [
            {
              "style": "solid_line",
              "width": 0.2,
              "color": "white"
            }
          ]
        },
        {
          "type": "travel",
          "direction": "backward",
          "designated": "motor_vehicle",
          "width": 3.5
        },
        {
          "type": "separator",
          "markings": [
            {
              "style": "dotted_line",
              "width": 0.2,
              "color": "white"
            }
          ]
        },
        {
          "type": "travel",
          "direction": "forward",
          "designated": "motor_vehicle",
          "width": 3.5
        },
        {
          "type": "separator",
          "markings": [
            {
              "style": "solid_line",
              "width": 0.2,
              "color": "white"
            }
          ]
        },
        {
          "type": "travel",
          "direction": "forward",
          "designated": "bicycle",
          "width": 2.0
        }
      ],
      "highway": {
        "highway": {
          "Classified": "Secondary"
        },
        "lifecycle": "Active"
      }
    },
    "warnings": [
      "unimplemented: access, bicycle=designated"
    ]
  }
}

Output, osm2lanes

  • type
    • travel, parking, shoulder, separator
  • designated
    • foot, bike, motor vehicle, bus
    • (in the future we will add access=* per lane)
  • direction
    • forward, backward, both
  • width
  • markings / separators

Inverse, lanes2osm

  • An easier OSM lanes editor
    • Pick a way, grab its tags
    • osm2lanes
    • Edit the lanes with something Streetmix-like
    • lanes2osm
    • Upload the diff
  • Maybe a tag “autoformatter” in iD/JOSM?
  • Complications?

Code overview

  • https://github.com/a-b-street/osm2lanes
  • Rust, Python, and Kotlin
  • Originally…
    • make it easy for people to get involved, no matter the preferred language
    • “not hard” to keep the implementations in-sync
  • Going forward…
    • Rust can target any build environment

Tests!

https://github.com/a-b-street/osm2lanes/blob/main/data/tests.yml

Code Walkthrough

  • Lane schema
  • Nested switch case logic by transport mode
    special case non-motorized paths, bus, bike, parking, sidewalks / shoulders
  • forward and backward lanes handled separately, lanes usually appended inside-to-out
  • separators inserted last based on the two adjacent lane types

Part 3: Complications

Errors are rampant

unsupported: cycleway=* with any cycleway:* values


bicycle = designated
cycleway = lane
cycleway:left = separate
cycleway:right = lane
highway = secondary
lanes = 4
lanes:backward = 2
lanes:forward = 2
lcn = yes
maxheight = default
maxspeed = 25 mph
name = Dexter Avenue North
oneway = no
surface = paved

Error and Warning Handling

  • issues encountered in tags classified as
    • ambiguity
    • unimplemented
    • unsupported
    • deprecated
  • error is thrown if sufficiently problematic
  • otherwise a warning is added, and we try and continue

Inferred Values

not all data is right or wrong, usually it is missing

  • Direct tagged data
  • Calculated (total width must be the sum of the other widths)
  • Inferred (splitting total width over all the lanes evenly)
  • Default based on locale
  • Reasonable default

the data consumer wants to know what lane data was tagged and what was a guess?

Designated vs Allowed

  • footpaths allowing, but not prioritizing, cyclists
  • bus lanes allowing cyclists

this is a generic library

  • most rendering applications simply wants to know what the designated purpose is
  • a routing application wants to know what the full access is

Separate Ways

https://www.youtube.com/watch?v=LatorN4P9aA

Part 4: Next steps / contributing

https://github.com/a-b-street/osm2lanes

Test cases

we need a healthy combination of:

  • real world examples (with mapillary / pictures to know what exists on the ground)
  • esoteric examples, when real world examples cannot be found to test the extremes

osm2lanes

Most implementation is in Rust, but Rust is not too hard to learn.

Try one of the good first issues!

Web Interface

Web interface: https://a-b-street.github.io/osm2lanes/

  • written almost entirely in Rust
  • allows for rapid improvement of implementation

osm2lanes Future

Per-lane Width

  • Use it when it’s tagged
  • If we know the curb-to-curb width or entire road width…
    • sanely distribute width to known lanes

Per-lane Data

  • turn:lanes
  • allowed vehicles (bus lanes with bikes or taxis)
  • time-restricted turns or parking
  • surface type
  • speed limit

Locales

Library

  • This library needs to be used to be useful.
  • If you know a project that can use this functionality, help contribute there to make it a dependency.
  • Use it on your own projects!

Web map

https://github.com/a-b-street/osm2lanes/blob/main/web/index.html

  • Click a road, see its lanes in cross-section view
  • Rust <-> Javascript API
  • Publish on npm