-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfopdt_regression_model.py
116 lines (104 loc) · 2.91 KB
/
fopdt_regression_model.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint
from scipy.optimize import minimize
from scipy.interpolate import interp1d
# Import CSV data file
# Column 1 = time (t)
# Column 2 = input (u)
# Column 3 = output (yp)
data = np.loadtxt('Step_Response_Regression.csv',delimiter=',',skiprows=1)
u0 = data[0,1]
yp0 = data[0,2]
t = data[:,0].T - data[0,0]
u = data[:,1].T
yp = data[:,2].T
# specify number of steps
ns = len(t)
delta_t = t[1]-t[0]
# create linear interpolation of the u data versus time
uf = interp1d(t,u)
# define first-order plus dead-time approximation
def fopdt(y,t,uf,Km,taum,thetam):
# arguments
# y = output
# t = time
# uf = input linear function (for time shift)
# Km = model gain
# taum = model time constant
# thetam = model time constant
# time-shift u
try:
if (t-thetam) <= 0:
um = uf(0.0)
else:
um = uf(t-thetam)
except:
#print('Error with time extrapolation: ' + str(t))
um = u0
# calculate derivative
dydt = (-(y-yp0) + Km * (um-u0))/taum
return dydt
# simulate FOPDT model with x=[Km,taum,thetam]
def sim_model(x):
# input arguments
Km = x[0]
taum = x[1]
thetam = x[2]
# storage for model values
ym = np.zeros(ns) # model
# initial condition
ym[0] = yp0
# loop through time steps
for i in range(0,ns-1):
ts = [t[i],t[i+1]]
y1 = odeint(fopdt,ym[i],ts,args=(uf,Km,taum,thetam))
ym[i+1] = y1[-1]
return ym
# define objective
def objective(x):
# simulate model
ym = sim_model(x)
# calculate objective
obj = 0.0
for i in range(len(ym)):
obj = obj + (ym[i]-yp[i])**2
# return result
return obj
# initial guesses
x0 = np.zeros(3)
x0[0] = 1.0 # Km
x0[1] = 130.0 # taum
x0[2] = 13.0 # thetam
# show initial objective
print('Initial SSE Objective: ' + str(objective(x0)))
# optimize Km, taum, thetam
print('Optimizing Values...')
solution = minimize(objective,x0)
# Another way to solve: with bounds on variables
#bnds = ((0.4, 1.0), (1.0, 200.0), (0.0, 30.0))
#solution = minimize(objective,x0,bounds=bnds,method='SLSQP')
x = solution.x
# show final objective
print('Final SSE Objective: ' + str(objective(x)))
print('Kp: ' + str(x[0]))
print('taup: ' + str(x[1]))
print('thetap: ' + str(x[2]))
# calculate model with updated parameters
ym1 = sim_model(x0)
ym2 = sim_model(x)
# plot results
plt.figure(figsize=(10,7))
plt.subplot(2,1,1)
plt.plot(t,yp,'kx-',linewidth=2,label='Temperature Data')
plt.plot(t,ym1,'b-',linewidth=2,label='Initial Guess')
plt.plot(t,ym2,'r--',linewidth=3,label='Optimized FOPDT')
plt.ylabel(r'Temp ($^o$C)')
plt.legend(loc='best')
plt.subplot(2,1,2)
plt.plot(t,u,'bx-',linewidth=2)
plt.plot(t,uf(t),'r--',linewidth=3)
plt.legend(['Measured','Interpolated'],loc='best')
plt.ylabel('Heater (%)')
plt.xlabel('Time (sec)')
plt.show()