In [1]:
import numpy as np
import sympy as sy
import control.matlab as cm
sy.init_printing(use_latex='mathjax', order='lex')
In [2]:
h,w0 = sy.symbols('h,omega0', real=True, positive=True)
s,z = sy.symbols('s,z')
t = sy.symbols('t', real=True)
In [3]:
# Zero-order hold sampling
G = w0**2/(s**2 - w0**2)
ystep = sy.inverse_laplace_transform(G/s, s, t)
sy.expand(ystep)
Out[3]:
In [4]:
Yz = w0**2/(2*w0**2) * ( z/(z-sy.exp(w0*h)) - 2*z/(z-1) + z/(z-sy.exp(-w0*h)))
Uz = z/(z-1)
H = sy.simplify(Yz/Uz)
sy.cancel(H)
Out[4]:
In [5]:
num, den = sy.fraction(sy.cancel(H))
den
Out[5]:
In [6]:
num = sy.simplify(num/(2*sy.exp(h*w0)))
den = sy.simplify(den/(2*sy.exp(h*w0)))
den, num
Out[6]:
In [7]:
# Coefficients
dencoeffs = sy.Poly(den, z).all_coeffs()
numcoeffs = sy.Poly(num, z).all_coeffs()
dencoeffs, numcoeffs
Out[7]:
In [8]:
# Observable canonical form
Phi = sy.simplify(sy.Matrix([[-dencoeffs[1], 1],[-dencoeffs[2], 0]]))
Gamma2 = sy.trigsimp(sy.cancel(sy.Matrix([[numcoeffs[0]],[numcoeffs[1]]])))
C = sy.Matrix([[1, 0]])
Htest = sy.simplify(C*(z*sy.eye(2)-Phi).inv()*Gamma2)
sy.cancel(H), Htest[0]
Out[8]:
In [9]:
Phi, Gamma2
Out[9]:
In [10]:
Gamma = sy.Matrix([[sy.cosh(h*w0)-1],[sy.cosh(h*w0)-1]])
sy.simplify(Gamma2-Gamma)
Out[10]:
In [11]:
Phi,Gamma
Out[11]:
In [12]:
# Some numerical values
w0n = 1.0
hn = 0.2/w0n
Phi_n = np.asarray(Phi.subs({w0:w0n, h:hn})).astype(np.float64)
Gamma_n = np.asarray(Gamma.subs({w0:w0n, h:hn})).astype(np.float64)
Phi_n, Gamma_n
Out[12]:
In [13]:
C = np.array([1., 0])
D = np.array([[0]])
sys = cm.ss(Phi_n, Gamma_n, C, D, hn)
cm.pole(sys)
Out[13]:
In [14]:
# Desired poles: double pole in -2w0 (continuous time)
pd = np.exp(-2*w0n*hn)
L = cm.acker(A=Phi_n, B=Gamma_n,poles = [pd,pd])
L
Out[14]:
In [15]:
L2 = np.array([[19,15]])
np.linalg.eig(Phi_n - np.dot(Gamma_n, L2))
Out[15]:
In [16]:
# Closed-loop system
Phic = Phi_n - np.dot(Gamma_n, L2)
sys_c = cm.ss(Phic, Gamma_n, C, D, hn)
# Steady-state solution
cm.dcgain(sys_c)
Out[16]:
In [17]:
l0=1/0.3705
In [18]:
import matplotlib.pyplot as plt
tvec = np.arange(0,40)*hn
yout, tout = cm.step(sys_c*2.7, tvec)
plt.figure(figsize=(13,4))
plt.plot(tout, yout)
Out[18]:
In [19]:
cm.tf(sys_c*2.7)
Out[19]:
In [20]:
cm.pole(sys_c)
Out[20]:
In [21]:
# Finding the deadbeat observer
CT = C.copy()
CT.shape = (2,1)
KT = cm.acker(Phi_n.T, CT, [0,0])
K = KT.T
K
Out[21]:
In [22]:
# Verify
sys_o = cm.ss(Phi_n - np.dot(K, CT.T), Gamma_n, C, D, hn)
cm.pole(sys_o)
Out[22]:
In [23]:
D_o = np.array([[l0, 0]])
sys_o = cm.ss(Phi_n - np.dot(K, CT.T)-np.dot(L2, Gamma_n),
np.hstack((l0*Gamma_n,K)), -L, D_o, hn)
In [24]:
cm.tf(sys_o)
Out[24]:
In [25]:
K
Out[25]:
In [26]:
np.hstack((l0*Gamma_n, K))
Out[26]:
In [ ]: