Tutorials / Inverted Pendulum Modeling and Control

Inverted Pendulum Modeling and Control

June 6, 2026 · Updated June 15, 2026

inverted pendulumLQRpole placementstate feedbackÅströmlinearizationPID tuning

Prerequisites

  • Linear algebra: matrix exponential, controllability
  • Basic control: state-space form x˙=Ax+Bu\dot{x} = Ax + Bu, eigenvalues
  • python-control ≥ 0.10 and scipy
  • Helpful but not required: read Getting Started with PID Tuning first

1. The cart-pole, fully assembled

A cart of mass MM slides on a horizontal rail. Let pp denote the cart’s horizontal position along the rail (positive to the right, p=0p = 0 at the rail’s center). A pole of mass mm and length 2l2l (so the center of mass, CoM, is at distance ll from the pivot) is hinged on top of the cart. A horizontal force FF is applied to the cart. The pole angle θ\theta is measured from the upright, positive in the fall-right direction. Viscous friction coefficients bcartb_{\text{cart}} and bpivotb_{\text{pivot}} resist motion in the cart and at the pivot. The simulator uses the same symbol pp for the cart position state.

Choosing q=(p,θ)q = (p, \theta) as the generalized coordinates and applying the Euler–Lagrange equations (Lagrange’s equations of the second kind)

ddt ⁣(Lq˙i)    Lqi  =  Qi,L=TV\frac{d}{dt}\!\left(\frac{\partial \mathcal{L}}{\partial \dot q_i}\right) \;-\; \frac{\partial \mathcal{L}}{\partial q_i} \;=\; Q_i, \qquad \mathcal{L} = T - V

with TT the kinetic energy, VV the potential energy, and QiQ_i the generalized non-conservative forces (here: the applied force FF on q1=pq_1 = p and the friction torques on q2=θq_2 = \theta), gives the standard cart-pole mass matrix. With the notation in Åström & Murray, Feedback Systems (2008), eq. (2.9)/(3.9), where the angle is measured from the downward vertical with positive θ\theta counter-clockwise:

(M+mmlcosθmlcosθJt)(p¨θ¨)+(cp˙+mlθ˙2sinθγθ˙mglsinθ)=(F0)\begin{pmatrix} M + m & -ml\cos\theta \\ -ml\cos\theta & J_t \end{pmatrix} \begin{pmatrix} \ddot{p} \\ \ddot{\theta} \end{pmatrix} + \begin{pmatrix} c\dot{p} + ml\dot{\theta}^2\sin\theta \\ \gamma\dot{\theta} - mgl\sin\theta \end{pmatrix} = \begin{pmatrix} F \\ 0 \end{pmatrix}

Sign convention. This tutorial, and the simulator, measure θ\theta from the upright instead, with θ>0\theta > 0 meaning the pole is falling to the right. The two conventions differ by θbook=πθsim\theta_{\text{book}} = \pi - \theta_{\text{sim}}, so the off-diagonal signs and the gravity term look different. Near the unstable equilibrium, however, both give the same linearized coupled equations shown below.

For the rest of this tutorial we set c=γ=0c = \gamma = 0 (no friction) to match the textbook’s cleanest form, and use the point-mass moment of inertia Jt=ml2J_t = ml^2 (a uniform rod about its end would give Jt=13ml2J_t = \tfrac{1}{3}ml^2, but the simpler form is what the simulator integrates). Linearizing near the upright equilibrium (θθsim0\theta \approx \theta_{\text{sim}} \approx 0, equivalently θbookπ\theta_{\text{book}} \approx \pi) gives the two coupled equations used in §2:

(M+m)p¨+mlθ¨=F(M + m)\ddot p + ml\,\ddot\theta = F mlp¨+ml2θ¨=mglθml\,\ddot p + ml^2\,\ddot\theta = mgl\,\theta

(See the simulator’s equations-of-motion section for the pre-solved implementation form with friction; the simulator follows Spong, Hutchinson, & Vidyasagar, Robot Modeling and Control (Wiley, 2006), eq. 5.6–5.7, which is algebraically equivalent to the above after pre-solving for the accelerations.)

2. Linearize at the upright

The upright is an equilibrium: θ=0\theta = 0, θ˙=0\dot\theta = 0, p˙=0\dot p = 0, F=0F = 0. We want to know what happens for small perturbations. The two linearized coupled equations from the end of §1 already contain the answer; here we solve them for the individual accelerations. Substitute sinθθ\sin\theta \to \theta, cosθ1\cos\theta \to 1, and drop the θ˙2\dot\theta^2 (quadratic in small quantities) terms, then solve for p¨\ddot p and θ¨\ddot\theta:

p¨=mgMθ+1MF\ddot p = -\frac{mg}{M}\,\theta + \frac{1}{M}\,F θ¨=g(M+m)Mlθ1MlF\ddot\theta = \frac{g(M + m)}{Ml}\,\theta - \frac{1}{Ml}\,F

The linearized state-space form x˙=Ax+Bu\dot x = Ax + Bu:

A=(001000010mgM000g(M+m)Ml00),B=(001/M1/(Ml))A = \begin{pmatrix} 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ 0 & -\dfrac{mg}{M} & 0 & 0 \\ 0 & \dfrac{g(M + m)}{Ml} & 0 & 0 \end{pmatrix}, \qquad B = \begin{pmatrix} 0 \\ 0 \\ 1/M \\ -1/(Ml) \end{pmatrix}

For the canonical Åström values M=2,  m=0.2,  l=0.5,  g=9.81M = 2,\; m = 0.2,\; l = 0.5,\; g = 9.81:

A=(0010000100.98100021.58200),B=(000.51.0)A = \begin{pmatrix} 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ 0 & -0.981 & 0 & 0 \\ 0 & 21.582 & 0 & 0 \end{pmatrix}, \qquad B = \begin{pmatrix} 0 \\ 0 \\ 0.5 \\ -1.0 \end{pmatrix}

Open-loop eigenvalues

eig(A)={0,  0,  +4.646,  4.646}\text{eig}(A) = \{0,\; 0,\; +4.646,\; -4.646\}

The +4.646+4.646 rad/sec eigenvalue is the falling-pole instability. Two zero eigenvalues correspond to the cart’s position being a free state (no spring pulling it back to zero) and the angle-rate being the derivative of the angle. With this single unstable mode, the reachability matrix [B,  AB,  A2B,  A3B][B,\;AB,\;A^2B,\;A^3B] has full rank — the system is controllable. Good.

2.2. Same physics, different coordinates: Ex 2.2 vs Ex 9.6

The two presets on the simulator’s preset bar — Ex 2.2 and Ex 9.6 — come from Åström & Murray, Feedback Systems (2008): Example 2.2 in §2.2 gives the finite-mass cart-pole state-space form, and Example 9.6 in §9.6 (also previewed in §8.3) gives the massless-pivot normalized transfer-function form. They look very different (different masses, different default gains, very different time scale) but they are the same cart-pole equation in two different unit systems. The simulator’s 4-state nonlinear equations of motion (EoM, Spong eq. 5.6–5.7, point-mass pole with I=ml2I = ml^2) is integrated in both cases. The presets only change the slider values of (M,m,l,bcart,bpivot)(M, m, l, b_{\text{cart}}, b_{\text{pivot}}).

Linearized about the upright, frictionless, the theta-channel of either preset reduces to a single-input single-output plant:

Θ(s)F(s)  =  1Mls2(M+m)g\frac{\Theta(s)}{F(s)} \;=\; \frac{1}{Ml\,s^2 - (M+m)g}

with one open-loop pole on the right-half plane at

s  =  +(M+m)gMl(rad/sec)s \;=\; +\sqrt{\frac{(M+m)\,g}{M\,l}} \quad \text{(rad/sec)}

Plug in the two presets’ slider values and the open-loop pole is at very different rad/sec:

PresetMM, mm, llMlMl(M+m)g(M+m)gOpen-loop pole
Ex 2.20.5, 0.2, 0.30.156.867±6.77 rad/sec (≈ 1.1 Hz)
Ex 9.60.001, 1, 10.0019.821±99.1 rad/sec (≈ 15.8 Hz)

The Ex 9.6 plant is ~15× faster than Ex 2.2 in raw time. That’s the only intrinsic difference between the two as far as the linearized theta-channel goes.

Where does the 15× come from? It is a change of frequency unit, not a change of physics. Start from the linearized transfer function and factor out (M+m)g(M+m)g:

Θ(s)F(s)  =  1(M+m)g[Ml(M+m)gs21]  =  1(M+m)g[s2ωunstable21]\frac{\Theta(s)}{F(s)} \;=\; \frac{1}{(M+m)g\,\left[\dfrac{Ml}{(M+m)g}\,s^2 - 1\right]} \;=\; \frac{1}{(M+m)g\,\left[\dfrac{s^2}{\omega_{\text{unstable}}^2} - 1\right]}

where the unstable open-loop pole is ωunstable=(M+m)g/(Ml)\omega_{\text{unstable}} = \sqrt{(M+m)g/(Ml)} as above. Now define a normalized Laplace variable

σ  =  sωunstable\sigma \;=\; \frac{s}{\omega_{\text{unstable}}}

Substitute s=ωunstableσs = \omega_{\text{unstable}}\,\sigma into the transfer function:

Θ(σ)F(σ)  =  1(M+m)g(σ21)\frac{\Theta(\sigma)}{F(\sigma)} \;=\; \frac{1}{(M+m)g\,\left(\sigma^2 - 1\right)}

The denominator σ21\sigma^2 - 1 is dimensionless and has poles at σ=±1\sigma = \pm 1, independent of MM, mm, ll. That is the unit system Åström & Murray use in Feedback Systems, §8.3 and §9.6 (Example 9.6), when they write P(s)=1/(s21)P(s) = 1/(s^2-1) with the cart on a massless pivot. It is not different physics — it is the same linearized plant, but frequencies are measured in units of ωunstable\omega_{\text{unstable}} instead of rad/sec.

Equivalently, in the time domain the normalized time is τ=ωunstablet\tau = \omega_{\text{unstable}}\,t; the relationship s=ωunstableσs = \omega_{\text{unstable}}\,\sigma is exactly the Laplace property that a 1rad1\,\text{rad} frequency in the τ\tau-domain corresponds to ωunstablerad/sec\omega_{\text{unstable}}\,\text{rad/sec} in the real-time domain. The 15× factor is simply ωunstable, Ex 9.6/ωunstable, Ex 2.299.1/6.7714.6\omega_{\text{unstable, Ex 9.6}} / \omega_{\text{unstable, Ex 2.2}} \approx 99.1 / 6.77 \approx 14.6.

Consequence for tuning. The 15× speed difference is an interesting fact about the two textbook parameter sets, but it is not a useful design rule. In practice, the simulator’s PID gains are found by trial and error: sweep Kp×KdK_p \times K_d on the nonlinear plant and pick the corner of the basin that keeps the pole upright without saturating the cart force. A gain set that works on Ex 2.2 will not, in general, transfer to Ex 9.6, because the two presets differ in cart friction bcartb_{\text{cart}} and the simulator integrates the full 4-state nonlinear plant — not the 2-state linearization the dimensionless ratios assume. For a reliable design, use the State Feedback mode described in §3, which places all four closed-loop poles exactly where you want them.

2.3. Why classical PID tuning doesn’t work here

If you came here from a process-control background, your first instinct will be to reach for Ziegler–Nichols (ZN) tuning of a proportional–integral–derivative (PID) controller (or one of its relatives: Cohen–Coon, Tyreus–Luyben, integral of time-weighted absolute error, ITAE). The honest answer is that none of these methods give a useful starting point for the cart-pole, and the simulator’s PID defaults are empirically tuned (a 2D sweep of Kp×KdK_p \times K_d on the nonlinear plant), not derived from any analytical tuning rule. Three structural reasons:

  1. The plant has a pole in the right-half plane (RHP). ZN and friends assume the open-loop plant is stable — they find a gain where the loop oscillates, then back off to 30–60% of that. With an unstable open loop, the closed-loop system doesn’t oscillate; it diverges monotonically. The proportional-gain-at-sustained-oscillation that ZN presumes simply doesn’t exist.

  2. Linearized-model PID doesn’t transfer to the nonlinear plant. The textbook “design on the linearization, then trust the result” pipeline (Ex 9.6, Ex 2.2 in their linearized form, or any P(s)P(s) derived from the Jacobian at the upright) gives gains that stabilize the 2-state linearized plant P(s)=1/(Mls2(M+m)g)P(s) = 1/(M l\,s^2 - (M+m)g), not the simulator’s full 4-state nonlinear cart-pole. Three failure modes show up once the linearization breaks down:

    (a) The θ/ω\theta/\omega-only feedback stabilizes the inner unstable pole pair but does not move the cart-position eigenvalues. With bcart=0b_{\text{cart}} = 0 the linearized 4-state has eigenvalues {0,0,+6.77,6.77}\{0, 0, +6.77, -6.77\} rad/sec on the Ex 2.2 plant — the two imaginary-axis poles are the cart-position double integrator, and any tiny numerical force eventually excites the runaway mode. The Åström Ex 9.6 k=2k=2 design (Kp=4,Kd=2K_p = 4, K_d = 2 in the simulator’s F=KpθKddfF = K_p\theta - K_d\,d_f form) is the canonical example: stable on the massless-cart P(s)=1/(s21)P(s) = 1/(s^2-1), but degrades badly on the simulator’s finite-mass force-input plant.

    (b) The linearization drops the ω2sinθ\omega^2 \sin\theta term in the cart equations of motion (EOM) and the sinθ\sin\theta vs θ\theta terms in the moment equation. These dominate when θ\theta is a few degrees off vertical — i.e. exactly when the controller needs to be working hardest. A PID designed for the linear plant can saturate the control effort on the nonlinear plant even with the “same” gains.

    (c) The force saturation ±Fmax\pm F_{\max} is absent from every linear design. The simulator clamps FF at ±30\pm 30 N by default, which limits the closed-loop bandwidth in ways the Bode plot can’t see.

    Net effect: a PID that looks clean on a Bode plot of the linearized plant can be either too weak (the cart still drifts because the linearization ignored the cart-position mode) or too strong (saturates FmaxF_{\max} on the nonlinear plant) on the actual simulator. The closed-loop response of the nonlinear plant is not what the linear analysis predicts. The two views — Bode plot on the linearization, time response on the nonlinear plant — do not agree, and the time response is the one that matters for the actual physical cart-pole.

What the simulator’s PID defaults are, then. The defaults Kp=30K_p = 30, Ki=0K_i = 0, Kd=0.5K_d = 0.5, N=20N = 20 (and the Åström Ex 2.2 / Ex 9.6 presets’ Kp=200,Kd=5K_p = 200, K_d = 5 and Kp=25,Kd=1K_p = 25, K_d = 1 respectively) are all from a 2D sweep of Kp×KdK_p \times K_d on the nonlinear plant, picking the corner of the basin that gave the best peak-θ\theta + settle-time trade-off. They are empirical starting points, not derived answers. The §4 walkthrough tells you how to verify them and tune further by hand. In other words, the simulator’s PID gains are trial and error on the nonlinear plant — they work for the parameter set they were swept over, and they transfer only loosely to a different MM, mm, ll, bcartb_{\text{cart}} slider setting.

The clean alternative: state feedback. For a controllable linear system with one unstable mode, the right design method is state feedback (SF) — pick the four closed-loop poles and solve for KK via Ackermann (§3.1), or pick a cost function and solve for KK via linear quadratic regulator (LQR) design (§3.2). Both give a gain that actually stabilizes the full 4-state plant (including the cart-position mode), with predictable closed-loop behavior. Unlike the proportional–integral–derivative (PID) loop on θ, the state-feedback gain is not empirical: KK is the exact solution of ABK=A - BK = desired closed-loop dynamics (Ackermann) or the minimizer of a cost functional (xTQx+uTRu)dt\int (x^T Q x + u^T R u)\,dt (LQR), so the closed-loop poles are where you put them, not where the 2D sweep happened to land. This is the recommended path for any design beyond “scalar proportional–derivative (PD) on θ, cart drifts a bit”.

3. State feedback design

The classical fix for a controllable linear system with one unstable mode is to put all four closed-loop poles in the open left-half plane (LHP). The subsections below cover the two standard ways to pick the gain, and how to load the result into the simulator:

3.1. Pole placement (Ackermann)

Pick the four desired closed-loop poles. A reasonable starting point for “moderately damped, a few seconds settling time” is:

import numpy as np
from scipy.signal import place_poles

M, m, l, g = 2.0, 0.2, 0.5, 9.81
A = np.array([
  [0, 0, 1, 0],
  [0, 0, 0, 1],
  [0, -m*g/M, 0, 0],
  [0, g*(M+m)/(M*l), 0, 0],
])
B = np.array([[0], [0], [1/M], [-1/(M*l)]])

# Two slow poles for the (cart-position) integrator-like behavior
# and two faster poles for the (pole-angle) unstable mode.
desired = np.array([-1.5 + 0.5j, -1.5 - 0.5j, -3.0 + 1.5j, -3.0 - 1.5j])
K = place_poles(A, B, desired).gain_matrix
print(K)
# K = [[ -2.87, -54.77,  -4.97,  -11.48 ]]

The sign of each gain matters. The four entries of KK multiply (p,θ,p˙,θ˙)(p, \theta, \dot p, \dot\theta)^\top — so K0<0K_0 < 0 means “if the cart is too far right, push it left” (regulate p0p \to 0), K1<0K_1 < 0 means “if the pole is leaning right, push the cart right to get under it” (regulate θ0\theta \to 0), and so on.

In-browser Ackermann. The simulator’s State Feedback mode has a sub-radio for “design method” — pick Ackermann instead of LQR and four eigenvalue sliders appear (range [100,1][-100, -1], all real). Drag them to your desired pole locations and the page runs the Ackermann formula in your browser (~0.1 ms) to produce KK and the four resulting closed-loop poles. The same K readout and closed-loop pole display update live, so you can iterate visually. See §3.3 for the walk-through.

3.2. Linear quadratic regulator (LQR)

The linear quadratic regulator (LQR) finds the gain KK that minimizes 0(xQx+uRu)dt\int_0^\infty (x^\top Q x + u^\top R\, u)\, dt for a chosen weighting. Pick QQ to penalize what you care about (pole angle is usually the priority) and RR to penalize control effort. For the canonical plant (M=2M = 2, m=0.2m = 0.2, l=0.5l = 0.5, bcart=0.1b_{\text{cart}} = 0.1, g=9.81g = 9.81):

import numpy as np
from scipy.linalg import solve_continuous_are

M, m, l, g, b = 2.0, 0.2, 0.5, 9.81, 0.1
A = np.array([
  [0, 0, 1, 0],
  [0, 0, 0, 1],
  [0, -m*g/M, -b/M, 0],
  [0,  g*(M+m)/(M*l), 0, 0],
])
B = np.array([[0], [0], [1/M], [-1/(M*l)]])

Q = np.diag([1, 50, 1, 1])   # weight θ heavily
R = np.array([[0.05]])        # small control effort
P = solve_continuous_are(A, B, Q, R)
K_lqr = np.linalg.solve(R, B.T @ P)
print(K_lqr)
# K_lqr = [[ -4.47, -87.29, -8.94, -18.44 ]]

LQR guarantees closed-loop stability and a guaranteed gain/phase margin. It’s almost always a better starting point than pole placement. The four closed-loop eigenvalues of ABKA - BK for these gains are

{0.94±0.48j, 6.05±1.78j}\{-0.94 \pm 0.48\,j,\ -6.05 \pm 1.78\,j\}

(both pairs stable, damping ratios ζ0.89\zeta \approx 0.89 and ζ0.96\zeta \approx 0.96 — well-damped, fast enough).

Q and R are the design knobs; K is the answer. LQR is one of the few control methods where you don’t pick the gain directly — you pick a cost function (Q penalizes state error, R penalizes control effort) and K=R1BPK = R^{-1} B^\top P falls out of the algebraic Riccati equation (ARE). The simulator exposes this via the State Feedback controller mode in the Controller card. Switch the mode to State Feedback, leave the SF design method at LQR (the default), and drag Qp,Qθ,Qv,QωQ_p, Q_\theta, Q_v, Q_\omega or RR — the page solves the ARE in your browser and shows you the resulting KK and the four closed-loop eigenvalues live, so you can see the cost-to-gain-to-pole pipeline without doing any matrix math by hand. See §3.3 for the in-browser walk-through.

3.3. Using the 4-state gain in the simulator

The simulator’s State Feedback mode implements the F=(Kxp+Kθθ+Kvv+Kωω)F = -(K_x p + K_\theta \theta + K_v v + K_\omega \omega) control law directly. Switching from PID to SF is a one-click toggle under the “Controller mode” radio. Inside SF mode, a second “SF design method” radio picks LQR (Q, R weight sliders) or Ackermann (4 closed-loop eigenvalue sliders); the K readout and the four closed-loop eigenvalues update live for whichever method is active. Two practical workflows:

Design by Ackermann, in browser.

  1. Open the simulator, switch the controller mode to State Feedback, then pick Ackermann (eigenvalue assignment) under the SF design method radio. The page shows four eigenvalue sliders (λ1,λ2,λ3,λ4\lambda_1, \lambda_2, \lambda_3, \lambda_4) with default values {1,2,3,4}\{-1, -2, -3, -4\} (all real, in the left-half plane, LHP).
  2. Drag the sliders to your desired pole locations. The page runs the Ackermann pole-placement formula in your browser (~0.1 ms) to produce KK, and the four closed-loop eigenvalues + the K readout update live as you drag. The K readout panel at the top of the SF section always shows the current KK and the closed-loop poles, regardless of which design method produced them.
  3. For complex closed-loop poles (the ζ=0.707\zeta = 0.707 case from §3.1’s “moderately damped” example with P={1.5±0.5j,3.0±1.5j}P = \{-1.5 \pm 0.5j, -3.0 \pm 1.5j\}), the simulator currently only supports the 4-real case via the slider UX. Compute the equivalent 4-real pole set (e.g. project the complex pair to the real axis with the same real part: P={1.5,1.5,3.0,3.0}P' = \{-1.5, -1.5, -3.0, -3.0\}) and type those into the sliders. The resulting KK will be different from the complex- pole design but still stabilize the plant.
  4. Press Start. The pole stabilizes in ≈1.5 s, the cart comes to rest near origin.
  5. To go faster, drag all four eigenvalues more negative. To reduce ringing, place two of them near each other to create a complex pair (the “dominant” pair; the integrator in the 4-state plant gives the other two natural resonance).

Design by LQR in the browser.

  1. Switch the controller mode to State Feedback, then pick LQR (Q, R weights) under the SF design method radio (this is the default; the LQR State Feedback preset button on the page selects it for you).
  2. Drag the Q, R sliders to taste. The page solves the continuous-time algebraic Riccati equation (~1–5 ms) on every change to produce KK and the four closed-loop poles. As you move QθQ_\theta up, the closed-loop poles migrate further left; drag RR up and the controller becomes more conservative.
  3. Click the State Feedback preset to load the canonical plant (M=2, m=0.2, l=0.5, b_cart=0.1) with the §3.2 LQR weights. The closed-loop poles will land at {0.94±0.48j, 6.05±1.78j}\{-0.94 \pm 0.48j,\ -6.05 \pm 1.78j\}, all in the LHP.

Sign convention. All four KK values in the readout are negative to zero. A negative KθK_\theta means “if the pole is leaning right, push the cart right” (the stabilizing direction). The LQR cost function guarantees a stabilizing KK for any Q0Q \succeq 0 and R>0R > 0 on a stabilizable plant, so the readout should always be negative when the ARE is well-posed.

4. Take it to the simulator

The simulator now ships three preset buttons:

  • Åström Ex. 2.2 — the full state-space form with scalar PD on θ, ω only (Åström & Murray, Feedback Systems, §2.2 Example 2.2). Pole stays upright, cart drifts (see §1).
  • Åström Ex. 9.6 — the normalized transfer-function form with the massless-cart assumption (Åström & Murray, Feedback Systems, §9.6 Example 9.6). The textbook controller for this plant is C(s)=k(s+2)C(s) = k(s+2) with k=2k = 2, but the simulator uses empirical PD gains Kp=25K_p = 25, Kd=1K_d = 1 (not the textbook’s Kp=4K_p = 4, Kd=2K_d = 2 — the textbook design assumes a massless cart with acceleration input; the simulator integrates a 4-state force-input plant and the textbook’s C(s)=2(s+2)C(s) = 2(s+2) doesn’t stabilize it). See the comment in the click handler and §2.3 for why. The cart doesn’t drift because bcart=1b_{\text{cart}} = 1 adds friction to damp the otherwise-uncontrollable cart-position mode.
  • State Feedback (controller mode) — in the Controller card, switch the controller mode to State Feedback and leave the SF design method at LQR (the default). This loads the LQR weights Q=diag(1,50,1,1)Q = \text{diag}(1, 50, 1, 1) and R=0.05R = 0.05 for the canonical M=2,m=0.2,l=0.5,bcart=0.1M = 2, m = 0.2, l = 0.5, b_{\text{cart}} = 0.1 plant. The page solves the ARE in your browser to produce K=[4.47,87.29,8.94,18.44]K = [-4.47, -87.29, -8.94, -18.44]. The four closed-loop poles {0.94±0.48j, 6.05±1.78j}\{-0.94 \pm 0.48\,j,\ -6.05 \pm 1.78\,j\} are shown in the “Closed-Loop Poles” panel below the slider. See §3.3 for the in-browser walk-through and §3.2 for the LQR derivation. (The Ackermann sub-radio in the same card lets you drive the same K with 4 eigenvalue sliders instead; see §3.1.)

To switch to state feedback in the browser:

  1. In the Controller card, pick State feedback under Controller mode (the radio toggles instantly to show the SF inputs).
  2. The SF design method defaults to LQR. If you want Ackermann instead, pick Ackermann (eigenvalue assignment) and drag the 4 eigenvalue sliders to your desired closed-loop pole locations.
  3. Press Start. The pole swings to upright in ≈1.5 s and stays there. The cart reaches a steady offset of ≈0.1 m (small, not runaway).

For a custom LQR design, switch the SF design method to LQR and drag the Q, R sliders to taste; for a custom Ackermann design, switch to Ackermann and drag the 4 eigenvalue sliders. In both cases the closed-loop pole display updates as you move the sliders, so you can see the gain-to-eigenvalue pipeline in real time.

5. What to take away

  • Åström Example 2.2 is a teaching model, not a working controller. Its value is in showing the structure of the inverted-pendulum equations of motion (EOM), not in producing a deployable design.
  • A real cart-pole controller closes the loop on all four states. Pole-only PD is enough to keep the pole upright for a while but cannot hold the cart still. The simulator’s State Feedback mode is the only mode that regulates the cart — the LQR preset is a one-click way to see this in action.
  • The two controller modes are equivalent when the four SF gains are zero (PID on θ with Kp=0, Ki=0, Kd=0 → F=0; SF with Kx=Ktheta=Kv=Komega=0 → F=0). For non-zero gains, the SF mode is strictly more capable: it sees the cart position and velocity, which the scalar PD cannot.
  • The simulator is intentionally minimal in PID mode so you can build intuition. The State Feedback mode is the next step up — a single K (four numbers) instead of three knobs.
  • Ex 2.2 and Ex 9.6 are the same physics in different unit systems, but their PID gains are not interchangeable. The simulator’s PID defaults were found empirically on each preset, not mapped analytically. Use State Feedback (§3) for a predictable design.

References

  • Åström, K. J., & Murray, R. M. (2008). Feedback Systems: An Introduction for Scientists and Engineers. Princeton University Press. §2.2 Example 2.2 (cart-pole state-space form), §8.3 and §9.6 Example 9.6 (normalized transfer-function form), §6.3 State Feedback, Exercise 8.3 (linearized model), Exercise 8.13 (PD design).
  • Spong, M. W., Hutchinson, S., & Vidyasagar, M. (2006). Robot Modeling and Control. Wiley. Ch. 5 (decoupled EOM derivation).
  • Åström, K. J., & Hägglund, T. (2006). Advanced PID Control. ISA. (PID form with derivative filter.)

Comments