use argument to system object in matlab code generation - matlab

I'm tring to use system object for my generated matlab code (.mex)
here is the function.
function [ ] = filereaderTest( videofile )
fileReader = vision.VideoFileReader(videofile);
while ~isDone(fileReader)
step(fileReader);
% do something
end
release(fileReader);
end
when I try codegen filereaderTest -args videofile , error occurs.
It says "fail to compute constant value for constructor arguement #1. To generate code, all argument for System Object constructor should be constant. ..."
To use VideoFileReader, must pass file name to its constructor.
So, here is my question: there is any way to use this function to any files? for example:
filereaderTest.mex(video1);
filereaderTest.mex(video2); % video1 and video2 are different

What you are trying to do is not possible. The documentation states clearly:
Set arguments to System object™ constructors as compile-time constants.
(1)

Related

How to test arguments for a figure or axis object in MATLAB 2022?

A function receives a figure or axis object object as parameter.
I want to test this as shown in the FIXME line.
Which test should be used here in order to allow all valid objects for exportgraphics?
% myexportgraphics.m
function myexportgraphics(f)
arguments
f (1,1) {}; % FIXME add a test here
end
exportgraphics(f,...);
end
This full list of validation functions is documented here:
https://uk.mathworks.com/help/matlab/matlab_prog/argument-validation-functions.html
The only relevant one for checking the input type (other than ones for specific types like "double") is mustBeUnderlyingType
You can check which types are valid using underlyingType on example objects you want to accept.
underlyingType( figure() ); % 'matlab.ui.Figure'
underlyingType( axes() ); % 'matlab.graphics.axis.Axes'
So this would check for figures
function myexportgraphics(f)
arguments
f (1,1) {mustBeUnderlyingType(f,'matlab.ui.Figure')};
end
end
However, that doesn't allow multiple variable types, so per the docs you probably want to make your own validation function
function myexportgraphics(f)
arguments
f (1,1) {mustBeExportGraphicsType(f)};
end
end
function mustBeExportGraphicsType(g)
if ~ismember( class(g), {'matlab.ui.Figure','matlab.graphics.axis.Axes'} )
eidType = 'mustBeExportGraphicsType:notExportGraphicsType';
msgType = 'Input must be a figure or axes object';
throwAsCaller(MException(eidType,msgType));
end
end
These are the requirements for a custom validation function, emphasis mine:
Functions used for validation have these design elements:
Validation functions do not return outputs or modify program state. The only purpose is to check the validity of the input value.
Validation functions must accept the value being validated as an input argument. If the function accepts more than one input argument, the first input is the value to be validated.
Validation functions rely only on the inputs. No other values are available to the function.
Validation functions throw an error if the validation fails. Using throwAsCaller to throw exceptions avoids showing the validation function itself in the displayed error message.
Creating your own validation function is useful when you want to provide specific validation that is not available using the MATLAB validation functions. You can create a validation function as a local function within the function file or place it on the MATLAB path.
As an aside, you could use ishghandle within the custom validation function which returns true for figure and axes inputs. If you didn't use the arguments validation syntax, you could instead use ishghandle with the slightly older inputParser approach to input validation, or a simple assert near the start of your function, but that's probably beyond the scope of this question.

How do I get the value of a Simulink struct from the workspace within a MATLAB function?

I need to access the values of variables in MATLAB's workspace of type Simulink.parameter:
CAL_vars = dsdd('find','/path/CAL','ObjectKind','Variable','Property',{'name' 'Class' 'value' 'CAL'})
%gets ids of variables in data dictionary
i = 10
for i=1:length(CAL_vars)
var_name = dsdd('GetAttribute',CAL_vars(i),'name');
% gets names of variables in data dict
var_eval = eval(var_name); % this works in standalone script and it does exactly
% what I need, but once i put it in the function I need this for, it returns error
if (length(var_eval.Value) ==1)
if (var_eval.Value == true)
var_eval.Value = 1;
elseif (var_eval.Value == false)
var_eval.Value = 0;
else
end
end
% do something with the Value
if (errorCode ~= 0)
fprintf('\nSomething is wrong at %s\n', var_name)
end
end
The problem arises because the structs are of made by Simulink and give error, when I try to call eval(name_of_var): Undefined function 'eval' for input arguments of type 'Simulink.Parameter'.
Curiously, it seems to function properly in a stand-alone script but once I plug it into the larger function, it stops working and starts displaying error saying
Error using eval
Undefined function or variable 'name_of_var'.
The function is clearly in the workspace.
Curiously, it seems to function properly in a stand-alone script but
once I plug it into the larger function, it stops working
This is the expected behaviour. A function has its own workspace and can't directly access variables in the base workspace.
You could try using evalin instead of eval, and specify the base workspace:
evalin(ws, expression) executes expression, a character vector or
string scalar containing any valid MATLAB® expression using variables
in the workspace ws. ws can have a value of 'base' or 'caller' to
denote the MATLAB base workspace or the workspace of the caller
function.
In general though, there are lots of reasons for trying to avoid using eval if at all possible (see the MATLAB help for eval) and it would be best if you could find a different way of getting this data.

Avoiding eval in matlab function

I use the symbolic toolbox in matlab to generate some very long symbolic expressions. Then I use matlabFunction to generate a function file.
Say there are three parameters: p1, p2 and p3.
I have a cell with strings {'p1', 'p2', 'p3'}.
In the derivation of the model I generate symbolic variables p1, p2 and p3 out of them using eval in a loop and stack them in a vector par.
Then when in matlabFunction, I specify par as input.
Moreover, I save the cell string in a .mat file.
Then when I want to simulate this model, I can construct this parameter array using that cell of strings from the .mat file out of 30 available parameters and their values.
Advantages: No need to keep track of the different parameters if I add one to . I can change the order, mess around, but older models still work.
Disadvantage:
Turning things into a function file leads to this error (psi is one of the parameters):
Error: File: f_derive_model.m Line: 96 Column: 5
"psi" previously appeared to be used as a function or
command, conflicting with its use here as the name of a
variable.
A possible cause of this error is that you forgot to
initialize the variable, or you have initialized it
implicitly using load or eval.
Apparently some unnescescary checking is going on because the variable will be intialized in an eval statement.
Question: How can I avoid eval but keep the list of parameters indepent from the model stuff.
Code deriving the long equations:
% Model parameters
mdl.parameters = {'mp','mb','lp','lb','g','d','mP','mM','k','kt'};
par = [];
for i=1:length(mdl.parameters)
eval(strcat(mdl.parameters{i}, '=sym(''', mdl.parameters{i}, "');"));
eval(sprintf(['par = [par;' mdl.parameters{i} '];']));
end
%% Calculate stuff
matlabFunction(MM,'file',[modelName '_mass'],'vars',{par},'outputs',{'M'});
Code using the generated file:
getparams
load('m3d_1')
par = [];
for i=1:length(mdl.parameters)
eval(sprintf(['par = [par;params.' mdl.parameters{i} '];']));
end
See how, as long as I specify the correct value to for example params.mp, it always gets assigned to the input corresponding to the symbolic variable mp in the par vector. I do not want to lose that and have to keep track of the order and so on, nor do I want to call my functions with all the parameters one by one.
Actually, I see nothing wrong in your approach even if the "public opinion" affirms that it's better to avoid using the eval function. An alternative would be using the assignin function as follows:
% use 'caller' instead of 'base' if this code runs within a function
for i = 1:numel(mdl.parameters)
var_name = mdl.parameters{i};
assignin('base',var_name,sym(var_name));
end
In the second case (the one concerning the par variable) I would instead use the getfield function:
par_len = numel(mdl.parameters);
par = cell(par_len,1);
for i = 1:par_len
par{i} = getfield(params,mdl.parameters{i});
end
or, alternatively, this approach:
par_len = numel(mdl.parameters);
par = cell(par_len,1);
for i = 1:par_len
par{i} = params.(mdl.parameters{i});
end

Creating a function handle to an overloaded `end` function

MATLAB allows overloading various operators for custom classes. One of the unlisted overloadable operators is end, as can be learned from \matlab\lang\end.m:
% END(A,K,N) is called for indexing expressions involving the object A
% when END is part of the K-th index out of N indices. For example,
% the expression A(end-1,:) calls A's END method with END(A,1,2).
An example of such a method is table.end (paste in the MATLAB command line and press "Open Selection" to go to its definition; it is defined in ...\matlab\datatypes\#tabular\end.m).
Unlike a normal method, one cannot simply write hEnd = #end, because this gives the error:
>> hEnd = #end;
hEnd = #end;
↑
Error: Illegal use of reserved keyword "end".
On the other hand, writing e = str2func('end'); works, but it links to the default end function (even when temporarily switching to the folder where the desired end.m is found).
Failed attempts include str2func('table>end');, str2func('table\end');, str2func('table.end'); and #(a,b,c)table.end(a,b,c);.
My question: How do I create a handle to the end function of a specific class?
Overloading — If the function you specify overloads a function in a class that is not a fundamental MATLAB class, the function is not associated with the function handle at the time it is constructed. Instead, MATLAB considers the input arguments and determines which implementation to call at the time of evaluation.
Function handles store their absolute path, so when you have a valid handle, you can invoke the function from any location. You do not have to specify the path to the function when creating the handle, only the function name.
so if your 'end' function is in matlab path , matlab consider it as a candidate for evaluation depending on the inputs,in your case if input object is of 'table' class type the feval(str2func('end'),i,j) evaluate the end function which is defined in the folder #table/end.m

Use workspace variables in a Matlab function

I'd like to use the data that are loaded to my workspace in a Matlab function. This is the beginning of my function.
function [totalProfit] = compute(p,exit)
%% Declaration of variables
entry=0;
T = length(data);
.
.
.
end
I'm getting an error:
Undefined function or variable 'data'.
Where is the error?
The variable data was probably defined outside of the function, so it is out of scope.
Pass data as a parameter to compute and then it will be available inside the function.
You can use evalin to work with variables from another workspace. In your example this could be
T = evalin('caller','length(data)')
But please note that in most cases you get cleaner code if you define the variable as input argument for the function. So for your case this would be
function [totalProfit] = compute(p,exit,data)
T = length(data) ;
end
Ran is correct, but I wanted to mention something else. In general, only variables that are passed as arguments to a function are able to be used inside that function, so if you want to use your existing variables inside the function, pass them as input arguments.
It is possible to create global variables which allow you to use them inside functions without passing them as arguments, but it's usually not the best way of writing code. The times where I have used global variables are where I am calling multiple functions from a single script, and I have some constants that will be used by all the functions (for example gravity is a common one). An alternative to global variables is to use a struct, with the variables you want to pass to the function in it, so you only need one extra input argument, but you still have to be a bit careful.