% TOGAC38_AMBF_CartesianSystemIdent.m % This file was used to analyze the input and and output data for the galen % surgical robot in AMBF. This was done with the Cartesian test data from % the chirp signals to get the transfer functions % The systems were identified using the tfest method and ssest methods from % matlab's system identification toolbox % Created by Brevin Banks % Modified April 15 2023 %% Chirp input % load the data dt = 0.0231; % measured time step per sampling loop Vout = load('AMBFCartesianData/CartChirp0d001TO5HzXVOUT.mat'); Vin = load('AMBFCartesianData/CartChirp0d001TO5HzXVIN.mat'); Voutx = Vout.cv(1,:); Vinx = Vin.rv(1,:); Vout = load('AMBFCartesianData/CartChirp0d001TO5HzYVOUT.mat'); Vin = load('AMBFCartesianData/CartChirp0d001TO5HzYVIN.mat'); Vouty = Vout.cv(2,:); Viny = Vin.rv(2,:); Vout = load('AMBFCartesianData/CartChirp0d001TO5HzZVOUT.mat'); Vin = load('AMBFCartesianData/CartChirp0d001TO5HzZVIN.mat'); Voutz = Vout.cv(3,:); Vinz = Vin.rv(3,:); Vout = load('AMBFCartesianData/CartChirp0d001TO5HzWxVOUT.mat'); Vin = load('AMBFCartesianData/CartChirp0d001TO5HzWxVIN.mat'); Voutwx = Vout.cv(4,:); Vinwx = Vin.rv(4,:); Vout = load('AMBFCartesianData/CartChirp0d001TO5HzWyVOUT.mat'); Vin = load('AMBFCartesianData/CartChirp0d001TO5HzWyVIN.mat'); Voutwy = Vout.cv(5,:); Vinwy = Vin.rv(5,:); %% IdentifySystem(Voutx,Vinx,0.0284) %% IdentifySystem(Vouty,Viny,0.0296) IdentifySystem(Voutz,Vinz,0.0221) IdentifySystem(Voutwx,Vinwx,0.0222) IdentifySystem(Voutwy,Vinwy,0.0219) %% s = tf('s'); % tfest Transfer resultm for chirp on 0.01 to 20Hz for 180s simultaneous % X tfest 26.1% match Xtf = tf([2282],[1 72.45 2360]); % X ssest 19.75% match Xest = exp(-0.0231*s) * 37.61/(s + 59.96); % Y tfest 30.86 % match Ytf = 1682/(s^2 + 57.13*s + 1761); % Y ssest 26.4% match Yest = exp(-0.0231*s) * (24.88*s^2 + 1419*s - 207.8)/(s^3 + 79.87*s^2 + 1998*s + 6.701); % Z tfest 27.43% match Ztf = 2205/(s^2 + 67.05*s + 2285); % Z ssest 22.07% match Zest = exp(-0.0231*s) * 41.64/(s + 64.6); % WX tfest 14.69% match Wxtf = 2771/(s^2 + 87.77*s + 2804); % WX ssest 24.13% match Wxest = exp(-0.0231*s)*(244.2*s^6 + 2.66e04*s^5 + 8.088e06*s^4 + 6.18e08*s^3 + 2.995e10*s^2 + 7.436e11*s + 1.128e13)/(s^7 + 464.1*s^6 + 8.301e04*s^5 + 1.517e07*s^4 + 1.422e09*s^3 + 6.897e10*s^2 + 1.793e12*s+ 2.751e13); % WY tfest -0.3697% match Wytf = -1.777/(s^2 + 1.339*s + 0.7451); % WY ssest 23.74% match Wyest = exp(-0.0231*s) * (34.21*s^4 + 1522*s^3 + 5.851e04*s^2 + 1.637e06*s + 8.274e05)/(s^5 + 93.08*s^4 + 3811*s^3 + 1.315e05*s^2 + 2.366e06*s + 1.673e06); %% s = tf('s'); % tfest Transfer resultm for chirp on 0.001 to 5Hz for 60s indiviudally % X tfest -72.16% Xtf = -0.4909/(s^2 + 1.045*s + 1.541e-12); % X ssest 77.93% Xest = 132.8/(s + 145.8); % Y tfest -1.981% Ytf = -6.848e04/(s^2 + 1.716e05*s + 3.164e05); % Y ssest 92.15% Yest = 131.8/(s + 132.4); % Z tfest 92.58% Ztf = 1.973e06/(s^2 + 1.558e04*s + 1.975e06); % Z ssest 92.58% Zest = 127.2/(s + 127.3); % WX tfest 89.39% Wxtf = 2.542e05/(s^2 + 153.1*s + 2.561e05); % WX ssest -489.1% unstable Wxest = exp(-0.0231*s)*(1.326e04*s^6 + 4.967e05*s^5 + 7.575e08*s^4 + 4.319e10*s^3 + 3.464e12*s^2 + 1.253e14*s + 1.506e15)/(s^7 + 2962*s^6 + 4.305e05*s^5 + 1.825e08*s^4 + 2.164e10*s^3 + 1.248e12*s^2 + 6.95e13*s + 1.493e15); % WY tfest 91.04% Wytf = 1.587e04/(s^2 + 230.7*s + 1.584e04); % WY ssest 91.03% Wyest = 80.55/(s + 80.06); %% % Plot out the quality of the fit. Output vs Identified Transfer function % response %Close figure if already open if ishandle(1) close 1 end %Asign input and output u = Vinx'; yreal = Voutx'; data = iddata(yreal,u,dt); figure(1) opt = compareOptions; opt.InitialCondition = 'z'; %discretize compare(data,Xtf,opt)% plot the quality comparison set(findall(gca, 'Type', 'Line'), 'LineWidth', 4) xlabel("Time (s)") subtitle("Identified System Comparison") ylabel('Velocity (m/s)') grid on %% % This function will take input and output joint command data for the galen % carriage joints. It only needs the data for one joint as the % identification was made with the assumption that the galen was a lumped % mass. It uses the tfest and ssest methods from the system identification % toolbox. % % Inputs: % Vout - output data from control response % Vin - input data from control % dt - the estimated sampling time used for control % Outputs: % Gest - the estimated transfer function using the tfest method with 2nd % order guess % Gest2 - the estimated transfer functino using the ssest method function [Gest, Gest2] = IdentifySystem(Vout,Vin,dt) s = tf('s'); u = Vin(1,:)'; yreal = Vout'; data = iddata(yreal,u,dt); Gest = tfest(data,2,0,NaN) close all figure(1) opt = compareOptions; opt.InitialCondition = 'z'; compare(data,Gest,opt) set(findall(gca, 'Type', 'Line'), 'LineWidth', 4) xlabel("Time (s)") subtitle("2nd Order Est with no Zeros") ylabel('Velocity (m/s)') grid on ylim([-0.06 0.06]) % estimate the delay term delay_samples = delayest(data); % Remove delay from output yreal_no_delay = yreal(delay_samples+1:end); % Repackage offset data data_offset = iddata(yreal_no_delay, u(1:end-delay_samples), dt); % Fit data to a state space model of unknown oder Gss = ssest(data_offset, 1:10); % Convert to tf and add in the delay term Gest2 = tf(Gss)*exp(-delay_samples * dt * s) figure(2) opt = compareOptions; opt.InitialCondition = 'z'; compare(data,Gest2,opt) set(findall(gca, 'Type', 'Line'), 'LineWidth', 4) xlabel(["Time (s)"]) subtitle("SS Estimate") ylabel('Velocity (m/s)') grid on ylim([-0.06 0.06]) end