7#include "capturemodulestate.h"
8#include "ekos/manager/meridianflipstate.h"
9#include "ekos/capture/sequencejob.h"
10#include "ekos/capture/sequencequeue.h"
11#include "fitsviewer/fitsdata.h"
13#include "ksnotification.h"
14#include <ekos_capture_debug.h>
16#define GD_TIMER_TIMEOUT 60000
20CaptureModuleState::CaptureModuleState(
QObject *parent):
QObject{parent}
22 m_sequenceQueue.reset(
new SequenceQueue());
23 m_refocusState.reset(
new RefocusState());
24 m_TargetADUTolerance = Options::calibrationADUValueTolerance();
25 connect(m_refocusState.get(), &RefocusState::newLog,
this, &CaptureModuleState::newLog);
27 getGuideDeviationTimer().setInterval(GD_TIMER_TIMEOUT);
30 setCalibrationPreAction(Options::calibrationPreActionIndex());
31 setFlatFieldDuration(
static_cast<FlatFieldDuration
>(Options::calibrationFlatDurationIndex()));
32 wallCoord().setAz(Options::calibrationWallAz());
33 wallCoord().setAlt(Options::calibrationWallAlt());
34 setTargetADU(Options::calibrationADUValue());
35 setSkyFlat(Options::calibrationSkyFlat());
40 return m_sequenceQueue->allJobs();
43const QUrl &CaptureModuleState::sequenceURL()
const
45 return m_sequenceQueue->sequenceURL();
53void CaptureModuleState::setActiveJob(
SequenceJob *value)
56 if (m_activeJob == value)
60 if (m_activeJob !=
nullptr)
62 disconnect(
this,
nullptr, m_activeJob,
nullptr);
63 disconnect(m_activeJob,
nullptr,
this,
nullptr);
65 m_activeJob->disconnectDeviceAdaptor();
72 if (m_activeJob !=
nullptr)
75 m_activeJob->connectDeviceAdaptor();
77 connect(
this, &CaptureModuleState::newGuiderDrift, m_activeJob, &SequenceJob::updateGuiderDrift);
79 connect(m_activeJob, &SequenceJob::prepareState,
this, &CaptureModuleState::updatePrepareState);
80 connect(m_activeJob, &SequenceJob::prepareComplete,
this, [
this](
bool success)
84 setCaptureState(CAPTURE_PROGRESS);
85 emit executeActiveJob();
90 setCaptureState(CAPTURE_ABORTED);
94 connect(m_activeJob, &SequenceJob::abortCapture,
this, &CaptureModuleState::abortCapture);
95 connect(m_activeJob, &SequenceJob::captureStarted,
this, &CaptureModuleState::captureStarted);
96 connect(m_activeJob, &SequenceJob::newLog,
this, &CaptureModuleState::newLog);
98 m_activeJob->updateDeviceStates();
99 m_activeJob->setAutoFocusReady(getRefocusState()->isAutoFocusReady());
104int CaptureModuleState::activeJobID()
106 if (m_activeJob ==
nullptr)
109 for (
int i = 0; i < allJobs().count(); i++)
111 if (m_activeJob == allJobs().at(i))
119void CaptureModuleState::initCapturePreparation()
121 setStartingCapture(
false);
124 setIgnoreJobProgress(!hasCapturedFramesMap() && Options::alwaysResetSequenceWhenStarting());
127 if (isGuidingDeviationDetected() ==
false && getCaptureState() != CAPTURE_SUSPENDED)
130 getRefocusState()->startRefocusTimer();
135 if (isGuidingDeviationDetected() ==
false)
137 resetDitherCounter();
138 getRefocusState()->resetInSequenceFocusCounter();
139 getRefocusState()->setAdaptiveFocusDone(
false);
142 setGuidingDeviationDetected(
false);
143 resetSpikesDetected();
145 setCaptureState(CAPTURE_PROGRESS);
148 if (Options::enforceGuideDeviation() && isGuidingOn() ==
false)
149 emit newLog(
i18n(
"Warning: Guide deviation is selected but autoguide process was not started."));
154void CaptureModuleState::setCaptureState(CaptureState value)
165 if (mf_state->getMeridianFlipStage() == MeridianFlipState::MF_REQUESTED)
166 mf_state->updateMeridianFlipStage(MeridianFlipState::MF_READY);
178 if (m_CaptureState != value)
181 m_CaptureState) <<
"to" << getCaptureStatusString(value);
182 m_CaptureState = value;
183 getMeridianFlipState()->setCaptureState(m_CaptureState);
184 emit newStatus(m_CaptureState);
189 emit newStatus(m_CaptureState);
194void CaptureModuleState::setGuideState(GuideState state)
196 if (state != m_GuideState)
198 Ekos::getGuideStatusString(m_GuideState)
199 <<
"to" << Ekos::getGuideStatusString(state);
204 case GUIDE_CALIBRATION_SUCCESS:
208 case GUIDE_CALIBRATION_ERROR:
209 processGuidingFailed();
212 case GUIDE_DITHERING_SUCCESS:
213 qCInfo(
KSTARS_EKOS_CAPTURE) <<
"Dithering succeeded, capture state" << getCaptureStatusString(
216 appendLogText(
i18n(
"Dithering succeeded."));
217 if (getCaptureState() != CAPTURE_DITHERING)
220 if (Options::guidingSettle() > 0)
223 appendLogText(
i18n(
"Dither complete. Resuming in %1 seconds...", Options::guidingSettle()));
226 setDitheringState(
IPS_OK);
231 appendLogText(
i18n(
"Dither complete."));
232 setDitheringState(
IPS_OK);
236 case GUIDE_DITHERING_ERROR:
237 qCInfo(
KSTARS_EKOS_CAPTURE) <<
"Dithering failed, capture state" << getCaptureStatusString(
239 if (getCaptureState() != CAPTURE_DITHERING)
242 if (Options::guidingSettle() > 0)
245 appendLogText(
i18n(
"Warning: Dithering failed. Resuming in %1 seconds...", Options::guidingSettle()));
249 setDitheringState(
IPS_OK);
254 appendLogText(
i18n(
"Warning: Dithering failed."));
256 setDitheringState(
IPS_OK);
265 m_GuideState = state;
267 if (m_activeJob !=
nullptr)
268 m_activeJob->setCoreProperty(SequenceJob::SJ_GuiderActive, isActivelyGuiding());
275 m_CurrentFilterPosition = position;
278 m_CurrentFilterName =
name;
283 m_CurrentFilterName =
"--";
284 m_CurrentFocusFilterName =
"--";
291 if (mf_state.isNull())
292 mf_state.reset(
new MeridianFlipState());
300 if (! mf_state.isNull())
302 mf_state->disconnect(
this);
303 mf_state->deleteLater();
307 connect(mf_state.data(), &Ekos::MeridianFlipState::newMountMFStatus,
this, &Ekos::CaptureModuleState::updateMFMountState,
311void CaptureModuleState::setObserverName(
const QString &value)
313 m_ObserverName = value;
314 Options::setDefaultObserver(value);
317void CaptureModuleState::setBusy(
bool busy)
320 emit captureBusy(busy);
323void CaptureModuleState::decreaseDitherCounter()
325 if (m_ditherCounter > 0)
329void CaptureModuleState::resetDitherCounter()
333 value = m_activeJob->getCoreProperty(SequenceJob::SJ_DitherPerJobFrequency).toInt(0);
336 m_ditherCounter = value;
338 m_ditherCounter = Options::ditherFrames();
341bool CaptureModuleState::checkDithering()
344 if (m_activeJob && m_activeJob->jobType() == SequenceJob::JOBTYPE_PREVIEW)
347 if ( (Options::ditherEnabled() || Options::ditherNoGuiding())
349 && getMeridianFlipState()->getMeridianFlipStage() != MeridianFlipState::MF_GUIDING
351 && (getGuideState() == GUIDE_GUIDING || Options::ditherNoGuiding())
353 && (m_activeJob !=
nullptr && m_activeJob->getFrameType() == FRAME_LIGHT)
355 && m_ditherCounter == 0)
358 resetDitherCounter();
361 appendLogText(
i18n(
"Dithering..."));
363 setCaptureState(CAPTURE_DITHERING);
372void CaptureModuleState::updateMFMountState(MeridianFlipState::MeridianFlipMountState status)
374 qCDebug(
KSTARS_EKOS_CAPTURE) <<
"updateMFMountState: " << MeridianFlipState::meridianFlipStatusString(status);
378 case MeridianFlipState::MOUNT_FLIP_NONE:
380 if (getMeridianFlipState()->getMeridianFlipStage() < MeridianFlipState::MF_COMPLETED)
381 updateMeridianFlipStage(MeridianFlipState::MF_NONE);
384 case MeridianFlipState::MOUNT_FLIP_PLANNED:
385 if (getMeridianFlipState()->getMeridianFlipStage() > MeridianFlipState::MF_REQUESTED)
389 getMeridianFlipState()->getMeridianFlipStage();
393 getMeridianFlipState()->setResumeGuidingAfterFlip(isGuidingOn());
396 updateMeridianFlipStage(MeridianFlipState::MF_REQUESTED);
398 if (m_CaptureState == CAPTURE_IDLE || m_CaptureState == CAPTURE_ABORTED
399 || m_CaptureState == CAPTURE_COMPLETE || m_CaptureState == CAPTURE_PAUSED)
400 getMeridianFlipState()->updateMFMountState(MeridianFlipState::MOUNT_FLIP_ACCEPTED);
404 case MeridianFlipState::MOUNT_FLIP_RUNNING:
405 updateMeridianFlipStage(MeridianFlipState::MF_INITIATED);
406 setCaptureState(CAPTURE_MERIDIAN_FLIP);
409 case MeridianFlipState::MOUNT_FLIP_COMPLETED:
410 updateMeridianFlipStage(MeridianFlipState::MF_COMPLETED);
419void CaptureModuleState::updateMeridianFlipStage(
const MeridianFlipState::MFStage &stage)
422 getMeridianFlipState()->updateMeridianFlipStage(stage);
427 case MeridianFlipState::MF_READY:
430 case MeridianFlipState::MF_INITIATED:
431 emit meridianFlipStarted();
434 case MeridianFlipState::MF_COMPLETED:
437 if (getRefocusState()->isInSequenceFocus())
441 getRefocusState()->setInSequenceFocusCounter(0);
445 if ( Options::ditherEnabled() || Options::ditherNoGuiding())
446 resetDitherCounter();
449 if (Options::refocusAfterMeridianFlip() ==
true)
450 getRefocusState()->setRefocusAfterMeridianFlip(
true);
452 if (hasDome && (m_domeState == ISD::Dome::DOME_MOVING_CW || m_domeState == ISD::Dome::DOME_MOVING_CCW))
455 KSNotification::event(
QLatin1String(
"MeridianFlipCompleted"),
i18n(
"Meridian flip is successfully completed"),
456 KSNotification::Capture);
458 getMeridianFlipState()->processFlipCompleted();
461 setCaptureState(m_ContinueAction == CONTINUE_ACTION_NONE ? CAPTURE_IDLE :
CAPTURE_PAUSED);
468 emit newMeridianFlipStage(stage);
471bool CaptureModuleState::checkMeridianFlipActive()
473 return (getMeridianFlipState()->checkMeridianFlipRunning() ||
474 checkPostMeridianFlipActions() ||
475 checkMeridianFlipReady());
478bool CaptureModuleState::checkMeridianFlipReady()
480 if (hasTelescope ==
false)
485 if (m_activeJob && m_activeJob->getFrameType() == FRAME_FLAT && m_activeJob->getCalibrationPreAction() & ACTION_WALL)
488 if (getMeridianFlipState()->getMeridianFlipStage() != MeridianFlipState::MF_REQUESTED)
495 if (m_refocusState->isInSequenceFocus() ||
496 (Options::enforceRefocusEveryN() && m_refocusState->getRefocusEveryNTimerElapsedSec() > 0))
500 if (getMeridianFlipState()->getMeridianFlipStage() == MeridianFlipState::MF_REQUESTED)
501 getMeridianFlipState()->updateMeridianFlipStage(MeridianFlipState::MF_READY);
507bool CaptureModuleState::checkPostMeridianFlipActions()
510 if (m_CaptureState == CAPTURE_ALIGNING || checkAlignmentAfterFlip())
515 if (getMeridianFlipState()->getMeridianFlipStage() >= MeridianFlipState::MF_COMPLETED && m_GuideState != GUIDE_GUIDING
516 && checkGuidingAfterFlip())
522 if (m_CaptureState == CAPTURE_CALIBRATING
523 && getMeridianFlipState()->getMeridianFlipStage() == MeridianFlipState::MF_GUIDING)
525 if (Options::enforceGuideDeviation() || Options::enforceStartGuiderDrift())
528 updateMeridianFlipStage(MeridianFlipState::MF_NONE);
535bool CaptureModuleState::checkGuidingAfterFlip()
538 if (getMeridianFlipState()->getMeridianFlipStage() < MeridianFlipState::MF_COMPLETED)
541 if (getMeridianFlipState()->resumeGuidingAfterFlip() ==
false)
543 getMeridianFlipState()->updateMeridianFlipStage(MeridianFlipState::MF_NONE);
548 if (getMeridianFlipState()->getMeridianFlipStage() >= MeridianFlipState::MF_COMPLETED
549 && getMeridianFlipState()->getMeridianFlipStage() < MeridianFlipState::MF_GUIDING)
551 appendLogText(
i18n(
"Performing post flip re-calibration and guiding..."));
553 setCaptureState(CAPTURE_CALIBRATING);
555 getMeridianFlipState()->updateMeridianFlipStage(MeridianFlipState::MF_GUIDING);
556 emit guideAfterMeridianFlip();
559 else if (m_CaptureState == CAPTURE_CALIBRATING)
561 if (getGuideState() == GUIDE_CALIBRATION_ERROR || getGuideState() == GUIDE_ABORTED)
564 appendLogText(
i18n(
"Post meridian flip calibration error. Restarting..."));
565 emit guideAfterMeridianFlip();
568 else if (getGuideState() != GUIDE_GUIDING)
580void CaptureModuleState::processGuidingFailed()
582 if (m_FocusState > FOCUS_PROGRESS)
584 appendLogText(
i18n(
"Autoguiding stopped. Waiting for autofocus to finish..."));
587 else if (isGuidingOn()
588 && getMeridianFlipState()->getMeridianFlipStage() == MeridianFlipState::MF_NONE &&
590 ((m_activeJob && m_activeJob->getStatus() == JOB_BUSY && m_activeJob->getFrameType() == FRAME_LIGHT) ||
591 m_CaptureState == CAPTURE_SUSPENDED || m_CaptureState == CAPTURE_PAUSED))
593 appendLogText(
i18n(
"Autoguiding stopped. Aborting..."));
596 else if (getMeridianFlipState()->getMeridianFlipStage() == MeridianFlipState::MF_GUIDING)
598 if (increaseAlignmentRetries() >= 3)
600 appendLogText(
i18n(
"Post meridian flip calibration error. Aborting..."));
606void CaptureModuleState::updateAdaptiveFocusState(
bool success)
608 m_refocusState->setAdaptiveFocusDone(
true);
616 m_refocusState->setAutoFocusReady(
true);
618 if (m_activeJob !=
nullptr)
619 m_activeJob->setAutoFocusReady(
true);
621 setFocusState(FOCUS_COMPLETE);
622 emit newLog(
i18n(success ?
"Adaptive focus complete." :
"Adaptive focus failed. Continuing..."));
625void CaptureModuleState::updateFocusState(FocusState state)
627 if (state != m_FocusState)
629 Ekos::getFocusStatusString(m_FocusState) <<
630 "to" << Ekos::getFocusStatusString(state);
631 setFocusState(state);
634 if (getMeridianFlipState()->checkMeridianFlipRunning())
641 if (!(getMeridianFlipState()->getMeridianFlipStage() == MeridianFlipState::MF_INITIATED))
645 emit newFocusStatus(state);
646 appendLogText(
i18n(
"Autofocus failed. Aborting exposure..."));
652 m_refocusState->setAutoFocusReady(
true);
654 if (m_activeJob !=
nullptr)
655 m_activeJob->setAutoFocusReady(
true);
657 if (m_refocusState->getFocusHFRInAutofocus())
658 m_refocusState->startRefocusTimer(
true);
661 if (Options::hFRCheckAlgorithm() == HFR_CHECK_MEDIAN_MEASURE ||
662 (m_refocusState->getFocusHFRInAutofocus() && Options::hFRCheckAlgorithm() == HFR_CHECK_LAST_AUTOFOCUS))
664 m_refocusState->addHFRValue(getFocusFilterName());
665 updateHFRThreshold();
667 emit newFocusStatus(state);
673 if (m_activeJob !=
nullptr)
674 m_activeJob->setFocusStatus(state);
677AutofocusReason CaptureModuleState::getAFReason(RefocusState::RefocusReason state,
QString &reasonInfo)
683 case RefocusState::REFOCUS_USER_REQUEST:
684 afReason = AutofocusReason::FOCUS_USER_REQUEST;
686 case RefocusState::REFOCUS_TEMPERATURE:
687 afReason = AutofocusReason::FOCUS_TEMPERATURE;
688 reasonInfo =
i18n(
"Limit: %1 °C",
QString::number(Options::maxFocusTemperatureDelta(),
'f', 2));
690 case RefocusState::REFOCUS_TIME_ELAPSED:
691 afReason = AutofocusReason::FOCUS_TIME;
692 reasonInfo =
i18n(
"Limit: %1 mins", Options::refocusEveryN());
694 case RefocusState::REFOCUS_POST_MF:
695 afReason = AutofocusReason::FOCUS_MERIDIAN_FLIP;
698 afReason = AutofocusReason::FOCUS_NONE;
703bool CaptureModuleState::startFocusIfRequired()
709 if (m_activeJob ==
nullptr || m_activeJob->getFrameType() != FRAME_LIGHT
710 || m_activeJob->jobType() == SequenceJob::JOBTYPE_PREVIEW)
713 RefocusState::RefocusReason reason = m_refocusState->checkFocusRequired();
716 if (reason == RefocusState::REFOCUS_NONE)
720 m_refocusState->setRefocusAfterMeridianFlip(
false);
726 if (getMeridianFlipState()->getMeridianFlipStage() != MeridianFlipState::MF_NONE)
728 int targetFilterPosition = m_activeJob->getTargetFilter();
729 if (targetFilterPosition > 0 && targetFilterPosition != getCurrentFilterPosition())
730 emit newFilterPosition(targetFilterPosition);
733 emit abortFastExposure();
734 updateFocusState(FOCUS_PROGRESS);
740 case RefocusState::REFOCUS_HFR:
741 m_refocusState->resetInSequenceFocusCounter();
742 emit checkFocus(Options::hFRDeviation());
745 case RefocusState::REFOCUS_ADAPTIVE:
746 m_refocusState->setAdaptiveFocusDone(
true);
747 emit adaptiveFocus();
750 case RefocusState::REFOCUS_USER_REQUEST:
751 case RefocusState::REFOCUS_TEMPERATURE:
752 case RefocusState::REFOCUS_TIME_ELAPSED:
753 case RefocusState::REFOCUS_POST_MF:
755 if (m_refocusState->getRefocusEveryNTimerElapsedSec() >= 1800)
759 afReason = getAFReason(reason, reasonInfo);
762 m_refocusState->resetInSequenceFocusCounter();
770 setCaptureState(CAPTURE_FOCUSING);
774void CaptureModuleState::updateHFRThreshold()
777 if (Options::hFRCheckAlgorithm() == HFR_CHECK_FIXED)
788 if (Options::hFRCheckAlgorithm() == HFR_CHECK_LAST_AUTOFOCUS)
798 value += value * (Options::hFRThresholdPercentage() / 100.0);
799 Options::setHFRDeviation(value);
800 emit newLimitFocusHFR(value);
803QString CaptureModuleState::getFocusFilterName()
806 if (m_CurrentFilterPosition > 0)
811 finalFilter = (m_CurrentFocusFilterName ==
"--" ? m_CurrentFilterName : m_CurrentFocusFilterName);
818bool CaptureModuleState::checkAlignmentAfterFlip()
821 if (getMeridianFlipState()->getMeridianFlipStage() < MeridianFlipState::MF_COMPLETED)
824 if (getMeridianFlipState()->resumeAlignmentAfterFlip() ==
false)
828 if (m_CaptureState < CAPTURE_ALIGNING)
830 appendLogText(
i18n(
"Performing post flip re-alignment..."));
832 resetAlignmentRetries();
833 setCaptureState(CAPTURE_ALIGNING);
835 getMeridianFlipState()->updateMeridianFlipStage(MeridianFlipState::MF_ALIGNING);
843void CaptureModuleState::checkGuideDeviationTimeout()
845 if (m_activeJob && m_activeJob->getStatus() == JOB_ABORTED
846 && isGuidingDeviationDetected())
848 appendLogText(
i18n(
"Guide module timed out."));
849 setGuidingDeviationDetected(
false);
852 if (m_CaptureState == CAPTURE_SUSPENDED)
854 setCaptureState(CAPTURE_ABORTED);
859void CaptureModuleState::setGuideDeviation(
double deviation_rms)
867 if (m_activeJob ==
nullptr && checkMeridianFlipReady())
871 if (m_CaptureState == CAPTURE_PROGRESS &&
872 getMeridianFlipState()->getMeridianFlipStage() != MeridianFlipState::MF_REQUESTED &&
873 getMeridianFlipState()->checkMeridianFlipRunning() ==
false)
876 if (Options::enforceStartGuiderDrift() ==
false ||
deviation_rms < Options::startGuideDeviation())
878 setCaptureState(CAPTURE_CALIBRATING);
879 if (Options::enforceStartGuiderDrift())
880 appendLogText(
i18n(
"Initial guiding deviation %1 below limit value of %2 arcsecs",
882 setGuidingDeviationDetected(
false);
883 setStartingCapture(
false);
888 if (isGuidingDeviationDetected() ==
false)
889 appendLogText(
i18n(
"Initial guiding deviation %1 exceeded limit value of %2 arcsecs",
892 setGuidingDeviationDetected(
true);
896 if (checkMeridianFlipReady())
906 if (getMeridianFlipState()->getMeridianFlipStage() == MeridianFlipState::MF_GUIDING)
909 if (Options::enforceGuideDeviation() ==
false ||
deviation_rms < Options::guideDeviation())
911 appendLogText(
i18n(
"Post meridian flip calibration completed successfully."));
913 getMeridianFlipState()->updateMeridianFlipStage(MeridianFlipState::MF_NONE);
919 if (m_activeJob && m_activeJob->getStatus() == JOB_BUSY && m_activeJob->getFrameType() == FRAME_LIGHT
920 && isStartingCapture() && Options::enforceStartGuiderDrift())
922 setStartingCapture(
false);
925 appendLogText(
i18n(
"Guiding deviation at capture startup %1 exceeded limit %2 arcsecs.",
927 emit suspendCapture();
928 setGuidingDeviationDetected(
true);
932 if (checkMeridianFlipReady())
935 getGuideDeviationTimer().start();
939 appendLogText(
i18n(
"Guiding deviation at capture startup %1 below limit value of %2 arcsecs",
943 if (m_CaptureState != CAPTURE_SUSPENDED)
947 if ((Options::enforceGuideDeviation() ==
false)
949 (m_activeJob && (m_activeJob->jobType() == SequenceJob::JOBTYPE_PREVIEW ||
950 m_activeJob->getExposeLeft() == 0.0 ||
951 m_activeJob->getFrameType() != FRAME_LIGHT)))
956 if (m_activeJob && m_activeJob->getStatus() == JOB_BUSY && m_activeJob->getFrameType() == FRAME_LIGHT)
959 resetSpikesDetected();
963 if (increaseSpikesDetected() < Options::guideDeviationReps())
966 appendLogText(
i18n(
"Guiding deviation %1 exceeded limit value of %2 arcsecs for %4 consecutive samples, "
967 "suspending exposure and waiting for guider up to %3 seconds.",
969 QString(
"%L1").arg(getGuideDeviationTimer().interval() / 1000.0, 0,
'f', 3),
970 Options::guideDeviationReps()));
972 emit suspendCapture();
974 resetSpikesDetected();
975 setGuidingDeviationDetected(
true);
979 if (checkMeridianFlipReady())
982 getGuideDeviationTimer().start();
990 for(
auto &job : allJobs())
992 if (job->getStatus() == JOB_ABORTED)
999 if (
abortedJob !=
nullptr && isGuidingDeviationDetected())
1003 getGuideDeviationTimer().stop();
1006 if (! getCaptureDelayTimer().isActive())
1009 if (m_CaptureState == CAPTURE_SUSPENDED)
1013 appendLogText(
i18n(
"Guiding deviation %1 is now lower than limit value of %2 arcsecs, "
1014 "resuming exposure.",
1017 appendLogText(
i18n(
"Guiding deviation %1 is now lower than limit value of %2 arcsecs, "
1018 "resuming exposure in %3 seconds.",
1021 emit startCapture();
1029 if (getCaptureDelayTimer().isActive())
1030 getCaptureDelayTimer().stop();
1032 appendLogText(
i18n(
"Guiding deviation %1 is still higher than limit value of %2 arcsecs.",
1038void CaptureModuleState::addDownloadTime(
double time)
1040 totalDownloadTime += time;
1044int CaptureModuleState::pendingJobCount()
1050 if (job->getStatus() == JOB_DONE)
1058QString CaptureModuleState::jobState(
int id)
1060 if (
id < allJobs().count())
1063 return job->getStatusString();
1070QString CaptureModuleState::jobFilterName(
int id)
1072 if (
id < allJobs().count())
1075 return job->getCoreProperty(SequenceJob::SJ_Filter).toString();
1082CCDFrameType CaptureModuleState::jobFrameType(
int id)
1084 if (
id < allJobs().count())
1087 return job->getFrameType();
1093int CaptureModuleState::jobImageProgress(
int id)
1095 if (
id < allJobs().count())
1098 return job->getCompleted();
1104int CaptureModuleState::jobImageCount(
int id)
1106 if (
id < allJobs().count())
1109 return job->getCoreProperty(SequenceJob::SJ_Count).toInt();
1115double CaptureModuleState::jobExposureProgress(
int id)
1117 if (
id < allJobs().count())
1120 return job->getExposeLeft();
1126double CaptureModuleState::jobExposureDuration(
int id)
1128 if (
id < allJobs().count())
1131 return job->getCoreProperty(SequenceJob::SJ_Exposure).toDouble();
1137double CaptureModuleState::progressPercentage()
1144 totalImageCount += job->getCoreProperty(SequenceJob::SJ_Count).toInt();
1154int CaptureModuleState::activeJobRemainingTime()
1156 if (m_activeJob ==
nullptr)
1159 return m_activeJob->getJobRemainingTime(averageDownloadTime());
1162int CaptureModuleState::overallRemainingTime()
1173QString CaptureModuleState::sequenceQueueStatus()
1175 if (allJobs().count() == 0)
1181 int idle = 0,
error = 0, complete = 0, aborted = 0, running = 0;
1185 switch (job->getStatus())
1210 if (m_CaptureState == CAPTURE_SUSPENDED)
1219 if (
idle == allJobs().count())
1222 if (complete == allJobs().count())
1228QJsonObject CaptureModuleState::calibrationSettings()
1232 {
"preAction",
static_cast<int>(calibrationPreAction())},
1233 {
"duration", flatFieldDuration()},
1234 {
"az", wallCoord().az().Degrees()},
1235 {
"al", wallCoord().alt().Degrees()},
1236 {
"adu", targetADU()},
1237 {
"tolerance", targetADUTolerance()},
1238 {
"skyflat", skyFlat()},
1244void CaptureModuleState::setCalibrationSettings(
const QJsonObject &settings)
1246 const int preAction = settings[
"preAction"].toInt(calibrationPreAction());
1247 const int duration = settings[
"duration"].toInt(flatFieldDuration());
1248 const double az = settings[
"az"].toDouble(wallCoord().az().Degrees());
1249 const double al = settings[
"al"].toDouble(wallCoord().alt().Degrees());
1250 const int adu = settings[
"adu"].toInt(
static_cast<int>(std::round(targetADU())));
1251 const int tolerance = settings[
"tolerance"].toInt(
static_cast<int>(std::round(targetADUTolerance())));
1252 const int skyflat = settings[
"skyflat"].toBool();
1254 setCalibrationPreAction(
static_cast<CalibrationPreActions
>(
preAction));
1255 setFlatFieldDuration(
static_cast<FlatFieldDuration
>(duration));
1256 wallCoord().setAz(az);
1257 wallCoord().setAlt(
al);
1263bool CaptureModuleState::setDarkFlatExposure(
SequenceJob *job)
1265 const auto darkFlatFilter = job->getCoreProperty(SequenceJob::SJ_Filter).toString();
1266 const auto darkFlatBinning = job->getCoreProperty(SequenceJob::SJ_Binning).toPoint();
1267 const auto darkFlatADU = job->getCoreProperty(SequenceJob::SJ_TargetADU).toInt();
1269 for (
auto &
oneJob : allJobs())
1271 if (
oneJob->getFrameType() != FRAME_FLAT)
1274 const auto filter =
oneJob->getCoreProperty(SequenceJob::SJ_Filter).toString();
1281 const auto binning =
oneJob->getCoreProperty(SequenceJob::SJ_Binning).toPoint();
1286 const auto adu =
oneJob->getCoreProperty(SequenceJob::SJ_TargetADU).
toInt();
1287 if (job->getFlatFieldDuration() == DURATION_ADU)
1294 job->setCoreProperty(SequenceJob::SJ_Exposure,
oneJob->getCoreProperty(SequenceJob::SJ_Exposure).toDouble());
1301void CaptureModuleState::checkSeqBoundary(
QUrl sequenceURL)
1304 if (getMeridianFlipState()->getMeridianFlipStage() >= MeridianFlipState::MF_ALIGNING)
1307 auto placeholderPath = PlaceholderPath(sequenceURL.
toLocalFile());
1308 setNextSequenceID(placeholderPath.checkSeqBoundary(*getActiveJob()));
1311bool CaptureModuleState::isModelinDSLRInfo(
const QString &model)
1315 return (oneDSLRInfo[
"Model"] == model);
1318 return (pos != m_DSLRInfos.end());
1321void CaptureModuleState::setCapturedFramesCount(
const QString &signature, uint16_t count)
1323 m_capturedFramesMap[signature] = count;
1325 QString(
"Client module indicates that storage for '%1' has already %2 captures processed.").
arg(signature).
arg(count);
1327 setIgnoreJobProgress(
false);
1330void CaptureModuleState::changeSequenceValue(
int index,
QString key,
QString value)
1340void CaptureModuleState::addCapturedFrame(
const QString &signature)
1342 CapturedFramesMap::iterator
frame_item = m_capturedFramesMap.find(signature);
1345 else m_capturedFramesMap[signature] = 1;
1349void CaptureModuleState::removeCapturedFrameCount(
const QString &signature, uint16_t count)
1351 CapturedFramesMap::iterator
frame_item = m_capturedFramesMap.find(signature);
1358 m_capturedFramesMap.remove(signature);
1364void CaptureModuleState::appendLogText(
const QString &message)
1367 emit newLog(message);
1370bool CaptureModuleState::isGuidingOn()
1373 if (Options::ditherNoGuiding())
1376 return (m_GuideState == GUIDE_GUIDING ||
1377 m_GuideState == GUIDE_CALIBRATING ||
1378 m_GuideState == GUIDE_CALIBRATION_SUCCESS ||
1379 m_GuideState == GUIDE_DARK ||
1380 m_GuideState == GUIDE_SUBFRAME ||
1381 m_GuideState == GUIDE_STAR_SELECT ||
1382 m_GuideState == GUIDE_REACQUIRE ||
1383 m_GuideState == GUIDE_DITHERING ||
1384 m_GuideState == GUIDE_DITHERING_SUCCESS ||
1385 m_GuideState == GUIDE_DITHERING_ERROR ||
1386 m_GuideState == GUIDE_DITHERING_SETTLE ||
1387 m_GuideState == GUIDE_SUSPENDED
1391bool CaptureModuleState::isActivelyGuiding()
1393 return isGuidingOn() && (m_GuideState == GUIDE_GUIDING);
1396void CaptureModuleState::setAlignState(AlignState value)
1398 if (value != m_AlignState)
1400 m_AlignState) <<
"to" << Ekos::getAlignStatusString(value);
1401 m_AlignState = value;
1403 getMeridianFlipState()->setResumeAlignmentAfterFlip(
true);
1408 if (getMeridianFlipState()->getMeridianFlipStage() == MeridianFlipState::MF_ALIGNING)
1410 appendLogText(
i18n(
"Post flip re-alignment completed successfully."));
1411 resetAlignmentRetries();
1413 if (checkGuidingAfterFlip() ==
false)
1416 updateMeridianFlipStage(MeridianFlipState::MF_NONE);
1417 setCaptureState(CAPTURE_WAITING);
1425 if (getMeridianFlipState()->getMeridianFlipStage() == MeridianFlipState::MF_ALIGNING)
1427 if (increaseAlignmentRetries() >= 3)
1429 appendLogText(
i18n(
"Post-flip alignment failed."));
1430 emit abortCapture();
1434 appendLogText(
i18n(
"Post-flip alignment failed. Retrying..."));
1436 updateMeridianFlipStage(MeridianFlipState::MF_COMPLETED);
Sequence Job is a container for the details required to capture a series of images.
QString i18n(const char *text, const TYPE &arg...)
Ekos is an advanced Astrophotography tool for Linux.
@ ALIGN_FAILED
Alignment failed.
@ ALIGN_ABORTED
Alignment aborted by user or agent.
@ ALIGN_COMPLETE
Alignment successfully completed.
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
QString name(StandardShortcut id)
QString arg(Args &&... args) const const
QString number(double n, char format, int precision)
QFuture< void > filter(QThreadPool *pool, Sequence &sequence, KeepFunctor &&filterFunction)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
QString toLocalFile() const const