def makeListOfCmds(self): rectPath = RectPath(self.point0, self.point1, plane=self.plane) x0, y0 = self.point0 x1, y1 = self.point1 xMid = 0.5 * (x0 + x1) yMid = 0.5 * (y0 + y1) kx, ky = PLANE_COORD[self.plane] self.listOfCmds = [] for i, cmd in enumerate(rectPath.listOfCmds): self.listOfCmds.append(cmd) if i > 0: cornerStr = self.numToCornerStr[i] if self.cornerCutDict[cornerStr]: x = cmd.motionDict[kx] y = cmd.motionDict[ky] normConst = math.sqrt((x - xMid)**2 + (y - yMid)**2) u = (x - xMid) / abs(x - xMid) v = (y - yMid) / abs(y - yMid) xCut = x + self.cornerCutLen * u / math.sqrt(2.0) yCut = y + self.cornerCutLen * v / math.sqrt(2.0) cmd = gcode_cmd.LinearFeed(**{kx: xCut, ky: yCut}) self.listOfCmds.append(cmd) cmd = gcode_cmd.LinearFeed(**{kx: x, ky: y}) self.listOfCmds.append(cmd)
def makeListOfCmds(self): kx, ky = PLANE_COORD[self.plane] kz = PLANE_NORM_COORD[self.plane] pointList = self.getPathPointList() if self.radius is None: if self.helix is None: self.listOfCmds = [ gcode_cmd.LinearFeed(**{ kx: x, ky: y }) for x, y in pointList ] else: self.listOfCmds = [ gcode_cmd.LinearFeed(**{ kx: x, ky: y, kz: z }) for x, y, z in pointList ] else: ki, kj = HELICAL_OFFSETS[self.plane] cornerArcClass = PLANE_TO_HELIX_MOTION[self.plane] arcDir = getDirFromPts(pointList[0][:2], pointList[1][:2], pointList[2][:2]) self.listOfCmds = [] for i in range(0, len(pointList) - 1): # Create linear feed x0, y0 = pointList[i][:2] linearFeedDict = {kx: x0, ky: y0} if self.helix is not None: z0 = pointList[i][2] linearFeedDict[kz] = z0 linearFeed = gcode_cmd.LinearFeed(**linearFeedDict) self.listOfCmds.append(linearFeed) # Create corner arc feed if (i - 1) % 2 == 0: x1, y1 = pointList[i + 1][:2] if arcDir == 'ccw': cx = 0.5 * (y0 - y1 + x0 + x1) cy = 0.5 * (y0 + y1 - x0 + x1) else: cx = 0.5 * (-y0 + y1 + x0 + x1) cy = 0.5 * (y0 + y1 + x0 - x1) offsetx = cx - x0 offsety = cy - y0 cornerArcDict = { ki: offsetx, kj: offsety, kx: x1, ky: y1, 'd': arcDir } if self.helix is not None: z1 = pointList[i + 1][2] cornerArcDict[kz] = z1 cornerArcFeed = cornerArcClass(**cornerArcDict) self.listOfCmds.append(cornerArcFeed)
def getUniDirRasterRect(point0, point1, step, cutZ, retZ, keys=('x', 'y', 'z')): """ Generates a uni-directional rastered rectangle path. Details: ... """ x0, y0 = point0 x1, y1 = point1 cmdList = [] # Get step size and raster completion function if y0 < y1: dy = step def outOfBounds(y): return y > y1 else: dy = -step def outOfBounds(y): return y < y1 # Get function for alternating x direction def getAlternateX(xLast): if xLast == x0: return x1 else: return x0 # Generate raster x, y = x0, y0 kx, ky, kz = keys isFirst = True isLast = False cmdList.append(gcode_cmd.LinearFeed(**{kx: x, ky: y, kz: cutZ})) while 1: x = getAlternateX(x) if x == x0: cmdList.append(gcode_cmd.LinearFeed(**{kz: retZ})) cmdList.append(gcode_cmd.RapidMotion(**{kx: x, ky: y})) else: cmdList.append(gcode_cmd.LinearFeed(**{kz: cutZ})) if isFirst: isFirst = False else: y += dy if outOfBounds(y): y = y1 isLast = True cmdList.append(gcode_cmd.LinearFeed(**{ky: y})) cmdList.append(gcode_cmd.LinearFeed(**{kx: x, ky: y})) if isLast: break return cmdList
def makeListOfCmds(self): kx, ky = PLANE_COORD[self.plane] ki, kj = HELICAL_OFFSETS[self.plane] kz = PLANE_NORM_COORD[self.plane] cx, cy = self.center x0, y0 = self.getStartPoint()[:2] x1, y1 = self.getStopPoint()[:2] turns = self.getNumTurns() # Get helix motion class based on plane helixMotionClass = PLANE_TO_HELIX_MOTION[self.plane] self.listOfCmds = [] # Add linear feed to start position if self.includeFeedToStart: linearFeedArgs = {kx: x0, ky: y0} if self.helix is not None: linearFeedArgs[kz] = self.helix[0] self.listOfCmds.append(gcode_cmd.LinearFeed(**linearFeedArgs)) # Add helical motion feed helixFeedArgs = { kx: x1, ky: y1, ki: cx - x0, kj: cy - y0, 'd': self.direction } if self.helix is not None: helixFeedArgs[kz] = self.helix[1] if turns > 1: helixFeedArgs['p'] = turns self.listOfCmds.append(helixMotionClass(**helixFeedArgs))
def getBiDirRasterRect(point0, point1, step, keys=('x', 'y')): """ Generates a bi-directional rastered rectangle path defined by point0=(x0,y0) and point1=(x1,y1). The raster scan is in the direction of the 1st coordinate and path starts by initially cutting from x0 to x1. The spacing between rows in is determined by step. """ x0, y0 = point0 x1, y1 = point1 cmdList = [] # Get step size and raster completion function if y0 < y1: dy = step def rasterDone(y): return (y + dy) > y1 else: dy = -step def rasterDone(y): return (y + dy) < y1 # Get function for alternating x direction def getAlternateX(xLast): if xLast == x0: return x1 else: return x0 # Generate raster x, y = x0, y0 kx, ky = keys cmdList.append(gcode_cmd.LinearFeed(**{kx: x, ky: y})) while 1: x = getAlternateX(x) cmdList.append(gcode_cmd.LinearFeed(**{kx: x, ky: y})) if rasterDone(y): break y += dy cmdList.append(gcode_cmd.LinearFeed(**{kx: x, ky: y})) if y != y1: y = y1 cmdList.append(gcode_cmd.LinearFeed(**{kx: x, ky: y})) x = getAlternateX(x) cmdList.append(gcode_cmd.LinearFeed(**{kx: x, ky: y})) return cmdList
def getLinearFeedFromPt(self, p): kx, ky = PLANE_COORD[self.plane] if len(p) == 2: feedArgs = {kx: p[0], ky: p[1]} else: kz = PLANE_NORM_COORD[self.plane] feedArgs = {kx: p[0], ky: p[1], kz: p[2]} return gcode_cmd.LinearFeed(**feedArgs)
def makeListOfCmds(self): # Retreive numerical parameters and convert to float cx = float(self.param['centerX']) cy = float(self.param['centerY']) width = abs(float(self.param['width'])) height = abs(float(self.param['height'])) depth = abs(float(self.param['depth'])) startZ = float(self.param['startZ']) overlap = float(self.param['overlap']) try: overlapFinish = self.param['overlapFinish'] except KeyError: overlapFinish = overlap overlapFinish = float(overlapFinish) maxCutDepth = float(self.param['maxCutDepth']) toolDiam = abs(float(self.param['toolDiam'])) try: startDwell = self.param['startDwell'] except KeyError: startDwell = 0.0 startDwell = abs(float(startDwell)) try: cornerMargin = self.param['cornerMargin'] except KeyError: cornerMargin = 0.0 cornerMargin = float(cornerMargin) try: coolingPause = self.param['coolingPause'] except KeyError: coolingPause = None # Check params checkRectPocketOverlap(overlap) checkRectPocketOverlap(overlapFinish) # Get rectangular path parameters if self.param['direction'] == 'cw': sgnDir = 1.0 else: sgnDir = -1.0 x0 = cx + 0.5*(-width + toolDiam) x1 = cx + 0.5*( width - toolDiam) y0 = cy + 0.5*sgnDir*(-height + toolDiam) y1 = cy + 0.5*sgnDir*( height - toolDiam) point0 = x0,y0 point1 = x1,y1 # Move to safe height, then to start x,y and then to start z self.addStartComment() self.addRapidMoveToSafeZ() self.addRapidMoveToPos(x=x0,y=y0,comment='start x,y') self.addDwell(startDwell) self.addMoveToStartZ() # Get z cutting parameters stopZ = startZ - depth prevZ = startZ currZ = max([startZ - maxCutDepth, stopZ]) done = False passCnt = 0 while not done: passCnt+=1 # Lead-in to cut depth self.addComment('pass {0} lead-in'.format(passCnt)) leadInRect = cnc_path.RectPath( point0, point1, plane='xy', helix=(prevZ,currZ) ) self.listOfCmds.extend(leadInRect.listOfCmds) # Cut filled rectangular path self.addComment('pass {0} filled rectangle'.format(passCnt)) if currZ == stopZ: passOverlap = overlapFinish else: passOverlap = overlap stepSize = toolDiam - passOverlap*toolDiam stepSize = min([stepSize, abs(x1-x0), abs(y1-y0)]) numStepX = int(math.ceil(0.5*width/stepSize)) numStepY = int(math.ceil(0.5*height/stepSize)) numStep = min([numStepX, numStepY]) if not self.param['cornerCut']: rectPath = cnc_path.FilledRectPath( point0, point1, stepSize, numStep, plane='xy' ) else: cutLen = 0.5*toolDiam*(math.sqrt(2.0) - 1.0) + cornerMargin rectPath = cnc_path.FilledRectWithCornerCutPath( point0, point1, stepSize, numStep, cutLen, plane='xy' ) self.listOfCmds.extend(rectPath.listOfCmds) # Get next z position if currZ <= stopZ: done = True else: if coolingPause is not None: self.addRapidMoveToSafeZ() self.listOfCmds.append(gcode_cmd.Dwell(coolingPause)) self.listOfCmds.append(gcode_cmd.LinearFeed(z=currZ)) prevZ = currZ currZ = max([currZ - maxCutDepth, stopZ]) self.addRapidMoveToSafeZ() self.addEndComment()
def makeListOfCmds(self): # Retreive numerical parameters and convert to float cx = float(self.param['centerX']) cy = float(self.param['centerY']) radius = abs(float(self.param['radius'])) thickness = abs(float(self.param['thickness'])) depth = abs(float(self.param['depth'])) startZ = float(self.param['startZ']) overlap = float(self.param['overlap']) try: overlapFinish = self.param['overlapFinish'] except KeyError: overlapFinish = overlap overlapFinish = float(overlapFinish) maxCutDepth = float(self.param['maxCutDepth']) toolDiam = abs(float(self.param['toolDiam'])) try: startDwell = self.param['startDwell'] except KeyError: startDwell = 0.0 startDwell = abs(float(startDwell)) # Check params if overlap < 0.0 or overlap >= 1.0: raise ValueError('overlap must >=0 and < 1') if 2*radius <= toolDiam: raise ValueError('circle diameter must be > tool diameter') if thickness > radius: raise ValueError('thickness must be <= radius') if toolDiam > thickness: raise ValueError('toolDiam must be <= thickness') # Get circle cutting parameters - assumes startAngle=0 adjustedRadius = radius - 0.5*toolDiam x0 = cx + adjustedRadius y0 = cy # Move to safe height, then to start x,y and then to start z self.addStartComment() self.addRapidMoveToSafeZ() self.addRapidMoveToPos(x=x0,y=y0,comment='start x,y') self.addDwell(startDwell) self.addMoveToStartZ() # Get z cutting parameters stopZ = startZ - depth prevZ = startZ currZ = max([startZ - maxCutDepth, stopZ]) done = False passCnt = 0 while not done: passCnt+=1 # Add lead-in self.addComment('pass {0} lead-in'.format(passCnt)) moveToStartCmd = gcode_cmd.LinearFeed(x=x0,y=y0) self.listOfCmds.append(moveToStartCmd) leadInPath = cnc_path.CircPath( (cx,cy), adjustedRadius, startAng=0, plane='xy', direction=self.param['direction'], turns=1, helix=(prevZ,currZ) ) self.listOfCmds.extend(leadInPath.listOfCmds) # Add filled circle self.addComment('pass {0} filled circle'.format(passCnt)) if currZ == stopZ: passOverlap = overlapFinish else: passOverlap = overlap if abs(toolDiam - thickness) <= FLOAT_TOLERANCE: numStep = 0 stepSize = 0.0 else: stepSizePrelim = toolDiam - passOverlap*toolDiam numStep = int(math.floor((thickness - toolDiam)/stepSizePrelim)) + 1 stepSize = (thickness -toolDiam)/float(numStep) circPath = cnc_path.FilledCircPath( (cx,cy), adjustedRadius, stepSize, numStep, startAng=0, plane='xy', direction=self.param['direction'], turns=1 ) self.listOfCmds.extend(circPath.listOfCmds) # Get next z position if currZ <= stopZ: done = True prevZ = currZ currZ = max([currZ - maxCutDepth, stopZ]) # Move to safe z and add end comment self.addRapidMoveToSafeZ() self.addEndComment()
def getFeedToStartCmd(self, plane='xy'): kx, ky = tuple(plane) feedArgs = {kx: self.startPoint[0], ky: self.startPoint[1]} return gcode_cmd.LinearFeed(**feedArgs)
def addMoveToStartZ(self): startZ = float(self.param['startZ']) self.listOfCmds.append(gcode_cmd.Space()) commentStr = '{0}: move to start z'.format(self.__class__.__name__) self.listOfCmds.append(gcode_cmd.Comment(commentStr)) self.listOfCmds.append(gcode_cmd.LinearFeed(z=startZ))