Include Final Operating Point for a Logged Signal while setting its Sample Time Property

10 views (last 30 days)
When using logged signals to export data from a simulation, I have been specifying the signal logging sample time parameter. The motivation behind this is to limit the impact on memory and storage when running a simulation multiple times (10,000's of times). However, my one main issue is that the final operating point is not logged unless it perfectly lines up with the logging sample time specified.
Is there a way to specificy a sample time for a logged signal, and also include the final operating point in the same signal log, even if the termination time isn't at a timestep of logging?
Demo of Ask
To demo what I'd like, I drafted this simple simulink model of a point mass subject to gravity. Below is the model diagram:
Some background info on this model:
  • Using ode4 fixed step solver (ode4)
  • Using time step of 0.001 s (1000 Hz)
  • Stop Simulation triggered when h [m] crosses zero. This occurs at t = 6.4340 [s] for this demo
Here is a scope output of it running nominally:

Run Cases

In each case Timing info is gathered by:
% running sim (it returns a 1x1 SimulationOutput named `out`)
% Grab Altitude Output (outputs as a timeseries)
h = out.logsout.get('h [m]').Values

Case 1: Leaving signal logging sample time as inherited (outputs at simulation rate):

%% Result:
>> h.Time
ans =
0:0.001:6.434
>> numel(h.Time)
ans =
6435

Case 2: Specifying signal logging sample time as 0.1 [s]:

%% Result:
>> h.Time
ans =
0:0.1:6.4
>> numel(h.Time)
ans =
65
%% Desired:
% h.Time = [0:0.1:6.4, 6.434]
% numel(h.Time) = 66

Case 3: Specifying signal logging sample time as 1 [s]:

%% Result:
>> h.Time
ans =
0:1:6
>> numel(h.Time)
ans =
7
%% Desired:
% h.Time = [0:1:6, 6.434]
% numel(h.Time) = 8
Intuitivly, this result make sense, as it is not set to log until the next time specified logging time step, but I would like a method for including the final point of t = 6.4340 in the signal log as well.
Possible Alternative & Issues:
  • Duplicate every logged signal. Have one be at the desired output rate, and one a the simulation rate, but limit it to one data point
  • This would just make every thing way more messy. Every signal of interest would need to be copied, and then each pair would need to be stiched together in post processing
  • Downsample as a post process step
  • The motivation for setting the signal logging sample time was due to memory and storage limitations, so it is preferable to avoid methods that even temporarilly increase resource allocation.
  • Also this would increase overall run time by needing an additional processing step on each signal of each run where as just saving off one additional
  • "Pause" the model until current time equals a logged time
  • Figuring out this logic for each subsystem and model reference may be trickey, and it could break some realistic effects.
  • Also, a quick test by putting the whole model inside an enabled subsystem yielded no difference in result as above, so a more complex fix would be needed here.
Other Notes:
  • It looks like there is a model configuration option for saving the final operating points of "states" but I would want every signal logged at the final operating point, and not just the states.

Answers (1)

Suraj Kumar
Suraj Kumar on 28 Mar 2024
Hi Matthew,
There are various ways in which we can include the final operating point in the logged signals, even if it doesn’t coincide with the timestep of logging.
One way to achieve this would be by interpolation i.e. using MATLAB to post-process the simulation data without downsampling.
After completion of the simulation, you can get the logged data for h[m] by executing the below mentioned code:
hData = out.logsout.get('h[m]').Values;
t = hData.Time;
h = hData.Data;
Now, you can run the following code which uses an advanced interpolation technique using “interp1” function to precisely determine when a signal hits zero, focusing on a narrow area near the initial sign change.
signChangeIndices = find(diff(sign(h)) ~= 0);
index = signChangeIndices(1);
startIndex = max(1, index - 2);
endIndex = min(length(h), index + 2);
tRange = t(startIndex:endIndex);
hRange = h(startIndex:endIndex);
t_zero = interp1(hRange, tRange, 0, 'pchip', 'extrap');
disp(['Estimated zero-crossing time using higher-order interpolation: ', num2str(t_zero)]);
The image attached below is the output displaying the last data point calculated from the interpolation method.
Another workaround is to use variable-step solver and set the following configurations:
Max step size=0.1s
Min step size=0.001s
Initial step size=0.1s
Now using this the simulation will start from sample time 0.1s but when the signal h[m]” becomes <=0 it will use the min step size i.e. 0.001s which will provide the desired results.
You can refer the below image for better understanding.
Similarly for sample time of 1s, you can set the Max step size and Initial step size as 1s and get the required results.
To know more about interp1 function and solvers you can refer the following documentations:
  1. https://www.mathworks.com/help/matlab/ref/interp1.html
  2. https://www.mathworks.com/help/simulink/ug/variable-step-solvers-in-simulink-1.html
  3. https://www.mathworks.com/help/simulink/configure-simulation.html?s_tid=CRUX_lftnav#:~:text=Step%20Size%20and%20Error%20Tolerance
Hope this helps!

Categories

Find more on Save Run-Time Data from Simulation in Help Center and File Exchange

Products


Release

R2023b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!