Test the orbit Kalman Filter with omni and GPS measurements.
The simulation and the filter both use the same RHS, FOrbKF, but the simulation uses more terms in the gravity model. ------------------------------------------------------------------------ See also CDKF45, OrbitKFRHS, HRangeMeasurement, RangeMeasurement, GPSReceiver, and FOrbKF, Plot2D, TimeGUI, Cross, RK4, RK45, Date2JD, JD2T, LoadGravityModel, OrbRate, El2RV, Period, EarthRot, EarthRte, GPSSatellite, Omni ------------------------------------------------------------------------
Contents
%------------------------------------------------------------------------------- % Copyright (c) 2001-2003 Princeton Satellite Systems, Inc. All rights reserved. %-------------------------------------------------------------------------------
Global for the time GUI
%------------------------ global simulationAction simulationAction = ' '; printIt = 0;
Set up the orbit
%-----------------
el = [7000 0.6 0 0 0.0001 0];
p = Period( el(1) );
[r, v] = El2RV( el );
Initial estimates
%------------------
dT = 120;
jD = Date2JD([2001 3 20 13 15 1]);
Initialize the sim
%------------------- nOrbits = 2; nSim = ceil(nOrbits*p/dT); bias = 0.01/3e5/3600; % 0.01 sec/hr one sigma biasDrift = bias/3600; x = [r;v;bias;biasDrift]; t = 0; useOmni = 1; useGPS = 1; gravityModel = LoadGravityModel( 'load file', 'GEMT1.geo' ); simData = struct('jD',jD,... 'gravityModel',gravityModel,... 'highFidelity',1,... 'nTess',6,... 'nZonal',6,... 'planetaryOn',1,... 'aExt',[0;0;0]);
For print outs
%--------------- if( bias > 0 ) prefix = 'Clock'; else prefix = ''; end
Set up omni measurements
%---------------------------------------------------
rStationEF = {};
vStationEF = {};
rStationEF{1} = [6378.165;0;0];
vStationEF{1} = Cross( [0;0;EarthRte(jD)], rStationEF{1} );
nOmni = length(rStationEF);
rOmni = [0.001 0;0 1e-6].^2;
omni = struct();
omni.power = 5;
omni.range1Sigma = 0.001;
omni.rangeRate1Sigma = 1e-6;
omni.minimumAngle = 3*pi/180;
Set up GPS
%------------------------------------------------------- nGPS = 4; useReceiver = 1; gPSReceiver = struct(); gPSReceiver.tSamp = 1; gPSReceiver.minimumAltitude = 100; gPSReceiver.power = 5; gPSReceiver.range1Sigma = 0.001; % noise in model gPSReceiver.rangeRate1Sigma = 1e-6; rGPS = [0.001 0;0 1e-6].^2; GPSReceiver( 'initialize', gPSReceiver ); nMeas = useOmni*nOmni+useGPS*nGPS;
Initialize the estimator
%------------------------- dR = 0.25; dV = dR/1000; d = struct; d.p = diag([dR*[1 1 1] dV*[1 1 1] bias biasDrift].^2 ); mu = 3.98600436e5; rE = r + [0.1;-0.15;0.07]; vE = v + [0.001;-0.004;0.003]; d.x = [rE;vE;0;0]; d.propagator = 'RK45'; d.q = diag([0 0 0 (0.001*mu/7000^2)*[1 1 1] 0.1*bias 0.1*biasDrift].^2); d.fName = @OrbitKFRHS; d.fData = struct('dFName',@FOrbKF,... 'nStates',17,... 'jD',jD,... 'highFidelity',1,... 'gravityModel',gravityModel,... 'nTess',2,... 'nZonal',2,... 'planetaryOn',1,... 'aExt',[0;0;0]); d.hName = @HRangeMeasurement; if (d.fData.nStates == 17) d.x = [d.x;zeros(9,1)]; pDist = 1e-7*[1 1 1e-3]; d.p = diag ([dR*[1 1 1] dV*[1 1 1] bias biasDrift pDist pDist pDist].^2 ); d.q = diag([0 0 0 (0.001*mu/7000^2)*[1 1 1] 0.1*bias 0.1*biasDrift 0.1*[pDist pDist pDist]].^2); end d.xMeas = d.x; d.pMeas = d.p; d.hLast = 0.1*dT; d.nIterations = 2; d.tol = 1e-6; range = []; rangeRate = []; d.r = {}; j = 0;
Plotting arrays
%----------------
xPlot = zeros(length(x),nSim);
xEPlot = zeros(length(d.x),nSim);
pPlot = zeros(length(d.x),nSim);
rPlot = zeros(nMeas*2,nSim);
resPlot = zeros(nMeas*2,nSim);
Numerical integration
%----------------------
tol = 1e-6;
hLastT = 0.1*dT;
hLastE = 0.1*dT;
Initialize the time display
%---------------------------- [ ratioRealTime, tToGoMem ] = TimeGUI( nSim, 0, [], 0, dT, 'Orbit Kalman Filter' ); for k = 1:nSim % Display the status message %--------------------------- [ ratioRealTime, tToGoMem ] = TimeGUI( nSim, k, tToGoMem, ratioRealTime, dT ); % Measurement from earth stations %-------------------------------- if useOmni mEarth = EarthRot( JD2T( jD ) )'; for i = 1:nOmni j = j + 1; % Skip omni model and idealize ground stations as always available [range(j,1), rangeRate(j,1)] = RangeMeasurement( x(1:3,:), x(4:6,:), x(7:8,:)*3e5, mEarth*rStationEF{i}, mEarth*vStationEF{i} ); range(j,1) = range(j,1) + omni.range1Sigma*randn; rangeRate(j,1) = rangeRate(j,1) + omni.rangeRate1Sigma*randn; d.r{j} = rOmni; d.hData(j).rSource = rStationEF{i}; d.hData(j).vSource = vStationEF{i}; d.hData(j).rSourceECI = mEarth*rStationEF{i}; d.hData(j).vSourceECI = mEarth*vStationEF{i}; end end % useOmni if useGPS % Measurements from GPS %---------------------- if( useReceiver ) % Use GPSReceiver model %------------------------------------- GPSReceiver( 'update', struct( 'r',x(1:3),'v', x(4:6), 'jD', jD, 'clockError', x(7:8) ) ); gPSData = GPSReceiver( 'get output' ); if gPSData.nSatellites < nGPS nGPS = gPSData.nSatellites; end for i = 1:nGPS j = j + 1; range(j,1) = gPSData.range(i); rangeRate(j,1) = gPSData.rangeRate(i); d.hData(j).rSourceECI = gPSData.rGPS(:,i); d.hData(j).vSourceECI = gPSData.vGPS(:,i); d.r{j} = rGPS; end else % Skip GPS model and idealize GPS satellites as always visible [r, v] = GPSSatellite( jD, 'eci' ); for i = 1:nGPS j = j + 1; [range(j,1), rangeRate(j,1)] = RangeMeasurement( x(1:3), x(4:6), x(7:8), r(:,i), v(:,i) ); range(j,1) = range(j,1) + gps.range1Sigma*randn; rangeRate(j,1) = rangeRate(j,1) + gps.rangeRate1Sigma*randn; d.hData(j).rSourceECI = r(:,i); d.hData(j).vSourceECI = v(:,i); d.r{j} = rGPS; end end % useReceiver end % useGPS % External disturbance %--------------------- simData.aExt = 1e-7*[0;0;5] + 1e-6*[1;1;1]*sin(OrbRate(el(1))*t); % Update the plot array %---------------------- xPlot(:,k) = x; pPlot(:,k) = diag(d.p); xEPlot(:,k) = d.x; % Kalman Filter %-------------- d.secFromStart = t; d.time = jD; d.meas.z = [range;rangeRate]; d.dT = dT; d = CDKF45( d ); % Update the plot array %---------------------- rPlot(:,k) = [range;rangeRate]; resPlot(:,k) = d.residual; % Propagate %---------- switch d.propagator case 'RK45' [x, hLastT] = RK45( @FOrbKF, x, hLastT, dT, 0, tol, t, simData ); case 'RK4' x = RK4( @FOrbKF, x, dT, t, simData ); end t = t + dT; jD = jD + dT/86400; range = []; rangeRate = []; d.r = {}; d.hData = []; d.meas.z = []; j = 0; % Time control %------------- switch simulationAction case 'pause' pause simulationAction = ' '; case 'stop' return; case 'plot' break; end end t = ( 0:(nSim-1))*dT/60; dX = 1000*abs(xPlot(1:3,:) - xEPlot(1:3,:)); dV = 1000*abs(xPlot(4:6,:) - xEPlot(4:6,:)); P = sqrt(pPlot); yCL = char({'|dRx|, sqrt(pXX) (m)','|dRy|, sqrt(pYY) (m)','|dRz|, sqrt(pZZ) (m)',... '|dVx|, sqrt(pUU) (m/s)','|dVy|, sqrt(pVV) (m/s)','|dVz|, sqrt(pWW) (m/s)',... ' sqrt(b) (km)','sqrt(f) (km/s)'}); Plot2D( t, xEPlot(1:3,:), 'Time (min)', ['x (km)';'y (km)';'z (km)'], 'Estimated Position' ); Plot2D( t, [dX; 1000*P(1:3,:)], 'Time (min)', yCL(1:3,:),... 'Absolute Position Error and Covariance','lin',['[1 4]';'[2 5]';'[3 6]'] ); Plot2D( t, [dV; 1000*P(4:6,:)], 'Time (min)', yCL(4:6,:),... 'Absolute Velocity Error and Covariance','lin',['[1 4]';'[2 5]';'[3 6]'] ); Plot2D( t, abs([xPlot(7:8,:) - xEPlot(7:8,:)]), 'Time (min)', [' |bias| (km) ';'|drift| (km/s)'],'Clock Errors' ); Plot2D( t, P(7:8,:), 'Time (min)', yCL(7:8,:), 'Clock Sqrt Covariance' ); if size(xEPlot,1) == 17 Plot2D( t, xEPlot(9:17,:), 'Time (min)', ['B ';'w1';'w2'],'Disturbance states',... 'lin',['[1 4 7]';'[2 5 8]';'[3 6 9]']); Plot2D( t, P(9:17,:), 'Time (min)', ['Bias ';'Harm1';'Harm2'],... 'Disturbances Covariance','lin',['[1 4 7]';'[2 5 8]';'[3 6 9]']); end yL = {}; nL = {}; for k = 1:useOmni*nOmni yL{k} = ['Omni ' num2str(k)]; nL{k} = num2str(k); end for k = (useOmni*nOmni+1):(nMeas) yL{k} = ['GPS ' num2str(k-useOmni*nOmni)]; nL{k} = num2str(k-useOmni*nOmni); end Plot2D( t, rPlot(1:nMeas,:), 'Time (sec)', yL,'Range Measurements' ); Plot2D( t, rPlot(nMeas+1:end,:), 'Time (sec)', yL,'Range Rate Measurements' ); Plot2D( t, resPlot, 'Time (sec)', {nL{:} nL{:}},'Residuals' ); TimeGUI('close'); %--------------------------------------