Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Path: blob/master/Tools/simulink/arducopter/sid_controller_validation.m
Views: 1799
% Validation of the controller model1%2% The script initializes and runs the Simulink model in controller3% validation mode and validates the controller model.4%5% The user has to specify the controller that is to be validated (simMode)6% and the index of the logfile in "sidLogs" (log_idx) that is used for the7% validation.8%9% Fabian Bredemeier - IAV GmbH10% License: GPL v31112curPath = pwd;1314%% Define log file index and controller type to be validated15% Log file index used for validation16log_idx = 5;1718% Check validity of log_idx19if log_idx > numel(sidLogs)20error(['Defined log_idx exceeds number of elements in sidLogs (' num2str(numel(sidLogs)) ')!']);21end2223% Show figure with flight paths for user to decide which controller to24% validate25figure % Attitude controller signals26subplot(311)27plot(sidLogs(log_idx).data.ATT.TimeS, sidLogs(log_idx).data.ATT.DesRoll, 'LineWidth', 1.4);28hold on29plot(sidLogs(log_idx).data.ATT.TimeS, sidLogs(log_idx).data.ATT.Roll, 'LineWidth', 1.4);30hold off31grid on32legend('Desired', 'Actual');33xlabel('Time (s)');34ylabel('Roll angle (deg)');35xlim([0 max(sidLogs(log_idx).data.ATT.TimeS)]);36subplot(312)37plot(sidLogs(log_idx).data.ATT.TimeS, sidLogs(log_idx).data.ATT.DesPitch, 'LineWidth', 1.4);38hold on39plot(sidLogs(log_idx).data.ATT.TimeS, sidLogs(log_idx).data.ATT.Pitch, 'LineWidth', 1.4);40hold off41grid on42legend('Desired', 'Actual');43xlabel('Time (s)');44ylabel('Pitch angle (deg)');45xlim([0 max(sidLogs(log_idx).data.ATT.TimeS)]);46subplot(313)47plot(sidLogs(log_idx).data.ATT.TimeS, sidLogs(log_idx).data.ATT.DesYaw, 'LineWidth', 1.4);48hold on49plot(sidLogs(log_idx).data.ATT.TimeS, sidLogs(log_idx).data.ATT.Yaw, 'LineWidth', 1.4);50hold off51grid on52legend('Desired', 'Actual');53xlabel('Time (s)');54ylabel('Yaw angle (deg)');55xlim([0 max(sidLogs(log_idx).data.ATT.TimeS)]);5657% Plot z Controller signals if Althold flight mode was active58if sidLogs(log_idx).data.MODE.Mode == 259figure60plot(sidLogs(log_idx).data.PSCD.TimeS, -1*(sidLogs(log_idx).data.PSCD.TPD), 'LineWidth', 1.4); % -1 to yield upwards position61hold on62plot(sidLogs(log_idx).data.PSCD.TimeS, -1*(sidLogs(log_idx).data.PSCD.PD), 'LineWidth', 1.4);63hold off64grid on65legend('Desired', 'Actual');66xlabel('Time (s)');67ylabel('z Position (m)');68xlim([0 max(sidLogs(log_idx).data.RATE.TimeS)]);69end7071% Ask user for controller to validate72% 1 = Rate controller73% 2 = Attitude controller74% 3 = Position controller75fprintf('Flight mode in log file: ');76fprintf('%d', sidLogs(log_idx).data.MODE.Mode);77switch sidLogs(log_idx).data.MODE.Mode78case 079fprintf(' (Stabilize)\n');80case 281fprintf(' (Althold)\n');82otherwise83fprintf(['\n No available flight mode for the validation could be found. ' ...84'Please use the Stabilize or Althold flight mode!\n']);85return;86end87fprintf('Available controllers that can be validated: \n');88fprintf('1 = Rate controller\n');89fprintf('2 = Attitude controller\n');90fprintf('3 = z Position controller\n');91fprintf('0 = Abort.\n');92simMode = input(['Enter controller to be validated: ']);93switch simMode94case 095fprintf('Aborting...\n');96close all97return;98case 199ctrlName = 'rateCtrl';100case 2101ctrlName = 'attCtrl';102case 3103ctrlName = 'zPosCtrl';104end105106% Define title of validation for documentation purposes107valTitle = 'Arducopter-4.3';108109%% Configuration of validation - Get signal names for comparison110% Declaration of temporary evaluation structs111val_out_sig_names = {};112val_out_sig_sim = {};113val_out_sig_meas = {};114val_in_sig_names = {};115val_in_sig = {};116117% Call the config script to read the necessary signals for the evaluation118% and the names of their counterparts in the Ardupilot code119sid_controller_validation_cfg120121%% Run simulation122% Sim init script123sid_sim_init124125% Run simulation126simOut = sim("arducopter");127128%% Store results129130% Create directory for storing the results for the controller validation131% if we are not currently in the result folder...132if isempty(regexp(curPath, 'results'))133% ...AND if the folder is not already existing on the current path134if ~exist('results', 'file')135mkdir results136cd results137else138cd results139end140end141if isempty(regexp(curPath, 'ctrlVal'))142if ~exist('ctrlVal', 'file')143mkdir ctrlVal144cd ctrlVal145else146cd ctrlVal147end148end149150% Get number of existing subdirectories with today's date and create new151% subdirectory with the validation title and controller that is validated152date = datestr(now, 'yy_mm_dd');153numFolders = 0;154while true155if numFolders < 10156dir_name = [date '_0' num2str(numFolders) '_' valTitle '_' ctrlName];157if ~(isfolder(dir_name))158mkdir(dir_name);159break;160end161else162dir_name = [date '_' num2str(numFolders) '_' valTitle '_' ctrlName];163if ~(isfolder(dir_name))164mkdir(dir_name);165break;166end167end168numFolders = numFolders + 1;169end170171% Open or create log172log_id = fopen('result_log.txt','a+');173fprintf(log_id, 'Validation %s\n', dir_name); % Print directory to safe figures174fprintf(log_id, 'Flight data path: %s\n', sidLogs(log_idx).data.filePathName); % Print flight data path175fprintf(log_id, 'Flight data file: %s\n', sidLogs(log_idx).data.fileName); % Print flight data file name176fprintf(log_id, 'Subflight: %d\n', loadedDataConfig.subflights(log_idx));177header_mark = '---------------------------------------------------------------\n';178fprintf(log_id, header_mark);179table_header = '%s\t\t\t|%s\n';180fprintf(log_id, table_header, 'Signal', 'Fit between measured and simulated signal (in %)');181fprintf(log_id, header_mark);182fclose(log_id);183184% Calculate evaluation struct & save results185for i=1:length(val_out_sig_names)186% Get SimulationData object187out_sim = simOut.logsout.get(val_out_sig_sim{i});188out_meas = simOut.logsout.get(val_out_sig_meas{i});189out_name = val_out_sig_names{i};190in_test = simOut.logsout.get(val_in_sig{i});191192% Create figure of results193figure('Name', out_name);194plot(out_sim.Values.time, out_sim.Values.Data);195hold on196plot(out_meas.Values.time, out_meas.Values.Data);197hold off198ylabel(out_name)199200yyaxis right201plot(in_test.Values.time, in_test.Values.Data);202yAxR = gca;203ylabel(val_in_sig_names{i});204yAxR.YLim = [min(in_test.Values.Data)-min(in_test.Values.Data)*0.05, max(in_test.Values.Data)+max(in_test.Values.Data)*0.05];205206% Figure settings207xlim([0 out_sim.Values.time(end)]); % Limit time208grid on % Activate grid of axes209title([out_name ': Comparison between simulated and measured controller outputs.'], 'Interpreter', 'none');210legend('Simulated Output', 'Measured Output', 'Input');211212% Save figure213cd(dir_name)214savefig([out_name '.fig'])215cd ..216close all217218% Calculate coefficient of determination to determine fit between219% measured and simulated signal220sigFit = 1 - sum((out_meas.Values.Data - out_sim.Values.Data).^2)/sum(out_meas.Values.Data.^2);221222% Write log223log_line = '%s\t\t| %6.3f \n';224log_id = fopen('result_log.txt','a');225fprintf(log_id, log_line, out_name, sigFit*100);226fclose(log_id);227end228229log_id = fopen('result_log.txt','a');230fprintf(log_id, '\n');231fclose(log_id);232233% Return to main directory234cd(curPath);235236clear val_in_sig val_in_sig_names val_out_sig_meas val_out_sig_sim val_out_sig_names237clear valTitle sigFit sig_name out_name sig_meas sig_test test_sig test_sig_names238clear table_header f_name num_folders file_struct header header_mark239clear log_id log_line num_folders sig_name_ap sig_sim sig_real signal_log underscore240clear date i dir_name out out_meas out_sim in_test yAxR ctrlName241242