# Automation of Xcos models using Scilab

Testing is a very important step in the process of development a system, component or software. In this article we are going to focus on software (model based design) testing. Depending on the methodology of running a test case, software testing falls into two categories:

• manual testing: where the test engineer defines and runs the test case (test scenario) and checks the results
• automated testing: where the test engineer defines the test cases but they are run and the results checked automatically by a script

Nowadays, automated testing is widely spread in the engineering and software development companies for several reasons. Compared with a manual test, an automated test allows you to run a lot of test cases in a short time, reproduce exactly the same scenario if needed and check large batch of data (results) automatically.

Scilab and Xcos allows you to run automatic tests on Xcos model using Scilab scripts. In this article we are going to explain how you can:

• set the parameters of Xcos blocks using Scilab functions
• run automatically Xcos models from Scilab
• save and check the result of the Xcos model against other data

As an example we are going to use the bilinear interpolation function from previous article and compare its results against the predefined interpolation function which comes with Xcos. In this example, the Xcos model is the reference model, which means that it holds the truth (we trust the results), and the bespoke Scilab function for bilinear interpolation is the object under test.

The principle of the test automation is depicted in the image below.

Image: Test automation with Scilab and Xcos

From a Scilab script we are going to generate test pairs of (xp, yp) points. These points are going to be fed to both the Scilab function and the Xcos model. At the end we are going to check if the zp points have the same value for both calculation methods. This way we are making sure that our created bilinear interpolation works well for a large set of input points.

The Xcos model uses two constant inputs, both set to zero, which are placeholders for the (xp, yp) points.

Image: Xcos bilinear 2-D interpolation model

The Saturation block are used to limit the input points to the MIN and MAX of the axes. If we are not doing the saturation, if the x or y points are outside the axes limits, the Interp 2 block will perform an extrapolation which is not desired.

The result of the Xcos model are saved in the Scilab workspace under the name zpt_out.

The Scilab function which implements the bilinear interpolation algorithm is displayed below.

function [P]=f_interp2d(x, y, z, xp, yp)

// Check if x axis is monotonically increasing
for i=1:length(x)
// Axis is not monotonically increasing
if i>1 && x(i) <= x(i-1)
//disp("Axis x is not monotonically increasing")
break;
end
end

// Find x1 and x2 coordinates
for i=1:length(x)
// Point xp is outside range
if xp < x(1) || xp > x(length(x))
//disp("Point xp is out or range");
if xp < x(1)
xp = x(1);
else
xp = x(length(x));
end
end

// Point x is the first point in the axis
if xp == x(1)
x1 = x(1);
x1_idx = 1;
x2 = x(2);
x2_idx = 2;
break;
end

// Point x is the last value in the axis
if xp == x(length(x))
x1 = x(length(x)-1);
x1_idx = length(x)-1;
x2 = x(length(x));
x2_idx = length(x);
break;
end

// Point x is in between first and last point of the axis
if xp >= x(i) && xp <= x(i+1)
x1 = x(i);
x1_idx = i;
x2 = x(i+1);
x2_idx = i+1;
break;
end
end

// Check if y axis is monotonically increasing
for i=1:length(y)
// Axis is not monotonically increasing
if i>1 && y(i) <= y(i-1)
//disp("Axis y is not monotonically increasing")
break;
end
end

// Find y1 and y2 coordinates
for i=1:length(y)

// Point yp is outside range
if yp < y(1) || yp > y(length(y))
//disp("Point yp is out or range");
if yp < y(1)
yp = y(1);
else
yp = y(length(y));
end
end

// Point y is the first point in the axis
if yp == y(1)
y1 = y(1);
y1_idx = 1;
y2 = y(2);
y2_idx = 2;
break;
end

// Point y is the last value in the axis
if yp == y(length(y))
y1 = y(length(y)-1);
y1_idx = length(y)-1;
y2 = y(length(y));
y2_idx = length(y);
break;
end

// Point y is in between first and last point of the axis
if yp >= y(i) && yp <= y(i+1)
y1 = y(i);
y1_idx = i;
y2 = y(i+1);
y2_idx = i+1;
break;
end
end
Q11 = z(y1_idx, x1_idx);
Q12 = z(y2_idx, x1_idx);
Q21 = z(y1_idx, x2_idx);
Q22 = z(y2_idx, x2_idx);

R1 = Q11*((x2-xp)/(x2-x1)) + Q21*((xp-x1)/(x2-x1));
R2 = Q12*((x2-xp)/(x2-x1)) + Q22*((xp-x1)/(x2-x1));
P = R1*((y2-yp)/(y2-y1)) + R2*((yp-y1)/(y2-y1));

endfunction

The function is saved as a Scilab function in a separate *.sci file. The function does some consistency check of the input data before doing the actual bilinear interpolation:

• check if both x and y axes are monotonically increasing
• check if the xp and yp points are between the minimum and maximum values of the axes

The Scilab bilinear interpolation function has 5 input parameters and 1 output:

• x-axis
• y-axis
• z-map
• xp coordinate
• yp coordinate
• zp interpolation result

For further information on the bilinear interpolation algorithm read this article Bilinear (2-D) interpolation with algorithm and calculator.

The Scilab script implementing the test automation is displayed below.

clc();
exec("f_interp2d.sci");

x = [1;2;3;4;5];
y = [1;2;3;4];

z(4,:) = [41,42,43,44,45];
z(3,:) = [31,32,33,34,35];
z(2,:) = [21,22,23,24,25];
z(1,:) = [11,12,13,14,15];

xpt = 1:0.1:5;
ypt = 1:0.1:4;

scs_interp2d = xcosDiagramToScilab("interp2d.zcos");

xcos("interp2d.zcos")

scs_interp2d.objs(2).graphics.exprs = "xp";
xcosUpdateBlock(scs_interp2d.objs(2))
scs_interp2d.objs(9).graphics.exprs = "yp";
xcosUpdateBlock(scs_interp2d.objs(9));

errCnt = 0;

for i=1:length(xpt)
for j=1:length(ypt)
xp = xpt(i);
yp = ypt(j);
zp_scilab(i,j) = f_interp2d(x,y,z,xp,yp);
xcos_simulate(scs_interp2d,4);
zp_xcos(i,j) = zpt_out.values(\$);
if abs(zp_scilab(i,j) - zp_xcos(i,j)) > 0.1
errCnt = errCnt + 1;
end
end
end

disp("Done!")

figure(0)
surf(x,y,z), xgrid();
hf0 = gcf(),ha0 = gca();
hf0.background = -2;
ha0.x_label.font_size = 2, ha0.x_label.font_foreground = 5;
ha0.y_label.font_size = 2, ha0.y_label.font_foreground = 5;
ha0.z_label.font_size = 2, ha0.z_label.font_foreground = 5;
title("x-engineer.org","FontSize",2,"Color","blue");

figure(1)
surf(xpt,ypt,zp_scilab'),xgrid();
hf1 = gcf(),ha1 = gca();
hf1.background = -2;
ha1.x_label.font_size = 2, ha1.x_label.font_foreground = 5;
ha1.y_label.font_size = 2, ha1.y_label.font_foreground = 5;
ha1.z_label.font_size = 2, ha1.z_label.font_foreground = 5;
title("x-engineer.org","FontSize",2,"Color","blue");

figure(2)
surf(xpt,ypt,zp_xcos'), xgrid();
hf2 = gcf(),ha2 = gca();
hf2.background = -2;
ha2.x_label.font_size = 2, ha2.x_label.font_foreground = 5;
ha2.y_label.font_size = 2, ha2.y_label.font_foreground = 5;
ha2.z_label.font_size = 2, ha2.z_label.font_foreground = 5;
title("x-engineer.org","FontSize",2,"Color","blue");

Let’s explain it line by line.

First we clear the Scilab console calling the function clc(). This is not mandatory but is useful in order to spot easily any warning or error messages. Next we load the Scilab bilinear interpolation function with the exec() function.

The next lines deal with the definition of the axes x, y and map z data.

The interpolation points are defined as vectors in the variables xpt and ypt. The nested FOR loop defined later in the script will cycle through all these points and call the Xcos model and Scilab bilinear interpolation function.

Next step is to load the Xcos diagram into the Scilab workspace. This is required in order to have access to the model parameters in the Scilab environment. To load the Xcos model into the Scilab workspace we use the function xcosDiagramToScilab().

Next we open the Xcos model calling the xcos() function.

The next piece of code modifies the Constant block from the Xcos model and sets the value from 0 and 0 to xp and yp. When the nested FOR loop will run, xp and yp variables will be modified in the Scilab workspace and the Xcos model will read from there.

scs_interp2d.objs(2).graphics.exprs = "xp";
xcosUpdateBlock(scs_interp2d.objs(2))
scs_interp2d.objs(9).graphics.exprs = "yp";
xcosUpdateBlock(scs_interp2d.objs(9));

We also define an error counter variable errCnt which will count how many differences there are between the Xcos and Scilab interpolation functions.

The nested FOR loop will perform the following operations:

• cycle throught the xpt and ypt arrays and assign values to xp and yp
• call the Scilab bilinear interpolation function and return the result into the zp_scilab matrix
• call and run the Xcos model and return the result into the zp_xcos matrix
• check if the difference between the two interpolation methods exceeds 0.1, if yes, increment the error counter

After the nested FOR loop is executed, the Done! message is displayed in the Scilab console and the results of the interpolation functions are plotted into surf plots for comparison.

 Image: Plot of the input data Image: Plot of the Scilab interpolated data Image: Plot of the Xcos interpolated data

The results show that the Scilab implementation of the bilinear interpolation is correct, there are no difference in the result compare with the Xcos model. The error counter variable errCnt remains 0 throughout the simulation.

Also, if we look in the Scilab workspace at the size of the zp variables, they contain 41 x 31 elements, which means that the model was run 1271 times. This shows the capability of this method for test automation.