Simulate ONS for elements of a lunar mission

This only simulates the orbital motion.

The right hand side can be referenced to either the Earth or the Moon.

There are five built-in test cases:

'gps orbit' Reference is the Earth horizon from GPS altitude 'earth orbit' Reference is the Earth horizon from equatorial LEO 'cis-lunar to moon' Switches from Earth horizon, to Earth center to Moon Center 'reentry' Experiences high disturbance forces 'lunar orbit' Reference is the lunar horizon

------------------------------------------------------------------------
See also ONSMessengerSimulation, ONSHelioSimulation, LunarLandingTRNSim
-----------------------------------------------------------------------

Contents

Copyright (c) 2021 Princeton Satellite Systems, Inc.
All rights reserved.
%--------------------------------------------------------------------------
%   Since version 2021.1
%--------------------------------------------------------------------------

Constants

rE        = Constant('equatorial radius earth');
rM        = Constant('equatorial radius moon');
secToDay  = 1/86400;

% Targets
moon      = 1;
earth     = 2;

% Get the default data structure for the dynamical model
dRHS      = RHSCisLunarMission;

Script control

massFuel	= 1000; % kg
dRHS.mD   = 1000; % kg dry mass
viewersOn = true; % The star camera viewer
printAll  = false; % Print plots to pdf files

% Names are 'reentry' 'earth orbit' 'cis-lunar to moon'  'lunar orbit'
% 'gps orbit'
simName  = 'reentry';

% Initialize the moon ephemeris
PlanetPosJPL( 'initialize', 10 )

% Initialize the state for different scenarios
% If you add a scenario you must specify a target below
switch simName
	case 'gps orbit'
    jD0       = Date2JD([2024 8 3 0 0 0]);
    dRHS.ref  = earth;
    [r,v]     = GPSSatellite(jD0);
    x         = [r(:,1);v(:,1);massFuel];
    dT        = 10;
    el        = RV2El(r(:,1),v(:,1));
    p         = Period(el(1));
    p         = 1000;
    tEnd      = p; % sec

	case 'earth orbit'
    x0        = 6700;
    dRHS.ref  = earth;
    x         = [x0;0;0;0;sqrt(Constant('mu earth')/x0);0;massFuel];
    dT        = 10;
    tEnd      = 8000; % sec
    jD0       = Date2JD([2024 8 3 0 0 0]);

	case 'cis-lunar to moon'
    r         = [ 6.8293e+03; 1.5366e+03;4.2943];
    v         = [ -2.1189;    9.4409;    4.2943];
    dRHS.ref  = earth;
    x         = [r;v;massFuel];
    dT        = 200;
    tEnd      = 1000*dT;
    jD0       = Date2JD([2024 8 3 12 0]); %

  case 'reentry'
    dRHS.ref  = earth;
    x         = [6500;0;0;0;7.5;0;massFuel];
    jD0       = Date2JD([2024 8 3 0 0 0]);
    dT        = 0.5;
    tEnd      = 600; % sec

  case 'lunar orbit'
    x0      	= rM + 100;
    dRHS.ref	= moon;
    x       	= [x0;0;0;0;sqrt(Constant('mu moon')/x0);0;massFuel];
    jD0      	= Date2JD([2024 8 3 0 0 0]);
    dT       	= 1;
    tEnd     	= 200; % sec

  otherwise
    error('%s is not a pre-defined simulation',simName);
end

% Set the Julian date for the dynamical model
dRHS.jD0 = jD0;

% Simulation steps
n     = ceil(tEnd/dT);

Setup data structures for the camera and measurements

dCam	= NavigationCamera;
dGPS  = MeasGPS;
dGS   = MeasRangeGroundStation;
dOM   = MeasStarAngleAndChord;

Add noise

dCam.camera.sigmaXY = 1;
dCam.camera.noise   = true;

Set up the displays

TimeDisplay('initialize','ONS Simulation',n);

if( viewersOn )
  hNav = StarCameraViewer('initialize','Navigation Camera',n); %#ok<*UNRCH>
end

% The time vector
t       = (0:n-1)*dT;

Setup Optical Navigation

dONS                = OpticalNavigation;
dONS.ukf.fData      = RHSUKFCisLunarMission;
dONS.ukf.fData.jD0  = dRHS.jD0;

r         = x(1:3);
v         = x(4:6);

% Set the target
switch simName
  case 'gps orbit'
    dONS.target         = earth;
    dONS.ukf.fData.ref  = earth;

  case 'earth orbit'
    dONS.target         = earth;
    dONS.ukf.fData.ref  = earth;

  case 'reentry'
    dONS.target         = earth;
    dONS.ukf.fData.ref  = earth;

  case 'cis-lunar to moon'
    dONS.target         = earth;
    dONS.ukf.fData.ref  = earth;

  case 'lunar orbit'
    dONS.target         = moon;
    dONS.ukf.fData.ref  = moon;

  otherwise
    error('%s does not have a specified target',simName);
end

% Initialize ONS
OpticalNavigation( 'initialize', dONS, r, v, dT );
meas.optical        = NavigationCamera( r, dCam );
dONS.t              = t(1);
dONS.useUKF         = false; % Otherwise it will use a static solution
dONS.ref            = dRHS.ref;

% These are for the UKF only
dONS.ukf.useOptical = false;
dONS.ukf.useState   = false;
dONS.ukf.usePos     = false;
dONS.ukf.m          = x(1:6);

% Plotting arrays
xP      = zeros(25,n);
target  = zeros(1,n);
type    = zeros(1,n);
nStars  = zeros(1,n);

Run the simulation

for k = 1:n

  % Time update
	TimeDisplay('update',k);

  % Determine if the spacecraft has hit the ground
  if( dRHS.ref == moon )
    h = Mag(x(1:3))-rM;
  else
    h = Mag(x(1:3))-rE;
  end

  % Get data for plotting
  [~,~,~,drag,acc] = RHSCisLunarMission(x,t(k),dRHS);

  [rMoon,~,vMoon] = PlanetPosJPL( 'update', jD0 + t(k)*secToDay );

  if( dRHS.ref == moon )
    dCam.xPlanet  = [[0;0;0] -rMoon];
    rMoon         = [0;0;0];
    vMoon         = [0;0;0];
  else
    dCam.xPlanet  = [rMoon [0;0;0]];
  end

  % Stop on landing
  if( h <= 0 )
    break;
  end

	% Find the camera position in the ECI frame
  if( dRHS.ref == earth )
    rCam = x(1:3);
    vCam = x(4:6);
  else
    rCam = dCam.xPlanet(:,1) - x(1:3);
    vCam = vMoon - x(4:6);
  end

  % Needed to point the camera
  dONS          = OpticalNavigation( 'get unit vector', dONS, rMoon, vMoon, rCam, vCam );

	% Get the camera output for use with optical measurements
  dCam.q        = U2Q(dONS.uC,[0;0;1]);
  dOM.cam       = NavigationCamera( rCam, dCam );
  dOM.type      = dONS.type;
  dOM.target    = dONS.target;
  dOM.ref       = dRHS.ref;
  dOM.uCamera   = dONS.uCamera;
  dOM.aBody1    = dONS.aBody1;
  dOM.aBody2    = dONS.aBody2;
  dOM.r1        = rMoon;
  dOM.v1        = vMoon;

  % Get measurements
  meas.jD0      = jD0 + t(k)*secToDay;
  meas.state    = x(1:6);
  meas.acc      = acc; % Non-gravitational spacecraft acceleration
  meas.optical  = MeasStarAngleAndChord( [rCam;vCam], dOM );
  meas.gps      = MeasGPS( x, dGPS );
  meas.gs       = MeasRangeGroundStation( x, dGS );

  % ONS
  dONS.cam      = dOM.cam;
  dONS.ref      = dRHS.ref;
  dONS.r1       = dOM.r1;
  dONS.v1       = dOM.v1;
  dONS.t        = t(k);
  dONS          = OpticalNavigation( 'update', dONS, meas, rMoon, vMoon, rCam, vCam );
  target(k)     = dONS.target;
  type(k)       = dONS.type;
  nStars(k)     = dONS.ukf.optical.nStars;

  % Display the camera view
  if( viewersOn )
    StarCameraViewer('update', dOM.cam, [], hNav, dCam, k);
  end

  % Store for plots
	xP(:,k)        = [x;rMoon;dRHS.thrust;dRHS.ref;drag;h;Mag(drag);dONS.x];

  % Propagate the state
  x              = RK4(@RHSCisLunarMission,x,dT,t(k),dRHS);
end

TimeDisplay('close');

Plotting

% Shorten the vectors if it hits the ground
j           = 1:k;
xP          = xP(:,j);
t           = t(j);
target      = target(j);
type        = type(j);
nStars      = nStars(j);

% Make earth and moon reference position
rEarth      = zeros(3,k);
rMoon       = zeros(3,k);
j           = find(xP(14,:) == moon );
rMoon(:,j)  = xP(1:3,j);
rEarth(:,j) = xP(8:10,j) - rMoon(:,j);

j           = find(xP(14,:) == earth );
rEarth(:,j) = xP(1:3,j);
rMoon(:,j)	= xP(8:10,j) + rEarth(:,j);

% Earth/Moon plot
EarthMoon( xP(1:3,:), jD0 + t/86400, [1 1], xP(8:10,:) );

% Plot
[t,tL]      = TimeLabl(t);
yL          = {'x (km)' 'y (km)' 'z (km)'};
yD          = {'a_x (km/s^2)' 'a_y (km/s^2)' 'a_z (km/s^2)'  'H (km)' '|a| (km/s^2)'};

Plot2D(t,rEarth,tL,yL,'Earth Referenced Position');
Plot2D(t,rMoon, tL,yL,'Moon Referenced Position');
Plot2D(t,xP(15:19,:),tL,yD,'Drag acceleration');

yS          = {'x (km)' 'y (km)' 'z (km)' 'v_x (km/s)' 'v_y (km/s)' 'v_z (km/s)'};

Plot2D(t,xP(1:6,:),tL,yS,'State');
Plot2D(t,xP(20:25,:),tL,yS,'Navigation Solution');
Plot2D(t,xP(20:25,:) - xP(1:6,:),tL,yS,'Navigation Error');

NewFig('Targeting')
subplot(3,1,1);
h = plot(t,target);
set(h,'linewidth',2);
grid on
XLabelS(tL);
YLabelS('Target')
set(gca,'ytick',[1 2],'yticklabel',{'Moon' 'Earth'});

subplot(3,1,2);
h = plot(t,type);
set(h,'linewidth',2);
grid on
XLabelS(tL);
YLabelS('Measurement Type')
set(gca,'ytick',[1 2],'yticklabel',{'Horizon' 'Center'});

subplot(3,1,3);
h = plot(t,nStars);
set(h,'linewidth',2);
grid on
XLabelS(tL);
YLabelS('Stars')

Figui

if( printAll )
  n = get(gcf,'number');
  for k = 1:n
    PrintFig(1,4,k,sprintf('%s%d',simName,k));
  end
end


%--------------------------------------