diff --git a/ci/README.md b/ci/README.md index edd129cadf36d32a62065683ba34da5f479641da..c6fe244562c59a6ff1ab3f89ca7c48e31f2456c7 100644 --- a/ci/README.md +++ b/ci/README.md @@ -10,3 +10,33 @@ It runs [make](quad/Makefile) under the quad directory to build the project. ## Test Stage The test stage is defined by the [`ci-test.sh`](ci/ci-test.sh) file. It runs [make test](quad/Makefile#L36) under the quad directory to run the tests. + +# CI Server +The CI server for this project is at `microcart.ece.iastate.edu` +login information should be handed off outside this repo for security reasons. +The gitlab runner uses docker to launch a container, in which the scripts are run. +The VM is running Red Hat Enterprise Linux, which as of Oct. 6, 2018 was licensed. +**Note:** RHEL uses `yum` for package management, but the docker image uses `apt-get`. + +## Accessing System Folders +If you need to access any folders on the VM from within the docker, +the information [here](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#volumes-in-the-runners-docker-section) should help +Specifically this part: + +### Example 2: mount a host directory as a data volume +In addition to creating a volume using you can also mount a directory from your +Docker daemon's host into a container. It's useful when you want to store builds +outside the container. + + [runners.docker] + ... whatever config is already there ... + volumes = ["/path/to/persistent/data/in/container", /path/to/bind/from/host:/path/to/bind/in/container:rw"] + +## Accessing a remote share on the VM +To get to the Xilinx tools for hardware simulation, we need access to +`logic.ece.iastate.edu/export/Xilinx` as a mounted folder. This can be done with NFS. +NFS is installed and the folder mounted. If it becomes unmounted, then run + + $ sudo mount logic.ece.iastate.edu:/export/Xilinx /remote/Xilinx + +on the VM. This may not be doable from within the CI run as it is in a container (Docker image) that may behave differently or have different permissions. diff --git a/controls/DataAnalysisTool/Tool/GUI.asv b/controls/DataAnalysisTool/Tool/GUI.asv new file mode 100644 index 0000000000000000000000000000000000000000..831028acb356e56ec500e969d0c4dc1a83f8b775 --- /dev/null +++ b/controls/DataAnalysisTool/Tool/GUI.asv @@ -0,0 +1,784 @@ +function varargout = GUI(varargin) +% GUI MATLAB code for GUI.fig +% GUI, by itself, creates a new GUI or raises the existing +% singleton*. +% +% H = GUI returns the handle to a new GUI or the handle to +% the existing singleton*. +% +% GUI('CALLBACK',hObject,eventData,handles,...) calls the local +% function named CALLBACK in GUI.M with the given input arguments. +% +% GUI('Property','Value',...) creates a new GUI or raises the +% existing singleton*. Starting from the left, property value pairs are +% applied to the GUI before GUI_OpeningFcn gets called. An +% unrecognized property name or invalid value makes property application +% stop. All inputs are passed to GUI_OpeningFcn via varargin. +% +% *See GUI Options on GUIDE's Tools menu. Choose "GUI allows only one +% instance to run (singleton)". +% +% See also: GUIDE, GUIDATA, GUIHANDLES + +% Edit the above text to modify the response to help GUI + +% Last Modified by GUIDE v2.5 24-Mar-2015 21:23:27 + +% Begin initialization code - DO NOT EDIT +gui_Singleton = 1; +gui_State = struct('gui_Name', mfilename, ... + 'gui_Singleton', gui_Singleton, ... + 'gui_OpeningFcn', @GUI_OpeningFcn, ... + 'gui_OutputFcn', @GUI_OutputFcn, ... + 'gui_LayoutFcn', [] , ... + 'gui_Callback', []); +if nargin && ischar(varargin{1}) + gui_State.gui_Callback = str2func(varargin{1}); +end + +if nargout + [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:}); +else + gui_mainfcn(gui_State, varargin{:}); +end +% End initialization code - DO NOT EDIT + + +% --- Executes just before GUI is made visible. +function GUI_OpeningFcn(hObject, eventdata, handles, varargin) +% This function has no output args, see OutputFcn. +% hObject handle to figure +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +% varargin command line arguments to GUI (see VARARGIN) + +% Choose default command line output for GUI +handles.output = hObject; + +handles.filepath = hObject; +handles.filepath = mfilename('fullpath'); +handles.filepath = strrep(handles.filepath, 'GUI', ''); +addpath(handles.filepath); +cd(handles.filepath); +if (~exist(handles.filepath,'file')) + error(strcat(handles.filepath, ' does not exist')) +end + +if(~isfield(handles, 'axes')) + for i = 1:12 + eval(['handles.axes{' num2str(i) '} = handles.axes' num2str(i) ';']); + eval(['handles = rmfield(handles,''axes' num2str(i) ''');']); + eval(['handles.togglebuttons{' num2str(i) '} = handles.togglebutton' num2str(i) ';']); + eval(['handles = rmfield(handles,''togglebutton' num2str(i) ''');']); + eval(['handles.radiobutton{' num2str(i) '} = handles.radiobutton' num2str(i) ';']); + eval(['handles = rmfield(handles,''radiobutton' num2str(i) ''');']); + end + for i = 13:16 + eval(['handles.radiobutton{' num2str(i) '} = handles.radiobutton' num2str(i) ';']); + eval(['handles = rmfield(handles,''radiobutton' num2str(i) ''');']); + end +end +handles.main = hObject; +handles.main = struct(); + +if(evalin('base','exist(''main'')')) + handles.main = importData(hObject, eventdata, handles); + handles = loadOptions(hObject, eventdata, handles); + previewPlot(hObject, eventdata, handles); + if(~isfield(handles.main.params.file,'pathName')) + handles.main.params.file.name = ''; + handles.main.params.file.path = handles.filepath; + handles.main.params.file.pathName = handles.filepath; + end +else + handles.main.params.file.name = ''; + handles.main.params.file.path = handles.filepath; + handles.main.params.file.pathName = handles.filepath; +end + +handles.pause_play_timer = timer('BusyMode', 'queue', 'ExecutionMode',... + 'fixedRate', 'Period', 5.0); +set(handles.pause_play_timer, 'TimerFcn', @(hObject, event) pushbutton2_Callback(hObject, eventdata, guidata(hObject))); +cd(handles.main.params.file.path); +load_listbox(hObject, eventdata, handles) +guidata(hObject, handles); +% Update handles structure +%findobj('tag', 'figure\*'); + + +% UIWAIT makes GUI wait for user response (see UIRESUME) +% uiwait(handles.figure1); + + +% --- Outputs from this function are returned to the command line. +function varargout = GUI_OutputFcn(hObject, eventdata, handles) +% varargout cell array for returning output args (see VARARGOUT); +% hObject handle to figure +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Get default command line output from handles structure +varargout{1} = handles.output; + +% --- Executes when user attempts to close figure1. +function figure1_CloseRequestFcn(hObject, eventdata, handles) +% hObject handle to figure1 (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +cd(handles.filepath); +% Hint: delete(hObject) closes the figure +delete(hObject); + + +function uipanel1_SelectionChangeFcn(hObject, eventdata, handles) +if(isfield(handles.main,'expData')) +previewPlot(hObject, eventdata, handles) +end + + +% --- Executes when selected object is changed in uipanel3. +function uipanel3_SelectionChangeFcn(hObject, eventdata, handles) +% hObject handle to the selected object in uipanel3 +% eventdata structure with the following fields (see UIBUTTONGROUP) +% EventName: string 'SelectionChanged' (read only) +% OldValue: handle of the previously selected object or empty if none was selected +% NewValue: handle of the currently selected object +% handles structure with handles and user data (see GUIDATA) +handles = guidata(hObject); + +handles.main.params.plotting.separatePlot = 0; % to generate separate plots +handles.main.params.plotting.multiPlot = 0; % to super impose multiple quantities on the same plot +handles.main.params.plotting.subPlot = 0; + +switch get(get(handles.uipanel3,'SelectedObject'),'Tag') +case 'radiobutton14', handles.main.params.plotting.separatePlot = 1; +case 'radiobutton15', handles.main.params.plotting.subPlot = 1; +case 'radiobutton16', handles.main.params.plotting.multiPlot = 1; + otherwise + error('You must select a radio button to indicate what field''s options you are changing.') +end +exportData(hObject, eventdata, handles); +previewPlot(hObject, eventdata, handles); +guidata(hObject,handles); + +function pause_play_Timer(hObject, eventdata, handles) +% hObject handle to pushbutton_pause +% eventdata reserved - to be defeined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +handles = guidata(hObject); +handles = updateOptions(hObject, eventdata, handles);; + +if (handles.pause + + +% --- Executes on button press in pushbutton2. +function pushbutton2_Callback(hObject, eventdata, handles) +% hObject handle to pushbutton2 (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +handles = guidata(hObject); + +handles = updateOptions(hObject, eventdata, handles);; + +if(handles.main.params.plotting.clearFigs) + set(handles.figure1, 'HandleVisibility', 'off'); + close all; + set(handles.figure1, 'HandleVisibility', 'on'); +end +handles.main.params.plotting.toPlot = handles.main.params.plotting.toPlot(~cellfun('isempty',handles.main.params.plotting.toPlot)); +if(~isempty(handles.main.params.plotting.toPlot)) + if(handles.main.params.plotting.subPlot) %% plot on one figure using multiple subplots + counter = 1; + x = ceil(sqrt(length(handles.main.params.plotting.toPlot))); + y = x - floor((x ^ 2 - length(handles.main.params.plotting.toPlot))/x); + figure_handle = figure; + else if(handles.main.params.plotting.multiPlot) + figure_handle = figure; + end + end + + tempData{1} = handles.main.expData.data{1}; + tempParams{1} = handles.main.expData.params{1}; + tempUnit{1} = handles.main.expData.unit{1}; + tempName{1} = handles.main.expData.datafields{1}; + if(isfield(handles.main.params.plotting,'toPlot')) + for m = 1:length(handles.main.params.plotting.toPlot) + for n = 1:length(handles.main.expData.datafields) + if(strcmp(handles.main.expData.datafields{n},handles.main.params.plotting.toPlot{m})) + tempData{m+1} = handles.main.expData.data{n}; + tempParams{m+1} = handles.main.expData.params{n}; + tempUnit{m+1} = handles.main.expData.unit{n}; + tempName{m+1} = handles.main.expData.datafields{n}; + end + end + end + end + + + for i=1:length(handles.main.params.plotting.toPlot) + if(strcmp(tempName{i},'Marker')) + + else + if(handles.main.params.plotting.subPlot) + subplot(x,y,counter); + counter = counter + 1; + + else if(handles.main.params.plotting.separatePlot) + figure_handle = figure; + whitebg(tempParams{1}.backgnd); + else + hold on; + end + whitebg('white'); + end + + + if(strcmp(get(get(handles.uipanel1,'SelectedObject'),'Tag'), 'radiobutton13')) + whitebg(tempParams{1}.backgnd); + plot(tempData{1},tempData{i+1},'LineStyle',tempParams{1}.style,'Marker',tempParams{1}.marker,'Color',tempParams{1}.color); + set(gca,'Color',tempParams{1}.backgnd); + set(gcf,'Color',tempParams{1}.backgnd); + grid ON; + title(tempName{i+1}) + xlabel(strcat(tempName{1},'(', tempUnit{1},')')); + ylabel(tempUnit{i+1}); + else + plot(tempData{1},tempData{i+1},'LineStyle',tempParams{i+1}.style,'Marker',tempParams{i+1}.marker,'Color',tempParams{i+1}.color); + if(handles.main.params.plotting.subPlot||handles.main.params.plotting.separatePlot) + set(gca,'Color',tempParams{i+1}.backgnd); + end + grid ON; + xlabel(strcat(tempName{1},'(', tempUnit{1},')')); + if(~handles.main.params.plotting.multiPlot) + ylabel(tempUnit{i+1}); + title(tempName{i+1}) + else + hold off; + end + + end + + if(isfield(handles.main.expData,'Marker')) + marks = find(handles.main.expData.Marker.data); + l = length(marks); + for n = 1:l + x = handles.main.expData.data{1}(marks(n)); + line([x x], get(gca,'YLim'),'Color',[rand(1) rand(1) rand(1)]); + y = get(gca,'YLim'); + y = y(1)+(1/l)*n*(y(2)-y(1)); + text('String',strcat('M',num2str(n),'>'),'Position',[x,y],'HorizontalAlignment','right') + end + end + end + end + all_ha = findobj( figure_handle, 'type', 'axes', 'tag', '' ); + linkaxes( all_ha, 'x' ); +else + error('You must select fields to plot first.') +end +guidata(hObject,handles); + +% --- Executes on button press in checkbox1. +function checkbox1_Callback(hObject, eventdata, handles) +% hObject handle to checkbox1 (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hint: get(hObject,'Value') returns toggle state of checkbox1 +handles = guidata(hObject); + +button_state = get(hObject,'Value'); +if button_state == get(hObject,'Max') + handles.main.params.plotting.clearFigs = 1; +elseif button_state == get(hObject,'Min') + handles.main.params.plotting.clearFigs = 0; +end +handles = updateOptions(hObject, eventdata, handles); +guidata(hObject,handles); + + + +% --- Executes on button press in pushbutton3. +function pushbutton3_Callback(hObject, eventdata, handles) +% hObject handle to pushbutton3 (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +handles = guidata(hObject); +switch get(get(handles.uipanel1,'SelectedObject'),'Tag') +case 'radiobutton1', i = 2; +case 'radiobutton2', i = 3; +case 'radiobutton3', i = 4; +case 'radiobutton4', i = 5; +case 'radiobutton5', i = 6; +case 'radiobutton6', i = 7; +case 'radiobutton7', i = 8; +case 'radiobutton8', i = 9; +case 'radiobutton9', i = 10; +case 'radiobutton10', i = 11; +case 'radiobutton11', i = 12; +case 'radiobutton12', i = 13; +case 'radiobutton13', i = 1; + otherwise + error('You must select a radio button to indicate what field''s options you are changing before pressing this button.') +end + +color = get(handles.listbox1,'String'); +color = color{get(handles.listbox1,'Value')}; +style = get(handles.listbox2,'String'); +style = style{get(handles.listbox2,'Value')}; +marker = get(handles.listbox3,'String'); +marker = marker{get(handles.listbox3,'Value')}; +bg = get(handles.listbox4,'String'); +bg = bg{get(handles.listbox4,'Value')}; +handles.main.expData.params{i}.color = color; +handles.main.expData.params{i}.style = style; +handles.main.expData.params{i}.marker = marker; +handles.main.expData.params{i}.backgnd = bg; +exportData(hObject, eventdata, handles); +previewPlot(hObject, eventdata, handles); +handles = updateOptions(hObject, eventdata, handles); +guidata(hObject,handles); + +% --- Executes on button press in pushbutton4. +function pushbutton4_Callback(hObject, eventdata, handles) +% hObject handle to pushbutton4 (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +if isdir(handles.main.params.file.pathName) + cd (handles.main.params.file.pathName); + handles.main.params.file.path = cd; + handles.main.params.file.pathName = cd; + addpath(cd); + load_listbox(hObject, eventdata, handles); +end + +% --- Executes on selection change in listbox5. +function listbox5_Callback(hObject, eventdata, handles) +% hObject handle to listbox5 (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) + +% Hints: contents = cellstr(get(hObject,'String')) returns listbox5 contents as cell array +% contents{get(hObject,'Value')} returns selected item from listbox5 +handles = guidata(hObject); +get(handles.figure1,'SelectionType'); +if strcmp(get(handles.figure1,'SelectionType'),'open') + index_selected = get(handles.listbox5,'Value'); + file_list = get(handles.listbox5,'String'); + [path, handles.main.params.file.name, ext] = fileparts(file_list{index_selected}); + handles.main.params.file.name = strcat(handles.main.params.file.name,ext); + handles.main.params.file.pathName = strcat(handles.main.params.file.path,'/', handles.main.params.file.name); + if isdir(handles.main.params.file.pathName) + cd (handles.main.params.file.pathName); + handles.main.params.file.path = cd; + handles.main.params.file.pathName = cd; + addpath(cd); + load_listbox(hObject, eventdata, handles); + else + cd(handles.main.params.file.path); + switch ext + case '.txt' + + if(isfield(handles.main.params,'plotting')) + if(isfield(handles.main,'expData')) + handles.main.expData = parse_log(handles.main.params.file.pathName,handles.main.params,handles.main.expData); + else + handles.main.expData = parse_log(handles.main.params.file.pathName,handles.main.params); + end + else + handles.main.params = set_params(hObject, eventdata, handles); + handles.main.expData = parse_log(handles.main.params.file.pathName,handles.main.params); + end + handles.main = generateGuiData(hObject, eventdata, handles); + exportData(hObject, eventdata, handles); + handles.main = importData(hObject, eventdata, handles); + handles = updateOptions(hObject, eventdata, handles); + handles = loadOptions(hObject, eventdata, handles); + set(handles.text5,'string',strcat('Current Log:', handles.main.params.file.pathName)); + previewPlot(hObject, eventdata, handles); + + case '.mat' + handles.main = importData(hObject, eventdata, handles); + handles = updateOptions(hObject, eventdata, handles); + handles = loadOptions(hObject, eventdata, handles); + set(handles.text5,'string',strcat('Current Log:', handles.main.params.file.pathName)); + previewPlot(hObject, eventdata, handles); + + otherwise + try + open(handles.main.params.file.pathName,handles.main.params); + catch ex + errordlg(ex.getReport('basic'),'File Type Error','modal'); + end + + end + end +end + +guidata(hObject,handles); + + + + +%% Extra Functions +% Used by above + + +function previewPlot(hObject, eventdata, handles) +%handles.datafields = fieldnames(handles.main.expData); +if(~isnan(handles.main.expData.Time.data)) + if(strcmp(get(get(handles.uipanel1,'SelectedObject'),'Tag'), 'radiobutton13')) + whitebg(handles.main.expData.params{1}.backgnd); + for i = 1:length(handles.main.expData.data)-1 + if(~isnan(handles.main.expData.data{i}(1,1)) && i<=12) + plot(handles.axes{i},handles.main.expData.data{1},handles.main.expData.data{i+1},'LineStyle',handles.main.expData.params{1}.style,'Marker',handles.main.expData.params{1}.marker,'Color',handles.main.expData.params{1}.color); + set(handles.axes{i},'Color',handles.main.expData.params{1}.backgnd); + set(handles.togglebuttons{i},'string',handles.main.expData.datafields{i+1},'enable','on'); + grid(handles.axes{i}, 'on'); + xlabel(handles.axes{i},strcat(handles.main.expData.datafields{1},'(', handles.main.expData.unit{1},')')); + ylabel(handles.axes{i},handles.main.expData.unit{i+1}); + if(isfield(handles.main.expData,'Marker')) + marks = find(handles.main.expData.Marker.data); + for j = 1:length(marks) + line([handles.main.expData.data{1}(marks(j)) handles.main.expData.data{1}(marks(j))], get(handles.axes{i},'YLim'),'Color','red','Parent',handles.axes{i}) + end + + end + end + end + else + whitebg('white'); + for i = 1:length(handles.main.expData.data)-1 + if(~isnan(handles.main.expData.data{i}(1,1)) && (i<=12)) + plot(handles.axes{i},handles.main.expData.data{1},handles.main.expData.data{i+1},'LineStyle',handles.main.expData.params{i+1}.style,'Marker',handles.main.expData.params{i+1}.marker,'Color',handles.main.expData.params{i+1}.color); + if(~handles.main.params.plotting.multiPlot) + set(handles.axes{i},'Color',handles.main.expData.params{i+1}.backgnd); + end + set(handles.togglebuttons{i},'string',handles.main.expData.datafields{i+1},'enable','on'); + grid(handles.axes{i}, 'on'); + xlabel(handles.axes{i},strcat(handles.main.expData.datafields{1},'(', handles.main.expData.unit{1},')')); + ylabel(handles.axes{i},handles.main.expData.unit{i+1}); + if(isfield(handles.main.expData,'Marker')) + marks = find(handles.main.expData.Marker.data); + for j = 1:length(marks) + line([handles.main.expData.data{1}(marks(j)) handles.main.expData.data{1}(marks(j))], get(handles.axes{i},'YLim'),'Color','red','Parent',handles.axes{i}) + end + + end + end + end + end + for i = length(handles.main.expData.data):12 + plot(handles.axes{i},0,0); + set(handles.axes{i},'Color','white'); + grid(handles.axes{i}, 'off'); + set(handles.togglebuttons{i},'string','no data','enable','off'); + set(handles.togglebuttons{i},'value',0); + handles.main.params.plotting.toPlot{i} = []; + end + setbgcolor(hObject, eventdata, handles); +end +guidata(hObject, handles); + + + +function main = importData(hObject, eventdata, handles) + +main = evalin('base' , 'main'); +handles.main = main; +handles.main = generateGuiData(hObject, eventdata, handles); + +if(~isfield(handles.main.params,'plotting')) + handles.main.params = set_params(hObject, eventdata, handles); +end +if(~isfield(handles.main.params.plotting,'separatePlot')) + handles.main.params.plotting.separatePlot = 1; % to generate separate plots +end +if(~isfield(handles.main.params.plotting,'multiPlot')) + handles.main.params.plotting.multiPlot = 0; % to super impose multiple quantities on the same plot +end +if(~isfield(handles.main.params.plotting,'subPlot')) + handles.main.params.plotting.subPlot = 0; % to generate sub plots for multiple quantities +end +if(~isfield(handles.main.params.plotting,'clearFigs')) + handles.main.params.plotting.clearFigs = 1; +end +main = handles.main; +guidata(hObject, handles); + + + +function main = generateGuiData(hObject, eventdata, handles) +n = length(fieldnames(handles.main.expData)); +handles.main.expData.datafields = fieldnames(handles.main.expData); +for i = 1:n +eval(['handles.main.expData.data{i} = handles.main.expData.', handles.main.expData.datafields{i}, '.data;']); %% +eval(['handles.main.expData.unit{i} = handles.main.expData.', handles.main.expData.datafields{i}, '.unit;']); %% +eval(['handles.main.expData.params{i} = handles.main.expData.', handles.main.expData.datafields{i}, '.params;']); +end +main = handles.main; +guidata(hObject, handles); + + + +function exportData(hObject, eventdata, handles) + +handles.main.expData.datafields = fieldnames(handles.main.expData); +for i = 1:length(handles.main.expData.data) +eval(['handles.main.expData.', handles.main.expData.datafields{i}, '.data = handles.main.expData.data{i};']); %% +eval(['handles.main.expData.', handles.main.expData.datafields{i}, '.unit = handles.main.expData.unit{i};']); %% +eval(['handles.main.expData.', handles.main.expData.datafields{i}, '.params = handles.main.expData.params{i};']); +end +handles.main.expData = rmfield(handles.main.expData, 'datafields'); +handles.main.expData = rmfield(handles.main.expData, 'data'); +handles.main.expData = rmfield(handles.main.expData, 'unit'); +handles.main.expData = rmfield(handles.main.expData, 'params'); + +assignin('base', 'main', handles.main); + + + +function setbgcolor(hObject, eventdata, handles) + +bgcolor = get(handles.figure1,'color'); +set(handles.uipanel1,'BackgroundColor', bgcolor); +set(handles.uipanel2,'BackgroundColor', bgcolor); +set(handles.uipanel3,'BackgroundColor', bgcolor); +for i = 1:16 + set(handles.radiobutton{i},'BackgroundColor', bgcolor); +end +for i = 1:6 + eval(['set(handles.text', num2str(i) , ',''BackgroundColor'', bgcolor);']) +end +set(handles.checkbox1,'BackgroundColor', bgcolor); +guidata(hObject, handles); + + + +function load_listbox(hObject, eventdata, handles) +dir_struct = dir(cd); +[sorted_names,sorted_index] = sortrows({dir_struct.name}'); +handles.file_names = sorted_names; +handles.is_dir = [dir_struct.isdir]; +handles.sorted_index = sorted_index; +guidata(handles.figure1,handles) +set(handles.listbox5,'String',handles.file_names,'Value',1) +set(handles.text5,'string',strcat('Current Log:', handles.main.params.file.pathName)) +cd(handles.filepath); +guidata(hObject, handles); + + + +function params = set_params(hObject, eventdata, handles) +handles.main.params.plotting.plot = 1; % switch to choose plotting +handles.main.params.plotting.separatePlot = 1; % to generate separate plots +handles.main.params.plotting.multiPlot = 0; % to super impose multiple quantities on the same plot +handles.main.params.plotting.subPlot = 0; % to generate sub plots for multiple quantities +handles.main.params.plotting.clearFigs = 1; +handles.main.params.plotting.separateData = {}; % column numbers to plot on separate figures +handles.main.params.plotting.toPlot = {}; + % if empty & plot = 1, all the columns will be plotted +handles.main.params.plotting.multiData = {}; % if empty but switch is on, use separateData values +handles.main.params.plotting.subData = {}; % if empty but switch is on, use multiData values +handles.main.params.plotting.color = 'black'; % one character for color of the plotting line +handles.main.params.plotting.marker = 'none'; % one character for the maker of the plotting line +handles.main.params.plotting.style = '-'; % one character for the style of the plotting line +handles.main.params.plotting.backgnd = 'white'; % rgb array for background color of the plot +params = handles.main.params; + + + +function handles = loadOptions(hObject, eventdata, handles) +handles = guidata(hObject); +set(handles.radiobutton{14},'Value',0) +set(handles.radiobutton{15},'Value',0) +set(handles.radiobutton{16},'Value',0) +if(handles.main.params.plotting.separatePlot) + set(handles.radiobutton{14},'Value',1) +else if(handles.main.params.plotting.subPlot) + set(handles.radiobutton{15},'Value',1) + else if(handles.main.params.plotting.multiPlot) + set(handles.radiobutton{16},'Value',1) + else + set(handles.radiobutton{14},'Value',1); + handles.main.params.plotting.separatePlot = 1; + end + end +end +if(handles.main.params.plotting.clearFigs) + set(handles.checkbox1,'Value',1) +else + set(handles.checkbox1,'Value',0) +end + +for n = 2:length(handles.main.expData.datafields) + if(n<=13) + set(handles.togglebuttons{n-1}, 'Value', 0); + end +end +if(isfield(handles.main.params.plotting,'toPlot')) + for m = 1:length(handles.main.params.plotting.toPlot) + for n = 2:length(handles.main.expData.datafields) + if(strcmp(handles.main.expData.datafields{n},handles.main.params.plotting.toPlot{m})) + set(handles.togglebuttons{n-1}, 'Value', 1); + end + end + end +end +exportData(hObject, eventdata, handles); +guidata(hObject, handles); + + + +function handles = updateOptions(hObject, eventdata, handles) + +handles = guidata(hObject); + +uipanel3_SelectionChangeFcn(hObject, eventdata, handles); + +if(get(handles.checkbox1,'Value')) + handles.main.params.plotting.clearFigs = 1; +else + handles.main.params.plotting.clearFigs = 0; +end + +handles.main.params.plotting.toPlot = {}; +for i = 1:length(handles.main.expData.datafields)-1 + if(i<=12) + button_state = get(handles.togglebuttons{i},'Value'); + end + if button_state == 1 + handles.main.params.plotting.toPlot = {handles.main.params.plotting.toPlot{:}, handles.main.expData.datafields{i+1}}; + else + handles.main.params.plotting.toPlot(strcmp(handles.main.expData.datafields{i+1},handles.main.params.plotting.toPlot)) = []; + end +end +handles.main.params.plotting.toPlot = handles.main.params.plotting.toPlot(~cellfun('isempty',handles.main.params.plotting.toPlot)); + +exportData(hObject, eventdata, handles); +guidata(hObject, handles); + + + +%% unused functions +function uipanel1_ButtonDownFcn(hObject, eventdata, handles) +function togglebutton7_CreateFcn(hObject, eventdata, handles) +function listbox5_CreateFcn(hObject, eventdata, handles) +function listbox1_Callback(hObject, eventdata, handles) +function listbox1_CreateFcn(hObject, eventdata, handles) +if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor','white'); +end +function listbox2_Callback(hObject, eventdata, handles) +function listbox2_CreateFcn(hObject, eventdata, handles) +function listbox3_Callback(hObject, eventdata, handles) +function listbox3_CreateFcn(hObject, eventdata, handles) +if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor','white'); +end +function listbox4_Callback(hObject, eventdata, handles) +function listbox4_CreateFcn(hObject, eventdata, handles) +if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor')) + set(hObject,'BackgroundColor','white'); +end + + +%% bulky functions (repetative) + +%--- Executes on button press in togglebutton1. +function togglebutton1_Callback(hObject, eventdata, handles) +% hObject handle to togglebutton1 (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +handles = guidata(hObject); +handles = updateOptions(hObject, eventdata, handles); +guidata(hObject,handles); +% --- Executes on button press in togglebutton2. +function togglebutton2_Callback(hObject, eventdata, handles) +% hObject handle to togglebutton2 (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +handles = guidata(hObject); +handles = updateOptions(hObject, eventdata, handles); +guidata(hObject,handles); +% --- Executes on button press in togglebutton3. +function togglebutton3_Callback(hObject, eventdata, handles) +% hObject handle to togglebutton3 (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +handles = guidata(hObject); +handles = updateOptions(hObject, eventdata, handles); +guidata(hObject,handles); +% --- Executes on button press in togglebutton4. +function togglebutton4_Callback(hObject, eventdata, handles) +% hObject handle to togglebutton4 (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +handles = guidata(hObject); +handles = updateOptions(hObject, eventdata, handles); +guidata(hObject,handles); +% --- Executes on button press in togglebutton5. +function togglebutton5_Callback(hObject, eventdata, handles) +% hObject handle to togglebutton5 (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +handles = guidata(hObject); +handles = updateOptions(hObject, eventdata, handles); +guidata(hObject,handles); +% --- Executes on button press in togglebutton6. +function togglebutton6_Callback(hObject, eventdata, handles) +% hObject handle to togglebutton6 (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +handles = guidata(hObject); +handles = updateOptions(hObject, eventdata, handles); +guidata(hObject,handles); +% --- Executes on button press in togglebutton7. +function togglebutton7_Callback(hObject, eventdata, handles) +% hObject handle to togglebutton7 (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +handles = guidata(hObject); +handles = updateOptions(hObject, eventdata, handles); +guidata(hObject,handles); +% --- Executes on button press in togglebutton8. +function togglebutton8_Callback(hObject, eventdata, handles) +% hObject handle to togglebutton8 (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA)clc +handles = guidata(hObject); +handles = updateOptions(hObject, eventdata, handles); +guidata(hObject,handles); +% --- Executes on button press in togglebutton9. +function togglebutton9_Callback(hObject, eventdata, handles) +% hObject handle to togglebutton9 (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +handles = guidata(hObject); +handles = updateOptions(hObject, eventdata, handles); +guidata(hObject,handles); +% --- Executes on button press in togglebutton10. +function togglebutton10_Callback(hObject, eventdata, handles) +% hObject handle to togglebutton10 (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +handles = guidata(hObject); +handles = updateOptions(hObject, eventdata, handles); +guidata(hObject,handles); +% --- Executes on button press in togglebutton11. +function togglebutton11_Callback(hObject, eventdata, handles) +% hObject handle to togglebutton11 (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +handles = guidata(hObject); +handles = updateOptions(hObject, eventdata, handles); +guidata(hObject,handles); +% --- Executes on button press in togglebutton12. +function togglebutton12_Callback(hObject, eventdata, handles) +% hObject handle to togglebutton12 (see GCBO) +% eventdata reserved - to be defined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +handles = guidata(hObject); +handles = updateOptions(hObject, eventdata, handles); +guidata(hObject,handles); diff --git a/controls/DataAnalysisTool/Tool/GUI.fig b/controls/DataAnalysisTool/Tool/GUI.fig index 0e62ff281260cd9f294eff1374daa9c160bab03e..cbbcff33b682e326691c4bffc93b94c4dde630a0 100644 Binary files a/controls/DataAnalysisTool/Tool/GUI.fig and b/controls/DataAnalysisTool/Tool/GUI.fig differ diff --git a/controls/DataAnalysisTool/Tool/GUI.m b/controls/DataAnalysisTool/Tool/GUI.m index 3794047e00cc08f8ad91d60cbe691a2839368fa4..95016c85f4251c7337a1c7b9b799a0bb79b8d0ae 100644 --- a/controls/DataAnalysisTool/Tool/GUI.m +++ b/controls/DataAnalysisTool/Tool/GUI.m @@ -95,6 +95,11 @@ else handles.main.params.file.path = handles.filepath; handles.main.params.file.pathName = handles.filepath; end + +handles.pause_or_play = 0; +handles.pause_play_timer = timer('BusyMode', 'queue', 'ExecutionMode',... + 'fixedRate', 'Period', 5.0); +set(handles.pause_play_timer, 'TimerFcn', @(hObject, event) pushbutton2_Callback(hObject, eventdata, guidata(hObject))); cd(handles.main.params.file.path); load_listbox(hObject, eventdata, handles) guidata(hObject, handles); @@ -158,6 +163,22 @@ exportData(hObject, eventdata, handles); previewPlot(hObject, eventdata, handles); guidata(hObject,handles); +function pause_play_timer(hObject, eventdata, handles) +% hObject handle to pushbutton_pause +% eventdata reserved - to be defeined in a future version of MATLAB +% handles structure with handles and user data (see GUIDATA) +handles = guidata(hObject); +handles = updateOptions(hObject, eventdata, handles);; + +if (handles.pause_or_play == 0) + handles.pause_or_play = 1; + start(handles.pause_play_timer); +else + handles.pause_or_play = 0; + stop(handles.pause_play_timer); +end +guidata(hObject, handles); + % --- Executes on button press in pushbutton2. function pushbutton2_Callback(hObject, eventdata, handles) diff --git a/controls/README.md b/controls/README.md index 8a1d285f263eea8ecc25b67f4ec5d80e7ee04709..3dc51e0812f5cf04783e8e0fcd4e0f49bc5c72c1 100644 --- a/controls/README.md +++ b/controls/README.md @@ -2,6 +2,32 @@ This folder contains the files used in developing the model of the quadcopter. -## Documentation +### **1. Simulink Flight Simulator** + +**How to Run the Simulator** +1. In the project folder, open “MicroCART/controls/modelâ€. The “model†folder contains the files needed to run the Simulink simulator. Make sure this folder is the current workspace directory. +2. Open “modelParameters.m†in MATLAB and run the script. This will create/update parameters in the MATLAB workspace which are used by the simulator. At this point you should also check that the contents of the “model†folder are displayed in the “Current Folder†window in MATLAB. +3. Open “Quadcopter_Model.slx†+4. To view the 3D simulator, navigate within the model by clicking on the following blocks: Sensors -> 3D Graphical Simulation -> VR Sink +5. Press “Run†in Simulink + + +**Changing Setpoints** +1. To change the simulation setpoints, return to the top level of the simulink model and then enter the “Setpoints†block. +2. The default version of the simulator has five step functions which individually instruct the quad to move 1 unit in the x-direction, 1 unit in the y-direction, 1 unit in the z-direction, turn clockwise by 1 unit along the yaw angle, and then return to its starting values. Each step function can be thought of as a setpoint. +3. Open a step function block by double clicking on it. Altering the step time will change when the quad begins to move towards a setpoint. Initial and final value have the format [x-position, y-position, z-position, yaw-angle], and any alterations to these fields will change where the quad starts and where it goes to respectively. +4. Setpoints can be added or removed by adding or removing step functions from the Simulink model diagram. + + *Note: + For this model, negative z values correspond to a position above the starting point [0,0,0,0] and positive z values correspond to a position beneath the starting point. (Example: If the quad is instructed to move from [0,0,-2,0] to [0,0,-1,0], it will be moving from a height of 2 units above the starting point down to a height of 1 unit above the starting point.) This means we will usually only work with negative z-values since our starting point is usually the ground and we cannot fly beneath it :)* + + +**Changing Control Models** +1. To select which controller is used to simulate quad flight, navigate to the top level of the Simulink model and toggle the controller switch to either LQR or PID + + + + +## Additional Documents [Measuring Motor Resistance](documentation/MeasuringMotorResistance.pdf) [Simulink Model](documentation/SimulinkModel.md) \ No newline at end of file