Fix a Model to Comply with Conditions that You Specify with the Model Advisor
This example shows how to create a customized Model Advisor pass/fail check with a fix action. When a model does not contain a check violation, the results contain the check description and result status. When a model contains a check violation, the results contain the check description, result status, and the recommended action to fix the issue. This example adds a custom check to a Model Advisor By Product > Demo subfolder.
For this example, the custom check identifies blocks whose names do not appear below the blocks. The fix action is to make the block names appear below the blocks.
When a check does not pass, the results include a hyperlink to each model element that
violates the check. Use these hyperlinks to easily locate areas in your model or
subsystem. The code for this example consists of an
sl_customization.m
file and a
defineDetailStyleCheck.m
file.
Create the sl_customization
File
In your working folder, create an
sl_customization.m
file.To register the custom checks, create an
sl_customization(cm)
function as shown here. This function accepts one argument, a customization manager object. The customization manager object includes theaddModelAdvisorCheckFcn
method for registering the custom check. The input to this method is a handle to the functiondefineModelAdvisorChecks
.defineModelAdvisorChecks
contains a call to the check definition function for custom Model Advisor pass/fail check.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 defineDetailStyleCheck;
Create the Check Definition File
The check definition function defines the check and fix actions that the Model
Advisor takes when you run the check. For this example, the completed check
definition function file is defineDetailStyleCheck.m
, and it
contains this
code:
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.'; 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
The following steps explain how to create the
defineDetailStyleCheck.m
file.
Create a
ModelAdvisor.Root
object.mdladvRoot = ModelAdvisor.Root;
Create a
ModelAdvisor.Check
object and define the unique check ID. For this check, the ID iscom.mathworks.sample.detailStyle
.rec = ModelAdvisor.Check('com.mathworks.sample.detailStyle');
Specify the
ModelAdvisor.Check.Title
andModelAdvisor.Check.TitleTips
properties.rec.Title = 'Check whether block names appear below blocks'; rec.TitleTips = 'Check position of block names';
Use the
setCallbackFcn
method to call the callback function. ThesetCallbackFcn
method arguments are a handle to the callback function and theModelAdvisor.Check.CallbackStyle
property value. For this example, theCallbackStyle
property value isDetailStyle
. This style allows you to view results by block, subsystem, or recommended action. Applying this style produces default formatting, so that you do not have to use theModelAdvisor.FormatTemplate
class or the other Model Advisor formatting APIs to format the results that appear in the Model Advisor.rec.setCallbackFcn(@DetailStyleCallback,'None','DetailStyle');
To set the fix operation, create a
ModelAdvisor.Action
object and define its properties. Use thesetCallbackFcn
method to call the action callback function. The input to this method is a handle to the action callback function.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';
Use the
setAction
method to set the action for the check.rec.setAction(myAction);
Use the
publish
method to publish the check to a folder within the By Product folder. For this example, the folder name is Demo.mdladvRoot.publish(rec, 'Demo'); % publish check into Demo group.
Create the Check Callback Definition Function
In the
defineDetailStyleCheck.m
file, create the check callback function. In this example, the function name isDetailStyleCallback
. The inputs to this function are aModelAdvisor.CheckObject
and the path to the model or system that the Model Advisor analyzes.function DetailStyleCallback(system, CheckObj)
To create a
Simulink.ModelAdvisor
object, use the functionSimulink.ModelAdvisor.getModelAdvisor
.mdladvObj = Simulink.ModelAdvisor.getModelAdvisor(system); % get object
To identify blocks that violate the check, use the
find_system
function. For each model element, this function creates aModelAdvisor.ResultDetail
object.violationBlks = find_system(system, 'Type','block',... 'NamePlacement','alternate',... 'ShowName', 'on');
Write code for the case when the
find_system
function does not identify blocks whose names do not appear below the block. In this case,ElementResults
is one instance of aModelAdvisor.ResultDetail
object and provides information content only. The method specifies that there is no check violation and displays Passed in the Model Advisor.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);
Write code for the case when the
find_system
function returns a list of blocks whose names do not appear below the block (violationBlks
).ElementResults
includes eachModelAdvisor.ResultDetail
object that violates the check and provides a recommended action message for fixing the check violation.For this case, the
setCheckResultStatus
method specifies the check violation and displays Warning or Failed in the Model Advisor. TheSimulink.ModelAdvisor.setActionEnable(true)
method enables the ability to fix the check violation issue from the Model Advisor.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.'; end mdladvObj.setCheckResultStatus(false); mdladvObj.setActionEnable(true); end
To associate the results with a check object, use the
setResultDetails
method.CheckObj.setResultDetails(ElementResults); end
Create the Action Callback Definition Function
In the
defineDetailStyleCheck.m
file, create the action callback function. In this example, the function name issampleActionCB
. The input to this function is aModelAdvisor.Task
object.function result = ActionCB(taskobj)
Create handles to
Simulink.ModelAdvisor
andModelAdvisor.Check
objects.mdladvObj = taskobj.MAObj; checkObj = taskobj.Check;
Create an array of
ModelAdvisor.ResultDetail
objects for storing the information for blocks that violate the check.resultDetailObjs = checkObj.ResultDetails;
Write code that changes the block name location to below the block.
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.');
Disable the Action box.
mdladvObj.setActionEnable(false);
Run the Check
Save the
sl_customization.m
anddefineDetailStyleCheck.m
files.In the MATLAB command window, enter:
Advisor.Manager.refresh_customizations
Open the model
sldemo_fuelsys
by typing this command in the MATLAB command prompt:openExample('sldemo_fuelsys')
In the top model, select the block named
Engine Speed
. In the toolstrip, on the Format tab, click Flip Name.Open the
fuel_rate_control
subsystem. Select the block namedvalidate_sample_time
. In the toolstrip, on the Format tab, click Flip Name.Return to the top model and save as
example_sldemo_fuelsys
.In the Modeling tab, select Model Advisor. A System Selector ― Model Advisor dialog box opens. Click OK. The Model Advisor opens.
In the left pane, select By Product > Demo > Check whether block names appear below blocks.
Select Run Checks. The Model Advisor check produces a warning for the blocks that you changed.
Review the results by selecting either the Report or Result Detail tabs.
Both tabs provide a recommended action for each block that violates the check. You can click the hyperlink path to open the block in the model editor. For example:
Follow the recommended action for fixing the violating blocks by using one of these methods:
Update each violation individually by double-clicking the hyperlink to open the block. Select the block. In the toolstrip, on the Format tab, select Flip Name.
In the toolstrip, click Fix. The Model Advisor automatically fixes the issues in the model. Notice that the button is dimmed after the violations are fixed.
Rerun the Model Advisor check. The check passes.
See Also
ModelAdvisor.Check
| ModelAdvisor.FormatTemplate
| ModelAdvisor.FormatTemplate
| ModelAdvisor.Check.CallbackContext
| Simulink.ModelAdvisor
| Simulink.ModelAdvisor.getModelAdvisor
| Simulink.ModelAdvisor.openConfigUI
| Simulink.ModelAdvisor.reportExists