Search code examples
pythonmatlabfilterkalman-filterestimation

Designing Kalman Filter


So, I was asked to design a Kalman filter and run some simulations to see the results. Given equations:

x(k+1) = -0.8*x(k) + sin(0.1k) + w(k)
y(k) = x(k) + v(k)

where w(k) and v(k) are processing and measurment noises
w(k)~N(0, 0.01)
v(k)~N(0, 1)

I want to make sure that everything works fine and makes sense in my code.

A = -0.8;
B = 1;
C = 1;

% Covariance matrices
% Processing noise
W = 0.01;
Q=W;

% Measurement noise
V = 1;
R=V;

% Initial conditions
x0 = 0;
P0 = 0;
xpri = x0;
Ppri = P0;
xpost = x0;
Ppost = P0;

% State
Y = zeros(1, size(t,2));
X = Y;
X(1) = x0;

% xpri - x priori
% xpost - x posteriori
% Ppri - P priori
% Ppost - P posteriori

for i = 1:size(t,2)
    %Simulation
    Y(i) = C*sin((i-1)*0.1)+normrnd(0,sqrt(V));

    if i > 1

        % Prediction
        xpri = A*xpost+B*sin((i-1)*0.1);
        Ppri = A*Ppost*A' + Q;

        eps = Y(i) - C*xpri;
        S = C*Ppri*C' + R;
        K = Ppri*C'*S^(-1);
        xpost = xpri + K*eps;
        Ppost = Ppri - K*S*K';
        X(i) = xpost;
    end
end

plot(t, Y, 'b', t, X, 'r')
title('Kalman's Filter')
xlabel('Time')
ylabel('Value')
legend('Measured value', 'Estimated value')

Does this KF work properly? If not, what is wrong?

enter image description here


Solution

  • The code looks OK and the results also. What makes you suspicious?

    Here is a generic Kalman-filter implementation as a function that you can check out if you want to double-check. But with the filter, its all about the tuning of the covariance matrices P, Q, R...

    function [v_f,xyz] = KF(u,z,A,B,C,D,x0,P0,Q,R)
    %% initialization
    persistent x P
    if isempty(x)||isempty(P)
       % state vector
       x = reshape(x0,numel(x0),1);  % ensure vector size
    
       if nargin < 8 || isempty(P0)
           P0 = eye(length(x)); %default initialization
       emd
       P = P0;    % covariance matrix
    end
    
    
    %% covariance matrices 
    if nargin < 9 || isempty(Q)
        Q = diag( ones(length(x) )*1e1;  % proess-noise-covariance
    end
    % % Q = 0 -> perfect model. Q =/= 0 -> pay more attention to the measurements.
    %
    if nargin < 10
         R = diag( ones(length(z)) ) *1e1;     % measurement-noise-covariance
    end
    % The higher R, the less trusting the measurements
    
    
    %% prediction
    x_P = A*x + B*u;
    P = A*P*A.' + Q;   % covariance matrix
    
    %% update
    H = C;
    
    K = P*H.'*(H*P*H.' +R)^-1;
    x = x_P + K*(z - H*x_P);
    P = (eye(length(x)) - K*H)*P;
    
    %% Output
    y = C*x;
    end
    

    In any case, I would suggest to transfer this question to the codereview-pages because you have apparently no problem and just want to review your code, right?