Tagebuch von Spargel

最近zennに移行しましたhttps://zenn.dev/spargel

MATLAB/Simulink シミュレーションパラメータをtableで管理する

本記事は
MATLAB/Simulink Advent Calendar 2022のカレンダー | Advent Calendar 2022 - Qiita
の10日目の記事になります.

はじめに

MATLAB/Simulinkでシミュレーションをすることはよくあります.
その際,パラメータを変化させて結果の比較をすることがよくあると思いますが,そのパラメータはどのように管理しているでしょうか?
本記事は,MATLABのtableを使用して,パラメータを変えた試験ケースを管理することで,諸々楽になるかもしれないという記事です.
流れとしては,MATLABのTABLEで試験ケースを作成→MATLABに読み込んで実行→結果の保存となります.
記事ではMATLABのみの記載ですが,付録にSimulinkの場合を記載しています.

参考:
table - MATLAB & Simulink - MathWorks 日本

対象者

  • シミュレーションケースのパラメータがわからず,後で思い出すのに苦労したことがある人
  • 試験ケースの管理につかれた人
  • 一目でシミュレーションパラメータをわかるようにして引き継ぎを楽にしたい人
  • 試験ケース毎の命名ルールは決めるものの長すぎてすぐ守れなくなる人(私です)

等々

シミュレーション例

例えば,下記の関数で振幅 Aや角周波数 \omegaを変えてでシミュレーションしたい場合を考えていきます.
 y=f(t), ~~f(t) = A\sin(\omega t + \phi) + c

試験ケースを作成して回すまでの流れ

tableを作成してパラメータ入力する.

コマンドラインに下記を打ち込み,空のtableを作成します.

caseSet = table;

作成したcaseSetをダブルクリックすると変数ウィンドウが開くので,列名を変数に,行名を試験ケース名にしてパラメータを書き込んでいきます.
ここで注意することとして,下記の仕様があります.

  • 列名はセルに値を入れてからでないと,設定ができません.
  • 行名は最初の一行はコマンドで設定する必要があります.二行目以降は変数ウィンドウで書き込めます.
% 例
caseSet.Properties.RowNames(1) = "case001"
  • 数式の入力をすると,計算された結果が格納されます.
  • 文字列の格納も可能です.
  • 列の変数の型は同じにする必要があります.同じ列に数値型と文字列を入れ込むことはできません.

実際の操作画面は下記を見ていただくとわかりやすいと思います.
操作感はエクセルににており,コピーペーストも可能です.

gifの最後のほうで分かるように,tableの操作はデフォルトであればコマンドウィンドウにすべて表示されるので,それを見ながらコードで記述することも可能です.
また,同じ内容は下記コードで実行できます.

% パラメータをコードで実行
caseSet = table;
caseSet.A = 1;
caseSet.omega = 2;
caseSet.phi = (1/4)*pi;
caseSet.c = 0.2;
caseSet.Properties.RowNames(1) = "case001";

二行目以降は下記で追加できます.以降,i行目のパラメータはcaseSet.args(i,1)で入れることができます.
パラメータを追加した際にwarningが出ますが,明示していない変数を既定値で埋めるwarningなので,特に気にしなくても大丈夫です.

caseSet.A(2,1) = 1;
caseSet.omega(2,1) = 3;
caseSet.phi(2,1) = (1/2)*pi;
caseSet.c(2,1) = 0.3;
caseSet.Properties.RowNames(2) = "case002";

ここまででわかるように,table自体はpythonのDataFrameなどのような使い方です.(本来はそっちが正当な使い方)
また,関数自体をパラメータに含めることも可能ですが,これは後に記載します..(例えば \sin(t)の場合と \cos(t)の場合をシミュレーションしたいときなど.)

ここまでの操作により,caseSetは下記のようになります.

これを保存しておきます.

save('caseName.mat','caseSet','-mat')

パラメータを読み込んでシミュレーションの実行

load関数で先ほどのcaseSetを読み込み,そのあと各パラメータを読みだしていきます.
注:ここからはソースコードが長くなるため,適宜コードを折りたたんでいます.

load("caseName.mat");

読み出し方は複数ありますので,下記にその例を記載します.

% 一行目(case001を読みだす)
A = caseSet(1,:).A
A = caseSet("case001",:).A
A = caseSet(1,"A").Variables

case001を読み出してシミュレーションする場合は下記のようになります.


プロットすると下記のようにちゃんと読み込めて計算できていることがわかります..

複数の試験ケースをまとめて実行する場合は下記のようになります.


結果は下記のようになり,確かに2つのケースでシミュレーションを行えていることが確かめられます.

以上で試験ケースの作成から実行までを行うことができました.

そのほか小技

パラメータに関数を含める

関数を含めたい場合は,無名関数の形で記入すれば可能です.
文字列として入れる必要があります.
例:sinとcosを使用するとき
列にfuncという列に関数を書き込んでいます.(便宜上caseSet2としています)

読み出し方:
str2func関数を使用します.
jp.mathworks.com

    func = caseSet2(caseSetName,:).func{1,1}; %文字列の取り出しには{1,1}が必要
    func = str2func(func); %ここで文字列から無名関数に変える

まとめて呼び出してプロットすると下記のようになります.
sinとcosでそれぞれ実行できていることが確認できます.



付録(Simulinkでの運用例)

おわりに

今回やっていることはただパラメータテーブルを読み込んでいるだけなので単純なのですが,
試験ケース毎に変数をsaveしておくことで,後々見返す際に当時想定していたパラメータを
確認できるというのが便利なところかなと思います.

これでケース名やパラメータ管理に悩む人が少しでも減ればいいなと思います.