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)