% TOGAC20_MSD_StabilityofFeedback.m

% This file takes the transfer function from the MSD feedback controller
% that provides the framework for our approach.
% The system stability is analyzed using phase margin and closed loop poles

%%% It has been acknowledged that CL poles should be analyzed using a
%%% different method, and the method in this file is no longer valid. See
%%% the following files for a correct stability analysis:


% Impedance_select.m
% TFFeedback.m
% FeedbackStabMap.m
% FeedbackStabMapNoImped.m
% CostTransMapFeedback.m
% Check_stable.m

% Created by Brevin Banks
% Modified 3/13/2023


%default values for a given arbitrary mass spring damper
m = 10; %kg
b = 5; %Ns/m
k = 1; %N/m

%human impedance
mh = 5;%5; Worst case reported mass from Aydin et al.
bh = 41;%41; Worst case reported damping from Aydin et al.
kh = 401;%401; Worst case reported stiffness from Aydin et al.

%environoment impedance
me = 0;%unused assumed only largely stiff
be = 0;%unused assumed only largely stiff
ke = 16599;% Worst case reported stiffness from Aydin et al.

m_ad = 50; % Desired impedance mass
b_ad = 500; % Desired impedance damping

Zhs = tf([mh bh],[1]) + tf([kh],[1 0]); % Impedance human
Ze = tf([me be],[1])+tf([ke],[1 0]); % Impedance from environment
Z = minreal(Zhs+Ze);

% our plant design with velocity control of mass spring damper according to
% simulink tf extraction
Ps = tf([1 0],[m b k]); % dynamics tf including spring stiffness for velocity

% P = tf([1],[m b]); % not spring stiffness on velocity. Similar to Steinen et al Yr

% controller gains
P = 900; %Ns/m
D = 10;
muff = 10; %kg
bff = 2; %Ns/m

Cfb = tf([D 0],[1]) + tf([P],[1]); %Feedback
Cff = tf([muff bff],[1]); %Feedforward

A = tf([1],[m_ad b_ad]); % Admittance Controller


fprintf('The system transfer function is: \n');
T = (A*Cfb*Ps)/(1+Cfb*Ps*(A*Z+1)) % Total system CL transfer function


figure('name','Bode Plot of feedback only Transfer Function')
bode(T)
title('The resonse of the CL feedback only transfer function.')

%% Stienen et al. stability method Phase margin evaluation


Ya = (A*Cfb*Ps)/(Ps*Cfb+1); % Open loop transfer function no impedance

% grab the phase margin of the system Ya*Zs
[mag,phase1] = margin(Ya*Z);

% Check if stable or not
if isinf(phase1) % Stable if infinite
    stable_stienen = true;
elseif phase1 <= 0 % unstable if negative
    stable_stienen = false;
elseif phase1 > 0 % stable if positive
    stable_stienen = true;
end

formatSpec = 'Stability according to phase margin: %s with phase margin of %4.2f \n';
stable_string = stringstable(stable_stienen);
fprintf(formatSpec,stable_string,phase1)

%% Aydin et al. stability method closed loop poles

stable_aydin =1;

poles = pole(T);
for tester=1:length(poles)
    if real(poles(tester))>0
        stable_aydin =0;
    end
end



formatSpec = 'Stability according to CL Poles: %s with the following CL poles \n';
stable_string = stringstable(stable_aydin);
fprintf(formatSpec,stable_string)
fprintf('%d\n',poles);


% This function will check the boolean case for the stable_condition
% variable. Because the above stability testers initialize the map with
% ones, but the stability checks return 1 for unstable, this will flip the
% response to return the correct variable to place in the map.
% Input:
%   stable_condition - a boolean for the stability of a TF for a given ma
%   and ba
function stable_string = stringstable(stable_condition)
if stable_condition==true
    stable_string = 'Stable';
else
    stable_string = 'Unstable';
end
end

