RobotForge
Published·~18 min

Model predictive control (MPC): when and why

Every control tick, solve an optimization over the next N timesteps, apply the first action, repeat. The controller that took over autonomous driving, humanoid gait, and drone racing.

by RobotForge
#control#mpc#optimization

PID reacts. LQR plans one-step. MPC plans the next N steps, every tick, and can respect hard constraints along the way. That's why MPC runs in autonomous cars, modern quadruped gaits, drone racers, and humanoid whole-body control. Here's the mental model and the minimal working implementation.

The core idea

  1. At time , measure the state .
  2. Solve: minimize cost over the next timesteps, subject to the dynamics and constraints.
  3. Apply only the first control action.
  4. Advance one tick. Repeat.

The solved plan is thrown away except for its first action. Feels wasteful; isn't — it's the mechanism that gives MPC feedback (each tick re-plans with fresh state).

time t t+N prediction horizon (N steps) xₜ apply uₜ planned (discarded) At t+1: plan new horizon, apply first step, repeat.
Every tick, MPC plans a full N-step trajectory (dashed) but only commits to the first action (solid). Next tick, the horizon shifts forward — 'receding horizon.'

The optimization

In mathematical form:

Read in plain English:

  • Minimize: stage cost (tracking + control effort) plus a terminal cost .
  • Subject to: the dynamics (next state = f of current state and action) and path constraints (joint limits, collision, obstacle avoidance).

If is linear and there are no constraints, you recover LQR exactly. MPC generalizes by allowing nonlinear dynamics and real constraints — at the cost of solving a fresh optimization every tick.

What MPC buys you over LQR

  • Hard constraints. "Joint 3 stays under 170°." "Motor current stays under 8A." "Do not collide with this object." LQR can't enforce them. MPC treats them as inequalities the solver respects.
  • Nonlinear dynamics. Linearize locally for linear MPC, or use nonlinear solvers (SQP, interior point) for full nonlinear MPC.
  • Reference-aware planning. MPC sees the reference trajectory ahead — LQR only sees the current error. For following a curved path, this matters a lot.
  • Anticipation. For slow-responding plants (industrial processes, heavy vehicles), MPC can start reacting before the disturbance hits the output.

What MPC costs you

  • Computation. Solving an optimization every tick. Must finish before the next tick starts, or your robot misses a control cycle.
  • Model dependence. Bad → bad plans. You need a half-decent model of dynamics.
  • Complexity. More gains to tune: Q, R, terminal P, horizon N, solver tolerance, maybe soft-constraint weights.

Practical implementation with CasADi

For nonlinear MPC in Python, CasADi is the standard tool. It builds symbolic problems, compiles them to C, and calls IPOPT or QP solvers.

import casadi as ca
import numpy as np

N = 20           # horizon
dt = 0.05
nx, nu = 4, 1    # e.g., cart-pole

opti = ca.Opti()
x = opti.variable(nx, N+1)
u = opti.variable(nu, N)
x0 = opti.parameter(nx)

Q = np.diag([10, 1, 100, 1])
R = np.diag([0.1])
opti.minimize(sum((x[:, k].T @ Q @ x[:, k]
                   + u[:, k].T @ R @ u[:, k]) for k in range(N)))

# dynamics (example: your cart-pole f(x,u))
for k in range(N):
    opti.subject_to(x[:, k+1] == x[:, k] + dt * cart_pole(x[:, k], u[:, k]))

opti.subject_to(x[:, 0] == x0)
opti.subject_to(opti.bounded(-5, u, 5))   # force limit

opti.solver('ipopt')

# Online: each tick, set x0, solve, take u[:,0], discard rest
opti.set_value(x0, current_state())
sol = opti.solve()
u_apply = sol.value(u[:, 0])

That template handles 90% of small-scale MPC problems. Swap in your dynamics; tune Q, R, N.

Rule-of-thumb horizon N

  • Too short: controller is myopic, can't anticipate.
  • Too long: problem gets huge, solver slow, numerical issues.
  • Start with N covering 0.5–2 seconds of motion. Tune up if the controller looks short-sighted.

When to reach for MPC

  • You have real constraints that must never be violated.
  • Your system is nonlinear enough that LQR linearization breaks down.
  • You have a reference trajectory the controller should track with anticipation (autonomous driving, path following).
  • You can afford the computation budget (modern solvers handle 20-step horizons at 100 Hz easily).

When to not

  • Single-input systems with no constraints — PID is fine.
  • Systems where your dynamics model is wildly wrong — MPC will confidently execute wrong plans.
  • Hard real-time at >1 kHz with nonlinear dynamics — you'll run out of budget. Use cascaded control (MPC outer loop @ 100 Hz, LQR inner loop @ 1 kHz).

Next

Feedback linearization — a control trick for specific nonlinear systems that's often more elegant than MPC when applicable.

Comments

    Sign in to post a comment.