diff --git a/matlab/figs-inkscape b/matlab/figs-inkscape
index 4ac36b0..bb6c3d7 120000
--- a/matlab/figs-inkscape
+++ b/matlab/figs-inkscape
@@ -1 +1 @@
-../inkscape/figs
\ No newline at end of file
+../inkscape
\ No newline at end of file
diff --git a/matlab/figs/mod_iff_damping_wi.pdf b/matlab/figs/mod_iff_damping_wi.pdf
index ad1abae..c50dc33 100644
Binary files a/matlab/figs/mod_iff_damping_wi.pdf and b/matlab/figs/mod_iff_damping_wi.pdf differ
diff --git a/matlab/figs/root_locus_wi_modified_iff.pdf b/matlab/figs/root_locus_wi_modified_iff.pdf
index 9cc1dad..b864d14 100644
Binary files a/matlab/figs/root_locus_wi_modified_iff.pdf and b/matlab/figs/root_locus_wi_modified_iff.pdf differ
diff --git a/matlab/figs/root_locus_wi_modified_iff.png b/matlab/figs/root_locus_wi_modified_iff.png
index 32899a2..6d95f72 100644
Binary files a/matlab/figs/root_locus_wi_modified_iff.png and b/matlab/figs/root_locus_wi_modified_iff.png differ
diff --git a/matlab/index.org b/matlab/index.org
index 059a265..f3d24f6 100644
--- a/matlab/index.org
+++ b/matlab/index.org
@@ -14,7 +14,6 @@
#+HTML_HEAD:
#+PROPERTY: header-args:matlab :session *MATLAB*
-#+PROPERTY: header-args:matlab+ :tangle matlab/comp_filters_design.m
#+PROPERTY: header-args:matlab+ :comments org
#+PROPERTY: header-args:matlab+ :exports both
#+PROPERTY: header-args:matlab+ :results none
@@ -35,6 +34,9 @@
- Section [[sec:notations]]
* System Description and Analysis
+:PROPERTIES:
+:header-args:matlab+: :tangle matlab/s1_system_description.m
+:END:
<>
** Introduction :ignore:
@@ -47,7 +49,7 @@
<>
#+end_src
-#+begin_src matlab
+#+begin_src matlab :tangle no
addpath('./matlab/');
addpath('./src/');
#+end_src
@@ -75,13 +77,11 @@ Based on the Figure [[fig:rotating_xy_platform]], the equations of motions are:
Where $\bm{G}_d$ is a $2 \times 2$ transfer function matrix.
\begin{equation}
-\begin{bmatrix} d_u \\ d_v \end{bmatrix} =
-\frac{1}{k} \frac{1}{G_{dp}}
+\bm{G}_d = \frac{1}{k} \frac{1}{G_{dp}}
\begin{bmatrix}
G_{dz} & G_{dc} \\
-G_{dc} & G_{dz}
\end{bmatrix}
-\begin{bmatrix} F_u \\ F_v \end{bmatrix}
\end{equation}
With:
\begin{align}
@@ -391,6 +391,9 @@ They are compared in Figure [[fig:plant_compare_rotating_speed]].
#+end_src
* Problem with pure Integral Force Feedback
+:PROPERTIES:
+:header-args:matlab+: :tangle matlab/s2_iff_pure_int.m
+:END:
<>
** Introduction :ignore:
@@ -406,7 +409,7 @@ They are compared in Figure [[fig:plant_compare_rotating_speed]].
<>
#+end_src
-#+begin_src matlab
+#+begin_src matlab :tangle no
addpath('./matlab/');
addpath('./src/');
#+end_src
@@ -714,6 +717,9 @@ It is shown that for non-null rotating speed, one pole is bound to the right-hal
#+end_src
* Integral Force Feedback with an High Pass Filter
+:PROPERTIES:
+:header-args:matlab+: :tangle matlab/s3_iff_hpf.m
+:END:
<>
** Introduction :ignore:
@@ -728,7 +734,7 @@ It is shown that for non-null rotating speed, one pole is bound to the right-hal
<>
#+end_src
-#+begin_src matlab
+#+begin_src matlab :tangle no
addpath('./matlab/');
addpath('./src/');
#+end_src
@@ -983,7 +989,7 @@ In order to visualize the effect of $\omega_i$ on the attainable damping, the Ro
for wi_i = 1:length(wis)
set(gca,'ColorOrderIndex',wi_i);
wi = wis(wi_i);
- L(wi_i) = plot(nan, nan, '.', 'DisplayName', sprintf('$\\Omega_i = %.2f \\omega_0$', wi./w0));
+ L(wi_i) = plot(nan, nan, '.', 'DisplayName', sprintf('$\\omega_i = %.2f \\omega_0$', wi./w0));
for g = gains
clpoles = pole(feedback(Giff, (g/(wi+s))*eye(2)));
set(gca,'ColorOrderIndex',wi_i);
@@ -1030,8 +1036,8 @@ In order to visualize the effect of $\omega_i$ on the attainable damping, the Ro
#+RESULTS:
[[file:figs/root_locus_wi_modified_iff.png]]
-#+begin_src matlab :exports none
- gains = logspace(-2, 4, 100);
+#+begin_src matlab :exports none :tangle no
+ gains = logspace(-2, 4, 500);
poles_iff_hpf = rootLocusPolesSorted(Giff, 1/(s + wi)*eye(2), gains, 'd_max', 1e-4);
@@ -1043,7 +1049,7 @@ In order to visualize the effect of $\omega_i$ on the attainable damping, the Ro
wi = wis(wi_i);
set(gca,'ColorOrderIndex',wi_i);
- L(wi_i) = plot(nan, nan, '.', 'DisplayName', sprintf('$\\Omega_i = %.2f \\omega_0$', wi./w0));
+ L(wi_i) = plot(nan, nan, '.', 'DisplayName', sprintf('$\\omega_i = %.2f \\omega_0$', wi./w0));
poles = rootLocusPolesSorted(Giff, 1/(s + wi)*eye(2), gains, 'd_max', 1e-4);
for p_i = 1:size(poles, 2)
@@ -1159,10 +1165,13 @@ To find the optimum, the gain that maximize the simultaneous damping of the mode
[[file:figs/mod_iff_damping_wi.png]]
#+begin_src matlab :tangle no :exports none :results none
- exportFig('figs-inkscape/root_locus_wi_modified_iff.pdf', 'width', 'wide', 'height', 'normal', 'png', false, 'pdf', false, 'svg', true);
+ exportFig('figs-inkscape/mod_iff_damping_wi.pdf', 'width', 'wide', 'height', 'normal', 'png', false, 'pdf', false, 'svg', true);
#+end_src
* IFF with a stiffness in parallel with the force sensor
+:PROPERTIES:
+:header-args:matlab+: :tangle matlab/s4_iff_kp.m
+:END:
<>
** Introduction :ignore:
@@ -1175,7 +1184,7 @@ To find the optimum, the gain that maximize the simultaneous damping of the mode
<>
#+end_src
-#+begin_src matlab
+#+begin_src matlab :tangle no
addpath('./matlab/');
addpath('./src/');
#+end_src
@@ -1873,6 +1882,10 @@ Let's take $k_p = 5 m \Omega^2$ and find the optimal IFF control gain $g$ such t
#+end_src
* Direct Velocity Feedback
+:PROPERTIES:
+:header-args:matlab+: :tangle matlab/s5_dvf.m
+:header-args:matlab+: :comments org :mkdirp yes
+:END:
<>
** Introduction :ignore:
@@ -1885,7 +1898,7 @@ Let's take $k_p = 5 m \Omega^2$ and find the optimal IFF control gain $g$ such t
<>
#+end_src
-#+begin_src matlab
+#+begin_src matlab :tangle no
addpath('./matlab/');
addpath('./src/');
#+end_src
@@ -2097,7 +2110,7 @@ It is shown that for rotating speed $\Omega < \omega_0$, the closed loop system
#+RESULTS:
[[file:figs/root_locus_dvf.png]]
-#+begin_src matlab :exports none
+#+begin_src matlab :exports none :tangle no
gains = logspace(-2, 1, 1000);
figure;
@@ -2137,6 +2150,9 @@ It is shown that for rotating speed $\Omega < \omega_0$, the closed loop system
#+end_src
* Comparison
+:PROPERTIES:
+:header-args:matlab+: :tangle matlab/s6_act_damp_comparison.m
+:END:
<>
** Introduction :ignore:
@@ -2150,7 +2166,7 @@ It is shown that for rotating speed $\Omega < \omega_0$, the closed loop system
<>
#+end_src
-#+begin_src matlab
+#+begin_src matlab :tangle no
addpath('./matlab/');
addpath('./src/');
#+end_src
@@ -2658,7 +2674,7 @@ The obtained damping ratio and control are shown below.
figure;
hold on;
plot(freqs, abs(squeeze(freqresp(Ciff(1,1), freqs))), ...
- 'DisplayName', 'IFF + LPF')
+ 'DisplayName', 'IFF + HPF')
plot(freqs, abs(squeeze(freqresp(Ciff_kp(1,1), freqs))), ...
'DisplayName', 'IFF + $k_p$')
plot(freqs, abs(squeeze(freqresp(Cdvf(1,1), freqs))), ...
diff --git a/matlab/matlab/s1_system_description.m b/matlab/matlab/s1_system_description.m
new file mode 100644
index 0000000..44fc678
--- /dev/null
+++ b/matlab/matlab/s1_system_description.m
@@ -0,0 +1,219 @@
+%% Clear Workspace and Close figures
+clear; close all; clc;
+
+%% Intialize Laplace variable
+s = zpk('s');
+
+% Numerical Values
+% Let's define initial values for the model.
+
+k = 1; % Actuator Stiffness [N/m]
+c = 0.05; % Actuator Damping [N/(m/s)]
+m = 1; % Payload mass [kg]
+
+xi = c/(2*sqrt(k*m));
+w0 = sqrt(k/m); % [rad/s]
+
+% Campbell Diagram
+% The Campbell Diagram displays the evolution of the real and imaginary parts of the system as a function of the rotating speed.
+
+% It is shown in Figure [[fig:campbell_diagram]], and one can see that the system becomes unstable for $\Omega > \omega_0$ (the real part of one of the poles becomes positive).
+
+
+Ws = linspace(0, 2, 51); % Vector of considered rotation speed [rad/s]
+
+p_ws = zeros(4, length(Ws));
+
+for W_i = 1:length(Ws)
+ W = Ws(W_i);
+
+ pole_G = pole(1/(((s^2)/(w0^2) + 2*xi*s/w0 + 1 - (W^2)/(w0^2))^2 + (2*W*s/(w0^2))^2));
+ [~, i_sort] = sort(imag(pole_G));
+ p_ws(:, W_i) = pole_G(i_sort);
+end
+
+clear pole_G;
+
+figure;
+
+ax1 = subplot(1,2,1);
+hold on;
+for p_i = 1:size(p_ws, 1)
+ plot(Ws, real(p_ws(p_i, :)), 'k-')
+end
+plot(Ws, zeros(size(Ws)), 'k--')
+hold off;
+xlabel('Rotation Frequency [rad/s]'); ylabel('Real Part');
+
+ax2 = subplot(1,2,2);
+hold on;
+for p_i = 1:size(p_ws, 1)
+ plot(Ws, imag(p_ws(p_i, :)), 'k-')
+ plot(Ws, -imag(p_ws(p_i, :)), 'k-')
+end
+hold off;
+xlabel('Rotation Frequency [rad/s]'); ylabel('Imaginary Part');
+
+% Simscape Model
+% Define the rotating speed for the Simscape Model.
+
+W = 0.1; % Rotation Speed [rad/s]
+
+Kiff = tf(zeros(2));
+Kdvf = tf(zeros(2));
+
+kp = 0; % Parallel Stiffness [N/m]
+cp = 0; % Parallel Damping [N/(m/s)]
+
+open('rotating_frame.slx');
+
+
+
+% The transfer function from $[F_u, F_v]$ to $[d_u, d_v]$ is identified from the Simscape model.
+
+
+%% Name of the Simulink File
+mdl = 'rotating_frame';
+
+%% Input/Output definition
+clear io; io_i = 1;
+io(io_i) = linio([mdl, '/K'], 1, 'openinput'); io_i = io_i + 1;
+io(io_i) = linio([mdl, '/G'], 3, 'openoutput'); io_i = io_i + 1;
+
+G = linearize(mdl, io, 0);
+
+%% Input/Output definition
+G.InputName = {'Fu', 'Fv'};
+G.OutputName = {'du', 'dv'};
+
+
+
+% The same transfer function from $[F_u, F_v]$ to $[d_u, d_v]$ is written down from the analytical model.
+
+Gth = (1/k)/(((s^2)/(w0^2) + 2*xi*s/w0 + 1 - (W^2)/(w0^2))^2 + (2*W*s/(w0^2))^2) * ...
+ [(s^2)/(w0^2) + 2*xi*s/w0 + 1 - (W^2)/(w0^2), 2*W*s/(w0^2) ; ...
+ -2*W*s/(w0^2), (s^2)/(w0^2) + 2*xi*s/w0 + 1 - (W^2)/(w0^2)];
+
+
+
+% Both transfer functions are compared in Figure [[fig:plant_simscape_analytical]] and are found to perfectly match.
+
+
+freqs = logspace(-1, 1, 1000);
+
+figure;
+ax1 = subplot(2, 2, 1);
+hold on;
+plot(freqs, abs(squeeze(freqresp(G(1,1), freqs))), '-')
+plot(freqs, abs(squeeze(freqresp(Gth(1,1), freqs))), '--')
+hold off;
+set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
+set(gca, 'XTickLabel',[]); ylabel('Magnitude [m/N]');
+title('$d_u/F_u$, $d_v/F_v$');
+
+ax3 = subplot(2, 2, 3);
+hold on;
+plot(freqs, 180/pi*angle(squeeze(freqresp(G(1,1), freqs))), '-')
+plot(freqs, 180/pi*angle(squeeze(freqresp(Gth(1,1), freqs))), '--')
+set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
+xlabel('Frequency [rad/s]'); ylabel('Phase [deg]');
+yticks(-180:90:180);
+ylim([-180 180]);
+hold off;
+
+ax2 = subplot(2, 2, 2);
+hold on;
+plot(freqs, abs(squeeze(freqresp(G(1,2), freqs))), '-')
+plot(freqs, abs(squeeze(freqresp(Gth(1,2), freqs))), '--')
+hold off;
+set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
+set(gca, 'XTickLabel',[]); ylabel('Magnitude [m/N]');
+title('$d_u/F_v$, $d_v/F_u$');
+
+ax4 = subplot(2, 2, 4);
+hold on;
+plot(freqs, 180/pi*angle(squeeze(freqresp(G(1,2), freqs))), '-', ...
+ 'DisplayName', 'Simscape')
+plot(freqs, 180/pi*angle(squeeze(freqresp(Gth(1,2), freqs))), '--', ...
+ 'DisplayName', 'Analytical')
+set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
+xlabel('Frequency [rad/s]'); ylabel('Phase [deg]');
+yticks(-180:90:180);
+ylim([-180 180]);
+hold off;
+legend('location', 'southwest');
+
+linkaxes([ax1,ax2,ax3,ax4],'x');
+xlim([freqs(1), freqs(end)]);
+linkaxes([ax1,ax2],'y');
+
+% Effect of the rotation speed
+% The transfer functions from $[F_u, F_v]$ to $[d_u, d_v]$ are identified for the following rotating speeds.
+
+Ws = [0, 0.2, 0.7, 1.1]*w0; % Rotating Speeds [rad/s]
+
+Gs = {zeros(2, 2, length(Ws))};
+
+for W_i = 1:length(Ws)
+ W = Ws(W_i);
+
+ Gs(:, :, W_i) = {(1/k)/(((s^2)/(w0^2) + 2*xi*s/w0 + 1 - (W^2)/(w0^2))^2 + (2*W*s/(w0^2))^2) * ...
+ [(s^2)/(w0^2) + 2*xi*s/w0 + 1 - (W^2)/(w0^2), 2*W*s/(w0^2) ; ...
+ -2*W*s/(w0^2), (s^2)/(w0^2) + 2*xi*s/w0 + 1 - (W^2)/(w0^2)]};
+end
+
+
+
+% They are compared in Figure [[fig:plant_compare_rotating_speed]].
+
+
+freqs = logspace(-2, 1, 1000);
+
+figure;
+ax1 = subplot(2, 2, 1);
+hold on;
+for W_i = 1:length(Ws)
+ plot(freqs, abs(squeeze(freqresp(Gs{W_i}(1,1), freqs))), ...
+ 'DisplayName', sprintf('$\\Omega = %.1f \\omega_0 $', Ws(W_i)/w0))
+end
+hold off;
+set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
+set(gca, 'XTickLabel',[]); ylabel('Magnitude [m/N]');
+legend('location', 'southwest');
+title('$d_u/F_u$, $d_v/F_v$');
+
+ax3 = subplot(2, 2, 3);
+hold on;
+for W_i = 1:length(Ws)
+ plot(freqs, 180/pi*angle(squeeze(freqresp(Gs{W_i}(1,1), freqs))))
+end
+set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
+xlabel('Frequency [rad/s]'); ylabel('Phase [deg]');
+yticks(-180:90:180);
+ylim([-180 180]);
+hold off;
+
+ax2 = subplot(2, 2, 2);
+hold on;
+for W_i = 1:length(Ws)
+ plot(freqs, abs(squeeze(freqresp(Gs{W_i}(2,1), freqs))))
+end
+hold off;
+set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
+set(gca, 'XTickLabel',[]); ylabel('Magnitude [m/N]');
+title('$d_u/F_v$, $d_v/F_u$');
+
+ax4 = subplot(2, 2, 4);
+hold on;
+for W_i = 1:length(Ws)
+ plot(freqs, 180/pi*angle(squeeze(freqresp(Gs{W_i}(1,1), freqs))))
+end
+set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
+xlabel('Frequency [rad/s]'); ylabel('Phase [deg]');
+yticks(-180:90:180);
+ylim([-180 180]);
+hold off;
+
+linkaxes([ax1,ax2,ax3,ax4],'x');
+xlim([freqs(1), freqs(end)]);
+linkaxes([ax1,ax2],'y');
diff --git a/matlab/matlab/s2_iff_pure_int.m b/matlab/matlab/s2_iff_pure_int.m
new file mode 100644
index 0000000..5498130
--- /dev/null
+++ b/matlab/matlab/s2_iff_pure_int.m
@@ -0,0 +1,193 @@
+%% Clear Workspace and Close figures
+clear; close all; clc;
+
+%% Intialize Laplace variable
+s = zpk('s');
+
+% Plant Parameters
+% Let's define initial values for the model.
+
+k = 1; % Actuator Stiffness [N/m]
+c = 0.05; % Actuator Damping [N/(m/s)]
+m = 1; % Payload mass [kg]
+
+xi = c/(2*sqrt(k*m));
+w0 = sqrt(k/m); % [rad/s]
+
+kp = 0; % [N/m]
+cp = 0; % [N/(m/s)]
+
+% Simscape Model
+% The rotation speed is set to $\Omega = 0.1 \omega_0$.
+
+W = 0.1*w0; % [rad/s]
+
+Kiff = tf(zeros(2));
+Kdvf = tf(zeros(2));
+
+open('rotating_frame.slx');
+
+
+
+% And the transfer function from $[F_u, F_v]$ to $[f_u, f_v]$ is identified using the Simscape model.
+
+%% Name of the Simulink File
+mdl = 'rotating_frame';
+
+%% Input/Output definition
+clear io; io_i = 1;
+io(io_i) = linio([mdl, '/K'], 1, 'openinput'); io_i = io_i + 1;
+io(io_i) = linio([mdl, '/G'], 2, 'openoutput'); io_i = io_i + 1;
+
+Giff = linearize(mdl, io, 0);
+
+%% Input/Output definition
+Giff.InputName = {'Fu', 'Fv'};
+Giff.OutputName = {'fu', 'fv'};
+
+% Comparison of the Analytical Model and the Simscape Model
+% The same transfer function from $[F_u, F_v]$ to $[f_u, f_v]$ is written down from the analytical model.
+
+Giff_th = 1/(((s^2)/(w0^2) + 2*xi*s/w0 + 1 - (W^2)/(w0^2))^2 + (2*W*s/(w0^2))^2) * ...
+ [(s^2/w0^2 - W^2/w0^2)*((s^2)/(w0^2) + 2*xi*s/w0 + 1 - (W^2)/(w0^2)) + (2*W*s/(w0^2))^2, - (2*xi*s/w0 + 1)*2*W*s/(w0^2) ; ...
+ (2*xi*s/w0 + 1)*2*W*s/(w0^2), (s^2/w0^2 - W^2/w0^2)*((s^2)/(w0^2) + 2*xi*s/w0 + 1 - (W^2)/(w0^2))+ (2*W*s/(w0^2))^2];
+
+
+
+% The two are compared in Figure [[fig:plant_iff_comp_simscape_analytical]] and found to perfectly match.
+
+
+freqs = logspace(-1, 1, 1000);
+
+figure;
+ax1 = subplot(2, 2, 1);
+hold on;
+plot(freqs, abs(squeeze(freqresp(Giff(1,1), freqs))), '-')
+plot(freqs, abs(squeeze(freqresp(Giff_th(1,1), freqs))), '--')
+hold off;
+set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
+set(gca, 'XTickLabel',[]); ylabel('Magnitude [N/N]');
+title('$f_u/F_u$, $f_v/F_v$');
+
+ax3 = subplot(2, 2, 3);
+hold on;
+plot(freqs, 180/pi*angle(squeeze(freqresp(Giff(1,1), freqs))), '-')
+plot(freqs, 180/pi*angle(squeeze(freqresp(Giff_th(1,1), freqs))), '--')
+set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
+xlabel('Frequency [rad/s]'); ylabel('Phase [deg]');
+yticks(-180:90:180);
+ylim([-180 180]);
+hold off;
+
+ax2 = subplot(2, 2, 2);
+hold on;
+plot(freqs, abs(squeeze(freqresp(Giff(1,2), freqs))), '-')
+plot(freqs, abs(squeeze(freqresp(Giff_th(1,2), freqs))), '--')
+hold off;
+set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
+set(gca, 'XTickLabel',[]); ylabel('Magnitude [N/N]');
+title('$f_u/F_v$, $f_v/F_u$');
+
+ax4 = subplot(2, 2, 4);
+hold on;
+plot(freqs, 180/pi*angle(squeeze(freqresp(Giff(1,2), freqs))), '-', ...
+ 'DisplayName', 'Simscape')
+plot(freqs, 180/pi*angle(squeeze(freqresp(Giff_th(1,2), freqs))), '--', ...
+ 'DisplayName', 'Analytical')
+set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
+xlabel('Frequency [rad/s]'); ylabel('Phase [deg]');
+yticks(-180:90:180);
+ylim([-180 180]);
+hold off;
+legend('location', 'northeast');
+
+linkaxes([ax1,ax2,ax3,ax4],'x');
+xlim([freqs(1), freqs(end)]);
+linkaxes([ax1,ax2],'y');
+
+% Effect of the rotation speed
+% The transfer functions from $[F_u, F_v]$ to $[f_u, f_v]$ are identified for the following rotating speeds.
+
+Ws = [0, 0.2, 0.7, 1.1]*w0; % Rotating Speeds [rad/s]
+
+Gsiff = {zeros(2, 2, length(Ws))};
+
+for W_i = 1:length(Ws)
+ W = Ws(W_i);
+
+ Gsiff(:, :, W_i) = {1/(((s^2)/(w0^2) + 2*xi*s/w0 + 1 - (W^2)/(w0^2))^2 + (2*W*s/(w0^2))^2) * ...
+ [(s^2/w0^2 - W^2/w0^2)*((s^2)/(w0^2) + 2*xi*s/w0 + 1 - (W^2)/(w0^2)) + (2*W*s/(w0^2))^2, - (2*xi*s/w0 + 1)*2*W*s/(w0^2) ; ...
+ (2*xi*s/w0 + 1)*2*W*s/(w0^2), (s^2/w0^2 - W^2/w0^2)*((s^2)/(w0^2) + 2*xi*s/w0 + 1 - (W^2)/(w0^2))+ (2*W*s/(w0^2))^2]};
+end
+
+
+
+% The obtained transfer functions are shown in Figure [[fig:plant_iff_compare_rotating_speed]].
+
+freqs = logspace(-2, 1, 1000);
+
+figure;
+
+ax1 = subplot(2, 1, 1);
+hold on;
+for W_i = 1:length(Ws)
+ plot(freqs, abs(squeeze(freqresp(Gsiff{W_i}(1,1), freqs))), ...
+ 'DisplayName', sprintf('$\\Omega = %.1f \\omega_0 $', Ws(W_i)/w0))
+end
+hold off;
+set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
+set(gca, 'XTickLabel',[]); ylabel('Magnitude [N/N]');
+legend('location', 'southeast');
+
+ax2 = subplot(2, 1, 2);
+hold on;
+for W_i = 1:length(Ws)
+ plot(freqs, 180/pi*angle(squeeze(freqresp(Gsiff{W_i}(1,1), freqs))))
+end
+set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
+xlabel('Frequency [rad/s]'); ylabel('Phase [deg]');
+yticks(-180:90:180);
+ylim([-180 180]);
+hold off;
+
+linkaxes([ax1,ax2],'x');
+xlim([freqs(1), freqs(end)]);
+
+% Decentralized Integral Force Feedback
+% The decentralized IFF controller consists of pure integrators:
+% \begin{equation}
+% \bm{K}_{\text{IFF}}(s) = \frac{g}{s} \begin{bmatrix}
+% 1 & 0 \\
+% 0 & 1
+% \end{bmatrix}
+% \end{equation}
+
+% The Root Locus (evolution of the poles of the closed loop system in the complex plane as a function of $g$) is shown in Figure [[fig:root_locus_pure_iff]].
+% It is shown that for non-null rotating speed, one pole is bound to the right-half plane, and thus the closed loop system is unstable.
+
+
+figure;
+
+gains = logspace(-2, 4, 100);
+
+hold on;
+for W_i = 1:length(Ws)
+ set(gca,'ColorOrderIndex',W_i);
+ plot(real(pole(Gsiff{W_i})), imag(pole(Gsiff{W_i})), 'x', ...
+ 'DisplayName', sprintf('$\\Omega = %.1f \\omega_0 $', Ws(W_i)/w0));
+ set(gca,'ColorOrderIndex',W_i);
+ plot(real(tzero(Gsiff{W_i})), imag(tzero(Gsiff{W_i})), 'o', ...
+ 'HandleVisibility', 'off');
+ for g = gains
+ set(gca,'ColorOrderIndex',W_i);
+ cl_poles = pole(feedback(Gsiff{W_i}, g/s*eye(2)));
+ plot(real(cl_poles), imag(cl_poles), '.', ...
+ 'HandleVisibility', 'off');
+ end
+end
+hold off;
+axis square;
+xlim([-2, 0.5]); ylim([0, 2.5]);
+
+xlabel('Real Part'); ylabel('Imaginary Part');
+legend('location', 'northwest');
diff --git a/matlab/matlab/s3_iff_hpf.m b/matlab/matlab/s3_iff_hpf.m
new file mode 100644
index 0000000..ddb77ce
--- /dev/null
+++ b/matlab/matlab/s3_iff_hpf.m
@@ -0,0 +1,251 @@
+%% Clear Workspace and Close figures
+clear; close all; clc;
+
+%% Intialize Laplace variable
+s = zpk('s');
+
+% Plant Parameters
+% Let's define initial values for the model.
+
+k = 1; % Actuator Stiffness [N/m]
+c = 0.05; % Actuator Damping [N/(m/s)]
+m = 1; % Payload mass [kg]
+
+xi = c/(2*sqrt(k*m));
+w0 = sqrt(k/m); % [rad/s]
+
+kp = 0; % [N/m]
+cp = 0; % [N/(m/s)]
+
+% Modified Integral Force Feedback Controller
+% Let's modify the initial Integral Force Feedback Controller ; 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:
+
+g = 2;
+wi = 0.1*w0;
+
+Kiff = (g/(wi+s))*eye(2);
+
+
+
+% And the following rotating speed.
+
+W = 0.1*w0;
+
+Giff = 1/(((s^2)/(w0^2) + 2*xi*s/w0 + 1 - (W^2)/(w0^2))^2 + (2*W*s/(w0^2))^2) * ...
+ [(s^2/w0^2 - W^2/w0^2)*((s^2)/(w0^2) + 2*xi*s/w0 + 1 - (W^2)/(w0^2)) + (2*W*s/(w0^2))^2, - (2*xi*s/w0 + 1)*2*W*s/(w0^2) ; ...
+ (2*xi*s/w0 + 1)*2*W*s/(w0^2), (s^2/w0^2 - W^2/w0^2)*((s^2)/(w0^2) + 2*xi*s/w0 + 1 - (W^2)/(w0^2))+ (2*W*s/(w0^2))^2];
+
+
+
+% The obtained Loop Gain is shown in Figure [[fig:loop_gain_modified_iff]].
+
+freqs = logspace(-2, 1, 1000);
+
+figure;
+
+ax1 = subplot(2, 1, 1);
+hold on;
+plot(freqs, abs(squeeze(freqresp(Giff(1,1)*(g/s), freqs))))
+plot(freqs, abs(squeeze(freqresp(Giff(1,1)*Kiff(1,1), freqs))))
+hold off;
+set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
+set(gca, 'XTickLabel',[]); ylabel('Loop Gain');
+
+ax2 = subplot(2, 1, 2);
+hold on;
+plot(freqs, 180/pi*angle(squeeze(freqresp(Giff(1,1)*(g/s), freqs))), ...
+ 'DisplayName', 'IFF')
+plot(freqs, 180/pi*angle(squeeze(freqresp(Giff(1,1)*Kiff(1,1), freqs))), ...
+ 'DisplayName', 'IFF + HPF')
+set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
+xlabel('Frequency [rad/s]'); ylabel('Phase [deg]');
+yticks(-180:90:180);
+ylim([-180 180]);
+legend('location', 'southwest');
+hold off;
+
+linkaxes([ax1,ax2],'x');
+xlim([freqs(1), freqs(end)]);
+
+% Root Locus
+% As shown in the Root Locus plot (Figure [[fig:root_locus_modified_iff]]), for some value of the gain, the system remains stable.
+
+
+figure;
+
+gains = logspace(-2, 4, 100);
+
+ax1 = subplot(1, 2, 1);
+hold on;
+% Pure Integrator
+set(gca,'ColorOrderIndex',1);
+plot(real(pole(Giff)), imag(pole(Giff)), 'x', 'DisplayName', 'IFF');
+set(gca,'ColorOrderIndex',1);
+plot(real(tzero(Giff)), imag(tzero(Giff)), 'o', 'HandleVisibility', 'off');
+for g = gains
+ clpoles = pole(feedback(Giff, (g/s)*eye(2)));
+ set(gca,'ColorOrderIndex',1);
+ plot(real(clpoles), imag(clpoles), '.', 'HandleVisibility', 'off');
+end
+% Modified IFF
+set(gca,'ColorOrderIndex',2);
+plot(real(pole(Giff)), imag(pole(Giff)), 'x', 'DisplayName', 'IFF + HPF');
+set(gca,'ColorOrderIndex',2);
+plot(real(tzero(Giff)), imag(tzero(Giff)), 'o', 'HandleVisibility', 'off');
+for g = gains
+ clpoles = pole(feedback(Giff, (g/(wi+s))*eye(2)));
+ set(gca,'ColorOrderIndex',2);
+ plot(real(clpoles), imag(clpoles), '.', 'HandleVisibility', 'off');
+end
+hold off;
+axis square;
+xlim([-2, 0.5]); ylim([-1.25, 1.25]);
+legend('location', 'northwest');
+xlabel('Real Part'); ylabel('Imaginary Part');
+
+ax2 = subplot(1, 2, 2);
+hold on;
+% Pure Integrator
+set(gca,'ColorOrderIndex',1);
+plot(real(pole(Giff)), imag(pole(Giff)), 'x');
+set(gca,'ColorOrderIndex',1);
+plot(real(tzero(Giff)), imag(tzero(Giff)), 'o');
+for g = gains
+ clpoles = pole(feedback(Giff, (g/s)*eye(2)));
+ set(gca,'ColorOrderIndex',1);
+ plot(real(clpoles), imag(clpoles), '.');
+end
+% Modified IFF
+set(gca,'ColorOrderIndex',2);
+plot(real(pole(Giff)), imag(pole(Giff)), 'x');
+set(gca,'ColorOrderIndex',2);
+plot(real(tzero(Giff)), imag(tzero(Giff)), 'o');
+for g = gains
+ clpoles = pole(feedback(Giff, (g/(wi+s))*eye(2)));
+ set(gca,'ColorOrderIndex',2);
+ plot(real(clpoles), imag(clpoles), '.');
+end
+hold off;
+axis square;
+xlim([-0.2, 0.1]); ylim([-0.15, 0.15]);
+xlabel('Real Part'); ylabel('Imaginary Part');
+
+% What is the optimal $\omega_i$ and $g$?
+% In order to visualize the effect of $\omega_i$ on the attainable damping, the Root Locus is displayed in Figure [[fig:root_locus_wi_modified_iff]] for the following $\omega_i$:
+
+wis = [0.01, 0.1, 0.5, 1]*w0; % [rad/s]
+
+figure;
+
+gains = logspace(-2, 4, 100);
+
+ax1 = subplot(1, 2, 1);
+hold on;
+for wi_i = 1:length(wis)
+ set(gca,'ColorOrderIndex',wi_i);
+ wi = wis(wi_i);
+ L(wi_i) = plot(nan, nan, '.', 'DisplayName', sprintf('$\\omega_i = %.2f \\omega_0$', wi./w0));
+ for g = gains
+ clpoles = pole(feedback(Giff, (g/(wi+s))*eye(2)));
+ set(gca,'ColorOrderIndex',wi_i);
+ plot(real(clpoles), imag(clpoles), '.');
+ end
+end
+plot(real(pole(Giff)), imag(pole(Giff)), 'kx');
+plot(real(tzero(Giff)), imag(tzero(Giff)), 'ko');
+hold off;
+axis square;
+xlim([-2.3, 0.1]); ylim([-1.2, 1.2]);
+xticks([-2:1:2]); yticks([-2:1:2]);
+legend(L, 'location', 'northwest');
+xlabel('Real Part'); ylabel('Imaginary Part');
+
+clear L
+
+ax2 = subplot(1, 2, 2);
+hold on;
+for wi_i = 1:length(wis)
+ set(gca,'ColorOrderIndex', wi_i);
+ wi = wis(wi_i);
+ for g = gains
+ clpoles = pole(feedback(Giff, (g/(wi+s))*eye(2)));
+ set(gca,'ColorOrderIndex', wi_i);
+ plot(real(clpoles), imag(clpoles), '.');
+ end
+end
+plot(real(pole(Giff)), imag(pole(Giff)), 'kx');
+plot(real(tzero(Giff)), imag(tzero(Giff)), 'ko');
+hold off;
+axis square;
+xlim([-0.2, 0.1]); ylim([-0.15, 0.15]);
+xticks([-0.2:0.1:0.1]); yticks([-0.2:0.1:0.2]);
+xlabel('Real Part'); ylabel('Imaginary Part');
+
+
+
+% For the controller
+% \begin{equation}
+% K_{\text{IFF}}(s) = g\frac{1}{\omega_i + s} \begin{bmatrix}
+% 1 & 0 \\
+% 0 & 1
+% \end{bmatrix}
+% \end{equation}
+% The gain at which the system becomes unstable is
+% \begin{equation}
+% g_\text{max} = \omega_i \left( \frac{{\omega_0}^2}{\Omega^2} - 1 \right) \label{eq:iff_gmax}
+% \end{equation}
+
+% While it seems that small $\omega_i$ do allow more damping to be added to the system (Figure [[fig:root_locus_wi_modified_iff]]), the control gains may be limited to small values due to eqref:eq:iff_gmax thus reducing the attainable damping.
+
+
+% There must be an optimum for $\omega_i$.
+% To find the optimum, the gain that maximize the simultaneous damping of the mode is identified for a wide range of $\omega_i$ (Figure [[fig:mod_iff_damping_wi]]).
+
+wis = logspace(-2, 1, 31)*w0; % [rad/s]
+
+opt_zeta = 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);
+ gains = linspace(0, (w0^2/W^2 - 1)*wi, 100);
+
+ for g = gains
+ Kiff = (g/(wi+s))*eye(2);
+
+ [w, zeta] = damp(minreal(feedback(Giff, Kiff)));
+
+ if min(zeta) > opt_zeta(wi_i) && all(zeta > 0)
+ opt_zeta(wi_i) = min(zeta);
+ opt_gain(wi_i) = g;
+ end
+ end
+end
+
+figure;
+yyaxis left
+plot(wis, opt_zeta, '-o', 'DisplayName', '$\xi_{cl}$');
+set(gca, 'YScale', 'lin');
+ylim([0,1]);
+ylabel('Attainable Damping Ratio $\xi$');
+
+yyaxis right
+hold on;
+plot(wis, opt_gain, '-x', 'DisplayName', '$g_{opt}$');
+plot(wis, wis*((w0/W)^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');
diff --git a/matlab/matlab/s4_iff_kp.m b/matlab/matlab/s4_iff_kp.m
new file mode 100644
index 0000000..0f48a51
--- /dev/null
+++ b/matlab/matlab/s4_iff_kp.m
@@ -0,0 +1,389 @@
+%% Clear Workspace and Close figures
+clear; close all; clc;
+
+%% Intialize Laplace variable
+s = zpk('s');
+
+% Plant Parameters
+% Let's define initial values for the model.
+
+k = 1; % Actuator Stiffness [N/m]
+c = 0.05; % Actuator Damping [N/(m/s)]
+m = 1; % Payload mass [kg]
+
+xi = c/(2*sqrt(k*m));
+w0 = sqrt(k/m); % [rad/s]
+
+kp = 0; % [N/m]
+cp = 0; % [N/(m/s)]
+
+% Comparison of the Analytical Model and the Simscape Model
+% The same transfer function from $[F_u, F_v]$ to $[f_u, f_v]$ is written down from the analytical model.
+
+W = 0.1*w0; % [rad/s]
+
+kp = 1.5*m*W^2;
+cp = 0;
+
+Kiff = tf(zeros(2));
+Kdvf = tf(zeros(2));
+
+open('rotating_frame.slx');
+
+%% Name of the Simulink File
+mdl = 'rotating_frame';
+
+%% Input/Output definition
+clear io; io_i = 1;
+io(io_i) = linio([mdl, '/K'], 1, 'openinput'); io_i = io_i + 1;
+io(io_i) = linio([mdl, '/G'], 2, 'openoutput'); io_i = io_i + 1;
+
+Giff = linearize(mdl, io, 0);
+
+%% Input/Output definition
+Giff.InputName = {'Fu', 'Fv'};
+Giff.OutputName = {'fu', 'fv'};
+
+w0p = sqrt((k + kp)/m);
+xip = c/(2*sqrt((k+kp)*m));
+
+Giff_th = 1/( (s^2/w0p^2 + 2*xip*s/w0p + 1 - W^2/w0p^2)^2 + (2*(s/w0p)*(W/w0p))^2 ) * [ ...
+ (s^2/w0p^2 + kp/(k + kp) - W^2/w0p^2)*(s^2/w0p^2 + 2*xip*s/w0p + 1 - W^2/w0p^2) + (2*(s/w0p)*(W/w0p))^2, -(2*xip*s/w0p + k/(k + kp))*(2*(s/w0p)*(W/w0p));
+ (2*xip*s/w0p + k/(k + kp))*(2*(s/w0p)*(W/w0p)), (s^2/w0p^2 + kp/(k + kp) - W^2/w0p^2)*(s^2/w0p^2 + 2*xip*s/w0p + 1 - W^2/w0p^2) + (2*(s/w0p)*(W/w0p))^2 ];
+Giff_th.InputName = {'Fu', 'Fv'};
+Giff_th.OutputName = {'fu', 'fv'};
+
+freqs = logspace(-1, 1, 1000);
+
+figure;
+ax1 = subplot(2, 2, 1);
+hold on;
+plot(freqs, abs(squeeze(freqresp(Giff(1,1), freqs))), '-')
+plot(freqs, abs(squeeze(freqresp(Giff_th(1,1), freqs))), '--')
+hold off;
+set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
+set(gca, 'XTickLabel',[]); ylabel('Magnitude [N/N]');
+title('$f_u/F_u$, $f_v/F_v$');
+
+ax3 = subplot(2, 2, 3);
+hold on;
+plot(freqs, 180/pi*angle(squeeze(freqresp(Giff(1,1), freqs))), '-')
+plot(freqs, 180/pi*angle(squeeze(freqresp(Giff_th(1,1), freqs))), '--')
+set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
+xlabel('Frequency [rad/s]'); ylabel('Phase [deg]');
+yticks(-180:90:180);
+ylim([-180 180]);
+hold off;
+
+ax2 = subplot(2, 2, 2);
+hold on;
+plot(freqs, abs(squeeze(freqresp(Giff(1,2), freqs))), '-')
+plot(freqs, abs(squeeze(freqresp(Giff_th(1,2), freqs))), '--')
+hold off;
+set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
+set(gca, 'XTickLabel',[]); ylabel('Magnitude [N/N]');
+title('$f_u/F_v$, $f_v/F_u$');
+
+ax4 = subplot(2, 2, 4);
+hold on;
+plot(freqs, 180/pi*angle(squeeze(freqresp(Giff(1,2), freqs))), '-', ...
+ 'DisplayName', 'Simscape')
+plot(freqs, 180/pi*angle(squeeze(freqresp(Giff_th(1,2), freqs))), '--', ...
+ 'DisplayName', 'Analytical')
+set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
+xlabel('Frequency [rad/s]'); ylabel('Phase [deg]');
+yticks(-180:90:180);
+ylim([-180 180]);
+hold off;
+legend('location', 'northeast');
+
+linkaxes([ax1,ax2,ax3,ax4],'x');
+xlim([freqs(1), freqs(end)]);
+linkaxes([ax1,ax2],'y');
+
+% Effect of the parallel stiffness on the IFF plant
+% The rotation speed is set to $\Omega = 0.1 \omega_0$.
+
+W = 0.1*w0; % [rad/s]
+
+
+
+% And the IFF plant (transfer function from $[F_u, F_v]$ to $[f_u, f_v]$) is identified in three different cases:
+% - without parallel stiffness
+% - with a small parallel stiffness $k_p < m \Omega^2$
+% - with a large parallel stiffness $k_p > m \Omega^2$
+
+% The results are shown in Figure [[fig:plant_iff_kp]].
+
+% One can see that for $k_p > m \Omega^2$, the systems shows alternating complex conjugate poles and zeros.
+
+
+kp = 0;
+cp = 0;
+
+w0p = sqrt((k + kp)/m);
+xip = c/(2*sqrt((k+kp)*m));
+
+Giff = 1/( (s^2/w0p^2 + 2*xip*s/w0p + 1 - W^2/w0p^2)^2 + (2*(s/w0p)*(W/w0p))^2 ) * [ ...
+ (s^2/w0p^2 + kp/(k + kp) - W^2/w0p^2)*(s^2/w0p^2 + 2*xip*s/w0p + 1 - W^2/w0p^2) + (2*(s/w0p)*(W/w0p))^2, -(2*xip*s/w0p + k/(k + kp))*(2*(s/w0p)*(W/w0p));
+ (2*xip*s/w0p + k/(k + kp))*(2*(s/w0p)*(W/w0p)), (s^2/w0p^2 + kp/(k + kp) - W^2/w0p^2)*(s^2/w0p^2 + 2*xip*s/w0p + 1 - W^2/w0p^2) + (2*(s/w0p)*(W/w0p))^2];
+
+kp = 0.5*m*W^2;
+cp = 0;
+
+w0p = sqrt((k + kp)/m);
+xip = c/(2*sqrt((k+kp)*m));
+
+Giff_s = 1/( (s^2/w0p^2 + 2*xip*s/w0p + 1 - W^2/w0p^2)^2 + (2*(s/w0p)*(W/w0p))^2 ) * [ ...
+ (s^2/w0p^2 + kp/(k + kp) - W^2/w0p^2)*(s^2/w0p^2 + 2*xip*s/w0p + 1 - W^2/w0p^2) + (2*(s/w0p)*(W/w0p))^2, -(2*xip*s/w0p + k/(k + kp))*(2*(s/w0p)*(W/w0p));
+ (2*xip*s/w0p + k/(k + kp))*(2*(s/w0p)*(W/w0p)), (s^2/w0p^2 + kp/(k + kp) - W^2/w0p^2)*(s^2/w0p^2 + 2*xip*s/w0p + 1 - W^2/w0p^2) + (2*(s/w0p)*(W/w0p))^2];
+
+kp = 1.5*m*W^2;
+cp = 0;
+
+w0p = sqrt((k + kp)/m);
+xip = c/(2*sqrt((k+kp)*m));
+
+Giff_l = 1/( (s^2/w0p^2 + 2*xip*s/w0p + 1 - W^2/w0p^2)^2 + (2*(s/w0p)*(W/w0p))^2 ) * [ ...
+ (s^2/w0p^2 + kp/(k + kp) - W^2/w0p^2)*(s^2/w0p^2 + 2*xip*s/w0p + 1 - W^2/w0p^2) + (2*(s/w0p)*(W/w0p))^2, -(2*xip*s/w0p + k/(k + kp))*(2*(s/w0p)*(W/w0p));
+ (2*xip*s/w0p + k/(k + kp))*(2*(s/w0p)*(W/w0p)), (s^2/w0p^2 + kp/(k + kp) - W^2/w0p^2)*(s^2/w0p^2 + 2*xip*s/w0p + 1 - W^2/w0p^2) + (2*(s/w0p)*(W/w0p))^2];
+
+freqs = logspace(-2, 1, 1000);
+
+figure;
+
+ax1 = subplot(2, 1, 1);
+hold on;
+plot(freqs, abs(squeeze(freqresp(Giff(1,1), freqs))), 'k-')
+plot(freqs, abs(squeeze(freqresp(Giff_s(1,1), freqs))), 'k--')
+plot(freqs, abs(squeeze(freqresp(Giff_l(1,1), freqs))), 'k:')
+hold off;
+set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
+set(gca, 'XTickLabel',[]); ylabel('Magnitude [N/N]');
+
+ax2 = subplot(2, 1, 2);
+hold on;
+plot(freqs, 180/pi*angle(squeeze(freqresp(Giff(1,1), freqs))), 'k-', ...
+ 'DisplayName', '$k_p = 0$')
+plot(freqs, 180/pi*angle(squeeze(freqresp(Giff_s(1,1), freqs))), 'k--', ...
+ 'DisplayName', '$k_p < m\Omega^2$')
+plot(freqs, 180/pi*angle(squeeze(freqresp(Giff_l(1,1), freqs))), 'k:', ...
+ 'DisplayName', '$k_p > m\Omega^2$')
+set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
+xlabel('Frequency [rad/s]'); ylabel('Phase [deg]');
+yticks(-180:90:180);
+ylim([-180 180]);
+hold off;
+legend('location', 'southwest');
+
+linkaxes([ax1,ax2],'x');
+xlim([freqs(1), freqs(end)]);
+
+% IFF when adding a spring in parallel
+% In Figure [[fig:root_locus_iff_kp]] is displayed the Root Locus in the three considered cases with
+% \begin{equation}
+% K_{\text{IFF}} = \frac{g}{s} \begin{bmatrix}
+% 1 & 0 \\
+% 0 & 1
+% \end{bmatrix}
+% \end{equation}
+
+% One can see that for $k_p > m \Omega^2$, the root locus stays in the left half of the complex plane and thus the control system is unconditionally stable.
+
+% Thus, decentralized IFF controller with pure integrators can be used if:
+% \begin{equation}
+% k_{p} > m \Omega^2
+% \end{equation}
+
+
+figure;
+
+gains = logspace(-2, 2, 100);
+
+subplot(1,2,1);
+hold on;
+set(gca,'ColorOrderIndex',1);
+plot(real(pole(Giff)), imag(pole(Giff)), 'x', ...
+ 'DisplayName', '$k_p = 0$');
+set(gca,'ColorOrderIndex',1);
+plot(real(tzero(Giff)), imag(tzero(Giff)), 'o', ...
+ 'HandleVisibility', 'off');
+for g = gains
+ cl_poles = pole(feedback(Giff, (g/s)*eye(2)));
+ set(gca,'ColorOrderIndex',1);
+ plot(real(cl_poles), imag(cl_poles), '.', ...
+ 'HandleVisibility', 'off');
+end
+
+set(gca,'ColorOrderIndex',2);
+plot(real(pole(Giff_s)), imag(pole(Giff_s)), 'x', ...
+ 'DisplayName', '$k_p < m\Omega^2$');
+set(gca,'ColorOrderIndex',2);
+plot(real(tzero(Giff_s)), imag(tzero(Giff_s)), 'o', ...
+ 'HandleVisibility', 'off');
+for g = gains
+ cl_poles = pole(feedback(Giff_s, (g/s)*eye(2)));
+ set(gca,'ColorOrderIndex',2);
+ plot(real(cl_poles), imag(cl_poles), '.', ...
+ 'HandleVisibility', 'off');
+end
+
+set(gca,'ColorOrderIndex',3);
+plot(real(pole(Giff_l)), imag(pole(Giff_l)), 'x', ...
+ 'DisplayName', '$k_p > m\Omega^2$');
+set(gca,'ColorOrderIndex',3);
+plot(real(tzero(Giff_l)), imag(tzero(Giff_l)), 'o', ...
+ 'HandleVisibility', 'off');
+for g = gains
+ set(gca,'ColorOrderIndex',3);
+ cl_poles = pole(feedback(Giff_l, (g/s)*eye(2)));
+ plot(real(cl_poles), imag(cl_poles), '.', ...
+ 'HandleVisibility', 'off');
+end
+hold off;
+axis square;
+xlim([-1, 0.2]); ylim([0, 1.2]);
+
+xlabel('Real Part'); ylabel('Imaginary Part');
+legend('location', 'northwest');
+
+subplot(1,2,2);
+hold on;
+set(gca,'ColorOrderIndex',1);
+plot(real(pole(Giff)), imag(pole(Giff)), 'x');
+set(gca,'ColorOrderIndex',1);
+plot(real(tzero(Giff)), imag(tzero(Giff)), 'o');
+for g = gains
+ cl_poles = pole(feedback(Giff, (g/s)*eye(2)));
+ set(gca,'ColorOrderIndex',1);
+ plot(real(cl_poles), imag(cl_poles), '.');
+end
+
+set(gca,'ColorOrderIndex',2);
+plot(real(pole(Giff_s)), imag(pole(Giff_s)), 'x');
+set(gca,'ColorOrderIndex',2);
+plot(real(tzero(Giff_s)), imag(tzero(Giff_s)), 'o');
+for g = gains
+ cl_poles = pole(feedback(Giff_s, (g/s)*eye(2)));
+ set(gca,'ColorOrderIndex',2);
+ plot(real(cl_poles), imag(cl_poles), '.');
+end
+
+set(gca,'ColorOrderIndex',3);
+plot(real(pole(Giff_l)), imag(pole(Giff_l)), 'x');
+set(gca,'ColorOrderIndex',3);
+plot(real(tzero(Giff_l)), imag(tzero(Giff_l)), 'o');
+for g = gains
+ set(gca,'ColorOrderIndex',3);
+ cl_poles = pole(feedback(Giff_l, (g/s)*eye(2)));
+ plot(real(cl_poles), imag(cl_poles), '.');
+end
+hold off;
+axis square;
+xlim([-0.04, 0.06]); ylim([0, 0.1]);
+
+xlabel('Real Part'); ylabel('Imaginary Part');
+
+% Effect of $k_p$ on the attainable damping
+% However, having large values of $k_p$ may:
+% - decrease the actuator force authority
+% - decrease the attainable damping
+
+% To study the second point, Root Locus plots for the following values of $k_p$ are shown in Figure [[fig:root_locus_iff_kps]].
+
+kps = [2, 20, 40]*m*W^2;
+
+
+
+% It is shown that large values of $k_p$ decreases the attainable damping.
+
+
+figure;
+
+gains = logspace(-2, 4, 500);
+
+hold on;
+for kp_i = 1:length(kps)
+ kp = kps(kp_i);
+
+ w0p = sqrt((k + kp)/m);
+ xip = c/(2*sqrt((k+kp)*m));
+
+ Giff = 1/( (s^2/w0p^2 + 2*xip*s/w0p + 1 - W^2/w0p^2)^2 + (2*(s/w0p)*(W/w0p))^2 ) * [ ...
+ (s^2/w0p^2 + kp/(k + kp) - W^2/w0p^2)*(s^2/w0p^2 + 2*xip*s/w0p + 1 - W^2/w0p^2) + (2*(s/w0p)*(W/w0p))^2, -(2*xip*s/w0p + k/(k + kp))*(2*(s/w0p)*(W/w0p));
+ (2*xip*s/w0p + k/(k + kp))*(2*(s/w0p)*(W/w0p)), (s^2/w0p^2 + kp/(k + kp) - W^2/w0p^2)*(s^2/w0p^2 + 2*xip*s/w0p + 1 - W^2/w0p^2) + (2*(s/w0p)*(W/w0p))^2 ];
+
+ set(gca,'ColorOrderIndex',kp_i);
+ plot(real(pole(Giff)), imag(pole(Giff)), 'x', ...
+ 'DisplayName', sprintf('$k_p = %.1f m \\Omega^2$', kp/(m*W^2)));
+ set(gca,'ColorOrderIndex',kp_i);
+ plot(real(tzero(Giff)), imag(tzero(Giff)), 'o', ...
+ 'HandleVisibility', 'off');
+ for g = gains
+ Kiffa = (g/s)*eye(2);
+ cl_poles = pole(feedback(Giff, Kiffa));
+ set(gca,'ColorOrderIndex',kp_i);
+ plot(real(cl_poles), imag(cl_poles), '.', ...
+ 'HandleVisibility', 'off');
+ end
+end
+hold off;
+axis square;
+xlim([-1.2, 0.2]); ylim([0, 1.4]);
+
+xlabel('Real Part'); ylabel('Imaginary Part');
+legend('location', 'northwest');
+
+% Optimal Gain
+% Let's take $k_p = 5 m \Omega^2$ and find the optimal IFF control gain $g$ such that maximum damping are added to the poles of the closed loop system.
+
+
+kp = 5*m*W^2;
+cp = 0.01;
+
+w0p = sqrt((k + kp)/m);
+xip = c/(2*sqrt((k+kp)*m));
+
+Giff = 1/( (s^2/w0p^2 + 2*xip*s/w0p + 1 - W^2/w0p^2)^2 + (2*(s/w0p)*(W/w0p))^2 ) * [ ...
+ (s^2/w0p^2 + kp/(k + kp) - W^2/w0p^2)*(s^2/w0p^2 + 2*xip*s/w0p + 1 - W^2/w0p^2) + (2*(s/w0p)*(W/w0p))^2, -(2*xip*s/w0p + k/(k + kp))*(2*(s/w0p)*(W/w0p));
+ (2*xip*s/w0p + k/(k + kp))*(2*(s/w0p)*(W/w0p)), (s^2/w0p^2 + kp/(k + kp) - W^2/w0p^2)*(s^2/w0p^2 + 2*xip*s/w0p + 1 - W^2/w0p^2) + (2*(s/w0p)*(W/w0p))^2 ];
+
+opt_zeta = 0;
+opt_gain = 0;
+
+gains = logspace(-2, 4, 1000);
+
+for g = gains
+ Kiff = (g/s)*eye(2);
+
+ [w, zeta] = damp(minreal(feedback(Giff, Kiff)));
+
+ if min(zeta) > opt_zeta && all(zeta > 0)
+ opt_zeta = min(zeta);
+ opt_gain = min(g);
+ end
+end
+
+figure;
+
+gains = logspace(-2, 4, 1000);
+
+hold on;
+plot(real(pole(Giff)), imag(pole(Giff)), 'kx');
+plot(real(tzero(Giff)), imag(tzero(Giff)), 'ko');
+for g = gains
+ clpoles = pole(minreal(feedback(Giff, (g/s)*eye(2))));
+ plot(real(clpoles), imag(clpoles), 'k.');
+end
+% Optimal Gain
+clpoles = pole(minreal(feedback(Giff, (opt_gain/s)*eye(2))));
+set(gca,'ColorOrderIndex',1);
+plot(real(clpoles), imag(clpoles), 'x');
+for clpole = clpoles'
+ set(gca,'ColorOrderIndex',1);
+ plot([0, real(clpole)], [0, imag(clpole)], '-', 'LineWidth', 1);
+end
+hold off;
+axis square;
+xlim([-1.2, 0.2]); ylim([0, 1.4]);
+xlabel('Real Part'); ylabel('Imaginary Part');
diff --git a/matlab/matlab/s5_dvf.m b/matlab/matlab/s5_dvf.m
new file mode 100644
index 0000000..0bf9d94
--- /dev/null
+++ b/matlab/matlab/s5_dvf.m
@@ -0,0 +1,159 @@
+%% Clear Workspace and Close figures
+clear; close all; clc;
+
+%% Intialize Laplace variable
+s = zpk('s');
+
+% Plant Parameters
+% Let's define initial values for the model.
+
+k = 1; % Actuator Stiffness [N/m]
+c = 0.05; % Actuator Damping [N/(m/s)]
+m = 1; % Payload mass [kg]
+
+xi = c/(2*sqrt(k*m));
+w0 = sqrt(k/m); % [rad/s]
+
+kp = 0; % [N/m]
+cp = 0; % [N/(m/s)]
+
+% Comparison of the Analytical Model and the Simscape Model
+% The rotating speed is set to $\Omega = 0.1 \omega_0$.
+
+W = 0.1*w0;
+
+Kiff = tf(zeros(2));
+Kdvf = tf(zeros(2));
+
+open('rotating_frame.slx');
+
+
+
+% And the transfer function from $[F_u, F_v]$ to $[v_u, v_v]$ is identified using the Simscape model.
+
+%% Name of the Simulink File
+mdl = 'rotating_frame';
+
+%% Input/Output definition
+clear io; io_i = 1;
+io(io_i) = linio([mdl, '/K'], 1, 'openinput'); io_i = io_i + 1;
+io(io_i) = linio([mdl, '/G'], 1, 'openoutput'); io_i = io_i + 1;
+
+Gdvf = linearize(mdl, io, 0);
+
+%% Input/Output definition
+Gdvf.InputName = {'Fu', 'Fv'};
+Gdvf.OutputName = {'Vu', 'Vv'};
+
+
+
+% The same transfer function from $[F_u, F_v]$ to $[v_u, v_v]$ is written down from the analytical model.
+
+Gdvf_th = (s/k)/(((s^2)/(w0^2) + 2*xi*s/w0 + 1 - (W^2)/(w0^2))^2 + (2*W*s/(w0^2))^2) * ...
+ [(s^2)/(w0^2) + 2*xi*s/w0 + 1 - (W^2)/(w0^2), 2*W*s/(w0^2) ; ...
+ -2*W*s/(w0^2), (s^2)/(w0^2) + 2*xi*s/w0 + 1 - (W^2)/(w0^2)];
+
+Gdvf_th.InputName = {'Fu', 'Fv'};
+Gdvf_th.OutputName = {'vu', 'vv'};
+
+
+
+% The two are compared in Figure [[fig:plant_iff_comp_simscape_analytical]] and found to perfectly match.
+
+
+freqs = logspace(-1, 1, 1000);
+
+figure;
+ax1 = subplot(2, 2, 1);
+hold on;
+plot(freqs, abs(squeeze(freqresp(Gdvf(1,1), freqs))), '-')
+plot(freqs, abs(squeeze(freqresp(Gdvf_th(1,1), freqs))), '--')
+hold off;
+set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
+set(gca, 'XTickLabel',[]); ylabel('Magnitude [$\frac{m/s}{N}$]');
+title('$v_u/F_u$, $v_v/F_v$');
+
+ax3 = subplot(2, 2, 3);
+hold on;
+plot(freqs, 180/pi*angle(squeeze(freqresp(Gdvf(1,1), freqs))), '-')
+plot(freqs, 180/pi*angle(squeeze(freqresp(Gdvf_th(1,1), freqs))), '--')
+set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
+xlabel('Frequency [rad/s]'); ylabel('Phase [deg]');
+yticks(-180:90:180);
+ylim([-180 180]);
+hold off;
+
+ax2 = subplot(2, 2, 2);
+hold on;
+plot(freqs, abs(squeeze(freqresp(Gdvf(1,2), freqs))), '-')
+plot(freqs, abs(squeeze(freqresp(Gdvf_th(1,2), freqs))), '--')
+hold off;
+set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
+set(gca, 'XTickLabel',[]); ylabel('Magnitude [$\frac{m/s}{N}$]');
+title('$v_u/F_v$, $v_v/F_u$');
+
+ax4 = subplot(2, 2, 4);
+hold on;
+plot(freqs, 180/pi*angle(squeeze(freqresp(Gdvf(1,2), freqs))), '-')
+plot(freqs, 180/pi*angle(squeeze(freqresp(Gdvf_th(1,2), freqs))), '--')
+set(gca, 'XScale', 'log'); set(gca, 'YScale', 'lin');
+xlabel('Frequency [rad/s]'); ylabel('Phase [deg]');
+yticks(-180:90:180);
+ylim([-180 180]);
+hold off;
+
+linkaxes([ax1,ax2,ax3,ax4],'x');
+xlim([freqs(1), freqs(end)]);
+
+linkaxes([ax1,ax2],'y');
+
+% Root Locus
+% The Decentralized Direct Velocity Feedback controller consist of a pure gain on the diagonal:
+% \begin{equation}
+% K_{\text{DVF}}(s) = g \begin{bmatrix}
+% 1 & 0 \\
+% 0 & 1
+% \end{bmatrix}
+% \end{equation}
+
+% The corresponding Root Locus plots for the following rotating speeds are shown in Figure [[fig:root_locus_dvf]].
+
+Ws = [0, 0.2, 0.7, 1.1]*w0; % Rotating Speeds [rad/s]
+
+
+
+% It is shown that for rotating speed $\Omega < \omega_0$, the closed loop system is unconditionally stable and arbitrary damping can be added to the poles.
+
+gains = logspace(-2, 1, 100);
+
+figure;
+hold on;
+for W_i = 1:length(Ws)
+ W = Ws(W_i);
+
+ Gdvf = (s/k)/(((s^2)/(w0^2) + 2*xi*s/w0 + 1 - (W^2)/(w0^2))^2 + (2*W*s/(w0^2))^2) * ...
+ [(s^2)/(w0^2) + 2*xi*s/w0 + 1 - (W^2)/(w0^2), 2*W*s/(w0^2) ; ...
+ -2*W*s/(w0^2), (s^2)/(w0^2) + 2*xi*s/w0 + 1 - (W^2)/(w0^2)];
+
+ set(gca,'ColorOrderIndex',W_i);
+ plot(real(pole(Gdvf)), imag(pole(Gdvf)), 'x', ...
+ 'DisplayName', sprintf('$\\Omega = %.2f \\omega_0 $', W/w0));
+
+ set(gca,'ColorOrderIndex',W_i);
+ plot(real(tzero(Gdvf)), imag(tzero(Gdvf)), 'o', ...
+ 'HandleVisibility', 'off');
+
+ for g = gains
+ set(gca,'ColorOrderIndex',W_i);
+ cl_poles = pole(feedback(Gdvf, g*eye(2)));
+
+ plot(real(cl_poles), imag(cl_poles), '.', ...
+ 'HandleVisibility', 'off');
+ end
+end
+hold off;
+axis square;
+xlim([-2, 0.5]); ylim([0, 2.5]);
+
+xlabel('Real Part'); ylabel('Imaginary Part');
+legend('location', 'northwest');
diff --git a/matlab/matlab/s6_act_damp_comparison.m b/matlab/matlab/s6_act_damp_comparison.m
new file mode 100644
index 0000000..637b977
--- /dev/null
+++ b/matlab/matlab/s6_act_damp_comparison.m
@@ -0,0 +1,364 @@
+%% Clear Workspace and Close figures
+clear; close all; clc;
+
+%% Intialize Laplace variable
+s = zpk('s');
+
+% Plant Parameters
+% Let's define initial values for the model.
+
+k = 1; % Actuator Stiffness [N/m]
+c = 0.05; % Actuator Damping [N/(m/s)]
+m = 1; % Payload mass [kg]
+
+xi = c/(2*sqrt(k*m));
+w0 = sqrt(k/m); % [rad/s]
+
+kp = 0; % [N/m]
+cp = 0; % [N/(m/s)]
+
+
+
+% The rotating speed is set to $\Omega = 0.1 \omega_0$.
+
+W = 0.1*w0;
+
+% Root Locus
+% IFF with High Pass Filter
+
+wi = 0.1*w0; % [rad/s]
+
+Giff = 1/(((s^2)/(w0^2) + 2*xi*s/w0 + 1 - (W^2)/(w0^2))^2 + (2*W*s/(w0^2))^2) * ...
+ [(s^2/w0^2 - W^2/w0^2)*((s^2)/(w0^2) + 2*xi*s/w0 + 1 - (W^2)/(w0^2)) + (2*W*s/(w0^2))^2, - (2*xi*s/w0 + 1)*2*W*s/(w0^2) ; ...
+ (2*xi*s/w0 + 1)*2*W*s/(w0^2), (s^2/w0^2 - W^2/w0^2)*((s^2)/(w0^2) + 2*xi*s/w0 + 1 - (W^2)/(w0^2))+ (2*W*s/(w0^2))^2];
+
+
+
+% IFF With parallel Stiffness
+
+kp = 5*m*W^2;
+k = k - kp;
+
+w0p = sqrt((k + kp)/m);
+xip = c/(2*sqrt((k+kp)*m));
+
+Giff_kp = 1/( (s^2/w0p^2 + 2*xip*s/w0p + 1 - W^2/w0p^2)^2 + (2*(s/w0p)*(W/w0p))^2 ) * [ ...
+ (s^2/w0p^2 + kp/(k + kp) - W^2/w0p^2)*(s^2/w0p^2 + 2*xip*s/w0p + 1 - W^2/w0p^2) + (2*(s/w0p)*(W/w0p))^2, -(2*xip*s/w0p + k/(k + kp))*(2*(s/w0p)*(W/w0p));
+ (2*xip*s/w0p + k/(k + kp))*(2*(s/w0p)*(W/w0p)), (s^2/w0p^2 + kp/(k + kp) - W^2/w0p^2)*(s^2/w0p^2 + 2*xip*s/w0p + 1 - W^2/w0p^2) + (2*(s/w0p)*(W/w0p))^2 ];
+
+k = k + kp;
+
+
+
+% DVF
+
+Gdvf = (s/k)/(((s^2)/(w0^2) + 2*xi*s/w0 + 1 - (W^2)/(w0^2))^2 + (2*W*s/(w0^2))^2) * ...
+ [(s^2)/(w0^2) + 2*xi*s/w0 + 1 - (W^2)/(w0^2), 2*W*s/(w0^2) ; ...
+ -2*W*s/(w0^2), (s^2)/(w0^2) + 2*xi*s/w0 + 1 - (W^2)/(w0^2)];
+
+figure;
+
+gains = logspace(-2, 2, 100);
+
+hold on;
+set(gca,'ColorOrderIndex',1);
+plot(real(pole(Giff)), imag(pole(Giff)), 'x', ...
+ 'DisplayName', 'IFF + LFP');
+set(gca,'ColorOrderIndex',1);
+plot(real(tzero(Giff)), imag(tzero(Giff)), 'o', ...
+ 'HandleVisibility', 'off');
+for g = gains
+ Kiff = (g/(wi + s))*eye(2);
+ cl_poles = pole(feedback(Giff, Kiff));
+ set(gca,'ColorOrderIndex',1);
+ plot(real(cl_poles), imag(cl_poles), '.', ...
+ 'HandleVisibility', 'off');
+end
+
+set(gca,'ColorOrderIndex',2);
+plot(real(pole(Giff_kp)), imag(pole(Giff_kp)), 'x', ...
+ 'DisplayName', 'IFF + $k_p$');
+set(gca,'ColorOrderIndex',2);
+plot(real(tzero(Giff_kp)), imag(tzero(Giff_kp)), 'o', ...
+ 'HandleVisibility', 'off');
+for g = gains
+ Kiffa = (g/s)*eye(2);
+ cl_poles = pole(feedback(Giff_kp, Kiffa));
+ set(gca,'ColorOrderIndex',2);
+ plot(real(cl_poles), imag(cl_poles), '.', ...
+ 'HandleVisibility', 'off');
+end
+
+set(gca,'ColorOrderIndex',3);
+plot(real(pole(Gdvf)), imag(pole(Gdvf)), 'x', ...
+ 'DisplayName', 'DVF');
+set(gca,'ColorOrderIndex',3);
+plot(real(tzero(Gdvf)), imag(tzero(Gdvf)), 'o', ...
+ 'HandleVisibility', 'off');
+for g = gains
+ Kdvf = g*eye(2);
+ cl_poles = pole(feedback(Gdvf, Kdvf));
+ set(gca,'ColorOrderIndex',3);
+ plot(real(cl_poles), imag(cl_poles), '.', ...
+ 'HandleVisibility', 'off');
+end
+hold off;
+axis square;
+xlim([-1.2, 0.05]); ylim([0, 1.25]);
+
+xlabel('Real Part'); ylabel('Imaginary Part');
+legend('location', 'northwest');
+
+% Controllers - Optimal Gains
+% In order to compare to three considered Active Damping techniques, gains that yield maximum damping of all the modes are computed for each case.
+
+
+%% IFF with pseudo integrators
+gains = linspace(0, (w0^2/W^2 - 1)*wi, 100);
+opt_zeta_iff = 0;
+opt_gain_iff = 0;
+
+for g = gains
+ Kiff = (g/(wi+s))*eye(2);
+
+ [w, zeta] = damp(minreal(feedback(Giff, Kiff)));
+
+ if min(zeta) > opt_zeta_iff && all(zeta > 0)
+ opt_zeta_iff = min(zeta);
+ opt_gain_iff = g;
+ end
+end
+
+%% IFF with Parallel Stiffness
+gains = logspace(-2, 4, 100);
+opt_zeta_kp = 0;
+opt_gain_kp = 0;
+
+for g = gains
+ Kiff = g/s*eye(2);
+
+ [w, zeta] = damp(minreal(feedback(Giff_kp, Kiff)));
+
+ if min(zeta) > opt_zeta_kp && all(zeta > 0)
+ opt_zeta_kp = min(zeta);
+ opt_gain_kp = g;
+ end
+end
+
+%% Direct Velocity Feedback
+gains = logspace(0, 2, 100);
+opt_zeta_dvf = 0;
+opt_gain_dvf = 0;
+
+for g = gains
+ Kdvf = g*eye(2);
+
+ [w, zeta] = damp(minreal(feedback(Gdvf, Kdvf)));
+
+ if min(zeta) > opt_zeta_dvf && all(zeta > 0) && min(zeta) < 0.85
+ opt_zeta_dvf = min(zeta);
+ opt_gain_dvf = g;
+ end
+end
+
+% Transmissibility
+% <>
+
+
+open('rotating_frame.slx');
+
+% Open Loop :ignore:
+
+Kdvf = tf(zeros(2));
+Kiff = tf(zeros(2));
+
+kp = 0;
+cp = 0;
+
+%% Name of the Simulink File
+mdl = 'rotating_frame';
+
+%% Input/Output definition
+clear io; io_i = 1;
+io(io_i) = linio([mdl, '/dw'], 1, 'input'); io_i = io_i + 1;
+io(io_i) = linio([mdl, '/Meas'], 1, 'output'); io_i = io_i + 1;
+
+Tol = linearize(mdl, io, 0);
+
+%% Input/Output definition
+Tol.InputName = {'Dwx', 'Dwy'};
+Tol.OutputName = {'Dx', 'Dy'};
+
+% Pseudo Integrator IFF :ignore:
+
+kp = 0;
+cp = 0;
+
+Kdvf = tf(zeros(2));
+
+Kiff = opt_gain_iff/(wi + s)*tf(eye(2));
+
+%% Name of the Simulink File
+mdl = 'rotating_frame';
+
+%% Input/Output definition
+clear io; io_i = 1;
+io(io_i) = linio([mdl, '/dw'], 1, 'input'); io_i = io_i + 1;
+io(io_i) = linio([mdl, '/Meas'], 1, 'output'); io_i = io_i + 1;
+
+Tiff = linearize(mdl, io, 0);
+
+%% Input/Output definition
+Tiff.InputName = {'Dwx', 'Dwy'};
+Tiff.OutputName = {'Dx', 'Dy'};
+
+% IFF With parallel Stiffness :ignore:
+
+kp = 5*m*W^2;
+cp = 0.01;
+
+Kiff = opt_gain_kp/s*tf(eye(2));
+
+Kdvf = tf(zeros(2));
+
+%% Name of the Simulink File
+mdl = 'rotating_frame';
+
+%% Input/Output definition
+clear io; io_i = 1;
+io(io_i) = linio([mdl, '/dw'], 1, 'input'); io_i = io_i + 1;
+io(io_i) = linio([mdl, '/Meas'], 1, 'output'); io_i = io_i + 1;
+
+Tiff_kp = linearize(mdl, io, 0);
+
+%% Input/Output definition
+Tiff_kp.InputName = {'Dwx', 'Dwy'};
+Tiff_kp.OutputName = {'Dx', 'Dy'};
+
+% DVF :ignore:
+
+kp = 0;
+cp = 0;
+
+Kiff = tf(zeros(2));
+
+Kdvf = opt_gain_kp*tf(eye(2));
+
+%% Name of the Simulink File
+mdl = 'rotating_frame';
+
+%% Input/Output definition
+clear io; io_i = 1;
+io(io_i) = linio([mdl, '/dw'], 1, 'input'); io_i = io_i + 1;
+io(io_i) = linio([mdl, '/Meas'], 1, 'output'); io_i = io_i + 1;
+
+Tdvf = linearize(mdl, io, 0);
+
+%% Input/Output definition
+Tdvf.InputName = {'Dwx', 'Dwy'};
+Tdvf.OutputName = {'Dx', 'Dy'};
+
+% Transmissibility :ignore:
+
+freqs = logspace(-2, 1, 1000);
+
+figure;
+hold on;
+plot(freqs, abs(squeeze(freqresp(Tiff(1,1), freqs))), ...
+ 'DisplayName', 'IFF + HPF')
+plot(freqs, abs(squeeze(freqresp(Tiff_kp(1,1), freqs))), ...
+ 'DisplayName', 'IFF + $k_p$')
+plot(freqs, abs(squeeze(freqresp(Tdvf(1,1), freqs))), ...
+ 'DisplayName', 'DVF')
+plot(freqs, abs(squeeze(freqresp(Tol(1,1), freqs))), 'k-', ...
+ 'DisplayName', 'Open-Loop')
+hold off;
+set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
+xlabel('Frequency [rad/s]'); ylabel('Transmissibility [m/m]');
+legend('location', 'southwest');
+
+% Open Loop :ignore:
+
+Kdvf = tf(zeros(2));
+Kiff = tf(zeros(2));
+
+kp = 0;
+cp = 0;
+
+%% Name of the Simulink File
+mdl = 'rotating_frame';
+
+%% Input/Output definition
+clear io; io_i = 1;
+io(io_i) = linio([mdl, '/fd'], 1, 'input'); io_i = io_i + 1;
+io(io_i) = linio([mdl, '/Meas'], 1, 'output'); io_i = io_i + 1;
+
+Col = linearize(mdl, io, 0);
+
+%% Input/Output definition
+Col.InputName = {'Fdx', 'Fdy'};
+Col.OutputName = {'Dx', 'Dy'};
+
+% Pseudo Integrator IFF :ignore:
+
+kp = 0;
+cp = 0;
+
+Kdvf = tf(zeros(2));
+
+Kiff = opt_gain_iff/(wi + s)*tf(eye(2));
+
+Ciff = linearize(mdl, io, 0);
+
+%% Input/Output definition
+Ciff.InputName = {'Fdx', 'Fdy'};
+Ciff.OutputName = {'Dx', 'Dy'};
+
+% IFF With parallel Stiffness :ignore:
+
+kp = 5*m*W^2;
+cp = 0.01;
+
+Kiff = opt_gain_kp/s*tf(eye(2));
+
+Kdvf = tf(zeros(2));
+
+Ciff_kp = linearize(mdl, io, 0);
+
+%% Input/Output definition
+Ciff_kp.InputName = {'Fdx', 'Fdy'};
+Ciff_kp.OutputName = {'Dx', 'Dy'};
+
+% DVF :ignore:
+
+kp = 0;
+cp = 0;
+
+Kiff = tf(zeros(2));
+
+Kdvf = opt_gain_kp*tf(eye(2));
+
+Cdvf = linearize(mdl, io, 0);
+
+%% Input/Output definition
+Cdvf.InputName = {'Fdx', 'Fdy'};
+Cdvf.OutputName = {'Dx', 'Dy'};
+
+% Compliance :ignore:
+
+freqs = logspace(-2, 1, 1000);
+
+figure;
+hold on;
+plot(freqs, abs(squeeze(freqresp(Ciff(1,1), freqs))), ...
+ 'DisplayName', 'IFF + HPF')
+plot(freqs, abs(squeeze(freqresp(Ciff_kp(1,1), freqs))), ...
+ 'DisplayName', 'IFF + $k_p$')
+plot(freqs, abs(squeeze(freqresp(Cdvf(1,1), freqs))), ...
+ 'DisplayName', 'DVF')
+plot(freqs, abs(squeeze(freqresp(Col(1,1), freqs))), 'k-', ...
+ 'DisplayName', 'Open-Loop')
+hold off;
+set(gca, 'XScale', 'log'); set(gca, 'YScale', 'log');
+xlabel('Frequency [rad/s]'); ylabel('Compliance [m/N]');
+legend('location', 'southwest');