From f3f141680333ec859339788f0ac2c7512cc230ed Mon Sep 17 00:00:00 2001
From: Stefano Belletti <stefano.belletti@skywarder.eu>
Date: Fri, 17 Jan 2025 11:57:14 +0100
Subject: [PATCH] New .update function for all sensors, SensorFault<Sensor1D

---
 commonFunctions/sensors/Sensor1D.m            |   8 +-
 commonFunctions/sensors/SensorFault.m         | 254 +++---------------
 .../initSensors2024_Lyra_Portugal_October.m   |  18 +-
 3 files changed, 52 insertions(+), 228 deletions(-)

diff --git a/commonFunctions/sensors/Sensor1D.m b/commonFunctions/sensors/Sensor1D.m
index 5b4d509..8470de0 100644
--- a/commonFunctions/sensors/Sensor1D.m
+++ b/commonFunctions/sensors/Sensor1D.m
@@ -87,10 +87,10 @@ classdef Sensor1D < handle
                 if found
                     obj.noiseType = vect(ii).noise_type;
                     
-                    if isa(obj,"Sensor1D") || isa(obj,"SensorFault")
+                    if strcmp("Sensor1D", class(obj)) || strcmp("SensorFault", class(obj))
                         obj.noiseDataTrack1 = vect(ii).track1;
                         obj.noiseFactor = vect(ii).factor;
-                    elseif isa(obj,"Sensor3D") || isa(obj,"SensorGPS")
+                    elseif strcmp("Sensor3D", class(obj)) || strcmp("SensorGPS", class(obj))
                         obj.noiseDataTrack1 = vect(ii).track1;
                         obj.noiseDataTrack2 = vect(ii).track2;
                         obj.noiseDataTrack3 = vect(ii).track3;
@@ -99,9 +99,9 @@ classdef Sensor1D < handle
                         error("Sensor not defined")
                     end
                 else
-                    if isa(obj,"Sensor1D") || isa(obj,"SensorFault")
+                    if strcmp("Sensor1D", class(obj)) || strcmp("SensorFault", class(obj))
                         obj.noiseDataTrack1 = [];
-                    elseif isa(obj,"Sensor3D") || isa(obj,"SensorGPS")
+                    elseif strcmp("Sensor3D", class(obj)) || strcmp("SensorGPS", class(obj))
                         obj.noiseDataTrack1 = [];
                         obj.noiseDataTrack2 = [];
                         obj.noiseDataTrack3 = [];
diff --git a/commonFunctions/sensors/SensorFault.m b/commonFunctions/sensors/SensorFault.m
index c201e86..6c41382 100644
--- a/commonFunctions/sensors/SensorFault.m
+++ b/commonFunctions/sensors/SensorFault.m
@@ -1,46 +1,22 @@
-classdef SensorFault < handle
-    
-    % Author: Jan Hammelman
-    % Skyward Experimental Rocketry | ELC-SCS Dept | electronics@skywarder.eu
-    % email: jan.hammelmann@skywarder.eu,alessandro.delduca@skywarder.eu
-    % Release date: 01/03/2021
-    
-    %SENSOR Super call for all sensor
-    %   Inherit from handle to have state variables which can be changed
-    %   inside a method
-    % update: Alessandro Donadi, 31/08/2023
-    %NOTE ON THE UPDATE:
-    %   Added fault simulation capabilities from the faliure simulator made
-    %   by Angelo G. Gaillet and released on 31/07/2022
-    properties (Access='public')
-        minMeasurementRange; % Max limit of sensor
-        maxMeasurementRange; % Min limit of sensor
-        
-        bit; % number of bits for the sensor ( if available)
-        resolution; % resolution of the sensor
-        
-        % noises
-        noiseType;                              % White (default) or Pink
-        noiseDataTrack1;
-        noiseFactor;
-        noiseVariance; % Varianze for the gaussian white noise
-        
-        offset; % Offset in all directions
-        
-        tempOffset; % Coefficent for temperature depending offset
-        
-        dt; % Sampling time
-        
-        error2dOffset; % first column: inputArg, second column: relativeArg, third column: error
+classdef SensorFault < Sensor1D
+    
+    % Author: Stefano Belletti, Samuel Flore
+    % Skyward Experimental Rocketry | AVN - GNC
+    % email: stefano.belletti@skywarder.eu
+    % Release date: 18/11/2024
+    % 
+    % Sensor class for SensorFault
+    % 
+    % Creating a new sensor: [obj] = Sensor1D()
 
+    properties (Access='public')
         fault_time; % if set to -1 it will be randomly chosen between a min and a max time in seconds
 
         max_fault_time; %upper bound of the time window where the fault can occur in case it's randomly chosen
 
         min_fault_time; %lower bound of the time window where the fault can occur in case it's randomly chosen
-    end
 
-    properties (Access = public) %attributes used for fault simulation
+        % attributes used for fault simulation
         failureType;
         fault_offset;
         lambda;
@@ -231,191 +207,33 @@ classdef SensorFault < handle
     
     
     methods (Access='protected')
-        function outputArg = saturation(obj,inputArg)
-            %SATURATION Includes saturation to the sensor model
-            %   inputArg is limited to minMeasurementRange at the lower end and maxMeasurementRange at the upper end
-            %
-            %  Necessary properties:
-            %  minMeasurementRange: Max limit of sensor
-            %  maxMeasurementRange: Min limit of sensor
-            %
-            %  Inputs:
-            %  inputArg: sensor data
-            %  
-            %  Outputs:
-            %  outputArg: sensor data with saturation
-            
-            % checks if sensor data is higher than max possible value
-            if (~isempty(obj.maxMeasurementRange))
-                inputArg(inputArg>obj.maxMeasurementRange)=obj.maxMeasurementRange;
-            end
-            
-            % checks if sensor data is lower than min possible value
-            if (~isempty(obj.minMeasurementRange))
-                inputArg(inputArg<obj.minMeasurementRange)=obj.minMeasurementRange;
-            end
-            
-            outputArg = inputArg;
-        end
-        
-        
-        function outputArg = quantization(obj,inputArg)
-            %QUATIZATION Quantize the sensor data
-            %   Quantizes the signal with the resolution properie of the object
-            %
-            %  Necessary properties:
-            %  resolution: resolution of the sensor
-            %
-            %  Inputs:
-            %  inputArg: sensor data
-            %  
-            %  Outputs:
-            %  outputArg: quantized sensor data
-            
-            if (~isempty(obj.resolution))
-                inputArg = obj.resolution*round(inputArg/obj.resolution);
-            end
-            outputArg = inputArg;
-        end
-        
-        
-        function outputArg = addNoise(obj,inputArg,t)
-            %WHITE_NOISE Includes gaussian white noise to the sensor data
-            %   Adds gaussian white noise with variance noiseVariance
-            %
-            %  Necessary properties:
-            %  noiseVariance: Varianze for the gaussian white noise
-            %
-            %  Inputs:
-            %  inputArg: sensor data
-            %  
-            %  Outputs:
-            %  outputArg: sensor data with white noise
-            
-            % if (~isempty(obj.noiseVariance))
-            %     %inputArg=inputArg+ones(size(inputArg)).*sqrt(obj.noiseVariance).*randn(1,1);,
-            %     inputArg=inputArg+sqrt(obj.noiseVariance).*randn(size(inputArg));
-            % end
-            % outputArg = inputArg;
-
-            if ~isempty(obj.noiseVariance)              % check for old results
-                inputArg = inputArg + sqrt(obj.noiseVariance).*randn(length(inputArg),1);
-            elseif ~isempty(obj.noiseDataTrack1)    
-                if strcmp(obj.noiseType, "white")
-                    inputArg = inputArg + sqrt(obj.noiseDataTrack1*obj.noiseFactor).*randn(length(inputArg),1);
-                elseif strcmp(obj.noiseType, "pink")
-                    for ii = 1:length(obj.noiseDataTrack1.peaks_vect_f)
-                        inputArg = inputArg + obj.noiseDataTrack1.peaks_vect_val(ii)*obj.noiseFactor*sin(2*pi*obj.noiseDataTrack1.peaks_vect_f(ii)*t + randn(1));
-                    end
-                    inputArg = inputArg + sqrt(obj.noiseDataTrack1.variance*obj.noiseFactor).*randn(length(inputArg),1);
-                else
-                    error("This noise is not defined")
-                end
-            end
-
-            outputArg = inputArg;
-        end
-                
-        
-        function outputArg = addOffset(obj,inputArg)
-            %ADD_OFFSET Adds an offset to the signal
-            %   adds the propertie offset to the input signal
-            %
-            %  Necessary properties:
-            %  offset: Offset in all directions
-            %
-            %  Inputs:
-            %  inputArg: sensor data
-            %  
-            %  Outputs:
-            %  outputArg: sensor data plus offset
-            
-            if (~isempty(obj.offset))
-                inputArg=inputArg+ones(size(inputArg)).*obj.offset;
-            end
-            outputArg = inputArg;
-        end
-        
-        
-        function outputArg = addTempOffset(obj,inputArg,temp)
-            %ADD_Temp_OFFSET Adds an temperature dependen offset to the signal
-            %   adds the propertie tempOffset multiplied by the temperature input temp to the input signal
-            %
-            %  Necessary properties:
-            %  tempOffset: Coefficent for temperature depending offset
-            %
-            %  Inputs:
-            %  inputArg: sensor data
-            %  temp: temperature of the sensor
-            %  
-            %  Outputs:
-            %  outputArg: sensor data plus temerature depending offset
-            
-            if (~isempty(obj.tempOffset))
-                inputArg=inputArg+ones(size(inputArg)).*temp*obj.tempOffset;
-            end
-            outputArg = inputArg;
-        end
-        
-        
-        function outputArg = add2DOffset(obj,inputArg,temp)
-            %ADD_2D_OFFSET Adds a offset that depends on the inputArg and temp
-            %  The offset is linear interpolated with the data in matrice error2dOffset
-            %
-            %  Necessary properties:
-            %  error2dOffset: data for offset with first column: inputArg, second column: relativeArg, third column: error
-            %
-            %  Inputs:
-            %  inputArg: sensor data
-            %  temp: temperature of the sensor
-            %  
-            %  Outputs:
-            %  outputArg: sensor data plus 2D depending offset
-            
-            if (~isempty(obj.error2dOffset))
-                inputArg=inputArg+...
-                    griddata(obj.error2dOffset(:,1),obj.error2dOffset(:,2),obj.error2dOffset(:,3),inputArg,temp);
-            end
-            outputArg = inputArg;
-        end
-        
         function obj = reset(obj) %method
-                obj.failureType = 'None';
-                obj.fault_offset = 0;
-                obj.lambda = 0;
-                obj.sigmaDeg = 0;
-                obj.sigmaIS = 0;
-                obj.tError = 0;
-                obj.gain = 1;
-                obj.value = 0;
-                obj.likelihoodFS = 0;
-                obj.likelihoodIS = 0;
-                obj.alsoNegSpikes = false;
-                obj.severity = 0;
-                obj.randomSpikeAmpl = false;
-                obj.satMax = inf;
-                obj.satMin = -inf;
-                obj.settings.saturateFlag = false;
-                obj.settings.bias = false;
-                obj.settings.drift = false;
-                obj.settings.degradation = false;
-                obj.settings.freezing = false;
-                obj.settings.calerr = false;
-                obj.settings.fs = false;
-                obj.settings.is = false;
-    
-                obj.frozenValue = nan;
-            end
+            obj.failureType = 'None';
+            obj.fault_offset = 0;
+            obj.lambda = 0;
+            obj.sigmaDeg = 0;
+            obj.sigmaIS = 0;
+            obj.tError = 0;
+            obj.gain = 1;
+            obj.value = 0;
+            obj.likelihoodFS = 0;
+            obj.likelihoodIS = 0;
+            obj.alsoNegSpikes = false;
+            obj.severity = 0;
+            obj.randomSpikeAmpl = false;
+            obj.satMax = inf;
+            obj.satMin = -inf;
+            obj.settings.saturateFlag = false;
+            obj.settings.bias = false;
+            obj.settings.drift = false;
+            obj.settings.degradation = false;
+            obj.settings.freezing = false;
+            obj.settings.calerr = false;
+            obj.settings.fs = false;
+            obj.settings.is = false;
 
-    
-    end
-    
-    methods (Access = private)
-    
-        function data = saturate(data)
-            data = max(obj.satMin, min(obj.satMax, data));
+            obj.frozenValue = nan;
         end
-    
     end
 end
 
diff --git a/data/2024_Lyra_Portugal_October/initSensors2024_Lyra_Portugal_October.m b/data/2024_Lyra_Portugal_October/initSensors2024_Lyra_Portugal_October.m
index 3ba0538..8de0bb4 100644
--- a/data/2024_Lyra_Portugal_October/initSensors2024_Lyra_Portugal_October.m
+++ b/data/2024_Lyra_Portugal_October/initSensors2024_Lyra_Portugal_October.m
@@ -13,9 +13,9 @@ sensorSettings.barometer1 = SensorFault();
 sensorSettings.barometer1.maxMeasurementRange   =   1000;                   % 1100, 1300 in mbar
 sensorSettings.barometer1.minMeasurementRange   =   0;                      % 300, 10 in mbar
 sensorSettings.barometer1.bit                   =   24;                     % adc on rocket is 24 bits 
-sensorSettings.barometer1.resolution = (sensorSettings.barometer1.maxMeasurementRange -sensorSettings.barometer1.minMeasurementRange)/(2^sensorSettings.barometer1.bit);
+% sensorSettings.barometer1.resolution = (sensorSettings.barometer1.maxMeasurementRange -sensorSettings.barometer1.minMeasurementRange)/(2^sensorSettings.barometer1.bit);
 
-sensorSettings.barometer1 = loadSensorNoiseData(sensorSettings.barometer1, Lyra_Port_sensor_vect, "main_Main_StaticPressureData1.csv", 1);
+% sensorSettings.barometer1 = loadSensorNoiseData(sensorSettings.barometer1, Lyra_Port_sensor_vect, "main_Main_StaticPressureData1.csv", 1);
 % sensorSettings.barometer1.noiseVariance         =   1;                      % mbar^2
 
 sensorSettings.barometer1.fault_time = 9;           % if negative it will be generated at random between a max and a min value
@@ -38,15 +38,17 @@ switch  settings.fault_sim.fault_type(1)
     otherwise
 end
 
+sensorSettings.barometer1.update(Lyra_Port_sensor_vect, "main_Main_StaticPressureData1.csv", 1);
+
 %% barometer2 - static measure (HSCMAND001BAAA5)
 % NOTE: pressure in mbar, temp should be in C°
 sensorSettings.barometer2 = SensorFault();
 sensorSettings.barometer2.maxMeasurementRange   =   1000;                   % 1100, 1300 in mbar
 sensorSettings.barometer2.minMeasurementRange   =   0;                      % 300, 10 in mbar
 sensorSettings.barometer2.bit                   =   24;                     % adc on rocket is 24 bits 
-sensorSettings.barometer2.resolution = (sensorSettings.barometer2.maxMeasurementRange -sensorSettings.barometer2.minMeasurementRange)/(2^sensorSettings.barometer2.bit);
+% sensorSettings.barometer2.resolution = (sensorSettings.barometer2.maxMeasurementRange -sensorSettings.barometer2.minMeasurementRange)/(2^sensorSettings.barometer2.bit);
 
-sensorSettings.barometer2 = loadSensorNoiseData(sensorSettings.barometer2, Lyra_Port_sensor_vect, "main_Main_StaticPressureData2.csv", 1);
+% sensorSettings.barometer2 = loadSensorNoiseData(sensorSettings.barometer2, Lyra_Port_sensor_vect, "main_Main_StaticPressureData2.csv", 1);
 % sensorSettings.barometer2.noiseVariance         =   1;                      % mbar^2
 
 sensorSettings.barometer2.fault_time = -1;          % if negative it will be generated at random between a max and a min value
@@ -69,15 +71,17 @@ switch  settings.fault_sim.fault_type(2)
     otherwise
 end
 
+sensorSettings.barometer2.update(Lyra_Port_sensor_vect, "main_Main_StaticPressureData2.csv", 1);
+
 %% barometer3 - digital measure (LPS28DFWTR)
 % NOTE: pressure in mbar, temp should be in C°
 sensorSettings.barometer3 = SensorFault();
 sensorSettings.barometer3.maxMeasurementRange   =   4060;                   % 1100, 1300 in mbar
 sensorSettings.barometer3.minMeasurementRange   =   260;                    % 300, 10 in mbar
 sensorSettings.barometer3.bit                   =   24; 
-sensorSettings.barometer3.resolution = (sensorSettings.barometer3.maxMeasurementRange -sensorSettings.barometer3.minMeasurementRange)/(2^sensorSettings.barometer3.bit);
+% sensorSettings.barometer3.resolution = (sensorSettings.barometer3.maxMeasurementRange -sensorSettings.barometer3.minMeasurementRange)/(2^sensorSettings.barometer3.bit);
 
-sensorSettings.barometer3 = loadSensorNoiseData(sensorSettings.barometer3, Lyra_Port_sensor_vect, "main_Boardcore_LPS28DFWData.csv", 1);
+% sensorSettings.barometer3 = loadSensorNoiseData(sensorSettings.barometer3, Lyra_Port_sensor_vect, "main_Boardcore_LPS28DFWData.csv", 1);
 % sensorSettings.barometer3.noiseVariance         =   4.06;                   % guess in mbar
 
 sensorSettings.barometer3.fault_time = -1;          % if negative it will be generated at random between a max and a min value
@@ -100,6 +104,8 @@ switch  settings.fault_sim.fault_type(3)
     otherwise
 end
 
+sensorSettings.barometer3.update(Lyra_Port_sensor_vect, "main_Boardcore_LPS28DFWData.csv", 1);
+
 %% accelerometer (6 dof imu - LSM6DSRXTR)
 % NOTE: acceleration in mg
 sensorSettings.accelerometer = Sensor3D();
-- 
GitLab