File indexing completed on 2024-04-14 14:12:08

0001 /*
0002     KStars UI tests for meridian flip
0003 
0004     SPDX-FileCopyrightText: 2020 Wolfgang Reissenberger <sterne-jaeger@openfuture.de>
0005 
0006     SPDX-License-Identifier: GPL-2.0-or-later
0007 */
0008 
0009 
0010 #include "test_ekos_meridianflip.h"
0011 
0012 #if defined(HAVE_INDI)
0013 
0014 #include <qdir.h>
0015 
0016 #include "kstars_ui_tests.h"
0017 #include "test_ekos.h"
0018 #include "test_ekos_simulator.h"
0019 
0020 #include "auxiliary/dms.h"
0021 #include "ksutils.h"
0022 #include "ekos/guide/internalguide/gmath.h"
0023 #include "Options.h"
0024 #include "ekos/capture/capture.h"
0025 
0026 /* *****************************************************************************
0027  *
0028  * Properly executing a meridian flip and continuing afterwards in exactly the
0029  * same way as before is a challenge:
0030  * - If no capturing is running, it should simply take place.
0031  * - If capturing is running, the meridian flip should wait until the current
0032  *   frame is captured, capturing is suspended, the meridian flip takes place
0033  *   and capturing continues where it was suspended. This needs to be tested if
0034  *   a meridian flip happens in the middle of a capture sequence or between two
0035  *   of them. Therefore, all capture tests are executed for a LLL sequence and
0036  *   a RGB sequence. In addition:
0037  *   - if guiding was active, guiding should be activated again after the meridian
0038  *     flip and afterwards guiding should continue
0039  *   - if an alignment has taken place after the last slew, a re-alignment should
0040  *     be executed after the flip and before guiding and capturing.
0041  *   All this could be combined with the pre-capturing actions of focusing and
0042  *   dithering.
0043  *
0044  * The tests are available both for the internal guider and for PHD2. For testing
0045  * with PHD2, invoke the test with the arguments -guider PHD2.
0046  * ***************************************************************************** */
0047 
0048 
0049 TestEkosMeridianFlip::TestEkosMeridianFlip(QObject *parent) : TestEkosMeridianFlipBase(parent)
0050 {
0051 }
0052 
0053 TestEkosMeridianFlip::TestEkosMeridianFlip(QString guider, QObject *parent) : TestEkosMeridianFlipBase(guider, parent)
0054 {
0055 }
0056 
0057 
0058 void TestEkosMeridianFlip::testSimpleMF()
0059 {
0060     // slew close to the meridian
0061     QVERIFY(positionMountForMF(7.0));
0062 
0063     // check if meridian flip runs and completes successfully (15 secs buffer for startup)
0064     QVERIFY(checkMFStarted(7 + 15));
0065 }
0066 
0067 
0068 void TestEkosMeridianFlip::testSimpleMFDelay()
0069 {
0070     // switch to mount module
0071     KTRY_SWITCH_TO_MODULE_WITH_TIMEOUT(Ekos::Manager::Instance()->mountModule(), 1000);
0072 
0073     double delay = 4.8;
0074     // activate meridian flip
0075     QVERIFY(enableMeridianFlip(delay));
0076 
0077     // slew close to the meridian
0078     QVERIFY(positionMountForMF(7.0));
0079 
0080     // check that the meridian flip is distance is in the expected corridor
0081     int distance = secondsToMF();
0082     qCInfo(KSTARS_EKOS_TEST()) << distance << "seconds to meridian flip...";
0083     QTRY_VERIFY(delay < distance && distance < delay + 7);
0084 
0085     // check if meridian flip runs and completes successfully (15 secs buffer for startup)
0086     QVERIFY(checkMFStarted(static_cast<int>(delay) + 7 + 15));
0087 }
0088 
0089 
0090 void TestEkosMeridianFlip::testGuidingMF()
0091 {
0092     // prepare the test case and calibrate
0093     QVERIFY(prepareMFTestcase(false, false));
0094 
0095     // slew close to the meridian
0096     QVERIFY(positionMountForMF(75.0));
0097 
0098     // start guiding
0099     QVERIFY(m_CaptureHelper->startGuiding(2.0));
0100 
0101     // expected guiding behavior during the meridian flip
0102     m_CaptureHelper->expectedGuidingStates.enqueue(Ekos::GUIDE_ABORTED);
0103 
0104     // check if meridian flip runs and completes successfully
0105     QVERIFY(checkMFExecuted(80));
0106     // meridian flip should have been aborted
0107     KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedGuidingStates, 0.0);
0108 
0109     // check if guiding has NOT been restarted (since we are not capturing
0110     QTRY_VERIFY_WITH_TIMEOUT(m_CaptureHelper->getGuidingStatus() == Ekos::GUIDE_IDLE
0111                              || m_CaptureHelper->getGuidingStatus() == Ekos::GUIDE_ABORTED, 10000);
0112 }
0113 
0114 
0115 void TestEkosMeridianFlip::testCaptureMF()
0116 {
0117     // set up the capture sequence
0118     QVERIFY(prepareCaptureTestcase(10, false, false));
0119 
0120     // start capturing
0121     QVERIFY(startCapturing());
0122 
0123     // check if single capture completes correctly
0124     m_CaptureHelper->expectedCaptureStates.enqueue(Ekos::CAPTURE_IMAGE_RECEIVED);
0125 
0126     KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates, refocus_checked ? 61000 : 21000);
0127 
0128     // check if meridian flip runs and completes successfully
0129     QVERIFY(checkMFExecuted(15));
0130 
0131     // Now check if everything continues as it should be
0132     QVERIFY(checkPostMFBehavior());
0133 }
0134 
0135 
0136 void TestEkosMeridianFlip::testCaptureMFAbortWaiting()
0137 {
0138     // set up the capture sequence
0139     QVERIFY(prepareCaptureTestcase(10, false, false));
0140 
0141     // start capturing
0142     QVERIFY(startCapturing());
0143 
0144     // Let capture run a little bit
0145     QTest::qWait(5000);
0146 
0147     // stop capturing
0148     m_CaptureHelper->expectedCaptureStates.enqueue(Ekos::CAPTURE_ABORTED);
0149     KTRY_CLICK(Ekos::Manager::Instance()->captureModule(), startB);
0150     KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates, 2000);
0151 
0152     // check if meridian flip runs and completes successfully
0153     QVERIFY(checkMFExecuted(18));
0154 
0155     // wait for settling
0156     QTest::qWait(2000);
0157 
0158     // check if capturing remains aborted
0159     QVERIFY(m_CaptureHelper->getCaptureStatus() == Ekos::CAPTURE_IDLE);
0160 }
0161 
0162 
0163 void TestEkosMeridianFlip::testCaptureMFAbortFlipping()
0164 {
0165     // set up the capture sequence
0166     QVERIFY(prepareCaptureTestcase(10, false, false));
0167 
0168     // start capturing
0169     QVERIFY(startCapturing());
0170 
0171     // check if the meridian flip starts running
0172     KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedMeridianFlipStates, 22000);
0173 
0174     // Let capture run a little bit
0175     QTest::qWait(2000);
0176 
0177     // stop capturing
0178     m_CaptureHelper->expectedCaptureStates.enqueue(Ekos::CAPTURE_ABORTED);
0179     KTRY_CLICK(Ekos::Manager::Instance()->captureModule(), startB);
0180     KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates, 2000);
0181 
0182     // check if the meridian flip is completed latest after one minute
0183     m_CaptureHelper->expectedMeridianFlipStates.enqueue(Ekos::MeridianFlipState::MOUNT_FLIP_COMPLETED);
0184     KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedMeridianFlipStates, 60000);
0185 
0186     // wait for settling
0187     QTest::qWait(2000);
0188 
0189     // check if capturing remains aborted
0190     QVERIFY(m_CaptureHelper->getCaptureStatus() == Ekos::CAPTURE_IDLE);
0191 }
0192 
0193 
0194 void TestEkosMeridianFlip::testCaptureGuidingMF()
0195 {
0196     // set up the capture sequence
0197     QVERIFY(prepareCaptureTestcase(20, false, false));
0198 
0199     // start guiding
0200     QVERIFY(m_CaptureHelper->startGuiding(2.0));
0201 
0202     // start capturing
0203     QVERIFY(startCapturing());
0204 
0205     // check if single capture completes correctly
0206     m_CaptureHelper->expectedCaptureStates.enqueue(Ekos::CAPTURE_IMAGE_RECEIVED);
0207     KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates, 21000);
0208 
0209     // check if meridian flip runs and completes successfully
0210     QVERIFY(checkMFExecuted(45));
0211 
0212     // Now check if everything continues as it should be
0213     QVERIFY(checkPostMFBehavior());
0214 }
0215 
0216 
0217 void TestEkosMeridianFlip::testCaptureAlignMF()
0218 {
0219     if (!astrometry_available)
0220         QSKIP("No astrometry files available to run test");
0221 
0222     // set up the capture sequence
0223     QVERIFY(prepareCaptureTestcase(40, false, false));
0224 
0225     // start alignment
0226     QVERIFY(executeAlignment(5.0));
0227 
0228     // start capturing
0229     QVERIFY(startCapturing());
0230 
0231     // check if single capture completes correctly
0232     m_CaptureHelper->expectedCaptureStates.enqueue(Ekos::CAPTURE_IMAGE_RECEIVED);
0233     KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates, 21000);
0234 
0235     // check if meridian flip runs and completes successfully
0236     QVERIFY(checkMFExecuted(39));
0237 
0238     // Now check if everything continues as it should be
0239     m_CaptureHelper->expectedCaptureStates.enqueue(Ekos::CAPTURE_CAPTURING);
0240     QVERIFY(checkPostMFBehavior());
0241 
0242     // check if capturing has started
0243     KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates, 20000);
0244 }
0245 
0246 
0247 void TestEkosMeridianFlip::testCaptureAlignGuidingMF()
0248 {
0249     if (!astrometry_available)
0250         QSKIP("No astrometry files available to run test");
0251 
0252     // set up the capture sequence
0253     QVERIFY(prepareCaptureTestcase(40, false, false));
0254 
0255     // execute alignment
0256     QVERIFY(executeAlignment(5.0));
0257 
0258     // start guiding
0259     QVERIFY(m_CaptureHelper->startGuiding(2.0));
0260 
0261     // start capturing
0262     QVERIFY(startCapturing());
0263 
0264     // check if single capture completes correctly
0265     m_CaptureHelper->expectedCaptureStates.enqueue(Ekos::CAPTURE_IMAGE_RECEIVED);
0266     KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates, 21000);
0267 
0268     // check if meridian flip runs and completes successfully
0269     QVERIFY(checkMFExecuted(60));
0270 
0271     // Now check if everything continues as it should be
0272     QVERIFY(checkPostMFBehavior());
0273 }
0274 
0275 void TestEkosMeridianFlip::testRefocusAfterMF()
0276 {
0277     // set up the capture sequence
0278     QVERIFY(prepareCaptureTestcase(15, false, false));
0279 
0280     // start guiding if configured
0281     QFETCH(bool, guide);
0282     if (guide)
0283         QVERIFY(m_CaptureHelper->startGuiding(2.0));
0284 
0285     // start capturing
0286     QVERIFY(startCapturing());
0287 
0288     // check if single capture completes correctly
0289     m_CaptureHelper->expectedCaptureStates.enqueue(Ekos::CAPTURE_IMAGE_RECEIVED);
0290     KVERIFY_EMPTY_QUEUE_WITH_TIMEOUT(m_CaptureHelper->expectedCaptureStates, 21000);
0291 
0292     // check if meridian flip runs and completes successfully
0293     QVERIFY(checkMFExecuted(45));
0294 
0295     // Now check if everything continues as it should be
0296     QVERIFY(checkPostMFBehavior());
0297 }
0298 
0299 
0300 
0301 /* *********************************************************************************
0302  *
0303  * Test data
0304  *
0305  * ********************************************************************************* */
0306 
0307 void TestEkosMeridianFlip::testSimpleMF_data()
0308 {
0309     prepareTestData(18.0, {"Greenwich", "Reykjavik", "San Diego", "Hilo", "Hong Kong", "Kuwait City"}, {true, false}, {{"Luminance", 6}}, {0}, {false}, {false});
0310 }
0311 
0312 void TestEkosMeridianFlip::testSimpleMFDelay_data()
0313 {
0314     testSimpleMF_data();
0315 }
0316 
0317 void TestEkosMeridianFlip::testGuidingMF_data()
0318 {
0319     prepareTestData(18.0, {"Greenwich"}, {true}, {{"Luminance", 6}}, {false}, {true}, {false});
0320 }
0321 
0322 void TestEkosMeridianFlip::testCaptureMF_data()
0323 {
0324     prepareTestData(18.0, {"Greenwich"}, {true}, {{"Luminance", 6}, {"Red,Green,Blue,Red,Green,Blue", 1}}, {0}, {false}, {false});
0325 }
0326 
0327 void TestEkosMeridianFlip::testCaptureMFAbortWaiting_data()
0328 {
0329     // no tests for focusing and dithering
0330     prepareTestData(18.0, {"Greenwich"}, {true}, {{"Luminance", 6}, {"Red,Green,Blue,Red,Green,Blue", 1}}, {0}, {false}, {false});
0331 }
0332 
0333 void TestEkosMeridianFlip::testCaptureMFAbortFlipping_data()
0334 {
0335     testCaptureMFAbortWaiting_data();
0336 }
0337 
0338 void TestEkosMeridianFlip::testCaptureGuidingMF_data()
0339 {
0340     prepareTestData(18.0, {"Greenwich"}, {true}, {{"Luminance", 6}, {"Red,Green,Blue,Red,Green,Blue", 1}}, {0}, {true}, {false, true});
0341 }
0342 
0343 void TestEkosMeridianFlip::testCaptureAlignMF_data()
0344 {
0345     testCaptureMF_data();
0346 }
0347 
0348 void TestEkosMeridianFlip::testCaptureAlignGuidingMF_data()
0349 {
0350     testCaptureGuidingMF_data();
0351 }
0352 
0353 void TestEkosMeridianFlip::testRefocusAfterMF_data()
0354 {
0355     prepareTestData(18.0, {"Greenwich"}, {true}, {{"Luminance", 6}}, {3}, {false}, {false});
0356 }
0357 
0358 QTEST_KSTARS_WITH_GUIDER_MAIN(TestEkosMeridianFlip)
0359 
0360 #endif // HAVE_INDI