|
@@ -21,13 +21,13 @@
|
21
|
21
|
*/
|
22
|
22
|
|
23
|
23
|
/**
|
24
|
|
- * Least Squares Best Fit By Roxy and Ed Williams
|
|
24
|
+ * Least Squares Best Fit by Roxy and Ed Williams
|
25
|
25
|
*
|
26
|
26
|
* This algorithm is high speed and has a very small code footprint.
|
27
|
27
|
* Its results are identical to both the Iterative Least-Squares published
|
28
|
28
|
* earlier by Roxy and the QR_SOLVE solution. If used in place of QR_SOLVE
|
29
|
|
- * it saves roughly 10K of program memory. It also does not require all of
|
30
|
|
- * coordinates to be present during the calculations. Each point can be
|
|
29
|
+ * it saves roughly 10K of program memory. It also does not require all of
|
|
30
|
+ * coordinates to be present during the calculations. Each point can be
|
31
|
31
|
* probed and then discarded.
|
32
|
32
|
*
|
33
|
33
|
*/
|
|
@@ -41,56 +41,44 @@
|
41
|
41
|
|
42
|
42
|
#include "least_squares_fit.h"
|
43
|
43
|
|
44
|
|
-void incremental_LSF_reset(struct linear_fit_data *lsf) {
|
45
|
|
- lsf->n = 0;
|
46
|
|
- lsf->A = 0.0; // probably a memset() can be done to zero
|
47
|
|
- lsf->B = 0.0; // this whole structure
|
48
|
|
- lsf->D = 0.0;
|
49
|
|
- lsf->xbar = lsf->ybar = lsf->zbar = 0.0;
|
50
|
|
- lsf->x2bar = lsf->y2bar = lsf->z2bar = 0.0;
|
51
|
|
- lsf->xybar = lsf->xzbar = lsf->yzbar = 0.0;
|
52
|
|
- lsf->max_absx = lsf->max_absy = 0.0;
|
53
|
|
- }
|
|
44
|
+void incremental_LSF_reset(struct linear_fit_data *lsf) { ZERO(lsf); }
|
54
|
45
|
|
55
|
46
|
void incremental_LSF(struct linear_fit_data *lsf, float x, float y, float z) {
|
56
|
|
- lsf->xbar += x;
|
57
|
|
- lsf->ybar += y;
|
58
|
|
- lsf->zbar += z;
|
59
|
|
- lsf->x2bar += x*x;
|
60
|
|
- lsf->y2bar += y*y;
|
61
|
|
- lsf->z2bar += z*z;
|
62
|
|
- lsf->xybar += x*y;
|
63
|
|
- lsf->xzbar += x*z;
|
64
|
|
- lsf->yzbar += y*z;
|
65
|
|
- lsf->max_absx = (fabs(x) > lsf->max_absx) ? fabs(x) : lsf->max_absx;
|
66
|
|
- lsf->max_absy = (fabs(y) > lsf->max_absy) ? fabs(y) : lsf->max_absy;
|
67
|
|
- lsf->n++;
|
68
|
|
- return;
|
69
|
|
- }
|
|
47
|
+ lsf->xbar += x;
|
|
48
|
+ lsf->ybar += y;
|
|
49
|
+ lsf->zbar += z;
|
|
50
|
+ lsf->x2bar += sq(x);
|
|
51
|
+ lsf->y2bar += sq(y);
|
|
52
|
+ lsf->z2bar += sq(z);
|
|
53
|
+ lsf->xybar += sq(x);
|
|
54
|
+ lsf->xzbar += sq(x);
|
|
55
|
+ lsf->yzbar += sq(y);
|
|
56
|
+ lsf->max_absx = max(fabs(x), lsf->max_absx);
|
|
57
|
+ lsf->max_absy = max(fabs(y), lsf->max_absy);
|
|
58
|
+ lsf->n++;
|
|
59
|
+}
|
70
|
60
|
|
71
|
61
|
int finish_incremental_LSF(struct linear_fit_data *lsf) {
|
72
|
|
- float DD, N;
|
|
62
|
+ const float N = (float)lsf->n;
|
73
|
63
|
|
74
|
|
- N = (float) lsf->n;
|
75
|
|
- lsf->xbar /= N;
|
76
|
|
- lsf->ybar /= N;
|
77
|
|
- lsf->zbar /= N;
|
78
|
|
- lsf->x2bar = lsf->x2bar/N - lsf->xbar*lsf->xbar;
|
79
|
|
- lsf->y2bar = lsf->y2bar/N - lsf->ybar*lsf->ybar;
|
80
|
|
- lsf->z2bar = lsf->z2bar/N - lsf->zbar*lsf->zbar;
|
81
|
|
- lsf->xybar = lsf->xybar/N - lsf->xbar*lsf->ybar;
|
82
|
|
- lsf->yzbar = lsf->yzbar/N - lsf->ybar*lsf->zbar;
|
83
|
|
- lsf->xzbar = lsf->xzbar/N - lsf->xbar*lsf->zbar;
|
|
64
|
+ lsf->xbar /= N;
|
|
65
|
+ lsf->ybar /= N;
|
|
66
|
+ lsf->zbar /= N;
|
|
67
|
+ lsf->x2bar = lsf->x2bar / N - lsf->xbar * lsf->xbar;
|
|
68
|
+ lsf->y2bar = lsf->y2bar / N - lsf->ybar * lsf->ybar;
|
|
69
|
+ lsf->z2bar = lsf->z2bar / N - lsf->zbar * lsf->zbar;
|
|
70
|
+ lsf->xybar = lsf->xybar / N - lsf->xbar * lsf->ybar;
|
|
71
|
+ lsf->yzbar = lsf->yzbar / N - lsf->ybar * lsf->zbar;
|
|
72
|
+ lsf->xzbar = lsf->xzbar / N - lsf->xbar * lsf->zbar;
|
84
|
73
|
|
85
|
|
- DD = lsf->x2bar*lsf->y2bar - lsf->xybar*lsf->xybar;
|
86
|
|
- if (fabs(DD) <= 1e-10*(lsf->max_absx+lsf->max_absy))
|
87
|
|
- return -1;
|
88
|
|
-
|
89
|
|
- lsf->A = (lsf->yzbar*lsf->xybar - lsf->xzbar*lsf->y2bar) / DD;
|
90
|
|
- lsf->B = (lsf->xzbar*lsf->xybar - lsf->yzbar*lsf->x2bar) / DD;
|
91
|
|
- lsf->D = -(lsf->zbar + lsf->A*lsf->xbar + lsf->B*lsf->ybar);
|
92
|
|
- return 0;
|
93
|
|
-}
|
94
|
|
-#endif
|
|
74
|
+ const float DD = lsf->x2bar * lsf->y2bar - sq(lsf->xybar);
|
|
75
|
+ if (fabs(DD) <= 1e-10 * (lsf->max_absx + lsf->max_absy))
|
|
76
|
+ return -1;
|
95
|
77
|
|
|
78
|
+ lsf->A = (lsf->yzbar * lsf->xybar - lsf->xzbar * lsf->y2bar) / DD;
|
|
79
|
+ lsf->B = (lsf->xzbar * lsf->xybar - lsf->yzbar * lsf->x2bar) / DD;
|
|
80
|
+ lsf->D = -(lsf->zbar + lsf->A * lsf->xbar + lsf->B * lsf->ybar);
|
|
81
|
+ return 0;
|
|
82
|
+}
|
96
|
83
|
|
|
84
|
+#endif // AUTO_BED_LEVELING_UBL
|