PageRenderTime 55ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/skein_engines/skeinforge-33/fabmetheus_utilities/miscellaneous/fabricate/extrude.py

https://github.com/josefprusa/ReplicatorG-Erik5D
Python | 390 lines | 378 code | 5 blank | 7 comment | 2 complexity | f202f6f8c8df4e56c01632aad62f2364 MD5 | raw file
  1. """
  2. Extrude is a script to display and extrude a gcode file.
  3. It controls the extruder and movement. It can read linear and helical move commands. It saves a log file with the suffix _log.
  4. To run extrude, install python 2.x on your machine, which is avaliable from http://www.python.org/download/
  5. Then in the folder which extrude is in, type 'python' in a shell to run the python interpreter. Finally type 'import extrude' to import
  6. this program. Extrude requires pySerial installed for this module to work. If you are using Fedora it is available on yum
  7. (run "sudo yum install pyserial"). To actually control the reprap requires write access to the serial device, running as root is
  8. one way to get that access.
  9. This example displays and extrudes a gcode file. This example is run in a terminal as root in the folder which contains
  10. Hollow Square.gcode, and extrude.py.
  11. >>> import extrude
  12. Extrude has been imported.
  13. The gcode files in this directory that are not log files are the following:
  14. ['Hollow Square.gcode']
  15. >>> extrude.display()
  16. File Hollow Square.gcode is being displayed.
  17. reprap.serial = serial.Serial(0, 19200, timeout = 60)
  18. reprap.cartesian.x.active = True
  19. reprap.cartesian.y.active = True
  20. reprap.cartesian.z.active = True
  21. reprap.extruder.active = True
  22. reprap.cartesian.x.setNotify()
  23. reprap.cartesian.y.setNotify()
  24. reprap.cartesian.z.setNotify()
  25. reprap.cartesian.x.limit = 2523
  26. reprap.cartesian.y.limit = 2000
  27. reprap.cartesian.homeReset( 200, True )
  28. ( GCode generated by March 29,2007 Skeinforge )
  29. ( Extruder Initialization )
  30. M100 P210
  31. M103
  32. reprap.extruder.setMotor(reprap.CMD_REVERSE, 0)
  33. ..
  34. many lines of gcode and extruder commands
  35. ..
  36. reprap.cartesian.homeReset( 600, True )
  37. reprap.cartesian.free()
  38. The gcode log file is saved as Hollow Square_log.gcode
  39. >>> extrude.displayFile("Hollow Square.gcode")
  40. File Hollow Square.gcode is being displayed.
  41. ..
  42. The gcode log file is saved as Hollow Square_log.gcode
  43. >>> extrude.displayFiles(["Hollow Square.gcode"])
  44. File Hollow Square.gcode is being displayed.
  45. ..
  46. The gcode log file is saved as Hollow Square_log.gcode
  47. >>> extrude.displayText("
  48. ( GCode generated by March 29,2007 Skeinforge )
  49. ( Extruder Initialization )
  50. ..
  51. many lines of gcode
  52. ..
  53. ")
  54. reprap.serial = serial.Serial(0, 19200, timeout = 60)
  55. reprap.cartesian.x.active = True
  56. reprap.cartesian.y.active = True
  57. reprap.cartesian.z.active = True
  58. reprap.extruder.active = True
  59. reprap.cartesian.x.setNotify()
  60. reprap.cartesian.y.setNotify()
  61. reprap.cartesian.z.setNotify()
  62. reprap.cartesian.x.limit = 2523
  63. reprap.cartesian.y.limit = 2000
  64. reprap.cartesian.homeReset( 200, True )
  65. ( GCode generated by March 29,2007 Skeinforge )
  66. ( Extruder Initialization )
  67. M100 P210
  68. M103
  69. reprap.extruder.setMotor(reprap.CMD_REVERSE, 0)
  70. ..
  71. many lines of gcode and extruder commands
  72. ..
  73. reprap.cartesian.homeReset( 600, True )
  74. reprap.cartesian.free()
  75. Note: On my system the reprap is not connected, so I get can not connect messages, like:
  76. >>> extrude.extrude()
  77. File Hollow Square.gcode is being extruded.
  78. reprap.serial = serial.Serial(0, 19200, timeout = 60)
  79. reprap.cartesian.x.active = True
  80. reprap.cartesian.y.active = True
  81. reprap.cartesian.z.active = True
  82. reprap.extruder.active = True
  83. reprap.cartesian.x.setNotify()
  84. Error: Serial timeout
  85. Error: ACK not recieved
  86. ..
  87. On a system where a reprap is connected to the serial port, you should get the following:
  88. >>> extrude.extrude()
  89. File Hollow Square.gcode is being extruded.
  90. ..
  91. The gcode log file is saved as Hollow Square_log.gcode
  92. >>> extrude.extrudeFile("Hollow Square.gcode")
  93. File Hollow Square.gcode is being extruded.
  94. ..
  95. The gcode log file is saved as Hollow Square_log.gcode
  96. >>> extrude.extrudeFiles(["Hollow Square.gcode"])
  97. File Hollow Square.gcode is being extruded.
  98. ..
  99. The gcode log file is saved as Hollow Square_log.gcode
  100. >>> extrude.extrudeText("
  101. ( GCode generated by March 29,2007 Skeinforge )
  102. ( Extruder Initialization )
  103. ..
  104. many lines of gcode
  105. ..
  106. ")
  107. reprap.serial = serial.Serial(0, 19200, timeout = 60)
  108. reprap.cartesian.x.active = True
  109. reprap.cartesian.y.active = True
  110. reprap.cartesian.z.active = True
  111. reprap.extruder.active = True
  112. reprap.cartesian.x.setNotify()
  113. reprap.cartesian.y.setNotify()
  114. reprap.cartesian.z.setNotify()
  115. reprap.cartesian.x.limit = 2523
  116. reprap.cartesian.y.limit = 2000
  117. reprap.cartesian.homeReset( 200, True )
  118. ( GCode generated by March 29,2007 Skeinforge )
  119. ( Extruder Initialization )
  120. M100 P210
  121. M103
  122. reprap.extruder.setMotor(reprap.CMD_REVERSE, 0)
  123. ..
  124. many lines of gcode and extruder commands
  125. ..
  126. reprap.cartesian.homeReset( 600, True )
  127. reprap.cartesian.free()
  128. """
  129. from __future__ import absolute_import
  130. #Init has to be imported first because it has code to workaround the python bug where relative imports don't work if the module is imported as a main module.
  131. import __init__
  132. try:
  133. import serial # Import the pySerial modules.
  134. except:
  135. print('You do not have pySerial installed, which is needed to control the serial port.')
  136. print('Information on pySerial is at:\nhttp://pyserial.wiki.sourceforge.net/pySerial')
  137. from skeinforge_tools.skeinforge_utilities.vector3 import Vector3
  138. from skeinforge_tools.skeinforge_utilities import archive
  139. from skeinforge_tools.skeinforge_utilities import euclidean
  140. from skeinforge_tools.skeinforge_utilities import gcodec
  141. import math
  142. import os
  143. import reprap # Import the reprap module.
  144. import time
  145. __author__ = 'Enrique Perez (perez_enrique@yahoo.com)'
  146. __credits__ = 'greenarrow <http://forums.reprap.org/profile.php?12,81>'
  147. __date__ = '$Date: 2008/21/04 $'
  148. __license__ = 'GPL 3.0'
  149. def display( filename = ''):
  150. "Parse a gcode file and display the commands. If no filename is specified, parse all the gcode files which are not log files in this folder."
  151. if filename == '':
  152. displayFiles( getGCodeFilesWhichAreNotLogFiles() )
  153. return
  154. displayFile( filename )
  155. def displayFile( filename ):
  156. "Parse a gcode file and display the commands."
  157. print('File ' + filename + ' is being displayed.')
  158. fileText = archive.getFileText( filename )
  159. gcodec.writeFileMessageSuffix( filename, displayText(fileText), 'The gcode log file is saved as ', '_log')
  160. def displayFiles( filenames ):
  161. "Parse gcode files and display the commands."
  162. for filename in filenames:
  163. displayFile( filename )
  164. def displayText(gcodeText):
  165. "Parse a gcode text and display the commands."
  166. skein = displaySkein()
  167. skein.parseText(gcodeText)
  168. return skein.output
  169. def extrude( filename = ''):
  170. """Parse a gcode file and send the commands to the extruder. If no filename is specified, parse all the gcode files which are not log files in this folder.
  171. This function requires write access to the serial device, running as root is one way to get that access."""
  172. if filename == '':
  173. extrudeFiles( getGCodeFilesWhichAreNotLogFiles() )
  174. return
  175. extrudeFile( filename )
  176. def extrudeFile( filename ):
  177. """Parse a gcode file and send the commands to the extruder.
  178. This function requires write access to the serial device, running as root is one way to get that access."""
  179. print('File ' + filename + ' is being extruded.')
  180. fileText = archive.getFileText( filename )
  181. gcodec.writeFileMessageSuffix( filename, extrudeText(fileText), 'The gcode log file is saved as ', '_log')
  182. def extrudeFiles( filenames ):
  183. """Parse gcode files and send the commands to the extruder.
  184. This function requires write access to the serial device, running as root is one way to get that access."""
  185. for filename in filenames:
  186. extrudeFile( filename )
  187. def extrudeText(gcodeText):
  188. """Parse a gcode text and send the commands to the extruder.
  189. This function requires write access to the serial device, running as root is one way to get that access."""
  190. skein = extrudeSkein()
  191. skein.parseText(gcodeText)
  192. return skein.output
  193. def getGCodeFilesWhichAreNotLogFiles():
  194. "Get gcode files which are not log files."
  195. return archive.getFilesWithFileTypeWithoutWords('gcode', ['_log'] )
  196. def getIntegerString(number):
  197. "Get integer as string."
  198. return str( int(number) )
  199. class displaySkein:
  200. "A class to display a gcode skein of extrusions."
  201. def __init__(self):
  202. self.extruderActive = 0
  203. self.feedrateMinute = 200.0
  204. self.oldLocation = None
  205. self.output = ''
  206. def addToOutput(self, line):
  207. "Add line with a newline at the end to the output."
  208. print(line)
  209. self.output += line + '\n'
  210. def evaluateCommand( self, command ):
  211. "Add an extruder command to the output."
  212. self.addToOutput( command )
  213. def helicalMove( self, isCounterclockwise, splitLine ):
  214. "Parse a helical move gcode line and send the commands to the extruder."
  215. if self.oldLocation == None:
  216. return
  217. location = Vector3( self.oldLocation )
  218. self.setFeedrate(splitLine)
  219. setPointToSplitLine( location, splitLine )
  220. location = location + self.oldLocation
  221. center = Vector3( self.oldLocation )
  222. indexOfR = indexOfStartingWithSecond( "R", splitLine )
  223. if indexOfR > 0:
  224. radius = getDoubleAfterFirstLetter( splitLine[ indexOfR ] )
  225. halfLocationMinusOld = location - self.oldLocation
  226. halfLocationMinusOld *= 0.5
  227. halfLocationMinusOldLength = halfLocationMinusOld.length()
  228. centerMidpointDistance = math.sqrt( radius * radius - halfLocationMinusOldLength * halfLocationMinusOldLength )
  229. centerMinusMidpoint = getRotatedWiddershinsQuarterAroundZAxis( halfLocationMinusOld )
  230. centerMinusMidpoint.normalize()
  231. centerMinusMidpoint *= centerMidpointDistance
  232. if isCounterclockwise:
  233. center.setToVec3( halfLocationMinusOld + centerMinusMidpoint )
  234. else:
  235. center.setToVec3( halfLocationMinusOld - centerMinusMidpoint )
  236. else:
  237. center.x = getDoubleForLetter( "I", splitLine )
  238. center.y = getDoubleForLetter( "J", splitLine )
  239. curveSection = 0.5
  240. center += self.oldLocation
  241. afterCenterSegment = location - center
  242. beforeCenterSegment = self.oldLocation - center
  243. afterCenterDifferenceAngle = getAngleAroundZAxisDifference( afterCenterSegment, beforeCenterSegment )
  244. absoluteDifferenceAngle = abs( afterCenterDifferenceAngle )
  245. steps = int( math.ceil( max( absoluteDifferenceAngle * 2.4, absoluteDifferenceAngle * beforeCenterSegment.length() / curveSection ) ) )
  246. stepPlaneAngle = getPolar( afterCenterDifferenceAngle / steps, 1.0 )
  247. zIncrement = ( afterCenterSegment.z - beforeCenterSegment.z ) / float( steps )
  248. for step in range( 1, steps ):
  249. beforeCenterSegment = getRoundZAxisByPlaneAngle( stepPlaneAngle, beforeCenterSegment )
  250. beforeCenterSegment.z += zIncrement
  251. arcPoint = center + beforeCenterSegment
  252. self.moveExtruder( arcPoint )
  253. self.moveExtruder( location )
  254. self.oldLocation = location
  255. def homeReset(self):
  256. "Send all axies to home position. Wait until arrival."
  257. homeCommandString = 'reprap.cartesian.homeReset(' + getIntegerString( self.feedrateMinute ) + ', True )'
  258. self.evaluateCommand( homeCommandString )
  259. def linearMove( self, splitLine ):
  260. "Parse a linear move gcode line and send the commands to the extruder."
  261. location = Vector3()
  262. if self.oldLocation != None:
  263. location = self.oldLocation
  264. self.setFeedrate(splitLine)
  265. setPointToSplitLine( location, splitLine )
  266. self.moveExtruder( location )
  267. self.oldLocation = location
  268. def moveExtruder(self, location):
  269. "Seek to location. Wait until arrival."
  270. moveSpeedString = getIntegerString( self.feedrateMinute )
  271. xMoveString = getIntegerString(location.x)
  272. yMoveString = getIntegerString(location.y)
  273. zMoveString = getIntegerString(location.z)
  274. moveCommandString = 'reprap.cartesian.seek( (' + xMoveString + ', ' + yMoveString + ', ' + zMoveString + '), ' + moveSpeedString + ', True )'
  275. self.evaluateCommand( moveCommandString )
  276. def parseGCode(self, lines):
  277. "Parse gcode and send the commands to the extruder."
  278. self.evaluateCommand('reprap.serial = serial.Serial(0, 19200, timeout = 60)') # Initialise serial port, here the first port (0) is used.
  279. self.evaluateCommand('reprap.cartesian.x.active = True') # These devices are present in network, will automatically scan in the future.
  280. self.evaluateCommand('reprap.cartesian.y.active = True')
  281. self.evaluateCommand('reprap.cartesian.z.active = True')
  282. self.evaluateCommand('reprap.extruder.active = True')
  283. self.evaluateCommand('reprap.cartesian.x.setNotify()')
  284. self.evaluateCommand('reprap.cartesian.y.setNotify()')
  285. self.evaluateCommand('reprap.cartesian.z.setNotify()')
  286. self.evaluateCommand('reprap.cartesian.x.limit = 2523')
  287. self.evaluateCommand('reprap.cartesian.y.limit = 2000')
  288. self.homeReset() # The module is now ready to receive commands
  289. for line in lines:
  290. self.parseLine(line)
  291. self.homeReset()
  292. self.evaluateCommand('reprap.cartesian.free()') # Shut off power to all motors.
  293. def parseLine(self, line):
  294. "Parse a gcode line and send the command to the extruder."
  295. self.addToOutput(line)
  296. splitLine = line.split(' ')
  297. if len(splitLine) < 1:
  298. return 0
  299. firstWord = splitLine[0]
  300. if firstWord == 'G1':
  301. self.linearMove(splitLine)
  302. if firstWord == 'G2':
  303. self.helicalMove( False, splitLine )
  304. if firstWord == 'G3':
  305. self.helicalMove( True, splitLine )
  306. if firstWord == 'M101':
  307. self.extruderActive = 1
  308. self.evaluateCommand('reprap.extruder.setMotor(reprap.CMD_REVERSE, 150)')
  309. if firstWord == 'M103':
  310. self.extruderActive = 0
  311. self.evaluateCommand('reprap.extruder.setMotor(reprap.CMD_REVERSE, 0)')
  312. self.oldActiveLocation = None
  313. def parseText( self, text ):
  314. "Parse a gcode text and evaluate the commands."
  315. textLines = getTextLines(text)
  316. self.parseGCode( textLines )
  317. def setFeedrate( self, splitLine ):
  318. "Set the feedrate to the gcode split line."
  319. indexOfF = indexOfStartingWithSecond( "F", splitLine )
  320. if indexOfF > 0:
  321. self.feedrateMinute = getDoubleAfterFirstLetter( splitLine[indexOfF] )
  322. class extrudeSkein( displaySkein ):
  323. "A class to extrude a gcode skein of extrusions."
  324. def evaluateCommand( self, command ):
  325. """Add an extruder command to the output and evaluate the extruder command.
  326. Display the entire command, but only evaluate the command after the first equal sign."""
  327. self.addToOutput( command )
  328. firstEqualIndex = command.find('=')
  329. exec( command )
  330. print('Extrude has been imported.')
  331. print('The gcode files in this directory that are not log files are the following:')
  332. print( getGCodeFilesWhichAreNotLogFiles() )