File indexing completed on 2024-04-28 03:43:19
0001 /* Ekos state machine for a single capture job sequence. 0002 SPDX-FileCopyrightText: Wolfgang Reissenberger <sterne-jaeger@openfuture.de> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #pragma once 0008 0009 #include "indi/indicommon.h" 0010 #include "skypoint.h" 0011 #include "capturemodulestate.h" 0012 #include "ekos/auxiliary/filtermanager.h" 0013 #include "fitsviewer/fitscommon.h" 0014 0015 #include <QWidget> 0016 #include <QVector> 0017 #include <QMap> 0018 0019 namespace Ekos 0020 { 0021 /* Status of a single {@see SequenceJob}. */ 0022 typedef enum 0023 { 0024 JOB_IDLE, /* Initial state, nothing happens. */ 0025 JOB_BUSY, /* Job is running. */ 0026 JOB_ERROR, /* Error occured, unresolved. */ 0027 JOB_ABORTED, /* Job stopped before completion. */ 0028 JOB_DONE /* Job completed. */ 0029 } JOBStatus; 0030 0031 class SequenceJobState: public QObject 0032 { 0033 Q_OBJECT 0034 0035 friend class SequenceJob; 0036 friend class CaptureDeviceAdaptor; 0037 // Fixme: too many friends 0038 friend class Capture; 0039 0040 public: 0041 typedef enum 0042 { 0043 CAL_NONE, /* initial state */ 0044 CAL_DUSTCAP_PARKING, /* unused */ 0045 CAL_DUSTCAP_PARKED, /* unused */ 0046 CAL_LIGHTBOX_ON, /* unused */ 0047 CAL_SLEWING, /* unused */ 0048 CAL_SLEWING_COMPLETE, /* unused */ 0049 CAL_MOUNT_PARKING, /* unused */ 0050 CAL_MOUNT_PARKED, /* unused */ 0051 CAL_DOME_PARKING, /* unused */ 0052 CAL_DOME_PARKED, /* unused */ 0053 CAL_PRECAPTURE_COMPLETE, /* unused */ 0054 CAL_CALIBRATION, 0055 CAL_CALIBRATION_COMPLETE, 0056 CAL_CAPTURING 0057 } CalibrationStage; 0058 0059 typedef enum 0060 { 0061 PREP_NONE, /* preparation has not been executed */ 0062 PREP_BUSY, /* preparation started */ 0063 PREP_COMPLETED, /* preparation completed */ 0064 PREP_INIT_CAPTURE /* initialize capturing (last step before device capturing starts) */ 0065 } PreparationState; 0066 0067 typedef enum 0068 { 0069 CAL_CHECK_TASK, 0070 CAL_CHECK_CONFIRMATION, 0071 } CalibrationCheckType; 0072 0073 typedef enum 0074 { 0075 WP_NONE, /* slewing to wall position not started */ 0076 WP_SLEWING, /* slewing to wall position started */ 0077 WP_SLEW_COMPLETED, /* wall position reached */ 0078 WP_TRACKING_BUSY, /* turning tracking off running */ 0079 WP_TRACKING_OFF /* wall position reached, tracking off */ 0080 } ScopeWallPositionStatus; 0081 0082 typedef enum /* synching the focuser to the focus position */ 0083 { 0084 FS_NONE, /* not started */ 0085 FS_BUSY, /* running */ 0086 FS_COMPLETED /* completed */ 0087 } FlatSyncStatus; 0088 0089 SequenceJobState(const QSharedPointer<CaptureModuleState> &sharedState); 0090 0091 /** 0092 * @brief Initialize the state machine. 0093 * @param frameType frame type for which the preparation should be done 0094 */ 0095 void setFrameType(CCDFrameType frameType); 0096 CCDFrameType getFrameType() 0097 { 0098 return m_frameType; 0099 } 0100 0101 /** 0102 * @brief initPreparation Reset all states properly for capture preparation 0103 * @param isPreview flag if the captures are in the preview mode 0104 */ 0105 void initPreparation(bool isPreview); 0106 0107 /** 0108 * @brief Trigger all peparation actions before a capture may be started. 0109 * @param enforceCCDTemp flag if the CCD temperature should be set to the target value. 0110 * @param isPreview flag if the captures are in the preview mode 0111 */ 0112 void prepareLightFrameCapture(bool enforceCCDTemp, bool isPreview); 0113 0114 /** 0115 * @brief Initiate tasks required so that capturing of flats may start. 0116 * @param enforceCCDTemp flag if the CCD temperature should be set to the target value. 0117 * @param isPreview flag if the captures are in the preview mode 0118 */ 0119 void prepareFlatFrameCapture(bool enforceCCDTemp, bool isPreview); 0120 0121 /** 0122 * @brief Initiate tasks required so that capturing of darks may start. 0123 * @param enforceCCDTemp flag if the CCD temperature should be set to the target value. 0124 * @param isPreview flag if the captures are in the preview mode 0125 */ 0126 void prepareDarkFrameCapture(bool enforceCCDTemp, bool isPreview); 0127 0128 /** 0129 * @brief Initiate tasks required so that capturing of bias may start. 0130 * @param enforceCCDTemp flag if the CCD temperature should be set to the target value. 0131 * @param isPreview flag if the captures are in the preview mode 0132 */ 0133 void prepareBiasFrameCapture(bool enforceCCDTemp, bool isPreview); 0134 0135 /** 0136 * @brief initCapture Initialize capturing (currently only setting the 0137 * target filter). 0138 * @param frameType frame type to be captured 0139 * @param isPreview is the captured frame only a preview? 0140 * @param isAutofocusReady is an autofocus possible? 0141 * @return true if the initialization is already completed 0142 */ 0143 bool initCapture(CCDFrameType frameType, bool isPreview, bool isAutofocusReady, FITSMode mode); 0144 0145 /** 0146 * @brief The current capture sequence job status 0147 */ 0148 JOBStatus getStatus() 0149 { 0150 return m_status; 0151 } 0152 0153 /** 0154 * @brief Preparation state of the sequence job 0155 */ 0156 PreparationState getPreparationState() const; 0157 0158 /** 0159 * @brief Reset the status to a dedicated value. 0160 * @param status new status, by default {@see JOB_IDLE} 0161 */ 0162 void reset(JOBStatus status = JOB_IDLE) 0163 { 0164 m_status = status; 0165 } 0166 0167 public slots: 0168 ////////////////////////////////////////////////////////////////////// 0169 // Slots for device events that change the state. 0170 ////////////////////////////////////////////////////////////////////// 0171 0172 /** 0173 * @brief setFilterStatus Update the current filter state 0174 */ 0175 void setFilterStatus(FilterState filterState); 0176 0177 /** 0178 * @brief Update the currently active filter ID 0179 */ 0180 void setCurrentFilterID(int value); 0181 0182 /** 0183 * @brief Update the current CCD temperature 0184 */ 0185 void setCurrentCCDTemperature(double value); 0186 /** 0187 * @brief Set the target CCD temperature 0188 */ 0189 void setTargetCCDTemperature(double value) 0190 { 0191 targetTemperature = value; 0192 } 0193 0194 /** 0195 * @brief setFocusStatus Evaluate the current focus state 0196 */ 0197 void setFocusStatus(FocusState state); 0198 0199 /** 0200 * @brief Update the current rotator position (calculated from the rotator angle) 0201 */ 0202 void setCurrentRotatorPositionAngle(double currentRotation, IPState state); 0203 /** 0204 * @brief Set the target rotation angle 0205 */ 0206 void setTargetRotatorAngle(double value) 0207 { 0208 targetPositionAngle = value; 0209 } 0210 0211 /** 0212 * @brief Cover for the scope with a flats light source or dark cover done 0213 */ 0214 void updateManualScopeCover(bool closed, bool success, bool light); 0215 /** 0216 * @brief Light box light is on. 0217 */ 0218 void lightBoxLight(bool on); 0219 /** 0220 * @brief dust cap status change 0221 */ 0222 void dustCapStateChanged(ISD::DustCap::Status status); 0223 /** 0224 * @brief telescope status change 0225 */ 0226 void scopeStatusChanged(ISD::Mount::Status status); 0227 /** 0228 * @brief telescope status change 0229 */ 0230 void scopeParkStatusChanged(ISD::ParkStatus status); 0231 /** 0232 * @brief dome status change 0233 */ 0234 void domeStatusChanged(ISD::Dome::Status status); 0235 /** 0236 * @brief flat sync focus status change 0237 */ 0238 void flatSyncFocusChanged(bool completed); 0239 /** 0240 * @brief CCD has a shutter 0241 */ 0242 void hasShutter(bool present); 0243 0244 signals: 0245 // communicate that a preparation step needs to be executed 0246 void prepareState(Ekos::CaptureState state); 0247 // ask for the current device state 0248 void readCurrentState(Ekos::CaptureState state); 0249 // Capture preparation complete(d) 0250 void prepareComplete(bool success = true); 0251 // Capture initialization complete(d) 0252 void initCaptureComplete(FITSMode mode); 0253 // change the rotator angle 0254 void setRotatorAngle(double rawAngle); 0255 // ask for the current filter position 0256 void readFilterPosition(); 0257 // Change the filter to the given position and the filter change policy 0258 void changeFilterPosition(int targetFilterPosition, FilterManager::FilterPolicy policy); 0259 // set the CCD target temperature 0260 void setCCDTemperature(double temp); 0261 // set CCD to preview mode 0262 void setCCDBatchMode(bool m_preview); 0263 // ask for manually covering the scope with a flat light source or dark cover 0264 void askManualScopeCover(QString question, QString title, bool light); 0265 // ask for manually opening the scope cover 0266 void askManualScopeOpen(bool light); 0267 // turn light on in the light box 0268 void setLightBoxLight(bool on); 0269 // turn light on in the dust cap 0270 void setDustCapLight(bool on); 0271 // park the dust cap 0272 void parkDustCap(bool park); 0273 // slew the telescope to a target 0274 void slewTelescope(SkyPoint &target); 0275 // turn scope tracking on and off 0276 void setScopeTracking(bool on); 0277 // park / unpark telescope 0278 void setScopeParked(bool parked); 0279 // park / unpark dome 0280 void setDomeParked(bool parked); 0281 // check if the focuser needs to be moved to the focus position. 0282 void flatSyncFocus(int targetFilterID); 0283 // ask whether the CCD has a shutter 0284 void queryHasShutter(); 0285 // abort capturing 0286 void abortCapture(); 0287 // log entry 0288 void newLog(QString); 0289 0290 private: 0291 // current status of the capture sequence job 0292 JOBStatus m_status { JOB_IDLE }; 0293 0294 // Is the capture preparation ready? 0295 PreparationState m_PreparationState { PREP_NONE }; 0296 0297 // //////////////////////////////////////////////////////////////////// 0298 // capture preparation relevant flags 0299 // //////////////////////////////////////////////////////////////////// 0300 0301 // Mapping PrepareActions --> bool marks whether a certain action is completed (=true) or not (=false) 0302 QMap<CaptureModuleState::PrepareActions, bool> prepareActions; 0303 // This is a workaround for a specific INDI behaviour. If a INDI property is set, it sends this value 0304 // back to the clients. If the value does not immediately change to the target value (like e.g. the CCD 0305 // temperature), the first value after setting a property must be ignored. 0306 QMap<CaptureModuleState::PrepareActions, bool> ignoreNextValue; 0307 0308 // capture frame type (light, flat, dark, bias) 0309 CCDFrameType m_frameType { FRAME_NONE }; 0310 // do we shoot a preview? 0311 bool m_isPreview { false }; 0312 // should a certain temperature should be enforced? 0313 bool m_enforceTemperature { false }; 0314 // flag if auto focus has been completed for the selected filter 0315 bool autoFocusReady; 0316 // Capturing mode, necessary for the display in the FITS viewer 0317 FITSMode m_fitsMode; 0318 // //////////////////////////////////////////////////////////////////// 0319 // flat preparation attributes 0320 // //////////////////////////////////////////////////////////////////// 0321 // status of the focuser synchronisation 0322 FlatSyncStatus flatSyncStatus { FS_NONE }; 0323 // light source for flat capturing 0324 uint32_t m_CalibrationPreAction { ACTION_NONE }; 0325 // wall coordinates for capturing flats with the wall as light source 0326 SkyPoint wallCoord; 0327 // telescope status for flats using the wall position 0328 ScopeWallPositionStatus wpScopeStatus { WP_NONE }; 0329 0330 // //////////////////////////////////////////////////////////////////// 0331 // capture preparation state 0332 // //////////////////////////////////////////////////////////////////// 0333 /** 0334 * @brief Check if all actions are ready and emit {@see prepareComplete()} if all are ready. 0335 */ 0336 void checkAllActionsReady(); 0337 0338 /** 0339 * @brief Check if all preparation actions are completed 0340 * @return true if all preparation actions are completed 0341 */ 0342 bool areActionsReady(); 0343 0344 /** 0345 * @brief Clear all actions required for preparation 0346 */ 0347 void setAllActionsReady(); 0348 0349 /** 0350 * @brief Prepare CCD temperature checks 0351 */ 0352 void prepareTemperatureCheck(bool enforceCCDTemp); 0353 0354 /** 0355 * @brief prepareRotatorCheck Check if the rotator is at the expected 0356 * target angle. 0357 */ 0358 void prepareRotatorCheck(); 0359 0360 /** 0361 * @brief prepareTargetFilter Initiate changing the filter to the target position 0362 * {@see #targetFilterID} 0363 * @param frameType frame type to be captured 0364 * @param isPreview is the captured frame only a preview? 0365 */ 0366 void prepareTargetFilter(CCDFrameType frameType, bool isPreview); 0367 0368 /** 0369 * @brief Before capturing light frames check, if the scope cover is open. 0370 * @return IPS_OK if cover closed, IPS_BUSY if not and IPS_ALERT if the 0371 * process should be aborted. 0372 */ 0373 IPState checkLightFrameScopeCoverOpen(); 0374 0375 /** 0376 * @brief Check if a certain action has already been initialized 0377 */ 0378 bool isInitialized(CaptureModuleState::PrepareActions action); 0379 /** 0380 * @brief Set a certain action as initialized 0381 */ 0382 void setInitialized(CaptureModuleState::PrepareActions action, bool init); 0383 0384 // //////////////////////////////////////////////////////////////////// 0385 // flats preparation state 0386 // //////////////////////////////////////////////////////////////////// 0387 0388 /** 0389 * @brief checkCalibrationPreActionsReady Check if we completed all the required pre-calibration actions 0390 * @return IPS_OK if completed, IPS_BUSY if in progress, and IPS_ALERT if trouble. 0391 */ 0392 IPState checkCalibrationPreActionsReady(); 0393 0394 /** 0395 * @brief Check if the cover and light for flats is ready 0396 * @return IPS_OK if cover closed, IPS_BUSY if not and IPS_ALERT if the 0397 * process should be aborted. 0398 */ 0399 IPState checkFlatsCoverReady(); 0400 0401 /** 0402 * @brief Check if the selected dark covers is ready. 0403 * @return IPS_OK if cover closed, IPS_BUSY if not and IPS_ALERT if the 0404 * process should be aborted. 0405 */ 0406 IPState checkDarksCoverReady(); 0407 0408 /** 0409 * @brief Ask the user to place a flat screen onto the telescope if a light source is required. 0410 * @return IPS_OK if cover closed, IPS_BUSY if not and IPS_ALERT if the 0411 * process should be aborted. 0412 */ 0413 IPState checkManualCoverReady(bool lightSourceRequired); 0414 0415 /** 0416 * @brief Check if the telescope dust cap is ready for capturing flats or darks. 0417 * @return IPS_OK if cap is closed, IPS_BUSY if not and IPS_ALERT if the 0418 * process should be aborted. 0419 */ 0420 IPState checkDustCapReady(CCDFrameType frameType); 0421 0422 /** 0423 * @brief Check if the telescope is pointing to the desired position on the wall 0424 * for capturing flats. 0425 * @return IPS_OK if cap is closed, IPS_BUSY if not and IPS_ALERT if the 0426 * process should be aborted. 0427 */ 0428 IPState checkWallPositionReady(CCDFrameType frametype); 0429 0430 /** 0431 * @brief Check mount parking before capturing flats. 0432 * @return IPS_OK if cap is closed, IPS_BUSY if not and IPS_ALERT if the 0433 * process should be aborted. 0434 */ 0435 IPState checkPreMountParkReady(); 0436 0437 /** 0438 * @brief Check dome parking before capturing flats. 0439 * @return IPS_OK if cap is closed, IPS_BUSY if not and IPS_ALERT if the 0440 * process should be aborted. 0441 */ 0442 IPState checkPreDomeParkReady(); 0443 0444 /** 0445 * @brief Check if the focuser needs to be moved to the focus position. 0446 * @return IPS_OK if cover closed, IPS_BUSY if not and IPS_ALERT if the 0447 * process should be aborted. 0448 */ 0449 IPState checkFlatSyncFocus(); 0450 0451 // //////////////////////////////////////////////////////////////////// 0452 // darks preparation state 0453 // //////////////////////////////////////////////////////////////////// 0454 0455 /** 0456 * @brief Check if the CCD has a shutter or not. 0457 * @return IPS_OK if ready, IPS_BUSY if running and IPS_ALERT if the 0458 * process should be aborted. 0459 */ 0460 IPState checkHasShutter(); 0461 0462 // //////////////////////////////////////////////////////////////////// 0463 // Attributes shared across all sequence jobs 0464 // //////////////////////////////////////////////////////////////////// 0465 QSharedPointer<CaptureModuleState> m_CaptureModuleState; 0466 0467 // //////////////////////////////////////////////////////////////////// 0468 // sequence job specific states 0469 // //////////////////////////////////////////////////////////////////// 0470 // target filter ID 0471 int targetFilterID { Ekos::INVALID_VALUE }; 0472 FilterManager::FilterPolicy m_filterPolicy { FilterManager::ALL_POLICIES }; 0473 // target temperature 0474 double targetTemperature { Ekos::INVALID_VALUE }; 0475 // target rotation in absolute ticks, NOT angle 0476 double targetPositionAngle { Ekos::INVALID_VALUE }; 0477 // calibration state 0478 CalibrationStage calibrationStage { CAL_NONE }; 0479 // query state for (un)covering the scope 0480 CalibrationCheckType coverQueryState { CAL_CHECK_TASK }; 0481 }; 0482 0483 }; // namespace