File indexing completed on 2024-04-28 03:43:09
0001 /* 0002 SPDX-FileCopyrightText: 2022 Toni Schriber 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 /****************************************************************************************************** 0008 * Angle calculations are based on position measurements of 0009 * - Rotator angle in "Circular Angle (A)" mode (0 <> 359.99° CCW) 0010 * - Camera offset angle & Camera position angle in "Position Angle (PA)" mode (180 <> -179.99° CCW) 0011 * This leads to the following calculations: 0012 * - Camera PA = calcCameraAngel(Rotator A) 0013 * - Rotator A = calcRotatorAngle(Camera PA) 0014 * - Camera offset PA = calcOffsetAngle(Rotator A, Camera PA) 0015 *******************************************************************************************************/ 0016 0017 #include "rotatorutils.h" 0018 #include "Options.h" 0019 0020 #include "opticaltrainmanager.h" 0021 0022 #include <indicom.h> 0023 #include <basedevice.h> 0024 #include <cmath> 0025 0026 RotatorUtils * RotatorUtils::m_Instance = nullptr; 0027 0028 RotatorUtils * RotatorUtils::Instance() 0029 { 0030 if (m_Instance) 0031 return m_Instance; 0032 0033 m_Instance = new RotatorUtils(); 0034 return m_Instance; 0035 } 0036 0037 void RotatorUtils::release() 0038 { 0039 delete (m_Instance); 0040 m_Instance = nullptr; 0041 } 0042 0043 RotatorUtils::RotatorUtils() {} 0044 0045 RotatorUtils::~RotatorUtils() {} 0046 0047 void RotatorUtils::initRotatorUtils(const QString &train) 0048 { 0049 m_Offset = Options::pAOffset(); 0050 m_Mount = Ekos::OpticalTrainManager::Instance()->getMount(train); 0051 0052 if (m_Mount) 0053 { 0054 connect(m_Mount, &ISD::Mount::pierSideChanged, this, [this] (ISD::Mount::PierSide Side) 0055 { 0056 m_flippedMount = (Side != m_CalPierside); 0057 emit changedPierside(Side); 0058 }); 0059 } 0060 } 0061 0062 double RotatorUtils::calcRotatorAngle(double PositionAngle) 0063 { 0064 if (m_flippedMount) 0065 { 0066 PositionAngle += 180; 0067 } 0068 return KSUtils::range360(PositionAngle - m_Offset); 0069 } 0070 0071 double RotatorUtils::calcCameraAngle(double RotatorAngle, bool flippedImage) 0072 { 0073 double PositionAngle = 0; 0074 if (RotatorAngle > 180) 0075 { 0076 PositionAngle = (RotatorAngle - 360) + m_Offset; 0077 } 0078 else 0079 { 0080 PositionAngle = RotatorAngle + m_Offset; 0081 } 0082 if (!m_flippedMount != !flippedImage) // XOR 0083 { 0084 if (PositionAngle > 0) 0085 { 0086 PositionAngle -= 180; 0087 } 0088 else 0089 { 0090 PositionAngle += 180; 0091 } 0092 0093 } 0094 return KSUtils::rangePA(PositionAngle); 0095 } 0096 0097 double RotatorUtils::calcOffsetAngle(double RotatorAngle, double PositionAngle) 0098 { 0099 double OffsetAngle = 0; 0100 if (RotatorAngle > 180) 0101 { 0102 OffsetAngle = PositionAngle - (RotatorAngle - 360); 0103 } 0104 else 0105 { 0106 OffsetAngle = PositionAngle - RotatorAngle; 0107 } 0108 if (m_flippedMount) 0109 { 0110 OffsetAngle -= 180; 0111 } 0112 return KSUtils::rangePA(OffsetAngle); 0113 } 0114 0115 void RotatorUtils::updateOffset(double Angle) 0116 { 0117 m_Offset = Angle; 0118 Options::setPAOffset(Angle); 0119 } 0120 0121 ISD::Mount::PierSide RotatorUtils::getMountPierside() 0122 { 0123 return(m_Mount->pierSide()); 0124 } 0125 0126 void RotatorUtils::setImagePierside(ISD::Mount::PierSide ImgPierside) 0127 { 0128 m_ImgPierside = ImgPierside; 0129 } 0130 0131 bool RotatorUtils::checkImageFlip() 0132 { 0133 bool flipped = false; 0134 0135 if (m_ImgPierside != ISD::Mount::PIER_UNKNOWN) 0136 if (!m_flippedMount != (m_ImgPierside == m_CalPierside)) // XOR 0137 flipped = true; 0138 return flipped; 0139 } 0140 0141 double RotatorUtils::DiffPA(double diff) 0142 { 0143 if (diff > 180) 0144 return (360 - diff); 0145 else 0146 return diff; 0147 } 0148 0149 void RotatorUtils::initTimeFrame(const double EndAngle) 0150 { 0151 m_EndAngle = EndAngle; 0152 m_initParameter = true; 0153 m_CCW = true; 0154 } 0155 0156 int RotatorUtils::calcTimeFrame(const double CurrentAngle) 0157 { 0158 m_CurrentTime = QTime::currentTime(); 0159 m_DeltaTime = m_StartTime.secsTo(m_CurrentTime); 0160 m_TimeFrame = 0; 0161 if (m_DeltaTime >= 1) 0162 { 0163 if (m_initParameter) 0164 { 0165 m_DeltaAngle = CurrentAngle + m_ShiftAngle; 0166 // Moving CCW or positive 0167 if (m_DeltaAngle >= 360) 0168 { 0169 if (m_DiffAngle < 0) 0170 m_DiffAngle = (360 + m_DiffAngle); 0171 } 0172 else // Moving CW or negative 0173 { 0174 if (m_DiffAngle > 0) 0175 m_DiffAngle = (360 - m_DiffAngle); 0176 m_CCW = false; 0177 } 0178 m_initParameter = false; 0179 } 0180 m_DeltaAngle = KSUtils::range360(CurrentAngle + m_ShiftAngle); 0181 if (!m_CCW) 0182 m_DeltaAngle = 360 - m_DeltaAngle; 0183 0184 m_TimeFrame = fabs(m_DiffAngle) / fabs(m_DeltaAngle/m_DeltaTime); 0185 } 0186 return m_TimeFrame; 0187 } 0188 0189 void RotatorUtils::startTimeFrame(const double StartAngle) 0190 { 0191 m_StartAngle = StartAngle; 0192 m_StartTime = QTime::currentTime(); 0193 m_ShiftAngle = 360 - m_StartAngle; 0194 m_DiffAngle = m_EndAngle - m_StartAngle; 0195 }