Main Content

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

生成されたコードによる環境とのデータ交換方法

モデルから生成するコードを使用するには、stepinitialize などの生成されたエントリポイント関数を呼び出します。これらの関数を呼び出す環境は、入力信号データと、アプリケーションに応じてスケジューリング情報を提供しなければなりません。次に、生成されたアルゴリズムは呼び出し環境が使用できる出力データを計算します。環境およびアルゴリズムは、このデータをグローバル変数または仮パラメーター (引数) を介して交換できます。

入出力データのセットおよび交換メカニズムは、エントリポイント関数のインターフェイスを構成します。既定のインターフェイスについて、そしてその制御方法を理解すると、次を行うことができます。

  • 生成されたコードを呼び出すコードを記載する。

  • 1 つのアプリケーションで複数回呼び出すことができる再利用可能な (再呼び出し可能な) コードを生成する。

  • 生成されたコードとアプリケーションのその他の外部コードを統合する。

モデルでは、ルートレベルの Inport ブロックと Outport ブロックは、ブロック アルゴリズムの基本入力と出力を表します。既定では、コード ジェネレーターは、これらのブロックを入出力データを保存する標準の構造体に集約します。

生成されたコードがモデル インターフェイスを使用しない内部データを保存する方法の詳細については、生成されたコードによる内部信号、状態、パラメーター データの保存方法を参照してください。

生成されたコードのデータ インターフェイス

この例では、生成されたコードが環境とデータを交換する方法を示します。

モデル例の確認

モデル例 rtwdemo_roll を開きます。

open_system('rtwdemo_roll')

ルート レベルでは、モデルにはいくつかの Inport ブロックと 1 つの Outport ブロックがあります。

モデルで、[コンフィギュレーション パラメーター]、[コード生成]、[システム ターゲット ファイル]grt.tlc に設定します。

set_param('rtwdemo_roll','SystemTargetFile','grt.tlc')

[コンフィギュレーション パラメーター]、[コード生成]、[インターフェイス]、[コード インターフェイスのパッケージ化] の設定を検査します。設定 Nonreusable function は、生成されたコードが再利用可能ではない (再呼び出し可能ではない) ことを意味します。

この例の場合、より簡単なコードを生成するために、[コンフィギュレーション パラメーター]、[コード生成]、[インターフェイス]、[詳細設定パラメーター]、[MAT ファイルのログ] をクリアします。

set_param('rtwdemo_roll','MatFileLogging','off')

再利用できないコードの生成

モデルからコードを生成します。

rtwbuild('rtwdemo_roll')
### Starting build procedure for: rtwdemo_roll
### Successful completion of build procedure for: rtwdemo_roll

ファイル rtwdemo_roll.h を検証します。ファイルは、入力データおよび出力データを表す型を表す構造体の型を定義します。

file = fullfile('rtwdemo_roll_grt_rtw','rtwdemo_roll.h');
rtwdemodbtype(file,...
    '/* External inputs (root inport signals with default storage) */',...
    '} ExtY_rtwdemo_roll_T;',1,1)
/* External inputs (root inport signals with default storage) */
typedef struct {
  real32_T Phi;                        /* '<Root>/Phi' */
  real32_T Psi;                        /* '<Root>/Psi' */
  real32_T Rate_FB;                    /* '<Root>/Rate_FB' */
  real32_T TAS;                        /* '<Root>/TAS' */
  boolean_T AP_Eng;                    /* '<Root>/AP_Eng' */
  boolean_T HDG_Mode;                  /* '<Root>/HDG_Mode' */
  real32_T HDG_Ref;                    /* '<Root>/HDG_Ref' */
  real32_T Turn_Knob;                  /* '<Root>/Turn_Knob' */
} ExtU_rtwdemo_roll_T;

/* External outputs (root outports fed by signals with default storage) */
typedef struct {
  real32_T Ail_Cmd;                    /* '<Root>/Ail_Cmd' */
} ExtY_rtwdemo_roll_T;

各フィールドは、モデルのルート レベルにある Inport ブロックまたは Outport ブロックに対応します。各フィールドの名前は、ブロックの名前から派生します。

ファイルは、生成されたコードで実行中にエラーが発生したかどうかの実行時指標を 1 つのフィールドに保存する 1 つの構造体型、つまり "リアルタイム モデル データ構造体" も定義します。

rtwdemodbtype(file,'/* Real-time Model Data Structure */',...
    '/* Block states (default storage) */',1,0)
/* Real-time Model Data Structure */
struct tag_RTM_rtwdemo_roll_T {
  const char_T *errorStatus;
};

アプリケーションに合わせてモデル コンフィギュレーション パラメーターを変更する場合、この構造体には、スケジューリング情報などのモデル全体に関するその他のデータも含めることができます。

リアルタイム モデル データ構造体を表す構造体型の場合、ファイル rtwdemo_roll_types.h は、生成されたコードで構造体にメモリを割り当てるために後で使用されるエイリアス (typedef) を作成します。

file = fullfile('rtwdemo_roll_grt_rtw','rtwdemo_roll_types.h');
rtwdemodbtype(file,'/* Forward declaration for rtModel */',...
    'RT_MODEL_rtwdemo_roll_T;',1,1)
/* Forward declaration for rtModel */
typedef struct tag_RTM_rtwdemo_roll_T RT_MODEL_rtwdemo_roll_T;

これらの構造体型を使用して、ファイル rtwdemo_roll.c は生成されたアルゴリズムの入出力データを保存するグローバル構造体変数を定義します (メモリを割り当てます)。またファイルは、リアルタイム モデル データ構造体を表す変数とその構造体を指すポインターも定義します。

file = fullfile('rtwdemo_roll_grt_rtw','rtwdemo_roll.c');
rtwdemodbtype(file,...
    '/* External inputs (root inport signals with default storage) */',...
    '= &rtwdemo_roll_M_;',1,1)
/* External inputs (root inport signals with default storage) */
ExtU_rtwdemo_roll_T rtwdemo_roll_U;

/* External outputs (root outports fed by signals with default storage) */
ExtY_rtwdemo_roll_T rtwdemo_roll_Y;

/* Real-time model */
RT_MODEL_rtwdemo_roll_T rtwdemo_roll_M_;
RT_MODEL_rtwdemo_roll_T *const rtwdemo_roll_M = &rtwdemo_roll_M_;

ファイル rtwdemo_roll.h は、これらの構造体変数を宣言します。外部コードには、一般名が model.h であるこのファイルをインクルード (#include) できます。ここで、model は、モデル インターフェイスを使用するデータにアクセスするためのモデルの名前です。

rtwdemo_roll.c では、プライマリ モデル アルゴリズムを表すモデルの関数 stepvoid void インターフェイス (引数なし) を使用します。

rtwdemodbtype(file,...
    '/* Model step function */','void rtwdemo_roll_step(void)',1,1)
/* Model step function */
void rtwdemo_roll_step(void)

関数定義では、アルゴリズムは入力データを読み取り、グローバル構造体変数に直接アクセスして出力データを書き出します。たとえば、アルゴリズムの終端付近で EngSwitch ブロックのコードは (入力を表す) AP_Eng フィールドの値を読み取り、その値に基づいて、定数値を (出力を表す) Ail_Cmd フィールドに条件付きで書き出します。

rtwdemodbtype(file,'if (rtwdemo_roll_U.AP_Eng) {','      }',1,1)
  if (rtwdemo_roll_U.AP_Eng) {
    /* Outputs for Atomic SubSystem: '<Root>/BasicRollMode' */
    /* Saturate: '<S1>/CmdLimit' */
    if (rtwdemo_roll_Y.Ail_Cmd > 15.0F) {
      /* Sum: '<S1>/Sum2' incorporates:
       *  Outport: '<Root>/Ail_Cmd'
       */
      rtwdemo_roll_Y.Ail_Cmd = 15.0F;
    } else {
      if (rtwdemo_roll_Y.Ail_Cmd < -15.0F) {
        /* Sum: '<S1>/Sum2' incorporates:
         *  Outport: '<Root>/Ail_Cmd'
         */
        rtwdemo_roll_Y.Ail_Cmd = -15.0F;
      }

void void インターフェイスおよび直接データ アクセスのため、関数は再呼び出し可能ではありません。アプリケーションで関数を複数回呼び出すと、呼び出しごとに同じグローバル構造体変数に対して入出力データの読み取りと書き込みが行われるため、データが破損し、呼び出し間での意図しない相互作用が発生します。

モデル初期化関数 rtwdemo_roll_initialize は、入出力データをゼロに初期化します。また関数はエラー ステータスを初期化します。関数はグローバル変数に直接アクセスしますが、これは関数が再呼び出し可能ではないことを意味します。

rtwdemodbtype(file,'/* Model initialize function */',...
    'rtmSetErrorStatus(rtwdemo_roll_M, (NULL));',1,1)
/* Model initialize function */
void rtwdemo_roll_initialize(void)
{
  /* Registration code */

  /* initialize error status */
  rtmSetErrorStatus(rtwdemo_roll_M, (NULL));
rtwdemodbtype(file,'  /* external inputs */',...
    '/* SystemInitialize for Atomic SubSystem:',1,0)
  /* external inputs */
  (void)memset(&rtwdemo_roll_U, 0, sizeof(ExtU_rtwdemo_roll_T));

  /* external outputs */
  rtwdemo_roll_Y.Ail_Cmd = 0.0F;

再利用可能なコードの生成

生成されたコードを再呼び出し可能に設定できます。これは、エントリポイント関数をアプリケーションで複数回呼び出しできることを意味します。グローバル変数に直接アクセスするのではなく、この設定を使用して、エントリポイント関数は仮パラメーター (ポインター引数) を介して入力、出力およびその他のモデル データを交換します。これらのポインター引数を使用して、各呼び出しは入力を読み取り、出力を別個のグローバル変数のセットに書き出すことができるため、呼び出し間での意図しない相互作用を防ぎます。

モデルで、[コンフィギュレーション パラメーター]、[コード生成]、[インターフェイス]、[コード インターフェイスのパッケージ化]Reusable function に設定します。

set_param('rtwdemo_roll','CodeInterfacePackaging','Reusable function')

モデルからコードを生成します。

rtwbuild('rtwdemo_roll')
### Starting build procedure for: rtwdemo_roll
### Successful completion of build procedure for: rtwdemo_roll

ここで、rtwdemo_roll.h では、リアルタイム モデル データ構造体にはエラー指標へのポインター、入力データ、出力データおよび DWork サブ構造体の形式の追加データ (たとえば、Discrete-Time Integrator ブロックの状態などのブロック状態を保存します) が含まれます。

file = fullfile('rtwdemo_roll_grt_rtw','rtwdemo_roll.h');
rtwdemodbtype(file,'/* Real-time Model Data Structure */',...
    '/* External data declarations for dependent source files */',1,0)
/* Real-time Model Data Structure */
struct tag_RTM_rtwdemo_roll_T {
  const char_T *errorStatus;
  ExtU_rtwdemo_roll_T *inputs;
  ExtY_rtwdemo_roll_T *outputs;
  DW_rtwdemo_roll_T *dwork;
};

生成されたコードをアプリケーションで複数回呼び出すには、コードで、リアルタイム モデル データ構造体に呼び出し単位でメモリを割り当てなければなりません。ファイル rtwdemo_roll.c は、新しいリアルタイム モデル データ構造体にメモリを割り当て、ポインターを構造体に返す特殊な関数を定義します。また関数は、入力および出力構造体などのモデル データ構造体のフィールドが指し示すサブ構造体にメモリを割り当てます。

file = fullfile('rtwdemo_roll_grt_rtw','rtwdemo_roll.c');
rtwdemodbtype(file,'/* Model data allocation function */',...
    'RT_MODEL_rtwdemo_roll_T *rtwdemo_roll(void)',1,1)
/* Model data allocation function */
RT_MODEL_rtwdemo_roll_T *rtwdemo_roll(void)

rtwdemo_roll.c では、モデルの関数 step は、リアルタイム モデル データ構造体を表す引数を受け入れます。

file = fullfile('rtwdemo_roll_grt_rtw','rtwdemo_roll.c');
rtwdemodbtype(file,...
    '/* Model step function */','void rtwdemo_roll_step',1,1)
/* Model step function */
void rtwdemo_roll_step(RT_MODEL_rtwdemo_roll_T *const rtwdemo_roll_M)

関数定義では、アルゴリズムは最初にリアルタイム モデル データ構造体から各ポインターを抽出し、ローカル変数に渡します。

rtwdemodbtype(file,...
    '*rtwdemo_roll_DW =','rtwdemo_roll_M->outputs;',1,1)
  DW_rtwdemo_roll_T *rtwdemo_roll_DW = ((DW_rtwdemo_roll_T *)
    rtwdemo_roll_M->dwork);
  ExtU_rtwdemo_roll_T *rtwdemo_roll_U = (ExtU_rtwdemo_roll_T *)
    rtwdemo_roll_M->inputs;
  ExtY_rtwdemo_roll_T *rtwdemo_roll_Y = (ExtY_rtwdemo_roll_T *)
    rtwdemo_roll_M->outputs;

次に、グローバル メモリに保存されている入出力データにアクセスするために、アルゴリズムはこれらのローカル変数を操作します。

rtwdemodbtype(file,'  if (rtwdemo_roll_U->AP_Eng) {',...
    '  /* End of Switch: ''<Root>/EngSwitch'' */',1,1)
  if (rtwdemo_roll_U->AP_Eng) {
    /* Outputs for Atomic SubSystem: '<Root>/BasicRollMode' */
    /* Saturate: '<S1>/CmdLimit' */
    if (rtwdemo_roll_Y->Ail_Cmd > 15.0F) {
      /* Sum: '<S1>/Sum2' incorporates:
       *  Outport: '<Root>/Ail_Cmd'
       */
      rtwdemo_roll_Y->Ail_Cmd = 15.0F;
    } else {
      if (rtwdemo_roll_Y->Ail_Cmd < -15.0F) {
        /* Sum: '<S1>/Sum2' incorporates:
         *  Outport: '<Root>/Ail_Cmd'
         */
        rtwdemo_roll_Y->Ail_Cmd = -15.0F;
      }
    }

    /* End of Saturate: '<S1>/CmdLimit' */
    /* End of Outputs for SubSystem: '<Root>/BasicRollMode' */
  } else {
    /* Sum: '<S1>/Sum2' incorporates:
     *  Constant: '<Root>/Zero'
     *  Outport: '<Root>/Ail_Cmd'
     */
    rtwdemo_roll_Y->Ail_Cmd = 0.0F;
  }

同様に、モデル初期化関数はリアルタイム モデル データ構造体を引数として受け入れます。

rtwdemodbtype(file,...
    '/* Model initialize function */','void rtwdemo_roll_initialize',1,1)
/* Model initialize function */
void rtwdemo_roll_initialize(RT_MODEL_rtwdemo_roll_T *const rtwdemo_roll_M)

エントリポイント関数に対して行う各呼び出しは、別個のリアルタイム モデル データ構造体を操作するため、呼び出し間での意図しない相互作用が行われません。

データ インターフェイスの構成

生成されたコードのデータ インターフェイスの特性を制御するには、生成コードでのデータと関数インターフェイスの制御を参照してください。

関連するトピック