Import LinuxCNC source tree

This commit is contained in:
Wang Dequan
2026-08-20 06:17:39 +08:00
commit 2c814634c3
9429 changed files with 10556013 additions and 0 deletions

1
tests/abort/feed-rate/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
sim.var*

View File

@@ -0,0 +1,4 @@
This test starts LinuxCNC, sets the feed rate (in G94 and G95), then
Aborts and verifies that the expected feed rate is active.
In 2.6.12 and 2.7.7 this test replicates Github Issue #180.

View File

@@ -0,0 +1,2 @@
#!/bin/sh
exit 0 # test failure is indicated by test.sh exit value

View File

@@ -0,0 +1,61 @@
# core HAL config file for simulation
# first load all the RT modules that will be needed
# kinematics
loadrt [KINS]KINEMATICS
#autoconverted trivkins
# motion controller, get name and thread periods from INI file
loadrt [EMCMOT]EMCMOT base_period_nsec=[EMCMOT]BASE_PERIOD servo_period_nsec=[EMCMOT]SERVO_PERIOD num_joints=[KINS]JOINTS
# load 6 differentiators (for velocity and accel signals
loadrt ddt count=6
# load additional blocks
loadrt hypot count=2
loadrt comp count=3
loadrt or2 count=1
# add motion controller functions to servo thread
addf motion-command-handler servo-thread
addf motion-controller servo-thread
# link the differentiator functions into the code
addf ddt.0 servo-thread
addf ddt.1 servo-thread
addf ddt.2 servo-thread
addf ddt.3 servo-thread
addf ddt.4 servo-thread
addf ddt.5 servo-thread
addf hypot.0 servo-thread
addf hypot.1 servo-thread
# create HAL signals for position commands from motion module
# loop position commands back to motion module feedback
net Xpos joint.0.motor-pos-cmd => joint.0.motor-pos-fb ddt.0.in
net Ypos joint.1.motor-pos-cmd => joint.1.motor-pos-fb ddt.2.in
net Zpos joint.2.motor-pos-cmd => joint.2.motor-pos-fb ddt.4.in
# send the position commands thru differentiators to
# generate velocity and accel signals
net Xvel ddt.0.out => ddt.1.in hypot.0.in0
net Xacc <= ddt.1.out
net Yvel ddt.2.out => ddt.3.in hypot.0.in1
net Yacc <= ddt.3.out
net Zvel ddt.4.out => ddt.5.in hypot.1.in0
net Zacc <= ddt.5.out
# Cartesian 2- and 3-axis velocities
net XYvel hypot.0.out => hypot.1.in1
net XYZvel <= hypot.1.out
# estop loopback
net estop-loop iocontrol.0.user-enable-out iocontrol.0.emc-enable-in
# create signals for tool loading loopback
net tool-prepare <= iocontrol.0.tool-prepare
net tool-prepared => iocontrol.0.tool-prepared
net tool-change <= iocontrol.0.tool-change
net tool-changed => iocontrol.0.tool-changed
net tool-number <= iocontrol.0.tool-number
net tool-prep-number <= iocontrol.0.tool-prep-number
net tool-prep-pocket <= iocontrol.0.tool-prep-pocket

View File

@@ -0,0 +1,82 @@
#!/usr/bin/env python3
import linuxcnc
import hal
import math
import time
import sys
import subprocess
import os
import signal
import glob
import re
def wait_for_linuxcnc_startup(status, timeout=10.0):
"""Poll the Status buffer waiting for it to look initialized,
rather than just allocated (all-zero). Returns on success, throws
RuntimeError on failure."""
start_time = time.time()
while time.time() - start_time < timeout:
status.poll()
if (status.angular_units == 0.0) \
or (status.axis_mask == 0) \
or (status.cycle_time == 0.0) \
or (status.exec_state != linuxcnc.EXEC_DONE) \
or (status.interp_state != linuxcnc.INTERP_IDLE) \
or (status.inpos == False) \
or (status.linear_units == 0.0) \
or (status.max_acceleration == 0.0) \
or (status.max_velocity == 0.0) \
or (status.program_units == 0.0) \
or (status.rapidrate == 0.0) \
or (status.state != linuxcnc.RCS_DONE) \
or (status.task_state != linuxcnc.STATE_ESTOP):
time.sleep(0.1)
else:
# looks good
return
# timeout, throw an exception
raise RuntimeError("Timeout")
c = linuxcnc.command()
s = linuxcnc.stat()
e = linuxcnc.error_channel()
# Wait for LinuxCNC to initialize itself so the Status buffer stabilizes.
wait_for_linuxcnc_startup(s)
c.state(linuxcnc.STATE_ESTOP_RESET)
c.state(linuxcnc.STATE_ON)
c.home(-1)
c.wait_complete()
c.mode(linuxcnc.MODE_MDI)
feed_rate = 234.5
c.mdi('g94 ; normal "units per minute" feed mode')
c.mdi('f%.1f' % feed_rate)
c.wait_complete()
c.abort()
c.wait_complete()
s.poll()
print("feed rate:{}".format(s.settings[1]))
assert(math.fabs(s.settings[1] - feed_rate) < 0.0000001)
feed_rate = 345.6
c.mdi('g95 ; "units per revolution" feed mode')
c.mdi('f%.1f' % feed_rate)
c.wait_complete()
c.abort()
c.wait_complete()
s.poll()
print("feed rate:{}".format(s.settings[1]))
assert(math.fabs(s.settings[1] - feed_rate) < 0.0000001)
sys.exit(0)

View File

@@ -0,0 +1,119 @@
# This config file was created 2016-10-21 21:15:55.646298 by the update_ini script
# The original config files may be found in the /home/seb/linuxcnc-dev/tests/abort/feed-rate/test.old directory
[EMC]
# The version string for this INI file.
VERSION = 1.1
#DEBUG = 0x0
DEBUG = 0xffffffff
[DISPLAY]
DISPLAY = ./test-ui.py
[FILTER]
#No Content
[RS274NGC]
PARAMETER_FILE = sim.var
USER_M_PATH = ./subs
[EMCMOT]
EMCMOT = motmod
COMM_TIMEOUT = 4.0
BASE_PERIOD = 0
SERVO_PERIOD = 1000000
[TASK]
TASK = milltask
CYCLE_TIME = 0.001
[HAL]
HALUI = halui
HALFILE = core_sim.hal
[HALUI]
#No Content
[TRAJ]
NO_FORCE_HOMING=1
AXES = 3
COORDINATES = X Y Z
HOME = 0 0 0
LINEAR_UNITS = inch
ANGULAR_UNITS = degree
DEFAULT_LINEAR_VELOCITY = 1.2
MAX_LINEAR_ACCELERATION = 123.45
MAX_LINEAR_VELOCITY = 45.67
[EMCIO]
TOOL_TABLE = simpockets.tbl
TOOL_CHANGE_QUILL_UP = 1
RANDOM_TOOLCHANGER = 0
[KINS]
KINEMATICS = trivkins
#This is a best-guess at the number of joints, it should be checked
JOINTS = 3
[AXIS_X]
MIN_LIMIT = -40.0
MAX_LIMIT = 40.0
MAX_VELOCITY = 4
MAX_ACCELERATION = 1000.0
[JOINT_0]
TYPE = LINEAR
HOME = 0.000
MAX_VELOCITY = 4
MAX_ACCELERATION = 1000.0
BACKLASH = 0.000
INPUT_SCALE = 4000
OUTPUT_SCALE = 1.000
MIN_LIMIT = -40.0
MAX_LIMIT = 40.0
FERROR = 0.050
MIN_FERROR = 0.010
[AXIS_Y]
MIN_LIMIT = -40.0
MAX_LIMIT = 40.0
MAX_VELOCITY = 4
MAX_ACCELERATION = 1000.0
[JOINT_1]
TYPE = LINEAR
HOME = 0.000
MAX_VELOCITY = 4
MAX_ACCELERATION = 1000.0
BACKLASH = 0.000
INPUT_SCALE = 4000
OUTPUT_SCALE = 1.000
MIN_LIMIT = -40.0
MAX_LIMIT = 40.0
FERROR = 0.050
MIN_FERROR = 0.010
[AXIS_Z]
MIN_LIMIT = -40.0
MAX_LIMIT = 40.0
MAX_VELOCITY = 4
MAX_ACCELERATION = 1000.0
[JOINT_2]
TYPE = LINEAR
HOME = 0.0
MAX_VELOCITY = 4
MAX_ACCELERATION = 1000.0
BACKLASH = 0.000
INPUT_SCALE = 4000
OUTPUT_SCALE = 1.000
MIN_LIMIT = -40.0
MAX_LIMIT = 40.0
FERROR = 0.050
MIN_FERROR = 0.010

5
tests/abort/feed-rate/test.sh Executable file
View File

@@ -0,0 +1,5 @@
#!/bin/bash
rm -f sim.var
linuxcnc -r test.ini

1
tests/abort/g64/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
sim.var*

24
tests/abort/g64/README Normal file
View File

@@ -0,0 +1,24 @@
After program abort, show whether G61/G61.1/G64 settings are
consistent with machine state at last executing motion prior to abort.
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:
1) Motion mode: Does stat buffer agree with programmed mode?
2) G64 tolerance settings: Does stat buffer agree with programmed P/Q
args? (Only for G64, and only when these params are available in
stat buffer)
3) G64 tolerance settings: Do programmed tolerance settings produce
expected motion, as evidenced by samples taken during program
execution?
The .ngc program is aborted before ever reaching a G64 programmed at
the end. This demonstrates a bug caused by motion and interp running
out of synch, affecting LinuxCNC v. 2.7 and reported in Github issue
#177.
The fix will be introduced with Rob Ellenberg's state tags work,
discussed in Github issue #134.

2
tests/abort/g64/checkresult Executable file
View File

@@ -0,0 +1,2 @@
#!/bin/sh
exit 0 # test failure is indicated by test.sh exit value

View File

@@ -0,0 +1,18 @@
# sample where motion tells us to go
loadrt sampler depth=1000 cfg=fffffffff
addf sampler.0 servo-thread
net Xpos => sampler.0.pin.0
net Ypos => sampler.0.pin.1
net Zpos => sampler.0.pin.2
net Xvel => sampler.0.pin.3
net Yvel => sampler.0.pin.4
net Zvel => sampler.0.pin.5
net Xacc => sampler.0.pin.6
net Yacc => sampler.0.pin.7
net Zacc => sampler.0.pin.8
loadusr halsampler -t motion-samples.log

161
tests/abort/g64/test-ui.py Executable file
View File

@@ -0,0 +1,161 @@
#!/usr/bin/env python3
import linuxcnc
import time, sys, os
def process_samples(z_lev, expected_max_x):
# Read motion-samples.log for samples at the specified Z level and
# find the maximum X
res = 0
f = open('motion-samples.log','r')
max_x = 0.0
max_y = 0.0
samples = 0
for line in f:
try:
i, x, y, z, xvel, yvel, zvel, xacc, yacc, zacc = [
float(n) for n in line.split(' ')[:10]]
except ValueError:
# halsampler is still writing, so an incomplete line may be read
break
if z < z_lev:
# Ignore travel between Z levels
continue
if z > z_lev:
break
if x > max_x:
# Record new maximum
max_x = x
max_y = y
samples += 1
f.close()
print("z=%.1f; max_x = %.6f; max_y = %.6f; samples = %d" % (
z_lev, max_x, max_y, samples))
if abs(max_x - expected_max_x) > 0.1:
print("*** ERROR max X%.3f != expected X%.3f" % (
max_x, expected_max_x))
res += 1
return res
def check_status(msg, expected_mode, expected_p, expected_q):
res = 0
# Read status and print control mode and tolerances
s.poll()
control_mode = None
for i in s.gcodes:
if i in (610, 611, 640):
control_mode = i
if len(s.settings) == 3:
# Pre-state-tags fix
print("%s: Control mode = %d" % (msg, control_mode))
p, q = (expected_p, expected_q) # Fake valid results
else:
# After state-tags fix
print("%s: Control mode = %d; tolerances = P%.3f Q%.3f" % (
msg, control_mode, s.settings[3], s.settings[4]))
p, q = (s.settings[3], s.settings[4])
if control_mode != expected_mode:
print("*** ERROR control mode %d != expected %d" % (
control_mode, expected_mode))
res += 1
if expected_p is not None and abs(p - expected_p) > 0.001:
print("*** ERROR blend tolerance P%.3f != expected P%.3f" % (
p, expected_p))
res += 1
if expected_q is not None and abs(q - expected_q) > 0.001:
print("*** ERROR naive CAM tolerance Q%.3f != expected Q%.3f" % (
q, expected_q))
res += 1
return res
def run_and_abort(msg, z_lev, expected_max_x,
expected_mode, expected_p, expected_q, *init_cmds):
res = 0
# Move to specified Z level and run init commands; run test.ngc
# and abort; print status and max X values during run
# Run init commands
c.mode(linuxcnc.MODE_MDI)
c.mdi('F1200 G0X0Y0Z%.1f' % z_lev)
c.wait_complete()
for cmd in init_cmds:
print("Running command '%s'" % cmd)
c.mdi(cmd)
c.wait_complete()
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.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)
s.poll()
res += check_status(
'%s pre-abort' % msg, expected_mode, expected_p, expected_q)
c.abort()
c.wait_complete()
# Check settings
res += check_status(
'%s post-abort' % msg, expected_mode, expected_p, expected_q)
# Print max
res += process_samples(z_lev, expected_max_x)
print()
return res
#
# INIT
#
c = linuxcnc.command()
s = linuxcnc.stat()
e = linuxcnc.error_channel()
c.state(linuxcnc.STATE_ESTOP_RESET)
c.state(linuxcnc.STATE_ON)
c.home(-1)
c.wait_complete()
#
# TESTS
#
# Set up with various G61/G61.1/G64 commands, run test.ngc, and check
# 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
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)
#
# CLEANUP
#
if res == 0: # Leave samples in case of error
os.unlink('motion-samples.log')
os.unlink('sim.var')
os.unlink('sim.var.bak')
print("Exiting with %d errors" % res)
sys.exit(res)

120
tests/abort/g64/test.ini Normal file
View File

@@ -0,0 +1,120 @@
[EMC]
# The version string for this INI file.
VERSION = 1.1
DEBUG = 0x0
#DEBUG = 2147483647
[DISPLAY]
DISPLAY = ./test-ui.py
[FILTER]
#No Content
[RS274NGC]
PARAMETER_FILE = sim.var
USER_M_PATH = ./subs
LOG_LEVEL=5
[EMCMOT]
EMCMOT = motmod
COMM_TIMEOUT = 4.0
COMM_WAIT = 0.010
BASE_PERIOD = 0
SERVO_PERIOD = 1000000
[TASK]
TASK = milltask
CYCLE_TIME = 0.001
[HAL]
HALUI = halui
HALFILE = LIB:core_sim.hal
HALFILE = motion-test.hal
[HALUI]
#No Content
[TRAJ]
NO_FORCE_HOMING=1
AXES = 3
COORDINATES = X Y Z
HOME = 0 0 0
LINEAR_UNITS = inch
ANGULAR_UNITS = degree
CYCLE_TIME = 0.010
DEFAULT_LINEAR_VELOCITY = 1.2
MAX_LINEAR_ACCELERATION = 10
MAX_LINEAR_VELOCITY = 140
[EMCIO]
TOOL_TABLE = simpockets.tbl
TOOL_CHANGE_QUILL_UP = 1
RANDOM_TOOLCHANGER = 0
[KINS]
KINEMATICS = trivkins
#This is a best-guess at the number of joints, it should be checked
JOINTS = 3
[AXIS_X]
MIN_LIMIT = -40.0
MAX_LIMIT = 40.0
MAX_VELOCITY = 4
MAX_ACCELERATION = 5
[JOINT_0]
TYPE = LINEAR
HOME = 0.000
MAX_VELOCITY = 4
MAX_ACCELERATION = 5
BACKLASH = 0.000
INPUT_SCALE = 4000
OUTPUT_SCALE = 1.000
MIN_LIMIT = -40.0
MAX_LIMIT = 40.0
FERROR = 0.050
MIN_FERROR = 0.010
[AXIS_Y]
MIN_LIMIT = -40.0
MAX_LIMIT = 40.0
MAX_VELOCITY = 4
MAX_ACCELERATION = 5
[JOINT_1]
TYPE = LINEAR
HOME = 0.000
MAX_VELOCITY = 4
MAX_ACCELERATION = 5
BACKLASH = 0.000
INPUT_SCALE = 4000
OUTPUT_SCALE = 1.000
MIN_LIMIT = -40.0
MAX_LIMIT = 40.0
FERROR = 0.050
MIN_FERROR = 0.010
[AXIS_Z]
MIN_LIMIT = -40.0
MAX_LIMIT = 40.0
MAX_VELOCITY = 4
MAX_ACCELERATION = 5
[JOINT_2]
TYPE = LINEAR
HOME = 0.0
MAX_VELOCITY = 4
MAX_ACCELERATION = 5
BACKLASH = 0.000
INPUT_SCALE = 4000
OUTPUT_SCALE = 1.000
MIN_LIMIT = -40.0
MAX_LIMIT = 40.0
FERROR = 0.050
MIN_FERROR = 0.010

25
tests/abort/g64/test.ngc Normal file
View File

@@ -0,0 +1,25 @@
%
; Stepover for zig-zag
#100 = 1
; Start at a fast clip from X0Y0
G0 X0Y0 F120
; Run a bunch of zig-zags
#1 = 0
O100 WHILE [#1 LT 5*#100]
; zig
G1 X5 Y[#1 + #100]
; zag
G1 X0 Y[#1 + 2*#100]
#1 = [#1 + 2*#100]
O100 ENDWHILE
; Do a nice, slow move to ensure time for abort
F1 G1 Y10 (bogus location)
; Set G64; execution will never reach here
G64 P1 Q2
%

4
tests/abort/g64/test.sh Executable file
View File

@@ -0,0 +1,4 @@
#!/bin/bash -e
rm -f motion-samples.log
linuxcnc -r test.ini

View File

@@ -0,0 +1,4 @@
out.motion-logger
rs274ngc.var
rs274ngc.var.bak
test.ngc

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,10 @@
# Test for movement after abort
Test for issue [#579][1], [#393][2] & [#241][3], where an abort while
interp is loading a long `.ngc` file, and an `ON_ABORT_COMMAND` block
triggers a readahead bug where unflushed segments are appended to the
interp list.
[1]: https://github.com/LinuxCNC/linuxcnc/issues/579
[2]: https://github.com/LinuxCNC/linuxcnc/issues/393
[3]: https://github.com/LinuxCNC/linuxcnc/issues/241

View File

@@ -0,0 +1,3 @@
#!/bin/sh
# Python script exit indicates test success/fail
exit 0

View File

@@ -0,0 +1,3 @@
loadusr -W motion-logger out.motion-logger
setp iocontrol.0.emc-enable-in 1

View File

@@ -0,0 +1,2 @@
net Xpos => test-ui.Xpos
net Ypos => test-ui.Ypos

View File

@@ -0,0 +1,3 @@
T1 P0 D0.125000 Z+1.000000 ;
T10 P3 D0.500000 Z+3.000000 ;
T99999 P50 Z+2.000000 ;

View File

@@ -0,0 +1,4 @@
o<on_abort> sub
G64 P0.1
o<on_abort> endsub
m2

View File

@@ -0,0 +1,135 @@
#!/usr/bin/env python3
import linuxcnc
import linuxcnc_util
import hal
import time
import sys
import os
# Time increment and timeout, seconds
TIME_INCR = 0.1
TIMEOUT = 10.0
MAX_QWAIT_TRIES = 4
#
# connect to LinuxCNC
#
c = linuxcnc.command()
s = linuxcnc.stat()
e = linuxcnc.error_channel()
l = linuxcnc_util.LinuxCNC(command=c, status=s, error=e)
#
# Create and connect test feedback comp
#
h = hal.component("test-ui")
h.newpin("Xpos", hal.HAL_FLOAT, hal.HAL_IN)
h.newpin("Ypos", hal.HAL_FLOAT, hal.HAL_IN)
h.ready()
os.system("halcmd source ./postgui.hal")
#
# Come out of E-stop, turn the machine on, home
#
c.state(linuxcnc.STATE_ESTOP_RESET)
c.state(linuxcnc.STATE_ON)
c.home(0)
c.home(1)
c.home(2)
l.wait_for_home([1, 1, 1, 0, 0, 0, 0, 0, 0])
#
# Print status function
#
def print_stats(x = None, y = None):
s.poll()
if x is None:
sys.stderr.write(
"queue=%d; active_queue=%d; queue_full=%s;"
" x=%.3f; y=%.3f\n" %
(s.queue, s.active_queue, s.queue_full, h['Xpos'], h['Ypos']))
else:
sys.stderr.write(
"queue=%d; active_queue=%d; queue_full=%s;"
" x=%.3f(%.3f); y=%.3f(%.3f)\n" %
(s.queue, s.active_queue, s.queue_full,
h['Xpos'], x-h['Xpos'], h['Ypos'], y-h['Ypos']))
#
# Set up tool and start position
#
c.mode(linuxcnc.MODE_MDI)
c.mdi('T1M6') # Load tool 1
c.mdi('G0 X2 Y2') # Move near to start
c.wait_complete()
start_time = time.time()
while (abs(h['Xpos'] - 2) > .001) or (abs(h['Ypos'] - 2) > .001):
if (time.time() - start_time) > TIMEOUT:
sys.stderr.write("Failed to reach start position in time\n")
os.system("halcmd show")
sys.exit(1)
time.sleep(TIME_INCR)
sys.stderr.write("Starting at X=%.3f Y=%.3f\n" % (h["Xpos"], h["Ypos"]))
#
# Run the generated program, wait for motion to start and the queue to
# fill up
#
c.mode(linuxcnc.MODE_AUTO)
# c.program_open('test.ngc')
c.program_open('3D_Chips.ngc')
c.auto(linuxcnc.AUTO_RUN, 0)
start_time = time.time()
s.poll()
MAX_QWAIT_TRIES=4
ct=0
while not (s.queue > 1000):
delta_t = time.time() - start_time
if delta_t > TIMEOUT:
sys.stderr.write("ct=%d s.queue=%d delta_t=%f TIMEOUT=%f\n"%(
ct,s.queue,delta_t,TIMEOUT))
start_time = time.time()
ct += 1
if ct > MAX_QWAIT_TRIES:
sys.stderr.write("Failed to load segments from program\n")
sys.exit(1)
print_stats()
time.sleep(TIME_INCR)
sys.stderr.write("Program partially loaded\n")
#
# Now stop the program and wait for any additional motion
#
# Program X stepover is 2.5mm, or 0.1in; error out if the X stepover
# exceeds 0.15 (fudge added to eliminate a legitimate stepover during
# lag between cycles)
pre_stop_x, pre_stop_y = h['Xpos'], h['Ypos']
c.abort()
start_time = time.time()
last_x = pre_stop_x
fail = False
while (time.time() - start_time) < TIMEOUT and h['Xpos'] != last_x:
print_stats(pre_stop_x, pre_stop_y)
err = abs(pre_stop_x - h['Xpos'])
if err > 0.15:
sys.stderr.write(
'ERROR: X axis motion stopped %.3f" past stop position\n' % err)
fail = True
last_x = h['Xpos']
time.sleep(TIME_INCR)
if fail:
sys.exit(1)
sys.stderr.write('Success\n')
sys.exit(0)

View File

@@ -0,0 +1,106 @@
[EMC]
# DEBUG = 0
DEBUG = 2147483647
VERSION = 1.1
[DISPLAY]
DISPLAY = ./test-ui.py
[TASK]
TASK = milltask
CYCLE_TIME = 0.001
[RS274NGC]
PARAMETER_FILE = sim.var
LOG_LEVEL = 5
ON_ABORT_COMMAND=O <on_abort> call
SUBROUTINE_PATH = subroutines
[EMCMOT]
EMCMOT = motmod
COMM_TIMEOUT = 4.0
BASE_PERIOD = 0
SERVO_PERIOD = 1000000
[HAL]
HALFILE = LIB:core_sim.hal
[TRAJ]
AXES = 3
COORDINATES = X Y Z
HOME = 0 0 0
LINEAR_UNITS = inch
ANGULAR_UNITS = degree
DEFAULT_LINEAR_VELOCITY = 120
MAX_LINEAR_VELOCITY = 400
NO_FORCE_HOMING = 1
[EMCIO]
TOOL_TABLE = simpockets.tbl
TOOL_CHANGE_QUILL_UP = 1
RANDOM_TOOLCHANGER = 1
[AXIS_X]
HOME = 0.000
MIN_LIMIT = -40.0
MAX_LIMIT = 40.0
MAX_VELOCITY = 400
MAX_ACCELERATION = 100.0
[AXIS_Y]
HOME = 0.000
MIN_LIMIT = -40.0
MAX_LIMIT = 40.0
MAX_VELOCITY = 400
MAX_ACCELERATION = 100.0
[AXIS_Z]
HOME = 0.0
MIN_LIMIT = -4.0
MAX_LIMIT = 4.0
MAX_VELOCITY = 400
MAX_ACCELERATION = 100.0
[KINS]
KINEMATICS = trivkins
JOINTS = 3
[JOINT_0]
TYPE = LINEAR
HOME = 0.000
MAX_VELOCITY = 400
MAX_ACCELERATION = 100.0
BACKLASH = 0.000
INPUT_SCALE = 4000
OUTPUT_SCALE = 1.000
MIN_LIMIT = -40.0
MAX_LIMIT = 40.0
FERROR = 0.050
MIN_FERROR = 0.010
[JOINT_1]
TYPE = LINEAR
HOME = 0.000
MAX_VELOCITY = 400
MAX_ACCELERATION = 100.0
BACKLASH = 0.000
INPUT_SCALE = 4000
OUTPUT_SCALE = 1.000
MIN_LIMIT = -40.0
MAX_LIMIT = 40.0
FERROR = 0.050
MIN_FERROR = 0.010
[JOINT_2]
TYPE = LINEAR
HOME = 0.0
MAX_VELOCITY = 400
MAX_ACCELERATION = 100.0
BACKLASH = 0.000
INPUT_SCALE = 4000
OUTPUT_SCALE = 1.000
MIN_LIMIT = -4.0
MAX_LIMIT = 4.0
FERROR = 0.050
MIN_FERROR = 0.010

View File

@@ -0,0 +1,7 @@
#!/bin/bash -e
# Run test file in task
linuxcnc -r test.ini
RES=$?
exit $RES

View File

@@ -0,0 +1,4 @@
out.motion-logger
rs274ngc.var
rs274ngc.var.bak
test.ngc

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,8 @@
# Test for movement after abort
Test for [issue #865][1], where an abort while interp is loading a
long `.ngc` file, and a block restoring a state tag triggers a
readahead bug where unflushed segments are appended to the interp
list.
[1]: https://github.com/LinuxCNC/linuxcnc/issues/865

View File

@@ -0,0 +1,3 @@
#!/bin/sh
# Python script exit indicates test success/fail
exit 0

View File

@@ -0,0 +1,3 @@
loadusr -W motion-logger out.motion-logger
setp iocontrol.0.emc-enable-in 1

View File

@@ -0,0 +1,2 @@
net Xpos => test-ui.Xpos
net Ypos => test-ui.Ypos

View File

@@ -0,0 +1,3 @@
T1 P0 D0.125000 Z+1.000000 ;
T10 P3 D0.500000 Z+3.000000 ;
T99999 P50 Z+2.000000 ;

View File

@@ -0,0 +1,126 @@
#!/usr/bin/env python3
import linuxcnc
import linuxcnc_util
import hal
import time
import sys
import os
# Time increment and timeout, seconds
TIME_INCR = 0.1
TIMEOUT = 10.0
#
# connect to LinuxCNC
#
c = linuxcnc.command()
s = linuxcnc.stat()
e = linuxcnc.error_channel()
l = linuxcnc_util.LinuxCNC(command=c, status=s, error=e)
#
# Create and connect test feedback comp
#
h = hal.component("test-ui")
h.newpin("Xpos", hal.HAL_FLOAT, hal.HAL_IN)
h.newpin("Ypos", hal.HAL_FLOAT, hal.HAL_IN)
h.ready()
os.system("halcmd source ./postgui.hal")
#
# Come out of E-stop, turn the machine on, home
#
c.state(linuxcnc.STATE_ESTOP_RESET)
c.state(linuxcnc.STATE_ON)
c.home(0)
c.home(1)
c.home(2)
l.wait_for_home([1, 1, 1, 0, 0, 0, 0, 0, 0])
#
# Print status function
#
def print_stats(x = None, y = None):
s.poll()
if x is None:
sys.stderr.write(
"queue=%d; active_queue=%d; queue_full=%s;"
" x=%.3f; y=%.3f\n" %
(s.queue, s.active_queue, s.queue_full, h['Xpos'], h['Ypos']))
else:
sys.stderr.write(
"queue=%d; active_queue=%d; queue_full=%s;"
" x=%.3f(%.3f); y=%.3f(%.3f)\n" %
(s.queue, s.active_queue, s.queue_full,
h['Xpos'], x-h['Xpos'], h['Ypos'], y-h['Ypos']))
#
# Set up tool and start position
#
c.mode(linuxcnc.MODE_MDI)
c.mdi('T1M6') # Load tool 1
c.mdi('G0 X2 Y2') # Move near to start
c.wait_complete()
start_time = time.time()
while (abs(h['Xpos'] - 2) > .001) or (abs(h['Ypos'] - 2) > .001):
if (time.time() - start_time) > TIMEOUT:
sys.stderr.write("Failed to reach start position in time\n")
os.system("halcmd show")
sys.exit(1)
time.sleep(TIME_INCR)
sys.stderr.write("Starting at X=%.3f Y=%.3f\n" % (h["Xpos"], h["Ypos"]))
#
# Run the generated program, wait for motion to start and the queue to
# fill up
#
c.mode(linuxcnc.MODE_AUTO)
# c.program_open('test.ngc')
c.program_open('3D_Chips.ngc')
c.auto(linuxcnc.AUTO_RUN, 0)
start_time = time.time()
s.poll()
while not (s.queue > 1000):
if (time.time() - start_time) > TIMEOUT:
sys.stderr.write("Failed to load segments from program\n")
sys.exit(1)
print_stats()
time.sleep(TIME_INCR)
sys.stderr.write("Program partially loaded\n")
#
# Now stop the program and wait for any additional motion
#
# Program X stepover is 2.5mm, or 0.1in; error out if the X stepover
# exceeds 0.15 (fudge added to eliminate a legitimate stepover during
# lag between cycles)
pre_stop_x, pre_stop_y = h['Xpos'], h['Ypos']
c.abort()
start_time = time.time()
last_x = pre_stop_x
fail = False
while (time.time() - start_time) < TIMEOUT and h['Xpos'] != last_x:
print_stats(pre_stop_x, pre_stop_y)
err = abs(pre_stop_x - h['Xpos'])
if err > 0.15:
sys.stderr.write(
'ERROR: X axis motion stopped %.3f" past stop position\n' % err)
fail = True
last_x = h['Xpos']
time.sleep(TIME_INCR)
if fail:
sys.exit(1)
sys.stderr.write('Success\n')
sys.exit(0)

View File

@@ -0,0 +1,104 @@
[EMC]
DEBUG = 0
# DEBUG = 2147483647
VERSION = 1.1
[DISPLAY]
DISPLAY = ./test-ui.py
[TASK]
TASK = milltask
CYCLE_TIME = 0.001
[RS274NGC]
PARAMETER_FILE = sim.var
# LOG_LEVEL = 5
[EMCMOT]
EMCMOT = motmod
COMM_TIMEOUT = 4.0
BASE_PERIOD = 0
SERVO_PERIOD = 1000000
[HAL]
HALFILE = LIB:core_sim.hal
[TRAJ]
AXES = 3
COORDINATES = X Y Z
HOME = 0 0 0
LINEAR_UNITS = inch
ANGULAR_UNITS = degree
DEFAULT_LINEAR_VELOCITY = 120
MAX_LINEAR_VELOCITY = 400
NO_FORCE_HOMING = 1
[EMCIO]
TOOL_TABLE = simpockets.tbl
TOOL_CHANGE_QUILL_UP = 1
RANDOM_TOOLCHANGER = 1
[AXIS_X]
HOME = 0.000
MIN_LIMIT = -40.0
MAX_LIMIT = 40.0
MAX_VELOCITY = 400
MAX_ACCELERATION = 100.0
[AXIS_Y]
HOME = 0.000
MIN_LIMIT = -40.0
MAX_LIMIT = 40.0
MAX_VELOCITY = 400
MAX_ACCELERATION = 100.0
[AXIS_Z]
HOME = 0.0
MIN_LIMIT = -4.0
MAX_LIMIT = 4.0
MAX_VELOCITY = 400
MAX_ACCELERATION = 100.0
[KINS]
KINEMATICS = trivkins
JOINTS = 3
[JOINT_0]
TYPE = LINEAR
HOME = 0.000
MAX_VELOCITY = 400
MAX_ACCELERATION = 100.0
BACKLASH = 0.000
INPUT_SCALE = 4000
OUTPUT_SCALE = 1.000
MIN_LIMIT = -40.0
MAX_LIMIT = 40.0
FERROR = 0.050
MIN_FERROR = 0.010
[JOINT_1]
TYPE = LINEAR
HOME = 0.000
MAX_VELOCITY = 400
MAX_ACCELERATION = 100.0
BACKLASH = 0.000
INPUT_SCALE = 4000
OUTPUT_SCALE = 1.000
MIN_LIMIT = -40.0
MAX_LIMIT = 40.0
FERROR = 0.050
MIN_FERROR = 0.010
[JOINT_2]
TYPE = LINEAR
HOME = 0.0
MAX_VELOCITY = 400
MAX_ACCELERATION = 100.0
BACKLASH = 0.000
INPUT_SCALE = 4000
OUTPUT_SCALE = 1.000
MIN_LIMIT = -4.0
MAX_LIMIT = 4.0
FERROR = 0.050
MIN_FERROR = 0.010

View File

@@ -0,0 +1,7 @@
#!/bin/bash -e
# Run test file in task
linuxcnc -r test.ini
RES=$?
exit $RES