Loading Common/Servers/PyDewarPositioner/src/DewarPositioner/DewarPositionerImpl.py +39 −15 Original line number Diff line number Diff line Loading @@ -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: Loading Loading @@ -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 Loading Common/Servers/PyDewarPositioner/src/DewarPositioner/positioner.py +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 Loading Loading @@ -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: Loading @@ -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 Loading @@ -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) Loading @@ -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( Loading @@ -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) Loading Loading @@ -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() Loading @@ -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) Loading @@ -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()) Loading Common/Servers/PyDewarPositioner/src/Makefile +1 −1 Original line number Diff line number Diff line Loading @@ -5,7 +5,7 @@ CDB_SCHEMAS = DewarPositioner PY_SCRIPTS_L = derotatorPosition PY_SCRIPTS_L = PY_MODULES = PY_PACKAGES = DewarPositioner Loading Common/Servers/PyDewarPositioner/src/derotatorPosition.pydeleted 100644 → 0 +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) Common/Servers/PyDewarPositioner/test/functional/test_checkUpdating.py 0 → 100644 +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
Common/Servers/PyDewarPositioner/src/DewarPositioner/DewarPositionerImpl.py +39 −15 Original line number Diff line number Diff line Loading @@ -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: Loading Loading @@ -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 Loading
Common/Servers/PyDewarPositioner/src/DewarPositioner/positioner.py +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 Loading Loading @@ -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: Loading @@ -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 Loading @@ -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) Loading @@ -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( Loading @@ -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) Loading Loading @@ -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() Loading @@ -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) Loading @@ -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()) Loading
Common/Servers/PyDewarPositioner/src/Makefile +1 −1 Original line number Diff line number Diff line Loading @@ -5,7 +5,7 @@ CDB_SCHEMAS = DewarPositioner PY_SCRIPTS_L = derotatorPosition PY_SCRIPTS_L = PY_MODULES = PY_PACKAGES = DewarPositioner Loading
Common/Servers/PyDewarPositioner/src/derotatorPosition.pydeleted 100644 → 0 +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)
Common/Servers/PyDewarPositioner/test/functional/test_checkUpdating.py 0 → 100644 +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()