392 lines
21 KiB
TeX
392 lines
21 KiB
TeX
\chapter{Algorithm Overview} \label{algorithm}
|
|
|
|
In this section, we will review the actual execution of the algorithm developed. As an
|
|
overview, the routine was developed to enable the determination of an optimized spacecraft
|
|
trajectory from the selection of some very basic mission parameters. Those parameters
|
|
include:
|
|
|
|
\begin{itemize}
|
|
\item Spacecraft dry mass
|
|
\item Thruster Specific Impulse
|
|
\item Thruster Maximum Thrusting Force
|
|
\item Thruster Duty Cycle Percentage
|
|
\item Number of Thruster on Spacecraft
|
|
\item Total Starting Weight of the Spacecraft
|
|
\item A Maximum Acceptable $V_\infty$ at arrival and $C_3$ at launch
|
|
\item The Launch Window Timing and the Latest Arrival
|
|
\item A cost function relating the mass usage, $v_\infty$ at arrival, and $C_3$ at
|
|
launch to a cost
|
|
\item A list of flyby planets starting with Earth and ending with the destination
|
|
\end{itemize}
|
|
|
|
Which allows for extremely automated optimization of the trajectory, while still providing
|
|
the mission designer with the flexibility to choose the particular flyby planets to
|
|
investigate.
|
|
|
|
This is achieved via an optimal control problem in which the ``inner loop'' is a
|
|
non-linear programming problem to determine the optimal low-thrust control law and flyby
|
|
parameters given a suitable initial guess. Then an ``outer loop'' monotonic basin hopping
|
|
algorithm is used to traverse the search space and more carefully optimize the solutions
|
|
found by the inner loop.
|
|
|
|
\section{Trajectory Composition}
|
|
|
|
In this thesis, a specific nomenclature will be adopted to define the stages of an
|
|
interplanetary mission in order to standardize the discussion about which aspects of the
|
|
software affect which phases of the mission.
|
|
|
|
Overall, a mission is considered to be the entire overall trajectory. In the context of
|
|
this software procedure, a mission is taken to always begin at the Earth, with some
|
|
initial launch C3 intended to be provided by an external launch vehicle. This C3 is not
|
|
fully specified by the mission designer, but instead is optimized as a part of the
|
|
overall cost function (and normalized by a designer-specified maximum allowable value).
|
|
|
|
This overall mission can then be broken down into a variable number of ``phases''
|
|
defined as beginning at one planetary body with some excess hyperbolic velocity and
|
|
ending at another. The first phase of the mission is from the Earth to the first flyby
|
|
planet. The final phase is from the last flyby planet to the planet of interest.
|
|
|
|
Each of these phases are then connected by a flyby event at the boundary. Each flyby
|
|
event must satisfy the following conditions:
|
|
|
|
\begin{enumerate}
|
|
\item The planet at the end of one phase must match the planet at the beginning of
|
|
the next phase.
|
|
\item The magnitude of the excess hyperbolic velocity coming into the planet (at the
|
|
end of the previous phase) must equal the magnitude of the excess hyperbolic
|
|
velocity leaving the planet (at the beginning of the next phase).
|
|
\item The flyby ``turning angle'' must be such that the craft maintains a safe
|
|
minimum altitude above the surface or atmosphere of the flyby planet.
|
|
\end{enumerate}
|
|
|
|
These conditions then effectively stitch the separate mission phases into a single
|
|
coherent mission, allowing for the optimization of both individual phases and the entire
|
|
mission as a whole. This nomenclature is similar to the nomenclature adopted by Jacob
|
|
Englander in his Hybrid Optimal Control Problem paper, but does not allow for missions
|
|
with multiple targets, simplifying the optimization.
|
|
|
|
\section{Inner Loop Implementation}\label{inner_loop_section}
|
|
|
|
The optimization routine can be reasonable separated into two separate ``loops'' wherein
|
|
the first loop is used, given an initial guess, to find valid trajectories within the
|
|
region of the initial guess and submit the best. The outer loop is then used to traverse
|
|
the search space and supply the initial loop with a number of well chosen initial
|
|
guesses.
|
|
|
|
Figure~\ref{nlp} provides an overview of the process of breaking a mission guess down
|
|
into an NLP, but there are essentially three primary routines involved in the inner
|
|
loop. A given state is propagated forward using the LaGuerre-Conway Kepler solution
|
|
algorithm, which itself is used to generate powered trajectory arcs via the
|
|
Sims-Flanagan transcribed propagator. Finally, these powered arcs are connected via a
|
|
multiple-shooting non-linear optimization problem. The trajectories describing each
|
|
phase complete one ``Mission Guess'' which is fed to the non-linear solver to generate
|
|
one valid trajectory within the vicinity of the original Mission Guess.
|
|
|
|
\begin{figure}[H]
|
|
\centering
|
|
\includegraphics[width=\textwidth]{flowcharts/nlp}
|
|
\caption{A flowchart of the Non-Linear Problem Solving Formulation}
|
|
\label{nlp}
|
|
\end{figure}
|
|
|
|
\subsection{LaGuerre-Conway Kepler Solver}\label{conway_pseudocode}
|
|
|
|
The most basic building block of any trajectory is a physical model for simulating
|
|
natural trajectories from one point forward in time. The approach taken by this
|
|
paper uses the solution to Kepler's equation put forward by
|
|
Conway\cite{laguerre_conway} in 1986 in order to provide simple and very
|
|
processor-efficient propagation without the use of integration. The code logic
|
|
itself is actually quite simple, providing an approach similar to the Newton-Raphson
|
|
approach for finding the roots of the Battin form of Kepler's equation.
|
|
|
|
The following pseudo-code outlines the approach taken for the elliptical case. The
|
|
approach is quite similar when $a<0$:
|
|
|
|
% TODO: Some symbols here aren't recognized by the font
|
|
\begin{singlespacing}
|
|
\begin{verbatim}
|
|
i = 0
|
|
# First declare some useful variables from the state
|
|
sig0 = (position ⋅ velocity) / √(mu)
|
|
a = 1 / ( 2/norm(position) - norm(velocity)^2/mu )
|
|
coeff = 1 - norm(position)/a
|
|
|
|
# This loop is essentially a second-order Newton solver for ΔE
|
|
ΔM = ΔE_new = √(mu/a^3) * time
|
|
ΔE = 1000
|
|
while abs(ΔE - ΔE_new) > 1e-10
|
|
ΔE = ΔE_new
|
|
F = ΔE - ΔM + sig0 / √(a) * (1-cos(ΔE)) - coeff * sin(ΔE)
|
|
dF = 1 + sig0 / √(a) * sin(ΔE) - coeff * cos(ΔE)
|
|
d2F = sig0 / √(a) * cos(ΔE) + coeff * sin(ΔE)
|
|
ΔE_new = ΔE - n*F / ( dF + sign(dF) * √(abs((n-1)^2*dF^2 - n*(n-1)*F*d2F )))
|
|
i += 1
|
|
end
|
|
|
|
# ΔE can then be used to determine the F/Ft and G/Gt coefficients
|
|
F = 1 - a/norm(position) * (1-cos(ΔE))
|
|
G = a * sig0/ √(mu) * (1-cos(ΔE)) + norm(position) * √(a) / √(μ) * sin(ΔE)
|
|
r = a + (norm(position) - a) * cos(ΔE) + sig0 * √(a) * sin(ΔE)
|
|
Ft = -√(a)*√(mu) / (r*norm(position)) * sin(ΔE)
|
|
Gt = 1 - a/r * (1-cos(ΔE))
|
|
|
|
# Which provide transformations from the original position and velocity to the
|
|
# final
|
|
final_position = F*position + G*velocity
|
|
final_velocity = Ft*position + Gt*velocity
|
|
\end{verbatim}
|
|
\end{singlespacing}
|
|
|
|
This approach was validated by generating known good orbits in the 2 Body Problem.
|
|
For example, from the orbital parameters of a certain state, the orbital period can
|
|
be determined. If the system is then propagated for an integer multiple of the orbit
|
|
period, the state should remain exactly the same as it began. In
|
|
Figure~\ref{laguerre_plot} an example of such an orbit is provided.
|
|
|
|
\begin{figure}[H]
|
|
\centering
|
|
\includegraphics[width=\textwidth]{fig/laguerre_plot}
|
|
\caption{Example of a natural trajectory propagated via the Laguerre-Conway
|
|
approach to solving Kepler's Problem}
|
|
\label{laguerre_plot}
|
|
\end{figure}
|
|
% TODO: Consider adding a paragraph about the improvements in processor time
|
|
|
|
\subsection{Sims-Flanagan Propagator}
|
|
|
|
Until this point, we've not yet discussed how best to model the low-thrust
|
|
trajectory arcs themselves. The Laguerre-Conway algorithm efficiently determines
|
|
natural trajectories given an initial state, but it still remains, given a control
|
|
law, that we'd like to determine the trajectory of a system with continuous input
|
|
thrust.
|
|
|
|
For this, we leverage the Sims-Flanagan transcription mentioned earlier. This allows
|
|
us to break a single phase into a number of ($n$) different arcs. At the center of
|
|
each of these arcs we can place a small impulsive burn, scaled appropriately for the
|
|
thruster configured on the spacecraft of interest. Therefore, for any given phase,
|
|
we actually split the trajectory into $2n$ sub-trajectories, with $n$ scaled
|
|
impulsive thrust events. As $n$ is increased, the trajectory becomes increasingly
|
|
accurate as a model of low-thrust propulsion in the 2BP. This allows the mission
|
|
designer to trade-off speed of propagation and the fidelity of the results quite
|
|
effectively.
|
|
|
|
\begin{figure}[H]
|
|
\centering
|
|
\includegraphics[width=\textwidth]{fig/spiral_plot}
|
|
\caption{An example trajectory showing that classic continuous-thrust orbit
|
|
shapes, such as this orbit spiral, are easily achievable using a Sims-Flanagan
|
|
model}
|
|
\label{sft_plot}
|
|
\end{figure}
|
|
|
|
Figure~\ref{sft_plot} shows that the Sims-Flanagan transcription model can be used
|
|
to effectively model these types of orbit trajectories. In fact, the Sims-Flanagan
|
|
model is capable of modeling nearly any low-thrust trajectory with a sufficiently
|
|
high number of $n$ samples.
|
|
|
|
Finally, it should be noted that, in any proper propagation scheme, mass should be
|
|
decremented proportionally to the thrust used. The Sims-Flanagan Transcription
|
|
assumes that the thrust for a given sub-trajectory is constant across the entirety
|
|
of that sub-trajectory. Therefore, the mass used by that particular thrusting event
|
|
can be determined by knowledge of the percentage of maximum thrust being provided
|
|
and the mass flow rate (a function of the duty cycle percentage ($d$), thrust ($f$),
|
|
and the specific impulse of the thruster ($I_{sp}$), commonly used to measure
|
|
efficiency)\cite{sutton2016rocket}:
|
|
|
|
\begin{equation}
|
|
\Delta m = \Delta t \frac{f d}{I_{sp} g_0}
|
|
\end{equation}
|
|
|
|
Where $\Delta m$ is the fuel used in the sub-trajectory, $\Delta t$ is the time of
|
|
flight of the sub-trajectory, and $g_0$ is the standard gravity at the surface of
|
|
Earth.
|
|
|
|
\subsection{Non-Linear Problem Solver}
|
|
|
|
Now that we have the basic building blocks of a continuous-thrust trajectory, we can
|
|
leverage one of the many non-linear optimization packages to find solutions near to
|
|
a (proposed) trajectory. This trajectory need not be valid.
|
|
|
|
For the purposes of discussion in this Section, we will assume that the inner-loop
|
|
algorithm starts with just such a ''Mission Guess``, which represents the proposed
|
|
trajectory. However, we'll briefly mention what quantities are needed for this
|
|
input:
|
|
|
|
A Mission Guess object contains:
|
|
\begin{singlespacing}
|
|
\begin{itemize}
|
|
\item The spacecraft and thruster parameters for the mission
|
|
\item A launch date
|
|
\item A launch $v_\infty$ vector representing excess Earth velocity
|
|
\item For each phase of the mission:
|
|
\begin{itemize}
|
|
\item The planet that the spacecraft will encounter (either flyby or
|
|
complete the mission) at the end of the phase
|
|
\item The $v_{\infty,out}$ vector representing excess velocity at the
|
|
planetary flyby (or launch if phase 1) at the beginning of the phase
|
|
\item The $v_{\infty,in}$ vector representing excess velocity at the
|
|
planetary flyby (or completion of mission) at the end of the phase
|
|
\item The time of flight for the phase
|
|
\item The unit-thrust profile in a sun-fixed frame represented by a
|
|
series of vectors with each element ranging from 0 to 1.
|
|
\end{itemize}
|
|
\end{itemize}
|
|
\end{singlespacing}
|
|
|
|
From this information, as can be seen in Figure~\ref{nlp}, we can formulate the
|
|
mission in terms of a non-linear problem. Specifically, the Mission Guess object can
|
|
be represented as a vector, $x$, the propagation function as a function $F$, and the
|
|
constraints as another function $G$ such that $G(x) = \vec{0}$.
|
|
|
|
This is a format that we can apply directly to the IPOPT solver, which Julia (the
|
|
programming language used) can utilize via bindings supplied by the SNOW.jl
|
|
package\cite{snow}.
|
|
|
|
IPOPT also requires the derivatives of both the $F$ and $G$ functions in the
|
|
formulation above. Generally speaking, a project designer has two options for
|
|
determining derivatives. The first option is to analytically determine the
|
|
derivatives, guaranteeing accuracy, but requiring processor time if determined
|
|
algorithmically and sometimes simply impossible or mathematically very rigorous to
|
|
determine manually. The second option is to numerically derive the derivatives,
|
|
using a technique such as finite differencing. This limits the accuracy, but can be
|
|
faster than algorithmic symbolic manipulation and doesn't require rigorous manual
|
|
derivations.
|
|
|
|
However, the Julia language has an excellent interface to a new technique, known as
|
|
automatic differentiation\cite{RevelsLubinPapamarkou2016}. Automatic differentiation
|
|
takes a slightly different approach to numerical derivation. It takes advantage of
|
|
the fact that any algorithmic function, no matter how complicated, can be broken
|
|
down into a series of smaller arithmetic functions, down to the level of simple
|
|
arithmetic. Since all of these simple arithmetic functions have a known derivative,
|
|
we can define a new datatype that carries through the function both the float and a
|
|
second number representing the derivative. Then, by applying (to the derivative) the
|
|
chain rule for every minute arithmetic function derivative as that arithmetic
|
|
function is applied to the main float value, the derivative can be determined,
|
|
accurate to the machine precision of the float type being used, with a processing
|
|
equivalent of two function calls (this of course depends on the simplicity of the
|
|
chained derivatives compared to the function pieces themselves). Generally speaking
|
|
this is much faster than the three or more function calls necessary for accurate
|
|
finite differencing and removes the need for the designer to tweak the epsilon value
|
|
in order to achieve maximum precision.
|
|
|
|
\section{Outer Loop Implementation}
|
|
|
|
Now we have the tools in place for, given a potential ''mission guess`` in the
|
|
vicinity of a valid guess, attempting to find a valid and optimal solution in that
|
|
vicinity. Now what remains is to develop a routine for efficiently generating these
|
|
random mission guesses in such a way that thoroughly searches the entirety of the
|
|
solution space with enough granularity that all spaces are considered by the inner loop
|
|
solver.
|
|
|
|
Once that has been accomplished, all that remains is an ''outer loop`` that can generate
|
|
new guesses or perturb existing valid missions as needed in order to drill down into a
|
|
specific local minimum. In this thesis, that is accomplished through the use of a
|
|
Monotonic Basin Hopping algorithm. This will be described more thoroughly in
|
|
Section~\ref{mbh_subsection}, but Figure~\ref{mbh_flow} outlines the process steps of
|
|
the algorithm.
|
|
|
|
\begin{figure}[H]
|
|
\centering
|
|
\includegraphics[width=\textwidth]{flowcharts/mbh}
|
|
\caption{A flowchart visualizing the steps in the monotonic basin hopping
|
|
algorithm}
|
|
\label{mbh_flow}
|
|
\end{figure}
|
|
|
|
\subsection{Random Mission Generation}\label{random_gen_section}
|
|
|
|
At a basic level, the algorithm needs to produce a mission guess (represented by all
|
|
of the values described in Section~\ref{inner_loop_section}) that contains random
|
|
values within reasonable bounds in the space. This leaves a number of variables open
|
|
to for implementation. For instance, it remains to be determined which distribution
|
|
function to use for the random values over each of those variables, which bounds to
|
|
use, as well as the possibilities for any improvements to a purely random search.
|
|
|
|
Currently, the first value set for the mission guess is that of $n$, which is the
|
|
number of sub-trajectories that each arc will be broken into for the Sims-Flanagan
|
|
based propagator. For this implementation, that was chosen to be 20, based upon a
|
|
number of tests in which the calculation time for the propagation was compared
|
|
against the accuracy of a much higher $n$ value for some known thrust controls, such
|
|
as a simple spiral orbit trajectory. This value of 20 tends to perform well and
|
|
provide reasonable accuracy, without producing too many variables for the NLP
|
|
optimizer to control for (since the impulsive thrust at the center of each of the
|
|
sub-trajectories is a control variable). This leaves some room for future
|
|
improvements, as will be discussed in Section~\ref{improvement_section}.
|
|
|
|
The bounds for the launch date are provided by the user in the form of a launch
|
|
window, so the initial launch date is just chosen as a standard random value from a
|
|
uniform distribution within those bounds.
|
|
|
|
A unit launch direction is then also chosen as a 3-length vector of uniform random
|
|
numbers and normalized. This vector is then multiplied by a uniform random number
|
|
between 0 and the root of the maximum launch $C_3$ specified by the user to generate
|
|
an initial $\vec{v}_\infty$ vector at launch.
|
|
|
|
Next, the times of flight of each phase of the mission is then decided. Since launch
|
|
date has already been selected, the maximum time of flight can be calculated by
|
|
subtracting the launch date from the latest arrival date provided by the mission
|
|
designer. Then, each leg is chosen from a uniform distribution with bounds currently
|
|
set to a minimum flight time of 30 days and a maximum of 70\% of the maximum time of
|
|
flight. These leg flight times are then iteratively re-generated until the total
|
|
time of flight (represented by the sum of the leg flight times) is less than the
|
|
maximum time of flight. This allows for a lot of flexibility in the leg flight
|
|
times, but does tend toward more often producing longer missions, particularly for
|
|
missions with more flybys.
|
|
|
|
Then, the internal components for each phase are generated. It is at this step, that
|
|
the mission guess generator splits the outputs into two separate outputs. The first
|
|
is meant to be truly random, as is generally used as input for a monotonic basin
|
|
hopping algorithm. The second utilizes a Lambert's solver to determine the
|
|
appropriate hyperbolic velocities (both in and out) at each flyby to generate a
|
|
natural trajectory arc. For this Lambert's case, the mission guess is simply seeded
|
|
with zero thrust controls and outputted to the monotonic basin hopper. The intention
|
|
here is that if the time of flights are randomly chosen so as to produce a
|
|
trajectory that is possible with a control in the vicinity of a natural trajectory,
|
|
we want to be sure to find that trajectory. More detail on how this is handled is
|
|
available in Section~\ref{mbh_subsection}.
|
|
|
|
However, for the truly random mission guess, there are still the $v_\infty$ values
|
|
and the initial thrust guesses to generate. For each of the phases, the incoming
|
|
excess hyperbolic velocity is calculated in much the same way that the launch
|
|
velocity was calculated. However, instead of multiplying the randomly generate unit
|
|
direction vector by a random number between 0 and the square root of the maximum
|
|
launch $C_3$, bounds of 0 and 10 kilometers per second are used instead, to provide
|
|
realistic flyby values.
|
|
|
|
The outgoing excess hyperbolic velocity at infinity is then calculated by again
|
|
choosing a uniform random unit direction vector, then by multiplying this value by
|
|
the magnitude of the incoming $v_{\infty}$ since this is a constraint of a
|
|
non-powered flyby.
|
|
|
|
From these two velocity vectors the turning angle, and thus the periapsis of the
|
|
flyby, can then be calculated by the following equations:
|
|
|
|
\begin{align}
|
|
\delta &= \arccos \left( \frac{\vec{v}_{\infty,in} \cdot
|
|
\vec{v}_{\infty,out}}{|v_{\infty,in}| \cdot {|v_{\infty,out}}|} \right) \\
|
|
r_p &= \frac{\mu}{\vec{v}_{\infty,in} \cdot \vec{v}_{\infty,out}} \cdot \left(
|
|
\frac{1}{\sin(\delta/2)} - 1 \right)
|
|
\end{align}
|
|
|
|
If this radius of periapse is then found to be less than the minimum safe radius
|
|
(currently set to the radius of the planet plus 100 kilometers), then the process is
|
|
repeated with new random flyby velocities until a valid seed flyby is found. These
|
|
checks are also performed each time a mission is perturbed or generated by the NLP
|
|
solver.
|
|
|
|
The final requirement then, is the thrust controls, which are actually quite simple.
|
|
Since the thrust is defined as a 3-vector of values between -1 and 1 representing
|
|
some percentage of the full thrust producible by the spacecraft thrusters in that
|
|
direction, the initial thrust controls can then be generated as a $20 \times 3$
|
|
matrix of uniform random numbers within that bound.
|
|
|
|
\subsection{Monotonic Basin Hopping}\label{mbh_subsection}
|
|
|
|
Now that a generator has been developed for mission guesses, we can build the
|
|
monotonic basin hopping algorithm. Since the implementation of the MBH algorithm
|
|
used in this paper differs from the standard implementation, the standard version
|
|
won't be described here. Instead, the variation used in this paper, with some
|
|
performance improvements, will be considered.
|
|
|
|
|