WorldViz User Forum

WorldViz User Forum (https://forum.worldviz.com/index.php)
-   Vizard (https://forum.worldviz.com/forumdisplay.php?f=17)
-   -   Script blocked while Vizard-window resizes (https://forum.worldviz.com/showthread.php?t=5288)

willpower2727 02-17-2015 05:48 AM

Script blocked while Vizard-window resizes
 
Hi I was hoping someone here might help me understand this issue I'm having:

I'm running a multi-thread python script where one of the threads gets motion data from a camera system and another thread takes that information and updates the objects in the main worldviz window.

Sometimes, there is a short 500 millisecond block of the script execution and thus a 500 ms delay in updating the main window. Without spewing out a ton of details, I'll just say this 500 ms gap in the flow of data is unacceptable. I need to avoid similar delays.

The only known cause I have determined so far is that moving/re-sizing (by mouse drag) the main window onto a second monitor can cause it. I have come to understand that this might be Windows7 changing "modes" and blocking the python script until the window is finished moving/re-sizing. I have gotten around this issue by setting up a vizcore.cfg file that initializes the window the way I need it, thus avoiding the re-sizing problem.

However, I feel certain that there will be other events that can cause this type of block to happen. Can anyone help me understand how worldviz handles update commands? For example, if I call vizobject.setPosition(), is there some kind of response that my python script is waiting to receive from worldviz?

Any help or insight will be helpful and appreciated. Thanks!

P.S. I'm using Vizard 4, windows 7

Jeff 02-23-2015 01:36 AM

If Vizard's main update loop gets blocked then it's possible to see the script freeze. If you're still having an issue with this it's best to post Vizard code that shows the problem.

willpower2727 02-23-2015 07:45 AM

Ok here is a slightly simplified version of my code, however I doubt anyone else will be able to run it due to the lack of having all the dependencies.

Code:

import socket
import sys
import io
import re
from xml.etree import ElementTree
import viz
import threading
import Queue
import time
import json
import vizact

viz.go()

#initialize objects
global scalorxx
scalorxx = 0.6667
global targetL
targetL = 1
global targetR
targetR = 1
global targettol
targettol = 0.05
global boxL
boxL = viz.addChild('target.obj',color=(0.063,0.102,0.898),scale=[0.1,(targettol+0.04)*0.75,0.0125])
boxL.setPosition([-0.2,targetL*scalorxx,0])
global boxR
boxR = viz.addChild('target.obj',color=(0.063,0.102,0.898),scale=[0.1,(targettol+0.04)*0.75,0.0125])
boxR.setPosition([0.2,targetR*scalorxx,0])
global cursorR
cursorR = viz.add('box3.obj', color=viz.RED, scale=[0.1,0.1,0.0125], cache=viz.CACHE_NONE)
cursorR.setPosition([0.2,0,0.05])
global cursorL
cursorL = viz.add('box3.obj', color=viz.GREEN, scale=[0.1,0.1,0.0125], cache=viz.CACHE_NONE)
cursorL.setPosition([-0.2,0,0.05])
global HistBallR
HistBallR = viz.add('footprint2.obj', color=viz.YELLOW, scale=[0.03,0.03,0.1], cache=viz.CACHE_NONE)
HistBallR.setPosition([0.2,targetR*scalorxx,0])
HistBallR.setEuler(0,0,0)
HistBallR.alpha(0.8)
global HistBallL
HistBallL = viz.add('footprint2.obj', color=viz.YELLOW, scale=[0.03,0.03,0.1], cache=viz.CACHE_NONE)
HistBallL.setPosition([-0.2,targetL*scalorxx,0])
HistBallR.setEuler(180,0,0)
HistBallL.alpha(0.8)

viz.MainView.setPosition(0, 0.5, -1.5)
viz.MainView.setEuler(0,0,0)

global histzR
global histzL
histzR = 0
histzL = 0

global rstridetime
global lstridetime
rstridetime = 0
lstridetime = 0

#global RHS
#global LHS
#RHS = 0
#LHS = 0
global FNold
FNold = 0

#definition for the first thread
def UpdateViz(root,q,savestring,q3):
        timeold = time.time()
        RHS = 0
        LHS = 0

        while not endflag.isSet():
                global targetR
                global targettol
                global histzR
                global histzL
                global rstridetime
                global lstridetime
#                print(Queue.Queue.qsize(q))
                root = q.get()#look for the next frame data in the thread queue
                q.task_done()
#                print(Queue.Queue.qsize(q))
                timediff = time.time()-timeold

                lp1 = root.find(".//Forceplate_0/Subframe_9/F_z")#Left Treadmill
                rp1 = root.find(".//Forceplate_1/Subframe_9/F_z")#Right Treadmill

                temp = rp1.attrib.values()
                Rz = float(temp[0])#cast forceplate data as float
                temp3 = lp1.attrib.values()
                Lz = float(temp3[0])
                cursorR.setScale(0.1,rstridetime*scalorxx,0.01250)
                cursorL.setScale(-0.1,lstridetime*scalorxx,0.01250)
                #check for gait events
                if (Rz < -30) & (histzR >= -30):#HS condition
                        HistBallR.setPosition([0.2, rstridetime*scalorxx, 0])
                        RHS = 1
                        if (abs(rstridetime-targetR) <= targettol):
                                boxR.color( viz.WHITE )
                        else:
                                boxR.color( viz.BLUE )
                        rstridetime = 0
                else:
                        rstridetime = rstridetime+timediff
                        RHS = 0
                       
                if (Lz < -30) & (histzL >= -30):
                        HistBallL.setPosition([-0.2, lstridetime*scalorxx, 0])
                        LHS = 1
                        if (abs(lstridetime-targetL) <= targettol):
                                boxL.color( viz.WHITE )
                        else:
                                boxL.color( viz.BLUE )
                        lstridetime = 0
                else:
                        lstridetime = lstridetime+timediff
                        LHS = 0
               
                timeold = time.time()
                histzR = Rz
                histzL = Lz
               
                #send some data to be saved
                fn = root.find(".//FrameNumber")#Left Treadmill
                fnn = fn.attrib.values()
#                print(fnn[0])
               
                savestring = [int(fnn[0]),Rz,Lz,RHS,LHS]
#                print(sys.getsizeof(savestring))
                q3.put(savestring)
#                print(q3.qsize())
        q3.join()
        print("data has all been gotten")

#definition of tcp thread
def runclient(root,q):
       
        #illegal characters to remove from string later before going to xml
        RE_XML_ILLEGAL = u'([\u0000-\u0008\u000b-\u000c\u000e-\u001f\ufffe-\uffff])' + \
                                        u'|' + \
                                        u'([%s-%s][^%s-%s])|([^%s-%s][%s-%s])|([%s-%s]$)|(^[%s-%s])' % \
                                          (unichr(0xd800),unichr(0xdbff),unichr(0xdc00),unichr(0xdfff),
                                          unichr(0xd800),unichr(0xdbff),unichr(0xdc00),unichr(0xdfff),
                                          unichr(0xd800),unichr(0xdbff),unichr(0xdc00),unichr(0xdfff))
        HOST = 'localhost'#IP address of CPP server
        PORT = 50008
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        print 'Socket created'
        print 'Socket now connecting'
        s.connect((HOST,PORT))
        s.send('1')#send initial request for data

        while not endflag.isSet():
                global FNold
                data = s.recv(50)#receive the initial message
                data3 = data[:3]#get first 3 letters
                if (data3 == "New"):
                        nextsizestring = data[3:]#get the integer after "New"
                        nextsizestring2 = nextsizestring.rstrip('\0')#format
                        nextsize = int(nextsizestring2,10)#cast as type int
#                        print("Next Packet is size: ")
#                        print(nextsize)
                        s.send('b')#tell cpp server we are ready for the packet
                        databuf = ''#initialize a buffer
                        while (sys.getsizeof(databuf) < nextsize+21):
                                data = s.recv(nextsize)#data buffer as a python string
                                databuf = databuf + data#collect data into buffer until size is matched
#                        print(sys.getsizeof(databuf))
                        root = ElementTree.ElementTree(ElementTree.fromstring(databuf))#create the element tree
                        q.put(root)#place the etree into the threading queue
                        fn = root.find(".//FrameNumber")#Left Treadmill
                        fnn = fn.attrib.values()
                        FN = int(fnn[0])
                        if (FN - FNold >= 20) & (FNold != 0):
                                print("gap larger than 20 has occured")

                        FNold = FN
                elif (data3 != "New"):
                        print("WARNING! TCP SYNCH HAS FAILED")
                        break
                if not data: break
                s.send('b')

        s.close()
        q.join()

#thread that saves data (no problems here)
def savedata(savestring,q3):

        #initialize the file
        mst = time.time()
        mst2 = int(round(mst))
        mststring = str(mst2)+'StrideTime.txt'
        print("Data file created named:")
        print(mststring)
        file = open(mststring,'w+')
        json.dump(['FrameNumber','Rfz','Lfz','RHS','LHS'],file)
        file.close()
       
        file = open(mststring,'a')#reopen for appending only
        print('file is open for appending')
        while not endflag.isSet():
#                print(q3.empty())
                savestring = q3.get()#look in the queue for data to write
                print(savestring)
                q3.task_done()
                if savestring is None:
                        continue
                else:
                        json.dump(savestring, file)
        print("savedata stop flag raised, finishing...")
        while 1:
                try:
                        savestring = q3.get(False,2)
                except:
                        savestring = 'g'
#                print(savestring)
                if savestring  == 'g':
                        break
                        print("data finished write to file")
                else:
                        json.dump(savestring, file)
                        print("data still writing to file")
               
        print("savedata finished writing")
        file.close()

#event callback when user presses 'q'
endflag = threading.Event()
def raisestop(sign):
        print("stop flag raised")
        endflag.set()
        t1.join()
        t2.join()
        t4.join()
        viz.quit()

root = ''#empty string
savestring = ''
q = Queue.Queue()#initialize the queue
q3 = Queue.Queue()#intialize another queue for saving data
#create threads for client
t1 = threading.Thread(target=runclient,args=(root,q))
t2 = threading.Thread(target=UpdateViz,args=(root,q,savestring,q3))
t4 = threading.Thread(target=savedata,args=(savestring,q3))

t1.daemon = True
t2.daemon = True
t4.daemon = True
#start the threads
t1.start()
t2.start()
t4.start()

print("\n")
print("press 'q' to stop")
print("\n")

vizact.onkeydown('q',raisestop,'t')


Jeff 02-24-2015 06:51 AM

You might try using Vizard's director function to read the motion data instead of creating your own thread. It's designed for cases such as this where you need to perform some IO operation without halting rendering of the scene.


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

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