生成コード内の変数の保持
モデルの反復的な開発においては、モデル実行で生成される信号や状態の値を取得します。実行時にはパラメーターの値の調整も行い、信号および状態の結果を確認します。そうすることで、設計を決定する際の判断をこのような出力の解析に基づいたものにできます。ラピッド プロトタイピング環境では、信号、状態、パラメーターのデータにアクセスするために、データをアドレス可能なメモリに格納するように生成コードを設定できます。
使用するシステム ターゲット ファイルに応じて (grt.tlc
など)、既定では、最適化設定により、次を行うことで生成されたコードを効率化できます。
信号および一部の状態向けの不要なグローバル ストレージとローカル ストレージを削除します。
ただし、最適化によってシステムの基本入力と出力を表すルートレベルの Inport ブロックと Outport ブロックのストレージは削除されません。このデータにアクセスするために、最適化を検討する必要はありません。
ブロック パラメーターの数値をインライン化します。コードではパラメーターはメモリに格納されないため、コードの実行中にパラメーターと対話できません。
その代わりに、このデータ用にアドレス可能なメモリを割り当てるコードを生成するには、最適化を無効にするか、個々のデータ項目に対してコード生成設定を指定して最適化をオーバーライドします。
信号、状態、パラメーター データへの実行時のアクセス
モデルの反復的な開発においては、モデル実行で生成される出力信号や状態のデータを取得します。実行時にはパラメーターの値の調整も行い、出力での結果を確認します。そうすることで、設計を決定する際の判断をこのような出力の解析に基づいたものにできます。ラピッド プロトタイピング環境では、この信号、状態、パラメーターのデータにアクセスするために、データをアドレス可能なメモリに格納するように生成コードを設定できます。
既定では、生成コードの効率を高めるために、最適化設定によって、不要な信号ストレージを削除したり、ブロック パラメーターの数値をインライン化したりするように設定されています。その代わりに、このデータ用にアドレス可能なメモリを割り当てるコードを生成するには、最適化を無効にするか、個々のデータ項目に対してコード生成設定を指定します。
モデル例の確認
この例のためにモデル ConfigurationRapidPrototypingInterface を準備するスクリプトを実行します。
prepare_configurationRapidPrototypingInterface
以下のデータはコード生成のために構成されます。
パラメーター
UPPER
、LOWER
、K1
、Table1
、およびTable2
信号
In1
、In2
、In3
、In4
、およびOut1
状態
X
(遅延) およびmode
(データストア メモリ書き込み)
モデル例 ConfigurationRapidPrototypingInterface
を開きます。
ConfigurationRapidPrototypingInterface
このモデルでは MATLAB® の数値変数をモデル ワークスペースに読み込みます。ワークスペース変数は、モデルにいくつかのブロック パラメーターを設定します。しかし、モデル内の Gain ブロックは、リテラル値 2 を使用します。
最適化の無効化
1. モデルで、モデル コンフィギュレーション パラメーターの [信号ストレージの再利用] をクリアします。この最適化のほか、[余分なローカル変数の削除 (式の畳み込み)] などの最適化をクリアすると、生成コードで信号線にメモリが割り当てられます。[信号ストレージの再利用] をクリアすると、他のほとんどの最適化が無効になります。
set_param('ConfigurationRapidPrototypingInterface','OptimizeBlockIOStorage','off')
2. モデル コンフィギュレーション パラメーター [既定のパラメーター動作] を [Tunable
] に設定します。このコンフィギュレーション パラメーターを [Tunable
] に設定すると、生成コードでブロック パラメーターおよびワークスペース変数にメモリが割り当てられます。
set_param('ConfigurationRapidPrototypingInterface','DefaultParameterBehavior','Tunable')
3. コードを生成します。
slbuild('ConfigurationRapidPrototypingInterface')
### Starting build procedure for: ConfigurationRapidPrototypingInterface ### Successful completion of build procedure for: ConfigurationRapidPrototypingInterface Build Summary Top model targets built: Model Action Rebuild Reason ======================================================================================================================== ConfigurationRapidPrototypingInterface 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 45.968s
4. コード生成レポートで、ファイル ConfigurationRapidPrototypingInterface.h
を表示します。このヘッダー ファイルは、信号のデータを格納する構造体型を定義しています。構造体にはモデル内の各信号線を表すフィールドが格納されます。たとえば、Gain
という名前の Gain ブロックの出力信号はフィールド Gain
として表されています。
file = fullfile('ConfigurationRapidPrototypingInterface_grt_rtw','ConfigurationRapidPrototypingInterface.h'); coder.example.extractLines(file,'/* Block signals (default storage) */',... 'B_ConfigurationRapidPrototypingInterface_T;',1,1)
/* Block signals (default storage) */ typedef struct { real_T Delay; /* '<Root>/Delay' */ real_T Table2; /* '<Root>/Table2' */ real_T Table1; /* '<Root>/Table1' */ real_T Gain; /* '<Root>/Gain' */ boolean_T RelOp1; /* '<Root>/RelOp1' */ boolean_T RelOp2; /* '<Root>/RelOp2' */ boolean_T LogOp; /* '<Root>/LogOp' */ boolean_T DataStoreRead; /* '<Root>/Data Store Read' */ } B_ConfigurationRapidPrototypi_T; /* Block states (default storage) for system '<Root>' */ typedef struct { real_T X; /* '<Root>/Delay' */ } DW_ConfigurationRapidPrototyp_T; /* External inputs (root inport signals with default storage) */ typedef struct { real_T In1; /* '<Root>/In1' */ real_T input2; /* '<Root>/In2' */ real_T In3; /* '<Root>/In3' */ real_T In4; /* '<Root>/In4' */ } ExtU_ConfigurationRapidProtot_T; /* Parameters (default storage) */ struct P_ConfigurationRapidPrototypi_T_ { Table1_Type Table1; /* Variable: Table1 * Referenced by: '<Root>/Table1' */ Table2_Type Table2; /* Variable: Table2 * Referenced by: '<Root>/Table2' */ real_T LOWER; /* Variable: LOWER * Referenced by: '<Root>/Constant2' */ real_T UPPER; /* Variable: UPPER * Referenced by: '<Root>/Constant1' */ real_T Gain_Gain; /* Expression: 2 * Referenced by: '<Root>/Gain' */ real_T Delay_InitialCondition; /* Expression: 0 * Referenced by: '<Root>/Delay' */ uint32_T Table2_maxIndex[2]; /* Computed Parameter: Table2_maxIndex * Referenced by: '<Root>/Table2' */ boolean_T DataStoreMemory_InitialValue; /* Computed Parameter: DataStoreMemory_InitialValue * Referenced by: '<Root>/Data Store Memory' */ }; /* Real-time Model Data Structure */ struct tag_RTM_ConfigurationRapidPro_T { const char_T *errorStatus; }; /* Block parameters (default storage) */ extern P_ConfigurationRapidPrototypi_T ConfigurationRapidPrototyping_P; /* Block signals (default storage) */ extern B_ConfigurationRapidPrototypi_T ConfigurationRapidPrototyping_B; /* Block states (default storage) */ extern DW_ConfigurationRapidPrototyp_T ConfigurationRapidPrototypin_DW; /* External inputs (root inport signals with default storage) */ extern ExtU_ConfigurationRapidProtot_T ConfigurationRapidPrototyping_U; /* * Exported States * * Note: Exported states are block states with an exported global * storage class designation. Code generation will declare the memory for these * states and exports their symbols. * */ extern boolean_T mode; /* '<Root>/Data Store Memory' */ /* Model entry point functions */ extern void ConfigurationRapidPrototypingInterface_initialize(void); extern void ConfigurationRapidPrototypingInterface_step(void); extern void ConfigurationRapidPrototypingInterface_terminate(void); /* Exported data declaration */ /* Data with Exported storage */ extern real_T output; /* '<Root>/Out1' */ /* Real-time Model object */ extern RT_MODEL_ConfigurationRapidPr_T *const ConfigurationRapidPrototypin_M; /*- * The generated code includes comments that allow you to trace directly * back to the appropriate location in the model. The basic format * is <system>/block_name, where system is the system number (uniquely * assigned by Simulink) and block_name is the name of the block. * * Use the MATLAB hilite_system command to trace the generated code back * to the model. For example, * * hilite_system('<S3>') - opens system 3 * hilite_system('<S3>/Kp') - opens and selects block Kp which resides in S3 * * Here is the system hierarchy for this model * * '<Root>' : 'ConfigurationRapidPrototypingInterface' */ #endif /* ConfigurationRapidPrototypingInterface_h_ */
このファイルは、ブロック パラメーターのデータを格納する構造体型を定義しています。たとえば、Gain ブロックの [ゲイン] パラメーターはフィールド Gain_Gain
として表されています。構造体のその他のフィールドは、信号および状態の初期条件など、モデルの他のブロック パラメーターやワークスペース変数を表します。
coder.example.extractLines(file,'/* Parameters (default storage) */',... '/* Real-time Model Data Structure */',1,0)
/* Parameters (default storage) */ struct P_ConfigurationRapidPrototypi_T_ { Table1_Type Table1; /* Variable: Table1 * Referenced by: '<Root>/Table1' */ Table2_Type Table2; /* Variable: Table2 * Referenced by: '<Root>/Table2' */ real_T LOWER; /* Variable: LOWER * Referenced by: '<Root>/Constant2' */ real_T UPPER; /* Variable: UPPER * Referenced by: '<Root>/Constant1' */ real_T Gain_Gain; /* Expression: 2 * Referenced by: '<Root>/Gain' */ real_T Delay_InitialCondition; /* Expression: 0 * Referenced by: '<Root>/Delay' */ uint32_T Table2_maxIndex[2]; /* Computed Parameter: Table2_maxIndex * Referenced by: '<Root>/Table2' */ boolean_T DataStoreMemory_InitialValue; /* Computed Parameter: DataStoreMemory_InitialValue * Referenced by: '<Root>/Data Store Memory' */ };
5. ファイル ConfigurationRapidPrototypingInterface_data.c
を表示します。このソース ファイルは、パラメーター構造体にグローバル メモリを割り当て、モデルのパラメーターの値に基づいてフィールドの値を初期化します。
6. ソース ファイル ConfigurationRapidPrototypingInterface.c
を表示します。このコードは、信号のデータを格納する構造体変数にグローバル メモリを割り当てます。
file = fullfile('ConfigurationRapidPrototypingInterface_grt_rtw','ConfigurationRapidPrototypingInterface.c'); coder.example.extractLines(file,'/* Block signals (default storage) */',... 'B_ConfigurationRapidPrototypingInterface_T ConfigurationRapidPrototypingInterface_B;',1,1)
/* Block signals (default storage) */ B_ConfigurationRapidPrototypi_T ConfigurationRapidPrototyping_B; /* Block states (default storage) */ DW_ConfigurationRapidPrototyp_T ConfigurationRapidPrototypin_DW; /* External inputs (root inport signals with default storage) */ ExtU_ConfigurationRapidProtot_T ConfigurationRapidPrototyping_U; /* Real-time model */ static RT_MODEL_ConfigurationRapidPr_T ConfigurationRapidPrototypin_M_; RT_MODEL_ConfigurationRapidPr_T *const ConfigurationRapidPrototypin_M = &ConfigurationRapidPrototypin_M_; /* Model step function */ void ConfigurationRapidPrototypingInterface_step(void) { /* RelationalOperator: '<Root>/RelOp1' incorporates: * Constant: '<Root>/Constant1' * Inport: '<Root>/In1' */ ConfigurationRapidPrototyping_B.RelOp1 = (ConfigurationRapidPrototyping_U.In1 > ConfigurationRapidPrototyping_P.UPPER); /* RelationalOperator: '<Root>/RelOp2' incorporates: * Constant: '<Root>/Constant2' * Inport: '<Root>/In1' */ ConfigurationRapidPrototyping_B.RelOp2 = (ConfigurationRapidPrototyping_U.In1 < ConfigurationRapidPrototyping_P.LOWER); /* Logic: '<Root>/LogOp' */ ConfigurationRapidPrototyping_B.LogOp = (ConfigurationRapidPrototyping_B.RelOp1 || ConfigurationRapidPrototyping_B.RelOp2); /* DataStoreWrite: '<Root>/Data Store Write' */ mode = ConfigurationRapidPrototyping_B.LogOp; /* DataStoreRead: '<Root>/Data Store Read' */ ConfigurationRapidPrototyping_B.DataStoreRead = mode; /* UnitDelay: '<Root>/Delay' */ ConfigurationRapidPrototyping_B.Delay = ConfigurationRapidPrototypin_DW.X; /* Switch: '<Root>/Switch' */ if (ConfigurationRapidPrototyping_B.DataStoreRead) { /* Lookup_n-D: '<Root>/Table1' incorporates: * Inport: '<Root>/In2' */ ConfigurationRapidPrototyping_B.Table1 = look1_binlc (ConfigurationRapidPrototyping_U.input2, ConfigurationRapidPrototyping_P.Table1.BP, ConfigurationRapidPrototyping_P.Table1.Table, 10U); /* Gain: '<Root>/Gain' */ ConfigurationRapidPrototyping_B.Gain = ConfigurationRapidPrototyping_P.Gain_Gain * ConfigurationRapidPrototyping_B.Table1; /* Outport: '<Root>/Out1' */ output = ConfigurationRapidPrototyping_B.Gain; } else { /* Outport: '<Root>/Out1' */ output = ConfigurationRapidPrototyping_B.Delay; } /* End of Switch: '<Root>/Switch' */ /* Lookup_n-D: '<Root>/Table2' incorporates: * Inport: '<Root>/In3' * Inport: '<Root>/In4' */ ConfigurationRapidPrototyping_B.Table2 = look2_binlc (ConfigurationRapidPrototyping_U.In3, ConfigurationRapidPrototyping_U.In4, ConfigurationRapidPrototyping_P.Table2.BP1, ConfigurationRapidPrototyping_P.Table2.BP2, ConfigurationRapidPrototyping_P.Table2.Table, ConfigurationRapidPrototyping_P.Table2_maxIndex, 3U); /* Update for UnitDelay: '<Root>/Delay' */ ConfigurationRapidPrototypin_DW.X = ConfigurationRapidPrototyping_B.Table2; } /* Model initialize function */ void ConfigurationRapidPrototypingInterface_initialize(void) { /* Registration code */ /* initialize error status */ rtmSetErrorStatus(ConfigurationRapidPrototypin_M, (NULL)); /* block I/O */ (void) memset(((void *) &ConfigurationRapidPrototyping_B), 0, sizeof(B_ConfigurationRapidPrototypi_T)); /* Storage classes */ output = 0.0; /* states (dwork) */ (void) memset((void *)&ConfigurationRapidPrototypin_DW, 0, sizeof(DW_ConfigurationRapidPrototyp_T)); /* exported global states */ mode = false; /* external inputs */ (void)memset(&ConfigurationRapidPrototyping_U, 0, sizeof (ExtU_ConfigurationRapidProtot_T)); /* Start for DataStoreMemory: '<Root>/Data Store Memory' */ mode = ConfigurationRapidPrototyping_P.DataStoreMemory_InitialValue; /* InitializeConditions for UnitDelay: '<Root>/Delay' */ ConfigurationRapidPrototypin_DW.X = ConfigurationRapidPrototyping_P.Delay_InitialCondition; } /* Model terminate function */ void ConfigurationRapidPrototypingInterface_terminate(void) { /* (no terminate code required) */ }
信号の値は、モデルの関数 step
のコード アルゴリズムで計算されます。その後、それらの値が信号構造体のフィールドに代入されます。アルゴリズムによる計算には、パラメーター構造体のフィールドのパラメーター値が使用されます。
最適化からのデータ項目の除外
[信号ストレージの再利用] などのコード生成の最適化を選択する際、個々のデータ項目について、最適化しないで保持することができます。それらの項目に対しては、生成コードでアドレス可能メモリが割り当てられます。
前にクリアした最適化を選択します。
set_param('ConfigurationRapidPrototypingInterface','OptimizeBlockIOStorage','on') set_param('ConfigurationRapidPrototypingInterface','LocalBlockOutputs','on') set_param('ConfigurationRapidPrototypingInterface','DefaultParameterBehavior','Inlined')
1. [C コード] タブで、[コード インターフェイス]、[個々の要素コードのマッピング] を選択します。
2. コード マッピング エディターで [信号/状態] タブを検査します。
3. モデルで、Gain ブロックの出力信号を選択します。
4. 信号線の上または下に表示される省略記号上で一時停止してアクション バーを開きます。[信号の追加] ボタンをクリックします。コード マッピング エディターで [信号] ノードが展開され、追加した信号がリストされます。
cm = coder.mapping.api.get('ConfigurationRapidPrototypingInterface'); gain_ports = get_param('ConfigurationRapidPrototypingInterface/Gain','PortHandles'); gain_outPort = gain_ports.Outport; addSignal(cm,gain_outPort);
5. [ストレージ クラス] を Model default
に設定して、Outport の既定のストレージ クラスを信号に適用します。
setSignal(cm,gain_outPort,'StorageClass','Model default','Identifier','Gain');
6. モデルで Gain ブロックを選択します。
7. プロパティ インスペクターで、ゲイン値をモデル ワークスペース パラメーター オブジェクト K1
に設定します。
8. コード マッピング エディターの [パラメーター] タブで [Model parameters] を展開します。
9. パラメーター K1
を選択します。[ストレージ クラス] を設定して、Auto
以外のストレージ クラスを適用します。たとえば、ストレージ クラス Model default
を使用します。Model default
を使用して、K1
はモデル パラメーター Default
に対して指定された既定のストレージ クラスを取得し、グローバルなパラメーター構造体のフィールドとして表示されます。
set_param('ConfigurationRapidPrototypingInterface/Gain','Gain','K1'); setModelParameter(cm,'K1','StorageClass','Model default');
10. コードを生成します。
slbuild('ConfigurationRapidPrototypingInterface')
### Starting build procedure for: ConfigurationRapidPrototypingInterface ### Successful completion of build procedure for: ConfigurationRapidPrototypingInterface Build Summary Top model targets built: Model Action Rebuild Reason ======================================================================================================= ConfigurationRapidPrototypingInterface 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 17.674s
11.コード生成レポートで、ファイル ConfigurationRapidPrototypingInterface.h
を表示します。信号のデータを格納する構造体は、Gain ブロックのテスト ポイント出力を表すフィールド Gain
のみを 1 つ定義しています。
file = fullfile('ConfigurationRapidPrototypingInterface_grt_rtw','ConfigurationRapidPrototypingInterface.h'); coder.example.extractLines(file,'/* Block signals (default storage) */',... 'B_ConfigurationRapidPrototypingInterface_T;',1,1)
/* Block signals (default storage) */ typedef struct { real_T Gain; /* '<Root>/Gain' */ } B_ConfigurationRapidPrototypi_T; /* Block states (default storage) for system '<Root>' */ typedef struct { real_T X; /* '<Root>/Delay' */ } DW_ConfigurationRapidPrototyp_T; /* External inputs (root inport signals with default storage) */ typedef struct { real_T In1; /* '<Root>/In1' */ real_T input2; /* '<Root>/In2' */ real_T In3; /* '<Root>/In3' */ real_T In4; /* '<Root>/In4' */ } ExtU_ConfigurationRapidProtot_T; /* Parameters (default storage) */ struct P_ConfigurationRapidPrototypi_T_ { int8_T K1; /* Variable: K1 * Referenced by: '<Root>/Gain' */ }; /* Real-time Model Data Structure */ struct tag_RTM_ConfigurationRapidPro_T { const char_T *errorStatus; }; /* Block parameters (default storage) */ extern P_ConfigurationRapidPrototypi_T ConfigurationRapidPrototyping_P; /* Block signals (default storage) */ extern B_ConfigurationRapidPrototypi_T ConfigurationRapidPrototyping_B; /* Block states (default storage) */ extern DW_ConfigurationRapidPrototyp_T ConfigurationRapidPrototypin_DW; /* External inputs (root inport signals with default storage) */ extern ExtU_ConfigurationRapidProtot_T ConfigurationRapidPrototyping_U; /* * Exported States * * Note: Exported states are block states with an exported global * storage class designation. Code generation will declare the memory for these * states and exports their symbols. * */ extern boolean_T mode; /* '<Root>/Data Store Memory' */ /* Model entry point functions */ extern void ConfigurationRapidPrototypingInterface_initialize(void); extern void ConfigurationRapidPrototypingInterface_step(void); extern void ConfigurationRapidPrototypingInterface_terminate(void); /* Exported data declaration */ /* Data with Exported storage */ extern real_T output; /* '<Root>/Out1' */ /* Real-time Model object */ extern RT_MODEL_ConfigurationRapidPr_T *const ConfigurationRapidPrototypin_M; /*- * The generated code includes comments that allow you to trace directly * back to the appropriate location in the model. The basic format * is <system>/block_name, where system is the system number (uniquely * assigned by Simulink) and block_name is the name of the block. * * Use the MATLAB hilite_system command to trace the generated code back * to the model. For example, * * hilite_system('<S3>') - opens system 3 * hilite_system('<S3>/Kp') - opens and selects block Kp which resides in S3 * * Here is the system hierarchy for this model * * '<Root>' : 'ConfigurationRapidPrototypingInterface' */ #endif /* ConfigurationRapidPrototypingInterface_h_ */
ブロック パラメーターのデータを格納する構造体は、パラメーター オブジェクト K1
を表すフィールド K1
を 1 つ定義しています。
coder.example.extractLines(file,'/* Parameters (default storage) */',... '/* Real-time Model Data Structure */',1,0)
/* Parameters (default storage) */ struct P_ConfigurationRapidPrototypi_T_ { int8_T K1; /* Variable: K1 * Referenced by: '<Root>/Gain' */ };
生成されたインターフェイスによるデータへのアクセス
標準化されたインターフェイスを介してモデル データにアクセスするために、生成コードに追加のコードやファイルを含めるように設定できます。たとえば、信号のデータをログに記録したり実行時にパラメーターを調整したりするには C API を使用します。
次のカスタム ソース コードを現在のフォルダーの ex_myHandCode.c
という名前のファイルにコピーします。
#include "ex_myHandHdr.h" #define paramIdx 0 /* Index of the target parameter, determined by inspecting the array of structures generated by the C API. */ #define sigIdx 0 /* Index of the target signal, determined by inspecting the array of structures generated by the C API. */ void tuneFcn(rtwCAPI_ModelMappingInfo *mmi, time_T *tPtr) { /* Take action with the parameter value only at the beginning of simulation and at the 5-second mark. */ if (*tPtr == 0 || *tPtr == 5) { /* Local variables to store information extracted from the model mapping information (mmi). */ void** dataAddrMap; const rtwCAPI_DataTypeMap *dataTypeMap; const rtwCAPI_ModelParameters *params; int_T addrIdx; uint16_T dTypeIdx; uint8_T slDataType; /* Use built-in C API macros to extract information. */ dataAddrMap = rtwCAPI_GetDataAddressMap(mmi); dataTypeMap = rtwCAPI_GetDataTypeMap(mmi); params = rtwCAPI_GetModelParameters(mmi); addrIdx = rtwCAPI_GetModelParameterAddrIdx(params,paramIdx); dTypeIdx = rtwCAPI_GetModelParameterDataTypeIdx(params,paramIdx); slDataType = rtwCAPI_GetDataTypeSLId(dataTypeMap, dTypeIdx); /* Handle data types 'double' and 'int8'. */ switch (slDataType) { case SS_DOUBLE: { real_T* dataAddress; dataAddress = dataAddrMap[addrIdx]; /* At the 5-second mark, increment the parameter value by 1. */ if (*tPtr == 5) { (*dataAddress)++; } printf("Parameter value is %f\n", *dataAddress); break; } case SS_INT8: { int8_T* dataAddress; dataAddress = dataAddrMap[addrIdx]; if (*tPtr == 5) { (*dataAddress)++; } printf("Parameter value is %i\n", *dataAddress); break; } } } } void logFcn(rtwCAPI_ModelMappingInfo *mmi, time_T *tPtr) { /* Take action with the signal value only when the simulation time is an integer value. */ if (*tPtr-(int_T)*tPtr == 0) { /* Local variables to store information extracted from the model mapping information (mmi). */ void** dataAddrMap; const rtwCAPI_DataTypeMap *dataTypeMap; const rtwCAPI_Signals *sigs; int_T addrIdx; uint16_T dTypeIdx; uint8_T slDataType; /* Use built-in C API macros to extract information. */ dataAddrMap = rtwCAPI_GetDataAddressMap(mmi); dataTypeMap = rtwCAPI_GetDataTypeMap(mmi); sigs = rtwCAPI_GetSignals(mmi); addrIdx = rtwCAPI_GetSignalAddrIdx(sigs,sigIdx); dTypeIdx = rtwCAPI_GetSignalDataTypeIdx(sigs,sigIdx); slDataType = rtwCAPI_GetDataTypeSLId(dataTypeMap, dTypeIdx); /* Handle data types 'double' and 'single'. */ switch (slDataType) { case SS_DOUBLE: { real_T* dataAddress; dataAddress = dataAddrMap[addrIdx]; printf("Signal value is %f\n", *dataAddress); break; } case SS_SINGLE: { real32_T* dataAddress; dataAddress = dataAddrMap[addrIdx]; printf("Signal value is %f\n", *dataAddress); break; } } } }
2. 次のカスタム ヘッダー コードを現在のフォルダーの ex_myHandHdr.h
という名前のファイルにコピーします。
#include <stdio.h> #include <string.h> #include <math.h> /* Include rtw_modelmap.h for definitions of C API macros. */ #include "rtw_modelmap.h" #include "builtin_typeid_types.h" #include "rtwtypes.h" void tuneFcn(rtwCAPI_ModelMappingInfo *mmi, time_T *tPtr); void logFcn(rtwCAPI_ModelMappingInfo *mmi, time_T *tPtr);
これらのファイルでは、モデル例から生成したコードの信号やパラメーター データにアクセスするために C API を使用します。
3. モデル コンフィギュレーション パラメーター [インクルード ヘッダー] を [#include "ex_myHandHdr.h"]
に、[ソース ファイル] を [ex_myHandCode.c]
に設定します。
set_param('ConfigurationRapidPrototypingInterface','CustomHeaderCode','#include "ex_myHandHdr.h"') set_param('ConfigurationRapidPrototypingInterface','CustomSource','ex_myHandCode.c')
4. モデル コンフィギュレーション パラメーター [MAT ファイルのログ] を選択します。生成された実行可能ファイルは、シミュレーションの停止時間 (モデル コンフィギュレーション パラメーターで設定) までしか実行されません。
set_param('ConfigurationRapidPrototypingInterface','MatFileLogging','on')
5. C API モデル コンフィギュレーション パラメーター [パラメーター]、[信号]、[状態]、[ルートレベル I/O] を選択します。
set_param('ConfigurationRapidPrototypingInterface','RTWCAPIParams','on') set_param('ConfigurationRapidPrototypingInterface','RTWCAPISignals','on') set_param('ConfigurationRapidPrototypingInterface','RTWCAPIStates','on') set_param('ConfigurationRapidPrototypingInterface','RTWCAPIRootIO','on')
6. Custom Code ブロック ライブラリを読み込みます。
custcode
7. モデルに System Outputs ブロックを追加します。
add_block('custcode/System Outputs','ConfigurationRapidPrototypingInterface/System Outputs')
8. System Outputs ブロックのダイアログ ボックスで、[System Outputs Function 実行コード] を次のコードに設定します。
{ ConfigurationRapidPrototypingInterface_U.input2++; rtwCAPI_ModelMappingInfo *MMI = &(rtmGetDataMapInfo(ConfigurationRapidPrototypingInterface_M).mmi); tuneFcn(MMI, rtmGetTPtr(ConfigurationRapidPrototypingInterface_M)); }
9. ブロックのダイアログ ボックスで、[System Outputs Function 終了コード] を次のコードに設定します。
{ rtwCAPI_ModelMappingInfo *MMI = &(rtmGetDataMapInfo(ConfigurationRapidPrototypingInterface_M).mmi); logFcn(MMI, rtmGetTPtr(ConfigurationRapidPrototypingInterface_M)); }
または、System Outputs ブロックの設定のために、コマンド プロンプトで以下のコマンドを使用します。
temp.TLCFile = 'custcode'; temp.Location = 'System Outputs Function'; temp.Middle = sprintf(['{\nConfigurationRapidPrototyping_U.input2++;'... '\nrtwCAPI_ModelMappingInfo *MMI = '... '&(rtmGetDataMapInfo(ConfigurationRapidPrototypingInterface_M).mmi);'... '\ntuneFcn(MMI, rtmGetTPtr(ConfigurationRapidPrototypingInterface_M));\n}']); temp.Bottom = sprintf(['{\nrtwCAPI_ModelMappingInfo *MMI = '... '&(rtmGetDataMapInfo(ConfigurationRapidPrototypingInterface_M).mmi);'... '\nlogFcn(MMI, rtmGetTPtr(ConfigurationRapidPrototypingInterface_M));\n}']); set_param('ConfigurationRapidPrototypingInterface/System Outputs','RTWdata',temp)
10. コードを生成します。
slbuild('ConfigurationRapidPrototypingInterface')
### Starting build procedure for: ConfigurationRapidPrototypingInterface ### Successful completion of build procedure for: ConfigurationRapidPrototypingInterface Build Summary Top model targets built: Model Action Rebuild Reason ======================================================================================================= ConfigurationRapidPrototypingInterface 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 23.089s
11.コード生成レポートで、インターフェイス ファイル ConfigurationRapidPrototypingInterface_capi.c
を表示します。このファイルは、C API を介したデータ項目の処理に使用できる構造体の配列を初期化します。たとえば、構造体 rtBlockSignals
の配列では、最初の構造体 (インデックス 0) は、モデルの Gain ブロックのテスト ポイント出力信号を表します。
file = fullfile('ConfigurationRapidPrototypingInterface_grt_rtw','ConfigurationRapidPrototypingInterface_capi.c'); coder.example.extractLines(file,'/* Block output signal information */',... '/* Individual block tuning',1,0)
/* Block output signal information */ static const rtwCAPI_Signals rtBlockSignals[] = { /* addrMapIndex, sysNum, blockPath, * signalName, portNumber, dataTypeIndex, dimIndex, fxpIndex, sTimeIndex */ { 0, 0, TARGET_STRING("ConfigurationRapidPrototypingInterface/Gain"), TARGET_STRING(""), 0, 0, 0, 0, 0 }, { 0, 0, (NULL), (NULL), 0, 0, 0, 0, 0 } };
addrMapIndex
などの構造体のフィールドは、信号の特性を表す rtDataAddrMap
など他の構造体の配列のインデックスを示します。これらの特性には、信号データのアドレス (データへのポインター)、数値データ型および信号の次元が含まれます。
12.ファイル ConfigurationRapidPrototypingInterface.c
で、モデルの関数 step
のコード アルゴリズムを表示します。アルゴリズムでは、最初に System Outputs ブロックで指定したコードが実行されます。
file = fullfile('ConfigurationRapidPrototypingInterface_grt_rtw','ConfigurationRapidPrototypingInterface.c'); coder.example.extractLines(file,'/* user code (Output function Body) */',... '/* Logic: ''<Root>/LogOp'' incorporates:',1,0)
/* user code (Output function Body) */ /* System '<Root>' */ { ConfigurationRapidPrototyping_U.input2++; rtwCAPI_ModelMappingInfo *MMI = &(rtmGetDataMapInfo (ConfigurationRapidPrototypingInterface_M).mmi); tuneFcn(MMI, rtmGetTPtr(ConfigurationRapidPrototypingInterface_M)); } /* DataStoreWrite: '<Root>/Data Store Write' incorporates: * Constant: '<Root>/Constant1' * Constant: '<Root>/Constant2' * Inport: '<Root>/In1' * Logic: '<Root>/LogOp' * RelationalOperator: '<Root>/RelOp1' * RelationalOperator: '<Root>/RelOp2' */ mode = ((ConfigurationRapidPrototyping_U.In1 > 10.0) || (ConfigurationRapidPrototyping_U.In1 < -10.0)); /* Gain: '<Root>/Gain' incorporates: * Inport: '<Root>/In2' * Lookup_n-D: '<Root>/Table1' */ ConfigurationRapidPrototyping_B.Gain = (real_T) ConfigurationRapidPrototyping_P.K1 * look1_binlc (ConfigurationRapidPrototyping_U.input2, rtCP_Table1_bp01Data, rtCP_Table1_tableData, 10U); /* Switch: '<Root>/Switch' incorporates: * DataStoreRead: '<Root>/Data Store Read' */ if (mode) { /* Outport: '<Root>/Out1' */ output = ConfigurationRapidPrototyping_B.Gain; } else { /* Outport: '<Root>/Out1' incorporates: * UnitDelay: '<Root>/Delay' */ output = ConfigurationRapidPrototypin_DW.X; } /* End of Switch: '<Root>/Switch' */ /* Lookup_n-D: '<Root>/Table2' incorporates: * Inport: '<Root>/In3' * Inport: '<Root>/In4' */ rtb_Table2 = look2_binlc(ConfigurationRapidPrototyping_U.In3, ConfigurationRapidPrototyping_U.In4, rtCP_Table2_bp01Data, rtCP_Table2_bp02Data, rtCP_Table2_tableData, rtCP_Table2_maxIndex, 3U); /* user code (Output function Trailer) */ /* System '<Root>' */ { rtwCAPI_ModelMappingInfo *MMI = &(rtmGetDataMapInfo (ConfigurationRapidPrototypingInterface_M).mmi); logFcn(MMI, rtmGetTPtr(ConfigurationRapidPrototypingInterface_M)); } /* Update for UnitDelay: '<Root>/Delay' */ ConfigurationRapidPrototypin_DW.X = rtb_Table2; /* Matfile logging */ rt_UpdateTXYLogVars(ConfigurationRapidPrototypin_M->rtwLogInfo, (&ConfigurationRapidPrototypin_M->Timing.taskTime0)); /* signal main to stop simulation */ { /* Sample time: [1.0s, 0.0s] */ if ((rtmGetTFinal(ConfigurationRapidPrototypin_M)!=-1) && !((rtmGetTFinal(ConfigurationRapidPrototypin_M)- ConfigurationRapidPrototypin_M->Timing.taskTime0) > ConfigurationRapidPrototypin_M->Timing.taskTime0 * (DBL_EPSILON))) { rtmSetErrorStatus(ConfigurationRapidPrototypin_M, "Simulation finished"); } } /* Update absolute time for base rate */ /* The "clockTick0" counts the number of times the code of this task has * been executed. The absolute time is the multiplication of "clockTick0" * and "Timing.stepSize0". Size of "clockTick0" ensures timer will not * overflow during the application lifespan selected. * Timer of this task consists of two 32 bit unsigned integers. * The two integers represent the low bits Timing.clockTick0 and the high bits * Timing.clockTickH0. When the low bit overflows to 0, the high bits increment. */ if (!(++ConfigurationRapidPrototypin_M->Timing.clockTick0)) { ++ConfigurationRapidPrototypin_M->Timing.clockTickH0; } ConfigurationRapidPrototypin_M->Timing.taskTime0 = ConfigurationRapidPrototypin_M->Timing.clockTick0 * ConfigurationRapidPrototypin_M->Timing.stepSize0 + ConfigurationRapidPrototypin_M->Timing.clockTickH0 * ConfigurationRapidPrototypin_M->Timing.stepSize0 * 4294967296.0; } /* Model initialize function */ void ConfigurationRapidPrototypingInterface_initialize(void) { /* Registration code */ /* initialize non-finites */ rt_InitInfAndNaN(sizeof(real_T)); /* initialize real-time model */ (void) memset((void *)ConfigurationRapidPrototypin_M, 0, sizeof(RT_MODEL_ConfigurationRapidPr_T)); rtmSetTFinal(ConfigurationRapidPrototypin_M, 10.0); ConfigurationRapidPrototypin_M->Timing.stepSize0 = 1.0; /* Setup for data logging */ { static RTWLogInfo rt_DataLoggingInfo; rt_DataLoggingInfo.loggingInterval = (NULL); ConfigurationRapidPrototypin_M->rtwLogInfo = &rt_DataLoggingInfo; } /* Setup for data logging */ { rtliSetLogXSignalInfo(ConfigurationRapidPrototypin_M->rtwLogInfo, (NULL)); rtliSetLogXSignalPtrs(ConfigurationRapidPrototypin_M->rtwLogInfo, (NULL)); rtliSetLogT(ConfigurationRapidPrototypin_M->rtwLogInfo, ""); rtliSetLogX(ConfigurationRapidPrototypin_M->rtwLogInfo, ""); rtliSetLogXFinal(ConfigurationRapidPrototypin_M->rtwLogInfo, ""); rtliSetLogVarNameModifier(ConfigurationRapidPrototypin_M->rtwLogInfo, "rt_"); rtliSetLogFormat(ConfigurationRapidPrototypin_M->rtwLogInfo, 0); rtliSetLogMaxRows(ConfigurationRapidPrototypin_M->rtwLogInfo, 1000); rtliSetLogDecimation(ConfigurationRapidPrototypin_M->rtwLogInfo, 1); rtliSetLogY(ConfigurationRapidPrototypin_M->rtwLogInfo, ""); rtliSetLogYSignalInfo(ConfigurationRapidPrototypin_M->rtwLogInfo, (NULL)); rtliSetLogYSignalPtrs(ConfigurationRapidPrototypin_M->rtwLogInfo, (NULL)); } /* block I/O */ (void) memset(((void *) &ConfigurationRapidPrototyping_B), 0, sizeof(B_ConfigurationRapidPrototypi_T)); /* Storage classes */ output = 0.0; /* states (dwork) */ (void) memset((void *)&ConfigurationRapidPrototypin_DW, 0, sizeof(DW_ConfigurationRapidPrototyp_T)); /* exported global states */ mode = false; /* external inputs */ (void)memset(&ConfigurationRapidPrototyping_U, 0, sizeof (ExtU_ConfigurationRapidProtot_T)); /* Initialize DataMapInfo substructure containing ModelMap for C API */ ConfigurationRapidPrototypingInterface_InitializeDataMapInfo(); /* Matfile logging */ rt_StartDataLoggingWithStartTime(ConfigurationRapidPrototypin_M->rtwLogInfo, 0.0, rtmGetTFinal(ConfigurationRapidPrototypin_M), ConfigurationRapidPrototypin_M->Timing.stepSize0, (&rtmGetErrorStatus (ConfigurationRapidPrototypin_M))); /* Start for DataStoreMemory: '<Root>/Data Store Memory' */ mode = false; /* InitializeConditions for UnitDelay: '<Root>/Delay' */ ConfigurationRapidPrototypin_DW.X = 0.0; } /* Model terminate function */ void ConfigurationRapidPrototypingInterface_terminate(void) { /* (no terminate code required) */ }
このコードでは最初に、関数 step
が実行されるたびに信号の値をインクリメントして入力信号 input2
に摂動を与えます。その後、コードは組み込みのマクロ rtmGetDataMapInfo
を使用して、モデル データ構造体 ConfigurationRapidPrototypingInterface_M
からモデル マッピング情報を抽出します。ポインター MMI
は抽出されたマッピング情報をポイントします。これにより、関数 tuneFcn
および関数 logFcn
は、C API ファイル ConfigurationRapidPrototypingInterface_capi.c
で定義されている構造体の配列に含まれる情報にアクセスできます。
13.ファイル ex_myHandCode.c
の関数 tuneFcn
を表示します。この関数は、C API (モデル マッピング情報 mmi
を介して) およびシミュレーション時間へのポインターを使用して、コード実行中の特定の時間にパラメーター K1
の値を出力します。シミュレーション時間が 5 秒に達すると、関数はメモリ内のパラメーター値を変更します。switch case
ブロックを使用することで、関数はデータ型が int8
または double
のどちらでも、パラメーター データにアクセスできます。
14.モデルの関数 step
のコード アルゴリズムをもう一度表示します。関数の終わりに近づくと、アルゴリズムは System Outputs ブロックで指定したコードを実行します。このコードは関数 logFcn
を呼び出します。
coder.example.extractLines(file,'/* user code (Output function Trailer) */',... '/* Matfile logging */',1,0)
/* user code (Output function Trailer) */ /* System '<Root>' */ { rtwCAPI_ModelMappingInfo *MMI = &(rtmGetDataMapInfo (ConfigurationRapidPrototypingInterface_M).mmi); logFcn(MMI, rtmGetTPtr(ConfigurationRapidPrototypingInterface_M)); } /* Update for UnitDelay: '<Root>/Delay' */ ConfigurationRapidPrototypin_DW.X = rtb_Table2;
15.ファイル ex_myHandCode.c
の関数 logFcn
を表示します。この関数は C API を使用してテスト ポイントされた信号の値を出力します。関数は、データ型が single
または double
のどちらでも信号データにアクセスできます。
16.コマンド プロンプトで、生成された実行可能ファイル ConfigurationRapidPrototypingInterface.exe
を実行します。
system('ConfigurationRapidPrototypingInterface')
パラメーターと信号値がコマンド ウィンドウの出力に表示されます。
C API などのデータ インターフェイスの詳細については、生成されたコードのインターフェイスを参照してください。
データ アクセスの設定
目的 | 考慮事項および詳細情報 |
---|---|
既定で信号をアクセス可能にしてパラメーターを調整可能に設定する | モデル コンフィギュレーション パラメーター [信号ストレージの再利用] をクリアして、コンフィギュレーション パラメーター [既定のパラメーター動作] を [既定のパラメーター動作] の詳細については、既定のパラメーター動作を参照してください。信号のストレージを削除する最適化の詳細については、生成されたコードによる内部信号、状態、パラメーター データの保存方法およびブロック出力時の中間結果の計算と保存の最小化を参照してください。 |
最適化の選択後にデータ項目のアクセスと調整可能性を維持する | [信号ストレージの再利用] などの最適化を選択することでさらに効率的なコードを生成できますが、コード ジェネレーターはデータ項目の数と同数のストレージを削除します。個々のデータ項目を最適化から除外するには、次を行います。
|
生成されたコードで、データ項目を別個のグローバル変数として表現する | 最適化を無効にすると、信号線、ブロック状態、パラメーターは、生成されたコードで構造体のフィールドとして表示されます。Embedded Coder® がないと、構造体の名前を制御できません。代わりにデータ項目を別のグローバル変数の名前、ファイルの配置およびその他の制御可能な特性に保存するには、ストレージ クラスを信号、状態または |
データにアクセスするための標準化された C コード インターフェイスを生成する | 標準化されたインターフェイスを介してモデル データにアクセスするために、生成コードに追加のコードやファイルを含めるように設定できます。詳細については、C API を使用した生成コードと外部コードの間のデータ交換を参照してください。 |
パラメーターの調整とエクスターナル モード シミュレーション中の信号の監視 | モデルからコードおよび外部の実行可能ファイルを生成する場合、エクスターナル モードでモデルのシミュレーションを実行し、実行中の実行可能ファイルと通信できます。シミュレーション中にパラメーターを調整して信号をモニターできます。ただし、このシミュレーション モードでは、コード生成に適用されるパラメーターの調整可能性の制限がシミュレーションにも適用されます。コード生成の制限事項の詳細については、生成されたコードにおけるブロック パラメーターの調整可能性の制限を参照してください。 エクスターナル モードの詳細については、エクスターナル モード シミュレーションによるパラメーター調整、信号監視、コード実行プロファイリングを参照してください。 |
Simulink® Real-Time™ を使用してパラメーターを調整し、信号を監視する | Simulink Real-Time をご利用の場合、リアルタイム アプリケーションの実行中にパラメーターを調整して信号を監視できます。最適化をクリアしてテスト ポイントとストレージ クラスを適用することで、信号にアクセス可能にしてパラメーターを調節可能にします。Parameter Tuning with Simulink Real-Time Explorer (Simulink Real-Time)を参照してください。 |
制限
生成されたコードでパラメーターの調整可能性に適用される制限の詳細については、生成されたコードにおけるブロック パラメーターの調整可能性の制限を参照してください。