Skip to content

Commit d06fe46

Browse files
committed
Add test of period math, and improve comments.
Signed-off-by: Mike Stitt <[email protected]>
1 parent 1b009f5 commit d06fe46

File tree

2 files changed

+50
-8
lines changed

2 files changed

+50
-8
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import pytest
2+
3+
from wpilib.timedrobotpy import _Callback
4+
5+
def test_calcFutureExpirationUs() -> None:
6+
cb = _Callback(func=None, periodUs=20_000, expirationUs=100)
7+
assert cb.calcFutureExpirationUs(100) == 20_100
8+
assert cb.calcFutureExpirationUs(101) == 20_100
9+
assert cb.calcFutureExpirationUs(20_099) == 20_100
10+
assert cb.calcFutureExpirationUs(20_100) == 40_100
11+
assert cb.calcFutureExpirationUs(20_101) == 40_100
12+
13+
cb = _Callback(func=None, periodUs=40_000, expirationUs=500)
14+
assert cb.calcFutureExpirationUs(500) == 40_500
15+
assert cb.calcFutureExpirationUs(501) == 40_500
16+
assert cb.calcFutureExpirationUs(40_499) == 40_500
17+
assert cb.calcFutureExpirationUs(40_500) == 80_500
18+
assert cb.calcFutureExpirationUs(40_501) == 80_500
19+
20+
cb = _Callback(func=None, periodUs=1_000, expirationUs=0)
21+
assert cb.calcFutureExpirationUs(1_000_000_000_000_000_000) == 1_000_000_000_000_001_000
22+
assert cb.calcFutureExpirationUs(1_000_000_000_000_000_001) == 1_000_000_000_000_001_000
23+
assert cb.calcFutureExpirationUs(1_000_000_000_000_000_999) == 1_000_000_000_000_001_000
24+
assert cb.calcFutureExpirationUs(1_000_000_000_000_001_000) == 1_000_000_000_000_002_000
25+
assert cb.calcFutureExpirationUs(1_000_000_000_000_001_001) == 1_000_000_000_000_002_000
26+
27+

subprojects/robotpy-wpilib/wpilib/timedrobotpy.py

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -55,16 +55,29 @@ def calcFutureExpirationUs(
5555
self, currentTimeUs: microsecondsAsInt
5656
) -> microsecondsAsInt:
5757
# increment the expiration time by the number of full periods it's behind
58-
# plus one to avoid rapid repeat fires from a large loop overrun. We assume
59-
# currentTime ≥ startTimeUs rather than checking for it since the
58+
# plus one to avoid rapid repeat fires from a large loop overrun.
59+
#
60+
# This routine is called when either:
61+
# this callback has never ran and self.expirationUs is
62+
# TimedRobot._starttimeUs and we are calculating where the first
63+
# expiration should be relative to TimedRobot._starttimeUs
64+
# or:
65+
# this call back has ran and self.expirationUs is when it was scheduled to
66+
# expire and we are calculating when the next expirations should be relative
67+
# to the last scheduled expiration
68+
#
69+
# We assume currentTime ≥ self.expirationUs rather than checking for it since the
6070
# callback wouldn't be running otherwise.
61-
# todo does this math work?
62-
# todo does the "// periodUs * periodUs" do the correct integer math?
63-
return (
64-
self.expirationUs
65-
+ self._periodUs
71+
#
72+
# We take when we previously expired or when we started: self.expirationUs
73+
# add + self._periodUs to get at least one period in the future
74+
# then calculate how many whole periods we are behind:
75+
# ((currentTimeUs - self.expirationUs) // self._periodUs)
76+
# and multiply that by self._periodUs to calculate how much time in full
77+
# periods we need to skip to catch up, and add that to the sum to calculate
78+
# when we should run again.
79+
return self.expirationUs + self._periodUs \
6680
+ ((currentTimeUs - self.expirationUs) // self._periodUs) * self._periodUs
67-
)
6881

6982
def setNextStartTimeUs(self, currentTimeUs: microsecondsAsInt) -> None:
7083
self.expirationUs = self.calcFutureExpirationUs(currentTimeUs)
@@ -129,6 +142,8 @@ def __init__(self, period: wpimath.units.seconds = kDefaultPeriod) -> None:
129142
"""
130143
super().__init__(period)
131144

145+
# All periodic functions created by addPeriodic are relative
146+
# to this self._startTimeUs
132147
self._startTimeUs = _getFPGATime()
133148
self._callbacks = _OrderedList()
134149
self._loopStartTimeUs = 0

0 commit comments

Comments
 (0)