How to programmatically configure the tunability of model parameters? - matlab

I'm porting a large Simulink model from Simulink R2010a → R2017b.
The main model is basically a glue-layer for many interwoven reference models. My objective is to generate a standalone executable out of this main model using Coder.
Parameter tunability in this context is not done via the Signals and Parameters section on the Optimization tab in the Model Configuration Parameters dialog (as is the case in stand-alone models), but rather, via constructing Simulink.Parameter objects in the base workspace, and referencing those in the respective referenced models, or in their respective model workspaces.
Now, AFAIK, in R2010a it was enough to set
new_parameter.RTWInfo.StorageClass = 'Auto';
new_parameter.RTWInfo.CustomStorageClass = 'Define';
to make the parameter non-tunable and convert it into a #define in the generated code. In R2017b, this is no longer allowed; the StorageClass must be 'Custom' if you set a non-empty CustomStorageClass:
new_parameter.CoderInfo.StorageClass = 'Custom'; % <- can't be 'Auto'
new_parameter.CoderInfo.CustomStorageClass = 'Define';
But apparently, this does not make the parameter non-tunable:
Warning: Parameter 'OutPortSampleTime' of '[...]/Rate Transition1' is non-tunable but refers to tunable variables (Simulation_compiletimeConstant (base workspace))
I can't find anything in the R2017b documentation on making parameters non-tunable, programatically; I can only find how to do it in stand-alone models via the dialog, but that's not what I want here.
Can anyone point me in the right direction?
NOTE: Back in the day, Simulink Coder was called Real-Time Workshop (well, Real-time Workshop split into Coder and several other things), hence the difference RTWInfo vs. CoderInfo. Note that RTWInfo still works in R2017b, but issues a warning and gets converted into Coderinfo automatically.

In generated code it should appear as #define, the way you specified it.
https://www.mathworks.com/help/rtw/ug/choose-a-built-in-storage-class-for-controlling-data-representation-in-the-generated-code.html
Btw, yes, it's a bit confusing, because in m-file you specify CustomStorageClass = 'Define';, in GUI you specify Storage class as Define (custom), but in documentation they say Storage Class as Defined.
I am not sure why warning about tunability shows up.

Related

How to extract an MSL model, modify the code, and use locally?

I am interested to replace my own PID-regulator models with MSL/Blocks/Continuous/LimPID. The problem is that this model restricts limitations of output signals to be parameters and thus do not allow time-varying limits, which I need to have.
Studying the code I understand that the output limitation is created by a block MSL/Blocks/Nonlinear/Limiter and I just want to change this to the block VariableLimiter.
I can imagine that you need to ensure that changes of output-limitations vary in a time-scale slower than the regulator in order to not excite unwanted behaviour of the controller. Still here is a class of problems where it would be very useful to allow this limits to vary slowly.
Thanks for the good input to my question and below a very simple example to refine my question. (The LimPID is more complicated and I come back to that).
Let us instead just modify the block Add to a local block in MyModel.
I copy the code from Modelica.Blocks.Math.Add and call it Addb in MyModel. Since here is a dependence of Interfaces.SI2SO I need to make an import before the extends-clause. This import I take from the ordinary general MSL package, instead of copying also that in to MyModel. Then I introduce a new parameter "bias" and modify the equation. The annotation may need some update as well but we do not bother with that now.
MyModel
...
block Addb "Output the sum of the two inputs"
import Modelica.Blocks.Interfaces;
extends Interfaces.SI2SO;
parameter Real k1=+1 "Gain of input signal 1";
parameter Real k2=+1 "Gain of input signal 2";
parameter Real bias=0 "Bias term";
equation
y = k1*u1 + k2*u2 + bias;
annotation (...);
end Addb;
MyModel;
This code seems to work.
My added new question is whether it is enough to look up "extends-clauses" and other references to MSL and make the proper imports since the code is now local, or here are more aspects to think of? The LimPID code is rather complex with procedures for initialization etc so I just wonder if here is more to do than just bring in a number of import-clauses?
The models in Modelica Standard Library (MSL) should only be seen as exemplary models, not covering all possible applications. MSL is write protected and it is not possible to replace the limiter block in LimPID (and add max/min input connectors). Also, it wouldn't work out if you shared your simulation model with others, expecting their MSL to work like your modified MSL.
Personally, I have my own libraries of components where MSL models are inadequate. For example, I have PID controllers with variable limits, manual/automatic functions and many more functions which are needed in my applications.
Often, I create a copy of an MSL model, place it in the same package in my own library and make the necessary modifications and additions, e.g. MyLibrary.Blocks.Continuous.PID.

Subsystem Parameters Always Mapped to Global Variables in Code Generated by Matlab/Simulink Embedded Coder

For a simple test setup, we want to generate C code from a Simulink subsystem, which has several configuration parameters defined in its block mask. The environment shall be able to modify these parameters and the input signals, and to evaluate the output signals for several instances of the subsystem's code representation.
Expected Outcome
The code generation is expected to provide structure declarations for model, parameters, inputs, and outputs in the generated code, which can be instantiated and initialized (parameters, inputs) by the environment, and passed to the generated functions as pointers. Functions should only depend on these passed arguments.
However, even after several hours of investigation, the generator still puts the configuration parameters into one global variable, which is directly accessed by the generated functions, what makes instance-specific configuration impossible.
Attempts
Only the following Model Settings turned out as useful on the newest release R2022a:
Optimization.Default parameter behavior = Tunable
Code Generation:
Code Interface.Code Interface Packaging = Reusable function
Pass root level I/O as = Structure reference
Result
After generating code for subsystem X, declarations for all structures are available; model M, inputs U and outputs Y are passed by reference to the functions, for example:
void X_step (RT_MODEL_X_T *const X_M, ExtU_X_T *X_U, ExtY_X_T *X_Y) {
...
... X_P.X_someParam ...
}
However, the parameter structure is still accessed as a global variable X_P. Instead, the parameter structure should be also passed as a pointer either explicitly or as part of the model structure, so that it can be used as X_P->someParam.
Is there any way to achieve this behavior?
History
Years ago, in Release 2013b, this already worked smoothly:
The model structure contained a substructure called ModelData which in turn contained
the field P_X_T defaultParam. These parameters were passed to the functions as part of the model structure and thus could be made instance-specific. This worked out of the box with a few standard settings (no storage classes or other sophisticated configurations). Is this feature removed or just hidden?

Simulink code generation: set tunable parameters programmatically

I use Simulink Coder to generate code from a huge model. I use a rsim target with tunable parameters to be able to give the executable variable inputs via a parameter file.
I can specify which model parameters should be tunable (by default all parameters will be in-lined in generated code on compile time) via the code generation settings:
code generation options > optimization > signals and parameters > configure default parameter behavior
Here I can manually choose from all workspace variables the ones I want to be globally tunable:
Q: Is there a way to add a variable (given its name) to this list programmatically?
For example if a have list of 50 variables i would want to add them to the tunables list, via a MATLAB script without having to add every single one manually. Or loop over the list and set the tunable setting on each one.
I can generate a parameter struct which contains a list of tunable parameters using rsimgetrtp('model_name'). But I was not able to find a function to actually set the parameters in the first place.
I use Matlab 2015b for this, since its legacy code.

When to use "to workspace" block vs "outport" block

I can use both blocks for getting output from simulink to matlab, but if there are two of them there should be difference in the way they are used but I can not figure it out.
Using an Outport block allows you to,
use your model as a Model Reference
when generating code (using Simulink Coder) from the model, interface the model with other code
If you're not needing to do either of the above - for instance you only want to dump data to the MATLAB Workspace - then the To Workspace block is arguably easier to use. Plus it shows the user what the resulting variable will be without them having to open the model properties window.
Note also that To Workspace can be used at any level of model hierarchy, whereas Outport can only be used to get data out of the highest level of a model. (Outport are used in SubSystems but to interface a sub-level of a model to a higher level, not to get data out of the model.)

Impossible to tune Simulink Parameter at simulation time

I have a problem. I have an embedded function in my simulink model which has a structure (struct) as parameter. It contains only numerical values and I generate an S-Function of the embedded function by right clicking on the block and C/C++ code --> Generate S-function.
I then have the compiled block, if I try to change some values of my struct nothing changes (the fields of my struct stay the same as when I first compiled my embedded function).
When I compiled the embedded function block I selected the parameter to be tunable. I selected the parameter to be tunable in the Model Explorer. I tried to follow this video tutorial by mathworks: http://fr.mathworks.com/videos/tunable-structure-parameters-68947.html (The video is for r2010a while I am at r2015b) It is a bit different the interface in r2015b (from the one in the video) but when I click on Configure , like the guy does in the video, nothing happens.
Could you help me please?
Thanks a lot.
Once I had also decided to reduce the number of tunable parameters by checking the 'inline parameters' checkbox and then specifying the exception variables (variable that have the permission to be tunable even when 'inline parameters' is turned on. It did not work.
In case you aim does not heavily rely on optimization, it would be better if you simply turn off 'inline parameters'.
After that, the constant blocks (i suppose you are giving the input to your s-function from constant blocks) will become tunable.
Another advice: add mex in the init function of your model callbacks. It will save you from getting weird output (usually due to uncleared/un-reset variables from previous runs).
Hope it helps!