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:
sliptonic
2024-04-02 07:57:55 -05:00
committed by GitHub
5 changed files with 127 additions and 2 deletions

View File

@@ -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/>

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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)