From cb30c61cf38c11c9acffa036034d233ea56af0b5 Mon Sep 17 00:00:00 2001 From: gehelem Date: Sat, 18 Oct 2025 14:41:09 +0200 Subject: [PATCH 01/11] sequencer can ask to guider to stop during focus --- src/modules/guider/guider.cpp | 22 +++++++++++++++++++++- src/modules/sequencer/sequencer.cpp | 18 ++++++++++++++++++ src/modules/sequencer/sequencer.json | 19 +++++++++++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) diff --git a/src/modules/guider/guider.cpp b/src/modules/guider/guider.cpp index 0517fef..5163620 100644 --- a/src/modules/guider/guider.cpp +++ b/src/modules/guider/guider.cpp @@ -38,10 +38,30 @@ Guider::~Guider() void Guider::OnMyExternalEvent(const QString &eventType, const QString &eventModule, const QString &eventKey, const QVariantMap &eventData) { - Q_UNUSED(eventType); Q_UNUSED(eventKey); //BOOST_LOG_TRIVIAL(debug) << "OnMyExternalEvent - recv : " << getName().toStdString() << "-" << eventType.toStdString() << "-" << eventKey.toStdString(); + + // Handle suspend/resume guiding events from sequencer + if (eventType == "suspendguiding" && getModuleName() == eventModule) + { + sendMessage("Guiding suspended by external request (focus in progress)"); + // Stop the guiding state machine + _SMGuide.stop(); + return; + } + + if (eventType == "resumeguiding" && getModuleName() == eventModule) + { + sendMessage("Resuming guiding after external suspension (focus completed)"); + // Restart the guiding state machine + disconnect(&_SMInit, &QStateMachine::finished, nullptr, nullptr); + disconnect(&_SMCalibration, &QStateMachine::finished, nullptr, nullptr); + connect(&_SMInit, &QStateMachine::finished, &_SMGuide, &QStateMachine::start); + _SMInit.start(); + return; + } + if (getModuleName() == eventModule) { foreach(const QString &keyprop, eventData.keys()) diff --git a/src/modules/sequencer/sequencer.cpp b/src/modules/sequencer/sequencer.cpp index 1e05bdf..1ce15d2 100644 --- a/src/modules/sequencer/sequencer.cpp +++ b/src/modules/sequencer/sequencer.cpp @@ -448,6 +448,15 @@ void Sequencer::requestFocus() mWaitingForFocus = true; + // Suspend guiding if option is enabled + bool suspendGuiding = getBool("parameters", "suspendguidingduringfocus"); + if (suspendGuiding) + { + QString guiderModule = getString("parameters", "guidermodule"); + sendMessage("Suspending guiding on module: " + guiderModule); + emit moduleEvent("suspendguiding", guiderModule, "", QVariantMap()); + } + // Emit custom event type "requestautofocus" that focus module will handle emit moduleEvent("requestautofocus", focusModule, "", QVariantMap()); } @@ -463,6 +472,15 @@ void Sequencer::OnFocusDone(const QString &eventType, const QString &eventModule sendMessage("Autofocus completed - resuming sequence"); mWaitingForFocus = false; + // Resume guiding if it was suspended + bool suspendGuiding = getBool("parameters", "suspendguidingduringfocus"); + if (suspendGuiding) + { + QString guiderModule = getString("parameters", "guidermodule"); + sendMessage("Resuming guiding on module: " + guiderModule); + emit moduleEvent("resumeguiding", guiderModule, "", QVariantMap()); + } + // If currentLine is -1, focus was done at sequence start, so start the first line if (currentLine == -1) { diff --git a/src/modules/sequencer/sequencer.json b/src/modules/sequencer/sequencer.json index 5d4c3d5..eab4f71 100644 --- a/src/modules/sequencer/sequencer.json +++ b/src/modules/sequencer/sequencer.json @@ -169,6 +169,25 @@ "value": "focus", "order": 2, "hint": "Name of the focus module INSTANCE to use (e.g. 'focus', 'myfocus1')" + }, + "suspendguidingduringfocus": { + "type": "bool", + "label": "Suspend guiding during focus", + "autoupdate": true, + "directedit": true, + "value": false, + "order": 3, + "hint": "Suspend guiding when autofocus is triggered and resume after focus completes" + }, + "guidermodule": { + "type": "string", + "label": "Guider module instance", + "listOfValues":"loadedModules", + "autoupdate": true, + "directedit": true, + "value": "guider", + "order": 4, + "hint": "Name of the guider module INSTANCE to use (e.g. 'guider', 'myguider1')" } } } From 9847354efde494c18785ec586d08d479ad9ede65 Mon Sep 17 00:00:00 2001 From: gehelem Date: Sat, 18 Oct 2025 14:55:34 +0200 Subject: [PATCH 02/11] Add settle time after guide resume --- src/modules/sequencer/sequencer.cpp | 40 ++++++++++++++++++++++++++++ src/modules/sequencer/sequencer.h | 3 +++ src/modules/sequencer/sequencer.json | 10 +++++++ 3 files changed, 53 insertions(+) diff --git a/src/modules/sequencer/sequencer.cpp b/src/modules/sequencer/sequencer.cpp index 1ce15d2..f3a6088 100644 --- a/src/modules/sequencer/sequencer.cpp +++ b/src/modules/sequencer/sequencer.cpp @@ -1,5 +1,6 @@ #include "sequencer.h" #include +#include #include "versionModule.cc" Sequencer *initialize(QString name, QString label, QString profile, QVariantMap availableModuleLibs) @@ -25,6 +26,11 @@ Sequencer::Sequencer(QString name, QString label, QString profile, QVariantMap a defineMeAsSequencer(); refreshFilterLov(); + // Initialize guiding settle timer + mGuidingSettleTimer = new QTimer(this); + mGuidingSettleTimer->setSingleShot(true); + connect(mGuidingSettleTimer, &QTimer::timeout, this, &Sequencer::OnGuidingSettleTimeout); + } Sequencer::~Sequencer() @@ -60,6 +66,11 @@ void Sequencer::OnMyExternalEvent(const QString &eventType, const QString &even emit Abort(); isSequenceRunning = false; mWaitingForFocus = false; + mWaitingForGuidingSettle = false; + if (mGuidingSettleTimer->isActive()) + { + mGuidingSettleTimer->stop(); + } } } if (keyprop == "devices") @@ -479,8 +490,19 @@ void Sequencer::OnFocusDone(const QString &eventType, const QString &eventModule QString guiderModule = getString("parameters", "guidermodule"); sendMessage("Resuming guiding on module: " + guiderModule); emit moduleEvent("resumeguiding", guiderModule, "", QVariantMap()); + + // Wait for guiding to settle before continuing + int settleTime = getInt("parameters", "guidingsettletime"); + if (settleTime > 0) + { + sendMessage("Waiting " + QString::number(settleTime) + " seconds for guiding to settle..."); + mWaitingForGuidingSettle = true; + mGuidingSettleTimer->start(settleTime * 1000); // Convert seconds to milliseconds + return; // OnGuidingSettleTimeout() will continue the sequence + } } + // Continue sequence immediately if no settle time needed // If currentLine is -1, focus was done at sequence start, so start the first line if (currentLine == -1) { @@ -493,3 +515,21 @@ void Sequencer::OnFocusDone(const QString &eventType, const QString &eventModule Shoot(); } } + +void Sequencer::OnGuidingSettleTimeout() +{ + sendMessage("Guiding settle time completed - continuing sequence"); + mWaitingForGuidingSettle = false; + + // Continue sequence after settle time + if (currentLine == -1) + { + sendMessage("Starting sequence"); + StartLine(); + } + else + { + // Shoot the first image of the current line + Shoot(); + } +} diff --git a/src/modules/sequencer/sequencer.h b/src/modules/sequencer/sequencer.h index 5d5754a..a819243 100644 --- a/src/modules/sequencer/sequencer.h +++ b/src/modules/sequencer/sequencer.h @@ -46,6 +46,7 @@ class MODULE_INIT Sequencer: public IndiModule const QVariantMap &eventData) override; void OnSucessSEP(); void OnFocusDone(const QString &eventType, const QString &eventModule, const QString &eventKey, const QVariantMap &eventData); + void OnGuidingSettleTimeout(); private: void newBLOB(INDI::PropertyBlob pblob); @@ -91,6 +92,8 @@ class MODULE_INIT Sequencer: public IndiModule QVariantMap mActiveSeq; bool isSequenceRunning = false; bool mWaitingForFocus = false; + bool mWaitingForGuidingSettle = false; + QTimer *mGuidingSettleTimer = nullptr; QString mObjectName = "default"; QString mDate; diff --git a/src/modules/sequencer/sequencer.json b/src/modules/sequencer/sequencer.json index eab4f71..f0c51d6 100644 --- a/src/modules/sequencer/sequencer.json +++ b/src/modules/sequencer/sequencer.json @@ -188,6 +188,16 @@ "value": "guider", "order": 4, "hint": "Name of the guider module INSTANCE to use (e.g. 'guider', 'myguider1')" + }, + "guidingsettletime": { + "type": "int", + "label": "Resume guiding settle time (s)", + "autoupdate": true, + "directedit": true, + "value": 10, + "order": 5, + "format": "99", + "hint": "Wait time in seconds after resuming guiding before continuing sequence (allows guiding to stabilize)" } } } From e0295071690a5c6a1151fa9eaecc7071eaaff225 Mon Sep 17 00:00:00 2001 From: gehelem Date: Sat, 18 Oct 2025 15:18:43 +0200 Subject: [PATCH 03/11] Calibration data is saved to profile --- src/modules/guider/guider.cpp | 16 ++++++++-------- src/modules/guider/guider.json | 29 +++++++++++++++++++++++------ 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/src/modules/guider/guider.cpp b/src/modules/guider/guider.cpp index 5163620..5f7ef04 100644 --- a/src/modules/guider/guider.cpp +++ b/src/modules/guider/guider.cpp @@ -401,10 +401,10 @@ void Guider::SMInitCal() _calPulseS = 0; _calPulseE = 0; _calPulseW = 0; - getEltInt("values", "calPulseN")->setValue(_calPulseN); - getEltInt("values", "calPulseS")->setValue(_calPulseS); - getEltInt("values", "calPulseE")->setValue(_calPulseE); - getEltInt("values", "calPulseW")->setValue(_calPulseW, true); + getEltInt("calibrationvalues", "calPulseN")->setValue(_calPulseN); + getEltInt("calibrationvalues", "calPulseS")->setValue(_calPulseS); + getEltInt("calibrationvalues", "calPulseE")->setValue(_calPulseE); + getEltInt("calibrationvalues", "calPulseW")->setValue(_calPulseW, true); _pulseN = 0; _pulseS = 0; _pulseE = 0; @@ -611,10 +611,10 @@ void Guider::SMComputeCal() //BOOST_LOG_TRIVIAL(debug) << "*********************** cal E " << _calPulseE; //BOOST_LOG_TRIVIAL(debug) << "*********************** cal N " << _calPulseN; //BOOST_LOG_TRIVIAL(debug) << "*********************** cal S " << _calPulseS; - getEltInt("values", "calPulseN")->setValue(_calPulseN); - getEltInt("values", "calPulseS")->setValue(_calPulseS); - getEltInt("values", "calPulseE")->setValue(_calPulseE); - getEltInt("values", "calPulseW")->setValue(_calPulseW, true); + getEltInt("calibrationvalues", "calPulseN")->setValue(_calPulseN); + getEltInt("calibrationvalues", "calPulseS")->setValue(_calPulseS); + getEltInt("calibrationvalues", "calPulseE")->setValue(_calPulseE); + getEltInt("calibrationvalues", "calPulseW")->setValue(_calPulseW, true); emit CalibrationDone(); _trigFirst = _trigCurrent; return; diff --git a/src/modules/guider/guider.json b/src/modules/guider/guider.json index b2121e9..71e052f 100644 --- a/src/modules/guider/guider.json +++ b/src/modules/guider/guider.json @@ -11,51 +11,68 @@ "type":"int", "label": "Pulse N", "order":"01", + "value": 0, "format": "99.99" }, "pulseS": { "type":"int", "label": "Pulse S", "order":"02", + "value": 0, "format": "99.99" }, "pulseE": { "type":"int", "label": "Pulse E", "order":"03", + "value": 0, "format": "99.99" }, "pulseW": { "type":"int", "label": "Pulse W", "order":"04", + "value": 0, "format": "99.99" - }, + } + } + }, + "calibrationvalues": { + "devcat": "Control", + "group": "", + "order":"Control850", + "permission": 0, + "hasprofile": true, + "label": "Calibration Values", + "elements": { "calPulseN": { "type":"int", "label": "Calibration Pulse N", - "order":"91", + "order":"01", + "value": 0, "format": "99.99" }, "calPulseS": { "type":"int", "label": "Calibration Pulse S", - "order":"92", + "order":"02", + "value": 0, "format": "99.99" }, "calPulseE": { "type":"int", "label": "Calibration Pulse E", - "order":"93", + "order":"03", + "value": 0, "format": "99.99" }, "calPulseW": { "type":"int", "label": "Calibration Pulse W", - "order":"94", + "order":"04", + "value": 0, "format": "99.99" } - } }, "drift": { From 7a8ec5e76d415930327760f48e5490a72c6d9cd0 Mon Sep 17 00:00:00 2001 From: gehelem Date: Sun, 19 Oct 2025 11:48:21 +0200 Subject: [PATCH 04/11] This was missing, but there's still a problem when re-using calibration data - we'll have to analyse this --- src/modules/guider/guider.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/modules/guider/guider.cpp b/src/modules/guider/guider.cpp index 5f7ef04..1363a7d 100644 --- a/src/modules/guider/guider.cpp +++ b/src/modules/guider/guider.cpp @@ -424,6 +424,10 @@ void Guider::SMInitGuide() { //sendMessage("SMInitGuide"); getProperty("drift")->clearGrid();; + _calPulseN = getInt("calibrationvalues", "calPulseN"); + _calPulseS = getInt("calibrationvalues", "calPulseS"); + _calPulseE = getInt("calibrationvalues", "calPulseE"); + _calPulseW = getInt("calibrationvalues", "calPulseW"); //BOOST_LOG_TRIVIAL(debug) << "************************************************************"; //BOOST_LOG_TRIVIAL(debug) << "************************************************************"; From 48242e94dc745861193783615e69582b6871a316 Mon Sep 17 00:00:00 2001 From: gehelem Date: Sun, 19 Oct 2025 11:49:14 +0200 Subject: [PATCH 05/11] Remove SNR dedicated graph and move SNR value to PHD graph --- src/modules/guider/guider.cpp | 7 +---- src/modules/guider/guider.json | 48 +++++++++++----------------------- 2 files changed, 16 insertions(+), 39 deletions(-) diff --git a/src/modules/guider/guider.cpp b/src/modules/guider/guider.cpp index 1363a7d..0713007 100644 --- a/src/modules/guider/guider.cpp +++ b/src/modules/guider/guider.cpp @@ -348,7 +348,6 @@ void Guider::SMInitInit() getProperty("actions")->setState(OST::Busy); getProperty("drift")->clearGrid(); getProperty("guiding")->clearGrid(); - getProperty("snr")->clearGrid(); } else @@ -739,13 +738,9 @@ void Guider::SMComputeGuide() getEltFloat("guiding", "DE")->setValue(_driftDE); getEltFloat("guiding", "pDE")->setValue(_pulseN - _pulseS); getEltFloat("guiding", "pRA")->setValue( _pulseE - _pulseW); + getEltFloat("guiding", "SNR")->setValue(_image->getStats().SNR); getProperty("guiding")->push(); - //setOstElementValue("snr", "time", QDateTime::currentDateTime().toString("dd/MM/yyyy hh:mm:ss zzz"), false); - getEltFloat("snr", "time")->setValue(tt); - getEltFloat("snr", "snr")->setValue(_image->getStats().SNR); - getProperty("snr")->push(); - emit ComputeGuideDone(); } void Guider::SMRequestPulses() diff --git a/src/modules/guider/guider.json b/src/modules/guider/guider.json index 71e052f..341c3ec 100644 --- a/src/modules/guider/guider.json +++ b/src/modules/guider/guider.json @@ -82,12 +82,17 @@ "permission": 0, "label": "Drift", "hasGrid":true, + "showElts":false, "showGrid":false, "gridLimit":200, "graphType":"XY", "graphParams":{ "X":"RA", - "Y":"DEC" + "Y":"DEC", + "Xmin":-10, + "Xmax":10, + "Ymin":-10, + "Ymax":10 }, "elements": { "RA": { @@ -111,6 +116,7 @@ "permission": 0, "label": "Guiding graph", "hasGrid":true, + "showElts":false, "showGrid":false, "gridLimit":20, "graphType":"PHD", @@ -119,7 +125,8 @@ "RA":"RA", "DE":"DE", "pRA":"pRA", - "pDE":"pDE" + "pDE":"pDE", + "RSB":"SNR" }, "elements": { "time": { @@ -151,40 +158,15 @@ "label": "Pulse (DE)", "order":"05", "format": "99.99" + }, + "SNR": { + "type": "float", + "label": "SNR", + "value":0, + "order":6 } } }, - "snr": { - "devcat": "Control", - "gridLimit":50, - "order":"Control300", - "rule":0, - "hasGrid":true, - "showGrid":false, - "gridLimit":20, - "graphType":"DY", - "graphParams":{ - "D":"time", - "Y":"snr" - }, - "elements": { - "time": { - "type":"float", - "label": "Time", - "order":"01", - "value":0 - }, - "snr": { - "type":"float", - "label": "SNR", - "order":"02", - "value":0 - } - }, - "group": "", - "permission": 0, - "label": "SNR" - }, "calParams": { "devcat": "Parameters", "group": "", From 9e6b69dab4caf2ee486b7e592a8c703ea0d058b0 Mon Sep 17 00:00:00 2001 From: gehelem Date: Sun, 19 Oct 2025 12:18:43 +0200 Subject: [PATCH 06/11] add calibration messages --- src/modules/guider/guider.cpp | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/modules/guider/guider.cpp b/src/modules/guider/guider.cpp index 0713007..af5d690 100644 --- a/src/modules/guider/guider.cpp +++ b/src/modules/guider/guider.cpp @@ -394,6 +394,7 @@ void Guider::SMInitCal() //emit propertyUpdated(_states,&_modulename); //_propertyStore.update(_states); + sendMessage("Starting calibration..."); _calState = 0; _calStep = 0; _calPulseN = 0; @@ -524,7 +525,9 @@ void Guider::SMComputeCal() } else { - qDebug() << "houston, we have a problem"; + sendError("No stars, can't calibrate"); + emit abort(); + return; } //BOOST_LOG_TRIVIAL(debug) << "Drifts // prev " << sqrt(square(_dxPrev) + square(_dyPrev)); _trigPrev = _trigCurrent; @@ -540,6 +543,16 @@ void Guider::SMComputeCal() _pulseE = 0; _pulseW = 0; _calStep++; + + // Send progress messages during calibration + QString directionName; + if (_calState == 0) directionName = "West"; + else if (_calState == 1) directionName = "East"; + else if (_calState == 2) directionName = "North"; + else if (_calState == 3) directionName = "South"; + + sendMessage("Calibration " + directionName + " - step " + QString::number(_calStep) + "/" + QString::number(getInt("calParams", "calsteps"))); + if (_calStep >= getInt("calParams", "calsteps") ) { double ddx = 0; @@ -562,6 +575,7 @@ void Guider::SMComputeCal() _ccdOrientation = a; _calMountPointingWest = _mountPointingWest; _calCcdOrientation = _ccdOrientation; + sendMessage("West calibration complete: " + QString::number(_calPulseW, 'f', 2) + " ms/px"); //BOOST_LOG_TRIVIAL(debug) << "*********************** step " << _calState << " Drift orientation = " << a * 180 / PI; //BOOST_LOG_TRIVIAL(debug) << "*********************** step " << _calState << " W drift (px) " << sqrt(square(ddy) + square( @@ -573,6 +587,7 @@ void Guider::SMComputeCal() if (_calState == 1) { _calPulseE = getInt("calParams", "pulse") / sqrt(square(ddx) + square(ddy)); + sendMessage("East calibration complete: " + QString::number(_calPulseE, 'f', 2) + " ms/px"); //BOOST_LOG_TRIVIAL(debug) << "*********************** step " << _calState << " Drift orientation = " << a * 180 / PI; //BOOST_LOG_TRIVIAL(debug) << "*********************** step " << _calState << " E drift (px) " << sqrt(square(ddy) + square( // ddy)); @@ -583,6 +598,7 @@ void Guider::SMComputeCal() if (_calState == 2) { _calPulseN = getInt("calParams", "pulse") / sqrt(square(ddx) + square(ddy)); + sendMessage("North calibration complete: " + QString::number(_calPulseN, 'f', 2) + " ms/px"); //BOOST_LOG_TRIVIAL(debug) << "*********************** step " << _calState << " Drift orientation = " << a * 180 / PI; //BOOST_LOG_TRIVIAL(debug) << "*********************** step " << _calState << " N drift (px) " << sqrt(square(ddy) + square( // ddy)); @@ -593,6 +609,7 @@ void Guider::SMComputeCal() if (_calState == 3) { _calPulseS = getInt("calParams", "pulse") / sqrt(square(ddx) + square(ddy)); + sendMessage("South calibration complete: " + QString::number(_calPulseS, 'f', 2) + " ms/px"); //BOOST_LOG_TRIVIAL(debug) << "*********************** step " << _calState << " Drift orientation = " << a * 180 / PI; //BOOST_LOG_TRIVIAL(debug) << "*********************** step " << _calState << " S drift (px) " << sqrt(square(ddy) + square( // ddy)); @@ -618,6 +635,7 @@ void Guider::SMComputeCal() getEltInt("calibrationvalues", "calPulseS")->setValue(_calPulseS); getEltInt("calibrationvalues", "calPulseE")->setValue(_calPulseE); getEltInt("calibrationvalues", "calPulseW")->setValue(_calPulseW, true); + sendMessage("Calibration completed successfully"); emit CalibrationDone(); _trigFirst = _trigCurrent; return; From 64ae1a08ffba1a07de4ad43631642925c8262b9f Mon Sep 17 00:00:00 2001 From: gehelem Date: Sun, 19 Oct 2025 12:34:23 +0200 Subject: [PATCH 07/11] convert pixels to arcs --- src/modules/guider/guider.cpp | 45 +++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/src/modules/guider/guider.cpp b/src/modules/guider/guider.cpp index af5d690..8ec399e 100644 --- a/src/modules/guider/guider.cpp +++ b/src/modules/guider/guider.cpp @@ -551,7 +551,8 @@ void Guider::SMComputeCal() else if (_calState == 2) directionName = "North"; else if (_calState == 3) directionName = "South"; - sendMessage("Calibration " + directionName + " - step " + QString::number(_calStep) + "/" + QString::number(getInt("calParams", "calsteps"))); + sendMessage("Calibration " + directionName + " - step " + QString::number(_calStep) + "/" + QString::number( + getInt("calParams", "calsteps"))); if (_calStep >= getInt("calParams", "calsteps") ) { @@ -575,7 +576,11 @@ void Guider::SMComputeCal() _ccdOrientation = a; _calMountPointingWest = _mountPointingWest; _calCcdOrientation = _ccdOrientation; - sendMessage("West calibration complete: " + QString::number(_calPulseW, 'f', 2) + " ms/px"); + double ech = getSampling(); + double drift_arcsec = sqrt(square(ddx) + square(ddy)) * ech; + sendMessage("West calibration complete: " + QString::number(_calPulseW, 'f', + 2) + " ms/px (" + QString::number(_calPulseW / ech, 'f', 2) + " ms/arcsec, drift=" + QString::number(drift_arcsec, 'f', + 2) + "\")"); //BOOST_LOG_TRIVIAL(debug) << "*********************** step " << _calState << " Drift orientation = " << a * 180 / PI; //BOOST_LOG_TRIVIAL(debug) << "*********************** step " << _calState << " W drift (px) " << sqrt(square(ddy) + square( @@ -587,7 +592,11 @@ void Guider::SMComputeCal() if (_calState == 1) { _calPulseE = getInt("calParams", "pulse") / sqrt(square(ddx) + square(ddy)); - sendMessage("East calibration complete: " + QString::number(_calPulseE, 'f', 2) + " ms/px"); + double ech = getSampling(); + double drift_arcsec = sqrt(square(ddx) + square(ddy)) * ech; + sendMessage("East calibration complete: " + QString::number(_calPulseE, 'f', + 2) + " ms/px (" + QString::number(_calPulseE / ech, 'f', 2) + " ms/arcsec, drift=" + QString::number(drift_arcsec, 'f', + 2) + "\")"); //BOOST_LOG_TRIVIAL(debug) << "*********************** step " << _calState << " Drift orientation = " << a * 180 / PI; //BOOST_LOG_TRIVIAL(debug) << "*********************** step " << _calState << " E drift (px) " << sqrt(square(ddy) + square( // ddy)); @@ -598,7 +607,11 @@ void Guider::SMComputeCal() if (_calState == 2) { _calPulseN = getInt("calParams", "pulse") / sqrt(square(ddx) + square(ddy)); - sendMessage("North calibration complete: " + QString::number(_calPulseN, 'f', 2) + " ms/px"); + double ech = getSampling(); + double drift_arcsec = sqrt(square(ddx) + square(ddy)) * ech; + sendMessage("North calibration complete: " + QString::number(_calPulseN, 'f', + 2) + " ms/px (" + QString::number(_calPulseN / ech, 'f', 2) + " ms/arcsec, drift=" + QString::number(drift_arcsec, 'f', + 2) + "\")"); //BOOST_LOG_TRIVIAL(debug) << "*********************** step " << _calState << " Drift orientation = " << a * 180 / PI; //BOOST_LOG_TRIVIAL(debug) << "*********************** step " << _calState << " N drift (px) " << sqrt(square(ddy) + square( // ddy)); @@ -609,7 +622,11 @@ void Guider::SMComputeCal() if (_calState == 3) { _calPulseS = getInt("calParams", "pulse") / sqrt(square(ddx) + square(ddy)); - sendMessage("South calibration complete: " + QString::number(_calPulseS, 'f', 2) + " ms/px"); + double ech = getSampling(); + double drift_arcsec = sqrt(square(ddx) + square(ddy)) * ech; + sendMessage("South calibration complete: " + QString::number(_calPulseS, 'f', + 2) + " ms/px (" + QString::number(_calPulseS / ech, 'f', 2) + " ms/arcsec, drift=" + QString::number(drift_arcsec, 'f', + 2) + "\")"); //BOOST_LOG_TRIVIAL(debug) << "*********************** step " << _calState << " Drift orientation = " << a * 180 / PI; //BOOST_LOG_TRIVIAL(debug) << "*********************** step " << _calState << " S drift (px) " << sqrt(square(ddy) + square( // ddy)); @@ -636,6 +653,7 @@ void Guider::SMComputeCal() getEltInt("calibrationvalues", "calPulseE")->setValue(_calPulseE); getEltInt("calibrationvalues", "calPulseW")->setValue(_calPulseW, true); sendMessage("Calibration completed successfully"); + getProperty("actions")->setState(OST::Ok); emit CalibrationDone(); _trigFirst = _trigCurrent; return; @@ -659,8 +677,9 @@ void Guider::SMComputeCal() } double _driftRA = _dxFirst * cos(_calCcdOrientation) + _dyFirst * sin(_calCcdOrientation); double _driftDE = _dxFirst * sin(_calCcdOrientation) + _dyFirst * cos(_calCcdOrientation); - getEltFloat("drift", "RA")->setValue(_driftRA); - getEltFloat("drift", "DEC")->setValue(_driftDE); + double ech = getSampling(); + getEltFloat("drift", "RA")->setValue(_driftRA * ech); + getEltFloat("drift", "DEC")->setValue(_driftDE * ech); getProperty("drift")->push(); @@ -745,15 +764,16 @@ void Guider::SMComputeGuide() getEltInt("values", "pulseS")->setValue(_pulseS); getEltInt("values", "pulseE")->setValue(_pulseE); getEltInt("values", "pulseW")->setValue(_pulseW, true); - getEltFloat("drift", "RA")->setValue(_driftRA); - getEltFloat("drift", "DEC")->setValue(_driftDE, true); + double ech = getSampling(); + getEltFloat("drift", "RA")->setValue(_driftRA * ech); + getEltFloat("drift", "DEC")->setValue(_driftDE * ech, true); getProperty("drift")->push(); //setOstElementValue("guiding", "time", QDateTime::currentDateTime().toString("dd/MM/yyyy hh:mm:ss zzz"), false); double tt = QDateTime::currentDateTime().toMSecsSinceEpoch(); getEltFloat("guiding", "time")->setValue(tt); - getEltFloat("guiding", "RA")->setValue(_driftRA); - getEltFloat("guiding", "DE")->setValue(_driftDE); + getEltFloat("guiding", "RA")->setValue(_driftRA * ech); + getEltFloat("guiding", "DE")->setValue(_driftDE * ech); getEltFloat("guiding", "pDE")->setValue(_pulseN - _pulseS); getEltFloat("guiding", "pRA")->setValue( _pulseE - _pulseW); getEltFloat("guiding", "SNR")->setValue(_image->getStats().SNR); @@ -859,7 +879,8 @@ void Guider::OnSucessSEP() { //BOOST_LOG_TRIVIAL(debug) << "OnSucessSEP"; OST::ImgData dta = getEltImg("image", "image")->value(); - dta.HFRavg = _solver.HFRavg; + double ech = getSampling(); + dta.HFRavg = _solver.HFRavg * ech; dta.starsCount = _solver.stars.size(); getEltImg("image", "image")->setValue(dta, true); From 4d5f23af7f3d5ebcdf91b7d0418c52d69147d066 Mon Sep 17 00:00:00 2001 From: gehelem Date: Sun, 19 Oct 2025 12:48:28 +0200 Subject: [PATCH 08/11] Add RMS calculation --- src/modules/guider/guider.cpp | 41 +++++++++++++++++++++++++++++++++- src/modules/guider/guider.json | 31 +++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/src/modules/guider/guider.cpp b/src/modules/guider/guider.cpp index 8ec399e..c63244d 100644 --- a/src/modules/guider/guider.cpp +++ b/src/modules/guider/guider.cpp @@ -429,6 +429,10 @@ void Guider::SMInitGuide() _calPulseE = getInt("calibrationvalues", "calPulseE"); _calPulseW = getInt("calibrationvalues", "calPulseW"); + // Clear RMS drift history when starting guide + _dRAvector.clear(); + _dDEvector.clear(); + //BOOST_LOG_TRIVIAL(debug) << "************************************************************"; //BOOST_LOG_TRIVIAL(debug) << "************************************************************"; //BOOST_LOG_TRIVIAL(debug) << "Guider module - Start guide with fllowing calibration data : "; @@ -760,10 +764,45 @@ void Guider::SMComputeGuide() _itt++; + // Store drift history for RMS calculation + _dRAvector.push_back(_driftRA * getSampling()); + _dDEvector.push_back(_driftDE * getSampling()); + + // Limit vector size to rmsOver parameter + int rmsOver = getInt("guideParams", "rmsOver"); + while (_dRAvector.size() > (size_t)rmsOver) + { + _dRAvector.erase(_dRAvector.begin()); + } + while (_dDEvector.size() > (size_t)rmsOver) + { + _dDEvector.erase(_dDEvector.begin()); + } + + // Calculate RMS + double rmsRA = 0; + double rmsDEC = 0; + double rmsTotal = 0; + + if (_dRAvector.size() > 0) + { + for (size_t i = 0; i < _dRAvector.size(); i++) + { + rmsRA += square(_dRAvector[i]); + rmsDEC += square(_dDEvector[i]); + } + rmsRA = sqrt(rmsRA / _dRAvector.size()); + rmsDEC = sqrt(rmsDEC / _dDEvector.size()); + rmsTotal = sqrt(square(rmsRA) + square(rmsDEC)); + } + getEltInt("values", "pulseN")->setValue(_pulseN); getEltInt("values", "pulseS")->setValue(_pulseS); getEltInt("values", "pulseE")->setValue(_pulseE); - getEltInt("values", "pulseW")->setValue(_pulseW, true); + getEltInt("values", "pulseW")->setValue(_pulseW); + getEltFloat("values", "rmsRA")->setValue(rmsRA); + getEltFloat("values", "rmsDEC")->setValue(rmsDEC); + getEltFloat("values", "rmsTotal")->setValue(rmsTotal, true); double ech = getSampling(); getEltFloat("drift", "RA")->setValue(_driftRA * ech); getEltFloat("drift", "DEC")->setValue(_driftDE * ech, true); diff --git a/src/modules/guider/guider.json b/src/modules/guider/guider.json index 341c3ec..779dc86 100644 --- a/src/modules/guider/guider.json +++ b/src/modules/guider/guider.json @@ -34,6 +34,27 @@ "order":"04", "value": 0, "format": "99.99" + }, + "rmsRA": { + "type":"float", + "label": "RMS RA", + "order":"05", + "value": 0, + "format": "99.99" + }, + "rmsDEC": { + "type":"float", + "label": "RMS DEC", + "order":"06", + "value": 0, + "format": "99.99" + }, + "rmsTotal": { + "type":"float", + "label": "RMS Total", + "order":"07", + "value": 0, + "format": "99.99" } } }, @@ -240,6 +261,16 @@ "order":"04", "value":0.8, "format": "99" + }, + "rmsOver": { + "type":"int", + "autoupdate":true, + "directedit":true, + "label": "RMS drift over x", + "order":"05", + "value":10, + "format": "99", + "hint": "Number of frames to calculate RMS drift" } } }, From 88ea611115e49220b6e0d61bff532cc8eb859723 Mon Sep 17 00:00:00 2001 From: gehelem Date: Sun, 19 Oct 2025 13:06:42 +0200 Subject: [PATCH 09/11] Add RMS to guiding graph --- src/modules/guider/guider.cpp | 1 + src/modules/guider/guider.json | 9 ++++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/modules/guider/guider.cpp b/src/modules/guider/guider.cpp index c63244d..97104b9 100644 --- a/src/modules/guider/guider.cpp +++ b/src/modules/guider/guider.cpp @@ -816,6 +816,7 @@ void Guider::SMComputeGuide() getEltFloat("guiding", "pDE")->setValue(_pulseN - _pulseS); getEltFloat("guiding", "pRA")->setValue( _pulseE - _pulseW); getEltFloat("guiding", "SNR")->setValue(_image->getStats().SNR); + getEltFloat("guiding", "RMS")->setValue(rmsTotal); getProperty("guiding")->push(); emit ComputeGuideDone(); diff --git a/src/modules/guider/guider.json b/src/modules/guider/guider.json index 779dc86..275aabc 100644 --- a/src/modules/guider/guider.json +++ b/src/modules/guider/guider.json @@ -147,7 +147,8 @@ "DE":"DE", "pRA":"pRA", "pDE":"pDE", - "RSB":"SNR" + "RSB":"SNR", + "RMS":"RMS" }, "elements": { "time": { @@ -185,6 +186,12 @@ "label": "SNR", "value":0, "order":6 + }, + "RMS": { + "type": "float", + "label": "RMS", + "value":0, + "order":7 } } }, From ec15ca6639c4412146b6fbb18175e45e6fd4a357 Mon Sep 17 00:00:00 2001 From: gehelem Date: Sun, 19 Oct 2025 14:43:07 +0200 Subject: [PATCH 10/11] Decrease drift graph min/max from 10 to 5" --- src/modules/guider/guider.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/modules/guider/guider.json b/src/modules/guider/guider.json index 275aabc..19be7fb 100644 --- a/src/modules/guider/guider.json +++ b/src/modules/guider/guider.json @@ -110,10 +110,10 @@ "graphParams":{ "X":"RA", "Y":"DEC", - "Xmin":-10, - "Xmax":10, - "Ymin":-10, - "Ymax":10 + "Xmin":-5, + "Xmax":5, + "Ymin":-5, + "Ymax":5 }, "elements": { "RA": { From 1a00e68891a8ce30beef44963d2584393d80812c Mon Sep 17 00:00:00 2001 From: gehelem Date: Sun, 19 Oct 2025 14:55:00 +0200 Subject: [PATCH 11/11] ...IA documented... --- src/modules/sequencer/sequencer.en.md | 286 ++++++++++++++++++++++++++ src/modules/sequencer/sequencer.fr.md | 284 ++++++++++++++++++++++++- 2 files changed, 568 insertions(+), 2 deletions(-) create mode 100644 src/modules/sequencer/sequencer.en.md diff --git a/src/modules/sequencer/sequencer.en.md b/src/modules/sequencer/sequencer.en.md new file mode 100644 index 0000000..b4e1727 --- /dev/null +++ b/src/modules/sequencer/sequencer.en.md @@ -0,0 +1,286 @@ +--- +title: Module - Sequencer +weight : 20 +--- + +{{% notice style="note" title="Notice" icon="exclamation-triangle" %}} +10/19/2025 - Developer note: +This documentation was generated by Claude AI as a starting point that I will update when I find some time +{{% /notice %}} + +# Sequencer Module + +The **Sequencer** module automates astronomical image acquisition by defining sequences of exposures with different parameters (filters, exposure time, gain, offset, etc.). + +## Overview + +The sequencer is designed to manage complex imaging sessions by enabling: +- Multi-line sequence definition with different parameters per line +- Integration with the autofocus module +- Integration with the guiding module +- Real-time progress tracking +- Configuration saving in profiles + +## Basic Configuration + +### Object (Target Object) + +This section allows you to define the coordinates of the observed object: + +| Parameter | Description | +|-----------|-------------| +| **Name** | Object name (e.g., M31, NGC7000) | +| **RA** | Right ascension of the object | +| **DEC** | Declination of the object | + +This information is used to name acquired files and can be synchronized with the navigator module. + +### Sequence (Acquisition Sequence) + +The sequence is defined as a table where each line represents a set of exposures: + +| Column | Description | Possible Values | +|--------|-------------|-----------------| +| **Frame type** | Exposure type | Light (L), Bias (B), Dark (D), Flat (F) | +| **Filter** | Filter to use | List of available filters on the wheel | +| **Exposure** | Exposure time in seconds | Decimal number (e.g., 300.0 for 5 minutes) | +| **Count** | Number of exposures to take | Integer | +| **Gain** | Camera gain | Value depending on camera | +| **Offset** | Camera offset | Value depending on camera | +| **Progress** | Line progress | Visual indicator (automatic) | + +#### Sequence Example + +``` +Frame Type | Filter | Exposure | Count | Gain | Offset +-----------|--------|----------|-------|------|------- +Light | Ha | 300 | 20 | 120 | 20 +Light | OIII | 300 | 20 | 120 | 20 +Light | SII | 300 | 20 | 120 | 20 +Dark | - | 300 | 10 | 120 | 20 +``` + +### Progress + +This section displays real-time progress: + +- **Sequence**: Overall progress of the entire sequence +- **Current exposure**: Progress of the current exposure + +## Advanced Parameters + +### Auto-focus at sequence start + +**Type**: Boolean (checkbox) +**Default value**: Enabled + +When this option is enabled, the sequencer automatically triggers a focus before starting the first line of the sequence. The focus uses the filter defined in the first line. + +**Recommended usage**: Always enabled to ensure optimal focus at the start of the session. + +### Auto-focus on filter change + +**Type**: Boolean (checkbox) +**Default value**: Disabled + +Automatically triggers a focus each time the filter changes between two sequence lines. + +**Recommended usage**: +- Enabled if your optical system has focus shift between filters (chromatism) +- Disabled if your filters are perfectly compensated + +### Focus module instance + +**Type**: Module selection +**Default value**: "focus" + +Allows selection of which focus module instance to use for autofocus operations. Useful if you have multiple focus modules loaded with different configurations. + +### Suspend guiding during focus + +**Type**: Boolean (checkbox) +**Default value**: Disabled + +When this option is enabled: +1. The sequencer suspends guiding before launching autofocus +2. Autofocus runs without active guiding +3. Guiding automatically resumes after focusing +4. A settling time is applied (see next parameter) + +**Recommended usage**: +- Enabled if the guiding system interferes with HFR measurement during autofocus +- Enabled for small focus movements that could trigger parasitic guiding corrections + +### Guider module instance + +**Type**: Module selection +**Default value**: "guider" + +Defines which guider module instance to control for suspend/resume guiding operations. + +### Resume guiding settle time + +**Type**: Integer (seconds) +**Default value**: 10 seconds + +Wait time after guiding resumes before continuing the sequence. This delay allows the guiding system to stabilize and avoids starting an exposure while guiding is converging. + +**Recommended values**: +- **5-10 seconds**: Standard configuration +- **15-20 seconds**: Mount with high inertia or aggressive guiding +- **3-5 seconds**: Very stable mount with gentle guiding + +## Practical Usage + +### Starting a Sequence + +1. **Define the target object** in the "Object" section +2. **Create sequence lines** by clicking "+" to add lines +3. **Configure each line** with desired parameters +4. **Check autofocus and guiding parameters** +5. **Launch the sequence** via the action button + +### Stopping a Sequence + +The sequence can be interrupted at any time. The stop is clean: +- The current exposure is completed +- Files are saved +- Equipment is returned to a safe state + +### Resuming an Interrupted Sequence + +The sequencer keeps track of each line's progress. To resume: +1. The sequence automatically resumes where it left off +2. Already completed lines are skipped +3. The current line resumes at the remaining exposure count + +## Integration with Other Modules + +### Focus Module + +The sequencer communicates with the focus module to: +- Trigger autofocus at the start of the sequence +- Trigger autofocus during filter changes +- Wait for autofocus completion before continuing + +**Required configuration**: The focus module must be loaded and configured. + +### Guider Module + +The sequencer can control the guider module to: +- Suspend guiding during autofocus +- Resume guiding after autofocus +- Wait for guiding stabilization + +**Required configuration**: The guider module must be loaded, calibrated, and actively guiding. + +### Camera Module + +The sequencer automatically controls: +- Exposure parameters (time, gain, offset) +- Exposure type (Light/Dark/Bias/Flat) +- FITS file recording + +### Filter Wheel Module + +If a filter wheel is configured: +- The sequencer automatically changes filters between lines +- Filter changes can trigger autofocus (if configured) + +## Profiles + +The following configurations are saved in profiles: +- Complete sequence definition (all lines) +- Object coordinates +- All autofocus and guiding parameters + +To save a profile: +1. Configure the sequence and parameters +2. Use the system's profile save function +3. Give it a meaningful name (e.g., "M31_HaOIIISII", "Broadband_LRGB") + +## Tips and Best Practices + +### Sequence Organization + +- **Group similar exposures**: All Ha exposures together, then OIII, etc. +- **Alternate if necessary**: To compensate for field rotation or changing conditions +- **Darks at the end**: Acquire darks at the end of the session when the camera is at stable temperature + +### Autofocus Management + +- **Always enable autofocus at startup** to start on solid ground +- **Test focus shift between filters** before enabling autofocus on filter change +- **Monitor first exposures** of each filter to verify focus quality + +### Guiding Management + +- **Calibrate guiding before** starting the sequence +- **Enable suspension during focus** if you notice erratic HFR variations +- **Adjust settle time** according to your mount (observe first exposures after focus) + +### Time Optimization + +Total sequence time includes: +- Total exposure time (sum of all exposures) +- Camera readout time +- Filter change time (~2-5 seconds per change) +- Autofocus time (~1-3 minutes per autofocus) +- Guiding settling time (settle time parameter) + +**Tip**: Minimizing the number of filter changes reduces total time. + +### Error Management + +In case of problems during the sequence: +- **Clouds/weather**: Stop cleanly, resuming will be possible +- **Guiding loss**: Check guider configuration before resuming +- **Focus problem**: Check focus module, recalibrate if necessary +- **Camera error**: Check INDI connection, restart camera if necessary + +## Troubleshooting + +### Sequence Won't Start + +- Check that the camera is connected +- Check that the focus module is loaded (if autofocus enabled) +- Check that all sequence parameters are valid +- Consult error messages in logs + +### Autofocus Fails + +- The sequencer pauses the sequence +- Fix the problem in the focus module +- Manually relaunch autofocus +- Resume the sequence + +### Guiding Won't Resume + +- Check that the guider module is still active +- Check that the guide star is still visible +- Adjust settle time parameter if necessary +- Recalibrate guiding if necessary + +### Files Are Not Saved + +- Check destination directory permissions +- Check available disk space +- Check camera module configuration + +## File Formats + +Generated FITS files contain the following metadata in their header: +- `OBJECT`: Object name +- `OBJCTRA`: Right ascension +- `OBJCTDEC`: Declination +- `EXPTIME`: Exposure time +- `GAIN`: Gain used +- `OFFSET`: Offset used +- `FILTER`: Filter used +- `IMAGETYP`: Exposure type (Light/Dark/Bias/Flat) + +This metadata is used by processing software (PixInsight, Siril, etc.) to organize and calibrate images. + +## Conclusion + +The Sequencer module is the central tool for automating your imaging sessions. Good mastery of its parameters and integration with the focus and guider modules enables reliable, high-quality acquisition sessions, even unattended. diff --git a/src/modules/sequencer/sequencer.fr.md b/src/modules/sequencer/sequencer.fr.md index 748a24f..ef847fc 100644 --- a/src/modules/sequencer/sequencer.fr.md +++ b/src/modules/sequencer/sequencer.fr.md @@ -1,6 +1,286 @@ --- title: Module - Sequencer weight : 20 ---- +--- + +{{% notice style="note" title="Attention" icon="exclamation-triangle" %}} +19/10/2025 - Note du développeur : +Cette documentation a été générée par l'IA Claude, comme un point de départ que je mettrai à jour lorsque je trouverai un peu de temps +{{% /notice %}} + +# Module Sequencer + +Le module **Sequencer** permet d'automatiser l'acquisition d'images astronomiques en définissant des séquences de poses avec différents paramètres (filtres, temps d'exposition, gain, offset, etc.). + +## Vue d'ensemble + +Le séquenceur est conçu pour gérer des sessions d'imagerie complexes en permettant : +- La définition de séquences multi-lignes avec différents paramètres par ligne +- L'intégration avec le module de mise au point automatique (autofocus) +- L'intégration avec le module de guidage +- Le suivi de la progression en temps réel +- La sauvegarde des configurations dans des profils + +## Configuration de base + +### Object (Objet cible) + +Cette section permet de définir les coordonnées de l'objet observé : + +| Paramètre | Description | +|-----------|-------------| +| **Name** | Nom de l'objet (ex: M31, NGC7000) | +| **RA** | Ascension droite de l'objet | +| **DEC** | Déclinaison de l'objet | + +Ces informations sont utilisées pour nommer les fichiers acquis et peuvent être synchronisées avec le module navigator. + +### Sequence (Séquence d'acquisition) + +La séquence est définie sous forme de tableau où chaque ligne représente un ensemble de poses : + +| Colonne | Description | Valeurs possibles | +|---------|-------------|-------------------| +| **Frame type** | Type de pose | Light (L), Bias (B), Dark (D), Flat (F) | +| **Filter** | Filtre à utiliser | Liste des filtres disponibles sur la roue | +| **Exposure** | Temps d'exposition en secondes | Nombre décimal (ex: 300.0 pour 5 minutes) | +| **Count** | Nombre de poses à réaliser | Nombre entier | +| **Gain** | Gain de la caméra | Valeur dépendant de la caméra | +| **Offset** | Offset de la caméra | Valeur dépendant de la caméra | +| **Progress** | Progression de la ligne | Indicateur visuel (automatique) | + +#### Exemple de séquence + +``` +Frame Type | Filter | Exposure | Count | Gain | Offset +-----------|--------|----------|-------|------|------- +Light | Ha | 300 | 20 | 120 | 20 +Light | OIII | 300 | 20 | 120 | 20 +Light | SII | 300 | 20 | 120 | 20 +Dark | - | 300 | 10 | 120 | 20 +``` + +### Progress (Progression) + +Cette section affiche l'avancement en temps réel : + +- **Sequence** : Progression globale de toute la séquence +- **Current exposure** : Progression de la pose en cours + +## Paramètres avancés + +### Auto-focus at sequence start + +**Type** : Booléen (case à cocher) +**Valeur par défaut** : Activé + +Lorsque cette option est activée, le séquenceur déclenche automatiquement une mise au point avant de commencer la première ligne de la séquence. La mise au point utilise le filtre défini dans la première ligne. + +**Utilisation recommandée** : Toujours activé pour garantir une mise au point optimale au début de la session. + +### Auto-focus on filter change + +**Type** : Booléen (case à cocher) +**Valeur par défaut** : Désactivé + +Déclenche automatiquement une mise au point chaque fois que le filtre change entre deux lignes de la séquence. + +**Utilisation recommandée** : +- Activé si votre système optique présente un décalage de mise au point entre filtres (chromatisme) +- Désactivé si vos filtres sont parfaitement compensés + +### Focus module instance + +**Type** : Sélection de module +**Valeur par défaut** : "focus" + +Permet de sélectionner quelle instance du module focus utiliser pour les opérations d'autofocus. Utile si vous avez plusieurs modules focus chargés avec des configurations différentes. + +### Suspend guiding during focus + +**Type** : Booléen (case à cocher) +**Valeur par défaut** : Désactivé + +Lorsque cette option est activée : +1. Le séquenceur suspend le guidage avant de lancer l'autofocus +2. L'autofocus s'exécute sans guidage actif +3. Le guidage reprend automatiquement après la mise au point +4. Un temps de stabilisation est appliqué (voir paramètre suivant) + +**Utilisation recommandée** : +- Activé si le système de guidage perturbe la mesure de HFR pendant l'autofocus +- Activé pour les petits déplacements de mise au point qui pourraient déclencher des corrections de guidage parasites + +### Guider module instance + +**Type** : Sélection de module +**Valeur par défaut** : "guider" + +Définit quelle instance du module guider contrôler pour les opérations de suspension/reprise du guidage. + +### Resume guiding settle time + +**Type** : Entier (secondes) +**Valeur par défaut** : 10 secondes + +Temps d'attente après la reprise du guidage avant de continuer la séquence. Ce délai permet au système de guidage de se stabiliser et d'éviter de commencer une pose pendant que le guidage converge. + +**Valeurs recommandées** : +- **5-10 secondes** : Configuration standard +- **15-20 secondes** : Monture avec beaucoup d'inertie ou guidage agressif +- **3-5 secondes** : Monture très stable avec guidage doux + +## Utilisation pratique + +### Démarrer une séquence + +1. **Définir l'objet cible** dans la section "Object" +2. **Créer les lignes de séquence** en cliquant sur "+" pour ajouter des lignes +3. **Configurer chaque ligne** avec les paramètres souhaités +4. **Vérifier les paramètres** d'autofocus et de guidage +5. **Lancer la séquence** via le bouton d'action + +### Arrêter une séquence + +La séquence peut être interrompue à tout moment. L'arrêt se fait de manière propre : +- La pose en cours est terminée +- Les fichiers sont sauvegardés +- Les équipements sont remis en état sûr + +### Reprendre une séquence interrompue + +Le séquenceur conserve la progression de chaque ligne. Pour reprendre : +1. La séquence reprend automatiquement là où elle s'était arrêtée +2. Les lignes déjà complétées sont ignorées +3. La ligne en cours reprend au nombre de poses restantes + +## Intégration avec d'autres modules + +### Module Focus + +Le séquenceur communique avec le module focus pour : +- Déclencher l'autofocus au début de la séquence +- Déclencher l'autofocus lors des changements de filtre +- Attendre la fin de l'autofocus avant de continuer + +**Configuration requise** : Le module focus doit être chargé et configuré. + +### Module Guider + +Le séquenceur peut contrôler le module guider pour : +- Suspendre le guidage pendant l'autofocus +- Reprendre le guidage après l'autofocus +- Attendre la stabilisation du guidage + +**Configuration requise** : Le module guider doit être chargé, calibré et en cours de guidage. + +### Module Camera + +Le séquenceur contrôle automatiquement : +- Les paramètres d'exposition (temps, gain, offset) +- Le type de pose (Light/Dark/Bias/Flat) +- L'enregistrement des fichiers FITS + +### Module Filter Wheel + +Si une roue à filtres est configurée : +- Le séquenceur change automatiquement de filtre entre les lignes +- Le changement de filtre peut déclencher un autofocus (si configuré) + +## Profils + +Les configurations suivantes sont sauvegardées dans les profils : +- Définition complète de la séquence (toutes les lignes) +- Coordonnées de l'objet +- Tous les paramètres d'autofocus et de guidage + +Pour sauvegarder un profil : +1. Configurer la séquence et les paramètres +2. Utiliser la fonction de sauvegarde de profil du système +3. Donner un nom significatif (ex: "M31_HaOIIISII", "Broadband_LRGB") + +## Conseils et bonnes pratiques + +### Organisation des séquences + +- **Grouper les poses similaires** : Toutes les poses Ha ensemble, puis OIII, etc. +- **Alterner si nécessaire** : Pour compenser la rotation du champ ou les conditions changeantes +- **Darks à la fin** : Acquérir les darks en fin de session quand la caméra est à température stable + +### Gestion de l'autofocus + +- **Toujours activer l'autofocus au démarrage** pour partir sur de bonnes bases +- **Tester le décalage entre filtres** avant d'activer l'autofocus sur changement de filtre +- **Monitorer les premières poses** de chaque filtre pour vérifier la qualité du focus + +### Gestion du guidage + +- **Calibrer le guidage avant** de démarrer la séquence +- **Activer la suspension pendant focus** si vous constatez des variations de HFR erratiques +- **Ajuster le settle time** selon votre monture (observer les premières poses après focus) + +### Optimisation du temps + +Le temps total de la séquence inclut : +- Temps d'exposition total (sum of all exposures) +- Temps de lecture de la caméra (readout time) +- Temps de changement de filtre (~2-5 secondes par changement) +- Temps d'autofocus (~1-3 minutes par autofocus) +- Temps de stabilisation du guidage (paramètre settle time) + +**Astuce** : Minimiser le nombre de changements de filtre réduit le temps total. + +### Gestion des erreurs + +En cas de problème pendant la séquence : +- **Nuages/météo** : Arrêter proprement, la reprise sera possible +- **Perte de guidage** : Vérifier la configuration du guider avant de reprendre +- **Problème de focus** : Vérifier le module focus, recalibrer si nécessaire +- **Erreur caméra** : Vérifier la connexion INDI, redémarrer la caméra si nécessaire + +## Dépannage + +### La séquence ne démarre pas + +- Vérifier que la caméra est connectée +- Vérifier que le module focus est chargé (si autofocus activé) +- Vérifier que tous les paramètres de la séquence sont valides +- Consulter les messages d'erreur dans les logs + +### L'autofocus échoue + +- Le séquenceur met la séquence en pause +- Corriger le problème dans le module focus +- Relancer manuellement l'autofocus +- Reprendre la séquence + +### Le guidage ne reprend pas + +- Vérifier que le module guider est toujours actif +- Vérifier que l'étoile guide est toujours visible +- Ajuster le paramètre settle time si nécessaire +- Recalibrer le guidage si nécessaire + +### Les fichiers ne sont pas sauvegardés + +- Vérifier les permissions du répertoire de destination +- Vérifier l'espace disque disponible +- Vérifier la configuration du module caméra + +## Formats de fichiers + +Les fichiers FITS générés contiennent les métadonnées suivantes dans leur en-tête : +- `OBJECT` : Nom de l'objet +- `OBJCTRA` : Ascension droite +- `OBJCTDEC` : Déclinaison +- `EXPTIME` : Temps d'exposition +- `GAIN` : Gain utilisé +- `OFFSET` : Offset utilisé +- `FILTER` : Filtre utilisé +- `IMAGETYP` : Type de pose (Light/Dark/Bias/Flat) + +Ces métadonnées sont utilisées par les logiciels de traitement (PixInsight, Siril, etc.) pour organiser et calibrer les images. + +## Conclusion -Documentation du module Sequencer +Le module Sequencer est l'outil central pour automatiser vos sessions d'imagerie. Une bonne maîtrise de ses paramètres et de son intégration avec les modules focus et guider permet d'obtenir des sessions d'acquisition fiables et de haute qualité, même sans surveillance.