Kstars

camerastate.h
1/* Ekos state machine for the Capture module
2 SPDX-FileCopyrightText: 2022 Wolfgang Reissenberger <sterne-jaeger@openfuture.de>
3
4 SPDX-License-Identifier: GPL-2.0-or-later
5*/
6
7#pragma once
8
9#include <QObject>
10
11#include "Options.h"
12
13#include "capturetypes.h"
14#include "ekos/ekos.h"
15#include "indiapi.h"
16#include "indi/indistd.h"
17#include "indi/indidustcap.h"
18#include "indi/indicamera.h"
19#include "indi/indimount.h"
20#include "indi/indidome.h"
21
22#include "ekos/manager/meridianflipstate.h"
23#include "ekos/auxiliary/filtermanager.h"
24#include "ekos/scheduler/schedulertypes.h"
25#include "ekos/capture/refocusstate.h"
26#include "ekos/focus/focusutils.h"
27#include "placeholderpath.h"
28
29// Wait 3-minutes as maximum beyond exposure
30// value.
31#define CAPTURE_TIMEOUT_THRESHOLD 180000
32
33class FITSData;
34
35namespace Ekos
36{
37
38constexpr double HFR_CHECK_DEFAULT_THRESHOLD = 10.0;
39
40class SequenceJob;
41class SequenceQueue;
42class CaptureDeviceAdaptor;
43class RefocusState;
44
45class CameraState: public QObject
46{
48 public:
49 /* Interval with double lower and upper bound */
50 typedef struct
51 {
52 double min, max;
53 } DoubleRange;
54
55 CameraState(QObject *parent = nullptr);
56
57 // ////////////////////////////////////////////////////////////////////
58 // sequence jobs
59 // ////////////////////////////////////////////////////////////////////
60 QList<SequenceJob *> &allJobs();
61
62 QSharedPointer<SequenceQueue> getSequenceQueue()
63 {
64 return m_sequenceQueue;
65 }
66
67 SequenceJob *getActiveJob() const
68 {
69 return m_activeJob;
70 }
71 void setActiveJob(SequenceJob *value);
72
73 const QUrl &sequenceURL() const;
74 void setSequenceURL(const QUrl &newSequenceURL);
75
76 // ////////////////////////////////////////////////////////////////////
77 // pointer to last captured frame
78 // ////////////////////////////////////////////////////////////////////
79 QSharedPointer<FITSData> imageData()
80 {
81 return m_ImageData;
82 }
83 void setImageData(QSharedPointer<FITSData> newImageData)
84 {
85 m_ImageData = newImageData;
86 }
87
88 // ////////////////////////////////////////////////////////////////////
89 // capture attributes
90 // ////////////////////////////////////////////////////////////////////
91 // current filter ID
92 int currentFilterID { Ekos::INVALID_VALUE };
93 // Map tracking whether the current value has been initialized.
94 // With this construct we could do a lazy initialization of current values if setCurrent...()
95 // sets this flag to true. This is necessary since we listen to the events, but as long as
96 // the value does not change, there won't be an event.
98
99 // ////////////////////////////////////////////////////////////////////
100 // flat preparation attributes
101 // ////////////////////////////////////////////////////////////////////
102 // flag if telescope has been covered
103 typedef enum
104 {
105 MANAUL_COVER_OPEN,
106 MANUAL_COVER_CLOSED_LIGHT,
107 MANUAL_COVER_CLOSED_DARK
108 } ManualCoverState;
109
110 ManualCoverState m_ManualCoverState { MANAUL_COVER_OPEN };
111 // flag if there is a light box device
112 bool hasLightBox { false };
113 // flag if there is a dust cap device
114 bool hasDustCap { false };
115 // flag if there is a telescope device
116 bool hasTelescope { false };
117 // flag if there is a dome device
118 bool hasDome { false };
119
120 // ////////////////////////////////////////////////////////////////////
121 // dark preparation attributes
122 // ////////////////////////////////////////////////////////////////////
123 ShutterStatus shutterStatus { SHUTTER_UNKNOWN };
124
125
126 // ////////////////////////////////////////////////////////////////////
127 // state changes
128 // ////////////////////////////////////////////////////////////////////
129 /**
130 * @brief captureStarted The preparation to capture have been started.
131 */
132 void initCapturePreparation();
133
134 // ////////////////////////////////////////////////////////////////////
135 // state accessors
136 // ////////////////////////////////////////////////////////////////////
137 CaptureState getCaptureState() const
138 {
139 return m_CaptureState;
140 }
141 void setCaptureState(CaptureState value);
142
143 bool isStartingCapture() const
144 {
145 return m_StartingCapture;
146 }
147 void setStartingCapture(bool newStartingCapture)
148 {
149 m_StartingCapture = newStartingCapture;
150 }
151
152 CaptureContinueAction getContinueAction() const
153 {
154 return m_ContinueAction;
155 }
156 void setContinueAction(CaptureContinueAction newPauseFunction)
157 {
158 m_ContinueAction = newPauseFunction;
159 }
160
161 FocusState getFocusState() const
162 {
163 return m_FocusState;
164 }
165 void setFocusState(FocusState value)
166 {
167 m_FocusState = value;
168 }
169
170 GuideState getGuideState() const
171 {
172 return m_GuideState;
173 }
174 void setGuideState(GuideState state);
175
176 // short cut for all guiding states that indicate guiding is on
177 bool isGuidingOn();
178 // short cut for all guiding states that indicate guiding in state GUIDING
179 bool isActivelyGuiding();
180
181 bool useGuideHead() const
182 {
183 return m_useGuideHead;
184 }
185 void setUseGuideHead(bool value)
186 {
187 m_useGuideHead = value;
188 }
189 bool isGuidingDeviationDetected() const
190 {
191 return m_GuidingDeviationDetected;
192 }
193 void setGuidingDeviationDetected(bool newDeviationDetected)
194 {
195 m_GuidingDeviationDetected = newDeviationDetected;
196 }
197
198 bool suspendGuidingOnDownload() const
199 {
200 return m_SuspendGuidingOnDownload;
201 }
202 void setSuspendGuidingOnDownload(bool value)
203 {
204 m_SuspendGuidingOnDownload = value;
205 }
206
207 uint SpikesDetected() const
208 {
209 return m_SpikesDetected;
210 }
211 uint increaseSpikesDetected()
212 {
213 return ++m_SpikesDetected;
214 }
215 void resetSpikesDetected()
216 {
217 m_SpikesDetected = 0;
218 }
219
220 IPState getDitheringState() const
221 {
222 return m_DitheringState;
223 }
224 void setDitheringState(IPState value)
225 {
226 m_DitheringState = value;
227 }
228
229 AlignState getAlignState() const
230 {
231 return m_AlignState;
232 }
233 void setAlignState(AlignState value);
234
235 FilterState getFilterManagerState() const
236 {
237 return m_FilterManagerState;
238 }
239 void setFilterManagerState(FilterState value)
240 {
241 m_FilterManagerState = value;
242 }
243
244 int getCurrentFilterPosition() const
245 {
246 return m_CurrentFilterPosition;
247 }
248
249 const QString &getCurrentFilterName() const
250 {
251 return m_CurrentFilterName;
252 }
253
254 const QString &CurrentFocusFilterName() const
255 {
256 return m_CurrentFocusFilterName;
257 }
258
259 void setCurrentFilterPosition(int position, const QString &name, const QString &focusFilterName);
260
261 LightState getLightBoxLightState() const
262 {
263 return m_lightBoxLightState;
264 }
265 void setLightBoxLightState(LightState value)
266 {
267 m_lightBoxLightState = value;
268 }
269
270 bool lightBoxLightEnabled() const
271 {
272 return m_lightBoxLightEnabled;
273 }
274 void setLightBoxLightEnabled(bool value)
275 {
276 m_lightBoxLightEnabled = value;
277 }
278
279 /**
280 * @brief dust cap status change
281 */
282 void dustCapStateChanged(ISD::DustCap::Status status);
283
284 CapState getDustCapState() const
285 {
286 return m_dustCapState;
287 }
288 void setDustCapState(CapState value)
289 {
290 m_dustCapState = value;
291 }
292
293 ISD::Mount::Status getScopeState() const
294 {
295 return m_scopeState;
296 }
297 void setScopeState(ISD::Mount::Status value)
298 {
299 m_scopeState = value;
300 }
301
302 ISD::Mount::PierSide getPierSide() const
303 {
304 return m_pierSide;
305 }
306 void setPierSide(ISD::Mount::PierSide value)
307 {
308 m_pierSide = value;
309 }
310
311 ISD::ParkStatus getScopeParkState() const
312 {
313 return m_scopeParkState;
314 }
315 void setScopeParkState(ISD::ParkStatus value)
316 {
317 m_scopeParkState = value;
318 }
319
320 ISD::Dome::Status getDomeState() const
321 {
322 return m_domeState;
323 }
324 void setDomeState(ISD::Dome::Status value)
325 {
326 m_domeState = value;
327 }
328
329 QSharedPointer<MeridianFlipState> getMeridianFlipState();
330 void setMeridianFlipState(QSharedPointer<MeridianFlipState> state);
331
332 QSharedPointer<RefocusState> getRefocusState() const
333 {
334 return m_refocusState;
335 }
336
337 const QString &observerName() const
338 {
339 return m_ObserverName;
340 }
341 void setObserverName(const QString &value);
342
343 bool ignoreJobProgress() const
344 {
345 return m_ignoreJobProgress;
346 }
347 void setIgnoreJobProgress(bool value)
348 {
349 m_ignoreJobProgress = value;
350 }
351
352 bool isRememberFastExposure() const
353 {
354 return m_RememberFastExposure;
355 }
356 void setRememberFastExposure(bool value)
357 {
358 m_RememberFastExposure = value;
359 }
360
361 bool dirty() const
362 {
363 return m_Dirty;
364 }
365 void setDirty(bool value)
366 {
367 m_Dirty = value;
368 }
369
370 bool isBusy() const
371 {
372 return m_Busy;
373 }
374 void setBusy(bool busy);
375
376 bool isLooping() const
377 {
378 return m_Looping;
379 }
380 void setLooping(bool newLooping)
381 {
382 m_Looping = newLooping;
383 }
384
385 QJsonArray &getSequence()
386 {
387 return m_SequenceArray;
388 }
389 void setSequence(const QJsonArray &value)
390 {
391 m_SequenceArray = value;
392 }
393
394 PlaceholderPath &placeholderPath()
395 {
396 return m_currentPlaceholderPath;
397 }
398 void initPlaceholderPath()
399 {
400 m_currentPlaceholderPath = PlaceholderPath();
401 }
402
403 /**
404 * @brief generateFilename generate the final file name for storing captured frames locally.
405 * @param extension file name extension (including ".")
406 * @param filename resulting file name
407 * @return
408 */
409 bool generateFilename(const QString &extension, QString *filename);
410
411 // ////////////////////////////////////////////////////////////////////
412 // counters
413 // ////////////////////////////////////////////////////////////////////
414
415 int getAlignmentRetries() const
416 {
417 return m_AlignmentRetries;
418 }
419 int increaseAlignmentRetries()
420 {
421 return ++m_AlignmentRetries;
422 }
423 void resetAlignmentRetries()
424 {
425 m_AlignmentRetries = 0;
426 }
427
428 int getDitherCounter() const
429 {
430 return m_ditherCounter;
431 }
432 void decreaseDitherCounter();
433
434 /**
435 * @brief resetDitherCounter Reset the dither counter to its start value. If a per job counter is
436 * set to > 0, this value is used and the general dither counter otherwise.
437 */
438 void resetDitherCounter();
439
440 int nextSequenceID() const
441 {
442 return m_nextSequenceID;
443 }
444 void setNextSequenceID(int id)
445 {
446 m_nextSequenceID = id;
447 }
448
449 uint16_t capturedFramesCount(const QString &signature) const
450 {
451 return m_capturedFramesMap[signature];
452 }
453 void setCapturedFramesCount(const QString &signature, uint16_t count);
454
455 double lastRemainingFrameTimeMS() const
456 {
457 return m_lastRemainingFrameTimeMS;
458 }
459 void setLastRemainingFrameTimeMS(double value)
460 {
461 m_lastRemainingFrameTimeMS = value;
462 }
463
464 // ////////////////////////////////////////////////////////////////////
465 // Timers
466 // ////////////////////////////////////////////////////////////////////
467 QTimer &getCaptureTimeout()
468 {
469 return m_captureTimeout;
470 }
471 uint8_t captureTimeoutCounter() const
472 {
473 return m_CaptureTimeoutCounter;
474 }
475 void setCaptureTimeoutCounter(uint8_t value)
476 {
477 m_CaptureTimeoutCounter = value;
478 }
479 uint8_t deviceRestartCounter() const
480 {
481 return m_DeviceRestartCounter;
482 }
483 void setDeviceRestartCounter(uint8_t value)
484 {
485 m_DeviceRestartCounter = value;
486 }
487 QTimer &downloadProgressTimer()
488 {
489 return m_downloadProgressTimer;
490 }
491 QElapsedTimer &downloadTimer()
492 {
493 return m_DownloadTimer;
494 }
495 QTimer &getCaptureDelayTimer()
496 {
497 return m_captureDelayTimer;
498 }
499 QTimer &getGuideDeviationTimer()
500 {
501 return m_guideDeviationTimer;
502 }
503
504 QTime &imageCountDown()
505 {
506 return m_imageCountDown;
507 }
508 void imageCountDownAddMSecs(int value)
509 {
510 m_imageCountDown = m_imageCountDown.addMSecs(value);
511 }
512
513 QTime &sequenceCountDown()
514 {
515 return m_sequenceCountDown;
516 }
517 void sequenceCountDownAddMSecs(int value)
518 {
519 m_sequenceCountDown = m_sequenceCountDown.addMSecs(value);
520 }
521
522 /**
523 * @brief changeSequenceValue Change a single sequence in the sequence array
524 * @param index position in the array
525 * @param key sequence key
526 * @param value new sequence value
527 */
528 void changeSequenceValue(int index, QString key, QString value);
529
530 // ////////////////////////////////////////////////////////////////////
531 // Action checks
532 // ////////////////////////////////////////////////////////////////////
533 /**
534 * @brief Check, whether dithering is necessary and, in that case initiate it.
535 *
536 * Dithering is only required for batch images and does not apply for PREVIEW.
537 *
538 * There are several situations that determine, if dithering is necessary:
539 * 1. the current job captures light frames AND the dither counter has reached 0 AND
540 * 2. guiding is running OR the manual dithering option is selected AND
541 * 3. there is a guiding camera active AND
542 * 4. there hasn't just a meridian flip been finised.
543 *
544 * @return true iff dithering is necessary.
545 */
546
547 bool checkDithering();
548
549 bool checkCapturing()
550 {
551 return (m_CaptureState == CAPTURE_CAPTURING || m_CaptureState == CAPTURE_PAUSE_PLANNED);
552 }
553
554 /**
555 * @brief updateMFMountState Handle changes of the meridian flip mount state
556 */
557 void updateMFMountState(MeridianFlipState::MeridianFlipMountState status);
558
559 /**
560 * @brief updateMeridianFlipStage Update the meridian flip stage
561 */
562 void updateMeridianFlipStage(const MeridianFlipState::MFStage &stage);
563
564 /**
565 * @brief checkMeridianFlipActive
566 * @return true iff the meridian flip itself or post flip actions are running
567 */
568 bool checkMeridianFlipActive();
569
570 /**
571 * @brief Check whether a meridian flip has been requested and trigger it
572 * @return true iff a meridian flip has been triggered
573 */
574 bool checkMeridianFlipReady();
575
576 /**
577 * @brief checkPostMeridianFlipActions Execute the checks necessary after the mount
578 * has completed the meridian flip.
579 * @return true iff the post meridian flip actions are ongoing, false if completed or not necessary
580 */
581 bool checkPostMeridianFlipActions();
582
583 /**
584 * @brief Check if an alignment needs to be executed after completing
585 * a meridian flip.
586 * @return
587 */
588 bool checkAlignmentAfterFlip();
589
590 /**
591 * @brief checkGuideDeviationTimeout Handle timeout when no guide deviation has been received.
592 */
593 void checkGuideDeviationTimeout();
594
595 /**
596 * @brief Check if the mount's flip has been completed and start guiding
597 * if necessary. Starting guiding after the meridian flip works through
598 * the signal {@see startGuidingAfterFlip()}
599 * @return true if guiding needs to start but is not running yet
600 */
601 bool checkGuidingAfterFlip();
602
603 /**
604 * @brief processGuidingFailed React when guiding failed.
605 *
606 * If aguiding has been started before and stopped, capturing aborts except
607 * for the case that either
608 * - a meridian flip is running
609 * - a job is running for non light frames
610 * - capturing is either paused or suspended
611 * In these case, nothing is done.
612 */
613 void processGuidingFailed();
614
615 /**
616 * @brief Process changes necessary when the focus state changes.
617 */
618 void updateFocusState(FocusState state);
619
620 /**
621 * @brief Check if focusing is running (abbreviating function for focus state
622 * neither idle nor completed nor aborted).
623 */
624 bool checkFocusRunning()
625 {
626 return (m_FocusState != FOCUS_IDLE && m_FocusState != FOCUS_COMPLETE && m_FocusState != FOCUS_ABORTED);
627 }
628
629 /**
630 * @brief Converts from RefocusReason (used by Capture) to AutofocusReason (used by Focus)
631 * @param reasonInfo for the associated reason code
632 * @return Reason code for the Autofocus
633 */
634 AutofocusReason getAFReason(RefocusState::RefocusReason state, QString &reasonInfo);
635
636 /**
637 * @brief Start focusing if necessary (see {@see RefocusState#checkFocusRequired()}).
638 * @return TRUE if we need to run focusing, false if not necessary
639 */
640 bool startFocusIfRequired();
641
642 /**
643 * @brief Start adaptive focus if necessary
644 * @return TRUE if we need adaptive focus, false if not necessary
645 */
646
647 void updateAdaptiveFocusState(bool success);
648
649 /**
650 * @brief calculate new HFR threshold based on median value for current selected filter
651 */
652 void updateHFRThreshold();
653
654 /**
655 * @brief get the focus filter for the currently active capture filter
656 */
657 QString getFocusFilterName();
658
659 /**
660 * @brief Slot that listens to guiding deviations reported by the Guide module.
661 *
662 * Depending on the current status, it triggers several actions:
663 * - If there is no active job, it calls {@see CameraState::checkMeridianFlipReady()}, which may initiate a meridian flip.
664 * - If guiding has been started after a meridian flip and the deviation is within the expected limits,
665 * the meridian flip is regarded as completed by setMeridianFlipStage(MF_NONE) (@see setMeridianFlipStage()).
666 * - If the deviation is beyond the defined limit, capturing is suspended (@see suspend()) and the
667 * #guideDeviationTimer is started.
668 * - Otherwise, it checks if there has been a job suspended and restarts it, since guiding is within the limits.
669 */
670
671 void setGuideDeviation(double deviation_rms);
672
673 /**
674 * @brief addDownloadTime Record a new download time
675 */
676 void addDownloadTime(double time);
677
678 /**
679 * @brief averageDownloadTime Determine the average download time
680 * @return
681 */
682 double averageDownloadTime()
683 {
684 return (downloadsCounter == 0 ? 0 : totalDownloadTime / downloadsCounter);
685 }
686
687 /**
688 * @brief setDarkFlatExposure Given a dark flat job, find the exposure suitable from it by searching for
689 * completed flat frames.
690 * @param job Dark flat job
691 * @return True if a matching exposure is found and set, false otherwise.
692 * @warning This only works if the flat frames were captured in the same live session.
693 * If the flat frames were captured in another session (i.e. Ekos restarted), then all automatic exposure
694 * calculation results are discarded since Ekos does not save this information to the sequene file.
695 * Possible solution is to write to a local config file to keep this information persist between sessions.
696 */
697 bool setDarkFlatExposure(SequenceJob *job);
698
699 /**
700 * @brief checkSeqBoundary Determine the next file number sequence.
701 * That is, if we have file1.png and file2.png, then the next
702 * sequence should be file3.png.
703 */
704 void checkSeqBoundary();
705 /**
706 * @brief isModelinDSLRInfo Check if the DSLR model is already known
707 */
708 bool isModelinDSLRInfo(const QString &model);
709
710 // ////////////////////////////////////////////////////////////////////
711 // Helper functions
712 // ////////////////////////////////////////////////////////////////////
713
714 /**
715 * @brief activeJobID Determine the ID of the currently active job
716 */
717 int activeJobID();
718
719 /**
720 * @brief pPendingJobCount Returns the number of pending uncompleted jobs in the sequence queue.
721 */
722 int pendingJobCount();
723
724 /**
725 * @brief getJobState Returns the job state (Idle, In Progress, Error, Aborted, Complete)
726 * @param id job number. Job IDs start from 0 to N-1.
727 */
728
729 QString jobState(int id);
730
731 /**
732 * @brief jobFilterName Returns the job filter name.
733 * @param id job number. Job IDs start from 0 to N-1.
734 */
735 QString jobFilterName(int id);
736
737 /**
738 * @param id job number. Job IDs start from 0 to N-1.
739 * @return Returns the frame type (light, dark, ...) of the job.
740 */
741 CCDFrameType jobFrameType(int id);
742
743 /**
744 * @brief jobImageProgress Returns The number of images completed capture in the job.
745 * @param id job number. Job IDs start from 0 to N-1.
746 */
747 int jobImageProgress(int id);
748
749 /**
750 * @param id job number. Job IDs start from 0 to N-1.
751 * @return Returns the total number of images to capture in the job.
752 */
753 int jobImageCount(int id);
754
755 /**
756 * @param id job number. Job IDs start from 0 to N-1.
757 * @return Returns the number of seconds left in an exposure operation.
758 */
759 double jobExposureProgress(int id);
760
761 /**
762 * @param id job number. Job IDs start from 0 to N-1.
763 * @return Returns the total requested exposure duration in the job.
764 */
765 double jobExposureDuration(int id);
766
767 /**
768 * @return Returns the percentage of completed captures in all active jobs
769 */
770 double progressPercentage();
771
772 /**
773 * @return Returns true if there's an active job and it is a preview job.
774 */
775 bool isActiveJobPreview();
776
777 /**
778 * @return Returns time left in seconds until active job is estimated to be complete.
779 */
780 int activeJobRemainingTime();
781
782 /**
783 * @return Returns overall time left in seconds until all jobs are estimated to be complete
784 */
785 int overallRemainingTime();
786
787 /**
788 * Returns the overall sequence queue status. If there are no jobs pending, it returns "Invalid". If all jobs are idle, it returns "Idle". If all jobs are complete, it returns "Complete". If one or more jobs are aborted
789 * it returns "Aborted" unless it was temporarily aborted due to guiding deviations, then it would return "Suspended". If one or more jobs have errors, it returns "Error". If any jobs is under progress, returns "Running".
790 */
791 QString sequenceQueueStatus();
792
793 /**
794 * @brief getCalibrationSettings Get Calibration settings
795 * @return settings as JSON object
796 */
797 QJsonObject calibrationSettings();
798
799 /**
800 * @brief setCalibrationSettings Set Calibration settings
801 * @param settings as JSON object
802 */
803 void setCalibrationSettings(const QJsonObject &settings);
804
805 /**
806 * @brief hasCapturedFramesMap Check if at least one frame has been recorded
807 */
808 bool hasCapturedFramesMap()
809 {
810 return m_capturedFramesMap.count() > 0;
811 }
812 /**
813 * @brief addCapturedFrame Record a captured frame
814 */
815 void addCapturedFrame(const QString &signature);
816 /**
817 * @brief removeCapturedFrameCount Reduce the frame counts for the given signature
818 */
819 void removeCapturedFrameCount(const QString &signature, uint16_t count);
820 /**
821 * @brief clearCapturedFramesMap Clear the map of captured frames counts
822 */
823 void clearCapturedFramesMap()
824 {
825 m_capturedFramesMap.clear();
826 }
827
828 bool isCaptureRunning()
829 {
830 return (m_CaptureState == CAPTURE_PROGRESS || m_CaptureState == CAPTURE_CAPTURING || m_CaptureState == CAPTURE_PAUSE_PLANNED ||
831 m_CaptureState == CAPTURE_IMAGE_RECEIVED || m_CaptureState == CAPTURE_CHANGING_FILTER || m_CaptureState == CAPTURE_CALIBRATING);
832 }
833
834 bool isCaptureStopped()
835 {
836 return (m_CaptureState == CAPTURE_IDLE || m_CaptureState == CAPTURE_ABORTED || m_CaptureState == CAPTURE_SUSPENDED);
837 }
838
839 bool isCapturePausing()
840 {
841 return (m_CaptureState == CAPTURE_PAUSE_PLANNED || m_CaptureState == CAPTURE_PAUSED);
842 }
843
844 ScriptTypes captureScriptType() const
845 {
846 return m_CaptureScriptType;
847 }
848 void setCaptureScriptType(ScriptTypes value)
849 {
850 m_CaptureScriptType = value;
851 }
852 double targetADU() const
853 {
854 return m_targetADU;
855 }
856 void setTargetADU(double value)
857 {
858 m_targetADU = value;
859 }
860 double targetADUTolerance() const
861 {
862 return m_TargetADUTolerance;
863 }
864 void setTargetADUTolerance(double value)
865 {
866 m_TargetADUTolerance = value;
867 }
868 bool skyFlat() const
869 {
870 return m_skyFlat;
871 }
872 void setSkyFlat(bool enabled)
873 {
874 m_skyFlat = enabled;
875 }
876 SkyPoint &wallCoord()
877 {
878 return m_wallCoord;
879 }
880 void setWallCoord(SkyPoint value)
881 {
882 m_wallCoord = value;
883 }
884 const DoubleRange &exposureRange() const
885 {
886 return m_ExposureRange;
887 }
888 void setExposureRange(double min, double max)
889 {
890 m_ExposureRange.min = min;
891 m_ExposureRange.max = max;
892 }
893
895 {
896 return m_frameSettings;
897 }
898 void setFrameSettings(const QMap<ISD::CameraChip *, QVariantMap> &value)
899 {
900 m_frameSettings = value;
901 }
902
903 FlatFieldDuration flatFieldDuration() const
904 {
905 return m_flatFieldDuration;
906 }
907 void setFlatFieldDuration(FlatFieldDuration value)
908 {
909 m_flatFieldDuration = value;
910 }
911
912 uint32_t calibrationPreAction() const
913 {
914 return m_CalibrationPreAction;
915 }
916 void setCalibrationPreAction(uint32_t value)
917 {
918 m_CalibrationPreAction = value;
919 }
920
921 QList<QMap<QString, QVariant> > &DSLRInfos()
922 {
923 return m_DSLRInfos;
924 }
925
926 const QString &opticalTrain() const
927 {
928 return m_opticalTrain;
929 }
930 void setOpticalTrain(const QString &newOpticalTrain)
931 {
932 m_opticalTrain = newOpticalTrain;
933 }
934
935 void setPrepareComplete(bool success);
936
937signals:
938 // controls for capture execution
939 void captureBusy(bool busy);
940 void startCapture();
941 void abortCapture();
942 void suspendCapture();
943 void executeActiveJob();
944 void updatePrepareState(CaptureState state);
945 void captureStarted(CaptureResult rc);
946 // request the execution of an action orchestrated by the capture module
947 void requestAction(CaptureWorkflowActionType action);
948 // mount meridian flip status update event
949 void newMeridianFlipStage(MeridianFlipState::MFStage status);
950 // meridian flip started
951 void meridianFlipStarted();
952 // new guiding deviation measured
953 void newGuiderDrift(double deviation_rms);
954 // guiding should be started after a successful meridian flip
955 void guideAfterMeridianFlip();
956 // reset non guided dithering properties
957 void resetNonGuidedDither();
958 // new capture state
959 void newStatus(CaptureState status);
960 // forward new focus status
961 void newFocusStatus(FocusState status);
962 // forward new adaptive focus status
963 void newAdaptiveFocusStatus(bool success);
964 // check focusing is necessary for the given HFR
965 void checkFocus(double hfr);
966 // run Autofocus
967 void runAutoFocus(AutofocusReason autofocusReason, const QString &reasonInfo);
968 // reset the focus frame
969 void resetFocusFrame();
970 // signal focus module to perform adaptive focus
971 void adaptiveFocus();
972 // abort capturing if fast exposure mode is used
973 void abortFastExposure();
974 // new HFR focus limit calculated
975 void newLimitFocusHFR(double hfr);
976 // Select the filter at the given position
977 void newFilterPosition(int targetFilterPosition, FilterManager::FilterPolicy policy = FilterManager::ALL_POLICIES);
978 // capture sequence status changes
979 void sequenceChanged(const QJsonArray &sequence);
980 // new log text for the module log window
981 void newLog(const QString &text);
982
983 private:
984 // initialize the class
985 void init();
986
987 // Container for the list of SequenceJobs.
988 QSharedPointer<SequenceQueue> m_sequenceQueue;
989 // Currently active sequence job.
990 SequenceJob *m_activeJob { nullptr };
991 // pointer to the image data
992 QSharedPointer<FITSData> m_ImageData;
993 // CCD Chip frame settings
995 // DSLR Infos
997
998 // current optical train
999 QString m_opticalTrain;
1000 // current filter position
1001 // TODO: check why we have both currentFilterID and this, seems redundant
1002 int m_CurrentFilterPosition { -1 };
1003 // current filter name matching the filter position
1004 QString m_CurrentFilterName { "--" };
1005 // holds the filter name used for focusing or "--" if the current one is used
1006 QString m_CurrentFocusFilterName { "--" };
1007 // Captured Frames Map
1008 CapturedFramesMap m_capturedFramesMap;
1009 // are we in the starting phase of capturing?
1010 bool m_StartingCapture { true };
1011 // Does the camera have a dedicated guiding chip?
1012 bool m_useGuideHead { false };
1013 // Guide Deviation
1014 bool m_GuidingDeviationDetected { false };
1015 // suspend guiding when downloading a captured image
1016 bool m_SuspendGuidingOnDownload { false };
1017 // Guiding spikes
1018 uint m_SpikesDetected { 0 };
1019 // Timer for guiding recovery
1020 QTimer m_guideDeviationTimer;
1021 // Capture timeout timer
1022 QTimer m_captureTimeout;
1023 uint8_t m_CaptureTimeoutCounter { 0 };
1024 uint8_t m_DeviceRestartCounter { 0 };
1025 // time left of the current exposure
1026 QTime m_imageCountDown;
1027 double m_lastRemainingFrameTimeMS;
1028 // Timer for delay before capturing an image
1029 // @see CaptureProcess::captureImageWithDelay()
1030 QTimer m_captureDelayTimer;
1031 // time left for the current sequence
1032 QTime m_sequenceCountDown;
1033 // timer for updating the download progress
1034 QTimer m_downloadProgressTimer;
1035 // timer measuring the download time
1036 QElapsedTimer m_DownloadTimer;
1037 // sum over all recorded list of download times
1038 double totalDownloadTime {0};
1039 // number of downloaded frames
1040 uint downloadsCounter {0};
1041 // current placeholder path
1042 PlaceholderPath m_currentPlaceholderPath;
1043 // next capture sequence ID
1044 int m_nextSequenceID { 0 };
1045 // how to continue after pausing
1046 CaptureContinueAction m_ContinueAction { CAPTURE_CONTINUE_ACTION_NONE };
1047 // name of the observer
1048 QString m_ObserverName;
1049 // ignore already captured files
1050 bool m_ignoreJobProgress { true };
1051 // Fast Exposure
1052 bool m_RememberFastExposure {false};
1053 // Set dirty bit to indicate sequence queue file was modified and needs saving.
1054 bool m_Dirty { false };
1055 // Capturing (incl. preparation actions) is active
1056 bool m_Busy { false };
1057 // preview loop running
1058 bool m_Looping { false };
1059 // script type of the currently running script
1060 ScriptTypes m_CaptureScriptType { SCRIPT_N };
1061 // Flat field automation
1062 double m_TargetADUTolerance { 1000 };
1063 double m_targetADU { 0 };
1064 bool m_skyFlat { false };
1065 SkyPoint m_wallCoord;
1066 FlatFieldDuration m_flatFieldDuration { DURATION_MANUAL };
1067 uint32_t m_CalibrationPreAction { CAPTURE_PREACTION_NONE };
1068 bool m_lightBoxLightEnabled { false };
1069 // Allowed camera exposure times
1070 DoubleRange m_ExposureRange;
1071 // Misc
1072 QJsonArray m_SequenceArray;
1073
1074 // ////////////////////////////////////////////////////////////////////
1075 // device states
1076 // ////////////////////////////////////////////////////////////////////
1077 CaptureState m_CaptureState { CAPTURE_IDLE };
1078 FocusState m_FocusState { FOCUS_IDLE };
1079 GuideState m_GuideState { GUIDE_IDLE };
1080 IPState m_DitheringState {IPS_IDLE};
1081 AlignState m_AlignState { ALIGN_IDLE };
1082 FilterState m_FilterManagerState { FILTER_IDLE };
1083 LightState m_lightBoxLightState { CAP_LIGHT_UNKNOWN };
1084 CapState m_dustCapState { CAP_UNKNOWN };
1085 ISD::Mount::Status m_scopeState { ISD::Mount::MOUNT_IDLE };
1086 ISD::Mount::PierSide m_pierSide { ISD::Mount::PIER_UNKNOWN };
1087 ISD::ParkStatus m_scopeParkState { ISD::PARK_UNKNOWN };
1088 ISD::Dome::Status m_domeState { ISD::Dome::DOME_IDLE };
1089
1090 // ////////////////////////////////////////////////////////////////////
1091 // counters
1092 // ////////////////////////////////////////////////////////////////////
1093 // Number of alignment retries
1094 int m_AlignmentRetries { 0 };
1095 // How many images to capture before dithering operation is executed?
1096 uint m_ditherCounter { 0 };
1097
1098 /* Refocusing */
1099 QSharedPointer<RefocusState> m_refocusState;
1100 /* Meridian Flip */
1102
1103 /**
1104 * @brief Add log message
1105 */
1106 void appendLogText(const QString &message);
1107};
1108
1109}; // namespace
Sequence Job is a container for the details required to capture a series of images.
The sky coordinates of a point in the sky.
Definition skypoint.h:45
Ekos is an advanced Astrophotography tool for Linux.
Definition align.cpp:83
QMap< QString, uint16_t > CapturedFramesMap
mapping signature --> frames count
@ ALIGN_IDLE
No ongoing operations.
Definition ekos.h:146
@ CAPTURE_PROGRESS
Definition ekos.h:94
@ CAPTURE_PAUSE_PLANNED
Definition ekos.h:96
@ CAPTURE_PAUSED
Definition ekos.h:97
@ CAPTURE_IMAGE_RECEIVED
Definition ekos.h:101
@ CAPTURE_SUSPENDED
Definition ekos.h:98
@ CAPTURE_ABORTED
Definition ekos.h:99
@ CAPTURE_CAPTURING
Definition ekos.h:95
@ CAPTURE_CALIBRATING
Definition ekos.h:110
@ CAPTURE_CHANGING_FILTER
Definition ekos.h:105
@ CAPTURE_IDLE
Definition ekos.h:93
void clear()
size_type count() const const
Q_OBJECTQ_OBJECT
QObject * parent() const const
QTime addMSecs(int ms) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Nov 29 2024 11:57:47 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.