|
| 1 | +# Copyright [2020] [Alessio Russo - alessior@kth.se] |
| 2 | +# This file is part of PythonVRFT. |
| 3 | +# PythonVRFT is free software: you can redistribute it and/or modify |
| 4 | +# it under the terms of the GNU General Public License as published by |
| 5 | +# the Free Software Foundation, version 3 of the License. |
| 6 | +# PythonVRFT is distributed in the hope that it will be useful, |
| 7 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 8 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 9 | +# GNU General Public License for more details. |
| 10 | +# You should have received a copy of the GNU General Public License |
| 11 | +# along with PythonVRFT. If not, see <http://www.gnu.org/licenses/>. |
| 12 | +# |
| 13 | +# Code author: [Alessio Russo - alessior@kth.se] |
| 14 | +# Last update: 08th January 2020, by alessior@kth.se |
| 15 | +# |
| 16 | + |
| 17 | +import numpy as np |
| 18 | +import matplotlib.pyplot as plt |
| 19 | +import scipy.signal as scipysig |
| 20 | +from vrft import * |
| 21 | + |
| 22 | +# Example 3 |
| 23 | +# ------------ |
| 24 | +# In this example we see how to apply VRFT to a simple SISO model |
| 25 | +# with measurement noise using instrumental variables |
| 26 | +# Input data is generated using random normal noise |
| 27 | +# |
| 28 | + |
| 29 | +#Generate time and u(t) signals |
| 30 | +t_start = 0 |
| 31 | +t_end = 10 |
| 32 | +dt = 1e-2 |
| 33 | +t = np.array([i * dt for i in range(int(t_end/dt ))]) |
| 34 | + |
| 35 | +#Experiment |
| 36 | +num = [0.5] |
| 37 | +den = [1, -0.9] |
| 38 | +sys = ExtendedTF(num, den, dt=dt) |
| 39 | + |
| 40 | +def generate_data(sys, u, t): |
| 41 | + t, y = scipysig.dlsim(sys, u, t) |
| 42 | + y = y.flatten() + 0.5 * np.random.normal(size = t.size) |
| 43 | + return iddata(y, u, dt, [0]) |
| 44 | + |
| 45 | +u = np.random.normal(size=t.size) |
| 46 | +data1 = generate_data(sys, u, t) |
| 47 | +data2 = generate_data(sys, u, t) |
| 48 | +data = [data1, data2] |
| 49 | + |
| 50 | +#Reference Model |
| 51 | +refModel = ExtendedTF([0.6], [1, -0.4], dt=dt) |
| 52 | + |
| 53 | +#PI Controller |
| 54 | +control = [ExtendedTF([1], [1, -1], dt=dt), |
| 55 | + ExtendedTF([1, 0], [1, -1], dt=dt)] |
| 56 | + |
| 57 | +#Experiment filter |
| 58 | +prefilter = refModel * (1 - refModel) |
| 59 | + |
| 60 | +# VRFT method with Instrumental variables |
| 61 | +theta_iv, r_iv, loss_iv, C_iv = compute_vrft(data, refModel, control, prefilter, iv=True) |
| 62 | + |
| 63 | +# VRFT method without Instrumental variables |
| 64 | +theta_noiv, r_noiv, loss_noiv, C_noiv = compute_vrft(data1, refModel, control, prefilter, iv=False) |
| 65 | + |
| 66 | +#Obtained controller |
| 67 | +print('------IV------') |
| 68 | +print("Loss: {}\nTheta: {}\nController: {}".format(loss_iv, theta_iv, C_iv)) |
| 69 | +print('------No IV------') |
| 70 | +print("Loss: {}\nTheta: {}\nController: {}".format(loss_noiv, theta_noiv, C_noiv)) |
| 71 | + |
| 72 | + |
| 73 | +# Closed loop system |
| 74 | +closed_loop_iv = (C_iv * sys).feedback() |
| 75 | +closed_loop_noiv = (C_noiv * sys).feedback() |
| 76 | + |
| 77 | +t = t[:len(r_iv)] |
| 78 | +u = np.ones(len(t)) |
| 79 | + |
| 80 | +_, yr = scipysig.dlsim(refModel, u, t) |
| 81 | +_, yc_iv = scipysig.dlsim(closed_loop_iv, u, t) |
| 82 | +_, yc_noiv = scipysig.dlsim(closed_loop_noiv, u, t) |
| 83 | +_, ys = scipysig.dlsim(sys, u, t) |
| 84 | + |
| 85 | +yr = yr.flatten() |
| 86 | +ys = ys.flatten() |
| 87 | +yc_noiv = yc_noiv.flatten() |
| 88 | +yc_iv = yc_iv.flatten() |
| 89 | + |
| 90 | +fig, ax = plt.subplots(4, sharex=True, figsize=(12,8), dpi= 100, facecolor='w', edgecolor='k') |
| 91 | +ax[0].plot(t, yr,label='Ref System') |
| 92 | +ax[0].plot(t, yc_iv, label='CL System - IV') |
| 93 | +ax[0].plot(t, yc_noiv, label='CL System - No IV') |
| 94 | +ax[0].set_title('CL Systems response') |
| 95 | +ax[0].grid(True) |
| 96 | +ax[1].plot(t, ys, label='OL System') |
| 97 | +ax[1].set_title('OL Systems response') |
| 98 | +ax[1].grid(True) |
| 99 | +ax[2].plot(t, data1.y[:len(r_iv)]) |
| 100 | +ax[2].grid(True) |
| 101 | +ax[2].set_title('Experiment data') |
| 102 | +ax[3].plot(t, r_iv) |
| 103 | +ax[3].grid(True) |
| 104 | +ax[3].set_title('Virtual Reference') |
| 105 | + |
| 106 | +# Now add the legend with some customizations. |
| 107 | +legend = ax[0].legend(loc='lower right', shadow=True) |
| 108 | + |
| 109 | +# The frame is matplotlib.patches.Rectangle instance surrounding the legend. |
| 110 | +frame = legend.get_frame() |
| 111 | +frame.set_facecolor('0.90') |
| 112 | + |
| 113 | + |
| 114 | +plt.show() |
0 commit comments