model advisor是simulink自带的静态模型检查器,能够根据设定的规则对模型进行检查,并且能够进行部分错误的自动修改。在汽车电子以及相关基于MBD(Model Based Design)开发的嵌入式项目中有重要的作用,能够帮助开发人员和团队搭建高质量的模型和使用高度统一的风格。自带的检查规则中,包含MAAB这种行业中应用广泛的规则,随着团队或者项目进程的积累,后续会慢慢发展出属于自己的一套建模规则和体系。此时则需要进行对model advisor的检查规则进行自定义。
自定义规则分两种情况,一种是对现有规则进行勾选,组合成团队需要的检查体系,另外一种是编写脚本,创建新的检查规则。在确认现有检查规则中无法满足所需要的检查,则可以进行新规则的编写。例如:
Simplest
。这条模型检查规则在官方自带的检查中就没有,如果想要统一团队风格只能通过编写脚本或者组织人工审查,显然作为程序员的我们对于这种选择问题的思考是不存在的,答案只有一个,代码撸起来。
本文主要针对这条规则需求进行编写脚本的详细说明和示例。
既然是在model advisor中添加新的检查规则,就需要将编写的检查规则都放到统一文件夹目录下,不能与其它检查规则混用。
%--- test_int_round_mode_check function description----------------------------function test_int_round_mode_checkint_round_mode = ModelAdvisor.Check('int_round_mode');int_round_mode.Title = 'int_round_mode:Check the integer rounding mode 检查整数舍入模式设定';int_round_mode.TitleTips = ['Fail if the rounding mode config is not <Simplest>'... '该模块设置如果不为<Simplest>则判断为违反本条规则'];int_round_mode.setCallbackFcn(@test_int_round_mode_checkCallback,'None','StyleOne');% publish the checkmdladvRoot = ModelAdvisor.Root;mdladvRoot.publish(int_round_mode,'TEST');
这些代码定义了检查规则的名字、简介、调用具体函数的句柄test_int_round_mode_checkCallback
,并将这条规则发布在TEST
文件夹下。
model advisor中,允许进行部分规则的自动修改,就是点一个按钮直接把模型改的符合本条检查规则,这个功能十分实用,尤其对于规模庞大的模型简直就是福音,所以回到本示例中,因为需要检查的内容单一,规则明确,所以可以增加自动修改的功能。当检查出整数舍入模式没有设置成Simplest
的模块,点击一个按钮,自动将这些模块舍入模式设成Simplest
。
% fix action descriptionint_round_modeAct = ModelAdvisor.Action;int_round_modeAct.Name = 'Fix settings';int_round_modeAct.Description = ['Click the button to set all blocks to Simplest'... '按下按钮,将所有模块设置成 Simpleset'];int_round_modeAct.setCallbackFcn(@test_int_round_mode_checkActCallback);int_round_mode.setAction(int_round_modeAct);
这段代码定义了修复按钮,按钮名字为Fix settings
,点击按钮的句柄为test_int_round_mode_checkActCallback
。
find_system(system,'RegExp','On','RndMeth','.');
可以找出模型中所有具有 integer rouding mode 配置选项的模块。 get_param(all_rnd_meth_block{i},'RndMeth');
得到模块的整形舍入模式设定选项int_round_mode_fc = ModelAdvisor.FormatTemplate('TableTemplate');
int_round_mode_fc.setColTitles({'Block','Old Setting','New Setting'});
int_round_mode_fc.addRow({all_rnd_meth_block{i},current_rnd,correct_cfg_rnd});
set_param(all_rnd_meth_block{i},'RndMeth',correct_cfg_rnd);
%------------------------------------------------------------------------------% Simulink scrip for customer check which used in model advisor.% MATLAB version: R2017a% Shibo Jiang 2017/8/20% Version: 0.1% Instructions: Type the 'sl_refresh_customizations' in matlab command % window with all the model closed. %------------------------------------------------------------------------------function sl_customization(cm)% --- register custom checkscm.addModelAdvisorCheckFcn(@test_int_round_mode_check);%-----Start of test_int_round_mode_check--------------------------------------- %--- test_int_round_mode_check function description------------------------ function test_int_round_mode_check int_round_mode = ModelAdvisor.Check('int_round_mode'); int_round_mode.Title = 'int_round_mode:Check the integer rounding mode'; int_round_mode.TitleTips = ['Fail if the rounding mode config is not ' ... '<Simplest>']; int_round_mode.setCallbackFcn(@test_int_round_mode_checkCallback, ... 'None','StyleOne'); % fix action description int_round_modeAct = ModelAdvisor.Action; int_round_modeAct.Name = 'Fix settings'; int_round_modeAct.Description = ['Click the button to set all blocks' ... ' to Simplest']; int_round_modeAct.setCallbackFcn(@test_int_round_mode_checkActCallback); int_round_mode.setAction(int_round_modeAct); % publish the check mdladvRoot = ModelAdvisor.Root; mdladvRoot.publish(int_round_mode,'TEST'); %--------------creates test_int_round_mode_checkCallback function---------- function int_round_mode_result = test_int_round_mode_checkCallback(system) int_round_mode_obj = Simulink.ModelAdvisor.getModelAdvisor(system); int_round_mode_result={}; int_round_mode_fc = ModelAdvisor.FormatTemplate('ListTemplate'); int_round_mode_fc.setInformation(['This check looks for the blocks' ... ' which integer rounding mode is not configed as [Simplest]']); % find all blocks which have 'integer ronuding mode' setting all_rnd_meth_block = find_system(system,'RegExp','On','RndMeth','.'); wrong_rnd_flag = 0; if ~isempty(all_rnd_meth_block) % find wrong config block length_rnd = length(all_rnd_meth_block); j = 1; correct_cfg_rnd = 'Simplest'; for i = 1:length_rnd current_rnd = get_param(all_rnd_meth_block{i},'RndMeth'); if 0 == strcmp(correct_cfg_rnd,current_rnd) wrong_rnd_flag = 1; wrong_rnd_block{j} = all_rnd_meth_block{i}; j = j + 1; else % Do nothing end end else wrong_rnd_flag = 0; end % report finding results if 0 == wrong_rnd_flag int_round_mode_fc.setSubResultStatusText(['Check has passed.']); int_round_mode_fc.setSubResultStatus('pass'); int_round_mode_obj.setCheckResultStatus(true); else int_round_mode_fc.setSubResultStatusText(['Check has failed.' ... ' The integer rounding mode config is wrong']); int_round_mode_fc.setListObj(wrong_rnd_block); int_round_mode_fc.setSubResultStatus('warn'); int_round_mode_fc.setRecAction(['Config the integer rounding' ... ' mode as [Simplest] .']); int_round_mode_obj.setCheckResultStatus(false); int_round_mode_obj.setActionEnable(true); end int_round_mode_fc.setSubBar(0); int_round_mode_result{end+1} = int_round_mode_fc; %--------------creates test_int_round_mode_checkActCallback function------- function int_round_mode_ActResult = ... test_int_round_mode_checkActCallback(taskobj) int_round_mode_obj = taskobj.MAObj; int_round_mode_ActResult = {}; system = getfullname(int_round_mode_obj.System); int_round_mode_fc = ModelAdvisor.FormatTemplate('TableTemplate'); int_round_mode_fc.setColTitles({'Block','Old Setting','New Setting'}) % find all blocks which have 'integer ronuding mode' setting all_rnd_meth_block = find_system(system,'RegExp','On','RndMeth','.'); % fix wrong config block length_rnd = length(all_rnd_meth_block); correct_cfg_rnd = 'Simplest'; for i = 1:length_rnd current_rnd = get_param(all_rnd_meth_block{i},'RndMeth'); if 0 == strcmp(correct_cfg_rnd,current_rnd) int_round_mode_fc.addRow({all_rnd_meth_block{i}, ... current_rnd,correct_cfg_rnd}); set_param(all_rnd_meth_block{i},'RndMeth',correct_cfg_rnd); else % Do nothing end end int_round_mode_fc.setSubBar(0); int_round_mode_ActResult = int_round_mode_fc; int_round_mode_obj.setActionEnable(false);%----End of test_int_round_mode_check -----------------------------------------
将脚本放到matlab工作目录下,然后在命令窗口输入sl_refresh_customizations
。
打开模型,并打开model advisor
点击检查本条规则
点击修复按钮
编写的规则存在一些使用上的bug,和Matlab版本有关,例如在Matlab2017a中,仅在第一次打开matlab时才能使用sl_refresh_customizations
命令进行model advisor的规则更新,如果修改了脚本代码,再次进行更新则会失败,此时需要重启Matlab才能更新,而这个问题在Matlab2016a中不存在。
联系客服