Main Content

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.