File indexing completed on 2024-04-14 03:43:42

0001 /*  CalibrationProcess class test.
0002     Copyright (C) 2021 Hy Murveit
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #include "ekos/guide/internalguide/calibrationprocess.h"
0008 
0009 #include <QTest>
0010 #include <QObject>
0011 
0012 #include "Options.h"
0013 #include "ekos/guide/internalguide/calibration.h"
0014 //#include "guidelog.h"
0015 #include "indi/indicommon.h"
0016 #include "ekos/ekos.h"
0017 
0018 using Ekos::GuideState;
0019 using Ekos::CalibrationProcess;
0020 
0021 struct CalibrationIteration
0022 {
0023     double x, y;
0024     GuideDirection pulseDir;
0025     int pulseMsec;
0026     GuideState state;
0027 };
0028 
0029 struct CalibrationTest
0030 {
0031     // input parameters
0032     bool twoAxis, justRA;
0033     int iterations;
0034     bool backlash;
0035     int pulse;
0036     int maxMove;
0037     // input data
0038     QVector<CalibrationIteration> io;
0039     // calibration results
0040     double raAngle, decAngle;
0041     double raMsPerPixel, decMsPerPixel;
0042     bool decSwap;
0043 };
0044 
0045 class TestCalibrationProcess : public QObject
0046 {
0047         Q_OBJECT
0048 
0049     public:
0050         TestCalibrationProcess();
0051         ~TestCalibrationProcess() override = default;
0052 
0053     private slots:
0054         void basicTest();
0055 
0056     private:
0057         void runTest(const CalibrationTest &test);
0058 };
0059 
0060 #include "testcalibrationprocess.moc"
0061 
0062 TestCalibrationProcess::TestCalibrationProcess() : QObject()
0063 {
0064 }
0065 
0066 bool compareDouble(double d1, double d2, double tolerance = .001)
0067 {
0068     return (fabs(d1 - d2) < tolerance);
0069 }
0070 
0071 bool checkCalibrationProcessOutputs(CalibrationProcess *cp,
0072                                     GuideDirection pulseDir, int pulseMsec,
0073                                     GuideState calibrationState)
0074 {
0075     GuideDirection dir;
0076     int msec;
0077     cp->getPulse(&dir, &msec);
0078     if (dir != pulseDir || msec != pulseMsec)
0079     {
0080         fprintf(stderr, "dir,pulse %d %d don't match %d,%d\n",
0081                 static_cast<int>(dir), msec, pulseDir, pulseMsec);
0082         return false;
0083     }
0084 
0085     Ekos::GuideState status = cp->getStatus();
0086     if (status != calibrationState)
0087     {
0088         fprintf(stderr, "status %d doesn't match %d\n",
0089                 static_cast<int>(status), static_cast<int>(calibrationState));
0090         return false;
0091     }
0092     return true;
0093 }
0094 
0095 // These test cases are taken from scraping data from running the simulator with the calibration
0096 // scheme (before a refractor, had seemed to be working well for a number of years).
0097 
0098 // Standard successful calibration. Hits the limit of 5 iterations per direction--doesn't reach the 15-pixel max-move.
0099 // Sumulator had binning 2x2, so moved fewer pixels per pulse.
0100 CalibrationTest calTest1 =
0101 {
0102     /*twoAxis*/true, /*justRA*/false, /*iterations*/5, /*backlash*/true, /*pulse*/1100, /*maxMove*/15,
0103     {   { 104.989693, 85.002304, GuideDirection::RA_INC_DIR, 1100, GuideState::GUIDE_CALIBRATING },
0104         { 104.999672, 85.989754, GuideDirection::RA_INC_DIR, 1100, GuideState::GUIDE_CALIBRATING },
0105         { 105.013229, 87.017471, GuideDirection::RA_INC_DIR, 1100, GuideState::GUIDE_CALIBRATING },
0106         { 104.977692, 87.086075, GuideDirection::RA_INC_DIR, 2200, GuideState::GUIDE_CALIBRATING },
0107         { 104.989830, 89.007881, GuideDirection::RA_INC_DIR, 1100, GuideState::GUIDE_CALIBRATING },
0108         { 105.034843, 89.030762, GuideDirection::RA_DEC_DIR, 1100, GuideState::GUIDE_CALIBRATING },
0109         { 104.995323, 88.999382, GuideDirection::RA_DEC_DIR, 1100, GuideState::GUIDE_CALIBRATING },
0110         { 105.000000, 88.005966, GuideDirection::RA_DEC_DIR, 1100, GuideState::GUIDE_CALIBRATING },
0111         { 104.995422, 86.993683, GuideDirection::RA_DEC_DIR, 1100, GuideState::GUIDE_CALIBRATING },
0112         { 105.005203, 86.976059, GuideDirection::RA_DEC_DIR, 1100, GuideState::GUIDE_CALIBRATING },
0113         { 105.018433, 86.018028, GuideDirection::DEC_INC_DIR, 1100, GuideState::GUIDE_CALIBRATING },
0114         { 106.029907, 86.026863, GuideDirection::DEC_INC_DIR, 1100, GuideState::GUIDE_CALIBRATING },
0115         { 105.992226, 85.968170, GuideDirection::DEC_INC_DIR, 1100, GuideState::GUIDE_CALIBRATING },
0116         { 107.023537, 85.995636, GuideDirection::DEC_INC_DIR, 1100, GuideState::GUIDE_CALIBRATING },
0117         { 106.964882, 85.875992, GuideDirection::DEC_INC_DIR, 1100, GuideState::GUIDE_CALIBRATING },
0118         { 107.960190, 86.033669, GuideDirection::DEC_INC_DIR, 1100, GuideState::GUIDE_CALIBRATING },
0119         { 108.015701, 86.008209, GuideDirection::DEC_INC_DIR, 2200, GuideState::GUIDE_CALIBRATING },
0120         { 108.999283, 85.967667, GuideDirection::DEC_INC_DIR, 1100, GuideState::GUIDE_CALIBRATING },
0121         { 110.004478, 85.963715, GuideDirection::DEC_INC_DIR, 1100, GuideState::GUIDE_CALIBRATING },
0122         { 110.056694, 85.984901, GuideDirection::DEC_DEC_DIR, 1100, GuideState::GUIDE_CALIBRATING },
0123         { 110.009071, 85.982864, GuideDirection::DEC_DEC_DIR, 2200, GuideState::GUIDE_CALIBRATING },
0124         { 109.005264, 86.021690, GuideDirection::DEC_DEC_DIR, 1100, GuideState::GUIDE_CALIBRATING },
0125         { 107.971313, 86.018730, GuideDirection::DEC_DEC_DIR, 1100, GuideState::GUIDE_CALIBRATING },
0126         { 107.890785, 85.981506, GuideDirection::DEC_DEC_DIR, 1100, GuideState::GUIDE_CALIBRATING },
0127         { 107.052650, 85.997002, GuideDirection::DEC_DEC_DIR, 1100, GuideState::GUIDE_CALIBRATING },
0128         { 106.989433, 86.010635, GuideDirection::DEC_DEC_DIR, 1100, GuideState::GUIDE_CALIBRATING },
0129         { 105.983643, 85.992851, GuideDirection::NO_DIR, 0, GuideState::GUIDE_CALIBRATION_SUCCESS }
0130     },
0131     /*raAngle*/ 270.642141, /*decAngle*/357.982581, /*raMsPerPx*/ 1365.201045, /*decMsPerPx*/1777.789432, /*decSwap*/true
0132 };
0133 
0134 // Similar successful calibration. Because of the long (5000ms) pulses, hits the maxMove limit before the 10 iterations.
0135 CalibrationTest calTest2 =
0136 {
0137     /*twoAxis*/true, /*justRA*/false, /*iterations*/10, /*backlash*/true, /*pulse*/5000, /*maxMove*/15,
0138     {   { 155.981155, 62.958744, GuideDirection::RA_INC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0139         { 155.995193, 66.021431, GuideDirection::RA_INC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0140         { 155.981567, 67.996651, GuideDirection::RA_INC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0141         { 156.015305, 71.015106, GuideDirection::RA_INC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0142         { 156.101456, 74.015106, GuideDirection::RA_INC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0143         { 155.998688, 77.011536, GuideDirection::RA_INC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0144         { 156.046844, 80.006264, GuideDirection::RA_DEC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0145         { 156.001404, 77.005074, GuideDirection::RA_DEC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0146         { 155.995056, 73.996086, GuideDirection::RA_DEC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0147         { 155.955582, 71.022438, GuideDirection::RA_DEC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0148         { 156.002792, 67.984299, GuideDirection::RA_DEC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0149         { 155.975494, 65.963425, GuideDirection::RA_DEC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0150         { 155.978531, 63.003754, GuideDirection::DEC_INC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0151         { 158.011566, 63.041481, GuideDirection::DEC_INC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0152         { 161.019012, 62.996876, GuideDirection::DEC_INC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0153         { 163.008865, 62.995979, GuideDirection::DEC_INC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0154         { 165.022339, 63.001591, GuideDirection::DEC_INC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0155         { 168.014999, 62.961784, GuideDirection::DEC_INC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0156         { 170.014236, 62.975964, GuideDirection::DEC_INC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0157         { 172.002640, 63.029968, GuideDirection::DEC_INC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0158         { 174.016953, 63.025021, GuideDirection::DEC_INC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0159         { 177.018311, 63.009003, GuideDirection::DEC_DEC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0160         { 174.006042, 63.034149, GuideDirection::DEC_DEC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0161         { 172.016876, 62.972244, GuideDirection::DEC_DEC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0162         { 170.013077, 62.983200, GuideDirection::DEC_DEC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0163         { 167.967270, 62.898540, GuideDirection::DEC_DEC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0164         { 164.990936, 63.028084, GuideDirection::DEC_DEC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0165         { 162.964462, 62.978321, GuideDirection::DEC_DEC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0166         { 161.016037, 63.011227, GuideDirection::DEC_DEC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0167         { 158.015213, 63.022118, GuideDirection::DEC_DEC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0168         { 156.009674, 62.980377, GuideDirection::NO_DIR, 0, GuideState::GUIDE_CALIBRATION_SUCCESS }
0169     },
0170     /*raAngle*/ 270.220776, /*decAngle*/359.956572, /*raMsPerPx*/ 1759.773729, /*decMsPerPx*/2187.595339, /*decSwap*/true
0171 };
0172 
0173 // Standard successful calibration. Limited by the 25 max-move (had binning 1x1).
0174 CalibrationTest calTest3 =
0175 {
0176     /*twoAxis*/true, /*justRA*/false, /*iterations*/10, /*backlash*/true, /*pulse*/5000, /*maxMove*/25,
0177     {
0178         {446.999634, 55.999676, GuideDirection::RA_INC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0179         {447.034882, 61.971882, GuideDirection::RA_INC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0180         {446.993652, 67.997871, GuideDirection::RA_INC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0181         {446.981628, 73.984337, GuideDirection::RA_INC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0182         {446.996338, 80.001945, GuideDirection::RA_INC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0183         {446.988403, 85.002335, GuideDirection::RA_DEC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0184         {446.994995, 79.995117, GuideDirection::RA_DEC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0185         {446.998596, 73.953369, GuideDirection::RA_DEC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0186         {446.974060, 67.939110, GuideDirection::RA_DEC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0187         {447.005188, 61.985844, GuideDirection::RA_DEC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0188         {447.020874, 55.966709, GuideDirection::DEC_INC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0189         {450.979340, 55.993347, GuideDirection::DEC_INC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0190         {455.958221, 56.010612, GuideDirection::DEC_INC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0191         {460.005951, 55.988449, GuideDirection::DEC_INC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0192         {465.008972, 56.003986, GuideDirection::DEC_INC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0193         {469.441742, 55.977436, GuideDirection::DEC_INC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0194         {474.052795, 56.021942, GuideDirection::DEC_INC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0195         {478.997711, 55.995457, GuideDirection::DEC_DEC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0196         {474.003296, 55.990456, GuideDirection::DEC_DEC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0197         {469.449066, 55.949821, GuideDirection::DEC_DEC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0198         {464.989258, 56.006073, GuideDirection::DEC_DEC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0199         {460.006256, 55.995888, GuideDirection::DEC_DEC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0200         {455.963013, 56.034840, GuideDirection::DEC_DEC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0201         {451.027283, 56.041237, GuideDirection::DEC_DEC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0202         {447.000793, 56.051575, GuideDirection::NO_DIR, 0, GuideState::GUIDE_CALIBRATION_SUCCESS }
0203     },
0204     /*raAngle*/ 269.977814, /*decAngle*/359.995686, /*raMsPerPx*/ 861.989870, /*decMsPerPx*/1070.726035, /*decSwap*/true
0205 };
0206 
0207 // Like above, but tricked the simulator to move in the opposite dec direction --> decSwap = false.
0208 CalibrationTest calTest4 =
0209 {
0210     /*twoAxis*/true, /*justRA*/false, /*iterations*/10, /*backlash*/true, /*pulse*/5000, /*maxMove*/25,
0211     {
0212 
0213         {157.016357, 251.045471, GuideDirection::RA_INC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0214         {156.975937, 257.043976, GuideDirection::RA_INC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0215         {157.006653, 263.000519, GuideDirection::RA_INC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0216         {157.004440, 269.004608, GuideDirection::RA_INC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0217         {156.989700, 275.023102, GuideDirection::RA_INC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0218         {157.025482, 281.030853, GuideDirection::RA_DEC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0219         {157.013367, 275.001831, GuideDirection::RA_DEC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0220         {157.000717, 269.004669, GuideDirection::RA_DEC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0221         {157.008133, 263.028442, GuideDirection::RA_DEC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0222         {157.025223, 256.971863, GuideDirection::RA_DEC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0223         {157.004089, 251.025360, GuideDirection::DEC_INC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0224         {151.997040, 250.967361, GuideDirection::DEC_INC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0225         {147.966919, 251.009552, GuideDirection::DEC_INC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0226         {143.053177, 251.002197, GuideDirection::DEC_INC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0227         {139.009094, 250.998291, GuideDirection::DEC_INC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0228         {133.968353, 251.036285, GuideDirection::DEC_INC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0229         {129.004593, 251.000305, GuideDirection::DEC_INC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0230         {125.026917, 251.038864, GuideDirection::DEC_DEC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0231         {129.021027, 250.987061, GuideDirection::DEC_DEC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0232         {133.992371, 250.999512, GuideDirection::DEC_DEC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0233         {138.996811, 251.009186, GuideDirection::DEC_DEC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0234         {143.031677, 250.988510, GuideDirection::DEC_DEC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0235         {148.006699, 251.001663, GuideDirection::DEC_DEC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0236         {151.995514, 251.071701, GuideDirection::DEC_DEC_DIR, 5000, GuideState::GUIDE_CALIBRATING },
0237         {157.012283, 251.060547, GuideDirection::NO_DIR, 0, GuideState::GUIDE_CALIBRATION_SUCCESS }
0238     },
0239     /*raAngle*/ 270.017435, /*decAngle*/180.151901, /*raMsPerPx*/ 833.739546, /*decMsPerPx*/1112.338058, /*decSwap*/false
0240 };
0241 
0242 
0243 void TestCalibrationProcess::runTest(const CalibrationTest &test)
0244 {
0245     //Options::setTwoAxisEnabled(true);
0246     Options::setAutoModeIterations(test.iterations);
0247     Options::setGuideCalibrationBacklash(test.backlash);
0248     Options::setCalibrationPulseDuration(test.pulse);
0249     Options::setCalibrationMaxMove(test.maxMove);
0250 
0251     Calibration calibration;
0252 
0253     std::unique_ptr<CalibrationProcess> calibrationProcess;
0254     calibrationProcess.reset(new CalibrationProcess(test.io[0].x, test.io[0].y, test.justRA));
0255     QVERIFY(!calibrationProcess->inProgress());
0256     calibrationProcess->useCalibration(&calibration);
0257 
0258     for (const auto &d : test.io)
0259     {
0260         calibrationProcess->iterate(d.x, d.y);
0261         bool checkCalibrationProcessOutputs(CalibrationProcess * cp,
0262                                             GuideDirection pulseDir, int pulseMsec,
0263                                             GuideState calibrationState);
0264         QVERIFY(checkCalibrationProcessOutputs(calibrationProcess.get(), d.pulseDir, d.pulseMsec, d.state));
0265     }
0266 
0267     QVERIFY(compareDouble(calibration.getRAAngle(), test.raAngle));
0268     QVERIFY(compareDouble(calibration.getDECAngle(), test.decAngle));
0269     QVERIFY(compareDouble(calibration.raPulseMillisecondsPerArcsecond() * calibration.xArcsecondsPerPixel(),
0270                           test.raMsPerPixel));
0271     QVERIFY(compareDouble(calibration.decPulseMillisecondsPerArcsecond() * calibration.yArcsecondsPerPixel(),
0272                           test.decMsPerPixel));
0273     QVERIFY(calibration.declinationSwapEnabled() == test.decSwap);
0274 }
0275 
0276 void TestCalibrationProcess::basicTest()
0277 {
0278     runTest(calTest1);
0279     runTest(calTest2);
0280     runTest(calTest3);
0281     runTest(calTest4);
0282 }
0283 
0284 QTEST_GUILESS_MAIN(TestCalibrationProcess)