修复模型以符合您使用模型顾问指定的条件
此示例说明如何创建一个自定义的具有修复操作的模型顾问通过/失败检查。当模型不包含检查违规时,结果包含检查说明和结果状态。当模型包含检查违规时,结果包含该检查的说明、结果状态和修复问题的建议操作。此示例将自定义检查添加到模型顾问的按产品 > Demo 子文件夹。
对于此示例,自定义检查识别其名称未显示在模块下方的模块。修复操作是使模块名称显示在模块下方。
当某项检查未通过时,结果包括指向违反该检查的每个模型元素的超链接。使用这些超链接可以轻松定位模型或子系统中的对应区域。此示例的代码由 sl_customization.m
文件和 defineDetailStyleCheck.m
文件组成。
创建 sl_customization
文件
在您的工作文件夹中,创建
sl_customization.m
文件。要注册自定义检查,请创建如下所示的
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
文件。
创建一个
ModelAdvisor.Root
对象。mdladvRoot = ModelAdvisor.Root;
创建一个
ModelAdvisor.Check
对象,并定义唯一检查 ID。对于此检查,ID 是com.mathworks.sample.detailStyle
。rec = ModelAdvisor.Check('com.mathworks.sample.detailStyle');
指定
ModelAdvisor.Check.Title
和ModelAdvisor.Check.TitleTips
属性。rec.Title = 'Check whether block names appear below blocks'; rec.TitleTips = 'Check position of block names';
使用
setCallbackFcn
方法调用回调函数。setCallbackFcn
方法参量是回调函数的句柄和ModelAdvisor.Check.CallbackStyle
属性值。对于此示例,CallbackStyle
属性值为DetailStyle
。此样式允许您按模块、子系统或建议的操作查看结果。应用此样式会生成默认格式,因此您不必使用ModelAdvisor.FormatTemplate
类或其他模型顾问格式 API 来格式化模型顾问中显示的结果。rec.setCallbackFcn(@DetailStyleCallback,'None','DetailStyle');
要设置修复操作,请创建一个
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';
使用
setAction
方法设置检查的操作。rec.setAction(myAction);
使用
publish
方法将检查发布到按产品文件夹中的一个文件夹。对于此示例,文件夹名称为 Demo。mdladvRoot.publish(rec, 'Demo'); % publish check into Demo group.
创建检查回调定义函数
在
defineDetailStyleCheck.m
文件中,创建检查回调函数。在此示例中,函数名称为DetailStyleCallback
。此函数的输入是ModelAdvisor.CheckObject
和模型顾问分析的模型或系统的路径。function DetailStyleCallback(system, CheckObj)
要创建
Simulink.ModelAdvisor
对象,请使用Simulink.ModelAdvisor.getModelAdvisor
函数。mdladvObj = Simulink.ModelAdvisor.getModelAdvisor(system); % get object
要识别违反检查的模块,请使用
find_system
函数。对于每个模型元素,此函数创建一个ModelAdvisor.ResultDetail
对象。violationBlks = find_system(system, 'Type','block',... 'NamePlacement','alternate',... 'ShowName', 'on');
如果
find_system
函数无法识别其名称未显示在模块下方的模块,则针对这种情况编写代码。在这种情况下,ElementResults
是ModelAdvisor.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);
如果
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
要将结果与某检查对象相关联,请使用
setResultDetails
方法。CheckObj.setResultDetails(ElementResults); end
创建操作回调定义函数
在
defineDetailStyleCheck.m
文件中,创建操作回调函数。在此示例中,函数名称为sampleActionCB
。此函数的输入是ModelAdvisor.Task
对象。function result = ActionCB(taskobj)
创建
Simulink.ModelAdvisor
和ModelAdvisor.Check
对象的句柄。mdladvObj = taskobj.MAObj; checkObj = taskobj.Check;
创建
ModelAdvisor.ResultDetail
对象数组,用于存储违反检查的模块的信息。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);
运行检查
保存
sl_customization.m
和defineDetailStyleCheck.m
文件。在 MATLAB 命令行窗口中,输入:
Advisor.Manager.refresh_customizations
通过在 MATLAB 命令提示符下键入以下命令,打开模型
sldemo_fuelsys
:openExample('sldemo_fuelsys')
在顶层模型中,选择名为
Engine Speed
的模块。在工具条的格式选项卡上,点击翻转名称。打开
fuel_rate_control
子系统。选择名为validate_sample_time
的模块。在工具条的格式选项卡上,点击翻转名称。返回顶层模型并另存为
example_sldemo_fuelsys
。在建模选项卡中,选择模型顾问。将打开系统选择器 ― Model Advisor 对话框。点击确定。将打开模型顾问。
在左窗格中,选择按产品 > Demo > 检查模块名称是否出现在模块下方。
选择运行检查。模型顾问检查为您更改的模块生成一条警告。
通过选择报告或结果详细信息选项卡查看结果。
这两个选项卡都为违反该检查的每个模块提供建议的操作。您可以点击超链接路径以在模型编辑器中打开该模块。例如:
使用以下方法之一,执行建议的用于修复违规模块的操作:
通过双击超链接打开模块来单独更新每项违规。选择该模块。在工具条的格式选项卡上,选择翻转名称。
在工具条中,点击修复。模型顾问会自动修复模型中的问题。请注意,在修复违规后,按钮会灰显。
重新运行模型顾问检查。检查通过。
另请参阅
ModelAdvisor.Check
| ModelAdvisor.FormatTemplate
| ModelAdvisor.FormatTemplate
| ModelAdvisor.Check.CallbackContext
| Simulink.ModelAdvisor
| Simulink.ModelAdvisor.getModelAdvisor
| Simulink.ModelAdvisor.openConfigUI
| Simulink.ModelAdvisor.reportExists