LCOV - code coverage report
Current view: top level - include/ad/rss/map/detail - RssRouteCheckerDataDetail.hpp (source / functions) Hit Total Coverage
Test: ad_rss_map_integration Lines: 182 266 68.4 %
Date: 2025-07-22 06:56:19 Functions: 11 12 91.7 %
Branches: 153 394 38.8 %

           Branch data     Line data    Source code
       1                 :            : // ----------------- BEGIN LICENSE BLOCK ---------------------------------
       2                 :            : //
       3                 :            : // Copyright (C) 2019-2022 Intel Corporation
       4                 :            : //
       5                 :            : // SPDX-License-Identifier: LGPL-2.1-only
       6                 :            : //
       7                 :            : // ----------------- END LICENSE BLOCK -----------------------------------
       8                 :            : 
       9                 :            : #include <ad/map/lane/Operation.hpp>
      10                 :            : #include <ad/map/match/MapMatchedOperation.hpp>
      11                 :            : #include <ad/map/route/Planning.hpp>
      12                 :            : #include "ad/rss/map/Logging.hpp"
      13                 :            : #include "ad/rss/map/RssObjectDataOperation.hpp"
      14                 :            : #include "ad/rss/map/RssRouteCheckerControl.hpp"
      15                 :            : #include "ad/rss/map/RssRouteCheckerData.hpp"
      16                 :            : 
      17                 :            : namespace ad {
      18                 :            : namespace rss {
      19                 :            : namespace map {
      20                 :            : 
      21                 :         30 : template <class OBJECT_INSTANCE_TYPE> RssRouteCheckerVehicleData<OBJECT_INSTANCE_TYPE>::~RssRouteCheckerVehicleData()
      22                 :            : {
      23                 :            :   // housekeeping of RssRouteCheckerControl
      24         [ +  + ]:         30 :   if (mVehicleAdapter != nullptr)
      25                 :            :   {
      26                 :         10 :     mVehicleAdapter->getCheckerControl()->dropVehicle(mRssObjectData.id);
      27                 :            :   }
      28                 :         30 : }
      29                 :            : 
      30                 :            : enum class ReachedRoutingTargetsMode
      31                 :            : {
      32                 :            :   eDISTANCE_ONLY,
      33                 :            :   eDISTANCE_AND_ORIENTATION
      34                 :            : };
      35                 :            : 
      36                 :         26 : inline void dropReachedRoutingTargets(std::vector<::ad::map::point::ENUPoint> &routingTargets,
      37                 :            :                                       RssObjectData const &rssObjectData,
      38                 :            :                                       ad::physics::Distance const &reachedDistance,
      39                 :            :                                       ReachedRoutingTargetsMode reachedRoutingTargetsMode)
      40                 :            : {
      41                 :            :   // removeReachedRoutingTargets
      42         [ -  + ]:         26 :   while (!routingTargets.empty())
      43                 :            :   {
      44                 :          0 :     auto const nextTarget = routingTargets.front();
      45                 :            :     auto const distanceToNextTarget
      46         [ #  # ]:          0 :       = ad::map::point::distance(nextTarget, rssObjectData.match_object.enu_position.center_point);
      47   [ #  #  #  # ]:          0 :     if (distanceToNextTarget < reachedDistance)
      48                 :            :     {
      49         [ #  # ]:          0 :       routingTargets.erase(routingTargets.begin());
      50   [ #  #  #  # ]:          0 :       getLogger()->debug(
      51                 :            :         "RssRouteCheckerVehicleData::removeReachedRoutingTargets[{}] Next target reached by distance: {}; "
      52                 :            :         "remaining targets: {}",
      53         [ #  # ]:          0 :         rssObjectData.id,
      54                 :            :         nextTarget,
      55                 :            :         routingTargets);
      56                 :            :     }
      57                 :          0 :     else if ((reachedRoutingTargetsMode == ReachedRoutingTargetsMode::eDISTANCE_AND_ORIENTATION)
      58   [ #  #  #  #  :          0 :              && (routingTargets.size() > 1u) && (distanceToNextTarget < 10. * reachedDistance))
          #  #  #  #  #  
                #  #  # ]
      59                 :            : 
      60                 :            :     {
      61                 :            :       // if we have a new list of targets and there will be additional targets left if we drop this
      62                 :            :       // and the next target is already located behind the vehicle and not more than 10 time further away as
      63                 :            :       // reachedDistance, we also drop this; otherwhise the ego might try to plan more or less a round trip before
      64                 :            :       // finishing the target list
      65                 :            :       auto routingTargetHeading
      66         [ #  # ]:          0 :         = ad::map::point::createENUHeading(rssObjectData.match_object.enu_position.center_point, nextTarget);
      67         [ #  # ]:          0 :       auto headingDiffSigned = ad::physics::normalizeAngleSigned(ad::physics::Angle(
      68                 :          0 :         routingTargetHeading.mENUHeading - rssObjectData.match_object.enu_position.heading.mENUHeading));
      69   [ #  #  #  # ]:          0 :       if (std::fabs(headingDiffSigned) > ad::physics::cPI_2)
      70                 :            :       {
      71         [ #  # ]:          0 :         routingTargets.erase(routingTargets.begin());
      72   [ #  #  #  # ]:          0 :         getLogger()->debug(
      73                 :            :           "RssRouteCheckerVehicleData::removeReachedRoutingTargets[{}] Next target reached by orientation: {}, {}; "
      74                 :            :           "remaining targets: {}",
      75         [ #  # ]:          0 :           rssObjectData.id,
      76                 :            :           nextTarget,
      77                 :            :           headingDiffSigned,
      78                 :            :           routingTargets);
      79                 :            :       }
      80                 :            :       else
      81                 :            :       {
      82                 :          0 :         break;
      83                 :            :       }
      84                 :            :     }
      85                 :            :     else
      86                 :            :     {
      87                 :          0 :       break;
      88                 :            :     }
      89                 :            :   }
      90                 :         26 : }
      91                 :            : 
      92                 :            : template <class OBJECT_INSTANCE_TYPE>
      93                 :         26 : std::vector<::ad::map::point::ENUPoint> RssRouteCheckerVehicleData<OBJECT_INSTANCE_TYPE>::handleRoutingTargets()
      94                 :            : {
      95         [ +  - ]:         26 :   auto const routingTargetOperation = getAdapter()->getRoutingTargetOperation();
      96                 :         26 :   std::vector<::ad::map::point::ENUPoint> routingTargetsToAppend;
      97         [ -  + ]:         26 :   if (routingTargetOperation.command
      98                 :            :       == RssVehicleAdapter<OBJECT_INSTANCE_TYPE>::RssRoutingTargetCommand::ReplaceTargets)
      99                 :            :   {
     100                 :          0 :     mRoutes.clear();
     101         [ #  # ]:          0 :     mRoutingTargets = routingTargetOperation.routingTargets;
     102                 :          0 :     dropReachedRoutingTargets(mRoutingTargets,
     103         [ #  # ]:          0 :                               mRssObjectData,
     104         [ #  # ]:          0 :                               getAdapter()->getRoutingTargetReachedDistance(),
     105                 :            :                               ReachedRoutingTargetsMode::eDISTANCE_AND_ORIENTATION);
     106                 :            :   }
     107                 :            :   else
     108                 :            :   {
     109                 :         26 :     dropReachedRoutingTargets(mRoutingTargets,
     110         [ +  - ]:         26 :                               mRssObjectData,
     111         [ +  - ]:         52 :                               getAdapter()->getRoutingTargetReachedDistance(),
     112                 :            :                               ReachedRoutingTargetsMode::eDISTANCE_ONLY);
     113                 :            : 
     114         [ -  + ]:         26 :     if (routingTargetOperation.command
     115                 :            :         == RssVehicleAdapter<OBJECT_INSTANCE_TYPE>::RssRoutingTargetCommand::AppendTargets)
     116                 :            :     {
     117         [ #  # ]:          0 :       routingTargetsToAppend = routingTargetOperation.routingTargets;
     118                 :          0 :       dropReachedRoutingTargets(routingTargetsToAppend,
     119         [ #  # ]:          0 :                                 mRssObjectData,
     120         [ #  # ]:          0 :                                 getAdapter()->getRoutingTargetReachedDistance(),
     121                 :            :                                 ReachedRoutingTargetsMode::eDISTANCE_AND_ORIENTATION);
     122                 :            :     }
     123                 :            :   }
     124                 :         52 :   return routingTargetsToAppend;
     125                 :         26 : }
     126                 :            : 
     127                 :         16 : template <class OBJECT_INSTANCE_TYPE> void RssRouteCheckerVehicleData<OBJECT_INSTANCE_TYPE>::shortenRoutes()
     128                 :            : {
     129                 :         16 :   ad::map::point::ParaPointList allLaneMatches;
     130         [ +  + ]:         48 :   for (auto const &referencePoint :
     131                 :            :        {::ad::map::match::ObjectReferencePoints::RearRight, ::ad::map::match::ObjectReferencePoints::RearLeft})
     132                 :            :   {
     133         [ +  + ]:        115 :     for (auto const &matchPoint :
     134                 :            :          mRssObjectData.match_object.map_matched_bounding_box.reference_point_positions[size_t(referencePoint)])
     135                 :            :     {
     136                 :            :       // consider only longitudinal in lane matches here, because we want to cover the rear of the vehicle
     137                 :            :       // allow lateral outside matches to cover vehicle driving slightly outside the route
     138   [ +  -  +  - ]:         83 :       if (ad::map::match::isLongitudinalInLaneMatch(matchPoint))
     139                 :            :       {
     140         [ +  - ]:         83 :         allLaneMatches.push_back(matchPoint.lane_point.para_point);
     141                 :            :       }
     142                 :            :     }
     143                 :            :   }
     144                 :            : 
     145                 :         16 :   auto routeIndex = 0u;
     146         [ +  + ]:         44 :   while (routeIndex < mRoutes.size())
     147                 :            :   {
     148   [ +  -  +  - ]:         58 :     getLogger()->trace("RssVehicleAdapter::shortenRoutes[{}:{}] call shorten route with {} and  {}",
     149                 :         29 :                        mRssObjectData.id,
     150         [ +  - ]:         29 :                        mRoutes[routeIndex].route_id,
     151                 :            :                        allLaneMatches,
     152                 :         29 :                        mRoutes[routeIndex].route);
     153                 :         58 :     auto shortenRouteResult = ::ad::map::route::shortenRoute(
     154                 :            :       allLaneMatches,
     155         [ +  - ]:         29 :       mRoutes[routeIndex].route,
     156                 :            :       ::ad::map::route::ShortenRouteMode::DontCutIntersectionAndPrependIfSucceededBeforeRoute);
     157                 :            : 
     158         [ +  + ]:         29 :     if ((shortenRouteResult != ::ad::map::route::ShortenRouteResult::Succeeded)
     159         [ +  + ]:          6 :         && (shortenRouteResult != ::ad::map::route::ShortenRouteResult::SucceededIntersectionNotCut))
     160                 :            :     {
     161   [ +  -  +  - ]:          6 :       getLogger()->trace("RssVehicleAdapter::shortenRoutes[{}:{}] shorten current route failed. Dropping. {}",
     162                 :          3 :                          mRssObjectData.id,
     163         [ +  - ]:          3 :                          mRoutes[routeIndex].route_id,
     164                 :          3 :                          mRoutes[routeIndex].route);
     165         [ +  - ]:          3 :       mRoutes.erase(mRoutes.begin() + routeIndex);
     166                 :            :     }
     167                 :            :     else
     168                 :            :     {
     169   [ +  -  +  - ]:         52 :       getLogger()->trace("RssVehicleAdapter::shortenRoutes[{}:{}] shorten current route succeeded {}",
     170                 :         25 :                          mRssObjectData.id,
     171         [ +  - ]:         25 :                          mRoutes[routeIndex].route_id,
     172                 :         26 :                          mRoutes[routeIndex].route);
     173         [ +  - ]:         26 :       auto findWaypointResult = findNearestWaypoint(allLaneMatches, mRoutes[routeIndex].route);
     174         [ +  - ]:         26 :       mRoutes[routeIndex].progress_on_route = calcLength(findWaypointResult);
     175                 :         25 :       routeIndex++;
     176                 :            :     }
     177                 :            :   }
     178                 :         15 : }
     179                 :            : 
     180                 :            : template <class OBJECT_INSTANCE_TYPE>
     181                 :         16 : void RssRouteCheckerVehicleData<OBJECT_INSTANCE_TYPE>::extendRoutes(
     182                 :            :   physics::Distance const routePreviewDistance,
     183                 :            :   std::vector<::ad::map::point::ENUPoint> const &routingTargetsToAppend,
     184                 :            :   ::ad::map::lane::LaneIdSet const &mapAreaLanes)
     185                 :            : {
     186                 :         16 :   RssRouteList routesToAdd;
     187                 :         16 :   auto routeIndex = 0u;
     188         [ +  + ]:         68 :   while (routeIndex < mRoutes.size())
     189                 :            :   {
     190                 :         26 :     std::vector<::ad::map::route::FullRoute> additionalRoutes;
     191                 :            : 
     192                 :         26 :     bool routeValid = false;
     193         [ -  + ]:         26 :     if (!routingTargetsToAppend.empty())
     194                 :            :     {
     195         [ #  # ]:          0 :       routeValid = ::ad::map::route::extendRouteToDestinations(mRoutes[routeIndex].route, routingTargetsToAppend);
     196         [ #  # ]:          0 :       mRoutingTargets.insert(mRoutingTargets.end(), routingTargetsToAppend.begin(), routingTargetsToAppend.end());
     197                 :            :     }
     198   [ +  -  +  -  :         26 :     else if (mRoutingTargets.empty() && (mRouteExtensionMode != RouteExtensionMode::eAllowOnlyTargetRoute))
                   +  - ]
     199                 :            :     {
     200                 :            :       // only extend if no routing targets are provided and not forbidden to extend by extension mode
     201         [ +  - ]:         26 :       routeValid = ::ad::map::route::extendRouteToDistance(mRoutes[routeIndex].route,
     202         [ +  - ]:         52 :                                                            mRoutes[routeIndex].progress_on_route + routePreviewDistance,
     203                 :            :                                                            additionalRoutes,
     204                 :            :                                                            mapAreaLanes);
     205                 :            :     }
     206                 :            :     else
     207                 :            :     {
     208                 :          0 :       routeValid = true;
     209                 :            :     }
     210                 :            : 
     211         [ +  - ]:         26 :     if (routeValid)
     212                 :            :     {
     213   [ +  -  +  - ]:         52 :       getLogger()->trace("RssVehicleAdapter::extendRoutes[{}:{}] extended current route {} {}",
     214                 :         26 :                          mRssObjectData.id,
     215         [ +  - ]:         26 :                          mRoutes[routeIndex].route_id,
     216                 :         26 :                          mRoutes[routeIndex].progress_on_route,
     217                 :         26 :                          mRoutes[routeIndex].route);
     218         [ +  - ]:         26 :       if (mRouteExtensionMode == RouteExtensionMode::eAllowMultipleRoutes)
     219                 :            :       {
     220         [ +  + ]:         29 :         for (auto &additionalRoute : additionalRoutes)
     221                 :            :         {
     222                 :          3 :           bool addRoute = true;
     223         [ +  + ]:          6 :           for (auto checkRouteIndex = 0u; checkRouteIndex < mRoutes.size(); checkRouteIndex++)
     224                 :            :           {
     225         [ -  + ]:          3 :             if (checkRouteIndex != routeIndex)
     226                 :            :             {
     227                 :          0 :               auto const compareResult = ::ad::map::route::planning::compareRoutesOnIntervalLevel(
     228         [ #  # ]:          0 :                 additionalRoute, mRoutes[checkRouteIndex].route);
     229         [ #  # ]:          0 :               if (compareResult != ::ad::map::route::planning::CompareRouteResult::Differ)
     230                 :            :               {
     231   [ #  #  #  # ]:          0 :                 getLogger()->trace("RssVehicleAdapter::extendRoutes[{}:{}] drop additional route {} because compares "
     232                 :            :                                    "{} to route_id {} {}",
     233                 :          0 :                                    mRssObjectData.id,
     234         [ #  # ]:          0 :                                    mRoutes[routeIndex].route_id,
     235                 :            :                                    additionalRoute,
     236                 :            :                                    compareResult,
     237                 :          0 :                                    mRoutes[checkRouteIndex].route_id,
     238                 :          0 :                                    mRoutes[checkRouteIndex].route);
     239                 :          0 :                 addRoute = false;
     240                 :          0 :                 break;
     241                 :            :               }
     242                 :            :             }
     243                 :            :           }
     244                 :            : 
     245         [ +  - ]:          3 :           if (addRoute)
     246                 :            :           {
     247                 :            :             // as the current point in the route is identical with the new one, we take over the current vehicle
     248                 :            :             // dynamics, too.
     249                 :          3 :             RssRoute newRssRoute;
     250                 :          3 :             newRssRoute.route_id = mNextRouteId++;
     251         [ +  - ]:          3 :             newRssRoute.route = additionalRoute;
     252                 :          3 :             newRssRoute.vehicle_dynamics_on_route = mRoutes[routeIndex].vehicle_dynamics_on_route;
     253                 :          3 :             newRssRoute.likelihood = mRoutes[routeIndex].likelihood;
     254                 :          3 :             newRssRoute.parent_route_id = mRoutes[routeIndex].route_id;
     255                 :          3 :             newRssRoute.progress_on_route = mRoutes[routeIndex].progress_on_route;
     256   [ +  -  +  - ]:          6 :             getLogger()->trace("RssVehicleAdapter::extendRoutes[{}:{}] additional route {}: {} {}",
     257                 :          3 :                                mRssObjectData.id,
     258         [ +  - ]:          3 :                                mRoutes[routeIndex].route_id,
     259                 :            :                                newRssRoute.route_id,
     260                 :            :                                newRssRoute.progress_on_route,
     261                 :            :                                newRssRoute.route);
     262         [ +  - ]:          3 :             routesToAdd.push_back(newRssRoute);
     263                 :          3 :           }
     264                 :            :         }
     265                 :            :       }
     266         [ #  # ]:          0 :       else if (additionalRoutes.size() > 0u)
     267                 :            :       {
     268   [ #  #  #  # ]:          0 :         getLogger()->trace(
     269                 :            :           "RssVehicleAdapter::extendRoutes[{}:{}] allow only single route mode: drop additional routes {}",
     270                 :          0 :           mRssObjectData.id,
     271         [ #  # ]:          0 :           mRoutes[routeIndex].route_id,
     272                 :          0 :           additionalRoutes.size());
     273                 :            :       }
     274                 :         26 :       routeIndex++;
     275                 :            :     }
     276                 :            :     else
     277                 :            :     {
     278                 :            :       // drop this
     279   [ #  #  #  # ]:          0 :       getLogger()->warn("RssVehicleAdapter::extendRoutes[{}:{}] extend current route failed, dropping {}",
     280                 :          0 :                         mRssObjectData.id,
     281         [ #  # ]:          0 :                         mRoutes[routeIndex].route_id,
     282                 :          0 :                         mRoutes[routeIndex].route);
     283         [ #  # ]:          0 :       mRoutes.erase(mRoutes.begin() + routeIndex);
     284                 :            :     }
     285                 :            :   }
     286         [ +  - ]:         16 :   mRoutes.insert(mRoutes.end(), routesToAdd.begin(), routesToAdd.end());
     287                 :         16 : }
     288                 :            : 
     289                 :            : template <class OBJECT_INSTANCE_TYPE>
     290                 :            : std::vector<::ad::map::route::FullRoute>
     291                 :         10 : RssRouteCheckerVehicleData<OBJECT_INSTANCE_TYPE>::createRoutes(physics::Distance const routePreviewDistance,
     292                 :            :                                                                ::ad::map::lane::LaneIdSet const &mapAreaLanes)
     293                 :            : {
     294                 :         10 :   std::vector<::ad::map::route::FullRoute> newRoutes;
     295         [ +  + ]:         30 :   for (const auto &refPoint :
     296                 :            :        {::ad::map::match::ObjectReferencePoints::RearLeft, ::ad::map::match::ObjectReferencePoints::RearRight})
     297                 :            :   {
     298         [ +  + ]:         70 :     for (const auto &position :
     299                 :            :          mRssObjectData.match_object.map_matched_bounding_box.reference_point_positions[std::size_t(int32_t(refPoint))])
     300                 :            :     {
     301                 :            :       // consider only longitudinal in lane matches here, to be consistent to shortenRoute
     302                 :            :       // otherwhise the next shorten route might fail
     303   [ +  -  -  + ]:         50 :       if (!ad::map::match::isLongitudinalInLaneMatch(position))
     304                 :            :       {
     305                 :          0 :         continue;
     306                 :            :       }
     307                 :         50 :       auto startPoint = position.lane_point.para_point;
     308                 :         50 :       auto projectedStartPoint = startPoint;
     309   [ +  -  +  + ]:         50 :       if (!::ad::map::lane::isHeadingInLaneDirection(startPoint, mRssObjectData.match_object.enu_position.heading))
     310                 :            :       {
     311   [ +  -  +  - ]:         10 :         getLogger()->trace("Vehicle heading in opposite lane direction");
     312         [ +  - ]:         10 :         if (::ad::map::lane::projectPositionToLaneInHeadingDirection(
     313         [ +  - ]:         10 :               startPoint, mRssObjectData.match_object.enu_position.heading, projectedStartPoint))
     314                 :            :         {
     315   [ +  -  +  - ]:         20 :           getLogger()->trace("Projected to lane {}", projectedStartPoint.lane_id);
     316                 :            :         }
     317                 :            :       }
     318   [ +  -  +  - ]:        100 :       getLogger()->trace("Route startPoint: {}, projectedStartPoint: {}", startPoint, projectedStartPoint);
     319                 :         50 :       auto routingStartPoint = ::ad::map::route::planning::createRoutingPoint(
     320         [ +  - ]:         50 :         projectedStartPoint, mRssObjectData.match_object.enu_position.heading);
     321                 :            : 
     322   [ -  +  -  -  :         50 :       if (!mRoutingTargets.empty() && ad::map::point::isValid(mRoutingTargets))
             -  -  -  + ]
     323                 :            :       {
     324                 :          0 :         auto newRoute = ::ad::map::route::planning::planRoute(
     325         [ #  # ]:          0 :           routingStartPoint, mRoutingTargets, ::ad::map::route::RouteCreationMode::AllRoutableLanes);
     326         [ #  # ]:          0 :         if (newRoute.route_planning_counter > 0u)
     327                 :            :         {
     328         [ #  # ]:          0 :           newRoutes.push_back(newRoute);
     329   [ #  #  #  # ]:          0 :           getLogger()->trace("Route found from startPoint: {}, projectedStartPoint: {}, routingTargets: {}, route: {}",
     330                 :            :                              startPoint,
     331                 :            :                              projectedStartPoint,
     332         [ #  # ]:          0 :                              mRoutingTargets,
     333                 :            :                              newRoute);
     334                 :            :         }
     335                 :            :         else
     336                 :            :         {
     337   [ #  #  #  # ]:          0 :           getLogger()->warn("No Route found from startPoint: {}, projectedStartPoint: {}, routingTargets: {}",
     338                 :            :                             startPoint,
     339                 :            :                             projectedStartPoint,
     340         [ #  # ]:          0 :                             mRoutingTargets);
     341                 :            :         }
     342                 :          0 :       }
     343         [ +  - ]:         50 :       else if (mRouteExtensionMode != RouteExtensionMode::eAllowOnlyTargetRoute)
     344                 :            :       {
     345                 :            :         // better prefer longer routes to ensure back of the vehicle is in
     346         [ +  - ]:         50 :         auto newRoutesFromCurrentStart = ::ad::map::route::planning::predictRoutesOnDistance(
     347                 :            :           routingStartPoint,
     348                 :            :           routePreviewDistance,
     349                 :            :           ::ad::map::route::RouteCreationMode::AllRoutableLanes,
     350                 :            :           ::ad::map::route::planning::FilterDuplicatesMode::SubRoutesPreferLongerOnes,
     351                 :            :           mapAreaLanes);
     352         [ +  - ]:         50 :         newRoutes.insert(newRoutes.end(), newRoutesFromCurrentStart.begin(), newRoutesFromCurrentStart.end());
     353   [ +  -  +  - ]:        100 :         getLogger()->trace("Routes predicted from startPoint: {}, projectedStartPoint: {}, routes: {}",
     354                 :            :                            startPoint,
     355                 :            :                            projectedStartPoint,
     356                 :            :                            newRoutesFromCurrentStart);
     357                 :         50 :       }
     358                 :            :     }
     359                 :            :   }
     360                 :            : 
     361                 :            :   // better prefer longer routes to ensure back of the vehicle is in
     362   [ +  -  +  - ]:         10 :   newRoutes = ::ad::map::route::planning::filterDuplicatedRoutes(
     363                 :            :     newRoutes, ::ad::map::route::planning::FilterDuplicatesMode::SubRoutesPreferLongerOnes);
     364                 :            : 
     365                 :         10 :   return newRoutes;
     366                 :          0 : }
     367                 :            : 
     368                 :            : template <class OBJECT_INSTANCE_TYPE>
     369                 :         26 : void RssRouteCheckerVehicleData<OBJECT_INSTANCE_TYPE>::updateRoutes(
     370                 :            :   ::ad::physics::Distance const routePreviewDistance,
     371                 :            :   ::ad::map::lane::LaneIdSet const &mapAreaLanes,
     372                 :            :   RssRouteCheckerVehicleData<OBJECT_INSTANCE_TYPE>::RouteExtensionMode routeExtensionMode)
     373                 :            : {
     374                 :         26 :   mRouteExtensionMode = routeExtensionMode;
     375         [ +  - ]:         26 :   auto adapterPredictions = getAdapter()->getRoutePredictions();
     376         [ -  + ]:         26 :   if (!adapterPredictions.empty())
     377                 :            :   {
     378         [ #  # ]:          0 :     if (!mExternalRoutes)
     379                 :            :     {
     380                 :            :       // mode switch between external and internal routes
     381                 :          0 :       mRoutes.clear();
     382                 :            :     }
     383                 :          0 :     mExternalRoutes = true;
     384                 :          0 :     RssRouteList oldRoutes;
     385                 :          0 :     oldRoutes.swap(mRoutes);
     386         [ #  # ]:          0 :     for (auto &prediction : adapterPredictions)
     387                 :            :     {
     388         [ #  # ]:          0 :       mRoutes.push_back(prediction);
     389                 :            :       auto oldRouteIter
     390         [ #  # ]:          0 :         = std::find_if(oldRoutes.begin(), oldRoutes.end(), [&prediction](RssRoute const &route) -> bool {
     391                 :          0 :             return route.route_id == prediction.route_id;
     392                 :            :           });
     393         [ #  # ]:          0 :       if (oldRouteIter != oldRoutes.end())
     394                 :            :       {
     395                 :            :         // preserve vehicle dynamics if possible
     396                 :          0 :         mRoutes.back().vehicle_dynamics_on_route = oldRouteIter->vehicle_dynamics_on_route;
     397                 :            :       }
     398                 :            :     }
     399                 :          0 :   }
     400                 :            :   else
     401                 :            :   {
     402         [ -  + ]:         26 :     if (mExternalRoutes)
     403                 :            :     {
     404                 :            :       // mode switch between external and internal routes
     405                 :          0 :       mRoutes.clear();
     406                 :            :     }
     407                 :         26 :     mExternalRoutes = false;
     408                 :            : 
     409         [ +  - ]:         26 :     auto const routingTargetsToAppend = handleRoutingTargets();
     410                 :            : 
     411         [ +  + ]:         26 :     if (mRoutes.empty())
     412                 :            :     {
     413                 :            :       // try to create routes
     414         [ +  - ]:         10 :       ::ad::map::route::FullRouteList newRoutes = createRoutes(routePreviewDistance, mapAreaLanes);
     415         [ +  + ]:         27 :       for (auto &newRoute : newRoutes)
     416                 :            :       {
     417                 :         17 :         RssRoute rss_route;
     418                 :         17 :         rss_route.route_id = mNextRouteId++;
     419         [ +  - ]:         17 :         rss_route.route = newRoute;
     420                 :         17 :         rss_route.object_data_on_route = RssObjectDataOnRoute();
     421                 :         17 :         rss_route.vehicle_dynamics_on_route = RssEgoVehicleDynamicsOnRoute();
     422                 :         17 :         rss_route.likelihood = physics::Probability(1.);
     423                 :         17 :         rss_route.parent_route_id = RssRouteId(0);
     424                 :         17 :         rss_route.progress_on_route = physics::Distance(0.);
     425   [ +  -  +  - ]:         34 :         getLogger()->trace("RssVehicleAdapter::updateRoutes[{}] new route {}: {} {}",
     426         [ +  - ]:         17 :                            mRssObjectData.id,
     427                 :            :                            rss_route.route_id,
     428                 :            :                            rss_route.progress_on_route,
     429                 :            :                            rss_route.route);
     430         [ +  - ]:         17 :         mRoutes.push_back(rss_route);
     431                 :            :       }
     432                 :         10 :     }
     433                 :            :     else
     434                 :            :     {
     435                 :            :       // adapt routes if required
     436         [ +  - ]:         16 :       shortenRoutes();
     437         [ +  - ]:         16 :       extendRoutes(routePreviewDistance, routingTargetsToAppend, mapAreaLanes);
     438                 :            :     }
     439         [ +  - ]:         26 :     getAdapter()->activeRoutingTargets(mRoutingTargets);
     440                 :         26 :   }
     441                 :         26 : }
     442                 :            : 
     443                 :         26 : template <class OBJECT_INSTANCE_TYPE> void RssRouteCheckerVehicleData<OBJECT_INSTANCE_TYPE>::normalizeAndOrderRoutes()
     444                 :            : {
     445                 :         26 :   physics::Probability likelihoodSum(.0);
     446         [ +  + ]:         72 :   for (auto &rss_route : mRoutes)
     447                 :            :   {
     448         [ +  - ]:         46 :     likelihoodSum += rss_route.likelihood;
     449                 :            :   }
     450                 :            : 
     451   [ +  -  +  - ]:         26 :   if (likelihoodSum != physics::Probability(0.))
     452                 :            :   {
     453                 :            :     // normalize
     454         [ +  + ]:         72 :     for (auto &rss_route : mRoutes)
     455                 :            :     {
     456         [ +  - ]:         46 :       rss_route.likelihood = physics::Probability(rss_route.likelihood / likelihoodSum);
     457                 :            :     }
     458                 :            :   }
     459                 :            : 
     460                 :            :   // sort
     461         [ +  - ]:         26 :   std::sort(mRoutes.begin(), mRoutes.end(), [](RssRoute const &left, RssRoute const &right) -> bool {
     462                 :         40 :     return left.likelihood > right.likelihood;
     463                 :            :   });
     464                 :            : 
     465   [ -  +  -  -  :         26 :   if ((mRouteExtensionMode == RouteExtensionMode::eAllowOnlySingleRoute) && (mRoutes.size() > 1))
                   -  + ]
     466                 :            :   {
     467   [ #  #  #  # ]:          0 :     getLogger()->trace(
     468                 :            :       "RssVehicleAdapter::normalizeAndOrderRoutes[{}] allow only single route mode: drop other routes #{}",
     469                 :          0 :       mRssObjectData.id,
     470         [ #  # ]:          0 :       mRoutes.size() - 1);
     471         [ #  # ]:          0 :     mRoutes.resize(1u);
     472                 :            :   }
     473                 :         26 : }
     474                 :            : 
     475                 :            : template <class OBJECT_INSTANCE_TYPE>
     476                 :         17 : void RssRouteCheckerEgoVehicleData<OBJECT_INSTANCE_TYPE>::updateVehicleDynamicsOnRoutes()
     477                 :            : {
     478         [ +  + ]:         45 :   for (auto &rss_route : mRoutes)
     479                 :            :   {
     480                 :            :     // before starting to override, store required old data
     481                 :         28 :     physics::Duration deltaTime(0.);
     482         [ +  + ]:         28 :     if (rss_route.vehicle_dynamics_on_route.last_update.time_since_epoch().count() != 0)
     483                 :            :     {
     484                 :         17 :       deltaTime = physics::Duration(
     485         [ +  - ]:         34 :         std::chrono::duration<double>(mRssObjectData.last_update - rss_route.vehicle_dynamics_on_route.last_update)
     486                 :            :           .count());
     487                 :            :     }
     488                 :         28 :     auto const lastRouteSpeedValid = rss_route.object_data_on_route.is_valid;
     489                 :         28 :     auto const lastRouteSpeedLat = rss_route.object_data_on_route.route_speed_lat;
     490                 :         28 :     auto const lastRouteSpeedLon = rss_route.object_data_on_route.route_speed_lon;
     491                 :            : 
     492                 :            :     // start the update
     493         [ +  - ]:         28 :     rss_route.object_data_on_route = calculateRssObjectDataOnRoute(rss_route.route, mRssObjectData);
     494                 :         28 :     rss_route.vehicle_dynamics_on_route.last_update = mRssObjectData.last_update;
     495                 :            : 
     496   [ +  -  +  +  :         28 :     if ((deltaTime > physics::Duration(0.0001)) && lastRouteSpeedValid && rss_route.object_data_on_route.is_valid)
          +  +  +  -  +  
                      + ]
     497                 :            :     {
     498                 :            :       rss_route.vehicle_dynamics_on_route.route_accel_lat
     499   [ +  -  +  - ]:         14 :         = (rss_route.object_data_on_route.route_speed_lat - lastRouteSpeedLat) / deltaTime;
     500                 :            :       rss_route.vehicle_dynamics_on_route.avg_route_accel_lat
     501                 :          0 :         = ((rss_route.vehicle_dynamics_on_route.avg_route_accel_lat * 2.)
     502         [ +  - ]:         14 :            + rss_route.vehicle_dynamics_on_route.route_accel_lat)
     503   [ +  -  +  - ]:         28 :         / 3.;
     504                 :            :       rss_route.vehicle_dynamics_on_route.route_accel_lon
     505   [ +  -  +  - ]:         14 :         = (rss_route.object_data_on_route.route_speed_lon - lastRouteSpeedLon) / deltaTime;
     506                 :            :       rss_route.vehicle_dynamics_on_route.avg_route_accel_lon
     507                 :          0 :         = ((rss_route.vehicle_dynamics_on_route.avg_route_accel_lon * 2.)
     508         [ +  - ]:         14 :            + rss_route.vehicle_dynamics_on_route.route_accel_lon)
     509   [ +  -  +  - ]:         28 :         / 3.;
     510                 :            : 
     511   [ +  -  +  + ]:         14 :       if (rss_route.vehicle_dynamics_on_route.avg_route_accel_lat == physics::Acceleration(0.))
     512                 :            :       {
     513                 :            :         // prevent from underrun
     514                 :         12 :         rss_route.vehicle_dynamics_on_route.avg_route_accel_lat = physics::Acceleration(0.);
     515                 :            :       }
     516   [ +  -  +  - ]:         14 :       if (rss_route.vehicle_dynamics_on_route.avg_route_accel_lon == physics::Acceleration(0.))
     517                 :            :       {
     518                 :            :         // prevent from underrun
     519                 :         14 :         rss_route.vehicle_dynamics_on_route.avg_route_accel_lon = physics::Acceleration(0.);
     520                 :            :       }
     521                 :            :     }
     522                 :            :   }
     523                 :         17 : }
     524                 :            : 
     525                 :         17 : template <class OBJECT_INSTANCE_TYPE> void RssRouteCheckerEgoVehicleData<OBJECT_INSTANCE_TYPE>::evaluateRoutes()
     526                 :            : {
     527         [ +  - ]:         17 :   if (!mExternalRoutes)
     528                 :            :   {
     529                 :         17 :     physics::Angle const maxHeadingDelta(M_PI / 4.);
     530                 :         17 :     physics::Distance const maxCenterDistance(4.);
     531         [ +  + ]:         45 :     for (auto &rss_route : mRoutes)
     532                 :            :     {
     533                 :         28 :       rss_route.likelihood = physics::Probability(.05);
     534         [ +  - ]:         28 :       if (rss_route.object_data_on_route.is_valid)
     535                 :            :       {
     536                 :            :         // distance to nominal center
     537                 :         28 :         auto const distanceToRouteNominalCenter = ad::map::point::distance(
     538                 :         28 :           rss_route.object_data_on_route.nominal_center_position_of_lane_in_nominal_route_direction,
     539         [ +  - ]:         28 :           mRssObjectData.match_object.enu_position.center_point);
     540         [ -  + ]:         28 :         if (!rss_route.object_data_on_route.object_within_route)
     541                 :            :         {
     542                 :          0 :           rss_route.likelihood = physics::Probability(.01);
     543                 :            :         }
     544                 :         56 :         else if ((rss_route.object_data_on_route.object_center_within_route)
     545   [ +  -  -  + ]:         28 :                  && (distanceToRouteNominalCenter < maxCenterDistance)
     546   [ +  -  -  -  :         56 :                  && (std::fabs(rss_route.object_data_on_route.route_heading_delta) < maxHeadingDelta))
             -  -  -  + ]
     547                 :            :         {
     548         [ #  # ]:          0 :           auto const distanceFactor = 1. - distanceToRouteNominalCenter / maxCenterDistance;
     549                 :          0 :           auto const headingFactor
     550         [ #  # ]:          0 :             = 1. - std::fabs(rss_route.object_data_on_route.route_heading_delta) / maxHeadingDelta;
     551                 :          0 :           rss_route.likelihood = physics::Probability(distanceFactor * headingFactor);
     552                 :            :         }
     553                 :            :         else
     554                 :            :         {
     555                 :            :           // center not within route anymore, or heading diff larger than 45 degree
     556                 :            :         }
     557                 :            :       }
     558                 :            :     }
     559                 :            :   }
     560                 :         17 : }
     561                 :            : 
     562                 :            : } // namespace map
     563                 :            : } // namespace rss
     564                 :            : } // namespace ad

Generated by: LCOV version 1.14