1223 lines
50 KiB
Python
1223 lines
50 KiB
Python
#!/usr/bin/env python3
|
|
# vim: sts=4 sw=4 et
|
|
|
|
import _hal, hal
|
|
import linuxcnc
|
|
import os
|
|
import math
|
|
|
|
from gi.repository import GObject
|
|
from gi.repository import GLib
|
|
|
|
# constants
|
|
JOGJOINT = 1
|
|
JOGTELEOP = 0
|
|
|
|
# add try for QtVCP Designer and probably GTK GLADE editor too
|
|
# The INI file is not available then
|
|
try:
|
|
inifile = linuxcnc.ini(os.environ['INI_FILE_NAME'])
|
|
trajcoordinates = inifile.find("TRAJ", "COORDINATES").lower().replace(" ", "")
|
|
jointcount = int(inifile.find("KINS", "JOINTS"))
|
|
except:
|
|
pass
|
|
try:
|
|
# get cycle time which could be in ms or seconds
|
|
# convert to ms - use this to set update time
|
|
ct = float(inifile.find('DISPLAY', 'CYCLE_TIME') or 100)
|
|
if ct < 1:
|
|
CYCLE_TIME = int(ct * 1000)
|
|
else:
|
|
CYCLE_TIME = int(ct)
|
|
except:
|
|
CYCLE_TIME = 100
|
|
|
|
class GPin(GObject.Object, hal.Pin):
|
|
__gtype_name__ = 'GPin'
|
|
__gsignals__ = {'value-changed': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, ())}
|
|
|
|
REGISTRY = []
|
|
UPDATE = False
|
|
|
|
def __init__(self, *a, **kw):
|
|
GObject.Object.__init__(self)
|
|
hal.Pin.__init__(self, *a, **kw)
|
|
self._item_wrap(self._item)
|
|
self._prev = None
|
|
self.REGISTRY.append(self)
|
|
self.update_start()
|
|
|
|
def update(self):
|
|
tmp = self.get()
|
|
if tmp != self._prev:
|
|
self.emit('value-changed')
|
|
self._prev = tmp
|
|
|
|
@classmethod
|
|
def update_all(self):
|
|
if not self.UPDATE:
|
|
return
|
|
kill = []
|
|
for p in self.REGISTRY:
|
|
try:
|
|
p.update()
|
|
except:
|
|
kill.append(p)
|
|
print("Error updating pin %s; Removing" % p)
|
|
for p in kill:
|
|
self.REGISTRY.remove(p)
|
|
return self.UPDATE
|
|
|
|
@classmethod
|
|
def update_start(self, timeout=100):
|
|
if GPin.UPDATE:
|
|
return
|
|
GPin.UPDATE = True
|
|
GLib.timeout_add(timeout, self.update_all)
|
|
|
|
@classmethod
|
|
def update_stop(self, timeout=100):
|
|
GPin.UPDATE = False
|
|
|
|
class GComponent:
|
|
def __init__(self, comp):
|
|
if isinstance(comp, GComponent):
|
|
comp = comp.comp
|
|
self.comp = comp
|
|
|
|
def newpin(self, *a, **kw): return GPin(_hal.component.newpin(self.comp, *a, **kw))
|
|
def getpin(self, *a, **kw): return GPin(_hal.component.getpin(self.comp, *a, **kw))
|
|
|
|
def exit(self, *a, **kw): return self.comp.exit(*a, **kw)
|
|
|
|
def __getitem__(self, k): return self.comp[k]
|
|
def __setitem__(self, k, v): self.comp[k] = v
|
|
|
|
class _GStat(GObject.GObject):
|
|
'''Emits signals based on linuxcnc status '''
|
|
__gsignals__ = {
|
|
'periodic': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, ()),
|
|
'state-estop': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, ()),
|
|
'state-estop-reset': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, ()),
|
|
'state-on': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, ()),
|
|
'state-off': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, ()),
|
|
|
|
'homed': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, (GObject.TYPE_STRING,)),
|
|
'unhomed': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, (GObject.TYPE_STRING,)),
|
|
'all-homed': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, ()),
|
|
'not-all-homed': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, (GObject.TYPE_STRING,)),
|
|
'override-limits-changed': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, (GObject.TYPE_BOOLEAN, GObject.TYPE_PYOBJECT,)),
|
|
|
|
'hard-limits-tripped': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, (GObject.TYPE_BOOLEAN, GObject.TYPE_PYOBJECT,)),
|
|
|
|
'mode-manual': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, ()),
|
|
'mode-auto': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, ()),
|
|
'mode-mdi': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, ()),
|
|
|
|
'command-running': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, ()),
|
|
'command-stopped': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, ()),
|
|
'command-error': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, ()),
|
|
|
|
'interp-run': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, ()),
|
|
'interp-idle': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, ()),
|
|
'interp-paused': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, ()),
|
|
'interp-reading': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, ()),
|
|
'interp-waiting': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, ()),
|
|
|
|
'jograte-changed': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, (GObject.TYPE_FLOAT,)),
|
|
'jograte-angular-changed': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, (GObject.TYPE_FLOAT,)),
|
|
'jogincrement-changed': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, (GObject.TYPE_FLOAT, GObject.TYPE_STRING)),
|
|
'jogincrement-angular-changed': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, (GObject.TYPE_FLOAT, GObject.TYPE_STRING)),
|
|
|
|
'joint-selection-changed': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, (GObject.TYPE_INT,)),
|
|
'axis-selection-changed': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, (GObject.TYPE_STRING,)),
|
|
|
|
'program-pause-changed': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, (GObject.TYPE_BOOLEAN,)),
|
|
'optional-stop-changed': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, (GObject.TYPE_BOOLEAN,)),
|
|
'block-delete-changed': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, (GObject.TYPE_BOOLEAN,)),
|
|
|
|
'file-loaded': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, (GObject.TYPE_STRING,)),
|
|
'reload-display': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, ()),
|
|
'line-changed': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, (GObject.TYPE_INT,)),
|
|
|
|
'tool-in-spindle-changed': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, (GObject.TYPE_INT,)),
|
|
'tool-prep-changed': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, (GObject.TYPE_INT,)),
|
|
'tool-info-changed': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, (GObject.TYPE_PYOBJECT,)),
|
|
'current-tool-offset': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, (GObject.TYPE_PYOBJECT,)),
|
|
|
|
'motion-mode-changed': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, (GObject.TYPE_INT,)),
|
|
'motion-type-changed': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, (GObject.TYPE_INT,)),
|
|
'spindle-control-changed': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE,
|
|
(GObject.TYPE_INT, GObject.TYPE_BOOLEAN, GObject.TYPE_INT, GObject.TYPE_BOOLEAN)),
|
|
'current-feed-rate': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, (GObject.TYPE_FLOAT,)),
|
|
'current-x-rel-position': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, (GObject.TYPE_FLOAT,)),
|
|
'current-position': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, (GObject.TYPE_PYOBJECT,GObject.TYPE_PYOBJECT,
|
|
GObject.TYPE_PYOBJECT, GObject.TYPE_PYOBJECT,)),
|
|
'current-z-rotation': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_FLOAT,)),
|
|
'requested-spindle-speed-changed': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_FLOAT,)),
|
|
'actual-spindle-speed-changed': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_FLOAT,)),
|
|
'spindle-override-changed': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_FLOAT,)),
|
|
'feed-override-changed': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_FLOAT,)),
|
|
'rapid-override-changed': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_FLOAT,)),
|
|
'max-velocity-override-changed': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_FLOAT,)),
|
|
|
|
'feed-hold-enabled-changed': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_BOOLEAN,)),
|
|
|
|
'g90-mode': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_BOOLEAN,)),
|
|
'g91-mode': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_BOOLEAN,)),
|
|
'itime-mode': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_BOOLEAN,)),
|
|
'fpm-mode': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_BOOLEAN,)),
|
|
'fpr-mode': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_BOOLEAN,)),
|
|
'css-mode': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_BOOLEAN,)),
|
|
'rpm-mode': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_BOOLEAN,)),
|
|
'radius-mode': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_BOOLEAN,)),
|
|
'diameter-mode': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_BOOLEAN,)),
|
|
'flood-changed': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_BOOLEAN,)),
|
|
'mist-changed': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_BOOLEAN,)),
|
|
|
|
'm-code-changed': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_STRING,)),
|
|
'g-code-changed': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_STRING,)),
|
|
'f-code-changed': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_FLOAT,)),
|
|
'blend-code-changed': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_FLOAT, GObject.TYPE_FLOAT)),
|
|
|
|
'metric-mode-changed': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_BOOLEAN,)),
|
|
'user-system-changed': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_STRING,)),
|
|
|
|
'mdi-line-selected': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_STRING, GObject.TYPE_STRING)),
|
|
'gcode-line-selected': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_INT,)),
|
|
'graphics-line-selected': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_INT,)),
|
|
'graphics-loading-progress': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_INT,)),
|
|
'graphics-gcode-error': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_STRING,)),
|
|
'graphics-gcode-properties': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_PYOBJECT,)),
|
|
'graphics-view-changed': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_STRING, GObject.TYPE_PYOBJECT)),
|
|
'mdi-history-changed': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, ()),
|
|
'machine-log-changed': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, ()),
|
|
'update-machine-log': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_STRING, GObject.TYPE_STRING)),
|
|
'move-text-lineup': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, ()),
|
|
'move-text-linedown': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, ()),
|
|
'dialog-request': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_PYOBJECT,)),
|
|
'focus-overlay-changed': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE, (GObject.TYPE_BOOLEAN, GObject.TYPE_STRING,
|
|
GObject.TYPE_PYOBJECT)),
|
|
'play-sound': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, (GObject.TYPE_STRING,)),
|
|
'virtual-keyboard': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, (GObject.TYPE_STRING,)),
|
|
'dro-reference-change-request': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, (GObject.TYPE_INT,)),
|
|
'system_notify_button_pressed': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE,
|
|
(GObject.TYPE_STRING, GObject.TYPE_BOOLEAN)),
|
|
'show-preference': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, ()),
|
|
'shutdown': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, ()),
|
|
'error': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, (GObject.TYPE_INT, GObject.TYPE_STRING)),
|
|
'general': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, (GObject.TYPE_PYOBJECT,)),
|
|
'forced-update': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, ()),
|
|
'progress': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE, (GObject.TYPE_INT, GObject.TYPE_PYOBJECT)),
|
|
'following-error': (GObject.SignalFlags.RUN_FIRST , GObject.TYPE_NONE,(GObject.TYPE_PYOBJECT,)),
|
|
}
|
|
|
|
STATES = { linuxcnc.STATE_ESTOP: 'state-estop'
|
|
, linuxcnc.STATE_ESTOP_RESET: 'state-estop-reset'
|
|
, linuxcnc.STATE_ON: 'state-on'
|
|
, linuxcnc.STATE_OFF: 'state-off'
|
|
}
|
|
|
|
MODES = { linuxcnc.MODE_MANUAL: 'mode-manual'
|
|
, linuxcnc.MODE_AUTO: 'mode-auto'
|
|
, linuxcnc.MODE_MDI: 'mode-mdi'
|
|
}
|
|
|
|
INTERP = { linuxcnc.INTERP_WAITING: 'interp-waiting'
|
|
, linuxcnc.INTERP_READING: 'interp-reading'
|
|
, linuxcnc.INTERP_PAUSED: 'interp-paused'
|
|
, linuxcnc.INTERP_IDLE: 'interp-idle'
|
|
}
|
|
|
|
TEMPARARY_MESSAGE = 255
|
|
OPERATOR_ERROR = linuxcnc.OPERATOR_ERROR
|
|
OPERATOR_TEXT = linuxcnc.OPERATOR_TEXT
|
|
NML_ERROR = linuxcnc.NML_ERROR
|
|
NML_TEXT = linuxcnc.NML_TEXT
|
|
|
|
MANUAL = linuxcnc.MODE_MANUAL
|
|
AUTO = linuxcnc.MODE_AUTO
|
|
MDI = linuxcnc.MODE_MDI
|
|
|
|
STATE_ESTOP = linuxcnc.STATE_ESTOP
|
|
STATE_ESTOP_RESET = linuxcnc.STATE_ESTOP_RESET
|
|
STATE_ON = linuxcnc.STATE_ON
|
|
STATE_OFF = linuxcnc.STATE_OFF
|
|
|
|
def __init__(self, stat = None):
|
|
GObject.Object.__init__(self)
|
|
self.stat = stat or linuxcnc.stat()
|
|
self.cmd = linuxcnc.command()
|
|
self._status_active = False
|
|
self.old = {}
|
|
self.old['tool-prep-number'] = 0
|
|
try:
|
|
self.stat.poll()
|
|
self.merge()
|
|
except:
|
|
pass
|
|
|
|
self.current_jog_rate = 15
|
|
self.current_angular_jog_rate = 360
|
|
self.current_jog_distance = 0
|
|
self.current_jog_distance_text =''
|
|
self.current_jog_distance_angular= 0
|
|
self.current_jog_distance_angular_text =''
|
|
self.selected_joint = -1
|
|
self.selected_axis = ''
|
|
self._is_all_homed = False
|
|
self.set_timer()
|
|
|
|
# we put this in a function so qtvcp
|
|
# can override it to fix a seg fault
|
|
def set_timer(self):
|
|
GLib.timeout_add(CYCLE_TIME, self.update)
|
|
|
|
def merge(self):
|
|
self.old['command-state'] = self.stat.state
|
|
self.old['state'] = self.stat.task_state
|
|
self.old['mode'] = self.stat.task_mode
|
|
self.old['interp']= self.stat.interp_state
|
|
# Only update file if call level is 0, which
|
|
# means we are not executing a subroutine/remap
|
|
# This avoids emitting signals for bogus file names below
|
|
if self.stat.call_level == 0:
|
|
self.old['file'] = self.stat.file
|
|
self.old['paused']= self.stat.paused
|
|
self.old['line'] = self.stat.motion_line
|
|
self.old['homed'] = self.stat.homed
|
|
self.old['tool-in-spindle'] = self.stat.tool_in_spindle
|
|
try:
|
|
if hal.get_value('iocontrol.0.tool-prepare'):
|
|
self.old['tool-prep-number'] = hal.get_value('iocontrol.0.tool-prep-number')
|
|
except RuntimeError:
|
|
self.old['tool-prep-number'] = -1
|
|
self.old['motion-mode'] = self.stat.motion_mode
|
|
self.old['motion-type'] = self.stat.motion_type
|
|
self.old['spindle-or'] = self.stat.spindle[0]['override']
|
|
self.old['feed-or'] = self.stat.feedrate
|
|
self.old['rapid-or'] = self.stat.rapidrate
|
|
self.old['max-velocity-or'] = self.stat.max_velocity
|
|
self.old['feed-hold'] = self.stat.feed_hold_enabled
|
|
self.old['g5x-index'] = self.stat.g5x_index
|
|
self.old['spindle-enabled'] = self.stat.spindle[0]['enabled']
|
|
self.old['spindle-direction'] = self.stat.spindle[0]['direction']
|
|
self.old['block-delete']= self.stat.block_delete
|
|
self.old['optional-stop']= self.stat.optional_stop
|
|
try:
|
|
self.old['actual-spindle-speed'] = hal.get_value('spindle.0.speed-in') * 60
|
|
except RuntimeError:
|
|
self.old['actual-spindle-speed'] = 0
|
|
try:
|
|
self.old['spindle-at-speed'] = hal.get_value('spindle.0.at-speed')
|
|
except RuntimeError:
|
|
self.old['spindle-at-speed'] = False
|
|
self.old['flood']= self.stat.flood
|
|
self.old['mist']= self.stat.mist
|
|
self.old['current-z-rotation'] = self.stat.rotation_xy
|
|
self.old['current-tool-offset'] = self.stat.tool_offset
|
|
|
|
# override limits / hard limits
|
|
or_limit_list=[]
|
|
hard_limit_list = []
|
|
ferror = []
|
|
hard_limit = False
|
|
or_limit_set = False
|
|
for j in range(0, self.stat.joints):
|
|
or_limit_list.append( self.stat.joint[j]['override_limits'])
|
|
or_limit_set = or_limit_set or self.stat.joint[j]['override_limits']
|
|
min_hard_limit = self.stat.joint[j]['min_hard_limit']
|
|
max_hard_limit = self.stat.joint[j]['max_hard_limit']
|
|
hard_limit = hard_limit or min_hard_limit or max_hard_limit
|
|
hard_limit_list.append([min_hard_limit,max_hard_limit])
|
|
ferror.append(self.stat.joint[j]['ferror_current'])
|
|
self.old['override-limits'] = or_limit_list
|
|
self.old['override-limits-set'] = bool(or_limit_set)
|
|
self.old['hard-limits-tripped'] = bool(hard_limit)
|
|
self.old['hard-limits-list'] = hard_limit_list
|
|
self.old['ferror-current'] = ferror
|
|
|
|
# active G-codes
|
|
active_gcodes = []
|
|
codes =''
|
|
for i in sorted(self.stat.gcodes[1:]):
|
|
if i == -1: continue
|
|
if i % 10 == 0:
|
|
active_gcodes.append("G%d" % (i/10))
|
|
else:
|
|
active_gcodes.append("G%d.%d" % (i/10, i%10))
|
|
for i in active_gcodes:
|
|
codes = codes +('%s '%i)
|
|
self.old['g-code'] = codes
|
|
# extract specific G-code modes
|
|
itime = fpm = fpr = css = rpm = metric = False
|
|
radius = diameter = adm = idm = False
|
|
for num,i in enumerate(active_gcodes):
|
|
if i == 'G90': adm = True
|
|
elif i == 'G91': idm = True
|
|
elif i == 'G93': itime = True
|
|
elif i == 'G94': fpm = True
|
|
elif i == 'G95': fpr = True
|
|
elif i == 'G96': css = True
|
|
elif i == 'G97': rpm = True
|
|
elif i == 'G21': metric = True
|
|
elif i == 'G7': diameter = True
|
|
elif i == 'G8': radius = True
|
|
self.old['g90'] = adm
|
|
self.old['g91'] = idm
|
|
self.old['itime'] = itime
|
|
self.old['fpm'] = fpm
|
|
self.old['fpr'] = fpr
|
|
self.old['css'] = css
|
|
self.old['rpm'] = rpm
|
|
self.old['metric'] = metric
|
|
self.old['radius'] = radius
|
|
self.old['diameter'] = diameter
|
|
if css:
|
|
try:
|
|
self.old['spindle-speed']= hal.get_value('spindle.0.speed-out')
|
|
except RuntimeError:
|
|
self.old['spindle-speed']= self.stat.spindle[0]['speed']
|
|
else:
|
|
self.old['spindle-speed']= self.stat.spindle[0]['speed']
|
|
|
|
# active M-codes
|
|
active_mcodes = []
|
|
mcodes = ''
|
|
for i in sorted(self.stat.mcodes[1:]):
|
|
if i == -1: continue
|
|
active_mcodes.append("M%d"%i )
|
|
for i in active_mcodes:
|
|
mcodes = mcodes + ("%s "%i)
|
|
#active_mcodes.append("M%s "%i)
|
|
self.old['m-code'] = mcodes
|
|
self.old['tool-info'] = self.stat.tool_table[0]
|
|
settings = self.stat.settings
|
|
self.old['f-code'] = settings[1]
|
|
self.old['blend-tolerance-code'] = settings[3]
|
|
self.old['nativecam-tolerance-code'] = settings[4]
|
|
|
|
def update(self):
|
|
try:
|
|
self.stat.poll()
|
|
except:
|
|
self._status_active = False
|
|
# some things might not need linuxcnc status but do need periodic
|
|
self.emit('periodic')
|
|
# Reschedule
|
|
return True
|
|
self._status_active = True
|
|
old = dict(self.old)
|
|
self.merge()
|
|
cmd_state_old = old.get('command-state')
|
|
cmd_state_new = self.old['command-state']
|
|
if cmd_state_new != cmd_state_old:
|
|
if cmd_state_new == linuxcnc.RCS_EXEC:
|
|
self.emit('command-running')
|
|
elif cmd_state_new == linuxcnc.RCS_DONE:
|
|
self.emit('command-stopped')
|
|
elif cmd_state_new == linuxcnc.RCS_ERROR:
|
|
self.emit('command-error')
|
|
|
|
state_old = old.get('state', 0)
|
|
state_new = self.old['state']
|
|
if state_new != state_old:
|
|
|
|
# set machine estop/clear
|
|
if state_old == linuxcnc.STATE_ESTOP and state_new == linuxcnc.STATE_ESTOP_RESET:
|
|
self.emit('state-estop-reset')
|
|
self.emit('interp-idle')
|
|
elif state_new == linuxcnc.STATE_ESTOP:
|
|
self.emit('state-estop')
|
|
self.emit('interp-idle')
|
|
|
|
# set machine on/off
|
|
if state_new == linuxcnc.STATE_ON:
|
|
self.emit('state-on')
|
|
elif state_old == linuxcnc.STATE_ON and state_new < linuxcnc.STATE_ON:
|
|
self.emit('state-off')
|
|
|
|
# reset modes/interpreter on machine on
|
|
if state_new == linuxcnc.STATE_ON:
|
|
old['mode'] = 0
|
|
old['interp'] = 0
|
|
|
|
mode_old = old.get('mode', 0)
|
|
mode_new = self.old['mode']
|
|
if mode_new != mode_old:
|
|
self.emit(self.MODES[mode_new])
|
|
|
|
interp_old = old.get('interp', 0)
|
|
interp_new = self.old['interp']
|
|
if interp_new != interp_old:
|
|
if not interp_old or interp_old == linuxcnc.INTERP_IDLE:
|
|
self.emit('interp-run')
|
|
self.emit(self.INTERP[interp_new])
|
|
# paused
|
|
paused_old = old.get('paused', None)
|
|
paused_new = self.old['paused']
|
|
if paused_new != paused_old:
|
|
self.emit('program-pause-changed',paused_new)
|
|
# block delete
|
|
block_delete_old = old.get('block-delete', None)
|
|
block_delete_new = self.old['block-delete']
|
|
if block_delete_new != block_delete_old:
|
|
self.emit('block-delete-changed',block_delete_new)
|
|
# optional_stop
|
|
optional_stop_old = old.get('optional-stop', None)
|
|
optional_stop_new = self.old['optional-stop']
|
|
if optional_stop_new != optional_stop_old:
|
|
self.emit('optional-stop-changed',optional_stop_new)
|
|
# file changed
|
|
file_old = old.get('file', None)
|
|
file_new = self.old['file']
|
|
if file_new != file_old:
|
|
# if interpreter is reading or waiting, the new file
|
|
# is a remap procedure, with the following test we
|
|
# partly avoid emitting a signal in that case, which would cause
|
|
# a reload of the preview and sourceview widgets. A signal could
|
|
# still be emitted if aborting a program shortly after it ran an
|
|
# external file subroutine, but that is fixed by not updating the
|
|
# file name if call level != 0 in the merge() function above.
|
|
# do avoid that a signal is emitted in that case, causing
|
|
# a reload of the preview and sourceview widgets
|
|
if self.stat.interp_state == linuxcnc.INTERP_IDLE:
|
|
self.emit('file-loaded', file_new)
|
|
|
|
#ToDo : Find a way to avoid signal when the line changed due to
|
|
# a remap procedure, because the signal do highlight a wrong
|
|
# line in the code
|
|
# current line
|
|
line_old = old.get('line', None)
|
|
line_new = self.old['line']
|
|
if line_new != line_old:
|
|
self.emit('line-changed', line_new)
|
|
|
|
tool_old = old.get('tool-in-spindle', None)
|
|
tool_new = self.old['tool-in-spindle']
|
|
if tool_new != tool_old:
|
|
self.emit('tool-in-spindle-changed', tool_new)
|
|
tool_num_old = old.get('tool-prep-number')
|
|
tool_num_new = self.old['tool-prep-number']
|
|
if tool_num_new != tool_num_old:
|
|
self.emit('tool-prep-changed', tool_num_new)
|
|
|
|
motion_mode_old = old.get('motion-mode', None)
|
|
motion_mode_new = self.old['motion-mode']
|
|
if motion_mode_new != motion_mode_old:
|
|
self.emit('motion-mode-changed', motion_mode_new)
|
|
|
|
motion_type_old = old.get('motion-type', None)
|
|
motion_type_new = self.old['motion-type']
|
|
if motion_type_new != motion_type_old:
|
|
self.emit('motion-type-changed', motion_type_new)
|
|
|
|
# if the homed status has changed
|
|
# check number of homed joints against number of available joints
|
|
# if they are equal send the all-homed signal
|
|
# else send the not-all-homed signal (with a string of unhomed joint numbers)
|
|
# if a joint is homed send 'homed' (with a string of homed joint number)
|
|
homed_joint_old = old.get('homed', None)
|
|
homed_joint_new = self.old['homed']
|
|
if homed_joint_new != homed_joint_old:
|
|
homed_joints = 0
|
|
unhomed_joints = ""
|
|
for joint in range(0, self.stat.joints):
|
|
if self.stat.homed[joint]:
|
|
homed_joints += 1
|
|
self.emit('homed', joint)
|
|
else:
|
|
self.emit('unhomed', joint)
|
|
unhomed_joints += str(joint)
|
|
if homed_joints == self.stat.joints:
|
|
self._is_all_homed = True
|
|
self.emit('all-homed')
|
|
else:
|
|
self._is_all_homed = False
|
|
self.emit('not-all-homed', unhomed_joints)
|
|
|
|
# override limits
|
|
or_limits_old = old.get('override-limits', None)
|
|
or_limits_new = self.old['override-limits']
|
|
or_limits_set_new = self.old['override-limits-set']
|
|
if or_limits_new != or_limits_old:
|
|
self.emit('override-limits-changed',or_limits_set_new, or_limits_new)
|
|
# hard limits tripped
|
|
t_list_old = old.get('hard-limits-list')
|
|
t_list_new = self.old['hard-limits-list']
|
|
if t_list_new != t_list_old:
|
|
hard_limits_tripped_new = self.old['hard-limits-tripped']
|
|
self.emit('hard-limits-tripped',hard_limits_tripped_new, t_list_new)
|
|
# current velocity
|
|
self.emit('current-feed-rate',self.stat.current_vel * 60.0)
|
|
# X relative position
|
|
position = self.stat.actual_position[0]
|
|
g5x_offset = self.stat.g5x_offset[0]
|
|
tool_offset = self.stat.tool_offset[0]
|
|
g92_offset = self.stat.g92_offset[0]
|
|
self.emit('current-x-rel-position',position-g5x_offset-tool_offset-g92_offset)
|
|
|
|
# calculate position offsets (native units)
|
|
p,rel_p,dtg = self.get_position()
|
|
self.emit('current-position',p, rel_p, dtg, self.stat.joint_actual_position)
|
|
|
|
# ferror
|
|
self.emit('following-error', self.old['ferror-current'])
|
|
|
|
# spindle control
|
|
spindle_enabled_old = old.get('spindle-enabled', None)
|
|
spindle_enabled_new = self.old['spindle-enabled']
|
|
spindle_direction_old = old.get('spindle-direction', None)
|
|
spindle_direction_new = self.old['spindle-direction']
|
|
up_to_speed_old = old.get('spindle-at-speed',None)
|
|
up_to_speed_new = self.old['spindle-at-speed']
|
|
if up_to_speed_new != up_to_speed_old or \
|
|
spindle_enabled_new != spindle_enabled_old or \
|
|
spindle_direction_new != spindle_direction_old:
|
|
self.emit('spindle-control-changed', 0, spindle_enabled_new, spindle_direction_new, up_to_speed_new)
|
|
# requested spindle speed
|
|
spindle_spd_old = old.get('spindle-speed', None)
|
|
spindle_spd_new = self.old['spindle-speed']
|
|
if spindle_spd_new != spindle_spd_old:
|
|
self.emit('requested-spindle-speed-changed', spindle_spd_new)
|
|
# actual spindle speed
|
|
act_spindle_spd_old = old.get('actual-spindle-speed', None)
|
|
act_spindle_spd_new = self.old['actual-spindle-speed']
|
|
if act_spindle_spd_new != act_spindle_spd_old:
|
|
self.emit('actual-spindle-speed-changed', act_spindle_spd_new)
|
|
# spindle override
|
|
spindle_or_old = old.get('spindle-or', None)
|
|
spindle_or_new = self.old['spindle-or']
|
|
if spindle_or_new != spindle_or_old:
|
|
self.emit('spindle-override-changed',spindle_or_new * 100)
|
|
# feed override
|
|
feed_or_old = old.get('feed-or', None)
|
|
feed_or_new = self.old['feed-or']
|
|
if feed_or_new != feed_or_old:
|
|
self.emit('feed-override-changed',feed_or_new * 100)
|
|
# rapid override
|
|
rapid_or_old = old.get('rapid-or', None)
|
|
rapid_or_new = self.old['rapid-or']
|
|
if rapid_or_new != rapid_or_old:
|
|
self.emit('rapid-override-changed',rapid_or_new * 100)
|
|
# max-velocity override
|
|
max_velocity_or_old = old.get('max-velocity-or', None)
|
|
max_velocity_or_new = self.old['max-velocity-or']
|
|
if max_velocity_or_new != max_velocity_or_old:
|
|
# work around misconfigured config (missing MAX_LINEAR_VELOCITY in TRAJ)
|
|
if max_velocity_or_new != 1e99:
|
|
self.emit('max-velocity-override-changed',max_velocity_or_new * 60)
|
|
# feed hold
|
|
feed_hold_old = old.get('feed-hold', None)
|
|
feed_hold_new = self.old['feed-hold']
|
|
if feed_hold_new != feed_hold_old:
|
|
self.emit('feed-hold-enabled-changed',feed_hold_new)
|
|
# mist
|
|
mist_old = old.get('mist', None)
|
|
mist_new = self.old['mist']
|
|
if mist_new != mist_old:
|
|
self.emit('mist-changed',mist_new)
|
|
# flood
|
|
flood_old = old.get('flood', None)
|
|
flood_new = self.old['flood']
|
|
if flood_new != flood_old:
|
|
self.emit('flood-changed',flood_new)
|
|
# rotation around Z
|
|
z_rot_old = old.get('current-z-rotation', None)
|
|
z_rot_new = self.old['current-z-rotation']
|
|
if z_rot_new != z_rot_old:
|
|
self.emit('current-z-rotation',z_rot_new)
|
|
# current tool offsets
|
|
tool_off_old = old.get('current-tool-offset', None)
|
|
tool_off_new = self.old['current-tool-offset']
|
|
if tool_off_new != tool_off_old:
|
|
self.emit('current-tool-offset',tool_off_new)
|
|
#############################
|
|
# Gcodes
|
|
#############################
|
|
# G-codes
|
|
g_code_old = old.get('g-code', None)
|
|
g_code_new = self.old['g-code']
|
|
if g_code_new != g_code_old:
|
|
self.emit('g-code-changed',g_code_new)
|
|
# metric mode g21
|
|
metric_old = old.get('metric', None)
|
|
metric_new = self.old['metric']
|
|
if metric_new != metric_old:
|
|
self.emit('metric-mode-changed',metric_new)
|
|
# G5x (active user system)
|
|
g5x_index_old = old.get('g5x-index', None)
|
|
g5x_index_new = self.old['g5x-index']
|
|
if g5x_index_new != g5x_index_old:
|
|
self.emit('user-system-changed',g5x_index_new)
|
|
|
|
# absolute mode g90
|
|
g90_old = old.get('g90', None)
|
|
g90_new = self.old['g90']
|
|
if g90_new != g90_old:
|
|
self.emit('g90-mode',g90_new)
|
|
|
|
# incremental mode g91
|
|
g91_old = old.get('g91', None)
|
|
g91_new = self.old['g91']
|
|
if g91_new != g91_old:
|
|
self.emit('g91-mode',g91_new)
|
|
|
|
# inverse time mode g93
|
|
itime_old = old.get('itime', None)
|
|
itime_new = self.old['itime']
|
|
if itime_new != itime_old:
|
|
self.emit('itime-mode',itime_new)
|
|
# feed per minute mode g94
|
|
fpm_old = old.get('fpm', None)
|
|
fpm_new = self.old['fpm']
|
|
if fpm_new != fpm_old:
|
|
self.emit('fpm-mode',fpm_new)
|
|
# feed per revolution mode g95
|
|
fpr_old = old.get('fpr', None)
|
|
fpr_new = self.old['fpr']
|
|
if fpr_new != fpr_old:
|
|
self.emit('fpr-mode',fpr_new)
|
|
# css mode g96
|
|
css_old = old.get('css', None)
|
|
css_new = self.old['css']
|
|
if css_new != css_old:
|
|
self.emit('css-mode',css_new)
|
|
# rpm mode g97
|
|
rpm_old = old.get('rpm', None)
|
|
rpm_new = self.old['rpm']
|
|
if rpm_new != rpm_old:
|
|
self.emit('rpm-mode',rpm_new)
|
|
# radius mode g8
|
|
radius_old = old.get('radius', None)
|
|
radius_new = self.old['radius']
|
|
if radius_new != radius_old:
|
|
self.emit('radius-mode',radius_new)
|
|
# diameter mode g7
|
|
diam_old = old.get('diameter', None)
|
|
diam_new = self.old['diameter']
|
|
if diam_new != diam_old:
|
|
self.emit('diameter-mode',diam_new)
|
|
####################################
|
|
# Mcodes
|
|
####################################
|
|
# M-codes
|
|
m_code_old = old.get('m-code', None)
|
|
m_code_new = self.old['m-code']
|
|
if m_code_new != m_code_old:
|
|
self.emit('m-code-changed',m_code_new)
|
|
tool_info_old = old.get('tool-info', None)
|
|
tool_info_new = self.old['tool-info']
|
|
if tool_info_new != tool_info_old:
|
|
self.emit('tool-info-changed', tool_info_new)
|
|
|
|
#####################################
|
|
# settings
|
|
#####################################
|
|
# feed code
|
|
f_code_old = old.get('f-code', None)
|
|
f_code_new = self.old['f-code']
|
|
if f_code_new != f_code_old:
|
|
self.emit('f-code-changed',f_code_new)
|
|
|
|
# g53 blend code
|
|
blend_code_old = old.get('blend-tolerance-code', None)
|
|
blend_code_new = self.old['blend-tolerance-code']
|
|
cam_code_old = old.get('nativecam-tolerance-code', None)
|
|
cam_code_new = self.old['nativecam-tolerance-code']
|
|
|
|
if blend_code_new != blend_code_old or \
|
|
blend_code_new != blend_code_old:
|
|
self.emit('blend-code-changed',blend_code_new, cam_code_new)
|
|
|
|
# AND DONE... Return true to continue timeout
|
|
self.emit('periodic')
|
|
return True
|
|
|
|
def forced_update(self):
|
|
try:
|
|
self.stat.poll()
|
|
except:
|
|
# Reschedule
|
|
return True
|
|
self.merge()
|
|
cmd_state_new = self.old['command-state']
|
|
if cmd_state_new == linuxcnc.RCS_EXEC:
|
|
self.emit('command-running')
|
|
elif cmd_state_new == linuxcnc.RCS_DONE:
|
|
self.emit('command-stopped')
|
|
elif cmd_state_new == linuxcnc.RCS_ERROR:
|
|
self.emit('command-error')
|
|
|
|
state_new = self.old['state']
|
|
if state_new > linuxcnc.STATE_ESTOP:
|
|
self.emit('state-estop-reset')
|
|
else:
|
|
self.emit('state-estop')
|
|
self.emit('state-off')
|
|
self.emit('interp-idle')
|
|
# override limits
|
|
or_limits_new = self.old['override-limits']
|
|
or_limits_set_new = self.old['override-limits-set']
|
|
self.emit('override-limits-changed',or_limits_set_new, or_limits_new)
|
|
# hard limits tripped
|
|
t_list_new = self.old['hard-limits-list']
|
|
hard_limits_tripped_new = self.old['hard-limits-tripped']
|
|
self.emit('hard-limits-tripped',hard_limits_tripped_new, t_list_new)
|
|
# overrides
|
|
feed_or_new = self.old['feed-or']
|
|
self.emit('feed-override-changed',feed_or_new * 100)
|
|
rapid_or_new = self.old['rapid-or']
|
|
self.emit('rapid-override-changed',rapid_or_new * 100)
|
|
max_velocity_or_new = self.old['max-velocity-or']
|
|
# work around misconfigured config (missing MAX_LINEAR_VELOCITY in TRAJ)
|
|
if max_velocity_or_new != 1e99:
|
|
self.emit('max-velocity-override-changed',max_velocity_or_new * 60)
|
|
spindle_or_new = self.old['spindle-or']
|
|
self.emit('spindle-override-changed',spindle_or_new * 100)
|
|
|
|
# spindle speed mpde
|
|
css_new = self.old['css']
|
|
self.emit('css-mode',css_new)
|
|
rpm_new = self.old['rpm']
|
|
self.emit('rpm-mode',rpm_new)
|
|
|
|
# absolute mode g90
|
|
g90_new = self.old['g90']
|
|
self.emit('g90-mode',g90_new)
|
|
# incremental mode g91
|
|
g91_new = self.old['g91']
|
|
self.emit('g91-mode',g91_new)
|
|
# feed mode:
|
|
itime_new = self.old['itime']
|
|
self.emit('itime-mode',itime_new)
|
|
fpm_new = self.old['fpm']
|
|
self.emit('fpm-mode',fpm_new)
|
|
fpr_new = self.old['fpr']
|
|
self.emit('fpr-mode',fpr_new)
|
|
# paused
|
|
paused_new = self.old['paused']
|
|
self.emit('program-pause-changed',paused_new)
|
|
# block delete
|
|
block_delete_new = self.old['block-delete']
|
|
self.emit('block-delete-changed',block_delete_new)
|
|
# optional_stop
|
|
optional_stop_new = self.old['optional-stop']
|
|
self.emit('optional-stop-changed',optional_stop_new)
|
|
# user system G5x
|
|
system_new = self.old['g5x-index']
|
|
self.emit('user-system-changed',system_new)
|
|
# radius mode g8
|
|
radius_new = self.old['radius']
|
|
self.emit('radius-mode',radius_new)
|
|
# diameter mode g7
|
|
diam_new = self.old['diameter']
|
|
self.emit('diameter-mode',diam_new)
|
|
# rotation around Z
|
|
z_rot_new = self.old['current-z-rotation']
|
|
self.emit('current-z-rotation',z_rot_new)
|
|
# current tool offsets
|
|
tool_off_new = self.old['current-tool-offset']
|
|
self.emit('current-tool-offset',tool_off_new)
|
|
|
|
# M-codes
|
|
m_code_new = self.old['m-code']
|
|
self.emit('m-code-changed',m_code_new)
|
|
flood_new = self.old['flood']
|
|
self.emit('flood-changed',flood_new)
|
|
mist_new = self.old['mist']
|
|
self.emit('mist-changed',mist_new)
|
|
|
|
# G-codes
|
|
g_code_new = self.old['g-code']
|
|
self.emit('g-code-changed',g_code_new)
|
|
# metric units G21
|
|
metric_new = self.old['metric']
|
|
self.emit('metric_mode_changed',metric_new)
|
|
# tool in spindle
|
|
tool_new = self.old['tool-in-spindle']
|
|
self.emit('tool-in-spindle-changed', tool_new)
|
|
tool_num_new = self.old['tool-prep-number']
|
|
self.emit('tool-prep-changed', tool_num_new)
|
|
|
|
# feed code
|
|
f_code_new = self.old['f-code']
|
|
self.emit('f-code-changed',f_code_new)
|
|
|
|
# g53 blend code
|
|
blend_code_new = self.old['blend-tolerance-code']
|
|
cam_code_new = self.old['nativecam-tolerance-code']
|
|
self.emit('blend-code-changed',blend_code_new, cam_code_new)
|
|
|
|
# Trajectory Motion mode
|
|
motion_mode_new = self.old['motion-mode']
|
|
self.emit('motion-mode-changed', motion_mode_new)
|
|
|
|
# Trajectory Motion type
|
|
motion_type_new = self.old['motion-type']
|
|
self.emit('motion-type-changed', motion_type_new)
|
|
|
|
# Spindle requested speed
|
|
spindle_spd_new = self.old['spindle-speed']
|
|
self.emit('requested-spindle-speed-changed', spindle_spd_new)
|
|
spindle_spd_new = self.old['actual-spindle-speed']
|
|
self.emit('actual-spindle-speed-changed', spindle_spd_new)
|
|
self.emit('spindle-control-changed', 0, False, 0, False)
|
|
self.emit('jograte-changed', self.current_jog_rate)
|
|
self.emit('jograte-angular-changed', self.current_angular_jog_rate)
|
|
self.emit('jogincrement-changed', self.current_jog_distance, self.current_jog_distance_text)
|
|
self.emit('jogincrement-angular-changed', self.current_jog_distance_angular, self.current_jog_distance_angular_text)
|
|
tool_info_new = self.old['tool-info']
|
|
self.emit('tool-info-changed', tool_info_new)
|
|
|
|
# homing
|
|
homed_joints = 0
|
|
unhomed_joints = ""
|
|
for joint in range(0, self.stat.joints):
|
|
if self.stat.homed[joint]:
|
|
homed_joints += 1
|
|
self.emit('homed', joint)
|
|
else:
|
|
self.emit('unhomed', joint)
|
|
unhomed_joints += str(joint)
|
|
if homed_joints == self.stat.joints:
|
|
self._is_all_homed = True
|
|
self.emit('all-homed')
|
|
else:
|
|
self._is_all_homed = False
|
|
self.emit('not-all-homed', unhomed_joints)
|
|
|
|
# ferror
|
|
self.emit('following-error', self.old['ferror-current'])
|
|
|
|
# update external objects
|
|
self.emit('forced-update')
|
|
|
|
# ********** Helper function ********************
|
|
def get_position(self):
|
|
p = self.stat.actual_position
|
|
mp = self.stat.position
|
|
dtg = self.stat.dtg
|
|
|
|
x = p[0] - self.stat.g5x_offset[0] - self.stat.tool_offset[0]
|
|
y = p[1] - self.stat.g5x_offset[1] - self.stat.tool_offset[1]
|
|
z = p[2] - self.stat.g5x_offset[2] - self.stat.tool_offset[2]
|
|
a = p[3] - self.stat.g5x_offset[3] - self.stat.tool_offset[3]
|
|
b = p[4] - self.stat.g5x_offset[4] - self.stat.tool_offset[4]
|
|
c = p[5] - self.stat.g5x_offset[5] - self.stat.tool_offset[5]
|
|
u = p[6] - self.stat.g5x_offset[6] - self.stat.tool_offset[6]
|
|
v = p[7] - self.stat.g5x_offset[7] - self.stat.tool_offset[7]
|
|
w = p[8] - self.stat.g5x_offset[8] - self.stat.tool_offset[8]
|
|
|
|
if self.stat.rotation_xy != 0:
|
|
t = math.radians(-self.stat.rotation_xy)
|
|
xr = x * math.cos(t) - y * math.sin(t)
|
|
yr = x * math.sin(t) + y * math.cos(t)
|
|
x = xr
|
|
y = yr
|
|
|
|
x -= self.stat.g92_offset[0]
|
|
y -= self.stat.g92_offset[1]
|
|
z -= self.stat.g92_offset[2]
|
|
a -= self.stat.g92_offset[3]
|
|
b -= self.stat.g92_offset[4]
|
|
c -= self.stat.g92_offset[5]
|
|
u -= self.stat.g92_offset[6]
|
|
v -= self.stat.g92_offset[7]
|
|
w -= self.stat.g92_offset[8]
|
|
|
|
relp = [x, y, z, a, b, c, u, v, w]
|
|
return p,relp,dtg
|
|
|
|
# check for required modes
|
|
# fail if mode is 0
|
|
# fail if machine is busy
|
|
# true if all ready in mode
|
|
# None if possible to change
|
|
def check_for_modes(self, *modes):
|
|
def running(s):
|
|
return s.task_mode == linuxcnc.MODE_AUTO and s.interp_state != linuxcnc.INTERP_IDLE
|
|
self.stat.poll()
|
|
premode = self.stat.task_mode
|
|
if not modes: return (None, premode)
|
|
try:
|
|
if self.stat.task_mode in modes[0]: return (True, premode)
|
|
except:
|
|
if self.stat.task_mode == modes[0]: return (True, premode)
|
|
if running( self.stat): return (None, premode)
|
|
return (False, premode)
|
|
|
|
def get_current_mode(self):
|
|
return self.old['mode']
|
|
|
|
# linear - in machine units
|
|
def set_jograte(self, upm):
|
|
self.current_jog_rate = upm
|
|
self.emit('jograte-changed', upm)
|
|
|
|
def get_jograte(self):
|
|
return self.current_jog_rate
|
|
|
|
def set_jograte_angular(self,rate):
|
|
self.current_angular_jog_rate = rate
|
|
self.emit('jograte-angular-changed', rate)
|
|
|
|
def get_jograte_angular(self):
|
|
return self.current_angular_jog_rate
|
|
|
|
def get_jog_increment_angular(self):
|
|
return self.current_jog_distance_angular
|
|
|
|
def set_jog_increment_angular(self, distance, text):
|
|
try:
|
|
isinstance(float(distance), float)
|
|
except:
|
|
print('error converting angular jog increment ({}) to float: staying at {}'.format(distance,self.current_jog_distance_angular))
|
|
return
|
|
self.current_jog_distance_angular = distance
|
|
self.current_jog_distance_text_angular = text
|
|
self.emit('jogincrement-angular-changed', distance, text)
|
|
|
|
# should be in machine units
|
|
def set_jog_increments(self, distance, text):
|
|
try:
|
|
isinstance(float(distance), float)
|
|
except:
|
|
print('error converting jog increment ({}) to float: staying at {}'.format(distance,self.current_jog_distance))
|
|
return
|
|
self.current_jog_distance = distance
|
|
self.current_jog_distance_text = text
|
|
self.emit('jogincrement-changed', distance, text)
|
|
|
|
def get_jog_increment(self):
|
|
return self.current_jog_distance
|
|
|
|
def get_max_velocity(self):
|
|
return self.old['max-velocity-or'] * 60
|
|
|
|
def set_selected_joint(self, data):
|
|
self.selected_joint = int(data)
|
|
self.emit('joint-selection-changed', data)
|
|
|
|
def get_selected_joint(self):
|
|
return self.selected_joint
|
|
|
|
def set_selected_axis(self, data):
|
|
self.selected_axis = str(data)
|
|
self.emit('axis-selection-changed', data)
|
|
|
|
def get_selected_axis(self):
|
|
return self.selected_axis
|
|
|
|
def is_joint_homed(self, joint):
|
|
self.stat.poll()
|
|
return bool(self.stat.homed[joint])
|
|
|
|
def is_all_homed(self):
|
|
return self._is_all_homed
|
|
|
|
def is_homing(self):
|
|
for j in range(0, self.stat.joints):
|
|
if self.stat.joint[j].get('homing'):
|
|
return True
|
|
return False
|
|
|
|
def machine_is_on(self):
|
|
return self.old['state'] > linuxcnc.STATE_OFF
|
|
|
|
def estop_is_clear(self):
|
|
self.stat.poll()
|
|
return self.stat.task_state > linuxcnc.STATE_ESTOP
|
|
|
|
def is_man_mode(self):
|
|
self.stat.poll()
|
|
return self.stat.task_mode == linuxcnc.MODE_MANUAL
|
|
|
|
def is_mdi_mode(self):
|
|
self.stat.poll()
|
|
return self.stat.task_mode == linuxcnc.MODE_MDI
|
|
|
|
def is_auto_mode(self):
|
|
self.stat.poll()
|
|
return self.stat.task_mode == linuxcnc.MODE_AUTO
|
|
|
|
def is_on_and_idle(self):
|
|
self.stat.poll()
|
|
return self.stat.task_state > linuxcnc.STATE_OFF and self.stat.interp_state == linuxcnc.INTERP_IDLE
|
|
|
|
def is_auto_running(self):
|
|
self.stat.poll()
|
|
return self.stat.task_mode == linuxcnc.MODE_AUTO and self.stat.interp_state != linuxcnc.INTERP_IDLE
|
|
|
|
def is_auto_paused(self):
|
|
return self.old['paused']
|
|
|
|
def is_interp_running(self):
|
|
self.stat.poll()
|
|
return self.stat.interp_state != linuxcnc.INTERP_IDLE
|
|
|
|
def is_interp_paused(self):
|
|
self.stat.poll()
|
|
return self.stat.interp_state == linuxcnc.INTERP_PAUSED
|
|
|
|
def is_interp_reading(self):
|
|
self.stat.poll()
|
|
return self.stat.interp_state == linuxcnc.INTERP_READING
|
|
|
|
def is_interp_waiting(self):
|
|
self.stat.poll()
|
|
return self.stat.interp_state == linuxcnc.INTERP_WAITING
|
|
|
|
def is_interp_idle(self):
|
|
self.stat.poll()
|
|
return self.stat.interp_state == linuxcnc.INTERP_IDLE
|
|
|
|
def is_file_loaded(self):
|
|
self.stat.poll()
|
|
if self.stat.file:
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
def is_metric_mode(self):
|
|
return self.old['metric']
|
|
|
|
def is_spindle_on(self, num = 0):
|
|
self.stat.poll()
|
|
return self.stat.spindle[num]['enabled']
|
|
|
|
def get_spindle_speed(self, num):
|
|
self.stat.poll()
|
|
return self.stat.spindle[num]['speed']
|
|
|
|
def is_joint_mode(self):
|
|
try:
|
|
self.stat.poll()
|
|
except:
|
|
return None
|
|
return bool(self.stat.motion_mode == linuxcnc.TRAJ_MODE_FREE)
|
|
|
|
def is_status_valid(self):
|
|
return self._status_active
|
|
|
|
def is_limits_override_set(self):
|
|
return self.old['override-limits-set']
|
|
|
|
def is_hard_limits_tripped(self):
|
|
return self.old['hard-limits-tripped']
|
|
|
|
def get_current_tool(self):
|
|
self.stat.poll()
|
|
return self.stat.tool_in_spindle
|
|
|
|
def set_tool_touchoff(self,tool,axis,value):
|
|
premode = None
|
|
m = "G10 L10 P%d %s%f"%(tool,axis,value)
|
|
self.stat.poll()
|
|
if self.stat.task_mode != linuxcnc.MODE_MDI:
|
|
premode = self.stat.task_mode
|
|
self.cmd.mode(linuxcnc.MODE_MDI)
|
|
self.cmd.wait_complete()
|
|
self.cmd.mdi(m)
|
|
self.cmd.wait_complete()
|
|
self.cmd.mdi("g43")
|
|
self.cmd.wait_complete()
|
|
if premode:
|
|
self.cmd.mode(premode)
|
|
|
|
def set_axis_origin(self,axis,value):
|
|
premode = None
|
|
m = "G10 L20 P0 %s%f"%(axis,value)
|
|
self.stat.poll()
|
|
if self.stat.task_mode != linuxcnc.MODE_MDI:
|
|
premode = self.stat.task_mode
|
|
self.cmd.mode(linuxcnc.MODE_MDI)
|
|
self.cmd.wait_complete()
|
|
self.cmd.mdi(m)
|
|
self.cmd.wait_complete()
|
|
if premode:
|
|
self.cmd.mode(premode)
|
|
self.emit('reload-display')
|
|
|
|
def do_jog(self, axisnum, direction, distance=0):
|
|
jjogmode,j_or_a = self.get_jog_info(axisnum)
|
|
if direction == 0:
|
|
self.cmd.jog(linuxcnc.JOG_STOP, jjogmode, j_or_a)
|
|
else:
|
|
if axisnum in (3,4,5):
|
|
rate = self.current_angular_jog_rate
|
|
else:
|
|
rate = self.current_jog_rate/60
|
|
if distance == 0:
|
|
self.cmd.jog(linuxcnc.JOG_CONTINUOUS, jjogmode, j_or_a, direction * rate)
|
|
else:
|
|
self.cmd.jog(linuxcnc.JOG_INCREMENT, jjogmode, j_or_a, direction * rate, distance)
|
|
|
|
def get_jjogmode(self):
|
|
self.stat.poll()
|
|
if self.stat.motion_mode == linuxcnc.TRAJ_MODE_FREE:
|
|
return JOGJOINT
|
|
if self.stat.motion_mode == linuxcnc.TRAJ_MODE_TELEOP:
|
|
return JOGTELEOP
|
|
print("commands.py: unexpected motion_mode",self.stat.motion_mode)
|
|
return JOGTELEOP
|
|
|
|
def jnum_for_axisnum(self,axisnum):
|
|
if self.stat.kinematics_type != linuxcnc.KINEMATICS_IDENTITY:
|
|
print("\n%s:\n Joint jogging not supported for"
|
|
"non-identity kinematics"%__file__)
|
|
return -1 # emcJogCont() et al reject neg joint/axis no.s
|
|
jnum = trajcoordinates.index( "xyzabcuvw"[axisnum] )
|
|
if jnum > jointcount:
|
|
print("\n%s:\n Computed joint number=%d for axisnum=%d "
|
|
"exceeds jointcount=%d with trajcoordinates=%s"
|
|
%(__file__,jnum,axisnum,jointcount,trajcoordinates))
|
|
# Note: primary gui should protect for this misconfiguration
|
|
# decline to jog
|
|
return -1 # emcJogCont() et al reject neg joint/axis no.s
|
|
return jnum
|
|
|
|
def get_jog_info (self,axisnum):
|
|
jjogmode = self.get_jjogmode()
|
|
j_or_a = axisnum
|
|
if jjogmode == JOGJOINT: j_or_a = self.jnum_for_axisnum(axisnum)
|
|
return jjogmode,j_or_a
|
|
|
|
def get_probed_position_with_offsets(self) :
|
|
self.stat.poll()
|
|
probed_position=list(self.stat.probed_position)
|
|
coord=list(self.stat.probed_position)
|
|
g5x_offset=list(self.stat.g5x_offset)
|
|
g92_offset=list(self.stat.g92_offset)
|
|
tool_offset=list(self.stat.tool_offset)
|
|
for i in range(0, len(probed_position)-1):
|
|
coord[i] = probed_position[i] - g5x_offset[i] - g92_offset[i] - tool_offset[i]
|
|
angl=self.stat.rotation_xy
|
|
res=self._rott00_point(coord[0],coord[1],-angl)
|
|
coord[0]=res[0]
|
|
coord[1]=res[1]
|
|
return coord
|
|
|
|
# rotate around 0,0 point coordinates
|
|
def _rott00_point(self,x1=0.,y1=0.,a1=0.) :
|
|
coord = [x1,y1]
|
|
if a1 != 0:
|
|
t = math.radians(a1)
|
|
coord[0] = x1 * math.cos(t) - y1 * math.sin(t)
|
|
coord[1] = x1 * math.sin(t) + y1 * math.cos(t)
|
|
return coord
|
|
|
|
def shutdown(self):
|
|
self.emit('shutdown')
|
|
|
|
def __getitem__(self, item):
|
|
return getattr(self, item)
|
|
def __setitem__(self, item, value):
|
|
return setattr(self, item, value)
|
|
|
|
class GStat(_GStat):
|
|
_instance = None
|
|
def __new__(cls, *args, **kwargs):
|
|
if not cls._instance:
|
|
cls._instance = _GStat.__new__(cls, *args, **kwargs)
|
|
return cls._instance
|