From 1fd3f21436a53375a59035486cf3d2e1a6035bbb Mon Sep 17 00:00:00 2001 From: "Wolfgang Draxinger (root@gar-ex-erdastep)" Date: Fri, 9 Dec 2011 22:29:15 +0100 Subject: rpyc too laggy --- MotionControl/Axis.py | 8 +++++++- MotionControl/MotionStage.py | 36 ++++++++++++++++++++++-------------- MotionControl/PhytronAxis.py | 9 +++++++-- MotionControl/Service.py | 31 +++++++++++++++++++++++++++++++ motiond/motiond | 38 ++++++++++++++++++++++++++++++++++++-- 5 files changed, 103 insertions(+), 19 deletions(-) create mode 100644 MotionControl/Service.py diff --git a/MotionControl/Axis.py b/MotionControl/Axis.py index 4d669c5..d137d54 100644 --- a/MotionControl/Axis.py +++ b/MotionControl/Axis.py @@ -1,8 +1,9 @@ # -*- coding: utf8 -*- class Axis(object): - def __init__(self, inverted = False, scale={}): + def __init__(self, limits=None, inverted = False, scale={}): from blinker import Signal + self.limits = limits self.inverted = inverted self.scale = scale self.position = None @@ -71,6 +72,11 @@ class Axis(object): raise NotImplementedError() def goto_absolute(self, target, speed = None): + if self.limits and (target < min(self.limits) or target > max(self.limits)): + raise ValueError() + self.do_goto_absolute(target, speed) + + def do_goto_absolute(self, target, speed): raise NotImplementedError() def goto_relative(self, offset, speed = None): diff --git a/MotionControl/MotionStage.py b/MotionControl/MotionStage.py index 2e3583f..90f811a 100644 --- a/MotionControl/MotionStage.py +++ b/MotionControl/MotionStage.py @@ -20,10 +20,10 @@ class MotionStage(object): self.onCycleAborted = Signal() self.onDestinationChanged = Signal() - self.onPositionChanged = Signal() + self.onPositionChanged = Signal() for axis in self.axes: - axis.onPosition.connect(self.forward_onPosition) + axis.onPosition.connect(self.onPosition_repeat) self.worker_thread = None self.active = False @@ -48,15 +48,13 @@ class MotionStage(object): def position(self): return tuple([axis.position for axis in self.axes]) - def forward_onPosition(self, sender, position): + def onPosition_repeat(self, sender, position): self.onPositionChanged.send(self, axis=self.axes_idx[sender], position=position) def update(self): old_position = self.position for axis in self.axes: axis.update() - if old_position != self.position: - self.onPositionChanged.send(self, position = self.position) def set_destination(self, destination): current_position = self.position @@ -89,22 +87,23 @@ class MotionStage(object): self.cycle_add_action(GotoAbsolute(self.axes, self.destination, speed)) def can_cycle_start(self): - if self.active: - return False return True # FIXME: Add constraint tests here def cycle_start(self): import threading, weakref - if not self.can_cycle_start(): + if self.active: return False +# if not self.can_cycle_start(): +# return False + self.current_action = None self.active = True - self.worker_thread = threading.Thread(target = MotionStage.cycle_worker, name = "MotionControl.worker", args=(weakref.proxy(self),)) - self.worker_thread.daemon =True + self.worker_thread = threading.Thread(target = MotionStage.cycleWorker, name = "MotionControl.cycleWorker", args=(weakref.proxy(self),)) + self.worker_thread.daemon = True self.worker_thread.start() - self.onCycleStarted.send() + self.onCycleStarted.send(self) def abort(self): import threading @@ -112,7 +111,7 @@ class MotionStage(object): if isinstance(self.worker_thread, threading.Thread): self.worker_thread.join() - def cycle_worker(ref): + def cycleWorker(ref): abort_action = ref.abort_action try: import time @@ -136,10 +135,10 @@ class MotionStage(object): ref.action_queue.task_done() - ref.onCycleFinished.send() + ref.onCycleFinished.send(ref) except CycleAbort: ref.abort_action.execute() - ref.onCycleAborted.send() + ref.onCycleAborted.send(ref) finally: try: @@ -149,3 +148,12 @@ class MotionStage(object): except: pass ref.active = False + + def reference(self): + from Action import Initiate, GotoAbsolute + self.destination = None + self.cycle_clear() + self.cycle_add_action(Initiate([self.axes[0]])) + self.cycle_add_action(GotoAbsolute([self.axes[0]], [0])) + self.cycle_start() + diff --git a/MotionControl/PhytronAxis.py b/MotionControl/PhytronAxis.py index 80e1c47..986dad7 100644 --- a/MotionControl/PhytronAxis.py +++ b/MotionControl/PhytronAxis.py @@ -5,8 +5,8 @@ from Axis import Axis class PhytronAxis(Axis): INITIATOR_MINUS = 1 INITIATOR_PLUS = 2 - def __init__(self, ipcomm_axis, max_run_freq=None, initiator=INITIATOR_MINUS, initiator_position = 0, inverted = False, scale={}): - super(PhytronAxis, self).__init__(inverted = inverted, scale = scale) + def __init__(self, ipcomm_axis, limits=None, max_run_freq=None, initiator=INITIATOR_MINUS, initiator_position = 0, inverted = False, limited = True, scale={}): + super(PhytronAxis, self).__init__(limits = limits, inverted = inverted, scale = scale) self.ipcomm_axis = ipcomm_axis if not max_run_freq: @@ -16,6 +16,11 @@ class PhytronAxis(Axis): self.initiator = initiator self.initiator_position = initiator_position self.onInitialized.connect(self.handle_initialized) + + self.ipcomm_axis.limited = limited + + def __del__(self): + self.ipcomm_axis.stop() def handle_initialized(self, sender, initialized): if self.initialisation and sender == self and initialized: diff --git a/MotionControl/Service.py b/MotionControl/Service.py new file mode 100644 index 0000000..241d141 --- /dev/null +++ b/MotionControl/Service.py @@ -0,0 +1,31 @@ +# -*- coding: utf-8 -*- + +import rpyc + +class Service(rpyc.Service): + stage = None + def on_connect(self): + Service.stage.onPositionChanged.connect(self.onPosition) + + for i,p in enumerate(Service.stage.position): + self.onPosition(None, i, p) + + def on_disconnect(self): + Service.stage.onPositionChanged.disconnect(self.onPosition) + + def onPosition(self, sender, axis, position): + rpyc.async(self._conn.root.onPosition)(axis, position) + + def exposed_set_destination(self, destination): + Service.stage.set_destination(destination) + def exposed_cycle_start(self): + Service.stage.cycle_start() + def exposed_abort(self): + Service.stage.abort() + + def exposed_reference(self): + Service.stage.reference() + + def exposed_getAxisLimits(self, axis): + return Service.stage.axes[axis].limits + diff --git a/motiond/motiond b/motiond/motiond index 3bfbde2..64ddaff 100755 --- a/motiond/motiond +++ b/motiond/motiond @@ -1,12 +1,13 @@ #!/usr/bin/python2 # -*- encoding: utf-8 -*- +STAGE_POSITION_STORE = '/var/lib/erdastep/laststageposition' + import Phytron import MotionControl.MotionStage, MotionControl.PhytronAxis, MotionControl.Service from MotionControl.MotionStage import MotionStage from MotionControl.PhytronAxis import PhytronAxis -from MotionControl.Service import Service ipcomm = Phytron.IPCOMM('/dev/ttyERDASTEP', axes=4) @@ -14,12 +15,14 @@ axis_x = PhytronAxis( ipcomm[0], \ max_run_freq = 825, \ initiator = PhytronAxis.INITIATOR_PLUS, \ initiator_position = 221786, \ + limits = (-179000, 221000), \ scale = {'mm': 8000} ) axis_y = PhytronAxis( ipcomm[1], \ max_run_freq = 825, \ initiator = PhytronAxis.INITIATOR_PLUS, \ initiator_position = 115256, \ + limits = (-285000, 115000), \ scale = {'mm': 8000} ) axis_z = PhytronAxis( ipcomm[2], \ @@ -27,20 +30,51 @@ axis_z = PhytronAxis( ipcomm[2], \ initiator = PhytronAxis.INITIATOR_PLUS, \ # FIXME: Z zero position needs yet to be determined initiator_position = 217952, \ + limits = (-183000, 217000), \ scale = {'mm': 8000} ) axis_phi = PhytronAxis( ipcomm[3], \ max_run_freq = 1000, \ initiator = PhytronAxis.INITIATOR_MINUS, \ initiator_position = -273432, \ + limits = (-273000, 271000), \ scale = {'°': 1600} ) stage_axes = (axis_x, axis_y, axis_z, axis_phi) -Service.stage = MotionStage(stage_axes) +stage = MotionStage(stage_axes) + +def load_stage_position_store(): + try: + position = tuple( [int(line.strip()) for line in open(STAGE_POSITION_STORE)] ) + except: + return + for i,p in enumerate(position): + ipcomm[i].position = p + +def update_stage_position_store(): +# try: + store = open(STAGE_POSITION_STORE, 'w') + store.writelines([str(axis.position)+'\n' for axis in ipcomm]) + store.close() +# except: +# pass + +def onCycleTermination(sender): + update_stage_position_store() + +stage.onCycleFinished.connect(onCycleTermination) +stage.onCycleAborted.connect(onCycleTermination) if __name__ == "__main__": from rpyc.utils.server import ThreadedServer + from MotionControl.Service import Service + + load_stage_position_store() + + stage.update() + + Service.stage = stage server = ThreadedServer(Service, port = 12345) server.start() -- cgit v1.2.3