fix errors in coordinate extractor due to duplicated coordinates
fix offset calculation in curve detection
This commit is contained in:
parent
17a18b5c7c
commit
a28a20a1ba
@ -275,7 +275,7 @@ Feature: Slipways and Dedicated Turn Lanes
|
|||||||
| a,i | Ebertstrasse,Ebertstrasse | depart,arrive |
|
| a,i | Ebertstrasse,Ebertstrasse | depart,arrive |
|
||||||
| a,l | Ebertstrasse,Ebertstrasse | depart,arrive |
|
| a,l | Ebertstrasse,Ebertstrasse | depart,arrive |
|
||||||
| a,f | Ebertstrasse,Brauerstrasse,Brauerstrasse | depart,turn right,arrive |
|
| a,f | Ebertstrasse,Brauerstrasse,Brauerstrasse | depart,turn right,arrive |
|
||||||
| a,1 | Ebertstrasse,, | depart,turn right,arrive |
|
| a,1 | Ebertstrasse,, | depart,turn slight right,arrive |
|
||||||
|
|
||||||
#2839
|
#2839
|
||||||
Scenario: Self-Loop
|
Scenario: Self-Loop
|
||||||
|
@ -322,7 +322,7 @@ Feature: Simple Turns
|
|||||||
|
|
|
|
||||||
|
|
|
|
||||||
|
|
|
|
||||||
| . b - - - - - - - - - - - - - - - - - - a
|
| . b - - - - - - - - - - - - - - - - - - - - - - - a
|
||||||
| .
|
| .
|
||||||
| .
|
| .
|
||||||
| c
|
| c
|
||||||
@ -336,7 +336,7 @@ Feature: Simple Turns
|
|||||||
e |
|
e |
|
||||||
. |
|
. |
|
||||||
. |
|
. |
|
||||||
g - - - - - - - - - - - - - f |
|
g - - - - - - - - - - - - - - - - - - f |
|
||||||
|
|
|
|
||||||
|
|
|
|
||||||
|
|
|
|
||||||
@ -443,9 +443,9 @@ Feature: Simple Turns
|
|||||||
| ef | residential | road | 2 | yes |
|
| ef | residential | road | 2 | yes |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route | turns | locations |
|
| waypoints | route | turns | locations | # |
|
||||||
| g,f | turn,road,road | depart,turn left,arrive | g,e,f |
|
| g,f | turn,road | depart,arrive | g,f | #could offer an additional turn at `e` if you don't detect the turn in between as curve |
|
||||||
| c,f | road,road,road | depart,continue right,arrive | c,b,f |
|
| c,f | road,road,road | depart,continue right,arrive | c,b,f | |
|
||||||
|
|
||||||
#http://www.openstreetmap.org/search?query=52.479264%2013.295617#map=19/52.47926/13.29562
|
#http://www.openstreetmap.org/search?query=52.479264%2013.295617#map=19/52.47926/13.29562
|
||||||
Scenario: Splitting Roads with curved split
|
Scenario: Splitting Roads with curved split
|
||||||
@ -627,12 +627,14 @@ Feature: Simple Turns
|
|||||||
| 1,h | ,allee,allee | depart,turn left,arrive |
|
| 1,h | ,allee,allee | depart,turn left,arrive |
|
||||||
| 2,h | ,allee,allee | depart,turn left,arrive |
|
| 2,h | ,allee,allee | depart,turn left,arrive |
|
||||||
|
|
||||||
|
|
||||||
#http://www.openstreetmap.org/#map=18/52.56251/13.32650
|
#http://www.openstreetmap.org/#map=18/52.56251/13.32650
|
||||||
|
@todo
|
||||||
Scenario: Curved Turn on Separated Directions
|
Scenario: Curved Turn on Separated Directions
|
||||||
Given the node map
|
Given the node map
|
||||||
"""
|
"""
|
||||||
e d
|
e d
|
||||||
f - - - - - - - - - - - - - - - c - - - - - - - - - - - j
|
f c - - - - - - - - - - - j
|
||||||
| l ' |
|
| l ' |
|
||||||
| ' |
|
| ' |
|
||||||
| ' |
|
| ' |
|
||||||
@ -680,6 +682,58 @@ Feature: Simple Turns
|
|||||||
| j,o | Kapweg,Kapweg,Kapweg | depart,continue uturn,arrive |
|
| j,o | Kapweg,Kapweg,Kapweg | depart,continue uturn,arrive |
|
||||||
| a,i | Kurt,Kurt,Kurt | depart,continue uturn,arrive |
|
| a,i | Kurt,Kurt,Kurt | depart,continue uturn,arrive |
|
||||||
|
|
||||||
|
#http://www.openstreetmap.org/#map=18/52.56251/13.32650
|
||||||
|
Scenario: Curved Turn on Separated Directions
|
||||||
|
Given the node map
|
||||||
|
"""
|
||||||
|
e d
|
||||||
|
f c - - - - - - - - - - - j
|
||||||
|
| l ' |
|
||||||
|
| ' |
|
||||||
|
| ' |
|
||||||
|
| ' |
|
||||||
|
| ' |
|
||||||
|
| n |
|
||||||
|
| |
|
||||||
|
| ' |
|
||||||
|
| |
|
||||||
|
| ' |
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
|' |
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
g |
|
||||||
|
h - - - - - - - - - - - - - - - b - - - - - - - - - - - o
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
| |
|
||||||
|
i a
|
||||||
|
"""
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | name | oneway | lanes | highway |
|
||||||
|
| jc | Kapweg | yes | 3 | primary |
|
||||||
|
| clngh | Kapweg | yes | | primary_link |
|
||||||
|
| hbo | Kapweg | yes | 2 | primary |
|
||||||
|
| efh | Kurt | yes | 4 | secondary |
|
||||||
|
| hi | Kurt | yes | 3 | primary |
|
||||||
|
| ab | Kurt | yes | 4 | primary |
|
||||||
|
| cd | Kurt | yes | 3 | secondary |
|
||||||
|
| bc | Kurt | yes | 2 | primary |
|
||||||
|
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | turns |
|
||||||
|
| j,i | Kapweg,Kurt,Kurt | depart,turn left,arrive |
|
||||||
|
| j,o | Kapweg,Kapweg,Kapweg | depart,continue uturn,arrive |
|
||||||
|
| a,i | Kurt,Kurt,Kurt | depart,continue uturn,arrive |
|
||||||
|
|
||||||
#http://www.openstreetmap.org/#map=19/52.53731/13.36033
|
#http://www.openstreetmap.org/#map=19/52.53731/13.36033
|
||||||
Scenario: Splitting Road to Left
|
Scenario: Splitting Road to Left
|
||||||
Given the node map
|
Given the node map
|
||||||
@ -1112,8 +1166,9 @@ Feature: Simple Turns
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
And the ways
|
And the ways
|
||||||
| nodes | name | highway | lanes |
|
| nodes | name | highway | lanes | oneway |
|
||||||
| abcdefghijklmnopc | circled | residential | 1 |
|
| abc | circled | residential | 1 | no |
|
||||||
|
| cdefghijklmnopc | circled | residential | 1 | yes |
|
||||||
|
|
||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | bearings | route | turns |
|
| waypoints | bearings | route | turns |
|
||||||
@ -1168,3 +1223,40 @@ Feature: Simple Turns
|
|||||||
When I route I should get
|
When I route I should get
|
||||||
| waypoints | route |
|
| waypoints | route |
|
||||||
| a,e | ab,bcde,bcde |
|
| a,e | ab,bcde,bcde |
|
||||||
|
|
||||||
|
|
||||||
|
@3401
|
||||||
|
Scenario: Curve With Duplicated Coordinates
|
||||||
|
Given the node locations
|
||||||
|
| node | lat | lon | # |
|
||||||
|
| a | 0.9999280745650984 | 1.0 | |
|
||||||
|
| b | 0.9999280745650984 | 1.0000179813587253 | |
|
||||||
|
| c | 0.9999280745650984 | 1.0000359627174509 | |
|
||||||
|
| d | 0.9999460559238238 | 1.0000674300952204 | |
|
||||||
|
| e | 0.9999640372825492 | 1.0000809161142643 | |
|
||||||
|
| f | 0.9999820186412746 | 1.0000854114539457 | |
|
||||||
|
| g | 1.0 | 1.0000854114539457 | |
|
||||||
|
| h | 1.0 | 1.0000854114539457 | #same as g |
|
||||||
|
| z | 0.9999100932063729 | 1.0000179813587253 | |
|
||||||
|
# g
|
||||||
|
# |
|
||||||
|
# f
|
||||||
|
# '
|
||||||
|
# e
|
||||||
|
# '
|
||||||
|
# d
|
||||||
|
# '
|
||||||
|
#a - b - c
|
||||||
|
# |
|
||||||
|
# z
|
||||||
|
|
||||||
|
And the ways
|
||||||
|
| nodes | oneway | lanes | # |
|
||||||
|
| ab | yes | 1 | |
|
||||||
|
| zb | yes | 1 | |
|
||||||
|
| bcdefgh | yes | 1 | #intentional duplication |
|
||||||
|
|
||||||
|
# we don't care for turn instructions, this is a coordinate extraction bug check
|
||||||
|
When I route I should get
|
||||||
|
| waypoints | route | intersections |
|
||||||
|
| a,g | ab,bcdefgh,bcdefgh | true:90;true:45 false:180 false:270;true:180 |
|
||||||
|
@ -125,13 +125,13 @@ util::Coordinate CoordinateExtractor::ExtractRepresentativeCoordinate(
|
|||||||
|
|
||||||
// due to repeated coordinates / smaller offset errors we skip over the very first parts of the
|
// due to repeated coordinates / smaller offset errors we skip over the very first parts of the
|
||||||
// coordinate set to add a small level of fault tolerance
|
// coordinate set to add a small level of fault tolerance
|
||||||
const constexpr double distance_to_skip_over_due_to_coordinate_inaccuracies = 2;
|
const constexpr double skipping_inaccuracies_distance = 2;
|
||||||
|
|
||||||
// fallback, mostly necessary for dead ends
|
// fallback, mostly necessary for dead ends
|
||||||
if (intersection_node == to_node)
|
if (intersection_node == to_node)
|
||||||
{
|
{
|
||||||
const auto result = ExtractCoordinateAtLength(
|
const auto result = ExtractCoordinateAtLength(
|
||||||
distance_to_skip_over_due_to_coordinate_inaccuracies, coordinates);
|
skipping_inaccuracies_distance, coordinates);
|
||||||
BOOST_ASSERT(is_valid_result(coordinates.back()));
|
BOOST_ASSERT(is_valid_result(coordinates.back()));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -147,7 +147,7 @@ util::Coordinate CoordinateExtractor::ExtractRepresentativeCoordinate(
|
|||||||
if (turn_edge_data.roundabout || turn_edge_data.circular)
|
if (turn_edge_data.roundabout || turn_edge_data.circular)
|
||||||
{
|
{
|
||||||
const auto result = ExtractCoordinateAtLength(
|
const auto result = ExtractCoordinateAtLength(
|
||||||
distance_to_skip_over_due_to_coordinate_inaccuracies, coordinates);
|
skipping_inaccuracies_distance, coordinates);
|
||||||
BOOST_ASSERT(is_valid_result(result));
|
BOOST_ASSERT(is_valid_result(result));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -235,7 +235,7 @@ util::Coordinate CoordinateExtractor::ExtractRepresentativeCoordinate(
|
|||||||
|
|
||||||
// if we are now left with two, well than we don't have to worry, or the segment is very small
|
// if we are now left with two, well than we don't have to worry, or the segment is very small
|
||||||
if (coordinates.size() == 2 ||
|
if (coordinates.size() == 2 ||
|
||||||
total_distance <= distance_to_skip_over_due_to_coordinate_inaccuracies)
|
total_distance <= skipping_inaccuracies_distance)
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(is_valid_result(coordinates.back()));
|
BOOST_ASSERT(is_valid_result(coordinates.back()));
|
||||||
return coordinates.back();
|
return coordinates.back();
|
||||||
@ -253,7 +253,7 @@ util::Coordinate CoordinateExtractor::ExtractRepresentativeCoordinate(
|
|||||||
if (coordinates.front() == coordinates.back())
|
if (coordinates.front() == coordinates.back())
|
||||||
{
|
{
|
||||||
const auto result = ExtractCoordinateAtLength(
|
const auto result = ExtractCoordinateAtLength(
|
||||||
distance_to_skip_over_due_to_coordinate_inaccuracies, coordinates);
|
skipping_inaccuracies_distance, coordinates);
|
||||||
BOOST_ASSERT(is_valid_result(result));
|
BOOST_ASSERT(is_valid_result(result));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -337,38 +337,9 @@ util::Coordinate CoordinateExtractor::ExtractRepresentativeCoordinate(
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsCurve(coordinates,
|
// We check offsets before curves to avoid detecting lane offsets due to large roads as curves
|
||||||
segment_distances,
|
// (think major highway here). If the road is wide, it can have quite a few coordinates in the
|
||||||
total_distance,
|
// beginning.
|
||||||
considered_lanes * 0.5 * ASSUMED_LANE_WIDTH,
|
|
||||||
turn_edge_data))
|
|
||||||
{
|
|
||||||
if (total_distance <= distance_to_skip_over_due_to_coordinate_inaccuracies)
|
|
||||||
return coordinates.back();
|
|
||||||
/*
|
|
||||||
* In curves we now have to distinguish between larger curves and tiny curves modelling the
|
|
||||||
* actual turn in the beginnig.
|
|
||||||
*
|
|
||||||
* We distinguish between turns that simply model the initial way of getting onto the
|
|
||||||
* destination lanes and the ones that performa a larger turn.
|
|
||||||
*/
|
|
||||||
const double offset =
|
|
||||||
std::min(0.5 * considered_lanes * ASSUMED_LANE_WIDTH, 0.2 * segment_distances.back());
|
|
||||||
coordinates = TrimCoordinatesToLength(std::move(coordinates), offset, segment_distances);
|
|
||||||
BOOST_ASSERT(coordinates.size() >= 2);
|
|
||||||
segment_distances.resize(coordinates.size());
|
|
||||||
segment_distances.back() = util::coordinate_calculation::haversineDistance(
|
|
||||||
*(coordinates.end() - 2), coordinates.back());
|
|
||||||
const auto vector_head = coordinates.back();
|
|
||||||
coordinates =
|
|
||||||
TrimCoordinatesToLength(std::move(coordinates), 0.5 * offset, segment_distances);
|
|
||||||
BOOST_ASSERT(coordinates.size() >= 2);
|
|
||||||
const auto result =
|
|
||||||
GetCorrectedCoordinate(turn_coordinate, coordinates.back(), vector_head);
|
|
||||||
BOOST_ASSERT(is_valid_result(result));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsDirectOffset(coordinates,
|
if (IsDirectOffset(coordinates,
|
||||||
straight_index,
|
straight_index,
|
||||||
straight_distance,
|
straight_distance,
|
||||||
@ -387,6 +358,40 @@ util::Coordinate CoordinateExtractor::ExtractRepresentativeCoordinate(
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IsCurve(coordinates,
|
||||||
|
segment_distances,
|
||||||
|
total_distance,
|
||||||
|
considered_lanes * 0.5 * ASSUMED_LANE_WIDTH,
|
||||||
|
turn_edge_data))
|
||||||
|
{
|
||||||
|
if (total_distance <= skipping_inaccuracies_distance)
|
||||||
|
return coordinates.back();
|
||||||
|
/*
|
||||||
|
* In curves we now have to distinguish between larger curves and tiny curves modelling the
|
||||||
|
* actual turn in the beginnig.
|
||||||
|
*
|
||||||
|
* We distinguish between turns that simply model the initial way of getting onto the
|
||||||
|
* destination lanes and the ones that performa a larger turn.
|
||||||
|
*/
|
||||||
|
coordinates =
|
||||||
|
TrimCoordinatesToLength(std::move(coordinates),
|
||||||
|
2 * skipping_inaccuracies_distance,
|
||||||
|
segment_distances);
|
||||||
|
BOOST_ASSERT(coordinates.size() >= 2);
|
||||||
|
segment_distances.resize(coordinates.size());
|
||||||
|
segment_distances.back() = util::coordinate_calculation::haversineDistance(
|
||||||
|
*(coordinates.end() - 2), coordinates.back());
|
||||||
|
const auto vector_head = coordinates.back();
|
||||||
|
coordinates = TrimCoordinatesToLength(std::move(coordinates),
|
||||||
|
skipping_inaccuracies_distance,
|
||||||
|
segment_distances);
|
||||||
|
BOOST_ASSERT(coordinates.size() >= 2);
|
||||||
|
const auto result =
|
||||||
|
GetCorrectedCoordinate(turn_coordinate, coordinates.back(), vector_head);
|
||||||
|
BOOST_ASSERT(is_valid_result(result));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
// skip over the first coordinates, in specific the assumed lane count. We add a small
|
// skip over the first coordinates, in specific the assumed lane count. We add a small
|
||||||
// safety factor, to not overshoot on the regression
|
// safety factor, to not overshoot on the regression
|
||||||
@ -600,6 +605,9 @@ CoordinateExtractor::GetCoordinatesAlongRoad(const NodeID intersection_node,
|
|||||||
std::back_inserter(result),
|
std::back_inserter(result),
|
||||||
compressedGeometryToCoordinate);
|
compressedGeometryToCoordinate);
|
||||||
}
|
}
|
||||||
|
// filter duplicated coordinates
|
||||||
|
auto end = std::unique(result.begin(), result.end());
|
||||||
|
result.erase(end, result.end());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -693,12 +701,12 @@ bool CoordinateExtractor::IsCurve(const std::vector<util::Coordinate> &coordinat
|
|||||||
std::tie(has_up_down_deviation, maximum_deviation_index, maximum_deviation) =
|
std::tie(has_up_down_deviation, maximum_deviation_index, maximum_deviation) =
|
||||||
[&coordinates, get_deviation]() -> std::tuple<bool, std::size_t, double> {
|
[&coordinates, get_deviation]() -> std::tuple<bool, std::size_t, double> {
|
||||||
const auto increasing = [&](const util::Coordinate lhs, const util::Coordinate rhs) {
|
const auto increasing = [&](const util::Coordinate lhs, const util::Coordinate rhs) {
|
||||||
return get_deviation(coordinates.front(), coordinates.back(), lhs) <=
|
return get_deviation(coordinates.front(), coordinates.back(), lhs) <
|
||||||
get_deviation(coordinates.front(), coordinates.back(), rhs);
|
get_deviation(coordinates.front(), coordinates.back(), rhs);
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto decreasing = [&](const util::Coordinate lhs, const util::Coordinate rhs) {
|
const auto decreasing = [&](const util::Coordinate lhs, const util::Coordinate rhs) {
|
||||||
return get_deviation(coordinates.front(), coordinates.back(), lhs) >=
|
return get_deviation(coordinates.front(), coordinates.back(), lhs) >
|
||||||
get_deviation(coordinates.front(), coordinates.back(), rhs);
|
get_deviation(coordinates.front(), coordinates.back(), rhs);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -709,16 +717,17 @@ bool CoordinateExtractor::IsCurve(const std::vector<util::Coordinate> &coordinat
|
|||||||
return std::make_tuple(
|
return std::make_tuple(
|
||||||
true, 1, get_deviation(coordinates.front(), coordinates.back(), coordinates[1]));
|
true, 1, get_deviation(coordinates.front(), coordinates.back(), coordinates[1]));
|
||||||
|
|
||||||
const auto maximum_itr =
|
const auto one_past_maximum_iter =
|
||||||
std::is_sorted_until(coordinates.begin() + 1, coordinates.end(), increasing);
|
std::is_sorted_until(coordinates.begin() + 1, coordinates.end(), increasing);
|
||||||
|
|
||||||
if (maximum_itr == coordinates.end())
|
if (one_past_maximum_iter == coordinates.end())
|
||||||
return std::make_tuple(true, coordinates.size() - 1, 0.);
|
return std::make_tuple(true, coordinates.size() - 1, 0.);
|
||||||
else if (std::is_sorted(maximum_itr, coordinates.end(), decreasing))
|
else if (std::is_sorted(one_past_maximum_iter, coordinates.end(), decreasing))
|
||||||
return std::make_tuple(
|
return std::make_tuple(true,
|
||||||
true,
|
std::distance(coordinates.begin(), one_past_maximum_iter) - 1,
|
||||||
std::distance(coordinates.begin(), maximum_itr),
|
get_deviation(coordinates.front(),
|
||||||
get_deviation(coordinates.front(), coordinates.back(), *maximum_itr));
|
coordinates.back(),
|
||||||
|
*(one_past_maximum_iter - 1)));
|
||||||
else
|
else
|
||||||
return std::make_tuple(false, 0, 0.);
|
return std::make_tuple(false, 0, 0.);
|
||||||
}();
|
}();
|
||||||
@ -731,7 +740,7 @@ bool CoordinateExtractor::IsCurve(const std::vector<util::Coordinate> &coordinat
|
|||||||
// if the maximum deviation is at a quarter of the total curve, we are probably looking at a
|
// if the maximum deviation is at a quarter of the total curve, we are probably looking at a
|
||||||
// normal turn
|
// normal turn
|
||||||
const auto distance_to_max_deviation = std::accumulate(
|
const auto distance_to_max_deviation = std::accumulate(
|
||||||
segment_distances.begin(), segment_distances.begin() + maximum_deviation_index, 0.);
|
segment_distances.begin(), segment_distances.begin() + maximum_deviation_index + 1, 0.);
|
||||||
|
|
||||||
if ((distance_to_max_deviation <= 0.35 * segment_length ||
|
if ((distance_to_max_deviation <= 0.35 * segment_length ||
|
||||||
maximum_deviation < std::max(0.3 * considered_lane_width, 0.5 * ASSUMED_LANE_WIDTH)) &&
|
maximum_deviation < std::max(0.3 * considered_lane_width, 0.5 * ASSUMED_LANE_WIDTH)) &&
|
||||||
|
Loading…
Reference in New Issue
Block a user