2 This page is in the table of contents.
3 Gcode time segment is an export plugin to convert gcode from float position to number of steps.
5 An export plugin is a script in the export_plugins folder which has the getOutput function, the globalIsReplaceable variable and if it's output is not replaceable, the writeOutput function. It is meant to be run from the export tool. To ensure that the plugin works on platforms which do not handle file capitalization properly, give the plugin a lower case name.
7 The getOutput function of this script takes a gcode text and returns it with the positions converted into number of steps and time. The writeOutput function of this script takes a gcode text and writes that with the positions converted into number of steps and time.
10 ===Add Space Between Words===
13 When selected, a space will be added between each gcode word.
35 Defines the radius step length.
38 Default is 1 microsecond(mcs).
40 Defines the time step duration.
45 Defines the X axis step length.
50 Defines the Y axis step length.
55 Defines the Z axis step length.
60 from __future__ import absolute_import
62 from fabmetheus_utilities import archive
63 from fabmetheus_utilities import gcodec
64 from fabmetheus_utilities import settings
65 from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret
66 from skeinforge_application.skeinforge_utilities import skeinforge_polyfile
67 from skeinforge_application.skeinforge_utilities import skeinforge_profile
68 from struct import Struct
74 __author__ = 'Enrique Perez (perez_enrique@yahoo.com)'
75 __date__ = '$Date: 2008/21/04 $'
76 __license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'
79 # This is true if the output is text and false if it is binary."
80 globalIsReplaceable = True
83 def getCharacterIntegerString( character, offset, splitLine, step ):
84 "Get a character and integer string."
85 floatValue = getFloatFromCharacterSplitLine(character, splitLine)
86 if floatValue == None:
89 integerValue = int(round(float(floatValue / step)))
90 return character + str( integerValue )
92 def getFloatFromCharacterSplitLine(character, splitLine):
93 "Get the float after the first occurence of the character in the split line."
94 lineFromCharacter = gcodec.getStringFromCharacterSplitLine(character, splitLine)
95 if lineFromCharacter == None:
97 return float(lineFromCharacter)
99 def getNewRepository():
100 'Get new repository.'
101 return GcodeTimeSegmentRepository()
103 def getOutput(gcodeText, repository=None):
104 'Get the exported version of a gcode file.'
107 if repository == None:
108 repository = GcodeTimeSegmentRepository()
109 settings.getReadRepository(repository)
110 return GcodeTimeSegmentSkein().getCraftedGcode(gcodeText, repository)
112 def writeOutput( fileName, gcodeText = ''):
113 "Write the exported version of a gcode file."
114 gcodeText = gcodec.getGcodeFileText(fileName, gcodeText)
115 repository = GcodeTimeSegmentRepository()
116 settings.getReadRepository(repository)
117 output = getOutput(gcodeText, repository)
118 suffixFileName = fileName[ : fileName.rfind('.') ] + '_gcode_time_segment.gcode'
119 archive.writeFileText( suffixFileName, output )
120 print('The converted file is saved as ' + archive.getSummarizedFileName(suffixFileName) )
123 class GcodeTimeSegmentRepository:
124 "A class to handle the export settings."
126 "Set the default settings, execute title & settings fileName."
127 skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.export_plugins.gcode_time.html', self)
128 self.addSpaceBetweenWords = settings.BooleanSetting().getFromValue('Add Space Between Words', self, True )
129 self.fileNameInput = settings.FileNameInput().getFromFileName( [ ('Gcode text files', '*.gcode') ], 'Open File to be Converted to Gcode Time', self, '')
130 self.initialTime = settings.FloatSpin().getFromValue(0.0, 'Initial Time (s)', self, 20.0, 10.0)
131 settings.LabelSeparator().getFromRepository(self)
132 settings.LabelDisplay().getFromName('- Offset -', self )
133 self.xOffset = settings.FloatSpin().getFromValue( - 100.0, 'X Offset (mm)', self, 100.0, 0.0 )
134 self.yOffset = settings.FloatSpin().getFromValue( -100.0, 'Y Offset (mm)', self, 100.0, 0.0 )
135 self.zOffset = settings.FloatSpin().getFromValue( - 10.0, 'Z Offset (mm)', self, 10.0, 0.0 )
136 settings.LabelSeparator().getFromRepository(self)
137 settings.LabelDisplay().getFromName('- Step -', self )
138 self.extrusionStep = settings.FloatSpin().getFromValue(0.0, 'Extrusion Step (mm)', self, 0.2, 0.01)
139 self.timeStep = settings.FloatSpin().getFromValue(0.0, 'Time Step (mcs)', self, 2000.0, 1000.0)
140 self.xStep = settings.FloatSpin().getFromValue(0.0, 'X Step (mm)', self, 1.0, 0.1)
141 self.yStep = settings.FloatSpin().getFromValue(0.0, 'Y Step (mm)', self, 1.0, 0.1)
142 self.zStep = settings.FloatSpin().getFromValue(0.0, 'Z Step (mm)', self, 0.2, 0.01)
143 settings.LabelSeparator().getFromRepository(self)
144 self.executeTitle = 'Convert to Gcode Time'
147 "Convert to gcode step button has been clicked."
148 fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode( self.fileNameInput.value, ['.gcode'], self.fileNameInput.wasCancelled )
149 for fileName in fileNames:
150 writeOutput(fileName)
153 class GcodeTimeSegmentSkein:
154 "A class to convert gcode into time segments."
157 self.feedRateMinute = None
158 self.isExtruderActive = False
159 self.oldFeedRateString = None
160 self.oldLocation = None
161 self.oldZString = None
162 self.operatingFlowRate = None
163 self.output = cStringIO.StringIO()
165 def addCharacterInteger(self, character, lineStringIO, offset, splitLine, step):
166 "Add a character and integer to line string."
167 characterIntegerString = getCharacterIntegerString(character, offset, splitLine, step)
168 self.addStringToLine(lineStringIO, characterIntegerString)
170 def addLine(self, line):
171 "Add a line of text and a newline to the output."
172 self.output.write(line + '\n')
174 def addStringToLine( self, lineStringIO, wordString ):
175 "Add a character and integer to line string."
176 if wordString == None:
178 if self.repository.addSpaceBetweenWords.value:
179 lineStringIO.write(' ')
180 lineStringIO.write( wordString )
182 def getCraftedGcode(self, gcodeText, repository):
183 "Parse gcode text and store the gcode."
184 self.repository = repository
185 lines = archive.getTextLines(gcodeText)
188 return self.output.getvalue()
190 def parseLine(self, line):
191 "Parse a gcode line."
192 splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line)
193 firstWord = gcodec.getFirstWord(splitLine)
194 if len(firstWord) < 1:
196 firstLetter = firstWord[0]
197 if firstWord == '(<operatingFeedRatePerSecond>':
198 self.feedRateMinute = 60.0 * float(splitLine[1])
199 elif firstWord == '(<operatingFlowRate>':
200 self.operatingFlowRate = float(splitLine[1])
201 self.flowRate = self.operatingFlowRate
202 if firstLetter == '(':
204 if firstWord == 'M101':
205 self.isExtruderActive = True
206 elif firstWord == 'M103':
207 self.isExtruderActive = False
208 elif firstWord == 'M108':
209 self.flowRate = float(splitLine[1][1 :])
210 if firstWord != 'G1' and firstWord != 'G2' and firstWord != 'G3':
213 self.feedRateMinute = gcodec.getFeedRateMinute(self.feedRateMinute, splitLine)
214 lineStringIO = cStringIO.StringIO()
215 lineStringIO.write(firstWord)
216 location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine)
217 self.addCharacterInteger('X', lineStringIO, self.repository.xOffset.value, splitLine, self.repository.xStep.value )
218 self.addCharacterInteger('Y', lineStringIO, self.repository.yOffset.value, splitLine, self.repository.yStep.value )
219 zString = getCharacterIntegerString('Z', self.repository.zOffset.value, splitLine, self.repository.zStep.value )
221 zString = self.oldZString
222 self.addStringToLine(lineStringIO, zString)
223 duration = self.repository.initialTime.value
224 if self.oldLocation != None:
225 distance = abs(location - self.oldLocation)
226 duration = 60.0 / self.feedRateMinute * distance
227 extrusionDistance = 0.0
228 if self.isExtruderActive:
229 extrusionDistance = self.flowRate * duration
230 self.addStringToLine(lineStringIO, 'E%s' % int(round(extrusionDistance / self.repository.extrusionStep.value)))
231 self.addStringToLine(lineStringIO, 'D%s' % int(round(duration * 1000000.0 / self.repository.timeStep.value)))
232 self.addLine(lineStringIO.getvalue())
233 self.oldLocation = location
234 self.oldZString = zString
238 "Display the export dialog."
239 if len(sys.argv) > 1:
240 writeOutput(' '.join(sys.argv[1 :]))
242 settings.startMainLoopFromConstructor(getNewRepository())
244 if __name__ == "__main__":