00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include "robot_localization/ukf.h"
00034 #include "robot_localization/filter_common.h"
00035
00036 #include <XmlRpcException.h>
00037
00038 #include <sstream>
00039 #include <iomanip>
00040 #include <limits>
00041
00042 #include <Eigen/Cholesky>
00043
00044 #include <iostream>
00045
00046 #include <assert.h>
00047
00048 namespace RobotLocalization
00049 {
00050 Ukf::Ukf(std::vector<double> args) :
00051 FilterBase(),
00052 uncorrected_(true)
00053 {
00054 assert(args.size() == 3);
00055
00056 double alpha = args[0];
00057 double kappa = args[1];
00058 double beta = args[2];
00059
00060 size_t sigmaCount = (STATE_SIZE << 1) + 1;
00061 sigmaPoints_.resize(sigmaCount, Eigen::VectorXd(STATE_SIZE));
00062
00063
00064 lambda_ = alpha * alpha * (STATE_SIZE + kappa) - STATE_SIZE;
00065
00066 stateWeights_.resize(sigmaCount);
00067 covarWeights_.resize(sigmaCount);
00068
00069 stateWeights_[0] = lambda_ / (STATE_SIZE + lambda_);
00070 covarWeights_[0] = stateWeights_[0] + (1 - (alpha * alpha) + beta);
00071 sigmaPoints_[0].setZero();
00072 for(size_t i = 1; i < sigmaCount; ++i)
00073 {
00074 sigmaPoints_[i].setZero();
00075 stateWeights_[i] = 1 / (2 * (STATE_SIZE + lambda_));
00076 covarWeights_[i] = stateWeights_[i];
00077 }
00078 }
00079
00080 Ukf::~Ukf()
00081 {
00082 }
00083
00084 void Ukf::correct(const Measurement &measurement)
00085 {
00086 FB_DEBUG("---------------------- Ukf::correct ----------------------\n" <<
00087 "State is:\n" << state_ <<
00088 "\nMeasurement is:\n" << measurement.measurement_ <<
00089 "\nMeasurement covariance is:\n" << measurement.covariance_ << "\n");
00090
00091
00092
00093
00094
00095 if(!uncorrected_)
00096 {
00097
00098 weightedCovarSqrt_ = ((STATE_SIZE + lambda_) * estimateErrorCovariance_).llt().matrixL();
00099
00100
00101
00102
00103 sigmaPoints_[0] = state_;
00104
00105
00106
00107 for(size_t sigmaInd = 0; sigmaInd < STATE_SIZE; ++sigmaInd)
00108 {
00109 sigmaPoints_[sigmaInd + 1] = state_ + weightedCovarSqrt_.col(sigmaInd);
00110 sigmaPoints_[sigmaInd + 1 + STATE_SIZE] = state_ - weightedCovarSqrt_.col(sigmaInd);
00111 }
00112 }
00113
00114
00115
00116
00117
00118 std::vector<size_t> updateIndices;
00119 for (size_t i = 0; i < measurement.updateVector_.size(); ++i)
00120 {
00121 if (measurement.updateVector_[i])
00122 {
00123
00124 if (std::isnan(measurement.measurement_(i)))
00125 {
00126 FB_DEBUG("Value at index " << i << " was nan. Excluding from update.\n");
00127 }
00128 else if (std::isinf(measurement.measurement_(i)))
00129 {
00130 FB_DEBUG("Value at index " << i << " was inf. Excluding from update.\n");
00131 }
00132 else
00133 {
00134 updateIndices.push_back(i);
00135 }
00136 }
00137 }
00138
00139 FB_DEBUG("Update indices are:\n" << updateIndices << "\n");
00140
00141 size_t updateSize = updateIndices.size();
00142
00143
00144 Eigen::VectorXd stateSubset(updateSize);
00145 Eigen::VectorXd measurementSubset(updateSize);
00146 Eigen::MatrixXd measurementCovarianceSubset(updateSize, updateSize);
00147 Eigen::MatrixXd stateToMeasurementSubset(updateSize, STATE_SIZE);
00148 Eigen::MatrixXd kalmanGainSubset(STATE_SIZE, updateSize);
00149 Eigen::VectorXd innovationSubset(updateSize);
00150 Eigen::VectorXd predictedMeasurement(updateSize);
00151 Eigen::VectorXd sigmaDiff(updateSize);
00152 Eigen::MatrixXd predictedMeasCovar(updateSize, updateSize);
00153 Eigen::MatrixXd crossCovar(STATE_SIZE, updateSize);
00154
00155 std::vector<Eigen::VectorXd> sigmaPointMeasurements(sigmaPoints_.size(), Eigen::VectorXd(updateSize));
00156
00157 stateSubset.setZero();
00158 measurementSubset.setZero();
00159 measurementCovarianceSubset.setZero();
00160 stateToMeasurementSubset.setZero();
00161 kalmanGainSubset.setZero();
00162 innovationSubset.setZero();
00163 predictedMeasurement.setZero();
00164 predictedMeasCovar.setZero();
00165 crossCovar.setZero();
00166
00167
00168 for (size_t i = 0; i < updateSize; ++i)
00169 {
00170 measurementSubset(i) = measurement.measurement_(updateIndices[i]);
00171 stateSubset(i) = state_(updateIndices[i]);
00172
00173 for (size_t j = 0; j < updateSize; ++j)
00174 {
00175 measurementCovarianceSubset(i, j) = measurement.covariance_(updateIndices[i], updateIndices[j]);
00176 }
00177
00178
00179
00180
00181 if (measurementCovarianceSubset(i, i) < 0)
00182 {
00183 FB_DEBUG("WARNING: Negative covariance for index " << i <<
00184 " of measurement (value is" << measurementCovarianceSubset(i, i) <<
00185 "). Using absolute value...\n");
00186
00187 measurementCovarianceSubset(i, i) = ::fabs(measurementCovarianceSubset(i, i));
00188 }
00189
00190
00191
00192
00193
00194
00195
00196 if (measurementCovarianceSubset(i, i) < 1e-9)
00197 {
00198 measurementCovarianceSubset(i, i) = 1e-9;
00199
00200 FB_DEBUG("WARNING: measurement had very small error covariance for index " <<
00201 updateIndices[i] <<
00202 ". Adding some noise to maintain filter stability.\n");
00203 }
00204 }
00205
00206
00207
00208 for (size_t i = 0; i < updateSize; ++i)
00209 {
00210 stateToMeasurementSubset(i, updateIndices[i]) = 1;
00211 }
00212
00213 FB_DEBUG("Current state subset is:\n" << stateSubset <<
00214 "\nMeasurement subset is:\n" << measurementSubset <<
00215 "\nMeasurement covariance subset is:\n" << measurementCovarianceSubset <<
00216 "\nState-to-measurement subset is:\n" << stateToMeasurementSubset << "\n");
00217
00218
00219 for(size_t sigmaInd = 0; sigmaInd < sigmaPoints_.size(); ++sigmaInd)
00220 {
00221 sigmaPointMeasurements[sigmaInd] = stateToMeasurementSubset * sigmaPoints_[sigmaInd];
00222 predictedMeasurement.noalias() += stateWeights_[sigmaInd] * sigmaPointMeasurements[sigmaInd];
00223 }
00224
00225
00226
00227 for(size_t sigmaInd = 0; sigmaInd < sigmaPoints_.size(); ++sigmaInd)
00228 {
00229 sigmaDiff = sigmaPointMeasurements[sigmaInd] - predictedMeasurement;
00230 predictedMeasCovar.noalias() += covarWeights_[sigmaInd] * (sigmaDiff * sigmaDiff.transpose());
00231 crossCovar.noalias() += covarWeights_[sigmaInd] * ((sigmaPoints_[sigmaInd] - state_) * sigmaDiff.transpose());
00232 }
00233
00234
00235 Eigen::MatrixXd invInnovCov = (predictedMeasCovar + measurementCovarianceSubset).inverse();
00236 kalmanGainSubset = crossCovar * invInnovCov;
00237
00238
00239 innovationSubset = (measurementSubset - predictedMeasurement);
00240
00241
00242 if (checkMahalanobisThreshold(innovationSubset, invInnovCov, measurement.mahalanobisThresh_))
00243 {
00244
00245 for (size_t i = 0; i < updateSize; ++i)
00246 {
00247 if (updateIndices[i] == StateMemberRoll || updateIndices[i] == StateMemberPitch || updateIndices[i] == StateMemberYaw)
00248 {
00249 while (innovationSubset(i) < -PI)
00250 {
00251 innovationSubset(i) += TAU;
00252 }
00253
00254 while (innovationSubset(i) > PI)
00255 {
00256 innovationSubset(i) -= TAU;
00257 }
00258 }
00259 }
00260
00261 state_.noalias() += kalmanGainSubset * innovationSubset;
00262
00263
00264 estimateErrorCovariance_.noalias() -= (kalmanGainSubset * predictedMeasCovar * kalmanGainSubset.transpose());
00265
00266 wrapStateAngles();
00267
00268
00269 uncorrected_ = false;
00270
00271 FB_DEBUG("Predicated measurement covariance is:\n" << predictedMeasCovar <<
00272 "\nCross covariance is:\n" << crossCovar <<
00273 "\nKalman gain subset is:\n" << kalmanGainSubset <<
00274 "\nInnovation:\n" << innovationSubset <<
00275 "\nCorrected full state is:\n" << state_ <<
00276 "\nCorrected full estimate error covariance is:\n" << estimateErrorCovariance_ <<
00277 "\n\n---------------------- /Ukf::correct ----------------------\n");
00278 }
00279 }
00280
00281 void Ukf::predict(const double delta)
00282 {
00283 FB_DEBUG("---------------------- Ukf::predict ----------------------\n" <<
00284 "delta is " << delta <<
00285 "\nstate is " << state_ << "\n");
00286
00287 double roll = state_(StateMemberRoll);
00288 double pitch = state_(StateMemberPitch);
00289 double yaw = state_(StateMemberYaw);
00290
00291
00292 double cr = cos(roll);
00293 double cp = cos(pitch);
00294 double cy = cos(yaw);
00295 double sr = sin(roll);
00296 double sp = sin(pitch);
00297 double sy = sin(yaw);
00298
00299
00300 transferFunction_(StateMemberX, StateMemberVx) = cy * cp * delta;
00301 transferFunction_(StateMemberX, StateMemberVy) = (cy * sp * sr - sy * cr) * delta;
00302 transferFunction_(StateMemberX, StateMemberVz) = (cy * sp * cr + sy * sr) * delta;
00303 transferFunction_(StateMemberX, StateMemberAx) = 0.5 * transferFunction_(StateMemberX, StateMemberVx) * delta;
00304 transferFunction_(StateMemberX, StateMemberAy) = 0.5 * transferFunction_(StateMemberX, StateMemberVy) * delta;
00305 transferFunction_(StateMemberX, StateMemberAz) = 0.5 * transferFunction_(StateMemberX, StateMemberVz) * delta;
00306 transferFunction_(StateMemberY, StateMemberVx) = sy * cp * delta;
00307 transferFunction_(StateMemberY, StateMemberVy) = (sy * sp * sr + cy * cr) * delta;
00308 transferFunction_(StateMemberY, StateMemberVz) = (sy * sp * cr - cy * sr) * delta;
00309 transferFunction_(StateMemberY, StateMemberAx) = 0.5 * transferFunction_(StateMemberY, StateMemberVx) * delta;
00310 transferFunction_(StateMemberY, StateMemberAy) = 0.5 * transferFunction_(StateMemberY, StateMemberVy) * delta;
00311 transferFunction_(StateMemberY, StateMemberAz) = 0.5 * transferFunction_(StateMemberY, StateMemberVz) * delta;
00312 transferFunction_(StateMemberZ, StateMemberVx) = -sp * delta;
00313 transferFunction_(StateMemberZ, StateMemberVy) = cp * sr * delta;
00314 transferFunction_(StateMemberZ, StateMemberVz) = cp * cr * delta;
00315 transferFunction_(StateMemberZ, StateMemberAx) = 0.5 * transferFunction_(StateMemberZ, StateMemberVx) * delta;
00316 transferFunction_(StateMemberZ, StateMemberAy) = 0.5 * transferFunction_(StateMemberZ, StateMemberVy) * delta;
00317 transferFunction_(StateMemberZ, StateMemberAz) = 0.5 * transferFunction_(StateMemberZ, StateMemberVz) * delta;
00318 transferFunction_(StateMemberRoll, StateMemberVroll) = transferFunction_(StateMemberX, StateMemberVx);
00319 transferFunction_(StateMemberRoll, StateMemberVpitch) = transferFunction_(StateMemberX, StateMemberVy);
00320 transferFunction_(StateMemberRoll, StateMemberVyaw) = transferFunction_(StateMemberX, StateMemberVz);
00321 transferFunction_(StateMemberPitch, StateMemberVroll) = transferFunction_(StateMemberY, StateMemberVx);
00322 transferFunction_(StateMemberPitch, StateMemberVpitch) = transferFunction_(StateMemberY, StateMemberVy);
00323 transferFunction_(StateMemberPitch, StateMemberVyaw) = transferFunction_(StateMemberY, StateMemberVz);
00324 transferFunction_(StateMemberYaw, StateMemberVroll) = transferFunction_(StateMemberZ, StateMemberVx);
00325 transferFunction_(StateMemberYaw, StateMemberVpitch) = transferFunction_(StateMemberZ, StateMemberVy);
00326 transferFunction_(StateMemberYaw, StateMemberVyaw) = transferFunction_(StateMemberZ, StateMemberVz);
00327 transferFunction_(StateMemberVx, StateMemberAx) = delta;
00328 transferFunction_(StateMemberVy, StateMemberAy) = delta;
00329 transferFunction_(StateMemberVz, StateMemberAz) = delta;
00330
00331
00332 weightedCovarSqrt_ = ((STATE_SIZE + lambda_) * estimateErrorCovariance_).llt().matrixL();
00333
00334
00335
00336
00337
00338 sigmaPoints_[0] = transferFunction_ * state_;
00339
00340
00341
00342 for(size_t sigmaInd = 0; sigmaInd < STATE_SIZE; ++sigmaInd)
00343 {
00344 sigmaPoints_[sigmaInd + 1] = transferFunction_ * (state_ + weightedCovarSqrt_.col(sigmaInd));
00345 sigmaPoints_[sigmaInd + 1 + STATE_SIZE] = transferFunction_ * (state_ - weightedCovarSqrt_.col(sigmaInd));
00346 }
00347
00348
00349 state_.setZero();
00350 for(size_t sigmaInd = 0; sigmaInd < sigmaPoints_.size(); ++sigmaInd)
00351 {
00352 state_.noalias() += stateWeights_[sigmaInd] * sigmaPoints_[sigmaInd];
00353 }
00354
00355
00356 estimateErrorCovariance_.setZero();
00357 Eigen::VectorXd sigmaDiff(STATE_SIZE);
00358 for(size_t sigmaInd = 0; sigmaInd < sigmaPoints_.size(); ++sigmaInd)
00359 {
00360 sigmaDiff = (sigmaPoints_[sigmaInd] - state_);
00361 estimateErrorCovariance_.noalias() += covarWeights_[sigmaInd] * (sigmaDiff * sigmaDiff.transpose());
00362 }
00363
00364
00365
00366 estimateErrorCovariance_.noalias() += delta * processNoiseCovariance_;
00367
00368
00369 wrapStateAngles();
00370
00371
00372 uncorrected_ = true;
00373
00374 FB_DEBUG("Predicted state is:\n" << state_ <<
00375 "\nPredicted estimate error covariance is:\n" << estimateErrorCovariance_ <<
00376 "\n\n--------------------- /Ukf::predict ----------------------\n");
00377 }
00378
00379 }