MATLAB®スクリプトでSimulink®モデルを修正してみた【第3回】実際にモデルを修正してみた

このブログでは、自動車業界で普及している、モデルベース設計ツールのMathWorks社のSimulink®で作成したモデルを、MATLAB®スクリプトで修正することを試みます。
今回は全3回のうちの第3回目で「実際にモデルを修正してみた」と題して、Simulink® APIを使用してSimulink®モデルの修正を行い、シミュレーションを実行する、一連の流れを説明します。
なお、全3回の内容は以下の通りです。
第1回:Simulink® APIの基本1(基礎の基礎)
第2回:Simulink® APIの基本2(モデル編集のAPI)
第3回:実際にモデルを修正してみた
実行した環境は以下の通りです。
OS | Microsoft Windows 10 Pro |
---|---|
MathWorks社製 | MATLAB® バージョン 9.9 (R2020b) |
Simulink® バージョン 10.2 (R2020b) |
目次
修正対象モデル
修正対象モデルは、図1の2入力の加算器とGainの各々1個からなる、サブシステム「Adds」をもつモデル「all_add.slx」を使用します。「第1回:Simulink® APIの基本1(基礎の基礎)」で使用したモデルです。
図1 修正対象モデル「all_add.slx」
出典:MATLAB®/Simulink®上で自らした、コマンド実行/実行結果のキャプチャー画像
モデル修正の内容
「all_add.slx」を対象にSimulink® APIを使用して以下の修正を行います。
- 2入力加算器Add_1を3入力に修正
- Gain_1を削除
- 修正した、サブシステム「Adds」と同構成のサブシステム「Adds1」を追加
手順
上記内容のモデル修正をして、シミュレーションの実行をSimulink® APIで行うためには、図2のような手順になります。大きく5つのStepに分かれます。各Stepで順に説明していきます。
図2 手順
出典:Microsoft® PowerPointで作成
Step1. 既存モデル読込み
既存モデルを読込むには図3のように変数sysにモデル名を設定し、
load_system(sys)
でモデルを読込みます。
今回は、モデルの変化の過程が見えるようにモデルを表示させるため、
open_system(sys)
もあわせて実行しています。図3のコマンドを実行することで、図1の上側のモデルが開いた状態になります。
図3 既存モデル読込み
出典:MATLAB®/Simulink®上で自らした、コマンド実行/実行結果のキャプチャー画像
Step2. サブシステム「Adds」の変更
加算器を2入力から3入力に変更
2入力の加算器add_1に変更を行うために、まずAdd_1のパスを検出するために、図4のように、
find_system(モデル名,’Name’,’Add_1’)
を実行します。その後、
set_system(設定対象のパス ‘Inputs’,’+++’)
で入力数を3入力に変更します。
図4 加算器の入力数変更のAPI実行
出典:MATLAB®/Simulink®上で自らした、コマンド実行/実行結果のキャプチャー画像
図5 加算器の入力数変更結果
出典:MATLAB®/Simulink®上で自らした、コマンド実行/実行結果のキャプチャー画像
APIの実行結果は図5の通り、加算器Add_1の入力が3つに増えています。
加算器の3つ目の入力値を設定
増やした加算器の3つ目の入力に定数ブロックで値「3」をつなぎます。
定数ブロックとは、加算器Add_1の親階層でつなぐため、まず入力ポートを追加します。
図6のように
get_param(Add_1のパス,’Parent’)
でAdd_1の親階層のパスを検出し、
add_block('simulink/Sources/In1', Add_1の親階層のパス+"/In3")
で入力ポート「In3」を追加します。APIの実行結果は図7の通りです。
図6 入力ポート追加のAPI実行
出典:MATLAB®/Simulink®上で自らした、コマンド実行/実行結果のキャプチャー画像
図7 入力ポート追加の結果
出典:MATLAB®/Simulink®上で自らした、コマンド実行/実行結果のキャプチャー画像
次に、追加された入力ポートIn3と加算器Add_1を結線します。図8のように、
add_line(結線する階層のパス,’In3/1’,’Add_1/3’)
で、「入力ポートIn3の出力端子1」と「加算器Add_1の入力端子3」を結線します。
APIの実行結果は図9の通りです。
図8 「入力ポートIn3の出力端子1」と「加算器Add_1の入力端子3」の結線のAPI実行
出典:MATLAB®/Simulink®上で自らした、コマンド実行/実行結果のキャプチャー画像
図9 「入力ポートIn3の出力端子1」と「加算器Add_1の入力端子3」の結線の結果
出典:MATLAB®/Simulink®上で自らした、コマンド実行/実行結果のキャプチャー画像
続いて、Add_1の親階層に定数ブロックを追加します。
図10のように、
add_block('simulink/Sources/Constant',sys+"/Constant2")
で定数ブロックを追加します。追加した定数ブロック「Constant2」で、値「3」、サンプリング時間が変数Ts、出力データ型がシングルになるように
set_param(sys+"/Constant2",'Value','3','SampleTime','Ts','OutDataTypeStr','single')
のように設定します。
add_line(sys,'Constant2/1','Adds/3')
を実行して、定数ブロック「Const2」の出力端子1と、サブシステム「Adds」の入力端子1を結線し、
Simulink.BlockDiagram.arrangeSystem(sys)
でsys階層をレイアウト整形します。
図10 定数ブロック追加のAPI実行
出典:MATLAB®/Simulink®上で自らした、コマンド実行/実行結果のキャプチャー画像
図11 定数ブロック追加結果
出典:MATLAB®/Simulink®上で自らした、コマンド実行/実行結果のキャプチャー画像
Gainブロックを削除
続いて、図9のGainブロックを削除します。図12のように、まず
find_system(parent_path{1},'BlockType','Gain','Gain','1');
で、削除対象のGainブロックのパスを抽出します。
今回は、対象ブロックの検索をブロックの名前ではなく、BlockTypeが「Gain」でゲイン係数が「1」を指定して行いました。
図12 Gainブロック削除のAPI実行
出典:MATLAB®/Simulink®上で自らした、コマンド実行/実行結果のキャプチャー画像
図13 Gainブロック削除結果
出典:MATLAB®/Simulink®上で自らした、コマンド実行/実行結果のキャプチャー画像
そして、削除対象のゲインブロックにつながるラインハンドルを
lh_gain = get_param(gain_path{1},'LineHandles');
で取得し、その中から、入力側、出力側につながるラインハンドルを
lh_gain_i = lh_gain(1).Inport;
lh_gain_o = lh_gain(1).Outport;
でそれぞれ抽出します。あとは、これらのラインハンドルを使って、ゲインブロックの入力につながるラインを
delete_line(lh_gain_i);
で、削除し、 ゲインブロックの出力につながるラインを
delete_line(lh_gain_o);
で削除します。最後に、ゲインブロックを
delete_block(gain_path {1});
で削除します。 図12のAPIを実行した結果は図13の通りです。
結線
Gainブロック削除後の、図13のAdd_1と出力端子1(出力ポート名「Out1」)の結線をします。
図14 結線のAPI実行
出典:MATLAB®/Simulink®上で自らした、コマンド実行/実行結果のキャプチャー画像
図15 結線の結果
出典:MATLAB®/Simulink®上で自らした、コマンド実行/実行結果のキャプチャー画像
図14のように、まず加算器「Add_1」のポートハンドルを
ph_add = get_param(ch_blk_path{1},'PortHandles');
で取得し、入力ポートハンドル、出力ポートハンドルを
ph_add_i = ph_add.Inport;
ph_add_o = ph_add.Outport;
でそれぞれ抽出します。
次に、出力ポート名「Out1」のパスを
outport_path = find_system(parent_path{1},'Name','Out1');
で検出し、出力ポートのポートハンドルを
ph_outport = get_param(outport_path{1},'PortHandles');
で取得します。
その中から、入力ポートハンドルを
ph_outport_i = ph_outport.Inport;
で抽出します。
抽出したポートハンドルを使用して、加算器「Add_1」の出力端子と出力ポート名「Out1」の入力端子を
add_line(parent_path{1},ph_add_o,ph_outport_i);
で結線します。図14のAPIを実行した結果は図15の通りです。
レイアウト整形
図15のように入力ポート3とAdd_1の結線のレイアウトが崩れているため、レイアウト整形をします。図6で使用した、Add_1の親階層のパスのparent_path{1}を使用して、図16のように整形対象階層を指定します。
Simulink.BlockDiagram.arrangeSystem(parent_path{1});
図16 レイアウト整形のAPI実行
出典:MATLAB®/Simulink®上で自らした、コマンド実行/実行結果のキャプチャー画像
図17 レイアウト整形の結果
出典:MATLAB®/Simulink®上で自らした、コマンド実行/実行結果のキャプチャー画像
図16のAPIを実行した結果は図17の通りです。
Step3. サブシステム「Adds1」の作成
サブシステム「Adds」をコピーして「Adds1」を作成
図18のようにサブシステム「Adds」をコピーして「Adds1」を作成するために、
add_block(sys + "/Adds",sys + "/Adds1");
を実行します。
今回は、途中経過の説明時のレイアウトを見やすくするために、
Simulink.BlockDiagram.arrangeSystem(sys);
も実行しました。図18のAPIを実行した結果は、図19の通りです。
図18 サブシステム「Adds1」作成のAPI実行
出典:MATLAB®/Simulink®上で自らした、コマンド実行/実行結果のキャプチャー画像
図19 サブシステム「Adds1」の作成結果
出典:MATLAB®/Simulink®上で自らした、コマンド実行/実行結果のキャプチャー画像
入力値を設定
サブシステム「Adds1」の入力値を設定します。図20のようにまず定数ブロックを追加するために、
add_block('simulink/Sources/Constant',sys+"/Constant3");
add_block('simulink/Sources/Constant',sys+"/Constant4");
add_block('simulink/Sources/Constant',sys+"/Constant5");
を実行します。
続いて、各定数ブロックに、値に「4」「5」「6」、サンプリング時間にTs、出力データ型にSingleを設定するために、
set_param(sys+"/Constant3",'Value','4','SampleTime','Ts','OutDataTypeStr','single');
set_param(sys+"/Constant4",'Value','5','SampleTime','Ts','OutDataTypeStr','single');
set_param(sys+"/Constant5",'Value','6','SampleTime','Ts','OutDataTypeStr','single');
を実行します。あとは、各定数ブロックの出力端子とサブシステム「Adds1」の入力端子を結線するために、
add_line(sys,'Constant3/1','Adds1/1');
add_line(sys,'Constant4/1','Adds1/2');
add_line(sys,'Constant5/1','Adds1/3');
を実行します。そして最後に、途中経過の説明時のレイアウトを見やすくするために、
Simulink.BlockDiagram.arrangeSystem(sys);
でレイアウト整形します。
図20 入力値設定のAPIを実行
出典:MATLAB®/Simulink®上で自らした、コマンド実行/実行結果のキャプチャー画像
図21 入力値設定の結果
出典:MATLAB®/Simulink®上で自らした、コマンド実行/実行結果のキャプチャー画像
図20のAPIを実行した結果は図21の通りです。
Displayブロック追加
図21で、サブシステム「Adds1」の接続先として、Displayブロック「Display1」を追加するために、図22のように
add_block('simulink/Sinks/Display',sys+"/Display1");
を実行します。そして、サブシステム「Adds1」の出力端子1とDisplayブロック「Display1」の入力端子1を結線するために、
add_line(sys,'Adds1/1','Display1/1');
を実行します。最後に、レイアウト整形をするために
add_line(sys,'Adds1/1','Display1/1');
を実行します。図22のAPIの実行結果は図23の通りです。
図22 Displayブロック追加のAPI実行
出典:MATLAB®/Simulink®上で自らした、コマンド実行/実行結果のキャプチャー画像
図23 Displayブロック追加の結果
出典:MATLAB®/Simulink®上で自らした、コマンド実行/実行結果のキャプチャー画像
Step4. シミュレーション実行
モデルの修正が終わったので、シミュレーションを実行して期待通りの値が得られるか確認します。
今回は、図24のように変数Tstopに値を設定した後、
set_param(sys,'StopTime','Tstop');
として、Tstopをシミュレーション終了時間に設定しました。
図24のAPIを実行した結果は図 25の通りです。橙色の枠で囲まれた箇所に終了時間が設定されています。
図24 シミュレーション終了時間を設定するAPI実行
出典:MATLAB®/Simulink®上で自らした、コマンド実行/実行結果のキャプチャー画像
図25 シミュレーション終了時間を設定した結果
出典:MATLAB®/Simulink®上で自らした、コマンド実行/実行結果のキャプチャー画像
図26 シミュレーション開始のAPIを実行
出典:MATLAB®/Simulink®上で自らした、コマンド実行/実行結果のキャプチャー画像
図27 シミュレーションを実行した結果
出典:MATLAB®/Simulink®上で自らした、コマンド実行/実行結果のキャプチャー画像
準備が整ったので、最後に図26のように
sim(sys);
として、シミュレーションを開始します。図27がシミュレーションの結果です。
Displayブロックにサブシステム「Adds」、「Adds1」各々の出力結果が表示されており、期待通りの結果が得られています。
Step5. モデルの保存&クローズ
最後に、修正したモデルを保存し、クローズします。まず図28のように、
sys_new = 'all_add_new';
で、修正したモデルにつける、新たなモデル名を変数sys_newに設定し、
save_system(sys,sys_new);
を実行し保存します。そして
close_system(sys_new);
でモデルをクローズして終了です。
図28 モデルの保存&クローズ
出典:MATLAB®/Simulink®上で自らした、コマンド実行/実行結果のキャプチャー画像
おわりに
今回は「MATLAB®スクリプトでSimulink®モデルを修正してみた」の第3回目で「実際にモデルを修正してみた」と題して、Simulink® APIを使用してSimulink®モデルの修正を行い、シミュレーションを実行し、一連の流れを説明しました。
シミュレーションで期待した結果が得られ、正しく修正できたことを確認できました。
ブログ内で説明した、Simulink® APIによるSimulink®モデルの修正のMATLAB®スクリプト「sample_prg.m」、変更前モデル「all_add.slx」については、以下よりダウンロードしてご活用ください。
モデルベースデザイン設計委託やお手元にあるSimulink®モデルのHDL化のご要望がございましたら、お気軽にお問い合わせください。
最後までお付き合いいただきありがとうございました。
参考文献
[1]:MathWorks社 「Simulink API トレーニング」テキスト, 2019年
[2]: MathWorks社Webサイト,「プログラムによるモデル編集」