CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
Ardupilot

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.

GitHub Repository: Ardupilot/ardupilot
Path: blob/master/Tools/simulink/arducopter/sid_controller_validation.m
Views: 1799
1
% Validation of the controller model
2
%
3
% The script initializes and runs the Simulink model in controller
4
% validation mode and validates the controller model.
5
%
6
% The user has to specify the controller that is to be validated (simMode)
7
% and the index of the logfile in "sidLogs" (log_idx) that is used for the
8
% validation.
9
%
10
% Fabian Bredemeier - IAV GmbH
11
% License: GPL v3
12
13
curPath = pwd;
14
15
%% Define log file index and controller type to be validated
16
% Log file index used for validation
17
log_idx = 5;
18
19
% Check validity of log_idx
20
if log_idx > numel(sidLogs)
21
error(['Defined log_idx exceeds number of elements in sidLogs (' num2str(numel(sidLogs)) ')!']);
22
end
23
24
% Show figure with flight paths for user to decide which controller to
25
% validate
26
figure % Attitude controller signals
27
subplot(311)
28
plot(sidLogs(log_idx).data.ATT.TimeS, sidLogs(log_idx).data.ATT.DesRoll, 'LineWidth', 1.4);
29
hold on
30
plot(sidLogs(log_idx).data.ATT.TimeS, sidLogs(log_idx).data.ATT.Roll, 'LineWidth', 1.4);
31
hold off
32
grid on
33
legend('Desired', 'Actual');
34
xlabel('Time (s)');
35
ylabel('Roll angle (deg)');
36
xlim([0 max(sidLogs(log_idx).data.ATT.TimeS)]);
37
subplot(312)
38
plot(sidLogs(log_idx).data.ATT.TimeS, sidLogs(log_idx).data.ATT.DesPitch, 'LineWidth', 1.4);
39
hold on
40
plot(sidLogs(log_idx).data.ATT.TimeS, sidLogs(log_idx).data.ATT.Pitch, 'LineWidth', 1.4);
41
hold off
42
grid on
43
legend('Desired', 'Actual');
44
xlabel('Time (s)');
45
ylabel('Pitch angle (deg)');
46
xlim([0 max(sidLogs(log_idx).data.ATT.TimeS)]);
47
subplot(313)
48
plot(sidLogs(log_idx).data.ATT.TimeS, sidLogs(log_idx).data.ATT.DesYaw, 'LineWidth', 1.4);
49
hold on
50
plot(sidLogs(log_idx).data.ATT.TimeS, sidLogs(log_idx).data.ATT.Yaw, 'LineWidth', 1.4);
51
hold off
52
grid on
53
legend('Desired', 'Actual');
54
xlabel('Time (s)');
55
ylabel('Yaw angle (deg)');
56
xlim([0 max(sidLogs(log_idx).data.ATT.TimeS)]);
57
58
% Plot z Controller signals if Althold flight mode was active
59
if sidLogs(log_idx).data.MODE.Mode == 2
60
figure
61
plot(sidLogs(log_idx).data.PSCD.TimeS, -1*(sidLogs(log_idx).data.PSCD.TPD), 'LineWidth', 1.4); % -1 to yield upwards position
62
hold on
63
plot(sidLogs(log_idx).data.PSCD.TimeS, -1*(sidLogs(log_idx).data.PSCD.PD), 'LineWidth', 1.4);
64
hold off
65
grid on
66
legend('Desired', 'Actual');
67
xlabel('Time (s)');
68
ylabel('z Position (m)');
69
xlim([0 max(sidLogs(log_idx).data.RATE.TimeS)]);
70
end
71
72
% Ask user for controller to validate
73
% 1 = Rate controller
74
% 2 = Attitude controller
75
% 3 = Position controller
76
fprintf('Flight mode in log file: ');
77
fprintf('%d', sidLogs(log_idx).data.MODE.Mode);
78
switch sidLogs(log_idx).data.MODE.Mode
79
case 0
80
fprintf(' (Stabilize)\n');
81
case 2
82
fprintf(' (Althold)\n');
83
otherwise
84
fprintf(['\n No available flight mode for the validation could be found. ' ...
85
'Please use the Stabilize or Althold flight mode!\n']);
86
return;
87
end
88
fprintf('Available controllers that can be validated: \n');
89
fprintf('1 = Rate controller\n');
90
fprintf('2 = Attitude controller\n');
91
fprintf('3 = z Position controller\n');
92
fprintf('0 = Abort.\n');
93
simMode = input(['Enter controller to be validated: ']);
94
switch simMode
95
case 0
96
fprintf('Aborting...\n');
97
close all
98
return;
99
case 1
100
ctrlName = 'rateCtrl';
101
case 2
102
ctrlName = 'attCtrl';
103
case 3
104
ctrlName = 'zPosCtrl';
105
end
106
107
% Define title of validation for documentation purposes
108
valTitle = 'Arducopter-4.3';
109
110
%% Configuration of validation - Get signal names for comparison
111
% Declaration of temporary evaluation structs
112
val_out_sig_names = {};
113
val_out_sig_sim = {};
114
val_out_sig_meas = {};
115
val_in_sig_names = {};
116
val_in_sig = {};
117
118
% Call the config script to read the necessary signals for the evaluation
119
% and the names of their counterparts in the Ardupilot code
120
sid_controller_validation_cfg
121
122
%% Run simulation
123
% Sim init script
124
sid_sim_init
125
126
% Run simulation
127
simOut = sim("arducopter");
128
129
%% Store results
130
131
% Create directory for storing the results for the controller validation
132
% if we are not currently in the result folder...
133
if isempty(regexp(curPath, 'results'))
134
% ...AND if the folder is not already existing on the current path
135
if ~exist('results', 'file')
136
mkdir results
137
cd results
138
else
139
cd results
140
end
141
end
142
if isempty(regexp(curPath, 'ctrlVal'))
143
if ~exist('ctrlVal', 'file')
144
mkdir ctrlVal
145
cd ctrlVal
146
else
147
cd ctrlVal
148
end
149
end
150
151
% Get number of existing subdirectories with today's date and create new
152
% subdirectory with the validation title and controller that is validated
153
date = datestr(now, 'yy_mm_dd');
154
numFolders = 0;
155
while true
156
if numFolders < 10
157
dir_name = [date '_0' num2str(numFolders) '_' valTitle '_' ctrlName];
158
if ~(isfolder(dir_name))
159
mkdir(dir_name);
160
break;
161
end
162
else
163
dir_name = [date '_' num2str(numFolders) '_' valTitle '_' ctrlName];
164
if ~(isfolder(dir_name))
165
mkdir(dir_name);
166
break;
167
end
168
end
169
numFolders = numFolders + 1;
170
end
171
172
% Open or create log
173
log_id = fopen('result_log.txt','a+');
174
fprintf(log_id, 'Validation %s\n', dir_name); % Print directory to safe figures
175
fprintf(log_id, 'Flight data path: %s\n', sidLogs(log_idx).data.filePathName); % Print flight data path
176
fprintf(log_id, 'Flight data file: %s\n', sidLogs(log_idx).data.fileName); % Print flight data file name
177
fprintf(log_id, 'Subflight: %d\n', loadedDataConfig.subflights(log_idx));
178
header_mark = '---------------------------------------------------------------\n';
179
fprintf(log_id, header_mark);
180
table_header = '%s\t\t\t|%s\n';
181
fprintf(log_id, table_header, 'Signal', 'Fit between measured and simulated signal (in %)');
182
fprintf(log_id, header_mark);
183
fclose(log_id);
184
185
% Calculate evaluation struct & save results
186
for i=1:length(val_out_sig_names)
187
% Get SimulationData object
188
out_sim = simOut.logsout.get(val_out_sig_sim{i});
189
out_meas = simOut.logsout.get(val_out_sig_meas{i});
190
out_name = val_out_sig_names{i};
191
in_test = simOut.logsout.get(val_in_sig{i});
192
193
% Create figure of results
194
figure('Name', out_name);
195
plot(out_sim.Values.time, out_sim.Values.Data);
196
hold on
197
plot(out_meas.Values.time, out_meas.Values.Data);
198
hold off
199
ylabel(out_name)
200
201
yyaxis right
202
plot(in_test.Values.time, in_test.Values.Data);
203
yAxR = gca;
204
ylabel(val_in_sig_names{i});
205
yAxR.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];
206
207
% Figure settings
208
xlim([0 out_sim.Values.time(end)]); % Limit time
209
grid on % Activate grid of axes
210
title([out_name ': Comparison between simulated and measured controller outputs.'], 'Interpreter', 'none');
211
legend('Simulated Output', 'Measured Output', 'Input');
212
213
% Save figure
214
cd(dir_name)
215
savefig([out_name '.fig'])
216
cd ..
217
close all
218
219
% Calculate coefficient of determination to determine fit between
220
% measured and simulated signal
221
sigFit = 1 - sum((out_meas.Values.Data - out_sim.Values.Data).^2)/sum(out_meas.Values.Data.^2);
222
223
% Write log
224
log_line = '%s\t\t| %6.3f \n';
225
log_id = fopen('result_log.txt','a');
226
fprintf(log_id, log_line, out_name, sigFit*100);
227
fclose(log_id);
228
end
229
230
log_id = fopen('result_log.txt','a');
231
fprintf(log_id, '\n');
232
fclose(log_id);
233
234
% Return to main directory
235
cd(curPath);
236
237
clear val_in_sig val_in_sig_names val_out_sig_meas val_out_sig_sim val_out_sig_names
238
clear valTitle sigFit sig_name out_name sig_meas sig_test test_sig test_sig_names
239
clear table_header f_name num_folders file_struct header header_mark
240
clear log_id log_line num_folders sig_name_ap sig_sim sig_real signal_log underscore
241
clear date i dir_name out out_meas out_sim in_test yAxR ctrlName
242