mirror of
https://git.mirrors.martin98.com/https://github.com/petaflot/pygcode
synced 2025-08-15 00:36:09 +08:00
gcodes sortable by linuxcnc execution order
This commit is contained in:
parent
3a5dec14f0
commit
cf5f9a17cd
@ -21,7 +21,32 @@ class Block(object):
|
|||||||
self.text = text
|
self.text = text
|
||||||
|
|
||||||
self.words = list(iter_words(self.text))
|
self.words = list(iter_words(self.text))
|
||||||
self.gcodes = list(words_to_gcodes(self.words))
|
(self.gcodes, self.modal_params) = words_to_gcodes(self.words)
|
||||||
|
|
||||||
|
self._assert_gcodes()
|
||||||
|
|
||||||
|
# TODO: gcode verification
|
||||||
|
# - gcodes in the same modal_group raises exception
|
||||||
|
|
||||||
|
def _assert_gcodes(self):
|
||||||
|
modal_groups = set()
|
||||||
|
code_words = set()
|
||||||
|
for gc in self.gcodes:
|
||||||
|
# Assert all gcodes are not repeated in the same block
|
||||||
|
if gc.word in code_words:
|
||||||
|
raise AssertionError("%s cannot be in the same block" % ([
|
||||||
|
x for x in self.gcodes
|
||||||
|
if x.modal_group == gc.modal_group
|
||||||
|
]))
|
||||||
|
code_words.add(gc.word)
|
||||||
|
# Assert all gcodes are from different modal groups
|
||||||
|
if gc.modal_group is not None:
|
||||||
|
if gc.modal_group in modal_groups:
|
||||||
|
raise AssertionError("%s cannot be in the same block" % ([
|
||||||
|
x for x in self.gcodes
|
||||||
|
if x.modal_group == 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 WORD_MAP:
|
||||||
|
@ -64,6 +64,34 @@ from .words import Word
|
|||||||
# Override Switches (Group 9) M48, M49
|
# Override Switches (Group 9) M48, M49
|
||||||
# User Defined (Group 10) M100-M199
|
# User Defined (Group 10) M100-M199
|
||||||
#
|
#
|
||||||
|
# Execution Order
|
||||||
|
# Order taken http://linuxcnc.org/docs/html/gcode/overview.html#_g_code_order_of_execution
|
||||||
|
# (as of 2017-07-03)
|
||||||
|
# 010: O-word commands (optionally followed by a comment but no other words allowed on the same line)
|
||||||
|
# 020: Comment (including message)
|
||||||
|
# 030: Set feed rate mode (G93, G94).
|
||||||
|
# 040: Set feed rate (F).
|
||||||
|
# 050: Set spindle speed (S).
|
||||||
|
# 060: Select tool (T).
|
||||||
|
# 070: HAL pin I/O (M62-M68).
|
||||||
|
# 080: Change tool (M6) and Set Tool Number (M61).
|
||||||
|
# 090: Spindle on or off (M3, M4, M5).
|
||||||
|
# 100: Save State (M70, M73), Restore State (M72), Invalidate State (M71).
|
||||||
|
# 110: Coolant on or off (M7, M8, M9).
|
||||||
|
# 120: Enable or disable overrides (M48, M49,M50,M51,M52,M53).
|
||||||
|
# 130: User-defined Commands (M100-M199).
|
||||||
|
# 140: Dwell (G4).
|
||||||
|
# 150: Set active plane (G17, G18, G19).
|
||||||
|
# 160: Set length units (G20, G21).
|
||||||
|
# 170: Cutter radius compensation on or off (G40, G41, G42)
|
||||||
|
# 180: Cutter length compensation on or off (G43, G49)
|
||||||
|
# 190: Coordinate system selection (G54, G55, G56, G57, G58, G59, G59.1, G59.2, G59.3).
|
||||||
|
# 200: Set path control mode (G61, G61.1, G64)
|
||||||
|
# 210: Set distance mode (G90, G91).
|
||||||
|
# 220: Set retract mode (G98, G99).
|
||||||
|
# 230: Go to reference location (G28, G30) or change coordinate system data (G10) or set axis offsets (G92, G92.1, G92.2, G94).
|
||||||
|
# 240: Perform motion (G0 to G3, G33, G38.x, G73, G76, G80 to G89), as modified (possibly) by G53.
|
||||||
|
# 250: Stop (M0, M1, M2, M30, M60).
|
||||||
|
|
||||||
|
|
||||||
class GCode(object):
|
class GCode(object):
|
||||||
@ -77,6 +105,9 @@ class GCode(object):
|
|||||||
# Modal Group
|
# Modal Group
|
||||||
modal_group = None
|
modal_group = None
|
||||||
|
|
||||||
|
# Execution Order
|
||||||
|
exec_order = 999 # if not otherwise specified, run last
|
||||||
|
|
||||||
def __init__(self, word, *params):
|
def __init__(self, word, *params):
|
||||||
assert isinstance(word, Word), "invalid gcode word %r" % code_word
|
assert isinstance(word, Word), "invalid gcode word %r" % code_word
|
||||||
self.word = word
|
self.word = word
|
||||||
@ -87,13 +118,16 @@ class GCode(object):
|
|||||||
self.add_parameter(param)
|
self.add_parameter(param)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<{class_name}: {gcode}{{{word_list}}}>".format(
|
param_str = ''
|
||||||
class_name=self.__class__.__name__,
|
if self.params:
|
||||||
gcode=self.word,
|
param_str = "{%s}" % (', '.join([
|
||||||
word_list=', '.join([
|
|
||||||
"{}".format(self.params[k])
|
"{}".format(self.params[k])
|
||||||
for k in sorted(self.params.keys())
|
for k in sorted(self.params.keys())
|
||||||
]),
|
]))
|
||||||
|
return "<{class_name}: {gcode}{params}>".format(
|
||||||
|
class_name=self.__class__.__name__,
|
||||||
|
gcode=self.word,
|
||||||
|
params=param_str,
|
||||||
)
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
@ -106,6 +140,10 @@ class GCode(object):
|
|||||||
]),
|
]),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Sort by exec_order
|
||||||
|
def __lt__(self, other):
|
||||||
|
return self.exec_order < other.exec_order
|
||||||
|
|
||||||
def add_parameter(self, word):
|
def add_parameter(self, word):
|
||||||
assert isinstance(word, Word), "invalid parameter class: %r" % word
|
assert isinstance(word, Word), "invalid parameter class: %r" % word
|
||||||
assert word.letter in self.param_letters, "invalid parameter for %s: %s" % (self.__class__.__name__, str(word))
|
assert word.letter in self.param_letters, "invalid parameter for %s: %s" % (self.__class__.__name__, str(word))
|
||||||
@ -113,6 +151,7 @@ class GCode(object):
|
|||||||
self.params[word.letter] = word
|
self.params[word.letter] = word
|
||||||
|
|
||||||
def __getattr__(self, key):
|
def __getattr__(self, key):
|
||||||
|
# Return parameter values (if valid parameter for gcode)
|
||||||
if key in self.param_letters:
|
if key in self.param_letters:
|
||||||
if key in self.params:
|
if key in self.params:
|
||||||
return self.params[key].value
|
return self.params[key].value
|
||||||
@ -124,6 +163,10 @@ class GCode(object):
|
|||||||
key=key
|
key=key
|
||||||
))
|
))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def description(self):
|
||||||
|
return self.__doc__
|
||||||
|
|
||||||
|
|
||||||
# ======================= Motion =======================
|
# ======================= Motion =======================
|
||||||
# (X Y Z A B C U V W apply to all motions)
|
# (X Y Z A B C U V W apply to all motions)
|
||||||
@ -143,7 +186,7 @@ class GCode(object):
|
|||||||
class GCodeMotion(GCode):
|
class GCodeMotion(GCode):
|
||||||
param_letters = set('XYZABCUVW')
|
param_letters = set('XYZABCUVW')
|
||||||
modal_group = 1
|
modal_group = 1
|
||||||
|
exec_order = 241
|
||||||
|
|
||||||
class GCodeRapidMove(GCodeMotion):
|
class GCodeRapidMove(GCodeMotion):
|
||||||
"""G0: Rapid Move"""
|
"""G0: Rapid Move"""
|
||||||
@ -175,6 +218,7 @@ class GCodeDwell(GCodeMotion):
|
|||||||
param_letters = GCodeMotion.param_letters | set('P')
|
param_letters = GCodeMotion.param_letters | set('P')
|
||||||
word_key = Word('G', 4)
|
word_key = Word('G', 4)
|
||||||
modal_group = None # one of the few motion commands that isn't modal
|
modal_group = None # one of the few motion commands that isn't modal
|
||||||
|
exec_order = 140
|
||||||
|
|
||||||
|
|
||||||
class GCodeCublcSpline(GCodeMotion):
|
class GCodeCublcSpline(GCodeMotion):
|
||||||
@ -238,6 +282,7 @@ class GCodeCancelCannedCycle(GCodeMotion):
|
|||||||
class GCodeCannedCycle(GCode):
|
class GCodeCannedCycle(GCode):
|
||||||
param_letters = set('XYZUVW')
|
param_letters = set('XYZUVW')
|
||||||
modal_group = 1
|
modal_group = 1
|
||||||
|
exec_order = 241
|
||||||
|
|
||||||
class GCodeDrillingCycle(GCodeCannedCycle):
|
class GCodeDrillingCycle(GCodeCannedCycle):
|
||||||
"""G81: Drilling Cycle"""
|
"""G81: Drilling Cycle"""
|
||||||
@ -289,7 +334,7 @@ class GCodeThreadingCycle(GCodeCannedCycle):
|
|||||||
# G8 Lathe Radius Mode
|
# G8 Lathe Radius Mode
|
||||||
|
|
||||||
class GCodeDistanceMode(GCode):
|
class GCodeDistanceMode(GCode):
|
||||||
pass
|
exec_order = 210
|
||||||
|
|
||||||
|
|
||||||
class GCodeAbsoluteDistanceMode(GCodeDistanceMode):
|
class GCodeAbsoluteDistanceMode(GCodeDistanceMode):
|
||||||
@ -333,7 +378,7 @@ class GCodeLatheRadiusMode(GCodeDistanceMode):
|
|||||||
|
|
||||||
class GCodeFeedRateMode(GCode):
|
class GCodeFeedRateMode(GCode):
|
||||||
modal_group = 5
|
modal_group = 5
|
||||||
|
exec_order = 30
|
||||||
|
|
||||||
class GCodeInverseTimeMode(GCodeFeedRateMode):
|
class GCodeInverseTimeMode(GCodeFeedRateMode):
|
||||||
"""G93: Inverse Time Mode"""
|
"""G93: Inverse Time Mode"""
|
||||||
@ -357,25 +402,25 @@ class GCodeUnitsPerRevolution(GCodeFeedRateMode):
|
|||||||
# G96, G97 S D Spindle Control Mode
|
# G96, G97 S D Spindle Control Mode
|
||||||
|
|
||||||
class GCodeSpindle(GCode):
|
class GCodeSpindle(GCode):
|
||||||
pass
|
exec_order = 90
|
||||||
|
|
||||||
|
|
||||||
class GCodeStartSpindleCW(GCodeSpindle):
|
class GCodeStartSpindleCW(GCodeSpindle):
|
||||||
"""M3: Start Spindle Clockwise"""
|
"""M3: Start Spindle Clockwise"""
|
||||||
param_letters = set('S')
|
#param_letters = set('S') # S is it's own gcode, makes no sense to be here
|
||||||
word_key = Word('M', 3)
|
word_key = Word('M', 3)
|
||||||
modal_group = 7
|
modal_group = 7
|
||||||
|
|
||||||
class GCodeStartSpindleCCW(GCodeSpindle):
|
class GCodeStartSpindleCCW(GCodeSpindle):
|
||||||
"""M4: Start Spindle Counter-Clockwise"""
|
"""M4: Start Spindle Counter-Clockwise"""
|
||||||
param_letters = set('S')
|
#param_letters = set('S') # S is it's own gcode, makes no sense to be here
|
||||||
word_key = Word('M', 4)
|
word_key = Word('M', 4)
|
||||||
modal_group = 7
|
modal_group = 7
|
||||||
|
|
||||||
|
|
||||||
class GCodeStopSpindle(GCodeSpindle):
|
class GCodeStopSpindle(GCodeSpindle):
|
||||||
"""M5: Stop Spindle"""
|
"""M5: Stop Spindle"""
|
||||||
param_letters = set('S')
|
#param_letters = set('S') # S is it's own gcode, makes no sense to be here
|
||||||
word_key = Word('M', 5)
|
word_key = Word('M', 5)
|
||||||
modal_group = 7
|
modal_group = 7
|
||||||
|
|
||||||
@ -406,6 +451,7 @@ class GCodeSpindleRPMMode(GCodeSpindle):
|
|||||||
|
|
||||||
class GCodeCoolant(GCode):
|
class GCodeCoolant(GCode):
|
||||||
modal_group = 8
|
modal_group = 8
|
||||||
|
exec_order = 110
|
||||||
|
|
||||||
|
|
||||||
class GCodeCoolantMistOn(GCodeCoolant):
|
class GCodeCoolantMistOn(GCodeCoolant):
|
||||||
@ -432,6 +478,7 @@ class GCodeCoolantOff(GCodeCoolant):
|
|||||||
|
|
||||||
class GCodeToolLength(GCode):
|
class GCodeToolLength(GCode):
|
||||||
modal_group = 8
|
modal_group = 8
|
||||||
|
exec_order = 180
|
||||||
|
|
||||||
|
|
||||||
class GCodeToolLengthOffset(GCodeToolLength):
|
class GCodeToolLengthOffset(GCodeToolLength):
|
||||||
@ -464,7 +511,7 @@ class GCodeCancelToolLengthOffset(GCodeToolLength):
|
|||||||
|
|
||||||
class GCodeProgramControl(GCode):
|
class GCodeProgramControl(GCode):
|
||||||
modal_group = 4
|
modal_group = 4
|
||||||
|
exec_order = 250
|
||||||
|
|
||||||
class GCodePauseProgram(GCodeProgramControl):
|
class GCodePauseProgram(GCodeProgramControl):
|
||||||
"""M0: Program Pause"""
|
"""M0: Program Pause"""
|
||||||
@ -497,6 +544,7 @@ class GCodePalletChangePause(GCodeProgramControl):
|
|||||||
|
|
||||||
class GCodeUnit(GCode):
|
class GCodeUnit(GCode):
|
||||||
modal_group = 6
|
modal_group = 6
|
||||||
|
exec_order = 160
|
||||||
|
|
||||||
|
|
||||||
class GCodeUseInches(GCodeUnit):
|
class GCodeUseInches(GCodeUnit):
|
||||||
@ -516,6 +564,7 @@ class GCodeUseMillimeters(GCodeUnit):
|
|||||||
|
|
||||||
class GCodePlaneSelect(GCode):
|
class GCodePlaneSelect(GCode):
|
||||||
modal_group = 2
|
modal_group = 2
|
||||||
|
exec_order = 150
|
||||||
|
|
||||||
|
|
||||||
class GCodeSelectZYPlane(GCodePlaneSelect):
|
class GCodeSelectZYPlane(GCodePlaneSelect):
|
||||||
@ -556,6 +605,7 @@ class GCodeSelectVWPlane(GCodePlaneSelect):
|
|||||||
|
|
||||||
class GCodeCutterRadiusComp(GCode):
|
class GCodeCutterRadiusComp(GCode):
|
||||||
modal_group = 7
|
modal_group = 7
|
||||||
|
exec_order = 170
|
||||||
|
|
||||||
|
|
||||||
class GCodeCutterRadiusCompOff(GCodeCutterRadiusComp):
|
class GCodeCutterRadiusCompOff(GCodeCutterRadiusComp):
|
||||||
@ -594,6 +644,7 @@ class GCodeDynamicCutterCompRight(GCodeCutterRadiusComp):
|
|||||||
|
|
||||||
class GCodePathControlMode(GCode):
|
class GCodePathControlMode(GCode):
|
||||||
modal_group = 13
|
modal_group = 13
|
||||||
|
exec_order = 200
|
||||||
|
|
||||||
|
|
||||||
class GCodeExactPathMode(GCodePathControlMode):
|
class GCodeExactPathMode(GCodePathControlMode):
|
||||||
@ -618,6 +669,7 @@ class GCodePathBlendingMode(GCodePathControlMode):
|
|||||||
|
|
||||||
class GCodeCannedReturnMode(GCode):
|
class GCodeCannedReturnMode(GCode):
|
||||||
modal_group = 10
|
modal_group = 10
|
||||||
|
exec_order = 220
|
||||||
|
|
||||||
|
|
||||||
class GCodeCannedCycleReturnLevel(GCodeCannedReturnMode):
|
class GCodeCannedCycleReturnLevel(GCodeCannedReturnMode):
|
||||||
@ -646,10 +698,12 @@ class GCodeFeedRate(GCodeOtherModal):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def word_matches(cls, w):
|
def word_matches(cls, w):
|
||||||
return w.letter == 'F'
|
return w.letter == 'F'
|
||||||
# Modal Group n/a:
|
# Modal Group :
|
||||||
# although this sets the machine's state, there are no other codes to
|
# although this sets the machine's state, there are no other codes to
|
||||||
# group with this one, so although it's modal, it has no group.
|
# group with this one, so although it's modal, it usually has no group.
|
||||||
#modal_group = n/a
|
# However,
|
||||||
|
modal_group = 101
|
||||||
|
exec_order = 40
|
||||||
|
|
||||||
|
|
||||||
class GCodeSpindleSpeed(GCodeOtherModal):
|
class GCodeSpindleSpeed(GCodeOtherModal):
|
||||||
@ -657,10 +711,9 @@ class GCodeSpindleSpeed(GCodeOtherModal):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def word_matches(cls, w):
|
def word_matches(cls, w):
|
||||||
return w.letter == 'S'
|
return w.letter == 'S'
|
||||||
# Modal Group n/a:
|
# Modal Group: (see description in GCodeFeedRate)
|
||||||
# although this sets the machine's state, there are no other codes to
|
modal_group = 102
|
||||||
# group with this one, so although it's modal, it has no group.
|
exec_order = 50
|
||||||
#modal_group = n/a
|
|
||||||
|
|
||||||
|
|
||||||
class GCodeSelectTool(GCodeOtherModal):
|
class GCodeSelectTool(GCodeOtherModal):
|
||||||
@ -668,46 +721,51 @@ class GCodeSelectTool(GCodeOtherModal):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def word_matches(cls, w):
|
def word_matches(cls, w):
|
||||||
return w.letter == 'T'
|
return w.letter == 'T'
|
||||||
# Modal Group n/a:
|
# Modal Group: (see description in GCodeFeedRate)
|
||||||
# although this sets the machine's state, there are no other codes to
|
modal_group = 103
|
||||||
# group with this one, so although it's modal, it has no group.
|
exec_order = 60
|
||||||
#modal_group = n/a
|
|
||||||
|
|
||||||
|
|
||||||
class GCodeSpeedAndFeedOverrideOn(GCodeOtherModal):
|
class GCodeSpeedAndFeedOverrideOn(GCodeOtherModal):
|
||||||
"""M48: Speed and Feed Override Control On"""
|
"""M48: Speed and Feed Override Control On"""
|
||||||
word_key = Word('M', 48)
|
word_key = Word('M', 48)
|
||||||
modal_group = 9
|
modal_group = 9
|
||||||
|
exec_order = 120
|
||||||
|
|
||||||
|
|
||||||
class GCodeSpeedAndFeedOverrideOff(GCodeOtherModal):
|
class GCodeSpeedAndFeedOverrideOff(GCodeOtherModal):
|
||||||
"""M49: Speed and Feed Override Control Off"""
|
"""M49: Speed and Feed Override Control Off"""
|
||||||
word_key = Word('M', 49)
|
word_key = Word('M', 49)
|
||||||
modal_group = 9
|
modal_group = 9
|
||||||
|
exec_order = 120
|
||||||
|
|
||||||
|
|
||||||
class GCodeFeedOverride(GCodeOtherModal):
|
class GCodeFeedOverride(GCodeOtherModal):
|
||||||
"""M50: Feed Override Control"""
|
"""M50: Feed Override Control"""
|
||||||
param_letters = set('P')
|
param_letters = set('P')
|
||||||
word_key = Word('M', 50)
|
word_key = Word('M', 50)
|
||||||
|
exec_order = 120
|
||||||
|
|
||||||
|
|
||||||
class GCodeSpindleSpeedOverride(GCodeOtherModal):
|
class GCodeSpindleSpeedOverride(GCodeOtherModal):
|
||||||
"""M51: Spindle Speed Override Control"""
|
"""M51: Spindle Speed Override Control"""
|
||||||
param_letters = set('P')
|
param_letters = set('P')
|
||||||
word_key = Word('M', 51)
|
word_key = Word('M', 51)
|
||||||
|
exec_order = 120
|
||||||
|
|
||||||
|
|
||||||
class GCodeAdaptiveFeed(GCodeOtherModal):
|
class GCodeAdaptiveFeed(GCodeOtherModal):
|
||||||
"""M52: Adaptive Feed Control"""
|
"""M52: Adaptive Feed Control"""
|
||||||
param_letters = set('P')
|
param_letters = set('P')
|
||||||
word_key = Word('M', 52)
|
word_key = Word('M', 52)
|
||||||
|
exec_order = 120
|
||||||
|
|
||||||
|
|
||||||
class GCodeFeedStop(GCodeOtherModal):
|
class GCodeFeedStop(GCodeOtherModal):
|
||||||
"""M53: Feed Stop Control"""
|
"""M53: Feed Stop Control"""
|
||||||
param_letters = set('P')
|
param_letters = set('P')
|
||||||
word_key = Word('M', 53)
|
word_key = Word('M', 53)
|
||||||
|
exec_order = 120
|
||||||
|
|
||||||
|
|
||||||
class GCodeSelectCoordinateSystem(GCodeOtherModal):
|
class GCodeSelectCoordinateSystem(GCodeOtherModal):
|
||||||
@ -726,6 +784,7 @@ class GCodeSelectCoordinateSystem(GCodeOtherModal):
|
|||||||
def word_matches(cls, w):
|
def word_matches(cls, w):
|
||||||
return (w.letter == 'G') and (w.value in [54, 55, 56, 57, 58, 59, 59.1, 59.2, 59.3])
|
return (w.letter == 'G') and (w.value in [54, 55, 56, 57, 58, 59, 59.1, 59.2, 59.3])
|
||||||
modal_group = 12
|
modal_group = 12
|
||||||
|
exec_order = 190
|
||||||
|
|
||||||
|
|
||||||
# ======================= Flow-control Codes =======================
|
# ======================= Flow-control Codes =======================
|
||||||
@ -750,7 +809,7 @@ class GCodeSelectCoordinateSystem(GCodeOtherModal):
|
|||||||
# M68 T Analog Output, Immediate
|
# M68 T Analog Output, Immediate
|
||||||
|
|
||||||
class GCodeIO(GCode):
|
class GCodeIO(GCode):
|
||||||
pass
|
exec_order = 70
|
||||||
|
|
||||||
|
|
||||||
class GCodeDigitalOutput(GCodeIO):
|
class GCodeDigitalOutput(GCodeIO):
|
||||||
@ -824,18 +883,21 @@ class GCodeToolChange(GCodeNonModal):
|
|||||||
"""M6: Tool Change"""
|
"""M6: Tool Change"""
|
||||||
param_letters = set('T')
|
param_letters = set('T')
|
||||||
word_key = Word('M', 6)
|
word_key = Word('M', 6)
|
||||||
|
exec_order = 80
|
||||||
|
|
||||||
|
|
||||||
class GCodeToolSetCurrent(GCodeNonModal):
|
class GCodeToolSetCurrent(GCodeNonModal):
|
||||||
"""M61: Set Current Tool"""
|
"""M61: Set Current Tool"""
|
||||||
param_letters = set('Q')
|
param_letters = set('Q')
|
||||||
word_key = Word('M', 61)
|
word_key = Word('M', 61)
|
||||||
|
exec_order = 80
|
||||||
|
|
||||||
|
|
||||||
class GCodeSet(GCodeNonModal):
|
class GCodeSet(GCodeNonModal):
|
||||||
"""G10: Set stuff"""
|
"""G10: Set stuff"""
|
||||||
param_letters = set('LPQR')
|
param_letters = set('LPQR')
|
||||||
word_key = Word('G', 10)
|
word_key = Word('G', 10)
|
||||||
|
exec_order = 230
|
||||||
|
|
||||||
|
|
||||||
class GCodeGotoPredefinedPosition(GCodeNonModal):
|
class GCodeGotoPredefinedPosition(GCodeNonModal):
|
||||||
@ -843,6 +905,7 @@ class GCodeGotoPredefinedPosition(GCodeNonModal):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def word_matches(cls, w):
|
def word_matches(cls, w):
|
||||||
return (w.letter == 'G') and (w.value in [28, 30])
|
return (w.letter == 'G') and (w.value in [28, 30])
|
||||||
|
exec_order = 230
|
||||||
|
|
||||||
|
|
||||||
class GCodeSetPredefinedPosition(GCodeNonModal):
|
class GCodeSetPredefinedPosition(GCodeNonModal):
|
||||||
@ -850,16 +913,19 @@ class GCodeSetPredefinedPosition(GCodeNonModal):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def word_matches(cls, w):
|
def word_matches(cls, w):
|
||||||
return (w.letter == 'G') and (w.value in [28.1, 30.1])
|
return (w.letter == 'G') and (w.value in [28.1, 30.1])
|
||||||
|
exec_order = 230
|
||||||
|
|
||||||
|
|
||||||
class GCodeMoveInMachineCoords(GCodeNonModal):
|
class GCodeMoveInMachineCoords(GCodeNonModal):
|
||||||
"""G53: Move in Machine Coordinates"""
|
"""G53: Move in Machine Coordinates"""
|
||||||
word_key = Word('G', 53)
|
word_key = Word('G', 53)
|
||||||
|
exec_order = 240
|
||||||
|
|
||||||
|
|
||||||
class GCodeCoordSystemOffset(GCodeNonModal):
|
class GCodeCoordSystemOffset(GCodeNonModal):
|
||||||
"""G92: Coordinate System Offset"""
|
"""G92: Coordinate System Offset"""
|
||||||
word_key = Word('G', 92)
|
word_key = Word('G', 92)
|
||||||
|
exec_order = 230
|
||||||
|
|
||||||
|
|
||||||
class GCodeResetCoordSystemOffset(GCodeNonModal):
|
class GCodeResetCoordSystemOffset(GCodeNonModal):
|
||||||
@ -867,11 +933,13 @@ class GCodeResetCoordSystemOffset(GCodeNonModal):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def word_matches(cls, w):
|
def word_matches(cls, w):
|
||||||
return (w.letter == 'G') and (w.value in [92.1, 92.2])
|
return (w.letter == 'G') and (w.value in [92.1, 92.2])
|
||||||
|
exec_order = 230
|
||||||
|
|
||||||
|
|
||||||
class GCodeRestoreCoordSystemOffset(GCodeNonModal):
|
class GCodeRestoreCoordSystemOffset(GCodeNonModal):
|
||||||
"""G92.3: Restore Coordinate System Offset"""
|
"""G92.3: Restore Coordinate System Offset"""
|
||||||
word_key = Word('G', 92.3)
|
word_key = Word('G', 92.3)
|
||||||
|
exec_order = 230
|
||||||
|
|
||||||
|
|
||||||
class GCodeUserDefined(GCodeNonModal):
|
class GCodeUserDefined(GCodeNonModal):
|
||||||
@ -881,6 +949,7 @@ class GCodeUserDefined(GCodeNonModal):
|
|||||||
#@classmethod
|
#@classmethod
|
||||||
#def word_matches(cls, w):
|
#def word_matches(cls, w):
|
||||||
# return (w.letter == 'M') and (101 <= w.value <= 199)
|
# return (w.letter == 'M') and (101 <= w.value <= 199)
|
||||||
|
exec_order = 130
|
||||||
|
|
||||||
|
|
||||||
# ======================= Utilities =======================
|
# ======================= Utilities =======================
|
||||||
|
@ -44,3 +44,27 @@ class AbstractMachine(object):
|
|||||||
def process_line(self, line):
|
def process_line(self, line):
|
||||||
"""Change machine's state based on the given gcode line"""
|
"""Change machine's state based on the given gcode line"""
|
||||||
pass # TODO
|
pass # TODO
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
class Axes(object):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class MyMachineState(MachineState):
|
||||||
|
axes_state_class = AxesState
|
||||||
|
pass
|
||||||
|
|
||||||
|
class MyMachine(AbstractMachine):
|
||||||
|
available_axes = set('xyz')
|
||||||
|
state_class = MyMachineState
|
||||||
|
|
||||||
|
|
||||||
|
m = MyMachine(
|
||||||
|
state=MyMachineState(
|
||||||
|
absolute_position=
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
"""
|
||||||
|
@ -4,12 +4,12 @@ import six
|
|||||||
|
|
||||||
from .exceptions import GCodeBlockFormatError
|
from .exceptions import GCodeBlockFormatError
|
||||||
|
|
||||||
|
|
||||||
FLOAT_REGEX = re.compile(r'^-?(\d+\.?\d*|\.\d+)') # testcase: ..tests.test_words.WordValueMatchTests.test_float
|
FLOAT_REGEX = re.compile(r'^-?(\d+\.?\d*|\.\d+)') # testcase: ..tests.test_words.WordValueMatchTests.test_float
|
||||||
INT_REGEX = re.compile(r'^-?\d+')
|
INT_REGEX = re.compile(r'^-?\d+')
|
||||||
POSITIVEINT_REGEX = re.compile(r'^\d+')
|
POSITIVEINT_REGEX = re.compile(r'^\d+')
|
||||||
CODE_REGEX = re.compile(r'^\d+(\.\d)?') # similar
|
CODE_REGEX = re.compile(r'^\d+(\.\d)?') # similar
|
||||||
|
|
||||||
|
|
||||||
WORD_MAP = {
|
WORD_MAP = {
|
||||||
# Descriptions copied from wikipedia:
|
# Descriptions copied from wikipedia:
|
||||||
# https://en.wikipedia.org/wiki/G-code#Letter_addresses
|
# https://en.wikipedia.org/wiki/G-code#Letter_addresses
|
||||||
@ -163,87 +163,6 @@ WORD_MAP = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ORDER_LINUXCNC_LETTER_MAP = {
|
|
||||||
'O': 10,
|
|
||||||
'F': 40,
|
|
||||||
'S': 50,
|
|
||||||
'T': 60,
|
|
||||||
}
|
|
||||||
|
|
||||||
_v_csv = lambda v, ks: [(k, v) for k in ks.split(',')]
|
|
||||||
|
|
||||||
ORDER_LINUXCNC_LETTERVALUE_MAP = dict(itertools.chain.from_iterable([
|
|
||||||
_v_csv(30, 'G93,G94'),
|
|
||||||
_v_csv(70, 'M62,M63,M64,M65,M66,M67,M68'),
|
|
||||||
_v_csv(80, 'M6,M61'),
|
|
||||||
_v_csv(90, 'M3,M4,M5'),
|
|
||||||
_v_csv(100, 'M71,M73,M72,M71'),
|
|
||||||
_v_csv(110, 'M7,M8,M9'),
|
|
||||||
_v_csv(120, 'M48,M49,M50,M51,M52,M53'),
|
|
||||||
[('G4', 140)],
|
|
||||||
_v_csv(150, 'G17,G18,G19'),
|
|
||||||
_v_csv(160, 'G20,G21'),
|
|
||||||
_v_csv(170, 'G40,G41,G42'),
|
|
||||||
_v_csv(180, 'G43,G49'),
|
|
||||||
_v_csv(190, 'G54,G55,G56,G57,G58,G59,G59.1,G59.2,G59.3'),
|
|
||||||
_v_csv(200, 'G61,G61.1,G64'),
|
|
||||||
_v_csv(210, 'G90,G91'),
|
|
||||||
_v_csv(220, 'G98,G99'),
|
|
||||||
_v_csv(230, 'G28,G30,G10,G92,G92.1,G92.2,G94'),
|
|
||||||
_v_csv(240, 'G0,G1,G2,G3,G33,G73,G76,G80,G81,G82,G83,G84,G85,G86,G87,G88,G89'),
|
|
||||||
_v_csv(250, 'M0,M1,M2,M30,M60'),
|
|
||||||
]))
|
|
||||||
|
|
||||||
def _word_order_linuxcnc(word):
|
|
||||||
'''
|
|
||||||
Order taken http://linuxcnc.org/docs/html/gcode/overview.html#_g_code_order_of_execution
|
|
||||||
(as of 2017-07-03)
|
|
||||||
010: O-word commands (optionally followed by a comment but no other words allowed on the same line)
|
|
||||||
N/A: Comment (including message)
|
|
||||||
030: Set feed rate mode (G93, G94).
|
|
||||||
040: Set feed rate (F).
|
|
||||||
050: Set spindle speed (S).
|
|
||||||
060: Select tool (T).
|
|
||||||
070: HAL pin I/O (M62-M68).
|
|
||||||
080: Change tool (M6) and Set Tool Number (M61).
|
|
||||||
090: Spindle on or off (M3, M4, M5).
|
|
||||||
100: Save State (M70, M73), Restore State (M72), Invalidate State (M71).
|
|
||||||
110: Coolant on or off (M7, M8, M9).
|
|
||||||
120: Enable or disable overrides (M48, M49,M50,M51,M52,M53).
|
|
||||||
130: User-defined Commands (M100-M199).
|
|
||||||
140: Dwell (G4).
|
|
||||||
150: Set active plane (G17, G18, G19).
|
|
||||||
160: Set length units (G20, G21).
|
|
||||||
170: Cutter radius compensation on or off (G40, G41, G42)
|
|
||||||
180: Cutter length compensation on or off (G43, G49)
|
|
||||||
190: Coordinate system selection (G54, G55, G56, G57, G58, G59, G59.1, G59.2, G59.3).
|
|
||||||
200: Set path control mode (G61, G61.1, G64)
|
|
||||||
210: Set distance mode (G90, G91).
|
|
||||||
220: Set retract mode (G98, G99).
|
|
||||||
230: Go to reference location (G28, G30) or change coordinate system data (G10) or set axis offsets (G92, G92.1, G92.2, G94).
|
|
||||||
240: Perform motion (G0 to G3, G33, G38.x, G73, G76, G80 to G89), as modified (possibly) by G53.
|
|
||||||
250: Stop (M0, M1, M2, M30, M60).
|
|
||||||
900 + letter val: (else)
|
|
||||||
'''
|
|
||||||
if word.letter in ORDER_LINUXCNC_LETTER_MAP:
|
|
||||||
return ORDER_LINUXCNC_LETTER_MAP[word.letter]
|
|
||||||
letter_value = str(word)
|
|
||||||
if letter_value in ORDER_LINUXCNC_LETTERVALUE_MAP:
|
|
||||||
return ORDER_LINUXCNC_LETTERVALUE_MAP[letter_value]
|
|
||||||
|
|
||||||
# special cases
|
|
||||||
if (word.letter == 'M') and (100 <= int(word.value) <= 199):
|
|
||||||
return 130
|
|
||||||
if (word.letter == 'G') and (38 < float(word.value) < 39):
|
|
||||||
return 240
|
|
||||||
|
|
||||||
# otherwise, sort last, in alphabetic order
|
|
||||||
return (900 + (ord(word.letter) - ord('A')))
|
|
||||||
|
|
||||||
def by_linuxcnc_order(word):
|
|
||||||
return word.orderval_linuxcnc
|
|
||||||
|
|
||||||
|
|
||||||
class Word(object):
|
class Word(object):
|
||||||
def __init__(self, letter, value):
|
def __init__(self, letter, value):
|
||||||
self.letter = letter.upper()
|
self.letter = letter.upper()
|
||||||
@ -302,7 +221,7 @@ class Word(object):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def description(self):
|
def description(self):
|
||||||
return WORD_MAP[self.letter]['description']
|
return "%s: %s" % (self.letter, WORD_MAP[self.letter]['description'])
|
||||||
|
|
||||||
NEXT_WORD = re.compile(r'^.*?(?P<letter>[%s])' % ''.join(WORD_MAP.keys()), re.IGNORECASE)
|
NEXT_WORD = re.compile(r'^.*?(?P<letter>[%s])' % ''.join(WORD_MAP.keys()), re.IGNORECASE)
|
||||||
|
|
||||||
@ -336,3 +255,11 @@ def iter_words(block_text):
|
|||||||
remainder = block_text[index:]
|
remainder = block_text[index:]
|
||||||
if remainder and re.search(r'\S', remainder):
|
if remainder and re.search(r'\S', remainder):
|
||||||
raise GCodeBlockFormatError("block code remaining '%s'" % remainder)
|
raise GCodeBlockFormatError("block code remaining '%s'" % remainder)
|
||||||
|
|
||||||
|
|
||||||
|
def str2word(word_str):
|
||||||
|
words = list(iter_words(word_str))
|
||||||
|
if words:
|
||||||
|
assert len(words) <= 1, "more than one word given"
|
||||||
|
return words[0]
|
||||||
|
return None
|
||||||
|
Loading…
x
Reference in New Issue
Block a user