View Single Post
  #7  
Old 12-27-2016, 03: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