filter_base.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2015, Charles River Analytics, Inc.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * 1. Redistributions of source code must retain the above copyright
00010  * notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above
00012  * copyright notice, this list of conditions and the following
00013  * disclaimer in the documentation and/or other materials provided
00014  * with the distribution.
00015  * 3. Neither the name of the copyright holder nor the names of its
00016  * contributors may be used to endorse or promote products derived
00017  * from this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00020  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00021  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00022  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00023  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00024  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00025  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00026  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00027  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00028  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00029  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00030  * POSSIBILITY OF SUCH DAMAGE.
00031  */
00032 
00033 #include "robot_localization/filter_base.h"
00034 #include "robot_localization/filter_common.h"
00035 
00036 #include <sstream>
00037 #include <iomanip>
00038 #include <limits>
00039 #include <iostream>
00040 
00041 namespace RobotLocalization
00042 {
00043   FilterBase::FilterBase() :
00044     state_(STATE_SIZE),
00045     predictedState_(STATE_SIZE),
00046     transferFunction_(STATE_SIZE, STATE_SIZE),
00047     transferFunctionJacobian_(STATE_SIZE, STATE_SIZE),
00048     estimateErrorCovariance_(STATE_SIZE, STATE_SIZE),
00049     covarianceEpsilon_(STATE_SIZE, STATE_SIZE),
00050     processNoiseCovariance_(STATE_SIZE, STATE_SIZE),
00051     identity_(STATE_SIZE, STATE_SIZE),
00052     debug_(false),
00053     debugStream_(NULL)
00054   {
00055     initialized_ = false;
00056 
00057     // Clear the state and predicted state
00058     state_.setZero();
00059     predictedState_.setZero();
00060 
00061     // Prepare the invariant parts of the transfer
00062     // function
00063     transferFunction_.setIdentity();
00064 
00065     // Clear the Jacobian
00066     transferFunctionJacobian_.setZero();
00067 
00068     // Set the estimate error covariance. We want our measurements
00069     // to be accepted rapidly when the filter starts, so we should
00070     // initialize the state's covariance with large values.
00071     estimateErrorCovariance_.setIdentity();
00072     estimateErrorCovariance_ *= 1e-9;
00073 
00074     // We need the identity for the update equations
00075     identity_.setIdentity();
00076 
00077     // Set the epsilon matrix to be a matrix with small values on the diagonal
00078     // It is used to maintain the positive-definite property of the covariance
00079     covarianceEpsilon_.setIdentity();
00080     covarianceEpsilon_ *= 0.001;
00081 
00082     // Assume 30Hz from sensor data (configurable)
00083     sensorTimeout_ = 0.033333333;
00084 
00085     // Initialize our last update and measurement times
00086     lastUpdateTime_ = 0;
00087     lastMeasurementTime_ = 0;
00088 
00089     // These can be overridden via the launch parameters,
00090     // but we need default values.
00091     processNoiseCovariance_.setZero();
00092     processNoiseCovariance_(StateMemberX, StateMemberX) = 0.05;
00093     processNoiseCovariance_(StateMemberY, StateMemberY) = 0.05;
00094     processNoiseCovariance_(StateMemberZ, StateMemberZ) = 0.06;
00095     processNoiseCovariance_(StateMemberRoll, StateMemberRoll) = 0.03;
00096     processNoiseCovariance_(StateMemberPitch, StateMemberPitch) = 0.03;
00097     processNoiseCovariance_(StateMemberYaw, StateMemberYaw) = 0.06;
00098     processNoiseCovariance_(StateMemberVx, StateMemberVx) = 0.025;
00099     processNoiseCovariance_(StateMemberVy, StateMemberVy) = 0.025;
00100     processNoiseCovariance_(StateMemberVz, StateMemberVz) = 0.04;
00101     processNoiseCovariance_(StateMemberVroll, StateMemberVroll) = 0.01;
00102     processNoiseCovariance_(StateMemberVpitch, StateMemberVpitch) = 0.01;
00103     processNoiseCovariance_(StateMemberVyaw, StateMemberVyaw) = 0.02;
00104     processNoiseCovariance_(StateMemberAx, StateMemberAx) = 0.01;
00105     processNoiseCovariance_(StateMemberAy, StateMemberAy) = 0.01;
00106     processNoiseCovariance_(StateMemberAz, StateMemberAz) = 0.015;
00107   }
00108 
00109   FilterBase::~FilterBase()
00110   {
00111   }
00112 
00113   bool FilterBase::getDebug()
00114   {
00115     return debug_;
00116   }
00117 
00118   const Eigen::MatrixXd& FilterBase::getEstimateErrorCovariance()
00119   {
00120     return estimateErrorCovariance_;
00121   }
00122 
00123   bool FilterBase::getInitializedStatus()
00124   {
00125     return initialized_;
00126   }
00127 
00128   double FilterBase::getLastMeasurementTime()
00129   {
00130     return lastMeasurementTime_;
00131   }
00132 
00133   double FilterBase::getLastUpdateTime()
00134   {
00135     return lastUpdateTime_;
00136   }
00137 
00138   const Eigen::VectorXd& FilterBase::getPredictedState()
00139   {
00140     return predictedState_;
00141   }
00142 
00143   const Eigen::MatrixXd& FilterBase::getProcessNoiseCovariance()
00144   {
00145     return processNoiseCovariance_;
00146   }
00147 
00148   double FilterBase::getSensorTimeout()
00149   {
00150     return sensorTimeout_;
00151   }
00152 
00153   const Eigen::VectorXd& FilterBase::getState()
00154   {
00155     return state_;
00156   }
00157 
00158   void FilterBase::processMeasurement(const Measurement &measurement)
00159   {
00160     FB_DEBUG("------ FilterBase::processMeasurement (" << measurement.topicName_ << ") ------\n");
00161 
00162     double delta = 0.0;
00163 
00164     // If we've had a previous reading, then go through the predict/update
00165     // cycle. Otherwise, set our state and covariance to whatever we get
00166     // from this measurement.
00167     if (initialized_)
00168     {
00169       // Determine how much time has passed since our last measurement
00170       delta = measurement.time_ - lastMeasurementTime_;
00171 
00172       FB_DEBUG("Filter is already initialized. Carrying out predict/correct loop...\n"
00173                "Measurement time is " << std::setprecision(20) << measurement.time_ <<
00174                ", last measurement time is " << lastMeasurementTime_ << ", delta is " << delta << "\n");
00175 
00176       // Only want to carry out a prediction if it's
00177       // forward in time. Otherwise, just correct.
00178       if (delta > 0)
00179       {
00180         validateDelta(delta);
00181 
00182         predict(delta);
00183 
00184         // Return this to the user
00185         predictedState_ = state_;
00186       }
00187 
00188       correct(measurement);
00189     }
00190     else
00191     {
00192       FB_DEBUG("First measurement. Initializing filter.\n");
00193 
00194       // Initialize the filter, but only with the values we're using
00195       size_t measurementLength = measurement.updateVector_.size();
00196       for(size_t i = 0; i < measurementLength; ++i)
00197       {
00198         state_[i] = (measurement.updateVector_[i] ? measurement.measurement_[i] : state_[i]);
00199       }
00200 
00201       // Same for covariance
00202       for(size_t i = 0; i < measurementLength; ++i)
00203       {
00204         for(size_t j = 0; j < measurementLength; ++j)
00205         {
00206           estimateErrorCovariance_(i, j) = (measurement.updateVector_[i] && measurement.updateVector_[j] ?
00207                                             measurement.covariance_(i, j) :
00208                                             estimateErrorCovariance_(i, j));
00209         }
00210       }
00211 
00212       initialized_ = true;
00213     }
00214 
00215     if(delta >= 0.0)
00216     {
00217       // Update the last measurement and update time.
00218       // The measurement time is based on the time stamp of the
00219       // measurement, whereas the update time is based on this
00220       // node's current ROS time. The update time is used to
00221       // determine if we have a sensor timeout, whereas the
00222       // measurement time is used to calculate time deltas for
00223       // prediction and correction.
00224       lastMeasurementTime_ = measurement.time_;
00225     }
00226 
00227     FB_DEBUG("------ /FilterBase::processMeasurement (" << measurement.topicName_ << ") ------\n");
00228   }
00229 
00230   void FilterBase::setDebug(const bool debug, std::ostream *outStream)
00231   {
00232     if (debug)
00233     {
00234       if (outStream != NULL)
00235       {
00236         debugStream_ = outStream;
00237         debug_ = true;
00238       }
00239       else
00240       {
00241         debug_ = false;
00242       }
00243     }
00244     else
00245     {
00246       debug_ = false;
00247     }
00248   }
00249 
00250   void FilterBase::setEstimateErrorCovariance(const Eigen::MatrixXd &estimateErrorCovariance)
00251   {
00252     estimateErrorCovariance_ = estimateErrorCovariance;
00253   }
00254 
00255   void FilterBase::setLastMeasurementTime(const double lastMeasurementTime)
00256   {
00257     lastMeasurementTime_ = lastMeasurementTime;
00258   }
00259 
00260   void FilterBase::setLastUpdateTime(const double lastUpdateTime)
00261   {
00262     lastUpdateTime_ = lastUpdateTime;
00263   }
00264 
00265   void FilterBase::setProcessNoiseCovariance(const Eigen::MatrixXd &processNoiseCovariance)
00266   {
00267     processNoiseCovariance_ = processNoiseCovariance;
00268   }
00269 
00270   void FilterBase::setSensorTimeout(const double sensorTimeout)
00271   {
00272     sensorTimeout_ = sensorTimeout;
00273   }
00274 
00275   void FilterBase::setState(const Eigen::VectorXd &state)
00276   {
00277     state_ = state;
00278   }
00279 
00280   void FilterBase::validateDelta(double &delta)
00281   {
00282     // This handles issues with ROS time when use_sim_time is on and we're playing from bags.
00283     if (delta > 100000.0)
00284     {
00285       FB_DEBUG("Delta was very large. Suspect playing from bag file. Setting to 0.01\n");
00286 
00287       delta = 0.01;
00288     }
00289   }
00290 
00291   void FilterBase::wrapStateAngles()
00292   {
00293     state_(StateMemberRoll)  = FilterUtilities::clampRotation(state_(StateMemberRoll));
00294     state_(StateMemberPitch) = FilterUtilities::clampRotation(state_(StateMemberPitch));
00295     state_(StateMemberYaw)   = FilterUtilities::clampRotation(state_(StateMemberYaw));
00296   }
00297 
00298   bool FilterBase::checkMahalanobisThreshold(const Eigen::VectorXd &innovation,
00299                                              const Eigen::MatrixXd &invCovariance,
00300                                              const double nsigmas)
00301   {
00302     double sqMahalanobis = innovation.dot(invCovariance * innovation);
00303     double threshold = nsigmas * nsigmas;
00304 
00305     if (sqMahalanobis >= threshold)
00306     {
00307       FB_DEBUG("Innovation mahalanobis distance test failed. Squared Mahalanobis is: " << sqMahalanobis << "\n" <<
00308                "Threshold is: " << threshold << "\n" <<
00309                "Innovation is: " << innovation << "\n" <<
00310                "Innovation covariance is:\n" << invCovariance << "\n");
00311 
00312       return false;
00313     }
00314 
00315     return true;
00316   }
00317 }


robot_localization
Author(s): Tom Moore
autogenerated on Fri Aug 28 2015 12:26:20