File indexing completed on 2024-04-28 03:43:17

0001 /*  Ekos state machine for refocusing
0002     SPDX-FileCopyrightText: 2022 Wolfgang Reissenberger <sterne-jaeger@openfuture.de>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #pragma once
0008 
0009 #include <QObject>
0010 #include <QElapsedTimer>
0011 
0012 #include "Options.h"
0013 
0014 namespace Ekos
0015 {
0016 
0017 class RefocusState : public QObject
0018 {
0019         Q_OBJECT
0020     public:
0021         typedef enum
0022         {
0023             REFOCUS_NONE,         /* no need to refocus                                 */
0024             REFOCUS_HFR,          /* refocusing due to HFR (in sequence) value          */
0025             REFOCUS_ADAPTIVE,     /* adaptive refocusing (in sequence)                  */
0026             REFOCUS_TEMPERATURE,  /* refocusing due to temperature change               */
0027             REFOCUS_TIME_ELAPSED, /* refocusing due to elapsed time since last focusing */
0028             REFOCUS_POST_MF       /* refocusing after a completed meridian flip         */
0029         } RefocusReason;
0030 
0031         explicit RefocusState(QObject *parent = nullptr): QObject{parent} {}
0032 
0033         /**
0034          * @brief Check if focusing is necessary:
0035          * 1. time limit based
0036          * 2. temperature based
0037          * 3. HFR based in sequence
0038          * 4. post meridian flip         *
0039          */
0040         RefocusReason checkFocusRequired();
0041 
0042         /**
0043          * @brief Start the timer triggering refosing after the configured time.
0044          * @param forced if true restart the timer even if it is already running
0045          */
0046         void startRefocusTimer(bool forced = false);
0047 
0048         const QElapsedTimer &getRefocusEveryNTimer() const
0049         {
0050             return m_refocusEveryNTimer;
0051         }
0052         qint64 restartRefocusEveryNTimer()
0053         {
0054             return m_refocusEveryNTimer.restart();
0055         }
0056 
0057         int getRefocusEveryNTimerElapsedSec();
0058 
0059         double getFocusHFR() const
0060         {
0061             return m_focusHFR;
0062         }
0063         void setFocusHFR(double newFocusHFR, bool inAutofocus)
0064         {
0065             m_focusHFR = newFocusHFR;
0066             m_focusHFRInAutofocus = inAutofocus;
0067         }
0068         bool getFocusHFRInAutofocus() const
0069         {
0070             return m_focusHFRInAutofocus;
0071         }
0072 
0073         /**
0074          * @brief Is the temperature or HFR based autofocus ready to start? This flag ensures that
0075          *        focusing has run at least once before the autofocus is triggered by the configured parameters.
0076          * @return true if focusing has been executed once
0077          */
0078         bool isAutoFocusReady() const
0079         {
0080             return m_AutoFocusReady;
0081         }
0082         void setAutoFocusReady(bool value)
0083         {
0084             m_AutoFocusReady = value;
0085         }
0086 
0087         bool isInSequenceFocus() const
0088         {
0089             return m_InSequenceFocus;
0090         }
0091         void setInSequenceFocus(bool value)
0092         {
0093             m_InSequenceFocus = value;
0094         }
0095 
0096         bool isAdaptiveFocusDone() const
0097         {
0098             return m_AdaptiveFocusDone;
0099         }
0100         void setAdaptiveFocusDone(bool value)
0101         {
0102             m_AdaptiveFocusDone = value;
0103         }
0104 
0105         uint getInSequenceFocusCounter() const
0106         {
0107             return inSequenceFocusCounter;
0108         }
0109         void decreaseInSequenceFocusCounter();
0110         void setInSequenceFocusCounter(uint value)
0111         {
0112             inSequenceFocusCounter = value;
0113         }
0114         void resetInSequenceFocusCounter()
0115         {
0116             inSequenceFocusCounter = Options::inSequenceCheckFrames();
0117         }
0118 
0119         double getFocusTemperatureDelta() const
0120         {
0121             return m_focusTemperatureDelta;
0122         }
0123         void setFocusTemperatureDelta(double value)
0124         {
0125             m_focusTemperatureDelta = value;
0126         }
0127 
0128         bool isRefocusAfterMeridianFlip() const
0129         {
0130             return m_refocusAfterMeridianFlip;
0131         }
0132         void setRefocusAfterMeridianFlip(bool value)
0133         {
0134             m_refocusAfterMeridianFlip = value;
0135         }
0136 
0137         bool isRefocusing() const
0138         {
0139             return m_refocusing;
0140         }
0141         void setRefocusing(bool value)
0142         {
0143             m_refocusing = value;
0144         }
0145 
0146         const QMap<QString, QList<double> > &getHFRMap() const
0147         {
0148             return m_HFRMap;
0149         }
0150         void setHFRMap(const QMap<QString, QList<double>> &newHFRMap)
0151         {
0152             m_HFRMap = newHFRMap;
0153         }
0154 
0155         /**
0156          * @brief Add the current HFR value measured for a frame with given filter
0157          */
0158         void addHFRValue(const QString &filter);
0159 
0160     signals:
0161         // new log text for the module log window
0162         void newLog(const QString &text);
0163 
0164 
0165     private:
0166         // HFR value as received from the Ekos focus module
0167         double m_focusHFR { 0 };
0168         // Whether m_focusHFR was taken during Autofocus
0169         bool m_focusHFRInAutofocus { false };
0170         // used to determine when next force refocus should occur
0171         QElapsedTimer m_refocusEveryNTimer;
0172         // Ready for running autofocus (HFR or temperature based)
0173         bool m_AutoFocusReady { false };
0174         // focusing during the capture sequence
0175         bool m_InSequenceFocus { false };
0176         // adaptive focusing complete
0177         bool m_AdaptiveFocusDone { false };
0178         // counter how many captures to be executed until focusing is triggered
0179         uint inSequenceFocusCounter { 0 };
0180         // Temperature change since last focusing
0181         double m_focusTemperatureDelta { 0 };
0182         // set to true at meridian flip to request refocus
0183         bool m_refocusAfterMeridianFlip { false };
0184         // map filter name --> list of HFR values
0185         QMap<QString, QList<double>> m_HFRMap;
0186 
0187 
0188         // Refocusing running
0189         bool m_refocusing { false };
0190 
0191 
0192         /**
0193          * @brief Add log message
0194          */
0195         void appendLogText(const QString &message);
0196 
0197 };
0198 
0199 }; // namespace