Example #1
0
 def _init(self):
     Logger().trace("MerlinOrionAxis._init()")
     AbstractHardwarePlugin._init(self)
     AbstractAxisPlugin._init(self)
     self._hardware = MerlinOrionHardware()
     self.__run = False
     self.__driveEvent = threading.Event()
     self.__setPoint = None
     self.__currentPos = None
Example #2
0
class MerlinOrionShutter(AbstractHardwarePlugin, ShutterPlugin):
    def __init__(self, *args, **kwargs):
        """
        """
        AbstractHardwarePlugin.__init__(self, *args, **kwargs)
        ShutterPlugin.__init__(self, *args, **kwargs)

    def _init(self):
        Logger().trace("MerlinOrionShutter._init()")
        AbstractHardwarePlugin._init(self)
        ShutterPlugin._init(self)
        self._hardware = MerlinOrionHardware()

    def _defineConfig(self):
        AbstractHardwarePlugin._defineConfig(self)
        ShutterPlugin._defineConfig(self)

    def _triggerOnShutter(self):
        """ Set the shutter on.
        """
        self._hardware.setOutput(True)

    def _triggerOffShutter(self):
        """ Set the shutter off.
        """
        self._hardware.setOutput(False)

    def init(self):
        Logger().trace("MerlinOrionShutter.init()")
        self._hardware.setAxis(AXIS_TABLE[self.capacity]),
        AbstractHardwarePlugin.init(self)
        ShutterPlugin.init(self)

    def shutdown(self):
        Logger().trace("MerlinOrionShutter.shutdown()")
        self._triggerOffShutter()
        AbstractHardwarePlugin.shutdown(self)
        ShutterPlugin.shutdown(self)
Example #3
0
 def _init(self):
     Logger().trace("MerlinOrionShutter._init()")
     AbstractHardwarePlugin._init(self)
     ShutterPlugin._init(self)
     self._hardware = MerlinOrionHardware()
Example #4
0
class MerlinOrionAxis(AbstractHardwarePlugin, AbstractAxisPlugin, QtCore.QThread):
    """
    """
    def __init__(self, *args, **kwargs):
        AbstractHardwarePlugin.__init__(self, *args, **kwargs)  # Only 1?
        AbstractAxisPlugin.__init__(self, *args, **kwargs)
        QtCore.QThread.__init__(self)

    def __onPositionUpdate(self, yaw, pitch):
        """ Refresh position according to new pos.

        @param yaw: yaw axis value
        @type yaw: float

        @param pitch: pitch axix value
        @type pitch: float
        """
        if self.capacity == 'yawAxis':
            self.__currentPos = yaw
        else:
            self.__currentPos = pitch

    def _init(self):
        Logger().trace("MerlinOrionAxis._init()")
        AbstractHardwarePlugin._init(self)
        AbstractAxisPlugin._init(self)
        self._hardware = MerlinOrionHardware()
        self.__run = False
        self.__driveEvent = threading.Event()
        self.__setPoint = None
        self.__currentPos = None

    def _defineConfig(self):
        AbstractAxisPlugin._defineConfig(self)
        AbstractHardwarePlugin._defineConfig(self)
        self._addConfigKey('_alternateDrive', 'ALTERNATE_DRIVE', default=DEFAULT_ALTERNATE_DRIVE)
        self._addConfigKey('_alternateDrive', 'ALTERNATE_DRIVE_ANGLE', default=DEFAULT_ALTERNATE_DRIVE_ANGLE)
        self._addConfigKey('_inertiaAngle', 'INERTIA_ANGLE', default=DEFAULT_INERTIA_ANGLE)
        self._addConfigKey('_overwriteEncoderFullCircle', 'OVERWRITE_ENCODER_FULL_CIRCLE', default=DEFAULT_OVERWRITE_ENCODER_FULL_CIRCLE)
        self._addConfigKey('_encoderFullCircle', 'ENCODER_FULL_CIRCLE', default=DEFAULT_ENCODER_FULL_CIRCLE)

    def activate(self):
        Logger().trace("MerlinOrionPlugin.activate()")
        AbstractAxisPlugin.activate(self)

        # Start the thread
        self.start()

    def deactivate(self):
        Logger().trace("MerlinOrionPlugin.deactivate()")

        # Stop the thread
        self._stopThread()

        AbstractAxisPlugin.deactivate(self)

    def init(self):
        Logger().trace("MerlinOrionAxis.init()")
        self._hardware.setAxis(AXIS_TABLE[self.capacity]),
        AbstractHardwarePlugin.init(self)
        if self._config['OVERWRITE_ENCODER_FULL_CIRCLE']:
            self._hardware.overwriteEncoderFullCircle(self._config['ENCODER_FULL_CIRCLE'])

        # Connect Spy update signal
        self.connect(Spy(), QtCore.SIGNAL("update"), self.__onPositionUpdate, QtCore.Qt.BlockingQueuedConnection)

    def shutdown(self):
        Logger().trace("MerlinOrionAxis.shutdown()")
        self.stop()
        AbstractHardwarePlugin.shutdown(self)
        AbstractAxisPlugin.shutdown(self)

        # Disconnect Spy update signal
        self.disconnect(Spy(), QtCore.SIGNAL("update"), self.__onPositionUpdate)

    def configure(self):
        AbstractAxisPlugin.configure(self)
        AbstractHardwarePlugin.configure(self)
        if self._config['OVERWRITE_ENCODER_FULL_CIRCLE']:
            self._hardware.overwriteEncoderFullCircle(self._config['ENCODER_FULL_CIRCLE'])
        else:
            self._hardware.useFirmwareEncoderFullCircle()

    def run(self):
        """ Main entry of the thread.
        """
        threadName = "%s_%s" % (self.name, self.capacity)
        threading.currentThread().setName(threadName)
        Logger().debug("MerlinOrionAxis.run(): start thread")
        self.__run = True
        while self.__run:
            self.__driveEvent.wait()

            # Check again __run flag to see if _stopThread has been called
            if self.__run:

                # Choose alternate drive if needed
                currentPos = self.read()
                if self._config['ALTERNATE_DRIVE'] and \
                   1.1 * self._config['INERTIA_ANGLE'] < abs(self.__setPoint - currentPos) < self._config['ALTERNATE_DRIVE_ANGLE']:
                    self._alternateDrive(self.__setPoint)

                # Use standard drive to reach the position
                if self.__driveEvent.isSet():
                    self._directDrive(self.__setPoint)

        Logger().debug("MerlinOrionAxis.run(): thread terminated")

    def _stopThread(self):
        """ Stop the thread.
        """
        self.__run = False
        self.__driveEvent.set()
        self.wait()

    def read(self):
        pos = self._hardware.read() - self._offset
        return pos

    def drive(self, pos, useOffset=True, wait=True):
        Logger().debug("MerlinOrionAxis.drive(): '%s' drive to %.1f" % (self.capacity, pos))
        currentPos = self.read()

        self._checkLimits(pos)

        # Only move if needed
        if abs(pos - currentPos) > AXIS_ACCURACY or not useOffset:
            if not useOffset:  # Move before if?
                pos -= self._offset

            self.__setPoint = pos
            self.__driveEvent.set() # Start thread action

            # Wait end of movement
            if wait:
                self.waitEndOfDrive()

    def _directDrive(self, pos):
        """ Direct drive.

        This method uses the Merlin/Orion internal closed loop regulation.

        @param pos: position to reach, in °
        @type pos: float
        """
        Logger().trace("MerlinOrionAxis._directDrive()")
        pos += self._offset
        self._hardware.drive(pos)
        self.__driveEvent.clear()

    def _alternateDrive(self, pos):
        """ Alternate drive.

        This method implements an external closed-loop regulation.
        It is faster for angles < 6-7°, because in this case, the
        head does not accelerate to full speed, but rather stays at
        very low speed.

        @param pos: position to reach, in °
        @type pos: float
        """
        Logger().trace("MerlinOrionAxis._alternateDrive()")

        # Compute initial direction
        # BUG!!! Arm side is not taken in account!!!
        if pos > self.__currentPos:
            dir_ = '+'
        else:
            dir_ = '-'
        self._hardware.startJog(dir_, MANUAL_SPEED_TABLE['alternate'])

        # Check when to stop
        #while ((dir_ == '-' and self.__currentPos - pos > self._config['INERTIA_ANGLE']) or \
               #(dir_ == '+' and pos - self.__currentPos > self._config['INERTIA_ANGLE'])) and \
              #self.__driveEvent.isSet():
        while abs(self.__currentPos - pos) > self._config['INERTIA_ANGLE'] and self.__driveEvent.isSet():
            time.sleep(config.SPY_REFRESH_DELAY / 1000.)

        self._hardware.stop()

    def waitEndOfDrive(self):
        while self.isMoving():
            time.sleep(config.SPY_REFRESH_DELAY / 1000.)
        self.waitStop()

    def startJog(self, dir_):
        self._hardware.startJog(dir_, MANUAL_SPEED_TABLE[self._manualSpeed])

    def stop(self):
        self.__driveEvent.clear()
        self._hardware.stop()

    def waitStop(self):
        previousPos = self.__currentPos
        time.sleep(config.SPY_REFRESH_DELAY / 1000.)
        while abs(previousPos - self.__currentPos) > AXIS_ACCURACY:
            previousPos = self.__currentPos
            time.sleep(config.SPY_REFRESH_DELAY / 1000.)

    def isMoving(self):
        status = self._hardware.getStatus()
        if status[1] != '0' or self.__driveEvent.isSet():
            return True
        else:
            return False