Commit 4c62b963 authored by marco-buttu's avatar marco-buttu
Browse files

Implemented startUpdating during rewinding

A test has been added in pyunit/positioner/test_startUpdating.py
parent 8c653820
Loading
Loading
Loading
Loading
+39 −15
Original line number Diff line number Diff line
@@ -353,9 +353,33 @@ class DewarPositionerImpl(POA, cc, services, lcycle):
        res += 'rewindingOffset: %.4f' %info.rewindingOffset
        return res
        

    def getScanInfo(self):
        return ScanInfo(**self.positioner.getScanInfo())


    def checkUpdating(self, stime, axis, sector, az, el, ra, dec):
        try:
            return self.positioner.checkUpdating(
                stime, axis, sector, az, el, ra, dec
            )
        except PositionerError, ex:
            logger.logError(ex.message)
            exc = ComponentErrorsImpl.OperationErrorExImpl()
            exc.setReason(ex.message)
            raise exc.getComponentErrorsEx()
        except NotAllowedError, ex:
            logger.logError(ex.message)
            exc = ComponentErrorsImpl.NotAllowedExImpl()
            exc.setReason(ex.message)
            raise exc.getComponentErrorsEx()
        except Exception, ex:
            logger.logError(ex.message)
            exc = ComponentErrorsImpl.UnexpectedExImpl(ex.message)
            exc.setReason(ex.message)
            raise exc.getComponentErrorsEx()


    def startUpdating(self, axis, sector, az, el, ra, dec):
        logger.logNotice('starting the derotator position updating')
        try:
@@ -570,7 +594,7 @@ class DewarPositionerImpl(POA, cc, services, lcycle):


    def setConfiguration(self, confCode):
        if self.positioner.isUpdating():
        if self.positioner.isUpdating() and not self.isRewinding():
            self.positioner.stopUpdating()
            # The unit of time is `seconds`
            max_wait_time = 2 
+90 −12
Original line number Diff line number Diff line
from __future__ import with_statement
from __future__ import with_statement, division
import threading
import datetime
import time
@@ -143,6 +143,78 @@ class Positioner(object):
                %(self.control.target, self.device.getMinLimit(), self.device.getMaxLimit()))


    def checkUpdating(self, stime, axis, sector, az, el, ra, dec):
        sectors = ('ANT_NORTH', 'ANT_SOUTH')
        if not self.isSetup():
            raise NotAllowedError('positioner not configured: a setup() is required')
        elif str(axis) == 'MNG_BEAMPARK':
            return (True, stime)
        elif self.conf.getAttribute('DynamicUpdatingAllowed') != 'true':
            raise NotAllowedError('dynamic updating not allowed')
        elif not self.siteInfo:
            raise NotAllowedError('no site information available')
        elif str(sector) not in sectors:
            raise NotAllowedError('sector %s not in %s' %(sector, sectors))

        updatingConf = self.conf.getUpdatingConfiguration(str(axis))
        initialPosition = float(updatingConf['initialPosition']) + self.control.user_position
        functionName = updatingConf['functionName']
        posgen = getattr(self.posgen, functionName) 
        angle_mapping = self.posgen.mapping[functionName]
        getAngleFunction = angle_mapping['getAngleFunction']
        coordinateFrame = angle_mapping['coordinateFrame']
        lat = self.siteInfo['latitude']
        try:
            if coordinateFrame == 'horizontal':
                iParallacticPos = getAngleFunction(lat, az, el)
            elif coordinateFrame == 'equatorial':
                iParallacticPos = getAngleFunction(lat, az, el, ra, dec)
            else:
                raise PositionerError('coordinate frame %s unknown' % coordinateFrame)
        except ZeroDivisionError:
            raise NotAllowedError('zero division error computing p(%.2f, %.2f)' %(az, el))

        Pis = initialPosition + self.control.offset
        Pip = iParallacticPos
        if self.isConfigured():
            isOptimized = (self.conf.getAttribute('AddInitialParallactic') == 'false')
        else:
            isOptimized = False
        target = Pis if isOptimized else Pis + Pip

        future_time = 0
        ready = True

        if self.isRewinding():
            # rdistance -> rewinding distance, rtime -> rewinding time
            rdistance = abs(self.getPosition() - self.getCmdPosition())
            speed = self.device.getSpeed()
            # Safety factor of 1.2
            rtime_distance = round((1.2 * rdistance)/speed, 4)
            rtime = getTimeStamp().value + int(rtime_distance * 10**7)
            # tdistance -> target distance, ttime -> target time
            # After rewinding, the derotator has to move to the target
            tdistance = abs(self.getCmdPosition() - target)
            # Safety factor of 1.2
            ttime_distance = round((1.2 * tdistance)/speed, 4)
            ttime = getTimeStamp().value + int(ttime_distance)
            future_time = rtime + ttime
        else:
            distance = abs(self.getPosition() - target)
            # Safety factor of 1.2
            time_distance = round((1.2 * distance)/speed, 4)
            future_time = getTimeStamp().value + int(time_distance)

        if stime == 0 and (future_time - getTimeStamp().value) < 3*10**7:  # 3 seconds
            ready = True
        elif stime >= future_time:
            ready = True
        else:
            ready = False

        return (ready, future_time)


    def startUpdating(self, axis, sector, az, el, ra, dec):
        sectors = ('ANT_NORTH', 'ANT_SOUTH')
        try:
@@ -161,11 +233,7 @@ class Positioner(object):
                raise NotAllowedError('no source available')
            elif str(sector) not in sectors:
                raise NotAllowedError('sector %s not in %s' %(sector, sectors))
            elif self.isRewinding():
                raise NotAllowedError('the positioner is rewinding')
            else:
                if self.isUpdating():
                    self.stopUpdating()
                try:
                    updatingConf = self.conf.getUpdatingConfiguration(str(axis))
                    initialPosition = float(updatingConf['initialPosition']) + self.control.user_position
@@ -183,6 +251,9 @@ class Positioner(object):
                            dParallacticPos=0,
                            rewindingOffset=0,
                        )
                        # Stop even if a rewinding is in progress
                        self.stopUpdating()
                        # Move to the target static position
                        self._start(self.posgen.goto, position)
                    else:
                        posgen = getattr(self.posgen, functionName) 
@@ -201,7 +272,6 @@ class Positioner(object):
                            raise NotAllowedError('zero division error computing p(%.2f, %.2f)' %(az, el))

                        # Remember the sign of the first scan of the map
                        if self.sign is None:
                        self.sign = int(numpy.sign(iParallacticPos))

                        self.control.setScanInfo(
@@ -212,7 +282,15 @@ class Positioner(object):
                            dParallacticPos=0,
                            rewindingOffset=0,
                        )

                        if self.isRewinding():
                            pass
                        elif self.isUpdating():
                            self.stopUpdating()
                            self._start(posgen, self.source, self.siteInfo)
                        else:
                            self._start(posgen, self.source, self.siteInfo)

                    self.control.mustUpdate = True
                except Exception, ex:
                    raise PositionerError('configuration problem: %s' %ex.message)
@@ -343,7 +421,7 @@ class Positioner(object):
        #   * SOUTH: the derotator must go closer to the lower limit
        #   * NORTH: the derotator must go closer to the higher limit
        #
        # The name space is the distance between the target position and the
        # `space` is the distance between the target position and the
        # limit (lower in case of SOUTH, higher in case of NORTH)
        min_limit = self.device.getMinLimit()
        max_limit = self.device.getMaxLimit()
@@ -357,7 +435,7 @@ class Positioner(object):
                numberOfSteps = int(space // self.device.getStep())
            elif target - delta <= min_limit:
                sign = +1
                numberOfSteps = int(space // self.device.getStep()) + 1
                numberOfSteps = int(round(space / self.device.getStep())) + 1
            else:
                raise ValueError('cannot get the rewinding parameters: ' \
                                 'target %.2f in range' %target)
@@ -365,7 +443,7 @@ class Positioner(object):
            space = abs(target - max_limit)
            if target + delta >= max_limit:
                sign = -1
                numberOfSteps = int(space // self.device.getStep()) + 1
                numberOfSteps = int(round(space / self.device.getStep())) + 1
            elif target - delta <= min_limit:
                sign = +1
                numberOfSteps = int(space // self.device.getStep())
+1 −1
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@

CDB_SCHEMAS = DewarPositioner

PY_SCRIPTS_L = derotatorPosition
PY_SCRIPTS_L =
PY_MODULES =
PY_PACKAGES = DewarPositioner

+0 −22
Original line number Diff line number Diff line
#!/usr/bin/env python

from Acspy.Clients.SimpleClient import PySimpleClient
from Acspy.Common.TimeHelper import getTimeStamp
from DewarPositioner.posgenerator import PosGenerator
import time

client = PySimpleClient()
latitude = 0.68928288149012062

dp = client.getComponent('RECEIVERS/DewarPositioner')
antenna = client.getComponent('ANTENNA/Boss')

counter = 0
while True:
    position = dp.getPosition()
    t = getTimeStamp().value + 1*10*6 # 100 ms in the future
    az, el = antenna.getRawCoordinates(t) # Values in radians
    parallactic = PosGenerator.getParallacticAngle(latitude, az, el)
    print "%d -> %.2f  -- parallactic: %.2f" %(counter, position, parallactic)
    counter += 1
    time.sleep(3)
+61 −0
Original line number Diff line number Diff line
from __future__ import with_statement
import unittest
import time
from Antenna import ANT_HORIZONTAL, ANT_NORTH, ANT_SOUTH
from Management import MNG_TRACK, MNG_BEAMPARK

from Acspy.Clients.SimpleClient import PySimpleClient
from Acspy.Common.TimeHelper import getTimeStamp
from ComponentErrors import ComponentErrorsEx


class TestCheckUpdating(unittest.TestCase):
    """Test the DewarPositioner.startUpdating() end-to-end method"""
    def setUp(self):
        self.client = PySimpleClient()
        self.positioner = self.client.getComponent('RECEIVERS/DewarPositioner')
        self.positioner.setup('KKG')
        self.positioner.setConfiguration('custom')
        self.lat = 0.689 # 39.5 degrees

    def tearDown(self):
        if self.positioner.isReady():
            self.positioner.stopUpdating()
            time.sleep(1)
            self.positioner.park()
        time.sleep(0.5)
        self.client.releaseComponent('RECEIVERS/DewarPositioner')


    def test_system_not_ready(self):
        """Raise ComponentErrorsEx when the system is not ready"""
        with self.assertRaisesRegexp(ComponentErrorsEx, 'positioner not configured'):
            self.positioner.park()
            time.sleep(0.5)
            starting_time = getTimeStamp().value + 100000000
            az, el, ra, dec = 0, 0, 0, 0
            self.positioner.checkUpdating(
                    starting_time,
                    MNG_TRACK,
                    ANT_SOUTH,
                    az, el, ra, dec
            )


    def test_system_not_ready(self):
        """Return (True, starting_time) when axis is MNG_BEAMPARK"""
        starting_time = getTimeStamp().value + 100000000
        az, el, ra, dec = 0, 0, 0, 0
        value, feasible_time = self.positioner.checkUpdating(
                starting_time,
                MNG_BEAMPARK,
                ANT_SOUTH,
                az, el, ra, dec
        )
        self.assertEqual(value, True)
        self.assertEqual(feasible_time, starting_time)



if __name__ == '__main__':
    unittest.main()
Loading