Main Content

修复模型以符合您使用模型顾问指定的条件

此示例说明如何创建一个自定义的具有修复操作的模型顾问通过/失败检查。当模型不包含检查违规时,结果包含检查说明和结果状态。当模型包含检查违规时,结果包含该检查的说明、结果状态和修复问题的建议操作。此示例将自定义检查添加到模型顾问的按产品 > Demo 子文件夹。

对于此示例,自定义检查识别其名称未显示在模块下方的模块。修复操作是使模块名称显示在模块下方。

当某项检查未通过时,结果包括指向违反该检查的每个模型元素的超链接。使用这些超链接可以轻松定位模型或子系统中的对应区域。此示例的代码由 sl_customization.m 文件和 defineDetailStyleCheck.m 文件组成。

创建 sl_customization 文件

  1. 在您的工作文件夹中,创建 sl_customization.m 文件。

  2. 要注册自定义检查,请创建如下所示的 sl_customization(cm) 函数。此函数接受一个参量,即自定义管理器对象。该自定义管理器对象包含用于注册自定义检查的 addModelAdvisorCheckFcn 方法。此方法的输入是函数 defineModelAdvisorChecks 的句柄。defineModelAdvisorChecks 包含对自定义模型顾问通过/失败检查的检查定义函数的调用。

    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;
    

创建检查定义文件

检查定义函数定义在运行检查时模型顾问采取的检查和修复操作。对于此示例,完整的检查定义函数文件是 defineDetailStyleCheck.m,它包含以下代码:

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

以下步骤说明如何创建 defineDetailStyleCheck.m 文件。

  1. 创建一个 ModelAdvisor.Root 对象。

    mdladvRoot = ModelAdvisor.Root;
  2. 创建一个 ModelAdvisor.Check 对象,并定义唯一检查 ID。对于此检查,ID 是 com.mathworks.sample.detailStyle

    rec = ModelAdvisor.Check('com.mathworks.sample.detailStyle');
    
  3. 指定 ModelAdvisor.Check.TitleModelAdvisor.Check.TitleTips 属性。

    rec.Title = 'Check whether block names appear below blocks';
    rec.TitleTips = 'Check position of block names';
  4. 使用 setCallbackFcn 方法调用回调函数。setCallbackFcn 方法参量是回调函数的句柄和 ModelAdvisor.Check.CallbackStyle 属性值。对于此示例,CallbackStyle 属性值为 DetailStyle。此样式允许您按模块、子系统或建议的操作查看结果。应用此样式会生成默认格式,因此您不必使用 ModelAdvisor.FormatTemplate 类或其他模型顾问格式 API 来格式化模型顾问中显示的结果。

    rec.setCallbackFcn(@DetailStyleCallback,'None','DetailStyle');
  5. 要设置修复操作,请创建一个 ModelAdvisor.Action 对象并定义其属性。使用 setCallback 方法调用操作回调函数。此方法的输入是操作回调函数的句柄。

    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. 使用 setAction 方法设置检查的操作。

    rec.setAction(myAction);
  7. 使用 publish 方法将检查发布到按产品文件夹中的一个文件夹。对于此示例,文件夹名称为 Demo

    mdladvRoot.publish(rec, 'Demo'); % publish check into Demo group.

创建检查回调定义函数

  1. defineDetailStyleCheck.m 文件中,创建检查回调函数。在此示例中,函数名称为 DetailStyleCallback。此函数的输入是 ModelAdvisor.CheckObject 和模型顾问分析的模型或系统的路径。

    function DetailStyleCallback(system, CheckObj)
  2. 要创建 Simulink.ModelAdvisor 对象,请使用 Simulink.ModelAdvisor.getModelAdvisor 函数。

    mdladvObj = Simulink.ModelAdvisor.getModelAdvisor(system); % get object
    
  3. 要识别违反检查的模块,请使用 find_system 函数。对于每个模型元素,此函数创建一个 ModelAdvisor.ResultDetail 对象。

    violationBlks = find_system(system, 'Type','block',...
                               'NamePlacement','alternate',...
                               'ShowName', 'on');
  4. 如果 find_system 函数无法识别其名称未显示在模块下方的模块,则针对这种情况编写代码。在这种情况下,ElementResultsModelAdvisor.ResultDetail 对象的一个实例,它仅提供信息内容。该方法指定不存在检查违规,并在模型顾问中显示通过

    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);  
  5. 如果 find_system 函数返回名称未显示在模块下方的模块的列表 (violationBlks),则针对这种情况编写代码。ElementResults 包括违反检查的每个 ModelAdvisor.ResultDetail 对象,并提供针对修复检查违规的建议操作消息。

    在这种情况下,setCheckResultStatus 方法指定检查违规,并在模型顾问中显示警告失败Simulink.ModelAdvisor.setActionEnable(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    
  6. 要将结果与某检查对象相关联,请使用 setResultDetails 方法。

    CheckObj.setResultDetails(ElementResults);
    end

创建操作回调定义函数

  1. defineDetailStyleCheck.m 文件中,创建操作回调函数。在此示例中,函数名称为 sampleActionCB。此函数的输入是 ModelAdvisor.Task 对象。

    function result = ActionCB(taskobj)
  2. 创建 Simulink.ModelAdvisor ModelAdvisor.Check 对象的句柄。

    mdladvObj = taskobj.MAObj;
    checkObj = taskobj.Check;
  3. 创建 ModelAdvisor.ResultDetail 对象数组,用于存储违反检查的模块的信息。

    resultDetailObjs = checkObj.ResultDetails;
  4. 编写代码,以将模块名称位置更改为在模块下方。

    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. 禁用操作 框。

    mdladvObj.setActionEnable(false);

运行检查

  1. 保存 sl_customization.mdefineDetailStyleCheck.m 文件。

  2. 在 MATLAB 命令行窗口中,输入:

    Advisor.Manager.refresh_customizations
  3. 通过在 MATLAB 命令提示符下键入以下命令,打开模型 sldemo_fuelsys

    openExample('sldemo_fuelsys')

  4. 在顶层模型中,选择名为 Engine Speed 的模块。在工具条的格式选项卡上,点击翻转名称

  5. 打开 fuel_rate_control 子系统。选择名为 validate_sample_time 的模块。在工具条的格式选项卡上,点击翻转名称

    返回顶层模型并另存为 example_sldemo_fuelsys

  6. 建模选项卡中,选择模型顾问。将打开系统选择器 ― Model Advisor 对话框。点击确定。将打开模型顾问。

  7. 在左窗格中,选择按产品 > Demo > 检查模块名称是否出现在模块下方

  8. 选择运行检查。模型顾问检查为您更改的模块生成一条警告。

  9. 通过选择报告结果详细信息选项卡查看结果。

    这两个选项卡都为违反该检查的每个模块提供建议的操作。您可以点击超链接路径以在模型编辑器中打开该模块。例如:

    The Model Advisor showing a table of blocks with violations and the hyperlinks to the block paths

  10. 使用以下方法之一,执行建议的用于修复违规模块的操作:

    • 通过双击超链接打开模块来单独更新每项违规。选择该模块。在工具条的格式选项卡上,选择翻转名称

    • 在工具条中,点击修复。模型顾问会自动修复模型中的问题。请注意,在修复违规后,按钮会灰显。

  11. 重新运行模型顾问检查。检查通过。

    The Model Advisor with a passing result

另请参阅

| | | | | | |

相关主题