add low precision intersection_generator mode for faster graph traversal
This commit is contained in:
parent
b2c27fbd25
commit
a49bd70985
@ -49,6 +49,17 @@ class CoordinateExtractor
|
|||||||
std::vector<util::Coordinate> GetForwardCoordinatesAlongRoad(const NodeID from,
|
std::vector<util::Coordinate> GetForwardCoordinatesAlongRoad(const NodeID from,
|
||||||
const EdgeID turn_edge) const;
|
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
|
/* When extracting the coordinates, we first extract all coordinates. We don't care about most
|
||||||
* of them, though.
|
* of them, though.
|
||||||
*
|
*
|
||||||
|
@ -51,8 +51,14 @@ class IntersectionGenerator
|
|||||||
// Check for restrictions/barriers and generate a list of valid and invalid turns present at
|
// 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
|
// the node reached from `from_node` via `via_eid`. The resulting candidates have to be analysed
|
||||||
// for their actual instructions later on.
|
// 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
|
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:
|
private:
|
||||||
const util::NodeBasedDynamicGraph &node_based_graph;
|
const util::NodeBasedDynamicGraph &node_based_graph;
|
||||||
|
@ -315,6 +315,55 @@ CoordinateExtractor::GetCoordinateAlongRoad(const NodeID intersection_node,
|
|||||||
.back();
|
.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>
|
std::vector<util::Coordinate>
|
||||||
CoordinateExtractor::GetForwardCoordinatesAlongRoad(const NodeID from, const EdgeID turn_edge) const
|
CoordinateExtractor::GetForwardCoordinatesAlongRoad(const NodeID from, const EdgeID turn_edge) const
|
||||||
{
|
{
|
||||||
|
@ -20,6 +20,12 @@ namespace extractor
|
|||||||
{
|
{
|
||||||
namespace guidance
|
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(
|
IntersectionGenerator::IntersectionGenerator(
|
||||||
const util::NodeBasedDynamicGraph &node_based_graph,
|
const util::NodeBasedDynamicGraph &node_based_graph,
|
||||||
@ -35,14 +41,14 @@ IntersectionGenerator::IntersectionGenerator(
|
|||||||
|
|
||||||
Intersection IntersectionGenerator::operator()(const NodeID from_node, const EdgeID via_eid) const
|
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
|
// a
|
||||||
// |
|
// |
|
||||||
// |
|
// |
|
||||||
// v
|
// 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
|
// but also (from_node, turn_node, a), (from_node, turn_node, b). These turns are
|
||||||
// marked as invalid and only needed for intersection classification.
|
// marked as invalid and only needed for intersection classification.
|
||||||
Intersection IntersectionGenerator::GetConnectedRoads(const NodeID from_node,
|
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;
|
Intersection intersection;
|
||||||
const NodeID turn_node = node_based_graph.GetTarget(via_eid);
|
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 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))
|
for (const EdgeID onto_edge : node_based_graph.GetAdjacentEdgeRange(turn_node))
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(onto_edge != SPECIAL_EDGEID);
|
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,
|
// 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
|
// just as the target coordinate can. Here we compute the corrected coordinate for the
|
||||||
// incoming edge.
|
// incoming edge.
|
||||||
const auto first_coordinate = coordinate_extractor.GetCoordinateAlongRoad(
|
const auto first_coordinate = extract_coordinate(from_node, via_eid, INVERT, turn_node);
|
||||||
from_node, via_eid, INVERT, turn_node, intersection_lanes);
|
|
||||||
|
|
||||||
if (from_node == to_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
|
// the default distance we lookahead on a road. This distance prevents small mapping
|
||||||
// errors to impact the turn angles.
|
// errors to impact the turn angles.
|
||||||
const auto third_coordinate = coordinate_extractor.GetCoordinateAlongRoad(
|
const auto third_coordinate =
|
||||||
turn_node, onto_edge, !INVERT, to_node, intersection_lanes);
|
extract_coordinate(turn_node, onto_edge, !INVERT, to_node);
|
||||||
|
|
||||||
angle = util::coordinate_calculation::computeAngle(
|
angle = util::coordinate_calculation::computeAngle(
|
||||||
first_coordinate, turn_coordinate, third_coordinate);
|
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.
|
// will never happen we add an artificial invalid uturn in this case.
|
||||||
if (!has_uturn_edge)
|
if (!has_uturn_edge)
|
||||||
{
|
{
|
||||||
const auto first_coordinate = coordinate_extractor.GetCoordinateAlongRoad(
|
const auto first_coordinate = extract_coordinate(from_node, via_eid, INVERT, turn_node);
|
||||||
from_node,
|
|
||||||
via_eid,
|
|
||||||
INVERT,
|
|
||||||
turn_node,
|
|
||||||
node_based_graph.GetEdgeData(via_eid).road_classification.GetNumberOfLanes());
|
|
||||||
const double bearing =
|
const double bearing =
|
||||||
util::coordinate_calculation::bearing(turn_coordinate, first_coordinate);
|
util::coordinate_calculation::bearing(turn_coordinate, first_coordinate);
|
||||||
|
|
||||||
|
@ -12,6 +12,11 @@ namespace guidance
|
|||||||
namespace lanes
|
namespace lanes
|
||||||
{
|
{
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
const constexpr bool USE_LOW_PRECISION_MODE = true;
|
||||||
|
}
|
||||||
|
|
||||||
bool findPreviousIntersection(const NodeID node_v,
|
bool findPreviousIntersection(const NodeID node_v,
|
||||||
const EdgeID via_edge,
|
const EdgeID via_edge,
|
||||||
const Intersection intersection,
|
const Intersection intersection,
|
||||||
@ -50,7 +55,8 @@ bool findPreviousIntersection(const NodeID node_v,
|
|||||||
// (looking at the reverse direction).
|
// (looking at the reverse direction).
|
||||||
const auto node_w = node_based_graph.GetTarget(via_edge);
|
const auto node_w = node_based_graph.GetTarget(via_edge);
|
||||||
const auto u_turn_at_node_w = intersection[0].eid;
|
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
|
// Continue along the straightmost turn. If there is no straight turn, we cannot find a valid
|
||||||
// previous intersection.
|
// previous intersection.
|
||||||
@ -64,8 +70,8 @@ bool findPreviousIntersection(const NodeID node_v,
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
const auto node_u = node_based_graph.GetTarget(straightmost_at_v_in_reverse->eid);
|
const auto node_u = node_based_graph.GetTarget(straightmost_at_v_in_reverse->eid);
|
||||||
const auto node_u_reverse_intersection =
|
const auto node_u_reverse_intersection = intersection_generator.GetConnectedRoads(
|
||||||
intersection_generator(node_v, straightmost_at_v_in_reverse->eid);
|
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
|
// 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.
|
// The u-turn at the now found intersection should, hopefully, represent the previous edge.
|
||||||
|
Loading…
Reference in New Issue
Block a user