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

レート変換の処理

レート変換

モデル内には次の 2 つの周期的なサンプル レート変換が存在します。

  • 低速のブロックを駆動する高速のブロック

  • 高速のブロックを駆動する低速のブロック

以下の節では、オフセットがゼロのみの周期的なサンプル時間のモデルについて説明します。また、非同期タスクに関連するマルチレート モデルについても検討します。非同期のマルチタスクのコード生成の詳細は、非同期のサポートを参照してください。

マルチタスク システムと疑似マルチタスク システムでは、サンプルレートが異なると、ブロックが誤った順序で実行される場合があります。算出されたデータでエラーが発生しないようにするには、このようなレートの変換時にモデルの実行を制御しなければなりません。高速ブロックと低速ブロックを接続する場合、ユーザーまたは Simulink® エンジンは、これらのブロック間に Rate Transition ブロックを追加しなければなりません。次の図では、高速から低速への遷移を示します。

次の図では、低速から高速への遷移を示します。

メモ

Rate Transition ブロックは、Unit Delay ブロック (低速から高速への遷移) および Zero-Order Hold ブロック (高速から低速への遷移) の機能のスーパーセットをもつブロックですが、これらのブロックではなく Rate Transition ブロックを使用しなければなりません。

データ転送時の問題

Rate Transition ブロックは、異なるレートで実行されているブロック間のデータ転送に関連するデータの整合性と確定性の問題を処理します。

  • データの整合性:データの整合性の問題は、ブロックへの入力がそのブロックの実行時に変更されると発生します。その原因は、プリエンプションである場合があります。

    次のシナリオを検討します。

    • 高速ブロックから低速ブロックに値が入力されます。

    • 低速ブロックは高速ブロックからの入力値 V1 を読み取り、この値を使用して計算を開始します。

    • この計算は別の高速ブロックの実行によってプリエンプトされ、新しい出力値 V2 が計算されます。

    • このとき、データの整合性の問題が発生します。すなわち、低速ブロックが実行を再開したとき、"新しい" 入力値 V2 を使用して計算が継続されます。

    このようなデータ転送は "非保護" データ転送と呼ばれます。リアル タイムでのより高速のブロックからより低速のブロックへの遷移は、非保護データ転送を示しています。

    "保護されている" データ転送の場合、高速ブロックの出力 V1 は、低速ブロックの実行が終了するまで保持されます。

  • "確定的" データ転送と "非確定的" データ転送:"確定的" データ転送では、データ転送のタイミングは、ブロックのサンプル レートによって決定されるため、完全に予測可能です。

    "非確定的" データ転送のタイミングは、データの利用、ブロックのサンプル レート、および受信ブロックが駆動ブロックに対して実行を開始するタイミングに依存します。

Rate Transition ブロックを使用すると、アプリケーションのデータ転送を保護してこれらを確定的にすることができます。これらはほとんどのアプリケーションにおいて望まれる特性です。ただし、Rate Transition ブロックは、レイテンシをより低く抑えるためにデータの整合性と確定性を妥協できるようにする柔軟なオプションをサポートしています。次節では、このオプションについて簡単に説明します。

データ転送の仮定

タスク間のデータ転送を処理する場合、コード ジェネレーターは以下の内容を仮定します。

  • 1 つの読み取りタスクと 1 つの書き込みタスクの間でデータ遷移が発生する。

  • バイト単位の変数の読み取りと書き込みはアトミックである。

  • データの遷移中に 2 つのタスクが対話した場合、一方のタスクがもう一方のタスクをプリエンプトする場合がある。

  • 周期的タスクの場合、速いレートのタスクの優先順位は遅いレートのタスクよりも高くなる。すなわち、速いレートのタスクは遅いレートのタスクをプリエンプトする。

  • すべてのタスクは 1 つのプロセッサ上で実行される。タイム スライスは許可されない。

  • プロセスはクラッシュまたは再起動しない (特にデータがタスク間を転送されているとき)。

Rate Transition ブロックのオプション

Rate Transition ブロックの複数のパラメーターは、以下で説明するように、リアルタイム実行のコード生成での使用に関連付けられています。ブロックの詳細な説明は、Rate Transition を参照してください。

Rate Transition ブロックは、周期的で (高速から低速および低速から高速)、非同期的な遷移を処理します。Rate Transition ブロックは、サンプル レートが異なる 2 つのブロック間に挿入されると、遷移のタイプの入力および出力のサンプル レートを自動的に構成します。すなわち、遷移が低速から高速への遷移か、高速から低速への遷移かどうか (非同期タスクの場合は、低速から高速への優先度か、高速から低速への優先度かどうか) を指定する必要がありません。

Rate Transition ブロックの設定時に行わなければならない重大な決断は、2 つのレート間で使用するデータ転送メカニズムの選択です。これは、安全性、メモリ使用量、およびパフォーマンスを考慮して選択します。次の図では、Rate Transition ブロック パラメーター ダイアログ ボックスの 2 つのオプションを使用して、データ転送の仕組みを制御しています。

  • データ転送中の整合性を確保:このパラメーターを選択する場合、レート間で転送されたデータの整合性が維持されます (データ転送が保護されます)。このパラメーターをオフにすると、データの整合性が維持されない可能性があります (データ転送は保護されません)。既定の設定では、パラメーター [データ転送中の整合性を確保] は選択されています。

  • 確定的にデータ転送を確保 (最大遅延):このパラメーターは、オフセットがゼロで、お互いが倍数である高速および低速レートの周期的タスクについて、サポートされます。このパラメーターは、データ転送が保護されている場合に選択します ([データ転送中の整合性を確保] が選択されている場合)。このパラメーターがオフの場合、Rate Transition ブロックは、Zero-Order Hold ブロック (高速から低速への遷移の場合) または Unit Delay ブロック (低速から高速への遷移の場合) と同様に動作します。Rate Transition ブロックは、完全に予測可能な方法で、データ転送のタイミングを制御します。このパラメーターがオフの場合、データ転送は非確定的になります。既定の設定では、[確定的にデータ転送を確保 (最大遅延)] は、オフセットがゼロの周期的なレート間の遷移の場合、選択されています。非同期遷移の場合、このオプションは選択できません。

Rate Transition ブロックでは、データ転送について、次の 3 つのモードの操作が可能です。安全性のレベル順では、次のとおりになります。

  • 保護/確定的 (既定):最も安全性が高いモードです。このモードの欠点は、低速から高速への周期的レートの遷移では、システムで確実にレイテンシが発生することです。この場合、Rate Transition ブロックが原因で発生したレイテンシは、低速のタスクの 1 サンプル期間です。高速から低速への周期的レートの遷移では、Rate Transition ブロックが原因でさらにレイテンシが発生することはありません。

  • 保護/非確定的:このモードでは、低速から高速への周期的レートの遷移では、データの整合性は、レート間で転送されたダブルバッファリング データによって保護されます。高速から低速への周期的レートの遷移では、セマフォ フラグが使用されます。Rate Transition ブロックからの下流のブロックでは、Rate Transition ブロックを駆動するブロックからの使用可能な最後のデータが使用されます。最大レイテンシは、高速タスクの 1 サンプル期間以下になります。

    このモードの欠点は、タイミングが非確定的であることです。このモードの利点はそのレイテンシの低さです。

  • 非保護/非確定的:このモードは重要な目的には使用しないようにしてください。このモードのレイテンシは [保護/非確定的] モードと同じですが、ダブルバッファリングとセマフォが不要であるため、メモリ必要量が少なくなります。すなわち、Rate Transition ブロックは、このモードでは、信号を渡すだけで、レート変換が存在することを知らせるためにのみ存在します (また、生成コードによって算出された答えが不正確な場合もあります)。ただし、このモードをセットすると、コードの量は最も少なくなります。

    メモ:

    非保護モードでは ([データ転送中の整合性を確保] オプションが選択されている場合)、Rate Transition ブロックは、モデル内にレート変換が存在できるようにするだけです。

Rate Transition ブロックと連続時間

Rate Transition ブロックの出力端子のサンプル時間は、離散か、マイナー タイム ステップで固定されます。すなわち、Rate Transition ブロックは、その接続先ブロックから連続サンプル時間を継承すると、継承したサンプル時間をマイナー タイム ステップで固定された時間として処理します。したがって、Rate Transition ブロックの出力関数は、メジャー タイム ステップでのみ実行されます。接続先ブロックのサンプル時間が連続の場合、Rate Transition ブロックの出力サンプル時間は基本レートのサンプル時間 (固定ステップ ソルバーの場合) か、ゼロ次ホールド連続サンプル時間 (可変ステップ ソルバーの場合) になります。

自動レート変換

Simulink エンジンは、ブロック線図の更新時にマルチタスク モデルで一致しないレート変換を検出し、自動的に Rate Transition ブロックを挿入して、これを処理します。これを有効にするには、モデル コンフィギュレーション パラメーター [データ転送に対するレート変換を自動的に取り扱う] を選択します。既定の設定では、このパラメーターはオフです。このパラメーターを選択すると、以下の処理が行われます。

  • Simulink は、周期的なサンプル時間と非同期タスクとの間の遷移を処理します。

  • Simulink は、非表示の Rate Transition ブロックをブロック線図に挿入します。

  • コード ジェネレーターは自動で挿入された Rate Transition ブロックのコードを生成します。このコードは、手動で挿入された Rate Transition ブロック用に生成されたコードと同じです。

  • 自動で挿入された Rate Transition ブロックは、周期的タスクおよび非同期タスクについて保護されたモードで動作します。この動作は変更できません。周期的タスクの場合、自動で挿入された Rate Transition ブロックは、モデル コンフィギュレーション パラメーター [確定的なデータ転送] で指定した確定レベルで動作します。既定の設定は [可能な限り] で、整数の倍数で関連付けられた周期的なサンプル時間のデータ転送の確定性が実現されます。詳細は、データ転送の確定性 (Simulink)を参照してください。他のモードを使用した場合は、Rate Transition ブロックを挿入して、そのモードを手動で設定しなければなりません。

たとえば、以下のモデル SineWave2 ではサンプル時間は 2、SineWave3 ではサンプル時間は 3 です。

モデル コンフィギュレーション パラメーター [データ転送に対するレート変換を自動的に取り扱う] を選択すると、Simulink は各 Sine Wave ブロックと Product ブロック間に Rate Transition ブロックを挿入します。挿入されたブロックには、Sine Wave ブロックのサンプル時間を調整するパラメーター値があります。

モデル内の入力端子と出力端子のデータ サンプル レートが互いに倍数でない場合、Simulink は、サンプル レートが 2 つのレートの最大公約数 (GCD) となる Rate Transition ブロックを挿入します。モデル内の他のブロックにこの新しいレートが含まれていない場合、シミュレーション中にエラーが発生します。この場合は、Rate Transition ブロックを手動で挿入しなければなりません。

挿入された Rate Transition ブロックの可視化

モデル コンフィギュレーション パラメーター [データ転送に対するレート変換を自動的に取り扱う] を選択すると、Simulink は一致しない遷移速度をもつパス間に Rate Transition ブロックを挿入します。これらのブロックは既定では非表示です。挿入されたブロックを可視化するには、ブロック線図を更新します。バッジ ラベルがモデルに表示され、コンパイル段階で Simulink によって Rate Transition ブロックが挿入された位置を示します。たとえば、このモデルでは、モデルのコンパイル時に 3 つの Rate Transition ブロックが、2 つの Sine Wave ブロックとマルチプレクサーおよび積分器との間に挿入されました。ZOH バッチ ラベルと DbBuf バッチ ラベルはこれらのブロックを示します。

バッチ ラベルは表示または非表示にできます。[デバッグ] タブを開きます。[情報のオーバーレイ]、[サンプル時間] ギャラリーの [診断] セクションで、[非表示の Rate Transition ブロック インジケーター] を選択またはクリアします。

非表示の Rate Transition ブロックを設定してブロックが表示されるようにするには、バッチ ラベルを右クリックし、[Rate Transition ブロックの挿入] をクリックします。

非表示の Rate Transition ブロックを表示すると、以下のことが可能です。

  • 挿入された Rate Transition ブロックのタイプとモデル内でのブロックの場所を確認できます。

  • ブロック パラメーター [初期条件] を設定できます。

  • レート転送のブロック パラメーター設定を変更できます。

ブロック線図を更新して、モデルへの変更を検証します。

挿入された Rate Transition ブロックの表示は、以下との互換性がありません。

  • 同時実行環境

  • エクスポート関数モデル

Rate Transition ブロックのタイプの詳細は、Rate Transition を参照してください。

周期的なサンプル レート変換

以下の節では、周期的なサンプル レート変換において、Rate Transition ブロックが必須となる場合について説明します。これらの節の説明とタイミング図は、Rate Transition ブロックが既定の設定 (保護/確定的) モードで使用されているという前提に基づいています。モデル コンフィギュレーション パラメーター [データ転送中の整合性を確保][確定的にデータ転送を確保 (最大遅延)] が選択されます。これらの設定は、自動で挿入された Rate Transition ブロックで使用されます。

Simulink モデルでのより高速のブロックからより低速のブロックへの遷移

より高速のブロックによって、直達をもつより低速のブロックが駆動されるモデルでは、より高速のブロックの出力が最初に計算されます。より低速のブロックが実行されないシミュレーション間隔では、実行対象のブロックが少なくなるためシミュレーションがより高速に進行します。次の図はこの状況を示します。

Simulink シミュレーションは、リアル タイムで実行されないため、リアルタイムの制約によって制限されません。シミュレーションは、タスクでシミュレーション フローを完了する必要がある場合、待機するか、先に進みます。サンプル時間の実際の時間間隔はさまざまです。

リアル タイムでのより高速のブロックからより低速のブロックへの遷移

より高速のブロックがより低速のブロックを駆動するモデルでは、より低速のブロックの実行がより高速のブロックの 1 実行時間を超える可能性があることを考慮しなければなりません。すなわち、より高速のブロックの出力は、より低速のブロックの出力の計算が終了する前に変更される可能性があります。次の図は、この問題が発生したときの状況を示しています (T = サンプル時間)。優先度の低いタスクは、完了前に優先度の高いタスクにプリエンプトされます。

上図では、より高速のブロックは、より低速のブロックの実行が完了する前に 2 回目の実行が行われています。このため、低速のタスクへの入力データが変更され、予測できない結果が生じる可能性があります。この状況では、データの整合性が維持されない可能性があります。

このような状況が発生しないようにするには、2 秒 (低速) ブロックの実行が終了するまでに、Simulink エンジンが 1 秒 (高速) ブロックの実行の出力を保持しなければなりません。これを行うには、1 秒ブロックと 2 秒ブロックの間に Rate Transition ブロックを挿入します。これによって、低速ブロックへの入力は実行中に変更されず、データの整合性も維持されます。

ここでは、Rate Transition ブロックが既定の設定 (保護/確定的) モードで使用されることを想定しています。

Rate Transition ブロックは、より低速のブロックのサンプル レートで実行されますが、より高速のブロックの優先度で実行されます。

Rate Transition ブロックを追加すると、Rate Transition ブロックが 2 秒ブロックの実行前に実行され (優先度が高い)、その出力値は、2 秒ブロックの実行中は一定に保持されます (低速ブロックのサンプル レートで実行されます)。

Simulink モデルでのより低速のブロックからより高速のブロックへの遷移

より低速のブロックがより高速のブロックを駆動するモデルでは、再度 Simulink エンジンによって駆動ブロックの出力が最初に計算されます。高速ブロックのみが実行されるサンプル間隔では、シミュレーションがより高速に進行します。

次の図はこの実行シーケンスを示します。

この図に示されているように、Simulink エンジンは複数のサンプル レートをもつモデルを効率的な方法でシミュレートします。ただし、Simulink シミュレーションはリアル タイムでは動作しません。

リアル タイムでのより低速のブロックからより高速のブロックへの遷移

より低速のブロックがより高速のブロックを駆動するモデルでは、生成されたコードによってより高速のブロックにより低速のブロックよりも高い優先度が与えられます。すなわち、より高速のブロックはより低速のブロックよりも先に実行されるため、不正確な結果が生じないように特に注意する必要があります。

このタイミング図では、次の 2 つの問題について説明します。

  • より低速のブロックの実行は、より高速のブロックの 1 間隔よりも長い時間で分割されます。この場合、より高速のタスクは、より低速のタスクの実行が完了する前に 2 回目の実行が行われます。すなわち、より高速のタスクへの入力は、ある時間では不正確な値になります。

  • より高速のブロックは、より低速のブロックよりも先に実行されます (Simulink シミュレーションの動作から後ろ方向になります)。この場合、1 秒のブロックが最初に実行されますが、より高速のタスクへの入力は計算されません。これによって、予測できない結果が生成される可能性があります。

このような問題を解消するには、低速ブロックと高速ブロック間に Rate Transition ブロックを挿入しなければなりません。

ここでは、Rate Transition ブロックが既定の設定 (保護/確定的) モードで使用されることを想定しています。

次の図には、Rate Transition ブロックが追加されるタイミング シーケンスが示されています。

この図の遷移に関するキー ポイントは次のとおりです (丸数字を参照):

  1. Rate Transition ブロックの出力は、1 秒タスクで実行されますが、より遅いレートで実行されます (2 秒)。Rate Transition ブロックの出力によって、1 秒タスクのブロックが送られます。

  2. Rate Transition の更新では 2 秒タスクの出力が使用され、内部状態が更新されます。

  3. 1 秒タスクの Rate Transition 出力では、2 秒タスクで更新された Rate Transition の状態が使用されます。

最初の問題は、Rate Transition ブロックがより遅いレートで、より低速のブロックの優先度で更新されるため、軽減されます。Rate Transition ブロックへの入力 (より低速のブロックの出力) は、より低速のブロックの実行が完了すると読み取られます。

2 番目の問題は、Rate Transition ブロックがより遅いレートで実行され、その出力が駆動中のより高速のブロックの計算中に変更されないため、軽減されます。Rate Transition ブロックの出力部分は、より低速のブロックのサンプル レートと、より高速のブロックの優先度で実行されます。Rate Transition ブロックは、より高速のブロックを駆動し、優先度が効率的に同じため、より高速のブロックよりも先に実行されます。

メモ:

Rate Transition ブロックをこのように使用すると、モデルが変更されます。より低速のブロックの出力は、Rate Transition ブロックを使用しない出力と比較して 1 タイム ステップ遅延します。

volatile キーワードを使用したデータの整合性の保護

モデル コンフィギュレーション パラメーター [データ転送中の整合性を確保] を選択すると、Rate Transition ブロックに対して生成されたコードでは、グローバルなバッファーとセマフォを定義し、それらを使用して転送されたデータの整合性を保護します。

特にマルチタスク アプリケーションの場合、データの転送に関係するタスク (レート) によって、コンパイラが予測できないときに、転送されるデータ、バッファーおよびセマフォに書き込みが行われる可能性があります。転送されるデータの整合性が損なわれるような方法でコンパイラがアセンブリ コードを最適化しないように、コード ジェネレーターはキーワード volatile をバッファーとセマフォに適用します。volatile バッファーとセマフォは通常は十分な保護を行うため、コード ジェネレーターは、転送されるデータを表すグローバル変数に volatile を適用しません。

Embedded Coder® を使用して、組み込みのカスタム ストレージ クラス VolatileRate Transition ブロックの入力に適用して転送されるデータに volatile を明示的に適用できます。たとえば、この手法を使用して、外部コードで生成コードと共有するデータの整合性を保護できます。

あるいは、外部コードが生成コードと共有するデータを保護するために、データを保護された方法で読み書きする独自の C 関数を作成できます。その後に、カスタム ストレージ クラス GetSet をモデル内のデータに適用できます。これにより、生成コードはデータに直接アクセスするのではなく、関数を呼び出します。

volatile の適用の詳細については、Protect Global Data with const and volatile Type Qualifiers (Embedded Coder)を参照してください。GetSet の詳細については、Access Data Through Functions with Storage Class GetSet (Embedded Coder)を参照してください。

アルゴリズム コードとデータからの Rate Transition ブロック コードとデータの分離

コード ジェネレーターが Rate Transition ブロック用に生成するコードとデータをモデル コードでインライン化するか、コードとデータをモデル コードが呼び出す個別の関数に配置するかを指定できます。これは、[Rate Transition ブロック コード] パラメーターを選択して制御します。Rate Transition ブロック コードとデータをアルゴリズム コードとデータに分離すると、Rate Transition ブロックおよびアルゴリズム コードをそれぞれ個別に解析、最適化、テストできます。既定では、Rate Transition ブロック コードがアルゴリズム コードおよびデータとともにインラインで設定されます。コードとデータを分離して、関数 model_step が呼び出す個別の関数 get と関数 set、および状態データ専用の構造体を生成コードに含めることができます。生成コードには、関数 model_initialize が呼び出す個別の関数 start と関数 initialize も含まれます。

モデル例

モデル <matlab:rtwdemo_ratetrans rtwdemo_ratetrans> を開きます。このマルチレートでマルチタスクのモデルには、異なるモードで動作する複数の Rate Transition ブロックが含まれます。

open_system('rtwdemo_ratetrans');
set_param('rtwdemo_ratetrans','SystemTargetFile','ert.tlc');
set_param('rtwdemo_ratetrans','GenerateComments', 'Off');

Rate Transition ブロックの個別コード

[コンフィギュレーション パラメーター] ダイアログ ボックスで、[Rate Transition ブロック コード] パラメーターを Function に設定します。モデルのコードを生成します。コードは rtwdemo_ratetrans.c ファイルと rtwdemo_ratetrans.h ファイルにあります。

currentDir = pwd;
[~,cgDir] = rtwdemodir();
rtwbuild('rtwdemo_ratetrans');
### Starting build procedure for model: rtwdemo_ratetrans
### Successful completion of build procedure for model: rtwdemo_ratetrans
hfile=fullfile(cgDir, 'rtwdemo_ratetrans_ert_rtw','rtwdemo_ratetrans.h');
rtwdemodbtype(hfile,'typedef struct {','} DW;', 1, 1);
typedef struct {
  real_T OutportBufferForOut3[20];
  real_T Integrator1_DSTATE[20];
  real_T Integrator2_DSTATE[20];
  real_T Integrator3_DSTATE[20];
  real_T Integrator1_PREV_U[20];
  real_T Integrator2_PREV_U[20];
  real_T Integrator3_PREV_U[20];
  uint32_T Algorithm_PREV_T;
  struct {
    uint_T Algorithm_RESET_ELAPS_T:1;
  } bitsForTID1;

  uint8_T Integrator1_SYSTEM_ENABLE;
  uint8_T Integrator2_SYSTEM_ENABLE;
  uint8_T Integrator3_SYSTEM_ENABLE;
} DW;

Rate Transition ブロックの場合、状態のデータはグローバル状態の構造体 DW_rtwdemo_ratetrans_T にはありません。このデータは rtwdemo_ratetrans_rtb.h ファイル内の独自の構造体にあります。

このコードは rtwdemo_ratetrans.c ファイルにあります。

cfile=fullfile(cgDir, 'rtwdemo_ratetrans_ert_rtw','rtwdemo_ratetrans.c');
rtwdemodbtype(cfile,'void rtwdemo_ratetrans_step0','void rtwdemo_ratetrans_terminate(void)', 1, 0);
void rtwdemo_ratetrans_step0(void)
{
  (rtM->Timing.RateInteraction.TID0_1)++;
  if ((rtM->Timing.RateInteraction.TID0_1) > 1) {
    rtM->Timing.RateInteraction.TID0_1 = 0;
  }

  rtwdemo_rate_DetAndIntegS2F_get(rtY.Out1);
  rtwdemo_ratetr_IntegOnlyS2F_get(rtY.Out2);
  memcpy(&rtY.Out3[0], &rtDW.OutportBufferForOut3[0], 20U * sizeof(real_T));
  rtwdemo_rate_DetAndIntegF2S_set(rtU.In1);
  rtwdemo_ratetr_IntegOnlyF2S_set(rtU.In2);
}

void rtwdemo_ratetrans_step1(void)
{
  real_T rtb_DetAndIntegF2S[20];
  real_T rtb_IntegOnlyF2S[20];
  uint32_T Algorithm_ELAPS_T;
  int32_T i;
  real_T tmp;
  rtwdemo_rate_DetAndIntegF2S_get(rtb_DetAndIntegF2S);
  rtwdemo_ratetr_IntegOnlyF2S_get(rtb_IntegOnlyF2S);
  if (rtDW.bitsForTID1.Algorithm_RESET_ELAPS_T) {
    Algorithm_ELAPS_T = 0U;
  } else {
    Algorithm_ELAPS_T = rtM->Timing.clockTick1 - rtDW.Algorithm_PREV_T;
  }

  rtDW.Algorithm_PREV_T = rtM->Timing.clockTick1;
  rtDW.bitsForTID1.Algorithm_RESET_ELAPS_T = false;
  tmp = 0.001 * (real_T)Algorithm_ELAPS_T;
  for (i = 0; i < 20; i++) {
    if (rtDW.Integrator1_SYSTEM_ENABLE == 0) {
      rtDW.Integrator1_DSTATE[i] += tmp * rtDW.Integrator1_PREV_U[i];
    }

    if (rtDW.Integrator2_SYSTEM_ENABLE == 0) {
      rtDW.Integrator2_DSTATE[i] += tmp * rtDW.Integrator2_PREV_U[i];
    }

    if (rtDW.Integrator3_SYSTEM_ENABLE == 0) {
      rtDW.Integrator3_DSTATE[i] += tmp * rtDW.Integrator3_PREV_U[i];
    }

    rtDW.OutportBufferForOut3[i] = rtDW.Integrator3_DSTATE[i];
    rtDW.Integrator1_PREV_U[i] = rtb_DetAndIntegF2S[i];
    rtDW.Integrator2_PREV_U[i] = rtb_IntegOnlyF2S[i];
    rtDW.Integrator3_PREV_U[i] = rtU.In3[i];
  }

  rtDW.Integrator1_SYSTEM_ENABLE = 0U;
  rtDW.Integrator2_SYSTEM_ENABLE = 0U;
  rtDW.Integrator3_SYSTEM_ENABLE = 0U;
  rtwdemo_rate_DetAndIntegS2F_set(rtDW.Integrator1_DSTATE);
  rtwdemo_ratetr_IntegOnlyS2F_set(rtDW.Integrator2_DSTATE);
  rtM->Timing.clockTick1++;
}

void rtwdemo_ratetrans_initialize(void)
{
  rtDW.bitsForTID1.Algorithm_RESET_ELAPS_T = true;
  rtDW.Integrator1_SYSTEM_ENABLE = 1U;
  rtDW.Integrator2_SYSTEM_ENABLE = 1U;
  rtDW.Integrator3_SYSTEM_ENABLE = 1U;
}

関数 rtwdemo_ratetrans_step0 と関数 rtwdemo_ratetrans_step1 には関数 get と関数 set への呼び出しが含まれます。これらの関数には Rate Transition ブロック コードが含まれます。これらの関数定義は rtwdemo_ratetrans_rtb.c ファイルにあります。

Rate Transition ブロックのインライン化コードの生成

[コンフィギュレーション パラメーター] ダイアログ ボックスで、[Rate Transition ブロック コード] パラメーターを Inline に設定します。モデルのコードを生成します。コードは rtwdemo_ratetrans.c ファイルと rtwdemo_ratetrans.h ファイルにあります。

set_param('rtwdemo_ratetrans','RateTransitionBlockCode','Inline');
rtwbuild('rtwdemo_ratetrans')
### Starting build procedure for model: rtwdemo_ratetrans
### Successful completion of build procedure for model: rtwdemo_ratetrans

このコードは現在、rtwdemo_ratetrans.h ファイルにあります。

hfile=fullfile(cgDir, 'rtwdemo_ratetrans_ert_rtw','rtwdemo_ratetrans.h');
rtwdemodbtype(hfile, 'typedef struct {', '} DW;', 1, 1);
typedef struct {
  real_T Integrator1_DSTATE[20];
  real_T Integrator2_DSTATE[20];
  real_T Integrator3_DSTATE[20];
  real_T DetAndIntegS2F_Buffer0[20];
  volatile real_T IntegOnlyS2F_Buffer[40];
  real_T DetAndIntegF2S_Buffer[20];
  volatile real_T IntegOnlyF2S_Buffer0[20];
  real_T Integrator1_PREV_U[20];
  real_T Integrator2_PREV_U[20];
  real_T Integrator3_PREV_U[20];
  uint32_T Algorithm_PREV_T;
  struct {
    uint_T Algorithm_RESET_ELAPS_T:1;
  } bitsForTID1;

  volatile int8_T IntegOnlyS2F_ActiveBufIdx;
  volatile int8_T IntegOnlyF2S_semaphoreTaken;
  uint8_T Integrator1_SYSTEM_ENABLE;
  uint8_T Integrator2_SYSTEM_ENABLE;
  uint8_T Integrator3_SYSTEM_ENABLE;
} DW;

Rate Transition ブロックの場合、状態のデータはグローバル状態の構造体 DW_rtwdemo_ratetrans_T にはありません。このデータは rtwdemo_ratetrans_rtb.h ファイル内の独自の構造体にあります。

このコードは現在、rtwdemo_ratetrans_rtb.c ファイルにあります。

cfile=fullfile(cgDir, 'rtwdemo_ratetrans_ert_rtw','rtwdemo_ratetrans.c');
rtwdemodbtype(cfile,'void rtwdemo_ratetrans_step0','void rtwdemo_ratetrans_terminate(void)', 1, 0);
void rtwdemo_ratetrans_step0(void)
{
  int32_T i;
  int32_T i_0;
  (rtM->Timing.RateInteraction.TID0_1)++;
  if ((rtM->Timing.RateInteraction.TID0_1) > 1) {
    rtM->Timing.RateInteraction.TID0_1 = 0;
  }

  if (rtM->Timing.RateInteraction.TID0_1 == 1) {
    memcpy(&rtY.Out1[0], &rtDW.DetAndIntegS2F_Buffer0[0], 20U * sizeof(real_T));
  }

  i = rtDW.IntegOnlyS2F_ActiveBufIdx * 20;
  for (i_0 = 0; i_0 < 20; i_0++) {
    rtY.Out2[i_0] = rtDW.IntegOnlyS2F_Buffer[i_0 + i];
  }

  if (rtM->Timing.RateInteraction.TID0_1 == 1) {
    memcpy(&rtDW.DetAndIntegF2S_Buffer[0], &rtU.In1[0], 20U * sizeof(real_T));
  }

  if (rtDW.IntegOnlyF2S_semaphoreTaken == 0) {
    for (i = 0; i < 20; i++) {
      rtDW.IntegOnlyF2S_Buffer0[i] = rtU.In2[i];
    }
  }
}

void rtwdemo_ratetrans_step1(void)
{
  real_T rtb_IntegOnlyF2S[20];
  uint32_T Algorithm_ELAPS_T;
  int32_T i;
  real_T tmp;
  rtDW.IntegOnlyF2S_semaphoreTaken = 1;
  for (i = 0; i < 20; i++) {
    rtb_IntegOnlyF2S[i] = rtDW.IntegOnlyF2S_Buffer0[i];
  }

  rtDW.IntegOnlyF2S_semaphoreTaken = 0;
  if (rtDW.bitsForTID1.Algorithm_RESET_ELAPS_T) {
    Algorithm_ELAPS_T = 0U;
  } else {
    Algorithm_ELAPS_T = rtM->Timing.clockTick1 - rtDW.Algorithm_PREV_T;
  }

  rtDW.Algorithm_PREV_T = rtM->Timing.clockTick1;
  rtDW.bitsForTID1.Algorithm_RESET_ELAPS_T = false;
  tmp = 0.001 * (real_T)Algorithm_ELAPS_T;
  for (i = 0; i < 20; i++) {
    if (rtDW.Integrator1_SYSTEM_ENABLE == 0) {
      rtDW.Integrator1_DSTATE[i] += tmp * rtDW.Integrator1_PREV_U[i];
    }

    if (rtDW.Integrator2_SYSTEM_ENABLE == 0) {
      rtDW.Integrator2_DSTATE[i] += tmp * rtDW.Integrator2_PREV_U[i];
    }

    if (rtDW.Integrator3_SYSTEM_ENABLE != 0) {
      rtY.Out3[i] = rtDW.Integrator3_DSTATE[i];
    } else {
      rtY.Out3[i] = tmp * rtDW.Integrator3_PREV_U[i] + rtDW.Integrator3_DSTATE[i];
    }

    rtDW.Integrator1_PREV_U[i] = rtDW.DetAndIntegF2S_Buffer[i];
    rtDW.Integrator2_PREV_U[i] = rtb_IntegOnlyF2S[i];
    rtDW.Integrator3_DSTATE[i] = rtY.Out3[i];
    rtDW.Integrator3_PREV_U[i] = rtU.In3[i];
    rtDW.DetAndIntegS2F_Buffer0[i] = rtDW.Integrator1_DSTATE[i];
  }

  rtDW.Integrator1_SYSTEM_ENABLE = 0U;
  rtDW.Integrator2_SYSTEM_ENABLE = 0U;
  rtDW.Integrator3_SYSTEM_ENABLE = 0U;
  for (i = 0; i < 20; i++) {
    rtDW.IntegOnlyS2F_Buffer[i + (rtDW.IntegOnlyS2F_ActiveBufIdx == 0) * 20] =
      rtDW.Integrator2_DSTATE[i];
  }

  rtDW.IntegOnlyS2F_ActiveBufIdx = (int8_T)(rtDW.IntegOnlyS2F_ActiveBufIdx == 0);
  rtM->Timing.clockTick1++;
}

void rtwdemo_ratetrans_initialize(void)
{
  rtDW.bitsForTID1.Algorithm_RESET_ELAPS_T = true;
  rtDW.Integrator1_SYSTEM_ENABLE = 1U;
  rtDW.Integrator2_SYSTEM_ENABLE = 1U;
  rtDW.Integrator3_SYSTEM_ENABLE = 1U;
}

コードは関数 rtwdemo_ratetrans_step0 と関数 rtwdemo_ratetrans_step1 にインライン化されます。

制限

コード ジェネレーターは、可変サイズの信号をもつか、For Each Subsystem ブロック内にある Rate Transition ブロックのコードとデータを分離しません。

参考

bdclose('rtwdemo_ratetrans');
rtwdemoclean;
cd(currentDir)

関連するトピック