Путем выполнения кода в постоянных интервалах вы можете точно время и планировать задачи. Используя rateControl
объект позволяет вам управлять уровнем своего выполнения кода. Эти примеры показывают различные приложения для rateControl
объект включая его использование с ROS и передающие команды для управления роботом.
Создайте объект уровня, который достигает 1 Гц.
r = rateControl(1);
Запустите цикл с помощью rateControl
возразите внутри, чтобы управлять выполнением цикла. Сбросьте объект до выполнения цикла, чтобы сбросить таймер. Распечатайте итерацию, и время протекло.
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.002622 Iteration: 2 - Time Elapsed: 1.001115 Iteration: 3 - Time Elapsed: 2.001586 Iteration: 4 - Time Elapsed: 3.000964 Iteration: 5 - Time Elapsed: 4.001710 Iteration: 6 - Time Elapsed: 5.001164 Iteration: 7 - Time Elapsed: 6.000850 Iteration: 8 - Time Elapsed: 7.001124 Iteration: 9 - Time Elapsed: 8.000808 Iteration: 10 - Time Elapsed: 9.000687
Каждая итерация выполняется в 1 втором интервале.
rateControl
возразите использует OverrunAction
свойство решить, как обработать код, который занимает больше времени, чем желаемый период, чтобы действовать. Опциями является 'slip'
(значение по умолчанию) или 'drop'
. В этом примере показано, как OverrunAction
влияет на выполнение кода.
Setup желал время цикла и уровня. slowFrames
массив времен, когда цикл должен быть остановлен дольше, чем желаемый уровень.
desiredRate = 1; loopTime = 20; slowFrames = [3 7 12 18];
Создайте Rate
возразите и задайте OverrunAction
свойство. 'slip'
указывает что waitfor
функция сразу возвратится если время для LastPeriod
больше DesiredRate
свойство.
rate = rateControl(desiredRate);
rate.OverrunAction = 'slip';
Сбросьте Rate
возразите и начните цикл. Этот цикл выполнится на желаемом уровне, пока время цикла не будет достигнуто. Когда TotalElapsedTime
достигает медленного времени системы координат, оно остановится для дольше, чем желаемый период.
reset(rate); while rate.TotalElapsedTime < loopTime if ~isempty(find(slowFrames == floor(rate.TotalElapsedTime))) pause(desiredRate + 0.1) end waitfor(rate); end
Просмотрите статистику по Rate
объект. Заметьте количество периодов.
stats = statistics(rate)
stats = struct with fields:
Periods: [1.0004 1.0000 1.0000 1.1024 0.9997 0.9997 1.0005 ... ]
NumPeriods: 20
AveragePeriod: 1.0203
StandardDeviation: 0.0419
NumOverruns: 4
Измените OverrunAction
к 'drop'
. 'drop'
указывает что waitfor
функция возвратится на следующем временном шаге, даже если LastPeriod
больше DesiredRate
свойство. Это эффективно пропускает итерацию, которая была пропущена более медленным выполнением кода.
rate.OverrunAction = 'drop';
Сбросьте Rate
возразите и начните цикл.
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.0003 1.0000 2.0031 0.9970 1.0000 2.0003 ... ]
NumPeriods: 16
AveragePeriod: 1.2501
StandardDeviation: 0.4478
NumOverruns: 4
Используя 'drop'
по запущенному действию привел к 16 периодам когда 'slip'
приведший к 20 периодам. Это различие то, потому что 'slip'
не ожидал до следующего интервала на основе желаемого уровня. По существу, использование 'slip'
попытки сохранить AveragePeriod
свойство как близко к желаемому уровню. Используя 'drop'
гарантирует, что код выполнится в ровном интервале относительно DesiredRate
с некоторыми пропускаемыми итерациями.
rateControl
| rosrate
(ROS Toolbox) | waitfor
(Robotics System Toolbox)