Lunar Mission Demo

Simulate a mission from Earth orbit to lunar orbit. The spacecraft has 3 orthogonal reaction wheels and a single delta-v thruster. The mission plan does not perform the lunar insertion burn.

It uses the default values from RHSLunarMission for a 6U CubeSat. The dimensions are 30 x 20 x 10 cm.

Contents

%--------------------------------------------------------------------------
%   Copyright (c) 2016 Princeton Satellite Systems, Inc.
%   All rights reserved.
%--------------------------------------------------------------------------
%   Since 2016.1
%   2020.1 Fixed the lunar insertion burn and the lunar orbit plotting
%--------------------------------------------------------------------------

Constants

rMoon                       = 1738;
dayToSec                    = 86400;

User inputs

dateEncounter               = [2016 5 10 1 30 0]; % "Encounter" is passing into lunar sphere of influence
dT                          = 2;    % integration time step seconds
el0                         = [7000 0 0 0 0];
rLunarOrbit                 = 3000; % km
incLunarOrbit               = 1;
surfaceMagnificationFactor  = 10;   % For lunar terrain display
timeAdded                   = 36000; % sec added simulation time after intercept
useSphericalHarmonics       = 0;

Control setup

% Find transfer orbit to the moon
jDEncounter   = Date2JD( dateEncounter );
InterpolateState([],[],'bin2000.405');
if( HasOptimizationToolbox )
  [x0,el,~,jD0,jDP] = LunarTargeting( jDEncounter, el0, rLunarOrbit, incLunarOrbit, [], true );
else
  disp('LunarMission: Optimization toolbox not installed; using hard-coded values.')
  x0  = [-2.8408    6.3976         0   -0.0034    0.0099    0.0018]'*1e3;
  el  = [-5.2588    0.0010    0.0001    0.0041    0.0016    0.0088]*1e3;
  jD0 = 2.457514449298204e+06;
end

tEnd      = (jDP-jD0)*dayToSec + timeAdded;

% Get the default data structure
dC        = LunarMissionControl;

dC.dT     = dT;
dC        = LunarMissionControl('initialize',jD0,dC);
dRHS      = RHSLunarMission;

if( useSphericalHarmonics )
  dRHS.sphHarmMoon    = LoadSGM150( 'SGM150.geo' ); %#ok<*UNRCH>
  dRHS.sphHarmMoon.nN = 3;
  dRHS.sphHarmMoon.nM = 3;
end

% Set up the control data structure
dC.mass   = struct('mass',dRHS.mass,'inertia',dRHS.inertia,'cM',dRHS.surfData.cM);
dC.rWA    = dRHS.rWA;

% This command list is for an lunar orbit insertion
cList     = { jDP-1e3/dayToSec,...
                  'lunar orbit insertion prepare',...
                  struct('thrust',20,'massInitial',6, 'uE', 290*9.806,'body_vector',[1;0;0],'hLunarOrbit',200);...
                  +2,...
                  'align for lunar insertion',...
                  [];...
                  +1e3,...
                  'start main engine',...
                  struct('iD',1,'thrust',20)};

% Initial state setup
qECIToBody                  = [1;0;0;0];
omega                       = [0;0;0];  % rad/s
omegaRWA                    = [0;0;0];  % rad/s
accelBias                   = [0;0;0];  % km/s^2
gyroBias                    = [0;0;0];  % rad/s
massFuel                    = 3;        % kg
Your initial point x0 is not between bounds lb and ub; FMINCON
shifted x0 to strictly satisfy the bounds.

                                            First-order      Norm of
 Iter F-count            f(x)  Feasibility   optimality         step
    0       5    1.338059e+01    1.153e+04    1.441e+00
    1      19    1.200025e+01    1.039e+04    4.190e+00    3.551e-01
    2      28    1.055581e+01    4.551e+03    4.925e-03    3.816e-01
    3      34    1.055585e+01    4.484e+03    1.071e-02    5.354e-02
    4      39    1.057161e+01    2.404e+03    1.820e+00    9.663e-02
    5      44    1.055624e+01    3.164e+02    1.801e-02    2.845e-02
    6      49    1.055633e+01    1.124e+02    1.893e-02    1.812e-02
    7      54    1.055629e+01    4.419e-01    1.922e-02    1.105e-02
    8      60    1.055615e+01    1.429e-05    1.934e-02    4.267e-02
    9      87    1.055615e+01    3.289e-06    5.388e-03    1.547e-04
   10      94    1.055607e+01    2.399e-01    5.491e-03    2.592e-02
   11     111    1.055607e+01    4.802e-03    3.792e-03    1.876e-04
   12     132    1.055607e+01    7.692e-04    3.792e-03    7.693e-05
   13     138    1.055607e+01    8.022e-04    3.792e-03    1.663e-04
   14     154    1.055607e+01    7.678e-07    3.792e-03    2.404e-06
   15     168    1.055607e+01    3.671e-08    3.792e-03    5.258e-07
   16     181    1.055607e+01    6.672e-09    3.793e-03    2.301e-07
   17     195    1.055607e+01    3.693e-10    3.792e-03    5.033e-08
   18     209    1.055607e+01    9.595e-11    3.793e-03    1.101e-08
   19     222    1.055607e+01    7.776e-11    3.792e-03    4.816e-09
   20     235    1.055607e+01    8.868e-11    3.792e-03    2.107e-09
   21     249    1.055607e+01    4.275e-11    3.793e-03    4.609e-10
   22     262    1.055607e+01    2.638e-11    3.793e-03    2.017e-10
   23     275    1.055607e+01    5.002e-12    3.792e-03    8.823e-11

Optimization stopped because the relative changes in all elements of x are
less than options.StepTolerance = 1.000000e-10, and the relative maximum constraint
violation, 4.338970e-16, is less than options.ConstraintTolerance = 1.000000e-04.

Hyperbolic Lunar Elements
Radius of perilune      3000.00 km
Semi major axis         -456.07 km 
Inclination               57.30 deg
Longitude                251.32 deg
Perigee                   82.49 deg
Eccentricity               7.58 
Mean anomaly            6821.23 deg
Start JD               2457514.6975 day
Transfer Time                3.8650 days

Initialize the simulation model

% Initialize JPL Ephemerides to include the Sun, Earth and Moon
PlanetPosJPL( 'initialize', [0 3 10] );

nSim          = ceil(tEnd/dT);
dRHS.jD0      = jD0;
x             = [x0;qECIToBody;omega;massFuel;dRHS.power.batteryCapacity;...
                  accelBias;gyroBias;omegaRWA];

% This initializes the state and auxiliary output names
RHSLunarMission( x );

Run the simulation

t       = 0;
xP      = zeros(length(x),nSim);
[~, p]	= RHSLunarMission( x, t, dRHS );
pP      = zeros(length(p.auxNames),nSim);

% Globals for the time tracking GUI
global simulationAction
simulationAction = ' ';

for k = 1:nSim

  % Plot storage
  [~, p]      = RHSLunarMission( x, t, dRHS );
  q = x(7:10);
  xP(:,k)     = x;
  pP(:,k)     = p.aux;

  % The controller
  jD          = jD0 + t/dayToSec;
  dC.rMoon    = pP(21:23,k);
  dC.vMoon    = pP(24:26,k);
  [dC, dRHS]	= LunarMissionControl( 'update', jD, dC, dRHS, x, cList );

  % Propagate
  x           = RK4(@RHSLunarMission,x,dT,t,dRHS);
  t           = t + dT;

  switch simulationAction
    case 'pause'
      pause
      simulationAction = ' ';
    case 'stop'
      LunarMissionControl( 'terminate' );
      return;
    case 'plot'
      break;
  end

end
LunarMissionControl( 'terminate' );
jD  2457517.78528 lunar orbit insertion prepare
jD  2457517.78530 align for lunar insertion
jD  2457517.79687 start main engine

Plot the results

if k<nSim
  xP = xP(:,1:k);
  pP = pP(:,1:k);
  nSim = k;
end
tS      = (0:nSim-1)*dT;
jD      = jD0 + t/dayToSec; % in days

[t,tL]	= TimeLabl(tS);

% Plot the states
k = 1:3;
Plot2D(t,xP(k,:),tL,p.stateNames(k),'Position');          k = 4:6;
Plot2D(t,xP(k,:),tL,p.stateNames(k),'Velocity');          k = 7:10;
Plot2D(t,xP(k,:),tL,p.stateNames(k),'Quaternion');        k = 11:13;
Plot2D(t,xP(k,:),tL,p.stateNames(k),'Angular Velocity');  k = 14:15;
Plot2D(t,xP(k,:),tL,p.stateNames(k),'Fuel and Battery');  k = 16:18;
Plot2D(t,xP(k,:),tL,p.stateNames(k),'IMU Accel Bias');    k = 19:21;
Plot2D(t,xP(k,:),tL,p.stateNames(k),'IMU Gyro Bias');     k = 22:24;
Plot2D(t,xP(k,:),tL,p.stateNames(k),'Reaction Wheel Rates');

% Plot the auxiliary outputs
k = 4:6;
Plot2D(t,pP(k,:),tL,p.auxNames(k),'Thruster Force');        k = k+3;
Plot2D(t,pP(k,:),tL,p.auxNames(k),'Solar Torque');        k = 10:12;
Plot2D(t,pP(k,:),tL,p.auxNames(k),'Solar Force');         k = 13:14;
Plot2D(t,pP(k,:),tL,p.auxNames(k),'Power');               k = 21:23;

dR = xP(1:3,:) - pP(k,:);
dV = Mag(xP(4:6,:) - pP(24:26,:));
h  = Mag(dR) - rMoon;
yL = {'x (km)', 'y (km)', 'z (km)', 'h (km)' '|v| (km/s)'};
Plot2D(t,[dR;h;dV],tL,yL,'Moon Relative Position');

% Plot the trajectory for the Earth/Moon transfer
EarthMoon( xP(1:3,:), jD, [1, 1], pP(21:23,:) );

% Display from encounter time
jD    = jD0 + tS/dayToSec;
kB = find(jD>jDEncounter);

if ~isempty(kB)
  k = kB(1):nSim;
  dR    = dR(:,k);
  jD    = jD(1,k);
  uSun  = SunV1(jD(1));

  PlotLunarOrbit( dR, jD, uSun, pP(4:6,k), surfaceMagnificationFactor );
end
Figui;


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