MLTE03 · Week 7 · Lecture + Lab

Optimal control: LQR

for hover & attitude stabilization · 最優控制:懸停與姿態穩定的 LQR

Flight Dynamics & Intelligent Control Technologies
Block: Make it fly — classical control. Stop hand-tuning. Let a cost function pick the gains.

Recap → today

From tuned loops to an optimal gain

  • Wk 4: linearized hover model \( \dot{\mathbf{x}}=A\mathbf{x}+B\mathbf{u} \) — \(A\) is \(12\times12\), \(B\) is \(12\times4\), poles at the origin.
  • Wk 5–6: cascade PID — we picked \(K_p,K_d\) by hand, loop by loop.
  • Today: one cost function ⇒ one optimal full-state gain \(K\) for all 12 states at once.
The shift: PID asks "what gains feel right?"
LQR asks "what do I care about?" — then solves for the gains that are provably best.

Learning objectives

By the end of today you can…

  • State the LQR problem: minimize \( \int_0^\infty (\mathbf{x}^\top Q\,\mathbf{x} + \mathbf{u}^\top R\,\mathbf{u})\,dt \) with full-state feedback \( \mathbf{u}=-K\mathbf{x} \).
  • Write the continuous-time algebraic Riccati equation (CARE) and read off how \(Q,R\) trade tracking vs effort.
  • Design \(K\) on the Week-4 linear model, confirm the closed-loop poles move into the left half-plane, and compare to PID.
  • Lab Build the LQR gain in quadsim.analysis.lqr; plot the open- vs closed-loop pole map.

The problem

What "optimal" means here

Linear model about hover, \( \mathbf{x}=\delta\)state, \( \mathbf{u}=\delta\)wrench \([\delta T,\tau_x,\tau_y,\tau_z]\):

\[ \dot{\mathbf{x}} = A\mathbf{x} + B\mathbf{u} \]

Choose the input that minimizes a quadratic cost over all future time:

\[ J = \int_0^\infty \Big( \underbrace{\mathbf{x}^\top Q\,\mathbf{x}}_{\text{tracking error}} \;+\; \underbrace{\mathbf{u}^\top R\,\mathbf{u}}_{\text{control effort}} \Big)\,dt, \qquad Q=Q^\top\succeq 0,\; R=R^\top\succ 0 \]
The remarkable result: the optimal law is plain linear full-state feedback, \( \mathbf{u}=-K\mathbf{x} \). No gain scheduling, no lookup table — one constant matrix \(K\).

How K is computed

The Riccati equation gives the gain

The optimal cost-to-go is \( \mathbf{x}^\top P\,\mathbf{x} \). The matrix \(P=P^\top\succeq 0\) solves the continuous-time algebraic Riccati equation (CARE):

\[ A^\top P + P A - P B R^{-1} B^\top P + Q = 0 \]

and the gain falls straight out of \(P\):

\[ K = R^{-1} B^\top P, \qquad \mathbf{u} = -K\mathbf{x} \]
quadsim solves CARE with the Hamiltonian eigenvector method (pure NumPy): form \( H=\begin{bmatrix} A & -BR^{-1}B^\top \\ -Q & -A^\top \end{bmatrix} \), take the \(n\) eigenvectors with \( \mathrm{Re}(\lambda)<0 \), and \( P = U_{21}U_{11}^{-1} \). No SciPy required.

The design knobs

\(Q\) and \(R\): the whole tuning story

  • \(Q\) bigger ⇒ penalize state error harder ⇒ faster, more aggressive response, more effort.
  • \(R\) bigger ⇒ penalize actuator use ⇒ gentler, slower, motors saturate less.
  • Only the ratio \(Q/R\) matters; scale both, \(K\) is unchanged.
  • Diagonal \(Q,R\) = one weight per state / per channel — interpretable and enough here.
A sensible hover starting point (from examples/04_analysis.py):
Q = diag(10,10,10, 1,1,1, 10,10,10, 1,1,1)
R = diag(1, 10,10,10)
order: pos, vel, Euler, body-rates · wrench \([\,T,\tau_x,\tau_y,\tau_z\,]\)

Does it stabilize?

Poles march into the left half-plane

Closed loop is \( \dot{\mathbf{x}} = (A-BK)\,\mathbf{x} \). LQR guarantees every eigenvalue of \(A-BK\) has negative real part (for stabilizable \(A,B\) and sensible \(Q,R\)).

        Im
         ^            |   UNSTABLE (Re>0)
     o   |            |   shaded red
   o     |   o        |
  -------+----X---X---+------------------> Re
   o     |     X  X   |   0
     o   |  X         |
         |            |
   LQR closed loop (X): all Re < 0      open loop (o): poles at origin
   verified max Re(pole) ~ -1.74        (marginally stable, must feed back)
  

With the \(Q,R\) above, cl.real.max() ≈ -1.74 — a comfortable stability margin, no hand-tuning.

In the simulator

Eight lines from model to gain

Re-use the Week-4 linearization, then call analysis.lqr:

import numpy as np
from quadsim import QuadParams, analysis as an

p = QuadParams()
A, B = an.linearize(p)                 # Wk-4 linear model about hover (12x12, 12x4)
ol = an.poles(A)                       # open-loop poles — sit at the origin

Q = np.diag([10,10,10, 1,1,1, 10,10,10, 1,1,1.0])
R = np.diag([1.0, 10, 10, 10])
K, P, cl = an.lqr(A, B, Q, R)          # solves CARE, returns K, P, closed-loop poles

print("max Re(closed-loop pole) =", cl.real.max())   # ~ -1.74, all < 0
print("stable:", np.all(cl.real < 0))

Apply it about hover as \( \mathbf{u}=\mathbf{u}_{\text{hover}}-K(\mathbf{x}-\mathbf{x}_{\text{eq}}) \). See examples/04_analysis.py.

Compare

LQR vs the PID you already built

PID (Wk 5–6)
  • Tuned per loop, by hand.
  • Local, decoupled axes.
  • Intuitive; no model needed.
LQR (today)
  • One gain, solved from a cost.
  • Couples all 12 states at once.
  • Optimal & stable — but needs \(A,B\).

In the lab you'll put them head to head: overshoot, settling time, control effort on the same step.

Same plant, two philosophies. Neither is "right" — LQR shines when you trust the model and care about effort.

Second half · hands-on

Now you build it

  • Open the Week 7 lab sheet → design an LQR gain with quadsim.analysis.lqr.
  • Plot open-loop vs LQR closed-loop poles with plotting.plot_poles.
  • Run export PYTHONPATH=. && python examples/04_analysis.py.
  • Checkpoint: all closed-loop poles have \( \mathrm{Re}<0 \) (max \( \approx -1.74 \)). ⭐ graded.

Open the Week 7 lab sheet →

Wrap-up

What to remember

  • LQR minimizes \( \int \mathbf{x}^\top Q\mathbf{x} + \mathbf{u}^\top R\mathbf{u}\,dt \) ⇒ optimal feedback \( \mathbf{u}=-K\mathbf{x} \).
  • \(K=R^{-1}B^\top P\), where \(P\) solves the CARE \( A^\top P+PA-PBR^{-1}B^\top P+Q=0 \).
  • \(Q\) vs \(R\) trades tracking against effort; LQR puts every pole of \(A-BK\) in the left half-plane.
  • Next week: when the model is uncertain or constrained, we go to model-predictive control — LQR with a horizon and limits.

Reading: MIT 16.323 (How), Lec 3–4 — ocw.mit.edu/courses/16-323 · conventions in simulator/CONVENTIONS.md. Deliverable & deadline on the lab sheet.