com.velasolaris.plugin.controller.matlab.matconsolectl.MatlabPluginController Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of polysun-public-plugin Show documentation
Show all versions of polysun-public-plugin Show documentation
Polysun plugin with controllers for Polysun simulations.
The newest version!
package com.velasolaris.plugin.controller.matlab.matconsolectl;
import static com.velasolaris.plugin.controller.spi.PluginControllerConfiguration.DEFAULT_TIMESTEP;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.velasolaris.plugin.controller.flowrate.FlowratePluginController;
import com.velasolaris.plugin.controller.spi.PluginControllerConfiguration;
import com.velasolaris.plugin.controller.spi.PluginControllerConfiguration.ControlSignal;
import com.velasolaris.plugin.controller.spi.PluginControllerConfiguration.Log;
import com.velasolaris.plugin.controller.spi.PluginControllerConfiguration.Property;
import com.velasolaris.plugin.controller.spi.PluginControllerConfiguration.Sensor;
import com.velasolaris.plugin.controller.spi.PluginControllerException;
import com.velasolaris.plugin.controller.spi.PolysunSettings;
import com.velasolaris.plugin.painter.MatlabPluginControllerPainter;
import com.velasolaris.plugin.util.PluginUtils;
import matlabcontrol.MatlabConnectionException;
import matlabcontrol.MatlabInvocationException;
import matlabcontrol.MatlabProxy;
import matlabcontrol.MatlabProxyFactory;
import matlabcontrol.MatlabProxyFactoryOptions;
/**
* Matlab plugin controller that delegates control() to a user-defined matlab function.
*
* The communication with Matlab is done with https://github.com/diffplug/matconsolectl.
*
* [plugin.dataPath] = plugins/com.velasolaris.plugin.controller.matlab.matconsolectl.MatlabPluginController
* Basic configuration is read from [plugin.dataPath]/config.properties
.
* Basically all settings of MatConsoleCtl are configurable in config.properties
.
* The most important setting is the matlabStartingDirectory
.
* fixedTimestep
= 0 means the default Polysun timesteps will be used.
*
* Matlab files are copied the first time to [plugin.dataPath].
* The file control.m
describes the Matlab function interface.
*
* The the user sets the matlab function name in the controller element GUI.
* The function must either be in the path of Matlab or in the starting directory.
*
* The MatConsoleCtl demo can be run with
* java -jar matconsolectl.jar
.
*
* Performance:
* A Java implementation is much faster. The time per function call is not measurable.
* If performance is an important, the controller logic should directly implemented in Java,
* see {@link FlowratePluginController}.
*
* Measured average time per function call for control_flowrate() in Python and controlFlowrate() in Matlab
* and {@link FlowratePluginController} in Java 8 on a Intel Core i7-4500U CPU 1.80GHz (dual core) are about:
* JSON-RPC stream JSON-RPC XML-RPC Java Matlab
* RPC type custom standard standard native library
* Communication protocol: TCP socket HTTP HTTP native RMI
* TCP connection per simulation timestep timestep N/A simulation
* PyPy 5.4.1 and Polysun compiled: 0.06ms 0.3ms 0.6ms 0ms 0.6ms
* Python 3.4 and Eclipse debug: 0.08ms 0.9ms 1.4ms 0ms 0.6ms
*
* Note: Since Matlab R2016b there is an official Matlab Enginge API for Java,
* see https://ch.mathworks.com/help/matlab/matlab-engine-api-for-java.html
*
* @author rkurmann
* @since Polysun 9.1
*
*/
public class MatlabPluginController extends AbstractMatlabPluginController {
/** Static instance of the Logger for this class */
protected static Logger sLog = Logger.getLogger(MatlabPluginController.class.getName());
/** Property name for the matlab function in the controller element GUI. */
private static final String PROPERTY_MATLAB_FUNCTION = "Matlab function";
/** Property name for the matlab starting path (read only) in the controller element GUI. */
private static final String PROPERTY_MATLAB_STARTING_DIRECTORY = "Matlab starting directory";
/**
* Static MatConsoleCtl factory to create proxies.
* This factory survies project reloads and avoids restarting Matlab.
*/
private static MatlabProxyFactory staticFactory;
/** MatConsoleCtl factory to create proxies. Stored in an instance. */
private MatlabProxyFactory factory;
/** MatConsoleCtl proxy to communicates with Matlab. */
private MatlabProxy proxy;
/**
* Should we keep the same factory during a Polysun session?
* I.e. Should we use the static MatConsoleCtl factory to create proxies?
*/
private boolean keepFactory = true;
/** Name of the Matlab function to call. Comes from the controller element GUI. */
private String matlabFunction;
/** MatConsoleCtl matlabStartingDirectory factory setting. */
private String matlabStartingDirectory = null;
/** MatConsoleCtl usePreviouslyControlledSession factory setting. */
private boolean usePreviouslyControlledSession = true;
/** MatConsoleCtl port factory setting. */
private int port = 2100;
/** MatConsoleCtl matlabLocation factory setting. */
private String matlabLocation = null;
/** MatConsoleCtl proxyTimeout [ms] factory setting. */
private long proxyTimeout = 180000l;
/** MatConsoleCtl hidden factory setting. */
private boolean hidden = false;
/** MatConsoleCtl osgiClassloaderFriendly factory setting. */
private boolean osgiClassloaderFriendly = true;
/** MatConsoleCtl logFile factory setting. */
private String logFile = null;
/** MatConsoleCtl javaDebugPort factory setting. */
private Integer javaDebugPort = null;
/** MatConsoleCtl licenseFile factory setting. */
private String licenseFile = null;
/** MatConsoleCtl useSingleCompThread factory setting. */
private boolean useSingleCompThread = false;
/** Has the invalid number of control signals message already be shown? Avoid repeating output. */
private boolean invalidControlSignalsMsgShown;
/** Has the invalid number of logs already be shown? Avoid repeating output. */
private boolean invalidLogsMsgShown;
/**
* Default constructor.
*/
public MatlabPluginController() {
}
@Override
public String getName() {
return "Matlab";
}
@Override
public PluginControllerConfiguration getConfiguration(Map parameters) throws PluginControllerException {
setConfiguration(parameters);
Properties config = new Properties();
int defaultNumGenericSensors = 3;
int defaultNumGenericControlSignals = 3;
int defaultNumGenericProperties = 5;
int defaultNumLogValues = 1;
int defaultFixedTimestep = DEFAULT_TIMESTEP;
String defaultMatlabFunction = "control";
Integer defaultVerboseLevel = 1;
List printMessage = new ArrayList<>();
File configFile = new File(pluginDataPath + File.separator + "config.properties");
matlabStartingDirectory = "[pluginDataPath]";
try {
if (configFile.exists()) {
try(FileReader fileReader = new FileReader(configFile);
BufferedReader reader = new BufferedReader(fileReader);) {
config.load(reader);
Object obj;
defaultNumGenericProperties = (obj = config.get("defaultNumGenericProperties")) != null && !"".equals(obj) ? Integer.parseInt(obj.toString()) : defaultNumGenericProperties;
defaultNumGenericSensors = (obj = config.get("defaultNumGenericSensors")) != null && !"".equals(obj) ? Integer.parseInt(obj.toString()) : defaultNumGenericSensors;
defaultNumGenericControlSignals = (obj = config.get("defaultNumGenericControlSignals")) != null && !"".equals(obj) ? Integer.parseInt(obj.toString()) : defaultNumGenericControlSignals;
defaultFixedTimestep = (obj = config.get("defaultFixedTimestep")) != null && !"".equals(obj) ? Integer.parseInt(obj.toString()) : defaultFixedTimestep;
defaultNumLogValues = (obj = config.get("defaultNumLogValues")) != null && !"".equals(obj) ? Integer.parseInt(obj.toString()) : defaultNumLogValues;
defaultMatlabFunction = (obj = config.get("defaultMatlabFunction")) != null && !"".equals(obj) ? obj.toString() : defaultMatlabFunction;
defaultVerboseLevel = (obj = config.get("defaultVerboseLevel")) != null && !"".equals(obj) ? Integer.parseInt(obj.toString()) : defaultVerboseLevel;
port = (obj = config.get("matctl.port")) != null && !"".equals(obj) ? Integer.parseInt(obj.toString()) : port;
javaDebugPort = (obj = config.get("matctl.javaDebugPort")) != null && !"".equals(obj) ? Integer.parseInt(obj.toString()) : null;
proxyTimeout = (obj = config.get("matctl.proxyTimeout")) != null && !"".equals(obj) ? Long.parseLong(obj.toString()) : proxyTimeout;
keepFactory = (obj = config.get("keepFactory")) != null && !"".equals(obj) ? Boolean.parseBoolean(obj.toString()) : keepFactory;
usePreviouslyControlledSession = (obj = config.get("matctl.usePreviouslyControlledSession")) != null && !"".equals(obj) ? Boolean.parseBoolean(obj.toString()) : usePreviouslyControlledSession;
hidden = (obj = config.get("matctl.hidden")) != null && !"".equals(obj) ? Boolean.parseBoolean(obj.toString()) : hidden;
osgiClassloaderFriendly = (obj = config.get("matctl.osgiClassloaderFriendly")) != null && !"".equals(obj) ? Boolean.parseBoolean(obj.toString()) : osgiClassloaderFriendly;
useSingleCompThread = (obj = config.get("matctl.useSingleCompThread")) != null && !"".equals(obj) ? Boolean.parseBoolean(obj.toString()) : useSingleCompThread;
matlabLocation = (obj = config.get("matctl.matlabLocation")) != null && !"".equals(obj) ? obj.toString() : null;
logFile = (obj = config.get("matctl.logFile")) != null && !"".equals(obj) ? obj.toString() : null;
licenseFile = (obj = config.get("matctl.licenseFile")) != null && !"".equals(obj) ? obj.toString() : null;
matlabStartingDirectory = (obj = config.get("matctl.matlabStartingDirectory")) != null && !"".equals(obj) ? obj.toString() : matlabStartingDirectory;
sLog.info("Config.properties read: " + configFile);
} catch (IOException e) {
sLog.warning(PluginUtils.getRootCauseStackTrace(e));
}
} else {
new File(pluginDataPath).mkdirs();
try (FileWriter fileWriter = new FileWriter(configFile);
BufferedWriter writer = new BufferedWriter(fileWriter)) {
config.put("defaultNumGenericProperties", "" + defaultNumGenericProperties);
config.put("defaultNumGenericSensors", "" + defaultNumGenericSensors);
config.put("defaultNumGenericControlSignals", "" + defaultNumGenericControlSignals);
config.put("defaultNumLogValues", "" + defaultNumLogValues);
config.put("defaultFixedTimestep", "" + defaultFixedTimestep);
config.put("keepFactory", "" + keepFactory);
config.put("defaultMatlabFunction", "" + defaultMatlabFunction);
config.put("defaultVerboseLevel", "" + defaultVerboseLevel);
config.put("matctl.matlabStartingDirectory", matlabStartingDirectory != null ? matlabStartingDirectory : "");
config.put("matctl.matlabLocation", matlabLocation != null ? matlabLocation : "");
config.put("matctl.port", "" + port);
config.put("matctl.proxyTimeout", "" + proxyTimeout);
config.put("matctl.usePreviouslyControlledSession", "" + usePreviouslyControlledSession);
config.put("matctl.logFile", logFile != null ? logFile : "");
config.put("matctl.javaDebugPort", javaDebugPort != null ? "" + javaDebugPort : "");
config.put("matctl.useSingleCompThread", "" + useSingleCompThread);
config.put("matctl.osgiClassloaderFriendly", "" + osgiClassloaderFriendly);
config.put("matctl.hidden", "" + hidden);
config.store(writer, "Properties of the Polysun MatlabPluginController + [" + getId() + "]");
sLog.info("Config file written: " + configFile);
exportResource("/com/velasolaris/plugin/controller/matlab/control.m", pluginDataPath, true);
exportResource("/com/velasolaris/plugin/controller/matlab/controlFlowrate.m", pluginDataPath, true);
exportResource("/com/velasolaris/plugin/controller/matlab/controlCoSimSimulink.m", pluginDataPath, true);
new File(pluginDataPath + "/simulink").mkdirs();
exportResource("/com/velasolaris/plugin/controller/matlab/simulink/pauseCallback.m", pluginDataPath + "/simulink", true);
exportResource("/com/velasolaris/plugin/controller/matlab/simulink/SFunCoSim_ReadSensors.m", pluginDataPath + "/simulink", true);
exportResource("/com/velasolaris/plugin/controller/matlab/simulink/SFunCoSim_WriteCtrlSig.m", pluginDataPath + "/simulink", true);
exportResource("/com/velasolaris/plugin/controller/matlab/simulink/SimulinkBreak.m", pluginDataPath + "/simulink", true);
exportResource("/com/velasolaris/plugin/controller/matlab/simulink/SimulinkModel.slx", pluginDataPath + "/simulink", true);
printMessage.add("Configuration file and .m files written to " + pluginDataPath);
} catch(IOException e) {
sLog.warning(PluginUtils.getRootCauseStackTrace(e));
}
}
} catch (Exception e) {
sLog.warning(PluginUtils.getRootCauseStackTrace(e));
}
List properties = new ArrayList<>();
properties.add(new Property(PROPERTY_MATLAB_FUNCTION, defaultMatlabFunction));
properties.add(new Property(PROPERTY_MATLAB_STARTING_DIRECTORY, matlabStartingDirectory));
properties.add(new Property(PROPERTY_FIXED_TIMESTEP, defaultFixedTimestep, 0f, 900, "s"));
properties.add(new Property(PROPERTY_NUM_GENERIC_SENSORS, defaultNumGenericSensors, 0, 100));
properties.add(new Property(PROPERTY_NUM_GENERIC_CONTROL_SIGNALS, defaultNumGenericControlSignals, 0, 100));
properties.add(new Property(PROPERTY_NUM_GENERIC_LOGS, defaultNumLogValues, 0, 100));
// properties.add(new Property(PROPERTY_NUM_GENERIC_PROPERTIES, defaultNumGenericProperties, 0, 100));
properties.add(new Property(PROPERTY_VERBOSE_LEVEL, new String[] { "Standard", "Verbose", "Debug" }, defaultVerboseLevel));
numInternProperties = properties.size();
List sensors = new ArrayList<>();
List controlSignals = new ArrayList<>();
List logs = new ArrayList<>();
parameters.put("Plugin.PrintMessage", printMessage);
PluginControllerConfiguration.Builder builder = new PluginControllerConfiguration.Builder();
builder.setProperties(properties);
builder.setSensors(sensors);
builder.setControlSignals(controlSignals);
builder.setLogs(logs);
builder.setNumGenericProperties(defaultNumGenericProperties);
builder.setNumGenericSensors(defaultNumGenericSensors);
builder.setNumGenericControlSignals(defaultNumGenericControlSignals);
builder.setPropertyNameNumGenericSensors(PROPERTY_NUM_GENERIC_SENSORS);
builder.setPropertyNameNumGenericControlSignals(PROPERTY_NUM_GENERIC_CONTROL_SIGNALS);
builder.setPropertyNameNumGenericLogs(PROPERTY_NUM_GENERIC_LOGS);
builder.setImagePainter(new MatlabPluginControllerPainter());
return builder.build();
}
@Override
public void initialiseSimulation(Map parameters) throws PluginControllerException {
super.initialiseSimulation(parameters);
invalidControlSignalsMsgShown = false;
invalidLogsMsgShown = false;
try {
if (verboseLevel > VERBOSE_LEVEL_STANDARD) {
writeMsgToMatlab("Polysun simulation started");
}
File matlabStartingDir = getMatlabStartingDir(parameters);
if (matlabStartingDir != null && matlabStartingDir.exists()) {
getProxy().eval("cd('" + matlabStartingDir.getPath() + "')");
writeMsgToMatlab("Changed directory to " + matlabStartingDir.getPath());
getProxy().eval("disp(['The current directory is ', pwd])");
// Object[] obj = getProxy().returningEval("pwd", 1);
// if (obj != null && obj.length != 0) {
// String path = (String) obj[0];
// writeMsgToMatlab("The current directory is " + path);
// }
}
// function [ controlSignals, logValues, timepoints ] = control( simulationTime, status, sensors, sensorsUsed, properties, propertiesStr, preRun, controlSignalsUsed, numLogValues, stage, fixedTimestep, verboseLevel, parameters)
getProxy().returningFeval(matlabFunction, 3, 0, false, new float[sensorsUsed.length], sensorsUsed, matlabPropertiesFloat, matlabPropertiesString, true, controlSignalsUsed, 0, FUNCTION_STAGE_INIT, fixedTimestep, verboseLevel, null);
} catch (MatlabInvocationException | MatlabConnectionException e) {
sLog.severe(PluginUtils.getRootCauseStackTrace(e));
disconnectProxy();
throw new PluginControllerException(e);
}
}
/**
* Returns the Matlab starting directory.
* [pluginDataPath], [userHome], [projectDir] are replaced.
*
* @param parameters Generic parameters
* @return the plugin data path or null
if matlabStartingDirectory is null or empty
* @see MatlabPluginController#replacePathPlaceholders(String, Map)
*/
private File getMatlabStartingDir(Map parameters) {
if (matlabStartingDirectory != null && !"".equals(matlabStartingDirectory)) {
return new File(replacePathPlaceholders(matlabStartingDirectory, parameters));
}
return null;
}
@Override
public void build(PolysunSettings polysunSettings, Map parameters) throws PluginControllerException {
super.build(polysunSettings, parameters);
matlabStartingDirectory = getProperty(PROPERTY_MATLAB_STARTING_DIRECTORY).getString();
matlabFunction = getProperty(PROPERTY_MATLAB_FUNCTION).getString();
try {
setupMatlabCtl(parameters);
} catch (MatlabConnectionException | MatlabInvocationException e) {
sLog.warning(PluginUtils.getRootCauseStackTrace(e));
disconnectProxy();
throw new PluginControllerException(e);
}
}
@Override
public int[] control(int simulationTime, boolean status, float[] sensors, float[] controlSignals, float[] logValues,
boolean preRun, Map parameters) throws PluginControllerException {
try {
// function [ controlSignals, logValues, timepoints ] = control( simulationTime, status, sensors, sensorsUsed, properties, propertiesStr, preRun, controlSignalsUsed, numLogValues, stage, fixedTimestep, verboseLevel, parameters )
startMeasureFunctionCall();
Object[] result = getProxy().returningFeval(matlabFunction, 3, simulationTime, status, sensors, sensorsUsed, matlabPropertiesFloat, matlabPropertiesString, preRun, controlSignalsUsed, logValues.length, FUNCTION_STAGE_SIMULATION, fixedTimestep, verboseLevel, parameters);
double[] matlabControlSignals = (double[]) result[0];
double[] matlabLogs = (double[]) result[1];
double[] matlabTimepoints = (double[]) result[2];
stopMeasureFunctionCall();
if (matlabControlSignals.length != controlSignals.length && verboseLevel > VERBOSE_LEVEL_STANDARD && !invalidControlSignalsMsgShown) {
writeMsgToMatlab("Wrong number of control signals. Using smaller value. Expected: " + controlSignals.length + ", actual: " + matlabControlSignals.length);
invalidControlSignalsMsgShown = true;
}
if (matlabLogs.length != logValues.length && verboseLevel > VERBOSE_LEVEL_STANDARD && !invalidLogsMsgShown) {
writeMsgToMatlab("Wrong number of log values. Using smaller value. Expected: " + logValues.length + ", actual: " + matlabLogs.length);
invalidLogsMsgShown = true;
}
for (int i = 0; i < Math.min(controlSignals.length, matlabControlSignals.length); i++) {
controlSignals[i] = (float) matlabControlSignals[i];
}
for (int i = 0; i < Math.min(logValues.length, matlabLogs.length); i++) {
logValues[i] = (float) matlabLogs[i];
}
int[] timepoints = new int[matlabTimepoints.length];
for (int i = 0; i < timepoints.length; i++) {
timepoints[i] = (int) matlabTimepoints[i];
}
return timepoints;
} catch (MatlabInvocationException | MatlabConnectionException e) {
sLog.severe(PluginUtils.getRootCauseStackTrace(e));
disconnectProxy();
throw new PluginControllerException(e);
}
}
@Override
public void terminateSimulation(Map parameters) {
super.terminateSimulation(parameters);
try {
if (verboseLevel > VERBOSE_LEVEL_STANDARD) {
writeMsgToMatlab("Polysun simulation terminated");
logPerfMeasure("Overall: ", parameters);
}
// function [ controlSignals, logValues, timepoints ] = control( simulationTime, status, sensors, sensorsUsed, properties, propertiesStr, preRun, controlSignalsUsed, numLogValues, stage, fixedTimestep, verboseLevel, parameters)
getProxy().returningFeval(matlabFunction, 3, 0, false, new float[0], sensorsUsed, matlabPropertiesFloat, matlabPropertiesString, true, controlSignalsUsed, 0, FUNCTION_STAGE_TERMINATE, fixedTimestep, verboseLevel, null);
writeMsgToMatlab("Disconnect");
getProxy().disconnect();
} catch (Throwable e) {
sLog.warning(PluginUtils.getRootCauseStackTrace(e));
// ignore
disconnectProxy();
}
}
/**
* Sets up the MatConsoleCtl factory with settings from config.properties.
* @param parameters Generic parameters
* @throws MatlabConnectionException for any Matlab connection problems
* @throws MatlabInvocationException for any Matlab function or command invocation problems
*/
protected void setupMatlabCtl(Map parameters) throws MatlabConnectionException, MatlabInvocationException {
if (factory == null) {
if (keepFactory && staticFactory != null) {
factory = staticFactory;
} else {
sLog.info("Start connecting to Matlab...");
MatlabProxyFactoryOptions.Builder builder = new MatlabProxyFactoryOptions.Builder()
.setUsePreviouslyControlledSession(usePreviouslyControlledSession)
.setPort(port)
.setOSGiClassloaderFriendly(osgiClassloaderFriendly)
.setProxyTimeout(proxyTimeout)
.setHidden(hidden)
.setUseSingleComputationalThread(useSingleCompThread)
;
File matlabStartingDir = getMatlabStartingDir(parameters);
if (matlabStartingDir != null && matlabStartingDir.exists()) {
builder.setMatlabStartingDirectory(matlabStartingDir);
}
if (matlabLocation != null && !"".equals(matlabLocation)) {
builder.setMatlabLocation(matlabLocation);
}
if (logFile != null && !"".equals(logFile)) {
builder.setLogFile(logFile);
}
if (licenseFile != null && !"".equals(licenseFile)) {
builder.setLicenseFile(licenseFile);
}
if (javaDebugPort != null && javaDebugPort != 0) {
builder.setJavaDebugger(javaDebugPort);
}
sLog.info("Create MatlabProxyFactory");
factory = new MatlabProxyFactory(builder.build());
if (staticFactory == null) {
staticFactory = factory;
}
}
writeMsgToMatlab("Polysun connected to Matlab.");
sLog.info("Connected to Matlab");
parameters.put("Plugin.PrintMessage", "Connected to Matlab");
getProxy().eval("format compact;");
getProxy().disconnect();
}
}
/**
* Returns a proxy to communicate with Matlab.
*
* @return the proxy
* @throws MatlabConnectionException for any Matlab connection problems
*/
protected MatlabProxy getProxy() throws MatlabConnectionException {
if (proxy == null || !proxy.isConnected()) {
if (verboseLevel >= VERBOSE_LEVEL_DEBUG) {
sLog.fine("Create Matlab proxy");
}
proxy = factory.getProxy();
}
return proxy;
}
/**
* Writes a message to the Matlab console.
* @param msg message to print in Matlab console
* @throws MatlabConnectionException for any Matlab connection problems
* @throws MatlabInvocationException for any Matlab function or command invocation problems
*/
protected void writeMsgToMatlab(String msg) throws MatlabInvocationException, MatlabConnectionException {
if (verboseLevel >= VERBOSE_LEVEL_DEBUG) {
sLog.fine("Write Message to Matlab: " + msg);
}
getProxy().eval("disp('" + msg + "')");
}
@Override
public String getDescription() {
return "Matlab plugin controller that delegates the controller call to a user-defined matlab function.";
}
@Override
public String getDocumentation() {
return "Matlab plugin controller that delegates control() to a user-defined matlab function." +
"
" +
"
[plugin.dataPath] = plugins/com.velasolaris.plugin.controller.matlab.matconsolectl.MatlabPluginController
" +
"
Basic configuration is read from [plugin.dataPath]/config.properties
." +
"
Basically all settings of MatConsoleCtl are configurable in config.properties
." +
"
" +
"
Matlab files are copied the first time to [plugin.dataPath]." +
"
The file control.m
describes the Matlab function interface." +
"
" +
"
The the user sets the matlab function name in the controller element GUI." +
"
The function must either be in the path of Matlab or in the starting directory." +
"
" +
"
The communication with Matlab is done with https://github.com/diffplug/matconsolectl."
;
}
/**
* Disconnects the Matlab proxy.
* It is important that the proxy is disconnected at the end since a
* Matlab instance can be only connected to one Proxy at a time.
* If project is closed, but proxies remain open, a new Matlab instance
* will be started.
*/
protected void disconnectProxy() {
if (proxy != null) {
if (sLog.isLoggable(Level.INFO)) sLog.info("Disconnect proxy, isConnected=" + proxy.isConnected());
proxy.disconnect();
}
}
@Override
public void closeResources() {
disconnectProxy();
}
@Override
protected void finalize() throws Throwable {
super.finalize();
disconnectProxy();
}
// /** Test call. */
// public static void main(String... args) throws MatlabConnectionException, MatlabInvocationException, PluginControllerException {
// MatlabPluginController controller = new MatlabPluginController();
// System.out.println("Start");
// controller.setupMatlabCtl();
// controller.initialiseSimulation(null);
// controller.control(0, true, new float[1], new float[1], new float[1], false, null);
// controller.control(0, true, new float[1], new float[1], new float[1], false, null);
// controller.terminateSimulation(null);
// System.out.println("End");
// System.exit(0);
// }
}