chiark / gitweb /
Add back the ultimaker platform, and made the platform mesh simpler.
[cura.git] / Cura / slice / cura_sf / skeinforge_application / skeinforge_plugins / craft_plugins / unpause.py
1 """
2 This page is in the table of contents.
3 The unpause plugin is based on the Shane Hathaway's patch to speed up a line segment to compensate for the delay of the microprocessor.  The description is at:
4 http://shane.willowrise.com/archives/delay-compensation-in-firmware/
5
6 The unpause manual page is at:
7 http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Unpause
8
9 ==Operation==
10 The default 'Activate Unpause' checkbox is off.  When it is on, the functions described below will work, when it is off, nothing will be done.
11
12 ==Settings==
13 ===Delay===
14 Default is 28 milliseconds, which Shane found for the Arduino.
15
16 Defines the delay on the microprocessor that will be at least partially compensated for.
17
18 ===Maximum Speed===
19 Default is 1.3.
20
21 Defines the maximum amount that the feed rate will be sped up to, compared to the original feed rate.
22
23 ==Examples==
24 The following examples unpause the file Screw Holder Bottom.stl.  The examples are run in a terminal in the folder which contains Screw Holder Bottom.stl and unpause.py.
25
26 > python unpause.py
27 This brings up the unpause dialog.
28
29 > python unpause.py Screw Holder Bottom.stl
30 The unpause tool is parsing the file:
31 Screw Holder Bottom.stl
32 ..
33 The unpause tool has created the file:
34 .. Screw Holder Bottom_unpause.gcode
35
36 """
37
38 from __future__ import absolute_import
39
40 from fabmetheus_utilities import archive
41 from fabmetheus_utilities import gcodec
42 from fabmetheus_utilities.fabmetheus_tools import fabmetheus_interpret
43 from fabmetheus_utilities import settings
44 from skeinforge_application.skeinforge_utilities import skeinforge_craft
45 from skeinforge_application.skeinforge_utilities import skeinforge_polyfile
46 from skeinforge_application.skeinforge_utilities import skeinforge_profile
47 import sys
48
49
50 __author__ = 'Enrique Perez (perez_enrique@yahoo.com)'
51 __date__ = '$Date: 2008/21/04 $'
52 __license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'
53
54
55 def getCraftedText( fileName, gcodeText, repository=None):
56         "Unpause a gcode linear move file or text."
57         return getCraftedTextFromText( archive.getTextIfEmpty( fileName, gcodeText ), repository )
58
59 def getCraftedTextFromText(gcodeText, repository=None):
60         "Unpause a gcode linear move text."
61         if gcodec.isProcedureDoneOrFileIsEmpty( gcodeText, 'unpause'):
62                 return gcodeText
63         if repository == None:
64                 repository = settings.getReadRepository( UnpauseRepository() )
65         if not repository.activateUnpause.value:
66                 return gcodeText
67         return UnpauseSkein().getCraftedGcode(gcodeText, repository)
68
69 def getNewRepository():
70         'Get new repository.'
71         return UnpauseRepository()
72
73 def getSelectedPlugin(repository):
74         "Get the selected plugin."
75         for plugin in repository.unpausePlugins:
76                 if plugin.value:
77                         return plugin
78         return None
79
80 def writeOutput(fileName, shouldAnalyze=True):
81         "Unpause a gcode linear move file."
82         skeinforge_craft.writeChainTextWithNounMessage(fileName, 'unpause', shouldAnalyze)
83
84
85 class UnpauseRepository(object):
86         "A class to handle the unpause settings."
87         def __init__(self):
88                 "Set the default settings, execute title & settings fileName."
89                 skeinforge_profile.addListsToCraftTypeRepository('skeinforge_application.skeinforge_plugins.craft_plugins.unpause.html', self)
90                 self.fileNameInput = settings.FileNameInput().getFromFileName( fabmetheus_interpret.getGNUTranslatorGcodeFileTypeTuples(), 'Open File for Unpause', self, '')
91                 self.openWikiManualHelpPage = settings.HelpPage().getOpenFromAbsolute('http://fabmetheus.crsndoo.com/wiki/index.php/Skeinforge_Unpause')
92                 self.activateUnpause = settings.BooleanSetting().getFromValue('Activate Unpause', self, False )
93                 self.delay = settings.FloatSpin().getFromValue( 2.0, 'Delay (milliseconds):', self, 42.0, 28.0 )
94                 self.maximumSpeed = settings.FloatSpin().getFromValue( 1.1, 'Maximum Speed (ratio):', self, 1.9, 1.3 )
95                 self.executeTitle = 'Unpause'
96
97         def execute(self):
98                 "Unpause button has been clicked."
99                 fileNames = skeinforge_polyfile.getFileOrDirectoryTypesUnmodifiedGcode(self.fileNameInput.value, fabmetheus_interpret.getImportPluginFileNames(), self.fileNameInput.wasCancelled)
100                 for fileName in fileNames:
101                         writeOutput(fileName)
102
103
104 class UnpauseSkein(object):
105         "A class to unpause a skein of extrusions."
106         def __init__(self):
107                 self.distanceFeedRate = gcodec.DistanceFeedRate()
108                 self.feedRateMinute = 959.0
109                 self.lineIndex = 0
110                 self.lines = None
111                 self.oldLocation = None
112
113         def getCraftedGcode(self, gcodeText, repository):
114                 "Parse gcode text and store the unpause gcode."
115                 self.delaySecond = repository.delay.value * 0.001
116                 self.maximumSpeed = repository.maximumSpeed.value
117                 self.minimumSpeedUpReciprocal = 1.0 / self.maximumSpeed
118                 self.repository = repository
119                 self.lines = archive.getTextLines(gcodeText)
120                 self.parseInitialization()
121                 for self.lineIndex in xrange(self.lineIndex, len(self.lines)):
122                         line = self.lines[self.lineIndex]
123                         self.parseLine(line)
124                 return self.distanceFeedRate.output.getvalue()
125
126         def getUnpausedArcMovement( self, line, splitLine ):
127                 "Get an unpaused arc movement."
128                 self.feedRateMinute = gcodec.getFeedRateMinute( self.feedRateMinute, splitLine )
129                 if self.oldLocation == None:
130                         return line
131                 relativeLocation = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine)
132                 self.oldLocation += relativeLocation
133                 distance = gcodec.getArcDistance(relativeLocation, splitLine)
134                 return self.getUnpausedMovement(distance, line, splitLine)
135
136         def getUnpausedLinearMovement( self, line, splitLine ):
137                 "Get an unpaused linear movement."
138                 self.feedRateMinute = gcodec.getFeedRateMinute( self.feedRateMinute, splitLine )
139                 location = gcodec.getLocationFromSplitLine(self.oldLocation, splitLine)
140                 if self.oldLocation == None:
141                         self.oldLocation = location
142                         return line
143                 distance = abs(self.oldLocation - location)
144                 self.oldLocation = location
145                 return self.getUnpausedMovement(distance, line, splitLine)
146
147         def getUnpausedMovement(self, distance, line, splitLine):
148                 "Get an unpaused movement."
149                 if distance <= 0.0:
150                         return line
151                 resultantReciprocal = 1.0 - self.delaySecond / distance * self.feedRateMinute / 60.0
152                 resultantReciprocal = max(self.minimumSpeedUpReciprocal, resultantReciprocal)
153                 return self.distanceFeedRate.getLineWithFeedRate(self.feedRateMinute / resultantReciprocal, line, splitLine)
154
155         def parseInitialization(self):
156                 'Parse gcode initialization and store the parameters.'
157                 for self.lineIndex in xrange(len(self.lines)):
158                         line = self.lines[self.lineIndex]
159                         splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line)
160                         firstWord = gcodec.getFirstWord(splitLine)
161                         self.distanceFeedRate.parseSplitLine(firstWord, splitLine)
162                         if firstWord == '(</extruderInitialization>)':
163                                 self.distanceFeedRate.addTagBracketedProcedure('unpause')
164                                 return
165                         self.distanceFeedRate.addLine(line)
166
167         def parseLine(self, line):
168                 "Parse a gcode line."
169                 splitLine = gcodec.getSplitLineBeforeBracketSemicolon(line)
170                 if len(splitLine) < 1:
171                         return
172                 firstWord = splitLine[0]
173                 if firstWord == 'G1':
174                         line = self.getUnpausedLinearMovement( line, splitLine )
175                 if firstWord == 'G2' or firstWord == 'G3':
176                         line = self.getUnpausedArcMovement( line, splitLine )
177                 self.distanceFeedRate.addLine(line)
178
179
180 def main():
181         "Display the unpause dialog."
182         if len(sys.argv) > 1:
183                 writeOutput(' '.join(sys.argv[1 :]))
184         else:
185                 settings.startMainLoopFromConstructor(getNewRepository())
186
187 if __name__ == "__main__":
188         main()