File indexing completed on 2024-04-21 14:47:23
0001 /* KStars UI tests 0002 SPDX-FileCopyrightText: 2020 Eric Dejouhanet <eric.dejouhanet@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 0008 #include "test_ekos_focus.h" 0009 0010 #if defined(HAVE_INDI) 0011 0012 #include "kstars_ui_tests.h" 0013 #include "test_ekos.h" 0014 #include "test_ekos_simulator.h" 0015 #include "test_ekos_mount.h" 0016 #include "Options.h" 0017 0018 class KFocusProcedureSteps: public QObject 0019 { 0020 public: 0021 QMetaObject::Connection starting; 0022 QMetaObject::Connection aborting; 0023 QMetaObject::Connection completing; 0024 QMetaObject::Connection notguiding; 0025 QMetaObject::Connection guiding; 0026 QMetaObject::Connection quantifying; 0027 0028 public: 0029 bool started { false }; 0030 bool aborted { false }; 0031 bool complete { false }; 0032 bool unguided { false }; 0033 double hfr { -2 }; 0034 0035 public: 0036 KFocusProcedureSteps(): 0037 starting (connect(Ekos::Manager::Instance()->focusModule(), &Ekos::Focus::autofocusStarting, this, [ & ]() 0038 { 0039 started = true; 0040 }, Qt::UniqueConnection)), 0041 aborting (connect(Ekos::Manager::Instance()->focusModule(), &Ekos::Focus::autofocusAborted, this, [&]() 0042 { 0043 started = false; 0044 aborted = true; 0045 }, Qt::UniqueConnection)), 0046 completing (connect(Ekos::Manager::Instance()->focusModule(), &Ekos::Focus::autofocusComplete, this, [&]() 0047 { 0048 started = false; 0049 complete = true; 0050 }, Qt::UniqueConnection)), 0051 notguiding (connect(Ekos::Manager::Instance()->focusModule(), &Ekos::Focus::suspendGuiding, this, [&]() 0052 { 0053 unguided = true; 0054 }, Qt::UniqueConnection)), 0055 guiding (connect(Ekos::Manager::Instance()->focusModule(), &Ekos::Focus::resumeGuiding, this, [&]() 0056 { 0057 unguided = false; 0058 }, Qt::UniqueConnection)), 0059 quantifying (connect(Ekos::Manager::Instance()->focusModule(), &Ekos::Focus::newHFR, this, [&](double _hfr) 0060 { 0061 hfr = _hfr; 0062 }, Qt::UniqueConnection)) 0063 {}; 0064 virtual ~KFocusProcedureSteps() 0065 { 0066 disconnect(starting); 0067 disconnect(aborting); 0068 disconnect(completing); 0069 disconnect(notguiding); 0070 disconnect(guiding); 0071 disconnect(quantifying); 0072 }; 0073 }; 0074 0075 class KFocusStateList: public QObject, public QList <Ekos::FocusState> 0076 { 0077 public: 0078 QMetaObject::Connection handler; 0079 0080 public: 0081 KFocusStateList(): 0082 handler (connect(Ekos::Manager::Instance()->focusModule(), &Ekos::Focus::newStatus, this, [ & ](Ekos::FocusState s) 0083 { 0084 append(s); 0085 }, Qt::UniqueConnection)) 0086 {}; 0087 virtual ~KFocusStateList() {}; 0088 }; 0089 0090 TestEkosFocus::TestEkosFocus(QObject *parent) : QObject(parent) 0091 { 0092 } 0093 0094 void TestEkosFocus::initTestCase() 0095 { 0096 KVERIFY_EKOS_IS_HIDDEN(); 0097 KTRY_OPEN_EKOS(); 0098 KVERIFY_EKOS_IS_OPENED(); 0099 KTRY_EKOS_START_SIMULATORS(); 0100 0101 // We can't use this here because of the meridian flip test 0102 // HACK: Reset clock to initial conditions 0103 // KHACK_RESET_EKOS_TIME(); 0104 0105 KTELL_BEGIN(); 0106 } 0107 0108 void TestEkosFocus::cleanupTestCase() 0109 { 0110 KTELL_END(); 0111 KTRY_EKOS_STOP_SIMULATORS(); 0112 KTRY_CLOSE_EKOS(); 0113 KVERIFY_EKOS_IS_HIDDEN(); 0114 } 0115 0116 void TestEkosFocus::init() 0117 { 0118 } 0119 0120 void TestEkosFocus::cleanup() 0121 { 0122 if (Ekos::Manager::Instance()) 0123 if (Ekos::Manager::Instance()->focusModule()) 0124 Ekos::Manager::Instance()->focusModule()->abort(); 0125 KTELL_HIDE(); 0126 } 0127 0128 void TestEkosFocus::testCaptureStates() 0129 { 0130 KTELL("Sync high on meridian to avoid jitter in CCD Simulator."); 0131 KTRY_MOUNT_SYNC(60.0, true, -1); 0132 0133 // Prepare to detect state change 0134 KFocusStateList state_list; 0135 QVERIFY(state_list.handler); 0136 0137 KTELL("Configure fields.\nCapture a frame.\nExpect PROGRESS, IDLE."); 0138 KTRY_FOCUS_MOVETO(40000); 0139 KTRY_FOCUS_CONFIGURE("SEP", "Iterative", 0.0, 100.0, 3.0); 0140 KTRY_FOCUS_DETECT(2, 1, 99); 0141 QTRY_COMPARE_WITH_TIMEOUT(state_list.count(), 2, 5000); 0142 QCOMPARE(state_list[0], Ekos::FocusState::FOCUS_PROGRESS); 0143 QCOMPARE(state_list[1], Ekos::FocusState::FOCUS_IDLE); 0144 state_list.clear(); 0145 0146 KTELL("Move focuser.\nExpect no capture triggered."); 0147 KTRY_FOCUS_CONFIGURE("SEP", "Iterative", 0.0, 100.0, 3.0); 0148 KTRY_FOCUS_MOVETO(43210); 0149 QTest::qWait(1000); 0150 QCOMPARE(state_list.count(), 0); 0151 0152 KTRY_FOCUS_GADGET(QPushButton, startLoopB); 0153 KTRY_FOCUS_GADGET(QPushButton, stopFocusB); 0154 0155 KTELL("Loop captures.\nAbort loop.\nExpect FRAMING, PROGRESS, ABORTED, ABORTED."); 0156 KTRY_FOCUS_CONFIGURE("SEP", "Iterative", 0.0, 100.0, 3.0); 0157 KTRY_FOCUS_CLICK(startLoopB); 0158 QTRY_VERIFY_WITH_TIMEOUT(state_list.count() >= 1, 5000); 0159 KTRY_FOCUS_CLICK(stopFocusB); 0160 QTRY_VERIFY_WITH_TIMEOUT(state_list.count() >= 4, 5000); 0161 QCOMPARE((int)state_list[0], (int)Ekos::FocusState::FOCUS_FRAMING); 0162 QCOMPARE((int)state_list[1], (int)Ekos::FocusState::FOCUS_PROGRESS); 0163 QCOMPARE((int)state_list[2], (int)Ekos::FocusState::FOCUS_ABORTED); 0164 QCOMPARE((int)state_list[3], (int)Ekos::FocusState::FOCUS_ABORTED); 0165 state_list.clear(); 0166 0167 KTRY_FOCUS_GADGET(QCheckBox, useAutoStar); 0168 KTRY_FOCUS_GADGET(QPushButton, resetFrameB); 0169 0170 QWARN("This test does not wait for the hardcoded timeout to select a star."); 0171 0172 KTELL("Use a successful automatic star selection (not full-field).\nCapture a frame.\nExpect PROGRESS, IDLE\nCheck star selection."); 0173 KTRY_FOCUS_CONFIGURE("SEP", "Iterative", 0.0, 0.0, 3.0); 0174 useAutoStar->setCheckState(Qt::CheckState::Checked); 0175 KTRY_FOCUS_DETECT(2, 1, 99); 0176 QTRY_VERIFY_WITH_TIMEOUT(state_list.count() >= 2, 5000); 0177 QTRY_VERIFY_WITH_TIMEOUT(!stopFocusB->isEnabled(), 1000); 0178 KTRY_FOCUS_CLICK(resetFrameB); 0179 QCOMPARE(state_list[0], Ekos::FocusState::FOCUS_PROGRESS); 0180 QCOMPARE(state_list[1], Ekos::FocusState::FOCUS_IDLE); 0181 useAutoStar->setCheckState(Qt::CheckState::Unchecked); 0182 state_list.clear(); 0183 0184 KTELL("Use an unsuccessful automatic star selection (not full-field).\nCapture a frame\nExpect PROGRESS, WAITING.\nCheck star selection."); 0185 KTRY_FOCUS_CONFIGURE("SEP", "Iterative", 0.0, 0.0, 3.0); 0186 useAutoStar->setCheckState(Qt::CheckState::Checked); 0187 KTRY_FOCUS_DETECT(0.01, 1, 1); 0188 QTRY_VERIFY_WITH_TIMEOUT(state_list.count() >= 2, 5000); 0189 QTRY_VERIFY_WITH_TIMEOUT(!stopFocusB->isEnabled(), 1000); 0190 KTRY_FOCUS_CLICK(resetFrameB); 0191 QCOMPARE(state_list[0], Ekos::FocusState::FOCUS_PROGRESS); 0192 QCOMPARE(state_list[1], Ekos::FocusState::FOCUS_WAITING); 0193 useAutoStar->setCheckState(Qt::CheckState::Unchecked); 0194 state_list.clear(); 0195 } 0196 0197 void TestEkosFocus::testDuplicateFocusRequest() 0198 { 0199 KTELL("Sync high on meridian to avoid jitter in CCD Simulator.\nConfigure a fast autofocus."); 0200 KTRY_FOCUS_SHOW(); 0201 KTRY_MOUNT_SYNC(60.0, true, -1); 0202 KTRY_FOCUS_MOVETO(35000); 0203 KTRY_FOCUS_CONFIGURE("SEP", "Iterative", 0.0, 0.0, 30); 0204 KTRY_FOCUS_EXPOSURE(3, 99); 0205 0206 KTRY_FOCUS_GADGET(QPushButton, startFocusB); 0207 KTRY_FOCUS_GADGET(QPushButton, stopFocusB); 0208 QTRY_VERIFY_WITH_TIMEOUT(startFocusB->isEnabled(), 1000); 0209 QTRY_VERIFY_WITH_TIMEOUT(!stopFocusB->isEnabled(), 1000); 0210 0211 // Prepare to detect the beginning of the autofocus_procedure 0212 KFocusProcedureSteps autofocus; 0213 QVERIFY(autofocus.starting); 0214 0215 KTELL("Click the autofocus button\nExpect a signal that the procedure starts.\nExpect state change and disabled button."); 0216 KTRY_FOCUS_CLICK(startFocusB); 0217 QTRY_VERIFY_WITH_TIMEOUT(autofocus.started, 500); 0218 QVERIFY(Ekos::Manager::Instance()->focusModule()->status() != Ekos::FOCUS_IDLE); 0219 QVERIFY(!startFocusB->isEnabled()); 0220 QVERIFY(stopFocusB->isEnabled()); 0221 0222 KTELL("Issue a few autofocus commands at that point through the d-bus entry point\nExpect no parallel procedure start."); 0223 for (int i = 0; i < 5; i++) 0224 { 0225 autofocus.started = false; 0226 Ekos::Manager::Instance()->focusModule()->start(); 0227 QTest::qWait(500); 0228 QVERIFY(!autofocus.started); 0229 } 0230 0231 KTELL("Stop the running autofocus."); 0232 KTRY_FOCUS_CLICK(stopFocusB); 0233 QTRY_VERIFY_WITH_TIMEOUT(autofocus.aborted, 5000); 0234 } 0235 0236 void TestEkosFocus::testAutofocusSignalEmission() 0237 { 0238 KTELL("Sync high on meridian to avoid jitter in CCD Simulator.\nConfigure fast autofocus."); 0239 KTRY_FOCUS_SHOW(); 0240 KTRY_MOUNT_SYNC(60.0, true, -1); 0241 0242 KTRY_FOCUS_MOVETO(35000); 0243 KTRY_FOCUS_CONFIGURE("SEP", "Iterative", 0.0, 100.0, 30); 0244 KTRY_FOCUS_EXPOSURE(3, 99); 0245 0246 KTRY_FOCUS_GADGET(QPushButton, startFocusB); 0247 KTRY_FOCUS_GADGET(QPushButton, stopFocusB); 0248 QTRY_VERIFY_WITH_TIMEOUT(startFocusB->isEnabled(), 1000); 0249 QTRY_VERIFY_WITH_TIMEOUT(!stopFocusB->isEnabled(), 1000); 0250 0251 // Prepare to detect the beginning of the autofocus_procedure 0252 KFocusProcedureSteps autofocus; 0253 QVERIFY(autofocus.starting); 0254 0255 KTELL("Configure to restart autofocus when it finishes, like Scheduler does."); 0256 volatile bool ran_once = false; 0257 autofocus.completing = connect(Ekos::Manager::Instance()->focusModule(), &Ekos::Focus::autofocusComplete, &autofocus, [&]() 0258 { 0259 autofocus.complete = true; 0260 autofocus.started = false; 0261 if (!ran_once) 0262 { 0263 Ekos::Manager::Instance()->focusModule()->start(); 0264 ran_once = true; 0265 } 0266 }, Qt::UniqueConnection); 0267 QVERIFY(autofocus.completing); 0268 0269 KTELL("Run autofocus, wait for completion.\nHandler restarts a second one immediately."); 0270 QVERIFY(!autofocus.started); 0271 QVERIFY(!autofocus.complete); 0272 KTRY_FOCUS_CLICK(startFocusB); 0273 QTRY_VERIFY_WITH_TIMEOUT(autofocus.started, 500); 0274 QTRY_VERIFY_WITH_TIMEOUT(autofocus.complete, 30000); 0275 0276 KTELL("Wait for the second run to finish.\nNo other autofocus started."); 0277 autofocus.complete = false; 0278 QTRY_VERIFY_WITH_TIMEOUT(autofocus.complete, 30000); 0279 QVERIFY(!autofocus.started); 0280 } 0281 0282 void TestEkosFocus::testFocusAbort() 0283 { 0284 KTELL("Sync high on meridian to avoid jitter in CCD Simulator.\nConfigure fast autofocus."); 0285 KTRY_FOCUS_SHOW(); 0286 KTRY_MOUNT_SYNC(60.0, true, -1); 0287 KTRY_FOCUS_MOVETO(35000); 0288 KTRY_FOCUS_CONFIGURE("SEP", "Iterative", 0.0, 100.0, 30); 0289 KTRY_FOCUS_EXPOSURE(3, 99); 0290 0291 KTRY_FOCUS_GADGET(QPushButton, startFocusB); 0292 KTRY_FOCUS_GADGET(QPushButton, stopFocusB); 0293 QTRY_VERIFY_WITH_TIMEOUT(startFocusB->isEnabled(), 1000); 0294 QTRY_VERIFY_WITH_TIMEOUT(!stopFocusB->isEnabled(), 1000); 0295 0296 // Prepare to detect the beginning of the autofocus_procedure 0297 KFocusProcedureSteps autofocus; 0298 QVERIFY(autofocus.starting); 0299 QVERIFY(autofocus.completing); 0300 0301 KTELL("Configure to restart autofocus when it finishes, like Scheduler does."); 0302 volatile bool ran_once = false; 0303 autofocus.aborting = connect(Ekos::Manager::Instance()->focusModule(), &Ekos::Focus::autofocusAborted, this, [&]() 0304 { 0305 autofocus.aborted = true; 0306 autofocus.started = false; 0307 if (!ran_once) 0308 { 0309 Ekos::Manager::Instance()->focusModule()->start(); 0310 ran_once = true; 0311 } 0312 }, Qt::UniqueConnection); 0313 QVERIFY(autofocus.aborting); 0314 0315 KTELL("Run autofocus, don't wait for the completion signal and abort it.\nHandler restarts a second one immediately."); 0316 QVERIFY(!autofocus.started); 0317 QVERIFY(!autofocus.aborted); 0318 QVERIFY(!autofocus.complete); 0319 KTRY_FOCUS_CLICK(startFocusB); 0320 QTRY_VERIFY_WITH_TIMEOUT(autofocus.started, 500); 0321 KTRY_FOCUS_CLICK(stopFocusB); 0322 QTRY_VERIFY_WITH_TIMEOUT(autofocus.aborted, 1000); 0323 0324 KTELL("Wait for the second run to finish.\nNo other autofocus started."); 0325 QTRY_VERIFY_WITH_TIMEOUT(autofocus.started, 500); 0326 QTRY_VERIFY_WITH_TIMEOUT(autofocus.complete, 30000); 0327 QVERIFY(!autofocus.started); 0328 } 0329 0330 void TestEkosFocus::testGuidingSuspendWhileFocusing() 0331 { 0332 KTELL("Sync high on meridian to avoid jitter in CCD Simulator\nConfigure a fast autofocus."); 0333 KTRY_FOCUS_SHOW(); 0334 KTRY_MOUNT_SYNC(60.0, true, -1); 0335 KTRY_FOCUS_MOVETO(35000); 0336 KTRY_FOCUS_CONFIGURE("SEP", "Iterative", 0.0, 100.0, 30); 0337 KTRY_FOCUS_EXPOSURE(3, 99); 0338 0339 KTRY_FOCUS_GADGET(QPushButton, startFocusB); 0340 KTRY_FOCUS_GADGET(QPushButton, stopFocusB); 0341 QTRY_VERIFY_WITH_TIMEOUT(startFocusB->isEnabled(), 1000); 0342 QTRY_VERIFY_WITH_TIMEOUT(!stopFocusB->isEnabled(), 1000); 0343 0344 // Prepare to detect the beginning of the autofocus_procedure 0345 KFocusProcedureSteps autofocus; 0346 QVERIFY(autofocus.starting); 0347 QVERIFY(autofocus.aborting); 0348 QVERIFY(autofocus.completing); 0349 QVERIFY(autofocus.notguiding); 0350 QVERIFY(autofocus.guiding); 0351 0352 KTRY_FOCUS_GADGET(QCheckBox, suspendGuideCheck); 0353 0354 KTELL("Abort the autofocus with guiding set to suspend\nGuiding required to suspend, then required to resume"); 0355 suspendGuideCheck->setCheckState(Qt::CheckState::Checked); 0356 QVERIFY(!autofocus.started); 0357 QVERIFY(!autofocus.aborted); 0358 QVERIFY(!autofocus.complete); 0359 QVERIFY(!autofocus.unguided); 0360 KTRY_FOCUS_CLICK(startFocusB); 0361 QTRY_VERIFY_WITH_TIMEOUT(autofocus.started, 500); 0362 QVERIFY(autofocus.unguided); 0363 Ekos::Manager::Instance()->focusModule()->abort(); 0364 QTRY_VERIFY_WITH_TIMEOUT(autofocus.aborted, 5000); 0365 QVERIFY(!autofocus.unguided); 0366 0367 KTELL("Run the autofocus to completion with guiding set to suspend\nGuiding required to suspend, then required to resume\nNo other autofocus started."); 0368 autofocus.started = autofocus.aborted = false; 0369 KTRY_FOCUS_CLICK(startFocusB); 0370 QTRY_VERIFY_WITH_TIMEOUT(autofocus.started, 500); 0371 QVERIFY(autofocus.unguided); 0372 QTRY_VERIFY_WITH_TIMEOUT(autofocus.complete, 30000); 0373 QVERIFY(!autofocus.unguided); 0374 QVERIFY(!autofocus.started); 0375 0376 KTELL("Abort the autofocus with guiding set to continue\nNo guiding signal emitted"); 0377 suspendGuideCheck->setCheckState(Qt::CheckState::Unchecked); 0378 autofocus.started = autofocus.aborted = autofocus.complete = autofocus.unguided = false; 0379 KTRY_FOCUS_CLICK(startFocusB); 0380 QTRY_VERIFY_WITH_TIMEOUT(autofocus.started, 500); 0381 QVERIFY(!autofocus.unguided); 0382 Ekos::Manager::Instance()->focusModule()->abort(); 0383 QTRY_VERIFY_WITH_TIMEOUT(autofocus.aborted, 5000); 0384 QVERIFY(!autofocus.unguided); 0385 0386 KTELL("Run the autofocus to completion with guiding set to continue\nNo guiding signal emitted\nNo other autofocus started."); 0387 autofocus.started = autofocus.aborted = false; 0388 KTRY_FOCUS_CLICK(startFocusB); 0389 QTRY_VERIFY_WITH_TIMEOUT(autofocus.started, 500); 0390 QVERIFY(!autofocus.unguided); 0391 QTRY_VERIFY_WITH_TIMEOUT(autofocus.complete, 30000); 0392 QVERIFY(!autofocus.unguided); 0393 QVERIFY(!autofocus.started); 0394 } 0395 0396 void TestEkosFocus::testFocusWhenMountFlips() 0397 { 0398 KTELL("Sync high on meridian to avoid jitter in CCD Simulator.\nConfigure a fast autofocus."); 0399 KTRY_FOCUS_SHOW(); 0400 KTRY_MOUNT_SYNC(60.0, true, +10.0 / 3600); 0401 KTRY_FOCUS_MOVETO(35000); 0402 KTRY_FOCUS_CONFIGURE("SEP", "Iterative", 0.0, 100.0, 5); 0403 KTRY_FOCUS_EXPOSURE(3, 99); 0404 0405 KTRY_FOCUS_GADGET(QPushButton, startFocusB); 0406 KTRY_FOCUS_GADGET(QPushButton, stopFocusB); 0407 QTRY_VERIFY_WITH_TIMEOUT(startFocusB->isEnabled(), 1000); 0408 QTRY_VERIFY_WITH_TIMEOUT(!stopFocusB->isEnabled(), 1000); 0409 0410 // Prepare to detect the states of the autofocus_procedure 0411 KFocusProcedureSteps autofocus; 0412 QVERIFY(autofocus.starting); 0413 QVERIFY(autofocus.aborting); 0414 QVERIFY(autofocus.completing); 0415 0416 KTELL("Ensure flip is enabled on meridian.\n.Start a standard autofocus."); 0417 Ekos::Manager::Instance()->mountModule()->setMeridianFlipValues(true, 0); 0418 QTRY_VERIFY_WITH_TIMEOUT(Ekos::Manager::Instance()->mountModule()->meridianFlipEnabled(), 1000); 0419 QTRY_VERIFY_WITH_TIMEOUT(Ekos::Manager::Instance()->mountModule()->meridianFlipValue() == 0, 1000); 0420 QVERIFY(!autofocus.started); 0421 QVERIFY(!autofocus.aborted); 0422 QVERIFY(!autofocus.complete); 0423 KTRY_FOCUS_CLICK(startFocusB); 0424 QTRY_VERIFY_WITH_TIMEOUT(autofocus.started, 5000); 0425 0426 KTELL("Wait for the meridian flip to occur.\nCheck procedure aborts while flipping."); 0427 QTRY_VERIFY_WITH_TIMEOUT(Ekos::Manager::Instance()->mountModule()->status() == ISD::Mount::MOUNT_SLEWING, 15000); 0428 QTRY_VERIFY_WITH_TIMEOUT(autofocus.aborted, 5000); 0429 0430 KTELL("Wait for the flip to end."); 0431 QTRY_VERIFY_WITH_TIMEOUT(Ekos::Manager::Instance()->mountModule()->status() == ISD::Mount::MOUNT_TRACKING, 120000); 0432 0433 KTELL("Start the procedure again.\nExpect the procedure to succeed."); 0434 autofocus.started = false; 0435 autofocus.aborted = false; 0436 autofocus.complete = false; 0437 KTRY_FOCUS_CLICK(startFocusB); 0438 QTRY_VERIFY_WITH_TIMEOUT(autofocus.complete, 60000); 0439 } 0440 0441 void TestEkosFocus::testFocusWhenHFRChecking() 0442 { 0443 KTELL("Sync high on meridian to avoid jitter in CCD Simulator.\nConfigure a fast autofocus."); 0444 KTRY_FOCUS_SHOW(); 0445 KTRY_MOUNT_SYNC(60.0, true, -1); 0446 int initialFocusPosition = 35000; 0447 KTRY_FOCUS_MOVETO(initialFocusPosition); 0448 KTRY_FOCUS_CONFIGURE("SEP", "Iterative", 0.0, 100.0, 50); 0449 KTRY_FOCUS_EXPOSURE(3, 99); 0450 0451 KTRY_FOCUS_GADGET(QPushButton, startFocusB); 0452 KTRY_FOCUS_GADGET(QPushButton, stopFocusB); 0453 QTRY_VERIFY_WITH_TIMEOUT(startFocusB->isEnabled(), 1000); 0454 QTRY_VERIFY_WITH_TIMEOUT(!stopFocusB->isEnabled(), 1000); 0455 0456 // Prepare to detect the beginning of the autofocus_procedure 0457 KFocusProcedureSteps autofocus; 0458 QVERIFY(autofocus.starting); 0459 QVERIFY(autofocus.aborting); 0460 QVERIFY(autofocus.completing); 0461 0462 KTELL("Run a standard autofocus.\nRun a HFR check.\nExpect no effect on the procedure."); 0463 QVERIFY(!autofocus.started); 0464 QVERIFY(!autofocus.aborted); 0465 QVERIFY(!autofocus.complete); 0466 KTRY_FOCUS_CLICK(startFocusB); 0467 QTRY_VERIFY_WITH_TIMEOUT(autofocus.started, 10000); 0468 0469 KTELL("Wait a little, run a first HFR check while the procedure runs."); 0470 QTest::qWait(3000); 0471 Ekos::Manager::Instance()->focusModule()->checkFocus(0.1); 0472 0473 KTELL("Expect procedure to succeed nonetheless."); 0474 QTRY_VERIFY_WITH_TIMEOUT(autofocus.complete, 60000); 0475 0476 KTELL("Run a second HFR check that would start an autofocus."); 0477 autofocus.complete = false; 0478 Ekos::Manager::Instance()->focusModule()->checkFocus(0.1); 0479 0480 KTELL("Expect procedure to start properly.\nAbort the procedure manually.\nRun a third HFR check."); 0481 QTRY_VERIFY_WITH_TIMEOUT(autofocus.started, 10000); 0482 KTRY_FOCUS_CLICK(stopFocusB); 0483 QTRY_VERIFY_WITH_TIMEOUT(autofocus.aborted, 10000); 0484 0485 KTELL("Expect autofocus to start properly.\nChange settings so that the procedure fails now.\nExpect a failure."); 0486 autofocus.aborted = autofocus.complete = false; 0487 Ekos::Manager::Instance()->focusModule()->checkFocus(0.1); 0488 QTRY_VERIFY_WITH_TIMEOUT(autofocus.started, 10000); 0489 KTRY_FOCUS_CONFIGURE("SEP", "Iterative", 0.0, 0.1, 0.1); 0490 KTRY_FOCUS_EXPOSURE(0.1, 1); 0491 QTRY_VERIFY_WITH_TIMEOUT(autofocus.aborted, 90000); 0492 KTRY_FOCUS_CHECK_POSITION_WITH_TIMEOUT(initialFocusPosition, 5000); 0493 0494 KTELL("Run a fourth HFR check.\nExpect autofocus to complete."); 0495 KTRY_FOCUS_CONFIGURE("SEP", "Iterative", 0.0, 100.0, 50); 0496 KTRY_FOCUS_EXPOSURE(3, 99); 0497 autofocus.aborted = autofocus.complete = false; 0498 Ekos::Manager::Instance()->focusModule()->checkFocus(0.1); 0499 QTRY_VERIFY_WITH_TIMEOUT(autofocus.started, 10000); 0500 QTRY_VERIFY_WITH_TIMEOUT(autofocus.complete, 60000); 0501 } 0502 0503 void TestEkosFocus::testFocusFailure() 0504 { 0505 KTELL("Sync high on meridian to avoid jitter in CCD Simulator"); 0506 KTRY_FOCUS_SHOW(); 0507 KTRY_MOUNT_SYNC(60.0, true, -1); 0508 0509 KTELL("Configure an autofocus that cannot see any star, so that the initial setup fails."); 0510 KTRY_FOCUS_MOVETO(10000); 0511 KTRY_FOCUS_CONFIGURE("SEP", "Polynomial", 0.0, 1.0, 0.1); 0512 KTRY_FOCUS_EXPOSURE(0.01, 1); 0513 0514 KTRY_FOCUS_GADGET(QPushButton, startFocusB); 0515 KTRY_FOCUS_GADGET(QPushButton, stopFocusB); 0516 QTRY_VERIFY_WITH_TIMEOUT(startFocusB->isEnabled(), 1000); 0517 QTRY_VERIFY_WITH_TIMEOUT(!stopFocusB->isEnabled(), 1000); 0518 0519 // Prepare to detect the beginning of the autofocus_procedure 0520 KFocusProcedureSteps autofocus; 0521 QVERIFY(autofocus.starting); 0522 QVERIFY(autofocus.aborting); 0523 QVERIFY(autofocus.completing); 0524 0525 KTELL("Run the autofocus, wait for the completion signal.\nExpect no further autofocus started as we are not running a sequence."); 0526 QVERIFY(!autofocus.started); 0527 QVERIFY(!autofocus.aborted); 0528 QVERIFY(!autofocus.complete); 0529 KTRY_FOCUS_CLICK(startFocusB); 0530 QTRY_VERIFY_WITH_TIMEOUT(autofocus.started, 500); 0531 QTRY_VERIFY_WITH_TIMEOUT(autofocus.aborted, 30000); 0532 QVERIFY(!autofocus.started); 0533 0534 QSKIP("Skipping abort test for device limits, focus algorithms are too sensitive to CCD Sim noise."); 0535 0536 KTELL("Configure an autofocus that can see stars but is too far off and cannot achieve focus, so that the procedure fails."); 0537 KTRY_FOCUS_MOVETO(25000); 0538 QWARN("Iterative and Polynomial are too easily successful for this test."); 0539 KTRY_FOCUS_CONFIGURE("SEP", "Linear", 0.0, 100.0, 1.0); 0540 KTRY_FOCUS_EXPOSURE(5, 99); 0541 KTRY_FOCUS_GADGET(QDoubleSpinBox, maxTravelIN); 0542 maxTravelIN->setValue(2000); 0543 0544 QTRY_VERIFY_WITH_TIMEOUT(startFocusB->isEnabled(), 1000); 0545 QTRY_VERIFY_WITH_TIMEOUT(!stopFocusB->isEnabled(), 1000); 0546 autofocus.started = false; 0547 autofocus.aborted = false; 0548 autofocus.complete = false; 0549 0550 KTELL("Run the autofocus, wait for the completion signal.\nNo further autofocus started as we are not running a sequence."); 0551 QVERIFY(!autofocus.started); 0552 QVERIFY(!autofocus.aborted); 0553 QVERIFY(!autofocus.complete); 0554 KTRY_FOCUS_CLICK(startFocusB); 0555 QTRY_VERIFY_WITH_TIMEOUT(autofocus.started, 500); 0556 QTRY_VERIFY_WITH_TIMEOUT(autofocus.aborted, 240000); 0557 QVERIFY(!autofocus.started); 0558 } 0559 0560 void TestEkosFocus::testStarDetection_data() 0561 { 0562 #if QT_VERSION < 0x050900 0563 QSKIP("Skipping fixture-based test on old QT version."); 0564 #else 0565 QTest::addColumn<QString>("NAME"); 0566 QTest::addColumn<QString>("RA"); 0567 QTest::addColumn<QString>("DEC"); 0568 0569 // Altitude computation taken from SchedulerJob::findAltitude 0570 GeoLocation * const geo = KStarsData::Instance()->geo(); 0571 KStarsDateTime const now(KStarsData::Instance()->lt()); 0572 KSNumbers const numbers(now.djd()); 0573 CachingDms const LST = geo->GSTtoLST(geo->LTtoUT(now).gst()); 0574 0575 std::list<char const *> Objects = { "Polaris", "Mizar", "M 51", "M 13", "M 47", "Vega", "NGC 2238", "M 81" }; 0576 size_t count = 0; 0577 0578 foreach (char const *name, Objects) 0579 { 0580 SkyObject const * const so = KStars::Instance()->data()->objectNamed(name); 0581 if (so != nullptr) 0582 { 0583 SkyObject o(*so); 0584 o.updateCoordsNow(&numbers); 0585 o.EquatorialToHorizontal(&LST, geo->lat()); 0586 if (10.0 < o.alt().Degrees()) 0587 { 0588 QTest::addRow("%s", name) 0589 << name 0590 << o.ra().toHMSString() 0591 << o.dec().toDMSString(); 0592 count++; 0593 } 0594 else QWARN(QString("Fixture '%1' altitude is '%2' degrees, discarding.").arg(name).arg( 0595 so->alt().Degrees()).toStdString().c_str()); 0596 } 0597 } 0598 0599 if (!count) 0600 QSKIP("No usable fixture objects, bypassing test."); 0601 #endif 0602 } 0603 0604 void TestEkosFocus::testStarDetection() 0605 { 0606 0607 #if QT_VERSION < 0x050900 0608 QSKIP("Skipping fixture-based test on old QT version."); 0609 #else 0610 Ekos::Manager * const ekos = Ekos::Manager::Instance(); 0611 QVERIFY(ekos); 0612 0613 QFETCH(QString, NAME); 0614 QFETCH(QString, RA); 0615 QFETCH(QString, DEC); 0616 0617 KTELL(QString(NAME + "\nSync to %1/%2 to make the mount teleport to the object.").arg(qPrintable(RA)).arg(qPrintable(DEC))); 0618 QTRY_VERIFY_WITH_TIMEOUT(ekos->mountModule() != nullptr, 5000); 0619 ekos->mountModule()->setMeridianFlipValues(false, 0); 0620 QVERIFY(ekos->mountModule()->sync(RA, DEC)); 0621 ekos->mountModule()->setTrackEnabled(true); 0622 0623 KTELL(NAME + "\nWait for Focus to come up\nSwitch to Focus tab."); 0624 KTRY_FOCUS_SHOW(); 0625 0626 KTRY_FOCUS_GADGET(QPushButton, startFocusB); 0627 KTRY_FOCUS_GADGET(QPushButton, stopFocusB); 0628 QTRY_VERIFY_WITH_TIMEOUT(startFocusB->isEnabled(), 1000); 0629 QTRY_VERIFY_WITH_TIMEOUT(!stopFocusB->isEnabled(), 1000); 0630 0631 KTRY_FOCUS_GADGET(QLineEdit, starsOut); 0632 0633 KTELL(NAME + "\nMove focuser to see stars."); 0634 KTRY_FOCUS_MOVETO(35000); 0635 0636 KTELL(NAME + "\nRun the detection with SEP."); 0637 KTRY_FOCUS_CONFIGURE("SEP", "Iterative", 0.0, 100.0, 3.0); 0638 KTRY_FOCUS_DETECT(1, 3, 99); 0639 QTRY_VERIFY_WITH_TIMEOUT(starsOut->text().toInt() >= 1, 5000); 0640 0641 KTELL(NAME + "\nRun the detection with Centroid."); 0642 KTRY_FOCUS_CONFIGURE("Centroid", "Iterative", 0.0, 100.0, 3.0); 0643 KTRY_FOCUS_DETECT(1, 3, 99); 0644 QTRY_VERIFY_WITH_TIMEOUT(starsOut->text().toInt() >= 1, 5000); 0645 0646 KTELL(NAME + "\nRun the detection with Threshold (no full-field)."); 0647 KTRY_FOCUS_CONFIGURE("Threshold", "Iterative", 0.0, 0.0, 3.0); 0648 KTRY_FOCUS_DETECT(1, 3, 99); 0649 QTRY_VERIFY_WITH_TIMEOUT(starsOut->text().toInt() >= 1, 5000); 0650 0651 KTELL(NAME + "\nRun the detection with Gradient (no full-field)."); 0652 KTRY_FOCUS_CONFIGURE("Gradient", "Iterative", 0.0, 0.0, 3.0); 0653 KTRY_FOCUS_DETECT(1, 3, 99); 0654 QTRY_VERIFY_WITH_TIMEOUT(starsOut->text().toInt() >= 1, 5000); 0655 0656 KTELL(NAME + "\nRun the detection with SEP (8s capture)."); 0657 KTRY_FOCUS_CONFIGURE("SEP", "Iterative", 0.0, 100.0, 3.0); 0658 KTRY_FOCUS_DETECT(8, 1, 99); 0659 QTRY_VERIFY_WITH_TIMEOUT(starsOut->text().toInt() >= 1, 5000); 0660 0661 KTELL(NAME + "\nRun the detection with SEP\nFull-field with various values\nHFR averaged on 3 frames."); 0662 for (double inner = 0.0; inner < 100.0; inner += 43.0) 0663 { 0664 for (double outer = 100.0; inner < outer; outer -= 42.0) 0665 { 0666 KTRY_FOCUS_CONFIGURE("SEP", "Iterative", inner, outer, 3.0); 0667 KTRY_FOCUS_DETECT(1, 2, 99); 0668 } 0669 } 0670 0671 KTELL(NAME + "\nRun the detection with Threshold, full-field."); 0672 for (double threshold = 80.0; threshold < 99.0; threshold += 13.3) 0673 { 0674 KTRY_FOCUS_GADGET(QDoubleSpinBox, thresholdSpin); 0675 thresholdSpin->setValue(threshold); 0676 KTRY_FOCUS_CONFIGURE("Threshold", "Iterative", 0, 0.0, 3.0); 0677 KTRY_FOCUS_DETECT(1, 1, 99); 0678 } 0679 #endif 0680 } 0681 0682 QTEST_KSTARS_MAIN(TestEkosFocus) 0683 0684 #endif // HAVE_INDI