Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions scripts/linuxcnc.in
Original file line number Diff line number Diff line change
Expand Up @@ -694,8 +694,9 @@ function Cleanup() {
# Unused variable 'i', just a counter
# shellcheck disable=SC2034
for i in $(seq 10); do
# (the one component is the halcmd itself)
if [ "$($HALCMD list comp | wc -w)" = 1 ]; then break; fi
# (the one component is the halcmd itself; a thread is listed as
# a __<name> pseudo component, which stays until realtime stops)
if [ "$($HALCMD list comp | tr -s ' ' '\n' | grep -c -v -e '^__' -e '^$')" = 1 ]; then break; fi
sleep .2
done

Expand Down
4 changes: 4 additions & 0 deletions src/emc/task/emctaskmain.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3389,6 +3389,10 @@ static int emctask_shutdown(void)
delete emcStatus;
emcStatus = NULL;
}

// releases iocontrol.0
delete task_methods;
task_methods = NULL;
return 0;
}

Expand Down
5 changes: 4 additions & 1 deletion src/emc/task/taskclass.cc
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,10 @@ Task::Task(EMC_IO_STAT & emcioStatus_in) :
}
};

Task::~Task() {};
Task::~Task() {
if(comp_id >= 0)
hal_exit(comp_id);
}

// set the have_tool_change_position global
static int readToolChange(const IniFile &toolInifile)
Expand Down
6 changes: 6 additions & 0 deletions tests/abort/g64/README
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ This test runs and aborts a test .ngc program several times with
various motion mode and blend/naive CAM tolerance settings. Checks
are performed at various times relative to program execution:

Each setting is a test of its own in the directory named after it
(g61, g61.1, g64p0.5, g64, g64q6), so they run in parallel: it runs the
program twice, once after the mode command and once without it, which
must keep the mode across the first abort. Their test.ini includes the
shared settings in g64.inc; test-ui.py picks the case by the directory.

1) Motion mode: Does stat buffer agree with programmed mode?

2) G64 tolerance settings: Does stat buffer agree with programmed P/Q
Expand Down
File renamed without changes.
1 change: 1 addition & 0 deletions tests/abort/g64/g61.1/test.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#INCLUDE ../g64.inc
File renamed without changes.
2 changes: 2 additions & 0 deletions tests/abort/g64/g61/checkresult
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/sh
exit 0 # test failure is indicated by test.sh exit value
1 change: 1 addition & 0 deletions tests/abort/g64/g61/test.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#INCLUDE ../g64.inc
4 changes: 4 additions & 0 deletions tests/abort/g64/g61/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash -e
rm -f motion-samples.log

linuxcnc -r test.ini
6 changes: 4 additions & 2 deletions tests/abort/g64/test.ini → tests/abort/g64/g64.inc
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# Shared by the five cases, each in its own directory with a test.ini
# that includes this file; relative paths are from that directory.
[EMC]
# The version string for this INI file.
VERSION = 1.1
Expand All @@ -6,7 +8,7 @@ DEBUG = 0x0
#DEBUG = 2147483647

[DISPLAY]
DISPLAY = ./test-ui.py
DISPLAY = ../test-ui.py

[FILTER]
#No Content
Expand All @@ -30,7 +32,7 @@ CYCLE_TIME = 0.001
[HAL]
HALUI = halui
HALFILE = LIB:core_sim.hal
HALFILE = motion-test.hal
HALFILE = ../motion-test.hal

[HALUI]
#No Content
Expand Down
2 changes: 2 additions & 0 deletions tests/abort/g64/g64/checkresult
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/sh
exit 0 # test failure is indicated by test.sh exit value
1 change: 1 addition & 0 deletions tests/abort/g64/g64/test.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#INCLUDE ../g64.inc
4 changes: 4 additions & 0 deletions tests/abort/g64/g64/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash -e
rm -f motion-samples.log

linuxcnc -r test.ini
2 changes: 2 additions & 0 deletions tests/abort/g64/g64p0.5/checkresult
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/sh
exit 0 # test failure is indicated by test.sh exit value
1 change: 1 addition & 0 deletions tests/abort/g64/g64p0.5/test.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#INCLUDE ../g64.inc
4 changes: 4 additions & 0 deletions tests/abort/g64/g64p0.5/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash -e
rm -f motion-samples.log

linuxcnc -r test.ini
2 changes: 2 additions & 0 deletions tests/abort/g64/g64q6/checkresult
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/sh
exit 0 # test failure is indicated by test.sh exit value
1 change: 1 addition & 0 deletions tests/abort/g64/g64q6/test.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#INCLUDE ../g64.inc
4 changes: 4 additions & 0 deletions tests/abort/g64/g64q6/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash -e
rm -f motion-samples.log

linuxcnc -r test.ini
74 changes: 49 additions & 25 deletions tests/abort/g64/test-ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,21 @@ def process_samples(z_lev, expected_max_x):
res += 1
return res

def wait_for_samples(z_lev, y):
# halsampler writes behind the motion; wait until the log reaches the
# point the zig-zags were aborted at
end = time.time() + 10
while time.time() < end:
with open('motion-samples.log','r') as f:
for line in f:
try:
y_s, z_s = [float(n) for n in line.split(' ')[2:4]]
except ValueError:
break
if z_s == z_lev and y_s >= y:
return
time.sleep(0.1)

def check_status(msg, expected_mode, expected_p, expected_q):
res = 0
# Read status and print control mode and tolerances
Expand Down Expand Up @@ -77,37 +92,41 @@ def run_and_abort(msg, z_lev, expected_max_x,

# Run init commands
c.mode(linuxcnc.MODE_MDI)
c.wait_complete(30)
c.mdi('F1200 G0X0Y0Z%.1f' % z_lev)
c.wait_complete()
c.wait_complete(30)
for cmd in init_cmds:
print("Running command '%s'" % cmd)
c.mdi(cmd)
c.wait_complete()
c.wait_complete(30)
res += check_status(
'%s post-command' % msg, expected_mode, expected_p, expected_q)

# Run program
print("Running program 'test.ngc'")
c.mode(linuxcnc.MODE_AUTO)
c.program_open("test.ngc")
c.wait_complete(30)
c.program_open(os.path.join(os.path.dirname(os.path.abspath(__file__)), "test.ngc"))
c.wait_complete(30)
c.auto(linuxcnc.AUTO_RUN, 1)

# Wait for things to get underway, then abort
c.wait_complete()
# Let zig-zags run to a certain point
while s.position[1] < 1.0:
time.sleep(0.1)
# Let zig-zags run to a certain point, then abort
end = time.time() + 60
s.poll()
while s.position[1] < 1.0 and time.time() < end:
time.sleep(0.05)
s.poll()
res += check_status(
'%s pre-abort' % msg, expected_mode, expected_p, expected_q)
c.abort()
c.wait_complete()
c.wait_complete(30)

# Check settings
res += check_status(
'%s post-abort' % msg, expected_mode, expected_p, expected_q)

# Print max
wait_for_samples(z_lev, 1.0)
res += process_samples(z_lev, expected_max_x)
print()

Expand All @@ -121,9 +140,11 @@ def run_and_abort(msg, z_lev, expected_max_x,
e = linuxcnc.error_channel()

c.state(linuxcnc.STATE_ESTOP_RESET)
c.wait_complete(30)
c.state(linuxcnc.STATE_ON)
c.wait_complete(30)
c.home(-1)
c.wait_complete()
c.wait_complete(30)

#
# TESTS
Expand All @@ -132,22 +153,25 @@ def run_and_abort(msg, z_lev, expected_max_x,
# 1) whether stat buffer shows correct motion mode;
# 2) whether tolerance settings produce expected motion;
# 3) for G64, whether tolerance settings are correct in stat buffer
#
# One case per directory, named after it: a mode command, then a redo
# without it, which must keep the mode across the first abort
cases = {
# exact path mode: X up to 5"
'g61': ('G61', 0.0, 5.0, 610, None, None, 'G61'),
# exact stop mode: X up to 5"
'g61.1': ('G61.1', 1.0, 5.0, 611, None, None, 'G61.1'),
# path blending, 0.5" blend tolerance: X up to 4.5"
'g64p0.5': ('G64P0.5', 2.0, 4.5, 640, 0.5, 0.0, 'G64P0.5Q0'),
# path blending, best possible speed: X up to 3.725"
'g64': ('G64', 3.0, 3.7, 640, 0.0, 0.0, 'G64'),
# path blending, 6" naive cam tolerance: X always 0" (zig-zags collapse)
'g64q6': ('G64P0Q6', 4.0, 0.0, 640, 0.0, 6.0, 'G64Q6'),
}
msg, z_lev, max_x, mode, p, q, cmd = cases[os.path.basename(os.getcwd())]
res = 0
# Z=0: exact path mode: X up to 5"
res += run_and_abort('G61', 0.0, 5.0, 610, None, None, 'G61')
res += run_and_abort('G61 redo', 0.5, 5.0, 610, None, None)
# Z=1: exact stop mode: X up to 5"
res += run_and_abort('G61.1', 1.0, 5.0, 611, None, None, 'G61.1')
res += run_and_abort('G61.1 redo', 1.5, 5.0, 611, None, None)
# Z=2: path blending, 0.5" blend tolerance: X up to 4.5"
res += run_and_abort('G64P0.5', 2.0, 4.5, 640, 0.5, 0.0, 'G64P0.5Q0')
res += run_and_abort('G64P0.5 redo', 2.5, 4.5, 640, 0.5, 0.0)
# Z=3: path blending, best possible speed: X up to 3.725"
res += run_and_abort('G64', 3.0, 3.7, 640, 0.0, 0.0, 'G64')
res += run_and_abort('G64 redo', 3.5, 3.7, 640, 0.0, 0.0)
# Z=4: path blending, 6" naive cam tolerance: X always 0" (zig-zags collapse)
res += run_and_abort('G64P0Q6', 4.0, 0.0, 640, 0.0, 6.0, 'G64Q6')
res += run_and_abort('G64P0Q6 redo', 4.5, 0.0, 640, 0.0, 6.0)
res += run_and_abort(msg, z_lev, max_x, mode, p, q, cmd)
res += run_and_abort(msg + ' redo', z_lev + 0.5, max_x, mode, p, q)

#
# CLEANUP
Expand Down
51 changes: 33 additions & 18 deletions tests/workplane-retain/test-ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,24 +36,39 @@ def errors():

def mdi(*cmds):
c.mode(linuxcnc.MODE_MDI)
c.wait_complete()
c.wait_complete(30)
for cmd in cmds:
c.mdi(cmd)
c.wait_complete()
c.wait_complete(30)
l.wait_for_interp_state(linuxcnc.INTERP_IDLE, timeout=30)

def run(prog, abort_after=None):
def wait_for(done, timeout=30):
end = time.time() + timeout
while True:
s.poll()
if done():
return True
if time.time() > end:
return False
time.sleep(0.05)

def run(prog, abort=False):
c.mode(linuxcnc.MODE_AUTO)
c.wait_complete()
c.wait_complete(30)
c.program_open(prog)
c.wait_complete()
c.wait_complete(30)
c.auto(linuxcnc.AUTO_RUN, 0)
c.wait_complete()
if abort_after is not None:
time.sleep(abort_after)
if abort:
# abort in the slow F10 move, once the read ahead has stopped at
# the queue buster or M2
lines = open(prog).readlines()
slow = 1 + next(n for n, t in enumerate(lines) if "F10" in t)
stop = 1 + next(n for n, t in enumerate(lines) if t.startswith(("M66", "M2")))
if not wait_for(lambda: s.motion_line == slow and s.read_line >= stop):
say("%s: never in the slow move with the read ahead at line %d" % (prog, stop))
c.abort()
c.wait_complete()
time.sleep(0.3)
# the end of the program, or of the abort
c.wait_complete(30)
l.wait_for_interp_state(linuxcnc.INTERP_IDLE, timeout=30)

def at(x, y, z):
Expand All @@ -63,11 +78,11 @@ def at(x, y, z):
return "at %g %g %g" % (x, y, z) if d < 1e-6 else \
"at %.4f %.4f %.4f" % tuple(s.position[i] * 25.4 for i in range(3))

def case(name, prog, setup, abort_after, origin):
def case(name, prog, setup, abort, origin):
mdi("G69", "G21", "G54", "G52 X0 Y0 Z0", "G10 L2 P2 X5 Y0 Z0", "G0 X0 Y0 Z0", *setup)
errors()
if prog:
run(prog, abort_after)
run(prog, abort)
s.poll()
active = s.g68_active
s.poll()
Expand All @@ -81,11 +96,11 @@ def case(name, prog, setup, abort_after, origin):
o, z = (10, 20, 5), (0, 0, 0)
retain = inifile.find("RS274NGC", "RETAIN_WORK_PLANE") == "1"
# no program: a change of coordinate system in the plane takes it along
case("G55 in the plane", None, ["G68.2 X10 Y20 Z5 I10 J20 K30", "G55"], None, (15, 20, 5))
case("M2", "end.ngc", ["G68.2 X10 Y20 Z5 I10 J20 K30"], None, o if retain else z)
case("abort, read ahead in the next plane", "readahead.ngc", [], 1.0, o if retain else z)
case("abort, read ahead past G55", "g55.ngc", [], 1.0, o if retain else z)
case("abort, read ahead in a plane on G55", "g55plane.ngc", [], 1.0, z)
case("abort, G52 in the plane", "slow.ngc", ["G68.2 X10 Y20 Z5 I10 J20 K30", "G52 X1"], 1.0, o if retain else z)
case("G55 in the plane", None, ["G68.2 X10 Y20 Z5 I10 J20 K30", "G55"], False, (15, 20, 5))
case("M2", "end.ngc", ["G68.2 X10 Y20 Z5 I10 J20 K30"], False, o if retain else z)
case("abort, read ahead in the next plane", "readahead.ngc", [], True, o if retain else z)
case("abort, read ahead past G55", "g55.ngc", [], True, o if retain else z)
case("abort, read ahead in a plane on G55", "g55plane.ngc", [], True, z)
case("abort, G52 in the plane", "slow.ngc", ["G68.2 X10 Y20 Z5 I10 J20 K30", "G52 X1"], True, o if retain else z)
mdi("G69")
c.state(linuxcnc.STATE_OFF)
Loading