home *** CD-ROM | disk | FTP | other *** search
- echo on
-
- % This file demonstrates MATLAB's ability to do Kalman filtering.
- % Both a steady state filter and a time varying filter are designed
- % and simulated below.
-
- echo off
- % Copyright (c) 1986-93 by the MathWorks, Inc.
- echo on
-
- pause % Press any key to continue ...
-
- % Given the following discrete plant
- A=[
- 1.1269 -0.4940 0.1129
- 1.0000 0 0
- 0 1.0000 0];
- B = [
- -0.3832
- 0.5919
- 0.5191];
- C=[ 1 0 0];
- D=0;
- printsys(A,B,C,D)
-
- % Design a Kalman filter to filter out Gaussian noise added to the
- % input (i.e sensor noise).
-
- pause % Press any key to continue ...
-
- % Let's do a steady state filter design first using the function
- % DLQE. The function DLQE determines the optimal steady state
- % filter gain based on the process noise covariance Q, and the
- % sensor noise covariance, R.
-
- % For your information the dcgain of this plant is
- ddcgain(A,B,C,D)
-
- % and the covariance of the output due to process noise with
- % covariance of 1 is:
- dcovar(A,B,C,D,1)
-
- % Enter the process noise covariance:
- Q = input('Enter a number greater than zero (e.g. 1): ')
-
- % Enter the sensor noise covariance:
- R = input('Enter a number greater than zero (e.g. 1): ')
-
- % Now design the steady state filter gain
- Lss = dlqe(A,B,C,Q,R)
-
- pause % Press any key to continue ...
-
- % The steady state Kalman filter we have just designed has the
- % following update equations:
- % - *
- % time update: x[n+1] = Ax[n] + Bu[n]
- %
- % * - -
- % observation update: x[n] = x[n] + L(y[n] - Cx[n] - Du[n])
-
- % Since this is a steady state filter we can combine these equations
- % into one state model (the Kalman filter)
- % - -
- % x[n+1] = (A-ALC) x[n] + AL y[n]
- %
- % * -
- % y[n] = (C-CLC) x[n] + CL y[n]
- %
- % The function DESTIM produces this model (but also includes the
- % estimated states as outputs):
- [af,bf,cf,df] = destim(A,B,C,D,Lss,[1],[1]);
-
- % Remove est. state outputs
- [af,bf,cf,df] = ssdelete(af,bf,cf,df,[],[2:4]);
- printsys(af,bf,cf,df,'u y','y*','x1 x2 x3')
-
- pause % Press any key to continue ...
-
- % Let's see how it works by generating some data and comparing the
- % filtered response with the true response
- % noise noise
- % | |
- % V V
- % u -+->O-->[Plant]-->O--> y --O->[filter]-->y*
- % | |
- % +-------------------------------+
- %
-
- % To simulate the system above, we could generate the response of
- % each part separately or we could generate both together. To
- % simulate each seperately we would use DLSIM with the plant first
- % and then the filter. Below we illustrate how to simulate both
- % together.
-
- % First, build one plant that contains the original plant and the
- % filter connected as shown in the diagram above. Use PARALLEL and
- % CLOOP. Before connecting, add a process noise input to the plant
- % that is the same as u and a sensor noise input.
- a = A; b=[B,B,zeros(3,1)]; c = C; d=[D,D,1];
-
- % Now connect the original plant input (1) with the known input (1)
- % of the filter using PARALLEL.
- [at,bt,ct,dt] = parallel(a,b,c,d,af,bf,cf,df,[1],[1],[],[]);
-
- % Put the plant output (1) into the filter sensor input (4)
- [at,bt,ct,dt] = cloop(at,bt,ct,dt,[1],[4]);
-
- pause % Press any key to continue ...
-
- % The complete system model now has 4 inputs
- % (plant input,process noise,sensor noise,sensor input),
- % 2 outputs
- % (plant output with noise,filtered output),
- % and 6 states.
-
- % Generate a sinusoidal input vector (known)
- t = [0:100]';
- u = sin(t/5);
-
- % Generate process noise and sensor noise vectors
- pnoise = sqrt(Q)*randn(length(t),1);
- snoise = sqrt(R)*randn(length(t),1);
-
- pause % Press any key to continue ...
-
- % Now simulate using DLSIM
- [y,x] = dlsim(at,bt,ct,dt,[u,pnoise,snoise,zeros(length(t),1)]);
-
- % Generate "true" response
- ytrue = y(:,1)-snoise;
-
- % Plot comparison
- clg
- %subplot(211), plot(t,ytrue,t,y), xlabel('No. of samples'), ylabel('Output')
- %subplot(212), plot(t,ytrue-y(:,2)), xlabel('No. of samples'), ylabel('Error')
- %pause % Press any key to continue ...
- echo off
- subplot(211), plot(t,ytrue,t,y), xlabel('No. of samples'), ylabel('Output')
- subplot(212), plot(t,ytrue-y(:,2)), xlabel('No. of samples'), ylabel('Error')
- pause % Press any key after the plot ...
- echo on
-
- % Compute covariance of error
- err1 = ytrue-y(:,1);
- err1cov = sum(err1.*err1)/length(err1);
- err2 = ytrue-y(:,2);
- err2cov = sum(err2.*err2)/length(err2);
-
- % Covariance of error before filtering
- err1cov
-
- % Covariance of error after filtering
- err2cov
-
- pause % Press any key to continue ...
-
- % Now let's form a time varying Kalman filter to perform the same
- % task. A time varying Kalman filter is able to perform well even
- % when the noise covariance is not stationary. However for this
- % demonstration, we will use stationary covariance.
-
- % The time varying Kalman filter has the following update equations
- % - *
- % time update: x[n+1] = Ax[n] + Bu[n]
- % - *
- % P[n+1] = AP[n]A' + B*Q*B'
- %
- % - - -1
- % observation update: L[n] = P[n]C'(CP[n]C'+R)
- % * - -
- % x[n] = x[n] + L[n](y[n] - Cx[n] - Du[n])
- % * -
- % P[n] = (I-L[n]C)P[n]
- % * *
- % y[n] = Cx[n] + Du[n]
- %
-
- pause % Press any key to continue ...
-
- % Generate the noisy plant response
- y = dlsim(A,B,C,D,u+pnoise) + snoise;
-
- % Now filter. We can't use DLSIM here since the system is nonlinear,
- % so just implement the above equations in a loop. Use the same inputs
- % as before.
-
- P=B*Q*B'; % Guess for initial state covariance
- x=zeros(3,1); % Initial condition on the state
- yest = zeros(length(t),1);
- ycov = zeros(length(t),1);
- for i=1:length(t)
- yest(i) = C*x + D*u(i);
- ycov(i) = C*P*C';
-
- % Time update
- x = A*x + B*u(i);
- P = A*P*A' + B*Q*B';
-
- % Observation update
- L = P*C'/(C*P*C'+R);
- x = x + L*(y(i) - C*x - D*u(i));
- P = (eye(3)-L*C)*P;
- end
-
- % Compare true response with filtered response
- clg
- %subplot(211), plot(t,y-snoise,t,yest), ylabel('Output')
- %subplot(212), plot(t,yest-y+snoise), ylabel('Error'), pause % Press any key
- echo off
- subplot(211), plot(t,y-snoise,t,yest), ylabel('Output')
- subplot(212), plot(t,yest-y+snoise), ylabel('Error'), pause % Press any key
- echo on
-
- % The time varying filter also estimates the output covariance
- % during the estimation. Let's plot it to see if our filter reached
- % steady state (as we would expect with stationary input noise).
- subplot(111), plot(t,ycov), ylabel('Covar'), pause % Press any key after plot
-
- % From the covariance plot we see that the output covariance did
- % indeed reach a steady state in about 5 samples. From then on,
- % our time varying filter has the same performance as the steady
- % state version.
-
- % Compute covariance of error
- err = y-snoise-yest;
- errcov = sum(err.*err)/length(err)
-
- pause % Press any key to continue ...
-
- %Let's compare the final Kalman gain matrices
- L,Lss
-
- % So we see that they both obtain the same gain matrix in steady
- % state.
-
- echo off
-