123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228 |
- import numpy as np
- import scipy.signal as scipysig
- import cvxpy as cp
- import matplotlib.pyplot as plt
- from fontTools.misc.cython import returns
- from typing import List
- from cvxpy.expressions.expression import Expression
- from cvxpy.constraints.constraint import Constraint
- from pydeepc import DeePC
- from pydeepc.utils import Data
- from utils import System
- from scipy.signal import step
- from scipy import signal
- ### To ignore warnings about cp.ECOS not being available
- import warnings
- warnings.simplefilter(action='ignore', category=FutureWarning)
- warnings.simplefilter(action='ignore', category=UserWarning)
- # Define the loss function for DeePC
- def loss_callback(u: cp.Variable, y: cp.Variable) -> Expression:
- horizon, M, P = u.shape[0], u.shape[1], y.shape[1]
- # Sum_t ||y_t - 1||^2
- return 1e3 * cp.norm(y-1,'fro')**2 + 1e-1 * cp.norm(u, 'fro')**2
- # Define the constraints for DeePC
- def constraints_callback(u: cp.Variable, y: cp.Variable) -> List[Constraint]:
- horizon, M, P = u.shape[0], u.shape[1], y.shape[1]
- # Define a list of input/output constraints (no constraints here)
- return []
- # DeePC paramters
- s = 1 # How many steps before we solve again the DeePC problem
- T_INI = 4 # Size of the initial set of data
- # T_list = [50, 500] # Number of data points used to estimate the system
- T_list = [1000] # Number of data points used to estimate the system 训练数据的个数,熟练越多,效果越好
- HORIZON = 10 # Horizon length defaut:10
- LAMBDA_G_REGULARIZER = 20 # g regularizer (see DeePC paper, eq. 8) defaut:1
- LAMBDA_Y_REGULARIZER = 0 # y regularizer (see DeePC paper, eq. 8) 解决测量数据有噪声时的鲁棒性 defaut:1
- LAMBDA_U_REGULARIZER = 0 # u regularizer
- EXPERIMENT_HORIZON = 100 # Total number of steps
- # Plant
- # In this example we consider the three-pulley
- # system analyzed in the original VRFT paper:
- #
- # "Virtual reference feedback tuning:
- # a direct method for the design offeedback controllers"
- # -- Campi et al. 2003
- dt = 0.05
- num = [0.28261, 0.50666]
- den = [1, -1.41833, 1.58939, -1.31608, 0.88642]
- sys = System(scipysig.TransferFunction(num, den, dt=dt).to_ss(), noise_std=1e-2) #转换为状态空间
- # 画图看看系统的响应
- # # lti = scipysig.lti([1],[1,1])
- # lti = scipysig.lti(num,den)
- # t, y = scipysig.step(lti,None,None,10000) # 计算单位阶跃响应,t是时间向量,y是系统输出向量
- # # t, y = scipysig.impulse(lti) # 计算单位阶跃响应,t是时间向量,y是系统输出向量
- #
- # # plt.plot(t[0:300], y[0:300])
- # plt.plot(t,y)
- # plt.xlabel('Time [s]')
- # plt.ylabel('Amplitude')
- # plt.title('Step Response')
- # plt.grid()
- # plt.show()
- # exit()
- fig, ax = plt.subplots(1, 2, figsize=(10,4))
- plt.margins(x=0, y=0)
- # Simulate for different values of T
- i=0
- for T in T_list:
- i=i+1
- print(f'Simulating with {T} initial samples...count={i}')
- sys.reset()
- # Generate initial data and initialize DeePC data : u->1000*1 y-> 1000*1
- data = sys.apply_input(u = np.random.normal(size=T).reshape((T, 1)))
- data_train = data
- #Uf 10*987 Up 4*987 Yf 10*987 Yp 4*987 Tini=4 horizon=10
- deepc = DeePC(data, Tini = T_INI, horizon = HORIZON)
- # deepc = DeePC(data, Tini=T_INI, horizon=HORIZON, explained_variance=.9999)
- # Create initial data u:4*1 y:4*1
- data_ini = Data(u = np.zeros((T_INI, 1)), y = np.zeros((T_INI, 1)))
- sys.reset(data_ini = data_ini)
- deepc.build_problem(
- build_loss = loss_callback,
- build_constraints = constraints_callback,
- lambda_g = LAMBDA_G_REGULARIZER,
- lambda_y = LAMBDA_Y_REGULARIZER,
- lambda_u = LAMBDA_U_REGULARIZER)
- for idx in range(EXPERIMENT_HORIZON // s): #整除
- # Solve DeePC u_optimal:10*1
- u_optimal, info = deepc.solve(data_ini = data_ini, warm_start=True, solver=cp.ECOS)
- # Apply optimal control input 计算出来控制量u 取第1:s行,所有列数据
- _ = sys.apply_input(u = u_optimal[:s, :])
- # Fetch last T_INI samples 计算出来的u:4*1 y4*1
- data_ini = sys.get_last_n_samples(T_INI)
- if idx % 10 == 1 :
- print(f'idx={idx}/{EXPERIMENT_HORIZON // s}')
- # Plot curve
- data = sys.get_all_samples()
- ax[0].plot(data.y[T_INI:], label=f'$s={s}, T={T}, T_i={T_INI}, N={HORIZON}$')
- ax[1].plot(data.u[T_INI:], label=f'$s={s}, T={T}, T_i={T_INI}, N={HORIZON}$')
- # plt.figure()
- # plt.plot(data_train.u,data_train.y,'r-');
- # plt.title('This is the trainning data')
- # plt.grid()
- #
- # ax[0].set_ylim(0, 2)
- # ax[1].set_ylim(-4, 4)
- ax[0].set_xlabel('t')
- ax[0].set_ylabel('y')
- ax[0].grid()
- ax[1].set_ylabel('u')
- ax[1].set_xlabel('t')
- ax[1].grid()
- ax[0].set_title('Closed loop - output signal $y_t$')
- ax[1].set_title('Closed loop - control signal $u_t$')
- ax[0].legend(fancybox=True, shadow=True)
- plt.show()
- #
- #
- # # DeePC paramters
- # s = 1 # How many steps before we solve again the DeePC problem
- # T_INI = 4 # Size of the initial set of data
- # T_list = [1000] # Number of data points used to estimate the system
- # HORIZON = 100 # Horizon length
- # LAMBDA_G_REGULARIZER = 20 # g regularizer (see DeePC paper, eq. 8)
- # LAMBDA_Y_REGULARIZER = 0 # y regularizer (see DeePC paper, eq. 8)
- # LAMBDA_U_REGULARIZER = 0 # u regularizer
- # EXPERIMENT_HORIZON = 100 # Total number of steps
- #
- # # Plant
- # # In this example we consider the three-pulley
- # # system analyzed in the original VRFT paper:
- # #
- # # "Virtual reference feedback tuning:
- # # a direct method for the design offeedback controllers"
- # # -- Campi et al. 2003
- #
- # dt = 0.05
- # num = [0.28261, 0.50666]
- # den = [1, -1.41833, 1.58939, -1.31608, 0.88642]
- # sys = System(scipysig.TransferFunction(num, den, dt=dt).to_ss(), noise_std=1e-2)
- #
- # fig, ax = plt.subplots(1, 2, figsize=(10,4))
- # plt.margins(x=0, y=0)
- #
- #
- # # Simulate for different values of T
- # for T in T_list:
- # print(f'Simulating with {T} initial samples...')
- # sys.reset()
- # # Generate initial data and initialize DeePC
- # data = sys.apply_input(u = np.random.normal(size=T).reshape((T, 1)))
- # deepc = DeePC(data, Tini = T_INI, horizon = HORIZON, explained_variance = .99)
- #
- # # Create initial data
- # data_ini = Data(u = np.zeros((T_INI, 1)), y = np.zeros((T_INI, 1)))
- # sys.reset(data_ini = data_ini)
- #
- # deepc.build_problem(
- # build_loss = loss_callback,
- # build_constraints = constraints_callback,
- # lambda_g = LAMBDA_G_REGULARIZER,
- # lambda_y = LAMBDA_Y_REGULARIZER,
- # lambda_u = LAMBDA_U_REGULARIZER)
- #
- # for idx in range(EXPERIMENT_HORIZON // s):
- # # Solve DeePC
- # u_optimal, info = deepc.solve(data_ini = data_ini, warm_start=True, solver=cp.ECOS)
- #
- #
- # # Apply optimal control input
- # _ = sys.apply_input(u = u_optimal[:s, :])
- #
- # # Fetch last T_INI samples
- # data_ini = sys.get_last_n_samples(T_INI)
- #
- # if idx % 10 == 1 :
- # print(f'idx={idx}/{EXPERIMENT_HORIZON // s}')
- #
- #
- # # Plot curve
- # data = sys.get_all_samples()
- # ax[0].plot(data.y[T_INI:], label=f'$s={s}, T={T}, T_i={T_INI}, N={HORIZON}$')
- # ax[1].plot(data.u[T_INI:], label=f'$s={s}, T={T}, T_i={T_INI}, N={HORIZON}$')
- #
- # ax[0].set_ylim(0, 2)
- # ax[1].set_ylim(-4, 4)
- # ax[0].set_xlabel('t')
- # ax[0].set_ylabel('y')
- # ax[0].grid()
- # ax[1].set_ylabel('u')
- # ax[1].set_xlabel('t')
- # ax[1].grid()
- # ax[0].set_title('Closed loop - output signal $y_t$')
- # ax[1].set_title('Closed loop - control signal $u_t$')
- # ax[0].legend(fancybox=True, shadow=True)
- # plt.show()
|