This example shows how to convert a Simulink® model that is parameterized by unstructured workspace variables to a model that is parameterized by a MATLAB® structure. The example uses a number of Simulink utilities to organize model variables from the base workspace into a hierarchical structure and then apply the structure to the model.
Open the model sldemo_applyVarStruct
.
This model uses a number of numeric parameters from the base workspace.
This example changes the original model and creates files in the current working directory. If you plan to save the example models, save a copy in the current directory.
Migrating a model to use structure parameters follows these steps:
1. Collect all numeric variables used by the model into a MATLAB structure.
2. Modify the MATLAB structure (if necessary).
3. Apply the MATLAB structure to the model.
4. Configure the appearance of the parameter structure in the generated code (optional).
You can use Simulink.findVars to find out what variables are used by the Simulink model.
model = 'sldemo_applyVarStruct'; varList = Simulink.findVars(model, 'WorkspaceType', 'base')
varList = 20x1 VariableUsage array with properties: Name Source SourceType Users
var = varList(1)
var = VariableUsage with properties: Name: 'Ka' Source: 'base workspace' SourceType: 'base workspace' Users: {'sldemo_applyVarStruct/Controller/Gain3'}
You can use Simulink.BlockDiagram.createVarStruct to generate a MATLAB structure containing all numeric variables from the base workspace or data dictionary used by the model.
Simulink.BlockDiagram.createVarStruct(model, 'ModelParam')
Created variable 'ModelParam' in base workspace.
Variable ModelParam is a MATLAB structure that contains the numeric variables as fields (sorted by name).
NOTE:
The model and all data that the model uses must be loaded before calling Simulink.BlockDiagram.createVarStruct.
You cannot give the MATLAB structure the same name as an existing variable.
The original structure contains all the variables in one level of hierarchy. You can change the structure before applying it to the model. For example, reorder parameter fields, add extra levels to group model parameters, or add extra fields.
NOTE:
Do not change the names of the leaf fields in the structure.
Do not clear the original variables until you have finished the migration process.
1. One way to do this is to use Simulink.saveVars to write the structure to a MATLAB script and make changes in the file.
Simulink.saveVars('sldemo_applyVarStruct_data.m','ModelParam') edit sldemo_applyVarStruct_data.m
2. Edit the MATLAB script as needed. For example, split the structure into two structures.
'ControlParam' contains all parameters for the Controller subsystem.
'ModelParam' contains all other numeric parameters.
ControlParam = struct; ControlParam.Ka = 0.677; ControlParam.Kf = -1.746; ControlParam.Ki = -3.864; ControlParam.Kq = 0.8156; ControlParam.Tal = [0.3959 1]; ControlParam.Ts = [0.1 1]; ControlParam.W1 = [1 2.971]; ControlParam.W2 = [1 4.144];
ModelParam = struct; ModelParam.Md = -6.8847; ModelParam.Mq = -0.6571; ModelParam.Mw = -0.00592; ModelParam.Swg = 3; ModelParam.Ta = 0.05; ModelParam.Uo = 689.4; ModelParam.Vto = 690.4; ModelParam.Zd = -63.9979; ModelParam.Zw = -0.6385; ModelParam.a = 2.5348; ModelParam.b = 64.13; ModelParam.g = 32.2;
Save the modified data file. You can use it as a preload function.
3. Run the modified MATLAB script to create the MATLAB structures.
sldemo_applyVarStruct_data;
You can use Simulink.BlockDiagram.applyVarStruct to automatically replace the variable references in the block diagram by the equivalent structure references.
1. Apply the MATLAB structure to the model. The model will be changed. You can then save it to a writable directory.
[applied,unapplied]=Simulink.BlockDiagram.applyVarStruct(model,'ControlParam')
[applied,unapplied]=Simulink.BlockDiagram.applyVarStruct(model,'ModelParam')
NOTE:
You can use 'preview' ApplyMode to get information about what will be changed without actually changing the model:
Simulink.BlockDiagram.applyVarStruct(model,'ModelParam', 'ApplyMode', 'preview')
If the model has been compiled, you can use 'cached' SearchMethod to avoid model recompiling:
Simulink.BlockDiagram.applyVarStruct(model,'ModelParam', 'SearchMethod', 'cached')
If unapplied output is not empty, you can investigate the reason using Simulink.findVars(model,'WorkspaceType','base','Name',variableName). The probable causes are: you changed structure field names or added extra fields; the variable is used by a block that needs special consideration, e.g., Stateflow® chart, S-Function or Model block.
2. Test the MATLAB structure in the modified model.
Clear unnecessary variables and run the simulation to check results.
clear; model = 'sldemo_applyVarStruct'; sldemo_applyVarStruct_data;
sim('sldemo_applyVarStruct');
Check for any warnings or errors.
Check simulation results.
By default, the MATLAB structure does not appear in generated code because numeric values are inlined. Code generation requires Simulink® Coder™.
1. To make the structure variable tunable, create Simulink.Parameter with the structure value and 'ExportedGlobal' storage class.
p=Simulink.Parameter; p.Value=ControlParam; p.CoderInfo.StorageClass='ExportedGlobal'; ControlParam=p; clear p;
rtwbuild('sldemo_applyVarStruct');
The generated code now contains a structure type definition for the tunable structure in the model_types.h header file. By default, Simulink Coder generates an automatic name for the type of parameter structures. This name is unique, but not easy to recognize.
typedef struct { real_T Ka; real_T Kf; real_T Ki; real_T Kq; real_T Tal[2]; real_T Ts[2]; real_T W1[2]; real_T W2[2]; } struct_mn4cJ7zsH8aqc8bBlbIkqC;
2. You can control this type name by using Simulink.Bus to specify the data type of the Simulink.Parameter object.
You can use Simulink.Bus.createObject to create a bus object with the same shape as the MATLAB structure.
busInfo=Simulink.Bus.createObject(ControlParam.Value)
Assign the bus object name to the Simulink.Parameter DataType attribute.
ParamType=eval(busInfo.busName); ControlParam.DataType='Bus: ParamType'; clear(busInfo.busName); clear busInfo;
NOTE: Only Simulink.Parameter can accept the bus object name as a data type. For MATLAB structures, Simulink Coder generates an automatic name for the type.
3. Resave the data file to include the modified workspace variables.
Simulink.saveVars('sldemo_applyVarStruct_data.m', '-append')
4. Regenerate code for the modified model (requires Simulink Coder).
rtwbuild(model);
The generated type definition now appears as:
typedef struct { real_T Ka; real_T Kf; real_T Ki; real_T Kq; real_T Tal[2]; real_T Ts[2]; real_T W1[2]; real_T W2[2]; } ParamType;
The parameter definition is:
ParamType ControlParam = { 0.677, -1.746, -3.864, 0.8156, {0.3959, 1.0}, {0.1, 1.0}, {1.0, 2.971}, {1.0, 4.144} }