psychopy.org | Reference | Downloads | Github

Faster rotation

URL of experiment:


Description of the problem:
Hello,
I am trying to code an experiment where I have 2 aligned dots (creating an imaginary line), and with the left/right arrow key I want to move them to control their imaginary orientation line.

In real time, I want to modify the positions of 2 dots by pressing left/right arrow keys.
I managed to make it work, but the rotation is VERY slow.

Any idea on how to speed up this?

This is what I did:
Routine: N_p_Resp

Begin Experiment:


xStart = 0;
yStart = 0;
xStart2 = 0;
yStart2 = 0;

  Dot1 = new visual.Polygon ({
    win: psychoJS.window, name: 'Dot1', units : 'height', 
    edges: 99, size:[0.05, 0.05],
    ori: 0, pos: [xStart, yStart],
    lineWidth: 1, lineColor: new util.Color([1, 1, 1]),
    fillColor: new util.Color([1, 1, 1]),
    opacity: 1, depth: -5, interpolate: true,
  });

  Dot2 = new visual.Polygon ({
    win: psychoJS.window, name: 'Dot2', units : 'height', 
    edges: 99, size:[0.05, 0.05],
    ori: 0, pos: [xStart2, yStart2],
    lineWidth: 1, lineColor: new util.Color([1, 0, 0]),
    fillColor: new util.Color([1, 0, 0]),
    opacity: 1, depth: -5, interpolate: true,
  });

Begin Routine:

BarOrientation = Math.floor(Math.random() * 360 - 0);
BarOrientation2 = BarOrientation+180;
// bar_p_3.setOri((- BarOrientation));
error = GabOrPractice2 - BarOrientation;
ErrorMessage = "Stripe Orientation=" + (GabOrPractice2) + "°   Bar Orientation=" + BarOrientation + "°   Error=" + error + "°\n   Hit space when you're done";

radiusDeg = .1

angleR = BarOrientation * (Math.PI/180);
line1Response = angleR;
xStart = Math.sin(angleR) * radiusDeg;
yStart = Math.cos(angleR) * radiusDeg;

angleR2 = BarOrientation2 * (Math.PI/180);
line1Response2 = angleR2;
xStart2 = Math.sin(angleR2) * radiusDeg;
yStart2 = Math.cos(angleR2) * radiusDeg;

Dot1.setAutoDraw(true);
Dot2.setAutoDraw(true);

Each Frame:

 if(BarOrientation > 359) {
     BarOrientation -= 360;
 }

 if(BarOrientation2 > 359) {
     BarOrientation2 -= 360;
 }

angleR = BarOrientation * (Math.PI/180);
xStart = Math.sin(angleR) * radiusDeg
yStart = Math.cos(angleR) * radiusDeg
angleR2 = BarOrientation2 * (Math.PI/180);
xStart2 = Math.sin(angleR2) * radiusDeg
yStart2 = Math.cos(angleR2) * radiusDeg

Dot1.setPos([(xStart), yStart]);
Dot1.setAutoDraw(true);
Dot2.setPos([(xStart2), yStart2]);
Dot2.setAutoDraw(true);

End Routine:

  Dot1.setAutoDraw(false);
  Dot2.setAutoDraw(false);

Where is the code that updates the bar orientation in response to the key presses?

Thanks for your reply Michael!

I put that code in a separate routine at the beginning of the loop (J_Randomiz), in Begin Routine

document.body.style.cursor = 'none';
var keys = new Array();
var mytime = setInterval(RotateBar, 25);
window.addEventListener('keydown',doKeyDown,true);
window.addEventListener('keyup',doKeyUp,true);

function doKeyDown(evt){
    keys[evt.keyCode] = true;
}

function doKeyUp(evt){
    keys[evt.keyCode] = false;
}

function RotateBar() {  
    if (37 in keys && keys[37]) {
        BarOrientation -= 1;
        BarOrientation2 -= 1;
    };

    if (39 in keys && keys[39]) {
        BarOrientation += 1;
        BarOrientation2 += 1;      
    };
}

So change the BarOrientation by more than 1 for a single key press.

In order to avoid changing in multiple places I would create a new variable called, for example, rotationSpeed and change BarOrientation by rotationSpeed

You can then play about with the value of rotationSpeed to find the number that works for you. I’d try something like 5 to start with.

It is a good idea, but it makes me sacrifice sensibility in the movement (if rotation is 1 I can deal with 360°, if 2 is 180°).
I wonder if there is a way to optimize the code I have (I put it into functions in another routine for this reason), or this is the best speed I will ever get with PsychoPy online.

I tried with a bar adjustment with a single rotation and the speed was definitely faster…

Mauro

The way I did my screenscale routine I change the size by five times as much it the keys are being pressed more often than twice per second so you can move fast and then get finer changes if you slow down

mmm it is a good idea, do you have any code to share on that?

Either way I would need the rotation to have a stable speed :frowning:
I really wonder if there is a way to speed up all of this code, maybe with functions, or putting the code in different routines or parts of the code…can’t believe the rotation is so slow just by moving 2 dots…

Mauro

Here’s my code from Screen Scale https://pavlovia.org/Wake/screenscale

keys=event.getKeys()

if len(keys):
    if t-oldt<.5:
        dscale=5*dbase
        oldt=t
    else:
        dscale=dbase
        oldt=t
    if 'space' in keys:
        continueRoutine=False
    elif 'up' in keys:
        y_scale=round((y_scale+dscale)*10000)/10000
    elif 'down' in keys:
        y_scale=round((y_scale-dscale)*10000)/10000
    elif 'left' in keys:
        x_scale=round((x_scale-dscale)*10000)/10000
    elif 'right' in keys:
        x_scale=round((x_scale+dscale)*10000)/10000
    screen_height=round(vsize*10/y_scale)/10
    text_bottom.text='X Scale = '+str(x_scale)+unittext+' per cm, Y Scale = '+str(y_scale)+unittext+' per cm\nScreen height = '+str(screen_height)+' cm\n\nPress the space bar when done'
    ccimage.size=[x_size*x_scale, y_size*y_scale]
    

If you want 1 degree at 60 Hz then I guess you’re wanting a revolution in 6 seconds. How long is is currently taking?

As Wakefield is indicating the code isn’t slow from a performance sense. You are checking the keyboard and updating the screen probably at 60 Hz, which is far faster than anyone can press keys. It is slow from a design sense: the issue is that for each keypress, you only rotate the bar by 1 degree. So you either need to simply increase the value of the per-keypress increment, or do something crafty like Wakefield suggests, with variable speeds depending on keypress rate.

2 Likes