Python for Control Engineering
Python for Control Engineering
blog
https://www.halvorsen.blog/documents/programming/python/
Additional Python Resources
https://www.halvorsen.blog/documents/programming/python/
Contents
• Introduction to Control Engineering
• Python Libraries useful in Control
Engineering Applications
– NumPy, Matplotlib
– SciPy (especially scipy.signal)
– Python Control Systems Library (control)
• Python Examples
• Additional Tutorials/Videos/Topics
Additional Tutorials/Videos/Topics
This Tutorial is only the beginning. Some Examples of Tutorials that goes more in depth:
• Transfer Functions with Python
• State-space Models with Python
Videos available
• Frequency Response with Python
on YouTube
• PID Control with Python
• Stability Analysis with Python
• Frequency Response Stability Analysis with Python
• Logging Measurement Data to File with Python
• Control System with Python
– Exemplified using Small-scale Industrial Processes and Simulators
• DAQ Systems
• etc.
https://www.halvorsen.blog/documents/programming/python/
https://www.halvorsen.blog
Python Libraries
Hans-Petter Halvorsen
NumPy, Matplotlib
• In addition to Python itself, the
Python libraries NumPy, Matplotlib is
typically needed in all kind of
application
• If you have installed Python using the
Anaconda distribution, these are
already installed
SciPy.signal
• An alternative to The Python Control Systems Library is
SciPy.signal, i.e. the Signal Module in the SciPy Library
• https://docs.scipy.org/doc/scipy/reference/signal.html
Control Engineering
Hans-Petter Halvorsen
Control System
Noise/Disturbance
Reference The Controller is 𝑣
Value typically a PID Controller
𝑟 𝑒 𝑢 𝑥
Controller Actuators Process
− Control
𝑦 Signal
Process
Output
Filtering Sensors
Control System
• 𝑟 – Reference Value, SP (Set-point), SV (Set Value)
• 𝑦 – Measurement Value (MV), Process Value (PV)
• 𝑒 – Error between the reference value and the
measurement value (𝑒 = 𝑟 – 𝑦)
• 𝑣 – Disturbance, makes it more complicated to control
the process
• 𝑢 - Control Signal from the Controller
The PID Algorithm
𝐾# &
𝑢 𝑡 = 𝐾# 𝑒 + ( 𝑒𝑑𝜏 + 𝐾# 𝑇' 𝑒̇
𝑇$ %
Where 𝑢 is the controller output and 𝑒 is the Tuning Parameters:
control error:
𝑒 𝑡 = 𝑟 𝑡 − 𝑦(𝑡) 𝐾! Proportional Gain
Python Examples
Hans-Petter Halvorsen
https://www.halvorsen.blog
Assume 𝑢(𝑡) is a step (𝑈), then we can find that the solution to the differential equation is:
%
𝑦 𝑡 = 𝐾𝑈(1 − 𝑒 $
") (we use Laplace)
Python
We start by plotting the following: import numpy as np
import matplotlib.pyplot as plt
0
/1
𝑦 𝑡 = 𝐾𝑈(1 − 𝑒 ) K = 3
T = 4
start = 0
In the Python code we can set: stop = 30
increment = 0.1
𝑈=1 t = np.arange(start,stop,increment)
𝐾=3
𝑇=4 y = K * (1-np.exp(-t/T))
plt.plot(t, y)
plt.title('1.order Dynamic System')
plt.xlabel('t [s]')
plt.ylabel('y(t) ')
plt.grid()
Comments
We have many different options when it comes to simulation a Dynamic
System:
• We can solve the differential Equation(s) and then implement the the
algebraic solution and plot it.
– This solution may work for simple systems. For more complicated
systems it may be difficult to solve the differential equation(s) by
hand
• We can use one of the “built-in” ODE solvers in Python
• We can make a Discrete version of the system
• We can convert the differential equation(s) to Transfer Function(s)
• etc.
# Initialization
Differential Equation: Using ODE Solver K = 3
T = 4
1 u = 1
tstart = 0
𝑦̇ = (−𝑦 + 𝐾𝑢) tstop = 25
𝑇 increment = 1
y0 = 0
t = np.arange(tstart,tstop+1,increment)
In the Python code we can set:
# Function that returns dx/dt
𝐾=3 def system1order(y, t, K, T, u):
𝑇=4 dydt = (1/T) * (-y + K*u)
return dydt
# Solve ODE
x = odeint(system1order, y0, t, args=(K, T, u))
print(x)
8!"# /8!
= 𝑎𝑦4 + 𝑏𝑢4
𝑦$%& = (1 + 𝑇' 𝑎)𝑦$ + 𝑇' 𝑏𝑢$
1$
Python
import numpy as np
import matplotlib.pyplot as plt
# Model Parameters
K = 3
T = 4
Let's simulate the discrete system: a = -1/T
b = K/T
𝐾=3 # Simulation
for k in range(N):
𝑇=4 yk1 = (1 + a*Ts) * yk
yk = yk1
+ Ts * b * uk
data.append(yk1)
plt.plot(t,data)
plt.title('1.order Dynamic System')
plt.xlabel('t [s]')
plt.ylabel('y(t)')
plt.grid()
https://www.halvorsen.blog
Transfer Functions
Hans-Petter Halvorsen
Transfer Functions
• Transfer functions are a model form
based on the Laplace transform.
• Transfer functions are very useful in
analysis and design of linear dynamic
systems.
• You can create Transfer Functions both
with SciPy.signal and the Python Control
Systems Library
1.order Transfer Functions
A 1.order transfer function is given by:
Input Signal Output Signal
𝑦(𝑠) 𝐾 𝑢(𝑠) 𝐻 𝑠 𝑦(𝑠)
𝐻 𝑠 = =
𝑢(𝑠) 𝑇𝑠 + 1
Differential 1
Where 𝐾 is the Gain and 𝑇 is the Time constant
Equation 𝑦̇ = (−𝑦 + 𝐾𝑢)
In the time domain we get the following 𝑇
equation (using Inverse Laplace):
) We ca find the Transfer function from
( the Differential Equation using Laplace
𝑦 𝑡 = 𝐾𝑈(1 − 𝑒 *)
(After a Step 𝑈 for the unput signal 𝑢(𝑠))
1.order – Step Response
𝑦(𝑡)
100% 𝐾𝑈
0
/1
𝑦 𝑡 = 𝐾𝑈(1 − 𝑒 )
63%
𝑦(𝑠) 𝐾
𝐻 𝑠 = =
𝑢(𝑠) 𝑇𝑠 + 1
𝑡
𝑇
Python
import control
import numpy as np
import matplotlib.pyplot as plt
Transfer Function: K = 3
3 T = 4
𝐻(𝑠) = num = np.array([K])
4𝑠 + 1 den = np.array([T , 1])
H = control.tf(num , den)
print ('H(s) =', H)
t, y = control.step_response(H)
plt.plot(t,y)
plt.title("Step Response")
https://www.halvorsen.blog
State-space Models
Hans-Petter Halvorsen
State-space Models
A general State-space Model is given by: System
Input Internal Output
𝑥̇ = 𝐴𝑥 + 𝐵𝑢 𝑢 States 𝑦
𝑦 = 𝐶𝑥 + 𝐷𝑢 𝑥
!"
Note that 𝑥̇ is the same as 𝐴, 𝐵, 𝐶 and 𝐷 are matrices
!#
𝑥, 𝑥,̇ 𝑢, 𝑦 are vectors
• A state-space model is a structured form or representation of a set of differential
equations. State-space models are very useful in Control theory and design. The
differential equations are converted in matrices and vectors.
• You can create State.space Models both with SciPy.signal and the Python Control Systems
Library
Basic Example
Given the following System: We want to put the equations on the following form:
𝑥̇ & = 𝑥+
𝑥̇ = 𝐴𝑥 + 𝐵𝑢
𝑥̇ + = −𝑥+ + 𝑢 𝑦 = 𝐶𝑥 + 𝐷𝑢
𝑦 = 𝑥&
This gives the following State-space Model: Where:
𝑥̇ * 0 1 𝑥* 0 𝐴=
0 1
𝐵=
0
= 𝑥 + 𝑢 0 −1 1
𝑥̇ , 0 −1 , 1 𝐶= 1 0 𝐷= 0
𝑥* 𝑥!
𝑦= 1 0 𝑥 𝑥̇ =
𝑥̇ !
𝑥̇ &
𝑥= 𝑥
&
,
Python
import scipy.signal as sig
import matplotlib.pyplot as plt
import numpy as np
#Simulation Parameters
x0 = [0,0]
1 stop = 30
step = 1
𝑥̇ ! = −𝑥! + 𝐾𝑢 t = np.arange(start,stop,step)
𝑇
𝑥̇ & = 0 K = 3
T = 4
𝑦 = 𝑥! # State-space Model
A = [[-1/T, 0],
The State-space Model becomes: [0, 0]]
B = [[K/T],
[0]]
1 𝑥 𝐾
𝑥̇ !
C = [[1, 0]]
= −𝑇 0 𝑥 + 𝑇 𝑢
! D = 0
𝑦= 1 0 𝑥 # Plotting
& plt.plot(t, y)
plt.title("Step Response")
Here we use the following function: plt.xlabel("t")
plt.ylabel("y")
t, y = sig.step(sys, x0, t) plt.grid()
plt.show()
Python
import scipy.signal as sig
import matplotlib.pyplot as plt
import numpy as np
#Simulation Parameters
x0 = [0,0]
State-space Model: start = 0; stop = 30; step = 1
t = np.arange(start,stop,step)
K = 3; T = 4
1 𝐾
𝑥̇ !
= − 0 𝑥! +
𝑇 𝑢
# State-space Model
𝑥̇ " 𝑇 𝑥" A = [[-1/T, 0],
0 0 0 [0, 0]]
B = [[K/T],
𝑥! [0]]
𝑦= 1 0 𝑥 C = [[1, 0]]
" D = 0
# Step Response
t, y = sig.step(H, x0, t)
Python give us the following:
# Plotting
0.75 3 plt.plot(t, y)
4𝑠 + 1
plt.xlabel("t"); plt.ylabel("y")
𝑠 + 0.25 plt.grid()
Which is the same as plt.show()
https://www.halvorsen.blog
Frequency Response
Hans-Petter Halvorsen
Frequency Response
• The Frequency Response is an important tool for
Analysis and Design of signal filters and for
analysis and design of Control Systems
• The frequency response can be found from a
transfer function model
• The Bode diagram gives a simple Graphical
overview of the Frequency Response for a given
system
• The Bode Diagram is tool for Analyzing the
Stability properties of the Control System.
Python
import numpy as np
import scipy.signal as signal
import matplotlib.pyplot as plt
𝐻 𝑠 =
den = np.convolve(den1, den2)
# Frequencies
w_start = 0.01
w_stop = 10
step = 0.01
N = int ((w_stop-w_start )/step) + 1
w = np.linspace (w_start , w_stop , N)
# Bode Plot
w, mag, phase = signal.bode(H, w)
plt.figure()
plt.subplot (2, 1, 1)
plt.semilogx(w, mag) # Bode Magnitude Plot
plt.title("Bode Plot")
plt.grid(b=None, which='major', axis='both')
plt.grid(b=None, which='minor', axis='both')
plt.ylabel("Magnitude (dB)")
plt.subplot (2, 1, 2)
plt.semilogx(w, phase) # Bode Phase plot
plt.grid(b=None, which='major', axis='both')
plt.grid(b=None, which='minor', axis='both')
plt.ylabel("Phase (deg)")
plt.xlabel("Frequency (rad/sec)")
plt.show()
Python Python Control Systems Library
H = control.tf(num, den)
print ('H(s) =', H)
# Bode Plot
control.bode(H, dB=True)
https://www.halvorsen.blog
PID Control
Hans-Petter Halvorsen
Control System
The purpose with a Control System is to Control a Dynamic System, e.g., an industrial
process, an airplane, a self-driven car, etc. (a Control System is “everywhere“).
PID Controller
Reference 𝑟 𝑒 𝑢 𝑦
Value Controller Process
− Control
𝑦 Signal
PID
• The PID Controller is the most used
controller today
• It is easy to understand and
implement
• There are few Tuning Parameters
The PID Algorithm
𝐾# &
𝑢 𝑡 = 𝐾# 𝑒 + ( 𝑒𝑑𝜏 + 𝐾# 𝑇' 𝑒̇
𝑇$ %
Where 𝑢 is the controller output and 𝑒 is the Tuning Parameters:
control error:
𝑒 𝑡 = 𝑟 𝑡 − 𝑦(𝑡) 𝐾! Proportional Gain
Then we get:
Finally, we get:
𝑢& − 𝑢&'( 𝑒& − 𝑒&'( 𝐾! 𝐾C
= 𝐾! + 𝑒 𝑢4 = 𝑢4/6 + 𝐾C 𝑒4 − 𝑒4/6 + 𝑇7 𝑒4
𝑇% 𝑇% 𝑇" & 𝑇D
Where 𝑒* = 𝑟* − 𝑦*
Control System Simulations
PI Controller: Discrete Version (Ready to implement in Python):
𝐾, / 𝑒4 = 𝑟4 − 𝑦4
𝑢 𝑡 = 𝐾, 𝑒 + ( 𝑒𝑑𝜏
𝑇- . 𝐾C
𝑢4 = 𝑢4/6 + 𝐾C 𝑒4 − 𝑒4/6 + 𝑇7 𝑒4
𝑇D
Process (1.order system):
! #
𝑦()* = (1 + 𝑇+ 𝑎)𝑦( + 𝑇+ 𝑏𝑢(
Where 𝑎 = − and 𝑏 =
" "
In the Python code we can set 𝐾 = 3 and 𝑇 = 4
Python
import numpy as np
import matplotlib.pyplot as plt
# Model Parameters
K = 3
T = 4
a = -(1/T) # Plot Process Value
b = K/T plt.figure(1)
plt.plot(t,y)
# Simulation Parameters
Ts = 0.1 # Sampling Time # Formatting the appearance of the Plot
Tstop = 20 # End of Simulation Time plt.title('Control of Dynamic System')
N = int(Tstop/Ts) # Simulation length plt.xlabel('t [s]')
y = np.zeros(N+2) # Initialization the Tout vector plt.ylabel('y')
y[0] = 0 # Initial Vaue plt.grid()
xmin = 0
# PI Controller Settings xmax = Tstop
Kp = 0.5 ymin = 0
Ti = 5 ymax = 8
plt.axis([xmin, xmax, ymin, ymax])
r = 5 # Reference value
plt.show()
e = np.zeros(N+2) # Initialization
u = np.zeros(N+2) # Initialization
# Plot Control Signal
# Simulation plt.figure(2)
for k in range(N+1): plt.plot(t,u)
e[k] = r - y[k]
u[k] = u[k-1] + Kp*(e[k] - e[k-1]) + (Kp/Ti)*Ts*e[k] # Formatting the appearance of the Plot
y[k+1] = (1+Ts*a)*y[k] + Ts*b*u[k] plt.title('Control Signal')
plt.xlabel('t [s]')
# Plot the Simulation Results plt.ylabel('u [V]')
t = np.arange(0,Tstop+2*Ts,Ts) #Create the Time Series plt.grid()
Python
https://www.halvorsen.blog
Stability Analysis
Hans-Petter Halvorsen
Stability Analysis
Asymptotically Stable System Marginally Stable System Unstable System
Poles: Im Im Im
Re Re
Re
Step Response:
𝑡 𝑡 𝑡
Poles
Step Response
https://www.halvorsen.blog/documents/programming/python/
Additional Python Resources
https://www.halvorsen.blog/documents/programming/python/
Hans-Petter Halvorsen
University of South-Eastern Norway
www.usn.no
E-mail: [email protected]
Web: https://www.halvorsen.blog