Create a list of all current variables and their respective values in FMIKit-Simulink - simulink

I am currently using FMIKit for Simulink found here https://github.com/CATIA-Systems/FMIKit-Simulink
From the documentation it works very well to query values of parameters within the FMU using FMIKit.getStartValue(FMUBLOCK, 'Variablename');
but only if you know the name and structure of the variable you are looking for.
I wanted to know if there is a way to extract the full list of variables in the FMU together with their values just before I start the simulation (for sim debugging purposes)?

You can get the start values of the model variables by reading the model description of the FMU (e.g. the VanDerPol.fmu from the FMI 2.0 Test FMUs):
% import the FMU and select the FMU block
% set a different start value for variable "mu"
FMIKit.setStartValue(gcb, 'mu', '1.3');
% read the model description (returns a Java object)
md = FMIKit.getModelDescription('VanDerPol.fmu');
% iterate over the list of variables
for i = 1:md.scalarVariables.size
v = md.scalarVariables.get(i-1);
% get the name and start value
name = char(v.name);
% get the start value from the FMU block
start = FMIKit.getStartValue(gcb, name); % might be empty
disp([name ': ' start])
end
gives you
x0: 2
der(x0):
x1: 0
der(x1):
mu: 1.3

Related

Separate definition of constant values and dependent parameters in Matlab

In my code, I have a lot of constant values and parameters that take significant space in my code.
For example in C++, I would make a header and a separate file where I would define these parameters as, e.g., "const-type" and share the header with main or other .cpp files.
How do you keep such structuring in MATLAB, is it worth it?
An example: Coefficients.m looks as follows:
classdef coefficients
properties(Constant)
% NIST data
A_N = 28.98641;
end
end
Another file: Gas.m where I would like to use A_N looks as follows:
function Gas()
clear all
clc
import Coefficients.* % Does not work
% A simple print
Values.A_N % Does not work
coefficients.A_N % Does not work
Constant.A_N % Does not work
end
Ok so assuming the class coefficients defined as:
classdef coefficients
properties(Constant)
% NIST data
A_N = 28.98641;
end
end
This code must be saved in a file named coefficients.m (The class name and file name have to match to avoid weird effect sometimes).
Then assuming the following Gas.m file:
function Gas()
% Usage with "disp()"
disp('The A_N coefficient taken from NIST data is:')
disp(coefficients.A_N)
% Usage with fprintf
fprintf('\nFrom NIST data, the coefficient A_N = %f\n',coefficients.A_N)
% Usage in calculation (just use it as if it was a variable/constant name
AN2 = coefficients.A_N^2 ;
fprintf('\nA_N coefficient squared = %.2f\n',AN2)
% If you want a shorter notation, you can copy the coefficient value in
% a variable with a shorter name, then use that variable later in code
A_N = coefficients.A_N ;
fprintf('\nA_N coefficient cubed = %.2f\n',A_N^3)
end
Then running this file (calling it from the command line) yields:
>> Gas
The A_N coefficient taken from NIST data is:
28.98641
From NIST data, the coefficient A_N = 28.986410
A_N coefficient squared = 840.21
A_N coefficient cubed = 24354.73
Or if you simply need to access the coefficient in the Matlab console:
>> coefficients.A_N
ans =
28.98641
Now all these examples assume that the class file coefficient.m is visible in the current Matlab scope. For Matlab, it means the file must be in the MATLAB search path (or the current folder works too).
For more info about what is the Matlab search path and how it works you can read:
What Is the MATLAB Search
Path?
Files and Folders that MATLAB
Accesses
In your case, I would make a folder containing all these sorts of classes, then add this folder to the Matlab path, so you never have to worry again about individual script, function or program calling for it.
See this link for tips on using a class definition for this. Highlights of the tips are:
Properties can be accessed directly to get the value
Properties can be added that give the units of the constant (highly advised!)
Comments can be added that act as help text for the constants
The doc command automatically creates a reference page for this classdef
E.g.,
classdef myconstants
properties(Constant)
% g is the gravity of Earth
% (https://en.wikipedia.org/wiki/Gravity_of_Earth)
g = 9.8;
g_units = 'm/s/s';
% c is the speed of light in a vacuum
c = 299792458;
c_units = 'm/s';
end
end
>> help myconstants.g

Reading multiple numbered data variables from the workspace

For reading time-based data of variables from the Matlab workspace in Simulink (for time-based inter- and extrapolation), a typical solution is the use of the From Workspace block, by e.g. providing variable input data var in the following structure format:
var.time=[nx1]
var.signals.dimensions=m
var.signals.values=[nxm]
for providing the data of m variables with n time-based samples. Since variables' data is stored in a single matrix, it is implied that all variables are required to have the same (number of) time stamps.
If this is not the case, a solution could be the use of multiple From Workspace blocks, and corresponding variable input data structs (e.g. varA, varB, varC, etc.), like so:
However, this solution requires the number of variables to be fixed for all simulations. In my case, variables are numbered (rather than named) and the number of variables might not be the same from one simulation to the next. As such, for generalization purposes, I would like to find a solution without having to change the simulation file. A first step in this direction is the use of a struct array (i.e. var(1), var(2), var(3), etc.), which works:
A candidate next step is then to use a For Iterator to loop over N variables (and then to assign and concatenate the output in some output array, which I know can be done and is not the focus here):
The problem here is that the index id can't be fed to the From Workspace block! I ran into an identical issue when trying to solve the problem with a lookup table block. How to solve this problem of reading multiple but varying number of data variables from the workspace with different (number of) time stamps? Solutions that don't use a From Workspace or lookup table block are welcome too.
Here is equivalent code for running the whole thing in Matlab instead of Simulink:
% DEFINED IN MATLAB:
% Examplary input of variable data with different time stamps, according to
% Simulink structure conventions (.time, .signals etc)
N=3; % number of variables
for id=N:-1:1
var(id).time = linspace(0,2,id*2+2)';
var(id).signals.dimensions = 1;
var(id).signals.values = sin((var(id).time-id)*pi/2)';
end
% TO BE EXECUTED IN SIMULINK:
% the simulink clock time:
t = 1.234; % random time
for id=N:-1:1
var_t(id) = interp1(var(id).time,var(id).signals.values,t);
end
And here a figure to illustrate the results:
% Figure code:
figure(1),clf
colors=lines(N);
for id=1:N
plot(var(id).time,var(id).signals.values,'*-','color',colors(id,:)),hold on
plot(t,var_t(id),'o','color',colors(id,:))
end
xlabel('time'),ylabel('variable data')

How can I create my own parameters or attributes for a block in simulink?

In this case I am trying to create a new block parameter as a new property to save a specific new data which I don't want to be saved in a defalut parameter which is already reserved for other diffrent related datas
for this parameter I want to use the command get_param and set_para that need to be alreday existed
I mean with default parameters , those .
https://edoras.sdsu.edu/doc/matlab/toolbox/simulink/slref/parameters2.html#7515
Programmatically create masks
I'm not sure this is exactly what you are searching for, but I made an example on how to create programmatically a mask via script in MATLAB/Simulink. I will not use get_param/set_param, even if it is possible to obtain the same results using those commands. We will go with the Simulink object that is simpler and more clear (at least IMHO).
For our playground lets create this simple subsystem (block) with a simple constant that gives in output the name of a variable named a that we want to take from the mask:
Look at the address of this block. My simulink model is mask.slx, thus I can address this subgroup with the address mask/block (upper left corner of the viewport), as you can see here:
At this point we can use the following code to add an edit parameter box for the subgroup, which fixes the value of a:
clc
clear all
% The subgroup for which we want to programmatically create a mask
block_name = 'mask/block';
% Now we can create the mask parameter programmatically as you requested
% There are two way: the old one using get_param and set_param and a more
% clear one using the Simulink interface.
% I will go with thw second one, since it is really more straightforward
% with respect to the first one.
% The first think to do is to create the mask itself
% If the mask already exist, we would get an error, thus we can avoid it by
% checking if it already exist. This is something that you should check out.
mask_hdl = Simulink.Mask.create(block_name);
% mask_hdl = Simulink.Mask.get(block_name); % For use an existing mask
% Now we are ready to create the mask parameters:
edit_a_hdl = mask_hdl.addParameter( ...
'Type', 'edit', ...
'Prompt', 'Sets constant variable', ...
'Name', 'a');
edit_a_hdl.Value = '10';
Running the script the code will be masked and the variable will be set, as you can see here:
There are more information on this topic here.
Setup parameters programmatically for masked Block
Now lets say you have the playground as before done and you have the subgroup masked as in the last image. You can set its value in the mask programmatically (or get it) through the get_param and set_param as follows:
value = get_param(block_name, 'a');
value = str2double(value); % Values should always be string!
% Thus we must convert it
set_param(block_name, 'a', sprintf('%d', value * 100));
and as you can see the value has now been updated:
Again, you can achieve the same result by using the Simulink object.
mask_hdl = Simulink.Mask.get(block_name);
edit_a_hdl = mask_hdl.Parameters(1); % We know its position in the struct array
value = str2double(edit_a_hdl.Value);
value = value * pi;
edit_a_hdl.Value = sprintf('%f', value);
and, as you can see, we have our new value:
Simulink blocks in many toolboxes are created using MATLAB System objects. If you want to create a new parameter for an existing Simulink block, you may want to create a public property in the shipped System object code. If you are creating your own Simulink block, then writing your code in MATLAB system objects will be very friendly to change/create parameters as you wish.
Simulink extension system object can be created as follows:
To create a Simulink block from a System object, create "MATLAB system" block from the existing Simulink blocks and call your system object from the MATLAB system.
All public properties in the system object code are visible in Simulink mask dialog as shown in below picture.
Hope this is what you are looking for.

matlab model -- access base workspace variables

I am running my test.m file to create variables in my base work space. This is the content of my test.m file :--
a=10; % define a variable with particular value
b=20; % define a variable with particular value
c=0; % define a variable with particular value
In my MATLAB model now i am trying to access the variables a & b. But it is returning me the value zero for both a & b.
I am using a function call generator to trigger a model every 10 msec.
Solver type : Fixed Step
Solver : Discreate(No Continous states)
Why i am not able to access the workspace variables in my simulink model.
Please see the attached print shot.
You are using an Inport and you named it with the variable name but it does not affect the variable to it, it is only a port. Try using the Constant block and set it to your variable name ("a" for example)

Matlab function to pass a vector into simulink using 'fromworkspace'

I would like to write a matlab function that wraps around a simulink block. The function should load data into the simulink model, run it, then return the data back from the function.
The only way I can think of doing this is by using the 'To Workspace' and 'From Workspace' blocks in simulink. The problem is that the 'From Workspace' block doesn't pick up variables from the function scope, only from the workspace scope.
Below is the only solution I could come up with, which basically converts the incoming vector to a string, and then creates a function which gets called when the model starts (effectively this is just as bad as eval).
Here is the code:
function [ dataOut ] = run_simulink( dataIn )
% Convert data to a string (this is the part I would like to avoid)
variableInitString = sprintf('simin = %s;', mat2str(dataIn));
% we need both the name and the filename
modelName = 'programatic_simulink';
modelFileName = strcat(modelName,'.slx');
% load model (without displaying window)
load_system(modelFileName);
% Set the InitFcn to the god awful string
% this is how the dataIn actually gets into the model
set_param(modelName, 'InitFcn', variableInitString);
% run it
sim(modelName);
% explicity close without saving (0) because changing InitFcn
% counts as changing the model. Note that set_param also
% creates a .autosave file (which is deleted after close_system)
close_system(modelName, 0);
% return data from simOut that is created by simulink
dataOut = simout;
end
And you run it like this: run_simulink([0 0.25 0.5 0.75; 1 2 3 4]') where the first part of the matrix is the time vector.
Finally here is the underlying simulink file with the workspace block properties open for completeness.
(If the image is fuzzy, click to enlarge)
Is there a more clean way to do this without the mat2str() and sprintf() ? The sprint line takes forever to run, even with vectors of size 50k.
It depends which version you are using. In recent version, you can specify the workspace to use as part of the call to the sim function, e.g.:
sim(modelName,'SrcWorkspace','current'); % the default is 'base'
For more details, see the documentation on sim. In older versions (not sure exactly when this changed, some time around R0211a or R0211b I think), you had to use simset, e.g.:
myoptions = simset('SrcWorkspace','current',...
'DstWorkspace','current',...
'ReturnWorkspaceOutputs', 'on');
simOut = sim(mdlName, endTime, myoptions);
Update
To return data back from sim in R2014b, you need to use an output argument when calling sim, which contains all the simulation outputs, e.g.:
simOut = sim(modelName,'SrcWorkspace','current'); % the default is 'base'
simOut is a Simulink.SimulationOutput object containing the time vector, the logged states and outputs of the model.