【MATLAB/Simulink】スクリプトによるモデル自動作成の実例

MATLABスクリプトを使ってブロックを配置したり、ブロック同士の結線を行うことができます。

ここでは実際にモデルを自動で作成するスクリプトの例を紹介します。

スポンサーリンク

作成するモデル

以下のように複数のConstantブロックをMuxブロックに接続し、MuxブロックとOutportブロックを接続するモデルを作成します。

配置するモデルは既に開いており、アクティブになっているとします。(gcsコマンドを打つとブロックを配置したいサブシステムのパスが表示される状態)

また、Constantに設定する定数名はベースワークスペースに存在するセル配列”ConstNameList”の値を参照するものとします。

処理のフロー

今回のモデルを作成する処理フローとして、以下が考えられます。

①Muxブロックを配置する

②Muxブロックの配置位置、サイズを変更する

③Muxブロックの入力数を変更する

—④~⑦は配置するConstantブロックの数だけループさせる—

④Constantブロックを配置する

⑤Constantブロックの配置位置を変更する

⑥ConstantブロックのValueプロパティに定数名を設定する

⑦ConstantブロックとMuxブロックを結線する

—ループ終了—

⑧Outportブロックを配置する

⑨Outportブロックの配置位置を変更する

⑩MuxブロックとOutportブロックを結線する

⑪信号線に名前を付ける

配置する順番はMux→Constant→Outportとしました。

Constant→Muxと配置するとConstantを置くために1回ループし、更にMuxと各Constantブロックを結線をするためにもう一度ループする必要があるため処理が冗長になります。

スクリプトサンプル

実際のスクリプトがこちらです。

function make_model_sample()

%% 事前準備
% 基準となる位置(最初のConstantブロックが置かれる位置)
BASEPOS_X = 40;
BASEPOS_Y = 50;
% Constantブロックの間隔(縦方向)
CONSTSPACE = 20;
% ConstantブロックとMuxブロックの間隔(横方向)
CONSTMUXSPACE = 200;
% MuxブロックとOutportブロックの間隔(横方向)
MUXOUTPORTSPACE = 200;
% CONSTブロックの幅
CONSTWIDTH = 80;
% Constantブロックの高さ
CONSTHEIGHT = 30;

% Constant定数リストをベースワークスペースから取ってくる
constNameList = evalin('base', 'constNameList');

% 配置するConstantブロックの数
constCount = size(constNameList, 1);

%% ①Muxブロックを配置する
muxH = add_block('simulink/Signal Routing/Mux', [gcs, '/Mux'], 'MakeNameUnique', 'on');

%% ②Muxブロックの配置位置を変更する
% Muxブロックの縦幅、横幅を算出
% 縦幅はConstantの高さと幅から算出
muxHeight = CONSTHEIGHT * constCount + CONSTSPACE * (constCount - 1) + 10;
% 横幅はデフォルトの横幅から変更しない
muxPos = get(muxH, 'Position');
muxWidth = muxPos(3) - muxPos(1);

% Muxブロックの基準位置(X軸)
muxBaseXpos = BASEPOS_X + CONSTWIDTH + CONSTMUXSPACE;
% Muxブロックの基準位置(Y軸)
muxBaseYpos = BASEPOS_Y - 5;

% 位置を変更
set(muxH, 'Position', [muxBaseXpos, muxBaseYpos, muxBaseXpos+muxWidth, muxBaseYpos+muxHeight]);

%% ③Muxブロックの入力数を変更する
set(muxH, 'Inputs', num2str(constCount));
% 結線用にポートハンドルを取得
muxPH = get(muxH, 'PortHandles');

for icnt = 1 : constCount
    %% ④Constantブロックを配置する
    constH = add_block('simulink/Sources/Constant', [gcs, '/Constant'], 'MakeNameUnique', 'on');
    
	%% ⑤Constantブロックの配置位置を変更する

    % Constantブロックの高さの基準位置をMuxブロックのInportの位置とする
    muxOutPos = get(muxPH.Inport(icnt), 'Position');
    % 位置を変更
    set(constH, 'Position', [BASEPOS_X, muxOutPos(2)-CONSTHEIGHT/2, BASEPOS_X+CONSTWIDTH, muxOutPos(2)+CONSTHEIGHT/2]);
    
    %% ⑥ConstantブロックのValueプロパティに定数名を設定する
    set(constH, 'Value', constNameList{icnt, 1});
    
    %% ⑦ConstantブロックとMuxブロックを結線する
    constPH = get(constH, 'PortHandles');
    add_line(gcs, constPH.Outport, muxPH.Inport(icnt));
end
%% ⑧Outportブロックを配置する
outportH = add_block('simulink/Sinks/Out1', [gcs, '/sample_sig'], 'MakeNameUnique', 'on');

%% ⑨Outportブロックの配置位置を変更する
% 縦幅、横幅共にデフォルトから変更しない
outportPos = get(outportH, 'Position');
% Outportブロックの縦幅、横幅を算出
outportHeight = outportPos(4) - outportPos(2);
outportWidth = outportPos(3) - outportPos(1);
% Outportブロックの高さの基準位置をMuxブロックのOutportの位置とする
muxOutPos = get(muxPH.Outport, 'Position');

% Muxブロックの基準位置(X軸)
outportBaseXpos = muxBaseXpos + muxWidth + MUXOUTPORTSPACE;
% Muxブロックの基準位置(Y軸)
outportBaseYpos = muxOutPos(2) - outportHeight / 2;
% 位置を変更
set(outportH, 'Position', [outportBaseXpos, outportBaseYpos, outportBaseXpos+outportWidth, outportBaseYpos+outportHeight]);

%% ⑩MuxブロックとOutportブロックを結線する
% outportブロックのポートハンドル
outportPH = get(outportH, 'PortHandles');
lineH = add_line(gcs, muxPH.Outport, outportPH.Inport);

%% ⑪信号線に名前を付ける
set(lineH, 'Name', 'sample_sig');

実行結果は以下の通りです。

スクリプト解説

ここからはスクリプトの中身を一部ピックアップして簡単に解説したいと思います。

%% 事前準備
% 基準となる位置(最初のConstantブロックが置かれる位置)
BASEPOS_X = 40;
BASEPOS_Y = 50;
% Constantブロックの間隔(縦方向)
CONSTSPACE = 20;
% ConstantブロックとMuxブロックの間隔(横方向)
CONSTMUXSPACE = 200;
% MuxブロックとOutportブロックの間隔(横方向)
MUXOUTPORTSPACE = 200;
% Constantブロックの幅
CONSTWIDTH = 80;
% Constantブロックの高さ
CONSTHEIGHT = 30;

自動作成するモデルの見た目をある程度自由に変更するための設定をしておきます。

完成したモデルを見て、もう少しConstantの幅があった方がいいとか感じた場合にすぐ変更できます。

% Constant定数リストをベースワークスペースから取ってくる
constNameList = evalin('base', 'constNameList');
% 配置するConstantブロックの数
constCount = size(constNameList, 1);

ベースワークスペースの変数を参照するためにevalin関数を使っています。

%% ②Muxブロックの配置位置を変更する
% Muxブロックの縦幅、横幅を算出
% 縦幅はConstantの高さと幅から算出
muxHeight = CONSTHEIGHT * constCount + CONSTSPACE * (constCount - 1) + 10;
% 横幅はデフォルトの横幅から変更しない
muxPos = get(muxH, 'Position');
muxWidth = muxPos(3) - muxPos(1);

% Muxブロックの基準位置(X軸)
muxBaseXpos = BASEPOS_X + CONSTWIDTH + CONSTMUXSPACE;
% Muxブロックの基準位置(Y軸)
muxBaseYpos = BASEPOS_Y - 5;

% 位置を変更
set(muxH, 'Position', [muxBaseXpos, muxBaseYpos, muxBaseXpos+muxWidth, muxBaseYpos+muxHeight]);

Muxブロックの縦幅はConstantブロックの数で決まります。Constantブロック一つがCONSTHEIGHT(30)で、間隔がCONSTSPACE(20)と設定しているので、それにブロック数をかければ高さが決まります。

10足しているのは+αしたほうが見た目が良さそうというだけの理由です。

    %% ⑤Constantブロックの配置位置を変更する
    % Constantブロックの高さの基準位置をMuxブロックのInportの位置とする
    muxOutPos = get(muxPH.Inport(icnt), 'Position');
    % 位置を変更
    set(constH, 'Position', [BASEPOS_X, muxOutPos(2)-CONSTHEIGHT/2, BASEPOS_X+CONSTWIDTH, muxOutPos(2)+CONSTHEIGHT/2]);

ブロックとブロックを直線で結ぶためにConstantブロックの中央がMuxブロックのInportと合うように設定しています。MuxとOutportも同じようにしています。

終わりに

もしスクリプトで聞きたいことがあれば答えられる範囲で回答しますので、その際はお気軽にコメントしてください。

コメント

タイトルとURLをコピーしました