diff --git a/kstars/ekos/focus/focus.ui b/kstars/ekos/focus/focus.ui
--- a/kstars/ekos/focus/focus.ui
+++ b/kstars/ekos/focus/focus.ui
@@ -1201,7 +1201,7 @@
-
- Linear (Experimental v2)
+ Linear (Experimental v3)
diff --git a/kstars/ekos/focus/focusalgorithms.cpp b/kstars/ekos/focus/focusalgorithms.cpp
--- a/kstars/ekos/focus/focusalgorithms.cpp
+++ b/kstars/ekos/focus/focusalgorithms.cpp
@@ -54,6 +54,9 @@
// Used in the 2nd pass. Focus is getting worse. Requires several consecutive samples getting worse.
bool gettingWorse();
+ // If one of the last 2 samples are as good or better than the 2nd best so far, return true.
+ bool bestSamplesHeuristic();
+
// Adds to the debug log a line summarizing the result of running this algorithm.
void debugLog();
@@ -122,7 +125,7 @@
secondPassStartIndex = -1;
qCDebug(KSTARS_EKOS_FOCUS)
- << QString("Linear: 1st pass. Travel %1 initStep %2 pos %3 min %4 max %5 maxIters %6 tolerance %7 minlimit %8 maxlimit %9")
+ << QString("Linear: v3. 1st pass. Travel %1 initStep %2 pos %3 min %4 max %5 maxIters %6 tolerance %7 minlimit %8 maxlimit %9")
.arg(params.maxTravel).arg(params.initialStepSize).arg(params.startPosition).arg(params.minPositionAllowed)
.arg(params.maxPositionAllowed).arg(params.maxIterations).arg(params.focusTolerance).arg(minPositionLimit).arg(maxPositionLimit);
@@ -157,25 +160,13 @@
const int nSteps = (start - end) / params.initialStepSize;
if (nSteps > params.maxIterations/2)
{
- const int topSize = start - position;
- const int bottomSize = position - end;
- if (topSize <= bottomSize)
- {
- const int newStart = position + params.initialStepSize * (params.maxIterations/4);
- start = std::min(newStart, maxPositionLimit);
- end = start - params.initialStepSize * (params.maxIterations/2);
- }
- else
- {
- const int newEnd = position - params.initialStepSize * (params.maxIterations/4);
- end = std::max(newEnd, minPositionLimit);
- start = end + params.initialStepSize * (params.maxIterations/2);
- }
+ const int newStart = position + params.initialStepSize * (params.maxIterations/6);
+ start = std::min(newStart, maxPositionLimit);
}
requestedPosition = start;
passStartPosition = requestedPosition;
- qCDebug(KSTARS_EKOS_FOCUS) << QString("Linear: initialPosition %1 end %2 steps %3 sized %4")
- .arg(start).arg(end).arg((start-end)/params.initialStepSize).arg(params.initialStepSize);
+ qCDebug(KSTARS_EKOS_FOCUS) << QString("Linear: initialPosition %1 sized %2")
+ .arg(start).arg(params.initialStepSize);
}
int LinearFocusAlgorithm::newMeasurement(int position, double value)
@@ -209,6 +200,7 @@
constexpr int kMinPolynomialPoints = 5;
constexpr int kNumPolySolutionsRequired = 3;
constexpr int kNumRestartSolutionsRequired = 3;
+ constexpr double kDecentValue = 2.5;
if (values.size() >= kMinPolynomialPoints)
{
@@ -225,14 +217,18 @@
numPolySolutionsFound = 0;
numRestartSolutionsFound = 0;
qCDebug(KSTARS_EKOS_FOCUS) << QString("Linear: Solutions reset %1 = %2").arg(minPos).arg(minVal);
- const int stepsToMin = distanceToMin / stepSize;
- // Temporarily increase the step size if the minimum is very far inward.
- if (stepsToMin >= 8)
- thisStepSize = stepSize * 4;
- else if (stepsToMin >= 4)
- thisStepSize = stepSize * 2;
+ if (value > kDecentValue)
+ {
+ // Only skip samples if the HFV values aren't very good.
+ const int stepsToMin = distanceToMin / stepSize;
+ // Temporarily increase the step size if the minimum is very far inward.
+ if (stepsToMin >= 8)
+ thisStepSize = stepSize * 4;
+ else if (stepsToMin >= 4)
+ thisStepSize = stepSize * 2;
+ }
}
- else
+ else if (!bestSamplesHeuristic())
{
// We have potentially passed the bottom of the curve,
// but it's possible it is further back than the start of our sweep.
@@ -254,12 +250,12 @@
if (numPolySolutionsFound >= kNumPolySolutionsRequired)
{
// We found a minimum. Setup the 2nd pass. We could use either the polynomial min or the
- // min measured star as the target HFR. Will use the min of both as I've seen using just
- // the polynomial minimum to be too conservative.
+ // min measured star as the target HFR. I've seen using the polynomial minimum to be
+ // sometimes too conservative, sometimes too low. For now using the min sample.
double minMeasurement = *std::min_element(values.begin(), values.end());
qCDebug(KSTARS_EKOS_FOCUS) << QString("Linear: 1stPass solution @ %1: pos %2 val %3, min measurement %4")
.arg(position).arg(minPos).arg(minVal).arg(minMeasurement);
- return setupSecondPass(static_cast(minPos), std::min(minVal, minMeasurement));
+ return setupSecondPass(static_cast(minPos), minMeasurement);
}
else if (numRestartSolutionsFound >= kNumRestartSolutionsRequired)
{
@@ -269,6 +265,7 @@
.arg(position).arg(minPos).arg(minVal).arg(requestedPosition);
return requestedPosition;
}
+
}
else
{
@@ -372,6 +369,19 @@
return requestedPosition;
}
+// Return true if one of the 2 recent samples is among the best 2 samples so far.
+bool LinearFocusAlgorithm::bestSamplesHeuristic()
+{
+ const int length = values.size();
+ if (length < 5) return true;
+ QVector tempValues = values;
+ std::nth_element(tempValues.begin(), tempValues.begin() + 2, tempValues.end());
+ double secondBest = tempValues[1];
+ if ((values[length-1] <= secondBest) || (values[length-2] <= secondBest))
+ return true;
+ return false;
+}
+
// Return true if there are "streak" consecutive values which are successively worse.
bool LinearFocusAlgorithm::gettingWorse()
{