00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00024
00025 #include <qvmath/qvukf.h>
00026 QVUKF::QVUKF(const QVUKFstate &state)
00027 {
00028 currentState = state;
00029 n = state.mean.getCols();
00030
00031
00032 k = 0;
00033 alpha = 0.5;
00034 beta = 2;
00035 discrepance = 0;
00036 }
00037
00038 void QVUKF::setState(const QVUKFstate &state)
00039 {
00040 currentState = state;
00041 n = state.mean.getCols();
00042 discrepance = 0;
00043 }
00044
00045 QVMatrix QVUKF::getState() const
00046 {
00047 return currentState.mean;
00048 }
00049
00050 double QVUKF::getDiscrepance() const
00051 {
00052 return discrepance;
00053 }
00054
00055 QVMatrix QVUKF::sigmaPoints(const QVMatrix &X, const QVMatrix &P) const
00056 {
00057 double lambda = (alpha*alpha) * (n+k) - n;
00058 QVMatrix aux = P * (n + lambda);
00059
00060 QVMatrix aux2 = QVMatrix();
00061
00062
00063 CholeskyDecomposition(aux, aux2);
00064 aux2 = aux2.transpose();
00065 QVMatrix Sigma = QVMatrix(2*n + 1, n, 0.0);
00066 QVVector Xvector = QVVector(X);
00067 for(int i=0; i<2*n+1; i++)
00068 {
00069 if(i==0)
00070 Sigma.setRow(i, Xvector);
00071 if (i>0 && i<=n)
00072 Sigma.setRow(i, X + aux2.getRow(i-1));
00073 if (i>n && i<2*n+1)
00074 Sigma.setRow(i, X - aux2.getRow(i-n-1));
00075 }
00076
00077 return Sigma;
00078 }
00079
00080 void QVUKF::computeWeights()
00081 {
00082 double lambda = pow(alpha, 2)*(n+k)-n;
00083 QVMatrix Wm = QVMatrix(2*n+1, 1);
00084 QVMatrix Wc = QVMatrix(2*n+1, 1);
00085
00086 for(int i=0; i<2*n+1; i++)
00087 {
00088 if(i==0)
00089 {
00090 QVVector x = QVVector(1,lambda/(n+lambda));
00091 QVVector y = QVVector(1,(lambda/(n+lambda))+(1.0-pow(alpha,2)+beta));
00092 Wm.setRow(i, x);
00093 Wc.setRow(i, y);
00094 }
00095
00096 if (i>0)
00097 {
00098 QVVector z = QVVector(1,1.0/(2.0*(n+lambda)));
00099 Wm.setRow(i, z);
00100 Wc.setRow(i, z);
00101 }
00102 }
00103
00104 this->weights.Wm = Wm;
00105 this->weights.Wc = Wc;
00106 }
00107
00108 QVMatrix QVUKF::computeMean(const QVMatrix &M) const
00109 {
00110 QVMatrix mean = QVMatrix(1, M.getCols(), 0.0);
00111 for(int j=0; j<M.getCols(); j++)
00112 {
00113 double accum =0;
00114 for(int i=0; i<2*n+1; i++)
00115 accum += weights.Wm(i,0)*M(i,j);
00116 QVVector v = QVVector(1, (accum));
00117 mean.setCol(j, v);
00118 }
00119
00120 return mean;
00121 }
00122
00123 QVMatrix QVUKF::computeCovariance(const QVMatrix &mean, const QVMatrix &FdeSigma) const
00124 {
00125 QVMatrix covariance = QVMatrix(mean.getCols(), mean.getCols(), 0.0);
00126
00127 for(int i=0; i<2*n+1; i++)
00128 {
00129 QVMatrix accum = QVMatrix(mean.getCols(), mean.getCols(), 0.0);
00130 QVMatrix YXprima = FdeSigma.getRow(i)-mean;
00131 QVMatrix YXprimaTrans = YXprima.transpose();
00132 accum = YXprimaTrans*YXprima;
00133 accum = accum.operator*(weights.Wc(i, 0));
00134 covariance = covariance + accum;
00135 }
00136
00137 return covariance;
00138 }
00139
00140 QVMatrix QVUKF::CrossCovariance (const QVMatrix &mean, const QVMatrix &FdeSigma, const QVMatrix &zt, const QVMatrix &Zt) const
00141 {
00142
00143 QVMatrix covariance = QVMatrix(n, zt.getCols(), 0.0);
00144
00145 for(int i=0; i<2*n+1; i++)
00146 {
00147 QVMatrix accum = QVMatrix(n, zt.getRows(), 0.0);
00148 QVMatrix YXprima = FdeSigma.getRow(i) - mean;
00149 QVMatrix zZprima = Zt.getRow(i) - zt;
00150
00151 accum = YXprima.transpose()*zZprima;
00152 accum = accum.operator*(weights.Wc(i,0));
00153 covariance = covariance + accum;
00154 }
00155
00156 return covariance;
00157
00158 }
00159
00160 void QVUKF::update(const QVMatrix &obs, QVFunction<QVVector, QVVector> &g, QVFunction<QVVector, QVVector> &h, const QVMatrix &Rt, const QVMatrix &Qt)
00161 {
00162 QVMatrix SigmaPoints = sigmaPoints(currentState.mean, currentState.covariance);
00163 QVMatrix FdeSigma = QVMatrix(2*n+1, n, 0.0);
00164
00165 for (int i=0; i<2*n+1; i++)
00166 {
00167
00168 QVVector aux = SigmaPoints.getRow(i);
00169 FdeSigma.setRow(i, g.evaluate(aux));
00170 }
00171
00172 computeWeights();
00173 QVMatrix mean_t = computeMean(FdeSigma);
00174 QVMatrix covar_t = computeCovariance(mean_t, FdeSigma) + Rt;
00175 QVMatrix SigmaPoints_t = sigmaPoints(mean_t, covar_t);
00176
00177 QVMatrix Zt = QVMatrix(2*n+1, obs.getCols(), 0.0);
00178 for (int i=0; i<2*n+1; i++)
00179 {
00180 QVVector aux = SigmaPoints_t.getRow(i);
00181 Zt.setRow(i, h.evaluate(aux));
00182 }
00183
00184 QVMatrix zt = computeMean(Zt);
00185 QVMatrix St = computeCovariance(zt, Zt) + Qt;
00186 QVMatrix CrossCov = CrossCovariance(mean_t, FdeSigma, zt, Zt);
00187
00188
00189 QVMatrix St_inv(St.getRows(), St.getCols());
00190 SolveByCholeskyDecomposition(St, St_inv, QVMatrix::identity(St.getRows()));
00191 QVMatrix Kt = CrossCov * St_inv;
00192
00193
00194 QVMatrix dis = obs - zt;
00195 QVMatrix final_mean = mean_t + (dis)*Kt.transpose();
00196 QVMatrix final_covariance = covar_t - Kt*St*Kt.transpose();
00197
00198
00199 this->currentState.mean = final_mean;
00200 this->currentState.covariance = final_covariance;
00201 this->discrepance = dis.norm2();
00202 }