Skip to content

Instantly share code, notes, and snippets.

@cmower
Last active June 11, 2024 06:18
Show Gist options
  • Save cmower/ea7143715caf05dab3fce8950b4ef715 to your computer and use it in GitHub Desktop.
Save cmower/ea7143715caf05dab3fce8950b4ef715 to your computer and use it in GitHub Desktop.
Convenience class for sleeping in a loop at a specified rate (based on rospy.Rate)
from time import time_ns, sleep
class Rate(object):
"""
Convenience class for sleeping in a loop at a specified rate
"""
def __init__(self, hz, reset=True):
"""
Constructor.
@param hz: hz rate to determine sleeping
@type hz: float
@param reset: if True, timer is reset when time moved backward. [default: True]
@type reset: bool
"""
self.last_time = time_ns()
self.sleep_dur = 1e9 / float(hz)
self._reset = reset
def _remaining(self, curr_time):
"""
Calculate the time remaining for rate to sleep.
@param curr_time: current time
@type curr_time: L{Time}
@return: time remaining
@rtype: L{Time}
"""
# detect time jumping backwards
if self.last_time > curr_time:
self.last_time = curr_time
# calculate remaining time
elapsed = curr_time - self.last_time
return self.sleep_dur - elapsed
def remaining(self):
"""
Return the time remaining for rate to sleep.
@return: time remaining
@rtype: L{Time}
"""
curr_time = time_ns()
return self._remaining(curr_time)
def sleep(self):
"""
Attempt sleep at the specified rate. sleep() takes into
account the time elapsed since the last successful
sleep().
@raise ValueError: if time is set backwards
"""
curr_time = time_ns()
try:
sleep(1e-9 * self._remaining(curr_time))
except ValueError:
if not self._reset:
raise
self.last_time = time_ns()
return
self.last_time = self.last_time + self.sleep_dur
# detect time jumping forwards, as well as loops that are
# inherently too slow
if curr_time - self.last_time > self.sleep_dur * 2:
self.last_time = curr_time
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment