3D Matrix as output of a Matlab Function in a Simulink model

1.4k views Asked by At

I have the following problem.

I have a SIMULINK model and in this model I have a block: Matlab Function, the following http://it.mathworks.com/help/simulink/slref/matlabfunction.html

To my function I have in input :

  • a vector (N x 1)
  • a constant (1 X 1)

In output I would like to have a 3D Matrix, so a matrix R with dimensions (3 X 3 X N).

But I get the following error:

Data 'R' (#41) is inferred as a variable size matrix, while its specified
type is something else.
Component: MATLAB Function | Category: Coder error

Could you please help me?

The function in the block is the following :

function R = fcn(u,n_robots)

% u is the vector of the quaternions.
% If there are 2 robots involved the u will look like this:
% u=[w1 x1 y1 z1 w2 x2 y2 z2]'
%#eml
assert(n_robots<10);
% Initialization of the variables. If you remove this it won't work because
% code generation doesn't support dynamic changing size variables.
w=zeros(n_robots,1);
x=zeros(n_robots,1);
y=zeros(n_robots,1);
z=zeros(n_robots,1);
n=zeros(n_robots,1);

Rxx=zeros(n_robots,1);
Rxy=zeros(n_robots,1);
Rxz=zeros(n_robots,1);
Ryx=zeros(n_robots,1);
Ryy=zeros(n_robots,1);
Ryz=zeros(n_robots,1);
Rzx=zeros(n_robots,1);
Rzy=zeros(n_robots,1);
Rzz=zeros(n_robots,1);

R=zeros(3,3,n_robots);

for i=0:n_robots-1

    w(i+1) = u( 1+3*i );
    x(i+1) = u( 2+3*i );
    y(i+1) = u( 3+3*i );
    z(i+1) = u( 4+3*i );

    n(i+1) = sqrt(x(i+1)*x(i+1) + y(i+1)*y(i+1) + z(i+1)*z(i+1) + w(i+1)*w(i+1));

    x(i+1) = x(i+1)/ n(i+1);
    y(i+1) = y(i+1)/ n(i+1);
    z(i+1) = z(i+1)/ n(i+1);
    w(i+1) = w(i+1)/ n(i+1);

    Rxx(i+1) = 1 - 2*(y(i+1)^2 + z(i+1)^2);
    Rxy(i+1) = 2*(x(i+1)*y(i+1) - z(i+1)*w(i+1));
    Rxz(i+1) = 2*(x(i+1)*z(i+1) + y(i+1)*w(i+1));

    Ryx(i+1) = 2*(x(i+1)*y(i+1) + z(i+1)*w(i+1));
    Ryy(i+1) = 1 - 2*(x(i+1)^2 + z(i+1)^2);
    Ryz(i+1) = 2*(y(i+1)*z(i+1) - x(i+1)*w(i+1) );

    Rzx(i+1) = 2*(x(i+1)*z(i+1) - y(i+1)*w(i+1) );
    Rzy(i+1) = 2*(y(i+1)*z(i+1) + x(i+1)*w(i+1) );
    Rzz(i+1) = 1 - 2 *(x(i+1)^2 + y(i+1)^2);

    R(:,:,i+1) = [
        Rxx(i+1),    Rxy(i+1),    Rxz(i+1);
        Ryx(i+1),    Ryy(i+1),    Ryz(i+1);
        Rzx(i+1),    Rzy(i+1),    Rzz(i+1)];
end
2

There are 2 answers

0
James On BEST ANSWER

You may need to parameterise your whole model so you can repeat simulation with different numbers of robots and collect the results.

Either that, or figure out a max number of robots and make sure all variables are set to the maximum capacity - fill the space unused by robots with 0 or -1 or NaN to mark it as unused (whatever's appropriate for you.

3
Ryan Livingston On

I agree that the answer @James gave, parameteterize the model with the size, is ideal. You could declare n_robots to be a non-tunable parameter for the MATLAB Function Block and then the value would be considered constant during each simulation. That would in turn make R fixed size during each simulation. However, the value could be changed between simulations to handle other numbers of robots.

However, for completeness, you are able to set the output signal, R, to be variable size. From the MATLAB Function Block editor, click "Edit Data". Find and select the entry for R. Check the "variable size" check box and enter the upper bounds that are appropriate. [3,3,10] seems to suffice from your code.

There is more information on using variable size data with the MATLAB Function Block at:

http://www.mathworks.com/help/simulink/variable-size-data.html