9#include "guideadaptor.h"
11#include "ksmessagebox.h"
12#include "kstarsdata.h"
13#include "opscalibration.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"
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);
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;
212void Guide::handleHorizontalPlotSizeChange()
214 targetPlot->handleHorizontalPlotSizeChange();
215 calibrationPlot->xAxis->setScaleRatio(calibrationPlot->yAxis, 1.0);
216 calibrationPlot->replot();
219void Guide::handleVerticalPlotSizeChange()
221 targetPlot->handleVerticalPlotSizeChange();
222 calibrationPlot->yAxis->setScaleRatio(calibrationPlot->xAxis, 1.0);
223 calibrationPlot->replot();
226void 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();
258void Guide::buildTarget()
260 targetPlot->buildTarget(guiderAccuracyThreshold->value());
263void Guide::clearGuideGraphs()
269void 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();
279void 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();
292void 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);
303void 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();
357 if (captureTimeout.isActive() && m_State >= Ekos::GUIDE_CAPTURE)
363void Guide::configurePHD2Camera()
367 if(guiderType != GUIDE_PHD2)
374 if(!phd2Guider->isConnected())
378 if(phd2Guider->getCurrentCamera().isEmpty())
380 phd2Guider->requestCurrentEquipmentUpdate();
386 QString currentPHD2CameraName =
"None";
387 if(m_Camera && phd2Guider->getCurrentCamera().contains(m_Camera->getDeviceName()))
390 currentPHD2CameraName = (phd2Guider->getCurrentCamera());
396 if(m_LastPHD2CameraName == currentPHD2CameraName)
398 setExternalGuiderBLOBEnabled(!guideSubframe->isChecked());
404 setExternalGuiderBLOBEnabled(
false);
410 m_LastPHD2CameraName = currentPHD2CameraName;
412 m_LastPHD2MountName = phd2Guider->getCurrentMount();
415 phd2Guider->setCurrentCameraIsNotInEkos(m_Camera ==
nullptr);
417 if(phd2Guider->isCurrentCameraNotInEkos())
420 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.",
421 phd2Guider->getCurrentCamera()));
422 guideSubframe->setEnabled(
false);
425 guideSubframe->setChecked(
true);
430 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.",
431 phd2Guider->getCurrentCamera()));
432 guideSubframe->setEnabled(
true);
434 guideSubframe->setChecked(guideSubframe->isChecked());
439 if (m_Mount && m_Mount == device)
446 m_Mount->disconnect(
this);
456 return m_Camera->getDeviceName();
461void Guide::checkCamera()
465 if (!m_Camera || guiderType != GUIDE_INTERNAL)
473 case GUIDE_CONNECTED:
474 case GUIDE_DISCONNECTED:
475 case GUIDE_CALIBRATION_ERROR:
483 case GUIDE_STAR_SELECT:
484 case GUIDE_CALIBRATING:
485 case GUIDE_CALIBRATION_SUCCESS:
487 case GUIDE_SUSPENDED:
488 case GUIDE_REACQUIRE:
489 case GUIDE_DITHERING:
490 case GUIDE_MANUAL_DITHERING:
491 case GUIDE_DITHERING_ERROR:
492 case GUIDE_DITHERING_SUCCESS:
493 case GUIDE_DITHERING_SETTLE:
499 auto targetChip = m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
502 qCCritical(KSTARS_EKOS_GUIDE) <<
"Failed to retrieve active guide chip in camera";
506 if (targetChip->isCapturing())
509 if (guiderType != GUIDE_INTERNAL)
521void Ekos::Guide::checkUseGuideHead()
523 if (m_Camera ==
nullptr)
526 if (m_Camera->hasGuideHead() && Options::useGuideHead())
529 useGuideHead =
false;
531 opsGuide->kcfg_UseGuideHead->
setEnabled(m_Camera->hasGuideHead());
534void Guide::syncCameraInfo()
539 auto nvp = m_Camera->getNumber(useGuideHead ?
"GUIDER_INFO" :
"CCD_INFO");
543 auto np = nvp->findWidgetByName(
"CCD_PIXEL_SIZE_X");
545 ccdPixelSizeX = np->getValue();
547 np = nvp->findWidgetByName(
"CCD_PIXEL_SIZE_Y");
549 ccdPixelSizeY = np->getValue();
551 np = nvp->findWidgetByName(
"CCD_PIXEL_SIZE_Y");
553 ccdPixelSizeY = np->getValue();
559void Guide::syncTelescopeInfo()
561 if (m_Mount ==
nullptr || m_Mount->isConnected() ==
false)
567void Guide::updateGuideParams()
569 if (m_Camera ==
nullptr)
574 ISD::CameraChip *targetChip = m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
576 if (targetChip ==
nullptr)
578 appendLogText(
i18n(
"Connection to the guide CCD is lost."));
582 if (targetChip->getFrameType() != FRAME_LIGHT)
585 if(guiderType == GUIDE_INTERNAL)
586 guideBinning->setEnabled(targetChip->canBin());
588 int subBinX = 1, subBinY = 1;
589 if (targetChip->canBin())
591 int maxBinX, maxBinY;
593 targetChip->getBinning(&subBinX, &subBinY);
594 targetChip->getMaxBin(&maxBinX, &maxBinY);
597 if( guideBinIndex >= 0 && guideBinIndex < maxBinX && guideBinIndex < maxBinY )
599 subBinX = guideBinIndex + 1;
600 subBinY = guideBinIndex + 1;
603 guideBinIndex = subBinX - 1;
605 guideBinning->blockSignals(
true);
607 guideBinning->clear();
608 for (
int i = 1; i <= maxBinX; i++)
609 guideBinning->addItem(
QString(
"%1x%2").arg(i).arg(i));
611 guideBinning->setCurrentIndex( guideBinIndex );
613 guideBinning->blockSignals(
false);
617 if (frameSettings.
contains(targetChip) ==
false)
620 if (targetChip->getFrame(&
x, &
y, &w, &h))
624 int minX, maxX, minY, maxY, minW, maxW, minH, maxH;
625 targetChip->getFrameMinMax(&minX, &maxX, &minY, &maxY, &minW, &maxW, &minH, &maxH);
626 auto subframed = guideSubframe->isChecked();
628 QVariantMap settings;
630 settings[
"x"] = subframed ?
x : minX;
631 settings[
"y"] = subframed ?
y : minY;
632 settings[
"w"] = subframed ? w : maxW;
633 settings[
"h"] = subframed ? h : maxH;
634 settings[
"binx"] = subBinX;
635 settings[
"biny"] = subBinY;
637 frameSettings[targetChip] = settings;
644 QVariantMap settings = frameSettings[targetChip];
645 settings[
"binx"] = subBinX;
646 settings[
"biny"] = subBinY;
647 frameSettings[targetChip] = settings;
650 if (ccdPixelSizeX != -1 && ccdPixelSizeY != -1 && m_FocalLength > 0)
652 auto effectiveFocaLength = m_Reducer * m_FocalLength;
653 m_GuiderInstance->setGuiderParams(ccdPixelSizeX, ccdPixelSizeY, m_Aperture, effectiveFocaLength);
654 emit guideChipUpdated(targetChip);
657 if (targetChip->getFrame(&
x, &
y, &w, &h))
659 m_GuiderInstance->setFrameParams(
x,
y, w, h, subBinX, subBinY);
662 l_Focal->setText(
QString(
"%1mm").arg(m_FocalLength, 0,
'f', 0));
664 l_Aperture->setText(
QString(
"%1mm").arg(m_Aperture, 0,
'f', 0));
667 l_Aperture->setText(
"DSLR");
670 if (m_FocalRatio > 0)
671 l_FbyD->setText(
QString(
"F/%1").arg(m_FocalRatio, 0,
'f', 1));
672 else if (m_Aperture > 0)
673 l_FbyD->setText(
QString(
"F/%1").arg(m_FocalLength / m_Aperture, 0,
'f', 1));
676 pixScaleX = 206264.8062470963552 * ccdPixelSizeX / 1000.0 / effectiveFocaLength;
677 pixScaleY = 206264.8062470963552 * ccdPixelSizeY / 1000.0 / effectiveFocaLength;
680 double fov_w = (w * pixScaleX) / 60.0;
681 double fov_h = (h * pixScaleY) / 60.0;
687 if (m_Camera->hasGain())
689 double min, max, step, value;
690 m_Camera->getGainMinMaxStep(&min, &max, &step);
693 guideGainSpecialValue = min - step;
694 guideGain->setRange(guideGainSpecialValue, max);
695 guideGain->setSpecialValueText(
i18n(
"--"));
696 guideGain->setEnabled(
true);
697 guideGain->setSingleStep(step);
698 m_Camera->getGain(&value);
700 auto gain = m_Settings[
"guideGain"];
704 TargetCustomGainValue = gain.toDouble();
705 if (TargetCustomGainValue > 0)
706 guideGain->setValue(TargetCustomGainValue);
708 guideGain->setValue(guideGainSpecialValue);
710 guideGain->setReadOnly(m_Camera->getGainPermission() == IP_RO);
714 if (guideGain->value() > guideGainSpecialValue)
715 TargetCustomGainValue = guideGain->value();
719 guideGain->setEnabled(
false);
724 if (guiderType != GUIDE_INTERNAL || (m_Guider && device == m_Guider))
734 connect(m_Guider, &ISD::ConcreteDevice::Connected,
this, [
this]()
736 guideB->setEnabled(
true);
738 connect(m_Guider, &ISD::ConcreteDevice::Disconnected,
this, [
this]()
740 guideB->setEnabled(
false);
744 guideB->setEnabled(m_Guider && m_Guider->isConnected());
750 if (guiderType != GUIDE_INTERNAL || (m_AO && device == m_AO))
763 if (guiderType != GUIDE_INTERNAL || m_Guider ==
nullptr)
766 return m_Guider->getDeviceName();
797 qCDebug(KSTARS_EKOS_GUIDE) <<
"Internal guider skipping capture, already running with remaining seconds =" <<
802 buildOperationStack(GUIDE_CAPTURE);
804 return executeOperationStack();
807bool Guide::captureOneFrame()
809 captureTimeout.
stop();
811 if (m_Camera ==
nullptr)
814 if (m_Camera->isConnected() ==
false)
816 appendLogText(
i18n(
"Error: lost connection to CCD."));
820 double seqExpose = guideExposure->value();
822 ISD::CameraChip *targetChip = m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
824 prepareCapture(targetChip);
826 m_GuideView->setBaseSize(guideWidget->size());
830 if (frameSettings.
contains(targetChip))
832 QVariantMap settings = frameSettings[targetChip];
833 targetChip->setFrame(settings[
"x"].toInt(), settings[
"y"].toInt(), settings[
"w"].toInt(),
834 settings[
"h"].toInt());
835 targetChip->setBinning(settings[
"binx"].toInt(), settings[
"biny"].toInt());
839 qCDebug(KSTARS_EKOS_GUIDE) <<
"Capturing frame...";
841 double finalExposure = seqExpose;
845 if (operationStack.contains(GUIDE_STAR_SELECT) && guideAutoStar->isChecked() &&
846 !((guiderType == GUIDE_INTERNAL) && internalGuider->SEPMultiStarEnabled()))
850 m_GuideView->setProperty(
"suspended", operationStack.contains(GUIDE_DARK));
853 captureTimeout.
start(finalExposure * 1000 + CAPTURE_TIMEOUT_THRESHOLD);
855 targetChip->capture(finalExposure);
862 targetChip->setBatchMode(
false);
863 targetChip->setCaptureMode(FITS_GUIDE);
864 targetChip->setFrameType(FRAME_LIGHT);
865 targetChip->setCaptureFilter(FITS_NONE);
866 m_Camera->setEncodingFormat(
"FITS");
869 if (m_Camera->hasGain() && guideGain->isEnabled() && guideGain->value() > guideGainSpecialValue)
870 m_Camera->setGain(guideGain->value());
873void Guide::abortExposure()
875 if (m_Camera && guiderType == GUIDE_INTERNAL)
877 captureTimeout.
stop();
880 m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
881 if (targetChip->isCapturing())
883 qCDebug(KSTARS_EKOS_GUIDE) <<
"Aborting guide capture";
884 targetChip->abortExposure();
891 if (m_Camera && guiderType == GUIDE_INTERNAL)
893 captureTimeout.
stop();
896 m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
897 if (targetChip->isCapturing())
898 targetChip->abortExposure();
901 manualDitherB->setEnabled(
false);
908 case GUIDE_CONNECTED:
909 case GUIDE_DISCONNECTED:
912 case GUIDE_CALIBRATING:
913 case GUIDE_DITHERING:
914 case GUIDE_STAR_SELECT:
918 m_GuiderInstance->abort();
928void Guide::setBusy(
bool enable)
932 else if (enable ==
false && pi->
isAnimated() ==
false)
937 clearCalibrationB->setEnabled(
false);
938 guideB->setEnabled(
false);
939 captureB->setEnabled(
false);
940 loopB->setEnabled(
false);
941 guideDarkFrame->setEnabled(
false);
942 guideSubframe->setEnabled(
false);
943 guideAutoStar->setEnabled(
false);
944 stopB->setEnabled(
true);
946 opticalTrainCombo->setEnabled(
false);
947 trainB->setEnabled(
false);
953 if(guiderType != GUIDE_LINGUIDER)
955 captureB->setEnabled(
true);
956 loopB->setEnabled(
true);
957 guideAutoStar->setEnabled(!internalGuider->SEPMultiStarEnabled());
959 guideSubframe->setEnabled(!internalGuider->SEPMultiStarEnabled());
961 if (guiderType == GUIDE_INTERNAL)
962 guideDarkFrame->setEnabled(
true);
964 if (calibrationComplete ||
965 ((guiderType == GUIDE_INTERNAL) &&
966 Options::reuseGuideCalibration() &&
967 !Options::serializedCalibration().isEmpty()))
968 clearCalibrationB->setEnabled(
true);
969 guideB->setEnabled(
true);
970 stopB->setEnabled(
false);
974 opticalTrainCombo->setEnabled(
true);
975 trainB->setEnabled(
true);
981void Guide::processCaptureTimeout()
984 if (m_State == GUIDE_SUSPENDED)
986 appendLogText(
i18n(
"Exposure timeout, but suspended. Ignoring..."));
990 auto restartExposure = [&]()
992 appendLogText(
i18n(
"Exposure timeout. Restarting exposure..."));
993 m_Camera->setEncodingFormat(
"FITS");
994 ISD::CameraChip *targetChip = m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
995 targetChip->abortExposure();
996 prepareCapture(targetChip);
1000 targetChip->capture(guideExposure->value());
1001 captureTimeout.
start(guideExposure->value() * 1000 + CAPTURE_TIMEOUT_THRESHOLD);
1004 m_CaptureTimeoutCounter++;
1006 if (m_Camera ==
nullptr)
1009 if (m_DeviceRestartCounter >= 3)
1011 m_CaptureTimeoutCounter = 0;
1012 m_DeviceRestartCounter = 0;
1013 if (m_State == GUIDE_GUIDING)
1014 appendLogText(
i18n(
"Exposure timeout. Aborting Autoguide."));
1015 else if (m_State == GUIDE_DITHERING)
1016 appendLogText(
i18n(
"Exposure timeout. Aborting Dithering."));
1017 else if (m_State == GUIDE_CALIBRATING)
1018 appendLogText(
i18n(
"Exposure timeout. Aborting Calibration."));
1020 captureTimeout.
stop();
1025 if (m_CaptureTimeoutCounter > 3)
1027 appendLogText(
i18n(
"Exposure timeout. Too many. Restarting driver."));
1028 QString camera = m_Camera->getDeviceName();
1029 QString via = m_Guider ? m_Guider->getDeviceName() :
"";
1030 ISD::CameraChip *targetChip = m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
1031 QVariantMap settings = frameSettings[targetChip];
1032 emit driverTimedout(camera);
1035 m_DeviceRestartCounter++;
1036 reconnectDriver(camera, settings);
1044void Guide::reconnectDriver(
const QString &camera, QVariantMap settings)
1046 if (m_Camera && m_Camera->getDeviceName() == camera)
1049 Ekos::GuideState currentState = m_State;
1050 m_State = GUIDE_IDLE;
1053 m_State = currentState;
1055 if (guiderType == GUIDE_INTERNAL)
1058 ISD::CameraChip *targetChip = m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
1059 frameSettings[targetChip] = settings;
1061 m_CaptureTimeoutCounter = 0;
1070 reconnectDriver(camera, settings);
1076 ISD::CameraChip *targetChip = m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
1077 if (targetChip->getCaptureMode() != FITS_GUIDE)
1081 QString blobInfo =
QString(
"{Device: %1 Property: %2 Element: %3 Chip: %4}").
arg(data->property(
"device").toString())
1082 .
arg(data->property(
"blobVector").toString())
1083 .
arg(data->property(
"blobElement").toString())
1084 .
arg(data->property(
"chip").toInt());
1086 qCWarning(KSTARS_EKOS_GUIDE) << blobInfo <<
"Ignoring Received FITS as it has the wrong capture mode" <<
1087 targetChip->getCaptureMode();
1093 captureTimeout.
stop();
1094 m_CaptureTimeoutCounter = 0;
1098 m_GuideView->loadData(data);
1102 m_ImageData.
reset();
1104 if (guiderType == GUIDE_INTERNAL)
1105 internalGuider->setImageData(m_ImageData);
1111 int subBinX = 1, subBinY = 1;
1112 targetChip->getBinning(&subBinX, &subBinY);
1114 if (starCenter.
x() == 0 && starCenter.
y() == 0)
1116 int x = 0,
y = 0, w = 0, h = 0;
1118 if (frameSettings.
contains(targetChip))
1120 QVariantMap settings = frameSettings[targetChip];
1121 x = settings[
"x"].toInt();
1122 y = settings[
"y"].toInt();
1123 w = settings[
"w"].toInt();
1124 h = settings[
"h"].toInt();
1127 targetChip->getFrame(&
x, &
y, &w, &h);
1129 starCenter.
setX(w / (2 * subBinX));
1130 starCenter.
setY(h / (2 * subBinY));
1131 starCenter.
setZ(subBinX);
1134 syncTrackingBoxPosition();
1137 setCaptureComplete();
1142void Guide::setCaptureComplete()
1144 if (!m_GuideView.
isNull())
1145 m_GuideView->clearNeighbors();
1147 DarkLibrary::Instance()->disconnect(
this);
1149 if (operationStack.isEmpty() ==
false)
1151 executeOperationStack();
1155 qCDebug(KSTARS_EKOS_GUIDE) <<
"Capture complete, state=" << getGuideStatusString(m_State);
1160 case GUIDE_CONNECTED:
1161 case GUIDE_DISCONNECTED:
1162 case GUIDE_CALIBRATION_SUCCESS:
1163 case GUIDE_CALIBRATION_ERROR:
1164 case GUIDE_DITHERING_ERROR:
1169 qCDebug(KSTARS_EKOS_GUIDE) <<
"Guiding capture complete.";
1170 m_State = GUIDE_IDLE;
1171 emit newStatus(m_State);
1179 case GUIDE_CALIBRATING:
1180 m_GuiderInstance->calibrate();
1184 m_GuiderInstance->guide();
1187 case GUIDE_DITHERING:
1188 m_GuiderInstance->dither(Options::ditherPixels());
1192 case GUIDE_MANUAL_DITHERING:
1193 dynamic_cast<InternalGuider*
>(m_GuiderInstance)->processManualDithering();
1196 case GUIDE_REACQUIRE:
1197 m_GuiderInstance->reacquire();
1200 case GUIDE_DITHERING_SETTLE:
1201 if (Options::ditherNoGuiding())
1206 case GUIDE_SUSPENDED:
1207 if (Options::gPGEnabled())
1208 m_GuiderInstance->guide();
1215 emit newImage(m_GuideView);
1216 emit newStarPixmap(m_GuideView->getTrackingBoxPixmap(10));
1219void Guide::appendLogText(
const QString &text)
1221 m_LogText.
insert(0,
i18nc(
"log entry; %1 is the date, %2 is the text",
"%1 %2",
1222 KStarsData::Instance()->lt().
toString(
"yyyy-MM-ddThh:mm:ss"), text));
1224 qCInfo(KSTARS_EKOS_GUIDE) << text;
1237 if (m_Guider ==
nullptr || m_GuiderInstance ==
nullptr)
1240 if (guiderType == GUIDE_INTERNAL)
1242 dynamic_cast<InternalGuider *
>(m_GuiderInstance)->
setDECSwap(enable);
1243 m_Guider->setDECSwap(enable);
1247bool Guide::sendMultiPulse(GuideDirection ra_dir,
int ra_msecs, GuideDirection dec_dir,
int dec_msecs,
1248 CaptureAfterPulses followWithCapture)
1250 if (m_Guider ==
nullptr || (ra_dir == NO_DIR && dec_dir == NO_DIR))
1253 if (followWithCapture == StartCaptureAfterPulses)
1257 auto ms = std::max(ra_msecs, dec_msecs) + 100;
1258 auto delay = std::max(
static_cast<int>(guideDelay->value() * 1000), ms);
1260 m_PulseTimer.
start(delay);
1262 return m_Guider->doPulse(ra_dir, ra_msecs, dec_dir, dec_msecs);
1265bool Guide::sendSinglePulse(GuideDirection dir,
int msecs, CaptureAfterPulses followWithCapture)
1267 if (m_Guider ==
nullptr || dir == NO_DIR)
1270 if (followWithCapture == StartCaptureAfterPulses)
1274 auto ms = msecs + 100;
1275 auto delay = std::max(
static_cast<int>(guideDelay->value() * 1000), ms);
1277 m_PulseTimer.
start(delay);
1280 return m_Guider->doPulse(dir, msecs);
1286 m_State = GUIDE_IDLE;
1287 qCDebug(KSTARS_EKOS_GUIDE) <<
"Calibrating...";
1288 emit newStatus(m_State);
1290 if (guiderType == GUIDE_INTERNAL)
1294 qCCritical(KSTARS_EKOS_GUIDE) <<
"No camera detected. Check optical trains.";
1298 auto targetChip = m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
1300 if (frameSettings.
contains(targetChip))
1302 targetChip->resetFrame();
1304 targetChip->getFrame(&
x, &
y, &w, &h);
1305 QVariantMap settings = frameSettings[targetChip];
1310 frameSettings[targetChip] = settings;
1316 buildOperationStack(GUIDE_CALIBRATING);
1318 executeOperationStack();
1320 if (m_Camera && m_Guider)
1322 qCDebug(KSTARS_EKOS_GUIDE) <<
"Starting calibration using camera:" << m_Camera->getDeviceName() <<
"via" <<
1323 m_Guider->getDeviceName();
1331 auto executeGuide = [
this]()
1333 if(guiderType != GUIDE_PHD2)
1335 if (calibrationComplete ==
false)
1342 m_GuiderInstance->guide();
1348 if(!guideAutoStar->isChecked())
1350 if(guiderType == GUIDE_PHD2 && m_GuideView->isTrackingBoxEnabled())
1352 double x = starCenter.
x();
1353 double y = starCenter.
y();
1355 if(!m_ImageData.
isNull())
1357 if(m_ImageData->width() > 50)
1359 guideConnect =
connect(
this, &Guide::newStatus,
this, [
this,
x,
y](Ekos::GuideState newState)
1361 if(newState == GUIDE_GUIDING)
1363 phd2Guider->setLockPosition(
x,
y);
1373 if (m_MountStatus == ISD::Mount::MOUNT_PARKED)
1375 KSMessageBox::Instance()->sorry(
i18n(
"The mount is parked. Unpark to start guiding."));
1385 if (Options::ditherNoGuiding() && m_State == GUIDE_IDLE)
1391 if (m_State == GUIDE_DITHERING || m_State == GUIDE_DITHERING_SETTLE)
1395 double time = guideTimer.
elapsed() / 1000.0;
1399 ditherLabel->position->
setCoords(time, 1.5);
1403 ditherLabel->
setText(
"Dither");
1406 if (guiderType == GUIDE_INTERNAL && !Options::ditherWithOnePulse())
1408 if (m_State != GUIDE_GUIDING)
1411 setStatus(GUIDE_DITHERING);
1416 return m_GuiderInstance->dither(Options::ditherPixels());
1421 if (m_State == GUIDE_SUSPENDED)
1423 else if (m_State >= GUIDE_CAPTURE)
1424 return m_GuiderInstance->suspend();
1431 if (m_State == GUIDE_GUIDING)
1433 else if (m_State == GUIDE_SUSPENDED)
1434 return m_GuiderInstance->resume();
1460void Guide::setPierSide(ISD::Mount::PierSide newSide)
1462 m_GuiderInstance->setPierSide(newSide);
1467 if (guiderType == GUIDE_INTERNAL &&
1468 m_State != GUIDE_GUIDING &&
1469 m_State != GUIDE_CALIBRATING &&
1470 calibrationComplete)
1473 if (Options::reuseGuideCalibration())
1474 calibrationComplete =
false;
1478 appendLogText(
i18n(
"Pier side change detected. Clearing calibration."));
1483void Guide::setMountStatus(ISD::Mount::Status newState)
1485 m_MountStatus = newState;
1487 if (newState == ISD::Mount::MOUNT_PARKING || newState == ISD::Mount::MOUNT_SLEWING)
1490 if (Options::resetGuideCalibration())
1492 appendLogText(
i18n(
"Mount is moving. Resetting calibration..."));
1495 else if (Options::reuseGuideCalibration() && (guiderType == GUIDE_INTERNAL))
1498 calibrationComplete =
false;
1501 if (Options::gPGEnabled())
1502 m_GuiderInstance->resetGPG();
1505 if (m_State == GUIDE_GUIDING || m_State == GUIDE_DITHERING)
1507 if (newState == ISD::Mount::MOUNT_PARKING)
1508 appendLogText(
i18n(
"Mount is parking. Aborting guide..."));
1510 appendLogText(
i18n(
"Mount is slewing. Aborting guide..."));
1516 if (guiderType != GUIDE_INTERNAL)
1521 case ISD::Mount::MOUNT_SLEWING:
1522 case ISD::Mount::MOUNT_PARKING:
1523 case ISD::Mount::MOUNT_MOVING:
1524 captureB->setEnabled(
false);
1525 loopB->setEnabled(
false);
1526 clearCalibrationB->setEnabled(
false);
1527 manualPulseB->setEnabled(
false);
1533 captureB->setEnabled(
true);
1534 loopB->setEnabled(
true);
1535 clearCalibrationB->setEnabled(
true);
1536 manualPulseB->setEnabled(
true);
1541void Guide::setMountCoords(
const SkyPoint &position, ISD::Mount::PierSide pierSide,
const dms &ha)
1544 m_GuiderInstance->setMountCoords(position, pierSide);
1545 m_ManaulPulse->setMountCoords(position);
1550 guideExposure->setValue(value);
1555 if (guideSubframe->isChecked() != enable)
1556 guideSubframe->setChecked(enable);
1557 if(guiderType == GUIDE_PHD2)
1558 setExternalGuiderBLOBEnabled(!enable);
1563 if(guiderType == GUIDE_INTERNAL)
1564 guideAutoStar->setChecked(enable);
1569 calibrationComplete =
false;
1571 m_GuiderInstance->clearCalibration();
1573 appendLogText(
i18n(
"Calibration is cleared."));
1576void Guide::setStatus(Ekos::GuideState newState)
1578 if (newState == m_State)
1581 if (newState == GUIDE_ABORTED)
1582 emit newStatus(m_State);
1586 GuideState previousState = m_State;
1589 emit newStatus(m_State);
1593 case GUIDE_CONNECTED:
1594 appendLogText(
i18n(
"External guider connected."));
1595 externalConnectB->setEnabled(
false);
1596 externalDisconnectB->setEnabled(
true);
1597 clearCalibrationB->setEnabled(
true);
1598 guideB->setEnabled(
true);
1600 if(guiderType == GUIDE_PHD2)
1602 captureB->setEnabled(
true);
1603 loopB->setEnabled(
true);
1604 guideAutoStar->setEnabled(
true);
1605 configurePHD2Camera();
1606 setExternalGuiderBLOBEnabled(!guideSubframe->isChecked());
1607 guideSquareSize->setEnabled(
true);
1611 case GUIDE_DISCONNECTED:
1612 appendLogText(
i18n(
"External guider disconnected."));
1614 externalConnectB->setEnabled(
true);
1615 externalDisconnectB->setEnabled(
false);
1616 clearCalibrationB->setEnabled(
false);
1617 guideB->setEnabled(
false);
1618 captureB->setEnabled(
false);
1619 loopB->setEnabled(
false);
1620 guideAutoStar->setEnabled(
false);
1621 guideSquareSize->setEnabled(
false);
1628 case GUIDE_CALIBRATION_SUCCESS:
1629 appendLogText(
i18n(
"Calibration completed."));
1630 manualPulseB->setEnabled(
true);
1631 calibrationComplete =
true;
1639 case GUIDE_CALIBRATION_ERROR:
1641 manualDitherB->setEnabled(
false);
1642 manualPulseB->setEnabled(
true);
1645 case GUIDE_CALIBRATING:
1646 clearCalibrationGraphs();
1647 appendLogText(
i18n(
"Calibration started."));
1649 manualPulseB->setEnabled(
false);
1653 if (previousState == GUIDE_SUSPENDED || previousState == GUIDE_DITHERING_SUCCESS)
1654 appendLogText(
i18n(
"Guiding resumed."));
1657 appendLogText(
i18n(
"Autoguiding started."));
1662 driftGraph->resetTimer();
1663 driftGraph->refreshColorScheme();
1665 manualDitherB->setEnabled(
true);
1669 appendLogText(
i18n(
"Autoguiding aborted."));
1673 case GUIDE_SUSPENDED:
1674 appendLogText(
i18n(
"Guiding suspended."));
1677 case GUIDE_REACQUIRE:
1678 if (guiderType == GUIDE_INTERNAL)
1682 case GUIDE_MANUAL_DITHERING:
1683 appendLogText(
i18n(
"Manual dithering in progress."));
1686 case GUIDE_DITHERING:
1687 appendLogText(
i18n(
"Dithering in progress."));
1690 case GUIDE_DITHERING_SETTLE:
1691 appendLogText(
i18np(
"Post-dither settling for %1 second...",
"Post-dither settling for %1 seconds...",
1692 Options::ditherSettle()));
1695 case GUIDE_DITHERING_ERROR:
1696 appendLogText(
i18n(
"Dithering failed."));
1698 if (guiderType != GUIDE_LINGUIDER)
1701 m_State = GUIDE_ABORTED;
1706 case GUIDE_DITHERING_SUCCESS:
1707 appendLogText(
i18n(
"Dithering completed successfully."));
1709 if (Options::ditherNoGuiding() ==
false)
1711 setStatus(GUIDE_GUIDING);
1713 if (guiderType == GUIDE_INTERNAL)
1722void Guide::updateCCDBin(
int index)
1724 if (m_Camera ==
nullptr || guiderType != GUIDE_INTERNAL)
1727 ISD::CameraChip *targetChip = m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
1729 targetChip->setBinning(index + 1, index + 1);
1730 guideBinIndex = index;
1732 QVariantMap settings = frameSettings[targetChip];
1733 settings[
"binx"] = index + 1;
1734 settings[
"biny"] = index + 1;
1735 frameSettings[targetChip] = settings;
1737 m_GuiderInstance->setFrameParams(settings[
"x"].toInt(), settings[
"y"].toInt(), settings[
"w"].toInt(), settings[
"h"].toInt(),
1738 settings[
"binx"].toInt(), settings[
"biny"].toInt());
1743 if (m_Camera ==
nullptr || (prop.getDeviceName() != m_Camera->getDeviceName()) || guiderType != GUIDE_INTERNAL)
1746 if ((prop.isNameMatch(
"CCD_BINNING") && useGuideHead ==
false) ||
1747 (prop.isNameMatch(
"GUIDER_BINNING") && useGuideHead))
1749 auto nvp = prop.getNumber();
1750 auto value = nvp->at(0)->getValue();
1751 if (guideBinIndex > (value - 1))
1753 appendLogText(
i18n(
"%1x%1 guide binning is not supported.", guideBinIndex + 1));
1754 guideBinning->setCurrentIndex( value - 1 );
1759 guideBinning->setCurrentIndex(guideBinIndex);
1767 if (guiderType != GUIDE_INTERNAL || targetChip->getCCD() != m_Camera)
1770 INDI_UNUSED(exposure);
1772 if (expState == IPS_ALERT &&
1773 ((m_State == GUIDE_GUIDING) || (m_State == GUIDE_DITHERING) || (m_State == GUIDE_CALIBRATING)))
1775 appendLogText(
i18n(
"Exposure failed. Restarting exposure..."));
1776 m_Camera->setEncodingFormat(
"FITS");
1777 targetChip->capture(guideExposure->value());
1781void Guide::configSEPMultistarOptions()
1784 if (internalGuider->SEPMultiStarEnabled())
1786 guideSubframe->setChecked(
false);
1787 guideSubframe->setEnabled(
false);
1788 guideAutoStar->setChecked(
true);
1789 guideAutoStar->setEnabled(
false);
1793 guideAutoStar->setEnabled(
true);
1794 guideSubframe->setEnabled(
true);
1796 auto subframed = m_Settings[
"guideSubframe"];
1797 if (subframed.isValid())
1798 guideSubframe->setChecked(subframed.toBool());
1800 auto autostar = m_Settings[
"guideAutoStar"];
1801 if (autostar.isValid())
1802 guideAutoStar->setChecked(autostar.toBool());
1808 if (guideDarkFrame->isChecked() != enable)
1809 guideDarkFrame->setChecked(enable);
1812void Guide::saveDefaultGuideExposure()
1814 if(guiderType == GUIDE_PHD2)
1816 phd2Guider->requestSetExposureTime(guideExposure->value() * 1000);
1817 else if (guiderType == GUIDE_INTERNAL)
1819 internalGuider->setExposureTime();
1823void Guide::setStarPosition(
const QVector3D &newCenter,
bool updateNow)
1825 starCenter.
setX(newCenter.
x());
1826 starCenter.
setY(newCenter.
y());
1827 if (newCenter.
z() > 0)
1828 starCenter.
setZ(newCenter.
z());
1831 syncTrackingBoxPosition();
1834void Guide::syncTrackingBoxPosition()
1836 if(!m_Camera || guiderType == GUIDE_LINGUIDER)
1839 if(guiderType == GUIDE_PHD2)
1842 if(!m_ImageData.
isNull())
1844 if(m_ImageData->width() < 50)
1846 m_GuideView->setTrackingBoxEnabled(
false);
1852 ISD::CameraChip *targetChip = m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
1853 Q_ASSERT(targetChip);
1855 int subBinX = 1, subBinY = 1;
1856 targetChip->getBinning(&subBinX, &subBinY);
1858 if (starCenter.
isNull() ==
false)
1860 double boxSize = guideSquareSize->currentText().toInt();
1862 targetChip->getFrame(&
x, &
y, &w, &h);
1864 if (boxSize / subBinX >= w || boxSize / subBinY >= h)
1866 int newIndex = guideSquareSize->currentIndex() - 1;
1868 guideSquareSize->setCurrentIndex(newIndex);
1873 if (subBinX != starCenter.
z())
1875 if (starCenter.
z() > 0)
1877 starCenter.
setX(starCenter.
x() * (starCenter.
z() / subBinX));
1878 starCenter.
setY(starCenter.
y() * (starCenter.
z() / subBinY));
1881 starCenter.
setZ(subBinX);
1884 QRect starRect =
QRect(starCenter.
x() - boxSize / (2 * subBinX), starCenter.
y() - boxSize / (2 * subBinY),
1885 boxSize / subBinX, boxSize / subBinY);
1886 m_GuideView->setTrackingBoxEnabled(
true);
1887 m_GuideView->setTrackingBox(starRect);
1895 type = Options::guiderType();
1896 else if (type == guiderType)
1899 if (m_State == GUIDE_CALIBRATING || m_State == GUIDE_GUIDING || m_State == GUIDE_DITHERING)
1901 appendLogText(
i18n(
"Cannot change guider type while active."));
1905 if (m_GuiderInstance !=
nullptr)
1908 if (m_GuiderInstance->isConnected())
1909 m_GuiderInstance->Disconnect();
1915 guiderType =
static_cast<GuiderType
>(type);
1919 case GUIDE_INTERNAL:
1921 connect(internalGuider, &InternalGuider::newMultiPulse,
this, &Guide::sendMultiPulse);
1922 connect(internalGuider, &InternalGuider::newSinglePulse,
this, &Guide::sendSinglePulse);
1924 connect(internalGuider, &InternalGuider::newStarPixmap,
this, &Guide::newStarPixmap);
1926 m_GuiderInstance = internalGuider;
1928 internalGuider->setSquareAlgorithm(opsGuide->kcfg_GuideAlgorithm->currentIndex());
1930 clearCalibrationB->setEnabled(
true);
1931 guideB->setEnabled(
true);
1932 captureB->setEnabled(
true);
1933 loopB->setEnabled(
true);
1935 configSEPMultistarOptions();
1936 guideDarkFrame->setEnabled(
true);
1938 guideExposure->setEnabled(
true);
1939 guideBinning->setEnabled(
true);
1940 guideSquareSize->setEnabled(
true);
1942 externalConnectB->setEnabled(
false);
1943 externalDisconnectB->setEnabled(
false);
1946 infoGroup->setEnabled(
true);
1947 l_Aperture->setEnabled(
true);
1948 l_FOV->setEnabled(
true);
1949 l_FbyD->setEnabled(
true);
1950 l_Focal->setEnabled(
true);
1951 driftGraphicsGroup->setEnabled(
true);
1953 updateGuideParams();
1958 if (phd2Guider.isNull())
1959 phd2Guider =
new PHD2();
1961 m_GuiderInstance = phd2Guider;
1962 phd2Guider->setGuideView(m_GuideView);
1966 clearCalibrationB->setEnabled(
true);
1967 captureB->setEnabled(
false);
1968 loopB->setEnabled(
false);
1969 guideDarkFrame->setEnabled(
false);
1970 guideSubframe->setEnabled(
false);
1971 guideAutoStar->setEnabled(
false);
1972 guideB->setEnabled(
false);
1973 externalConnectB->setEnabled(
false);
1975 rAGuideEnabled->setEnabled(
false);
1976 eastRAGuideEnabled->setEnabled(
false);
1977 westRAGuideEnabled->setEnabled(
false);
1980 infoGroup->setEnabled(
true);
1981 l_Aperture->setEnabled(
false);
1982 l_FOV->setEnabled(
false);
1983 l_FbyD->setEnabled(
false);
1984 l_Focal->setEnabled(
false);
1985 driftGraphicsGroup->setEnabled(
true);
1987 guideExposure->setEnabled(
true);
1988 guideBinning->setEnabled(
false);
1989 guideSquareSize->setEnabled(
false);
1991 if (Options::resetGuideCalibration())
1992 appendLogText(
i18n(
"Warning: Reset Guiding Calibration is enabled. It is recommended to turn this option off for PHD2."));
1994 updateGuideParams();
1997 case GUIDE_LINGUIDER:
1998 if (linGuider.isNull())
2001 m_GuiderInstance = linGuider;
2003 clearCalibrationB->setEnabled(
true);
2004 captureB->setEnabled(
false);
2005 loopB->setEnabled(
false);
2006 guideDarkFrame->setEnabled(
false);
2007 guideSubframe->setEnabled(
false);
2008 guideAutoStar->setEnabled(
false);
2009 guideB->setEnabled(
true);
2010 externalConnectB->setEnabled(
true);
2013 infoGroup->setEnabled(
false);
2014 driftGraphicsGroup->setEnabled(
false);
2016 guideExposure->setEnabled(
false);
2017 guideBinning->setEnabled(
false);
2018 guideSquareSize->setEnabled(
false);
2020 updateGuideParams();
2025 if (m_GuiderInstance !=
nullptr)
2028 connect(m_GuiderInstance, &Ekos::GuideInterface::newLog,
this, &Ekos::Guide::appendLogText);
2029 connect(m_GuiderInstance, &Ekos::GuideInterface::newStatus,
this, &Ekos::Guide::setStatus);
2030 connect(m_GuiderInstance, &Ekos::GuideInterface::newStarPosition,
this, &Ekos::Guide::setStarPosition);
2031 connect(m_GuiderInstance, &Ekos::GuideInterface::guideStats,
this, &Ekos::Guide::guideStats);
2033 connect(m_GuiderInstance, &Ekos::GuideInterface::newAxisDelta,
this, &Ekos::Guide::setAxisDelta);
2034 connect(m_GuiderInstance, &Ekos::GuideInterface::newAxisPulse,
this, &Ekos::Guide::setAxisPulse);
2035 connect(m_GuiderInstance, &Ekos::GuideInterface::newAxisSigma,
this, &Ekos::Guide::setAxisSigma);
2036 connect(m_GuiderInstance, &Ekos::GuideInterface::newSNR,
this, &Ekos::Guide::setSNR);
2037 connect(m_GuiderInstance, &Ekos::GuideInterface::guideInfo,
this, &Ekos::Guide::guideInfo);
2038 connect(m_GuiderInstance, &Ekos::GuideInterface::abortExposure,
this, &Ekos::Guide::abortExposure);
2040 driftGraph->connectGuider(m_GuiderInstance);
2041 targetPlot->connectGuider(m_GuiderInstance);
2043 connect(m_GuiderInstance, &Ekos::GuideInterface::calibrationUpdate,
this, &Ekos::Guide::calibrationUpdate);
2045 connect(m_GuiderInstance, &Ekos::GuideInterface::guideEquipmentUpdated,
this, &Ekos::Guide::configurePHD2Camera);
2048 externalConnectB->setEnabled(
false);
2049 externalDisconnectB->setEnabled(
false);
2051 if (m_GuiderInstance !=
nullptr && guiderType != GUIDE_INTERNAL)
2053 externalConnectB->setEnabled(!m_GuiderInstance->isConnected());
2054 externalDisconnectB->setEnabled(m_GuiderInstance->isConnected());
2057 if (m_GuiderInstance !=
nullptr)
2058 m_GuiderInstance->Connect();
2063void Guide::guideInfo(
const QString &info)
2065 if (info.size() == 0)
2067 guideInfoLabel->setVisible(
false);
2068 guideInfoText->setVisible(
false);
2071 guideInfoLabel->setVisible(
true);
2072 guideInfoLabel->setText(
"Detections");
2073 guideInfoText->setVisible(
true);
2074 guideInfoText->setText(info);
2077void Guide::updateTrackingBoxSize(
int currentIndex)
2079 if (currentIndex >= 0)
2081 if (guiderType == GUIDE_INTERNAL)
2082 dynamic_cast<InternalGuider *
>(m_GuiderInstance)->setGuideBoxSize(guideSquareSize->currentText().toInt());
2084 syncTrackingBoxPosition();
2088void Guide::onThresholdChanged(
int index)
2092 case GUIDE_INTERNAL:
2093 dynamic_cast<InternalGuider *
>(m_GuiderInstance)->setSquareAlgorithm(index);
2101void Guide::onEnableDirRA()
2104 if (Options::gPGEnabled())
2105 m_GuiderInstance->resetGPG();
2108void Guide::onEnableDirDEC()
2110 onControlDirectionChanged();
2113void Guide::onControlDirectionChanged()
2115 if(guiderType == GUIDE_PHD2)
2116 phd2Guider -> requestSetDEGuideMode(dECGuideEnabled->isChecked(), northDECGuideEnabled->isChecked(),
2117 southDECGuideEnabled->isChecked());
2120void Guide::updateDirectionsFromPHD2(
const QString &mode)
2129 dECGuideEnabled->setChecked(
true);
2130 northDECGuideEnabled->setChecked(
true);
2131 southDECGuideEnabled->setChecked(
true);
2133 else if(mode ==
"North")
2135 dECGuideEnabled->setChecked(
true);
2136 northDECGuideEnabled->setChecked(
true);
2137 southDECGuideEnabled->setChecked(
false);
2139 else if(mode ==
"South")
2141 dECGuideEnabled->setChecked(
true);
2142 northDECGuideEnabled->setChecked(
false);
2143 southDECGuideEnabled->setChecked(
true);
2147 dECGuideEnabled->setChecked(
false);
2148 northDECGuideEnabled->setChecked(
true);
2149 southDECGuideEnabled->setChecked(
true);
2161 setStarPosition(newStarPosition,
true);
2163 if(guiderType == GUIDE_PHD2)
2166 if(!m_ImageData.
isNull())
2168 if(m_ImageData->width() > 50)
2169 phd2Guider->setLockPosition(starCenter.
x(), starCenter.
y());
2173 if (operationStack.isEmpty() ==
false)
2174 executeOperationStack();
2177void Guide::setAxisDelta(
double ra,
double de)
2187 int currentNumPoints = driftGraph->graph(GuideGraph::G_RA)->dataCount();
2188 guideSlider->setMaximum(currentNumPoints);
2191 guideSlider->setValue(currentNumPoints);
2196 emit newAxisDelta(ra, de);
2199void Guide::calibrationUpdate(GuideInterface::CalibrationUpdateType type,
const QString &message,
2200 double dx,
double dy)
2204 case GuideInterface::RA_OUT:
2205 calibrationPlot->graph(GuideGraph::G_RA)->addData(dx, dy);
2207 case GuideInterface::RA_IN:
2208 calibrationPlot->graph(GuideGraph::G_DEC)->addData(dx, dy);
2210 case GuideInterface::BACKLASH:
2211 calibrationPlot->graph(GuideGraph::G_RA_HIGHLIGHT)->addData(dx, dy);
2213 case GuideInterface::DEC_OUT:
2214 calibrationPlot->graph(GuideGraph::G_DEC_HIGHLIGHT)->addData(dx, dy);
2216 case GuideInterface::DEC_IN:
2217 calibrationPlot->graph(GuideGraph::G_RA_PULSE)->addData(dx, dy);
2219 case GuideInterface::CALIBRATION_MESSAGE_ONLY:
2223 calibrationPlot->replot();
2226void Guide::setAxisSigma(
double ra,
double de)
2230 const double total = std::hypot(ra, de);
2233 emit newAxisSigma(ra, de);
2240 delta << l_DeltaRA->text().toDouble() << l_DeltaDEC->text().toDouble();
2249 sigma << l_ErrRA->text().toDouble() << l_ErrDEC->text().toDouble();
2254void Guide::setAxisPulse(
double ra,
double de)
2260void Guide::setSNR(
double snr)
2265void Guide::buildOperationStack(GuideState operation)
2267 operationStack.clear();
2272 if (guideDarkFrame->isChecked())
2273 operationStack.
push(GUIDE_DARK);
2275 operationStack.
push(GUIDE_CAPTURE);
2276 operationStack.
push(GUIDE_SUBFRAME);
2279 case GUIDE_CALIBRATING:
2280 operationStack.
push(GUIDE_CALIBRATING);
2281 if (guiderType == GUIDE_INTERNAL)
2283 if (guideDarkFrame->isChecked())
2284 operationStack.
push(GUIDE_DARK);
2287 if (guideAutoStar->isChecked() ||
2289 internalGuider->SEPMultiStarEnabled())
2293 if (subFramed ==
false && guideSubframe->isChecked())
2294 operationStack.
push(GUIDE_CAPTURE);
2296 operationStack.
push(GUIDE_SUBFRAME);
2297 operationStack.
push(GUIDE_STAR_SELECT);
2300 operationStack.
push(GUIDE_CAPTURE);
2303 if (subFramed ==
true && guideSubframe->isChecked() ==
false)
2304 operationStack.
push(GUIDE_SUBFRAME);
2310 if (subFramed ==
false && guideSubframe->isChecked())
2311 operationStack.
push(GUIDE_CAPTURE);
2314 operationStack.
push(GUIDE_SUBFRAME);
2317 operationStack.
push(GUIDE_CAPTURE);
2328bool Guide::executeOperationStack()
2330 if (operationStack.isEmpty())
2333 GuideState nextOperation = operationStack.
pop();
2336 bool actionRequired =
false;
2338 switch (nextOperation)
2340 case GUIDE_SUBFRAME:
2341 actionRequired = executeOneOperation(nextOperation);
2345 actionRequired = executeOneOperation(nextOperation);
2349 actionRequired = captureOneFrame();
2352 case GUIDE_STAR_SELECT:
2353 actionRequired = executeOneOperation(nextOperation);
2356 case GUIDE_CALIBRATING:
2357 if (guiderType == GUIDE_INTERNAL)
2359 m_GuiderInstance->setStarPosition(starCenter);
2362 if (m_Mount && m_Mount->canControlTrack() && m_Mount->isTracking() ==
false)
2363 m_Mount->setTrackEnabled(
true);
2366 if (m_GuiderInstance->calibrate())
2368 if (guiderType == GUIDE_INTERNAL)
2374 emit newStatus(GUIDE_CALIBRATION_ERROR);
2375 m_State = GUIDE_IDLE;
2376 appendLogText(
i18n(
"Calibration failed to start."));
2390 return executeOperationStack();
2393bool Guide::executeOneOperation(GuideState operation)
2395 bool actionRequired =
false;
2397 if (m_Camera ==
nullptr)
2398 return actionRequired;
2400 ISD::CameraChip *targetChip = m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
2401 if (targetChip ==
nullptr)
2404 int subBinX, subBinY;
2405 targetChip->getBinning(&subBinX, &subBinY);
2409 case GUIDE_SUBFRAME:
2412 if ((guiderType == GUIDE_INTERNAL) && internalGuider->SEPMultiStarEnabled())
2415 if (subFramed ==
false && guideSubframe->isChecked() ==
true && targetChip->canSubframe())
2417 int minX, maxX, minY, maxY, minW, maxW, minH, maxH;
2418 targetChip->getFrameMinMax(&minX, &maxX, &minY, &maxY, &minW, &maxW, &minH, &maxH);
2420 int offset = guideSquareSize->currentText().toInt() / subBinX;
2422 int x = starCenter.
x();
2423 int y = starCenter.
y();
2425 x = (
x - offset * 2) * subBinX;
2426 y = (
y - offset * 2) * subBinY;
2427 int w = offset * 4 * subBinX;
2428 int h = offset * 4 * subBinY;
2439 targetChip->setFrame(
x,
y, w, h);
2442 QVariantMap settings = frameSettings[targetChip];
2447 settings[
"binx"] = subBinX;
2448 settings[
"biny"] = subBinY;
2450 frameSettings[targetChip] = settings;
2452 starCenter.
setX(w / (2 * subBinX));
2453 starCenter.
setY(h / (2 * subBinX));
2459 else if (subFramed &&
2460 (guideSubframe->isChecked() ==
false ||
2461 m_State == GUIDE_REACQUIRE))
2463 targetChip->resetFrame();
2466 targetChip->getFrame(&
x, &
y, &w, &h);
2468 QVariantMap settings;
2473 settings[
"binx"] = subBinX;
2474 settings[
"biny"] = subBinY;
2475 frameSettings[targetChip] = settings;
2479 starCenter.
setX(w / (2 * subBinX));
2480 starCenter.
setY(h / (2 * subBinX));
2491 if (m_ImageData && guideDarkFrame->isChecked())
2493 QVariantMap settings = frameSettings[targetChip];
2494 uint16_t offsetX = 0;
2495 uint16_t offsetY = 0;
2497 if (settings[
"x"].
isValid() &&
2502 offsetX = settings[
"x"].toInt() / settings[
"binx"].toInt();
2503 offsetY = settings[
"y"].toInt() / settings[
"biny"].toInt();
2506 actionRequired =
true;
2507 targetChip->setCaptureFilter(FITS_NONE);
2508 m_DarkProcessor->denoise(OpticalTrainManager::Instance()->
id(opticalTrainCombo->currentText()),
2509 targetChip, m_ImageData, guideExposure->value(), offsetX, offsetY);
2514 case GUIDE_STAR_SELECT:
2516 m_State = GUIDE_STAR_SELECT;
2517 emit newStatus(m_State);
2519 if (guideAutoStar->isChecked() ||
2521 ((guiderType == GUIDE_INTERNAL) &&
2522 internalGuider->SEPMultiStarEnabled()))
2524 bool autoStarCaptured = internalGuider->selectAutoStar();
2525 if (autoStarCaptured)
2527 appendLogText(
i18n(
"Auto star selected."));
2531 appendLogText(
i18n(
"Failed to select an auto star."));
2532 actionRequired =
true;
2533 m_State = GUIDE_CALIBRATION_ERROR;
2534 emit newStatus(m_State);
2540 appendLogText(
i18n(
"Select a guide star to calibrate."));
2541 actionRequired =
true;
2550 return actionRequired;
2553void Guide::processGuideOptions()
2555 if (Options::guiderType() != guiderType)
2557 guiderType =
static_cast<GuiderType
>(Options::guiderType());
2562void Guide::showFITSViewer()
2564 static int lastFVTabID = -1;
2571 fv->loadData(m_ImageData, url, &lastFVTabID);
2572 connect(fv.
get(), &FITSViewer::terminated,
this, [
this]()
2577 else if (fv->updateData(m_ImageData, url, lastFVTabID, &lastFVTabID) ==
false)
2578 fv->loadData(m_ImageData, url, &lastFVTabID);
2584void Guide::setExternalGuiderBLOBEnabled(
bool enable)
2587 if (guiderType == GUIDE_INTERNAL)
2593 m_Camera->setBLOBEnabled(enable);
2595 if(m_Camera->isBLOBEnabled())
2597 checkUseGuideHead();
2599 auto targetChip = m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
2601 targetChip->setCaptureMode(FITS_GUIDE);
2610 nonGuidedDitherRaOffsetMsec = 0;
2611 nonGuidedDitherDecOffsetMsec = 0;
2612 qCDebug(KSTARS_EKOS_GUIDE) <<
"Reset non guiding dithering position";
2615 if (!isNonGuidedDitherInitialized)
2617 auto seed = std::chrono::system_clock::now().time_since_epoch().count();
2618 nonGuidedPulseGenerator.seed(seed);
2619 isNonGuidedDitherInitialized =
true;
2620 qCDebug(KSTARS_EKOS_GUIDE) <<
"Initialize non guiding dithering random generator";
2624void Guide::nonGuidedDither()
2626 double ditherPulse = Options::ditherNoGuidingPulse();
2629 std::uniform_int_distribution<int> newPos(-ditherPulse, +ditherPulse);
2634 const int newRaOffsetMsec = newPos(nonGuidedPulseGenerator);
2635 const int raPulse = nonGuidedDitherRaOffsetMsec - newRaOffsetMsec;
2636 nonGuidedDitherRaOffsetMsec = newRaOffsetMsec;
2637 const int raMsec = std::abs(raPulse);
2638 const int raPolarity = (raPulse >= 0 ? 1 : -1);
2641 const int newDecOffsetMsec = newPos(nonGuidedPulseGenerator);
2642 const int decPulse = nonGuidedDitherDecOffsetMsec - newDecOffsetMsec;
2643 nonGuidedDitherDecOffsetMsec = newDecOffsetMsec;
2644 const int decMsec = std::abs(decPulse);
2645 const int decPolarity = (decPulse >= 0 ? 1 : -1);
2647 qCInfo(KSTARS_EKOS_GUIDE) <<
"Starting non-guiding dither...";
2648 qCDebug(KSTARS_EKOS_GUIDE) <<
"dither ra_msec:" << raMsec <<
"ra_polarity:" << raPolarity <<
"de_msec:" << decMsec <<
2649 "de_polarity:" << decPolarity;
2651 bool rc = sendMultiPulse(raPolarity > 0 ? RA_INC_DIR : RA_DEC_DIR, raMsec, decPolarity > 0 ? DEC_INC_DIR : DEC_DEC_DIR,
2652 decMsec, DontCaptureAfterPulses);
2656 qCInfo(KSTARS_EKOS_GUIDE) <<
"Non-guiding dither successful.";
2657 QTimer::singleShot( (raMsec > decMsec ? raMsec : decMsec) + Options::ditherSettle() * 1000 + 100,
this, [
this]()
2659 emit newStatus(GUIDE_DITHERING_SUCCESS);
2660 m_State = GUIDE_IDLE;
2665 qCWarning(KSTARS_EKOS_GUIDE) <<
"Non-guiding dither failed.";
2666 emit newStatus(GUIDE_DITHERING_ERROR);
2667 m_State = GUIDE_IDLE;
2671void Guide::handleManualDither()
2673 ISD::CameraChip *targetChip = m_Camera->getChip(useGuideHead ? ISD::CameraChip::GUIDE_CCD : ISD::CameraChip::PRIMARY_CCD);
2674 if (targetChip ==
nullptr)
2677 Ui::ManualDither ditherDialog;
2679 ditherDialog.setupUi(&container);
2681 if (guiderType != GUIDE_INTERNAL)
2683 ditherDialog.coordinatesR->setEnabled(
false);
2684 ditherDialog.x->setEnabled(
false);
2685 ditherDialog.y->setEnabled(
false);
2688 int minX, maxX, minY, maxY, minW, maxW, minH, maxH;
2689 targetChip->getFrameMinMax(&minX, &maxX, &minY, &maxY, &minW, &maxW, &minH, &maxH);
2691 ditherDialog.x->setMinimum(minX);
2692 ditherDialog.x->setMaximum(maxX);
2693 ditherDialog.y->setMinimum(minY);
2694 ditherDialog.y->setMaximum(maxY);
2696 ditherDialog.x->setValue(starCenter.
x());
2697 ditherDialog.y->setValue(starCenter.
y());
2701 if (ditherDialog.magnitudeR->isChecked())
2702 m_GuiderInstance->dither(ditherDialog.magnitude->value());
2705 InternalGuider *
const ig =
dynamic_cast<InternalGuider *
>(m_GuiderInstance);
2707 ig->ditherXY(ditherDialog.x->value(), ditherDialog.y->value());
2714 setStatus(GUIDE_IDLE);
2715 return m_GuiderInstance->Connect();
2720 return m_GuiderInstance->Disconnect();
2723void Guide::initPlots()
2726 initCalibrationPlot();
2734void Guide::initDriftGraph()
2744 driftGraph->setCorrectionGraphScale(correctionSlider->value());
2752 correctionSlider->setValue(scale);
2755void Guide::initCalibrationPlot()
2758 calibrationPlot->setSelectionTolerance(10);
2769 calibrationPlot->xAxis->setTickLabelColor(
Qt::white);
2770 calibrationPlot->yAxis->setTickLabelColor(
Qt::white);
2772 calibrationPlot->xAxis->setLabelColor(
Qt::white);
2773 calibrationPlot->yAxis->setLabelColor(
Qt::white);
2775 calibrationPlot->xAxis->setLabelFont(
QFont(
font().family(), 10));
2776 calibrationPlot->yAxis->setLabelFont(
QFont(
font().family(), 10));
2777 calibrationPlot->xAxis->setTickLabelFont(
QFont(
font().family(), 9));
2778 calibrationPlot->yAxis->setTickLabelFont(
QFont(
font().family(), 9));
2780 calibrationPlot->xAxis->setLabelPadding(2);
2781 calibrationPlot->yAxis->setLabelPadding(2);
2787 calibrationPlot->xAxis->grid()->setZeroLinePen(
QPen(
Qt::gray));
2788 calibrationPlot->yAxis->grid()->setZeroLinePen(
QPen(
Qt::gray));
2790 calibrationPlot->xAxis->setLabel(
i18n(
"x (pixels)"));
2791 calibrationPlot->yAxis->setLabel(
i18n(
"y (pixels)"));
2793 calibrationPlot->xAxis->setRange(-20, 20);
2794 calibrationPlot->yAxis->setRange(-20, 20);
2799 calibrationPlot->addGraph();
2802 QPen(KStarsData::Instance()->colorScheme()->colorNamed(
"RAGuideError"), 2),
QBrush(), 6));
2803 calibrationPlot->graph(GuideGraph::G_RA)->setName(
"RA out");
2805 calibrationPlot->addGraph();
2809 calibrationPlot->graph(GuideGraph::G_DEC)->setName(
"RA in");
2811 calibrationPlot->addGraph();
2812 calibrationPlot->graph(GuideGraph::G_RA_HIGHLIGHT)->setLineStyle(
QCPGraph::lsNone);
2816 calibrationPlot->graph(GuideGraph::G_RA_HIGHLIGHT)->setName(
"Backlash");
2818 calibrationPlot->addGraph();
2819 calibrationPlot->graph(GuideGraph::G_DEC_HIGHLIGHT)->setLineStyle(
QCPGraph::lsNone);
2821 QPen(KStarsData::Instance()->colorScheme()->colorNamed(
"DEGuideError"), 2),
QBrush(), 6));
2822 calibrationPlot->graph(GuideGraph::G_DEC_HIGHLIGHT)->setName(
"DEC out");
2824 calibrationPlot->addGraph();
2825 calibrationPlot->graph(GuideGraph::G_RA_PULSE)->setLineStyle(
QCPGraph::lsNone);
2829 calibrationPlot->graph(GuideGraph::G_RA_PULSE)->setName(
"DEC in");
2840 calibrationPlot->resize(190, 190);
2841 calibrationPlot->replot();
2844void Guide::initView()
2846 guideStateWidget =
new GuideStateWidget();
2847 guideInfoLayout->insertWidget(-1, guideStateWidget);
2851 m_GuideView->setBaseSize(guideWidget->size());
2852 m_GuideView->createFloatingToolBar();
2855 guideWidget->setLayout(vlayout);
2857 guideInfoLabel->setVisible(
false);
2858 guideInfoText->setVisible(
false);
2861void Guide::initConnections()
2874 &Ekos::Guide::updateTrackingBoxSize);
2879 if(guiderType != GUIDE_PHD2)
2884 &Ekos::Guide::updateCCDBin);
2899 m_State = GUIDE_CAPTURE;
2900 emit newStatus(m_State);
2902 if(guiderType == GUIDE_PHD2)
2904 configurePHD2Camera();
2905 if(phd2Guider->isCurrentCameraNotInEkos())
2907 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."));
2908 else if(guideSubframe->isChecked())
2911 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"));
2912 guideSubframe->setChecked(
false);
2914 phd2Guider->captureSingleFrame();
2916 else if (guiderType == GUIDE_INTERNAL)
2937 m_GuiderInstance->Connect();
2942 m_GuiderInstance->Disconnect();
2951 &Ekos::Guide::buildTarget);
2956 driftGraph->toggleShowPlot(GuideGraph::G_RA, isChecked);
2960 driftGraph->toggleShowPlot(GuideGraph::G_DEC, isChecked);
2964 driftGraph->toggleShowPlot(GuideGraph::G_RA_PULSE, isChecked);
2968 driftGraph->toggleShowPlot(GuideGraph::G_DEC_PULSE, isChecked);
2972 driftGraph->toggleShowPlot(GuideGraph::G_SNR, isChecked);
2976 driftGraph->toggleShowPlot(GuideGraph::G_RMS, isChecked);
2982 connect(
this, &Ekos::Guide::newStatus, guideStateWidget, &Ekos::GuideStateWidget::updateGuideStatus);
2987 auto name = device->getDeviceName();
2989 device->disconnect(
this);
2992 if (m_Mount && m_Mount->getDeviceName() == name)
3000 if (m_Camera && m_Camera->getDeviceName() == name)
3008 if (m_Guider && m_Guider->getDeviceName() == name)
3016 if (m_AO && m_AO->getDeviceName() == name)
3025 m_State = GUIDE_LOOPING;
3026 emit newStatus(m_State);
3028 if(guiderType == GUIDE_PHD2)
3030 configurePHD2Camera();
3031 if(phd2Guider->isCurrentCameraNotInEkos())
3033 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."));
3034 else if(guideSubframe->isChecked())
3037 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"));
3038 guideSubframe->setChecked(
false);
3041 stopB->setEnabled(
true);
3043 else if (guiderType == GUIDE_INTERNAL)
3050QVariantMap Guide::getAllSettings()
const
3052 QVariantMap settings;
3056 settings.insert(oneWidget->objectName(), oneWidget->currentText());
3060 settings.insert(oneWidget->objectName(), oneWidget->value());
3064 settings.insert(oneWidget->objectName(), oneWidget->value());
3068 settings.insert(oneWidget->objectName(), oneWidget->isChecked());
3076void Guide::setAllSettings(
const QVariantMap &settings)
3080 disconnectSettings();
3082 for (
auto &name : settings.keys())
3088 syncControl(settings, name, comboBox);
3096 syncControl(settings, name, doubleSpinBox);
3104 syncControl(settings, name, spinBox);
3112 syncControl(settings, name, checkbox);
3118 for (
auto &key : settings.keys())
3120 auto value = settings[key];
3122 Options::self()->setProperty(key.toLatin1(), value);
3124 m_Settings[key] = value;
3125 m_GlobalSettings[key] = value;
3128 emit settingsUpdated(getAllSettings());
3131 OpticalTrainSettings::Instance()->setOpticalTrainID(OpticalTrainManager::Instance()->
id(opticalTrainCombo->currentText()));
3132 OpticalTrainSettings::Instance()->setOneSetting(OpticalTrainSettings::Guide, m_Settings);
3141bool Guide::syncControl(
const QVariantMap &settings,
const QString &key,
QWidget * widget)
3152 const int value = settings[key].toInt(&ok);
3161 const double value = settings[key].toDouble(&ok);
3170 const bool value = settings[key].toBool();
3177 const bool value = settings[key].toBool();
3179 pRadioButton->
click();
3185 const QString value = settings[key].toString();
3193void Guide::setupOpticalTrainManager()
3195 connect(OpticalTrainManager::Instance(), &OpticalTrainManager::updated,
this, &Guide::refreshOpticalTrain);
3198 OpticalTrainManager::Instance()->openEditor(opticalTrainCombo->currentText());
3202 if (guiderType == GUIDE_PHD2 && m_GuiderInstance->isConnected())
3204 appendLogText(
i18n(
"Cannot change active optical train while PHD2 is connected"));
3208 ProfileSettings::Instance()->setOneSetting(ProfileSettings::GuideOpticalTrain,
3209 OpticalTrainManager::Instance()->
id(opticalTrainCombo->itemText(index)));
3210 refreshOpticalTrain();
3211 emit trainChanged();
3215void Guide::refreshOpticalTrain()
3217 opticalTrainCombo->blockSignals(
true);
3218 opticalTrainCombo->clear();
3219 opticalTrainCombo->addItems(OpticalTrainManager::Instance()->getTrainNames());
3220 trainB->setEnabled(
true);
3222 QVariant trainID = ProfileSettings::Instance()->getOneSetting(ProfileSettings::GuideOpticalTrain);
3226 auto id = trainID.
toUInt();
3229 if (OpticalTrainManager::Instance()->exists(
id) ==
false)
3231 qCWarning(KSTARS_EKOS_GUIDE) <<
"Optical train doesn't exist for id" << id;
3232 id = OpticalTrainManager::Instance()->id(opticalTrainCombo->itemText(0));
3235 auto name = OpticalTrainManager::Instance()->name(
id);
3237 opticalTrainCombo->setCurrentText(name);
3239 auto scope = OpticalTrainManager::Instance()->getScope(name);
3240 m_FocalLength = scope[
"focal_length"].
toDouble(-1);
3241 m_Aperture = scope[
"aperture"].toDouble(-1);
3242 m_FocalRatio = scope[
"focal_ratio"].toDouble(-1);
3243 m_Reducer = OpticalTrainManager::Instance()->getReducer(name);
3246 if (m_Aperture < 0 && m_FocalRatio > 0)
3247 m_Aperture = m_FocalLength / m_FocalRatio;
3249 auto mount = OpticalTrainManager::Instance()->getMount(name);
3252 auto camera = OpticalTrainManager::Instance()->getCamera(name);
3255 if (guiderType == GUIDE_INTERNAL)
3258 camera->setScopeInfo(m_FocalLength * m_Reducer, m_Aperture);
3259 opticalTrainCombo->setToolTip(
QString(
"%1 @ %2").arg(camera->getDeviceName(), scope[
"name"].toString()));
3263 syncTelescopeInfo();
3265 auto guider = OpticalTrainManager::Instance()->getGuider(name);
3268 auto ao = OpticalTrainManager::Instance()->getAdaptiveOptics(name);
3272 OpticalTrainSettings::Instance()->setOpticalTrainID(
id);
3273 auto settings = OpticalTrainSettings::Instance()->getOneSetting(OpticalTrainSettings::Guide);
3274 if (settings.isValid())
3276 auto map = settings.toJsonObject().toVariantMap();
3277 if (map != m_Settings)
3280 setAllSettings(map);
3284 m_Settings = m_GlobalSettings;
3287 opticalTrainCombo->blockSignals(
false);
3290void Guide::loadGlobalSettings()
3295 QVariantMap settings;
3299 if (oneWidget->objectName() ==
"opticalTrainCombo")
3302 key = oneWidget->objectName();
3303 value = Options::self()->property(key.
toLatin1());
3304 if (value.
isValid() && oneWidget->count() > 0)
3306 oneWidget->setCurrentText(value.
toString());
3307 settings[key] = value;
3314 key = oneWidget->objectName();
3315 value = Options::self()->property(key.
toLatin1());
3318 oneWidget->setValue(value.
toDouble());
3319 settings[key] = value;
3326 key = oneWidget->objectName();
3327 value = Options::self()->property(key.
toLatin1());
3330 oneWidget->setValue(value.
toInt());
3331 settings[key] = value;
3338 key = oneWidget->objectName();
3339 value = Options::self()->property(key.
toLatin1());
3342 oneWidget->setChecked(value.
toBool());
3343 settings[key] = value;
3347 m_GlobalSettings = m_Settings = settings;
3350void Guide::connectSettings()
3376void Guide::disconnectSettings()
3403 Options::self()->setProperty(key.
toLatin1(), value);
3404 m_Settings[key] = value;
3405 m_GlobalSettings[key] = value;
3407 m_DebounceTimer.
start();
3413void Guide::settleSettings()
3415 Options::self()->save();
3416 emit settingsUpdated(getAllSettings());
3418 OpticalTrainSettings::Instance()->setOpticalTrainID(OpticalTrainManager::Instance()->
id(opticalTrainCombo->currentText()));
3419 OpticalTrainSettings::Instance()->setOneSetting(OpticalTrainSettings::Guide, m_Settings);
3422void Guide::syncSettings()
3436 value = dsb->
value();
3442 value = sb->
value();
3459 m_Settings.remove(key);
Q_SCRIPTABLE bool connectGuider()
DBUS interface function.
bool setMount(ISD::Mount *device)
Add new Mount.
Q_SCRIPTABLE bool calibrate()
DBUS interface function.
void updateProperty(INDI::Property prop)
processCCDNumber Process number properties arriving from CCD.
Q_SCRIPTABLE Q_NOREPLY void setAutoStarEnabled(bool enable)
DBUS interface function.
Q_SCRIPTABLE Q_NOREPLY void setDarkFrameEnabled(bool enable)
DBUS interface function.
void processData(const QSharedPointer< FITSData > &data)
newFITS is called by the INDI framework whenever there is a new BLOB arriving
Q_SCRIPTABLE bool resume()
DBUS interface function.
void setTrackingStar(int x, int y)
setTrackingStar Gets called when the user select a star in the guide frame
Q_SCRIPTABLE bool setGuiderType(int type)
DBUS interface function.
void checkExposureValue(ISD::CameraChip *targetChip, double exposure, IPState expState)
checkExposureValue This function is called by the INDI framework whenever there is a new exposure val...
void updateSetting(const QString &key, const QVariant &value)
updateSetting Update per-train and global setting
bool setGuider(ISD::Guider *device)
Add new Guider.
Q_SCRIPTABLE bool suspend()
DBUS interface function.
Q_SCRIPTABLE bool dither()
DBUS interface function.
void resetNonGuidedDither()
Reset non guided dithering properties and initialize the random generator seed if not already done.
Q_SCRIPTABLE Q_NOREPLY void setExposure(double value)
DBUS interface function.
Q_SCRIPTABLE Q_NOREPLY void setSubFrameEnabled(bool enable)
DBUS interface function.
void checkCamera()
checkCamera Check all CCD parameters and ensure all variables are updated to reflect the selected CCD
Q_SCRIPTABLE bool capture()
DBUS interface function.
Q_SCRIPTABLE Q_NOREPLY void clearCalibration()
DBUS interface function.
Q_SCRIPTABLE bool abort()
DBUS interface function.
Q_SCRIPTABLE bool disconnectGuider()
DBUS interface function.
bool setAdaptiveOptics(ISD::AdaptiveOptics *device)
Add new Adaptive Optics.
void setDECSwap(bool enable)
setDECSwap Change ST4 declination pulse direction.
Q_SCRIPTABLE void clearLog()
clearLog As the name suggests
Q_SCRIPTABLE Q_NOREPLY void loop()
DBUS interface function.
Q_SCRIPTABLE bool guide()
DBUS interface function.
bool setCamera(ISD::Camera *device)
Add new Camera.
Uses external LinGuider for guiding.
Uses external PHD2 for guiding.
The main change relative to fitsview is to add the capability of displaying the 'neighbor guide stars...
AdaptiveOptics class handles control of INDI AdaptiveOptics devices.
CameraChip class controls a particular chip in camera.
Camera class controls an INDI Camera device.
device handle controlling Mounts.
KPageWidgetItem * addPage(QWidget *page, const QString &itemName, const QString &pixmapName=QString(), const QString &header=QString(), bool manage=true)
void setIcon(const QIcon &icon)
static KStars * Instance()
void colorSchemeChanged()
DBUS interface notification.
Manages a single axis inside a QCustomPlot.
void rangeChanged(const QCPRange &newRange)
Q_SLOT void setRange(const QCPRange &range)
@ lsNone
data points are not connected with any lines (e.g.
void setType(PositionType type)
void setCoords(double key, double value)
@ ptAxisRectRatio
Static positioning given by a fraction of the axis rect size (see setAxisRect).
@ ptPlotCoords
Dynamic positioning at a plot coordinate defined by two axes (see setAxes).
void setBrush(const QBrush &brush)
void setText(const QString &text)
void setPositionAlignment(Qt::Alignment alignment)
void setFont(const QFont &font)
void setPen(const QPen &pen)
void setColor(const QColor &color)
Represents the range an axis is encompassing.
Represents the visual appearance of scatter points.
@ ssDisc
\enumimage{ssDisc.png} a circle which is filled with the pen's color (not the brush as with ssCircle)
@ ssPlus
\enumimage{ssPlus.png} a plus
@ ssCircle
\enumimage{ssCircle.png} a circle
void mouseMove(QMouseEvent *event)
void mousePress(QMouseEvent *event)
The QProgressIndicator class lets an application display a progress indicator to show that a long tas...
void stopAnimation()
Stops the spin animation.
void startAnimation()
Starts the spin animation.
bool isAnimated() const
Returns a Boolean value indicating whether the component is currently animated.
The sky coordinates of a point in the sky.
An angle, stored as degrees, but expressible in many ways.
QString i18np(const char *singular, const char *plural, const TYPE &arg...)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
AKONADI_CALENDAR_EXPORT KCalendarCore::Event::Ptr event(const Akonadi::Item &item)
char * toString(const EngineQuery &query)
Ekos is an advanced Astrophotography tool for Linux.
CaptureState
Capture states.
KIOCORE_EXPORT SimpleJob * mount(bool ro, const QByteArray &fstype, const QString &dev, const QString &point, JobFlags flags=DefaultFlags)
bool isValid(QStringView ifopt)
QString name(StandardAction id)
@ iRangeDrag
0x001 Axis ranges are draggable (see QCPAxisRect::setRangeDrag, QCPAxisRect::setRangeDragAxes)
@ iRangeZoom
0x002 Axis ranges are zoomable with the mouse wheel (see QCPAxisRect::setRangeZoom,...
void sliderMoved(int value)
void activated(int index)
void currentIndexChanged(int index)
void setCurrentText(const QString &text)
bool registerObject(const QString &path, QObject *object, RegisterOptions options)
QDBusConnection sessionBus()
void setValue(double val)
void valueChanged(double d)
qint64 elapsed() const const
QIcon fromTheme(const QString &name)
iterator insert(const_iterator before, parameter_type value)
bool contains(const Key &key) const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool disconnect(const QMetaObject::Connection &connection)
T findChild(const QString &name, Qt::FindChildOptions options) const const
QList< T > findChildren(Qt::FindChildOptions options) const const
T qobject_cast(QObject *object)
QObject * sender() const const
bool isNull() const const
void splitterMoved(int pos, int index)
QString arg(Args &&... args) const const
QString number(double n, char format, int precision)
double toDouble(bool *ok) const const
QByteArray toLatin1() const const
QFuture< void > map(Iterator begin, Iterator end, MapFunctor &&function)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
void setInterval(int msec)
bool isActive() const const
QUrl fromLocalFile(const QString &localFile)
bool isValid() const const
bool toBool() const const
double toDouble(bool *ok) const const
int toInt(bool *ok) const const
QString toString() const const
uint toUInt(bool *ok) const const
bool isNull() const const