475 lines
18 KiB
Mathematica
475 lines
18 KiB
Mathematica
|
%% Clear Workspace and Close figures
|
||
|
clear; close all; clc;
|
||
|
|
||
|
%% Intialize Laplace variable
|
||
|
s = zpk('s');
|
||
|
|
||
|
%% Path for functions, data and scripts
|
||
|
addpath('./mat/'); % Path for data
|
||
|
addpath('./src/'); % Path for Functions
|
||
|
|
||
|
%% Colors for the figures
|
||
|
colors = colororder;
|
||
|
|
||
|
%% Simscape model name
|
||
|
mdl = 'rotating_model';
|
||
|
|
||
|
%% Load "Generic" system dynamics
|
||
|
load('rotating_generic_plants.mat', 'Gs', 'Wzs');
|
||
|
|
||
|
% Modified Integral Force Feedback Controller
|
||
|
% The Integral Force Feedback Controller is modified such that instead of using pure integrators, pseudo integrators (i.e. low pass filters) are used:
|
||
|
% \begin{equation}
|
||
|
% K_{\text{IFF}}(s) = g\frac{1}{\omega_i + s} \begin{bmatrix}
|
||
|
% 1 & 0 \\
|
||
|
% 0 & 1
|
||
|
% \end{bmatrix}
|
||
|
% \end{equation}
|
||
|
% where $\omega_i$ characterize down to which frequency the signal is integrated.
|
||
|
|
||
|
% Let's arbitrary choose the following control parameters:
|
||
|
|
||
|
%% Modified IFF - parameters
|
||
|
g = 2; % Controller gain
|
||
|
wi = 0.1; % HPF Cut-Off frequency [rad/s]
|
||
|
|
||
|
Kiff = (g/s)*eye(2); % Pure IFF
|
||
|
Kiff_hpf = (g/(wi+s))*eye(2); % IFF with added HPF
|
||
|
|
||
|
|
||
|
|
||
|
% The loop gains ($K_F(s)$ times the direct dynamics $f_u/F_u$) with and without the added HPF are shown in Figure ref:fig:rotating_iff_modified_loop_gain.
|
||
|
% The effect of the added HPF limits the low frequency gain to finite values as expected.
|
||
|
|
||
|
|
||
|
%% Loop gain for the IFF with pure integrator and modified IFF with added high pass filter
|
||
|
freqs = logspace(-2, 1, 1000);
|
||
|
Wz_i = 2;
|
||
|
|
||
|
figure;
|
||
|
tiledlayout(3, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
|
||
|
|
||
|
% Magnitude
|
||
|
ax1 = nexttile([2, 1]);
|
||
|
hold on;
|
||
|
plot(freqs, abs(squeeze(freqresp(Gs{Wz_i}('fu', 'Fu')*Kiff(1,1), freqs, 'rad/s'))))
|
||
|
plot(freqs, abs(squeeze(freqresp(Gs{Wz_i}('fu', 'Fu')*Kiff_hpf(1,1), freqs, 'rad/s'))))
|
||
|
hold off;
|
||
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
||
|
set(gca, 'XTickLabel',[]); ylabel('Loop Gain');
|
||
|
|
||
|
% Phase
|
||
|
ax2 = nexttile;
|
||
|
hold on;
|
||
|
plot(freqs, 180/pi*angle(squeeze(freqresp(Gs{Wz_i}('fu', 'Fu')*Kiff(1,1), freqs, 'rad/s'))), 'DisplayName', 'IFF')
|
||
|
plot(freqs, 180/pi*angle(squeeze(freqresp(Gs{Wz_i}('fu', 'Fu')*Kiff_hpf(1,1), freqs, 'rad/s'))), 'DisplayName', 'IFF + HPF')
|
||
|
hold off;
|
||
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
|
||
|
xlabel('Frequency [rad/s]'); ylabel('Phase [deg]');
|
||
|
yticks(-180:90:180);
|
||
|
ylim([-180 180]);
|
||
|
xticks([1e-2,1e-1,1,1e1])
|
||
|
xticklabels({'$0.01 \omega_0$', '$0.1 \omega_0$', '$\omega_0$', '$10 \omega_0$'})
|
||
|
leg = legend('location', 'southwest', 'FontSize', 8);
|
||
|
leg.ItemTokenSize(1) = 20;
|
||
|
|
||
|
linkaxes([ax1,ax2],'x');
|
||
|
xlim([freqs(1), freqs(end)]);
|
||
|
|
||
|
|
||
|
|
||
|
% #+name: fig:rotating_iff_modified_loop_gain
|
||
|
% #+caption: Loop gain for the IFF with pure integrator and modified IFF with added high pass filter ($\Omega = 0.1\omega_0$)
|
||
|
% #+RESULTS:
|
||
|
% [[file:figs/rotating_iff_modified_loop_gain.png]]
|
||
|
|
||
|
% The Root Locus plots for the decentralized IFF with and without the HPF are displayed in Figure ref:fig:rotating_iff_root_locus_hpf.
|
||
|
% With the added HPF, the poles of the closed loop system are shown to be *stable up to some value of the gain* $g_\text{max}$ given by equation eqref:eq:gmax_iff_hpf.
|
||
|
|
||
|
% #+name: eq:gmax_iff_hpf
|
||
|
% \begin{equation}
|
||
|
% \boxed{g_{\text{max}} = \omega_i \left( \frac{{\omega_0}^2}{\Omega^2} - 1 \right)}
|
||
|
% \end{equation}
|
||
|
|
||
|
% It is interesting to note that $g_{\text{max}}$ also corresponds to the controller gain at which the low frequency loop gain (Figure ref:fig:rotating_iff_modified_loop_gain) reaches one.
|
||
|
|
||
|
|
||
|
%% Root Locus for the initial IFF and the modified IFF
|
||
|
gains = logspace(-2, 4, 200);
|
||
|
|
||
|
figure;
|
||
|
tiledlayout(1, 3, 'TileSpacing', 'Compact', 'Padding', 'None');
|
||
|
|
||
|
ax1 = nexttile([1,2]);
|
||
|
hold on;
|
||
|
for g = gains
|
||
|
clpoles = pole(feedback(Gs{Wz_i}({'fu', 'fv'}, {'Fu', 'Fv'}), g*Kiff));
|
||
|
plot(real(clpoles), imag(clpoles), '.', 'color', colors(1,:), 'HandleVisibility', 'off','MarkerSize',4);
|
||
|
end
|
||
|
for g = gains
|
||
|
clpoles = pole(feedback(Gs{Wz_i}({'fu', 'fv'}, {'Fu', 'Fv'}), g*Kiff_hpf));
|
||
|
plot(real(clpoles), imag(clpoles), '.', 'color', colors(2,:), 'HandleVisibility', 'off','MarkerSize',4);
|
||
|
end
|
||
|
% Pure Integrator
|
||
|
plot(real(pole(Gs{Wz_i}({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff)), ...
|
||
|
imag(pole(Gs{Wz_i}({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff)), ...
|
||
|
'x', 'color', colors(1,:), 'DisplayName', 'IFF','MarkerSize',8);
|
||
|
plot(real(tzero(Gs{Wz_i}({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff)), ...
|
||
|
imag(tzero(Gs{Wz_i}({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff)), ...
|
||
|
'o', 'color', colors(1,:), 'HandleVisibility', 'off','MarkerSize',8);
|
||
|
% Modified IFF
|
||
|
plot(real(pole(Gs{Wz_i}({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff_hpf)), ...
|
||
|
imag(pole(Gs{Wz_i}({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff_hpf)), ...
|
||
|
'x', 'color', colors(2,:), 'DisplayName', 'IFF + HPF','MarkerSize',8);
|
||
|
plot(real(tzero(Gs{Wz_i}({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff_hpf)), ...
|
||
|
imag(tzero(Gs{Wz_i}({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff_hpf)), ...
|
||
|
'o', 'color', colors(2,:), 'HandleVisibility', 'off','MarkerSize',8);
|
||
|
hold off;
|
||
|
axis square;
|
||
|
leg = legend('location', 'northwest', 'FontSize', 8);
|
||
|
leg.ItemTokenSize(1) = 8;
|
||
|
xlabel('Real Part'); ylabel('Imaginary Part');
|
||
|
|
||
|
xlim([-2.25, 0.25]); ylim([-1.25, 1.25]);
|
||
|
xticks([-2, -1, 0])
|
||
|
xticklabels({'$-2\omega_0$', '$-\omega_0$', '$0$'})
|
||
|
yticks([-1, 0, 1])
|
||
|
yticklabels({'$-\omega_0$', '$0$', '$\omega_0$'})
|
||
|
|
||
|
ax2 = nexttile();
|
||
|
hold on;
|
||
|
for g = gains
|
||
|
clpoles = pole(feedback(Gs{Wz_i}({'fu', 'fv'}, {'Fu', 'Fv'}), g*Kiff));
|
||
|
plot(real(clpoles), imag(clpoles), '.', 'color', colors(1,:),'MarkerSize',4);
|
||
|
end
|
||
|
for g = gains
|
||
|
clpoles = pole(feedback(Gs{Wz_i}({'fu', 'fv'}, {'Fu', 'Fv'}), g*Kiff_hpf));
|
||
|
plot(real(clpoles), imag(clpoles), '.', 'color', colors(2,:),'MarkerSize',4);
|
||
|
end
|
||
|
% Pure Integrator
|
||
|
plot(real(pole(Gs{Wz_i}({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff)), ...
|
||
|
imag(pole(Gs{Wz_i}({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff)), ...
|
||
|
'x', 'color', colors(1,:),'MarkerSize',8);
|
||
|
plot(real(tzero(Gs{Wz_i}({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff)), ...
|
||
|
imag(tzero(Gs{Wz_i}({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff)), ...
|
||
|
'o', 'color', colors(1,:),'MarkerSize',8);
|
||
|
% Modified IFF
|
||
|
plot(real(pole(Gs{Wz_i}({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff_hpf)), ...
|
||
|
imag(pole(Gs{Wz_i}({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff_hpf)), ...
|
||
|
'x', 'color', colors(2,:),'MarkerSize',8);
|
||
|
plot(real(tzero(Gs{Wz_i}({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff_hpf)), ...
|
||
|
imag(tzero(Gs{Wz_i}({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff_hpf)), ...
|
||
|
'o', 'color', colors(2,:),'MarkerSize',8);
|
||
|
hold off;
|
||
|
axis square;
|
||
|
xlabel('Real Part'); ylabel('Imaginary Part');
|
||
|
title('Zoom near the origin');
|
||
|
|
||
|
xlim([-0.15, 0.1]); ylim([-0.15, 0.15]);
|
||
|
xticks([-0.1, 0, 0.1])
|
||
|
xticklabels({'$-0.1\omega_0$', '$0$', '$0.1\omega_0$'})
|
||
|
yticks([-0.1, 0, 0.1])
|
||
|
yticklabels({'$-0.1\omega_0$', '$0$', '$0.1\omega_0$'})
|
||
|
|
||
|
% Optimal IFF with HPF parameters $\omega_i$ and $g$
|
||
|
% Two parameters can be tuned for the modified controller in equation eqref:eq:iff_lhf: the gain $g$ and the pole's location $\omega_i$.
|
||
|
% The optimal values of $\omega_i$ and $g$ are here considered as the values for which the damping of all the closed-loop poles are simultaneously maximized.
|
||
|
|
||
|
% In order to visualize how $\omega_i$ does affect the attainable damping, the Root Locus plots for several $\omega_i$ are displayed in Figure ref:fig:rotating_root_locus_iff_modified_effect_wi.
|
||
|
% It is shown that even though small $\omega_i$ seem to allow more damping to be added to the suspension modes, the control gain $g$ may be limited to small values due to equation eqref:eq:gmax_iff_hpf.
|
||
|
|
||
|
|
||
|
%% High Pass Filter Cut-Off Frequency
|
||
|
wis = [0.01, 0.1, 0.5, 1]*Wzs(2); % [rad/s]
|
||
|
|
||
|
%% Root Locus for the initial IFF and the modified IFF
|
||
|
gains = logspace(-2, 4, 200);
|
||
|
|
||
|
figure;
|
||
|
tiledlayout(1, 2, 'TileSpacing', 'Compact', 'Padding', 'None');
|
||
|
|
||
|
ax1 = nexttile();
|
||
|
hold on;
|
||
|
for wi_i = 1:length(wis)
|
||
|
wi = wis(wi_i);
|
||
|
Kiff = (1/(wi+s))*eye(2);
|
||
|
L(wi_i) = plot(nan, nan, '.', 'color', colors(wi_i,:), 'DisplayName', sprintf('$\\omega_i = %.2f \\omega_0$', wi./Wzs(2)));
|
||
|
for g = gains
|
||
|
clpoles = pole(feedback(Gs{2}({'fu', 'fv'}, {'Fu', 'Fv'}), g*Kiff));
|
||
|
plot(real(clpoles), imag(clpoles), '.', 'color', colors(wi_i,:),'MarkerSize',4);
|
||
|
end
|
||
|
plot(real(pole(Gs{2}({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff)), ...
|
||
|
imag(pole(Gs{2}({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff)), ...
|
||
|
'x', 'color', colors(wi_i,:),'MarkerSize',8);
|
||
|
plot(real(tzero(Gs{2}({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff)), ...
|
||
|
imag(tzero(Gs{2}({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff)), ...
|
||
|
'o', 'color', colors(wi_i,:),'MarkerSize',8);
|
||
|
end
|
||
|
hold off;
|
||
|
axis square;
|
||
|
xlim([-2.3, 0.1]); ylim([-1.2, 1.2]);
|
||
|
xticks([-2:1:2]); yticks([-2:1:2]);
|
||
|
leg = legend(L, 'location', 'northwest', 'FontSize', 8);
|
||
|
leg.ItemTokenSize(1) = 8;
|
||
|
xlabel('Real Part'); ylabel('Imaginary Part');
|
||
|
clear L
|
||
|
|
||
|
xlim([-2.25, 0.25]); ylim([-1.25, 1.25]);
|
||
|
xticks([-2, -1, 0])
|
||
|
xticklabels({'$-2\omega_0$', '$-\omega_0$', '$0$'})
|
||
|
yticks([-1, 0, 1])
|
||
|
yticklabels({'$-\omega_0$', '$0$', '$\omega_0$'})
|
||
|
|
||
|
ax2 = nexttile();
|
||
|
hold on;
|
||
|
for wi_i = 1:length(wis)
|
||
|
wi = wis(wi_i);
|
||
|
Kiff = (1/(wi+s))*eye(2);
|
||
|
L(wi_i) = plot(nan, nan, '.', 'color', colors(wi_i,:));
|
||
|
for g = gains
|
||
|
clpoles = pole(feedback(Gs{2}({'fu', 'fv'}, {'Fu', 'Fv'}), g*Kiff));
|
||
|
plot(real(clpoles), imag(clpoles), '.', 'color', colors(wi_i,:),'MarkerSize',4);
|
||
|
end
|
||
|
plot(real(pole(Gs{2}({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff)), ...
|
||
|
imag(pole(Gs{2}({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff)), ...
|
||
|
'x', 'color', colors(wi_i,:),'MarkerSize',8);
|
||
|
plot(real(tzero(Gs{2}({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff)), ...
|
||
|
imag(tzero(Gs{2}({'fu', 'fv'}, {'Fu', 'Fv'})*Kiff)), ...
|
||
|
'o', 'color', colors(wi_i,:),'MarkerSize',8);
|
||
|
end
|
||
|
hold off;
|
||
|
axis square;
|
||
|
xlim([-2.3, 0.1]); ylim([-1.2, 1.2]);
|
||
|
xticks([-2:1:2]); yticks([-2:1:2]);
|
||
|
xlabel('Real Part'); ylabel('Imaginary Part');
|
||
|
title('Zoom near the origin');
|
||
|
clear L
|
||
|
|
||
|
xlim([-0.15, 0.1]); ylim([-0.15, 0.15]);
|
||
|
xticks([-0.1, 0, 0.1])
|
||
|
xticklabels({'$-0.1\omega_0$', '$0$', '$0.1\omega_0$'})
|
||
|
yticks([-0.1, 0, 0.1])
|
||
|
yticklabels({'$-0.1\omega_0$', '$0$', '$0.1\omega_0$'})
|
||
|
|
||
|
|
||
|
|
||
|
% #+name: fig:rotating_root_locus_iff_modified_effect_wi
|
||
|
% #+caption: Root Locus for several high pass filter cut-off frequency
|
||
|
% #+RESULTS:
|
||
|
% [[file:figs/rotating_root_locus_iff_modified_effect_wi.png]]
|
||
|
|
||
|
% In order to study this trade off, the attainable closed-loop damping ratio $\xi_{\text{cl}}$ is computed as a function of $\omega_i/\omega_0$.
|
||
|
% The gain $g_{\text{opt}}$ at which this maximum damping is obtained is also displayed and compared with the gain $g_{\text{max}}$ at which the system becomes unstable (Figure ref:fig:rotating_iff_hpf_optimal_gain).
|
||
|
|
||
|
% Three regions can be observed:
|
||
|
% - $\omega_i/\omega_0 < 0.02$: the added damping is limited by the maximum allowed control gain $g_{\text{max}}$
|
||
|
% - $0.02 < \omega_i/\omega_0 < 0.2$: the attainable damping ratio is maximized and is reached for $g \approx 2$
|
||
|
% - $0.2 < \omega_i/\omega_0$: the added damping decreases as $\omega_i/\omega_0$ increases.
|
||
|
|
||
|
|
||
|
%% Compute the optimal control gain
|
||
|
wis = logspace(-2, 1, 100); % [rad/s]
|
||
|
|
||
|
opt_xi = zeros(1, length(wis)); % Optimal simultaneous damping
|
||
|
opt_gain = zeros(1, length(wis)); % Corresponding optimal gain
|
||
|
|
||
|
for wi_i = 1:length(wis)
|
||
|
wi = wis(wi_i);
|
||
|
Kiff = 1/(s + wi)*eye(2);
|
||
|
|
||
|
fun = @(g)computeSimultaneousDamping(g, Gs{2}({'fu', 'fv'}, {'Fu', 'Fv'}), Kiff);
|
||
|
|
||
|
[g_opt, xi_opt] = fminsearch(fun, 0.5*wi*((1/Wzs(2))^2 - 1));
|
||
|
opt_xi(wi_i) = 1/xi_opt;
|
||
|
opt_gain(wi_i) = g_opt;
|
||
|
end
|
||
|
|
||
|
%% Attainable damping ratio as a function of wi/w0. Corresponding control gain g_opt and g_max are also shown
|
||
|
figure;
|
||
|
yyaxis left
|
||
|
plot(wis, opt_xi, '-', 'DisplayName', '$\xi_{cl}$');
|
||
|
set(gca, 'YScale', 'lin');
|
||
|
ylim([0,1]);
|
||
|
ylabel('Damping Ratio $\xi$');
|
||
|
|
||
|
yyaxis right
|
||
|
hold on;
|
||
|
plot(wis, opt_gain, '-', 'DisplayName', '$g_{opt}$');
|
||
|
plot(wis, wis*((1/Wzs(2))^2 - 1), '--', 'DisplayName', '$g_{max}$');
|
||
|
set(gca, 'YScale', 'lin');
|
||
|
ylim([0,10]);
|
||
|
ylabel('Controller gain $g$');
|
||
|
|
||
|
xlabel('$\omega_i/\omega_0$');
|
||
|
set(gca, 'XScale', 'log');
|
||
|
legend('location', 'northeast', 'FontSize', 8);
|
||
|
|
||
|
% Obtained Damped Plant
|
||
|
|
||
|
% Let's choose $\omega_i = 0.1 \cdot \omega_0$ and compute the damped plant.
|
||
|
% The undamped and damped plants are compared in Figure ref:fig:rotating_iff_hpf_damped_plant in blue and red respectively.
|
||
|
% A well damped plant is indeed obtained.
|
||
|
|
||
|
% However, the magnitude of the coupling term ($d_v/F_u$) is larger then IFF is applied.
|
||
|
|
||
|
|
||
|
%% Compute damped plant
|
||
|
wi = 0.1; % [rad/s]
|
||
|
g = 2; % Gain
|
||
|
Kiff_hpf = (g/(wi+s))*eye(2); % IFF with added HPF
|
||
|
Kiff_hpf.InputName = {'fu', 'fv'};
|
||
|
Kiff_hpf.OutputName = {'Fu', 'Fv'};
|
||
|
|
||
|
G_iff_hpf = feedback(Gs{2}, Kiff_hpf, 'name');
|
||
|
|
||
|
isstable(G_iff_hpf) % Verify stability
|
||
|
|
||
|
%% Damped plant with IFF and added HPF - Transfer function from $F_u$ to $d_u$
|
||
|
freqs = logspace(-2, 1, 1000);
|
||
|
|
||
|
figure;
|
||
|
tiledlayout(3, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
|
||
|
|
||
|
% Magnitude
|
||
|
ax1 = nexttile([2, 1]);
|
||
|
hold on;
|
||
|
plot(freqs, abs(squeeze(freqresp(Gs{2}('Du', 'Fu'), freqs, 'rad/s'))), '-', 'color', [zeros(1,3)], ...
|
||
|
'DisplayName', '$d_u/F_u$, OL')
|
||
|
plot(freqs, abs(squeeze(freqresp(G_iff_hpf('Du', 'Fu'), freqs, 'rad/s'))), '-', 'color', [colors(1,:)], ...
|
||
|
'DisplayName', '$d_u/F_u$, IFF')
|
||
|
plot(freqs, abs(squeeze(freqresp(Gs{2}('Dv', 'Fu'), freqs, 'rad/s'))), '-', 'color', [zeros(1,3), 0.5], ...
|
||
|
'DisplayName', '$d_v/F_u$, OL')
|
||
|
plot(freqs, abs(squeeze(freqresp(G_iff_hpf('Dv', 'Fu'), freqs, 'rad/s'))), '-', 'color', [colors(1,:), 0.5], ...
|
||
|
'DisplayName', '$d_v/F_u$, IFF')
|
||
|
hold off;
|
||
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
||
|
set(gca, 'XTickLabel',[]); ylabel('Magnitude [m/N]');
|
||
|
leg = legend('location', 'southwest', 'FontSize', 8, 'NumColumns', 2);
|
||
|
leg.ItemTokenSize(1) = 20;
|
||
|
|
||
|
ax2 = nexttile;
|
||
|
hold on;
|
||
|
plot(freqs, 180/pi*angle(squeeze(freqresp(Gs{2}('Du', 'Fu'), freqs, 'rad/s'))), '-', 'color', zeros(1,3))
|
||
|
plot(freqs, 180/pi*angle(squeeze(freqresp(G_iff_hpf('Du', 'Fu'), freqs, 'rad/s'))), '-', 'color', colors(1,:))
|
||
|
hold off;
|
||
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
|
||
|
xlabel('Frequency [rad/s]'); ylabel('Phase [deg]');
|
||
|
yticks(-180:90:180);
|
||
|
ylim([-180 180]);
|
||
|
xticks([1e-2,1e-1,1,1e1])
|
||
|
xticklabels({'$0.01 \omega_0$', '$0.1 \omega_0$', '$\omega_0$', '$10 \omega_0$'})
|
||
|
|
||
|
linkaxes([ax1,ax2],'x');
|
||
|
xlim([freqs(1), freqs(end)]);
|
||
|
|
||
|
|
||
|
|
||
|
% #+name: fig:rotating_iff_hpf_damped_plant
|
||
|
% #+caption: Damped plant with IFF and added HPF - Transfer function from $F_u$ to $d_u$, $\omega_i = 0.1 \cdot \omega_0$, $\Omega = 0.1 \cdot \omega_0$
|
||
|
% #+RESULTS:
|
||
|
% [[file:figs/rotating_iff_hpf_damped_plant.png]]
|
||
|
|
||
|
% In order to study how $\omega_i$ affects the coupling of the damped plant, the closed-loop plant is identified for several $\omega_i$.
|
||
|
% The direct and coupling terms of the plants are shown in Figure ref:fig:rotating_iff_hpf_damped_plant_effect_wi_coupling (left) and the ratio between the two (i.e. the coupling ratio) is shown in Figure ref:fig:rotating_iff_hpf_damped_plant_effect_wi_coupling (right).
|
||
|
|
||
|
% The coupling ratio is decreasing as $\omega_i$ increases.
|
||
|
% There is therefore a *trade-off between achievable damping and coupling ratio* for the choice of $\omega_i$.
|
||
|
% The same trade-off can be seen between achievable damping and loss of compliance at low frequency (see Figure ref:fig:rotating_iff_hpf_effect_wi_compliance).
|
||
|
|
||
|
|
||
|
%% Compute damped plant
|
||
|
wis = [0.03, 0.1, 0.5]; % [rad/s]
|
||
|
g = 2; % Gain
|
||
|
|
||
|
Gs_iff_hpf = {};
|
||
|
|
||
|
for i = 1:length(wis)
|
||
|
Kiff_hpf = (g/(wis(i)+s))*eye(2); % IFF with added HPF
|
||
|
Kiff_hpf.InputName = {'fu', 'fv'};
|
||
|
Kiff_hpf.OutputName = {'Fu', 'Fv'};
|
||
|
|
||
|
Gs_iff_hpf(i) = {feedback(Gs{2}, Kiff_hpf, 'name')};
|
||
|
end
|
||
|
|
||
|
%% Effect of $\omega_i$ on the damped plant coupling
|
||
|
freqs = logspace(-2, 1, 1000);
|
||
|
|
||
|
figure;
|
||
|
tiledlayout(3, 2, 'TileSpacing', 'Compact', 'Padding', 'None');
|
||
|
|
||
|
% Magnitude
|
||
|
ax1 = nexttile([2, 1]);
|
||
|
hold on;
|
||
|
for i = 1:length(wis)
|
||
|
plot(freqs, abs(squeeze(freqresp(Gs_iff_hpf{i}('Du', 'Fu'), freqs, 'rad/s'))), '-', 'color', [colors(i,:)], ...
|
||
|
'DisplayName', sprintf('$d_u/F_u$, $\\omega_i = %.2f \\omega_0$', wis(i)))
|
||
|
plot(freqs, abs(squeeze(freqresp(Gs_iff_hpf{i}('Dv', 'Fu'), freqs, 'rad/s'))), '-', 'color', [colors(i,:), 0.5], ...
|
||
|
'DisplayName', sprintf('$d_v/F_u$, $\\omega_i = %.2f \\omega_0$', wis(i)))
|
||
|
end
|
||
|
hold off;
|
||
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
||
|
set(gca, 'XTickLabel',[]); ylabel('Magnitude [m/N]');
|
||
|
leg = legend('location', 'southwest', 'FontSize', 8, 'NumColumns', 1);
|
||
|
leg.ItemTokenSize(1) = 20;
|
||
|
|
||
|
ax3 = nexttile([3,1]);
|
||
|
hold on;
|
||
|
for i = 1:length(wis)
|
||
|
plot(freqs, abs(squeeze(freqresp(Gs_iff_hpf{i}('Dv', 'Fu')/Gs_iff_hpf{i}('Du', 'Fu'), freqs, 'rad/s'))), '-', 'color', [colors(i,:)], ...
|
||
|
'DisplayName', sprintf('$\\omega_i = %.2f \\omega_0$', wis(i)))
|
||
|
end
|
||
|
hold off;
|
||
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
||
|
xlabel('Frequency [rad/s]'); ylabel('Coupling Ratio');
|
||
|
leg = legend('location', 'northeast', 'FontSize', 8, 'NumColumns', 1);
|
||
|
leg.ItemTokenSize(1) = 20;
|
||
|
xticks([1e-2,1e-1,1,1e1])
|
||
|
xticklabels({'$0.01 \omega_0$', '$0.1 \omega_0$', '$\omega_0$', '$10 \omega_0$'})
|
||
|
|
||
|
ax2 = nexttile;
|
||
|
hold on;
|
||
|
for i = 1:length(wis)
|
||
|
plot(freqs, 180/pi*angle(squeeze(freqresp(Gs_iff_hpf{i}('Du', 'Fu'), freqs, 'rad/s'))), '-')
|
||
|
end
|
||
|
hold off;
|
||
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
|
||
|
xlabel('Frequency [rad/s]'); ylabel('Phase [deg]');
|
||
|
yticks(-180:90:180);
|
||
|
ylim([-180 180]);
|
||
|
xticks([1e-2,1e-1,1,1e1])
|
||
|
xticklabels({'$0.01 \omega_0$', '$0.1 \omega_0$', '$\omega_0$', '$10 \omega_0$'})
|
||
|
|
||
|
linkaxes([ax1,ax2],'x');
|
||
|
xlim([freqs(1), freqs(end)]);
|
||
|
|
||
|
|
||
|
|
||
|
% #+name: fig:rotating_iff_hpf_damped_plant_effect_wi_coupling
|
||
|
% #+caption: Effect of $\omega_i$ on the damped plant coupling
|
||
|
% #+RESULTS:
|
||
|
% [[file:figs/rotating_iff_hpf_damped_plant_effect_wi_coupling.png]]
|
||
|
|
||
|
|
||
|
%% Effect of $\omega_i$ on the obtained compliance
|
||
|
freqs = logspace(-2, 1, 1000);
|
||
|
|
||
|
figure;
|
||
|
tiledlayout(1, 1, 'TileSpacing', 'Compact', 'Padding', 'None');
|
||
|
|
||
|
% Magnitude
|
||
|
ax1 = nexttile();
|
||
|
hold on;
|
||
|
for i = 1:length(wis)
|
||
|
plot(freqs, abs(squeeze(freqresp(Gs_iff_hpf{i}('Du', 'Fdx'), freqs, 'rad/s'))), '-', 'color', [colors(i,:)], ...
|
||
|
'DisplayName', sprintf('$d_{x}/F_{dx}$, $\\omega_i = %.2f \\omega_0$', wis(i)))
|
||
|
end
|
||
|
plot(freqs, abs(squeeze(freqresp(Gs{2}('Du', 'Fdx'), freqs, 'rad/s'))), 'k--', ...
|
||
|
'DisplayName', '$d_{x}/F_{dx}$, OL')
|
||
|
hold off;
|
||
|
set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
|
||
|
xlabel('Frequency [rad/s]'); ylabel('Compliance [m/N]');
|
||
|
leg = legend('location', 'southwest', 'FontSize', 8, 'NumColumns', 1);
|
||
|
leg.ItemTokenSize(1) = 20;
|
||
|
xticks([1e-2,1e-1,1,1e1])
|
||
|
xticklabels({'$0.01 \omega_0$', '$0.1 \omega_0$', '$\omega_0$', '$10 \omega_0$'})
|