3D lander simulation at Pluto.

The spacecraft has 3-axis thruster control. Ideal attitude pointing is assumed. You must run PlutoLanderCAD first. An altimeter gives the altitude. The planet is assumed to be a perfect sphere.

This demo demonstrates the bilinear tangent law for descent from a circular equatorial orbit.

See also Constant, Plot2D, TimeLabl, Inertias, RK4, Dot, Mag, Unit, RHSPointMass, LandingControlBilinear

Contents

%--------------------------------------------------------------------------
%   Copyright (c) 2013-2014 Princeton Satellite Systems, Inc.
%   All rights reserved.
%--------------------------------------------------------------------------
%   Since Version 2015.1
%--------------------------------------------------------------------------

Simulation time parameters

dT              = 0.25; % sec
hStop           = 0.0005; % km
uE              = 285*9.806; % Exhaust velocity (m/s)

% Select the planet or moon
body                = 'Pluto';%
rPlanet             = Constant('equatorial radius pluto'); % km
muPlanet            = Constant('mu pluto');
h                   = 15;  % Altitude of initial orbit
tEnd                = 10*60; % sec
nAccel              = 7; % Engine acceleration is this multiple of gravity
massFuel            = 80;
gainVelocity        = 6;
velocityThreshold   = 0.001;
vMaxFrac            = 0.2;
hSwitch             = 0.3;

% Simulation time steps
nSim            = floor(tEnd/dT);

% Spacecraft inertia at start
d = struct;
d.mass    = 150; % kg
d.inertia = Inertias( d.mass + massFuel, [1 1 1], 'box', 1 ); % kg-m^2

Set up the bilinear controller

dBilinear = struct;
dBilinear.mu                        = muPlanet;
dBilinear.mass                      = d.mass + massFuel;
dBilinear.rP                        = rPlanet;
dBilinear.h                         = h;
dBilinear.nG                        = nAccel;
dBilinear.dT                        = dT;
dBilinear.inertia                   = d.inertia;
dBilinear.hLanding                  = hSwitch; % The altitude at which to switch to landing mode
dBilinear.throttle                  = 1;
dBilinear.landing.gainVelocity      = gainVelocity;
dBilinear.landing.velocityThreshold = velocityThreshold;
dBilinear.landing.vMaxFrac          = vMaxFrac;
dBilinear.landing.hTouchdown        = 0.001;
dBilinear.bypassACS                 = 1;
dBilinear                           = LandingControlBilinear( 'initialize', dBilinear );

% Determine initial s/c orientation (align s/c with initial beta angle)
d.hLanding                          = dBilinear.hLanding;

Simulation

% Gravity
d.mu = muPlanet; % km^3/s^2

% Disturbances
d.fDist = []; % The landing force function

% State vector [r;v;mass fuel]
% Assume a circular orbit to start
r = rPlanet + h;
u = sqrt(muPlanet/r);
x = [0;r;0;-u;0;0;massFuel];

% Initialize state vector array for plotting
xP = zeros(length(x)+3,nSim);

% Initialize time
t = 0;

% Simulate until the lander reaches the surface (within 1 mm)
for k = 1:nSim

	% Sensing - determine altitude
	hAltimeter            = Mag(x(1:3)) - rPlanet;
  massFuel              = x(7);

	% Controller
	dBilinear.mass       	= d.mass + massFuel;
	dBilinear.r         	= x(1:3);
	dBilinear.v          	= x(4:6);
	dBilinear.hAltimeter	= hAltimeter;
	dBilinear.t          	= t;
  dBilinear.pointingTol = 0.001;
	dBilinear            	= LandingControlBilinear('update',dBilinear);
	d.forceECI           	= dBilinear.forceECI;

	% Store for plotting
	xP(:,k)               = [x;hAltimeter;dBilinear.throttle;dBilinear.mode];

  % Stop when we reach the surface or run out of fuel
	if( dBilinear.landing.mode == 4 )
    fprintf(1,'Touchdown! |v| = %12.4f km/s\n',Mag(x(4:6)));
    break
  end

	if( hAltimeter <= hStop )
    fprintf(1,'Terminating due to hitting the ground. |v| = %12.4f km/s\n',Mag(x(4:6)));
    break
  end

  if( massFuel  <= 0 )
    fprintf(1,'Terminating due to running out of fuel. |v| = %12.4f km/s h = $12.4 km\n',Mag(x(4:6)),h);
    break
  end

	% Fuel consumption
	d.mDot	= -abs(Mag(d.forceECI))/uE;

	% Integrate
	x       = RK4(@RHSPointMass,x,dT,t,d);

	% Increment time
	t       = t + dT;
end
        0.0762979220578472       0.00708208803946932       0.00141641760789386
Touchdown! |v| =       0.0004 km/s

Plot the simulation results

xP = xP(:,1:k);

% Time label
[t,tL] = TimeLabl((0:(k-1))*dT);

% Plot Titles
s1 = sprintf('%s Orbit State',body);
s2 = sprintf('%s Velocity, Altitude, and Throttle',body);
s3 = sprintf('%s Terminal Descent',body);

% Plot position in ECI frame
yL = {'x (km)','y (km)','z (km)','v_x (km)','v_y (km)','v_z (km)'};
Plot2D( t, xP(  1:6,:), tL, yL, s1 )

% Summary plot
yL = {'|v| (km/s)' ,'h (km)', 'Throttle' 'Mode' , 'Fuel Mass (kg)'};
Plot2D( t, [Mag(xP(4:6,:));xP([8 9 10 7],:)], tL, yL, s2);

% Velocity plot
uV = Unit(xP(1:3,:));
vV = Dot(uV,xP(4:6,:));
vH = Mag(xP(4:6,:) - uV.*[vV;vV;vV]);

s2 = sprintf('%s Velocity,Plot',body);

Plot2D( t, [vV;vH;xP(10,:)], tL, {'Vertical Velocity (km/s)' 'Horizontal Velocity (km/s)' 'Mode'},s2)
set(gca,'YTick',[0 1 2 3 4],'YTickMode','manual',...
    'YTickLabel',{'Bilinear' 'Vertical' 'Velocity' 'Terminal' 'Touchdown'})

% Generate a terminal maneuvering plot
k = find(xP(10,:) > 0 );
vV = vV(k);
vH = vH(k);
xP = xP(8:10,k);
t  = t(k);

Plot2D( t, [vV;vH;xP], tL, {'Vertical Velocity (km/s)' 'Horizontal Velocity (km/s)' 'Altitude (km)' 'Throttle' 'Mode'},s3)
set(gca,'YTick',[0 1 2 3 4],'YTickMode','manual',...
    'YTickLabel',{'Bilinear' 'Vertical' 'Velocity' 'Terminal' 'Touchdown'})

%--------------------------------------
% PSS internal file version information
%--------------------------------------