Skip to content

Commit bcaf9a2

Browse files
committed
autotune: Change id interface to work with SIPPY
SIPPY support will be added in the near future
1 parent 38345ac commit bcaf9a2

3 files changed

Lines changed: 27 additions & 28 deletions

File tree

File renamed without changes.

autotune/autotune.py

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -452,29 +452,20 @@ def runIdentification(self):
452452
n = self.sys_id_n_poles # order of the denominator (a_1,...,a_n)
453453
m = self.sys_id_n_zeros # order of the numerator (b_0,...,b_m)
454454
d = self.sys_id_delays # number of delays
455-
tau = 60.0 # forgetting period
456-
lbda = 1.0 - self.dt/tau
457-
self.sysid = SystemIdentification(n, m, d)
458-
self.sysid.lbda = lbda
455+
id = SystemIdentification(n, m, d, self.dt)
459456

460-
(theta_hat, a_coeffs, b_coeffs) = self.sysid.run(self.t, self.u, self.y)
457+
est = id.fit(self.u.reshape(-1, 1), self.y.reshape(-1, 1))
461458

462-
self.plotStateVector(a_coeffs, b_coeffs)
459+
self.num = est.G_.num_list[0][0]
460+
self.den = est.G_.den_list[0][0][0:n+1]
461+
self.Gz = ctrl.TransferFunction(self.num, self.den, self.dt)
462+
463+
num_coeffs = self.num
464+
den_coeffs = self.den[1:n+1]
463465
self.is_system_identified = True
464466
self.btn_run_sys_id.setEnabled(False)
465-
dt = self.dt
466-
# num = self.sysid.getNum()
467-
# den = self.sysid.getDen()
468-
# self.Gz_dot = ctrl.TransferFunction(num, den, dt)
469-
470-
# Uncomment below to add integrator
471-
# self.sysid.addIntegrator()
472-
self.num = self.sysid.getNum()
473-
474-
self.den = self.sysid.getDen()
475467

476-
self.Gz = ctrl.TransferFunction(self.num, self.den, dt)
477-
self.updateTfDisplay(a_coeffs[:, -1], b_coeffs[:, -1])
468+
self.updateTfDisplay(den_coeffs, num_coeffs)
478469
self.plotPolesZeros()
479470
self.replayInputData()
480471

@@ -500,7 +491,7 @@ def plotStateVector(self, a_coeffs, b_coeffs):
500491
def replayInputData(self):
501492
if not self.is_system_identified:
502493
return
503-
d = self.sysid.d
494+
d = self.sys_id_delays
504495
u_detrended = detrend(self.u)
505496
u_delayed = np.concatenate(([0 for k in range(d)], u_detrended[0:(len(u_detrended)-d)]))
506497
self.t_est, self.y_est = ctrl.forced_response(self.Gz, T=self.t, U=u_delayed)

autotune/system_identification.py

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,23 +44,30 @@
4444
from arx_rls import ArxRls
4545
from scipy.optimize import lsq_linear, minimize
4646

47+
class SysIdResult(object):
48+
def __init__(self, num, den, dt):
49+
self.G_ = ctrl.TransferFunction(num, den, dt)
50+
4751
class SystemIdentification(object):
48-
def __init__(self, n=2, m=2, d=1):
52+
def __init__(self, n=2, m=2, d=1, dt = 0.0):
4953
self.n = n # order of the denominator (a_1,...,a_n)
5054
self.m = m # order of the numerator (b_0,...,b_m)
5155
self.d = d # number of delays
5256
self.forgetting_tc = 60.0 # forgetting factor for weighted RLS in seconds
5357
self.f_hp = 0.5 # high-pass filter cutoff frequency
5458
self.f_lp = 30.0 # low-pass filter cutoff frequency
59+
self.dt = dt
60+
61+
tau = 60.0 # forgetting period
62+
self.lbda = 1.0 - self.dt/tau
5563

56-
def run(self, t, u, y):
57-
n_steps = len(t)
58-
dt = t[1] - t[0]
64+
def fit(self, u, y):
65+
n_steps = len(u)
5966

6067
# High-pass filter parameters
6168
if self.f_hp > 0.0:
6269
tau_hp = 1/(2*np.pi*self.f_hp)
63-
alpha_hp = tau_hp/(tau_hp+dt)
70+
alpha_hp = tau_hp/(tau_hp+self.dt)
6471
else:
6572
alpha_hp = 0.0
6673

@@ -71,7 +78,7 @@ def run(self, t, u, y):
7178

7279
# Low-pass filter parameters
7380
tau_lp = 1/(2*np.pi*self.f_lp)
74-
alpha_lp = tau_lp/(tau_lp+dt)
81+
alpha_lp = tau_lp/(tau_lp+self.dt)
7582
u_lp = np.zeros(n_steps)
7683
y_lp = np.zeros(n_steps)
7784
u_lp[0] = u[0]
@@ -97,7 +104,7 @@ def run(self, t, u, y):
97104
use_rls = True
98105
if use_rls:
99106
# Identification
100-
rls = ArxRls(self.n, self.m, self.d, lbda=(1 - dt / self.forgetting_tc))
107+
rls = ArxRls(self.n, self.m, self.d, lbda=(1 - self.dt / self.forgetting_tc))
101108

102109
for k in range(n_steps):
103110
# Update model
@@ -126,7 +133,7 @@ def run(self, t, u, y):
126133
theta_hat = res.x
127134

128135
# Refine model using output-error optimization
129-
J = lambda x: np.sum(np.power(abs(np.array(B)-self.simulateModel(x, u_lp, dt)), 2.0)) # cost function
136+
J = lambda x: np.sum(np.power(abs(np.array(B)-self.simulateModel(x, u_lp, self.dt)), 2.0)) # cost function
130137
x0 = np.append(res.x, 0) # initial conditions
131138
res = minimize(J, x0, method='nelder-mead', options={'disp': True})
132139
theta_hat = res.x
@@ -138,7 +145,8 @@ def run(self, t, u, y):
138145

139146
self.theta_hat = theta_hat
140147

141-
return (theta_hat, a_coeffs, b_coeffs)
148+
estimate = SysIdResult(self.getNum(), self.getDen(), self.dt)
149+
return estimate
142150

143151
def simulateModel(self, x, u, dt):
144152
a_coeffs = np.ones(self.n+1)

0 commit comments

Comments
 (0)