def circularHoleExecute(self, obj, holes): '''circularHoleExecute(obj, holes) ... generate drill operation for each hole in holes.''' PathLog.track() self.commandlist.append(Path.Command("(Begin Drilling)")) # rapid to clearance height self.commandlist.append(Path.Command('G0', {'Z': obj.ClearanceHeight.Value, 'F': self.vertRapid})) tiplength = 0.0 if obj.ExtraOffset == 'Drill Tip': tiplength = PathUtils.drillTipLength(self.tool) elif obj.ExtraOffset == '2x Drill Tip': tiplength = PathUtils.drillTipLength(self.tool) * 2 holes = PathUtils.sort_jobs(holes, ['x', 'y']) self.commandlist.append(Path.Command('G90')) self.commandlist.append(Path.Command(obj.ReturnLevel)) cmd = "G81" cmdParams = {} cmdParams['Z'] = obj.FinalDepth.Value - tiplength cmdParams['F'] = self.vertFeed cmdParams['R'] = obj.RetractHeight.Value if obj.PeckEnabled and obj.PeckDepth.Value > 0: cmd = "G83" cmdParams['Q'] = obj.PeckDepth.Value elif obj.DwellEnabled and obj.DwellTime > 0: cmd = "G82" cmdParams['P'] = obj.DwellTime # parentJob = PathUtils.findParentJob(obj) # startHeight = obj.StartDepth.Value + parentJob.SetupSheet.SafeHeightOffset.Value startHeight = obj.StartDepth.Value + self.job.SetupSheet.SafeHeightOffset.Value for p in holes: params = {} params['X'] = p['x'] params['Y'] = p['y'] # move to hole location self.commandlist.append(Path.Command('G0', {'X': p['x'], 'Y': p['y'], 'F': self.horizRapid})) self.commandlist.append(Path.Command('G0', {'Z': startHeight, 'F': self.vertRapid})) self.commandlist.append(Path.Command('G1', {'Z': obj.StartDepth.Value, 'F': self.vertFeed})) # Update changes to parameters params.update(cmdParams) # Perform canned drilling cycle self.commandlist.append(Path.Command(cmd, params)) # Cancel canned drilling cycle self.commandlist.append(Path.Command('G80')) self.commandlist.append(Path.Command('G0', {'Z': obj.SafeHeight.Value}))
def circularHoleExecute(self, obj, holes): '''circularHoleExecute(obj, holes) ... generate drill operation for each hole in holes.''' PathLog.track() self.commandlist.append(Path.Command("(Begin Drilling)")) # rapid to clearance height self.commandlist.append( Path.Command('G0', { 'Z': obj.ClearanceHeight.Value, 'F': self.vertRapid })) tiplength = 0.0 if obj.AddTipLength: tiplength = PathUtils.drillTipLength(self.tool) holes = PathUtils.sort_jobs(holes, ['x', 'y']) self.commandlist.append(Path.Command('G90')) self.commandlist.append(Path.Command(obj.ReturnLevel)) # ml: I'm not sure whey these were here, they seem redundant ## rapid to first hole location, with spindle still retracted: #p0 = holes[0] #self.commandlist.append(Path.Command('G0', {'X': p0['x'], 'Y': p0['y'], 'F': self.horizRapid})) ## move tool to clearance plane #self.commandlist.append(Path.Command('G0', {'Z': obj.ClearanceHeight.Value, 'F': self.vertRapid})) cmd = "G81" cmdParams = {} cmdParams['Z'] = obj.FinalDepth.Value - tiplength cmdParams['F'] = self.vertFeed cmdParams['R'] = obj.RetractHeight.Value if obj.PeckEnabled and obj.PeckDepth.Value > 0: cmd = "G83" cmdParams['Q'] = obj.PeckDepth.Value elif obj.DwellEnabled and obj.DwellTime > 0: cmd = "G82" cmdParams['P'] = obj.DwellTime for p in holes: params = {} params['X'] = p['x'] params['Y'] = p['y'] params.update(cmdParams) self.commandlist.append(Path.Command(cmd, params)) self.commandlist.append(Path.Command('G80'))
def circularHoleExecute(self, obj, holes): '''circularHoleExecute(obj, holes) ... generate drill operation for each hole in holes.''' PathLog.track() self.commandlist.append(Path.Command("(Begin Drilling)")) # rapid to clearance height self.commandlist.append(Path.Command('G0', {'Z': obj.ClearanceHeight.Value, 'F': self.vertRapid})) tiplength = 0.0 if obj.AddTipLength: tiplength = PathUtils.drillTipLength(self.tool) holes = PathUtils.sort_jobs(holes, ['x', 'y']) self.commandlist.append(Path.Command('G90')) self.commandlist.append(Path.Command(obj.ReturnLevel)) # ml: I'm not sure whey these were here, they seem redundant ## rapid to first hole location, with spindle still retracted: #p0 = holes[0] #self.commandlist.append(Path.Command('G0', {'X': p0['x'], 'Y': p0['y'], 'F': self.horizRapid})) ## move tool to clearance plane #self.commandlist.append(Path.Command('G0', {'Z': obj.ClearanceHeight.Value, 'F': self.vertRapid})) cmd = "G81" cmdParams = {} cmdParams['Z'] = obj.FinalDepth.Value - tiplength cmdParams['F'] = self.vertFeed cmdParams['R'] = obj.RetractHeight.Value if obj.PeckEnabled and obj.PeckDepth.Value > 0: cmd = "G83" cmdParams['Q'] = obj.PeckDepth.Value elif obj.DwellEnabled and obj.DwellTime > 0: cmd = "G82" cmdParams['P'] = obj.DwellTime for p in holes: params = {} params['X'] = p['x'] params['Y'] = p['y'] params.update(cmdParams) self.commandlist.append(Path.Command(cmd, params)) self.commandlist.append(Path.Command('G80'))
def execute(self, obj): PathLog.track() if not obj.Active: path = Path.Path("(inactive operation)") obj.Path = path obj.ViewObject.Visibility = False return output = "" if obj.Comment != "": output += '(' + str(obj.Comment) + ')\n' toolLoad = obj.ToolController if toolLoad is None or toolLoad.ToolNumber == 0: FreeCAD.Console.PrintError( "No Tool Controller is selected. We need a tool to build a Path." ) return else: self.vertFeed = toolLoad.VertFeed.Value self.horizFeed = toolLoad.HorizFeed.Value self.vertRapid = toolLoad.VertRapid.Value self.horizRapid = toolLoad.HorizRapid.Value tool = toolLoad.Proxy.getTool(toolLoad) if not tool or tool.Diameter == 0: FreeCAD.Console.PrintError( "No Tool found or diameter is zero. We need a tool to build a Path." ) return else: self.radius = tool.Diameter / 2 tiplength = 0.0 if obj.AddTipLength: tiplength = PathUtils.drillTipLength(tool) if len(obj.Names) == 0: parentJob = PathUtils.findParentJob(obj) if parentJob is None: return baseobject = parentJob.Base if baseobject is None: return # Arch PanelSheet if hasattr(baseobject, "Proxy"): holes = [] if isinstance(baseobject.Proxy, ArchPanel.PanelSheet): baseobject.Proxy.execute(baseobject) i = 0 holeshapes = baseobject.Proxy.getHoles(baseobject, transform=True) tooldiameter = obj.ToolController.Proxy.getTool( obj.ToolController).Diameter for holeshape in holeshapes: PathLog.debug('Entering new HoleShape') for wire in holeshape.Wires: PathLog.debug('Entering new Wire') for edge in wire.Edges: if PathUtils.isDrillable( baseobject, edge, tooldiameter): PathLog.debug( 'Found drillable hole edges: {}'. format(edge)) x = edge.Curve.Center.x y = edge.Curve.Center.y diameter = edge.BoundBox.XLength holes.append({ 'x': x, 'y': y, 'featureName': baseobject.Name + '.' + 'Drill' + str(i), 'd': diameter }) i = i + 1 else: holes = self.findHoles(obj, baseobject.Shape) for i in range(len(holes)): holes[i]['featureName'] = baseobject.Name + '.' + holes[i][ 'featureName'] names = [] positions = [] enabled = [] diameters = [] for h in holes: if len(names) == 0: self.setDepths(obj, baseobject, h) names.append(h['featureName']) positions.append(FreeCAD.Vector(h['x'], h['y'], 0)) enabled.append(1) diameters.append(h['d']) obj.Names = names obj.Positions = positions obj.Enabled = enabled obj.Diameters = diameters locations = [] output = "(Begin Drilling)\n" for i in range(len(obj.Names)): if obj.Enabled[i] > 0: locations.append({ 'x': obj.Positions[i].x, 'y': obj.Positions[i].y }) if len(locations) > 0: locations = PathUtils.sort_jobs(locations, ['x', 'y']) output += "G90 " + obj.ReturnLevel + "\n" # rapid to clearance height output += "G0 Z" + str( obj.ClearanceHeight.Value) + "F " + PathUtils.fmt( self.vertRapid) + "\n" # rapid to first hole location, with spindle still retracted: p0 = locations[0] output += "G0 X" + fmt(p0['x']) + " Y" + fmt( p0['y']) + "F " + PathUtils.fmt(self.horizRapid) + "\n" # move tool to clearance plane output += "G0 Z" + fmt( obj.ClearanceHeight.Value) + "F " + PathUtils.fmt( self.vertRapid) + "\n" pword = "" qword = "" if obj.PeckDepth.Value > 0 and obj.PeckEnabled: cmd = "G83" qword = " Q" + fmt(obj.PeckDepth.Value) elif obj.DwellTime > 0 and obj.DwellEnabled: cmd = "G82" pword = " P" + fmt(obj.DwellTime) else: cmd = "G81" for p in locations: output += cmd + \ " X" + fmt(p['x']) + \ " Y" + fmt(p['y']) + \ " Z" + fmt(obj.FinalDepth.Value - tiplength) + qword + pword + \ " R" + str(obj.RetractHeight.Value) + \ " F" + str(self.vertFeed) + "\n" \ output += "G80\n" path = Path.Path(output) obj.Path = path
def circularHoleExecute(self, obj, holes): '''circularHoleExecute(obj, holes) ... generate drill operation for each hole in holes.''' PathLog.track() PathLog.debug("\ncircularHoleExecute() in PathDrilling.py") lastAxis = None lastAngle = 0.0 self.commandlist.append(Path.Command("(Begin Drilling)")) # rapid to clearance height self.commandlist.append( Path.Command('G0', { 'Z': obj.ClearanceHeight.Value, 'F': self.vertRapid })) tiplength = 0.0 if obj.AddTipLength: tiplength = PathUtils.drillTipLength(self.tool) holes = PathUtils.sort_jobs(holes, ['x', 'y']) self.commandlist.append(Path.Command('G90')) self.commandlist.append(Path.Command(obj.ReturnLevel)) for p in holes: cmd = "G81" cmdParams = {} cmdParams['Z'] = p['trgtDep'] - tiplength cmdParams['F'] = self.vertFeed cmdParams['R'] = obj.RetractHeight.Value if obj.PeckEnabled and obj.PeckDepth.Value > 0: cmd = "G83" cmdParams['Q'] = obj.PeckDepth.Value elif obj.DwellEnabled and obj.DwellTime > 0: cmd = "G82" cmdParams['P'] = obj.DwellTime params = {} params['X'] = p['x'] params['Y'] = p['y'] params.update(cmdParams) if obj.EnableRotation != 'Off': angle = p['angle'] axis = p['axis'] # Rotate model to index for hole if axis == 'X': axisOfRot = 'A' elif axis == 'Y': axisOfRot = 'B' # Reverse angle temporarily to match model. Error in FreeCAD render of B axis rotations if obj.B_AxisErrorOverride is True: angle = -1 * angle elif axis == 'Z': axisOfRot = 'C' else: axisOfRot = 'A' # Set initial values for last axis and angle if lastAxis is None: lastAxis = axisOfRot lastAngle = angle # Handle axial and angular transitions if axisOfRot != lastAxis: self.commandlist.append( Path.Command('G0', { 'Z': obj.SafeHeight.Value, 'F': self.vertRapid })) self.commandlist.append( Path.Command('G0', { lastAxis: 0.0, 'F': self.axialRapid })) elif angle != lastAngle: self.commandlist.append( Path.Command('G0', { 'Z': obj.SafeHeight.Value, 'F': self.vertRapid })) # Prepare for drilling cycle self.commandlist.append( Path.Command('G0', { axisOfRot: angle, 'F': self.axialRapid })) self.commandlist.append( Path.Command('G0', { 'X': p['x'], 'Y': p['y'], 'F': self.horizRapid })) self.commandlist.append( Path.Command('G1', { 'Z': p['stkTop'], 'F': self.vertFeed })) # Perform and cancel canned drilling cycle self.commandlist.append(Path.Command(cmd, params)) self.commandlist.append( Path.Command('G0', {'Z': obj.SafeHeight.Value})) # shift axis and angle values if obj.EnableRotation != 'Off': lastAxis = axisOfRot lastAngle = angle if obj.EnableRotation != 'Off': self.commandlist.append( Path.Command('G0', { 'Z': obj.SafeHeight.Value, 'F': self.vertRapid })) self.commandlist.append( Path.Command('G0', { lastAxis: 0.0, 'F': self.axialRapid }))
def circularHoleExecute(self, obj, holes): """circularHoleExecute(obj, holes) ... generate drill operation for each hole in holes.""" PathLog.track() machine = PathMachineState.MachineState() self.commandlist.append(Path.Command("(Begin Drilling)")) # rapid to clearance height command = Path.Command("G0", {"Z": obj.ClearanceHeight.Value}) machine.addCommand(command) self.commandlist.append(command) self.commandlist.append(Path.Command("G90")) # Absolute distance mode # Calculate offsets to add to target edge endoffset = 0.0 if obj.ExtraOffset == "Drill Tip": endoffset = PathUtils.drillTipLength(self.tool) elif obj.ExtraOffset == "2x Drill Tip": endoffset = PathUtils.drillTipLength(self.tool) * 2 # http://linuxcnc.org/docs/html/gcode/g-code.html#gcode:g98-g99 self.commandlist.append(Path.Command(obj.ReturnLevel)) holes = PathUtils.sort_locations(holes, ["x", "y"]) # This section is technical debt. The computation of the # target shapes should be factored out for re-use. # This will likely mean refactoring upstream CircularHoleBase to pass # spotshapes instead of holes. startHeight = obj.StartDepth.Value + self.job.SetupSheet.SafeHeightOffset.Value edgelist = [] for hole in holes: v1 = FreeCAD.Vector(hole["x"], hole["y"], obj.StartDepth.Value) v2 = FreeCAD.Vector(hole["x"], hole["y"], obj.FinalDepth.Value - endoffset) edgelist.append(Part.makeLine(v1, v2)) # iterate the edgelist and generate gcode for edge in edgelist: PathLog.debug(edge) # move to hole location startPoint = edge.Vertexes[0].Point command = Path.Command("G0", { "X": startPoint.x, "Y": startPoint.y }) self.commandlist.append(command) machine.addCommand(command) command = Path.Command("G0", {"Z": startHeight}) self.commandlist.append(command) machine.addCommand(command) # command = Path.Command("G1", {"Z": obj.StartDepth.Value}) # self.commandlist.append(command) # machine.addCommand(command) # Technical Debt: We are assuming the edges are aligned. # This assumption should be corrected and the necessary rotations # performed to align the edge with the Z axis for drilling # Perform drilling dwelltime = obj.DwellTime if obj.DwellEnabled else 0.0 peckdepth = obj.PeckDepth.Value if obj.PeckEnabled else 0.0 repeat = 1 # technical debt: Add a repeat property for user control chipBreak = (obj.chipBreakEnabled and obj.PeckEnabled) try: drillcommands = generator.generate(edge, dwelltime, peckdepth, repeat, obj.RetractHeight.Value, chipBreak=chipBreak) except ValueError as e: # any targets that fail the generator are ignored PathLog.info(e) continue for command in drillcommands: self.commandlist.append(command) machine.addCommand(command) # Cancel canned drilling cycle self.commandlist.append(Path.Command("G80")) command = Path.Command("G0", {"Z": obj.SafeHeight.Value}) self.commandlist.append(command) machine.addCommand(command) # Apply feedrates to commands PathFeedRate.setFeedRate(self.commandlist, obj.ToolController)
def circularHoleExecute(self, obj, holes): '''circularHoleExecute(obj, holes) ... generate drill operation for each hole in holes.''' PathLog.track() PathLog.debug("\ncircularHoleExecute() in PathDrilling.py") lastAxis = None lastAngle = 0.0 self.commandlist.append(Path.Command("(Begin Drilling)")) # rapid to clearance height self.commandlist.append(Path.Command('G0', {'Z': obj.ClearanceHeight.Value, 'F': self.vertRapid})) tiplength = 0.0 if obj.ExtraOffset == 'Drill Tip': tiplength = PathUtils.drillTipLength(self.tool) elif obj.ExtraOffset == '2x Drill Tip': tiplength = PathUtils.drillTipLength(self.tool) * 2 holes = PathUtils.sort_jobs(holes, ['x', 'y']) self.commandlist.append(Path.Command('G90')) self.commandlist.append(Path.Command(obj.ReturnLevel)) for p in holes: cmd = "G81" cmdParams = {} cmdParams['Z'] = p['trgtDep'] - tiplength cmdParams['F'] = self.vertFeed cmdParams['R'] = obj.RetractHeight.Value if obj.PeckEnabled and obj.PeckDepth.Value > 0: cmd = "G83" cmdParams['Q'] = obj.PeckDepth.Value elif obj.DwellEnabled and obj.DwellTime > 0: cmd = "G82" cmdParams['P'] = obj.DwellTime params = {} params['X'] = p['x'] params['Y'] = p['y'] if obj.EnableRotation != 'Off': angle = p['angle'] axis = p['axis'] # Rotate model to index for hole if axis == 'X': axisOfRot = 'A' elif axis == 'Y': axisOfRot = 'B' elif axis == 'Z': axisOfRot = 'C' else: axisOfRot = 'A' # Set initial values for last axis and angle if lastAxis is None: lastAxis = axisOfRot lastAngle = angle # Handle axial and angular transitions if axisOfRot != lastAxis: self.commandlist.append(Path.Command('G0', {'Z': obj.SafeHeight.Value, 'F': self.vertRapid})) self.commandlist.append(Path.Command('G0', {lastAxis: 0.0, 'F': self.axialRapid})) elif angle != lastAngle: self.commandlist.append(Path.Command('G0', {'Z': obj.SafeHeight.Value, 'F': self.vertRapid})) # Prepare for drilling cycle self.commandlist.append(Path.Command('G0', {axisOfRot: angle, 'F': self.axialRapid})) self.commandlist.append(Path.Command('G0', {'X': p['x'], 'Y': p['y'], 'F': self.horizRapid})) self.commandlist.append(Path.Command('G1', {'Z': obj.StartDepth.Value, 'F': self.vertFeed})) # Update retract height due to rotation self.opSetDefaultRetractHeight(obj) cmdParams['R'] = obj.RetractHeight.Value # Update changes to parameters params.update(cmdParams) # Perform canned drilling cycle self.commandlist.append(Path.Command(cmd, params)) # Cancel canned drilling cycle self.commandlist.append(Path.Command('G80')) self.commandlist.append(Path.Command('G0', {'Z': obj.SafeHeight.Value})) # shift axis and angle values if obj.EnableRotation != 'Off': lastAxis = axisOfRot lastAngle = angle if obj.EnableRotation != 'Off': self.commandlist.append(Path.Command('G0', {'Z': obj.SafeHeight.Value, 'F': self.vertRapid})) self.commandlist.append(Path.Command('G0', {lastAxis: 0.0, 'F': self.axialRapid}))