Create and Deploy Model Advisor Custom Configuration
To check that a model meets the standards and modeling guidelines of your company, you can customize the Model Advisor. This example shows you how to add custom checks to the Model Advisor and remove shipping checks that you do not require. You can save the custom check configuration and deploy it to others in your development group. Deploying a custom configuration allows your development group to review models using the same set of checks.
Define Custom Checks
This example defines four types of custom checks:
An edit-time check that provides a fix action.
A check that runs in only the Model Advisor and groups results by blocks and subsystems and provides a fix action.
A check that runs only in the Model Advisor and verifies model configuration parameter settings.
An edit-time check that specifies a constraint for a block parameter setting and provides a fix action.
The example files include the sl_customization.m
file. This file contains the sl_customization
function, which contains calls to functions that define the custom checks. Open and inspect the sl_customization.m
file.
function sl_customization(cm) % SL_CUSTOMIZATION - Model Advisor customization demonstration. % Copyright 2019 The MathWorks, Inc. % register custom checks cm.addModelAdvisorCheckFcn(@defineModelAdvisorChecks); % ----------------------------- % defines Model Advisor Checks % ----------------------------- function defineModelAdvisorChecks defineEditTimeCheck defineDetailStyleCheck; defineConfigurationParameterCheck; defineNewBlockConstraintCheck;
The sl_customization
function accepts a customization manager object that includes the addModelAdvisorCheckFcn
method for registering custom checks. The input to this method is a handle to a function, defineModelAdvisorChecks
, which contains calls to the four check definition functions that correspond to the four custom checks.
Edit-Time Check with Fix
The defineEditTimeCheck.m
file contains the defineEditTimeCheck
check definition function, which defines a check that checks whether Inport and Outport blocks have certain colors depending on their output data types. This check must check other edited blocks, but it does not have to check for affected blocks at the same level or across the entire model hierarchy. This check provides a fix that updates the color of the blocks that do not have the correct colors. The name of this check is Check color of Inport and Outport blocks. This check runs at edit-time and in the Model Advisor. Open and inspect the defineEditTimeCheck.m
file.
function defineEditTimeCheck % Check the background color of Inport and Outport blocks. rec = ModelAdvisor.Check("advisor.edittimecheck.PortColor"); rec.Title = 'Check color of Inport and Outport blocks'; rec.CallbackHandle = 'MyEditTimeChecks.PortColor'; mdladvRoot = ModelAdvisor.Root; mdladvRoot.publish(rec,'Demo');
The edit-time check has a class definition, PortColor
, that derives from the ModelAdvisor.EdittimeCheck
base class. For more information on how to create this type of check, see Define Edit-Time Checks to Comply with Conditions That You Specify with the Model Advisor. Create a folder named +MyEditTimeChecks
and save PortColor.m
to this folder.
copyfile PortColor.m* +MyEditTimeChecks
Open and inspect the PortColor.m
file.
classdef PortColor < ModelAdvisor.EdittimeCheck % Check that ports conform to software design standards for background color. % % Background Color Data Types % orange Boolean % green all floating-point % cyan all integers % Light Blue Enumerations and Bus Objects % white auto % methods function obj=PortColor(checkId) obj=obj@ModelAdvisor.EdittimeCheck(checkId); obj.traversalType = edittimecheck.TraversalTypes.BLKITER; end function violation = blockDiscovered(obj, blk) violation = []; if strcmp(get_param(blk,'BlockType'),'Inport') || strcmp(get_param(blk,'BlockType'),'Outport') dataType = get_param(blk,'OutDataTypeStr'); currentBgColor = get_param(blk,'BackgroundColor'); if strcmp(dataType,'boolean') if ~strcmp(currentBgColor, 'orange') % Create a violation object using the ModelAdvisor.ResultDetail class. violation = ModelAdvisor.ResultDetail; ModelAdvisor.ResultDetail.setData(violation,'SID',Simulink.ID.getSID(blk)); violation.CheckID = obj.checkId; violation.Description = 'Inport/Outport blocks with Boolean outputs should be orange.'; violation.title = 'Port Block Color'; violation.ViolationType = 'warn'; end elseif any(strcmp({'single','double'},dataType)) if ~strcmp(currentBgColor, 'green') violation = ModelAdvisor.ResultDetail; ModelAdvisor.ResultDetail.setData(violation,'SID',Simulink.ID.getSID(blk)); violation.CheckID = obj.checkId; violation.Description = 'Inport/Outport blocks with floating-point outputs should be green.'; violation.title = 'Port Block Color'; violation.ViolationType = 'warn'; end elseif any(strcmp({'uint8','uint16','uint32','int8','int16','int32'}, dataType)) if ~strcmp(currentBgColor, 'cyan') violation = ModelAdvisor.ResultDetail; ModelAdvisor.ResultDetail.setData(violation,'SID',Simulink.ID.getSID(blk)); violation.CheckID = obj.checkId; violation.Description = 'Inport/Outport blocks with integer outputs should be cyan.'; violation.title = 'Port Block Color'; violation.ViolationType = 'warn'; end elseif contains(dataType,'Bus:') if ~strcmp(currentBgColor, 'lightBlue') violation = ModelAdvisor.ResultDetail; ModelAdvisor.ResultDetail.setData(violation,'SID',Simulink.ID.getSID(blk)); violation.CheckID = obj.checkId; violation.Description = 'Inport/Outport blocks with bus outputs should be light blue.'; violation.title = 'Port Block Color'; violation.ViolationType = 'warn'; end elseif contains(dataType,'Enum:') if ~strcmp(currentBgColor, 'lightBlue') violation = ModelAdvisor.ResultDetail; ModelAdvisor.ResultDetail.setData(violation,'SID',Simulink.ID.getSID(blk)); violation.CheckID = obj.checkId; violation.Description = 'Inport/Outport blocks with enumeration outputs should be light blue.'; violation.title = 'Port Block Color'; violation.ViolationType = 'warn'; end elseif contains(dataType, 'auto') if ~strcmp(currentBgColor, 'white') violation = ModelAdvisor.ResultDetail; ModelAdvisor.ResultDetail.setData(violation,'SID',Simulink.ID.getSID(blk)); violation.CheckID = obj.checkId; violation.Description = 'Inport/Outport blocks with auto outputs should be white.'; violation.title = 'Port Block Color'; violation.ViolationType = 'warn'; end end end end function violation = finishedTraversal(obj) violation = []; end function success = fix(obj, violation) success = true; dataType = get_param(violation.Data,'OutDataTypeStr'); if strcmp(dataType,'boolean') set_param(violation.Data,'BackgroundColor','orange'); elseif any(strcmp({'single','double'},dataType)) set_param(violation.Data,'BackgroundColor','green'); elseif any(strcmp({'uint8','uint16','uint32','int8','int16','int32'}, dataType)) set_param(violation.Data,'BackgroundColor','cyan'); elseif contains(dataType,'Bus:') || contains(dataType,'Enum:') set_param(violation.Data,'BackgroundColor','lightBlue'); elseif contains(dataType,'auto') set_param(violation.Data,'BackgroundColor','white'); end end end end
Model Advisor Check with Fix
The defineDetailStyleCheck.m
file contains the defineDetailStyleCheck
check definition function, which defines a check that lists blocks whose names are not displayed below the blocks. This check provides a fix that moves those names below the blocks. The name of this check is Check whether block names appear below blocks. This check authoring style is for checks that only run in the Model Advisor. Open and inspect the defineDetailStyleCheck.m
file.
function defineDetailStyleCheck mdladvRoot = ModelAdvisor.Root; % Create ModelAdvisor.Check object and set properties. rec = ModelAdvisor.Check('com.mathworks.sample.detailStyle'); rec.Title = 'Check whether block names appear below blocks'; rec.TitleTips = 'Check position of block names'; rec.setCallbackFcn(@DetailStyleCallback,'None','DetailStyle'); % Create ModelAdvisor.Action object for setting fix operation. myAction = ModelAdvisor.Action; myAction.setCallbackFcn(@ActionCB); myAction.Name='Make block names appear below blocks'; myAction.Description='Click the button to place block names below blocks'; rec.setAction(myAction); mdladvRoot.publish(rec, 'Demo'); % publish check into Demo group. end % ----------------------------- % This callback function uses the DetailStyle CallbackStyle type. % ----------------------------- function DetailStyleCallback(system, CheckObj) mdladvObj = Simulink.ModelAdvisor.getModelAdvisor(system); % get object % Find all blocks whose name does not appear below blocks violationBlks = find_system(system, 'Type','block',... 'NamePlacement','alternate',... 'ShowName', 'on'); if isempty(violationBlks) ElementResults = ModelAdvisor.ResultDetail; ElementResults.Description = 'Identify blocks where the name is not displayed below the block.'; ElementResults.Status = 'All blocks have names displayed below the block.'; mdladvObj.setCheckResultStatus(true); else for i=1:numel(violationBlks) ElementResults(1,i) = ModelAdvisor.ResultDetail; end for i=1:numel(ElementResults) ModelAdvisor.ResultDetail.setData(ElementResults(i), 'SID',violationBlks{i}); ElementResults(i).Description = 'Identify blocks where the name is not displayed below the block.'; ElementResults(i).Status = 'The following blocks have names that do not display below the blocks:'; ElementResults(i).RecAction = 'Change the location such that the block name is below the block.'; ElementResults(i).ViolationType = 'warn'|'info'|'fail'; end mdladvObj.setCheckResultStatus(false); mdladvObj.setActionEnable(true); end CheckObj.setResultDetails(ElementResults); end % ----------------------------- % This action callback function changes the location of block names. % ----------------------------- function result = ActionCB(taskobj) mdladvObj = taskobj.MAObj; checkObj = taskobj.Check; resultDetailObjs = checkObj.ResultDetails; for i=1:numel(resultDetailObjs) % take some action for each of them block=Simulink.ID.getHandle(resultDetailObjs(i).Data); set_param(block,'NamePlacement','normal'); end result = ModelAdvisor.Text('Changed the location such that the block name is below the block.'); mdladvObj.setActionEnable(false); end
This check uses the setCallbackFcn
type of DetailStyle
, which produces default formatting, so that you do not have to use the ModelAdvisor.FormatTemplate
or the other Model Advisor formatting APIs to format the results that appear in the Model Advisor. For more information on how to create this type of check definition function, see Fix a Model to Comply with Conditions that You Specify with the Model Advisor.
Model Configuration Parameter Settings Check
The defineConfigurationParameterCheck.m
file contains the defineConfigurationParameterCheck
check definition function, which defines a check that identifies model configuration parameter settings that might impact MISRA C:2012 compliant code generation. The name of this check is Check model configuration parameters.
This check requires a supporting XML data file that must be on the MATLAB path and contain the model configuration parameter settings that you want to check. For this example, that file is configurationParameterDataFile.xml.
For more information on how to create this check type, see Create Model Advisor Check for Model Configuration Parameters.
Open and inspect the defineConfigurationParameterCheck.m
file.
function defineConfigurationParameterCheck % Create ModelAdvisor.Check object and set properties. rec = ModelAdvisor.Check('com.mathworks.sample.configurationParameter'); rec.Title = 'Check model configuration parameters'; rec.setCallbackFcn(@(system)(Advisor.authoring.CustomCheck.checkCallback... (system)), 'None', 'StyleOne'); rec.TitleTips = 'Identify configuration parameters that might impact MISRA C:2012 compliant code generation.'; % --- data file input parameters rec.setInputParametersLayoutGrid([1 1]); inputParam1 = ModelAdvisor.InputParameter; inputParam1.Name = 'Data File'; inputParam1.Value = 'configurationParameterDataFile.xml'; inputParam1.Type = 'String'; inputParam1.Description = 'Name or full path of XML data file.'; inputParam1.setRowSpan([1 1]); inputParam1.setColSpan([1 1]); rec.setInputParameters({inputParam1}); % -- set fix operation act = ModelAdvisor.Action; act.setCallbackFcn(@(task)(Advisor.authoring.CustomCheck.actionCallback... (task))); act.Name = 'Modify Settings'; act.Description = 'Modify model configuration settings.'; rec.setAction(act); % publish check into Demo folder. mdladvRoot = ModelAdvisor.Root; mdladvRoot.publish(rec, 'Demo'); end
Block Parameter Constraint Check
The defineNewBlockConstraintCheck.m
file contains the defineNewBlockConstraintCheck
check definition function, which defines a check that identifies Logical Operator blocks that do not have a rectangular shape. The name of this check is Check icon shape of Logical Operator blocks.
A block parameter constraint check supports edit-time checking. For more information on this check type, see Define Model Advisor Checks for Supported and Unsupported Blocks and Parameters.
Open and inspect the defineNewBlockConstraintChec
k.m
file.
function defineNewBlockConstraintCheck rec = Advisor.authoring.createBlockConstraintCheck('com.mathworks.sample.blockConstraint',... 'Constraints',@createBlockConstraints); % constraint creation is part of block constraint check definition rec.Title = 'Check icon shape of Logical Operator blocks'; rec.TitleTips = 'Checks icon shape of Logical Operator blocks. Icon shape of Logical Operator should be rectangular.'; % Publish check into Demo folder. mdladvRoot = ModelAdvisor.Root; mdladvRoot.publish(rec, 'Demo'); end function constraints = createBlockConstraints() % Create block constraints. c1 = Advisor.authoring.PositiveBlockParameterConstraint; c1.ID = 'ID_c1'; c1.BlockType = 'Logic'; c1.ParameterName = 'IconShape'; c1.SupportedParameterValues = {'rectangular'}; c1.ValueOperator = 'eq'; constraints = {c1}; end
The createBlockConstraints
function defines the block constraint c1
. The Advisor.authoring.createBlockConstraintCheck
function has a 'Constraints'
name-value argument that calls the constraints creation function createBlockConstraints
.
View Custom Checks in the Model Advisor
To confirm that your custom checks are available, open the Model Advisor.
1. For your custom checks to be visible in the Model Advisor, you must refresh the Model Advisor check information cache. At the MATLAB command prompt, enter:
Advisor.Manager.refresh_customizations();
2. Open the example model.
open_system('AdvisorCustomizationExample.slx');
3. On the Modeling tab, open the Model Advisor. You can also open the Model Advisor by entering this command at the MATLAB command prompt:
modeladvisor('AdvisorCustomizationExample.slx');
Updating Model Advisor cache... Model Advisor cache updated. For new customizations, to update the cache, use the Advisor.Manager.refresh_customizations method.
4. Expand the By Product > Demo folder. In the check definition functions, the publish
command adds the checks to the By Product > Demo folder.
Specify and Deploy a Model Advisor Custom Configuration
To specify which checks to include in the Model Advisor and which checks to use during edit-time checking, use the Model Advisor Configuration Editor.
1. To open the Configuration Editor, in the Model Advisor, click Open > Open Configuration Editor.
2. To add or remove checks and folders, select from the options in the Edit section of the Model Advisor Configuration Editor.
3. To save a configuration, select Save. A window opens and prompts you to save the configuration as a JSON file. For this example, you do not have to save the configuration, because the file demoConfiguration.json
file contains the four custom checks for this example.
4. Close the model and the Model Advisor Configuration Editor.
bdclose;
Associate a Custom Check Configuration with a Model and Address Check Issues
To address check issues, first associate the configuration with a model. Then, you can address issues during edit-time and in the Model Advisor.
1. Open the example model.
open_system('AdvisorCustomizationExample.slx');
2. Associate the custom configuration, demoConfiguration.json
, with the model. When you associate a custom configuration with a model, the model uses the same check configuration every time you open a model. Click the Modeling tab and select Model Advisor > Edit-Time Checks. In the Configuration Parameters dialog box, specify the path to the configuration file for the Model Advisor configuration file parameter. Alternatively, enter this command at the command prompt:
ModelAdvisor.setModelConfiguration('AdvisorCustomizationExample', 'demoConfiguration.json');
3. Turn on edit-time checking by clicking the Modeling tab and selecting Model Advisor > Edit-Time Checks. The Configuration Parameters dialog box opens. Select the Edit-Time Checks parameter. Alternatively, you can enter this command at the command prompt:
edittime.setAdvisorChecking('AdvisorCustomizationExample','on');
At the top level of the model, the two Inport blocks have an output data type of int32
. The blocks produce edit-time warnings because they should be cyan. The Outport block does not produce a warning because it has an auto
data type and is white.
4. For each Inport block, click the edit-time warning window. Then click Fix. The color of the blocks changes to cyan and the warning goes away.
5. The Logical Operator block produces a warning because it should have a rectangular shape. Click the edit-time warning window and then click Fix. The shape of the Logical Operator block changes to a rectangle, and the warning goes away.
6. Now that you have addressed the edit-time check warnings, open the Model Advisor to address any remaining check issues.
modeladvisor('AdvisorCustomizationExample.slx');
Model Advisor is removing the existing report.
7. The Model Advisor contains the four checks in the custom configuration. Click Run Checks. The two checks that you addressed during edit-time pass. The other two checks produce warnings.
8. Click the Check whether block names appear below blocks check. To apply a fix and resolve the warnings, in the right pane, click Fix.
9. Click the Check model configuration parameters check. To apply a fix and resolve the warnings, click Fix.
10. Rerun the checks. They now pass.
11. Close the model and the Model Advisor.
bdclose;
12. Remove the files from your working directory. Refresh the Model Advisor check information cache by entering this command:
Advisor.Manager.refresh_customizations
Programmatically Run a Model Advisor Custom Configuration and View Results
You can programmatically run a Model Advisor configuration and then open the results in the Model Advisor.
1. Call the ModelAdvisor.run
function.
SysResultObjArray = ModelAdvisor.run({'AdvisorCustomizationExample'},... 'Configuration','demoConfiguration.json');
2. View the results in the Model Advisor:
viewReport(SysResultObjArray{1},'MA')
3. Click Continue in the dialog box. You can now apply fixes and resolve warnings.
4. Close the model and the Model Advisor.
bdclose;
5. Remove the files from your working directory. Refresh the Model Advisor check information cache by entering this command:
Advisor.Manager.refresh_customizations
See Also
ModelAdvisor.Check
| ModelAdvisor.EdittimeCheck