WorldViz User Forum  

Go Back   WorldViz User Forum > Vizard

Reply
 
Thread Tools Rate Thread Display Modes
  #1  
Old 12-05-2016, 09:47 PM
Vaquero Vaquero is offline
Member
 
Join Date: Nov 2015
Posts: 62
Question how to check if specified number of targets are in proximity sensor?

Hey there! Can anyone tell me what's the best way to check, if a specified number of targets are inside a proximity sensor?

I have an experiment in which a person is required to move a specified number of targets into a proximity sensor in order to continue. On top of that, this should be done within a specified time, e.g. 5 seconds.

I tried something like:
Code:
...
...
def task1(numActiveTargets):
    import random 
    numTrials = 100
    
    for trial in xrange(numTrials):
        targetSensor = random.choice(sensors) #a list of sensors
        activeTargets = manager.getActiveTargets(sensor=targetSensor)
        if len(activeTargets) < numActiveTargets:
            yield vizproximity.waitEnter(sensor = targetSensor, target = targets) #seems to be activated by any target in list of targets
            
        yield viztask.waitTime(5)

def experiment():
    yield task1(2)
    yield task1(3)

viztask.schedule(experiment)
...but it wouldn't work. Like, I'd have to check for 5 seconds if my chosen sensor contains at least 3 targets, for example.
Reply With Quote
  #2  
Old 12-06-2016, 04:14 AM
rajnishv rajnishv is offline
Member
 
Join Date: Jan 2016
Location: Kalina,Sanatcruz(East),Mumbai,Maharashtra,India
Posts: 94
Hi Vaquero ,
You might be looking for this
Call these methods as per logic:

1)<Manager>.getTargets()
2)<Manager>.getActiveTargets(sensor=None)

Thank You!!!
Reply With Quote
  #3  
Old 12-06-2016, 07:35 AM
Vaquero Vaquero is offline
Member
 
Join Date: Nov 2015
Posts: 62
Thank you for your reply. I already use manager.getActiveTargets(sensor=targetSensor) in my code sample above. So unfortunately your reply doesn't provide any logic to the problem of how to check for 5 seconds long if at least 3 targets occupy a sensor at the same time, and if not, start the next trial.
Reply With Quote
  #4  
Old 12-06-2016, 11:52 AM
Jeff Jeff is offline
WorldViz Team Member
 
Join Date: Aug 2008
Posts: 2,471
One way to do this is create a custom event that's triggered when 3 targets are inside a sensor. Write a function that's called every frame, checks to see how many targets are in the sensor, and sends the event. In the viztask function, use the viztask.waitAny command to wait for either the custom event or 5 seconds:

Code:
waitTargets = viztask.waitEvent(THREE_TARGETS_EVENT)
waitTime = viztask.waitTime(5)

for trial in xrange(numTrials):
	d = yield viztask.waitAny( [ waitTargets, waitTime ] )
	
	if d.condition is waitTargets:
		print 'targets entered'
	else:
		print '5 seconds passed'
Reply With Quote
  #5  
Old 12-19-2016, 02:14 AM
Vaquero Vaquero is offline
Member
 
Join Date: Nov 2015
Posts: 62
Thanks Jeff, that brought me closer to a solution, but I can't get it to work.
In each trial there's another sensor that needs to trigger the event, but whatever I do, I can't seem to get the functions/events recognize the newly chosen sensor.

First I thought, well, I would only need to check for the number of targets in the sensor, if a target enters the sensor. Here's some pseudo-code:

Code:
TRIGGER_ACTIVATED_EVENT = viz.getEventID('TRIGGER_ACTIVATED_EVENT')
def checkTrigger(manager,requiredSensor):
    activeTargets = manager.getActiveTargets(sensor=requiredSensor)
    if len(activeTargets) == len(targets):
        time = viz.tick()
        viz.sendEvent(TRIGGER_ACTIVATED_EVENT,requiredSensor.name,time)

def myTask():
    targets = [target1,target2,target3]
    sensors = [sensor1,sensor2,sensor3]
    triggerSensor = someSensor

    def EnterSensor(e):
        checkTrigger(e.manager,triggerSensor)

    for sensor in sensors:
        manager.addSensor(sensor)
        manager.onEnter(sensor, EnterSensor)

    results = yield mySubTask()

def mySubTask():
    waitTargets = viztask.waitEvent(TRIGGER_ACTIVATED_EVENT)
    waitTime = viztask.waitTime(5)

    for trial in xrange(100):
        triggerSensor = random.choice(sensors)
	d = yield viztask.waitAny( [ waitTargets, waitTime ] )
	
	if d.condition is waitTargets:
		print 'targets entered'
	else:
		print '5 seconds passed'

viztask.schedule(myTask)
But the EnterSensor/checkTrigger function is always checking for 'someSensor' and not updating to the new triggerSensor in each trial (IDs were the same for triggerSensor object in both functions, I checked)

Now I tried using
checkingTrigger = vizact.onupdate(0,checkTrigger,manager,triggerSens or)
and using checkingTrigger.setEnabled(viz.<OFF/ON>) when I need it, but it's the same problem in that it only recognizes the very first triggerSensor.

Could you please give a more complete, working example?
Reply With Quote
  #6  
Old 12-19-2016, 06:59 AM
Vaquero Vaquero is offline
Member
 
Join Date: Nov 2015
Posts: 62
It works by doing the checkingTrigger = vizact.onupdate(0,checkTrigger,manager,triggerSens or) part inside the loop after triggerSensor = random.choice(sensors) was called, and removing the EventFunction at the end of the loop.
Reply With Quote
  #7  
Old 12-27-2016, 04:15 PM
Vaquero Vaquero is offline
Member
 
Join Date: Nov 2015
Posts: 62
Concurrency?

There's another requirement for the task I need to implement, but can't figure out how to accomplish it. All the targets shall reach the given sensor concurrently (within tolerance) to count as a success.
So there's, for example, a 5 seconds time limit in which the sensor must be reached, but within that time limit the targets must reach the sensor within a shorter amount of time, e.g. 1 second. For now, the user should be able to try this within the time limit until she succeeds.

I guess I should utilize starttimer, so I'd have to start it, when the first target enters the sensor and before it elapses, all targets should have followed. If one target exits the sensor before the timer elapsed, it should be stopped (killtimer). But if I put the starttimer in the on_enter function of the sensor, then each target starts a new timer. I suppose there should be an event that marks a success only when the TRIGGER_ACTIVATED_EVENT occured while the timer event did not yet occur.
I tried setting a global variable to true and false, but since each onEnter-call sets it to true, it's useless.

Here's a condensed debug version of my script so far:
Code:
import viz
import vizcam
import vizshape
import vizproximity
import viztask
import random

def use_pivot_cam():
	cam = vizcam.PivotNavigate(distance=1.5,center=(0,0,0))
	cam.rotateUp(30)
	viz.cam.setHandler(cam)

def create_proximity_manager():
	manager = vizproximity.Manager()
	manager.setDebug(viz.ON)
	debugEventHandle = vizact.onkeydown('1',manager.setDebug,viz.TOGGLE)
	return manager
	
def add_debug_tracker(targetName,controlScheme):
	axis = vizshape.addAxes(length=0.1)
	if controlScheme == 0:
		tracker = vizcam.addKeyboardPos()
	elif controlScheme == 1:
		tracker = vizcam.addKeyboardPos(forward=viz.KEY_UP,backward=viz.KEY_DOWN,left=viz.KEY_LEFT,right=viz.KEY_RIGHT,up=viz.KEY_PAGE_UP,down=viz.KEY_PAGE_DOWN)
	else:
		tracker = vizcam.addKeyboardPos(forward='i',backward='k',left='j',right='l',up='p',down='o')
	viz.link(tracker,axis)
	target = vizproximity.Target(axis)
	target.name = targetName
	return target

def add_sensor(position,shape,color,name):
	if shape == 'torus':
		sensorShape = vizshape.addTorus(0.15,0.025,24,32,vizshape.AXIS_Z)
		sensorShape.name = 'TorusShape'
		sensorRadius = 0.175
	elif shape == 'sphere':
		sensorShape = vizshape.addSphere(0.1)
		sensorShape.name = 'SphereShape'
		sensorRadius = 0.1
	else:
		sensorShape = vizshape.addCube(0.3)
		sensorRadius = 0.15
	sensorShape.setPosition(position)
	sensorShape.color(color)
	sensor = vizproximity.Sensor(vizproximity.Sphere(sensorRadius), source=sensorShape)
	sensor.name = name
	return sensor
	
TRIGGER_ACTIVATED_EVENT = viz.getEventID('TRIGGER_ACTIVATED_EVENT')
bTimerActive = False
def check_trigger(manager,requiredSensor,numTargets):
	activeTargets = manager.getActiveTargets(sensor=requiredSensor)
	#print('Timer active: ', bTimerActive) #Debug
	if len(activeTargets) == numTargets and bTimerActive:
		viz.sendEvent(TRIGGER_ACTIVATED_EVENT,requiredSensor)

def on_trigger_activated(trigger):
    triggerSound = trigger.getSourceObject().playsound('quack.wav', viz.PLAY)
    print('TRIGGER ACTIVATED')
    return
viz.callback(TRIGGER_ACTIVATED_EVENT,on_trigger_activated)

def experiment():
	manager = create_proximity_manager()
	sensors = []
	sensors.append(add_sensor([0,0,0.3],'torus',viz.VIOLET,'torus'))
	sensors.append(add_sensor([0,0,-0.3],'sphere',viz.ORANGE_RED,'sphere'))
	for sensor in sensors:
		manager.addSensor(sensor)	
	targets = []
	targets.append(add_debug_tracker('axis1',0))
	targets.append(add_debug_tracker('axis2',1))
	targets.append(add_debug_tracker('axis3',2))
	for target in targets:
			manager.addTarget(target)
	numTargets = len(manager.getTargets())
	
	waitTargets = viztask.waitEvent(TRIGGER_ACTIVATED_EVENT)
	timeLimit = 5
	waitTime = viztask.waitTime(timeLimit)
	
	global bTimerActive
	bTimerActive = False
	
	def on_timer_elapsed(timerID):
		print 'Elapsed time: {:.2f} seconds'.format(viz.elapsed())
		global bTimerActive		
		bTimerActive = False

	viz.callback(viz.TIMER_EVENT,on_timer_elapsed)
	
	concurrencyTolerance = 1.0 # Time frame for accepting targets as entering simulataneously.
	def enter_sensor(e):
		print('{0} entered {1} .'.format(e.target.name,e.sensor.name))
		print('Starting timer.')
		viz.starttimer(0,concurrencyTolerance)
		global bTimerActive
		bTimerActive = True
	
	def exit_sensor(e):
		print('{0} exited {1}.'.format(e.target.name,e.sensor.name))
		print('Killing timer.')
		viz.killtimer(0)
		global bTimerActive
		bTimerActive = False
	
	manager.onEnter(None, enter_sensor)
	manager.onExit(None, exit_sensor)

	i = 0
	while True:
		i += 1
		triggerSensor = random.choice(sensors)
		
		print('Press spacebar to start next trial:\nMove {0} targets concurrently (tolerance: {2}s) into {3} sensor within {1} seconds.'.format(numTargets,timeLimit,concurrencyTolerance,triggerSensor.name))
		yield viztask.waitKeyDown(' ')
		print("Trial {} started.".format(i))
		#ToDo: Trigger shall be reached by all targets within concurrencyTolerance.
		checkingTrigger = vizact.onupdate(0,check_trigger,manager,triggerSensor,numTargets)

		d = yield viztask.waitAny([waitTargets, waitTime])
		if d.condition is waitTargets:
			print('Success!')
		else:
			print('Failure! {} seconds passed'.format(timeLimit))

		#checkingTrigger.remove()
		checkingTrigger.setEnabled(viz.OFF)

use_pivot_cam()
viztask.schedule(experiment)
viz.go()
Does anybody have an idea how to solve this?
Reply With Quote
  #8  
Old 12-27-2016, 05:40 PM
Vaquero Vaquero is offline
Member
 
Join Date: Nov 2015
Posts: 62
I think I got it. I just check for the boolean status of the timer before I start a new one AND make sure, there are not already other targets in the sensor.

Code:
	def enter_sensor(e):
		print('{0} entered {1}.'.format(e.target.name,e.sensor.name))
		numTargets = len(e.manager.getActiveTargets(sensor=e.sensor))
		global bTimerActive
		if not bTimerActive and numTargets == 1:
			print('Starting timer.')
			viz.starttimer(0,concurrencyTolerance)
			bTimerActive = True
But maybe there's a more elegant solution?
Reply With Quote
  #9  
Old 12-27-2016, 06:23 PM
Vaquero Vaquero is offline
Member
 
Join Date: Nov 2015
Posts: 62
Unfortunately, when 2 targets arrive at the exact same time at the sensor, the timer isn't started because numtargets > 1. I didn't think it was possible or probable, but it is. So my solution is still not good enough.
Reply With Quote
Reply

Thread Tools
Display Modes Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
delaying proximity reaction makes sensor unresponsive for the time of delay jelly Vizard 4 11-23-2016 05:20 AM
sensor radius bug? lalechuza Vizard 7 08-25-2015 06:57 AM
Orientation selective (Viewing Vector) Proximity Sensor lmGehrke Vizard 2 03-17-2015 01:31 PM
Proximity Sensor Problem kmkm Vizard 3 03-04-2014 12:54 PM
CompositeShape proximity sensor mhtong Vizard 1 09-24-2012 12:18 PM


All times are GMT -7. The time now is 08:19 PM.


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