expose lanes as enums, adjusted for comments

This commit is contained in:
Moritz Kobitzsch 2016-06-21 10:41:08 +02:00
parent 5d91b759d1
commit 5905708111
45 changed files with 1020 additions and 722 deletions

View File

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

View File

@ -437,16 +437,11 @@ step.
| geojson | [GeoJSON `LineString`](http://geojson.org/geojson-spec.html#linestring) or [GeoJSON `Point`](http://geojson.org/geojson-spec.html#point) if it is only one coordinate (not wrapped by a GeoJSON feature)|
- `name`: The name of the way along which travel proceeds.
- `lanes`: the available turn lanes at the turn
- `marked`: markings on the road, following the OSM scheme (e.g. left, slight_right, or through)
- `take`: a boolean flag indicating whether the lane is a possible choice in the maneuver
- `pronunciation`: The pronunciation hint of the way name. Will be `undefined` if there is no pronunciation hit.
- `destinations`: The destinations of the way. Will be `undefined` if there are no destinations.
- `mode`: A string signifying the mode of transportation.
- `maneuver`: A `StepManeuver` object representing the maneuver.
- `intersections`: A list of `Intersections` that are passed along the segment, the very first belonging to the StepManeuver
Currently, the supported lane tags are: `sharp_left, left, slight_left, sharp_right, right, slight_right, through, reverse, none`.
- `intersections`: A list of `Intersection` objects that are passed along the segment, the very first belonging to the StepManeuver
#### Example
@ -455,23 +450,20 @@ Currently, the supported lane tags are: `sharp_left, left, slight_left, sharp_ri
"distance":152.3,
"duration":15.6,
"name":"Lortzingstraße",
"lanes":{
{"marked":"left",
"take":"false"},
{"marked":"right",
"take":"true"}
},
"maneuver":{
"type":"turn",
"modifier":"right"
},
"modifier":"right",
"lanes":[
{"indications":["left","straight"], "valid":"false"},
{"indications":["right"], "valid":"true"}
]},
"geometry":"{lu_IypwpAVrAvAdI",
"mode":"driving",
"intersections":[
{"location":[13.39677,52.54366],
"in":2,
"in":3,
"out":1,
"bearings":[10,184,270],
"bearings":[10,92,184,270],
"entry":[false,"true","true"]},
{"location":[13.394718,52.543096],
"in":0,
@ -515,7 +507,6 @@ Currently, the supported lane tags are: `sharp_left, left, slight_left, sharp_ri
Please note that even though there are `new name` and `notification` instructions, the `mode` and `name` can change
between all instructions. They only offer a fallback in case nothing else is to report.
- `modifier` An optional `string` indicating the direction change of the maneuver.
| `modifier` | Description |
@ -529,7 +520,7 @@ Currently, the supported lane tags are: `sharp_left, left, slight_left, sharp_ri
| left | a normal turn to the left |
| sharp left | a sharp turn to the left |
The list of turns without a modifier is limited to: `depart/arrive`. If the source/target location is close enough to the `depart/arrive` location, no modifier will be given.
The list of turns without a modifier is limited to: `depart/arrive`. If the source/target location is close enough to the `depart/arrive` location, no modifier will be given.
The meaning depends on the `type` field.
@ -538,7 +529,6 @@ Currently, the supported lane tags are: `sharp_left, left, slight_left, sharp_ri
| `turn` | `modifier` indicates the change in direction accomplished through the turn |
| `depart`/`arrive` | `modifier` indicates the position of departure point and arrival point in relation to the current direction of travel |
- `exit` An optional `integer` indicating number of the exit to take. The field exists for the following `type` field:
| `type` | Description |
@ -546,10 +536,42 @@ Currently, the supported lane tags are: `sharp_left, left, slight_left, sharp_ri
| `roundabout` | Number of the roundabout exit to take. If exit is `undefined` the destination is on the roundabout. |
| else | Indicates the number of intersections passed until the turn. Example instruction: `at the fourth intersection, turn left` |
- `lanes`: Array of `Lane` objects that denote the available turn lanes at the turn location
New properties (potentially depending on `type`) may be introduced in the future without an API version change.
### Intersections
### Lane
A lane give a representation of turn lane at the corresponding turn location.
#### Properties
- `indications`: a indication (e.g. marking on the road) specifying the turn lane. A road can have multiple indications (e.g. an arrow pointing straight and left). The indications are given in an array, each containing one of the following types. Further indications might be added on without an API version change.
| `value` | Description |
|------------------------|---------------------------------------------------------------------------------------------------------------------------|
| `none` | No dedicated indication is shown. |
| `sharp right` | An indication indicating a sharp right turn (i.e. strongly bend arrow). |
| `right` | An indication indicating a right turn (i.e. bend arrow). |
| `sharp right` | An indication indicating a slight right turn (i.e. slightly bend arrow). |
| `straight` | No dedicated indication is shown (i.e. straight arrow). |
| `sharp left` | An indication indicating a sharp left turn (i.e. strongly bend arrow). |
| `left` | An indication indicating a left turn (i.e. bend arrow). |
| `sharp left` | An indication indicating a slight left turn (i.e. slightly bend arrow). |
| `uturn` | An indication signaling the possibility to reverse (i.e. fully bend arrow). |
- `valid`: a boolean flag indicating whether the lane is a valid choice in the current maneuver
#### Example
```json
{
"indication": ["left", "straight"],
"valid": "false"
}
```
### Intersection
An intersection gives a full representation of any cross-way the path passes bay. For every step, the very first intersection (`intersections[0]`) corresponds to the
location of the StepManeuver. Further intersections are listed for every cross-way until the next turn instruction.

View File

@ -25,9 +25,9 @@ Feature: Turn Lane Guidance
| de | |
When I route I should get
| waypoints | route | turns | lanes | # |
| a,d | ab,bc,cd,cd | depart,turn right,turn left,arrive | ,through:false right:true right:true right:false,left:true left:true through:false, | 2 hops |
| a,e | ab,bc,cd,de,de | depart,turn right,turn left,turn right,arrive | ,through:false right:false right:true right:false,left:false left:true through:false,through:false right:true, | 3 hops |
| waypoints | route | turns | lanes | # |
| a,d | ab,bc,cd,cd | depart,turn right,turn left,arrive | ,straight:false right:true right:true right:false,left:true left:true straight:false, | 2 hops |
| a,e | ab,bc,cd,de,de | depart,turn right,turn left,turn right,arrive | ,straight:false right:false right:true right:false,left:false left:true straight:false,straight:false right:true, | 3 hops |
@anticipate
Scenario: Anticipate Lane Change for quick same direction turns, staying on the same street
@ -48,9 +48,9 @@ Feature: Turn Lane Guidance
| dy | | | YSt |
When I route I should get
| waypoints | route | turns | lanes |
| a,e | MySt,MySt,MySt,MySt | depart,continue right,end of road right,arrive | ,through:false right:false right:true,left:false right:true, |
| e,a | MySt,MySt,MySt,MySt | depart,continue left,end of road left,arrive | ,left:true left:false through:false,left:true right:false, |
| waypoints | route | turns | lanes |
| a,e | MySt,MySt,MySt,MySt | depart,continue right,turn right,arrive | ,straight:false right:false right:true,left:false right:true, |
| e,a | MySt,MySt,MySt,MySt | depart,continue left,turn left,arrive | ,left:true left:false straight:false,left:true right:false, |
@anticipate
Scenario: Anticipate Lane Change for quick same direction turns, changing between streets
@ -71,9 +71,9 @@ Feature: Turn Lane Guidance
| dy | | | EYSt |
When I route I should get
| waypoints | route | turns | lanes |
| a,e | AXSt,BDSt,EYSt,EYSt | depart,turn right,end of road right,arrive | ,through:false right:false right:true,left:false right:true, |
| e,a | EYSt,BDSt,AXSt,AXSt | depart,turn left,end of road left,arrive | ,left:true left:false through:false,left:true right:false, |
| waypoints | route | turns | lanes |
| a,e | AXSt,BDSt,EYSt,EYSt | depart,turn right,turn right,arrive | ,straight:false right:false right:true,left:false right:true, |
| e,a | EYSt,BDSt,AXSt,AXSt | depart,turn left,turn left,arrive | ,left:true left:false straight:false,left:true right:false, |
@anticipate
@ -92,8 +92,8 @@ Feature: Turn Lane Guidance
| cy | | Hwy | motorway | |
When I route I should get
| waypoints | route | turns | lanes |
| a,d | On,Hwy,Off,Off | depart,merge slight right,off ramp right,arrive | ,slight_left:false slight_left:true,through:false slight_right:true, |
| waypoints | route | turns | lanes |
| a,d | On,Hwy,Off,Off | depart,merge slight right,off ramp right,arrive | ,slight left:false slight left:true,straight:false slight right:true, |
@anticipate
@ -115,8 +115,8 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes |
| a,i | abx,bcd,di,di | depart,off ramp right,fork slight left,arrive | ,none:false none:false none:false slight_right:true slight_right:true,slight_left:true slight_left;slight_right:true slight_right:false, |
| a,j | abx,bcd,dj,dj | depart,off ramp right,fork slight right,arrive | ,none:false none:false none:false slight_right:true slight_right:true,slight_left:false slight_left;slight_right:true slight_right:true, |
| a,i | abx,bcd,di,di | depart,off ramp right,fork slight left,arrive | ,none:false none:false none:false slight right:true slight right:true,slight left:true slight left;slight right:true slight right:false, |
| a,j | abx,bcd,dj,dj | depart,off ramp right,fork slight right,arrive | ,none:false none:false none:false slight right:true slight right:true,slight left:false slight left;slight right:true slight right:true, |
@anticipate
@ -136,8 +136,8 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes |
| a,i | ab,xbcj,ci,ci | depart,merge slight left,turn slight right,arrive | ,,none:false slight_right:true, |
| a,j | ab,xbcj,xbcj,xbcj | depart,merge slight left,use lane straight,arrive | ,,none:true slight_right:false, |
| a,i | ab,xbcj,ci,ci | depart,merge slight left,turn slight right,arrive | ,,none:false slight right:true, |
| a,j | ab,xbcj,xbcj,xbcj | depart,merge slight left,use lane straight,arrive | ,,none:true slight right:false, |
@anticipate
@ -160,8 +160,8 @@ Feature: Turn Lane Guidance
| de | | de |
When I route I should get
| waypoints | route | turns | lanes |
| a,e | abx,bcy,cdz,de,de | depart,turn right,turn left,turn right,arrive | ,through:false right:false right:true right:false,left:false left:true through:false,through:false right:true, |
| waypoints | route | turns | lanes |
| a,e | abx,bcy,cdz,de,de | depart,turn right,turn left,turn right,arrive | ,straight:false right:false right:true right:false,left:false left:true straight:false,straight:false right:true, |
@anticipate
Scenario: Lane anticipation for fan-out
@ -183,8 +183,8 @@ Feature: Turn Lane Guidance
| de | | de |
When I route I should get
| waypoints | route | turns | lanes |
| a,e | abx,bcy,cdz,de,de | depart,turn right,turn left,turn right,arrive | ,through:false right:true,left:true left:true through:false,through:false right:true right:true right:true, |
| waypoints | route | turns | lanes |
| a,e | abx,bcy,cdz,de,de | depart,turn right,turn left,turn right,arrive | ,straight:false right:true,left:true left:true straight:false,straight:false right:true right:true right:true, |
@anticipate
Scenario: Lane anticipation for fan-in followed by fan-out
@ -206,8 +206,8 @@ Feature: Turn Lane Guidance
| de | | de |
When I route I should get
| waypoints | route | turns | lanes |
| a,e | abx,bcy,cdz,de,de | depart,turn right,turn left,turn right,arrive | ,through:false right:true right:true right:false,left:true left:true through:false,through:false right:true right:true right:true, |
| waypoints | route | turns | lanes |
| a,e | abx,bcy,cdz,de,de | depart,turn right,turn left,turn right,arrive | ,straight:false right:true right:true right:false,left:true left:true straight:false,straight:false right:true right:true right:true, |
@anticipate
Scenario: Lane anticipation for fan-out followed by fan-in
@ -229,8 +229,8 @@ Feature: Turn Lane Guidance
| de | | de |
When I route I should get
| waypoints | route | turns | lanes |
| a,e | abx,bcy,cdz,de,de | depart,turn right,turn left,turn right,arrive | ,through:false right:true,left:false left:true through:false,through:false right:true, |
| waypoints | route | turns | lanes |
| a,e | abx,bcy,cdz,de,de | depart,turn right,turn left,turn right,arrive | ,straight:false right:true,left:false left:true straight:false,straight:false right:true, |
@anticipate
Scenario: Lane anticipation for multiple hops with same number of lanes
@ -256,8 +256,8 @@ Feature: Turn Lane Guidance
| ef | | ef |
When I route I should get
| waypoints | route | turns | lanes |
| a,f | abx,bcy,cdz,dew,ef,ef | depart,turn right,turn left,turn right,turn left,arrive | ,through:false right:false right:true right:false,left:false left:true through:false,through:false right:true right:false,left:true through:false, |
| waypoints | route | turns | lanes |
| a,f | abx,bcy,cdz,dew,ef,ef | depart,turn right,turn left,turn right,turn left,arrive | ,straight:false right:false right:true right:false,left:false left:true straight:false,straight:false right:true right:false,left:true straight:false, |
@anticipate @bug @todo
Scenario: Tripple Right keeping Left

View File

@ -20,11 +20,11 @@ Feature: Turn Lane Guidance
| bd | | | left\|right | right |
When I route I should get
| waypoints | route | turns | lanes |
| a,c | in,straight,straight | depart,new name straight,arrive | ,through:true right:false, |
| a,d | in,right,right | depart,turn right,arrive | ,through:false right:true, |
| c,a | straight,in,in | depart,new name straight,arrive | ,left:false through:true none:true none:true, |
| c,d | straight,right,right | depart,turn left,arrive | ,left:true through:false none:false none:false, |
| waypoints | route | turns | lanes |
| a,c | in,straight,straight | depart,new name straight,arrive | ,straight:true right:false, |
| a,d | in,right,right | depart,turn right,arrive | ,straight:false right:true, |
| c,a | straight,in,in | depart,new name straight,arrive | ,left:false straight:true none:true none:true, |
| c,d | straight,right,right | depart,turn left,arrive | ,left:true straight:false none:false none:false, |
Scenario: Basic Turn Lane 4-Way Turn
Given the node map
@ -81,11 +81,11 @@ Feature: Turn Lane Guidance
| be | | | left |
When I route I should get
| from | to | bearings | route | turns | lanes |
| a | c | 180,180 180,180 | in,straight,straight | depart,new name straight,arrive | ,reverse;left:false through;right:true, |
| a | d | 180,180 180,180 | in,right,right | depart,turn right,arrive | ,reverse;left:false through;right:true, |
| a | e | 180,180 180,180 | in,left,left | depart,turn left,arrive | ,reverse;left:true through;right:false, |
| 1 | a | 90,2 270,2 | in,in,in | depart,turn uturn,arrive | ,reverse;left:true through;right:false, |
| from | to | bearings | route | turns | lanes |
| a | c | 180,180 180,180 | in,straight,straight | depart,new name straight,arrive | ,left;uturn:false straight;right:true, |
| a | d | 180,180 180,180 | in,right,right | depart,turn right,arrive | ,left;uturn:false straight;right:true, |
| a | e | 180,180 180,180 | in,left,left | depart,turn left,arrive | ,left;uturn:true straight;right:false, |
| 1 | a | 90,2 270,2 | in,in,in | depart,turn uturn,arrive | ,left;uturn:true straight;right:false, |
#this next test requires decision on how to announce lanes for going straight if there is no turn
@ -103,9 +103,9 @@ Feature: Turn Lane Guidance
| bd | turn | | |
When I route I should get
| waypoints | route | turns | lanes |
| a,d | road,turn,turn | depart,turn right,arrive | ,through:false right:true, |
| a,c | road,road,road | depart,use lane straight,arrive | ,through:true right:false, |
| waypoints | route | turns | lanes |
| a,d | road,turn,turn | depart,turn right,arrive | ,straight:false right:true, |
| a,c | road,road,road | depart,use lane straight,arrive | ,straight:true right:false, |
#turn lanes are often drawn at the incoming road, even though the actual turn requires crossing the intersection first
@todo @WORKAROUND-FIXME @bug
@ -134,23 +134,23 @@ Feature: Turn Lane Guidance
| fl | cross | | yes |
When I route I should get
| waypoints | route | turns | lanes |
| a,j | road,cross,cross | depart,turn right,arrive | ,left:false through:false right:true |
| a,d | road,road,road | depart,use lane straight,arrive | ,left:false through:true right:false, |
| a,l | road,cross,cross | depart,turn left,arrive | ,left:true through:false right:false, |
| a,h | road,road,road | depart,continue uturn,arrive | ,left:true through:false right:false, |
| k,d | cross,road,road | depart,turn right,arrive | ,left:false through;right:true, |
| k,l | cross,cross,cross | depart,use lane straight,arrive | ,left:false through;right:true, |
| k,h | cross,road,road | depart,turn left,arrive | ,left:true through;right:false, |
| k,j | cross,cross,cross | depart,continue uturn,arrive | ,left:true through;right:false, |
| e,l | road,cross,cross | depart,turn right,arrive | ,none:false through:false through;right:true, |
| e,h | road,road | depart,arrive | ,none:false through:true through;right:true |
| e,j | road,cross,cross | depart,turn left,arrive | ,none:true through:false through;right:false, |
| e,d | road,road,road | depart,continue uturn,arrive | ,none:true through:false through;right:false, |
| i,h | cross,road,road | depart,turn right,arrive | ,, |
| i,j | cross,cross,cross | depart,use lane straight,arrive | ,left:false through:true, |
| i,d | cross,road,road | depart,turn left,arrive | ,left:true through:false, |
| i,l | cross,cross,cross | depart,continue uturn,arrive | ,left:true through:false, |
| waypoints | route | turns | lanes |
| a,j | road,cross,cross | depart,turn right,arrive | ,left:false straight:false right:true |
| a,d | road,road,road | depart,use lane straight,arrive | ,left:false straight:true right:false, |
| a,l | road,cross,cross | depart,turn left,arrive | ,left:true straight:false right:false, |
| a,h | road,road,road | depart,continue uturn,arrive | ,left:true straight:false right:false, |
| k,d | cross,road,road | depart,turn right,arrive | ,left:false straight;right:true, |
| k,l | cross,cross,cross | depart,use lane straight,arrive | ,left:false straight;right:true, |
| k,h | cross,road,road | depart,turn left,arrive | ,left:true straight;right:false, |
| k,j | cross,cross,cross | depart,continue uturn,arrive | ,left:true straight;right:false, |
| e,l | road,cross,cross | depart,turn right,arrive | ,none:false straight:false straight;right:true, |
| e,h | road,road | depart,arrive | ,none:false straight:true straight;right:true |
| e,j | road,cross,cross | depart,turn left,arrive | ,none:true straight:false straight;right:false, |
| e,d | road,road,road | depart,continue uturn,arrive | ,none:true straight:false straight;right:false, |
| i,h | cross,road,road | depart,turn right,arrive | ,, |
| i,j | cross,cross,cross | depart,use lane straight,arrive | ,left:false straight:true, |
| i,d | cross,road,road | depart,turn left,arrive | ,left:true straight:false, |
| i,l | cross,cross,cross | depart,continue uturn,arrive | ,left:true straight:false, |
#copy of former case to prevent further regression
Scenario: Turn Lanes at Segregated Road
@ -178,13 +178,13 @@ Feature: Turn Lane Guidance
| fl | cross | | yes |
When I route I should get
| waypoints | route | turns | lanes |
| a,j | road,cross,cross | depart,turn right,arrive | ,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, |
| waypoints | route | turns | lanes |
| a,j | road,cross,cross | depart,turn right,arrive | ,left:false straight:false right:true, |
| k,d | cross,road,road | depart,turn right,arrive | ,left:false straight;right:true, |
| e,l | road,cross,cross | depart,turn right,arrive | ,none:false straight:false straight;right:true, |
| i,h | cross,road,road | depart,turn right,arrive | ,, |
| i,j | cross,cross,cross | depart,use lane straight,arrive | ,left:false straight:true, |
| i,l | cross,cross,cross | depart,continue uturn,arrive | ,left:true straight:false, |
Scenario: Turn Lanes at Segregated Road
Given the node map
@ -204,8 +204,8 @@ Feature: Turn Lane Guidance
| cf | cross | | yes |
When I route I should get
| waypoints | route | turns | lanes |
| a,j | road,cross,cross | depart,turn right,arrive | ,left:false through:false right:true, |
| waypoints | route | turns | lanes |
| a,j | road,cross,cross | depart,turn right,arrive | ,left:false straight:false right:true, |
#this can happen due to traffic lights / lanes not drawn up to the intersection itself
Scenario: Turn Lanes Given earlier than actual turn
@ -261,8 +261,8 @@ Feature: Turn Lane Guidance
| cf | turn | | |
When I route I should get
| waypoints | route | turns | lanes |
| a,f | road,turn,turn | depart,turn left,arrive | ,left:true through:false, |
| waypoints | route | turns | lanes |
| a,f | road,turn,turn | depart,turn left,arrive | ,left:true straight:false, |
Scenario: Passing a one-way street, partly pulled back lanes
Given the node map
@ -279,9 +279,9 @@ Feature: Turn Lane Guidance
| bg | right | | no |
When I route I should get
| waypoints | route | turns | lanes |
| a,f | road,turn,turn | depart,turn left,arrive | ,left:true through;right:false, |
| a,g | road,right,right | depart,turn right,arrive | ,left:false through;right:true, |
| waypoints | route | turns | lanes |
| a,f | road,turn,turn | depart,turn left,arrive | ,left:true straight;right:false, |
| a,g | road,right,right | depart,turn right,arrive | ,left:false straight;right:true, |
Scenario: Passing a one-way street, partly pulled back lanes, no through
Given the node map
@ -320,10 +320,10 @@ Feature: Turn Lane Guidance
| cf | right | |
When I route I should get
| waypoints | route | turns | lanes |
| a,g | road,left,left | depart,turn left,arrive | ,left:true through:false right:false, |
| a,e | road,through,through | depart,new name straight,arrive | ,left:false through:true right:false, |
| a,f | road,right,right | depart,turn right,arrive | ,left:false through:false right:true, |
| waypoints | route | turns | lanes |
| a,g | road,left,left | depart,turn left,arrive | ,left:true straight:false right:false, |
| a,e | road,through,through | depart,new name straight,arrive | ,left:false straight:true right:false, |
| a,f | road,right,right | depart,turn right,arrive | ,left:false straight:false right:true, |
Scenario: Turn at a traffic light
Given the node map
@ -342,9 +342,9 @@ Feature: Turn Lane Guidance
| ce | turn | |
When I route I should get
| waypoints | route | turns | lanes |
| a,d | road,road,road | depart,use lane straight,arrive | ,through:true right:false, |
| a,e | road,turn,turn | depart,turn right,arrive | ,through:false right:true, |
| waypoints | route | turns | lanes |
| a,d | road,road,road | depart,use lane straight,arrive | ,straight:true right:false, |
| a,e | road,turn,turn | depart,turn right,arrive | ,straight:false right:true, |
@bug @todo
Scenario: Theodor Heuss Platz
@ -379,8 +379,8 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes |
| i,m | top,top-right,top-right | depart,roundabout-exit-4,arrive | ,slight_left:false slight_left;slight_right:true slight_right:true slight_right:true, |
| i,l | top,top-right-out,top-right-out | depart,roundabout-exit-4,arrive | ,slight_left:true slight_left;slight_right:true slight_right:false slight_right:false, |
| i,m | top,top-right,top-right | depart,roundabout-exit-4,arrive | ,slight left:false slight left;slight right:true slight right:true slight right:true, |
| i,l | top,top-right-out,top-right-out | depart,roundabout-exit-4,arrive | ,slight left:true slight left;slight right:true slight right:false slight right:false, |
| i,o | top,top,top | depart,roundabout-exit-5,arrive | ,, |
Scenario: Turn Lanes Breaking up
@ -406,9 +406,9 @@ Feature: Turn Lane Guidance
| restriction | bc | fdcg | c | no_right_turn |
When I route I should get
| waypoints | route | turns | lanes |
| a,g | road,cross,cross | depart,turn left,arrive | ,left:true left:true through:false through:false, |
| a,e | road,road,road | depart,use lane straight,arrive | ,left:false left:false through:true through:true, |
| waypoints | route | turns | lanes |
| a,g | road,cross,cross | depart,turn left,arrive | ,left:true left:true straight:false straight:false, |
| a,e | road,road,road | depart,use lane straight,arrive | ,left:false left:false straight:true straight:true, |
Scenario: U-Turn Road at Intersection
Given the node map
@ -429,11 +429,11 @@ Feature: Turn Lane Guidance
| gdeh | cross | | no | primary |
When I route I should get
| from | to | bearings | route | turns | lanes |
| a | g | 180,180 180,180 | road,cross,cross | depart,turn right,arrive | ,none:false through:false right:true, |
| a | h | 180,180 180,180 | road,cross,cross | depart,turn left,arrive | ,none:true through:false right:false, |
| a | i | 180,180 180,180 | road,road,road | depart,use lane straight,arrive | ,none:true through:true right:false, |
| b | a | 90,2 270,2 | road,road,road | depart,continue uturn,arrive | ,none:true through:false right:false, |
| from | to | bearings | route | turns | lanes |
| a | g | 180,180 180,180 | road,cross,cross | depart,turn right,arrive | ,none:false straight:false right:true, |
| a | h | 180,180 180,180 | road,cross,cross | depart,turn left,arrive | ,none:true straight:false right:false, |
| a | i | 180,180 180,180 | road,road,road | depart,use lane straight,arrive | ,none:true straight:true right:false, |
| b | a | 90,2 270,2 | road,road,road | depart,continue uturn,arrive | ,none:true straight:false right:false, |
Scenario: Segregated Intersection Merges With Lanes
Given the node map
@ -454,10 +454,10 @@ Feature: Turn Lane Guidance
| cf | left | | yes | primary |
When I route I should get
| waypoints | route | turns | lanes |
| a,f | road,left,left | depart,turn left,arrive | ,left:true left:true left:true through:false through:false, |
| a,e | road,road,road | depart,turn uturn,arrive | ,left:true left:false left:false through:false through:false, |
| a,g | road,straight,straight | depart,new name straight,arrive | ,left:false left:false left:false through:true through:true, |
| waypoints | route | turns | lanes |
| a,f | road,left,left | depart,turn left,arrive | ,left:true left:true left:true straight:false straight:false, |
| a,e | road,road,road | depart,turn uturn,arrive | ,left:true left:false left:false straight:false straight:false, |
| a,g | road,straight,straight | depart,new name straight,arrive | ,left:false left:false left:false straight:true straight:true, |
@bug @todo
Scenario: Passing Through a Roundabout
@ -502,9 +502,9 @@ Feature: Turn Lane Guidance
| ce | cross | | primary |
When I route I should get
| waypoints | route | turns | lanes |
| a,d | road,road,road | depart,use lane straight,arrive | ,through:true through:true through;slight_right:true slight_right:false, |
| a,e | road,cross,cross | depart,turn slight right,arrive | ,through:false through:false through;slight_right:true slight_right:true, |
| waypoints | route | turns | lanes |
| a,d | road,road,road | depart,use lane straight,arrive | ,straight:true straight:true straight;slight right:true slight right:false, |
| a,e | road,cross,cross | depart,turn slight right,arrive | ,straight:false straight:false straight;slight right:true slight right:true, |
Scenario: Highway Ramp
Given the node map
@ -518,9 +518,9 @@ Feature: Turn Lane Guidance
| ce | ramp | | motorway_link |
When I route I should get
| waypoints | route | turns | lanes |
| a,d | hwy,hwy,hwy | depart,use lane straight,arrive | ,through:true through:true through;slight_right:true slight_right:false, |
| a,e | hwy,ramp,ramp | depart,off ramp slight right,arrive | ,through:false through:false through;slight_right:true slight_right:true, |
| waypoints | route | turns | lanes |
| a,d | hwy,hwy,hwy | depart,use lane straight,arrive | ,straight:true straight:true straight;slight right:true slight right:false, |
| a,e | hwy,ramp,ramp | depart,off ramp slight right,arrive | ,straight:false straight:false straight;slight right:true slight right:true, |
@bug @todo
Scenario: Turning Off Ramp
@ -558,9 +558,9 @@ Feature: Turn Lane Guidance
| bd | ramp | | motorway_link | yes |
When I route I should get
| waypoints | route | turns | lanes |
| a,c | hwy,hwy,hwy | depart,use lane slight left,arrive | ,through:true through:true slight_right:false, |
| a,d | hwy,ramp,ramp | depart,off ramp slight right,arrive | ,through:false through:false slight_right:true, |
| waypoints | route | turns | lanes |
| a,c | hwy,hwy,hwy | depart,use lane slight left,arrive | ,straight:true straight:true slight right:false, |
| a,d | hwy,ramp,ramp | depart,off ramp slight right,arrive | ,straight:false straight:false slight right:true, |
Scenario: Reverse Lane in Segregated Road
Given the node map
@ -578,7 +578,7 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes |
| a,h | road,road,road | depart,continue uturn,arrive | ,reverse:true through:false through:false,|
| a,h | road,road,road | depart,continue uturn,arrive | ,uturn:true straight:false straight:false,|
Scenario: Reverse Lane in Segregated Road with none
Given the node map
@ -595,8 +595,8 @@ Feature: Turn Lane Guidance
| fgh | road | | primary | yes |
When I route I should get
| waypoints | route | turns | lanes |
| a,h | road,road,road | depart,continue uturn,arrive | ,reverse:true through:false none:false, |
| waypoints | route | turns | lanes |
| a,h | road,road,road | depart,continue uturn,arrive | ,uturn:true straight:false none:false, |
Scenario: Reverse Lane in Segregated Road with none, Service Turn Prior
Given the node map
@ -615,8 +615,8 @@ Feature: Turn Lane Guidance
| ji | park | | service | no |
When I route I should get
| waypoints | route | turns | lanes |
| a,h | road,road,road | depart,continue uturn,arrive | ,reverse:true through:false none:false, |
| waypoints | route | turns | lanes |
| a,h | road,road,road | depart,continue uturn,arrive | ,uturn:true straight:false none:false, |
Scenario: Don't collapse everything to u-turn / too wide
Given the node map
@ -633,9 +633,9 @@ Feature: Turn Lane Guidance
| cf | secondary | bottom | |
When I route I should get
| waypoints | turns | route | lanes |
| a,d | depart,continue right,end of road right,arrive | road,road,road,road | ,through:false right:true,, |
| d,a | depart,continue left,end of road left,arrive | road,road,road,road | ,left:true through:false,, |
| waypoints | turns | route | lanes |
| a,d | depart,continue right,turn right,arrive | road,road,road,road | ,straight:false right:true,, |
| d,a | depart,continue left,turn left,arrive | road,road,road,road | ,left:true straight:false,, |
Scenario: Merge Lanes Onto Freeway
Given the node map
@ -649,7 +649,7 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | turns | route | lanes |
| d,c | depart,merge slight left,arrive | ramp,Hwy,Hwy | ,slight_right:true slight_right:true, |
| d,c | depart,merge slight left,arrive | ramp,Hwy,Hwy | ,slight right:true slight right:true, |
Scenario: Fork on motorway links - don't fork on through but use lane
Given the node map
@ -666,5 +666,5 @@ Feature: Turn Lane Guidance
When I route I should get
| waypoints | route | turns | lanes |
| a,j | on,xbcj,xbcj,xbcj | depart,merge slight left,use lane straight,arrive | ,,none:true slight_right:false, |
| a,i | on,xbcj,off,off | depart,merge slight left,turn slight right,arrive | ,,none:false slight_right:true, |
| a,j | on,xbcj,xbcj,xbcj | depart,merge slight left,use lane straight,arrive | ,,none:true slight right:false, |
| a,i | on,xbcj,off,off | depart,merge slight left,turn slight right,arrive | ,,none:false slight right:true, |

View File

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

View File

@ -7,6 +7,7 @@
#include "extractor/edge_based_node.hpp"
#include "extractor/external_memory_node.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include "extractor/guidance/turn_lane_types.hpp"
#include "engine/phantom_node.hpp"
#include "util/exception.hpp"
#include "util/guidance/bearing_class.hpp"
@ -140,7 +141,8 @@ class BaseDataFacade
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 extractor::guidance::TurnLaneDescription
GetTurnDescription(const LaneDescriptionID lane_description_id) const = 0;
virtual unsigned GetCheckSum() const = 0;

View File

@ -83,13 +83,14 @@ class InternalDataFacade final : public BaseDataFacade
util::ShM<util::guidance::LaneTupelIdPair, false>::vector m_lane_tupel_id_pairs;
util::ShM<extractor::TravelMode, false>::vector m_travel_mode_list;
util::ShM<char, false>::vector m_names_char_list;
util::ShM<char, false>::vector m_lanes_char_list;
util::ShM<unsigned, false>::vector m_geometry_indices;
util::ShM<extractor::CompressedEdgeContainer::CompressedEdge, false>::vector m_geometry_list;
util::ShM<bool, false>::vector m_is_core_node;
util::ShM<unsigned, false>::vector m_segment_weights;
util::ShM<uint8_t, false>::vector m_datasource_list;
util::ShM<std::string, false>::vector m_datasource_names;
util::ShM<std::uint32_t, false>::vector m_lane_description_offsets;
util::ShM<extractor::guidance::TurnLaneType::Mask, false>::vector m_lane_description_masks;
extractor::ProfileProperties m_profile_properties;
std::unique_ptr<InternalRTree> m_static_rtree;
@ -97,7 +98,6 @@ class InternalDataFacade final : public BaseDataFacade
boost::filesystem::path ram_index_path;
boost::filesystem::path file_index_path;
util::RangeTable<16, false> m_name_table;
util::RangeTable<16, false> m_lane_string_table;
// bearing classes by node based node
util::ShM<BearingClassID, false>::vector m_bearing_class_id_table;
@ -305,18 +305,13 @@ class InternalDataFacade final : public BaseDataFacade
new InternalGeospatialQuery(*m_static_rtree, m_coordinate_list, *this));
}
void LoadLaneStrings(const boost::filesystem::path &lane_string_file)
void LoadLaneDescriptions(const boost::filesystem::path &lane_description_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';
if (!util::deserializeAdjacencyArray(lane_description_file.string(),
m_lane_description_offsets,
m_lane_description_masks))
util::SimpleLogger().Write(logWARNING) << "Failed to read turn lane descriptions from "
<< lane_description_file.string();
}
void LoadStreetNames(const boost::filesystem::path &names_file)
@ -422,7 +417,7 @@ class InternalDataFacade final : public BaseDataFacade
LoadStreetNames(config.names_data_path);
util::SimpleLogger().Write() << "loading lane tags";
LoadLaneStrings(config.turn_lane_string_path);
LoadLaneDescriptions(config.turn_lane_description_path);
util::SimpleLogger().Write() << "loading rtree";
LoadRTree();
@ -794,24 +789,16 @@ class InternalDataFacade final : public BaseDataFacade
return m_lane_tupel_id_pairs[m_lane_data_id[id]];
}
std::string GetTurnStringForID(const LaneStringID lane_string_id) const override final
extractor::guidance::TurnLaneDescription
GetTurnDescription(const LaneDescriptionID lane_description_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;
if (lane_description_id == INVALID_LANE_DESCRIPTIONID)
return {};
else
return extractor::guidance::TurnLaneDescription(
m_lane_description_masks.begin() + m_lane_description_offsets[lane_description_id],
m_lane_description_masks.begin() +
m_lane_description_offsets[lane_description_id + 1]);
}
};
}

View File

@ -9,6 +9,7 @@
#include "extractor/compressed_edge_container.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include "extractor/guidance/turn_lane_types.hpp"
#include "extractor/profile_properties.hpp"
#include "util/guidance/bearing_class.hpp"
#include "util/guidance/entry_class.hpp"
@ -84,14 +85,13 @@ class SharedDataFacade final : public BaseDataFacade
util::ShM<extractor::guidance::TurnInstruction, true>::vector m_turn_instruction_list;
util::ShM<extractor::TravelMode, true>::vector m_travel_mode_list;
util::ShM<char, true>::vector m_names_char_list;
util::ShM<char, true>::vector m_turn_string_char_list;
util::ShM<unsigned, true>::vector m_name_begin_indices;
util::ShM<char, true>::vector m_lane_string_char_list;
util::ShM<unsigned, true>::vector m_lane_string_begin_indices;
util::ShM<unsigned, true>::vector m_geometry_indices;
util::ShM<extractor::CompressedEdgeContainer::CompressedEdge, true>::vector m_geometry_list;
util::ShM<bool, true>::vector m_is_core_node;
util::ShM<uint8_t, true>::vector m_datasource_list;
util::ShM<std::uint32_t, true>::vector m_lane_description_offsets;
util::ShM<extractor::guidance::TurnLaneType::Mask, true>::vector m_lane_description_masks;
util::ShM<char, true>::vector m_datasource_name_data;
util::ShM<std::size_t, true>::vector m_datasource_name_offsets;
@ -103,7 +103,6 @@ class SharedDataFacade final : public BaseDataFacade
boost::filesystem::path file_index_path;
std::shared_ptr<util::RangeTable<16, true>> m_name_table;
std::shared_ptr<util::RangeTable<16, true>> m_turn_string_table;
// bearing classes by node based node
util::ShM<BearingClassID, true>::vector m_bearing_class_id_table;
@ -258,29 +257,23 @@ class SharedDataFacade final : public BaseDataFacade
m_names_char_list = std::move(names_char_list);
}
void LoadTurnLaneStrings()
void LoadTurnLaneDescriptions()
{
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 offsets_ptr = data_layout->GetBlockPtr<std::uint32_t>(
shared_memory, storage::SharedDataLayout::LANE_DESCRIPTION_OFFSETS);
util::ShM<std::uint32_t, true>::vector offsets(
offsets_ptr,
data_layout->num_entries[storage::SharedDataLayout::LANE_DESCRIPTION_OFFSETS]);
m_lane_description_offsets = std::move(offsets);
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()));
auto masks_ptr = data_layout->GetBlockPtr<extractor::guidance::TurnLaneType::Mask>(
shared_memory, storage::SharedDataLayout::LANE_DESCRIPTION_MASKS);
m_turn_string_char_list = std::move(turn_strings_char_list);
util::ShM<extractor::guidance::TurnLaneType::Mask, true>::vector masks(
masks_ptr, data_layout->num_entries[storage::SharedDataLayout::LANE_DESCRIPTION_MASKS]);
m_lane_description_masks = std::move(masks);
}
void LoadCoreInformation()
{
if (data_layout->num_entries[storage::SharedDataLayout::CORE_MARKER] <= 0)
@ -459,7 +452,7 @@ class SharedDataFacade final : public BaseDataFacade
LoadTimestamp();
LoadViaNodeList();
LoadNames();
LoadTurnLaneStrings();
LoadTurnLaneDescriptions();
LoadCoreInformation();
LoadProfileProperties();
LoadRTree();
@ -839,24 +832,15 @@ class SharedDataFacade final : public BaseDataFacade
return m_lane_tupel_id_pairs.at(m_lane_data_id.at(id));
}
std::string GetTurnStringForID(const LaneStringID lane_string_id) const override final
extractor::guidance::TurnLaneDescription
GetTurnDescription(const LaneDescriptionID lane_description_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;
if (lane_description_id == INVALID_LANE_DESCRIPTIONID)
return {};
else
return extractor::guidance::TurnLaneDescription(
m_lane_description_masks.begin() + m_lane_description_offsets[lane_description_id],
m_lane_description_masks.begin() + m_lane_description_offsets[lane_description_id + 1]);
}
};
}

View File

@ -3,6 +3,7 @@
#include "extractor/guidance/turn_instruction.hpp"
#include "extractor/travel_mode.hpp"
#include "extractor/guidance/turn_lane_types.hpp"
#include "engine/datafacade/datafacade_base.hpp"
#include "engine/guidance/leg_geometry.hpp"
#include "engine/guidance/route_step.hpp"
@ -73,7 +74,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
WaypointType::Depart,
0,
util::guidance::LaneTupel(),
""};
{}};
Intersection intersection{source_node.location,
std::vector<short>({bearings.second}),
std::vector<bool>({true}),
@ -152,9 +153,9 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
WaypointType::None,
0,
path_point.lane_data.first,
(path_point.lane_data.second != INVALID_LANE_STRINGID
? facade.GetTurnStringForID(path_point.lane_data.second)
: "")};
(path_point.lane_data.second != INVALID_LANE_DESCRIPTIONID
? facade.GetTurnDescription(path_point.lane_data.second)
: extractor::guidance::TurnLaneDescription())};
segment_index++;
segment_duration = 0;
}
@ -211,7 +212,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
WaypointType::Arrive,
0,
util::guidance::LaneTupel(),
""};
{}};
intersection = {
target_node.location,
std::vector<short>({static_cast<short>(util::bearing::reverseBearing(bearings.first))}),
@ -244,7 +245,7 @@ inline std::vector<RouteStep> assembleSteps(const datafacade::BaseDataFacade &fa
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 == "");
BOOST_ASSERT(steps.back().maneuver.lane_description.empty());
return steps;
}

View File

@ -1,52 +0,0 @@
#ifndef OSRM_ENGINE_GUIDANCE_DEBUG_HPP_
#define OSRM_ENGINE_GUIDANCE_DEBUG_HPP_
#include "engine/guidance/route_step.hpp"
#include <iostream>
#include <vector>
namespace osrm
{
namespace engine
{
namespace guidance
{
inline void print(const RouteStep &step)
{
std::cout << static_cast<int>(step.maneuver.instruction.type) << " "
<< static_cast<int>(step.maneuver.instruction.direction_modifier) << " "
<< static_cast<int>(step.maneuver.waypoint_type) << " Duration: " << step.duration
<< " Distance: " << step.distance << " Geometry: " << step.geometry_begin << " "
<< step.geometry_end << " exit: " << step.maneuver.exit
<< " Intersections: " << step.intersections.size() << " [";
for (const auto &intersection : step.intersections)
{
std::cout << "(bearings:";
for (auto bearing : intersection.bearings)
std::cout << " " << bearing;
std::cout << ", entry: ";
for (auto entry : intersection.entry)
std::cout << " " << entry;
std::cout << ")";
}
std::cout << "] name[" << step.name_id << "]: " << step.name;
}
inline void print(const std::vector<RouteStep> &steps)
{
std::cout << "Path\n";
int segment = 0;
for (const auto &step : steps)
{
std::cout << "\t[" << segment++ << "]: ";
print(step);
std::cout << std::endl;
}
}
} // namespace guidance
} // namespace engine
} // namespace osrm
#endif /*OSRM_ENGINE_GUIDANCE_DEBUG_HPP_*/

View File

@ -2,6 +2,7 @@
#define ENGINE_GUIDANCE_STEP_MANEUVER_HPP
#include "extractor/guidance/turn_instruction.hpp"
#include "extractor/guidance/turn_lane_types.hpp"
#include "util/coordinate.hpp"
#include "util/guidance/turn_lanes.hpp"
@ -34,7 +35,7 @@ struct StepManeuver
unsigned exit;
util::guidance::LaneTupel lanes;
std::string turn_lane_string;
extractor::guidance::TurnLaneDescription lane_description;
};
inline StepManeuver getInvalidStepManeuver()
@ -46,7 +47,7 @@ inline StepManeuver getInvalidStepManeuver()
WaypointType::None,
0,
util::guidance::LaneTupel(),
""};
{}};
}
} // namespace guidance

View File

@ -327,7 +327,7 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
name_index,
weight_vector[i],
extractor::guidance::TurnInstruction::NO_TURN(),
{{0, INVALID_LANEID}, INVALID_LANE_STRINGID},
{{0, INVALID_LANEID}, INVALID_LANE_DESCRIPTIONID},
travel_mode,
INVALID_ENTRY_CLASSID});
}
@ -393,7 +393,7 @@ template <class DataFacadeT, class Derived> class BasicRoutingInterface
phantom_node_pair.target_phantom.name_id,
weight_vector[i],
extractor::guidance::TurnInstruction::NO_TURN(),
{{0, INVALID_LANEID}, INVALID_LANE_STRINGID},
{{0, INVALID_LANEID}, INVALID_LANE_DESCRIPTIONID},
target_traversed_in_reverse ? phantom_node_pair.target_phantom.backward_travel_mode
: phantom_node_pair.target_phantom.forward_travel_mode,
INVALID_ENTRY_CLASSID});

View File

@ -13,6 +13,7 @@
#include "extractor/guidance/turn_analysis.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include "extractor/guidance/turn_lane_types.hpp"
#include "util/guidance/bearing_class.hpp"
#include "util/guidance/entry_class.hpp"
@ -48,15 +49,17 @@ class EdgeBasedGraphFactory
EdgeBasedGraphFactory(const EdgeBasedGraphFactory &) = delete;
EdgeBasedGraphFactory &operator=(const EdgeBasedGraphFactory &) = delete;
explicit EdgeBasedGraphFactory(std::shared_ptr<util::NodeBasedDynamicGraph> node_based_graph,
const CompressedEdgeContainer &compressed_edge_container,
const std::unordered_set<NodeID> &barrier_nodes,
const std::unordered_set<NodeID> &traffic_lights,
std::shared_ptr<const RestrictionMap> restriction_map,
const std::vector<QueryNode> &node_info_list,
ProfileProperties profile_properties,
const util::NameTable &name_table,
const util::NameTable &turn_lanes);
explicit EdgeBasedGraphFactory(
std::shared_ptr<util::NodeBasedDynamicGraph> node_based_graph,
const CompressedEdgeContainer &compressed_edge_container,
const std::unordered_set<NodeID> &barrier_nodes,
const std::unordered_set<NodeID> &traffic_lights,
std::shared_ptr<const RestrictionMap> restriction_map,
const std::vector<QueryNode> &node_info_list,
ProfileProperties profile_properties,
const util::NameTable &name_table,
const std::vector<std::uint32_t> &turn_lane_offsets,
const std::vector<guidance::TurnLaneType::Mask> &turn_lane_masks);
void Run(const std::string &original_edge_data_filename,
const std::string &turn_lane_data_filename,
@ -119,7 +122,8 @@ class EdgeBasedGraphFactory
ProfileProperties profile_properties;
const util::NameTable &name_table;
const util::NameTable &turn_lanes;
const std::vector<std::uint32_t> &turn_lane_offsets;
const std::vector<guidance::TurnLaneType::Mask> &turn_lane_masks;
void CompressGeometry();
unsigned RenumberEdges();

View File

@ -3,12 +3,14 @@
#include "extractor/external_memory_node.hpp"
#include "extractor/first_and_last_segment_of_way.hpp"
#include "extractor/guidance/turn_lane_types.hpp"
#include "extractor/internal_extractor_edge.hpp"
#include "extractor/restriction.hpp"
#include "extractor/scripting_environment.hpp"
#include <stxxl/vector>
#include <unordered_map>
#include <cstdint>
namespace osrm
{
@ -40,6 +42,9 @@ class ExtractionContainers
void WriteCharData(const std::string &file_name,
const stxxl::vector<unsigned> &offests,
const stxxl::vector<char> &char_data) const;
void WriteTurnLaneMasks(const std::string &file_name,
const stxxl::vector<std::uint32_t> &turn_lane_offsets,
const stxxl::vector<guidance::TurnLaneType::Mask> &turn_lane_masks) const;
public:
using STXXLNodeIDVector = stxxl::vector<OSMNodeID>;
@ -53,8 +58,9 @@ class ExtractionContainers
STXXLEdgeVector all_edges_list;
stxxl::vector<char> name_char_data;
stxxl::vector<unsigned> name_lengths;
stxxl::vector<char> turn_lane_char_data;
stxxl::vector<unsigned> turn_lane_lengths;
// an adjacency array containing all turn lane masks
stxxl::vector<std::uint32_t> turn_lane_offsets;
stxxl::vector<guidance::TurnLaneType::Mask> turn_lane_masks;
STXXLRestrictionsVector restrictions_list;
STXXLWayIDStartEndVector way_start_end_id_list;
std::unordered_map<OSMNodeID, NodeID> external_to_internal_node_id_map;

View File

@ -2,6 +2,8 @@
#define EXTRACTOR_CALLBACKS_HPP
#include "util/typedefs.hpp"
#include "extractor/guidance/turn_lane_types.hpp"
#include <boost/functional/hash.hpp>
#include <boost/optional/optional_fwd.hpp>
@ -38,7 +40,7 @@ class ExtractorCallbacks
using MapKey = std::pair<std::string, std::string>;
using MapVal = unsigned;
std::unordered_map<MapKey, MapVal, boost::hash<MapKey>> string_map;
std::unordered_map<std::string, LaneStringID> lane_map;
std::unordered_map<guidance::TurnLaneDescription,LaneDescriptionID,guidance::TurnLaneDescription_hash> lane_description_map;
ExtractionContainers &external_memory;
public:

View File

@ -61,7 +61,7 @@ struct ExtractorConfig
output_file_name = basepath + ".osrm";
restriction_file_name = basepath + ".osrm.restrictions";
names_file_name = basepath + ".osrm.names";
turn_lane_strings_file_name = basepath + ".osrm.tls";
turn_lane_descriptions_file_name = basepath + ".osrm.tls";
turn_lane_data_file_name = basepath + ".osrm.tld";
timestamp_file_name = basepath + ".osrm.timestamp";
geometry_output_path = basepath + ".osrm.geometry";
@ -85,7 +85,7 @@ struct ExtractorConfig
std::string restriction_file_name;
std::string names_file_name;
std::string turn_lane_data_file_name;
std::string turn_lane_strings_file_name;
std::string turn_lane_descriptions_file_name;
std::string timestamp_file_name;
std::string geometry_output_path;
std::string edge_output_path;

View File

@ -1,46 +0,0 @@
#ifndef OSRM_EXTRACTOR_GUIDANCE_DEBUG_HPP_
#define OSRM_EXTRACTOR_GUIDANCE_DEBUG_HPP_
#include <iomanip>
#include <iostream>
#include <string>
namespace osrm
{
namespace extractor
{
namespace guidance
{
inline void print(const LaneDataVector &turn_lane_data)
{
std::cout << " Tags:\n";
for (auto entry : turn_lane_data)
std::cout << "\t" << entry.tag << " from: " << static_cast<int>(entry.from)
<< " to: " << static_cast<int>(entry.to) << "\n";
std::cout << std::flush;
}
inline void printTurnAssignmentData(const NodeID at,
const LaneDataVector &turn_lane_data,
const Intersection &intersection,
const std::vector<QueryNode> &node_info_list)
{
std::cout << "[Turn Assignment Progress]\nLocation:";
auto coordinate = node_info_list[at];
std::cout << std::setprecision(12) << toFloating(coordinate.lat) << " "
<< toFloating(coordinate.lon) << "\n";
std::cout << " Intersection:\n";
for (const auto &road)
std::cout << "\t" << toString(road) << "\n";
// flushes as well
print(turn_lane_data);
}
} // namespace guidance
} // namespace extractor
} // namespace osrm
#endif /* OSRM_EXTRACTOR_GUIDANCE_DEBUG_HPP_ */

View File

@ -2,6 +2,7 @@
#define OSRM_EXTRACTOR_GUIDANCE_TURN_LANE_DATA_HPP_
#include "util/typedefs.hpp"
#include "extractor/guidance/turn_lane_types.hpp"
#include <string>
#include <vector>
@ -16,7 +17,7 @@ namespace lanes
struct TurnLaneData
{
std::string tag;
TurnLaneType::Mask tag;
LaneID from;
LaneID to;
@ -25,13 +26,14 @@ struct TurnLaneData
typedef std::vector<TurnLaneData> LaneDataVector;
// convertes a string given in the OSM format into a TurnLaneData vector
LaneDataVector laneDataFromString(std::string turn_lane_string);
LaneDataVector laneDataFromDescription(const TurnLaneDescription &turn_lane_description);
// Locate A Tag in a lane data vector
LaneDataVector::const_iterator findTag(const std::string &tag, const LaneDataVector &data);
LaneDataVector::iterator findTag(const std::string &tag, LaneDataVector &data);
// Locate A Tag in a lane data vector (if multiple tags are set, the first one found is returned)
LaneDataVector::const_iterator findTag(const TurnLaneType::Mask tag, const LaneDataVector &data);
LaneDataVector::iterator findTag(const TurnLaneType::Mask tag, LaneDataVector &data);
bool hasTag(const std::string &tag, const LaneDataVector &data);
// Returns true if any of the queried tags is contained
bool hasTag(const TurnLaneType::Mask tag, const LaneDataVector &data);
} // namespace lane_data_generation

View File

@ -5,6 +5,7 @@
#include "extractor/guidance/toolkit.hpp"
#include "extractor/guidance/turn_analysis.hpp"
#include "extractor/guidance/turn_lane_data.hpp"
#include "extractor/guidance/turn_lane_types.hpp"
#include "extractor/query_node.hpp"
#include "util/guidance/turn_lanes.hpp"
@ -12,6 +13,7 @@
#include "util/node_based_graph.hpp"
#include "util/typedefs.hpp"
#include <cstdint>
#include <map>
#include <string>
#include <utility>
@ -34,7 +36,8 @@ class TurnLaneHandler
typedef std::vector<TurnLaneData> LaneDataVector;
TurnLaneHandler(const util::NodeBasedDynamicGraph &node_based_graph,
const util::NameTable &turn_lane_strings,
const std::vector<std::uint32_t> &turn_lane_offsets,
const std::vector<TurnLaneType::Mask> &turn_lane_masks,
const std::vector<QueryNode> &node_info_list,
const TurnAnalysis &turn_analysis);
@ -47,7 +50,8 @@ class TurnLaneHandler
// we need to be able to look at previous intersections to, in some cases, find the correct turn
// lanes for a turn
const util::NodeBasedDynamicGraph &node_based_graph;
const util::NameTable &turn_lane_strings;
const std::vector<std::uint32_t> &turn_lane_offsets;
const std::vector<TurnLaneType::Mask> &turn_lane_masks;
const std::vector<QueryNode> &node_info_list;
const TurnAnalysis &turn_analysis;
@ -58,7 +62,7 @@ class TurnLaneHandler
// in case of a simple intersection, assign the lane entries
Intersection simpleMatchTuplesToTurns(Intersection intersection,
const LaneDataVector &lane_data,
const LaneStringID lane_string_id,
const LaneDescriptionID lane_string_id,
LaneDataIdMap &id_map) const;
// partition lane data into lane data relevant at current turn and at next turn

View File

@ -21,24 +21,16 @@ namespace lanes
{
// Translate Turn Lane Tags into a matching modifier
DirectionModifier::Enum getMatchingModifier(const std::string &tag);
DirectionModifier::Enum getMatchingModifier(const TurnLaneType::Mask &tag);
// check whether a match of a given tag and a turn instruction can be seen as valid
bool isValidMatch(const std::string &tag, const TurnInstruction instruction);
bool isValidMatch(const TurnLaneType::Mask &tag, const TurnInstruction instruction);
// Every tag is somewhat idealized in form of the expected angle. A through lane should go straight
// (or follow a 180 degree turn angle between in/out segments.) The following function tries to find
// the best possible match for every tag in a given intersection, considering a few corner cases
// introduced to OSRM handling u-turns
typename Intersection::const_iterator findBestMatch(const std::string &tag,
// localisation of the best possible match for a tag
typename Intersection::const_iterator findBestMatch(const TurnLaneType::Mask &tag,
const Intersection &intersection);
// Reverse is a special case, because it requires access to the leftmost tag. It has its own
// matching function as a result of that. The leftmost tag is required, since u-turns are disabled
// by default in OSRM. Therefor we cannot check whether a turn is allowed, since it could be
// possible that it is forbidden. In addition, the best u-turn angle does not necessarily represent
// the u-turn, since it could be a sharp-left turn instead on a road with a middle island.
typename Intersection::const_iterator findBestMatchForReverse(const std::string &leftmost_tag,
const Intersection &intersection);
typename Intersection::const_iterator
findBestMatchForReverse(const TurnLaneType::Mask &leftmost_tag, const Intersection &intersection);
// a match is trivial if all turns can be associated with their best match in a valid way and the
// matches occur in order
@ -48,7 +40,7 @@ bool canMatchTrivially(const Intersection &intersection, const LaneDataVector &l
Intersection triviallyMatchLanesToTurns(Intersection intersection,
const LaneDataVector &lane_data,
const util::NodeBasedDynamicGraph &node_based_graph,
const LaneStringID lane_string_id,
const LaneDescriptionID lane_string_id,
LaneDataIdMap &lane_data_to_id);
} // namespace lanes

View File

@ -0,0 +1,102 @@
#ifndef OSRM_GUIDANCE_TURN_LANE_TYPES_HPP_
#define OSRM_GUIDANCE_TURN_LANE_TYPES_HPP_
#include <bitset>
#include <cstddef>
#include <cstdint>
#include <string>
#include <vector>
#include <boost/assert.hpp>
#include <boost/functional/hash_fwd.hpp>
#include "util/simple_logger.hpp"
#include "util/typedefs.hpp"
#include "util/json_container.hpp"
namespace osrm
{
namespace extractor
{
namespace guidance
{
namespace TurnLaneType
{
namespace detail
{
const constexpr std::size_t num_supported_lane_types = 11;
const constexpr char *translations[detail::num_supported_lane_types] = {"none",
"straight",
"sharp left",
"left",
"slight left",
"slight right",
"right",
"sharp right",
"uturn",
"merge to left",
"merge to right"};
} // namespace detail
typedef std::uint16_t Mask;
const constexpr Mask empty = 0u;
const constexpr Mask none = 1u << 0u;
const constexpr Mask straight = 1u << 1u;
const constexpr Mask sharp_left = 1u << 2u;
const constexpr Mask left = 1u << 3u;
const constexpr Mask slight_left = 1u << 4u;
const constexpr Mask slight_right = 1u << 5u;
const constexpr Mask right = 1u << 6u;
const constexpr Mask sharp_right = 1u << 7u;
const constexpr Mask uturn = 1u << 8u;
const constexpr Mask merge_to_left = 1u << 9u;
const constexpr Mask merge_to_right = 1u << 10u;
inline std::string toString(const Mask lane_type)
{
if (lane_type == 0)
return "none";
std::bitset<8 * sizeof(Mask)> mask(lane_type);
std::string result = "";
for (std::size_t lane_id_nr = 0; lane_id_nr < detail::num_supported_lane_types; ++lane_id_nr)
if (mask[lane_id_nr])
result += (result.empty() ? detail::translations[lane_id_nr]
: (std::string(";") + detail::translations[lane_id_nr]));
return result;
}
inline util::json::Array toJsonArray(const Mask lane_type)
{
util::json::Array result;
std::bitset<8 * sizeof(Mask)> mask(lane_type);
for (std::size_t lane_id_nr = 0; lane_id_nr < detail::num_supported_lane_types; ++lane_id_nr)
if (mask[lane_id_nr])
result.values.push_back(detail::translations[lane_id_nr]);
return result;
}
} // TurnLaneType
typedef std::vector<TurnLaneType::Mask> TurnLaneDescription;
// hash function for TurnLaneDescription
struct TurnLaneDescription_hash
{
std::size_t operator()(const TurnLaneDescription &lane_description) const
{
std::size_t seed = 0;
for (auto val : lane_description)
boost::hash_combine(seed, val);
return seed;
}
};
} // guidance
} // extractor
} // osrm
#endif /* OSRM_GUIDANCE_TURN_LANE_TYPES_HPP_ */

View File

@ -50,7 +50,7 @@ struct InternalExtractorEdge
true,
TRAVEL_MODE_INACCESSIBLE,
false,
INVALID_LANE_STRINGID,
guidance::TurnLaneType::empty,
guidance::RoadClassificationData())
{
}
@ -66,7 +66,7 @@ struct InternalExtractorEdge
bool startpoint,
TravelMode travel_mode,
bool is_split,
const LaneStringID lane_id,
LaneDescriptionID lane_description,
guidance::RoadClassificationData road_classification)
: result(OSMNodeID(source),
OSMNodeID(target),
@ -79,7 +79,7 @@ struct InternalExtractorEdge
startpoint,
travel_mode,
is_split,
lane_id,
lane_description,
std::move(road_classification)),
weight_data(std::move(weight_data))
{
@ -106,7 +106,7 @@ struct InternalExtractorEdge
true,
TRAVEL_MODE_INACCESSIBLE,
false,
INVALID_LANE_STRINGID,
INVALID_LANE_DESCRIPTIONID,
guidance::RoadClassificationData());
}
static InternalExtractorEdge max_osm_value()
@ -122,7 +122,7 @@ struct InternalExtractorEdge
true,
TRAVEL_MODE_INACCESSIBLE,
false,
INVALID_LANE_STRINGID,
INVALID_LANE_DESCRIPTIONID,
guidance::RoadClassificationData());
}

View File

@ -26,7 +26,7 @@ struct NodeBasedEdge
bool startpoint,
TravelMode travel_mode,
bool is_split,
const LaneStringID lane_id,
const LaneDescriptionID lane_description_id,
guidance::RoadClassificationData road_classification);
bool operator<(const NodeBasedEdge &other) const;
@ -42,7 +42,7 @@ struct NodeBasedEdge
bool startpoint : 1;
bool is_split : 1;
TravelMode travel_mode : 4;
LaneStringID lane_string_id;
LaneDescriptionID lane_description_id;
guidance::RoadClassificationData road_classification;
};
@ -59,7 +59,7 @@ struct NodeBasedEdgeWithOSM : NodeBasedEdge
bool startpoint,
TravelMode travel_mode,
bool is_split,
const LaneStringID lane_string_id,
const LaneDescriptionID lane_description_id,
guidance::RoadClassificationData road_classification);
OSMNodeID osm_source_id;
@ -71,7 +71,7 @@ struct NodeBasedEdgeWithOSM : NodeBasedEdge
inline NodeBasedEdge::NodeBasedEdge()
: source(SPECIAL_NODEID), target(SPECIAL_NODEID), name_id(0), weight(0), forward(false),
backward(false), roundabout(false), access_restricted(false), startpoint(true),
is_split(false), travel_mode(false), lane_string_id(0)
is_split(false), travel_mode(false), lane_description_id(INVALID_LANE_DESCRIPTIONID)
{
}
@ -86,12 +86,12 @@ inline NodeBasedEdge::NodeBasedEdge(NodeID source,
bool startpoint,
TravelMode travel_mode,
bool is_split,
const LaneStringID lane_string_id,
const LaneDescriptionID lane_description_id,
guidance::RoadClassificationData road_classification)
: source(source), target(target), name_id(name_id), weight(weight), forward(forward),
backward(backward), roundabout(roundabout), access_restricted(access_restricted),
startpoint(startpoint), is_split(is_split), travel_mode(travel_mode),
lane_string_id(lane_string_id), road_classification(std::move(road_classification))
lane_description_id(lane_description_id), road_classification(std::move(road_classification))
{
}
@ -124,7 +124,7 @@ inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM(
bool startpoint,
TravelMode travel_mode,
bool is_split,
const LaneStringID lane_string_id,
const LaneDescriptionID lane_description_id,
guidance::RoadClassificationData road_classification)
: NodeBasedEdge(SPECIAL_NODEID,
SPECIAL_NODEID,
@ -137,7 +137,7 @@ inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM(
startpoint,
travel_mode,
is_split,
lane_string_id,
lane_description_id,
std::move(road_classification)),
osm_source_id(std::move(source)), osm_target_id(std::move(target))
{

View File

@ -47,9 +47,8 @@ const constexpr char *block_id_to_name[] = {"NAME_OFFSETS",
"ENTRY_CLASS",
"LANE_DATA_ID",
"TURN_LANE_DATA",
"TURN_STRING_OFFSETS",
"TURN_STRING_BLOCKS",
"TURN_STRING_CHAR_LIST"};
"LANE_DESCRIPTION_OFFSETS",
"LANE_DESCRIPTION_MASKS"};
struct SharedDataLayout
{
@ -86,9 +85,8 @@ struct SharedDataLayout
ENTRY_CLASS,
LANE_DATA_ID,
TURN_LANE_DATA,
TURN_STRING_OFFSETS,
TURN_STRING_BLOCKS,
TURN_STRING_CHAR_LIST,
LANE_DESCRIPTION_OFFSETS,
LANE_DESCRIPTION_MASKS,
NUM_BLOCKS
};
@ -184,6 +182,9 @@ struct SharedDataTimestamp
SharedDataType data;
unsigned timestamp;
};
static_assert(sizeof(block_id_to_name) / sizeof(*block_id_to_name) == SharedDataLayout::NUM_BLOCKS,
"Number of blocks needs to match the number of Block names.");
}
}

View File

@ -66,7 +66,7 @@ struct StorageConfig final
boost::filesystem::path properties_path;
boost::filesystem::path intersection_class_path;
boost::filesystem::path turn_lane_data_path;
boost::filesystem::path turn_lane_string_path;
boost::filesystem::path turn_lane_description_path;
};
}
}

88
include/util/debug.hpp Normal file
View File

@ -0,0 +1,88 @@
#ifndef OSRM_ENGINE_GUIDANCE_DEBUG_HPP_
#define OSRM_ENGINE_GUIDANCE_DEBUG_HPP_
#include "extractor/guidance/intersection.hpp"
#include "extractor/guidance/turn_lane_data.hpp"
#include "extractor/query_node.hpp"
#include "engine/guidance/route_step.hpp"
#include "util/typedefs.hpp"
#include <iomanip>
#include <iostream>
#include <vector>
namespace osrm
{
namespace util
{
namespace guidance
{
inline void print(const engine::guidance::RouteStep &step)
{
std::cout << static_cast<int>(step.maneuver.instruction.type) << " "
<< static_cast<int>(step.maneuver.instruction.direction_modifier) << " "
<< static_cast<int>(step.maneuver.waypoint_type) << " Duration: " << step.duration
<< " Distance: " << step.distance << " Geometry: " << step.geometry_begin << " "
<< step.geometry_end << " exit: " << step.maneuver.exit
<< " Intersections: " << step.intersections.size() << " [";
for (const auto &intersection : step.intersections)
{
std::cout << "(bearings:";
for (auto bearing : intersection.bearings)
std::cout << " " << bearing;
std::cout << ", entry: ";
for (auto entry : intersection.entry)
std::cout << " " << (entry ? "true" : "false");
std::cout << ")";
}
std::cout << "] name[" << step.name_id << "]: " << step.name;
}
inline void print(const std::vector<engine::guidance::RouteStep> &steps)
{
std::cout << "Path\n";
int segment = 0;
for (const auto &step : steps)
{
std::cout << "\t[" << segment++ << "]: ";
print(step);
std::cout << std::endl;
}
}
inline void print(const extractor::guidance::lanes::LaneDataVector &turn_lane_data)
{
std::cout << " Tags:\n";
for (auto entry : turn_lane_data)
std::cout << "\t" << entry.tag << "("
<< extractor::guidance::TurnLaneType::toString(entry.tag)
<< ") from: " << static_cast<int>(entry.from)
<< " to: " << static_cast<int>(entry.to) << "\n";
std::cout << std::flush;
}
inline void
printTurnAssignmentData(const NodeID at,
const extractor::guidance::lanes::LaneDataVector &turn_lane_data,
const extractor::guidance::Intersection &intersection,
const std::vector<extractor::QueryNode> &node_info_list)
{
std::cout << "[Turn Assignment Progress]\nLocation:";
auto coordinate = node_info_list[at];
std::cout << std::setprecision(12) << toFloating(coordinate.lat) << " "
<< toFloating(coordinate.lon) << "\n";
std::cout << " Intersection:\n";
for (const auto &road : intersection)
std::cout << "\t" << toString(road) << "\n";
// flushes as well
print(turn_lane_data);
}
} // namespace guidance
} // namespace util
} // namespace osrm
#endif /*OSRM_ENGINE_GUIDANCE_DEBUG_HPP_*/

View File

@ -74,7 +74,7 @@ class LaneTupel
}
};
using LaneTupelIdPair = std::pair<util::guidance::LaneTupel, LaneStringID>;
using LaneTupelIdPair = std::pair<util::guidance::LaneTupel, LaneDescriptionID>;
} // namespace guidance
} // namespace util
} // namespace osrm

View File

@ -4,12 +4,14 @@
#include "util/simple_logger.hpp"
#include <boost/filesystem.hpp>
#include <boost/numeric/conversion/cast.hpp>
#include <cstddef>
#include <cstdint>
#include <bitset>
#include <fstream>
#include <stxxl/vector>
#include <vector>
#include "util/fingerprint.hpp"
@ -88,6 +90,84 @@ bool deserializeVector(std::istream &stream, std::vector<simple_type> &data)
return static_cast<bool>(stream);
}
// serializes a vector of vectors into an adjacency array (creates a copy of the data internally)
template <typename simple_type>
bool serializeVectorIntoAdjacencyArray(const std::string &filename,
const std::vector<std::vector<simple_type>> &data)
{
std::ofstream out_stream(filename, std::ios::binary);
std::vector<std::uint32_t> offsets;
offsets.reserve(data.size() + 1);
std::uint64_t current_offset = 0;
offsets.push_back(current_offset);
for (auto const &vec : data)
{
current_offset += vec.size();
offsets.push_back(boost::numeric_cast<std::uint32_t>(current_offset));
}
if (!serializeVector(out_stream, offsets))
return false;
std::vector<simple_type> all_data;
all_data.reserve(offsets.back());
for (auto const &vec : data)
all_data.insert(all_data.end(), vec.begin(), vec.end());
if (!serializeVector(out_stream, all_data))
return false;
return static_cast<bool>(out_stream);
}
template <typename simple_type, std::size_t WRITE_BLOCK_BUFFER_SIZE = 1024>
bool serializeVector(std::ofstream &out_stream, const stxxl::vector<simple_type> &data)
{
const std::uint64_t size = data.size();
out_stream.write(reinterpret_cast<const char *>(&size), sizeof(size));
simple_type write_buffer[WRITE_BLOCK_BUFFER_SIZE];
std::size_t buffer_len = 0;
for (const auto entry : data)
{
write_buffer[buffer_len++] = entry;
if (buffer_len >= WRITE_BLOCK_BUFFER_SIZE)
{
out_stream.write(reinterpret_cast<const char *>(write_buffer),
WRITE_BLOCK_BUFFER_SIZE * sizeof(simple_type));
buffer_len = 0;
}
}
// write remaining entries
if (buffer_len > 0)
out_stream.write(reinterpret_cast<const char *>(write_buffer),
buffer_len * sizeof(simple_type));
return static_cast<bool>(out_stream);
}
template <typename simple_type>
bool deserializeAdjacencyArray(const std::string &filename,
std::vector<std::uint32_t> &offsets,
std::vector<simple_type>& data)
{
std::ifstream in_stream(filename, std::ios::binary);
if (!deserializeVector(in_stream, offsets))
return false;
if (!deserializeVector(in_stream, data))
return false;
// offsets have to match up with the size of the data
if (offsets.empty() || (offsets.back() != boost::numeric_cast<std::uint32_t>(data.size())))
return false;
return static_cast<bool>(in_stream);
}
inline bool serializeFlags(const boost::filesystem::path &path, const std::vector<bool> &flags)
{
// TODO this should be replaced with a FILE-based write using error checking

View File

@ -21,7 +21,7 @@ struct NodeBasedEdgeData
: distance(INVALID_EDGE_WEIGHT), edge_id(SPECIAL_NODEID),
name_id(std::numeric_limits<unsigned>::max()), access_restricted(false), reversed(false),
roundabout(false), travel_mode(TRAVEL_MODE_INACCESSIBLE),
lane_string_id(INVALID_LANE_STRINGID)
lane_description_id(INVALID_LANE_DESCRIPTIONID)
{
}
@ -33,10 +33,10 @@ struct NodeBasedEdgeData
bool roundabout,
bool startpoint,
extractor::TravelMode travel_mode,
const LaneStringID lane_string_id)
const LaneDescriptionID lane_description_id)
: distance(distance), edge_id(edge_id), name_id(name_id),
access_restricted(access_restricted), reversed(reversed), roundabout(roundabout),
startpoint(startpoint), travel_mode(travel_mode), lane_string_id(lane_string_id)
startpoint(startpoint), travel_mode(travel_mode), lane_description_id(lane_description_id)
{
}
@ -48,7 +48,7 @@ struct NodeBasedEdgeData
bool roundabout : 1;
bool startpoint : 1;
extractor::TravelMode travel_mode : 4;
LaneStringID lane_string_id;
LaneDescriptionID lane_description_id;
extractor::guidance::RoadClassificationData road_classification;
bool IsCompatibleTo(const NodeBasedEdgeData &other) const
@ -83,7 +83,7 @@ NodeBasedDynamicGraphFromEdges(NodeID number_of_nodes,
output_edge.data.travel_mode = input_edge.travel_mode;
output_edge.data.startpoint = input_edge.startpoint;
output_edge.data.road_classification = input_edge.road_classification;
output_edge.data.lane_string_id = input_edge.lane_string_id;
output_edge.data.lane_description_id = input_edge.lane_description_id;
});
tbb::parallel_sort(edges_list.begin(), edges_list.end());

View File

@ -59,12 +59,12 @@ using EdgeID = std::uint32_t;
using NameID = std::uint32_t;
using EdgeWeight = std::int32_t;
using LaneStringID = std::uint16_t;
static const LaneStringID INVALID_LANE_STRINGID = std::numeric_limits<LaneStringID>::max();
using LaneID = std::uint8_t;
static const LaneID INVALID_LANEID = std::numeric_limits<LaneID>::max();
using LaneDataID = std::uint16_t;
static const LaneDataID INVALID_LANE_DATAID = std::numeric_limits<LaneStringID>::max();
static const LaneDataID INVALID_LANE_DATAID = std::numeric_limits<LaneDataID>::max();
using LaneDescriptionID = std::uint16_t;
static const LaneDescriptionID INVALID_LANE_DESCRIPTIONID = std::numeric_limits<LaneDescriptionID>::max();
using BearingClassID = std::uint32_t;
static const BearingClassID INVALID_BEARING_CLASSID = std::numeric_limits<BearingClassID>::max();

View File

@ -11,7 +11,6 @@
#include <boost/assert.hpp>
#include <boost/optional.hpp>
#include <boost/tokenizer.hpp>
#include <algorithm>
#include <iterator>
@ -76,23 +75,18 @@ util::json::Array lanesFromManeuver(const guidance::StepManeuver &maneuver)
{
BOOST_ASSERT(maneuver.lanes.lanes_in_turn >= 1);
util::json::Array result;
LaneID lane_id = 0;
typedef boost::tokenizer<boost::char_separator<char>> tokenizer;
boost::char_separator<char> sep("|", "", boost::keep_empty_tokens);
tokenizer tokens(maneuver.turn_lane_string, sep);
LaneID lane_id = maneuver.lane_description.size();
lane_id = std::distance(tokens.begin(), tokens.end());
for (auto iter = tokens.begin(); iter != tokens.end(); ++iter)
for (const auto &lane_desc : maneuver.lane_description)
{
--lane_id;
util::json::Object lane;
lane.values["marked"] = (iter->empty() ? "none" : *iter);
lane.values["indications"] = extractor::guidance::TurnLaneType::toJsonArray(lane_desc);
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();
lane.values["valid"] = util::json::True();
else
lane.values["take"] = util::json::False();
lane.values["valid"] = util::json::False();
result.values.push_back(lane);
}

View File

@ -140,8 +140,6 @@ RouteStep forwardInto(RouteStep destination, const RouteStep &source)
destination.geometry_begin = std::min(destination.geometry_begin, source.geometry_begin);
destination.geometry_end = std::max(destination.geometry_end, source.geometry_end);
destination.maneuver.exit = source.maneuver.exit;
return destination;
}
@ -224,6 +222,7 @@ void closeOffRoundabout(const bool on_roundabout,
const std::size_t step_index)
{
auto &step = steps[step_index];
step.maneuver.exit += 1;
if (!on_roundabout)
{
// We reached a special case that requires the addition of a special route step in the
@ -257,7 +256,6 @@ void closeOffRoundabout(const bool on_roundabout,
if (steps[1].maneuver.instruction.type == TurnType::EnterRotary)
steps[1].rotary_name = steps[0].name;
}
step.maneuver.exit += 1;
// Normal exit from the roundabout, or exit from a previously fixed roundabout. Propagate the
// index back to the entering location and prepare the current silent set of instructions for
@ -280,7 +278,6 @@ void closeOffRoundabout(const bool on_roundabout,
propagation_step = forwardInto(propagation_step, steps[propagation_index + 1]);
if (entersRoundabout(propagation_step.maneuver.instruction))
{
propagation_step.maneuver.exit = step.maneuver.exit;
const auto entry_intersection = propagation_step.intersections.front();
// remember rotary name
@ -412,7 +409,7 @@ void collapseTurnAt(std::vector<RouteStep> &steps,
else if (one_back_step.distance <= MAX_COLLAPSE_DISTANCE &&
isCollapsableInstruction(current_step.maneuver.instruction))
{
// TODO check for lanes
// TODO check for lanes (https://github.com/Project-OSRM/osrm-backend/issues/2553)
if (compatible(one_back_step, current_step))
{
steps[one_back_index] = elongate(std::move(steps[one_back_index]), steps[step_index]);
@ -583,8 +580,6 @@ std::vector<RouteStep> postProcess(std::vector<RouteStep> steps)
has_entered_roundabout = false;
on_roundabout = false;
}
else if (has_entered_roundabout)
steps[step_index + 1].maneuver.exit = step.maneuver.exit;
}
// unterminated roundabout
@ -864,7 +859,7 @@ void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry)
// we need to make this conform with the intersection format for the first intersection
auto &first_intersection = designated_depart.intersections.front();
designated_depart.maneuver.lanes = util::guidance::LaneTupel();
designated_depart.maneuver.turn_lane_string = "";
designated_depart.maneuver.lane_description.clear();
first_intersection.bearings = {first_intersection.bearings[first_intersection.out]};
first_intersection.entry = {true};
first_intersection.in = Intersection::NO_INDEX;
@ -932,7 +927,7 @@ void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry)
next_to_last_step.maneuver.instruction = TurnInstruction::NO_TURN();
next_to_last_step.maneuver.bearing_after = 0;
next_to_last_step.maneuver.lanes = util::guidance::LaneTupel();
next_to_last_step.maneuver.turn_lane_string = "";
next_to_last_step.maneuver.lane_description.clear();
BOOST_ASSERT(next_to_last_step.intersections.size() == 1);
auto &last_intersection = next_to_last_step.intersections.back();
last_intersection.bearings = {last_intersection.bearings[last_intersection.in]};

View File

@ -1,5 +1,5 @@
#include "extractor/edge_based_graph_factory.hpp"
#include "extractor/edge_based_edge.hpp"
#include "extractor/edge_based_graph_factory.hpp"
#include "util/coordinate.hpp"
#include "util/coordinate_calculation.hpp"
#include "util/exception.hpp"
@ -41,13 +41,14 @@ EdgeBasedGraphFactory::EdgeBasedGraphFactory(
const std::vector<QueryNode> &node_info_list,
ProfileProperties profile_properties,
const util::NameTable &name_table,
const util::NameTable &turn_lanes)
const std::vector<std::uint32_t> &turn_lane_offsets,
const std::vector<guidance::TurnLaneType::Mask> &turn_lane_masks)
: m_max_edge_id(0), m_node_info_list(node_info_list),
m_node_based_graph(std::move(node_based_graph)),
m_restriction_map(std::move(restriction_map)), m_barrier_nodes(barrier_nodes),
m_traffic_lights(traffic_lights), m_compressed_edge_container(compressed_edge_container),
profile_properties(std::move(profile_properties)), name_table(name_table),
turn_lanes(turn_lanes)
turn_lane_offsets(turn_lane_offsets), turn_lane_masks(turn_lane_masks)
{
}
@ -346,7 +347,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
name_table,
street_name_suffix_table);
guidance::lanes::TurnLaneHandler turn_lane_handler(
*m_node_based_graph, turn_lanes, m_node_info_list, turn_analysis);
*m_node_based_graph, turn_lane_offsets, turn_lane_masks, m_node_info_list, turn_analysis);
bearing_class_by_node_based_node.resize(m_node_based_graph->GetNumberOfNodes(),
std::numeric_limits<std::uint32_t>::max());

View File

@ -6,6 +6,7 @@
#include "util/exception.hpp"
#include "util/fingerprint.hpp"
#include "util/io.hpp"
#include "util/lua_util.hpp"
#include "util/simple_logger.hpp"
#include "util/timing_util.hpp"
@ -51,7 +52,11 @@ ExtractionContainers::ExtractionContainers()
name_lengths.push_back(0);
name_lengths.push_back(0);
name_lengths.push_back(0);
turn_lane_lengths.push_back(0);
// the offsets have to be initialized with two values, since we have the empty turn string for
// the first id
turn_lane_offsets.push_back(0);
turn_lane_offsets.push_back(0);
}
/**
@ -86,7 +91,7 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
WriteRestrictions(restrictions_file_name);
WriteCharData(name_file_name, name_lengths, name_char_data);
WriteCharData(turn_lane_file_name, turn_lane_lengths, turn_lane_char_data);
WriteTurnLaneMasks(turn_lane_file_name, turn_lane_offsets, turn_lane_masks);
}
catch (const std::exception &e)
{
@ -94,6 +99,32 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
}
}
void ExtractionContainers::WriteTurnLaneMasks(
const std::string &file_name,
const stxxl::vector<std::uint32_t> &offsets,
const stxxl::vector<guidance::TurnLaneType::Mask> &masks) const
{
util::SimpleLogger().Write() << "Writing turn lane masks...";
TIMER_START(turn_lane_timer);
std::ofstream ofs(file_name, std::ios::binary);
if (!util::serializeVector(ofs, offsets))
{
util::SimpleLogger().Write(logWARNING) << "Error while writing.";
return;
}
if (!util::serializeVector(ofs, masks))
{
util::SimpleLogger().Write(logWARNING) << "Error while writing.";
return;
}
TIMER_STOP(turn_lane_timer);
util::SimpleLogger().Write() << "done (" << TIMER_SEC(turn_lane_timer) << ")";
}
void ExtractionContainers::WriteCharData(const std::string &file_name,
const stxxl::vector<unsigned> &offsets,
const stxxl::vector<char> &char_data) const

View File

@ -239,7 +239,7 @@ int Extractor::run()
extraction_containers.PrepareData(config.output_file_name,
config.restriction_file_name,
config.names_file_name,
config.turn_lane_strings_file_name,
config.turn_lane_descriptions_file_name,
main_context.state);
WriteProfileProperties(config.profile_properties_output_path, main_context.properties);
@ -504,7 +504,14 @@ Extractor::BuildEdgeExpandedGraph(lua_State *lua_state,
compressed_edge_container.SerializeInternalVector(config.geometry_output_path);
util::NameTable name_table(config.names_file_name);
util::NameTable turn_lanes(config.turn_lane_strings_file_name);
std::vector<std::uint32_t> turn_lane_offsets;
std::vector<guidance::TurnLaneType::Mask> turn_lane_masks;
if( !util::deserializeAdjacencyArray(
config.turn_lane_descriptions_file_name, turn_lane_offsets, turn_lane_masks) )
{
util::SimpleLogger().Write(logWARNING) << "Reading Turn Lane Masks failed.";
}
EdgeBasedGraphFactory edge_based_graph_factory(
node_based_graph,
@ -515,7 +522,8 @@ Extractor::BuildEdgeExpandedGraph(lua_State *lua_state,
internal_to_external_node_map,
profile_properties,
name_table,
turn_lanes);
turn_lane_offsets,
turn_lane_masks);
edge_based_graph_factory.Run(config.edge_output_path,
config.turn_lane_data_file_name,

View File

@ -1,17 +1,17 @@
#include "extractor/extractor_callbacks.hpp"
#include "extractor/external_memory_node.hpp"
#include "extractor/extraction_containers.hpp"
#include "extractor/extraction_node.hpp"
#include "extractor/extraction_way.hpp"
#include "extractor/external_memory_node.hpp"
#include "extractor/extractor_callbacks.hpp"
#include "extractor/restriction.hpp"
#include "util/for_each_pair.hpp"
#include "util/guidance/turn_lanes.hpp"
#include "util/simple_logger.hpp"
#include "extractor/extractor_callbacks.hpp"
#include <boost/numeric/conversion/cast.hpp>
#include <boost/optional/optional.hpp>
#include <boost/tokenizer.hpp>
#include <osmium/osm.hpp>
@ -27,12 +27,15 @@ namespace osrm
namespace extractor
{
using TurnLaneDescription = guidance::TurnLaneDescription;
namespace TurnLaneType = guidance::TurnLaneType;
ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers &extraction_containers)
: external_memory(extraction_containers)
{
// we reserved 0, 1, 2 for the empty case
string_map[MapKey("", "")] = 0;
lane_map[""] = 0;
lane_description_map[TurnLaneDescription()] = 0;
}
/**
@ -144,44 +147,109 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
road_classification.road_class = guidance::functionalRoadClassFromTag(data);
}
// Deduplicates street names and street destination names based on the street_map map.
// In case we do not already store the name, inserts (name, id) tuple and return id.
// Otherwise fetches the id based on the name and returns it without insertion.
const auto laneStringToDescription = [](std::string lane_string) -> TurnLaneDescription {
if (lane_string.empty())
return {};
const constexpr auto MAX_STRING_LENGTH = 255u;
const auto requestId = [this, MAX_STRING_LENGTH](const std::string &turn_lane_string_) {
if (turn_lane_string_ == "")
return INVALID_LANE_STRINGID;
TurnLaneDescription lane_description;
// 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 = '|';
typedef boost::tokenizer<boost::char_separator<char>> tokenizer;
boost::char_separator<char> sep("|&", "", boost::keep_empty_tokens);
boost::char_separator<char> inner_sep(";", "");
tokenizer tokens(lane_string, sep);
const auto &lane_map_iterator = lane_map.find(turn_lane_string);
if (lane_map.end() == lane_map_iterator)
const constexpr std::size_t num_osm_tags = 11;
const constexpr char *osm_lane_strings[num_osm_tags] = {"none",
"through",
"sharp_left",
"left",
"slight_left",
"slight_right",
"right",
"sharp_right",
"reverse",
"merge_to_left",
"merge_to_right"};
const constexpr TurnLaneType::Mask masks_by_osm_string[num_osm_tags + 1] = {
TurnLaneType::none,
TurnLaneType::straight,
TurnLaneType::sharp_left,
TurnLaneType::left,
TurnLaneType::slight_left,
TurnLaneType::slight_right,
TurnLaneType::right,
TurnLaneType::sharp_right,
TurnLaneType::uturn,
TurnLaneType::merge_to_left,
TurnLaneType::merge_to_right,
TurnLaneType::empty}; // fallback, if string not found
for (auto iter = tokens.begin(); iter != tokens.end(); ++iter)
{
LaneStringID turn_lane_id =
boost::numeric_cast<LaneStringID>(external_memory.turn_lane_lengths.size());
auto turn_lane_length = std::min<unsigned>(MAX_STRING_LENGTH, turn_lane_string.size());
std::copy(turn_lane_string.c_str(),
turn_lane_string.c_str() + turn_lane_length,
std::back_inserter(external_memory.turn_lane_char_data));
external_memory.turn_lane_lengths.push_back(turn_lane_length);
lane_map.insert(std::make_pair(turn_lane_string, turn_lane_id));
return turn_lane_id;
tokenizer inner_tokens(*iter, inner_sep);
guidance::TurnLaneType::Mask lane_mask = inner_tokens.begin() == inner_tokens.end()
? TurnLaneType::none
: TurnLaneType::empty;
for (auto token_itr = inner_tokens.begin(); token_itr != inner_tokens.end();
++token_itr)
{
auto position = std::find(osm_lane_strings, osm_lane_strings + num_osm_tags, *token_itr);
const auto translated_mask =
masks_by_osm_string[std::distance(osm_lane_strings, position)];
if (translated_mask == TurnLaneType::empty)
{
// if we have unsupported tags, don't handle them
util::SimpleLogger().Write(logDEBUG) << "Unsupported lane tag found: \""
<< *token_itr << "\"";
return {};
}
BOOST_ASSERT((lane_mask & translated_mask) == 0); // make sure the mask is valid
lane_mask |= translated_mask;
}
// add the lane to the description
lane_description.push_back(lane_mask);
}
return lane_description;
};
// convert the lane description into an ID and, if necessary, remembr the description in the
// description_map
const auto requestId = [&](std::string lane_string) {
if( lane_string.empty() )
return INVALID_LANE_DESCRIPTIONID;
TurnLaneDescription lane_description = laneStringToDescription(std::move(lane_string));
const auto lane_description_itr = lane_description_map.find(lane_description);
if (lane_description_itr == lane_description_map.end())
{
const LaneDescriptionID new_id =
boost::numeric_cast<LaneDescriptionID>(lane_description_map.size());
lane_description_map[lane_description] = new_id;
// since we are getting a new ID, we can augment the current offsets
// and store the turn lane masks, sadly stxxl does not support insert
for (const auto mask : lane_description)
external_memory.turn_lane_masks.push_back(mask);
external_memory.turn_lane_offsets.push_back(external_memory.turn_lane_offsets.back() +
lane_description.size());
return new_id;
}
else
{
return lane_map_iterator->second;
return lane_description_itr->second;
}
};
// Deduplicates street names and street destination names based on the street_map map.
// In case we do not already store the name, inserts (name, id) tuple and return id.
// Otherwise fetches the id based on the name and returns it without insertion.
const auto turn_lane_id_forward = requestId(parsed_way.turn_lanes_forward);
const auto turn_lane_id_backward = requestId(parsed_way.turn_lanes_backward);
const constexpr auto MAX_STRING_LENGTH = 255u;
// Get the unique identifier for the street name
// Get the unique identifier for the street name and destination
const auto name_iterator = string_map.find(MapKey(parsed_way.name, parsed_way.destinations));

View File

@ -160,18 +160,18 @@ void GraphCompressor::Compress(const std::unordered_set<NodeID> &barrier_nodes,
* turn-lanes. Without this,we would have to treat any turn-lane beginning/ending just
* like a barrier.
*/
const auto selectLaneID = [](const LaneStringID front, const LaneStringID back) {
const auto selectLaneID = [](const LaneDescriptionID front, const LaneDescriptionID back) {
// A lane has tags: u - (front) - v - (back) - w
// During contraction, we keep only one of the tags. Usually the one closer to the
// intersection is preferred. If its empty, however, we keep the non-empty one
if (back == INVALID_LANE_STRINGID)
if (back == INVALID_LANE_DESCRIPTIONID)
return front;
return back;
};
graph.GetEdgeData(forward_e1).lane_string_id = selectLaneID(
graph.GetEdgeData(forward_e1).lane_string_id, fwd_edge_data2.lane_string_id);
graph.GetEdgeData(reverse_e1).lane_string_id = selectLaneID(
graph.GetEdgeData(reverse_e1).lane_string_id, rev_edge_data2.lane_string_id);
graph.GetEdgeData(forward_e1).lane_description_id = selectLaneID(
graph.GetEdgeData(forward_e1).lane_description_id, fwd_edge_data2.lane_description_id);
graph.GetEdgeData(reverse_e1).lane_description_id = selectLaneID(
graph.GetEdgeData(reverse_e1).lane_description_id, rev_edge_data2.lane_description_id);
// remove e2's (if bidir, otherwise only one)
graph.DeleteEdge(node_v, forward_e2);

View File

@ -1,4 +1,5 @@
#include "extractor/guidance/turn_lane_augmentation.hpp"
#include "extractor/guidance/turn_lane_types.hpp"
#include "util/simple_logger.hpp"
#include <algorithm>
@ -18,14 +19,14 @@ namespace lanes
namespace
{
const constexpr char *tag_by_modifier[] = {"reverse",
"sharp_right",
"right",
"slight_right",
"through",
"slight_left",
"left",
"sharp_left"};
const constexpr TurnLaneType::Mask tag_by_modifier[] = {TurnLaneType::uturn,
TurnLaneType::sharp_right,
TurnLaneType::right,
TurnLaneType::slight_right,
TurnLaneType::straight,
TurnLaneType::slight_left,
TurnLaneType::left,
TurnLaneType::sharp_left};
std::size_t getNumberOfTurns(const Intersection &intersection)
{
@ -126,7 +127,6 @@ LaneDataVector augmentMultiple(const std::size_t none_index,
// This handles situations like "left | | | right".
LaneDataVector mergeNoneTag(const std::size_t none_index, LaneDataVector lane_data)
{
if (none_index == 0 || none_index + 1 == lane_data.size())
{
if (none_index == 0)
@ -175,11 +175,11 @@ LaneDataVector handleRenamingSituations(const std::size_t none_index,
if (none_index == 0)
{
if (has_right &&
(lane_data.size() == 1 || (lane_data[none_index + 1].tag != "sharp_right" &&
lane_data[none_index + 1].tag != "right")))
(lane_data.size() == 1 || (lane_data[none_index + 1].tag != TurnLaneType::sharp_right &&
lane_data[none_index + 1].tag != TurnLaneType::right)))
{
lane_data[none_index].tag = "right";
if (lane_data.size() > 1 && lane_data[none_index + 1].tag == "through")
lane_data[none_index].tag = TurnLaneType::right;
if (lane_data.size() > 1 && lane_data[none_index + 1].tag == TurnLaneType::straight)
{
lane_data[none_index + 1].from = lane_data[none_index].from;
// turning right through a possible through lane is not possible
@ -187,39 +187,39 @@ LaneDataVector handleRenamingSituations(const std::size_t none_index,
}
}
else if (has_through &&
(lane_data.size() == 1 || lane_data[none_index + 1].tag != "through"))
(lane_data.size() == 1 || lane_data[none_index + 1].tag != TurnLaneType::straight))
{
lane_data[none_index].tag = "through";
lane_data[none_index].tag = TurnLaneType::straight;
}
}
else if (none_index + 1 == lane_data.size())
{
if (has_left && ((lane_data[none_index - 1].tag != "sharp_left" &&
lane_data[none_index - 1].tag != "left")))
if (has_left && ((lane_data[none_index - 1].tag != TurnLaneType::sharp_left &&
lane_data[none_index - 1].tag != TurnLaneType::left)))
{
lane_data[none_index].tag = "left";
if (lane_data[none_index - 1].tag == "through")
lane_data[none_index].tag = TurnLaneType::left;
if (lane_data[none_index - 1].tag == TurnLaneType::straight)
{
lane_data[none_index - 1].to = lane_data[none_index].to;
// turning left through a possible through lane is not possible
lane_data[none_index].from = lane_data[none_index].to;
}
}
else if (has_through && lane_data[none_index - 1].tag != "through")
else if (has_through && lane_data[none_index - 1].tag != TurnLaneType::straight)
{
lane_data[none_index].tag = "through";
lane_data[none_index].tag = TurnLaneType::straight;
}
}
else
{
if ((lane_data[none_index + 1].tag == "left" ||
lane_data[none_index + 1].tag == "slight_left" ||
lane_data[none_index + 1].tag == "sharp_left") &&
(lane_data[none_index - 1].tag == "right" ||
lane_data[none_index - 1].tag == "slight_right" ||
lane_data[none_index - 1].tag == "sharp_right"))
if ((lane_data[none_index + 1].tag == TurnLaneType::left ||
lane_data[none_index + 1].tag == TurnLaneType::slight_left ||
lane_data[none_index + 1].tag == TurnLaneType::sharp_left) &&
(lane_data[none_index - 1].tag == TurnLaneType::right ||
lane_data[none_index - 1].tag == TurnLaneType::slight_right ||
lane_data[none_index - 1].tag == TurnLaneType::sharp_right))
{
lane_data[none_index].tag = "through";
lane_data[none_index].tag = TurnLaneType::straight;
}
}
return std::move(lane_data);
@ -236,7 +236,7 @@ LaneDataVector handleNoneValueAtSimpleTurn(LaneDataVector lane_data,
const Intersection &intersection)
{
const bool needs_no_processing =
(intersection.empty() || lane_data.empty() || !hasTag("none", lane_data));
(intersection.empty() || lane_data.empty() || !hasTag(TurnLaneType::none, lane_data));
if (needs_no_processing)
return std::move(lane_data);
@ -265,10 +265,10 @@ LaneDataVector handleNoneValueAtSimpleTurn(LaneDataVector lane_data,
const std::size_t connection_count =
getNumberOfTurns(intersection) -
((intersection[0].entry_allowed && lane_data.back().tag != "reverse") ? 1 : 0);
((intersection[0].entry_allowed && lane_data.back().tag != TurnLaneType::uturn) ? 1 : 0);
// TODO check for impossible turns to see whether the turn lane is at the correct place
const std::size_t none_index = std::distance(lane_data.begin(), findTag("none", lane_data));
const std::size_t none_index = std::distance(lane_data.begin(), findTag(TurnLaneType::none, lane_data));
BOOST_ASSERT(none_index != lane_data.size());
// we have to create multiple turns
if (connection_count > lane_data.size())
@ -279,7 +279,7 @@ LaneDataVector handleNoneValueAtSimpleTurn(LaneDataVector lane_data,
// we have to reduce it, assigning it to neighboring turns
else if (connection_count < lane_data.size())
{
// a prerequisite is simple turns. Larger differences should not end up here
// a pgerequisite is simple turns. Larger differences should not end up here
// an additional line at the side is only reasonable if it is targeting public
// service vehicles. Otherwise, we should not have it
BOOST_ASSERT(connection_count + 1 == lane_data.size());

View File

@ -30,55 +30,69 @@ bool TurnLaneData::operator<(const TurnLaneData &other) const
if (to > other.to)
return false;
const constexpr char *tag_by_modifier[] = {"sharp_right",
"right",
"slight_right",
"through",
"slight_left",
"left",
"sharp_left",
"reverse"};
const constexpr TurnLaneType::Mask tag_by_modifier[] = {TurnLaneType::sharp_right,
TurnLaneType::right,
TurnLaneType::slight_right,
TurnLaneType::straight,
TurnLaneType::slight_left,
TurnLaneType::left,
TurnLaneType::sharp_left,
TurnLaneType::uturn};
return std::find(tag_by_modifier, tag_by_modifier + 8, this->tag) <
std::find(tag_by_modifier, tag_by_modifier + 8, other.tag);
}
LaneDataVector laneDataFromString(std::string turn_lane_string)
LaneDataVector laneDataFromDescription(const TurnLaneDescription &turn_lane_description)
{
typedef std::unordered_map<std::string, std::pair<LaneID, LaneID>> LaneMap;
typedef std::unordered_map<TurnLaneType::Mask, std::pair<LaneID, LaneID>> LaneMap;
// FIXME this is a workaround due to https://github.com/cucumber/cucumber-js/issues/417,
// need to switch statements when fixed
// const auto num_lanes = std::count(turn_lane_string.begin(), turn_lane_string.end(), '|') + 1;
// count the number of lanes
const auto num_lanes = [](const std::string &turn_lane_string) {
return boost::numeric_cast<LaneID>(
std::count(turn_lane_string.begin(), turn_lane_string.end(), '|') + 1);
}(turn_lane_string);
const auto num_lanes = boost::numeric_cast<LaneID>(turn_lane_description.size());
const auto setLaneData = [&](
LaneMap &map, TurnLaneType::Mask full_mask, const LaneID current_lane) {
const auto isSet = [&](const TurnLaneType::Mask test_mask) -> bool {
return (test_mask & full_mask) == test_mask;
};
const auto getNextTag = [](std::string &string, const char *separators) {
auto pos = string.find_last_of(separators);
auto result = pos != std::string::npos ? string.substr(pos + 1) : string;
string.resize(pos == std::string::npos ? 0 : pos);
return result;
};
const auto setLaneData = [&](LaneMap &map, std::string lane, const LaneID current_lane) {
do
for (std::size_t shift = 0; shift < TurnLaneType::detail::num_supported_lane_types; ++shift)
{
auto identifier = getNextTag(lane, ";");
if (identifier.empty())
identifier = "none";
auto map_iterator = map.find(identifier);
if (map_iterator == map.end())
map[identifier] = std::make_pair(current_lane, current_lane);
else
TurnLaneType::Mask mask = 1 << shift;
if (isSet(mask))
{
map_iterator->second.second = current_lane;
auto map_iterator = map.find(mask);
if (map_iterator == map.end())
map[mask] = std::make_pair(current_lane, current_lane);
else
{
map_iterator->second.first = current_lane;
}
}
} while (!lane.empty());
}
};
LaneMap lane_map;
LaneID lane_nr = num_lanes - 1;
if (turn_lane_description.empty())
return {};
for (auto full_mask : turn_lane_description)
{
setLaneData(lane_map, full_mask, lane_nr);
--lane_nr;
}
// transform the map into the lane data vector
LaneDataVector lane_data;
for (const auto tag : lane_map)
{
lane_data.push_back({tag.first, tag.second.first, tag.second.second});
}
std::sort(lane_data.begin(), lane_data.end());
// check whether a given turn lane string resulted in valid lane data
const auto hasValidOverlaps = [](const LaneDataVector &lane_data) {
// Allow an overlap of at most one. Larger overlaps would result in crossing another turn,
@ -91,50 +105,26 @@ LaneDataVector laneDataFromString(std::string turn_lane_string)
return true;
};
LaneMap lane_map;
LaneID lane_nr = 0;
LaneDataVector lane_data;
if (turn_lane_string.empty())
return lane_data;
do
{
// FIXME this is a cucumber workaround, since escaping does not work properly in
// cucumber.js (see https://github.com/cucumber/cucumber-js/issues/417). Needs to be
// changed to "|" only, when the bug is fixed
auto lane = getNextTag(turn_lane_string, "|");
setLaneData(lane_map, lane, lane_nr);
++lane_nr;
} while (lane_nr < num_lanes);
for (const auto tag : lane_map)
{
lane_data.push_back({tag.first, tag.second.first, tag.second.second});
}
std::sort(lane_data.begin(), lane_data.end());
if (!hasValidOverlaps(lane_data))
{
lane_data.clear();
}
return lane_data;
}
LaneDataVector::iterator findTag(const std::string &tag, LaneDataVector &data)
LaneDataVector::iterator findTag(const TurnLaneType::Mask tag, LaneDataVector &data)
{
return std::find_if(data.begin(), data.end(), [&](const TurnLaneData &lane_data) {
return tag == lane_data.tag;
return (tag & lane_data.tag) != TurnLaneType::empty;
});
}
LaneDataVector::const_iterator findTag(const std::string &tag, const LaneDataVector &data)
LaneDataVector::const_iterator findTag(const TurnLaneType::Mask tag, const LaneDataVector &data)
{
return std::find_if(data.cbegin(), data.cend(), [&](const TurnLaneData &lane_data) {
return tag == lane_data.tag;
return (tag & lane_data.tag) != TurnLaneType::empty;
});
}
bool hasTag(const std::string &tag, const LaneDataVector &data)
bool hasTag(const TurnLaneType::Mask tag, const LaneDataVector &data)
{
return findTag(tag, data) != data.cend();
}

View File

@ -1,7 +1,7 @@
#include "extractor/guidance/turn_lane_handler.hpp"
#include "extractor/guidance/constants.hpp"
#include "extractor/guidance/turn_discovery.hpp"
#include "extractor/guidance/turn_lane_augmentation.hpp"
#include "extractor/guidance/turn_lane_handler.hpp"
#include "extractor/guidance/turn_lane_matcher.hpp"
#include "util/simple_logger.hpp"
#include "util/typedefs.hpp"
@ -31,11 +31,12 @@ std::size_t getNumberOfTurns(const Intersection &intersection)
} // namespace
TurnLaneHandler::TurnLaneHandler(const util::NodeBasedDynamicGraph &node_based_graph,
const util::NameTable &turn_lane_strings,
const std::vector<std::uint32_t> &turn_lane_offsets,
const std::vector<TurnLaneType::Mask> &turn_lane_masks,
const std::vector<QueryNode> &node_info_list,
const TurnAnalysis &turn_analysis)
: node_based_graph(node_based_graph), turn_lane_strings(turn_lane_strings),
node_info_list(node_info_list), turn_analysis(turn_analysis)
: node_based_graph(node_based_graph), turn_lane_offsets(turn_lane_offsets),
turn_lane_masks(turn_lane_masks), node_info_list(node_info_list), turn_analysis(turn_analysis)
{
}
@ -43,7 +44,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
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_descriptions of a format that describes an intersection as:
----------
A -^
@ -53,49 +54,64 @@ TurnLaneHandler::TurnLaneHandler(const util::NodeBasedDynamicGraph &node_based_g
C -v
----------
with a string like |left|through;right|right| and performs an assignment onto the turns:
for example: (130, turn slight right), (180, ramp straight), (320, turn sharp left)
witch is the result of a string like looking |left|through;right|right| and performs an
assignment onto the turns.
For example: (130, turn slight right), (180, ramp straight), (320, turn sharp left).
*/
Intersection TurnLaneHandler::assignTurnLanes(const NodeID at,
const EdgeID via_edge,
Intersection intersection,
LaneDataIdMap &id_map) const
{
//if only a uturn exists, there is nothing we can do
if( intersection.size() == 1 )
return std::move(intersection);
const auto &data = node_based_graph.GetEdgeData(via_edge);
const auto turn_lane_string = data.lane_string_id != INVALID_LANE_STRINGID
? turn_lane_strings.GetNameForID(data.lane_string_id)
: "";
// Extract a lane description for the ID
const auto turn_lane_description =
data.lane_description_id != INVALID_LANE_DESCRIPTIONID
? TurnLaneDescription(
turn_lane_masks.begin() + turn_lane_offsets[data.lane_description_id],
turn_lane_masks.begin() + turn_lane_offsets[data.lane_description_id + 1])
: TurnLaneDescription();
BOOST_ASSERT( turn_lane_description.empty() || turn_lane_description.size() == (turn_lane_offsets[data.lane_description_id+1] - turn_lane_offsets[data.lane_description_id]));
// going straight, due to traffic signals, we can have uncompressed geometry
if (intersection.size() == 2 &&
((data.lane_string_id != INVALID_LANE_STRINGID &&
data.lane_string_id ==
node_based_graph.GetEdgeData(intersection[1].turn.eid).lane_string_id) ||
((data.lane_description_id != INVALID_LANE_DESCRIPTIONID &&
data.lane_description_id ==
node_based_graph.GetEdgeData(intersection[1].turn.eid).lane_description_id) ||
angularDeviation(intersection[1].turn.angle, STRAIGHT_ANGLE) < FUZZY_ANGLE_DIFFERENCE))
return std::move(intersection);
auto lane_data = laneDataFromString(turn_lane_string);
auto lane_data = laneDataFromDescription(turn_lane_description);
// if we see an invalid conversion, we stop immediately
if (!turn_lane_string.empty() && lane_data.empty())
if (!turn_lane_description.empty() && lane_data.empty())
return std::move(intersection);
// might be reasonable to handle multiple turns, if we know of a sequence of lanes
// e.g. one direction per lane, if three lanes and right, through, left available
if (!turn_lane_string.empty() && lane_data.size() == 1 && lane_data[0].tag == "none")
if (!turn_lane_description.empty() && lane_data.size() == 1 &&
lane_data[0].tag == TurnLaneType::none)
return std::move(intersection);
const std::size_t possible_entries = getNumberOfTurns(intersection);
// merge does not justify an instruction
const bool has_merge_lane =
(hasTag("merge_to_left", lane_data) || hasTag("merge_to_right", lane_data));
hasTag(TurnLaneType::merge_to_left | TurnLaneType::merge_to_right, lane_data);
// Dead end streets that don't have any left-tag. This can happen due to the fallbacks for
// broken data/barriers.
const bool has_non_usable_u_turn =
(intersection[0].entry_allowed && !hasTag("none", lane_data) &&
!hasTag("left", lane_data) && !hasTag("sharp_left", lane_data) &&
!hasTag("reverse", lane_data) && lane_data.size() + 1 == possible_entries);
const bool has_non_usable_u_turn = (intersection[0].entry_allowed &&
!hasTag(TurnLaneType::none | TurnLaneType::left |
TurnLaneType::sharp_left | TurnLaneType::uturn,
lane_data) &&
lane_data.size() + 1 == possible_entries);
if (has_merge_lane || has_non_usable_u_turn)
return std::move(intersection);
@ -103,19 +119,19 @@ Intersection TurnLaneHandler::assignTurnLanes(const NodeID at,
if (!lane_data.empty() && canMatchTrivially(intersection, lane_data) &&
lane_data.size() !=
static_cast<std::size_t>(
lane_data.back().tag != "reverse" && intersection[0].entry_allowed ? 1 : 0) +
lane_data.back().tag != TurnLaneType::uturn && intersection[0].entry_allowed ? 1
: 0) +
possible_entries &&
intersection[0].entry_allowed && !hasTag("none", lane_data))
lane_data.push_back({"reverse", lane_data.back().to, lane_data.back().to});
intersection[0].entry_allowed && !hasTag(TurnLaneType::none, lane_data))
lane_data.push_back({TurnLaneType::uturn, lane_data.back().to, lane_data.back().to});
bool is_simple = isSimpleIntersection(lane_data, intersection);
// simple intersections can be assigned directly
if (is_simple)
{
lane_data = handleNoneValueAtSimpleTurn(std::move(lane_data), intersection);
return simpleMatchTuplesToTurns(
std::move(intersection), lane_data, data.lane_string_id, id_map);
std::move(intersection), lane_data, data.lane_description_id, id_map);
}
// if the intersection is not simple but we have lane data, we check for intersections with
// middle islands. We have two cases. The first one is providing lane data on the current
@ -136,13 +152,13 @@ Intersection TurnLaneHandler::assignTurnLanes(const NodeID at,
{
lane_data = handleNoneValueAtSimpleTurn(std::move(lane_data), intersection);
return simpleMatchTuplesToTurns(
std::move(intersection), lane_data, data.lane_string_id, id_map);
std::move(intersection), lane_data, data.lane_description_id, id_map);
}
}
}
// The second part does not provide lane data on the current segment, but on the segment prior
// to the turn. We try to partition the data and only consider the second part.
else if (turn_lane_string.empty())
else if (turn_lane_description.empty())
{
// acquire the lane data of a previous segment and, if possible, use it for the current
// intersection.
@ -162,10 +178,11 @@ Intersection TurnLaneHandler::handleTurnAtPreviousIntersection(const NodeID at,
NodeID previous_node = SPECIAL_NODEID;
Intersection previous_intersection;
EdgeID previous_id = SPECIAL_EDGEID;
LaneDataVector lane_data;
// Get the previous lane string. We only accept strings that stem from a not-simple intersection
// and are not empty.
const auto previous_lane_string = [&]() -> std::string {
const auto previous_lane_description = [&]() -> TurnLaneDescription {
if (!findPreviousIntersection(at,
via_edge,
intersection,
@ -174,32 +191,38 @@ Intersection TurnLaneHandler::handleTurnAtPreviousIntersection(const NodeID at,
previous_node,
previous_id,
previous_intersection))
return "";
return {};
BOOST_ASSERT(previous_id != SPECIAL_EDGEID);
const auto &previous_data = node_based_graph.GetEdgeData(previous_id);
auto previous_string = previous_data.lane_string_id != INVALID_LANE_STRINGID
? turn_lane_strings.GetNameForID(previous_data.lane_string_id)
: "";
if (previous_string.empty())
return "";
const auto &previous_edge_data = node_based_graph.GetEdgeData(previous_id);
// TODO access correct data
const auto previous_description =
previous_edge_data.lane_description_id != INVALID_LANE_DESCRIPTIONID
? TurnLaneDescription(
turn_lane_masks.begin() +
turn_lane_offsets[previous_edge_data.lane_description_id],
turn_lane_masks.begin() +
turn_lane_offsets[previous_edge_data.lane_description_id + 1])
: TurnLaneDescription();
if (previous_description.empty())
return previous_description;
previous_intersection = turn_analysis.assignTurnTypes(
previous_node, previous_id, std::move(previous_intersection));
auto previous_lane_data = laneDataFromString(previous_string);
lane_data = laneDataFromDescription(previous_description);
if (isSimpleIntersection(previous_lane_data, previous_intersection))
return "";
return previous_string;
if (isSimpleIntersection(lane_data, previous_intersection))
return {};
else
return previous_description;
}();
// no lane string, no problems
if (previous_lane_string.empty())
if (previous_lane_description.empty())
return std::move(intersection);
auto lane_data = laneDataFromString(previous_lane_string);
// stop on invalid lane data conversion
if (lane_data.empty())
return std::move(intersection);
@ -210,7 +233,7 @@ Intersection TurnLaneHandler::handleTurnAtPreviousIntersection(const NodeID at,
{
lane_data = handleNoneValueAtSimpleTurn(std::move(lane_data), intersection);
return simpleMatchTuplesToTurns(
std::move(intersection), lane_data, previous_data.lane_string_id, id_map);
std::move(intersection), lane_data, previous_data.lane_description_id, id_map);
}
else
{
@ -230,7 +253,7 @@ Intersection TurnLaneHandler::handleTurnAtPreviousIntersection(const NodeID at,
{
lane_data = handleNoneValueAtSimpleTurn(std::move(lane_data), intersection);
return simpleMatchTuplesToTurns(
std::move(intersection), lane_data, previous_data.lane_string_id, id_map);
std::move(intersection), lane_data, previous_data.lane_description_id, id_map);
}
}
}
@ -257,7 +280,10 @@ bool TurnLaneHandler::isSimpleIntersection(const LaneDataVector &lane_data,
return std::count_if(
lane_data.begin(),
lane_data.end(),
[](const TurnLaneData &data) { return boost::starts_with(data.tag, "merge"); }) +
[](const TurnLaneData &data) {
return ((data.tag & TurnLaneType::merge_to_left) != TurnLaneType::empty) ||
((data.tag & TurnLaneType::merge_to_right) != TurnLaneType::empty);
}) +
std::size_t{1} >=
lane_data.size();
}
@ -268,7 +294,7 @@ bool TurnLaneHandler::isSimpleIntersection(const LaneDataVector &lane_data,
const auto num_turns = [&]() {
auto count = getNumberOfTurns(intersection);
if (count < lane_data.size() && !intersection[0].entry_allowed &&
lane_data.back().tag == "reverse")
lane_data.back().tag == TurnLaneType::uturn)
return count + 1;
return count;
}();
@ -281,8 +307,8 @@ bool TurnLaneHandler::isSimpleIntersection(const LaneDataVector &lane_data,
// single additional lane data entry is alright, if it is none at the side. This usually
// refers to a bus-lane
if (num_turns + std::size_t{1} == lane_data.size() && lane_data.front().tag != "none" &&
lane_data.back().tag != "none")
if (num_turns + std::size_t{1} == lane_data.size() &&
lane_data.front().tag != TurnLaneType::none && lane_data.back().tag != TurnLaneType::none)
{
return false;
}
@ -291,15 +317,16 @@ bool TurnLaneHandler::isSimpleIntersection(const LaneDataVector &lane_data,
if (num_turns > lane_data.size() &&
lane_data.end() ==
std::find_if(lane_data.begin(), lane_data.end(), [](const TurnLaneData &data) {
return data.tag == "none";
return data.tag == TurnLaneType::none;
}))
{
return false;
}
if (num_turns > lane_data.size() && intersection[0].entry_allowed &&
!(hasTag("reverse", lane_data) ||
(lane_data.back().tag != "left" && lane_data.back().tag != "sharp_left")))
!(hasTag(TurnLaneType::uturn, lane_data) ||
(lane_data.back().tag != TurnLaneType::left &&
lane_data.back().tag != TurnLaneType::sharp_left)))
{
return false;
}
@ -310,21 +337,21 @@ bool TurnLaneHandler::isSimpleIntersection(const LaneDataVector &lane_data,
std::unordered_set<std::size_t> matched_indices;
for (const auto &data : lane_data)
{
if (data.tag == "none")
if (data.tag == TurnLaneType::none)
{
has_none = true;
continue;
}
const auto best_match = [&]() {
if (data.tag != "reverse" || lane_data.size() == 1)
if (data.tag != TurnLaneType::uturn || lane_data.size() == 1)
return findBestMatch(data.tag, intersection);
// lane_data.size() > 1
if (lane_data.back().tag == "reverse")
if (lane_data.back().tag == TurnLaneType::uturn)
return findBestMatchForReverse(lane_data[lane_data.size() - 2].tag, intersection);
BOOST_ASSERT(lane_data.front().tag == "reverse");
BOOST_ASSERT(lane_data.front().tag == TurnLaneType::uturn);
return findBestMatchForReverse(lane_data[1].tag, intersection);
}();
std::size_t match_index = std::distance(intersection.begin(), best_match);
@ -396,7 +423,8 @@ std::pair<LaneDataVector, LaneDataVector> TurnLaneHandler::partitionLaneData(
std::size_t straightmost_tag_index = turn_lane_data.size();
for (std::size_t lane = 0; lane < turn_lane_data.size(); ++lane)
{
if (turn_lane_data[lane].tag == "none" || turn_lane_data[lane].tag == "reverse")
if ((turn_lane_data[lane].tag & (TurnLaneType::none | TurnLaneType::uturn)) !=
TurnLaneType::empty)
continue;
const auto best_match = findBestMatch(turn_lane_data[lane].tag, intersection);
@ -419,7 +447,8 @@ std::pair<LaneDataVector, LaneDataVector> TurnLaneHandler::partitionLaneData(
return {turn_lane_data, {}};
}
std::size_t none_index = std::distance(turn_lane_data.begin(), findTag("none", turn_lane_data));
std::size_t none_index =
std::distance(turn_lane_data.begin(), findTag(TurnLaneType::none, turn_lane_data));
// if the turn lanes are pull forward, we might have to add an additional straight tag
// did we find something that matches against the straightmost road?
@ -477,7 +506,7 @@ std::pair<LaneDataVector, LaneDataVector> TurnLaneHandler::partitionLaneData(
std::count(matched_at_second.begin(), matched_at_second.end(), true)) ==
getNumberOfTurns(next_intersection))
{
TurnLaneData data = {"through", 255, 0};
TurnLaneData data = {TurnLaneType::straight, 255, 0};
augmentEntry(data);
first.push_back(data);
std::sort(first.begin(), first.end());
@ -489,19 +518,18 @@ std::pair<LaneDataVector, LaneDataVector> TurnLaneHandler::partitionLaneData(
Intersection TurnLaneHandler::simpleMatchTuplesToTurns(Intersection intersection,
const LaneDataVector &lane_data,
const LaneStringID lane_string_id,
const LaneDescriptionID lane_description_id,
LaneDataIdMap &id_map) const
{
if (lane_data.empty() || !canMatchTrivially(intersection, lane_data))
return std::move(intersection);
BOOST_ASSERT(!hasTag("none", lane_data));
BOOST_ASSERT(std::count_if(lane_data.begin(), lane_data.end(), [](const TurnLaneData &data) {
return boost::starts_with(data.tag, "merge");
}) == 0);
BOOST_ASSERT(
!hasTag(TurnLaneType::none | TurnLaneType::merge_to_left | TurnLaneType::merge_to_right,
lane_data));
return triviallyMatchLanesToTurns(
std::move(intersection), lane_data, node_based_graph, lane_string_id, id_map);
std::move(intersection), lane_data, node_based_graph, lane_description_id, id_map);
}
} // namespace lanes

View File

@ -1,5 +1,5 @@
#include "extractor/guidance/turn_lane_matcher.hpp"
#include "extractor/guidance/toolkit.hpp"
#include "extractor/guidance/turn_lane_matcher.hpp"
#include "util/guidance/toolkit.hpp"
#include <boost/assert.hpp>
@ -17,18 +17,18 @@ namespace lanes
{
// Translate Turn Tags into a Matching Direction Modifier
DirectionModifier::Enum getMatchingModifier(const std::string &tag)
DirectionModifier::Enum getMatchingModifier(const TurnLaneType::Mask &tag)
{
const constexpr char *tag_by_modifier[] = {"reverse",
"sharp_right",
"right",
"slight_right",
"through",
"slight_left",
"left",
"sharp_left",
"merge_to_left",
"merge_to_right"};
const constexpr TurnLaneType::Mask tag_by_modifier[] = {TurnLaneType::uturn,
TurnLaneType::sharp_right,
TurnLaneType::right,
TurnLaneType::slight_right,
TurnLaneType::straight,
TurnLaneType::slight_left,
TurnLaneType::left,
TurnLaneType::sharp_left,
TurnLaneType::merge_to_left,
TurnLaneType::merge_to_right};
const auto index =
std::distance(tag_by_modifier, std::find(tag_by_modifier, tag_by_modifier + 10, tag));
@ -51,7 +51,7 @@ DirectionModifier::Enum getMatchingModifier(const std::string &tag)
}
// check whether a match of a given tag and a turn instruction can be seen as valid
bool isValidMatch(const std::string &tag, const TurnInstruction instruction)
bool isValidMatch(const TurnLaneType::Mask &tag, const TurnInstruction instruction)
{
using util::guidance::hasLeftModifier;
using util::guidance::hasRightModifier;
@ -59,12 +59,13 @@ bool isValidMatch(const std::string &tag, const TurnInstruction instruction)
return instruction.type == TurnType::Merge;
};
if (tag == "reverse")
if (tag == TurnLaneType::uturn)
{
return hasLeftModifier(instruction) ||
instruction.direction_modifier == DirectionModifier::UTurn;
}
else if (tag == "sharp_right" || tag == "right" || tag == "slight_right")
else if (tag == TurnLaneType::sharp_right || tag == TurnLaneType::right ||
tag == TurnLaneType::slight_right)
{
if (isMirroredModifier(instruction))
return hasLeftModifier(instruction);
@ -72,7 +73,7 @@ bool isValidMatch(const std::string &tag, const TurnInstruction instruction)
// needs to be adjusted for left side driving
return leavesRoundabout(instruction) || hasRightModifier(instruction);
}
else if (tag == "through")
else if (tag == TurnLaneType::straight)
{
return instruction.direction_modifier == DirectionModifier::Straight ||
instruction.type == TurnType::Suppressed || instruction.type == TurnType::NewName ||
@ -87,7 +88,8 @@ bool isValidMatch(const std::string &tag, const TurnInstruction instruction)
instruction.direction_modifier == DirectionModifier::SlightRight)) ||
instruction.type == TurnType::UseLane;
}
else if (tag == "slight_left" || tag == "left" || tag == "sharp_left")
else if (tag == TurnLaneType::slight_left || tag == TurnLaneType::left ||
tag == TurnLaneType::sharp_left)
{
if (isMirroredModifier(instruction))
return hasRightModifier(instruction);
@ -100,7 +102,11 @@ bool isValidMatch(const std::string &tag, const TurnInstruction instruction)
return false;
}
typename Intersection::const_iterator findBestMatch(const std::string &tag,
// Every tag is somewhat idealized in form of the expected angle. A through lane should go straight
// (or follow a 180 degree turn angle between in/out segments.) The following function tries to find
// the best possible match for every tag in a given intersection, considering a few corner cases
// introduced to OSRM handling u-turns
typename Intersection::const_iterator findBestMatch(const TurnLaneType::Mask &tag,
const Intersection &intersection)
{
const constexpr double idealized_turn_angles[] = {0, 35, 90, 135, 180, 225, 270, 315};
@ -122,15 +128,20 @@ typename Intersection::const_iterator findBestMatch(const std::string &tag,
});
}
typename Intersection::const_iterator findBestMatchForReverse(const std::string &leftmost_tag,
const Intersection &intersection)
// Reverse is a special case, because it requires access to the leftmost tag. It has its own
// matching function as a result of that. The leftmost tag is required, since u-turns are disabled
// by default in OSRM. Therefor we cannot check whether a turn is allowed, since it could be
// possible that it is forbidden. In addition, the best u-turn angle does not necessarily represent
// the u-turn, since it could be a sharp-left turn instead on a road with a middle island.
typename Intersection::const_iterator
findBestMatchForReverse(const TurnLaneType::Mask &leftmost_tag, const Intersection &intersection)
{
const auto leftmost_itr = findBestMatch(leftmost_tag, intersection);
if (leftmost_itr + 1 == intersection.cend())
return intersection.begin();
const constexpr double idealized_turn_angles[] = {0, 35, 90, 135, 180, 225, 270, 315};
const std::string tag = "reverse";
const TurnLaneType::Mask tag = TurnLaneType::uturn;
const auto idealized_angle = idealized_turn_angles[getMatchingModifier(tag)];
return std::min_element(
intersection.begin() + std::distance(intersection.begin(), leftmost_itr),
@ -149,6 +160,8 @@ typename Intersection::const_iterator findBestMatchForReverse(const std::string
});
}
// a match is trivial if all turns can be associated with their best match in a valid way and the
// matches occur in order
bool canMatchTrivially(const Intersection &intersection, const LaneDataVector &lane_data)
{
std::size_t road_index = 1, lane = 0;
@ -163,17 +176,18 @@ bool canMatchTrivially(const Intersection &intersection, const LaneDataVector &l
if (findBestMatch(lane_data[lane].tag, intersection) !=
intersection.begin() + road_index)
return false;
++lane;
}
}
return lane == lane_data.size() ||
(lane + 1 == lane_data.size() && lane_data.back().tag == "reverse");
(lane + 1 == lane_data.size() && lane_data.back().tag == TurnLaneType::uturn);
}
Intersection triviallyMatchLanesToTurns(Intersection intersection,
const LaneDataVector &lane_data,
const util::NodeBasedDynamicGraph &node_based_graph,
const LaneStringID lane_string_id,
const LaneDescriptionID lane_string_id,
LaneDataIdMap &lane_data_to_id)
{
std::size_t road_index = 1, lane = 0;
@ -212,7 +226,7 @@ Intersection triviallyMatchLanesToTurns(Intersection intersection,
}
// handle reverse tag, if present
if (lane + 1 == lane_data.size() && lane_data.back().tag == "reverse")
if (lane + 1 == lane_data.size() && lane_data.back().tag == TurnLaneType::uturn)
{
std::size_t u_turn = 0;
if (node_based_graph.GetEdgeData(intersection[0].turn.eid).reversed)

View File

@ -1,4 +1,3 @@
#include "storage/storage.hpp"
#include "contractor/query_edge.hpp"
#include "extractor/compressed_edge_container.hpp"
#include "extractor/guidance/turn_instruction.hpp"
@ -9,6 +8,7 @@
#include "storage/shared_barriers.hpp"
#include "storage/shared_datatype.hpp"
#include "storage/shared_memory.hpp"
#include "storage/storage.hpp"
#include "engine/datafacade/datafacade_base.hpp"
#include "util/coordinate.hpp"
#include "util/exception.hpp"
@ -147,25 +147,17 @@ int Storage::Run()
name_stream.read((char *)&number_of_chars, sizeof(unsigned));
shared_layout_ptr->SetBlockSize<char>(SharedDataLayout::NAME_CHAR_LIST, number_of_chars);
boost::filesystem::ifstream turn_string_stream(config.turn_lane_string_path, std::ios::binary);
if (!turn_string_stream)
{
throw util::exception("Could not open " + config.turn_lane_string_path.string() +
" for reading.");
}
unsigned turn_string_blocks = 0;
turn_string_stream.read((char *)&turn_string_blocks, sizeof(unsigned));
shared_layout_ptr->SetBlockSize<unsigned>(SharedDataLayout::TURN_STRING_OFFSETS,
turn_string_blocks);
shared_layout_ptr->SetBlockSize<typename util::RangeTable<16, true>::BlockT>(
SharedDataLayout::TURN_STRING_BLOCKS, turn_string_blocks);
BOOST_ASSERT_MSG(0 != turn_string_blocks, "turn string file broken");
unsigned number_of_turn_string_chars = 0;
turn_string_stream.read((char *)&number_of_turn_string_chars, sizeof(unsigned));
shared_layout_ptr->SetBlockSize<char>(SharedDataLayout::TURN_STRING_CHAR_LIST,
number_of_turn_string_chars);
std::vector<std::uint32_t> lane_description_offsets;
std::vector<extractor::guidance::TurnLaneType::Mask> lane_description_masks;
if (!util::deserializeAdjacencyArray(config.turn_lane_description_path.string(),
lane_description_offsets,
lane_description_masks))
throw util::exception("Could not open read lane descriptions from: " +
config.turn_lane_description_path.string());
shared_layout_ptr->SetBlockSize<std::uint32_t>(SharedDataLayout::LANE_DESCRIPTION_OFFSETS,
lane_description_offsets.size());
shared_layout_ptr->SetBlockSize<extractor::guidance::TurnLaneType::Mask>(
SharedDataLayout::LANE_DESCRIPTION_MASKS, lane_description_masks.size());
// Loading information for original edges
boost::filesystem::ifstream edges_input_stream(config.edges_data_path, std::ios::binary);
@ -454,7 +446,7 @@ int Storage::Run()
char *name_char_ptr = shared_layout_ptr->GetBlockPtr<char, true>(
shared_memory_ptr, SharedDataLayout::NAME_CHAR_LIST);
unsigned temp_length;
unsigned temp_length = 0;
name_stream.read((char *)&temp_length, sizeof(unsigned));
BOOST_ASSERT_MSG(shared_layout_ptr->AlignBlockSize(temp_length) ==
@ -468,16 +460,6 @@ int Storage::Run()
}
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>(
@ -489,30 +471,29 @@ int Storage::Run()
}
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)
auto *turn_lane_offset_ptr = shared_layout_ptr->GetBlockPtr<std::uint32_t, true>(
shared_memory_ptr, SharedDataLayout::LANE_DESCRIPTION_OFFSETS);
if (!lane_description_offsets.empty())
{
turn_string_stream.read(
(char *)turn_string_blocks_ptr,
shared_layout_ptr->GetBlockSize(SharedDataLayout::TURN_STRING_BLOCKS));
BOOST_ASSERT(shared_layout_ptr->GetBlockSize(SharedDataLayout::LANE_DESCRIPTION_OFFSETS) >=
sizeof(lane_description_offsets[0]) * lane_description_offsets.size());
std::copy(
lane_description_offsets.begin(), lane_description_offsets.end(), turn_lane_offset_ptr);
std::vector<std::uint32_t> tmp;
lane_description_offsets.swap(tmp);
}
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)
auto *turn_lane_mask_ptr =
shared_layout_ptr->GetBlockPtr<extractor::guidance::TurnLaneType::Mask, true>(
shared_memory_ptr, SharedDataLayout::LANE_DESCRIPTION_MASKS);
if (!lane_description_masks.empty())
{
turn_string_stream.read(
turn_string_char_ptr,
shared_layout_ptr->GetBlockSize(SharedDataLayout::TURN_STRING_CHAR_LIST));
BOOST_ASSERT(shared_layout_ptr->GetBlockSize(SharedDataLayout::LANE_DESCRIPTION_MASKS) >=
sizeof(lane_description_masks[0]) * lane_description_masks.size());
std::copy(lane_description_masks.begin(), lane_description_masks.end(), turn_lane_mask_ptr);
std::vector<extractor::guidance::TurnLaneType::Mask> tmp;
lane_description_masks.swap(tmp);
}
turn_string_stream.close();
// load original edge information
NodeID *via_node_ptr = shared_layout_ptr->GetBlockPtr<NodeID, true>(
@ -595,7 +576,7 @@ int Storage::Run()
{
util::SimpleLogger().Write()
<< "Copying " << (m_datasource_name_data.end() - m_datasource_name_data.begin())
<< " chars into name data ptr\n";
<< " chars into name data ptr";
std::copy(
m_datasource_name_data.begin(), m_datasource_name_data.end(), datasource_name_data_ptr);
}

View File

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

View File

@ -40,7 +40,7 @@ BOOST_AUTO_TEST_CASE(long_road_test)
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
INVALID_LANE_DESCRIPTIONID},
{1,
0,
1,
@ -51,7 +51,7 @@ BOOST_AUTO_TEST_CASE(long_road_test)
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
INVALID_LANE_DESCRIPTIONID},
{1,
2,
1,
@ -62,7 +62,7 @@ BOOST_AUTO_TEST_CASE(long_road_test)
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
INVALID_LANE_DESCRIPTIONID},
{2,
1,
1,
@ -73,7 +73,7 @@ BOOST_AUTO_TEST_CASE(long_road_test)
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
INVALID_LANE_DESCRIPTIONID},
{2,
3,
1,
@ -84,7 +84,7 @@ BOOST_AUTO_TEST_CASE(long_road_test)
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
INVALID_LANE_DESCRIPTIONID},
{3,
2,
1,
@ -95,7 +95,7 @@ BOOST_AUTO_TEST_CASE(long_road_test)
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
INVALID_LANE_DESCRIPTIONID},
{3,
4,
1,
@ -106,7 +106,7 @@ BOOST_AUTO_TEST_CASE(long_road_test)
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
INVALID_LANE_DESCRIPTIONID},
{4,
3,
1,
@ -117,7 +117,7 @@ BOOST_AUTO_TEST_CASE(long_road_test)
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID}};
INVALID_LANE_DESCRIPTIONID}};
BOOST_ASSERT(edges[0].data.IsCompatibleTo(edges[2].data));
BOOST_ASSERT(edges[2].data.IsCompatibleTo(edges[4].data));
@ -159,7 +159,7 @@ BOOST_AUTO_TEST_CASE(loop_test)
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
INVALID_LANE_DESCRIPTIONID},
{0,
5,
1,
@ -170,7 +170,7 @@ BOOST_AUTO_TEST_CASE(loop_test)
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
INVALID_LANE_DESCRIPTIONID},
{1,
0,
1,
@ -181,7 +181,7 @@ BOOST_AUTO_TEST_CASE(loop_test)
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
INVALID_LANE_DESCRIPTIONID},
{1,
2,
1,
@ -192,7 +192,7 @@ BOOST_AUTO_TEST_CASE(loop_test)
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
INVALID_LANE_DESCRIPTIONID},
{2,
1,
1,
@ -203,7 +203,7 @@ BOOST_AUTO_TEST_CASE(loop_test)
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
INVALID_LANE_DESCRIPTIONID},
{2,
3,
1,
@ -214,7 +214,7 @@ BOOST_AUTO_TEST_CASE(loop_test)
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
INVALID_LANE_DESCRIPTIONID},
{3,
2,
1,
@ -225,7 +225,7 @@ BOOST_AUTO_TEST_CASE(loop_test)
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
INVALID_LANE_DESCRIPTIONID},
{3,
4,
1,
@ -236,7 +236,7 @@ BOOST_AUTO_TEST_CASE(loop_test)
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
INVALID_LANE_DESCRIPTIONID},
{4,
3,
1,
@ -247,7 +247,7 @@ BOOST_AUTO_TEST_CASE(loop_test)
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
INVALID_LANE_DESCRIPTIONID},
{4,
5,
1,
@ -258,7 +258,7 @@ BOOST_AUTO_TEST_CASE(loop_test)
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
INVALID_LANE_DESCRIPTIONID},
{5,
0,
1,
@ -269,7 +269,7 @@ BOOST_AUTO_TEST_CASE(loop_test)
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
INVALID_LANE_DESCRIPTIONID},
{5,
4,
1,
@ -280,7 +280,7 @@ BOOST_AUTO_TEST_CASE(loop_test)
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
INVALID_LANE_DESCRIPTIONID},
};
BOOST_ASSERT(edges.size() == 12);
@ -334,7 +334,7 @@ BOOST_AUTO_TEST_CASE(t_intersection)
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
INVALID_LANE_DESCRIPTIONID},
{1,
0,
1,
@ -345,7 +345,7 @@ BOOST_AUTO_TEST_CASE(t_intersection)
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
INVALID_LANE_DESCRIPTIONID},
{1,
2,
1,
@ -356,7 +356,7 @@ BOOST_AUTO_TEST_CASE(t_intersection)
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
INVALID_LANE_DESCRIPTIONID},
{1,
3,
1,
@ -367,7 +367,7 @@ BOOST_AUTO_TEST_CASE(t_intersection)
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
INVALID_LANE_DESCRIPTIONID},
{2,
1,
1,
@ -378,7 +378,7 @@ BOOST_AUTO_TEST_CASE(t_intersection)
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
INVALID_LANE_DESCRIPTIONID},
{3,
1,
1,
@ -389,7 +389,7 @@ BOOST_AUTO_TEST_CASE(t_intersection)
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
INVALID_LANE_DESCRIPTIONID},
};
BOOST_ASSERT(edges[0].data.IsCompatibleTo(edges[1].data));
@ -430,7 +430,7 @@ BOOST_AUTO_TEST_CASE(street_name_changes)
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
INVALID_LANE_DESCRIPTIONID},
{1,
0,
1,
@ -441,7 +441,7 @@ BOOST_AUTO_TEST_CASE(street_name_changes)
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
INVALID_LANE_DESCRIPTIONID},
{1,
2,
1,
@ -452,7 +452,7 @@ BOOST_AUTO_TEST_CASE(street_name_changes)
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
INVALID_LANE_DESCRIPTIONID},
{2,
1,
1,
@ -463,7 +463,7 @@ BOOST_AUTO_TEST_CASE(street_name_changes)
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
INVALID_LANE_DESCRIPTIONID},
};
BOOST_ASSERT(edges[0].data.IsCompatibleTo(edges[1].data));
@ -500,7 +500,7 @@ BOOST_AUTO_TEST_CASE(direction_changes)
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
INVALID_LANE_DESCRIPTIONID},
{1,
0,
1,
@ -511,7 +511,7 @@ BOOST_AUTO_TEST_CASE(direction_changes)
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
INVALID_LANE_DESCRIPTIONID},
{1,
2,
1,
@ -522,7 +522,7 @@ BOOST_AUTO_TEST_CASE(direction_changes)
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
INVALID_LANE_DESCRIPTIONID},
{2,
1,
1,
@ -533,7 +533,7 @@ BOOST_AUTO_TEST_CASE(direction_changes)
false,
true,
TRAVEL_MODE_INACCESSIBLE,
INVALID_LANE_STRINGID},
INVALID_LANE_DESCRIPTIONID},
};
Graph graph(5, edges);

View File

@ -5,6 +5,7 @@
#include "contractor/query_edge.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include "extractor/guidance/turn_lane_types.hpp"
#include "engine/datafacade/datafacade_base.hpp"
#include "util/guidance/bearing_class.hpp"
#include "util/guidance/entry_class.hpp"
@ -180,9 +181,16 @@ class MockDataFacade final : public engine::datafacade::BaseDataFacade
BearingClassID GetBearingClassID(const NodeID /*id*/) const override { return 0; };
EntryClassID GetEntryClassID(const EdgeID /*id*/) const override { return 0; }
bool hasLaneData(const EdgeID /*id*/) const { return true; };
util::guidance::LaneTupelIdPair GetLaneData(const EdgeID /*id*/) const { return {{0, 0}, 0}; }
std::string GetTurnStringForID(const LaneStringID /*lane_string_id*/) const { return ""; };
bool hasLaneData(const EdgeID /*id*/) const override final { return true; };
util::guidance::LaneTupelIdPair GetLaneData(const EdgeID /*id*/) const override final
{
return {{0, 0}, 0};
}
extractor::guidance::TurnLaneDescription
GetTurnDescription(const LaneDescriptionID /*lane_description_id*/) const override final
{
return {};
}
util::guidance::BearingClass
GetBearingClass(const BearingClassID /*bearing_class_id*/) const override