Note Wisdom
These annotated notes for AA203 Lecture 6 break down indirect optimal control reformulation for free final‑time problems, walk through a particle example, and introduce direct methods, highlighting confusing spots and unresolved practical questions.
Institution: Stanford
Original Course: Stanford AA203 Optimal and Learning‑Based Control | Spring 2026 | Lecture 6: Direct Methods — Annotated Lecture Notes & Key Takeaways
Instructor Bio: Taught by Prof. Marco Pavone and Dr. Daniele Gammelli, with extensive research outputs on direct optimal control methods and their industrial applications.
Course Description: This lecture presents direct solution methods including collocation and sequential convex programming (SCP). It explains how to convert optimal control problems into numerical optimization tasks, and compares direct vs. indirect approaches.
These notes cover Lecture 6 of Stanford’s AA203 course, focused on Direct Methods. The session wraps up discussion on indirect optimal control approaches, walks through a practical coding example for free‑final‑time problems, and sets up the conceptual foundation for direct transcription. I’ve tried to capture what the instructor laid out, plus spots that felt confusing or needed extra mental unpacking for someone watching the recording.
The lecture opens by closing out indirect methods material. Indirect methods solve optimal control problems by first deriving mathematical optimality rules. Those optimality conditions turn the original control problem into a two‑point boundary‑value problem (BVP), which we then solve numerically. Up to this point in the course, students had worked with Python’s solve_bvp tool for abstract BVP setups. This lecture shifts to applying that exact solver to a real optimal control example (00:00‑01:22).
One big practical catch comes up immediately. Most off‑the‑shelf BVP solvers expect the problem to follow a “standard form”. A core assumption of this standard setup is that final time is fixed and known ahead of time. But many real‑world optimal control tasks have free final time, meaning end‑time is itself a decision variable we need the solver to figure out. That mismatch means we cannot just feed these problems straight to standard BVP software (01:23‑02:34).
The instructor mentions an older reference from the 1980s that collects many different problem‑rewriting “tricks” to cast non‑standard optimal control setups into forms compatible with classical solvers. He zeroes in on one of the most frequent use‑cases: handling free final‑time scenarios (02:04‑02:33).
The core fix shown is time rescaling. We introduce a normalized time variable τ (tau). Original real time t is written as t = τ · t_f. Here t_f is the unknown final time. By definition τ always runs from zero to one, no matter what value t_f ends up taking. This means our rescaled problem has a fixed final “time” equal to one, fitting the standard BVP expectation (02:59‑03:44).
Changing the time variable does not come for free. Through the chain rule, all system time derivatives need scaling by t_f. On top of that, we add a dummy state variable r whose derivative is zero. This dummy state represents our unknown final time t_f inside the state vector for the BVP solver. Because its derivative equals zero, r holds constant for the whole solution interval. Everywhere the original equations use t_f, we substitute r. This lets the numerical solver treat t_f as another unknown state to solve for alongside our physical states and costates (03:45‑05:17).
I found this section a little tricky on first pass. It is easy to mix up which variables belong to physical time versus normalized τ‑time. The instructor does not work through every single chain‑rule algebra step verbally. You have to accept that scaling derivatives by t_f comes from change‑of‑variables calculus, or work it out on scratch paper yourself. He promises a concrete example will illustrate every piece, which helps ground these somewhat abstract manipulations.
The example revisits a particle‑on‑a‑line problem covered in earlier lectures (05:37). The setup: particle starts at position x₁ = 10 with zero velocity x₂ = 0. It must reach origin position zero with zero velocity. The cost functional balances two terms: one penalizes total final time, another penalizes control effort. Final time here is free, not pre‑assigned. Previously the class derived an analytical closed‑form answer for this problem; now we will solve it numerically using indirect methods with solve_bvp (05:43‑06:33).
He quickly restates the optimality conditions built from the Hamiltonian. The second‑order particle dynamics get rewritten as first‑order ODE system: ẋ₁ = x₂, ẋ₂ = u. From constructing the Hamiltonian we get costate equations, plus the optimality condition for control, which lets us eliminate u and write it purely as function of costate p₂. We also get our boundary conditions: initial state constraints, terminal state constraints, plus the special extra boundary condition required for free final time (the Hamiltonian evaluated at final time equals zero for this problem). That extra condition supplies the missing equation needed because t_f is unknown (06:44‑12:14).
When implementing in code, we apply the time‑rescaling trick described earlier. Our state vector grows to include that dummy variable r representing t_f, with ṙ = 0. Every derivative in the whole ODE system multiplies by r (our stand‑in for t_f) because of τ time scaling. Boundary conditions get passed to solve_bvp as residual functions. The time grid we feed the solver now spans from zero to one, corresponding to normalized τ instead of physical time t (12:43‑14:24).
After supplying ODE function, boundary residuals, discretized time grid, and an initial guess for the full state/costate/dummy‑state trajectory, we run the solver. The numerical calculation outputs final‑time value 4.47, matching the previously‑computed analytical solution. We can also inspect state trajectories for x₁ and x₂ to confirm the particle starts at 10 and ends at zero with zero final velocity (14:25‑15:26).
This demonstration shows indirect methods in full practice. It is not just pencil‑and‑paper Pontryagin’s maximum principle. You have to restructure your problem to fit numerical software’s assumptions. One thing the lecture glosses over is picking an initial guess for the trajectory. Bad guesses can make BVP solvers fail to converge, yet the example does not discuss guess‑tuning strategies. That feels like a real‑world gap left for students to discover on their own.
Once the example finishes, the instructor gives a high‑level recap of indirect methods. Historically, indirect approaches were where optimal control as a field got its start. The workflow is “optimize, then discretize”: first derive all continuous‑time optimality conditions analytically, then hand those resulting two‑point BVP equations to numerical solvers. The solver internally discretizes time to compute a numerical solution (15:43‑16:31).
Indirect methods have meaningful strengths. When things work out, you can end up with an analytical control law. If you have an analytic solution, real‑time computation reduces to evaluating a function, which is very fast. Even when full closed‑form solutions are impossible, you can often deduce structural properties of optimal control profiles, like bang‑bang control. These structural insights are helpful for system analysis and design work (16:14‑16:49).
Even so, within robotics practice direct methods keep growing more popular. That does not mean indirect methods are obsolete, just that community emphasis has shifted (16:50‑16:56).
One point I wondered about: the instructor does not go deep on indirect method weaknesses beyond the need for problem reformulation tricks. Common pain points like costate guess sensitivity, handling hard state constraints, or convergence fragility get only passing mention. He moves swiftly onward to introduce direct methods.
Direct methods flip the order of operations compared to indirect methods. Indirect: derive optimality first, discretize second. Direct methods take the original continuous‑time optimal control problem and discretize time first. After discretization, the whole problem becomes a finite‑dimensional constrained nonlinear optimization problem. You feed this nonlinear program to a generic nonlinear optimization solver and hope it spits out a solution (18:11‑19:27).
The instructor lays out the general problem statement: we have a cost functional to minimize, system dynamics, initial state, terminal state lying on some manifold defined by function f’s zero level set, and potential control constraints. For simplicity in this lecture he sets terminal cost to zero and sets initial time t₀=0, though he notes those can be added back without huge hassle (17:30‑18:10).
The rising adoption of direct methods in robotics ties to major progress in nonlinear optimization algorithms over recent years. These improvements make solving these large‑scale transcribed problems practical, even for near‑real‑time applications (19:28‑19:44).
He notes that direct transcription approaches can be split into two main families. The dividing line between families is how you carry out transcription, the step that converts continuous‑time control problem into finite‑dimensional nonlinear optimization (19:57‑20:14). At the point where the lecture transcript cuts off, he is about to unpack those two families, so we do not get details in this recording snippet.
There are several open threads left hanging by the end of this segment.
All contents below are exclusive to the paid Word file, NOT available on this web page

