2016-05-16 2 views
2

J'essaye de planifier une action (un bip sonore) dans Vizard en utilisant Python. Cependant, je veux que le bip se produise à certains moments depuis le début de l'essai. Ce que j'ai jusqu'ici me donne (par exemple, après l'avoir exécuté une fois) une liste de fois fois: [1.89229142 5.2610474 9.86058804 11.43137033 13.87078666] et joue le son à ce qui semble être des intervalles variables et imprime les éléments de la liste de synchronisation mentionnée ci-dessus. C'est juste que ce n'est pas en utilisant ces éléments en tant que secondes/timings à jouer.Comment planifier une action à différents moments à partir d'une liste en Python

Ma question est: Comment faire pour que Python sache que ce ne sont pas seulement des nombres, mais des minutages depuis le début de la fonction/procès? Probablement je suis censé utiliser time.time() quelque part, mais je ne suis pas sûr de la logique de la façon d'y arriver.

import time 
import numpy as np 
import viztask            


### Start Vizard ### 
viz.go() 


### Cue sound ### 
cue = viz.addAudio('cues\dong.wav') 
cueDuration = cue.getDuration() 

### Timings ### 

def uniform_min_range(a, b, n, min_dist): 
    while True: 
     times = np.random.uniform(a, b, size=n) 
     np.sort(times) 
     if np.all(np.diff(times) >= min_dist): 
      return times 

def timings(): 
    global times 
    times = uniform_min_range(0, 20, 5, 1.0) 
    print "times: ", times 


def main(): 
    global times 
    timesIndex =0 
    for x in range(len(times)): 
     cuetime = times[timesIndex] 
     cue.play() 
     print 'cue' 
     print cuetime 
     yield viztask.waitTime(cueDuration + cuetime) 
     cue.stop() 
     timesIndex = timesIndex + 1 



timings() 
viztask.schedule(main()) 

EDIT basé sur la suggestion de jacantebury dans le commentaire à sa réponse: Ceci est le code de travail ferme. Je suppose que le décalage dans le timing est lié au framerate, comme le suggère Jacanterbury.

import time 
import viztask 

viz.go() 

times= [1.76493425, 3.10174059, 4.49576803, 10.99379224, 18.84178369] #at these times since onset of script, a text "hello world" should be printed 
time_intervals=[] 
prev=0 

for val in times: 
    time_intervals.append(val - prev) 
    prev = val 
    print time_intervals 

intervalsIndex = 1 

start = time.time() 

def main(): 
    global intervalsIndex 
    yield viztask.waitTime(time_intervals[0]) 
    for x in range (len(time_intervals)): 
     print ('hello world', '- now: ', time.time()- start) 
     yield viztask.waitTime(time_intervals[intervalsIndex]) 
     intervalsIndex = intervalsIndex + 1 

viztask.schedule(main()) 

Cela me donne maintenant ('bonjour', '- maintenant:', 1,7820000648498535) ('bonjour', '- maintenant:', 3,133000135421753) ('bonjour', « - maintenant: ', 4.5350000858306885) (' hello world ',' - now: ', 11.040000200271606) (' hello world ',' - now: ', 18.897000074386597) qui est très proche de mes éléments de liste (c.-à-d. ce que je voulais initialement).

+0

Qu'est-ce qui ne fonctionne pas actuellement? –

+0

Salut busfault! Il ne semble pas que l'on traite les éléments de la liste comme des «temps» écoulés depuis le début. Peut-être que j'ai besoin de définir un début de quelque sorte, mais alors je ne sais pas quoi faire avec elle .. – Spica

+0

Y at-il une raison particulière d'utiliser 'global'? Je ne suis pas sûr si cela a quelque chose à voir avec votre problème. –

Répondre

2

busfault est correct sur votre utilisation de la boucle FOR.

Pour le tester en utilisant yield, vous devez schedule la fonction appelée. par exemple.

import viz 
import viztask 

def myfunc(): 

    for cuetime in (2,3,4): 

     mydata = yield viztask.waitTime(cuetime) 
     print('Wait time: ' , cuetime, ' - Elapsed time: ', mydata.elapsed) 

viz.go() 
viztask.schedule(myfunc) 

qui produit une sortie comme ça ...

('Wait time: ', 2, ' - Elapsed time: ', 2.002306576051085) 
('Wait time: ', 3, ' - Elapsed time: ', 3.016386045747815) 
('Wait time: ', 4, ' - Elapsed time: ', 4.016321305293874) 

Vous verrez que le décalage dans le temps est généralement lié à votre taux de trame (60 Hz ~ de 16.7ms)

Après édition par OP: .. un moyen facile de tester si les différences de synchronisation sont dues à la synchronisation de trame est d'éteindre la synchronisation verticale (V-Sync) pour votre carte graphique et de la relancer - je soupçonne que vous obtiendrez beaucoup mieux les horaires, mais vous risquez d'avoir du cadre qui se déchire sur votre écran - alors c'est votre appel quant à ce qui est le plus important pour vous, la qualité de l'image ou la précision du timing. Une autre option pour prouver son rafraîchissement est simplement de changer votre taux de rafraîchissement et de voir si les différences de temps varient en conséquence. Je remarque que vous avez recommencé à utiliser le temps.time() - ce sera MOINS précis que d'utiliser l'objet de retour de waitTime selon ma démo (ie mydata = yield viztask.waitTime(cuetime) ...)

+0

Merci jacanterbury! J'ai changé la commande d'impression pour imprimer ('Now:', viz.tick(), 'Wait time:', cuetime, '- Temps écoulé:', mydata.elapsed). Juste pour montrer que l'impression elle-même n'arrive pas aux horaires de la liste. Je me demande pourquoi je reçois ('Maintenant:', 2.376125239373963, 'Temps d'attente:', 2, '- Temps écoulé:', 2.0099786548416336) ('Maintenant:', 5.378527175519809, 'Temps d'attente:', 3, '- Écoulé temps: ', 3.002428450099741) (' Maintenant: ', 9.3816914591142,' Temps d'attente: ', 4,' - Temps écoulé: ', 4.003159436957659) – Spica

+0

Cela signifie que le "Maintenant" et le "Temps écoulé" ne sont pas les mêmes , même si le "temps écoulé" et le "temps d'attente" sont équivalents. – Spica

+0

A partir des pages d'aide: .tick(): Cette commande renvoie l'heure actuelle, en secondes, depuis le démarrage du script. Le temps écoulé est l'heure à laquelle waitTime() a attendu – jacanterbury

0

Je pense que votre problème est ici: avec une boucle for vous n'avez pas besoin de répéter, il le fait automatiquement. Ce que cela va faire itérer votre liste times chaque fois que la mise cuetime à la valeur spécifique

En outre, pas cue.stop() ne sera pas appelé jusqu'à ce que tout rendement se fait, je pense? Vous pouvez vérifier cela avec un appel d'impression après la yield que je ne suis pas aussi familier avec yield

def main(): 
    global times 
    for cuetime in times: 
     cue.play() 
     print 'cue' 
     print cuetime 
     yield viztask.waitTime(cueDuration + cuetime) 
     cue.stop() 
+0

Merci busfault, la fonction et la boucle look maintenant! Et vous avez raison sur le rendement. Mais le problème est toujours qu'il ne traite pas ces éléments comme des timings (jouer à ces secondes depuis le début du procès). Je suis maintenant essayer d'envelopper ma tête autour des fonctions de la minuterie. Peut-être devrais-je dire quelque part que ces éléments sont apparus. – Spica