LCOV - code coverage report
Current view: top level - src/match - AdMapMatching.cpp (source / functions) Hit Total Coverage
Test: ad_map_access Lines: 272 314 86.6 %
Date: 2022-10-04 09:48:07 Functions: 29 31 93.5 %
Branches: 283 518 54.6 %

           Branch data     Line data    Source code
       1                 :            : // ----------------- BEGIN LICENSE BLOCK ---------------------------------
       2                 :            : //
       3                 :            : // Copyright (C) 2018-2021 Intel Corporation
       4                 :            : //
       5                 :            : // SPDX-License-Identifier: MIT
       6                 :            : //
       7                 :            : // ----------------- END LICENSE BLOCK -----------------------------------
       8                 :            : 
       9                 :            : #include "ad/map/match/AdMapMatching.hpp"
      10                 :            : 
      11                 :            : #include <algorithm>
      12                 :            : #include <cmath>
      13                 :            : #include <functional>
      14                 :            : #include "ad/map/access/Logging.hpp"
      15                 :            : #include "ad/map/access/Operation.hpp"
      16                 :            : #include "ad/map/lane/LaneOperation.hpp"
      17                 :            : #include "ad/map/match/MapMatchedOperation.hpp"
      18                 :            : #include "ad/map/point/Transform.hpp"
      19                 :            : #include "ad/physics/RangeOperation.hpp"
      20                 :            : 
      21                 :            : namespace ad {
      22                 :            : namespace map {
      23                 :            : namespace match {
      24                 :            : 
      25                 :            : match::MapMatchedPositionConfidenceList
      26                 :      21576 : AdMapMatching::findLanesInputChecked(std::vector<lane::Lane::ConstPtr> const &relevantLanes,
      27                 :            :                                      point::ECEFPoint const &ecefPoint,
      28                 :            :                                      physics::Distance const &distance)
      29                 :            : {
      30                 :      21576 :   match::MapMatchedPositionConfidenceList mapMatchingResults;
      31                 :      21576 :   physics::Probability probabilitySum(0.);
      32         [ +  + ]:     490589 :   for (auto lane : relevantLanes)
      33                 :            :   {
      34         [ +  - ]:     469013 :     MapMatchedPosition mmpt;
      35   [ +  -  +  - ]:     469013 :     if (lane::findNearestPointOnLane(*lane, ecefPoint, mmpt))
      36                 :            :     {
      37   [ +  -  +  + ]:     469013 :       if (mmpt.matchedPointDistance <= distance)
      38                 :            :       {
      39         [ +  - ]:     126201 :         mapMatchingResults.push_back(mmpt);
      40         [ +  - ]:     126201 :         probabilitySum += mmpt.probability;
      41                 :            :       }
      42                 :            :     }
      43                 :            :   }
      44                 :            : 
      45         [ +  - ]:      21576 :   normalizeResults(mapMatchingResults, probabilitySum);
      46                 :      43152 :   return mapMatchingResults;
      47                 :            : }
      48                 :            : 
      49                 :      21580 : void AdMapMatching::normalizeResults(match::MapMatchedPositionConfidenceList &mapMatchingResults,
      50                 :            :                                      physics::Probability const &probabilitySum)
      51                 :            : {
      52                 :            :   // normalize result probabilities
      53   [ +  -  +  + ]:      21580 :   if (probabilitySum > physics::Probability(0.01))
      54                 :            :   {
      55         [ +  + ]:     147780 :     for (auto &mmpt : mapMatchingResults)
      56                 :            :     {
      57         [ +  - ]:     126205 :       mmpt.probability = mmpt.probability / static_cast<double>(probabilitySum);
      58                 :            :     }
      59                 :            :   }
      60                 :            : 
      61                 :            :   // sort the final results
      62         [ +  - ]:      21580 :   std::sort(std::begin(mapMatchingResults),
      63                 :            :             std::end(mapMatchingResults),
      64                 :     308771 :             [](MapMatchedPosition const &left, MapMatchedPosition const &right) {
      65                 :     308771 :               return left.probability > right.probability;
      66                 :            :             });
      67                 :      21580 : }
      68                 :            : 
      69                 :            : match::MapMatchedPositionConfidenceList
      70                 :          4 : AdMapMatching::findLanesInputCheckedAltitudeUnknown(point::GeoPoint const &geo_point,
      71                 :            :                                                     physics::Distance const &distance,
      72                 :            :                                                     ::ad::map::lane::LaneIdSet const &relevantLaneSet)
      73                 :            : {
      74                 :          4 :   match::MapMatchedPositionConfidenceList map_matching_results;
      75                 :          4 :   physics::Probability probability_sum(0.);
      76                 :          8 :   std::vector<lane::Lane::ConstPtr> relevantLanes;
      77         [ -  + ]:          4 :   if (!relevantLaneSet.empty())
      78                 :            :   {
      79         [ #  # ]:          0 :     for (auto laneId : relevantLaneSet)
      80                 :            :     {
      81   [ #  #  #  # ]:          0 :       auto lane = access::getStore().getLanePtr(laneId);
      82         [ #  # ]:          0 :       if (lane)
      83                 :            :       {
      84         [ #  # ]:          0 :         relevantLanes.push_back(lane);
      85                 :            :       }
      86                 :            :     }
      87                 :            :   }
      88                 :            :   else
      89                 :            :   {
      90   [ +  -  +  -  :        568 :     for (auto laneId : access::getStore().getLanes())
                   +  + ]
      91                 :            :     {
      92   [ +  -  +  - ]:       1128 :       auto lane = access::getStore().getLanePtr(laneId);
      93         [ +  - ]:        564 :       if (lane)
      94                 :            :       {
      95         [ +  - ]:        564 :         relevantLanes.push_back(lane);
      96                 :            :       }
      97                 :            :     }
      98                 :            :   }
      99         [ +  + ]:        568 :   for (auto lane : relevantLanes)
     100                 :            :   {
     101         [ +  - ]:        564 :     auto const altitude_range = calcLaneAltitudeRange(*lane);
     102                 :        564 :     auto geo_point_check = geo_point;
     103   [ +  -  +  - ]:        564 :     auto const altitude_delta_2 = (altitude_range.maximum - altitude_range.minimum) / 2.;
     104         [ +  - ]:        564 :     geo_point_check.altitude = altitude_range.minimum + altitude_delta_2;
     105         [ +  - ]:        564 :     point::BoundingSphere matchingSphere;
     106         [ +  - ]:        564 :     matchingSphere.center = point::toECEF(geo_point_check);
     107         [ +  - ]:        564 :     matchingSphere.radius = distance + physics::Distance(static_cast<double>(altitude_delta_2));
     108   [ +  -  +  + ]:        564 :     if (lane::isNear(*lane, matchingSphere))
     109                 :            :     {
     110         [ +  - ]:         16 :       MapMatchedPosition mmpt;
     111   [ +  -  +  - ]:         16 :       if (lane::findNearestPointOnLane(*lane, matchingSphere.center, mmpt))
     112                 :            :       {
     113   [ +  -  +  + ]:         16 :         if (mmpt.matchedPointDistance <= matchingSphere.radius)
     114                 :            :         {
     115                 :            :           // now correct query point and assume the matched point's altitude to perform final local decision
     116         [ +  - ]:          4 :           geo_point_check.altitude = point::toGeo(mmpt.matchedPoint).altitude;
     117         [ +  - ]:          4 :           matchingSphere.center = point::toECEF(geo_point_check);
     118   [ +  -  +  - ]:          4 :           if (lane::findNearestPointOnLane(*lane, matchingSphere.center, mmpt))
     119                 :            :           {
     120   [ +  -  +  - ]:          4 :             if (mmpt.matchedPointDistance <= distance)
     121                 :            :             {
     122         [ +  - ]:          4 :               map_matching_results.push_back(mmpt);
     123         [ +  - ]:          4 :               probability_sum += mmpt.probability;
     124                 :            :             }
     125                 :            :           }
     126                 :            :         }
     127                 :            :       }
     128                 :            :     }
     129                 :            :   }
     130         [ +  - ]:          4 :   normalizeResults(map_matching_results, probability_sum);
     131                 :          8 :   return map_matching_results;
     132                 :            : }
     133                 :            : 
     134                 :            : std::vector<lane::Lane::ConstPtr>
     135                 :      21275 : AdMapMatching::getRelevantLanesInputChecked(point::ECEFPoint const &ecefPoint,
     136                 :            :                                             physics::Distance const &distance,
     137                 :            :                                             ::ad::map::lane::LaneIdSet const &relevantLaneSet)
     138                 :            : {
     139                 :      21275 :   std::vector<lane::Lane::ConstPtr> relevantLanes;
     140         [ +  + ]:      21275 :   if (!relevantLaneSet.empty())
     141                 :            :   {
     142         [ +  + ]:     485248 :     for (auto laneId : relevantLaneSet)
     143                 :            :     {
     144   [ +  -  +  - ]:     929696 :       auto lane = access::getStore().getLanePtr(laneId);
     145         [ +  - ]:     464848 :       if (lane)
     146                 :            :       {
     147         [ +  - ]:     464848 :         relevantLanes.push_back(lane);
     148                 :            :       }
     149                 :            :     }
     150                 :            :   }
     151                 :            :   else
     152                 :            :   {
     153         [ +  - ]:        875 :     point::BoundingSphere matchingSphere;
     154                 :        875 :     matchingSphere.center = ecefPoint;
     155                 :        875 :     matchingSphere.radius = distance;
     156   [ +  -  +  -  :     129503 :     for (auto laneId : access::getStore().getLanes())
                   +  + ]
     157                 :            :     {
     158   [ +  -  +  - ]:     257256 :       auto lane = access::getStore().getLanePtr(laneId);
     159                 :            : 
     160         [ +  - ]:     128628 :       if (lane)
     161                 :            :       {
     162   [ +  -  +  + ]:     128628 :         if (lane::isNear(*lane, matchingSphere))
     163                 :            :         {
     164         [ +  - ]:       2419 :           relevantLanes.push_back(lane);
     165                 :            :         }
     166                 :            :       }
     167                 :            :     }
     168                 :            :   }
     169                 :            : 
     170                 :      21275 :   return relevantLanes;
     171                 :            : }
     172                 :            : 
     173                 :            : match::MapMatchedPositionConfidenceList
     174                 :      21258 : AdMapMatching::findLanesInputChecked(point::ECEFPoint const &ecefPoint,
     175                 :            :                                      physics::Distance const &distance,
     176                 :            :                                      ::ad::map::lane::LaneIdSet const &relevantLaneSet)
     177                 :            : {
     178         [ +  - ]:      42516 :   return findLanesInputChecked(getRelevantLanesInputChecked(ecefPoint, distance, relevantLaneSet), ecefPoint, distance);
     179                 :            : }
     180                 :            : 
     181                 :      21259 : match::MapMatchedPositionConfidenceList AdMapMatching::findLanes(point::GeoPoint const &geoPoint,
     182                 :            :                                                                  physics::Distance const &distance,
     183                 :            :                                                                  ::ad::map::lane::LaneIdSet const &relevantLaneSet)
     184                 :            : {
     185         [ -  + ]:      21259 :   if (!distance.isValid())
     186                 :            :   {
     187         [ #  # ]:          0 :     access::getLogger()->error("Invalid radius passed to AdMapMatching::findLanes(): {}", distance);
     188                 :          0 :     return MapMatchedPositionConfidenceList();
     189                 :            :   }
     190         [ +  + ]:      21259 :   if (geoPoint.altitude == point::AltitudeUnknown)
     191                 :            :   {
     192   [ +  -  -  +  :          4 :     if (!withinValidInputRange(geoPoint.latitude) || !withinValidInputRange(geoPoint.longitude))
                   -  + ]
     193                 :            :     {
     194         [ #  # ]:          0 :       access::getLogger()->error(
     195                 :            :         "Invalid Latitude/Longitude of Geo Point passed to AdMapMatching::findLanes() with AltitudeUnknown: {}",
     196                 :            :         geoPoint);
     197                 :          0 :       return MapMatchedPositionConfidenceList();
     198                 :            :     }
     199                 :          4 :     return findLanesInputCheckedAltitudeUnknown(geoPoint, distance, relevantLaneSet);
     200                 :            :   }
     201                 :            :   else
     202                 :            :   {
     203         [ -  + ]:      21255 :     if (!isValid(geoPoint))
     204                 :            :     {
     205         [ #  # ]:          0 :       access::getLogger()->error("Invalid Geo Point passed to AdMapMatching::findLanes(): {}", geoPoint);
     206                 :          0 :       return MapMatchedPositionConfidenceList();
     207                 :            :     }
     208         [ +  - ]:      42510 :     return findLanesInputChecked(point::toECEF(geoPoint), distance, relevantLaneSet);
     209                 :            :   }
     210                 :            : }
     211                 :            : 
     212                 :          5 : match::MapMatchedPositionConfidenceList AdMapMatching::findLanes(point::ECEFPoint const &ecefPoint,
     213                 :            :                                                                  physics::Distance const &distance,
     214                 :            :                                                                  ::ad::map::lane::LaneIdSet const &relevantLaneSet)
     215                 :            : {
     216         [ +  + ]:          5 :   if (!isValid(ecefPoint))
     217                 :            :   {
     218         [ +  - ]:          2 :     access::getLogger()->error("Invalid ECEF Point passed to AdMapMatching::findLanes(): {}", ecefPoint);
     219                 :          1 :     return MapMatchedPositionConfidenceList();
     220                 :            :   }
     221         [ +  + ]:          4 :   if (!distance.isValid())
     222                 :            :   {
     223         [ +  - ]:          2 :     access::getLogger()->error("Invalid radius passed to AdMapMatching::findLanes(): {}", distance);
     224                 :          1 :     return MapMatchedPositionConfidenceList();
     225                 :            :   }
     226                 :          3 :   return findLanesInputChecked(ecefPoint, distance, relevantLaneSet);
     227                 :            : }
     228                 :            : 
     229                 :       1990 : AdMapMatching::AdMapMatching()
     230                 :            : {
     231                 :       1990 : }
     232                 :            : 
     233                 :          6 : point::ENUHeading AdMapMatching::getLaneENUHeading(MapMatchedPosition const &mapMatchedPosition) const
     234                 :            : {
     235                 :          6 :   return lane::getLaneENUHeading(mapMatchedPosition);
     236                 :            : }
     237                 :            : 
     238                 :     125728 : bool AdMapMatching::isLanePartOfRouteHints(lane::LaneId const &laneId) const
     239                 :            : {
     240         [ +  + ]:     125983 :   for (auto const &route : mRouteHints)
     241                 :            :   {
     242         [ +  + ]:        294 :     for (auto const &roadSegment : route.roadSegments)
     243                 :            :     {
     244         [ +  + ]:         72 :       for (auto const &laneSegment : roadSegment.drivableLaneSegments)
     245                 :            :       {
     246   [ +  -  +  + ]:         39 :         if (laneSegment.laneInterval.laneId == laneId)
     247                 :            :         {
     248                 :          6 :           return true;
     249                 :            :         }
     250                 :            :       }
     251                 :            :     }
     252                 :            :   }
     253                 :     125722 :   return false;
     254                 :            : }
     255                 :            : 
     256                 :     125726 : double AdMapMatching::getHeadingFactor(MapMatchedPosition const &matchedPosition) const
     257                 :            : {
     258                 :     125726 :   double headingFactor = 1.0;
     259                 :            : 
     260         [ +  + ]:     125726 :   if (mHeadingHints.size() > 0u)
     261                 :            :   {
     262         [ +  - ]:     123857 :     point::ECEFHeading const laneDrivingDirection = lane::getLaneECEFHeading(matchedPosition);
     263         [ +  + ]:     511266 :     for (auto const &headingHint : mHeadingHints)
     264                 :            :     {
     265                 :            :       // -1 <= dot product <= 1  (cosine between the two directional vectors)
     266         [ +  - ]:     387409 :       auto dotProduct = headingHint * laneDrivingDirection;
     267                 :            : 
     268                 :            :       // pushes the 1. <= headingFactor <= mHeadingHintFactor
     269                 :     387409 :       double newHeadingFactor = 1. + (dotProduct + 1.) / 2. * mHeadingHintFactor;
     270                 :     387409 :       headingFactor = std::max(headingFactor, newHeadingFactor);
     271                 :            :     }
     272                 :            : 
     273   [ +  -  +  - ]:     247714 :     access::getLogger()->trace("getHeadingFactor {}, {}", matchedPosition.lanePoint.paraPoint.laneId, headingFactor);
     274                 :            :   }
     275                 :     125726 :   return headingFactor;
     276                 :            : }
     277                 :            : 
     278                 :      21259 : MapMatchedPositionConfidenceList AdMapMatching::getMapMatchedPositions(point::GeoPoint const &geoPoint,
     279                 :            :                                                                        physics::Distance const &distance,
     280                 :            :                                                                        physics::Probability const &minProbability) const
     281                 :            : {
     282                 :      21259 :   auto mapMatchingResult = findLanes(geoPoint, distance, mRelevantLanes);
     283         [ +  - ]:      21259 :   mapMatchingResult = considerMapMatchingHints(mapMatchingResult, minProbability);
     284   [ +  -  +  - ]:      42518 :   access::getLogger()->trace("MapMatching result {}", mapMatchingResult);
     285                 :      21259 :   return mapMatchingResult;
     286                 :            : }
     287                 :            : 
     288                 :      20404 : MapMatchedPositionConfidenceList AdMapMatching::getMapMatchedPositions(point::ENUPoint const &enuPoint,
     289                 :            :                                                                        physics::Distance const &distance,
     290                 :            :                                                                        physics::Probability const &minProbability) const
     291                 :            : {
     292         [ +  - ]:      40808 :   return getMapMatchedPositions(point::toGeo(enuPoint), distance, minProbability);
     293                 :            : }
     294                 :            : 
     295                 :          2 : MapMatchedPositionConfidenceList AdMapMatching::getMapMatchedPositions(point::ENUPoint const &enuPoint,
     296                 :            :                                                                        point::GeoPoint const &enuReferencePoint,
     297                 :            :                                                                        physics::Distance const &distance,
     298                 :            :                                                                        physics::Probability const &minProbability) const
     299                 :            : {
     300         [ +  - ]:          4 :   return getMapMatchedPositions(point::toGeo(enuPoint, enuReferencePoint), distance, minProbability);
     301                 :            : }
     302                 :            : 
     303                 :          2 : MapMatchedPositionConfidenceList AdMapMatching::getMapMatchedPositions(ENUObjectPosition const &enuObjectPosition,
     304                 :            :                                                                        physics::Distance const &distance,
     305                 :            :                                                                        physics::Probability const &minProbability)
     306                 :            : {
     307                 :          2 :   addHeadingHint(enuObjectPosition.heading, enuObjectPosition.enuReferencePoint);
     308                 :            :   auto mapMatchedPositions = getMapMatchedPositions(
     309                 :          2 :     enuObjectPosition.centerPoint, enuObjectPosition.enuReferencePoint, distance, minProbability);
     310                 :          2 :   clearHeadingHints();
     311                 :          2 :   return mapMatchedPositions;
     312                 :            : }
     313                 :            : 
     314                 :            : MapMatchedPositionConfidenceList
     315                 :      21259 : AdMapMatching::considerMapMatchingHints(MapMatchedPositionConfidenceList const &mapMatchedPositions,
     316                 :            :                                         physics::Probability const &minProbability) const
     317                 :            : {
     318   [ +  -  +  - ]:      42518 :   access::getLogger()->trace("considerMapMatchingHints {}", mapMatchedPositions);
     319                 :            : 
     320                 :            :   // revised probabilities can be > 1. while calculating
     321                 :      21259 :   physics::Probability revisedProbabilitySum(0.);
     322                 :      21259 :   MapMatchedPositionConfidenceList mapMatchingResults;
     323         [ +  - ]:      21259 :   mapMatchingResults.reserve(mapMatchedPositions.size());
     324         [ +  + ]:     146985 :   for (auto const &mapMatchingResult : mapMatchedPositions)
     325                 :            :   {
     326                 :     125726 :     auto revisedProbability = mapMatchingResult.probability;
     327         [ +  - ]:     125726 :     if (match::isLaneType(mapMatchingResult.type))
     328                 :            :     {
     329                 :            :       // probability of lanes on current route are multiplied by a certain factor
     330   [ +  -  +  + ]:     125726 :       if (isLanePartOfRouteHints(mapMatchingResult.lanePoint.paraPoint.laneId))
     331                 :            :       {
     332   [ +  -  +  - ]:         10 :         access::getLogger()->trace("AdMapMatching::considerMapMatchingHints {} is on current route",
     333                 :          5 :                                    mapMatchingResult.lanePoint.paraPoint.laneId);
     334         [ +  - ]:          5 :         revisedProbability = revisedProbability * getRouteHintFactor();
     335                 :            :       }
     336                 :            : 
     337                 :            :       // add heading hint factor
     338   [ +  -  +  - ]:     125726 :       revisedProbability = revisedProbability * getHeadingFactor(mapMatchingResult);
     339                 :            :     }
     340                 :            : 
     341         [ +  - ]:     125726 :     revisedProbabilitySum = revisedProbabilitySum + revisedProbability;
     342         [ +  - ]:     125726 :     mapMatchingResults.push_back(mapMatchingResult);
     343                 :     125726 :     mapMatchingResults.back().probability = revisedProbability;
     344                 :            :   }
     345                 :            : 
     346                 :            :   // post processing
     347                 :          1 :   do
     348                 :            :   {
     349                 :      21260 :     auto const probabilityDivisor = revisedProbabilitySum;
     350   [ +  -  +  + ]:      21260 :     if (probabilityDivisor == physics::Probability(0.))
     351                 :            :     {
     352                 :          5 :       break;
     353                 :            :     }
     354                 :      21255 :     revisedProbabilitySum = physics::Probability(1.);
     355                 :      21255 :     size_t writeIndex = 0u;
     356         [ +  + ]:     146982 :     for (size_t readIndex = 0u; readIndex < mapMatchingResults.size(); ++readIndex)
     357                 :            :     {
     358         [ -  + ]:     125727 :       if (writeIndex != readIndex)
     359                 :            :       {
     360                 :          0 :         mapMatchingResults[writeIndex] = mapMatchingResults[readIndex];
     361                 :            :       }
     362                 :     125727 :       mapMatchingResults[writeIndex].probability
     363         [ +  - ]:     125727 :         = mapMatchingResults[writeIndex].probability / static_cast<double>(probabilityDivisor);
     364   [ +  -  +  + ]:     125727 :       if (mapMatchingResults[writeIndex].probability >= minProbability)
     365                 :            :       {
     366                 :            :         // write index only incremented if new probability is above minProbability
     367                 :     125726 :         writeIndex++;
     368                 :            :       }
     369                 :            :       else
     370                 :            :       {
     371                 :            :         // otherwise the entry is dropped so the probabilities of the others have to be adapted next loop
     372         [ +  - ]:          1 :         revisedProbabilitySum = revisedProbabilitySum - mapMatchingResults[writeIndex].probability;
     373                 :            :       }
     374                 :            :     }
     375         [ +  - ]:      21255 :     mapMatchingResults.resize(writeIndex);
     376   [ +  -  +  + ]:      21255 :   } while (revisedProbabilitySum < physics::Probability(1.));
     377                 :            : 
     378                 :            :   // sort the final results
     379         [ +  - ]:      21259 :   std::sort(std::begin(mapMatchingResults),
     380                 :            :             std::end(mapMatchingResults),
     381                 :     249409 :             [](MapMatchedPosition const &left, MapMatchedPosition const &right) {
     382                 :     249409 :               return left.probability > right.probability;
     383                 :            :             });
     384                 :      42518 :   return mapMatchingResults;
     385                 :            : }
     386                 :            : 
     387                 :         17 : MapMatchedObjectBoundingBox AdMapMatching::getMapMatchedBoundingBox(ENUObjectPosition const &enuObjectPosition,
     388                 :            :                                                                     physics::Distance const &samplingDistance) const
     389                 :            : {
     390         [ +  - ]:         17 :   MapMatchedObjectBoundingBox mapMatchedObjectBoundingBox;
     391                 :         17 :   mapMatchedObjectBoundingBox.samplingDistance = samplingDistance;
     392                 :            :   mapMatchedObjectBoundingBox.matchRadius
     393   [ +  -  +  -  :         17 :     = samplingDistance + (0.5 * enuObjectPosition.dimension.length) + (0.5 * enuObjectPosition.dimension.width);
             +  -  +  - ]
     394                 :            : 
     395                 :            :   // if the vehicle covers multiple lanes
     396                 :            :   // the occupied regions usually don't span up to the borders
     397                 :            :   // To ensure that longitudinally and laterally we don't miss parts of the lane in
     398                 :            :   // between the the sampling points, we have to ensure: point matching distance >= sampling distance
     399                 :            : 
     400                 :            :   // directly calculate in ECEF to get rid of unnecessary coordinate transformations
     401         [ +  - ]:         17 :   point::ENUPoint directionalVectorENU;
     402         [ +  - ]:         17 :   point::ENUPoint orthogonalVectorENU;
     403         [ +  - ]:         17 :   point::getDirectionVectorsZPlane(enuObjectPosition.heading, directionalVectorENU, orthogonalVectorENU);
     404                 :            : 
     405         [ +  - ]:         17 :   point::ECEFPoint const start = toECEF(enuObjectPosition.enuReferencePoint);
     406         [ +  - ]:         17 :   point::ECEFPoint const directionalVectorEnd = toECEF(directionalVectorENU, enuObjectPosition.enuReferencePoint);
     407   [ +  -  +  - ]:         17 :   point::ECEFPoint const directionalVector = vectorNorm(directionalVectorEnd - start);
     408         [ +  - ]:         17 :   point::ECEFPoint const orthogonalVectorEnd = toECEF(orthogonalVectorENU, enuObjectPosition.enuReferencePoint);
     409   [ +  -  +  - ]:         17 :   point::ECEFPoint const orthogonalVector = vectorNorm(orthogonalVectorEnd - start);
     410                 :            : 
     411   [ +  -  +  - ]:         17 :   point::ECEFPoint directionalLength = directionalVector * (0.5 * enuObjectPosition.dimension.length);
     412   [ +  -  +  - ]:         17 :   point::ECEFPoint directionalWidth = orthogonalVector * (0.5 * enuObjectPosition.dimension.width);
     413                 :            : 
     414   [ +  +  +  - ]:        102 :   point::ECEFPoint referencePoints[int32_t(ObjectReferencePoints::NumPoints)];
     415                 :            : 
     416                 :            :   referencePoints[int32_t(ObjectReferencePoints::Center)]
     417         [ +  - ]:         17 :     = toECEF(enuObjectPosition.centerPoint, enuObjectPosition.enuReferencePoint);
     418                 :            : 
     419                 :            :   referencePoints[int32_t(ObjectReferencePoints::FrontLeft)]
     420   [ +  -  +  - ]:         17 :     = (referencePoints[int32_t(ObjectReferencePoints::Center)] + directionalLength) + directionalWidth;
     421                 :            :   referencePoints[int32_t(ObjectReferencePoints::FrontRight)]
     422   [ +  -  +  - ]:         17 :     = (referencePoints[int32_t(ObjectReferencePoints::Center)] + directionalLength) - directionalWidth;
     423                 :            :   referencePoints[int32_t(ObjectReferencePoints::RearLeft)]
     424   [ +  -  +  - ]:         17 :     = (referencePoints[int32_t(ObjectReferencePoints::Center)] - directionalLength) + directionalWidth;
     425                 :            :   referencePoints[int32_t(ObjectReferencePoints::RearRight)]
     426   [ +  -  +  - ]:         17 :     = (referencePoints[int32_t(ObjectReferencePoints::Center)] - directionalLength) - directionalWidth;
     427                 :            : 
     428         [ -  + ]:         17 :   if (!samplingDistance.isValid())
     429                 :            :   {
     430   [ #  #  #  # ]:          0 :     access::getLogger()->error("Invalid sampling distance passed to AdMapMatching::getMapMatchedBoundingBox(): {}",
     431                 :            :                                samplingDistance);
     432                 :          0 :     return mapMatchedObjectBoundingBox;
     433                 :            :   }
     434         [ +  + ]:        102 :   for (size_t i = 0; i < size_t(ObjectReferencePoints::NumPoints); i++)
     435                 :            :   {
     436   [ +  -  -  + ]:         85 :     if (!isValid(referencePoints[i]))
     437                 :            :     {
     438   [ #  #  #  # ]:          0 :       access::getLogger()->error("Invalid reference point within AdMapMatching::getMapMatchedBoundingBox(): {}",
     439                 :          0 :                                  referencePoints[i]);
     440                 :          0 :       return mapMatchedObjectBoundingBox;
     441                 :            :     }
     442                 :            :   }
     443                 :            : 
     444                 :            :   // filter lanes on large scale first
     445                 :            :   auto const relevantLanes = getRelevantLanesInputChecked(
     446         [ +  - ]:         34 :     referencePoints[int32_t(ObjectReferencePoints::Center)], mapMatchedObjectBoundingBox.matchRadius, mRelevantLanes);
     447                 :            : 
     448         [ +  - ]:         17 :   mapMatchedObjectBoundingBox.referencePointPositions.resize(size_t(ObjectReferencePoints::NumPoints));
     449                 :            : 
     450                 :            :   // we have to ensure that the confidence list used for the calculation of the lane regions
     451                 :            :   // covers ALL matching samples at once!
     452                 :            :   // Otherwise the fill-up to inner borders of the region is not working properly
     453                 :         34 :   MapMatchedPositionConfidenceList regionConfidenceList;
     454         [ +  + ]:        102 :   for (size_t i = 0; i < size_t(ObjectReferencePoints::NumPoints); i++)
     455                 :            :   {
     456                 :         85 :     mapMatchedObjectBoundingBox.referencePointPositions[i]
     457         [ +  - ]:        170 :       = findLanesInputChecked(relevantLanes, referencePoints[i], samplingDistance);
     458                 :         85 :     regionConfidenceList.insert(regionConfidenceList.end(),
     459                 :         85 :                                 mapMatchedObjectBoundingBox.referencePointPositions[i].begin(),
     460         [ +  - ]:        255 :                                 mapMatchedObjectBoundingBox.referencePointPositions[i].end());
     461                 :            :   }
     462                 :            : 
     463                 :            :   // calculate actual sampling stride
     464                 :            :   // stride below 10cm doesn't actually make sense
     465         [ +  - ]:         17 :   physics::Distance const stride = std::max(samplingDistance, physics::Distance(0.1));
     466                 :            : 
     467         [ +  - ]:         17 :   auto const lengthStrideCount = std::ceil(enuObjectPosition.dimension.length / stride);
     468                 :         17 :   auto const lengthStrideCountUInt = static_cast<uint32_t>(lengthStrideCount);
     469         [ +  - ]:         17 :   auto const lengthStride = enuObjectPosition.dimension.length / lengthStrideCount;
     470         [ +  - ]:         17 :   point::ECEFPoint const lengthStrideVector = directionalVector * lengthStride;
     471                 :            : 
     472         [ +  - ]:         17 :   auto const widthStrideCount = std::ceil(enuObjectPosition.dimension.width / stride);
     473                 :         17 :   auto const widthStrideCountUInt = static_cast<uint32_t>(widthStrideCount);
     474         [ +  - ]:         17 :   auto const widthStride = enuObjectPosition.dimension.width / widthStrideCount;
     475         [ +  - ]:         17 :   point::ECEFPoint const widthStrideVector = orthogonalVector * widthStride;
     476                 :            : 
     477                 :         17 :   point::ECEFPoint widthStartPos = referencePoints[int32_t(ObjectReferencePoints::FrontLeft)];
     478                 :            : 
     479         [ +  + ]:         65 :   for (uint32_t widthStrideNum = 0u; widthStrideNum <= widthStrideCountUInt; widthStrideNum++)
     480                 :            :   {
     481                 :         48 :     point::ECEFPoint currentPoint = widthStartPos;
     482         [ +  + ]:        281 :     for (uint32_t lengthStrideNum = 0u; lengthStrideNum <= lengthStrideCountUInt; lengthStrideNum++)
     483                 :            :     {
     484                 :            :       MapMatchedPositionConfidenceList mapMatchedPositions
     485         [ +  - ]:        466 :         = findLanesInputChecked(relevantLanes, currentPoint, samplingDistance);
     486         [ +  - ]:        233 :       regionConfidenceList.insert(regionConfidenceList.end(), mapMatchedPositions.begin(), mapMatchedPositions.end());
     487                 :            : 
     488         [ +  - ]:        233 :       currentPoint = currentPoint - lengthStrideVector;
     489                 :            :     }
     490         [ +  - ]:         48 :     widthStartPos = widthStartPos - widthStrideVector;
     491                 :            :   }
     492                 :            : 
     493         [ +  - ]:         17 :   addLaneRegions(mapMatchedObjectBoundingBox.laneOccupiedRegions, regionConfidenceList);
     494                 :            : 
     495   [ +  -  +  - ]:         34 :   access::getLogger()->trace("getMapMatchedBoundingBox result {}", mapMatchedObjectBoundingBox);
     496                 :            : 
     497                 :         17 :   return mapMatchedObjectBoundingBox;
     498                 :            : }
     499                 :            : 
     500                 :          1 : LaneOccupiedRegionList AdMapMatching::getLaneOccupiedRegions(std::vector<ENUObjectPosition> enuObjectPositions,
     501                 :            :                                                              physics::Distance const &samplingDistance) const
     502                 :            : {
     503                 :          1 :   LaneOccupiedRegionList laneOccupiedRegions;
     504                 :            : 
     505         [ +  + ]:          2 :   for (auto const &objectPosition : enuObjectPositions)
     506                 :            :   {
     507         [ +  - ]:          2 :     auto const mapMatchedBoundingBox = getMapMatchedBoundingBox(objectPosition, samplingDistance);
     508         [ +  - ]:          1 :     addLaneRegions(laneOccupiedRegions, mapMatchedBoundingBox.laneOccupiedRegions);
     509                 :            :   }
     510                 :          1 :   return laneOccupiedRegions;
     511                 :            : }
     512                 :            : 
     513                 :        944 : inline bool isLateralInLaneMatch(const MapMatchedPosition &mapMatchedPosition)
     514                 :            : {
     515         [ +  - ]:        944 :   if ((mapMatchedPosition.lanePoint.lateralT > physics::RatioValue(1.0))
     516   [ +  +  +  -  :        944 :       || (mapMatchedPosition.lanePoint.lateralT < physics::RatioValue(0.0)))
             +  +  +  + ]
     517                 :            :   {
     518                 :        250 :     return false;
     519                 :            :   }
     520                 :        694 :   return true;
     521                 :            : }
     522                 :            : 
     523                 :        694 : inline bool isLongitudinalInLaneMatch(const MapMatchedPosition &mapMatchedPosition)
     524                 :            : {
     525                 :            :   // filter out longitudinal out-of-lane matches, indicated by border points being > 5cm away
     526         [ +  - ]:        694 :   if ((mapMatchedPosition.lanePoint.paraPoint.parametricOffset == physics::ParametricValue(0.))
     527   [ +  +  +  -  :        694 :       || (mapMatchedPosition.lanePoint.paraPoint.parametricOffset == physics::ParametricValue(1.)))
             +  +  +  + ]
     528                 :            :   {
     529   [ +  -  +  - ]:         54 :     if (mapMatchedPosition.matchedPointDistance > physics::Distance(0.05))
     530                 :            :     {
     531                 :         54 :       return false;
     532                 :            :     }
     533                 :            :   }
     534                 :        640 :   return true;
     535                 :            : }
     536                 :            : 
     537                 :        472 : inline bool isActualWithinLaneMatch(const MapMatchedPosition &mapMatchedPosition)
     538                 :            : {
     539   [ +  +  +  + ]:        472 :   return isLateralInLaneMatch(mapMatchedPosition) && isLongitudinalInLaneMatch(mapMatchedPosition);
     540                 :            : }
     541                 :            : 
     542                 :         17 : void AdMapMatching::addLaneRegions(LaneOccupiedRegionList &laneOccupiedRegions,
     543                 :            :                                    MapMatchedPositionConfidenceList const &mapMatchedPositions) const
     544                 :            : {
     545                 :            :   // Basic algorithm:
     546                 :            :   // First, collect all actual matches within the respective lane (lateral AND longitudinal)
     547                 :            :   // Second, ensure all inner-regions are expanded to the borders (lateral AND longitudinal)
     548                 :            : 
     549                 :            :   // 1. collect matches within the lane
     550                 :         34 :   std::map<lane::LaneId, physics::ParametricValue> longitudinalBorderMatches;
     551         [ +  + ]:        489 :   for (auto const &currentPosition : mapMatchedPositions)
     552                 :            :   {
     553                 :            :     // only consider actual lateral in lane matches
     554   [ +  -  +  + ]:        472 :     if (isLateralInLaneMatch(currentPosition))
     555                 :            :     {
     556                 :        347 :       physics::ParametricValue const currentLateralOffset(static_cast<double>(currentPosition.lanePoint.lateralT));
     557                 :            : 
     558   [ +  -  +  + ]:        347 :       if (isLongitudinalInLaneMatch(currentPosition))
     559                 :            :       {
     560                 :            :         // 1.a longitudinal in lane
     561                 :            :         auto search = std::find_if(std::begin(laneOccupiedRegions),
     562                 :            :                                    std::end(laneOccupiedRegions),
     563                 :        345 :                                    [currentPosition](LaneOccupiedRegion const &region) {
     564                 :        345 :                                      return region.laneId == currentPosition.lanePoint.paraPoint.laneId;
     565         [ +  - ]:        320 :                                    });
     566                 :            : 
     567         [ +  + ]:        320 :         if (search != laneOccupiedRegions.end())
     568                 :            :         {
     569         [ +  - ]:        299 :           unionRangeWith(search->longitudinalRange, currentPosition.lanePoint.paraPoint.parametricOffset);
     570         [ +  - ]:        299 :           unionRangeWith(search->lateralRange, currentLateralOffset);
     571                 :            :         }
     572                 :            :         else
     573                 :            :         {
     574         [ +  - ]:         21 :           LaneOccupiedRegion laneRegion;
     575                 :         21 :           laneRegion.laneId = currentPosition.lanePoint.paraPoint.laneId;
     576                 :         21 :           laneRegion.longitudinalRange.maximum = currentPosition.lanePoint.paraPoint.parametricOffset;
     577                 :         21 :           laneRegion.longitudinalRange.minimum = currentPosition.lanePoint.paraPoint.parametricOffset;
     578                 :         21 :           laneRegion.lateralRange.maximum = currentLateralOffset;
     579                 :         21 :           laneRegion.lateralRange.minimum = currentLateralOffset;
     580         [ +  - ]:         21 :           laneOccupiedRegions.push_back(laneRegion);
     581                 :            :         }
     582                 :            :       }
     583         [ +  - ]:         27 :       else if ((currentPosition.lanePoint.paraPoint.parametricOffset == physics::ParametricValue(0.))
     584   [ +  +  +  -  :         27 :                || (currentPosition.lanePoint.paraPoint.parametricOffset == physics::ParametricValue(1.)))
             +  -  +  - ]
     585                 :            :       {
     586                 :            :         // 1.b handle lane segments that are shorter than the sampling distance
     587                 :            :         // If we have short lane segment the sampling could jump over it
     588                 :            :         // Jumping over would be indicated by out of lane matches before (0.0) AND after (1.0)
     589                 :            :         auto insertResult = longitudinalBorderMatches.insert(
     590         [ +  - ]:         27 :           {currentPosition.lanePoint.paraPoint.laneId, currentPosition.lanePoint.paraPoint.parametricOffset});
     591         [ +  + ]:         27 :         if (!insertResult.second)
     592                 :            :         {
     593   [ +  -  +  + ]:         22 :           if (insertResult.first->second != currentPosition.lanePoint.paraPoint.parametricOffset)
     594                 :            :           {
     595                 :            :             // found a short lane segment to be added as a whole
     596                 :            :             auto search = std::find_if(std::begin(laneOccupiedRegions),
     597                 :            :                                        std::end(laneOccupiedRegions),
     598                 :         12 :                                        [currentPosition](LaneOccupiedRegion const &region) {
     599                 :         12 :                                          return region.laneId == currentPosition.lanePoint.paraPoint.laneId;
     600         [ +  - ]:          4 :                                        });
     601                 :            : 
     602         [ +  - ]:          4 :             if (search != laneOccupiedRegions.end())
     603                 :            :             {
     604                 :            :               // adapt the borders
     605                 :          4 :               search->longitudinalRange.maximum = physics::ParametricValue(1.);
     606                 :          4 :               search->longitudinalRange.minimum = physics::ParametricValue(0.);
     607                 :            :             }
     608                 :            :             else
     609                 :            :             {
     610                 :            :               // add the region
     611         [ #  # ]:          0 :               LaneOccupiedRegion laneRegion;
     612                 :          0 :               laneRegion.laneId = currentPosition.lanePoint.paraPoint.laneId;
     613                 :          0 :               laneRegion.longitudinalRange.maximum = physics::ParametricValue(1.);
     614                 :          0 :               laneRegion.longitudinalRange.minimum = physics::ParametricValue(0.);
     615                 :          0 :               laneRegion.lateralRange.maximum = currentLateralOffset;
     616                 :          0 :               laneRegion.lateralRange.minimum = currentLateralOffset;
     617         [ #  # ]:          0 :               laneOccupiedRegions.push_back(laneRegion);
     618                 :            :             }
     619                 :            :           }
     620                 :            :         }
     621                 :            :       }
     622                 :            :     }
     623                 :            :   }
     624                 :            :   // 2. If the vehicle covers multiple lanes the occupied regions usually don't span up to the borders
     625                 :            :   // since in the above loop only collects actual matches within the lane
     626                 :            :   // Since the likelihood for a match exactly at the border is very low, we have to enlarge
     627                 :            :   // the inner regions to cover also the space in between the map matching points
     628                 :            :   // This can be achieved by taking the out-of-lane matches into account.
     629                 :            :   // (Remember: we ensured that the matching distance >= sampling distance,
     630                 :            :   // so that respective out of lane matches are present!)
     631         [ +  + ]:        489 :   for (auto const &currentPosition : mapMatchedPositions)
     632                 :            :   {
     633   [ +  -  +  + ]:        472 :     if (!isActualWithinLaneMatch(currentPosition))
     634                 :            :     {
     635                 :            :       auto search = std::find_if(std::begin(laneOccupiedRegions),
     636                 :            :                                  std::end(laneOccupiedRegions),
     637                 :        204 :                                  [currentPosition](LaneOccupiedRegion const &region) {
     638                 :        204 :                                    return region.laneId == currentPosition.lanePoint.paraPoint.laneId;
     639         [ +  - ]:        152 :                                  });
     640                 :            : 
     641         [ +  + ]:        152 :       if (search != laneOccupiedRegions.end())
     642                 :            :       {
     643                 :            :         // 2.a in longitudinal direction just perform union (either in-lane and present in each case, or out-of-lane and
     644                 :            :         // therefore exactly 1.0 or 0.0)
     645         [ +  - ]:         30 :         unionRangeWith(search->longitudinalRange, currentPosition.lanePoint.paraPoint.parametricOffset);
     646                 :            : 
     647                 :            :         // 2.b in lateral direction map out-of-lane to in lane
     648   [ +  -  +  + ]:         30 :         if (currentPosition.lanePoint.lateralT >= physics::RatioValue(1.0))
     649                 :            :         {
     650         [ +  - ]:         10 :           unionRangeWith(search->lateralRange, physics::ParametricValue(1.0));
     651                 :            :         }
     652   [ +  -  +  + ]:         20 :         else if (currentPosition.lanePoint.lateralT <= physics::RatioValue(0.0))
     653                 :            :         {
     654         [ +  - ]:          4 :           unionRangeWith(search->lateralRange, physics::ParametricValue(0.0));
     655                 :            :         }
     656                 :            :       }
     657                 :            :     }
     658                 :            :   }
     659                 :         17 : }
     660                 :            : 
     661                 :          3 : void AdMapMatching::addLaneRegions(LaneOccupiedRegionList &laneOccupiedRegions,
     662                 :            :                                    LaneOccupiedRegionList const &otherLaneOccupiedRegions) const
     663                 :            : {
     664         [ +  + ]:          6 :   for (auto const &otherRegion : otherLaneOccupiedRegions)
     665                 :            :   {
     666                 :            :     auto search
     667                 :            :       = std::find_if(std::begin(laneOccupiedRegions),
     668                 :            :                      std::end(laneOccupiedRegions),
     669         [ +  - ]:          4 :                      [otherRegion](LaneOccupiedRegion const &region) { return region.laneId == otherRegion.laneId; });
     670                 :            : 
     671         [ +  + ]:          3 :     if (search != laneOccupiedRegions.end())
     672                 :            :     {
     673         [ +  - ]:          1 :       unionRangeWith(search->longitudinalRange, otherRegion.longitudinalRange);
     674         [ +  - ]:          1 :       unionRangeWith(search->lateralRange, otherRegion.lateralRange);
     675                 :            :     }
     676                 :            :     else
     677                 :            :     {
     678         [ +  - ]:          2 :       laneOccupiedRegions.push_back(otherRegion);
     679                 :            :     }
     680                 :            :   }
     681                 :          3 : }
     682                 :            : 
     683                 :          0 : MapMatchedPositionConfidenceList AdMapMatching::findRouteLanes(point::ECEFPoint const &ecefPoint,
     684                 :            :                                                                route::FullRoute const &route)
     685                 :            : {
     686   [ #  #  #  # ]:          0 :   if (!isValid(ecefPoint))
     687                 :            :   {
     688   [ #  #  #  # ]:          0 :     access::getLogger()->error("Invalid ECEF Point passed to AdMapMatching::findLanes(): {}", ecefPoint);
     689                 :          0 :     return MapMatchedPositionConfidenceList();
     690                 :            :   }
     691                 :          0 :   match::MapMatchedPositionConfidenceList mapMatchingResults;
     692                 :          0 :   physics::Distance distanceSum(0.);
     693         [ #  # ]:          0 :   for (auto const &roadSegment : route.roadSegments)
     694                 :            :   {
     695         [ #  # ]:          0 :     for (auto const &laneSegment : roadSegment.drivableLaneSegments)
     696                 :            :     {
     697         [ #  # ]:          0 :       MapMatchedPosition mmpt;
     698   [ #  #  #  # ]:          0 :       if (lane::findNearestPointOnLaneInterval(laneSegment.laneInterval, ecefPoint, mmpt))
     699                 :            :       {
     700         [ #  # ]:          0 :         mapMatchingResults.push_back(mmpt);
     701         [ #  # ]:          0 :         distanceSum += mmpt.matchedPointDistance;
     702                 :            :       }
     703                 :            :     }
     704                 :            :   }
     705                 :            : 
     706                 :            :   // set the result probabilities in respect to matched point distances
     707   [ #  #  #  # ]:          0 :   if (distanceSum > physics::Distance(0.01))
     708                 :            :   {
     709         [ #  # ]:          0 :     for (auto &mmpt : mapMatchingResults)
     710                 :            :     {
     711   [ #  #  #  # ]:          0 :       mmpt.probability = physics::Probability(1.) - physics::Probability(mmpt.matchedPointDistance / distanceSum);
     712                 :            :     }
     713                 :            :   }
     714                 :            : 
     715                 :            :   // sort the final results
     716         [ #  # ]:          0 :   std::sort(std::begin(mapMatchingResults),
     717                 :            :             std::end(mapMatchingResults),
     718                 :          0 :             [](MapMatchedPosition const &left, MapMatchedPosition const &right) {
     719                 :          0 :               return left.probability > right.probability;
     720                 :            :             });
     721                 :            : 
     722                 :          0 :   return mapMatchingResults;
     723                 :            : }
     724                 :            : 
     725                 :            : } // namespace match
     726                 :            : } // namespace map
     727                 :            : } // namespace ad

Generated by: LCOV version 1.14