diff --git a/README.md b/README.md index 2dff4b5..e82db78 100644 --- a/README.md +++ b/README.md @@ -1,68 +1,42 @@ !!! Important !!! -See Example: start the App in Matlab the correct folder (see picture), otherwise it will throw an error -![double click app.mlapp in this folder! make sure ](tutorial/image.png)! - -Updated app is out. Check out app2 (everything except laps, grayed out buttons and presets works, presets might work in old app) +See Example: start the App in Matlab the correct folder (see picture), otherwise it will give out an error +![double click app.mlapp in this folder! make sure ](tutorial/image.png) KNOWN ERRORS / NOT WORKING / UNKNOWN -- FT25-Presets -> instead use Load(fast) and Plot Subplot -- new implementation of date selection might mess with lap selection -- unknown status of Presets for FT23 and FT24 after the last few updates, might not work +- should the imported data contain more than one day, preconfigured presets will might not work +- geoplot was not tested throughly, might not work with subplotting, so close the figures before you plot either of them FYI: -- code is starting to get really clunky, going to rewrite the handling of loaded data some time in the future - search is case sensitive - you need to delete your search if you misspelled something - if something doesnt work try reset subplot and then press plot subplot again +Short tutorial: +Part 1 - General Tab: ![Tutorial for new app2]() +Part 2 - Preset Tab: +![Tutorial for new app2 - presets]() +Part 3 - Geoplot: +- need to manually load latitude and longitude +- third value can be inserted as linecolor by choosing a dataset in the dropdown next to custom geoplot +- can also apply timestamps like the subplots +![Tutorial for new app2 - Geoplot]() +Quick notes: +There are two options to plot data +- 1. Tab: General + - Allows to make custom plots based on the data you have choosen + - Allows to apply external functions saved in the folder "functions" to be applied to loaded dataset + - Note: check "example.m" in the functions folder to learn how to make a custom function (there are some rules) + - Timestamped data can only be created from app.data / Loaded Datasets + - To timestamp the data you created with custom functions you need to append it first +- 2. Tab: Presets + - this tab allows you to plot and save preconfigured seasonal presets + - presets exist for the seasons 23,24,25 + - check the Dropdown Box to see which plots are available -Quick tutorial: -1. Browse the .mat file you want to open. (put it into /data folder) -2. Choose either Load (fast) or Load (Presets) - - Load(fast): - - will load ONLY the name of all saved data in your .mat file - - select data you want to plot in custom subplots -> select data (left side) - - all features will work for this option - - for customizing look under the next chapter - - - Load (Presets) - - will load a pre configured set of data in your .mat file (takes a bit of time) - - choose a preset and a season, then press "Plot Presets" - -> will plot pre configured graphs - - all features in "Custom Subplots" do NOT work with this - - the idea is that only sortdata.m and the plot_settings need to be configured each season - - for customizing look under the next chapter (only features within Set Timestamps panel work) - -Features: -1. Set Timestamps: - - works for both - - entire stint (all data recorded) is the default option that will be plotted - - otherwise you can select either the detected laps (will plot, but laps might be inaccurately recorded) or custom timestamps (remember to tick the Use box) -2. Reset Panel and To Workspace Buttons: - - work only for Presets - - should something not work try pressing reset and plot preset again - - to workspace throws the entire preset dataset into the matlab workspace (for further manipulation) - - currently limited in capabilites -3. Custom Subplots: - - only works for the selected data (if you press load preset you can also use the displayed data, but somethings like cell voltages might not be avaible) - - columns and rows to set the number of plots you want in one figure - - press Plot Subplot to plot - - how it works: -![selected subplot is 1](tutorial/1.png) -![this time a lap, and a different dataset was selected](tutorial/2.png) -![only if you want a second -yaxis select the option "plot with 2nd yAxis](tutorial/3.png) - - press reset subplot to delete the selected graph - - -Presets: -Adapting a preset: -- sortdata creates an struct pltData with all necessary data for plot_settings - - easiest case: the data from the vectorlogger has the same fieldnames as last season -> probably no changes necessary, unless you want to plot different things - - vectorlogger fieldnames changed: adapt the fieldname to the updated name - - otherwise: add missing data with pltData.XXX = -- plot_settings: uses the data given from pltData to plot, adapt as you see fit - - plotData currently hands over all data that use the following strings: - - "ABX*","Shunt*","AMS_Status*","INV*","XSens* - - which can make problems (e.g. FT23 and FT25 use XSens, FT24 uses VN200) \ No newline at end of file +4 seperate datasets: +app.data - main dataset for custom plots +app.data_created - dataset created by custom functions/filter, can be appended to app.data via synchronize() +app.data_tr = app.data(tr,:) - main dataset cut down with timestamp (timerange tr) +app.pltData - main dataset for preset dataset diff --git a/app2.mlapp b/app2.mlapp index 7087d7a..3b86b47 100644 Binary files a/app2.mlapp and b/app2.mlapp differ diff --git a/legacy/app.mlapp b/legacy/app.mlapp new file mode 100644 index 0000000..ce784ed Binary files /dev/null and b/legacy/app.mlapp differ diff --git a/season/FT25/sortdata.m b/season/FT25/sortdata.m index 7a933be..46141f5 100644 --- a/season/FT25/sortdata.m +++ b/season/FT25/sortdata.m @@ -1,44 +1,45 @@ -function [pltData] = sortdata(data,start,stop) +function [pltData, stats] = sortdata(data) date = dateshift(data.Time(1),'start','day'); time_hms = data.Time-date; time_s = seconds(time_hms); time_s = time_s - time_s(1); % set beginning of session to 0 % x-Axis: - pltData.Time = data.Time(start:stop); - pltData.time_s = time_s(start:stop)-time_s(start); - pltData.time_hms = time_hms(start:stop); + pltData.time_s = time_s; + pltData.time_hms = time_hms; + % distance calculation - speed_mps = movmean(data.ABX_Driver_ABX_Speed(start:stop),50); % TODO: test different speed filters for distance calculation + speed_mps = movmean(data.FTCU_Driver_FTCU_Speed,50); % TODO: test different speed filters for distance calculation pltData.distance(1) = 0; for i = 2:length(speed_mps) - pltData.distance(i) = speed_mps(i)*(pltData.time_s(i)-pltData.time_s(i-1)) + pltData.distance(i-1); + pltData.distance(i) = speed_mps(i)*(time_s(i)-time_s(i-1)) + pltData.distance(i-1); end + pltData.distance = pltData.distance.'; pltData.xAxis = pltData.time_s; % set time as default x-Axis for plotting %% Misc - pltData.app_percent = data.ABX_Driver_ABX_APPS_percent(start:stop); - pltData.speed_kph = 3.6*movmean(data.ABX_Driver_ABX_Speed(start:stop),50); % same filter as for distance calculation ??? - pltData.steering_deg = data.ABX_Driver_ABX_Steering_Angle(start:stop); + pltData.app_percent = data.FTCU_Driver_FTCU_APPS_Percent; + pltData.speed_kph = 3.6*movmean(data.FTCU_Driver_FTCU_Speed,50); % same filter as for distance calculation ??? + pltData.steering_deg = data.FTCU_Driver_FTCU_Steering_Angle; %% AMS: - pltData.ams_soc = data.AMS_Status_SOC(start:stop); - pltData.ams_tmax = data.AMS_Status_Max_cell_temp(start:stop); - pltData.ams_utot = data.Shunt_Voltage1_Shunt_Voltage1(start:stop); - pltData.ams_itot = data.Shunt_Current_Shunt_Current(start:stop); + pltData.ams_soc = data.AMS_Status_SOC; + pltData.ams_tmax = data.AMS_Status_Max_cell_temp; + pltData.ams_utot = data.Shunt_Voltage1_Shunt_Voltage1; + pltData.ams_itot = data.Shunt_Current_Shunt_Current; % calculations: pltData.ams_ptot = pltData.ams_utot.*pltData.ams_itot/1000; %% Brakes % brake pressure - pltData.brakePFront_bar = data.ABX_Driver_ABX_BrakeP_F(start:stop); - pltData.brakePRear_bar = data.ABX_Driver_ABX_BrakeP_R(start:stop); + pltData.brakePFront_bar = data.FTCU_Driver_FTCU_Brake_Pressure_F; + pltData.brakePRear_bar = data.FTCU_Driver_FTCU_Brake_Pressure_R; % brake disc temperatures - pltData.brakeTFrontLeft_degC = data.ABX_BrakeT_ABX_BrakeT_FL(start:stop); - pltData.brakeTFrontRight_degC = data.ABX_BrakeT_ABX_BrakeT_FR(start:stop); - pltData.brakeTRearLeft_degC = data.ABX_BrakeT_ABX_BrakeT_RL(start:stop); - pltData.brakeTRearRight_degC = data.ABX_BrakeT_ABX_BrakeT_RR(start:stop); + pltData.brakeTFrontLeft_degC = data.Sensornode_F_10Hz_BDTS_FL; + pltData.brakeTFrontRight_degC = data.Sensornode_F_10Hz_BDTS_FR; + pltData.brakeTRearLeft_degC = data.Sensornode_R_10Hz_BDTS_RL; + pltData.brakeTRearRight_degC = data.Sensornode_R_10Hz_BDTS_RR; % calculate brake bias [%] minBrakeP = 5; % minimum brake pressure to avoid artifacts due to sensor noise near 0 bar brakePFront = pltData.brakePFront_bar; @@ -51,10 +52,10 @@ function [pltData] = sortdata(data,start,stop) %% Dampers % damper positions - pltData.damper_FL_mm = data.ABX_Dampers_ABX_Damper_FL(start:stop); %Heave_F - pltData.damper_FR_mm = data.ABX_Dampers_ABX_Damper_FR(start:stop); %Roll_F - pltData.damper_RL_mm = data.ABX_Dampers_ABX_Damper_RL(start:stop); %Heave_R - pltData.damper_RR_mm = data.ABX_Dampers_ABX_Damper_RR(start:stop); %Roll_R + pltData.damper_FL_mm = data.Sensornode_F_100Hz_2_DS_FL; %Heave_F + pltData.damper_FR_mm = data.Sensornode_F_100Hz_2_DS_FR; %Roll_F + pltData.damper_RL_mm = data.Sensornode_R_100Hz_DS_RL; %Heave_R + pltData.damper_RR_mm = data.Sensornode_R_100Hz_DS_RR; %Roll_R % calculate damper velocities pltData.velocity_FL_mmps(1) = 0; pltData.velocity_FR_mmps(1) = 0; @@ -68,36 +69,36 @@ function [pltData] = sortdata(data,start,stop) pltData.velocity_RR_mmps(i) = pltData.damper_RR_mm(i)-pltData.damper_RR_mm(i-1)/timestep; end % filter damper velocities ??? bessere Berechnung über mittelwert aus mehreren werten? Vorfilterung? - pltData.velocity_FL_mmps = movmean(pltData.velocity_FL_mmps,100); - pltData.velocity_FR_mmps = movmean(pltData.velocity_FR_mmps,100); - pltData.velocity_RL_mmps = movmean(pltData.velocity_RL_mmps,100); - pltData.velocity_RR_mmps = movmean(pltData.velocity_RR_mmps,100); + pltData.velocity_FL_mmps = movmean(pltData.velocity_FL_mmps,100).'; + pltData.velocity_FR_mmps = movmean(pltData.velocity_FR_mmps,100).'; + pltData.velocity_RL_mmps = movmean(pltData.velocity_RL_mmps,100).'; + pltData.velocity_RR_mmps = movmean(pltData.velocity_RR_mmps,100).'; - %% IMU + %% IMU - VN200, no need to implement didnt work well anyway % Acceleration - pltData.acc_long_g = movmean(data.XSens_Acceleration_XSens_accX(start:stop),100)/9.81; - pltData.acc_lat_g = movmean(data.XSens_Acceleration_XSens_accY(start:stop),100)/9.81; + pltData.acc_long_g = movmean(data.XSens_Acceleration_XSens_accX,100)/9.81; + pltData.acc_lat_g = movmean(data.XSens_Acceleration_XSens_accY,100)/9.81; % Rate of turn - pltData.rot_roll_degps = movmean(data.XSens_RateOfTurn_XSens_gyrX(start:stop),100); - pltData.rot_pitch_degps = movmean(data.XSens_RateOfTurn_XSens_gyrY(start:stop),100); - pltData.rot_yaw_degps = movmean(data.XSens_RateOfTurn_XSens_gyrZ(start:stop),100); + pltData.rot_roll_degps = movmean(data.XSens_rateofturn_XSens_gyrX,100); + pltData.rot_pitch_degps = movmean(data.XSens_rateofturn_XSens_gyrY,100); + pltData.rot_yaw_degps = movmean(data.XSens_rateofturn_XSens_gyrZ,100); %% Inverters % inverter temperatures - pltData.invL_temp = data.INV_L_TxPDO_1_T_Inv_L(start:stop); - pltData.invR_temp = data.INV_R_TxPDO_1_T_Inv_R(start:stop); + pltData.invL_temp = data.INV_1_TxPDO_1_T_Inv_1; % not sure if 1 is left and 2 is right + pltData.invR_temp = data.INV_2_TxPDO_1_T_Inv_2; % motor temperatures - pltData.motL_temp = data.INV_L_TxPDO_1_T_Mot_L(start:stop); - pltData.motR_temp = data.INV_R_TxPDO_1_T_Mot_R(start:stop); + pltData.motL_temp = data.INV_1_TxPDO_1_T_Mot_1; % not sure if 1 is left and 2 is right + pltData.motR_temp = data.INV_2_TxPDO_1_T_Mot_2; % motor velocities - pltData.motL_vel_rpm = 60*data.INV_L_TxPDO_4_Velocity_L(start:stop); - pltData.motR_vel_rpm = 60*data.INV_R_TxPDO_4_Velocity_R(start:stop); + pltData.motL_vel_rpm = 60*data.INV_1_TxPDO_4_Velocity_1; % not sure if 1 is left and 2 is right + pltData.motR_vel_rpm = 60*data.INV_2_TxPDO_4_Velocity_2; % inverter torque demand - pltData.invL_torqueDemand = data.INV_L_TxPDO_3_DemandedTorque_L(start:stop)/10; % /10 to match autobox torque - pltData.invR_torqueDemand = data.INV_R_TxPDO_3_DemandedTorque_R(start:stop)/10; + pltData.invL_torqueDemand = data.INV_1_TxPDO_3_DemandedTorque_1/10; % /10 to match autobox torque % not sure if 1 is left and 2 is right + pltData.invR_torqueDemand = data.INV_2_TxPDO_3_DemandedTorque_2/10; % inverter actual torque - pltData.invL_torqueActual = data.INV_L_TxPDO_3_ActualTorque_L(start:stop)/10; - pltData.invR_torqueActual = data.INV_R_TxPDO_3_ActualTorque_R(start:stop)/10; + pltData.invL_torqueActual = data.INV_1_TxPDO_3_DemandedTorque_1/10; % not sure if 1 is left and 2 is right + pltData.invR_torqueActual = data.INV_2_TxPDO_3_DemandedTorque_2/10; %% Wheelspeed @@ -109,15 +110,18 @@ function [pltData] = sortdata(data,start,stop) power_regen_kw(power_regen_kw > 0) = 0; power_used_kw = pltData.ams_ptot; power_used_kw(power_used_kw < 0) = 0; - pltData.energy_kwh = trapz(pltData.time_s, pltData.ams_ptot)/3600; - pltData.energy_regen_kwh = trapz(pltData.time_s, power_regen_kw)/3600; - pltData.energy_used_kwh = trapz(pltData.time_s, power_used_kw)/3600; - pltData.distanceTotal_km = trapz(pltData.time_s, pltData.speed_kph./3.6)/1000; % 1/3.6 for km/h to m/s and /1000 for km output - pltData.peakPower_kw = max(pltData.ams_ptot); - pltData.peakPowerMean_kw = max(movmean(pltData.ams_ptot,500)); + stats.energy_kwh = trapz(time_s, pltData.ams_ptot)/3600; + stats.energy_regen_kwh = trapz(time_s, power_regen_kw)/3600; + stats.energy_used_kwh = trapz(time_s, power_used_kw)/3600; + stats.distanceTotal_km = trapz(time_s, pltData.speed_kph./3.6)/1000; % 1/3.6 for km/h to m/s and /1000 for km output + stats.peakPower_kw = max(pltData.ams_ptot); + stats.peakPowerMean_kw = max(movmean(pltData.ams_ptot,500)); - pltData.maxSpeed_kph = max(pltData.speed_kph); - pltData.startTime = time_hms(start); - pltData.stopTime = time_hms(stop); + stats.maxSpeed_kph = max(pltData.speed_kph); + % pltData.startTime = time_hms(1); + % pltData.stopTime = time_hms(end); + + %% struct2timetable + pltData = table2timetable(struct2table(pltData), "RowTimes", data.Time); end diff --git a/tutorial/app2 tutorial - presets.png b/tutorial/app2 tutorial - presets.png new file mode 100644 index 0000000..2a7f1f9 Binary files /dev/null and b/tutorial/app2 tutorial - presets.png differ diff --git a/tutorial/geoplot.png b/tutorial/geoplot.png new file mode 100644 index 0000000..19a1bea Binary files /dev/null and b/tutorial/geoplot.png differ