Trajectory optimization · from zero

ALTRO: The Augmented Lagrangian Trajectory Optimizer

ALTRO solves nonlinear optimal-control problems with general state and input constraints by wrapping iterative LQR (iLQR) inside an augmented Lagrangian loop, then finishing with an active-set solution-polishing phase. This page builds the whole thing from first principles: first the unconstrained core, then constraints, then the numerical-robustness tricks that make it fast and dependable in practice.

iLQR / DDP coreaugmented Lagrangian square-root backward passsolution polishing infeasible initializationfree-time problems

Notation used throughout

symbolmeaning
\(x_k,\ u_k\)state and control at time step \(k\) (stage \(k = 0,\dots,N-1\))
\(f(x_k,u_k)\)discrete-time dynamics, \(x_{k+1} = f(x_k,u_k)\)
\(A_k,\ B_k\)Jacobians of the dynamics: \(A = \partial f/\partial x\), \(B = \partial f/\partial u\)
\(\ell_k,\ \ell_N\)stage cost and terminal cost
\(g_k,\ h_k\)inequality and equality constraints, \(g \le 0\), \(h = 0\)
\(c_k = (g_k, h_k)\)combined constraint vector
\(\lambda_k\)Lagrange-multiplier (dual) vector, one per constraint per stage
\(\rho,\ \mu\)penalty weight (the paper writes \(\mu\); here \(\rho\)) and its growth factor
\(P_k,\ p_k\)Hessian and gradient of the cost-to-go value function
\(Q_{xx}, Q_{uu}, Q_{xu}, Q_x, Q_u\)second-order local model of the action-value function
\(K_k,\ d_k\)feedback gain and feedforward term of the optimal control update
\(S_k,\ Z\)square-root (Cholesky-type) factors in the robust backward pass

A bar \(\bar{x}\) marks the current nominal trajectory (the point the local model is built around).

1The problem ALTRO is built for

Why this matters. Say you must steer an underactuated robot — a cart-pole, a quadrotor, a 7-DOF arm — through a cluttered room, subject to torque limits and obstacle constraints, from rest to a target pose. Sampling-based planners struggle with dynamic constraints, and differential flatness only works for special systems. The general tool is trajectory optimization: search over the whole time history of controls (and states) to minimize a cost while satisfying the dynamics and any constraints. This is the problem ALTRO solves, fast.

The mathematical form (following the ALTRO paper, Howell, Jackson & Manchester, IROS 2019):

Trajectory optimization problem
\[ \min_{x_{0:N},\,u_{0:N-1},\,\Delta t}\;\; \ell_N(x_N) + \sum_{k=0}^{N-1} \ell_k(x_k,u_k,\Delta t) \qquad \begin{array}{rll} \text{s.t.} & x_{k+1} = f(x_k,u_k,\Delta t), & k = 0,\dots,N-1,\\[2pt] & g_k(x_k,u_k) \le 0, & \text{inequality constraints},\\[2pt] & h_k(x_k,u_k) = 0, & \text{equality constraints}. \end{array} \]

Typical costs are quadratic (control effort, distance to target); typical constraints are torque limits, joint limits, obstacle avoidance, and terminal state goals.

Direct methods

Transcribe states and controls as decision variables; hand the big sparse NLP to SNOPT or IPOPT. Robust, handles any constraint, accepts dynamically infeasible initial guesses — but the NLPs are large and the solvers are general-purpose, hence slower.

Indirect methods (DDP / iLQR)

Keep only the controls as decision variables; the dynamics are enforced by simulation, and dynamic programming (the Riccati sweep) exploits the chain structure. Very fast and small, always dynamically feasible, but historically fragile and without general constraint support.

ALTRO’s bet

Take the indirect core (iLQR) for speed, add an augmented-Lagrangian outer loop for general constraints, square-root the backward pass for conditioning, and polish with an active-set projection for machine-precision constraint satisfaction.

The paper’s contributions, which this page derives one by one: (1) a numerically robust square-root backward pass; (2) a way to start from a dynamically infeasible state trajectory; (3) a free-time formulation; and (4) an objective-weighted Newton projection for solution polishing.

Takeaway. ALTRO is a fast, indirect trajectory optimizer that keeps the direct methods’ most desirable feature — general state and input constraints — by layering constraint machinery over a clean iLQR core.

2The unconstrained core: iLQR from first principles

Why start here. Every piece of ALTRO enters through iLQR, so we need its mechanism cold before anything else. The idea is old and beautiful: the problem has a chain (Markov) structure — each \(x_{k+1}\) depends only on \((x_k,u_k)\) — so we can peel it step by step from the end, exactly like dynamic programming for shortest paths, but in continuous state space using local quadratic models.

2.1 The value function and the local model

Define the cost-to-go \(V_k(x_k)\): the cheapest remaining cost from state \(x_k\) using the best possible controls \(u_k,\dots,u_{N-1}\). Bellman’s principle gives

\[ V_k(x_k) \;=\; \min_{u_k} \Big[\; \ell_k(x_k,u_k) + V_{k+1}\big(f(x_k,u_k)\big) \Big], \qquad V_N(x_N) = \ell_N(x_N). \]

We cannot solve this exactly for nonlinear \(f,\ell\), so we linearize the dynamics about the current nominal trajectory \((\bar{x}_k, \bar{u}_k)\) and quadratize the cost. Write the value function locally as \[ V_{k+1}(\bar x_{k+1} + \delta) \;\approx\; \tfrac12 \delta^\mathsf{T} P_{k+1}\,\delta + p_{k+1}^\mathsf{T}\delta . \] Then the local expansion of the quantity inside the \(\min\) — the action-value function \(Q_k\) — has (dropping stage indices, primed quantities evaluated at \(k{+}1\), \(\delta x = x-\bar x\), \(\delta u = u-\bar u\)):

Local quadratic model (Gauss–Newton: no second derivatives of the dynamics)
\[ \begin{aligned} Q_{xx} &= \ell_{xx} + A^\mathsf{T} P'A, & Q_{uu} &= \ell_{uu} + B^\mathsf{T} P' B, & Q_{xu} &= \ell_{xu} + A^\mathsf{T} P' B,\\ Q_x &= \ell_x + A^\mathsf{T} p', & Q_u &= \ell_u + B^\mathsf{T} p', \end{aligned} \]

with \(A = \partial f/\partial x\), \(B = \partial f/\partial u\) evaluated at \((\bar x_k,\bar u_k)\). These six blocks are all a Riccati sweep needs. Why drop second derivatives of \(f\)? Because the \(\ell_{xx}\) terms are usually available and cheap, while \(f\)'s second derivatives are expensive and often destabilizing — the Gauss–Newton choice keeps the model positive-semidefinite-like and reliable, and it is what ALTRO uses.

2.2 The backward pass: one Riccati sweep

Minimizing the quadratic model over \(\delta u\) — with a small regularization \(\rho_{\mathrm{reg}} \ge 0\) to keep \(Q_{uu} + \rho_{\mathrm{reg}} I\) safely invertible — yields the optimal control correction, split into a feedforward term \(d_k\) and a feedback gain \(K_k\):

Optimal local control and value update
\[ \delta u_k^* = -(Q_{uu}+\rho_{\mathrm{reg}} I)^{-1}\big(Q_{ux}\,\delta x_k + Q_u\big) \;\equiv\; K_k\,\delta x_k + d_k , \] \[ \begin{aligned} P_k &= Q_{xx} + K^\mathsf{T} Q_{uu} K + K^\mathsf{T} Q_{ux} + Q_{xu} K,\\ p_k &= Q_x + K^\mathsf{T} Q_{uu} d + K^\mathsf{T} Q_u + Q_{xu} d,\\ \Delta V_k &= d^\mathsf{T} Q_u + \tfrac12\, d^\mathsf{T} Q_{uu}\, d . \end{aligned} \]

Sweeping \(k = N-1, N-2, \dots, 0\) with terminal \(P_N = \ell_{xx}(x_N)\), \(p_N = \ell_x(x_N)\) produces the gain sequence \(\{K_k, d_k\}\) — the exact optimal feedback law of the local LQR problem. This is the whole backward pass: \(O(N)\) steps, each just a few small matrix products.

2.3 The forward pass, line search, and iteration

The gains describe the best local policy, not the final answer for a nonlinear problem. We re-simulate the system from \(x_0\) with the updated policy, scaled by a step size \(\alpha \in [0,1]\):

\[ u_k = \bar u_k + \alpha\, d_k + K_k\,(x_k - \bar x_k). \]

Why \(\alpha\)? The quadratic model is only locally accurate; by backtracking \(\alpha = 1, \tfrac12, \tfrac14, \dots\) until the true cost decreases, we guarantee progress (a line search on the actual objective). Then we rebuild the model at the new trajectory and repeat: backward sweep, forward roll, repeat. This is Iterative Linear Quadratic Regulator (iLQR) — and with the exact second-order terms included it becomes DDP; the mathematical core is the same.

2.4 Worked example: two steps of a 1-D chain

Let’s make the machinery concrete. Take \(N=2\) steps, \(x_{k+1} = x_k + u_k\), \(x_0 = 1\), cost \(J = \tfrac12 u_0^2 + \tfrac12 u_1^2 + \tfrac12 x_2^2\) (softly reach \(x=0\)). All numbers below are exact rationals, verified by computer.

stepquantityvaluewhy
\(k=1\) (last stage) \(p_2,\ P_2\)\(1,\;1\)terminal gradient/Hessian of \(\tfrac12 x_2^2\) at \(\bar x_2 = 1\)
\(Q_u,\ Q_{uu},\ Q_{ux}\)\(1,\;2,\;1\)\(\ell_u{+}p_2=1\), \(\ell_{uu}{+}P_2=2\), \(P_2=1\)
\(K_1,\ d_1\)\(-\tfrac12,\ -\tfrac12\)\(-Q_{ux}/Q_{uu}\), \(-Q_u/Q_{uu}\)
\(P_1,\ p_1\)\(\tfrac12,\ \tfrac12\)Riccati updates; \(V_1(x_1) = \tfrac14 x_1^2\) exactly
rollout\(u_1 = -\tfrac12 - \tfrac12(x_1-1)\)the brake, applied at the state you actually reach
\(k=0\) \(Q_u,\ Q_{uu},\ Q_{ux}\)\(\tfrac12,\ \tfrac32,\ \tfrac12\)\(p_1=\tfrac12\), \(P_1=\tfrac12\)
\(K_0,\ d_0\)\(-\tfrac13,\ -\tfrac13\)\(-Q_{ux}/Q_{uu}\), \(-Q_u/Q_{uu}\)
first step\(u_0 = -\tfrac13,\ x_1 = \tfrac23\)\(\bar u_0 = 0\), so \(u_0 = d_0\)

Rolling the whole policy forward from \(x_0 = 1\): \(u_0 = -\tfrac13\), \(x_1 = 1-\tfrac13 = \tfrac23\), then \(u_1 = -\tfrac12 - \tfrac12(\tfrac23-1) = -\tfrac13\), \(x_2 = \tfrac13\). Cost: \(\tfrac12(\tfrac19)+\tfrac12(\tfrac19)+\tfrac12(\tfrac19) = \tfrac16\). The exact optimum (solve the 2-variable quadratic directly) is \((u_0^*,u_1^*) = (-\tfrac13,-\tfrac13)\) with \(J^* = \tfrac16\). One sweep landed exactly on the optimum. That is the LQR-exactness of iLQR: for linear dynamics and quadratic cost the model is globally exact, so the first Riccati sweep is Newton’s method and converges in one step. Nonlinearities are precisely the reason the loop iterates.

A tiny puzzle worth sitting with: even though \(u_1\) enters the cost with no dynamics coupling, the backward pass still re-derives the brake \(u_1 = -x_1/2\) conditioned on the state you will actually be in. Only the backward sweep knows that; the forward pass then executes it. This state-conditioning is what makes iLQR/DDP feedback-aware and fast.
Takeaway. iLQR alternates a backward Riccati sweep (local optimal policy) with a forward rollout (apply it where you really are), repeating until the local model stops moving — an anytime algorithm that keeps every iterate dynamically feasible.

3Adding constraints: the augmented Lagrangian method

Why the augmented Lagrangian (AL) and not a plain penalty? The naïve penalty method keeps the constraints’ residual \(g(x)\) only as a squared term, \(\tfrac12\rho\,g^2\), and grows \(\rho \to \infty\) to drive the solution onto the constraint. The 1-D picture explains both why that works and why it is the wrong tool:

Two panels: penalty method valleys narrow and minima creep along y=x toward the constraint but never reach it; augmented Lagrangian with fixed small rho and growing lambda slides the minimum exactly onto the constraint.
Figure 1. Minimize \(\tfrac12 x^2\) subject to \(x = 2\). (a) Penalty method: the minimizer of \(\tfrac12 x^2 + \tfrac12\rho(x-2)^2\) is \(x^* = 2\rho/(1+\rho)\), inching toward 2 as \(\rho\to\infty\) — never exact, and the objective’s valley narrows with condition number \(\approx 1+\rho\) (shades of §5). (b) Augmented Lagrangian, \(\rho = 1\) fixed: adding the multiplier term \(\lambda(x-2)\) slides the minimum onto \(x = 2\) at a finite penalty. The multiplier — not the penalty — does the work.

3.1 The augmented Lagrangian

For constraints \(g \le 0\) and \(h = 0\), ALTRO combines them into \(c = (g,h)\) and augments every stage cost with the indicator-weighted term

Augmented Lagrangian (paper eq. 2)
\[ L_A(x,u;\lambda,\rho) \;=\; \ell(x,u) + \Big(\lambda + \tfrac12\, I_\rho\, c(x,u)\Big)^\mathsf{T} c(x,u), \qquad I_\rho^{(i)} = \begin{cases} 0 & c^{(i)} < 0 \;\text{and}\; \lambda^{(i)} = 0,\;\; i \in \text{inequalities},\\ \rho & \text{otherwise}. \end{cases} \]

Why the indicator \(I_\rho\)? For an inequality that is strictly satisfied (\(g < 0\)) and never active (\(\lambda = 0\)), the constraint costs nothing — it is simply off. Once violated (or once its multiplier is positive), the penalty switches on and the inequality is treated with the same machinery as an equality. This active-set trick is what lets one framework swallow arbitrary mixed state-action constraints.

3.2 The outer loop: dual and penalty updates

AL methods abandon the \(\rho \to \infty\) chase. Instead the multiplier is the memory: the gradient of the constraint violation accumulates into \(\lambda_k\). After each minimization of the augmented cost (with \(\lambda,\rho\) held fixed — here, a few iLQR sweeps), update

Dual and penalty updates (paper eqs. 17–18)
\[ \lambda_k^{(i)+} = \begin{cases} \lambda_k^{(i)} + \rho\, c_k^{(i)}(x_k^*, u_k^*) & i \in \text{equalities},\\ \max\big(0,\ \lambda_k^{(i)} + \rho\, c_k^{(i)}(x_k^*, u_k^*)\big) & i \in \text{inequalities}, \end{cases} \qquad \rho^+ = \phi\,\rho,\quad \phi > 1 . \]

The \(\max(0,\cdot)\) for inequalities enforces complementary slackness — a multiplier for a strictly satisfied inequality would otherwise drift negative and pull the trajectory across the boundary. The penalty grows only geometrically, \(\rho \leftarrow \phi\rho\) (ALTRO typically \(\phi = 10\)) up to a cap; the exactness comes from \(\lambda\), not from \(\rho\).

AL-iLQR (paper Algorithm 1)
 1  input: x0, U, tolerance
 2  initialize lambda = 0, rho = 1, growth factor phi
 3  while max constraint violation > tolerance:
 4      (X, U) ← minimize L_A(X, U; lambda, rho) with iLQR     # inner loop
 5      lambda ← dual update (eq. above)                        # outer loop
 6      rho    ← min(rho_max, phi * rho)
 7  return X, U, lambda

3.3 Why this converges (without blowing up the conditioning)

Log plot comparing outer-loop convergence of the penalty method (rho multiplied by 10 each iteration) versus augmented Lagrangian with fixed rho=10 and multiplier updates; AL reaches machine precision while penalty keeps creeping.
Figure 2. Outer-loop convergence on the 1-D problem of Figure 1. The penalty curve (blue) marks its \(\rho\) value at each iterate — it only makes progress by pushing \(\rho\) to \(10^8\), which is exactly the regime that destroys the inner problem’s conditioning. Augmented Lagrangian with fixed \(\rho = 10\) and multiplier updates (purple) contracts the violation by a factor \(\approx 1+\rho\) per outer iteration — here, machine precision in eight iterations at a penalty that never stresses the inner solver. (Derivation: with multiplier error \(e_k = \lambda_k - \lambda^*\) — here \(\lambda^* = -2\) — the dual update gives \(e_{k+1} = e_k/(1+\rho)\).)
What can still go wrong. The trade-off is real: large \(\rho\) accelerates the dual update (rate \(\sim (1+\rho)^{-1}\) per iteration) but inflates the condition number of the inner LQR problem (§5), while small \(\rho\) is well-behaved but slow. The practical recipe — grow \(\rho\) but keep it bounded, and let \(\lambda\) accumulate — is precisely ALTRO’s staging, and the reason the inner loop conditions on \(\lambda, \rho\) make the whole design tick.
Takeaway. The augmented Lagrangian turns a constrained problem into a sequence of unconstrained ones: each inner iLQR solve minimizes the augmented cost at the current \((\lambda,\rho)\), and the multiplier update is what actually forces the constraints, keeping the penalty magnitude — and the conditioning — under control.

4ALTRO = augmented Lagrangian ∘ iLQR

Why assemble them? iLQR (fast, structure-exploiting, no constraints) plus AL (general constraint machinery, but it needs a good unconstrained solver inside) is a marriage with a long lineage — ALTRO’s phase-1 solver is exactly AL-iLQR: the algorithm of §3 with the iLQR of §2 as its inner minimizer.

Constrained problem

\(\min \ell_N + \sum \ell_k\) s.t. dynamics, \(g\le 0\), \(h = 0\)

▼
phase 1 · coarse

AL-iLQR loop

inner: iLQR sweeps (backward Riccati + forward rollout + line search) to minimize \(L_A\) for fixed \(\lambda, \rho\)

outer: \(\lambda \leftarrow \max(0,\lambda+\rho c)\), \(\rho \leftarrow \phi\rho\) — until violations \(\sim 10^{-3}\)

▼
warm start

Coarse solution \((X, U, \lambda)\)

constraint residual \(\sim 10^{-3}\), dynamically feasible

phase 2 · polish

Active-set Newton projection

project the solution onto the active-constraint manifold with a Hessian-weighted norm → constraint residual \(\sim 10^{-8}\) in a handful of iterations

▼

High-precision solution

machine-precision constraint satisfaction, warm-startable for the next call

4.1 How the constraints enter the inner iLQR

Inside the backward pass, the augmented stage cost \(\ell_k + \lambda_k^\mathsf{T} c_k + \tfrac12 c_k^\mathsf{T} I_\rho c_k\) contributes, under the Gauss–Newton treatment of the constraints (linearized \(c\), dropped second derivatives), exactly four extra terms to each \(Q\)-block:

Constraint-augmented LQR data (paper eqs. 8–12)
\[ \begin{aligned} Q_{xx} &= \ell_{xx} + A^\mathsf{T} P' A + c_x^\mathsf{T} I_\rho\, c_x, & Q_{uu} &= \ell_{uu} + B^\mathsf{T} P' B + c_u^\mathsf{T} I_\rho\, c_u,\\ Q_{ux} &= \ell_{ux} + B^\mathsf{T} P' A + c_u^\mathsf{T} I_\rho\, c_x, & Q_x &= \ell_x + A^\mathsf{T} p' + c_x^\mathsf{T}\big(\lambda + I_\rho c\big),\\ Q_u &= \ell_u + B^\mathsf{T} p' + c_u^\mathsf{T}\big(\lambda + I_\rho c\big). \end{aligned} \]

Why this shape? The multiplier acts like a state-dependent gradient (\(c_x^\mathsf{T}\lambda\) pushes along the constraint gradient), while the penalty adds curvature (\(c_x^\mathsf{T} I_\rho c_x\)) that makes the local QP trust the constraint direction. Nothing else about the backward pass changes — which is the design win: the constraint machinery is data, not a new algorithm.

4.2 The whole loop, end to end, on a real problem

To see phase 1 behave (both its power and its honest limitations), here is a miniature ALTRO — the exact structure above, implemented from scratch in a compact numpy script — applied to a 2-D double-integrator (point mass) that must reach the goal \((1,1)\) while staying outside a circular obstacle. Because the dynamics are linear and the cost quadratic, the Riccati sweep is exact; the only nonlinear object is the obstacle constraint — which is the thing we are here to learn about. (Full source: mini_altro.py in this folder.)

Three panels: trajectory around a circular obstacle reaching the goal; constraint violation vs outer iterations showing a plateau then a cliff to zero; final control profiles.
Figure 3. Mini-ALTRO on “avoid the circle, reach the goal”. (a) The early iterate (gray dashed) cuts straight through the obstacle; the final trajectory (purple) arcs over it and lands on \((1,1)\). (b) The outer-loop max constraint violation \(c_{\max} = \max_k \max(0,g_k(x_k))\): a long plateau while the multiplier accumulates, then a phase transition — the detour finally costs less than cutting through, and \(c_{\max}\) snaps to \(0\). (c) The resulting control profile (steep maneuver away from the circle). The plateau-then-cliff shape is characteristic of plain AL-iLQR and is exactly the “slow tail” the paper reports; §6 shows the fix.
Reading the plateau honestly. While \(\lambda\) is still weak, the cheapest trajectory under \(L_A\) genuinely cuts the circle — the iLQR inner loop is doing its job, and the “violation” is the cost of the constraint at the current multiplier. AL converges because each outer update raises \(\lambda^{(i)}\) by \(\rho\, c^{(i)}\) (~the violated residual), so the penalty’s effective push grows until the constraint wins. When the dynamics are more nonlinear than here, this plateau is where raw AL-iLQR struggles — the motivation for the robustness work that follows.
Takeaway. ALTRO’s phase 1 is a working constrained trajectory optimizer built from two components you already fully understand — and its computing profile already shows both the power (it solves a genuinely non-convex constrained problem from scratch) and the weakness (slow constraint convergence) that the remaining sections cure.

5Why the “square-root” backward pass?

Motivation. AL convergence improves with larger \(\rho\) (§3.3), and ALTRO pushes \(\rho\) to \(10^4\)–\(10^6\) to drive constraints below \(10^{-6}\). But every outer iteration inflates the condition number of the value-function matrix \(P_k\) that the Riccati recursion maintains. A badly conditioned \(P\) means the inner LQR solve loses digits — on hardware with single precision this is fatal. The paper’s first contribution is to run the recursion on a square-root factor instead.

Log-log plot: condition number of the value matrix grows linearly with the penalty rho (slope 1); the square-root factor has condition number equal to the square root of that (slope 1/2); annotations mark the double-precision wall.
Figure 4. A 2-state Riccati recursion whose stage Hessian carries an active penalty term \(\rho\, c_x c_x^\mathsf{T}\) (the AL regime). The value matrix’s condition number grows proportionally to \(\rho\) (slope 1, top); the square-root factor \(S\) with \(S^\mathsf{T}S = P\) has \(\kappa(S) = \sqrt{\kappa(P)}\) (slope 1/2, bottom) — doubling the usable dynamic range before float precision runs out (the dashed wall at \(1/\varepsilon \approx 4.5\times 10^{15}\) for IEEE double). Curves shown are exact (rational) and matching numerically; data in figD_conditioning.py.

5.1 Matrix square roots for sums and differences

The tools are classical (square-root Kalman filtering). Given upper-triangular factors \(\sqrt{A}, \sqrt{B}\) with \(\sqrt{A}^\mathsf{T}\sqrt{A} = A\) (likewise \(B\)):

\[ \sqrt{A + B} \;\leftarrow\; \mathrm{QR}\!\Big(\begin{bmatrix}\sqrt{A}\\ \sqrt{B}\end{bmatrix}\Big), \qquad \sqrt{A - B} \;\leftarrow\; \mathrm{DD}\big(\sqrt{A},\,\sqrt{B}\big), \]

QR of the stacked factors gives an upper-triangular \(R\) with \(R^\mathsf{T}R = A + B\) — without ever forming the sum. The downdate \(\mathrm{DD}\) removes one rank at a time (the rank-one downdate of a Cholesky factor). Why bother? Forming \(A + B\) or \(A - B\) explicitly adds and subtracts across wildly different scales when \(\rho\) is large; the factorized form keeps relative digits of each scale.

5.2 The square-root recursion (structure, not bookkeeping)

Define \(S_k = \sqrt{P_k}\) with \(S_k^\mathsf{T} S_k = P_k\), and let \(Z_{xx} = \sqrt{Q_{xx}}\), \(Z_{uu} = \sqrt{Q_{uu}}\) be the factors of the action-value Hessians. The factorized backward pass is (paper eqs. 19–29):

Square-root backward pass (paper §III-A)
\[ S_N \leftarrow \mathrm{QR}\Big(\big[\,\sqrt{\ell_{N,xx}},\ \sqrt{I_\rho}\, c_x \,\big]\Big),\qquad Z_{xx} \leftarrow \mathrm{QR}\Big(\big[\,\sqrt{\ell_{xx}},\ S' A,\ \sqrt{I_\rho}\, c_x \,\big]\Big), \] \[ Z_{uu} \leftarrow \mathrm{QR}\Big(\big[\,\sqrt{\ell_{uu}},\ S' B,\ \sqrt{I_\rho}\, c_u,\ \sqrt{\rho_{\mathrm{reg}}} I \,\big]\Big), \] \[ K = -Z_{uu}^{-1} Z_{uu}^{-\mathsf{T}} Q_{ux}, \qquad d = -Z_{uu}^{-1} Z_{uu}^{-\mathsf{T}} Q_u, \] \[ S_k \leftarrow \mathrm{QR}\Bigg(\begin{bmatrix} Z_{xx} + Z_{xx}^{-\mathsf{T}} Q_{xu}\, K \\ \mathrm{DD}\big(Z_{uu},\, Z_{xx}^{-\mathsf{T}} Q_{xu}\big)\, K \end{bmatrix}\Bigg). \]

Every update is either a \(\{ \text{multiply, solve, QR} \}\) step or a \(\{ \text{multiply, solve, downdate} \}\) step — no large-matrices mixing of scales, no subtraction of near-equal numbers. The scalar gains and expected decrease can be read off the factors: \(p = Q_x + (Z_{uu}K)^\mathsf{T}(Z_{uu}d) + K^\mathsf{T}Q_u + Q_{xu}d\) and \(\Delta V = d^\mathsf{T}Q_u + \tfrac12 (Z_{uu}d)^\mathsf{T}(Z_{uu}d)\), keeping the same \(O(N(n^3 + m^3))\) cost as the standard pass.

Takeaway. As the AL loop demands large penalties, the backward pass’s conditioning degrades like \(\kappa(P) \sim \rho\); the square-root form iterates on \(S\) with \(\kappa(S) = \sqrt{\kappa(P)}\) using numerically stable QR/downdate operations, which is what lets ALTRO keep working at penalty magnitudes plain iLQR would choke on.

6Solution polishing: killing the slow tail

Motivation. Phase 1 gets you to constraint violations around \(10^{-3}\)–\(10^{-4}\) quickly, but AL-iLQR’s tail is slow — in the paper’s cartpole benchmark, Figure 1, plain AL-iLQR never reaches the target tolerance at all, while ALTRO with polishing converges to \(10^{-8}\) in roughly the same wall-clock time as a single IPOPT solve. The plateau in Figure 3(b) is the same phenomenon. Polishing trades the AL slow tail for a Newton projection onto the active-constraint manifold.

6.1 The projection problem

Collect the decision variables \(z = (x_0, u_0, \dots, u_{N-1}, x_N)\) and the active constraints \(\bar E(z) = 0\): the dynamics plus the equality constraints plus the currently-active inequalities (detected by the multipliers from phase 1). Phase 2 solves the minimum-norm problem

Polishing (thesis §6 / paper Alg. 2)
\[ \min_z\;\; \tfrac12\,\|z - \bar z\|_J^2 \qquad \text{s.t.}\quad \bar E(z) = 0, \qquad J = \mathrm{blockdiag}\big([\ell_1]_{xx}, [\ell_1]_{xu}, [\ell_1]_{ux}, [\ell_1]_{uu}, \dots, [\ell_N]_{xx}\big), \]

where the norm is weighted by the objective Hessian \(J\): among all points satisfying the constraints exactly, take the one nearest to the coarse solution in the cost’s notion of distance. Each Newton step on this problem is the projection map

\[ \delta z = -J^{-1}\bar E_z^{\mathsf{T}}\Big(\bar E_z\, J^{-1} \bar E_z^{\mathsf{T}}\Big)^{-1} \bar E(z), \]

followed by a backtracking line search on the constraint residual \(\|\bar E(z + \alpha\,\delta z)\|_\infty < \|\bar E(z)\|_\infty\). The big middle factorization \((\bar E_z J^{-1} \bar E_z^\mathsf{T})^{-1}\) is reused across steps and only refactored when convergence slows or the active set changes, and the chain structure of \(\bar E\) lets the whole procedure run sequentially without ever building the large matrices — keeping it embeddable.

Why this beats AL’s tail. AL drives violations down by escalating \(\rho\), which starves the inner problem of precision. Projection solves a least-squares-hit-the-constraint problem directly: once the active set is right, the exact solution of the linearized equality problem lands on the manifold, and the Newton iterations polish quadratically. In the paper’s benchmarks, constraint satisfaction goes from \(10^{-3}\) to \(10^{-8}\) “in a handful of iterations.”
Takeaway. ALTRO is two-stage by design: AL-iLQR for a robust coarse solve, then a Hessian-weighted active-set Newton projection that warms starts from it and snaps the constraints to machine precision — the combination is what makes both speed and accuracy possible.

7Two problem reformulations: infeasible starts and free time

7.1 Start from a state trajectory, not a control trajectory

Why. For direct methods it is trivial to hand a solver a state path (from a sampling planner or an expert sketch). For shooting methods the decision variables are controls, and finding a control sequence that produces the desired states is itself an optimal-control problem — a chicken-and-egg that historically made iLQR hard to initialize. ALTRO instead makes the system artificially fully actuated with slack controls \(s_k\):

Slack dynamics (paper eqs. 30–32)
\[ x_{k+1} = f(x_k, u_k) + s_k, \qquad s_k = \tilde x_{k+1} - f(\tilde x_k, \tilde u_k) \;\;\text{(initialized to match the given trajectory)}, \]

with an extra quadratic cost \(\tfrac12 \sum s_k^\mathsf{T} R_s\, s_k\) and constraints \(s_k = 0\). The given trajectory \(\tilde x\) makes the slacks start at zero; the dynamics are instantly “feasible,” and the AL machinery drives \(s_k \to 0\) in the limit, recovering a solution of the nominal system. The trajectory stays dynamically feasible (with slacks) at every iterate — anytime-usable even mid-solve.

7.2 Minimum-time (free-time) problems

Why. Many plans want “get there as fast as possible.” ALTRO encodes the time-step duration as a decision variable through its square root, \(\tau_k = \sqrt{\Delta t_k}\ge 0\), making it an input. The augmented dynamics and constraints

Free-time formulation (paper eqs. 33–34)
\[ \begin{bmatrix} x_{k+1} \\ \delta_{k+1} \end{bmatrix} = \begin{bmatrix} f(x_k, u_k, \tau_k) \\ \tau_k \end{bmatrix}, \qquad \text{cost: }\; \sum_k R_\tau\, \tau_k^2, \qquad \text{constraints: }\; \delta_k = \tau_k \]

where \(\delta_k\) is a carried state that must equal the input square root — this equality prevents the solver from exploiting discretization error by shrinking/expanding step sizes inconsistently. The paper’s car example plans a 5 s fixed-horizon trajectory; the free-time version finds a 2.2 s bang-bang plan with the same machinery.

Honest caveats from the paper. The free-time formulation is more sensitive to initialization than the fixed-horizon one, and infeasible-start initialization underdelivers if the initial penalty \(\rho\) is badly tuned — both are noted as design sensitivities in the paper’s limitations section.
Takeaway. Infeasible-state starts and free time are not new algorithms but reformulations — extra slack inputs or a time-step input — that hand the same iLQR+AL+projection machinery problems it can already solve.

8Where ALTRO fits: benchmarks, lineage, and limits

8.1 What the paper reports

ALTRO was benchmarked against direct collocation with SNOPT and IPOPT on a suite: a 1-D block move, pendulum, acrobot, cartpole, a Reeds–Shepp car (parallel park, obstacle avoidance, room escape), a 14-state Kuka iiwa arm, and a 13-state quadrotor maze. The headline numbers:

2–5× faster

than SNOPT/IPOPT on most benchmark problems, at equal or better constraint satisfaction (\(c_{\max} = 10^{-8}\), \(10^{-6}\) for time-penalized).

Anytime feasible

every iterate is dynamically feasible, so trajectories can be handed to a tracking controller mid-solve (once slacks are small).

Not every case wins

for time-penalized problems, direct transcription+DIRCOL does considerably better — the free-time reformulation trades away some robustness.

Warm-startable

for MPC-style single-update use, ALTRO needs good warm starts of the trajectory, multipliers, and penalties — the paper flags this as open future-work territory.

8.2 Lineage and relatives

ALTRO sits in a long family of constraint-handling DDP/iLQR methods: control-bound box constraints via per-step QPs (Tassa et al.), stage-wise constrained-QP backward passes (Xie & Duan; Lin; Lantoine & How’s hybrid), penalty methods (Farshidian et al.), and earlier AL-iLQR hybrids (Plancher et al.). The AL outer loop itself goes back to Hestenes and Powell’s augmented Lagrangian method of the 1960s. Immediate descendants and neighbors include ALTRO’s successor anymotion / AL-iLQR variants, the stochastic AL-iLQR line (chance constraints), and the closely-related Crocoddyl (a DDP-framework with its own constraint handling), while generic solvers like IPOPT/SNOPT remain the robust direct-method baseline.

8.3 Implementations

The reference implementation is Julia: Altro.jl (solver) on top of TrajectoryOptimization.jl (problem definitions, derivative evaluations via ForwardDiff.jl). The inner loop is designed to be allocation-free, and the paper emphasizes suitability for embedded deployment; the accompanying mini_altro.py in this folder is a from-scratch, dependency-light version of the same core.

8.4 The big picture

ALTRO is a case study in algorithm design by composition: a structure-exploiting inner solver, a general constraint layer, a numerical-conditioning repair, and a convergence accelerator, each independently simple and each earning its place. If you take one idea away beyond the mechanics, take the pattern: when a fast solver can’t handle constraints, don’t build a new solver — build a loop around it that lets a simple, provably convergent multiplier scheme do the constraining, then polish.

Takeaway. ALTRO earns its speed from iLQR’s structure, its generality from the augmented Lagrangian, its robustness from the square-root backward pass, and its accuracy from projected-Newton polishing — four ideas you now have from zero.