# Polygon motion not in sync with what is coded, issues not seen with different speed

Monitor info:

• 59.4 cm width, 57 cm distance
• 1920 x 1080, 60 Hz, 92 ppi
• 18 deg (one-sided) vertical max

What are you trying to achieve?:

• A circle (3x3), moving at 0.2 deg / frame vertically, that is capable of switching directions when hitting edge of screen. Its size makes it hit the edge at 15 deg, thus it must switch directions when `Target.pos[1] >= 15 or Target.pos[1] <= -15`

What did you try to make it work?:

``````###begin experiment
moveSpeed = 0.2
``````
``````###begin routine; can ignore, purely randomizing target
#annuli data
if Position == [-19.5, 0]:
Target = leftAnnuli
leftStop = 1200
rightStop = 60

if Position == [19.5, 0]:
Target = rightAnnuli
rightStop = 1200
leftStop = 60

#positions of R/L annuli
movingUp = None

direction = randint(0, 2)

if direction == 0:
moveSpeed *= -1
``````
``````###each frame - the guts
#beginning mvmt
if frameN >= 61:
Target.pos[1] += moveSpeed
Target._needVertexUpdate = True

if Target.pos[1] >= 15 or Target.pos[1] <= -15:
moveSpeed *= -1
print('Switching frame - ', frameN)

if Target.pos[1] == 3:
print('3 = ', frameN)

if Target.pos[1] == 9:
print('9 = ', frameN)

if Target.pos[1] == 15:
print('15 = ', frameN)
``````

What specifically went wrong when you tried that?:

• Through logging its positions, it seems that the movement is out of sync with the frames. Not sure if thatâ€™s a good analysis of the problem - donâ€™t know how else to word it.
• It should be hitting 3 deg at the 75th frame, 9 deg at 105th, 15 deg at 135th. Instead, it seems to be out of sync slightly in the beginning, then later the incongruence is greatly magnified, likely through switching directions. Note that it never logs 3 deg or 15 deg, since it seems to skip over those.

Note
This doesnâ€™t occur if I set the speed to 0.25 deg / frame. See these logs:

Could it be that my frame rate isnâ€™t truly 60 Hz? Data file indicates that it flies around 59.9xx. Anyone know how to deal with this?

There is a general principle here that computers arenâ€™t perfect at dealing with floating point numbers. They are natively built to deal with integers (at heart, binary). So while you can always compare two integers exactly, you canâ€™t expect to reliably compare two floating point values.

i.e. a computer will store an integer of `3` exactly. So you can do tests like this reliably:

``````if number_of_targets == 3: # comparing two integers
# do something every time
``````

But a floating point value of `3.0` may actually be stored as `3.0000000000000004` or `2.999999999997` or similar. It will vary depending on your platform and the series of calculations taken to reach it. So never try to test two floating point values for equality. Instead, take the absolute difference between the two and see if it is below some acceptable minimum threshold.

``````if Target.pos[1] == 3.0:
``````

try something like:

``````if abs(Target.pos[1] - 3.0) <= 0.0001:
``````

The size of the threshold is situation-dependent. In this case, an angle smaller than one ten thousandth of a degree is not meaningful, so we can use that as a (relatively high) threshold.

Note that the deviations you are seeing are absolutely infinitesimal fractions of the width of a pixel. The target will be displayed exactly where you intend it to be, as its displayed location will effectively be rounded to the nearest integer pixel value. There is not only no perceptible difference between a stimulus intended to be displayed at `3.0` degrees and one whose coordinate is `3.00000000000000004` degrees, but also no physical difference, due to the quantised nature of a pixel-based display.

This issue of floating point precision is not a restriction unique to PsychoPy or Python, but common to all computing systems.

Hey, thank you. That is some great insight and itâ€™s completely fixed the discrepancies. I really appreciate your help.

Glad that helped. The frustrating thing about this is that it does sometimes work (as you found when stepping by `0.25` instead of `0.2`) - it is the unpredictability that can make this issue hard to track down. Everyone falls for it at some stage.

1 Like

Socratic paradox hits me every time I post hereâ€¦