9 #include "guideadaptor.h"
11 #include "ksmessagebox.h"
12 #include "kstarsdata.h"
13 #include "opscalibration.h"
15 #include "opsdither.h"
18 #include "indi/indiguider.h"
19 #include "indi/indiadaptiveoptics.h"
20 #include "auxiliary/QProgressIndicator.h"
21 #include "ekos/auxiliary/opticaltrainmanager.h"
22 #include "ekos/auxiliary/profilesettings.h"
23 #include "ekos/auxiliary/opticaltrainsettings.h"
24 #include "ekos/auxiliary/darklibrary.h"
25 #include "externalguide/linguider.h"
26 #include "externalguide/phd2.h"
27 #include "fitsviewer/fitsdata.h"
28 #include "fitsviewer/fitsview.h"
29 #include "fitsviewer/fitsviewer.h"
30 #include "internalguide/internalguider.h"
31 #include "guideview.h"
32 #include "guidegraph.h"
34 #include <KConfigDialog>
36 #include <basedevice.h>
37 #include <ekos_guide_debug.h>
39 #include "ui_manualdither.h"
43 #define CAPTURE_TIMEOUT_THRESHOLD 30000
50 internalGuider =
new InternalGuider();
54 opsGuide =
new OpsGuide();
57 connect(opsGuide, &OpsGuide::settingsUpdated, [
this]()
59 onThresholdChanged(Options::guideAlgorithm());
60 configurePHD2Camera();
61 configSEPMultistarOptions();
65 opsCalibration =
new OpsCalibration(internalGuider);
66 page = dialog->
addPage(opsCalibration,
i18n(
"Calibration"));
69 opsDither =
new OpsDither();
73 opsGPG =
new OpsGPG(internalGuider);
74 page = dialog->
addPage(opsGPG,
i18n(
"GPG RA Guider"));
81 qRegisterMetaType<Ekos::GuideState>(
"Ekos::GuideState");
82 qDBusRegisterMetaType<Ekos::GuideState>();
83 new GuideAdaptor(
this);
91 internalGuider->setGuideView(m_GuideView);
98 controlLayout->addWidget(pi, 1, 2, 1, 1);
100 showFITSViewerB->setIcon(
105 guideAutoScaleGraphB->setIcon(
110 guideSaveDataB->setIcon(
115 guideDataClearB->setIcon(
122 guideZoomInXB->setText(
"+");
128 guideZoomOutXB->setText(
"-");
133 focalLengthIcon->setPixmap(
QIcon::fromTheme(
"gnumeric-formulaguru").pixmap(32, 32));
135 reducerIcon->setPixmap(
QIcon::fromTheme(
"format-align-vertical-bottom").pixmap(32, 32));
136 FOVIcon->setPixmap(
QIcon::fromTheme(
"timeline-use-zone-on").pixmap(32, 32));
137 focalRatioIcon->setPixmap(
QIcon::fromTheme(
"node-type-symmetric").pixmap(32, 32));
142 exposureValues << 0.02 << 0.05 << 0.1 << 0.2 << 0.5 << 1 << 1.5 << 2 << 2.5 << 3 << 3.5 << 4 << 4.5 << 5 << 6 << 7 << 8 << 9
144 guideExposure->setRecommendedValues(exposureValues);
145 connect(guideExposure, &NonLinearDoubleSpinBox::editingFinished,
this, &Ekos::Guide::saveDefaultGuideExposure);
151 if(guiderType == GUIDE_PHD2)
153 setExternalGuiderBLOBEnabled(!Options::guideSubframe());
158 opsDither->kcfg_DitherTimeout->setEnabled(
false);
159 opsDither->kcfg_DitherThreshold->setEnabled(
false);
160 opsDither->kcfg_DitherMaxIterations->setEnabled(!Options::ditherWithOnePulse());
164 resetNonGuidedDither();
169 for (
auto &button : qButtons)
170 button->setAutoDefault(
false);
174 m_DarkProcessor =
new DarkProcessor(
this);
175 connect(m_DarkProcessor, &DarkProcessor::newLog,
this, &Ekos::Guide::appendLogText);
176 connect(m_DarkProcessor, &DarkProcessor::darkFrameCompleted,
this, [
this](
bool completed)
178 if (completed != guideDarkFrame->isChecked())
179 setDarkFrameEnabled(completed);
180 m_GuideView->setProperty(
"suspended",
false);
183 m_GuideView->rescale(ZOOM_KEEP_LEVEL);
184 m_GuideView->updateFrame();
186 m_GuideView->updateFrame();
187 setCaptureComplete();
190 loadGlobalSettings();
193 setupOpticalTrainManager();
198 delete m_GuiderInstance;
201 void Guide::handleHorizontalPlotSizeChange()
203 targetPlot->handleHorizontalPlotSizeChange();
204 calibrationPlot->xAxis->setScaleRatio(calibrationPlot->yAxis, 1.0);
205 calibrationPlot->replot();
208 void Guide::handleVerticalPlotSizeChange()
210 targetPlot->handleVerticalPlotSizeChange();
211 calibrationPlot->yAxis->setScaleRatio(calibrationPlot->xAxis, 1.0);
212 calibrationPlot->replot();
215 void Guide::guideAfterMeridianFlip()
219 m_GuideView->setTrackingBoxEnabled(
false);
222 if (Options::resetGuideCalibration())
226 if (Options::gPGEnabled())
227 m_GuiderInstance->resetGPG();
234 if (
event->oldSize().width() != -1)
236 if (
event->oldSize().width() != size().width())
237 handleHorizontalPlotSizeChange();
238 else if (
event->oldSize().height() != size().height())
239 handleVerticalPlotSizeChange();
247 void Guide::buildTarget()
249 targetPlot->buildTarget(guiderAccuracyThreshold->value());
252 void Guide::clearGuideGraphs()
258 void Guide::clearCalibrationGraphs()
260 calibrationPlot->graph(GuideGraph::G_RA)->data()->clear();
261 calibrationPlot->graph(GuideGraph::G_DEC)->data()->clear();
262 calibrationPlot->graph(GuideGraph::G_RA_HIGHLIGHT)->data()->clear();
263 calibrationPlot->graph(GuideGraph::G_DEC_HIGHLIGHT)->data()->clear();
264 calibrationPlot->graph(GuideGraph::G_RA_PULSE)->data()->clear();
265 calibrationPlot->replot();
268 void Guide::slotAutoScaleGraphs()
270 driftGraph->zoomX(defaultXZoomLevel);
272 driftGraph->autoScaleGraphs();
273 targetPlot->autoScaleGraphs(guiderAccuracyThreshold->value());
275 calibrationPlot->rescaleAxes();
276 calibrationPlot->yAxis->setScaleRatio(calibrationPlot->xAxis, 1.0);
277 calibrationPlot->xAxis->setScaleRatio(calibrationPlot->yAxis, 1.0);
278 calibrationPlot->replot();
281 void Guide::guideHistory()
283 int sliderValue = guideSlider->value();
284 latestCheck->setChecked(sliderValue == guideSlider->maximum() - 1 || sliderValue == guideSlider->maximum());
285 double ra = driftGraph->graph(GuideGraph::G_RA)->dataMainValue(sliderValue);
286 double de = driftGraph->graph(GuideGraph::G_DEC)->dataMainValue(sliderValue);
287 driftGraph->guideHistory(sliderValue, graphOnLatestPt);
289 targetPlot->showPoint(ra, de);
292 void Guide::setLatestGuidePoint(
bool isChecked)
294 graphOnLatestPt = isChecked;
295 driftGraph->setLatestGuidePoint(isChecked);
296 targetPlot->setLatestGuidePoint(isChecked);
299 guideSlider->setValue(guideSlider->maximum());
304 guideExposure->setRecommendedValues(values);
305 return guideExposure->getRecommendedValuesString();
310 if (m_Camera && device == m_Camera)
317 m_Camera->disconnect(
this);
323 connect(m_Camera, &ISD::ConcreteDevice::Connected,
this, [
this]()
325 controlGroupBox->setEnabled(
true);
327 connect(m_Camera, &ISD::ConcreteDevice::Disconnected,
this, [
this]()
329 controlGroupBox->setEnabled(
false);
333 controlGroupBox->setEnabled(m_Camera && m_Camera->isConnected());
339 if(guiderType != GUIDE_INTERNAL)
340 m_Camera->setBLOBEnabled(
false);
343 configurePHD2Camera();
347 void Guide::configurePHD2Camera()
351 if(guiderType != GUIDE_PHD2)
358 if(!phd2Guider->isConnected())
362 if(phd2Guider->getCurrentCamera().isEmpty())
364 phd2Guider->requestCurrentEquipmentUpdate();
370 QString currentPHD2CameraName =
"None";
371 if(m_Camera && phd2Guider->getCurrentCamera().contains(m_Camera->getDeviceName()))
374 currentPHD2CameraName = (phd2Guider->getCurrentCamera());
380 if(lastPHD2CameraName == currentPHD2CameraName)
382 setExternalGuiderBLOBEnabled(!guideSubframe->isChecked());
388 setExternalGuiderBLOBEnabled(
false);
394 lastPHD2CameraName = currentPHD2CameraName;
397 phd2Guider->setCurrentCameraIsNotInEkos(m_Camera ==
nullptr);
399 if(phd2Guider->isCurrentCameraNotInEkos())
402 i18n(
"PHD2's current camera: %1, is NOT connected to Ekos. The PHD2 Guide Star Image will be received, but the full external guide frames cannot.",
403 phd2Guider->getCurrentCamera()));
404 guideSubframe->setEnabled(
false);
407 guideSubframe->setChecked(
true);
412 i18n(
"PHD2's current camera: %1, IS connected to Ekos. You can select whether to use the full external guide frames or just receive the PHD2 Guide Star Image using the SubFrame checkbox.",
413 phd2Guider->getCurrentCamera()));
414 guideSubframe->setEnabled(
true);
416 guideSubframe->setChecked(guideSubframe->isChecked());
421 if (m_Mount && m_Mount == device)
428 m_Mount->disconnect(
this);
438 return m_Camera->getDeviceName();
443 void Guide::checkCamera()
447 if (!m_Camera || guiderType != GUIDE_INTERNAL)
455 case GUIDE_CONNECTED:
456 case GUIDE_DISCONNECTED:
457 case GUIDE_CALIBRATION_ERROR:
465 case GUIDE_STAR_SELECT:
466 case GUIDE_CALIBRATING:
467 case GUIDE_CALIBRATION_SUCCESS:
469 case GUIDE_SUSPENDED:
470 case GUIDE_REACQUIRE:
471 case GUIDE_DITHERING:
472 case GUIDE_MANUAL_DITHERING:
473 case GUIDE_DITHERING_ERROR:
474 case GUIDE_DITHERING_SUCCESS:
475 case GUIDE_DITHERING_SETTLE:
482 ISD::CameraChip *targetChip = m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
485 qCCritical(KSTARS_EKOS_GUIDE) <<
"Failed to retrieve active guide chip in camera";
489 if (targetChip->isCapturing())
492 if (guiderType != GUIDE_INTERNAL)
504 void Ekos::Guide::checkUseGuideHead()
506 if (m_Camera ==
nullptr)
509 if (m_Camera->hasGuideHead() && Options::useGuideHead())
512 useGuideHead =
false;
514 opsGuide->kcfg_UseGuideHead->
setEnabled(m_Camera->hasGuideHead());
517 void Guide::syncCameraInfo()
522 auto nvp = m_Camera->getNumber(useGuideHead ?
"GUIDER_INFO" :
"CCD_INFO");
526 auto np = nvp->findWidgetByName(
"CCD_PIXEL_SIZE_X");
528 ccdPixelSizeX = np->getValue();
530 np = nvp->findWidgetByName(
"CCD_PIXEL_SIZE_Y");
532 ccdPixelSizeY = np->getValue();
534 np = nvp->findWidgetByName(
"CCD_PIXEL_SIZE_Y");
536 ccdPixelSizeY = np->getValue();
542 void Guide::syncTelescopeInfo()
544 if (m_Mount ==
nullptr || m_Mount->isConnected() ==
false)
550 void Guide::updateGuideParams()
552 if (m_Camera ==
nullptr)
557 ISD::CameraChip *targetChip = m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
559 if (targetChip ==
nullptr)
561 appendLogText(
i18n(
"Connection to the guide CCD is lost."));
565 if (targetChip->getFrameType() != FRAME_LIGHT)
568 if(guiderType == GUIDE_INTERNAL)
569 guideBinning->setEnabled(targetChip->canBin());
571 int subBinX = 1, subBinY = 1;
572 if (targetChip->canBin())
574 int maxBinX, maxBinY;
576 targetChip->getBinning(&subBinX, &subBinY);
577 targetChip->getMaxBin(&maxBinX, &maxBinY);
580 if( guideBinIndex >= 0 && guideBinIndex < maxBinX && guideBinIndex < maxBinY )
582 subBinX = guideBinIndex + 1;
583 subBinY = guideBinIndex + 1;
586 guideBinIndex = subBinX - 1;
588 guideBinning->blockSignals(
true);
590 guideBinning->clear();
591 for (
int i = 1; i <= maxBinX; i++)
592 guideBinning->addItem(
QString(
"%1x%2").arg(i).arg(i));
594 guideBinning->setCurrentIndex( guideBinIndex );
596 guideBinning->blockSignals(
false);
600 if (frameSettings.
contains(targetChip) ==
false)
603 if (targetChip->getFrame(&
x, &
y, &w, &h))
607 int minX, maxX, minY, maxY, minW, maxW, minH, maxH;
608 targetChip->getFrameMinMax(&minX, &maxX, &minY, &maxY, &minW, &maxW, &minH, &maxH);
609 auto subframed = guideSubframe->isChecked();
611 QVariantMap settings;
613 settings[
"x"] = subframed ?
x : minX;
614 settings[
"y"] = subframed ?
y : minY;
615 settings[
"w"] = subframed ? w : maxW;
616 settings[
"h"] = subframed ? h : maxH;
617 settings[
"binx"] = subBinX;
618 settings[
"biny"] = subBinY;
620 frameSettings[targetChip] = settings;
627 QVariantMap settings = frameSettings[targetChip];
628 settings[
"binx"] = subBinX;
629 settings[
"biny"] = subBinY;
630 frameSettings[targetChip] = settings;
633 if (ccdPixelSizeX != -1 && ccdPixelSizeY != -1 && m_FocalLength > 0)
635 auto effectiveFocaLength = m_Reducer * m_FocalLength;
636 m_GuiderInstance->setGuiderParams(ccdPixelSizeX, ccdPixelSizeY, m_Aperture, effectiveFocaLength);
637 emit guideChipUpdated(targetChip);
640 if (targetChip->getFrame(&
x, &
y, &w, &h))
642 m_GuiderInstance->setFrameParams(
x,
y, w, h, subBinX, subBinY);
645 l_Focal->setText(
QString(
"%1mm").arg(m_FocalLength, 0,
'f', 0));
647 l_Aperture->setText(
QString(
"%1mm").arg(m_Aperture, 0,
'f', 0));
650 l_Aperture->setText(
"DSLR");
653 if (m_FocalRatio > 0)
654 l_FbyD->setText(
QString(
"F/%1").arg(m_FocalRatio, 0,
'f', 1));
655 else if (m_Aperture > 0)
656 l_FbyD->setText(
QString(
"F/%1").arg(m_FocalLength / m_Aperture, 0,
'f', 1));
659 pixScaleX = 206264.8062470963552 * ccdPixelSizeX / 1000.0 / effectiveFocaLength;
660 pixScaleY = 206264.8062470963552 * ccdPixelSizeY / 1000.0 / effectiveFocaLength;
663 double fov_w = (w * pixScaleX) / 60.0;
664 double fov_h = (h * pixScaleY) / 60.0;
672 if (guiderType != GUIDE_INTERNAL || (m_Guider && device == m_Guider))
676 m_Guider->disconnect(
this);
682 connect(m_Guider, &ISD::ConcreteDevice::Connected,
this, [
this]()
684 guideB->setEnabled(
true);
686 connect(m_Guider, &ISD::ConcreteDevice::Disconnected,
this, [
this]()
688 guideB->setEnabled(
false);
692 guideB->setEnabled(m_Guider && m_Guider->isConnected());
698 if (guiderType != GUIDE_INTERNAL || (m_AO && device == m_AO))
711 if (guiderType != GUIDE_INTERNAL || m_Guider ==
nullptr)
714 return m_Guider->getDeviceName();
719 buildOperationStack(GUIDE_CAPTURE);
721 return executeOperationStack();
724 bool Guide::captureOneFrame()
726 captureTimeout.
stop();
728 if (m_Camera ==
nullptr)
731 if (m_Camera->isConnected() ==
false)
733 appendLogText(
i18n(
"Error: lost connection to CCD."));
737 double seqExpose = guideExposure->value();
739 ISD::CameraChip *targetChip = m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
741 prepareCapture(targetChip);
743 m_GuideView->setBaseSize(guideWidget->size());
747 if (frameSettings.
contains(targetChip))
749 QVariantMap settings = frameSettings[targetChip];
750 targetChip->setFrame(settings[
"x"].toInt(), settings[
"y"].toInt(), settings[
"w"].toInt(),
751 settings[
"h"].toInt());
752 targetChip->setBinning(settings[
"binx"].toInt(), settings[
"biny"].toInt());
756 qCDebug(KSTARS_EKOS_GUIDE) <<
"Capturing frame...";
758 double finalExposure = seqExpose;
762 if (operationStack.contains(GUIDE_STAR_SELECT) && guideAutoStar->isChecked() &&
763 !((guiderType == GUIDE_INTERNAL) && internalGuider->SEPMultiStarEnabled()))
767 m_GuideView->setProperty(
"suspended", operationStack.contains(GUIDE_DARK));
770 captureTimeout.
start(finalExposure * 1000 + CAPTURE_TIMEOUT_THRESHOLD);
772 targetChip->capture(finalExposure);
779 targetChip->setBatchMode(
false);
780 targetChip->setCaptureMode(FITS_GUIDE);
781 targetChip->setFrameType(FRAME_LIGHT);
782 targetChip->setCaptureFilter(FITS_NONE);
783 m_Camera->setEncodingFormat(
"FITS");
788 if (m_Camera && guiderType == GUIDE_INTERNAL)
790 captureTimeout.
stop();
793 m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
794 if (targetChip->isCapturing())
795 targetChip->abortExposure();
798 manualDitherB->setEnabled(
false);
805 case GUIDE_CONNECTED:
806 case GUIDE_DISCONNECTED:
809 case GUIDE_CALIBRATING:
810 case GUIDE_DITHERING:
811 case GUIDE_STAR_SELECT:
815 m_GuiderInstance->abort();
825 void Guide::setBusy(
bool enable)
829 else if (enable ==
false && pi->
isAnimated() ==
false)
834 clearCalibrationB->setEnabled(
false);
835 guideB->setEnabled(
false);
836 captureB->setEnabled(
false);
837 loopB->setEnabled(
false);
838 guideDarkFrame->setEnabled(
false);
839 guideSubframe->setEnabled(
false);
840 guideAutoStar->setEnabled(
false);
841 stopB->setEnabled(
true);
843 opticalTrainCombo->setEnabled(
false);
844 trainB->setEnabled(
false);
850 if(guiderType != GUIDE_LINGUIDER)
852 captureB->setEnabled(
true);
853 loopB->setEnabled(
true);
854 guideAutoStar->setEnabled(!internalGuider->SEPMultiStarEnabled());
856 guideSubframe->setEnabled(!internalGuider->SEPMultiStarEnabled());
858 if (guiderType == GUIDE_INTERNAL)
859 guideDarkFrame->setEnabled(
true);
861 if (calibrationComplete ||
862 ((guiderType == GUIDE_INTERNAL) &&
863 Options::reuseGuideCalibration() &&
864 !Options::serializedCalibration().isEmpty()))
865 clearCalibrationB->setEnabled(
true);
866 guideB->setEnabled(
true);
867 stopB->setEnabled(
false);
871 opticalTrainCombo->setEnabled(
true);
872 trainB->setEnabled(
true);
878 void Guide::processCaptureTimeout()
880 auto restartExposure = [&]()
882 appendLogText(
i18n(
"Exposure timeout. Restarting exposure..."));
883 m_Camera->setEncodingFormat(
"FITS");
884 ISD::CameraChip *targetChip = m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
885 targetChip->abortExposure();
886 prepareCapture(targetChip);
887 targetChip->capture(guideExposure->value());
888 captureTimeout.
start(guideExposure->value() * 1000 + CAPTURE_TIMEOUT_THRESHOLD);
891 m_CaptureTimeoutCounter++;
893 if (m_Camera ==
nullptr)
896 if (m_DeviceRestartCounter >= 3)
898 m_CaptureTimeoutCounter = 0;
899 m_DeviceRestartCounter = 0;
900 if (m_State == GUIDE_GUIDING)
901 appendLogText(
i18n(
"Exposure timeout. Aborting Autoguide."));
902 else if (m_State == GUIDE_DITHERING)
903 appendLogText(
i18n(
"Exposure timeout. Aborting Dithering."));
904 else if (m_State == GUIDE_CALIBRATING)
905 appendLogText(
i18n(
"Exposure timeout. Aborting Calibration."));
907 captureTimeout.
stop();
912 if (m_CaptureTimeoutCounter > 1)
914 QString camera = m_Camera->getDeviceName();
915 QString via = m_Guider ? m_Guider->getDeviceName() :
"";
916 ISD::CameraChip *targetChip = m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
917 QVariantMap settings = frameSettings[targetChip];
918 emit driverTimedout(camera);
921 m_DeviceRestartCounter++;
922 reconnectDriver(camera, settings);
931 void Guide::reconnectDriver(
const QString &camera, QVariantMap settings)
933 if (m_Camera && m_Camera->getDeviceName() == camera)
937 m_State = GUIDE_IDLE;
942 if (guiderType == GUIDE_INTERNAL)
945 ISD::CameraChip *targetChip = m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
946 frameSettings[targetChip] = settings;
948 m_CaptureTimeoutCounter = 0;
957 reconnectDriver(camera, settings);
963 ISD::CameraChip *targetChip = m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
964 if (targetChip->getCaptureMode() != FITS_GUIDE)
968 QString blobInfo =
QString(
"{Device: %1 Property: %2 Element: %3 Chip: %4}").
arg(data->property(
"device").toString())
969 .
arg(data->property(
"blobVector").toString())
970 .
arg(data->property(
"blobElement").toString())
971 .
arg(data->property(
"chip").toInt());
973 qCWarning(KSTARS_EKOS_GUIDE) << blobInfo <<
"Ignoring Received FITS as it has the wrong capture mode" <<
974 targetChip->getCaptureMode();
982 m_GuideView->loadData(data);
988 if (guiderType == GUIDE_INTERNAL)
989 internalGuider->setImageData(m_ImageData);
991 captureTimeout.
stop();
992 m_CaptureTimeoutCounter = 0;
996 qCDebug(KSTARS_EKOS_GUIDE) <<
"Received guide frame.";
998 int subBinX = 1, subBinY = 1;
999 targetChip->getBinning(&subBinX, &subBinY);
1001 if (starCenter.
x() == 0 && starCenter.
y() == 0)
1003 int x = 0,
y = 0, w = 0, h = 0;
1005 if (frameSettings.
contains(targetChip))
1007 QVariantMap settings = frameSettings[targetChip];
1008 x = settings[
"x"].toInt();
1009 y = settings[
"y"].toInt();
1010 w = settings[
"w"].toInt();
1011 h = settings[
"h"].toInt();
1014 targetChip->getFrame(&
x, &
y, &w, &h);
1016 starCenter.
setX(w / (2 * subBinX));
1017 starCenter.
setY(h / (2 * subBinY));
1018 starCenter.
setZ(subBinX);
1021 syncTrackingBoxPosition();
1022 qCDebug(KSTARS_EKOS_GUIDE) <<
"Tracking box position synched.";
1024 setCaptureComplete();
1025 qCDebug(KSTARS_EKOS_GUIDE) <<
"Capture complete.";
1029 void Guide::setCaptureComplete()
1031 if (!m_GuideView.
isNull())
1032 m_GuideView->clearNeighbors();
1034 DarkLibrary::Instance()->disconnect(
this);
1036 if (operationStack.isEmpty() ==
false)
1038 executeOperationStack();
1042 qCDebug(KSTARS_EKOS_GUIDE) <<
"Capture complete, state=" << getGuideStatusString(m_State);
1047 case GUIDE_CONNECTED:
1048 case GUIDE_DISCONNECTED:
1049 case GUIDE_CALIBRATION_SUCCESS:
1050 case GUIDE_CALIBRATION_ERROR:
1051 case GUIDE_DITHERING_ERROR:
1056 qCDebug(KSTARS_EKOS_GUIDE) <<
"Guiding capture complete.";
1057 m_State = GUIDE_IDLE;
1058 emit newStatus(m_State);
1066 case GUIDE_CALIBRATING:
1067 m_GuiderInstance->calibrate();
1071 m_GuiderInstance->guide();
1074 case GUIDE_DITHERING:
1075 m_GuiderInstance->dither(Options::ditherPixels());
1079 case GUIDE_MANUAL_DITHERING:
1080 dynamic_cast<InternalGuider*
>(m_GuiderInstance)->processManualDithering();
1083 case GUIDE_REACQUIRE:
1084 m_GuiderInstance->reacquire();
1087 case GUIDE_DITHERING_SETTLE:
1088 if (Options::ditherNoGuiding())
1093 case GUIDE_SUSPENDED:
1094 if (Options::gPGEnabled())
1095 m_GuiderInstance->guide();
1102 emit newImage(m_GuideView);
1103 emit newStarPixmap(m_GuideView->getTrackingBoxPixmap(10));
1106 void Guide::appendLogText(
const QString &text)
1108 m_LogText.
insert(0,
i18nc(
"log entry; %1 is the date, %2 is the text",
"%1 %2",
1109 KStarsData::Instance()->lt().
toString(
"yyyy-MM-ddThh:mm:ss"), text));
1111 qCInfo(KSTARS_EKOS_GUIDE) << text;
1124 if (m_Guider ==
nullptr || m_GuiderInstance ==
nullptr)
1127 if (guiderType == GUIDE_INTERNAL)
1129 dynamic_cast<InternalGuider *
>(m_GuiderInstance)->
setDECSwap(enable);
1130 m_Guider->setDECSwap(enable);
1134 bool Guide::sendMultiPulse(GuideDirection ra_dir,
int ra_msecs, GuideDirection dec_dir,
int dec_msecs,
1135 CaptureAfterPulses followWithCapture)
1137 if (m_Guider ==
nullptr || (ra_dir == NO_DIR && dec_dir == NO_DIR))
1140 if (followWithCapture == StartCaptureAfterPulses)
1144 auto ms = std::max(ra_msecs, dec_msecs) + 100;
1145 auto delay = std::max(
static_cast<int>(guideDelay->value() * 1000), ms);
1147 m_PulseTimer.
start(delay);
1149 return m_Guider->doPulse(ra_dir, ra_msecs, dec_dir, dec_msecs);
1152 bool Guide::sendSinglePulse(GuideDirection dir,
int msecs, CaptureAfterPulses followWithCapture)
1154 if (m_Guider ==
nullptr || dir == NO_DIR)
1157 if (followWithCapture == StartCaptureAfterPulses)
1161 auto ms = msecs + 100;
1162 auto delay = std::max(
static_cast<int>(guideDelay->value() * 1000), ms);
1164 m_PulseTimer.
start(delay);
1167 return m_Guider->doPulse(dir, msecs);
1173 m_State = GUIDE_IDLE;
1174 qCDebug(KSTARS_EKOS_GUIDE) <<
"Calibrating...";
1175 emit newStatus(m_State);
1177 if (guiderType == GUIDE_INTERNAL)
1181 qCCritical(KSTARS_EKOS_GUIDE) <<
"No camera detected. Check optical trains.";
1185 auto targetChip = m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
1187 if (frameSettings.
contains(targetChip))
1189 targetChip->resetFrame();
1191 targetChip->getFrame(&
x, &
y, &w, &h);
1192 QVariantMap settings = frameSettings[targetChip];
1197 frameSettings[targetChip] = settings;
1203 buildOperationStack(GUIDE_CALIBRATING);
1205 executeOperationStack();
1207 if (m_Camera && m_Guider)
1209 qCDebug(KSTARS_EKOS_GUIDE) <<
"Starting calibration using camera:" << m_Camera->getDeviceName() <<
"via" <<
1210 m_Guider->getDeviceName();
1218 auto executeGuide = [
this]()
1220 if(guiderType != GUIDE_PHD2)
1222 if (calibrationComplete ==
false)
1229 m_GuiderInstance->guide();
1235 if(!guideAutoStar->isChecked())
1237 if(guiderType == GUIDE_PHD2 && m_GuideView->isTrackingBoxEnabled())
1239 double x = starCenter.
x();
1240 double y = starCenter.
y();
1242 if(!m_ImageData.
isNull())
1244 if(m_ImageData->width() > 50)
1246 guideConnect =
connect(
this, &Guide::newStatus,
this, [
this,
x,
y](Ekos::GuideState newState)
1248 if(newState == GUIDE_GUIDING)
1250 phd2Guider->setLockPosition(
x,
y);
1260 if (m_MountStatus == ISD::Mount::MOUNT_PARKED)
1262 KSMessageBox::Instance()->sorry(
i18n(
"The mount is parked. Unpark to start guiding."));
1272 if (Options::ditherNoGuiding() && m_State == GUIDE_IDLE)
1278 if (m_State == GUIDE_DITHERING || m_State == GUIDE_DITHERING_SETTLE)
1282 double time = guideTimer.
elapsed() / 1000.0;
1286 ditherLabel->position->
setCoords(time, 1.5);
1290 ditherLabel->
setText(
"Dither");
1293 if (guiderType == GUIDE_INTERNAL)
1295 if (m_State != GUIDE_GUIDING)
1298 setStatus(GUIDE_DITHERING);
1303 return m_GuiderInstance->dither(Options::ditherPixels());
1308 if (m_State == GUIDE_SUSPENDED)
1310 else if (m_State >= GUIDE_CAPTURE)
1311 return m_GuiderInstance->suspend();
1318 if (m_State == GUIDE_GUIDING)
1320 else if (m_State == GUIDE_SUSPENDED)
1321 return m_GuiderInstance->resume();
1340 resetNonGuidedDither();
1347 void Guide::setPierSide(ISD::Mount::PierSide newSide)
1349 m_GuiderInstance->setPierSide(newSide);
1354 if (guiderType == GUIDE_INTERNAL &&
1355 m_State != GUIDE_GUIDING &&
1356 m_State != GUIDE_CALIBRATING &&
1357 calibrationComplete)
1360 if (Options::reuseGuideCalibration())
1361 calibrationComplete =
false;
1365 appendLogText(
i18n(
"Pier side change detected. Clearing calibration."));
1370 void Guide::setMountStatus(ISD::Mount::Status newState)
1372 m_MountStatus = newState;
1374 if (newState == ISD::Mount::MOUNT_PARKING || newState == ISD::Mount::MOUNT_SLEWING)
1377 if (Options::resetGuideCalibration())
1379 appendLogText(
i18n(
"Mount is moving. Resetting calibration..."));
1382 else if (Options::reuseGuideCalibration() && (guiderType == GUIDE_INTERNAL))
1385 calibrationComplete =
false;
1388 if (Options::gPGEnabled())
1389 m_GuiderInstance->resetGPG();
1392 if (m_State == GUIDE_GUIDING || m_State == GUIDE_DITHERING)
1394 if (newState == ISD::Mount::MOUNT_PARKING)
1395 appendLogText(
i18n(
"Mount is parking. Aborting guide..."));
1397 appendLogText(
i18n(
"Mount is slewing. Aborting guide..."));
1403 if (guiderType != GUIDE_INTERNAL)
1408 case ISD::Mount::MOUNT_SLEWING:
1409 case ISD::Mount::MOUNT_PARKING:
1410 case ISD::Mount::MOUNT_MOVING:
1411 captureB->setEnabled(
false);
1412 loopB->setEnabled(
false);
1413 clearCalibrationB->setEnabled(
false);
1419 captureB->setEnabled(
true);
1420 loopB->setEnabled(
true);
1421 clearCalibrationB->setEnabled(
true);
1426 void Guide::setMountCoords(
const SkyPoint &position, ISD::Mount::PierSide pierSide,
const dms &ha)
1429 m_GuiderInstance->setMountCoords(position, pierSide);
1434 guideExposure->setValue(value);
1439 if (guideSubframe->isChecked() != enable)
1440 guideSubframe->setChecked(enable);
1441 if(guiderType == GUIDE_PHD2)
1442 setExternalGuiderBLOBEnabled(!enable);
1447 if(guiderType == GUIDE_INTERNAL)
1448 guideAutoStar->setChecked(enable);
1453 calibrationComplete =
false;
1455 m_GuiderInstance->clearCalibration();
1457 appendLogText(
i18n(
"Calibration is cleared."));
1460 void Guide::setStatus(Ekos::GuideState newState)
1462 if (newState == m_State)
1465 if (newState == GUIDE_ABORTED)
1466 emit newStatus(m_State);
1470 GuideState previousState = m_State;
1473 emit newStatus(m_State);
1477 case GUIDE_CONNECTED:
1478 appendLogText(
i18n(
"External guider connected."));
1479 externalConnectB->setEnabled(
false);
1480 externalDisconnectB->setEnabled(
true);
1481 clearCalibrationB->setEnabled(
true);
1482 guideB->setEnabled(
true);
1484 if(guiderType == GUIDE_PHD2)
1486 captureB->setEnabled(
true);
1487 loopB->setEnabled(
true);
1488 guideAutoStar->setEnabled(
true);
1489 configurePHD2Camera();
1490 setExternalGuiderBLOBEnabled(!guideSubframe->isChecked());
1491 guideSquareSize->setEnabled(
true);
1495 case GUIDE_DISCONNECTED:
1496 appendLogText(
i18n(
"External guider disconnected."));
1498 externalConnectB->setEnabled(
true);
1499 externalDisconnectB->setEnabled(
false);
1500 clearCalibrationB->setEnabled(
false);
1501 guideB->setEnabled(
false);
1502 captureB->setEnabled(
false);
1503 loopB->setEnabled(
false);
1504 guideAutoStar->setEnabled(
false);
1505 guideSquareSize->setEnabled(
false);
1512 case GUIDE_CALIBRATION_SUCCESS:
1513 appendLogText(
i18n(
"Calibration completed."));
1514 calibrationComplete =
true;
1522 case GUIDE_CALIBRATION_ERROR:
1524 manualDitherB->setEnabled(
false);
1527 case GUIDE_CALIBRATING:
1528 clearCalibrationGraphs();
1529 appendLogText(
i18n(
"Calibration started."));
1534 if (previousState == GUIDE_SUSPENDED || previousState == GUIDE_DITHERING_SUCCESS)
1535 appendLogText(
i18n(
"Guiding resumed."));
1538 appendLogText(
i18n(
"Autoguiding started."));
1543 driftGraph->resetTimer();
1544 driftGraph->refreshColorScheme();
1546 manualDitherB->setEnabled(
true);
1551 appendLogText(
i18n(
"Autoguiding aborted."));
1555 case GUIDE_SUSPENDED:
1556 appendLogText(
i18n(
"Guiding suspended."));
1559 case GUIDE_REACQUIRE:
1560 if (guiderType == GUIDE_INTERNAL)
1564 case GUIDE_MANUAL_DITHERING:
1565 appendLogText(
i18n(
"Manual dithering in progress."));
1568 case GUIDE_DITHERING:
1569 appendLogText(
i18n(
"Dithering in progress."));
1572 case GUIDE_DITHERING_SETTLE:
1573 appendLogText(
i18np(
"Post-dither settling for %1 second...",
"Post-dither settling for %1 seconds...",
1574 Options::ditherSettle()));
1577 case GUIDE_DITHERING_ERROR:
1578 appendLogText(
i18n(
"Dithering failed."));
1580 if (guiderType != GUIDE_LINGUIDER)
1583 m_State = GUIDE_ABORTED;
1588 case GUIDE_DITHERING_SUCCESS:
1589 appendLogText(
i18n(
"Dithering completed successfully."));
1591 if (Options::ditherNoGuiding() ==
false)
1593 setStatus(GUIDE_GUIDING);
1595 if (guiderType == GUIDE_INTERNAL)
1604 void Guide::updateCCDBin(
int index)
1606 if (m_Camera ==
nullptr || guiderType != GUIDE_INTERNAL)
1609 ISD::CameraChip *targetChip = m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
1611 targetChip->setBinning(index + 1, index + 1);
1612 guideBinIndex = index;
1614 QVariantMap settings = frameSettings[targetChip];
1615 settings[
"binx"] = index + 1;
1616 settings[
"biny"] = index + 1;
1617 frameSettings[targetChip] = settings;
1619 m_GuiderInstance->setFrameParams(settings[
"x"].toInt(), settings[
"y"].toInt(), settings[
"w"].toInt(), settings[
"h"].toInt(),
1620 settings[
"binx"].toInt(), settings[
"biny"].toInt());
1625 if (m_Camera ==
nullptr || (prop.getDeviceName() != m_Camera->getDeviceName()) || guiderType != GUIDE_INTERNAL)
1628 if ((prop.isNameMatch(
"CCD_BINNING") && useGuideHead ==
false) ||
1629 (prop.isNameMatch(
"GUIDER_BINNING") && useGuideHead))
1631 auto nvp = prop.getNumber();
1632 auto value = nvp->at(0)->getValue();
1633 if (guideBinIndex > (value - 1))
1635 appendLogText(
i18n(
"%1x%1 guide binning is not supported.", guideBinIndex + 1));
1636 guideBinning->setCurrentIndex( value - 1 );
1641 guideBinning->setCurrentIndex(guideBinIndex);
1649 if (guiderType != GUIDE_INTERNAL || targetChip->getCCD() != m_Camera)
1652 INDI_UNUSED(exposure);
1654 if (expState == IPS_ALERT &&
1655 ((m_State == GUIDE_GUIDING) || (m_State == GUIDE_DITHERING) || (m_State == GUIDE_CALIBRATING)))
1657 appendLogText(
i18n(
"Exposure failed. Restarting exposure..."));
1658 m_Camera->setEncodingFormat(
"FITS");
1659 targetChip->capture(guideExposure->value());
1663 void Guide::configSEPMultistarOptions()
1666 if (internalGuider->SEPMultiStarEnabled())
1668 guideSubframe->setChecked(
false);
1669 guideSubframe->setEnabled(
false);
1670 guideAutoStar->setChecked(
true);
1671 guideAutoStar->setEnabled(
false);
1675 guideAutoStar->setEnabled(
true);
1676 guideSubframe->setEnabled(
true);
1678 auto subframed = m_Settings[
"guideSubframe"];
1679 if (subframed.isValid())
1680 guideSubframe->setChecked(subframed.toBool());
1682 auto autostar = m_Settings[
"guideAutoStar"];
1683 if (autostar.isValid())
1684 guideAutoStar->setChecked(autostar.toBool());
1690 if (guideDarkFrame->isChecked() != enable)
1691 guideDarkFrame->setChecked(enable);
1694 void Guide::saveDefaultGuideExposure()
1696 if(guiderType == GUIDE_PHD2)
1698 phd2Guider->requestSetExposureTime(guideExposure->value() * 1000);
1699 else if (guiderType == GUIDE_INTERNAL)
1701 internalGuider->setExposureTime();
1705 void Guide::setStarPosition(
const QVector3D &newCenter,
bool updateNow)
1707 starCenter.
setX(newCenter.
x());
1708 starCenter.
setY(newCenter.
y());
1709 if (newCenter.
z() > 0)
1710 starCenter.
setZ(newCenter.
z());
1713 syncTrackingBoxPosition();
1716 void Guide::syncTrackingBoxPosition()
1718 if(!m_Camera || guiderType == GUIDE_LINGUIDER)
1721 if(guiderType == GUIDE_PHD2)
1724 if(!m_ImageData.
isNull())
1726 if(m_ImageData->width() < 50)
1728 m_GuideView->setTrackingBoxEnabled(
false);
1734 ISD::CameraChip *targetChip = m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
1735 Q_ASSERT(targetChip);
1737 int subBinX = 1, subBinY = 1;
1738 targetChip->getBinning(&subBinX, &subBinY);
1740 if (starCenter.
isNull() ==
false)
1742 double boxSize = guideSquareSize->currentText().toInt();
1744 targetChip->getFrame(&
x, &
y, &w, &h);
1746 if (boxSize / subBinX >= w || boxSize / subBinY >= h)
1748 int newIndex = guideSquareSize->currentIndex() - 1;
1750 guideSquareSize->setCurrentIndex(newIndex);
1755 if (subBinX != starCenter.
z())
1757 if (starCenter.
z() > 0)
1759 starCenter.
setX(starCenter.
x() * (starCenter.
z() / subBinX));
1760 starCenter.
setY(starCenter.
y() * (starCenter.
z() / subBinY));
1763 starCenter.
setZ(subBinX);
1766 QRect starRect =
QRect(starCenter.
x() - boxSize / (2 * subBinX), starCenter.
y() - boxSize / (2 * subBinY),
1767 boxSize / subBinX, boxSize / subBinY);
1768 m_GuideView->setTrackingBoxEnabled(
true);
1769 m_GuideView->setTrackingBox(starRect);
1777 type = Options::guiderType();
1778 else if (type == guiderType)
1781 if (m_State == GUIDE_CALIBRATING || m_State == GUIDE_GUIDING || m_State == GUIDE_DITHERING)
1783 appendLogText(
i18n(
"Cannot change guider type while active."));
1787 if (m_GuiderInstance !=
nullptr)
1790 if (m_GuiderInstance->isConnected())
1791 m_GuiderInstance->Disconnect();
1797 guiderType =
static_cast<GuiderType
>(type);
1801 case GUIDE_INTERNAL:
1803 connect(internalGuider, &InternalGuider::newMultiPulse,
this, &Guide::sendMultiPulse);
1804 connect(internalGuider, &InternalGuider::newSinglePulse,
this, &Guide::sendSinglePulse);
1806 connect(internalGuider, &InternalGuider::newStarPixmap,
this, &Guide::newStarPixmap);
1808 m_GuiderInstance = internalGuider;
1810 internalGuider->setSquareAlgorithm(opsGuide->kcfg_GuideAlgorithm->currentIndex());
1812 clearCalibrationB->setEnabled(
true);
1813 guideB->setEnabled(
true);
1814 captureB->setEnabled(
true);
1815 loopB->setEnabled(
true);
1817 configSEPMultistarOptions();
1818 guideDarkFrame->setEnabled(
true);
1820 guideExposure->setEnabled(
true);
1821 guideBinning->setEnabled(
true);
1822 guideSquareSize->setEnabled(
true);
1824 externalConnectB->setEnabled(
false);
1825 externalDisconnectB->setEnabled(
false);
1828 infoGroup->setEnabled(
true);
1829 l_Aperture->setEnabled(
true);
1830 l_FOV->setEnabled(
true);
1831 l_FbyD->setEnabled(
true);
1832 l_Focal->setEnabled(
true);
1833 driftGraphicsGroup->setEnabled(
true);
1835 updateGuideParams();
1840 if (phd2Guider.isNull())
1841 phd2Guider =
new PHD2();
1843 m_GuiderInstance = phd2Guider;
1844 phd2Guider->setGuideView(m_GuideView);
1848 clearCalibrationB->setEnabled(
true);
1849 captureB->setEnabled(
false);
1850 loopB->setEnabled(
false);
1851 guideDarkFrame->setEnabled(
false);
1852 guideSubframe->setEnabled(
false);
1853 guideAutoStar->setEnabled(
false);
1854 guideB->setEnabled(
false);
1855 externalConnectB->setEnabled(
false);
1857 rAGuideEnabled->setEnabled(
false);
1858 eastRAGuideEnabled->setEnabled(
false);
1859 westRAGuideEnabled->setEnabled(
false);
1862 infoGroup->setEnabled(
true);
1863 l_Aperture->setEnabled(
false);
1864 l_FOV->setEnabled(
false);
1865 l_FbyD->setEnabled(
false);
1866 l_Focal->setEnabled(
false);
1867 driftGraphicsGroup->setEnabled(
true);
1869 guideExposure->setEnabled(
true);
1870 guideBinning->setEnabled(
false);
1871 guideSquareSize->setEnabled(
false);
1873 if (Options::resetGuideCalibration())
1874 appendLogText(
i18n(
"Warning: Reset Guiding Calibration is enabled. It is recommended to turn this option off for PHD2."));
1876 updateGuideParams();
1879 case GUIDE_LINGUIDER:
1880 if (linGuider.isNull())
1883 m_GuiderInstance = linGuider;
1885 clearCalibrationB->setEnabled(
true);
1886 captureB->setEnabled(
false);
1887 loopB->setEnabled(
false);
1888 guideDarkFrame->setEnabled(
false);
1889 guideSubframe->setEnabled(
false);
1890 guideAutoStar->setEnabled(
false);
1891 guideB->setEnabled(
true);
1892 externalConnectB->setEnabled(
true);
1895 infoGroup->setEnabled(
false);
1896 driftGraphicsGroup->setEnabled(
false);
1898 guideExposure->setEnabled(
false);
1899 guideBinning->setEnabled(
false);
1900 guideSquareSize->setEnabled(
false);
1902 updateGuideParams();
1907 if (m_GuiderInstance !=
nullptr)
1910 connect(m_GuiderInstance, &Ekos::GuideInterface::newLog,
this, &Ekos::Guide::appendLogText);
1911 connect(m_GuiderInstance, &Ekos::GuideInterface::newStatus,
this, &Ekos::Guide::setStatus);
1912 connect(m_GuiderInstance, &Ekos::GuideInterface::newStarPosition,
this, &Ekos::Guide::setStarPosition);
1913 connect(m_GuiderInstance, &Ekos::GuideInterface::guideStats,
this, &Ekos::Guide::guideStats);
1915 connect(m_GuiderInstance, &Ekos::GuideInterface::newAxisDelta,
this, &Ekos::Guide::setAxisDelta);
1916 connect(m_GuiderInstance, &Ekos::GuideInterface::newAxisPulse,
this, &Ekos::Guide::setAxisPulse);
1917 connect(m_GuiderInstance, &Ekos::GuideInterface::newAxisSigma,
this, &Ekos::Guide::setAxisSigma);
1918 connect(m_GuiderInstance, &Ekos::GuideInterface::newSNR,
this, &Ekos::Guide::setSNR);
1919 connect(m_GuiderInstance, &Ekos::GuideInterface::guideInfo,
this, &Ekos::Guide::guideInfo);
1921 driftGraph->connectGuider(m_GuiderInstance);
1922 targetPlot->connectGuider(m_GuiderInstance);
1924 connect(m_GuiderInstance, &Ekos::GuideInterface::calibrationUpdate,
this, &Ekos::Guide::calibrationUpdate);
1926 connect(m_GuiderInstance, &Ekos::GuideInterface::guideEquipmentUpdated,
this, &Ekos::Guide::configurePHD2Camera);
1929 externalConnectB->setEnabled(
false);
1930 externalDisconnectB->setEnabled(
false);
1932 if (m_GuiderInstance !=
nullptr && guiderType != GUIDE_INTERNAL)
1934 externalConnectB->setEnabled(!m_GuiderInstance->isConnected());
1935 externalDisconnectB->setEnabled(m_GuiderInstance->isConnected());
1938 if (m_GuiderInstance !=
nullptr)
1939 m_GuiderInstance->Connect();
1944 void Guide::guideInfo(
const QString &info)
1946 if (info.size() == 0)
1948 guideInfoLabel->setVisible(
false);
1949 guideInfoText->setVisible(
false);
1952 guideInfoLabel->setVisible(
true);
1953 guideInfoLabel->setText(
"Detections");
1954 guideInfoText->setVisible(
true);
1955 guideInfoText->setText(info);
1958 void Guide::updateTrackingBoxSize(
int currentIndex)
1960 if (currentIndex >= 0)
1962 if (guiderType == GUIDE_INTERNAL)
1963 dynamic_cast<InternalGuider *
>(m_GuiderInstance)->setGuideBoxSize(guideSquareSize->currentText().toInt());
1965 syncTrackingBoxPosition();
1969 void Guide::onThresholdChanged(
int index)
1973 case GUIDE_INTERNAL:
1974 dynamic_cast<InternalGuider *
>(m_GuiderInstance)->setSquareAlgorithm(index);
1982 void Guide::onEnableDirRA()
1985 if (Options::gPGEnabled())
1986 m_GuiderInstance->resetGPG();
1989 void Guide::onEnableDirDEC()
1991 onControlDirectionChanged();
1994 void Guide::onControlDirectionChanged()
1996 if(guiderType == GUIDE_PHD2)
1997 phd2Guider -> requestSetDEGuideMode(dECGuideEnabled->isChecked(), northDECGuideEnabled->isChecked(),
1998 southDECGuideEnabled->isChecked());
2001 void Guide::updateDirectionsFromPHD2(
const QString &mode)
2010 dECGuideEnabled->setChecked(
true);
2011 northDECGuideEnabled->setChecked(
true);
2012 southDECGuideEnabled->setChecked(
true);
2014 else if(mode ==
"North")
2016 dECGuideEnabled->setChecked(
true);
2017 northDECGuideEnabled->setChecked(
true);
2018 southDECGuideEnabled->setChecked(
false);
2020 else if(mode ==
"South")
2022 dECGuideEnabled->setChecked(
true);
2023 northDECGuideEnabled->setChecked(
false);
2024 southDECGuideEnabled->setChecked(
true);
2028 dECGuideEnabled->setChecked(
false);
2029 northDECGuideEnabled->setChecked(
true);
2030 southDECGuideEnabled->setChecked(
true);
2042 setStarPosition(newStarPosition,
true);
2044 if(guiderType == GUIDE_PHD2)
2047 if(!m_ImageData.
isNull())
2049 if(m_ImageData->width() > 50)
2050 phd2Guider->setLockPosition(starCenter.
x(), starCenter.
y());
2054 if (operationStack.isEmpty() ==
false)
2055 executeOperationStack();
2058 void Guide::setAxisDelta(
double ra,
double de)
2068 int currentNumPoints = driftGraph->graph(GuideGraph::G_RA)->dataCount();
2069 guideSlider->setMaximum(currentNumPoints);
2072 guideSlider->setValue(currentNumPoints);
2077 emit newAxisDelta(ra, de);
2080 void Guide::calibrationUpdate(GuideInterface::CalibrationUpdateType type,
const QString &
message,
2081 double dx,
double dy)
2085 case GuideInterface::RA_OUT:
2086 calibrationPlot->graph(GuideGraph::G_RA)->addData(dx, dy);
2088 case GuideInterface::RA_IN:
2089 calibrationPlot->graph(GuideGraph::G_DEC)->addData(dx, dy);
2091 case GuideInterface::BACKLASH:
2092 calibrationPlot->graph(GuideGraph::G_RA_HIGHLIGHT)->addData(dx, dy);
2094 case GuideInterface::DEC_OUT:
2095 calibrationPlot->graph(GuideGraph::G_DEC_HIGHLIGHT)->addData(dx, dy);
2097 case GuideInterface::DEC_IN:
2098 calibrationPlot->graph(GuideGraph::G_RA_PULSE)->addData(dx, dy);
2100 case GuideInterface::CALIBRATION_MESSAGE_ONLY:
2104 calibrationPlot->replot();
2107 void Guide::setAxisSigma(
double ra,
double de)
2111 const double total = std::hypot(ra, de);
2114 emit newAxisSigma(ra, de);
2121 delta << l_DeltaRA->text().toDouble() << l_DeltaDEC->text().toDouble();
2130 sigma << l_ErrRA->text().toDouble() << l_ErrDEC->text().toDouble();
2135 void Guide::setAxisPulse(
double ra,
double de)
2141 void Guide::setSNR(
double snr)
2146 void Guide::buildOperationStack(GuideState operation)
2148 operationStack.clear();
2153 if (guideDarkFrame->isChecked())
2154 operationStack.
push(GUIDE_DARK);
2156 operationStack.
push(GUIDE_CAPTURE);
2157 operationStack.
push(GUIDE_SUBFRAME);
2160 case GUIDE_CALIBRATING:
2161 operationStack.
push(GUIDE_CALIBRATING);
2162 if (guiderType == GUIDE_INTERNAL)
2164 if (guideDarkFrame->isChecked())
2165 operationStack.
push(GUIDE_DARK);
2168 if (guideAutoStar->isChecked() ||
2170 internalGuider->SEPMultiStarEnabled())
2174 if (subFramed ==
false && guideSubframe->isChecked())
2175 operationStack.
push(GUIDE_CAPTURE);
2177 operationStack.
push(GUIDE_SUBFRAME);
2178 operationStack.
push(GUIDE_STAR_SELECT);
2181 operationStack.
push(GUIDE_CAPTURE);
2184 if (subFramed ==
true && guideSubframe->isChecked() ==
false)
2185 operationStack.
push(GUIDE_SUBFRAME);
2191 if (subFramed ==
false && guideSubframe->isChecked())
2192 operationStack.
push(GUIDE_CAPTURE);
2195 operationStack.
push(GUIDE_SUBFRAME);
2198 operationStack.
push(GUIDE_CAPTURE);
2209 bool Guide::executeOperationStack()
2211 if (operationStack.isEmpty())
2214 GuideState nextOperation = operationStack.
pop();
2215 qCDebug(KSTARS_EKOS_GUIDE) <<
"Executing operation " << getGuideStatusString(nextOperation);
2217 bool actionRequired =
false;
2219 switch (nextOperation)
2221 case GUIDE_SUBFRAME:
2222 actionRequired = executeOneOperation(nextOperation);
2226 actionRequired = executeOneOperation(nextOperation);
2230 actionRequired = captureOneFrame();
2233 case GUIDE_STAR_SELECT:
2234 actionRequired = executeOneOperation(nextOperation);
2237 case GUIDE_CALIBRATING:
2238 if (guiderType == GUIDE_INTERNAL)
2240 m_GuiderInstance->setStarPosition(starCenter);
2243 if (m_Mount && m_Mount->canControlTrack() && m_Mount->isTracking() ==
false)
2244 m_Mount->setTrackEnabled(
true);
2247 if (m_GuiderInstance->calibrate())
2249 if (guiderType == GUIDE_INTERNAL)
2255 emit newStatus(GUIDE_CALIBRATION_ERROR);
2256 m_State = GUIDE_IDLE;
2257 appendLogText(
i18n(
"Calibration failed to start."));
2271 return executeOperationStack();
2274 bool Guide::executeOneOperation(GuideState operation)
2276 bool actionRequired =
false;
2278 if (m_Camera ==
nullptr)
2279 return actionRequired;
2281 ISD::CameraChip *targetChip = m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
2282 if (targetChip ==
nullptr)
2285 int subBinX, subBinY;
2286 targetChip->getBinning(&subBinX, &subBinY);
2290 case GUIDE_SUBFRAME:
2293 if ((guiderType == GUIDE_INTERNAL) && internalGuider->SEPMultiStarEnabled())
2296 if (subFramed ==
false && guideSubframe->isChecked() ==
true && targetChip->canSubframe())
2298 int minX, maxX, minY, maxY, minW, maxW, minH, maxH;
2299 targetChip->getFrameMinMax(&minX, &maxX, &minY, &maxY, &minW, &maxW, &minH, &maxH);
2301 int offset = guideSquareSize->currentText().toInt() / subBinX;
2303 int x = starCenter.
x();
2304 int y = starCenter.
y();
2306 x = (
x - offset * 2) * subBinX;
2307 y = (
y - offset * 2) * subBinY;
2308 int w = offset * 4 * subBinX;
2309 int h = offset * 4 * subBinY;
2320 targetChip->setFrame(
x,
y, w, h);
2323 QVariantMap settings = frameSettings[targetChip];
2328 settings[
"binx"] = subBinX;
2329 settings[
"biny"] = subBinY;
2331 frameSettings[targetChip] = settings;
2333 starCenter.
setX(w / (2 * subBinX));
2334 starCenter.
setY(h / (2 * subBinX));
2340 else if (subFramed &&
2341 (guideSubframe->isChecked() ==
false ||
2342 m_State == GUIDE_REACQUIRE))
2344 targetChip->resetFrame();
2347 targetChip->getFrame(&
x, &
y, &w, &h);
2349 QVariantMap settings;
2354 settings[
"binx"] = subBinX;
2355 settings[
"biny"] = subBinY;
2356 frameSettings[targetChip] = settings;
2360 starCenter.
setX(w / (2 * subBinX));
2361 starCenter.
setY(h / (2 * subBinX));
2372 if (m_ImageData && guideDarkFrame->isChecked())
2374 QVariantMap settings = frameSettings[targetChip];
2375 uint16_t offsetX = 0;
2376 uint16_t offsetY = 0;
2378 if (settings[
"x"].
isValid() &&
2379 settings[
"y"].isValid() &&
2380 settings[
"binx"].isValid() &&
2381 settings[
"biny"].isValid())
2383 offsetX = settings[
"x"].toInt() / settings[
"binx"].toInt();
2384 offsetY = settings[
"y"].toInt() / settings[
"biny"].toInt();
2387 actionRequired =
true;
2388 targetChip->setCaptureFilter(FITS_NONE);
2389 m_DarkProcessor->denoise(OpticalTrainManager::Instance()->id(opticalTrainCombo->currentText()),
2390 targetChip, m_ImageData, guideExposure->value(), offsetX, offsetY);
2395 case GUIDE_STAR_SELECT:
2397 m_State = GUIDE_STAR_SELECT;
2398 emit newStatus(m_State);
2400 if (guideAutoStar->isChecked() ||
2402 ((guiderType == GUIDE_INTERNAL) &&
2403 internalGuider->SEPMultiStarEnabled()))
2405 bool autoStarCaptured = internalGuider->selectAutoStar();
2406 if (autoStarCaptured)
2408 appendLogText(
i18n(
"Auto star selected."));
2412 appendLogText(
i18n(
"Failed to select an auto star."));
2413 actionRequired =
true;
2414 m_State = GUIDE_CALIBRATION_ERROR;
2415 emit newStatus(m_State);
2421 appendLogText(
i18n(
"Select a guide star to calibrate."));
2422 actionRequired =
true;
2431 return actionRequired;
2434 void Guide::processGuideOptions()
2436 if (Options::guiderType() != guiderType)
2438 guiderType =
static_cast<GuiderType
>(Options::guiderType());
2443 void Guide::showFITSViewer()
2445 static int lastFVTabID = -1;
2452 fv->loadData(m_ImageData, url, &lastFVTabID);
2454 else if (fv->updateData(m_ImageData, url, lastFVTabID, &lastFVTabID) ==
false)
2455 fv->loadData(m_ImageData, url, &lastFVTabID);
2461 void Guide::setExternalGuiderBLOBEnabled(
bool enable)
2464 if (guiderType == GUIDE_INTERNAL)
2470 m_Camera->setBLOBEnabled(enable);
2472 if(m_Camera->isBLOBEnabled())
2474 checkUseGuideHead();
2476 auto targetChip = m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
2478 targetChip->setCaptureMode(FITS_GUIDE);
2484 void Guide::resetNonGuidedDither()
2487 nonGuidedDitherRaOffsetMsec = 0;
2488 nonGuidedDitherDecOffsetMsec = 0;
2489 qCDebug(KSTARS_EKOS_GUIDE) <<
"Reset non guiding dithering position";
2492 if (!isNonGuidedDitherInitialized)
2494 auto seed = std::chrono::system_clock::now().time_since_epoch().count();
2495 nonGuidedPulseGenerator.seed(seed);
2496 isNonGuidedDitherInitialized =
true;
2497 qCDebug(KSTARS_EKOS_GUIDE) <<
"Initialize non guiding dithering random generator";
2501 void Guide::nonGuidedDither()
2503 double ditherPulse = Options::ditherNoGuidingPulse();
2506 std::uniform_int_distribution<int> newPos(-ditherPulse, +ditherPulse);
2511 const int newRaOffsetMsec = newPos(nonGuidedPulseGenerator);
2512 const int raPulse = nonGuidedDitherRaOffsetMsec - newRaOffsetMsec;
2513 nonGuidedDitherRaOffsetMsec = newRaOffsetMsec;
2514 const int raMsec = std::abs(raPulse);
2515 const int raPolarity = (raPulse >= 0 ? 1 : -1);
2518 const int newDecOffsetMsec = newPos(nonGuidedPulseGenerator);
2519 const int decPulse = nonGuidedDitherDecOffsetMsec - newDecOffsetMsec;
2520 nonGuidedDitherDecOffsetMsec = newDecOffsetMsec;
2521 const int decMsec = std::abs(decPulse);
2522 const int decPolarity = (decPulse >= 0 ? 1 : -1);
2524 qCInfo(KSTARS_EKOS_GUIDE) <<
"Starting non-guiding dither...";
2525 qCDebug(KSTARS_EKOS_GUIDE) <<
"dither ra_msec:" << raMsec <<
"ra_polarity:" << raPolarity <<
"de_msec:" << decMsec <<
2526 "de_polarity:" << decPolarity;
2528 bool rc = sendMultiPulse(raPolarity > 0 ? RA_INC_DIR : RA_DEC_DIR, raMsec, decPolarity > 0 ? DEC_INC_DIR : DEC_DEC_DIR,
2529 decMsec, StartCaptureAfterPulses);
2533 qCInfo(KSTARS_EKOS_GUIDE) <<
"Non-guiding dither successful.";
2534 QTimer::singleShot( (raMsec > decMsec ? raMsec : decMsec) + Options::ditherSettle() * 1000 + 100, [
this]()
2536 emit newStatus(GUIDE_DITHERING_SUCCESS);
2537 m_State = GUIDE_IDLE;
2542 qCWarning(KSTARS_EKOS_GUIDE) <<
"Non-guiding dither failed.";
2543 emit newStatus(GUIDE_DITHERING_ERROR);
2544 m_State = GUIDE_IDLE;
2548 void Guide::handleManualDither()
2550 ISD::CameraChip *targetChip = m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
2551 if (targetChip ==
nullptr)
2554 Ui::ManualDither ditherDialog;
2556 ditherDialog.setupUi(&container);
2558 if (guiderType != GUIDE_INTERNAL)
2560 ditherDialog.coordinatesR->setEnabled(
false);
2561 ditherDialog.x->setEnabled(
false);
2562 ditherDialog.y->setEnabled(
false);
2565 int minX, maxX, minY, maxY, minW, maxW, minH, maxH;
2566 targetChip->getFrameMinMax(&minX, &maxX, &minY, &maxY, &minW, &maxW, &minH, &maxH);
2568 ditherDialog.x->setMinimum(minX);
2569 ditherDialog.x->setMaximum(maxX);
2570 ditherDialog.y->setMinimum(minY);
2571 ditherDialog.y->setMaximum(maxY);
2573 ditherDialog.x->setValue(starCenter.
x());
2574 ditherDialog.y->setValue(starCenter.
y());
2578 if (ditherDialog.magnitudeR->isChecked())
2579 m_GuiderInstance->dither(ditherDialog.magnitude->value());
2582 InternalGuider *
const ig =
dynamic_cast<InternalGuider *
>(m_GuiderInstance);
2584 ig->ditherXY(ditherDialog.x->value(), ditherDialog.y->value());
2591 setStatus(GUIDE_IDLE);
2592 return m_GuiderInstance->Connect();
2597 return m_GuiderInstance->Disconnect();
2600 void Guide::initPlots()
2603 initCalibrationPlot();
2611 void Guide::initDriftGraph()
2621 driftGraph->setCorrectionGraphScale(correctionSlider->value());
2629 correctionSlider->setValue(scale);
2632 void Guide::initCalibrationPlot()
2635 calibrationPlot->setSelectionTolerance(10);
2646 calibrationPlot->xAxis->setTickLabelColor(
Qt::white);
2647 calibrationPlot->yAxis->setTickLabelColor(
Qt::white);
2649 calibrationPlot->xAxis->setLabelColor(
Qt::white);
2650 calibrationPlot->yAxis->setLabelColor(
Qt::white);
2652 calibrationPlot->xAxis->setLabelFont(
QFont(
font().family(), 10));
2653 calibrationPlot->yAxis->setLabelFont(
QFont(
font().family(), 10));
2654 calibrationPlot->xAxis->setTickLabelFont(
QFont(
font().family(), 9));
2655 calibrationPlot->yAxis->setTickLabelFont(
QFont(
font().family(), 9));
2657 calibrationPlot->xAxis->setLabelPadding(2);
2658 calibrationPlot->yAxis->setLabelPadding(2);
2664 calibrationPlot->xAxis->grid()->setZeroLinePen(
QPen(
Qt::gray));
2665 calibrationPlot->yAxis->grid()->setZeroLinePen(
QPen(
Qt::gray));
2667 calibrationPlot->xAxis->setLabel(
i18n(
"x (pixels)"));
2668 calibrationPlot->yAxis->setLabel(
i18n(
"y (pixels)"));
2670 calibrationPlot->xAxis->setRange(-20, 20);
2671 calibrationPlot->yAxis->setRange(-20, 20);
2676 calibrationPlot->addGraph();
2679 QPen(KStarsData::Instance()->colorScheme()->colorNamed(
"RAGuideError"), 2),
QBrush(), 6));
2680 calibrationPlot->graph(GuideGraph::G_RA)->setName(
"RA out");
2682 calibrationPlot->addGraph();
2686 calibrationPlot->graph(GuideGraph::G_DEC)->setName(
"RA in");
2688 calibrationPlot->addGraph();
2689 calibrationPlot->graph(GuideGraph::G_RA_HIGHLIGHT)->setLineStyle(
QCPGraph::lsNone);
2693 calibrationPlot->graph(GuideGraph::G_RA_HIGHLIGHT)->setName(
"Backlash");
2695 calibrationPlot->addGraph();
2696 calibrationPlot->graph(GuideGraph::G_DEC_HIGHLIGHT)->setLineStyle(
QCPGraph::lsNone);
2698 QPen(KStarsData::Instance()->colorScheme()->colorNamed(
"DEGuideError"), 2),
QBrush(), 6));
2699 calibrationPlot->graph(GuideGraph::G_DEC_HIGHLIGHT)->setName(
"DEC out");
2701 calibrationPlot->addGraph();
2702 calibrationPlot->graph(GuideGraph::G_RA_PULSE)->setLineStyle(
QCPGraph::lsNone);
2706 calibrationPlot->graph(GuideGraph::G_RA_PULSE)->setName(
"DEC in");
2717 calibrationPlot->resize(190, 190);
2718 calibrationPlot->replot();
2721 void Guide::initView()
2723 guideStateWidget =
new GuideStateWidget();
2724 guideInfoLayout->insertWidget(-1, guideStateWidget);
2728 m_GuideView->setBaseSize(guideWidget->size());
2729 m_GuideView->createFloatingToolBar();
2732 guideWidget->setLayout(vlayout);
2734 guideInfoLabel->setVisible(
false);
2735 guideInfoText->setVisible(
false);
2738 void Guide::initConnections()
2746 &Ekos::Guide::updateTrackingBoxSize);
2751 if(guiderType != GUIDE_PHD2)
2756 &Ekos::Guide::updateCCDBin);
2771 m_State = GUIDE_CAPTURE;
2772 emit newStatus(m_State);
2774 if(guiderType == GUIDE_PHD2)
2776 configurePHD2Camera();
2777 if(phd2Guider->isCurrentCameraNotInEkos())
2779 i18n(
"The PHD2 camera is not available to Ekos, so you cannot see the captured images. But you will still see the Guide Star Image when you guide."));
2780 else if(guideSubframe->isChecked())
2783 i18n(
"To receive PHD2 images other than the Guide Star Image, SubFrame must be unchecked. Unchecking it now to enable your image captures. You can re-enable it before Guiding"));
2784 guideSubframe->setChecked(
false);
2786 phd2Guider->captureSingleFrame();
2788 else if (guiderType == GUIDE_INTERNAL)
2809 m_GuiderInstance->Connect();
2814 m_GuiderInstance->Disconnect();
2823 &Ekos::Guide::buildTarget);
2828 driftGraph->toggleShowPlot(GuideGraph::G_RA, isChecked);
2832 driftGraph->toggleShowPlot(GuideGraph::G_DEC, isChecked);
2836 driftGraph->toggleShowPlot(GuideGraph::G_RA_PULSE, isChecked);
2840 driftGraph->toggleShowPlot(GuideGraph::G_DEC_PULSE, isChecked);
2844 driftGraph->toggleShowPlot(GuideGraph::G_SNR, isChecked);
2848 driftGraph->toggleShowPlot(GuideGraph::G_RMS, isChecked);
2854 connect(
this, &Ekos::Guide::newStatus, guideStateWidget, &Ekos::GuideStateWidget::updateGuideStatus);
2859 auto name = device->getDeviceName();
2861 device->disconnect(
this);
2864 if (m_Mount && m_Mount->getDeviceName() == name)
2872 if (m_Camera && m_Camera->getDeviceName() == name)
2880 if (m_Guider && m_Guider->getDeviceName() == name)
2882 m_Guider->disconnect(
this);
2888 if (m_AO && m_AO->getDeviceName() == name)
2897 m_State = GUIDE_LOOPING;
2898 emit newStatus(m_State);
2900 if(guiderType == GUIDE_PHD2)
2902 configurePHD2Camera();
2903 if(phd2Guider->isCurrentCameraNotInEkos())
2905 i18n(
"The PHD2 camera is not available to Ekos, so you cannot see the captured images. But you will still see the Guide Star Image when you guide."));
2906 else if(guideSubframe->isChecked())
2909 i18n(
"To receive PHD2 images other than the Guide Star Image, SubFrame must be unchecked. Unchecking it now to enable your image captures. You can re-enable it before Guiding"));
2910 guideSubframe->setChecked(
false);
2913 stopB->setEnabled(
true);
2915 else if (guiderType == GUIDE_INTERNAL)
2922 QVariantMap Guide::getAllSettings()
const
2924 QVariantMap settings;
2927 for (
auto &oneWidget : findChildren<QComboBox*>())
2928 settings.insert(oneWidget->objectName(), oneWidget->currentText());
2931 for (
auto &oneWidget : findChildren<QDoubleSpinBox*>())
2932 settings.insert(oneWidget->objectName(), oneWidget->value());
2935 for (
auto &oneWidget : findChildren<QSpinBox*>())
2936 settings.insert(oneWidget->objectName(), oneWidget->value());
2939 for (
auto &oneWidget : findChildren<QCheckBox*>())
2940 settings.insert(oneWidget->objectName(), oneWidget->isChecked());
2948 void Guide::setAllSettings(
const QVariantMap &settings)
2952 disconnectSettings();
2954 for (
auto &name : settings.keys())
2957 auto comboBox = findChild<QComboBox*>(name);
2960 syncControl(settings, name, comboBox);
2965 auto doubleSpinBox = findChild<QDoubleSpinBox*>(name);
2968 syncControl(settings, name, doubleSpinBox);
2973 auto spinBox = findChild<QSpinBox*>(name);
2976 syncControl(settings, name, spinBox);
2981 auto checkbox = findChild<QCheckBox*>(name);
2984 syncControl(settings, name, checkbox);
2990 for (
auto &key : settings.keys())
2992 auto value = settings[key];
2994 Options::self()->setProperty(key.toLatin1(), value);
2995 Options::self()->save();
2997 m_Settings[key] = value;
2998 m_GlobalSettings[key] = value;
3001 emit settingsUpdated(getAllSettings());
3004 OpticalTrainSettings::Instance()->setOpticalTrainID(OpticalTrainManager::Instance()->
id(opticalTrainCombo->currentText()));
3005 OpticalTrainSettings::Instance()->setOneSetting(OpticalTrainSettings::Guide, m_Settings);
3014 bool Guide::syncControl(
const QVariantMap &settings,
const QString &key,
QWidget * widget)
3022 if ((pSB = qobject_cast<QSpinBox *>(widget)))
3024 const int value = settings[key].toInt(&ok);
3031 else if ((pDSB = qobject_cast<QDoubleSpinBox *>(widget)))
3033 const double value = settings[key].toDouble(&ok);
3040 else if ((pCB = qobject_cast<QCheckBox *>(widget)))
3042 const bool value = settings[key].toBool();
3047 else if ((pComboBox = qobject_cast<QComboBox *>(widget)))
3049 const QString value = settings[key].toString();
3057 void Guide::setupOpticalTrainManager()
3059 connect(OpticalTrainManager::Instance(), &OpticalTrainManager::updated,
this, &Guide::refreshOpticalTrain);
3062 OpticalTrainManager::Instance()->openEditor(opticalTrainCombo->currentText());
3066 ProfileSettings::Instance()->setOneSetting(ProfileSettings::GuideOpticalTrain,
3067 OpticalTrainManager::Instance()->
id(opticalTrainCombo->itemText(index)));
3068 refreshOpticalTrain();
3069 emit trainChanged();
3071 refreshOpticalTrain();
3074 void Guide::refreshOpticalTrain()
3076 opticalTrainCombo->blockSignals(
true);
3077 opticalTrainCombo->clear();
3078 opticalTrainCombo->addItems(OpticalTrainManager::Instance()->getTrainNames());
3079 trainB->setEnabled(opticalTrainCombo->count() > 0);
3081 QVariant trainID = ProfileSettings::Instance()->getOneSetting(ProfileSettings::GuideOpticalTrain);
3085 auto id = trainID.
toUInt();
3086 auto name = OpticalTrainManager::Instance()->name(
id);
3088 opticalTrainCombo->setCurrentText(name);
3090 auto scope = OpticalTrainManager::Instance()->getScope(name);
3091 m_FocalLength = scope[
"focal_length"].
toDouble(-1);
3092 m_Aperture = scope[
"aperture"].toDouble(-1);
3093 m_FocalRatio = scope[
"focal_ratio"].toDouble(-1);
3094 m_Reducer = OpticalTrainManager::Instance()->getReducer(name);
3097 if (m_Aperture < 0 && m_FocalRatio > 0)
3098 m_Aperture = m_FocalLength * m_FocalRatio;
3100 auto mount = OpticalTrainManager::Instance()->getMount(name);
3103 auto camera = OpticalTrainManager::Instance()->getCamera(name);
3106 if (guiderType == GUIDE_INTERNAL)
3109 camera->setScopeInfo(m_FocalLength * m_Reducer, m_Aperture);
3111 auto scope = OpticalTrainManager::Instance()->getScope(name);
3112 opticalTrainCombo->setToolTip(
QString(
"%1 @ %2").arg(camera->getDeviceName(), scope[
"name"].toString()));
3116 syncTelescopeInfo();
3118 auto guider = OpticalTrainManager::Instance()->getGuider(name);
3121 auto ao = OpticalTrainManager::Instance()->getAdaptiveOptics(name);
3125 OpticalTrainSettings::Instance()->setOpticalTrainID(
id);
3126 auto settings = OpticalTrainSettings::Instance()->getOneSetting(OpticalTrainSettings::Guide);
3127 if (settings.isValid())
3128 setAllSettings(settings.toJsonObject().toVariantMap());
3130 m_Settings = m_GlobalSettings;
3133 opticalTrainCombo->blockSignals(
false);
3136 void Guide::loadGlobalSettings()
3141 QVariantMap settings;
3143 for (
auto &oneWidget : findChildren<QComboBox*>())
3145 if (oneWidget->objectName() ==
"opticalTrainCombo")
3148 key = oneWidget->objectName();
3149 value = Options::self()->property(key.
toLatin1());
3152 oneWidget->setCurrentText(value.
toString());
3153 settings[key] = value;
3158 for (
auto &oneWidget : findChildren<QDoubleSpinBox*>())
3160 key = oneWidget->objectName();
3161 value = Options::self()->property(key.
toLatin1());
3165 settings[key] = value;
3170 for (
auto &oneWidget : findChildren<QSpinBox*>())
3172 key = oneWidget->objectName();
3173 value = Options::self()->property(key.
toLatin1());
3177 settings[key] = value;
3182 for (
auto &oneWidget : findChildren<QCheckBox*>())
3184 key = oneWidget->objectName();
3185 value = Options::self()->property(key.
toLatin1());
3188 oneWidget->setChecked(value.
toBool());
3189 settings[key] = value;
3193 m_GlobalSettings = m_Settings = settings;
3196 void Guide::connectSettings()
3199 for (
auto &oneWidget : findChildren<QComboBox*>())
3203 for (
auto &oneWidget : findChildren<QDoubleSpinBox*>())
3207 for (
auto &oneWidget : findChildren<QSpinBox*>())
3211 for (
auto &oneWidget : findChildren<QCheckBox*>())
3218 void Guide::disconnectSettings()
3221 for (
auto &oneWidget : findChildren<QComboBox*>())
3225 for (
auto &oneWidget : findChildren<QDoubleSpinBox*>())
3229 for (
auto &oneWidget : findChildren<QSpinBox*>())
3233 for (
auto &oneWidget : findChildren<QCheckBox*>())
3241 Options::self()->setProperty(key.
toLatin1(), value);
3242 Options::self()->save();
3244 m_Settings[key] = value;
3245 m_GlobalSettings[key] = value;
3247 emit settingsUpdated(getAllSettings());
3250 OpticalTrainSettings::Instance()->setOpticalTrainID(OpticalTrainManager::Instance()->
id(opticalTrainCombo->currentText()));
3251 OpticalTrainSettings::Instance()->setOneSetting(OpticalTrainSettings::Guide, m_Settings);
3254 void Guide::syncSettings()
3264 if ( (dsb = qobject_cast<QDoubleSpinBox*>(
sender())))
3267 value = dsb->
value();
3270 else if ( (sb = qobject_cast<QSpinBox*>(
sender())))
3273 value = sb->
value();
3275 else if ( (cb = qobject_cast<QCheckBox*>(
sender())))
3280 else if ( (cbox = qobject_cast<QComboBox*>(
sender())))