モデリングでの Simulink および Stateflow の使用
Stateflow® を使用する場合、入力、出力、および構成に Simulink® が必要です。Stateflow 単独では、さまざまな式の処理を実行できます。Simulink を使用する場合は、Switch Case ブロックを使用するなどの方法で、複素数状態の変数を実現できます。
Simulink または Stateflow を使用して、コントロールの特定の部分をモデル化できますが、開発ワークフロー内のいずれかの製品の適用は、基礎となるアルゴリズムに対するユーザーの理解に基づいており、最終的に、ニーズに最適なツールの判断は組織にゆだねられます。設計に Simulink または Stateflow のどちらを使用するべきかの判断は、タスクに従ってユーザーのグループが判断しなければなりません。Stateflow での実装を、状態遷移とフロー チャートのどちらを使用して実行するかについても指定しなければなりません。
多くの場合、Stateflow は RAM に関して効率が低下します。したがって、単純な式を使用する計算では、Simulink にメリットがあります。さらに、状態変数が単純なフリップフロップと Relay ブロックで動作する場合も Simulink の方がメリットがあります。プロジェクトで Simulink または Stateflow を使用するかどうか評価する場合、以下の点を考慮しなければなりません。
RAM の増加: Stateflow 入力、出力、および内部変数の可視化に利用できる RAM を常に用意しておかなければなりません。
計算式のエラーの処理: 一般的な計算式が内部で使用されている場合、ユーザーはオーバーフローを回避する方法を設計します。
機能の分割と分離: Stateflow 外で Simulink を使用する計算を実行する場合は、計算が分割されて、可読性が低下する可能性があります。可読性が向上する場合もあります。これは判断が難しい事項です。
Stateflow に、Simulink よりも効率の高いコードがあり、コードに近い最適な式を得られる場合がありますが、その多くは理解が困難なモデルになることがあります。コードが既に存在する場合は、Stateflow のモデリングではなく S-Function を使用した方が効果的です。Stateflow では、特定の配置が指定されている計算、または for ループを使用する計算は Simulink よりも効率的ですが、近年では、記述に MATLAB® 言語を使用することも便利になりました。必要に応じて、モデリングには MATLAB 言語を使用することを検討してください。
Stateflow モデルの場合は、ステートを以下に説明するように扱う場合、ステートを状態遷移として記述することで可読性が向上します。
同一の入力に対して異なる出力値が出力される。
複数のステートが存在する (3 つ以上が目安)。
ステートには、単なる数値ではなく、意味のある名前を与えられる。
ステート内部では、初期化 (初回) と実行中 (2 回目以降) の区別が必要。
たとえば、フリップフロップ回路では、入力に対して異なる値が出力されます。状態変数は 0 および 1 に制限されます。ただし、boolean 型の数値を保持するだけでは、意味のある名前を各ステートに追加できません。また、ステート内では初期化と実行も区別されません。したがって、上記の 4 項目の中で 1 つのフリップフロップのみ適用されるため、Simulink の方が有利です。
Stateflow では、ステートとして表すことができる状況は、状態遷移として実装され、ステートではない条件付き分岐はフロー チャートとして実装されます。真理値表は、条件分岐実装方法として分類されます。Stateflow を使用してステートを状態遷移として設計する場合は、Classic
をステート マシン タイプとして選択し、制御システムの組み込みのマイクロ コントローラーにソフトウェアとして実装されるようにしなければなりません。
HDL Coder™ は Stateflow でサポートされます。HDL Coder を使用する場合は、Mealy
または Moore
を選択しなければなりません。電気的な内部の漏れを防ぐために保護が必要な場合は、Moore
モードの方が適しています。
メモ
HDL Coder ユース ケースは、これらのガイドラインには記載されていません。
Simulink の機能
ここでは、Simulink を使用したモデリングについて説明します。
状態変数をもつブロック
状態変数をもつブロックは、主に Simulink および離散タイプにグループ化されます。
これらのほとんどのブロックでは、ユーザーはブロック パラメーターを使用して状態属性と初期値を設定できます。条件付きサブシステムには、構造パターンに応じて、状態変数を含めることができます。
この例では、Unit Delay ブロックに状態属性が含まれています。
この例では、Tapped Delay ブロックに状態属性が含まれていません。
ガイドライン jc_0640 を参照
状態変数を使用した分岐構文
Switch ブロックおよび条件付きサブシステムは、状態変数が使用される場合、動作が異なります。
コンフィギュレーション設定に応じて、状態変数が存在する場合、一般的に、Switch ブロックは、制御端子の条件が満たされると、サブシステム A を実行します。条件が満たされない場合は、サブシステム A を計算せずにサブシステム B のみを実行します。ただし、サブシステム A に状態変数が含まれる場合、サブシステム A 内の状態変数の計算は、制御端子の条件が満たされていない場合でも処理されます。
条件付きサブシステムの場合、条件が満たされると、サブシステム A が計算されます。条件が満たされない場合、サブシステム A の状態変数の有無に関係なく、サブシステム A ではなくサブシステム B が計算されます。
再計算のリセット アクションは、{Action Port} 設定を使用して指定できます。
Switch ブロックと条件付き制御フローを使用している場合のサブシステム A の動作を、以下の表に示します。これらの動作を十分に理解して、目的のために Switch ブロックまたは条件付きサブシステムが最も適している構造を判断します。
以下の表にサブシステム A の動作を示します。
制御端子条件 | (サブシステム A 内) 状態変数 | Switch | 条件付きサブシステム |
保持 | なし | 実行される | 実行される |
あり | |||
保持しない | なし | 実行されない | 実行されない |
あり | 最小限の処理 *状態変数に関連する計算のみ実行 |
以下の表に、サブシステム A の初期化のタイミングを示します。
Action Port | 初期化 | |
Switch | - | 初回のみ |
条件付きサブシステム | 保持 | 初回のみ |
リセット | 条件復帰時 |
以下のガイドランを参照してください。
サブシステム
サブシステムは、さまざまなブロックとサブシステムのコンパイルに使用されます。
サブシステムは、他の目的でも使用できます。機能サブシステムではない使用方法は次のとおりです。
サブシステムのマスク表示を使用して、概要を記述したり、"機密事項" などの定型のドキュメントを表示します。
サブシステムのオープン ファンクション (ブロック プロパティのコールバック関数) は、複数のツールを実行したり、モデルとは異なる説明テキストを表示するために使用されます。
管理権限を持つユーザーが変更を行い、設定をマスク サブシステム (単純に
NoReadOrWrite
に設定されたサブシステム) に変更したが、他のユーザーは内容を参照できないサブシステム。
これらの非標準サブマスクはガイドラインの範囲外です。除外した場合は、プロジェクト内で管理されている除外リストに含めなければなりません。
以下のガイドランを参照してください。
Atomic サブシステムとバーチャル サブシステム. サブシステムは 2 種類あります。バーチャル サブシステムと Atomic サブシステムです。これらのサブシステムの大きな違いは、サブシステムが単一の実行単位として扱われているかどうかです。バーチャル サブシステムは、既定のサブシステム ブロックです。
モデルでは、バーチャル サブシステムの境界線は、太い Atomic サブシステムの境界線に比べて細くなっています。
バーチャル サブシステム
視覚的表現を提供するブロックは、"バーチャル ブロック" と呼ばれます。たとえば、複数の信号線をコンパイルする Mux ブロック、信号を渡す From ブロック、およびバーチャル ブロックに対応する Goto ブロックがあります。既定の設定のサブシステム ブロックのみが、視覚的な階層構造を構成するため、これらのブロックはバーチャル ブロックと呼ばれます。サブシステムはバーチャル サブシステムと呼ばれます。
次の例に示す、サブシステム内の外部の計算結果を参照するサブシステムを考えます。このシステムは、以下の 4 つの方程式から計算されます。
temp1= in1 + in2
temp2= in3 + in4
out1= in1 + in2 + temp2
out2= temp1 + in3 + in4
Atomic サブシステム
Atomic サブシステムは、外部システムから分離され、境界をまたいだ最適化の対象になりません。Atomic サブシステムは、各サブシステムの内部計算の結果を使用しません。したがって、中間出力値は、1 セッション分だけ遅れた計算結果を使用します。
temp1= in1 + in2
temp2= in4 + in5
out1= in1+ in2 + in3
out2= in4+ in5 + in6
in3= temp2
in6= temp1
Atomic サブシステムは、他のサブシステムへの中間計算結果を直接参照することを禁止します。
Atomic サブシステムでは、次の点に注意します。
Atomic サブシステムは、C ソースの関数設定を選択できます。
上記で説明したように、Atomic サブシステムの内部セクションはカプセル化 (オブジェクト化) されます。
前後の関係によっては、静的 RAM セクションを、出力信号のサブシステム内に確保すべきです。
Atomic サブシステム (関数設定の追加を含む) は注意して使用しなければなりません。因子設定は、単純に因子名が C コード内に挿入されることではありません。数学的に独立したシステムとして記述されることを認識し、Atomic サブシステムを使用できる条件を確認すべきです。
構造レイヤーとの関係を含めます。プロジェクトごとに運用ルールを決定し、そのガイドライン ルールとの関係を決定することが必要です。
信号名
信号には名前を付けることができます。これを信号名と呼びます。信号に名前が付けられると、信号名はラベルとして表示されます。ラベルの更新は信号名に反映されるだけでなく、表示されます。
信号名は、分岐した信号線または端子ブロックを介して信号線に伝播されて、信号名として表示されます。
以下のガイドランを参照してください。
信号名を信号オブジェクト (Simulink オブジェクトまたは mpt
オブジェクト) と関連付けてコードを生成できます。型の設定はデータ ディクショナリを通じて構成され、ストレージ クラスの設定はオプションです。ブロックの推奨されるデータ型設定は次のとおりです。
ガイドラインjc_0644: 型の設定方法を参照してください。
ベクトル信号/パス信号
ベクトルを構成する個々のスカラー信号には、共通する機能、データ型、および単位があります。
ベクトルとしての条件を満たさない信号は、バス信号としてのみグループ化できます。Bus Selector ブロックは、バス信号入力でのみ使用します。このブロックは、ベクトル信号からスカラー信号を抽出するために使用できません。
以下の表に、ベクトル信号の例を示します。
ベクトルのタイプ | サイズ |
---|---|
行ベクトル | [1 n] |
列ベクトル | [n 1] |
車輪速度サブシステム | [1 ホイール数] |
シリンダー ベクトル | [1 シリンダー数] |
2 次元座標ポイントに基づく位置ベクトル | [1 2] |
3 次元座標ポイントに基づく位置ベクトル | [1 3] |
以下の表に、バス信号の例を示します。
バスのタイプ | 要素 |
---|---|
センサー バス | 力ベクトル |
場所 | |
車輪速度ベクトル [Θlf, Θrf, Θlr, Θrr] | |
加速 | |
圧力 | |
コントローラー バス | センサー バス |
アクチュエータ バス | |
シリアル データ バス | 循環水の温度 |
エンジ速度、助手席ドア開き |
以下のガイドランを参照してください。
列挙型
列挙型のデータは、決定された数値に制限されるデータを表します。
Simulink の列挙型で使用できるブロックのタイプは制限されます。
列挙型を使用するには、MATLAB で .m
ファイルを使用して列挙型を定義しなければなりません。列挙データ型の定義の詳細については、Simulink モデルでの列挙型データの使用を参照してください。
Stateflow の機能
ここでは、Stateflow を使用したモデリングについて説明します。
Stateflow で使用可能な演算
Stateflow の演算の詳細については、Stateflow データの演算 (Stateflow)を参照してください。
以下のガイドランを参照してください。
状態遷移とフロー チャートの違い
Stateflow は、状態遷移とフロー チャート両方を表すことができます。
Stateflow では、状態遷移図内にフロー チャートを設計できます。
entry アクションは、以下の図に示すように、デフォルト遷移から始まり、遷移線を介してジャンクションに移動する、ステート内のフロー チャートとして表されます。内部遷移線から開始すると、during アクションをフロー チャートで表すことができます。
フロー チャートは、更新間でそのアクティブ ステートを維持できません。その結果、フロー チャートは常に終端ジャンクション (有効な出力遷移のないコネクティブ ジャンクション) で終端します。
一方、状態遷移図ではその現在のステートをメモリ内に保続し、更新間でローカル データとアクティブ ステートを保持します。その結果、状態遷移図は、前のタイム ステップを中断した場所から実行を開始できます。つまり、状態遷移は、履歴に依存するリアクティブ システムや監視システムのモデル化に適しています。
次の表で、フロー チャートと状態遷移図の始点と終点を定義しています。
始点 | 終点 | |
フロー チャート | デフォルト遷移 | ステートからのすべての終端がコネクティブ ジャンクションに接続される。 |
状態線図 | デフォルト遷移 | いずれかの終端を状態に接続しなければならない。 |
以下の図は、一般的なフロー チャートと状態遷移図の違いを示しています。
フロー チャートおよび状態遷移図と自己遷移との混合により、制約がより厳格になっています。
以下のガイドランを参照してください。
バックトラック
以下の例では、フロー チャートでのバックトラッキング動作を強制するコネクティブ ジャンクションを経由した遷移の動作を説明します。チャートでは、出力遷移の暗黙的な順序付けが使用されます。
最初は、ステート A がアクティブで、遷移条件 c1、c2、および c3 が true です。遷移条件 c4 は false です。
チャートのルートは、ステート A から有効な遷移が存在しないかどうかをチェックします。
ステート A からコネクティブ ジャンクションに遷移条件 c1 とマークされた有効な遷移セグメントが存在します。
遷移条件 c1 は true であるため、アクション a1 が実行されます。
遷移条件 c3 が true であるため、アクション a3 が実行されます。
遷移条件 c4 は true でないため、制御フローはステート A にバックトラックします。
チャートのルートは、ステート A から他に有効な遷移が存在しないかどうかをチェックします。
ステート A からコネクティブ ジャンクションに遷移条件 c2 とマークされた有効な遷移セグメントが存在します。
遷移条件 c2 が true であるため、アクション a2 が実行されます。
遷移条件 c3 が true であるため、アクション a3 が実行されます。
遷移条件 c4 は true でないため、制御フローはステート A にバックトラックします。
チャートはスリープします。
この問題を解決するには、無条件遷移線を終端ジャンクションに追加することを検討します。終端ジャンクションでは、c3 または c4 が true でない場合に、フローを終了できます。これにより、ステート A は不要なアクションを伴わずにアクティブなままです。
以下のガイドランを参照してください。
ステート外フロー チャート
ステートに関連付けられているフロー チャートはステート内またはステート外に記述できますが、実行順序とバックトラッキングに注意します。
ステート外でフロー チャートを実行した後の a から b への遷移を評価する次のフロー チャートは、新しい計算の期間と同じ期間内に遷移を実行しているようです。ただし、b への遷移線は、ステート外の遷移を計算することで終了点に到達するかどうか評価されません。これは、常に a に留まるステート遷移図です。
以下の図に示すように、正しく実行されると、遷移条件は外部フロー チャートの終端に配置されず、a から b の遷移線は、フロー チャートの実行後に評価できます。これにより、外部フロー チャートは遷移前に実行し、遷移の時点における最新の値を使用して評価できます。このチャートには、遷移条件が保持されないデッド パスが含まれているため、将来仕様が変更されるとエラーになる可能性があります。このチャート構造は注意して使用してください。
一方、以下のフロー チャートはステート内にあり、ステート a を実行すると内部フロー チャートが常に計算され、デッド パスのない、理解しやすい構造で記述することができます。ただし、パフォーマンスの特性として、ステート a が実行される場合、内部フロー チャートが計算された後のサイクルで a から b への遷移が評価されます。この特性により、外部フロー チャートの計算と遷移の実行タイミングがずれる可能性があります。注意して使用してください。
以下のガイドランを参照してください。
ポインター変数
これは、モデル sf_custom
のコード サンプルです。モデルを開くには、MATLAB コマンド ラインで次のように入力します。
openExample('sf_custom')
sf_custom
で、[Open my_header.h] をクリックします。 #include "tmwtypes.h" extern real_T my_function(real_T x); /* Definition of custom type */ typedef struct { real_T a; int8_T b[10]; }MyStruct; /* External declaration of a global struct variable */ extern MyStruct gMyStructVar; extern MyStruct *gMyStructPointerVar;
sf_custom
で、[Open my_function.c] をクリックします。#include "my_header.h" #include <stdio.h> /* Definition of global struct var */ MyStruct gMyStructVar; MyStruct *gMyStructPointerVar=NULL; real_T my_function(real_T x) { real_T y; y=2*x; return(y); }
gMyStructVar
は Stateflow で定義されていません。通常、my_function
の関数は、C ソースから呼び出されて Stateflow で使用します。ただし、C ソースで公開されているグローバル変数の直接参照は、Stateflow からも利用できます。
初期化
ここでは、初期化値の使用について説明します。
初期化における初期値設定
信号を初期化する必要がある場合、初期値を正しく設定します。
初期値をブロック内に設定する場合は、注釈を含む初期値リストを使用して、初期値入力を視覚的に確認できるようにします。
初期値が必要になるのは、次のような場合です。
状態変数が定義され、かつ状態変数をもつブロックが使用されている場合。
内部ブロック設定を使用する。
外部入力値を使用する。
状態変数が定義され、かつ特定の構成が実行されるときに、ブロックに対して初期値が有効な場合。
Merge ブロックで初期値を設定する。
データ ディクショナリに登録されている信号を使用する。
外部から参照できる信号設定 (RAM を含む) が定義されている場合。
データ ディクショナリに登録されている信号を使用する。
データ ディクショナリに登録されている信号の初期値
データ ディクショナリに登録されている信号の初期値を設定します。
Unit Delay や Data Store Memory などの離散ブロック グループには状態変数が含まれます。
自動コード生成の場合、データ ディクショナリの信号と一致させることで (Simulink 信号オブジェクトに関連付けて) 信号名、タイプ、および初期値を状態変数に設定できます。状態変数のデータ ディクショナリで定義されている信号を使用する場合は、各初期値が同じ値と一致しなければなりません。
状態変数にデータ ディクショナリで定義されている信号を使用する場合
Unit Delay や Data Store Memory などの離散ブロックの場合、ブロック出力線ではなく、ブロック内の状態変数のデータ ディクショナリで定義されている信号を使用するときに設定が実行されます。データ ディクショナリの信号名が信号遷移に関連付けられている場合でも、RAM は二重に確保され、RAM が無駄になります。
例 — 正
信号は、ブロック内の状態変数に定義されています。信号名が定義され、ブロック パラメーター [状態名を Simulink の信号オブジェクトに関連付ける] が選択されています。
例 — 誤
信号は、状態変数をもつブロックの出力信号に定義されています。信号名が定義され、ブロック パラメーター [状態名を Simulink の信号オブジェクトに関連付ける] が選択されていません。
ワークスペースで定義されている信号オブジェクトは、disableimplicitsignalresolution(modelname)
を使用して、信号オブジェクトおよび同じ名前の信号名に関連付けることができます。ただし、ブロック内の状態変数の場合は、ブロック内の状態変数および同じ名前の信号名に関連付けられます。グローバルに設定された信号が同時に 2 つの変数に関連付けられている場合は、ブロック内の状態変数と信号線上の信号ラベルが異なる名前になるように設定を実行することをお勧めします。このように設定しないと、モデルをシミュレーションできません。
外部入力値を初期値とするブロック
初期化中に初期値を設定するときに、関数 init
が呼び出されて、信号がブロック内の値、またはデータ ディクショナリで定義されている初期値に設定されます。次に、ステップ関数 (データ フロー実行関数) が実行されます。ここで、外部入力値は初期値として設定されます。モデル化する場合は、初期値の実行関数と実行タイミングに注意してください。これを次の図に示します。
初期化パラメーターを有効にするシステム構成の初期値設定
設定に応じて、条件付きサブシステムと Merge ブロックの組み合わせに対して初期化パラメーターが有効となるシステム構成があります。これらの組み合わせに初期値が必要な場合は、次のいずれかのモデリング方法を実行します。
例外は、初期値を持つブロックが連続しており、信号の初期値を明確に示すために各ブロックの設定が不要である場合です。
例 — 正
Merge ブロックに初期値が設定されています。
例 — 正
mpt
オブジェクトに初期値が設定されています。
例 — 誤
初期値設定の要件に関係なく、どこにも示されていません。