%% 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

%% Colors for the figures
colors = colororder;

%% Force Sensor Calibration
% Load measurement data
load('calibration_force_sensor.mat', 't', 'F', 'Fc')

% Remove any offset such that they are both measuring no force when not in contact.
F  = F  - mean(F( t > 0.5 & t < 1.0)); % FC2231 [N]
Fc = Fc - mean(Fc(t > 0.5 & t < 1.0)); % XFL212R [N]

% Only get useful stroke
F  = F( t > 2 & t < 2.2);
Fc = Fc(t > 2 & t < 2.2);
t  = t( t > 2 & t < 2.2);

% Make a line fit
fit_F = polyfit(Fc, F, 1);

% Estimate the gain mismatch
F_gain_mismatch = 100*(1 - fit_F(1)); % in %

% Estimate non-linearity of the sensors
F_non_linearity = 100*(F - (Fc*fit_F(1) + fit_F(2)))./Fc; % in %

%% Measured two forces and linear fit
figure;
yyaxis left
hold on;
plot(Fc, F, '.', 'DisplayName', 'Raw Data');
plot([0, 6], [0,6]*fit_F(1) + fit_F(2), '-', 'color', [colors(3,:), 0.5], 'DisplayName', 'Line Fit');
hold off;
xlabel('XFL212R [N]'); ylabel('FC2231 [N]');
xlim([0,6]); ylim([0,6]);
xticks([0:6])
yticks([0:6])

yyaxis right
plot(Fc, movmean(F_non_linearity, 200), '-', 'DisplayName', 'Non linearity');
ylim([-0.15, 0.15]);
ylabel('Non Linearity [$\%$]')

leg = legend('location', 'southeast', 'FontSize', 8, 'NumColumns', 1);
leg.ItemTokenSize(1) = 15;

%% Estimaetd load cell stiffness
% Load measurement data
load('force_sensor_stiffness_meas.mat', 't', 'F', 'd')

% Remove offset
F  = F - mean(F(t > 0.5 & t < 1.0));

% Select important part of data
F  = F( t > 4.55 & t < 7.24);
d  = d( t > 4.55 & t < 7.24); d = d - d(1);
t  = t( t > 4.55 & t < 7.24);

% Linear fit
fit_k = polyfit(F(F<10), d(F<10), 1);

%% Displacement as a function of the measured force
figure;
hold on;
plot(F, 1e6*d, 'k-', 'DisplayName', 'Raw Data');
plot(F([1,end]), 1e6*(F([1,end])*fit_k(1) + fit_k(2)), '--', 'DisplayName', sprintf('Fit, $k_F \\approx %.2f N/\\mu m$', 1e-6/fit_k(1)));
hold off;
xlabel('Force [$N$]'); ylabel('Displacement [$\mu m$]');
xlim([0,45]); ylim([0,60]);
legend('location', 'southeast', 'FontSize', 8);

%% Estimate the bending stiffness and stroke from the measurement - First Flexible joint
% Load Measured Data for first flexible joint
load('meas_stiff_flex_1_x.mat', 't', 'F', 'd');

% Start measurement at t = 0.2 s
d = d(t > 0.2);
F = F(t > 0.2);
t = t(t > 0.2); t = t - t(1);

% Zero the force
F = F - mean(F(t < 0.2));

% Find when the force sensor touches the flexible joint
i_l_start = find(F > 0.3, 1, 'first');

% Compute torque and angular displacement
h = 22.5e-3; % Height [m]
Tx = h * F; % Applied torque in [Nm]
thetax = atan2(d - d(i_l_start), h); % Measured angle in [rad]

% Find then the maximum torque is applied
[~, i_s_stop] = max(Tx);
% Linear region stops ~ when 90% of the stroke is reached
i_l_stop = find(thetax > 0.9*thetax(i_s_stop), 1, 'first');
% Mechanical "Stop" region start ~20Nmm before maximum torque is applied
i_s_start = find(Tx > max(Tx)-20e-3, 1, 'first');

% Linear fit in the "linear" region
fit_l = polyfit(Tx(i_l_start:i_l_stop), thetax(i_l_start:i_l_stop), 1);

% Linear fit in the "mechanical stop" region
fit_s = polyfit(Tx(i_s_start:i_s_stop), thetax(i_s_start:i_s_stop), 1);

% Reset displacement more precisely based on fit
thetax = thetax - fit_l(2);
fit_s(2) = fit_s(2) - fit_l(2);
fit_l(2) = 0;

%% Estimation of the bending stiffness
kRx_l = 1/fit_l(1); % Bending Stiffness [Nm/rad]
kRx_s = 1/fit_s(1); % Mechanical "Stop" Stiffness [Nm/rad]

%% Estimation of the bending stroke
% This is done by finding the intersection of the two linear fits
theta_max = fit_l(1)*fit_s(2)/(fit_l(1) - fit_s(1)); % Maximum angular stroke [rad]
Tx_at_theta_max = (fit_s(2) - fit_l(2))/(fit_l(1) - fit_s(1));

%% Measured force and displacement as a function of time
figure;
yyaxis left
hold on;
plot(t, F);
plot(0.8*cos(0:0.01:2*pi)+0.8, ...
     2.8*sin(0:0.01:2*pi)-1, 'k--', 'HandleVisibility', 'off');
text(1.8, -1.2, sprintf('Not in\ncontact'), 'horizontalalignment', 'left');
plot(0.4*cos(0:0.01:2*pi)+3, ...
     1.1*sin(0:0.01:2*pi)+4.8, 'k--');
text(3.5, 4.8, sprintf('Mechanical\nStop'), 'horizontalalignment', 'left');
hold off;
ylabel('Force $F_y$ [N]');
ylim([-4, 6])
ylimr = get(gca,'Ylim');

yyaxis right
plot(t, 1e3*d);
xlabel('Time [s]');
ylabel('Displacement $d_y$ [mm]');
xlim([0,5]);
% Make the force and displacement superimpose
ylim([0.364 - 4*(0.8315-0.364)/4.095, 0.364 + 6*(0.8315-0.364)/4.095])

% Regions where to plot the fitted data
Tx_l_fit = [0, Tx_at_theta_max];
Tx_s_fit = [Tx_at_theta_max, Tx(i_s_stop)];

figure;
hold on;
plot(Tx(1:i_s_stop), 1e3*thetax(1:i_s_stop), '-k', 'DisplayName', 'Raw data')
plot(Tx_l_fit, 1e3*(Tx_l_fit*fit_l(1) + fit_l(2)), '--', 'DisplayName', sprintf('$k_{R_x} = %.1f$ Nm/rad', kRx_l))
plot(Tx_s_fit, 1e3*(Tx_s_fit*fit_s(1) + fit_s(2)), '--', 'DisplayName', sprintf('$k_{R_x,stop} = %.0f$ Nm/rad', kRx_s))
plot([0, Tx_at_theta_max], [1e3*theta_max, 1e3*theta_max], 'k--', 'HandleVisibility', 'off')
plot([0, Tx_at_theta_max], [0, 0], 'k--', 'HandleVisibility', 'off')
anArrow = annotation('doublearrow', 'LineWidth', 0.5);
anArrow.Parent = gca;
anArrow.Position = [0.05, 0, 0, 1e3*fit_l(1)*fit_s(2)/(fit_l(1) - fit_s(1))];
text(0.052, 0.4*1e3*fit_l(1)*fit_s(2)/(fit_l(1) - fit_s(1)), sprintf('$\\theta_{x,\\max} = %.1f$ mrad', 1e3*theta_max), 'horizontalalignment', 'left');
hold off;
xlabel('Torque $T_x$ [Nm]');
ylabel('Angle $\theta_x$ [mrad]');
xlim([0, 0.15]);
ylim([-5,25]);
leg = legend('location', 'southeast', 'FontSize', 8);
leg.ItemTokenSize(1) = 15;

%% Measure the bending stiffness and Stroke for all the flexible joints
figure;
hold on;

%% Start with the X-bending
% Initialize variables
Rx = zeros(1,16); % Bending stiffnesses [Nm/rad]
kSx = zeros(1,16); % Bending stiffnesses at "stop" [Nm/rad]
Rmx = zeros(1,16); % Bending stroke [rad]

for i = 1:16
    % Load the data
    load(sprintf('meas_stiff_flex_%i_x.mat', i), 't', 'F', 'd');

    % Start measurement at t = 0.2 s
    d = d(t > 0.2);
    F = F(t > 0.2);
    t = t(t > 0.2); t = t - t(1);

    % Zero the force
    F = F - mean(F(t < 0.2));

    % Find when the force sensor touches the flexible joint
    i_l_start = find(F > 0.3, 1, 'first');

    % Zero the displacement when it comes in contact
    d = d - d(i_l_start);

    % Compute torque and angular displacement
    h = 22.5e-3; % Height [m]
    Tx = h * F; % Applied torque in [Nm]
    thetax = atan2(d, h); % Measured angle in [rad]

    % Find then the maximum torque is applied
    [~, i_s_stop] = max(Tx);
    % Linear region stops ~ when 90% of the stroke is reached
    i_l_stop = find(thetax > 0.9*thetax(i_s_stop), 1, 'first');
    % Mechanical "Stop" region start ~20Nmm before maximum torque is applied
    i_s_start = find(Tx > max(Tx)-20e-3, 1, 'first');

    % Linear fit in the "linear" region
    fit_l = polyfit(Tx(i_l_start:i_l_stop), thetax(i_l_start:i_l_stop), 1);

    % Linear fit in the "mechanical stop" region
    fit_s = polyfit(Tx(i_s_start:i_s_stop), thetax(i_s_start:i_s_stop), 1);

    % Reset displacement more precisely based on fit
    thetax = thetax - fit_l(2);
    fit_s(2) = fit_s(2) - fit_l(2);
    fit_l(2) = 0;

    % Estimation of the bending stiffness and bending stroke
    kRx(i) = 1/fit_l(1); % Bending Stiffness [Nm/rad]
    kSx(i) = 1/fit_s(1); % Mechanical "Stop" Stiffness [Nm/rad]
    Rmx(i) = fit_l(1)*fit_s(2)/(fit_l(1) - fit_s(1)); % Maximum angular stroke [rad]

    if i == 1
        plot(Tx(1:10:i_s_stop), 1e3*thetax(1:10:i_s_stop), '-', 'color', [colors(1,:), 0.4], ...
            'DisplayName', '$k_{R_x}$')
    else
        plot(Tx(1:10:i_s_stop), 1e3*thetax(1:10:i_s_stop), '-', 'color', [colors(1,:), 0.4], ...
            'HandleVisibility', 'off')
    end
end

%% Continue with the Y-bending
% Initialize variables
kRy = zeros(1,16); % Bending stiffnesses [Nm/rad]
kSy = zeros(1,16); % Bending stiffnesses at "stop" [Nm/rad]
Rmy = zeros(1,16); % Bending stroke [rad]

for i = 1:16
    % Load the data
    load(sprintf('meas_stiff_flex_%i_y.mat', i), 't', 'F', 'd');

    % Start measurement at t = 0.2 s
    d = d(t > 0.2);
    F = F(t > 0.2);
    t = t(t > 0.2); t = t - t(1);

    % Zero the force
    F = F - mean(F(t < 0.2));

    % Find when the force sensor touches the flexible joint
    i_l_start = find(F > 0.3, 1, 'first');

    % Zero the displacement when it comes in contact
    d = d - d(i_l_start);

    % Compute torque and angular displacement
    h = 22.5e-3; % Height [m]
    Ty = h * F; % Applied torque in [Nm]
    thetay = atan2(d, h); % Measured angle in [rad]

    % Find then the maximum torque is applied
    [~, i_s_stop] = max(Ty);
    % Linear region stops ~ when 90% of the stroke is reached
    i_l_stop = find(thetay > 0.9*thetay(i_s_stop), 1, 'first');
    % Mechanical "Stop" region start ~20Nmm before maximum torque is applied
    i_s_start = find(Ty > max(Ty)-20e-3, 1, 'first');

    % Linear fit in the "linear" region
    fit_l = polyfit(Ty(i_l_start:i_l_stop), thetay(i_l_start:i_l_stop), 1);

    % Linear fit in the "mechanical stop" region
    fit_s = polyfit(Ty(i_s_start:i_s_stop), thetay(i_s_start:i_s_stop), 1);

    % Reset displacement more precisely based on fit
    thetay = thetay - fit_l(2);
    fit_s(2) = fit_s(2) - fit_l(2);
    fit_l(2) = 0;

    % Estimation of the bending stiffness and bending stroke
    kRy(i) = 1/fit_l(1); % Bending Stiffness [Nm/rad]
    kSy(i) = 1/fit_s(1); % Mechanical "Stop" Stiffness [Nm/rad]
    Rmy(i) = fit_l(1)*fit_s(2)/(fit_l(1) - fit_s(1)); % Maximum angular stroke [rad]

    if i == 1
        plot(Ty(1:10:i_s_stop), 1e3*thetay(1:10:i_s_stop), '-', 'color', [colors(2,:), 0.4], ...
            'DisplayName', '$k_{R_y}$')
    else
        plot(Ty(1:10:i_s_stop), 1e3*thetay(1:10:i_s_stop), '-', 'color', [colors(2,:), 0.4], ...
            'HandleVisibility', 'off')
    end
end

xlabel('Torque $T$ [Nm]');
ylabel('Angle $\theta$ [mrad]');
xlim([0, 0.15]);
ylim([-5,25]);
legend('location', 'southeast', 'FontSize', 8);

figure;
histogram([kRx, kRy], [4:0.2:5])
xlabel('Bending stiffness [Nm/rad]')
xticks([4:0.2:5])
