LCOV - code coverage report
Current view: top level - src/structured - RssNonIntersectionConstellationChecker.cpp (source / functions) Hit Total Coverage
Test: ad_rss Lines: 173 179 96.6 %
Date: 2025-07-22 06:53:46 Functions: 6 6 100.0 %
Branches: 107 148 72.3 %

           Branch data     Line data    Source code
       1                 :            : // ----------------- BEGIN LICENSE BLOCK ---------------------------------
       2                 :            : //
       3                 :            : // Copyright (C) 2018-2021 Intel Corporation
       4                 :            : //
       5                 :            : // SPDX-License-Identifier: LGPL-2.1-only
       6                 :            : //
       7                 :            : // ----------------- END LICENSE BLOCK -----------------------------------
       8                 :            : 
       9                 :            : #include "ad/rss/structured/RssNonIntersectionConstellationChecker.hpp"
      10                 :            : #include "ad/rss/core/Logging.hpp"
      11                 :            : #include "ad/rss/state/RssStateOperation.hpp"
      12                 :            : #include "ad/rss/structured/RssFormulas.hpp"
      13                 :            : 
      14                 :            : namespace ad {
      15                 :            : namespace rss {
      16                 :            : namespace structured {
      17                 :            : 
      18                 :      66191 : bool RssNonIntersectionConstellationChecker::calculateRssStateNonIntersection(
      19                 :            :   world::TimeIndex const &time_index, core::RelativeConstellation const &constellation, state::RssState &rssState)
      20                 :            : {
      21         [ +  + ]:      66191 :   if (time_index != mCurrentTimeIndex)
      22                 :            :   {
      23                 :       3109 :     mLastStatesBeforeDangerThresholdTime.swap(mNewStatesBeforeDangerThresholdTime);
      24                 :       3109 :     mNewStatesBeforeDangerThresholdTime.clear();
      25                 :       3109 :     mCurrentTimeIndex = time_index;
      26                 :            :   }
      27                 :            : 
      28                 :      66191 :   rssState.constellation_id = constellation.constellation_id;
      29                 :      66191 :   rssState.constellation_type = constellation.constellation_type;
      30                 :      66191 :   rssState.ego_id = constellation.ego_id;
      31                 :      66191 :   rssState.object_id = constellation.object_id;
      32                 :            : 
      33                 :      66191 :   rssState.longitudinal_state.is_safe = false;
      34                 :      66191 :   rssState.longitudinal_state.response = state::LongitudinalResponse::BrakeMin;
      35                 :      66191 :   rssState.longitudinal_state.alpha_lon = constellation.ego_state.dynamics.alpha_lon;
      36                 :            : 
      37                 :      66191 :   rssState.lateral_state_left.is_safe = false;
      38                 :      66191 :   rssState.lateral_state_left.response = state::LateralResponse::BrakeMin;
      39                 :      66191 :   rssState.lateral_state_left.alpha_lat = constellation.ego_state.dynamics.alpha_lat;
      40                 :            : 
      41                 :      66191 :   rssState.lateral_state_right.is_safe = false;
      42                 :      66191 :   rssState.lateral_state_right.response = state::LateralResponse::BrakeMin;
      43                 :      66191 :   rssState.lateral_state_right.alpha_lat = constellation.ego_state.dynamics.alpha_lat;
      44                 :            : 
      45                 :      66191 :   bool result = false;
      46                 :            :   // first calculate the current state
      47         [ +  + ]:      66191 :   if (constellation.constellation_type == world::ConstellationType::SameDirection)
      48                 :            :   {
      49         [ +  - ]:      65123 :     result = calculateRssStateSameDirection(constellation, rssState);
      50                 :            :   }
      51         [ +  - ]:       1068 :   else if (constellation.constellation_type == world::ConstellationType::OppositeDirection)
      52                 :            :   {
      53         [ +  - ]:       1068 :     result = calculateRssStateOppositeDirection(constellation, rssState);
      54                 :            :   }
      55                 :            :   else
      56                 :            :   {
      57   [ #  #  #  # ]:          0 :     core::getLogger()->error("RssNonIntersectionConstellationChecker::calculateRssStateNonIntersection[{}->{}]>> "
      58                 :            :                              "constellation type invalid {}",
      59                 :          0 :                              rssState.ego_id,
      60         [ #  # ]:          0 :                              rssState.object_id,
      61                 :            :                              constellation);
      62                 :            :   }
      63                 :            : 
      64                 :            :   // second calculate proper response in respect to the state before danger threshold according to definition 10 of the
      65                 :            :   // RSS paper v6
      66                 :      66191 :   RssSafeState lastStateBeforeDangerThresholdTimeToRemember;
      67         [ +  + ]:      66191 :   if (isDangerous(rssState))
      68                 :            :   {
      69                 :            :     auto const previousLastStateBeforeDangerThresholdTime
      70         [ +  - ]:      13314 :       = mLastStatesBeforeDangerThresholdTime.find(rssState.constellation_id);
      71         [ +  + ]:      13314 :     if (previousLastStateBeforeDangerThresholdTime != mLastStatesBeforeDangerThresholdTime.end())
      72                 :            :     {
      73                 :       1278 :       lastStateBeforeDangerThresholdTimeToRemember = previousLastStateBeforeDangerThresholdTime->second;
      74                 :            :     }
      75                 :            :     else
      76                 :            :     {
      77                 :            :       // This is the first time the constellation appears and it is immediately in dangerous state
      78                 :            :       // in same direction use-case we are able to deduce the non dangereous state:
      79                 :            :       // if the vehicles are actually overlapping in their lateral dimension, the vehicles are following each other
      80                 :            :       // Therefore, we don't require to break in lateral direction
      81                 :            :       // and can store a previous longitudinal safe state
      82                 :            :       // Example: something dropping from a vehicle driving in front or let the tracker of the perception system
      83                 :            :       // just loose the track of a vehicle in front/at back and assign it a new object id
      84                 :            :       // In such cases, a lateral proper response with breakMin would even prevent from an evasive maneuver
      85                 :            :       // which might want to evade laterally
      86         [ +  + ]:      12036 :       if ((constellation.constellation_type == world::ConstellationType::SameDirection)
      87         [ +  + ]:      12028 :           && ((constellation.relative_position.lateral_position == core::LateralRelativePosition::OverlapLeft)
      88         [ +  + ]:      12026 :               || (constellation.relative_position.lateral_position == core::LateralRelativePosition::Overlap)
      89         [ +  + ]:         20 :               || (constellation.relative_position.lateral_position == core::LateralRelativePosition::OverlapRight)))
      90                 :            :       {
      91                 :      12009 :         lastStateBeforeDangerThresholdTimeToRemember.longitudinalSafe = true;
      92                 :      12009 :         lastStateBeforeDangerThresholdTimeToRemember.lateralSafe = false;
      93   [ +  -  +  - ]:      24018 :         core::getLogger()->info(
      94                 :            :           "RssNonIntersectionConstellationChecker[{}->{}]>> State is dangerous spontaneously and relative position "
      95                 :            :           "already overlaps laterally. Asuming longitudinal safe at danger threshold time. {} {}",
      96                 :      12009 :           rssState.ego_id,
      97         [ +  - ]:      12009 :           rssState.object_id,
      98                 :            :           rssState,
      99                 :            :           constellation);
     100                 :            :       }
     101                 :            :     }
     102                 :            :   }
     103                 :            :   else
     104                 :            :   {
     105                 :      52877 :     lastStateBeforeDangerThresholdTimeToRemember.longitudinalSafe = isLongitudinalSafe(rssState);
     106                 :      52877 :     lastStateBeforeDangerThresholdTimeToRemember.lateralSafe = isLateralSafe(rssState);
     107                 :            :   }
     108                 :            : 
     109         [ +  + ]:      66191 :   if ((lastStateBeforeDangerThresholdTimeToRemember.lateralSafe)
     110         [ +  + ]:       1537 :       && (lastStateBeforeDangerThresholdTimeToRemember.longitudinalSafe))
     111                 :            :   {
     112                 :            :     // Both longitudinal and lateral distances became dangerous at the same time
     113         [ -  + ]:        321 :     if (isDangerous(rssState))
     114                 :            :     {
     115   [ #  #  #  # ]:          0 :       core::getLogger()->info(
     116                 :            :         "RssNonIntersectionConstellationChecker[{}->{}]>> State is dangerous (t_b == t_b,lon == t_b,lat) {}",
     117                 :          0 :         rssState.ego_id,
     118         [ #  # ]:          0 :         rssState.object_id,
     119                 :            :         rssState);
     120                 :            :     }
     121                 :            :   }
     122         [ +  + ]:      65870 :   else if (lastStateBeforeDangerThresholdTimeToRemember.lateralSafe)
     123                 :            :   {
     124                 :            :     // @todo: Handling of a cut-in by a leading vehicle as stated in definitions 11-13 of the RSS paper v6
     125                 :            :     //        will be handled outside of this function. As a consequence.
     126                 :            :     //        There is currently no response for a cut-in of a leading vehicle
     127                 :       1216 :     rssState.longitudinal_state.response = state::LongitudinalResponse::None;
     128         [ +  + ]:       1216 :     if (isDangerous(rssState))
     129                 :            :     {
     130   [ +  -  +  - ]:        396 :       core::getLogger()->info("RssNonIntersectionConstellationChecker[{}->{}]>> State is dangerous (t_b == t_b,lat) No "
     131                 :            :                               "longitudinal response: {}",
     132                 :        198 :                               rssState.ego_id,
     133         [ +  - ]:        198 :                               rssState.object_id,
     134                 :            :                               rssState);
     135                 :            :     }
     136                 :            :   }
     137                 :     129308 :   else if (lastStateBeforeDangerThresholdTimeToRemember.longitudinalSafe
     138   [ +  +  +  +  :      64654 :            && (getRightBorderObjectId() != rssState.object_id) && (getLeftBorderObjectId() != rssState.object_id))
             +  -  +  + ]
     139                 :            :   {
     140                 :      64588 :     rssState.lateral_state_left.response = state::LateralResponse::None;
     141                 :      64588 :     rssState.lateral_state_right.response = state::LateralResponse::None;
     142         [ +  + ]:      64588 :     if (isDangerous(rssState))
     143                 :            :     {
     144   [ +  -  +  - ]:      26102 :       core::getLogger()->info(
     145                 :            :         "RssNonIntersectionConstellationChecker[{}->{}]>> State is dangerous (t_b == t_b,lon) No lateral response: {}",
     146                 :      13051 :         rssState.ego_id,
     147         [ +  - ]:      13051 :         rssState.object_id,
     148                 :            :         rssState);
     149                 :            :     }
     150                 :            :   }
     151                 :            :   else
     152                 :            :   {
     153                 :            :     // no non dangerous state available: the constellation appeared spontaneously being unsafe immediately
     154         [ +  + ]:         66 :     if (isDangerous(rssState))
     155                 :            :     {
     156   [ +  -  +  - ]:        130 :       core::getLogger()->info(
     157                 :            :         "RssNonIntersectionConstellationChecker[{}->{}]>> State is dangerous, no non dangerous state available {}",
     158                 :         65 :         rssState.ego_id,
     159         [ +  - ]:         65 :         rssState.object_id,
     160                 :            :         rssState);
     161                 :            :     }
     162                 :            :   }
     163                 :            : 
     164                 :            :   // store state for the next time step
     165                 :            :   auto const insertResult
     166         [ +  + ]:      66191 :     = mNewStatesBeforeDangerThresholdTime.insert(RssSafeStateBeforeDangerThresholdTimeMap::value_type(
     167                 :      66191 :       constellation.constellation_id, lastStateBeforeDangerThresholdTimeToRemember));
     168                 :            : 
     169         [ +  + ]:      66180 :   if (!insertResult.second)
     170                 :            :   {
     171                 :      11976 :     result = false;
     172   [ +  -  +  - ]:      23952 :     core::getLogger()->error("RssNonIntersectionConstellationChecker[{}->{}]>> map insertion failed unexpectedly",
     173                 :      11976 :                              rssState.ego_id,
     174         [ +  - ]:      11976 :                              rssState.object_id);
     175                 :            :   }
     176                 :            : 
     177                 :      66180 :   return result;
     178                 :            : }
     179                 :            : 
     180                 :      65123 : bool RssNonIntersectionConstellationChecker::calculateRssStateSameDirection(
     181                 :            :   core::RelativeConstellation const &constellation, state::RssState &rssState)
     182                 :            : {
     183                 :      65123 :   bool result = calculateLongitudinalRssStateSameDirection(constellation, rssState.longitudinal_state);
     184         [ +  + ]:      65123 :   if (result)
     185                 :            :   {
     186                 :      53122 :     result = calculateLateralRssState(constellation, rssState.lateral_state_left, rssState.lateral_state_right);
     187                 :            :   }
     188                 :      65123 :   return result;
     189                 :            : }
     190                 :            : 
     191                 :       1068 : bool RssNonIntersectionConstellationChecker::calculateRssStateOppositeDirection(
     192                 :            :   core::RelativeConstellation const &constellation, state::RssState &rssState)
     193                 :            : {
     194                 :       1068 :   bool result = calculateLongitudinalRssStateOppositeDirection(constellation, rssState.longitudinal_state);
     195         [ +  + ]:       1068 :   if (result)
     196                 :            :   {
     197                 :       1066 :     result = calculateLateralRssState(constellation, rssState.lateral_state_left, rssState.lateral_state_right);
     198                 :            :   }
     199                 :       1068 :   return result;
     200                 :            : }
     201                 :            : 
     202                 :      65123 : bool RssNonIntersectionConstellationChecker::calculateLongitudinalRssStateSameDirection(
     203                 :            :   core::RelativeConstellation const &constellation, state::LongitudinalRssState &rssState)
     204                 :            : {
     205                 :      65123 :   bool result = false;
     206                 :            : 
     207                 :      65123 :   rssState.response = state::LongitudinalResponse::BrakeMin;
     208                 :      65123 :   rssState.rss_state_information.current_distance = constellation.relative_position.longitudinal_distance;
     209                 :            : 
     210                 :      65123 :   bool is_safe = false;
     211                 :            : 
     212         [ +  + ]:      65123 :   if ((core::LongitudinalRelativePosition::InFront == constellation.relative_position.longitudinal_position)
     213         [ +  + ]:       2083 :       || (core::LongitudinalRelativePosition::OverlapFront == constellation.relative_position.longitudinal_position))
     214                 :            :   {
     215                 :      63140 :     rssState.rss_state_information.evaluator = state::RssStateEvaluator::LongitudinalDistanceSameDirectionEgoFront;
     216                 :            : 
     217                 :            :     // The ego vehicle is leading in this constellation so we don't need to break longitudinal
     218                 :      63140 :     rssState.response = state::LongitudinalResponse::None;
     219                 :            : 
     220                 :      63140 :     result = checkSafeLongitudinalDistanceSameDirection(constellation.ego_state,
     221                 :      63140 :                                                         constellation.other_state,
     222                 :      63140 :                                                         constellation.relative_position.longitudinal_distance,
     223         [ +  - ]:      63140 :                                                         rssState.rss_state_information.safe_distance,
     224                 :            :                                                         is_safe);
     225                 :            :   }
     226                 :            :   else
     227                 :            :   {
     228                 :       1983 :     rssState.rss_state_information.evaluator = state::RssStateEvaluator::LongitudinalDistanceSameDirectionOtherInFront;
     229                 :            : 
     230                 :       1983 :     result = checkSafeLongitudinalDistanceSameDirection(constellation.other_state,
     231                 :       1983 :                                                         constellation.ego_state,
     232                 :       1983 :                                                         constellation.relative_position.longitudinal_distance,
     233         [ +  - ]:       1983 :                                                         rssState.rss_state_information.safe_distance,
     234                 :            :                                                         is_safe);
     235                 :            :   }
     236                 :            : 
     237                 :      65123 :   rssState.is_safe = is_safe;
     238         [ +  + ]:      65123 :   if (is_safe)
     239                 :            :   {
     240                 :      51470 :     rssState.response = state::LongitudinalResponse::None;
     241                 :            :   }
     242                 :            : 
     243                 :      65123 :   return result;
     244                 :            : }
     245                 :            : 
     246                 :       1068 : bool RssNonIntersectionConstellationChecker::calculateLongitudinalRssStateOppositeDirection(
     247                 :            :   core::RelativeConstellation const &constellation, state::LongitudinalRssState &rssState)
     248                 :            : {
     249                 :       1068 :   bool result = false;
     250                 :            : 
     251                 :       1068 :   bool is_safe = false;
     252                 :       1068 :   rssState.response = state::LongitudinalResponse::BrakeMin;
     253                 :       1068 :   rssState.rss_state_information.current_distance = constellation.relative_position.longitudinal_distance;
     254                 :            : 
     255         [ +  + ]:       1068 :   if (constellation.ego_state.structured_object_state.is_in_correct_lane)
     256                 :            :   {
     257                 :            :     rssState.rss_state_information.evaluator
     258                 :        749 :       = state::RssStateEvaluator::LongitudinalDistanceOppositeDirectionEgoCorrectLane;
     259                 :            : 
     260                 :       1498 :     result = checkSafeLongitudinalDistanceOppositeDirection(constellation.ego_state,
     261                 :        749 :                                                             constellation.other_state,
     262                 :        749 :                                                             constellation.relative_position.longitudinal_distance,
     263         [ +  - ]:        749 :                                                             rssState.rss_state_information.safe_distance,
     264                 :            :                                                             is_safe);
     265                 :        749 :     rssState.response = state::LongitudinalResponse::BrakeMinCorrect;
     266                 :            :   }
     267                 :            :   else
     268                 :            :   {
     269                 :        319 :     rssState.rss_state_information.evaluator = state::RssStateEvaluator::LongitudinalDistanceOppositeDirection;
     270                 :            : 
     271                 :        319 :     result = checkSafeLongitudinalDistanceOppositeDirection(constellation.other_state,
     272                 :        319 :                                                             constellation.ego_state,
     273                 :        319 :                                                             constellation.relative_position.longitudinal_distance,
     274         [ +  - ]:        319 :                                                             rssState.rss_state_information.safe_distance,
     275                 :            :                                                             is_safe);
     276                 :            :   }
     277                 :            : 
     278                 :       1068 :   rssState.is_safe = is_safe;
     279         [ +  + ]:       1068 :   if (rssState.is_safe)
     280                 :            :   {
     281                 :        389 :     rssState.response = state::LongitudinalResponse::None;
     282                 :            :   }
     283                 :            : 
     284                 :       1068 :   return result;
     285                 :            : }
     286                 :            : 
     287                 :      54188 : bool RssNonIntersectionConstellationChecker::calculateLateralRssState(core::RelativeConstellation const &constellation,
     288                 :            :                                                                       state::LateralRssState &rssStateLeft,
     289                 :            :                                                                       state::LateralRssState &rssStateRight)
     290                 :            : {
     291                 :      54188 :   rssStateLeft.is_safe = false;
     292                 :      54188 :   rssStateLeft.response = state::LateralResponse::BrakeMin;
     293                 :      54188 :   rssStateRight.is_safe = false;
     294                 :      54188 :   rssStateRight.response = state::LateralResponse::BrakeMin;
     295                 :            : 
     296                 :      54188 :   bool isDistanceSafe = false;
     297                 :            : 
     298                 :      54188 :   bool result = false;
     299                 :     108376 :   if ((core::LateralRelativePosition::AtLeft == constellation.relative_position.lateral_position)
     300   [ +  +  +  +  :      54188 :       || (getRightBorderObjectId() == constellation.object_id))
                   +  + ]
     301                 :            :   {
     302                 :        906 :     rssStateLeft.rss_state_information.evaluator = state::RssStateEvaluator::None;
     303                 :        906 :     rssStateLeft.rss_state_information.current_distance = std::numeric_limits<physics::Distance>::max();
     304                 :        906 :     rssStateLeft.rss_state_information.safe_distance = std::numeric_limits<physics::Distance>::max();
     305                 :            : 
     306                 :            :     // ego is the left vehicle, so right side has to be checked
     307                 :        906 :     rssStateRight.rss_state_information.evaluator = state::RssStateEvaluator::LateralDistance;
     308                 :        906 :     rssStateRight.rss_state_information.current_distance = constellation.relative_position.lateral_distance;
     309                 :        906 :     result = checkSafeLateralDistance(constellation.ego_state,
     310                 :        906 :                                       constellation.other_state,
     311                 :        906 :                                       constellation.relative_position.lateral_distance,
     312         [ +  - ]:        906 :                                       rssStateRight.rss_state_information.safe_distance,
     313                 :            :                                       isDistanceSafe);
     314                 :            :   }
     315                 :     106564 :   else if ((core::LateralRelativePosition::AtRight == constellation.relative_position.lateral_position)
     316   [ +  +  -  +  :      53282 :            || (getLeftBorderObjectId() == constellation.object_id))
                   +  + ]
     317                 :            :   {
     318                 :       1086 :     rssStateRight.rss_state_information.evaluator = state::RssStateEvaluator::None;
     319                 :       1086 :     rssStateRight.rss_state_information.current_distance = std::numeric_limits<physics::Distance>::max();
     320                 :       1086 :     rssStateRight.rss_state_information.safe_distance = std::numeric_limits<physics::Distance>::max();
     321                 :            : 
     322                 :            :     // ego is the right vehicle, so left side has to be checked
     323                 :       1086 :     rssStateLeft.rss_state_information.evaluator = state::RssStateEvaluator::LateralDistance;
     324                 :       1086 :     rssStateLeft.rss_state_information.current_distance = constellation.relative_position.lateral_distance;
     325                 :       1086 :     result = checkSafeLateralDistance(constellation.other_state,
     326                 :       1086 :                                       constellation.ego_state,
     327                 :       1086 :                                       constellation.relative_position.lateral_distance,
     328         [ +  - ]:       1086 :                                       rssStateLeft.rss_state_information.safe_distance,
     329                 :            :                                       isDistanceSafe);
     330                 :            :   }
     331                 :            :   else
     332                 :            :   {
     333                 :      52196 :     rssStateLeft.rss_state_information.evaluator = state::RssStateEvaluator::LateralDistance;
     334                 :      52196 :     rssStateLeft.rss_state_information.current_distance = physics::Distance(0);
     335                 :      52196 :     rssStateLeft.rss_state_information.safe_distance = physics::Distance(0);
     336                 :      52196 :     rssStateRight.rss_state_information.evaluator = state::RssStateEvaluator::LateralDistance;
     337                 :      52196 :     rssStateRight.rss_state_information.current_distance = physics::Distance(0);
     338                 :      52196 :     rssStateRight.rss_state_information.safe_distance = physics::Distance(0);
     339                 :            : 
     340                 :            :     // lateral distance is zero, never safe
     341                 :      52196 :     result = true;
     342                 :            :   }
     343                 :            : 
     344         [ +  + ]:      54188 :   if (isDistanceSafe)
     345                 :            :   {
     346                 :       1339 :     rssStateLeft.is_safe = true;
     347                 :       1339 :     rssStateLeft.response = state::LateralResponse::None;
     348                 :       1339 :     rssStateRight.is_safe = true;
     349                 :       1339 :     rssStateRight.response = state::LateralResponse::None;
     350                 :            :   }
     351                 :     105698 :   else if ((core::LateralRelativePosition::AtLeft == constellation.relative_position.lateral_position)
     352         [ +  + ]:      52692 :            || (core::LateralRelativePosition::OverlapLeft == constellation.relative_position.lateral_position)
     353   [ +  +  +  +  :     105541 :            || (getRightBorderObjectId() == constellation.object_id))
                   +  + ]
     354                 :            :   {
     355                 :            :     // ego is the left vehicle, so the collision is on the right side
     356                 :        284 :     rssStateLeft.is_safe = true;
     357                 :        284 :     rssStateLeft.response = state::LateralResponse::None;
     358                 :            :   }
     359                 :     105130 :   else if ((core::LateralRelativePosition::AtRight == constellation.relative_position.lateral_position)
     360         [ +  + ]:      52070 :            || (core::LateralRelativePosition::OverlapRight == constellation.relative_position.lateral_position)
     361   [ +  +  -  +  :     104635 :            || (getLeftBorderObjectId() == constellation.object_id))
                   +  + ]
     362                 :            :   {
     363                 :            :     // ego is the right vehicle, so the collision is on the left side
     364                 :        605 :     rssStateRight.is_safe = true;
     365                 :        605 :     rssStateRight.response = state::LateralResponse::None;
     366                 :            :   }
     367                 :            : 
     368                 :      54188 :   return result;
     369                 :            : }
     370                 :            : 
     371                 :            : } // namespace structured
     372                 :            : } // namespace rss
     373                 :            : } // namespace ad

Generated by: LCOV version 1.14