Warning, file /education/kstars/kstars/ekos/align/polaralignmentassistant.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* Ekos Polar Alignment Assistant Tool 0002 SPDX-FileCopyrightText: 2018-2021 Jasem Mutlaq 0003 SPDX-FileCopyrightText: 2020-2021 Hy Murveit 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #pragma once 0009 0010 #include "ui_polaralignmentassistant.h" 0011 #include "ekos/ekos.h" 0012 #include "ekos/guide/internalguide/starcorrespondence.h" 0013 #include "polaralign.h" 0014 #include "align.h" 0015 #include "indi/indimount.h" 0016 0017 class AlignView; 0018 class QProgressIndicator; 0019 class SolverUtils; 0020 0021 namespace Ekos 0022 { 0023 0024 class PolarAlignWidget; 0025 0026 /** 0027 * @brief The PolarAlignmentAssistant class 0028 * 0029 * Captures three images rotated by a set number of degrees decided by the user (default 30). 0030 * Each image is plate solver to find the center RA,DE coordinates. The three points are then 0031 * used to generate a unique circle with its center as the RA axis. As the mount rotated around 0032 * these point, we can identify the RA rotational axis. From there, we compare the distance from RA axis 0033 * to the celestial pole axis. For a perfectly aligned mount, the two points would overlap exactly. 0034 * In reality, there is also some differences due to the mount mechanical limitations and measurements 0035 * errors. 0036 * 0037 * The user is then presented with a triangle that couples the corrections required in Altitude and Azimuth 0038 * knobs to move the RA axis to the celestial pole. An optional feature is available the calculates the error 0039 * in real time as the user move the mount around during refresh, but this feature is computationally intensive 0040 * as we need to extract stars from each frame. 0041 * 0042 * @author Jasem Mutlaq 0043 * @author Hy Murveit 0044 */ 0045 class PolarAlignmentAssistant : public QWidget, public Ui::PolarAlignmentAssistant 0046 { 0047 Q_OBJECT 0048 0049 public: 0050 explicit PolarAlignmentAssistant(Align *parent, const QSharedPointer<AlignView> &view); 0051 ~PolarAlignmentAssistant(); 0052 0053 typedef enum 0054 { 0055 PAH_IDLE, 0056 PAH_FIRST_CAPTURE, 0057 PAH_FIRST_SOLVE, 0058 PAH_FIND_CP, 0059 PAH_FIRST_ROTATE, 0060 PAH_FIRST_SETTLE, 0061 PAH_SECOND_CAPTURE, 0062 PAH_SECOND_SOLVE, 0063 PAH_SECOND_ROTATE, 0064 PAH_SECOND_SETTLE, 0065 PAH_THIRD_CAPTURE, 0066 PAH_THIRD_SOLVE, 0067 PAH_STAR_SELECT, 0068 PAH_REFRESH, 0069 PAH_POST_REFRESH 0070 } Stage; 0071 0072 // Algorithm choice in UI 0073 typedef enum 0074 { 0075 PLATE_SOLVE_ALGORITHM, 0076 MOVE_STAR_ALGORITHM, 0077 MOVE_STAR_UPDATE_ERR_ALGORITHM 0078 } RefreshAlgorithm; 0079 0080 enum CircleSolution 0081 { 0082 NO_CIRCLE_SOLUTION, 0083 ONE_CIRCLE_SOLUTION, 0084 TWO_CIRCLE_SOLUTION, 0085 INFINITE_CIRCLE_SOLUTION 0086 }; 0087 typedef enum { NORTH_HEMISPHERE, SOUTH_HEMISPHERE } HemisphereType; 0088 0089 // Set the mount used in Align class. 0090 void setCurrentTelescope(ISD::Mount *scope) 0091 { 0092 m_CurrentTelescope = scope; 0093 } 0094 // Sync mount slew speed and available rates from the telescope object 0095 void syncMountSpeed(const QString &speed); 0096 // Enable PAA if the FOV is sufficient 0097 void setEnabled(bool enabled); 0098 // Return the exposure used in the refresh phase. 0099 double getPAHExposureDuration() const 0100 { 0101 return pAHExposure->value(); 0102 } 0103 // Handle updates during the refresh phase such as error estimation. 0104 void processPAHRefresh(); 0105 // Handle solver failure and retry to capture until a preset number of retries is met. 0106 bool processSolverFailure(); 0107 // Handle both automated and manual mount rotations. 0108 void processMountRotation(const dms &ra, double settleDuration); 0109 // After solver is complete, handle PAH Stage processing 0110 void processPAHStage(double orientation, double ra, double dec, double pixscale, bool eastToTheRight, short healpix, 0111 short index); 0112 // Return current PAH stage 0113 Stage getPAHStage() const 0114 { 0115 return m_PAHStage; 0116 } 0117 // Set active stage. 0118 void setPAHStage(Stage stage); 0119 // Start the polar alignment process. 0120 void startPAHProcess(); 0121 // Stops the polar alignment process. 0122 void stopPAHProcess(); 0123 // Process the results of WCS from the solving process. If the results are good, we continue to the next phase. 0124 // Otherwise, we abort the operation. 0125 void setWCSToggled(bool result); 0126 // Update GUI to reflect mount status. 0127 void setMountStatus(ISD::Mount::Status newState); 0128 // Update the correction offset by this percentage in order to move the triangle around when clicking on 0129 // for example. 0130 void setPAHCorrectionOffsetPercentage(double dx, double dy); 0131 // Update the PAH refresh duration 0132 void setPAHRefreshDuration(double value) 0133 { 0134 pAHExposure->setValue(value); 0135 } 0136 // Start the refresh process. 0137 void startPAHRefreshProcess(); 0138 // This should be called when manual slewing is complete. 0139 void setPAHSlewDone(); 0140 // Return current active stage label 0141 QString getPAHStageString(bool translated = true) const 0142 { 0143 return translated ? i18n(PAHStages[m_PAHStage]) : PAHStages[m_PAHStage]; 0144 } 0145 // Return last message 0146 QString getPAHMessage() const; 0147 // Set image data from align class 0148 void setImageData(const QSharedPointer<FITSData> &image); 0149 0150 void setPAHRefreshAlgorithm(RefreshAlgorithm value); 0151 0152 protected: 0153 // Polar Alignment Helper slots 0154 void rotatePAH(); 0155 void setPAHCorrectionOffset(int x, int y); 0156 0157 private: 0158 /** 0159 * @brief Warns the user if the polar alignment might cross the meridian. 0160 */ 0161 bool checkPAHForMeridianCrossing(); 0162 0163 /** 0164 * @brief calculatePAHError Calculate polar alignment error in the Polar Alignment Helper (PAH) method 0165 * @return True if calculation is successsful, false otherwise. 0166 */ 0167 bool calculatePAHError(); 0168 0169 /** 0170 * @brief syncCorrectionVector Flip correction vector based on user settings. 0171 */ 0172 void syncCorrectionVector(); 0173 0174 /** 0175 * @brief setupCorrectionGraphics Update align view correction graphics. 0176 * @param pixel 0177 */ 0178 void setupCorrectionGraphics(const QPointF &pixel); 0179 0180 /** 0181 * @brief supdateRefreshDisplay Updates the UI's refresh error stats. 0182 * @param azError the azimuth error in degrees 0183 * @param altError the altitude error in degrees 0184 */ 0185 void updateRefreshDisplay(double azError, double altError); 0186 0187 signals: 0188 // Report new log 0189 void newLog(const QString &); 0190 // Request new capture and solve 0191 void captureAndSolve(); 0192 // Report correction vector and original errors 0193 void polarResultUpdated(QLineF correctionVector, double polarError, double azError, double altError); 0194 // Report updated errors 0195 void updatedErrorsChanged(double total, double az, double alt); 0196 // Report new correction vector 0197 void newCorrectionVector(QLineF correctionVector); 0198 // Report new PAH stage 0199 void newPAHStage(Stage stage); 0200 // Report new PAH message 0201 void newPAHMessage(const QString &message); 0202 // Report whether the tool is enabled or not 0203 void PAHEnabled(bool); 0204 // Request to set alignment table result 0205 void newAlignTableResult(Align::AlignResult result); 0206 // Report that the align view was updated. 0207 void newFrame(const QSharedPointer<FITSView> &view); 0208 0209 private: 0210 void updateDisplay(Stage stage, const QString &message); 0211 void drawArrows(double altError, double azError); 0212 void showUpdatedError(bool show); 0213 // These are only used in the plate-solve refresh scheme. 0214 void solverDone(bool timedOut, bool success, const FITSImage::Solution &solution, double elapsedSeconds); 0215 void startSolver(); 0216 void updatePlateSolveTriangle(const QSharedPointer<FITSData> &image); 0217 0218 // Polar Alignment Helper 0219 Stage m_PAHStage { PAH_IDLE }; 0220 0221 SkyPoint targetPAH; 0222 0223 // Which hemisphere are we located on? 0224 HemisphereType hemisphere; 0225 0226 // Polar alignment will retry capture & solve a few times if solve fails. 0227 int m_PAHRetrySolveCounter { 0 }; 0228 0229 // Points on the image to correct mount's ra axis. 0230 // correctionFrom is the star the user selected (or center of the image at start). 0231 // correctionTo is where theuser should move that star. 0232 // correctionAltTo is where the use should move that star to only fix altitude. 0233 QPointF correctionFrom, correctionTo, correctionAltTo; 0234 0235 // RA/DEC coordinates where the image center needs to be move to to correct the RA axis. 0236 SkyPoint refreshSolution, altOnlyRefreshSolution; 0237 0238 0239 bool detectStarsPAHRefresh(QList<Edge> *stars, int num, int x, int y, int *xyIndex); 0240 0241 // Incremented every time sufficient # of stars are detected (for move-star refresh) or 0242 // when solver is successful (for plate-solve refresh). 0243 int refreshIteration { 0 }; 0244 // Incremented on every image received. 0245 int imageNumber { 0 }; 0246 StarCorrespondence starCorrespondencePAH; 0247 0248 // Class used to estimate alignment error. 0249 PolarAlign polarAlign; 0250 0251 // Pointer to image data 0252 QSharedPointer<FITSData> m_ImageData; 0253 0254 // Reference to parent 0255 Align *m_AlignInstance {nullptr}; 0256 0257 // Reference to current active telescope 0258 ISD::Mount *m_CurrentTelescope { nullptr }; 0259 0260 // Reference to align view 0261 QSharedPointer<AlignView> m_AlignView; 0262 0263 // PAH Stage Map 0264 static const QMap<Stage, const char *> PAHStages; 0265 0266 // Threshold to stop PAH rotation in degrees 0267 static constexpr uint8_t PAH_ROTATION_THRESHOLD { 5 }; 0268 0269 PolarAlignWidget *polarAlignWidget {nullptr}; 0270 0271 // Used in the refresh part of polar alignment. 0272 QSharedPointer<SolverUtils> m_Solver; 0273 double m_LastRa {0}; 0274 double m_LastDec {0}; 0275 double m_LastOrientation {0}; 0276 double m_LastPixscale {0}; 0277 0278 // Restricts (the internal solver) to using the index and healpix 0279 // from the previous solve, if that solve was successful. 0280 int m_IndexToUse { -1 }; 0281 int m_HealpixToUse { -1 }; 0282 int m_NumHealpixFailures { 0 }; 0283 }; 0284 }