Main Content

シンプルな振動子と減衰振動子をモデル化する MATLAB クラスに対応する C++ クラスの生成

MATLAB® クラスは、物理システムをモデル化するための自然なフレームワークを提供します。

  • シンプルなシステムを MATLAB クラスとしてモデル化できます。プライベートなクラス プロパティはシステム パラメーターです。クラス コンストラクターは、指定されたパラメーターを使用してシステムのインスタンスを作成します。パブリック メソッドは、指定された初期状態と時間間隔の最終状態を返すことで、システムのダイナミクスを取得します。クラスには、数学的な解析をモジュール化する他の補助メソッドを含めることもできます。

  • 多くの場合、シンプルなシステムで解析を開始し、追加効果 (機械的な減衰など) を導入して解析の正確性を向上させます。MATLAB では、元のクラスから継承するサブクラスとして、拡張システムをモデル化できます。サブクラスには、追加のシステム パラメーターに対応する追加のプライベート プロパティが含まれる場合があります (減衰定数など)。システムの仕様によっては、サブクラスが基底クラスから特定のメソッドを継承し、他のメソッドをオーバーロードする場合があります。

この例では、同じパラメーターと初期条件を使用してシンプルな振動子と減衰振動子の時間発展を比較する MATLAB 関数に対応する C++ コードを生成する方法を示します。2 つの振動子システムは、MATLAB 名前空間 mySystem 内で定義されている MATLAB クラス simpleOscillator および dampedOscillator を使用してモデル化されます。生成されたコードには、ソース MATLAB クラスに対応する C++ クラスが含まれます。この例では、生成された C++ クラスに MATLAB クラスがどのようにマッピングされるか、および生成されたコードをカスタム C++ main 関数でどのように使用するかも示します。

MATLAB クラスとしてのシンプルな振動子と減衰振動子

支配方程式

シンプルな調和振動子には、質量 m とバネ定数 k の 2 つのパラメーターがあります。振動子の角周波数は ω=km です。時間 t の関数としての振動子の位置 x は次のようになります。

x(t)=Asin(ωt+ϕ).

振幅 A と位相定数 ϕ は、シンプルな振動子の初期位置 x0 と初期速度 v0 で決まります。この例では、MATLAB クラス simpleOscillator によってこのシステムがモデル化されます。

減衰調和振動子には、減衰定数 b という追加のパラメーターが 1 つあります。この例では、正規化された減衰パラメーター γ=b2m が角周波数 ω と比較して小さく、1 次の減衰効果のみが顕著な場合を検討します。時間 t の関数としての減衰振動子の位置 xd は次のようになります。

xd(t)=Ae-γtsin(ωt+ϕd)

前述のように、振幅 A と位相定数 ϕd は、減衰振動子の初期位置 x0 と初期速度 v0 で決まります。減衰の主効果は、振幅を指数的に減衰させることです。この例では、simpleOscillator モデルのサブクラスである MATLAB クラス dampedOscillator によって減衰システムがモデル化されます。

MATLAB ファイルと C++ ファイル

この例では、現在の作業ディレクトリにある次のサポート ファイルを使用します。

  • 名前空間フォルダー +mySystem には、2 つのクラス ファイル simpleOscillator.m および dampedOscillator.m が含まれています。

  • 関数 effectOfDamping は、指定されたパラメーターと初期条件を使用して、シンプルな振動子と減衰振動子の軌跡を計算して返します。

  • C++ ヘッダー ファイル main_damped_oscillator.h およびソース ファイル main_damped_oscillator.cpp は、カスタム C++ main 関数を実装しており、この例の最後の部分で実行可能ファイルを生成するために使用されます。

MATLAB コードの実行

3 つの振動子パラメーターのフィールドをもつ構造体 params を定義します。dampingConstant パラメーターが springConstant および mass と比較して小さくなるようにします (正規化された単位)。

params.springConstant = 1;
params.dampingConstant = 0.1;
params.mass = 1;

関数 effectOfDamping を呼び出して、シンプルな振動子と減衰振動子の位置と時間の軌跡を t=0 から t=100 まで計算します。初期位置 x0=1 と初期速度 v0=0 を指定します。

[time1,position1,time2,position2] = effectOfDamping(params,1,0,100,0.01);

シンプルな振動子と減衰振動子の位置と時間のグラフをプロットします。時間の経過に伴い、減衰振動子の振幅がどのように指数的に減衰するかを確認します。

plot(time1,position1)
hold on
plot(time2,position2)

Figure contains an axes object. The axes object contains 2 objects of type line.

シンプルな振動子の最終位置を表示します。

disp(position1(end))
    0.8623

減衰振動子の最終位置を表示します。減衰によってこの最終位置が平均位置 xmean=0 に近づくことを確認します。

disp(position2(end))
    0.0056

C++ MEX の生成と実行

実行時の問題を確認するには、関数 effectOfDamping に対応する C++ MEX 関数を生成します。最初の引数は params と同じ型およびサイズをもつように指定します。その他の引数は double 型のスカラーに指定します。

codegen -lang:c++ effectOfDamping -args {params,0,0,0,0} -report
Code generation successful: To view the report, open('codegen/mex/effectOfDamping/html/report.mldatx')

生成された MEX 関数 effectOfDamping_mex を呼び出して、シンプルな振動子と減衰振動子の位置と時間の軌跡を t=0 から t=100 まで計算します。初期位置 x0=1 と初期速度 v0=0 を指定します。

[time1,position1,time2,position2] = effectOfDamping_mex(params,1,0,100,0.01);

シンプルな振動子と減衰振動子の位置と時間のグラフをプロットします。プロットが元の MATLAB 関数によって生成されたプロットと同じであることを確認します。

plot(time1,position1)
hold on
plot(time2,position2)

Figure contains an axes object. The axes object contains 4 objects of type line.

2 つの振動子の最終位置を表示します。これらの値も元の MATLAB コードによって生成された値と同じです。

disp(position1(end))
    0.8623
disp(position2(end))
    0.0056

MEX ファイルをメモリからクリアします。

clear effectOfDamping_mex

C++ スタティック ライブラリの生成と検査

クラス インターフェイスをもつ C++ スタティック ライブラリの生成用にコード構成オブジェクトを作成します。インターフェイス クラスの名前を 'myOscillators' に指定します。以下の設定では、コード ジェネレーターはエントリポイント関数を C++ クラス 'myOscillators' のメソッドとして生成します。このインターフェイス クラスのコンストラクターとデストラクターは、それぞれ初期化関数と終了関数を実装します。

cfg = coder.config('lib');
cfg.TargetLang = 'C++';
cfg.CppInterfaceStyle = 'Methods';
cfg.CppInterfaceClassName = 'myOscillators';

関数のインライン化のグローバル設定を次のように調整します。

  • 可読性を高めるために記述したコードのモジュール性を維持します。InlineBetweenUserFunctions'Readability' に設定します。

  • コードの可読性が低下するとしても、MathWorks® 関数の高度に最適化されたコードを生成します。コード ベースのこの部分を検査する可能性は低いためです。InlineBetweenMathWorksFunctions'Speed' に設定します。

  • 生成コードで、記述した関数と MathWorks 関数を分離して、生成コードの外観が MATLAB コードとあまり異ならないようにします。InlineBetweenUserAndMathWorksFunctions'Readability' に設定します。

cfg.InlineBetweenUserFunctions = 'Readability'; 
cfg.InlineBetweenUserAndMathWorksFunctions = 'Readability';
cfg.InlineBetweenMathWorksFunctions = 'Speed';

コード ジェネレーターの関数のインライン化動作を制御する方法の詳細については、生成コードのパフォーマンスと可読性を微調整するためのインライン化の制御を参照してください。

codegen コマンドを使用して C++ スタティック ライブラリを生成します。

codegen -config cfg effectOfDamping -args {params,0,0,0,0} -report
Code generation successful: To view the report, open('codegen/lib/effectOfDamping/html/report.mldatx')

コード生成レポートを開き、生成された C++ ソース コードを検査します。

  • ファイル simpleOscillator.h および simpleOscillator.cpp には、シンプルな振動子の C++ クラスの実装が含まれています。ファイル dampedOscillator.h および dampedOscillator.cpp には、減衰振動子の C++ クラスの実装が含まれています。MATLAB クラスの継承構造は、生成されたコードではフラットになります。そのため、dampedOscillatorsimpleOscillator のサブクラスではなく、対応する MATLAB クラスが継承するすべてのメソッドを再実装します。MATLAB クラスと C++ クラスのマッピングの詳細については、MATLAB クラスに対応する C++ クラスの生成を参照してください。

  • MATLAB 名前空間は C++ 名前空間にマッピングされています。生成されたコードでは、simpleOscillator クラスと dampedOscillator クラスは mySystem 名前空間で定義されています。詳細については、生成された C++ コードの名前空間への整理を参照してください。

  • ファイル myOscillators.h および myOscillators.cpp には、インターフェイス クラス myOscillators の実装が含まれています。エントリポイント関数はメソッド myOscillators::effectOfDamping に実装されています。初期化関数と終了関数は、それぞれクラス コンストラクターとクラス デストラクターに実装されています。この例の次の部分では、このクラス インターフェイスをカスタム C++ main 関数で使用する方法を示します。詳細については、クラス インターフェイスをもつ C++ コードの生成を参照してください。

  • 関数 effectOfDamping の出力引数のサイズは、実行時の入力 timeInterval および timeStep で決まります。そのため、生成されたコードでは、これらの引数は coder::array クラス テンプレートを使用して実装される動的な配列 C++ として表されます。この例の次の部分では、coder::array クラス テンプレートをカスタム C++ main 関数で使用する方法を示します。詳細については、生成された関数インターフェイスでの動的に割り当てられた C++ 配列の使用を参照してください。

たとえば、ヘッダー ファイル simpleOscillator.h に含まれている生成された mySystem::simpleOscillator クラスの宣言を次に示します。

type codegen/lib/effectOfDamping/simpleOscillator.h
//
// Prerelease License - for engineering feedback and testing purposes
// only. Not for sale.
// File: simpleOscillator.h
//
// MATLAB Coder version            : 24.1
// C/C++ source code generated on  : 25-Jan-2024 15:05:13
//

#ifndef SIMPLEOSCILLATOR_H
#define SIMPLEOSCILLATOR_H

// Include Files
#include "rtwtypes.h"
#include "coder_array.h"
#include <cstddef>
#include <cstdlib>

// Type Definitions
namespace mySystem {
class simpleOscillator {
public:
  void init(double m, double k);
  void evolution(double initialPosition, double initialVelocity,
                 double timeInterval, double timeStep,
                 coder::array<double, 1U> &b_time,
                 coder::array<double, 1U> &position) const;
  double dynamics(double initialPosition, double initialVelocity,
                  double timeInterval) const;
  double amplitude(double initialPosition, double initialVelocity) const;
  double angularFrequency() const;
  double phase(double initialPosition, double initialVelocity) const;

protected:
  double mass;
  double springConstant;
};

} // namespace mySystem

#endif
//
// File trailer for simpleOscillator.h
//
// [EOF]
//

Embedded Coder® をお持ちの方は、構成オブジェクトの VerificationMode プロパティを 'SIL' に設定して、SIL MEX 関数 effectOfDamping_sil を生成できます。この SIL インターフェイスを使用すると、MATLAB 環境内で製品向けソース コードを検証できます。Software-in-the-Loop Execution from Command Line (Embedded Coder)を参照してください。

実行可能ファイルの生成と実行

この例の前の部分でライブラリ コードを生成した際に、コード ジェネレーターはメイン ファイルの例 main.h および main.cpp もビルド フォルダーの examples サブフォルダーに生成しています。C++ サポート ファイル main_damped_oscillator.h および main_damped_oscillator.cpp は、これらのサンプル ファイルを変更したものです。

  • main_damped_oscillator.cpp では、main 関数がインターフェイス クラス myOscillators を使用して生成コードを操作します。この関数は、C++ new 演算子を使用して myOscillators のインスタンスにメモリを割り当て、関数 main_effectOfDamping を呼び出して、最後に C++ delete 演算子を使用してメモリを解放します。

  • 関数 main_effectOfDamping は、この例の最初の部分で MATLAB スクリプトが実行した計算と同じ計算を実行します。coder::array API を使用して、生成された関数 effectOfDamping によって返される動的な配列を操作します。関数 main_effectOfDamping は、その実行の終了時に 2 つの振動子の最終位置を出力します。

C++ 実行可能ファイルの生成用にコード構成オブジェクトを作成します。この例の前の部分と同じ設定を使用します。

cfg = coder.config('exe');
cfg.TargetLang = 'C++';
cfg.CppInterfaceStyle = 'Methods';
cfg.CppInterfaceClassName = 'myOscillators';

cfg.InlineBetweenUserFunctions = 'Readability'; 
cfg.InlineBetweenUserAndMathWorksFunctions = 'Readability';
cfg.InlineBetweenMathWorksFunctions = 'Speed';

カスタム C++ ソース ファイルとカスタム インクルード フォルダーを指定します。

cfg.CustomSource = 'main_damped_oscillator.cpp';
cfg.CustomInclude = {pwd};

codegen コマンドを使用して実行可能ファイルを生成します。

codegen -config cfg effectOfDamping -args {params,0,0,0,0} -report
Code generation successful: To view the report, open('codegen/exe/effectOfDamping/html/report.mldatx')

生成された実行可能ファイルを実行します。この実行で返される 2 つの振動子の最終位置が、元の MATLAB コードの出力と一致することを確認します。

if isunix
    system('./effectOfDamping')
elseif ispc
    system('effectOfDamping.exe')
else
    disp('Platform is not supported')
end
0.862319
0.00563263
ans = 0

参考

|

関連するトピック