Contents
3D lander simulation.
The spacecraft has 3-axis thruster control. Ideal attitude pointing
is assumed.
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.
Things to explore:
1. For the bilinear control vary the control acceleration (nAccel).
2. Try different starting altitudes.
3. Try different planets
Simulation time parameters
dT = 0.25;
Parameters
hStop = 0.0005;
uE = 320*9.806;
body = 'moon';
d = struct;
switch lower(body)
case 'moon'
rPlanet = Constant('equatorial radius moon');
muPlanet = Constant('mu moon');
h = 15;
tEnd = 7*60;
nAccel = 10;
massFuel = 25;
d.mass = 25;
gainVelocity = 2;
velocityThreshold = 0.001;
vMaxFrac = 0.2;
case 'enceladus'
rPlanet = 252.1;
muPlanet = 1.08022e20*Constant('newtonian constant of gravitation')/1e9;
h = 10;
tEnd = 10*60;
nAccel = 8;
massFuel = 8;
d.mass = 100;
gainVelocity = 0.5;
velocityThreshold = 0.001;
vMaxFrac = 0.2;
case 'mars'
rPlanet = Constant('equatorial radius mars');
muPlanet = Constant('mu mars');
h = 150;
nAccel = 7;
tEnd = 5*60;
massFuel = 1000;
d.mass = 200;
gainVelocity = 4;
velocityThreshold = 0.001;
vMaxFrac = 0.2;
end
nSim = floor(tEnd/dT);
d.inertia = Inertias( d.mass + massFuel, [1 1 1], 'box', 1 );
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 = 0.1;
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 );
d.hLanding = dBilinear.hLanding;
Simulation
d.mu = muPlanet;
d.fDist = [];
r = rPlanet + h;
u = sqrt(muPlanet/r);
x = [0;r;0;-u;0;0;massFuel];
xP = zeros(length(x)+3,nSim);
t = 0;
for k = 1:nSim
hAltimeter = Mag(x(1:3)) - rPlanet;
massFuel = x(7);
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;
xP(:,k) = [x;hAltimeter;dBilinear.throttle;dBilinear.mode];
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
d.mDot = -abs(Mag(d.forceECI))/uE;
x = RK4(@RHSPointMass,x,dT,t,d);
t = t + dT;
end
0.019025731913416 0.005556968767565 0.001111393753513
Touchdown! |v| = 0.0011 km/s
Plot the simulation results
xP = xP(:,1:k);
[t,tL] = TimeLabl((0:(k-1))*dT);
s1 = sprintf('%s Orbit State',body);
s2 = sprintf('%s Velocity, Altitude, and Throttle',body);
s3 = sprintf('%s Terminal Descent',body);
yL = {'x (km)','y (km)','z (km)','v_x (km)','v_y (km)','v_z (km)'};
Plot2D( t, xP( 1:6,:), tL, yL, s1 )
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);
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'})
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'})