このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。
再利用可能な参照モデルへのインスタンス固有パラメーター値の指定
モデル参照を使用して大規模なシステムをコンポーネントに分割する場合、各コンポーネントは個別のモデルになります。コンポーネントは複数の Model ブロックで参照することにより、再利用できます。各 Model ブロックはコンポーネントのインスタンスです。次に、ブロック パラメーター (Gain ブロックの [ゲイン] パラメーターなど) を設定して、コンポーネントの各インスタンスに同じ値または異なる値のいずれかを使用できます。異なる値を使用する場合、モデル引数を作成して使用し、ブロック パラメーターの値を設定します。
モデル引数を使用するモデルの階層構造からコードを生成する場合、引数は出力の関数 (step
) など、参照モデルのエントリ ポイント関数の仮パラメーターとしてコードに表示されます。生成されたコードは次に、各 Model ブロックに指定するインスタンス固有パラメーター値を対応する関数呼び出しに渡します。
モデル引数を使用するか否かに関係なく、ストレージ クラスを使用し、生成されたコードに調整可能なグローバル変数として表示されるようにブロック パラメーターを設定できます。また、ストレージ クラスを使用して、生成されたコードによりメモリに保存されて関数呼び出しに渡される、調整可能なモデル引数の値を生成することもできます。この後、実行中に値を変更できます。
パラメーター データを参照モデルのエントリポイント関数に引数として渡す
生成モデルのエントリポイント関数の仮パラメーターを介して、パラメーター データを受け取るように参照モデルを構成します。この手法により、参照モデルのインスタンス (Model ブロック) ごとに異なるパラメーター値を指定できます。
モデル引数を使用するように参照モデルを構成する
モデル ex_arg_code_ref
を開きます。このモデルは再利用可能なアルゴリズムを表します。
open_system('ex_arg_code_ref')
[モデル化] タブで [モデル データ エディター] をクリックします。
モデル データ エディターのデータ テーブルで、[データ型] 列を使用して Inport ブロックのデータ型を single
に設定します。データ型の継承により、モデル内のその他の信号は同じデータ型を使用します。
[パラメーター] タブを選択します。
モデルで Gain ブロックを選択します。
モデル データ エディターで、[値] 列を使用して、[ゲイン] パラメーターの値を gainArg
に設定します。gainArg
はモデル ワークスペースの Simulink.Parameter
オブジェクトであり、その値は 3.17
です。
モデル データ エディターを使用して、[分子係数] パラメーターを Simulink.Parameter
オブジェクト coeffArg
(値 1.05
) に設定します。
モデル データ エディターで [追加情報の表示/更新] ボタンをクリックします。
[コンテンツのフィルター] ボックスを使用して、各パラメーター オブジェクト (gainArg
と coeffArg
) を検索します。それぞれのオブジェクトについて、[引数] 列のチェック ボックスをオンにします。
ex_arg_code_ref
モデルを保存します。
または、コマンド プロンプトで、次のコマンドを使用してブロックとパラメーター オブジェクトを設定できます。
set_param('ex_arg_code_ref/In1','OutDataTypeStr','single') set_param('ex_arg_code_ref/Gain','Gain','gainArg') modelWorkspace = get_param('ex_arg_code_ref','ModelWorkspace'); assignin(modelWorkspace,'gainArg',Simulink.Parameter(3.17)); set_param('ex_arg_code_ref/Discrete Filter','Numerator','coeffArg') assignin(modelWorkspace,'coeffArg',Simulink.Parameter(1.05)); set_param('ex_arg_code_ref','ParameterArgumentNames','coeffArg,gainArg') save_system('ex_arg_code_ref')
Model ブロックにおけるインスタンス固有パラメーター値の指定
モデル ex_arg_code
を開きます。このモデルでは再利用可能なアルゴリズムの複数のインスタンス (Model ブロック) を使用します。
open_system('ex_arg_code')
モデルで、モデル データ エディターの [パラメーター] タブ ([モデル化]、[モデル データ エディター]) を開きます。モデル データ エディターに、2 つの Model ブロックに対して指定できるモデル引数 (coeffArg
と gainArg
) に対応する 4 つの行が表示されます。
モデル データ エディターを使用して Model
のモデル引数の値を設定します。たとえば、次の図の値を使用します。Model1
について、モデル引数の値を指定しないでください。既定では、モデル引数はモデルの階層構造 (値 from below
によって示される) 内で、その下で指定された最後の値を使用します。
または、コマンド プロンプトで、次のコマンドを使用して Model
の値を設定できます。
instSpecParams = get_param('ex_arg_code/Model','InstanceParameters'); instSpecParams(1).Value = '.98'; instSpecParams(2).Value = '2.98'; set_param('ex_arg_code/Model','InstanceParameters',instSpecParams);
最上位モデルからコードを生成します。
slbuild('ex_arg_code')
### Searching for referenced models in model 'ex_arg_code'. ### Found 1 model references to update. ### Starting serial model reference code generation build. ### Successfully updated the model reference code generation target for: ex_arg_code_ref ### Starting build procedure for: ex_arg_code ### Successful completion of build procedure for: ex_arg_code Build Summary Code generation targets built: Model Action Rebuild Reason ================================================================================== ex_arg_code_ref Code generated and compiled. ex_arg_code_ref.c does not exist. Top model targets built: Model Action Rebuild Reason ============================================================================================= ex_arg_code Code generated and compiled. Code generation information file does not exist. 2 of 2 models built (0 models already up to date) Build duration: 0h 0m 35.725s
ex_arg_code_ref.c
ファイルは参照モデルのエントリポイント関数 ex_arg_code_ref
を定義します。この関数には 2 つの仮パラメーター rtp_coeffArg
と rtp_gainArg
があり、モデル引数 coeffArg
と gainArg
に対応しています。仮パラメーターは、Simulink® でデータ型 single
に対応するデータ型 real32_T
を使用します。
file = fullfile('slprj','grt','ex_arg_code_ref','ex_arg_code_ref.c'); coder.example.extractLines(file,'/* Output and update for referenced model:',... 'real32_T rtp_gainArg)',1,1)
/* Output and update for referenced model: 'ex_arg_code_ref' */ void ex_arg_code_ref(const real32_T *rtu_In1, real32_T *rty_Out1, real32_T rtp_coeffArg, real32_T rtp_gainArg, DW_ex_arg_code_ref_f_T * localDW) { real32_T denAccum; real32_T rtb_Sum; /* Sum: '<Root>/Sum' incorporates: * UnitDelay: '<Root>/Unit Delay' */ rtb_Sum = *rtu_In1 + localDW->UnitDelay_DSTATE; /* Gain: '<Root>/Gain' */ rtb_Sum *= rtp_gainArg; /* DiscreteFilter: '<Root>/Discrete Filter' */ localDW->DiscreteFilter_tmp = rtb_Sum - 0.5F * localDW->DiscreteFilter_states; denAccum = rtp_coeffArg * localDW->DiscreteFilter_tmp; *rty_Out1 = denAccum; /* Update for UnitDelay: '<Root>/Unit Delay' */ localDW->UnitDelay_DSTATE = rtb_Sum; /* Update for DiscreteFilter: '<Root>/Discrete Filter' */ localDW->DiscreteFilter_states = localDW->DiscreteFilter_tmp; } /* Model initialize function */ void ex_arg_code_ref_initialize(const char_T **rt_errorStatus, RT_MODEL_ex_arg_code_ref_T *const ex_arg_code_ref_M, DW_ex_arg_code_ref_f_T *localDW) { /* Registration code */ /* initialize error status */ rtmSetErrorStatusPointer(ex_arg_code_ref_M, rt_errorStatus); /* states (dwork) */ (void) memset((void *)localDW, 0, sizeof(DW_ex_arg_code_ref_f_T)); }
ex_arg_code.c
ファイルには、最上位モデルのエントリポイント関数 ex_arg_code
の定義が含まれます。この関数は参照モデルのエントリポイント関数 ex_arg_code_ref
を呼び出し、rtp_coeffArg
および rtp_gainArg
の値として指定したモデル引数の値 (1.11
や 3.34
など) を使用します。
file = fullfile('ex_arg_code_grt_rtw','ex_arg_code.c'); coder.example.extractLines(file,'/* ModelReference: ''<Root>/Model'' incorporates:',... '1.05F, 3.17F)',1,1)
/* ModelReference: '<Root>/Model' incorporates: * Inport: '<Root>/In1' * Outport: '<Root>/Out1' */ ex_arg_code_ref(&ex_arg_code_U.In1, &ex_arg_code_Y.Out1, 0.98F, 2.98F, &(ex_arg_code_DW.Model_InstanceData.rtdw)); /* ModelReference: '<Root>/Model1' incorporates: * Inport: '<Root>/In1' * Outport: '<Root>/Out2' */ ex_arg_code_ref(&ex_arg_code_U.In1, &ex_arg_code_Y.Out2, 1.05F, 3.17F, &(ex_arg_code_DW.Model1_InstanceData.rtdw)); /* Matfile logging */ rt_UpdateTXYLogVars(ex_arg_code_M->rtwLogInfo, (&ex_arg_code_M->Timing.taskTime0)); /* signal main to stop simulation */ { /* Sample time: [0.2s, 0.0s] */ if ((rtmGetTFinal(ex_arg_code_M)!=-1) && !((rtmGetTFinal(ex_arg_code_M)-ex_arg_code_M->Timing.taskTime0) > ex_arg_code_M->Timing.taskTime0 * (DBL_EPSILON))) { rtmSetErrorStatus(ex_arg_code_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 (!(++ex_arg_code_M->Timing.clockTick0)) { ++ex_arg_code_M->Timing.clockTickH0; } ex_arg_code_M->Timing.taskTime0 = ex_arg_code_M->Timing.clockTick0 * ex_arg_code_M->Timing.stepSize0 + ex_arg_code_M->Timing.clockTickH0 * ex_arg_code_M->Timing.stepSize0 * 4294967296.0; } /* Model initialize function */ void ex_arg_code_initialize(void) { /* Registration code */ /* initialize non-finites */ rt_InitInfAndNaN(sizeof(real_T)); /* initialize real-time model */ (void) memset((void *)ex_arg_code_M, 0, sizeof(RT_MODEL_ex_arg_code_T)); rtmSetTFinal(ex_arg_code_M, 10.0); ex_arg_code_M->Timing.stepSize0 = 0.2; /* Setup for data logging */ { static RTWLogInfo rt_DataLoggingInfo; rt_DataLoggingInfo.loggingInterval = (NULL); ex_arg_code_M->rtwLogInfo = &rt_DataLoggingInfo; } /* Setup for data logging */ { rtliSetLogXSignalInfo(ex_arg_code_M->rtwLogInfo, (NULL)); rtliSetLogXSignalPtrs(ex_arg_code_M->rtwLogInfo, (NULL)); rtliSetLogT(ex_arg_code_M->rtwLogInfo, "tout"); rtliSetLogX(ex_arg_code_M->rtwLogInfo, ""); rtliSetLogXFinal(ex_arg_code_M->rtwLogInfo, ""); rtliSetLogVarNameModifier(ex_arg_code_M->rtwLogInfo, "rt_"); rtliSetLogFormat(ex_arg_code_M->rtwLogInfo, 0); rtliSetLogMaxRows(ex_arg_code_M->rtwLogInfo, 0); rtliSetLogDecimation(ex_arg_code_M->rtwLogInfo, 1); /* * Set pointers to the data and signal info for each output */ { static void * rt_LoggedOutputSignalPtrs[] = { &ex_arg_code_Y.Out1, &ex_arg_code_Y.Out2 }; rtliSetLogYSignalPtrs(ex_arg_code_M->rtwLogInfo, ((LogSignalPtrsType) rt_LoggedOutputSignalPtrs)); } { static int_T rt_LoggedOutputWidths[] = { 1, 1 }; static int_T rt_LoggedOutputNumDimensions[] = { 1, 1 }; static int_T rt_LoggedOutputDimensions[] = { 1, 1 }; static boolean_T rt_LoggedOutputIsVarDims[] = { 0, 0 }; static void* rt_LoggedCurrentSignalDimensions[] = { (NULL), (NULL) }; static int_T rt_LoggedCurrentSignalDimensionsSize[] = { 4, 4 }; static BuiltInDTypeId rt_LoggedOutputDataTypeIds[] = { SS_SINGLE, SS_SINGLE }; static int_T rt_LoggedOutputComplexSignals[] = { 0, 0 }; static RTWPreprocessingFcnPtr rt_LoggingPreprocessingFcnPtrs[] = { (NULL), (NULL) }; static const char_T *rt_LoggedOutputLabels[] = { "", "" }; static const char_T *rt_LoggedOutputBlockNames[] = { "ex_arg_code/Out1", "ex_arg_code/Out2" }; static RTWLogDataTypeConvert rt_RTWLogDataTypeConvert[] = { { 0, SS_SINGLE, SS_SINGLE, 0, 0, 0, 1.0, 0, 0.0 }, { 0, SS_SINGLE, SS_SINGLE, 0, 0, 0, 1.0, 0, 0.0 } }; static RTWLogSignalInfo rt_LoggedOutputSignalInfo[] = { { 2, rt_LoggedOutputWidths, rt_LoggedOutputNumDimensions, rt_LoggedOutputDimensions, rt_LoggedOutputIsVarDims, rt_LoggedCurrentSignalDimensions, rt_LoggedCurrentSignalDimensionsSize, rt_LoggedOutputDataTypeIds, rt_LoggedOutputComplexSignals, (NULL), rt_LoggingPreprocessingFcnPtrs, { rt_LoggedOutputLabels }, (NULL), (NULL), (NULL), { rt_LoggedOutputBlockNames }, { (NULL) }, (NULL), rt_RTWLogDataTypeConvert } }; rtliSetLogYSignalInfo(ex_arg_code_M->rtwLogInfo, rt_LoggedOutputSignalInfo); /* set currSigDims field */ rt_LoggedCurrentSignalDimensions[0] = &rt_LoggedOutputWidths[0]; rt_LoggedCurrentSignalDimensions[1] = &rt_LoggedOutputWidths[1]; } rtliSetLogY(ex_arg_code_M->rtwLogInfo, "yout"); } /* states (dwork) */ (void) memset((void *)&ex_arg_code_DW, 0, sizeof(DW_ex_arg_code_T)); /* external inputs */ ex_arg_code_U.In1 = 0.0F; /* external outputs */ (void)memset(&ex_arg_code_Y, 0, sizeof(ExtY_ex_arg_code_T)); /* Model Initialize function for ModelReference Block: '<Root>/Model' */ ex_arg_code_ref_initialize(rtmGetErrorStatusPointer(ex_arg_code_M), &(ex_arg_code_DW.Model_InstanceData.rtm), &(ex_arg_code_DW.Model_InstanceData.rtdw)); /* Model Initialize function for ModelReference Block: '<Root>/Model1' */ ex_arg_code_ref_initialize(rtmGetErrorStatusPointer(ex_arg_code_M), &(ex_arg_code_DW.Model1_InstanceData.rtm), &(ex_arg_code_DW.Model1_InstanceData.rtdw)); /* Matfile logging */ rt_StartDataLoggingWithStartTime(ex_arg_code_M->rtwLogInfo, 0.0, rtmGetTFinal (ex_arg_code_M), ex_arg_code_M->Timing.stepSize0, (&rtmGetErrorStatus (ex_arg_code_M))); /* SystemInitialize for ModelReference: '<Root>/Model' */ ex_arg_code_ref_Init(&(ex_arg_code_DW.Model_InstanceData.rtdw)); /* SystemInitialize for ModelReference: '<Root>/Model1' */ ex_arg_code_ref_Init(&(ex_arg_code_DW.Model1_InstanceData.rtdw)); } /* Model terminate function */ void ex_arg_code_terminate(void) { /* (no terminate code required) */ }
次の理由により、仮パラメーターはデータ型 real32_T
(single
) を使用します。
ex_arg_code_ref
でブロック パラメーターは内部ルールに基づいてデータ型を決定する。たとえば、Gain ブロック ダイアログ ボックスの [パラメーター属性] タブで、[パラメーターのデータ型] はInherit: Inherit via internal rule
(既定値) に設定されています。この場合、内部ルールは同じデータ型single
を入出力信号として選択します。DataType
プロパティの値がauto
(既定値) に設定されているため、モデル ワークスペース内のモデル引数は、状況依存データ型指定を使用します。この設定により、モデル引数はブロック パラメーターsingle
と同じデータ型を使用します。生成されたコード内の仮パラメーターは、モデル引数
single
と同じデータ型を使用します。
調整可能な引数の値の生成
インスタンス固有の値を生成されたコードに調整可能なグローバル変数として表示されるように Model ブロックで設定できます。この手法を使用すると、各インスタンスのパラメーター値をメモリ内に格納して、コードの実行時に値を調整できます。
最上位モデル ex_arg_code
で、モデル データ エディターの [パラメーター] タブを選択します。
モデル データ エディターを使用して、次の図に従ってモデル引数の値を設定します。
ex_arg_code_ref
モデル ワークスペースの内容をモデル エクスプローラーに表示します。
ex_arg_code_ref
モデル ワークスペースからベース ワークスペースに gainArg
および coeffArg
をコピーします。
名前 gainArg
を gainForInst1
に変更します。名前 coeffArg
を coeffForInst1
に変更します。
gainForInst1 = getVariable(modelWorkspace,'gainArg'); gainForInst1 = copy(gainForInst1); coeffForInst1 = getVariable(modelWorkspace,'coeffArg'); coeffForInst1 = copy(coeffForInst1);
gainForInst1
および coeffForInst1
を gainForInst2
および coeffForInst2
としてコピーします。
gainForInst2 = copy(gainForInst1); coeffForInst2 = copy(coeffForInst1);
ベース ワークスペースのパラメーター オブジェクトの Value
プロパティを使用して、インスタンス固有のパラメーター値を設定します。
gainForInst1.Value = 2.98; coeffForInst1.Value = 0.98; gainForInst2.Value = 3.34; coeffForInst2.Value = 1.11;
それぞれの新しいパラメーター オブジェクトについて、[コード生成] タブで、StorageClass
を ExportedGlobal
に設定します。この設定によって、パラメーター オブジェクトが調整可能なグローバル変数として生成されたコードに表示されるようになります。
gainForInst1.StorageClass = 'ExportedGlobal'; coeffForInst1.StorageClass = 'ExportedGlobal'; gainForInst2.StorageClass = 'ExportedGlobal'; coeffForInst2.StorageClass = 'ExportedGlobal'; instSpecParams = get_param('ex_arg_code/Model','InstanceParameters'); instSpecParams(1).Value = 'coeffForInst1'; instSpecParams(2).Value = 'gainForInst1'; instSpecParams1 = get_param('ex_arg_code/Model1','InstanceParameters'); instSpecParams1(1).Value = 'coeffForInst2'; instSpecParams1(2).Value = 'gainForInst2'; set_param('ex_arg_code/Model','InstanceParameters',instSpecParams); set_param('ex_arg_code/Model1','InstanceParameters',instSpecParams1);
最上位モデルからコードを生成します。
slbuild('ex_arg_code')
### Searching for referenced models in model 'ex_arg_code'. ### Found 1 model references to update. ### Starting serial model reference code generation build. ### Model reference code generation target for ex_arg_code_ref is up to date. ### Starting build procedure for: ex_arg_code ### Successful completion of build procedure for: ex_arg_code Build Summary Top model targets built: Model Action Rebuild Reason ============================================================================ ex_arg_code Code generated and compiled. Generated code was out of date. 1 of 2 models built (1 models already up to date) Build duration: 0h 0m 18.655s
ファイル ex_arg_code.c
は、ベース ワークスペースのパラメーター オブジェクトに対応するグローバル変数を定義します。
file = fullfile('ex_arg_code_grt_rtw','ex_arg_code.c'); coder.example.extractLines(file,'/* Exported block parameters */',... '/* Block states (default storage) */',1,0)
/* Exported block parameters */ real32_T coeffForInst1 = 0.98F; /* Variable: coeffForInst1 * Referenced by: '<Root>/Model' */ real32_T coeffForInst2 = 1.11F; /* Variable: coeffForInst2 * Referenced by: '<Root>/Model1' */ real32_T gainForInst1 = 2.98F; /* Variable: gainForInst1 * Referenced by: '<Root>/Model' */ real32_T gainForInst2 = 3.34F; /* Variable: gainForInst2 * Referenced by: '<Root>/Model1' */
ex_arg_code_ref
の各呼び出しでは、最上位モデルのアルゴリズムはグローバル変数を使用して仮パラメーターの値を設定します。
coder.example.extractLines(file,'/* ModelReference: ''<Root>/Model'' incorporates:',... 'gainForInst2);',1,1)
/* ModelReference: '<Root>/Model' incorporates: * Inport: '<Root>/In1' * Outport: '<Root>/Out1' */ ex_arg_code_ref(&ex_arg_code_U.In1, &ex_arg_code_Y.Out1, coeffForInst1, gainForInst1, &(ex_arg_code_DW.Model_InstanceData.rtdw)); /* ModelReference: '<Root>/Model1' incorporates: * Inport: '<Root>/In1' * Outport: '<Root>/Out2' */ ex_arg_code_ref(&ex_arg_code_U.In1, &ex_arg_code_Y.Out2, coeffForInst2, gainForInst2, &(ex_arg_code_DW.Model1_InstanceData.rtdw)); /* Matfile logging */ rt_UpdateTXYLogVars(ex_arg_code_M->rtwLogInfo, (&ex_arg_code_M->Timing.taskTime0)); /* signal main to stop simulation */ { /* Sample time: [0.2s, 0.0s] */ if ((rtmGetTFinal(ex_arg_code_M)!=-1) && !((rtmGetTFinal(ex_arg_code_M)-ex_arg_code_M->Timing.taskTime0) > ex_arg_code_M->Timing.taskTime0 * (DBL_EPSILON))) { rtmSetErrorStatus(ex_arg_code_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 (!(++ex_arg_code_M->Timing.clockTick0)) { ++ex_arg_code_M->Timing.clockTickH0; } ex_arg_code_M->Timing.taskTime0 = ex_arg_code_M->Timing.clockTick0 * ex_arg_code_M->Timing.stepSize0 + ex_arg_code_M->Timing.clockTickH0 * ex_arg_code_M->Timing.stepSize0 * 4294967296.0; } /* Model initialize function */ void ex_arg_code_initialize(void) { /* Registration code */ /* initialize non-finites */ rt_InitInfAndNaN(sizeof(real_T)); /* initialize real-time model */ (void) memset((void *)ex_arg_code_M, 0, sizeof(RT_MODEL_ex_arg_code_T)); rtmSetTFinal(ex_arg_code_M, 10.0); ex_arg_code_M->Timing.stepSize0 = 0.2; /* Setup for data logging */ { static RTWLogInfo rt_DataLoggingInfo; rt_DataLoggingInfo.loggingInterval = (NULL); ex_arg_code_M->rtwLogInfo = &rt_DataLoggingInfo; } /* Setup for data logging */ { rtliSetLogXSignalInfo(ex_arg_code_M->rtwLogInfo, (NULL)); rtliSetLogXSignalPtrs(ex_arg_code_M->rtwLogInfo, (NULL)); rtliSetLogT(ex_arg_code_M->rtwLogInfo, "tout"); rtliSetLogX(ex_arg_code_M->rtwLogInfo, ""); rtliSetLogXFinal(ex_arg_code_M->rtwLogInfo, ""); rtliSetLogVarNameModifier(ex_arg_code_M->rtwLogInfo, "rt_"); rtliSetLogFormat(ex_arg_code_M->rtwLogInfo, 0); rtliSetLogMaxRows(ex_arg_code_M->rtwLogInfo, 0); rtliSetLogDecimation(ex_arg_code_M->rtwLogInfo, 1); /* * Set pointers to the data and signal info for each output */ { static void * rt_LoggedOutputSignalPtrs[] = { &ex_arg_code_Y.Out1, &ex_arg_code_Y.Out2 }; rtliSetLogYSignalPtrs(ex_arg_code_M->rtwLogInfo, ((LogSignalPtrsType) rt_LoggedOutputSignalPtrs)); } { static int_T rt_LoggedOutputWidths[] = { 1, 1 }; static int_T rt_LoggedOutputNumDimensions[] = { 1, 1 }; static int_T rt_LoggedOutputDimensions[] = { 1, 1 }; static boolean_T rt_LoggedOutputIsVarDims[] = { 0, 0 }; static void* rt_LoggedCurrentSignalDimensions[] = { (NULL), (NULL) }; static int_T rt_LoggedCurrentSignalDimensionsSize[] = { 4, 4 }; static BuiltInDTypeId rt_LoggedOutputDataTypeIds[] = { SS_SINGLE, SS_SINGLE }; static int_T rt_LoggedOutputComplexSignals[] = { 0, 0 }; static RTWPreprocessingFcnPtr rt_LoggingPreprocessingFcnPtrs[] = { (NULL), (NULL) }; static const char_T *rt_LoggedOutputLabels[] = { "", "" }; static const char_T *rt_LoggedOutputBlockNames[] = { "ex_arg_code/Out1", "ex_arg_code/Out2" }; static RTWLogDataTypeConvert rt_RTWLogDataTypeConvert[] = { { 0, SS_SINGLE, SS_SINGLE, 0, 0, 0, 1.0, 0, 0.0 }, { 0, SS_SINGLE, SS_SINGLE, 0, 0, 0, 1.0, 0, 0.0 } }; static RTWLogSignalInfo rt_LoggedOutputSignalInfo[] = { { 2, rt_LoggedOutputWidths, rt_LoggedOutputNumDimensions, rt_LoggedOutputDimensions, rt_LoggedOutputIsVarDims, rt_LoggedCurrentSignalDimensions, rt_LoggedCurrentSignalDimensionsSize, rt_LoggedOutputDataTypeIds, rt_LoggedOutputComplexSignals, (NULL), rt_LoggingPreprocessingFcnPtrs, { rt_LoggedOutputLabels }, (NULL), (NULL), (NULL), { rt_LoggedOutputBlockNames }, { (NULL) }, (NULL), rt_RTWLogDataTypeConvert } }; rtliSetLogYSignalInfo(ex_arg_code_M->rtwLogInfo, rt_LoggedOutputSignalInfo); /* set currSigDims field */ rt_LoggedCurrentSignalDimensions[0] = &rt_LoggedOutputWidths[0]; rt_LoggedCurrentSignalDimensions[1] = &rt_LoggedOutputWidths[1]; } rtliSetLogY(ex_arg_code_M->rtwLogInfo, "yout"); } /* states (dwork) */ (void) memset((void *)&ex_arg_code_DW, 0, sizeof(DW_ex_arg_code_T)); /* external inputs */ ex_arg_code_U.In1 = 0.0F; /* external outputs */ (void)memset(&ex_arg_code_Y, 0, sizeof(ExtY_ex_arg_code_T)); /* Model Initialize function for ModelReference Block: '<Root>/Model' */ ex_arg_code_ref_initialize(rtmGetErrorStatusPointer(ex_arg_code_M), &(ex_arg_code_DW.Model_InstanceData.rtm), &(ex_arg_code_DW.Model_InstanceData.rtdw)); /* Model Initialize function for ModelReference Block: '<Root>/Model1' */ ex_arg_code_ref_initialize(rtmGetErrorStatusPointer(ex_arg_code_M), &(ex_arg_code_DW.Model1_InstanceData.rtm), &(ex_arg_code_DW.Model1_InstanceData.rtdw)); /* Matfile logging */ rt_StartDataLoggingWithStartTime(ex_arg_code_M->rtwLogInfo, 0.0, rtmGetTFinal (ex_arg_code_M), ex_arg_code_M->Timing.stepSize0, (&rtmGetErrorStatus (ex_arg_code_M))); /* SystemInitialize for ModelReference: '<Root>/Model' */ ex_arg_code_ref_Init(&(ex_arg_code_DW.Model_InstanceData.rtdw)); /* SystemInitialize for ModelReference: '<Root>/Model1' */ ex_arg_code_ref_Init(&(ex_arg_code_DW.Model1_InstanceData.rtdw)); } /* Model terminate function */ void ex_arg_code_terminate(void) { /* (no terminate code required) */ }
生成されたコードのグローバル変数はデータ型 real32_T
(single
) を使用します。
DataType
プロパティがauto
(既定値) に設定されているため、ベース ワークスペースのパラメーター オブジェクトは状況依存データ型指定を使用します。この設定により、ベース ワークスペースのパラメーター オブジェクトはモデル引数と同じデータ型single
を使用します。生成されたコードのグローバル変数は、ベース ワークスペースのパラメーター オブジェクトと同じデータ型を使用します。
複数のモデル引数を単一の構造体にグループ化
モデル エクスプローラーを使用して、ex_arg_code_ref
モデル ワークスペースからベース ワークスペースに gainArg
および coeffArg
をコピーします。
temp = getVariable(modelWorkspace,'gainArg'); gainArg = copy(temp); temp = getVariable(modelWorkspace,'coeffArg'); coeffArg = copy(temp);
コマンド プロンプトで、これらの 2 つのパラメーター オブジェクトを 1 つの構造体 structArg
にコピーします。
structArg = Simulink.Parameter(struct('gain',gainArg.Value,... 'coeff',coeffArg.Value));
モデル エクスプローラーを使用して、structArg
をモデル ワークスペースに移動します。
assignin(modelWorkspace,'structArg',copy(structArg)); clear structArg gainArg coeffArg
[コンテンツ] ペインで、structArg
を唯一のモデル引数として設定します。
set_param('ex_arg_code_ref','ParameterArgumentNames','structArg')
ex_arg_code_ref
モデルで、モデル データ エディターの [パラメーター] タブを選択します。
モデル データ エディターを使用して、[ゲイン] パラメーターの値を structArg.gain
に設定し、[分子係数] パラメーターの値を structArg.coeff
に設定します。モデルを保存します。
set_param('ex_arg_code_ref/Gain','Gain','structArg.gain') set_param('ex_arg_code_ref/Discrete Filter',... 'Numerator','structArg.coeff') save_system('ex_arg_code_ref')
コマンド プロンプトで、ベース ワークスペースの 4 つのパラメーター オブジェクトを 2 つの構造体に結合します。各構造体には、ex_arg_code_ref
の 1 つのインスタンスのパラメーター値を格納します。
structForInst1 = Simulink.Parameter(struct('gain',gainForInst1.Value,... 'coeff',coeffForInst1.Value)); structForInst2 = Simulink.Parameter(struct('gain',gainForInst2.Value,... 'coeff',coeffForInst2.Value));
最上位モデル ex_arg_code で、モデル データ エディターを使用して、次の図に従って引数値を設定します。
instSpecParams = get_param('ex_arg_code/Model','InstanceParameters'); instSpecParams(1).Value = 'structForInst1'; instSpecParams1 = get_param('ex_arg_code/Model1','InstanceParameters'); instSpecParams1(1).Value = 'structForInst2'; set_param('ex_arg_code/Model','InstanceParameters',instSpecParams); set_param('ex_arg_code/Model1','InstanceParameters',instSpecParams1);
[追加情報の表示/更新] ボタンをクリックします。
新しいパラメーター オブジェクト structForInst1
および structForInst2
に対して、モデル エクスプローラーを使用してストレージ クラス ExportedGlobal
を適用します。
structForInst1.StorageClass = 'ExportedGlobal'; structForInst2.StorageClass = 'ExportedGlobal';
Simulink.Bus
オブジェクトを作成するには、コマンド プロンプトで関数 Simulink.Bus.createObject
を使用します。オブジェクト内の要素の階層は、構造体フィールドの階層と一致します。オブジェクトの既定の名前は slBus1
です。
Simulink.Bus.createObject(structForInst1.Value);
バス オブジェクトをコピーして名前を myParamStructType
に変更します。
myParamStructType = copy(slBus1);
ex_arg_code
のモデル データ エディターで、[データ型] 列を使用して、structForInst1
と structForInst2
のデータ型を Bus: myParamStructType
に設定します。
structForInst1.DataType = 'Bus: myParamStructType'; structForInst2.DataType = 'Bus: myParamStructType';
temp = getVariable(modelWorkspace,'structArg'); temp = copy(temp); temp.DataType = 'Bus: myParamStructType'; assignin(modelWorkspace,'structArg',copy(temp));
ex_arg_code_ref
モデルを保存します。
save_system('ex_arg_code_ref')
構造体を使用してパラメーター値をグループ化する場合、構造体のフィールド (たとえば、structForInst1
のフィールド) のデータ型を制御するために状況依存データ型指定を利用することはできません。ただし、バス オブジェクトのプロパティを使用してフィールドのデータ型を制御することはできます。
コマンド プロンプトで、バス オブジェクトの要素のデータ型を single
に設定します。構造体の対応するフィールド (structForInst1
および structArg
など) は、同じデータ型を使用します。
myParamStructType.Elements(1).DataType = 'single'; myParamStructType.Elements(2).DataType = 'single';
最上位モデル ex_arg_code
からコードを生成します。
slbuild('ex_arg_code')
### Searching for referenced models in model 'ex_arg_code'. ### Found 1 model references to update. ### Starting serial model reference code generation build. ### Successfully updated the model reference code generation target for: ex_arg_code_ref ### Starting build procedure for: ex_arg_code ### Successful completion of build procedure for: ex_arg_code Build Summary Code generation targets built: Model Action Rebuild Reason ========================================================================================== ex_arg_code_ref Code generated and compiled. Model or library ex_arg_code_ref changed. Top model targets built: Model Action Rebuild Reason ============================================================================ ex_arg_code Code generated and compiled. Referenced models were updated. 2 of 2 models built (0 models already up to date) Build duration: 0h 0m 28.8s
ファイル ex_arg_code_types.h
では、Simulink.Bus
オブジェクトに対応付けられている構造体型 myParamStructType
を定義します。
file = fullfile('ex_arg_code_grt_rtw','ex_arg_code_types.h'); coder.example.extractLines(file,'typedef struct {','} myParamStructType;',1,1)
typedef struct { real32_T gain; real32_T coeff; } myParamStructType;
ファイル ex_arg_code_ref.c
の、参照モデルのエントリポイント関数には、モデル引数 structArg
に対応する仮パラメーター rtp_structArg
があります。
file = fullfile('slprj','grt','ex_arg_code_ref','ex_arg_code_ref.c'); coder.example.extractLines(file,'/* Output and update for referenced model:',... '*rtp_structArg)',1,1)
/* Output and update for referenced model: 'ex_arg_code_ref' */ void ex_arg_code_ref(const real32_T *rtu_In1, real32_T *rty_Out1, const myParamStructType *rtp_structArg, DW_ex_arg_code_ref_f_T *localDW) { real32_T rtb_Sum; /* Sum: '<Root>/Sum' incorporates: * UnitDelay: '<Root>/Unit Delay' */ rtb_Sum = *rtu_In1 + localDW->UnitDelay_DSTATE; /* Gain: '<Root>/Gain' */ rtb_Sum *= rtp_structArg->gain; /* DiscreteFilter: '<Root>/Discrete Filter' */ localDW->DiscreteFilter_tmp = rtb_Sum - 0.5F * localDW->DiscreteFilter_states; *rty_Out1 = rtp_structArg->coeff * localDW->DiscreteFilter_tmp; /* Update for UnitDelay: '<Root>/Unit Delay' */ localDW->UnitDelay_DSTATE = rtb_Sum; /* Update for DiscreteFilter: '<Root>/Discrete Filter' */ localDW->DiscreteFilter_states = localDW->DiscreteFilter_tmp; } /* Model initialize function */ void ex_arg_code_ref_initialize(const char_T **rt_errorStatus, RT_MODEL_ex_arg_code_ref_T *const ex_arg_code_ref_M, DW_ex_arg_code_ref_f_T *localDW) { /* Registration code */ /* initialize error status */ rtmSetErrorStatusPointer(ex_arg_code_ref_M, rt_errorStatus); /* states (dwork) */ (void) memset((void *)localDW, 0, sizeof(DW_ex_arg_code_ref_f_T)); }
ファイル ex_arg_code.c
は、ベース ワークスペースのパラメーター オブジェクトに対応するグローバル構造体変数を定義します。
file = fullfile('ex_arg_code_grt_rtw','ex_arg_code.c'); coder.example.extractLines(file,'/* Exported block parameters */',... '/* Block states (default storage) */',1,0)
/* Exported block parameters */ myParamStructType structForInst1 = { 2.98F, 0.98F } ; /* Variable: structForInst1 * Referenced by: '<Root>/Model' */ myParamStructType structForInst2 = { 3.34F, 1.11F } ; /* Variable: structForInst2 * Referenced by: '<Root>/Model1' */
ファイル ex_arg_code.c
の最上位モデルのアルゴリズムは、構造体変数のアドレスを参照モデルのエントリポイント関数に渡します。
file = fullfile('ex_arg_code_grt_rtw','ex_arg_code.c'); coder.example.extractLines(file,'/* ModelReference: ''<Root>/Model'' incorporates:',... '&structForInst2);',1,1)
/* ModelReference: '<Root>/Model' incorporates: * Inport: '<Root>/In1' * Outport: '<Root>/Out1' */ ex_arg_code_ref(&ex_arg_code_U.In1, &ex_arg_code_Y.Out1, &structForInst1, &(ex_arg_code_DW.Model_InstanceData.rtdw)); /* ModelReference: '<Root>/Model1' incorporates: * Inport: '<Root>/In1' * Outport: '<Root>/Out2' */ ex_arg_code_ref(&ex_arg_code_U.In1, &ex_arg_code_Y.Out2, &structForInst2, &(ex_arg_code_DW.Model1_InstanceData.rtdw)); /* Matfile logging */ rt_UpdateTXYLogVars(ex_arg_code_M->rtwLogInfo, (&ex_arg_code_M->Timing.taskTime0)); /* signal main to stop simulation */ { /* Sample time: [0.2s, 0.0s] */ if ((rtmGetTFinal(ex_arg_code_M)!=-1) && !((rtmGetTFinal(ex_arg_code_M)-ex_arg_code_M->Timing.taskTime0) > ex_arg_code_M->Timing.taskTime0 * (DBL_EPSILON))) { rtmSetErrorStatus(ex_arg_code_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 (!(++ex_arg_code_M->Timing.clockTick0)) { ++ex_arg_code_M->Timing.clockTickH0; } ex_arg_code_M->Timing.taskTime0 = ex_arg_code_M->Timing.clockTick0 * ex_arg_code_M->Timing.stepSize0 + ex_arg_code_M->Timing.clockTickH0 * ex_arg_code_M->Timing.stepSize0 * 4294967296.0; } /* Model initialize function */ void ex_arg_code_initialize(void) { /* Registration code */ /* initialize non-finites */ rt_InitInfAndNaN(sizeof(real_T)); /* initialize real-time model */ (void) memset((void *)ex_arg_code_M, 0, sizeof(RT_MODEL_ex_arg_code_T)); rtmSetTFinal(ex_arg_code_M, 10.0); ex_arg_code_M->Timing.stepSize0 = 0.2; /* Setup for data logging */ { static RTWLogInfo rt_DataLoggingInfo; rt_DataLoggingInfo.loggingInterval = (NULL); ex_arg_code_M->rtwLogInfo = &rt_DataLoggingInfo; } /* Setup for data logging */ { rtliSetLogXSignalInfo(ex_arg_code_M->rtwLogInfo, (NULL)); rtliSetLogXSignalPtrs(ex_arg_code_M->rtwLogInfo, (NULL)); rtliSetLogT(ex_arg_code_M->rtwLogInfo, "tout"); rtliSetLogX(ex_arg_code_M->rtwLogInfo, ""); rtliSetLogXFinal(ex_arg_code_M->rtwLogInfo, ""); rtliSetLogVarNameModifier(ex_arg_code_M->rtwLogInfo, "rt_"); rtliSetLogFormat(ex_arg_code_M->rtwLogInfo, 0); rtliSetLogMaxRows(ex_arg_code_M->rtwLogInfo, 0); rtliSetLogDecimation(ex_arg_code_M->rtwLogInfo, 1); /* * Set pointers to the data and signal info for each output */ { static void * rt_LoggedOutputSignalPtrs[] = { &ex_arg_code_Y.Out1, &ex_arg_code_Y.Out2 }; rtliSetLogYSignalPtrs(ex_arg_code_M->rtwLogInfo, ((LogSignalPtrsType) rt_LoggedOutputSignalPtrs)); } { static int_T rt_LoggedOutputWidths[] = { 1, 1 }; static int_T rt_LoggedOutputNumDimensions[] = { 1, 1 }; static int_T rt_LoggedOutputDimensions[] = { 1, 1 }; static boolean_T rt_LoggedOutputIsVarDims[] = { 0, 0 }; static void* rt_LoggedCurrentSignalDimensions[] = { (NULL), (NULL) }; static int_T rt_LoggedCurrentSignalDimensionsSize[] = { 4, 4 }; static BuiltInDTypeId rt_LoggedOutputDataTypeIds[] = { SS_SINGLE, SS_SINGLE }; static int_T rt_LoggedOutputComplexSignals[] = { 0, 0 }; static RTWPreprocessingFcnPtr rt_LoggingPreprocessingFcnPtrs[] = { (NULL), (NULL) }; static const char_T *rt_LoggedOutputLabels[] = { "", "" }; static const char_T *rt_LoggedOutputBlockNames[] = { "ex_arg_code/Out1", "ex_arg_code/Out2" }; static RTWLogDataTypeConvert rt_RTWLogDataTypeConvert[] = { { 0, SS_SINGLE, SS_SINGLE, 0, 0, 0, 1.0, 0, 0.0 }, { 0, SS_SINGLE, SS_SINGLE, 0, 0, 0, 1.0, 0, 0.0 } }; static RTWLogSignalInfo rt_LoggedOutputSignalInfo[] = { { 2, rt_LoggedOutputWidths, rt_LoggedOutputNumDimensions, rt_LoggedOutputDimensions, rt_LoggedOutputIsVarDims, rt_LoggedCurrentSignalDimensions, rt_LoggedCurrentSignalDimensionsSize, rt_LoggedOutputDataTypeIds, rt_LoggedOutputComplexSignals, (NULL), rt_LoggingPreprocessingFcnPtrs, { rt_LoggedOutputLabels }, (NULL), (NULL), (NULL), { rt_LoggedOutputBlockNames }, { (NULL) }, (NULL), rt_RTWLogDataTypeConvert } }; rtliSetLogYSignalInfo(ex_arg_code_M->rtwLogInfo, rt_LoggedOutputSignalInfo); /* set currSigDims field */ rt_LoggedCurrentSignalDimensions[0] = &rt_LoggedOutputWidths[0]; rt_LoggedCurrentSignalDimensions[1] = &rt_LoggedOutputWidths[1]; } rtliSetLogY(ex_arg_code_M->rtwLogInfo, "yout"); } /* states (dwork) */ (void) memset((void *)&ex_arg_code_DW, 0, sizeof(DW_ex_arg_code_T)); /* external inputs */ ex_arg_code_U.In1 = 0.0F; /* external outputs */ (void)memset(&ex_arg_code_Y, 0, sizeof(ExtY_ex_arg_code_T)); /* Model Initialize function for ModelReference Block: '<Root>/Model' */ ex_arg_code_ref_initialize(rtmGetErrorStatusPointer(ex_arg_code_M), &(ex_arg_code_DW.Model_InstanceData.rtm), &(ex_arg_code_DW.Model_InstanceData.rtdw)); /* Model Initialize function for ModelReference Block: '<Root>/Model1' */ ex_arg_code_ref_initialize(rtmGetErrorStatusPointer(ex_arg_code_M), &(ex_arg_code_DW.Model1_InstanceData.rtm), &(ex_arg_code_DW.Model1_InstanceData.rtdw)); /* Matfile logging */ rt_StartDataLoggingWithStartTime(ex_arg_code_M->rtwLogInfo, 0.0, rtmGetTFinal (ex_arg_code_M), ex_arg_code_M->Timing.stepSize0, (&rtmGetErrorStatus (ex_arg_code_M))); /* SystemInitialize for ModelReference: '<Root>/Model' */ ex_arg_code_ref_Init(&(ex_arg_code_DW.Model_InstanceData.rtdw)); /* SystemInitialize for ModelReference: '<Root>/Model1' */ ex_arg_code_ref_Init(&(ex_arg_code_DW.Model1_InstanceData.rtdw)); } /* Model terminate function */ void ex_arg_code_terminate(void) { /* (no terminate code required) */ }
モデル引数および引数の値のデータ型の制御
モデル引数を使用すると、以下にデータ型を適用できます。
引数を使用するブロック パラメーター (Discrete ライブラリ内のブロックなどの特定のブロックの場合)。
参照モデル ワークスペース内の引数。
Model ブロックで指定する引数の値。
不必要な型変換および C シフトを除去することで効率的なコードを生成するには、データ型を一致させるために継承および状況依存データ型指定の使用を検討してください。
モデル ワークスペースで、データ型が
double
の MATLAB® 変数またはDataType
プロパティがauto
に設定されているパラメーター オブジェクトを使用します。この場合、変数またはオブジェクトはブロック パラメーターと同じデータ型を使用します。Model ブロックで引数の値を設定する場合、状況依存データ型指定を利用します。引数の値を指定するには、データ型をもたない値を使用します。
15.23
などの数値リテラル。single(15.23)
などの型付き式を使用しないでください。データ型が
double
の MATLAB 変数。DataType
プロパティがauto
に設定されているSimulink.Parameter
オブジェクト。
このような場合、数値、変数またはオブジェクトは、参照モデル ワークスペースのモデル引数と同じデータ型を使用します。状況依存データ型指定を使用するようにモデル引数も設定する場合は、ブロック パラメーターの型を指定するだけでブロック パラメーター、引数および引数の値のデータ型を制御できます。
パラメーターのデータ型の制御の基本的な情報については、生成されたコードにおけるパラメーターのデータ型を参照してください。
異なるデータ型のコンテキストでのモデル引数の使用
モデル引数を使用して複数のブロック パラメーターの値を設定する場合、そしてブロック パラメーターのデータ型が異なる場合は、モデル ワークスペースの引数には状況依存データ型指定 (double
または auto
) を使用できません。その引数にはデータ型を明示的に指定しなければなりません。たとえば、モデル ワークスペースの引数がパラメーター オブジェクト (Simulink.Parameter
など) である場合、DataType
プロパティには auto
以外の値を設定します。この状況の詳細については、異なるデータ型のコンテキストでパラメーター データを再利用を参照してください。
この場合、Model ブロックで指定する引数の値のデータ型を制御するために、状況依存データ型指定を引き続き利用できます。各引数の値は、モデル ワークスペースの対応する引数に対して指定するデータ型を使用します。