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 skeinforge_application.skeinforge_utilities import skeinforge_polyfile
66 from skeinforge_application.skeinforge_utilities import skeinforge_profile
71 __author__ = 'Enrique Perez (perez_enrique@yahoo.com)'
72 __date__ = '$Date: 2008/21/04 $'
73 __license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'
76 # This is true if the output is text and false if it is binary."
77 globalIsReplaceable = True
80 def getCharacterIntegerString( character, offset, splitLine, step ):
81 "Get a character and integer string."
82 floatValue = getFloatFromCharacterSplitLine(character, splitLine)
83 if floatValue == None:
86 integerValue = int(round(float(floatValue / step)))
87 return character + str( integerValue )
89 def getFloatFromCharacterSplitLine(character, splitLine):
90 "Get the float after the first occurence of the character in the split line."
91 lineFromCharacter = gcodec.getStringFromCharacterSplitLine(character, splitLine)
92 if lineFromCharacter == None:
94 return float(lineFromCharacter)
96 def getNewRepository():
98 return GcodeTimeSegmentRepository()
100 def getOutput(gcodeText, repository=None):
101 'Get the exported version of a gcode file.'
104 if repository == None:
105 repository = GcodeTimeSegmentRepository()
106 settings.getReadRepository(repository)
107 return GcodeTimeSegmentSkein().getCraftedGcode(gcodeText, repository)
109 def writeOutput( fileName, gcodeText = ''):
110 "Write the exported version of a gcode file."
111 gcodeText = gcodec.getGcodeFileText(fileName, gcodeText)
112 repository = GcodeTimeSegmentRepository()
113 settings.getReadRepository(repository)
114 output = getOutput(gcodeText, repository)
115 suffixFileName = fileName[ : fileName.rfind('.') ] + '_gcode_time_segment.gcode'
116 archive.writeFileText( suffixFileName, output )
117 print('The converted file is saved as ' + archive.getSummarizedFileName(suffixFileName) )
120 class GcodeTimeSegmentRepository:
121 "A class to handle the export settings."
123 "Set the default settings, execute title & settings fileName."
124 skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.export_plugins.gcode_time.html', self)
125 self.addSpaceBetweenWords = settings.BooleanSetting().getFromValue('Add Space Between Words', self, True )
126 self.fileNameInput = settings.FileNameInput().getFromFileName( [ ('Gcode text files', '*.gcode') ], 'Open File to be Converted to Gcode Time', self, '')
127 self.initialTime = settings.FloatSpin().getFromValue(0.0, 'Initial Time (s)', self, 20.0, 10.0)
128 settings.LabelSeparator().getFromRepository(self)
129 settings.LabelDisplay().getFromName('- Offset -', self )
130 self.xOffset = settings.FloatSpin().getFromValue( - 100.0, 'X Offset (mm)', self, 100.0, 0.0 )
131 self.yOffset = settings.FloatSpin().getFromValue( -100.0, 'Y Offset (mm)', self, 100.0, 0.0 )
132 self.zOffset = settings.FloatSpin().getFromValue( - 10.0, 'Z Offset (mm)', self, 10.0, 0.0 )
133 settings.LabelSeparator().getFromRepository(self)
134 settings.LabelDisplay().getFromName('- Step -', self )
135 self.extrusionStep = settings.FloatSpin().getFromValue(0.0, 'Extrusion Step (mm)', self, 0.2, 0.01)
136 self.timeStep = settings.FloatSpin().getFromValue(0.0, 'Time Step (mcs)', self, 2000.0, 1000.0)
137 self.xStep = settings.FloatSpin().getFromValue(0.0, 'X Step (mm)', self, 1.0, 0.1)
138 self.yStep = settings.FloatSpin().getFromValue(0.0, 'Y Step (mm)', self, 1.0, 0.1)
139 self.zStep = settings.FloatSpin().getFromValue(0.0, 'Z Step (mm)', self, 0.2, 0.01)
140 settings.LabelSeparator().getFromRepository(self)
141 self.executeTitle = 'Convert to Gcode Time'
144 "Convert to gcode step button has been clicked."
145 fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode( self.fileNameInput.value, ['.gcode'], self.fileNameInput.wasCancelled )
146 for fileName in fileNames:
147 writeOutput(fileName)
150 class GcodeTimeSegmentSkein:
151 "A class to convert gcode into time segments."
154 self.feedRateMinute = None
155 self.isExtruderActive = False
156 self.oldFeedRateString = None
157 self.oldLocation = None
158 self.oldZString = None
159 self.operatingFlowRate = None
160 self.output = cStringIO.StringIO()
162 def addCharacterInteger(self, character, lineStringIO, offset, splitLine, step):
163 "Add a character and integer to line string."
164 characterIntegerString = getCharacterIntegerString(character, offset, splitLine, step)
165 self.addStringToLine(lineStringIO, characterIntegerString)
167 def addLine(self, line):
168 "Add a line of text and a newline to the output."
169 self.output.write(line + '\n')
171 def addStringToLine( self, lineStringIO, wordString ):
172 "Add a character and integer to line string."
173 if wordString == None:
175 if self.repository.addSpaceBetweenWords.value:
176 lineStringIO.write(' ')
177 lineStringIO.write( wordString )
179 def getCraftedGcode(self, gcodeText, repository):
180 "Parse gcode text and store the gcode."
181 self.repository = repository
182 lines = archive.getTextLines(gcodeText)
185 return self.output.getvalue()
187 def parseLine(self, line):
188 "Parse a gcode line."
189 splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line)
190 firstWord = gcodec.getFirstWord(splitLine)
191 if len(firstWord) < 1:
193 firstLetter = firstWord[0]
194 if firstWord == '(<operatingFeedRatePerSecond>':
195 self.feedRateMinute = 60.0 * float(splitLine[1])
196 elif firstWord == '(<operatingFlowRate>':
197 self.operatingFlowRate = float(splitLine[1])
198 self.flowRate = self.operatingFlowRate
199 if firstLetter == '(':
201 if firstWord == 'M101':
202 self.isExtruderActive = True
203 elif firstWord == 'M103':
204 self.isExtruderActive = False
205 elif firstWord == 'M108':
206 self.flowRate = float(splitLine[1][1 :])
207 if firstWord != 'G1' and firstWord != 'G2' and firstWord != 'G3':
210 self.feedRateMinute = gcodec.getFeedRateMinute(self.feedRateMinute, splitLine)
211 lineStringIO = cStringIO.StringIO()
212 lineStringIO.write(firstWord)
213 location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine)
214 self.addCharacterInteger('X', lineStringIO, self.repository.xOffset.value, splitLine, self.repository.xStep.value )
215 self.addCharacterInteger('Y', lineStringIO, self.repository.yOffset.value, splitLine, self.repository.yStep.value )
216 zString = getCharacterIntegerString('Z', self.repository.zOffset.value, splitLine, self.repository.zStep.value )
218 zString = self.oldZString
219 self.addStringToLine(lineStringIO, zString)
220 duration = self.repository.initialTime.value
221 if self.oldLocation != None:
222 distance = abs(location - self.oldLocation)
223 duration = 60.0 / self.feedRateMinute * distance
224 extrusionDistance = 0.0
225 if self.isExtruderActive:
226 extrusionDistance = self.flowRate * duration
227 self.addStringToLine(lineStringIO, 'E%s' % int(round(extrusionDistance / self.repository.extrusionStep.value)))
228 self.addStringToLine(lineStringIO, 'D%s' % int(round(duration * 1000000.0 / self.repository.timeStep.value)))
229 self.addLine(lineStringIO.getvalue())
230 self.oldLocation = location
231 self.oldZString = zString
235 "Display the export dialog."
236 if len(sys.argv) > 1:
237 writeOutput(' '.join(sys.argv[1 :]))
239 settings.startMainLoopFromConstructor(getNewRepository())
241 if __name__ == "__main__":