From 59057081112ca5c39b5b581b11e730717a83feb5 Mon Sep 17 00:00:00 2001 From: Moritz Kobitzsch Date: Tue, 21 Jun 2016 10:41:08 +0200 Subject: [PATCH] expose lanes as enums, adjusted for comments --- .clang-format | 2 +- docs/http.md | 70 +++++--- features/guidance/anticipate-lanes.feature | 50 +++--- features/guidance/turn-lanes.feature | 170 +++++++++--------- features/support/route.js | 2 +- include/engine/datafacade/datafacade_base.hpp | 4 +- .../engine/datafacade/internal_datafacade.hpp | 49 ++--- .../engine/datafacade/shared_datafacade.hpp | 66 +++---- include/engine/guidance/assemble_steps.hpp | 13 +- include/engine/guidance/debug.hpp | 52 ------ include/engine/guidance/step_maneuver.hpp | 5 +- .../routing_algorithms/routing_base.hpp | 4 +- .../extractor/edge_based_graph_factory.hpp | 24 +-- include/extractor/extraction_containers.hpp | 10 +- include/extractor/extractor_callbacks.hpp | 4 +- include/extractor/extractor_config.hpp | 4 +- include/extractor/guidance/debug.hpp | 46 ----- include/extractor/guidance/turn_lane_data.hpp | 14 +- .../extractor/guidance/turn_lane_handler.hpp | 10 +- .../extractor/guidance/turn_lane_matcher.hpp | 22 +-- .../extractor/guidance/turn_lane_types.hpp | 102 +++++++++++ include/extractor/internal_extractor_edge.hpp | 10 +- include/extractor/node_based_edge.hpp | 16 +- include/storage/shared_datatype.hpp | 13 +- include/storage/storage_config.hpp | 2 +- include/util/debug.hpp | 88 +++++++++ include/util/guidance/turn_lanes.hpp | 2 +- include/util/io.hpp | 80 +++++++++ include/util/node_based_graph.hpp | 10 +- include/util/typedefs.hpp | 6 +- src/engine/api/json_factory.cpp | 16 +- src/engine/guidance/post_processing.cpp | 13 +- src/extractor/edge_based_graph_factory.cpp | 9 +- src/extractor/extraction_containers.cpp | 35 +++- src/extractor/extractor.cpp | 14 +- src/extractor/extractor_callbacks.cpp | 128 +++++++++---- src/extractor/graph_compressor.cpp | 12 +- .../guidance/turn_lane_augmentation.cpp | 64 +++---- src/extractor/guidance/turn_lane_data.cpp | 114 ++++++------ src/extractor/guidance/turn_lane_handler.cpp | 158 +++++++++------- src/extractor/guidance/turn_lane_matcher.cpp | 62 ++++--- src/storage/storage.cpp | 83 ++++----- src/storage/storage_config.cpp | 2 +- unit_tests/extractor/graph_compressor.cpp | 68 +++---- unit_tests/mocks/mock_datafacade.hpp | 14 +- 45 files changed, 1020 insertions(+), 722 deletions(-) delete mode 100644 include/engine/guidance/debug.hpp delete mode 100644 include/extractor/guidance/debug.hpp create mode 100644 include/extractor/guidance/turn_lane_types.hpp create mode 100644 include/util/debug.hpp diff --git a/.clang-format b/.clang-format index 009977c96..8f7cd4f10 100644 --- a/.clang-format +++ b/.clang-format @@ -2,7 +2,7 @@ Language: Cpp # BasedOnStyle: LLVM AccessModifierOffset: -2 -AlignAfterOpenBracket: true +AlignAfterOpenBracket: Align AlignConsecutiveAssignments: false AlignConsecutiveDeclarations: false AlignEscapedNewlinesLeft: false diff --git a/docs/http.md b/docs/http.md index 0654874b6..f8b576c35 100644 --- a/docs/http.md +++ b/docs/http.md @@ -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,9 +507,8 @@ 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 | |-------------------|-------------------------------------------| | uturn | indicates reversal of direction | @@ -528,17 +519,16 @@ Currently, the supported lane tags are: `sharp_left, left, slight_left, sharp_ri | slight left | a slight turn to the left | | 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. - + | `type` | Description | |------------------------|---------------------------------------------------------------------------------------------------------------------------| | `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. diff --git a/features/guidance/anticipate-lanes.feature b/features/guidance/anticipate-lanes.feature index 713be5679..3d7a9eb7a 100644 --- a/features/guidance/anticipate-lanes.feature +++ b/features/guidance/anticipate-lanes.feature @@ -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 diff --git a/features/guidance/turn-lanes.feature b/features/guidance/turn-lanes.feature index 4d244c839..91450edd2 100644 --- a/features/guidance/turn-lanes.feature +++ b/features/guidance/turn-lanes.feature @@ -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, | diff --git a/features/support/route.js b/features/support/route.js index ea0482627..a08dc9329 100644 --- a/features/support/route.js +++ b/features/support/route.js @@ -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 ''; diff --git a/include/engine/datafacade/datafacade_base.hpp b/include/engine/datafacade/datafacade_base.hpp index 8f2558fce..81cdde129 100644 --- a/include/engine/datafacade/datafacade_base.hpp +++ b/include/engine/datafacade/datafacade_base.hpp @@ -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; diff --git a/include/engine/datafacade/internal_datafacade.hpp b/include/engine/datafacade/internal_datafacade.hpp index 25a4a19db..7123f9c63 100644 --- a/include/engine/datafacade/internal_datafacade.hpp +++ b/include/engine/datafacade/internal_datafacade.hpp @@ -83,13 +83,14 @@ class InternalDataFacade final : public BaseDataFacade util::ShM::vector m_lane_tupel_id_pairs; util::ShM::vector m_travel_mode_list; util::ShM::vector m_names_char_list; - util::ShM::vector m_lanes_char_list; util::ShM::vector m_geometry_indices; util::ShM::vector m_geometry_list; util::ShM::vector m_is_core_node; util::ShM::vector m_segment_weights; util::ShM::vector m_datasource_list; util::ShM::vector m_datasource_names; + util::ShM::vector m_lane_description_offsets; + util::ShM::vector m_lane_description_masks; extractor::ProfileProperties m_profile_properties; std::unique_ptr 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::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]); } }; } diff --git a/include/engine/datafacade/shared_datafacade.hpp b/include/engine/datafacade/shared_datafacade.hpp index 2ceeb9994..91e2a0286 100644 --- a/include/engine/datafacade/shared_datafacade.hpp +++ b/include/engine/datafacade/shared_datafacade.hpp @@ -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::vector m_turn_instruction_list; util::ShM::vector m_travel_mode_list; util::ShM::vector m_names_char_list; - util::ShM::vector m_turn_string_char_list; util::ShM::vector m_name_begin_indices; - util::ShM::vector m_lane_string_char_list; - util::ShM::vector m_lane_string_begin_indices; util::ShM::vector m_geometry_indices; util::ShM::vector m_geometry_list; util::ShM::vector m_is_core_node; util::ShM::vector m_datasource_list; + util::ShM::vector m_lane_description_offsets; + util::ShM::vector m_lane_description_masks; util::ShM::vector m_datasource_name_data; util::ShM::vector m_datasource_name_offsets; @@ -103,7 +103,6 @@ class SharedDataFacade final : public BaseDataFacade boost::filesystem::path file_index_path; std::shared_ptr> m_name_table; - std::shared_ptr> m_turn_string_table; // bearing classes by node based node util::ShM::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( - shared_memory, storage::SharedDataLayout::TURN_STRING_OFFSETS); - auto blocks_ptr = data_layout->GetBlockPtr( - shared_memory, storage::SharedDataLayout::TURN_STRING_BLOCKS); - util::ShM::vector turn_string_offsets( - offsets_ptr, data_layout->num_entries[storage::SharedDataLayout::TURN_STRING_OFFSETS]); - util::ShM::vector turn_string_blocks( - blocks_ptr, data_layout->num_entries[storage::SharedDataLayout::TURN_STRING_BLOCKS]); + auto offsets_ptr = data_layout->GetBlockPtr( + shared_memory, storage::SharedDataLayout::LANE_DESCRIPTION_OFFSETS); + util::ShM::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( - shared_memory, storage::SharedDataLayout::TURN_STRING_CHAR_LIST); - util::ShM::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>( - turn_string_offsets, - turn_string_blocks, - static_cast(turn_strings_char_list.size())); + auto masks_ptr = data_layout->GetBlockPtr( + shared_memory, storage::SharedDataLayout::LANE_DESCRIPTION_MASKS); - m_turn_string_char_list = std::move(turn_strings_char_list); + util::ShM::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]); } }; } diff --git a/include/engine/guidance/assemble_steps.hpp b/include/engine/guidance/assemble_steps.hpp index 39526d1e5..943c1b9d8 100644 --- a/include/engine/guidance/assemble_steps.hpp +++ b/include/engine/guidance/assemble_steps.hpp @@ -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 assembleSteps(const datafacade::BaseDataFacade &fa WaypointType::Depart, 0, util::guidance::LaneTupel(), - ""}; + {}}; Intersection intersection{source_node.location, std::vector({bearings.second}), std::vector({true}), @@ -152,9 +153,9 @@ inline std::vector 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 assembleSteps(const datafacade::BaseDataFacade &fa WaypointType::Arrive, 0, util::guidance::LaneTupel(), - ""}; + {}}; intersection = { target_node.location, std::vector({static_cast(util::bearing::reverseBearing(bearings.first))}), @@ -244,7 +245,7 @@ inline std::vector 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; } diff --git a/include/engine/guidance/debug.hpp b/include/engine/guidance/debug.hpp deleted file mode 100644 index 0f7d62966..000000000 --- a/include/engine/guidance/debug.hpp +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef OSRM_ENGINE_GUIDANCE_DEBUG_HPP_ -#define OSRM_ENGINE_GUIDANCE_DEBUG_HPP_ - -#include "engine/guidance/route_step.hpp" - -#include -#include - -namespace osrm -{ -namespace engine -{ -namespace guidance -{ -inline void print(const RouteStep &step) -{ - std::cout << static_cast(step.maneuver.instruction.type) << " " - << static_cast(step.maneuver.instruction.direction_modifier) << " " - << static_cast(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 &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_*/ diff --git a/include/engine/guidance/step_maneuver.hpp b/include/engine/guidance/step_maneuver.hpp index 213a3695c..3a765c5e3 100644 --- a/include/engine/guidance/step_maneuver.hpp +++ b/include/engine/guidance/step_maneuver.hpp @@ -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 diff --git a/include/engine/routing_algorithms/routing_base.hpp b/include/engine/routing_algorithms/routing_base.hpp index c1ba386b8..4f77c0975 100644 --- a/include/engine/routing_algorithms/routing_base.hpp +++ b/include/engine/routing_algorithms/routing_base.hpp @@ -327,7 +327,7 @@ template 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 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}); diff --git a/include/extractor/edge_based_graph_factory.hpp b/include/extractor/edge_based_graph_factory.hpp index 491cb0fb7..ce64508dc 100644 --- a/include/extractor/edge_based_graph_factory.hpp +++ b/include/extractor/edge_based_graph_factory.hpp @@ -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 node_based_graph, - const CompressedEdgeContainer &compressed_edge_container, - const std::unordered_set &barrier_nodes, - const std::unordered_set &traffic_lights, - std::shared_ptr restriction_map, - const std::vector &node_info_list, - ProfileProperties profile_properties, - const util::NameTable &name_table, - const util::NameTable &turn_lanes); + explicit EdgeBasedGraphFactory( + std::shared_ptr node_based_graph, + const CompressedEdgeContainer &compressed_edge_container, + const std::unordered_set &barrier_nodes, + const std::unordered_set &traffic_lights, + std::shared_ptr restriction_map, + const std::vector &node_info_list, + ProfileProperties profile_properties, + const util::NameTable &name_table, + const std::vector &turn_lane_offsets, + const std::vector &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 &turn_lane_offsets; + const std::vector &turn_lane_masks; void CompressGeometry(); unsigned RenumberEdges(); diff --git a/include/extractor/extraction_containers.hpp b/include/extractor/extraction_containers.hpp index a03d3637c..6f56dffb7 100644 --- a/include/extractor/extraction_containers.hpp +++ b/include/extractor/extraction_containers.hpp @@ -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 #include +#include namespace osrm { @@ -40,6 +42,9 @@ class ExtractionContainers void WriteCharData(const std::string &file_name, const stxxl::vector &offests, const stxxl::vector &char_data) const; + void WriteTurnLaneMasks(const std::string &file_name, + const stxxl::vector &turn_lane_offsets, + const stxxl::vector &turn_lane_masks) const; public: using STXXLNodeIDVector = stxxl::vector; @@ -53,8 +58,9 @@ class ExtractionContainers STXXLEdgeVector all_edges_list; stxxl::vector name_char_data; stxxl::vector name_lengths; - stxxl::vector turn_lane_char_data; - stxxl::vector turn_lane_lengths; + // an adjacency array containing all turn lane masks + stxxl::vector turn_lane_offsets; + stxxl::vector turn_lane_masks; STXXLRestrictionsVector restrictions_list; STXXLWayIDStartEndVector way_start_end_id_list; std::unordered_map external_to_internal_node_id_map; diff --git a/include/extractor/extractor_callbacks.hpp b/include/extractor/extractor_callbacks.hpp index 2c5314a5f..2adfb7dc5 100644 --- a/include/extractor/extractor_callbacks.hpp +++ b/include/extractor/extractor_callbacks.hpp @@ -2,6 +2,8 @@ #define EXTRACTOR_CALLBACKS_HPP #include "util/typedefs.hpp" +#include "extractor/guidance/turn_lane_types.hpp" + #include #include @@ -38,7 +40,7 @@ class ExtractorCallbacks using MapKey = std::pair; using MapVal = unsigned; std::unordered_map> string_map; - std::unordered_map lane_map; + std::unordered_map lane_description_map; ExtractionContainers &external_memory; public: diff --git a/include/extractor/extractor_config.hpp b/include/extractor/extractor_config.hpp index fa3cf3979..d0b5fd2c6 100644 --- a/include/extractor/extractor_config.hpp +++ b/include/extractor/extractor_config.hpp @@ -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; diff --git a/include/extractor/guidance/debug.hpp b/include/extractor/guidance/debug.hpp deleted file mode 100644 index 601b72d63..000000000 --- a/include/extractor/guidance/debug.hpp +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef OSRM_EXTRACTOR_GUIDANCE_DEBUG_HPP_ -#define OSRM_EXTRACTOR_GUIDANCE_DEBUG_HPP_ - -#include -#include -#include - -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(entry.from) - << " to: " << static_cast(entry.to) << "\n"; - std::cout << std::flush; -} - -inline void printTurnAssignmentData(const NodeID at, - const LaneDataVector &turn_lane_data, - const Intersection &intersection, - const std::vector &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_ */ diff --git a/include/extractor/guidance/turn_lane_data.hpp b/include/extractor/guidance/turn_lane_data.hpp index b35c5ccd5..f1a7d7e12 100644 --- a/include/extractor/guidance/turn_lane_data.hpp +++ b/include/extractor/guidance/turn_lane_data.hpp @@ -2,6 +2,7 @@ #define OSRM_EXTRACTOR_GUIDANCE_TURN_LANE_DATA_HPP_ #include "util/typedefs.hpp" +#include "extractor/guidance/turn_lane_types.hpp" #include #include @@ -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 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 diff --git a/include/extractor/guidance/turn_lane_handler.hpp b/include/extractor/guidance/turn_lane_handler.hpp index fe675a7d4..2fb54164b 100644 --- a/include/extractor/guidance/turn_lane_handler.hpp +++ b/include/extractor/guidance/turn_lane_handler.hpp @@ -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 #include #include #include @@ -34,7 +36,8 @@ class TurnLaneHandler typedef std::vector LaneDataVector; TurnLaneHandler(const util::NodeBasedDynamicGraph &node_based_graph, - const util::NameTable &turn_lane_strings, + const std::vector &turn_lane_offsets, + const std::vector &turn_lane_masks, const std::vector &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 &turn_lane_offsets; + const std::vector &turn_lane_masks; const std::vector &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 diff --git a/include/extractor/guidance/turn_lane_matcher.hpp b/include/extractor/guidance/turn_lane_matcher.hpp index 36bf8cf5b..8dfcfe8da 100644 --- a/include/extractor/guidance/turn_lane_matcher.hpp +++ b/include/extractor/guidance/turn_lane_matcher.hpp @@ -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 diff --git a/include/extractor/guidance/turn_lane_types.hpp b/include/extractor/guidance/turn_lane_types.hpp new file mode 100644 index 000000000..3a06a3b10 --- /dev/null +++ b/include/extractor/guidance/turn_lane_types.hpp @@ -0,0 +1,102 @@ +#ifndef OSRM_GUIDANCE_TURN_LANE_TYPES_HPP_ +#define OSRM_GUIDANCE_TURN_LANE_TYPES_HPP_ + +#include +#include +#include +#include +#include + +#include +#include + +#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 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_ */ diff --git a/include/extractor/internal_extractor_edge.hpp b/include/extractor/internal_extractor_edge.hpp index 5a892170d..a189bbdb3 100644 --- a/include/extractor/internal_extractor_edge.hpp +++ b/include/extractor/internal_extractor_edge.hpp @@ -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()); } diff --git a/include/extractor/node_based_edge.hpp b/include/extractor/node_based_edge.hpp index 6c1d212fe..100977699 100644 --- a/include/extractor/node_based_edge.hpp +++ b/include/extractor/node_based_edge.hpp @@ -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)) { diff --git a/include/storage/shared_datatype.hpp b/include/storage/shared_datatype.hpp index 33b841d70..8c05c3aad 100644 --- a/include/storage/shared_datatype.hpp +++ b/include/storage/shared_datatype.hpp @@ -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."); } } diff --git a/include/storage/storage_config.hpp b/include/storage/storage_config.hpp index 0d877772b..e68129a11 100644 --- a/include/storage/storage_config.hpp +++ b/include/storage/storage_config.hpp @@ -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; }; } } diff --git a/include/util/debug.hpp b/include/util/debug.hpp new file mode 100644 index 000000000..11f9f9044 --- /dev/null +++ b/include/util/debug.hpp @@ -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 +#include +#include + +namespace osrm +{ +namespace util +{ +namespace guidance +{ +inline void print(const engine::guidance::RouteStep &step) +{ + std::cout << static_cast(step.maneuver.instruction.type) << " " + << static_cast(step.maneuver.instruction.direction_modifier) << " " + << static_cast(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 &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(entry.from) + << " to: " << static_cast(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 &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_*/ diff --git a/include/util/guidance/turn_lanes.hpp b/include/util/guidance/turn_lanes.hpp index 5eec9de44..a4f9a7473 100644 --- a/include/util/guidance/turn_lanes.hpp +++ b/include/util/guidance/turn_lanes.hpp @@ -74,7 +74,7 @@ class LaneTupel } }; -using LaneTupelIdPair = std::pair; +using LaneTupelIdPair = std::pair; } // namespace guidance } // namespace util } // namespace osrm diff --git a/include/util/io.hpp b/include/util/io.hpp index 2f3177fb3..cb4473dd4 100644 --- a/include/util/io.hpp +++ b/include/util/io.hpp @@ -4,12 +4,14 @@ #include "util/simple_logger.hpp" #include +#include #include #include #include #include +#include #include #include "util/fingerprint.hpp" @@ -88,6 +90,84 @@ bool deserializeVector(std::istream &stream, std::vector &data) return static_cast(stream); } +// serializes a vector of vectors into an adjacency array (creates a copy of the data internally) +template +bool serializeVectorIntoAdjacencyArray(const std::string &filename, + const std::vector> &data) +{ + std::ofstream out_stream(filename, std::ios::binary); + std::vector 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(current_offset)); + } + if (!serializeVector(out_stream, offsets)) + return false; + + std::vector 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(out_stream); +} + +template +bool serializeVector(std::ofstream &out_stream, const stxxl::vector &data) +{ + const std::uint64_t size = data.size(); + out_stream.write(reinterpret_cast(&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(write_buffer), + WRITE_BLOCK_BUFFER_SIZE * sizeof(simple_type)); + buffer_len = 0; + } + } + + // write remaining entries + if (buffer_len > 0) + out_stream.write(reinterpret_cast(write_buffer), + buffer_len * sizeof(simple_type)); + + return static_cast(out_stream); +} + +template +bool deserializeAdjacencyArray(const std::string &filename, + std::vector &offsets, + std::vector& 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(data.size()))) + return false; + + return static_cast(in_stream); +} + inline bool serializeFlags(const boost::filesystem::path &path, const std::vector &flags) { // TODO this should be replaced with a FILE-based write using error checking diff --git a/include/util/node_based_graph.hpp b/include/util/node_based_graph.hpp index cfdfc77d9..957b83c7b 100644 --- a/include/util/node_based_graph.hpp +++ b/include/util/node_based_graph.hpp @@ -21,7 +21,7 @@ struct NodeBasedEdgeData : distance(INVALID_EDGE_WEIGHT), edge_id(SPECIAL_NODEID), name_id(std::numeric_limits::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()); diff --git a/include/util/typedefs.hpp b/include/util/typedefs.hpp index 7893f7553..7c4337182 100644 --- a/include/util/typedefs.hpp +++ b/include/util/typedefs.hpp @@ -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::max(); using LaneID = std::uint8_t; static const LaneID INVALID_LANEID = std::numeric_limits::max(); using LaneDataID = std::uint16_t; -static const LaneDataID INVALID_LANE_DATAID = std::numeric_limits::max(); +static const LaneDataID INVALID_LANE_DATAID = std::numeric_limits::max(); +using LaneDescriptionID = std::uint16_t; +static const LaneDescriptionID INVALID_LANE_DESCRIPTIONID = std::numeric_limits::max(); using BearingClassID = std::uint32_t; static const BearingClassID INVALID_BEARING_CLASSID = std::numeric_limits::max(); diff --git a/src/engine/api/json_factory.cpp b/src/engine/api/json_factory.cpp index 1a5fe31fe..2fa00dae8 100644 --- a/src/engine/api/json_factory.cpp +++ b/src/engine/api/json_factory.cpp @@ -11,7 +11,6 @@ #include #include -#include #include #include @@ -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> tokenizer; - boost::char_separator 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); } diff --git a/src/engine/guidance/post_processing.cpp b/src/engine/guidance/post_processing.cpp index 2dcadbe69..0aebefc8b 100644 --- a/src/engine/guidance/post_processing.cpp +++ b/src/engine/guidance/post_processing.cpp @@ -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 &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 postProcess(std::vector 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 &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 &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]}; diff --git a/src/extractor/edge_based_graph_factory.cpp b/src/extractor/edge_based_graph_factory.cpp index da1a7b1ff..79ff239a7 100644 --- a/src/extractor/edge_based_graph_factory.cpp +++ b/src/extractor/edge_based_graph_factory.cpp @@ -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 &node_info_list, ProfileProperties profile_properties, const util::NameTable &name_table, - const util::NameTable &turn_lanes) + const std::vector &turn_lane_offsets, + const std::vector &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::max()); diff --git a/src/extractor/extraction_containers.cpp b/src/extractor/extraction_containers.cpp index 2f945c1d3..2f36ee762 100644 --- a/src/extractor/extraction_containers.cpp +++ b/src/extractor/extraction_containers.cpp @@ -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 &offsets, + const stxxl::vector &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 &offsets, const stxxl::vector &char_data) const diff --git a/src/extractor/extractor.cpp b/src/extractor/extractor.cpp index 3861b521c..78015b1ac 100644 --- a/src/extractor/extractor.cpp +++ b/src/extractor/extractor.cpp @@ -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 turn_lane_offsets; + std::vector 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, diff --git a/src/extractor/extractor_callbacks.cpp b/src/extractor/extractor_callbacks.cpp index 9d26e7266..76669cb94 100644 --- a/src/extractor/extractor_callbacks.cpp +++ b/src/extractor/extractor_callbacks.cpp @@ -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 #include +#include #include @@ -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> tokenizer; + boost::char_separator sep("|&", "", boost::keep_empty_tokens); + boost::char_separator 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(external_memory.turn_lane_lengths.size()); - auto turn_lane_length = std::min(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(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)); diff --git a/src/extractor/graph_compressor.cpp b/src/extractor/graph_compressor.cpp index 02c1841f6..18af7fdb4 100644 --- a/src/extractor/graph_compressor.cpp +++ b/src/extractor/graph_compressor.cpp @@ -160,18 +160,18 @@ void GraphCompressor::Compress(const std::unordered_set &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); diff --git a/src/extractor/guidance/turn_lane_augmentation.cpp b/src/extractor/guidance/turn_lane_augmentation.cpp index 755143370..c911583c4 100644 --- a/src/extractor/guidance/turn_lane_augmentation.cpp +++ b/src/extractor/guidance/turn_lane_augmentation.cpp @@ -1,4 +1,5 @@ #include "extractor/guidance/turn_lane_augmentation.hpp" +#include "extractor/guidance/turn_lane_types.hpp" #include "util/simple_logger.hpp" #include @@ -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()); diff --git a/src/extractor/guidance/turn_lane_data.cpp b/src/extractor/guidance/turn_lane_data.cpp index f407d4e5c..b78722b22 100644 --- a/src/extractor/guidance/turn_lane_data.cpp +++ b/src/extractor/guidance/turn_lane_data.cpp @@ -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> LaneMap; + typedef std::unordered_map> 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( - std::count(turn_lane_string.begin(), turn_lane_string.end(), '|') + 1); - }(turn_lane_string); + const auto num_lanes = boost::numeric_cast(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(); } diff --git a/src/extractor/guidance/turn_lane_handler.cpp b/src/extractor/guidance/turn_lane_handler.cpp index f42b53224..22a9d138d 100644 --- a/src/extractor/guidance/turn_lane_handler.cpp +++ b/src/extractor/guidance/turn_lane_handler.cpp @@ -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 &turn_lane_offsets, + const std::vector &turn_lane_masks, const std::vector &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( - 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 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 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 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 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 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 diff --git a/src/extractor/guidance/turn_lane_matcher.cpp b/src/extractor/guidance/turn_lane_matcher.cpp index 906edaddb..56b00cec7 100644 --- a/src/extractor/guidance/turn_lane_matcher.cpp +++ b/src/extractor/guidance/turn_lane_matcher.cpp @@ -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 @@ -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) diff --git a/src/storage/storage.cpp b/src/storage/storage.cpp index aa0972317..b3b125551 100644 --- a/src/storage/storage.cpp +++ b/src/storage/storage.cpp @@ -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(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(SharedDataLayout::TURN_STRING_OFFSETS, - turn_string_blocks); - shared_layout_ptr->SetBlockSize::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(SharedDataLayout::TURN_STRING_CHAR_LIST, - number_of_turn_string_chars); + std::vector lane_description_offsets; + std::vector 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(SharedDataLayout::LANE_DESCRIPTION_OFFSETS, + lane_description_offsets.size()); + shared_layout_ptr->SetBlockSize( + 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( 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( - 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( @@ -489,30 +471,29 @@ int Storage::Run() } lane_data_stream.close(); - unsigned *turn_string_blocks_ptr = shared_layout_ptr->GetBlockPtr( - 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( + 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 tmp; + lane_description_offsets.swap(tmp); } - char *turn_string_char_ptr = shared_layout_ptr->GetBlockPtr( - 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( + 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 tmp; + lane_description_masks.swap(tmp); } - turn_string_stream.close(); // load original edge information NodeID *via_node_ptr = shared_layout_ptr->GetBlockPtr( @@ -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); } diff --git a/src/storage/storage_config.cpp b/src/storage/storage_config.cpp index 984408b39..c1edaf6f7 100644 --- a/src/storage/storage_config.cpp +++ b/src/storage/storage_config.cpp @@ -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"} { } diff --git a/unit_tests/extractor/graph_compressor.cpp b/unit_tests/extractor/graph_compressor.cpp index 948e82db0..7ef65ae87 100644 --- a/unit_tests/extractor/graph_compressor.cpp +++ b/unit_tests/extractor/graph_compressor.cpp @@ -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); diff --git a/unit_tests/mocks/mock_datafacade.hpp b/unit_tests/mocks/mock_datafacade.hpp index 17c511287..f36276c6a 100644 --- a/unit_tests/mocks/mock_datafacade.hpp +++ b/unit_tests/mocks/mock_datafacade.hpp @@ -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