KKT Example: Spacecraft Landing Problem¶
We demonstrate with a spacecraft landing problem:
Consider a spacecraft 100 km above the surface of some planet. It has just been released from the mother-ship and needs to descend to the surface carrying two astronauts. The spacecraft weighs 2000 kg and has 1000 kg of fuel onboard. The gravitational acceleration of the planet is 6 \(\text{m/s}^{-2}\) (on Earth it is 9.8 \(\text{m/s}^{-2}\)). Burning 1 kg of fuel in one second generates 6000 N of upward thrust. Your job is to write some python code that decides how much fuel to burn, every second, so that the spacecraft lands on the surface under the following constraints:
The upward acceleration must never be more than 3g otherwise the astronauts will pass out.
The vertical velocity must be less than 2 \(\text{m/s}\) when the spacecraft lands otherwise you destroy it.
The goal is to land on the surface, under these constraints, with as much fuel in the tank as possible.
Proof¶
The solution is trivial if we can recognize that the most fuel-efficient way is “suicide burn”, i.e. free-fall until the last moment then burn till landing. Yet as we always assume that the rigorous police is around we need to prove it.
Constraint¶
Formalize the constraints (let upwards be positive):
Altitude \(x(t)\ge 0\):
\[ x'(t) = v(t) \]Speed \(v(t) \le 0\) (downward):
\[ v' (t) = a(t) + g \]where \(g=-6\) and \(a(t) \in [0,a_{\max}]\) is the upward acceleration generated by thrust, where \(a_{\max} = 3 \cdot 9.8 = 29.4\)
Let \(T\) be the landing time. The boundary data:
Note that if \(v(T) > -2\), we can always decrease fuel consumption further i.e. increase \(m(T)\) to make \(v(T) = -2\) and save more fuel.
Objective¶
The objective is about minimizing the usage of fuel i.e.:
Total mass is the sum of spacecraft and fuel:
Thrust force is \(F = -k \cdot u(t)\) with \(k=6000\), so
Now the objective is equivalent to:
The knowns include two integrals: one is about speed, the other is about position. First, let’s look at speed \(v(t)\):
This means the integral is totally determined by \(T\). We denote it as \(A(T)\):
Also, \(A(T)\) is monotonically increasing in \(T\).
Now look at position \(x(t)\):
Note that (3) is also monotonically increasing in \(T\).
Combining (1), (2) and (4) and the bound constraints, we have the new objective:
KKT Conditions¶
By fixing \(T\), the current problem is a perfect setup for KKT. With scalar \(\lambda\) and functions \(\mu_1(t), \mu_2(t) \ge 0\) as Lagrange multipliers, the Lagrangian is:
For \(\text{a.e.} \, t \in [0,T]\):
stationarity:
\[ (T-t) + \lambda - \mu_1(t) + \mu_2(t) = 0 \]complementary slackness:
\[\begin{split} \mu_1(t) \cdot a(t) = 0 \\ \mu_2(t) \cdot (a(t) - a_{\max}) = 0 \end{split}\]
Define \(w (t) = (T-t) + \lambda\), we have three cases:
When \(a(t) = 0\), \(\mu_2 (t) = 0\) due to complementary slackness
\[ w (t) = \mu_1(t) \ge 0 \implies t \le T + \lambda \]When \(a(t) = a_{\max}\), \(\mu_1 (t) = 0\) due to complementary slackness
\[ w (t) = -\mu_2(t) \le 0 \implies t \ge T + \lambda \]When \(0 < a(t) < a_{\max}\), \(\mu_1 (t) = \mu_2 (t) = 0\) due to complementary
\[ w (t) = 0 \implies t = T + \lambda \]
Since \(w (t)\) is monotonically decreasing in \(t\), there exists exactly one switching time \(t^* = T + \lambda\).
which is exactly the “suicide burn” strategy.
Back to Miscellaneous.