Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Controls Applications Cases #30

Merged
merged 10 commits into from
May 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cable/userDefinedFunctions.m
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
figure()
subplot(2,1,1)
initialLength = norm(cable(1).base.location - cable(1).follower.location );
plot([0 output.cables(1).time(end)], [cable(1).length cable(1).length],'k--',...
plot([0 output.cables(1).time(end)], [cable(1).cableLength cable(1).cableLength],'k--',...
output.cables(1).time, output.cables(1).position(:,3) + initialLength)
ylabel('Displacement [m]');
title('Cable Displacement');
Expand Down
2 changes: 1 addition & 1 deletion Cable/wecSimInputFile.m
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
cable(1) = cableClass('Cable','constraint(2)','constraint(3)');
cable(1).stiffness = 1000000;
cable(1).damping = 100;
cable(1).length = 17.8; % Cable equilibrium length [m]
cable(1).cableLength = 17.8; % Cable equilibrium length [m]
% cable(1).preTension = 5100000; % Cable equilibrium pre-tension [N]
cable(1).quadDrag.cd = [1.4 1.4 1.4 0 0 0];
cable(1).quadDrag.area = [10 10 10 0 0 0];
Binary file added Controls/Declutching/declutch.slx
Binary file not shown.
15 changes: 15 additions & 0 deletions Controls/Declutching/declutching.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
function [Force, tDeclutch, tNormal, vel] = declutching(vel, tDeclutch, tNormal, velPrev, declutchTime, dt, Kp)

% Declutch when velocity is zero and reengage when declutching time is
% reached
if ((diff(sign([vel,velPrev]))~=0 && tDeclutch==0 && tNormal>.2) || (tDeclutch>0 && tDeclutch<declutchTime))
Force = 0;
tDeclutch = tDeclutch + dt;
tNormal = 0;
else
Force = -Kp*vel;
tNormal = tNormal + dt;
tDeclutch = 0;
end

end
11 changes: 11 additions & 0 deletions Controls/Declutching/mcrBuildTimes.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
close all;clear all;clc;
%%
mcr = struct();
mcr.header = ["controller(1).declutching.declutchTime"];
mcr.cases = zeros(9,1);
%%
time = linspace(0,1.2,13);
%%
mcr.cases = time';
%%
save mcrCases mcr
73 changes: 73 additions & 0 deletions Controls/Declutching/optimalTimeCalc.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
% This script identifies the dynamics of the float in the respective wave
% conditions and determines the optimal proportional gain value for a
% passive controller (for regular waves)

close all; clear all; clc;

% Inputs (from wecSimInputFile)
simu = simulationClass();
body(1) = bodyClass('../hydroData/sphere.h5');
waves.height = 1;
waves.period = 3.5;

% Load hydrodynamic data for float from BEM
hydro = readBEMIOH5(body.h5File, 1, body.meanDrift);

% Define wave conditions
H = waves.height;
A = H/2;
T = waves.period;
omega = (1/T)*(2*pi);

% Define excitation force based on wave conditions
ampSpect = zeros(length(hydro.simulation_parameters.w),1);
[~,closestIndOmega] = min(abs(omega-hydro.simulation_parameters.w));
ampSpect(closestIndOmega) = A;
FeRao = squeeze(hydro.hydro_coeffs.excitation.re(3,:))'*simu.rho*simu.gravity + squeeze(hydro.hydro_coeffs.excitation.im(3,:))'*simu.rho*simu.gravity*1j;
Fexc = ampSpect.*FeRao;

% Define the intrinsic mechanical impedance for the device
mass = simu.rho*hydro.properties.volume;
addedMass = squeeze(hydro.hydro_coeffs.added_mass.all(3,3,:))*simu.rho;
radiationDamping = squeeze(hydro.hydro_coeffs.radiation_damping.all(3,3,:)).*squeeze(hydro.simulation_parameters.w')*simu.rho;
hydrostaticStiffness = hydro.hydro_coeffs.linear_restoring_stiffness(3,3)*simu.rho*simu.gravity;
Gi = -((hydro.simulation_parameters.w)'.^2.*(mass+addedMass)) + 1j*hydro.simulation_parameters.w'.*radiationDamping + hydrostaticStiffness;
Zi = Gi./(1j*hydro.simulation_parameters.w');

% Calculate magnitude and phase for bode plot
Mag = 20*log10(abs(Zi));
Phase = (angle(Zi))*(180/pi);

% Determine natural frequency based on the phase of the impedance
[~,closestIndNat] = min(abs(imag(Zi)));
natFreq = hydro.simulation_parameters.w(closestIndNat);
natT = (2*pi)/natFreq;

% Create bode plot for impedance
figure()
subplot(2,1,1)
semilogx((hydro.simulation_parameters.w)/(2*pi),Mag)
xlabel('freq (hz)')
ylabel('mag (dB)')
grid on
xline(natFreq/(2*pi))
xline(1/T,'--')
legend('','Natural Frequency','Wave Frequency','Location','southwest')

subplot(2,1,2)
semilogx((hydro.simulation_parameters.w)/(2*pi),Phase)
xlabel('freq (hz)')
ylabel('phase (deg)')
grid on
xline(natFreq/(2*pi))
xline(1/T,'--')
legend('','Natural Frequency','Wave Frequency','Location','northwest')

% Determine optimal latching time
optDeclutchTime = 0.5*(natT - T)
KpOpt = sqrt(radiationDamping(closestIndOmega)^2 + ((hydrostaticStiffness/omega) - omega*(mass + addedMass(closestIndOmega)))^2)

% Calculate the maximum potential power
P_max = -sum(abs(Fexc).^2./(8*real(Zi)))


50 changes: 50 additions & 0 deletions Controls/Declutching/userDefinedFunctions.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
%Example of user input MATLAB file for post processing
close all

%Plot waves
waves.plotElevation(simu.rampTime);
try
waves.plotSpectrum();
catch
end

%Plot heave response for body 1
output.plotResponse(1,3);

%Plot heave forces for body 1
output.plotForces(1,3);

controllersOutput = controller1_out;
signals = {'force','power'};
for ii = 1:length(controllersOutput)
for jj = 1:length(signals)
controllersOutput(ii).(signals{jj}) = controllersOutput(ii).signals.values(:,(jj-1)*6+1:(jj-1)*6+6);
end
end

% Plot controller power
figure()
plot(controllersOutput.time,controllersOutput.power(:,3))
title('Controller Power')
ylabel('Power (W)')
xlabel('Time (s)')

% Calculate average power for last 10 wave periods
endInd = length(controllersOutput.time);
startTime = controllersOutput.time(end) - 10*waves.period; % select last 10 periods
[~,startInd] = min(abs(controllersOutput.time - startTime));
disp('Controller Power:')
mean(controllersOutput.power(startInd:endInd,3))

% Plot declutching
figure()
yyaxis left
plot(output.bodies.time,output.bodies.velocity(:,3))
hold on
xlabel('Time (s)')
xlim([200 210])
ylabel('Velocity (m/s)')
ylim([-.4 .4])
yyaxis right
plot(output.bodies.time,output.bodies.forceExcitation(:,3)/1000)
ylabel('Excitation Force (kN)')
28 changes: 28 additions & 0 deletions Controls/Declutching/userDefinedFunctionsMCR.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
%% User Defined Functions for MCR run
controllersOutput = controller1_out;
signals = {'force','power'};
for ii = 1:length(controllersOutput)
for jj = 1:length(signals)
controllersOutput(ii).(signals{jj}) = controllersOutput(ii).signals.values(:,(jj-1)*6+1:(jj-1)*6+6);
end
end

endInd = length(controllersOutput.time);
startTime = controllersOutput.time(end) - 10*waves.period; % select last 10 periods
[~,startInd] = min(abs(controllersOutput.time - startTime));

mcr.meanPower(imcr) = mean(controllersOutput.power(startInd:endInd,3));
mcr.meanForce(imcr) = mean(controllersOutput.force(startInd:endInd,3));

mcr.maxPower(imcr) = max(abs(controllersOutput.power(startInd:endInd,3)));
mcr.maxForce(imcr) = max(abs(controllersOutput.force(startInd:endInd,3)));

if imcr == length(mcr.cases)
figure()
plot(mcr.cases,mcr.meanPower)
title('Mean Power vs. Declutching Time')
xlabel('Declutching Time (s)')
ylabel('Mean Power (W)')
xline(.4166, '--')
legend('','Theoretical Optimal')
end
37 changes: 37 additions & 0 deletions Controls/Declutching/wecSimInputFile.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
%% Simulation Data
simu = simulationClass(); % Initialize Simulation Class
simu.simMechanicsFile = 'declutch.slx'; % Specify Simulink Model File
simu.mode = 'normal'; % Specify Simulation Mode ('normal','accelerator','rapid-accelerator')
simu.explorer = 'on'; % Turn SimMechanics Explorer (on/off)
simu.startTime = 0; % Simulation Start Time [s]
simu.rampTime = 100; % Wave Ramp Time [s]
simu.endTime = 400; % Simulation End Time [s]
simu.solver = 'ode4'; % simu.solver = 'ode4' for fixed step & simu.solver = 'ode45' for variable step
simu.dt = 0.01; % Simulation time-step [s]
simu.mcrMatFile = 'mcrCases.mat';

%% Wave Information

% % Regular Waves
waves = waveClass('regular'); % Initialize Wave Class and Specify Type
waves.height = 2.5; % Wave Height [m]
waves.period = 9.6664; % Wave Period [s]

%% Body Data
% Sphere
body(1) = bodyClass('../hydroData/sphere.h5'); % Create the body(1) Variable
body(1).geometryFile = '../geometry/sphere.stl'; % Location of Geomtry File
body(1).mass = 'equilibrium'; % Body Mass
body(1).inertia = [20907301 21306090.66 37085481.11]; % Moment of Inertia [kg*m^2]

%% PTO and Constraint Parameters

% Translational PTO
pto(1) = ptoClass('PTO1'); % Initialize PTO Class for PTO1
pto(1).stiffness = 0; % PTO Stiffness [N/m]
pto(1).damping = 0; % PTO Damping [N/(m/s)]
pto(1).location = [0 0 0]; % PTO Location [m]

% Declutching Controller
controller(1).declutching.declutchTime = 0.8;
controller(1).declutching.Kp = 2.3202e5;
Binary file added Controls/Latching/latchTime.slx
Binary file not shown.
14 changes: 14 additions & 0 deletions Controls/Latching/latchingTime.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
function [Force, tLatch, tNormal, vel] = latchingTime(vel, tLatch, tNormal, velPrev, latchTime, dt, Kp, forceCoeff)

% Latch when velocity is zero and release when latching time is reached
if ((diff(sign([vel,velPrev]))~=0 && tLatch==0 && tNormal>.2) || (tLatch>0 && tLatch<latchTime))
Force = -forceCoeff*vel; %-forceOnBody;
tLatch = tLatch + dt;
tNormal = 0;
else
Force = -Kp*vel;
tNormal = tNormal + dt;
tLatch = 0;
end

end
11 changes: 11 additions & 0 deletions Controls/Latching/mcrBuildTimes.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
close all;clear all;clc;
%%
mcr = struct();
mcr.header = ["controller(1).latching.latchTime"];
mcr.cases = zeros(9,1);
%%
time = linspace(2.0666,2.9666,25);
%%
mcr.cases = time';
%%
save mcrCases mcr
74 changes: 74 additions & 0 deletions Controls/Latching/optimalTimeCalc.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
% This script identifies the dynamics of the float in the respective wave
% conditions and determines the optimal proportional gain value for a
% passive controller (for regular waves)

close all; clear all; clc;

% Inputs (from wecSimInputFile)
simu = simulationClass();
body(1) = bodyClass('../hydroData/sphere.h5');
waves.height = 2.5;
waves.period = 9.6664;

% Load hydrodynamic data for float from BEM
hydro = readBEMIOH5(body.h5File, 1, body.meanDrift);

% Define wave conditions
H = waves.height;
A = H/2;
T = waves.period;
omega = (1/T)*(2*pi);

% Define excitation force based on wave conditions
ampSpect = zeros(length(hydro.simulation_parameters.w),1);
[~,closestIndOmega] = min(abs(omega-hydro.simulation_parameters.w));
ampSpect(closestIndOmega) = A;
FeRao = squeeze(hydro.hydro_coeffs.excitation.re(3,:))'*simu.rho*simu.gravity + squeeze(hydro.hydro_coeffs.excitation.im(3,:))'*simu.rho*simu.gravity*1j;
Fexc = ampSpect.*FeRao;

% Define the intrinsic mechanical impedance for the device
mass = simu.rho*hydro.properties.volume;
addedMass = squeeze(hydro.hydro_coeffs.added_mass.all(3,3,:))*simu.rho;
radiationDamping = squeeze(hydro.hydro_coeffs.radiation_damping.all(3,3,:)).*squeeze(hydro.simulation_parameters.w')*simu.rho;
hydrostaticStiffness = hydro.hydro_coeffs.linear_restoring_stiffness(3,3)*simu.rho*simu.gravity;
Gi = -((hydro.simulation_parameters.w)'.^2.*(mass+addedMass)) + 1j*hydro.simulation_parameters.w'.*radiationDamping + hydrostaticStiffness;
Zi = Gi./(1j*hydro.simulation_parameters.w');

% Calculate magnitude and phase for bode plot
Mag = 20*log10(abs(Zi));
Phase = (angle(Zi))*(180/pi);

% Determine natural frequency based on the phase of the impedance
[~,closestIndNat] = min(abs(imag(Zi)));
natFreq = hydro.simulation_parameters.w(closestIndNat);
natT = (2*pi)/natFreq;

% Create bode plot for impedance
figure()
subplot(2,1,1)
semilogx((hydro.simulation_parameters.w)/(2*pi),Mag)
xlabel('freq (hz)')
ylabel('mag (dB)')
grid on
xline(natFreq/(2*pi))
xline(1/T,'--')
legend('','Natural Frequency','Wave Frequency','Location','southwest')

subplot(2,1,2)
semilogx((hydro.simulation_parameters.w)/(2*pi),Phase)
xlabel('freq (hz)')
ylabel('phase (deg)')
grid on
xline(natFreq/(2*pi))
xline(1/T,'--')
legend('','Natural Frequency','Wave Frequency','Location','northwest')

% Determine optimal latching time
optLatchTime = 0.5*(T - natT)
KpOpt = radiationDamping(closestIndOmega)
force = 80*(mass+addedMass(closestIndOmega))

% Calculate the maximum potential power
P_max = -sum(abs(Fexc).^2./(8*real(Zi)))


50 changes: 50 additions & 0 deletions Controls/Latching/userDefinedFunctions.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
%Example of user input MATLAB file for post processing
close all

%Plot waves
waves.plotElevation(simu.rampTime);
try
waves.plotSpectrum();
catch
end

%Plot heave response for body 1
output.plotResponse(1,3);

%Plot heave forces for body 1
output.plotForces(1,3);

controllersOutput = controller1_out;
signals = {'force','power'};
for ii = 1:length(controllersOutput)
for jj = 1:length(signals)
controllersOutput(ii).(signals{jj}) = controllersOutput(ii).signals.values(:,(jj-1)*6+1:(jj-1)*6+6);
end
end

% Plot controller power
figure()
plot(controllersOutput.time,controllersOutput.power(:,3))
title('Controller Power')
ylabel('Power (W)')
xlabel('Time (s)')

% Calculate average power for last 10 wave periods
endInd = length(controllersOutput.time);
startTime = controllersOutput.time(end) - 10*waves.period; % select last 10 periods
[~,startInd] = min(abs(controllersOutput.time - startTime));
disp('Controller Power:')
mean( mean(controllersOutput.power(startInd:endInd,3)))

% Plot latching
figure()
yyaxis left
plot(output.bodies.time,output.bodies.velocity(:,3))
xlabel('Time (s)')
xlim([200 220])
ylabel('Velocity (m/s)')
ylim([-10 10])
hold on
yyaxis right
plot(output.bodies.time,output.bodies.forceExcitation(:,3)/1000)
ylabel('Excitation Force (kN)')
Loading