mirror of
https://git.mirrors.martin98.com/https://github.com/petaflot/pygcode
synced 2025-07-28 09:02:02 +08:00
linuxcnc word map
This commit is contained in:
parent
71d3e02261
commit
5577d6560e
@ -34,6 +34,7 @@ __all__ = [
|
|||||||
'Block',
|
'Block',
|
||||||
# Comment
|
# Comment
|
||||||
'Comment', 'split_line',
|
'Comment', 'split_line',
|
||||||
|
|
||||||
# Word
|
# Word
|
||||||
'Word', 'text2words', 'str2word', 'words2dict',
|
'Word', 'text2words', 'str2word', 'words2dict',
|
||||||
|
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
import re
|
import re
|
||||||
from .words import text2words, WORD_MAP
|
from .words import text2words
|
||||||
from .gcodes import words2gcodes
|
from .gcodes import words2gcodes
|
||||||
|
from . import dialects
|
||||||
|
|
||||||
|
|
||||||
class Block(object):
|
class Block(object):
|
||||||
"""GCode block (effectively any gcode file line that defines any <word><value>)"""
|
"""GCode block (effectively any gcode file line that defines any <word><value>)"""
|
||||||
|
|
||||||
def __init__(self, text=None, verify=True):
|
def __init__(self, text=None, dialect=None, verify=True):
|
||||||
"""
|
"""
|
||||||
Block Constructor
|
Block Constructor
|
||||||
:param text: gcode line content (including comments) as string
|
:param text: gcode line content (including comments) as string
|
||||||
@ -26,6 +28,12 @@ class Block(object):
|
|||||||
self.gcodes = []
|
self.gcodes = []
|
||||||
self.modal_params = []
|
self.modal_params = []
|
||||||
|
|
||||||
|
if dialect is None:
|
||||||
|
dialect = dialects.get_default()
|
||||||
|
self.dialect = dialect
|
||||||
|
|
||||||
|
self._word_map = getattr(getattr(dialects, dialect), 'WORD_MAP')
|
||||||
|
|
||||||
# clean up block string
|
# clean up block string
|
||||||
if text:
|
if text:
|
||||||
self._raw_text = text # unaltered block content (before alteration)
|
self._raw_text = text # unaltered block content (before alteration)
|
||||||
@ -71,7 +79,7 @@ class Block(object):
|
|||||||
modal_groups.add(gc.modal_group)
|
modal_groups.add(gc.modal_group)
|
||||||
|
|
||||||
def __getattr__(self, k):
|
def __getattr__(self, k):
|
||||||
if k in WORD_MAP:
|
if k in self._word_map:
|
||||||
for w in self.words:
|
for w in self.words:
|
||||||
if w.letter == k:
|
if w.letter == k:
|
||||||
return w
|
return w
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
__all__ = [
|
|
||||||
|
|
||||||
'DEFAULT',
|
|
||||||
|
|
||||||
# registration decorators
|
|
||||||
'gcode_dialect',
|
|
||||||
'word_dialect',
|
|
||||||
]
|
|
||||||
|
|
||||||
DEFAULT = 'linuxcnc'
|
|
||||||
|
|
||||||
# Registration decorators
|
|
||||||
from .mapping import gcode_dialect
|
|
||||||
from .mapping import word_dialect
|
|
@ -1,18 +0,0 @@
|
|||||||
"""
|
|
||||||
LinuxCNC
|
|
||||||
|
|
||||||
The linuxcnc gcode dialect is typically used for subtractive fabrication, such
|
|
||||||
as milling.
|
|
||||||
|
|
||||||
This dialect is the basis for all other dialects; GCodes and Words in other
|
|
||||||
dialects either inherit, or directly reference these classes.
|
|
||||||
|
|
||||||
**Specification:** http://www.linuxcnc.org
|
|
||||||
|
|
||||||
TODO: verify above info before publishing
|
|
||||||
"""
|
|
||||||
|
|
||||||
# ======================== WORDS ========================
|
|
||||||
|
|
||||||
|
|
||||||
# ======================== G-CODES ========================
|
|
55
src/pygcode/dialects/__init__.py
Normal file
55
src/pygcode/dialects/__init__.py
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
__all__ = [
|
||||||
|
'DEFAULT',
|
||||||
|
|
||||||
|
# registration decorators
|
||||||
|
'gcode_dialect',
|
||||||
|
'word_dialect',
|
||||||
|
|
||||||
|
# dialects
|
||||||
|
'linuxcnc',
|
||||||
|
'reprap',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# Registration decorators
|
||||||
|
from .mapping import gcode_dialect
|
||||||
|
from .mapping import word_dialect
|
||||||
|
|
||||||
|
# Dialects
|
||||||
|
from . import linuxcnc
|
||||||
|
from . import reprap
|
||||||
|
|
||||||
|
|
||||||
|
_DEFAULT = 'linuxcnc'
|
||||||
|
|
||||||
|
|
||||||
|
def get_default():
|
||||||
|
"""
|
||||||
|
Get the default gcode interpreter dialect.
|
||||||
|
(see :meth:`set_default` for details)
|
||||||
|
"""
|
||||||
|
return _DEFAULT
|
||||||
|
|
||||||
|
|
||||||
|
def set_default(name):
|
||||||
|
"""
|
||||||
|
Set the default gcode interpreter dialect.
|
||||||
|
This dialect will be used if no other is specified for particular function
|
||||||
|
calls.
|
||||||
|
|
||||||
|
:param name: name of dialect
|
||||||
|
:type name: :class:`str`
|
||||||
|
|
||||||
|
.. doctest::
|
||||||
|
|
||||||
|
>>> from pygcode import dialect
|
||||||
|
>>> dialect.get_default()
|
||||||
|
'linuxcnc'
|
||||||
|
>>> dialect.set_default('reprap')
|
||||||
|
>>> dialect.get_default()
|
||||||
|
'reprap'
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# TODO: verify valid name
|
||||||
|
_DEFAULT = name
|
216
src/pygcode/dialects/linuxcnc.py
Normal file
216
src/pygcode/dialects/linuxcnc.py
Normal file
@ -0,0 +1,216 @@
|
|||||||
|
"""
|
||||||
|
LinuxCNC
|
||||||
|
|
||||||
|
The linuxcnc gcode dialect is typically used for subtractive fabrication, such
|
||||||
|
as milling.
|
||||||
|
|
||||||
|
This dialect is the basis for all other dialects; GCodes and Words in other
|
||||||
|
dialects either inherit, or directly reference these classes.
|
||||||
|
|
||||||
|
**Specification:** http://www.linuxcnc.org
|
||||||
|
|
||||||
|
TODO: verify above info before publishing
|
||||||
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
|
from .utils import WordType
|
||||||
|
|
||||||
|
# ======================== WORDS ========================
|
||||||
|
|
||||||
|
REGEX_FLOAT = re.compile(r'^\s*-?(\d+\.?\d*|\.\d+)') # testcase: ..tests.test_words.WordValueMatchTests.test_float
|
||||||
|
REGEX_INT = re.compile(r'^\s*-?\d+')
|
||||||
|
REGEX_POSITIVEINT = re.compile(r'^\s*\d+')
|
||||||
|
REGEX_CODE = re.compile(r'^\s*\d+(\.\d)?') # float, but can't be negative
|
||||||
|
|
||||||
|
# Value cleaning functions
|
||||||
|
def _clean_codestr(value):
|
||||||
|
if value < 10:
|
||||||
|
return "0%g" % value
|
||||||
|
return "%g" % value
|
||||||
|
|
||||||
|
CLEAN_NONE = lambda v: v
|
||||||
|
CLEAN_FLOAT = lambda v: "{0:g}".format(round(v, 3))
|
||||||
|
CLEAN_CODE = _clean_codestr
|
||||||
|
CLEAN_INT = lambda v: "%g" % v
|
||||||
|
|
||||||
|
WORD_MAP = {
|
||||||
|
# Descriptions copied from wikipedia:
|
||||||
|
# https://en.wikipedia.org/wiki/G-code#Letter_addresses
|
||||||
|
|
||||||
|
# Rotational Axes
|
||||||
|
'A': WordType(
|
||||||
|
cls=float,
|
||||||
|
value_regex=REGEX_FLOAT,
|
||||||
|
description="Absolute or incremental position of A axis (rotational axis around X axis)",
|
||||||
|
clean_value=CLEAN_FLOAT,
|
||||||
|
),
|
||||||
|
'B': WordType(
|
||||||
|
cls=float,
|
||||||
|
value_regex=REGEX_FLOAT,
|
||||||
|
description="Absolute or incremental position of B axis (rotational axis around Y axis)",
|
||||||
|
clean_value=CLEAN_FLOAT,
|
||||||
|
),
|
||||||
|
'C': WordType(
|
||||||
|
cls=float,
|
||||||
|
value_regex=REGEX_FLOAT,
|
||||||
|
description="Absolute or incremental position of C axis (rotational axis around Z axis)",
|
||||||
|
clean_value=CLEAN_FLOAT,
|
||||||
|
),
|
||||||
|
'D': WordType(
|
||||||
|
cls=float,
|
||||||
|
value_regex=REGEX_FLOAT,
|
||||||
|
description="Defines diameter or radial offset used for cutter compensation. D is used for depth of cut on lathes. It is used for aperture selection and commands on photoplotters.",
|
||||||
|
clean_value=CLEAN_FLOAT,
|
||||||
|
),
|
||||||
|
# Feed Rates
|
||||||
|
'E': WordType(
|
||||||
|
cls=float,
|
||||||
|
value_regex=REGEX_FLOAT,
|
||||||
|
description="Precision feedrate for threading on lathes",
|
||||||
|
clean_value=CLEAN_FLOAT,
|
||||||
|
),
|
||||||
|
'F': WordType(
|
||||||
|
cls=float,
|
||||||
|
value_regex=REGEX_FLOAT,
|
||||||
|
description="Feedrate",
|
||||||
|
clean_value=CLEAN_FLOAT,
|
||||||
|
),
|
||||||
|
# G-Codes
|
||||||
|
'G': WordType(
|
||||||
|
cls=float,
|
||||||
|
value_regex=REGEX_CODE,
|
||||||
|
description="Address for preparatory commands",
|
||||||
|
clean_value=CLEAN_CODE,
|
||||||
|
),
|
||||||
|
# Tool Offsets
|
||||||
|
'H': WordType(
|
||||||
|
cls=float,
|
||||||
|
value_regex=REGEX_FLOAT,
|
||||||
|
description="Defines tool length offset; Incremental axis corresponding to C axis (e.g., on a turn-mill)",
|
||||||
|
clean_value=CLEAN_FLOAT,
|
||||||
|
),
|
||||||
|
# Arc radius center coords
|
||||||
|
'I': WordType(
|
||||||
|
cls=float,
|
||||||
|
value_regex=REGEX_FLOAT,
|
||||||
|
description="Defines arc center in X axis for G02 or G03 arc commands. Also used as a parameter within some fixed cycles.",
|
||||||
|
clean_value=CLEAN_FLOAT,
|
||||||
|
),
|
||||||
|
'J': WordType(
|
||||||
|
cls=float,
|
||||||
|
value_regex=REGEX_FLOAT,
|
||||||
|
description="Defines arc center in Y axis for G02 or G03 arc commands. Also used as a parameter within some fixed cycles.",
|
||||||
|
clean_value=CLEAN_FLOAT,
|
||||||
|
),
|
||||||
|
'K': WordType(
|
||||||
|
cls=float,
|
||||||
|
value_regex=REGEX_FLOAT,
|
||||||
|
description="Defines arc center in Z axis for G02 or G03 arc commands. Also used as a parameter within some fixed cycles, equal to L address.",
|
||||||
|
clean_value=CLEAN_FLOAT,
|
||||||
|
),
|
||||||
|
# Loop Count
|
||||||
|
'L': WordType(
|
||||||
|
cls=int,
|
||||||
|
value_regex=REGEX_POSITIVEINT,
|
||||||
|
description="Fixed cycle loop count; Specification of what register to edit using G10",
|
||||||
|
clean_value=CLEAN_INT,
|
||||||
|
),
|
||||||
|
# Miscellaneous Function
|
||||||
|
'M': WordType(
|
||||||
|
cls=float,
|
||||||
|
value_regex=REGEX_CODE,
|
||||||
|
description="Miscellaneous function",
|
||||||
|
clean_value=CLEAN_CODE,
|
||||||
|
),
|
||||||
|
# Line Number
|
||||||
|
'N': WordType(
|
||||||
|
cls=int,
|
||||||
|
value_regex=REGEX_POSITIVEINT,
|
||||||
|
description="Line (block) number in program; System parameter number to change using G10",
|
||||||
|
clean_value=CLEAN_INT,
|
||||||
|
),
|
||||||
|
# Program Name
|
||||||
|
'O': WordType(
|
||||||
|
cls=str,
|
||||||
|
value_regex=re.compile(r'^.+$'), # all the way to the end
|
||||||
|
description="Program name",
|
||||||
|
clean_value=CLEAN_NONE,
|
||||||
|
),
|
||||||
|
# Parameter (arbitrary parameter)
|
||||||
|
'P': WordType(
|
||||||
|
cls=float, # parameter is often an integer, but can be a float
|
||||||
|
value_regex=REGEX_FLOAT,
|
||||||
|
description="Serves as parameter address for various G and M codes",
|
||||||
|
clean_value=CLEAN_FLOAT,
|
||||||
|
),
|
||||||
|
# Peck increment
|
||||||
|
'Q': WordType(
|
||||||
|
cls=float,
|
||||||
|
value_regex=REGEX_FLOAT,
|
||||||
|
description="Depth to increase on each peck; Peck increment in canned cycles",
|
||||||
|
clean_value=CLEAN_FLOAT,
|
||||||
|
),
|
||||||
|
# Arc Radius
|
||||||
|
'R': WordType(
|
||||||
|
cls=float,
|
||||||
|
value_regex=REGEX_FLOAT,
|
||||||
|
description="Defines size of arc radius, or defines retract height in milling canned cycles",
|
||||||
|
clean_value=CLEAN_FLOAT,
|
||||||
|
),
|
||||||
|
# Spindle speed
|
||||||
|
'S': WordType(
|
||||||
|
cls=float,
|
||||||
|
value_regex=REGEX_FLOAT,
|
||||||
|
description="Defines speed, either spindle speed or surface speed depending on mode",
|
||||||
|
clean_value=CLEAN_FLOAT,
|
||||||
|
),
|
||||||
|
# Tool Selecton
|
||||||
|
'T': WordType(
|
||||||
|
cls=str,
|
||||||
|
value_regex=REGEX_POSITIVEINT, # tool string may have leading '0's, but is effectively an index (integer)
|
||||||
|
description="Tool selection",
|
||||||
|
clean_value=CLEAN_NONE,
|
||||||
|
),
|
||||||
|
# Incremental axes
|
||||||
|
'U': WordType(
|
||||||
|
cls=float,
|
||||||
|
value_regex=REGEX_FLOAT,
|
||||||
|
description="Incremental axis corresponding to X axis (typically only lathe group A controls) Also defines dwell time on some machines (instead of 'P' or 'X').",
|
||||||
|
clean_value=CLEAN_FLOAT,
|
||||||
|
),
|
||||||
|
'V': WordType(
|
||||||
|
cls=float,
|
||||||
|
value_regex=REGEX_FLOAT,
|
||||||
|
description="Incremental axis corresponding to Y axis",
|
||||||
|
clean_value=CLEAN_FLOAT,
|
||||||
|
),
|
||||||
|
'W': WordType(
|
||||||
|
cls=float,
|
||||||
|
value_regex=REGEX_FLOAT,
|
||||||
|
description="Incremental axis corresponding to Z axis (typically only lathe group A controls)",
|
||||||
|
clean_value=CLEAN_FLOAT,
|
||||||
|
),
|
||||||
|
# Linear Axes
|
||||||
|
'X': WordType(
|
||||||
|
cls=float,
|
||||||
|
value_regex=REGEX_FLOAT,
|
||||||
|
description="Absolute or incremental position of X axis.",
|
||||||
|
clean_value=CLEAN_FLOAT,
|
||||||
|
),
|
||||||
|
'Y': WordType(
|
||||||
|
cls=float,
|
||||||
|
value_regex=REGEX_FLOAT,
|
||||||
|
description="Absolute or incremental position of Y axis.",
|
||||||
|
clean_value=CLEAN_FLOAT,
|
||||||
|
),
|
||||||
|
'Z': WordType(
|
||||||
|
cls=float,
|
||||||
|
value_regex=REGEX_FLOAT,
|
||||||
|
description="Absolute or incremental position of Z axis.",
|
||||||
|
clean_value=CLEAN_FLOAT,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# ======================== G-CODES ========================
|
9
src/pygcode/dialects/utils.py
Normal file
9
src/pygcode/dialects/utils.py
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
# Data Classes
|
||||||
|
|
||||||
|
class WordType(object):
|
||||||
|
def __init__(self, cls, value_regex, description, clean_value):
|
||||||
|
self.cls = cls
|
||||||
|
self.value_regex = value_regex
|
||||||
|
self.description = description
|
||||||
|
self.clean_value = clean_value
|
@ -2,218 +2,31 @@ import re
|
|||||||
import itertools
|
import itertools
|
||||||
import six
|
import six
|
||||||
|
|
||||||
|
from . import dialects
|
||||||
from .exceptions import GCodeBlockFormatError, GCodeWordStrError
|
from .exceptions import GCodeBlockFormatError, GCodeWordStrError
|
||||||
|
|
||||||
REGEX_FLOAT = re.compile(r'^\s*-?(\d+\.?\d*|\.\d+)') # testcase: ..tests.test_words.WordValueMatchTests.test_float
|
|
||||||
REGEX_INT = re.compile(r'^\s*-?\d+')
|
|
||||||
REGEX_POSITIVEINT = re.compile(r'^\s*\d+')
|
|
||||||
REGEX_CODE = re.compile(r'^\s*\d+(\.\d)?') # float, but can't be negative
|
|
||||||
|
|
||||||
# Value cleaning functions
|
|
||||||
def _clean_codestr(value):
|
|
||||||
if value < 10:
|
|
||||||
return "0%g" % value
|
|
||||||
return "%g" % value
|
|
||||||
|
|
||||||
CLEAN_NONE = lambda v: v
|
|
||||||
CLEAN_FLOAT = lambda v: "{0:g}".format(round(v, 3))
|
|
||||||
CLEAN_CODE = _clean_codestr
|
|
||||||
CLEAN_INT = lambda v: "%g" % v
|
|
||||||
|
|
||||||
WORD_MAP = {
|
|
||||||
# Descriptions copied from wikipedia:
|
|
||||||
# https://en.wikipedia.org/wiki/G-code#Letter_addresses
|
|
||||||
|
|
||||||
# Rotational Axes
|
|
||||||
'A': {
|
|
||||||
'class': float,
|
|
||||||
'value_regex': REGEX_FLOAT,
|
|
||||||
'description': "Absolute or incremental position of A axis (rotational axis around X axis)",
|
|
||||||
'clean_value': CLEAN_FLOAT,
|
|
||||||
},
|
|
||||||
'B': {
|
|
||||||
'class': float,
|
|
||||||
'value_regex': REGEX_FLOAT,
|
|
||||||
'description': "Absolute or incremental position of B axis (rotational axis around Y axis)",
|
|
||||||
'clean_value': CLEAN_FLOAT,
|
|
||||||
},
|
|
||||||
'C': {
|
|
||||||
'class': float,
|
|
||||||
'value_regex': REGEX_FLOAT,
|
|
||||||
'description': "Absolute or incremental position of C axis (rotational axis around Z axis)",
|
|
||||||
'clean_value': CLEAN_FLOAT,
|
|
||||||
},
|
|
||||||
'D': {
|
|
||||||
'class': float,
|
|
||||||
'value_regex': REGEX_FLOAT,
|
|
||||||
'description': "Defines diameter or radial offset used for cutter compensation. D is used for depth of cut on lathes. It is used for aperture selection and commands on photoplotters.",
|
|
||||||
'clean_value': CLEAN_FLOAT,
|
|
||||||
},
|
|
||||||
# Feed Rates
|
|
||||||
'E': {
|
|
||||||
'class': float,
|
|
||||||
'value_regex': REGEX_FLOAT,
|
|
||||||
'description': "Precision feedrate for threading on lathes",
|
|
||||||
'clean_value': CLEAN_FLOAT,
|
|
||||||
},
|
|
||||||
'F': {
|
|
||||||
'class': float,
|
|
||||||
'value_regex': REGEX_FLOAT,
|
|
||||||
'description': "Feedrate",
|
|
||||||
'clean_value': CLEAN_FLOAT,
|
|
||||||
},
|
|
||||||
# G-Codes
|
|
||||||
'G': {
|
|
||||||
'class': float,
|
|
||||||
'value_regex': REGEX_CODE,
|
|
||||||
'description': "Address for preparatory commands",
|
|
||||||
'clean_value': CLEAN_CODE,
|
|
||||||
},
|
|
||||||
# Tool Offsets
|
|
||||||
'H': {
|
|
||||||
'class': float,
|
|
||||||
'value_regex': REGEX_FLOAT,
|
|
||||||
'description': "Defines tool length offset; Incremental axis corresponding to C axis (e.g., on a turn-mill)",
|
|
||||||
'clean_value': CLEAN_FLOAT,
|
|
||||||
},
|
|
||||||
# Arc radius center coords
|
|
||||||
'I': {
|
|
||||||
'class': float,
|
|
||||||
'value_regex': REGEX_FLOAT,
|
|
||||||
'description': "Defines arc center in X axis for G02 or G03 arc commands. Also used as a parameter within some fixed cycles.",
|
|
||||||
'clean_value': CLEAN_FLOAT,
|
|
||||||
},
|
|
||||||
'J': {
|
|
||||||
'class': float,
|
|
||||||
'value_regex': REGEX_FLOAT,
|
|
||||||
'description': "Defines arc center in Y axis for G02 or G03 arc commands. Also used as a parameter within some fixed cycles.",
|
|
||||||
'clean_value': CLEAN_FLOAT,
|
|
||||||
},
|
|
||||||
'K': {
|
|
||||||
'class': float,
|
|
||||||
'value_regex': REGEX_FLOAT,
|
|
||||||
'description': "Defines arc center in Z axis for G02 or G03 arc commands. Also used as a parameter within some fixed cycles, equal to L address.",
|
|
||||||
'clean_value': CLEAN_FLOAT,
|
|
||||||
},
|
|
||||||
# Loop Count
|
|
||||||
'L': {
|
|
||||||
'class': int,
|
|
||||||
'value_regex': REGEX_POSITIVEINT,
|
|
||||||
'description': "Fixed cycle loop count; Specification of what register to edit using G10",
|
|
||||||
'clean_value': CLEAN_INT,
|
|
||||||
},
|
|
||||||
# Miscellaneous Function
|
|
||||||
'M': {
|
|
||||||
'class': float,
|
|
||||||
'value_regex': REGEX_CODE,
|
|
||||||
'description': "Miscellaneous function",
|
|
||||||
'clean_value': CLEAN_CODE,
|
|
||||||
},
|
|
||||||
# Line Number
|
|
||||||
'N': {
|
|
||||||
'class': int,
|
|
||||||
'value_regex': REGEX_POSITIVEINT,
|
|
||||||
'description': "Line (block) number in program; System parameter number to change using G10",
|
|
||||||
'clean_value': CLEAN_INT,
|
|
||||||
},
|
|
||||||
# Program Name
|
|
||||||
'O': {
|
|
||||||
'class': str,
|
|
||||||
'value_regex': re.compile(r'^.+$'), # all the way to the end
|
|
||||||
'description': "Program name",
|
|
||||||
'clean_value': CLEAN_NONE,
|
|
||||||
},
|
|
||||||
# Parameter (arbitrary parameter)
|
|
||||||
'P': {
|
|
||||||
'class': float, # parameter is often an integer, but can be a float
|
|
||||||
'value_regex': REGEX_FLOAT,
|
|
||||||
'description': "Serves as parameter address for various G and M codes",
|
|
||||||
'clean_value': CLEAN_FLOAT,
|
|
||||||
},
|
|
||||||
# Peck increment
|
|
||||||
'Q': {
|
|
||||||
'class': float,
|
|
||||||
'value_regex': REGEX_FLOAT,
|
|
||||||
'description': "Depth to increase on each peck; Peck increment in canned cycles",
|
|
||||||
'clean_value': CLEAN_FLOAT,
|
|
||||||
},
|
|
||||||
# Arc Radius
|
|
||||||
'R': {
|
|
||||||
'class': float,
|
|
||||||
'value_regex': REGEX_FLOAT,
|
|
||||||
'description': "Defines size of arc radius, or defines retract height in milling canned cycles",
|
|
||||||
'clean_value': CLEAN_FLOAT,
|
|
||||||
},
|
|
||||||
# Spindle speed
|
|
||||||
'S': {
|
|
||||||
'class': float,
|
|
||||||
'value_regex': REGEX_FLOAT,
|
|
||||||
'description': "Defines speed, either spindle speed or surface speed depending on mode",
|
|
||||||
'clean_value': CLEAN_FLOAT,
|
|
||||||
},
|
|
||||||
# Tool Selecton
|
|
||||||
'T': {
|
|
||||||
'class': str,
|
|
||||||
'value_regex': REGEX_POSITIVEINT, # tool string may have leading '0's, but is effectively an index (integer)
|
|
||||||
'description': "Tool selection",
|
|
||||||
'clean_value': CLEAN_NONE,
|
|
||||||
},
|
|
||||||
# Incremental axes
|
|
||||||
'U': {
|
|
||||||
'class': float,
|
|
||||||
'value_regex': REGEX_FLOAT,
|
|
||||||
'description': "Incremental axis corresponding to X axis (typically only lathe group A controls) Also defines dwell time on some machines (instead of 'P' or 'X').",
|
|
||||||
'clean_value': CLEAN_FLOAT,
|
|
||||||
},
|
|
||||||
'V': {
|
|
||||||
'class': float,
|
|
||||||
'value_regex': REGEX_FLOAT,
|
|
||||||
'description': "Incremental axis corresponding to Y axis",
|
|
||||||
'clean_value': CLEAN_FLOAT,
|
|
||||||
},
|
|
||||||
'W': {
|
|
||||||
'class': float,
|
|
||||||
'value_regex': REGEX_FLOAT,
|
|
||||||
'description': "Incremental axis corresponding to Z axis (typically only lathe group A controls)",
|
|
||||||
'clean_value': CLEAN_FLOAT,
|
|
||||||
},
|
|
||||||
# Linear Axes
|
|
||||||
'X': {
|
|
||||||
'class': float,
|
|
||||||
'value_regex': REGEX_FLOAT,
|
|
||||||
'description': "Absolute or incremental position of X axis.",
|
|
||||||
'clean_value': CLEAN_FLOAT,
|
|
||||||
},
|
|
||||||
'Y': {
|
|
||||||
'class': float,
|
|
||||||
'value_regex': REGEX_FLOAT,
|
|
||||||
'description': "Absolute or incremental position of Y axis.",
|
|
||||||
'clean_value': CLEAN_FLOAT,
|
|
||||||
},
|
|
||||||
'Z': {
|
|
||||||
'class': float,
|
|
||||||
'value_regex': REGEX_FLOAT,
|
|
||||||
'description': "Absolute or incremental position of Z axis.",
|
|
||||||
'clean_value': CLEAN_FLOAT,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class Word(object):
|
class Word(object):
|
||||||
def __init__(self, *args):
|
def __init__(self, *args, **kwargs):
|
||||||
if len(args) not in (1, 2):
|
# Parameters (listed)
|
||||||
raise AssertionError("input arguments either: (letter, value) or (word_str)")
|
args_count = len(args)
|
||||||
if len(args) == 2:
|
if args_count == 1:
|
||||||
# Word('G', 90)
|
|
||||||
(letter, value) = args
|
|
||||||
else:
|
|
||||||
# Word('G90')
|
# Word('G90')
|
||||||
letter = args[0][0] # first letter
|
letter = args[0][0] # first letter
|
||||||
value = args[0][1:] # rest of string
|
value = args[0][1:] # rest of string
|
||||||
|
elif args_count == 2:
|
||||||
|
# Word('G', 90)
|
||||||
|
(letter, value) = args
|
||||||
|
else:
|
||||||
|
raise AssertionError("input arguments either: (letter, value) or (word_str)")
|
||||||
|
|
||||||
|
# Parameters (keyword)
|
||||||
|
dialect = kwargs.pop('dialect', dialects.get_default())
|
||||||
|
|
||||||
letter = letter.upper()
|
letter = letter.upper()
|
||||||
|
|
||||||
self._value_class = WORD_MAP[letter]['class']
|
self._word_map = getattr(getattr(dialects, dialect), 'WORD_MAP')
|
||||||
self._value_clean = WORD_MAP[letter]['clean_value']
|
self._value_class = self._word_map[letter].cls
|
||||||
|
self._value_clean = self._word_map[letter].clean_value
|
||||||
|
|
||||||
self.letter = letter
|
self.letter = letter
|
||||||
self.value = value
|
self.value = value
|
||||||
@ -272,15 +85,19 @@ class Word(object):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def description(self):
|
def description(self):
|
||||||
return "%s: %s" % (self.letter, WORD_MAP[self.letter]['description'])
|
return "%s: %s" % (self.letter, self._word_map[self.letter].description)
|
||||||
|
|
||||||
|
|
||||||
def text2words(block_text):
|
def text2words(block_text, dialect=None):
|
||||||
"""
|
"""
|
||||||
Iterate through block text yielding Word instances
|
Iterate through block text yielding Word instances
|
||||||
:param block_text: text for given block with comments removed
|
:param block_text: text for given block with comments removed
|
||||||
"""
|
"""
|
||||||
next_word = re.compile(r'^.*?(?P<letter>[%s])' % ''.join(WORD_MAP.keys()), re.IGNORECASE)
|
if dialect is None:
|
||||||
|
dialect = dialects.get_default()
|
||||||
|
word_map = getattr(getattr(dialects, dialect), 'WORD_MAP')
|
||||||
|
|
||||||
|
next_word = re.compile(r'^.*?(?P<letter>[%s])' % ''.join(word_map.keys()), re.IGNORECASE)
|
||||||
|
|
||||||
index = 0
|
index = 0
|
||||||
while True:
|
while True:
|
||||||
@ -291,7 +108,7 @@ def text2words(block_text):
|
|||||||
index += letter_match.end() # propogate index to start of value
|
index += letter_match.end() # propogate index to start of value
|
||||||
|
|
||||||
# Value
|
# Value
|
||||||
value_regex = WORD_MAP[letter]['value_regex']
|
value_regex = word_map[letter].value_regex
|
||||||
value_match = value_regex.search(block_text[index:])
|
value_match = value_regex.search(block_text[index:])
|
||||||
if value_match is None:
|
if value_match is None:
|
||||||
raise GCodeWordStrError("word '%s' value invalid" % letter)
|
raise GCodeWordStrError("word '%s' value invalid" % letter)
|
||||||
|
@ -6,6 +6,7 @@ add_pygcode_to_path()
|
|||||||
|
|
||||||
# Units under test
|
# Units under test
|
||||||
from pygcode import words
|
from pygcode import words
|
||||||
|
from pygcode import dialects
|
||||||
|
|
||||||
|
|
||||||
class WordIterTests(unittest.TestCase):
|
class WordIterTests(unittest.TestCase):
|
||||||
@ -33,8 +34,7 @@ class WordIterTests(unittest.TestCase):
|
|||||||
self.assertEqual([w[5].letter, w[5].value], ['F', 70])
|
self.assertEqual([w[5].letter, w[5].value], ['F', 70])
|
||||||
|
|
||||||
|
|
||||||
class WordValueMatchTests(unittest.TestCase):
|
class WordValueMatchTest(unittest.TestCase):
|
||||||
|
|
||||||
def regex_assertions(self, regex, positive_list, negative_list):
|
def regex_assertions(self, regex, positive_list, negative_list):
|
||||||
# Assert all elements of positive_list match regex
|
# Assert all elements of positive_list match regex
|
||||||
for (value_str, expected_match) in positive_list:
|
for (value_str, expected_match) in positive_list:
|
||||||
@ -47,9 +47,11 @@ class WordValueMatchTests(unittest.TestCase):
|
|||||||
match = regex.search(value_str)
|
match = regex.search(value_str)
|
||||||
self.assertIsNone(match, "matched for '%s'" % value_str)
|
self.assertIsNone(match, "matched for '%s'" % value_str)
|
||||||
|
|
||||||
|
|
||||||
|
class WordTests_LinuxCNC(WordValueMatchTest):
|
||||||
def test_float(self):
|
def test_float(self):
|
||||||
self.regex_assertions(
|
self.regex_assertions(
|
||||||
regex=words.REGEX_FLOAT,
|
regex=dialects.linuxcnc.REGEX_FLOAT,
|
||||||
positive_list=[
|
positive_list=[
|
||||||
('1.2', '1.2'), ('1', '1'), ('200', '200'), ('0092', '0092'),
|
('1.2', '1.2'), ('1', '1'), ('200', '200'), ('0092', '0092'),
|
||||||
('1.', '1.'), ('.2', '.2'), ('-1.234', '-1.234'),
|
('1.', '1.'), ('.2', '.2'), ('-1.234', '-1.234'),
|
||||||
@ -63,7 +65,7 @@ class WordValueMatchTests(unittest.TestCase):
|
|||||||
|
|
||||||
def test_code(self):
|
def test_code(self):
|
||||||
self.regex_assertions(
|
self.regex_assertions(
|
||||||
regex=words.REGEX_CODE,
|
regex=dialects.linuxcnc.REGEX_CODE,
|
||||||
positive_list=[
|
positive_list=[
|
||||||
('1.2', '1.2'), ('1', '1'), ('10', '10'),
|
('1.2', '1.2'), ('1', '1'), ('10', '10'),
|
||||||
('02', '02'), ('02.3', '02.3'),
|
('02', '02'), ('02.3', '02.3'),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user