Main Content

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.

This example also shows you how to collect results into groups that violate a check (that is, detailed result collections), such as blocks in a subsystem. In the Model Advisor, you can review results by selecting:

  • View By > Recommended Action ─ When a check is violated, this view shows a list of model elements that violate the check. When there is no violation, this view provides a brief description stating that the check was not violated.

  • View By > Subsystem ─ This view shows a table of model elements that violate the check, organized by model or subsystem (when applicable).

  • View By > Block ─ This view provides a list of check violations for each block.

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

  1. In your working folder, create an sl_customization.m file.

  2. 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 the addModelAdvisorCheckFcn method for registering the custom check. The input to this method is a handle to the check definition function.

    function sl_customization(cm)
    % SL_CUSTOMIZATION - Model Advisor customization demonstration.
    
    % Copyright 2019 The MathWorks, Inc.
    
    % register custom checks 
    cm.addModelAdvisorCheckFcn(@defineDetailStyleCheck);
    
    % -----------------------------
    % defines Model Advisor Checks
    % -----------------------------
    function 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.Name='Make block names appear below blocks';
myAction.Description='Click the button to place block names below blocks';
rec.setAction(myAction);
myAction.setCallbackFcn(@ActionCB);
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.IsInformer = true;
    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
    ElementResults(1,numel(violationBlks))=ModelAdvisor.ResultDetail;
    for i=1:numel(ElementResults)
        ElementResults(i).setData(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 completed the defineDetailStyleCheck.m file.

  1. Create a ModelAdvisor.Root object.

    mdladvRoot = ModelAdvisor.Root;
  2. Create a ModelAdvisor.Check object and define the unique check ID. For this check, the ID is com.mathworks.sample.detailStyle.

    rec = ModelAdvisor.Check('com.mathworks.sample.detailStyle');
    
  3. Specify the ModelAdvisor.Check.Title and ModelAdvisor.Check.TitleTips properties.

    rec.Title = 'Check whether block names appear below blocks';
    rec.TitleTips = 'Check position of block names';
  4. Use the setCallbackFcn method to call the callback function. The setCallbackFcn method arguments are a handle to the callback function and the ModelAdvisor.Check.CallbackStyle property value. For this example, the CallbackStyle property value is DetailStyle. 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 the ModelAdvisor.FormatTemplate class or the other Model Advisor formatting APIs to format the results that appear in the Model Advisor.

    rec.setCallbackFcn(@DetailStyleCallback,'None','DetailStyle');
  5. To set the fix operation, create a ModelAdvisor.Action object and define its properties.

    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';
  6. Use the setCallback method to call the action callback function. The input to this method is a handle to the action callback function.

    myAction.setCallbackFcn(@ActionCB);
    
  7. Use the setAction method to set the action for the check.

    rec.setAction(myAction);
  8. 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

  1. In the defineDetailStyleCheck.m file, create the check callback function. In this example, the function name is DetailStyleCallback. The inputs to this function are a ModelAdvisor.CheckObject and the path to the model or system that the Model Advisor analyzes.

    function DetailStyleCallback(system, CheckObj)
  2. To create a Simulink.ModelAdvisor object, use the Simulink.ModelAdvisor.getModelAdvisor method.

    mdladvObj = Simulink.ModelAdvisor.getModelAdvisor(system); % get object
    
  3. To identify blocks that violate the check, use the find_system function. For each model element, this function creates a ModelAdvisor.ResultDetail object.

    violationBlks = find_system(system, 'Type','block',...
                               'NamePlacement','alternate',...
                               'ShowName', 'on');
  4. 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 a ModelAdvisor.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.IsInformer = true;
        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);  
  5. 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 each ModelAdvisor.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. The Simulink.ModelAdvisor.setActionEnable(true) method enables the ability to fix the check violation issue from the Model Advisor.

    else
        ElementResults(1,numel(violationBlks))=ModelAdvisor.ResultDetail;
        for i=1:numel(ElementResults)
            ElementResults(i).setData(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    
  6. To associate the results with a check object, use the setResultDetails method.

    CheckObj.setResultDetails(ElementResults);
    end

Create the Action Callback Definition Function

  1. In the defineDetailStyleCheck.m file, create the action callback function. In this example, the function name is sampleActionCB. The input to this function is a ModelAdvisor.Task object.

    function result = ActionCB(taskobj)
  2. Create handles to Simulink.ModelAdvisor and ModelAdvisor.Check objects.

    mdladvObj = taskobj.MAObj;
    checkObj = taskobj.Check;
  3. Create an array of ModelAdvisor.ResultDetail objects for storing the information for blocks that violate the check.

    resultDetailObjs = checkObj.ResultDetails;
  4. 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.');
  5. Disable the Action box.

    mdladvObj.setActionEnable(false);

Run the Check

  1. Save the sl_customization.m and defineDetailStyleCheck.m files.

  2. In the MATLAB command window, enter:

    Advisor.Manager.refresh_customizations
  3. From the MATLAB window, open the sldemo_fuelsys model.

  4. In the top model, right-click the Engine Speed block and select Rotate & Flip > Flip Block Name.

  5. Open the fuel_rate_control subsystem. Right-click the validate_sample_time block and select Rotate & Flip > Flip Block Name.

    Return to the top model and save as example_sldemo_fuelsys.

  6. In the Modeling tab, select Model Advisor. A System Selector ― Model Advisor dialog box opens. Click OK. The Model Advisor opens.

  7. In the left pane, select By Product > Demo > Check whether block names appear below blocks.

    Note

    If the By Product folder is not displayed in the Model Advisor window, select Settings > Preferences > Show By Product Folder

  8. Select Run This Check. The Model Advisor check fails for the blocks you changed.

  9. Review the results by selecting one of the View by options.

    The report provides a recommended action for each check. You can click the hyperlink path to open the violating block in the model editor. For example:

  10. 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. Right-click the block and select Rotate & Flip > Flip Block Name.

    • Select the Make block names appear below blocks button. The Model Advisor automatically fixes the issues in the model. Notice that the button is dimmed after the violations are fixed.

  11. Save the model and rerun the Model Advisor check. The check passes.

See Also

| | |

Related Topics