I am using MATLAB 2013b, and I am attempting to write a script that will automatically wire up ToWorkspace blocks to a selected set of signals.
I can handle finding/getting handles to the signals, adding the blocks, setting the variable names, and so forth. What I want to do, however, is programmatically discover if a selected signal is a scalar, array, or bus signal. This way, I can reshape arrays to be 1D (so that they concatenate the way I want) and break down bus signals into their individual elements.
I attempted the fix posted at See if a signal originates from a bus in Simulink but with no luck. I'm betting that the post is old enough that the proposed fix didn't work in the version of MATLAB I'm attempting to use.
I know the answer involves compiling the model or updating the model with a certain command, but I am stuck. Help please!
Here's what I tried to do, based on the link above:
function usedNames = addToWorkspaceBlock( signal, usedNames )
% Recursively add whatever blocks are necessary to break down the signal
% into raw bus elements or reshaped arrays and output them that way
switch upper( get(signal,'CompiledBusType') )
case 'NOT_BUS'
% Will add the reshape block and ToWorkspace block here, saving
% the name of the ToWorkspace VariableName to usedNames
keyboard % for debugging
case {'VIRTUAL_BUS','NON_VIRTUAL_BUS'}
% Will add the reshape block and ToWorkspace block here, saving
% the name of the ToWorkspace VariableName to usedNames
keyboard % for debugging
otherwise
error('Unrecognized CompiledBusType %s', get(signal,'CompiledBusType'));
end
end
The error I get is this: (ignore the line numbers; my addToWorkspaceBlock() function is a subfunction of my main function which handles getting the signals and looping through them)
Error using createToWorkspaceBlocks>addToWorkspaceBlock (line 48)
line does not have a parameter named 'CompiledBusType'
Error in createToWorkspaceBlocks (line 36)
usedNames = addToWorkspaceBlock( signals(i), usedNames );
-
To help others answer your question, post your formatted code in the question.Joey Harwood– Joey Harwood2018年01月14日 04:18:59 +00:00Commented Jan 14, 2018 at 4:18
2 Answers 2
A less elegant but more practical way, which doesn't require compilation, is to pass the value into the string() function, then catch the error that's thrown if it's a bus. This worked in Matlab 2019:
try
string(value)
catch bus2stringFail
if strcmp(bus2stringFail.identifier, 'MATLAB:invalidConversion')
disp ('it was a bus after all')
end
end
Scalars, arrays, and matrices can all be passed to the string() function, so can be distinguished from a bus. If you have some other exotic value that cannot be turned into a string, this method won't distinguish it from a bus.
Comments
I think I have found a solution.
After the model has been compiled with modelName([],[],[],'compile') and the sizes phase has been executed with modelName([],[],[],'sizes'), the CompiledPortDimensions will now be a property of the source port of the signal. If the signal is a bus, the first CompiledPortDimensions will be negative. If it's numeric (scalar or array), CompiledPortDimensions will show the size() of the signal.
I have updated my code below. Note that I don't show my actual finding of signals or how I'm going to add the blocks, but this is how I ended up doing it:
function createToWorkspaceBlocks(signals)
% Create a ToWorkspace output for each of the given signals
% Get the root model containing these signals (assume all given signals
% are in the same root diagram)
rootSystem = bdroot( get(signals(1),'Parent') );
% Update the model to establish the CompiledPortDimensions property and rethrow
% any errors that occur during (i.e., stop this function)
try
cmd = [ rootSystem '([],[],[],''compile'')' ];
evalin('base',cmd);
% set_param( rootSystem, 'SimulationCommand', 'update' );
catch me
warndlg('The model could not be compiled!');
rethrow(me);
end
cmd = [ rootSystem '([],[],[],''sizes'')' ];
evalin('base',cmd);
% Loop through the signals and determine what signal type it is. Make
% ToWorkspace blocks based on the signal type:
% - scalars: signal --> ToWorkspace block
% - arrays: signal --> Reshape(1D) --> ToWorkspace block
% - bus: signal --> BusSelector --> (Reshape(1D) if needed) --> ToWorkspaceBlock
% Recursively
usedNames = cell( numel(signals), 1 );
for i = 1 : numel(signals)
usedNames = addToWorkspaceBlock( signals(i), usedNames );
end
cmd = [ rootSystem '([],[],[],''term'')' ];
evalin('base',cmd);
end
function usedNames = addToWorkspaceBlock( signal, usedNames )
% Recursively add whatever blocks is necessary to break down the signal
% into raw bus elements or reshaped arrays and output them that way
srcPort = get( signal, 'SrcPortHandle' );
srcPortDims = get( srcPort, 'CompiledPortDimensions' );
if srcPortDims(1) < 0
% Signal is a BUS
elseif all(srcPortDims > 0)
% Signal is NUMERIC
% % Add reshape block
% % Add ToWorkspace block
end
end