File indexing completed on 2024-05-05 15:55:06
0001 /* 0002 SPDX-FileCopyrightText: 2023 John Evans <john.e.evans.email@googlemail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #pragma once 0008 0009 #include "focus.h" 0010 0011 namespace Ekos 0012 { 0013 0014 // AdaptiveFocus is setup as a friend class of Focus because it is tightly coupled to Focus relying on many 0015 // members of Focus, both variables and functions. 0016 // 0017 // adaptiveFocus is signalled (by capture). Check each adaptive dimension (temp, alt) to determine whether a focus move is required. 0018 // Total the movements from each dimension and, if required, adjust focus. 0019 // 0020 // Use the adaptive focus parameters associated with the current filter unless that has a lock filter, in which case use the lock filter. 0021 // Use the last good autofocus run as the reference that provides the focus position, temperature 0022 // and altitude. Adaptive focus then calculates the proposed position based on the current temperature and altitude 0023 // and calculates how to move from the current position to the proposed position - note there may be an overscan involved. 0024 // 0025 // To keep track of the movements the data are passed to Analyze which allows the user to review everything. Analyze displays the 0026 // deltas from the previous adaptive focus run for temperature and altitude to the next adaptive focus run. 0027 // 0028 // Calculations are performed as doubles and rounded to int for the final movement. 0029 // 0030 // A complication is that not all focusers move exactly to the requested position - 'bad boy' focusers. E.g. a request to 0031 // goto position X results in the focuser moving to X, X +/- 1 or X +/- 2. These position errors need to be managed. There 0032 // are 2 aspects to this; before an Adaptive Focus iteration, the focuser may be "off" where it should be. This could be 0033 // because the focuser is a "bad boy" so it moved to the correct position +/- 1 or 2 ticks; this is the Last Pos Error. 0034 // Adaptive Focus will attempt to correct this error even if there are no temperature or altitude changes (providing the 0035 // movement is above the user defined minimum movement. 0036 // When the Adaptive Focus iteration runs, the focuser may again experience a Pos Error. 0037 // These Position Errors are passed to Analyze to breakdown each focuser movement. 0038 // 0039 // Proposed Position = Ref Position (from last Autofocus) + adjustment for temperature + adjustment for altitude 0040 // 0041 // Accounting since last Adaptive Focus 0042 // Last Pos Error Reversal = Last Iteration Proposed Move - Focuser position at start of Adaptive Focus iteration 0043 // This Pos Error = Focuser position at end of Adaptive Focus iteration - Proposed Move 0044 // End Position = Start Position + temperature adjustment + altitude adjustment + Last Pos Error Reversal + This Pos Error 0045 // 0046 // Example: Last Autofocus Run, Pos=100 0C 70Alt. Parameters: 10ticks/Degree C, 1tick/Degree Alt 0047 // 1st Adaptive Focus: 0.5C 71Alt 0048 // Proposed Position = 100 + 5 + 1 = 106 0049 // Actual Position = 105 (focuser movement error) 0050 // Accounting: Start Position = 100 0051 // Temperature Adjustment = 5 0052 // Altitude Adjustment = 1 0053 // Last Pos Error Reversal = 0 0054 // This Pos Error = -1 0055 // End Position = 100 + 5 + 1 + 0 - 1 = 105 0056 // 0057 // 2nd Adaptive Focus: 0.75C 72Alt 0058 // Proposed Position = 100 + 7.5 + 2 = 110 0059 // Actual Position = 112 (focuser movement error) 0060 // Accounting: Start Position = 105 0061 // Temperature Adjustment = 2.5 0062 // Altitude Adjustment = 1 0063 // Last Pos Error Reversal = 1 0064 // This Pos Error = 2 0065 // End Position = 100 + 5 + 1 + 0 - 1 = 112 0066 // 0067 // 3rd Adaptive Focus: 0.25C 72Alt 0068 // Proposed Position = 100 + 2.5 + 2 = 105 0069 // Actual Position = 105 (no focuser movement error) 0070 // Accounting: Start Position = 112 0071 // Temperature Adjustment = -5 0072 // Altitude Adjustment = 0 0073 // Last Pos Error Reversal = -2 0074 // This Pos Error = 0075 // End Position = 100 + 5 + 1 + 0 - 1 = 105 0076 // 0077 // Adaptive Focus moves the focuser between Autofocus runs. 0078 // Adapt Start Pos adjusts the start position of an autofocus run based on Adaptive Focus settings 0079 // The start position uses the last successful AF run for the active filter and adapts that position 0080 // based on the temperature and altitude delta between now and when the last successful AF run happened 0081 // Only enabled for LINEAR 1 PASS 0082 0083 class AdaptiveFocus 0084 { 0085 public: 0086 0087 AdaptiveFocus(Focus* _focus); 0088 ~AdaptiveFocus(); 0089 0090 /** 0091 * @brief runAdaptiveFocus runs the next iteration of Adaptive Focus 0092 * @param current focuser position 0093 * @param active filter 0094 */ 0095 void runAdaptiveFocus(const int currentPosition, const QString &filter); 0096 0097 /** 0098 * @brief Perform admin functions on Adaptive Focus to inform other modules of 0099 * @param current focuser position 0100 * @param success (or not) 0101 * @param focuserMoved (or not) 0102 */ 0103 void adaptiveFocusAdmin(const int currentPosition, const bool success, const bool focuserMoved); 0104 0105 /** 0106 * @brief Reset the variables used by Adaptive Focus 0107 */ 0108 void resetAdaptiveFocusCounters(); 0109 0110 /** 0111 * @brief Return whether Adaptive Focus is running 0112 * @return inAdaptiveFocus 0113 */ 0114 bool inAdaptiveFocus() 0115 { 0116 return m_inAdaptiveFocus; 0117 } 0118 0119 /** 0120 * @brief Set the value of inAdaptiveFocus 0121 * @param value 0122 */ 0123 void setInAdaptiveFocus(bool value); 0124 0125 /** 0126 * @brief adapt the start position based on temperature and altitude 0127 * @param position is the unadapted focuser position 0128 * @param AFfilter is the filter to run autofocus on 0129 * @return adapted start position 0130 */ 0131 int adaptStartPosition(int position, QString &AFfilter); 0132 0133 private: 0134 0135 /** 0136 * @brief Get the Adaptive Filter to use 0137 * @param active filter 0138 * @return filter 0139 */ 0140 QString getAdaptiveFilter(const QString filter); 0141 0142 /** 0143 * @brief Get filter offset between active and adaptive filters 0144 * @param Active filter 0145 * @param Adaptive filter 0146 * @return offset 0147 */ 0148 int getAdaptiveFilterOffset(const QString &activeFilter, const QString &adaptiveFilter); 0149 0150 Focus *m_focus { nullptr }; 0151 0152 // Focuser is processing an adaptive focus request 0153 bool m_inAdaptiveFocus { false }; 0154 0155 // m_ThisAdaptiveFocus* variables hold values for the current Adaptive Focus run 0156 int m_ThisAdaptiveFocusStartPos { INVALID_VALUE }; 0157 double m_ThisAdaptiveFocusTemperature { INVALID_VALUE }; 0158 double m_ThisAdaptiveFocusAlt { INVALID_VALUE }; 0159 double m_ThisAdaptiveFocusTempTicks { INVALID_VALUE }; 0160 double m_ThisAdaptiveFocusAltTicks { INVALID_VALUE }; 0161 int m_ThisAdaptiveFocusRoundingError { 0 }; 0162 // m_LastAdaptiveFocus* variables hold values for the previous Adaptive Focus run 0163 QString m_LastAdaptiveFilter { NULL_FILTER }; 0164 double m_LastAdaptiveFocusTemperature { INVALID_VALUE }; 0165 double m_LastAdaptiveFocusAlt { INVALID_VALUE }; 0166 int m_LastAdaptiveFocusPosErrorReversal { INVALID_VALUE }; 0167 0168 int m_AdaptiveFocusPositionReq { INVALID_VALUE }; 0169 int m_AdaptiveTotalMove { 0 }; 0170 }; 0171 0172 }