How to continously run a piece of code while simultaneously checking for a condition?

Asked by Martin Roth on 2017-11-05

Hi. How can you make Sikuli check if a statement / condition is being fulfilled while simultaneously executing another piece of code?

What I'm trying to achieve:
* While there isn't an image in a region, keep running a piece of code
* If the image appears (while running the code), stop running piece of code

Lacking approach:

Settings.WaitScanRate = 0.25
someRegion = Region(x1, y1, x2, y2)
someImage = "image.png"

def danceLeft(): #Just some functions
def danceRight():
def danceAcrossTheHallway():

someCondition = None
while someCondition == None:
    danceLeft()
    danceRight()
    danceAcrossTheHallway()
    someCondition = someRegion.exists(someImg, 1)
else:
   print("Stopped dancing; the image has appeared!")

The problem is obvious - the script won't check the condition until it reaches the very last line in the while loop, and while it will be checking, the next iteration of the loop will be held on pause. How can this be avoided? I want it run a while loop without any interruptions while checking for a condition meanwhile, and stop the loop while the condition (an image appearing in a region, in this case) is met.
My hobby-level programming skills have so far mostly consisted of solving everything by doing silly loops, but something tells me there must be a better way. Cheers for the wonderful piece of software that is Sikuli; it's really amazing! Cheers. :D

Question information

Language:
English Edit question
Status:
Solved
For:
Sikuli Edit question
Assignee:
No assignee Edit question
Solved by:
Manfred Hampl
Solved:
2017-11-05
Last query:
2017-11-05
Last reply:
2017-11-05
RaiMan (raimund-hocke) said : #1

so if you want to leave the loop, when a condition is met, you have to use break.
If the loop does not have any condition to be check at every loop run beginning, the use while True (endless).
endless loops should have any terminating condition check in its body, so the script does not need to be killed by brute force.

#someCondition = None # not needed here
#while someCondition == None:
while True; # starts endless loop
    danceLeft()
    danceRight()
    danceAcrossTheHallway()
    if someRegion.exists(someImg, 1): # check terminating condition
        print("Stopped dancing; the image has appeared!")
        break
# next statement after loop is exited

RaiMan (raimund-hocke) said : #2

... and here is faq 1437, that I wrote on loops in Python scripts 6 years ago ;-)

Martin Roth (captain-rage) said : #3

Thanks for your reply and the link. I didn't know about 'break'. Certainly it will be handy in the future, as well as the rest of the FAQ. :) However, this does not entirely answer the question. The problem is that I want the functions to continue running, without having to stop and wait for the image explicitly (using 'exists'). I mean, to eliminate all such pauses. If I put multiple copies of the condition check, between the defined functions, it will have to wait before executing the next function.

while True; # starts endless loop
    danceLeft()
    if someRegion.exists(someImg, 1): # check terminating condition, losing 1 seconds
        print("Stopped dancing; the image has appeared!")
        break
    danceRight()
    if someRegion.exists(someImg, 1): # check terminating condition, losing another 1 second
        print("Stopped dancing; the image has appeared!")
        break
    danceAcrossTheHallway()
    if someRegion.exists(someImg, 1): # check terminating condition, losing yet another 1 second
        print("Stopped dancing; the image has appeared!")
        break

Perhaps this could work, if I make the condition check is short enough, but it doesn't feel optimal.
I was hoping there would be a way of continuously watching for an image in a region, while running / looping some functions in parallel, and stopping / breaking the loop while the condition is met.

Otherwise the condition check will have to be inserted everywhere, or atleast every now and then, in the loop, and the ride won't be smooth.

RaiMan (raimund-hocke) said : #5

@Manfred
Good idea, but I guess this will make it for him even more complex.

@Martin
an image check always costs some time.
So the only chance is to minimise this "pause" in the script.

1. step: use
exists(image, 0)

which does only one search. depending on region and image size this may reduce the search time to some 10 millisecs.

2. step: make the search region as small as possible

Martin Roth (captain-rage) said : #6

Excellent, thanks! "It is possible to let the script wait for the completion of an observation or let the observation run in background (meaning in parallel)" sounds exactly like what I was looking for. It is difficult refer to the documentation, unless you know the jargon, but now it makes sense. Thanks alot RaiMan and Manfred. This helped alot. :)

Martin Roth (captain-rage) said : #7

Cheers for the additional feedback, RaiMan. I will try both approaches and see how they work out!

Martin Roth (captain-rage) said : #8

Thanks Manfred Hampl, that solved my question.