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を、自身の<作業ディレクトリ>にコピーします。
Simulinkモデルの準備 – コードの生成

これらのInportsおよびOutportsの順序はそれぞれ、MotionSolveモデル内でのControl_PlantOutput’s and Control_PlantInput'sの順序に一致している必要があります。
- Simulinkでrtw_BusSuspension2PMIMODiscrete.mdlを開きます。
-
Simulink Coderによって使用されるソルバー内のコンフィギュレーションパラメータを指定します。これを行うには、下に示す
メニューオプションを使用します。
図 2.
-
左側のブラウザ / ツリーで、Code
Generationを選択します:
図 3.
-
ここで、BrowseをクリックしてSystem target fileを変更し、"grt.tlc - Create Visual C/C++ Solution File for the
"grt" target"を探します。これは、以下のように示されています:
図 4.
- これを終えたら、同じCode Generationウィンドウ内で、Languageオプションを“C++”に変更します。
-
次に、左側のブラウザ / ツリーで、Solverオプションを選択します:
Simulink Coderでは、このコードを生成するためにMotionSolveに必要とされるGeneric Real-Timeターゲットのための可変ステップ積分器を使用することができません(Generic Real-Timeターゲット選択の詳細については、本チュートリアルの後半で述べます)。したがって、左側のSolverオプションで、下に示すとおりFixed-step solverソルバーを選択します:
図 5.
注: ユーザーのモデルに適切な固定ステップサイズの選択について詳しくは、Mathworksドキュメントをご参照ください(特に、モデルが複数のサンプル時間を有している場合、各サンプル時間がソルバーによってヒットされるよう、指定したサンプル時間の最小公分母に等しいステップサイズを選択する必要性が高いでしょう)。 - 次に、左側のブラウザ / ツリーで、Code Generationオプションを再度選択します。
-
Buildをクリックし、コードを構築します。
コードの作成により、現在のMATLABのディレクトリに2つのフォルダが生成されます(ここでは、<Simulink_model>がモデルの名称です):
- <Simulink_model>_grt_rtw
- slprj
下に示すものに似ていて、### Successful completion of Real-Time Workshop build procedure for model: rtw_BusSuspension2PMIMODiscreteで終わる
もしくは同様のメッセージが表示されるはずです。
図 6.
コードを修正、コンパイル、リンクしてDLLを作成
この時点で、Simulink CoderはSimulinkモデル用のソースコードを生成していますが、MotionSolveにより必要とされるDLLを生成するためには、このコードを修正、再コンパイルする必要があります。次の手順では、あるスクリプトを使ってこのコードを自動的にコンパイル、リンクし、MotionSolveモデルで使用されるSimulink Coder DLLを作成します。
- (Simulinkがコードを生成した)作業ディレクトリでコマンドプロンプトを開きます。
- 以下のコマンドを実行します:
"ms_rtw_pre <mdl_name> <altair_root> <msvs_root> <win32|win64>"
ここで、
<mdl_name>は、Simulinkモデルの名称(拡張子.mdlなし)
<altair_root>は、インストールのルートフォルダーへの完全なパスです。
<msvs_root>は、MSVSインストレーションのルートフォルダの完全なパス
<win32|win64> は、DLLのプラットフォームに応じてwin32またはwin64を指定
-
ms_rtw_preを成功裏に実行するには、“PATH” 環境変数内にMotionSolveバイナリのパスを含めてください。これは、Windows上では個々のPCで以下のコマンドを実行することにより行われます:
set PATH = <MS_bin_path>;%PATH%
ここで、<MS_bin_path>は、MotionSolveバイナリへのパス: 例えば、"C:\Program Files\Altair\<version>\hwsolvers\motionsolve\bin\win64」
- <altair_root>および / または<msvs_root>へのパスにスペースが含まれている場合、そのパスを引用符で囲む必要があります。
このモデルのための上記コマンドの例:
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モデルと同じディレクトリにあることが前提です。
- この例では、ms_pre_rtwスクリプトはDLLを、MotionSolveモデル(.xml)と同じフォルダに生成しているはずです。DLLが別の場所に生成されている場合は、MotionSolve .xmlファイルの作業ディレクトリにコピーしてください。
- コマンドウィンドウを開き、モデルを実行するために、パスをこのフォルダに変更します。
- MotionSolveモデルをコマンド行で実行するため、MotionSolveが起動できるように環境変数を設定する必要があります。コマンド行を実行するためのオプションの詳細については、MotionSolveユーザーズガイドをご参照ください。
- コマンド“mbd_d x.xml x.mrf”を実行して、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
;