4. State-Space Description of a Dynamic System
Unlike a memoryless system, a dynamic system’s output depends on past inputs, not just the present one. State-space (modern control) representations capture exactly how much past information is needed, in a compact, general form.
Lecture videos
Section titled “Lecture videos”Slides
Section titled “Slides”PowerPoint handouts: State-Space Models (dark) · State-Space Models (light) · State-Space to Transfer Functions (dark) · State-Space to Transfer Functions (light)
Interactive example
Section titled “Interactive example”Mass-spring-damper state-space model
Section titled “Mass-spring-damper state-space model”Builds the state-space model (A, B, C, D) for a mass-spring-damper system with m=1, k=2, b=1, then converts it to a transfer function via ss2tf() to confirm it matches the closed-form G(s) = (1/m) / (s^2 + (b/m)s + (k/m)) derived by hand — the same model in two equivalent representations.
import control as ctimport numpy as np
m = 1k = 2b = 1A = np.array([[0, 1], [-k / m, -b / m]])B = np.array([[0], [1 / m]])C = np.array([1, 0])D = np.array([0])
sys = ct.ss(A, B, C, D) # state-space representationprint(sys)
sys_tf = ct.ss2tf(sys)print(sys_tf)Mass-spring-damper state-space model (mcimp/codes/ssdescription/msd.py)
Click "Run" to execute.
Vehicle steering: linearization accuracy
Section titled “Vehicle steering: linearization accuracy”A bicycle-model of vehicle steering is nonlinear in general, but near a straight-line equilibrium it can be linearized into a simple state-space model. This simulates both the true nonlinear system and its linearization under a 1 Hz sinusoidal steering input of increasing magnitude, and plots them together.
At small input magnitudes the two curves are nearly indistinguishable — the linearization is accurate near the equilibrium point. As the magnitude grows, the nonlinear and linearized responses visibly diverge, illustrating that a linearized model is only a local approximation, valid in a neighborhood of the point it was linearized around. (The book’s original example also sweeps input frequency at fixed magnitude; that second sweep is omitted here to keep the demo focused, but follows the identical pattern.)
import numpy as npimport matplotlibmatplotlib.use("Agg")import matplotlib.pyplot as pltimport control.matlab as ctfrom scipy.integrate import odeintimport io, base64
# Vehicle steering: bicycle model -- accuracy of linearizationa = 1.799 / 2 # length from rear wheels to center of massb = 1.799 # length of the carv_0 = 10 # initial velocity, m/s
def f(x, t, u): y, theta = x dydt = v_0 * np.sin(np.arctan(a * np.tan(u) / b) + theta) dthetadt = v_0 * np.sin(np.arctan(a * np.tan(u) / b)) / a return [dydt, dthetadt]
tspan = [0, 10]
# Linearized state-space model of the vehicle (output = position only)A = np.array([[0, v_0], [0, 0]])B = np.array([a * v_0 / b, v_0 / b]).reshape(-1, 1)C = np.array([1, 0])D = np.array([0])
# Reduced point count (vs. the book's 1000) keeps this fast enough to# re-run in the browser while still showing the same trend clearly.Ugain = [0.05, 0.1, 0.5, 1]t = np.linspace(tspan[0], tspan[1], 300)Y = np.zeros((len(t), len(Ugain)))Ylinear = Y.copy()
for ii in range(len(Ugain)): u = Ugain[ii] * np.sin(2 * np.pi * 1 * t) x0 = [0, 0] for jj in range(1, len(t)): x = odeint(f, x0, [t[jj - 1], t[jj]], args=(u[jj],)) x0 = x[1] Y[jj, ii] = x[1][0] Ylinear[:, ii], _, _ = ct.lsim(ct.ss(A, B, C, D), u, t, [0, 0]) print(f"gain={Ugain[ii]}: nonlinear max |y| = {np.max(np.abs(Y[:, ii])):.3f}, " f"linearized max |y| = {np.max(np.abs(Ylinear[:, ii])):.3f}")
fig, axs = plt.subplots(4, 1, figsize=(7, 9), sharex=True)for ii in range(len(Ugain)): axs[ii].plot(t, Y[:, ii], label="nonlinear model") axs[ii].plot(t, Ylinear[:, ii], "r--", label="linearized model") axs[ii].set_title(f"Input at 1 Hz, magnitude {Ugain[ii]} rad") axs[ii].set_ylabel("Position y (m)") axs[ii].grid(True)axs[0].legend(loc="upper left")axs[-1].set_xlabel("Time (s)")plt.tight_layout()
buf = io.BytesIO()plt.savefig(buf, format="png", dpi=90)plot_b64 = base64.b64encode(buf.getvalue()).decode()Vehicle steering: linearization accuracy (mcimp/codes/ssdescription/vehicle_steer_linear.py)
Click "Run" to execute.