Control TheoryLagrangian MechanicsBack2BasicsNonlinear Systems
ℹ️Disclaimer
Back to basics #Back2Basics is
a series of notes, that I mostly wrote for myself and putting it here. Note,
all the math, notes and discussions are my own, AI usage is limited to
building the tools, website, formatting and sanity-checking my work.
The cart-pole system is one of the first nonlinear systems I ever learned and ran experiments on. I have been feeling a bit dumb lately with all the AI usage and want to get back to basics. I do not have a specific objective in mind, may be some vague ideas as to where I would go with these notes. As opposed to static images, it's so easy to add cool visualizations like the one below using AI, to make the notes a bit more lively.
No control at all. Drag the pole, or the cart, and let go.
The model
Consider a cart-pole system, with the cart motion restricted to the horizontal axis, and pole is free to swing, assume the mass of the pole is negligible and mass is lumped at the tip of the pole. Other end of the pole is connected to the center of mass of the cart and is free to rotate at this point. We can apply a horizontal force at the center of mass of the cart. This system is underactuated, with one input and two degrees of freedom (one for the cart and another for the pole).
Let M be the mass of the cart, m the mass lumped at the tip, l the length of the pole, and u the input force applied at the cart's centre of mass. Let x be the cart position, positive to the right, and let θ be the pole angle measured from the downward vertical (the −y direction). Here, θ=0 is the hanging position; positive angles are counter-clockwise, and negative angles are clockwise.
Cart-pole schematic. The pole pivots at the cart's centre of mass; θ is measured from the downward vertical, positive anti-clockwise.
I have implemented a symbolic way to derive equations of motion using the
Principle of Least Action in
pygeomech
L is the Lagrangian, L=T−V, where T is the kinetic energy and V is the potential energy. δW is the infinitesimal virtual work done by non-conservative forces. In our case, the only non-conservative force is the input force u applied at the cart's centre of mass.
For my convenience, I'll switch to 2D, with y positive upward. The cart and pole positions are Xc=[x0] and Xp=[x+lsinθ−lcosθ], so their velocities are X˙c=[x˙0] and X˙p=[x˙+lcosθθ˙lsinθθ˙], so the total kinetic energy of the system is T=21M⟨X˙c,X˙c⟩+21m⟨X˙p,X˙p⟩ and the potential energy is V=mg⟨e2,Xp⟩, where e2=[01] is the unit vector in the y direction.
let's put our fancy hat and do integration by parts. The variations vanish at
the endpoints, δx(t0)=δx(t1)=0 and δθ(t0)=δθ(t1)=0,
so the boundary terms [⋅δx]t0t1 and [⋅δθ]t0t1
drop out and only the −∫dtd(⋅) pieces survive,
Same cart-pole, now with viscous friction on the rail and at the pivot. Set both to zero to recover the frictionless swing.
Lets add some reality (aka friction) into these equations. In reality, friction is everywhere, its eternal. We'll add it both to the cart and at the pivot. Friction is non-conservative, so it becomes part of the virtual work, δW.
Keeping it simple with just viscous friction, a drag uf=−μcx˙e1 on the cart proportional to x˙, and a torque due to friction τf=−μpθ˙ at the pivot proportional to θ˙, where μc,μp≥0. The virtual work is then,
With no force applied, u=0, the first term goes and the energy can only
ever fall,
dtdE=−q˙⊤Dq˙=−μcx˙2−μpθ˙2≤0
and the sign is decided entirely by D⪰0.
The Balancing Act
Okay, now lets write up a simple controller to keep the pole upright. Linear Quadratic Regulator (LQR), is an optimal formulation to find the control inputs for time invariant systems.
For a linear system of the form z˙=Az+Bu, the control input is given,
u∗=argumin∫0∞(z⊤Qz+u⊤Ru)dt
where Q⪰0, R≻0, the solution for this optimal control turns to be,
u∗=−Kx, where K=R−1B⊤S and S is the solution to the algebraic Riccati equation (No way, I'm deriving this right now, 🤷♂️),
0=A⊤S+SA−SBR−1B⊤S+Q
Before any of that though, we need the dynamics as a first-order system. With z=[xθx˙θ˙]T, invert the mass matrix and doing some algebraic magic,
That M+msin2θ in the denominator never goes to zero, it just wanders between M and M+m, so the mass matrix is always invertible and f is well defined everywhere. No singular configurations to worry about, which is not something you get for free in general.
Taking help of Brook Taylor, we can write, f(z)≈f(z0)+∂z∂f(z−z0)+21∂z2∂2f(z−z0)2+…
and only considering the first order approximation, the dynamics linearize to z~˙=Az~+Bu, where z~=z−z0 is the deviation from the equilibrium, A=∂z∂f(z0) and B=∂u∂f(z0). About the equilibrium point z0=[0,π,0,0]T (i.e., the pole standing vertically up, cart at x=0), we have:
LQR balancing about upright. Drag the pole away and let go, or raise the effort penalty R until the controller becomes too polite to catch it. The friction sliders act on the plant only, the gain never knows about them.
and f(z0)=0, which is the whole point of linearizing about an equilibrium (although a bit "delulu" is that the term, I mean unstable). Worth keeping straight that the gain then multiplies z~ and not z: the pole angle that goes into u=−Kz~ is φ=θ−π, measured from upright, not θ measured from hanging. Going back to our imaginary frictionless world and solving the LQR with
There is no scipy in a browser, so we are solving it the blunt way, discretize at a fine step and iterate the Riccati recursion backwards until P stops moving. Converges in a few thousand iterations, a couple of milliseconds, and it re-solves every time you change a parameter, so the gain under the simulation below is always the one being applied.
✏️Fun Fact
Lets says we pick new Q′=αQ and R′=αR, the cost functional
becomes ∫0∞(αxTQx+αuTRu)dt=α∫0∞(xTQx+uTRu)dt. So the optimal solution is the same for
the quadratic cost functional, what actually matters is the relative weights
of Q and R.
Control Performance
There are different ways to control a system, but how do you tell if one is better than the other? There is no easy answer; it comes down to what you are trying to achieve with the controller.
Performance Metricsall of them, all the time
🎯
Region of attraction
how far can you push it
How far from the setpoint can you take the system and still have it come
back to the origin?
🎲
Noise
is what you measure real
How stable is the system in the presence of noise? Is the measured state
correct? Is the applied force exact?
🛡️
Robustness
is your model right
How stable is the system in the presence of model uncertainties? Are the
model parameters correct? And what about the dynamics you never modelled at
all?
⚡
Effort
what does it cost
How much energy are you using to bring the state to origin?
⏱️
Speed
how fast is it over
How fast are you bringing the state to origin?
🚧
Limits
what the hardware refuses
Actuator limits (the motor driving the cart doesn't have infinite force,
obviously), state constraints (the cart can only move so much), force rates
(I can't ask for 100N and then -100N the next instant!), etc.
⏳
Latency
everything arrives late
When you apply a force, it might take a moment to reach the motor, and how
soon did the sensor tell you what just happened at the pivot?
💻
Compute
what you get to run it on
Do you have a Raspberry Pi or a Nvidia Jetson? How much memory do you have?
How fast can you run the controller, 10Hz or 1000Hz?
Ah! Lost enthu to move forward for now, but plan to revisit to add cool visuals to see how the ROA is changing with various factors, like model uncertainties, costs, limits and the whole shebang. I'm calling it a day.
P.S.: ... LLMs can generate this page in a matter of seconds.