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"
33 #include "guidestatewidget.h"
34 #include "manualpulse.h"
35 #include "ekos/auxiliary/darkprocessor.h"
37 #include <KConfigDialog>
39 #include <basedevice.h>
40 #include <ekos_guide_debug.h>
42 #include "ui_manualdither.h"
46 #define CAPTURE_TIMEOUT_THRESHOLD 30000
53 internalGuider =
new InternalGuider();
57 opsGuide =
new OpsGuide();
60 connect(opsGuide, &OpsGuide::settingsUpdated,
this, [
this]()
62 onThresholdChanged(Options::guideAlgorithm());
63 configurePHD2Camera();
64 configSEPMultistarOptions();
68 opsCalibration =
new OpsCalibration(internalGuider);
69 page = dialog->
addPage(opsCalibration,
i18n(
"Calibration"));
72 opsDither =
new OpsDither();
76 opsGPG =
new OpsGPG(internalGuider);
77 page = dialog->
addPage(opsGPG,
i18n(
"GPG RA Guider"));
84 qRegisterMetaType<Ekos::GuideState>(
"Ekos::GuideState");
85 qDBusRegisterMetaType<Ekos::GuideState>();
86 new GuideAdaptor(
this);
94 internalGuider->setGuideView(m_GuideView);
101 controlLayout->addWidget(pi, 1, 2, 1, 1);
103 showFITSViewerB->setIcon(
108 guideAutoScaleGraphB->setIcon(
113 guideSaveDataB->setIcon(
118 guideDataClearB->setIcon(
125 guideZoomInXB->setText(
"+");
131 guideZoomOutXB->setText(
"-");
136 focalLengthIcon->setPixmap(
QIcon::fromTheme(
"gnumeric-formulaguru").pixmap(32, 32));
138 reducerIcon->setPixmap(
QIcon::fromTheme(
"format-align-vertical-bottom").pixmap(32, 32));
139 FOVIcon->setPixmap(
QIcon::fromTheme(
"timeline-use-zone-on").pixmap(32, 32));
140 focalRatioIcon->setPixmap(
QIcon::fromTheme(
"node-type-symmetric").pixmap(32, 32));
145 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
147 guideExposure->setRecommendedValues(exposureValues);
148 connect(guideExposure, &NonLinearDoubleSpinBox::editingFinished,
this, &Ekos::Guide::saveDefaultGuideExposure);
154 if(guiderType == GUIDE_PHD2)
156 setExternalGuiderBLOBEnabled(!Options::guideSubframe());
161 opsDither->kcfg_DitherTimeout->setEnabled(
false);
162 opsDither->kcfg_DitherThreshold->setEnabled(
false);
163 opsDither->kcfg_DitherMaxIterations->setEnabled(!Options::ditherWithOnePulse());
167 resetNonGuidedDither();
172 for (
auto &button : qButtons)
173 button->setAutoDefault(
false);
177 m_DarkProcessor =
new DarkProcessor(
this);
178 connect(m_DarkProcessor, &DarkProcessor::newLog,
this, &Ekos::Guide::appendLogText);
179 connect(m_DarkProcessor, &DarkProcessor::darkFrameCompleted,
this, [
this](
bool completed)
181 if (completed != guideDarkFrame->isChecked())
182 setDarkFrameEnabled(completed);
183 m_GuideView->setProperty(
"suspended",
false);
186 m_GuideView->rescale(ZOOM_KEEP_LEVEL);
187 m_GuideView->updateFrame();
189 m_GuideView->updateFrame();
190 setCaptureComplete();
193 m_ManaulPulse =
new ManualPulse(
this);
194 connect(m_ManaulPulse, &ManualPulse::newSinglePulse,
this, &Guide::sendSinglePulse);
197 m_ManaulPulse->reset();
198 m_ManaulPulse->show();
201 loadGlobalSettings();
204 setupOpticalTrainManager();
209 delete m_GuiderInstance;
212 void Guide::handleHorizontalPlotSizeChange()
214 targetPlot->handleHorizontalPlotSizeChange();
215 calibrationPlot->xAxis->setScaleRatio(calibrationPlot->yAxis, 1.0);
216 calibrationPlot->replot();
219 void Guide::handleVerticalPlotSizeChange()
221 targetPlot->handleVerticalPlotSizeChange();
222 calibrationPlot->yAxis->setScaleRatio(calibrationPlot->xAxis, 1.0);
223 calibrationPlot->replot();
226 void Guide::guideAfterMeridianFlip()
230 m_GuideView->setTrackingBoxEnabled(
false);
233 if (Options::resetGuideCalibration())
237 if (Options::gPGEnabled())
238 m_GuiderInstance->resetGPG();
245 if (
event->oldSize().width() != -1)
247 if (
event->oldSize().width() != size().width())
248 handleHorizontalPlotSizeChange();
249 else if (
event->oldSize().height() != size().height())
250 handleVerticalPlotSizeChange();
258 void Guide::buildTarget()
260 targetPlot->buildTarget(guiderAccuracyThreshold->value());
263 void Guide::clearGuideGraphs()
269 void Guide::clearCalibrationGraphs()
271 calibrationPlot->graph(GuideGraph::G_RA)->data()->clear();
272 calibrationPlot->graph(GuideGraph::G_DEC)->data()->clear();
273 calibrationPlot->graph(GuideGraph::G_RA_HIGHLIGHT)->data()->clear();
274 calibrationPlot->graph(GuideGraph::G_DEC_HIGHLIGHT)->data()->clear();
275 calibrationPlot->graph(GuideGraph::G_RA_PULSE)->data()->clear();
276 calibrationPlot->replot();
279 void Guide::slotAutoScaleGraphs()
281 driftGraph->zoomX(defaultXZoomLevel);
283 driftGraph->autoScaleGraphs();
284 targetPlot->autoScaleGraphs(guiderAccuracyThreshold->value());
286 calibrationPlot->rescaleAxes();
287 calibrationPlot->yAxis->setScaleRatio(calibrationPlot->xAxis, 1.0);
288 calibrationPlot->xAxis->setScaleRatio(calibrationPlot->yAxis, 1.0);
289 calibrationPlot->replot();
292 void Guide::guideHistory()
294 int sliderValue = guideSlider->value();
295 latestCheck->setChecked(sliderValue == guideSlider->maximum() - 1 || sliderValue == guideSlider->maximum());
296 double ra = driftGraph->graph(GuideGraph::G_RA)->dataMainValue(sliderValue);
297 double de = driftGraph->graph(GuideGraph::G_DEC)->dataMainValue(sliderValue);
298 driftGraph->guideHistory(sliderValue, graphOnLatestPt);
300 targetPlot->showPoint(ra, de);
303 void Guide::setLatestGuidePoint(
bool isChecked)
305 graphOnLatestPt = isChecked;
306 driftGraph->setLatestGuidePoint(isChecked);
307 targetPlot->setLatestGuidePoint(isChecked);
310 guideSlider->setValue(guideSlider->maximum());
315 guideExposure->setRecommendedValues(values);
316 return guideExposure->getRecommendedValuesString();
321 if (m_Camera && device == m_Camera)
328 m_Camera->disconnect(
this);
334 connect(m_Camera, &ISD::Camera::Connected,
this, [
this]()
336 controlGroupBox->setEnabled(
true);
338 connect(m_Camera, &ISD::ConcreteDevice::Disconnected,
this, [
this]()
340 controlGroupBox->setEnabled(
false);
344 controlGroupBox->setEnabled(m_Camera && m_Camera->isConnected());
350 if(guiderType != GUIDE_INTERNAL)
351 m_Camera->setBLOBEnabled(
false);
354 configurePHD2Camera();
358 void Guide::configurePHD2Camera()
362 if(guiderType != GUIDE_PHD2)
369 if(!phd2Guider->isConnected())
373 if(phd2Guider->getCurrentCamera().isEmpty())
375 phd2Guider->requestCurrentEquipmentUpdate();
381 QString currentPHD2CameraName =
"None";
382 if(m_Camera && phd2Guider->getCurrentCamera().contains(m_Camera->getDeviceName()))
385 currentPHD2CameraName = (phd2Guider->getCurrentCamera());
391 if(m_LastPHD2CameraName == currentPHD2CameraName)
393 setExternalGuiderBLOBEnabled(!guideSubframe->isChecked());
399 setExternalGuiderBLOBEnabled(
false);
405 m_LastPHD2CameraName = currentPHD2CameraName;
407 m_LastPHD2MountName = phd2Guider->getCurrentMount();
410 phd2Guider->setCurrentCameraIsNotInEkos(m_Camera ==
nullptr);
412 if(phd2Guider->isCurrentCameraNotInEkos())
415 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.",
416 phd2Guider->getCurrentCamera()));
417 guideSubframe->setEnabled(
false);
420 guideSubframe->setChecked(
true);
425 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.",
426 phd2Guider->getCurrentCamera()));
427 guideSubframe->setEnabled(
true);
429 guideSubframe->setChecked(guideSubframe->isChecked());
434 if (m_Mount && m_Mount == device)
441 m_Mount->disconnect(
this);
451 return m_Camera->getDeviceName();
456 void Guide::checkCamera()
460 if (!m_Camera || guiderType != GUIDE_INTERNAL)
468 case GUIDE_CONNECTED:
469 case GUIDE_DISCONNECTED:
470 case GUIDE_CALIBRATION_ERROR:
478 case GUIDE_STAR_SELECT:
479 case GUIDE_CALIBRATING:
480 case GUIDE_CALIBRATION_SUCCESS:
482 case GUIDE_SUSPENDED:
483 case GUIDE_REACQUIRE:
484 case GUIDE_DITHERING:
485 case GUIDE_MANUAL_DITHERING:
486 case GUIDE_DITHERING_ERROR:
487 case GUIDE_DITHERING_SUCCESS:
488 case GUIDE_DITHERING_SETTLE:
495 ISD::CameraChip *targetChip = m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
498 qCCritical(KSTARS_EKOS_GUIDE) <<
"Failed to retrieve active guide chip in camera";
502 if (targetChip->isCapturing())
505 if (guiderType != GUIDE_INTERNAL)
517 void Ekos::Guide::checkUseGuideHead()
519 if (m_Camera ==
nullptr)
522 if (m_Camera->hasGuideHead() && Options::useGuideHead())
525 useGuideHead =
false;
527 opsGuide->kcfg_UseGuideHead->
setEnabled(m_Camera->hasGuideHead());
530 void Guide::syncCameraInfo()
535 auto nvp = m_Camera->getNumber(useGuideHead ?
"GUIDER_INFO" :
"CCD_INFO");
539 auto np = nvp->findWidgetByName(
"CCD_PIXEL_SIZE_X");
541 ccdPixelSizeX = np->getValue();
543 np = nvp->findWidgetByName(
"CCD_PIXEL_SIZE_Y");
545 ccdPixelSizeY = np->getValue();
547 np = nvp->findWidgetByName(
"CCD_PIXEL_SIZE_Y");
549 ccdPixelSizeY = np->getValue();
555 void Guide::syncTelescopeInfo()
557 if (m_Mount ==
nullptr || m_Mount->isConnected() ==
false)
563 void Guide::updateGuideParams()
565 if (m_Camera ==
nullptr)
570 ISD::CameraChip *targetChip = m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
572 if (targetChip ==
nullptr)
574 appendLogText(
i18n(
"Connection to the guide CCD is lost."));
578 if (targetChip->getFrameType() != FRAME_LIGHT)
581 if(guiderType == GUIDE_INTERNAL)
582 guideBinning->setEnabled(targetChip->canBin());
584 int subBinX = 1, subBinY = 1;
585 if (targetChip->canBin())
587 int maxBinX, maxBinY;
589 targetChip->getBinning(&subBinX, &subBinY);
590 targetChip->getMaxBin(&maxBinX, &maxBinY);
593 if( guideBinIndex >= 0 && guideBinIndex < maxBinX && guideBinIndex < maxBinY )
595 subBinX = guideBinIndex + 1;
596 subBinY = guideBinIndex + 1;
599 guideBinIndex = subBinX - 1;
601 guideBinning->blockSignals(
true);
603 guideBinning->clear();
604 for (
int i = 1; i <= maxBinX; i++)
605 guideBinning->addItem(
QString(
"%1x%2").arg(i).arg(i));
607 guideBinning->setCurrentIndex( guideBinIndex );
609 guideBinning->blockSignals(
false);
613 if (frameSettings.
contains(targetChip) ==
false)
616 if (targetChip->getFrame(&
x, &
y, &w, &h))
620 int minX, maxX, minY, maxY, minW, maxW, minH, maxH;
621 targetChip->getFrameMinMax(&minX, &maxX, &minY, &maxY, &minW, &maxW, &minH, &maxH);
622 auto subframed = guideSubframe->isChecked();
624 QVariantMap settings;
626 settings[
"x"] = subframed ?
x : minX;
627 settings[
"y"] = subframed ?
y : minY;
628 settings[
"w"] = subframed ? w : maxW;
629 settings[
"h"] = subframed ? h : maxH;
630 settings[
"binx"] = subBinX;
631 settings[
"biny"] = subBinY;
633 frameSettings[targetChip] = settings;
640 QVariantMap settings = frameSettings[targetChip];
641 settings[
"binx"] = subBinX;
642 settings[
"biny"] = subBinY;
643 frameSettings[targetChip] = settings;
646 if (ccdPixelSizeX != -1 && ccdPixelSizeY != -1 && m_FocalLength > 0)
648 auto effectiveFocaLength = m_Reducer * m_FocalLength;
649 m_GuiderInstance->setGuiderParams(ccdPixelSizeX, ccdPixelSizeY, m_Aperture, effectiveFocaLength);
650 emit guideChipUpdated(targetChip);
653 if (targetChip->getFrame(&
x, &
y, &w, &h))
655 m_GuiderInstance->setFrameParams(
x,
y, w, h, subBinX, subBinY);
658 l_Focal->setText(
QString(
"%1mm").arg(m_FocalLength, 0,
'f', 0));
660 l_Aperture->setText(
QString(
"%1mm").arg(m_Aperture, 0,
'f', 0));
663 l_Aperture->setText(
"DSLR");
666 if (m_FocalRatio > 0)
667 l_FbyD->setText(
QString(
"F/%1").arg(m_FocalRatio, 0,
'f', 1));
668 else if (m_Aperture > 0)
669 l_FbyD->setText(
QString(
"F/%1").arg(m_FocalLength / m_Aperture, 0,
'f', 1));
672 pixScaleX = 206264.8062470963552 * ccdPixelSizeX / 1000.0 / effectiveFocaLength;
673 pixScaleY = 206264.8062470963552 * ccdPixelSizeY / 1000.0 / effectiveFocaLength;
676 double fov_w = (w * pixScaleX) / 60.0;
677 double fov_h = (h * pixScaleY) / 60.0;
685 if (guiderType != GUIDE_INTERNAL || (m_Guider && device == m_Guider))
689 m_Guider->disconnect(
this);
695 connect(m_Guider, &ISD::ConcreteDevice::Connected,
this, [
this]()
697 guideB->setEnabled(
true);
699 connect(m_Guider, &ISD::ConcreteDevice::Disconnected,
this, [
this]()
701 guideB->setEnabled(
false);
705 guideB->setEnabled(m_Guider && m_Guider->isConnected());
711 if (guiderType != GUIDE_INTERNAL || (m_AO && device == m_AO))
724 if (guiderType != GUIDE_INTERNAL || m_Guider ==
nullptr)
727 return m_Guider->getDeviceName();
732 buildOperationStack(GUIDE_CAPTURE);
734 return executeOperationStack();
737 bool Guide::captureOneFrame()
739 captureTimeout.
stop();
741 if (m_Camera ==
nullptr)
744 if (m_Camera->isConnected() ==
false)
746 appendLogText(
i18n(
"Error: lost connection to CCD."));
750 double seqExpose = guideExposure->value();
752 ISD::CameraChip *targetChip = m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
754 prepareCapture(targetChip);
756 m_GuideView->setBaseSize(guideWidget->size());
760 if (frameSettings.
contains(targetChip))
762 QVariantMap settings = frameSettings[targetChip];
763 targetChip->setFrame(settings[
"x"].toInt(), settings[
"y"].toInt(), settings[
"w"].toInt(),
764 settings[
"h"].toInt());
765 targetChip->setBinning(settings[
"binx"].toInt(), settings[
"biny"].toInt());
769 qCDebug(KSTARS_EKOS_GUIDE) <<
"Capturing frame...";
771 double finalExposure = seqExpose;
775 if (operationStack.contains(GUIDE_STAR_SELECT) && guideAutoStar->isChecked() &&
776 !((guiderType == GUIDE_INTERNAL) && internalGuider->SEPMultiStarEnabled()))
780 m_GuideView->setProperty(
"suspended", operationStack.contains(GUIDE_DARK));
783 captureTimeout.
start(finalExposure * 1000 + CAPTURE_TIMEOUT_THRESHOLD);
785 targetChip->capture(finalExposure);
792 targetChip->setBatchMode(
false);
793 targetChip->setCaptureMode(FITS_GUIDE);
794 targetChip->setFrameType(FRAME_LIGHT);
795 targetChip->setCaptureFilter(FITS_NONE);
796 m_Camera->setEncodingFormat(
"FITS");
799 void Guide::abortExposure()
801 if (m_Camera && guiderType == GUIDE_INTERNAL)
803 captureTimeout.
stop();
806 m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
807 if (targetChip->isCapturing())
809 qCDebug(KSTARS_EKOS_GUIDE) <<
"Aborting guide capture";
810 targetChip->abortExposure();
817 if (m_Camera && guiderType == GUIDE_INTERNAL)
819 captureTimeout.
stop();
822 m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
823 if (targetChip->isCapturing())
824 targetChip->abortExposure();
827 manualDitherB->setEnabled(
false);
834 case GUIDE_CONNECTED:
835 case GUIDE_DISCONNECTED:
838 case GUIDE_CALIBRATING:
839 case GUIDE_DITHERING:
840 case GUIDE_STAR_SELECT:
844 m_GuiderInstance->abort();
854 void Guide::setBusy(
bool enable)
858 else if (enable ==
false && pi->
isAnimated() ==
false)
863 clearCalibrationB->setEnabled(
false);
864 guideB->setEnabled(
false);
865 captureB->setEnabled(
false);
866 loopB->setEnabled(
false);
867 guideDarkFrame->setEnabled(
false);
868 guideSubframe->setEnabled(
false);
869 guideAutoStar->setEnabled(
false);
870 stopB->setEnabled(
true);
872 opticalTrainCombo->setEnabled(
false);
873 trainB->setEnabled(
false);
879 if(guiderType != GUIDE_LINGUIDER)
881 captureB->setEnabled(
true);
882 loopB->setEnabled(
true);
883 guideAutoStar->setEnabled(!internalGuider->SEPMultiStarEnabled());
885 guideSubframe->setEnabled(!internalGuider->SEPMultiStarEnabled());
887 if (guiderType == GUIDE_INTERNAL)
888 guideDarkFrame->setEnabled(
true);
890 if (calibrationComplete ||
891 ((guiderType == GUIDE_INTERNAL) &&
892 Options::reuseGuideCalibration() &&
893 !Options::serializedCalibration().isEmpty()))
894 clearCalibrationB->setEnabled(
true);
895 guideB->setEnabled(
true);
896 stopB->setEnabled(
false);
900 opticalTrainCombo->setEnabled(
true);
901 trainB->setEnabled(
true);
907 void Guide::processCaptureTimeout()
909 auto restartExposure = [&]()
911 appendLogText(
i18n(
"Exposure timeout. Restarting exposure..."));
912 m_Camera->setEncodingFormat(
"FITS");
913 ISD::CameraChip *targetChip = m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
914 targetChip->abortExposure();
915 prepareCapture(targetChip);
916 targetChip->capture(guideExposure->value());
917 captureTimeout.
start(guideExposure->value() * 1000 + CAPTURE_TIMEOUT_THRESHOLD);
920 m_CaptureTimeoutCounter++;
922 if (m_Camera ==
nullptr)
925 if (m_DeviceRestartCounter >= 3)
927 m_CaptureTimeoutCounter = 0;
928 m_DeviceRestartCounter = 0;
929 if (m_State == GUIDE_GUIDING)
930 appendLogText(
i18n(
"Exposure timeout. Aborting Autoguide."));
931 else if (m_State == GUIDE_DITHERING)
932 appendLogText(
i18n(
"Exposure timeout. Aborting Dithering."));
933 else if (m_State == GUIDE_CALIBRATING)
934 appendLogText(
i18n(
"Exposure timeout. Aborting Calibration."));
936 captureTimeout.
stop();
941 if (m_CaptureTimeoutCounter > 1)
943 QString camera = m_Camera->getDeviceName();
944 QString via = m_Guider ? m_Guider->getDeviceName() :
"";
945 ISD::CameraChip *targetChip = m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
946 QVariantMap settings = frameSettings[targetChip];
947 emit driverTimedout(camera);
950 m_DeviceRestartCounter++;
951 reconnectDriver(camera, settings);
960 void Guide::reconnectDriver(
const QString &camera, QVariantMap settings)
962 if (m_Camera && m_Camera->getDeviceName() == camera)
965 Ekos::GuideState currentState = m_State;
966 m_State = GUIDE_IDLE;
969 m_State = currentState;
971 if (guiderType == GUIDE_INTERNAL)
974 ISD::CameraChip *targetChip = m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
975 frameSettings[targetChip] = settings;
977 m_CaptureTimeoutCounter = 0;
986 reconnectDriver(camera, settings);
992 ISD::CameraChip *targetChip = m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
993 if (targetChip->getCaptureMode() != FITS_GUIDE)
997 QString blobInfo =
QString(
"{Device: %1 Property: %2 Element: %3 Chip: %4}").
arg(data->property(
"device").toString())
998 .
arg(data->property(
"blobVector").toString())
999 .
arg(data->property(
"blobElement").toString())
1000 .
arg(data->property(
"chip").toInt());
1002 qCWarning(KSTARS_EKOS_GUIDE) << blobInfo <<
"Ignoring Received FITS as it has the wrong capture mode" <<
1003 targetChip->getCaptureMode();
1011 m_GuideView->loadData(data);
1015 m_ImageData.
reset();
1017 if (guiderType == GUIDE_INTERNAL)
1018 internalGuider->setImageData(m_ImageData);
1020 captureTimeout.
stop();
1021 m_CaptureTimeoutCounter = 0;
1027 int subBinX = 1, subBinY = 1;
1028 targetChip->getBinning(&subBinX, &subBinY);
1030 if (starCenter.
x() == 0 && starCenter.
y() == 0)
1032 int x = 0,
y = 0, w = 0, h = 0;
1034 if (frameSettings.
contains(targetChip))
1036 QVariantMap settings = frameSettings[targetChip];
1037 x = settings[
"x"].toInt();
1038 y = settings[
"y"].toInt();
1039 w = settings[
"w"].toInt();
1040 h = settings[
"h"].toInt();
1043 targetChip->getFrame(&
x, &
y, &w, &h);
1045 starCenter.
setX(w / (2 * subBinX));
1046 starCenter.
setY(h / (2 * subBinY));
1047 starCenter.
setZ(subBinX);
1050 syncTrackingBoxPosition();
1053 setCaptureComplete();
1058 void Guide::setCaptureComplete()
1060 if (!m_GuideView.
isNull())
1061 m_GuideView->clearNeighbors();
1063 DarkLibrary::Instance()->disconnect(
this);
1065 if (operationStack.isEmpty() ==
false)
1067 executeOperationStack();
1071 qCDebug(KSTARS_EKOS_GUIDE) <<
"Capture complete, state=" << getGuideStatusString(m_State);
1076 case GUIDE_CONNECTED:
1077 case GUIDE_DISCONNECTED:
1078 case GUIDE_CALIBRATION_SUCCESS:
1079 case GUIDE_CALIBRATION_ERROR:
1080 case GUIDE_DITHERING_ERROR:
1085 qCDebug(KSTARS_EKOS_GUIDE) <<
"Guiding capture complete.";
1086 m_State = GUIDE_IDLE;
1087 emit newStatus(m_State);
1095 case GUIDE_CALIBRATING:
1096 m_GuiderInstance->calibrate();
1100 m_GuiderInstance->guide();
1103 case GUIDE_DITHERING:
1104 m_GuiderInstance->dither(Options::ditherPixels());
1108 case GUIDE_MANUAL_DITHERING:
1109 dynamic_cast<InternalGuider*
>(m_GuiderInstance)->processManualDithering();
1112 case GUIDE_REACQUIRE:
1113 m_GuiderInstance->reacquire();
1116 case GUIDE_DITHERING_SETTLE:
1117 if (Options::ditherNoGuiding())
1122 case GUIDE_SUSPENDED:
1123 if (Options::gPGEnabled())
1124 m_GuiderInstance->guide();
1131 emit newImage(m_GuideView);
1132 emit newStarPixmap(m_GuideView->getTrackingBoxPixmap(10));
1135 void Guide::appendLogText(
const QString &text)
1137 m_LogText.
insert(0,
i18nc(
"log entry; %1 is the date, %2 is the text",
"%1 %2",
1138 KStarsData::Instance()->lt().
toString(
"yyyy-MM-ddThh:mm:ss"), text));
1140 qCInfo(KSTARS_EKOS_GUIDE) << text;
1153 if (m_Guider ==
nullptr || m_GuiderInstance ==
nullptr)
1156 if (guiderType == GUIDE_INTERNAL)
1158 dynamic_cast<InternalGuider *
>(m_GuiderInstance)->
setDECSwap(enable);
1159 m_Guider->setDECSwap(enable);
1163 bool Guide::sendMultiPulse(GuideDirection ra_dir,
int ra_msecs, GuideDirection dec_dir,
int dec_msecs,
1164 CaptureAfterPulses followWithCapture)
1166 if (m_Guider ==
nullptr || (ra_dir == NO_DIR && dec_dir == NO_DIR))
1169 if (followWithCapture == StartCaptureAfterPulses)
1173 auto ms = std::max(ra_msecs, dec_msecs) + 100;
1174 auto delay = std::max(
static_cast<int>(guideDelay->value() * 1000), ms);
1176 m_PulseTimer.
start(delay);
1178 return m_Guider->doPulse(ra_dir, ra_msecs, dec_dir, dec_msecs);
1181 bool Guide::sendSinglePulse(GuideDirection dir,
int msecs, CaptureAfterPulses followWithCapture)
1183 if (m_Guider ==
nullptr || dir == NO_DIR)
1186 if (followWithCapture == StartCaptureAfterPulses)
1190 auto ms = msecs + 100;
1191 auto delay = std::max(
static_cast<int>(guideDelay->value() * 1000), ms);
1193 m_PulseTimer.
start(delay);
1196 return m_Guider->doPulse(dir, msecs);
1202 m_State = GUIDE_IDLE;
1203 qCDebug(KSTARS_EKOS_GUIDE) <<
"Calibrating...";
1204 emit newStatus(m_State);
1206 if (guiderType == GUIDE_INTERNAL)
1210 qCCritical(KSTARS_EKOS_GUIDE) <<
"No camera detected. Check optical trains.";
1214 auto targetChip = m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
1216 if (frameSettings.
contains(targetChip))
1218 targetChip->resetFrame();
1220 targetChip->getFrame(&
x, &
y, &w, &h);
1221 QVariantMap settings = frameSettings[targetChip];
1226 frameSettings[targetChip] = settings;
1232 buildOperationStack(GUIDE_CALIBRATING);
1234 executeOperationStack();
1236 if (m_Camera && m_Guider)
1238 qCDebug(KSTARS_EKOS_GUIDE) <<
"Starting calibration using camera:" << m_Camera->getDeviceName() <<
"via" <<
1239 m_Guider->getDeviceName();
1247 auto executeGuide = [
this]()
1249 if(guiderType != GUIDE_PHD2)
1251 if (calibrationComplete ==
false)
1258 m_GuiderInstance->guide();
1264 if(!guideAutoStar->isChecked())
1266 if(guiderType == GUIDE_PHD2 && m_GuideView->isTrackingBoxEnabled())
1268 double x = starCenter.
x();
1269 double y = starCenter.
y();
1271 if(!m_ImageData.
isNull())
1273 if(m_ImageData->width() > 50)
1275 guideConnect =
connect(
this, &Guide::newStatus,
this, [
this,
x,
y](Ekos::GuideState newState)
1277 if(newState == GUIDE_GUIDING)
1279 phd2Guider->setLockPosition(
x,
y);
1289 if (m_MountStatus == ISD::Mount::MOUNT_PARKED)
1291 KSMessageBox::Instance()->sorry(
i18n(
"The mount is parked. Unpark to start guiding."));
1301 if (Options::ditherNoGuiding() && m_State == GUIDE_IDLE)
1307 if (m_State == GUIDE_DITHERING || m_State == GUIDE_DITHERING_SETTLE)
1311 double time = guideTimer.
elapsed() / 1000.0;
1315 ditherLabel->position->
setCoords(time, 1.5);
1319 ditherLabel->
setText(
"Dither");
1322 if (guiderType == GUIDE_INTERNAL && !Options::ditherWithOnePulse())
1324 if (m_State != GUIDE_GUIDING)
1327 setStatus(GUIDE_DITHERING);
1332 return m_GuiderInstance->dither(Options::ditherPixels());
1337 if (m_State == GUIDE_SUSPENDED)
1339 else if (m_State >= GUIDE_CAPTURE)
1340 return m_GuiderInstance->suspend();
1347 if (m_State == GUIDE_GUIDING)
1349 else if (m_State == GUIDE_SUSPENDED)
1350 return m_GuiderInstance->resume();
1369 resetNonGuidedDither();
1376 void Guide::setPierSide(ISD::Mount::PierSide newSide)
1378 m_GuiderInstance->setPierSide(newSide);
1383 if (guiderType == GUIDE_INTERNAL &&
1384 m_State != GUIDE_GUIDING &&
1385 m_State != GUIDE_CALIBRATING &&
1386 calibrationComplete)
1389 if (Options::reuseGuideCalibration())
1390 calibrationComplete =
false;
1394 appendLogText(
i18n(
"Pier side change detected. Clearing calibration."));
1399 void Guide::setMountStatus(ISD::Mount::Status newState)
1401 m_MountStatus = newState;
1403 if (newState == ISD::Mount::MOUNT_PARKING || newState == ISD::Mount::MOUNT_SLEWING)
1406 if (Options::resetGuideCalibration())
1408 appendLogText(
i18n(
"Mount is moving. Resetting calibration..."));
1411 else if (Options::reuseGuideCalibration() && (guiderType == GUIDE_INTERNAL))
1414 calibrationComplete =
false;
1417 if (Options::gPGEnabled())
1418 m_GuiderInstance->resetGPG();
1421 if (m_State == GUIDE_GUIDING || m_State == GUIDE_DITHERING)
1423 if (newState == ISD::Mount::MOUNT_PARKING)
1424 appendLogText(
i18n(
"Mount is parking. Aborting guide..."));
1426 appendLogText(
i18n(
"Mount is slewing. Aborting guide..."));
1432 if (guiderType != GUIDE_INTERNAL)
1437 case ISD::Mount::MOUNT_SLEWING:
1438 case ISD::Mount::MOUNT_PARKING:
1439 case ISD::Mount::MOUNT_MOVING:
1440 captureB->setEnabled(
false);
1441 loopB->setEnabled(
false);
1442 clearCalibrationB->setEnabled(
false);
1443 manualPulseB->setEnabled(
false);
1449 captureB->setEnabled(
true);
1450 loopB->setEnabled(
true);
1451 clearCalibrationB->setEnabled(
true);
1452 manualPulseB->setEnabled(
true);
1457 void Guide::setMountCoords(
const SkyPoint &position, ISD::Mount::PierSide pierSide,
const dms &ha)
1460 m_GuiderInstance->setMountCoords(position, pierSide);
1461 m_ManaulPulse->setMountCoords(position);
1466 guideExposure->setValue(value);
1471 if (guideSubframe->isChecked() != enable)
1472 guideSubframe->setChecked(enable);
1473 if(guiderType == GUIDE_PHD2)
1474 setExternalGuiderBLOBEnabled(!enable);
1479 if(guiderType == GUIDE_INTERNAL)
1480 guideAutoStar->setChecked(enable);
1485 calibrationComplete =
false;
1487 m_GuiderInstance->clearCalibration();
1489 appendLogText(
i18n(
"Calibration is cleared."));
1492 void Guide::setStatus(Ekos::GuideState newState)
1494 if (newState == m_State)
1497 if (newState == GUIDE_ABORTED)
1498 emit newStatus(m_State);
1502 GuideState previousState = m_State;
1505 emit newStatus(m_State);
1509 case GUIDE_CONNECTED:
1510 appendLogText(
i18n(
"External guider connected."));
1511 externalConnectB->setEnabled(
false);
1512 externalDisconnectB->setEnabled(
true);
1513 clearCalibrationB->setEnabled(
true);
1514 guideB->setEnabled(
true);
1516 if(guiderType == GUIDE_PHD2)
1518 captureB->setEnabled(
true);
1519 loopB->setEnabled(
true);
1520 guideAutoStar->setEnabled(
true);
1521 configurePHD2Camera();
1522 setExternalGuiderBLOBEnabled(!guideSubframe->isChecked());
1523 guideSquareSize->setEnabled(
true);
1527 case GUIDE_DISCONNECTED:
1528 appendLogText(
i18n(
"External guider disconnected."));
1530 externalConnectB->setEnabled(
true);
1531 externalDisconnectB->setEnabled(
false);
1532 clearCalibrationB->setEnabled(
false);
1533 guideB->setEnabled(
false);
1534 captureB->setEnabled(
false);
1535 loopB->setEnabled(
false);
1536 guideAutoStar->setEnabled(
false);
1537 guideSquareSize->setEnabled(
false);
1544 case GUIDE_CALIBRATION_SUCCESS:
1545 appendLogText(
i18n(
"Calibration completed."));
1546 manualPulseB->setEnabled(
true);
1547 calibrationComplete =
true;
1555 case GUIDE_CALIBRATION_ERROR:
1557 manualDitherB->setEnabled(
false);
1558 manualPulseB->setEnabled(
true);
1561 case GUIDE_CALIBRATING:
1562 clearCalibrationGraphs();
1563 appendLogText(
i18n(
"Calibration started."));
1565 manualPulseB->setEnabled(
false);
1569 if (previousState == GUIDE_SUSPENDED || previousState == GUIDE_DITHERING_SUCCESS)
1570 appendLogText(
i18n(
"Guiding resumed."));
1573 appendLogText(
i18n(
"Autoguiding started."));
1578 driftGraph->resetTimer();
1579 driftGraph->refreshColorScheme();
1581 manualDitherB->setEnabled(
true);
1585 appendLogText(
i18n(
"Autoguiding aborted."));
1589 case GUIDE_SUSPENDED:
1590 appendLogText(
i18n(
"Guiding suspended."));
1593 case GUIDE_REACQUIRE:
1594 if (guiderType == GUIDE_INTERNAL)
1598 case GUIDE_MANUAL_DITHERING:
1599 appendLogText(
i18n(
"Manual dithering in progress."));
1602 case GUIDE_DITHERING:
1603 appendLogText(
i18n(
"Dithering in progress."));
1606 case GUIDE_DITHERING_SETTLE:
1607 appendLogText(
i18np(
"Post-dither settling for %1 second...",
"Post-dither settling for %1 seconds...",
1608 Options::ditherSettle()));
1611 case GUIDE_DITHERING_ERROR:
1612 appendLogText(
i18n(
"Dithering failed."));
1614 if (guiderType != GUIDE_LINGUIDER)
1617 m_State = GUIDE_ABORTED;
1622 case GUIDE_DITHERING_SUCCESS:
1623 appendLogText(
i18n(
"Dithering completed successfully."));
1625 if (Options::ditherNoGuiding() ==
false)
1627 setStatus(GUIDE_GUIDING);
1629 if (guiderType == GUIDE_INTERNAL)
1638 void Guide::updateCCDBin(
int index)
1640 if (m_Camera ==
nullptr || guiderType != GUIDE_INTERNAL)
1643 ISD::CameraChip *targetChip = m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
1645 targetChip->setBinning(index + 1, index + 1);
1646 guideBinIndex = index;
1648 QVariantMap settings = frameSettings[targetChip];
1649 settings[
"binx"] = index + 1;
1650 settings[
"biny"] = index + 1;
1651 frameSettings[targetChip] = settings;
1653 m_GuiderInstance->setFrameParams(settings[
"x"].toInt(), settings[
"y"].toInt(), settings[
"w"].toInt(), settings[
"h"].toInt(),
1654 settings[
"binx"].toInt(), settings[
"biny"].toInt());
1659 if (m_Camera ==
nullptr || (prop.getDeviceName() != m_Camera->getDeviceName()) || guiderType != GUIDE_INTERNAL)
1662 if ((prop.isNameMatch(
"CCD_BINNING") && useGuideHead ==
false) ||
1663 (prop.isNameMatch(
"GUIDER_BINNING") && useGuideHead))
1665 auto nvp = prop.getNumber();
1666 auto value = nvp->at(0)->getValue();
1667 if (guideBinIndex > (value - 1))
1669 appendLogText(
i18n(
"%1x%1 guide binning is not supported.", guideBinIndex + 1));
1670 guideBinning->setCurrentIndex( value - 1 );
1675 guideBinning->setCurrentIndex(guideBinIndex);
1683 if (guiderType != GUIDE_INTERNAL || targetChip->getCCD() != m_Camera)
1686 INDI_UNUSED(exposure);
1688 if (expState == IPS_ALERT &&
1689 ((m_State == GUIDE_GUIDING) || (m_State == GUIDE_DITHERING) || (m_State == GUIDE_CALIBRATING)))
1691 appendLogText(
i18n(
"Exposure failed. Restarting exposure..."));
1692 m_Camera->setEncodingFormat(
"FITS");
1693 targetChip->capture(guideExposure->value());
1697 void Guide::configSEPMultistarOptions()
1700 if (internalGuider->SEPMultiStarEnabled())
1702 guideSubframe->setChecked(
false);
1703 guideSubframe->setEnabled(
false);
1704 guideAutoStar->setChecked(
true);
1705 guideAutoStar->setEnabled(
false);
1709 guideAutoStar->setEnabled(
true);
1710 guideSubframe->setEnabled(
true);
1712 auto subframed = m_Settings[
"guideSubframe"];
1713 if (subframed.isValid())
1714 guideSubframe->setChecked(subframed.toBool());
1716 auto autostar = m_Settings[
"guideAutoStar"];
1717 if (autostar.isValid())
1718 guideAutoStar->setChecked(autostar.toBool());
1724 if (guideDarkFrame->isChecked() != enable)
1725 guideDarkFrame->setChecked(enable);
1728 void Guide::saveDefaultGuideExposure()
1730 if(guiderType == GUIDE_PHD2)
1732 phd2Guider->requestSetExposureTime(guideExposure->value() * 1000);
1733 else if (guiderType == GUIDE_INTERNAL)
1735 internalGuider->setExposureTime();
1739 void Guide::setStarPosition(
const QVector3D &newCenter,
bool updateNow)
1741 starCenter.
setX(newCenter.
x());
1742 starCenter.
setY(newCenter.
y());
1743 if (newCenter.
z() > 0)
1744 starCenter.
setZ(newCenter.
z());
1747 syncTrackingBoxPosition();
1750 void Guide::syncTrackingBoxPosition()
1752 if(!m_Camera || guiderType == GUIDE_LINGUIDER)
1755 if(guiderType == GUIDE_PHD2)
1758 if(!m_ImageData.
isNull())
1760 if(m_ImageData->width() < 50)
1762 m_GuideView->setTrackingBoxEnabled(
false);
1768 ISD::CameraChip *targetChip = m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
1769 Q_ASSERT(targetChip);
1771 int subBinX = 1, subBinY = 1;
1772 targetChip->getBinning(&subBinX, &subBinY);
1774 if (starCenter.
isNull() ==
false)
1776 double boxSize = guideSquareSize->currentText().toInt();
1778 targetChip->getFrame(&
x, &
y, &w, &h);
1780 if (boxSize / subBinX >= w || boxSize / subBinY >= h)
1782 int newIndex = guideSquareSize->currentIndex() - 1;
1784 guideSquareSize->setCurrentIndex(newIndex);
1789 if (subBinX != starCenter.
z())
1791 if (starCenter.
z() > 0)
1793 starCenter.
setX(starCenter.
x() * (starCenter.
z() / subBinX));
1794 starCenter.
setY(starCenter.
y() * (starCenter.
z() / subBinY));
1797 starCenter.
setZ(subBinX);
1800 QRect starRect =
QRect(starCenter.
x() - boxSize / (2 * subBinX), starCenter.
y() - boxSize / (2 * subBinY),
1801 boxSize / subBinX, boxSize / subBinY);
1802 m_GuideView->setTrackingBoxEnabled(
true);
1803 m_GuideView->setTrackingBox(starRect);
1811 type = Options::guiderType();
1812 else if (type == guiderType)
1815 if (m_State == GUIDE_CALIBRATING || m_State == GUIDE_GUIDING || m_State == GUIDE_DITHERING)
1817 appendLogText(
i18n(
"Cannot change guider type while active."));
1821 if (m_GuiderInstance !=
nullptr)
1824 if (m_GuiderInstance->isConnected())
1825 m_GuiderInstance->Disconnect();
1831 guiderType =
static_cast<GuiderType
>(type);
1835 case GUIDE_INTERNAL:
1837 connect(internalGuider, &InternalGuider::newMultiPulse,
this, &Guide::sendMultiPulse);
1838 connect(internalGuider, &InternalGuider::newSinglePulse,
this, &Guide::sendSinglePulse);
1840 connect(internalGuider, &InternalGuider::newStarPixmap,
this, &Guide::newStarPixmap);
1842 m_GuiderInstance = internalGuider;
1844 internalGuider->setSquareAlgorithm(opsGuide->kcfg_GuideAlgorithm->currentIndex());
1846 clearCalibrationB->setEnabled(
true);
1847 guideB->setEnabled(
true);
1848 captureB->setEnabled(
true);
1849 loopB->setEnabled(
true);
1851 configSEPMultistarOptions();
1852 guideDarkFrame->setEnabled(
true);
1854 guideExposure->setEnabled(
true);
1855 guideBinning->setEnabled(
true);
1856 guideSquareSize->setEnabled(
true);
1858 externalConnectB->setEnabled(
false);
1859 externalDisconnectB->setEnabled(
false);
1862 infoGroup->setEnabled(
true);
1863 l_Aperture->setEnabled(
true);
1864 l_FOV->setEnabled(
true);
1865 l_FbyD->setEnabled(
true);
1866 l_Focal->setEnabled(
true);
1867 driftGraphicsGroup->setEnabled(
true);
1869 updateGuideParams();
1874 if (phd2Guider.isNull())
1875 phd2Guider =
new PHD2();
1877 m_GuiderInstance = phd2Guider;
1878 phd2Guider->setGuideView(m_GuideView);
1882 clearCalibrationB->setEnabled(
true);
1883 captureB->setEnabled(
false);
1884 loopB->setEnabled(
false);
1885 guideDarkFrame->setEnabled(
false);
1886 guideSubframe->setEnabled(
false);
1887 guideAutoStar->setEnabled(
false);
1888 guideB->setEnabled(
false);
1889 externalConnectB->setEnabled(
false);
1891 rAGuideEnabled->setEnabled(
false);
1892 eastRAGuideEnabled->setEnabled(
false);
1893 westRAGuideEnabled->setEnabled(
false);
1896 infoGroup->setEnabled(
true);
1897 l_Aperture->setEnabled(
false);
1898 l_FOV->setEnabled(
false);
1899 l_FbyD->setEnabled(
false);
1900 l_Focal->setEnabled(
false);
1901 driftGraphicsGroup->setEnabled(
true);
1903 guideExposure->setEnabled(
true);
1904 guideBinning->setEnabled(
false);
1905 guideSquareSize->setEnabled(
false);
1907 if (Options::resetGuideCalibration())
1908 appendLogText(
i18n(
"Warning: Reset Guiding Calibration is enabled. It is recommended to turn this option off for PHD2."));
1910 updateGuideParams();
1913 case GUIDE_LINGUIDER:
1914 if (linGuider.isNull())
1917 m_GuiderInstance = linGuider;
1919 clearCalibrationB->setEnabled(
true);
1920 captureB->setEnabled(
false);
1921 loopB->setEnabled(
false);
1922 guideDarkFrame->setEnabled(
false);
1923 guideSubframe->setEnabled(
false);
1924 guideAutoStar->setEnabled(
false);
1925 guideB->setEnabled(
true);
1926 externalConnectB->setEnabled(
true);
1929 infoGroup->setEnabled(
false);
1930 driftGraphicsGroup->setEnabled(
false);
1932 guideExposure->setEnabled(
false);
1933 guideBinning->setEnabled(
false);
1934 guideSquareSize->setEnabled(
false);
1936 updateGuideParams();
1941 if (m_GuiderInstance !=
nullptr)
1944 connect(m_GuiderInstance, &Ekos::GuideInterface::newLog,
this, &Ekos::Guide::appendLogText);
1945 connect(m_GuiderInstance, &Ekos::GuideInterface::newStatus,
this, &Ekos::Guide::setStatus);
1946 connect(m_GuiderInstance, &Ekos::GuideInterface::newStarPosition,
this, &Ekos::Guide::setStarPosition);
1947 connect(m_GuiderInstance, &Ekos::GuideInterface::guideStats,
this, &Ekos::Guide::guideStats);
1949 connect(m_GuiderInstance, &Ekos::GuideInterface::newAxisDelta,
this, &Ekos::Guide::setAxisDelta);
1950 connect(m_GuiderInstance, &Ekos::GuideInterface::newAxisPulse,
this, &Ekos::Guide::setAxisPulse);
1951 connect(m_GuiderInstance, &Ekos::GuideInterface::newAxisSigma,
this, &Ekos::Guide::setAxisSigma);
1952 connect(m_GuiderInstance, &Ekos::GuideInterface::newSNR,
this, &Ekos::Guide::setSNR);
1953 connect(m_GuiderInstance, &Ekos::GuideInterface::guideInfo,
this, &Ekos::Guide::guideInfo);
1954 connect(m_GuiderInstance, &Ekos::GuideInterface::abortExposure,
this, &Ekos::Guide::abortExposure);
1956 driftGraph->connectGuider(m_GuiderInstance);
1957 targetPlot->connectGuider(m_GuiderInstance);
1959 connect(m_GuiderInstance, &Ekos::GuideInterface::calibrationUpdate,
this, &Ekos::Guide::calibrationUpdate);
1961 connect(m_GuiderInstance, &Ekos::GuideInterface::guideEquipmentUpdated,
this, &Ekos::Guide::configurePHD2Camera);
1964 externalConnectB->setEnabled(
false);
1965 externalDisconnectB->setEnabled(
false);
1967 if (m_GuiderInstance !=
nullptr && guiderType != GUIDE_INTERNAL)
1969 externalConnectB->setEnabled(!m_GuiderInstance->isConnected());
1970 externalDisconnectB->setEnabled(m_GuiderInstance->isConnected());
1973 if (m_GuiderInstance !=
nullptr)
1974 m_GuiderInstance->Connect();
1979 void Guide::guideInfo(
const QString &info)
1981 if (info.size() == 0)
1983 guideInfoLabel->setVisible(
false);
1984 guideInfoText->setVisible(
false);
1987 guideInfoLabel->setVisible(
true);
1988 guideInfoLabel->setText(
"Detections");
1989 guideInfoText->setVisible(
true);
1990 guideInfoText->setText(info);
1993 void Guide::updateTrackingBoxSize(
int currentIndex)
1995 if (currentIndex >= 0)
1997 if (guiderType == GUIDE_INTERNAL)
1998 dynamic_cast<InternalGuider *
>(m_GuiderInstance)->setGuideBoxSize(guideSquareSize->currentText().toInt());
2000 syncTrackingBoxPosition();
2004 void Guide::onThresholdChanged(
int index)
2008 case GUIDE_INTERNAL:
2009 dynamic_cast<InternalGuider *
>(m_GuiderInstance)->setSquareAlgorithm(index);
2017 void Guide::onEnableDirRA()
2020 if (Options::gPGEnabled())
2021 m_GuiderInstance->resetGPG();
2024 void Guide::onEnableDirDEC()
2026 onControlDirectionChanged();
2029 void Guide::onControlDirectionChanged()
2031 if(guiderType == GUIDE_PHD2)
2032 phd2Guider -> requestSetDEGuideMode(dECGuideEnabled->isChecked(), northDECGuideEnabled->isChecked(),
2033 southDECGuideEnabled->isChecked());
2036 void Guide::updateDirectionsFromPHD2(
const QString &mode)
2045 dECGuideEnabled->setChecked(
true);
2046 northDECGuideEnabled->setChecked(
true);
2047 southDECGuideEnabled->setChecked(
true);
2049 else if(mode ==
"North")
2051 dECGuideEnabled->setChecked(
true);
2052 northDECGuideEnabled->setChecked(
true);
2053 southDECGuideEnabled->setChecked(
false);
2055 else if(mode ==
"South")
2057 dECGuideEnabled->setChecked(
true);
2058 northDECGuideEnabled->setChecked(
false);
2059 southDECGuideEnabled->setChecked(
true);
2063 dECGuideEnabled->setChecked(
false);
2064 northDECGuideEnabled->setChecked(
true);
2065 southDECGuideEnabled->setChecked(
true);
2077 setStarPosition(newStarPosition,
true);
2079 if(guiderType == GUIDE_PHD2)
2082 if(!m_ImageData.
isNull())
2084 if(m_ImageData->width() > 50)
2085 phd2Guider->setLockPosition(starCenter.
x(), starCenter.
y());
2089 if (operationStack.isEmpty() ==
false)
2090 executeOperationStack();
2093 void Guide::setAxisDelta(
double ra,
double de)
2103 int currentNumPoints = driftGraph->graph(GuideGraph::G_RA)->dataCount();
2104 guideSlider->setMaximum(currentNumPoints);
2107 guideSlider->setValue(currentNumPoints);
2112 emit newAxisDelta(ra, de);
2115 void Guide::calibrationUpdate(GuideInterface::CalibrationUpdateType type,
const QString &
message,
2116 double dx,
double dy)
2120 case GuideInterface::RA_OUT:
2121 calibrationPlot->graph(GuideGraph::G_RA)->addData(dx, dy);
2123 case GuideInterface::RA_IN:
2124 calibrationPlot->graph(GuideGraph::G_DEC)->addData(dx, dy);
2126 case GuideInterface::BACKLASH:
2127 calibrationPlot->graph(GuideGraph::G_RA_HIGHLIGHT)->addData(dx, dy);
2129 case GuideInterface::DEC_OUT:
2130 calibrationPlot->graph(GuideGraph::G_DEC_HIGHLIGHT)->addData(dx, dy);
2132 case GuideInterface::DEC_IN:
2133 calibrationPlot->graph(GuideGraph::G_RA_PULSE)->addData(dx, dy);
2135 case GuideInterface::CALIBRATION_MESSAGE_ONLY:
2139 calibrationPlot->replot();
2142 void Guide::setAxisSigma(
double ra,
double de)
2146 const double total = std::hypot(ra, de);
2149 emit newAxisSigma(ra, de);
2156 delta << l_DeltaRA->text().toDouble() << l_DeltaDEC->text().toDouble();
2165 sigma << l_ErrRA->text().toDouble() << l_ErrDEC->text().toDouble();
2170 void Guide::setAxisPulse(
double ra,
double de)
2176 void Guide::setSNR(
double snr)
2181 void Guide::buildOperationStack(GuideState operation)
2183 operationStack.clear();
2188 if (guideDarkFrame->isChecked())
2189 operationStack.
push(GUIDE_DARK);
2191 operationStack.
push(GUIDE_CAPTURE);
2192 operationStack.
push(GUIDE_SUBFRAME);
2195 case GUIDE_CALIBRATING:
2196 operationStack.
push(GUIDE_CALIBRATING);
2197 if (guiderType == GUIDE_INTERNAL)
2199 if (guideDarkFrame->isChecked())
2200 operationStack.
push(GUIDE_DARK);
2203 if (guideAutoStar->isChecked() ||
2205 internalGuider->SEPMultiStarEnabled())
2209 if (subFramed ==
false && guideSubframe->isChecked())
2210 operationStack.
push(GUIDE_CAPTURE);
2212 operationStack.
push(GUIDE_SUBFRAME);
2213 operationStack.
push(GUIDE_STAR_SELECT);
2216 operationStack.
push(GUIDE_CAPTURE);
2219 if (subFramed ==
true && guideSubframe->isChecked() ==
false)
2220 operationStack.
push(GUIDE_SUBFRAME);
2226 if (subFramed ==
false && guideSubframe->isChecked())
2227 operationStack.
push(GUIDE_CAPTURE);
2230 operationStack.
push(GUIDE_SUBFRAME);
2233 operationStack.
push(GUIDE_CAPTURE);
2244 bool Guide::executeOperationStack()
2246 if (operationStack.isEmpty())
2249 GuideState nextOperation = operationStack.
pop();
2252 bool actionRequired =
false;
2254 switch (nextOperation)
2256 case GUIDE_SUBFRAME:
2257 actionRequired = executeOneOperation(nextOperation);
2261 actionRequired = executeOneOperation(nextOperation);
2265 actionRequired = captureOneFrame();
2268 case GUIDE_STAR_SELECT:
2269 actionRequired = executeOneOperation(nextOperation);
2272 case GUIDE_CALIBRATING:
2273 if (guiderType == GUIDE_INTERNAL)
2275 m_GuiderInstance->setStarPosition(starCenter);
2278 if (m_Mount && m_Mount->canControlTrack() && m_Mount->isTracking() ==
false)
2279 m_Mount->setTrackEnabled(
true);
2282 if (m_GuiderInstance->calibrate())
2284 if (guiderType == GUIDE_INTERNAL)
2290 emit newStatus(GUIDE_CALIBRATION_ERROR);
2291 m_State = GUIDE_IDLE;
2292 appendLogText(
i18n(
"Calibration failed to start."));
2306 return executeOperationStack();
2309 bool Guide::executeOneOperation(GuideState operation)
2311 bool actionRequired =
false;
2313 if (m_Camera ==
nullptr)
2314 return actionRequired;
2316 ISD::CameraChip *targetChip = m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
2317 if (targetChip ==
nullptr)
2320 int subBinX, subBinY;
2321 targetChip->getBinning(&subBinX, &subBinY);
2325 case GUIDE_SUBFRAME:
2328 if ((guiderType == GUIDE_INTERNAL) && internalGuider->SEPMultiStarEnabled())
2331 if (subFramed ==
false && guideSubframe->isChecked() ==
true && targetChip->canSubframe())
2333 int minX, maxX, minY, maxY, minW, maxW, minH, maxH;
2334 targetChip->getFrameMinMax(&minX, &maxX, &minY, &maxY, &minW, &maxW, &minH, &maxH);
2336 int offset = guideSquareSize->currentText().toInt() / subBinX;
2338 int x = starCenter.
x();
2339 int y = starCenter.
y();
2341 x = (
x - offset * 2) * subBinX;
2342 y = (
y - offset * 2) * subBinY;
2343 int w = offset * 4 * subBinX;
2344 int h = offset * 4 * subBinY;
2355 targetChip->setFrame(
x,
y, w, h);
2358 QVariantMap settings = frameSettings[targetChip];
2363 settings[
"binx"] = subBinX;
2364 settings[
"biny"] = subBinY;
2366 frameSettings[targetChip] = settings;
2368 starCenter.
setX(w / (2 * subBinX));
2369 starCenter.
setY(h / (2 * subBinX));
2375 else if (subFramed &&
2376 (guideSubframe->isChecked() ==
false ||
2377 m_State == GUIDE_REACQUIRE))
2379 targetChip->resetFrame();
2382 targetChip->getFrame(&
x, &
y, &w, &h);
2384 QVariantMap settings;
2389 settings[
"binx"] = subBinX;
2390 settings[
"biny"] = subBinY;
2391 frameSettings[targetChip] = settings;
2395 starCenter.
setX(w / (2 * subBinX));
2396 starCenter.
setY(h / (2 * subBinX));
2407 if (m_ImageData && guideDarkFrame->isChecked())
2409 QVariantMap settings = frameSettings[targetChip];
2410 uint16_t offsetX = 0;
2411 uint16_t offsetY = 0;
2413 if (settings[
"x"].
isValid() &&
2414 settings[
"y"].isValid() &&
2415 settings[
"binx"].isValid() &&
2416 settings[
"biny"].isValid())
2418 offsetX = settings[
"x"].toInt() / settings[
"binx"].toInt();
2419 offsetY = settings[
"y"].toInt() / settings[
"biny"].toInt();
2422 actionRequired =
true;
2423 targetChip->setCaptureFilter(FITS_NONE);
2424 m_DarkProcessor->denoise(OpticalTrainManager::Instance()->id(opticalTrainCombo->currentText()),
2425 targetChip, m_ImageData, guideExposure->value(), offsetX, offsetY);
2430 case GUIDE_STAR_SELECT:
2432 m_State = GUIDE_STAR_SELECT;
2433 emit newStatus(m_State);
2435 if (guideAutoStar->isChecked() ||
2437 ((guiderType == GUIDE_INTERNAL) &&
2438 internalGuider->SEPMultiStarEnabled()))
2440 bool autoStarCaptured = internalGuider->selectAutoStar();
2441 if (autoStarCaptured)
2443 appendLogText(
i18n(
"Auto star selected."));
2447 appendLogText(
i18n(
"Failed to select an auto star."));
2448 actionRequired =
true;
2449 m_State = GUIDE_CALIBRATION_ERROR;
2450 emit newStatus(m_State);
2456 appendLogText(
i18n(
"Select a guide star to calibrate."));
2457 actionRequired =
true;
2466 return actionRequired;
2469 void Guide::processGuideOptions()
2471 if (Options::guiderType() != guiderType)
2473 guiderType =
static_cast<GuiderType
>(Options::guiderType());
2478 void Guide::showFITSViewer()
2480 static int lastFVTabID = -1;
2487 fv->loadData(m_ImageData, url, &lastFVTabID);
2489 else if (fv->updateData(m_ImageData, url, lastFVTabID, &lastFVTabID) ==
false)
2490 fv->loadData(m_ImageData, url, &lastFVTabID);
2496 void Guide::setExternalGuiderBLOBEnabled(
bool enable)
2499 if (guiderType == GUIDE_INTERNAL)
2505 m_Camera->setBLOBEnabled(enable);
2507 if(m_Camera->isBLOBEnabled())
2509 checkUseGuideHead();
2511 auto targetChip = m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
2513 targetChip->setCaptureMode(FITS_GUIDE);
2519 void Guide::resetNonGuidedDither()
2522 nonGuidedDitherRaOffsetMsec = 0;
2523 nonGuidedDitherDecOffsetMsec = 0;
2524 qCDebug(KSTARS_EKOS_GUIDE) <<
"Reset non guiding dithering position";
2527 if (!isNonGuidedDitherInitialized)
2529 auto seed = std::chrono::system_clock::now().time_since_epoch().count();
2530 nonGuidedPulseGenerator.seed(seed);
2531 isNonGuidedDitherInitialized =
true;
2532 qCDebug(KSTARS_EKOS_GUIDE) <<
"Initialize non guiding dithering random generator";
2536 void Guide::nonGuidedDither()
2538 double ditherPulse = Options::ditherNoGuidingPulse();
2541 std::uniform_int_distribution<int> newPos(-ditherPulse, +ditherPulse);
2546 const int newRaOffsetMsec = newPos(nonGuidedPulseGenerator);
2547 const int raPulse = nonGuidedDitherRaOffsetMsec - newRaOffsetMsec;
2548 nonGuidedDitherRaOffsetMsec = newRaOffsetMsec;
2549 const int raMsec = std::abs(raPulse);
2550 const int raPolarity = (raPulse >= 0 ? 1 : -1);
2553 const int newDecOffsetMsec = newPos(nonGuidedPulseGenerator);
2554 const int decPulse = nonGuidedDitherDecOffsetMsec - newDecOffsetMsec;
2555 nonGuidedDitherDecOffsetMsec = newDecOffsetMsec;
2556 const int decMsec = std::abs(decPulse);
2557 const int decPolarity = (decPulse >= 0 ? 1 : -1);
2559 qCInfo(KSTARS_EKOS_GUIDE) <<
"Starting non-guiding dither...";
2560 qCDebug(KSTARS_EKOS_GUIDE) <<
"dither ra_msec:" << raMsec <<
"ra_polarity:" << raPolarity <<
"de_msec:" << decMsec <<
2561 "de_polarity:" << decPolarity;
2563 bool rc = sendMultiPulse(raPolarity > 0 ? RA_INC_DIR : RA_DEC_DIR, raMsec, decPolarity > 0 ? DEC_INC_DIR : DEC_DEC_DIR,
2564 decMsec, DontCaptureAfterPulses);
2568 qCInfo(KSTARS_EKOS_GUIDE) <<
"Non-guiding dither successful.";
2569 QTimer::singleShot( (raMsec > decMsec ? raMsec : decMsec) + Options::ditherSettle() * 1000 + 100,
this, [
this]()
2571 emit newStatus(GUIDE_DITHERING_SUCCESS);
2572 m_State = GUIDE_IDLE;
2577 qCWarning(KSTARS_EKOS_GUIDE) <<
"Non-guiding dither failed.";
2578 emit newStatus(GUIDE_DITHERING_ERROR);
2579 m_State = GUIDE_IDLE;
2583 void Guide::handleManualDither()
2585 ISD::CameraChip *targetChip = m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
2586 if (targetChip ==
nullptr)
2589 Ui::ManualDither ditherDialog;
2591 ditherDialog.setupUi(&container);
2593 if (guiderType != GUIDE_INTERNAL)
2595 ditherDialog.coordinatesR->setEnabled(
false);
2596 ditherDialog.x->setEnabled(
false);
2597 ditherDialog.y->setEnabled(
false);
2600 int minX, maxX, minY, maxY, minW, maxW, minH, maxH;
2601 targetChip->getFrameMinMax(&minX, &maxX, &minY, &maxY, &minW, &maxW, &minH, &maxH);
2603 ditherDialog.x->setMinimum(minX);
2604 ditherDialog.x->setMaximum(maxX);
2605 ditherDialog.y->setMinimum(minY);
2606 ditherDialog.y->setMaximum(maxY);
2608 ditherDialog.x->setValue(starCenter.
x());
2609 ditherDialog.y->setValue(starCenter.
y());
2613 if (ditherDialog.magnitudeR->isChecked())
2614 m_GuiderInstance->dither(ditherDialog.magnitude->value());
2617 InternalGuider *
const ig =
dynamic_cast<InternalGuider *
>(m_GuiderInstance);
2619 ig->ditherXY(ditherDialog.x->value(), ditherDialog.y->value());
2626 setStatus(GUIDE_IDLE);
2627 return m_GuiderInstance->Connect();
2632 return m_GuiderInstance->Disconnect();
2635 void Guide::initPlots()
2638 initCalibrationPlot();
2646 void Guide::initDriftGraph()
2656 driftGraph->setCorrectionGraphScale(correctionSlider->value());
2664 correctionSlider->setValue(scale);
2667 void Guide::initCalibrationPlot()
2670 calibrationPlot->setSelectionTolerance(10);
2681 calibrationPlot->xAxis->setTickLabelColor(
Qt::white);
2682 calibrationPlot->yAxis->setTickLabelColor(
Qt::white);
2684 calibrationPlot->xAxis->setLabelColor(
Qt::white);
2685 calibrationPlot->yAxis->setLabelColor(
Qt::white);
2687 calibrationPlot->xAxis->setLabelFont(
QFont(
font().family(), 10));
2688 calibrationPlot->yAxis->setLabelFont(
QFont(
font().family(), 10));
2689 calibrationPlot->xAxis->setTickLabelFont(
QFont(
font().family(), 9));
2690 calibrationPlot->yAxis->setTickLabelFont(
QFont(
font().family(), 9));
2692 calibrationPlot->xAxis->setLabelPadding(2);
2693 calibrationPlot->yAxis->setLabelPadding(2);
2699 calibrationPlot->xAxis->grid()->setZeroLinePen(
QPen(
Qt::gray));
2700 calibrationPlot->yAxis->grid()->setZeroLinePen(
QPen(
Qt::gray));
2702 calibrationPlot->xAxis->setLabel(
i18n(
"x (pixels)"));
2703 calibrationPlot->yAxis->setLabel(
i18n(
"y (pixels)"));
2705 calibrationPlot->xAxis->setRange(-20, 20);
2706 calibrationPlot->yAxis->setRange(-20, 20);
2711 calibrationPlot->addGraph();
2714 QPen(KStarsData::Instance()->colorScheme()->colorNamed(
"RAGuideError"), 2),
QBrush(), 6));
2715 calibrationPlot->graph(GuideGraph::G_RA)->setName(
"RA out");
2717 calibrationPlot->addGraph();
2721 calibrationPlot->graph(GuideGraph::G_DEC)->setName(
"RA in");
2723 calibrationPlot->addGraph();
2724 calibrationPlot->graph(GuideGraph::G_RA_HIGHLIGHT)->setLineStyle(
QCPGraph::lsNone);
2728 calibrationPlot->graph(GuideGraph::G_RA_HIGHLIGHT)->setName(
"Backlash");
2730 calibrationPlot->addGraph();
2731 calibrationPlot->graph(GuideGraph::G_DEC_HIGHLIGHT)->setLineStyle(
QCPGraph::lsNone);
2733 QPen(KStarsData::Instance()->colorScheme()->colorNamed(
"DEGuideError"), 2),
QBrush(), 6));
2734 calibrationPlot->graph(GuideGraph::G_DEC_HIGHLIGHT)->setName(
"DEC out");
2736 calibrationPlot->addGraph();
2737 calibrationPlot->graph(GuideGraph::G_RA_PULSE)->setLineStyle(
QCPGraph::lsNone);
2741 calibrationPlot->graph(GuideGraph::G_RA_PULSE)->setName(
"DEC in");
2752 calibrationPlot->resize(190, 190);
2753 calibrationPlot->replot();
2756 void Guide::initView()
2758 guideStateWidget =
new GuideStateWidget();
2759 guideInfoLayout->insertWidget(-1, guideStateWidget);
2763 m_GuideView->setBaseSize(guideWidget->size());
2764 m_GuideView->createFloatingToolBar();
2767 guideWidget->setLayout(vlayout);
2769 guideInfoLabel->setVisible(
false);
2770 guideInfoText->setVisible(
false);
2773 void Guide::initConnections()
2781 &Ekos::Guide::updateTrackingBoxSize);
2786 if(guiderType != GUIDE_PHD2)
2791 &Ekos::Guide::updateCCDBin);
2806 m_State = GUIDE_CAPTURE;
2807 emit newStatus(m_State);
2809 if(guiderType == GUIDE_PHD2)
2811 configurePHD2Camera();
2812 if(phd2Guider->isCurrentCameraNotInEkos())
2814 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."));
2815 else if(guideSubframe->isChecked())
2818 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"));
2819 guideSubframe->setChecked(
false);
2821 phd2Guider->captureSingleFrame();
2823 else if (guiderType == GUIDE_INTERNAL)
2844 m_GuiderInstance->Connect();
2849 m_GuiderInstance->Disconnect();
2858 &Ekos::Guide::buildTarget);
2863 driftGraph->toggleShowPlot(GuideGraph::G_RA, isChecked);
2867 driftGraph->toggleShowPlot(GuideGraph::G_DEC, isChecked);
2871 driftGraph->toggleShowPlot(GuideGraph::G_RA_PULSE, isChecked);
2875 driftGraph->toggleShowPlot(GuideGraph::G_DEC_PULSE, isChecked);
2879 driftGraph->toggleShowPlot(GuideGraph::G_SNR, isChecked);
2883 driftGraph->toggleShowPlot(GuideGraph::G_RMS, isChecked);
2889 connect(
this, &Ekos::Guide::newStatus, guideStateWidget, &Ekos::GuideStateWidget::updateGuideStatus);
2894 auto name = device->getDeviceName();
2896 device->disconnect(
this);
2899 if (m_Mount && m_Mount->getDeviceName() == name)
2907 if (m_Camera && m_Camera->getDeviceName() == name)
2915 if (m_Guider && m_Guider->getDeviceName() == name)
2917 m_Guider->disconnect(
this);
2923 if (m_AO && m_AO->getDeviceName() == name)
2932 m_State = GUIDE_LOOPING;
2933 emit newStatus(m_State);
2935 if(guiderType == GUIDE_PHD2)
2937 configurePHD2Camera();
2938 if(phd2Guider->isCurrentCameraNotInEkos())
2940 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."));
2941 else if(guideSubframe->isChecked())
2944 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"));
2945 guideSubframe->setChecked(
false);
2948 stopB->setEnabled(
true);
2950 else if (guiderType == GUIDE_INTERNAL)
2957 QVariantMap Guide::getAllSettings()
const
2959 QVariantMap settings;
2962 for (
auto &oneWidget : findChildren<QComboBox*>())
2963 settings.insert(oneWidget->objectName(), oneWidget->currentText());
2966 for (
auto &oneWidget : findChildren<QDoubleSpinBox*>())
2967 settings.insert(oneWidget->objectName(), oneWidget->value());
2970 for (
auto &oneWidget : findChildren<QSpinBox*>())
2971 settings.insert(oneWidget->objectName(), oneWidget->value());
2974 for (
auto &oneWidget : findChildren<QCheckBox*>())
2975 settings.insert(oneWidget->objectName(), oneWidget->isChecked());
2983 void Guide::setAllSettings(
const QVariantMap &settings)
2987 disconnectSettings();
2989 for (
auto &name : settings.keys())
2992 auto comboBox = findChild<QComboBox*>(name);
2995 syncControl(settings, name, comboBox);
3000 auto doubleSpinBox = findChild<QDoubleSpinBox*>(name);
3003 syncControl(settings, name, doubleSpinBox);
3008 auto spinBox = findChild<QSpinBox*>(name);
3011 syncControl(settings, name, spinBox);
3016 auto checkbox = findChild<QCheckBox*>(name);
3019 syncControl(settings, name, checkbox);
3025 for (
auto &key : settings.keys())
3027 auto value = settings[key];
3029 Options::self()->setProperty(key.toLatin1(), value);
3030 Options::self()->save();
3032 m_Settings[key] = value;
3033 m_GlobalSettings[key] = value;
3036 emit settingsUpdated(getAllSettings());
3039 OpticalTrainSettings::Instance()->setOpticalTrainID(OpticalTrainManager::Instance()->
id(opticalTrainCombo->currentText()));
3040 OpticalTrainSettings::Instance()->setOneSetting(OpticalTrainSettings::Guide, m_Settings);
3049 bool Guide::syncControl(
const QVariantMap &settings,
const QString &key,
QWidget * widget)
3057 if ((pSB = qobject_cast<QSpinBox *>(widget)))
3059 const int value = settings[key].toInt(&ok);
3066 else if ((pDSB = qobject_cast<QDoubleSpinBox *>(widget)))
3068 const double value = settings[key].toDouble(&ok);
3075 else if ((pCB = qobject_cast<QCheckBox *>(widget)))
3077 const bool value = settings[key].toBool();
3082 else if ((pComboBox = qobject_cast<QComboBox *>(widget)))
3084 const QString value = settings[key].toString();
3092 void Guide::setupOpticalTrainManager()
3094 connect(OpticalTrainManager::Instance(), &OpticalTrainManager::updated,
this, &Guide::refreshOpticalTrain);
3097 OpticalTrainManager::Instance()->openEditor(opticalTrainCombo->currentText());
3101 if (guiderType == GUIDE_PHD2 && m_GuiderInstance->isConnected())
3103 appendLogText(i18n(
"Cannot change active optical train while PHD2 is connected"));
3107 ProfileSettings::Instance()->setOneSetting(ProfileSettings::GuideOpticalTrain,
3108 OpticalTrainManager::Instance()->id(opticalTrainCombo->itemText(index)));
3109 refreshOpticalTrain();
3110 emit trainChanged();
3114 void Guide::refreshOpticalTrain()
3116 opticalTrainCombo->blockSignals(
true);
3117 opticalTrainCombo->clear();
3118 opticalTrainCombo->addItems(OpticalTrainManager::Instance()->getTrainNames());
3119 trainB->setEnabled(
true);
3121 QVariant trainID = ProfileSettings::Instance()->getOneSetting(ProfileSettings::GuideOpticalTrain);
3125 auto id = trainID.
toUInt();
3128 if (OpticalTrainManager::Instance()->exists(
id) ==
false)
3130 qCWarning(KSTARS_EKOS_GUIDE) <<
"Optical train doesn't exist for id" << id;
3131 id = OpticalTrainManager::Instance()->id(opticalTrainCombo->itemText(0));
3134 auto name = OpticalTrainManager::Instance()->name(
id);
3136 opticalTrainCombo->setCurrentText(name);
3138 auto scope = OpticalTrainManager::Instance()->getScope(name);
3139 m_FocalLength = scope[
"focal_length"].
toDouble(-1);
3140 m_Aperture = scope[
"aperture"].toDouble(-1);
3141 m_FocalRatio = scope[
"focal_ratio"].toDouble(-1);
3142 m_Reducer = OpticalTrainManager::Instance()->getReducer(name);
3145 if (m_Aperture < 0 && m_FocalRatio > 0)
3146 m_Aperture = m_FocalLength / m_FocalRatio;
3148 auto mount = OpticalTrainManager::Instance()->getMount(name);
3151 auto camera = OpticalTrainManager::Instance()->getCamera(name);
3154 if (guiderType == GUIDE_INTERNAL)
3157 camera->setScopeInfo(m_FocalLength * m_Reducer, m_Aperture);
3158 opticalTrainCombo->setToolTip(
QString(
"%1 @ %2").arg(camera->getDeviceName(), scope[
"name"].toString()));
3162 syncTelescopeInfo();
3164 auto guider = OpticalTrainManager::Instance()->getGuider(name);
3167 auto ao = OpticalTrainManager::Instance()->getAdaptiveOptics(name);
3171 OpticalTrainSettings::Instance()->setOpticalTrainID(
id);
3172 auto settings = OpticalTrainSettings::Instance()->getOneSetting(OpticalTrainSettings::Guide);
3173 if (settings.isValid())
3174 setAllSettings(settings.toJsonObject().toVariantMap());
3176 m_Settings = m_GlobalSettings;
3179 opticalTrainCombo->blockSignals(
false);
3182 void Guide::loadGlobalSettings()
3187 QVariantMap settings;
3189 for (
auto &oneWidget : findChildren<QComboBox*>())
3191 if (oneWidget->objectName() ==
"opticalTrainCombo")
3194 key = oneWidget->objectName();
3195 value = Options::self()->property(key.
toLatin1());
3198 oneWidget->setCurrentText(value.
toString());
3199 settings[key] = value;
3204 for (
auto &oneWidget : findChildren<QDoubleSpinBox*>())
3206 key = oneWidget->objectName();
3207 value = Options::self()->property(key.
toLatin1());
3211 settings[key] = value;
3216 for (
auto &oneWidget : findChildren<QSpinBox*>())
3218 key = oneWidget->objectName();
3219 value = Options::self()->property(key.
toLatin1());
3223 settings[key] = value;
3228 for (
auto &oneWidget : findChildren<QCheckBox*>())
3230 key = oneWidget->objectName();
3231 value = Options::self()->property(key.
toLatin1());
3234 oneWidget->setChecked(value.
toBool());
3235 settings[key] = value;
3239 m_GlobalSettings = m_Settings = settings;
3242 void Guide::connectSettings()
3245 for (
auto &oneWidget : findChildren<QComboBox*>())
3249 for (
auto &oneWidget : findChildren<QDoubleSpinBox*>())
3253 for (
auto &oneWidget : findChildren<QSpinBox*>())
3257 for (
auto &oneWidget : findChildren<QCheckBox*>())
3264 void Guide::disconnectSettings()
3267 for (
auto &oneWidget : findChildren<QComboBox*>())
3271 for (
auto &oneWidget : findChildren<QDoubleSpinBox*>())
3275 for (
auto &oneWidget : findChildren<QSpinBox*>())
3279 for (
auto &oneWidget : findChildren<QCheckBox*>())
3287 Options::self()->setProperty(key.
toLatin1(), value);
3288 Options::self()->save();
3290 m_Settings[key] = value;
3291 m_GlobalSettings[key] = value;
3293 emit settingsUpdated(getAllSettings());
3296 OpticalTrainSettings::Instance()->setOpticalTrainID(OpticalTrainManager::Instance()->
id(opticalTrainCombo->currentText()));
3297 OpticalTrainSettings::Instance()->setOneSetting(OpticalTrainSettings::Guide, m_Settings);
3300 void Guide::syncSettings()
3310 if ( (dsb = qobject_cast<QDoubleSpinBox*>(
sender())))
3313 value = dsb->
value();
3316 else if ( (sb = qobject_cast<QSpinBox*>(
sender())))
3319 value = sb->
value();
3321 else if ( (cb = qobject_cast<QCheckBox*>(
sender())))
3326 else if ( (cbox = qobject_cast<QComboBox*>(
sender())))