% Lap analysis script based on vector CAN Data % ToDo: % - add Driver - Steering -> Oversteer calculation (steering/acc_lat) % - fix Driver - Statistics -> Braking distribution to start at >1 bar % - calculation damper velocities!! % - add size selection for output graphics % - add legend for multiple laps selection (instead of statistics?) % - automatic plot_settings detection?? close all clear all format shortEng %% Add required paths addpath("assets\"); addpath("plot_settings\"); save_path = "plots\"; % intital variables: global pltData; pltData = 0; global filepath_last; filepath_last = "none"; %% create uifigure fig = uifigure; fig.Position = [100 100 800 600]; fig.Name = "FT23-Ultra Data Analysis Tool"; fig.Icon = "assets/FT_icon.png"; % create 5x3 grid layout (row,column) g = uigridlayout(fig); g.RowHeight = {22, 22,'1x',22,22}; g.ColumnWidth = {150,'1x',200}; % (1,2) Load path filepathField = uieditfield(g); filepathField.Value = "data/"; filepathField.Layout.Row = 1; filepathField.Layout.Column = 2; % (2,1) label "Plot type:" labelPlot = uilabel(g); labelPlot.Text = "Plot type:"; labelPlot.Layout.Row = 2; labelPlot.Layout.Column = 1; labelPlot.HorizontalAlignment = "right"; % (2,2) create dropdown selection for plot type dd = uidropdown(g); dd.Items = ["Driver - General", "Driver - Steering", "Driver - Braking", "Driver - Statistics" ... "Powertrain", "Brakes", "Accumulator", "Inverter", ... "Suspension - Positions", "Suspension - Velocities", "Suspension - Histogram", ... "Tires - Temperatures", "Tires - Friction Circle"]; dd.Layout.Row = 2; dd.Layout.Column = 2; % ([3 4],1) create list box with laptimes and multiselection lb = uilistbox(g); lb.Multiselect = "on"; lb.Items = "No data loaded!"; lb.ItemsData = 1; lb.Layout.Row = [3 4]; lb.Layout.Column = 1; % (3,2) create plot window pltpanel = uipanel(g); pltpanel.Layout.Row = 3; pltpanel.Layout.Column = 2; % (3,3) lap/stint statistics (peak power, max speed, engergy used) labelStats = uilabel(g); labelStats.Text = "Statistics:"; labelStats.Layout.Row = 3; labelStats.Layout.Column = 3; labelStats.VerticalAlignment = "top"; % (4,2) create dropdown selection for x-Axis (time/distance) ddAxis = uidropdown(g); ddAxis.Items = ["Time [s]", "Distance [m]", "Time [h:m:s]"]; ddAxis.ItemsData = linspace(1,3,3); ddAxis.Layout.Row = 4; ddAxis.Layout.Column = 2; % (4,3) ??? % (5,1) dropdown selection for plot output format ddFormat = uidropdown(g); ddFormat.Items = ["png", "pdf", "fig", "m"]; ddFormat.ItemsData = ddFormat.Items; ddFormat.Layout.Row = 5; ddFormat.Layout.Column = 1; % (5,2) edit field for output plot name editPlotName = uieditfield(g); editPlotName.Value = "plot"; editPlotName.Layout.Row = 5; editPlotName.Layout.Column = 2; % (1,1) browse button btnbrowse = uibutton(g,"ButtonPushedFcn", @(src,event) browseButtonPushed(filepathField)); btnbrowse.Text = "Browse"; btnbrowse.Layout.Row = 1; btnbrowse.Layout.Column = 1; % (1,3) Load button btnLoad = uibutton(g,"ButtonPushedFcn", @(src,event) loadButtonPushed(lb, filepathField.Value)); btnLoad.Text = "Load"; btnLoad.Layout.Row = 1; btnLoad.Layout.Column = 3; % (2,3) create button for plotting new selection btnPlot = uibutton(g,"ButtonPushedFcn", @(src,event) plotButtonPushed(pltpanel, labelStats, lb.Value, dd.Value, ddAxis.Value)); btnPlot.Text = "Plot"; btnPlot.Layout.Row = 2; btnPlot.Layout.Column = 3; % (5,3) create button for saving displayed plot btnSave = uibutton(g,"ButtonPushedFcn", @(src,event) saveButtonPushed(pltpanel, append(save_path, editPlotName.Value), ddFormat.Value)); btnSave.Text = "Save"; btnSave.Layout.Row = 5; btnSave.Layout.Column = 3; % Plot window FT Logo for style points (and placeholder) tl = tiledlayout(pltpanel,"vertical"); pltpanelDefault = nexttile(tl); [imageData,~,imageAlpha] = imread("assets\FT_logo.png"); image(imageData, "Parent",pltpanelDefault, "alphadata", imageAlpha); pltpanelDefault.Visible = "off"; pltpanelDefault.DataAspectRatio = [1,1,1]; pltpanelDefault.Toolbar.Visible = "off"; %% Functions function plotButtonPushed(panel, labelStats, selected_laps, plottype, xplot) global pltData; % If complete stint selected -> disable plotting multiple laps if ismember(1, selected_laps) selected_laps = 1; % xplot = 3; % select hh:mm:ss format automatically?? end if size(selected_laps) == 1 % update statistics sidebarLabel = sidebar_stats(pltData(selected_laps)); else % clear stats sidebarLabel = "not available in multiselection (yet)"; end labelStats.Text = sidebarLabel; % change x-Axis based on drop-down selection: switch xplot case 2 for i = 1:length(pltData) pltData(i).xAxis = pltData(i).distance; end case 3 for i = 1:length(pltData) pltData(i).xAxis = pltData(i).time_hms; end otherwise for i = 1:length(pltData) pltData(i).xAxis = pltData(i).time_s; end end switch plottype case "Accumulator" plot_accumulator(panel, selected_laps, pltData); case "Brakes" plot_brakes(panel, selected_laps, pltData); case "Driver - Braking" plot_driver_braking(panel, selected_laps, pltData); case "Driver - General" plot_driver_general(panel, selected_laps, pltData); case "Driver - Statistics" plot_driver_statistics(panel, selected_laps, pltData); case "Driver - Steering" plot_driver_steering(panel, selected_laps, pltData); case "Inverter" plot_inverter(panel, selected_laps, pltData); case "Powertrain" plot_powertrain(panel, selected_laps, pltData); case "Suspension - Histogram" plot_suspension_histogram(panel, selected_laps, pltData); case "Suspension - Positions" plot_suspension_positions(panel, selected_laps, pltData); case "Suspension - Velocities" plot_suspension_velocities(panel, selected_laps, pltData); case "Tires - Friction Circle" plot_tires_firctionCircle(panel, selected_laps, pltData); case "Tires - Temperatures" % plot_tires_temperatures(panel, selected_laps, pltData); otherwise error("Error plotting") end % legend(ax1,string(selected_laps),'Location','northeastoutside'); end function loadButtonPushed(listbox, filepath) global pltData; global filepath_last; % check if data is already loaded if strcmp(filepath,filepath_last) == false [pltData,laps_strArray] = loadvector(filepath); % update UI elements listbox.Items = laps_strArray; listbox.ItemsData = linspace(1,length(laps_strArray),length(laps_strArray)); else msgbox("Data already loaded!"); end filepath_last = filepath; end function browseButtonPushed(filepathField) [name, location] = uigetfile(... {'*.m;*.mat',... 'MATLAB Files (*.m,*.mat)'; '*.*', 'All Files (*.*)'}, ... "Select File","data\"); filepath = append(location,name); filepathField.Value = filepath; end function saveButtonPushed(panel, savepath, format) try figure = panel.Children; savePlot(figure,savepath,format); fprintf("Plot saved to: %s.%s\n",savepath,format); catch msgbox("No plot available!") end end