1. 程式人生 > >使用matlabcontrol控制元件實現java與matlab混合程式設計

使用matlabcontrol控制元件實現java與matlab混合程式設計

背景: 本人在做畢設時需要實現以下場景,web前端接收資料,傳到Jsp後端後,接著需要將前端傳遞來的資料送到matlab演算法函式中,使用matlab進行演算法的計算,得到結果後,再次將資料傳到JSP後端,最終實現結果資料在前端網頁的顯示。最初考慮的是將matlab程式直接編譯成jar檔案,然後匯入到Myeclip中,網上也有很多類似的文章,但是感覺有點複雜。然後就發現有人使用matlabcontrol控制元件,實現java呼叫matlab軟體進行計算,看起來比上一種方法簡單些,於是有了今天這篇文章。PS:本人機械專業,程式設計技術很弱,因畢設論文牽涉到java,jsp,matlab,故硬著頭皮學了這些,花費了很長時間,才實現上述功能。我會盡量詳細記錄,希望這篇文章能幫到你。本人程式應用了hibernate、struts2框架。

一、首先附上參考過的文章

二、matlabcontrol-4.1.0控制元件下載

三、應用

1.首先編寫好matlab演算法函式

我的論文用到了NSGAII演算法程式,一般用matlab計算時,需要用到的資料直接在程式裡宣告賦值即可,但是我的資料來自於前端網頁,所以需要對編寫好的演算法進行小小的修改,即將需要用到的資料變數寫到演算法函式的輸入變數中,如下: function [v_best ,f_best]=Main_NSGA2(d1 ,d2),v_best ,f_best分別為演算法計算後的結果,d1,d2為輸入變數。修改前的函式形式為 function Main_NSGA2。

2.新建web project專案(或java專案),匯入matlabcontrol控制元件

在Eclipse中建好專案後,將matlabcontrol檔案匯入到專案的Web App Libraries中,如下圖: one 若是java專案,只需要將matlab檔案放入到該專案的根目錄下即可,放入後效果如下圖,(PS:matlabcontrol控制元件不需要放入該目錄,我是放m檔案時順手拖進去了。。): two 若是web專案(我舉的的例子),需要將matlab函式檔案放入到tomcat伺服器的bin檔案下(例如:我的F:\Tomcat7.0\bin),呼叫matlab程式時,預設從tomcat\bin檔案下呼叫m函式,理解如下圖: 3 從下圖可以看出matlab被java呼叫時,預設從tomact的bin檔案下呼叫: (PS:可以看到我的function函式的輸入變數有很多,這裡舉例子時,只是簡單用d1,d2兩個簡單變數示意下,另外,function函式的輸入變數是形式引數,在實際應用時,需要在多個m檔案之間呼叫這些變數,即需要將這些變數定義為全域性變數,但是形式引數不能直接定義成全域性變數。這裡,我的方法是,將變數稍微改變形式,比如,m檔案中其中一個全域性變數為d1,那麼它對應的形參寫成d11,然後將d1=d11,再將d1作為全域性變數。簡單說,就是d11作為形式引數接收java傳來的值,d1定義為全域性變數,接收d11的值,參與計算。怕大家在這出問題,有點囉嗦了。) 4

3.前端jquery程式碼及後端java程式碼實現資料的傳遞及接收

jquery程式碼從網頁輸入框獲取資料,並通過$.post方法將資料傳到後端(應用了struts2),部分重要程式碼如下: 前端: 5 後端:

  package capp.action;
import matlabcontrol.*;
import java.text.DecimalFormat;//用於資料格式化:保留兩位小數
import java.util.HashMap;
import java.util.Map;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class ModelTest extends ActionSupport{
	private double d1;
	public void setD1(double d1) {//普通屬性驅動,提供set方法進行接收,,d=Double.parseDouble(d)
		this.d1 = d1;
	}
	private double r_s1;
	public void setR_s1(double r_s1) {//普通屬性驅動,提供set方法進行接收,,d=Double.parseDouble(d)
		this.r_s1 = r_s1;
	}
	private double xx1;
	public void setXx1(double xx1) {
		this.xx1 = xx1;
	}
	private double yy1;
	public void setYy1(double yy1) {
		this.yy1 = yy1;
	}
	private double zz1;
	public void setZz1(double zz1) {
		this.zz1 = zz1;
	}
	......(省略部分引數的程式碼)
	private double C_T1;
	public void setC_T1(double C_T1) {
		this.C_T1 = C_T1;
	}
	
	public String matlab() throws MatlabConnectionException, MatlabInvocationException{
		
		Map<String,Object> result = new HashMap<String,Object>();//這是宣告一個集合result,用來存放matlab計算反饋來的結果v_best和f_best
		try{
		MatlabProxyFactory factory = new MatlabProxyFactory();
		MatlabProxy proxy = factory.getProxy();
        Object[] result1 = proxy.returningFeval("Main_NSGA2",2,d1,r_s1,xx1,yy1,zz1,x_Fc1,y_Fc1,n_Fc1,k_Fc1,nl1,nu1);//這裡有很多引數,僅保留部分引數供大家理解用。proxy.returningFeva方法是執行m檔案。
        double[] r=(double[]) result1[0];
        System.out.print("v_best:");
        for (int i = 0; i < r.length; i++) {
        	DecimalFormat    df   = new DecimalFormat("######0.00");//使結果保留兩位小數
        	String v_best = df.format(r[i]);
        System.out.print(v_best);
        result.put("v_best", v_best);/*將v_best值放入result集合中;下同。*/
        }
        double[] rr=(double[]) result1[1];
        System.out.print("f_best:");
        for (int i = 0; i < rr.length; i++) {
        	DecimalFormat    df   = new DecimalFormat("######0.00");
        	String f_best = df.format(rr[i]);
        System.out.print(f_best);
        result.put("f_best", f_best);
        }
		//proxy.feval("Main_NSGA2");
		//Disconnect the proxy from MATLAB
	    proxy.disconnect();
		} catch (Exception e) {
			
			e.printStackTrace();
			//result.put("success",false);
			//失敗原因
			//result.put("msg",e.getMessage());//對應儲存資料失敗時的提示資訊
		}
		ActionContext.getContext().getValueStack().push(result);/*這裡是將result集合傳遞到前臺,即為data,即$。post的回撥函式function(data)中的data,然後通過data.f_best得到f_best的值。具體操作不是太懂。。*/
		return SUCCESS;
	}

}