LCOV - code coverage report
Current view: top level - motion - imotion_model.h (source / functions) Coverage Total Hit
Test: lcov.info Lines: 93.8 % 32 30
Test Date: 2026-04-26 21:52:20 Functions: 42.9 % 28 12
Legend: Lines: hit not hit

            Line data    Source code
       1              : #ifndef D33C0BB9_EF21_44C6_8DAD_0C38C418D824
       2              : #define D33C0BB9_EF21_44C6_8DAD_0C38C418D824
       3              : 
       4              : #include "base/first_include.h" // IWYU pragma: keep
       5              : #include "base/require_abstract_intf.h"
       6              : #include "env/ego_motion.h"
       7              : #include "filter/information_filter.h"
       8              : #include "filter/kalman_filter.h"
       9              : #include "math/linalg/contracts/covariance_matrix_policy_intf.h" // IWYU pragma: keep
      10              : #include "math/linalg/conversions/covariance_matrix_conversions.hpp"
      11              : #include "math/linalg/errors.h"
      12              : #include "motion/generic_predict.hpp"   // IWYU pragma: keep
      13              : #include "motion/motion_model_traits.h" // IWYU pragma: keep
      14              : #include "motion/state_mem.h"
      15              : 
      16              : namespace tracking
      17              : {
      18              : namespace motion
      19              : {
      20              : 
      21              : // TODO(matthias): add interface contract
      22              : // TODO(matthias): add doxygen
      23              : 
      24              : /// \brief Abstract Motion Model interface
      25              : /// \tparam CovarianceMatrixPolicy_  Policy type that defines the covariance matrix implementation
      26              : template <typename CovarianceMatrixPolicy_>
      27              : class IMotionModel
      28              :     : public math::contract::CovarianceMatrixPolicyIntf<CovarianceMatrixPolicy_>
      29              :     , public base::contract::RequireAbstractIntf<IMotionModel<CovarianceMatrixPolicy_>>
      30              : {
      31              : public:
      32              :   using value_type            = typename CovarianceMatrixPolicy_::value_type;
      33              :   using EgoMotionType         = env::EgoMotion<CovarianceMatrixPolicy_>;
      34              :   using KalmanFilterType      = filter::KalmanFilter<CovarianceMatrixPolicy_>;
      35              :   using InformationFilterType = filter::InformationFilter<CovarianceMatrixPolicy_>;
      36              : 
      37              :   // rule of 5 declarations
      38           24 :   IMotionModel()          = default;
      39           12 :   virtual ~IMotionModel() = default;
      40              : 
      41              :   virtual auto getX() const -> value_type  = 0;
      42              :   virtual auto getVx() const -> value_type = 0;
      43              :   virtual auto getAx() const -> value_type = 0;
      44              :   virtual auto getY() const -> value_type  = 0;
      45              :   virtual auto getVy() const -> value_type = 0;
      46              :   virtual auto getAy() const -> value_type = 0;
      47              : 
      48              :   /// \brief Predicts the underlying MotionModel with the given filter (includes ego motion compensation)
      49              :   /// \param[in] dt         The delta time from last state to predicted state
      50              :   /// \param[in] filter     The filter instance
      51              :   /// \param[in] egoMotion  The known egoMotion from last state to predicted state
      52              :   virtual void predict(const value_type dt, const KalmanFilterType& filter, const EgoMotionType& egoMotion) = 0;
      53              : 
      54              :   /// \brief Predicts the underlying MotionModel with the given filter (includes ego motion compensation)
      55              :   /// \param[in] dt         The delta time from last state to predicted state
      56              :   /// \param[in] filter     The filter instance
      57              :   /// \param[in] egoMotion  The known egoMotion from last state to predicted state
      58              :   virtual void predict(const value_type dt, const InformationFilterType& filter, const EgoMotionType& egoMotion) = 0;
      59              : 
      60              :   // clang-format off
      61              : TEST_REMOVE_PROTECTED:
      62              :   ; // workaround to keep following idententation
      63              :   // clang-format on
      64              : 
      65              :   // rule of 5 declarations (remaining declarations are protected according to A12-8-6)
      66              :   IMotionModel(const IMotionModel& other)                    = default;
      67              :   IMotionModel(IMotionModel&&) noexcept                      = default;
      68              :   auto operator=(const IMotionModel& other) -> IMotionModel& = default;
      69              :   auto operator=(IMotionModel&&) noexcept -> IMotionModel&   = default;
      70              : };
      71              : 
      72              : /// \brief Abstract MotionModel with known dimension, keeping the model memory for State and StateCovariance
      73              : /// \tparam MotionModel_
      74              : /// \tparam MotionModelTrait_
      75              : template <typename MotionModel_, typename MotionModelTrait_>
      76              : class ExtendedMotionModel
      77              :     : public IMotionModel<typename MotionModelTrait_::CovarianceMatrixPolicy>
      78              :     , public generic::Predict<MotionModel_, typename MotionModelTrait_::CovarianceMatrixPolicy>
      79              :     , public StateMem<typename MotionModelTrait_::CovarianceMatrixPolicy, MotionModelTrait_::Size>
      80              :     , public base::contract::RequireAbstractIntf<ExtendedMotionModel<MotionModel_, MotionModelTrait_>>
      81              : {
      82              : public:
      83              :   using value_type             = typename MotionModelTrait_::value_type;
      84              :   using StateDef               = typename MotionModelTrait_::StateDef;
      85              :   using CovarianceMatrixPolicy = typename MotionModelTrait_::CovarianceMatrixPolicy;
      86              :   using BaseIMotionModel       = IMotionModel<CovarianceMatrixPolicy>;
      87              :   using EgoMotionType          = typename BaseIMotionModel::EgoMotionType;
      88              :   using KalmanFilterType       = typename BaseIMotionModel::KalmanFilterType;
      89              :   using InformationFilterType  = typename BaseIMotionModel::InformationFilterType;
      90              :   using BaseGenericPredict     = generic::Predict<MotionModel_, typename MotionModelTrait_::CovarianceMatrixPolicy>;
      91              :   using BaseStateMem           = StateMem<CovarianceMatrixPolicy, MotionModelTrait_::Size>;
      92              :   using typename BaseStateMem::StateCov;
      93              :   using typename BaseStateMem::StateVec;
      94              : 
      95              :   // rule of 5 declarations
      96            4 :   ExtendedMotionModel()          = default;
      97           12 :   virtual ~ExtendedMotionModel() = default;
      98              : 
      99              :   /// \brief Create state vector from initializer list
     100              :   /// \param[in] list  Initializer list with state values
     101              :   /// \return StateVec
     102           36 :   static auto StateVecFromList(const std::initializer_list<value_type>& list) -> StateVec { return StateVec::FromList(list); }
     103              : 
     104              :   /// \brief Create state covariance from initializer list
     105              :   /// \param[in] list  Nested initializer list with covariance values
     106              :   /// \return StateCov
     107           36 :   static auto StateCovFromList(const std::initializer_list<std::initializer_list<value_type>>& list) -> StateCov
     108              :   {
     109              :     if constexpr (CovarianceMatrixPolicy::is_factored)
     110              :     {
     111           18 :       return math::conversions::CovarianceMatrixFactoredFromList<value_type, MotionModelTrait_::Size>(list);
     112              :     }
     113              :     else
     114              :     {
     115           18 :       return StateCov::FromList(list);
     116              :     }
     117              :   }
     118              : 
     119              :   /// \brief Create factored state covariance from initializer list
     120              :   /// \param[in] u Nested initializer list for the upper triangular U matrix
     121              :   /// \param[in] d Flat initializer list for the diagonal D matrix
     122              :   /// \return StateCov
     123              :   template <typename T = CovarianceMatrixPolicy>
     124              :   static auto StateCovFromList(const std::initializer_list<std::initializer_list<value_type>>& u,
     125              :                                const std::initializer_list<value_type>& d) -> std::enable_if_t<T::is_factored, StateCov>
     126              :   {
     127              :     return StateCov::FromList(u, d);
     128              :   }
     129              : 
     130              :   /// \brief Create complete ExtendedMotionModel from initializer lists
     131              :   /// \param[in] vecList  Initializer list for state vector
     132              :   /// \param[in] covList  Nested initializer list for covariance matrix
     133              :   /// \return ExtendedMotionModel instance
     134              :   static auto FromLists(const std::initializer_list<value_type>&                        vecList,
     135              :                         const std::initializer_list<std::initializer_list<value_type>>& covList) -> MotionModel_
     136              :   {
     137              :     auto vec = StateVecFromList(vecList);
     138              :     auto cov = StateCovFromList(covList);
     139              :     return MotionModel_{vec, cov};
     140              :   }
     141              : 
     142              :   /// \brief Read access to x position
     143              :   /// \return value_type
     144            0 :   auto getX() const -> value_type final { return this->operator[](StateDef::X); }
     145              : 
     146              :   /// \brief Read access to y position
     147              :   /// \return value_type
     148            0 :   auto getY() const -> value_type final { return this->operator[](StateDef::Y); }
     149              : 
     150              :   /// \brief Inverts the state covariance matrix into information form and vice versa
     151              :   auto invertCov() -> tl::expected<void, math::Errors>;
     152              : 
     153              :   /// \brief Predicts the underlying MotionModel with the given filter (includes ego motion compensation)
     154              :   /// \param[in] dt         The delta time from last state to predicted state
     155              :   /// \param[in] filter     The kalman filter instance
     156              :   /// \param[in] egoMotion  The known egoMotion from last state to predicted state
     157           40 :   void predict(const value_type dt, const KalmanFilterType& filter, const EgoMotionType& egoMotion) final
     158              :   {
     159           40 :     BaseGenericPredict::run(dt, filter, egoMotion);
     160           40 :   }
     161              : 
     162              :   /// \brief Predicts the underlying MotionModel with the given filter (includes ego motion compensation)
     163              :   /// \param[in] dt         The delta time from last state to predicted state
     164              :   /// \param[in] filter     The information filter instance
     165              :   /// \param[in] egoMotion  The known egoMotion from last state to predicted state
     166           40 :   void predict(const value_type dt, const InformationFilterType& filter, const EgoMotionType& egoMotion) final
     167              :   {
     168           40 :     BaseGenericPredict::run(dt, filter, egoMotion);
     169           40 :   }
     170              : 
     171              :   /// \brief Transform information space into state space
     172           40 :   void convertStateVecIntoStateSpace()
     173              :   {
     174           40 :     const auto& y = this->getVec();
     175           40 :     const auto& Y = this->getCovForInternalUse();
     176           40 :     auto&       x = this->getVecForInternalUse();
     177              :     // precondition: y and Y must be in information space (Y = P^-1, y = Y * x)
     178              :     // operation:
     179              :     // Y * result = y
     180              :     // result = Y^-1 * y = Y^-1 * Y * x = x
     181           40 :     x = Y().qrSolve(y);
     182              :     // postcondition: x is in state space, Y is unchanged (still in information space)
     183           40 :   }
     184              : 
     185              :   /// \brief Transform state space into information space
     186           40 :   void convertStateVecIntoInformationSpace()
     187              :   {
     188           40 :     const auto& x = this->getVec();
     189           40 :     const auto& Y = this->getCovForInternalUse();
     190           40 :     auto&       y = this->getVecForInternalUse();
     191              :     // precondition: x must be in state space, Y must be in information space (Y = P^-1)
     192              :     // operation:
     193              :     // y = Y * x
     194           40 :     y = static_cast<StateVec>(Y() * x);
     195              :     // postcondition: y is in information space (y = Y * x), Y is unchanged (still in information space)
     196           40 :   }
     197              : 
     198              :   // clang-format off
     199              : TEST_REMOVE_PROTECTED:
     200              :   ; // workaround to keep following idententation
     201              :   // clang-format on
     202              : 
     203              :   // rule of 5 declarations (remaining declarations are protected according to A12-8-6)
     204              :   ExtendedMotionModel(const ExtendedMotionModel& other)                    = default;
     205              :   ExtendedMotionModel(ExtendedMotionModel&&) noexcept                      = default;
     206              :   auto operator=(const ExtendedMotionModel& other) -> ExtendedMotionModel& = default;
     207              :   auto operator=(ExtendedMotionModel&&) noexcept -> ExtendedMotionModel&   = default;
     208              : 
     209              :   /// \brief Testing: Construct a new Extended Motion Model object
     210              :   /// \param[in] vec
     211              :   /// \param[in] cov
     212           20 :   explicit ExtendedMotionModel(const StateVec& vec, const StateCov& cov)
     213              :       : BaseIMotionModel{}
     214           20 :       , BaseStateMem{vec, cov}
     215              :   {
     216           20 :     assert(cov.determinant() > 0);
     217           20 :   }
     218              : };
     219              : 
     220              : template <typename MotionModel_, typename MotionModelTrait_>
     221              : auto ExtendedMotionModel<MotionModel_, MotionModelTrait_>::invertCov() -> tl::expected<void, math::Errors>
     222              : {
     223              :   auto&& res = this->getCov().inverse();
     224              :   if (res.has_value())
     225              :   {
     226              :     this->getCovForInternalUse() = res.value();
     227              :     return {};
     228              :   }
     229              :   else
     230              :   {
     231              :     return tl::unexpected<math::Errors>{res.error()};
     232              :   }
     233              : }
     234              : 
     235              : } // namespace motion
     236              : } // namespace tracking
     237              : 
     238              : #endif // D33C0BB9_EF21_44C6_8DAD_0C38C418D824
        

Generated by: LCOV version 2.0-1