mirror of
https://git.mirrors.martin98.com/https://github.com/petaflot/pygcode
synced 2025-08-13 20:35:57 +08:00
simplify canned drilling processes
This commit is contained in:
parent
b741603655
commit
9ca819d8c6
@ -475,42 +475,42 @@ class GCodeDrillingCycle(GCodeCannedCycle):
|
|||||||
"""G81: Drilling Cycle"""
|
"""G81: Drilling Cycle"""
|
||||||
param_letters = GCodeCannedCycle.param_letters | set('RLP')
|
param_letters = GCodeCannedCycle.param_letters | set('RLP')
|
||||||
word_key = Word('G', 81)
|
word_key = Word('G', 81)
|
||||||
modal_param_letters = GCodeCannedCycle.param_letters | set('RLP')
|
modal_param_letters = GCodeCannedCycle.param_letters | set('RP')
|
||||||
|
|
||||||
|
|
||||||
class GCodeDrillingCycleDwell(GCodeCannedCycle):
|
class GCodeDrillingCycleDwell(GCodeCannedCycle):
|
||||||
"""G82: Drilling Cycle, Dwell"""
|
"""G82: Drilling Cycle, Dwell"""
|
||||||
param_letters = GCodeCannedCycle.param_letters | set('RLP')
|
param_letters = GCodeCannedCycle.param_letters | set('RLP')
|
||||||
word_key = Word('G', 82)
|
word_key = Word('G', 82)
|
||||||
modal_param_letters = GCodeCannedCycle.param_letters | set('RLP')
|
modal_param_letters = GCodeCannedCycle.param_letters | set('RP')
|
||||||
|
|
||||||
|
|
||||||
class GCodeDrillingCyclePeck(GCodeCannedCycle):
|
class GCodeDrillingCyclePeck(GCodeCannedCycle):
|
||||||
"""G83: Drilling Cycle, Peck"""
|
"""G83: Drilling Cycle, Peck"""
|
||||||
param_letters = GCodeCannedCycle.param_letters | set('RLQ')
|
param_letters = GCodeCannedCycle.param_letters | set('RLQ')
|
||||||
word_key = Word('G', 83)
|
word_key = Word('G', 83)
|
||||||
modal_param_letters = GCodeCannedCycle.param_letters | set('RLQ')
|
modal_param_letters = GCodeCannedCycle.param_letters | set('RQ')
|
||||||
|
|
||||||
|
|
||||||
class GCodeDrillingCycleChipBreaking(GCodeCannedCycle):
|
class GCodeDrillingCycleChipBreaking(GCodeCannedCycle):
|
||||||
"""G73: Drilling Cycle, ChipBreaking"""
|
"""G73: Drilling Cycle, ChipBreaking"""
|
||||||
param_letters = GCodeCannedCycle.param_letters | set('RLQ')
|
param_letters = GCodeCannedCycle.param_letters | set('RLQ')
|
||||||
word_key = Word('G', 73)
|
word_key = Word('G', 73)
|
||||||
modal_param_letters = GCodeCannedCycle.param_letters | set('RLQ')
|
modal_param_letters = GCodeCannedCycle.param_letters | set('RQ')
|
||||||
|
|
||||||
|
|
||||||
class GCodeBoringCycleFeedOut(GCodeCannedCycle):
|
class GCodeBoringCycleFeedOut(GCodeCannedCycle):
|
||||||
"""G85: Boring Cycle, Feed Out"""
|
"""G85: Boring Cycle, Feed Out"""
|
||||||
param_letters = GCodeCannedCycle.param_letters | set('RLP')
|
param_letters = GCodeCannedCycle.param_letters | set('RLP')
|
||||||
word_key = Word('G', 85)
|
word_key = Word('G', 85)
|
||||||
modal_param_letters = GCodeCannedCycle.param_letters | set('RLP')
|
modal_param_letters = GCodeCannedCycle.param_letters | set('RP')
|
||||||
|
|
||||||
|
|
||||||
class GCodeBoringCycleDwellFeedOut(GCodeCannedCycle):
|
class GCodeBoringCycleDwellFeedOut(GCodeCannedCycle):
|
||||||
"""G89: Boring Cycle, Dwell, Feed Out"""
|
"""G89: Boring Cycle, Dwell, Feed Out"""
|
||||||
param_letters = GCodeCannedCycle.param_letters | set('RLP')
|
param_letters = GCodeCannedCycle.param_letters | set('RLP')
|
||||||
word_key = Word('G', 89)
|
word_key = Word('G', 89)
|
||||||
modal_param_letters = GCodeCannedCycle.param_letters | set('RLP')
|
modal_param_letters = GCodeCannedCycle.param_letters | set('RP')
|
||||||
|
|
||||||
|
|
||||||
class GCodeThreadingCycle(GCodeCannedCycle):
|
class GCodeThreadingCycle(GCodeCannedCycle):
|
||||||
@ -895,8 +895,8 @@ class GCodePathBlendingMode(GCodePathControlMode):
|
|||||||
|
|
||||||
# ======================= Return Mode in Canned Cycles =======================
|
# ======================= Return Mode in Canned Cycles =======================
|
||||||
# CODE PARAMETERS DESCRIPTION
|
# CODE PARAMETERS DESCRIPTION
|
||||||
# G98 Canned Cycle Return Level
|
# G98 Canned Cycle Return Level to previous
|
||||||
|
# G99 Canned Cycle Return to the level set by R
|
||||||
|
|
||||||
class GCodeCannedReturnMode(GCode):
|
class GCodeCannedReturnMode(GCode):
|
||||||
modal_group = MODAL_GROUP_MAP['canned_cycles_return']
|
modal_group = MODAL_GROUP_MAP['canned_cycles_return']
|
||||||
@ -1444,3 +1444,73 @@ def split_gcodes(gcode_list, splitter_class, sort_list=True):
|
|||||||
split[2] = gcode_list[split_index+1:]
|
split[2] = gcode_list[split_index+1:]
|
||||||
|
|
||||||
return split
|
return split
|
||||||
|
|
||||||
|
|
||||||
|
def _gcodes_abs2rel(start_pos, dist_mode=None, axes='XYZ'):
|
||||||
|
"""
|
||||||
|
Decorator to convert returned motion gcode coordinates to incremental.
|
||||||
|
Intended to be used internally (mainly because it's a little shonky)
|
||||||
|
Decorated function is only expected to return GCodeRapidMove or GCodeLinearMove
|
||||||
|
instances
|
||||||
|
:param start_pos: starting machine position (Position)
|
||||||
|
:param dist_mode: machine's distance mode (GCodeAbsoluteDistanceMode or GCodeIncrementalDistanceMode)
|
||||||
|
:param axes: axes machine accepts (set)
|
||||||
|
"""
|
||||||
|
# Usage:
|
||||||
|
# m = Machine() # defaults to absolute distance mode
|
||||||
|
# m.process_gcodes(GCodeRapidMove(X=10, Y=20, Z=3))
|
||||||
|
# m.process_gcodes(GCodeIncrementalDistanceMode())
|
||||||
|
#
|
||||||
|
# @_gcodes_abs2rel(start_pos=m.pos, dist_mode=m.mode.distance, axes=m.axes)
|
||||||
|
# def do_stuff():
|
||||||
|
# yield GCodeRapidMove(X=0, Y=30, Z=3)
|
||||||
|
# yield GCodeLinearMove(X=0, Y=30, Z=-5)
|
||||||
|
#
|
||||||
|
# gcode_list = do_stuff()
|
||||||
|
# gocde_list[0] # == GCodeRapidMove(X=-10, Y=10)
|
||||||
|
# gocde_list[1] # == GCodeLinearMove(Z=-8)
|
||||||
|
|
||||||
|
SUPPORTED_MOTIONS = (
|
||||||
|
GCodeRapidMove, GCodeLinearMove,
|
||||||
|
)
|
||||||
|
|
||||||
|
def wrapper(func):
|
||||||
|
|
||||||
|
def inner(*largs, **kwargs):
|
||||||
|
# Create Machine (with minimal information)
|
||||||
|
from .machine import Machine, Mode, Position
|
||||||
|
m = type('AbsoluteCoordMachine', (Machine,), {
|
||||||
|
'MODE_CLASS': type('NullMode', (Mode,), {'default_mode': 'G90'}),
|
||||||
|
'axes': axes,
|
||||||
|
})()
|
||||||
|
m.pos = start_pos
|
||||||
|
|
||||||
|
for gcode in func(*largs, **kwargs):
|
||||||
|
# Verification & passthrough's
|
||||||
|
if not isinstance(gcode, GCode):
|
||||||
|
yield gcode # whatever this thing is
|
||||||
|
else:
|
||||||
|
# Process gcode
|
||||||
|
pos_from = m.pos
|
||||||
|
m.process_gcodes(gcode)
|
||||||
|
pos_to = m.pos
|
||||||
|
|
||||||
|
if gcode.modal_group != MODAL_GROUP_MAP['motion']:
|
||||||
|
yield gcode # only deal with motion gcodes
|
||||||
|
continue
|
||||||
|
elif not isinstance(gcode, SUPPORTED_MOTIONS):
|
||||||
|
raise NotImplementedError("%r to iterative coords is not supported (this is only a very simple function)" % gcode)
|
||||||
|
|
||||||
|
# Convert coordinates to iterative
|
||||||
|
rel_pos = pos_to - pos_from
|
||||||
|
coord_words = [w for w in rel_pos.words if w.value]
|
||||||
|
if coord_words: # else relative coords are all zero; do nothing
|
||||||
|
yield words2gcodes([gcode.word] + coord_words)[0].pop()
|
||||||
|
|
||||||
|
|
||||||
|
# Return apropriate function
|
||||||
|
if (dist_mode is None) or isinstance(dist_mode, GCodeIncrementalDistanceMode):
|
||||||
|
return inner
|
||||||
|
else:
|
||||||
|
return func # bypass decorator entirely; nothing to be done
|
||||||
|
return wrapper
|
||||||
|
@ -1,10 +1,14 @@
|
|||||||
from math import sin, cos, tan, asin, acos, atan2, pi, sqrt, ceil
|
from math import sin, cos, tan, asin, acos, atan2, pi, sqrt, ceil
|
||||||
|
|
||||||
from .gcodes import GCodeLinearMove
|
from .gcodes import GCodeLinearMove, GCodeRapidMove
|
||||||
from .gcodes import GCodeArcMove, GCodeArcMoveCW, GCodeArcMoveCCW
|
from .gcodes import GCodeArcMove, GCodeArcMoveCW, GCodeArcMoveCCW
|
||||||
from .gcodes import GCodePlaneSelect, GCodeSelectXYPlane, GCodeSelectYZPlane, GCodeSelectZXPlane
|
from .gcodes import GCodePlaneSelect, GCodeSelectXYPlane, GCodeSelectYZPlane, GCodeSelectZXPlane
|
||||||
from .gcodes import GCodeAbsoluteDistanceMode, GCodeIncrementalDistanceMode
|
from .gcodes import GCodeAbsoluteDistanceMode, GCodeIncrementalDistanceMode
|
||||||
from .gcodes import GCodeAbsoluteArcDistanceMode, GCodeIncrementalArcDistanceMode
|
from .gcodes import GCodeAbsoluteArcDistanceMode, GCodeIncrementalArcDistanceMode
|
||||||
|
from .gcodes import GCodeCannedCycle
|
||||||
|
from .gcodes import GCodeDrillingCyclePeck, GCodeDrillingCycleDwell, GCodeDrillingCycleChipBreaking
|
||||||
|
from .gcodes import GCodeCannedReturnMode, GCodeCannedCycleReturnLevel, GCodeCannedCycleReturnToR
|
||||||
|
from .gcodes import _gcodes_abs2rel
|
||||||
|
|
||||||
from .machine import Position
|
from .machine import Position
|
||||||
from .exceptions import GCodeParameterError
|
from .exceptions import GCodeParameterError
|
||||||
@ -97,7 +101,7 @@ class ArcLinearizeMethod(object):
|
|||||||
self._outer_radius = self.get_outer_radius()
|
self._outer_radius = self.get_outer_radius()
|
||||||
return self._outer_radius
|
return self._outer_radius
|
||||||
|
|
||||||
# Iter
|
# Vertex Generator
|
||||||
def iter_vertices(self):
|
def iter_vertices(self):
|
||||||
"""Yield absolute (<start vertex>, <end vertex>) for each line for the arc"""
|
"""Yield absolute (<start vertex>, <end vertex>) for each line for the arc"""
|
||||||
start_vertex = self.arc_p_start - self.arc_p_center
|
start_vertex = self.arc_p_start - self.arc_p_center
|
||||||
@ -214,6 +218,17 @@ DEFAULT_LA_ARCDISTMODE = GCodeIncrementalArcDistanceMode
|
|||||||
def linearize_arc(arc_gcode, start_pos, plane=None, method_class=None,
|
def linearize_arc(arc_gcode, start_pos, plane=None, method_class=None,
|
||||||
dist_mode=None, arc_dist_mode=None,
|
dist_mode=None, arc_dist_mode=None,
|
||||||
max_error=0.01, decimal_places=3):
|
max_error=0.01, decimal_places=3):
|
||||||
|
"""
|
||||||
|
Convert a G2,G3 arc into a series of approsimation G1 codes
|
||||||
|
:param arc_gcode: arc gcode to approximate (GCodeArcMove)
|
||||||
|
:param start_pos: current machine position (Position)
|
||||||
|
:param plane: machine's active plane (GCodePlaneSelect)
|
||||||
|
:param method_class: method of linear approximation (ArcLinearizeMethod)
|
||||||
|
:param dist_mode: machine's distance mode (GCodeAbsoluteDistanceMode or GCodeIncrementalDistanceMode)
|
||||||
|
:param arc_dist_mode: machine's arc distance mode (GCodeAbsoluteArcDistanceMode or GCodeIncrementalArcDistanceMode)
|
||||||
|
:param max_error: maximum distance approximation arcs can stray from original arc (float)
|
||||||
|
:param decimal_places: number of decimal places gocde will be rounded to, used to mitigate risks of accumulated eror when in incremental distance mode (int)
|
||||||
|
"""
|
||||||
# set defaults
|
# set defaults
|
||||||
if method_class is None:
|
if method_class is None:
|
||||||
method_class = DEFAULT_LA_method_class
|
method_class = DEFAULT_LA_method_class
|
||||||
@ -362,4 +377,109 @@ def linearize_arc(arc_gcode, start_pos, plane=None, method_class=None,
|
|||||||
cur_pos += l_delta # mitigate errors by also adding them the accumulated cur_pos
|
cur_pos += l_delta # mitigate errors by also adding them the accumulated cur_pos
|
||||||
|
|
||||||
|
|
||||||
# ==================== Arc Precision Adjustment ====================
|
# ==================== Un-Canning ====================
|
||||||
|
|
||||||
|
DEFAULT_SCC_PLANE = GCodeSelectXYPlane
|
||||||
|
DEFAULT_SCC_DISTMODE = GCodeAbsoluteDistanceMode
|
||||||
|
DEFAULT_SCC_RETRACTMODE = GCodeCannedCycleReturnLevel
|
||||||
|
|
||||||
|
def simplify_canned_cycle(canned_gcode, start_pos,
|
||||||
|
plane=None, dist_mode=None, retract_mode=None,
|
||||||
|
axes='XYZ'):
|
||||||
|
"""
|
||||||
|
Simplify canned cycle into it's basic linear components
|
||||||
|
:param canned_gcode: canned gcode to be simplified (GCodeCannedCycle)
|
||||||
|
:param start_pos: current machine position (Position)
|
||||||
|
:param plane: machine's active plane (GCodePlaneSelect)
|
||||||
|
:param dist_mode: machine's distance mode (GCodeAbsoluteDistanceMode or GCodeIncrementalDistanceMode)
|
||||||
|
:param axes: axes machine accepts (set)
|
||||||
|
"""
|
||||||
|
|
||||||
|
# set defaults
|
||||||
|
if plane is None:
|
||||||
|
plane = DEFAULT_SCC_PLANE()
|
||||||
|
if dist_mode is None:
|
||||||
|
dist_mode = DEFAULT_SCC_DISTMODE()
|
||||||
|
if retract_mode is None:
|
||||||
|
retract_mode = DEFAULT_SCC_RETRACTMODE()
|
||||||
|
|
||||||
|
# Parameter Type Assertions
|
||||||
|
assert isinstance(canned_gcode, GCodeCannedCycle), "bad canned_gcode type: %r" % canned_gcode
|
||||||
|
assert isinstance(start_pos, Position), "bad start_pos type: %r" % start_pos
|
||||||
|
assert isinstance(plane, GCodePlaneSelect), "bad plane type: %r" % plane
|
||||||
|
assert isinstance(dist_mode, (GCodeAbsoluteDistanceMode, GCodeIncrementalDistanceMode)), "bad dist_mode type: %r" % dist_mode
|
||||||
|
assert isinstance(retract_mode, GCodeCannedReturnMode), "bad retract_mode type: %r" % retract_mode
|
||||||
|
|
||||||
|
# TODO: implement for planes other than XY
|
||||||
|
if not isinstance(plane, GCodeSelectXYPlane):
|
||||||
|
raise NotImplementedError("simplifying canned cycles for planes other than X/Y has not been implemented")
|
||||||
|
|
||||||
|
@_gcodes_abs2rel(start_pos=start_pos, dist_mode=dist_mode, axes=axes)
|
||||||
|
def inner():
|
||||||
|
cycle_count = 1 if (canned_gcode.L is None) else canned_gcode.L
|
||||||
|
cur_hole_p_axis = start_pos.vector
|
||||||
|
for i in range(cycle_count):
|
||||||
|
# Calculate Depths
|
||||||
|
if isinstance(dist_mode, GCodeAbsoluteDistanceMode):
|
||||||
|
retract_depth = canned_gcode.R
|
||||||
|
drill_depth = canned_gcode.Z
|
||||||
|
cur_hole_p_axis = Vector3(x=canned_gcode.X, y=canned_gcode.Y)
|
||||||
|
else: # incremental
|
||||||
|
retract_depth = start_pos.Z + canned_gcode.R
|
||||||
|
drill_depth = retract_depth + canned_gcode.Z
|
||||||
|
cur_hole_p_axis += Vector3(x=canned_gcode.X, y=canned_gcode.Y)
|
||||||
|
|
||||||
|
if retract_depth < drill_depth:
|
||||||
|
raise NotImplementedError("drilling upward is not supported")
|
||||||
|
|
||||||
|
if isinstance(retract_mode, GCodeCannedCycleReturnToR):
|
||||||
|
final_depth = retract_depth
|
||||||
|
else:
|
||||||
|
final_depth = start_pos.Z
|
||||||
|
|
||||||
|
# Move above hole (height of retract_depth)
|
||||||
|
if retract_depth > start_pos.Z:
|
||||||
|
yield GCodeRapidMove(Z=retract_depth)
|
||||||
|
yield GCodeRapidMove(X=cur_hole_p_axis.x, Y=cur_hole_p_axis.y)
|
||||||
|
if retract_depth < start_pos.Z:
|
||||||
|
yield GCodeRapidMove(Z=retract_depth)
|
||||||
|
|
||||||
|
# Drill hole
|
||||||
|
delta = drill_depth - retract_depth # full depth
|
||||||
|
if isinstance(canned_gcode, (GCodeDrillingCyclePeck, GCodeDrillingCycleChipBreaking)):
|
||||||
|
delta = -abs(canned_gcode.Q)
|
||||||
|
|
||||||
|
cur_depth = retract_depth
|
||||||
|
last_depth = cur_depth
|
||||||
|
while True:
|
||||||
|
# Determine new depth
|
||||||
|
cur_depth += delta
|
||||||
|
if cur_depth < drill_depth:
|
||||||
|
cur_depth = drill_depth
|
||||||
|
|
||||||
|
# Rapid to just above, then slowly drill through delta
|
||||||
|
just_above_base = last_depth + 0.1
|
||||||
|
if just_above_base < retract_depth:
|
||||||
|
yield GCodeRapidMove(Z=just_above_base)
|
||||||
|
yield GCodeLinearMove(Z=cur_depth)
|
||||||
|
if cur_depth <= drill_depth:
|
||||||
|
break # loop stops at the bottom of the hole
|
||||||
|
else:
|
||||||
|
# back up
|
||||||
|
if isinstance(canned_gcode, GCodeDrillingCycleChipBreaking):
|
||||||
|
# retract "a bit"
|
||||||
|
yield GCodeRapidMove(Z=cur_depth + 0.5) # TODO: configurable retraction
|
||||||
|
else:
|
||||||
|
# default behaviour: GCodeDrillingCyclePeck
|
||||||
|
yield GCodeRapidMove(Z=retract_depth)
|
||||||
|
|
||||||
|
last_depth = cur_depth
|
||||||
|
|
||||||
|
# Dwell
|
||||||
|
if isinstance(canned_gcode, GCodeDrillingCycleDwell):
|
||||||
|
yield GCodeDwell(P=0.5) # TODO: configurable pause
|
||||||
|
|
||||||
|
# Return
|
||||||
|
yield GCodeRapidMove(Z=final_depth)
|
||||||
|
|
||||||
|
return inner()
|
||||||
|
@ -66,8 +66,8 @@ def plane_projection(vect, normal):
|
|||||||
n = normal.normalized()
|
n = normal.normalized()
|
||||||
return vect - (n * vect.dot(n))
|
return vect - (n * vect.dot(n))
|
||||||
|
|
||||||
# ==================== GCode Utilities ====================
|
|
||||||
|
|
||||||
|
# ==================== GCode Utilities ====================
|
||||||
def omit_redundant_modes(gcode_iter):
|
def omit_redundant_modes(gcode_iter):
|
||||||
"""
|
"""
|
||||||
Replace redundant machine motion modes with whitespace,
|
Replace redundant machine motion modes with whitespace,
|
||||||
|
@ -20,7 +20,7 @@ for pygcode_lib_type in ('installed_lib', 'relative_lib'):
|
|||||||
from pygcode import GCodeCannedCycle
|
from pygcode import GCodeCannedCycle
|
||||||
from pygcode import split_gcodes
|
from pygcode import split_gcodes
|
||||||
from pygcode import Comment
|
from pygcode import Comment
|
||||||
from pygcode.transform import linearize_arc
|
from pygcode.transform import linearize_arc, simplify_canned_cycle
|
||||||
from pygcode.transform import ArcLinearizeInside, ArcLinearizeOutside, ArcLinearizeMid
|
from pygcode.transform import ArcLinearizeInside, ArcLinearizeOutside, ArcLinearizeMid
|
||||||
from pygcode.gcodes import _subclasses
|
from pygcode.gcodes import _subclasses
|
||||||
from pygcode.utils import omit_redundant_modes
|
from pygcode.utils import omit_redundant_modes
|
||||||
@ -89,13 +89,13 @@ group = parser.add_argument_group(
|
|||||||
"interpolation (G1), and pauses (or 'dwells', G4)"
|
"interpolation (G1), and pauses (or 'dwells', G4)"
|
||||||
)
|
)
|
||||||
group.add_argument(
|
group.add_argument(
|
||||||
'--canned_simplify', '-cs', dest='canned_simplify',
|
'--canned_expand', '-ce', dest='canned_expand',
|
||||||
action='store_const', const=True, default=False,
|
action='store_const', const=True, default=False,
|
||||||
help="Convert canned cycles into basic linear movements",
|
help="Expand canned cycles into basic linear movements, and pauses",
|
||||||
)
|
)
|
||||||
group.add_argument(
|
group.add_argument(
|
||||||
'---canned_codes', '-cc', dest='canned_codes', default=DEFAULT_CANNED_CODES,
|
'---canned_codes', '-cc', dest='canned_codes', default=DEFAULT_CANNED_CODES,
|
||||||
help="List of canned gcodes to simplify, (default is '%s')" % DEFAULT_CANNED_CODES,
|
help="List of canned gcodes to expand, (default is '%s')" % DEFAULT_CANNED_CODES,
|
||||||
)
|
)
|
||||||
|
|
||||||
#parser.add_argument(
|
#parser.add_argument(
|
||||||
@ -194,6 +194,7 @@ for line_str in args.infile[0].readlines():
|
|||||||
|
|
||||||
if args.arc_linearize and any(isinstance(g, GCodeArcMove) for g in effective_gcodes):
|
if args.arc_linearize and any(isinstance(g, GCodeArcMove) for g in effective_gcodes):
|
||||||
with split_and_process(effective_gcodes, GCodeArcMove, line.comment) as arc:
|
with split_and_process(effective_gcodes, GCodeArcMove, line.comment) as arc:
|
||||||
|
print(Comment("linearized arc: %r" % arc))
|
||||||
linearize_params = {
|
linearize_params = {
|
||||||
'arc_gcode': arc,
|
'arc_gcode': arc,
|
||||||
'start_pos': machine.pos,
|
'start_pos': machine.pos,
|
||||||
@ -207,14 +208,18 @@ for line_str in args.infile[0].readlines():
|
|||||||
for linear_gcode in omit_redundant_modes(linearize_arc(**linearize_params)):
|
for linear_gcode in omit_redundant_modes(linearize_arc(**linearize_params)):
|
||||||
print(linear_gcode)
|
print(linear_gcode)
|
||||||
|
|
||||||
elif args.canned_simplify and any((g.word in args.canned_codes) for g in effective_gcodes):
|
elif args.canned_expand and any((g.word in args.canned_codes) for g in effective_gcodes):
|
||||||
(befores, (canned,), afters) = split_gcodes(effective_gcodes, GCodeCannedCycle)
|
with split_and_process(effective_gcodes, GCodeCannedCycle, line.comment) as canned:
|
||||||
print(Comment('canning simplified: %r' % canned))
|
print(Comment("expanded: %r" % canned))
|
||||||
|
simplify_canned_params = {
|
||||||
# TODO: simplify canned things
|
'canned_gcode': canned,
|
||||||
|
'start_pos': machine.pos,
|
||||||
print(str(line))
|
'plane': machine.mode.plane_selection,
|
||||||
machine.process_block(line.block)
|
'dist_mode': machine.mode.distance,
|
||||||
|
'axes': machine.axes,
|
||||||
|
}
|
||||||
|
for simplified_gcode in omit_redundant_modes(simplify_canned_cycle(**simplify_canned_params)):
|
||||||
|
print(simplified_gcode)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print(str(line))
|
print(str(line))
|
||||||
|
@ -11,6 +11,7 @@ add_pygcode_to_path()
|
|||||||
# Units under test
|
# Units under test
|
||||||
from pygcode import gcodes
|
from pygcode import gcodes
|
||||||
from pygcode import words
|
from pygcode import words
|
||||||
|
from pygcode import machine
|
||||||
|
|
||||||
from pygcode.exceptions import GCodeWordStrError
|
from pygcode.exceptions import GCodeWordStrError
|
||||||
|
|
||||||
@ -139,3 +140,54 @@ class GCodeSplitTests(unittest.TestCase):
|
|||||||
self.assertTrue(any(isinstance(g, gcodes.GCodeMotion) for g in split[0]))
|
self.assertTrue(any(isinstance(g, gcodes.GCodeMotion) for g in split[0]))
|
||||||
self.assertTrue(isinstance(split[1][0], gcodes.GCodeStartSpindle))
|
self.assertTrue(isinstance(split[1][0], gcodes.GCodeStartSpindle))
|
||||||
self.assertTrue(any(isinstance(g, gcodes.GCodeSpindleSpeed) for g in split[2]))
|
self.assertTrue(any(isinstance(g, gcodes.GCodeSpindleSpeed) for g in split[2]))
|
||||||
|
|
||||||
|
|
||||||
|
class GCodeAbsoluteToRelativeDecoratorTests(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_gcodes_abs2rel(self):
|
||||||
|
# setup gcode testlist
|
||||||
|
L = gcodes.GCodeLinearMove
|
||||||
|
R = gcodes.GCodeRapidMove
|
||||||
|
args = lambda x, y, z: dict(a for a in zip('XYZ', [x,y,z]) if a[1] is not None)
|
||||||
|
gcode_list = [
|
||||||
|
# GCode instances Expected incremental output
|
||||||
|
(L(**args(0, 0, 0)), L(**args(-10, -20, -30))),
|
||||||
|
(L(**args(1, 2, 0)), L(**args(1, 2, None))),
|
||||||
|
(L(**args(3, 4, 0)), L(**args(2, 2, None))),
|
||||||
|
(R(**args(1, 2, 0)), R(**args(-2, -2, None))),
|
||||||
|
(R(**args(3, 4, 0)), R(**args(2, 2, None))),
|
||||||
|
(L(**args(3, 4, 0)), None),
|
||||||
|
(L(**args(3, 4, 8)), L(**args(None, None, 8))),
|
||||||
|
]
|
||||||
|
|
||||||
|
m = machine.Machine()
|
||||||
|
|
||||||
|
# Incremental Output
|
||||||
|
m.set_mode(gcodes.GCodeAbsoluteDistanceMode())
|
||||||
|
m.move_to(X=10, Y=20, Z=30) # initial position (absolute)
|
||||||
|
m.set_mode(gcodes.GCodeIncrementalDistanceMode())
|
||||||
|
|
||||||
|
@gcodes._gcodes_abs2rel(m.pos, dist_mode=m.mode.distance, axes=m.axes)
|
||||||
|
def expecting_rel():
|
||||||
|
return [g[0] for g in gcode_list]
|
||||||
|
|
||||||
|
trimmed_expecting_list = [x[1] for x in gcode_list if x[1] is not None]
|
||||||
|
for (i, g) in enumerate(expecting_rel()):
|
||||||
|
expected = trimmed_expecting_list[i]
|
||||||
|
self.assertEqual(type(g), type(expected))
|
||||||
|
self.assertEqual(g.word, expected.word)
|
||||||
|
self.assertEqual(g.params, expected.params)
|
||||||
|
|
||||||
|
# Absolute Output
|
||||||
|
m.set_mode(gcodes.GCodeAbsoluteDistanceMode())
|
||||||
|
m.move_to(X=10, Y=20, Z=30) # initial position
|
||||||
|
|
||||||
|
@gcodes._gcodes_abs2rel(m.pos, dist_mode=m.mode.distance, axes=m.axes)
|
||||||
|
def expecting_abs():
|
||||||
|
return [g[0] for g in gcode_list]
|
||||||
|
|
||||||
|
for (i, g) in enumerate(expecting_abs()):
|
||||||
|
expected = gcode_list[i][0] # expecting passthrough
|
||||||
|
self.assertEqual(type(g), type(expected))
|
||||||
|
self.assertEqual(g.word, expected.word)
|
||||||
|
self.assertEqual(g.params, expected.params)
|
||||||
|
@ -1,7 +1,3 @@
|
|||||||
import sys
|
|
||||||
import os
|
|
||||||
import inspect
|
|
||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
# Add relative pygcode to path
|
# Add relative pygcode to path
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
# utilities for the testing suite (as opposed to the tests for utils.py)
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import inspect
|
import inspect
|
||||||
|
Loading…
x
Reference in New Issue
Block a user