Skip to content

Commit

Permalink
Basic unit test for linuxcnc output.
Browse files Browse the repository at this point in the history
  • Loading branch information
mlampert committed Nov 18, 2016
1 parent dce1625 commit 2aa2560
Show file tree
Hide file tree
Showing 7 changed files with 175 additions and 36 deletions.
6 changes: 4 additions & 2 deletions src/Mod/Path/PathScripts/PathContour.py
Expand Up @@ -28,10 +28,11 @@
import TechDraw
from PathScripts import PathUtils
from PathScripts.PathUtils import depth_params
from PySide import QtCore

if FreeCAD.GuiUp:
import FreeCADGui
from PySide import QtCore, QtGui
from PySide import QtGui
# Qt tanslation handling
try:
_encoding = QtGui.QApplication.UnicodeUTF8
Expand Down Expand Up @@ -258,7 +259,8 @@ def execute(self, obj):
if obj.Active:
path = Path.Path(output)
obj.Path = path
obj.ViewObject.Visibility = True
if obj.ViewObject:
obj.ViewObject.Visibility = True

else:
path = Path.Path("(inactive operation)")
Expand Down
5 changes: 3 additions & 2 deletions src/Mod/Path/PathScripts/PathLoadTool.py
Expand Up @@ -181,13 +181,14 @@ def Activated(self):
FreeCAD.ActiveDocument.recompute()

@staticmethod
def Create(jobname = None):
def Create(jobname = None, assignViewProvider = True):
import PathScripts
import PathUtils

obj = FreeCAD.ActiveDocument.addObject("Path::FeaturePython", "TC")
PathScripts.PathLoadTool.LoadTool(obj)
PathScripts.PathLoadTool._ViewProviderLoadTool(obj.ViewObject)
if assignViewProvider:
PathScripts.PathLoadTool._ViewProviderLoadTool(obj.ViewObject)

PathUtils.addToJob(obj, jobname)

Expand Down
55 changes: 32 additions & 23 deletions src/Mod/Path/PathScripts/PathPost.py
Expand Up @@ -79,7 +79,7 @@ def exec_(self):
class CommandPathPost:

def resolveFileName(self, job):
print("resolveFileName(%s)" % job.Label)
#print("resolveFileName(%s)" % job.Label)
path = PathPreferences.defaultOutputFile()
if job.OutputFile:
path = job.OutputFile
Expand Down Expand Up @@ -134,7 +134,7 @@ def resolveFileName(self, job):
else:
filename = None

print("resolveFileName(%s, %s) -> '%s'" % (path, policy, filename))
#print("resolveFileName(%s, %s) -> '%s'" % (path, policy, filename))
return filename

def resolvePostProcessor(self, job):
Expand Down Expand Up @@ -179,35 +179,44 @@ def Activated(self):
job = PathUtils.findParentJob(obj)
if job:
jobs.add(job)

fail = True
rc = ''
if len(jobs) != 1:
FreeCAD.Console.PrintError("Please select a single job or other path object\n")
FreeCAD.ActiveDocument.abortTransaction()
else:
job = jobs.pop()
print("Job for selected objects = %s" % job.Name)
(fail, rc) = exportObjectsWith(selected, job)

# check if the user has a project and has set the default post and
# output filename
postArgs = PathPreferences.defaultPostProcessorArgs()
if hasattr(job, "PostProcessorArgs") and job.PostProcessorArgs:
postArgs = job.PostProcessorArgs
elif hasattr(job, "PostProcessor") and job.PostProcessor:
postArgs = ''

postname = self.resolvePostProcessor(job)
if postname:
filename = self.resolveFileName(job)

if postname and filename:
print("post: %s(%s, %s)" % (postname, filename, postArgs))
processor = PostProcessor.load(postname)
processor.export(selected, filename, postArgs)

FreeCAD.ActiveDocument.commitTransaction()
else:
FreeCAD.ActiveDocument.abortTransaction()
if fail:
FreeCAD.ActiveDocument.abortTransaction()
else:
FreeCAD.ActiveDocument.commitTransaction()
FreeCAD.ActiveDocument.recompute()

def exportObjectsWith(self, objs, job, needFilename = True):
# check if the user has a project and has set the default post and
# output filename
postArgs = PathPreferences.defaultPostProcessorArgs()
if hasattr(job, "PostProcessorArgs") and job.PostProcessorArgs:
postArgs = job.PostProcessorArgs
elif hasattr(job, "PostProcessor") and job.PostProcessor:
postArgs = ''

postname = self.resolvePostProcessor(job)
filename = '-'
if postname and needFilename:
filename = self.resolveFileName(job)

if postname and filename:
print("post: %s(%s, %s)" % (postname, filename, postArgs))
processor = PostProcessor.load(postname)
gcode = processor.export(objs, filename, postArgs)
return (False, gcode)
else:
return (True, '')

if FreeCAD.GuiUp:
# register the FreeCAD command
FreeCADGui.addCommand('Path_Post', CommandPathPost())
Expand Down
2 changes: 1 addition & 1 deletion src/Mod/Path/PathScripts/PathPostProcessor.py
Expand Up @@ -78,4 +78,4 @@ def __init__(self, script):
self.script = script

def export(self, obj, filename, args):
self.script.export(obj, filename, args)
return self.script.export(obj, filename, args)
15 changes: 12 additions & 3 deletions src/Mod/Path/PathScripts/linuxcnc_post.py
Expand Up @@ -38,6 +38,7 @@
--header,--no-header ... output headers (--header)
--comments,--no-comments ... output comments (--comments)
--line-numbers,--no-line-numbers ... prefix with line numbers (--no-lin-numbers)
--show-editor, --no-show-editor ... pop up editor before writing output(--show-editor)
'''

import datetime
Expand Down Expand Up @@ -90,6 +91,7 @@ def processArguments(argstring):
global OUTPUT_HEADER
global OUTPUT_COMMENTS
global OUTPUT_LINE_NUMBERS
global SHOW_EDITOR
for arg in argstring.split():
if arg == '--header':
OUTPUT_HEADER = True
Expand All @@ -103,6 +105,10 @@ def processArguments(argstring):
OUTPUT_LINE_NUMBERS = True
elif arg == '--no-line-numbers':
OUTPUT_LINE_NUMBERS = False
elif arg == '--show-editor':
SHOW_EDITOR = True
elif arg == '--no-show-editor':
SHOW_EDITOR = False

def export(objectslist, filename, argstring):
processArguments(argstring)
Expand Down Expand Up @@ -179,9 +185,12 @@ def export(objectslist, filename, argstring):

print "done postprocessing."

gfile = pythonopen(filename, "wb")
gfile.write(gcode)
gfile.close()
if not filename == '-':
gfile = pythonopen(filename, "wb")
gfile.write(final)
gfile.close()

return final


def linenumber():
Expand Down
66 changes: 61 additions & 5 deletions src/Mod/Path/PathTests/TestPathPost.py
Expand Up @@ -23,19 +23,75 @@
# ***************************************************************************

import FreeCAD
import Path
import PathScripts
import PathScripts.PathContour
import PathScripts.PathJob
import PathScripts.PathLoadTool
import PathScripts.PathPost
import PathScripts.PathUtils
import difflib
import unittest

from PathScripts import PathPost

class PathPostTestCases(unittest.TestCase):
def setUp(self):
self.doc = FreeCAD.newDocument("PathPostTest")

def tearDown(self):
FreeCAD.closeDocument("PathPostTest")

def testCommand(self):
self.box = self.doc.addObject("Part::Box", "Box")
print("Running command test")
def testLinuxCNC(self):
# first create something to generate a path for
box = self.doc.addObject("Part::Box", "Box")

# Create job and setup tool library + default tool
job = self.doc.addObject("Path::FeatureCompoundPython", "Job")
PathScripts.PathJob.ObjectPathJob(job)
job.Base = self.doc.Box
PathScripts.PathLoadTool.CommandPathLoadTool.Create(job.Name, False)
toolLib = job.Group[0]
tool1 = Path.Tool()
tool1.Diameter = 5.0
tool1.Name = "Default Tool"
tool1.CuttingEdgeHeight = 15.0
tool1.ToolType = "EndMill"
tool1.Material = "HighSpeedSteel"
job.Tooltable.addTools(tool1)
toolLib.ToolNumber = 1
self.failUnless(True)

self.doc.getObject("TC").ToolNumber = 2
self.doc.recompute()

contour = self.doc.addObject("Path::FeaturePython", "Contour")
PathScripts.PathContour.ObjectContour(contour)
contour.Active = True
contour.ClearanceHeight = 20.0
contour.StepDown = 1.0
contour.StartDepth= 10.0
contour.FinalDepth=0.0
contour.SafeHeight = 12.0
contour.OffsetExtra = 0.0
contour.Direction = 'CW'
contour.UseComp = True
contour.PlungeAngle = 90.0
PathScripts.PathUtils.addToJob(contour)
PathScripts.PathContour.ObjectContour.setDepths(contour.Proxy, contour)
self.doc.recompute()

job.PostProcessor = 'linuxcnc'
job.PostProcessorArgs = '--no-header --no-line-numbers --no-comments --no-show-editor'

post = PathScripts.PathPost.CommandPathPost()
(fail, gcode) = post.exportObjectsWith([job], job, False)
self.assertFalse(fail)

referenceFile = FreeCAD.getHomePath() + 'Mod/Path/PathTests/test_linuxcnc_00.ngc'
with open(referenceFile, 'r') as fp:
refGCode = fp.read()

if gcode != refGCode:
msg = ''.join(difflib.ndiff(gcode.splitlines(True), refGCode.splitlines(True)))
self.fail("linuxcnc output doesn't match: " + msg)


62 changes: 62 additions & 0 deletions src/Mod/Path/PathTests/test_linuxcnc_00.ngc
@@ -0,0 +1,62 @@
G17 G90
G21
(Contour :TC)
(Uncompensated Tool Path)
G0 Z15.0000
G00 X-0.2500 Y0.0000
G00 Z23.0000
G01 X-0.2500 Y0.0000 Z9.0000 F0.00
G01 X-0.2500 Y10.0000 Z9.0000 F0.00
G02 X0.2500 Y10.0000 Z9.0000 I0.2500 J0.0000 F0.00
G01 X0.2500 Y0.0000 Z9.0000 F0.00
G02 X-0.2500 Y0.0000 Z9.0000 I-0.2500 J0.0000 F0.00
G01 X-0.2500 Y0.0000 Z8.0000 F0.00
G01 X-0.2500 Y10.0000 Z8.0000 F0.00
G02 X0.2500 Y10.0000 Z8.0000 I0.2500 J0.0000 F0.00
G01 X0.2500 Y0.0000 Z8.0000 F0.00
G02 X-0.2500 Y0.0000 Z8.0000 I-0.2500 J0.0000 F0.00
G01 X-0.2500 Y0.0000 Z7.0000 F0.00
G01 X-0.2500 Y10.0000 Z7.0000 F0.00
G02 X0.2500 Y10.0000 Z7.0000 I0.2500 J0.0000 F0.00
G01 X0.2500 Y0.0000 Z7.0000 F0.00
G02 X-0.2500 Y0.0000 Z7.0000 I-0.2500 J0.0000 F0.00
G01 X-0.2500 Y0.0000 Z6.0000 F0.00
G01 X-0.2500 Y10.0000 Z6.0000 F0.00
G02 X0.2500 Y10.0000 Z6.0000 I0.2500 J0.0000 F0.00
G01 X0.2500 Y0.0000 Z6.0000 F0.00
G02 X-0.2500 Y0.0000 Z6.0000 I-0.2500 J0.0000 F0.00
G01 X-0.2500 Y0.0000 Z5.0000 F0.00
G01 X-0.2500 Y10.0000 Z5.0000 F0.00
G02 X0.2500 Y10.0000 Z5.0000 I0.2500 J0.0000 F0.00
G01 X0.2500 Y0.0000 Z5.0000 F0.00
G02 X-0.2500 Y0.0000 Z5.0000 I-0.2500 J0.0000 F0.00
G01 X-0.2500 Y0.0000 Z4.0000 F0.00
G01 X-0.2500 Y10.0000 Z4.0000 F0.00
G02 X0.2500 Y10.0000 Z4.0000 I0.2500 J0.0000 F0.00
G01 X0.2500 Y0.0000 Z4.0000 F0.00
G02 X-0.2500 Y0.0000 Z4.0000 I-0.2500 J0.0000 F0.00
G01 X-0.2500 Y0.0000 Z3.0000 F0.00
G01 X-0.2500 Y10.0000 Z3.0000 F0.00
G02 X0.2500 Y10.0000 Z3.0000 I0.2500 J0.0000 F0.00
G01 X0.2500 Y0.0000 Z3.0000 F0.00
G02 X-0.2500 Y0.0000 Z3.0000 I-0.2500 J0.0000 F0.00
G01 X-0.2500 Y0.0000 Z2.0000 F0.00
G01 X-0.2500 Y10.0000 Z2.0000 F0.00
G02 X0.2500 Y10.0000 Z2.0000 I0.2500 J0.0000 F0.00
G01 X0.2500 Y0.0000 Z2.0000 F0.00
G02 X-0.2500 Y0.0000 Z2.0000 I-0.2500 J0.0000 F0.00
G01 X-0.2500 Y0.0000 Z1.0000 F0.00
G01 X-0.2500 Y10.0000 Z1.0000 F0.00
G02 X0.2500 Y10.0000 Z1.0000 I0.2500 J0.0000 F0.00
G01 X0.2500 Y0.0000 Z1.0000 F0.00
G02 X-0.2500 Y0.0000 Z1.0000 I-0.2500 J0.0000 F0.00
G01 X-0.2500 Y0.0000 Z0.0000 F0.00
G01 X-0.2500 Y10.0000 Z0.0000 F0.00
G02 X0.2500 Y10.0000 Z0.0000 I0.2500 J0.0000 F0.00
G01 X0.2500 Y0.0000 Z0.0000 F0.00
G02 X-0.2500 Y0.0000 Z0.0000 I-0.2500 J0.0000 F0.00
G00 Z15.0000
M05
G00 X-1.0 Y1.0
G17 G90
M2

0 comments on commit 2aa2560

Please sign in to comment.