Skip to content

Commit 5459f35

Browse files
author
David Butterworth
committed
Add VanDerCorputSampleGenerator() which generates an optimal, non-linear sequence of t values to sample.
1 parent f98018d commit 5459f35

File tree

1 file changed

+66
-0
lines changed

1 file changed

+66
-0
lines changed

src/prpy/util.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,6 +1049,72 @@ def SampleTimeGenerator(start, end, step=1):
10491049
yield float(end)
10501050

10511051

1052+
def VanDerCorputSampleGenerator(start, end, step=2):
1053+
"""
1054+
This wraps VanDerCorputSequence() in a way that's useful for
1055+
collision-checking.
1056+
1057+
Generates a sequence of values from start to end, with specified
1058+
step size, using an approximate binary Van der Corput sequence.
1059+
1060+
The end value is also returned if it's more than half the
1061+
distance from the closest value.
1062+
1063+
For example, on the interval [0.0, 13.7], the sequence is:
1064+
[0.0, 13.7, 12.0, 6.0, 4.0, 8.0, 2.0, 10.0]
1065+
1066+
@param float start: The start value of the sequence.
1067+
@param float end: The last value of the sequence.
1068+
@param float step: The step-size between values.
1069+
1070+
@returns generator: A sequence of float values.
1071+
"""
1072+
import itertools
1073+
1074+
# The duration, rounded to nearest step-size
1075+
mod_end = int(end - (end % step))
1076+
steps_to_take = mod_end / float(step)
1077+
leftover_time = end - float(mod_end)
1078+
1079+
# Keep a list to make sure we return all the sample values
1080+
times_sampled = [False for i in range(mod_end+1)]
1081+
1082+
vdc = VanDerCorputSequence(start, steps_to_take)
1083+
vdc_seq = itertools.islice(vdc, steps_to_take+1)
1084+
count = 0
1085+
for s in vdc_seq:
1086+
# Snap this sample value to the desired step-size
1087+
idx = int( step * numpy.round(s) )
1088+
if (idx % step) != 0:
1089+
idx = idx + 1
1090+
1091+
# If required, return the actual end-point value (a float) as
1092+
# the 2nd sample point to be returned. Then the next sample
1093+
# point is the end-point rounded to step-size.
1094+
if count == 1:
1095+
if leftover_time > (step / 2.0):
1096+
yield float(end)
1097+
1098+
count = count+1
1099+
while True:
1100+
if times_sampled[idx] == False:
1101+
times_sampled[idx] = True
1102+
yield float(idx)
1103+
break
1104+
else:
1105+
# We have already sampled at this value of t,
1106+
# so lets try a different value of t.
1107+
decimals = (s % 1)
1108+
if decimals < 0.5:
1109+
idx = idx - step
1110+
if (idx < 0): # handle wrap past zero
1111+
idx = int(end - 1)
1112+
else:
1113+
idx = idx + step
1114+
if (idx > end): # handle wrap past end
1115+
idx = int(start + 1)
1116+
1117+
10521118
def GetCollisionCheckPts(robot, traj, include_start=True, start_time=0.,
10531119
first_step=None, epsilon=1e-6):
10541120
"""

0 commit comments

Comments
 (0)