diff --git a/tests/single-step/test-ui.py b/tests/single-step/test-ui.py index a971561befe..a7e2a690cdf 100755 --- a/tests/single-step/test-ui.py +++ b/tests/single-step/test-ui.py @@ -44,7 +44,7 @@ def print_state(): c.home(2) l.wait_for_home([1, 1, 1, 0, 0, 0, 0, 0, 0]) c.mode(linuxcnc.MODE_AUTO) - + # # run the .ngc test file, starting from the special line @@ -56,18 +56,56 @@ def print_state(): def mod_5_is_0(x): return abs((x+epsilon) % 5) < 2*epsilon -# Take first step + +def wait_complete_step(): + + '''The normal `linuxcnc.command.wait_complete()` function does not + understand single-stepping. It waits for the `state` to return to + `RCS_DONE` but this does not happen when single-stepping, `state` + stays at `RCS_EXEC` while waiting for the next step. + + This function instead waits for status.task.execState to tell us + that Task is no longer waiting for Motion in any way.''' + + timeout = 5.0 + start = time.time() + + # Wait for the command to be acknowledged by Task (FIXME or is it motion?). + while time.time() - start < timeout: + s.poll() + if s.echo_serial_number >= c.serial: + break + time.sleep(0.1) + + # Wait for Task to be done waiting for Motion. + while time.time() - start < timeout: + s.poll() + if s.exec_state not in [ linuxcnc.EXEC_WAITING_FOR_MOTION, linuxcnc.EXEC_WAITING_FOR_MOTION_AND_IO, linuxcnc.EXEC_WAITING_FOR_MOTION_QUEUE ]: + return + time.sleep(0.1) + + raise SystemExit('timeout in wait_complete_step()') + + +# Take first three steps (these cause no motion). +c.auto(linuxcnc.AUTO_STEP) +c.auto(linuxcnc.AUTO_STEP) c.auto(linuxcnc.AUTO_STEP) +wait_complete_step() count = 0 while True: s.poll() + if s.interp_state == linuxcnc.INTERP_IDLE: + sys.stderr.write("Finished: Detected program finish\n") + break + (x, y) = (h["Xpos"], h["Ypos"]) if mod_5_is_0(x) and mod_5_is_0(y): - # Both axes on goal; make next step and let motion start + # Both axes on goal; command the next step and wait for it to finish. sys.stderr.write("Taking step from X%.2f Y%.2f\n" % (x, y)) c.auto(linuxcnc.AUTO_STEP) - time.sleep(0.1) + wait_complete_step() print_state() @@ -75,9 +113,6 @@ def mod_5_is_0(x): if count >= 1000: # Shouldn't happen, but prevent runaways sys.stderr.write("Finished: Exceeded max cycles\n") sys.exit(1) - if s.interp_state == linuxcnc.INTERP_IDLE: - sys.stderr.write("Finished: Detected program finish\n") - break time.sleep(0.1)