| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| |
|
| | """ |
| | This is an example preprocessor file for the Path workbench. Its aim is to |
| | open a gcode file, parse its contents, and create the appropriate objects |
| | in FreeCAD. |
| | |
| | This preprocessor will split gcode on tool changes and create one or more |
| | PathCustom objects in the job. Tool Change commands themselves are not |
| | preserved. It is up to the user to create and assign appropriate tool |
| | controllers. |
| | |
| | Only gcodes that are supported by Path are imported. Thus things like G43 |
| | are suppressed. |
| | |
| | Importing gcode is inherently dangerous because context cannot be safely |
| | assumed. The user should carefully examine the resulting gcode! |
| | |
| | Read the Path Workbench documentation to know how to create Path objects |
| | from GCode. |
| | """ |
| |
|
| | import FreeCAD |
| | import Path |
| | import PathScripts.PathUtils as PathUtils |
| | import os |
| | import re |
| | from PySide.QtCore import QT_TRANSLATE_NOOP |
| | from builtins import open as pyopen |
| |
|
| | if FreeCAD.GuiUp: |
| | import Path.Op.Gui.Custom as PathCustomGui |
| |
|
| | PathCustom = PathCustomGui.PathCustom |
| | else: |
| | import Path.Op.Custom as PathCustom |
| |
|
| | translate = FreeCAD.Qt.translate |
| |
|
| |
|
| | if False: |
| | Path.Log.setLevel(Path.Log.Level.DEBUG, Path.Log.thisModule()) |
| | Path.Log.trackModule(Path.Log.thisModule()) |
| | else: |
| | Path.Log.setLevel(Path.Log.Level.INFO, Path.Log.thisModule()) |
| |
|
| |
|
| | class PathNoActiveDocumentException(Exception): |
| | """PathNoActiveDocumentException is raised when no active document is found.""" |
| |
|
| | def __init__(self): |
| | super().__init__("No active document") |
| |
|
| |
|
| | class PathNoJobException(Exception): |
| | """PathNoJobException is raised when no target Job object is available.""" |
| |
|
| | def __init__(self): |
| | super().__init__("No job object") |
| |
|
| |
|
| | def open(filename): |
| | """called when freecad opens a file.""" |
| | Path.Log.track(filename) |
| | docname = os.path.splitext(os.path.basename(filename))[0] |
| | doc = FreeCAD.newDocument(docname) |
| | insert(filename, doc.Name) |
| |
|
| |
|
| | def matchToolController(op, toolnumber): |
| | """Try to match a tool controller in the job by number""" |
| | toolcontrollers = PathUtils.getToolControllers(op) |
| | for tc in toolcontrollers: |
| | if tc.ToolNumber == toolnumber: |
| | return tc |
| | return toolcontrollers[0] |
| |
|
| |
|
| | def _isImportEnvironmentReady(): |
| | """_isImportEnvironmentReady(docname)... |
| | Helper function to verify an active document exists, and that a Job object is available |
| | as a receiver for the Custom operation(s) that will be created as a result of the import process. |
| | """ |
| |
|
| | |
| | if FreeCAD.ActiveDocument is None: |
| | raise PathNoActiveDocumentException() |
| |
|
| | |
| | if not PathUtils.GetJobs(): |
| | raise PathNoJobException() |
| |
|
| | return True |
| |
|
| |
|
| | def parse(inputstring): |
| | "parse(inputstring): returns a parsed output string" |
| |
|
| | supported = [ |
| | "G0", |
| | "G00", |
| | "G1", |
| | "G01", |
| | "G2", |
| | "G02", |
| | "G3", |
| | "G03", |
| | "G81", |
| | "G82", |
| | "G83", |
| | "G90", |
| | "G91", |
| | ] |
| |
|
| | axis = ["X", "Y", "Z", "A", "B", "C", "U", "V", "W"] |
| |
|
| | FreeCAD.Console.PrintMessage("preprocessing...\n") |
| | Path.Log.track(inputstring) |
| | |
| | lines = inputstring.splitlines() |
| | output = [] |
| | lastcommand = None |
| |
|
| | for lin in lines: |
| | |
| | lin = lin.strip() |
| |
|
| | |
| | if not lin: |
| | continue |
| |
|
| | |
| | if lin[0].upper() in ["N"]: |
| | lin = lin.split(" ", 1) |
| | if len(lin) >= 1: |
| | lin = lin[1].strip() |
| | else: |
| | continue |
| |
|
| | |
| | if lin[0] not in ["G", "M", "X", "Y", "Z", "A", "B", "C", "U", "V", "W"]: |
| | continue |
| |
|
| | |
| | currcommand = lin.split()[0] |
| |
|
| | if currcommand in supported: |
| | output.append(lin) |
| | lastcommand = currcommand |
| |
|
| | |
| | elif currcommand[0] in axis and lastcommand: |
| | output.append(lastcommand + " " + lin) |
| |
|
| | FreeCAD.Console.PrintMessage("done preprocessing.\n") |
| | return output |
| |
|
| |
|
| | def _identifygcodeByToolNumberList(filename): |
| | """called when freecad imports a file""" |
| | Path.Log.track(filename) |
| | gcodeByToolNumberList = [] |
| |
|
| | gfile = pyopen(filename) |
| | gcode = gfile.read() |
| | gfile.close() |
| |
|
| | |
| | p = re.compile(r"[mM]+?\s?0?6\s?T\d*\s") |
| |
|
| | |
| | paths = re.split(r"([mM]+?\s?0?6\s?T\d*\s)", gcode) |
| |
|
| | |
| | toolnumber = 0 |
| |
|
| | for path in paths: |
| |
|
| | |
| | m = p.match(path) |
| | if m: |
| | toolnumber = int(m.group().split("T")[-1]) |
| | continue |
| |
|
| | |
| | gcode = parse(path) |
| | if len(gcode) > 0: |
| | gcodeByToolNumberList.append((gcode, toolnumber)) |
| |
|
| | return gcodeByToolNumberList |
| |
|
| |
|
| | def insert(filename, docname=None): |
| | """called when freecad imports a file""" |
| | Path.Log.track(filename) |
| |
|
| | try: |
| | if not _isImportEnvironmentReady(): |
| | return |
| | except PathNoActiveDocumentException: |
| | Path.Log.error(translate("CAM_Gcode_pre", "No active document")) |
| | return |
| | except PathNoJobException: |
| | Path.Log.error(translate("CAM_Gcode_pre", "No job object")) |
| | return |
| |
|
| | |
| | for gcode, toolNumber in _identifygcodeByToolNumberList(filename): |
| | obj = PathCustom.Create("Custom") |
| |
|
| | |
| | obj.Gcode = gcode |
| | obj.ToolController = matchToolController(obj, toolNumber) |
| | if docname: |
| | obj.Label = obj.Label + "_" + docname |
| |
|
| | if FreeCAD.GuiUp: |
| | |
| | obj.ViewObject.Proxy = PathCustomGui.PathOpGui.ViewProvider( |
| | obj.ViewObject, PathCustomGui.Command.res |
| | ) |
| | obj.ViewObject.Proxy.setDeleteObjectsOnReject(False) |
| |
|
| | FreeCAD.ActiveDocument.recompute() |
| |
|
| |
|
| | print(__name__ + " gcode preprocessor loaded.") |
| |
|