File indexing completed on 2024-05-05 15:55:13
0001 #include "polynomialfit.h" 0002 0003 #include "ekos/ekos.h" 0004 #include <gsl/gsl_fit.h> 0005 #include <gsl/gsl_vector.h> 0006 #include <gsl/gsl_min.h> 0007 #include <ekos_focus_debug.h> 0008 0009 namespace Ekos 0010 { 0011 0012 PolynomialFit::PolynomialFit(int degree_, uint8_t maxCount, const QVector<double> &x_, const QVector<double> &y_) 0013 : degree(degree_), x(x_), y(y_) 0014 { 0015 Q_ASSERT(x_.size() == y_.size()); 0016 QVector<QPointF> values; 0017 for (int i = 0; i < x.count(); i++) 0018 values << QPointF(x[i], y[i]); 0019 0020 std::sort(values.begin(), values.end(), [](const QPointF & a, const QPointF & b) 0021 { 0022 return a.y() < b.y(); 0023 }); 0024 0025 while(values.count() > maxCount) 0026 values.takeLast(); 0027 0028 x.clear(); 0029 y.clear(); 0030 0031 for (const auto &onePoint : values) 0032 { 0033 x << onePoint.x(); 0034 y << onePoint.y(); 0035 } 0036 0037 solve(x, y); 0038 } 0039 0040 PolynomialFit::PolynomialFit(int degree_, const QVector<int> &x_, const QVector<double> &y_) 0041 : degree(degree_), y(y_) 0042 { 0043 Q_ASSERT(x_.size() == y_.size()); 0044 for (int i = 0; i < x_.size(); ++i) 0045 { 0046 x.push_back(static_cast<double>(x_[i])); 0047 } 0048 solve(x, y); 0049 } 0050 0051 void PolynomialFit::solve(const QVector<double> &x, const QVector<double> &y) 0052 { 0053 double chisq = 0; 0054 coefficients = gsl_polynomial_fit(x.data(), y.data(), x.count(), degree, chisq); 0055 } 0056 0057 double PolynomialFit::polynomialFunction(double x, void *params) 0058 { 0059 PolynomialFit *instance = static_cast<PolynomialFit *>(params); 0060 0061 if (instance && !instance->coefficients.empty()) 0062 return instance->f(x); 0063 else 0064 return -1; 0065 } 0066 0067 double PolynomialFit::f(double x) 0068 { 0069 const int order = coefficients.size() - 1; 0070 double sum = 0; 0071 for (int i = 0; i <= order; ++i) 0072 sum += coefficients[i] * pow(x, i); 0073 return sum; 0074 } 0075 0076 bool PolynomialFit::findMinimum(double expected, double minPosition, double maxPosition, double *position, double *value) 0077 { 0078 int status; 0079 int iter = 0, max_iter = 100; 0080 const gsl_min_fminimizer_type *T; 0081 gsl_min_fminimizer *s; 0082 double m = expected; 0083 0084 gsl_function F; 0085 F.function = &PolynomialFit::polynomialFunction; 0086 F.params = this; 0087 0088 // Must turn off error handler or it aborts on error 0089 gsl_set_error_handler_off(); 0090 0091 T = gsl_min_fminimizer_brent; 0092 s = gsl_min_fminimizer_alloc(T); 0093 status = gsl_min_fminimizer_set(s, &F, expected, minPosition, maxPosition); 0094 0095 if (status != GSL_SUCCESS) 0096 { 0097 qCWarning(KSTARS_EKOS_FOCUS) << "Focus GSL error:" << gsl_strerror(status); 0098 return false; 0099 } 0100 0101 do 0102 { 0103 iter++; 0104 status = gsl_min_fminimizer_iterate(s); 0105 0106 m = gsl_min_fminimizer_x_minimum(s); 0107 minPosition = gsl_min_fminimizer_x_lower(s); 0108 maxPosition = gsl_min_fminimizer_x_upper(s); 0109 0110 status = gsl_min_test_interval(minPosition, maxPosition, 0.01, 0.0); 0111 0112 if (status == GSL_SUCCESS) 0113 { 0114 *position = m; 0115 *value = polynomialFunction(m, this); 0116 } 0117 } 0118 while (status == GSL_CONTINUE && iter < max_iter); 0119 0120 gsl_min_fminimizer_free(s); 0121 return (status == GSL_SUCCESS); 0122 } 0123 } // namespace 0124