Test a Kalman Filter using a sun vector and the earth vector.
Includes states for unknown attitude biases. You can turn these states on or off. If on you will not get an accurate yaw bias estimate. ------------------------------------------------------------------------- See also C2DZOH, Plot2D, CosD, KFSunAndEarth2, RW2SDev -------------------------------------------------------------------------
Contents
------------------------------------------------------------------------- Copyright 1999 Princeton Satellite Systems, Inc. All rights reserved. -------------------------------------------------------------------------
Turn off the bias states
%-------------------------
d = struct;
d.biasStates = 1;
degToRad = (pi/180);
radToDeg = 180/pi;
arcsecToRad = degToRad / 3600;
perHrToPerSec = 1/3600;
dT = 10;
nSim = 9000;
angle = linspace(0,7.291e-5*dT*nSim,nSim) + 3*pi/2 - pi/4;
pPlot = zeros(9,nSim);
xPlot = zeros(9,nSim);
sunPlot = zeros(1,nSim);
bPlot = zeros(3,nSim);
gyro model
sqrtDT = sqrt(dT); % units of 1 sigma given for wn is rad/sec^.5, for rw rad/sec^1.5 % These are continuous values (except for an, which ?? wnIFOG = 1.4544e-6*ones(3,1);%/sqrtDT*ones(3,1); % white noise added to bias (drift) rad/sec % rwIFOG = 8.0964e-9*ones(3,1); %*sqrtDT*ones(3,1); % random walk added to bias (drift) rad/sec rwIFOG = RW2SDev(0.015*perHrToPerSec)*ones(3,1); % random walk added to bias (drift) rad/sec % rwIFOG = RW2SDev(0.006*perHrToPerSec)*ones(3,1); % random walk added to bias (drift) rad/sec anIFOG = zeros(3,1); %4.8481e-7*ones(3,1); % white noise added to delta angles % sfIFOG = 0.03928 * arcsecToRad; % scale factor for gyro counts
use Litton HRG parameters (these are not IFOG #'s, but keep same variable names for convenience)
rwIFOG = RW2SDev(0.005*perHrToPerSec)*ones(3,1); wnIFOG = RW2SDev(0.0003)*ones(3,1);
assume there is an unknown (and unestimable) attitude bias
bAtt = [0;0;0]; % this is the unknown attitude bias nAtt = [0.067; 0.071; 0] / 3 * degToRad; bGyro = [1;2;4]*1.e-5; wO = -7.291e-5; w = [0;wO;0]; p = diag([1e-5;1e-5;1e-5;0;0;0; nAtt]); x = zeros(9,1); theta = [0;0;0]; %[0.01;0.02;0.03] * degToRad; d.wO = w;
convert from continuous to discrete measurement noise
sigmaESA = [0.0280 0.0180]*degToRad /sqrtDT;
sigmaESA = [0.11 0.055]/3 *degToRad /sqrtDT; sigmaSSA = sqrt(0.003^2/12 + 0.001^2) *degToRad * ones(1,2) /sqrtDT; % sigmaSSA = 3 *degToRad * ones(1,2) /sqrtDT; d.r = diag([sigmaSSA sigmaESA].^2); % d.q = diag([wnIFOG.^2; rwIFOG.^2]*dT); % discrete plant noise depends on gyro & dT d.q = diag([wnIFOG.^2; rwIFOG.^2; zeros(3,1)]*dT); % discrete plant noise depends on gyro & dT sigWN = sqrt(diag(d.q(1:3,1:3))); sigRW = sqrt(diag(d.q(4:6,4:6))); d.noSun = CosD(50); % cosine of the sun sensor FOV %d.noSun = 1.1; % prevents all sun measurements %d.noSun = -2; % allows sun measurements throughout the orbit b = [eye(3);zeros(6,3)]; a = [ 0 0 -wO -1 0 0 0 0 -wO;... 0 0 0 0 -1 0 0 0 0 ;... wO 0 0 0 0 -1 wO 0 0 ;... zeros(6,9)];
Turn off the bias states
%------------------------- if( ~d.biasStates ) a = a(1:6,1:6); b = b(1:6,1:3); d.q = d.q(1:6,1:6); p = p(1:6,1:6); pPlot = pPlot(1:6,:); x = x(1:6); xPlot = xPlot(1:6,:); end [d.a, d.b] = C2DZOH(a,b,dT); sunAng = 0; % equinox cSun = cos(sunAng); sSun = sin(sunAng);
Simulation
%----------- for k = 1:length(angle) % Plotting %--------- pPlot(:,k) = diag(p); bPlot(:,k) = bGyro; xPlot(:,k) = x; % Sun sensor %----------- sAK = sin(angle(k)); cAK = cos(angle(k)); d.u = [-sAK*cSun;sSun;-cAK*cSun]; d.uMeas = [ 1 theta(3) -theta(2);... -theta(3) 1 theta(1);... theta(2) -theta(1) 1 ]*d.u; d.uMeas(2:3) = d.uMeas(2:3) + sigmaSSA'.*randn(2,1); % Earth Sensor %------------- d.theta = (theta(1:2) + bAtt(1:2)) + sigmaESA'.*randn(2,1); % Random walk %------------ bGyro = bGyro + sigRW.* randn(3,1); % Total drift is random walk + noise %----------------------------------- drift = bGyro + sigWN.* randn(3,1); % Update the covariance %---------------------- [p, x] = KFSunAndEarth2( p, x, d, w + drift + anIFOG.*randn(3,1)/dT ); % Show when the sun is available as a measurement %------------------------------------------------ sunPlot(k) = d.u(1) >= d.noSun; end angle = angle*radToDeg; if( d.biasStates ) yL = ['thetaX';'thetaY';'thetaZ';... 'gyroBX';'gyroBY';'gyroBZ';... 'attBX ';'attBY ';'attBZ ']; else yL = ['thetaX';'thetaY';'thetaZ';... 'gyroBX';'gyroBY';'gyroBZ']; end Plot2D(angle,pPlot, 'Alpha', yL, 'Covariance Matrix'); Plot2D(angle,xPlot(1:3,:)*radToDeg,'Alpha','Angle (deg)','Angle'); legend('roll','pitch','yaw') Plot2D(angle,[xPlot(4:6,:);bPlot],'Alpha',strvcat('Estimated Bias (rad/sec)','True bias'),'Bias',[],['1:3';'4:6']); legend('roll','pitch','yaw') Plot2D(angle,sunPlot,'Alpha','Sun in FOV'); ax = axis; axis([ax(1:2) -0.5 1.5]); att3Sigma = sqrt(pPlot(1:3,:))*3*radToDeg; Plot2D(angle,att3Sigma,'Alpha',strvcat('Roll (deg)','Pitch (deg)','Yaw (deg)'),'Attitude Covariance 3 Sigma') ax = axis; for k = 1:2 subplot(3,1,k); set(gca,'xticklabelmode','auto'); axis([ax(1:2) 0 0.02]); end %-------------------------------------- % PSS internal file version information %--------------------------------------