Added post process logic to collapse segregated turn instructions (#4925)

* Added post process logic to collapse segregated turn instructions

* format updates

* Fixed coordinates to reflect reality
Updated left turn road name

* fixed coordinates to fix test

* Skip last step when processing segregated steps

* updated segregated turn test

* Updated segregated test

* Updated test: Segregated Intersection, Cross Belonging to Correct Street - features/guidance/collapse.feature:79

* Fixed all but one for features/guidance/collapse.feature:124

* Fixed Scenario: Partly Segregated Intersection, Two Segregated Roads, Intersection belongs to Second - features/guidance/collapse.feature:219

* Fixed 7 of th 9 failures for Scenario: Partly Segregated Intersection, Two Segregated Roads, Intersection belongs to Second - features/guidance/collapse.feature:219

* Fixed 7 of the 9 failures for Scenario: Segregated Intersection, Cross Belonging to Mixed Streets - Slight Angles (2) - features/guidance/collapse.feature:318

* Fixed Scenario: Segregated Intersection into Slight Turn - features/guidance/collapse.feature:581

* Updated Scenario: U-turn after a traffic light - features/guidance/turn-lanes.feature:1220

* Updated how we combine segregated steps

* Added test to Verify end of road left turn across divided roads

* Fixed divided highwat tests

* Fixed test failure

* fixed Scenario: Partitioned turn, Slight Curve - maxspeed - features/guidance/turn-lanes.feature:936

* Fixed Scenario: Partitioned turn, Slight Curve - features/guidance/turn-lanes.feature:961

* Added strategies to combine segrgated intersections

* Added setModifier alias for readability

* Added strategies to combine segrgated intersections

* Format updates

* Fixes segregated indentification to not mark `circular` edge as segregated

* Added intersection prior to turn so we still call out end of road

* updated expectation to be turn instead of continue

* Confirmed with @oxidase that the lane information if correct - updated the expectation

* Added logic to handle wider straights
Fixed tests

* Update CHANGELOG.md

Added #4925

* Removed TODO

* Process straight step prior to wider straight step
This commit is contained in:
Duane Gearhart 2018-03-30 07:43:56 -04:00 committed by GitHub
parent 0d9f18fe1f
commit 8a63ad9b4b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 449 additions and 121 deletions

View File

@ -11,12 +11,13 @@
- Guidance:
- CHANGED #4929: Don't use obviousness for links bifurcations [#4929](https://github.com/Project-OSRM/osrm-backend/pull/4929)
- FIXED #4929: Adjust Straight direction modifiers of side roads in driveway handler [#4929](https://github.com/Project-OSRM/osrm-backend/pull/4929)
- CHANGED #4925: Added post process logic to collapse segregated turn instructions [#4925](https://github.com/Project-OSRM/osrm-backend/pull/4925)
- Tools:
- `osrm-routed` accepts a new property `--memory_file` to store memory in a file on disk.
- NodeJS:
- `OSRM` object accepts a new option `memory_file` that stores the memory in a file on disk.
- Internals
- CHANGED #4845 #4968: Updated segregated intersection identification
- CHANGED #4845 #4968: Updated segregated intersection identification [#4845](https://github.com/Project-OSRM/osrm-backend/pull/4845) [#4968](https://github.com/Project-OSRM/osrm-backend/pull/4968)
- REMOVED: Remove `.timestamp` file since it was unused.
- Documentation:
- ADDED: Add documentation about OSM node ids in nearest service response [#4436](https://github.com/Project-OSRM/osrm-backend/pull/4436)

View File

@ -691,14 +691,14 @@ Feature: Car - Turn restrictions
# """
Given the node locations
| node | lat | lon |
| a | 38.9113 | -77.0091 |
| b | 38.9108 | -77.0091 |
| c | 38.9104 | -77.0091 |
| d | 38.9110 | -77.0096 |
| e | 38.9106 | -77.0086 |
| f | 38.9105 | -77.0090 |
| g | 38.9108 | -77.0090 |
| h | 38.9113 | -77.0090 |
| a | 38.91124 | -77.00909 |
| b | 38.91080 | -77.00909 |
| c | 38.91038 | -77.00909 |
| d | 38.91105 | -77.00967 |
| e | 38.91037 | -77.00807 |
| f | 38.91036 | -77.00899 |
| g | 38.91076 | -77.00901 |
| h | 38.91124 | -77.00900 |
And the ways
| nodes | oneway | name |
@ -719,7 +719,7 @@ Feature: Car - Turn restrictions
When I route I should get
| from | to | route | turns |
| a | e | cap south,florida nw,florida nw,florida ne | depart,turn right,continue uturn,arrive |
| f | d | cap north,florida,florida nw | depart,turn left,arrive |
| f | d | cap north,florida nw,florida nw | depart,turn left,arrive |
| e | c | florida ne,florida nw,cap south,cap south | depart,continue uturn,turn right,arrive |
@no_turning @conditionals
@ -738,14 +738,14 @@ Feature: Car - Turn restrictions
# """
Given the node locations
| node | lat | lon |
| a | 38.9113 | -77.0091 |
| b | 38.9108 | -77.0091 |
| c | 38.9104 | -77.0091 |
| d | 38.9110 | -77.0096 |
| e | 38.9106 | -77.0086 |
| f | 38.9105 | -77.0090 |
| g | 38.9108 | -77.0090 |
| h | 38.9113 | -77.0090 |
| a | 38.91124 | -77.00909 |
| b | 38.91080 | -77.00909 |
| c | 38.91038 | -77.00909 |
| d | 38.91105 | -77.00967 |
| e | 38.91037 | -77.00807 |
| f | 38.91036 | -77.00899 |
| g | 38.91076 | -77.00901 |
| h | 38.91124 | -77.00900 |
And the ways
| nodes | oneway | name |
@ -765,7 +765,7 @@ Feature: Car - Turn restrictions
When I route I should get
| from | to | route | turns |
| a | e | cap south,florida,florida ne | depart,turn left,arrive |
| a | e | cap south,florida ne,florida ne | depart,turn left,arrive |
| f | d | cap north,florida ne,florida ne,florida nw | depart,turn sharp right,continue uturn,arrive |
| e | c | florida ne,cap south,cap south | depart,turn left,arrive |

View File

@ -35,20 +35,20 @@ Feature: Collapse
| waypoints | route | turns | locations |
| a,l | first,second,second | depart,turn right,arrive | a,b,l |
| a,d | first,first | depart,arrive | a,d |
| a,j | first,second,second | depart,turn left,arrive | a,c,j |
| a,h | first,first,first | depart,continue uturn,arrive | a,c,h |
| a,j | first,second,second | depart,turn left,arrive | a,b,j |
| a,h | first,first,first | depart,continue uturn,arrive | a,b,h |
| e,j | first,second,second | depart,turn right,arrive | e,f,j |
| e,h | first,first | depart,arrive | e,h |
| e,l | first,second,second | depart,turn left,arrive | e,g,l |
| e,d | first,first,first | depart,continue uturn,arrive | e,g,d |
| e,l | first,second,second | depart,turn left,arrive | e,f,l |
| e,d | first,first,first | depart,continue uturn,arrive | e,f,d |
| k,h | second,first,first | depart,turn right,arrive | k,g,h |
| k,l | second,second | depart,arrive | k,l |
| k,d | second,first,first | depart,turn left,arrive | k,b,d |
| k,j | second,second,second | depart,continue uturn,arrive | k,b,j |
| k,d | second,first,first | depart,turn left,arrive | k,g,d |
| k,j | second,second,second | depart,continue uturn,arrive | k,g,j |
| i,d | second,first,first | depart,turn right,arrive | i,c,d |
| i,j | second,second | depart,arrive | i,j |
| i,h | second,first,first | depart,turn left,arrive | i,f,h |
| i,l | second,second,second | depart,continue uturn,arrive | i,f,l |
| i,h | second,first,first | depart,turn left,arrive | i,c,h |
| i,l | second,second,second | depart,continue uturn,arrive | i,c,l |
Scenario: Segregated Intersection, Cross Belonging to Single Street
Given the node map
@ -74,7 +74,7 @@ Feature: Collapse
When I route I should get
| waypoints | route | turns | locations |
| a,i | first,second,third,third | depart,turn left,turn slight left,arrive | a,b,e,i |
| a,i | first,third,third | depart,turn sharp left,arrive | a,b,i |
Scenario: Segregated Intersection, Cross Belonging to Correct Street
Given the node map
@ -106,20 +106,20 @@ Feature: Collapse
| waypoints | route | turns | locations |
| a,l | first,second,second | depart,turn right,arrive | a,b,l |
| a,d | first,first | depart,arrive | a,d |
| a,j | first,second,second | depart,turn left,arrive | a,c,j |
| a,h | first,first,first | depart,continue uturn,arrive | a,c,h |
| a,j | first,second,second | depart,turn left,arrive | a,b,j |
| a,h | first,first,first | depart,continue uturn,arrive | a,b,h |
| e,j | first,second,second | depart,turn right,arrive | e,f,j |
| e,h | first,first | depart,arrive | e,h |
| e,l | first,second,second | depart,turn left,arrive | e,g,l |
| e,d | first,first,first | depart,continue uturn,arrive | e,g,d |
| e,l | first,second,second | depart,turn left,arrive | e,f,l |
| e,d | first,first,first | depart,continue uturn,arrive | e,f,d |
| k,h | second,first,first | depart,turn right,arrive | k,g,h |
| k,l | second,second | depart,arrive | k,l |
| k,d | second,first,first | depart,turn left,arrive | k,b,d |
| k,j | second,second,second | depart,continue uturn,arrive | k,b,j |
| k,d | second,first,first | depart,turn left,arrive | k,g,d |
| k,j | second,second,second | depart,continue uturn,arrive | k,g,j |
| i,d | second,first,first | depart,turn right,arrive | i,c,d |
| i,j | second,second | depart,arrive | i,j |
| i,h | second,first,first | depart,turn left,arrive | i,f,h |
| i,l | second,second,second | depart,continue uturn,arrive | i,f,l |
| i,h | second,first,first | depart,turn left,arrive | i,c,h |
| i,l | second,second,second | depart,continue uturn,arrive | i,c,l |
Scenario: Segregated Intersection, Cross Belonging to Mixed Streets
Given the node map
@ -151,20 +151,20 @@ Feature: Collapse
| waypoints | route | turns | locations |
| a,l | first,second,second | depart,turn right,arrive | a,b,l |
| a,d | first,first | depart,arrive | a,d |
| a,j | first,second,second | depart,turn left,arrive | a,c,j |
| a,h | first,first,first | depart,continue uturn,arrive | a,c,h |
| a,j | first,second,second | depart,turn left,arrive | a,b,j |
| a,h | first,first,first | depart,continue uturn,arrive | a,b,h |
| e,j | first,second,second | depart,turn right,arrive | e,f,j |
| e,h | first,first | depart,arrive | e,h |
| e,l | first,second,second | depart,turn left,arrive | e,g,l |
| e,d | first,first,first | depart,continue uturn,arrive | e,g,d |
| e,l | first,second,second | depart,turn left,arrive | e,f,l |
| e,d | first,first,first | depart,continue uturn,arrive | e,f,d |
| k,h | second,first,first | depart,turn right,arrive | k,g,h |
| k,l | second,second | depart,arrive | k,l |
| k,d | second,first,first | depart,turn left,arrive | k,b,d |
| k,j | second,second,second | depart,continue uturn,arrive | k,b,j |
| k,d | second,first,first | depart,turn left,arrive | k,g,d |
| k,j | second,second,second | depart,continue uturn,arrive | k,g,j |
| i,d | second,first,first | depart,turn right,arrive | i,c,d |
| i,j | second,second | depart,arrive | i,j |
| i,h | second,first,first | depart,turn left,arrive | i,f,h |
| i,l | second,second,second | depart,continue uturn,arrive | i,f,l |
| i,h | second,first,first | depart,turn left,arrive | i,c,h |
| i,l | second,second,second | depart,continue uturn,arrive | i,c,l |
Scenario: Partly Segregated Intersection, Two Segregated Roads
Given the node map
@ -209,11 +209,11 @@ Feature: Collapse
| d,c | first,first,first | depart,continue uturn,arrive | d,e,c |
| g,c | second,first,first | depart,turn right,arrive | g,b,c |
| g,j | second,second | depart,arrive | g,j |
| g,f | second,first,first | depart,turn left,arrive | g,e,f |
| g,f | second,first,first | depart,turn left,arrive | g,b,f |
| g,h | second,second,second | depart,continue uturn,arrive | g,b,h |
| i,f | second,first,first | depart,turn right,arrive | i,e,f |
| i,h | second,second | depart,arrive | i,h |
| i,c | second,first,first | depart,turn left,arrive | i,b,c |
| i,c | second,first,first | depart,turn left,arrive | i,e,c |
| i,j | second,second,second | depart,continue uturn,arrive | i,e,j |
Scenario: Partly Segregated Intersection, Two Segregated Roads, Intersection belongs to Second
@ -263,11 +263,11 @@ Feature: Collapse
| d,c | first,first,first | depart,continue uturn,arrive | d,e,c |
| g,c | second,first,first | depart,turn right,arrive | g,b,c |
| g,j | second,second | depart,arrive | g,j |
| g,f | second,first,first | depart,turn left,arrive | g,e,f |
| g,f | second,first,first | depart,turn left,arrive | g,b,f |
| g,h | second,second,second | depart,continue uturn,arrive | g,b,h |
| i,f | second,first,first | depart,turn right,arrive | i,e,f |
| i,h | second,second | depart,arrive | i,h |
| i,c | second,first,first | depart,turn left,arrive | i,b,c |
| i,c | second,first,first | depart,turn left,arrive | i,e,c |
| i,j | second,second,second | depart,continue uturn,arrive | i,e,j |
Scenario: Segregated Intersection, Cross Belonging to Mixed Streets - Slight Angles
@ -300,20 +300,20 @@ Feature: Collapse
| waypoints | route | turns | locations |
| a,l | first,second,second | depart,turn right,arrive | a,b,l |
| a,d | first,first | depart,arrive | a,d |
| a,j | first,second,second | depart,turn left,arrive | a,c,j |
| a,h | first,first,first | depart,continue uturn,arrive | a,c,h |
| a,j | first,second,second | depart,turn left,arrive | a,b,j |
| a,h | first,first,first | depart,continue uturn,arrive | a,b,h |
| e,j | first,second,second | depart,turn right,arrive | e,f,j |
| e,h | first,first | depart,arrive | e,h |
| e,l | first,second,second | depart,turn left,arrive | e,g,l |
| e,d | first,first,first | depart,continue uturn,arrive | e,g,d |
| e,l | first,second,second | depart,turn left,arrive | e,f,l |
| e,d | first,first,first | depart,continue uturn,arrive | e,f,d |
| k,h | second,first,first | depart,turn right,arrive | k,g,h |
| k,l | second,second | depart,arrive | k,l |
| k,d | second,first,first | depart,turn left,arrive | k,b,d |
| k,j | second,second,second | depart,continue uturn,arrive | k,b,j |
| k,d | second,first,first | depart,turn left,arrive | k,g,d |
| k,j | second,second,second | depart,continue uturn,arrive | k,g,j |
| i,d | second,first,first | depart,turn right,arrive | i,c,d |
| i,j | second,second | depart,arrive | i,j |
| i,h | second,first,first | depart,turn left,arrive | i,f,h |
| i,l | second,second,second | depart,continue uturn,arrive | i,f,l |
| i,h | second,first,first | depart,turn left,arrive | i,c,h |
| i,l | second,second,second | depart,continue uturn,arrive | i,c,l |
Scenario: Segregated Intersection, Cross Belonging to Mixed Streets - Slight Angles (2)
Given the node map
@ -345,28 +345,29 @@ Feature: Collapse
| waypoints | route | turns | locations |
| a,l | first,second,second | depart,turn right,arrive | a,b,l |
| a,d | first,first | depart,arrive | a,d |
| a,j | first,second,second | depart,turn left,arrive | a,c,j |
| a,h | first,first,first | depart,continue uturn,arrive | a,c,h |
| a,j | first,second,second | depart,turn left,arrive | a,b,j |
| a,h | first,first,first | depart,continue uturn,arrive | a,b,h |
| e,j | first,second,second | depart,turn right,arrive | e,f,j |
| e,h | first,first | depart,arrive | e,h |
| e,l | first,second,second | depart,turn left,arrive | e,g,l |
| e,d | first,first,first | depart,continue uturn,arrive | e,g,d |
| e,l | first,second,second | depart,turn left,arrive | e,f,l |
| e,d | first,first,first | depart,continue uturn,arrive | e,f,d |
| k,h | second,first,first | depart,turn right,arrive | k,g,h |
| k,l | second,second | depart,arrive | k,l |
| k,d | second,first,first | depart,turn left,arrive | k,b,d |
| k,j | second,second,second | depart,continue uturn,arrive | k,b,j |
| k,d | second,first,first | depart,turn left,arrive | k,g,d |
| k,j | second,second,second | depart,continue uturn,arrive | k,g,j |
| i,d | second,first,first | depart,turn right,arrive | i,c,d |
| i,j | second,second | depart,arrive | i,j |
| i,h | second,first,first | depart,turn left,arrive | i,f,h |
| i,l | second,second,second | depart,continue uturn,arrive | i,f,l |
| i,h | second,first,first | depart,turn left,arrive | i,c,h |
| i,l | second,second,second | depart,continue uturn,arrive | i,c,l |
Scenario: Entering a segregated road
Given the node map
"""
a f g
| | . '
b-e '
/ /
h
a f | g
| | i '
b-e ' |
/ / j
/ /
c d
"""
@ -376,7 +377,8 @@ Feature: Collapse
| abc | primary | first | yes |
| def | primary | first | yes |
| be | primary | first | no |
| ge | primary | second | no |
| gie | primary | second | no |
| hij | primary | maple | no |
When I route I should get
| waypoints | route | turns | locations |
@ -385,7 +387,7 @@ Feature: Collapse
| a,g | first,second,second | depart,turn left,arrive | a,b,g |
| d,g | first,second,second | depart,turn right,arrive | d,e,g |
| g,f | second,first,first | depart,turn right,arrive | g,e,f |
| g,c | second,first,first | depart,end of road left,arrive | g,b,c |
| g,c | second,first,first | depart,end of road left,arrive | g,e,c |
Scenario: Do not collapse turning roads
Given the node map
@ -603,7 +605,7 @@ Feature: Collapse
When I route I should get
| waypoints | route | turns | locations |
| i,h | in,road,road | depart,turn left,arrive | i,f,h |
| i,h | in,road,road | depart,turn slight left,arrive | i,c,h |
| a,d | road,road | depart,arrive | a,d |
| a,j | road,out,out | depart,turn slight right,arrive | a,b,j |

View File

@ -13,19 +13,23 @@ Feature: Divided road entry
d-------e-----f
|
|
g
i---g---j
|
|
h
"""
And the ways
| nodes | name | highway | oneway |
| abc | main st | residential | -1 |
| def | main st | residential | yes |
| be | main st | residential | |
| eg | side st | residential | |
| nodes | name | highway | oneway |
| abc | main st | residential | -1 |
| def | main st | residential | yes |
| be | main st | residential | |
| egh | side st | residential | |
| igj | maple st | residential | |
When I route I should get
| waypoints | route | turns |
| g,a | side st,main st,main st| depart,end of road left,arrive |
| h,a | side st,main st,main st| depart,end of road left,arrive |
# Similar to previous one, but the joining way is tagged with the side-street name
@ -37,18 +41,22 @@ Feature: Divided road entry
d-------e-----f
|
|
g
i---g---j
|
|
h
"""
And the ways
| nodes | name | highway | oneway |
| abc | main st | residential | -1 |
| def | main st | residential | yes |
| beg | side st | residential | |
| nodes | name | highway | oneway |
| abc | main st | residential | -1 |
| def | main st | residential | yes |
| begh | side st | residential | |
| igj | maple st | residential | |
When I route I should get
| waypoints | route | turns |
| g,a | side st,main st,main st| depart,end of road left,arrive |
| h,a | side st,main st,main st| depart,end of road left,arrive |
# Center join named after crossroad
@ -100,3 +108,32 @@ Feature: Divided road entry
When I route I should get
| waypoints | route | turns |
| g,a | side st,main st,main st| depart,turn left,arrive |
# Verify end of road left turn across divided roads
Scenario: Join on a divided road, named after the side street
Given the node map
"""
a-----h--b-----c
| |
d-----i--e-----f
| |
| |
m---j--g---n
| |
| |
k l
"""
And the ways
| nodes | name | highway | oneway |
| ahbc | main st | residential | -1 |
| dief | main st | residential | yes |
| begl | side st | residential | -1 |
| hijk | side st | residential | yes |
| mjgn | maple st| residential | no |
When I route I should get
| waypoints | route | turns |
| l,a | side st,main st,main st| depart,end of road left,arrive |

View File

@ -1072,7 +1072,7 @@ Feature: Simple Turns
When I route I should get
| from | to | route | turns |
| g | c | woll,brei,brei | depart,turn slight right,arrive |
| g | f | woll,scho,scho | depart,continue sharp left,arrive |
| g | f | woll,scho,scho | depart,turn sharp left,arrive |
| a | c | scho,brei | depart,arrive |
| d | f | brei,scho | depart,arrive |

View File

@ -301,7 +301,7 @@ Feature: Turn Lane Guidance
| e,l | road,cross,cross | depart,turn right,arrive | ,none:false straight:false straight;right:true, |
| i,h | cross,road,road | depart,turn right,arrive | ,, |
| i,j | cross,cross | depart,arrive | ;;left:false straight:true, |
| i,l | cross,cross,cross | depart,continue uturn,arrive | ;,left:true straight:false;left:true straight:false;left:false straight:true, |
| i,l | cross,cross,cross | depart,continue uturn,arrive | ,left:true straight:false;left:true straight:false;left:true straight:false;left:false straight:true, |
@partition-lanes
Scenario: Turn Lanes at Segregated Road
@ -937,48 +937,52 @@ Feature: Turn Lane Guidance
Scenario: Partitioned turn, Slight Curve - maxspeed
Given the node map
"""
f e
| |
| |
| c
a - b ' |
g d
f e
| |
i | |
| | c
h - a - b ' |
j g d
"""
And the ways
| nodes | name | highway | oneway | turn:lanes:forward | maxspeed |
| ha | road | primary | yes | | 1 |
| ab | road | primary | yes | left\|right | 1 |
| bc | cross | primary | yes | | 1 |
| fbg | cross | primary | yes | | 1 |
| dce | cross | primary | yes | | 1 |
| iaj | kross | primary | no | | 1 |
When I route I should get
| waypoints | route | turns | lanes | locations |
| a,g | road,cross,cross | depart,turn right,arrive | ,left:false right:true, | a,b,g |
| a,e | road,cross,cross | depart,end of road left,arrive | ;left:true right:false,left:true right:false, | a,c,e |
| h,g | road,cross,cross | depart,turn right,arrive | ;,left:false right:true, | h,b,g |
| h,e | road,cross,cross | depart,end of road left,arrive | ;,left:true right:false;left:true right:false, | h,b,e |
Scenario: Partitioned turn, Slight Curve
Given the node map
"""
f e
| |
| |
| c
a - b ' |
g d
f e
| |
i | |
| | c
h - a - b ' |
j g d
"""
And the ways
| nodes | name | highway | oneway | turn:lanes:forward |
| ha | road | primary | yes | |
| ab | road | primary | yes | left\|right |
| bc | cross | primary | yes | |
| fbg | cross | primary | yes | |
| dce | cross | primary | yes | |
| iaj | kross | primary | no | |
When I route I should get
| waypoints | route | turns | lanes | locations |
| a,g | road,cross,cross | depart,turn right,arrive | ,left:false right:true, | a,b,g |
| a,e | road,cross,cross | depart,end of road left,arrive | ;left:true right:false,left:true right:false, | a,c,e |
| waypoints | route | turns | lanes | locations |
| h,g | road,cross,cross | depart,turn right,arrive | ;,left:false right:true, | h,b,g |
| h,e | road,cross,cross | depart,end of road left,arrive | ;,left:true right:false;left:true right:false, | h,b,e |
Scenario: Lane Parsing Issue #2694
Given the node map
@ -1244,4 +1248,4 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes | locations |
| a,f | road1,road1,road1 | depart,continue uturn,arrive | ;left:false straight:true straight;right:false,left:true straight:false straight;right:false;;, | a,d,f |
| a,f | road1,road1,road1 | depart,continue uturn,arrive | ,;left:true straight:false straight;right:false;;, | a,c,f |

View File

@ -148,6 +148,9 @@ class RouteAPI : public BaseAPI
// processing is performed
guidance::applyOverrides(BaseAPI::facade, steps, leg_geometry);
// Collapse segregated steps before others
steps = guidance::collapseSegregatedTurnInstructions(std::move(steps));
/* Perform step-based post-processing.
*
* Using post-processing on basis of route-steps for a single leg at a time

View File

@ -13,13 +13,19 @@ namespace engine
namespace guidance
{
// Multiple possible reasons can result in unnecessary/confusing instructions
// Collapsing such turns into a single turn instruction, we give a clearer
// set of instructions that is not cluttered by unnecessary turns/name changes.
OSRM_ATTR_WARN_UNUSED
std::vector<RouteStep> collapseTurnInstructions(std::vector<RouteStep> steps);
// Multiple possible reasons can result in unnecessary/confusing instructions
// A prime example would be a segregated intersection. Turning around at this
// intersection would result in two instructions to turn left.
// Collapsing such turns into a single turn instruction, we give a clearer
// set of instructionst that is not cluttered by unnecessary turns/name changes.
// set of instructions that is not cluttered by unnecessary turns/name changes.
OSRM_ATTR_WARN_UNUSED
std::vector<RouteStep> collapseTurnInstructions(std::vector<RouteStep> steps);
std::vector<RouteStep> collapseSegregatedTurnInstructions(std::vector<RouteStep> steps);
// A combined turn is a set of two instructions that actually form a single turn, as far as we
// perceive it. A u-turn consisting of two left turns is one such example. But there are also lots
@ -93,6 +99,22 @@ struct StaggeredTurnStrategy : CombineStrategy
const RouteStep &step_prior_to_intersection;
};
// Handling of consecutive segregated steps
struct CombineSegregatedStepsStrategy : CombineStrategy
{
void operator()(RouteStep &step_at_turn_location, const RouteStep &transfer_from_step) const;
};
// Handling of segregated intersections
struct SegregatedTurnStrategy : CombineStrategy
{
SegregatedTurnStrategy(const RouteStep &step_prior_to_intersection);
void operator()(RouteStep &step_at_turn_location, const RouteStep &transfer_from_step) const;
const RouteStep &step_prior_to_intersection;
};
// Signage Strategies
// Transfer the signage from the next step onto this step

View File

@ -23,6 +23,7 @@ const constexpr std::size_t MIN_END_OF_ROAD_INTERSECTIONS = std::size_t{2};
const constexpr double MAX_COLLAPSE_DISTANCE = 30.0;
// a bit larger than 100 to avoid oscillation in tests
const constexpr double NAME_SEGMENT_CUTOFF_LENGTH = 105.0;
const double constexpr STRAIGHT_ANGLE = 180.;
// check if a step is completely without turn type
inline bool hasTurnType(const RouteStep &step)
@ -104,6 +105,12 @@ inline void setInstructionType(RouteStep &step, const osrm::guidance::TurnType::
step.maneuver.instruction.type = type;
}
// alias for readability
inline void setModifier(RouteStep &step, const osrm::guidance::DirectionModifier::Enum modifier)
{
step.maneuver.instruction.direction_modifier = modifier;
}
// alias for readability
inline bool haveSameMode(const RouteStep &lhs, const RouteStep &rhs)
{
@ -215,6 +222,86 @@ inline double totalTurnAngle(const RouteStep &entry_step, const RouteStep &exit_
return total_angle;
}
// check bearings for u-turns.
// since bearings are wrapped around at 0 (we only support 0,360), we need to do some minor math to
// check if bearings `a` and `b` go in opposite directions. In general we accept some minor
// deviations for u-turns.
inline bool bearingsAreReversed(const double bearing_in, const double bearing_out)
{
// Nearly perfectly reversed angles have a difference close to 180 degrees (straight)
const double left_turn_angle = [&]() {
if (0 <= bearing_out && bearing_out <= bearing_in)
return bearing_in - bearing_out;
return bearing_in + 360 - bearing_out;
}();
return util::angularDeviation(left_turn_angle, 180) <= 35;
}
// Returns true if the specified step has only one intersection
inline bool hasSingleIntersection(const RouteStep &step)
{
return (step.intersections.size() == 1);
}
// Returns true if the specified angle is a wider straight turn
inline bool isWiderStraight(const double angle) { return (angle >= 125 && angle <= 235); }
// Returns the straightest intersecting edge turn for the specified step
inline double getStraightestIntersectingEdgeTurn(const RouteStep &step)
{
const auto &intersection = step.intersections.front();
const double bearing_in = util::bearing::reverse(intersection.bearings[intersection.in]);
double staightest_turn = 360.;
double staightest_delta = 360.;
for (std::size_t i = 0; i < intersection.bearings.size(); ++i)
{
// Skip the in, out, and non-traversable edges
if ((i == intersection.in) || (i == intersection.out) || !intersection.entry.at(i))
continue;
double intersecting_turn =
util::bearing::angleBetween(bearing_in, intersection.bearings.at(i));
double straight_delta = util::angularDeviation(intersecting_turn, STRAIGHT_ANGLE);
if (straight_delta < staightest_delta)
{
staightest_delta = straight_delta;
staightest_turn = intersecting_turn;
}
}
return staightest_turn;
}
// Returns true if the specified step has the straightest turn as compared to
// the intersecting edges
inline bool hasStraightestTurn(const RouteStep &step)
{
const auto &intersection = step.intersections.front();
const double path_turn =
util::bearing::angleBetween(util::bearing::reverse(intersection.bearings[intersection.in]),
intersection.bearings[intersection.out]);
// Path turn must be a wider straight
if (isWiderStraight(path_turn))
{
const double straightest_intersecting_turn = getStraightestIntersectingEdgeTurn(step);
const double path_straight_delta = util::angularDeviation(path_turn, STRAIGHT_ANGLE);
const double intersecting_straight_delta =
util::angularDeviation(straightest_intersecting_turn, STRAIGHT_ANGLE);
const double path_intersecting_delta =
util::angularDeviation(path_turn, straightest_intersecting_turn);
// Add some fuzz - the delta between the path and intersecting turn must be greater
// than 10 in order to consider using the intersecting turn as the straightest
return ((path_intersecting_delta > 10.)
? (path_straight_delta <= intersecting_straight_delta)
: true);
}
return false;
}
} /* namespace guidance */
} /* namespace engine */
} /* namespace osrm */

View File

@ -17,21 +17,6 @@ using namespace osrm::guidance;
namespace
{
// check bearings for u-turns.
// since bearings are wrapped around at 0 (we only support 0,360), we need to do some minor math to
// check if bearings `a` and `b` go in opposite directions. In general we accept some minor
// deviations for u-turns.
bool bearingsAreReversed(const double bearing_in, const double bearing_out)
{
// Nearly perfectly reversed angles have a difference close to 180 degrees (straight)
const double left_turn_angle = [&]() {
if (0 <= bearing_out && bearing_out <= bearing_in)
return bearing_in - bearing_out;
return bearing_in + 360 - bearing_out;
}();
return util::angularDeviation(left_turn_angle, 180) <= 35;
}
// to collapse steps, we focus on short segments that don't interact with other roads. To collapse
// two instructions into one, we need to look at to instrutions immediately after each other.
bool noIntermediaryIntersections(const RouteStep &step)

View File

@ -221,12 +221,16 @@ void AdjustToCombinedTurnStrategy::operator()(RouteStep &step_at_turn_location,
if (hasTurnType(step_at_turn_location, TurnType::Suppressed))
{
if (new_modifier == DirectionModifier::Straight)
{
setInstructionType(step_at_turn_location, TurnType::NewName);
}
else
{
step_at_turn_location.maneuver.instruction.type =
haveSameName(step_prior_to_intersection, transfer_from_step)
? TurnType::Continue
: TurnType::Turn;
}
}
else if (hasTurnType(step_at_turn_location, TurnType::NewName) &&
hasTurnType(transfer_from_step, TurnType::Suppressed) &&
@ -285,6 +289,110 @@ void StaggeredTurnStrategy::operator()(RouteStep &step_at_turn_location,
: TurnType::NewName;
}
void CombineSegregatedStepsStrategy::operator()(RouteStep &step_at_turn_location,
const RouteStep &transfer_from_step) const
{
// Handle end of road
if (hasTurnType(step_at_turn_location, TurnType::EndOfRoad) ||
hasTurnType(transfer_from_step, TurnType::EndOfRoad))
{
setInstructionType(step_at_turn_location, TurnType::EndOfRoad);
}
}
SegregatedTurnStrategy::SegregatedTurnStrategy(const RouteStep &step_prior_to_intersection)
: step_prior_to_intersection(step_prior_to_intersection)
{
}
void SegregatedTurnStrategy::operator()(RouteStep &step_at_turn_location,
const RouteStep &transfer_from_step) const
{
// Used to control updating of the modifier based on turn direction
bool update_modifier_for_turn_direction = true;
const auto calculate_turn_angle = [](const RouteStep &entry_step, const RouteStep &exit_step) {
return util::bearing::angleBetween(entry_step.maneuver.bearing_before,
exit_step.maneuver.bearing_after);
};
// Calculate turn angle and direction for segregated
const auto turn_angle = calculate_turn_angle(step_at_turn_location, transfer_from_step);
const auto turn_direction = getTurnDirection(turn_angle);
const auto is_straight_step = [](const RouteStep &step) {
return ((hasTurnType(step, TurnType::NewName) || hasTurnType(step, TurnType::Continue) ||
hasTurnType(step, TurnType::Suppressed) || hasTurnType(step, TurnType::Turn)) &&
(hasModifier(step, DirectionModifier::Straight) ||
hasModifier(step, DirectionModifier::SlightLeft) ||
hasModifier(step, DirectionModifier::SlightRight)));
};
const auto is_turn_step = [](const RouteStep &step) {
return (hasTurnType(step, TurnType::Turn) || hasTurnType(step, TurnType::Continue) ||
hasTurnType(step, TurnType::NewName) || hasTurnType(step, TurnType::Suppressed));
};
// Process end of road step
if (hasTurnType(step_at_turn_location, TurnType::EndOfRoad) ||
hasTurnType(transfer_from_step, TurnType::EndOfRoad))
{
// Keep end of road
setInstructionType(step_at_turn_location, TurnType::EndOfRoad);
}
// Process fork step at turn
else if (hasTurnType(step_at_turn_location, TurnType::Fork))
{
// Do not update modifier based on turn direction
update_modifier_for_turn_direction = false;
}
// Process straight step
else if ((turn_direction == guidance::DirectionModifier::Straight) &&
is_straight_step(transfer_from_step))
{
// Determine if continue or new name
setInstructionType(step_at_turn_location,
(haveSameName(step_prior_to_intersection, transfer_from_step)
? TurnType::Suppressed
: TurnType::NewName));
}
// Process wider straight step
else if (isWiderStraight(turn_angle) && hasSingleIntersection(step_at_turn_location) &&
hasStraightestTurn(step_at_turn_location) && hasStraightestTurn(transfer_from_step))
{
// Determine if continue or new name
setInstructionType(step_at_turn_location,
(haveSameName(step_prior_to_intersection, transfer_from_step)
? TurnType::Suppressed
: TurnType::NewName));
// Set modifier to straight
setModifier(step_at_turn_location, osrm::guidance::DirectionModifier::Straight);
// Do not update modifier based on turn direction
update_modifier_for_turn_direction = false;
}
// Process turn step
else if ((turn_direction != guidance::DirectionModifier::Straight) &&
is_turn_step(transfer_from_step))
{
// Mark as turn
setInstructionType(step_at_turn_location, TurnType::Turn);
}
// Process the others not covered above by using the transfer step turn type
else
{
// Set type from transfer step
setInstructionType(step_at_turn_location, transfer_from_step.maneuver.instruction.type);
}
// Update modifier based on turn direction, if needed
if (update_modifier_for_turn_direction)
{
setModifier(step_at_turn_location, turn_direction);
}
}
SetFixedInstructionStrategy::SetFixedInstructionStrategy(const TurnInstruction instruction)
: instruction(instruction)
{
@ -478,6 +586,85 @@ RouteSteps collapseTurnInstructions(RouteSteps steps)
return steps;
}
// OTHER IMPLEMENTATIONS
OSRM_ATTR_WARN_UNUSED
RouteSteps collapseSegregatedTurnInstructions(RouteSteps steps)
{
// make sure we can safely iterate over all steps (has depart/arrive with TurnType::NoTurn)
BOOST_ASSERT(!hasTurnType(steps.front()) && !hasTurnType(steps.back()));
BOOST_ASSERT(hasWaypointType(steps.front()) && hasWaypointType(steps.back()));
if (steps.size() <= 2)
return steps;
auto curr_step = steps.begin() + 1;
auto next_step = curr_step + 1;
const auto last_step = steps.end() - 1;
// Loop over steps to collapse the segregated intersections; ignore first and last step
while (next_step != last_step)
{
const auto prev_step = findPreviousTurn(curr_step);
// if current step and next step are both segregated then combine the steps with no turn
// adjustment
if (curr_step->is_segregated && next_step->is_segregated)
{
// Combine segregated steps
combineRouteSteps(*curr_step,
*next_step,
CombineSegregatedStepsStrategy(),
TransferSignageStrategy(),
TransferLanesStrategy());
++next_step;
}
// else if the current step is segregated and the next step is not then combine with turn
// adjustment
else if (curr_step->is_segregated && !next_step->is_segregated)
{
// Determine if u-turn
if (bearingsAreReversed(
util::bearing::reverse(curr_step->intersections.front()
.bearings[curr_step->intersections.front().in]),
next_step->intersections.front()
.bearings[next_step->intersections.front().out]))
{
// Collapse segregated u-turn
combineRouteSteps(
*curr_step,
*next_step,
SetFixedInstructionStrategy({TurnType::Continue, DirectionModifier::UTurn}),
TransferSignageStrategy(),
NoModificationStrategy());
}
else
{
// Collapse segregated turn
combineRouteSteps(*curr_step,
*next_step,
SegregatedTurnStrategy(*prev_step),
TransferSignageStrategy(),
NoModificationStrategy());
}
// Segregated step has been removed
curr_step->is_segregated = false;
++next_step;
}
// else next step
else
{
curr_step = next_step;
++next_step;
}
}
// Clean up steps
steps = removeNoTurnInstructions(std::move(steps));
return steps;
}
} // namespace guidance
} // namespace engine
} // namespace osrm