SigPack - the C++ signal processing library
kalman_UKF.cpp
Go to the documentation of this file.
1 
15 #include "sigpack.h"
16 
17 using namespace std;
18 using namespace sp;
19 int main()
20 {
21  // Number of samples
22  arma::uword Nsamp = 120;
23  arma::uword N = 6; // Nr of states [X,Y,Vx,Vy,Ax,Ay]
24  arma::uword M = 2; // Nr of measurements
25  arma::uword L = 0; // Nr of inputs
26 
27  // // Instatiate a Extended Kalman Filter
28  // EKF kalman(N,M,L);
29  // Instatiate an Unscented Kalman Filter
30  UKF kalman(N, M, L);
31 
32  // Initialisation and setup of system
33  double P0 = 50;
34  double Q0 = 0.001;
35  double R0 = 8;
36 
37  // Meas interval
38  double dT = 0.1;
39 
40  // [X,Y,Vx,Vy,Ax,Ay] 2D position, velocity and acceleration as states
41  arma::mat x = {0, 5, 10, 50, -0.5, -9.8};
42  arma::inplace_trans(x);
43  arma::mat x_init(x * 0.5); // Init state as 50% of actual value
44  kalman.set_state_vec(x_init);
45 
46  // Set transition function
47  arma::mat A = {{1, 0, dT, 0, dT * dT / 2, 0},
48  {0, 1, 0, dT, 0, dT * dT / 2},
49  {0, 0, 1, 0, dT, 0},
50  {0, 0, 0, 1, 0, dT},
51  {0, 0, 0, 0, 1, 0},
52  {0, 0, 0, 0, 0, 1}};
53  kalman.set_trans_mat(A);
54  // fcn_t f0 = FCN_XUW{ return x(0)+x(2)*dT+x(4)*dT*dT/2; };
55  // fcn_t f1 = FCN_XUW{ return x(1)+x(3)*dT+x(5)*dT*dT/2; };
56  // fcn_t f2 = FCN_XUW{ return x(2)+x(4)*dT; };
57  // fcn_t f3 = FCN_XUW{ return x(3)+x(5)*dT; };
58  // fcn_t f4 = FCN_XUW{ return x(4); };
59  // fcn_t f5 = FCN_XUW{ return x(5); };
60  // fcn_v f = {f0,f1,f2,f3,f4,f5};
61  // kalman.set_trans_fcn(f);
62 
63  // Set process noise
64  arma::mat Q = Q0 * arma::diagmat(arma::vec("1 1 0.1 0.1 0.01 0.01"));
65  kalman.set_proc_noise(Q);
66 
67  // Nonlinear measurement function
68  fcn_t h0 = FCN_XUW { return sqrt(x(0) * x(0) + x(1) * x(1)); };
69  fcn_t h1 = FCN_XUW { return atan2(x(1), x(0)); };
70  fcn_v h = {h0, h1};
71  kalman.set_meas_fcn(h);
72 
73  // Nonlinear measurement jacobian - analytical
74  // fcn_t h_zero = FCN_XUW{ return 0; };
75  // fcn_t h00_j = FCN_XUW{ return x(0)/sqrt(x(0)*x(0)+x(1)*x(1)); };
76  // fcn_t h01_j = FCN_XUW{ return x(1)/sqrt(x(0)*x(0)+x(1)*x(1)); };
77  // fcn_t h10_j = FCN_XUW{ return -x(1)/(x(0)*x(0)+x(1)*x(1)); };
78  // fcn_t h11_j = FCN_XUW{ return x(0)/(x(0)*x(0)+x(1)*x(1)); };
79  // fcn_m h_jac =
80  // {
81  // {h00_j,h01_j,h_zero,h_zero,h_zero,h_zero},
82  // {h10_j,h11_j,h_zero,h_zero,h_zero,h_zero}
83  // };
84  // kalman.set_meas_jac(h_jac);
85 
86  // Error cov
87  arma::mat P = P0 * arma::eye<arma::mat>(N, N);
88  kalman.set_err_cov(P);
89 
90  // Meas noise (for distance and angle)
91  arma::mat R = {{1, 0}, {0, 0.005}};
92  R *= R0;
93  kalman.set_meas_noise(R);
94 
95  // Create simulation data
96  arma::mat z(M, Nsamp, arma::fill::zeros);
97  arma::mat z0(M, Nsamp, arma::fill::zeros);
98  for (arma::uword n = 0; n < Nsamp; n++)
99  {
100  arma::mat v0(N, 1, arma::fill::zeros);
101 
102  // Update state
103  x = A * x + Q * arma::randn(N, 1);
104 
105  // Update measurement
106  z0(0, n) = x(0);
107  z0(1, n) = x(1);
108 
109  // Add meas noise
110  z.col(n) = eval_fcn(h, z0.col(n)) + 0.5 * R * arma::randn(M, 1);
111  }
112 
113  arma::mat xhat_log(N, Nsamp);
114  arma::mat e_log(M, Nsamp);
115  arma::cube P_log(N, N, Nsamp);
116  arma::mat xs_log(M, Nsamp);
117  arma::cube Ps_log(N, N, Nsamp);
118  arma::cube K_log(N, M, Nsamp);
119 
120  // Kalman filter loop
121  for (arma::uword n = 0; n < Nsamp; n++)
122  {
123  // Update
124  kalman.update(z.col(n));
125  xhat_log.col(n) = kalman.get_state_vec();
126 
127  // Predict
128  kalman.predict();
129 
130  e_log.col(n) = kalman.get_err();
131  P_log.slice(n) = kalman.get_err_cov();
132  K_log.slice(n) = kalman.get_kalman_gain();
133  }
134 
135  // RTS smoother
136  kalman.rts_smooth(xhat_log, P_log, xs_log, Ps_log);
137 
138  // Display result
139  gplot gp0;
140  gp0.window("Plot", 10, 10, 500, 500);
141  gp0.set_term("qt");
142  gp0.plot_add(z0.row(0), z0.row(1), "True Y",
143  "lines dashtype 2 linecolor \"black\"");
144  gp0.plot_add(arma::mat(z.row(0) % cos(z.row(1))),
145  arma::mat(z.row(0) % sin(z.row(1))), "Meas Y", "points");
146  gp0.plot_add(xhat_log.row(0), xhat_log.row(1), "Kalman x hat");
147  gp0.plot_add(xs_log.row(0), xs_log.row(1), "RTS smooth");
148  gp0.plot_show();
149 
150  gplot gp1;
151  gp1.window("Plot", 800, 10, 500, 500);
152  gp1.set_term("qt");
153  gp1.plot_add(xhat_log.row(4), "Acc x");
154  gp1.plot_add(xhat_log.row(5), "Acc y");
155  gp1.plot_show();
156 
157  gplot gp2;
158  gp2.window("Plot", 800, 10, 500, 500);
159  gp2.set_term("qt");
160 
161  arma::mat ppp = P_log.tube(0, 0);
162  gp2.plot_add(ppp, "P x");
163  ppp = P_log.tube(1, 1);
164  gp2.plot_add(ppp, "P y");
165  ppp = P_log.tube(2, 2);
166  gp2.plot_add(ppp, "P Vx");
167  ppp = P_log.tube(3, 3);
168  gp2.plot_add(ppp, "P Vy");
169  ppp = P_log.tube(4, 4);
170  gp2.plot_add(ppp, "P Ax");
171  ppp = P_log.tube(5, 5);
172  gp2.plot_add(ppp, "P Ay");
173  gp2.plot_show();
174 
175  return 0;
176 }
void rts_smooth(const arma::mat &Xf, const arma::cube &Pf, arma::mat &Xs, arma::cube &Ps)
Rauch-Tung-Striebel smoother. See http://www.lce.hut.fi/~ssarkka/course_k2011/pdf/course_booklet_2011...
Definition: kalman.h:744
arma::mat get_state_vec(void)
Definition: kalman.h:237
Gnuplot class.
Definition: gplot.h:25
std::function< double(arma::mat, arma::mat, arma::mat)> fcn_t
Definition: kalman.h:13
Definition: base.h:7
Unscented Kalman filter class.
Definition: kalman.h:563
void plot_show(void)
Show plots.
Definition: gplot.h:395
std::vector< fcn_t > fcn_v
Definition: kalman.h:14
arma_inline arma::mat eval_fcn(const fcn_v f, const arma::mat &x, const arma::mat &u, const arma::mat &w)
Evaluate function f(x,u,w)
Definition: kalman.h:25
void predict(const arma::mat u)
Predict the internal states using a control input.
Definition: kalman.h:669
void set_state_vec(const arma::mat &_x)
Definition: kalman.h:197
void set_meas_fcn(fcn_v _h)
Definition: kalman.h:231
void set_proc_noise(const arma::mat &_Q)
Definition: kalman.h:214
arma::mat get_kalman_gain(void)
Definition: kalman.h:239
void set_term(const char *ttype)
Set output terminal.
Definition: gplot.h:759
void set_err_cov(const arma::mat &_P)
Definition: kalman.h:210
void set_trans_mat(const arma::mat &_A)
Definition: kalman.h:198
void window(const int fig, const char *name, const int x, const int y, const int width, const int height)
Configure the figure used Windows environment.
Definition: gplot.h:182
int main()
Definition: kalman_UKF.cpp:19
void plot_add(const T1 &x, const T2 &y, const std::string lb, const std::string ls="lines")
Push plot y vs. x with label and linespec.
Definition: gplot.h:316
void update(const arma::mat z)
Correct and update the internal states. UKF.
Definition: kalman.h:701
#define FCN_XUW
Definition: kalman.h:10
arma::mat get_err(void)
Definition: kalman.h:238
void set_meas_noise(const arma::mat &_R)
Definition: kalman.h:218
arma::mat get_err_cov(void)
Definition: kalman.h:240