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:
parent
0d9f18fe1f
commit
8a63ad9b4b
@ -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)
|
||||
|
@ -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 |
|
||||
|
||||
|
@ -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 |
|
||||
|
||||
|
@ -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 |
|
||||
|
||||
|
||||
|
@ -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 |
|
||||
|
||||
|
@ -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 |
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user