ドキュメンテーション

最新のリリースでは、このページがまだ翻訳されていません。 このページの最新版は英語でご覧になれます。

構造体形式での状態のログ

この例では、状態を配列形式でログに記録するという従来の方法よりも、Simulink® モデルの状態軌跡を構造体形式でログに記録する方が効率がよいことを示します。ログが作成される行列の列に沿った状態の順序は、モデルのコンパイル時に Simulink ソフトウェアによって決められるブロックの並べ替え順序に左右されます。さまざまな要因によってブロックの並べ替え順序が決まり、これによって状態の順序が変更されます。

この例で示す、構造体形式で状態のログを作成する方法では、ブロック名を状態軌跡と一緒に保存することで、状態の順序問題を回避することができます。

配列形式でのログの問題点

既定の設定では、Simulink ソフトウェアは状態軌跡を N (状態の数) 列の行列の配列形式でログに記録します。この行列は M 行で、各行は 1 シミュレーション タイム ステップに対応します。M 行 N 列の行列は、MATLAB® で処理しやすい形式です。ただし、ログが作成される行列の列に沿った状態変数の順序は、ブロックの並べ替え順序に左右されます。したがって、モデル内のブロックの状態と、状態行列の列との間のマッピングが固定されていると想定する MATLAB コードは、モデル内の変更が原因でブロックの並べ替え順序が変わると分解されやすくなります。

たとえば、以下の 2 つのブロック線図を考えてみます。

mdl1 = 'sldemo_state_logging1';
mdl2 = 'sldemo_state_logging2';
open_system(mdl1);
open_system(mdl2);

2 つのブロック線図のブロックは同じで、唯一の違いは出力端子の順序です。モデルのシミュレーションを実行し、状態を配列形式でログを作成します。

simOut1 = sim(mdl1, 'SaveFormat','Array');
simOut2 = sim(mdl2, 'SaveFormat','Array');

シミュレーションの出力ログを含んでいる Simulink.SimulationOutput オブジェクトから、状態ベクトルを抽出します。

x1 = simOut1.get('xout');
x2 = simOut2.get('xout');

Integrator ブロックの相対的順序が 2 つのブロック線図で異なっていることに注意してください。これにより、ログが作成される状態 x1x2 が異なることになります。列と状態の間のマッピングが異なるからです。

isequal(x1, x2)
ans =

     0

構造体形式でのログの使用

再びモデルのシミュレーションを実行しますが、今回は、状態を構造体形式でログに記録します。

simOut1=sim(mdl1,'SaveFormat','Structure');
simOut2=sim(mdl2,'SaveFormat','Structure');

シミュレーション出力オブジェクトから、状態ログを含んでいる構造体を抽出します。

x1s = simOut1.get('xout');
x2s = simOut2.get('xout');

これらの構造体を表示します。これらの構造体には、時間と信号の 2 つのフィールドがあることに注目してください。モデルの 'SaveFormat' パラメーターに 'Structure' を選択したので、'time' フィールドは空になっています。'StructureWithTime' を選んで、時間ベクトルを状態構造体の中に保存することもできます。

disp(x1s);
disp(x2s);
       time: []
    signals: [1x2 struct]

       time: []
    signals: [1x2 struct]

状態軌跡が、これらの状態に対応するブロックの名前 xs.signals(k).blockName と共に、 xs.signals(k).values にログとして記録されます。以下のように、状態を行列 (配列形式の場合と同様) に抽出します。

x1a = [x1s.signals.values];
x2a = [x2s.signals.values];

状態の順序問題 (x1a および x2a が、配列形式の場合に得られる x1 および x2 と同じであるという問題) はまだ未解決であることに注意してください。

isequal(x1a, x2a)
ans =

     0

状態順序が固定された状態行列の取得

状態の順序の問題を解決するために、値と共に保存されたブロック名を使用して、状態を固定順序 (たとえば、ブロック名のアルファベット順) にマッピングします。

[~, idx1] = sort({x1s.signals.blockName});
x1 = [x1s.signals(idx1).values];

[~, idx2] = sort({x2s.signals.blockName});
x2 = [x2s.signals(idx2).values];

isequal(x1, x2)
ans =

     1

x1x2 の信号配列をブロック名のアルファベット順に並べ替え、その順序で値フィールドを行列 x1x2 に抽出することで、ログが作成される行列の列とブロック状態の間のマッピングを固定して、状態を行列に記録する方法が得られます。

モデルを閉じて、この例で使用された変数をクリアします。

close_system(mdl1);
close_system(mdl2);
clear ans idx1 idx2 mdl1 mdl2 simOut1 simOut2 x1 x1a x1s x2 x2a x2s
この情報は役に立ちましたか?