/ scripts / torture.py
torture.py
  1  #!/usr/bin/env python
  2  #    Copyright (C) 2012 Jeff Epler <jepler@unpythonic.net>
  3  #
  4  #    This program is free software; you can redistribute it and/or modify
  5  #    it under the terms of the GNU General Public License as published by
  6  #    the Free Software Foundation; either version 2 of the License, or
  7  #    (at your option) any later version.
  8  #
  9  #    This program is distributed in the hope that it will be useful,
 10  #    but WITHOUT ANY WARRANTY; without even the implied warranty of
 11  #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 12  #    GNU General Public License for more details.
 13  #
 14  #    You should have received a copy of the GNU General Public License
 15  #    along with this program; if not, write to the Free Software
 16  #    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 17  """
 18  This program creates "torture test" ngc files.  These include arcs (helices)
 19  in any plane, straight feeds, and traverses all in a random order with
 20  differing feeds.
 21  
 22  Run the resulting file in a stepper inifile with no headroom, and kick
 23  things up a notch by using different max velocities and accelerations.
 24  Turning feed override past 100% has also helped turn up bugs.
 25  """
 26  
 27  from random import *
 28  from math import sin, cos, pi
 29  
 30  distances = [-10,1,-.1,0,0,.1,1,10]
 31  radii = [.1, 1, 10]
 32  arcangles = range(0, 360, 45)
 33  aangles = [-361,-89,-1,1,91,359]
 34  chance_angular = .5
 35  chance_angular_helix = .5
 36  chance_lineaxis = .2
 37  
 38  def feed():
 39      "Half the time, change the feed rate"
 40      if random() < .5: return
 41      print "F%d" % randrange(100, 1000, 10),
 42  
 43  def torture_arc(x, y, z, a, b, c, u, v, w):
 44      "Generate a random arc (helix)"
 45      plane = randrange(3)
 46      print "G%d" % (plane+17),
 47  
 48      direction = randrange(2)
 49      print "G%d" % (direction+2),
 50  
 51      feed()
 52  
 53      theta = choice(arcangles)
 54      theta1 = choice(arcangles)
 55      r = choice(radii)
 56      q = choice(distances)
 57  
 58      print "(%d %d)" % (theta*180/pi, theta1*180/pi),
 59      if plane == 0: # XY plane
 60          ox = -cos(theta)*r
 61          oy = -sin(theta)*r
 62          print "I%f J%f" % (ox, oy),
 63  
 64          z = z + q
 65          x = x + ox + cos(theta1)*r
 66          y = y + oy + sin(theta1)*r
 67  
 68      elif plane == 1: # XZ plane
 69          ox = -cos(theta)*r
 70          oz = -sin(theta)*r
 71          print "I%f K%f" % (ox, oz),
 72  
 73          x = x + ox + sin(theta1)*r
 74          z = z + oz + cos(theta1)*r
 75          y = y + q
 76  
 77      else: # YZ plane
 78          oy = -cos(theta)*r
 79          oz = -sin(theta)*r
 80          print "J%f K%f" % (oy, oz),
 81  
 82          x = x + q
 83          y = y + oy + cos(theta1)*r
 84          z = z + oz + sin(theta1)*r
 85  
 86      if random() < chance_angular_helix:
 87          a = a + choice(aangles)
 88          print "A%f" % a,
 89  
 90      if random() < chance_angular_helix:
 91          b = b + choice(aangles)
 92          print "B%f" % b,
 93  
 94      if random() < chance_angular_helix:
 95          c = c + choice(aangles)
 96          print "C%f" % c,
 97  
 98      if random() < chance_angular_helix:
 99          u = u + randrange(-500, 500)/100.
100          print "U%f" % u,
101  
102      if random() < chance_angular_helix:
103          v = v + randrange(-500, 500)/100.
104          print "V%f" % v,
105  
106      if random() < chance_angular_helix:
107          w = w + randrange(-500, 500)/100.
108          print "W%f" % w,
109  
110      print "X%f Y%f Z%f" % (x, y, z)
111  
112      return x, y, z, a, b, c, u, v, w
113  
114  def torture_line(x, y, z, a, b, c, u, v, w):
115      "Generate a random traverse or straight feed"
116      kind = randrange(2)
117      p = ""
118      p += "G%d " % kind
119  
120      if random() < chance_lineaxis:
121          x = x + randrange(-10, 11)/2.
122          p += "X%f " % x
123  
124      if random() < chance_lineaxis:
125          y = y + randrange(-10, 11)/2.
126          p += "Y%f " % y
127  
128      if random() < chance_lineaxis:
129          z = z + randrange(-10, 11)/2.
130          p += "Z%f " % z
131  
132      if random() < chance_lineaxis:
133          a = a + randrange(-180, 80)/2.
134          p += "A%f " % a
135  
136      if random() < chance_lineaxis:
137          b = b + randrange(-180, 80)/2.
138          p += "B%f " % b
139  
140      if random() < chance_lineaxis:
141          c = c + randrange(-180, 80)/2.
142          p += "C%f " % c
143  
144      if random() < chance_lineaxis:
145          u = u + randrange(-500, 500)/100.
146          p += "U%f " % u
147  
148      if random() < chance_lineaxis:
149          v = v + randrange(-500, 500)/100.
150          p += "V%f " % v
151  
152      if random() < chance_lineaxis:
153          w = w + randrange(-500, 500)/100.
154          p += "W%f " % w
155  
156      if len(p) > 4:
157          if kind == 1: feed()
158          print p
159  
160      return x, y, z, a, b, c, u, v, w
161  
162  def torture_main(runs):
163      """Generate random chains of movement several times, restarting near the
164       center each time motion gets too far away."""
165      funcs = [torture_line, torture_arc]
166      #funcs = [torture_arc]
167      def R(x,l=-50, k=50): return x < l or x > k
168  
169      print "g21"
170      for i in range(runs):
171          x = y = 0
172          z = 20
173          a = b = c = u = v = w = 0
174          if chance_angular or chance_angular_helix:
175              print "G0 X0 Y0 A0 B0 C0 U0 V0 W0 Z20"
176          else:
177              print "G0 X0 Y0 Z20"
178          print "F100"
179  
180          while 1:
181              x, y, z, a, b, c, u, v, w = choice(funcs)(x, y, z, a, b, c, u, v, w)
182              if (R(x) or R(y) or R(z,-10,30) or
183                  R(a,-30000,30000) or R(b, -30000,30000) or R(c, -30000,30000) or
184                  R(u) or R(v) or R(w)):
185                 break
186  
187  # Do ten runs then print m2
188  torture_main(20)
189  print "m2"