Variant SubSystem を使用して C のプリプロセッサ条件を使用するコードを生成する
この例では Simulink® variant subsystem を使用して、Simulink Coder™ によって生成されたコードで variant subsystem のどの子サブシステムがアクティブになるかを制御するための C プリプロセッサの条件を生成する方法を説明します。
Variant Subsystem の概要
Variant Subsystem ブロックには複数の子サブシステムがあり、モデルの実行時にいずれかの子がアクティブになります。アクティブな子サブシステムは "アクティブなバリアント" と呼ばれます。Variant Subsystem ブロックのアクティブなバリアントは、ベース ワークスペース内の変数の値を変更することによってプログラムで切り替えるか、または Variant Subsystem ブロックのダイアログを使用してバリアントの選択を手動でオーバーライドすることによって切り替えることができます。"アクティブなバリアント" はモデルのコンパイル時に Simulink によって Variant Subsystem の Inport ブロックと Outport ブロックにプログラムで結線されます。
バリアントの選択をプログラムで制御するには Variant Subsystem ブロックのダイアログで Simulink.Variant
オブジェクトを各子サブシステムに関連付けます。Simulink.Variant
オブジェクトは MATLAB® ベース ワークスペースで作成されます。これらのオブジェクトには、ブール値として評価され、アクティブなバリアントの子サブシステムを決定するために使用される式である、Condition
という名のプロパティがあります。
既定の設定では、生成されたコードにはアクティブなバリアントだけが含まれます。または、アクティブなバリアントの選択をパラメーター化したり、MATLAB のベース ワークスペースの変数およびオブジェクトの値に依存させたりすることもできます。コードを生成する場合、すべてのバリアントのコードを生成し、コードのコンパイル時までアクティブなバリアントの選択を行わないようにできます。
Subsystem ブロックのバリアントの指定
モデル例 rtwdemo_preprocessor_subsys
を開くと、PostLoadFcn が実行されます。これは、[ファイル]、[モデル プロパティ]、[コールバック] ダイアログで定義されています。これによりベース ワークスペースに Variant Subsystem ブロックの変数が入力されます。
open_system('rtwdemo_preprocessor_subsys')
LeftController バリアント サブシステムには 2 つの子サブシステムがあります。Linear と Nonlinear です。Simulink.Variant オブジェクト LINEAR が true
として評価されると LeftController/Linear 子サブシステムが実行され、Simulink.Variant オブジェクト NONLINEAR が true
として評価されると LeftController/Nonlinear 子サブシステムが実行されます。
LeftController サブシステムを右クリックして Subsystem Parameters
を選択すると表示される LeftController サブシステム ブロックのダイアログで LeftController サブシステムに Simulink.Variant オブジェクトを指定します。
open_system('rtwdemo_preprocessor_subsys/LeftController');
LeftController サブシステム ブロックのダイアログでは、ベース ワークスペース内に存在する LINEAR
と NONLINEAR
の 2 つの Simulink.Variant オブジェクトによって、Linear サブシステムと Nonlinear サブシステムが関連付けられます。これらのオブジェクトには、ブール値として評価され、アクティブなバリアントの子サブシステム (Linear または Nonlinear) を決定する式である、Condition
という名のプロパティがあります。条件は Subsystem ブロックのダイアログにも表示されます。この例では、LINEAR
および NONLINEAR
の条件はそれぞれ、'VSSMODE == 0'、'VSSMODE == 1' です。
この例では、Simulink.Variant オブジェクトはベース ワークスペース内に作成されます。
LINEAR = Simulink.Variant; LINEAR.Condition = 'VSSMODE==0'; NONLINEAR = Simulink.Variant; NONLINEAR.Condition = 'VSSMODE==1';
バリアント制御変数の指定
バリアント オブジェクトを使用することによって、モデル全体で任意の複雑な条件を再利用できます。複数の Variant Subsystem ブロックで同じ Simulink.Variant オブジェクトを使用すると、選択のアクティブ化を 1 つのセットとしてまとめて切り替えることができます。このセットは MATLAB 環境の VSSMODE
の値を変更するとシミュレーションの前に切り替えることができます。また、次の節で説明するように、生成コードのコンパイル時に切り替えることができます。この例では LeftController および RightController は同じバリアント オブジェクトを参照しているため、これらを同時に切り替えられます。
非線形コントローラー サブシステムはヒステリシスを実装しますが、線形コントローラー サブシステムは単純なローパス フィルターとして動作します。左側のチャネルのサブシステムを開きます。右側のチャネルのサブシステムも同様です。
生成されたコードは、バリアント制御変数 VSSMODE
にユーザー定義マクロとしてアクセスします。この例では、rtwdemo_importedmacros.h
が VSSMODE
を提供します。MATLAB 環境では、Simulink.Parameter
オブジェクトを使用して VSSMODE
を指定します。プリプロセッサ条件を含むコードを生成する場合、値は無視されます。ただし、値はシミュレーションに使用されます。レガシ ヘッダー ファイルは、生成コードのコンパイル時に使用するマクロの値を指定します。これは最終的に、組み込み実行ファイルの指定された 2 つのバリアントのどちらかをアクティブ化します。
バリアント制御変数は次のいずれかのストレージ クラスと共に Simulink.Parameter
オブジェクトとして定義できます。
ヘッダー ファイルが指定された
Define
またはImportedDefine
CompilerFlag
SystemConstant (AUTOSAR)
指定されたヘッダー ファイル内でデータをマクロとして定義するユーザー定義のカスタム ストレージ クラス
VSSMODE = Simulink.Parameter; VSSMODE.Value = 1; VSSMODE.DataType = 'int32'; VSSMODE.CoderInfo.StorageClass = 'Custom'; VSSMODE.CoderInfo.CustomStorageClass = 'ImportedDefine'; VSSMODE.CoderInfo.CustomAttributes.HeaderFile = 'rtwdemo_importedmacros.h';
複数のバリアントをもつモデルのシミュレーション
VSSMODE
の値を 1 に設定しているため、このモデルはシミュレーション時に非線形コントローラーを使用します。
sim('rtwdemo_preprocessor_subsys')
youtnl = yout;
VSSMODE
の値を 0 に変更すると、このモデルはシミュレーション時に線形コントローラーを使用します。
VSSMODE.Value = int32(0);
sim('rtwdemo_preprocessor_subsys')
youtl = yout;
次のようにして、線形コントローラーおよび非線形コントローラーの応答をプロットして比較できます。
figure('Tag','CloseMe'); plot(tout, youtnl.signals(1).values, 'r-', tout, youtl.signals(1).values, 'b-') title('Response of Left Channel Linear and Nonlinear Controllers'); ylabel('Response'); xlabel('Time (seconds)'); legend('nonlinear','linear') axis([0 100 -0.8 0.8]);
C プリプロセッサの条件の使用
このモデルの例は C プリプロセッサの条件を生成するように設定されています。モデルのコードを生成するには、ツールストリップの [C コード] タブで、[ビルド] を選択します。
プリプロセッサの条件のコード生成を有効にするには、次の条件が整っていることを確認してください。
[コンフィギュレーション パラメーター] ダイアログ ボックスの [コード生成]、[システム ターゲット ファイル] で Embedded Coder® ターゲットを選択します。
Variant Subsystem の [ブロック パラメーター] ダイアログ ボックスで、[バリアントのアクティベーションのタイミング] パラメーターを [
code compile
] に設定します。
この例で生成されたコードには、Simulink.Variant オブジェクト LINEAR
と NONLINEAR
への参照およびこれらのバリアントに対応するマクロの定義が含まれます。これらの定義は、外部ヘッダー ファイル rtwdemo_importedmacros.h
によって提供される、VSSMODE
の値に依存します。アクティブなバリアントはマクロ (#define) LINEAR
および NONLINEAR
でプリプロセッサの条件 (#if) を使用することにより決定されます。
マクロ LINEAR
および NONLINEAR
は生成される rtwdemo_preprocessor_subsys_types.h
ヘッダー ファイルで定義されます。
#ifndef LINEAR #define LINEAR (VSSMODE == 0) #endif
#ifndef NONLINEAR #define NONLINEAR (VSSMODE == 1) #endif
生成コードではバリアントに関連するコードが C プリプロセッサの条件によってガードされます。たとえば rtwdemo_preprocessor_subsys.c
では各バリアントの関数 step および初期化関数の呼び出しが条件付きでコンパイルされます。
/* Outputs for atomic SubSystem: '<Root>/LeftController' */ #if LINEAR /* Output and update for atomic system: '<S1>/Linear' */ #elif NONLINEAR /* Output and update for atomic system: '<S1>/Nonlinear' */ #endif
モデル、Figure および例のワークスペース変数を閉じます。
bdclose('rtwdemo_preprocessor_subsys') close(findobj(0,'Tag','CloseMe')); clear LINEAR NONLINEAR VSSMODE clear tout yout youtl youtnl