Merge pull request #13254 from jamwaffles/drill-g85-feed-retract
CAM/Drilling: Add feed retract option to drilling op settings for reaming/boring heads
This commit is contained in:
@@ -170,6 +170,16 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QCheckBox" name="feedRetractEnabled">
|
||||
<property name="text">
|
||||
<string>Feed retract</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>G85: Retract from the hole at the given feedrate instead of rapid move</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
@@ -197,6 +207,7 @@
|
||||
<tabstops>
|
||||
<tabstop>toolController</tabstop>
|
||||
<tabstop>peckEnabled</tabstop>
|
||||
<tabstop>feedRetractEnabled</tabstop>
|
||||
<tabstop>dwellEnabled</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
|
||||
@@ -38,7 +38,7 @@ else:
|
||||
|
||||
|
||||
def generate(
|
||||
edge, dwelltime=0.0, peckdepth=0.0, repeat=1, retractheight=None, chipBreak=False
|
||||
edge, dwelltime=0.0, peckdepth=0.0, repeat=1, retractheight=None, chipBreak=False, feedRetract=False
|
||||
):
|
||||
"""
|
||||
Generates Gcode for drilling a single hole.
|
||||
@@ -59,6 +59,11 @@ def generate(
|
||||
full retracts to clear chips from the hole.
|
||||
http://linuxcnc.org/docs/html/gcode/g-code.html#gcode:g73
|
||||
|
||||
If feedRetract is True, the generator will produce G85 cycles which retract
|
||||
the tool at the specified feed rate instead of performing a rapid move.
|
||||
This is useful for boring or reaming operations. Peck or dwell cannot be used with feed retract.
|
||||
http://linuxcnc.org/docs/html/gcode/g-code.html#gcode:g85
|
||||
|
||||
"""
|
||||
startPoint = edge.Vertexes[0].Point
|
||||
endPoint = edge.Vertexes[1].Point
|
||||
@@ -73,6 +78,12 @@ def generate(
|
||||
if dwelltime > 0.0 and peckdepth > 0.0:
|
||||
raise ValueError("Peck and Dwell cannot be used together")
|
||||
|
||||
if dwelltime > 0.0 and feedRetract:
|
||||
raise ValueError("Dwell and feed retract cannot be used together")
|
||||
|
||||
if peckdepth > 0.0 and feedRetract:
|
||||
raise ValueError("Peck and feed retract cannot be used together")
|
||||
|
||||
if repeat < 1:
|
||||
raise ValueError("repeat must be 1 or greater")
|
||||
|
||||
@@ -112,7 +123,9 @@ def generate(
|
||||
if repeat > 1:
|
||||
cmdParams["L"] = repeat
|
||||
|
||||
if peckdepth == 0.0:
|
||||
if feedRetract:
|
||||
cmd = "G85"
|
||||
elif peckdepth == 0.0:
|
||||
if dwelltime > 0.0:
|
||||
cmd = "G82"
|
||||
cmdParams["P"] = dwelltime
|
||||
|
||||
@@ -105,6 +105,14 @@ class ObjectDrilling(PathCircularHoleBase.ObjectOp):
|
||||
QT_TRANSLATE_NOOP("App::Property", "Use chipbreaking"),
|
||||
)
|
||||
|
||||
if not hasattr(obj, "feedRetractEnabled"):
|
||||
obj.addProperty(
|
||||
"App::PropertyBool", "feedRetractEnabled", "Drill",
|
||||
QT_TRANSLATE_NOOP(
|
||||
"App::Property",
|
||||
"Use G85 boring cycle with feed out")
|
||||
)
|
||||
|
||||
def initCircularHoleOperation(self, obj):
|
||||
"""initCircularHoleOperation(obj) ... add drilling specific properties to obj."""
|
||||
obj.addProperty(
|
||||
@@ -178,6 +186,12 @@ class ObjectDrilling(PathCircularHoleBase.ObjectOp):
|
||||
"App::Property",
|
||||
"Apply G99 retraction: only retract to RetractHeight between holes in this operation")
|
||||
)
|
||||
obj.addProperty(
|
||||
"App::PropertyBool", "feedRetractEnabled", "Drill",
|
||||
QT_TRANSLATE_NOOP(
|
||||
"App::Property",
|
||||
"Use G85 boring cycle with feed out")
|
||||
)
|
||||
|
||||
for n in self.propertyEnumerations():
|
||||
setattr(obj, n[0], n[1])
|
||||
@@ -276,6 +290,7 @@ class ObjectDrilling(PathCircularHoleBase.ObjectOp):
|
||||
repeat,
|
||||
obj.RetractHeight.Value,
|
||||
chipBreak=chipBreak,
|
||||
feedRetract=obj.feedRetractEnabled
|
||||
)
|
||||
|
||||
except ValueError as e: # any targets that fail the generator are ignored
|
||||
|
||||
@@ -62,11 +62,20 @@ class TaskPanelOpPage(PathCircularHoleBaseGui.TaskPanelOpPage):
|
||||
def registerSignalHandlers(self, obj):
|
||||
self.form.peckEnabled.toggled.connect(self.form.peckDepth.setEnabled)
|
||||
self.form.peckEnabled.toggled.connect(self.form.dwellEnabled.setDisabled)
|
||||
self.form.peckEnabled.toggled.connect(self.form.feedRetractEnabled.setDisabled)
|
||||
self.form.peckEnabled.toggled.connect(self.setChipBreakControl)
|
||||
|
||||
self.form.feedRetractEnabled.toggled.connect(self.form.peckDepth.setDisabled)
|
||||
self.form.feedRetractEnabled.toggled.connect(self.form.peckEnabled.setDisabled)
|
||||
self.form.feedRetractEnabled.toggled.connect(self.form.dwellEnabled.setDisabled)
|
||||
self.form.feedRetractEnabled.toggled.connect(self.form.chipBreakEnabled.setDisabled)
|
||||
self.form.feedRetractEnabled.toggled.connect(self.form.peckEnabled.setDisabled)
|
||||
self.form.feedRetractEnabled.toggled.connect(self.setChipBreakControl)
|
||||
|
||||
self.form.dwellEnabled.toggled.connect(self.form.dwellTime.setEnabled)
|
||||
self.form.dwellEnabled.toggled.connect(self.form.dwellTimelabel.setEnabled)
|
||||
self.form.dwellEnabled.toggled.connect(self.form.peckEnabled.setDisabled)
|
||||
self.form.dwellEnabled.toggled.connect(self.form.feedRetractEnabled.setDisabled)
|
||||
self.form.dwellEnabled.toggled.connect(self.setChipBreakControl)
|
||||
|
||||
self.form.peckRetractHeight.setEnabled(True)
|
||||
@@ -74,15 +83,18 @@ class TaskPanelOpPage(PathCircularHoleBaseGui.TaskPanelOpPage):
|
||||
|
||||
if self.form.peckEnabled.isChecked():
|
||||
self.form.dwellEnabled.setEnabled(False)
|
||||
self.form.feedRetractEnabled.setEnabled(False)
|
||||
self.form.peckDepth.setEnabled(True)
|
||||
self.form.peckDepthLabel.setEnabled(True)
|
||||
self.form.chipBreakEnabled.setEnabled(True)
|
||||
elif self.form.dwellEnabled.isChecked():
|
||||
self.form.feedRetractEnabled.setEnabled(False)
|
||||
self.form.peckEnabled.setEnabled(False)
|
||||
self.form.dwellTime.setEnabled(True)
|
||||
self.form.dwellTimelabel.setEnabled(True)
|
||||
self.form.chipBreakEnabled.setEnabled(False)
|
||||
else:
|
||||
self.form.feedRetractEnabled.setEnabled(True)
|
||||
self.form.chipBreakEnabled.setEnabled(False)
|
||||
|
||||
def setChipBreakControl(self):
|
||||
@@ -116,6 +128,8 @@ class TaskPanelOpPage(PathCircularHoleBaseGui.TaskPanelOpPage):
|
||||
obj.DwellEnabled = self.form.dwellEnabled.isChecked()
|
||||
if obj.PeckEnabled != self.form.peckEnabled.isChecked():
|
||||
obj.PeckEnabled = self.form.peckEnabled.isChecked()
|
||||
if obj.feedRetractEnabled != self.form.feedRetractEnabled.isChecked():
|
||||
obj.feedRetractEnabled = self.form.feedRetractEnabled.isChecked()
|
||||
if obj.chipBreakEnabled != self.form.chipBreakEnabled.isChecked():
|
||||
obj.chipBreakEnabled = self.form.chipBreakEnabled.isChecked()
|
||||
if obj.ExtraOffset != str(self.form.ExtraOffset.currentData()):
|
||||
@@ -154,6 +168,11 @@ class TaskPanelOpPage(PathCircularHoleBaseGui.TaskPanelOpPage):
|
||||
else:
|
||||
self.form.chipBreakEnabled.setCheckState(QtCore.Qt.Unchecked)
|
||||
|
||||
if obj.feedRetractEnabled:
|
||||
self.form.feedRetractEnabled.setCheckState(QtCore.Qt.Checked)
|
||||
else:
|
||||
self.form.feedRetractEnabled.setCheckState(QtCore.Qt.Unchecked)
|
||||
|
||||
self.selectInComboBox(obj.ExtraOffset, self.form.ExtraOffset)
|
||||
|
||||
self.setupToolController(obj, self.form.toolController)
|
||||
@@ -173,6 +192,7 @@ class TaskPanelOpPage(PathCircularHoleBaseGui.TaskPanelOpPage):
|
||||
signals.append(self.form.coolantController.currentIndexChanged)
|
||||
signals.append(self.form.ExtraOffset.currentIndexChanged)
|
||||
signals.append(self.form.KeepToolDownEnabled.stateChanged)
|
||||
signals.append(self.form.feedRetractEnabled.stateChanged)
|
||||
|
||||
return signals
|
||||
|
||||
|
||||
@@ -175,3 +175,69 @@ class TestPathDrillGenerator(PathTestUtils.PathTestBase):
|
||||
command = result[0]
|
||||
|
||||
self.assertTrue(command.Name == "G73")
|
||||
|
||||
def test70(self):
|
||||
"""Test feed retract enabled produces G85"""
|
||||
v1 = FreeCAD.Vector(0, 0, 10)
|
||||
v2 = FreeCAD.Vector(0, 0, 0)
|
||||
|
||||
e = Part.makeLine(v1, v2)
|
||||
|
||||
args = {"edge": e, "feedRetract": True}
|
||||
result = generator.generate(**args)
|
||||
command = result[0]
|
||||
|
||||
self.assertEqual(command.Name, "G85")
|
||||
# G85 does not support peck or dwell
|
||||
self.assertFalse(hasattr(command.Parameters, "Q"))
|
||||
self.assertFalse(hasattr(command.Parameters, "P"))
|
||||
|
||||
def test71(self):
|
||||
"""Test that dwell can be used when feed retract is not enabled"""
|
||||
v1 = FreeCAD.Vector(0, 0, 10)
|
||||
v2 = FreeCAD.Vector(0, 0, 0)
|
||||
|
||||
e = Part.makeLine(v1, v2)
|
||||
|
||||
args = {"edge": e, "dwelltime": 0.5, "feedRetract": False}
|
||||
result = generator.generate(**args)
|
||||
|
||||
command = result[0]
|
||||
|
||||
self.assertEqual(command.Name, "G82")
|
||||
self.assertEqual(command.Parameters["P"], 0.5)
|
||||
|
||||
def test72(self):
|
||||
"""Test that peck can be used when feed retract is not enabled"""
|
||||
v1 = FreeCAD.Vector(0, 0, 10)
|
||||
v2 = FreeCAD.Vector(0, 0, 0)
|
||||
|
||||
e = Part.makeLine(v1, v2)
|
||||
|
||||
args = {"edge": e, "peckdepth": 1.0, "feedRetract": False}
|
||||
result = generator.generate(**args)
|
||||
|
||||
command = result[0]
|
||||
|
||||
self.assertTrue(command.Name == "G83")
|
||||
self.assertEqual(command.Parameters["Q"], 1.0)
|
||||
|
||||
def test73(self):
|
||||
"""Test error when feed retract and dwell are enabled"""
|
||||
v1 = FreeCAD.Vector(0, 0, 10)
|
||||
v2 = FreeCAD.Vector(0, 0, 0)
|
||||
|
||||
e = Part.makeLine(v1, v2)
|
||||
|
||||
args = {"edge": e, "dwelltime": 1.0, "feedRetract": True}
|
||||
self.assertRaises(ValueError, generator.generate, **args)
|
||||
|
||||
def test74(self):
|
||||
"""Test error when feed retract and peck are enabled"""
|
||||
v1 = FreeCAD.Vector(0, 0, 10)
|
||||
v2 = FreeCAD.Vector(0, 0, 0)
|
||||
|
||||
e = Part.makeLine(v1, v2)
|
||||
|
||||
args = {"edge": e, "peckdepth": 1.0, "chipBreak": True, "feedRetract": True}
|
||||
self.assertRaises(ValueError, generator.generate, **args)
|
||||
|
||||
Reference in New Issue
Block a user