Logging States in Structure Format
Logging states using the Structure
format can provide advantages over the Array
format. When you log states using the Array
format, the ordering of the states along the columns in the logged array depends on the block sorted order. Various factors can affect the block sorted order, which can alter the ordering of the states from one simulation to the next. When you use the Structure
format, the block names are stored along with the logged state data for that block, so you can process your data without considering the block sorted order.
Logging States in Array Format
When you log states using the Array
format, the logged data is stored in an array with N
columns, where N
is the number of states, and M
rows, one for each simulation time step. This M-by-N matrix form is easy to manipulate in MATLAB®. However, the ordering of the state variables along the columns of the logged matrix depends on the block sorted order. Therefore, any MATLAB code which expects a fixed mapping between the states of blocks in the model and the columns of the states matrix is prone to breaking when the block sorted order changes due to changes in the model.
For example, consider the models sldemo_state_logging1
and sldemo_state_logging2
.
mdl1 = 'sldemo_state_logging1'; mdl2 = 'sldemo_state_logging2'; open_system(mdl1); open_system(mdl2);
The two models contain the same blocks, connected the same way. The only difference is the order of the output ports. Simulate the models and log the states using the Array
format.
simOut1 = sim(mdl1, 'SaveFormat','Array'); simOut2 = sim(mdl2, 'SaveFormat','Array');
Extract the states vectors from the Simulink.SimulationOutput
object, which contains all data logged in the simulation.
x1 = simOut1.get('xout'); x2 = simOut2.get('xout');
The logged states data for x1
and x2
are different because the blocks are ordered differently, so the mapping between the columns in the logged array and the blocks in the model is different.
isequal(x1, x2)
ans = logical 0
Log States Using the Structure Format
Simulate the models again, but this time log the states in structure format.
simOut1=sim(mdl1,'SaveFormat','Structure'); simOut2=sim(mdl2,'SaveFormat','Structure');
Extract the structures, which contain the logged states, from the SimulationOutput
object.
x1s = simOut1.get('xout'); x2s = simOut2.get('xout');
Display these structures, which contain two fields: time
and signals
. The time
field is empty because the data was logged using the Structure
format and not the StructureWithTime
format. You can use the StructureWithTime
format when you need to save the time data along with the states data.
disp(x1s); disp(x2s);
time: [] signals: [1x2 struct] time: [] signals: [1x2 struct]
The structure signals
field is an array of structures, with one structure for each block in the model that has state data. Each block data structure within the signals
field contains a values
field with the states data and a blockName
field with the name of the block that produced that state data. You can extract the states data into a matrix that you can process similar to how you would had you logged the states using the Array
format.
To fix the state ordering problem, first use the block names to sort the states data into a fixed order. For example, you could sort the states data so that the blocks are in alphabetical order, which will stay the same from one simulation to the next, regardless of the block sorted order.
[~, idx1] = sort({x1s.signals.blockName}); x1 = [x1s.signals(idx1).values]; [~, idx2] = sort({x2s.signals.blockName}); x2 = [x2s.signals(idx2).values]; isequal(x1, x2)
ans = logical 1
Once you reorder the signals fields alphabetically by block name, if you extract the values field data in the same order, you can then process the data similar to how you would when you use the Array
format, but the order of the block states data does not change from one simulation to the next.