From de942155bf8f93641f04d99923518bb1071a5e2b Mon Sep 17 00:00:00 2001 From: Michael Krasnyk Date: Tue, 15 Aug 2017 16:53:27 +0200 Subject: [PATCH] Add local left_hand_driving flag in API version 2 --- features/car/side_bias.feature | 32 +++++++++++++++++-- .../guidance/roundabout-left-sided.feature | 2 +- .../contiguous_internalmem_datafacade.hpp | 2 +- include/extractor/extraction_turn.hpp | 27 +++++++++++----- include/extractor/profile_properties.hpp | 2 +- profiles/car.lua | 15 ++++----- profiles/lib/way_handlers.lua | 20 ++++++++++-- src/extractor/edge_based_graph_factory.cpp | 8 +++-- src/extractor/graph_compressor.cpp | 14 ++++---- src/extractor/guidance/roundabout_handler.cpp | 5 +-- src/extractor/scripting_environment_lua.cpp | 8 +++-- 11 files changed, 96 insertions(+), 39 deletions(-) diff --git a/features/car/side_bias.feature b/features/car/side_bias.feature index 2547ef21a..8b8dd1ed0 100644 --- a/features/car/side_bias.feature +++ b/features/car/side_bias.feature @@ -5,7 +5,7 @@ Feature: Testbot - side bias Given the profile file "car" initialized with """ profile.left_hand_driving = true - profile.turn_bias = 1/1.075 + profile.turn_bias = 1.075 """ Given the node map """ @@ -28,7 +28,7 @@ Feature: Testbot - side bias Given the profile file "car" initialized with """ profile.left_hand_driving = true - profile.turn_bias = 1.075 + profile.turn_bias = 1 / 1.075 """ And the node map """ @@ -47,3 +47,31 @@ Feature: Testbot - side bias | d | a | bd,ab,ab | 27s +-1 | # should be inverse of left hand bias | d | c | bd,bc,bc | 24s +-1 | + + Scenario: Roundabout exit counting for left sided driving + Given the profile file "testbot" initialized with + """ + profile.left_hand_driving = true + """ + And a grid size of 10 meters + And the node map + """ + a + b + h g c d + e + f + """ + And the ways + | nodes | junction | + | ab | | + | cd | | + | ef | | + | gh | | + | bcegb | roundabout | + + When I route I should get + | waypoints | route | turns | + | a,d | ab,cd,cd | depart,roundabout turn left exit-1,arrive | + | a,f | ab,ef,ef | depart,roundabout turn straight exit-2,arrive | + | a,h | ab,gh,gh | depart,roundabout turn right exit-3,arrive | diff --git a/features/guidance/roundabout-left-sided.feature b/features/guidance/roundabout-left-sided.feature index 103da7544..ed099b41f 100644 --- a/features/guidance/roundabout-left-sided.feature +++ b/features/guidance/roundabout-left-sided.feature @@ -5,7 +5,7 @@ Feature: Basic Roundabout Given a grid size of 10 meters Given the profile file "car" initialized with """ - profile.properties.left_hand_driving = true + profile.left_hand_driving = true """ Scenario: Roundabout exit counting for left sided driving diff --git a/include/engine/datafacade/contiguous_internalmem_datafacade.hpp b/include/engine/datafacade/contiguous_internalmem_datafacade.hpp index 5824d7fa7..44e322d85 100644 --- a/include/engine/datafacade/contiguous_internalmem_datafacade.hpp +++ b/include/engine/datafacade/contiguous_internalmem_datafacade.hpp @@ -941,7 +941,7 @@ class ContiguousInternalMemoryDataFacadeBase : public BaseDataFacade bool IsLeftHandDriving() const override final { - return m_profile_properties->left_hand_driving; + return m_profile_properties->left_hand_driving; // TODO: remove } }; diff --git a/include/extractor/extraction_turn.hpp b/include/extractor/extraction_turn.hpp index fba8dafd5..ccb71009d 100644 --- a/include/extractor/extraction_turn.hpp +++ b/include/extractor/extraction_turn.hpp @@ -14,19 +14,28 @@ namespace extractor struct ExtractionTurn { - ExtractionTurn(const guidance::ConnectedRoad &turn, bool has_traffic_light) + ExtractionTurn(const guidance::ConnectedRoad &turn, + bool has_traffic_light, + bool source_restricted, + bool target_restricted, + bool is_left_hand_driving) : angle(180. - turn.angle), turn_type(turn.instruction.type), direction_modifier(turn.instruction.direction_modifier), - has_traffic_light(has_traffic_light), weight(0.), duration(0.), source_restricted(false), - target_restricted(false) + has_traffic_light(has_traffic_light), source_restricted(source_restricted), + target_restricted(target_restricted), is_left_hand_driving(is_left_hand_driving), + weight(0.), duration(0.) { } - ExtractionTurn(const bool has_traffic_light = false) + ExtractionTurn(bool has_traffic_light, + bool source_restricted, + bool target_restricted, + bool is_left_hand_driving) : angle(0), turn_type(guidance::TurnType::NoTurn), direction_modifier(guidance::DirectionModifier::Straight), - has_traffic_light(has_traffic_light), weight(0.), duration(0.), source_restricted(false), - target_restricted(false) + has_traffic_light(has_traffic_light), source_restricted(source_restricted), + target_restricted(target_restricted), is_left_hand_driving(is_left_hand_driving), + weight(0.), duration(0.) { } @@ -34,10 +43,12 @@ struct ExtractionTurn const guidance::TurnType::Enum turn_type; const guidance::DirectionModifier::Enum direction_modifier; const bool has_traffic_light; + const bool source_restricted; + const bool target_restricted; + const bool is_left_hand_driving; + double weight; double duration; - bool source_restricted; - bool target_restricted; }; } } diff --git a/include/extractor/profile_properties.hpp b/include/extractor/profile_properties.hpp index 6d98fd714..15e90e70e 100644 --- a/include/extractor/profile_properties.hpp +++ b/include/extractor/profile_properties.hpp @@ -124,7 +124,7 @@ struct ProfileProperties bool continue_straight_at_waypoint; //! flag used for restriction parser (e.g. used for the walk profile) bool use_turn_restrictions; - bool left_hand_driving; + bool left_hand_driving; // DEPRECATED: property value is local to edges from API version 2 bool fallback_to_duration; //! stores the name of the weight (e.g. 'duration', 'distance', 'safety') char weight_name[MAX_WEIGHT_NAME_LENGTH + 1]; diff --git a/profiles/car.lua b/profiles/car.lua index 92ec497bb..3795ec32a 100644 --- a/profiles/car.lua +++ b/profiles/car.lua @@ -9,11 +9,9 @@ find_access_tag = require("lib/access").find_access_tag limit = require("lib/maxspeed").limit function setup() - local use_left_hand_driving = false return { properties = { max_speed_for_map_matching = 180/3.6, -- 180kmph -> m/s - left_hand_driving = use_left_hand_driving, -- For routing based on duration, but weighted for preferring certain roads weight_name = 'routability', -- For shortest duration without penalties for accessibility @@ -27,16 +25,14 @@ function setup() traffic_light_penalty = 2, }, + left_hand_driving = false, default_mode = mode.driving, default_speed = 10, oneway_handling = true, side_road_multiplier = 0.8, turn_penalty = 7.5, speed_reduction = 0.8, - - -- Note: this biases right-side driving. - -- Should be inverted for left-driving countries. - turn_bias = use_left_hand_driving and 1/1.075 or 1.075, + turn_bias = 1.075, -- a list of suffixes to suppress in name change instructions suffix_list = { @@ -307,7 +303,7 @@ function process_node(profile, node, result) end end -function process_way(profile, way, result) +function process_way(profile, way, result, location_data) -- the intial filtering of ways based on presence of tags -- affects processing times significantly, because all ways -- have to be checked. @@ -382,6 +378,7 @@ function process_way(profile, way, result) -- handle various other flags WayHandlers.roundabouts, WayHandlers.startpoint, + WayHandlers.driving_side, -- set name, ref and pronunciation WayHandlers.names, @@ -390,7 +387,7 @@ function process_way(profile, way, result) WayHandlers.weights } - WayHandlers.run(profile,way,result,data,handlers) + WayHandlers.run(profile, way, result, data, handlers, location_data) end function process_turn(profile, turn) @@ -398,7 +395,7 @@ function process_turn(profile, turn) -- over the space of 0-180 degrees. Values here were chosen by fitting -- the function to some turn penalty samples from real driving. local turn_penalty = profile.turn_penalty - local turn_bias = profile.turn_bias + local turn_bias = turn.is_left_hand_driving and 1. / profile.turn_bias or profile.turn_bias if turn.has_traffic_light then turn.duration = profile.properties.traffic_light_penalty diff --git a/profiles/lib/way_handlers.lua b/profiles/lib/way_handlers.lua index e5d089374..88de8f3d4 100644 --- a/profiles/lib/way_handlers.lua +++ b/profiles/lib/way_handlers.lua @@ -552,6 +552,20 @@ function WayHandlers.blocked_ways(profile,way,result,data) end end +function WayHandlers.driving_side(profile, way, result, data, location_data) + local driving_side = way:get_value_by_key("driving_side") + if driving_side == 'left' then + result.is_left_hand_driving = true + elseif driving_side == 'right' then + result.is_left_hand_driving = false + elseif location_data then + result.is_left_hand_driving = location_data['driving_side'] == 'left' + elseif profile.left_hand_driving then + result.is_left_hand_driving = true + end +end + + -- Call a sequence of handlers, aborting in case a handler returns false. Example: -- -- handlers = Sequence { @@ -566,13 +580,13 @@ end -- WayHandlers.run(handlers,way,result,data,profile) -- -- Each method in the list will be called on the WayHandlers object. --- All handlers must accept the parameteres (profile,way,result,data) and return false +-- All handlers must accept the parameteres (profile, way, result, data[, location_data]) and return false -- if the handler chain should be aborted. -- To ensure the correct order of method calls, use a Sequence of handler names. -function WayHandlers.run(profile,way,result,data,handlers) +function WayHandlers.run(profile, way, result, data, handlers, location_data) for i,handler in ipairs(handlers) do - if handler(profile,way,result,data) == false then + if handler(profile, way, result, data, location_data) == false then return false end end diff --git a/src/extractor/edge_based_graph_factory.cpp b/src/extractor/edge_based_graph_factory.cpp index 3131e6519..20012bc97 100644 --- a/src/extractor/edge_based_graph_factory.cpp +++ b/src/extractor/edge_based_graph_factory.cpp @@ -578,9 +578,11 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges( // compute weight and duration penalties auto is_traffic_light = m_traffic_lights.count(node_at_center_of_intersection); - ExtractionTurn extracted_turn(turn, is_traffic_light); - extracted_turn.source_restricted = edge_data1.restricted; - extracted_turn.target_restricted = edge_data2.restricted; + ExtractionTurn extracted_turn(turn, + is_traffic_light, + edge_data1.restricted, + edge_data2.restricted, + edge_data1.is_left_hand_driving); scripting_environment.ProcessTurn(extracted_turn); // turn penalties are limited to [-2^15, 2^15) which roughly diff --git a/src/extractor/graph_compressor.cpp b/src/extractor/graph_compressor.cpp index 883bbd633..cab2ae4cd 100644 --- a/src/extractor/graph_compressor.cpp +++ b/src/extractor/graph_compressor.cpp @@ -205,16 +205,16 @@ void GraphCompressor::Compress( boost::optional node_weight_penalty = boost::none; if (has_node_penalty) { - // generate an artifical turn for the turn penalty generation - ExtractionTurn extraction_turn(true); - - extraction_turn.source_restricted = fwd_edge_data1.restricted; - extraction_turn.target_restricted = fwd_edge_data2.restricted; - // we cannot handle this as node penalty, if it depends on turn direction - if (extraction_turn.source_restricted != extraction_turn.target_restricted) + if (fwd_edge_data1.restricted != fwd_edge_data2.restricted) continue; + // generate an artifical turn for the turn penalty generation + ExtractionTurn extraction_turn(true, + fwd_edge_data1.restricted, + fwd_edge_data2.restricted, + fwd_edge_data1.is_left_hand_driving); + scripting_environment.ProcessTurn(extraction_turn); node_duration_penalty = extraction_turn.duration * 10; node_weight_penalty = extraction_turn.weight * weight_multiplier; diff --git a/src/extractor/guidance/roundabout_handler.cpp b/src/extractor/guidance/roundabout_handler.cpp index 954d2b602..36fb32bcf 100644 --- a/src/extractor/guidance/roundabout_handler.cpp +++ b/src/extractor/guidance/roundabout_handler.cpp @@ -74,7 +74,7 @@ detail::RoundaboutFlags RoundaboutHandler::getRoundaboutFlags( bool can_enter_roundabout = false; bool can_exit_roundabout_separately = false; - const bool lhs = profile_properties.left_hand_driving; + const bool lhs = in_edge_data.is_left_hand_driving; const int step = lhs ? -1 : 1; for (std::size_t cnt = 0, idx = lhs ? intersection.size() - 1 : 0; cnt < intersection.size(); ++cnt, idx += step) @@ -433,8 +433,9 @@ Intersection RoundaboutHandler::handleRoundabouts(const RoundaboutType roundabou Intersection intersection) const { NodeID node_at_center_of_intersection = node_based_graph.GetTarget(via_eid); + const auto &in_edge_data = node_based_graph.GetEdgeData(via_eid); - const bool lhs = profile_properties.left_hand_driving; + const bool lhs = in_edge_data.is_left_hand_driving; const int step = lhs ? -1 : 1; if (on_roundabout) diff --git a/src/extractor/scripting_environment_lua.cpp b/src/extractor/scripting_environment_lua.cpp index 416e8c816..be6819a5b 100644 --- a/src/extractor/scripting_environment_lua.cpp +++ b/src/extractor/scripting_environment_lua.cpp @@ -237,7 +237,7 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context) "interpolate", &RasterContainer::GetRasterInterpolateFromSource); - context.state.new_usertype( + auto registration_ProfileProperties = context.state.new_usertype( "ProfileProperties", "traffic_signal_penalty", sol::property(&ProfileProperties::GetTrafficSignalPenalty, @@ -446,7 +446,9 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context) "source_restricted", &ExtractionTurn::source_restricted, "target_restricted", - &ExtractionTurn::target_restricted); + &ExtractionTurn::target_restricted, + "is_left_hand_driving", + &ExtractionTurn::is_left_hand_driving); // Keep in mind .location is available only if .pbf is preprocessed to set the location with the // ref using osmium command "osmium add-locations-to-ways" @@ -580,6 +582,7 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context) if (use_turn_restrictions != sol::nullopt) context.properties.use_turn_restrictions = use_turn_restrictions.value(); + // DEPRECATED: global left_hand_driving will be removed in the next profile API sol::optional left_hand_driving = properties["left_hand_driving"]; if (left_hand_driving != sol::nullopt) context.properties.left_hand_driving = left_hand_driving.value(); @@ -992,6 +995,7 @@ void LuaScriptingContext::ProcessWay(const osmium::Way &way, case 1: case 0: way_function(way, result); + result.is_left_hand_driving = properties.left_hand_driving; break; } }