Problems · Problem 7 · Control · Hard
Model predictive control
Plan the next 0.4 s with the motor's limit built in, apply the first push, and plan again: the cart moves 15 cm with a 0.8 N motor where LQR crashes.
Builds on Optimisation: gradient descent, from the free Foundations.
Write and run this problem in the simulator with ProWhat it computes
LQR assumes the motor delivers whatever it asks for. This motor gives at most 0.8 N; LQR's first request on this 15 cm move is 3.5 N. Model predictive control puts the limit into the problem: every period it plans the next inputs subject to |u_k| \le u_\max, applies , and plans again.
Condensing
Work with the error . The target is an equilibrium, so , and stacking the next errors gives :
Let , where the terminal weight is LQR's cost-to-go. The cost is then twice , plus a constant, with
Projected gradient
Clipping projects onto the box, so: step down the gradient ( is 's largest eigenvalue), clip, repeat.
def solve_box_qp(H, g, u_max, U0, iters):
U = U0
repeat iters times:
U = clip(U - (H @ U + g) / L, -u_max, u_max)
every period: # mpc(x, x_ref)
g = F @ (x - x_ref)
plan = solve_box_qp(H, g, u_max, last plan shifted one period, 100)
apply plan[0]
The last plan, shifted one period, is nearly optimal already, so 100 iterations per period are enough.
Tools
np.linalg.matrix_power, np.kron(np.eye(N), Q), np.linalg.eigvalsh(H)[-1] (the largest eigenvalue) and np.clip.
The program
LQR drives the cart for 2 s, then the cart is reset and your mpc runs for 5 s. H, F = condense(A, B, Q, R, P, N) is built once, and the global plan (zeros at first) holds mpc's latest plan.
Your task
Implement condense, solve_box_qp and mpc. The grader compares the first two with the reference, then checks that MPC reaches the target without the pole leaning past 10°, touching a stop or asking for more than 0.8 N.