Implement Turn Lane Api

This commit is contained in:
Moritz Kobitzsch 2016-06-15 14:38:24 +02:00
parent ec0a1a4ab1
commit 5d91b759d1
59 changed files with 1274 additions and 439 deletions

View File

@ -2,7 +2,7 @@
Language: Cpp
# BasedOnStyle: LLVM
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignAfterOpenBracket: true
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlinesLeft: false

1
.gitignore vendored
View File

@ -43,7 +43,6 @@ Thumbs.db
/example/build/
/test/data/monaco*
/cmake/postinst
.bundle/
# Eclipse related files #
#########################

View File

@ -1,7 +1,7 @@
# 5.3.0
- API
- Introduces new `TurnType` in the form of `use lane`. The type indicates that you have to stick to a lane without turning
- Introduces lanes to the route response, indicating which lanes are to be used on a turn
- Introduces lanes to the route response. The lane data contains both the markings at the intersection and a flag indicating their involvement in the turn
- Infrastructure
- BREAKING: The new turn type changes the turn-type order. This breaks the **data format**.

View File

@ -437,12 +437,17 @@ step.
| geojson | [GeoJSON `LineString`](http://geojson.org/geojson-spec.html#linestring) or [GeoJSON `Point`](http://geojson.org/geojson-spec.html#point) if it is only one coordinate (not wrapped by a GeoJSON feature)|
- `name`: The name of the way along which travel proceeds.
- `lanes`: the available turn lanes at the turn
- `marked`: markings on the road, following the OSM scheme (e.g. left, slight_right, or through)
- `take`: a boolean flag indicating whether the lane is a possible choice in the maneuver
- `pronunciation`: The pronunciation hint of the way name. Will be `undefined` if there is no pronunciation hit.
- `destinations`: The destinations of the way. Will be `undefined` if there are no destinations.
- `mode`: A string signifying the mode of transportation.
- `maneuver`: A `StepManeuver` object representing the maneuver.
- `intersections`: A list of `Intersections` that are passed along the segment, the very first belonging to the StepManeuver
Currently, the supported lane tags are: `sharp_left, left, slight_left, sharp_right, right, slight_right, through, reverse, none`.
#### Example
```
@ -450,17 +455,24 @@ step.
"distance":152.3,
"duration":15.6,
"name":"Lortzingstraße",
"lanes":{
{"marked":"left",
"take":"false"},
{"marked":"right",
"take":"true"}
},
"maneuver":{
"type":"depart",
"modifier":"left"
"type":"turn",
"modifier":"right"
},
"geometry":"{lu_IypwpAVrAvAdI",
"mode":"driving",
"intersections":[
{"location":[13.39677,52.54366],
"in":2,
"out":1,
"bearings":[66,246],
"entry":["true","true"]},
"bearings":[10,184,270],
"entry":[false,"true","true"]},
{"location":[13.394718,52.543096],
"in":0,
"out":2,

View File

@ -26,8 +26,8 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes | # |
| a,d | ab,bc,cd,cd | depart,turn right,turn left,arrive | ,1 2,1 2, | 2 hops |
| a,e | ab,bc,cd,de,de | depart,turn right,turn left,turn right,arrive | ,1,1,0, | 3 hops |
| a,d | ab,bc,cd,cd | depart,turn right,turn left,arrive | ,through:false right:true right:true right:false,left:true left:true through:false, | 2 hops |
| a,e | ab,bc,cd,de,de | depart,turn right,turn left,turn right,arrive | ,through:false right:false right:true right:false,left:false left:true through:false,through:false right:true, | 3 hops |
@anticipate
Scenario: Anticipate Lane Change for quick same direction turns, staying on the same street
@ -49,8 +49,8 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes |
| a,e | MySt,MySt,MySt,MySt | depart,continue right,end of road right,arrive | ,0,0, |
| e,a | MySt,MySt,MySt,MySt | depart,continue left,end of road left,arrive | ,2,1, |
| a,e | MySt,MySt,MySt,MySt | depart,continue right,end of road right,arrive | ,through:false right:false right:true,left:false right:true, |
| e,a | MySt,MySt,MySt,MySt | depart,continue left,end of road left,arrive | ,left:true left:false through:false,left:true right:false, |
@anticipate
Scenario: Anticipate Lane Change for quick same direction turns, changing between streets
@ -72,8 +72,8 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes |
| a,e | AXSt,BDSt,EYSt,EYSt | depart,turn right,end of road right,arrive | ,0,0, |
| e,a | EYSt,BDSt,AXSt,AXSt | depart,turn left,end of road left,arrive | ,2,1, |
| a,e | AXSt,BDSt,EYSt,EYSt | depart,turn right,end of road right,arrive | ,through:false right:false right:true,left:false right:true, |
| e,a | EYSt,BDSt,AXSt,AXSt | depart,turn left,end of road left,arrive | ,left:true left:false through:false,left:true right:false, |
@anticipate
@ -93,7 +93,7 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes |
| a,d | On,Hwy,Off,Off | depart,merge slight right,off ramp right,arrive | ,0,0, |
| a,d | On,Hwy,Off,Off | depart,merge slight right,off ramp right,arrive | ,slight_left:false slight_left:true,through:false slight_right:true, |
@anticipate
@ -115,8 +115,8 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes |
| a,i | abx,bcd,di,di | depart,off ramp right,fork slight left,arrive | ,0 1,1 2, |
| a,j | abx,bcd,dj,dj | depart,off ramp right,fork slight right,arrive | ,0 1,0 1, |
| a,i | abx,bcd,di,di | depart,off ramp right,fork slight left,arrive | ,none:false none:false none:false slight_right:true slight_right:true,slight_left:true slight_left;slight_right:true slight_right:false, |
| a,j | abx,bcd,dj,dj | depart,off ramp right,fork slight right,arrive | ,none:false none:false none:false slight_right:true slight_right:true,slight_left:false slight_left;slight_right:true slight_right:true, |
@anticipate
@ -136,8 +136,8 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes |
| a,i | ab,xbcj,ci,ci | depart,merge slight left,turn slight right,arrive | ,,0, |
| a,j | ab,xbcj,xbcj,xbcj | depart,merge slight left,use lane straight,arrive | ,,1, |
| a,i | ab,xbcj,ci,ci | depart,merge slight left,turn slight right,arrive | ,,none:false slight_right:true, |
| a,j | ab,xbcj,xbcj,xbcj | depart,merge slight left,use lane straight,arrive | ,,none:true slight_right:false, |
@anticipate
@ -161,8 +161,7 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes |
| a,e | abx,bcy,cdz,de,de | depart,turn right,turn left,turn right,arrive | ,1,1,0, |
| a,e | abx,bcy,cdz,de,de | depart,turn right,turn left,turn right,arrive | ,through:false right:false right:true right:false,left:false left:true through:false,through:false right:true, |
@anticipate
Scenario: Lane anticipation for fan-out
@ -185,8 +184,7 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes |
| a,e | abx,bcy,cdz,de,de | depart,turn right,turn left,turn right,arrive | ,0,1 2,0 1 2, |
| a,e | abx,bcy,cdz,de,de | depart,turn right,turn left,turn right,arrive | ,through:false right:true,left:true left:true through:false,through:false right:true right:true right:true, |
@anticipate
Scenario: Lane anticipation for fan-in followed by fan-out
@ -209,8 +207,7 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes |
| a,e | abx,bcy,cdz,de,de | depart,turn right,turn left,turn right,arrive | ,1 2,1 2,0 1 2, |
| a,e | abx,bcy,cdz,de,de | depart,turn right,turn left,turn right,arrive | ,through:false right:true right:true right:false,left:true left:true through:false,through:false right:true right:true right:true, |
@anticipate
Scenario: Lane anticipation for fan-out followed by fan-in
@ -233,8 +230,7 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes |
| a,e | abx,bcy,cdz,de,de | depart,turn right,turn left,turn right,arrive | ,0,1,0, |
| a,e | abx,bcy,cdz,de,de | depart,turn right,turn left,turn right,arrive | ,through:false right:true,left:false left:true through:false,through:false right:true, |
@anticipate
Scenario: Lane anticipation for multiple hops with same number of lanes
@ -261,9 +257,9 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes |
| a,f | abx,bcy,cdz,dew,ef,ef | depart,turn right,turn left,turn right,turn left,arrive | ,1,1,1,1, |
| a,f | abx,bcy,cdz,dew,ef,ef | depart,turn right,turn left,turn right,turn left,arrive | ,through:false right:false right:true right:false,left:false left:true through:false,through:false right:true right:false,left:true through:false, |
@anticipate
@anticipate @bug @todo
Scenario: Tripple Right keeping Left
Given the node map
| a | | | | b | | i |
@ -285,10 +281,10 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes |
| a,f | start,first,second,third,fourth,fourth | depart,turn right,turn right,turn right,end of road left,arrive | ,2,2,2,2, |
| a,g | start,first,second,third,fourth,fourth | depart,turn right,turn right,turn right,end of road right,arrive | ,0 1,0 1,0 1,0 1, |
| a,f | start,first,second,third,fourth,fourth | depart,turn right,turn right,turn right,end of road left,arrive | ,none:false none:true right:false right:false,none:false none:true right:false right:false,none:false none:true right:false right:false,left:true right:false right:false, |
| a,g | start,first,second,third,fourth,fourth | depart,turn right,turn right,turn right,end of road right,arrive | ,none:false none:false right:true right:true,none:false none:false right:true right:true,none:false none:false right:true right:true,left:false right:true right:true, |
@anticipate
@anticipate @bug @todo
Scenario: Tripple Left keeping Right
Given the node map
| i | | b | | | | a |
@ -310,5 +306,5 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes |
| a,f | start,first,second,third,fourth,fourth | depart,turn left,turn left,turn left,end of road right,arrive | ,2,2,2,2, |
| a,g | start,first,second,third,fourth,fourth | depart,turn left,turn left,turn left,end of road left,arrive | ,0 1,0 1,0 1,0 1, |
| a,f | start,first,second,third,fourth,fourth | depart,turn left,turn left,turn left,end of road right,arrive | ,left:false left:false none:true none:false,left:false left:false none:true none:false,left:false left:false none:true none:false,left:false left:false right:true, |
| a,g | start,first,second,third,fourth,fourth | depart,turn left,turn left,turn left,end of road left,arrive | ,left:true left:true none:false none:false,left:true left:true none:false none:false,left:true left:true none:false none:false,left:true left:true right:false, |

View File

@ -21,10 +21,10 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes |
| a,c | in,straight,straight | depart,new name straight,arrive | ,1, |
| a,d | in,right,right | depart,turn right,arrive | ,0, |
| c,a | straight,in,in | depart,new name straight,arrive | ,0 1 2, |
| c,d | straight,right,right | depart,turn left,arrive | ,3, |
| a,c | in,straight,straight | depart,new name straight,arrive | ,through:true right:false, |
| a,d | in,right,right | depart,turn right,arrive | ,through:false right:true, |
| c,a | straight,in,in | depart,new name straight,arrive | ,left:false through:true none:true none:true, |
| c,d | straight,right,right | depart,turn left,arrive | ,left:true through:false none:false none:false, |
Scenario: Basic Turn Lane 4-Way Turn
Given the node map
@ -41,12 +41,12 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes |
| a,c | in,straight,straight | depart,new name straight,arrive | ,1, |
| a,d | in,right,right | depart,turn right,arrive | ,0, |
| a,e | in,left,left | depart,turn left,arrive | ,1, |
| d,a | right,in,in | depart,turn left,arrive | ,1, |
| d,e | right,left,left | depart,new name straight,arrive | ,0, |
| d,c | right,straight,straight | depart,turn right,arrive | ,0, |
| a,c | in,straight,straight | depart,new name straight,arrive | ,none:true right:false, |
| a,d | in,right,right | depart,turn right,arrive | ,none:false right:true, |
| a,e | in,left,left | depart,turn left,arrive | ,none:true right:false, |
| d,a | right,in,in | depart,turn left,arrive | ,left:true none:false, |
| d,e | right,left,left | depart,new name straight,arrive | ,left:false none:true, |
| d,c | right,straight,straight | depart,turn right,arrive | ,left:false none:true, |
Scenario: Basic Turn Lane 4-Way Turn using none
Given the node map
@ -63,9 +63,9 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes |
| a,c | in,straight,straight | depart,new name straight,arrive | ,1, |
| a,d | in,right,right | depart,turn right,arrive | ,0, |
| a,e | in,left,left | depart,turn left,arrive | ,1, |
| a,c | in,straight,straight | depart,new name straight,arrive | ,none:true right:false, |
| a,d | in,right,right | depart,turn right,arrive | ,none:false right:true, |
| a,e | in,left,left | depart,turn left,arrive | ,none:true right:false, |
Scenario: Basic Turn Lane 4-Way With U-Turn Lane
Given the node map
@ -82,10 +82,10 @@ Feature: Turn Lane Guidance
When I route I should get
| from | to | bearings | route | turns | lanes |
| a | c | 180,180 180,180 | in,straight,straight | depart,new name straight,arrive | ,0, |
| a | d | 180,180 180,180 | in,right,right | depart,turn right,arrive | ,0, |
| a | e | 180,180 180,180 | in,left,left | depart,turn left,arrive | ,1, |
| 1 | a | 90,2 270,2 | in,in,in | depart,turn uturn,arrive | ,1, |
| a | c | 180,180 180,180 | in,straight,straight | depart,new name straight,arrive | ,reverse;left:false through;right:true, |
| a | d | 180,180 180,180 | in,right,right | depart,turn right,arrive | ,reverse;left:false through;right:true, |
| a | e | 180,180 180,180 | in,left,left | depart,turn left,arrive | ,reverse;left:true through;right:false, |
| 1 | a | 90,2 270,2 | in,in,in | depart,turn uturn,arrive | ,reverse;left:true through;right:false, |
#this next test requires decision on how to announce lanes for going straight if there is no turn
@ -104,11 +104,11 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes |
| a,d | road,turn,turn | depart,turn right,arrive | ,0, |
| a,c | road,road,road | depart,use lane straight,arrive | ,1, |
| a,d | road,turn,turn | depart,turn right,arrive | ,through:false right:true, |
| a,c | road,road,road | depart,use lane straight,arrive | ,through:true right:false, |
#turn lanes are often drawn at the incoming road, even though the actual turn requires crossing the intersection first
@TODO @WORKAROUND-FIXME
@todo @WORKAROUND-FIXME @bug
Scenario: Turn Lanes at Segregated Road
Given the node map
| | | i | l | | |
@ -134,23 +134,57 @@ Feature: Turn Lane Guidance
| fl | cross | | yes |
When I route I should get
| waypoints | route | turns | lanes | # |
| a,j | road,cross,cross | depart,turn right,arrive | ,0, | |
| a,d | road,road,road | depart,use lane straight,arrive | ,1, | #post-processing reduction |
| a,l | road,cross,cross | depart,turn left,arrive | ,2, | |
| a,h | road,road,road | depart,continue uturn,arrive | ,2, | |
| k,d | cross,road,road | depart,turn right,arrive | ,0, | |
| k,l | cross,cross,cross | depart,use lane straight,arrive | ,0, | |
| k,h | cross,road,road | depart,turn left,arrive | ,1, | |
| k,j | cross,cross,cross | depart,continue uturn,arrive | ,1, | |
| e,l | road,cross,cross | depart,turn right,arrive | ,0, | |
| e,h | road,road | depart,arrive | , | |
| e,j | road,cross,cross | depart,turn left,arrive | ,2, | |
| e,d | road,road,road | depart,continue uturn,arrive | ,2, | |
| i,h | cross,road,road | depart,turn right,arrive | ,, | |
| i,j | cross,cross,cross | depart,use lane straight,arrive | ,0, | |
| i,d | cross,road,road | depart,turn left,arrive | ,1, | |
| i,l | cross,cross,cross | depart,continue uturn,arrive | ,1, | |
| waypoints | route | turns | lanes |
| a,j | road,cross,cross | depart,turn right,arrive | ,left:false through:false right:true |
| a,d | road,road,road | depart,use lane straight,arrive | ,left:false through:true right:false, |
| a,l | road,cross,cross | depart,turn left,arrive | ,left:true through:false right:false, |
| a,h | road,road,road | depart,continue uturn,arrive | ,left:true through:false right:false, |
| k,d | cross,road,road | depart,turn right,arrive | ,left:false through;right:true, |
| k,l | cross,cross,cross | depart,use lane straight,arrive | ,left:false through;right:true, |
| k,h | cross,road,road | depart,turn left,arrive | ,left:true through;right:false, |
| k,j | cross,cross,cross | depart,continue uturn,arrive | ,left:true through;right:false, |
| e,l | road,cross,cross | depart,turn right,arrive | ,none:false through:false through;right:true, |
| e,h | road,road | depart,arrive | ,none:false through:true through;right:true |
| e,j | road,cross,cross | depart,turn left,arrive | ,none:true through:false through;right:false, |
| e,d | road,road,road | depart,continue uturn,arrive | ,none:true through:false through;right:false, |
| i,h | cross,road,road | depart,turn right,arrive | ,, |
| i,j | cross,cross,cross | depart,use lane straight,arrive | ,left:false through:true, |
| i,d | cross,road,road | depart,turn left,arrive | ,left:true through:false, |
| i,l | cross,cross,cross | depart,continue uturn,arrive | ,left:true through:false, |
#copy of former case to prevent further regression
Scenario: Turn Lanes at Segregated Road
Given the node map
| | | i | l | | |
| | | | | | |
| h | | g | f | | e |
| a | | b | c | | d |
| | | | | | |
| | | j | k | | |
And the ways
| nodes | name | turn:lanes:forward | oneway |
| ab | road | left\|through&right | yes |
| bc | road | left\|through | yes |
| cd | road | | yes |
| ef | road | \|through&through;right | yes |
| fg | road | left;through\|through& | yes |
| gh | road | | yes |
| ig | cross | | yes |
| gb | cross | left\|through | yes |
| bj | cross | | yes |
| kc | cross | left\|through;right | yes |
| cf | cross | left\|through | yes |
| fl | cross | | yes |
When I route I should get
| waypoints | route | turns | lanes |
| a,j | road,cross,cross | depart,turn right,arrive | ,left:false through:false right:true, |
| k,d | cross,road,road | depart,turn right,arrive | ,left:false through;right:true, |
| e,l | road,cross,cross | depart,turn right,arrive | ,none:false through:false through;right:true, |
| i,h | cross,road,road | depart,turn right,arrive | ,, |
| i,j | cross,cross,cross | depart,use lane straight,arrive | ,left:false through:true, |
| i,l | cross,cross,cross | depart,continue uturn,arrive | ,left:true through:false, |
Scenario: Turn Lanes at Segregated Road
Given the node map
@ -171,7 +205,7 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes |
| a,j | road,cross,cross | depart,turn right,arrive | ,0, |
| a,j | road,cross,cross | depart,turn right,arrive | ,left:false through:false right:true, |
#this can happen due to traffic lights / lanes not drawn up to the intersection itself
Scenario: Turn Lanes Given earlier than actual turn
@ -189,8 +223,8 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes |
| a,e | road,turn,turn | depart,turn right,arrive | ,0, |
| a,d | road,road,road | depart,use lane straight,arrive | ,1, |
| a,e | road,turn,turn | depart,turn right,arrive | ,none:false right:true, |
| a,d | road,road,road | depart,use lane straight,arrive | ,none:true right:false, |
Scenario: Turn Lanes Given earlier than actual turn
Given the node map
@ -209,10 +243,10 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes |
| a,k | road,second-turn,second-turn | depart,turn right,arrive | ,0, |
| a,i | road,road,road | depart,use lane straight,arrive | ,1, |
| i,j | road,first-turn,first-turn | depart,turn left,arrive | ,1, |
| i,a | road,road,road | depart,use lane straight,arrive | ,0, |
| a,k | road,second-turn,second-turn | depart,turn right,arrive | ,none:false right:true, |
| a,i | road,road,road | depart,use lane straight,arrive | ,none:true right:false, |
| i,j | road,first-turn,first-turn | depart,turn left,arrive | ,left:true none:false, |
| i,a | road,road,road | depart,use lane straight,arrive | ,left:false none:true, |
Scenario: Passing a one-way street
Given the node map
@ -228,7 +262,7 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes |
| a,f | road,turn,turn | depart,turn left,arrive | ,1, |
| a,f | road,turn,turn | depart,turn left,arrive | ,left:true through:false, |
Scenario: Passing a one-way street, partly pulled back lanes
Given the node map
@ -246,8 +280,8 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes |
| a,f | road,turn,turn | depart,turn left,arrive | ,1, |
| a,g | road,right,right | depart,turn right,arrive | ,0, |
| a,f | road,turn,turn | depart,turn left,arrive | ,left:true through;right:false, |
| a,g | road,right,right | depart,turn right,arrive | ,left:false through;right:true, |
Scenario: Passing a one-way street, partly pulled back lanes, no through
Given the node map
@ -265,9 +299,10 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes |
| a,f | road,turn,turn | depart,turn left,arrive | ,1, |
| a,g | road,right,right | depart,turn right,arrive | ,0, |
| a,f | road,turn,turn | depart,turn left,arrive | ,left:true right:false, |
| a,g | road,right,right | depart,turn right,arrive | ,left:false right:true, |
@todo @bug
Scenario: Narrowing Turn Lanes
Given the node map
| | | | | g | |
@ -286,9 +321,9 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes |
| a,g | road,left,left | depart,turn left,arrive | ,2, |
| a,e | road,through,through | depart,new name straight,arrive | ,1, |
| a,f | road,right,right | depart,turn right,arrive | ,0, |
| a,g | road,left,left | depart,turn left,arrive | ,left:true through:false right:false, |
| a,e | road,through,through | depart,new name straight,arrive | ,left:false through:true right:false, |
| a,f | road,right,right | depart,turn right,arrive | ,left:false through:false right:true, |
Scenario: Turn at a traffic light
Given the node map
@ -308,10 +343,10 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes |
| a,d | road,road,road | depart,use lane straight,arrive | ,1, |
| a,e | road,turn,turn | depart,turn right,arrive | ,0, |
| a,d | road,road,road | depart,use lane straight,arrive | ,through:true right:false, |
| a,e | road,turn,turn | depart,turn right,arrive | ,through:false right:true, |
@bug @todo
Scenario: Theodor Heuss Platz
Given the node map
| | | | i | o | | | l | |
@ -344,8 +379,8 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes |
| i,m | top,top-right,top-right | depart,roundabout-exit-4,arrive | ,0 1 2, |
| i,l | top,top-right-out,top-right-out | depart,roundabout-exit-4,arrive | ,2 3, |
| i,m | top,top-right,top-right | depart,roundabout-exit-4,arrive | ,slight_left:false slight_left;slight_right:true slight_right:true slight_right:true, |
| i,l | top,top-right-out,top-right-out | depart,roundabout-exit-4,arrive | ,slight_left:true slight_left;slight_right:true slight_right:false slight_right:false, |
| i,o | top,top,top | depart,roundabout-exit-5,arrive | ,, |
Scenario: Turn Lanes Breaking up
@ -372,8 +407,8 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes |
| a,g | road,cross,cross | depart,turn left,arrive | ,2 3, |
| a,e | road,road,road | depart,use lane straight,arrive | ,0 1, |
| a,g | road,cross,cross | depart,turn left,arrive | ,left:true left:true through:false through:false, |
| a,e | road,road,road | depart,use lane straight,arrive | ,left:false left:false through:true through:true, |
Scenario: U-Turn Road at Intersection
Given the node map
@ -395,10 +430,10 @@ Feature: Turn Lane Guidance
When I route I should get
| from | to | bearings | route | turns | lanes |
| a | g | 180,180 180,180 | road,cross,cross | depart,turn right,arrive | ,0, |
| a | h | 180,180 180,180 | road,cross,cross | depart,turn left,arrive | ,2, |
| a | i | 180,180 180,180 | road,road,road | depart,use lane straight,arrive | ,1 2, |
| b | a | 90,2 270,2 | road,road,road | depart,continue uturn,arrive | ,2, |
| a | g | 180,180 180,180 | road,cross,cross | depart,turn right,arrive | ,none:false through:false right:true, |
| a | h | 180,180 180,180 | road,cross,cross | depart,turn left,arrive | ,none:true through:false right:false, |
| a | i | 180,180 180,180 | road,road,road | depart,use lane straight,arrive | ,none:true through:true right:false, |
| b | a | 90,2 270,2 | road,road,road | depart,continue uturn,arrive | ,none:true through:false right:false, |
Scenario: Segregated Intersection Merges With Lanes
Given the node map
@ -420,10 +455,11 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes |
| a,f | road,left,left | depart,turn left,arrive | ,2 3 4, |
| a,e | road,road,road | depart,turn uturn,arrive | ,4, |
| a,g | road,straight,straight | depart,new name straight,arrive | ,0 1, |
| a,f | road,left,left | depart,turn left,arrive | ,left:true left:true left:true through:false through:false, |
| a,e | road,road,road | depart,turn uturn,arrive | ,left:true left:false left:false through:false through:false, |
| a,g | road,straight,straight | depart,new name straight,arrive | ,left:false left:false left:false through:true through:true, |
@bug @todo
Scenario: Passing Through a Roundabout
Given the node map
| | | h | | g | | |
@ -467,8 +503,8 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes |
| a,d | road,road,road | depart,use lane straight,arrive | ,1 2 3, |
| a,e | road,cross,cross | depart,turn slight right,arrive | ,0 1, |
| a,d | road,road,road | depart,use lane straight,arrive | ,through:true through:true through;slight_right:true slight_right:false, |
| a,e | road,cross,cross | depart,turn slight right,arrive | ,through:false through:false through;slight_right:true slight_right:true, |
Scenario: Highway Ramp
Given the node map
@ -483,9 +519,10 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes |
| a,d | hwy,hwy,hwy | depart,use lane straight,arrive | ,1 2 3, |
| a,e | hwy,ramp,ramp | depart,off ramp slight right,arrive | ,0 1, |
| a,d | hwy,hwy,hwy | depart,use lane straight,arrive | ,through:true through:true through;slight_right:true slight_right:false, |
| a,e | hwy,ramp,ramp | depart,off ramp slight right,arrive | ,through:false through:false through;slight_right:true slight_right:true, |
@bug @todo
Scenario: Turning Off Ramp
Given the node map
| | a | |
@ -503,8 +540,8 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes |
| a,d | off,road,road | depart,turn_right,arrive | ,0, |
| a,g | off,road,road | depart,turn_left,arrive | ,1, |
| a,d | off,road,road | depart,turn_right,arrive | ,left:false right:true, |
| a,g | off,road,road | depart,turn_left,arrive | ,left:true right:false, |
| a,h | | | |
Scenario: Off Ramp In a Turn
@ -522,8 +559,8 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes |
| a,c | hwy,hwy,hwy | depart,use lane slight left,arrive | ,1 2, |
| a,d | hwy,ramp,ramp | depart,off ramp slight right,arrive | ,0, |
| a,c | hwy,hwy,hwy | depart,use lane slight left,arrive | ,through:true through:true slight_right:false, |
| a,d | hwy,ramp,ramp | depart,off ramp slight right,arrive | ,through:false through:false slight_right:true, |
Scenario: Reverse Lane in Segregated Road
Given the node map
@ -541,7 +578,7 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes |
| a,h | road,road,road | depart,continue uturn,arrive | ,2, |
| a,h | road,road,road | depart,continue uturn,arrive | ,reverse:true through:false through:false,|
Scenario: Reverse Lane in Segregated Road with none
Given the node map
@ -559,7 +596,7 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes |
| a,h | road,road,road | depart,continue uturn,arrive | ,2, |
| a,h | road,road,road | depart,continue uturn,arrive | ,reverse:true through:false none:false, |
Scenario: Reverse Lane in Segregated Road with none, Service Turn Prior
Given the node map
@ -579,7 +616,7 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes |
| a,h | road,road,road | depart,continue uturn,arrive | ,2, |
| a,h | road,road,road | depart,continue uturn,arrive | ,reverse:true through:false none:false, |
Scenario: Don't collapse everything to u-turn / too wide
Given the node map
@ -597,8 +634,8 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | turns | route | lanes |
| a,d | depart,continue right,end of road right,arrive | road,road,road,road | ,0,, |
| d,a | depart,continue left,end of road left,arrive | road,road,road,road | ,1,, |
| a,d | depart,continue right,end of road right,arrive | road,road,road,road | ,through:false right:true,, |
| d,a | depart,continue left,end of road left,arrive | road,road,road,road | ,left:true through:false,, |
Scenario: Merge Lanes Onto Freeway
Given the node map
@ -612,7 +649,7 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | turns | route | lanes |
| d,c | depart,merge slight left,arrive | ramp,Hwy,Hwy | ,0 1, |
| d,c | depart,merge slight left,arrive | ramp,Hwy,Hwy | ,slight_right:true slight_right:true, |
Scenario: Fork on motorway links - don't fork on through but use lane
Given the node map
@ -629,5 +666,5 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes |
| a,j | on,xbcj,xbcj,xbcj | depart,merge slight left,use lane straight,arrive | ,,1, |
| a,i | on,xbcj,off,off | depart,merge slight left,turn slight right,arrive | ,,0, |
| a,j | on,xbcj,xbcj,xbcj | depart,merge slight left,use lane straight,arrive | ,,none:true slight_right:false, |
| a,i | on,xbcj,off,off | depart,merge slight left,turn slight right,arrive | ,,none:false slight_right:true, |

View File

@ -223,7 +223,7 @@ module.exports = function () {
};
['osrm', 'osrm.ebg', 'osrm.edges', 'osrm.enw', 'osrm.fileIndex', 'osrm.geometry', 'osrm.icd',
'osrm.names', 'osrm.nodes', 'osrm.properties', 'osrm.ramIndex', 'osrm.restrictions'].forEach(file => {
'osrm.names', 'osrm.nodes', 'osrm.properties', 'osrm.ramIndex', 'osrm.restrictions', 'osrm.tld', 'osrm.tls'].forEach(file => {
q.defer(rename, file);
});
@ -283,7 +283,7 @@ module.exports = function () {
['osrm', 'osrm.core', 'osrm.datasource_indexes', 'osrm.datasource_names', 'osrm.ebg','osrm.edges',
'osrm.enw', 'osrm.fileIndex', 'osrm.geometry', 'osrm.hsgr', 'osrm.icd','osrm.level', 'osrm.names',
'osrm.nodes', 'osrm.properties', 'osrm.ramIndex', 'osrm.restrictions'].forEach((file) => {
'osrm.nodes', 'osrm.properties', 'osrm.ramIndex', 'osrm.restrictions', 'osrm.tld', 'osrm.tls'].forEach((file) => {
q.defer(rename, file);
});

View File

@ -169,7 +169,14 @@ module.exports = function () {
};
this.lanesList = (instructions) => {
return this.extractInstructionList(instructions, instruction => ('lanes' in instruction.maneuver ? instruction.maneuver.lanes.join(' ') : ''));
return this.extractInstructionList(instructions, instruction => {
if( 'lanes' in instruction.maneuver )
{
return instruction.maneuver.lanes.map( p => { return p.marked + ':' + p.take; } ).join(' ');
} else
{
return '';
}});
};
this.turnList = (instructions) => {

View File

@ -33,7 +33,8 @@ module.exports = function () {
var afterRequest = (err, res, body) => {
if (err) return cb(err);
if (body && body.length) {
let destinations, pronunciations, instructions, bearings, turns, modes, times, distances, summary, intersections, lanes;
let destinations, pronunciations, instructions, bearings, turns, modes, times,
distances, summary, intersections, lanes;
let json = JSON.parse(body);
@ -103,12 +104,10 @@ module.exports = function () {
got.time = instructions ? util.format('%ds', time) : '';
}
if (headers.has('lanes')) {
got.lanes = (lanes || '').trim();
}
if (headers.has('speed')) {
if (row.speed !== '' && instructions) {
if (!row.speed.match(/\d+ km\/h/))

View File

@ -12,6 +12,7 @@
#include "engine/guidance/assemble_overview.hpp"
#include "engine/guidance/assemble_route.hpp"
#include "engine/guidance/assemble_steps.hpp"
#include "engine/guidance/lane_processing.hpp"
#include "engine/guidance/post_processing.hpp"
#include "engine/internal_route_result.hpp"

View File

@ -138,6 +138,10 @@ class BaseDataFacade
const int bearing,
const int bearing_range) const = 0;
virtual bool hasLaneData(const EdgeID id) const = 0;
virtual util::guidance::LaneTupelIdPair GetLaneData(const EdgeID id) const = 0;
virtual std::string GetTurnStringForID(const LaneStringID lane_string_id) const = 0;
virtual unsigned GetCheckSum() const = 0;
virtual bool IsCoreNode(const NodeID id) const = 0;

View File

@ -16,6 +16,7 @@
#include "storage/storage_config.hpp"
#include "engine/geospatial_query.hpp"
#include "util/graph_loader.hpp"
#include "util/guidance/turn_lanes.hpp"
#include "util/io.hpp"
#include "util/packed_vector.hpp"
#include "util/range_table.hpp"
@ -78,8 +79,11 @@ class InternalDataFacade final : public BaseDataFacade
util::ShM<NodeID, false>::vector m_via_node_list;
util::ShM<unsigned, false>::vector m_name_ID_list;
util::ShM<extractor::guidance::TurnInstruction, false>::vector m_turn_instruction_list;
util::ShM<LaneDataID, false>::vector m_lane_data_id;
util::ShM<util::guidance::LaneTupelIdPair, false>::vector m_lane_tupel_id_pairs;
util::ShM<extractor::TravelMode, false>::vector m_travel_mode_list;
util::ShM<char, false>::vector m_names_char_list;
util::ShM<char, false>::vector m_lanes_char_list;
util::ShM<unsigned, false>::vector m_geometry_indices;
util::ShM<extractor::CompressedEdgeContainer::CompressedEdge, false>::vector m_geometry_list;
util::ShM<bool, false>::vector m_is_core_node;
@ -93,6 +97,7 @@ class InternalDataFacade final : public BaseDataFacade
boost::filesystem::path ram_index_path;
boost::filesystem::path file_index_path;
util::RangeTable<16, false> m_name_table;
util::RangeTable<16, false> m_lane_string_table;
// bearing classes by node based node
util::ShM<BearingClassID, false>::vector m_bearing_class_id_table;
@ -118,6 +123,20 @@ class InternalDataFacade final : public BaseDataFacade
sizeof(m_profile_properties));
}
void LoadLaneTupelIdPairs(const boost::filesystem::path &lane_data_path)
{
boost::filesystem::ifstream in_stream(lane_data_path);
if (!in_stream)
{
throw util::exception("Could not open " + lane_data_path.string() + " for reading.");
}
std::uint64_t size;
in_stream.read(reinterpret_cast<char *>(&size), sizeof(size));
m_lane_tupel_id_pairs.resize(size);
in_stream.read(reinterpret_cast<char *>(&m_lane_tupel_id_pairs[0]),
sizeof(m_lane_tupel_id_pairs) * size);
}
void LoadTimestamp(const boost::filesystem::path &timestamp_path)
{
util::SimpleLogger().Write() << "Loading Timestamp";
@ -173,6 +192,7 @@ class InternalDataFacade final : public BaseDataFacade
m_via_node_list.resize(number_of_edges);
m_name_ID_list.resize(number_of_edges);
m_turn_instruction_list.resize(number_of_edges);
m_lane_data_id.resize(number_of_edges);
m_travel_mode_list.resize(number_of_edges);
m_entry_class_id_list.resize(number_of_edges);
@ -184,6 +204,7 @@ class InternalDataFacade final : public BaseDataFacade
m_via_node_list[i] = current_edge_data.via_node;
m_name_ID_list[i] = current_edge_data.name_id;
m_turn_instruction_list[i] = current_edge_data.turn_instruction;
m_lane_data_id[i] = current_edge_data.lane_data_id;
m_travel_mode_list[i] = current_edge_data.travel_mode;
m_entry_class_id_list[i] = current_edge_data.entry_classid;
}
@ -284,6 +305,20 @@ class InternalDataFacade final : public BaseDataFacade
new InternalGeospatialQuery(*m_static_rtree, m_coordinate_list, *this));
}
void LoadLaneStrings(const boost::filesystem::path &lane_string_file)
{
boost::filesystem::ifstream lane_stream(lane_string_file, std::ios::binary);
lane_stream >> m_lane_string_table;
unsigned number_of_chars = 0;
lane_stream.read((char *)&number_of_chars, sizeof(unsigned));
m_lanes_char_list.resize(number_of_chars + 1); //+1 gives sentinel element
if( number_of_chars )
lane_stream.read((char *)&m_lanes_char_list[0], number_of_chars * sizeof(char));
m_lanes_char_list[number_of_chars] = '\0';
}
void LoadStreetNames(const boost::filesystem::path &names_file)
{
boost::filesystem::ifstream name_stream(names_file, std::ios::binary);
@ -386,11 +421,17 @@ class InternalDataFacade final : public BaseDataFacade
util::SimpleLogger().Write() << "loading street names";
LoadStreetNames(config.names_data_path);
util::SimpleLogger().Write() << "loading lane tags";
LoadLaneStrings(config.turn_lane_string_path);
util::SimpleLogger().Write() << "loading rtree";
LoadRTree();
util::SimpleLogger().Write() << "loading intersection class data";
LoadIntersectionClasses(config.intersection_class_path);
util::SimpleLogger().Write() << "Loading Lane Data Pairs";
LoadLaneTupelIdPairs(config.turn_lane_data_path);
}
// search graph access
@ -741,6 +782,37 @@ class InternalDataFacade final : public BaseDataFacade
{
return m_entry_class_table.at(entry_class_id);
}
bool hasLaneData(const EdgeID id) const override final
{
return m_lane_data_id[id] != INVALID_LANE_DATAID;
}
util::guidance::LaneTupelIdPair GetLaneData(const EdgeID id) const override final
{
BOOST_ASSERT(hasLaneData(id));
return m_lane_tupel_id_pairs[m_lane_data_id[id]];
}
std::string GetTurnStringForID(const LaneStringID lane_string_id) const override final
{
if (INVALID_LANE_STRINGID == lane_string_id)
{
return "";
}
auto range = m_lane_string_table.GetRange(lane_string_id);
std::string result;
result.reserve(range.size());
if (range.begin() != range.end())
{
result.resize(range.back() - range.front() + 1);
std::copy(m_lanes_char_list.begin() + range.front(),
m_lanes_char_list.begin() + range.back() + 1,
result.begin());
}
return result;
}
};
}
}

View File

@ -12,6 +12,7 @@
#include "extractor/profile_properties.hpp"
#include "util/guidance/bearing_class.hpp"
#include "util/guidance/entry_class.hpp"
#include "util/guidance/turn_lanes.hpp"
#include "engine/geospatial_query.hpp"
#include "util/make_unique.hpp"
@ -79,10 +80,14 @@ class SharedDataFacade final : public BaseDataFacade
util::PackedVector<OSMNodeID, true> m_osmnodeid_list;
util::ShM<NodeID, true>::vector m_via_node_list;
util::ShM<unsigned, true>::vector m_name_ID_list;
util::ShM<LaneDataID, true>::vector m_lane_data_id;
util::ShM<extractor::guidance::TurnInstruction, true>::vector m_turn_instruction_list;
util::ShM<extractor::TravelMode, true>::vector m_travel_mode_list;
util::ShM<char, true>::vector m_names_char_list;
util::ShM<char, true>::vector m_turn_string_char_list;
util::ShM<unsigned, true>::vector m_name_begin_indices;
util::ShM<char, true>::vector m_lane_string_char_list;
util::ShM<unsigned, true>::vector m_lane_string_begin_indices;
util::ShM<unsigned, true>::vector m_geometry_indices;
util::ShM<extractor::CompressedEdgeContainer::CompressedEdge, true>::vector m_geometry_list;
util::ShM<bool, true>::vector m_is_core_node;
@ -91,12 +96,14 @@ class SharedDataFacade final : public BaseDataFacade
util::ShM<char, true>::vector m_datasource_name_data;
util::ShM<std::size_t, true>::vector m_datasource_name_offsets;
util::ShM<std::size_t, true>::vector m_datasource_name_lengths;
util::ShM<util::guidance::LaneTupelIdPair, true>::vector m_lane_tupel_id_pairs;
std::unique_ptr<SharedRTree> m_static_rtree;
std::unique_ptr<SharedGeospatialQuery> m_geospatial_query;
boost::filesystem::path file_index_path;
std::shared_ptr<util::RangeTable<16, true>> m_name_table;
std::shared_ptr<util::RangeTable<16, true>> m_turn_string_table;
// bearing classes by node based node
util::ShM<BearingClassID, true>::vector m_bearing_class_id_table;
@ -186,6 +193,19 @@ class SharedDataFacade final : public BaseDataFacade
travel_mode_list_ptr, data_layout->num_entries[storage::SharedDataLayout::TRAVEL_MODE]);
m_travel_mode_list = std::move(travel_mode_list);
auto lane_data_id_ptr = data_layout->GetBlockPtr<LaneDataID>(
shared_memory, storage::SharedDataLayout::LANE_DATA_ID);
util::ShM<LaneDataID, true>::vector lane_data_id(
lane_data_id_ptr, data_layout->num_entries[storage::SharedDataLayout::LANE_DATA_ID]);
m_lane_data_id = std::move(lane_data_id);
auto lane_tupel_id_pair_ptr = data_layout->GetBlockPtr<util::guidance::LaneTupelIdPair>(
shared_memory, storage::SharedDataLayout::TURN_LANE_DATA);
util::ShM<util::guidance::LaneTupelIdPair, true>::vector lane_tupel_id_pair(
lane_tupel_id_pair_ptr,
data_layout->num_entries[storage::SharedDataLayout::TURN_LANE_DATA]);
m_lane_tupel_id_pairs = std::move(lane_tupel_id_pair);
auto turn_instruction_list_ptr =
data_layout->GetBlockPtr<extractor::guidance::TurnInstruction>(
shared_memory, storage::SharedDataLayout::TURN_INSTRUCTION);
@ -238,6 +258,29 @@ class SharedDataFacade final : public BaseDataFacade
m_names_char_list = std::move(names_char_list);
}
void LoadTurnLaneStrings()
{
auto offsets_ptr = data_layout->GetBlockPtr<unsigned>(
shared_memory, storage::SharedDataLayout::TURN_STRING_OFFSETS);
auto blocks_ptr = data_layout->GetBlockPtr<IndexBlock>(
shared_memory, storage::SharedDataLayout::TURN_STRING_BLOCKS);
util::ShM<unsigned, true>::vector turn_string_offsets(
offsets_ptr, data_layout->num_entries[storage::SharedDataLayout::TURN_STRING_OFFSETS]);
util::ShM<IndexBlock, true>::vector turn_string_blocks(
blocks_ptr, data_layout->num_entries[storage::SharedDataLayout::TURN_STRING_BLOCKS]);
auto turn_strings_list_ptr = data_layout->GetBlockPtr<char>(
shared_memory, storage::SharedDataLayout::TURN_STRING_CHAR_LIST);
util::ShM<char, true>::vector turn_strings_char_list(
turn_strings_list_ptr,
data_layout->num_entries[storage::SharedDataLayout::TURN_STRING_CHAR_LIST]);
m_turn_string_table = util::make_unique<util::RangeTable<16, true>>(
turn_string_offsets,
turn_string_blocks,
static_cast<unsigned>(turn_strings_char_list.size()));
m_turn_string_char_list = std::move(turn_strings_char_list);
}
void LoadCoreInformation()
{
if (data_layout->num_entries[storage::SharedDataLayout::CORE_MARKER] <= 0)
@ -416,6 +459,7 @@ class SharedDataFacade final : public BaseDataFacade
LoadTimestamp();
LoadViaNodeList();
LoadNames();
LoadTurnLaneStrings();
LoadCoreInformation();
LoadProfileProperties();
LoadRTree();
@ -783,6 +827,37 @@ class SharedDataFacade final : public BaseDataFacade
{
return m_entry_class_table.at(entry_class_id);
}
bool hasLaneData(const EdgeID id) const override final
{
return INVALID_LANE_DATAID != m_lane_data_id.at(id);
}
util::guidance::LaneTupelIdPair GetLaneData(const EdgeID id) const override final
{
BOOST_ASSERT(hasLaneData(id));
return m_lane_tupel_id_pairs.at(m_lane_data_id.at(id));
}
std::string GetTurnStringForID(const LaneStringID lane_string_id) const override final
{
if (INVALID_LANE_STRINGID == lane_string_id)
{
return "";
}
auto range = m_turn_string_table->GetRange(lane_string_id);
std::string result;
result.reserve(range.size());
if (range.begin() != range.end())
{
result.resize(range.back() - range.front() + 1);
std::copy(m_turn_string_char_list.begin() + range.front(),
m_turn_string_char_list.begin() + range.back() + 1,
result.begin());
}
return result;
}
};
}
}

View File

@ -15,6 +15,7 @@
#include "util/coordinate_calculation.hpp"
#include "util/guidance/entry_class.hpp"
#include "util/guidance/toolkit.hpp"
#include "util/guidance/turn_lanes.hpp"
#include "util/typedefs.hpp"
#include <boost/optional.hpp>
@ -70,7 +71,9 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
bearings.second,
extractor::guidance::TurnInstruction::NO_TURN(),
WaypointType::Depart,
0};
0,
util::guidance::LaneTupel(),
""};
Intersection intersection{source_node.location,
std::vector<short>({bearings.second}),
std::vector<bool>({true}),
@ -147,7 +150,11 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
bearings.second,
path_point.turn_instruction,
WaypointType::None,
0};
0,
path_point.lane_data.first,
(path_point.lane_data.second != INVALID_LANE_STRINGID
? facade.GetTurnStringForID(path_point.lane_data.second)
: "")};
segment_index++;
segment_duration = 0;
}
@ -202,7 +209,9 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
bearings.second,
extractor::guidance::TurnInstruction::NO_TURN(),
WaypointType::Arrive,
0};
0,
util::guidance::LaneTupel(),
""};
intersection = {
target_node.location,
std::vector<short>({static_cast<short>(util::bearing::reverseBearing(bearings.first))}),
@ -233,6 +242,9 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
BOOST_ASSERT(steps.back().intersections.front().bearings.size() == 1);
BOOST_ASSERT(steps.back().intersections.front().entry.size() == 1);
BOOST_ASSERT(steps.back().maneuver.waypoint_type == WaypointType::Arrive);
BOOST_ASSERT(steps.back().maneuver.lanes.lanes_in_turn == 0);
BOOST_ASSERT(steps.back().maneuver.lanes.first_lane_from_the_right == INVALID_LANEID);
BOOST_ASSERT(steps.back().maneuver.turn_lane_string == "");
return steps;
}

View File

@ -0,0 +1,24 @@
#ifndef OSRM_ENGINE_GUIDANCE_LANE_PROCESSING_HPP_
#define OSRM_ENGINE_GUIDANCE_LANE_PROCESSING_HPP_
#include <vector>
#include "engine/guidance/route_step.hpp"
namespace osrm
{
namespace engine
{
namespace guidance
{
// Constrains lanes for multi-hop situations where lane changes depend on earlier ones.
// Instead of forcing users to change lanes rapidly in a short amount of time,
// we anticipate lane changes emitting only matching lanes early on.
std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps);
} // namespace guidance
} // namespace engine
} // namespace osrm
#endif /* OSRM_ENGINE_GUIDANCE_LANE_PROCESSING_HPP_ */

View File

@ -43,11 +43,6 @@ std::vector<RouteStep> buildIntersections(std::vector<RouteStep> steps);
// remove steps invalidated by post-processing
std::vector<RouteStep> removeNoTurnInstructions(std::vector<RouteStep> steps);
// Constrains lanes for multi-hop situations where lane changes depend on earlier ones.
// Instead of forcing users to change lanes rapidly in a short amount of time,
// we anticipate lane changes emitting only matching lanes early on.
std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps);
// postProcess will break the connection between the leg geometry
// for which a segment is supposed to represent exactly the coordinates
// between routing maneuvers and the route steps itself.

View File

@ -3,8 +3,10 @@
#include "extractor/guidance/turn_instruction.hpp"
#include "util/coordinate.hpp"
#include "util/guidance/turn_lanes.hpp"
#include <cstdint>
#include <string>
#include <vector>
namespace osrm
@ -27,8 +29,12 @@ struct StepManeuver
short bearing_before;
short bearing_after;
extractor::guidance::TurnInstruction instruction;
WaypointType waypoint_type;
unsigned exit;
util::guidance::LaneTupel lanes;
std::string turn_lane_string;
};
inline StepManeuver getInvalidStepManeuver()
@ -38,7 +44,9 @@ inline StepManeuver getInvalidStepManeuver()
0,
extractor::guidance::TurnInstruction::NO_TURN(),
WaypointType::None,
0};
0,
util::guidance::LaneTupel(),
""};
}
} // namespace guidance

View File

@ -4,9 +4,9 @@
#include "extractor/guidance/turn_instruction.hpp"
#include "extractor/travel_mode.hpp"
#include "engine/phantom_node.hpp"
#include "util/typedefs.hpp"
#include "osrm/coordinate.hpp"
#include "util/guidance/turn_lanes.hpp"
#include "util/typedefs.hpp"
#include <vector>
@ -27,6 +27,8 @@ struct PathData
EdgeWeight duration_until_turn;
// instruction to execute at the turn
extractor::guidance::TurnInstruction turn_instruction;
// turn lane data
util::guidance::LaneTupelIdPair lane_data;
// travel mode of the street that leads to the turn
extractor::TravelMode travel_mode : 4;
// entry class of the turn, indicating possibility of turns

View File

@ -327,10 +327,14 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
name_index,
weight_vector[i],
extractor::guidance::TurnInstruction::NO_TURN(),
{{0, INVALID_LANEID}, INVALID_LANE_STRINGID},
travel_mode,
INVALID_ENTRY_CLASSID});
}
BOOST_ASSERT(unpacked_path.size() > 0);
if (facade->hasLaneData(ed.id))
unpacked_path.back().lane_data = facade->GetLaneData(ed.id);
unpacked_path.back().entry_classid = facade->GetEntryClassID(ed.id);
unpacked_path.back().turn_instruction = turn_instruction;
unpacked_path.back().duration_until_turn += (ed.distance - total_weight);
@ -389,6 +393,7 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
phantom_node_pair.target_phantom.name_id,
weight_vector[i],
extractor::guidance::TurnInstruction::NO_TURN(),
{{0, INVALID_LANEID}, INVALID_LANE_STRINGID},
target_traversed_in_reverse ? phantom_node_pair.target_phantom.backward_travel_mode
: phantom_node_pair.target_phantom.forward_travel_mode,
INVALID_ENTRY_CLASSID});

View File

@ -59,6 +59,7 @@ class EdgeBasedGraphFactory
const util::NameTable &turn_lanes);
void Run(const std::string &original_edge_data_filename,
const std::string &turn_lane_data_filename,
lua_State *lua_state,
const std::string &edge_segment_lookup_filename,
const std::string &edge_penalty_filename,
@ -124,6 +125,7 @@ class EdgeBasedGraphFactory
unsigned RenumberEdges();
void GenerateEdgeExpandedNodes();
void GenerateEdgeExpandedEdges(const std::string &original_edge_data_filename,
const std::string &turn_lane_data_filename,
lua_State *lua_state,
const std::string &edge_segment_lookup_filename,
const std::string &edge_fixed_penalties_filename,

View File

@ -2,8 +2,8 @@
#define EXTRACTION_WAY_HPP
#include "extractor/travel_mode.hpp"
#include "util/typedefs.hpp"
#include "util/guidance/turn_lanes.hpp"
#include "util/typedefs.hpp"
#include <string>
#include <vector>

View File

@ -61,7 +61,8 @@ struct ExtractorConfig
output_file_name = basepath + ".osrm";
restriction_file_name = basepath + ".osrm.restrictions";
names_file_name = basepath + ".osrm.names";
turn_lane_file_name = basepath + ".osrm.tld";
turn_lane_strings_file_name = basepath + ".osrm.tls";
turn_lane_data_file_name = basepath + ".osrm.tld";
timestamp_file_name = basepath + ".osrm.timestamp";
geometry_output_path = basepath + ".osrm.geometry";
node_output_path = basepath + ".osrm.nodes";
@ -83,7 +84,8 @@ struct ExtractorConfig
std::string output_file_name;
std::string restriction_file_name;
std::string names_file_name;
std::string turn_lane_file_name;
std::string turn_lane_data_file_name;
std::string turn_lane_strings_file_name;
std::string timestamp_file_name;
std::string geometry_output_path;
std::string edge_output_path;

View File

@ -35,7 +35,7 @@ inline void printTurnAssignmentData(const NodeID at,
for (const auto &road)
std::cout << "\t" << toString(road) << "\n";
//flushes as well
// flushes as well
print(turn_lane_data);
}

View File

@ -22,6 +22,7 @@ struct TurnOperation final
EdgeID eid;
double angle;
TurnInstruction instruction;
LaneDataID lane_data_id;
};
// A Connected Road is the internal representation of a potential turn. Internally, we require

View File

@ -5,9 +5,9 @@
#include "extractor/guidance/intersection.hpp"
#include "extractor/query_node.hpp"
#include "extractor/restriction_map.hpp"
#include "util/name_table.hpp"
#include "util/node_based_graph.hpp"
#include "util/typedefs.hpp"
#include "util/name_table.hpp"
#include <unordered_set>
#include <vector>

View File

@ -5,6 +5,8 @@
#include "util/coordinate.hpp"
#include "util/coordinate_calculation.hpp"
#include "util/guidance/toolkit.hpp"
#include "util/guidance/turn_lanes.hpp"
#include "util/typedefs.hpp"
#include "extractor/compressed_edge_container.hpp"
#include "extractor/query_node.hpp"
@ -20,10 +22,12 @@
#include <cstdint>
#include <map>
#include <string>
#include <unordered_map>
#include <utility>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/functional/hash.hpp>
namespace osrm
{
@ -32,6 +36,9 @@ namespace extractor
namespace guidance
{
using util::guidance::LaneTupelIdPair;
using LaneDataIdMap = std::unordered_map<LaneTupelIdPair, LaneDataID, boost::hash<LaneTupelIdPair>>;
using util::guidance::angularDeviation;
namespace detail

View File

@ -51,7 +51,7 @@ class TurnAnalysis
std::vector<TurnOperation>
transformIntersectionIntoTurns(const Intersection &intersection) const;
const IntersectionGenerator& getGenerator() const;
const IntersectionGenerator &getGenerator() const;
private:
const util::NodeBasedDynamicGraph &node_based_graph;

View File

@ -77,16 +77,14 @@ struct TurnInstruction
{
using LaneTupel = util::guidance::LaneTupel;
TurnInstruction(const TurnType::Enum type = TurnType::Invalid,
const DirectionModifier::Enum direction_modifier = DirectionModifier::Straight,
const LaneTupel lane_tupel = {0, INVALID_LANEID})
: type(type), direction_modifier(direction_modifier), lane_tupel(lane_tupel)
const DirectionModifier::Enum direction_modifier = DirectionModifier::UTurn)
: type(type), direction_modifier(direction_modifier)
{
}
TurnType::Enum type : 5;
DirectionModifier::Enum direction_modifier : 3;
// the lane tupel that is used for the turn
LaneTupel lane_tupel;
static TurnInstruction INVALID() { return {TurnType::Invalid, DirectionModifier::UTurn}; }
@ -147,18 +145,16 @@ struct TurnInstruction
}
};
static_assert(sizeof(TurnInstruction) == 3, "TurnInstruction does not fit three byte");
static_assert(sizeof(TurnInstruction) == 1, "TurnInstruction does not fit a byte");
inline bool operator!=(const TurnInstruction lhs, const TurnInstruction rhs)
{
return lhs.type != rhs.type || lhs.direction_modifier != rhs.direction_modifier ||
lhs.lane_tupel != rhs.lane_tupel;
return lhs.type != rhs.type || lhs.direction_modifier != rhs.direction_modifier;
}
inline bool operator==(const TurnInstruction lhs, const TurnInstruction rhs)
{
return lhs.type == rhs.type && lhs.direction_modifier == rhs.direction_modifier &&
lhs.lane_tupel == rhs.lane_tupel;
return lhs.type == rhs.type && lhs.direction_modifier == rhs.direction_modifier;
}
} // namespace guidance

View File

@ -2,6 +2,7 @@
#define OSRM_EXTRACTOR_GUIDANCE_TURN_LANE_HANDLER_HPP_
#include "extractor/guidance/intersection.hpp"
#include "extractor/guidance/toolkit.hpp"
#include "extractor/guidance/turn_analysis.hpp"
#include "extractor/guidance/turn_lane_data.hpp"
#include "extractor/query_node.hpp"
@ -13,7 +14,6 @@
#include <map>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
@ -38,13 +38,12 @@ class TurnLaneHandler
const std::vector<QueryNode> &node_info_list,
const TurnAnalysis &turn_analysis);
Intersection
assignTurnLanes(const NodeID at, const EdgeID via_edge, Intersection intersection) const;
Intersection assignTurnLanes(const NodeID at,
const EdgeID via_edge,
Intersection intersection,
LaneDataIdMap &id_map) const;
private:
using LaneTupel = util::guidance::LaneTupel;
std::unordered_map<LaneTupel, std::uint16_t> lane_tupels;
// we need to be able to look at previous intersections to, in some cases, find the correct turn
// lanes for a turn
const util::NodeBasedDynamicGraph &node_based_graph;
@ -58,7 +57,9 @@ class TurnLaneHandler
// in case of a simple intersection, assign the lane entries
Intersection simpleMatchTuplesToTurns(Intersection intersection,
const LaneDataVector &lane_data) const;
const LaneDataVector &lane_data,
const LaneStringID lane_string_id,
LaneDataIdMap &id_map) const;
// partition lane data into lane data relevant at current turn and at next turn
std::pair<TurnLaneHandler::LaneDataVector, TurnLaneHandler::LaneDataVector> partitionLaneData(
@ -68,7 +69,8 @@ class TurnLaneHandler
// intersection whose turns might be related to this current intersection
Intersection handleTurnAtPreviousIntersection(const NodeID at,
const EdgeID via_edge,
Intersection intersection) const;
Intersection intersection,
LaneDataIdMap &id_map) const;
};
} // namespace lanes

View File

@ -2,12 +2,15 @@
#define OSRM_EXTRACTOR_GUIDANCE_TURN_LANE_MATCHER_HPP_
#include "extractor/guidance/intersection.hpp"
#include "extractor/guidance/toolkit.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include "extractor/guidance/turn_lane_data.hpp"
#include "util/guidance/turn_lanes.hpp"
#include "util/node_based_graph.hpp"
#include <unordered_map>
namespace osrm
{
namespace extractor
@ -44,7 +47,9 @@ bool canMatchTrivially(const Intersection &intersection, const LaneDataVector &l
// perform a trivial match on the turn lanes
Intersection triviallyMatchLanesToTurns(Intersection intersection,
const LaneDataVector &lane_data,
const util::NodeBasedDynamicGraph &node_based_graph);
const util::NodeBasedDynamicGraph &node_based_graph,
const LaneStringID lane_string_id,
LaneDataIdMap &lane_data_to_id);
} // namespace lanes
} // namespace guidance

View File

@ -90,8 +90,8 @@ inline NodeBasedEdge::NodeBasedEdge(NodeID source,
guidance::RoadClassificationData road_classification)
: source(source), target(target), name_id(name_id), weight(weight), forward(forward),
backward(backward), roundabout(roundabout), access_restricted(access_restricted),
startpoint(startpoint), is_split(is_split), travel_mode(travel_mode), lane_string_id(lane_string_id),
road_classification(std::move(road_classification))
startpoint(startpoint), is_split(is_split), travel_mode(travel_mode),
lane_string_id(lane_string_id), road_classification(std::move(road_classification))
{
}

View File

@ -17,18 +17,19 @@ struct OriginalEdgeData
{
explicit OriginalEdgeData(NodeID via_node,
unsigned name_id,
LaneDataID lane_data_id,
guidance::TurnInstruction turn_instruction,
EntryClassID entry_classid,
TravelMode travel_mode)
: via_node(via_node), name_id(name_id), entry_classid(entry_classid),
turn_instruction(turn_instruction), travel_mode(travel_mode)
lane_data_id(lane_data_id), turn_instruction(turn_instruction), travel_mode(travel_mode)
{
}
OriginalEdgeData()
: via_node(std::numeric_limits<unsigned>::max()),
name_id(std::numeric_limits<unsigned>::max()), entry_classid(INVALID_ENTRY_CLASSID),
turn_instruction(guidance::TurnInstruction::INVALID()),
lane_data_id(INVALID_LANE_DATAID), turn_instruction(guidance::TurnInstruction::INVALID()),
travel_mode(TRAVEL_MODE_INACCESSIBLE)
{
}
@ -36,9 +37,13 @@ struct OriginalEdgeData
NodeID via_node;
unsigned name_id;
EntryClassID entry_classid;
LaneDataID lane_data_id;
guidance::TurnInstruction turn_instruction;
TravelMode travel_mode;
};
static_assert(sizeof(OriginalEdgeData) == 16,
"Increasing the size of OriginalEdgeData increases memory consumption");
}
}

View File

@ -16,6 +16,41 @@ namespace storage
// Added at the start and end of each block as sanity check
const constexpr char CANARY[4] = {'O', 'S', 'R', 'M'};
const constexpr char *block_id_to_name[] = {"NAME_OFFSETS",
"NAME_BLOCKS",
"NAME_CHAR_LIST",
"NAME_ID_LIST",
"VIA_NODE_LIST",
"GRAPH_NODE_LIST",
"GRAPH_EDGE_LIST",
"COORDINATE_LIST",
"OSM_NODE_ID_LIST",
"TURN_INSTRUCTION",
"TRAVEL_MODE",
"ENTRY_CLASSID",
"R_SEARCH_TREE",
"GEOMETRIES_INDEX",
"GEOMETRIES_LIST",
"HSGR_CHECKSUM",
"TIMESTAMP",
"FILE_INDEX_PATH",
"CORE_MARKER",
"DATASOURCES_LIST",
"DATASOURCE_NAME_DATA",
"DATASOURCE_NAME_OFFSETS",
"DATASOURCE_NAME_LENGTHS",
"PROPERTIES",
"BEARING_CLASSID",
"BEARING_OFFSETS",
"BEARING_BLOCKS",
"BEARING_VALUES",
"ENTRY_CLASS",
"LANE_DATA_ID",
"TURN_LANE_DATA",
"TURN_STRING_OFFSETS",
"TURN_STRING_BLOCKS",
"TURN_STRING_CHAR_LIST"};
struct SharedDataLayout
{
enum BlockID
@ -30,8 +65,8 @@ struct SharedDataLayout
COORDINATE_LIST,
OSM_NODE_ID_LIST,
TURN_INSTRUCTION,
ENTRY_CLASSID,
TRAVEL_MODE,
ENTRY_CLASSID,
R_SEARCH_TREE,
GEOMETRIES_INDEX,
GEOMETRIES_LIST,
@ -49,6 +84,11 @@ struct SharedDataLayout
BEARING_BLOCKS,
BEARING_VALUES,
ENTRY_CLASS,
LANE_DATA_ID,
TURN_LANE_DATA,
TURN_STRING_OFFSETS,
TURN_STRING_BLOCKS,
TURN_STRING_CHAR_LIST,
NUM_BLOCKS
};
@ -113,11 +153,13 @@ struct SharedDataLayout
bool end_canary_alive = std::equal(CANARY, CANARY + sizeof(CANARY), end_canary_ptr);
if (!start_canary_alive)
{
throw util::exception("Start canary of block corrupted.");
throw util::exception(std::string("Start canary of block corrupted. (") +
block_id_to_name[bid] + ")");
}
if (!end_canary_alive)
{
throw util::exception("End canary of block corrupted.");
throw util::exception(std::string("End canary of block corrupted. (") +
block_id_to_name[bid] + ")");
}
}

View File

@ -65,6 +65,8 @@ struct StorageConfig final
boost::filesystem::path names_data_path;
boost::filesystem::path properties_path;
boost::filesystem::path intersection_class_path;
boost::filesystem::path turn_lane_data_path;
boost::filesystem::path turn_lane_string_path;
};
}
}

View File

@ -65,21 +65,18 @@ class LaneTupel
LaneID lanes_in_turn;
LaneID first_lane_from_the_right;
friend std::size_t std::hash<LaneTupel>::operator()(const LaneTupel &) const;
friend std::size_t hash_value(const LaneTupel &tup)
{
std::size_t seed{0};
boost::hash_combine(seed, tup.lanes_in_turn);
boost::hash_combine(seed, tup.first_lane_from_the_right);
return seed;
}
};
using LaneTupelIdPair = std::pair<util::guidance::LaneTupel, LaneStringID>;
} // namespace guidance
} // namespace util
} // namespace osrm
// make Bearing Class hasbable
namespace std
{
inline size_t hash<::osrm::util::guidance::LaneTupel>::
operator()(const ::osrm::util::guidance::LaneTupel &lane_tupel) const
{
return boost::hash_value(*reinterpret_cast<const std::uint16_t *>(&lane_tupel));
}
} // namespace std
#endif /* OSRM_UTIL_GUIDANCE_TURN_LANES_HPP */

View File

@ -20,7 +20,8 @@ struct NodeBasedEdgeData
NodeBasedEdgeData()
: distance(INVALID_EDGE_WEIGHT), edge_id(SPECIAL_NODEID),
name_id(std::numeric_limits<unsigned>::max()), access_restricted(false), reversed(false),
roundabout(false), travel_mode(TRAVEL_MODE_INACCESSIBLE), lane_string_id(INVALID_LANE_STRINGID)
roundabout(false), travel_mode(TRAVEL_MODE_INACCESSIBLE),
lane_string_id(INVALID_LANE_STRINGID)
{
}

View File

@ -60,9 +60,11 @@ using NameID = std::uint32_t;
using EdgeWeight = std::int32_t;
using LaneStringID = std::uint16_t;
static const LaneStringID INVALID_LANE_STRINGID = std::numeric_limits<LaneStringID>::max();
using LaneID = std::uint8_t;
static const LaneID INVALID_LANEID = std::numeric_limits<LaneID>::max();
static const LaneStringID INVALID_LANE_STRINGID = std::numeric_limits<LaneStringID>::max();
using LaneDataID = std::uint16_t;
static const LaneDataID INVALID_LANE_DATAID = std::numeric_limits<LaneStringID>::max();
using BearingClassID = std::uint32_t;
static const BearingClassID INVALID_BEARING_CLASSID = std::numeric_limits<BearingClassID>::max();

View File

@ -11,6 +11,7 @@
#include <boost/assert.hpp>
#include <boost/optional.hpp>
#include <boost/tokenizer.hpp>
#include <algorithm>
#include <iterator>
@ -63,7 +64,7 @@ inline bool isValidModifier(const guidance::StepManeuver maneuver)
inline bool hasValidLanes(const guidance::StepManeuver maneuver)
{
return maneuver.instruction.lane_tupel.lanes_in_turn > 0;
return maneuver.lanes.lanes_in_turn > 0;
}
std::string instructionTypeToString(const TurnType::Enum type)
@ -71,12 +72,31 @@ std::string instructionTypeToString(const TurnType::Enum type)
return turn_type_names[static_cast<std::size_t>(type)];
}
util::json::Array laneArrayFromLaneTupe(const util::guidance::LaneTupel lane_tupel)
util::json::Array lanesFromManeuver(const guidance::StepManeuver &maneuver)
{
BOOST_ASSERT(lane_tupel.lanes_in_turn >= 1);
BOOST_ASSERT(maneuver.lanes.lanes_in_turn >= 1);
util::json::Array result;
for (LaneID i = 0; i < lane_tupel.lanes_in_turn; ++i)
result.values.push_back(lane_tupel.first_lane_from_the_right + i);
LaneID lane_id = 0;
typedef boost::tokenizer<boost::char_separator<char>> tokenizer;
boost::char_separator<char> sep("|", "", boost::keep_empty_tokens);
tokenizer tokens(maneuver.turn_lane_string, sep);
lane_id = std::distance(tokens.begin(), tokens.end());
for (auto iter = tokens.begin(); iter != tokens.end(); ++iter)
{
--lane_id;
util::json::Object lane;
lane.values["marked"] = (iter->empty() ? "none" : *iter);
if (lane_id >= maneuver.lanes.first_lane_from_the_right &&
lane_id < maneuver.lanes.first_lane_from_the_right + maneuver.lanes.lanes_in_turn)
lane.values["take"] = util::json::True();
else
lane.values["take"] = util::json::False();
result.values.push_back(lane);
}
return result;
}
@ -162,8 +182,7 @@ util::json::Object makeStepManeuver(const guidance::StepManeuver &maneuver)
detail::instructionModifierToString(maneuver.instruction.direction_modifier);
if (detail::hasValidLanes(maneuver))
step_maneuver.values["lanes"] =
detail::laneArrayFromLaneTupe(maneuver.instruction.lane_tupel);
step_maneuver.values["lanes"] = detail::lanesFromManeuver(maneuver);
step_maneuver.values["location"] = detail::coordinateToLonLat(maneuver.location);
step_maneuver.values["bearing_before"] = std::round(maneuver.bearing_before);

View File

@ -0,0 +1,111 @@
#include "util/for_each_pair.hpp"
#include "util/group_by.hpp"
#include "util/guidance/toolkit.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include <iterator>
using TurnInstruction = osrm::extractor::guidance::TurnInstruction;
namespace TurnType = osrm::extractor::guidance::TurnType;
namespace DirectionModifier = osrm::extractor::guidance::DirectionModifier;
using osrm::util::guidance::isLeftTurn;
using osrm::util::guidance::isRightTurn;
namespace osrm
{
namespace engine
{
namespace guidance
{
std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps)
{
const constexpr auto MIN_DURATION_NEEDED_FOR_LANE_CHANGE = 15.;
// Postprocessing does not strictly guarantee for only turns
const auto is_turn = [](const RouteStep &step) {
return step.maneuver.instruction.type != TurnType::NewName &&
step.maneuver.instruction.type != TurnType::Notification;
};
const auto is_quick = [MIN_DURATION_NEEDED_FOR_LANE_CHANGE](const RouteStep &step) {
return step.duration < MIN_DURATION_NEEDED_FOR_LANE_CHANGE;
};
const auto is_quick_turn = [&](const RouteStep &step) {
return is_turn(step) && is_quick(step);
};
// Determine range of subsequent quick turns, candidates for possible lane anticipation
using StepIter = decltype(steps)::iterator;
using StepIterRange = std::pair<StepIter, StepIter>;
std::vector<StepIterRange> subsequent_quick_turns;
const auto keep_turn_range = [&](StepIterRange range) {
if (std::distance(range.first, range.second) > 1)
subsequent_quick_turns.push_back(std::move(range));
};
util::group_by(begin(steps), end(steps), is_quick_turn, keep_turn_range);
// Walk backwards over all turns, constraining possible turn lanes.
// Later turn lanes constrain earlier ones: we have to anticipate lane changes.
const auto constrain_lanes = [](const StepIterRange &turns) {
const std::reverse_iterator<StepIter> rev_first{turns.second};
const std::reverse_iterator<StepIter> rev_last{turns.first};
// We're walking backwards over all adjacent turns:
// the current turn lanes constrain the lanes we have to take in the previous turn.
util::for_each_pair(rev_first, rev_last, [](RouteStep &current, RouteStep &previous) {
const auto current_inst = current.maneuver.instruction;
const auto current_lanes = current.maneuver.lanes;
// Constrain the previous turn's lanes
auto &previous_inst = previous.maneuver.instruction;
auto &previous_lanes = previous.maneuver.lanes;
// Lane mapping (N:M) from previous lanes (N) to current lanes (M), with:
// N > M, N > 1 fan-in situation, constrain N lanes to min(N,M) shared lanes
// otherwise nothing to constrain
const bool lanes_to_constrain = previous_lanes.lanes_in_turn > 1;
const bool lanes_fan_in = previous_lanes.lanes_in_turn > current_lanes.lanes_in_turn;
if (!lanes_to_constrain || !lanes_fan_in)
return;
// In case there is no lane information we work with one artificial lane
const auto current_adjusted_lanes = std::max(current_lanes.lanes_in_turn, LaneID{1});
const auto num_shared_lanes = std::min(current_adjusted_lanes, //
previous_lanes.lanes_in_turn);
if (isRightTurn(current_inst))
{
// Current turn is right turn, already keep right during the previous turn.
// This implies constraining the leftmost lanes in the previous turn step.
previous_lanes = {num_shared_lanes, previous_lanes.first_lane_from_the_right};
}
else if (isLeftTurn(current_inst))
{
// Current turn is left turn, already keep left during previous turn.
// This implies constraining the rightmost lanes in the previous turn step.
const LaneID shared_lane_delta = previous_lanes.lanes_in_turn - num_shared_lanes;
const LaneID previous_adjusted_lanes =
std::min(current_adjusted_lanes, shared_lane_delta);
const LaneID constraint_first_lane_from_the_right =
previous_lanes.first_lane_from_the_right + previous_adjusted_lanes;
previous_lanes = {num_shared_lanes, constraint_first_lane_from_the_right};
}
});
};
std::for_each(begin(subsequent_quick_turns), end(subsequent_quick_turns), constrain_lanes);
return steps;
}
} // namespace guidance
} // namespace engine
} // namespace osrm

View File

@ -4,9 +4,8 @@
#include "engine/guidance/assemble_steps.hpp"
#include "engine/guidance/toolkit.hpp"
#include "util/for_each_pair.hpp"
#include "util/group_by.hpp"
#include "util/guidance/toolkit.hpp"
#include "util/guidance/turn_lanes.hpp"
#include <boost/assert.hpp>
#include <boost/range/algorithm_ext/erase.hpp>
@ -15,7 +14,6 @@
#include <cmath>
#include <cstddef>
#include <iostream>
#include <iterator>
#include <limits>
#include <utility>
@ -24,8 +22,6 @@ namespace TurnType = osrm::extractor::guidance::TurnType;
namespace DirectionModifier = osrm::extractor::guidance::DirectionModifier;
using osrm::util::guidance::angularDeviation;
using osrm::util::guidance::getTurnDirection;
using osrm::util::guidance::isLeftTurn;
using osrm::util::guidance::isRightTurn;
namespace osrm
{
@ -867,6 +863,8 @@ void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry)
designated_depart.maneuver.instruction = TurnInstruction::NO_TURN();
// we need to make this conform with the intersection format for the first intersection
auto &first_intersection = designated_depart.intersections.front();
designated_depart.maneuver.lanes = util::guidance::LaneTupel();
designated_depart.maneuver.turn_lane_string = "";
first_intersection.bearings = {first_intersection.bearings[first_intersection.out]};
first_intersection.entry = {true};
first_intersection.in = Intersection::NO_INDEX;
@ -933,6 +931,8 @@ void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry)
next_to_last_step.maneuver.waypoint_type = WaypointType::Arrive;
next_to_last_step.maneuver.instruction = TurnInstruction::NO_TURN();
next_to_last_step.maneuver.bearing_after = 0;
next_to_last_step.maneuver.lanes = util::guidance::LaneTupel();
next_to_last_step.maneuver.turn_lane_string = "";
BOOST_ASSERT(next_to_last_step.intersections.size() == 1);
auto &last_intersection = next_to_last_step.intersections.back();
last_intersection.bearings = {last_intersection.bearings[last_intersection.in]};
@ -1038,94 +1038,6 @@ std::vector<RouteStep> assignRelativeLocations(std::vector<RouteStep> steps,
return steps;
}
std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps)
{
const constexpr auto MIN_DURATION_NEEDED_FOR_LANE_CHANGE = 15.;
// Postprocessing does not strictly guarantee for only turns
const auto is_turn = [](const RouteStep &step) {
return step.maneuver.instruction.type != TurnType::NewName &&
step.maneuver.instruction.type != TurnType::Notification;
};
const auto is_quick = [](const RouteStep &step) {
return step.duration < MIN_DURATION_NEEDED_FOR_LANE_CHANGE;
};
const auto is_quick_turn = [&](const RouteStep &step) {
return is_turn(step) && is_quick(step);
};
// Determine range of subsequent quick turns, candidates for possible lane anticipation
using StepIter = decltype(steps)::iterator;
using StepIterRange = std::pair<StepIter, StepIter>;
std::vector<StepIterRange> subsequent_quick_turns;
const auto keep_turn_range = [&](StepIterRange range) {
if (std::distance(range.first, range.second) > 1)
subsequent_quick_turns.push_back(std::move(range));
};
util::group_by(begin(steps), end(steps), is_quick_turn, keep_turn_range);
// Walk backwards over all turns, constraining possible turn lanes.
// Later turn lanes constrain earlier ones: we have to anticipate lane changes.
const auto constrain_lanes = [](const StepIterRange &turns) {
const std::reverse_iterator<StepIter> rev_first{turns.second};
const std::reverse_iterator<StepIter> rev_last{turns.first};
// We're walking backwards over all adjacent turns:
// the current turn lanes constrain the lanes we have to take in the previous turn.
util::for_each_pair(rev_first, rev_last, [](RouteStep &current, RouteStep &previous) {
const auto current_inst = current.maneuver.instruction;
const auto current_lanes = current_inst.lane_tupel;
// Constrain the previous turn's lanes
auto &previous_inst = previous.maneuver.instruction;
auto &previous_lanes = previous_inst.lane_tupel;
// Lane mapping (N:M) from previous lanes (N) to current lanes (M), with:
// N > M, N > 1 fan-in situation, constrain N lanes to min(N,M) shared lanes
// otherwise nothing to constrain
const bool lanes_to_constrain = previous_lanes.lanes_in_turn > 1;
const bool lanes_fan_in = previous_lanes.lanes_in_turn > current_lanes.lanes_in_turn;
if (!lanes_to_constrain || !lanes_fan_in)
return;
// In case there is no lane information we work with one artificial lane
const auto current_adjusted_lanes = std::max(current_lanes.lanes_in_turn, LaneID{1});
const auto num_shared_lanes = std::min(current_adjusted_lanes, //
previous_lanes.lanes_in_turn);
if (isRightTurn(current_inst))
{
// Current turn is right turn, already keep right during the previous turn.
// This implies constraining the leftmost lanes in the previous turn step.
previous_lanes = {num_shared_lanes, previous_lanes.first_lane_from_the_right};
}
else if (isLeftTurn(current_inst))
{
// Current turn is left turn, already keep left during previous turn.
// This implies constraining the rightmost lanes in the previous turn step.
const LaneID shared_lane_delta = previous_lanes.lanes_in_turn - num_shared_lanes;
const LaneID previous_adjusted_lanes =
std::min(current_adjusted_lanes, shared_lane_delta);
const LaneID constraint_first_lane_from_the_right =
previous_lanes.first_lane_from_the_right + previous_adjusted_lanes;
previous_lanes = {num_shared_lanes, constraint_first_lane_from_the_right};
}
});
};
std::for_each(begin(subsequent_quick_turns), end(subsequent_quick_turns), constrain_lanes);
return steps;
}
LegGeometry resyncGeometry(LegGeometry leg_geometry, const std::vector<RouteStep> &steps)
{
// The geometry uses an adjacency array-like structure for representation.

View File

@ -1,5 +1,5 @@
#include "extractor/edge_based_edge.hpp"
#include "extractor/edge_based_graph_factory.hpp"
#include "extractor/edge_based_edge.hpp"
#include "util/coordinate.hpp"
#include "util/coordinate_calculation.hpp"
#include "util/exception.hpp"
@ -182,6 +182,7 @@ void EdgeBasedGraphFactory::FlushVectorToStream(
}
void EdgeBasedGraphFactory::Run(const std::string &original_edge_data_filename,
const std::string &turn_lane_data_filename,
lua_State *lua_state,
const std::string &edge_segment_lookup_filename,
const std::string &edge_penalty_filename,
@ -198,6 +199,7 @@ void EdgeBasedGraphFactory::Run(const std::string &original_edge_data_filename,
TIMER_START(generate_edges);
GenerateEdgeExpandedEdges(original_edge_data_filename,
turn_lane_data_filename,
lua_state,
edge_segment_lookup_filename,
edge_penalty_filename,
@ -296,6 +298,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedNodes()
/// Actually it also generates OriginalEdgeData and serializes them...
void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
const std::string &original_edge_data_filename,
const std::string &turn_lane_data_filename,
lua_State *lua_state,
const std::string &edge_segment_lookup_filename,
const std::string &edge_fixed_penalties_filename,
@ -348,6 +351,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
bearing_class_by_node_based_node.resize(m_node_based_graph->GetNumberOfNodes(),
std::numeric_limits<std::uint32_t>::max());
guidance::LaneDataIdMap lane_data_map;
for (const auto node_u : util::irange(0u, m_node_based_graph->GetNumberOfNodes()))
{
progress.PrintStatus(node_u);
@ -364,8 +368,8 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
intersection =
turn_analysis.assignTurnTypes(node_u, edge_from_u, std::move(intersection));
intersection =
turn_lane_handler.assignTurnLanes(node_u, edge_from_u, std::move(intersection));
intersection = turn_lane_handler.assignTurnLanes(
node_u, edge_from_u, std::move(intersection), lane_data_map);
const auto possible_turns = turn_analysis.transformIntersectionIntoTurns(intersection);
// the entry class depends on the turn, so we have to classify the interesction for
@ -437,6 +441,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
original_edge_data_vector.emplace_back(
m_compressed_edge_container.GetPositionForID(edge_from_u),
edge_data1.name_id,
turn.lane_data_id,
turn_instruction,
entry_class_id,
edge_data1.travel_mode);
@ -541,6 +546,22 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
util::SimpleLogger().Write() << "Created " << entry_class_hash.size() << " entry classes and "
<< bearing_class_hash.size() << " Bearing Classes";
util::SimpleLogger().Write() << "Writing Turn Lane Data to File...";
std::ofstream turn_lane_data_file(turn_lane_data_filename.c_str(), std::ios::binary);
std::vector<util::guidance::LaneTupelIdPair> lane_data(lane_data_map.size());
// extract lane data sorted by ID
for (auto itr : lane_data_map)
lane_data[itr.second] = itr.first;
std::uint64_t size = lane_data.size();
turn_lane_data_file.write(reinterpret_cast<const char *>(&size), sizeof(size));
if (!lane_data.empty())
turn_lane_data_file.write(reinterpret_cast<const char *>(&lane_data[0]),
sizeof(util::guidance::LaneTupelIdPair) * lane_data.size());
util::SimpleLogger().Write() << "done.";
FlushVectorToStream(edge_data_file, original_edge_data_vector);
// Finally jump back to the empty space at the beginning and write length prefix

View File

@ -51,8 +51,6 @@ ExtractionContainers::ExtractionContainers()
name_lengths.push_back(0);
name_lengths.push_back(0);
name_lengths.push_back(0);
name_lengths.push_back(0);
name_lengths.push_back(0);
turn_lane_lengths.push_back(0);
}
@ -87,8 +85,8 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
PrepareRestrictions();
WriteRestrictions(restrictions_file_name);
WriteCharData(name_file_name,name_lengths,name_char_data);
WriteCharData(turn_lane_file_name,turn_lane_lengths,turn_lane_char_data);
WriteCharData(name_file_name, name_lengths, name_char_data);
WriteCharData(turn_lane_file_name, turn_lane_lengths, turn_lane_char_data);
}
catch (const std::exception &e)
{

View File

@ -239,7 +239,7 @@ int Extractor::run()
extraction_containers.PrepareData(config.output_file_name,
config.restriction_file_name,
config.names_file_name,
config.turn_lane_file_name,
config.turn_lane_strings_file_name,
main_context.state);
WriteProfileProperties(config.profile_properties_output_path, main_context.properties);
@ -504,7 +504,7 @@ Extractor::BuildEdgeExpandedGraph(lua_State *lua_state,
compressed_edge_container.SerializeInternalVector(config.geometry_output_path);
util::NameTable name_table(config.names_file_name);
util::NameTable turn_lanes(config.turn_lane_file_name);
util::NameTable turn_lanes(config.turn_lane_strings_file_name);
EdgeBasedGraphFactory edge_based_graph_factory(
node_based_graph,
@ -518,6 +518,7 @@ Extractor::BuildEdgeExpandedGraph(lua_State *lua_state,
turn_lanes);
edge_based_graph_factory.Run(config.edge_output_path,
config.turn_lane_data_file_name,
lua_state,
config.edge_segment_lookup_path,
config.edge_penalty_path,

View File

@ -1,7 +1,7 @@
#include "extractor/extractor_callbacks.hpp"
#include "extractor/extraction_containers.hpp"
#include "extractor/extraction_node.hpp"
#include "extractor/extraction_way.hpp"
#include "extractor/extractor_callbacks.hpp"
#include "extractor/external_memory_node.hpp"
#include "extractor/restriction.hpp"
@ -149,9 +149,17 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
// Otherwise fetches the id based on the name and returns it without insertion.
const constexpr auto MAX_STRING_LENGTH = 255u;
const auto requestId = [this,MAX_STRING_LENGTH](const std::string turn_lane_string) {
if( turn_lane_string == "" )
const auto requestId = [this, MAX_STRING_LENGTH](const std::string &turn_lane_string_) {
if (turn_lane_string_ == "")
return INVALID_LANE_STRINGID;
// requires https://github.com/cucumber/cucumber-js/issues/417
// remove this handling when the issue is contained
std::string turn_lane_string = turn_lane_string_;
for (auto &val : turn_lane_string)
if (val == '&')
val = '|';
const auto &lane_map_iterator = lane_map.find(turn_lane_string);
if (lane_map.end() == lane_map_iterator)
{

View File

@ -113,7 +113,7 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
// traffic signals in the `traffic_lights` list, which EdgeData
// doesn't have access to.
const bool has_node_penalty = traffic_lights.find(node_v) != traffic_lights.end();
if( has_node_penalty )
if (has_node_penalty)
continue;
// Get distances before graph is modified
@ -168,10 +168,10 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
return front;
return back;
};
graph.GetEdgeData(forward_e1).lane_string_id =
selectLaneID(graph.GetEdgeData(forward_e1).lane_string_id, fwd_edge_data2.lane_string_id);
graph.GetEdgeData(reverse_e1).lane_string_id =
selectLaneID(graph.GetEdgeData(reverse_e1).lane_string_id, rev_edge_data2.lane_string_id);
graph.GetEdgeData(forward_e1).lane_string_id = selectLaneID(
graph.GetEdgeData(forward_e1).lane_string_id, fwd_edge_data2.lane_string_id);
graph.GetEdgeData(reverse_e1).lane_string_id = selectLaneID(
graph.GetEdgeData(reverse_e1).lane_string_id, rev_edge_data2.lane_string_id);
// remove e2's (if bidir, otherwise only one)
graph.DeleteEdge(node_v, forward_e2);

View File

@ -22,12 +22,9 @@ std::string toString(const ConnectedRoad &road)
result += " angle: ";
result += std::to_string(road.turn.angle);
result += " instruction: ";
result +=
std::to_string(static_cast<std::int32_t>(road.turn.instruction.type)) + " " +
std::to_string(static_cast<std::int32_t>(road.turn.instruction.direction_modifier)) + " " +
std::to_string(static_cast<std::int32_t>(road.turn.instruction.lane_tupel.lanes_in_turn)) +
" " + std::to_string(static_cast<std::int32_t>(
road.turn.instruction.lane_tupel.first_lane_from_the_right));
result += std::to_string(static_cast<std::int32_t>(road.turn.instruction.type)) + " " +
std::to_string(static_cast<std::int32_t>(road.turn.instruction.direction_modifier)) +
" " + std::to_string(static_cast<std::int32_t>(road.turn.lane_data_id));
return result;
}

View File

@ -1,5 +1,5 @@
#include "extractor/guidance/constants.hpp"
#include "extractor/guidance/intersection_generator.hpp"
#include "extractor/guidance/constants.hpp"
#include "extractor/guidance/toolkit.hpp"
#include <algorithm>
@ -114,8 +114,11 @@ Intersection IntersectionGenerator::getConnectedRoads(const NodeID from_node,
has_uturn_edge = true;
}
intersection.push_back(ConnectedRoad(
TurnOperation{onto_edge, angle, {TurnType::Invalid, DirectionModifier::UTurn}},
intersection.push_back(
ConnectedRoad(TurnOperation{onto_edge,
angle,
{TurnType::Invalid, DirectionModifier::UTurn},
INVALID_LANE_DATAID},
turn_is_valid));
}
@ -124,7 +127,9 @@ Intersection IntersectionGenerator::getConnectedRoads(const NodeID from_node,
if (!has_uturn_edge)
{
intersection.push_back(
{TurnOperation{via_eid, 0., {TurnType::Invalid, DirectionModifier::UTurn}}, false});
{TurnOperation{
via_eid, 0., {TurnType::Invalid, DirectionModifier::UTurn}, INVALID_LANE_DATAID},
false});
}
const auto ByAngle = [](const ConnectedRoad &first, const ConnectedRoad second) {

View File

@ -373,11 +373,12 @@ Intersection RoundaboutHandler::handleRoundabouts(const RoundaboutType roundabou
if (1 == node_based_graph.GetDirectedOutDegree(node_v))
{
// No turn possible.
if( intersection.size() == 2 )
if (intersection.size() == 2)
turn.instruction = TurnInstruction::NO_TURN();
else
{
turn.instruction.type = TurnType::Suppressed; //make sure to report intersection
turn.instruction.type =
TurnType::Suppressed; // make sure to report intersection
turn.instruction.direction_modifier = getTurnDirection(turn.angle);
}
}

View File

@ -1,5 +1,5 @@
#include "extractor/guidance/constants.hpp"
#include "extractor/guidance/turn_discovery.hpp"
#include "extractor/guidance/constants.hpp"
namespace osrm
{

View File

@ -2,9 +2,9 @@
#include "util/simple_logger.hpp"
#include <algorithm>
#include <boost/assert.hpp>
#include <cstddef>
#include <utility>
#include <boost/assert.hpp>
namespace osrm
{
@ -171,7 +171,6 @@ LaneDataVector handleRenamingSituations(const std::size_t none_index,
has_left |= modifier == DirectionModifier::SharpLeft;
}
// find missing tag and augment neighboring, if possible
if (none_index == 0)
{

View File

@ -52,8 +52,7 @@ LaneDataVector laneDataFromString(std::string turn_lane_string)
// count the number of lanes
const auto num_lanes = [](const std::string &turn_lane_string) {
return boost::numeric_cast<LaneID>(
std::count(turn_lane_string.begin(), turn_lane_string.end(), '|') + 1 +
std::count(turn_lane_string.begin(), turn_lane_string.end(), '&'));
std::count(turn_lane_string.begin(), turn_lane_string.end(), '|') + 1);
}(turn_lane_string);
const auto getNextTag = [](std::string &string, const char *separators) {
@ -103,7 +102,7 @@ LaneDataVector laneDataFromString(std::string turn_lane_string)
// FIXME this is a cucumber workaround, since escaping does not work properly in
// cucumber.js (see https://github.com/cucumber/cucumber-js/issues/417). Needs to be
// changed to "|" only, when the bug is fixed
auto lane = getNextTag(turn_lane_string, "|&");
auto lane = getNextTag(turn_lane_string, "|");
setLaneData(lane_map, lane, lane_nr);
++lane_nr;
} while (lane_nr < num_lanes);
@ -135,8 +134,9 @@ LaneDataVector::const_iterator findTag(const std::string &tag, const LaneDataVec
});
}
bool hasTag(const std::string &tag, const LaneDataVector &data){
return findTag(tag,data) != data.cend();
bool hasTag(const std::string &tag, const LaneDataVector &data)
{
return findTag(tag, data) != data.cend();
}
} // namespace lanes

View File

@ -1,8 +1,8 @@
#include "extractor/guidance/turn_lane_handler.hpp"
#include "extractor/guidance/constants.hpp"
#include "extractor/guidance/turn_discovery.hpp"
#include "extractor/guidance/turn_lane_handler.hpp"
#include "extractor/guidance/turn_lane_matcher.hpp"
#include "extractor/guidance/turn_lane_augmentation.hpp"
#include "extractor/guidance/turn_lane_matcher.hpp"
#include "util/simple_logger.hpp"
#include "util/typedefs.hpp"
@ -58,11 +58,9 @@ TurnLaneHandler::TurnLaneHandler(const util::NodeBasedDynamicGraph &node_based_g
*/
Intersection TurnLaneHandler::assignTurnLanes(const NodeID at,
const EdgeID via_edge,
Intersection intersection) const
Intersection intersection,
LaneDataIdMap &id_map) const
{
// initialize to invalid
for (auto &road : intersection)
road.turn.instruction.lane_tupel = {0, INVALID_LANEID};
const auto &data = node_based_graph.GetEdgeData(via_edge);
const auto turn_lane_string = data.lane_string_id != INVALID_LANE_STRINGID
? turn_lane_strings.GetNameForID(data.lane_string_id)
@ -89,17 +87,15 @@ Intersection TurnLaneHandler::assignTurnLanes(const NodeID at,
const std::size_t possible_entries = getNumberOfTurns(intersection);
// merge does not justify an instruction
const bool has_merge_lane = (hasTag("merge_to_left", lane_data) ||
hasTag("merge_to_right", lane_data));
const bool has_merge_lane =
(hasTag("merge_to_left", lane_data) || hasTag("merge_to_right", lane_data));
// Dead end streets that don't have any left-tag. This can happen due to the fallbacks for
// broken data/barriers.
const bool has_non_usable_u_turn =
(intersection[0].entry_allowed && !hasTag("none", lane_data) &&
!hasTag("left", lane_data) &&
!hasTag("sharp_left", lane_data) &&
!hasTag("reverse", lane_data) &&
lane_data.size() + 1 == possible_entries);
!hasTag("left", lane_data) && !hasTag("sharp_left", lane_data) &&
!hasTag("reverse", lane_data) && lane_data.size() + 1 == possible_entries);
if (has_merge_lane || has_non_usable_u_turn)
return std::move(intersection);
@ -118,7 +114,8 @@ Intersection TurnLaneHandler::assignTurnLanes(const NodeID at,
if (is_simple)
{
lane_data = handleNoneValueAtSimpleTurn(std::move(lane_data), intersection);
return simpleMatchTuplesToTurns(std::move(intersection), lane_data);
return simpleMatchTuplesToTurns(
std::move(intersection), lane_data, data.lane_string_id, id_map);
}
// if the intersection is not simple but we have lane data, we check for intersections with
// middle islands. We have two cases. The first one is providing lane data on the current
@ -138,7 +135,8 @@ Intersection TurnLaneHandler::assignTurnLanes(const NodeID at,
isSimpleIntersection(lane_data, intersection))
{
lane_data = handleNoneValueAtSimpleTurn(std::move(lane_data), intersection);
return simpleMatchTuplesToTurns(std::move(intersection), lane_data);
return simpleMatchTuplesToTurns(
std::move(intersection), lane_data, data.lane_string_id, id_map);
}
}
}
@ -148,7 +146,7 @@ Intersection TurnLaneHandler::assignTurnLanes(const NodeID at,
{
// acquire the lane data of a previous segment and, if possible, use it for the current
// intersection.
return handleTurnAtPreviousIntersection(at, via_edge, std::move(intersection));
return handleTurnAtPreviousIntersection(at, via_edge, std::move(intersection), id_map);
}
return std::move(intersection);
@ -158,7 +156,8 @@ Intersection TurnLaneHandler::assignTurnLanes(const NodeID at,
// actually take the turn, we need to look back to the edge we drove onto the intersection with.
Intersection TurnLaneHandler::handleTurnAtPreviousIntersection(const NodeID at,
const EdgeID via_edge,
Intersection intersection) const
Intersection intersection,
LaneDataIdMap &id_map) const
{
NodeID previous_node = SPECIAL_NODEID;
Intersection previous_intersection;
@ -176,6 +175,7 @@ Intersection TurnLaneHandler::handleTurnAtPreviousIntersection(const NodeID at,
previous_id,
previous_intersection))
return "";
BOOST_ASSERT(previous_id != SPECIAL_EDGEID);
const auto &previous_data = node_based_graph.GetEdgeData(previous_id);
auto previous_string = previous_data.lane_string_id != INVALID_LANE_STRINGID
@ -204,11 +204,13 @@ Intersection TurnLaneHandler::handleTurnAtPreviousIntersection(const NodeID at,
if (lane_data.empty())
return std::move(intersection);
const auto &previous_data = node_based_graph.GetEdgeData(previous_id);
const auto is_simple = isSimpleIntersection(lane_data, intersection);
if (is_simple)
{
lane_data = handleNoneValueAtSimpleTurn(std::move(lane_data), intersection);
return simpleMatchTuplesToTurns(std::move(intersection), lane_data);
return simpleMatchTuplesToTurns(
std::move(intersection), lane_data, previous_data.lane_string_id, id_map);
}
else
{
@ -227,14 +229,14 @@ Intersection TurnLaneHandler::handleTurnAtPreviousIntersection(const NodeID at,
isSimpleIntersection(lane_data, intersection))
{
lane_data = handleNoneValueAtSimpleTurn(std::move(lane_data), intersection);
return simpleMatchTuplesToTurns(std::move(intersection), lane_data);
return simpleMatchTuplesToTurns(
std::move(intersection), lane_data, previous_data.lane_string_id, id_map);
}
}
}
return std::move(intersection);
}
/* A simple intersection does not depend on the next intersection coming up. This is important
* for turn lanes, since traffic signals and/or segregated a intersection can influence the
* interpretation of turn-lanes at a given turn.
@ -296,7 +298,7 @@ bool TurnLaneHandler::isSimpleIntersection(const LaneDataVector &lane_data,
}
if (num_turns > lane_data.size() && intersection[0].entry_allowed &&
!( hasTag("reverse", lane_data) ||
!(hasTag("reverse", lane_data) ||
(lane_data.back().tag != "left" && lane_data.back().tag != "sharp_left")))
{
return false;
@ -417,7 +419,7 @@ std::pair<LaneDataVector, LaneDataVector> TurnLaneHandler::partitionLaneData(
return {turn_lane_data, {}};
}
std::size_t none_index = std::distance(turn_lane_data.begin(),findTag("none", turn_lane_data));
std::size_t none_index = std::distance(turn_lane_data.begin(), findTag("none", turn_lane_data));
// if the turn lanes are pull forward, we might have to add an additional straight tag
// did we find something that matches against the straightmost road?
@ -486,7 +488,9 @@ std::pair<LaneDataVector, LaneDataVector> TurnLaneHandler::partitionLaneData(
}
Intersection TurnLaneHandler::simpleMatchTuplesToTurns(Intersection intersection,
const LaneDataVector &lane_data) const
const LaneDataVector &lane_data,
const LaneStringID lane_string_id,
LaneDataIdMap &id_map) const
{
if (lane_data.empty() || !canMatchTrivially(intersection, lane_data))
return std::move(intersection);
@ -496,7 +500,8 @@ Intersection TurnLaneHandler::simpleMatchTuplesToTurns(Intersection intersection
return boost::starts_with(data.tag, "merge");
}) == 0);
return triviallyMatchLanesToTurns(std::move(intersection), lane_data, node_based_graph);
return triviallyMatchLanesToTurns(
std::move(intersection), lane_data, node_based_graph, lane_string_id, id_map);
}
} // namespace lanes

View File

@ -1,8 +1,11 @@
#include "extractor/guidance/toolkit.hpp"
#include "extractor/guidance/turn_lane_matcher.hpp"
#include "extractor/guidance/toolkit.hpp"
#include "util/guidance/toolkit.hpp"
#include <boost/assert.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <functional>
namespace osrm
{
@ -169,9 +172,27 @@ bool canMatchTrivially(const Intersection &intersection, const LaneDataVector &l
Intersection triviallyMatchLanesToTurns(Intersection intersection,
const LaneDataVector &lane_data,
const util::NodeBasedDynamicGraph &node_based_graph)
const util::NodeBasedDynamicGraph &node_based_graph,
const LaneStringID lane_string_id,
LaneDataIdMap &lane_data_to_id)
{
std::size_t road_index = 1, lane = 0;
const auto matchRoad = [&](ConnectedRoad &road, const TurnLaneData &data) {
LaneTupelIdPair key{{LaneID(data.to - data.from + 1), data.from}, lane_string_id};
auto lane_data_id = boost::numeric_cast<LaneDataID>(lane_data_to_id.size());
const auto it = lane_data_to_id.find(key);
if (it == lane_data_to_id.end())
lane_data_to_id.insert({key, lane_data_id});
else
lane_data_id = it->second;
// set lane id instead after the switch:
road.turn.lane_data_id = lane_data_id;
};
for (; road_index < intersection.size() && lane < lane_data.size(); ++road_index)
{
if (intersection[road_index].entry_allowed)
@ -185,8 +206,7 @@ Intersection triviallyMatchLanesToTurns(Intersection intersection,
if (TurnType::Suppressed == intersection[road_index].turn.instruction.type)
intersection[road_index].turn.instruction.type = TurnType::UseLane;
intersection[road_index].turn.instruction.lane_tupel = {
LaneID(lane_data[lane].to - lane_data[lane].from + 1), lane_data[lane].from};
matchRoad(intersection[road_index], lane_data[lane]);
++lane;
}
}
@ -209,8 +229,8 @@ Intersection triviallyMatchLanesToTurns(Intersection intersection,
intersection[u_turn].entry_allowed = true;
intersection[u_turn].turn.instruction.type = TurnType::Turn;
intersection[u_turn].turn.instruction.direction_modifier = DirectionModifier::UTurn;
intersection[u_turn].turn.instruction.lane_tupel = {
LaneID(lane_data.back().to - lane_data.back().from + 1), lane_data.back().from};
matchRoad(intersection[u_turn], lane_data.back());
}
return std::move(intersection);
}

View File

@ -147,6 +147,26 @@ int Storage::Run()
name_stream.read((char *)&number_of_chars, sizeof(unsigned));
shared_layout_ptr->SetBlockSize<char>(SharedDataLayout::NAME_CHAR_LIST, number_of_chars);
boost::filesystem::ifstream turn_string_stream(config.turn_lane_string_path, std::ios::binary);
if (!turn_string_stream)
{
throw util::exception("Could not open " + config.turn_lane_string_path.string() +
" for reading.");
}
unsigned turn_string_blocks = 0;
turn_string_stream.read((char *)&turn_string_blocks, sizeof(unsigned));
shared_layout_ptr->SetBlockSize<unsigned>(SharedDataLayout::TURN_STRING_OFFSETS,
turn_string_blocks);
shared_layout_ptr->SetBlockSize<typename util::RangeTable<16, true>::BlockT>(
SharedDataLayout::TURN_STRING_BLOCKS, turn_string_blocks);
BOOST_ASSERT_MSG(0 != turn_string_blocks, "turn string file broken");
unsigned number_of_turn_string_chars = 0;
turn_string_stream.read((char *)&number_of_turn_string_chars, sizeof(unsigned));
shared_layout_ptr->SetBlockSize<char>(SharedDataLayout::TURN_STRING_CHAR_LIST,
number_of_turn_string_chars);
// Loading information for original edges
boost::filesystem::ifstream edges_input_stream(config.edges_data_path, std::ios::binary);
if (!edges_input_stream)
@ -166,6 +186,8 @@ int Storage::Run()
number_of_original_edges);
shared_layout_ptr->SetBlockSize<extractor::guidance::TurnInstruction>(
SharedDataLayout::TURN_INSTRUCTION, number_of_original_edges);
shared_layout_ptr->SetBlockSize<LaneDataID>(SharedDataLayout::LANE_DATA_ID,
number_of_original_edges);
shared_layout_ptr->SetBlockSize<EntryClassID>(SharedDataLayout::ENTRY_CLASSID,
number_of_original_edges);
@ -368,6 +390,14 @@ int Storage::Run()
sizeof(bearing_class_table[0]) * num_bearings);
shared_layout_ptr->SetBlockSize<DiscreteBearing>(SharedDataLayout::BEARING_VALUES,
num_bearings);
// Loading turn lane data
boost::filesystem::ifstream lane_data_stream(config.turn_lane_data_path, std::ios::binary);
std::uint64_t lane_tupel_count = 0;
lane_data_stream.read(reinterpret_cast<char *>(&lane_tupel_count), sizeof(lane_tupel_count));
shared_layout_ptr->SetBlockSize<util::guidance::LaneTupelIdPair>(
SharedDataLayout::TURN_LANE_DATA, lane_tupel_count);
if (!static_cast<bool>(intersection_stream))
throw util::exception("Failed to read bearing values from " +
config.intersection_class_path.string());
@ -436,9 +466,54 @@ int Storage::Run()
name_stream.read(name_char_ptr,
shared_layout_ptr->GetBlockSize(SharedDataLayout::NAME_CHAR_LIST));
}
name_stream.close();
// Loading turn lane strings
unsigned *turn_string_offsets_ptr = shared_layout_ptr->GetBlockPtr<unsigned, true>(
shared_memory_ptr, SharedDataLayout::TURN_STRING_OFFSETS);
if (shared_layout_ptr->GetBlockSize(SharedDataLayout::TURN_STRING_OFFSETS) > 0)
{
turn_string_stream.read(
(char *)turn_string_offsets_ptr,
shared_layout_ptr->GetBlockSize(SharedDataLayout::TURN_STRING_OFFSETS));
}
// make sure do write canary...
auto *turn_lane_data_ptr =
shared_layout_ptr->GetBlockPtr<util::guidance::LaneTupelIdPair, true>(
shared_memory_ptr, SharedDataLayout::TURN_LANE_DATA);
if (shared_layout_ptr->GetBlockSize(SharedDataLayout::TURN_LANE_DATA) > 0)
{
lane_data_stream.read(reinterpret_cast<char *>(turn_lane_data_ptr),
shared_layout_ptr->GetBlockSize(SharedDataLayout::TURN_LANE_DATA));
}
lane_data_stream.close();
unsigned *turn_string_blocks_ptr = shared_layout_ptr->GetBlockPtr<unsigned, true>(
shared_memory_ptr, SharedDataLayout::TURN_STRING_BLOCKS);
if (shared_layout_ptr->GetBlockSize(SharedDataLayout::TURN_STRING_BLOCKS) > 0)
{
turn_string_stream.read(
(char *)turn_string_blocks_ptr,
shared_layout_ptr->GetBlockSize(SharedDataLayout::TURN_STRING_BLOCKS));
}
char *turn_string_char_ptr = shared_layout_ptr->GetBlockPtr<char, true>(
shared_memory_ptr, SharedDataLayout::TURN_STRING_CHAR_LIST);
turn_string_stream.read((char *)&temp_length, sizeof(unsigned));
BOOST_ASSERT_MSG(temp_length ==
shared_layout_ptr->GetBlockSize(SharedDataLayout::TURN_STRING_CHAR_LIST),
"turn string file corrupted!");
if (shared_layout_ptr->GetBlockSize(SharedDataLayout::TURN_STRING_CHAR_LIST) > 0)
{
turn_string_stream.read(
turn_string_char_ptr,
shared_layout_ptr->GetBlockSize(SharedDataLayout::TURN_STRING_CHAR_LIST));
}
turn_string_stream.close();
// load original edge information
NodeID *via_node_ptr = shared_layout_ptr->GetBlockPtr<NodeID, true>(
shared_memory_ptr, SharedDataLayout::VIA_NODE_LIST);
@ -450,6 +525,9 @@ int Storage::Run()
shared_layout_ptr->GetBlockPtr<extractor::TravelMode, true>(shared_memory_ptr,
SharedDataLayout::TRAVEL_MODE);
LaneDataID *lane_data_id_ptr = shared_layout_ptr->GetBlockPtr<LaneDataID, true>(
shared_memory_ptr, SharedDataLayout::LANE_DATA_ID);
extractor::guidance::TurnInstruction *turn_instructions_ptr =
shared_layout_ptr->GetBlockPtr<extractor::guidance::TurnInstruction, true>(
shared_memory_ptr, SharedDataLayout::TURN_INSTRUCTION);
@ -464,6 +542,7 @@ int Storage::Run()
via_node_ptr[i] = current_edge_data.via_node;
name_id_ptr[i] = current_edge_data.name_id;
travel_mode_ptr[i] = current_edge_data.travel_mode;
lane_data_id_ptr[i] = current_edge_data.lane_data_id;
turn_instructions_ptr[i] = current_edge_data.turn_instruction;
entry_class_id_ptr[i] = current_edge_data.entry_classid;
}
@ -514,7 +593,8 @@ int Storage::Run()
shared_memory_ptr, SharedDataLayout::DATASOURCE_NAME_DATA);
if (shared_layout_ptr->GetBlockSize(SharedDataLayout::DATASOURCE_NAME_DATA) > 0)
{
std::cout << "Copying " << (m_datasource_name_data.end() - m_datasource_name_data.begin())
util::SimpleLogger().Write()
<< "Copying " << (m_datasource_name_data.end() - m_datasource_name_data.begin())
<< " chars into name data ptr\n";
std::copy(
m_datasource_name_data.begin(), m_datasource_name_data.end(), datasource_name_data_ptr);

View File

@ -16,7 +16,8 @@ StorageConfig::StorageConfig(const boost::filesystem::path &base)
datasource_names_path{base.string() + ".datasource_names"},
datasource_indexes_path{base.string() + ".datasource_indexes"},
names_data_path{base.string() + ".names"}, properties_path{base.string() + ".properties"},
intersection_class_path{base.string() + ".icd"}
intersection_class_path{base.string() + ".icd"}, turn_lane_data_path{base.string() + ".tld"},
turn_lane_string_path{base.string() + ".tls"}
{
}

View File

@ -11,8 +11,7 @@ namespace util
{
namespace guidance
{
LaneTupel::LaneTupel()
: lanes_in_turn(0), first_lane_from_the_right(INVALID_LANEID)
LaneTupel::LaneTupel() : lanes_in_turn(0), first_lane_from_the_right(INVALID_LANEID)
{
// basic constructor, set everything to zero
}

View File

@ -36,11 +36,13 @@ NameTable::NameTable(const std::string &filename)
}
else
{
util::SimpleLogger().Write(logINFO) << "list of street names is empty in construction of name table from: \"" << filename << "\"";
util::SimpleLogger().Write(logINFO)
<< "list of street names is empty in construction of name table from: \"" << filename
<< "\"";
}
if (!name_stream)
throw exception("Failed to read " + std::to_string(number_of_chars) +
" characters from " + filename);
throw exception("Failed to read " + std::to_string(number_of_chars) + " characters from " +
filename);
}
std::string NameTable::GetNameForID(const unsigned name_id) const

View File

@ -30,14 +30,94 @@ BOOST_AUTO_TEST_CASE(long_road_test)
std::vector<InputEdge> edges = {
// src, tgt, dist, edge_id, name_id, access_restricted, fwd, bkwd, roundabout, travel_mode
{0, 1, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID},
{1, 0, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID},
{1, 2, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID},
{2, 1, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID},
{2, 3, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID},
{3, 2, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID},
{3, 4, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID},
{4, 3, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID}};
{0,
1,
1,
SPECIAL_EDGEID,
0,
false,
false,
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
{1,
0,
1,
SPECIAL_EDGEID,
0,
false,
false,
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
{1,
2,
1,
SPECIAL_EDGEID,
0,
false,
false,
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
{2,
1,
1,
SPECIAL_EDGEID,
0,
false,
false,
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
{2,
3,
1,
SPECIAL_EDGEID,
0,
false,
false,
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
{3,
2,
1,
SPECIAL_EDGEID,
0,
false,
false,
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
{3,
4,
1,
SPECIAL_EDGEID,
0,
false,
false,
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
{4,
3,
1,
SPECIAL_EDGEID,
0,
false,
false,
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID}};
BOOST_ASSERT(edges[0].data.IsCompatibleTo(edges[2].data));
BOOST_ASSERT(edges[2].data.IsCompatibleTo(edges[4].data));
@ -69,18 +149,138 @@ BOOST_AUTO_TEST_CASE(loop_test)
std::vector<InputEdge> edges = {
// src, tgt, dist, edge_id, name_id, access_restricted, fwd, bkwd, roundabout, travel_mode
{0, 1, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID},
{0, 5, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID},
{1, 0, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID},
{1, 2, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID},
{2, 1, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID},
{2, 3, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID},
{3, 2, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID},
{3, 4, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID},
{4, 3, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID},
{4, 5, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID},
{5, 0, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID},
{5, 4, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID},
{0,
1,
1,
SPECIAL_EDGEID,
0,
false,
false,
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
{0,
5,
1,
SPECIAL_EDGEID,
0,
false,
false,
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
{1,
0,
1,
SPECIAL_EDGEID,
0,
false,
false,
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
{1,
2,
1,
SPECIAL_EDGEID,
0,
false,
false,
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
{2,
1,
1,
SPECIAL_EDGEID,
0,
false,
false,
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
{2,
3,
1,
SPECIAL_EDGEID,
0,
false,
false,
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
{3,
2,
1,
SPECIAL_EDGEID,
0,
false,
false,
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
{3,
4,
1,
SPECIAL_EDGEID,
0,
false,
false,
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
{4,
3,
1,
SPECIAL_EDGEID,
0,
false,
false,
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
{4,
5,
1,
SPECIAL_EDGEID,
0,
false,
false,
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
{5,
0,
1,
SPECIAL_EDGEID,
0,
false,
false,
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
{5,
4,
1,
SPECIAL_EDGEID,
0,
false,
false,
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
};
BOOST_ASSERT(edges.size() == 12);
@ -124,12 +324,72 @@ BOOST_AUTO_TEST_CASE(t_intersection)
std::vector<InputEdge> edges = {
// src, tgt, dist, edge_id, name_id, access_restricted, fwd, bkwd, roundabout, travel_mode
{0, 1, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID},
{1, 0, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID},
{1, 2, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID},
{1, 3, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID},
{2, 1, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID},
{3, 1, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID},
{0,
1,
1,
SPECIAL_EDGEID,
0,
false,
false,
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
{1,
0,
1,
SPECIAL_EDGEID,
0,
false,
false,
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
{1,
2,
1,
SPECIAL_EDGEID,
0,
false,
false,
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
{1,
3,
1,
SPECIAL_EDGEID,
0,
false,
false,
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
{2,
1,
1,
SPECIAL_EDGEID,
0,
false,
false,
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
{3,
1,
1,
SPECIAL_EDGEID,
0,
false,
false,
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
};
BOOST_ASSERT(edges[0].data.IsCompatibleTo(edges[1].data));
@ -160,10 +420,50 @@ BOOST_AUTO_TEST_CASE(street_name_changes)
std::vector<InputEdge> edges = {
// src, tgt, dist, edge_id, name_id, access_restricted, fwd, bkwd, roundabout, travel_mode
{0, 1, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID},
{1, 0, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID},
{1, 2, 1, SPECIAL_EDGEID, 1, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID},
{2, 1, 1, SPECIAL_EDGEID, 1, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID},
{0,
1,
1,
SPECIAL_EDGEID,
0,
false,
false,
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
{1,
0,
1,
SPECIAL_EDGEID,
0,
false,
false,
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
{1,
2,
1,
SPECIAL_EDGEID,
1,
false,
false,
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
{2,
1,
1,
SPECIAL_EDGEID,
1,
false,
false,
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
};
BOOST_ASSERT(edges[0].data.IsCompatibleTo(edges[1].data));
@ -190,10 +490,50 @@ BOOST_AUTO_TEST_CASE(direction_changes)
std::vector<InputEdge> edges = {
// src, tgt, dist, edge_id, name_id, access_restricted, fwd, bkwd, roundabout, travel_mode
{0, 1, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID},
{1, 0, 1, SPECIAL_EDGEID, 0, false, true, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID},
{1, 2, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID},
{2, 1, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID},
{0,
1,
1,
SPECIAL_EDGEID,
0,
false,
false,
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
{1,
0,
1,
SPECIAL_EDGEID,
0,
false,
true,
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
{1,
2,
1,
SPECIAL_EDGEID,
0,
false,
false,
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
{2,
1,
1,
SPECIAL_EDGEID,
0,
false,
false,
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
};
Graph graph(5, edges);

View File

@ -180,6 +180,10 @@ class MockDataFacade final : public engine::datafacade::BaseDataFacade
BearingClassID GetBearingClassID(const NodeID /*id*/) const override { return 0; };
EntryClassID GetEntryClassID(const EdgeID /*id*/) const override { return 0; }
bool hasLaneData(const EdgeID /*id*/) const { return true; };
util::guidance::LaneTupelIdPair GetLaneData(const EdgeID /*id*/) const { return {{0, 0}, 0}; }
std::string GetTurnStringForID(const LaneStringID /*lane_string_id*/) const { return ""; };
util::guidance::BearingClass
GetBearingClass(const BearingClassID /*bearing_class_id*/) const override
{