add low precision intersection_generator mode for faster graph traversal

This commit is contained in:
Moritz Kobitzsch 2016-11-10 16:05:24 +01:00
parent b2c27fbd25
commit a49bd70985
5 changed files with 101 additions and 17 deletions

View File

@ -49,6 +49,17 @@ class CoordinateExtractor
std::vector<util::Coordinate> GetForwardCoordinatesAlongRoad(const NodeID from,
const EdgeID turn_edge) const;
// a less precise way to compute coordinates along a route. Due to the heavy interaction of
// graph traversal and turn instructions, we often don't care for high precision. We only want
// to check for available connections in order, or find (with room for error) the straightmost
// turn. This function will offer a bit more error potential but allow for much higher
// performance
OSRM_ATTR_WARN_UNUSED
util::Coordinate GetCoordinateCloseToTurn(const NodeID from_node,
const EdgeID turn_edge,
const bool traversed_in_reverse,
const NodeID to_node) const;
/* When extracting the coordinates, we first extract all coordinates. We don't care about most
* of them, though.
*

View File

@ -51,8 +51,14 @@ class IntersectionGenerator
// Check for restrictions/barriers and generate a list of valid and invalid turns present at
// the node reached from `from_node` via `via_eid`. The resulting candidates have to be analysed
// for their actual instructions later on.
// The switch for `use_low_precision_angles` enables a faster mode that will procude less
// accurate coordinates. It should be good enough to check order of turns, find striaghtmost
// turns. Even good enough to do some simple angle verifications. It is mostly available to
// allow for faster graph traversal in the extraction phase.
OSRM_ATTR_WARN_UNUSED
Intersection GetConnectedRoads(const NodeID from_node, const EdgeID via_eid) const;
Intersection GetConnectedRoads(const NodeID from_node,
const EdgeID via_eid,
const bool use_low_precision_angles = false) const;
private:
const util::NodeBasedDynamicGraph &node_based_graph;

View File

@ -315,6 +315,55 @@ CoordinateExtractor::GetCoordinateAlongRoad(const NodeID intersection_node,
.back();
}
util::Coordinate CoordinateExtractor::GetCoordinateCloseToTurn(const NodeID from_node,
const EdgeID turn_edge,
const bool traversed_in_reverse,
const NodeID to_node) const
{
const auto end_node = traversed_in_reverse ? from_node : to_node;
const auto start_node = traversed_in_reverse ? to_node : from_node;
if (!compressed_geometries.HasEntryForID(turn_edge))
return node_coordinates[end_node];
else
{
const auto &geometry = compressed_geometries.GetBucketReference(turn_edge);
// the compressed edges contain node ids, we transfer them to coordinates accessing the
// node_coordinates array
const auto compressedGeometryToCoordinate =
[this](const CompressedEdgeContainer::OnewayCompressedEdge &compressed_edge) {
return node_coordinates[compressed_edge.node_id];
};
// return the first coordinate that is reasonably far away from the start node
const util::Coordinate start_coordinate = node_coordinates[start_node];
// OSM data has a tendency to include repeated nodes with identical coordinates. To skip
// over these, we search for the first coordinate along the path that is at least a meter
// away from the first entry
const auto far_enough_away = [start_coordinate, compressedGeometryToCoordinate](
const CompressedEdgeContainer::OnewayCompressedEdge &compressed_edge) {
return util::coordinate_calculation::haversineDistance(
compressedGeometryToCoordinate(compressed_edge), start_coordinate) > 1;
};
// find the first coordinate, that is at least unequal to the begin of the edge
if (traversed_in_reverse)
{
const auto far_enough =
std::find_if(geometry.rbegin(), geometry.rend(), far_enough_away);
return (far_enough != geometry.rend()) ? compressedGeometryToCoordinate(*far_enough)
: node_coordinates[end_node];
}
else
{
const auto far_enough = std::find_if(geometry.begin(), geometry.end(), far_enough_away);
return (far_enough != geometry.end()) ? compressedGeometryToCoordinate(*far_enough)
: node_coordinates[end_node];
}
}
}
std::vector<util::Coordinate>
CoordinateExtractor::GetForwardCoordinatesAlongRoad(const NodeID from, const EdgeID turn_edge) const
{

View File

@ -20,6 +20,12 @@ namespace extractor
{
namespace guidance
{
namespace
{
const constexpr bool USE_LOW_PRECISION_MODE = true;
// the inverse of use low precision mode
const constexpr bool USE_HIGH_PRECISION_MODE = !USE_LOW_PRECISION_MODE;
}
IntersectionGenerator::IntersectionGenerator(
const util::NodeBasedDynamicGraph &node_based_graph,
@ -35,14 +41,14 @@ IntersectionGenerator::IntersectionGenerator(
Intersection IntersectionGenerator::operator()(const NodeID from_node, const EdgeID via_eid) const
{
return GetConnectedRoads(from_node, via_eid);
return GetConnectedRoads(from_node, via_eid, USE_HIGH_PRECISION_MODE);
}
// a
// |
// |
// v
// For an intersection from_node --via_edi--> turn_node ----> c
// For an intersection from_node --via_eid--> turn_node ----> c
// ^
// |
// |
@ -52,7 +58,8 @@ Intersection IntersectionGenerator::operator()(const NodeID from_node, const Edg
// but also (from_node, turn_node, a), (from_node, turn_node, b). These turns are
// marked as invalid and only needed for intersection classification.
Intersection IntersectionGenerator::GetConnectedRoads(const NodeID from_node,
const EdgeID via_eid) const
const EdgeID via_eid,
const bool use_low_precision_angles) const
{
Intersection intersection;
const NodeID turn_node = node_based_graph.GetTarget(via_eid);
@ -81,6 +88,17 @@ Intersection IntersectionGenerator::GetConnectedRoads(const NodeID from_node,
const auto intersection_lanes = getLaneCountAtIntersection(turn_node, node_based_graph);
const auto extract_coordinate = [&](const NodeID from_node,
const EdgeID via_eid,
const bool traversed_in_reverse,
const NodeID to_node) {
return use_low_precision_angles
? coordinate_extractor.GetCoordinateCloseToTurn(
from_node, via_eid, traversed_in_reverse, to_node)
: coordinate_extractor.GetCoordinateAlongRoad(
from_node, via_eid, traversed_in_reverse, to_node, intersection_lanes);
};
for (const EdgeID onto_edge : node_based_graph.GetAdjacentEdgeRange(turn_node))
{
BOOST_ASSERT(onto_edge != SPECIAL_EDGEID);
@ -105,8 +123,7 @@ Intersection IntersectionGenerator::GetConnectedRoads(const NodeID from_node,
// 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 = coordinate_extractor.GetCoordinateAlongRoad(
from_node, via_eid, INVERT, turn_node, intersection_lanes);
const auto first_coordinate = extract_coordinate(from_node, via_eid, INVERT, turn_node);
if (from_node == to_node)
{
@ -139,8 +156,8 @@ Intersection IntersectionGenerator::GetConnectedRoads(const NodeID from_node,
{
// the default distance we lookahead on a road. This distance prevents small mapping
// errors to impact the turn angles.
const auto third_coordinate = coordinate_extractor.GetCoordinateAlongRoad(
turn_node, onto_edge, !INVERT, to_node, intersection_lanes);
const auto third_coordinate =
extract_coordinate(turn_node, onto_edge, !INVERT, to_node);
angle = util::coordinate_calculation::computeAngle(
first_coordinate, turn_coordinate, third_coordinate);
@ -164,12 +181,7 @@ 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 = coordinate_extractor.GetCoordinateAlongRoad(
from_node,
via_eid,
INVERT,
turn_node,
node_based_graph.GetEdgeData(via_eid).road_classification.GetNumberOfLanes());
const auto first_coordinate = extract_coordinate(from_node, via_eid, INVERT, turn_node);
const double bearing =
util::coordinate_calculation::bearing(turn_coordinate, first_coordinate);

View File

@ -12,6 +12,11 @@ namespace guidance
namespace lanes
{
namespace
{
const constexpr bool USE_LOW_PRECISION_MODE = true;
}
bool findPreviousIntersection(const NodeID node_v,
const EdgeID via_edge,
const Intersection intersection,
@ -50,7 +55,8 @@ 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;
const auto node_v_reverse_intersection = intersection_generator(node_w, u_turn_at_node_w);
const auto node_v_reverse_intersection =
intersection_generator.GetConnectedRoads(node_w, u_turn_at_node_w, USE_LOW_PRECISION_MODE);
// Continue along the straightmost turn. If there is no straight turn, we cannot find a valid
// previous intersection.
@ -64,8 +70,8 @@ bool findPreviousIntersection(const NodeID node_v,
return false;
const auto node_u = node_based_graph.GetTarget(straightmost_at_v_in_reverse->eid);
const auto node_u_reverse_intersection =
intersection_generator(node_v, straightmost_at_v_in_reverse->eid);
const auto node_u_reverse_intersection = intersection_generator.GetConnectedRoads(
node_v, straightmost_at_v_in_reverse->eid, USE_LOW_PRECISION_MODE);
// now check that the u-turn at the given intersection connects to via-edge
// The u-turn at the now found intersection should, hopefully, represent the previous edge.