example_siso_pulley_deepc.py 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. import numpy as np
  2. import scipy.signal as scipysig
  3. import cvxpy as cp
  4. import matplotlib.pyplot as plt
  5. from fontTools.misc.cython import returns
  6. from typing import List
  7. from cvxpy.expressions.expression import Expression
  8. from cvxpy.constraints.constraint import Constraint
  9. from pydeepc import DeePC
  10. from pydeepc.utils import Data
  11. from utils import System
  12. from scipy.signal import step
  13. from scipy import signal
  14. ### To ignore warnings about cp.ECOS not being available
  15. import warnings
  16. warnings.simplefilter(action='ignore', category=FutureWarning)
  17. warnings.simplefilter(action='ignore', category=UserWarning)
  18. # Define the loss function for DeePC
  19. def loss_callback(u: cp.Variable, y: cp.Variable) -> Expression:
  20. horizon, M, P = u.shape[0], u.shape[1], y.shape[1]
  21. # Sum_t ||y_t - 1||^2
  22. return 1e3 * cp.norm(y-1,'fro')**2 + 1e-1 * cp.norm(u, 'fro')**2
  23. # Define the constraints for DeePC
  24. def constraints_callback(u: cp.Variable, y: cp.Variable) -> List[Constraint]:
  25. horizon, M, P = u.shape[0], u.shape[1], y.shape[1]
  26. # Define a list of input/output constraints (no constraints here)
  27. return []
  28. # DeePC paramters
  29. s = 1 # How many steps before we solve again the DeePC problem
  30. T_INI = 4 # Size of the initial set of data
  31. # T_list = [50, 500] # Number of data points used to estimate the system
  32. T_list = [1000] # Number of data points used to estimate the system 训练数据的个数,熟练越多,效果越好
  33. HORIZON = 10 # Horizon length defaut:10
  34. LAMBDA_G_REGULARIZER = 20 # g regularizer (see DeePC paper, eq. 8) defaut:1
  35. LAMBDA_Y_REGULARIZER = 0 # y regularizer (see DeePC paper, eq. 8) 解决测量数据有噪声时的鲁棒性 defaut:1
  36. LAMBDA_U_REGULARIZER = 0 # u regularizer
  37. EXPERIMENT_HORIZON = 100 # Total number of steps
  38. # Plant
  39. # In this example we consider the three-pulley
  40. # system analyzed in the original VRFT paper:
  41. #
  42. # "Virtual reference feedback tuning:
  43. # a direct method for the design offeedback controllers"
  44. # -- Campi et al. 2003
  45. dt = 0.05
  46. num = [0.28261, 0.50666]
  47. den = [1, -1.41833, 1.58939, -1.31608, 0.88642]
  48. sys = System(scipysig.TransferFunction(num, den, dt=dt).to_ss(), noise_std=1e-2) #转换为状态空间
  49. # 画图看看系统的响应
  50. # # lti = scipysig.lti([1],[1,1])
  51. # lti = scipysig.lti(num,den)
  52. # t, y = scipysig.step(lti,None,None,10000) # 计算单位阶跃响应,t是时间向量,y是系统输出向量
  53. # # t, y = scipysig.impulse(lti) # 计算单位阶跃响应,t是时间向量,y是系统输出向量
  54. #
  55. # # plt.plot(t[0:300], y[0:300])
  56. # plt.plot(t,y)
  57. # plt.xlabel('Time [s]')
  58. # plt.ylabel('Amplitude')
  59. # plt.title('Step Response')
  60. # plt.grid()
  61. # plt.show()
  62. # exit()
  63. fig, ax = plt.subplots(1, 2, figsize=(10,4))
  64. plt.margins(x=0, y=0)
  65. # Simulate for different values of T
  66. i=0
  67. for T in T_list:
  68. i=i+1
  69. print(f'Simulating with {T} initial samples...count={i}')
  70. sys.reset()
  71. # Generate initial data and initialize DeePC data : u->1000*1 y-> 1000*1
  72. data = sys.apply_input(u = np.random.normal(size=T).reshape((T, 1)))
  73. data_train = data
  74. #Uf 10*987 Up 4*987 Yf 10*987 Yp 4*987 Tini=4 horizon=10
  75. deepc = DeePC(data, Tini = T_INI, horizon = HORIZON)
  76. # deepc = DeePC(data, Tini=T_INI, horizon=HORIZON, explained_variance=.9999)
  77. # Create initial data u:4*1 y:4*1
  78. data_ini = Data(u = np.zeros((T_INI, 1)), y = np.zeros((T_INI, 1)))
  79. sys.reset(data_ini = data_ini)
  80. deepc.build_problem(
  81. build_loss = loss_callback,
  82. build_constraints = constraints_callback,
  83. lambda_g = LAMBDA_G_REGULARIZER,
  84. lambda_y = LAMBDA_Y_REGULARIZER,
  85. lambda_u = LAMBDA_U_REGULARIZER)
  86. for idx in range(EXPERIMENT_HORIZON // s): #整除
  87. # Solve DeePC u_optimal:10*1
  88. u_optimal, info = deepc.solve(data_ini = data_ini, warm_start=True, solver=cp.ECOS)
  89. # Apply optimal control input 计算出来控制量u 取第1:s行,所有列数据
  90. _ = sys.apply_input(u = u_optimal[:s, :])
  91. # Fetch last T_INI samples 计算出来的u:4*1 y4*1
  92. data_ini = sys.get_last_n_samples(T_INI)
  93. if idx % 10 == 1 :
  94. print(f'idx={idx}/{EXPERIMENT_HORIZON // s}')
  95. # Plot curve
  96. data = sys.get_all_samples()
  97. ax[0].plot(data.y[T_INI:], label=f'$s={s}, T={T}, T_i={T_INI}, N={HORIZON}$')
  98. ax[1].plot(data.u[T_INI:], label=f'$s={s}, T={T}, T_i={T_INI}, N={HORIZON}$')
  99. # plt.figure()
  100. # plt.plot(data_train.u,data_train.y,'r-');
  101. # plt.title('This is the trainning data')
  102. # plt.grid()
  103. #
  104. # ax[0].set_ylim(0, 2)
  105. # ax[1].set_ylim(-4, 4)
  106. ax[0].set_xlabel('t')
  107. ax[0].set_ylabel('y')
  108. ax[0].grid()
  109. ax[1].set_ylabel('u')
  110. ax[1].set_xlabel('t')
  111. ax[1].grid()
  112. ax[0].set_title('Closed loop - output signal $y_t$')
  113. ax[1].set_title('Closed loop - control signal $u_t$')
  114. ax[0].legend(fancybox=True, shadow=True)
  115. plt.show()
  116. #
  117. #
  118. # # DeePC paramters
  119. # s = 1 # How many steps before we solve again the DeePC problem
  120. # T_INI = 4 # Size of the initial set of data
  121. # T_list = [1000] # Number of data points used to estimate the system
  122. # HORIZON = 100 # Horizon length
  123. # LAMBDA_G_REGULARIZER = 20 # g regularizer (see DeePC paper, eq. 8)
  124. # LAMBDA_Y_REGULARIZER = 0 # y regularizer (see DeePC paper, eq. 8)
  125. # LAMBDA_U_REGULARIZER = 0 # u regularizer
  126. # EXPERIMENT_HORIZON = 100 # Total number of steps
  127. #
  128. # # Plant
  129. # # In this example we consider the three-pulley
  130. # # system analyzed in the original VRFT paper:
  131. # #
  132. # # "Virtual reference feedback tuning:
  133. # # a direct method for the design offeedback controllers"
  134. # # -- Campi et al. 2003
  135. #
  136. # dt = 0.05
  137. # num = [0.28261, 0.50666]
  138. # den = [1, -1.41833, 1.58939, -1.31608, 0.88642]
  139. # sys = System(scipysig.TransferFunction(num, den, dt=dt).to_ss(), noise_std=1e-2)
  140. #
  141. # fig, ax = plt.subplots(1, 2, figsize=(10,4))
  142. # plt.margins(x=0, y=0)
  143. #
  144. #
  145. # # Simulate for different values of T
  146. # for T in T_list:
  147. # print(f'Simulating with {T} initial samples...')
  148. # sys.reset()
  149. # # Generate initial data and initialize DeePC
  150. # data = sys.apply_input(u = np.random.normal(size=T).reshape((T, 1)))
  151. # deepc = DeePC(data, Tini = T_INI, horizon = HORIZON, explained_variance = .99)
  152. #
  153. # # Create initial data
  154. # data_ini = Data(u = np.zeros((T_INI, 1)), y = np.zeros((T_INI, 1)))
  155. # sys.reset(data_ini = data_ini)
  156. #
  157. # deepc.build_problem(
  158. # build_loss = loss_callback,
  159. # build_constraints = constraints_callback,
  160. # lambda_g = LAMBDA_G_REGULARIZER,
  161. # lambda_y = LAMBDA_Y_REGULARIZER,
  162. # lambda_u = LAMBDA_U_REGULARIZER)
  163. #
  164. # for idx in range(EXPERIMENT_HORIZON // s):
  165. # # Solve DeePC
  166. # u_optimal, info = deepc.solve(data_ini = data_ini, warm_start=True, solver=cp.ECOS)
  167. #
  168. #
  169. # # Apply optimal control input
  170. # _ = sys.apply_input(u = u_optimal[:s, :])
  171. #
  172. # # Fetch last T_INI samples
  173. # data_ini = sys.get_last_n_samples(T_INI)
  174. #
  175. # if idx % 10 == 1 :
  176. # print(f'idx={idx}/{EXPERIMENT_HORIZON // s}')
  177. #
  178. #
  179. # # Plot curve
  180. # data = sys.get_all_samples()
  181. # ax[0].plot(data.y[T_INI:], label=f'$s={s}, T={T}, T_i={T_INI}, N={HORIZON}$')
  182. # ax[1].plot(data.u[T_INI:], label=f'$s={s}, T={T}, T_i={T_INI}, N={HORIZON}$')
  183. #
  184. # ax[0].set_ylim(0, 2)
  185. # ax[1].set_ylim(-4, 4)
  186. # ax[0].set_xlabel('t')
  187. # ax[0].set_ylabel('y')
  188. # ax[0].grid()
  189. # ax[1].set_ylabel('u')
  190. # ax[1].set_xlabel('t')
  191. # ax[1].grid()
  192. # ax[0].set_title('Closed loop - output signal $y_t$')
  193. # ax[1].set_title('Closed loop - control signal $u_t$')
  194. # ax[0].legend(fancybox=True, shadow=True)
  195. # plt.show()