diff --git a/Camera/IndiCamera.py b/Camera/IndiCamera.py index 32550c0..5e9252a 100644 --- a/Camera/IndiCamera.py +++ b/Camera/IndiCamera.py @@ -19,6 +19,7 @@ # Local stuff: Focuser from Imaging.IndiAutoFocuser import IndiAutoFocuser from utils import load_module +from utils.error import ImageAcquisitionError class IndiCamera(IndiDevice): """ Indi Camera """ @@ -150,14 +151,18 @@ def prepare_shoot(self): 'receive blob CCD1 when it is ready') self.indi_client.enable_blob() - def synchronize_with_image_reception(self): + def synchronize_with_image_reception(self, exp_time_sec=None): try: + if exp_time_sec is None: + exp_time_sec = self.exp_time_sec + if exp_time_sec == 0: + return self.logger.debug(f"synchronize_with_image_reception: Start waiting for " \ - f"{self.exp_time_sec}s with margin {self.READOUT_TIME_MARGIN}s") - self.wait_for_incoming_blob_vector(timeout=self.exp_time_sec + self.READOUT_TIME_MARGIN) + f"{exp_time_sec}s with margin {self.READOUT_TIME_MARGIN}s") + self.wait_for_incoming_blob_vector(timeout=exp_time_sec + self.READOUT_TIME_MARGIN) self.logger.debug('synchronize_with_image_reception: Done') except Exception as e: - self.logger.error(f"Indi Camera Error in synchronize_with_image_reception: {e}") + raise ImageAcquisitionError(f"Indi Camera Error in synchronize_with_image_reception: {e}") def get_received_image(self): try: @@ -179,6 +184,9 @@ def shoot_async(self): except Exception as e: self.logger.error(f"Indi Camera Error in shoot: {e}") + def is_remaining_exposure_time(self): + return self.get_number('CCD_EXPOSURE')['CCD_EXPOSURE_VALUE'] + def get_thumbnail(self, exp_time_sec, thumbnail_size): """ There are 4 cases: diff --git a/Guider/GuiderPHD2.py b/Guider/GuiderPHD2.py index 10178d7..3979f66 100644 --- a/Guider/GuiderPHD2.py +++ b/Guider/GuiderPHD2.py @@ -464,7 +464,7 @@ def find_star(self, x=None, y=None, width=None, height=None): otherwise returns an error object desc. : Select a star """ - params = [x, y, width, height] + params = [int(x), int(y), int(width), int(height)] if all(map(lambda x: x is None, params)): params = [] else: diff --git a/Imaging/fits.py b/Imaging/fits.py index 8a556e2..86b5dca 100644 --- a/Imaging/fits.py +++ b/Imaging/fits.py @@ -71,6 +71,7 @@ def solve_field(fname, timeout=180, solve_opts=None, **kwargs): print("Cmd:", cmd) try: + os.system('rm -f /tmp/*.wcs.*') proc = subprocess.Popen(cmd, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) except OSError as e: diff --git a/Pointer/StarOffsetPointer.py b/Pointer/StarOffsetPointer.py index 60d3d77..e905796 100644 --- a/Pointer/StarOffsetPointer.py +++ b/Pointer/StarOffsetPointer.py @@ -13,7 +13,7 @@ # Local from Imaging.Image import Image from Imaging.SolvedImageAnalysis import find_best_candidate_star, get_brightest_detection -from utils.error import AstrometrySolverError +from utils.error import AstrometrySolverError, ImageAcquisitionError # Numerical stuff import numpy as np @@ -95,6 +95,17 @@ def offset_points_async(self, mount, camera, guiding_camera, guider, observation """ try: try: + # Our first action is to stop guiding + if guider is not None: + msg = f"Going to adjust pointing, need to stop guiding" + self.logger.debug(msg) + guider.stop_capture() + try: + exp_time_sec = guiding_camera.is_remaining_exposure_time() + guiding_camera.synchronize_with_image_reception(exp_time_sec=exp_time_sec) + except ImageAcquisitionError as e: + pass + img_num = 0 pointing_image = self.acquire_pointing(camera, guiding_camera, observation, fits_headers, img_num) if camera is None: @@ -111,8 +122,7 @@ def offset_points_async(self, mount, camera, guiding_camera, guider, observation observation.target.coord, self.max_identification_error) if px_identified_target is None: - msg = f"Cannot identify a star from {pointing_image.fits_file} while in offset_pointing state, will " \ - f"only rely on brightest detected star" + msg = f"Cannot identify a star from {pointing_image.fits_file} while in offset_pointing state" self.logger.warning(msg) px_identified_target = self.get_default_star_strategy(pointing_image) @@ -123,20 +133,20 @@ def offset_points_async(self, mount, camera, guiding_camera, guider, observation if self.use_guider_adjust: # If guider was locked on another star, then restart guiding - if not guider.is_lock_position_close_to(px_target=px_identified_target, - max_angle_sep=3 * u.arcsec): - guider.stop_capture() - guider.loop() - half_search_size = camera.adjust_roi_search_size / 2 - guider.find_star(x=max(0, int(round(px_identified_target[0] - half_search_size))), - y=max(0, int(round(px_identified_target[1] - half_search_size))), - width=camera.adjust_roi_search_size, - height=camera.adjust_roi_search_size) - guider.guide(recalibrate=False, - roi=[int(round(camera.adjust_center_x)), - int(round(camera.adjust_center_y)), - int(round(camera.adjust_roi_search_size)), - int(round(camera.adjust_roi_search_size))]) + # if not guider.is_lock_position_close_to(px_target=px_identified_target, + # max_angle_sep=3 * u.arcsec): + # guider.stop_capture() + guider.loop() + half_search_size = camera.adjust_roi_search_size / 2 + guider.find_star(x=max(0, int(round(px_identified_target[0] - half_search_size))), + y=max(0, int(round(px_identified_target[1] - half_search_size))), + width=camera.adjust_roi_search_size, + height=camera.adjust_roi_search_size) + guider.guide(recalibrate=False, + roi=[int(round(camera.adjust_center_x)), + int(round(camera.adjust_center_y)), + int(round(camera.adjust_roi_search_size)), + int(round(camera.adjust_roi_search_size))]) guider.set_lock_position(camera.adjust_center_x, camera.adjust_center_y, exact=True, @@ -178,12 +188,6 @@ def offset_points_async(self, mount, camera, guiding_camera, guider, observation dec=current.dec + pointing_error.delta_dec - offset_delta_dec, frame='icrs', equinox='J2000.0') # Now adjust by slewing to the specified counter-offseted coordinates - if guider is not None: - msg = f"Going to adjust pointing, need to pause guiding, and restart later" - self.logger.debug(msg) - guider.stop_capture() - # guider.set_paused(paused=True) - # guider.wait_for_state(one_of_states=["Paused"]) mount.slew_to_coord(target) if guider is not None: guider.loop() @@ -215,7 +219,7 @@ def get_default_star_strategy(self, pointing_image): def acquire_pointing(self, camera, guiding_camera, observation, fits_headers, img_num): self.logger.debug("Taking pointing picture.") - external_trigger = (camera is guiding_camera) + #external_trigger = (camera is guiding_camera) self.logger.debug(f"Exposing for camera: {camera.name}") try: @@ -225,7 +229,7 @@ def acquire_pointing(self, camera, guiding_camera, observation, fits_headers, im headers=fits_headers, filename='adjust_pointing{:02d}'.format(img_num), exp_time=camera.adjust_pointing_seconds * u.second, - external_trigger=external_trigger + #external_trigger=external_trigger ) status = camera_event.wait(timeout=self.timeout_seconds) if not status: diff --git a/StateMachine/States/focusing.py b/StateMachine/States/focusing.py index 0724eed..3dbc8f8 100644 --- a/StateMachine/States/focusing.py +++ b/StateMachine/States/focusing.py @@ -8,6 +8,7 @@ # Local from utils import error from utils import Timeout +from utils.error import ImageAcquisitionError SLEEP_SECONDS = 1.0 STATUS_INTERVAL = 10. * u.second @@ -45,8 +46,13 @@ def on_enter(event_data): model.logger.debug(msg) model.say(msg) model.manager.guider.set_paused(paused=True) - time.sleep(5) - # TODO TN URGENT: ASK Guiding camera if it is still waiting for an image, and wait for that amount of time + guiding_camera = model.manager.guiding_camera + if guiding_camera is not None: + try: + exp_time_sec = guiding_camera.is_remaining_exposure_time() + guiding_camera.synchronize_with_image_reception(exp_time_sec=exp_time_sec) + except ImageAcquisitionError as e: + pass try: model.say("Starting focusing") # Before each observation, we should refocus diff --git a/conf_files/config.yaml b/conf_files/config.yaml index 90e778e..32e2039 100644 --- a/conf_files/config.yaml +++ b/conf_files/config.yaml @@ -121,7 +121,7 @@ cameras: do_pointing: true pointing_seconds: 5 do_adjust_pointing: true - adjust_center_x: 400 + adjust_center_x: 580 adjust_center_y: 400 adjust_roi_search_size: 50 adjust_pointing_seconds: 5 @@ -193,7 +193,7 @@ cameras: adjust_center_y: 400 adjust_roi_search_size: 50 adjust_pointing_seconds: 5 - do_autofocus: true + do_autofocus: false autofocus_seconds: 5 autofocus_roi_size : 750 autofocus_merit_function : half_flux_radius #vollath_F4 diff --git a/utils/error.py b/utils/error.py index c18e344..11ed1f4 100644 --- a/utils/error.py +++ b/utils/error.py @@ -26,71 +26,59 @@ def exit_program(self, msg='No reason specified'): print("TERMINATING: {}".format(msg)) sys.exit(1) -class BLOBError(Error): +class ImageAcquisitionError(Error): + """ Error while trying to acquire image """ + def __init(self, message="Error while camera is trying to acquire an image"): + super().__init__(message) +class BLOBError(Error): """ Error for Indi Blob communication problem """ def __init(self, message="Indi BLOB Error"): super().__init__(message) - class GuidingError(Error): - """ Error for a guiding system malfunction """ - def __init__(self, msg='Guiding problem'): super().__init__(msg) class PointingError(Error): - """ Error during the pointing process """ - def __init__(self, msg='Pointing problem'): super().__init__(msg) class ScopeControllerError(Error): - """ Error for a scope controller system malfunction """ - def __init__(self, msg='Scope control problem'): super().__init__(msg) class DomeControllerError(Error): - """ Error for a dome controller system malfunction """ - def __init__(self, msg='Dome control problem'): super().__init__(msg) class InvalidSystemCommand(Error): - """ Error for a system level command malfunction """ - def __init__(self, msg='Problem running system command'): super().__init__(msg) class Timeout(Error): - """ Error called when an event times out """ - + pass class AstrometrySolverError(Error): - """ Error while trying to perform astrometry solving on an image """ def __init__(self, msg='Error while trying to perform astrometry solving'): super().__init__(msg) class NoObservation(Error): - """ Generic no Observation """ - def __init__(self, msg='No valid observations found.'): super().__init__(msg) class NotFound(Error): - """ Generic not found class """ pass @@ -101,31 +89,26 @@ class InvalidCollection(NotFound): class InvalidConfig(Error): - """ Error raised if config file is invalid """ pass class InvalidCommand(Error): - """ Error raised if a system command does not run """ pass class InvalidMountCommand(Error): - """ Error raised if attempting to send command that doesn't exist """ pass class BadConnection(Error): - """ Error raised when a connection is bad """ pass class BadSerialConnection(Error): - """ Error raised when serial command is bad """ pass @@ -136,15 +119,12 @@ class ArduinoDataError(Error): class MountNotFound(NotFound): - """ Mount cannot be import """ - def __init__(self, msg='Mount Not Found'): self.exit_program(msg=msg) class CameraNotFound(NotFound): - """ Camera cannot be imported """ pass @@ -155,7 +135,6 @@ class DomeNotFound(NotFound): class BadSerialConnection(Error): - """ Error raised when serial command is bad """ pass