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 Language: Cpp
# BasedOnStyle: LLVM # BasedOnStyle: LLVM
AccessModifierOffset: -2 AccessModifierOffset: -2
AlignAfterOpenBracket: Align AlignAfterOpenBracket: true
AlignConsecutiveAssignments: false AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false AlignConsecutiveDeclarations: false
AlignEscapedNewlinesLeft: false AlignEscapedNewlinesLeft: false
@ -46,7 +46,7 @@ DerivePointerAlignment: false
DisableFormat: false DisableFormat: false
ExperimentalAutoDetectBinPacking: false ExperimentalAutoDetectBinPacking: false
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
IncludeCategories: IncludeCategories:
- Regex: '^<' - Regex: '^<'
Priority: 3 Priority: 3
- Regex: '^"(osrm|util|engine|extract|contract)/' - Regex: '^"(osrm|util|engine|extract|contract)/'

1
.gitignore vendored
View File

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

View File

@ -1,7 +1,7 @@
# 5.3.0 # 5.3.0
- API - API
- Introduces new `TurnType` in the form of `use lane`. The type indicates that you have to stick to a lane without turning - 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 - Infrastructure
- BREAKING: The new turn type changes the turn-type order. This breaks the **data format**. - 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)| | 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. - `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. - `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. - `destinations`: The destinations of the way. Will be `undefined` if there are no destinations.
- `mode`: A string signifying the mode of transportation. - `mode`: A string signifying the mode of transportation.
- `maneuver`: A `StepManeuver` object representing the maneuver. - `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 - `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 #### Example
``` ```
@ -450,17 +455,24 @@ step.
"distance":152.3, "distance":152.3,
"duration":15.6, "duration":15.6,
"name":"Lortzingstraße", "name":"Lortzingstraße",
"lanes":{
{"marked":"left",
"take":"false"},
{"marked":"right",
"take":"true"}
},
"maneuver":{ "maneuver":{
"type":"depart", "type":"turn",
"modifier":"left" "modifier":"right"
}, },
"geometry":"{lu_IypwpAVrAvAdI", "geometry":"{lu_IypwpAVrAvAdI",
"mode":"driving", "mode":"driving",
"intersections":[ "intersections":[
{"location":[13.39677,52.54366], {"location":[13.39677,52.54366],
"in":2,
"out":1, "out":1,
"bearings":[66,246], "bearings":[10,184,270],
"entry":["true","true"]}, "entry":[false,"true","true"]},
{"location":[13.394718,52.543096], {"location":[13.394718,52.543096],
"in":0, "in":0,
"out":2, "out":2,

View File

@ -25,9 +25,9 @@ Feature: Turn Lane Guidance
| de | | | de | |
When I route I should get When I route I should get
| waypoints | route | turns | lanes | # | | waypoints | route | turns | lanes | # |
| a,d | ab,bc,cd,cd | depart,turn right,turn left,arrive | ,1 2,1 2, | 2 hops | | a,d | ab,bc,cd,cd | depart,turn right,turn left,arrive | ,through:false right:true right:true right:false,left:true left:true through:false, | 2 hops |
| a,e | ab,bc,cd,de,de | depart,turn right,turn left,turn right,arrive | ,1,1,0, | 3 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 @anticipate
Scenario: Anticipate Lane Change for quick same direction turns, staying on the same street Scenario: Anticipate Lane Change for quick same direction turns, staying on the same street
@ -48,9 +48,9 @@ Feature: Turn Lane Guidance
| dy | | | YSt | | dy | | | YSt |
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | waypoints | route | turns | lanes |
| a,e | MySt,MySt,MySt,MySt | depart,continue right,end of road right,arrive | ,0,0, | | 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 | ,2,1, | | 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 @anticipate
Scenario: Anticipate Lane Change for quick same direction turns, changing between streets Scenario: Anticipate Lane Change for quick same direction turns, changing between streets
@ -71,9 +71,9 @@ Feature: Turn Lane Guidance
| dy | | | EYSt | | dy | | | EYSt |
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | waypoints | route | turns | lanes |
| a,e | AXSt,BDSt,EYSt,EYSt | depart,turn right,end of road right,arrive | ,0,0, | | 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 | ,2,1, | | 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 @anticipate
@ -92,8 +92,8 @@ Feature: Turn Lane Guidance
| cy | | Hwy | motorway | | | cy | | Hwy | motorway | |
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | waypoints | route | turns | lanes |
| a,d | On,Hwy,Off,Off | depart,merge slight right,off ramp right,arrive | ,0,0, | | a,d | On,Hwy,Off,Off | depart,merge slight right,off ramp right,arrive | ,slight_left:false slight_left:true,through:false slight_right:true, |
@anticipate @anticipate
@ -114,9 +114,9 @@ Feature: Turn Lane Guidance
| dj | | 2 | motorway_link | yes | dj | | dj | | 2 | motorway_link | yes | dj |
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | waypoints | route | turns | lanes |
| a,i | abx,bcd,di,di | depart,off ramp right,fork slight left,arrive | ,0 1,1 2, | | 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 | ,0 1,0 1, | | 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 @anticipate
@ -135,9 +135,9 @@ Feature: Turn Lane Guidance
| cj | | 1 | motorway_link | yes | xbcj | | cj | | 1 | motorway_link | yes | xbcj |
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | waypoints | route | turns | lanes |
| a,i | ab,xbcj,ci,ci | depart,merge slight left,turn slight right,arrive | ,,0, | | 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 | ,,1, | | a,j | ab,xbcj,xbcj,xbcj | depart,merge slight left,use lane straight,arrive | ,,none:true slight_right:false, |
@anticipate @anticipate
@ -160,9 +160,8 @@ Feature: Turn Lane Guidance
| de | | de | | de | | de |
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | waypoints | route | turns | lanes |
| a,e | abx,bcy,cdz,de,de | depart,turn right,turn left,turn right,arrive | ,1,1,0, | | a,e | abx,bcy,cdz,de,de | depart,turn right,turn left,turn right,arrive | ,through:false right:false right:true right:false,left:false left:true through:false,through:false right:true, |
@anticipate @anticipate
Scenario: Lane anticipation for fan-out Scenario: Lane anticipation for fan-out
@ -184,9 +183,8 @@ Feature: Turn Lane Guidance
| de | | de | | de | | de |
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | waypoints | route | turns | lanes |
| a,e | abx,bcy,cdz,de,de | depart,turn right,turn left,turn right,arrive | ,0,1 2,0 1 2, | | a,e | abx,bcy,cdz,de,de | depart,turn right,turn left,turn right,arrive | ,through:false right:true,left:true left:true through:false,through:false right:true right:true right:true, |
@anticipate @anticipate
Scenario: Lane anticipation for fan-in followed by fan-out Scenario: Lane anticipation for fan-in followed by fan-out
@ -208,9 +206,8 @@ Feature: Turn Lane Guidance
| de | | de | | de | | de |
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | waypoints | route | turns | lanes |
| a,e | abx,bcy,cdz,de,de | depart,turn right,turn left,turn right,arrive | ,1 2,1 2,0 1 2, | | a,e | abx,bcy,cdz,de,de | depart,turn right,turn left,turn right,arrive | ,through:false right:true right:true right:false,left:true left:true through:false,through:false right:true right:true right:true, |
@anticipate @anticipate
Scenario: Lane anticipation for fan-out followed by fan-in Scenario: Lane anticipation for fan-out followed by fan-in
@ -232,9 +229,8 @@ Feature: Turn Lane Guidance
| de | | de | | de | | de |
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | waypoints | route | turns | lanes |
| a,e | abx,bcy,cdz,de,de | depart,turn right,turn left,turn right,arrive | ,0,1,0, | | a,e | abx,bcy,cdz,de,de | depart,turn right,turn left,turn right,arrive | ,through:false right:true,left:false left:true through:false,through:false right:true, |
@anticipate @anticipate
Scenario: Lane anticipation for multiple hops with same number of lanes Scenario: Lane anticipation for multiple hops with same number of lanes
@ -260,10 +256,10 @@ Feature: Turn Lane Guidance
| ef | | ef | | ef | | ef |
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | waypoints | route | turns | lanes |
| a,f | abx,bcy,cdz,dew,ef,ef | depart,turn right,turn left,turn right,turn left,arrive | ,1,1,1,1, | | a,f | abx,bcy,cdz,dew,ef,ef | depart,turn right,turn left,turn right,turn left,arrive | ,through:false right:false right:true right:false,left:false left:true through:false,through:false right:true right:false,left:true through:false, |
@anticipate @anticipate @bug @todo
Scenario: Tripple Right keeping Left Scenario: Tripple Right keeping Left
Given the node map Given the node map
| a | | | | b | | i | | a | | | | b | | i |
@ -284,11 +280,11 @@ Feature: Turn Lane Guidance
| feg | | tertiary | fourth | | feg | | tertiary | fourth |
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | 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,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 | ,0 1,0 1,0 1,0 1, | | 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 Scenario: Tripple Left keeping Right
Given the node map Given the node map
| i | | b | | | | a | | i | | b | | | | a |
@ -309,6 +305,6 @@ Feature: Turn Lane Guidance
| feg | | tertiary | fourth | | feg | | tertiary | fourth |
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | 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,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 | ,0 1,0 1,0 1,0 1, | | 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 | | bd | | | left\|right | right |
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | waypoints | route | turns | lanes |
| a,c | in,straight,straight | depart,new name straight,arrive | ,1, | | a,c | in,straight,straight | depart,new name straight,arrive | ,through:true right:false, |
| a,d | in,right,right | depart,turn right,arrive | ,0, | | a,d | in,right,right | depart,turn right,arrive | ,through:false right:true, |
| c,a | straight,in,in | depart,new name straight,arrive | ,0 1 2, | | 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 | ,3, | | c,d | straight,right,right | depart,turn left,arrive | ,left:true through:false none:false none:false, |
Scenario: Basic Turn Lane 4-Way Turn Scenario: Basic Turn Lane 4-Way Turn
Given the node map Given the node map
@ -40,13 +40,13 @@ Feature: Turn Lane Guidance
| be | | | | left | | be | | | | left |
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | waypoints | route | turns | lanes |
| a,c | in,straight,straight | depart,new name straight,arrive | ,1, | | a,c | in,straight,straight | depart,new name straight,arrive | ,none:true right:false, |
| a,d | in,right,right | depart,turn right,arrive | ,0, | | a,d | in,right,right | depart,turn right,arrive | ,none:false right:true, |
| a,e | in,left,left | depart,turn left,arrive | ,1, | | a,e | in,left,left | depart,turn left,arrive | ,none:true right:false, |
| d,a | right,in,in | depart,turn left,arrive | ,1, | | d,a | right,in,in | depart,turn left,arrive | ,left:true none:false, |
| d,e | right,left,left | depart,new name straight,arrive | ,0, | | d,e | right,left,left | depart,new name straight,arrive | ,left:false none:true, |
| d,c | right,straight,straight | depart,turn right,arrive | ,0, | | d,c | right,straight,straight | depart,turn right,arrive | ,left:false none:true, |
Scenario: Basic Turn Lane 4-Way Turn using none Scenario: Basic Turn Lane 4-Way Turn using none
Given the node map Given the node map
@ -62,10 +62,10 @@ Feature: Turn Lane Guidance
| be | | | | left | | be | | | | left |
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | waypoints | route | turns | lanes |
| a,c | in,straight,straight | depart,new name straight,arrive | ,1, | | a,c | in,straight,straight | depart,new name straight,arrive | ,none:true right:false, |
| a,d | in,right,right | depart,turn right,arrive | ,0, | | a,d | in,right,right | depart,turn right,arrive | ,none:false right:true, |
| a,e | in,left,left | depart,turn left,arrive | ,1, | | a,e | in,left,left | depart,turn left,arrive | ,none:true right:false, |
Scenario: Basic Turn Lane 4-Way With U-Turn Lane Scenario: Basic Turn Lane 4-Way With U-Turn Lane
Given the node map Given the node map
@ -81,11 +81,11 @@ Feature: Turn Lane Guidance
| be | | | left | | be | | | left |
When I route I should get When I route I should get
| from | to | bearings | route | turns | lanes | | from | to | bearings | route | turns | lanes |
| a | c | 180,180 180,180 | in,straight,straight | depart,new name straight,arrive | ,0, | | 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 | ,0, | | 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 | ,1, | | 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 | ,1, | | 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 #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 | | | | bd | turn | | |
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | waypoints | route | turns | lanes |
| a,d | road,turn,turn | depart,turn right,arrive | ,0, | | a,d | road,turn,turn | depart,turn right,arrive | ,through:false right:true, |
| a,c | road,road,road | depart,use lane straight,arrive | ,1, | | 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 #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 Scenario: Turn Lanes at Segregated Road
Given the node map Given the node map
| | | i | l | | | | | | i | l | | |
@ -134,23 +134,57 @@ Feature: Turn Lane Guidance
| fl | cross | | yes | | fl | cross | | yes |
When I route I should get When I route I should get
| waypoints | route | turns | lanes | # | | waypoints | route | turns | lanes |
| a,j | road,cross,cross | depart,turn right,arrive | ,0, | | | a,j | road,cross,cross | depart,turn right,arrive | ,left:false through:false right:true |
| a,d | road,road,road | depart,use lane straight,arrive | ,1, | #post-processing reduction | | 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 | ,2, | | | a,l | road,cross,cross | depart,turn left,arrive | ,left:true through:false right:false, |
| a,h | road,road,road | depart,continue uturn,arrive | ,2, | | | a,h | road,road,road | depart,continue uturn,arrive | ,left:true through:false right:false, |
| k,d | cross,road,road | depart,turn right,arrive | ,0, | | | k,d | cross,road,road | depart,turn right,arrive | ,left:false through;right:true, |
| k,l | cross,cross,cross | depart,use lane straight,arrive | ,0, | | | k,l | cross,cross,cross | depart,use lane straight,arrive | ,left:false through;right:true, |
| k,h | cross,road,road | depart,turn left,arrive | ,1, | | | k,h | cross,road,road | depart,turn left,arrive | ,left:true through;right:false, |
| k,j | cross,cross,cross | depart,continue uturn,arrive | ,1, | | | k,j | cross,cross,cross | depart,continue uturn,arrive | ,left:true through;right:false, |
| e,l | road,cross,cross | depart,turn right,arrive | ,0, | | | e,l | road,cross,cross | depart,turn right,arrive | ,none:false through:false through;right:true, |
| e,h | road,road | depart,arrive | , | | | e,h | road,road | depart,arrive | ,none:false through:true through;right:true |
| e,j | road,cross,cross | depart,turn left,arrive | ,2, | | | 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 | ,2, | | | 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,h | cross,road,road | depart,turn right,arrive | ,, |
| i,j | cross,cross,cross | depart,use lane straight,arrive | ,0, | | | i,j | cross,cross,cross | depart,use lane straight,arrive | ,left:false through:true, |
| i,d | cross,road,road | depart,turn left,arrive | ,1, | | | i,d | cross,road,road | depart,turn left,arrive | ,left:true through:false, |
| i,l | cross,cross,cross | depart,continue uturn,arrive | ,1, | | | 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 Scenario: Turn Lanes at Segregated Road
Given the node map Given the node map
@ -170,8 +204,8 @@ Feature: Turn Lane Guidance
| cf | cross | | yes | | cf | cross | | yes |
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | waypoints | route | turns | lanes |
| a,j | road,cross,cross | depart,turn right,arrive | ,0, | | a,j | road,cross,cross | depart,turn right,arrive | ,left:false through:false right:true, |
#this can happen due to traffic lights / lanes not drawn up to the intersection itself #this can happen due to traffic lights / lanes not drawn up to the intersection itself
Scenario: Turn Lanes Given earlier than actual turn Scenario: Turn Lanes Given earlier than actual turn
@ -188,9 +222,9 @@ Feature: Turn Lane Guidance
| ce | turn | | | ce | turn | |
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | waypoints | route | turns | lanes |
| a,e | road,turn,turn | depart,turn right,arrive | ,0, | | a,e | road,turn,turn | depart,turn right,arrive | ,none:false right:true, |
| a,d | road,road,road | depart,use lane straight,arrive | ,1, | | a,d | road,road,road | depart,use lane straight,arrive | ,none:true right:false, |
Scenario: Turn Lanes Given earlier than actual turn Scenario: Turn Lanes Given earlier than actual turn
Given the node map Given the node map
@ -208,11 +242,11 @@ Feature: Turn Lane Guidance
| hk | second-turn | | | | hk | second-turn | | |
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | waypoints | route | turns | lanes |
| a,k | road,second-turn,second-turn | depart,turn right,arrive | ,0, | | a,k | road,second-turn,second-turn | depart,turn right,arrive | ,none:false right:true, |
| a,i | road,road,road | depart,use lane straight,arrive | ,1, | | 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 | ,1, | | 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 | ,0, | | i,a | road,road,road | depart,use lane straight,arrive | ,left:false none:true, |
Scenario: Passing a one-way street Scenario: Passing a one-way street
Given the node map Given the node map
@ -227,8 +261,8 @@ Feature: Turn Lane Guidance
| cf | turn | | | | cf | turn | | |
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | waypoints | route | turns | lanes |
| a,f | road,turn,turn | depart,turn left,arrive | ,1, | | a,f | road,turn,turn | depart,turn left,arrive | ,left:true through:false, |
Scenario: Passing a one-way street, partly pulled back lanes Scenario: Passing a one-way street, partly pulled back lanes
Given the node map Given the node map
@ -245,9 +279,9 @@ Feature: Turn Lane Guidance
| bg | right | | no | | bg | right | | no |
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | waypoints | route | turns | lanes |
| a,f | road,turn,turn | depart,turn left,arrive | ,1, | | a,f | road,turn,turn | depart,turn left,arrive | ,left:true through;right:false, |
| a,g | road,right,right | depart,turn right,arrive | ,0, | | 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 Scenario: Passing a one-way street, partly pulled back lanes, no through
Given the node map Given the node map
@ -264,11 +298,12 @@ Feature: Turn Lane Guidance
| bg | right | | no | | bg | right | | no |
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | waypoints | route | turns | lanes |
| a,f | road,turn,turn | depart,turn left,arrive | ,1, | | a,f | road,turn,turn | depart,turn left,arrive | ,left:true right:false, |
| a,g | road,right,right | depart,turn right,arrive | ,0, | | 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 Given the node map
| | | | | g | | | | | | | g | |
| | | | | | | | | | | | | |
@ -285,12 +320,12 @@ Feature: Turn Lane Guidance
| cf | right | | | cf | right | |
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | waypoints | route | turns | lanes |
| a,g | road,left,left | depart,turn left,arrive | ,2, | | 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 | ,1, | | 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 | ,0, | | 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 Given the node map
| a | b | c | d | | a | b | c | d |
| | | e | | | | | e | |
@ -307,12 +342,12 @@ Feature: Turn Lane Guidance
| ce | turn | | | ce | turn | |
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | waypoints | route | turns | lanes |
| a,d | road,road,road | depart,use lane straight,arrive | ,1, | | a,d | road,road,road | depart,use lane straight,arrive | ,through:true right:false, |
| a,e | road,turn,turn | depart,turn right,arrive | ,0, | | a,e | road,turn,turn | depart,turn right,arrive | ,through:false right:true, |
@bug @todo
Scenario: Theodor Heuss Platz Scenario: Theodor Heuss Platz
Given the node map Given the node map
| | | | i | o | | | l | | | | | | i | o | | | l | |
| | | b | | | | a | | m | | | | b | | | | a | | m |
@ -343,10 +378,10 @@ Feature: Turn Lane Guidance
| hl | top-right-out | | | yes | secondary | | hl | top-right-out | | | yes | secondary |
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | waypoints | route | turns | lanes |
| i,m | top,top-right,top-right | depart,roundabout-exit-4,arrive | ,0 1 2, | | 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 | ,2 3, | | 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 | ,, | | i,o | top,top,top | depart,roundabout-exit-5,arrive | ,, |
Scenario: Turn Lanes Breaking up Scenario: Turn Lanes Breaking up
Given the node map Given the node map
@ -371,9 +406,9 @@ Feature: Turn Lane Guidance
| restriction | bc | fdcg | c | no_right_turn | | restriction | bc | fdcg | c | no_right_turn |
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | waypoints | route | turns | lanes |
| a,g | road,cross,cross | depart,turn left,arrive | ,2 3, | | 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 | ,0 1, | | a,e | road,road,road | depart,use lane straight,arrive | ,left:false left:false through:true through:true, |
Scenario: U-Turn Road at Intersection Scenario: U-Turn Road at Intersection
Given the node map Given the node map
@ -394,11 +429,11 @@ Feature: Turn Lane Guidance
| gdeh | cross | | no | primary | | gdeh | cross | | no | primary |
When I route I should get When I route I should get
| from | to | bearings | route | turns | lanes | | from | to | bearings | route | turns | lanes |
| a | g | 180,180 180,180 | road,cross,cross | depart,turn right,arrive | ,0, | | 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 | ,2, | | 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 | ,1 2, | | 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 | ,2, | | 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 Scenario: Segregated Intersection Merges With Lanes
Given the node map Given the node map
@ -419,12 +454,13 @@ Feature: Turn Lane Guidance
| cf | left | | yes | primary | | cf | left | | yes | primary |
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | waypoints | route | turns | lanes |
| a,f | road,left,left | depart,turn left,arrive | ,2 3 4, | | 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 | ,4, | | 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 | ,0 1, | | 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 Given the node map
| | | h | | g | | | | | | h | | g | | |
| | a | | | | f | k | | | a | | | | f | k |
@ -466,9 +502,9 @@ Feature: Turn Lane Guidance
| ce | cross | | primary | | ce | cross | | primary |
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | waypoints | route | turns | lanes |
| a,d | road,road,road | depart,use lane straight,arrive | ,1 2 3, | | 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 | ,0 1, | | a,e | road,cross,cross | depart,turn slight right,arrive | ,through:false through:false through;slight_right:true slight_right:true, |
Scenario: Highway Ramp Scenario: Highway Ramp
Given the node map Given the node map
@ -482,11 +518,12 @@ Feature: Turn Lane Guidance
| ce | ramp | | motorway_link | | ce | ramp | | motorway_link |
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | waypoints | route | turns | lanes |
| a,d | hwy,hwy,hwy | depart,use lane straight,arrive | ,1 2 3, | | 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 | ,0 1, | | 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 Given the node map
| | a | | | | a | |
| d | c | b | | d | c | b |
@ -502,12 +539,12 @@ Feature: Turn Lane Guidance
| fh | on | | motorway_link | yes | | fh | on | | motorway_link | yes |
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | waypoints | route | turns | lanes |
| a,d | off,road,road | depart,turn_right,arrive | ,0, | | a,d | off,road,road | depart,turn_right,arrive | ,left:false right:true, |
| a,g | off,road,road | depart,turn_left,arrive | ,1, | | a,g | off,road,road | depart,turn_left,arrive | ,left:true right:false, |
| a,h | | | | | a,h | | | |
Scenario: Off Ramp In a Turn Scenario: Off Ramp In a Turn
Given the node map Given the node map
| a | | | | | | | | | | | | | a | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | | | |
@ -521,11 +558,11 @@ Feature: Turn Lane Guidance
| bd | ramp | | motorway_link | yes | | bd | ramp | | motorway_link | yes |
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | waypoints | route | turns | lanes |
| a,c | hwy,hwy,hwy | depart,use lane slight left,arrive | ,1 2, | | 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 | ,0, | | 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 Given the node map
| h | | | | | g | | | | | | f | | h | | | | | g | | | | | | f |
| | | | | | | | e | | | | | | | | | | | | | e | | | | |
@ -540,8 +577,8 @@ Feature: Turn Lane Guidance
| fgh | road | | primary | yes | | fgh | road | | primary | yes |
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | waypoints | route | turns | lanes |
| a,h | road,road,road | depart,continue uturn,arrive | ,2, | | a,h | road,road,road | depart,continue uturn,arrive | ,reverse:true through:false through:false,|
Scenario: Reverse Lane in Segregated Road with none Scenario: Reverse Lane in Segregated Road with none
Given the node map Given the node map
@ -558,8 +595,8 @@ Feature: Turn Lane Guidance
| fgh | road | | primary | yes | | fgh | road | | primary | yes |
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | waypoints | route | turns | lanes |
| a,h | road,road,road | depart,continue uturn,arrive | ,2, | | a,h | road,road,road | depart,continue uturn,arrive | ,reverse:true through:false none:false, |
Scenario: Reverse Lane in Segregated Road with none, Service Turn Prior Scenario: Reverse Lane in Segregated Road with none, Service Turn Prior
Given the node map Given the node map
@ -578,8 +615,8 @@ Feature: Turn Lane Guidance
| ji | park | | service | no | | ji | park | | service | no |
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | waypoints | route | turns | lanes |
| a,h | road,road,road | depart,continue uturn,arrive | ,2, | | a,h | road,road,road | depart,continue uturn,arrive | ,reverse:true through:false none:false, |
Scenario: Don't collapse everything to u-turn / too wide Scenario: Don't collapse everything to u-turn / too wide
Given the node map Given the node map
@ -596,11 +633,11 @@ Feature: Turn Lane Guidance
| cf | secondary | bottom | | | cf | secondary | bottom | |
When I route I should get When I route I should get
| waypoints | turns | route | lanes | | waypoints | turns | route | lanes |
| a,d | depart,continue right,end of road right,arrive | road,road,road,road | ,0,, | | 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 | ,1,, | | 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 Given the node map
| a | | | b | c | | a | | | b | c |
| | d | | | | | | d | | | |
@ -611,10 +648,10 @@ Feature: Turn Lane Guidance
| db | motorway_link | ramp | slight_right\|slight_right | | db | motorway_link | ramp | slight_right\|slight_right |
When I route I should get When I route I should get
| waypoints | turns | route | lanes | | waypoints | turns | route | lanes |
| d,c | depart,merge slight left,arrive | ramp,Hwy,Hwy | ,0 1, | | d,c | depart,merge slight left,arrive | ramp,Hwy,Hwy | ,slight_right:true slight_right:true, |
Scenario: Fork on motorway links - don't fork on through but use lane Scenario: Fork on motorway links - don't fork on through but use lane
Given the node map Given the node map
| i | | | | | a | | i | | | | | a |
| j | | c | b | | x | | j | | c | b | | x |
@ -628,6 +665,6 @@ Feature: Turn Lane Guidance
| ab | on | motorway_link | | | ab | on | motorway_link | |
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | waypoints | route | turns | lanes |
| a,j | on,xbcj,xbcj,xbcj | depart,merge slight left,use lane straight,arrive | ,,1, | | 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 | ,,0, | | 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', '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); 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', '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.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); q.defer(rename, file);
}); });

View File

@ -169,7 +169,14 @@ module.exports = function () {
}; };
this.lanesList = (instructions) => { 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) => { this.turnList = (instructions) => {

View File

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

View File

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

View File

@ -138,6 +138,10 @@ class BaseDataFacade
const int bearing, const int bearing,
const int bearing_range) const = 0; 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 unsigned GetCheckSum() const = 0;
virtual bool IsCoreNode(const NodeID id) const = 0; virtual bool IsCoreNode(const NodeID id) const = 0;

View File

@ -16,6 +16,7 @@
#include "storage/storage_config.hpp" #include "storage/storage_config.hpp"
#include "engine/geospatial_query.hpp" #include "engine/geospatial_query.hpp"
#include "util/graph_loader.hpp" #include "util/graph_loader.hpp"
#include "util/guidance/turn_lanes.hpp"
#include "util/io.hpp" #include "util/io.hpp"
#include "util/packed_vector.hpp" #include "util/packed_vector.hpp"
#include "util/range_table.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<NodeID, false>::vector m_via_node_list;
util::ShM<unsigned, false>::vector m_name_ID_list; util::ShM<unsigned, false>::vector m_name_ID_list;
util::ShM<extractor::guidance::TurnInstruction, false>::vector m_turn_instruction_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<extractor::TravelMode, false>::vector m_travel_mode_list;
util::ShM<char, false>::vector m_names_char_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<unsigned, false>::vector m_geometry_indices;
util::ShM<extractor::CompressedEdgeContainer::CompressedEdge, false>::vector m_geometry_list; util::ShM<extractor::CompressedEdgeContainer::CompressedEdge, false>::vector m_geometry_list;
util::ShM<bool, false>::vector m_is_core_node; 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 ram_index_path;
boost::filesystem::path file_index_path; boost::filesystem::path file_index_path;
util::RangeTable<16, false> m_name_table; util::RangeTable<16, false> m_name_table;
util::RangeTable<16, false> m_lane_string_table;
// bearing classes by node based node // bearing classes by node based node
util::ShM<BearingClassID, false>::vector m_bearing_class_id_table; util::ShM<BearingClassID, false>::vector m_bearing_class_id_table;
@ -118,6 +123,20 @@ class InternalDataFacade final : public BaseDataFacade
sizeof(m_profile_properties)); 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) void LoadTimestamp(const boost::filesystem::path &timestamp_path)
{ {
util::SimpleLogger().Write() << "Loading Timestamp"; util::SimpleLogger().Write() << "Loading Timestamp";
@ -173,6 +192,7 @@ class InternalDataFacade final : public BaseDataFacade
m_via_node_list.resize(number_of_edges); m_via_node_list.resize(number_of_edges);
m_name_ID_list.resize(number_of_edges); m_name_ID_list.resize(number_of_edges);
m_turn_instruction_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_travel_mode_list.resize(number_of_edges);
m_entry_class_id_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_via_node_list[i] = current_edge_data.via_node;
m_name_ID_list[i] = current_edge_data.name_id; m_name_ID_list[i] = current_edge_data.name_id;
m_turn_instruction_list[i] = current_edge_data.turn_instruction; 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_travel_mode_list[i] = current_edge_data.travel_mode;
m_entry_class_id_list[i] = current_edge_data.entry_classid; 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)); 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) void LoadStreetNames(const boost::filesystem::path &names_file)
{ {
boost::filesystem::ifstream name_stream(names_file, std::ios::binary); 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"; util::SimpleLogger().Write() << "loading street names";
LoadStreetNames(config.names_data_path); LoadStreetNames(config.names_data_path);
util::SimpleLogger().Write() << "loading lane tags";
LoadLaneStrings(config.turn_lane_string_path);
util::SimpleLogger().Write() << "loading rtree"; util::SimpleLogger().Write() << "loading rtree";
LoadRTree(); LoadRTree();
util::SimpleLogger().Write() << "loading intersection class data"; util::SimpleLogger().Write() << "loading intersection class data";
LoadIntersectionClasses(config.intersection_class_path); LoadIntersectionClasses(config.intersection_class_path);
util::SimpleLogger().Write() << "Loading Lane Data Pairs";
LoadLaneTupelIdPairs(config.turn_lane_data_path);
} }
// search graph access // search graph access
@ -741,6 +782,37 @@ class InternalDataFacade final : public BaseDataFacade
{ {
return m_entry_class_table.at(entry_class_id); 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 "extractor/profile_properties.hpp"
#include "util/guidance/bearing_class.hpp" #include "util/guidance/bearing_class.hpp"
#include "util/guidance/entry_class.hpp" #include "util/guidance/entry_class.hpp"
#include "util/guidance/turn_lanes.hpp"
#include "engine/geospatial_query.hpp" #include "engine/geospatial_query.hpp"
#include "util/make_unique.hpp" #include "util/make_unique.hpp"
@ -79,10 +80,14 @@ class SharedDataFacade final : public BaseDataFacade
util::PackedVector<OSMNodeID, true> m_osmnodeid_list; util::PackedVector<OSMNodeID, true> m_osmnodeid_list;
util::ShM<NodeID, true>::vector m_via_node_list; util::ShM<NodeID, true>::vector m_via_node_list;
util::ShM<unsigned, true>::vector m_name_ID_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::guidance::TurnInstruction, true>::vector m_turn_instruction_list;
util::ShM<extractor::TravelMode, true>::vector m_travel_mode_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_names_char_list;
util::ShM<char, true>::vector m_turn_string_char_list;
util::ShM<unsigned, true>::vector m_name_begin_indices; 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<unsigned, true>::vector m_geometry_indices;
util::ShM<extractor::CompressedEdgeContainer::CompressedEdge, true>::vector m_geometry_list; util::ShM<extractor::CompressedEdgeContainer::CompressedEdge, true>::vector m_geometry_list;
util::ShM<bool, true>::vector m_is_core_node; 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<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_offsets;
util::ShM<std::size_t, true>::vector m_datasource_name_lengths; 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<SharedRTree> m_static_rtree;
std::unique_ptr<SharedGeospatialQuery> m_geospatial_query; std::unique_ptr<SharedGeospatialQuery> m_geospatial_query;
boost::filesystem::path file_index_path; boost::filesystem::path file_index_path;
std::shared_ptr<util::RangeTable<16, true>> m_name_table; 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 // bearing classes by node based node
util::ShM<BearingClassID, true>::vector m_bearing_class_id_table; 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]); travel_mode_list_ptr, data_layout->num_entries[storage::SharedDataLayout::TRAVEL_MODE]);
m_travel_mode_list = std::move(travel_mode_list); 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 = auto turn_instruction_list_ptr =
data_layout->GetBlockPtr<extractor::guidance::TurnInstruction>( data_layout->GetBlockPtr<extractor::guidance::TurnInstruction>(
shared_memory, storage::SharedDataLayout::TURN_INSTRUCTION); shared_memory, storage::SharedDataLayout::TURN_INSTRUCTION);
@ -238,6 +258,29 @@ class SharedDataFacade final : public BaseDataFacade
m_names_char_list = std::move(names_char_list); 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() void LoadCoreInformation()
{ {
if (data_layout->num_entries[storage::SharedDataLayout::CORE_MARKER] <= 0) if (data_layout->num_entries[storage::SharedDataLayout::CORE_MARKER] <= 0)
@ -416,6 +459,7 @@ class SharedDataFacade final : public BaseDataFacade
LoadTimestamp(); LoadTimestamp();
LoadViaNodeList(); LoadViaNodeList();
LoadNames(); LoadNames();
LoadTurnLaneStrings();
LoadCoreInformation(); LoadCoreInformation();
LoadProfileProperties(); LoadProfileProperties();
LoadRTree(); LoadRTree();
@ -783,6 +827,37 @@ class SharedDataFacade final : public BaseDataFacade
{ {
return m_entry_class_table.at(entry_class_id); 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/coordinate_calculation.hpp"
#include "util/guidance/entry_class.hpp" #include "util/guidance/entry_class.hpp"
#include "util/guidance/toolkit.hpp" #include "util/guidance/toolkit.hpp"
#include "util/guidance/turn_lanes.hpp"
#include "util/typedefs.hpp" #include "util/typedefs.hpp"
#include <boost/optional.hpp> #include <boost/optional.hpp>
@ -70,7 +71,9 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
bearings.second, bearings.second,
extractor::guidance::TurnInstruction::NO_TURN(), extractor::guidance::TurnInstruction::NO_TURN(),
WaypointType::Depart, WaypointType::Depart,
0}; 0,
util::guidance::LaneTupel(),
""};
Intersection intersection{source_node.location, Intersection intersection{source_node.location,
std::vector<short>({bearings.second}), std::vector<short>({bearings.second}),
std::vector<bool>({true}), std::vector<bool>({true}),
@ -147,7 +150,11 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
bearings.second, bearings.second,
path_point.turn_instruction, path_point.turn_instruction,
WaypointType::None, 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_index++;
segment_duration = 0; segment_duration = 0;
} }
@ -202,7 +209,9 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
bearings.second, bearings.second,
extractor::guidance::TurnInstruction::NO_TURN(), extractor::guidance::TurnInstruction::NO_TURN(),
WaypointType::Arrive, WaypointType::Arrive,
0}; 0,
util::guidance::LaneTupel(),
""};
intersection = { intersection = {
target_node.location, target_node.location,
std::vector<short>({static_cast<short>(util::bearing::reverseBearing(bearings.first))}), 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().bearings.size() == 1);
BOOST_ASSERT(steps.back().intersections.front().entry.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.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; 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 // remove steps invalidated by post-processing
std::vector<RouteStep> removeNoTurnInstructions(std::vector<RouteStep> steps); 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 // postProcess will break the connection between the leg geometry
// for which a segment is supposed to represent exactly the coordinates // for which a segment is supposed to represent exactly the coordinates
// between routing maneuvers and the route steps itself. // between routing maneuvers and the route steps itself.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -61,7 +61,8 @@ struct ExtractorConfig
output_file_name = basepath + ".osrm"; output_file_name = basepath + ".osrm";
restriction_file_name = basepath + ".osrm.restrictions"; restriction_file_name = basepath + ".osrm.restrictions";
names_file_name = basepath + ".osrm.names"; 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"; timestamp_file_name = basepath + ".osrm.timestamp";
geometry_output_path = basepath + ".osrm.geometry"; geometry_output_path = basepath + ".osrm.geometry";
node_output_path = basepath + ".osrm.nodes"; node_output_path = basepath + ".osrm.nodes";
@ -83,7 +84,8 @@ struct ExtractorConfig
std::string output_file_name; std::string output_file_name;
std::string restriction_file_name; std::string restriction_file_name;
std::string names_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 timestamp_file_name;
std::string geometry_output_path; std::string geometry_output_path;
std::string edge_output_path; std::string edge_output_path;

View File

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

View File

@ -22,6 +22,7 @@ struct TurnOperation final
EdgeID eid; EdgeID eid;
double angle; double angle;
TurnInstruction instruction; TurnInstruction instruction;
LaneDataID lane_data_id;
}; };
// A Connected Road is the internal representation of a potential turn. Internally, we require // 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/guidance/intersection.hpp"
#include "extractor/query_node.hpp" #include "extractor/query_node.hpp"
#include "extractor/restriction_map.hpp" #include "extractor/restriction_map.hpp"
#include "util/name_table.hpp"
#include "util/node_based_graph.hpp" #include "util/node_based_graph.hpp"
#include "util/typedefs.hpp" #include "util/typedefs.hpp"
#include "util/name_table.hpp"
#include <unordered_set> #include <unordered_set>
#include <vector> #include <vector>

View File

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

View File

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

View File

@ -77,16 +77,14 @@ struct TurnInstruction
{ {
using LaneTupel = util::guidance::LaneTupel; using LaneTupel = util::guidance::LaneTupel;
TurnInstruction(const TurnType::Enum type = TurnType::Invalid, TurnInstruction(const TurnType::Enum type = TurnType::Invalid,
const DirectionModifier::Enum direction_modifier = DirectionModifier::Straight, const DirectionModifier::Enum direction_modifier = DirectionModifier::UTurn)
const LaneTupel lane_tupel = {0, INVALID_LANEID}) : type(type), direction_modifier(direction_modifier)
: type(type), direction_modifier(direction_modifier), lane_tupel(lane_tupel)
{ {
} }
TurnType::Enum type : 5; TurnType::Enum type : 5;
DirectionModifier::Enum direction_modifier : 3; DirectionModifier::Enum direction_modifier : 3;
// the lane tupel that is used for the turn // the lane tupel that is used for the turn
LaneTupel lane_tupel;
static TurnInstruction INVALID() { return {TurnType::Invalid, DirectionModifier::UTurn}; } 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) inline bool operator!=(const TurnInstruction lhs, const TurnInstruction rhs)
{ {
return lhs.type != rhs.type || lhs.direction_modifier != rhs.direction_modifier || return lhs.type != rhs.type || lhs.direction_modifier != rhs.direction_modifier;
lhs.lane_tupel != rhs.lane_tupel;
} }
inline bool operator==(const TurnInstruction lhs, const TurnInstruction rhs) inline bool operator==(const TurnInstruction lhs, const TurnInstruction rhs)
{ {
return lhs.type == rhs.type && lhs.direction_modifier == rhs.direction_modifier && return lhs.type == rhs.type && lhs.direction_modifier == rhs.direction_modifier;
lhs.lane_tupel == rhs.lane_tupel;
} }
} // namespace guidance } // namespace guidance

View File

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

View File

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

View File

@ -90,8 +90,8 @@ inline NodeBasedEdge::NodeBasedEdge(NodeID source,
guidance::RoadClassificationData road_classification) guidance::RoadClassificationData road_classification)
: source(source), target(target), name_id(name_id), weight(weight), forward(forward), : source(source), target(target), name_id(name_id), weight(weight), forward(forward),
backward(backward), roundabout(roundabout), access_restricted(access_restricted), backward(backward), roundabout(roundabout), access_restricted(access_restricted),
startpoint(startpoint), is_split(is_split), travel_mode(travel_mode), lane_string_id(lane_string_id), startpoint(startpoint), is_split(is_split), travel_mode(travel_mode),
road_classification(std::move(road_classification)) 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, explicit OriginalEdgeData(NodeID via_node,
unsigned name_id, unsigned name_id,
LaneDataID lane_data_id,
guidance::TurnInstruction turn_instruction, guidance::TurnInstruction turn_instruction,
EntryClassID entry_classid, EntryClassID entry_classid,
TravelMode travel_mode) TravelMode travel_mode)
: via_node(via_node), name_id(name_id), entry_classid(entry_classid), : 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() OriginalEdgeData()
: via_node(std::numeric_limits<unsigned>::max()), : via_node(std::numeric_limits<unsigned>::max()),
name_id(std::numeric_limits<unsigned>::max()), entry_classid(INVALID_ENTRY_CLASSID), 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) travel_mode(TRAVEL_MODE_INACCESSIBLE)
{ {
} }
@ -36,9 +37,13 @@ struct OriginalEdgeData
NodeID via_node; NodeID via_node;
unsigned name_id; unsigned name_id;
EntryClassID entry_classid; EntryClassID entry_classid;
LaneDataID lane_data_id;
guidance::TurnInstruction turn_instruction; guidance::TurnInstruction turn_instruction;
TravelMode travel_mode; 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 // Added at the start and end of each block as sanity check
const constexpr char CANARY[4] = {'O', 'S', 'R', 'M'}; 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 struct SharedDataLayout
{ {
enum BlockID enum BlockID
@ -30,8 +65,8 @@ struct SharedDataLayout
COORDINATE_LIST, COORDINATE_LIST,
OSM_NODE_ID_LIST, OSM_NODE_ID_LIST,
TURN_INSTRUCTION, TURN_INSTRUCTION,
ENTRY_CLASSID,
TRAVEL_MODE, TRAVEL_MODE,
ENTRY_CLASSID,
R_SEARCH_TREE, R_SEARCH_TREE,
GEOMETRIES_INDEX, GEOMETRIES_INDEX,
GEOMETRIES_LIST, GEOMETRIES_LIST,
@ -49,6 +84,11 @@ struct SharedDataLayout
BEARING_BLOCKS, BEARING_BLOCKS,
BEARING_VALUES, BEARING_VALUES,
ENTRY_CLASS, ENTRY_CLASS,
LANE_DATA_ID,
TURN_LANE_DATA,
TURN_STRING_OFFSETS,
TURN_STRING_BLOCKS,
TURN_STRING_CHAR_LIST,
NUM_BLOCKS NUM_BLOCKS
}; };
@ -113,11 +153,13 @@ struct SharedDataLayout
bool end_canary_alive = std::equal(CANARY, CANARY + sizeof(CANARY), end_canary_ptr); bool end_canary_alive = std::equal(CANARY, CANARY + sizeof(CANARY), end_canary_ptr);
if (!start_canary_alive) 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) 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 names_data_path;
boost::filesystem::path properties_path; boost::filesystem::path properties_path;
boost::filesystem::path intersection_class_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 lanes_in_turn;
LaneID first_lane_from_the_right; 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 guidance
} // namespace util } // namespace util
} // namespace osrm } // 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 */ #endif /* OSRM_UTIL_GUIDANCE_TURN_LANES_HPP */

View File

@ -20,7 +20,8 @@ struct NodeBasedEdgeData
NodeBasedEdgeData() NodeBasedEdgeData()
: distance(INVALID_EDGE_WEIGHT), edge_id(SPECIAL_NODEID), : distance(INVALID_EDGE_WEIGHT), edge_id(SPECIAL_NODEID),
name_id(std::numeric_limits<unsigned>::max()), access_restricted(false), reversed(false), 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 EdgeWeight = std::int32_t;
using LaneStringID = std::uint16_t; using LaneStringID = std::uint16_t;
static const LaneStringID INVALID_LANE_STRINGID = std::numeric_limits<LaneStringID>::max();
using LaneID = std::uint8_t; using LaneID = std::uint8_t;
static const LaneID INVALID_LANEID = std::numeric_limits<LaneID>::max(); 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; using BearingClassID = std::uint32_t;
static const BearingClassID INVALID_BEARING_CLASSID = std::numeric_limits<BearingClassID>::max(); static const BearingClassID INVALID_BEARING_CLASSID = std::numeric_limits<BearingClassID>::max();

View File

@ -11,6 +11,7 @@
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <boost/tokenizer.hpp>
#include <algorithm> #include <algorithm>
#include <iterator> #include <iterator>
@ -63,7 +64,7 @@ inline bool isValidModifier(const guidance::StepManeuver maneuver)
inline bool hasValidLanes(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) 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)]; 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; util::json::Array result;
for (LaneID i = 0; i < lane_tupel.lanes_in_turn; ++i) LaneID lane_id = 0;
result.values.push_back(lane_tupel.first_lane_from_the_right + i); 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; return result;
} }
@ -162,8 +182,7 @@ util::json::Object makeStepManeuver(const guidance::StepManeuver &maneuver)
detail::instructionModifierToString(maneuver.instruction.direction_modifier); detail::instructionModifierToString(maneuver.instruction.direction_modifier);
if (detail::hasValidLanes(maneuver)) if (detail::hasValidLanes(maneuver))
step_maneuver.values["lanes"] = step_maneuver.values["lanes"] = detail::lanesFromManeuver(maneuver);
detail::laneArrayFromLaneTupe(maneuver.instruction.lane_tupel);
step_maneuver.values["location"] = detail::coordinateToLonLat(maneuver.location); step_maneuver.values["location"] = detail::coordinateToLonLat(maneuver.location);
step_maneuver.values["bearing_before"] = std::round(maneuver.bearing_before); 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/assemble_steps.hpp"
#include "engine/guidance/toolkit.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/toolkit.hpp"
#include "util/guidance/turn_lanes.hpp"
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/range/algorithm_ext/erase.hpp> #include <boost/range/algorithm_ext/erase.hpp>
@ -15,7 +14,6 @@
#include <cmath> #include <cmath>
#include <cstddef> #include <cstddef>
#include <iostream> #include <iostream>
#include <iterator>
#include <limits> #include <limits>
#include <utility> #include <utility>
@ -24,8 +22,6 @@ namespace TurnType = osrm::extractor::guidance::TurnType;
namespace DirectionModifier = osrm::extractor::guidance::DirectionModifier; namespace DirectionModifier = osrm::extractor::guidance::DirectionModifier;
using osrm::util::guidance::angularDeviation; using osrm::util::guidance::angularDeviation;
using osrm::util::guidance::getTurnDirection; using osrm::util::guidance::getTurnDirection;
using osrm::util::guidance::isLeftTurn;
using osrm::util::guidance::isRightTurn;
namespace osrm namespace osrm
{ {
@ -867,6 +863,8 @@ void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry)
designated_depart.maneuver.instruction = TurnInstruction::NO_TURN(); designated_depart.maneuver.instruction = TurnInstruction::NO_TURN();
// we need to make this conform with the intersection format for the first intersection // we need to make this conform with the intersection format for the first intersection
auto &first_intersection = designated_depart.intersections.front(); 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.bearings = {first_intersection.bearings[first_intersection.out]};
first_intersection.entry = {true}; first_intersection.entry = {true};
first_intersection.in = Intersection::NO_INDEX; 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.waypoint_type = WaypointType::Arrive;
next_to_last_step.maneuver.instruction = TurnInstruction::NO_TURN(); next_to_last_step.maneuver.instruction = TurnInstruction::NO_TURN();
next_to_last_step.maneuver.bearing_after = 0; 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); BOOST_ASSERT(next_to_last_step.intersections.size() == 1);
auto &last_intersection = next_to_last_step.intersections.back(); auto &last_intersection = next_to_last_step.intersections.back();
last_intersection.bearings = {last_intersection.bearings[last_intersection.in]}; last_intersection.bearings = {last_intersection.bearings[last_intersection.in]};
@ -1038,94 +1038,6 @@ std::vector<RouteStep> assignRelativeLocations(std::vector<RouteStep> steps,
return 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) LegGeometry resyncGeometry(LegGeometry leg_geometry, const std::vector<RouteStep> &steps)
{ {
// The geometry uses an adjacency array-like structure for representation. // 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_graph_factory.hpp"
#include "extractor/edge_based_edge.hpp"
#include "util/coordinate.hpp" #include "util/coordinate.hpp"
#include "util/coordinate_calculation.hpp" #include "util/coordinate_calculation.hpp"
#include "util/exception.hpp" #include "util/exception.hpp"
@ -182,6 +182,7 @@ void EdgeBasedGraphFactory::FlushVectorToStream(
} }
void EdgeBasedGraphFactory::Run(const std::string &original_edge_data_filename, void EdgeBasedGraphFactory::Run(const std::string &original_edge_data_filename,
const std::string &turn_lane_data_filename,
lua_State *lua_state, lua_State *lua_state,
const std::string &edge_segment_lookup_filename, const std::string &edge_segment_lookup_filename,
const std::string &edge_penalty_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); TIMER_START(generate_edges);
GenerateEdgeExpandedEdges(original_edge_data_filename, GenerateEdgeExpandedEdges(original_edge_data_filename,
turn_lane_data_filename,
lua_state, lua_state,
edge_segment_lookup_filename, edge_segment_lookup_filename,
edge_penalty_filename, edge_penalty_filename,
@ -296,6 +298,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedNodes()
/// Actually it also generates OriginalEdgeData and serializes them... /// Actually it also generates OriginalEdgeData and serializes them...
void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges( void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
const std::string &original_edge_data_filename, const std::string &original_edge_data_filename,
const std::string &turn_lane_data_filename,
lua_State *lua_state, lua_State *lua_state,
const std::string &edge_segment_lookup_filename, const std::string &edge_segment_lookup_filename,
const std::string &edge_fixed_penalties_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(), bearing_class_by_node_based_node.resize(m_node_based_graph->GetNumberOfNodes(),
std::numeric_limits<std::uint32_t>::max()); 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())) for (const auto node_u : util::irange(0u, m_node_based_graph->GetNumberOfNodes()))
{ {
progress.PrintStatus(node_u); progress.PrintStatus(node_u);
@ -364,8 +368,8 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
intersection = intersection =
turn_analysis.assignTurnTypes(node_u, edge_from_u, std::move(intersection)); turn_analysis.assignTurnTypes(node_u, edge_from_u, std::move(intersection));
intersection = intersection = turn_lane_handler.assignTurnLanes(
turn_lane_handler.assignTurnLanes(node_u, edge_from_u, std::move(intersection)); node_u, edge_from_u, std::move(intersection), lane_data_map);
const auto possible_turns = turn_analysis.transformIntersectionIntoTurns(intersection); const auto possible_turns = turn_analysis.transformIntersectionIntoTurns(intersection);
// the entry class depends on the turn, so we have to classify the interesction for // 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( original_edge_data_vector.emplace_back(
m_compressed_edge_container.GetPositionForID(edge_from_u), m_compressed_edge_container.GetPositionForID(edge_from_u),
edge_data1.name_id, edge_data1.name_id,
turn.lane_data_id,
turn_instruction, turn_instruction,
entry_class_id, entry_class_id,
edge_data1.travel_mode); edge_data1.travel_mode);
@ -541,6 +546,22 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
util::SimpleLogger().Write() << "Created " << entry_class_hash.size() << " entry classes and " util::SimpleLogger().Write() << "Created " << entry_class_hash.size() << " entry classes and "
<< bearing_class_hash.size() << " Bearing Classes"; << 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); FlushVectorToStream(edge_data_file, original_edge_data_vector);
// Finally jump back to the empty space at the beginning and write length prefix // 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); name_lengths.push_back(0);
name_lengths.push_back(0);
name_lengths.push_back(0);
turn_lane_lengths.push_back(0); turn_lane_lengths.push_back(0);
} }
@ -87,8 +85,8 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
PrepareRestrictions(); PrepareRestrictions();
WriteRestrictions(restrictions_file_name); WriteRestrictions(restrictions_file_name);
WriteCharData(name_file_name,name_lengths,name_char_data); WriteCharData(name_file_name, name_lengths, name_char_data);
WriteCharData(turn_lane_file_name,turn_lane_lengths,turn_lane_char_data); WriteCharData(turn_lane_file_name, turn_lane_lengths, turn_lane_char_data);
} }
catch (const std::exception &e) catch (const std::exception &e)
{ {

View File

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

View File

@ -1,7 +1,7 @@
#include "extractor/extractor_callbacks.hpp"
#include "extractor/extraction_containers.hpp" #include "extractor/extraction_containers.hpp"
#include "extractor/extraction_node.hpp" #include "extractor/extraction_node.hpp"
#include "extractor/extraction_way.hpp" #include "extractor/extraction_way.hpp"
#include "extractor/extractor_callbacks.hpp"
#include "extractor/external_memory_node.hpp" #include "extractor/external_memory_node.hpp"
#include "extractor/restriction.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. // Otherwise fetches the id based on the name and returns it without insertion.
const constexpr auto MAX_STRING_LENGTH = 255u; const constexpr auto MAX_STRING_LENGTH = 255u;
const auto requestId = [this,MAX_STRING_LENGTH](const std::string turn_lane_string) { const auto requestId = [this, MAX_STRING_LENGTH](const std::string &turn_lane_string_) {
if( turn_lane_string == "" ) if (turn_lane_string_ == "")
return INVALID_LANE_STRINGID; 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); const auto &lane_map_iterator = lane_map.find(turn_lane_string);
if (lane_map.end() == lane_map_iterator) 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 // traffic signals in the `traffic_lights` list, which EdgeData
// doesn't have access to. // doesn't have access to.
const bool has_node_penalty = traffic_lights.find(node_v) != traffic_lights.end(); const bool has_node_penalty = traffic_lights.find(node_v) != traffic_lights.end();
if( has_node_penalty ) if (has_node_penalty)
continue; continue;
// Get distances before graph is modified // Get distances before graph is modified
@ -168,10 +168,10 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
return front; return front;
return back; return back;
}; };
graph.GetEdgeData(forward_e1).lane_string_id = graph.GetEdgeData(forward_e1).lane_string_id = selectLaneID(
selectLaneID(graph.GetEdgeData(forward_e1).lane_string_id, fwd_edge_data2.lane_string_id); graph.GetEdgeData(forward_e1).lane_string_id, fwd_edge_data2.lane_string_id);
graph.GetEdgeData(reverse_e1).lane_string_id = graph.GetEdgeData(reverse_e1).lane_string_id = selectLaneID(
selectLaneID(graph.GetEdgeData(reverse_e1).lane_string_id, rev_edge_data2.lane_string_id); graph.GetEdgeData(reverse_e1).lane_string_id, rev_edge_data2.lane_string_id);
// remove e2's (if bidir, otherwise only one) // remove e2's (if bidir, otherwise only one)
graph.DeleteEdge(node_v, forward_e2); graph.DeleteEdge(node_v, forward_e2);

View File

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

View File

@ -1,5 +1,5 @@
#include "extractor/guidance/constants.hpp"
#include "extractor/guidance/intersection_generator.hpp" #include "extractor/guidance/intersection_generator.hpp"
#include "extractor/guidance/constants.hpp"
#include "extractor/guidance/toolkit.hpp" #include "extractor/guidance/toolkit.hpp"
#include <algorithm> #include <algorithm>
@ -114,9 +114,12 @@ Intersection IntersectionGenerator::getConnectedRoads(const NodeID from_node,
has_uturn_edge = true; has_uturn_edge = true;
} }
intersection.push_back(ConnectedRoad( intersection.push_back(
TurnOperation{onto_edge, angle, {TurnType::Invalid, DirectionModifier::UTurn}}, ConnectedRoad(TurnOperation{onto_edge,
turn_is_valid)); 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 // 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) if (!has_uturn_edge)
{ {
intersection.push_back( 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) { 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)) if (1 == node_based_graph.GetDirectedOutDegree(node_v))
{ {
// No turn possible. // No turn possible.
if( intersection.size() == 2 ) if (intersection.size() == 2)
turn.instruction = TurnInstruction::NO_TURN(); turn.instruction = TurnInstruction::NO_TURN();
else 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); 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/turn_discovery.hpp"
#include "extractor/guidance/constants.hpp"
namespace osrm namespace osrm
{ {

View File

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

View File

@ -52,8 +52,7 @@ LaneDataVector laneDataFromString(std::string turn_lane_string)
// count the number of lanes // count the number of lanes
const auto num_lanes = [](const std::string &turn_lane_string) { const auto num_lanes = [](const std::string &turn_lane_string) {
return boost::numeric_cast<LaneID>( 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(), '|') + 1);
std::count(turn_lane_string.begin(), turn_lane_string.end(), '&'));
}(turn_lane_string); }(turn_lane_string);
const auto getNextTag = [](std::string &string, const char *separators) { 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 // 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 // cucumber.js (see https://github.com/cucumber/cucumber-js/issues/417). Needs to be
// changed to "|" only, when the bug is fixed // 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); setLaneData(lane_map, lane, lane_nr);
++lane_nr; ++lane_nr;
} while (lane_nr < num_lanes); } 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){ bool hasTag(const std::string &tag, const LaneDataVector &data)
return findTag(tag,data) != data.cend(); {
return findTag(tag, data) != data.cend();
} }
} // namespace lanes } // namespace lanes

View File

@ -1,8 +1,8 @@
#include "extractor/guidance/turn_lane_handler.hpp"
#include "extractor/guidance/constants.hpp" #include "extractor/guidance/constants.hpp"
#include "extractor/guidance/turn_discovery.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_augmentation.hpp"
#include "extractor/guidance/turn_lane_matcher.hpp"
#include "util/simple_logger.hpp" #include "util/simple_logger.hpp"
#include "util/typedefs.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. 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: 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, Intersection TurnLaneHandler::assignTurnLanes(const NodeID at,
const EdgeID via_edge, 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 &data = node_based_graph.GetEdgeData(via_edge);
const auto turn_lane_string = data.lane_string_id != INVALID_LANE_STRINGID const auto turn_lane_string = data.lane_string_id != INVALID_LANE_STRINGID
? turn_lane_strings.GetNameForID(data.lane_string_id) ? 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); const std::size_t possible_entries = getNumberOfTurns(intersection);
// merge does not justify an instruction // merge does not justify an instruction
const bool has_merge_lane = (hasTag("merge_to_left", lane_data) || const bool has_merge_lane =
hasTag("merge_to_right", lane_data)); (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 // Dead end streets that don't have any left-tag. This can happen due to the fallbacks for
// broken data/barriers. // broken data/barriers.
const bool has_non_usable_u_turn = const bool has_non_usable_u_turn =
(intersection[0].entry_allowed && !hasTag("none", lane_data) && (intersection[0].entry_allowed && !hasTag("none", lane_data) &&
!hasTag("left", lane_data) && !hasTag("left", lane_data) && !hasTag("sharp_left", lane_data) &&
!hasTag("sharp_left", lane_data) && !hasTag("reverse", lane_data) && lane_data.size() + 1 == possible_entries);
!hasTag("reverse", lane_data) &&
lane_data.size() + 1 == possible_entries);
if (has_merge_lane || has_non_usable_u_turn) if (has_merge_lane || has_non_usable_u_turn)
return std::move(intersection); return std::move(intersection);
@ -118,7 +114,8 @@ Intersection TurnLaneHandler::assignTurnLanes(const NodeID at,
if (is_simple) if (is_simple)
{ {
lane_data = handleNoneValueAtSimpleTurn(std::move(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);
} }
// if the intersection is not simple but we have lane data, we check for intersections with // 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 // 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)) isSimpleIntersection(lane_data, intersection))
{ {
lane_data = handleNoneValueAtSimpleTurn(std::move(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 // acquire the lane data of a previous segment and, if possible, use it for the current
// intersection. // intersection.
return handleTurnAtPreviousIntersection(at, via_edge, std::move(intersection)); return handleTurnAtPreviousIntersection(at, via_edge, std::move(intersection), id_map);
} }
return std::move(intersection); 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. // actually take the turn, we need to look back to the edge we drove onto the intersection with.
Intersection TurnLaneHandler::handleTurnAtPreviousIntersection(const NodeID at, Intersection TurnLaneHandler::handleTurnAtPreviousIntersection(const NodeID at,
const EdgeID via_edge, const EdgeID via_edge,
Intersection intersection) const Intersection intersection,
LaneDataIdMap &id_map) const
{ {
NodeID previous_node = SPECIAL_NODEID; NodeID previous_node = SPECIAL_NODEID;
Intersection previous_intersection; Intersection previous_intersection;
@ -176,6 +175,7 @@ Intersection TurnLaneHandler::handleTurnAtPreviousIntersection(const NodeID at,
previous_id, previous_id,
previous_intersection)) previous_intersection))
return ""; return "";
BOOST_ASSERT(previous_id != SPECIAL_EDGEID);
const auto &previous_data = node_based_graph.GetEdgeData(previous_id); const auto &previous_data = node_based_graph.GetEdgeData(previous_id);
auto previous_string = previous_data.lane_string_id != INVALID_LANE_STRINGID 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()) if (lane_data.empty())
return std::move(intersection); return std::move(intersection);
const auto &previous_data = node_based_graph.GetEdgeData(previous_id);
const auto is_simple = isSimpleIntersection(lane_data, intersection); const auto is_simple = isSimpleIntersection(lane_data, intersection);
if (is_simple) if (is_simple)
{ {
lane_data = handleNoneValueAtSimpleTurn(std::move(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);
} }
else else
{ {
@ -227,14 +229,14 @@ Intersection TurnLaneHandler::handleTurnAtPreviousIntersection(const NodeID at,
isSimpleIntersection(lane_data, intersection)) isSimpleIntersection(lane_data, intersection))
{ {
lane_data = handleNoneValueAtSimpleTurn(std::move(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); return std::move(intersection);
} }
/* A simple intersection does not depend on the next intersection coming up. This is important /* 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 * for turn lanes, since traffic signals and/or segregated a intersection can influence the
* interpretation of turn-lanes at a given turn. * 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 && 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"))) (lane_data.back().tag != "left" && lane_data.back().tag != "sharp_left")))
{ {
return false; return false;
@ -417,7 +419,7 @@ std::pair<LaneDataVector, LaneDataVector> TurnLaneHandler::partitionLaneData(
return {turn_lane_data, {}}; 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 // 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? // 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, 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)) if (lane_data.empty() || !canMatchTrivially(intersection, lane_data))
return std::move(intersection); return std::move(intersection);
@ -496,7 +500,8 @@ Intersection TurnLaneHandler::simpleMatchTuplesToTurns(Intersection intersection
return boost::starts_with(data.tag, "merge"); return boost::starts_with(data.tag, "merge");
}) == 0); }) == 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 } // namespace lanes

View File

@ -1,8 +1,11 @@
#include "extractor/guidance/toolkit.hpp"
#include "extractor/guidance/turn_lane_matcher.hpp" #include "extractor/guidance/turn_lane_matcher.hpp"
#include "extractor/guidance/toolkit.hpp"
#include "util/guidance/toolkit.hpp" #include "util/guidance/toolkit.hpp"
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <functional>
namespace osrm namespace osrm
{ {
@ -169,9 +172,27 @@ bool canMatchTrivially(const Intersection &intersection, const LaneDataVector &l
Intersection triviallyMatchLanesToTurns(Intersection intersection, Intersection triviallyMatchLanesToTurns(Intersection intersection,
const LaneDataVector &lane_data, 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; 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) for (; road_index < intersection.size() && lane < lane_data.size(); ++road_index)
{ {
if (intersection[road_index].entry_allowed) if (intersection[road_index].entry_allowed)
@ -185,8 +206,7 @@ Intersection triviallyMatchLanesToTurns(Intersection intersection,
if (TurnType::Suppressed == intersection[road_index].turn.instruction.type) if (TurnType::Suppressed == intersection[road_index].turn.instruction.type)
intersection[road_index].turn.instruction.type = TurnType::UseLane; intersection[road_index].turn.instruction.type = TurnType::UseLane;
intersection[road_index].turn.instruction.lane_tupel = { matchRoad(intersection[road_index], lane_data[lane]);
LaneID(lane_data[lane].to - lane_data[lane].from + 1), lane_data[lane].from};
++lane; ++lane;
} }
} }
@ -209,8 +229,8 @@ Intersection triviallyMatchLanesToTurns(Intersection intersection,
intersection[u_turn].entry_allowed = true; intersection[u_turn].entry_allowed = true;
intersection[u_turn].turn.instruction.type = TurnType::Turn; intersection[u_turn].turn.instruction.type = TurnType::Turn;
intersection[u_turn].turn.instruction.direction_modifier = DirectionModifier::UTurn; 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); return std::move(intersection);
} }

View File

@ -147,6 +147,26 @@ int Storage::Run()
name_stream.read((char *)&number_of_chars, sizeof(unsigned)); name_stream.read((char *)&number_of_chars, sizeof(unsigned));
shared_layout_ptr->SetBlockSize<char>(SharedDataLayout::NAME_CHAR_LIST, number_of_chars); 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 // Loading information for original edges
boost::filesystem::ifstream edges_input_stream(config.edges_data_path, std::ios::binary); boost::filesystem::ifstream edges_input_stream(config.edges_data_path, std::ios::binary);
if (!edges_input_stream) if (!edges_input_stream)
@ -166,6 +186,8 @@ int Storage::Run()
number_of_original_edges); number_of_original_edges);
shared_layout_ptr->SetBlockSize<extractor::guidance::TurnInstruction>( shared_layout_ptr->SetBlockSize<extractor::guidance::TurnInstruction>(
SharedDataLayout::TURN_INSTRUCTION, number_of_original_edges); 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, shared_layout_ptr->SetBlockSize<EntryClassID>(SharedDataLayout::ENTRY_CLASSID,
number_of_original_edges); number_of_original_edges);
@ -368,6 +390,14 @@ int Storage::Run()
sizeof(bearing_class_table[0]) * num_bearings); sizeof(bearing_class_table[0]) * num_bearings);
shared_layout_ptr->SetBlockSize<DiscreteBearing>(SharedDataLayout::BEARING_VALUES, shared_layout_ptr->SetBlockSize<DiscreteBearing>(SharedDataLayout::BEARING_VALUES,
num_bearings); 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)) if (!static_cast<bool>(intersection_stream))
throw util::exception("Failed to read bearing values from " + throw util::exception("Failed to read bearing values from " +
config.intersection_class_path.string()); config.intersection_class_path.string());
@ -436,9 +466,54 @@ int Storage::Run()
name_stream.read(name_char_ptr, name_stream.read(name_char_ptr,
shared_layout_ptr->GetBlockSize(SharedDataLayout::NAME_CHAR_LIST)); shared_layout_ptr->GetBlockSize(SharedDataLayout::NAME_CHAR_LIST));
} }
name_stream.close(); 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 // load original edge information
NodeID *via_node_ptr = shared_layout_ptr->GetBlockPtr<NodeID, true>( NodeID *via_node_ptr = shared_layout_ptr->GetBlockPtr<NodeID, true>(
shared_memory_ptr, SharedDataLayout::VIA_NODE_LIST); shared_memory_ptr, SharedDataLayout::VIA_NODE_LIST);
@ -450,6 +525,9 @@ int Storage::Run()
shared_layout_ptr->GetBlockPtr<extractor::TravelMode, true>(shared_memory_ptr, shared_layout_ptr->GetBlockPtr<extractor::TravelMode, true>(shared_memory_ptr,
SharedDataLayout::TRAVEL_MODE); 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 = extractor::guidance::TurnInstruction *turn_instructions_ptr =
shared_layout_ptr->GetBlockPtr<extractor::guidance::TurnInstruction, true>( shared_layout_ptr->GetBlockPtr<extractor::guidance::TurnInstruction, true>(
shared_memory_ptr, SharedDataLayout::TURN_INSTRUCTION); shared_memory_ptr, SharedDataLayout::TURN_INSTRUCTION);
@ -464,6 +542,7 @@ int Storage::Run()
via_node_ptr[i] = current_edge_data.via_node; via_node_ptr[i] = current_edge_data.via_node;
name_id_ptr[i] = current_edge_data.name_id; name_id_ptr[i] = current_edge_data.name_id;
travel_mode_ptr[i] = current_edge_data.travel_mode; 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; turn_instructions_ptr[i] = current_edge_data.turn_instruction;
entry_class_id_ptr[i] = current_edge_data.entry_classid; entry_class_id_ptr[i] = current_edge_data.entry_classid;
} }
@ -514,8 +593,9 @@ int Storage::Run()
shared_memory_ptr, SharedDataLayout::DATASOURCE_NAME_DATA); shared_memory_ptr, SharedDataLayout::DATASOURCE_NAME_DATA);
if (shared_layout_ptr->GetBlockSize(SharedDataLayout::DATASOURCE_NAME_DATA) > 0) if (shared_layout_ptr->GetBlockSize(SharedDataLayout::DATASOURCE_NAME_DATA) > 0)
{ {
std::cout << "Copying " << (m_datasource_name_data.end() - m_datasource_name_data.begin()) util::SimpleLogger().Write()
<< " chars into name data ptr\n"; << "Copying " << (m_datasource_name_data.end() - m_datasource_name_data.begin())
<< " chars into name data ptr\n";
std::copy( std::copy(
m_datasource_name_data.begin(), m_datasource_name_data.end(), datasource_name_data_ptr); 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_names_path{base.string() + ".datasource_names"},
datasource_indexes_path{base.string() + ".datasource_indexes"}, datasource_indexes_path{base.string() + ".datasource_indexes"},
names_data_path{base.string() + ".names"}, properties_path{base.string() + ".properties"}, 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 namespace guidance
{ {
LaneTupel::LaneTupel() LaneTupel::LaneTupel() : lanes_in_turn(0), first_lane_from_the_right(INVALID_LANEID)
: lanes_in_turn(0), first_lane_from_the_right(INVALID_LANEID)
{ {
// basic constructor, set everything to zero // basic constructor, set everything to zero
} }

View File

@ -36,11 +36,13 @@ NameTable::NameTable(const std::string &filename)
} }
else 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) if (!name_stream)
throw exception("Failed to read " + std::to_string(number_of_chars) + throw exception("Failed to read " + std::to_string(number_of_chars) + " characters from " +
" characters from " + filename); filename);
} }
std::string NameTable::GetNameForID(const unsigned name_id) const 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 = { std::vector<InputEdge> edges = {
// src, tgt, dist, edge_id, name_id, access_restricted, fwd, bkwd, roundabout, travel_mode // 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,
{1, 0, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID}, 1,
{1, 2, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID}, 1,
{2, 1, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID}, SPECIAL_EDGEID,
{2, 3, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID}, 0,
{3, 2, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID}, false,
{3, 4, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID}, false,
{4, 3, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID}}; 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[0].data.IsCompatibleTo(edges[2].data));
BOOST_ASSERT(edges[2].data.IsCompatibleTo(edges[4].data)); BOOST_ASSERT(edges[2].data.IsCompatibleTo(edges[4].data));
@ -69,18 +149,138 @@ BOOST_AUTO_TEST_CASE(loop_test)
std::vector<InputEdge> edges = { std::vector<InputEdge> edges = {
// src, tgt, dist, edge_id, name_id, access_restricted, fwd, bkwd, roundabout, travel_mode // 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,
{0, 5, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID}, 1,
{1, 0, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID}, 1,
{1, 2, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID}, SPECIAL_EDGEID,
{2, 1, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID}, 0,
{2, 3, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID}, false,
{3, 2, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID}, false,
{3, 4, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID}, false,
{4, 3, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID}, true,
{4, 5, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID}, TRAVEL_MODE_INACCESSIBLE,
{5, 0, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID}, INVALID_LANE_STRINGID},
{5, 4, 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); BOOST_ASSERT(edges.size() == 12);
@ -124,12 +324,72 @@ BOOST_AUTO_TEST_CASE(t_intersection)
std::vector<InputEdge> edges = { std::vector<InputEdge> edges = {
// src, tgt, dist, edge_id, name_id, access_restricted, fwd, bkwd, roundabout, travel_mode // 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,
{1, 0, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID}, 1,
{1, 2, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID}, 1,
{1, 3, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID}, SPECIAL_EDGEID,
{2, 1, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID}, 0,
{3, 1, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID}, 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)); BOOST_ASSERT(edges[0].data.IsCompatibleTo(edges[1].data));
@ -160,10 +420,50 @@ BOOST_AUTO_TEST_CASE(street_name_changes)
std::vector<InputEdge> edges = { std::vector<InputEdge> edges = {
// src, tgt, dist, edge_id, name_id, access_restricted, fwd, bkwd, roundabout, travel_mode // 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,
{1, 0, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID}, 1,
{1, 2, 1, SPECIAL_EDGEID, 1, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID}, 1,
{2, 1, 1, SPECIAL_EDGEID, 1, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID}, 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)); BOOST_ASSERT(edges[0].data.IsCompatibleTo(edges[1].data));
@ -190,10 +490,50 @@ BOOST_AUTO_TEST_CASE(direction_changes)
std::vector<InputEdge> edges = { std::vector<InputEdge> edges = {
// src, tgt, dist, edge_id, name_id, access_restricted, fwd, bkwd, roundabout, travel_mode // 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,
{1, 0, 1, SPECIAL_EDGEID, 0, false, true, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID}, 1,
{1, 2, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID}, 1,
{2, 1, 1, SPECIAL_EDGEID, 0, false, false, false, true, TRAVEL_MODE_INACCESSIBLE,INVALID_LANE_STRINGID}, 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); 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; }; BearingClassID GetBearingClassID(const NodeID /*id*/) const override { return 0; };
EntryClassID GetEntryClassID(const EdgeID /*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 util::guidance::BearingClass
GetBearingClass(const BearingClassID /*bearing_class_id*/) const override GetBearingClass(const BearingClassID /*bearing_class_id*/) const override
{ {