def test_apogee_dome_flat_enclosure(self): """Tests shutter open, exposure +(ff on, ff off).""" name = 'apogeeDomeFlat' sopTester.updateModel('mcp', TestHelper.mcpState['apogee_parked']) multiCmd = MultiCommand(self.cmd, myGlobals.actorState.timeout + 50, name) self._apogee_dome_flat(3, 11, 0, 0, multiCmd)
def test_apogee_dome_flat_gang_on_podium_fails(self): """Tests fail immediately.""" name = 'apogeeDomeFlat' sopTester.updateModel('mcp', TestHelper.mcpState['all_off']) multiCmd = MultiCommand(self.cmd, myGlobals.actorState.timeout + 50, name) self._apogee_dome_flat(0, 5, 0, 0, multiCmd, finish=True, didFail=True)
def _status_threads(self, cmd, sopState, finish=True): # TBD: threads arg is only used with "geek" option, apparently? # TBD: I guess its useful for live debugging of the threads. try: sopState.ignoreAborting = True getStatus = MultiCommand(cmd, 5.0, None) for tid in sopState.threads.keys(): getStatus.append(tid, Msg.STATUS) if not getStatus.run(): if finish: cmd.fail("") return else: cmd.warn("") finally: sopState.ignoreAborting = False
def setUp(self): self.verbose = True self.tid = sopTester.TEST_QUEUE self.queueName = 'testMultiCmd' self.msgs = [Msg.LAMP_ON, Msg.FFS_MOVE, Msg.STATUS, Msg.SLEW] super(TestMultiCommand, self).setUp() self.timeout = 2 self.multiCmd = MultiCommand(self.cmd, self.timeout, 'testMultiCmd.stage') self.queue = Queue(self.queueName, 0) self.queues = {self.tid: self.queue} actorState = myGlobals.actorState actorState.queues = self.queues actorState.threads[self.tid] = threading.Thread( target=sopTester.FakeThread, name=self.queueName, args=[actorState.actor, actorState.queues]) actorState.threads[self.tid].daemon = True actorState.threads[self.tid].start()
def test_apogee_dome_flat_shuter_close_fails(self): """Tests shutter open, ffs close -> fail.""" name = 'apogeeDomeFlat' self.cmd.failOn = "apogee shutter close" sopTester.updateModel('mcp', TestHelper.mcpState['apogee_science']) multiCmd = MultiCommand(self.cmd, myGlobals.actorState.timeout + 50, name) self._apogee_dome_flat(4, 15, 0, 1, multiCmd, finish=True, didFail=True)
def main(actor, queues): """Main loop for SOP selw thread.""" threadName = 'slew' timeout = myGlobals.actorState.timeout while True: try: msg = queues[sopActor.SLEW].get(timeout=timeout) if msg.type == Msg.EXIT: if msg.cmd: msg.cmd.inform('text=\"Exiting thread {0}\"'.format( threading.current_thread().name)) return elif msg.type == Msg.GOTO_POSITION: cmd, cmdState, actorState = master.preprocess_msg(msg) goto_position(cmd, cmdState, actorState) elif msg.type == Msg.DO_APOGEE_DOME_FLAT: cmd, cmdState, actorState = master.preprocess_msg(msg) name = 'apogeeDomeFlat' finishMsg = "Dome flat done." # 50 seconds is the read time for this exposure. multiCmd = MultiCommand(cmd, actorState.timeout + 50, name) # the dome flat command sends a fail msg if it fails. if apogee_dome_flat(cmd, cmdState, actorState, multiCmd): master.finish_command(cmd, cmdState, actorState, finishMsg) elif msg.type == Msg.GOTO_GANG_CHANGE: cmd, cmdState, actorState = master.preprocess_msg(msg) goto_gang_change(cmd, cmdState, actorState) else: raise ValueError('Unknown message type {0}'.format(msg.type)) except Queue.Empty: actor.bcast.diag('text="%s alive"' % threadName) except Exception, ee: sopActor.handle_bad_exception(actor, ee, threadName, msg)
def goto_position(cmd, cmdState, actorState): """Goes to a certain (az, alt, rot) position.""" finishMsg = "On position." multiCmd = master.SopMultiCommand(cmd, actorState.timeout + 100, cmdState.name + ".slew") cmdState.setStageState('slew', 'running') # Heading towards the instrument change pos. az = cmdState.az alt = cmdState.alt rot = cmdState.rot slewDuration = 60 multiCmd = MultiCommand(cmd, slewDuration + actorState.timeout, None) # Start with an axis init, in case the axes are not clear. multiCmd.append(master.SopPrecondition(sopActor.TCC, Msg.AXIS_INIT)) multiCmd.append(sopActor.TCC, Msg.SLEW, actorState=actorState, az=az, alt=alt, rot=rot) multiCmd.append(sopActor.TCC, Msg.AXIS_STOP, actorState=actorState) if not master.handle_multiCmd( multiCmd, cmd, cmdState, 'slew', 'Failed to slew to position az={0}, alt={1},' ' rot={2}'.format(az, alt, rot)): return master.finish_command(cmd, cmdState, actorState, finishMsg)
def lampsOff(self, cmd, finish=True): """Turn all the lamps off""" sopState = myGlobals.actorState sopState.aborting = False multiCmd = MultiCommand(cmd, sopState.timeout, None) multiCmd.append(sopActor.FF_LAMP, Msg.LAMP_ON, on=False) multiCmd.append(sopActor.HGCD_LAMP, Msg.LAMP_ON, on=False) multiCmd.append(sopActor.NE_LAMP, Msg.LAMP_ON, on=False) multiCmd.append(sopActor.WHT_LAMP, Msg.LAMP_ON, on=False) multiCmd.append(sopActor.UV_LAMP, Msg.LAMP_ON, on=False) if multiCmd.run(): if finish: cmd.finish('text="Turned lamps off"') else: if finish: cmd.fail('text="Some lamps failed to turn off"')
class TestMultiCommand(sopTester.SopTester, unittest.TestCase): def setUp(self): self.verbose = True self.tid = sopTester.TEST_QUEUE self.queueName = 'testMultiCmd' self.msgs = [Msg.LAMP_ON, Msg.FFS_MOVE, Msg.STATUS, Msg.SLEW] super(TestMultiCommand, self).setUp() self.timeout = 2 self.multiCmd = MultiCommand(self.cmd, self.timeout, 'testMultiCmd.stage') self.queue = Queue(self.queueName, 0) self.queues = {self.tid: self.queue} actorState = myGlobals.actorState actorState.queues = self.queues actorState.threads[self.tid] = threading.Thread( target=sopTester.FakeThread, name=self.queueName, args=[actorState.actor, actorState.queues]) actorState.threads[self.tid].daemon = True actorState.threads[self.tid].start() def _prep_multiCmd_nopre(self): """Prep self.multiCmd with pre-arranged messages""" self.multiCmd.append(self.tid, self.msgs[0]) self.multiCmd.append(self.tid, self.msgs[1]) def _prep_multiCmd_pre(self): """Prep self.multiCmd with pre-arranged messages""" self.multiCmd.append(Precondition(self.tid, self.msgs[0])) self.multiCmd.append(Precondition(self.tid, self.msgs[1])) self.multiCmd.append(self.tid, self.msgs[2]) self.multiCmd.append(self.tid, self.msgs[3]) def test_append_not_precondition(self): self.multiCmd.append(self.tid, Msg.DONE, timeout=10, blah=1) msg = self.multiCmd.commands[0] self.assertEqual(msg[0], self.queue) self.assertFalse(msg[1]) self.assertEqual(msg[2].type, Msg.DONE) self.assertEqual(msg[2].type, Msg.DONE) self.assertEqual(msg[2].cmd, self.cmd) self.assertEqual(msg[2].blah, 1) self.assertEqual(self.multiCmd.timeout, 10) def test_append_precondition(self): self.multiCmd.append( Precondition(self.tid, Msg.DONE, timeout=1, blah=1)) msg = self.multiCmd.commands[0] self.assertEqual(msg[0], self.queue) self.assertTrue(msg[1]) self.assertEqual(msg[2].type, Msg.DONE) self.assertEqual(msg[2].type, Msg.DONE) self.assertEqual(msg[2].cmd, self.cmd) self.assertEqual(self.multiCmd.timeout, self.timeout) def test_append_precondition_unneeded(self): self.multiCmd.append( PreconditionUnneeded(self.tid, Msg.DONE, timeout=10, blah=1)) self.assertEqual(self.multiCmd.commands, []) def test_append_precondition_with_msgId(self): with self.assertRaises(AssertionError): self.multiCmd.append(Precondition(self.tid), Msg.DONE) def test_append_no_msgId(self): with self.assertRaises(AssertionError): self.multiCmd.append(self.tid) def test_run_nopre(self): self._prep_multiCmd_nopre() result = self.multiCmd.run() self.assertTrue(result) self._check_cmd(2, 3, 0, 0, False, didFail=not result) def test_run_pre(self): self._prep_multiCmd_pre() result = self.multiCmd.run() self.assertTrue(result) self._check_cmd(4, 6, 0, 0, False, didFail=not result) def test_run_nopre_fails(self): self.cmd.failOn = 'testMultiCmd sopActor.LAMP_ON' self._prep_multiCmd_nopre() result = self.multiCmd.run() self.assertFalse(result) self._check_cmd(2, 3, 0, 0, False, didFail=not result) def test_run_timesout(self): self.multiCmd.append(self.tid, Msg.EXIT) self._prep_multiCmd_nopre() result = self.multiCmd.run() self.assertFalse(result) self._check_cmd(0, 3, 1, 0, False, didFail=not result)
def goto_gang_change(cmd, cmdState, actorState, failMsg=None): """Goes to the gang change positions. Goto gang change position at requested altitude, taking a dome flat on the way if we have an APOGEE cartridge, and the gang is plugged into it. """ finishMsg = 'at gang change position' failMsg = 'failed to take flat before gang change' \ if failMsg is None else failMsg # Behavior varies depending on where the gang connector is. gangCart = actorState.apogeeGang.atCartridge() if cmdState.doDomeFlat: multiCmd = master.SopMultiCommand(cmd, actorState.timeout + 100, cmdState.name + '.domeFlat') cmdState.setStageState('domeFlat', 'running') # If the gang connector is at the cartridge, we should do cals. if gangCart and actorState.survey != sopActor.BOSS: cmd.inform('text="scheduling dome flat: {0}"'.format( actorState.survey)) doCals = apogee_dome_flat(cmd, cmdState, actorState, multiCmd, failMsg) if not doCals: return else: gangAt = actorState.apogeeGang.getPos() cmd.inform('text="Skipping flat with {0} and {1}"'.format( gangAt, actorState.survey)) cmdState.setStageState('domeFlat', 'idle') if cmdState.doSlew: multiCmd = master.SopMultiCommand(cmd, actorState.timeout + 100, cmdState.name + '.slew') cmdState.setStageState('slew', 'running') # Close the FFS, to prevent excess light # incase of slews past the moon, etc. multiCmd.append( master.SopPrecondition(sopActor.FFS, Msg.FFS_MOVE, open=False)) tccDict = actorState.models['tcc'].keyVarDict if gangCart: # Heading towards the instrument change pos. az = 121 alt = cmdState.alt rot = 0 # Try to move the rotator as far as we can while the altitude # is moving. thisAlt = tccDict['axePos'][1] thisRot = tccDict['axePos'][2] dRot = rot - thisRot if dRot != 0: dAlt = alt - thisAlt dAltTime = abs(dAlt) / 1.5 # deg/sec dRotTime = abs(dRot) / 2.0 # deg/sec dCanRot = dRot * min(1.0, dAltTime / dRotTime) rot = thisRot + dCanRot else: # Nod up: going to the commanded altitude, # leaving az and rot where they are. az = tccDict['axePos'][0] alt = cmdState.alt rot = tccDict['axePos'][2] slewDuration = 60 multiCmd = MultiCommand(cmd, slewDuration + actorState.timeout, None) # Start with an axis init, in case the axes are not clear. multiCmd.append(master.SopPrecondition(sopActor.TCC, Msg.AXIS_INIT)) # If the gang is at the cart, we need to close the apogee shutter # during the slew, no matter which survey is leading. if actorState.apogeeGang.atCartridge(): master.prep_apogee_shutter(multiCmd, open=False) # used to do darks on the way to the field. # multiCmd.append(sopActor.APOGEE_SCRIPT, Msg.APOGEE_PARK_DARKS) multiCmd.append(sopActor.TCC, Msg.SLEW, actorState=actorState, az=az, alt=alt, rot=rot) multiCmd.append(sopActor.TCC, Msg.AXIS_STOP, actorState=actorState) doMultiCmd = master.handle_multiCmd(multiCmd, cmd, cmdState, 'slew', 'Failed to slew to gang change') if not doMultiCmd: return master.finish_command(cmd, cmdState, actorState, finishMsg)