Asynchronous rate limiter¶
Non-blocking loop frequency limiter for asyncio.
Note that there is a difference between a (non-blocking) rate limiter and a (blocking) synchronous clock, which lies in the behavior when skipping cycles. A rate limiter does nothing if there is no time left, as the caller’s rate does not need to be limited. On the contrary, a synchronous clock waits for the next tick, which is by definition in the future, so it always waits for a non-zero duration.
- class loop_rate_limiters.async_rate_limiter.AsyncRateLimiter(frequency, name='rate limiter', warn=True)¶
Loop frequency regulator.
Calls to
sleep()
are non-blocking most of the time but become blocking close to the next clock tick to get more reliable loop frequencies.This rate limiter is in essence the same as in the one from pymanoid. It relies on the event loop time never jumping backwards nor forwards, so that it does not handle such cases contrary to e.g. rospy.Rate.
- name¶
Human-readable name used for logging.
- warn¶
If set (default), warn when the time between two calls exceeded the rate clock.
- property measured_period: float¶
Period measured at the end of the last call to
sleep()
.This duration is in seconds.
- property next_tick: float¶
Time of next clock tick.
- async remaining()¶
Get the time remaining until the next expected clock tick.
- Return type:
float
- Returns:
Time remaining, in seconds, until the next expected clock tick.
- property slack: float¶
Slack duration computed at the last call to
sleep()
.This duration is in seconds.
- async sleep(block_duration=0.0005)¶
Sleep the duration required to regulate the loop frequency.
This function is meant to be called once per loop cycle.
- Parameters:
block_duration (
float
) – the coroutine blocks the event loop for this duration (in seconds) before the next tick. It is non-blocking before that.
Note
A call to this function will be non-blocking except for the last
block_duration
seconds of the limiter period.The block duration helps trim period overshoots and brings the measured period much closer to the desired one (< 2% average error vs. 8-12% average error with a single asyncio.sleep). Empirically a block duration of 0.5 ms gives good behavior at 400 Hz or lower.