WorldViz User Forum

WorldViz User Forum (https://forum.worldviz.com/index.php)
-   Vizard (https://forum.worldviz.com/forumdisplay.php?f=17)
-   -   Need help with a project (https://forum.worldviz.com/showthread.php?t=1890)

mberkes 03-09-2009 11:29 AM

Need help with a project
 
So I'm VERY new to programming and WorldViz, and only have the basics down. I am, unfortunately, on a tight schedule though and need to create a simple project before April.
The project simply requires a table, 5 objects, and 9 locations. The 5 objects are randomly placed at one of the 9 locations each, and then after 3 seconds of viewing, the scene clears for 10 seconds. The scene should then reappear, with one random object moved to a location close to it's original. The viewer makes a judgement based on which object moved, and then the next 'trial' starts. I can do the timing functions (I think) and have the 3dmax models for the objects, but am unsure of how to set up the random assignments as well as 'clearing' the scene, and how to record the response.
Any help with those functions is appreciated, thank you!

Jeff 03-09-2009 01:05 PM

This will turn the scene's visibility on and off based on a timer and reset the objects randomly in one of nine specified positions when the scene comes back

check out the Vizard docs to learn how to write to files so you can record user responses.

Code:

import viz
viz.go()

viz.MainView.move(0,0,-10)

#keep nine positions in an array
pos = [[-4,0,0],[-3,0,0],[-2,0,0],[-1,0,0],[0,0,0],[1,0,0],[2,0,0],[3,0,0],[4,0,0]]

box = viz.add('box.wrl')
ball = viz.add('ball.wrl')
whiteball = viz.add('white_ball.wrl')


import random
def sceneOn():

        #set objects to 3 different random positions
        rand_numbers = [0,1,2,3,4,5,6,7,8]
        random.shuffle(rand_numbers)

        box.setPosition(pos[rand_numbers[0]])
        ball.setPosition(pos[rand_numbers[1]])
        whiteball.setPosition(pos[rand_numbers[2]])

        viz.MainScene.visible(viz.ON)
        vizact.ontimer2(2,0,sceneOff)


def sceneOff():
       
        viz.MainScene.visible(viz.OFF)
        vizact.ontimer2(2,0,sceneOn)

sceneOn()


mberkes 03-10-2009 09:03 AM

Hey thanks! This provides a good start. I've added in another function which brings up the object array and let's the viewer make a choice as to which object switched positions before starting again with sceneOn, but how do you make it to only move one object randomly? As it is, all the objects move when the scene turns on again.

mberkes 03-13-2009 10:37 AM

Still can't figure out how to just move one object from the initial randomised scene to the returned scene. Actually, can't figure out a lot of things haha. I have a mouseclick selecting an object and should (hopefully) record the data of which object was clicked (which should also match with the object that moved, though can't figure that out, obviously), but I can't disable the mouseclicking before I need it. Any help?

Jeff 03-13-2009 11:43 AM

To move one of the objects to a new place, you need to randomly select one of your objects and then randomly select one of the available positions to move it to.

Code:

import viz
viz.go()

viz.MainView.move(0,0,-10)

#keep nine positions in an array
pos = [[-4,0,0],[-3,0,0],[-2,0,0],[-1,0,0],[0,0,0],[1,0,0],[2,0,0],[3,0,0],[4,0,0]]

#add objects to an array
box = viz.add('box.wrl')
ball = viz.add('ball.wrl')
whiteball = viz.add('white_ball.wrl')

objects = [box,ball,whiteball]


import random

rand_positions = []
def sceneOn(num):

        global rand_positions
       
        positions = [0,1,2,3,4,5,6,7,8]
       
        if num == 1:
               
                #set objects to 3 different random positions
                rand_positions = random.sample(positions,3)
               
                objects[0].setPosition(pos[rand_positions[0]])
                objects[1].setPosition(pos[rand_positions[1]])
                objects[2].setPosition(pos[rand_positions[2]])

                vizact.ontimer2(2,0,sceneOff)

        elif num == 2:
               
                #choose one object to move randomly and leave others in there places
               
                #first get available positions
                diff_list = [item for item in positions if not item in rand_positions]
                rand_position = random.sample(diff_list,1)[0]
               
                #choose one of the objects
                rand_obj = random.randint(0,2)
               
                #set the randomly chosen object to the new random position
                objects[rand_obj].setPosition(pos[rand_position])
                print 'object ' + str(rand_obj) + ' moved to position ' + str(rand_position) 
               
        viz.MainScene.visible(viz.ON)
       

def sceneOff():
       
        viz.MainScene.visible(viz.OFF)
        vizact.ontimer2(2,0,sceneOn,2)

sceneOn(1)


mberkes 03-17-2009 12:48 PM

Thanks, that works great. I have an issue though where it runs through once perfectly, but then on any time after that, more than one object moves. I'll post the code, and would you be able to see where the issue lies? I added in a function ('prep') that keeps the screen blank and waits for a space press before going to 'sceneOn', and a mouseclick goes to 'prep'. Thanks

Code:

import random

objects = [bottle, candle, clamp, lock, wood]

def prep():
        viz.MainScene.visible(viz.OFF)
        vizact.onkeydown(' ', sceneOn,1)

rand_positions = []
def sceneOn(num):

        global rand_positions
       
        positions = [0,1,2,3,4,5,6,7,8]
       
        if num == 1:
               
                #set objects to 5 different random positions
                rand_positions = random.sample(positions,5)
               
                objects[0].setPosition(pos[rand_positions[0]])
                objects[1].setPosition(pos[rand_positions[1]])
                objects[2].setPosition(pos[rand_positions[2]])
                objects[3].setPosition(pos[rand_positions[3]])
                objects[4].setPosition(pos[rand_positions[4]])

                vizact.ontimer2(3,0,sceneOff)

        elif num == 2:
               
                #choose one object to move randomly and leave others in their places
               
                #first get available positions
                diff_list = [item for item in positions if not item in rand_positions]
                rand_position = random.sample(diff_list,1)[0]
               
                #choose one of the objects
                rand_obj = random.randint(0,4)
               
                #set the randomly chosen object to the new random position
                objects[rand_obj].setPosition(pos[rand_position])
                print 'object ' + str(rand_obj) + ' moved to position ' + str(rand_position) 
               
        viz.MainScene.visible(viz.ON)
       

def sceneOff():
       
        viz.MainScene.visible(viz.OFF)
        vizact.ontimer2(10,0,sceneOn,2)

prep()

Again, this isn't the complete code, but where I would think the issue lies.

Jeff 03-17-2009 01:16 PM

That code just goes through one trial. To see why following trials are not working I'd have to see the code you added for that

mberkes 03-19-2009 09:11 AM

I have this code for the mouseclick:

Code:

def mouseclick(button):
        if button == viz.MOUSEBUTTON_LEFT:
                object = viz.pick()
        if object.valid():
                data = 'Selected' + items
                position = object.get(viz.POSITION)
                position[1] += 1.2
                arrow.translate(position)
                arrow.visible(viz.ON)
                #record response
                response_data.write(data)
                #flush internal buffer
                response_data.flush()

viz.callback(viz.MOUSEDOWN_EVENT,mouseclick)
#go to blank scene
vizact.whilemousedown(viz.MOUSEBUTTON_LEFT,prep)
#disable mouse navigation
viz.mouse(viz.OFF)

It just goes back to prep, and I would think that it should just repeat what happened before, but no such luck. Still can't disable the mouseclick where I need to or write data, but looking into that. There's also a lot of incomplete code in there, or unnecessary code I need to get rid of (like the arrow over objects)

Jeff 03-19-2009 01:35 PM

each time prep is called another vizact object is created.
Code:

def prep():
        viz.MainScene.visible(viz.OFF)
        vizact.onkeydown(' ', sceneOn,1)

The first time in prep when spacebar is pressed sceneOn gets called 1 time, if you click your mouse again and then the space bar, there are two vizact objects calling sceneOn twice, and so on. That's why more than one object is moving.

Probably the best thing to do is to re-arrange your code using viztask. Waiting for mouseclicks, keypresses, and timers can all be done within the task function. Check out the documentation on viztask and let me know if you have any questions.

mberkes 03-26-2009 09:44 AM

Didn't have time to work on this recently, but just a quick question about viztask. Do I need to rewrite the previous functions into a task, or just include them into my task with yield statements? Can I write the whole project under one task? Thanks

Jeff 03-26-2009 11:18 AM

You just need one task function for this and can call sceneOn from there. You could take out vizact.ontimer from sceneOn and use viztask.waittime instead in the task function

mberkes 05-21-2009 09:29 AM

So after a two month absense from working on this, I'm back at it, and realised I don't know what I'm doing! My code seems to be a mess with extraneous, or at least poorly written, code and the experiment doesn't work how I'd like. Here's my code:

Code:

import viz
import viztask
import random
viz.go()

viz.MainView.move(0,1.4,-13)
#add pathway to bring objects from
viz.res.addPath('C:\Users\Matyi\Desktop\2009 Experiments')
#field of view at 45 degrees
viz.fov(45)


#keep nine positions in an array
pos = [[-2.667, 0.0, -1.524],[1.51892, 0.0, -2.53492],[-0.82042, 0.0, 2.89052],[2.286, 0.0, -0.04572],[-1.17856, 0.0, -1.30302],[1.8415, 0.0, 2.06248],[-0.94996, 0.0, -2.85242],[-3.15722, 0.0, 0.82042],[-0.20828, 0.0, 0.84328]]


#add table, keep it in position, scale
table = viz.add('bluetable.wrl')
table.setPosition(0,0,0)
table.setScale(.5,.5,.5)
table.disable(viz.PICKING)

#add objects and scale
bottle = viz.add('bottle.wrl')
bottle.setScale(.5,.5,.5)
bottle.center(0,0,0)

candle = viz.add('candle.wrl')
candle.setScale(.5,.5,.5)
candle.center(0,0,0)

clamp = viz.add('clamp.wrl')
clamp.setScale(.5,.5,.5)
clamp.center(0,.5,0)
clamp.rotate(0,150,90)

lock = viz.add('lock.wrl')
lock.setScale(.5,.5,.5)
lock.center(0,0,.0)

wood = viz.add('wood.wrl')
wood.setScale(.5,.5,.5)
wood.center(0,0,0)

#make a list with the objects in it
objects = [bottle, candle, clamp, lock, wood]

#disable mouse navigation
viz.mouse(viz.OFF)



def prep():
        viz.MainScene.visible(viz.OFF)
        #vizact.onkeydown(' ', sceneOn,1)

rand_positions = []
def sceneOn(num):

        global rand_positions
       
        positions = [0,1,2,3,4,5,6,7,8]
       
        if num == 1:
               
                #set objects to 5 different random positions
                rand_positions = random.sample(positions,5)
               
                objects[0].setPosition(pos[rand_positions[0]])
                objects[1].setPosition(pos[rand_positions[1]])
                objects[2].setPosition(pos[rand_positions[2]])
                objects[3].setPosition(pos[rand_positions[3]])
                objects[4].setPosition(pos[rand_positions[4]])

                #vizact.ontimer2(3,0,sceneOff)

        elif num == 2:
               
                #choose one object to move randomly and leave others in their places
               
                #first get available positions
                diff_list = [item for item in positions if not item in rand_positions]
                rand_position = random.sample(diff_list,1)[0]
               
                #choose one of the objects
                rand_obj = random.randint(0,4)
               
                #set the randomly chosen object to the new random position
                objects[rand_obj].setPosition(pos[rand_position])
                print 'object ' + str(rand_obj) + ' moved to position ' + str(rand_position) 
               
        viz.MainScene.visible(viz.ON)
       

def sceneOff():
       
        viz.MainScene.visible(viz.OFF)
        #vizact.ontimer2(10,0,sceneOn,2)



#define the file to save subject responses
response_data = open('exp_data','a')
       
#use this; viztask is better
def experiment():
       
        while True:
                viz.MainScene.visible(viz.OFF)
                yield viztask.waitKeyDown(' ')
                yield sceneOn(1)
                viztask.waitTime(3)
                yield sceneOff()
                viztask.waitTime(10)
                yield sceneOn(2)
                d = viz.Data()
                yield viztask.waitMouseDown(viz.MOUSEBUTTON_LEFT, d)
                print str(objects), 'was selected at', d.time

viztask.schedule( experiment() )


#viz.callback(viz.MOUSEDOWN_EVENT,mouseclick)
#go to blank scene
#vizact.whilemousedown(viz.MOUSEBUTTON_LEFT,prep)
       

       

#input subject number at start
subject = viz.input('What is the participant number?')

If I could get some help here telling me what's unnecessary, what's good and that I should keep expanding on, that would be amazing. In particular, my problems include:

- subject number can be blank and it still accepts this, I need that to change
- data file doesn't exist; do I create a spreadsheet and it stores there, or automatically makes one with the correct code?
- pressing space now just moves an object with no timing at all or scene change
- clicking anywhere at all makes the scene blank and gives me lines saying [vizard object yada yada yada moved positions] with nothing relevant, or the object name

Thanks for your help, my complete lack of understanding with vizard is getting somewhat discouraging.

Gladsomebeast 05-22-2009 02:30 PM

Don't give up hope yet. Clearly you have some work ahead of you, but listing what your missing is a start.

First, lets fix your stimulus presentation. Your syntax in the experiment task is incorrect. Place "yield" statments in front of 'viztask.wait' functions. Do not put a yield in front of plain functions like 'sceneOn.'

Code:

def experiment():
       
        while True:
                viz.MainScene.visible(viz.OFF)
                yield viztask.waitKeyDown(' ')
                sceneOn(1)
                yield viztask.waitTime(3)
                sceneOff()
                viztask.waitTime(10)
                sceneOn(2)
                d = viz.Data()
                yield viztask.waitMouseDown(viz.MOUSEBUTTON_LEFT, d)
                pickedObject = viz.pick()
                recordTrialResponse(pickedObject, d.time)

Also i added a viz.pick call to get the geometry the mouse clicked on. It pases the result to a new recordTrialResponse function. I'ed make this function check if it was the correct object and write the results to a file.

Vizard's installation directory has an example directory called file_io that has filewriting examples. If you put a tab between each of your data points and a new line between reach response the data file should import into Matlab or Excel nicely.

mberkes 05-27-2009 11:44 AM

Hey thanks for the help. Haven't quite got the data writing down yet, but my code now looks like this:

Code:

def Experiment():
       
        while True:
                viz.MainScene.visible(viz.OFF)
                for n in range(4):
                        for i in range(5):
                                yield viztask.waitKeyDown(' ')
                                sceneOn(1)
                                yield viztask.waitTime(3)
                                viz.MainScene.visible(viz.OFF)
                                yield viztask.waitTime(3)
                                sceneOn(2)
                                yield viztask.waitMouseDown(viz.MOUSEBUTTON_LEFT, d)
                                viz.MainScene.visible(viz.OFF)
                                                               
                        for j in range(5):
                                yield viztask.waitKeyDown(' ')
                                sceneOn(1)
                                group.rotate(0,1,0,0, viz.ABS_GLOBAL)
                                yield viztask.waitTime(3)
                                viz.MainScene.visible(viz.OFF)
                                yield viztask.waitTime(3)
                                sceneOn(3)
                                yield viztask.waitMouseDown(viz.MOUSEBUTTON_LEFT, d)
                                viz.MainScene.visible(viz.OFF)

SceneOn(3) calls a rotated version of the scene now. A quick question though:
I have the following code for when an object moves:
Code:

print 'object ' + str(rand_obj) + ' moved to position ' + str(rand_position)
How can I make it to show the object name instead of number? Right now it says 'object x moved to position y', but I'd like it to say the actual object name instead.

Gladsomebeast 05-27-2009 11:54 AM

.getFilename


All times are GMT -7. The time now is 05:12 AM.

Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Copyright 2002-2023 WorldViz LLC