2 This page is in the table of contents.
3 Gcode step 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. The writeOutput function of this script takes a gcode text and writes that with the positions converted into number of steps.
10 ===Add Feed Rate Even When Unchanging===
13 When selected, the feed rate will be added even when it did not change from the previous line.
15 ===Add Space Between Words===
18 When selected, a space will be added between each gcode word.
20 ===Add Z Even When Unchanging===
23 When selected, the z word will be added even when it did not change.
25 ===Feed Rate Step Length===
26 Default is 0.1 millimeters/second.
28 Defines the feed rate step length.
48 Default is 0.1 millimeters.
50 Defines the E extrusion distance step length.
52 ===Radius Rate Step Length===
53 Default is 0.1 millimeters/second.
55 Defines the radius step length.
58 Default is 0.1 millimeters.
60 Defines the X axis step length.
63 Default is 0.1 millimeters.
65 Defines the Y axis step length.
68 Default is 0.01 millimeters.
70 Defines the Z axis step length.
75 from __future__ import absolute_import
77 from fabmetheus_utilities import archive
78 from fabmetheus_utilities import gcodec
79 from fabmetheus_utilities import settings
80 from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret
81 from skeinforge_application.skeinforge_utilities import skeinforge_polyfile
82 from skeinforge_application.skeinforge_utilities import skeinforge_profile
83 from struct import Struct
89 __author__ = 'Enrique Perez (perez_enrique@yahoo.com)'
90 __date__ = '$Date: 2008/21/04 $'
91 __license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'
94 # This is true if the output is text and false if it is binary.
95 globalIsReplaceable = True
98 def getCharacterIntegerString(character, offset, splitLine, stepLength):
99 'Get a character and integer string.'
100 floatValue = getFloatFromCharacterSplitLine(character, splitLine)
101 if floatValue == None:
104 integerValue = int(round(float(floatValue / stepLength)))
105 return character + str(integerValue)
107 def getFloatFromCharacterSplitLine(character, splitLine):
108 'Get the float after the first occurence of the character in the split line.'
109 lineFromCharacter = gcodec.getStringFromCharacterSplitLine(character, splitLine)
110 if lineFromCharacter == None:
112 return float(lineFromCharacter)
114 def getNewRepository():
115 'Get new repository.'
116 return GcodeStepRepository()
118 def getOutput(gcodeText, repository=None):
119 'Get the exported version of a gcode file.'
122 if repository == None:
123 repository = GcodeStepRepository()
124 settings.getReadRepository(repository)
125 return GcodeStepSkein().getCraftedGcode(repository, gcodeText)
127 def writeOutput( fileName, gcodeText = ''):
128 'Write the exported version of a gcode file.'
129 gcodeText = gcodec.getGcodeFileText(fileName, gcodeText)
130 repository = GcodeStepRepository()
131 settings.getReadRepository(repository)
132 output = getOutput(gcodeText, repository)
133 suffixFileName = fileName[: fileName.rfind('.')] + '_gcode_step.gcode'
134 archive.writeFileText(suffixFileName, output)
135 print('The converted file is saved as ' + archive.getSummarizedFileName(suffixFileName))
138 class GcodeStepRepository:
139 'A class to handle the export settings.'
141 'Set the default settings, execute title & settings fileName.'
142 skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.export_plugins.gcode_step.html', self)
143 self.addFeedRateEvenWhenUnchanging = settings.BooleanSetting().getFromValue('Add Feed Rate Even When Unchanging', self, True)
144 self.addSpaceBetweenWords = settings.BooleanSetting().getFromValue('Add Space Between Words', self, True)
145 self.addZEvenWhenUnchanging = settings.BooleanSetting().getFromValue('Add Z Even When Unchanging', self, True)
146 self.fileNameInput = settings.FileNameInput().getFromFileName([('Gcode text files', '*.gcode')], 'Open File to be Converted to Gcode Step', self, '')
147 self.feedRateStepLength = settings.FloatSpin().getFromValue(0.0, 'Feed Rate Step Length (millimeters/second)', self, 1.0, 0.1)
148 settings.LabelSeparator().getFromRepository(self)
149 settings.LabelDisplay().getFromName('- Offset -', self )
150 self.xOffset = settings.FloatSpin().getFromValue(-100.0, 'X Offset (millimeters)', self, 100.0, 0.0)
151 self.yOffset = settings.FloatSpin().getFromValue(-100.0, 'Y Offset (millimeters)', self, 100.0, 0.0)
152 self.zOffset = settings.FloatSpin().getFromValue(-10.0, 'Z Offset (millimeters)', self, 10.0, 0.0)
153 settings.LabelSeparator().getFromRepository(self)
154 settings.LabelDisplay().getFromName('- Step Length -', self )
155 self.eStepLength = settings.FloatSpin().getFromValue(0.0, 'E Step Length (float)', self, 1.0, 0.1)
156 self.radiusStepLength = settings.FloatSpin().getFromValue(0.0, 'Radius Step Length (millimeters)', self, 1.0, 0.1)
157 self.xStepLength = settings.FloatSpin().getFromValue(0.0, 'X Step Length (millimeters)', self, 1.0, 0.1)
158 self.yStepLength = settings.FloatSpin().getFromValue(0.0, 'Y Step Length (millimeters)', self, 1.0, 0.1)
159 self.zStepLength = settings.FloatSpin().getFromValue(0.0, 'Z Step Length (millimeters)', self, 0.2, 0.01)
160 self.executeTitle = 'Convert to Gcode Step'
163 'Convert to gcode step button has been clicked.'
164 fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, ['.gcode'], self.fileNameInput.wasCancelled)
165 for fileName in fileNames:
166 writeOutput(fileName)
169 class GcodeStepSkein:
170 'A class to convert gcode into 16 byte binary segments.'
172 self.oldFeedRateString = None
173 self.oldZString = None
174 self.output = cStringIO.StringIO()
176 def addCharacterInteger(self, character, lineStringIO, offset, splitLine, stepLength):
177 'Add a character and integer to line string.'
178 characterIntegerString = getCharacterIntegerString(character, offset, splitLine, stepLength)
179 self.addStringToLine(lineStringIO, characterIntegerString)
181 def addLine(self, line):
182 'Add a line of text and a newline to the output.'
183 self.output.write(line + '\n')
185 def addStringToLine(self, lineStringIO, wordString):
186 'Add a character and integer to line string.'
189 if self.repository.addSpaceBetweenWords.value:
190 lineStringIO.write(' ')
191 lineStringIO.write(wordString)
193 def getCraftedGcode(self, repository, gcodeText):
194 'Parse gcode text and store the gcode.'
195 self.repository = repository
196 lines = archive.getTextLines(gcodeText)
199 return self.output.getvalue()
201 def parseLine(self, line):
202 'Parse a gcode line.'
203 splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line)
204 firstWord = gcodec.getFirstWord(splitLine)
205 if len(firstWord) < 1:
207 firstLetter = firstWord[0]
208 if firstLetter == '(':
210 if firstWord != 'G1' and firstWord != 'G2' and firstWord != 'G3':
213 lineStringIO = cStringIO.StringIO()
214 lineStringIO.write(firstWord)
215 self.addCharacterInteger('I', lineStringIO, 0.0, splitLine, self.repository.xStepLength.value)
216 self.addCharacterInteger('J', lineStringIO, 0.0, splitLine, self.repository.yStepLength.value)
217 self.addCharacterInteger('R', lineStringIO, 0.0, splitLine, self.repository.radiusStepLength.value)
218 self.addCharacterInteger('X', lineStringIO, self.repository.xOffset.value, splitLine, self.repository.xStepLength.value)
219 self.addCharacterInteger('Y', lineStringIO, self.repository.yOffset.value, splitLine, self.repository.yStepLength.value)
220 zString = getCharacterIntegerString('Z', self.repository.zOffset.value, splitLine, self.repository.zStepLength.value)
221 feedRateString = getCharacterIntegerString('F', 0.0, splitLine, self.repository.feedRateStepLength.value)
223 if zString != self.oldZString or self.repository.addZEvenWhenUnchanging.value:
224 self.addStringToLine(lineStringIO, zString)
225 if feedRateString != '':
226 if feedRateString != self.oldFeedRateString or self.repository.addFeedRateEvenWhenUnchanging.value:
227 self.addStringToLine(lineStringIO, feedRateString)
228 self.addCharacterInteger('E', lineStringIO, 0.0, splitLine, self.repository.eStepLength.value)
229 self.addLine(lineStringIO.getvalue())
230 self.oldFeedRateString = feedRateString
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__':