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

View File

@@ -0,0 +1,23 @@
Test that the spindle speed limits from the INI are honoured.
Tests three spindles, to ensure that multi-spindle is supported
The test starts from the test.sh script which loads linuxcnc, passing it an almost-standard INI file.
In place of the normal GUI the INI file loads test-ui.py which does not create any GUI elements.
test-ui.py puts LinuxCNC in a condition where is can respond to MDI commands, and then proceeds to use
both MDI and the Python command interface to set various spindle speeds and check that the HAL and status
outputs are within the specified limits.
The test-ui script then exits, and at that point the runtests script automatically runs "checkresult".
"checkresult" is needed to skip automatic testing of "expected" againsts "result" which wouldn't
work fot this test.
Spindle.0 has limits for MAX_FORWARD, MIN_FORWARD, MAX_REVERSE and MIN_REVERSE
Spindle.1 has no MIN_REVERSE to test that MIN_FORWARD is applied in reverse
Spindle.2 has no MIN_REVERSE or MAX_REVERSE to test that both *_FORWARD limits are applied in reverse
Spindle commands through both G-code (via MDI) and Python interface are tested.
FIXME (?)
spindle commands through halui are not tested
spindle commands through linuxcncrsh are not tested.

View File

@@ -0,0 +1,3 @@
#!/bin/sh
# Test passes if test-ui.py returns successfully
exit 0

View File

@@ -0,0 +1,17 @@
# HAL file for spindle limits test
# first load all the RT modules that will be needed
# kinematics
loadrt [KINS]KINEMATICS
# 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 num_spindles=[TRAJ]SPINDLES
# add motion controller functions to servo thread
addf motion-command-handler servo-thread
addf motion-controller servo-thread
# estop loopback
net estop-loop iocontrol.0.user-enable-out iocontrol.0.emc-enable-in

View File

@@ -0,0 +1,115 @@
[EMC]
VERSION = 1.1
DEBUG = 0x0
[DISPLAY]
DISPLAY = ./test-ui.py
[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
MDI_QUEUED_COMMANDS=10000
[HAL]
HALFILE = spindle.hal
[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_VELOCITY = 4
SPINDLES = 3
[EMCIO]
EMCIO = io
CYCLE_TIME = 0.100
[KINS]
KINEMATICS = trivkins
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 = -4.0
MAX_LIMIT = 4.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 = -4.0
MAX_LIMIT = 4.0
FERROR = 0.050
MIN_FERROR = 0.010
[SPINDLE_0]
MAX_FORWARD_VELOCITY = 1000
MIN_FORWARD_VELOCITY = 100
MAX_REVERSE_VELOCITY = 1500
MIN_REVERSE_VELOCITY = 500
[SPINDLE_1]
MAX_FORWARD_VELOCITY = 2000
MIN_FORWARD_VELOCITY = 200
MAX_REVERSE_VELOCITY = 2500
[SPINDLE_2]
MAX_FORWARD_VELOCITY = 3000
MIN_FORWARD_VELOCITY = 300

182
tests/spindle_limits/test-ui.py Executable file
View File

@@ -0,0 +1,182 @@
#!/usr/bin/env python3
import linuxcnc
import hal
import time
import sys
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
def wait_for_mdi_queue(queue_len, timeout=10):
start_time = time.time()
while (time.time() - start_time) < timeout:
s.poll()
if s.queued_mdi_commands == queue_len:
return
time.sleep(0.1)
print("queued_mdi_commands at %d after %.3f seconds" % (s.queued_mdi_commands, timeout))
sys.exit(1)
c = linuxcnc.command()
s = linuxcnc.stat()
e = linuxcnc.error_channel()
comp = hal.component('hal-watcher')
# 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.wait_complete()
# Check G-code / MDI spindle commands
c.mode(linuxcnc.MODE_MDI)
c.mdi("M3 S10 $0")
c.mdi("M3 S10 $1")
c.mdi("M3 S10 $2")
c.wait_complete()
s.poll()
assert hal.get_value('spindle.0.speed-out') == 100
assert s.spindle[0]['speed'] == 100
assert hal.get_value('spindle.1.speed-out') == 200
assert s.spindle[1]['speed'] == 200
assert hal.get_value('spindle.2.speed-out') == 300
assert s.spindle[2]['speed'] == 300
c.mdi("M3 S10000 $0")
c.mdi("M3 S10000 $1")
c.mdi("M3 S10000 $2")
c.wait_complete()
s.poll()
assert hal.get_value('spindle.0.speed-out') == 1000
assert s.spindle[0]['speed'] == 1000
assert hal.get_value('spindle.1.speed-out') == 2000
assert s.spindle[1]['speed'] == 2000
assert hal.get_value('spindle.2.speed-out') == 3000
assert s.spindle[2]['speed'] == 3000
c.mdi("M4 S10 $0")
c.mdi("M4 S10 $1")
c.mdi("M4 S10 $2")
c.wait_complete()
s.poll()
assert hal.get_value('spindle.0.speed-out') == -500
assert s.spindle[0]['speed'] == -500
assert hal.get_value('spindle.1.speed-out') == -200
assert s.spindle[1]['speed'] == -200
assert hal.get_value('spindle.2.speed-out') == -300
assert s.spindle[2]['speed'] == -300
c.mdi("M4 S10000 $0")
c.mdi("M4 S10000 $1")
c.mdi("M4 S10000 $2")
c.wait_complete()
s.poll()
assert hal.get_value('spindle.0.speed-out') == -1500
assert s.spindle[0]['speed'] == -1500
assert hal.get_value('spindle.1.speed-out') == -2500
assert s.spindle[1]['speed'] == -2500
assert hal.get_value('spindle.2.speed-out') == -3000
assert s.spindle[2]['speed'] == -3000
# Check Python interface commands
c.spindle(linuxcnc.SPINDLE_FORWARD, 10, 0, 0)
c.spindle(linuxcnc.SPINDLE_FORWARD, 10, 1, 0)
c.spindle(linuxcnc.SPINDLE_FORWARD, 10, 2, 0)
c.wait_complete()
s.poll()
assert hal.get_value('spindle.0.speed-out') == 100
assert s.spindle[0]['speed'] == 100
assert hal.get_value('spindle.1.speed-out') == 200
assert s.spindle[1]['speed'] == 200
assert hal.get_value('spindle.2.speed-out') == 300
assert s.spindle[2]['speed'] == 300
c.spindle(linuxcnc.SPINDLE_FORWARD, 10000, 0, 0)
c.spindle(linuxcnc.SPINDLE_FORWARD, 10000, 1, 0)
c.spindle(linuxcnc.SPINDLE_FORWARD, 10000, 2, 0)
c.wait_complete()
s.poll()
assert hal.get_value('spindle.0.speed-out') == 1000
assert s.spindle[0]['speed'] == 1000
assert hal.get_value('spindle.1.speed-out') == 2000
assert s.spindle[1]['speed'] == 2000
assert hal.get_value('spindle.2.speed-out') == 3000
assert s.spindle[2]['speed'] == 3000
c.spindle(linuxcnc.SPINDLE_REVERSE, 10, 0, 0)
c.spindle(linuxcnc.SPINDLE_REVERSE, 10, 1, 0)
c.spindle(linuxcnc.SPINDLE_REVERSE, 10, 2, 0)
c.wait_complete()
s.poll()
assert hal.get_value('spindle.0.speed-out') == -500
assert s.spindle[0]['speed'] == -500
assert hal.get_value('spindle.1.speed-out') == -200
assert s.spindle[1]['speed'] == -200
assert hal.get_value('spindle.2.speed-out') == -300
assert s.spindle[2]['speed'] == -300
c.spindle(linuxcnc.SPINDLE_REVERSE, 10000, 0, 0)
c.spindle(linuxcnc.SPINDLE_REVERSE, 10000, 1, 0)
c.spindle(linuxcnc.SPINDLE_REVERSE, 10000, 2, 0)
c.wait_complete()
s.poll()
assert hal.get_value('spindle.0.speed-out') == -1500
assert s.spindle[0]['speed'] == -1500
assert hal.get_value('spindle.1.speed-out') == -2500
assert s.spindle[1]['speed'] == -2500
assert hal.get_value('spindle.2.speed-out') == -3000
assert s.spindle[2]['speed'] == -3000
sys.exit(0)

4
tests/spindle_limits/test.sh Executable file
View File

@@ -0,0 +1,4 @@
#!/bin/bash -e
linuxcnc -r spindle.ini