From 187eaa07c04223219d1c8840d07e338943c0184c Mon Sep 17 00:00:00 2001
From: Mauco03 <marco.gaibotti@skywarder.eu>
Date: Tue, 27 Feb 2024 19:11:37 +0100
Subject: [PATCH] [tests][benchmark] Added test folder

---
 tests/Test.m           |  18 ++
 tests/ascent.m         | 378 +++++++++++++++++++++++++++++++++++++++++
 tests/speedBenchmark.m |  35 +++-
 3 files changed, 430 insertions(+), 1 deletion(-)
 create mode 100644 tests/Test.m
 create mode 100644 tests/ascent.m

diff --git a/tests/Test.m b/tests/Test.m
new file mode 100644
index 0000000..fb2be57
--- /dev/null
+++ b/tests/Test.m
@@ -0,0 +1,18 @@
+classdef Test < handle
+    %TEST Summary of this class goes here
+    %   Detailed explanation goes here
+
+    properties
+        a   double
+        b   double
+        c   double
+    end
+
+    methods
+        function obj = Test(a, b, c)
+            obj.a = a;
+            obj.b = b;
+            obj.c = c;
+        end
+    end
+end
\ No newline at end of file
diff --git a/tests/ascent.m b/tests/ascent.m
new file mode 100644
index 0000000..77219ad
--- /dev/null
+++ b/tests/ascent.m
@@ -0,0 +1,378 @@
+function [dY, parout] = ascent(t, Y, settings)
+% geometry, motor, environment
+
+%{
+ascent - ode function of the 6DOF Rigid Rocket Model
+
+INPUTS:
+- t,       double [1, 1] integration time [s];
+- Y,       double [13, 1] state vector [ x y z | u v w | p q r | q0 q1 q2 q3]:
+
+                                * (x y z), NED{north, east, down} horizontal frame;
+                                * (u v w), body frame velocities;
+                                * (p q r), body frame angular rates;
+                                * (q0 q1 q2 q3), attitude unit quaternion;
+- settings, struct(motor, CoeffsE, CoeffsF, para, ode, stoch, prob, wind), rocket data structure;
+
+OUTPUTS:
+- dY,      double [16, 1] state derivatives
+- parout,  struct, interesting fligth quantities structure (aerodyn coefficients, forces and so on..)
+
+
+CALLED FUNCTIONS: windMatlabGenerator, windInputGenerator, quatToDcm, interpCoeffs
+
+NOTE: To get the NED velocities the body-frame must be multiplied by the
+conjugated of the current attitude quaternion
+E.G.  quatrotate(quatconj(Y(:,10:13)),Y(:,4:6))
+
+REVISIONS:
+-#0 31/12/2014, Release, Ruben Di Battista
+
+-#1 16/04/2016, Second version, Francesco Colombi
+
+-#2 01/01/2021, Third version, Adriano Filippo Inno
+
+Copyright © 2021, Skyward Experimental Rocketry, AFD department
+All rights reserved
+
+SPDX-License-Identifier: GPL-3.0-or-later
+
+%}
+
+
+% recalling the states
+% x = Y(1);
+% y = Y(2);
+z = Y(3);
+u = Y(4);
+v = Y(5);
+w = Y(6);
+p = Y(7);
+q = Y(8);
+r = Y(9);
+q0 = Y(10);
+q1 = Y(11);
+q2 = Y(12);
+q3 = Y(13);
+
+%% CONSTANTS
+S = settings.S;                         % [m^2]   cross surface
+C = settings.C;                         % [m]     caliber
+g = settings.g0/(1 + (-z*1e-3/6371))^2; % [N/kg]  module of gravitational field
+tb = settings.tb;                       % [s]     Burning Time
+local = settings.Local;                 % vector containing inputs for atmosphereData
+
+if settings.stoch.N > 1
+    OMEGA = settings.stoch.OMEGA;
+    uncert = settings.stoch.uncert;
+    Day = settings.stoch.Day;
+    Hour = settings.stoch.Hour;
+    uw = settings.stoch.uw; vw = settings.stoch.vw; ww = settings.stoch.ww;
+else
+    OMEGA = settings.OMEGA;
+    uncert = [0, 0];
+
+    if not(settings.wind.input) && not(settings.wind.model)
+        uw = settings.constWind(1); vw = settings.constWind(2); ww = settings.constWind(3);
+    end
+end
+
+%% INERTIAS
+
+if t < tb 
+    if t < settings.timeEngineCut
+        I = interpLinear(settings.motor.expTime, settings.I, t);
+        Idot = interpLinear(settings.motor.expTime, settings.Idot, t);
+    else
+        I = settings.IengineCut;
+        Idot = zeros(3, 1);
+    end
+else
+    if settings.timeEngineCut < tb
+        I = settings.IengineCut;
+    else
+        I = settings.I(:, end);
+    end
+    Idot = zeros(3, 1);
+end
+Ixx = I(1); Iyy = I(2); Izz = I(3);
+Ixxdot = Idot(1); Iyydot = Idot(2); Izzdot = Idot(3);
+
+
+
+%% QUATERION ATTITUDE
+Q = [q0 q1 q2 q3];
+Q = Q/norm(Q);
+
+%% ADDING WIND (supposed to be added in NED axes);
+if settings.wind.model
+
+    if settings.stoch.N > 1
+        [uw, vw, ww] = windMatlabGenerator(settings, z, t, Hour, Day);
+    else
+        [uw, vw, ww] = windMatlabGenerator(settings, z, t);
+    end
+
+elseif settings.wind.input
+    [uw, vw, ww] = windInputGenerator(settings, z, uncert);
+elseif  settings.wind.variable
+
+    [uw, vw, ww] = windVariableGenerator(z, settings.stoch);
+end
+
+dcm = quatToDcm(Q);
+wind = dcm*[uw; vw; ww];
+
+% Relative velocities (plus wind);
+ur = u - wind(1);
+vr = v - wind(2);
+wr = w - wind(3);
+
+% Body to Inertial velocities
+Vels = dcm'*[u; v; w];
+V_norm = norm([ur vr wr]);
+
+%% ATMOSPHERE DATA
+if -z < 0     % z is directed as the gravity vector
+    z = 0;
+end
+
+absoluteAltitude = -z + settings.z0;
+[~, a, P, rho] = atmosphereData(absoluteAltitude, g, local);
+
+M = V_norm/a;
+M_value = M;
+
+%% TIME-DEPENDENTS VARIABLES
+if t < tb
+    
+    if t < settings.timeEngineCut
+        m = interpLinear(settings.motor.expTime, settings.mTotalTime, t);
+        T = interpLinear(settings.motor.expTime, settings.motor.expThrust, t);
+        Pe = interpLinear(settings.motor.expTime, settings.motor.Pe, t);
+        T = T + settings.motor.Ae*(Pe - P);
+    else
+        m = settings.expMengineCut + settings.ms;
+        T = 0;
+    end
+
+else     % for t >= tb the fligth condition is the empty one(no interpolation needed)
+    
+    if settings.timeEngineCut < tb
+        m = settings.ms + settings.expMengineCut;
+    else
+        m = settings.ms + settings.motor.expM(end);
+    end
+
+    T = 0;
+end
+
+%% AERODYNAMICS ANGLES
+if not(abs(ur) < 1e-9 || V_norm < 1e-9)
+    alpha = atan(wr/ur);
+    beta = atan(vr/ur);                         % beta = asin(vr/V_norm) is the classical notation, Datcom uses this one though.
+    % alpha_tot = atan(sqrt(wr^2 + vr^2)/ur);   % datcom 97' definition
+else
+    alpha = 0;
+    beta = 0;
+end
+
+alpha_value = alpha;
+beta_value = beta;
+
+%% CHOSING THE EMPTY CONDITION VALUE
+% interpolation of the coefficients with the value in the nearest condition of the Coeffs matrix
+
+if t >= settings.tControl && M <= settings.MachControl
+    c = settings.control;
+else
+    c = 1;
+end
+
+%% INTERPOLATE AERODYNAMIC COEFFICIENTS:
+
+[coeffsValues, angle0] = interpCoeffs(t, alpha, M, beta, absoluteAltitude,...
+    c, settings);
+
+% Retrieve Coefficients
+
+
+CA = coeffsValues(1); CYB = coeffsValues(2); CY0 = coeffsValues(3);
+CNA = coeffsValues(4); CN0 = coeffsValues(5); Cl = coeffsValues(6);
+Clp = coeffsValues(7); Cma = coeffsValues(8); Cm0 = coeffsValues(9);
+Cmad = coeffsValues(10); Cmq = coeffsValues(11); Cnb = coeffsValues(12);
+Cn0 = coeffsValues(13); Cnr = coeffsValues(14); Cnp = coeffsValues(15);
+%--------------------------------------------
+%Clb = coeffsValues(16);
+%--------------------------------------------
+
+% XCP_value = coeffsValues(16);
+
+% compute CN,CY,Cm,Cn (linearized with respect to alpha and beta):
+alpha0 = angle0(1); beta0 = angle0(2);
+
+CN = (CN0 + CNA*(alpha - alpha0));
+CY = (CY0 + CYB*(beta - beta0));
+Cm = (Cm0 + Cma*(alpha - alpha0));
+Cn = (Cn0 + Cnb*(beta - beta0));
+
+% XCPlon = Cm/CN;
+
+if abs(alpha) <= pi/180
+    XCPlon = Cma/CNA;
+else
+    XCPlon = Cm/CN; 
+end
+ 
+% XCPlat = Cn/CY;
+
+
+if abs(beta) <= pi/180
+    XCPlat = Cnb/CYB; 
+else
+    XCPlat = Cn/CY; 
+end
+
+% if Cn == 0 && CY == 0
+%     XCPlat = -5;
+% end
+
+
+
+%%
+if -z < settings.lrampa*sin(OMEGA)      % No torque on the launchpad
+
+    Fg = m*g*sin(OMEGA);                % [N] force due to the gravity
+    X = 0.5*rho*V_norm^2*S*CA;
+    F = -Fg +T -X;
+    du = F/m;
+
+    dv = 0;
+    dw = 0;
+    dp = 0;
+    dq = 0;
+    dr = 0;
+
+    alpha_value = NaN;
+    beta_value = NaN;
+    Y = 0;
+    Z = 0;
+    XCPlon = NaN;
+    XCPlat = NaN;
+
+    if T < Fg                           % No velocity untill T = Fg
+        du = 0;
+    end
+    
+    XCPtot = NaN; 
+else
+%% FORCES
+    % first computed in the body-frame reference system
+    qdyn = 0.5*rho*V_norm^2;            % [Pa] dynamics pressure
+    qdynL_V = 0.5*rho*V_norm*S*C;
+
+    X = qdyn*S*CA;                      % [N] x-body component of the aerodynamics force
+    Y = qdyn*S*CY;                      % [N] y-body component of the aerodynamics force
+    Z = qdyn*S*CN;                      % [N] z-body component of the aerodynamics force
+    Fg = dcm*[0; 0; m*g];               % [N] force due to the gravity in body frame
+    F = Fg + [-X+T, Y, -Z]';             % [N] total forces vector
+    
+    %-----------------------------------------------------
+    %F = Fg + [-X+T*cos(chi), Y+T*sin(chi), -Z]';             % [N] total forces vector
+    %-----------------------------------------------------
+
+%% STATE DERIVATIVES
+    % velocity
+    du = F(1)/m - q*w + r*v;
+    dv = F(2)/m - r*u + p*w;
+    dw = F(3)/m - p*v + q*u;
+
+    % Rotation
+    dp = (Iyy - Izz)/Ixx*q*r + qdynL_V/Ixx*(V_norm*Cl+Clp*p*C/2) - Ixxdot*p/Ixx;
+    dq = (Izz - Ixx)/Iyy*p*r + qdynL_V/Iyy*(V_norm*Cm + (Cmad+Cmq)*q*C/2)...
+        - Iyydot*q/Iyy;
+    dr = (Ixx - Iyy)/Izz*p*q + qdynL_V/Izz*(V_norm*Cn + (Cnr*r+Cnp*p)*C/2)...
+        - Izzdot*r/Izz;
+
+    % Compute the aerodynamici roll angle 
+    [~, phi] = getAlphaPhi(alpha, beta); 
+        
+    % Aerodynamic-force coefficient in the alpha-total plane
+    CFaTot = sin(phi)*CY + cos(phi)*(-CN);      
+    % Aerodynanic-moment coefficient in the alpha-total plane
+    CMaTot = cos(phi)*Cm - sin(phi)*Cn;
+    if CFaTot ~= 0
+        XCPtot = CMaTot/CFaTot; 
+    else
+        XCPtot = XCPlon; 
+    end
+end
+% Quaternions
+OM = [ 0 -p -q -r  ;
+       p  0  r -q  ;
+       q -r  0  p  ;
+       r  q -p  0 ];
+
+dQQ = 1/2*OM*Q';
+
+%% FINAL DERIVATIVE STATE ASSEMBLING
+dY(1:3) = Vels;
+dY(4) = du;
+dY(5) = dv;
+dY(6) = dw;
+dY(7) = dp;
+dY(8) = dq;
+dY(9) = dr;
+dY(10:13) = dQQ;
+dY = dY';
+
+%% SAVING THE QUANTITIES FOR THE PLOTS
+
+if nargout == 2
+    parout.integration.t = t;
+    
+    parout.interp.M = M_value;
+    parout.interp.alpha = alpha_value;
+    parout.interp.beta = beta_value;
+    parout.interp.alt = -z;
+    parout.interp.mass = m;
+    parout.interp.inertias = [Ixx, Iyy, Izz]; 
+
+    parout.wind.NED_wind = [uw, vw, ww];
+    parout.wind.body_wind = wind;
+    
+    parout.rotations.dcm = dcm;
+    
+    parout.velocities = Vels;
+    
+    parout.forces.AeroDyn_Forces = [X, Y, Z];
+    parout.forces.T = T;
+    
+    parout.air.rho = rho;
+    parout.air.P = P;
+    
+    parout.accelerations.body_acc = [du, dv, dw];
+    parout.accelerations.ang_acc = [dp, dq, dr];
+    
+    parout.coeff.CA = CA;
+    parout.coeff.CYB = CYB;
+    parout.coeff.CNA = CNA;
+    parout.coeff.Cl = Cl;
+    parout.coeff.Clp = Clp;
+    %--------------------------------------------
+    %parout.coeff.Clb = Clb;
+    %--------------------------------------------
+    parout.coeff.Cma = Cma;
+    parout.coeff.Cmad = Cmad;
+    parout.coeff.Cmq = Cmq;
+    parout.coeff.Cnb = Cnb;
+    parout.coeff.Cnr = Cnr;
+    parout.coeff.Cnp = Cnp;
+    parout.coeff.XCPlon = XCPlon;
+    parout.coeff.XCPlat = XCPlat;
+
+
+    parout.coeff.XCPtot = XCPtot; 
+
+
+end
\ No newline at end of file
diff --git a/tests/speedBenchmark.m b/tests/speedBenchmark.m
index 5c2c39e..1de77fa 100644
--- a/tests/speedBenchmark.m
+++ b/tests/speedBenchmark.m
@@ -1,5 +1,35 @@
 clear; clc; close all;
 
+%% Low overhead
+
+testClass = Test(1, 2, 3);
+testStruct = struct;
+
+testStruct.a = 1;
+testStruct.b = 2;
+testStruct.c = 3;
+
+len = 3*10000;
+arr1 = zeros(1, len);
+arr2 = zeros(1, len);
+
+fields = fieldnames(testClass);
+
+tic  
+for i = 1:len
+    arr1(i) = testStruct.(fields{mod(i,3) + 1});
+end
+fprintf('readTime, struct: %f s\n', toc);
+
+tic  
+for i = 1:len
+    arr2(i) = testClass.(fields{mod(i,3) + 1});
+end
+fprintf('readTime, class: %f s\n', toc);
+
+fprintf('\n=======================\n\n');
+
+%% High overhead
 ms = Mission(true);
 
 cl = Motor(ms);
@@ -29,4 +59,7 @@ tic
 for i = 1:len
     d(i) = st.xCg(i);
 end
-fprintf('elementWiseAssignment, struct: %f s\n', toc);
\ No newline at end of file
+fprintf('elementWiseAssignment, struct: %f s\n', toc);
+
+%% Integration test
+
-- 
GitLab