Main Content

このページは前リリースの情報です。該当の英語のページはこのリリースで削除されています。

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 ブロックのバリアントの指定

モデル例 PreprocessorConditionalsUsingVariantSubsystem を開くと、[モデル プロパティ][コールバック] ダイアログ ボックスで定義されている "PostLoadFcn" が実行されます。これによりベース ワークスペースに Variant Subsystem ブロックの変数が入力されます。

open_system('PreprocessorConditionalsUsingVariantSubsystem')

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('PreprocessorConditionalsUsingVariantSubsystem/LeftController');

LeftController サブシステム ブロックのダイアログ ボックスでは、ベース ワークスペース内に存在する LINEARNONLINEAR の 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 にユーザー定義マクロとしてアクセスします。この例では、variants_importedmacros.hVSSMODE を提供します。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 = 'variants_importedmacros.h';

複数のバリアントをもつモデルのシミュレーション

VSSMODE の値を 1 に設定しているため、このモデルはシミュレーション時に非線形コントローラーを使用します。

sim('PreprocessorConditionalsUsingVariantSubsystem')
youtnl = yout;

VSSMODE の値を 0 に変更すると、このモデルはシミュレーション時に線形コントローラーを使用します。

VSSMODE.Value = int32(0);
sim('PreprocessorConditionalsUsingVariantSubsystem')
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 オブジェクト LINEARNONLINEAR への参照およびこれらのバリアントに対応するマクロの定義が含まれます。これらの定義は、外部ヘッダー ファイル variants_importedmacros.h によって提供される、VSSMODE の値に依存します。アクティブなバリアントはマクロ (#define) LINEAR および NONLINEAR でプリプロセッサの条件 (#if) を使用することにより決定されます。

マクロ LINEAR および NONLINEAR は生成される PreprocessorConditionalsUsingVariantSubsystem_types.h ヘッダー ファイルで定義されます。

  #ifndef LINEAR
  #define LINEAR      (VSSMODE == 0)
  #endif
  #ifndef NONLINEAR
  #define NONLINEAR   (VSSMODE == 1)
  #endif

生成コードではバリアントに関連するコードが C プリプロセッサの条件によってガードされます。たとえば PreprocessorConditionalsUsingVariantSubsystem.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('PreprocessorConditionalsUsingVariantSubsystem')
close(findobj(0,'Tag','CloseMe'));
clear LINEAR NONLINEAR VSSMODE
clear tout yout youtl youtnl