Alpha-Beta-Gamma Filter

The ABG filter is a simplified version of a steady state Kalman filter.
Often it is practical to update the Kalman gains every iteration and
often one doesn't know the covarience of the system and measurement noise
so they are 'fudged' to get the desired results. It that is so then on can
chose the ABG filter were the one simply choses the bandwidth that yields
satisfactory results.

The prime use for the ABG filter for motion control is to filter reference
inputs like joy sticks or line speed encoders.

The ABG system matrix for 10 millisecond intervals.
The state x(n)=[[p(n)],[v(n)],[a(n)]]
The matrix is generate by
p(n+1)=p(n)+v(n)*δ+a(n)*δ^2/2
v(n+1)=v(n)+a(n)*δ
a(n+1)=a(n)
Basically the A matrix provides inertia for the filter. The A matrix
will not try to change state. Any corrections is done using the gains.

(%i48) numer: false$
'%delta=%delta: 1/100;
'A=A: matrix([1,%delta,%delta^2/2],[0,1,%delta],[0,0,1]);

Result

The ABG system matrix for 1 millisecond intervals.
This matrix is used to estimate the state between samples.

(%i51) '%delta=%delta: 1/1000;
'A=A: matrix([1,%delta,%delta^2/2],[0,1,%delta],[0,0,1]);

Result

10 iterations of the 1 millisecond system matrix is the same as
one iteration of the 10 millisecond system matrix.

(%i53) A^^10;
Result

Calculate the matrix coefficients for the transition matrix and the ABG gains.
'K=K: matrix([3*%omega],[3*%omega^2],[%omega^3])*%delta; /* For 3 Pole LP ABG or SS Kalman gains */
'K=K: matrix([2*%omega],[2*%omega^2],[%omega^3])*%delta; /* For Butterworth ABG or SS Kalman gains */
'K=K: matrix([2.090001*%omega],[1.479343*%omega^2],[%omega^3])*%delta; /* For IAE */

(%i54) numer: true$ /* Do floating point calcuclations below here */
load(distrib)$ /* Load the random_normal function */
'delta=%delta: 0.01; /* ABG sampling time in seconds */
'resolution=resolution: 3/16384; /* Resolution 14 bit = 3 meters/16384 counts */
'jitter=jitter: 0.0005; /* Jitter value for Weibull distribution, seconds */
'%omega=%omega: float(2*%pi*2); /* ABG filter bandwidth, radians per second */
'A=A: matrix([1,%delta,%delta^2/2],[0,1,%delta],[0,0,1]);
'K=K: matrix([3*%omega],[3*%omega^2],[%omega^3])*%delta; /* ABG or SS Kalman gains */
'K=K: matrix([2.090001*%omega],[1.479343*%omega^2],[%omega^3])*%delta; /* For IAE */
'Amp=Amp: 1.0; /* Wave amplitude */
'Tw=Tw: 10; /* Wave period */
r(t):=Amp*matrix([sin(2*%pi*t/Tw)],
                [cos(2*%pi*t/Tw)*(2*%pi/Tw)],
                [-sin(2*%pi*t/Tw)*(2*%pi/Tw)^2]);
'x=x: r(-%delta);

Result

Calculate the meassured positions
The time is varied to simulate sample jitter and the result is truncate to the feed back resolution

(%i67) ylist: makelist(floor(r(i*%delta+quantile_weibull(random(1.0),2,jitter))[1,1]/resolution)*resolution,i,0,2000)$

Calculate the estimated position, velocity and acceleration

(%i68) xt: transpose(x)$ /* Initialize xt, the transposed state */
for i:1 thru 2000 do
(
    x: A.x, /* Update estimated state */
    x: x+K*(ylist[i]-x[1,1]), /* Correct for errors between actual and estimated */
    xt: addrow(xt,transpose(x)) /* Append to end of array */
)$

Make lists for plotting

(%i70) '[Rows,Cols]=[Rows,Cols]: matrix_size(xt);
tlist: makelist((i-1)*%delta,i,1,Rows)$

Result

Plot the positions

(%i72) xlist: makelist(xt[i,1],i,1,Rows)$
rlist: makelist(r((i-1)*%delta)[1][1],i,1,Rows)$
wxplot2d([[discrete,tlist,xlist],
          [discrete,tlist,ylist],
          [discrete,tlist,rlist]],
    [legend,"Estimated Position","Measured Position","Actual Position"],
    [xlabel,"time, sec"],[ylabel,"Position, m"]);

Result

Plot the position error. There is a slight bias to the high side
because the measured position is rounded down.

(%i75) elist: makelist(r((i-1)*%delta)[1][1]-xt[i,1],i,1,Rows)$
wxplot2d([[discrete,tlist,elist]],
    [legend,"Estimated Position Error"],
    [xlabel,"time, sec"],[ylabel,"Estimated Position Error, m"]);

Result

Plot the velocities

(%i77) xxlist: makelist(xt[i,2],i,1,Rows)$
rrlist: makelist(r((i-1)*%delta)[2][1],i,1,Rows)$
wxplot2d([[discrete,tlist,xxlist],[discrete,tlist,rrlist]],
    [legend,"Estimated Velocity","Actual Velocity"],
    [xlabel,"time, sec"],[ylabel,"Velocity, m/s"]);

Result

(%i80) eelist: makelist(r((i-1)*%delta)[2][1]-xt[i,2],i,1,Rows)$
wxplot2d([[discrete,tlist,eelist]],
    [legend,"Estimated Velocity Error"],
    [xlabel,"time, sec"],[ylabel,"Estimated Velocity Error, m/s"]);

Result

Plot the accelerations

(%i82) xxxlist: makelist(xt[i,3],i,1,Rows)$
rrrlist: makelist(r((i-1)*%delta)[3][1],i,1,Rows)$
wxplot2d([[discrete,tlist,xxxlist],[discrete,tlist,rrrlist]],
    [legend,"Estimated Acceleration","Actual Acceleration"],
    [xlabel,"time, sec"],[ylabel,"Acceleration, m/s^2"]);

Result

(%i85) eeelist: makelist(r((i-1)*%delta)[3][1]-xt[i,3],i,1,Rows)$
wxplot2d([[discrete,tlist,eeelist]],
    [legend,"Estimated Accleration Error"],
    [xlabel,"time, sec"],[ylabel,"Estimated Acceleration Error, m/s^2"]);

Result

Calculate standard deviation of estimated position, velocity and
acceleration from actual position, velocity and accelreation.

(%i87) 'PositionStdDev=sqrt(lsum(i^2,i,elist)/Rows);
'VelocityStdDev=sqrt(lsum(i^2,i,eelist)/Rows);
'AccelerationStdDev=sqrt(lsum(i^2,i,eeelist)/Rows);

Result

Quantizing due to resolution.
Units are in meters and seconds

(%i90) 'PositionResolution=resolution;
'VelocityResolution=resolution/%delta;
'AccelerationResolution=resolution/%delta^2;

Result

Weibull distribution for simulating sample jitter.
The probabilty distribution function
The inverse cumulative distribution function.

(%i93) wxplot2d(pdf_weibull(i,2,jitter),[i,0.0,%delta]);
wxplot2d(quantile_weibull(i,2,jitter),[i,0.0,1.0]);

Result


Created with wxMaxima.