%% Clear Workspace and Close figures clear; close all; clc; %% Intialize Laplace variable s = zpk('s'); addpath('./mat/'); fs = 1e4; Ts = 1/fs; freqs = logspace(1, 3, 1000); % Input / Output data % The identification data is loaded uh = load('mat/data_cal_pd_h.mat', 't', 'Vph', 'Vpv', 'Vnh'); uv = load('mat/data_cal_pd_v.mat', 't', 'Vph', 'Vpv', 'Vnv'); % We remove the first seconds where the Sercalo is turned on. t0 = 1; uh.Vph(uh.t20 & f<200)), mean(Gi_resp_v(f>20 & f<200)))); GaZcGi_resp = abs(squeeze(freqresp(Ga*Zc*Gi, f, 'Hz'))); figure; ax1 = subplot(1, 2, 1); hold on; plot(f, abs(GaZcGi_h), 'k-', 'DisplayName', 'Identified') plot(f, squeeze(GaZcGi_resp(1,1,:)), 'k--', 'DisplayName', 'Theoretical') title('FRF $G_{i,h} Z_{c,h} G_{a,h} = \frac{V_{c,h}}{U_{c,h}}$') set(gca, 'Xscale', 'log'); set(gca, 'Yscale', 'log'); ylabel('Amplitude'); xlabel('Frequency [Hz]'); legend(); hold off; ax2 = subplot(1, 2, 2); hold on; plot(f, abs(GaZcGi_v), 'k-', 'DisplayName', 'Identified') plot(f, squeeze(GaZcGi_resp(2,2,:)), 'k--', 'DisplayName', 'Theoretical') title('FRF $G_{a,v} Z_{c,v} G_{i,v} = \frac{V_{c,v}}{U_{c,v}}$') set(gca, 'Xscale', 'log'); set(gca, 'Yscale', 'log'); ylabel('Amplitude'); xlabel('Frequency [Hz]'); legend(); hold off; linkaxes([ax1,ax2],'xy'); xlim([1, 2000]); % #+NAME: fig:current_amplifier_comp_theory_id_bis % #+CAPTION: Identified and Theoretical Transfer Function $G_a G_i$ ([[./figs/current_amplifier_comp_theory_id_bis.png][png]], [[./figs/current_amplifier_comp_theory_id_bis.pdf][pdf]]) % [[file:figs/current_amplifier_comp_theory_id_bis.png]] % Finally, we have the following transfer functions: Gi,Zc,Ga % Input / Output data % The identification data is loaded uh = load('mat/data_uch.mat', 't', 'Uch', 'Vph', 'Vpv'); uv = load('mat/data_ucv.mat', 't', 'Ucv', 'Vph', 'Vpv'); % We remove the first seconds where the Sercalo is turned on. t0 = 1; uh.Uch(uh.t(1-alpha)*freqs_res_uh(freq_i) & f<(1 + alpha)*freqs_res_uh(freq_i)) = 10; weight_Uch_Vpv(f>(1-alpha)*freqs_res_uh(freq_i) & f<(1 + alpha)*freqs_res_uh(freq_i)) = 10; weight_Ucv_Vph(f>(1-alpha)*freqs_res_uv(freq_i) & f<(1 + alpha)*freqs_res_uv(freq_i)) = 10; weight_Ucv_Vpv(f>(1-alpha)*freqs_res_uv(freq_i) & f<(1 + alpha)*freqs_res_uv(freq_i)) = 10; end weight_Uch_Vph(f>1000) = 0; weight_Uch_Vpv(f>1000) = 0; weight_Ucv_Vph(f>1000) = 0; weight_Ucv_Vpv(f>1000) = 0; % The weights are shown in Fig. [[fig:weights_sercalo]]. figure; hold on; plot(f, weight_Uch_Vph, 'DisplayName', '$W_{U_{ch},V_{ph}}$'); plot(f, weight_Uch_Vpv, 'DisplayName', '$W_{U_{ch},V_{pv}}$'); plot(f, weight_Ucv_Vph, 'DisplayName', '$W_{U_{cv},V_{ph}}$'); plot(f, weight_Ucv_Vpv, 'DisplayName', '$W_{U_{cv},V_{pv}}$'); hold off; xlabel('Frequency [Hz]'); ylabel('Weight Amplitude'); set(gca, 'xscale', 'log'); xlim([f(1), f(end)]); legend('location', 'northwest'); % #+NAME: fig:weights_sercalo % #+CAPTION: Weights amplitude ([[./figs/weights_sercalo.png][png]], [[./figs/weights_sercalo.pdf][pdf]]) % [[file:figs/weights_sercalo.png]] % When we set some options for =vfit3=. opts = struct(); opts.stable = 1; % Enforce stable poles opts.asymp = 1; % Force D matrix to be null opts.relax = 1; % Use vector fitting with relaxed non-triviality constraint opts.skip_pole = 0; % Do NOT skip pole identification opts.skip_res = 0; % Do NOT skip identification of residues (C,D,E) opts.cmplx_ss = 0; % Create real state space model with block diagonal A opts.spy1 = 0; % No plotting for first stage of vector fitting opts.spy2 = 0; % Create magnitude plot for fitting of f(s) % We define the number of iteration. Niter = 5; % An we run the =vectfit3= algorithm. for iter = 1:Niter [SER_Uch_Vph, poles, ~, fit_Uch_Vph] = vectfit3(tf_Uch_Vph.', 1i*2*pi*f, poles_uh, weight_Uch_Vph, opts); end for iter = 1:Niter [SER_Uch_Vpv, poles, ~, fit_Uch_Vpv] = vectfit3(tf_Uch_Vpv.', 1i*2*pi*f, poles_uh, weight_Uch_Vpv, opts); end for iter = 1:Niter [SER_Ucv_Vph, poles, ~, fit_Ucv_Vph] = vectfit3(tf_Ucv_Vph.', 1i*2*pi*f, poles_uv, weight_Ucv_Vph, opts); end for iter = 1:Niter [SER_Ucv_Vpv, poles, ~, fit_Ucv_Vpv] = vectfit3(tf_Ucv_Vpv.', 1i*2*pi*f, poles_uv, weight_Ucv_Vpv, opts); end figure; ax11 = subplot(2, 2, 1); hold on; plot(f, abs(tf_Uch_Vph)) plot(f, abs(fit_Uch_Vph)) title('Frequency Response Function $\frac{Vp_h}{Uc_h}$') set(gca, 'Xscale', 'log'); set(gca, 'Yscale', 'log'); ylabel('Amplitude [V/V]') hold off; ax12 = subplot(2, 2, 2); hold on; plot(f, abs(tf_Ucv_Vph)) plot(f, abs(fit_Ucv_Vph)) title('Frequency Response Function $\frac{Vp_h}{Uc_v}$') set(gca, 'Xscale', 'log'); set(gca, 'Yscale', 'log'); hold off; ax21 = subplot(2, 2, 3); hold on; plot(f, abs(tf_Uch_Vpv)) plot(f, abs(fit_Uch_Vpv)) title('Frequency Response Function $\frac{Vp_v}{Uc_h}$') set(gca, 'Xscale', 'log'); set(gca, 'Yscale', 'log'); ylabel('Amplitude [V/V]') xlabel('Frequency [Hz]') hold off; ax22 = subplot(2, 2, 4); hold on; plot(f, abs(tf_Ucv_Vpv)) plot(f, abs(fit_Ucv_Vpv)) title('Frequency Response Function $\frac{Vp_v}{Uc_v}$') set(gca, 'Xscale', 'log'); set(gca, 'Yscale', 'log'); xlabel('Frequency [Hz]') hold off; linkaxes([ax11,ax12,ax21,ax22],'xy'); xlim([10, 1000]); ylim([1e-2, 1e3]); % #+NAME: fig:identification_matrix_fit % #+CAPTION: Transfer Function Extraction of the FRF matrix ([[./figs/identification_matrix_fit.png][png]], [[./figs/identification_matrix_fit.pdf][pdf]]) % [[file:figs/identification_matrix_fit.png]] figure; ax11 = subplot(2, 2, 1); hold on; plot(f, 180/pi*unwrap(angle(tf_Uch_Vph))) plot(f, 180/pi*unwrap(angle(fit_Uch_Vph))) title('Frequency Response Function $\frac{Vp_h}{Uc_h}$') set(gca, 'Xscale', 'log'); ylabel('Phase [deg]') yticks(-180:90:180); hold off; ax12 = subplot(2, 2, 2); hold on; plot(f, 180/pi*unwrap(angle(tf_Ucv_Vph))) plot(f, 180/pi*unwrap(angle(fit_Ucv_Vph))) title('Frequency Response Function $\frac{Vp_h}{Uc_v}$') set(gca, 'Xscale', 'log'); yticks(-180:90:180); hold off; ax21 = subplot(2, 2, 3); hold on; plot(f, 180/pi*unwrap(angle(tf_Uch_Vpv))) plot(f, 180/pi*unwrap(angle(fit_Uch_Vpv))) title('Frequency Response Function $\frac{Vp_v}{Uc_h}$') set(gca, 'Xscale', 'log'); ylabel('Phase [deg]') xlabel('Frequency [Hz]') yticks(-180:90:180); hold off; ax22 = subplot(2, 2, 4); hold on; plot(f, 180/pi*unwrap(angle(tf_Ucv_Vpv))) plot(f, 180/pi*unwrap(angle(fit_Ucv_Vpv))) title('Frequency Response Function $\frac{Vp_v}{Uc_v}$') set(gca, 'Xscale', 'log'); xlabel('Frequency [Hz]') yticks(-180:90:180); hold off; linkaxes([ax11,ax12,ax21,ax22],'xy'); xlim([10, 1000]); ylim([-200, 200]); % #+NAME: fig:identification_matrix_fit_phase % #+CAPTION: Transfer Function Extraction of the FRF matrix ([[./figs/identification_matrix_fit_phase.png][png]], [[./figs/identification_matrix_fit_phase.pdf][pdf]]) % [[file:figs/identification_matrix_fit_phase.png]] % And finally, we create the identified $G_c$ matrix by multiplying by ${G_i}^{-1}$. G_Uch_Vph = tf(minreal(ss(full(SER_Uch_Vph.A),SER_Uch_Vph.B,SER_Uch_Vph.C,SER_Uch_Vph.D))); G_Ucv_Vph = tf(minreal(ss(full(SER_Ucv_Vph.A),SER_Ucv_Vph.B,SER_Ucv_Vph.C,SER_Ucv_Vph.D))); G_Uch_Vpv = tf(minreal(ss(full(SER_Uch_Vpv.A),SER_Uch_Vpv.B,SER_Uch_Vpv.C,SER_Uch_Vpv.D))); G_Ucv_Vpv = tf(minreal(ss(full(SER_Ucv_Vpv.A),SER_Ucv_Vpv.B,SER_Ucv_Vpv.C,SER_Ucv_Vpv.D))); Gc = [G_Uch_Vph, G_Ucv_Vph; G_Uch_Vpv, G_Ucv_Vpv]*inv(Gi); % Input / Output data % The identification data is loaded uh = load('mat/data_unh.mat', 't', 'Unh', 'Vph', 'Vpv'); uv = load('mat/data_unv.mat', 't', 'Unv', 'Vph', 'Vpv'); % We remove the first seconds where the Sercalo is turned on. t0 = 3; uh.Unh(uh.t10 & f<100)))), tf(mean(abs(tf_Unv_Vpv(f>10 & f<100))))); % Full System % We now have identified: % - $G_i$ % - $G_a$ % - $G_c$ % - $G_n$ % - $G_d$ % We name the input and output of each transfer function: Gi.InputName = {'Uch', 'Ucv'}; Gi.OutputName = {'Ich', 'Icv'}; Zc.InputName = {'Ich', 'Icv'}; Zc.OutputName = {'Vtch', 'Vtcv'}; Ga.InputName = {'Vtch', 'Vtcv'}; Ga.OutputName = {'Vch', 'Vcv'}; Gc.InputName = {'Ich', 'Icv'}; Gc.OutputName = {'Vpch', 'Vpcv'}; Gn.InputName = {'Unh', 'Unv'}; Gn.OutputName = {'Vpnh', 'Vpnv'}; Gd.InputName = {'Rh', 'Rv'}; Gd.OutputName = {'Vph', 'Vpv'}; Sh = sumblk('Vph = Vpch + Vpnh'); Sv = sumblk('Vpv = Vpcv + Vpnv'); inputs = {'Uch', 'Ucv', 'Unh', 'Unv'}; outputs = {'Vch', 'Vcv', 'Ich', 'Icv', 'Rh', 'Rv', 'Vph', 'Vpv'}; sys = connect(Gi, Zc, Ga, Gc, Gn, inv(Gd), Sh, Sv, inputs, outputs); % The file =mat/plant.mat= is accessible [[./mat/plant.mat][here]]. save('mat/plant.mat', 'sys', 'Gi', 'Zc', 'Ga', 'Gc', 'Gn', 'Gd');