From 7d076e93445a4d016422a575f1132b267cd13c29 Mon Sep 17 00:00:00 2001 From: Moritz Kobitzsch Date: Fri, 8 Jul 2016 10:44:49 +0200 Subject: [PATCH] handle access flags for lanes --- CHANGELOG.md | 2 + features/guidance/turn-lanes.feature | 16 ++++++++ .../extractor/extraction_helper_functions.hpp | 7 ++++ include/extractor/guidance/toolkit.hpp | 41 +++++++++++++++++++ profiles/lib/guidance.lua | 28 +++++++++---- src/extractor/scripting_environment_lua.cpp | 1 + taginfo.json | 17 +++++++- 7 files changed, 104 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f2a82805..cd63cd7ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # 5.4.0 - Profiles - includes library guidance.lua that offers preliminary configuration on guidance. + - Guidance + - Handle Access tags for lanes, only considering valid lanes in lane-guidance (think car | car | bike | car) # 5.3.0 Changes from 5.3.0-rc.3 diff --git a/features/guidance/turn-lanes.feature b/features/guidance/turn-lanes.feature index 189a7fe08..afb8fff3d 100644 --- a/features/guidance/turn-lanes.feature +++ b/features/guidance/turn-lanes.feature @@ -24,6 +24,22 @@ Feature: Turn Lane Guidance | 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 3-way Turn with designated lane + Given the node map + | a | | b | | c | + | | | d | | | + + And the ways + | nodes | turn:lanes | turn:lanes:forward | name | vehicle:lanes:forward | + | ab | | through\|through\|right | in | yes\|no\|yes | + | bc | | | straight | | + | bd | | | right | | + + When I route I should get + | 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, | + Scenario: Basic Turn Lane 4-Way Turn Given the node map | | | e | | | diff --git a/include/extractor/extraction_helper_functions.hpp b/include/extractor/extraction_helper_functions.hpp index 9fb5477d7..1240d33e3 100644 --- a/include/extractor/extraction_helper_functions.hpp +++ b/include/extractor/extraction_helper_functions.hpp @@ -106,6 +106,13 @@ trimLaneString(std::string lane_string, std::int32_t count_left, std::int32_t co { return extractor::guidance::trimLaneString(std::move(lane_string), count_left, count_right); } + +inline std::string +applyAccessTokens(const std::string &lane_string, const std::string &access_tokens) +{ + return extractor::guidance::trimLaneString(lane_string,access_tokens); +} + } } diff --git a/include/extractor/guidance/toolkit.hpp b/include/extractor/guidance/toolkit.hpp index 815cda224..0b59f100f 100644 --- a/include/extractor/guidance/toolkit.hpp +++ b/include/extractor/guidance/toolkit.hpp @@ -27,6 +27,7 @@ #include #include #include +#include namespace osrm { @@ -349,6 +350,46 @@ trimLaneString(std::string lane_string, std::int32_t count_left, std::int32_t co return lane_string; } +// https://github.com/Project-OSRM/osrm-backend/issues/2638 +// It can happen that some lanes are not drivable by car. Here we handle this tagging scheme +// (vehicle:lanes) to filter out not-allowed roads +// lanes=3 +// turn:lanes=left|through|through|right +// vehicle:lanes=yes|yes|no|yes +// bicycle:lanes=yes|no|designated|yes + +inline std::string trimLaneString(std::string lane_string, const std::string &access_tokens) +{ + typedef boost::tokenizer> tokenizer; + boost::char_separator sep("|", "", boost::keep_empty_tokens); + tokenizer tokens(lane_string, sep); + tokenizer access(access_tokens, sep); + + // strings don't match, don't do anything + if (std::distance(std::begin(tokens), std::end(tokens)) != + std::distance(std::begin(access), std::end(access))) + return lane_string; + + std::string result_string = ""; + const static std::string yes = "yes"; + + for (auto token_itr = std::begin(tokens), access_itr = std::begin(access); + token_itr != std::end(tokens); + ++token_itr, ++access_itr) + { + if (*access_itr == yes) + { + // we have to add this in front, because the next token could be invalid. Doing this on + // non-empty strings makes sure that the token string will be valid in the end + if (!result_string.empty()) + result_string += '|'; + + result_string += *token_itr; + } + } + return result_string; +} + } // namespace guidance } // namespace extractor } // namespace osrm diff --git a/profiles/lib/guidance.lua b/profiles/lib/guidance.lua index 19409ce11..3a4106eba 100644 --- a/profiles/lib/guidance.lua +++ b/profiles/lib/guidance.lua @@ -90,22 +90,36 @@ local function get_psv_counts(way) return fw, bw end +-- trims lane string with regard to supported lanes +local function process_lanes(turn_lane,vehicle_lane,first_count,second_count) + if turn_lane and turn_lane ~= "" then + if vehicle_lane and vehicle_lane ~= "" then + turn_lane = applyAccessTokens(turn_lane,vehicle_lane) + elseif fw_count ~= 0 or bw_count ~= 0 then + turn_lane = trimLaneString(turn_lane, first_count, second_count) + end + end + return turn_lane; +end + -- this is broken for left-sided driving. It needs to switch left and right in case of left-sided driving function Guidance.get_turn_lanes(way) local fw_psv = 0 - local bw_psv = 0 + local bw_psv = 0 fw_psv, bw_psv = get_psv_counts(way) local turn_lanes = way:get_value_by_key("turn:lanes") local turn_lanes_fw = way:get_value_by_key("turn:lanes:forward") local turn_lanes_bw = way:get_value_by_key("turn:lanes:backward") - if( fw_psv ~= 0 or bw_psv ~= 0 ) then - turn_lanes = trimLaneString(turn_lanes, bw_psv, fw_psv ) - turn_lanes_fw = trimLaneString(turn_lanes_fw, bw_psv, fw_psv ) - --backwards turn lanes need to treat bw_psv as fw_psv and vice versa - turn_lanes_bw = trimLaneString(turn_lanes_bw, fw_psv, bw_psv ) - end + local vehicle_lanes = way:get_value_by_key("vehicle:lanes"); + local vehicle_lanes_fw = way:get_value_by_key("vehicle:lanes:forward"); + local vehicle_lanes_bw = way:get_value_by_key("vehicle:lanes:backward"); + + turn_lanes = process_lanes(turn_lanes,vehicle_lanes,bw_psv,fw_psv) + turn_lanes_fw = process_lanes(turn_lanes_fw,vehicle_lanes_fw,bw_psv,fw_psv) + --backwards turn lanes need to treat bw_psv as fw_psv and vice versa + turn_lanes_bw = process_lanes(turn_lanes_bw,vehicle_lanes_bw,fw_psv,bw_psv) return turn_lanes, turn_lanes_fw, turn_lanes_bw end diff --git a/src/extractor/scripting_environment_lua.cpp b/src/extractor/scripting_environment_lua.cpp index bd35d1691..ccdcf4388 100644 --- a/src/extractor/scripting_environment_lua.cpp +++ b/src/extractor/scripting_environment_lua.cpp @@ -82,6 +82,7 @@ void LuaScriptingEnvironment::InitContext(LuaScriptingContext &context) [luabind::def("durationIsValid", durationIsValid), luabind::def("parseDuration", parseDuration), luabind::def("trimLaneString", trimLaneString), + luabind::def("applyAccessTokens", applyAccessTokens), luabind::class_("mode").enum_( "enums")[luabind::value("inaccessible", TRAVEL_MODE_INACCESSIBLE), luabind::value("driving", TRAVEL_MODE_DRIVING), diff --git a/taginfo.json b/taginfo.json index f83dc0d52..bc1883777 100644 --- a/taginfo.json +++ b/taginfo.json @@ -205,17 +205,32 @@ "object_types": [ "way" ], "description": "Turn Lanes for lane guidance." }, + { + "key": "vehicle:lanes", + "object_types": [ "way" ], + "description": "Access tags for turn lanes." + }, { "key": "turn:lanes:forward", "object_types": [ "way" ], "description": "Turn Lanes for lane guidance." }, + { + "key": "vehicle:lanes:forward", + "object_types": [ "way" ], + "description": "Access tags for turn lanes." + }, { "key": "turn:lanes:backward", "object_types": [ "way" ], "description": "Turn Lanes for lane guidance." }, - { + { + "key": "vehicle:lanes:backward", + "object_types": [ "way" ], + "description": "Access tags for turn lanes." + }, + { "key": "lanes:psv", "object_types": [ "way" ], "description": "Turn Lanes for lane guidance."