[education/kstars] kstars/ekos/guide: Guide: Persist Predictive Guiding (GPG) period length per optical train

Jasem Mutlaq <[email protected]>
Newsgroups gmane.comp.kde.cvs
Message-ID <[email protected]>
Git commit 27f23270b15120d3532de25b1bfb2de241992384 by Jasem Mutlaq, on behalf of Andreas R..
Committed on 24/07/2026 at 08:39.
Pushed by mutlaqja into branch 'master'.

Guide: Persist Predictive Guiding (GPG) period length per optical train

The Predictive Guiding (GPG) algorithm models the mount's periodic error with a Gaussian Process whose main periodic component has a "period length" hyperparameter. When automatic period estimation is enabled the algorithm continuously refines this value while guiding and keeps the current estimate in the single global Options::gPGPeriod() setting.

Because the setting is global, it is overwritten by whichever optical train is guiding at the time. For users who switch between mounts with very different periodic-error characteristics on the same machine this is not ideal: a classic worm-gear mount (period typically several hundred seconds) and a harmonic/strain-wave-drive mount (very different period, no single worm period) end up clobbering each other's value, and a fresh setup inherits whatever the previously active gear happened to leave behind. Automatic tuning therefore never settles into a value that is appropriate for the gear actually in use.

Store the period length per optical train instead, mirroring how other per-train guide settings are handled:

- Restore: when an optical train is loaded, seed Options::gPGPeriod() from the value stored for that train (refreshOpticalTrain()).
- Save: when guiding stops, persist the current Options::gPGPeriod() into the active train's settings (saveGPGPeriod(), called from abort()). This is a no-op unless the internal guider is used with the GPG algorithm and period estimation is enabled.
- Apply: GPG::reset() now re-applies the parameters from Options after clearing the model. reset() runs at the start of every guiding session, so the restored per-train period (and any GPG option the user changed) now takes effect immediately instead of only after pressing "Apply" or restarting. Since the estimator writes its running estimate back to Options each cycle, re-applying on the periodic in-session model reset preserves the learned value rather than discarding it.

Net effect: each mount/gear keeps and refines its own period length across sessions, so automatic period estimation produces sensible results for both worm-gear and harmonic-drive mounts used with the same KStars installation.

M  +27   -0    kstars/ekos/guide/guide.cpp
M  +8    -0    kstars/ekos/guide/guide.h
M  +5    -0    kstars/ekos/guide/internalguide/gpg.cpp

https://invent.kde.org/education/kstars/-/commit/27f23270b15120d3532de25b1bfb2de241992384

diff --git a/kstars/ekos/guide/guide.cpp b/kstars/ekos/guide/guide.cpp
index b0af363fa3..f7ad8f1c4a 100644
--- a/kstars/ekos/guide/guide.cpp
+++ b/kstars/ekos/guide/guide.cpp
@@ -1062,6 +1062,8 @@ bool Guide::abort()
         case GUIDE_CAPTURE:
         case GUIDE_GUIDING:
         case GUIDE_LOOPING:
+            // Persist the periodic-error period length learned during this session before stopping.
+            saveGPGPeriod();
             m_GuiderInstance->abort();
             break;
 
@@ -3916,6 +3918,13 @@ void Guide::refreshOpticalTrain()
         }
         else
             m_Settings = m_GlobalSettings;
+
+        // Restore the periodic-error period length used by Predictive Guiding (GPG) that was
+        // learned and stored for this optical train. Storing it per train lets a worm-gear
+        // mount and a harmonic-drive mount (which have very different periodic-error periods)
+        // each keep their own value instead of sharing a single global setting.
+        if (m_Settings.contains("gPGPeriod"))
+            Options::setGPGPeriod(m_Settings["gPGPeriod"].toDouble());
     }
 
     opticalTrainCombo->blockSignals(false);
@@ -4064,6 +4073,24 @@ void Guide::updateSetting(const QString &key, const QVariant &value)
     m_DebounceTimer.start();
 }
 
+///////////////////////////////////////////////////////////////////////////////////////////
+///
+///////////////////////////////////////////////////////////////////////////////////////////
+void Guide::saveGPGPeriod()
+{
+    // Predictive Guiding (GPG) learns the mount's periodic-error period length while guiding
+    // and keeps the current estimate in Options::gPGPeriod(). Persist it into the active
+    // optical train so that the value is retained per mount/gear across sessions. This is
+    // what allows very different mounts (e.g. worm-gear vs. harmonic-drive) to each keep an
+    // appropriate period rather than overwriting a single shared global value.
+    if (guiderType != GUIDE_INTERNAL)
+        return;
+    if (Options::rAGuidePulseAlgorithm() != OpsGuide::GPG_ALGORITHM || !Options::gPGEstimatePeriod())
+        return;
+
+    updateSetting("gPGPeriod", Options::gPGPeriod());
+}
+
 ///////////////////////////////////////////////////////////////////////////////////////////
 ///
 ///////////////////////////////////////////////////////////////////////////////////////////
diff --git a/kstars/ekos/guide/guide.h b/kstars/ekos/guide/guide.h
index 3cce335265..00fa8c4aaa 100644
--- a/kstars/ekos/guide/guide.h
+++ b/kstars/ekos/guide/guide.h
@@ -409,6 +409,14 @@ class Guide : public QWidget, public Ui::Guide
          */
         void updateSetting(const QString &key, const QVariant &value);
 
+        /**
+         * @brief saveGPGPeriod Persist the Predictive Guiding (GPG) periodic-error period length
+         * learned during the current session into the active optical train, so it is retained
+         * per mount/gear across sessions. No-op unless the internal guider is used with the GPG
+         * algorithm and automatic period estimation enabled.
+         */
+        void saveGPGPeriod();
+
         //plot slots
         void handleVerticalPlotSizeChange();
         void handleHorizontalPlotSizeChange();
diff --git a/kstars/ekos/guide/internalguide/gpg.cpp b/kstars/ekos/guide/internalguide/gpg.cpp
index 790fe9656b..ca8bb771cd 100644
--- a/kstars/ekos/guide/internalguide/gpg.cpp
+++ b/kstars/ekos/guide/internalguide/gpg.cpp
@@ -133,6 +133,11 @@ void GPG::reset()
     gpgSamples = 0;
     gpgSkippedSamples = 0;
     gpg->reset();
+    // Re-apply the parameters from Options after clearing the model. This picks up the
+    // periodic-error period length that was restored for the active optical train (and any
+    // other GPG option the user changed), so a freshly reset model starts guiding from the
+    // value stored for this particular mount/gear rather than a stale in-memory value.
+    updateParameters();
     qCDebug(KSTARS_EKOS_GUIDE) << "Resetting GPG";
 }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.