X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=Cura%2Futil%2FgcodeInterpreter.py;h=1a9ee094916fa39adc62674f2a6dd331025b0816;hb=6208201bafdeaf82883181471c6da3a41283cfe7;hp=5348c3cef010ff5fd0d19804b70d6720bc4e9134;hpb=6c884c5cbb2c02570165d1b39ebc1578be71551f;p=cura.git diff --git a/Cura/util/gcodeInterpreter.py b/Cura/util/gcodeInterpreter.py index 5348c3ce..1a9ee094 100644 --- a/Cura/util/gcodeInterpreter.py +++ b/Cura/util/gcodeInterpreter.py @@ -1,38 +1,45 @@ from __future__ import absolute_import +__copyright__ = "Copyright (C) 2013 David Braam - Released under terms of the AGPLv3 License" import sys import math import os import time +import numpy +import types +import cStringIO as StringIO from Cura.util import profile -class gcodePath(object): - def __init__(self, newType, pathType, layerThickness, startPoint): - self.type = newType - self.pathType = pathType - self.layerThickness = layerThickness - self.points = [startPoint] - self.extrusion = [0] +def gcodePath(newType, pathType, layerThickness, startPoint): + return {'type': newType, + 'pathType': pathType, + 'layerThickness': layerThickness, + 'points': [startPoint], + 'extrusion': [0.0]} class gcode(object): def __init__(self): self.regMatch = {} - self.layerList = [] + self.layerList = None self.extrusionAmount = 0 - self.totalMoveTimeMinute = 0 + self.filename = None self.progressCallback = None - def load(self, filename): - if os.path.isfile(filename): - self._fileSize = os.stat(filename).st_size - gcodeFile = open(filename, 'r') + def load(self, data): + self.filename = None + if type(data) in types.StringTypes and os.path.isfile(data): + self.filename = data + self._fileSize = os.stat(data).st_size + gcodeFile = open(data, 'r') self._load(gcodeFile) gcodeFile.close() - - def loadList(self, l): - self._load(l) - + elif type(data) is list: + self._load(data) + else: + self._fileSize = len(data.getvalue()) + self._load(StringIO.StringIO(data.getvalue())) + def calculateWeight(self): #Calculates the weight of the filament in kg radius = float(profile.getProfileSetting('filament_diameter')) / 2 @@ -51,23 +58,22 @@ class gcode(object): return None def _load(self, gcodeFile): - pos = [0.0, 0.0, 0.0] + self.layerList = [] + pos = [0.0,0.0,0.0] posOffset = [0.0, 0.0, 0.0] currentE = 0.0 - totalExtrusion = 0.0 - maxExtrusion = 0.0 currentExtruder = 0 extrudeAmountMultiply = 1.0 - totalMoveTimeMinute = 0.0 absoluteE = True scale = 1.0 posAbs = True feedRate = 3600.0 + moveType = 'move' layerThickness = 0.1 - pathType = 'CUSTOM'; + pathType = 'CUSTOM' currentLayer = [] - currentPath = gcodePath('move', pathType, layerThickness, pos[:]) - currentPath.extruder = currentExtruder + currentPath = gcodePath('move', pathType, layerThickness, pos) + currentPath['extruder'] = currentExtruder currentLayer.append(currentPath) for line in gcodeFile: @@ -88,23 +94,28 @@ class gcode(object): elif comment == 'skirt': pathType = 'SKIRT' if comment.startswith('LAYER:'): + currentPath = gcodePath(moveType, pathType, layerThickness, currentPath['points'][-1]) + currentPath['extruder'] = currentExtruder + for path in currentLayer: + path['points'] = numpy.array(path['points'], numpy.float32) + path['extrusion'] = numpy.array(path['extrusion'], numpy.float32) self.layerList.append(currentLayer) if self.progressCallback is not None: if self.progressCallback(float(gcodeFile.tell()) / float(self._fileSize)): #Abort the loading, we can safely return as the results here will be discarded gcodeFile.close() return - currentLayer = [] + currentLayer = [currentPath] line = line[0:line.find(';')] T = getCodeInt(line, 'T') if T is not None: if currentExtruder > 0: - posOffset[0] -= profile.getPreferenceFloat('extruder_offset_x%d' % (currentExtruder)) - posOffset[1] -= profile.getPreferenceFloat('extruder_offset_y%d' % (currentExtruder)) + posOffset[0] -= profile.getMachineSettingFloat('extruder_offset_x%d' % (currentExtruder)) + posOffset[1] -= profile.getMachineSettingFloat('extruder_offset_y%d' % (currentExtruder)) currentExtruder = T if currentExtruder > 0: - posOffset[0] += profile.getPreferenceFloat('extruder_offset_x%d' % (currentExtruder)) - posOffset[1] += profile.getPreferenceFloat('extruder_offset_y%d' % (currentExtruder)) + posOffset[0] += profile.getMachineSettingFloat('extruder_offset_x%d' % (currentExtruder)) + posOffset[1] += profile.getMachineSettingFloat('extruder_offset_y%d' % (currentExtruder)) G = getCodeInt(line, 'G') if G is not None: @@ -113,8 +124,9 @@ class gcode(object): y = getCodeFloat(line, 'Y') z = getCodeFloat(line, 'Z') e = getCodeFloat(line, 'E') - f = getCodeFloat(line, 'F') - oldPos = pos[:] + #f = getCodeFloat(line, 'F') + oldPos = pos + pos = pos[:] if posAbs: if x is not None: pos[0] = x * scale + posOffset[0] @@ -129,44 +141,38 @@ class gcode(object): pos[1] += y * scale if z is not None: pos[2] += z * scale - if f is not None: - feedRate = f - #if x is not None or y is not None or z is not None: - # diffX = oldPos[0] - pos[0] - # diffY = oldPos[1] - pos[1] - # totalMoveTimeMinute += math.sqrt(diffX * diffX + diffY * diffY) / feedRate moveType = 'move' if e is not None: if absoluteE: e -= currentE - if e > 0: + if e > 0.0: moveType = 'extrude' - if e < 0: + if e < 0.0: moveType = 'retract' - totalExtrusion += e currentE += e - if totalExtrusion > maxExtrusion: - maxExtrusion = totalExtrusion else: e = 0.0 if moveType == 'move' and oldPos[2] != pos[2]: if oldPos[2] > pos[2] and abs(oldPos[2] - pos[2]) > 5.0 and pos[2] < 1.0: oldPos[2] = 0.0 layerThickness = abs(oldPos[2] - pos[2]) - if currentPath.type != moveType or currentPath.pathType != pathType: - currentPath = gcodePath(moveType, pathType, layerThickness, currentPath.points[-1]) - currentPath.extruder = currentExtruder + if currentPath['type'] != moveType or currentPath['pathType'] != pathType: + currentPath = gcodePath(moveType, pathType, layerThickness, currentPath['points'][-1]) + currentPath['extruder'] = currentExtruder currentLayer.append(currentPath) - currentPath.points.append(pos[:]) - currentPath.extrusion.append(e * extrudeAmountMultiply) + currentPath['points'].append(pos) + currentPath['extrusion'].append(e * extrudeAmountMultiply) elif G == 4: #Delay S = getCodeFloat(line, 'S') - if S is not None: - totalMoveTimeMinute += S / 60.0 P = getCodeFloat(line, 'P') - if P is not None: - totalMoveTimeMinute += P / 60.0 / 1000.0 + elif G == 10: #Retract + currentPath = gcodePath('retract', pathType, layerThickness, currentPath['points'][-1]) + currentPath['extruder'] = currentExtruder + currentLayer.append(currentPath) + currentPath['points'].append(currentPath['points'][0]) + elif G == 11: #Push back after retract + pass elif G == 20: #Units are inches scale = 25.4 elif G == 21: #Units are mm @@ -175,15 +181,17 @@ class gcode(object): x = getCodeFloat(line, 'X') y = getCodeFloat(line, 'Y') z = getCodeFloat(line, 'Z') + center = [0.0,0.0,0.0] if x is None and y is None and z is None: - pos = [0.0,0.0,0.0] + pos = center else: + pos = pos[:] if x is not None: - pos[0] = 0.0 + pos[0] = center[0] if y is not None: - pos[0] = 0.0 + pos[1] = center[1] if z is not None: - pos[0] = 0.0 + pos[2] = center[2] elif G == 90: #Absolute position posAbs = True elif G == 91: #Relative position @@ -210,6 +218,8 @@ class gcode(object): pass elif M == 1: #Message with possible wait (ignored) pass + elif M == 25: #Stop SD printing + pass elif M == 80: #Enable power supply pass elif M == 81: #Suicide/disable power supply @@ -254,13 +264,12 @@ class gcode(object): extrudeAmountMultiply = s / 100.0 else: print "Unknown M code:" + str(M) + for path in currentLayer: + path['points'] = numpy.array(path['points'], numpy.float32) + path['extrusion'] = numpy.array(path['extrusion'], numpy.float32) self.layerList.append(currentLayer) if self.progressCallback is not None and self._fileSize > 0: self.progressCallback(float(gcodeFile.tell()) / float(self._fileSize)) - self.extrusionAmount = maxExtrusion - self.totalMoveTimeMinute = totalMoveTimeMinute - #print "Extruded a total of: %d mm of filament" % (self.extrusionAmount) - #print "Estimated print duration: %.2f minutes" % (self.totalMoveTimeMinute) def getCodeInt(line, code): n = line.find(code) + 1 @@ -291,6 +300,5 @@ if __name__ == '__main__': for filename in sys.argv[1:]: g = gcode() g.load(filename) - print g.totalMoveTimeMinute print time.time() - t