diff --git a/kstars/ekos/capture/capture.h b/kstars/ekos/capture/capture.h --- a/kstars/ekos/capture/capture.h +++ b/kstars/ekos/capture/capture.h @@ -458,6 +458,11 @@ //void updateAutofocusStatus(bool status, double HFR); void startPostFilterAutoFocus(); + // Timed refocus + void startRefocusEveryNTimer(); + void restartRefocusEveryNTimer(); + int getRefocusEveryNTimerElapsedSec(); + // Flat field void openCalibrationDialog(); IPState processPreCaptureCalibrationStage(); @@ -585,6 +590,11 @@ double focusHFR; // HFR value as received from the Ekos focus module double fileHFR; // HFR value as loaded from the sequence file + // Refocus every N minutes + bool isRefocus; + int refocusEveryNMinutesValue; // number of minutes between forced refocus + QElapsedTimer refocusEveryNTimer; // used to determine when next force refocus should occur + //Meridan flip double initialHA; double initialRA; diff --git a/kstars/ekos/capture/capture.cpp b/kstars/ekos/capture/capture.cpp --- a/kstars/ekos/capture/capture.cpp +++ b/kstars/ekos/capture/capture.cpp @@ -53,7 +53,7 @@ #define MAX_CAPTURE_RETRIES 3 // Current Sequence File Format: -#define SQ_FORMAT_VERSION 1.8 +#define SQ_FORMAT_VERSION 1.9 // We accept file formats with version back to: #define SQ_COMPAT_VERSION 1.6 @@ -108,6 +108,8 @@ autoFocusStatus = false; resumeAlignmentAfterFlip = false; + isRefocus = false; + mDirty = false; jobUnderEdit = false; currentFilterPosition = -1; @@ -221,11 +223,13 @@ guideDeviationCheck->setChecked(Options::enforceGuideDeviation()); guideDeviation->setValue(Options::guideDeviation()); autofocusCheck->setChecked(Options::enforceAutofocus()); + refocusEveryNCheck->setChecked(Options::enforceRefocusEveryN()); meridianCheck->setChecked(Options::autoMeridianFlip()); meridianHours->setValue(Options::autoMeridianHours()); useFITSViewerInCapture->setChecked(Options::useFITSViewerInCapture()); connect(autofocusCheck, SIGNAL(toggled(bool)), this, SLOT(setDirty())); + connect(refocusEveryNCheck, SIGNAL(toggled(bool)), this, SLOT(setDirty())); connect(HFRPixels, SIGNAL(valueChanged(double)), this, SLOT(setDirty())); connect(guideDeviationCheck, SIGNAL(toggled(bool)), this, SLOT(setDirty())); connect(guideDeviation, SIGNAL(valueChanged(double)), this, SLOT(setDirty())); @@ -357,6 +361,8 @@ Options::setGuideDeviation(guideDeviation->value()); Options::setEnforceGuideDeviation(guideDeviationCheck->isChecked()); Options::setEnforceAutofocus(autofocusCheck->isChecked()); + Options::setEnforceRefocusEveryN(refocusEveryNCheck->isChecked()); + Options::setAutoMeridianFlip(meridianCheck->isChecked()); Options::setAutoMeridianHours(meridianHours->value()); Options::setUseFITSViewerInCapture(useFITSViewerInCapture->isChecked()); @@ -422,6 +428,10 @@ initialHA = getCurrentHA(); meridianFlipStage = MF_NONE; + + // start timer to measure time until next forced refocus + startRefocusEveryNTimer(); + // Check if we need to update the sequence directory numbers before starting /*for (int i=0; i < jobs.count(); i++) { @@ -1313,6 +1323,16 @@ HFRPixels->setValue(fileHFR); } + // check if time for forced refocus + + if (Options::captureLogging()) + qDebug() << "Elapsed Time (secs): " << getRefocusEveryNTimerElapsedSec() << " Requested Interval (secs): " << refocusEveryN->value()*60; + + if (refocusEveryNCheck->isEnabled() && refocusEveryNCheck->isChecked() && getRefocusEveryNTimerElapsedSec() >= refocusEveryN->value()*60) + isRefocus = true; + else + isRefocus = false; + // If we suspended guiding due to primary chip download, resume guide chip guiding now if (guideState == GUIDE_SUSPENDED && suspendGuideOnDownload) emit resumeGuiding(); @@ -1327,6 +1347,18 @@ state = CAPTURE_DITHERING; emit newStatus(Ekos::CAPTURE_DITHERING); } + else if (isRefocus && activeJob->getFrameType() == FRAME_LIGHT) + { + appendLogText(i18n("Scheduled refocus started...")); + + secondsLabel->setText(i18n("Focusing...")); + + // force refocus + emit checkFocus(0.1); + + state = CAPTURE_FOCUSING; + emit newStatus(Ekos::CAPTURE_FOCUSING); + } else if (isAutoFocus && activeJob->getFrameType() == FRAME_LIGHT) { secondsLabel->setText(i18n("Focusing...")); @@ -1499,6 +1531,8 @@ appendLogText(i18n("Dither complete.")); + // FIXME ought to be able to combine these - only different is value passed + // to checkFocus() if (isAutoFocus && autoFocusStatus == false) { secondsLabel->setText(i18n("Focusing...")); @@ -1507,6 +1541,16 @@ emit newStatus(Ekos::CAPTURE_FOCUSING); return true; } + else if (isRefocus) + { + appendLogText(i18n("Scheduled refocus started...")); + + secondsLabel->setText(i18n("Focusing...")); + emit checkFocus(0.1); + state = CAPTURE_FOCUSING; + emit newStatus(Ekos::CAPTURE_FOCUSING); + return true; + } startNextExposure(); @@ -2059,6 +2103,15 @@ calibrationStage = CAL_NONE; } + // If we haven't performed a single autofocus yet, we stop + if (!job->isPreview() && Options::enforceRefocusEveryN() && (isAutoFocus == false && firstAutoFocus == true)) + { + appendLogText(i18n( + "Manual scheduled focusing is not supported. Run Autofocus process before trying again.")); + abort(); + return; + } + if (currentFilterPosition > 0) { // If we haven't performed a single autofocus yet, we stop @@ -2371,8 +2424,14 @@ if (focusState == FOCUS_COMPLETE) { + // enable option to have a refocus event occur if HFR goes over threshold autofocusCheck->setEnabled(true); HFRPixels->setEnabled(true); + + // also set scheduled refocus enabled + refocusEveryNCheck->setEnabled(true); + refocusEveryN->setEnabled(true); + if (focusHFR > 0 && firstAutoFocus && HFRPixels->value() == 0 && fileHFR == 0) { firstAutoFocus = false; @@ -2380,6 +2439,9 @@ // in case in-sequence-focusing is used. HFRPixels->setValue(focusHFR + (focusHFR * (Options::hFRThresholdPercentage() / 100.0))); } + + // successful focus so reset elapsed time + restartRefocusEveryNTimer(); } if (activeJob && @@ -2401,7 +2463,7 @@ return; } - if (isAutoFocus && activeJob && activeJob->getStatus() == SequenceJob::JOB_BUSY) + if ((isRefocus || isAutoFocus) && activeJob && activeJob->getStatus() == SequenceJob::JOB_BUSY) { if (focusState == FOCUS_COMPLETE) { @@ -2564,6 +2626,23 @@ else autofocusCheck->setChecked(false); } + else if (!strcmp(tagXMLEle(ep), "RefocusEveryN")) + { + if (!strcmp(findXMLAttValu(ep, "enabled"), "true")) + { + refocusEveryNCheck->setChecked(true); + int minutesValue = atof(pcdataXMLEle(ep)); + if (minutesValue > 0) + { + refocusEveryNMinutesValue = minutesValue; + refocusEveryN->setValue(refocusEveryNMinutesValue); + } + else + refocusEveryNMinutesValue = 0; + } + else + refocusEveryNCheck->setChecked(false); + } else if (!strcmp(tagXMLEle(ep), "MeridianFlip")) { if (!strcmp(findXMLAttValu(ep, "enabled"), "true")) @@ -2880,6 +2959,8 @@ << guideDeviation->value() << "" << endl; outstream << "" << HFRPixels->value() << "" << endl; + outstream << "" + << refocusEveryN->value() << "" << endl; outstream << "" << meridianHours->value() << "" << endl; foreach (SequenceJob *job, jobs) @@ -4547,4 +4628,20 @@ Options::setDefaultObserver(observerName); } + + +void Capture::startRefocusEveryNTimer() +{ + refocusEveryNTimer.restart(); +} + +void Capture::restartRefocusEveryNTimer() +{ + refocusEveryNTimer.restart(); +} + +int Capture::getRefocusEveryNTimerElapsedSec() +{ + return refocusEveryNTimer.elapsed()/1000; +} } diff --git a/kstars/ekos/capture/capture.ui b/kstars/ekos/capture/capture.ui --- a/kstars/ekos/capture/capture.ui +++ b/kstars/ekos/capture/capture.ui @@ -6,8 +6,8 @@ 0 0 - 662 - 517 + 707 + 580 @@ -970,7 +970,7 @@ 3 - + false @@ -992,7 +992,7 @@ - + false @@ -1056,32 +1056,32 @@ - - + + false - Abort sequence if guiding deviation exceed this value + Perform autofocusing once Half-Flux-Radius (HFR) value exceeds this limit - Guiding Deviation < - - - false + Autofocus if HFR > - - + + false - Perform autofocusing once Half-Flux-Radius (HFR) value exceeds this limit + Abort sequence if guiding deviation exceed this value - Autofocus if HFR > + Guiding Deviation < + + + false @@ -1098,7 +1098,7 @@ - + Number of images to capture @@ -1111,6 +1111,39 @@ + + + + false + + + Refocus every + + + + + + + false + + + 1 + + + 999 + + + 60 + + + + + + + minutes + + + diff --git a/kstars/kstars.kcfg b/kstars/kstars.kcfg --- a/kstars/kstars.kcfg +++ b/kstars/kstars.kcfg @@ -1443,6 +1443,15 @@ false + + + false + + + + Sets the time interval before forced autofocus attempts during a capture sequence. + 60 + If the target hour angle exceeds this value, Ekos will command a meridian flip and if successful it will resume guiding and capture operations.