3

is there a way to define the source workspace in Matlab for 'linearize' when used within a function?

Here a short minimal working example:

clear all
sys = 'watertank';
open(sys)
sys_io(1)   = linio('watertank/PID Controller',1,'input');
sys_io(2)   = linio('watertank/Water-Tank System',1,'openoutput');
linsys      = GetLinsys(sys,sys_io);
disp(linsys.a)

The function is:

function linsys = GetLinsys(sys,sys_io)
A       = 10;
linsys  = linearize(sys,sys_io);
end

The output is

-0.0500

since the linearize uses the inital value of A in the 'base' workspace (A=20) and not the value in the 'current' workspace (A=10).

However, I would expect

-0.1000

This is obtained if the code of the function is included in the script:

clear all
sys = 'watertank';
open(sys)
sys_io(1)   = linio('watertank/PID Controller',1,'input');
sys_io(2)   = linio('watertank/Water-Tank System',1,'openoutput');
A           = 10;
linsys      = linearize(sys,sys_io);
disp(linsys.a)

Thus, the question is: How can I get the same result using the function?

For the sim command, this can be done via the options:

options = simset('SrcWorkspace','current');
sim('modelname',[],options)

see here. However, I couldn't find something similar in the linearization options.

Thanks a lot for any help or suggestion!

Community
  • 1
  • 1
Ankaios Argo
  • 131
  • 3

2 Answers2

1

It appears that the standard way of passing parameters to Simulink is via the base workspace of MATLAB. To pass A=10 to Simulink from a function, i.e. create a variable in the base workspace, you use the assignin function:

function linsys = GetLinsys(sys,sys_io)
    assignin('base','A',10);
    linsys  = linearize(sys,sys_io);
end

then, calling

sys = 'watertank';
open(sys)
sys_io(1)   = linio('watertank/PID Controller',1,'input');
sys_io(2)   = linio('watertank/Water-Tank System',1,'openoutput');
linsys      = GetLinsys(sys,sys_io);
disp(linsys.a)

yields

-0.1000

as expected.

Note, that this is a bit dangerous, as you overwrite any A, which is present in the base workspace at that time... As an alternative, I'd propose using the following function

function linsys = GetLinsys(sys,sys_io)

% Save old 'A', if exists
if evalin('base', 'exist(''A'',''var'')');
    baseA = evalin('base','A');
end
assignin('base','A',10)

% Function call
linsys  = linearize(sys,sys_io);

% Clean up
evalin('base', 'clear(''A'')');
if exist('baseA', 'var')
    assignin('base','A',baseA)
end

end

This checks if a variable called A exists in the base workspace and saves its value in baseA. Then you can safely assign the new A and call linearize. Finally, we clear A again and (if needed) re-assign the old baseA. - Not very elegant, but safer.

hbaderts
  • 14,136
  • 4
  • 41
  • 48
  • Thanks for your suggestion. But changing the variable in the base workspace is exactely what I would like to avoid by the function. Since it is possible for the sim command, I hope there is also a solution for the linearize command. – Ankaios Argo Jun 22 '16 at 11:21
  • I included a work-around, which saves and restores any variable `A` which is present in the base workspace prior to the function call. Not an elegant solution, but does the job. Maybe (hopefully!) somebody comes up with a built-in, straightforward way to do this - I don't really like this solution either. – hbaderts Jun 22 '16 at 11:46
  • Thanks a lot for your effort! But again: The question is how to change to the 'current' workspace and not how to manipulate the base workspace :-) Hope someone has an idea. – Ankaios Argo Jun 22 '16 at 12:13
1

Within various of the files in MATLABROOT\toolbox\slcontrol\slcontrol that relate to linearization there is the following comment before the call to sim,

    % Run the simulation.  Do not need to simulate past
    % the final specified time.  Use the base workspace to write
    % variables and simulate.  This will be consistent with all
    % linearization functions that require the model parameters be
    % defined in the base workspace.
    S = simset('DstWorkspace','base');
    pmgr.sim([Tstart Tfinal],S);

I'd take from that that there is no easy/transparent (and possibly not even a difficult) way to get linearize to use the Caller Workspace.

Changing the above call to sim to use the Caller Workspace isn't an option because it would assume Caller is the function form where sim is being called, not from where you are calling linearize.

You might be able to set things up to get data from the Model Workspace, in which case you'd need to populate and set that workspace before calling linearize.

Phil Goddard
  • 10,571
  • 1
  • 16
  • 28