Black reformat (postprocessing files)

This commit is contained in:
sliptonic
2022-01-04 13:34:22 -06:00
parent 09d1e31b73
commit 0cbafaf270
5 changed files with 1067 additions and 822 deletions

View File

@@ -22,7 +22,7 @@
# ***************************************************************************/
'''
"""
This is an example preprocessor file for the Path workbench. Its aim is to
open a gcode file, parse its contents, and create the appropriate objects
in FreeCAD.
@@ -40,7 +40,7 @@ assumed. The user should carefully examine the resulting gcode!
Read the Path Workbench documentation to know how to create Path objects
from GCode.
'''
"""
import os
import FreeCAD
@@ -61,7 +61,7 @@ if LEVEL == PathLog.Level.DEBUG:
# to distinguish python built-in open function from the one declared below
if open.__module__ in ['__builtin__', 'io']:
if open.__module__ in ["__builtin__", "io"]:
pythonopen = open
@@ -90,10 +90,10 @@ def insert(filename, docname):
gfile.close()
# Regular expression to match tool changes in the format 'M6 Tn'
p = re.compile('[mM]+?\s?0?6\s?T\d*\s')
p = re.compile("[mM]+?\s?0?6\s?T\d*\s")
# split the gcode on tool changes
paths = re.split('([mM]+?\s?0?6\s?T\d*\s)', gcode)
paths = re.split("([mM]+?\s?0?6\s?T\d*\s)", gcode)
# iterate the gcode sections and add customs for each
toolnumber = 0
@@ -103,7 +103,7 @@ def insert(filename, docname):
# if the section is a tool change, extract the tool number
m = p.match(path)
if m:
toolnumber = int(m.group().split('T')[-1])
toolnumber = int(m.group().split("T")[-1])
continue
# Parse the gcode and throw away any empty lists
@@ -113,10 +113,15 @@ def insert(filename, docname):
# Create a custom and viewobject
obj = PathCustom.Create("Custom")
res = PathOpGui.CommandResources('Custom', PathCustom.Create,
PathCustomGui.TaskPanelOpPage,
'Path_Custom',
QtCore.QT_TRANSLATE_NOOP('Path_Custom', 'Custom'), '', '')
res = PathOpGui.CommandResources(
"Custom",
PathCustom.Create,
PathCustomGui.TaskPanelOpPage,
"Path_Custom",
QtCore.QT_TRANSLATE_NOOP("Path_Custom", "Custom"),
"",
"",
)
obj.ViewObject.Proxy = PathOpGui.ViewProvider(obj.ViewObject, res)
obj.ViewObject.Proxy.setDeleteObjectsOnReject(False)
@@ -127,16 +132,24 @@ def insert(filename, docname):
FreeCAD.ActiveDocument.recompute()
def parse(inputstring):
"parse(inputstring): returns a parsed output string"
supported = ['G0', 'G00',
'G1', 'G01',
'G2', 'G02',
'G3', 'G03',
'G81', 'G82', 'G83',
'G90', 'G91']
supported = [
"G0",
"G00",
"G1",
"G01",
"G2",
"G02",
"G3",
"G03",
"G81",
"G82",
"G83",
"G90",
"G91",
]
axis = ["X", "Y", "Z", "A", "B", "C", "U", "V", "W"]

File diff suppressed because it is too large Load Diff

View File

@@ -35,7 +35,7 @@ from FreeCAD import Units
import PathScripts.PathUtil as PathUtil
import PathScripts.PostUtils as PostUtils
Revised = '2020-11-03' # Revision date for this file.
Revised = "2020-11-03" # Revision date for this file.
# *****************************************************************************
# * Due to the fundamentals of the FreeCAD pre-processor, *
@@ -47,155 +47,148 @@ Revised = '2020-11-03' # Revision date for this file.
# *****************************************************************************
TOOLTIP = '''
TOOLTIP = """
Generate g-code from a Path that is compatible with the Marlin controller.
import marlin_post
marlin_post.export(object, "/path/to/file.nc")
'''
"""
# *****************************************************************************
# * Initial configuration, not changeable *
# *****************************************************************************
MOTION_MODE = 'G90' # G90 only, for absolute moves
WORK_PLANE = 'G17' # G17 only, XY plane, for vertical milling
UNITS = 'G21' # G21 only, for metric
UNIT_FORMAT = 'mm'
UNIT_FEED_FORMAT = 'mm/s'
MOTION_MODE = "G90" # G90 only, for absolute moves
WORK_PLANE = "G17" # G17 only, XY plane, for vertical milling
UNITS = "G21" # G21 only, for metric
UNIT_FORMAT = "mm"
UNIT_FEED_FORMAT = "mm/s"
# *****************************************************************************
# * Initial configuration, changeable via command line arguments *
# *****************************************************************************
PRECISION = 3 # Decimal places displayed for metric
DRILL_RETRACT_MODE = 'G98' # End of drill-cycle retractation type. G99
PRECISION = 3 # Decimal places displayed for metric
DRILL_RETRACT_MODE = "G98" # End of drill-cycle retractation type. G99
# is the alternative.
TRANSLATE_DRILL_CYCLES = True # If true, G81, G82, and G83 are translated
TRANSLATE_DRILL_CYCLES = True # If true, G81, G82, and G83 are translated
# into G0/G1 moves
OUTPUT_TOOL_CHANGE = False # Do not output M6 tool change (comment it)
RETURN_TO = None # None = No movement at end of program
SPINDLE_WAIT = 3 # 0 == No waiting after M3 / M4
MODAL = False # True: Commands are suppressed if they are
OUTPUT_TOOL_CHANGE = False # Do not output M6 tool change (comment it)
RETURN_TO = None # None = No movement at end of program
SPINDLE_WAIT = 3 # 0 == No waiting after M3 / M4
MODAL = False # True: Commands are suppressed if they are
# the same as the previous line
LINENR = 100 # Line number starting value
LINEINCR = 10 # Line number increment
PRE_OPERATION = '''''' # Pre operation text will be inserted before
LINENR = 100 # Line number starting value
LINEINCR = 10 # Line number increment
PRE_OPERATION = """""" # Pre operation text will be inserted before
# every operation
POST_OPERATION = '''''' # Post operation text will be inserted after
POST_OPERATION = """""" # Post operation text will be inserted after
# every operation
TOOL_CHANGE = '''''' # Tool Change commands will be inserted
TOOL_CHANGE = """""" # Tool Change commands will be inserted
# before a tool change
# *****************************************************************************
# * Initial gcode output options, changeable via command line arguments *
# *****************************************************************************
OUTPUT_HEADER = True # Output header in output gcode file
OUTPUT_COMMENTS = True # Comments in output gcode file
OUTPUT_FINISH = False # Include an operation finished comment
OUTPUT_PATH = False # Include a Path: comment
OUTPUT_MARLIN_CONFIG = False # Display expected #defines for Marlin config
OUTPUT_LINE_NUMBERS = False # Output line numbers in output gcode file
OUTPUT_BCNC = False # Add bCNC operation block headers in output
OUTPUT_HEADER = True # Output header in output gcode file
OUTPUT_COMMENTS = True # Comments in output gcode file
OUTPUT_FINISH = False # Include an operation finished comment
OUTPUT_PATH = False # Include a Path: comment
OUTPUT_MARLIN_CONFIG = False # Display expected #defines for Marlin config
OUTPUT_LINE_NUMBERS = False # Output line numbers in output gcode file
OUTPUT_BCNC = False # Add bCNC operation block headers in output
# gcode file
SHOW_EDITOR = True # Display the resulting gcode file
SHOW_EDITOR = True # Display the resulting gcode file
# *****************************************************************************
# * Command line arguments *
# *****************************************************************************
parser = argparse.ArgumentParser(prog='marlin', add_help=False)
parser = argparse.ArgumentParser(prog="marlin", add_help=False)
parser.add_argument("--header", action="store_true", help="output headers (default)")
parser.add_argument("--no-header", action="store_true", help="suppress header output")
parser.add_argument("--comments", action="store_true", help="output comment (default)")
parser.add_argument(
'--header',
action='store_true',
help='output headers (default)')
"--no-comments", action="store_true", help="suppress comment output"
)
parser.add_argument(
'--no-header',
action='store_true',
help='suppress header output')
"--finish-comments", action="store_true", help="output finish-comment"
)
parser.add_argument(
'--comments',
action='store_true',
help='output comment (default)')
"--no-finish-comments",
action="store_true",
help="suppress finish-comment output (default)",
)
parser.add_argument("--path-comments", action="store_true", help="output path-comment")
parser.add_argument(
'--no-comments',
action='store_true',
help='suppress comment output')
"--no-path-comments",
action="store_true",
help="suppress path-comment output (default)",
)
parser.add_argument(
'--finish-comments',
action='store_true',
help='output finish-comment')
"--marlin-config", action="store_true", help="output #defines for Marlin"
)
parser.add_argument(
'--no-finish-comments',
action='store_true',
help='suppress finish-comment output (default)')
"--no-marlin-config",
action="store_true",
help="suppress output #defines for Marlin (default)",
)
parser.add_argument(
'--path-comments',
action='store_true',
help='output path-comment')
"--line-numbers", action="store_true", help="prefix with line numbers"
)
parser.add_argument(
'--no-path-comments',
action='store_true',
help='suppress path-comment output (default)')
"--no-line-numbers",
action="store_true",
help="do not prefix with line numbers (default)",
)
parser.add_argument(
'--marlin-config',
action='store_true',
help='output #defines for Marlin')
"--show-editor",
action="store_true",
help="pop up editor before writing output (default)",
)
parser.add_argument(
'--no-marlin-config',
action='store_true',
help='suppress output #defines for Marlin (default)')
"--no-show-editor",
action="store_true",
help="do not pop up editor before writing output",
)
parser.add_argument(
'--line-numbers',
action='store_true',
help='prefix with line numbers')
"--precision", default="3", help="number of digits of precision, default=3"
)
parser.add_argument(
'--no-line-numbers',
action='store_true',
help='do not prefix with line numbers (default)')
"--translate_drill",
action="store_true",
help="translate drill cycles G81, G82, G83 into G0/G1 movements (default)",
)
parser.add_argument(
'--show-editor',
action='store_true',
help='pop up editor before writing output (default)')
"--no-translate_drill",
action="store_true",
help="do not translate drill cycles G81, G82, G83 into G0/G1 movements",
)
parser.add_argument(
'--no-show-editor',
action='store_true',
help='do not pop up editor before writing output')
"--preamble", help='set commands to be issued before the first command, default=""'
)
parser.add_argument(
'--precision',
default='3',
help='number of digits of precision, default=3')
"--postamble", help='set commands to be issued after the last command, default="M5"'
)
parser.add_argument(
'--translate_drill',
action='store_true',
help='translate drill cycles G81, G82, G83 into G0/G1 movements (default)')
"--tool-change", action="store_true", help="Insert M6 for all tool changes"
)
parser.add_argument(
'--no-translate_drill',
action='store_true',
help='do not translate drill cycles G81, G82, G83 into G0/G1 movements')
parser.add_argument(
'--preamble',
help='set commands to be issued before the first command, default=""')
parser.add_argument(
'--postamble',
help='set commands to be issued after the last command, default="M5"')
parser.add_argument(
'--tool-change', action='store_true',
help='Insert M6 for all tool changes')
parser.add_argument(
'--wait-for-spindle',
"--wait-for-spindle",
type=int,
default=3,
help='Wait for spindle to reach desired speed after M3 or M4, default=0')
help="Wait for spindle to reach desired speed after M3 or M4, default=0",
)
parser.add_argument(
'--return-to',
default='',
help='When done, move to, e.g. --return-to="3.175, 4.702, 50.915"')
"--return-to",
default="",
help='When done, move to, e.g. --return-to="3.175, 4.702, 50.915"',
)
parser.add_argument(
'--bcnc',
action='store_true',
help='Add Job operations as bCNC block headers. \
Consider suppressing existing comments: Add argument --no-comments')
"--bcnc",
action="store_true",
help="Add Job operations as bCNC block headers. \
Consider suppressing existing comments: Add argument --no-comments",
)
parser.add_argument(
'--no-bcnc',
action='store_true',
help='suppress bCNC block header output (default)')
"--no-bcnc", action="store_true", help="suppress bCNC block header output (default)"
)
TOOLTIP_ARGS = parser.format_help()
# *****************************************************************************
@@ -209,19 +202,19 @@ TOOLTIP_ARGS = parser.format_help()
# *****************************************************************************
# Default preamble text will appear at the beginning of the gcode output file.
PREAMBLE = ''''''
PREAMBLE = """"""
# Default postamble text will appear following the last operation.
POSTAMBLE = '''M5
'''
POSTAMBLE = """M5
"""
# *****************************************************************************
# * Internal global variables *
# *****************************************************************************
MOTION_COMMANDS = ['G0', 'G00', 'G1', 'G01', 'G2', 'G02', 'G3', 'G03']
RAPID_MOVES = ['G0', 'G00'] # Rapid moves gcode commands definition
SUPPRESS_COMMANDS = [''] # These commands are ignored by commenting them out
COMMAND_SPACE = ' '
MOTION_COMMANDS = ["G0", "G00", "G1", "G01", "G2", "G02", "G3", "G03"]
RAPID_MOVES = ["G0", "G00"] # Rapid moves gcode commands definition
SUPPRESS_COMMANDS = [""] # These commands are ignored by commenting them out
COMMAND_SPACE = " "
# Global variables storing current position (Use None for safety.)
CURRENT_X = None
CURRENT_Y = None
@@ -290,9 +283,9 @@ def processArguments(argstring):
OUTPUT_TOOL_CHANGE = True
if args.return_to:
RETURN_TO = args.return_to
if RETURN_TO.find(',') == -1:
if RETURN_TO.find(",") == -1:
RETURN_TO = None
print('--return-to coordinates must be specified as:')
print("--return-to coordinates must be specified as:")
print('--return-to "x.n,y.n,z.n"')
if args.bcnc:
OUTPUT_BCNC = True
@@ -311,14 +304,14 @@ def processArguments(argstring):
def dump(obj):
for attr in dir(obj):
try:
if attr.startswith('__'):
if attr.startswith("__"):
continue
print('>' + attr + '<')
print(">" + attr + "<")
attr_text = "%s = %s" % (attr, getattr(obj, attr))
if attr in ['HorizFeed', 'VertFeed']:
print('==============\n', attr_text)
if 'mm/s' in attr_text:
print('===> metric values <===')
if attr in ["HorizFeed", "VertFeed"]:
print("==============\n", attr_text)
if "mm/s" in attr_text:
print("===> metric values <===")
except Exception: # Insignificant errors
# print('==>', obj, attr)
pass
@@ -334,128 +327,134 @@ def export(objectslist, filename, argstring):
global MOTION_MODE
global SUPPRESS_COMMANDS
print('Post Processor: ' + __name__ + ' postprocessing...')
gcode = ''
print("Post Processor: " + __name__ + " postprocessing...")
gcode = ""
# Write header:
if OUTPUT_HEADER:
gcode += linenumber() + '(Exported by FreeCAD)\n'
gcode += linenumber() + '(Post Processor: ' + __name__
gcode += '.py, version: ' + Revised + ')\n'
gcode += linenumber() + '(Output Time:' + str(datetime.now()) + ')\n'
gcode += linenumber() + "(Exported by FreeCAD)\n"
gcode += linenumber() + "(Post Processor: " + __name__
gcode += ".py, version: " + Revised + ")\n"
gcode += linenumber() + "(Output Time:" + str(datetime.now()) + ")\n"
# Suppress drill-cycle commands:
if TRANSLATE_DRILL_CYCLES:
SUPPRESS_COMMANDS += ['G80', 'G98', 'G99']
SUPPRESS_COMMANDS += ["G80", "G98", "G99"]
# Write the preamble:
if OUTPUT_COMMENTS:
gcode += linenumber() + '(Begin preamble)\n'
gcode += linenumber() + "(Begin preamble)\n"
for line in PREAMBLE.splitlines(True):
gcode += linenumber() + line
# Write these settings AFTER the preamble,
# to prevent the preamble from changing these:
if OUTPUT_COMMENTS:
gcode += linenumber() + '(Default Configuration)\n'
gcode += linenumber() + MOTION_MODE + '\n'
gcode += linenumber() + UNITS + '\n'
gcode += linenumber() + WORK_PLANE + '\n'
gcode += linenumber() + "(Default Configuration)\n"
gcode += linenumber() + MOTION_MODE + "\n"
gcode += linenumber() + UNITS + "\n"
gcode += linenumber() + WORK_PLANE + "\n"
for obj in objectslist:
# Debug...
# print('\n' + '*'*70 + '\n')
# dump(obj)
# print('\n' + '*'*70 + '\n')
if not hasattr(obj, 'Path'):
print('The object ' + obj.Name +
' is not a path. Please select only path and Compounds.')
if not hasattr(obj, "Path"):
print(
"The object "
+ obj.Name
+ " is not a path. Please select only path and Compounds."
)
return
# Skip inactive operations:
if PathUtil.opProperty(obj, 'Active') is False:
if PathUtil.opProperty(obj, "Active") is False:
continue
# Do the pre_op:
if OUTPUT_BCNC:
gcode += linenumber() + '(Block-name: ' + obj.Label + ')\n'
gcode += linenumber() + '(Block-expand: 0)\n'
gcode += linenumber() + '(Block-enable: 1)\n'
gcode += linenumber() + "(Block-name: " + obj.Label + ")\n"
gcode += linenumber() + "(Block-expand: 0)\n"
gcode += linenumber() + "(Block-enable: 1)\n"
if OUTPUT_COMMENTS:
gcode += linenumber() + '(Begin operation: ' + obj.Label + ')\n'
gcode += linenumber() + "(Begin operation: " + obj.Label + ")\n"
for line in PRE_OPERATION.splitlines(True):
gcode += linenumber() + line
# Get coolant mode:
coolantMode = 'None' # None is the word returned from the operation
if hasattr(obj, 'CoolantMode') or hasattr(obj, 'Base') and \
hasattr(obj.Base, 'CoolantMode'):
if hasattr(obj, 'CoolantMode'):
coolantMode = "None" # None is the word returned from the operation
if (
hasattr(obj, "CoolantMode")
or hasattr(obj, "Base")
and hasattr(obj.Base, "CoolantMode")
):
if hasattr(obj, "CoolantMode"):
coolantMode = obj.CoolantMode
else:
coolantMode = obj.Base.CoolantMode
# Turn coolant on if required:
if OUTPUT_COMMENTS:
if not coolantMode == 'None':
gcode += linenumber() + '(Coolant On:' + coolantMode + ')\n'
if coolantMode == 'Flood':
gcode += linenumber() + 'M8\n'
if coolantMode == 'Mist':
gcode += linenumber() + 'M7\n'
if not coolantMode == "None":
gcode += linenumber() + "(Coolant On:" + coolantMode + ")\n"
if coolantMode == "Flood":
gcode += linenumber() + "M8\n"
if coolantMode == "Mist":
gcode += linenumber() + "M7\n"
# Parse the op:
gcode += parse(obj)
# Do the post_op:
if OUTPUT_COMMENTS and OUTPUT_FINISH:
gcode += linenumber() + '(Finish operation: ' + obj.Label + ')\n'
gcode += linenumber() + "(Finish operation: " + obj.Label + ")\n"
for line in POST_OPERATION.splitlines(True):
gcode += linenumber() + line
# Turn coolant off if previously enabled:
if not coolantMode == 'None':
if not coolantMode == "None":
if OUTPUT_COMMENTS:
gcode += linenumber() + '(Coolant Off:' + coolantMode + ')\n'
gcode += linenumber() + 'M9\n'
gcode += linenumber() + "(Coolant Off:" + coolantMode + ")\n"
gcode += linenumber() + "M9\n"
# Do the post_amble:
if OUTPUT_BCNC:
gcode += linenumber() + '(Block-name: post_amble)\n'
gcode += linenumber() + '(Block-expand: 0)\n'
gcode += linenumber() + '(Block-enable: 1)\n'
gcode += linenumber() + "(Block-name: post_amble)\n"
gcode += linenumber() + "(Block-expand: 0)\n"
gcode += linenumber() + "(Block-enable: 1)\n"
if OUTPUT_COMMENTS:
gcode += linenumber() + '(Begin postamble)\n'
gcode += linenumber() + "(Begin postamble)\n"
for line in POSTAMBLE.splitlines(True):
gcode += linenumber() + line
# Optionally add a final XYZ position to the end of the gcode:
if RETURN_TO:
first_comma = RETURN_TO.find(',')
last_comma = RETURN_TO.rfind(',') # == first_comma if only one comma
ref_X = ' X' + RETURN_TO[0: first_comma].strip()
first_comma = RETURN_TO.find(",")
last_comma = RETURN_TO.rfind(",") # == first_comma if only one comma
ref_X = " X" + RETURN_TO[0:first_comma].strip()
# Z is optional:
if last_comma != first_comma:
ref_Z = ' Z' + RETURN_TO[last_comma + 1:].strip()
ref_Y = ' Y' + RETURN_TO[first_comma + 1:last_comma].strip()
ref_Z = " Z" + RETURN_TO[last_comma + 1 :].strip()
ref_Y = " Y" + RETURN_TO[first_comma + 1 : last_comma].strip()
else:
ref_Z = ''
ref_Y = ' Y' + RETURN_TO[first_comma + 1:].strip()
ref_Z = ""
ref_Y = " Y" + RETURN_TO[first_comma + 1 :].strip()
gcode += linenumber() + 'G0' + ref_X + ref_Y + ref_Z + '\n'
gcode += linenumber() + "G0" + ref_X + ref_Y + ref_Z + "\n"
# Optionally add recommended Marlin 2.x configuration to gcode file:
if OUTPUT_MARLIN_CONFIG:
gcode += linenumber() + '(Marlin 2.x Configuration)\n'
gcode += linenumber() + '(The following should be enabled in)\n'
gcode += linenumber() + '(the configuration files of Marlin 2.x)\n'
gcode += linenumber() + '(#define ARC_SUPPORT)\n'
gcode += linenumber() + '(#define CNC_COORDINATE_SYSTEMS)\n'
gcode += linenumber() + '(#define PAREN_COMMENTS)\n'
gcode += linenumber() + '(#define GCODE_MOTION_MODES)\n'
gcode += linenumber() + '(#define G0_FEEDRATE)\n'
gcode += linenumber() + '(define VARIABLE_G0_FEEDRATE)\n'
gcode += linenumber() + "(Marlin 2.x Configuration)\n"
gcode += linenumber() + "(The following should be enabled in)\n"
gcode += linenumber() + "(the configuration files of Marlin 2.x)\n"
gcode += linenumber() + "(#define ARC_SUPPORT)\n"
gcode += linenumber() + "(#define CNC_COORDINATE_SYSTEMS)\n"
gcode += linenumber() + "(#define PAREN_COMMENTS)\n"
gcode += linenumber() + "(#define GCODE_MOTION_MODES)\n"
gcode += linenumber() + "(#define G0_FEEDRATE)\n"
gcode += linenumber() + "(define VARIABLE_G0_FEEDRATE)\n"
# Show the gcode result dialog:
if FreeCAD.GuiUp and SHOW_EDITOR:
@@ -469,26 +468,26 @@ def export(objectslist, filename, argstring):
else:
final = gcode
print('Done postprocessing.')
print("Done postprocessing.")
# Write the file:
with open(filename, 'w') as fp:
with open(filename, "w") as fp:
fp.write(final)
def linenumber():
if not OUTPUT_LINE_NUMBERS:
return ''
return ""
global LINENR
global LINEINCR
LINENR += LINEINCR
return 'N' + str(LINENR) + ' '
return "N" + str(LINENR) + " "
def format_outlist(strTable):
# construct the line for the final output
global COMMAND_SPACE
s = ''
s = ""
for w in strTable:
s += w + COMMAND_SPACE
return s.strip()
@@ -501,27 +500,46 @@ def parse(pathobj):
global CURRENT_Y
global CURRENT_Z
out = ''
out = ""
lastcommand = None
precision_string = '.' + str(PRECISION) + 'f'
precision_string = "." + str(PRECISION) + "f"
params = ['X', 'Y', 'Z', 'A', 'B', 'C', 'U', 'V', 'W', 'I', 'J', 'K', 'F',
'S', 'T', 'Q', 'R', 'L', 'P']
params = [
"X",
"Y",
"Z",
"A",
"B",
"C",
"U",
"V",
"W",
"I",
"J",
"K",
"F",
"S",
"T",
"Q",
"R",
"L",
"P",
]
if hasattr(pathobj, 'Group'): # We have a compound or project.
if hasattr(pathobj, "Group"): # We have a compound or project.
if OUTPUT_COMMENTS:
out += linenumber() + '(Compound: ' + pathobj.Label + ')\n'
out += linenumber() + "(Compound: " + pathobj.Label + ")\n"
for p in pathobj.Group:
out += parse(p)
return out
else: # Parsing simple path
# groups might contain non-path things like stock.
if not hasattr(pathobj, 'Path'):
if not hasattr(pathobj, "Path"):
return out
if OUTPUT_COMMENTS and OUTPUT_PATH:
out += linenumber() + '(Path: ' + pathobj.Label + ')\n'
out += linenumber() + "(Path: " + pathobj.Label + ")\n"
for c in pathobj.Path.Commands:
outlist = []
@@ -538,96 +556,102 @@ def parse(pathobj):
# Add the remaining parameters in order:
for param in params:
if param in c.Parameters:
if param == 'F':
if param == "F":
if command not in RAPID_MOVES:
feedRate = Units.Quantity(
c.Parameters['F'], FreeCAD.Units.Velocity)
c.Parameters["F"], FreeCAD.Units.Velocity
)
if feedRate.getValueAs(UNIT_FEED_FORMAT) > 0.0:
outlist.append(param + format(float(
feedRate.getValueAs(UNIT_FEED_FORMAT)),
precision_string))
elif param in ['T', 'H', 'D', 'S', 'P', 'L']:
outlist.append(
param
+ format(
float(feedRate.getValueAs(UNIT_FEED_FORMAT)),
precision_string,
)
)
elif param in ["T", "H", "D", "S", "P", "L"]:
outlist.append(param + str(c.Parameters[param]))
elif param in ['A', 'B', 'C']:
outlist.append(param + format(
c.Parameters[param], precision_string))
elif param in ["A", "B", "C"]:
outlist.append(
param + format(c.Parameters[param], precision_string)
)
# [X, Y, Z, U, V, W, I, J, K, R, Q]
else:
pos = Units.Quantity(
c.Parameters[param], FreeCAD.Units.Length)
outlist.append(param + format(float(
pos.getValueAs(UNIT_FORMAT)), precision_string))
pos = Units.Quantity(c.Parameters[param], FreeCAD.Units.Length)
outlist.append(
param
+ format(
float(pos.getValueAs(UNIT_FORMAT)), precision_string
)
)
# Store the latest command:
lastcommand = command
# Capture the current position for subsequent calculations:
if command in MOTION_COMMANDS:
if 'X' in c.Parameters:
CURRENT_X = Units.Quantity(
c.Parameters['X'], FreeCAD.Units.Length)
if 'Y' in c.Parameters:
CURRENT_Y = Units.Quantity(
c.Parameters['Y'], FreeCAD.Units.Length)
if 'Z' in c.Parameters:
CURRENT_Z = Units.Quantity(
c.Parameters['Z'], FreeCAD.Units.Length)
if "X" in c.Parameters:
CURRENT_X = Units.Quantity(c.Parameters["X"], FreeCAD.Units.Length)
if "Y" in c.Parameters:
CURRENT_Y = Units.Quantity(c.Parameters["Y"], FreeCAD.Units.Length)
if "Z" in c.Parameters:
CURRENT_Z = Units.Quantity(c.Parameters["Z"], FreeCAD.Units.Length)
if command in ('G98', 'G99'):
if command in ("G98", "G99"):
DRILL_RETRACT_MODE = command
if TRANSLATE_DRILL_CYCLES:
if command in ('G81', 'G82', 'G83'):
if command in ("G81", "G82", "G83"):
out += drill_translate(outlist, command, c.Parameters)
# Erase the line just translated:
outlist = []
if SPINDLE_WAIT > 0:
if command in ('M3', 'M03', 'M4', 'M04'):
out += linenumber() + format_outlist(outlist) + '\n'
if command in ("M3", "M03", "M4", "M04"):
out += linenumber() + format_outlist(outlist) + "\n"
# Marlin: P for milliseconds, S for seconds, change P to S
out += linenumber()
out += format_outlist(['G4', 'S%s' % SPINDLE_WAIT])
out += '\n'
out += format_outlist(["G4", "S%s" % SPINDLE_WAIT])
out += "\n"
outlist = []
# Check for Tool Change:
if command in ('M6', 'M06'):
if command in ("M6", "M06"):
if OUTPUT_COMMENTS:
out += linenumber() + '(Begin toolchange)\n'
out += linenumber() + "(Begin toolchange)\n"
if OUTPUT_TOOL_CHANGE:
for line in TOOL_CHANGE.splitlines(True):
out += linenumber() + line
if not OUTPUT_TOOL_CHANGE and OUTPUT_COMMENTS:
outlist[0] = '(' + outlist[0]
outlist[-1] = outlist[-1] + ')'
outlist[0] = "(" + outlist[0]
outlist[-1] = outlist[-1] + ")"
if not OUTPUT_TOOL_CHANGE and not OUTPUT_COMMENTS:
outlist = []
if command == 'message':
if command == "message":
if OUTPUT_COMMENTS:
outlist.pop(0) # remove the command
else:
out = []
if command in SUPPRESS_COMMANDS:
outlist[0] = '(' + outlist[0]
outlist[-1] = outlist[-1] + ')'
outlist[0] = "(" + outlist[0]
outlist[-1] = outlist[-1] + ")"
# Remove embedded comments:
if not OUTPUT_COMMENTS:
tmplist = []
list_index = 0
while list_index < len(outlist):
left_index = outlist[list_index].find('(')
left_index = outlist[list_index].find("(")
if left_index == -1: # Not a comment
tmplist.append(outlist[list_index])
else: # This line contains a comment, and possibly more
right_index = outlist[list_index].find(')')
comment_area = outlist[list_index][
left_index: right_index + 1]
line_minus_comment = outlist[list_index].replace(
comment_area, '').strip()
right_index = outlist[list_index].find(")")
comment_area = outlist[list_index][left_index : right_index + 1]
line_minus_comment = (
outlist[list_index].replace(comment_area, "").strip()
)
if line_minus_comment:
# Line contained more than just a comment
tmplist.append(line_minus_comment)
@@ -637,7 +661,7 @@ def parse(pathobj):
# Prepend a line number and append a newline
if len(outlist) >= 1:
out += linenumber() + format_outlist(outlist) + '\n'
out += linenumber() + format_outlist(outlist) + "\n"
return out
@@ -658,61 +682,56 @@ def drill_translate(outlist, cmd, params):
global UNIT_FEED_FORMAT
class Drill: # Using a class is necessary for the nested functions.
gcode = ''
gcode = ""
strFormat = '.' + str(PRECISION) + 'f'
strFormat = "." + str(PRECISION) + "f"
if OUTPUT_COMMENTS: # Comment the original command
outlist[0] = '(' + outlist[0]
outlist[-1] = outlist[-1] + ')'
Drill.gcode += linenumber() + format_outlist(outlist) + '\n'
outlist[0] = "(" + outlist[0]
outlist[-1] = outlist[-1] + ")"
Drill.gcode += linenumber() + format_outlist(outlist) + "\n"
# Cycle conversion only converts the cycles in the XY plane (G17).
# --> ZX (G18) and YZ (G19) planes produce false gcode.
drill_X = Units.Quantity(params['X'], FreeCAD.Units.Length)
drill_Y = Units.Quantity(params['Y'], FreeCAD.Units.Length)
drill_Z = Units.Quantity(params['Z'], FreeCAD.Units.Length)
drill_R = Units.Quantity(params['R'], FreeCAD.Units.Length)
drill_F = Units.Quantity(params['F'], FreeCAD.Units.Velocity)
if cmd == 'G82':
drill_DwellTime = params['P']
elif cmd == 'G83':
drill_Step = Units.Quantity(params['Q'], FreeCAD.Units.Length)
drill_X = Units.Quantity(params["X"], FreeCAD.Units.Length)
drill_Y = Units.Quantity(params["Y"], FreeCAD.Units.Length)
drill_Z = Units.Quantity(params["Z"], FreeCAD.Units.Length)
drill_R = Units.Quantity(params["R"], FreeCAD.Units.Length)
drill_F = Units.Quantity(params["F"], FreeCAD.Units.Velocity)
if cmd == "G82":
drill_DwellTime = params["P"]
elif cmd == "G83":
drill_Step = Units.Quantity(params["Q"], FreeCAD.Units.Length)
# R less than Z is error
if drill_R < drill_Z:
Drill.gcode += linenumber() + '(drill cycle error: R less than Z )\n'
Drill.gcode += linenumber() + "(drill cycle error: R less than Z )\n"
return Drill.gcode
# Z height to retract to when drill cycle is done:
if DRILL_RETRACT_MODE == 'G98' and CURRENT_Z > drill_R:
if DRILL_RETRACT_MODE == "G98" and CURRENT_Z > drill_R:
RETRACT_Z = CURRENT_Z
else:
RETRACT_Z = drill_R
# Z motion nested functions:
def rapid_Z_to(new_Z):
Drill.gcode += linenumber() + 'G0 Z'
Drill.gcode += format(
float(new_Z.getValueAs(UNIT_FORMAT)), strFormat) + '\n'
Drill.gcode += linenumber() + "G0 Z"
Drill.gcode += format(float(new_Z.getValueAs(UNIT_FORMAT)), strFormat) + "\n"
def feed_Z_to(new_Z):
Drill.gcode += linenumber() + 'G1 Z'
Drill.gcode += format(
float(new_Z.getValueAs(UNIT_FORMAT)), strFormat) + ' F'
Drill.gcode += format(
float(drill_F.getValueAs(UNIT_FEED_FORMAT)), '.2f') + '\n'
Drill.gcode += linenumber() + "G1 Z"
Drill.gcode += format(float(new_Z.getValueAs(UNIT_FORMAT)), strFormat) + " F"
Drill.gcode += format(float(drill_F.getValueAs(UNIT_FEED_FORMAT)), ".2f") + "\n"
# Make sure that Z is not below RETRACT_Z:
if CURRENT_Z < RETRACT_Z:
rapid_Z_to(RETRACT_Z)
# Rapid to hole position XY:
Drill.gcode += linenumber() + 'G0 X'
Drill.gcode += format(
float(drill_X.getValueAs(UNIT_FORMAT)), strFormat) + ' Y'
Drill.gcode += format(
float(drill_Y.getValueAs(UNIT_FORMAT)), strFormat) + '\n'
Drill.gcode += linenumber() + "G0 X"
Drill.gcode += format(float(drill_X.getValueAs(UNIT_FORMAT)), strFormat) + " Y"
Drill.gcode += format(float(drill_Y.getValueAs(UNIT_FORMAT)), strFormat) + "\n"
# Rapid to R:
rapid_Z_to(drill_R)
@@ -728,13 +747,13 @@ def drill_translate(outlist, cmd, params):
# * G99 After the hole has been drilled, retract to R height *
# * Select G99 only if safe to move from hole to hole at the R height *
# *************************************************************************
if cmd in ('G81', 'G82'):
if cmd in ("G81", "G82"):
feed_Z_to(drill_Z) # Drill hole in one step
if cmd == 'G82': # Dwell time delay at the bottom of the hole
Drill.gcode += linenumber() + 'G4 S' + str(drill_DwellTime) + '\n'
if cmd == "G82": # Dwell time delay at the bottom of the hole
Drill.gcode += linenumber() + "G4 S" + str(drill_DwellTime) + "\n"
# Marlin uses P for milliseconds, S for seconds, change P to S
elif cmd == 'G83': # Peck drill cycle:
elif cmd == "G83": # Peck drill cycle:
chip_Space = drill_Step * 0.5
next_Stop_Z = drill_R - drill_Step
while next_Stop_Z >= drill_Z: