LCOV - code coverage report
Current view: top level - src - RssObjectConversion.cpp (source / functions) Hit Total Coverage
Test: ad_rss_map_integration Lines: 141 154 91.6 %
Date: 2025-07-22 06:56:19 Functions: 16 16 100.0 %
Branches: 70 142 49.3 %

           Branch data     Line data    Source code
       1                 :            : // ----------------- BEGIN LICENSE BLOCK ---------------------------------
       2                 :            : //
       3                 :            : // Copyright (C) 2018-2021 Intel Corporation
       4                 :            : //
       5                 :            : // SPDX-License-Identifier: LGPL-2.1-only
       6                 :            : //
       7                 :            : // ----------------- END LICENSE BLOCK -----------------------------------
       8                 :            : 
       9                 :            : #include "ad/rss/map/RssObjectConversion.hpp"
      10                 :            : 
      11                 :            : #include <ad/map/point/HeadingOperation.hpp>
      12                 :            : #include <ad/map/route/RouteOperation.hpp>
      13                 :            : #include <ad/physics/Operation.hpp>
      14                 :            : #include <ad/rss/structured/RssFormulas.hpp>
      15                 :            : #include <algorithm>
      16                 :            : #include "ad/rss/map/Logging.hpp"
      17                 :            : #include "ad/rss/map/RssWorldModelCreator.hpp"
      18                 :            : 
      19                 :            : namespace ad {
      20                 :            : namespace rss {
      21                 :            : namespace map {
      22                 :            : 
      23                 :        526 : RssObjectConversion::RssObjectConversion(RssObjectData const &object_data)
      24                 :        526 :   : mObjectMapMatchedPosition(&object_data.match_object)
      25                 :        526 :   , mMaxSpeedOnAcceleration(0.)
      26                 :        526 :   , mOriginalObjectSpeed(object_data.speed_range)
      27                 :        526 :   , mRssDynamics(object_data.rss_dynamics)
      28                 :            : {
      29                 :        526 :   initializeRssObject(object_data.id,
      30         [ +  + ]:        526 :                       object_data.type,
      31                 :        527 :                       ::ad::rss::world::OccupiedRegionVector(),
      32                 :        526 :                       object_data.match_object.enu_position,
      33                 :        526 :                       object_data.speed_range,
      34                 :        526 :                       object_data.yaw_rate,
      35                 :        526 :                       object_data.steering_angle);
      36                 :        526 : }
      37                 :            : 
      38                 :          6 : RssObjectConversion::RssObjectConversion(RssObjectData const &object_data,
      39                 :          6 :                                          ::ad::rss::world::OccupiedRegionVector const &objectOccupiedRegions)
      40                 :          6 :   : mObjectMapMatchedPosition(nullptr)
      41                 :          6 :   , mMaxSpeedOnAcceleration(0.)
      42                 :          6 :   , mOriginalObjectSpeed(object_data.speed_range)
      43                 :          6 :   , mRssDynamics(object_data.rss_dynamics)
      44                 :            : {
      45                 :          6 :   initializeRssObject(object_data.id,
      46                 :          6 :                       object_data.type,
      47                 :            :                       objectOccupiedRegions,
      48                 :          6 :                       object_data.match_object.enu_position,
      49                 :          6 :                       object_data.speed_range,
      50                 :          6 :                       object_data.yaw_rate,
      51         [ +  - ]:          6 :                       object_data.steering_angle);
      52                 :          6 : }
      53                 :            : 
      54                 :        532 : void RssObjectConversion::initializeRssObject(::ad::rss::world::ObjectId const &object_id,
      55                 :            :                                               ::ad::rss::world::ObjectType const &object_type,
      56                 :            :                                               ::ad::rss::world::OccupiedRegionVector const &objectOccupiedRegions,
      57                 :            :                                               ::ad::map::match::ENUObjectPosition const &objectEnuPosition,
      58                 :            :                                               ::ad::physics::SpeedRange const &objectSpeed,
      59                 :            :                                               ::ad::physics::AngularVelocity const &objectYawRate,
      60                 :            :                                               ::ad::physics::Angle const &objectSteeringAngle)
      61                 :            : {
      62                 :        532 :   mRssObject.object_id = object_id;
      63                 :        532 :   mRssObject.object_type = object_type;
      64                 :        532 :   mRssObject.velocity.speed_lon_min = ::ad::physics::Speed(0.);
      65                 :        532 :   mRssObject.velocity.speed_lon_max = ::ad::physics::Speed(0.);
      66                 :        532 :   mRssObject.velocity.speed_lat_min = ::ad::physics::Speed(0.);
      67                 :        532 :   mRssObject.velocity.speed_lat_max = ::ad::physics::Speed(0.);
      68                 :        532 :   mRssObject.occupied_regions = objectOccupiedRegions;
      69                 :            : 
      70                 :        532 :   mRssObject.state.yaw = ::ad::physics::Angle(objectEnuPosition.heading.mENUHeading);
      71                 :        532 :   mRssObject.state.center_point.x = ::ad::physics::Distance(objectEnuPosition.center_point.x.mENUCoordinate);
      72                 :        532 :   mRssObject.state.center_point.y = ::ad::physics::Distance(objectEnuPosition.center_point.y.mENUCoordinate);
      73                 :        532 :   mRssObject.state.dimension.width = objectEnuPosition.dimension.width;
      74                 :        532 :   mRssObject.state.dimension.length = objectEnuPosition.dimension.length;
      75                 :        532 :   mRssObject.state.steering_angle = objectSteeringAngle;
      76                 :            : 
      77                 :            :   // restrict to positive speeds
      78         [ +  + ]:        532 :   mRssObject.state.speed_range.minimum = std::max(::ad::physics::Speed(0.), objectSpeed.minimum);
      79         [ +  - ]:        531 :   mRssObject.state.speed_range.maximum = std::max(::ad::physics::Speed(0.), objectSpeed.maximum);
      80   [ +  -  +  + ]:        531 :   if (mRssObject.state.speed_range.maximum == ::ad::physics::Speed(0.))
      81                 :            :   {
      82                 :            :     // ensure angular speed is also zero if speed is zero
      83                 :          6 :     mRssObject.state.yaw_rate = ::ad::physics::AngularVelocity(0.);
      84                 :            :   }
      85                 :            :   else
      86                 :            :   {
      87                 :        525 :     mRssObject.state.yaw_rate = objectYawRate;
      88                 :            :   }
      89                 :        531 : }
      90                 :            : 
      91                 :        734 : bool RssObjectConversion::isOriginalSpeedAcceptable(::ad::physics::Speed const acceptableNegativeSpeed) const
      92                 :            : {
      93         [ +  - ]:        734 :   if (mRssObject.state.speed_range == mOriginalObjectSpeed)
      94                 :            :   {
      95                 :        734 :     return true;
      96                 :            :   }
      97         [ #  # ]:          0 :   if (mOriginalObjectSpeed.minimum >= acceptableNegativeSpeed)
      98                 :            :   {
      99                 :          0 :     return true;
     100                 :            :   }
     101                 :          0 :   return false;
     102                 :            : }
     103                 :            : 
     104                 :       2350 : ::ad::rss::world::Object const &RssObjectConversion::getRssObject() const
     105                 :            : {
     106                 :       2350 :   return mRssObject;
     107                 :            : }
     108                 :            : 
     109                 :       6816 : ::ad::rss::world::ObjectId RssObjectConversion::getId() const
     110                 :            : {
     111                 :       6816 :   return mRssObject.object_id;
     112                 :            : }
     113                 :            : 
     114                 :        870 : ::ad::rss::world::RssDynamics RssObjectConversion::getRssDynamics() const
     115                 :            : {
     116                 :        870 :   ::ad::rss::world::RssDynamics resultDynamics(mRssDynamics);
     117   [ +  -  +  + ]:        870 :   if (mMaxSpeedOnAcceleration != ::ad::physics::Speed(0.))
     118                 :            :   {
     119                 :        481 :     resultDynamics.max_speed_on_acceleration = mMaxSpeedOnAcceleration;
     120                 :            :   }
     121                 :        870 :   return resultDynamics;
     122                 :            : }
     123                 :            : 
     124                 :        548 : bool RssObjectConversion::calculateConservativeMinStoppingDistance(
     125                 :            :   ::ad::rss::world::ObjectId const &object_id,
     126                 :            :   ::ad::physics::Speed const &current_max_speed,
     127                 :            :   ::ad::rss::world::RssDynamics const &rss_dynamics,
     128                 :            :   ::ad::physics::Distance &conservativeMinStoppingDistance)
     129                 :            : {
     130                 :            :   auto const result
     131         [ +  - ]:        548 :     = structured::calculateLongitudinalDistanceOffsetAfterStatedBrakingPattern(current_max_speed,
     132                 :          0 :                                                                                physics::Speed::getMax(),
     133                 :        548 :                                                                                rss_dynamics.response_time,
     134                 :        548 :                                                                                rss_dynamics.alpha_lon.accel_max,
     135                 :        548 :                                                                                rss_dynamics.alpha_lon.brake_min_correct,
     136                 :            :                                                                                conservativeMinStoppingDistance);
     137                 :            : 
     138         [ -  + ]:        548 :   if (!result)
     139                 :            :   {
     140         [ #  # ]:          0 :     getLogger()->error(
     141                 :            :       "RssObjectConversion::calculateConservativeMinStoppingDistance[ {} ]>> error calculating longitudinal "
     142                 :            :       "distance offset after stated braking pattern {} {}",
     143                 :            :       object_id,
     144                 :            :       current_max_speed,
     145                 :            :       rss_dynamics);
     146                 :            :   }
     147                 :        548 :   return result;
     148                 :            : }
     149                 :            : 
     150                 :        522 : bool RssObjectConversion::calculateConservativeMinStoppingDistance(
     151                 :            :   ::ad::physics::Distance &conservativeMinStoppingDistance) const
     152                 :            : {
     153                 :       1044 :   return calculateConservativeMinStoppingDistance(
     154                 :        522 :     mRssObject.object_id, mRssObject.state.speed_range.maximum, mRssDynamics, conservativeMinStoppingDistance);
     155                 :            : }
     156                 :            : 
     157                 :       1997 : void RssObjectConversion::updateSpeedLimit(::ad::physics::Speed const &max_speed_on_acceleration)
     158                 :            : {
     159         [ +  - ]:       1997 :   if (withinValidInputRange(max_speed_on_acceleration, false))
     160                 :            :   {
     161                 :       1997 :     mMaxSpeedOnAcceleration = std::max(mMaxSpeedOnAcceleration, max_speed_on_acceleration);
     162                 :            :   }
     163                 :       1997 : }
     164                 :            : 
     165                 :        897 : void RssObjectConversion::addRestrictedOccupiedRegion(::ad::map::match::LaneOccupiedRegion const &laneOccupiedRegion,
     166                 :            :                                                       ::ad::map::route::LaneInterval const &lane_interval)
     167                 :            : {
     168         [ +  - ]:        897 :   ::ad::rss::world::OccupiedRegion occupiedRegion;
     169                 :        897 :   occupiedRegion.segment_id = ::ad::rss::world::LaneSegmentId(laneOccupiedRegion.lane_id.mLaneId);
     170                 :            : 
     171                 :        897 :   ::ad::physics::ParametricValue cutAtStart;
     172   [ +  -  +  + ]:        897 :   if (::ad::map::route::isRouteDirectionNegative(lane_interval))
     173                 :            :   {
     174                 :            :     occupiedRegion.lon_range.maximum
     175         [ +  - ]:        354 :       = ::ad::physics::ParametricValue(1.) - laneOccupiedRegion.longitudinal_range.minimum;
     176                 :            :     occupiedRegion.lon_range.minimum
     177         [ +  - ]:        354 :       = ::ad::physics::ParametricValue(1.) - laneOccupiedRegion.longitudinal_range.maximum;
     178                 :            : 
     179         [ +  - ]:        354 :     occupiedRegion.lat_range.maximum = ::ad::physics::ParametricValue(1.) - laneOccupiedRegion.lateral_range.minimum;
     180         [ +  - ]:        354 :     occupiedRegion.lat_range.minimum = ::ad::physics::ParametricValue(1.) - laneOccupiedRegion.lateral_range.maximum;
     181         [ +  - ]:        354 :     cutAtStart = ::ad::physics::ParametricValue(1.) - lane_interval.start;
     182                 :            :   }
     183                 :            :   else
     184                 :            :   {
     185                 :        543 :     occupiedRegion.lon_range = laneOccupiedRegion.longitudinal_range;
     186                 :        543 :     occupiedRegion.lat_range = laneOccupiedRegion.lateral_range;
     187                 :        543 :     cutAtStart = lane_interval.start;
     188                 :            :   }
     189                 :            : 
     190                 :            :   // scale region to the lane interval sizes
     191         [ +  - ]:        897 :   auto const intervalLength = calcParametricLength(lane_interval);
     192   [ +  -  +  + ]:        897 :   if (intervalLength == ::ad::physics::ParametricValue(0.))
     193                 :            :   {
     194                 :        228 :     occupiedRegion.lon_range.minimum = ::ad::physics::ParametricValue(0.);
     195                 :        228 :     occupiedRegion.lon_range.maximum = ::ad::physics::ParametricValue(1.);
     196                 :            :   }
     197                 :            :   else
     198                 :            :   {
     199                 :            :     // move region
     200         [ +  - ]:        669 :     occupiedRegion.lon_range.minimum -= cutAtStart;
     201         [ +  - ]:        669 :     occupiedRegion.lon_range.maximum -= cutAtStart;
     202                 :            :     // scale region
     203         [ +  - ]:        669 :     occupiedRegion.lon_range.minimum = occupiedRegion.lon_range.minimum / intervalLength.mParametricValue;
     204         [ +  - ]:        669 :     occupiedRegion.lon_range.maximum = occupiedRegion.lon_range.maximum / intervalLength.mParametricValue;
     205                 :            :     // restrict to segment
     206                 :            :     occupiedRegion.lon_range.minimum
     207   [ +  -  +  - ]:        669 :       = std::min(std::max(occupiedRegion.lon_range.minimum, ::ad::physics::ParametricValue(0.)),
     208                 :        669 :                  ::ad::physics::ParametricValue(1.));
     209                 :            :     occupiedRegion.lon_range.maximum
     210   [ +  -  +  - ]:        669 :       = std::min(std::max(occupiedRegion.lon_range.maximum, ::ad::physics::ParametricValue(0.)),
     211                 :       1338 :                  ::ad::physics::ParametricValue(1.));
     212                 :            :   }
     213   [ +  -  +  - ]:       1794 :   getLogger()->trace(
     214                 :            :     "RssObjectConversion::addRestrictedOccupiedRegion[ {} ]>>laneOccupiedRegion {} lane_interval {} -> "
     215                 :            :     "occupiedRegion {}",
     216   [ +  -  +  - ]:       1794 :     getId(),
     217                 :            :     laneOccupiedRegion,
     218                 :            :     lane_interval,
     219                 :            :     occupiedRegion);
     220                 :            : 
     221         [ +  - ]:        897 :   mRssObject.occupied_regions.push_back(occupiedRegion);
     222                 :        897 : }
     223                 :            : 
     224                 :       1997 : void RssObjectConversion::laneIntervalAdded(::ad::map::route::LaneInterval const &lane_interval)
     225                 :            : {
     226         [ +  - ]:       1997 :   if (mObjectMapMatchedPosition != nullptr)
     227                 :            :   {
     228                 :            :     auto findLaneIntervalResult
     229         [ +  - ]:       1997 :       = std::find_if(mObjectMapMatchedPosition->map_matched_bounding_box.lane_occupied_regions.begin(),
     230                 :       1997 :                      mObjectMapMatchedPosition->map_matched_bounding_box.lane_occupied_regions.end(),
     231                 :       3354 :                      [lane_interval](::ad::map::match::LaneOccupiedRegion const &occupiedRegion) {
     232                 :       3354 :                        return lane_interval.lane_id == occupiedRegion.lane_id;
     233                 :            :                      });
     234         [ +  + ]:       1997 :     if (findLaneIntervalResult != mObjectMapMatchedPosition->map_matched_bounding_box.lane_occupied_regions.end())
     235                 :            :     {
     236         [ +  - ]:        897 :       addRestrictedOccupiedRegion(*findLaneIntervalResult, lane_interval);
     237                 :            :     }
     238                 :            :   }
     239                 :       1997 : }
     240                 :            : 
     241                 :        783 : void RssObjectConversion::updateVelocityOnRoute(::ad::map::point::ENUHeading const &route_heading)
     242                 :            : {
     243         [ +  + ]:        783 :   if (mRssObject.object_type == ::ad::rss::world::ObjectType::ArtificialVehicle)
     244                 :            :   {
     245                 :            :     // artificial vehicles are expected to drive along the respective route
     246                 :            :     // otherwhise in intersection areas they get -- depending on the route constellation --
     247                 :            :     // non reasonalbe lateral speeds
     248                 :            :     // @todo: if this is required to become possible in future, each route would desire its own
     249                 :            :     // artificial vehicle placed with the appropriate route heading
     250                 :          1 :     mRssObject.velocity.speed_lon_min = mRssObject.state.speed_range.minimum;
     251                 :          1 :     mRssObject.velocity.speed_lon_max = mRssObject.state.speed_range.maximum;
     252                 :          1 :     mRssObject.velocity.speed_lat_min = ::ad::physics::Speed(0.);
     253                 :          1 :     mRssObject.velocity.speed_lat_max = ::ad::physics::Speed(0.);
     254                 :            :   }
     255                 :            :   else
     256                 :            :   {
     257                 :            :     double headingDiff
     258         [ +  - ]:        782 :       = physics::normalizeAngleSigned(
     259                 :        782 :           physics::Angle(route_heading.mENUHeading - mObjectMapMatchedPosition->enu_position.heading.mENUHeading))
     260                 :        782 :           .mAngle;
     261                 :            : 
     262                 :        782 :     auto const headingDiffLonFactor = std::fabs(std::cos(headingDiff));
     263         [ +  - ]:        782 :     mRssObject.velocity.speed_lon_min = headingDiffLonFactor * mRssObject.state.speed_range.minimum;
     264         [ +  - ]:        782 :     mRssObject.velocity.speed_lon_max = headingDiffLonFactor * mRssObject.state.speed_range.maximum;
     265                 :            : 
     266                 :        782 :     auto const headingDiffLatFactor = std::sin(headingDiff);
     267         [ +  + ]:        782 :     if (headingDiffLatFactor < 0.)
     268                 :            :     {
     269         [ +  - ]:        256 :       mRssObject.velocity.speed_lat_min = headingDiffLatFactor * mRssObject.state.speed_range.maximum;
     270         [ +  - ]:        256 :       mRssObject.velocity.speed_lat_max = headingDiffLatFactor * mRssObject.state.speed_range.minimum;
     271                 :            :     }
     272                 :            :     else
     273                 :            :     {
     274         [ +  - ]:        526 :       mRssObject.velocity.speed_lat_min = headingDiffLatFactor * mRssObject.state.speed_range.minimum;
     275         [ +  - ]:        526 :       mRssObject.velocity.speed_lat_max = headingDiffLatFactor * mRssObject.state.speed_range.maximum;
     276                 :            :     }
     277                 :            :   }
     278                 :        783 : }
     279                 :            : 
     280                 :        127 : bool RssObjectConversion::updateVelocityOnRoute(::ad::map::route::FullRoute const &route)
     281                 :            : {
     282         [ -  + ]:        127 :   if (mObjectMapMatchedPosition == nullptr)
     283                 :            :   {
     284   [ #  #  #  # ]:          0 :     getLogger()->error(
     285                 :            :       "RssObjectConversion::updateVelocityOnRoute[ {} ] No map matched position of the object available. "
     286                 :            :       "Cannot calculate the orientation of the route at the object position",
     287   [ #  #  #  # ]:          0 :       getId());
     288                 :          0 :     return false;
     289                 :            :   }
     290                 :        127 :   ::ad::map::point::ENUHeading route_heading;
     291         [ -  + ]:        127 :   if (mRssObject.object_type == ::ad::rss::world::ObjectType::ArtificialVehicle)
     292                 :            :   {
     293                 :            :     // artificial vehicles are expected to drive along the respective route
     294                 :            :     // otherwhise in intersection areas they get -- depending on the route constellation --
     295                 :            :     // non reasonalbe lateral speeds
     296                 :            :     // @todo: if this is required to become possible in future, each route would desire its own
     297                 :            :     // artificial vehicle placed with the appropriate route heading
     298                 :          0 :     route_heading = mObjectMapMatchedPosition->enu_position.heading;
     299                 :            :   }
     300                 :            :   else
     301                 :            :   {
     302         [ +  - ]:        127 :     route_heading = getENUHeadingOfRoute(*mObjectMapMatchedPosition, route);
     303   [ +  -  -  + ]:        127 :     if (std::fabs(route_heading) >= ad::map::point::ENUHeading(2 * M_PI))
     304                 :            :     {
     305                 :            :       // if the map matched bounding box is outside, getENUHeadingOfRoute() returns 2*M_PI
     306                 :            :       // this should not happen
     307                 :            :       // - if the route input is derived from a connecting route,
     308                 :            :       //   the updateVelocityOnRoute() function with the provided route_heading from the connected route
     309                 :            :       //   should be taken as on creation of the ConnectedRoute the bounding boxes of the two vehicles are
     310                 :            :       //   are removed from the routes to ensure the connected route is actually in between the two vehicles
     311                 :            :       // - otherwise, the route should come either from an actually planned or predicted route of this vehicles.
     312                 :            :       //   In such case the
     313   [ #  #  #  # ]:          0 :       getLogger()->error(
     314                 :            :         "RssObjectConversion::updateVelocityOnRoute[ {} ] object seems to be located outside the route,"
     315                 :            :         "so calculating route heading seems to be impossible. {} {}",
     316         [ #  # ]:          0 :         getId(),
     317         [ #  # ]:          0 :         *mObjectMapMatchedPosition,
     318                 :            :         route);
     319                 :          0 :       return false;
     320                 :            :     }
     321                 :            :   }
     322                 :            : 
     323         [ +  - ]:        127 :   updateVelocityOnRoute(route_heading);
     324                 :        127 :   return true;
     325                 :            : }
     326                 :            : 
     327                 :        261 : ::ad::physics::Distance RssObjectConversion::getDistanceEstimate(RssObjectConversion::ConstPtr other) const
     328                 :            : {
     329         [ +  - ]:        261 :   auto const d_x = (mRssObject.state.center_point.x - other->mRssObject.state.center_point.x);
     330         [ +  - ]:        261 :   auto const d_y = (mRssObject.state.center_point.y - other->mRssObject.state.center_point.y);
     331   [ +  -  +  -  :        261 :   return std::sqrt(d_x * d_x + d_y * d_y);
             +  -  +  - ]
     332                 :            : }
     333                 :            : 
     334                 :            : } // namespace map
     335                 :            : } // namespace rss
     336                 :            : } // namespace ad

Generated by: LCOV version 1.14