取長補短:Simulink與VC++6.0介面比較(轉)

ba發表於2007-08-15
取長補短:Simulink與VC++6.0介面比較(轉)[@more@]Simulink與VC應用程式介面一個顯著的特點就是Simulink模擬必須依賴於 MATLAB系統,目前為止,MATLAB提供引擎方式將Simulink同VC應用程式的程式設計結合起來。要透過引擎方式將Simulink與VC結合起來首先要掌握VC與MATLAB透過引擎方式混合程式設計以及Simulink命令列模擬兩方面的內容。

MATLAB引擎方式函式庫

MATLAB引擎函式庫是MATLAB提供引擎方式介面的一系列程式的集合,它允許使用者用自己的C/C++語言或FORTRAN語言應用程式中對MATLAB進行呼叫,將MATLAB作為一個計算引擎使用,讓其在後臺執行,完成複雜的矩陣計算,簡化前臺使用者程式設計的任務。

在使用者啟動MATLAB引擎時,相當了啟動了另外一個MATLAB程式並在後臺執行。應用程式透過MATLAB引擎函式庫中提供的函式完成與MATLAB引擎之間進行資料交換和命令傳送的任務。MATLAB引擎函式庫總共提供了13個 C語言的引擎函式,它們均在標頭檔案engine.h中予以說明,所以在使用它們時,必須對該標頭檔案進行包含。下面簡要介紹引擎庫中的六個基本庫函式:

(1) engOpen

功能:啟動MATLAB引擎。

語法:Engine* engOpen(const char* startcmd);

其中,startcmd為一字串,用於啟動MATLAB程式。在Windows中,startcmd必須為NULL。

(2) engClose

功能:退出MATLAB引擎。

語法:int engClose(Engine* ep);

其中,ep是Engine型別的指標。EngClose發出退出MATLAB命令,成功時返回0,否則返回l。

(3) engEvalString

功能:執行一個用字串表示的MATLAB表示式。

語法:int engEvalString(Engine* ep, const char* string);

其中,string是命令字串,該字串必須是一個合法的MATLAB表示式。凡可在MATLAB命令視窗中執行的命令均可以字串形式執行。

(4) engGetArray

功能:從MATLAB的工作空間中複製一個變數。

語法:mxArray* engGetArray(Engine* ep, const char* name);

其中,name是從engine中得到的mxArray名。engGetArray 從ep所指向的engine中讀取使用引數name指定的mxArray結構體的內容,正確返回時其返回值為一指向新分配的mxArray結構體物件的指標,否則為NULL。 (5) engPutArray

功能:將mxArray結構體型別變數放入MATLAB的工作空間中。

語法:int engPutArray(engine* ep, const mxArray* mp);

其中,mp為mxArray結構體物件的指標。engPutArray將一個 mxArray結構體型別的變數寫入引擎ep。如果當前程式的工作空間中不存在指定的mxArray結構體,則函式會自動建立。若有同名的mxArray 結構體存在,它將被這一新的mxArray結構體取代。

(6) engOutPutBuffer

功能:確定存放MATLAB輸出結果的緩衝區域。

語法:int engOutputBuffer(Engine* eP,char* p,int n);

使用engOutputBuffer,使用者可以為引擎指標ep所指向的引擎設定一個輸出緩衝區,將MATLAB輸出到螢幕上的內容儲存在其中,其長度由引數n確定,位置由字元指標p來確定。

VC++6.0整合環境中建立MATLAB引擎程式的方法

第一步,建立專案工程。啟動VC++6.0整合環境,選擇File下拉式選單中的 New選項,可有三種型別的應用程式建立工程選擇.分別為MFC AppWizard(exe)、Win32Application和Win32conso1e Application。選擇其中一種,在Project name編輯框中輸入專案名,按照專案嚮導完成專案工程建立。

第二步,設定編譯環境。選擇下拉式選單Tools中的選單項Options,選擇其中的Directories屬性頁,在其中的Show directories下拉式選項框中分別選擇Include Files和Library Files,在下部的編輯框中透過瀏覽分別新增如下路徑:Include Fiels:MATLAB根目錄externinclude

MATLAB根目錄externincludecpp

Library Fiels:MATLAB根目錄externlib

MATLAB根目錄externinclude

第三步,設定專案連線選項。選擇選單Project中的子選單Settings,選擇其中的屬性頁Link,在其中的Catogery下拉式選項框中選擇Input.在下部的Object Library modules編輯框中填寫:libeng.lib、libmx.1ib和libmat.1ib。(具體用到什麼庫由你的應用決定)

第四步,加入引擎標頭檔案。在準備使用MATLAB引擎的類的cpp檔案中,加入“#include “engine.h””語句,並且在以後建立的要使用MATLAB引擎的類中也注意加入上述語句。

當完成以上述四步工作後,使用者就可以在VC++中對MATLAB引擎程式進行編譯和除錯了。

Simulink的命令列模擬方式

一般情況下,Simulink是類似框圖圖形化的模擬方法;而在透過引擎方式將 Simulink同VC相結合時,模擬的每個操作是透過呼叫engEvalString執行一個用字串表示的MATLAB表示式(Simulink模擬命令)來實現的。因此,要掌握Simulink&VC混合程式設計,首先需要掌握Simulink的命令列模擬方式:

[t,x,y]=sim('modelname')

利用對話方塊引數進行模擬,返回輸出矩陣;

[t,x,y]=sim('modelname', timespan, options, ut)

利用輸入引數進行模擬,返回輸出矩陣;

[t,x,y1,y2,...yn]=sim('modelname', timespan, options, ut)

利用輸入引數進行模擬,返回逐個輸出;

引數說明:

'modelname' 執行的模型名(不包含副檔名),必須在MATLAB的搜尋路徑上。

timespan 指定模擬的時間區間,可以採取以下幾種格式:

(1)[] 空,利用模型對話方塊設定時間;

(2)T_final 標量,制定終止模擬時間;

(3)[T_start T_final] 二元向量,指定模擬時間區間;

(4)outputTimes 任何指定輸出時間記錄點的向量。

options MATLAB特定的一種資料結構,具有最高優先權,可以覆蓋模型引數對話方塊中的設定。

ut 賦給模擬物件數入口模組的量,具有最高優先設定,它是形為[t,u1,u2...]的數值矩陣,每個為時間序列或輸入序列。

Simulink與VC++6.0介面中的幾點問題

根據自己在將Simulink與VC++6.0相結合過程中的經驗,在實際運作過程中,需要注意以下幾點問題:

Solver的選擇

模擬要涉及常微分方程組的數值積分,為適應計算的多樣性,Simulink提供了多種求解器。因此在解決具體的問題時,應當選擇合適的求解器,並且設定合適的引數,以得到精確且迅速的模擬結果。比如:

ode45 即Nonstiff微分方程式,應用Runge-Kutta解法的中階解法;應用最廣的ode23 即Nonstiff微分方程式,應用Runge-Kutta解法之較低階的求解方式,誤差會比ode45多一點,但執行的效率快 ;ode113 即Nonstiff微分方程式,應用Adams-Bashforth-Moulton解法; ode15s 即stiff微分方程式之變階數求解方式,是一種數值差分法;ode23s 即stiff微分方程式之低階數求解方式,應用修正的Rosenbrock二階解法;ode23t 即stiff微分方程式與dae三角形法整合求解方式 ode23tb 即stiff微分方程式之低階數求解方式。

對於ode45,通常適用於連續狀態模型,而對於剛性(stiff)系統,則需要採用如ode23s的剛性求解器。對於我們的可控整流電路故障模型,由於採用短路器模擬開路現象,系統為剛性系統,所以在solver選擇時需要選擇剛性求解演算法。

透過VC++編寫的應用程式採用引擎方式透過命令列模擬設定Solver只是改變了當前模擬的Solver,預設設定為Simulink中的模擬引數設定。比如對於可控整流電路故障診斷系統這一剛性系統,即便程式中選用了ode15s而預設為ode45,則本次模擬確實使用ode15s求解,但仍然會報警說應該用剛性解法。不過對於剛性系統,ode45可不好用,因此從模擬效果(如耗時)上可以認定程式中設定的剛性解法奏效了。

VC資料型別與MATLAB資料型別之間的轉換

使用VC++6.0與MATLAB透過引擎方式混合程式設計,不可避免地要在VC資料型別與MATLAB資料型別之間進行轉換。一般來說,可以使用memcpy進行轉換。即透過mxGetPr()獲取MATLAB資料型別的指標,再呼叫 memcpy,比如在命令列方式下設定模擬時間時可以如下處理:

//設定模擬時間VC資料型別àMATLAB資料型別

double timespan[2];

timespan[0] = (double) m_fStartTime;

timespan[1] = (double) m_fStopTime;

T = mxCreateDoubleMatrix(1, 2, mxREAL);

memcpy((char *) mxGetPr(T), (char *) timespan, 2*sizeof(double));

engPutVariable(ep, "T", T);

// MATLAB資料型別àVC資料型別

double test[2];

memcpy((char*)test, (char*)mxGetPr(T), 2*sizeof(double));

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10617731/viewspace-957352/,如需轉載,請註明出處,否則將追究法律責任。

相關文章