handle missing cases, cleaning up

This commit is contained in:
Moritz Kobitzsch 2016-08-15 12:43:26 +02:00
parent 21fb18fe5e
commit 9648821a79
16 changed files with 185 additions and 80 deletions

View File

@ -120,30 +120,27 @@ Feature: Simple Turns
When I route I should get
| waypoints | turns | route |
| a,d | depart,continue right,turn right,arrive | place,place,bottom,bottom |
| a,f | depart,continue right,continue left,continue right,arrive | place,place,place,place,place |
| a,d | depart,turn right,arrive | place,bottom,bottom |
| a,f | depart,continue left,continue right,arrive | place,place,place,place |
| d,f | depart,turn right,continue right,arrive | bottom,place,place,place |
| d,h | depart,turn right,continue left,turn right,arrive | bottom,place,place,top,top |
Scenario: Don't Collapse Places:
Given the node map
| | | | | | | h | | | | | | |
| | | | | | | g | | | | | | |
| | | | | | | | | | | | | |
| | | | | | | | | | | | | |
| | | | | | | | | | | | | |
| | | | | | | | | | | | | |
| | | | | | | | | | | | e | f |
| | | | | | | | | | | | | |
| | | | | | | | | | | | | |
| | | | | | | | | | | | | |
| | | | | | | | | | | | | |
| | | | | | | c | | | | | | |
| | b | | | | | | | | | | e | f |
And the ways
| nodes | name | oneway |
| ef | place | no |
| ceg | place | yes |
| fe | place | yes |
| gh | top | yes |
| egb | place | yes |
When I route I should get
| waypoints | turns | route |
| c,f | depart,turn right,continue right,arrive | bottom,place,place,place |
| f,h | depart,turn right,arrive | place,top,top |

View File

@ -88,9 +88,9 @@ Feature: Ramp Guidance
| | | | d | |
And the ways
| nodes | highway |
| abc | tertiary |
| bd | motorway_link |
| nodes | highway | oneway |
| abc | tertiary | yes |
| bd | motorway_link | yes |
When I route I should get
| waypoints | route | turns |
@ -110,7 +110,7 @@ Feature: Ramp Guidance
When I route I should get
| waypoints | route | turns |
| a,d | abc,bd,bd | depart,on ramp straight,arrive |
| a,c | abc,abc,abc | depart,continue left,arrive |
| a,c | abc,abc | depart,arrive |
Scenario: Fork Ramp Off Turning Though Street
Given the node map
@ -126,7 +126,7 @@ Feature: Ramp Guidance
When I route I should get
| waypoints | route | turns |
| a,d | abc,bd,bd | depart,on ramp right,arrive |
| a,c | abc,abc,abc | depart,continue left,arrive |
| a,c | abc,abc | depart,arrive |
Scenario: Fork Ramp
Given the node map
@ -176,7 +176,7 @@ Feature: Ramp Guidance
When I route I should get
| waypoints | route | turns |
| a,d | abc,bd,bd | depart,on ramp slight right,arrive |
| a,c | abc,abc,abc | depart,continue slight left,arrive |
| a,c | abc,abc | depart,arrive |
Scenario: Fork Slight Ramp on Obvious Through Street
Given the node map

View File

@ -35,6 +35,17 @@ class IntersectionGenerator
Intersection operator()(const NodeID nid, const EdgeID via_eid) const;
// Graph Compression cannot compress every setting. For example any barrier/traffic light cannot
// be compressed. As a result, a simple road of the form `a ----- b` might end up as having an
// intermediate intersection, if there is a traffic light in between. If we want to look farther
// down a road, finding the next actual decision requires the look at multiple intersections.
// Here we follow the road until we either reach a dead end or find the next intersection with
// more than a single next road.
Intersection GetActualNextIntersection(const NodeID starting_node,
const EdgeID via_edge,
NodeID *resulting_from_node,
EdgeID *resulting_via_edge) const;
private:
const util::NodeBasedDynamicGraph &node_based_graph;
const RestrictionMap &restriction_map;
@ -86,17 +97,6 @@ class IntersectionGenerator
OSRM_ATTR_WARN_UNUSED
Intersection AdjustForJoiningRoads(const NodeID node_at_intersection,
Intersection intersection) const;
// Graph Compression cannot compress every setting. For example any barrier/traffic light cannot
// be compressed. As a result, a simple road of the form `a ----- b` might end up as having an
// intermediate intersection, if there is a traffic light in between. If we want to look farther
// down a road, finding the next actual decision requires the look at multiple intersections.
// Here we follow the road until we either reach a dead end or find the next intersection with
// more than a single next road.
inline Intersection GetActualNextIntersection(const NodeID starting_node,
const EdgeID via_edge,
NodeID *resulting_from_node,
EdgeID *resulting_via_edge) const;
};
} // namespace guidance

View File

@ -2,6 +2,7 @@
#define OSRM_EXTRACTOR_GUIDANCE_INTERSECTION_HANDLER_HPP_
#include "extractor/guidance/intersection.hpp"
#include "extractor/guidance/intersection_generator.hpp"
#include "extractor/query_node.hpp"
#include "extractor/suffix_table.hpp"
@ -28,7 +29,8 @@ class IntersectionHandler
IntersectionHandler(const util::NodeBasedDynamicGraph &node_based_graph,
const std::vector<QueryNode> &node_info_list,
const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table);
const SuffixTable &street_name_suffix_table,
const IntersectionGenerator &intersection_generator);
virtual ~IntersectionHandler() = default;
@ -45,6 +47,7 @@ class IntersectionHandler
const std::vector<QueryNode> &node_info_list;
const util::NameTable &name_table;
const SuffixTable &street_name_suffix_table;
const IntersectionGenerator &intersection_generator;
// counts the number on allowed entry roads
std::size_t countValid(const Intersection &intersection) const;

View File

@ -3,6 +3,7 @@
#include "extractor/guidance/intersection.hpp"
#include "extractor/guidance/intersection_handler.hpp"
#include "extractor/guidance/intersection_generator.hpp"
#include "extractor/query_node.hpp"
#include "util/attributes.hpp"
@ -26,7 +27,8 @@ class MotorwayHandler : public IntersectionHandler
MotorwayHandler(const util::NodeBasedDynamicGraph &node_based_graph,
const std::vector<QueryNode> &node_info_list,
const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table);
const SuffixTable &street_name_suffix_table,
const IntersectionGenerator &intersection_generator);
~MotorwayHandler() override final = default;

View File

@ -4,6 +4,7 @@
#include "extractor/compressed_edge_container.hpp"
#include "extractor/guidance/intersection.hpp"
#include "extractor/guidance/intersection_handler.hpp"
#include "extractor/guidance/intersection_generator.hpp"
#include "extractor/guidance/roundabout_type.hpp"
#include "extractor/profile_properties.hpp"
#include "extractor/query_node.hpp"
@ -44,7 +45,8 @@ class RoundaboutHandler : public IntersectionHandler
const CompressedEdgeContainer &compressed_edge_container,
const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table,
const ProfileProperties &profile_properties);
const ProfileProperties &profile_properties,
const IntersectionGenerator &intersection_generator);
~RoundaboutHandler() override final = default;

View File

@ -42,9 +42,6 @@ class SliproadHandler : public IntersectionHandler
Intersection operator()(const NodeID nid,
const EdgeID via_eid,
Intersection intersection) const override final;
private:
const IntersectionGenerator &intersection_generator;
};
} // namespace guidance

View File

@ -3,6 +3,7 @@
#include "extractor/guidance/intersection.hpp"
#include "extractor/guidance/intersection_handler.hpp"
#include "extractor/guidance/intersection_generator.hpp"
#include "extractor/query_node.hpp"
#include "util/attributes.hpp"
@ -28,7 +29,8 @@ class TurnHandler : public IntersectionHandler
TurnHandler(const util::NodeBasedDynamicGraph &node_based_graph,
const std::vector<QueryNode> &node_info_list,
const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table);
const SuffixTable &street_name_suffix_table,
const IntersectionGenerator &intersection_generator);
~TurnHandler() override final = default;

View File

@ -1,5 +1,3 @@
#include "util/debug.hpp"
#include "extractor/guidance/turn_instruction.hpp"
#include "engine/guidance/post_processing.hpp"
@ -586,7 +584,6 @@ std::vector<RouteStep> removeNoTurnInstructions(std::vector<RouteStep> steps)
// that we come across.
std::vector<RouteStep> postProcess(std::vector<RouteStep> steps)
{
util::guidance::print(steps);
// the steps should always include the first/last step in form of a location
BOOST_ASSERT(steps.size() >= 2);
if (steps.size() == 2)

View File

@ -218,8 +218,7 @@ bool IntersectionGenerator::CanMerge(const NodeID node_at_intersection,
coordinate_at_intersection,
node_at_intersection](const std::size_t index,
const std::size_t other_index) {
const auto GetActualTarget = [&](const std::size_t index)
{
const auto GetActualTarget = [&](const std::size_t index) {
EdgeID last_in_edge_id;
GetActualNextIntersection(
node_at_intersection, intersection[index].turn.eid, nullptr, &last_in_edge_id);
@ -239,6 +238,10 @@ bool IntersectionGenerator::CanMerge(const NodeID node_at_intersection,
const double distance_to_target = util::coordinate_calculation::haversineDistance(
coordinate_at_intersection, coordinate_at_target);
const constexpr double MAX_COLLAPSE_DISTANCE = 30;
if (distance_to_target < MAX_COLLAPSE_DISTANCE)
return false;
const bool becomes_narrower =
angularDeviation(turn_angle, other_turn_angle) < NARROW_TURN_ANGLE &&
angularDeviation(turn_angle, other_turn_angle) <
@ -474,14 +477,14 @@ Intersection IntersectionGenerator::MergeSegregatedRoads(const NodeID intersecti
Intersection IntersectionGenerator::AdjustForJoiningRoads(const NodeID node_at_intersection,
Intersection intersection) const
{
// FIXME remove
return intersection;
// nothing to do for dead ends
if (intersection.size() <= 1)
return intersection;
for (auto &road : intersection)
// We can't adjust the very first angle, because the u-turn should always be 0
for (std::size_t road_index = 1; road_index < intersection.size(); ++road_index)
{
auto &road = intersection[road_index];
// to find out about the above situation, we need to look at the next intersection (at d in
// the example). If the initial road can be merged to the left/right, we are about to adjust
// the angle.
@ -525,7 +528,7 @@ Intersection IntersectionGenerator::AdjustForJoiningRoads(const NodeID node_at_i
return intersection;
}
inline Intersection
Intersection
IntersectionGenerator::GetActualNextIntersection(const NodeID starting_node,
const EdgeID via_edge,
NodeID *resulting_from_node = nullptr,

View File

@ -7,6 +7,7 @@
#include "util/simple_logger.hpp"
#include <algorithm>
#include <cstddef>
using EdgeData = osrm::util::NodeBasedDynamicGraph::EdgeData;
using osrm::util::guidance::getTurnDirection;
@ -29,9 +30,11 @@ inline bool requiresAnnouncement(const EdgeData &from, const EdgeData &to)
IntersectionHandler::IntersectionHandler(const util::NodeBasedDynamicGraph &node_based_graph,
const std::vector<QueryNode> &node_info_list,
const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table)
const SuffixTable &street_name_suffix_table,
const IntersectionGenerator &intersection_generator)
: node_based_graph(node_based_graph), node_info_list(node_info_list), name_table(name_table),
street_name_suffix_table(street_name_suffix_table)
street_name_suffix_table(street_name_suffix_table),
intersection_generator(intersection_generator)
{
}
@ -469,10 +472,10 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
}
// has no obvious continued road
const auto &best_data = node_based_graph.GetEdgeData(intersection[best].turn.eid);
if (best_continue == 0 || num_continue_names > 2 ||
(node_based_graph.GetEdgeData(intersection[best_continue].turn.eid).road_classification ==
node_based_graph.GetEdgeData(intersection[best].turn.eid).road_classification &&
std::abs(best_continue_deviation) > 1 && best_deviation / best_continue_deviation < 0.75))
(num_continue_names > 2 && best_continue_deviation >= 2 * NARROW_TURN_ANGLE) ||
(best_deviation < FUZZY_ANGLE_DIFFERENCE && !best_data.road_classification.IsRampClass()))
{
// Find left/right deviation
const double left_deviation = angularDeviation(
@ -484,7 +487,6 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
std::min(left_deviation, right_deviation) > FUZZY_ANGLE_DIFFERENCE)
return best;
const auto &best_data = node_based_graph.GetEdgeData(intersection[best].turn.eid);
const auto left_index = (best + 1) % intersection.size();
const auto right_index = best - 1;
const auto &left_data = node_based_graph.GetEdgeData(intersection[left_index].turn.eid);
@ -538,14 +540,87 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
if (i == best_continue || !intersection[i].entry_allowed)
continue;
if (angularDeviation(intersection[i].turn.angle, STRAIGHT_ANGLE) / deviation < 1.1 &&
!obvious_by_road_class(
in_data.road_classification,
const auto &turn_data = node_based_graph.GetEdgeData(intersection[i].turn.eid);
const bool is_obvious_by_road_class =
obvious_by_road_class(in_data.road_classification,
continue_data.road_classification,
node_based_graph.GetEdgeData(intersection[i].turn.eid).road_classification))
turn_data.road_classification);
// if the main road is obvious by class, we ignore the current road as a potential
// prevention of obviousness
if (is_obvious_by_road_class)
continue;
// continuation could be grouped with a straight turn and the turning road is a ramp
if (turn_data.road_classification.IsRampClass() && deviation < GROUP_ANGLE)
continue;
// perfectly straight turns prevent obviousness
const auto turn_deviation =
angularDeviation(intersection[i].turn.angle, STRAIGHT_ANGLE);
if (turn_deviation < FUZZY_ANGLE_DIFFERENCE)
return 0;
const auto deviation_ratio = turn_deviation / deviation;
// in comparison to normal devitions, a continue road can offer a smaller distinction
// ratio. Other roads close to the turn angle are not as obvious, if one road continues.
if (deviation_ratio < DISTINCTION_RATIO / 1.5)
return 0;
// in comparison to another continuing road, we need a better distinction. This prevents
// situations where the turn is probably less obvious. An example are places that have a
// road with the same name entering/exiting:
//
// d
// /
// /
// a -- b
// \
// \
// c
if (turn_data.name_id == continue_data.name_id &&
deviation_ratio < 1.5 * DISTINCTION_RATIO)
return 0;
}
return best_continue; // no obvious turn
// Segregated intersections can result in us finding an obvious turn, even though its only
// obvious due to a very short segment in between. So if the segment coming in is very
// short, we check the previous intersection for other continues in the opposite bearing.
const auto node_at_intersection = node_based_graph.GetTarget(via_edge);
const util::Coordinate coordinate_at_intersection = node_info_list[node_at_intersection];
const auto node_at_u_turn = node_based_graph.GetTarget(intersection[0].turn.eid);
const util::Coordinate coordinate_at_u_turn = node_info_list[node_at_u_turn];
const double constexpr MAX_COLLAPSE_DISTANCE = 30;
if (util::coordinate_calculation::haversineDistance(
coordinate_at_intersection, coordinate_at_u_turn) < MAX_COLLAPSE_DISTANCE)
{
// this request here actually goes against the direction of the ingoing edgeid. This can
// even reverse the direction. Since we don't want to compute actual turns but simply
// try to find whether there is a turn going to the opposite direction of our obvious
// turn, this should be alright.
const auto previous_intersection = intersection_generator.GetActualNextIntersection(
node_at_intersection, intersection[0].turn.eid, nullptr, nullptr);
const auto continue_road = intersection[best_continue];
for (const auto &comparison_road : previous_intersection)
{
// since we look at the intersection in the wrong direction, a similar angle
// actually represents a near 180 degree different in bearings between the two
// roads.
if (angularDeviation(comparison_road.turn.angle, STRAIGHT_ANGLE) > GROUP_ANGLE &&
angularDeviation(comparison_road.turn.angle, continue_road.turn.angle) <
FUZZY_ANGLE_DIFFERENCE &&
continue_data.IsCompatibleTo(
node_based_graph.GetEdgeData(comparison_road.turn.eid)))
return 0;
}
}
return best_continue;
}
return 0;

View File

@ -1,5 +1,5 @@
#include "extractor/guidance/motorway_handler.hpp"
#include "extractor/guidance/constants.hpp"
#include "extractor/guidance/motorway_handler.hpp"
#include "extractor/guidance/road_classification.hpp"
#include "extractor/guidance/toolkit.hpp"
@ -43,8 +43,13 @@ inline bool isRampClass(EdgeID eid, const util::NodeBasedDynamicGraph &node_base
MotorwayHandler::MotorwayHandler(const util::NodeBasedDynamicGraph &node_based_graph,
const std::vector<QueryNode> &node_info_list,
const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table)
: IntersectionHandler(node_based_graph, node_info_list, name_table, street_name_suffix_table)
const SuffixTable &street_name_suffix_table,
const IntersectionGenerator &intersection_generator)
: IntersectionHandler(node_based_graph,
node_info_list,
name_table,
street_name_suffix_table,
intersection_generator)
{
}

View File

@ -1,5 +1,5 @@
#include "extractor/guidance/roundabout_handler.hpp"
#include "extractor/guidance/constants.hpp"
#include "extractor/guidance/roundabout_handler.hpp"
#include "extractor/guidance/toolkit.hpp"
#include "util/coordinate_calculation.hpp"
@ -26,8 +26,13 @@ RoundaboutHandler::RoundaboutHandler(const util::NodeBasedDynamicGraph &node_bas
const CompressedEdgeContainer &compressed_edge_container,
const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table,
const ProfileProperties &profile_properties)
: IntersectionHandler(node_based_graph, node_info_list, name_table, street_name_suffix_table),
const ProfileProperties &profile_properties,
const IntersectionGenerator &intersection_generator)
: IntersectionHandler(node_based_graph,
node_info_list,
name_table,
street_name_suffix_table,
intersection_generator),
compressed_edge_container(compressed_edge_container), profile_properties(profile_properties)
{
}

View File

@ -26,8 +26,11 @@ SliproadHandler::SliproadHandler(const IntersectionGenerator &intersection_gener
const std::vector<QueryNode> &node_info_list,
const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table)
: IntersectionHandler(node_based_graph, node_info_list, name_table, street_name_suffix_table),
intersection_generator(intersection_generator)
: IntersectionHandler(node_based_graph,
node_info_list,
name_table,
street_name_suffix_table,
intersection_generator)
{
}

View File

@ -1,6 +1,6 @@
#include "extractor/guidance/turn_analysis.hpp"
#include "extractor/guidance/constants.hpp"
#include "extractor/guidance/road_classification.hpp"
#include "extractor/guidance/turn_analysis.hpp"
#include "util/coordinate.hpp"
#include "util/coordinate_calculation.hpp"
@ -49,9 +49,18 @@ TurnAnalysis::TurnAnalysis(const util::NodeBasedDynamicGraph &node_based_graph,
compressed_edge_container,
name_table,
street_name_suffix_table,
profile_properties),
motorway_handler(node_based_graph, node_info_list, name_table, street_name_suffix_table),
turn_handler(node_based_graph, node_info_list, name_table, street_name_suffix_table),
profile_properties,
intersection_generator),
motorway_handler(node_based_graph,
node_info_list,
name_table,
street_name_suffix_table,
intersection_generator),
turn_handler(node_based_graph,
node_info_list,
name_table,
street_name_suffix_table,
intersection_generator),
sliproad_handler(intersection_generator,
node_based_graph,
node_info_list,

View File

@ -24,8 +24,13 @@ namespace guidance
TurnHandler::TurnHandler(const util::NodeBasedDynamicGraph &node_based_graph,
const std::vector<QueryNode> &node_info_list,
const util::NameTable &name_table,
const SuffixTable &street_name_suffix_table)
: IntersectionHandler(node_based_graph, node_info_list, name_table, street_name_suffix_table)
const SuffixTable &street_name_suffix_table,
const IntersectionGenerator &intersection_generator)
: IntersectionHandler(node_based_graph,
node_info_list,
name_table,
street_name_suffix_table,
intersection_generator)
{
}