Contenido principal

Esta página se ha traducido mediante traducción automática. Haga clic aquí para ver la última versión en inglés.

Ejecutar código a una tasa fija

Introducción

Al ejecutar código a intervalos constantes, puede cronometrar y programar tareas con precisión. El uso de un objeto rateControl le permite controlar la velocidad de ejecución de su código. Estos ejemplos muestran diferentes aplicaciones para el objeto rateControl, incluidos sus usos con ROS y el envío de comandos para el control del robot.

Ejecutar bucle a velocidad fija

Cree un objeto de velocidad que se ejecute a 1 Hz.

r = rateControl(1);

Inicie un bucle utilizando el objeto rateControl dentro para controlar la ejecución del bucle. Restablezca el objeto antes de la ejecución del bucle para restablecer el temporizador. Imprime la iteración y el tiempo transcurrido.

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.001865
Iteration: 2 - Time Elapsed: 1.000779
Iteration: 3 - Time Elapsed: 2.001266
Iteration: 4 - Time Elapsed: 3.001085
Iteration: 5 - Time Elapsed: 4.000798
Iteration: 6 - Time Elapsed: 5.001535
Iteration: 7 - Time Elapsed: 6.000616
Iteration: 8 - Time Elapsed: 7.001048
Iteration: 9 - Time Elapsed: 8.000344
Iteration: 10 - Time Elapsed: 9.000979

Cada iteración se ejecuta en un intervalo de 1 segundo.

Acciones de desbordamiento para la ejecución de tasa fija

El objeto rateControl utiliza la propiedad OverrunAction para decidir cómo manejar el código que tarda más que el período deseado en funcionar. Las opciones son 'slip' (predeterminado) o 'drop'. Este ejemplo muestra cómo OverrunAction afecta la ejecución del código.

Configure la velocidad deseada y el tiempo de bucle. slowFrames es una matriz de momentos en los que el bucle debe detenerse por más tiempo que la velocidad deseada.

desiredRate = 1;
loopTime = 20;
slowFrames = [3 7 12 18];

Cree el objeto Rate y especifique la propiedad OverrunAction. 'slip' indica que la función waitfor regresará inmediatamente si el tiempo para LastPeriod es mayor que la propiedad DesiredRate.

rate = rateControl(desiredRate);
rate.OverrunAction = 'slip';

Restablecer el objeto Rate y comenzar el bucle. Este bucle se ejecutará a la velocidad deseada hasta que se alcance el tiempo del bucle. Cuando TotalElapsedTime alcanza un tiempo de cuadro lento, se detendrá durante más tiempo que el período deseado.

reset(rate);

while rate.TotalElapsedTime < loopTime
    if ~isempty(find(slowFrames == floor(rate.TotalElapsedTime)))
        pause(desiredRate + 0.1)
    end
    waitfor(rate);
end

Ver estadísticas sobre el objeto Rate. Observe el número de períodos.

stats = statistics(rate)
stats = struct with fields:
              Periods: [1.0014 0.9991 0.9999 1.1024 0.9994 0.9999 1.0003 1.1032 0.9987 1.0003 1.0004 1.0004 1.1015 0.9992 1.0003 1.0002 1.0000 1.0000 1.1009 1.0002]
           NumPeriods: 20
        AveragePeriod: 1.0204
    StandardDeviation: 0.0419
          NumOverruns: 4

Cambie OverrunAction a 'drop'. 'drop' indica que la función waitfor regresará en el siguiente paso de tiempo, incluso si LastPeriod es mayor que la propiedad DesiredRate. Esto efectivamente elimina la iteración que se perdió debido a la ejecución más lenta del código.

rate.OverrunAction = 'drop';

Restablecer el objeto Rate y comenzar el bucle.

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.0002 1.0008 0.9999 2.0022 0.9977 0.9999 2.0002 0.9996 1.0004 0.9993 2.0012 0.9993 1.0003 0.9994 1.0004 2.0005]
           NumPeriods: 16
        AveragePeriod: 1.2501
    StandardDeviation: 0.4478
          NumOverruns: 4

El uso de la acción de ejecución excesiva 'drop' dio como resultado 16 períodos, mientras que 'slip' dio como resultado 20 períodos. Esta diferencia se debe a que 'slip' no esperó hasta el siguiente intervalo en función de la velocidad deseada. Básicamente, el uso de 'slip' intenta mantener la propiedad AveragePeriod lo más cerca posible de la tasa deseada. El uso de 'drop' garantiza que el código se ejecutará en un intervalo uniforme con respecto a DesiredRate y se omitirán algunas iteraciones.

Consulte también

| (ROS Toolbox) | (Robotics System Toolbox)