Kstars
focusalgorithms.cpp
48 int newMeasurement(int position, double value, const double starWeight, const QList<Edge*> *stars) override;
52 void getMeasurements(QVector<int> *pos, QVector<double> *val, QVector<double> *sds) const override
59 void getPass1Measurements(QVector<int> *pos, QVector<double> *val, QVector<double> *sds, QVector<bool> *out) const override
76 if (params.focusAlgorithm == Focus::FOCUS_LINEAR || params.focusAlgorithm == Focus::FOCUS_LINEAR1PASS)
109 // Calc the next step size for Linear1Pass for FOCUS_WALK_FIXED_STEPS and FOCUS_WALK_CFZ_SHUFFLE
112 // Called when we've found a solution, e.g. the HFR value is within tolerance of the desired value.
113 // It it returns true, then it's decided tht we should try one more sample for a possible improvement.
141 // Used in the 2nd pass. Focus is getting worse. Requires several consecutive samples getting worse.
174 // The position where the first pass is begun. Usually requestedPosition unless there's a restart.
237 maxPositionLimit = std::min(params.maxPositionAllowed, params.startPosition + params.maxTravel);
238 minPositionLimit = std::max(params.minPositionAllowed, params.startPosition - params.maxTravel);
254 return QString("Pending: %1, %2").arg(solutionPendingPosition).arg(solutionPendingValue, 0, 'f', 2);
291 return text.append(" Solution: %1, R²=%2").arg(focusSolution).arg(trunc(R2 * 100.0) / 100.0, 0, 'f', 2);
313 << QString("Linear: Travel %1 initStep %2 pos %3 min %4 max %5 maxIters %6 tolerance %7 minlimit %8 maxlimit %9 init#steps %10 algo %11 backlash %12 curvefit %13 useweights %14")
314 .arg(params.maxTravel).arg(params.initialStepSize).arg(params.startPosition).arg(params.minPositionAllowed)
315 .arg(params.maxPositionAllowed).arg(params.maxIterations).arg(params.focusTolerance).arg(minPositionLimit)
316 .arg(maxPositionLimit).arg(params.initialOutwardSteps).arg(params.focusAlgorithm).arg(params.backlash)
327// For LINEAR1PASS most walks have a constant step size so again it is the number of outward points * step size.
328// For LINEAR1PASS and FOCUS_WALK_CFZ_SHUFFLE the middle 3 or 4 points are separated by half step size
332 return static_cast<int>(params.startPosition + params.initialOutwardSteps * params.initialStepSize);
340 firstPosition = static_cast<int>(params.startPosition + params.initialOutwardSteps * params.initialStepSize);
361 firstPosition = params.startPosition + (numFullStepsOut * params.initialStepSize) + (numHalfStepsOut *
367 firstPosition = static_cast<int>(params.startPosition + params.initialOutwardSteps * params.initialStepSize);
377// star detection scheme, two sets of star measurements may use different sets of actual stars to
380// relativeHFR tries to correct for this by comparing two sets of stars only using their common stars.
383// We maintain a reference set of stars, along with the HFR computed for those reference stars (bestRelativeHFR).
384// We find the common set of stars between an input star set and those reference stars. We compute
386// The ratio of those common-set HFRs multiply bestRelativeHFR to generate the relative HFR for this
387// input star set--that is, it's the HFR "relative to the reference set". E.g. if the common-set HFR
388// for the input stars is twice worse than that from the reference common stars, then the relative HFR
393// In unusual cases, e.g. when the common set can't be computed, we just return the input origHFR.
419 qCDebug(KSTARS_EKOS_FOCUS) << QString("Linear: Error: Inconsistent relativeHFR data structures, disabling.");
427 constexpr int starDistanceThreshold = 5; // Max distance (pixels) for two positions to be considered the same star.
476int LinearFocusAlgorithm::newMeasurement(int position, double value, const double starWeight, const QList<Edge*> *stars)
478 if (params.focusAlgorithm == Focus::FOCUS_LINEAR1PASS && (params.focusWalk == Focus::FOCUS_WALK_FIXED_STEPS
488 // should be the same. For now, we will use the full set of stars and therefore not adjust the HFR
581 params.curveFitting->fitCurve(goal, positions, values, weights, pass1Outliers, params.curveFit, params.useWeights,
584 foundFit = params.curveFitting->findMinMax(position, 0, params.maxPositionAllowed, &minPos, &minVal,
599 qCDebug(KSTARS_EKOS_FOCUS) << QString("Linear: Solutions reset %1 = %2").arg(minPos).arg(minVal);
601 // The next code block is an optimisation where the user starts focus off a long way from prime focus.
603 // However, when the solver is solving on a small number of points (e.g. 6 or 7) its possible that the
604 // best fit curve produces a solution much further in than what turns out to be the actual focus point.
636 // The LINEAR algo goes >2 steps past the minimum. The LINEAR 1 PASS algo uses the InitialOutwardSteps parameter
637 // in order to have some user control over the number of steps past the minimum when fitting the curve.
638 // With LINEAR 1 PASS setupSecondPass with a margin of 0.0 as no need to move the focuser further
639 // This will result in a step out, past the solution of either "backlash" id set, or 5 * step size, followed
653 qCDebug(KSTARS_EKOS_FOCUS) << QString("Linear: 1stPass solution @ %1: pos %2 val %3, min measurement %4")
670 // If the min position from the polynomial solution is not too far from the current start position
672 const double highestStartPosition = params.startPosition + params.initialOutwardSteps * params.initialStepSize;
675 qCDebug(KSTARS_EKOS_FOCUS) << QString("Linear: Restart. Current pos %1, min pos %2, min val %3, re-starting at %4")
685 // happen with noisy data and perhaps small step sizes. We still might be able to take advantage,
744// Process next step for LINEAR1PASS for walks: FOCUS_WALK_FIXED_STEPS and FOCUS_WALK_CFZ_SHUFFLE
761 qCDebug(KSTARS_EKOS_FOCUS) << QString("linearWalk error: position %1, requested position %2").arg(position)
791 params.curveFitting->fitCurve(goal, positions, values, weights, pass1Outliers, params.curveFit, params.useWeights,
794 foundFit = params.curveFitting->findMinMax(position, 0, params.maxPositionAllowed, &minPos, &minVal,
824// 3. Move outwards on each side of the minimum checking the next datapoint. If value drops this could be bad data
869 // Starting at the furthest outward point, move inward to minimum point, marking bad data (donuts) as outliers
894 // Starting at the furthest outward point, move inward to minimum point, marking bad data (donuts) as outliers
911// Function to calculate the next step size for LINEAR1PASS for walks: FOCUS_WALK_FIXED_STEPS and FOCUS_WALK_CFZ_SHUFFLE
968 str.append(QString("%1 = %2 (expected %3) delta=%4").arg(position).arg(value).arg(firstPassBestValue).arg(delta));
981 str.append(QString(". POOR result. If this happens repeatedly it may be a sign of poor backlash compensation."));
990int LinearFocusAlgorithm::completeIteration(int step, bool foundFit, double minPos, double minVal)
994 // If we're close to exceeding the iteration limit, retry this pass near the old minimum position.
995 // For Linear 1 Pass we are still in the first pass so no point retrying the 2nd pass. Just carry on and
997 const int minIndex = static_cast<int>(std::min_element(values.begin(), values.end()) - values.begin());
1020 const int minIndex = static_cast<int>(std::min_element(values.begin(), values.end()) - values.begin());
1021 qCDebug(KSTARS_EKOS_FOCUS) << QString("Linear: reached end without Vmin. Restarting %1 pos %2 value %3")
1032 // We can't travel far enough to find a solution so fail as focuser parameters require user attention
1042 qCDebug(KSTARS_EKOS_FOCUS) << QString("Linear: requesting position %1").arg(requestedPosition);
1067 // NotGettingWorse: not worse than the previous (non-repeat) 2nd pass sample, or the 1st 2nd pass sample.
1071 const bool couldGoFather = (numSteps < params.maxIterations - 2) && (position - stepSize > minPositionLimit);
1073 // Allow passing the 1st pass' minimum HFR position, but take smaller steps and don't retry as much.
1084 << QString("Linear: %1: Position(%2) & HFR(%3) -- Pass1: %4 %5, solution pending, searching further")
1085 .arg(length).arg(position).arg(thisValue, 0, 'f', 3).arg(firstPassBestPosition).arg(firstPassBestValue, 0, 'f', 3);
1096 << QString("Linear: %1: Position(%2) & HFR(%3) -- Pass1: %4 %5, solution pending, got worse, retrying")
1097 .arg(length).arg(position).arg(thisValue, 0, 'f', 3).arg(firstPassBestPosition).arg(firstPassBestValue, 0, 'f', 3);
1104 .arg(length).arg(position).arg(thisValue, 0, 'f', 3).arg(firstPassBestPosition).arg(firstPassBestValue, 0, 'f', 3);
1143 requestedPosition = std::min(static_cast<int>(firstPassBestPosition + stepSize * margin), maxPositionLimit);
1145 qCDebug(KSTARS_EKOS_FOCUS) << QString("Linear: 2ndPass starting at %1 step %2").arg(requestedPosition).arg(stepSize);
1173 auto curveDeltasX2Mean = Mathematics::RobustStatistics::ComputeLocation(Mathematics::RobustStatistics::LOCATION_MEAN,
1185 double pc = peirce_criterion(static_cast<double>(curveDeltas.size()), static_cast<double>(maxOutliers), modelUnknowns);
1219 double currentR2 = params.curveFitting->calculateR2(static_cast<CurveFitting::CurveFit>(params.curveFit));
1222 params.curveFitting->fitCurve(CurveFitting::FittingGoal::BEST, pass1Positions, pass1Values, pass1Weights,
1225 bool foundFit = params.curveFitting->findMinMax(position, 0, params.maxPositionAllowed, &minPos, &minVal,
1230 double newR2 = params.curveFitting->calculateR2(static_cast<CurveFitting::CurveFit>(params.curveFit));
1235 qCDebug(KSTARS_EKOS_FOCUS) << QString("Refine Curve Fit improved focus from %1 to %2. R2 improved from %3 to %4")
1250 QString("Refine Curve Fit failed to fit curve whilst refining curve fit. Running with original solution");
1261// See https://en.wikipedia.org/wiki/Peirce%27s_criterion for details incl Peirce's original paper
1262// and Gould's paper both referenced in the notes. The wikipedia entry also includes some code fragments
QString i18n(const char *text, const TYPE &arg...)
QString & append(QChar ch)
QString arg(Args &&... args) const const
void push_back(QChar ch)
qsizetype size() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:19:02 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:19:02 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.