[Routing] Fix of rare cases
Better handling of nodes.isCandidatesAngleValid == false from IRoutingResult::GetPossibleTurns() in GetTurnDirection(). Signed-off-by: Anton Makouski <anton.makouski@gmail.com>
This commit is contained in:
parent
be8f4e064e
commit
525b03154b
5 changed files with 55 additions and 15 deletions
|
@ -429,6 +429,8 @@ void GetTurnDirectionBasic(IRoutingResult const & result, size_t const outgoingS
|
|||
("Turn candidates should be sorted by its angle field."));
|
||||
}
|
||||
|
||||
/// @todo Proper handling of isCandidatesAngleValid == False, when we don't have angles of candidates.
|
||||
|
||||
if (nodes.candidates.size() == 0)
|
||||
return;
|
||||
|
||||
|
@ -437,11 +439,10 @@ void GetTurnDirectionBasic(IRoutingResult const & result, size_t const outgoingS
|
|||
return;
|
||||
|
||||
Segment firstOutgoingSeg;
|
||||
bool const isFirstOutgoingSegValid = turnInfo.m_outgoing->m_segmentRange.GetFirstSegment(numMwmIds, firstOutgoingSeg);
|
||||
if (!isFirstOutgoingSegValid)
|
||||
if (!turnInfo.m_outgoing->m_segmentRange.GetFirstSegment(numMwmIds, firstOutgoingSeg))
|
||||
return;
|
||||
|
||||
CorrectCandidatesSegmentByOutgoing(turnInfo, firstOutgoingSeg, nodes.candidates);
|
||||
CorrectCandidatesSegmentByOutgoing(turnInfo, firstOutgoingSeg, nodes);
|
||||
|
||||
RemoveUTurnCandidate(turnInfo, numMwmIds, nodes.candidates);
|
||||
auto const & turnCandidates = nodes.candidates;
|
||||
|
@ -496,7 +497,7 @@ void GetTurnDirectionBasic(IRoutingResult const & result, size_t const outgoingS
|
|||
|
||||
turn.m_turn = intermediateDirection;
|
||||
|
||||
if (turnCandidates.size() >= 2)
|
||||
if (turnCandidates.size() >= 2 && nodes.isCandidatesAngleValid)
|
||||
CorrectRightmostAndLeftmost(turnCandidates, firstOutgoingSeg, turnAngle, turn);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,14 +8,14 @@
|
|||
|
||||
namespace routing
|
||||
{
|
||||
using namespace std;
|
||||
using namespace turns;
|
||||
|
||||
PedestrianDirectionsEngine::PedestrianDirectionsEngine(MwmDataSource & dataSource, shared_ptr<NumMwmIds> numMwmIds)
|
||||
: DirectionsEngine(dataSource, move(numMwmIds))
|
||||
{
|
||||
}
|
||||
|
||||
using namespace std;
|
||||
using namespace turns;
|
||||
|
||||
// Angles in degrees for finding route segments with no actual forks.
|
||||
double constexpr kMaxForwardAngleCandidates = 95.0;
|
||||
double constexpr kMaxForwardAngleActual = 60.0;
|
||||
|
@ -59,6 +59,11 @@ size_t PedestrianDirectionsEngine::GetTurnDirection(IRoutingResult const & resul
|
|||
return 0;
|
||||
}
|
||||
|
||||
Segment firstOutgoingSeg;
|
||||
if (!turnInfo.m_outgoing->m_segmentRange.GetFirstSegment(numMwmIds, firstOutgoingSeg))
|
||||
return 0;
|
||||
|
||||
CorrectCandidatesSegmentByOutgoing(turnInfo, firstOutgoingSeg, nodes);
|
||||
RemoveUTurnCandidate(turnInfo, numMwmIds, nodes.candidates);
|
||||
|
||||
// If there is no fork on the road we don't need to generate any turn. It is pointless because
|
||||
|
|
|
@ -182,9 +182,11 @@ UNIT_TEST(TurnsNearAltufievskoeShosseLongFakeSegmentTest)
|
|||
|
||||
integration::TestTurnCount(route, 3 /* expectedTurnCount */);
|
||||
|
||||
/// @todo Problem with outgoingTurns from RoutingEngineResult::GetPossibleTurns at (turn_m_index == 3)
|
||||
/// For some reason for both of outgoingTurns angles are 0, but it is expected to be -90 and +90.
|
||||
/// But this does not prevent from proper directions.
|
||||
// Complicated case.
|
||||
// RoutingEngineResult::GetPossibleTurns at (turn_m_index == 3)
|
||||
// return nodes with isCandidatesAngleValid and 2 candidates with m_angle == 0
|
||||
// In fact they are -90 and +90, but we don't know it.
|
||||
// But this should not prevent from proper directions.
|
||||
integration::GetNthTurn(route, 0).TestValid().TestDirection(CarDirection::TurnRight);
|
||||
integration::GetNthTurn(route, 1).TestValid().TestDirection(CarDirection::TurnLeft);
|
||||
integration::GetNthTurn(route, 2).TestValid().TestDirection(CarDirection::TurnRight);
|
||||
|
|
|
@ -269,13 +269,16 @@ double CalcTurnAngle(IRoutingResult const & result,
|
|||
}
|
||||
|
||||
void CorrectCandidatesSegmentByOutgoing(TurnInfo const & turnInfo, Segment const & firstOutgoingSeg,
|
||||
std::vector<TurnCandidate> & candidates)
|
||||
TurnCandidates & nodes)
|
||||
{
|
||||
double const turnAngle = CalcOneSegmentTurnAngle(turnInfo);
|
||||
auto IsFirstOutgoingSeg = [&firstOutgoingSeg](TurnCandidate const & turnCandidate) { return turnCandidate.m_segment == firstOutgoingSeg; };
|
||||
if (find_if(candidates.begin(), candidates.end(), IsFirstOutgoingSeg) == candidates.end())
|
||||
auto & candidates = nodes.candidates;
|
||||
auto it = find_if(candidates.begin(), candidates.end(), IsFirstOutgoingSeg);
|
||||
if (it == candidates.end())
|
||||
{
|
||||
double const turnAngle = CalcOneSegmentTurnAngle(turnInfo);
|
||||
auto DoesAngleMatch = [&turnAngle](TurnCandidate const & turnCandidate) { return base::AlmostEqualAbs(turnCandidate.m_angle, turnAngle, 0.001); };
|
||||
auto DoesAngleMatch = [&turnAngle](TurnCandidate const & turnCandidate)
|
||||
{ return base::AlmostEqualAbs(turnCandidate.m_angle, turnAngle, 0.001) || abs(turnCandidate.m_angle) + abs(turnAngle) > 359.999; };
|
||||
auto it = find_if(candidates.begin(), candidates.end(), DoesAngleMatch);
|
||||
if (it != candidates.end())
|
||||
{
|
||||
|
@ -283,6 +286,35 @@ void CorrectCandidatesSegmentByOutgoing(TurnInfo const & turnInfo, Segment const
|
|||
ASSERT(it->m_segment.GetSegmentIdx() == firstOutgoingSeg.GetSegmentIdx() && it->m_segment.IsForward() == firstOutgoingSeg.IsForward(), ());
|
||||
it->m_segment = firstOutgoingSeg;
|
||||
}
|
||||
else if (nodes.isCandidatesAngleValid)
|
||||
ASSERT(false, ("Can't match any candidate with firstOutgoingSegment but isCandidatesAngleValid == true."));
|
||||
else
|
||||
{
|
||||
LOG(LWARNING, ("Can't match any candidate with firstOutgoingSegment and isCandidatesAngleValid == false"));
|
||||
if (candidates.size() == 1)
|
||||
{
|
||||
ASSERT(candidates.front().m_segment.GetMwmId() != firstOutgoingSeg.GetMwmId(), ());
|
||||
ASSERT(candidates.front().m_segment.GetSegmentIdx() == firstOutgoingSeg.GetSegmentIdx() && candidates.front().m_segment.IsForward() == firstOutgoingSeg.IsForward(), ());
|
||||
candidates.front().m_segment = firstOutgoingSeg;
|
||||
nodes.isCandidatesAngleValid = true;
|
||||
LOG(LWARNING, ("but since candidates.size() == 1, this was fixed."));
|
||||
}
|
||||
else
|
||||
LOG(LWARNING, ("and since candidates.size() > 1, this can't be fixed."));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nodes.isCandidatesAngleValid)
|
||||
ASSERT((base::AlmostEqualAbs(it->m_angle, turnAngle, 0.001) || abs(it->m_angle) + abs(turnAngle) > 359.999), ());
|
||||
else
|
||||
{
|
||||
it->m_angle = turnAngle;
|
||||
if (candidates.size() == 1)
|
||||
nodes.isCandidatesAngleValid = true;
|
||||
else
|
||||
LOG(LWARNING, ("isCandidatesAngleValid == false, and this can't be fixed."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ bool HasSingleForwardTurn(TurnCandidates const & turnCandidates, float maxForwar
|
|||
// It may happened if |firstOutgoingSeg| and candidates in |turnCandidates| are from different mwms.
|
||||
// Let's identify it in turnCandidates by angle and update according turnCandidate.
|
||||
void CorrectCandidatesSegmentByOutgoing(TurnInfo const & turnInfo, Segment const & firstOutgoingSeg,
|
||||
std::vector<TurnCandidate> & candidates);
|
||||
TurnCandidates & nodes);
|
||||
|
||||
/*!
|
||||
* \brief Returns ingoing point or outgoing point for turns.
|
||||
|
|
Reference in a new issue