-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'feature/ardupilot-tunable-parameter-postprocessing' int…
…o main
- Loading branch information
Showing
11 changed files
with
545 additions
and
52 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
function is_bdroot = bdIsRoot(model) | ||
% BDISROOT checks if the input is a handle or a path to a loaded top-level | ||
% Simulink model (model root). | ||
% | ||
% Inputs: | ||
% model Handle (numeric) or path (character vector). | ||
% Multiple models: numeric array of handles or cell array of | ||
% character vectors. | ||
% | ||
% Outputs: | ||
% is_bdroot Boolean, indicating whether the input is a loaded top-level | ||
% Simulink model (true) or not (false) | ||
|
||
% Disclaimer: | ||
% SPDX-License-Identifier: GPL-3.0-only | ||
% | ||
% Copyright (C) 2024 Jonas Withelm | ||
% Copyright (C) 2024 TU Braunschweig, Institute of Flight Guidance | ||
% ************************************************************************* | ||
|
||
is_bdroot = false; | ||
try | ||
bd = bdroot(model); | ||
if isnumeric(bd) | ||
is_bdroot = model == bd; | ||
else | ||
is_bdroot = strcmp(model, bd); | ||
end | ||
catch | ||
% Model is not loaded or input is invalid for bdroot | ||
end | ||
|
||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
function varargout = checkModelReqs(model, model_reqs) | ||
% CHECKMODELREQS checks whether the Simulink model fulfills the model | ||
% parameter requirements in 'model_reqs'. CheckModelReqs throws an error | ||
% with a tabular overview of the parameters that have not fulfilled the | ||
% requirements. The model must be loaded for usage. | ||
% | ||
% The parameter requirements must be provided in the form of a struct | ||
% (model_reqs) with the required fields 'param' and 'value' and the | ||
% optional field 'err_desc', whereby the values of the fields must be | ||
% cell arrays, e.g. | ||
% model_reqs.param{1} = 'TargetLang'; | ||
% model_reqs.value{1} = 'C++'; | ||
% model_reqs.err_desc{1} = 'Wrong target language'; | ||
% | ||
% The value check can also be provided as a function handle to a function | ||
% that must return a boolean as the check result, e.g. | ||
% model_reqs.value{1} = @(a) strcmp(a, C++); | ||
% | ||
% The parameter requirements can also be provided with a parameter file. | ||
% In this case, 'model_reqs' must be a path to the parameter file. | ||
% | ||
% Inputs: | ||
% model Handle or path to a top-level Simulink model | ||
% (model root) | ||
% model_reqs Model requirements struct as specified above or | ||
% a path to a model requirements file | ||
% | ||
% Outputs (optional): | ||
% varargout{1} No error is thrown, but instead an boolean array with | ||
% the indices of all failed parameter requirements is | ||
% returned | ||
|
||
% Disclaimer: | ||
% SPDX-License-Identifier: GPL-3.0-only | ||
% | ||
% Copyright (C) 2024 Jonas Withelm | ||
% Copyright (C) 2024 TU Braunschweig, Institute of Flight Guidance | ||
% ************************************************************************* | ||
|
||
% ToDo: | ||
% - change model_reqs to struct array instead of cell arrays? | ||
|
||
|
||
% Input checks | ||
err_msg = char.empty; | ||
|
||
if nargin ~=2 | ||
error('MATLAB:checkModelReqs:inputError', ... | ||
'Wrong number of input arguments!'); | ||
end | ||
|
||
if ~bdIsRoot(model) | ||
msg = sprintf(' - %s\n', 'expected input ''model'' to be a loaded top-level Simulink model'); | ||
err_msg = [err_msg, msg]; | ||
end | ||
|
||
if ischar(model_reqs) | ||
model_reqs = loadParams(model_reqs); | ||
end | ||
|
||
if ~all(isfield(model_reqs, {'param', 'value'})) | ||
msg = sprintf(' - %s\n', 'expected input ''model_reqs'' to be of type struct with at least two fields named ''param'' and ''value'''); | ||
err_msg = [err_msg, msg]; | ||
elseif any(size(model_reqs.param) ~= size(model_reqs.value)) | ||
msg = sprintf(' - %s\n', '''model_reqs.param'' and ''model_reqs.value'' must have the same size'); | ||
err_msg = [err_msg, msg]; | ||
end | ||
|
||
if ~isempty(err_msg) | ||
err_title = sprintf('Input error'); | ||
error('MATLAB:checkModelReqs:inputError', ... | ||
'\n%s:\n%s', err_title, err_msg); | ||
end | ||
|
||
has_err_desc = isfield(model_reqs, 'err_desc'); % ToDo: size check? | ||
|
||
|
||
% Do model requirement checks | ||
errs = {}; | ||
idxs = false(size(model_reqs.param)); | ||
for idx = 1:numel(model_reqs.param) | ||
|
||
% ToDo: | ||
% - Check that value is scalar and of type char? | ||
% -> Scalar is usefull, char could be dismissed, because a function | ||
% handle check could still succeed | ||
% - Check that param is an actual param of the model, raise error if | ||
% not | ||
value = get_param(model, model_reqs.param{idx}); | ||
|
||
switch class(model_reqs.value{idx}) | ||
case 'function_handle' | ||
is_ok = model_reqs.value{idx}(value); | ||
case {'char', 'string'} | ||
is_ok = strcmp(model_reqs.value{idx}, value); | ||
otherwise | ||
error('MATLAB:checkModelReqs:inputError', '''model_reqs.value{%i}'' not supported!', idx); | ||
end | ||
|
||
if ~is_ok | ||
idxs(idx) = true; | ||
|
||
err = repmat({char.empty}, 1, 4); | ||
err(1) = model_reqs.param(idx); | ||
err(3) = {value}; | ||
if has_err_desc | ||
err(4) = model_reqs.err_desc(idx); | ||
end | ||
switch class(model_reqs.value{idx}) | ||
case 'function_handle' | ||
err(2) = {func2str(model_reqs.value{idx})}; | ||
case {'char', 'string'} | ||
err(2) = model_reqs.value(idx); | ||
end | ||
errs = [errs; err]; | ||
end | ||
end | ||
|
||
|
||
if ~isempty(errs) | ||
header = {'Param:', 'Expected:', 'Actual:', char.empty}; | ||
if has_err_desc | ||
header(4) = {'Description:'}; | ||
end | ||
|
||
err_id = 'MATLAB:checkModelReqs:requirementsFailed'; | ||
err_title = 'Model parameter requirements failed for'; | ||
err_msg = printData(header, errs, 'headerstyle', 'bold', 'indent', 4, 'column_spacing', 2); | ||
|
||
ME = MException(err_id, '\n%s:\n%s', err_title, err_msg); | ||
|
||
if nargout ~= 1 | ||
throw(ME); | ||
end | ||
end | ||
|
||
if nargout == 1 | ||
varargout{1} = idxs; | ||
end | ||
|
||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
function [file] = getFileFromPath(file_path) | ||
% GETFILEFROMPATH returns the file part from a full path to a file. | ||
% | ||
% Inputs: | ||
% file_path full path to a file | ||
% | ||
% Outputs: | ||
% file filename with extension | ||
% | ||
% See also: | ||
% FILEPARTS | ||
|
||
% Disclaimer: | ||
% SPDX-License-Identifier: GPL-3.0-only | ||
% | ||
% Copyright (C) 2024 Jonas Withelm | ||
% Copyright (C) 2024 TU Braunschweig, Institute of Flight Guidance | ||
% ************************************************************************* | ||
|
||
|
||
[~, file_name, file_ext] = fileparts(file_path); | ||
file = [file_name file_ext]; | ||
|
||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
function file_link = getLink2File(file, link_text) | ||
% GETLINK2FILE returns a link to a file. | ||
% | ||
% This functions returns a link to a file which, when clicked, opens the | ||
% URL using the 'open()' function. | ||
% | ||
% Inputs: | ||
% file file | ||
% link_text Displayed name of the link (optional) | ||
% | ||
% Outputs: | ||
% file_link Link to the file | ||
% | ||
% See also: | ||
% OPEN | ||
% https://mathworks.com/help/matlab/matlab_prog/create-hyperlinks-that-run-functions.html | ||
|
||
% Disclaimer: | ||
% SPDX-License-Identifier: GPL-3.0-only | ||
% | ||
% Copyright (C) 2024 Jonas Withelm | ||
% Copyright (C) 2024 TU Braunschweig, Institute of Flight Guidance | ||
% ************************************************************************* | ||
|
||
if ~exist(file, 'file') | ||
err_msg = sprintf('''%s'' is either not a file or can not be found!', file); | ||
error('MATLAB:getLink2File:inputError', '\n%s', err_msg); | ||
end | ||
|
||
if nargin == 1 | ||
link_text = getFileFromPath(file); | ||
end | ||
|
||
file_link = sprintf('<a href = "matlab:open(''%s'')">%s</a>', file, link_text); | ||
|
||
end | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
function url_link = getLink2URL(url, link_text) | ||
% GETLINK2URL returns a link to an URL. | ||
% | ||
% This functions returns a link to an URL which, when clicked, opens the | ||
% URL using the 'web()' function with the system browser. | ||
% | ||
% Inputs: | ||
% url URL | ||
% link_text Displayed name of the link (optional) | ||
% | ||
% Outputs: | ||
% url_link Link to the URL | ||
% | ||
% See also: | ||
% WEB | ||
% https://mathworks.com/help/matlab/matlab_prog/create-hyperlinks-that-run-functions.html | ||
|
||
% Disclaimer: | ||
% SPDX-License-Identifier: GPL-3.0-only | ||
% | ||
% Copyright (C) 2024 Jonas Withelm | ||
% Copyright (C) 2024 TU Braunschweig, Institute of Flight Guidance | ||
% ************************************************************************* | ||
|
||
if nargin == 2 | ||
url_link = sprintf('<a href = "matlab:web(''%s'',''-browser'')">%s</a>', url, link_text); | ||
else | ||
url_link = sprintf('<a href = "matlab:web(''%1$s'',''-browser'')">%1$s</a>', url); | ||
end | ||
|
||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
function user_choice = getUserChoice(varargin) | ||
% GETUSERCHOICE allows the user to select one of the provided options via | ||
% the command line. | ||
% | ||
% Inputs: | ||
% prompt Prompt to be asked, character vector | ||
% options Selection options to be provided, cell array of | ||
% character vectors | ||
% | ||
% Outputs: | ||
% user_choice Index of the selected option | ||
% | ||
% See also: | ||
% GETUSERSELECTION, GETUSERCONFIRMATION | ||
|
||
% Disclaimer: | ||
% SPDX-License-Identifier: GPL-3.0-only | ||
% | ||
% Copyright (C) 2024 Jonas Withelm | ||
% Copyright (C) 2024 TU Braunschweig, Institute of Flight Guidance | ||
% ************************************************************************* | ||
|
||
% Input Parser | ||
p = inputParser; | ||
addRequired(p, 'prompt', @(a) ischar(a) || isstring(a)); | ||
addRequired(p, 'options', @(a) iscellstr(a) && numel(a) > 1); | ||
parse(p, varargin{:}) | ||
|
||
prompt = p.Results.prompt; | ||
options = p.Results.options; | ||
|
||
question = sprintf('%s (%s): ', prompt, strjoin(options, '/')); | ||
|
||
while true | ||
user_in = input(question, "s"); | ||
|
||
idxs = find(strcmpi(user_in, options)); | ||
|
||
if isempty(idxs) | ||
question = 'Wrong answer, please try again: '; | ||
elseif numel(idxs) == 1 | ||
user_choice = idxs; | ||
break; | ||
else | ||
error('Too many matches!'); | ||
end | ||
end | ||
|
||
end |
Oops, something went wrong.