Skip to content

Slightly decreases roundabout turn max radius from 25m to 15m - #4665

Merged
danpat merged 1 commit into
masterfrom
roundabout-turn
Nov 7, 2017
Merged

danpat merged 1 commit into
masterfrom
roundabout-turn

Conversation

@daniel-j-h

Copy link
Copy Markdown
Member

Roundabout turns are meant for situations like the following:

real-life

Quoting @1ec5:

In general, neighborhood roundabouts should have the same dimensions as mini roundabouts, the only difference being a planter instead of a traversable bump. For example, the City of Sacramento’s street design standards specify an inscribed circle diameter of 120 feet (36 meters) for standard single-lane roundabouts. The FHWA recommends a diameter of 90–180 ft. (27–55 m) for standard roundabouts and 45–90 ft. (13–27 m) for mini roundabouts.

@TheMarex

TheMarex commented Nov 4, 2017

Copy link
Copy Markdown
Member

Next steps here:

  • Generate a map of affected locations
  • Pick a random subset and use Mapillary to verify if we only fixed locations that we wanted
  • Decide if we want to have this as a global change
@daniel-j-h

daniel-j-h commented Nov 6, 2017 •

Copy link
Copy Markdown
Member Author

Super quick comparison from the stats handler we just merged into master - on California base map:

instruction master this branch
roundabout turn 10 10
enter roundabout turn 1951 1702
exit roundabout turn 2007 1741
enter and exit roundabout turn 15 15

full log

@danpat

danpat commented Nov 6, 2017

Copy link
Copy Markdown
Member

Here's the diff:

screen shot 2017-11-06 at 3 53 50 pm

@miccolis
miccolis requested a review from 1ec5 November 6, 2017 20:54
@1ec5

1ec5 commented Nov 7, 2017

Copy link
Copy Markdown
Member

The table above distinguishes between roundabout turn, enter roundabout turn, and exit roundabout turn, whereas my understanding is that “roundabout turns” would be treated as atomic maneuvers. Can you explain the difference?

@daniel-j-h

Copy link
Copy Markdown
Member Author

Yes roundabout turns are atomic from the API's point of view after post-processing. The above table is from pre-processing and includes internal instructions:

namespace TurnType
{
typedef std::uint8_t Enum;
const constexpr Enum Invalid = 0; // no valid turn instruction
const constexpr Enum NewName = 1; // no turn, but name changes
const constexpr Enum Continue = 2; // remain on a street
const constexpr Enum Turn = 3; // basic turn
const constexpr Enum Merge = 4; // merge onto a street
const constexpr Enum OnRamp = 5; // special turn (highway ramp on-ramps)
const constexpr Enum OffRamp = 6; // special turn, highway exit
const constexpr Enum Fork = 7; // fork road splitting up
const constexpr Enum EndOfRoad = 8; // T intersection
const constexpr Enum Notification = 9; // Travel Mode Changes, Restrictions apply...
const constexpr Enum EnterRoundabout = 10; // Entering a small Roundabout
const constexpr Enum EnterAndExitRoundabout = 11; // Touching a roundabout
const constexpr Enum EnterRotary = 12; // Enter a rotary
const constexpr Enum EnterAndExitRotary = 13; // Touching a rotary
const constexpr Enum EnterRoundaboutIntersection = 14; // Entering a small Roundabout
const constexpr Enum EnterAndExitRoundaboutIntersection = 15; // Touching a roundabout
// depreacted: const constexpr Enum UseLane = 16; // No Turn, but you need to stay on a given lane!
// Values below here are silent instructions
const constexpr Enum NoTurn = 17; // end of segment without turn/middle of a segment
const constexpr Enum Suppressed = 18; // location that suppresses a turn
const constexpr Enum EnterRoundaboutAtExit = 19; // Entering a small Roundabout at a countable exit
const constexpr Enum ExitRoundabout = 20; // Exiting a small Roundabout
const constexpr Enum EnterRotaryAtExit = 21; // Enter A Rotary at a countable exit
const constexpr Enum ExitRotary = 22; // Exit a rotary
const constexpr Enum EnterRoundaboutIntersectionAtExit =
23; // Entering a small Roundabout at a countable exit
const constexpr Enum ExitRoundaboutIntersection = 24; // Exiting a small Roundabout
const constexpr Enum StayOnRoundabout = 25; // Continue on Either a small or a large Roundabout
const constexpr Enum Sliproad =
26; // Something that looks like a ramp, but is actually just a small sliproad
const constexpr Enum MaxTurnType = 27; // Special value for static asserts
}

Orthogonal to the turn instructions our roundabout handler knows about the different roundabout types:

enum class RoundaboutType
{
None, // not a roundabout
Roundabout, // standard roundabout
Rotary, // traffic circle (large roundabout) with dedicated name
RoundaboutIntersection // small roundabout with distinct turns, handled as intersection
};

In post-processing we then do e.g. exit counting for regular roundabouts and rotaries and collapse everything between enter and exit roundabout turn instructions. Then you have your single roundabout turn instruction.

@daniel-j-h

Copy link
Copy Markdown
Member Author

Quick follow up here: currently the split between pre- and post-processing does not allow us to generate statistics for the post-processing part easily (other than querying for routes and see what we get out).

Ideally we could move all post-processing into pre-processing. Then we'd have maneuvers in our graph already and a clean and encapsulated guidance engine - something to look into in the future.

@1ec5 1ec5 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a sound change, at least as far as U.S. standards are concerned. Anything near this cutoff, such as a standard roundabout with the absolute minimum 14-meter radius specified in the standards, would be small enough that the motorist would not be confused by a turn instruction.

@danpat

danpat commented Nov 7, 2017 •

Copy link
Copy Markdown
Member

Our debug tiles contain point features for every maneuver. I generated the debug tile for x=511,y=340,z=10 (London, UK) with:

curl 'http://localhost:5000/tile/v1/car/tile(511,340,10).mvt'

for both this branch and master, and converted to GeoJSON with https://github.com/mapbox/vt2geojson

I then wrote a small script to compare the generated GeoJSON and make a map of the features that changed.

Here's the map:
http://bl.ocks.org/d/c5f88424738c01be146ce1638e5ee9cb

TL;DR - change looks fine. A few roundabouts that were very close (but under) to the 25m threshold have been converted to proper roundabouts. None of the changes look bad and there don't seem to be any surprises.

GeoJSON diffing script
#!/usr/bin/env node

var fs = require('fs');

if (process.argv.length < 4) {
  console.log(`Usage: ${process.argv[1]} <before.geojson> <after.geojson>`);
  return;
}

var before = JSON.parse(fs.readFileSync(process.argv[2]));
var after = JSON.parse(fs.readFileSync(process.argv[3]));


var diff = [];

for (var i in before.features) {

    // TODO: do a deep equal here to compare all properties
    if (before.features[i].properties.type !== after.features[i].properties.type ||
        before.features[i].properties.modifier !== after.features[i].properties.modifier) {

        var f = before.features[i];
        f.properties.before_type = f.properties.type;
        f.properties.after_type = after.features[i].properties.type;
        f.properties.before_modifier = f.properties.modifier;
        f.properties.after_modifier = after.features[i].properties.modifier;
        delete f.properties.type;
        delete f.properties.modifier;
        diff.push(f);

    }
}

console.log(JSON.stringify({'type':'FeatureCollection','features':diff}));
@danpat
danpat merged commit 3a1bf2c into master Nov 7, 2017
@daniel-j-h
daniel-j-h deleted the roundabout-turn branch November 7, 2017 19:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

4 participants