1
votes

I would like to write a matlab function that wraps around a simulink block. The function should load data into the simulink model, run it, then return the data back from the function.

The only way I can think of doing this is by using the 'To Workspace' and 'From Workspace' blocks in simulink. The problem is that the 'From Workspace' block doesn't pick up variables from the function scope, only from the workspace scope.

Below is the only solution I could come up with, which basically converts the incoming vector to a string, and then creates a function which gets called when the model starts (effectively this is just as bad as eval).

Here is the code:

function [ dataOut ] = run_simulink( dataIn )

    % Convert data to a string (this is the part I would like to avoid)
    variableInitString = sprintf('simin = %s;', mat2str(dataIn));

    % we need both the name and the filename
    modelName = 'programatic_simulink';
    modelFileName = strcat(modelName,'.slx');

    % load model (without displaying window)
    load_system(modelFileName);

    % Set the InitFcn to the god awful string
    % this is how the dataIn actually gets into the model
    set_param(modelName, 'InitFcn', variableInitString);

    % run it
    sim(modelName);

    % explicity close without saving (0) because changing InitFcn
    % counts as changing the model.  Note that set_param also
    % creates a .autosave file (which is deleted after close_system)
    close_system(modelName, 0);

    % return data from simOut that is created by simulink
    dataOut = simout;
end

And you run it like this: run_simulink([0 0.25 0.5 0.75; 1 2 3 4]') where the first part of the matrix is the time vector.

Finally here is the underlying simulink file with the workspace block properties open for completeness.

Simulink model

(If the image is fuzzy, click to enlarge)

Is there a more clean way to do this without the mat2str() and sprintf() ? The sprint line takes forever to run, even with vectors of size 50k.

1

1 Answers

2
votes

It depends which version you are using. In recent version, you can specify the workspace to use as part of the call to the sim function, e.g.:

sim(modelName,'SrcWorkspace','current'); % the default is 'base'

For more details, see the documentation on sim. In older versions (not sure exactly when this changed, some time around R0211a or R0211b I think), you had to use simset, e.g.:

 myoptions = simset('SrcWorkspace','current',...
                       'DstWorkspace','current',...
                       'ReturnWorkspaceOutputs', 'on');
 simOut = sim(mdlName, endTime, myoptions);

Update

To return data back from sim in R2014b, you need to use an output argument when calling sim, which contains all the simulation outputs, e.g.:

simOut = sim(modelName,'SrcWorkspace','current'); % the default is 'base'

simOut is a Simulink.SimulationOutput object containing the time vector, the logged states and outputs of the model.