├── .gitattributes ├── DeePC.m ├── LICENSE ├── MFAPC.m ├── README.md └── WKPC.m /.gitattributes: -------------------------------------------------------------------------------- 1 | *.m linguist-language=Matlab 2 | -------------------------------------------------------------------------------- /DeePC.m: -------------------------------------------------------------------------------- 1 | %_____________________________________________________________________% 2 | % Comparative Analysis of Data-Driven Predictive Control Strategies 3 | % 2023 9th International Conference on Control, Instrumentation, 4 | % and Automation. 5 | % December 2023 6 | % Sohrab (Ali) Rezaei, Ali Khaki-Sedigh 7 | % Data-Enabled Predictive Control (DeePC) 8 | % Software Generated by Sohrab Rezaei 9 | % 10 | % This software documentation accompanies the paper and is freely 11 | % available for use. 12 | % Please keep this information for proper attribution and 13 | % to provide feedback. 14 | % Email: arezaei2@jhu.edu 15 | %_____________________________________________________________________% 16 | 17 | %% Clear workspace, command window, and close all figures 18 | clear; clc; close all; 19 | % Set the random number generator to its default state. 20 | % Note: Due to the use of random input data, the results of the simulation may vary with each run. 21 | % To ensure consistent results across runs, uncomment the line below to set the random seed: 22 | rng('default'); 23 | 24 | %% Flag to determine whether to use the previous alpha values 25 | ALPHA_PREVIOUS = true; 26 | 27 | %% Optimization options 28 | options = mskoptimset('OptimalityTolerance', 1e-9, ... 29 | 'MaxIterations', 20000, ... 30 | 'ConstraintTolerance', 1e-9); 31 | 32 | %% Define the system dynamics function 33 | global uu 34 | sys = @func_sys; 35 | 36 | %% Initialize time array for storing computation times 37 | u_Time = []; 38 | 39 | %% Setup 40 | % Define system dimensions 41 | n = 2; % No. system states 42 | m = 1; % No. input 43 | l = 1; % No. output 44 | T_s = 0.1; % Sampling time 45 | C = [1, 0]; % Output matrix 46 | % Data parameters 47 | T = 20 / T_s; 48 | % Predictive Control parameters 49 | Tini = 3; 50 | N = 5; % Prediction horizon 51 | M_step = 1; % Number of consecutive applications of optimal input (multi-step) 52 | Tf = 40 / T_s; % Closed-loop horizon (simulation length) 53 | y_T = 0.3; 54 | 55 | % Define weighting matrices 56 | Q = 1 * eye(l); 57 | R = 0.1 * eye(m); 58 | S = 3 * eye(l); 59 | scale = 100; 60 | Q = Q * scale; 61 | R = R * scale; 62 | S = S * scale; 63 | lambda_g = 50; 64 | lambda_sigma = 1e7; 65 | 66 | %% Data Generation 67 | % Define initial conditions and parameters for system disturbance 68 | x0 = [-0; 0]; 69 | tau = Tf * 1.25; 70 | TTF = 10 / T_s; 71 | s1 = 20 * pi / 180 * ones(1, TTF); 72 | s2 = -10 * pi / 180 * ones(1, TTF); 73 | s3 = 10 * pi / 180 * ones(1, TTF); 74 | s4 = -20 * pi / 180 * ones(1, TTF + N + 1); 75 | r = [s1 s2 s3 s4]; 76 | u_test(1, :) = 3.5 * (2 * (rand(T, 1)) - 1); 77 | x_test = zeros(n, N + 1); 78 | y_test = zeros(l, N); 79 | for i = 1:T 80 | uu = u_test(:, i); 81 | t = i * T_s; 82 | [~, x] = ode45(sys, [t t + T_s], x_test(:, i)); 83 | x_test(:, i + 1) = x(end, :); 84 | y_test(:, i) = C * x_test(:, i); 85 | end 86 | 87 | % Memory initialization 88 | u_mem = u_test; 89 | y_mem = y_test; 90 | x_mem = x_test; 91 | u_mem = [u_mem zeros(l, Tini)]; 92 | y_mem = [y_mem zeros(l, Tini)]; 93 | x_mem = [x_mem zeros(n, Tini)]; 94 | cost_mem = []; 95 | 96 | %% Set up DeePC 97 | % Define constraints and bounds 98 | a1 = 3.5; % Bound on u_bar 99 | a2 = 70 * pi / 180; % Bound on y_bar 100 | a3 = a1 * 0.99; % Bound on us 101 | a4 = 70 * pi / 180 * 0.99; % Bound on ys 102 | u_min = -a1; 103 | u_max = a1; 104 | us_min = -a2; 105 | us_max = a2; 106 | 107 | % Optimization variable: x = [u_bar, y_bar, u_s, y_s, g, sigma, beta] 108 | % Cost Functoin: J=1/2*x'*H*x 109 | H=zeros(m*(N+Tini+1)+l*(2*(N+Tini)+1)+T-Tini-N+1); 110 | l_g=T-Tini-N+1; 111 | l_sigma=l*Tini; 112 | for i=1:l_g 113 | if i <= N 114 | H(m*(i-1)+1:m*i,m*(i-1)+1:m*i)=R; 115 | H(m*(i-1)+1:m*i,N*(m+l)+1)=-R; 116 | H(N*(m+l)+1,m*(i-1)+1:m*i)=-R; 117 | H(N*(m+l)+1,N*(m+l)+1)=N*R; 118 | H(N*m+i,N*m+i)=Q; 119 | H(N*m+i,N*(m+l)+m+1)=-Q; 120 | H(N*(m+l)+m+1,N*m+i)=-Q; 121 | H(N*(m+l)+m+1,N*(m+l)+m+1)=N*(Q+S); 122 | H(N*(m+l)+m+l+l_g+l_sigma+i,N*(m+l)+m+l+l_g+l_sigma+i)=S; 123 | H(N*(m+l)+m+l+l_g+l_sigma+i,N*(m+l)+m+1)=-S; 124 | H(N*(m+l)+m+1,N*(m+l)+m+l+l_g+l_sigma+i)=-S; 125 | end 126 | H(N*(m+l)+m+l+i,N*(m+l)+m+l+i)=lambda_g; 127 | if i <= l_sigma 128 | H(N*(m+l)+m+l+l_g+i,N*(m+l)+m+l+l_g+i)=lambda_sigma; 129 | end 130 | end 131 | aa1=[zeros(Tini,N);-eye(N)]; 132 | aa2=[-eye(Tini,Tini);zeros((N),Tini)]; 133 | aa3=[ones(1,N),zeros(1,T-2*N-Tini+1)]; 134 | A3=[zeros(1,(N+1)*(m+l)),aa3,zeros(1,l_sigma+l*N+Tini*(m+l))]; 135 | A4=[zeros(Tini,(N+1)*(m+l)+l_g+l_sigma+l*N),eye(Tini),zeros(Tini,Tini*l)]; 136 | A5=[zeros(Tini,(N+1)*(m+l)+l_g+l_sigma+l*N+m*Tini),eye(Tini)]; 137 | A6=[zeros(N,(N+1)*(m+l)+l_g+l_sigma),eye(N),zeros(N,(m+l)*Tini)]; 138 | A7=[zeros(Tini,N-Tini),eye(Tini),zeros(Tini,l*N),-ones(Tini,m),zeros(Tini,l+l_g+l_sigma+l*N+Tini*(m+l))]; 139 | A8=[zeros(Tini,m*N),zeros(Tini,N-Tini),eye(Tini),zeros(Tini,m),-ones(Tini,m),zeros(Tini,l_g+l_sigma+l*N+Tini*(m+l))]; 140 | B12=zeros((m+l)*(N+Tini),1); 141 | B3=1; 142 | B78=zeros((m+l)*(Tini),1); 143 | A_ineq = []; 144 | b_ineq = []; 145 | % Constraints 146 | lower=[-a1*ones(m*N,1);-a2*ones(l*N,1);-a3*ones(m,1);-a4*ones(l,1);-inf*ones(l_g+l_sigma+l*N+(m+l)*Tini,1)]; 147 | upper=[a1*ones(m*N,1);a2*ones(l*N,1);a3*ones(m,1);a4*ones(l,1);inf*ones(l_g+l_sigma+l*N+(m+l)*Tini,1)]; 148 | 149 | % Initializations 150 | f = zeros(size(H, 1), 1)'; 151 | H_u = Hankel_p(u_mem(:, end - T + 1:end), N + Tini); 152 | H_y = Hankel_p(y_mem(:, end - T + 1:end), N + Tini); 153 | 154 | %% DeePC iterations 155 | for i = 1:M_step:Tf 156 | % Extract initial conditions from memory 157 | u_ini = u_mem(:, end - Tini + 1:end); 158 | y_ini = y_mem(:, end - Tini + 1:end); 159 | 160 | % Desired output 161 | rd = r(:, i + 1:i + N); 162 | % Cost function related Matrices 163 | A1=[aa1,zeros(N+Tini,l*(N+1)+m),H_u,zeros(N+Tini,l*N+l_sigma),aa2,zeros(N+Tini,l*Tini)]; 164 | A2=[zeros(N+Tini,m*N),aa1,zeros(N+Tini,l+m),H_y,-eye(N+Tini,l_sigma),zeros(N+Tini,l*N),zeros(N+Tini,m*Tini),aa2]; 165 | B4=reshape(u_ini,[],1); 166 | B5=reshape(y_ini,[],1); 167 | B6=reshape(rd,[],1); 168 | A_eq=[A1;A2;A3;A4;A5;A6;A7;A8]; 169 | B_eq=[B12;B3;B4;B5;B6;B78]; 170 | 171 | % Solve optimization problem 172 | tic 173 | [sol, fval, exitflag, output, lambda] = quadprog(H, f, A_ineq, b_ineq, A_eq, B_eq, lower, upper, [], options); 174 | u_s = sol(1:m * M_step); 175 | TT_u = toc; 176 | u_Time = [u_Time TT_u]; 177 | 178 | % Simulate system output 179 | x_1 = zeros(n, M_step + 1); 180 | x_1(:, 1) = x_mem(:, end); 181 | y_1 = zeros(l, M_step); 182 | for k = 1:M_step 183 | uu = u_s(:, k); 184 | t = k * T_s; 185 | [~, x] = ode23t(sys, [t t + T_s], x_1(:, k)); 186 | x_1(:, k + 1) = x(end, :); 187 | y_1(:, k) = C * x_1(:, k); 188 | end 189 | 190 | % Update memory 191 | u_mem = [u_mem u_s]; 192 | y_mem = [y_mem y_1]; 193 | x_mem = [x_mem x_1]; 194 | cost_mem = [cost_mem fval]; 195 | 196 | % Display current iteration information 197 | disp("Sample Time is : " + num2str(i)) 198 | disp("System output is: " + num2str(y_mem(:, end))) 199 | disp("System input is : " + num2str(u_s(:, end))) 200 | end 201 | avg_time=sum(u_Time)/numel(u_Time); 202 | disp(avg_time) 203 | save Deepc.mat 204 | y_mem=y_mem*180/pi; 205 | r=r*180/pi; 206 | %% plotting results 207 | time=0:T_s:3*(Tf+T+4)*T_s; 208 | time=time(1:numel(y_mem)); 209 | time2=T*T_s:T_s:(Tf+T+4)*T_s; 210 | w1=2.2; % width 1 -- first line 211 | w2=1.5; % width 2 -- second line 212 | w3=1.5; % width 3 -- box line width 213 | xx0=0; % figuer location 214 | yy0=0; % figuer location 215 | width=850; % image width -- convert cm to pixel 216 | height=750; % image height -- convert cm to pixel 217 | t_it="\itt"; 218 | xleb="\its"; 219 | figure 220 | subplot(3,1,1) 221 | for i=1:l 222 | plot(time,y_mem(i,:),'r','LineWidth',w1); 223 | hold on; 224 | stairs(time2,r(:,1:numel(time2)),'b:','LineWidth',w2); 225 | xlabel("\fontname{Times New Roman}\bf\fontsize{10}Time (" + ... 226 | xleb+"\rm\fontname{Times New Roman}\bf\fontsize{10})",'FontWeight','bold') 227 | ylabel( {'\fontname{Times New Roman}\bf\fontsize{9}DeePC'... 228 | ;'Output and Reference Signals'}) 229 | legend("y("+t_it+"\rm)","r("+t_it+"\rm)",'Location','best') 230 | grid off 231 | box on 232 | end 233 | xlim([0 time(end)]) 234 | 235 | subplot(3,1,2) 236 | for i=1:m 237 | plot(time,u_mem(i,:),'r','LineWidth',w2); 238 | xlabel("\fontname{Times New Roman}\bf\fontsize{10}Time (" + ... 239 | xleb+"\rm\fontname{Times New Roman}\bf\fontsize{10})",'FontWeight','bold') 240 | ylabel( {'\fontname{Times New Roman}\bf\fontsize{10}DeePC'... 241 | ;'Control Signal'}) 242 | end 243 | xlim([0 time(end)]) 244 | 245 | subplot(3,1,3) 246 | plot(time2(1:length(cost_mem)),cost_mem,'r','LineWidth',w2); 247 | xlabel("\fontname{Times New Roman}\bf\fontsize{10}Time (" + ... 248 | xleb+"\rm\fontname{Times New Roman}\bf\fontsize{10})",'FontWeight','bold') 249 | ylabel( {'\fontname{Times New Roman}\bf\fontsize{10}DeePC'... 250 | ;'Cost Function'}) 251 | xlim([0,time2(length(cost_mem))]) 252 | 253 | 254 | 255 | %% functions 256 | function H=Hankel_p(u,L) 257 | % u should be in the form of [u1 u2 ... uT] 258 | T=size(u,2); 259 | m=size(u,1); 260 | H=zeros(L*m,T-L+1); 261 | for i=1:L 262 | H((i-1)*m+1:i*m,:)=u(:,i:T-L+i); 263 | end 264 | end 265 | 266 | 267 | function f = func_sys(t,x) 268 | global uu 269 | r=0.2; 270 | m=1; 271 | g=9.81; 272 | k=0.4; 273 | f=[x(2) 274 | -g/r*sin(x(1))-k/(m*r)*x(2)+uu/(m*r)]; 275 | 276 | 277 | end -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Sohrab (Ali) Rezaei 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MFAPC.m: -------------------------------------------------------------------------------- 1 | %_____________________________________________________________________% 2 | % Comparative Analysis of Data-Driven Predictive Control Strategies 3 | % 2023 9th International Conference on Control, Instrumentation, 4 | % and Automation. 5 | % December 2023 6 | % Sohrab (Ali) Rezaei, Ali Khaki-Sedigh 7 | % Model-Free Adaptive Predictive Control (MFAPC) 8 | % Software Generated by Sohrab Rezaei 9 | % 10 | % This software documentation accompanies the paper and is freely 11 | % available for use. 12 | % Please keep this information for proper attribution and 13 | % to provide feedback. 14 | % Email: arezaei2@jhu.edu 15 | %_____________________________________________________________________% 16 | %% -------- Initialization ------------------------------------------------ 17 | % Clear workspace, close all figures, and command window 18 | close all; clear; clc; 19 | global uu 20 | 21 | %% -------- Defining Time --------------------------------------------------- 22 | T_s = 0.1; % Sampling time 23 | N = 5; % Prediction horizon 24 | t_t = 0:40/T_s; 25 | Tf = numel(t_t); 26 | time = t_t * T_s; 27 | u_Time = []; 28 | 29 | %% -------- MFAPC Setups --------------------------------------------------- 30 | np = 4; % np is the fixed model order (hierarchical forecasting method) 31 | theta = zeros(np, Tf); 32 | k_s = max(np+1, 5); % Start point of simulation 33 | lambda = 0.37; 34 | ro = 1; 35 | mu = 1; 36 | eta = 1; 37 | sigma = 0.5; % (0,1] 38 | eps = 1e-5; % Resetting constant for SISO 39 | 40 | % Defining phi 41 | phi = zeros(1, Tf); 42 | phi_Ly1 = 0.1 ; 43 | 44 | for i = 1:k_s 45 | phi(:, i) = phi_Ly1; 46 | theta(:, i) = 0.7/np * ones(np, 1); 47 | end 48 | 49 | A1_hat = zeros(N); 50 | M = 2; 51 | E = ones(N, 1); 52 | g_t = [1; zeros(N-1, 1)]'; 53 | 54 | %% -------- System Initialization ----------------------------------------- 55 | n = 2; % True plant states 56 | C = [1, 0]; 57 | x1 = zeros(n, Tf); 58 | 59 | for i = 1:k_s 60 | x1(:, i) = 0; 61 | end 62 | 63 | y = zeros(1, Tf - k_s); 64 | y0 = x1(1) * ones(1, k_s); 65 | y = [y0 y]; 66 | e = zeros(1, Tf); 67 | 68 | %% -------- Y Desired ----------------------------------------------------- 69 | TTF = 10 / T_s; 70 | s1 = 20 * pi / 180 * ones(1, TTF); 71 | s0 = s1(1:k_s - 1); 72 | s2 = -10 * pi / 180 * ones(1, TTF); 73 | s3 = 10 * pi / 180 * ones(1, TTF); 74 | s4 = -20 * pi / 180 * ones(1, TTF + N + 1); 75 | yd = [s0 s1 s2 s3 s4]; 76 | 77 | %% -------- Controller Initialization --------------------------------------- 78 | u = zeros(1, Tf + k_s + 1); % Memory for controller signal 79 | u_lim = 3.5; 80 | 81 | %% -------- Real-time Simulation ------------------------------------------ 82 | for t = k_s:Tf 83 | uu = u(t-1); 84 | % -------- System Simulation ---------------------------------------------- 85 | i = t * T_s; 86 | [td, x] = ode23t(@func_sys, [i i + T_s], x1(:, t-1)); x1(:, t) = x(end, :); 87 | y(:, t) = C * x1(:, t); 88 | 89 | % -------- PPJM/ PJM/ PG/ PPD --------------------------------------------- 90 | tic % Start timer 91 | d_yt = y(t) - y(t-1); % delta_y(t) 92 | utc = u(t-1); 93 | utc0 = u(t-2); 94 | d_uc = (utc - utc0); % delta_u from t-2 --> t-1 95 | dU = d_uc'; % delta_u for CFDL; (t-1) 96 | 97 | % Updating phi 98 | phi(:, t) = phi(:, t-1) + eta * dU * (d_yt - (phi(:, t-1)') * dU) / (mu + (norm(dU))^2); 99 | 100 | % Resetting the phi (if necessary) 101 | ndH = norm(dU); 102 | nphi = norm(phi(:, t)); 103 | 104 | if nphi < eps || ndH < eps || ~isequal(sign(phi(1, t)), sign(phi(1, 1))) 105 | phi(:, t) = phi(:, 1); 106 | end 107 | 108 | % Predictor vector (theta) 109 | phi_hist = phi(:, t-1:-1:t-np)'; 110 | theta(:, t) = theta(:, t-1) + (phi_hist / (sigma + (norm(phi_hist)^2))) * ... 111 | (phi(:, t) - phi_hist.' * theta(:, t-1)); 112 | 113 | if norm(theta(:, t)) >= M 114 | theta(:, t) = theta(:, 1); 115 | end 116 | 117 | % Prediction of phi 118 | for i = 1:N 119 | phi(:, t+i) = theta(:, t).' * phi(:, t+i-1:-1:t+i-np).'; 120 | 121 | if ~isequal(sign(phi(:, t+i)), sign(phi(:, 1))) || norm(phi(:, t+i)) < eps 122 | phi(:, t+i) = phi(:, 1); 123 | end 124 | end 125 | 126 | for i = 1:N 127 | A1_hat(i, :) = [phi(:, t:t+i-1), zeros(1, N-i)]; 128 | end 129 | 130 | % -------- Control Signal ---------------------------------------------- 131 | Y_s = yd(t+1:t+N).'; 132 | dUn = (A1_hat.' * A1_hat + lambda * eye(size(A1_hat, 1)))^(-1) * A1_hat.' * (Y_s - E * y(t)); 133 | u(t) = u(t-1) + g_t * dUn; 134 | 135 | % Limiting the control signal 136 | if abs(u(t)) > u_lim 137 | u(t) = sign(u(t)) * u_lim; 138 | end 139 | 140 | TT_u = toc; % Stop timer 141 | u_Time = [u_Time TT_u]; 142 | end 143 | 144 | avg_time=sum(u_Time)/numel(u_Time); 145 | disp("Average each step run time (s): "+num2str(avg_time)) 146 | y=y(k_s-1:end); 147 | yd=yd(k_s-1:Tf); 148 | u=u(k_s-1:Tf); 149 | e=e(k_s-1:Tf); 150 | y=y*180/pi; 151 | yd=yd*180/pi; 152 | %% -------- plotting ----------------------------------------------------- 153 | m=1;n=1; 154 | Lu=1; 155 | leb='sec'; 156 | time2=(0:1000/T_s+N)*T_s; 157 | 158 | figure 159 | plot(time(1:length(y)),y,'-r','LineWidth',1.5);hold on; 160 | plot(time(1:length(yd)),yd,'-.b','LineWidth',1); 161 | legend('System','Desired','Location','best'); grid; 162 | xlabel(leb); ylabel('System output'); xlim([0 time(end)]) 163 | figure 164 | plot(time(1:end-k_s+2),u,'-r','LineWidth',1.5); grid; 165 | xlabel(leb); ylabel('System input'); xlim([0 time(end)]); 166 | figure 167 | column=m*(Lu); row=m; count=1; 168 | for j=1:m 169 | for i=1:n*Lu 170 | phi_plot=phi(i,:); 171 | subplot(row,column,count); plot(time2(1:length(phi_plot)),phi_plot,'LineWidth',1.25) 172 | ylabel('\phi'); grid; xlabel(leb); xlim([0 time(end)]); 173 | count=count+1; 174 | end 175 | end 176 | 177 | 178 | 179 | %% Functions 180 | 181 | function f = func_sys(t,x) 182 | global uu 183 | r=0.2; 184 | m=1; 185 | g=9.81; 186 | k=0.4; 187 | f=[x(2) 188 | -g/r*sin(x(1))-k/(m*r)*x(2)+uu/(m*r)]; 189 | end 190 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Sohrab Rezaei 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | --- 24 | 25 | This repository contains MATLAB simulation codes generated for the paper titled "Comparative Analysis of Data-Driven Predictive Control Strategies," published in the 2023 9th International Conference on Control, Instrumentation, and Automation. The paper is authored by Sohrab Rezaei & Ali Khaki-Sedigh. 26 | 27 | DOI: https://doi.org/10.1109/ICCIA61416.2023.10506351 28 | 29 | Citation: 30 | Rezaei, Sohrab, and Ali Khaki-Sedigh. "Comparative Analysis of Data-Driven Predictive Control Strategies." 2023 9th International Conference on Control, Instrumentation and Automation (ICCIA). IEEE, 2023. 31 | 32 | For any questions or inquiries about the code, please contact Sohrab Rezaei at arezaei2@jhu.edu. 33 | -------------------------------------------------------------------------------- /WKPC.m: -------------------------------------------------------------------------------- 1 | %_____________________________________________________________________% 2 | % Comparative Analysis of Data-Driven Predictive Control Strategies 3 | % 2023 9th International Conference on Control, Instrumentation, 4 | % and Automation. 5 | % December 2023 6 | % Sohrab Rezaei 7 | % Willems Koopman Predictive Control (WKPC) 8 | % Software Generated by Sohrab Rezaei 9 | % 10 | % This software documentation accompanies the paper and is freely 11 | % available for use. 12 | % Please keep this information for proper attribution and 13 | % to provide feedback. 14 | %_____________________________________________________________________% 15 | 16 | %% Clear workspace, command window, and close all figures 17 | clc; clear; close all; 18 | % Set the random number generator to its default state. 19 | % Note: Due to the use of random input data, the results of the simulation may vary with each run. 20 | % To ensure consistent results across runs, uncomment the line below to set the random seed: 21 | % rng('default'); 22 | %% Optimization options 23 | options = mskoptimset('OptimalityTolerance', 1e-9,... 24 | 'MaxIterations', 20000,... 25 | 'ConstraintTolerance', 1e-9); 26 | %% Define the system dynamics function 27 | global uu 28 | sys = @func_sys; 29 | %% Initialize time array for storing computation times 30 | u_Time=[]; 31 | %% Setup 32 | % Defining system dimensions 33 | n = 2; % No. system states 34 | m = 1; % No. input 35 | l = 1; % No. output 36 | T_s = 0.1; 37 | C=[1,0]; 38 | %% Parameters 39 | N = 5; % Prediction Horizon: Number of future steps considered in the predictive control 40 | M_step = 1; % Number of consecutive applications of optimal input (multi-step) 41 | Tf = 40/T_s; % "Closed-loop horizon" (simulation length) 42 | Tini = 2; % Initialization time, should be greater than the system lag 43 | T = 20/T_s; % Total simulation time 44 | 45 | Q=1*eye(l); % Weighting factor for the system output 46 | R=0.1*eye(m); % Weighting factor for the system input 47 | lambda_g=0.1; % Regularization factor for the optimization problem 48 | 49 | s=1; % Length of the inputs applied to the system 50 | P=10; % Number of eigenfunctions used in the predictive control 51 | n_eig_fcn=P+n; % Total number of eigenfunctions considered in the model 52 | 53 | %% Data Generation 54 | % Define initial conditions and parameters for system disturbance 55 | TTF = 10 / T_s; 56 | s1 = 20 * pi / 180 * ones(1, TTF); 57 | s2 = -10 * pi / 180 * ones(1, TTF); 58 | s3 = 10 * pi / 180 * ones(1, TTF); 59 | s4 = -20 * pi / 180 * ones(1, TTF + N + 1); 60 | r = [s1 s2 s3 s4]; 61 | u_test(1, :) = 3.5 * (2 * (rand(T, 1)) - 1); 62 | x_test=zeros(n,T+1); 63 | y_test=zeros(l,T); 64 | z_test=zeros(P+n,T); 65 | for i=1:T 66 | uu = u_test(:,i); 67 | t = i*T_s; 68 | [~,x] = ode45(sys,[t t+T_s],x_test(:,i)); 69 | x_test(:,i+1) = x(end,:); 70 | y_test(:,i) = C*x_test(:,i); 71 | z_test(:,i) = rbf_fcn(x_test(:,i),P); 72 | end 73 | % Memory initialization 74 | u_mem=u_test; 75 | y_mem=y_test; 76 | x_mem=x_test; 77 | z_mem=z_test; 78 | z_k=z_mem(:,end); 79 | cost_mem=[]; 80 | %% Set up WKPC 81 | % Define constraints and bounds 82 | a1=3.5; % bound on u_bar 83 | a2=170*pi/180; % bound on y_bar 84 | a3=a1*0.99; % bound on us 85 | % optimization variable: x=[u_bar,y_bar,u_s,y_s,g,sigma,y_d,u_ini,y_ini]' 86 | % Cost Functoin: J=1/2*x'*H*x 87 | l_g=T-Tini-N+1; 88 | H=zeros((N+Tini)*(m+l)+m+l_g+l*N+(Tini)*(n_eig_fcn)); 89 | for i = 1:l_g 90 | if i <=N 91 | H(m*(i-1)+1:m*i,m*(i-1)+1:m*i)=R; 92 | H(m*(i-1)+1:m*i,N*(m+l)+1)=-R; 93 | H(N*(m+l)+1,m*(i-1)+1:m*i)=-R; 94 | H(N*(m+l)+1,N*(m+l)+1)=N*R; 95 | H(N*m+i,N*m+i)=Q; 96 | H(N*m+i,N*(m+l)+m+l_g+i)=-Q; 97 | H(N*(m+l)+m+l_g+i,N*m+i)=-Q; 98 | H(N*(m+l)+m+l_g+i,N*(m+l)+m+l_g+i)=Q; 99 | end 100 | H(N*(m+l)+m+i,N*(m+l)+m+i)=lambda_g; 101 | end 102 | aa1=-eye(n_eig_fcn*Tini); 103 | aa3=-[zeros(m*Tini,m*N);eye(m*N)]; 104 | aa4=-[eye(m*Tini);zeros(m*N,m*Tini)]; 105 | aa5=-[zeros(l*Tini,m*N);eye(l*N)]; 106 | aa6=-[eye(l*Tini);zeros(l*N,m*Tini)]; 107 | A4=[zeros(m*Tini,N*(m+l)+m+l_g+N*l),eye(m*Tini),zeros(m*Tini,l*Tini+n_eig_fcn*(Tini))]; 108 | A5=[zeros(l*Tini,N*(m+l)+m+l_g+N*l+m*Tini),eye(l*Tini),zeros(l*Tini,n_eig_fcn*(Tini))]; 109 | A6=[zeros(l*N,N*(m+l)+m+l_g),eye(l*N),zeros(l*N,(m+l)*Tini+n_eig_fcn*(Tini))]; 110 | A7=[zeros(n_eig_fcn*Tini,N*(m+l)+m+l_g+N*l+(l+m)*Tini),eye(n_eig_fcn*Tini)]; 111 | A8=[zeros(m,N*(m+l)),eye(m),zeros(m,n_eig_fcn*(Tini)+l_g+N*l+(m+l)*Tini)]; 112 | B1=zeros(n_eig_fcn*(Tini),1); 113 | B2=zeros(m*(N+Tini),1); 114 | B3=zeros(l*(N+Tini),1); 115 | B8=zeros(m,1); 116 | A_ineq = []; 117 | b_ineq = []; 118 | % Constraints 119 | lower=[-a1*ones(m*N,1);-a2*ones(l*N,1);-a3*ones(m,1);-inf*ones(l_g+l*N+(m+l)*Tini+n_eig_fcn*(Tini),1)]; 120 | upper=[a1*ones(m*N,1);a2*ones(l*N,1);a3*ones(m,1);inf*ones(l_g+l*N+(m+l)*Tini+n_eig_fcn*(Tini),1)]; 121 | f=zeros(size(H,1),1); 122 | %% simulation 123 | u_mem=[u_mem zeros(m,Tini)]; 124 | y_mem=[y_mem zeros(l,Tini)]; 125 | x_mem=[x_mem zeros(n,Tini)]; 126 | H_u = Hankel_p(u_mem(:,end-T+1:end),N+Tini); 127 | H_y = Hankel_p(y_mem(:,end-T+1:end),N+Tini); 128 | for i=1:s:Tf 129 | % Extract initial conditions from memory 130 | u_ini=u_mem(:,end-Tini+1:end); 131 | y_ini=y_mem(:,end-Tini+1:end); 132 | z_ini=z_mem(:,end-Tini+1:end); 133 | % Desired output 134 | rd = r(:,i+1:i+N); 135 | % Hankel matrices 136 | H_z = Hankel_p(z_mem(:,end-T+1:end-N),Tini); 137 | % Cost function related Matrices 138 | A1=[zeros(n_eig_fcn*(Tini),(N*(m+l)+m)),H_z,zeros(n_eig_fcn*(Tini),N*l+(m+l)*Tini),aa1]; 139 | A2=[aa3,zeros(m*(Tini+N),N*l+m),H_u,zeros(m*(Tini+N),N*l),aa4,zeros(m*(Tini+N),Tini*(l+n_eig_fcn))]; 140 | A3=[zeros(l*(Tini+N),N*m),aa5,zeros(l*(Tini+N),m),H_y,zeros(l*(Tini+N),N*l+m*Tini),aa6,zeros(l*(Tini+N),n_eig_fcn*(Tini))]; 141 | A_eq=[A1;A2;A3;A4;A5;A6;A7]; 142 | B4=reshape(u_ini,[],1); 143 | B5=reshape(y_ini,[],1); 144 | B6=reshape(rd,[],1); 145 | B7=reshape(z_ini,[],1); 146 | B_eq=[B1;B2;B3;B4;B5;B6;B7]; 147 | % Solve optimization problem 148 | tic 149 | [sol,fval,exitflag,output,lambda] = quadprog(H,f,A_ineq,b_ineq,A_eq,B_eq,lower,upper,[],options); 150 | u_s = sol(1:m*M_step); 151 | TT_u=toc; 152 | u_Time=[u_Time TT_u]; 153 | 154 | % Simulate system output 155 | x_1=zeros(n,s+1); 156 | if i>0 157 | x_1(:,1)=x_mem(:,end); 158 | end 159 | y_1=zeros(l,s); 160 | z_k=zeros(n_eig_fcn,s+1); 161 | z_k(:,1)=rbf_fcn(x_1(:,1),P); 162 | for k = 1:s 163 | uu = u_s(:,k); 164 | t = k*T_s; 165 | [~,x] = ode23t(sys,[t t+T_s],x_1(:,k)); 166 | x_1(:,k+1) = x(end,:); 167 | y_1(:,k) = C*x_1(:,k); 168 | z_k(:,k+1) = rbf_fcn(x_1(:,k+1),P); 169 | end 170 | % Update memory 171 | u_mem=[u_mem u_s]; 172 | y_mem=[y_mem y_1]; 173 | x_mem=[x_mem x_1]; 174 | z_mem=[z_mem z_k]; 175 | cost_mem=[cost_mem fval]; 176 | 177 | % Display current iteration information 178 | disp( "Sample Time is: " + num2str(i) ) 179 | disp( "System output is: " + num2str(y_1(:,end)) ) 180 | disp( "System input is: " + num2str(u_s(:,end)) ) 181 | 182 | end 183 | avg_time=sum(u_Time)/numel(u_Time); 184 | disp(avg_time) 185 | save WKPC.mat 186 | y_mem=y_mem*180/pi; 187 | r=r*180/pi; 188 | %% plotting results 189 | time=0:T_s:(Tf+T+4)*T_s; 190 | time2=T*T_s:T_s:(Tf+T+4)*T_s; 191 | w1=2.2; % width 1 -- first line 192 | w2=1.5; % width 2 -- second line 193 | w3=1.5; % width 3 -- box line width 194 | xx0=0; % figuer location 195 | yy0=0; % figuer location 196 | width=850; % image width -- convert cm to pixel 197 | height=750; % image height -- convert cm to pixel 198 | t_it="\itt"; 199 | xleb="\itsec"; 200 | figure 201 | subplot(3,1,1) 202 | for i=1:l 203 | plot(time(1:length(y_mem(i,:))),y_mem(i,:),'r','LineWidth',w1); 204 | hold on; 205 | stairs(time2,r(:,1:numel(time2)),'b:','LineWidth',w2); 206 | xlabel("\fontname{Times New Roman}\bf\fontsize{10}Time (" + ... 207 | xleb+"\rm\fontname{Times New Roman}\bf\fontsize{10})",'FontWeight','bold') 208 | ylabel( {'\fontname{Times New Roman}\bf\fontsize{9}DeePC'... 209 | ;'Output and Reference Signals'}) 210 | legend("y("+t_it+"\rm)","r("+t_it+"\rm)",'Location','best') 211 | grid off 212 | box on 213 | end 214 | xlim([0,time2(length(cost_mem))]) 215 | 216 | subplot(3,1,2) 217 | for i=1:m 218 | plot(time(1:length(u_mem(i,:))),u_mem(i,:),'r','LineWidth',w2); 219 | xlabel("\fontname{Times New Roman}\bf\fontsize{10}Time (" + ... 220 | xleb+"\rm\fontname{Times New Roman}\bf\fontsize{10})",'FontWeight','bold') 221 | ylabel( {'\fontname{Times New Roman}\bf\fontsize{10}DeePC'... 222 | ;'Control Signal'}) 223 | end 224 | xlim([0,time2(length(cost_mem))]) 225 | 226 | subplot(3,1,3) 227 | plot(time2(1:length(cost_mem)),cost_mem,'r','LineWidth',w2); 228 | xlabel("\fontname{Times New Roman}\bf\fontsize{10}Time (" + ... 229 | xleb+"\rm\fontname{Times New Roman}\bf\fontsize{10})",'FontWeight','bold') 230 | ylabel( {'\fontname{Times New Roman}\bf\fontsize{10}DeePC'... 231 | ;'Cost Function'}) 232 | xlim([0,time2(length(cost_mem))]) 233 | 234 | 235 | 236 | %% Functions 237 | function z=rbf_fcn(x,P) 238 | n=length(x); % number of states 239 | p=P+n; % number of lifted states 240 | z=zeros(p,1); 241 | z(1:n,1)=x; 242 | c_i=rand(n,1); 243 | for i=n+1:p 244 | z(i,1)=(norm(x-c_i))^2 * log10(norm(x-c_i)); 245 | end 246 | end 247 | function H=Hankel_p(u,L) 248 | % u should be in the form of [u1 u2 ... uT] 249 | T=size(u,2); 250 | m=size(u,1); 251 | H=zeros(L*m,T-L+1); 252 | for i=1:L 253 | H((i-1)*m+1:i*m,:)=u(:,i:T-L+i); 254 | end 255 | end 256 | 257 | function f = func_sys(t,x) 258 | global uu 259 | r=0.2; 260 | m=1; 261 | g=9.81; 262 | k=0.4; 263 | f=[x(2) 264 | -g/r*sin(x(1))-k/(m*r)*x(2)+uu/(m*r)]; 265 | end 266 | --------------------------------------------------------------------------------