Example: Manage Matlab Simulink/Stateflow blocks from Epsilon

" >> Define matlab function that contains a global variable a".println;

M.statement("global e;");

" >> Create all necessary objects".println;

var simufc = new `simulink/User-Defined Functions/MATLAB Function`;
assert(SubSystem.all.size() = 1);

var store1 = new `simulink/Signal Routing/Data Store Memory`;
assert(DataStoreMemory.all.size() = 1);

var emChart = `Stateflow.EMChart`.all.first();
assert(`Stateflow.EMChart`.all.size()  = 1);

var dataSize = `Stateflow.Data`.all.size();
  var data_new = new `Stateflow.Data`;
  emChart.add(data_new);
assert(`Stateflow.Data`.all.size() = (dataSize + 1));

" >> setting properties".println;

simufc.Script="global a;"+"\\n"+"a=a+1;";
simufc.script.println;

emChart.Script = "global bb;";
emChart.script.println;

store1.position = "[100 100 130 130]";
assert(store1.position.at(0) = 100);
assert(store1.position.at(1) = 100);
assert(store1.position.at(2) = 130);
assert(store1.position.at(3) = 130);

store1.name="a";
assert(store1.name.println = "a");

data_new.name = "bb";assert(data_new.name.println = "bb");

data_new.Scope="Data Store Memory";
assert(data_new.Scope.println = "Data Store Memory");

store1.InitialValue = "2";
assert(store1.InitialValue = "2");

"finished".println;
"starting".println;

var reference = new `simulink/Sources/Step`;
assert(Step.all.size() = 1);  

var sum = new `simulink/Math Operations/Sum`;
assert(Sum.all.size() = 1);  

var controller = new `simulink/Ports & Subsystems/Subsystem`;
assert(SubSystem.all.size() = 1);  

var plant = new `simulink/Ports & Subsystems/Subsystem`;
assert(SubSystem.all.size() = 2);  

var pidController = new `simulink/Continuous/PID Controller`; // Controller subsystem
assert(SubSystem.all.size() = 3);  

var transferFcn = new `simulink/Continuous/Transfer Fcn`; // Plant subsystem
assert(TransferFcn.all.size() = 1);  

reference.name = "Reference";
assert(reference.name = "Reference");

controller.name = "Controller";
assert(controller.name = "Controller");

plant.name = "Plant";
assert(plant.name = "Plant");

pidController.name = "PID Controller";
assert(pidController.name = "PID Controller");

// Position them on the diagram
reference.position = "[100 100 130 130]";
assert(reference.position.at(0) = 100);
assert(reference.position.at(1) = 100);
assert(reference.position.at(2) = 130);
assert(reference.position.at(3) = 130);

sum.position = "[200 100 230 130]";
assert(sum.position.at(0) = 200);
assert(sum.position.at(1) = 100);
assert(sum.position.at(2) = 230);
assert(sum.position.at(3) = 130);

controller.position = "[300 100 400 130]";
assert(controller.position.at(0) = 300);
assert(controller.position.at(1) = 100);
assert(controller.position.at(2) = 400);
assert(controller.position.at(3) = 130);

plant.position = "[500 100 600 130]";
assert(plant.position.at(0) = 500);
assert(plant.position.at(1) = 100);
assert(plant.position.at(2) = 600);
assert(plant.position.at(3) = 130);

pidController.parent = controller;  // Parent is read only
"PID 1dof block (mask) parameter 'Parent' is read-only".println;

transferFcn.parent = plant; // Parent is read only
"TransferFcn block parameter 'Parent' is read-only".println;

var inports = Inport.all;
assert(inports.size() = 2);

var errorInport = inports.selectOne(ip|ip.parent = controller and ip.name="In1");

errorInport.name = "Error";
assert(errorInport.name = "Error");

var outports = Outport.all;
assert(outports.size() = 2);

var controlOutport = outports.selectOne(op|op.parent = controller and op.name="Out1"); 

controlOutport.name = "Control";
assert(controlOutport.name = "Control");

var plantInport = inports.selectOne(ip|ip.parent = plant);
var plantOutport = outports.selectOne(op|op.parent = plant);

"LINKING STARTS".println;

errorInport.unlink(controlOutport);
errorInport.link(pidController);
pidController.link(controlOutport);

plantInport.unlink(plantOutport);
plantInport.link(transferFcn);
transferFcn.link(plantOutport);

reference.link(sum); 
sum.link(controller); 
controller.link(plant); 
plant.linkTo(sum, 2);


"finished".println;
var multiply = new `simulink/User-Defined Functions/MATLAB Function`;
assert(SubSystem.all.size() = 1);

multiply.name = "Multiply";
assert(multiply.name = "Multiply");

multiply.script = "function y = fcn(x) \\n y = 2 * x;";
assert(multiply.script = "function y = fcn(x) \n y = 2 * x;");

multiply.position = "[100 100 180 160]";
assert(multiply.position.at(0) = 100);
assert(multiply.position.at(1) = 100);
assert(multiply.position.at(2) = 180);
assert(multiply.position.at(3) = 160);

var divide = new `simulink/User-Defined Functions/MATLAB Function`;
assert(SubSystem.all.size() = 2);

divide.name = "Divide";
assert(divide.name = "Divide");

divide.script = "function x = fcn(y) \\n x = y / 2;";
assert(divide.script = "function x = fcn(y) \n x = y / 2;");

divide.position = "[250 100 330 160]";
assert(divide.position.at(0) = 250);
assert(divide.position.at(1) = 100);
assert(divide.position.at(2) = 330);
assert(divide.position.at(3) = 160);

multiply.link(divide);//TODO assert
var sineWave = new `simulink/Sources/Sine Wave`;
assert(Sin.all.size() = 1);

var gain = new `simulink/Math Operations/Gain`;
assert(Gain.all.size() = 1);

var saturation = new `simulink/Discontinuities/Saturation`;
assert(Saturate.all.size() = 1);

var busCreator = new `simulink/Signal Routing/Bus Creator`;
assert(BusCreator.all.size() = 1);

var scope = new `simulink/Sinks/Scope`;
assert(Scope.all.size() = 1);

sineWave.position = "[100 100 130 130]";
assert(sineWave.position.at(0) = 100);
assert(sineWave.position.at(1) = 100);
assert(sineWave.position.at(2) = 130);
assert(sineWave.position.at(3) = 130);

gain.position = "[200 100 230 130]";
assert(gain.position.at(0) = 200);
assert(gain.position.at(1) = 100);
assert(gain.position.at(2) = 230);
assert(gain.position.at(3) = 130);

saturation.position = "[300 100 330 130]";
assert(saturation.position.at(0) = 300);
assert(saturation.position.at(1) = 100);
assert(saturation.position.at(2) = 330);
assert(saturation.position.at(3) = 130);

busCreator.position = "[400 72 410 303]";
assert(busCreator.position.at(0) = 400);
assert(busCreator.position.at(1) = 72);
assert(busCreator.position.at(2) = 410);
assert(busCreator.position.at(3) = 303);

scope.position = "[500 175 530 205]";
assert(scope.position.at(0) = 500);
assert(scope.position.at(1) = 175);
assert(scope.position.at(2) = 530);
assert(scope.position.at(3) = 205);

gain.Gain = "2";
assert(gain.Gain = "2");

busCreator.Inputs = "3";
assert(busCreator.Inputs = "3");

sineWave.link(gain); // TODO TESTS
gain.link(saturation); // TODO TESTS
saturation.link(busCreator); // TODO TESTS
gain.linkTo(busCreator, 2); // TODO TESTS
sineWave.linkTo(busCreator, 3); // TODO TESTS
busCreator.link(scope); // TODO TESTS
var simulinkChart = new `sflib/Chart`;
assert(`Stateflow.Chart`.all.size() = 1);  
assert(SubSystem.all.size() = 1);

simulinkChart.name = "Chart";
assert(simulinkChart.name.println = "Chart");

simulinkChart.position = "[200 100 230 130]";
assert(simulinkChart.position.at(0) = 200);
assert(simulinkChart.position.at(1) = 100);
assert(simulinkChart.position.at(2) = 230);
assert(simulinkChart.position.at(3) = 130);

var chart = `Stateflow.Chart`.all.selectOne(ch | ch.name = "Chart");

var sA = new `Stateflow.State`(chart);
assert(`Stateflow.State`.all.size() = 1);

sA.Name  = "A";
assert(sA.Name.println  = "A");

sA.position = "[50 50 310 200]";
assert(sA.position.at(0) = 50);
assert(sA.position.at(1) = 50);
assert(sA.position.at(2) = 310);
assert(sA.position.at(3) = 200);

var sA1 = new `Stateflow.State`;

chart.add(sA1);
assert(`Stateflow.State`.all.size() = 2);

sA1.Name = "A1";
assert(sA1.Name = "A1");

sA1.position = "[80 120 90 60]";
assert(sA1.position.at(0) = 80);
assert(sA1.position.at(1) = 120);
assert(sA1.position.at(2) = 90);
assert(sA1.position.at(3) = 60);

var sA2 = new `Stateflow.State`(chart);
assert(`Stateflow.State`.all.size() = 3);

sA2.Name = "A2";
assert(sA2.Name = "A2");

sA2.position = "[240 120 90 60]";
assert(sA2.position.at(0) = 240);
assert(sA2.position.at(1) = 120);
assert(sA2.position.at(2) = 90);
assert(sA2.position.at(3) = 60);

var tA1A2 = new `Stateflow.Transition`;
chart.add(tA1A2);
assert(`Stateflow.Transition`.all.size() = 1);

tA1A2.source = sA1; 
//assert(tA1A2.source.id = sA1.id);

tA1A2.destination = sA2; 
//assert(tA1A2.destination = sA2);

tA1A2.sourceOClock = 3;
assert(tA1A2.sourceOClock = 3);

tA1A2.destinationOClock = 9;
assert(tA1A2.destinationOClock = 9);

tA1A2.labelPosition = "[180 140 8 14]";
assert(tA1A2.labelPosition.at(0) = 180);
assert(tA1A2.labelPosition.at(1) = 140);
assert(tA1A2.labelPosition.at(2) = 8);
assert(tA1A2.labelPosition.at(3) = 14);

tA1A2.labelString = "E1";
assert(tA1A2.labelString = "E1");

var E1 = new `Stateflow.Event`(chart);
assert(`Stateflow.Event`.all.size() = 1);

E1.name = 'E1';
assert(E1.name = 'E1');

var pos = tA1A2.LabelPosition;
pos.set(0, pos.at(0) + 5);

tA1A2.LabelPosition = "[" + pos.concat(" ") + "]";
assert(tA1A2.LabelPosition.at(0) = pos.at(0));
assert(tA1A2.LabelPosition.at(1) = pos.at(1));
assert(tA1A2.LabelPosition.at(2) = pos.at(2));
assert(tA1A2.LabelPosition.at(3) = pos.at(3));

var dtA = new `Stateflow.Transition`(chart);
assert(`Stateflow.Transition`.all.size() = 2);

dtA.destination = sA;
//assert(dtA.destination = sA);

dtA.destinationOClock = 0;
assert(dtA.destinationOClock = 0);

var xsource = sA.Position.at(0) + sA.Position.at(2)/2;
var ysource = sA.Position.at(1) - 30;

dtA.SourceEndPoint = "[" + xsource + " " + ysource +"]";
dtA.SourceEndPoint.println;
assert(dtA.SourceEndPoint.at(0) = xsource);
assert(dtA.SourceEndPoint.at(1) = ysource);

xsource.println;
ysource.println;
dtA.MidPoint = "[" + xsource + " " + (ysource + 15) +"]";
assert(dtA.MidPoint.at(0) = xsource);
assert(dtA.MidPoint.at(1) = (ysource + 15));

var dtA1 = new `Stateflow.Transition`(chart);
assert(`Stateflow.Transition`.all.size() = 3);

dtA1.destination = sA1;
//assert(dtA1.destination = sA1); 
//dtA1.destination.println; // FAILS

dtA1.destinationOClock = 0;
assert(dtA1.destinationOClock = 0);

var xsource = sA1.Position.at(0) + sA1.Position.at(2)/2;
var ysource = sA1.Position.at(1) - 30;

dtA1.sourceEndPoint = "[" + xsource + " " + ysource +"]";
assert(dtA1.SourceEndPoint.at(0) = xsource);
assert(dtA1.SourceEndPoint.at(1) = ysource);

dtA1.midPoint = "[" + xsource + " " + (ysource + 15 ) +"]";
assert(dtA1.midPoint.at(0) = xsource);
assert(dtA1.midPoint.at(1) = (ysource + 15));

Clone Epsilon's Git repository and then:

Once you have checked out/imported the code, to run the example you need to go through the following steps:

  1. register any .ecore metamodels in the org.eclipse.epsilon.emc.simulink.examples project
  2. right click the .launch file in the org.eclipse.epsilon.emc.simulink.examples project
  3. select Run as... and click the first item in the menu that pops up

What's this?

In this example we show how to manage Matlab Simulink/Stateflow blocks with EOL.

What are .emf files?

.emf files are Ecore metamodels expressed using the Emfatic textual syntax.

More examples...

Epsilon Object Language
Epsilon Transformation Language
Epsilon Generation Language
Epsilon Validation Language
Epsilon Merging Language
Epsilon Flock
Epsilon Model Generation Language
Epsilon Pattern Language
Combining the Epsilon Languages
EuGENia
EUnit

Even more examples...

More examples are available in the examples folder of the Git repository.