diff --git a/.gitignore b/.gitignore index 3d286f605e4..039ca99f6a8 100644 --- a/.gitignore +++ b/.gitignore @@ -29,6 +29,7 @@ src/modules.order /docs/src/source-highlight/local docs/src/*/gui/gmoccapy_release_notes.txt lib/python/gremlin.py +lib/python/preview_helpers.py lib/python/qt5_graphics.py lib/python/touchy configs/sim/gmoccapy/*.pref diff --git a/src/emc/usr_intf/gremlin/Submakefile b/src/emc/usr_intf/gremlin/Submakefile index 4315900a2ec..541e0638e0c 100644 --- a/src/emc/usr_intf/gremlin/Submakefile +++ b/src/emc/usr_intf/gremlin/Submakefile @@ -1,4 +1,4 @@ -PYTARGETS += ../bin/gremlin ../lib/python/gremlin.py ../lib/python/qt5_graphics.py +PYTARGETS += ../bin/gremlin ../lib/python/gremlin.py ../lib/python/qt5_graphics.py ../lib/python/preview_helpers.py PYI18NSRCS += emc/usr_intf/gremlin/gremlin.py ../lib/python/%: emc/usr_intf/gremlin/% diff --git a/src/emc/usr_intf/gremlin/gremlin.py b/src/emc/usr_intf/gremlin/gremlin.py index 3a60f9fbc4b..fbc3073fbfd 100755 --- a/src/emc/usr_intf/gremlin/gremlin.py +++ b/src/emc/usr_intf/gremlin/gremlin.py @@ -64,6 +64,7 @@ import rs274.interpret import linuxcnc import gcode +import preview_helpers import time import re @@ -324,24 +325,12 @@ def load(self,filename = None): if parameter: shutil.copy(parameter, temp_parameter) canon.parameter_file = temp_parameter - - unitcode = "G%d" % (20 + (s.linear_units == 1)) - initcode = "G53 G0 " - for i in range(9): - if s.axis_mask & (1< gcode.MIN_ERROR: self.report_gcode_error(result, seq, filename) self.calculate_gcode_properties(canon) + except Exception as e: print (e) self.gcode_properties = None diff --git a/src/emc/usr_intf/gremlin/preview_helpers.py b/src/emc/usr_intf/gremlin/preview_helpers.py new file mode 100644 index 00000000000..8193b0309ac --- /dev/null +++ b/src/emc/usr_intf/gremlin/preview_helpers.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 + +def create_unitcode_and_initcode(s, inifile): + a_axis_wrapped = inifile.getbool("AXIS_A", "WRAPPED_ROTARY", fallback=False) + b_axis_wrapped = inifile.getbool("AXIS_B", "WRAPPED_ROTARY", fallback=False) + c_axis_wrapped = inifile.getbool("AXIS_C", "WRAPPED_ROTARY", fallback=False) + + s.poll() + # create unitcode and initcode reflecting currently active modal gcodes + unitcode = "G%d" % (20 + (s.linear_units == 1)) + initcode = "G53 G0 " + for i in range(9): + if s.axis_mask & (1< -1: + initcode = initcode + 'G' + str(active_gcodes[i]/10) + ' ' + return unitcode, initcode diff --git a/tests/interp_initcode/.gitignore b/tests/interp_initcode/.gitignore new file mode 100644 index 00000000000..7c5e3dc5bff --- /dev/null +++ b/tests/interp_initcode/.gitignore @@ -0,0 +1,4 @@ +test.var* +stderr +result +temp_log diff --git a/tests/interp_initcode/README b/tests/interp_initcode/README new file mode 100644 index 00000000000..7623658061e --- /dev/null +++ b/tests/interp_initcode/README @@ -0,0 +1,5 @@ +This test +- starts LinuxCNC using test.ini +- uses MDI commands to change the startup state of the modal gcodes +- initializes an interpreter instance to the currently active modal gcodes using the gremlin helper function and loads a test gcode file that lacks a preamble +- checks that the start up state reflects [RS274NGC] RS274NGC_STARTUP_CODE and output of the interpreter after loading the test gcode file. diff --git a/tests/interp_initcode/expected b/tests/interp_initcode/expected new file mode 100644 index 00000000000..c93f6946634 --- /dev/null +++ b/tests/interp_initcode/expected @@ -0,0 +1,20 @@ +startup gcodes (0, 800, -1, 170, 400, 200, 900, 940, 540, 430, 990, 640, -1, 970, 911, 80, -1) +set_g5x_offset (1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) +set_g92_offset (0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) +set_xy_rotation (0.0,) +# interpreter: feed mode set to units per minute +set feed rate 0.0 +set plane 1 +# interpreter: cutter radius compensation off +tool_offset (0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) +set_g5x_offset (2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) +set_g92_offset (0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) +set_xy_rotation (0.0,) +# interpreter: retract mode set to r_plane +straight_traverse (1.23, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) +set feed rate 100.0 +arc_feed (1.23, 0.0, 21.23, 0.0, -1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) +straight_traverse (10.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) +set_g5x_offset (1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0) +set_xy_rotation (0.0,) +set feed rate 0.0 diff --git a/tests/interp_initcode/test-ui.py b/tests/interp_initcode/test-ui.py new file mode 100755 index 00000000000..b463ee0ad6b --- /dev/null +++ b/tests/interp_initcode/test-ui.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python3 +import gcode +import linuxcnc +import linuxcnc_util +from rs274.interpret import PrintCanon, StatMixin +import preview_helpers +import sys +import os + + +class PreviewCanon(PrintCanon, StatMixin): + + def __init__(self, stat, randomtc, parameter): + StatMixin.__init__(self, stat, randomtc) + self.parameter_file = parameter + self.feed_rate = 0.0 + self.current_x = 0.0 + self.current_y = 0.0 + self.current_z = 0.0 + + def __getattr__(self, name): + if name.startswith("_"): + raise AttributeError(name) + print(f"[WARN] unimplemented canon: {name}()", file=sys.stderr) + return lambda *args, **kwargs: None + + def set_xy_rotation(self, *args): + print("set_xy_rotation", args) + + def set_g5x_offset(self, *args): + print("set_g5x_offset", args) + + def set_g92_offset(self, *args): + print("set_g92_offset", args) + + def tool_offset(self, *args): + print("tool_offset", args) + + def next_line(self, state): + #print("next_line", state.sequence_number) + self.state = state + + def set_plane(self, plane): + print("set plane", plane) + + def set_feed_rate(self, arg): + print("set feed rate", arg) + + def comment(self, arg): + print("#", arg) + + def straight_traverse(self, *args): + print("straight_traverse " , args) + + def straight_feed(self, *args): + print("straight_feed" , args) + + def dwell(self, arg): + if arg < .1: + print("dwell %f ms" % (1000 * arg)) + else: + print("dwell %f seconds" % arg) + + def arc_feed(self, *args): + print("arc_feed " , args) + + def close(self, *args): + pass + + +# route output to log file now +log_file = open("temp_log","w") +sys.stdout = log_file + +# connect +c = linuxcnc.command() +e = linuxcnc.error_channel() +s = linuxcnc.stat() +l = linuxcnc_util.LinuxCNC(command=c, status=s, error=e) + +# parse inifile variables +inifile = linuxcnc.ini("test.ini") +random = inifile.getbool("EMCIO", "RANDOM_TOOLCHANGER", fallback=False) +parameter = inifile.getstring("RS274NGC", "PARAMETER_FILE", fallback="test.var") + +# setup preview interpreter +filename = "test.ngc" +canon = PreviewCanon(s, random, parameter) + +# setup linuxcnc +c.state(linuxcnc.STATE_ESTOP_RESET) +c.state(linuxcnc.STATE_ON) +c.mode(linuxcnc.MODE_MANUAL) +c.home(-1) +l.wait_for_home(joints=[1,1,1,1,0,0,0,0,0]) + +# check for startup codes (must match ini [RS274NGC] RS274NGC_STARTUP_CODE ) +s.poll() +print("startup gcodes ", s.gcodes) + +# change some states +c.mode(linuxcnc.MODE_MDI) +c.wait_complete() +# move tool +c.mdi("G0 x 1.23") +c.wait_complete() +# Set G55 with offset +c.mdi("G55") +c.wait_complete() +c.mdi("G10 L2 P0 Z1") +c.wait_complete() + +# parse gcode test file +try: + initcodes = preview_helpers.create_unitcode_and_initcode(s, inifile) + result, seq = gcode.parse(filename, canon, *initcodes) + if result > gcode.MIN_ERROR: + print(f"G-code error at line {seq}: error code {result}",file=sys.stderr) + sys.exit(1) + +except Exception as e: + print(e,file=sys.stderr) + sys.exit(1) + +finally: + log_file.close() + canon.close() diff --git a/tests/interp_initcode/test.ini b/tests/interp_initcode/test.ini new file mode 100644 index 00000000000..d183d9276b9 --- /dev/null +++ b/tests/interp_initcode/test.ini @@ -0,0 +1,106 @@ +[EMC] +VERSION = 1.1 +MACHINE = preview_test_9_axis + DEBUG = 0 + +[DISPLAY] +DISPLAY = ./test-ui.py + +[FILTER] + +[TASK] +TASK = milltask +CYCLE_TIME = 0.001 + +[RS274NGC] +RS274NGC_STARTUP_CODE = G17 G20 G40 G43H0 G54 G64P0.005 G80 G90 G94 G97 M5 M9 +PARAMETER_FILE = test.var + +[PYTHON] + +[EMCMOT] +EMCMOT = motmod +COMM_TIMEOUT = 1.0 +BASE_PERIOD = 600000 +SERVO_PERIOD = 1000000 + +[EMCIO] +TOOL_TABLE = tool.tbl +TOOL_CHANGE_POSITION = 0 0 2 + +[HAL] +HALUI = halui +HALFILE = LIB:core_sim.hal +HALFILE = LIB:simulated_home.hal +HALFILE = LIB:lathe.hal + +[TRAJ] +COORDINATES = X Y Z A +LINEAR_UNITS = inch +ANGULAR_UNITS = degree +DEFAULT_LINEAR_VELOCITY = 50.0 +DEFAULT_LINEAR_ACCEL = 500.0 +DEFAULT_ANGULAR_VELOCITY = 45.0 +MAX_LINEAR_VELOCITY = 200.0 +MAX_LINEAR_ACCEL = 250.0 +MAX_ANGULAR_VELOCITY = 90.0 + +[KINS] +KINEMATICS = trivkins coordinates=XYZA +JOINTS = 4 + +[AXIS_X] +MIN_LIMIT = -250.0 +MAX_LIMIT = 250.0 +MAX_VELOCITY = 100 +MAX_ACCELERATION = 1250 + +[AXIS_Y] +MIN_LIMIT = -250.0 +MAX_LIMIT = 250.0 +MAX_VELOCITY = 100 +MAX_ACCELERATION = 1250 + +[AXIS_Z] +MIN_LIMIT = -50.0 +MAX_LIMIT = 100.0 +MAX_VELOCITY = 100 +MAX_ACCELERATION = 1250 + +[AXIS_A] +MIN_LIMIT = -360.0 +MAX_LIMIT = 360.0 +MAX_VELOCITY = 90.0 +MAX_ACCELERATION = 1200.0 + + +[JOINT_0] +TYPE = LINEAR +MAX_VELOCITY = 100 +MAX_ACCELERATION = 1250 +MIN_LIMIT = -250.0 +MAX_LIMIT = 250.0 +HOME_SEQUENCE = 0 + +[JOINT_1] +TYPE = LINEAR +MAX_VELOCITY = 100 +MAX_ACCELERATION = 1250 +MIN_LIMIT = -250.0 +MAX_LIMIT = 250.0 +HOME_SEQUENCE = 0 + +[JOINT_2] +TYPE = LINEAR +MAX_VELOCITY = 100 +MAX_ACCELERATION = 1250 +MIN_LIMIT = -50.0 +MAX_LIMIT = 100.0 +HOME_SEQUENCE = 0 + +[JOINT_3] +TYPE = ANGULAR +MAX_VELOCITY = 90.0 +MAX_ACCELERATION = 1200.0 +HOME_SEQUENCE = 0 + diff --git a/tests/interp_initcode/test.ngc b/tests/interp_initcode/test.ngc new file mode 100644 index 00000000000..9f1f8460ae3 --- /dev/null +++ b/tests/interp_initcode/test.ngc @@ -0,0 +1,7 @@ +;test respecting current tool position (issue #3855) +G2 I20 J0 P1 F100 + +;test respecting current WCS offsets (issue #2753) +G0 X10 + +M2 diff --git a/tests/interp_initcode/test.sh b/tests/interp_initcode/test.sh new file mode 100644 index 00000000000..eb54d8f4056 --- /dev/null +++ b/tests/interp_initcode/test.sh @@ -0,0 +1,12 @@ +#!/bin/bash -e + +# remove possibly leftover files +rm -f temp_log test.var test.var.bak + +# start linuxcnc headless and create result file +if linuxcnc -r test.ini; then + cp -f temp_log result +fi + +# clean up +rm -f test.var test.var.bak temp_log