- the parameter must be in the model workspace (not in the base workspace or a data dictionary)
- the parameter must be a model argument
- the parameter must define use a storage class not equal to "auto" ("Model default" for example)
Embedded Coder providing incompatible, non-reusable code.
2 views (last 30 days)
Show older comments
Will Coulter
on 25 Nov 2020
Commented: Nicolas Schoonbroodt
on 5 Dec 2020
I'm trying to move from MATLAB R2018b to R2020a (and then R2020b). However, some models are no longer generating the same, reentrant code as they were before.
In R2018b, the following reusable code was generated (copied from the in-application help, of which a screenshot will is attached):
/* Real-time Model Data Structure */
struct tag_RTM_rtwdemo_roll_T {
const char_T *errorStatus;
B_rtwdemo_roll_T *blockIO;
P_rtwdemo_roll_T *defaultParam;
ExtU_rtwdemo_roll_T *inputs;
ExtY_rtwdemo_roll_T *outputs;
boolean_T paramIsMalloced;
DW_rtwdemo_roll_T *dwork;
};
Note in the above, that defaultParam was a member in the Model data structure. This allows different instances of this model to run with the correct, tuned parameters.
Newer code makes the parameters independent of the model instance. This means that tuning parameters are shared between unrelated code execution instances. The new documentation now matches the new behavior -- https://www.mathworks.com/help/rtw/ug/how-generated-code-stores-internal-signal-state-and-parameter-data.html.
How can I keep the original behaviors and migrate to R2020a, which I believe was correct? Is there an explanation for why this was changed?
0 Comments
Accepted Answer
Nicolas Schoonbroodt
on 30 Nov 2020
Hi,
There are two questions here, one technical (How can I get the same behaviour as before?) and one more "philosophical" (Why did it change?)
So for the first question, I think that one way to have the desired code is to define the parameter as a model argument with a non-auto storage class to have the same behaviour as before (having the parameter as part of the data structure)
To do that, you would need to do the following
For the second question, I think without being certain that I have an explanation. So this is going to be a little bit of speculation (but I can probably ask internally to confirm this), I think that it's more "consistent" with Simulink/MATLAB semantic in this way. When you run a simulation in Simulink, if you have a parameter that comes from the base workspace, it can only have one value at a time, even if you have multiple instances of the model. Which translate in the generated code (since 2019a I think) in one unique global variable, even for reusable function interface.
What you want is to have multiple values for multiple instances of the generated code, which match Model Arguments when you think in Simulink term. (They allow each instance of the model to have separate values)
In term of documentation, this change in behaviour was documented in the release notes of R2019a, under the title "Model argument support for top models". In particular:
Compatibility Considerations
Previously, you accessed parameter data in the top model through a pointer in the real-time model. If you generated code that used the reusable code format, you could define different parameter values for each instance of a top model [your behaviour]. You defined these different values by setting the pointer to different memory with different sets of parameter values. In R2019a, for multi-instance top models and top models that use a malloc memory model, parameter data in the top model is declared as a standalone global variable. For C++ code generation, the parameter data is a static member of the model class. To define different parameter values for each instance of a top model, you must configure model arguments in the same way that you configure model arguments for referenced models. Define the parameter in the model workspace then, in the Model Data Editor, Property Inspector, or Model Explorer, select the Argument check box. [the current pattern to obtain the previous behaviour]
2 Comments
Nicolas Schoonbroodt
on 5 Dec 2020
Hi Will,
Yes, I think that these two pages are good example to follow. At the end, the model should generate the code that you expect (if you take the additional step to configure them for code generation with reusable functions.
About the pro and cons of parameter vs additional inputs, I would say that philosophically, I prefer to keep my signals for "data that changes often" (at every time step), and parameters for data that "don't change at all, or change not too often".
In term of model, I prefer for example to use a gain block with a gain "X" that is a parameter, than to use a signal with the value of X comming from the outside of the model and a product block. If the gain is deep in the model (into a subsystem, which is in a subsystem, in another subsystem, and so on), it's easier to use a parameter than having to pass the signal as an input of each subsystem. As you say, an alternative could be to use a datastore, but I'm not sure if I like this method. In all case, if you use an input signal instead of a parameter, that means that you need to add additional blocks in the model (input block in each subsystem, or data store, or other way of reaching the goal), while with parameter, the block diagram (the drawing part of the model) is more "clean" and I think that's important. (but as you have seen in this case, managing parameter can also introduce some questions. I think keeping the block diagram simple is more important, and I prefer to have to think about data/parameter management)
That being said, if you go for "input signal in place of parameters", you will not be the first user to do that, and it's doable.
More Answers (0)
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!