Control with state space
Build matrix models, test controllability, and place feedback poles. This module has 3 lessons and takes about 2h 25m. Each lesson has a practice exercise that runs real Python in your browser and a short quiz.
Start module 13 in the Learning LabStates, inputs, and outputs
Convert a second order equation into a state-space model.
A state contains enough information to predict future motion from future inputs. For a mechanical oscillator choose x1=position and x2=velocity. Then dx1/dt=x2 and dx2/dt=-(k/m)*x1-(b/m)*x2+u/m.
Write x_dot=A*x+B*u and y=C*x+D*u. For measured position, C=[1,0] and D=0. A has shape n by n, B n by inputs, C outputs by n, and D outputs by inputs.
State-space models handle nonzero initial conditions and multiple signals naturally. Different state coordinates can describe the same input-output behaviour. A state is not necessarily a directly measured quantity.
See it in action
import numpy as np
m,b,k = 2.,3.,8.
A = np.array([[0,1],[-k/m,-b/m]])
B = np.array([[0],[1/m]])
C = np.array([[1,0]])
x = np.array([0.1,0.])
print('State derivative:',A@x+B[:,0]*2.)
print('Measured position:',C@x)
Choose states with clear physical meaning and check matrix dimensions.
Controllability and pole placement
Check whether the input can move all states before placing poles.
For a two-state, single-input system, the controllability matrix is [B,A*B]. Full rank two means every state can be reached in finite time in the ideal model. A rank-deficient system cannot have all its poles assigned arbitrarily.
With state feedback u=-K*x, the closed-loop matrix is A-B*K. scipy.signal.place_poles finds K for requested poles when the pair is controllable and the requested multiplicities are supported.
For the double integrator A=[[0,1],[0,0]], B=[[0],[1]], feedback K=[k1,k2] gives polynomial s^2+k2*s+k1. Desired poles -2 and -3 give k1=6 and k2=5. Faster poles demand more input.
See it in action
import numpy as np
from scipy.signal import place_poles
A = np.array([[0.,1.],[0.,0.]])
B = np.array([[0.],[1.]])
print('Rank:',np.linalg.matrix_rank(np.hstack([B,A@B])))
K = place_poles(A,B,[-2.,-3.]).gain_matrix
print('K:',K,'Closed poles:',np.linalg.eigvals(A-B@K))
Check controllability before requesting pole locations.
Practical: build a position servo
Add reference scaling and verify state feedback tracking.
State feedback u=-K*x regulates the origin. To track a constant reference, add N*r. For D=0 and invertible A-B*K, steady output is -C*(A-B*K)^-1*B*N*r. Set N to the reciprocal of that scalar DC gain.
For a double integrator with K=[6,5] and measured position, N=6. This feedforward scaling gives unit DC tracking only for the exact model. It does not provide the disturbance rejection of integral action.
Use solve rather than forming an explicit matrix inverse. Plot position, velocity, and actuator command. Add a constant input load to see the limitation of model-based reference scaling.
Your experiment plan
Use the browser editor or the downloadable notebook. All plant data are simulated. Keep a notebook with parameters, predictions, results, and units.
- Simulate a position step and plot both states.
- Compute and plot u=-K*x+N*r.
- Add a constant force disturbance and measure the remaining offset.
- Compare a faster pole pair and report the increase in peak command.
What to hand in
- A position and velocity response.
- Reference gain and command-effort calculations.
- A load-offset experiment with an explanation.
Reflect on your results
Which assumption matters most? Describe one result that surprised you and one experiment that would test your explanation.
The automatic exercise checks the core code behaviour. Review observations and written deliverables yourself or with a mentor.
See it in action
import numpy as np
from scipy import signal
A = np.array([[0.,1.],[0.,0.]])
B = np.array([[0.],[1.]])
C = np.array([[1.,0.]])
K = np.array([[6.,5.]])
Acl = A-B@K
N = float(-1/(C@np.linalg.solve(Acl,B))[0,0])
t = np.linspace(0,8,801)
_, y, x = signal.lsim((Acl,B*N,C,np.zeros((1,1))),U=np.ones_like(t),T=t)
print('N:',N,'Final position:',y[-1],'Peak speed:',abs(x[:,1]).max())
Separate regulation, reference tracking, and disturbance rejection.
Free, open and run by a nonprofit.
This page is part of Control Engineering, a free course of 20 modules and 60 lessons in the engineering.fit( ) Learning Lab. The Learning Lab is built and run by engineering.fit( ), a nonprofit founded by Abdullateef Opeyemi Bakare that helps African engineering students gain research experience. You do not need an account or pay a fee to learn.