Warning, file /education/kstars/kstars/ekos/align/polaralign.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 SPDX-FileCopyrightText: 2021 Hy Murveit <hy@murveit.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #pragma once 0008 0009 #include <dms.h> 0010 #include <skypoint.h> 0011 0012 class FITSData; 0013 class TestPolarAlign; 0014 0015 /********************************************************************* 0016 Polar alignment support class. Note, the telescope can be pointing anywhere. 0017 It doesn't need to point at the pole. 0018 0019 Use this class as follows: 0020 1) Construct with the geo information. 0021 PolarAlign polarAlign(geoLocation); 0022 2) Start the polar align procedure. Capture, solve and add wcs from the 0023 solve to the FITSData image. Then: 0024 polarAlign.addPoint(image); 0025 3) Rotate the mount in RA ~30 degrees (could be less or more) east (or west) 0026 and capture, solve and add wcs from the solve to the new image. Then: 0027 polarAlign.addPoint(image); 0028 4) Rotate the mount in RA another ~30 degrees east (or west) 0029 and capture, solve and add wcs from the solve to the new image. Then: 0030 polarAlign.addPoint(image); 0031 5) Find the mount's axis of rotation as follows: 0032 if (!polarAlign.findAxis()) 0033 error(); 0034 6) Compute the azimuth and altitude offset for the mount. 0035 double altitudeError = axisAlt - latitudeDegrees; 0036 double azimuthError = axisAz - 0; 0037 7) Compute the overall error 0038 dms polarError(hypot(azimuthError, altitudeError)); 0039 0040 Using the "move star" correction scheme: 0041 0042 8a) Compute a target correction 0043 int correctedX, correctedY; 0044 if (!polarAlign.findCorrectedPixel( 0045 imageData, x, y, altitudeError, azimuthError, &correctedX, &correctedY)) 0046 error(); 0047 9a) The user uses the GEM azimuth and altitude adjustments to move the 0048 object at position x,y in the image to position correctedX, correctedY. 0049 0050 Using the plate solve correction scheme: 0051 0052 8b) Compute the remaining axis error (after partial correction) 0053 SkyPoint coords, solution; 0054 coords = [coordinates from plate-solving a refresh image] 0055 // The signs of the error indicate the correction direction 0056 processRefreshCoords(coords, currentTime, &azError, &altError); 0057 9b) The user uses the GEM azimuth and altitude adjustments to move the telescope. 0058 positive altitude error: reduce altitide. 0059 positive azimuth error: point telescope more to the left. 0060 *********************************************************************/ 0061 0062 class PolarAlign 0063 { 0064 public: 0065 0066 // The polealignment scheme requires the GeoLocation to operate properly. 0067 // Certain aspects can be tested without it. 0068 PolarAlign(const GeoLocation *geo = nullptr); 0069 0070 // Add a sample point. 0071 bool addPoint(const QSharedPointer<FITSData> &image); 0072 0073 // Returns the i-th point (zero based). 0074 const SkyPoint getPoint(int index) 0075 { 0076 if (index >= 0 && index < points.size()) 0077 return points[index]; 0078 return SkyPoint(); 0079 } 0080 0081 // Finds the mount's axis of rotation. Three points must have been added. 0082 // Returns false if the axis can't be found. 0083 bool findAxis(); 0084 0085 // Returns the image coordinate that pixel x,y should be moved to to correct 0086 // the mount's axis. Image is usually the 3rd PAA image. x,y are image coordinates. 0087 // 3 Points must have been added and findAxis() must have been called. 0088 // Uses the axis determined by findAxis(). Returns correctedX and correctedY, 0089 // the target position that the x,y pixel should move to. 0090 bool findCorrectedPixel(const QSharedPointer<FITSData> &image, const QPointF &pixel, 0091 QPointF *corrected, bool altOnly = false); 0092 0093 // Returns the mount's azimuth and altitude error given the known geographic location 0094 // and the azimuth center and altitude center computed in findAxis(). 0095 void calculateAzAltError(double *azError, double *altError) const; 0096 0097 // Given the current axis, fill in azError and altError with the polar alignment 0098 // error, if a star at location pixel were move in the camera view to pixel2. 0099 // image would be the 3rd PAA image. 0100 // Returns false if the paa error couldn't be computer. 0101 bool pixelError(const QSharedPointer<FITSData> &image, const QPointF &pixel, const QPointF &pixel2, 0102 double *azError, double *altError); 0103 0104 /// reset starts the process over, removing the points. 0105 void reset(); 0106 0107 // Returns the mount's axis--for debugging. 0108 void getAxis(double *azAxis, double *altAxis) const; 0109 0110 // This is not required, and is a hint as to how far the pixelError method should search 0111 // for a solution. The suggestion may be ignored if it is too large or small, but in 0112 // general this should be a degree or so larger than the polar alignment error in degrees. 0113 void setMaxPixelSearchRange(double degrees); 0114 0115 // Compute the remaining polar-alignment azimuth and altitude error from a new image's coordinates 0116 // as compared with the coordinates from the last polar-align measurement image. 0117 // The differences between the two coordinates is a measure of the rotation that has been 0118 // applied during the polar-align correction phase. 0119 bool processRefreshCoords(const SkyPoint &coords, const KStarsDateTime &time, 0120 double *azError, double *altError, 0121 double *azAdjustment = nullptr, double *altAdjustment = nullptr) const; 0122 0123 // Find the skypoints where the telescope needs to point (rotated there by adjusting az and alt) 0124 // in order for the mount to be properly polar aligned. 0125 bool refreshSolution(SkyPoint *solution, SkyPoint *altOnlySolution) const; 0126 0127 private: 0128 // returns true in the northern hemisphere. 0129 // if no geo location available, defaults to northern. 0130 bool northernHemisphere() const; 0131 0132 // These internal methods find the pixel with the desired azimuth and altitude. 0133 bool findAzAlt(const QSharedPointer<FITSData> &image, double azimuth, double altitude, QPointF *pixel) const; 0134 0135 // Does the necessary processing so that azimuth and altitude values 0136 // can be retrieved for the x,y pixel in image. 0137 bool prepareAzAlt(const QSharedPointer<FITSData> &image, const QPointF &pixel, SkyPoint *point) const; 0138 0139 0140 // Internal utility used by the external findCorrectedPixel and by pixelError(). 0141 // Similar args as the public findCorrectedPixel(). 0142 bool findCorrectedPixel(const QSharedPointer<FITSData> &image, const QPointF &pixel, 0143 QPointF *corrected, double azError, double altError); 0144 0145 // Internal utility used by the public pixelError, which iterates at different 0146 // resolutions passed in to this method. As the resoltion can be coarse, actualPixel 0147 // is the one used (as opposed to pixel2) for the error returned. 0148 void pixelError(const QSharedPointer<FITSData> &image, const QPointF &pixel, const QPointF &pixel2, 0149 double minAz, double maxAz, double azInc, 0150 double minAlt, double maxAlt, double altInc, 0151 double *azError, double *altError, QPointF *actualPixel); 0152 0153 // These three positions are used to estimate the polar alignment error. 0154 QVector<SkyPoint> points; 0155 QVector<KStarsDateTime> times; 0156 0157 // The geographic location used to compute azimuth and altitude. 0158 const GeoLocation *geoLocation; 0159 0160 // Values set by the last call to findAxis() that correspond to the mount's axis. 0161 double azimuthCenter { 0 }; 0162 double altitudeCenter { 0 }; 0163 0164 // Constrains the search for the correction pixel. Units are degrees. 0165 double maxPixelSearchRange { 2 }; 0166 0167 friend TestPolarAlign; 0168 };