Our last blog post (German) about the “Straßenraumkarte” (public space map) is a few month old now. Alex continued to improve his map with even more attention to detail.
This blog post will look at those details, showing example screenshots and referencing the (micro) mapping practices – the tags – required to generate such an exquisite map. It is written by Tobias @tordans with Alex’ @Supaplex030 input and review.
An experimental map for Neukölln
As a reminder, this map is part of the Berlin OSM Verkehrswende UserGroup (user group OSM “traffic evolution”). It is an experiment, focussed on showcasing how detailed mapping of urban environment and street lane infrastructure – especially for bike and foot traffic – can be done with OSM.
It is only available for the district of Berlin Neukölln since it requires a very high detail of mapping in the area and the pre-processing script is optimized for experimentation and details, not scale.
Bike lanes: Show them in detail…
Bike lanes are now rendered right where you would find them on the street. And with marking, color and separation details.
Most of the micromapping involved for bike lanes is documented in our work in progress wiki page (German) and the work in progress proposal page for cycleway:separation
(English). Most importantly, we show …
- Surface color where present, mainly
highway=cycleway + surface:colour=red|green
. - Line marking and separation, mainly
highway=cycleway + separation:left|right=solid_line|dashed_line|bollard
andbuffer:left|right=<m>
. - Cycleway
width
, where specified.
Those are the tags used for separately mapped cycle ways, the wiki page shows examples for mapping on the main lane.
Bike lanes: Position them right…
The map shows separately mapped, physically separated cycleways (mapped as a separate way next to the road).
But more importantly, it shows those cycleways that are mapped on the main lane as well. This requires quite a bit of pre-processing to prepare the data for the map. This is a simple example: https://www.openstreetmap.org/way/986957310.
cycleway:both=lane
tells us to prepare cycleways on each side of this street. The cycleway separation- and surface-color-Tag specifies color and type of line marking.lanes=2
andwidth:lanes:forward/backward=4.2
tells us the space that cars take up. Default lane width in our local area is 3 (meter), but sometimes it differs.- finally
lane_markings=yes
tells us to mark the middle of the road with a dashed line
As a result, the cycle ways can be placed left and right of the car lanes with high precision.
A more complex example is way/413997566:
To display this correctly, more information is required:
- Again,
lanes=2
tells us to look out for two car lanes (historically only counting car lanes, even if there are special lanes for cyclists) - But
bicycle:lanes=no|designated|yes
andvehicle:lanes=yes|no|yes
indicates that there are more traffic modes present than cars – an exclusive bike lane between the car lanes in this case (cycleway:lanes=none|lane|none
makes it more explicit that this is a cycle lane).turn:lanes=left|left;through|right
is used for rendering the turn lane arrows. - In this case, we mapped the available space/lane width directly with
width:lanes=3|1.5|4
(car lane, cycle lane, car lane) - Additionally,
placement=right_of:1
helps to place the lanes precisely in relation to position of the osm way by indicating that the way geometry is located right of the first (left) lane and all other lanes are to be rendered right of it.
Adding that information to the preprocessing allows us to render the map with a cycleway right where we find it on the road.
Processing all this correctly now makes up for about two thirds of the pre-processing script.
Lane markings: Arrows left, right and center…
The map shows turn lane arrows on the lane. We already described the tagging required for this in the chapter above (turn:lanes
). Here are a few examples of complex and nice map clippings:
Lane markings: Buses only…
And while we are on the topic of painting on the lanes: Bus lanes are rendered with a “BUS” sign, based on lanes=3 + lanes:psv=1
. Tagging Reminder: in this case – and in contrast to the cycle way lane described in the chapter above – the bus lane is counted as part of lanes
-count.
Lane markings: Cases without a dashed line…
The map now shows lane markings as a dashed line in the middle of the road.
Respecting overtaking=no
(Wiki), of course, by showing this situation with a solid line – which happens once in the area of the map ;-).
Alex has plans to support the key change
(Wiki) in the future.
Streets that have lanes=2
but no marking are mapped with lane_markings=no
and do not show any markings.
Lane markings: Traffic islands require very special treatment…
A key challenge for the correct rendering of lanes are situations, when lanes split to create room for eg. traffic islands. An example for such a situation is way/954390045 at Hermannstraße (OSM) which flows around a traffic_calming=island
area (OSM).
Without any special treatment, the lanes would show up wrong (see Illustration, section “Rendering (lane markings)”, left), since the OSM data is not optimized for renderers. The goal is to show the lane markings as going more or less straight past the traffic island (see Illustration, right).
To solve this problem, we first need to identify those lane segments that are part of a dual carriageway, but split during mapping. In Neukölln, we use the tag dual_carriageway=yes
(Wiki) for this.
During pre-processing, the script can now check where a lane segment with dual_carriageway=yes
connects to a lane segment without the tag and then split and spread the lane (see Illustration, section “Post processed”).
Junctions, an unsolved problem…
Getting junctions right based on OSM data is hard. Dustin Carlino of ABStreet, an OSM based traffic simulation, gives a good overview about the issues he has and workarounds he applies in his recent StateOfTheMap 2021 Talk (Video, Starting ~12:30).
The goal of Alex’ micro mapping map is to create a map based on OSM data that represents what we see in real life as closely as possible. For junctions, that has two parts: stop lines and lane/turn lanes.
Stop lines: For this experimental map and for this area, that is mapped in high detail, this problem is solved (see below).
Lanes and turn lanes on the junction: Unfortunately, this is still not solved. Below is a list of experiments that solve part of this problem. But they are complex to map and are touching (or crossing?) the border to be “tagging for the renderer”.
The issue with junctions
This is, what a junction without special treatment looks like:
- The lane markings are a mess of crossing lines inside the junction
- Cycleways need special treatment in those situations
For comparison, let’s have a look at this junction on an aerial image:
For now, cut out junctions with area:highway
Alex’ solution for the given issues is to not render any lane markings for junctions. To specify the cut out area, all complex junctions in our experimentation area of Neukölln are mapped with area:highway=secondary|tertiary|… + junction=yes
. This tagging schema adds information to the map without disturbing the existing data. ATM, about 60 junctions in Neukölln are mapped this way (Overpass-turbo query).
If you want to read more, the wiki page that documents the status quo is a good place to start and the linked proposals as well. However, area:highway
is a very broad topic and not recommended to be applied without good reason and good planning.
The area:highway
mapping is also the basis for rending stop lines, our next chapter.
Junctions: Rendering stop lines right …
Where area:highway
is used, the map shows the stop line on the intersection of lanes/cycleway and junction area. For some cycleways those stop positions are brought forward, which can also be mapped by adding more details to the area.
For those curious about how those stop lines are rendered, here are more details …
- The
highway=traffic_signal
node (https://www.openstreetmap.org/node/5721702240) is part of thearea:highway
-outline. It represents the stop position. - The street (https://www.openstreetmap.org/way/413997566) is connected to the
area:highway
at this point. - Based on the placement tags
placement=right_of:1
and laneslanes=2
, the pre-processing calculates the length of the stop position line. — Example: For a 2 lane highway with the highway placed in the middle of the road and a default lane width of 3 meter, the stop line would continue 3 meter left and right of the traffic signal node. - If there is no
area:highway
-junction (see below), the line is drawn at 90°. - If there is an
area:highway
(https://www.openstreetmap.org/way/964402755), the line follows the given shape and draws the stop line. But only for segments of the outline, that use the same direction as the initial part of the way. And of course only, until it intersects with abarrier=kerb
. This makes sure, that in the given case (https://www.openstreetmap.org/node/5721702240) the cycleway stop line is drawn, but the parts that are parallel to the cycleway (and about 90° to the initial part of the way) are not.
For crossings without area:highway
, the stop line is rendered at 90° to the way at the position of the traffic signals (or stop sign) position. The length of the line depends on the number and width of lanes.
Junctions: Experiments to draw lanes and turn lanes despite all…
I wrote before that junctions are basically blank areas, since rendering lanes and turn lanes right is just too hard. Of course, Alex tried anyway :-). Here are a few experiments.
As the name suggests, those experiments are not standardized mapping practice and they do sometimes use non-standard tagging. This writeup is not meant as a review of those tags or to conclude the experiments. Instead it is meant to show what is possible and how, to continue and improve the discussion if and how to solve those mapping challenges.
Experiment: Overwrite the cut-out-rule for all cycleway crossing
In cases where the cycleway is mapped as a separate way, rendering the cycleway in junctions works well – at least for simple cycleway crossing configurations.
However, in cases where the cycleway is mapped as part of the main way, the rendering needs quite a bit more work to handle edge cases (Example).
Experiment: Overwrite the cut out-rule by specifying lane_markings:junction=yes
on the way.
It tells the renderer to add the lane markings even though this is an area:highway
-junction.
Other approaches
There is an experimental taggging from 2014 to draw road markings https://wiki.openstreetmap.org/wiki/Key:road_marking which might be a way to solve the visual issues discussed here.
Restricted areas
Since we just talked about area:highway
, let’s have a look at another detail: The map also uses area:highway=prohibited
to render restricted areas on the street (traffic sign 298, Wikipedia). We brushed of this in our last update, so here is an example:
You will also find places (Example) where this micro mapping is in conflict with the detailed rendering of bike lanes. At Glasower Straße, those markings are supposed to tame parked cars into their right spot, which makes for an unusuals pattern.
Pedestrian crossings: Show them in detail…
Following the spirit of the map, pedestrian crossings are rendered as detailed as possible.
Example: Zebra crossing (and curb-extension)
Example: Crossing with paint crossing:buffer_marking=both
(Experimental tagging, see Wiki “Gehwege” (German))
This kind of crossing is often combined with marked, restricted areas.
Example: Traffic signal.
Visually it’s just two lines, based on the crossing width
or default (5 m). The pre-processor extends the line and then cuts them at the curb (extreme example of this extension).
Most crossings in this experimentation area of Neukölln are mapped as separate sidewalks. However, this rendering also works for crossings, that are mapped as just a node on the main way: Example osm_url=”https://www.openstreetmap.org/node/8119544899”
Pedestrian crossing: Make tactile paving visible…
The updated map provides some nice motivation to add tactile paving tagging (Wiki) to the map. Add kerb=* + tactile_paving=yes
as a node on the crossing way where it intersects with a barrier=kerb
way that follows the curb.
To render it in the right place, the preprocessor creates a buffer circle around the curb node (with the buffer depending on the crossing width
or using a default value) and clips the intersecting barrier=kerb
way segments inside this buffer.
Barrier boards
Another little detail of the map is how the more types of barriers become visible. We micromap them with barrier=barrier_board + traffic_sign=DE:600
(if that is the case). In Neukölln, they are often used to split off sections of parked cars and protect bike stands.
Individual trees in woods
Before we finish, let’s take a break and look at some trees.
They have always been rendered in a lot of detail – respecting the crown diameter where tagged (diameter_crown
and trying to derive a good fallback value based on height, age or the trunk’s circumference
.
Now, let’s have a look at the natural=wood
in our our Lessinghöhe park:
The trees of the wood are placed randomly in a nicely organized hexagon grid, resulting in a random but tidy wood structure.
But how do I know which tree is micro mapped (real) and which are “virtually” trees in woods? Glad you asked ;-). Separately mapped trees are indicated by the brown trunc in the middle (which size is based on the mapped or derived circumvence, of course).
Finally, parked cars
In case you didn’t know, this map first started as a side project to the parking analysis (Map, Blogpost (EN)). So those parked cars were already visualized in high detail right from the start.
But this would not be a good micro map update, without adding some details to parking, so here is a place where only police may park:
And a place where only busses are allowed to park parking:condition:left|right:vehicles=bus
And a place where only taxi are allowed to park parking:condition:right|left=taxi
And a place where only trucks and vans are allowed to park parking:condition:both:vehicles=hgv
And of course there is a place where parking is allowed only for motorcars parking:condition:right:vehicles=motorcar
(OSM), but that looks visually very similar (it’s just the random vans that are missing).
Let’s talk about preprocessed OSM data
In her SOTM 2021 talk, Sarah Hoffmann nudged us to think about preprocessed OSM data (minute 21:54). This project is an example of that. It requires a lot of normalization and preprocessing to prepare the OSM data to be rendered.
And I am not talking about the trees, even though deriving the trunk size based on the crown diameter is certainly a fun processing experiment ;-).
There are two datasets here that would benefit from a standardized processing script and download: Parking data and lane data.
Preprocessed parking data:
For this experiment in Neukölln, the data is available in a preprocessed format on GitHub. So is the GQIS/Python Script to process the OSM parking data. And there is even a video of Alex explaining with nice visual slides how the model works in his FOSSGIS presentation from the beginning of the year.
Btw, we would like to continue evaluating this process. Read more at “Call for help from the data science community: Evaluate tradeoffs in data quality for mapping parking data in OSM”.
Preprocessed lane data:
Alex published the QGIS/Python Script that does a lot of the processing described in this blogpost.
Interpreting OSM lane data for visualizations like this or projects like AB Street is extremely complex. Please check out and help the new osm2lanes projects that started work on a standardized parser for the lane schema at https://github.com/a-b-street/osm2lanes.
Have fun exploring Neukölln
That’s it for this update. Have fun exploring Neukölln 👋.