By executing code at constant intervals, you can accurately time and schedule tasks.
rateControl object allows you to control the rate
of your code execution. These examples show different applications for the
rateControl object including its uses with ROS and sending
commands for robot control.
Create a rate object that runs at 1 Hz.
r = rateControl(1);
Start a loop using the
rateControl object inside to control the loop execution. Reset the object prior to the loop execution to reset timer. Print the iteration and time elapsed.
reset(r) for i = 1:10 time = r.TotalElapsedTime; fprintf('Iteration: %d - Time Elapsed: %f\n',i,time) waitfor(r); end
Iteration: 1 - Time Elapsed: 0.003167 Iteration: 2 - Time Elapsed: 1.001818 Iteration: 3 - Time Elapsed: 2.001102 Iteration: 4 - Time Elapsed: 3.001370 Iteration: 5 - Time Elapsed: 4.002419 Iteration: 6 - Time Elapsed: 5.001650 Iteration: 7 - Time Elapsed: 6.000856 Iteration: 8 - Time Elapsed: 7.001036 Iteration: 9 - Time Elapsed: 8.001618 Iteration: 10 - Time Elapsed: 9.000584
Each iteration executes at a 1-second interval.
rateControl object uses the
OverrunAction property to decide how to handle code that takes longer than the desired period to operate. The options are
'slip' (default) or
'drop'. This example shows how the
OverrunAction affects code execution.
Setup desired rate and loop time.
slowFrames is an array of times when the loop should be stalled longer than the desired rate.
desiredRate = 1; loopTime = 20; slowFrames = [3 7 12 18];
Rate object and specify the
'slip' indicates that the
waitfor function will return immediately if the time for
LastPeriod is greater than the
rate = rateControl(desiredRate); rate.OverrunAction = 'slip';
Rate object and begin loop. This loop will execute at the desired rate until the loop time is reached. When the
TotalElapsedTime reaches a slow frame time, it will stall for longer than the desired period.
reset(rate); while rate.TotalElapsedTime < loopTime if ~isempty(find(slowFrames == floor(rate.TotalElapsedTime))) pause(desiredRate + 0.1) end waitfor(rate); end
View statistics on the
Rate object. Notice the number of periods.
stats = statistics(rate)
stats = struct with fields: Periods: [1.0005 1.0001 0.9997 1.1051 0.9981 1.0000 0.9998 ... ] NumPeriods: 20 AveragePeriod: 1.0206 StandardDeviation: 0.0426 NumOverruns: 4
'drop' indicates that the
waitfor function will return at the next time step, even if the
LastPeriod is greater than the
DesiredRate property. This effectively drops the iteration that was missed by the slower code execution.
rate.OverrunAction = 'drop';
Rate object and begin loop.
reset(rate); while rate.TotalElapsedTime < loopTime if ~isempty(find(slowFrames == floor(rate.TotalElapsedTime))) pause(1.1) end waitfor(rate); end stats2 = statistics(rate)
stats2 = struct with fields: Periods: [1.0003 1.0004 1.0002 2.0021 0.9977 0.9998 2.0016 ... ] NumPeriods: 16 AveragePeriod: 1.2502 StandardDeviation: 0.4482 NumOverruns: 4
'drop' over run action resulted in 16 periods when the
'slip' resulted in 20 periods. This difference is because the
'slip' did not wait until the next interval based on the desired rate. Essentially, using
'slip' tries to keep the
AveragePeriod property as close to the desired rate. Using
'drop' ensures the code will execute at an even interval relative to
DesiredRate with some iterations being skipped.