Main Content

モデル アドバイザー カスタム コンフィギュレーションの作成と展開

モデルが企業の標準やモデリング ガイドラインに適合していることをチェックするために、モデル アドバイザーをカスタマイズできます。この例では、モデル アドバイザーにカスタム チェックを追加する方法と、必要のない付属チェックを削除する方法について説明します。カスタム チェック構成は保存して、開発グループの他の人に展開できます。カスタム コンフィギュレーションを展開すると、開発グループが同じチェック セットを使用してモデルを確認できるようになります。

カスタム チェックの定義

この例では、4 種類のカスタム チェックを定義します。

  • 修正アクションを提供する編集時のチェック。

  • モデル アドバイザーでのみ実行される、結果をブロックおよびサブシステムごとにグループ化して修正アクションを提供するチェック。

  • モデル アドバイザーでのみ実行される、モデル コンフィギュレーション パラメーター設定を検証するチェック。

  • ブロック パラメーター設定に制約を指定して修正アクションを提供する編集時のチェック。

サンプル ファイルの中に sl_customization.m ファイルが含まれています。このファイルには、カスタム チェックを定義する関数の呼び出しを含む関数 sl_customization が含まれています。sl_customization.m ファイルを開いて検証します。

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
defineEditTimeCheck
defineDetailStyleCheck;
defineConfigurationParameterCheck;
defineNewBlockConstraintCheck;

関数 sl_customization は、カスタム チェックを登録するための addModelAdvisorCheckFcn メソッドを含むカスタマイズ マネージャー オブジェクトを受け入れます。このメソッドへの入力は、4 つのカスタム チェックに対応する 4 つのチェック定義関数の呼び出しを含む関数 defineModelAdvisorChecks へのハンドルです。

修正を伴う編集時チェック

defineEditTimeCheck.m ファイルには、チェック定義関数 defineEditTimeCheck が含まれています。これは、Inport ブロックと Outport ブロックが出力データ型に応じた所定の色になっているかどうかを確認するチェックを定義する関数です。このチェックでは、編集された他のブロックを確認する必要がありますが、同じレベルやモデルの階層構造全体の影響を受けるブロックについて確認する必要はありません。このチェックは、正しい色になっていないブロックの色を更新する修正を提供します。このチェックの名前は Check color of Inport and Outport blocks です。このチェックは編集時およびモデル アドバイザーで実行されます。defineEditTimeCheck.m ファイルを開いて検証します。

function defineEditTimeCheck

% Check the background color of Inport and Outport blocks.
rec = ModelAdvisor.Check("advisor.edittimecheck.PortColor");
rec.Title = 'Check color of Inport and Outport blocks';
rec.CallbackHandle = 'MyEditTimeChecks.PortColor'; 
mdladvRoot = ModelAdvisor.Root;
mdladvRoot.publish(rec,'Demo');

この編集時チェックには、ModelAdvisor.EdittimeCheck基底クラスから派生するクラス定義 PortColor が含まれています。このタイプのチェックを作成する方法の詳細については、Define Edit-Time Checks to Comply with Conditions that You Specify with the Model Advisorを参照してください。+MyEditTimeChecks という名前のフォルダーを作成し、このフォルダーに PortColor.m を保存します。

copyfile PortColor.m* +MyEditTimeChecks

PortColor.m ファイルを開いて検証します。

classdef PortColor < ModelAdvisor.EdittimeCheck
    % Check that ports conform to software design standards for background color.
    %
    %   Background Color                Data Types
    %   orange                          Boolean
    %   green                           all floating-point
    %   cyan                            all integers
    %   Light Blue                      Enumerations and Bus Objects
    %   white                           auto
    %


    methods
        function obj=PortColor(checkId)
            obj=obj@ModelAdvisor.EdittimeCheck(checkId);
            obj.traversalType = edittimecheck.TraversalTypes.BLKITER;                       
        end
        
        function violation = blockDiscovered(obj, blk)
            violation = [];  
            if strcmp(get_param(blk,'BlockType'),'Inport') || strcmp(get_param(blk,'BlockType'),'Outport')
                
                dataType = get_param(blk,'OutDataTypeStr');
                currentBgColor = get_param(blk,'BackgroundColor');
                
                if strcmp(dataType,'boolean')
                        if ~strcmp(currentBgColor, 'orange')
                            % Create a violation object using the ModelAdvisor.ResultDetail class.
                            violation = ModelAdvisor.ResultDetail;
                            ModelAdvisor.ResultDetail.setData(violation,'SID',Simulink.ID.getSID(blk));
                            violation.CheckID = obj.checkId;
                            violation.Description = 'Inport/Outport blocks with Boolean outputs should be orange.';
                            violation.title = 'Port Block Color';
                            violation.ViolationType = 'Warning';
                        end
                elseif any(strcmp({'single','double'},dataType))
                        if ~strcmp(currentBgColor, 'green')
                            violation = ModelAdvisor.ResultDetail;
                            ModelAdvisor.ResultDetail.setData(violation,'SID',Simulink.ID.getSID(blk));
                            violation.CheckID = obj.checkId;
                            violation.Description = 'Inport/Outport blocks with floating-point outputs should be green.';
                            violation.title = 'Port Block Color';
                            violation.ViolationType = 'Warning';
                        end
                elseif any(strcmp({'uint8','uint16','uint32','int8','int16','int32'}, dataType))
                        if ~strcmp(currentBgColor, 'cyan')
                            violation = ModelAdvisor.ResultDetail;
                            ModelAdvisor.ResultDetail.setData(violation,'SID',Simulink.ID.getSID(blk));
                            violation.CheckID = obj.checkId;
                            violation.Description = 'Inport/Outport blocks with integer outputs should be cyan.';
                            violation.title = 'Port Block Color';
                            violation.ViolationType = 'Warning';
                        end
                elseif contains(dataType,'Bus:')
                    if ~strcmp(currentBgColor, 'lightBlue')
                        violation = ModelAdvisor.ResultDetail;
                        ModelAdvisor.ResultDetail.setData(violation,'SID',Simulink.ID.getSID(blk));
                        violation.CheckID = obj.checkId;
                        violation.Description = 'Inport/Outport blocks with bus outputs should be light blue.';
                        violation.title = 'Port Block Color';
                        violation.ViolationType = 'Warning';
                    end
                 elseif contains(dataType,'Enum:')
                    if ~strcmp(currentBgColor, 'lightBlue')
                        violation = ModelAdvisor.ResultDetail;
                        ModelAdvisor.ResultDetail.setData(violation,'SID',Simulink.ID.getSID(blk));
                        violation.CheckID = obj.checkId;
                        violation.Description = 'Inport/Outport blocks with enumeration outputs should be light blue.';
                        violation.title = 'Port Block Color';
                        violation.ViolationType = 'Warning';
                    end
                elseif contains(dataType, 'auto')
                    if ~strcmp(currentBgColor, 'white')
                        violation = ModelAdvisor.ResultDetail;
                        ModelAdvisor.ResultDetail.setData(violation,'SID',Simulink.ID.getSID(blk));
                        violation.CheckID = obj.checkId;
                        violation.Description = 'Inport/Outport blocks with auto outputs should be white.';
                        violation.title = 'Port Block Color';
                        violation.ViolationType = 'Warning';
                    end                    
                end
            end  
        end
        
        function violation = finishedTraversal(obj)            
            violation = [];
        end
        
        function success = fix(obj, violation)
            success = true;
            dataType = get_param(violation.Data,'OutDataTypeStr');
            if strcmp(dataType,'boolean')
                set_param(violation.Data,'BackgroundColor','orange');
            elseif any(strcmp({'single','double'},dataType))
                set_param(violation.Data,'BackgroundColor','green');
            elseif any(strcmp({'uint8','uint16','uint32','int8','int16','int32'}, dataType))
                set_param(violation.Data,'BackgroundColor','cyan');
            elseif contains(dataType,'Bus:')  || contains(dataType,'Enum:')
                set_param(violation.Data,'BackgroundColor','lightBlue');
            elseif contains(dataType,'auto')
                set_param(violation.Data,'BackgroundColor','white');
            end
        end
    end
end

修正を伴うモデル アドバイザー チェック

defineDetailStyleCheck.m ファイルには、チェック定義関数 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.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
    
   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

このチェックはsetCallbackFcnタイプの DetailStyle を使用します。このスタイルを適用すると既定の書式が生成されるため、ModelAdvisor.FormatTemplateまたはその他のモデル アドバイザーの書式設定 API を使用して、モデル アドバイザーに表示される結果の書式設定を行う必要がなくなります。このタイプのチェック定義関数を作成する方法の詳細については、モデルを修正し、モデル アドバイザーで指定した条件に準拠させるを参照してください。

モデル コンフィギュレーション パラメーター設定のチェック

defineConfigurationParameterCheck.m ファイルには、チェック定義関数 defineConfigurationParameterCheck が含まれています。これは、MISRA C:2012 準拠コード生成に影響を与える可能性のあるモデル コンフィギュレーション パラメーター設定を特定するチェックを定義する関数です。このチェックの名前は [Check model configuration parameters] です。

このチェックでは、チェック対象のモデル コンフィギュレーション パラメーター設定を含むサポート XML データ ファイルが MATLAB パス上になければなりません。この例では、このファイルは configurationParameterDataFile.xml. です。このチェック タイプを作成する方法の詳細については、モデル コンフィギュレーション パラメーターに対するモデル アドバイザー チェックの作成を参照してください。

defineConfigurationParameterCheck.m ファイルを開いて検証します。

function defineConfigurationParameterCheck

% Create ModelAdvisor.Check object and set properties.
rec = ModelAdvisor.Check('com.mathworks.sample.configurationParameter');
rec.Title = 'Check model configuration parameters';
rec.setCallbackFcn(@(system)(Advisor.authoring.CustomCheck.checkCallback...
    (system)), 'None', 'StyleOne');
rec.TitleTips = 'Identify configuration parameters that might impact MISRA C:2012 compliant code generation.';

% --- data file input parameters
rec.setInputParametersLayoutGrid([1 1]);
inputParam1 = ModelAdvisor.InputParameter;
inputParam1.Name = 'Data File';
inputParam1.Value = 'configurationParameterDataFile.xml';
inputParam1.Type = 'String';
inputParam1.Description = 'Name or full path of XML data file.';
inputParam1.setRowSpan([1 1]);
inputParam1.setColSpan([1 1]);
rec.setInputParameters({inputParam1});

% -- set fix operation
act = ModelAdvisor.Action;
act.setCallbackFcn(@(task)(Advisor.authoring.CustomCheck.actionCallback...
    (task)));
act.Name = 'Modify Settings';
act.Description = 'Modify model configuration settings.';
rec.setAction(act);

% publish check into Demo folder.
mdladvRoot = ModelAdvisor.Root;
mdladvRoot.publish(rec, 'Demo'); 

end

ブロック パラメーターの制約のチェック

defineNewBlockConstraintCheck.m ファイルには、チェック定義関数 defineNewBlockConstraintCheck が含まれます。これは、矩形形状を持たない Logical Operator ブロックを特定するチェックを定義する関数です。このチェックの名前は、[Logical Operator ブロックのアイコン形状をチェック] です。

ブロック パラメーターの制約のチェックは編集時のチェックをサポートします。このチェック タイプの詳細については、サポートされる、およびサポートされないブロックおよびパラメーターのモデル アドバイザー チェックの定義を参照してください。

defineNewBlockConstraintCheck.m ファイルを開き、検証します。.

function defineNewBlockConstraintCheck

rec = Advisor.authoring.createBlockConstraintCheck('com.mathworks.sample.blockConstraint',...
    'Constraints',@createBlockConstraints); % constraint creation is part of block constraint check definition
rec.Title = 'Check icon shape of Logical Operator blocks';
rec.TitleTips = 'Checks icon shape of Logical Operator blocks. Icon shape of Logical Operator should be rectangular.';

% Publish check into Demo folder.
mdladvRoot = ModelAdvisor.Root;
mdladvRoot.publish(rec, 'Demo'); 

end

function constraints = createBlockConstraints()

% Create block constraints.
c1 = Advisor.authoring.PositiveBlockParameterConstraint;
c1.ID = 'ID_c1';
c1.BlockType = 'Logic';
c1.ParameterName = 'IconShape';
c1.SupportedParameterValues = {'rectangular'};
c1.ValueOperator = 'eq';

constraints = {c1};

end

関数 createBlockConstraints によってブロック制約 c1 が定義されます。関数 Advisor.authoring.createBlockConstraintCheck には、制約作成関数 createBlockConstraints を呼び出す 'Constraints' 名前と値の引数があります。

モデル アドバイザーでのカスタム チェックの表示

カスタム チェックを利用できることを確認するには、モデル アドバイザーを開きます。

1.カスタム チェックがモデル アドバイザーで表示されるようにするには、モデル アドバイザー チェックの情報キャッシュを更新しなければなりません。MATLAB コマンド プロンプトで、次のように入力します。

Advisor.Manager.refresh_customizations();

2.モデル例を開きます。

open_system('AdvisorCustomizationExample.slx');

3.[モデル化] タブで [モデル アドバイザー] を開きます。MATLAB コマンド プロンプトに次のコマンドを入力してモデル アドバイザーを開くこともできます。

modeladvisor('AdvisorCustomizationExample.slx');
Updating Model Advisor cache...
Model Advisor cache updated. For new customizations, to update the cache, use the Advisor.Manager.refresh_customizations method.

4.[製品別][デモ] フォルダーを展開します。チェック定義関数内のpublishコマンドは、[製品別][デモ] フォルダーにチェックを追加します。

モデル アドバイザー カスタム コンフィギュレーションの指定と展開

モデル アドバイザーに含めるチェックや編集時のチェックに含めるチェックを指定するには、モデル アドバイザーの構成エディターを使用します。

1.構成エディターを開くには、モデル アドバイザーで [開く]、[設定エディターを開く] をクリックします。

2.チェックおよびフォルダーを追加または削除するには、モデル アドバイザーの設定エディターの [編集] セクションのオプションから選択します。

3.コンフィギュレーションを保存するには、[保存] を選択します。構成を JSON ファイルとして保存することを求めるウィンドウが表示されます。この例では、demoConfiguration.json ファイルにこの例の 4 つのカスタム チェックが含まれているため、構成を保存する必要はありません。

4.モデルを閉じ、モデル アドバイザーの設定エディターを閉じます。

bdclose;

モデルへのカスタム チェック構成の関連付けとチェックの問題への対処

チェックの問題に対処するには、まずモデルに構成を関連付けます。その後、編集時およびモデル アドバイザーで問題に対処できます。

1.モデル例を開きます。

open_system('AdvisorCustomizationExample.slx');

2.カスタム構成 demoConfiguration.json をモデルに関連付けます。カスタム構成をモデルに関連付けると、モデルを開くたびに同じチェック構成がモデルで使用されます。[モデル化] タブをクリックし、[モデル アドバイザー]、[編集時チェック] を選択します。[コンフィギュレーション パラメーター] ダイアログ ボックスで、[モデル アドバイザー] 構成ファイル パラメーターに構成ファイルのパスを指定します。あるいは、コマンド プロンプトで次のコマンドを入力します。

ModelAdvisor.setModelConfiguration('AdvisorCustomizationExample', 'demoConfiguration.json');

3.[モデル化] タブをクリックし、[モデル アドバイザー]、[編集時チェック] を選択して、編集時のチェックをオンにします。[コンフィギュレーション パラメーター] ダイアログ ボックスが開きます。[編集時チェック] パラメーターを選択します。あるいは、コマンド プロンプトで次のコマンドを入力できます。

edittime.setAdvisorChecking('AdvisorCustomizationExample','on');

モデルの最上位レベルで、2 つの Inport ブロックの出力データ型が int32 になっています。これらのブロックはシアンでなければならないため、編集時の警告が生成されます。Outport ブロックについては、データ型が auto で白になっているため、警告は生成されません。

4.それぞれの Inport ブロックについて、編集時の警告のウィンドウをクリックします。次に [修正] をクリックします。ブロックの色がシアンに変わり、警告が表示されなくなります。

5.Logical Operator ブロックの形状は矩形でなければならないため、警告が生成されます。編集時の警告のウィンドウをクリックし、[修正] をクリックします。Logical Operator ブロックの形状が矩形に変わり、警告が表示されなくなります。

6.編集時のチェックの警告に対処したので、次にモデル アドバイザーを開いて残りのチェックの問題に対処します。

modeladvisor('AdvisorCustomizationExample.slx');
Model Advisor is removing the existing report.

7.モデル アドバイザーには、カスタム構成の 4 つのチェックが含まれています。[チェックの実行] をクリックします。編集時に対処した 2 つのチェックにはパスします。他の 2 つのチェックでは警告が生成されます。

8.[ブロック名がブロックの下になっているかどうかをチェック] チェックをクリックします。修正を適用して警告を解決するには、右側のペインで [修正] をクリックします。

9.[Check model configuration parameters] チェックをクリックします。修正を適用して警告を解決するには、[修正] をクリックします。

10.チェックを再度実行します。今度はパスします。

11.モデルとモデル アドバイザーを閉じます。

bdclose;

12.作業ディレクトリからファイルを削除します。次のコマンドを入力して、モデル アドバイザー チェックの情報キャッシュを更新します。

Advisor.Manager.refresh_customizations

プログラムによってモデル アドバイザー カスタム コンフィギュレーションを実行し、結果を表示

プログラムによってモデル アドバイザー構成を実行し、結果をモデル アドバイザーで開くことができます。

1.関数ModelAdvisor.runを呼び出します。

SysResultObjArray = ModelAdvisor.run({'AdvisorCustomizationExample'},...
'Configuration','demoConfiguration.json');

2.モデル アドバイザーで結果を表示します。

viewReport(SysResultObjArray{1},'MA')

3.ダイアログ ボックスで [続行] をクリックします。修正を適用して警告を解決できるようになります。

4.モデルとモデル アドバイザーを閉じます。

bdclose;

5.作業ディレクトリからファイルを削除します。次のコマンドを入力して、モデル アドバイザー チェックの情報キャッシュを更新します。

Advisor.Manager.refresh_customizations

参考

|

関連するトピック