psychopy.org | Reference | Downloads | Github

Moving stimuli along curved path

I’m trying to move an image along a curved path, mainly from the coordinates (-5, -3) to (5, 3) along following the equation f(x) = -0.04x^2 -2. I’m trying to understand what I’m doing incorrectly here because the image moves on a diagonal line then the program stops. How should I go about creating a curve along which to plot the image?

import os
import time 
from psychopy import visual, event, core, monitors
import glob
from math import log10, floor, pow
import numpy as np


win = visual.Window([600, 600], units = 'pix', monitor = 'testMonitor', color = [.4,.7,1], colorSpace = "rgb")

keys = event.BuilderKeyResponse()

path = "/Users/Desktop/"
dot1 = visual.ImageStim(win, image = path + "crab.png", size = [5,5], units = 'deg', pos = (-5, -3))
FrameN = 50
speed = 1  # initial speed in whatever unit the stimulus use.
angle = 45  # initial angle in degrees
x_change = np.cos(angle) * speed  # initial
y_change = np.sin(angle) * speed  # initial

dot1.draw()
win.flip()

sign = 1

while True:
    if FrameN == 50:
        angle_current = np.rad2deg(np.arctan(y_change / float(x_change)))  # float to prevent integer division
        # More new stuff: Change direction angle (in degrees)
        x_change = np.cos(angle_current + 0.001) * speed
        y_change = np.sin(angle_current + 0.001 * sign) * speed

        dot1.pos+=(x_change, y_change)

        if dot1.pos[0] >= 0 or dot1.pos[1] >= 0:
            sign *= -1
            print('y-direction switched')
            break

        if dot1.pos[0] < -5:
            dot1.pos = (-5, -3)
            print("x-change and y -change : {0}, {1} at {2}, {3}".format(x_change, y_change, dot1.pos[0], dot1.pos[1]))


        if dot1.pos[0] >= 5:
            dot1.pos = (5, -3)
            print("x-change and y -change : {0}, {1} at {2}, {3}".format(x_change, y_change, dot1.pos[0], dot1.pos[1]))
            break

        if dot1.pos[1] < -3:
            print('hit lower bound')
            break
    FrameN += 1
        



    dot1.draw()
    win.flip()

    if event.getKeys(keyList=["escape"]):
        core.quit()

core.wait(4)
core.quit()

I think there are up to three things going on here but they mostly boil down to math issues.

  1. Numpy expects radians for its cos() and sin() functions, and you’re feeding it something in degrees.

  2. The x_change and y_change aren’t really going to do what you want here, I don’t think. Rather than adding them to the existing values of x and y, I think what you want to do is set x and y by plugging the sin and cos terms into a bigger equation.

  3. On the whole I’m not sure that you need to use sin and cos at all, since you have an equation that already spells out the relationship between the x and y coordinates. You should just be able to do this:

for i in range(0, 50):
    x = dot1.pos[0] + speed
    y = .04*(x^2) - 2
    dot1.pos = (x, y)
    dot1.draw()
    win.flip()