I defined this simple class in Simulink, and I want to create and share a 5x5 matrix of this class.
classdef evidential_grid
properties
Occ
Libr
Incert
Conf
end
methods
function obj = evidential_grid() % Grid Constructor
obj.Occ = 0;
obj.Libr = 1;
obj.Incert = 0;
obj.Conf = 0;
end
end
end
In matlab, this code works to create a matrix of 5x5
myGrid(5,5) = evidential_grid();
As we know. Simulink does not accept dynamic allocation of variables, so I should initialize it first.
For that, I created
function fcn()
%#codegen
global MySharedVariable;
coder.extrinsic('evidential_grid');
MySharedVariable(5,5) = evidential_grid();
a matlab function in simulink
a block of Data Store Memory to share a variable of "evidential_grid" type
But when I executed my simulink model I got these errors!
Global declaration not resolved to a Data Store Memory block
registered via the Ports and Data Manager.
Errors occurred during parsing of MATLAB function
Please find me a solution,
Thank you.
There could be multiple issue with your code. First, in order to use global variables from MATLAB function block they need to be mapped to data store memory blocks. See the help page at https://www.mathworks.com/help/simulink/ug/using-global-data-with-the-matlab-function-block.html. You can do this by opening the "Edit data" option and adding your global variable and choosing the type as "data store memory". You can also checkout the example dsm_demo by running open_system([docroot, '/toolbox/simulink/examples/dsm_demo']).
You still cannot store output from extrinsic functions in this variable. In your case, I believe the best case would be to move your array of objects also to the extrinsic function and store it as either global or persistent data there and access the necessary properties as outputs of that function.
If you want to keep the data in simulink there are two ways to approach this. One is to make the class into a struct/bus type in Simulink and follow the data store approach. Here you would need to define your data store type as a simulink.signal object with datatype set to a bus object. If you have only 4 fields as you have shown the simpler route is to separate them into 4 different variable and have a separate data store memory for each one.
Related
I hate using global variables, and everyone should. If a language has no way around using global variables it should be updated. Currently, I don't know any good alternative to using global variables in Matlab, when efficiency is the goal.
Sharing data between callbacks can be done in only 4 ways that I am aware of:
nested functions
getappdata (what guidata uses)
handle-derived class objects
global variables
nested functions forces the entire project to be in a single m-file, and handle-derived class objects (sent to callbacks), gives unreasonable overhead last I checked.
Comparing getappdata/guidata with global variables, in a given callback you can write(assuming uglyGlobal exists as a 1000x1000 mat):
global uglyGlobal;
prettyLocal = uglyGlobal;
prettyLocal(10:100,10:100) = 0;
uglyGlobal = prettyLocal;
or you can write (assuming uglyAppdata exists as a 1000x1000 mat):
prettyLocal = getappdata(0,'uglyAppdata');
prettyLocal(10:100,10:100) = 0;
setappdata(0,'x',prettyLocal);
The above snippets should work in the same way. It could be (but is not guaranteed) more efficient with just:
global uglyGlobal;
uglyGlobal(10:100,10:100) = 0;
This snippet, unlike the previous ones, may not trigger a copy-on-write in Matlab. The data in the global workspace is modified, and (potentially) only there.
however, if we do the innocent modification:
global uglyGlobal;
prettyLocal = uglyGlobal;
uglyGlobal(10:100,10:100) = 0;
Matlab will ensure that prettyLocal gets its own copy of the data. The third line above will show up as the culprit when you profile. To make that worse on my brain(globals tend to do that), any other workspace that exists that has a local reference to the global, will make a copy-on-write trigger for that variable, one for each.
However, iff one makes sure no local references exists:
Is it true that global variables, used carefully can yield the best performance programs in Matlab?
Note: I would provide som timing results, but unfortunately I no longer have access to Matlab.
I am trying to amend the example given here for creating a dynamic masked subsystem, where I want to dynamically change the number of imports and outports to an S-Function.
I have a very simple S-Function implemented in C (it's the timestwo example in the documentation) and for which I wish the user to be able to define the number of inputs and number of outputs in a mask. The intention is then, within the S Function, to manipulate the received input values and write to the output values. The S-Function will eventually do some quite complicated stuff and I need multiple instances of it in Simulink, hence why I want it defined in a library.
I have put the S-Function into a library and unlocked it by choosing Diagram->Unlock Library.
I have defined 2 variables, numInports and numOutports in the Parameters & Dialog pane of the mask editing window.
I then add the following to the Initialization pane:
blocks = find_system(gcb,...
'LookUnderMasks','on',...
'FollowLinks','on',...
'RegExp', 'on',...
'BlockType', 'port');
if ~isempty(blocks)
Simulink.SubSystem.deleteContents(gcb);
end
for n=0:(numInports - 1)
label = sprintf('/In%d', n);
add_block('built-in/Inport',[gcb,label]);
end
for n=0:(numOutports - 1)
label = sprintf('/Out%d', n);
add_block('built-in/Outport',[gcb,label]);
end
The intention is for the initialisation to delete all imports and outports when the parameters are changed, then recreate them. I then save the model within the library.
The find_system() command should find and delete all blocks with port in the type, as suggested here and here.
I have created a model that uses this library model S Function implementation. However, when I update the parameters, I get the error:
Error in 'MyModel/MyLibrarySFunction': Initialization commands cannot be evaluated. Caused by:
A new block named 'MyModel/MyLibrarySFunction/In0' cannot be added.
Can anybody please advise what is going wrong here?
EDIT:
The documentation for find_system() has all as a valid parameter value, not the on I used and which was in the documentation example, but this seems to have no effect when I change it. I added:
msg = sprintf('Num blocks: %d', numel(blocks));
disp(msg);
just after the find_system() call and get 0 for the number of blocks found, so I guess the problem may be that In0 is not deleted and hence I am trying to reinsert it.
I have to work with a lot of data and run the same MATLAB program more than once, and every time the program is run it will store the data in the same preset variables. The problem is, every time the program is run the values are overwritten and replaced, most likely because all the variables are type double and are not a matrix. I know how to make a variable that can store multiple values in a program, but only when the program is run once.
This is the code I am able to provide:
volED = reconstructVolume(maskAlignedED1,maskAlignedED2,maskAlignedED3,res)
volMean = (volED1+volED2+volES3)/3
strokeVol = volED-volES
EF = strokeVol/volED*100
The program I am running depends on a ton more MATLAB files that I cannot provide at this moment, however I believe the double variables strokeVol and EF are created at this instant. How do I create a variable that will store multiple values and keep adding the values every time the program is run?
The reason your variables are "overwritten" with each run is that every function (or standalone program) has its own workspace where the local variables are located, and these local variables cease to exist when the function (or standalone program) returns/terminates. In order to preserve the value of a variable, you have to return it from your function. Since MATLAB passes its variables by value (rather than reference), you have to explicitly provide a vector (or more generally, an array) as input and output from your function if you want to have a cumulative set of data in your calling workspace. But it all depends on whether you have a function or a deployed program.
Assuming your program is a function
If your function is now declared as something like
function strokefraction(inputvars)
you can change its definition to
function [EFvec]=strokefraction(inputvars,EFvec)
%... code here ...
%volES initialized somewhere
volED = reconstructVolume(maskAlignedED1,maskAlignedED2,maskAlignedED3,res);
volMean = (volED1+volED2+volES3)/3;
strokeVol = volED-volES;
EF = strokeVol/volED*100;
EFvec = [EFvec; EF]; %add EF to output (column) vector
Note that it's legal to have the same name for an input and an output variable. Now, when you call your function (from MATLAB or from another function) each time, you add the vector to its call, like this:
EFvec=[]; %initialize with empty vector
for k=1:ndata %simulate several calls
inputvar=inputvarvector(k); %meaning that the input changes
EFvec=strokefraction(inputvar,EFvec);
end
and you will see that the size of EFvec grows from call to call, saving the output from each run. If you want to save several variables or arrays, do the same (for arrays, you can always introduce an input/output array with one more dimension for this purpose, but you probably have to use explicit indexing instead of just shoving the next EF value to the bottom of your vector).
Note that if your input/output array eventually grows large, then it will cost you a lot of time to keep allocating the necessary memory by small chunks. You could then choose to allocate the EFvec (or equivalent) array instead of initializing it to [], and introduce a counter variable telling you where to overwrite the next data points.
Disclaimer: what I said about the workspace of functions is only true for local variables. You could also define a global EFvec in your function and on your workspace, and then you don't have to pass it in and out of the function. As I haven't yet seen a problem which actually needed the use of global variables, I would avoid this option. Then you also have persistent variables, which are basically globals with their scope limited to their own workspace (run help global and help persistent in MATLAB if you'd like to know more, these help pages are surprisingly informative compared to usual help entries).
Assuming your program is a standalone (deployed) program
While I don't have any experience with standalone MATLAB programs, it seems to me that it would be hard to do what you want for that. A MathWorks Support answer suggests that you can pass variables to standalone programs, but only as you would pass to a shell script. By this I mean that you have to pass filenames or explicit numbers (but this makes sense, as there is no MATLAB workspace in the first place). This implies that in order to keep a cumulative set of output from your program you would probably have to store those in a file. This might not be so painful: opening a file to append the next set of data is straightforward (I don't know about issues such as efficiency, and anyway this all depends on how much data and how many runs of your function we're talking about).
I have a simulink model connected to my hardware and I am able to see the response on my scope when I change the setpoints in my model etc. But I will like to save this data from the scope so that later I can plot it.
I have read some documentation online but I am still confused. Can someone give me a step by step method on how to plot this data from the scope used in external mode.
Kind Regards
There is a write data to workspace block in simulink. You can put that block in the same bus as the scope and save the data to Matlab. If you want it automatically save into the disk, then I recommend to write a small .m script that takes this variable and saves in disk using save(). You can automatically run this .m file after the Simulink model is stopped (or some other condition you prefer) going to Properties->Callbacks and choosing the appropriate function callback.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Declaring a global variable in MATLAB
Currently my matlab code is in one big script file with no internal functions. I would like to have functions declared within my script, to make my code more readable and reuse code etc. This in itself is not difficult in matlab, e.g.
Example 1:
function main()
myfunc('goat');
end
function myfunc(x)
fprintf(x);
end
My problem is that I have a biig datafile, which I want to load only once, such that I can re-run my code during development without spending time on re-loading the data. This is not a problem in my current framework with one big script with no internal functions. One solution is to have two matlab script files. One for loading data and then calling the functions in another script.
However in the above example 1 a true global variable declaration will not work, and I am forced load the biig file every time I run the script. What I would like to do can be shown in two examples:
Example 2:
% Global variable
if ~exist('data',var)
data = load biigdatafile.mat; %FAILS, outside function.
end
function main()
myfunc('goat');
end
function myfunc(x)
fprintf(x);
end
Example 3:
function main()
% Global variable
if ~exist('data',var)
global data; % Is not really global after whole script is completed.
data = load biigdatafile.mat;
end
myfunc('goat');
end
function myfunc(x)
fprintf(x);
end
So my question is how to declare a true global variable as in example 2, where I load my data once to stay in workspace, while calling my functions inside one script?
Use input arguments, that's what they're made for
You could just use arguments to the main function, load the dataset once into the base workspace and call your function with that dataset as an argument. If any subfunctions also use the dataset, pass it along
function main(data)
if nargin<1
disp('hey, you forgot to supply the dataset!');
end
% do your stuff
showData(data);
end
and then in the base workspace:
Data = load('biigdatafile.mat');
main(Data);
Use persistent variables
persistent X Y Z defines X, Y, and Z as variables that are local to the function in which they are declared; yet their values are retained in memory between calls to the function. Persistent variables are similar to global variables because the MATLAB software creates permanent storage for both. They differ from global variables in that persistent variables are known only to the function in which they are declared.
So you could easily use:
function main()
persistent data;
if isempty(data)
disp('loading dataset');
data=load('biigdatafile.mat');
end
% do your stuff
showData(data);
end
First time you call this function on a cleared base workspace or cleared function*, the dataset will be loaded. Every next time (when the function hasn't been edited), the dataset will already/still be in memory.
I usually do this when I'm just using one dataset; it's tedious to always load the dataset and when testing a function, it's also easier to just press F5.
* when is a function cleared you might ask?
Whenever you clear or modify a function that is in memory, MATLAB also clears all persistent variables declared by that function. To keep a function in memory until MATLAB quits, use mlock.
Global variables have to be declared everywhere they are used. Just add the global data to whereever you need it, and it will work.
It is not a duplicate of declaring global variables in matlab. A global var is only accesible to all functions, but when the script is complete, the global variables are gone and I need to read them into memory again.
What I need is to move the local variable into the base workspace and then access it again during other function calls. I actually solved it myself, just now with this code
function main()
try
Data = evalin('base','Data'); % Move back from base workspace
fprintf('Already loaded...\n');
catch
fprintf('Loading data...');
data = load biigdatafile.mat;
assignin('base', 'Data', Data); % Move to base workspace
fprintf('Ok\n');
end
showDocID(Data{1});
end
function showData(Data)
fprintf(['Data: "' Data '"\n']);
end