MV-7005: Matlab/Simulink生成のコード(Simulink Coder)とMotionSolveのリンク
このチュートリアルでは、Simulink Coder(旧名Real-Time Workshop)を使用してDLL(Dynamic Link Library)を生成し、それをMotionSolveとリンクして連成シミュレーションを実行する方法について学習します。
- MotionSolve(v12以上)が動作しているインストール環境
- MATLAB、Simulink、MATLAB Coder、およびSimulink Coderが動作しているインストール環境
- Microsoft Visual Studio (MSVS) 2010が動作しているインストール環境
サポートされているMATLABおよびMSVSのバージョンについては、XML Format Reference GuideのSupported Versions - Third Party Softwareをご参照ください。
この例ではMATLAB R2011bとMSVS 2010を使用します。
MotionSolveモデルの準備
<Control_PlantInput
id = "30100100"
num_element = "2"
variable_id_list = "30100400, 30100500"
sampling_period = "0.01"
offset_time = "0.0"
label = "for controller 1"
usrsub_param_string = "USER(987654321)"
usrsub_dll_name = "rtw_BusSuspension2PMIMODiscrete"
usrsub_fnc_name = "PINSUB"
hold_order = "2"
/>
<Control_PlantOutput
id = "30100200"
num_element = "2"
variable_id_list = "30100200, 30100300"
sampling_period = "0.01"
offset_time = "0.0"
label = "for controller 1"
usrsub_param_string = "USER(987654321)"
usrsub_dll_name = "rtw_BusSuspension2PMIMODiscrete"
usrsub_fnc_name = "POUTSUB"
hold_order = "2"
/>
<Control_PlantInput
id = "30100300"
num_element = "2"
variable_id_list = "30100800, 30100900"
sampling_period = "0.01"
offset_time = "0.0"
label = "for controller 2"
usrsub_param_string = "USER(987654321)"
usrsub_dll_name = "rtw_BusSuspension2PMIMODiscrete"
usrsub_fnc_name = "PINSUB"
hold_order = "2"
/>
<Control_PlantOutput
id = "30100400"
num_element = "2"
variable_id_list = "30100600, 30100700"
sampling_period = "0.01"
offset_time = "0.0"
label = "for controller 2"
usrsub_param_string = "USER(987654321)"
usrsub_dll_name = "rtw_BusSuspension2PMIMODiscrete"
usrsub_fnc_name = "POUTSUB"
hold_order = "2"
/>
- 属性
- 詳細
- usrsub_param_string
- このパラメータは“USER(id)”に等しくなるよう設定します。ここで、IDは、ユーザーが選択した整数(例えば、123)です。IDはSimulink Coderライブラリを特定し、このライブラリを使用する全てのControl_PlantInput'sおよびControl_PlantOutput'sをリンクします。IDは固有のものでなければなりません。注: 註: ライブラリ毎に複数のControl_PlantInput/Control_PlantOutput が存在し得ます。
- usrsub_dll_name
- 使用されるDLLの名称(例えば、Simulink Coderから)。
- usrsub_fnc_name
- MotionSolveがコールするユーザー関数 / サブルーチンの名称。これは、Control_PlantInputには“PINSUB”、Control_PlantOutputには“POUTSUB”でなければなりません。
ここでは、このMotionSolveモデルは既に用意されています。motionsolve\cosimulationフォルダーにあるMotionSolveおよびSimulinkモデルrtw_BusSuspension2PMIMODiscrete.xmlおよびSimulinkモデルrtw_BusSuspension2PMIMODiscrete.mdlを、自身の<working directory>にコピーします。
Simulinkモデルの準備 – コードの生成
これらのInportsおよびOutportsの順序はそれぞれ、MotionSolveモデル内でのControl_PlantOutput’s and Control_PlantInput'sの順序に一致している必要があります。
コードを修正、コンパイル、リンクしてDLLを作成
この時点で、Simulink CoderはSimulinkモデル用のソースコードを生成していますが、MotionSolveにより必要とされるDLLを生成するためには、このコードを修正、再コンパイルする必要があります。次の手順では、あるスクリプトを使ってこのコードを自動的にコンパイル、リンクし、MotionSolveモデルで使用されるSimulink Coder DLLを作成します。
このモデルのための上記コマンドの例:
ms_rtw_pre
rtw_BusSuspension2PMIMODiscrete "C:\Program Files\Altair\<version>" "C:\Program Files (x86)\Microsoft Visual Studio 10.0" "win64"
- Simulink Coderにより生成された元のソリューションのプロジェクト設定とソースファイル群を自動的に修正
- ソースコードをコンパイル、リンクして、MotionSolveで使用可能なDLLを生成
このプロセスが正常に完了したかどうかは、コマンドウィンドウ内の出力で確認できます。成功裏に実行された場合、次のように表示されます:
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========
1 file(s) copied.
** RTW dll is ready **
生成されたDLLでMotionSolveモデルを実行
この時点では、連成シミュレーションを完了するために、MotionSolveをSimulinkライブラリに単に指し示す必要があります。デフォルトでは、MotionSolveモデルと同じディレクトリにあることが前提です。
付録A
本セクションでは、アクセス関数CoSimAPI_SimulinkRTW_Update_U(api,model,input)およびCoSimAPI_SimulinkRTW_Update_Y(api,model,output) について述べます。これらは、DLLを介した連成シミュレーションの実行を補助するよう、Simulinkモデルソースコードに追加されます。
CoSimAPI_SimulinkRTW_Update_U(void *api, const RT_MODEL_x x_M, ExternalInputs_x &x_U)
この手法により、Simulink Coder生成コード内の入力データ構造はMotionSolveからの出力で更新されます。
最初の引数は、API IDへのポインタを要求します。API IDは、ラインusrsub_param_string = "USER(987654320)"内のモデルXMLから渡されます。USER()ストリング内の最初のパラメータは常にAPIのIDです。MotionSolve APIはメソッドvoid * CoSimAPI_Get_API_Ptr(int api_id) を与え、APIポインタを得ます。ここで、api_idは、XMLファイル内、USER()ストリングに指定されている番号です。
2つ目の引数は、生成Simulink Coderモデル情報に関連したデータ構造x_Mを要求します。‘x’はモデルの名称です。x_Mデータ構造は、Simulinkコードに固有のものです。
CoSimAPI_SimulinkRTW_Update_Y(void *api, const RT_MODEL_x x_M, const ExternalOutputs_x x_y)
このメソッドは、MotionSolveソルバー用の入力を、RTW生成コード内からの出力で更新します。
1つ目と2つ目の引数は、上で説明したものと同じです。
最後の引数は、現在のタイムステップについてMotionSolveに置かれるRTW出力x_Yです。x_Yは、外部出力に保管するためにSimulink Coderコードによって使用されるデータ構造です(Appendix Bをご参照ください)。
Appendix B
本セクションでは、外部入力 / 出力ポートを表すSimulink Coder生成コードについて述べます。以下のラインで、モデルの名称はrtw_MS(rtw = Real Time Workshop、Simulink Coderの旧名)と前提します。
一般的に、Simulink Coder生成コード(SCGC)は下記の表記を用います:
シングルチャンネルを有するSimulinkへの入力ポート | rtw_MS_U.In1、rtw_MS_U.In2など |
シングルチャンネルを有するSimulinkからの出力ポート | rtw_MS_Y.Out1、rtw_MS_Y.Out2など |
複数チャンネルを有する入力ポート | rtw_MS_U.In1[0]、rtw_MS_U.In1[1]など |
複数チャンネルを有する出力ポート | rtw_MS_Y.Out1[0]、rtw_MS_Y.Out1[1]など |
例えば、2つのControl_PlantInput (CPI)要素を有するモデルで、1つ目の要素が3つのチャンネルを、2つ目の要素が2つのチャンネルを有する場合、Simulink Coderコード内の対応するデータ構造は次のようになります:
CPI #1: rtw_MS_U.In1[0], rtw_MS_U.In1[1] and rtw_MS_U.In1[2]
CPI #2: rtw_MS_U.In2[0] and rtw_MS_U.In2[1]
Control_PlantOutputポートを扱うデータ構造についても同じことが当てはまります。
例えば最初の入力をIn1ではなくmyInと命名した場合、関数テンプレートに下記の変更を加えなければなりません:
double *u_ptr = (double *)&u.
myIn
;
元のコードを置き換えるには:
double *u_ptr = (double *)&u.
In1
;