Computing Library › Worked Examples
Worked Examples

PID vs LQR on a Mass-Spring

Control a damped mass-spring to a setpoint with a tuned PID loop and with an optimal LQR gain, and compare the closed-loop behavior.

Problem

A mass-spring-damper is the canonical second-order plant. We regulate its position to a target using two controllers: a hand-tuned PID and a linear-quadratic regulator (LQR) that minimizes a weighted sum of state error and control effort. Comparing them shows the difference between heuristic and optimal design.

Plant and LQR gain

Kronos motion — closed loop

State is position and velocity. The LQR solves the algebraic Riccati equation to find the gain K that minimizes integral of x'Qx + u'Ru. PID instead sums proportional, integral, and derivative terms of the error with gains chosen by tuning rules.

python
import numpy as np
from scipy.linalg import solve_continuous_are
m,k,c=1.0,1.0,0.4
A=np.array([[0,1],[-k/m,-c/m]]); B=np.array([[0],[1/m]])
Q=np.diag([10,1]); R=np.array([[1.0]])
P=solve_continuous_are(A,B,Q,R)
Klqr=np.linalg.inv(R)@B.T@P
print('LQR gain',np.round(Klqr,3))
eig=np.linalg.eigvals(A-B@Klqr)
print('closed-loop poles',np.round(eig,3))  # damped, stable

Comparison

The LQR gain places the closed-loop poles for a fast, well-damped response and guarantees stability given a controllable plant. A PID can match the settling time but requires manual balancing of overshoot against integral windup, and it has no built-in optimality. LQR extends to many coupled states where PID tuning becomes intractable.