Java如何连接MATLAB,实现函数调用

2020-05-04  本文已影响0人  程序员网址导航

前言

最近帮大四的弟弟解决了一个毕设的难题,课题内容大概是这样的:“Matlab利用调度算法实现一个车间零部件生产调度任务,最后MTALB会生成一个调用结果甘特图。现在需要通过Java web应用配置程序的入参,以及通过Java自动化操作Matlab进行传参,以及在web端可视化matlab的执行结果。”

之前没有没有做过类似Java操作MATLAB的经验,在实现的过程中遇到好多坑:“java连接不上matlab?”,“JDK版本、Matlab版本有关系吗?”,“如何传递矩阵?”,“结果拿不到?”……

在国内几乎0资料背景下,查阅了不少国外文档、Matlab相关源码,费了很大劲最终才解决,所以记录下,希望可以帮助到有同样问题的同学。

效果

  1. java web应用启动过程自动拉起MATLAB程序
image.png
  1. 通过web应用连接调用matlab程序,最后执行结果(图片+文字)实现可视化。


    image.png

具体实现核心步骤

环境准备

安装JDK(建议1.8)、安装MATLAB

IDEA(开发工具,可更换为其他的)
MySQL(如果需要数据存储、肯定是需要一个RDMS)

驱动包

matlab-control.jar
通过matlab-control实现Java和Matlab混合编程的方法,并将该方法应用于过程控制仿真实验系统的研究和开发。

下载地址:https://www.mvnjar.com/org.n52.matlab/matlab-control/5.0.0/detail.html

下载后需要倒入你的java应用中(导入方法有疑问的话,找度娘吧)

准备matlab程序

main.m demo程序

# 定义一个main函数,它有一个T入参和一个out返回值
function [out] = main(T)

具体实现根据你的需要编写……

java程序


import org.n52.matlab.control.*;
import org.n52.matlab.control.extensions.MatlabNumericArray;
import org.n52.matlab.control.extensions.MatlabTypeConverter;
import org.springframework.util.ResourceUtils;

import java.io.File;
import java.io.FileNotFoundException;

/****
 * 模拟java连接matlab
 * @Author http://wwww.relaxheart.cn  王琦
 */
public class MatlabTest {

    /***
     * 指定matlab程序所处的位置,注意是文件夹形式
     */
    private static final String matlabFile = "C:\\Users\\Administrator\\Desktop\\matlab";
    /***
     * matlab启动程序的路径,因为后续通过这个路径来拉起matlab应用程序
     */
    private static final String matlabExe = "G:\\MATLAB\\R2018a\\bin\\matlab.exe";

    public static void main(String[] args) throws MatlabConnectionException, MatlabInvocationException, FileNotFoundException {
        File file = null;
        try {
            System.out.println(">>>>>>>>>>>>>>>>>>>>> Mtalab文件获取开始...");
            file = ResourceUtils.getFile(matlabFile);
        } catch (FileNotFoundException e) {
            System.out.println("Mtalab文件获取失败!");
        }
        System.out.println(">>>>>>>>>>>>>>>>>>>>> Mtalab文件获取成功!");
        System.out.println(">>>>>>>>>>>>>>>>>>>>> Mtalab建立连接...");
        MatlabProxyFactoryOptions options = new MatlabProxyFactoryOptions.Builder()
                .setProxyTimeout(300000L)
                .setMatlabStartingDirectory(file)
                .setHidden(false)
                .setMatlabLocation(matlabExe)
                .build();
        System.out.println(">>>>>>>>>>>>>>>>>>>>> 开始拉起MATLAB程序...");
        // 通过matlab代理工厂,创建matlab代理,后续通过代理操作matlab
        MatlabProxyFactory factory = new MatlabProxyFactory(options);
        MatlabProxy proxy = factory.getProxy();
        System.out.println(">>>>>>>>>>>>>>>>>>>>> MATLAB连接成功!");

        System.out.println(">>>>>>>>>>>>>>>>>>>>> JAVA 调用 MATLAB 程序...");
        // 构造矩阵入参
        double[][] in = createMockInputDataArray();
        // 注意传递二维以上数组型入参,需要同MatlabNumericArray包装后传递,否则会报错
        MatlabNumericArray input = new MatlabNumericArray(in, null);
        MatlabTypeConverter converter = new MatlabTypeConverter(proxy);
        converter.setNumericArray("in", input);
        // 调用matlab程序
        proxy.eval("[out]=main(in,path)");
        // 获取返回值
        double[][] out = converter.getNumericArray("out").getRealArray2D();
        System.out.println(">>>>>>>>>>>>>>>>>>>>> java invoke matlab success");
        // 断开连接
        proxy.exit();
    }

    /***
     * 构造一个输入参数
     * @return
     */
    private static double[][] createMockInputDataArray() {
        String p = "1   1   2   3   6   3;" +
                "1  2   2   8   16  1; " +
                "1  3   2   9   18  2; " +
                "1  4   2   2   4   4;" +
                " 1 5   2   3   6   6;" +
                " 1 6   2   2   4   5; " +
                "2  1   3   6   18  2; " +
                "2  2   3   8   24  3; " +
                "2  3   3   2   6   6; ";
        String[] p1 = p.split(";");
        double[][] input = new double[p1.length][6];
        for (int i = 0; i < p1.length; i++) {
            String[] num = p1[i].split("\t");
            input[i][0] = Integer.parseInt(num[0].trim());
            input[i][1] = Integer.parseInt(num[1].trim());
            input[i][2] = Integer.parseInt(num[2].trim());
            input[i][3] = Integer.parseInt(num[3].trim());
            input[i][4] = Integer.parseInt(num[4].trim());
            input[i][5] = Integer.parseInt(num[5].trim());
        }
        return input;
    }
}

--- 上面是一个Java连接matlab示例,那Javaweb应用具体如何连接 ---

我的web应用选用的spring boot框架,在上面的基础上我需要做一些调整。我不希望每次调用都需要拉起一个matlab。

spring boot application.xml

#matlab 文件路径
matlab.file.path=C:\\Users\\Administrator\\Desktop\\matlab
#matlab 启动程序 路径
matlab.exe.path=G:\\MATLAB\\R2018a\\bin\\matlab.exe

MatlabConfiguration.java 创建一个matlabProxy bean

import com.digitization.util.DateUtil;
import org.n52.matlab.control.MatlabConnectionException;
import org.n52.matlab.control.MatlabProxy;
import org.n52.matlab.control.MatlabProxyFactory;
import org.n52.matlab.control.MatlabProxyFactoryOptions;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.ResourceUtils;

import java.io.File;
import java.io.FileNotFoundException;

/****
 * @Author http://wwww.relaxheart.cn  王琦
 */
@Configuration
public class MatlabConfiguration {

    @Value("${matlab.file.path}")
    private String matlabFilePath;
    @Value("${matlab.exe.path}")
    private String matlabExePath;

    @Bean(name = "matlabProxy")
    public MatlabProxy createFactory() throws MatlabConnectionException {
        File file = null;
        try {
            System.out.println(DateUtil.getDateStr()+" -------------------------> MATLAB文件获取开始...");
            file = ResourceUtils.getFile(matlabFilePath);
        } catch (FileNotFoundException e) {
            System.out.println(DateUtil.getDateStr()+" -------------------------> MATLAB文件获取失败!");
        }
        System.out.println(DateUtil.getDateStr()+" -------------------------> MATLAB文件获取成功!");
        System.out.println(DateUtil.getDateStr()+" -------------------------> JAVA与MATLAB开始建立连接...");
        MatlabProxyFactoryOptions options = new MatlabProxyFactoryOptions.Builder()
                .setProxyTimeout(300000L)
                .setMatlabStartingDirectory(file)
                .setHidden(false)
                .setMatlabLocation(matlabExePath)
                .build();
        System.out.println(DateUtil.getDateStr()+" -------------------------> 开始拉起MATLAB应用程序...");
        MatlabProxyFactory factory = new MatlabProxyFactory(options);
        MatlabProxy proxy = factory.getProxy();
        System.out.println(DateUtil.getDateStr()+" -------------------------> MATLAB应用程序已经启动!");
        System.out.println(DateUtil.getDateStr()+" -------------------------> JAVA与MATLAB开始建立连接成功!");
        return proxy;
    }
}

在再具体需要的时候只需要注入这个matlabProxy bean即可

/****
 * @Author http://wwww.relaxheart.cn  王琦
 */
@Service
public class MatlabService {

    @Autowired
    private MatlabProxy matlabProxy;

    public void task() {
            ……略
            // 调用Matlab程序
            matlabProxy.eval("[out]=main(in)");
             ……略
     }

完结!!!

原文:JAVA如何连接MATLAB,实现函数调用

最后欢迎浏览我的个人兴趣分享网站: http://www.wangqi94.com

上一篇下一篇

猜你喜欢

热点阅读