Main Content

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

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

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

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

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

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

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

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

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

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

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

モデル例の確認

モデル例 RollAxisAutopilot を開きます。

open_system('RollAxisAutopilot')

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

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

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

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

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

set_param('RollAxisAutopilot','MatFileLogging','off')

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

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

slbuild('RollAxisAutopilot')
### Starting build procedure for: RollAxisAutopilot
### Successful completion of build procedure for: RollAxisAutopilot

Build Summary

Top model targets built:

Model              Action                        Rebuild Reason                                    
===================================================================================================
RollAxisAutopilot  Code generated and compiled.  Code generation information file does not exist.  

1 of 1 models built (0 models already up to date)
Build duration: 0h 0m 9.9704s

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

file = fullfile('RollAxisAutopilot_grt_rtw','RollAxisAutopilot.h');
coder.example.extractLines(file,...
    '/* External inputs (root inport signals with default storage) */',...
    '} ExtY_RollAxisAutopilot_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_RollAxisAutopilot_T;

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

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

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

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

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

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

file = fullfile('RollAxisAutopilot_grt_rtw','RollAxisAutopilot_types.h');
coder.example.extractLines(file,'/* Forward declaration for rtModel */',...
    'RT_MODEL_RollAxisAutopilot_T;',1,1)
/* Forward declaration for rtModel */
typedef struct tag_RTM_RollAxisAutopilot_T RT_MODEL_RollAxisAutopilot_T;

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

file = fullfile('RollAxisAutopilot_grt_rtw','RollAxisAutopilot.c');
coder.example.extractLines(file,...
    '/* External inputs (root inport signals with default storage) */',...
    '= &RollAxisAutopilot_M_;',1,1)
/* External inputs (root inport signals with default storage) */
ExtU_RollAxisAutopilot_T RollAxisAutopilot_U;

/* External outputs (root outports fed by signals with default storage) */
ExtY_RollAxisAutopilot_T RollAxisAutopilot_Y;

/* Real-time model */
static RT_MODEL_RollAxisAutopilot_T RollAxisAutopilot_M_;
RT_MODEL_RollAxisAutopilot_T *const RollAxisAutopilot_M = &RollAxisAutopilot_M_;

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

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

coder.example.extractLines(file,...
    '/* Model step function */','void RollAxisAutopilot_step(void)',1,1)
/* Model step function */
void RollAxisAutopilot_step(void)

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

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

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

  /* End of Switch: '<Root>/EngSwitch' */
}

/* Model initialize function */
void RollAxisAutopilot_initialize(void)
{
  /* Registration code */

  /* initialize error status */
  rtmSetErrorStatus(RollAxisAutopilot_M, (NULL));

  /* states (dwork) */
  (void) memset((void *)&RollAxisAutopilot_DW, 0,
                sizeof(DW_RollAxisAutopilot_T));

  /* external inputs */
  (void)memset(&RollAxisAutopilot_U, 0, sizeof(ExtU_RollAxisAutopilot_T));

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

  /* SystemInitialize for Atomic SubSystem: '<Root>/RollAngleReference' */
  /* InitializeConditions for UnitDelay: '<S4>/FixPt Unit Delay1' */
  RollAxisAutopilot_DW.FixPtUnitDelay1_DSTATE = 0.0F;

  /* End of SystemInitialize for SubSystem: '<Root>/RollAngleReference' */

  /* SystemInitialize for Atomic SubSystem: '<Root>/BasicRollMode' */
  /* InitializeConditions for DiscreteIntegrator: '<S1>/Integrator' */
  RollAxisAutopilot_DW.Integrator_DSTATE = 0.0F;
  RollAxisAutopilot_DW.Integrator_PrevResetState = 0;

  /* End of SystemInitialize for SubSystem: '<Root>/BasicRollMode' */
}

/* Model terminate function */
void RollAxisAutopilot_terminate(void)
{
  /* (no terminate code required) */
}

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

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

coder.example.extractLines(file,'/* Model initialize function */',...
    'rtmSetErrorStatus(RollAxisAutopilot_M, (NULL));',1,1)
/* Model initialize function */
void RollAxisAutopilot_initialize(void)
{
  /* Registration code */

  /* initialize error status */
  rtmSetErrorStatus(RollAxisAutopilot_M, (NULL));
coder.example.extractLines(file,'  /* external inputs */',...
    '/* SystemInitialize for Atomic SubSystem:',1,0)
  /* external inputs */
  (void)memset(&RollAxisAutopilot_U, 0, sizeof(ExtU_RollAxisAutopilot_T));

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

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

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

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

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

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

slbuild('RollAxisAutopilot')
### Starting build procedure for: RollAxisAutopilot
### Successful completion of build procedure for: RollAxisAutopilot

Build Summary

Top model targets built:

Model              Action                        Rebuild Reason                   
==================================================================================
RollAxisAutopilot  Code generated and compiled.  Generated code was out of date.  

1 of 1 models built (0 models already up to date)
Build duration: 0h 0m 8.1214s

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

file = fullfile('RollAxisAutopilot_grt_rtw','RollAxisAutopilot.h');
coder.example.extractLines(file,'/* Real-time Model Data Structure */',...
    '/* External data declarations for dependent source files */',1,0)
/* Real-time Model Data Structure */
struct tag_RTM_RollAxisAutopilot_T {
  const char_T *errorStatus;
  ExtU_RollAxisAutopilot_T *inputs;
  ExtY_RollAxisAutopilot_T *outputs;
  DW_RollAxisAutopilot_T *dwork;
};

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

file = fullfile('RollAxisAutopilot_grt_rtw','RollAxisAutopilot.c');
coder.example.extractLines(file,'/* Model data allocation function */',...
    'RT_MODEL_RollAxisAutopilot_T *RollAxisAutopilot(void)',1,1)
/* Model data allocation function */
RT_MODEL_RollAxisAutopilot_T *RollAxisAutopilot(void)

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

file = fullfile('RollAxisAutopilot_grt_rtw','RollAxisAutopilot.c');
coder.example.extractLines(file,...
    '/* Model step function */','void RollAxisAutopilot_step',1,1)
/* Model step function */
void RollAxisAutopilot_step(RT_MODEL_RollAxisAutopilot_T *const

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

coder.example.extractLines(file,...
    '*RollAxisAutopilot_DW =','RollAxisAutopilot_M->outputs;',1,1)
  DW_RollAxisAutopilot_T *RollAxisAutopilot_DW = RollAxisAutopilot_M->dwork;
  ExtU_RollAxisAutopilot_T *RollAxisAutopilot_U = (ExtU_RollAxisAutopilot_T *)
    RollAxisAutopilot_M->inputs;
  ExtY_RollAxisAutopilot_T *RollAxisAutopilot_Y = (ExtY_RollAxisAutopilot_T *)
    RollAxisAutopilot_M->outputs;

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

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

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

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

coder.example.extractLines(file,...
    '/* Model initialize function */','void RollAxisAutopilot_initialize',1,1)
/* Model initialize function */
void RollAxisAutopilot_initialize(RT_MODEL_RollAxisAutopilot_T *const

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

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

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

関連するトピック