/ src / emc / usr_intf / pyui / commands.py
commands.py
  1  import linuxcnc
  2  import os,sys
  3  # path to the configuration the user requested
  4  # used to see if the is local handler files to use
  5  try:
  6      CONFIGPATH = os.environ['CONFIG_DIR']
  7      CONFIGDIR = os.path.join(CONFIGPATH, 'panelui_handler.py')
  8  except:
  9      print '**** PANEL COMMAND: no panelui_handlers.py file in config directory'
 10      CONFIGPATH = os.path.expanduser("~")
 11      CONFIGDIR = os.path.join(CONFIGPATH, 'panelui_handler.py')
 12  
 13  # constants
 14  JOGJOINT  = 1
 15  JOGTELEOP = 0
 16  
 17  inifile = linuxcnc.ini(os.environ['INI_FILE_NAME'])
 18  trajcoordinates = inifile.find("TRAJ", "COORDINATES").lower().replace(" ","")
 19  jointcount = int(inifile.find("KINS","JOINTS"))
 20  
 21  DBG_state = 0
 22  def DBG(str):
 23      if DBG_state > 0:
 24          print str
 25  
 26  # Loads user commands from a file named 'panelui_handler.py' from the config
 27  def load_handlers(usermod,halcomp,builder,commands,master):
 28      hdl_func = 'get_handlers'
 29      mod = object = None
 30      def add_handler(method, f):
 31          if method in handlers:
 32              handlers[method].append(f)
 33          else:
 34              handlers[method] = [f]
 35      handlers = {}
 36      for u in usermod:
 37          (directory,filename) = os.path.split(u)
 38          (basename,extension) = os.path.splitext(filename)
 39          if directory == '':
 40              directory = '.'
 41          if directory not in sys.path:
 42              sys.path.insert(0,directory)
 43              DBG( 'panelui: adding import dir %s' % directory)
 44          try:
 45              mod = __import__(basename)
 46          except ImportError,msg:
 47              print ("panelui: module '%s' skipped - import error: %s" %(basename,msg))
 48  	    continue
 49          DBG( "panelui: module '%s' imported OK" % mod.__name__)
 50          try:
 51              # look for 'get_handlers' function
 52              h = getattr(mod,hdl_func,None)
 53              if h and callable(h):
 54                  DBG("panelui: module '%s' : '%s' function found" % (mod.__name__,hdl_func))
 55                  objlist = h(halcomp,builder,commands,master)
 56              else:
 57                  # the module has no get_handlers() callable.
 58                  # in this case we permit any callable except class Objects in the module to register as handler
 59                  DBG("panelui: module '%s': no '%s' function - registering only functions as callbacks" % (mod.__name__,hdl_func))
 60                  objlist =  [mod]
 61              # extract callback candidates
 62              for object in objlist:
 63                  #DBG("Registering handlers in module %s object %s" % (mod.__name__, object))
 64                  if isinstance(object, dict):
 65                      methods = dict.items()
 66                  else:
 67                      methods = map(lambda n: (n, getattr(object, n, None)), dir(object))
 68                  for method,f in methods:
 69                      if method.startswith('_'):
 70                          continue
 71                      if callable(f):
 72                          DBG("panelui: Register callback '%s' in %s" % (method, basename))
 73                          add_handler(method, f)
 74          except Exception, e:
 75              print ("**** PANELUI ERROR: trouble looking for handlers in '%s': %s" %(basename, e))
 76  
 77      # Wrap lists in Trampoline, unwrap single functions
 78      for n,v in list(handlers.items()):
 79          if len(v) == 1:
 80              handlers[n] = v[0]
 81          else:
 82              handlers[n] = Trampoline(v)
 83  
 84      return handlers,mod,object
 85  
 86  # trampoline and load_handlers are used for custom keyboard commands
 87  class Trampoline(object):
 88      def __init__(self,methods):
 89          self.methods = methods
 90  
 91      def __call__(self, *a, **kw):
 92          for m in self.methods:
 93              m(*a, **kw)
 94  
 95  # linuxcnc commands
 96  class CNC_COMMANDS():
 97          def __init__(self, master):
 98              global DBG_state
 99              DBG_state = master._dbg
100              self.emc = linuxcnc
101              self.emcstat = linuxcnc.stat()
102              self.emccommand = linuxcnc.command()
103              self.return_to_mode = -1 # if not -1 return to the mode specified
104              self.sb = 0;
105              self.jog_velocity = 100.0/60.0
106              self.angular_jog_velocity = 3600/60
107              self._mdi = 0
108              self.isjogging = [0,0,0,0,0,0,0,0,0]
109              self.restart_line_number = self.restart_reset_line = 0
110              try:
111                  handlers,self.handler_module,self.handler_instance = \
112                  load_handlers([CONFIGDIR], self.emcstat, self.emccommand,self, master)
113              except Exception, e:
114                  print e
115  
116          def mdi_active(self, wname, m):
117              self._mdi = m
118  
119          def mist_on(self, wname, b):
120              self.emccommand.mist(1)
121  
122          def mist_off(self, wname, b):
123              self.emccommand.mist(0)
124  
125          def flood_on(self, wname, b):
126              self.emccommand.flood(1)
127  
128          def flood_off(self, wname, b):
129              self.emccommand.flood(0)
130  
131          def estop(self, wname, b):
132              self.emccommand.state(self.emc.STATE_ESTOP)
133  
134          def estop_reset(self, wname, b):
135              self.emccommand.state(self.emc.STATE_ESTOP_RESET)
136  
137          def machine_off(self, wname, b):
138              self.emccommand.state(self.emc.STATE_OFF)
139  
140          def machine_on(self, wname, b):
141              self.emccommand.state(self.emc.STATE_ON)
142  
143          def home_all(self, wname, b):
144              self.emccommand.mode(self.emc.MODE_MANUAL)
145              self.emccommand.home(-1)
146  
147          def unhome_all(self, wname, b):
148              self.emccommand.mode(self.emc.MODE_MANUAL)
149              self.emccommand.unhome(-1)
150  
151          def home_selected(self, wname, joint):
152              self.emccommand.mode(self.emc.MODE_MANUAL)
153              self.emccommand.home(int(joint))
154  
155          def unhome_selected(self, wname, joint):
156              self.emccommand.mode(self.emc.MODE_MANUAL)
157              self.emccommand.unhome(int(joint))
158  
159          def jogging(self, wname, b):
160              self.emccommand.mode(self.emc.MODE_MANUAL)
161  
162          def override_limits(self, wname, b):
163              self.emccommand.mode(self.emc.MODE_MANUAL)
164              self.emccommand.override_limits()
165  
166          def spindle_forward_adjust(self, wname, rpm=100):
167              if self.get_mode() == self.emc.MODE_MDI:
168                  self.emccommand.mode(self.emc.MODE_MANUAL)
169              speed = self.is_spindle_running()
170              if  speed == 0:
171                  self.emccommand.spindle(1,float(rpm));
172              elif speed > 0:
173                  self.emccommand.spindle(self.emc.SPINDLE_INCREASE)
174              else:
175                  self.emccommand.spindle(self.emc.SPINDLE_DECREASE)
176  
177          def spindle_forward(self, wname, rpm=100):
178              self.emccommand.mode(self.emc.MODE_MANUAL)
179              speed = self.is_spindle_running()
180              if  speed == 0:
181                  self.emccommand.spindle(1,float(rpm));
182  
183          def spindle_stop(self, wname, b):
184              self.emccommand.mode(self.emc.MODE_MANUAL)
185              self.emccommand.spindle(0);
186  
187          def spindle_reverse(self, wname, rpm=100):
188              self.emccommand.mode(self.emc.MODE_MANUAL)
189              speed = self.is_spindle_running()
190              if  speed == 0:
191                  self.emccommand.spindle(-1,float(rpm));
192  
193          def spindle_reverse_adjust(self, wname, rpm=100):
194              if self.get_mode() == self.emc.MODE_MDI:
195                  self.emccommand.mode(self.emc.MODE_MANUAL)
196              speed = self.is_spindle_running()
197              if  speed == 0:
198                  self.emccommand.spindle(-1,float(rpm));
199              elif speed < 0:
200                  self.emccommand.spindle(self.emc.SPINDLE_INCREASE)
201              else:
202                  self.emccommand.spindle(self.emc.SPINDLE_DECREASE)
203  
204          def spindle_faster(self, wname, b):
205              self.emccommand.mode(self.emc.MODE_MANUAL)
206              self.emccommand.spindle(0,self.emc.SPINDLE_INCREASE)
207  
208          def spindle_slower(self, wname, b):
209              self.emccommand.mode(self.emc.MODE_MANUAL)
210              self.emccommand.spindle(0,self.emc.SPINDLE_DECREASE)
211  
212          def set_linear_jog_velocity(self, wname, cmd):
213              velocity = float(cmd)
214              if velocity is not None:
215                  rate = self.jog_velocity = velocity / 60.0
216                  for axisnum in (0,1,2,6,7,8):
217                      if self.isjogging[axisnum]:
218                          jjogmode,j_or_a = self.get_jog_info(axisnum)
219                          self.emccommand.jog(self.emc.JOG_CONTINUOUS, jjogmode, j_or_a, self.isjogging[i] * rate)
220  
221          def set_angular_jog_velocity(self, wname, cmd):
222              angular = float(cmd)
223              if velocity is not None:
224                  rate = self.angular_jog_velocity = angular / 60.0
225                  for axisnum in (3,4,5):
226                      if self.isjogging[axisnum]:
227                          jjogmode,j_or_a = self.get_jog_info(axisnum)
228                          self.emccommand.jog(self.emc.JOG_CONTINUOUS, jjogmode, j_or_a, self.isjogging[i] * rate)
229  
230          def continuous_jog(self, wname, cmd):
231              axisnum = int(cmd[0])
232              jjogmode,j_or_a = self.get_jog_info(axisnum)
233              direction = int(cmd[1])
234              if direction == 0:
235                  self.isjogging[axisnum] = 0
236                  self.emccommand.jog(self.emc.JOG_STOP, jjogmode, j_or_a)
237              else:
238                  if axisnum in (3,4,5):
239                      rate = self.angular_jog_velocity
240                  else:
241                      rate = self.jog_velocity
242                  self.isjogging[axisnum] = direction
243                  self.emccommand.jog(self.emc.JOG_CONTINUOUS, jjogmode, j_or_a, direction * rate)
244  
245          def incremental_jog(self, wname, cmd):
246              axisnum = int(cmd[0])
247              jjogmode,j_or_a = self.get_jog_info(axisnum)
248              direction = int(cmd[1])
249              distance = float(cmd[2])
250              self.isjogging[axisnum] = direction
251              if axisnum in (3,4,5):
252                  rate = self.angular_jog_velocity
253              else:
254                  rate = self.jog_velocity
255              self.emccommand.jog(self.emc.JOG_INCREMENT, jjogmode, axisnum, direction * rate, distance)
256              self.isjogging[axisnum] = 0
257  
258          def quill_up(self, wname, cmd):
259              self.emccommand.mode(self.emc.MODE_MANUAL)
260              self.emccommand.wait_complete()
261              self.mdi('G53 G0 Z %f'% float(cmd))
262  
263          def feed_hold(self, wname, cmd):
264              self.emccommand.set_feed_hold(int(cmd))
265  
266          def feed_override(self, wname, f):
267              self.emccommand.feedrate(f)
268  
269          def rapid_override(self, wname, f):
270              self.emccommand.rapidrate(f)
271  
272          def spindle_override(self, wname, s):
273              self.emccommand.spindleoverride(0,s)
274  
275          def max_velocity(self, wname, m):
276              self.emccommand.maxvel(m)
277  
278          def reload_tooltable(self, wname, b):
279              self.emccommand.load_tool_table()
280  
281          def optional_stop(self, wname, cmd):
282              self.emccommand.set_optional_stop(int(cmd))
283  
284          def block_delete(self, wname, cmd):
285              self.emccommand.set_block_delete(int(cmd))
286  
287          def abort(self, wname, cmd=None):
288              self.emccommand.abort()
289  
290          def pause(self, wname, cmd=None):
291              self.emccommand.auto(self.emc.AUTO_PAUSE)
292  
293          def resume(self, wname, cmd=None):
294              self.emccommand.auto(self.emc.AUTO_RESUME)
295  
296          def single_block(self, wname, s):
297              self.sb = s
298              self.emcstat.poll()
299              if self.emcstat.queue > 0 or self.emcstat.paused:
300                  # program or mdi is running
301                  if s:
302                      self.emccommand.auto(self.emc.AUTO_PAUSE)
303                  else:
304                      self.emccommand.auto(self.emc.AUTO_RESUME)
305  
306          # make sure linuxcnc is in AUTO mode
307          # if Linuxcnc is paused then pushing cycle start will step the program
308          # else the program starts from restart_line_number
309          # after restarting it resets the restart_line_number to 0.
310          # You must explicitily set a different restart line each time
311          def smart_cycle_start(self, wname, cmd=None):
312              self.emcstat.poll()
313              if self.emcstat.task_mode != self.emc.MODE_AUTO:
314                  self.emccommand.mode(self.emc.MODE_AUTO)
315                  self.emccommand.wait_complete()
316              self.emcstat.poll()
317              if self.emcstat.paused:
318                  self.emccommand.auto(self.emc.AUTO_STEP)
319                  return
320              if self.emcstat.interp_state == self.emc.INTERP_IDLE:
321                  print self.restart_line_number
322                  self.emccommand.auto(self.emc.AUTO_RUN, self.restart_line_number)
323              self.restart_line_number = self.restart_reset_line
324  
325          # This restarts the program at the line specified directly (without cyscle start push)
326          def re_start(self, wname, line):
327              self.emccommand.mode(self.emc.MODE_AUTO)
328              self.emccommand.wait_complete()
329              self.emccommand.auto(self.emc.AUTO_RUN, line)
330              self.restart_line_number = self.restart_reset_line
331  
332          # checks if ready for commands
333          # calls MDI commands and when idle, periodic() will return to the mode it was in
334          def mdi_and_return(self, wname, cmd):
335              if self.ok_for_mdi():
336                  self.return_to_mode = self.get_mode() # for periodic()
337                  self.set_mdi_mode()
338                  if isinstance(cmd,list):
339                      for i in cmd:
340                          print str(i)
341                          self.emccommand.mdi(str(i))
342                  else:
343                      self.emccommand.mdi(str(cmd))
344  
345          # call MDI commands, set mode if needed
346          def mdi(self, wname, cmd):
347              self.set_mdi_mode()
348              if isinstance(cmd,list):
349                  for i in cmd:
350                      print str(i)
351                      self.emccommand.mdi(str(i))
352              else:
353                  self.emccommand.mdi(str(cmd))
354  
355          # set the restart line, you can the either restart directly
356          # or restart on the cycle start button push
357          # see above.
358          # reset option allows one to change the default restart after it next restarts
359          # eg while a restart dialog is open, always restart at the line it says
360          # when the dialog close change the  line and reset both to zero
361          def set_restart_line (self,  wname, line,reset=0):
362              self.restart_line_number = line
363              self.restart_reset_line = reset
364  
365          def set_manual_mode(self):
366              self.emcstat.poll()
367              if self.emcstat.task_mode != self.emc.MODE_MANUAL:
368                  self.emccommand.mode(self.emc.MODE_MANUAL)
369                  self.emccommand.wait_complete()
370  
371          def set_mdi_mode(self):
372              self.emcstat.poll()
373              if self.emcstat.task_mode != self.emc.MODE_MDI:
374                  self.emccommand.mode(self.emc.MODE_MDI)
375                  self.emccommand.wait_complete()
376  
377          def set_auto_mode(self):
378              self.emcstat.poll()
379              if self.emcstat.task_mode != self.emc.MODE_AUTO:
380                  self.emccommand.mode(self.emc.MODE_AUTO)
381                  self.emccommand.wait_complete()
382  
383          def get_mode(self):
384              self.emcstat.poll()
385              return self.emcstat.task_mode
386  
387          def ok_for_mdi(self):
388              self.emcstat.poll()
389              s = self.emcstat
390              return not s.estop and s.enabled and s.homed and \
391                  (s.interp_state == self.emc.INTERP_IDLE)
392  
393          def is_spindle_running(self):
394              self.emcstat.poll()
395              s = self.emcstat
396              if s.spindle[0]['enabled']:
397                  return s.spindle[0]['speed']
398              else:
399                  return 0
400  
401          def periodic(self):
402              # return mode back to preset variable, when idle
403              if self.return_to_mode > -1:
404                  self.emcstat.poll()
405                  if self.emcstat.interp_state == self.emc.INTERP_IDLE:
406                      self.emccommand.mode(self.return_to_mode)
407                      self.return_to_mode = -1
408  
409          def __getitem__(self, item):
410              return getattr(self, item)
411          def __setitem__(self, item, value):
412              return setattr(self, item, value)
413  
414          def get_jjogmode(self):
415              self.emcstat.poll()
416              if self.emcstat.motion_mode == linuxcnc.TRAJ_MODE_FREE:
417                  return JOGJOINT
418              if self.emcstat.motion_mode == linuxcnc.TRAJ_MODE_TELEOP:
419                  return JOGTELEOP
420              print "commands.py: unexpected motion_mode",self.emcstat.motion_mode
421              return JOGTELEOP
422  
423          def jnum_for_axisnum(self,axisnum):
424              if self.emcstat.kinematics_type != linuxcnc.KINEMATICS_IDENTITY:
425                  print ("\n%s:\n  Joint jogging not supported for"
426                         "non-identity kinematics"%__file__)
427                  return -1 # emcJogCont() et al reject neg joint/axis no.s
428              jnum = trajcoordinates.index( "xyzabcuvw"[axisnum] )
429              if jnum > jointcount:
430                  print ("\n%s:\n  Computed joint number=%d for axisnum=%d "
431                         "exceeds jointcount=%d with trajcoordinates=%s"
432                         %(__file__,jnum,axisnum,jointcount,trajcoordinates))
433                  # Note: primary gui should protect for this misconfiguration
434                  # decline to jog
435                  return -1 # emcJogCont() et al reject neg joint/axis no.s
436              return jnum
437  
438          def get_jog_info (self,axisnum):
439              jjogmode = self.get_jjogmode()
440              j_or_a = axisnum
441              if jjogmode == JOGJOINT: j_or_a = self.jnum_for_axisnum(axisnum)
442              return jjogmode,j_or_a
443