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
00034
00035
00036 #ifndef UKF_C_DEFINED
00037 #define UKF_C_DEFINED
00038
00039 #include "BayesFilters/UKF.H"
00040 #include "Util/MathFunctions.H"
00041
00042
00043
00044 UKF::UKF(int numStates, int numObservations,
00045 double k, double alpha, double beta) :
00046 itsNumStates(numStates),
00047 itsNumObservations(numObservations),
00048 itsAlpha(alpha),
00049 itsK(k),
00050 itsBeta(beta),
00051 itsUnstable(false)
00052 {
00053 itsR=Image<double>(itsNumStates,itsNumStates,ZEROS);
00054 itsQ=Image<double>(itsNumObservations,itsNumObservations,ZEROS);
00055
00056
00057 itsLambda = itsAlpha*itsAlpha*(itsNumStates+itsK)-itsNumStates;
00058 itsGamma = sqrt(itsNumStates + itsLambda);
00059
00060
00061 itsMuWeight = Image<double>(1+2*itsNumStates,1,ZEROS);
00062 itsSigmaWeight = Image<double>(1+2*itsNumStates,1,ZEROS);
00063
00064
00065 itsMuWeight[0] = itsLambda/(itsNumStates + itsLambda);
00066 itsSigmaWeight[0] = (itsLambda/(itsNumStates + itsLambda)) +
00067 (1-(itsAlpha*itsAlpha)+itsBeta);
00068
00069 double weight = 1/(2*(itsNumStates+itsLambda));
00070 for(int i=1; i<1+itsNumStates*2; i++)
00071 {
00072 itsMuWeight[i] = weight;
00073 itsSigmaWeight[i] = weight;
00074 }
00075
00076
00077 itsState = Image<double>(1,itsNumStates,ZEROS);
00078 itsSigma = Image<double>(itsNumStates,itsNumStates,ZEROS);
00079
00080 itsGaussNormalizer = 1.0/sqrt(pow(2.0*M_PI,itsNumStates));
00081 }
00082
00083 void UKF::predictState(const Image<double>& noise)
00084 {
00085 if (itsUnstable) return;
00086
00087 itsSigmaLocations = getSigmaLocations(itsState, itsSigma, itsGamma);
00088
00089
00090
00091 itsNewStates = Image<double>(itsSigmaLocations.getDims(),ZEROS);
00092 Image<double> predictedState(1,itsNumStates,ZEROS);
00093 for(int k=0; k<itsSigmaLocations.getWidth(); k++)
00094 {
00095 Image<double> state = getNextState(itsSigmaLocations,k);
00096 ASSERT(state.size() == (uint)itsNumStates);
00097 predictedState += state*itsMuWeight[k];
00098
00099 for(uint i=0; i<state.size(); i++)
00100 itsNewStates.setVal(k, i, state[i]);
00101 }
00102
00103
00104 Image<double> predictedSigma(itsSigma.getDims(),ZEROS);
00105 for(int k=0; k<itsNewStates.getWidth(); k++)
00106 {
00107
00108
00109
00110 Image<double> diff(1,predictedState.size(), ZEROS);
00111 for(uint i=0; i<diff.size(); i++)
00112 diff[i] = itsNewStates.getVal(k,i)-predictedState[i];
00113
00114 Image<double> variance = matrixMult(diff, transpose(diff));
00115
00116 predictedSigma += variance*itsSigmaWeight[k];
00117 }
00118
00119 if (noise.initialized())
00120 predictedSigma += noise;
00121 else
00122 predictedSigma += itsR;
00123
00124 itsState = predictedState;
00125 itsSigma = predictedSigma;
00126 }
00127
00128 void UKF::predictObservation(const Image<double>& noise)
00129 {
00130 if (itsUnstable) return;
00131
00132
00133
00134 itsNewZ = Image<double>(itsNewStates.getWidth(),
00135 itsNumObservations, ZEROS);
00136 Image<double> predictedZ(1,itsNumObservations, ZEROS);
00137
00138
00139 for(int k=0; k<itsNewStates.getWidth(); k++)
00140 {
00141 Image<double> observation = getObservation(itsNewStates, k);
00142 ASSERT(observation.size() == (uint)itsNumObservations);
00143 predictedZ += observation*itsMuWeight[k];
00144 for(uint i=0; i<observation.size(); i++)
00145 itsNewZ.setVal(k, i, observation[i]);
00146 }
00147
00148
00149
00150 Image<double> predictedZSigma(itsNumObservations, itsNumObservations,ZEROS);
00151 for(int k=0; k<itsNewStates.getWidth(); k++)
00152 {
00153
00154 Image<double> diff(1,predictedZ.size(), ZEROS);
00155 for(uint i=0; i<diff.size(); i++)
00156 diff[i] = itsNewZ.getVal(k,i)-predictedZ[i];
00157 Image<double> variance = matrixMult(diff, transpose(diff));
00158 predictedZSigma += variance*itsSigmaWeight[k];
00159 }
00160
00161 if (noise.initialized())
00162 predictedZSigma += noise;
00163 else
00164 predictedZSigma += itsQ;
00165
00166 itsPredictedZ = predictedZ;
00167 itsPredictedZSigma = predictedZSigma;
00168 }
00169
00170 double UKF::getLikelihood(const Image<double>& z, const Image<double>& observationNoise)
00171 {
00172 if (itsUnstable) return 0;
00173
00174 if (!itsPredictedZSigma.initialized())
00175 return 0;
00176
00177
00178
00179 Image<double> sigma = itsPredictedZSigma;
00180 if (observationNoise.initialized())
00181 sigma += observationNoise;
00182
00183
00184
00185 double normalizer = itsGaussNormalizer* (1/sqrt(lapack::det(&sigma)));
00186
00187
00188 Image<double> innov = z - itsPredictedZ;
00189
00190 try
00191 {
00192 Image<double> probMat = matrixMult(transpose(innov), matrixMult(matrixInv(sigma), innov));
00193 return normalizer*exp(-0.5*probMat.getVal(0,0));
00194 } catch (...)
00195 {
00196 itsUnstable = true;
00197 }
00198
00199 return 0;
00200
00201 }
00202
00203
00204 void UKF::update(const Image<double>& z, const Image<double>& noise)
00205 {
00206 if (itsUnstable) return;
00207
00208 Image<double> Pxy(itsNumObservations, itsNumStates, ZEROS);
00209 for(int k=0; k<itsNewStates.getWidth(); k++)
00210 {
00211
00212 Image<double> stateDiff(1,itsNumStates,NO_INIT);
00213 for(uint i=0; i<stateDiff.size(); i++)
00214 stateDiff[i] = itsNewStates.getVal(k,i) - itsState[i];
00215
00216 Image<double> zDiff(1,itsNumObservations,NO_INIT);
00217 for(uint i=0; i<zDiff.size(); i++)
00218 zDiff[i] = itsNewZ.getVal(k,i) - itsPredictedZ[i];
00219
00220 Image<double> variance = matrixMult(stateDiff, transpose(zDiff));
00221 Pxy += variance*itsSigmaWeight[k];
00222 }
00223
00224 try
00225 {
00226 Image<double> sigma = itsPredictedZSigma;
00227
00228
00229
00230
00231 Image<double> K = matrixMult(Pxy, matrixInv(sigma));
00232
00233
00234 Image<double> innov = z - itsPredictedZ;
00235
00236
00237 itsState += matrixMult(K,innov);
00238 itsSigma -= matrixMult(K,transpose(Pxy));
00239 } catch (...)
00240 {
00241 itsUnstable = true;
00242 }
00243
00244
00245 }
00246
00247
00248 Image<double> UKF::getSigmaLocations(const Image<double>& state,
00249 const Image<double>& sigma, double gamma)
00250 {
00251
00252
00253
00254 Image<double> A = sigma;
00255
00256
00257 Image<double> SChol = lapack::dpotrf(&A);
00258
00259 for(int j=0; j<SChol.getHeight(); j++)
00260 for(int i=0; i<j; i++)
00261 SChol.setVal(i,j,0);
00262
00263 A=transpose(SChol)*gamma;
00264
00265 Image<double> X(state.size()*2 + 1, state.size(),ZEROS);
00266
00267 for(int j=0; j<X.getHeight(); j++)
00268 X.setVal(0,j,state[j]);
00269
00270 for(int i=0; i<A.getWidth(); i++)
00271 for(int j=0; j<A.getHeight(); j++)
00272 X.setVal(1+i,j,state[j]+A.getVal(i,j));
00273
00274 for(int i=0; i<A.getWidth(); i++)
00275 for(int j=0; j<A.getHeight(); j++)
00276 X.setVal(1+state.size()+i,j,state[j]-A.getVal(i,j));
00277
00278 return X;
00279 }
00280
00281
00282
00283
00284
00285
00286
00287 #endif