Skip to content

Commit 12dcf04

Browse files
committed
autotune: add output-error model optimization
1 parent 54f4e68 commit 12dcf04

1 file changed

Lines changed: 27 additions & 2 deletions

File tree

autotune/system_identification.py

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,10 @@
3939
"""
4040

4141
import numpy as np
42+
import control as ctrl
43+
4244
from arx_rls import ArxRls
43-
from scipy.optimize import lsq_linear
45+
from scipy.optimize import lsq_linear, minimize
4446

4547
class SystemIdentification(object):
4648
def __init__(self, n=2, m=2, d=1):
@@ -92,7 +94,7 @@ def run(self, t, u, y):
9294
y_lp[k] = alpha_lp * y_lp[k-1] + (1-alpha_lp)*y_hp[k]
9395

9496

95-
use_rls = True
97+
use_rls = False
9698
if use_rls:
9799
# Identification
98100
rls = ArxRls(self.n, self.m, self.d, lbda=(1 - dt / self.forgetting_tc))
@@ -123,6 +125,12 @@ def run(self, t, u, y):
123125
res = lsq_linear(A, B, lsmr_tol='auto', verbose=1)
124126
theta_hat = res.x
125127

128+
# 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
130+
x0 = np.append(res.x, 0) # initial conditions
131+
res = minimize(J, x0, method='nelder-mead', options={'disp': True})
132+
theta_hat = res.x
133+
126134
for i in range(self.n):
127135
a_coeffs[i,-1] = theta_hat[i]
128136
for i in range(self.m+1):
@@ -132,6 +140,23 @@ def run(self, t, u, y):
132140

133141
return (theta_hat, a_coeffs, b_coeffs)
134142

143+
def simulateModel(self, x, u, dt):
144+
a_coeffs = np.ones(self.n+1)
145+
b_coeffs = np.zeros(self.m+1)
146+
147+
for i in range(self.n):
148+
a_coeffs[i+1] = x[i]
149+
for i in range(self.m+1):
150+
b_coeffs[i] = x[i+self.n]
151+
152+
delays = ctrl.TransferFunction([1], np.append([1], np.zeros(self.d)), dt, inputs='r', outputs='rd')
153+
plant = ctrl.TransferFunction(b_coeffs, a_coeffs, dt, inputs='rd', outputs='y')
154+
155+
system = ctrl.interconnect([delays, plant], inputs='r', outputs='y')
156+
157+
_, y = ctrl.forced_response(system, U=u)
158+
return y
159+
135160
def getNum(self):
136161
num = [self.theta_hat.item(i) for i in range(self.n, self.n+self.m+1)] # b0 .. bm
137162
return num

0 commit comments

Comments
 (0)