Merge pull request #23285 from davidgilkaufman/feed_rate_percentage
[CAM] Feed rate percentage for ramp and lead in/out moves
This commit is contained in:
@@ -49,7 +49,10 @@ class ToolControllerTemplate:
|
||||
HorizFeed = "hfeed"
|
||||
HorizRapid = "hrapid"
|
||||
Label = "label"
|
||||
LeadInFeed = "leadinfeed"
|
||||
LeadOutFeed = "leadoutfeed"
|
||||
Name = "name"
|
||||
RampFeed = "rampfeed"
|
||||
SpindleDir = "dir"
|
||||
SpindleSpeed = "speed"
|
||||
ToolNumber = "nr"
|
||||
@@ -59,6 +62,77 @@ class ToolControllerTemplate:
|
||||
VertRapid = "vrapid"
|
||||
|
||||
|
||||
def _migrateRampDressups(tc):
|
||||
# Enumerate ramp dressups using this TC and their feed rates
|
||||
ramps = set()
|
||||
job_ramp_feeds = []
|
||||
for job in tc.Document.Objects:
|
||||
if hasattr(job, "Operations") and hasattr(job.Operations, "Group"):
|
||||
for op in job.Operations.Group:
|
||||
for ramp in [op] + op.OutListRecursive:
|
||||
if ramp not in ramps and (
|
||||
hasattr(ramp, "RampFeedRate")
|
||||
or (hasattr(ramp, "Proxy") and hasattr(ramp.Proxy, "RampFeedRate"))
|
||||
):
|
||||
rampFeedRate = (
|
||||
ramp.RampFeedRate
|
||||
if hasattr(ramp, "RampFeedRate")
|
||||
else ramp.Proxy.RampFeedRate
|
||||
)
|
||||
if hasattr(ramp, "CustomFeedRate"):
|
||||
customFeedRate = ramp.CustomFeedRate.Value
|
||||
for prop, exp in ramp.ExpressionEngine:
|
||||
if prop == "CustomFeedRate":
|
||||
customFeedRate = exp
|
||||
else:
|
||||
customFeedRate = (
|
||||
ramp.Proxy.CustomFeedRate
|
||||
if hasattr(ramp.Proxy, "CustomFeedRate")
|
||||
else "HorizFeed"
|
||||
)
|
||||
|
||||
if op.Base.ToolController == tc:
|
||||
ramps.add(ramp)
|
||||
if rampFeedRate == "Horizontal Feed Rate":
|
||||
feed = "HorizFeed"
|
||||
elif rampFeedRate == "Vertical Feed Rate":
|
||||
feed = "VertFeed"
|
||||
elif rampFeedRate == "Ramp Feed Rate":
|
||||
feed = "sqrt(HorizFeed * HorizFeed + VertFeed * VertFeed)"
|
||||
else:
|
||||
feed = customFeedRate
|
||||
job_ramp_feeds.append((job, ramp, feed))
|
||||
|
||||
# Ensure there is a TC for each required feed, starting with this one
|
||||
feed_to_tc = {}
|
||||
for i, (job, ramp, feed) in enumerate(job_ramp_feeds):
|
||||
if feed in feed_to_tc:
|
||||
continue
|
||||
|
||||
if len(feed_to_tc) == 0:
|
||||
opTc = tc
|
||||
else:
|
||||
opTc = copyTC(tc, job)
|
||||
# Note: C++ doesn't try to deduplicate the Labels of objects created
|
||||
# during document restore, so here we will reuse the (deduplicated)
|
||||
# name as the label
|
||||
opTc.Label = opTc.Name
|
||||
|
||||
feed_to_tc[feed] = opTc
|
||||
|
||||
if isinstance(feed, str):
|
||||
opTc.setExpression("RampFeed", feed)
|
||||
else:
|
||||
opTc.setExpression("RampFeed", None)
|
||||
opTc.RampFeed = feed
|
||||
if opTc is not tc:
|
||||
opTc.recompute()
|
||||
|
||||
# Loop over ramps and assign each one the appropriate TC
|
||||
for _, ramp, feed in job_ramp_feeds:
|
||||
ramp.Base.ToolController = feed_to_tc[feed]
|
||||
|
||||
|
||||
class ToolController:
|
||||
def __init__(self, obj, createTool=True):
|
||||
Path.Log.track("tool: ")
|
||||
@@ -106,6 +180,31 @@ class ToolController:
|
||||
"Rapid",
|
||||
QT_TRANSLATE_NOOP("App::Property", "Rapid rate for horizontal moves"),
|
||||
)
|
||||
|
||||
obj.addProperty(
|
||||
"App::PropertySpeed",
|
||||
"RampFeed",
|
||||
"Feed",
|
||||
QT_TRANSLATE_NOOP("App::Property", "Feed rate for ramp moves"),
|
||||
)
|
||||
obj.setExpression("RampFeed", "HorizFeed")
|
||||
|
||||
obj.addProperty(
|
||||
"App::PropertySpeed",
|
||||
"LeadInFeed",
|
||||
"Feed",
|
||||
QT_TRANSLATE_NOOP("App::Property", "Feed rate for lead-in moves"),
|
||||
)
|
||||
obj.setExpression("LeadInFeed", "HorizFeed")
|
||||
|
||||
obj.addProperty(
|
||||
"App::PropertySpeed",
|
||||
"LeadOutFeed",
|
||||
"Feed",
|
||||
QT_TRANSLATE_NOOP("App::Property", "Feed rate for lead-out moves"),
|
||||
)
|
||||
obj.setExpression("LeadOutFeed", "HorizFeed")
|
||||
|
||||
obj.setEditorMode("Placement", 2)
|
||||
|
||||
for n in self.propertyEnumerations():
|
||||
@@ -166,6 +265,40 @@ class ToolController:
|
||||
|
||||
obj.setEditorMode("Placement", 2)
|
||||
|
||||
needsRecompute = False
|
||||
if not hasattr(obj, "RampFeed"):
|
||||
obj.addProperty(
|
||||
"App::PropertySpeed",
|
||||
"RampFeed",
|
||||
"Feed",
|
||||
QT_TRANSLATE_NOOP("App::Property", "Feed rate for ramp moves"),
|
||||
)
|
||||
_migrateRampDressups(obj)
|
||||
needsRecompute = True
|
||||
|
||||
if not hasattr(obj, "LeadInFeed"):
|
||||
obj.addProperty(
|
||||
"App::PropertySpeed",
|
||||
"LeadInFeed",
|
||||
"Feed",
|
||||
QT_TRANSLATE_NOOP("App::Property", "Feed rate for lead-in moves"),
|
||||
)
|
||||
obj.setExpression("LeadInFeed", "HorizFeed")
|
||||
needsRecompute = True
|
||||
|
||||
if not hasattr(obj, "LeadOutFeed"):
|
||||
obj.addProperty(
|
||||
"App::PropertySpeed",
|
||||
"LeadOutFeed",
|
||||
"Feed",
|
||||
QT_TRANSLATE_NOOP("App::Property", "Feed rate for lead-out moves"),
|
||||
)
|
||||
obj.setExpression("LeadOutFeed", "HorizFeed")
|
||||
needsRecompute = True
|
||||
|
||||
if needsRecompute:
|
||||
obj.recompute()
|
||||
|
||||
def onDelete(self, obj, arg2=None):
|
||||
if hasattr(obj.Tool, "InList") and len(obj.Tool.InList) == 1:
|
||||
if hasattr(obj.Tool.Proxy, "onDelete"):
|
||||
@@ -181,12 +314,22 @@ class ToolController:
|
||||
if template.get(ToolControllerTemplate.Version):
|
||||
version = int(template.get(ToolControllerTemplate.Version))
|
||||
if version == 1 or version == 2:
|
||||
# TODO figure out the meaning of this, and how to handle ramp/leadin/leadout feed rates
|
||||
# or what else must be added to templates
|
||||
if template.get(ToolControllerTemplate.Label):
|
||||
obj.Label = template.get(ToolControllerTemplate.Label)
|
||||
if template.get(ToolControllerTemplate.VertFeed):
|
||||
obj.VertFeed = template.get(ToolControllerTemplate.VertFeed)
|
||||
if template.get(ToolControllerTemplate.HorizFeed):
|
||||
obj.HorizFeed = template.get(ToolControllerTemplate.HorizFeed)
|
||||
if template.get(ToolControllerTemplate.LeadInFeed):
|
||||
obj.LeadInFeed = template.get(ToolControllerTemplate.LeadInFeed, obj.LeadInFeed)
|
||||
if template.get(ToolControllerTemplate.LeadOutFeed):
|
||||
obj.LeadOutFeed = template.get(
|
||||
ToolControllerTemplate.LeadOutFeed, obj.LeadOutFeed
|
||||
)
|
||||
if template.get(ToolControllerTemplate.RampFeed):
|
||||
obj.RampFeed = template.get(ToolControllerTemplate.RampFeed, obj.RampFeed)
|
||||
if template.get(ToolControllerTemplate.VertRapid):
|
||||
obj.VertRapid = template.get(ToolControllerTemplate.VertRapid)
|
||||
if template.get(ToolControllerTemplate.HorizRapid):
|
||||
@@ -241,6 +384,9 @@ class ToolController:
|
||||
attrs[ToolControllerTemplate.ToolNumber] = obj.ToolNumber
|
||||
attrs[ToolControllerTemplate.VertFeed] = "%s" % (obj.VertFeed)
|
||||
attrs[ToolControllerTemplate.HorizFeed] = "%s" % (obj.HorizFeed)
|
||||
attrs[ToolControllerTemplate.LeadInFeed] = "%s" % (obj.LeadInFeed)
|
||||
attrs[ToolControllerTemplate.LeadOutFeed] = "%s" % (obj.LeadOutFeed)
|
||||
attrs[ToolControllerTemplate.RampFeed] = "%s" % (obj.RampFeed)
|
||||
attrs[ToolControllerTemplate.VertRapid] = "%s" % (obj.VertRapid)
|
||||
attrs[ToolControllerTemplate.HorizRapid] = "%s" % (obj.HorizRapid)
|
||||
attrs[ToolControllerTemplate.SpindleSpeed] = obj.SpindleSpeed
|
||||
@@ -327,6 +473,23 @@ def Create(
|
||||
return obj
|
||||
|
||||
|
||||
def copyTC(tc, job):
|
||||
newtc = Create(name=tc.Label, tool=tc.Tool, toolNumber=tc.ToolNumber)
|
||||
job.Proxy.addToolController(newtc)
|
||||
|
||||
for prop in tc.PropertiesList:
|
||||
try:
|
||||
if prop not in ["Label", "Label2"]:
|
||||
setattr(newtc, prop, getattr(tc, prop))
|
||||
except RuntimeError:
|
||||
# Ignore errors for read-only properties
|
||||
pass
|
||||
for attr, expr in tc.ExpressionEngine:
|
||||
newtc.setExpression(attr, expr)
|
||||
|
||||
return newtc
|
||||
|
||||
|
||||
def FromTemplate(template, assignViewProvider=True):
|
||||
Path.Log.track()
|
||||
|
||||
|
||||
@@ -218,6 +218,11 @@ class ToolControllerEditor(object):
|
||||
PathGuiUtil.populateCombobox(self.controller, enumTups, comboToPropertyMap)
|
||||
self.vertFeed = PathGuiUtil.QuantitySpinBox(self.controller.vertFeed, obj, "VertFeed")
|
||||
self.horizFeed = PathGuiUtil.QuantitySpinBox(self.controller.horizFeed, obj, "HorizFeed")
|
||||
self.leadInFeed = PathGuiUtil.QuantitySpinBox(self.controller.leadInFeed, obj, "LeadInFeed")
|
||||
self.leadOutFeed = PathGuiUtil.QuantitySpinBox(
|
||||
self.controller.leadOutFeed, obj, "LeadOutFeed"
|
||||
)
|
||||
self.rampFeed = PathGuiUtil.QuantitySpinBox(self.controller.rampFeed, obj, "RampFeed")
|
||||
self.vertRapid = PathGuiUtil.QuantitySpinBox(self.controller.vertRapid, obj, "VertRapid")
|
||||
self.horizRapid = PathGuiUtil.QuantitySpinBox(self.controller.horizRapid, obj, "HorizRapid")
|
||||
|
||||
@@ -260,6 +265,9 @@ class ToolControllerEditor(object):
|
||||
self.controller.tcNumber,
|
||||
self.horizFeed.widget,
|
||||
self.horizRapid.widget,
|
||||
self.leadInFeed.widget,
|
||||
self.leadOutFeed.widget,
|
||||
self.rampFeed.widget,
|
||||
self.vertFeed.widget,
|
||||
self.vertRapid.widget,
|
||||
self.controller.spindleSpeed,
|
||||
@@ -273,6 +281,9 @@ class ToolControllerEditor(object):
|
||||
self.controller.tcNumber.setValue(tc.ToolNumber)
|
||||
self.horizFeed.updateWidget()
|
||||
self.horizRapid.updateWidget()
|
||||
self.leadInFeed.updateWidget()
|
||||
self.leadOutFeed.updateWidget()
|
||||
self.rampFeed.updateWidget()
|
||||
self.vertFeed.updateWidget()
|
||||
self.vertRapid.updateWidget()
|
||||
self.controller.spindleSpeed.setValue(tc.SpindleSpeed)
|
||||
@@ -292,6 +303,9 @@ class ToolControllerEditor(object):
|
||||
tc.ToolNumber = self.controller.tcNumber.value()
|
||||
self.horizFeed.updateProperty()
|
||||
self.vertFeed.updateProperty()
|
||||
self.leadInFeed.updateProperty()
|
||||
self.leadOutFeed.updateProperty()
|
||||
self.rampFeed.updateProperty()
|
||||
self.horizRapid.updateProperty()
|
||||
self.vertRapid.updateProperty()
|
||||
tc.SpindleSpeed = self.controller.spindleSpeed.value()
|
||||
@@ -323,6 +337,9 @@ class ToolControllerEditor(object):
|
||||
self.controller.tcNumber.editingFinished.connect(self.changed)
|
||||
self.vertFeed.widget.textChanged.connect(self.changed)
|
||||
self.horizFeed.widget.textChanged.connect(self.changed)
|
||||
self.leadInFeed.widget.textChanged.connect(self.changed)
|
||||
self.leadOutFeed.widget.textChanged.connect(self.changed)
|
||||
self.rampFeed.widget.textChanged.connect(self.changed)
|
||||
self.vertRapid.widget.textChanged.connect(self.changed)
|
||||
self.horizRapid.widget.textChanged.connect(self.changed)
|
||||
self.controller.spindleSpeed.editingFinished.connect(self.changed)
|
||||
|
||||
Reference in New Issue
Block a user