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
@ -46,7 +46,7 @@ DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
IncludeCategories:
IncludeCategories:
- Regex: '^<'
Priority: 3
- Regex: '^"(osrm|util|engine|extract|contract)/'

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

@ -25,9 +25,9 @@ Feature: Turn Lane Guidance
| de | |
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 |
| waypoints | route | turns | lanes | # |
| 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
@ -48,9 +48,9 @@ Feature: Turn Lane Guidance
| dy | | | YSt |
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, |
| waypoints | route | turns | lanes |
| 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
@ -71,9 +71,9 @@ Feature: Turn Lane Guidance
| dy | | | EYSt |
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, |
| waypoints | route | turns | lanes |
| 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
@ -92,8 +92,8 @@ Feature: Turn Lane Guidance
| cy | | Hwy | motorway | |
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, |
| waypoints | route | turns | lanes |
| 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
@ -114,9 +114,9 @@ Feature: Turn Lane Guidance
| dj | | 2 | motorway_link | yes | dj |
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, |
| waypoints | route | turns | lanes |
| 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
@ -135,9 +135,9 @@ Feature: Turn Lane Guidance
| cj | | 1 | motorway_link | yes | xbcj |
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, |
| waypoints | route | turns | lanes |
| 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
@ -160,9 +160,8 @@ Feature: Turn Lane Guidance
| de | | de |
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, |
| waypoints | route | turns | lanes |
| 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
@ -184,9 +183,8 @@ Feature: Turn Lane Guidance
| de | | de |
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, |
| waypoints | route | turns | lanes |
| 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
@ -208,9 +206,8 @@ Feature: Turn Lane Guidance
| de | | de |
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, |
| waypoints | route | turns | lanes |
| 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
@ -232,9 +229,8 @@ Feature: Turn Lane Guidance
| de | | de |
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, |
| waypoints | route | turns | lanes |
| 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
@ -260,10 +256,10 @@ Feature: Turn Lane Guidance
| ef | | ef |
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, |
| waypoints | route | turns | lanes |
| 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 |
@ -284,11 +280,11 @@ Feature: Turn Lane Guidance
| feg | | tertiary | fourth |
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, |
| waypoints | route | turns | lanes |
| 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 |
@ -309,6 +305,6 @@ Feature: Turn Lane Guidance
| feg | | tertiary | fourth |
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, |
| waypoints | route | turns | lanes |
| 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

@ -20,11 +20,11 @@ Feature: Turn Lane Guidance
| bd | | | left\|right | right |
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, |
| waypoints | route | turns | lanes |
| 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
@ -40,13 +40,13 @@ Feature: Turn Lane Guidance
| be | | | | left |
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, |
| waypoints | route | turns | lanes |
| 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
@ -62,10 +62,10 @@ Feature: Turn Lane Guidance
| be | | | | left |
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, |
| waypoints | route | turns | lanes |
| 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
@ -81,11 +81,11 @@ Feature: Turn Lane Guidance
| be | | | left |
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, |
| from | to | bearings | route | turns | lanes |
| 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
@ -103,12 +103,12 @@ Feature: Turn Lane Guidance
| bd | turn | | |
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, |
| waypoints | route | turns | lanes |
| 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
@ -170,8 +204,8 @@ Feature: Turn Lane Guidance
| cf | cross | | yes |
When I route I should get
| waypoints | route | turns | lanes |
| a,j | road,cross,cross | depart,turn right,arrive | ,0, |
| waypoints | route | turns | lanes |
| 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
@ -188,9 +222,9 @@ Feature: Turn Lane Guidance
| ce | turn | |
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, |
| waypoints | route | turns | lanes |
| 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
@ -208,11 +242,11 @@ Feature: Turn Lane Guidance
| hk | second-turn | | |
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, |
| waypoints | route | turns | lanes |
| 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
@ -227,8 +261,8 @@ Feature: Turn Lane Guidance
| cf | turn | | |
When I route I should get
| waypoints | route | turns | lanes |
| a,f | road,turn,turn | depart,turn left,arrive | ,1, |
| waypoints | route | turns | lanes |
| 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
@ -245,9 +279,9 @@ Feature: Turn Lane Guidance
| bg | right | | no |
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, |
| waypoints | route | turns | lanes |
| 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
@ -264,11 +298,12 @@ Feature: Turn Lane Guidance
| bg | right | | no |
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, |
| waypoints | route | turns | lanes |
| 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, |
Scenario: Narrowing Turn Lanes
@todo @bug
Scenario: Narrowing Turn Lanes
Given the node map
| | | | | g | |
| | | | | | |
@ -285,12 +320,12 @@ Feature: Turn Lane Guidance
| cf | right | |
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, |
| waypoints | route | turns | lanes |
| 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
Scenario: Turn at a traffic light
Given the node map
| a | b | c | d |
| | | e | |
@ -307,12 +342,12 @@ Feature: Turn Lane Guidance
| ce | turn | |
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, |
| waypoints | route | turns | lanes |
| 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, |
Scenario: Theodor Heuss Platz
@bug @todo
Scenario: Theodor Heuss Platz
Given the node map
| | | | i | o | | | l | |
| | | b | | | | a | | m |
@ -343,10 +378,10 @@ Feature: Turn Lane Guidance
| hl | top-right-out | | | yes | secondary |
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,o | top,top,top | depart,roundabout-exit-5,arrive | ,, |
| waypoints | route | turns | lanes |
| 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
Given the node map
@ -371,9 +406,9 @@ Feature: Turn Lane Guidance
| restriction | bc | fdcg | c | no_right_turn |
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, |
| waypoints | route | turns | lanes |
| 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
@ -394,11 +429,11 @@ Feature: Turn Lane Guidance
| gdeh | cross | | no | primary |
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, |
| from | to | bearings | route | turns | lanes |
| 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
@ -419,12 +454,13 @@ Feature: Turn Lane Guidance
| cf | left | | yes | primary |
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, |
| waypoints | route | turns | lanes |
| 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, |
Scenario: Passing Through a Roundabout
@bug @todo
Scenario: Passing Through a Roundabout
Given the node map
| | | h | | g | | |
| | a | | | | f | k |
@ -466,9 +502,9 @@ Feature: Turn Lane Guidance
| ce | cross | | primary |
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, |
| waypoints | route | turns | lanes |
| 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
@ -482,11 +518,12 @@ Feature: Turn Lane Guidance
| ce | ramp | | motorway_link |
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, |
| waypoints | route | turns | lanes |
| 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, |
Scenario: Turning Off Ramp
@bug @todo
Scenario: Turning Off Ramp
Given the node map
| | a | |
| d | c | b |
@ -502,12 +539,12 @@ Feature: Turn Lane Guidance
| fh | on | | motorway_link | yes |
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,h | | | |
| waypoints | route | turns | lanes |
| 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
Scenario: Off Ramp In a Turn
Given the node map
| a | | | | | | | | | | | |
| | | | | | | | | | | | |
@ -521,11 +558,11 @@ Feature: Turn Lane Guidance
| bd | ramp | | motorway_link | yes |
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, |
| waypoints | route | turns | lanes |
| 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
Scenario: Reverse Lane in Segregated Road
Given the node map
| h | | | | | g | | | | | | f |
| | | | | | | | e | | | | |
@ -540,8 +577,8 @@ Feature: Turn Lane Guidance
| fgh | road | | primary | yes |
When I route I should get
| waypoints | route | turns | lanes |
| a,h | road,road,road | depart,continue uturn,arrive | ,2, |
| waypoints | route | turns | lanes |
| 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
@ -558,8 +595,8 @@ Feature: Turn Lane Guidance
| fgh | road | | primary | yes |
When I route I should get
| waypoints | route | turns | lanes |
| a,h | road,road,road | depart,continue uturn,arrive | ,2, |
| waypoints | route | turns | lanes |
| 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
@ -578,8 +615,8 @@ Feature: Turn Lane Guidance
| ji | park | | service | no |
When I route I should get
| waypoints | route | turns | lanes |
| a,h | road,road,road | depart,continue uturn,arrive | ,2, |
| waypoints | route | turns | lanes |
| 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
@ -596,11 +633,11 @@ Feature: Turn Lane Guidance
| cf | secondary | bottom | |
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,, |
| waypoints | turns | route | lanes |
| 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
Scenario: Merge Lanes Onto Freeway
Given the node map
| a | | | b | c |
| | d | | | |
@ -611,10 +648,10 @@ Feature: Turn Lane Guidance
| db | motorway_link | ramp | slight_right\|slight_right |
When I route I should get
| waypoints | turns | route | lanes |
| d,c | depart,merge slight left,arrive | ramp,Hwy,Hwy | ,0 1, |
| waypoints | turns | route | lanes |
| 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
Scenario: Fork on motorway links - don't fork on through but use lane
Given the node map
| i | | | | | a |
| j | | c | b | | x |
@ -628,6 +665,6 @@ Feature: Turn Lane Guidance
| ab | on | motorway_link | |
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, |
| waypoints | route | turns | lanes |
| 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,9 +114,12 @@ Intersection IntersectionGenerator::getConnectedRoads(const NodeID from_node,
has_uturn_edge = true;
}
intersection.push_back(ConnectedRoad(
TurnOperation{onto_edge, angle, {TurnType::Invalid, DirectionModifier::UTurn}},
turn_is_valid));
intersection.push_back(
ConnectedRoad(TurnOperation{onto_edge,
angle,
{TurnType::Invalid, DirectionModifier::UTurn},
INVALID_LANE_DATAID},
turn_is_valid));
}
// We hit the case of a street leading into nothing-ness. Since the code here assumes that this
@ -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"
@ -40,7 +40,7 @@ TurnLaneHandler::TurnLaneHandler(const util::NodeBasedDynamicGraph &node_based_g
}
/*
Turn lanes are given in the form of strings that closely correspond to the direction modifiers
Turn lanes are given in the form of strings that closely correspond to the direction modifiers
we use for our turn types. However, we still cannot simply perform a 1:1 assignment.
This function parses the turn_lane_strings of a format that describes an intersection as:
@ -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,8 +593,9 @@ 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())
<< " chars into name data ptr\n";
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
{