KFCore.hpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2010, LABUST, UNIZG-FER
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/or other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of the LABUST nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
00033  *********************************************************************/
00034 #ifndef KFCORE_HPP_
00035 #define KFCORE_HPP_
00036 #include <labust/navigation/KFBase.hpp>
00037 
00038 #include <vector>
00039 #include <cassert>
00040 
00042 #include <iostream>
00043 #include <ros/ros.h>
00044 
00045 namespace labust
00046 {
00047         namespace navigation
00048         {
00053                 template <class Model>
00054                 class KFCore : public KFBase< Model >
00055                 {
00056                         typedef KFBase< Model > Base;
00057                 public:
00061                         KFCore(){};
00062 
00068                         void predict(typename Base::inputref u = typename Model::input_type())
00069                         {
00070                                 assert((this->Ts) && "KFCore: Sampling time set to zero." );
00075                                 this->step(u);
00080                                 this->P = this->A*this->P*this->A.transpose() +
00081                                                 //this can be optimized for constant noise models
00082                                                 this->W*this->Q*this->W.transpose();
00083                         }
00091                         typename Base::vectorref correct(typename Base::outputref y_meas)
00092                         {
00093                                 //ros::Time start(ros::Time::now());
00099                                 typename Base::matrix PH = this->P*this->H.transpose();
00100                                 this->innovationCov = this->H*PH;
00101                                 typename Base::matrix VR = this->V*this->R;
00102                                 //This can be optimized for constant R, V combinations
00103                                 this->innovationCov += VR*this->V.transpose();
00104                                 //this->K = PH*this->innovationCov.inverse();
00105                                 //TODO Add option to select solvers based on size for larger matrices this should be faster
00106                                 this->K = PH*this->innovationCov.ldlt().solve(
00107                                                                 Base::matrix::Identity(this->innovationCov.rows(),
00108                                                                                                 this->innovationCov.cols()));
00109                                 /*
00110                                  * Correct the state estimate
00111                                  *
00112                                  * x(k) = x_(k) + K(k)*(measurement - y(k));
00113                                  */
00114                                 typename Base::output_type y;
00115                                 this->estimate_y(y);
00116                                 this->innovation = y_meas - y;
00117                                 this->x += this->K*this->innovation;
00122                                 typename Base::matrix IKH = Base::matrix::Identity(this->P.rows(), this->P.cols());
00123                                 IKH -= this->K*this->H;
00124                                 this->P = IKH*this->P;
00125 
00126                                 //ros::Time end(ros::Time::now());
00127 
00128                                 //ROS_INFO("KF: Total elapsed time: %f", (start-end).toSec());
00129 
00130                                 return this->xk_1 = this->x;
00131                         }
00132 
00140                         template <class NewMeasVector>
00141                         typename Base::vectorref correct(
00142                                         typename Base::outputref measurements,
00143                                         NewMeasVector& newMeas,
00144                                         bool reject_outliers = true)
00145                         {
00146                                 //Check invariant.
00147                                 assert(measurements.size() == Model::stateNum &&
00148                                                 newMeas.size() == Model::stateNum);
00149 
00150                                 std::vector<size_t> arrived;
00151                                 std::vector<typename Model::numericprecission> dataVec;
00152 
00153                                 for (size_t i=0; i<newMeas.size(); ++i)
00154                                 {
00155                                         //Outlier rejection
00156                                         if (newMeas(i) && reject_outliers)
00157                                         {
00158                                                 double dist=fabs(this->x(i) - measurements(i));
00159                                                 newMeas(i) = (dist <= sqrt(this->P(i,i)) + sqrt(this->R0(i,i)));
00160 
00162                                                 if (!newMeas(i))
00163                                                 {
00164                                                         std::cerr<<"Outlier rejected: x(i)="<<this->x(i);
00165                                                         std::cerr<<", m(i)="<<measurements(i);
00166                                                         std::cerr<<", r(i)="<<sqrt(this->P(i,i)) + sqrt(this->R0(i,i));
00167                                                 }
00168                                         }
00169 
00170                                         if (newMeas(i))
00171                                         {
00172                                                 arrived.push_back(i);
00173                                                 dataVec.push_back(measurements(i));
00174                                                 newMeas(i) = 0;
00175                                         }
00176                                 }
00177 
00178                                 typename Base::output_type y_meas(arrived.size());
00179                                 this->H = Model::matrix::Zero(arrived.size(),Model::stateNum);
00180                                 this->V = Model::matrix::Zero(arrived.size(),Model::stateNum);
00181 
00182                                 for (size_t i=0; i<arrived.size();++i)
00183                                 {
00184                                         y_meas(i) = dataVec[i];
00185                                         this->H.row(i) = this->H0.row(arrived[i]);
00186                                         this->V.row(i) = this->V0.row(arrived[i]);
00187                                 }
00188 
00189                                 return this->correct(y_meas);
00190                         }
00191                 };
00192         };
00193 }
00194 /* KFCORE_HPP_ */
00195 #endif


labust_navigation
Author(s): Gyula Nagy
autogenerated on Fri Aug 28 2015 11:23:33