def parse(inputstring): "parse(inputstring): returns a parsed output string" print "postprocessing..." output = "" params = ['X', 'Y', 'Z', 'A', 'B', 'I', 'J', 'K', 'F', 'S', 'T'] #This list control the order of parameters # write some stuff first if OUTPUT_HEADER: print "outputting header" output += "'Exported by FreeCAD\n" output += "'Post Processor: " + __name__ + "\n" output += "'Output Time:" + str(now) + "\n" #Write the preamble if OUTPUT_COMMENTS: output += "'begin preamble\n" for line in PREAMBLE.splitlines(True): output += line # treat the input line by line lines = inputstring.splitlines(True) for line in lines: commandline = PostUtils.stringsplit(line) command = commandline['command'] try: print commandline print "command: " + command print command in scommands output += scommands[command](commandline) except: print "I don't know what the hell the command: " + command + " means. Maybe I should support it." print "finished" # write some more stuff at the end if OUTPUT_COMMENTS: output += "'begin postamble\n" for line in POSTAMBLE.splitlines(True): output += line if SHOW_EDITOR: dia = PostUtils.GCodeEditorDialog() dia.editor.setText(output) result = dia.exec_() if result: final = dia.editor.toPlainText() else: final = output else: final = output print "done postprocessing." return final
def export(obj, filename, argstring): modal = True gcode = "" safetyblock1 = "G90G40G49\n" gcode += safetyblock1 units = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Units") if units.GetInt("UserSchema") == 0: firstcommand = Path.Command("G21") # metric mode else: firstcommand = Path.Command("G20") # inch mode oldvals = saveVals(firstcommand) # save first command for modal use fp = obj[0] gcode += firstcommand.Name if hasattr(fp, "Path"): for c in fp.Path.Commands: gcode += lineout(c, oldvals, modal) + "\n" oldvals = saveVals(c) gcode += "M2\n" gfile = open(filename, "w") gfile.write(gcode) gfile.close() else: FreeCAD.Console.PrintError("Select a path object and try again\n") if SHOW_EDITOR: FreeCAD.Console.PrintMessage("Editor Activated\n") dia = PostUtils.GCodeEditorDialog() dia.editor.setText(gcode) dia.exec_()
def export(obj, filename): modal = True commands = obj[0] gcode = '' safetyblock1 = 'G90G40G49\n' gcode += safetyblock1 units = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Units") if units.GetInt('UserSchema') == 0: firstcommand = Path.Command('G21') #metric mode else: firstcommand = Path.Command('G20') #inch mode oldvals = saveVals(firstcommand) #save first command for modal use fp = obj[0] gcode += firstcommand.Name if hasattr(fp, "Path"): for c in fp.Path.Commands: gcode += lineout(c, oldvals, modal) + '\n' oldvals = saveVals(c) gcode += 'M2\n' gfile = open(filename, "wb") gfile.write(gcode) gfile.close() else: FreeCAD.Console.PrintError('Select a path object and try again\n') if obj[0].Editor: FreeCAD.Console.PrintMessage('Editor Activated\n') dia = PostUtils.GCodeEditorDialog() dia.editor.setText(gcode) dia.exec_()
def export(objectslist, filename, argstring): "called when freecad exports a list of objects" # pylint: disable=unused-argument output = '''(This output produced with the dump post processor) (Dump is useful for inspecting the raw commands in your paths) (but is not useful for driving machines.) (Consider setting a default postprocessor in your project or ) (exporting your paths using a specific post that matches your machine) ''' for obj in objectslist: if not hasattr(obj, "Path"): print("the object " + obj.Name + " is not a path. Please select only path and Compounds.") return print("postprocessing...") output += parse(obj) if SHOW_EDITOR: dia = PostUtils.GCodeEditorDialog() dia.editor.setText(output) result = dia.exec_() if result: final = dia.editor.toPlainText() else: final = output else: final = output print("done postprocessing.") return final
def test010(self): """Test the utility functions in the PostUtils.py file.""" commands = [ Path.Command("G1 X-7.5 Y5.0 Z0.0"), Path.Command("G2 I2.5 J0.0 K0.0 X-5.0 Y7.5 Z0.0"), Path.Command("G1 X5.0 Y7.5 Z0.0"), Path.Command("G2 I0.0 J-2.5 K0.0 X7.5 Y5.0 Z0.0"), Path.Command("G1 X7.5 Y-5.0 Z0.0"), Path.Command("G2 I-2.5 J0.0 K0.0 X5.0 Y-7.5 Z0.0"), Path.Command("G1 X-5.0 Y-7.5 Z0.0"), Path.Command("G2 I0.0 J2.5 K0.0 X-7.5 Y-5.0 Z0.0"), Path.Command("G1 X-7.5 Y0.0 Z0.0"), ] testpath = Path.Path(commands) self.assertTrue(len(testpath.Commands) == 9) self.assertTrue( len([c for c in testpath.Commands if c.Name in ["G2", "G3"]]) == 4 ) results = PostUtils.splitArcs(testpath) # self.assertTrue(len(results.Commands) == 117) self.assertTrue( len([c for c in results.Commands if c.Name in ["G2", "G3"]]) == 0 )
def export(objectslist, filename, argstring): """Export the list of objects into a filename. Parameters ---------- objectslists: list List of objects. filename: str Name of the output file ending in `'.knc'`. """ gcode = HEADER for obj in objectslist: for command in obj.Path.Commands: # Manipulate tool change commands if "M6" == command.Name: gcode += TOOL_CHANGE.replace("TOOL", str(int(command.Parameters["T"]))) elif "M3" == command.Name: # Convert spindle speed (rpm) command to comment gcode += ("M01 Set spindle speed to " + str(int(command.Parameters["S"])) + " rounds per minute") else: # Add other commands gcode += command.Name # Loop through command parameters for parameter, value in command.Parameters.items(): # Multiply F parameter value by 10, # FreeCAD = mm/s, nccad = 1/10 mm/s if "F" == parameter: value *= 10 # Add command parameters and values and round float # as nccad9 does not support exponents gcode += " " + parameter + str(round(value, 5)) gcode += "\n" gcode += POSTAMBLE + "\n" # Open editor window if FreeCAD.GuiUp: dia = PostUtils.GCodeEditorDialog() dia.editor.setText(gcode) result = dia.exec_() if result: gcode = dia.editor.toPlainText() # Save to file if filename != "-": gfile = open(filename, "w") gfile.write(gcode) gfile.close() return filename
def parse(inputstring): "parse(inputstring): returns a parsed output string" print "postprocessing..." output = "" params = ['X','Y','Z','A','B','I','J','K','F','S','T'] #This list control the order of parameters # write some stuff first if OUTPUT_HEADER: print "outputting header" output += "'Exported by FreeCAD\n" output += "'Post Processor: " + __name__ +"\n" output += "'Output Time:"+str(now)+"\n" #Write the preamble if OUTPUT_COMMENTS: output += "'begin preamble\n" for line in PREAMBLE.splitlines(True): output += line # treat the input line by line lines = inputstring.splitlines(True) for line in lines: commandline = PostUtils.stringsplit(line) command = commandline['command'] try: print commandline print "command: " + command print command in scommands output += scommands[command](commandline) except: print "I don't know what the hell the command: " + command + " means. Maybe I should support it." print "finished" # write some more stuff at the end if OUTPUT_COMMENTS: output += "'begin postamble\n" for line in POSTAMBLE.splitlines(True): output += line if SHOW_EDITOR: dia = PostUtils.GCodeEditorDialog() dia.editor.setText(output) result = dia.exec_() if result: final = dia.editor.toPlainText() else: final = output else: final = output print "done postprocessing." return final
def export(objectslist, filename, argstring): gcode = HEADER for obj in objectslist: for command in obj.Path.Commands: # Manipulate tool change commands if 'M6' == command.Name: gcode += TOOL_CHANGE.replace('TOOL', str(int(command.Parameters['T']))) # Convert spindle speed (rpm) command to comment elif 'M3' == command.Name: gcode += 'M01 Set spindle speed to ' + str( int(command.Parameters['S'])) + ' rounds per minute' # Add other commands else: gcode += command.Name # Loop through command parameters for parameter, value in command.Parameters.items(): # Multiply F parameter value by 10 (FreeCAD = mm/s, nccad = 1/10 mm/s) if 'F' == parameter: value *= 10 # Add command parameters and values and round float as nccad9 does not support exponents gcode += ' ' + parameter + str(round(value, 5)) gcode += '\n' gcode += POSTAMBLE + '\n' # Open editor window if FreeCAD.GuiUp: dia = PostUtils.GCodeEditorDialog() dia.editor.setText(gcode) result = dia.exec_() if result: gcode = dia.editor.toPlainText() # Save to file if filename != '-': gfile = open(filename, "w") gfile.write(gcode) gfile.close() return filename
def parse(inputstring): "parse(inputstring): returns a parsed output string" state = {'X': 0.0, 'Y': 0.0, 'Z': 0.0, 'XYspeed': -1.0, 'Zspeed': -1.0} output = [] # header output += addheader() output += motoron() output += speed(2.0, 1.0, state) # defaults # TODO: respect clearance height # treat the input line by line lines = inputstring.split("\n") for line in lines: if not line: continue parsed = PostUtils.stringsplit(line) command = parsed['command'] print('cmd', line) try: if command: code = convertgcode(command, parsed, state) if not isinstance(code, list): code = [code] if len(code) and code[0]: output += code except NotImplementedError as e: print(e) # footer output += motoroff() output += home() output += addfooter() return '\n'.join(output)
def parse(inputstring): "parse(inputstring): returns a parsed output string" state = { 'X': 0.0, 'Y': 0.0, 'Z': 0.0, 'XYspeed': -1.0, 'Zspeed': -1.0 } output = [] # header output += addheader() output += motoron() output += speed(2.0, 1.0, state) # defaults # TODO: respect clearance height # treat the input line by line lines = inputstring.split("\n") for line in lines: if not line: continue parsed = PostUtils.stringsplit(line) command = parsed['command'] print('cmd', line) try: if command: code = convertgcode(command, parsed, state) if not isinstance(code, list): code = [ code ] if len(code) and code[0]: output += code except NotImplementedError as e: print(e) # footer output += motoroff() output += home() output += addfooter() return '\n'.join(output)
def testSplitArcs(self): commands = [ Path.Command("G1 X-7.5 Y5.0 Z0.0"), Path.Command("G2 I2.5 J0.0 K0.0 X-5.0 Y7.5 Z0.0"), Path.Command("G1 X5.0 Y7.5 Z0.0"), Path.Command("G2 I0.0 J-2.5 K0.0 X7.5 Y5.0 Z0.0"), Path.Command("G1 X7.5 Y-5.0 Z0.0"), Path.Command("G2 I-2.5 J0.0 K0.0 X5.0 Y-7.5 Z0.0"), Path.Command("G1 X-5.0 Y-7.5 Z0.0"), Path.Command("G2 I0.0 J2.5 K0.0 X-7.5 Y-5.0 Z0.0"), Path.Command("G1 X-7.5 Y0.0 Z0.0"), ] testpath = Path.Path(commands) self.assertTrue(len(testpath.Commands) == 9) self.assertTrue( len([c for c in testpath.Commands if c.Name in ['G2', 'G3']]) == 4) results = PostUtils.splitArcs(testpath) # self.assertTrue(len(results.Commands) == 117) self.assertTrue( len([c for c in results.Commands if c.Name in ['G2', 'G3']]) == 0)
def export(objectslist, filename, argstring): # pylint: disable=global-statement if not processArguments(argstring): return None global UNITS global UNIT_FORMAT global UNIT_SPEED_FORMAT for obj in objectslist: if not hasattr(obj, "Path"): print("the object " + obj.Name + " is not a path. Please select only path and Compounds.") return None print("postprocessing...") gcode = "" # write header if OUTPUT_HEADER: gcode += linenumber() + "(Exported by FreeCAD)\n" gcode += linenumber() + "(Post Processor: " + __name__ + ")\n" gcode += linenumber() + "(Output Time:" + str(now) + ")\n" # Write the preamble if OUTPUT_COMMENTS: gcode += linenumber() + "(begin preamble)\n" for line in PREAMBLE.splitlines(False): gcode += linenumber() + line + "\n" gcode += linenumber() + UNITS + "\n" for obj in objectslist: # Skip inactive operations if hasattr(obj, 'Active'): if not obj.Active: continue if hasattr(obj, 'Base') and hasattr(obj.Base, 'Active'): if not obj.Base.Active: continue # fetch machine details job = PathUtils.findParentJob(obj) myMachine = 'not set' if hasattr(job, "MachineName"): myMachine = job.MachineName if hasattr(job, "MachineUnits"): if job.MachineUnits == "Metric": UNITS = "G21" UNIT_FORMAT = 'mm' UNIT_SPEED_FORMAT = 'mm/min' else: UNITS = "G20" UNIT_FORMAT = 'in' UNIT_SPEED_FORMAT = 'in/min' # do the pre_op if OUTPUT_COMMENTS: gcode += linenumber() + "(begin operation: %s)\n" % obj.Label gcode += linenumber() + "(machine: %s, %s)\n" % (myMachine, UNIT_SPEED_FORMAT) for line in PRE_OPERATION.splitlines(True): gcode += linenumber() + line # get coolant mode coolantMode = 'None' 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' # process the operation gcode gcode += parse(obj) # do the post_op if OUTPUT_COMMENTS: gcode += linenumber() + "(finish operation: %s)\n" % obj.Label for line in POST_OPERATION.splitlines(True): gcode += linenumber() + line # turn coolant off if required if not coolantMode == 'None': if OUTPUT_COMMENTS: gcode += linenumber() + '(Coolant Off:' + coolantMode + ')\n' gcode += linenumber() +'M9' + '\n' # do the post_amble if OUTPUT_COMMENTS: gcode += "(begin postamble)\n" for line in POSTAMBLE.splitlines(True): gcode += linenumber() + line if FreeCAD.GuiUp and SHOW_EDITOR: dia = PostUtils.GCodeEditorDialog() dia.editor.setText(gcode) result = dia.exec_() if result: final = dia.editor.toPlainText() else: final = gcode else: final = gcode print("done postprocessing.") if not filename == '-': gfile = pythonopen(filename, "w") gfile.write(final) gfile.close() return final
def export(selection, filename, argstring): global linenr linenr = STARTLINENR lastX = 0 lastY = 0 lastZ = 0 params = [ 'X', 'Y', 'Z', 'A', 'B', 'I', 'J', 'F', 'H', 'S', 'T', 'Q', 'R', 'L' ] #Using XY plane most of the time so skipping K modalParamsDict = dict() for mp in MODALPARAMS: modalParamsDict[mp] = None for obj in selection: if not hasattr(obj, "Path"): print "the object " + obj.Name + " is not a path. Please select only path and Compounds." return myMachine = None for pathobj in selection: if hasattr(pathobj, "MachineName"): myMachine = pathobj.MachineName if hasattr(pathobj, "MachineUnits"): if pathobj.MachineUnits == "Metric": UNITS = "G21" else: UNITS = "G20" if myMachine is None: print "No machine found in this selection" gcode = '' gcode += mkHeader(selection) gcode += linenumberify(GCODE_HEADER) if UNITS_INCLUDED: gcode += linenumberify(mapGCode(UNITS)) lastcommand = None gobjects = [] for g in selection[0].Group: if g.Name <> 'Machine': #filtering out gcode home position from Machine object gobjects.append(g) for obj in gobjects: if hasattr(obj, 'Comment'): gcode += linenumberify('(' + obj.Comment + ')') for c in obj.Path.Commands: outstring = [] command = c.Name if (command != UNITS or UNITS_INCLUDED): if command[0] == '(': command = PostUtils.fcoms(command, COMMENT) mappedCommand = mapGCode( command ) # the mapping is done for output only! For internal things we still use the old value. if not MODAL or command != lastcommand: outstring.append(mappedCommand) # if MODAL == True: ) # #\better: append iff MODAL == False ) # if command == lastcommand: ) # outstring.pop(0!#\ ) if c.Parameters >= 1: for param in params: if param in c.Parameters: if (param in MODALPARAMS) and ( modalParamsDict[str(param)] == c.Parameters[str(param)]): # do nothing or append white space outstring.append(' ') elif param == 'F': outstring.append(param + PostUtils.fmt( c.Parameters['F'], FEED_DECIMALS, UNITS)) elif param == 'H': outstring.append(param + str(int(c.Parameters['H']))) elif param == 'S': outstring.append( param + PostUtils.fmt(c.Parameters['S'], SPINDLE_DECIMALS, 'G21') ) #rpm is unitless-therefore I had to 'fake it out' by using metric units which don't get converted from entered value elif param == 'T': outstring.append(param + str(int(c.Parameters['T']))) elif param == 'I' and (command == 'G2' or command == 'G3'): # this is the special case for circular paths, where relative coordinates have to be changed to absolute i = c.Parameters['I'] # calculate the radius r j = c.Parameters['J'] r = math.sqrt(i**2 + j**2) if USE_RADIUS_IF_POSSIBLE and angleUnder180( command, lastX, lastY, c.Parameters['X'], c.Parameters['Y'], i, j): outstring.append( 'R' + PostUtils.fmt(r, AXIS_DECIMALS, UNITS)) else: if RADIUS_COMMENT: outstring.append('(R' + PostUtils.fmt( r, AXIS_DECIMALS, UNITS) + ')') if ABSOLUTE_CIRCLE_CENTER: i += lastX outstring.append( param + PostUtils.fmt(i, AXIS_DECIMALS, UNITS)) elif param == 'J' and (command == 'G2' or command == 'G3'): # this is the special case for circular paths, where incremental center has to be changed to absolute center i = c.Parameters['I'] j = c.Parameters['J'] if USE_RADIUS_IF_POSSIBLE and angleUnder180( command, lastX, lastY, c.Parameters['X'], c.Parameters['Y'], i, j): # R is handled with the I parameter, here: do nothing at all, keep the structure as with I command pass else: if ABSOLUTE_CIRCLE_CENTER: j += lastY if SWAP_Y_Z: # we have to swap j and k as well outstring.append('K' + PostUtils.fmt( j, AXIS_DECIMALS, UNITS)) else: outstring.append(param + PostUtils.fmt( j, AXIS_DECIMALS, UNITS)) elif param == 'K' and (command == 'G2' or command == 'G3'): # this is the special case for circular paths, where incremental center has to be changed to absolute center outstring.append( '(' + param + PostUtils.fmt(c.Parameters[param], AXIS_DECIMALS, UNITS) + ')') z = c.Parameters['Z'] k = c.Parameters['K'] if USE_RADIUS_IF_POSSIBLE and angleUnder180( command, lastX, lastY, c.Parameters['X'], c.Parameters['Y'], i, j): # R is handled with the I parameter, here: do nothing at all, keep the structure as with I command pass else: if ABSOLUTE_CIRCLE_CENTER: k += lastZ if SWAP_Y_Z: # we have to swap j and k as well outstring.append( 'J' + PostUtils.fmt(j, AXIS_DECIMALS, UNITS)) else: outstring.append( param + PostUtils.fmt(j, AXIS_DECIMALS, UNITS)) elif param == 'Y' and SWAP_Y_Z: outstring.append('Z' + PostUtils.fmt( c.Parameters[param], AXIS_DECIMALS, UNITS)) elif param == 'Z' and SWAP_Y_Z: outstring.append('Y' + PostUtils.fmt( c.Parameters[param], AXIS_DECIMALS, UNITS)) else: outstring.append(param + PostUtils.fmt( c.Parameters[param], AXIS_DECIMALS, UNITS)) if param in MODALPARAMS: modalParamsDict[str( param)] = c.Parameters[param] # save the last X, Y, Z values if 'X' in c.Parameters: lastX = c.Parameters['X'] if 'Y' in c.Parameters: lastY = c.Parameters['Y'] if 'Z' in c.Parameters: lastZ = c.Parameters['Z'] outstr = str(outstring) outstr = outstr.replace(']', '') outstr = outstr.replace('[', '') outstr = outstr.replace("'", '') outstr = outstr.replace(",", '') if LINENUMBERS: gcode += "N" + str(linenr) + " " linenr += LINENUMBER_INCREMENT gcode += outstr + '\n' lastcommand = c.Name gcode += linenumberify(GCODE_FOOTER) if SHOW_EDITOR: PostUtils.editor(gcode) gfile = pythonopen(filename, "wb") gfile.write(gcode) gfile.close()
def export(objectslist, filename, argstring): if not processArguments(argstring): print("export: process arguments failed, '{}'".format(argstring)) return None global warnings_count global problems_count warnings_count = 0 problems_count = 0 for obj in objectslist: if not hasattr(obj, "Path"): print("the object " + obj.Name + " is not a path. Please select only path and Compounds.") return None print("export: postprocessing...") gcode = append0("%" + PROG_NAME + "\n") if not argstring: gcode += append("(" + __name__ + " with default settings)\n") else: gcode += append("({} {})\n".format(__name__, argstring)) # write header if OUTPUT_HEADER: for line in HEADER.format( GCODE_PROCESSOR, __name__, VERSION, FreeCAD.ActiveDocument.FileName, str(now), ).splitlines(False): if line: gcode += append(line + "\n") # Write the preamble # G20/G21 not supported by UC-CNC, *always* report the configured units. gcode += append("(Units: '" + UNIT_FORMAT + "' and '" + UNIT_SPEED_FORMAT + "')\n") if UNIT_DEFAULT_CHANGED: gcode += append( "(WARNING: Units default changed, check your UC-CNC profile)\n") warnings_count += 1 if OUTPUT_COMMENTS: gcode += append("(preamble: begin)\n") # for obj in objectslist: # if isinstance(obj.Proxy, PathScripts.PathToolController.ToolController): # gcode += append("(T{}={})\n".format(obj.ToolNumber, item.Name)) # error: global name 'PathScripts' is not defined for line in PREAMBLE.splitlines(False): gcode += append(line + "\n") if OUTPUT_COMMENTS: gcode += append("(preamble: done)\n") # write the code body for obj in objectslist: # pre_op if OUTPUT_COMMENTS: gcode += append("(operation initialise: %s)\n" % obj.Label) for line in PRE_OPERATION.splitlines(True): gcode += append(line) # turn coolant on if required if hasattr(obj, "CoolantMode"): coolantMode = obj.CoolantMode if coolantMode == "Mist": if OUTPUT_COMMENTS: gcode += append("M7 (coolant: mist on)\n") else: gcode += append("M7\n") if coolantMode == "Flood": if OUTPUT_COMMENTS: gcode += append("M8 (coolant: flood on)\n") else: gcode += append("M8\n") # process the operation gcode if OUTPUT_COMMENTS: gcode += append("(operation start: %s)\n" % obj.Label) gcode += parse(obj) if OUTPUT_COMMENTS: gcode += append("(operation done: %s)\n" % obj.Label) # post_op for line in POST_OPERATION.splitlines(True): gcode += append(line) # turn coolant off if required if hasattr(obj, "CoolantMode"): coolantMode = obj.CoolantMode if not coolantMode == "None": if OUTPUT_COMMENTS: gcode += append("M9 (coolant: off)\n") else: gcode += append("M9\n") if OUTPUT_COMMENTS: gcode += append("(operation finalised: %s)\n" % obj.Label) # do the post_amble if OUTPUT_COMMENTS: gcode += append("(postamble: begin)\n") for line in POSTAMBLE.splitlines(True): gcode += append(line) if OUTPUT_COMMENTS: gcode += append("(postamble: done)\n") # Show the results if SHOW_EDITOR: dia = PostUtils.GCodeEditorDialog() dia.editor.setText(gcode) result = dia.exec_() if result: final = dia.editor.toPlainText() else: final = gcode else: final = gcode if (0 < problems_count) or (0 < warnings_count): print( "export: postprocessing: done, warnings: {}, problems: {}, see GCode for details." .format(warnings_count, problems_count)) else: print("export: postprocessing: done (none of the problems detected).") if not filename == "-": print("export: writing to '{}'".format(filename)) gfile = pythonopen(filename, "w") gfile.write(final) gfile.close() return final
def export(selection, filename, argstring): params = [ 'X', 'Y', 'Z', 'A', 'B', 'I', 'J', 'F', 'H', 'S', 'T', 'Q', 'R', 'L' ] #Using XY plane most of the time so skipping K for obj in selection: if not hasattr(obj, "Path"): print("the object " + obj.Name + " is not a path. Please select only path and Compounds.") return myMachine = None for pathobj in selection: if hasattr(pathobj, "MachineName"): myMachine = pathobj.MachineName if hasattr(pathobj, "MachineUnits"): if pathobj.MachineUnits == "Metric": UNITS = "G21" else: UNITS = "G20" if myMachine is None: print("No machine found in this selection") gcode = '' gcode += HEADER % (FreeCAD.ActiveDocument.FileName) gcode += SAFETYBLOCK gcode += UNITS + '\n' lastcommand = None gcode += COMMENT + selection[0].Description + '\n' gobjects = [] for g in selection[0].Group: gobjects.append(g) for obj in gobjects: for c in obj.Path.Commands: outstring = [] command = c.Name if command[0] == '(': command = PostUtils.fcoms(command, COMMENT) outstring.append(command) if MODAL == True: if command == lastcommand: outstring.pop(0) if c.Parameters >= 1: for param in params: if param in c.Parameters: if param == 'F': outstring.append(param + PostUtils.fmt( c.Parameters['F'], FEED_DECIMALS, UNITS)) elif param == 'H': outstring.append(param + str(int(c.Parameters['H']))) elif param == 'S': outstring.append( param + PostUtils.fmt(c.Parameters['S'], SPINDLE_DECIMALS, 'G21') ) #rpm is unitless-therefore I had to 'fake it out' by using metric units which don't get converted from entered value elif param == 'T': outstring.append(param + str(int(c.Parameters['T']))) else: outstring.append(param + PostUtils.fmt( c.Parameters[param], AXIS_DECIMALS, UNITS)) outstr = str(outstring) outstr = outstr.replace('[', '') outstr = outstr.replace(']', '') outstr = outstr.replace("'", '') outstr = outstr.replace(",", '') gcode += outstr + '\n' lastcommand = c.Name gcode += TOOLRETURN gcode += SAFETYBLOCK gcode += FOOTER if SHOW_EDITOR: PostUtils.editor(gcode) gfile = pythonopen(filename, "wb") gfile.write(gcode) gfile.close()
def export(objectslist, filename, argstring): processArguments(argstring) for i in objectslist: print(i.Name) global UNITS global UNIT_FORMAT # ISJOB = (len(objectslist) == 1) and isinstance(objectslist[0].Proxy, PathScripts.PathJob.ObjectJob) # print("isjob: {} {}".format(ISJOB, len(objectslist))) # if len(objectslist) > 1: # for obj in objectslist: # if not hasattr(obj, "Path"): # print("the object " + obj.Name + " is not a path. Please select only path and Compounds.") # return print("postprocessing...") gcode = "" # write header if OUTPUT_HEADER: gcode += HEADER gcode += SAFETYBLOCK # Write the preamble if OUTPUT_COMMENTS: for item in objectslist: if isinstance(item.Proxy, PathScripts.PathToolController.ToolController): gcode += ";T{}={}\n".format(item.ToolNumber, item.Name) gcode += linenumber() + ";begin preamble\n" for line in PREAMBLE.splitlines(True): gcode += linenumber() + line gcode += linenumber() + UNITS + "\n" for obj in objectslist: #skip postprocessing tools # if isinstance (obj.Proxy, PathScripts.PathToolController.ToolController): # continue # do the pre_op if OUTPUT_COMMENTS: gcode += linenumber() + ";begin operation\n" for line in PRE_OPERATION.splitlines(True): gcode += linenumber() + line gcode += parse(obj) # do the post_op if OUTPUT_COMMENTS: gcode += linenumber() + ";end operation: %s\n" % obj.Label for line in POST_OPERATION.splitlines(True): gcode += linenumber() + line # do the post_amble if OUTPUT_COMMENTS: gcode += ";begin postamble\n" for line in TOOLRETURN.splitlines(True): gcode += linenumber() + line for line in SAFETYBLOCK.splitlines(True): gcode += linenumber() + line for line in POSTAMBLE.splitlines(True): gcode += linenumber() + line if SHOW_EDITOR: dia = PostUtils.GCodeEditorDialog() dia.editor.setText(gcode) result = dia.exec_() if result: final = dia.editor.toPlainText() else: final = gcode else: final = gcode print("done postprocessing.") if not filename == '-': gfile = pythonopen(filename, "wb") gfile.write(final) gfile.close() return final
def export(selection,filename,argstring): global linenr linenr = STARTLINENR lastX = 0 lastY = 0 lastZ = 0 params = ['X','Y','Z','A','B','I','J','F','H','S','T','Q','R','L'] #Using XY plane most of the time so skipping K modalParamsDict = dict() for mp in MODALPARAMS: modalParamsDict[mp] = None for obj in selection: if not hasattr(obj,"Path"): print "the object " + obj.Name + " is not a path. Please select only path and Compounds." return myMachine = None for pathobj in selection: if hasattr(pathobj,"MachineName"): myMachine = pathobj.MachineName if hasattr(pathobj, "MachineUnits"): if pathobj.MachineUnits == "Metric": UNITS = "G21" else: UNITS = "G20" if myMachine is None: print "No machine found in this selection" gcode ='' gcode+= mkHeader(selection) gcode+= linenumberify(GCODE_HEADER) if UNITS_INCLUDED: gcode += linenumberify(mapGCode(UNITS)) lastcommand = None gobjects = [] for g in selection[0].Group: if g.Name <>'Machine': #filtering out gcode home position from Machine object gobjects.append(g) for obj in gobjects: if hasattr(obj,'Comment'): gcode += linenumberify('(' + obj.Comment + ')') for c in obj.Path.Commands: outstring = [] command = c.Name if (command != UNITS or UNITS_INCLUDED): if command[0]=='(': command = PostUtils.fcoms(command, COMMENT) mappedCommand = mapGCode(command) # the mapping is done for output only! For internal things we still use the old value. if not MODAL or command != lastcommand: outstring.append(mappedCommand) # if MODAL == True: ) # #\better: append iff MODAL == False ) # if command == lastcommand: ) # outstring.pop(0!#\ ) if c.Parameters >= 1: for param in params: if param in c.Parameters: if (param in MODALPARAMS) and (modalParamsDict[str(param)] == c.Parameters[str(param)]): # do nothing or append white space outstring.append(' ') elif param == 'F': outstring.append(param + PostUtils.fmt(c.Parameters['F'], FEED_DECIMALS,UNITS)) elif param == 'H': outstring.append(param + str(int(c.Parameters['H']))) elif param == 'S': outstring.append(param + PostUtils.fmt(c.Parameters['S'], SPINDLE_DECIMALS,'G21')) #rpm is unitless-therefore I had to 'fake it out' by using metric units which don't get converted from entered value elif param == 'T': outstring.append(param + str(int(c.Parameters['T']))) elif param == 'I' and (command == 'G2' or command == 'G3'): # this is the special case for circular paths, where relative coordinates have to be changed to absolute i = c.Parameters['I'] # calculate the radius r j = c.Parameters['J'] r = math.sqrt(i**2 + j**2) if USE_RADIUS_IF_POSSIBLE and angleUnder180(command,lastX,lastY,c.Parameters['X'],c.Parameters['Y'],i,j): outstring.append('R' + PostUtils.fmt(r,AXIS_DECIMALS,UNITS)) else: if RADIUS_COMMENT: outstring.append('(R' + PostUtils.fmt(r,AXIS_DECIMALS,UNITS) + ')') if ABSOLUTE_CIRCLE_CENTER: i += lastX outstring.append(param + PostUtils.fmt(i,AXIS_DECIMALS,UNITS)) elif param == 'J' and (command == 'G2' or command == 'G3'): # this is the special case for circular paths, where incremental center has to be changed to absolute center i = c.Parameters['I'] j = c.Parameters['J'] if USE_RADIUS_IF_POSSIBLE and angleUnder180(command,lastX,lastY,c.Parameters['X'],c.Parameters['Y'],i,j): # R is handled with the I parameter, here: do nothing at all, keep the structure as with I command pass else: if ABSOLUTE_CIRCLE_CENTER: j += lastY if SWAP_Y_Z: # we have to swap j and k as well outstring.append('K' + PostUtils.fmt(j,AXIS_DECIMALS,UNITS)) else: outstring.append(param + PostUtils.fmt(j,AXIS_DECIMALS,UNITS)) elif param == 'K' and (command == 'G2' or command == 'G3'): # this is the special case for circular paths, where incremental center has to be changed to absolute center outstring.append('(' + param + PostUtils.fmt(c.Parameters[param],AXIS_DECIMALS,UNITS) + ')') z = c.Parameters['Z'] k = c.Parameters['K'] if USE_RADIUS_IF_POSSIBLE and angleUnder180(command,lastX,lastY,c.Parameters['X'],c.Parameters['Y'],i,j): # R is handled with the I parameter, here: do nothing at all, keep the structure as with I command pass else: if ABSOLUTE_CIRCLE_CENTER: k += lastZ if SWAP_Y_Z: # we have to swap j and k as well outstring.append('J' + PostUtils.fmt(j,AXIS_DECIMALS,UNITS)) else: outstring.append(param + PostUtils.fmt(j,AXIS_DECIMALS,UNITS)) elif param == 'Y' and SWAP_Y_Z: outstring.append('Z' + PostUtils.fmt(c.Parameters[param],AXIS_DECIMALS,UNITS)) elif param == 'Z' and SWAP_Y_Z: outstring.append('Y' + PostUtils.fmt(c.Parameters[param],AXIS_DECIMALS,UNITS)) else: outstring.append(param + PostUtils.fmt(c.Parameters[param],AXIS_DECIMALS,UNITS)) if param in MODALPARAMS: modalParamsDict[str(param)] = c.Parameters[param] # save the last X, Y, Z values if 'X' in c.Parameters: lastX = c.Parameters['X'] if 'Y' in c.Parameters: lastY = c.Parameters['Y'] if 'Z' in c.Parameters: lastZ = c.Parameters['Z'] outstr = str(outstring) outstr =outstr.replace(']','') outstr =outstr.replace('[','') outstr =outstr.replace("'",'') outstr =outstr.replace(",",'') if LINENUMBERS: gcode += "N" + str(linenr) + " " linenr += LINENUMBER_INCREMENT gcode+= outstr + '\n' lastcommand = c.Name gcode+= linenumberify(GCODE_FOOTER) if SHOW_EDITOR: PostUtils.editor(gcode) gfile = pythonopen(filename,"wb") gfile.write(gcode) gfile.close()
def export(objectslist, filename, argstring): global UNITS global linenr linenr = STARTLINENR lastX = 0 lastY = 0 lastZ = 0 params = [ "X", "Y", "Z", "A", "B", "I", "J", "F", "H", "S", "T", "Q", "R", "L", ] # Using XY plane most of the time so skipping K modalParamsDict = dict() for mp in MODALPARAMS: modalParamsDict[mp] = None for obj in objectslist: if not hasattr(obj, "Path"): print("the object " + obj.Name + " is not a path. Please select only path and Compounds.") return myMachine = None for pathobj in objectslist: if hasattr(pathobj, "MachineName"): myMachine = pathobj.MachineName if hasattr(pathobj, "MachineUnits"): if pathobj.MachineUnits == "Metric": UNITS = "G21" else: UNITS = "G20" if myMachine is None: print("philips_post: No machine found in this selection") gcode = "" gcode += mkHeader(objectslist) gcode += linenumberify(GCODE_HEADER) if UNITS_INCLUDED: gcode += linenumberify(mapGCode(UNITS)) lastcommand = None for obj in objectslist: if hasattr(obj, "Comment"): gcode += linenumberify("(" + obj.Comment + ")") for c in obj.Path.Commands: outstring = [] command = c.Name if command != "G0": command = command.replace("G0", "G") # normalize: G01 -> G1 if command != UNITS or UNITS_INCLUDED: if command[0] == "(": command = PostUtils.fcoms(command, COMMENT) # the mapping is done for output only! For internal things we # still use the old value. mappedCommand = mapGCode(command) if not MODAL or command != lastcommand: outstring.append(mappedCommand) # if MODAL: # #\better: append iff MODAL == False # if command == lastcommand: # outstring.pop(0) if len(c.Parameters) >= 1: for param in params: # test print("param: " + param + ", command: " + command) if param in c.Parameters: if (param in MODALPARAMS) and ( modalParamsDict[str(param)] == c.Parameters[str(param)]): # do nothing or append white space outstring.append(" ") elif param == "F": feed = c.Parameters["F"] if SUPPRESS_ZERO_FEED and feed == 0: pass else: outstring.append(param + PostUtils.fmt( feed, FEED_DECIMALS, UNITS)) elif param == "H": outstring.append(param + str(int(c.Parameters["H"]))) elif param == "S": # rpm is unitless-therefore I had to 'fake it # out' by using metric units which don't get # converted from entered value outstring.append( param + PostUtils.fmt(c.Parameters["S"], SPINDLE_DECIMALS, "G21")) elif param == "T": outstring.append(param + str(int(c.Parameters["T"]))) elif param == "I" and (command == "G2" or command == "G3"): # test print("param = 'I'") # this is the special case for circular paths, # where relative coordinates have to be changed # to absolute i = c.Parameters["I"] # calculate the radius r j = c.Parameters["J"] r = math.sqrt(i**2 + j**2) if USE_RADIUS_IF_POSSIBLE and angleUnder180( command, lastX, lastY, c.Parameters["X"], c.Parameters["Y"], i, j, ): outstring.append( "R" + PostUtils.fmt(r, AXIS_DECIMALS, UNITS)) else: if RADIUS_COMMENT: outstring.append("(R" + PostUtils.fmt( r, AXIS_DECIMALS, UNITS) + ")") if ABSOLUTE_CIRCLE_CENTER: i += lastX outstring.append( param + PostUtils.fmt(i, AXIS_DECIMALS, UNITS)) elif param == "J" and (command == "G2" or command == "G3"): # this is the special case for circular paths, # where incremental center has to be changed to # absolute center i = c.Parameters["I"] j = c.Parameters["J"] if USE_RADIUS_IF_POSSIBLE and angleUnder180( command, lastX, lastY, c.Parameters["X"], c.Parameters["Y"], i, j, ): # R is handled with the I parameter, here: # do nothing at all, keep the structure as # with I command pass else: if ABSOLUTE_CIRCLE_CENTER: j += lastY if SWAP_Y_Z: # we have to swap j and k as well outstring.append("K" + PostUtils.fmt( j, AXIS_DECIMALS, UNITS)) else: outstring.append(param + PostUtils.fmt( j, AXIS_DECIMALS, UNITS)) elif param == "K" and (command == "G2" or command == "G3"): # this is the special case for circular paths, # where incremental center has to be changed to # absolute center outstring.append( "(" + param + PostUtils.fmt(c.Parameters[param], AXIS_DECIMALS, UNITS) + ")") z = c.Parameters["Z"] k = c.Parameters["K"] if USE_RADIUS_IF_POSSIBLE and angleUnder180( command, lastX, lastY, c.Parameters["X"], c.Parameters["Y"], i, j, ): # R is handled with the I parameter, here: # do nothing at all, keep the structure as # with I command pass else: if ABSOLUTE_CIRCLE_CENTER: k += lastZ if SWAP_Y_Z: # we have to swap j and k as well outstring.append( "J" + PostUtils.fmt(j, AXIS_DECIMALS, UNITS)) else: outstring.append( param + PostUtils.fmt(j, AXIS_DECIMALS, UNITS)) elif param == "Y" and SWAP_Y_Z: outstring.append("Z" + PostUtils.fmt( c.Parameters[param], AXIS_DECIMALS, UNITS)) elif param == "Z" and SWAP_Y_Z: outstring.append("Y" + PostUtils.fmt( c.Parameters[param], AXIS_DECIMALS, UNITS)) else: # To Do: suppress unknown commands, if this is done here, all X parameters are suppressed # this is an unknown command, don't create GCode for it # print("parameter " + param + " for command " + command + " ignored") outstring.append(param + PostUtils.fmt( c.Parameters[param], AXIS_DECIMALS, UNITS)) if param in MODALPARAMS: modalParamsDict[str( param)] = c.Parameters[param] # save the last X, Y, Z values if "X" in c.Parameters: lastX = c.Parameters["X"] if "Y" in c.Parameters: lastY = c.Parameters["Y"] if "Z" in c.Parameters: lastZ = c.Parameters["Z"] outstr = "" for w in outstring: outstr += w + COMMAND_SPACE outstr = outstr.replace("]", "") outstr = outstr.replace("[", "") outstr = outstr.replace("'", "") outstr = outstr.replace(",", ".") if LINENUMBERS: gcode += "N" + str(linenr) + " " linenr += LINENUMBER_INCREMENT gcode += outstr + "\n" lastcommand = c.Name gcode = gcode.replace("_", "-") gcode += linenumberify(GCODE_FOOTER) if SHOW_EDITOR: PostUtils.editor(gcode) gfile = pythonopen(filename, "w") gfile.write(gcode) gfile.close()
def export(objectslist, filename, argstring): if not processArguments(argstring): return None global UNITS global UNIT_FORMAT global UNIT_FEED_FORMAT global MOTION_MODE global SUPPRESS_COMMANDS 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' # Suppress drill-cycle commands: if TRANSLATE_DRILL_CYCLES: SUPPRESS_COMMANDS += ['G80', 'G98', 'G99'] # Write the preamble: if OUTPUT_COMMENTS: 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' 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.') return # Skip inactive operations: 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' if OUTPUT_COMMENTS: 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 = 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' # Parse the op: gcode += parse(obj) # Do the post_op: if OUTPUT_COMMENTS and OUTPUT_FINISH: 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 OUTPUT_COMMENTS: 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' if OUTPUT_COMMENTS: 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() # 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() else: ref_Z = '' ref_Y = ' Y' + RETURN_TO[first_comma + 1:].strip() 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' # Show the gcode result dialog: if FreeCAD.GuiUp and SHOW_EDITOR: dia = PostUtils.GCodeEditorDialog() dia.editor.setText(gcode) result = dia.exec_() if result: final = dia.editor.toPlainText() else: final = gcode else: final = gcode print('Done postprocessing.') # Write the file: with open(filename, 'w') as fp: fp.write(final)
def export(selection, filename, argstring): params = [ "X", "Y", "Z", "A", "B", "I", "J", "F", "H", "S", "T", "Q", "R", "L", ] # Using XY plane most of the time so skipping K for obj in selection: if not hasattr(obj, "Path"): print "the object " + obj.Name + " is not a path. Please select only path and Compounds." return myMachine = None for pathobj in selection: if hasattr(pathobj, "MachineName"): myMachine = pathobj.MachineName if hasattr(pathobj, "MachineUnits"): if pathobj.MachineUnits == "Metric": UNITS = "G21" else: UNITS = "G20" if myMachine is None: print "No machine found in this selection" gcode = "" gcode += HEADER % (FreeCAD.ActiveDocument.FileName) gcode += SAFETYBLOCK gcode += UNITS + "\n" lastcommand = None gcode += COMMENT + selection[0].Description + "\n" gobjects = [] for g in selection[0].Group: gobjects.append(g) for obj in gobjects: for c in obj.Path.Commands: outstring = [] command = c.Name if command[0] == "(": command = PostUtils.fcoms(command, COMMENT) outstring.append(command) if MODAL == True: if command == lastcommand: outstring.pop(0) if c.Parameters >= 1: for param in params: if param in c.Parameters: if param == "F": outstring.append(param + PostUtils.fmt(c.Parameters["F"], FEED_DECIMALS, UNITS)) elif param == "H": outstring.append(param + str(int(c.Parameters["H"]))) elif param == "S": outstring.append( param + PostUtils.fmt(c.Parameters["S"], SPINDLE_DECIMALS, "G21") ) # rpm is unitless-therefore I had to 'fake it out' by using metric units which don't get converted from entered value elif param == "T": outstring.append(param + str(int(c.Parameters["T"]))) else: outstring.append(param + PostUtils.fmt(c.Parameters[param], AXIS_DECIMALS, UNITS)) outstr = str(outstring) outstr = outstr.replace("[", "") outstr = outstr.replace("]", "") outstr = outstr.replace("'", "") outstr = outstr.replace(",", "") gcode += outstr + "\n" lastcommand = c.Name gcode += TOOLRETURN gcode += SAFETYBLOCK gcode += FOOTER if SHOW_EDITOR: PostUtils.editor(gcode) gfile = pythonopen(filename, "wb") gfile.write(gcode) gfile.close()
def export(objectslist, filename, argstring): processArguments(argstring) global UNITS global UNIT_FORMAT for obj in objectslist: if not hasattr(obj, "Path"): print("the object " + obj.Name + " is not a path. Please select only path and Compounds.") return print("postprocessing...") gcode = "" # write header if OUTPUT_HEADER: gcode += linenumber() + "(Exported by FreeCAD)\n" gcode += linenumber() + "(Post Processor: " + __name__ + ")\n" gcode += linenumber() + "(Output Time:" + str(now) + ")\n" # Write the preamble if OUTPUT_COMMENTS: gcode += linenumber() + "(begin preamble)\n" for line in PREAMBLE.splitlines(True): gcode += linenumber() + line gcode += linenumber() + UNITS + "\n" for obj in objectslist: # fetch machine details job = PathUtils.findParentJob(obj) myMachine = 'not set' if hasattr(job, "MachineName"): myMachine = job.MachineName if hasattr(job, "MachineUnits"): if job.MachineUnits == "Metric": UNITS = "G21" UNIT_FORMAT = 'mm/min' else: UNITS = "G20" UNIT_FORMAT = 'in/min' # do the pre_op if OUTPUT_COMMENTS: gcode += linenumber() + "(begin operation: %s)\n" % obj.Label gcode += linenumber() + "(machine: %s, %s)\n" % (myMachine, UNIT_FORMAT) for line in PRE_OPERATION.splitlines(True): gcode += linenumber() + line gcode += parse(obj) # do the post_op if OUTPUT_COMMENTS: gcode += linenumber() + "(finish operation: %s)\n" % obj.Label for line in POST_OPERATION.splitlines(True): gcode += linenumber() + line # do the post_amble if OUTPUT_COMMENTS: gcode += "(begin postamble)\n" for line in POSTAMBLE.splitlines(True): gcode += linenumber() + line if SHOW_EDITOR: dia = PostUtils.GCodeEditorDialog() dia.editor.setText(gcode) result = dia.exec_() if result: final = dia.editor.toPlainText() else: final = gcode else: final = gcode print("done postprocessing.") if not filename == '-': gfile = pythonopen(filename, "wb") gfile.write(final) gfile.close() return final
def export(objectslist, filename, argstring): if not processArguments(argstring): return None global UNITS global UNIT_FORMAT global UNIT_FEED_FORMAT global MOTION_MODE global SUPPRESS_COMMANDS 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" # Suppress drill-cycle commands: if TRANSLATE_DRILL_CYCLES: SUPPRESS_COMMANDS += ["G80", "G98", "G99"] # Write the preamble: if OUTPUT_COMMENTS: 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" 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." ) return # Skip inactive operations: 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" if OUTPUT_COMMENTS: 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 = 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" # Parse the op: gcode += parse(obj) # Do the post_op: if OUTPUT_COMMENTS and OUTPUT_FINISH: 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 OUTPUT_COMMENTS: 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" if OUTPUT_COMMENTS: 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() # 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() else: ref_Z = "" ref_Y = " Y" + RETURN_TO[first_comma + 1 :].strip() 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" # Show the gcode result dialog: if FreeCAD.GuiUp and SHOW_EDITOR: dia = PostUtils.GCodeEditorDialog() dia.editor.setText(gcode) result = dia.exec_() if result: final = dia.editor.toPlainText() else: final = gcode else: final = gcode print("Done postprocessing.") # Write the file: with open(filename, "w") as fp: fp.write(final)
def export(selection, filename, argstring): global linenr linenr = STARTLINENR lastX = 0 lastY = 0 lastZ = 0 params = [ "X", "Y", "Z", "A", "B", "I", "J", "F", "H", "S", "T", "Q", "R", "L", ] # Using XY plane most of the time so skipping K modalParamsDict = dict() for mp in MODALPARAMS: modalParamsDict[mp] = None for obj in selection: if not hasattr(obj, "Path"): print "the object " + obj.Name + " is not a path. Please select only path and Compounds." return myMachine = None for pathobj in selection: if hasattr(pathobj, "MachineName"): myMachine = pathobj.MachineName if hasattr(pathobj, "MachineUnits"): if pathobj.MachineUnits == "Metric": UNITS = "G21" else: UNITS = "G20" if myMachine is None: print "No machine found in this selection" gcode = "" gcode += mkHeader(selection) gcode += linenumberify(GCODE_HEADER) if UNITS_INCLUDED: gcode += linenumberify(mapGCode(UNITS)) lastcommand = None gobjects = [] for g in selection[0].Group: gobjects.append(g) for obj in gobjects: if hasattr(obj, "GComment"): gcode += linenumberify("(" + obj.GComment + ")") for c in obj.Path.Commands: outstring = [] command = c.Name if command != UNITS or UNITS_INCLUDED: if command[0] == "(": command = PostUtils.fcoms(command, COMMENT) mappedCommand = mapGCode( command ) # the mapping is done for output only! For internal things we still use the old value. if not MODAL or command != lastcommand: outstring.append(mappedCommand) # if MODAL == True: ) # #\better: append iff MODAL == False ) # if command == lastcommand: ) # outstring.pop(0!#\ ) if c.Parameters >= 1: for param in params: if param in c.Parameters: if (param in MODALPARAMS) and (modalParamsDict[str(param)] == c.Parameters[str(param)]): # do nothing or append white space outstring.append(" ") elif param == "F": outstring.append(param + PostUtils.fmt(c.Parameters["F"], FEED_DECIMALS, UNITS)) elif param == "H": outstring.append(param + str(int(c.Parameters["H"]))) elif param == "S": outstring.append( param + PostUtils.fmt(c.Parameters["S"], SPINDLE_DECIMALS, "G21") ) # rpm is unitless-therefore I had to 'fake it out' by using metric units which don't get converted from entered value elif param == "T": outstring.append(param + str(int(c.Parameters["T"]))) elif param == "I" and (command == "G2" or command == "G3"): # this is the special case for circular paths, where relative coordinates have to be changed to absolute i = c.Parameters["I"] # calculate the radius r j = c.Parameters["J"] r = math.sqrt(i ** 2 + j ** 2) if USE_RADIUS_IF_POSSIBLE and angleUnder180( command, lastX, lastY, c.Parameters["X"], c.Parameters["Y"], i, j ): outstring.append("R" + PostUtils.fmt(r, AXIS_DECIMALS, UNITS)) else: if RADIUS_COMMENT: outstring.append("(R" + PostUtils.fmt(r, AXIS_DECIMALS, UNITS) + ")") if ABSOLUTE_CIRCLE_CENTER: i += lastX outstring.append(param + PostUtils.fmt(i, AXIS_DECIMALS, UNITS)) elif param == "J" and (command == "G2" or command == "G3"): # this is the special case for circular paths, where incremental center has to be changed to absolute center i = c.Parameters["I"] j = c.Parameters["J"] if USE_RADIUS_IF_POSSIBLE and angleUnder180( command, lastX, lastY, c.Parameters["X"], c.Parameters["Y"], i, j ): # R is handled with the I parameter, here: do nothing at all, keep the structure as with I command pass else: if ABSOLUTE_CIRCLE_CENTER: j += lastY if SWAP_Y_Z: # we have to swap j and k as well outstring.append("K" + PostUtils.fmt(j, AXIS_DECIMALS, UNITS)) else: outstring.append(param + PostUtils.fmt(j, AXIS_DECIMALS, UNITS)) elif param == "K" and (command == "G2" or command == "G3"): # this is the special case for circular paths, where incremental center has to be changed to absolute center outstring.append( "(" + param + PostUtils.fmt(c.Parameters[param], AXIS_DECIMALS, UNITS) + ")" ) z = c.Parameters["Z"] k = c.Parameters["K"] if USE_RADIUS_IF_POSSIBLE and angleUnder180( command, lastX, lastY, c.Parameters["X"], c.Parameters["Y"], i, j ): # R is handled with the I parameter, here: do nothing at all, keep the structure as with I command pass else: if ABSOLUTE_CIRCLE_CENTER: k += lastZ if SWAP_Y_Z: # we have to swap j and k as well outstring.append("J" + PostUtils.fmt(j, AXIS_DECIMALS, UNITS)) else: outstring.append(param + PostUtils.fmt(j, AXIS_DECIMALS, UNITS)) elif param == "Y" and SWAP_Y_Z: outstring.append("Z" + PostUtils.fmt(c.Parameters[param], AXIS_DECIMALS, UNITS)) elif param == "Z" and SWAP_Y_Z: outstring.append("Y" + PostUtils.fmt(c.Parameters[param], AXIS_DECIMALS, UNITS)) else: outstring.append(param + PostUtils.fmt(c.Parameters[param], AXIS_DECIMALS, UNITS)) if param in MODALPARAMS: modalParamsDict[str(param)] = c.Parameters[param] # save the last X, Y, Z values if "X" in c.Parameters: lastX = c.Parameters["X"] if "Y" in c.Parameters: lastY = c.Parameters["Y"] if "Z" in c.Parameters: lastZ = c.Parameters["Z"] outstr = str(outstring) outstr = outstr.replace("]", "") outstr = outstr.replace("[", "") outstr = outstr.replace("'", "") outstr = outstr.replace(",", "") if LINENUMBERS: gcode += "N" + str(linenr) + " " linenr += LINENUMBER_INCREMENT gcode += outstr + "\n" lastcommand = c.Name gcode += linenumberify(GCODE_FOOTER) if SHOW_EDITOR: PostUtils.editor(gcode) gfile = pythonopen(filename, "wb") gfile.write(gcode) gfile.close()
def export(objectslist, filename, argstring): global UNITS global linenr global ABSOLUTE_CIRCLE_CENTER global USE_RADIUS_IF_POSSIBLE global RADIUS_COMMENT linenr = STARTLINENR lastX = 0 lastY = 0 lastZ = 0 params = ['X', 'Y', 'Z', 'A', 'B', 'I', 'J', 'F', 'H', 'S', 'T', 'Q', 'R', 'L'] # Using XY plane most of the time so skipping K modalParamsDict = dict() for mp in MODALPARAMS: modalParamsDict[mp] = None for obj in objectslist: if not hasattr(obj, "Path"): print("the object " + obj.Name + " is not a path. Please select only path and Compounds.") return myMachine = None for pathobj in objectslist: if hasattr(pathobj, "MachineName"): myMachine = pathobj.MachineName if hasattr(pathobj, "MachineUnits"): if pathobj.MachineUnits == "Metric": UNITS = "G21" else: UNITS = "G20" if myMachine is None: print("philips_post: No machine found in this selection") gcode = '' gcode += mkHeader(objectslist) gcode += linenumberify(GCODE_HEADER) if UNITS_INCLUDED: gcode += linenumberify(mapGCode(UNITS)) lastcommand = None for obj in objectslist: if hasattr(obj, 'Comment'): gcode += linenumberify('(' + obj.Comment + ')') for c in obj.Path.Commands: outstring = [] command = c.Name if command != 'G0': command = command.replace('G0','G') # normalize: G01 -> G1 if (command != UNITS or UNITS_INCLUDED): if command[0] == '(': command = PostUtils.fcoms(command, COMMENT) # the mapping is done for output only! For internal things we # still use the old value. mappedCommand = mapGCode(command) if not MODAL or command != lastcommand: outstring.append(mappedCommand) # if MODAL == True: # #\better: append iff MODAL == False # if command == lastcommand: # outstring.pop(0) if c.Parameters >= 1: for param in params: # test print("param: " + param + ", command: " + command) if param in c.Parameters: if (param in MODALPARAMS) and (modalParamsDict[str(param)] == c.Parameters[str(param)]): # do nothing or append white space outstring.append(' ') elif param == 'F': feed = c.Parameters['F'] if SUPPRESS_ZERO_FEED and feed == 0: pass else: outstring.append( param + PostUtils.fmt(feed, FEED_DECIMALS, UNITS)) elif param == 'H': outstring.append( param + str(int(c.Parameters['H']))) elif param == 'S': # rpm is unitless-therefore I had to 'fake it # out' by using metric units which don't get # converted from entered value outstring.append( param + PostUtils.fmt(c.Parameters['S'], SPINDLE_DECIMALS, 'G21')) elif param == 'T': outstring.append( param + str(int(c.Parameters['T']))) elif param == 'I' and (command == 'G2' or command == 'G3'): #test print("param = 'I'") # this is the special case for circular paths, # where relative coordinates have to be changed # to absolute i = c.Parameters['I'] # calculate the radius r j = c.Parameters['J'] r = math.sqrt(i**2 + j**2) if USE_RADIUS_IF_POSSIBLE and angleUnder180(command, lastX, lastY, c.Parameters['X'], c.Parameters['Y'], i, j): outstring.append( 'R' + PostUtils.fmt(r, AXIS_DECIMALS, UNITS)) else: if RADIUS_COMMENT: outstring.append( '(R' + PostUtils.fmt(r, AXIS_DECIMALS, UNITS) + ')') if ABSOLUTE_CIRCLE_CENTER: i += lastX outstring.append( param + PostUtils.fmt(i, AXIS_DECIMALS, UNITS)) elif param == 'J' and (command == 'G2' or command == 'G3'): # this is the special case for circular paths, # where incremental center has to be changed to # absolute center i = c.Parameters['I'] j = c.Parameters['J'] if USE_RADIUS_IF_POSSIBLE and angleUnder180(command, lastX, lastY, c.Parameters['X'], c.Parameters['Y'], i, j): # R is handled with the I parameter, here: # do nothing at all, keep the structure as # with I command pass else: if ABSOLUTE_CIRCLE_CENTER: j += lastY if SWAP_Y_Z: # we have to swap j and k as well outstring.append( 'K' + PostUtils.fmt(j, AXIS_DECIMALS, UNITS)) else: outstring.append( param + PostUtils.fmt(j, AXIS_DECIMALS, UNITS)) elif param == 'K' and (command == 'G2' or command == 'G3'): # this is the special case for circular paths, # where incremental center has to be changed to # absolute center outstring.append( '(' + param + PostUtils.fmt(c.Parameters[param], AXIS_DECIMALS, UNITS) + ')') z = c.Parameters['Z'] k = c.Parameters['K'] if USE_RADIUS_IF_POSSIBLE and angleUnder180(command, lastX, lastY, c.Parameters['X'], c.Parameters['Y'], i, j): # R is handled with the I parameter, here: # do nothing at all, keep the structure as # with I command pass else: if ABSOLUTE_CIRCLE_CENTER: k += lastZ if SWAP_Y_Z: # we have to swap j and k as well outstring.append( 'J' + PostUtils.fmt(j, AXIS_DECIMALS, UNITS)) else: outstring.append( param + PostUtils.fmt(j, AXIS_DECIMALS, UNITS)) elif param == 'Y' and SWAP_Y_Z: outstring.append( 'Z' + PostUtils.fmt(c.Parameters[param], AXIS_DECIMALS, UNITS)) elif param == 'Z' and SWAP_Y_Z: outstring.append( 'Y' + PostUtils.fmt(c.Parameters[param], AXIS_DECIMALS, UNITS)) else: # To Do: suppress unknown commands, if this is done here, all X parameters are suppressed # this is an unknown command, don't create GCode for it # print("parameter " + param + " for command " + command + " ignored") outstring.append( param + PostUtils.fmt(c.Parameters[param], AXIS_DECIMALS, UNITS)) if param in MODALPARAMS: modalParamsDict[str(param)] = c.Parameters[ param] # save the last X, Y, Z values if 'X' in c.Parameters: lastX = c.Parameters['X'] if 'Y' in c.Parameters: lastY = c.Parameters['Y'] if 'Z' in c.Parameters: lastZ = c.Parameters['Z'] outstr = '' for w in outstring: outstr += w + COMMAND_SPACE outstr = outstr.replace(']', '') outstr = outstr.replace('[', '') outstr = outstr.replace("'", '') outstr = outstr.replace(",", '.') if LINENUMBERS: gcode += "N" + str(linenr) + " " linenr += LINENUMBER_INCREMENT gcode += outstr + '\n' lastcommand = c.Name gcode = gcode.replace("_","-") gcode += linenumberify(GCODE_FOOTER) if SHOW_EDITOR: PostUtils.editor(gcode) gfile = pythonopen(filename, "w") gfile.write(gcode) gfile.close()
def export(objectslist, filename, argstring): if not processArguments(argstring): return None global UNITS global POSTGCODE global G_FUNCTION_STORE global MACHINE_WORK_AXIS global MACHINE_LAST_POSITION global MACHINE_TRASL_ROT global STORED_COMPENSATED_OBJ global COMPENSATION_DIFF_STATUS global LBLIZE_STAUS Object_Kind = None Feed_Rapid = False Feed = 0 Spindle_RPM = 0 Spindle_Active = False ToolId = "" Compensation = "0" params = [ 'X', 'Y', 'Z', 'A', 'B', 'C', 'I', 'J', 'K', 'F', 'H', 'S', 'T', 'Q', 'R', 'L' ] for obj in objectslist: if not hasattr(obj, "Path"): print( "the object " + obj.Name + " is not a path. Please select only path and Compounds." ) return POSTGCODE.append(HEIDEN_Begin(objectslist)) #add header for obj in objectslist: Cmd_Count = 0 # command line number LBLIZE_STAUS = False # useful to get idea of object kind if isinstance (obj.Proxy, PathScripts.PathToolController.ToolController): Object_Kind = "TOOL" # like we go to change tool position MACHINE_LAST_POSITION['X'] = 99999 MACHINE_LAST_POSITION['Y'] = 99999 MACHINE_LAST_POSITION['Z'] = 99999 elif isinstance (obj.Proxy, PathScripts.PathProfileEdges.ObjectProfile): Object_Kind = "PROFILE" if LBLIZE_ACTIVE: LBLIZE_STAUS = True elif isinstance (obj.Proxy, PathScripts.PathMillFace.ObjectFace): Object_Kind = "FACE" if LBLIZE_ACTIVE: LBLIZE_STAUS = True elif isinstance (obj.Proxy, PathScripts.PathHelix.ObjectHelix): Object_Kind = "HELIX" # If used compensated path, store, recompute and diff when asked if hasattr(obj, 'UseComp') and SOLVE_COMPENSATION_ACTIVE: if obj.UseComp: if hasattr(obj.Path, 'Commands') and Object_Kind == "PROFILE": # Take a copy of compensated path STORED_COMPENSATED_OBJ = obj.Path.Commands # Find mill compensation if hasattr(obj, 'Side') and hasattr(obj, 'Direction'): if obj.Side == "Outside" and obj.Direction == "CW": Compensation = "L" elif obj.Side == "Outside" and obj.Direction == "CCW": Compensation = "R" elif obj.Side != "Outside" and obj.Direction == "CW": Compensation = "R" else: Compensation = "L" # set obj.UseComp to false and recompute() to get uncompensated path obj.UseComp = False obj.recompute() # small edges could be skipped and movements joints can add edges NameStr = "" if hasattr(obj, 'Label'): NameStr = str(obj.Label) if len(obj.Path.Commands) != len(STORED_COMPENSATED_OBJ): # not same number of edges obj.UseComp = True obj.recompute() POSTGCODE.append("; MISSING EDGES UNABLE TO GET COMPENSATION") if not SKIP_WARNS: ( PostUtils.editor( "--solve-comp command ACTIVE\n\n" + "UNABLE to solve " + NameStr + " compensation\n\n" + "Some edges are missing\n" + "try to change Join Type to Miter or Square\n" + "try to use a smaller Tool Diameter\n" + "Internal Path could have too small corners\n\n" + "use --no-warns to not prompt this message" ) ) else: if not SKIP_WARNS: ( PostUtils.editor( "--solve-comp command ACTIVE\n\n" + "BE CAREFUL with solved " + NameStr + " compensation\n\n" + "USE AT YOUR OWN RISK\n" + "Simulate it before use\n" + "Offset Extra ignored use DR+ on TOOL CALL\n" + "Path could be different and/or give tool radius errors\n\n" + "use --no-warns to not prompt this message" ) ) # we can try to solve compensation POSTGCODE.append("; COMPENSATION ACTIVE") COMPENSATION_DIFF_STATUS[0] = True for c in obj.Path.Commands: Cmd_Count += 1 outstring = [] command = c.Name if command != 'G0': command = command.replace('G0','G') # normalize: G01 -> G1 Feed_Rapid = False else: Feed_Rapid = True for param in params: if param in c.Parameters: if param == 'F': Feed = c.Parameters['F'] elif param == 'S': Spindle_RPM = c.Parameters['S'] # Could be deleted if tool it's OK elif param == 'T': ToolId = c.Parameters['T'] # Could be deleted if tool it's OK if command == 'G90': G_FUNCTION_STORE['G90'] = True G_FUNCTION_STORE['G91'] = False if command == 'G91': G_FUNCTION_STORE['G91'] = True G_FUNCTION_STORE['G90'] = False if command == 'G98': G_FUNCTION_STORE['G98'] = True G_FUNCTION_STORE['G99'] = False if command == 'G99': G_FUNCTION_STORE['G99'] = True G_FUNCTION_STORE['G98'] = False # Rapid movement if command == 'G0': Spindle_Status = "" if Spindle_Active == False: # At first rapid movement we turn on spindle Spindle_Status += str(MACHINE_SPINDLE_DIRECTION) # Activate spindle Spindle_Active = True else: # At last rapid movement we turn off spindle if Cmd_Count == len(obj.Path.Commands): Spindle_Status += "5" # Deactivate spindle Spindle_Active = False else: Spindle_Status += "" # Spindle still active parsedElem = HEIDEN_Line( c.Parameters, Compensation, Feed, True, Spindle_Status, Cmd_Count ) if parsedElem != None: POSTGCODE.append(parsedElem) # Linear movement if command == 'G1': parsedElem = HEIDEN_Line( c.Parameters, Compensation, Feed, False, "", Cmd_Count ) if parsedElem != None: POSTGCODE.append(parsedElem) # Arc movement if command == 'G2' or command == 'G3': parsedElem = HEIDEN_Arc( c.Parameters, command, Compensation, Feed, False, "", Cmd_Count ) if parsedElem != None: POSTGCODE.extend(parsedElem) if command == 'G80': #Reset Canned Cycles G_FUNCTION_STORE['G81'] = False G_FUNCTION_STORE['G82'] = False G_FUNCTION_STORE['G83'] = False # Drilling, Dwell Drilling, Peck Drilling if command == 'G81' or command == 'G82' or command == 'G83': parsedElem = HEIDEN_Drill( obj, c.Parameters, command, Feed ) if parsedElem != None: POSTGCODE.extend(parsedElem) # Tool change if command == 'M6': parsedElem = HEIDEN_ToolCall(obj) if parsedElem != None: POSTGCODE.append(parsedElem) if COMPENSATION_DIFF_STATUS[0]: #Restore the compensation if removed obj.UseComp = True obj.recompute() COMPENSATION_DIFF_STATUS[0] = False if LBLIZE_STAUS: HEIDEN_LBL_Replace() LBLIZE_STAUS = False if LBLIZE_ACTIVE: if not SKIP_WARNS: ( PostUtils.editor( "--solve-lbl command ACTIVE\n\n" + "BE CAREFUL with LBL replacements\n\n" + "USE AT YOUR OWN RISK\n" + "Simulate it before use\n" + "Path could be different and/or give errors\n\n" + "use --no-warns to not prompt this message" ) ) POSTGCODE.append(HEIDEN_End(objectslist)) #add footer Program_Out = HEIDEN_Numberize(POSTGCODE) #add line number if SHOW_EDITOR: PostUtils.editor(Program_Out) gfile = pythonopen(filename, "w") gfile.write(Program_Out) gfile.close()
def export(objectslist, filename, argstring): if not processArguments(argstring): return None global UNITS global UNIT_FORMAT global UNIT_SPEED_FORMAT global MOTION_MODE global SUPPRESS_COMMANDS print("Post Processor: " + __name__ + " postprocessing...") gcode = "" # write header if OUTPUT_HEADER: gcode += linenumber() + "(Exported by FreeCAD)\n" gcode += linenumber() + "(Post Processor: " + __name__ + ")\n" gcode += linenumber() + "(Output Time:" + str(datetime.datetime.now()) + ")\n" # Check canned cycles for drilling if TRANSLATE_DRILL_CYCLES: if len(SUPPRESS_COMMANDS) == 0: SUPPRESS_COMMANDS = ['G99', 'G98', 'G80'] else: SUPPRESS_COMMANDS += ['G99', 'G98', 'G80'] # Write the preamble if OUTPUT_COMMENTS: gcode += linenumber() + "(Begin preamble)\n" for line in PREAMBLE.splitlines(True): gcode += linenumber() + line # verify if PREAMBLE have changed MOTION_MODE or UNITS if 'G90' in PREAMBLE: MOTION_MODE = 'G90' elif 'G91' in PREAMBLE: MOTION_MODE = 'G91' else: gcode += linenumber() + MOTION_MODE + "\n" if 'G21' in PREAMBLE: UNITS = 'G21' UNIT_FORMAT = 'mm' UNIT_SPEED_FORMAT = 'mm/min' elif 'G20' in PREAMBLE: UNITS = 'G20' UNIT_FORMAT = 'in' UNIT_SPEED_FORMAT = 'in/min' else: gcode += linenumber() + UNITS + "\n" for obj in objectslist: # Debug... # print("\n" + "*"*70) # dump(obj) # print("*"*70 + "\n") 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: 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" if OUTPUT_COMMENTS: gcode += linenumber() + "(Begin operation: " + obj.Label + ")\n" for line in PRE_OPERATION.splitlines(True): gcode += linenumber() + line # get coolant mode coolantMode = 'None' 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' # Parse the op gcode += parse(obj) # do the post_op if OUTPUT_COMMENTS: gcode += linenumber() + "(Finish operation: " + obj.Label + ")\n" for line in POST_OPERATION.splitlines(True): gcode += linenumber() + line # turn coolant off if required if not coolantMode == 'None': if OUTPUT_COMMENTS: 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" if OUTPUT_COMMENTS: gcode += linenumber() + "(Begin postamble)\n" for line in POSTAMBLE.splitlines(True): gcode += linenumber() + line if RETURN_TO: gcode += linenumber() + "G0 X%s Y%s" % tuple(RETURN_TO) # show the gCode result dialog if FreeCAD.GuiUp and SHOW_EDITOR: dia = PostUtils.GCodeEditorDialog() dia.editor.setText(gcode) result = dia.exec_() if result: final = dia.editor.toPlainText() else: final = gcode else: final = gcode print("Done postprocessing.") # write the file gfile = pythonopen(filename, "w") gfile.write(final) gfile.close()
def export(objectslist, filename, argstring): global OUTPUT_COMMENTS global OUTPUT_HEADER global SHOW_EDITOR global CurrentState global GetValue for arg in argstring.split(): if arg == '--comments': OUTPUT_COMMENTS = True if arg == '--inches': GetValue = getImperialValue if arg == '--no-header': OUTPUT_HEADER = False if arg == '--no-show-editor': SHOW_EDITOR = False for obj in objectslist: if not hasattr(obj, "Path"): s = "the object " + obj.Name s += " is not a path. Please select only path and Compounds." print(s) return CurrentState = { 'X': 0, 'Y': 0, 'Z': 0, 'F': 0, 'S': 0, 'JSXY': 0, 'JSZ': 0, 'MSXY': 0, 'MSZ': 0 } print("postprocessing...") gcode = "" # write header if OUTPUT_HEADER: gcode += linenumber() + "'Exported by FreeCAD\n" gcode += linenumber() + "'Post Processor: " + __name__ + "\n" gcode += linenumber() + "'Output Time:" + str(now) + "\n" # Write the preamble if OUTPUT_COMMENTS: gcode += linenumber() + "(begin preamble)\n" for line in PREAMBLE.splitlines(True): gcode += linenumber() + line for obj in objectslist: # do the pre_op if OUTPUT_COMMENTS: gcode += linenumber() + "(begin operation: " + obj.Label + ")\n" for line in PRE_OPERATION.splitlines(True): gcode += linenumber() + line gcode += parse(obj) # do the post_op if OUTPUT_COMMENTS: gcode += linenumber() + "(finish operation: " + obj.Label + ")\n" for line in POST_OPERATION.splitlines(True): gcode += linenumber() + line # do the post_amble if OUTPUT_COMMENTS: gcode += "(begin postamble)\n" for line in POSTAMBLE.splitlines(True): gcode += linenumber() + line if SHOW_EDITOR: dia = PostUtils.GCodeEditorDialog() dia.editor.setText(gcode) result = dia.exec_() if result: final = dia.editor.toPlainText() else: final = gcode else: final = gcode print("done postprocessing.") # Write the output gfile = pythonopen(filename, "wb") gfile.write(final) gfile.close()
def export(selection,filename): params = ['X','Y','Z','A','B','I','J','F','H','S','T','Q','R','L'] #Using XY plane most of the time so skipping K for obj in selection: if not hasattr(obj,"Path"): print "the object " + obj.Name + " is not a path. Please select only path and Compounds." return myMachine = None for pathobj in selection: if hasattr(pathobj,"Group"): #We have a compound or selection. for p in pathobj.Group: if p.Name == "Machine": myMachine = p if myMachine is None: print "No machine found in this selection" else: if myMachine.MachineUnits == "Metric": UNITS = "G21" else: UNITS = "G20" gcode ='' gcode+= HEADER gcode+= SAFETYBLOCK gcode+= UNITS+'\n' lastcommand = None gcode+= COMMENT+ selection[0].Description +'\n' gobjects = [] for g in selection[0].Group: if g.Name <>'Machine': #filtering out gcode home position from Machine object gobjects.append(g) for obj in gobjects: for c in obj.Path.Commands: outstring = [] command = c.Name if command[0]=='(': command = PostUtils.fcoms(command, COMMENT) outstring.append(command) if MODAL == True: if command == lastcommand: outstring.pop(0) if c.Parameters >= 1: for param in params: if param in c.Parameters: if param == 'F': outstring.append(param + PostUtils.fmt(c.Parameters['F'], FEED_DECIMALS,UNITS)) elif param == 'H': outstring.append(param + str(int(c.Parameters['H']))) elif param == 'S': outstring.append(param + PostUtils.fmt(c.Parameters['S'], SPINDLE_DECIMALS,'G21')) #rpm is unitless-therefore I had to 'fake it out' by using metric units which don't get converted from entered value elif param == 'T': outstring.append(param + str(int(c.Parameters['T']))) else: outstring.append(param + PostUtils.fmt(c.Parameters[param],AXIS_DECIMALS,UNITS)) outstr = str(outstring) outstr =outstr.replace('[','') outstr =outstr.replace(']','') outstr =outstr.replace("'",'') outstr =outstr.replace(",",'') gcode+= outstr + '\n' lastcommand = c.Name gcode+= TOOLRETURN gcode+= SAFETYBLOCK gcode+= FOOTER if SHOW_EDITOR: PostUtils.editor(gcode) gfile = pythonopen(filename,"wb") gfile.write(gcode) gfile.close()
def export(objectslist, filename, argstring): if not processArguments(argstring): return None global UNITS global UNIT_FORMAT global UNIT_SPEED_FORMAT for obj in objectslist: if not hasattr(obj, "Path"): print("the object " + obj.Name + " is not a path. Please select only path and Compounds.") return None print("postprocessing...") gcode = "" # write header if OUTPUT_HEADER: gcode += linenumber() + "(Exported by FreeCAD)\n" gcode += linenumber() + "(Post Processor: " + __name__ + ")\n" gcode += linenumber() + "(Output Time:" + str(now) + ")\n" # Write the preamble if OUTPUT_COMMENTS: gcode += linenumber() + "(begin preamble)\n" for line in PREAMBLE.splitlines(False): gcode += linenumber() + line + "\n" gcode += linenumber() + UNITS + "\n" for obj in objectslist: # do the pre_op if OUTPUT_COMMENTS: gcode += linenumber() + "(begin operation: %s)\n" % obj.Label for line in PRE_OPERATION.splitlines(True): gcode += linenumber() + line gcode += parse(obj) # do the post_op if OUTPUT_COMMENTS: gcode += linenumber() + "(finish operation: %s)\n" % obj.Label for line in POST_OPERATION.splitlines(True): gcode += linenumber() + line # do the post_amble if OUTPUT_COMMENTS: gcode += "(begin postamble)\n" for line in POSTAMBLE.splitlines(True): gcode += linenumber() + line if FreeCAD.GuiUp and SHOW_EDITOR: dia = PostUtils.GCodeEditorDialog() dia.editor.setText(gcode) result = dia.exec_() if result: final = dia.editor.toPlainText() else: final = gcode else: final = gcode print("done postprocessing.") if not filename == '-': gfile = pythonopen(filename, "wb") gfile.write(final) gfile.close() return final
def export(objectslist, filename, argstring): # pylint: disable=unused-argument if not processArguments(argstring): return None global UNITS global UNIT_FORMAT global UNIT_SPEED_FORMAT for obj in objectslist: if not hasattr(obj, "Path"): print("the object " + obj.Name + " is not a path. Please select only path and Compounds.") return print("postprocessing...") gcode = "" # Find the machine. # The user my have overridden post processor defaults in the GUI. Make sure we're using the current values in the Machine Def. myMachine = None for pathobj in objectslist: if hasattr(pathobj, "MachineName"): myMachine = pathobj.MachineName if hasattr(pathobj, "MachineUnits"): if pathobj.MachineUnits == "Metric": UNITS = "G21" else: UNITS = "G20" if myMachine is None: print("No machine found in this selection") # write header if OUTPUT_HEADER: gcode += linenumber() + "(Exported by FreeCAD)\n" gcode += linenumber() + "(Post Processor: " + __name__ + ")\n" gcode += linenumber() + "(Output Time:" + str(now) + ")\n" # Write the preamble if OUTPUT_COMMENTS: gcode += linenumber() + "(begin preamble)\n" for line in PREAMBLE.splitlines(True): gcode += linenumber() + line gcode += linenumber() + UNITS + "\n" for obj in objectslist: # do the pre_op if OUTPUT_COMMENTS: gcode += linenumber() + "(begin operation: " + obj.Label + ")\n" for line in PRE_OPERATION.splitlines(True): gcode += linenumber() + line gcode += parse(obj) # do the post_op if OUTPUT_COMMENTS: gcode += linenumber() + "(finish operation: " + obj.Label + ")\n" for line in POST_OPERATION.splitlines(True): gcode += linenumber() + line # do the post_amble if OUTPUT_COMMENTS: gcode += "(begin postamble)\n" for line in POSTAMBLE.splitlines(True): gcode += linenumber() + line print('show editor: {}'.format(SHOW_EDITOR)) if FreeCAD.GuiUp and SHOW_EDITOR: dia = PostUtils.GCodeEditorDialog() dia.editor.setText(gcode) result = dia.exec_() if result: final = dia.editor.toPlainText() else: final = gcode else: final = gcode print("done postprocessing.") gfile = pythonopen(filename, "w") gfile.write(final) gfile.close()
def export(objectslist, filename, argstring): if not processArguments(argstring): return None global UNITS global UNIT_FORMAT global UNIT_SPEED_FORMAT global MOTION_MODE print("Post Processor: " + __name__ + " postprocessing...") gcode = "" # write header if OUTPUT_HEADER: gcode += linenumber() + "(Exported by FreeCAD)\n" gcode += linenumber() + "(Post Processor: " + __name__ + ")\n" gcode += linenumber() + "(Output Time:" + str( datetime.datetime.now()) + ")\n" # Write the preamble if OUTPUT_COMMENTS: gcode += linenumber() + "(begin preamble)\n" for line in PREAMBLE.splitlines(True): gcode += linenumber() + line # verify if PREAMBLE have changed MOTION_MODE or UNITS if 'G90' in PREAMBLE: MOTION_MODE = 'G90' elif 'G91' in PREAMBLE: MOTION_MODE = 'G91' else: gcode += linenumber() + MOTION_MODE + "\n" if 'G21' in PREAMBLE: UNITS = 'G21' UNIT_FORMAT = 'mm' UNIT_SPEED_FORMAT = 'mm/min' elif 'G20' in PREAMBLE: UNITS = 'G20' UNIT_FORMAT = 'in' UNIT_SPEED_FORMAT = 'in/min' else: gcode += linenumber() + UNITS + "\n" for obj in objectslist: # Debug... # print("\n" + "*"*70) # dump(obj) # print("*"*70 + "\n") if not hasattr(obj, "Path"): print("The object " + obj.Name + " is not a path. Please select only path and Compounds.") return # do the pre_op if OUTPUT_COMMENTS: gcode += linenumber() + "(begin operation: " + obj.Label + ")\n" for line in PRE_OPERATION.splitlines(True): gcode += linenumber() + line # Parse the op gcode += parse(obj) # do the post_op if OUTPUT_COMMENTS: gcode += linenumber() + "(finish operation: " + obj.Label + ")\n" for line in POST_OPERATION.splitlines(True): gcode += linenumber() + line # do the post_amble if OUTPUT_COMMENTS: gcode += linenumber() + "(begin postamble)\n" for line in POSTAMBLE.splitlines(True): gcode += linenumber() + line # show the gCode result dialog if FreeCAD.GuiUp and SHOW_EDITOR: dia = PostUtils.GCodeEditorDialog() dia.editor.setText(gcode) result = dia.exec_() if result: final = dia.editor.toPlainText() else: final = gcode else: final = gcode print("done postprocessing.") # write the file gfile = pythonopen(filename, "w") gfile.write(final) gfile.close()
def export(objectslist, filename, argstring): global UNITS global linenr global ABSOLUTE_CIRCLE_CENTER global USE_RADIUS_IF_POSSIBLE global RADIUS_COMMENT linenr = STARTLINENR lastX = 0 lastY = 0 lastZ = 0 params = [ 'X', 'Y', 'Z', 'A', 'B', 'I', 'J', 'F', 'H', 'S', 'T', 'Q', 'R', 'L' ] # Using XY plane most of the time so skipping K modalParamsDict = dict() for mp in MODALPARAMS: modalParamsDict[mp] = None for obj in objectslist: if not hasattr(obj, "Path"): print("the object " + obj.Name + " is not a path. Please select only path and Compounds.") return myMachine = None for pathobj in objectslist: if hasattr(pathobj, "MachineName"): myMachine = pathobj.MachineName if hasattr(pathobj, "MachineUnits"): if pathobj.MachineUnits == "Metric": UNITS = "G21" else: UNITS = "G20" if myMachine is None: print("philips_post: No machine found in this selection") gcode = '' gcode += mkHeader(objectslist) gcode += linenumberify(GCODE_HEADER) if UNITS_INCLUDED: gcode += linenumberify(mapGCode(UNITS)) lastcommand = None for obj in objectslist: if hasattr(obj, 'Comment'): gcode += linenumberify('(' + obj.Comment + ')') for c in obj.Path.Commands: outstring = [] command = c.Name if command != 'G0': command = command.replace('G0', 'G') # normalize: G01 -> G1 if (command != UNITS or UNITS_INCLUDED): if command[0] == '(': command = PostUtils.fcoms(command, COMMENT) # the mapping is done for output only! For internal things we # still use the old value. mappedCommand = mapGCode(command) if not MODAL or command != lastcommand: outstring.append(mappedCommand) # if MODAL == True: # #\better: append iff MODAL == False # if command == lastcommand: # outstring.pop(0) if c.Parameters >= 1: for param in params: # test print("param: " + param + ", command: " + command) if param in c.Parameters: if (param in MODALPARAMS) and ( modalParamsDict[str(param)] == c.Parameters[str(param)]): # do nothing or append white space outstring.append(' ') elif param == 'F': feed = c.Parameters['F'] if SUPPRESS_ZERO_FEED and feed == 0: pass else: outstring.append(param + PostUtils.fmt( feed, FEED_DECIMALS, UNITS)) elif param == 'H': outstring.append(param + str(int(c.Parameters['H']))) elif param == 'S': # rpm is unitless-therefore I had to 'fake it # out' by using metric units which don't get # converted from entered value outstring.append( param + PostUtils.fmt(c.Parameters['S'], SPINDLE_DECIMALS, 'G21')) elif param == 'T': outstring.append(param + str(int(c.Parameters['T']))) elif param == 'I' and (command == 'G2' or command == 'G3'): #test print("param = 'I'") # this is the special case for circular paths, # where relative coordinates have to be changed # to absolute i = c.Parameters['I'] # calculate the radius r j = c.Parameters['J'] r = math.sqrt(i**2 + j**2) if USE_RADIUS_IF_POSSIBLE and angleUnder180( command, lastX, lastY, c.Parameters['X'], c.Parameters['Y'], i, j): outstring.append( 'R' + PostUtils.fmt(r, AXIS_DECIMALS, UNITS)) else: if RADIUS_COMMENT: outstring.append('(R' + PostUtils.fmt( r, AXIS_DECIMALS, UNITS) + ')') if ABSOLUTE_CIRCLE_CENTER: i += lastX outstring.append( param + PostUtils.fmt(i, AXIS_DECIMALS, UNITS)) elif param == 'J' and (command == 'G2' or command == 'G3'): # this is the special case for circular paths, # where incremental center has to be changed to # absolute center i = c.Parameters['I'] j = c.Parameters['J'] if USE_RADIUS_IF_POSSIBLE and angleUnder180( command, lastX, lastY, c.Parameters['X'], c.Parameters['Y'], i, j): # R is handled with the I parameter, here: # do nothing at all, keep the structure as # with I command pass else: if ABSOLUTE_CIRCLE_CENTER: j += lastY if SWAP_Y_Z: # we have to swap j and k as well outstring.append('K' + PostUtils.fmt( j, AXIS_DECIMALS, UNITS)) else: outstring.append(param + PostUtils.fmt( j, AXIS_DECIMALS, UNITS)) elif param == 'K' and (command == 'G2' or command == 'G3'): # this is the special case for circular paths, # where incremental center has to be changed to # absolute center outstring.append( '(' + param + PostUtils.fmt(c.Parameters[param], AXIS_DECIMALS, UNITS) + ')') z = c.Parameters['Z'] k = c.Parameters['K'] if USE_RADIUS_IF_POSSIBLE and angleUnder180( command, lastX, lastY, c.Parameters['X'], c.Parameters['Y'], i, j): # R is handled with the I parameter, here: # do nothing at all, keep the structure as # with I command pass else: if ABSOLUTE_CIRCLE_CENTER: k += lastZ if SWAP_Y_Z: # we have to swap j and k as well outstring.append( 'J' + PostUtils.fmt(j, AXIS_DECIMALS, UNITS)) else: outstring.append( param + PostUtils.fmt(j, AXIS_DECIMALS, UNITS)) elif param == 'Y' and SWAP_Y_Z: outstring.append('Z' + PostUtils.fmt( c.Parameters[param], AXIS_DECIMALS, UNITS)) elif param == 'Z' and SWAP_Y_Z: outstring.append('Y' + PostUtils.fmt( c.Parameters[param], AXIS_DECIMALS, UNITS)) else: # To Do: suppress unknown commands, if this is done here, all X parameters are suppressed # this is an unknown command, don't create GCode for it # print("parameter " + param + " for command " + command + " ignored") outstring.append(param + PostUtils.fmt( c.Parameters[param], AXIS_DECIMALS, UNITS)) if param in MODALPARAMS: modalParamsDict[str( param)] = c.Parameters[param] # save the last X, Y, Z values if 'X' in c.Parameters: lastX = c.Parameters['X'] if 'Y' in c.Parameters: lastY = c.Parameters['Y'] if 'Z' in c.Parameters: lastZ = c.Parameters['Z'] outstr = '' for w in outstring: outstr += w + COMMAND_SPACE outstr = outstr.replace(']', '') outstr = outstr.replace('[', '') outstr = outstr.replace("'", '') outstr = outstr.replace(",", '.') if LINENUMBERS: gcode += "N" + str(linenr) + " " linenr += LINENUMBER_INCREMENT gcode += outstr + '\n' lastcommand = c.Name gcode = gcode.replace("_", "-") gcode += linenumberify(GCODE_FOOTER) if SHOW_EDITOR: PostUtils.editor(gcode) gfile = pythonopen(filename, "wb") gfile.write(gcode) gfile.close()
def parse(pathobj): global AXIS_PRECISION global FEED_PRECISION out = "" lastcommand = None axis_precision_string = '.' + str(AXIS_PRECISION) +'f' feed_precision_string = '.' + str(FEED_PRECISION) +'f' # params = ['X','Y','Z','A','B','I','J','K','F','S'] #This list control # the order of parameters # centroid doesn't want K properties on XY plane Arcs need work. params = ['X', 'Y', 'Z', 'A', 'B', 'I', 'J', 'F', 'S', 'T', 'Q', 'R', 'L', 'H'] if hasattr(pathobj, "Group"): # We have a compound or project. # if OUTPUT_COMMENTS: # 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"): return out # if OUTPUT_COMMENTS: # out += linenumber() + "(" + pathobj.Label + ")\n" for c in pathobj.Path.Commands: commandlist = [] #list of elements in the command, code and params. command = c.Name #command M or G code or comment string if command[0]=='(': command = PostUtils.fcoms(command, COMMENT) commandlist.append(command) # if modal: only print the command if it is not the same as the # last one if MODAL is True: if command == lastcommand: commandlist.pop(0) # Now add the remaining parameters in order for param in params: if param in c.Parameters: if param == 'F': if c.Name not in ["G0", "G00"]: #centroid doesn't use rapid speeds speed = Units.Quantity(c.Parameters['F'], FreeCAD.Units.Velocity) commandlist.append( param + format(float(speed.getValueAs(UNIT_FORMAT)), feed_precision_string) ) elif param == 'H': commandlist.append(param + str(int(c.Parameters['H']))) elif param == 'S': commandlist.append(param + PostUtils.fmt(c.Parameters['S'], SPINDLE_DECIMALS, "G21")) elif param == 'T': commandlist.append(param + str(int(c.Parameters['T']))) else: commandlist.append( param + format(c.Parameters[param], axis_precision_string)) outstr = str(commandlist) outstr =outstr.replace('[','') outstr =outstr.replace(']','') outstr =outstr.replace("'",'') outstr =outstr.replace(",",'') #out += outstr + '\n' # store the latest command lastcommand = command # Check for Tool Change: if command == 'M6': # if OUTPUT_COMMENTS: # out += linenumber() + "(begin toolchange)\n" for line in TOOL_CHANGE.splitlines(True): out += linenumber() + line # if command == "message": # if OUTPUT_COMMENTS is False: # out = [] # else: # commandlist.pop(0) # remove the command # prepend a line number and append a newline if len(commandlist) >= 1: if OUTPUT_LINE_NUMBERS: commandlist.insert(0, (linenumber())) # append the line to the final output for w in commandlist: out += w + COMMAND_SPACE out = out.strip() + "\n" return out
def export(objectslist, filename, argstring): # pylint: disable=global-statement processArguments(argstring) for i in objectslist: print(i.Name) global UNITS global UNIT_FORMAT print("postprocessing...") gcode = "" # write header if OUTPUT_HEADER: gcode += HEADER gcode += SAFETYBLOCK # Write the preamble if OUTPUT_COMMENTS: for item in objectslist: if isinstance(item.Proxy, PathScripts.PathToolController.ToolController): gcode += ";T{}={}\n".format(item.ToolNumber, item.Name) gcode += linenumber() + ";begin preamble\n" for line in PREAMBLE.splitlines(True): gcode += linenumber() + line gcode += linenumber() + UNITS + "\n" for obj in objectslist: # do the pre_op if OUTPUT_COMMENTS: gcode += linenumber() + ";begin operation\n" for line in PRE_OPERATION.splitlines(True): gcode += linenumber() + line gcode += parse(obj) # do the post_op if OUTPUT_COMMENTS: gcode += linenumber() + ";end operation: %s\n" % obj.Label for line in POST_OPERATION.splitlines(True): gcode += linenumber() + line # do the post_amble if OUTPUT_COMMENTS: gcode += ";begin postamble\n" for line in TOOLRETURN.splitlines(True): gcode += linenumber() + line for line in SAFETYBLOCK.splitlines(True): gcode += linenumber() + line for line in POSTAMBLE.splitlines(True): gcode += linenumber() + line if SHOW_EDITOR: dia = PostUtils.GCodeEditorDialog() dia.editor.setText(gcode) result = dia.exec_() if result: final = dia.editor.toPlainText() else: final = gcode else: final = gcode print("done postprocessing.") if not filename == '-': gfile = pythonopen(filename, "w") gfile.write(final) gfile.close() return final
def export(objectslist, filename, argstring): processArguments(argstring) global UNITS global IP_ADDR for obj in objectslist: if not hasattr(obj, "Path"): FreeCAD.Console.PrintError("the object " + obj.Name + " is not a path. Please select only path and Compounds.\n") return FreeCAD.Console.PrintMessage("postprocessing...\n") gcode = "" # Find the machine. # The user my have overridden post processor defaults in the GUI. Make # sure we're using the current values in the Machine Def. myMachine = None for pathobj in objectslist: if hasattr(pathobj,"MachineName"): myMachine = pathobj.MachineName if hasattr(pathobj, "MachineUnits"): if pathobj.MachineUnits == "Metric": UNITS = "G21" else: UNITS = "G20" if myMachine is None: FreeCAD.Console.PrintWarning("No machine found in this selection\n") # write header if OUTPUT_HEADER: gcode += linenumber() + "(Exported by FreeCAD)\n" gcode += linenumber() + "(Post Processor: " + __name__ + ")\n" gcode += linenumber() + "(Output Time:" + str(now) + ")\n" # Write the preamble if OUTPUT_COMMENTS: gcode += linenumber() + "(begin preamble)\n" for line in PREAMBLE.splitlines(True): gcode += linenumber() + line gcode += linenumber() + UNITS + "\n" for obj in objectslist: # do the pre_op if OUTPUT_COMMENTS: gcode += linenumber() + "(begin operation: " + obj.Label + ")\n" for line in PRE_OPERATION.splitlines(True): gcode += linenumber() + line gcode += parse(obj) # do the post_op if OUTPUT_COMMENTS: gcode += linenumber() + "(finish operation: " + obj.Label + ")\n" for line in POST_OPERATION.splitlines(True): gcode += linenumber() + line # do the post_amble if OUTPUT_COMMENTS: gcode += "(begin postamble)\n" for line in POSTAMBLE.splitlines(True): gcode += linenumber() + line if SHOW_EDITOR: dia = PostUtils.GCodeEditorDialog() dia.editor.setText(gcode) result = dia.exec_() if result: final = dia.editor.toPlainText() else: final = gcode else: final = gcode if IP_ADDR is not None: sendToSmoothie(IP_ADDR, final, filename) else: if not filename == '-': gfile = pythonopen(filename, "wb") gfile.write(final) gfile.close() FreeCAD.Console.PrintMessage("done postprocessing.\n") return final
def parse(pathobj): out = "" lastcommand = None axis_precision_string = '.' + str(AXIS_PRECISION) + 'f' feed_precision_string = '.' + str(FEED_PRECISION) + 'f' # params = ['X','Y','Z','A','B','I','J','K','F','S'] #This list control # the order of parameters # centroid doesn't want K properties on XY plane Arcs need work. params = [ 'X', 'Y', 'Z', 'A', 'B', 'I', 'J', 'F', 'S', 'T', 'Q', 'R', 'L', 'H' ] if hasattr(pathobj, "Group"): # We have a compound or project. # if OUTPUT_COMMENTS: # 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"): return out # if OUTPUT_COMMENTS: # out += linenumber() + "(" + pathobj.Label + ")\n" for c in pathobj.Path.Commands: commandlist = [ ] # list of elements in the command, code and params. command = c.Name # command M or G code or comment string if command[0] == '(': command = PostUtils.fcoms(command, COMMENT) commandlist.append(command) # if modal: only print the command if it is not the same as the # last one if MODAL is True: if command == lastcommand: commandlist.pop(0) # Now add the remaining parameters in order for param in params: if param in c.Parameters: if param == 'F': if c.Name not in [ "G0", "G00" ]: # centroid doesn't use rapid speeds speed = Units.Quantity(c.Parameters['F'], FreeCAD.Units.Velocity) commandlist.append( param + format(float(speed.getValueAs(UNIT_FORMAT)), feed_precision_string)) elif param == 'H': commandlist.append(param + str(int(c.Parameters['H']))) elif param == 'S': commandlist.append(param + PostUtils.fmt( c.Parameters['S'], SPINDLE_DECIMALS, "G21")) elif param == 'T': commandlist.append(param + str(int(c.Parameters['T']))) else: commandlist.append( param + format(c.Parameters[param], axis_precision_string)) outstr = str(commandlist) outstr = outstr.replace('[', '') outstr = outstr.replace(']', '') outstr = outstr.replace("'", '') outstr = outstr.replace(",", '') # store the latest command lastcommand = command # Check for Tool Change: if command == 'M6': # if OUTPUT_COMMENTS: # out += linenumber() + "(begin toolchange)\n" for line in TOOL_CHANGE.splitlines(True): out += linenumber() + line # if command == "message": # if OUTPUT_COMMENTS is False: # out = [] # else: # commandlist.pop(0) # remove the command # prepend a line number and append a newline if len(commandlist) >= 1: if OUTPUT_LINE_NUMBERS: commandlist.insert(0, (linenumber())) # append the line to the final output for w in commandlist: out += w + COMMAND_SPACE out = out.strip() + "\n" return out
def export(objectslist, filename, args): global UNITS for obj in objectslist: if not hasattr(obj, "Path"): print "the object " + obj.Name + " is not a path. Please select only path and Compounds." return print "postprocessing..." gcode = "" #Find the machine. #The user my have overridden post processor defaults in the GUI. Make sure we're using the current values in the Machine Def. myMachine = None for pathobj in objectslist: if hasattr(pathobj, "Group"): #We have a compound or project. for p in pathobj.Group: if p.Name == "Machine": myMachine = p if myMachine is None: print "No machine found in this project" else: if myMachine.MachineUnits == "Metric": UNITS = "G21" else: UNITS = "G20" # write header if OUTPUT_HEADER: gcode += linenumber() + "(Exported by FreeCAD)\n" gcode += linenumber() + "(Post Processor: " + __name__ + ")\n" gcode += linenumber() + "(Output Time:" + str(now) + ")\n" #Write the preamble if OUTPUT_COMMENTS: gcode += linenumber() + "(begin preamble)\n" for line in PREAMBLE.splitlines(True): gcode += linenumber() + line gcode += linenumber() + UNITS + "\n" for obj in objectslist: #do the pre_op if OUTPUT_COMMENTS: gcode += linenumber() + "(begin operation: " + obj.Label + ")\n" for line in PRE_OPERATION.splitlines(True): gcode += linenumber() + line gcode += parse(obj) #do the post_op if OUTPUT_COMMENTS: gcode += linenumber() + "(finish operation: " + obj.Label + ")\n" for line in POST_OPERATION.splitlines(True): gcode += linenumber() + line #do the post_amble if OUTPUT_COMMENTS: gcode += "(begin postamble)\n" for line in POSTAMBLE.splitlines(True): gcode += linenumber() + line if SHOW_EDITOR: dia = PostUtils.GCodeEditorDialog() dia.editor.setText(gcode) result = dia.exec_() if result: final = dia.editor.toPlainText() else: final = gcode else: final = gcode print "done postprocessing." gfile = pythonopen(filename, "wb") gfile.write(gcode) gfile.close()
def export(objectslist, filename, argstring): if not processArguments(argstring): return None global UNITS global UNIT_FORMAT global UNIT_SPEED_FORMAT for obj in objectslist: if not hasattr(obj, "Path"): print("the object " + obj.Name + " is not a path. Please select only path and Compounds.") return None print("postprocessing...") gcode = linenumber() + 'IMF_PBL_V1.0\n' # write header now = datetime.datetime.now() gcode += linenumber() + ";- Exported by FreeCAD\n" gcode += linenumber() + ";- Post Processor: " + __name__ + '\n' gcode += linenumber() + ";- Output Time:" + str(now) + '\n' # Write the preamble if OUTPUT_COMMENTS: gcode += linenumber() + ";- begin preamble\n" for line in PREAMBLE.splitlines(False): gcode += linenumber() + line + '\n' if OUTPUT_COMMENTS: gcode += linenumber() + ";- finish preamble\n" for obj in objectslist: # fetch machine details job = PathUtils.findParentJob(obj) myMachine = job.Machine if hasattr(job, 'Machine') else MACHINE_NAME # FIXME: we only operate using ISEL units (µm and µm/s) if hasattr(job, "MachineUnits"): print("Unknown parameter 'MachineUnits: " "{}".format(job.MachineUnits)) # do the pre_op if OUTPUT_COMMENTS: gcode += linenumber() + ";- begin operation: %s\n" % obj.Label gcode += linenumber() + ";- machine: %s\n" % myMachine gcode += linenumber() + ";- unit system: %s\n" % UNIT_SPEED_FORMAT for line in PRE_OPERATION.splitlines(True): gcode += linenumber() + line gcode += parse(obj) # do the post_op if OUTPUT_COMMENTS: gcode += linenumber() + ";- finish operation: %s\n" % obj.Label for line in POST_OPERATION.splitlines(True): gcode += linenumber() + line # do the post_amble if OUTPUT_COMMENTS: gcode += linenumber() + ";- begin postamble\n" for line in POSTAMBLE.splitlines(False): gcode += linenumber() + line + '\n' if OUTPUT_COMMENTS: gcode += linenumber() + ";- finish postamble\n" if FreeCAD.GuiUp and SHOW_EDITOR: dia = PostUtils.GCodeEditorDialog() dia.editor.setText(gcode) result = dia.exec_() if result: final = dia.editor.toPlainText() else: final = gcode else: final = gcode print("done postprocessing.") if not filename == '-': # Clear read-only flag set by Isel Remote try: chmod(filename, S_IWRITE | S_IREAD) except: pass # file did not exist ? with pythonopen(filename, "w") as f: f.write(final) return final