Kstars

rotatorsettings.cpp
1/*
2 SPDX-FileCopyrightText: 2017 Jasem Mutlaq <mutlaqja@ikarustech.com>
3 2022 Toni Schriber
4
5 SPDX-License-Identifier: GPL-2.0-or-later
6*/
7
8/******************************************************************************************************
9* In 'rotatorGauge' and 'paGauge' all angles are displayed in viewing direction and positiv CCW.
10*******************************************************************************************************/
11
12#include "rotatorsettings.h"
13#include "Options.h"
14#include "fov.h"
15#include "kstarsdata.h"
16#include "ekos/manager.h"
17#include "indi/indirotator.h"
18#include <indicom.h>
19#include <basedevice.h>
20#include <cmath>
21#include "capture.h"
22#include "ekos/align/align.h"
23#include "ekos/capture/capturedeviceadaptor.h"
24#include "ekos/align/opsalign.h"
25#include "ekos/auxiliary/rotatorutils.h"
26
27#include "ekos_capture_debug.h"
28
29RotatorSettings::RotatorSettings(QWidget *parent) : QDialog(parent)
30{
31 setupUi(this);
32
33 connect(this, &RotatorSettings::newLog, Ekos::Manager::Instance()->captureModule(), &Ekos::Capture::appendLogText);
34 connect(RotatorUtils::Instance(), &RotatorUtils::changedPierside, this, &RotatorSettings::updateGaugeZeroPos);
35 connect(FlipPolicy, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &RotatorSettings::setFlipPolicy);
36 connect(AlignOptions, &QPushButton::clicked, this, &RotatorSettings::showAlignOptions);
37
38 // -- Parameter -> ui file
39
40 // -- Camera position angle
41 CameraPA->setKeyboardTracking(false);
42 connect(CameraPA, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, [ = ](double PAngle)
43 {
44 double RAngle = RotatorUtils::Instance()->calcRotatorAngle(PAngle);
45 RotatorAngle->setValue(RAngle);
46 syncFOV(PAngle);
47 activateRotator(RAngle);
48 CameraPASlider->setSliderPosition(PAngle * 100); // Prevent rounding to integer
49 });
50 connect(CameraPASlider, &QSlider::sliderReleased, this, [this]()
51 {
52 CameraPA->setValue(CameraPASlider->sliderPosition() / 100.0); // Set position angle
53 });
54 connect(CameraPASlider, &QSlider::valueChanged, this, [this](int PAngle100)
55 {
56 double PAngle = PAngle100 / 100;
57 paGauge->setValue(-(PAngle)); // Preview cameraPA in gauge
58 syncFOV(PAngle); // Preview FOV
59 });
60
61 // -- Options
62 // enforceJobPA -> header file
63 connect(reverseDirection, &QCheckBox::toggled, this, [ = ](bool toggled)
64 {
65 commitRotatorDirection(toggled);
66 });
67
68 // Rotator Gauge
69 rotatorGauge->setFormat("R"); // dummy format
70 rotatorGauge->setMinimum(-360); // display in viewing direction
71 rotatorGauge->setMaximum(0);
72
73 // Position Angle Gauge
74 paGauge->setFormat("P"); // dummy format
75 paGauge->setMinimum(-181); // display in viewing direction
76 paGauge->setMaximum(181);
77
78 // Angle Ruler
79 paRuler->plotLayout()->clear();
80 QCPPolarAxisAngular *angularAxis = new QCPPolarAxisAngular(paRuler);
81 angularAxis->removeRadialAxis(angularAxis->radialAxis());
82 QColor TransparentBlack(0, 0, 0, 100);
83 QPen Pen(TransparentBlack, 3);
84 angularAxis->setBasePen(Pen);
85 angularAxis->setTickPen(Pen);
86 angularAxis->setSubTickPen(Pen);
87 angularAxis->setTickLabels(false);
88 angularAxis->setTickLength(10, 10);
89 angularAxis->setSubTickLength(5, 5);
90 paRuler->plotLayout()->addElement(0, 0, angularAxis);
91 paRuler->setBackground(Qt::GlobalColor::transparent); // transparent background part 1
92 paRuler->setAttribute(Qt::WA_OpaquePaintEvent, false); // transparent background part 2
93 angularAxis->grid()->setAngularPen(QPen(Qt::GlobalColor::transparent)); // no grid
94 paRuler->replot();
95
96 // Parameter Interface
97 CameraPA->setMaximum(180.00); // uniqueness of angle (-180 = 180)
98 CameraPA->setMinimum(-179.99);
99 RotatorAngle->setButtonSymbols(QAbstractSpinBox::NoButtons);
100 CameraOffset->setValue(Options::pAOffset());
101 CameraOffset->setButtonSymbols(QAbstractSpinBox::NoButtons);
102 MountPierside->setCurrentIndex(ISD::Mount::PIER_UNKNOWN);
103 MountPierside->setDisabled(true); // only show pierside for information
104}
105
106void RotatorSettings::initRotator(const QString &train, Ekos::CaptureDeviceAdaptor *CaptureDA, ISD::Rotator *device)
107{
108 m_CaptureDA = CaptureDA;
109 RotatorUtils::Instance()->initRotatorUtils(train);
110
111 m_Rotator = device;
112 RotatorName->setText(m_Rotator->getDeviceName());
113 updateFlipPolicy(Options::astrometryFlipRotationAllowed());
114 // Give getState() a second
115 QTimer::singleShot(1000, [ = ]
116 {
117 if (m_CaptureDA->getRotatorAngleState() < IPS_BUSY)
118 {
119 double RAngle = m_CaptureDA->getRotatorAngle();
120 updateRotator(RAngle);
121 updateGaugeZeroPos(RotatorUtils::Instance()->getMountPierside());
122 qCInfo(KSTARS_EKOS_CAPTURE()) << "Rotator Settings: Initial raw angle is" << RAngle << ".";
123 emit newLog(i18n("Initial rotator angle %1° is read in successfully.", RAngle));
124 }
125 else
126 qCWarning(KSTARS_EKOS_CAPTURE()) << "Rotator Settings: Reading initial raw angle failed.";
127 });
128}
129
130void RotatorSettings::updateRotator(double RAngle)
131{
132 RotatorAngle->setValue(RAngle);
133 double PAngle = RotatorUtils::Instance()->calcCameraAngle(RAngle, false);
134 CameraPA->blockSignals(true); // Prevent reaction coupling via user input
135 CameraPA->setValue(PAngle);
136 CameraPA->blockSignals(false);
137 CameraPASlider->setSliderPosition(PAngle * 100); // Prevent rounding to integer
138 updateGauge(RAngle);
139}
140
141void RotatorSettings::updateGauge(double RAngle)
142{
143 rotatorGauge->setValue(-RAngle); // display in viewing direction
144 CurrentRotatorAngle->setText(QString::number(RAngle, 'f', 2));
145 paGauge->setValue(-(RotatorUtils::Instance()->calcCameraAngle(RAngle, false)));
146}
147
148void RotatorSettings::updateGaugeZeroPos(ISD::Mount::PierSide Pierside)
149{
150 double RAngle = 0;
151 if (Pierside == ISD::Mount::PIER_UNKNOWN)
152 MountPierside->setStyleSheet("QComboBox {border: 1px solid red;}");
153 else
154 MountPierside->setStyleSheet("QComboBox {}");
155 MountPierside->setCurrentIndex(Pierside);
156 if (Pierside == ISD::Mount::PIER_WEST)
157 rotatorGauge->setNullPosition(QRoundProgressBar::PositionTop);
158 else if (Pierside == ISD::Mount::PIER_EAST)
159 rotatorGauge->setNullPosition(QRoundProgressBar::PositionBottom);
160 if (Options::astrometryFlipRotationAllowed()) // Preserve rotator raw angle
161 RAngle = RotatorAngle->value();
162 else // Preserve camera position angle
163 {
164 RAngle = RotatorUtils::Instance()->calcRotatorAngle(CameraPA->value());
165 activateRotator(RAngle);
166 }
167 updateGauge(RAngle);
168 updateRotator(RAngle);
169}
170
171void RotatorSettings::setFlipPolicy(const int index)
172{
173 Ekos::OpsAlign::FlipPriority Priority = static_cast<Ekos::OpsAlign::FlipPriority>(index);
174 Ekos::OpsAlign *AlignOptionsModule = Ekos::Manager::Instance()->alignModule()->getAlignOptionsModule();
175 if (AlignOptionsModule)
176 AlignOptionsModule->setFlipPolicy(Priority);
177}
178
179void RotatorSettings::updateFlipPolicy(const bool FlipRotationAllowed)
180{
181 int i = -1;
182 if (FlipRotationAllowed)
183 i = static_cast<int>(Ekos::OpsAlign::FlipPriority::ROTATOR_ANGLE);
184 else
185 i = static_cast<int>(Ekos::OpsAlign::FlipPriority::POSITION_ANGLE);
186 FlipPolicy->blockSignals(true); // Prevent reaction coupling
187 FlipPolicy->setCurrentIndex(i);
188 FlipPolicy->blockSignals(false);
189}
190
191void RotatorSettings::showAlignOptions()
192{
193 KConfigDialog * alignSettings = KConfigDialog::exists("alignsettings");
194 if (alignSettings)
195 {
196 alignSettings->setEnabled(true);
197 alignSettings->show();
198 }
199}
200
201void RotatorSettings::activateRotator(double Angle)
202{
203 m_CaptureDA->setRotatorAngle(Angle);
204}
205
206void RotatorSettings::commitRotatorDirection(bool Reverse)
207{
208 m_CaptureDA->reverseRotator(Reverse);
209}
210
211void RotatorSettings::refresh(double PAngle) // Call from setAlignResults() in Module Capture
212{
213 CameraPA->setValue(PAngle);
214 syncFOV(PAngle);
215 CameraOffset->setValue(Options::pAOffset());
216}
217
218void RotatorSettings::syncFOV(double PA)
219{
220 for (auto oneFOV : KStarsData::Instance()->getTransientFOVs())
221 {
222 // Only change the PA for the sensor FOV
223 if (oneFOV->objectName() == "sensor_fov")
224 {
225 // Make sure that it is always displayed
226 if (!Options::showSensorFOV())
227 {
228 Options::setShowSensorFOV(true);
229 oneFOV->setProperty("visible", true);
230 }
231
232 // JM 2020-10-15
233 // While we have the correct Position Angle
234 // Because Ekos reads frame TOP-BOTTOM instead of the BOTTOM-TOP approach
235 // used by astrometry, the PA is always 180 degree off. To avoid confusion to the user
236 // the PA is drawn REVERSED to show the *expected* frame. However, the final PA is
237 // the "correct" PA as expected by astrometry.
238 //double drawnPA = PA >= 0 ? (PA - 180) : (PA + 180);
239 oneFOV->setPA(PA);
240 break;
241 }
242 }
243}
244
Rotator class handles control of INDI Rotator devices.
Definition indirotator.h:20
static KConfigDialog * exists(const QString &name)
The main container for polar plots, representing the angular axis as a circle.
void setTickPen(const QPen &pen)
void setTickLabels(bool show)
void setSubTickPen(const QPen &pen)
void setTickLength(int inside, int outside=0)
void setSubTickLength(int inside, int outside=0)
bool removeRadialAxis(QCPPolarAxisRadial *axis)
void setBasePen(const QPen &pen)
QCPPolarAxisRadial * radialAxis(int index=0) const
void setAngularPen(const QPen &pen)
QString i18n(const char *text, const TYPE &arg...)
void clicked(bool checked)
void toggled(bool checked)
void sliderReleased()
void valueChanged(int value)
void currentIndexChanged(int index)
void valueChanged(double d)
QString number(double n, char format, int precision)
WA_OpaquePaintEvent
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Dec 27 2024 11:51:45 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.