File indexing completed on 2024-05-12 15:23:40

0001 /*
0002     SPDX-FileCopyrightText: 2020 Hy Murveit <hy@murveit.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #pragma once
0008 
0009 #include "matr.h"
0010 #include "vect.h"
0011 #include <QString>
0012 #include "ekos/ekos.h"
0013 #include "indi/indicommon.h"
0014 #include "indi/indimount.h"
0015 
0016 class Calibration
0017 {
0018     public:
0019         Calibration();
0020         ~Calibration() {}
0021 
0022         // Initialize the parameters needed to convert from pixels to arc-seconds,
0023         // the current pier side, and the current pointing position.
0024         void setParameters(double ccd_pix_width, double ccd_pix_height, double focalLengthMm,
0025                            int binX, int binY, ISD::Mount::PierSide pierSide,
0026                            const dms &mountRA, const dms &mountDec);
0027 
0028         // Set the current binning, which may be different from what was used during calibration.
0029         void setBinningUsed(int x, int y);
0030 
0031         // Generate new calibrations according to the input parameters.
0032         bool calculate1D(double start_x, double start_y,
0033                          double end_x, double end_y, int RATotalPulse);
0034 
0035         bool calculate2D(
0036             double start_ra_x, double start_ra_y, double end_ra_x, double end_ra_y,
0037             double start_dec_x, double start_dec_y, double end_dec_x, double end_dec_y,
0038             bool *swap_dec, int RATotalPulse, int DETotalPulse);
0039 
0040         // Computes the drift from the detection relative to the reference position.
0041         // If inputs are in pixels, then drift outputs are in pixels.
0042         // If inputs are in arcsecond coordinates then drifts are in arcseconds.
0043         void computeDrift(const GuiderUtils::Vector &detection, const GuiderUtils::Vector &reference,
0044                           double *raDrift, double *decDrift) const;
0045 
0046         double getFocalLength() const
0047         {
0048             return focalMm;
0049         }
0050         double getAngle() const
0051         {
0052             return angle;
0053         }
0054         double getRAAngle() const
0055         {
0056             return calibrationAngleRA;
0057         }
0058         double getDECAngle() const
0059         {
0060             return calibrationAngleDEC;
0061         }
0062 
0063         // Converts the input x & y coordinates from pixels to arc-seconds.
0064         // Does not rotate the input into RA/DEC.
0065         GuiderUtils::Vector convertToArcseconds(const GuiderUtils::Vector &input) const;
0066 
0067         // Converts the input x & y coordinates from arc-seconds to pixels.
0068         // Does not rotate the input into RA/DEC.
0069         GuiderUtils::Vector convertToPixels(const GuiderUtils::Vector &input) const;
0070         void convertToPixels(double xArcseconds, double yArcseconds,
0071                              double *xPixel, double *yPixel) const;
0072 
0073         // Given offsets, convert to RA and DEC coordinates
0074         // by rotating according to the calibration.
0075         // Also inverts the y-axis. Does not convert to arc-seconds.
0076         GuiderUtils::Vector rotateToRaDec(const GuiderUtils::Vector &input) const;
0077         void rotateToRaDec(double dx, double dy, double *ra, double *dec) const;
0078 
0079         // Returns the number of milliseconds that should be pulsed to move
0080         // RA by one arcsecond.
0081         double raPulseMillisecondsPerArcsecond() const;
0082 
0083         // Returns the number of milliseconds that should be pulsed to move
0084         // DEC by one arcsecond.
0085         double decPulseMillisecondsPerArcsecond() const;
0086 
0087         // Returns the number of pixels per arc-second in X and Y and vica versa.
0088         double xPixelsPerArcsecond() const;
0089         double yPixelsPerArcsecond() const;
0090         double xArcsecondsPerPixel() const;
0091         double yArcsecondsPerPixel() const;
0092 
0093         // Save the calibration to Options.
0094         void save() const;
0095         // Restore the saved calibration. If the pier side is different than
0096         // when was calibrated, adjust the angle accordingly.
0097         bool restore(ISD::Mount::PierSide currentPierSide, bool reverseDecOnPierChange,
0098                      int currentBinX, int currentBinY,
0099                      const dms *declination = nullptr);
0100         // As above, but for testing.
0101         bool restore(const QString &encoding, ISD::Mount::PierSide currentPierSide,
0102                      bool reverseDecOnPierChange, int currentBinX, int currentBinY,
0103                      const dms *declination = nullptr);
0104 
0105         bool declinationSwapEnabled() const
0106         {
0107             return decSwap;
0108         }
0109         void setDeclinationSwapEnabled(bool value);
0110 
0111         void reset()
0112         {
0113             initialized = false;
0114         }
0115         // Returns true if calculate1D, calculate2D or restore have been called.
0116         bool isInitialized()
0117         {
0118             return initialized;
0119         }
0120         // Prints the calibration parameters in the debug log.
0121         void logCalibration() const;
0122 
0123     private:
0124         // Internal calibration methods.
0125         bool calculate1D(double dx, double dy, int RATotalPulse);
0126         bool calculate2D(double ra_dx, double ra_dy, double dec_dx, double dec_dy,
0127                          bool *swap_dec, int RATotalPulse, int DETotalPulse);
0128 
0129         // Serialize and restore the calibration state.
0130         QString serialize() const;
0131         bool restore(const QString &encoding);
0132 
0133         // Adjusts the RA rate, according to the calibration and current declination values.
0134         double correctRA(double raMsPerPixel, const dms &calibrationDec, const dms &currentDec);
0135 
0136         // Compute a rotation angle given pixel change coordinates
0137         static double calculateRotation(double x, double y);
0138 
0139         // Set the rotation angle and the rotation matrix.
0140         // The angles are in the arc-second coordinate system (not the pixels--though that would
0141         // be the same thing if the pixels were square).
0142         void setAngle(double rotationAngle);
0143 
0144         // Set the calibrated ra and dec rates.
0145         void setRaPulseMsPerArcsecond(double rate);
0146         void setDecPulseMsPerArcsecond(double rate);
0147 
0148         // computes the ratio of the binning currently used to the binning in use while calibrating.
0149         double binFactor() const;
0150         // Inverse of above.
0151         double inverseBinFactor() const;
0152 
0153         // Sub-binning in X and Y.
0154         int subBinX { 1 };
0155         int subBinY { 1 };
0156 
0157         // It is possible that this calibration was done with one binning, but is now
0158         // being used with another binning. This is the current binning (as opposed to the above
0159         // which is the binning that was in-place during calibration.
0160         int subBinXused { 1 };
0161         int subBinYused { 1 };
0162 
0163         // Pixel width mm, for each pixel,
0164         // Binning does not affect this.
0165         double ccd_pixel_width { 0.003 };
0166         double ccd_pixel_height { 0.003 };
0167 
0168         // Focal length in millimeters.
0169         double focalMm { 500 };
0170 
0171         // This angle is the one in use for calibrating. It may differ from the
0172         // calibrationAngle below if the pier side changes.
0173         double angle { 0 };
0174 
0175         // The rotation matrix that converts between pixel coordinates and RA/DEC.
0176         // This is derived from angle in setAngle().
0177         GuiderUtils::Matrix ROT_Z;
0178 
0179         // The angles associated with the calibration that was computed or
0180         // restored. They won't change as we change pier sides.
0181         double calibrationAngle { 0 };
0182         double calibrationAngleRA = 0;
0183         double calibrationAngleDEC = 0;
0184 
0185         // The calibrated values of how many pulse milliseconds are required to
0186         // move one arcsecond in RA and DEC.
0187         double raPulseMsPerArcsecond { 0 };
0188         double decPulseMsPerArcsecond { 0 };
0189 
0190         // The decSwap that was computed in calibration.
0191         bool calibrationDecSwap { false };
0192 
0193         // The decSwap in use. May be the opposite of calibrationDecSwap if the calibration
0194         // is being used on the opposite pier side as the calibration pier side.
0195         bool decSwap { false };
0196 
0197         // The RA and DEC when calibration was performed. For reference. Not currently used.
0198         dms calibrationRA;
0199         dms calibrationDEC;
0200 
0201         // The side of the pier where the current calibration was calculated.
0202         ISD::Mount::PierSide calibrationPierSide { ISD::Mount::PIER_UNKNOWN };
0203 
0204         bool initialized { false };
0205         friend class TestGuideStars;
0206 };
0207