[routing] Remove unnecessary "keep left/right" directions from the route #2397

Merged
AntonM030481 merged 4 commits from navigation-turn-directions into master 2022-04-15 19:11:41 +00:00

View file

@ -129,7 +129,7 @@ bool GetTurnHighwayClasses(TurnCandidates const & possibleTurns, TurnInfo const
if (t.m_segment == firstOutgoingSegment || t.m_segment == inversedLastIngoingSegment)
continue;
ftypes::HighwayClass const highwayClass = t.m_highwayClass;
// Note. The bigger road the less HighwayClass value.
// @note The bigger is the road, the lesser is HighwayClass value.
if (static_cast<int>(highwayClass) < static_cast<int>(turnHighwayClasses.m_biggestPossibleTurnRoadClass))
turnHighwayClasses.m_biggestPossibleTurnRoadClass = highwayClass;
}
@ -146,7 +146,7 @@ bool GetTurnHighwayClasses(TurnCandidates const & possibleTurns, TurnInfo const
if (turnHighwayClasses.m_biggestPossibleTurnRoadClass == ftypes::HighwayClass::Count)
return false; // No outgoing segments except for the route.
// Note. The bigger road the less HighwayClass value.
// @note The bigger is the road, the lesser is HighwayClass value.
turnHighwayClasses.m_smallestRouteRoadClass =
static_cast<ftypes::HighwayClass>(max(static_cast<int>(turnInfo.m_ingoing.m_highwayClass),
static_cast<int>(turnInfo.m_outgoing.m_highwayClass)));
@ -162,16 +162,16 @@ bool GetTurnHighwayClasses(TurnCandidates const & possibleTurns, TurnInfo const
return true;
}
/// * \returns false when
/// * \returns true when
/// * - the route leads from one big road to another one;
/// * - and the other possible turns lead to small roads;
/// * Returns true otherwise.
/// * Returns false otherwise.
/// \param possibleTurns is all possible ways out from a junction.
/// \param turnInfo is information about ingoing and outgoing segments of the route.
/// \param carDirection is a direction about the current turn if it's available.
/// If not, CarDirection::None should be passed.
bool KeepTurnByHighwayClass(TurnCandidates const & possibleTurns, TurnInfo const & turnInfo,
NumMwmIds const & numMwmIds, CarDirection carDirection)
bool DiscardTurnByHighwayClass(TurnCandidates const & possibleTurns, TurnInfo const & turnInfo,
NumMwmIds const & numMwmIds, CarDirection carDirection)
{
// Maximum difference between HighwayClasses of the route segments and
// the possible way segments to keep the junction as a turn.
@ -180,8 +180,9 @@ bool KeepTurnByHighwayClass(TurnCandidates const & possibleTurns, TurnInfo const
int constexpr kMaxHighwayClassDiffForService = 1;
TurnHighwayClasses turnHighwayClasses;
// Looks like a bug. If no info received turn should not be discarded
if (!GetTurnHighwayClasses(possibleTurns, turnInfo, numMwmIds, turnHighwayClasses))
return false;
return true;
int const diff =
static_cast<int>(turnHighwayClasses.m_biggestPossibleTurnRoadClass) - static_cast<int>(turnHighwayClasses.m_smallestRouteRoadClass);
@ -190,7 +191,64 @@ bool KeepTurnByHighwayClass(TurnCandidates const & possibleTurns, TurnInfo const
(diff >= kMaxHighwayClassDiffForService && turnHighwayClasses.m_biggestPossibleTurnRoadClass == ftypes::HighwayClass::Service))
{
// The turn shall be removed if the route goes near small roads.
return true;
biodranik commented 2022-04-14 15:47:30 +00:00 (Migrated from github.com)
Review

Незавершённое предложение?

Незавершённое предложение?
biodranik commented 2022-04-14 15:47:45 +00:00 (Migrated from github.com)
Review

Можно выровнять после скобки.

Можно выровнять после скобки.
biodranik commented 2022-04-14 15:52:30 +00:00 (Migrated from github.com)
Review
    // @note The bigger is the road, the lesser is HighwayClass value.
```suggestion // @note The bigger is the road, the lesser is HighwayClass value. ```
biodranik commented 2022-04-14 15:53:42 +00:00 (Migrated from github.com)
Review
      // Any alternative turn to a bigger road keeps the turn direction.
```suggestion // Any alternative turn to a bigger road keeps the turn direction. ```
biodranik commented 2022-04-14 15:54:53 +00:00 (Migrated from github.com)
Review
      // Any alternative turn to a similar road keeps the turn direction if the turn's angle is less than
      // kMaxAbsAngleSameRoadClass degrees (wider than SlightTurn).
```suggestion // Any alternative turn to a similar road keeps the turn direction if the turn's angle is less than // kMaxAbsAngleSameRoadClass degrees (wider than SlightTurn). ```
biodranik commented 2022-04-14 15:56:01 +00:00 (Migrated from github.com)
Review
      // Any alternative turn to a smaller road keeps the turn direction if it's GoStraight or SlightTurn.
```suggestion // Any alternative turn to a smaller road keeps the turn direction if it's GoStraight or SlightTurn. ```
AntonM030481 commented 2022-04-14 16:13:33 +00:00 (Migrated from github.com)
Review

да. завершил.

да. завершил.
AntonM030481 commented 2022-04-14 16:16:00 +00:00 (Migrated from github.com)
Review

ок. поправил еще в 2 местах откуда скопировал

ок. поправил еще в 2 местах откуда скопировал
AntonM030481 commented 2022-04-14 16:18:26 +00:00 (Migrated from github.com)
Review

ок

ок
AntonM030481 commented 2022-04-14 16:19:41 +00:00 (Migrated from github.com)
Review

ок

ок
AntonM030481 commented 2022-04-14 16:20:44 +00:00 (Migrated from github.com)
Review

ок

ок
AntonM030481 commented 2022-04-14 16:26:50 +00:00 (Migrated from github.com)
Review

непонятно

непонятно
vng commented 2022-04-14 19:48:58 +00:00 (Migrated from github.com)
Review
foo(int x,
    int y)
``` foo(int x, int y) ```
biodranik commented 2022-04-15 10:18:03 +00:00 (Migrated from github.com)
Review
bool KeepTurnByAlignedAlternatives(TurnCandidates const & possibleTurns, TurnInfo const & turnInfo,
                                   NumMwmIds const & numMwmIds)
```suggestion bool KeepTurnByAlignedAlternatives(TurnCandidates const & possibleTurns, TurnInfo const & turnInfo, NumMwmIds const & numMwmIds) ```
AntonM030481 commented 2022-04-15 13:57:57 +00:00 (Migrated from github.com)
Review

спасибо. понял.

спасибо. понял.
AntonM030481 commented 2022-04-15 15:15:07 +00:00 (Migrated from github.com)
Review

done

done
}
return false;
}
/// * \returns false when
/// * - any alternative turn to a bigger road
/// * - or any alternative turn to a similar road if the turn's angle is less than kMaxAbsAngleSameRoadClass degrees (wider than SlightTurn)
/// * - or any alternative turn to a smaller road if it's GoStraight or SlightTurn.
/// * Returns true otherwise.
/// \param possibleTurns is all possible ways out from a junction.
/// \param turnInfo is information about ingoing and outgoing segments of the route.
/// it is supposed that current turn is GoStraight or SlightTurn
bool DiscardTurnByNoAlignedAlternatives(TurnCandidates const & possibleTurns, TurnInfo const & turnInfo,
NumMwmIds const & numMwmIds)
{
double constexpr kMaxAbsAngleSameRoadClass = 70.0;
ftypes::HighwayClass outgoingRouteRoadClass = turnInfo.m_outgoing.m_highwayClass;
// The turn should be kept if there's no any information about feature id of outgoing segment
// just to be on the safe side. It may happen in case of outgoing segment is a finish segment.
Segment firstOutgoingSegment;
if (!turnInfo.m_outgoing.m_segmentRange.GetFirstSegment(numMwmIds, firstOutgoingSegment))
return false;
Segment inversedLastIngoingSegment;
if (!turnInfo.m_ingoing.m_segmentRange.GetLastSegment(numMwmIds, inversedLastIngoingSegment))
return false;
biodranik commented 2022-04-15 17:53:31 +00:00 (Migrated from github.com)
Review

Момент, если false исправлено на true, то коммент надо дополнить.
// Previous version was returning false and it looked like a bug. If no info received turn should not be discarded.

Момент, если false исправлено на true, то коммент надо дополнить. // Previous version was returning false and it looked like a bug. If no info received turn should not be discarded.
AntonM030481 commented 2022-04-15 18:37:35 +00:00 (Migrated from github.com)
Review

Я не исправлял логику.
False исправлено на True, потому что функция была инверсно переименована, и все return были инвертированы.

Я не исправлял логику. False исправлено на True, потому что функция была инверсно переименована, и все return были инвертированы.
inversedLastIngoingSegment.Inverse();
for (auto const & t : possibleTurns.candidates)
{
// Let's consider all outgoing segments except for
// (1) route outgoing segment
// (2) a U-turn segment (inversedLastIngoingSegment)
if (t.m_segment == firstOutgoingSegment || t.m_segment == inversedLastIngoingSegment)
continue;
ftypes::HighwayClass const highwayClass = t.m_highwayClass;
// @note The bigger is the road, the lesser is HighwayClass value.
if (static_cast<int>(highwayClass) < static_cast<int>(outgoingRouteRoadClass))
{
// Any alternative turn to a bigger road keeps the turn direction.
return false;
}
else if (highwayClass == outgoingRouteRoadClass)
{
// Any alternative turn to a similar road keeps the turn direction if the turn's angle is less than
// kMaxAbsAngleSameRoadClass degrees (wider than SlightTurn).
if (fabs(t.m_angle) < kMaxAbsAngleSameRoadClass)
return false;
}
else // static_cast<int>(highwayClass) > static_cast<int>(outgoingRouteRoadClass)
{
// Any alternative turn to a smaller road keeps the turn direction if it's GoStraight or SlightTurn.
if (IsGoStraightOrSlightTurn(IntermediateDirection(t.m_angle)))
return false;
}
}
return true;
}
@ -488,7 +546,7 @@ bool GetNextCrossSegmentRoutePoint(IRoutingResult const & result, RoutePointInde
return true;
}
if (!KeepTurnByHighwayClass(possibleTurns, turnInfo, numMwmIds, CarDirection::None))
if (DiscardTurnByHighwayClass(possibleTurns, turnInfo, numMwmIds, CarDirection::None))
{
// Taking the next point of the next segment.
nextIndex = {index.m_segmentIndex + 1, 1 /* m_pathIndex */};
@ -1140,15 +1198,18 @@ void GetTurnDirection(IRoutingResult const & result, size_t outgoingSegmentIndex
}
// Note 1. If the road significantly changes its direction this turn shall be kept here.
// Note 2. If there's only one exit from this junction (nodes.candidates.size() != 1)
// this turn should be kept.
// Note 2. If there's only one exit from this junction (nodes.candidates.size() == 1)
// this turn should be kept (because it was kept by previous logic as an exception).
// Note 3. Keeping a turn at this point means that the decision to keep this turn or not
// will be made after.
if (!turn.m_keepAnyway && IsGoStraightOrSlightTurn(turn.m_turn) && nodes.candidates.size() != 1 &&
!KeepTurnByHighwayClass(nodes, turnInfo, numMwmIds, turn.m_turn))
if (!turn.m_keepAnyway && IsGoStraightOrSlightTurn(turn.m_turn) && nodes.candidates.size() != 1)
{
biodranik commented 2022-04-14 15:58:06 +00:00 (Migrated from github.com)
Review
  1. Для чего проверка nodes.candidates.size() != 1 ?
  2. candidates.size() не может быть 0?
1. Для чего проверка `nodes.candidates.size() != 1` ? 2. candidates.size() не может быть 0?
AntonM030481 commented 2022-04-14 16:41:51 +00:00 (Migrated from github.com)
Review
  1. Хороший вопрос.
    Просто скопировал как в KeepTurnByHighwayClass.
    Я не вижу проблем с nodes.candidates.size() == 1.
  2. Предположительно, не может.
    @vng
1. Хороший вопрос. Просто скопировал как в KeepTurnByHighwayClass. Я не вижу проблем с `nodes.candidates.size() == 1`. 2. Предположительно, не может. @vng
vng commented 2022-04-14 19:47:50 +00:00 (Migrated from github.com)
Review

Не может, тут все хорошо и да по аналогии с предидущим сравнением.
Эквивалентно nodes.candidates.size() > 1, проверяем когда больше одной альтернативы

Не может, тут все хорошо и да по аналогии с предидущим сравнением. Эквивалентно nodes.candidates.size() > 1, проверяем когда больше одной альтернативы
biodranik commented 2022-04-14 20:05:41 +00:00 (Migrated from github.com)
Review

Тогда надо не копипастить, а сделать так:

  if (!turn.m_keepAnyway && IsGoStraightOrSlightTurn(turn.m_turn) && nodes.candidates.size() != 1)
  {
    if (!KeepTurnByHighwayClass(nodes, turnInfo, numMwmIds, turn.m_turn) ||
        !KeepTurnByAlignedAlternatives(nodes, turnInfo, numMwmIds))
    {
      turn.m_turn = CarDirection::None;
      return;
    }
  }
Тогда надо не копипастить, а сделать так: ```C++ if (!turn.m_keepAnyway && IsGoStraightOrSlightTurn(turn.m_turn) && nodes.candidates.size() != 1) { if (!KeepTurnByHighwayClass(nodes, turnInfo, numMwmIds, turn.m_turn) || !KeepTurnByAlignedAlternatives(nodes, turnInfo, numMwmIds)) { turn.m_turn = CarDirection::None; return; } } ```
AntonM030481 commented 2022-04-15 08:49:49 +00:00 (Migrated from github.com)
Review

вопросы к @vng :

Note 2. If there's only one exit from this junction (nodes.candidates.size() != 1)
  // this turn should be kept.
  • если выезд только один, то nodes.candidates.size() == 1, а не наоборот?
  • если выезд только один - то почему именно в этом случае нужно оставить поворот? Если этого условия не будет, то оба KeepTurnBy... превратят SlightTurn в None. По идее, он и так уже должен быть таким к этому моменту. А если например кандидата 2: вперед и назад - то почему поворот не обязательно оставлять?
вопросы к @vng : ``` Note 2. If there's only one exit from this junction (nodes.candidates.size() != 1) // this turn should be kept. ``` - если выезд только один, то nodes.candidates.size() == 1, а не наоборот? - если выезд только один - то почему именно в этом случае нужно оставить поворот? Если этого условия не будет, то оба KeepTurnBy... превратят SlightTurn в None. По идее, он и так уже должен быть таким к этому моменту. А если например кандидата 2: вперед и назад - то почему поворот не обязательно оставлять?
vng commented 2022-04-15 13:28:50 +00:00 (Migrated from github.com)
Review

Я эти комменты не писал :) но предполагаю что:

  • Для одного exit когда nodes.candidates.size() == 1, мы НЕ заходим в KeepTurnByHighwayClass и turn точно сохраняется. Можете переписать этот коммент на понятный :)
  • Вероятно он остается, потому что вычисляется по какому-то другому жесткому условию раньше (например это может быть пересадка на паром), тут не скажу точно. Пусть так и остается, пока не увидим явный косяк
Я эти комменты не писал :) но предполагаю что: - Для одного exit когда nodes.candidates.size() == 1, мы НЕ заходим в KeepTurnByHighwayClass и turn точно сохраняется. Можете переписать этот коммент на понятный :) - Вероятно он остается, потому что вычисляется по какому-то другому жесткому условию раньше (например это может быть пересадка на паром), тут не скажу точно. Пусть так и остается, пока не увидим явный косяк
AntonM030481 commented 2022-04-15 13:41:16 +00:00 (Migrated from github.com)
Review

Меняю, если нет возражений, на

  // Note 2. If there's only one exit from this junction (nodes.candidates.size() == 1)
  // this turn should be kept (because if was kept by previous logic as an exception).
Меняю, если нет возражений, на ``` // Note 2. If there's only one exit from this junction (nodes.candidates.size() == 1) // this turn should be kept (because if was kept by previous logic as an exception). ```
AntonM030481 commented 2022-04-15 13:51:39 +00:00 (Migrated from github.com)
Review

После перехода на

if (!KeepTurnByHighwayClass(nodes, turnInfo, numMwmIds, turn.m_turn) ||
        !KeepTurnByAlignedAlternatives(nodes, turnInfo, numMwmIds))

Стала понятна немного некорректная логика в названиях функций.
Исходя из названия, должно быть так

if (! (KeepTurnByHighwayClass(nodes, turnInfo, numMwmIds, turn.m_turn) ||
        KeepTurnByAlignedAlternatives(nodes, turnInfo, numMwmIds)))

те если ни одной причины нет, чтобы сохранить поворот - то мы его удаляем.
а у нас получается, что если причины 1 нет - удаляем, если причины 2 нет - удаляем.

Предлагаю инвертировать функции на DiscardTurnByHighwayClass и DiscardTurnByNoAlignedAlternatives.
Тогда получится:

if (DiscardTurnByHighwayClass(nodes, turnInfo, numMwmIds, turn.m_turn) ||
    DiscardTurnByNoAlignedAlternatives(nodes, turnInfo, numMwmIds))
После перехода на ``` if (!KeepTurnByHighwayClass(nodes, turnInfo, numMwmIds, turn.m_turn) || !KeepTurnByAlignedAlternatives(nodes, turnInfo, numMwmIds)) ``` Стала понятна немного некорректная логика в названиях функций. Исходя из названия, должно быть так ``` if (! (KeepTurnByHighwayClass(nodes, turnInfo, numMwmIds, turn.m_turn) || KeepTurnByAlignedAlternatives(nodes, turnInfo, numMwmIds))) ``` те если ни одной причины нет, чтобы сохранить поворот - то мы его удаляем. а у нас получается, что если причины 1 нет - удаляем, если причины 2 нет - удаляем. Предлагаю инвертировать функции на DiscardTurnByHighwayClass и DiscardTurnByNoAlignedAlternatives. Тогда получится: ``` if (DiscardTurnByHighwayClass(nodes, turnInfo, numMwmIds, turn.m_turn) || DiscardTurnByNoAlignedAlternatives(nodes, turnInfo, numMwmIds)) ```
vng commented 2022-04-15 14:15:22 +00:00 (Migrated from github.com)
Review

Согласен на переименовать. Тогда надо аккуратно внутри них инвертировать true/false и проверить актуальность комментов к ним.

Согласен на переименовать. Тогда надо аккуратно внутри них инвертировать true/false и проверить актуальность комментов к ним.
AntonM030481 commented 2022-04-15 14:27:55 +00:00 (Migrated from github.com)
Review

в процессе переименования обратил внимание на

bool KeepTurnByHighwayClass()
  ...
  if (!GetTurnHighwayClasses(possibleTurns, turnInfo, numMwmIds, turnHighwayClasses))
    return false;
в процессе переименования обратил внимание на ``` bool KeepTurnByHighwayClass() ... if (!GetTurnHighwayClasses(possibleTurns, turnInfo, numMwmIds, turnHighwayClasses)) return false; ```
AntonM030481 commented 2022-04-15 14:31:58 +00:00 (Migrated from github.com)
Review

Исходя из описания GetTurnHighwayClasses()
// If it's possible fills |turnHighwayClasses| and returns true, and returns false otherwise.
это выглядит ошибкой: если данные не получили - то вернуть false и удалить поворот.
должно быть наоборот? если данные не получили - то не трогать поворот на всякий случай.

Исходя из описания GetTurnHighwayClasses() // If it's possible fills |turnHighwayClasses| and returns true, and returns false otherwise. это выглядит ошибкой: если данные не получили - то вернуть false и удалить поворот. должно быть наоборот? если данные не получили - то не трогать поворот на всякий случай.
AntonM030481 commented 2022-04-15 14:38:51 +00:00 (Migrated from github.com)
Review

Есть подозрение, что
GetTurnHighwayClasses()
не совсем соответствует описанию в отношении возвращаемого значения.

Есть подозрение, что GetTurnHighwayClasses() не совсем соответствует описанию в отношении возвращаемого значения.
AntonM030481 commented 2022-04-15 15:14:05 +00:00 (Migrated from github.com)
Review

Оставил старую логику (инвертировав true на false), добавив комент:

bool DiscardTurnByHighwayClass(TurnCandidates const & possibleTurns, TurnInfo const & turnInfo,
                               NumMwmIds const & numMwmIds, CarDirection carDirection)
...
  // Looks like a bug. If no info received turn should not be discarded
  if (!GetTurnHighwayClasses(possibleTurns, turnInfo, numMwmIds, turnHighwayClasses))
    return true;
Оставил старую логику (инвертировав true на false), добавив комент: ``` bool DiscardTurnByHighwayClass(TurnCandidates const & possibleTurns, TurnInfo const & turnInfo, NumMwmIds const & numMwmIds, CarDirection carDirection) ... // Looks like a bug. If no info received turn should not be discarded if (!GetTurnHighwayClasses(possibleTurns, turnInfo, numMwmIds, turnHighwayClasses)) return true; ```
turn.m_turn = CarDirection::None;
return;
if (DiscardTurnByHighwayClass(nodes, turnInfo, numMwmIds, turn.m_turn) ||
DiscardTurnByNoAlignedAlternatives(nodes, turnInfo, numMwmIds))
{
turn.m_turn = CarDirection::None;
return;
}
}
if (IsGoStraightOrSlightTurn(turn.m_turn))