reduce numbers of intersections in findNextIntersection, don't normalise for turn lanes

This commit is contained in:
Moritz Kobitzsch
2016-11-15 11:21:26 +01:00
parent 01a57ff1d8
commit a1127c3e09
17 changed files with 203 additions and 125 deletions
+2 -1
View File
@@ -19,7 +19,8 @@
#include <string>
#include <vector>
static double search_radius_for_gps_radius(double gps_radius) {
static double search_radius_for_gps_radius(double gps_radius)
{
// For a given GPS radius, determine the radius we need to search for candidate street segments
// to have a 99.9% chance of finding the correct segment.
// For more detail, see the analysis at https://github.com/Project-OSRM/osrm-backend/pull/3184
@@ -56,13 +56,29 @@ CoordinateExtractor::GetCoordinateAlongRoad(const NodeID intersection_node,
const NodeID to_node,
const std::uint8_t intersection_lanes) const
{
const auto considered_lanes =
(intersection_lanes == 0) ? ASSUMED_LANE_COUNT : intersection_lanes;
// we first extract all coordinates from the road
auto coordinates =
GetCoordinatesAlongRoad(intersection_node, turn_edge, traversed_in_reverse, to_node);
return ExtractRepresentativeCoordinate(intersection_node,
turn_edge,
traversed_in_reverse,
to_node,
intersection_lanes,
std::move(coordinates));
}
util::Coordinate CoordinateExtractor::ExtractRepresentativeCoordinate(
const NodeID intersection_node,
const EdgeID turn_edge,
const bool traversed_in_reverse,
const NodeID to_node,
const std::uint8_t intersection_lanes,
std::vector<util::Coordinate> coordinates) const
{
const auto considered_lanes =
(intersection_lanes == 0) ? ASSUMED_LANE_COUNT : intersection_lanes;
/* if we are looking at a straight line, we don't care where exactly the coordinate
* is. Simply return the final coordinate. Turn angles/turn vectors are the same no matter which
* coordinate we look at.
@@ -406,10 +422,12 @@ CoordinateExtractor::GetCoordinatesAlongRoad(const NodeID intersection_node,
geometry.rend(),
std::back_inserter(result),
compressedGeometryToCoordinate);
BOOST_ASSERT(intersection_node < node_coordinates.size());
result.push_back(node_coordinates[intersection_node]);
}
else
{
BOOST_ASSERT(intersection_node < node_coordinates.size());
result.push_back(node_coordinates[intersection_node]);
std::transform(geometry.begin(),
geometry.end(),
+4 -2
View File
@@ -17,8 +17,10 @@ namespace extractor
namespace guidance
{
ConnectedRoad::ConnectedRoad(const TurnOperation turn, const bool entry_allowed)
: TurnOperation(turn), entry_allowed(entry_allowed)
ConnectedRoad::ConnectedRoad(const TurnOperation turn,
const bool entry_allowed,
boost::optional<double> segment_length)
: TurnOperation(turn), entry_allowed(entry_allowed), segment_length(segment_length)
{
}
@@ -99,6 +99,19 @@ Intersection IntersectionGenerator::GetConnectedRoads(const NodeID from_node,
from_node, via_eid, traversed_in_reverse, to_node, intersection_lanes);
};
// The first coordinate (the origin) can depend on the number of lanes turning onto,
// just as the target coordinate can. Here we compute the corrected coordinate for the
// incoming edge
// to compute the length along the path
const auto in_segment_length = [&]() {
const auto in_coordinates =
coordinate_extractor.GetCoordinatesAlongRoad(from_node, via_eid, INVERT, turn_node);
return util::coordinate_calculation::getLength(
in_coordinates, util::coordinate_calculation::haversineDistance);
}();
const auto first_coordinate = extract_coordinate(from_node, via_eid, INVERT, turn_node);
for (const EdgeID onto_edge : node_based_graph.GetAdjacentEdgeRange(turn_node))
{
BOOST_ASSERT(onto_edge != SPECIAL_EDGEID);
@@ -117,14 +130,7 @@ Intersection IntersectionGenerator::GetConnectedRoads(const NodeID from_node,
// the turn is not restricted
!restriction_map.CheckIfTurnIsRestricted(from_node, turn_node, to_node);
auto angle = 0.;
double bearing = 0.;
// The first coordinate (the origin) can depend on the number of lanes turning onto,
// just as the target coordinate can. Here we compute the corrected coordinate for the
// incoming edge.
const auto first_coordinate = extract_coordinate(from_node, via_eid, INVERT, turn_node);
double bearing = 0., out_segment_length = 0., angle = 0.;
if (from_node == to_node)
{
bearing = util::coordinate_calculation::bearing(turn_coordinate, first_coordinate);
@@ -150,14 +156,21 @@ Intersection IntersectionGenerator::GetConnectedRoads(const NodeID from_node,
}
}
has_uturn_edge = true;
out_segment_length = in_segment_length;
BOOST_ASSERT(angle >= 0. && angle < std::numeric_limits<double>::epsilon());
}
else
{
// the default distance we lookahead on a road. This distance prevents small mapping
// errors to impact the turn angles.
const auto third_coordinate =
extract_coordinate(turn_node, onto_edge, !INVERT, to_node);
{
// segment of out segment
const auto out_coordinates = coordinate_extractor.GetCoordinatesAlongRoad(
turn_node, onto_edge, !INVERT, to_node);
out_segment_length = util::coordinate_calculation::getLength(
out_coordinates, util::coordinate_calculation::haversineDistance);
}
const auto third_coordinate = extract_coordinate(turn_node, onto_edge, !INVERT, to_node);
angle = util::coordinate_calculation::computeAngle(
first_coordinate, turn_coordinate, third_coordinate);
@@ -173,7 +186,8 @@ Intersection IntersectionGenerator::GetConnectedRoads(const NodeID from_node,
bearing,
{TurnType::Invalid, DirectionModifier::UTurn},
INVALID_LANE_DATAID},
turn_is_valid));
turn_is_valid,
out_segment_length));
}
// We hit the case of a street leading into nothing-ness. Since the code here assumes
@@ -181,7 +195,6 @@ Intersection IntersectionGenerator::GetConnectedRoads(const NodeID from_node,
// will never happen we add an artificial invalid uturn in this case.
if (!has_uturn_edge)
{
const auto first_coordinate = extract_coordinate(from_node, via_eid, INVERT, turn_node);
const double bearing =
util::coordinate_calculation::bearing(turn_coordinate, first_coordinate);
@@ -190,7 +203,8 @@ Intersection IntersectionGenerator::GetConnectedRoads(const NodeID from_node,
bearing,
{TurnType::Invalid, DirectionModifier::UTurn},
INVALID_LANE_DATAID},
false});
false,
in_segment_length});
}
std::sort(std::begin(intersection),
@@ -227,41 +241,41 @@ IntersectionGenerator::GetActualNextIntersection(const NodeID starting_node,
NodeID *resulting_from_node = nullptr,
EdgeID *resulting_via_edge = nullptr) const
{
// This function skips over traffic lights/graph compression issues and similar to find the next
// actual intersection
Intersection result = GetConnectedRoads(starting_node, via_edge);
NodeID query_node = starting_node;
EdgeID query_edge = via_edge;
// Skip over stuff that has not been compressed due to barriers/parallel edges
NodeID node_at_intersection = starting_node;
EdgeID incoming_edge = via_edge;
const auto get_next_edge = [this](const NodeID from, const EdgeID via) {
const NodeID new_node = node_based_graph.GetTarget(via);
BOOST_ASSERT(node_based_graph.GetOutDegree(new_node) == 2);
const EdgeID begin_edges_new_node = node_based_graph.BeginEdges(new_node);
return (node_based_graph.GetTarget(begin_edges_new_node) == from) ? begin_edges_new_node + 1
: begin_edges_new_node;
};
// to prevent endless loops
const auto termination_node = node_based_graph.GetTarget(via_edge);
// using a maximum lookahead, we make sure not to end up in some form of loop
std::unordered_set<NodeID> visited_nodes;
while (visited_nodes.count(node_at_intersection) == 0 &&
(result.size() == 2 &&
node_based_graph.GetEdgeData(via_edge).IsCompatibleTo(
node_based_graph.GetEdgeData(result[1].eid))))
// skip trivial nodes without generating the intersection in between, stop at the very first
// intersection of degree > 2
while (0 == visited_nodes.count(query_node) &&
2 == node_based_graph.GetOutDegree(node_based_graph.GetTarget(query_edge)))
{
visited_nodes.insert(node_at_intersection);
node_at_intersection = node_based_graph.GetTarget(incoming_edge);
incoming_edge = result[1].eid;
result = GetConnectedRoads(node_at_intersection, incoming_edge);
// When looping back to the original node, we obviously are in a loop. Stop there.
if (termination_node == node_based_graph.GetTarget(incoming_edge))
visited_nodes.insert(query_node);
const auto next_node = node_based_graph.GetTarget(query_edge);
const auto next_edge = get_next_edge(query_node, query_edge);
if (!node_based_graph.GetEdgeData(query_edge)
.IsCompatibleTo(node_based_graph.GetEdgeData(next_edge)) ||
node_based_graph.GetTarget(next_edge) == starting_node)
break;
query_node = next_node;
query_edge = next_edge;
}
// return output if requested
if (resulting_from_node)
*resulting_from_node = node_at_intersection;
*resulting_from_node = query_node;
if (resulting_via_edge)
*resulting_via_edge = incoming_edge;
*resulting_via_edge = query_edge;
return result;
return GetConnectedRoads(query_node, query_edge);
}
const CoordinateExtractor &IntersectionGenerator::GetCoordinateExtractor() const
+27 -19
View File
@@ -1,5 +1,5 @@
#include "extractor/guidance/constants.hpp"
#include "extractor/guidance/intersection_handler.hpp"
#include "extractor/guidance/constants.hpp"
#include "extractor/guidance/toolkit.hpp"
#include "util/coordinate_calculation.hpp"
@@ -473,8 +473,8 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
std::abs(best_option_deviation - straightest_data_deviation) > FUZZY_ANGLE_DIFFERENCE;
const auto not_ramp_class = !straightest_data.road_classification.IsRampClass();
const auto not_link_class = !straightest_data.road_classification.IsLinkClass();
if (deviation_diff && !IsLowPriority(straightest_data) && not_ramp_class && not_link_class &&
!IsContinueRoad(best_option_data))
if (deviation_diff && !IsLowPriority(straightest_data) && not_ramp_class &&
not_link_class && !IsContinueRoad(best_option_data))
{
best_option = std::distance(begin(intersection), straightest);
best_option_deviation =
@@ -489,7 +489,8 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
auto best_continue_it =
std::min_element(begin(intersection), end(intersection), RoadCompareSameName);
const auto best_continue_data = node_based_graph.GetEdgeData(best_continue_it->eid);
if (IsContinueRoad(best_continue_data) || (in_way_data.name_id == EMPTY_NAMEID && best_continue_data.name_id == EMPTY_NAMEID))
if (IsContinueRoad(best_continue_data) ||
(in_way_data.name_id == EMPTY_NAMEID && best_continue_data.name_id == EMPTY_NAMEID))
{
best_continue = std::distance(begin(intersection), best_continue_it);
best_continue_deviation =
@@ -754,29 +755,36 @@ std::size_t IntersectionHandler::findObviousTurn(const EdgeID via_edge,
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)
const auto distance_at_u_turn = intersection[0].segment_length
? *intersection[0].segment_length
: util::coordinate_calculation::haversineDistance(
coordinate_at_intersection, coordinate_at_u_turn);
if (distance_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.
NodeID new_node;
const auto previous_intersection = intersection_generator.GetActualNextIntersection(
node_at_intersection, intersection[0].eid, nullptr, nullptr);
node_at_intersection, intersection[0].eid, &new_node, nullptr);
const auto continue_road = intersection[best_continue];
for (const auto &comparison_road : previous_intersection)
if (new_node != node_at_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. So if there is a road that is enterable in the opposite direction just
// prior, a turn is not obvious
const auto &turn_data = node_based_graph.GetEdgeData(comparison_road.eid);
if (angularDeviation(comparison_road.angle, STRAIGHT_ANGLE) > GROUP_ANGLE &&
angularDeviation(comparison_road.angle, continue_road.angle) <
FUZZY_ANGLE_DIFFERENCE &&
!turn_data.reversed && continue_data.CanCombineWith(turn_data))
return 0;
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. So if there is a road that is enterable in the opposite direction just
// prior, a turn is not obvious
const auto &turn_data = node_based_graph.GetEdgeData(comparison_road.eid);
if (angularDeviation(comparison_road.angle, STRAIGHT_ANGLE) > GROUP_ANGLE &&
angularDeviation(comparison_road.angle, continue_road.angle) <
FUZZY_ANGLE_DIFFERENCE &&
!turn_data.reversed && continue_data.CanCombineWith(turn_data))
return 0;
}
}
}
@@ -365,11 +365,17 @@ Intersection IntersectionNormalizer::AdjustForJoiningRoads(const NodeID node_at_
if (intersection.size() <= 1)
return intersection;
const util::Coordinate coordinate_at_intersection = node_coordinates[node_at_intersection];
// we don't adjust any road that is longer than 30 meters (between centers of intersections),
// since the road is probably too long otherwise to impact perception.
const double constexpr PRUNING_DISTANCE = 30;
// never adjust u-turns
for (std::size_t index = 1; index < intersection.size(); ++index)
{
auto &road = intersection[index];
// only consider roads that are close
if (road.segment_length && *(road.segment_length) > PRUNING_DISTANCE)
continue;
// 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.
@@ -380,11 +386,6 @@ Intersection IntersectionNormalizer::AdjustForJoiningRoads(const NodeID node_at_
continue;
const auto node_at_next_intersection = node_based_graph.GetTarget(road.eid);
const util::Coordinate coordinate_at_next_intersection =
node_coordinates[node_at_next_intersection];
if (util::coordinate_calculation::haversineDistance(coordinate_at_intersection,
coordinate_at_next_intersection) > 30)
continue;
const auto adjustAngle = [](double angle, double offset) {
angle += offset;
+11 -1
View File
@@ -19,7 +19,7 @@ const constexpr bool USE_LOW_PRECISION_MODE = true;
bool findPreviousIntersection(const NodeID node_v,
const EdgeID via_edge,
const Intersection intersection,
const Intersection &intersection,
const IntersectionGenerator &intersection_generator,
const util::NodeBasedDynamicGraph &node_based_graph,
// output parameters
@@ -55,6 +55,14 @@ bool findPreviousIntersection(const NodeID node_v,
// (looking at the reverse direction).
const auto node_w = node_based_graph.GetTarget(via_edge);
const auto u_turn_at_node_w = intersection[0].eid;
// make sure the ID is actually valid
BOOST_ASSERT(node_based_graph.BeginEdges(node_w) <= u_turn_at_node_w &&
u_turn_at_node_w <= node_based_graph.EndEdges(node_w));
// if we can't find the correct road, stop
if (node_based_graph.GetTarget(u_turn_at_node_w) != node_v)
return false;
const auto node_v_reverse_intersection =
intersection_generator.GetConnectedRoads(node_w, u_turn_at_node_w, USE_LOW_PRECISION_MODE);
@@ -77,6 +85,8 @@ bool findPreviousIntersection(const NodeID node_v,
// The u-turn at the now found intersection should, hopefully, represent the previous edge.
result_node = node_u;
result_via_edge = node_u_reverse_intersection[0].eid;
if (node_based_graph.GetTarget(result_via_edge) != node_v)
return false;
// if the edge is not traversable, we obviously don't have a previous intersection or couldn't
// find it.
+4 -3
View File
@@ -196,7 +196,7 @@ TurnLaneScenario TurnLaneHandler::deduceScenario(const NodeID at,
previous_intersection))
{
extractLaneData(previous_via_edge, previous_description_id, previous_lane_data);
previous_intersection = turn_analysis.PostProcess(
previous_intersection = turn_analysis.assignTurnTypes(
previous_node, previous_via_edge, std::move(previous_intersection));
for (std::size_t road_index = 0; road_index < previous_intersection.size(); ++road_index)
{
@@ -541,8 +541,9 @@ std::pair<LaneDataVector, LaneDataVector> TurnLaneHandler::partitionLaneData(
std::vector<bool> matched_at_second(turn_lane_data.size(), false);
// find out about the next intersection. To check for valid matches, we also need the turn
// types
const auto next_intersection = turn_analysis(at, straightmost->eid);
// types. We can skip merging/angle adjustments, though
const auto next_intersection = turn_analysis.assignTurnTypes(
at, straightmost->eid, turn_analysis.GetIntersectionGenerator()(at, straightmost->eid));
// check where we can match turn lanes
std::size_t straightmost_tag_index = turn_lane_data.size();
+6 -6
View File
@@ -8,8 +8,8 @@
#include "util/json_renderer.hpp"
#include "util/simple_logger.hpp"
#include "util/string_util.hpp"
#include "util/typedefs.hpp"
#include "util/timing_util.hpp"
#include "util/typedefs.hpp"
#include "engine/status.hpp"
#include "osrm/osrm.hpp"
@@ -146,11 +146,11 @@ void RequestHandler::HandleRequest(const http::request &current_request, http::r
<< 1900 + time_stamp->tm_year << " " << (time_stamp->tm_hour < 10 ? "0" : "")
<< time_stamp->tm_hour << ":" << (time_stamp->tm_min < 10 ? "0" : "")
<< time_stamp->tm_min << ":" << (time_stamp->tm_sec < 10 ? "0" : "")
<< time_stamp->tm_sec << " "
<< TIMER_MSEC(request_duration) << "ms " << current_request.endpoint.to_string() << " "
<< current_request.referrer << (0 == current_request.referrer.length() ? "- " : " ")
<< current_request.agent << (0 == current_request.agent.length() ? "- " : " ")
<< current_reply.status << " " //
<< time_stamp->tm_sec << " " << TIMER_MSEC(request_duration) << "ms "
<< current_request.endpoint.to_string() << " " << current_request.referrer
<< (0 == current_request.referrer.length() ? "- " : " ") << current_request.agent
<< (0 == current_request.agent.length() ? "- " : " ") << current_reply.status
<< " " //
<< request_string;
}
}