/*========================================================================= * * Copyright NumFOCUS * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *=========================================================================*/ #ifndef itkKalmanLinearEstimator_h #define itkKalmanLinearEstimator_h #include "itkMacro.h" #include "vnl/vnl_vector_fixed.h" #include "vnl/vnl_matrix_fixed.h" namespace itk { /** * \class KalmanLinearEstimator * \brief Implement a linear recursive estimator. * * KalmanLinearEstimator class implements a linear recursive estimator. The * class is templated over the type of the parameters to be estimated and * over the number of parameters. Recursive estimation is a fast mechanism * for getting information about a system for which we only have access to * measures that are linearly related with the parameters we want to * estimate. * * \ingroup Numerics * \ingroup ITKStatistics */ template class KalmanLinearEstimator { public: /** Dimension of the vector of parameters to be estimated. * It is equivalent to the number of parameters to estimate. */ static constexpr unsigned int Dimension = VEstimatorDimension; /** Vector type defines a generic vector type that is used * for the matricial operations performed during estimation. */ using VectorType = vnl_vector_fixed; /** Matrix type defines a generic matrix type that is used * for the matricial operations performed during estimation. */ using MatrixType = vnl_matrix_fixed; /** Type is the type associated with the parameters to be estimated. * All the parameters are of the same type. Natural choices could be * floats and doubles, because Type also is used for all the internal * computations. */ using ValueType = T; /** Update the estimation using the information provided by a new measure * along with a new line of the linear predictor. This method is the one * that should be called iteratively in order to estimate the parameter's * vector. It internally updates the covariance matrix. */ void UpdateWithNewMeasure(const ValueType & newMeasure, const VectorType & newPredictor); /** This method resets the estimator. It set all the parameters to null. * The covariance matrix is not changed. * \sa Estimator \sa Variance \sa ClearVariance */ void ClearEstimation() { m_Estimator = VectorType(T(0)); } /** This method resets the covariance matrix. It is set to an identity matrix * \sa Estimator \sa Variance \sa ClearEstimation */ void ClearVariance() { m_Variance.set_identity(); } /** This method sets the covariance matrix to a diagonal matrix with * equal values. It is useful when the variance of all the parameters * be estimated are the same and the parameters are considered independents. * \sa Estimator * \sa Variance * \sa ClearEstimation */ void SetVariance(const ValueType & var = 1.0) { m_Variance.set_identity(); m_Variance *= var; } /** This method sets the covariance matrix to known matrix. It is intended to * initialize the estimator with a priori information about the statistical * distribution of the parameters. It can also be used to resume the * operation of a previously used estimator using it last known state. * \sa Estimator \sa Variance \sa ClearEstimation */ void SetVariance(const MatrixType & m) { m_Variance = m; } /** This method returns the vector of estimated parameters * \sa Estimator */ const VectorType & GetEstimator() const { return m_Estimator; } /** This method returns the covariance matrix of the estimated parameters * \sa Variance */ const MatrixType & GetVariance() const { return m_Variance; } private: /** This methods performs the update of the parameter's covariance matrix. * It is called by updateWithNewMeasure() method. Users are not expected to * call this method directly. * \sa updateWithNewMeasure */ void UpdateVariance(const VectorType &); /** Vector of parameters to estimate. * \sa GetEstimator */ VectorType m_Estimator; /** Estimation of the parameter's covariance matrix. This matrix contains * the information about the state of the estimator. It holds all the * information obtained from previous measures provided to the * estimator. The initialization of this matrix is critical to the behavior * of the estimator, at least to ensure a short transient period for * stabilizing the estimation. \sa SetVariance \sa GetVariance */ MatrixType m_Variance; }; template void KalmanLinearEstimator::UpdateWithNewMeasure(const ValueType & newMeasure, const VectorType & newPredictor) { ValueType measurePrediction = dot_product(newPredictor, m_Estimator); ValueType errorMeasurePrediction = newMeasure - measurePrediction; VectorType Corrector = m_Variance * newPredictor; for (unsigned int j = 0; j < VEstimatorDimension; ++j) { m_Estimator(j) += Corrector(j) * errorMeasurePrediction; } UpdateVariance(newPredictor); } template void KalmanLinearEstimator::UpdateVariance(const VectorType & newPredictor) { VectorType aux = m_Variance * newPredictor; ValueType denominator = 1.0 / (1.0 + dot_product(aux, newPredictor)); for (unsigned int col = 0; col < VEstimatorDimension; ++col) { for (unsigned int row = 0; row < VEstimatorDimension; ++row) { m_Variance(col, row) -= aux(col) * aux(row) * denominator; } } } } // end namespace itk #endif