added geoplot function
This commit is contained in:
parent
4bcd68f244
commit
69e506d815
86
README.md
86
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
|
||||
!
|
||||
|
||||
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
|
||||

|
||||
|
||||
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:
|
||||

|
||||
Part 2 - Preset Tab:
|
||||

|
||||
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
|
||||

|
||||
|
||||
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:
|
||||

|
||||

|
||||

|
||||
- 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)
|
||||
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
|
||||
|
BIN
app2.mlapp
BIN
app2.mlapp
Binary file not shown.
BIN
legacy/app.mlapp
Normal file
BIN
legacy/app.mlapp
Normal file
Binary file not shown.
@ -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
|
||||
|
||||
|
BIN
tutorial/app2 tutorial - presets.png
Normal file
BIN
tutorial/app2 tutorial - presets.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 50 KiB |
BIN
tutorial/geoplot.png
Normal file
BIN
tutorial/geoplot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 511 KiB |
Loading…
x
Reference in New Issue
Block a user