qub_kalman.cpp.html | mathcode2html |
Source file: qub_kalman.cpp | |
Converted: Thu Feb 26 2015 at 13:39:00 | |
This documentation file will not reflect any later changes in the source file. |
$$\phantom{******** If you see this on the webpage then the
browser could not locate *********}$$
$$\phantom{******** jsMath/easy/load.js or the variable root
is set wrong in this file *********}$$
$$\newcommand{\vector}[1]{\left[\begin{array}{c} #1 \end{array}\right]}$$
$$\newenvironment{matrix}{\left[\begin{array}{cccccccccc}} {\end{array}\right]}$$
$$\newcommand{\A}{{\cal A}}$$
$$\newcommand{\W}{{\cal W}}$$
/* Copyright 2008-2011 Research Foundation State University of New York */ /* This file is part of QUB Express. */ /* QUB Express is free software; you can redistribute it and/or modify */ /* it under the terms of the GNU General Public License as published by */ /* the Free Software Foundation, either version 3 of the License, or */ /* (at your option) any later version. */ /* QUB Express is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* You should have received a copy of the GNU General Public License, */ /* named LICENSE.txt, in the QUB Express program directory. If not, see */ /* <http://www.gnu.org/licenses/>. */ /*
|
See also: |
*/ #ifdef _WIN32 #include <windows.h> #else #include <stdlib.h> #define BOOL int #define TRUE 1 #define FALSE 0 #endif #include <iostream> #include <fstream> #include <vector> #include "qub_kalman.h" #include "ublas_matrixutil.h" using std::cout; using std::cerr; using std::endl; class qub_kalman_storage { public: int Np, Nm; pointy_matrix<double> A, Q, H, R; qub_kalman_storage(int Nprocess, int Nmeasure) : Np(Nprocess), Nm(Nmeasure), A(Nprocess, Nprocess), Q(Nprocess, Nprocess), H(Nmeasure, Nprocess), R(Nmeasure, Nmeasure) { fill_identity(A.m); } }; extern "C" QUBFAST_API qub_kalman_const * qub_kalman_create(int Nprocess, int Nmeasure) { qub_kalman_const *f = new qub_kalman_const; qub_kalman_storage *s = new qub_kalman_storage(Nprocess, Nmeasure); f->storage = s; f->Nprocess = Nprocess; f->Nmeasure = Nmeasure; f->A = s->A.pp; f->Q = s->Q.pp; f->H = s->H.pp; f->R = s->R.pp; return f; } extern "C" QUBFAST_API void qub_kalman_free(qub_kalman_const *filter) { delete (qub_kalman_storage *) filter->storage; delete filter; } class qub_kalman_state_storage { public: qub_kalman_const *kalman; qub_kalman_storage *kst; pointy_col_vector<double> X, Z; pointy_matrix<double> P; pointy_col_vector<double> Xprior, ZmHx; pointy_matrix<double> Pprior, PpAt, PpHt, HPpHt, HPpHtRi, K, Ip, KH, ImKH; qub_kalman_state_storage(qub_kalman_const *kalman_) : kalman(kalman_), kst( (qub_kalman_storage *) kalman->storage ), X(kst->Np), Z(kst->Nm), P(kst->Np, kst->Np), Xprior(kst->Np), ZmHx(kst->Nm), Pprior(kst->Np, kst->Np), PpAt(kst->Np, kst->Np), PpHt(kst->Np, kst->Nm), HPpHt(kst->Nm, kst->Nm), HPpHtRi(kst->Nm, kst->Nm), K(kst->Np, kst->Nm), Ip(kst->Np, kst->Np), KH(kst->Np, kst->Np), ImKH(kst->Np, kst->Np) { fill_identity(Ip.m); reset(); } qub_kalman_state_storage& operator=(const qub_kalman_state_storage& other) { X.m = other.X.m; Z.m = other.Z.m; P.m = other.P.m; return *this; } void reset() { P.m = kst->Q.m; } void next(qub_kalman_state_storage& from, double *z) { noalias(Xprior.m) = prod(kst->A.m, from.X.m); // x- = A*x; noalias(PpAt.m) = prod(from.P.m, trans(kst->A.m)); noalias(Pprior.m) = prod(kst->A.m, PpAt.m); // p- = A*P*At Pprior.m += kst->Q.m; // + Q; noalias(PpHt.m) = prod(Pprior.m, trans(kst->H.m)); noalias(HPpHt.m) = prod(kst->H.m, PpHt.m); HPpHt.m += kst->R.m; if ( kst->Nm > 1 ) sv_invm(HPpHt.pp, kst->Nm, HPpHtRi.pp); // inv(H*P-*Ht + R) else HPpHtRi.p[0] = 1.0 / HPpHt.p[0]; noalias(K.m) = prod(PpHt.m, HPpHtRi.m); // K = P-*Ht * inv(HP-Ht + R); noalias(ZmHx.m) = prod(kst->H.m, Xprior.m); for (int i=0; i<kst->Nm; ++i) ZmHx.p[i] = z[i] - ZmHx.p[i]; // (Z - H*Xp) noalias(X.m) = prod(K.m, ZmHx.m); for (int i=0; i<kst->Np; ++i) X.p[i] += Xprior.p[i]; // X = Xp + K(Z - HXp); noalias(KH.m) = prod(K.m, kst->H.m); ImKH.m = Ip.m - KH.m; noalias(P.m) = prod(ImKH.m, Pprior.m); // P = (I - KH)Pp; noalias(Z.m) = prod(kst->H.m, X.m); // Z = HX; } }; extern "C" QUBFAST_API qub_kalman_state * qub_kalman_state_create(qub_kalman_const *kalman) { qub_kalman_state *f = new qub_kalman_state; qub_kalman_state_storage *s = new qub_kalman_state_storage(kalman); f->storage = s; f->kalman = kalman; f->X = s->X.p; f->Z = s->Z.p; f->P = s->P.pp; return f; } extern "C" QUBFAST_API void qub_kalman_state_free(qub_kalman_state *state) { if ( state ) delete (qub_kalman_state_storage*) state->storage; delete state; } extern "C" QUBFAST_API void qub_kalman_state_copy(qub_kalman_state *into, qub_kalman_state *from) { * (qub_kalman_state_storage *) into->storage = * (qub_kalman_state_storage *) from->storage; } extern "C" QUBFAST_API void qub_kalman_state_reset(qub_kalman_state *state) { ((qub_kalman_state_storage*) (state->storage))->reset(); } extern "C" QUBFAST_API void qub_kalman_state_next(qub_kalman_state *state, double *z) { qub_kalman_state_storage *st = (qub_kalman_state_storage*) state->storage; st->next(*st, z); } extern "C" QUBFAST_API void qub_kalman_state_next_into(qub_kalman_state *into, qub_kalman_state *from, double *z) { qub_kalman_state_storage *st_into = (qub_kalman_state_storage*) into->storage; qub_kalman_state_storage *st_from = (qub_kalman_state_storage*) from->storage; st_into->next(*st_from, z); } extern "C" QUBFAST_API void qub_kalman_filter(qub_kalman_state *state, int N, double *z, double *p) { qub_kalman_state_storage *st = (qub_kalman_state_storage*) state->storage; for (int i=0; i<N; ++i) { st->next(*st, z+i); z[i] = state->Z[0]; if ( p ) p[i] = state->P[0][0]; } }