You are on page 1of 12

Gain Scheduled Control for Entry, Descent, and Landing

Manan S. Gandhi∗

In this report, we review the effects of atmospheric modeling and initial condition uncertainty
for non-planar equations of motion for hypersonic planetary entry. The simulation is validated
in both the exoatmospheric region with a circular orbit, and in the atmospheric phase with a
gliding entry and a skipping entry. The two atmosphere models compared are an exponential
atmosphere and the 1976 Standard Atmosphere for altitudes less than 90 km and 1962 Standard
Atmosphere for altitudes greater than 90 km. The uncertainty in initial conditions is mitigated
utilizing a gain scheduled Linear Quadratic Regulator (LQR), which shows that the terminal
position dispersion can be greatly reduced given an appropriate distance metric to the desired
target and cost function tuning. The developed control scheme induces high bandwidth control,
which is undesirable, so some mitigations for future work are discussed.

I. Nomenclature

𝑉 = Velocity
𝛾 = flight path angle
ℎ = altitude
𝜓 = heading
𝜃 = longitude
𝜙 = latitude
𝜎 = roll angle
𝐿
𝐷 = lift to drag ratio
𝑄 = State cost matrix
𝑅 = Control cost matrix
Exp Atm = Exponential Atmosphere
Std Atm = Standard Atmosphere
OL = Open Loop
CL = Closed Loop
FPA = flight path angle

II. Introduction
n this report, we investigate the effects of atmospheric fidelity and initial condition uncertainty for the control of
I two entry vehicles. As case studies, we will review the Space Shuttle entry mission STS-13 [1], and the Apollo entry
mission APOLLO-4 [2]. The STS-13 mission was chosen as a baseline descent problem, which, given the mission
data, did not exhibit an exoatmospheric phase. The APOLLO-4 mission was chosen due to the preliminary mission
trajectories provided in literature [2]. In [2], a skipping entry is generated, and in this work we aim to both qualitatively
and quantitatively compare the fidelity of our simulation to this mission, which does involve an exo-atmospheric phase.
Additionally, the success of an entry, descent, and landing mission is highly dependent on the entry corridor, and we will
investigate the trajectory dispersion created by uncertainty in the initial altitude and flight path angle. This uncertainty
will be handled through feedback control.
By choosing to implement a closed-loop feedback controller for this project, we will have to deal with controllability
issues for the system at various stages of the trajectory, due to the nature of available actuation on the vehicle.
Controllability is lost when the magnitude of aerodynamic forces generated by control surfaces is neglible with respect
to the other forces on the vehicle. Additionally, this system is underactuated, meaning that the number of states (6) is
greater than the number of controls (2). The choice of controller for this system was the Linear Quadratic Regulator
∗ Ph.D Candidate, Georgia Institute of Technology

1
(LQR). There are segments of the trajectory where a stabilizing controller cannot be solved given our quadratic cost, and
the algebriac ricatti equations (ARE) do not return a stabilizing solution [3]. In this work we will attempt to address
these controllablility issues and demonstrate an improvement in terminal position error between the uncontrolled and
controlled systems undergoing initial condition uncertainty for both atmospheric models.

III. Approach
This software environment is based on three primary components. The first component is the non-planar equations
of motion, which were derived in [4]. The state variables for these equations of motion are velocity 𝑉, given in 𝑚𝑠 , flight
path angle 𝛾 given in 𝑟𝑎𝑑, altitude ℎ in 𝑚, heading angle 𝜓, longitude 𝜃, and latitude 𝜙, all given in 𝑟𝑎𝑑. Note that the
𝐿
heading angle was measured from east. The controls of the system were chosen to be roll angle 𝜎 and lift drag ratio 𝐷 .
The justification for these choices is discussed in Section III.A. The nonlinear equations of motion are verified in the
exoatmospheric portion of the state space by simulating a circular orbit above atmospheric interface atlitude.
The second component of the software environment is the atmospheric model. The initial atmospheric model is
the exponential atmosphere, which is then compared to a second atmospheric model defined by the 1976 Standard
Atmosphere [5] for all altitudes below 90 km. Above 90 km, the 1962 Standard Atmosphere [6] was utilized. This
comparison of atmospheric models was developed to demonstrate easy integration of alternative atmospheric models in
this simulation environment. Additionally, we wanted to investigate the differences in trajectories when the controller
utilizes one atmospheric model over another.
The final component of the software simulation is the control algorithm. This work implemented two basic control
algorithms, the first being an open-loop constant guidance controller and the second being a gain scheduled Linear
Quadratic Regulator (LQR) controller [7]. The open-loops constant guidance controller represents the baseline for
our system, the simulation of an entry, where the system is flying at a “trim” control for the duration of flight. The
closed-loop controller utilizes feedback to guide the trajectory to the design landing point, and mitigate the effect of
uncertainty.

A. Control Design
Given the equations of motion, and the fact that we were modeling unpowered entries into the atmosphere, the
𝐿
control variables were chosen to be the roll angle 𝜎 of the vehicle, and the lift drag ration 𝐷 of the vehicle. We justify
this choice since the roll angle can be modulated by the control surfaces of the aircraft, assuming a perfect underlying
controller. Additionally, the lift drag ratio of these entry vehicles can be modeled as proportional to the angle of attack
𝐿
𝛼 [cite datatext]. Thus we assume that 𝐷 can be controlled within the bounds defined by the system, which would
normally be done by modulating the angle of attack of the system.
Since we have a nonlinear system, the first step was to linearize the system, see Section VI.A. The state and control
jacobians of the dynamics were derived using Mathematica. The nonlinear system is then linearized about a given
trajectory. The state cost matrix 𝑄 and the control cost matrix 𝑅 were tuned by hand for the STS-13 mission to drive
the system toward along the given trajectory and then toward a desired target point, (for this mission is was Edwards
Airforce Base). The desired heading 𝜓 for the system was computed utilizing the error vector between the current
longitude 𝜃 and latitude 𝜙, and the desired longitude 𝜃 des and latitude 𝜙des , see Section VI.B. When computing the
control gains along our given trajectory, we utilized a constant quadratic control cost and attempted to solve the ARE at
each timestep. The solution was computed from the final point of the trajectory to the initial point, and in the event
where the solver failed to generate a stabilizing solution of the ARE, the gains of the previous timestep were repeated
Section VI.C. During simulation the appropriate gain is selected via the minimum distance of the current state to the
nominal trajectory, see Section VI.D.

IV. Results and Discussion


We will split the discussion between the verification of the code utilizing STS-13 and APOLLO-4, and then assessing
the mitigation of uncertainty via closed loop control.

A. Code Verification
The first comparison for code verification can be seen in Figure 1. In Figure 1a, we see the vehicle in a circular orbit
with initial conditions 𝑉 = 7416 𝑚𝑠 , 𝛾 = 0◦ , ℎ = 8.69𝑒5𝑚, and 𝜓 = 59.723◦ . The ground track is consistent with what

2
one would expect from the keplerian equations of motion. Figures 1b and 1c are shown for comparison for entry ground
tracks, while their comparison to higher fidelity data is shown in Figure 2 for the STS-13 mission and in Figure 3 for
the APOLLO-4 mission. STS-13 was simulated with initial conditions 𝑉 = 7397.19 𝑚𝑠 , 𝛾 = −2.036◦ , ℎ = 213241𝑚,
and 𝜓 = 30.277◦ . APOLLO-4 was simulated with initial conditions 𝑉 = 11074.30 𝑚𝑠 , 𝛾 = −7.350◦ , ℎ = 12190𝑚, and
𝜓 = 23.51◦ . We can see in Figure 2a that the simulation matches the ground truth up to about 80 kilometers, then
deviates slightly as atmospheric effects take over. The time at which this happens is approximately 600 seconds after
entry, and in Figure 2b we can see the velocity profile exhibiting similar behavior. In the atmospheric sections the
deceleration appears to be under estimated, as the velocity and resultant altitudes are larger. The overall velocity and
altitude profiles in Figure 3c are qualitatively close. A similar qualitative story can be see in the APOLLO-4 comparison.
In this case the flight time is smaller than the higher fidelity trajectory in Figure 1c by approximately 300 seconds. The
velocity profile in Figure 3a shows the same shape, but the plateau in the center of trajectory has a lower magnitude
by about 1000 𝑓𝑠𝑡 . The flight path angle comparison is similar in both shape and magnitude, see Figure 3b. From
the validation data, it appears that for shallow flight path angles, the simulator underestimates aerodynamic forces,
demonstrating less aerodynamic drag, while for sharper flight path angles and higher velocities, the drag forces are over
estimated. Thiscould explain the overshoot in ground track for the STS-13 mission, and the undershoot in groundtrack
for the APOLLO-4 mission. Note, the APOLLO-4 mission only shows entry to parachute deploy, not the full landing
sequence.

50 50 50

0 0 0

−50 −50 −50

−150 −100 −50 0 50 100 150 −150 −100 −50 0 50 100 150 −150 −100 −50 0 50 100 150

(a) STS-13 Circular Orbit Groundtrack (b) STS-13 Entry Groundtrack (c) APOLLO-4 Entry Groundtrack

Fig. 1 Ground track plots for STS-13 and APOLLO. The entry groundtrack shown in red utilizes the 1976
Standard Atmosphere model. The green star is the landing target.

True True True


200 Exp 7 Exp 200 Exp
Std Std Std
6
150 150
5
Altitude (km)
Altitude (km)

Velocity ( kfs t )

4
100 100
3

50 2 50

0 0 0

0 500 1000 1500 2000 0 500 1000 1500 2000 0 1 2 3 4 5 6 7


Time (s) Time (s) Velocity ( km
s )

(a) STS-13 Altitude vs. Time. (b) STS-13 Velocity vs. Time. (c) STS-13 Velocity vs. Altitude.

Fig. 2 STS-13 plots with Ground Truth (black), Exponential Atmosphere (blue), and Standard Atmosphere
(red).

3
Exp 0 Exp
35
Std Std
30 −10

−20

Flight Path Angle (◦ )


25
Velocity ( kfs t )

−30
20
−40
15
−50
10
−60
5
−70

0 −80
0 100 200 300 400 500 600 700 0 100 200 300 400 500 600 700
Time (s) Time (s)
(c) APOLLO-4 Ground Truth FPA and
(a) APOLLO-4 Velocity vs. Time. (b) APOLLO-4 FPA vs. Time. Velocity [2].

Fig. 3 APOLLO-4 plots with, Exponential Atmosphere (blue), and Standard Atmosphere (red) compared
against ground truth plots from [2].

B. Atmosphere Models and Control under Uncertainty


𝐿
The control limits for roll 𝜎 were (-90,90), while the control limits for 𝐷 were (0,1.07). 1.07 was the nominal lift to
drag ratio utilized for the open loop simulations. Additionally, the uncertainty in initial conditions were a Gaussian
with standard deviation 0.05◦ in 𝛾 and a Gaussian with standard deviation 5000𝑚 in ℎ. The Monte Carlo simulations
were run with a standardized seed between the uncontrolled and controlled systems with 50 samples each. For the
LQR controller, the parameters are 𝑄 = 𝑑𝑖𝑎𝑔(2, 1, 2, 1𝑒5, 20, 20) and 𝑅 = 𝑑𝑖𝑎𝑔(1𝑒4, 1𝑒4). Initially, I tried to focus
the tuning on the velocity, altitude, and longitude and latitude error, however, this did not prove to be fruitful when
analyzing the ground tracks and velocity profiles. Next, the magnitude of 𝑅 was increased to the point where the new
gains 𝐾 did not saturate the control limits. The resultant gains that were applied show that, for this specific control
problem, the primary driver for mitigating uncertainty was correcting the desired heading such that the down range and
cross range approximately reached the target. A similar example was also run with the 𝑄 and 𝑅 matries scaled so that
the 𝑅 matrix was identity, and indeed similar results were obtained.

Atmospheric Model Comparison


In Figure 4 we can see the slight difference between the exponential atmosphere and the standard atmosphere models.
The differences are more apparent after the exoatmospheric section of the APOLLO-4 trajectory. Figure 5 we can see
the effects on the closed loop control.

120 Exp 400 Exp


Std Std
350
100
300
80
Altitude (km)

Altitude (kf t)

250

60 200

150
40
100
20
50

0 0
0 2 4 6 8 10 0 100 200 300 400 500 600 700
Velocity ( km
s ) Time (s)

(a) APOLLO-4 Altitude versus Velocity (b) APOLLO-4 Altitude versus Time

Fig. 4 APOLLO-4 State with varying atmosphere models.

4
50 50

45 45

40 40

35 35

30 30

25 25
−125 −120 −115 −110 −105 −100 −125 −120 −115 −110 −105 −100

(a) STS-13 Closed Loop Terminal Position Comparison with (b) STS-13 Closed Loop Terminal Position Comparison with
Exponential Atmosphere Model. 1976 and 1962 Standard Atmosphere Model.

Fig. 5 STS-13 Trajectory Dispersion with varying atmosphere models.

Ground Track Comparison


We can qualitatively analyze the results thorough the trajectory dispersion in Figure 6 and quantitatively see the
effect of the control from Table 1. We can clearly see from Figure 6b that the trajectory dispersion is far tighter with the
closed loop control and the magnitude of error from the target point is much lower than the open loop controller Table 1.
Interestingly, the quantitative data shows that the simulation with the exponential atmosphere model has better error
than the standard atmosphere, but this could be a result of the larger nonlinearities of the Standard Atmosphere model
affecting the control.

50 50

45 45

40 40

35 35

30 30

25 25
−125 −120 −115 −110 −105 −100 −125 −120 −115 −110 −105 −100

(a) STS-13 Open loop control under initial condition uncer- (b) STS-13 Closed loop control under initial condition uncer-
tainty. tainty.

Fig. 6 STS-13 terminal position comparison. Blue trajectories are controlled, the green trajectories are
uncontrolled. The red star is the desired terminal position at Edwards Airforce Base. Standard Atmosphere.

5
Table 1 Ground track relative error with respect to latitude and longitude ( ◦ )

Mean Std Dev


Exp Atm OL 10.144 6.322
CL 6.286 2.320
Std Atm OL 10.742 6.981
CL 7.133 2.691

Sampled Trajectories
We can further see the trajectory dispersion when comparing the velocity and flight path angle trajectories. The
uncontrolled trajectories orient into a dive later than the controlled trajectories, Figure 7, and the velocities have a wider
variance.

7 0

6
Flight Path Angle (◦ ) −20
5
s )
Velocity ( km

4 −40

3
−60
2

1 −80

0
0 500 1000 1500 2000 2500 0 500 1000 1500 2000 2500
Time (s) Time (s)

(a) STS-13 Open loop control under initial condition uncer- (b) STS-13 Closed loop control under initial condition uncer-
tainty. tainty.

Fig. 7 STS-13 Velocity and FPA distribution. Blue samples are controlled, while green samples are uncontrolled.
Standard Atmosphere.

Sampled Controls
We can see a key weakness in the current control scheme which relies on high bandwidth control. The commanded
roll trajectories and commanded lift drag ratios can oscillate between the minimum and maximum values, Figure 8.
This is unrealistic and undesirable behavior from a controller, but a behavior that can be mitigated with appropriate
tuning on the control cost (increasing the control cost) and adding dynamics to the actuators as previously proposed.

6
75 1.0

50
0.8

25
Roll Angle (◦ )

0.6
0

D
L
−25 0.4

−50
0.2

−75
0.0
0 250 500 750 1000 1250 1500 1750 2000 0 250 500 750 1000 1250 1500 1750 2000
Time (s) Time (s)

(a) STS-13 Open loop control under initial condition uncer- (b) STS-13 Closed loop control under initial condition uncer-
tainty. tainty.

Fig. 8 STS-13 Control distribution for each sample.

V. Conclusions
To review, we have developed a computer simulation for running Monte Carlo simulations on controlled entry
vehicles with two atmospheric models. We saw in the comparison against ground truth data that the simulations are
accurate for exoatmospheric keplerian motion, but can over or underestimate aerodynamic effects during large flight
path angles and velocities. The effect between using a standard atmosphere model and exponential atmosphere model
shows up in two ways, one in terms of the flight duration of the system, the longer the flight time, the more differences
can emerge and two in the computation of the control of the system. We see that utilizing the developed gain scheduling
controller, uncertainty in the initial flight path angle and the initial altitude can be mitigated. Issues with controllability
of the system limit what kinds of uncertainties can be mitigated, and computation of a gain schedule can be problematic
when the system is not controllable. Overall, this is a promising step towards the utilization of dynamic programming for
entry, descent, and landing, since dynamic programming algorithms which solve for the value function can provide local
feedback gains to mitigate uncertainty while optimizing the trajectory. For optimal cost design, we discoved that, for
this set of problems, a key factor was the error in desired heading when attempting to land at a specific target. In future
work, it would also be important to factor in constraints of heating rate and maximum deceleration for a given trajectory.

VI. Appendix: Source Code Snippets


The full source code can be found at https://github.com/mgandhi635/AE-6355/tree/develop/Project.

A. Equations of Motion and Jacobians


def non_planar_eom (t: nd , state : nd , control : nd , params : EntryVehicleParams ,
exp_atmosphere : bool = True ,
control_gain = None , x_traj = None):
"""
The state vector is speed , flight path angle , altitude , heading , longitude , latitude
The control vector is bank angle , thrust force , thrust angle from flight path
: param t:
: param state :
: param control :
: param params :
: return :
"""
V = state [0]
gamma = state [1]
h = state [2] # The altitude is in meters

7
heading = state [3]
longitude = state [4]
latitude = state [5]

T = control [0]
epsilon = control [1]
sigma = control [2]
ld_ratio = control [3]

if control_gain is not None:


control_data = compute_control (state , control , x_traj , control_gain , params )
T = control_data [0]
epsilon = control_data [1]
sigma = control_data [2]
ld_ratio = control_data [3]

r = h + params . radius_planet

g = compute_gravity_from_altitude (h, params )


if exp_atmosphere :
rho = compute_density_from_altitude (h, params )
else:
rho = compute_density_std_atmosphere (h)

dv1 = T * cos( epsilon ) / params .mass


dv2 = -rho * V ** 2 / (2 * params . ballistic_coeff )
dv3 = -g * sin( gamma )
dv4 = params . omega_planet ** 2 * r * cos( latitude ) * \
(sin( gamma ) * cos( latitude ) - cos( gamma ) * sin( latitude ) * sin( heading ))

dvdt = dv1 + dv2 + dv3 + dv4

dg1 = T * sin( epsilon ) / (V * params .mass) * cos( sigma )


dg2 = V * cos( gamma ) / r
dg3 = rho * V / (2 * params . ballistic_coeff ) * ld_ratio * cos( sigma )
dg4 = -g * cos( gamma ) / V
dg5 = 2 * params . omega_planet * cos( latitude ) * cos( heading )
dg6 = params . omega_planet ** 2 * r / V * cos( latitude )
dg7 = cos( gamma ) * cos( latitude ) + sin( gamma ) * sin( latitude ) * sin( heading )

dgdt = dg1 + dg2 + dg3 + dg4 + dg5 + dg6 * dg7

dp1 = T * sin( epsilon ) * sin( sigma ) / (V * params .mass * cos( gamma ))


dp2 = rho * V / (2 * params . ballistic_coeff ) * ld_ratio * sin( sigma ) / cos( gamma )
dp3 = -V * cos( gamma ) * cos( heading ) * tan( latitude ) / r
dp4 = 2 * params . omega_planet * (tan( gamma ) * cos( latitude ) * sin( heading ) - sin( latitude ))
dp5 = - params . omega_planet ** 2 * r / (V * cos( gamma )) * sin( latitude ) * cos( latitude ) * cos(
heading )

dpdt = dp1 + dp2 + dp3 + dp4 + dp5

dhdt = V * sin( gamma )

dthetadt = V * cos( gamma ) * cos( heading ) / (r * cos( latitude ))

dphidt = V * cos( gamma ) * sin( heading ) / r

state_dot = np. array ([dvdt , dgdt , dhdt , dpdt , dthetadt , dphidt ])

return state_dot

def altitude_zero_event (t, state , *args):


h = state [2] # The altitude is in meters
return h

altitude_zero_event . terminal = True

8
altitude_zero_event . direction = -1

def altitude_exoatmosphere_event (t: float , state : nd , params : EntryVehicleParams ):


x = state [2] - params . atmosphere_altitude_planet # The altitude is in meters
return x

def nonplanar_eom_jacobians (t, state : nd , control : nd , params : EntryVehicleParams , exp_atmosphere


: bool = True):
"""
{, {0},
}
: param t:
: param state :
: param control :
: return :
"""
V = state [0]
gamma = state [1]
h = state [2] # The altitude is in meters
heading = state [3]
longitude = state [4]
latitude = state [5]

T = control [0]
epsilon = control [1]
sigma = control [2]
ldratio = control [3]

R = params . radius_planet
omega = params . omega_planet
beta = params . ballistic_coeff
m = params .mass

g = compute_gravity_from_altitude (h, params )


if exp_atmosphere :
rho = compute_density_from_altitude (h, params )
else:
rho = compute_density_std_atmosphere (h)

f1 = np. array ([[-1 * V * beta ** (-1) * rho],


[(-1 * g * cos( gamma ) + (h + R) * omega ** 2 * cos( latitude ) * (
cos( gamma ) * cos( latitude ) + sin( gamma ) * sin( latitude ) * sin( heading )
))],
[-1 * (h + R) * omega ** 2 * cos( gamma ) * cos( latitude ) * cos( heading ) * sin(
latitude )],
[ omega ** 2 * cos( latitude ) * (
cos( latitude ) * sin( gamma ) + -1 * cos( gamma ) * sin( latitude ) * sin(
heading ))],
[0],
[((h + R) * omega ** 2 * cos( latitude ) * (
-1 * sin( gamma ) * sin( latitude ) + -1 * cos( gamma ) * cos( latitude ) *
sin( heading )) + -1 * (h + R) * omega ** 2 * sin( latitude ) * (
cos( latitude ) * sin( gamma ) + -1 * cos( gamma ) * sin( latitude ) * sin(
heading )))]])

f2 = np. array ( [ [( ( ( h + R ) ) ** ( -1 ) * cos( gamma ) + ( g * ( V


) ** ( -2 ) * cos( gamma ) + ( 1/2 * ldratio * ( beta ) ** ( -1 ) * rho *
cos( sigma ) + ( -1 * ( m ) ** ( -1 ) * T * ( V ) ** ( -2 ) * cos( sigma
) * sin( epsilon ) + -1 * ( h + R ) * ( V ) ** ( -2 ) * ( omega ) ** (
2 ) * cos( latitude ) * ( cos( gamma ) * cos( latitude ) + sin( gamma ) *
sin( latitude ) * sin( heading ) ) ) ) ) ),] ,
[( g * ( V ) ** ( -1 )
* sin( gamma ) + ( -1 * ( ( h + R ) ) ** ( -1 ) * V * sin( gamma ) + (
h + R ) * ( V ) ** ( -1 ) * ( omega ) ** ( 2 ) * cos( latitude ) * ( -1 *
cos( latitude ) * sin( gamma ) + cos( gamma ) * sin( latitude ) * sin(
heading ) ) ) ),] ,

9
[( ( h + R ) * ( V ) ** ( -1 ) * ( omega ) ** ( 2
) * cos( latitude ) * cos( heading ) * sin( gamma ) * sin( latitude ) + -2
*
omega * cos( latitude ) * sin( heading ) ),] ,
[( -1 * ( ( h + R )
) ** ( -2 ) * V * cos( gamma ) + ( V ) ** ( -1 ) * ( omega ) ** ( 2 ) *
cos( latitude ) * ( cos( gamma ) * cos( latitude ) + sin( gamma ) * sin(
latitude ) * sin( heading ) ) ),] ,
[0,] ,
[( -2 * omega *
cos( heading ) * sin( latitude ) + ( ( h + R ) * ( V ) ** ( -1 ) * ( omega
) ** ( 2 ) * cos( latitude ) * ( -1 * cos( gamma ) * sin( latitude ) + cos(
latitude ) * sin( gamma ) * sin( heading ) ) + -1 * ( h + R ) * ( V ) ** ( -
1
) * ( omega ) ** ( 2 ) * sin( latitude ) * ( cos( gamma ) * cos( latitude )
+ sin( gamma ) * sin( latitude ) * sin( heading ) ) ) ),]] )

f4 = np. array ( [ [( 1/2 * ldratio * ( beta ) ** ( -1 ) * rho * 1/cos(


gamma ) * sin( sigma ) + ( -1 * ( m ) ** ( -1 ) * T * ( V ) ** ( -2 ) *
1/cos( gamma ) * sin( epsilon ) * sin( sigma ) + ( ( h + R ) * ( V
) ** ( -2 ) * ( omega ) ** ( 2 ) * cos( latitude ) * cos( heading ) * 1/
cos(
gamma ) * sin( latitude ) + -1 * ( ( h + R ) ) ** ( -1 ) * cos( gamma )
*
cos( heading ) * tan( latitude ) ) ) )],
[( 2 * omega * cos(
latitude ) * ( 1/cos( gamma ) ) ** ( 2 ) * sin( heading ) + ( 1/2 * ldratio
*
V * ( beta ) ** ( -1 ) * rho * 1/cos( gamma ) * sin( sigma ) * tan(
gamma ) + ( ( m ) ** ( -1 ) * T * ( V ) ** ( -1 ) * 1/cos( gamma ) * sin(
epsilon ) * sin( sigma ) * tan( gamma ) + ( -1 * ( h + R ) * ( V
) ** ( -1 ) * ( omega ) ** ( 2 ) * cos( latitude ) * cos( heading ) * 1/cos(
gamma ) * sin( latitude ) * tan( gamma ) + ( ( h + R ) ) ** ( -1 ) * V *
cos( heading ) * sin( gamma ) * tan( latitude ) ) ) ) )] ,
[( ( h +
R ) * ( V ) ** ( -1 ) * ( omega ) ** ( 2 ) * cos( latitude ) * 1/cos( gamma
) * sin( latitude ) * sin( heading ) + ( 2 * omega * cos( latitude ) *
cos(
heading ) * tan( gamma ) + ( ( h + R ) ) ** ( -1 ) * V * cos( gamma ) *
sin( heading ) * tan( latitude ) ) ),],
[( -1 * ( V ) ** ( -1 ) * (
omega ) ** ( 2 ) * cos( latitude ) * cos( heading ) * 1/cos( gamma ) * sin(
latitude ) + ( ( h + R ) ) ** ( -2 ) * V * cos( gamma ) * cos( heading ) *
tan( latitude ) ),] ,
[0,] ,
[( -1 * ( h + R ) * ( V ) ** (
-1 ) * ( omega ) ** ( 2 ) * ( cos( latitude ) ) ** ( 2 ) * cos( heading ) *
1/cos( gamma ) + ( -1 * ( ( h + R ) ) ** ( -1 ) * V * cos( gamma ) *
cos( heading ) * ( 1/cos( latitude ) ) ** ( 2 ) + ( ( h + R ) * ( V ) ** ( -1
)
* ( omega ) ** ( 2 ) * cos( heading ) * 1/cos( gamma ) * ( sin( latitude )
) ** ( 2 ) + 2 * omega * ( -1 * cos( latitude ) + -1 * sin( latitude ) *
sin( heading ) * tan( gamma ) ) ) ) ),] ] )

f3 = np. array ( [( [sin( gamma ),] ),


( [V * cos( gamma ),] ),
( [0,] ),
( [0,] ),
( [0,] ),
( [0,] ),] )

f5 = np. array ( [( [( ( h + R ) ) ** ( -1 ) * cos( gamma ) * cos( heading ) * 1/cos( latitude ),


] ),
( [-1 * ( ( h + R ) ) ** ( -1 ) * V * cos( heading ) * 1/cos( latitude ) * sin(
gamma ),] ),
( [-1 * ( ( h + R ) ) ** ( -1 ) * V * cos( gamma ) * 1/cos( latitude ) * sin(
heading ),] ),

10
( [-1 * ( ( h + R ) ) ** ( -2 ) * V * cos( gamma ) * cos( heading ) * 1/cos(
latitude ),] ),
( [0,] ),
( [( ( h + R ) ) ** ( -1 ) * V * cos( gamma ) * cos( heading ) * 1/cos( latitude )
* tan( latitude ),] ),] )

f6 = np. array ( [( [( ( h + R ) ) ** ( -1 ) * cos( gamma ) * sin( heading ),]),


( [-1 * ( ( h + R ) ) ** ( -1 ) * V * sin( gamma ) * sin( heading ),] ),
( [( ( h + R ) ) ** ( -1 ) * V * cos( gamma ) * cos( heading ),]),
( [-1 * ( ( h + R ) ) ** ( -2 ) * V * cos( gamma ) * sin( heading ),] ),
( [0,] ),
( [0,] ),] )

F = np. hstack ((f1 , f2 ,f3 ,f4 ,f5 ,f6)).T

g1 = np. array ( [( [( m ) ** ( -1 ) * cos( epsilon ),] ),


( [-1 * ( m ) ** ( -1 ) * T * sin( epsilon ),] ),
( [0,] ),
( [0,] )])

g2 = np. array ( [( [( m ) ** ( -1 ) * ( V ) ** ( -1 ) * cos( sigma ) * sin( epsilon ),] ),


( [( m ) ** ( -1 ) * T * ( V ) ** ( -1 ) * cos( epsilon ) * cos( sigma ),] ),
( [( -1/2 * ldratio * V * ( beta ) ** ( -1 ) * rho * sin( sigma ) + -1 * ( m ) ** (
-1 ) * T * ( V ) ** ( -1 ) * sin(
epsilon ) * sin( sigma ) ),] )
,
[rho*V*cos( sigma )/ (2 * beta)]])

g3 = np. zeros ((4, 1))

g4 = np. array ( [( [( m ) ** ( -1 ) * ( V ) ** ( -1 ) * 1/cos( gamma ) * sin( epsilon ) * sin(


sigma ),] ),
( [( m ) ** ( -1 ) * T * ( V ) ** ( -1 ) * cos( epsilon ) * 1/cos( gamma ) * sin(
sigma ),] ),
( [( 1/2 * ldratio * V * ( beta ) ** ( -1 ) * rho * cos( sigma ) * 1/cos( gamma )
+ ( m ) ** ( -1 ) * T * ( V ) ** (
-1 ) * cos( sigma ) * 1/cos(
gamma ) * sin( epsilon ) ),] ),
[rho*V*sin( sigma )/(cos( gamma )*2*beta)]] )

g56 = np. zeros ((4,2))

G = np. hstack ((g1 , g2 , g3 , g4 , g56)).T

# Only control roll angle


G = G[:,2:]
return F, G

B. Heading Error Computation


def compute_desired_heading ( cur_position , des_position ):
pos_vector = des_position - cur_position
heading_des = np. arctan2 ( pos_vector [1], pos_vector [0])
return normalize_angle ( heading_des )

C. Control gain computation along trajectory


# Precompute the control gains
K_vec = np. zeros (( x_traj . shape [1], 2, 6))
for i in range(1, x_traj . shape [1]):
curr_x = x_traj [:,-i]
A, B = nonplanar_eom_jacobians (0, curr_x , u_0 , STS_13_params , exponential_atmosphere )
try:
K, S, E = lqr(A, B, Q, R)

11
K_vec [-i,:,:] = K
except :
K_vec [-i,:,:] = K_vec [-i+1,:,:]

D. Compute Control
def compute_control (x, u_0 , x_traj , K, params : EntryVehicleParams ):
# Scale the trajectory
x_scale = x.copy ()
x_scale [0] = x_scale [0] / 1000
x_scale [2] = x_scale [2] / 1000
x_traj_scale = x_traj .copy ()
x_traj_scale [0] = x_traj_scale [0] / 1000
x_traj_scale [2] = x_traj_scale [2] / 1000

# Find the closest trajectory point


idx = np. argmin (np.sum (( x_traj_scale .T - x_scale ) ** 2, 1))
x_linearize = x_traj [:, idx]
K_i = K[idx , :, :]

dx = x - x_linearize

# Compute the heading separately


curr_pos = x[4:]
des_pos = params . desired_position
heading_des = compute_desired_heading (curr_pos , des_pos )

heading_delta = normalize_angle (x[3] - heading_des )


dx[3] = heading_delta
# print (np. degrees ( heading_des ))

u = u_0.copy ()
u[2:] = u_0[2:] - K_i @ dx
# print (K_i @ dx)

u[2] = np.clip(u[2], -np.pi / 2, np.pi / 2)


u[3] = np.clip(u[3], 0, params . lift_drag_ratio )

return u

References
[1] Findlay, J., Kelly, G. M., McConnell, J. G., and Heck, M., “STS-13 (41-C) BET Products,” Tech. rep., NASA, 1984.

[2] Dreyfus, J., Stableford, C., and Boughton, E., “Apollo Mission SA 501 Preliminary Mission Profile,” Tech. rep., NASA, 1965.

[3] Molinari, B., “The stabilizing solution of the algebraic Riccati equation,” SIAM Journal on Control, Vol. 11, No. 2, 1973, pp.
262–271.

[4] Vinh, N. X., Busemann, A., and Culp, R. D., “Hypersonic and planetary entry flight mechanics,” NASA Sti/Recon Technical
Report A, Vol. 81, 1980, p. 16245.

[5] Atmosphere, U. S., US standard atmosphere, National Oceanic and Atmospheric Administration, 1976.

[6] Atmosphere, U. S., US standard atmosphere, National Oceanic and Atmospheric Administration, 1962.

[7] Tassa, Y., Erez, T., and Todorov, E., “Synthesis and stabilization of complex behaviors through online trajectory optimization,”
2012 IEEE/RSJ International Conference on Intelligent Robots and Systems, IEEE, 2012, pp. 4906–4913.

12

You might also like