adjust testscases for collapse of use lane

This commit is contained in:
Moritz Kobitzsch 2016-07-22 09:08:40 +02:00
parent 86fd04e556
commit a551286a8f
25 changed files with 225 additions and 255 deletions

View File

@ -281,7 +281,7 @@ Feature: Turn Lane Guidance
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | waypoints | route | turns | lanes |
| a,e | main,main,main,main | depart,use lane straight,use lane straight,arrive | ,left:false straight:false straight:true straight:false right:false,left:false straight:true right:false, | | a,e | main,main,main | depart,use lane straight,arrive | ,left:false straight:false straight:true straight:false right:false, |
@anticipate @anticipate
Scenario: Anticipate Lanes for through and collapse multiple use lanes Scenario: Anticipate Lanes for through and collapse multiple use lanes
@ -306,8 +306,8 @@ Feature: Turn Lane Guidance
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | waypoints | route | turns | lanes |
| a,c | main,main,main | depart,use lane straight,arrive | ,left:false straight:true straight:true right:false, | | a,c | main,main | depart,arrive | , |
| a,d | main,main,main | depart,use lane straight,arrive | ,left:false straight:true straight:true right:false, | | a,d | main,main | depart,arrive | , |
@anticipate @anticipate
Scenario: Anticipate Lanes for through followed by left/right Scenario: Anticipate Lanes for through followed by left/right
@ -420,7 +420,7 @@ Feature: Turn Lane Guidance
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | waypoints | route | turns | lanes |
| a,e | main,main,main,main,main | depart,use lane straight,continue right,use lane straight,arrive | ,left:false straight:false straight:false straight:false straight:true straight:true right:false,straight:false straight:false right:false right:true right:true,left:false straight:true straight:true, | | a,e | main,main,main,main | depart,use lane straight,continue right,arrive | ,left:false straight:false straight:false straight:false straight:true straight:true right:false,straight:false straight:false right:false right:true right:true, |
@anticipate @todo @bug @2661 @anticipate @todo @bug @2661
Scenario: Anticipate with lanes in roundabout: roundabouts as the unit of anticipation Scenario: Anticipate with lanes in roundabout: roundabouts as the unit of anticipation
@ -615,7 +615,7 @@ Feature: Turn Lane Guidance
| x,c | xb,roundabout,roundabout | depart,roundabout-exit-undefined,arrive | ,, | | x,c | xb,roundabout,roundabout | depart,roundabout-exit-undefined,arrive | ,, |
| x,a | xb,roundabout,roundabout | depart,roundabout-exit-undefined,arrive | ,, | | x,a | xb,roundabout,roundabout | depart,roundabout-exit-undefined,arrive | ,, |
@anticipate @anticipate @todo @2032
Scenario: No Lanes for Roundabouts, see #2626 Scenario: No Lanes for Roundabouts, see #2626
Given the node map Given the node map
| a | b | | | x | | a | b | | | x |

View File

@ -768,7 +768,7 @@ Feature: Collapse
When I route I should get When I route I should get
| waypoints | route | turns | | waypoints | route | turns |
| a,e | main,main,main,main | depart,use lane straight,use lane straight,arrive | | a,e | main,main,main | depart,use lane straight,arrive |
Scenario: But _do_ collapse UseLane step when lanes stay the same Scenario: But _do_ collapse UseLane step when lanes stay the same
Given the node map Given the node map
@ -791,4 +791,4 @@ Feature: Collapse
When I route I should get When I route I should get
| waypoints | route | turns | | waypoints | route | turns |
| a,e | main,main,main | depart,use lane straight,arrive | | a,e | main,main | depart,arrive |

View File

@ -360,7 +360,7 @@ Feature: Turn Lane Guidance
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | waypoints | route | turns | lanes |
| a,f | road,turn,turn | depart,turn left,arrive | ,left:true straight;right:false, | | a,f | road,turn,turn | depart,turn left,arrive | ,left:true straight;right:false, |
| a,d | road,road,road | depart,use lane straight,arrive | ,left:false straight;right:true, | | a,d | road,road | depart,arrive | , |
| a,g | road,right,right | depart,turn right,arrive | ,left:false straight;right:true, | | a,g | road,right,right | depart,turn right,arrive | ,left:false straight;right:true, |
@partition-lanes @previous-lanes @partition-lanes @previous-lanes
@ -492,7 +492,7 @@ Feature: Turn Lane Guidance
When I route I should get When I route I should get
| waypoints | route | turns | lanes | | waypoints | route | turns | lanes |
| a,g | road,cross,cross | depart,turn left,arrive | ,left:true left:true straight:false straight:false, | | a,g | road,cross,cross | depart,turn left,arrive | ,left:true left:true straight:false straight:false right:false, |
| a,e | road,road | depart,arrive | , | | a,e | road,road | depart,arrive | , |
#NEEDS TO BE INVESTIGATED. Turn restriction shouldn't be here. See #2867 #NEEDS TO BE INVESTIGATED. Turn restriction shouldn't be here. See #2867

View File

@ -20,7 +20,8 @@ namespace osrm
namespace engine namespace engine
{ {
inline std::pair<bool, bool> boolPairAnd(const std::pair<bool, bool> &A, const std::pair<bool, bool> &B) inline std::pair<bool, bool> boolPairAnd(const std::pair<bool, bool> &A,
const std::pair<bool, bool> &B)
{ {
return std::make_pair(A.first && B.first, A.second && B.second); return std::make_pair(A.first && B.first, A.second && B.second);
} }

View File

@ -83,8 +83,7 @@ class EdgeBasedGraphFactory
EdgeBasedGraphFactory(const EdgeBasedGraphFactory &) = delete; EdgeBasedGraphFactory(const EdgeBasedGraphFactory &) = delete;
EdgeBasedGraphFactory &operator=(const EdgeBasedGraphFactory &) = delete; EdgeBasedGraphFactory &operator=(const EdgeBasedGraphFactory &) = delete;
explicit EdgeBasedGraphFactory( explicit EdgeBasedGraphFactory(std::shared_ptr<util::NodeBasedDynamicGraph> node_based_graph,
std::shared_ptr<util::NodeBasedDynamicGraph> node_based_graph,
const CompressedEdgeContainer &compressed_edge_container, const CompressedEdgeContainer &compressed_edge_container,
const std::unordered_set<NodeID> &barrier_nodes, const std::unordered_set<NodeID> &barrier_nodes,
const std::unordered_set<NodeID> &traffic_lights, const std::unordered_set<NodeID> &traffic_lights,

View File

@ -40,12 +40,11 @@ class ExtractorCallbacks
using MapKey = std::pair<std::string, std::string>; using MapKey = std::pair<std::string, std::string>;
using MapVal = unsigned; using MapVal = unsigned;
std::unordered_map<MapKey, MapVal, boost::hash<MapKey>> string_map; std::unordered_map<MapKey, MapVal, boost::hash<MapKey>> string_map;
guidance::LaneDescriptionMap &lane_description_map; guidance::LaneDescriptionMap lane_description_map;
ExtractionContainers &external_memory; ExtractionContainers &external_memory;
public: public:
explicit ExtractorCallbacks(ExtractionContainers &extraction_containers, explicit ExtractorCallbacks(ExtractionContainers &extraction_containers);
guidance::LaneDescriptionMap &lane_description_map);
ExtractorCallbacks(const ExtractorCallbacks &) = delete; ExtractorCallbacks(const ExtractorCallbacks &) = delete;
ExtractorCallbacks &operator=(const ExtractorCallbacks &) = delete; ExtractorCallbacks &operator=(const ExtractorCallbacks &) = delete;
@ -58,6 +57,9 @@ class ExtractorCallbacks
// warning: caller needs to take care of synchronization! // warning: caller needs to take care of synchronization!
void ProcessWay(const osmium::Way &current_way, const ExtractionWay &result_way); void ProcessWay(const osmium::Way &current_way, const ExtractionWay &result_way);
// destroys the internal laneDescriptionMap
guidance::LaneDescriptionMap &&moveOutLaneDescriptionMap();
}; };
} }
} }

View File

@ -40,10 +40,6 @@ LaneDataVector::iterator findTag(const TurnLaneType::Mask tag, LaneDataVector &d
// Returns true if any of the queried tags is contained // Returns true if any of the queried tags is contained
bool hasTag(const TurnLaneType::Mask tag, const LaneDataVector &data); bool hasTag(const TurnLaneType::Mask tag, const LaneDataVector &data);
// Check if a set of lanes is a subset of a different set of lanes
bool isSubsetOf(const LaneDataVector &subset_candidate, const LaneDataVector &superset_candidate);
} // namespace lane_data_generation } // namespace lane_data_generation
} // namespace guidance } // namespace guidance

View File

@ -14,6 +14,8 @@
#include "util/node_based_graph.hpp" #include "util/node_based_graph.hpp"
#include "util/typedefs.hpp" #include "util/typedefs.hpp"
#include <atomic>
#include <cstddef>
#include <cstdint> #include <cstdint>
#include <map> #include <map>
#include <string> #include <string>
@ -31,9 +33,10 @@ namespace guidance
// assigns appropriate turn tupels to the different turns. // assigns appropriate turn tupels to the different turns.
namespace lanes namespace lanes
{ {
class TurnLaneHandler
namespace
{ {
typedef enum TurnLaneScenario { typedef enum TurnLaneScenario {
SIMPLE, // a straightforward assignment SIMPLE, // a straightforward assignment
PARTITION_LOCAL, // an assignment that requires partitioning, using local turns PARTITION_LOCAL, // an assignment that requires partitioning, using local turns
SIMPLE_PREVIOUS, // an assignemtnn using the turns specified at the previous road (e.g. SIMPLE_PREVIOUS, // an assignemtnn using the turns specified at the previous road (e.g.
@ -48,10 +51,9 @@ class TurnLaneHandler
INVALID, // some error might have occurred INVALID, // some error might have occurred
UNKNOWN, // UNKNOWN describes all cases that we are currently not able to handle UNKNOWN, // UNKNOWN describes all cases that we are currently not able to handle
NUM_SCENARIOS NUM_SCENARIOS
} TurnLaneScenario; } TurnLaneScenario;
const constexpr static char *scenario_names[TurnLaneScenario::NUM_SCENARIOS] = { const constexpr char *scenario_names[] = {"Simple",
"Simple",
"Partition Local", "Partition Local",
"Simple Previous", "Simple Previous",
"Partition Previous", "Partition Previous",
@ -60,7 +62,10 @@ class TurnLaneHandler
"None", "None",
"Invalid", "Invalid",
"Unknown"}; "Unknown"};
} // namespace
class TurnLaneHandler
{
public: public:
typedef std::vector<TurnLaneData> LaneDataVector; typedef std::vector<TurnLaneData> LaneDataVector;
@ -78,8 +83,8 @@ class TurnLaneHandler
Intersection assignTurnLanes(const NodeID at, const EdgeID via_edge, Intersection intersection); Intersection assignTurnLanes(const NodeID at, const EdgeID via_edge, Intersection intersection);
private: private:
unsigned *count_handled; mutable std::atomic<std::size_t> count_handled;
unsigned *count_called; mutable std::atomic<std::size_t> count_called;
// we need to be able to look at previous intersections to, in some cases, find the correct turn // we need to be able to look at previous intersections to, in some cases, find the correct turn
// lanes for a turn // lanes for a turn
const util::NodeBasedDynamicGraph &node_based_graph; const util::NodeBasedDynamicGraph &node_based_graph;
@ -133,6 +138,9 @@ class TurnLaneHandler
LaneDataVector &lane_data) const; LaneDataVector &lane_data) const;
}; };
static_assert(sizeof(scenario_names) / sizeof(*scenario_names) == TurnLaneScenario::NUM_SCENARIOS,
"Number of scenarios needs to match the number of scenario names.");
} // namespace lanes } // namespace lanes
} // namespace guidance } // namespace guidance
} // namespace extractor } // namespace extractor

View File

@ -32,10 +32,10 @@ typename Intersection::const_iterator findBestMatch(const TurnLaneType::Mask tag
const Intersection &intersection); const Intersection &intersection);
// the quality of a matching to decide between first/second possibility on segregated intersections // the quality of a matching to decide between first/second possibility on segregated intersections
double getMatchingQuality( const TurnLaneType::Mask tag, const ConnectedRoad &road ); double getMatchingQuality(const TurnLaneType::Mask tag, const ConnectedRoad &road);
typename Intersection::const_iterator typename Intersection::const_iterator findBestMatchForReverse(const TurnLaneType::Mask leftmost_tag,
findBestMatchForReverse(const TurnLaneType::Mask leftmost_tag, const Intersection &intersection); const Intersection &intersection);
// a match is trivial if all turns can be associated with their best match in a valid way and the // a match is trivial if all turns can be associated with their best match in a valid way and the
// matches occur in order // matches occur in order

View File

@ -9,7 +9,7 @@
#include <vector> #include <vector>
#include <boost/assert.hpp> #include <boost/assert.hpp>
#include <boost/functional/hash_fwd.hpp> #include <boost/functional/hash.hpp>
#include "util/json_container.hpp" #include "util/json_container.hpp"
#include "util/simple_logger.hpp" #include "util/simple_logger.hpp"
@ -90,8 +90,7 @@ struct TurnLaneDescription_hash
std::size_t operator()(const TurnLaneDescription &lane_description) const std::size_t operator()(const TurnLaneDescription &lane_description) const
{ {
std::size_t seed = 0; std::size_t seed = 0;
for (auto val : lane_description) boost::hash_range(seed, lane_description.begin(), lane_description.end());
boost::hash_combine(seed, val);
return seed; return seed;
} }
}; };

View File

@ -1,15 +1,13 @@
#ifndef OSRM_ATTRIBUTES_HPP_ #ifndef OSRM_ATTRIBUTES_HPP_
#define OSRM_ATTRIBUTES_HPP_ #define OSRM_ATTRIBUTES_HPP_
// OSRM_ATTR_WARN_UNUSED - caller has to use function's return value // OSRM_ATTR_WARN_UNUSED - caller has to use function's return value
// https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html // https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html
#if defined(__GNUC__) && (__GNUC__ >= 4) #if defined(__GNUC__) && (__GNUC__ >= 4)
#define OSRM_ATTR_WARN_UNUSED __attribute__ ((warn_unused_result)) #define OSRM_ATTR_WARN_UNUSED __attribute__((warn_unused_result))
#else #else
#define OSRM_ATTR_WARN_UNUSED #define OSRM_ATTR_WARN_UNUSED
#endif #endif
#endif #endif

View File

@ -30,8 +30,7 @@ inline void print(const engine::guidance::RouteStep &step)
for (const auto &intersection : step.intersections) for (const auto &intersection : step.intersections)
{ {
std::cout << "(Lanes: " << static_cast<int>(intersection.lanes.lanes_in_turn) << " " std::cout << "(Lanes: " << static_cast<int>(intersection.lanes.lanes_in_turn) << " "
<< static_cast<int>(intersection.lanes.first_lane_from_the_right) << static_cast<int>(intersection.lanes.first_lane_from_the_right) << " bearings:";
<< " bearings:";
for (auto bearing : intersection.bearings) for (auto bearing : intersection.bearings)
std::cout << " " << bearing; std::cout << " " << bearing;
std::cout << ", entry: "; std::cout << ", entry: ";

View File

@ -251,7 +251,8 @@ parse_segment_lookup_from_csv_files(const std::vector<std::string> &segment_spee
const auto last = end(line); const auto last = end(line);
// The ulong_long -> uint64_t will likely break on 32bit platforms // The ulong_long -> uint64_t will likely break on 32bit platforms
const auto ok = parse(it, const auto ok =
parse(it,
last, // last, //
(ulong_long >> ',' >> ulong_long >> ',' >> uint_ >> *(',' >> *char_)), // (ulong_long >> ',' >> ulong_long >> ',' >> uint_ >> *(',' >> *char_)), //
from_node_id, from_node_id,
@ -334,10 +335,10 @@ parse_turn_penalty_lookup_from_csv_files(const std::vector<std::string> &turn_pe
const auto last = end(line); const auto last = end(line);
// The ulong_long -> uint64_t will likely break on 32bit platforms // The ulong_long -> uint64_t will likely break on 32bit platforms
const auto ok = const auto ok = parse(it,
parse(it,
last, // last, //
(ulong_long >> ',' >> ulong_long >> ',' >> ulong_long >> ',' >> double_ >> *(',' >> *char_)), // (ulong_long >> ',' >> ulong_long >> ',' >> ulong_long >> ',' >>
double_ >> *(',' >> *char_)), //
from_node_id, from_node_id,
via_node_id, via_node_id,
to_node_id, to_node_id,
@ -807,7 +808,8 @@ EdgeID Contractor::LoadEdgeExpandedGraph(
// We found a zero-speed edge, so we'll skip this whole edge-based-edge which // We found a zero-speed edge, so we'll skip this whole edge-based-edge which
// effectively removes it from the routing network. // effectively removes it from the routing network.
if (skip_this_edge) { if (skip_this_edge)
{
penaltyblock++; penaltyblock++;
continue; continue;
} }

View File

@ -68,7 +68,7 @@ inline bool hasValidLanes(const guidance::Intersection &intersection)
std::string instructionTypeToString(const TurnType::Enum type) std::string instructionTypeToString(const TurnType::Enum type)
{ {
static_assert(sizeof(turn_type_names)/sizeof(turn_type_names[0]) >= TurnType::MaxTurnType, static_assert(sizeof(turn_type_names) / sizeof(turn_type_names[0]) >= TurnType::MaxTurnType,
"Some turn types has not string representation."); "Some turn types has not string representation.");
return turn_type_names[static_cast<std::size_t>(type)]; return turn_type_names[static_cast<std::size_t>(type)];
} }
@ -99,14 +99,16 @@ util::json::Array lanesFromIntersection(const guidance::Intersection &intersecti
std::string instructionModifierToString(const DirectionModifier::Enum modifier) std::string instructionModifierToString(const DirectionModifier::Enum modifier)
{ {
static_assert(sizeof(modifier_names)/sizeof(modifier_names[0]) >= DirectionModifier::MaxDirectionModifier, static_assert(sizeof(modifier_names) / sizeof(modifier_names[0]) >=
DirectionModifier::MaxDirectionModifier,
"Some direction modifiers has not string representation."); "Some direction modifiers has not string representation.");
return modifier_names[static_cast<std::size_t>(modifier)]; return modifier_names[static_cast<std::size_t>(modifier)];
} }
std::string waypointTypeToString(const guidance::WaypointType waypoint_type) std::string waypointTypeToString(const guidance::WaypointType waypoint_type)
{ {
static_assert(sizeof(waypoint_type_names)/sizeof(waypoint_type_names[0]) >= static_cast<size_t>(guidance::WaypointType::MaxWaypointType), static_assert(sizeof(waypoint_type_names) / sizeof(waypoint_type_names[0]) >=
static_cast<size_t>(guidance::WaypointType::MaxWaypointType),
"Some waypoint types has not string representation."); "Some waypoint types has not string representation.");
return waypoint_type_names[static_cast<std::size_t>(waypoint_type)]; return waypoint_type_names[static_cast<std::size_t>(waypoint_type)];
} }

View File

@ -3,8 +3,8 @@
#include "util/guidance/toolkit.hpp" #include "util/guidance/toolkit.hpp"
#include "extractor/guidance/turn_instruction.hpp" #include "extractor/guidance/turn_instruction.hpp"
#include "engine/guidance/toolkit.hpp"
#include "engine/guidance/post_processing.hpp" #include "engine/guidance/post_processing.hpp"
#include "engine/guidance/toolkit.hpp"
#include <iterator> #include <iterator>
#include <unordered_set> #include <unordered_set>
@ -80,7 +80,8 @@ std::vector<RouteStep> anticipateLaneChange(std::vector<RouteStep> steps,
// where lanes in the turn fan in but for example the overall lanes at that location // where lanes in the turn fan in but for example the overall lanes at that location
// fan out, we would have to know the asymmetric mapping of lanes. This is currently // fan out, we would have to know the asymmetric mapping of lanes. This is currently
// not possible at the moment. In the following we implement a heuristic instead. // not possible at the moment. In the following we implement a heuristic instead.
const LaneID current_num_all_lanes = current.intersections.front().lane_description.size(); const LaneID current_num_all_lanes =
current.intersections.front().lane_description.size();
const LaneID current_num_lanes_right_of_turn = current_lanes.first_lane_from_the_right; const LaneID current_num_lanes_right_of_turn = current_lanes.first_lane_from_the_right;
const LaneID current_num_lanes_left_of_turn = const LaneID current_num_lanes_left_of_turn =
current_num_all_lanes - current_num_all_lanes -

View File

@ -1,5 +1,5 @@
#include "extractor/guidance/turn_instruction.hpp"
#include "engine/guidance/post_processing.hpp" #include "engine/guidance/post_processing.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include "engine/guidance/assemble_steps.hpp" #include "engine/guidance/assemble_steps.hpp"
#include "engine/guidance/lane_processing.hpp" #include "engine/guidance/lane_processing.hpp"
@ -408,9 +408,12 @@ void collapseTurnAt(std::vector<RouteStep> &steps,
if (bearingsAreReversed( if (bearingsAreReversed(
util::bearing::reverseBearing(getBearing(true, one_back_step)), util::bearing::reverseBearing(getBearing(true, one_back_step)),
getBearing(false, current_step))) getBearing(false, current_step)))
{
steps[one_back_index].maneuver.instruction.type = TurnType::Continue;
steps[one_back_index].maneuver.instruction.direction_modifier = steps[one_back_index].maneuver.instruction.direction_modifier =
DirectionModifier::UTurn; DirectionModifier::UTurn;
} }
}
else if (TurnType::Merge == one_back_step.maneuver.instruction.type && else if (TurnType::Merge == one_back_step.maneuver.instruction.type &&
current_step.maneuver.instruction.type != current_step.maneuver.instruction.type !=
TurnType::Suppressed) // This suppressed is a check for highways. We might TurnType::Suppressed) // This suppressed is a check for highways. We might
@ -550,8 +553,6 @@ RouteStep elongate(RouteStep step, const RouteStep &by_step)
return step; return step;
} }
// Post processing can invalidate some instructions. For example StayOnRoundabout // Post processing can invalidate some instructions. For example StayOnRoundabout
// is turned into exit counts. These instructions are removed by the following function // is turned into exit counts. These instructions are removed by the following function
@ -764,22 +765,23 @@ std::vector<RouteStep> collapseTurns(std::vector<RouteStep> steps)
else else
{ {
// Handle possible u-turns between highways that look like slip-roads // Handle possible u-turns between highways that look like slip-roads
if (steps[getPreviousIndex(one_back_index)].name_id == steps[step_index].name_id &&
steps[step_index].name_id != EMPTY_NAMEID)
{
steps[one_back_index].maneuver.instruction.type = TurnType::Continue;
}
else
{
steps[one_back_index].maneuver.instruction.type = TurnType::Turn;
}
if (compatible(one_back_step, current_step)) if (compatible(one_back_step, current_step))
{ {
// Turn Types in the response depend on whether we find the same road name
// (sliproad indcating a u-turn) or if we are turning onto a different road, in
// which case we use a turn.
if (steps[getPreviousIndex(one_back_index)].name_id ==
steps[step_index].name_id &&
steps[step_index].name_id != EMPTY_NAMEID)
steps[one_back_index].maneuver.instruction.type = TurnType::Continue;
else
steps[one_back_index].maneuver.instruction.type = TurnType::Turn;
steps[one_back_index] = steps[one_back_index] =
elongate(std::move(steps[one_back_index]), steps[step_index]); elongate(std::move(steps[one_back_index]), steps[step_index]);
steps[one_back_index].name_id = steps[step_index].name_id; steps[one_back_index].name_id = steps[step_index].name_id;
steps[one_back_index].name = steps[step_index].name; steps[one_back_index].name = steps[step_index].name;
steps[one_back_index].maneuver.instruction.type = TurnType::Turn;
// the turn lanes for this turn are on the sliproad itself, so we have to // the turn lanes for this turn are on the sliproad itself, so we have to
// remember them // remember them
steps[one_back_index].intersections.front().lanes = steps[one_back_index].intersections.front().lanes =
@ -1202,7 +1204,8 @@ std::vector<RouteStep> buildIntersections(std::vector<RouteStep> steps)
{ {
// count intersections. We cannot use exit, since intersections can follow directly // count intersections. We cannot use exit, since intersections can follow directly
// after a roundabout // after a roundabout
steps[last_valid_instruction] = elongate(std::move(steps[last_valid_instruction]), step); steps[last_valid_instruction] =
elongate(std::move(steps[last_valid_instruction]), step);
step.maneuver.instruction = TurnInstruction::NO_TURN(); step.maneuver.instruction = TurnInstruction::NO_TURN();
} }
else if (!isSilent(instruction)) else if (!isSilent(instruction))

View File

@ -1,5 +1,5 @@
#include "extractor/edge_based_edge.hpp"
#include "extractor/edge_based_graph_factory.hpp" #include "extractor/edge_based_graph_factory.hpp"
#include "extractor/edge_based_edge.hpp"
#include "util/coordinate.hpp" #include "util/coordinate.hpp"
#include "util/coordinate_calculation.hpp" #include "util/coordinate_calculation.hpp"
#include "util/exception.hpp" #include "util/exception.hpp"

View File

@ -47,6 +47,7 @@
#include <iostream> #include <iostream>
#include <numeric> //partial_sum #include <numeric> //partial_sum
#include <thread> #include <thread>
#include <tuple>
#include <type_traits> #include <type_traits>
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
@ -56,6 +57,36 @@ namespace osrm
namespace extractor namespace extractor
{ {
namespace
{
std::tuple<std::vector<std::uint32_t>, std::vector<guidance::TurnLaneType::Mask>>
transformTurnLaneMapIntoArrays(const guidance::LaneDescriptionMap &turn_lane_map)
{
// could use some additional capacity? To avoid a copy during processing, though small data so
// probably not that important.
//
// From the map, we construct an adjacency array that allows access from all IDs to the list of
// associated Turn Lane Masks.
//
// turn lane offsets points into the locations of the turn_lane_masks array. We use a standard
// adjacency array like structure to store the turn lane masks.
std::vector<std::uint32_t> turn_lane_offsets(turn_lane_map.size() + 2); // empty ID + sentinel
for (auto entry = turn_lane_map.begin(); entry != turn_lane_map.end(); ++entry)
turn_lane_offsets[entry->second + 1] = entry->first.size();
// inplace prefix sum
std::partial_sum(turn_lane_offsets.begin(), turn_lane_offsets.end(), turn_lane_offsets.begin());
// allocate the current masks
std::vector<guidance::TurnLaneType::Mask> turn_lane_masks(turn_lane_offsets.back());
for (auto entry = turn_lane_map.begin(); entry != turn_lane_map.end(); ++entry)
std::copy(entry->first.begin(),
entry->first.end(),
turn_lane_masks.begin() + turn_lane_offsets[entry->second]);
return std::make_tuple(std::move(turn_lane_offsets), std::move(turn_lane_masks));
}
} // namespace
/** /**
* TODO: Refactor this function into smaller functions for better readability. * TODO: Refactor this function into smaller functions for better readability.
* *
@ -94,8 +125,7 @@ int Extractor::run(ScriptingEnvironment &scripting_environment)
util::SimpleLogger().Write() << "Threads: " << number_of_threads; util::SimpleLogger().Write() << "Threads: " << number_of_threads;
ExtractionContainers extraction_containers; ExtractionContainers extraction_containers;
auto extractor_callbacks = auto extractor_callbacks = util::make_unique<ExtractorCallbacks>(extraction_containers);
util::make_unique<ExtractorCallbacks>(extraction_containers, turn_lane_map);
const osmium::io::File input_file(config.input_path.string()); const osmium::io::File input_file(config.input_path.string());
osmium::io::Reader reader(input_file); osmium::io::Reader reader(input_file);
@ -185,6 +215,9 @@ int Extractor::run(ScriptingEnvironment &scripting_environment)
<< number_of_ways << " ways, and " << number_of_relations << number_of_ways << " ways, and " << number_of_relations
<< " relations"; << " relations";
// take control over the turn lane map
turn_lane_map = extractor_callbacks->moveOutLaneDescriptionMap();
extractor_callbacks.reset(); extractor_callbacks.reset();
if (extraction_containers.all_edges_list.empty()) if (extraction_containers.all_edges_list.empty())
@ -447,19 +480,9 @@ Extractor::BuildEdgeExpandedGraph(ScriptingEnvironment &scripting_environment,
// could use some additional capacity? To avoid a copy during processing, though small data so // could use some additional capacity? To avoid a copy during processing, though small data so
// probably not that important. // probably not that important.
std::vector<std::uint32_t> turn_lane_offsets(turn_lane_map.size() + 2); // empty ID + sentinel std::vector<std::uint32_t> turn_lane_offsets;
for (auto entry = turn_lane_map.begin(); entry != turn_lane_map.end(); ++entry) std::vector<guidance::TurnLaneType::Mask> turn_lane_masks;
turn_lane_offsets[entry->second + 1] = entry->first.size(); std::tie(turn_lane_offsets, turn_lane_masks) = transformTurnLaneMapIntoArrays(turn_lane_map);
// inplace prefix sum
std::partial_sum(turn_lane_offsets.begin(), turn_lane_offsets.end(), turn_lane_offsets.begin());
// allocate the current masks
std::vector<guidance::TurnLaneType::Mask> turn_lane_masks(turn_lane_offsets.back());
for (auto entry = turn_lane_map.begin(); entry != turn_lane_map.end(); ++entry)
std::copy(entry->first.begin(),
entry->first.end(),
turn_lane_masks.begin() + turn_lane_offsets[entry->second]);
EdgeBasedGraphFactory edge_based_graph_factory( EdgeBasedGraphFactory edge_based_graph_factory(
node_based_graph, node_based_graph,
@ -649,24 +672,16 @@ void Extractor::WriteIntersectionClassificationData(
void Extractor::WriteTurnLaneData(const std::string &turn_lane_file) const void Extractor::WriteTurnLaneData(const std::string &turn_lane_file) const
{ {
// Write the turn lane data to file // Write the turn lane data to file
std::vector<std::uint32_t> turn_lane_offsets(turn_lane_map.size() + 2); // empty ID + sentinel std::vector<std::uint32_t> turn_lane_offsets;
for (auto entry = turn_lane_map.begin(); entry != turn_lane_map.end(); ++entry) std::vector<guidance::TurnLaneType::Mask> turn_lane_masks;
turn_lane_offsets[entry->second + 1] = entry->first.size(); std::tie(turn_lane_offsets, turn_lane_masks) = transformTurnLaneMapIntoArrays(turn_lane_map);
// inplace prefix sum
std::partial_sum(turn_lane_offsets.begin(), turn_lane_offsets.end(), turn_lane_offsets.begin());
// allocate the current masks
std::vector<guidance::TurnLaneType::Mask> turn_lane_masks(turn_lane_offsets.back());
for (auto entry = turn_lane_map.begin(); entry != turn_lane_map.end(); ++entry)
std::copy(entry->first.begin(),
entry->first.end(),
turn_lane_masks.begin() + turn_lane_offsets[entry->second]);
util::SimpleLogger().Write() << "Writing turn lane masks..."; util::SimpleLogger().Write() << "Writing turn lane masks...";
TIMER_START(turn_lane_timer); TIMER_START(turn_lane_timer);
std::ofstream ofs(turn_lane_file, std::ios::binary); std::ofstream ofs(turn_lane_file, std::ios::binary);
if (!ofs)
throw osrm::util::exception("Failed to open " + turn_lane_file + " for writing.");
if (!util::serializeVector(ofs, turn_lane_offsets)) if (!util::serializeVector(ofs, turn_lane_offsets))
{ {

View File

@ -31,15 +31,13 @@ namespace extractor
using TurnLaneDescription = guidance::TurnLaneDescription; using TurnLaneDescription = guidance::TurnLaneDescription;
namespace TurnLaneType = guidance::TurnLaneType; namespace TurnLaneType = guidance::TurnLaneType;
ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers &extraction_containers, ExtractorCallbacks::ExtractorCallbacks(ExtractionContainers &extraction_containers)
guidance::LaneDescriptionMap &lane_description_map) : external_memory(extraction_containers)
: lane_description_map(lane_description_map), external_memory(extraction_containers)
{ {
// we reserved 0, 1, 2 for the empty case // we reserved 0, 1, 2 for the empty case
string_map[MapKey("", "")] = 0; string_map[MapKey("", "")] = 0;
// The map should be empty before we start initializing it // The map should be empty before we start initializing it
BOOST_ASSERT(lane_description_map.empty());
lane_description_map[TurnLaneDescription()] = 0; lane_description_map[TurnLaneDescription()] = 0;
} }
@ -395,5 +393,10 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
OSMNodeID{static_cast<std::uint64_t>(input_way.nodes()[0].ref())}}); OSMNodeID{static_cast<std::uint64_t>(input_way.nodes()[0].ref())}});
} }
} }
guidance::LaneDescriptionMap &&ExtractorCallbacks::moveOutLaneDescriptionMap()
{
return std::move(lane_description_map);
} }
} } // namespace extractor
} // namespace osrm

View File

@ -1,5 +1,5 @@
#include "extractor/guidance/constants.hpp"
#include "extractor/guidance/intersection_generator.hpp" #include "extractor/guidance/intersection_generator.hpp"
#include "extractor/guidance/constants.hpp"
#include "extractor/guidance/toolkit.hpp" #include "extractor/guidance/toolkit.hpp"
#include <algorithm> #include <algorithm>

View File

@ -1,5 +1,5 @@
#include "extractor/guidance/constants.hpp"
#include "extractor/guidance/turn_discovery.hpp" #include "extractor/guidance/turn_discovery.hpp"
#include "extractor/guidance/constants.hpp"
namespace osrm namespace osrm
{ {

View File

@ -283,27 +283,18 @@ LaneDataVector handleNoneValueAtSimpleTurn(LaneDataVector lane_data,
// we have to reduce it, assigning it to neighboring turns // we have to reduce it, assigning it to neighboring turns
else if (connection_count < lane_data.size()) else if (connection_count < lane_data.size())
{ {
if( connection_count+1 < lane_data.size() ){
std::cout << "[error] failed assignment" << std::endl;
util::guidance::print(lane_data);
std::cout << "Intersection:\n";
for( auto road : intersection )
std::cout << "\t" << toString(road) << std::endl;
}
// a pgerequisite 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 // an additional line at the side is only reasonable if it is targeting public
// service vehicles. Otherwise, we should not have it // service vehicles. Otherwise, we should not have it
// if (connection_count + 1 == lane_data.size())
// TODO(mokob): #2730 have a look please
// BOOST_ASSERT(connection_count + 1 == lane_data.size());
//
if (connection_count + 1 != lane_data.size())
{ {
// skip broken intersections lane_data = mergeNoneTag(none_index, std::move(lane_data));
} }
else else
{ {
lane_data = mergeNoneTag(none_index, std::move(lane_data)); // This represents a currently unhandled case. It should not even get here, but to be
// sure we return nevertheless.
return lane_data;
} }
} }
// we have to rename and possibly augment existing ones. The pure count remains the // we have to rename and possibly augment existing ones. The pure count remains the

View File

@ -154,27 +154,6 @@ bool hasTag(const TurnLaneType::Mask tag, const LaneDataVector &data)
return findTag(tag, data) != data.cend(); return findTag(tag, data) != data.cend();
} }
bool isSubsetOf(const LaneDataVector &subset_candidate, const LaneDataVector &superset_candidate)
{
auto location = superset_candidate.begin();
for (const auto entry : subset_candidate)
{
location = std::find_if(
location, superset_candidate.end(), [entry](const TurnLaneData &lane_data) {
return lane_data.tag == entry.tag;
});
if (location == superset_candidate.end())
return false;
// compare the number of lanes TODO this might have be to be revisited for situations where
// a sliproad widens into multiple lanes
if ((location->to - location->from) != (entry.to - entry.from))
return false;
}
return true;
}
} // namespace lanes } // namespace lanes
} // namespace guidance } // namespace guidance
} // namespace extractor } // namespace extractor

View File

@ -1,9 +1,7 @@
#include "util/debug.hpp" #include "extractor/guidance/turn_lane_handler.hpp"
#include "extractor/guidance/constants.hpp" #include "extractor/guidance/constants.hpp"
#include "extractor/guidance/turn_discovery.hpp" #include "extractor/guidance/turn_discovery.hpp"
#include "extractor/guidance/turn_lane_augmentation.hpp" #include "extractor/guidance/turn_lane_augmentation.hpp"
#include "extractor/guidance/turn_lane_handler.hpp"
#include "extractor/guidance/turn_lane_matcher.hpp" #include "extractor/guidance/turn_lane_matcher.hpp"
#include "util/simple_logger.hpp" #include "util/simple_logger.hpp"
#include "util/typedefs.hpp" #include "util/typedefs.hpp"
@ -33,8 +31,6 @@ std::size_t getNumberOfTurns(const Intersection &intersection)
} }
} // namespace } // namespace
const constexpr char *TurnLaneHandler::scenario_names[TurnLaneScenario::NUM_SCENARIOS];
TurnLaneHandler::TurnLaneHandler(const util::NodeBasedDynamicGraph &node_based_graph, TurnLaneHandler::TurnLaneHandler(const util::NodeBasedDynamicGraph &node_based_graph,
std::vector<std::uint32_t> &turn_lane_offsets, std::vector<std::uint32_t> &turn_lane_offsets,
std::vector<TurnLaneType::Mask> &turn_lane_masks, std::vector<TurnLaneType::Mask> &turn_lane_masks,
@ -46,18 +42,12 @@ TurnLaneHandler::TurnLaneHandler(const util::NodeBasedDynamicGraph &node_based_g
turn_lane_masks(turn_lane_masks), lane_description_map(lane_description_map), turn_lane_masks(turn_lane_masks), lane_description_map(lane_description_map),
node_info_list(node_info_list), turn_analysis(turn_analysis), id_map(id_map) node_info_list(node_info_list), turn_analysis(turn_analysis), id_map(id_map)
{ {
count_handled = new unsigned;
count_called = new unsigned;
*count_handled = *count_called = 0;
} }
TurnLaneHandler::~TurnLaneHandler() TurnLaneHandler::~TurnLaneHandler()
{ {
std::cout << "Handled: " << *count_handled << " of " << *count_called std::cout << "Handled: " << count_handled << " of " << count_called
<< " lanes: " << (double)(*count_handled * 100) / (*count_called) << " %." << " lanes: " << (double)(count_handled * 100) / (count_called) << " %." << std::endl;
<< std::endl;
delete count_called;
delete count_handled;
} }
/* /*
@ -107,8 +97,8 @@ TurnLaneHandler::assignTurnLanes(const NodeID at, const EdgeID via_edge, Interse
previous_lane_data, previous_lane_data,
previous_description_id); previous_description_id);
if (scenario != TurnLaneHandler::NONE) if (scenario != TurnLaneScenario::NONE)
(*count_called)++; count_called++;
switch (scenario) switch (scenario)
{ {
@ -140,30 +130,12 @@ TurnLaneHandler::assignTurnLanes(const NodeID at, const EdgeID via_edge, Interse
// case TurnLaneScenario::UNKNOWN: // case TurnLaneScenario::UNKNOWN:
// case TurnLaneScenario::NONE: // case TurnLaneScenario::NONE:
// case TurnLaneScenario::INVALID: // case TurnLaneScenario::INVALID:
{
/*
static int print_count = 0;
if (TurnLaneScenario::NONE != scenario && print_count++ < 10)
{
std::cout << "[Unhandled] " << (int)lane_description_id << " -- "
<< (int)previous_description_id << "\n"
<< std::endl;
util::guidance::printTurnAssignmentData(
at, lane_data, intersection, node_info_list);
if (previous_node != SPECIAL_NODEID)
util::guidance::printTurnAssignmentData(
previous_node, previous_lane_data, previous_intersection, node_info_list);
}
*/
}
return intersection; return intersection;
} }
} }
// Find out which scenario we have to handle // Find out which scenario we have to handle
TurnLaneHandler::TurnLaneScenario TurnLaneScenario TurnLaneHandler::deduceScenario(const NodeID at,
TurnLaneHandler::deduceScenario(const NodeID at,
const EdgeID via_edge, const EdgeID via_edge,
const Intersection &intersection, const Intersection &intersection,
// Output Variables // Output Variables
@ -177,7 +149,7 @@ TurnLaneHandler::deduceScenario(const NodeID at,
{ {
// if only a uturn exists, there is nothing we can do // if only a uturn exists, there is nothing we can do
if (intersection.size() == 1) if (intersection.size() == 1)
return TurnLaneHandler::NONE; return TurnLaneScenario::NONE;
extractLaneData(via_edge, lane_description_id, lane_data); extractLaneData(via_edge, lane_description_id, lane_data);
@ -199,7 +171,7 @@ TurnLaneHandler::deduceScenario(const NodeID at,
angularDeviation(intersection[1].turn.angle, STRAIGHT_ANGLE) < FUZZY_ANGLE_DIFFERENCE)); angularDeviation(intersection[1].turn.angle, STRAIGHT_ANGLE) < FUZZY_ANGLE_DIFFERENCE));
if (is_going_straight_and_turns_continue) if (is_going_straight_and_turns_continue)
return TurnLaneHandler::NONE; return TurnLaneScenario::NONE;
// if we see an invalid conversion, we stop immediately // if we see an invalid conversion, we stop immediately
if (lane_description_id != INVALID_LANE_DESCRIPTIONID && lane_data.empty()) if (lane_description_id != INVALID_LANE_DESCRIPTIONID && lane_data.empty())
@ -694,7 +666,7 @@ Intersection TurnLaneHandler::simpleMatchTuplesToTurns(Intersection intersection
!hasTag(TurnLaneType::none | TurnLaneType::merge_to_left | TurnLaneType::merge_to_right, !hasTag(TurnLaneType::none | TurnLaneType::merge_to_left | TurnLaneType::merge_to_right,
lane_data)); lane_data));
(*count_handled)++; count_handled++;
return triviallyMatchLanesToTurns( return triviallyMatchLanesToTurns(
std::move(intersection), lane_data, node_based_graph, lane_description_id, id_map); std::move(intersection), lane_data, node_based_graph, lane_description_id, id_map);

View File

@ -1,5 +1,5 @@
#include "extractor/guidance/toolkit.hpp"
#include "extractor/guidance/turn_lane_matcher.hpp" #include "extractor/guidance/turn_lane_matcher.hpp"
#include "extractor/guidance/toolkit.hpp"
#include "util/guidance/toolkit.hpp" #include "util/guidance/toolkit.hpp"
#include <boost/assert.hpp> #include <boost/assert.hpp>
@ -102,11 +102,11 @@ bool isValidMatch(const TurnLaneType::Mask tag, const TurnInstruction instructio
return false; return false;
} }
double getMatchingQuality( const TurnLaneType::Mask tag, const ConnectedRoad &road) double getMatchingQuality(const TurnLaneType::Mask tag, const ConnectedRoad &road)
{ {
const constexpr double idealized_turn_angles[] = {0, 35, 90, 135, 180, 225, 270, 315}; const constexpr double idealized_turn_angles[] = {0, 35, 90, 135, 180, 225, 270, 315};
const auto idealized_angle = idealized_turn_angles[getMatchingModifier(tag)]; const auto idealized_angle = idealized_turn_angles[getMatchingModifier(tag)];
return angularDeviation(idealized_angle,road.turn.angle); return angularDeviation(idealized_angle, road.turn.angle);
} }
// Every tag is somewhat idealized in form of the expected angle. A through lane should go straight // Every tag is somewhat idealized in form of the expected angle. A through lane should go straight
@ -116,12 +116,12 @@ double getMatchingQuality( const TurnLaneType::Mask tag, const ConnectedRoad &ro
typename Intersection::const_iterator findBestMatch(const TurnLaneType::Mask tag, typename Intersection::const_iterator findBestMatch(const TurnLaneType::Mask tag,
const Intersection &intersection) const Intersection &intersection)
{ {
return std::min_element( return std::min_element(intersection.begin(),
intersection.begin(),
intersection.end(), intersection.end(),
[tag](const ConnectedRoad &lhs, const ConnectedRoad &rhs) { [tag](const ConnectedRoad &lhs, const ConnectedRoad &rhs) {
// prefer valid matches // prefer valid matches
if (isValidMatch(tag, lhs.turn.instruction) != isValidMatch(tag, rhs.turn.instruction)) if (isValidMatch(tag, lhs.turn.instruction) !=
isValidMatch(tag, rhs.turn.instruction))
return isValidMatch(tag, lhs.turn.instruction); return isValidMatch(tag, lhs.turn.instruction);
// if the entry allowed flags don't match, we select the one with // if the entry allowed flags don't match, we select the one with
@ -129,7 +129,7 @@ typename Intersection::const_iterator findBestMatch(const TurnLaneType::Mask tag
if (lhs.entry_allowed != rhs.entry_allowed) if (lhs.entry_allowed != rhs.entry_allowed)
return lhs.entry_allowed; return lhs.entry_allowed;
return getMatchingQuality(tag,lhs) < getMatchingQuality(tag,rhs); return getMatchingQuality(tag, lhs) < getMatchingQuality(tag, rhs);
}); });
} }
@ -138,8 +138,8 @@ typename Intersection::const_iterator findBestMatch(const TurnLaneType::Mask tag
// by default in OSRM. Therefor we cannot check whether a turn is allowed, since it could be // 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 // 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. // the u-turn, since it could be a sharp-left turn instead on a road with a middle island.
typename Intersection::const_iterator typename Intersection::const_iterator findBestMatchForReverse(const TurnLaneType::Mask neighbor_tag,
findBestMatchForReverse(const TurnLaneType::Mask neighbor_tag, const Intersection &intersection) const Intersection &intersection)
{ {
const auto neighbor_itr = findBestMatch(neighbor_tag, intersection); const auto neighbor_itr = findBestMatch(neighbor_tag, intersection);
if (neighbor_itr + 1 == intersection.cend()) if (neighbor_itr + 1 == intersection.cend())
@ -159,7 +159,7 @@ findBestMatchForReverse(const TurnLaneType::Mask neighbor_tag, const Intersectio
if (lhs.entry_allowed != rhs.entry_allowed) if (lhs.entry_allowed != rhs.entry_allowed)
return lhs.entry_allowed; return lhs.entry_allowed;
return getMatchingQuality(tag,lhs) < getMatchingQuality(tag,rhs); return getMatchingQuality(tag, lhs) < getMatchingQuality(tag, rhs);
}); });
} }