PX4 Firmware
PX4 Autopilot Software http://px4.io
polyfit.hpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (c) 2015-2016 PX4 Development Team. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  * 3. Neither the name PX4 nor the names of its contributors may be
16  * used to endorse or promote products derived from this software
17  * without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  *
32  ****************************************************************************/
33 
34 /*
35 
36 This algorithm performs a curve fit of m x,y data points using a polynomial
37 equation of the following form:
38 
39 yi = a0 + a1.xi + a2.xi^2 + a3.xi^3 + .... + an.xi^n + ei , where:
40 
41 i = [0,m]
42 xi is the x coordinate (independant variable) of the i'th measurement
43 yi is the y coordinate (dependant variable) of the i'th measurement
44 ei is a random fit error being the difference between the i'th y coordinate
45  and the value predicted by the polynomial.
46 
47 In vector form this is represented as:
48 
49 Y = V.A + E , where:
50 
51 V is Vandermonde matrix in x -> https://en.wikipedia.org/wiki/Vandermonde_matrix
52 Y is a vector of length m containing the y measurements
53 E is a vector of length m containing the fit errors for each measurement
54 
55 Use an Ordinary Least Squares derivation to minimise ∑(i=0..m)ei^2 -> https://en.wikipedia.org/wiki/Ordinary_least_squares
56 
57 Note: In the wikipedia reference, the X matrix in reference is equivalent to our V matrix and the Beta matrix is equivalent to our A matrix
58 
59 A = inv(transpose(V)*V)*(transpose(V)*Y)
60 
61 We can accumulate VTV and VTY recursively as they are of fixed size, where:
62 
63 VTV = transpose(V)*V =
64  __ __
65 | m+1 x0+x1+...+xm x0^2+x1^2+...+xm^3 .......... x0^n+x1^n+...+xm^n |
66 |x0+x1+...+xm x0^2+x1^2+...+xm^3 x0^3+x1^3+...+xm^3 .......... x0^(n+1)+x1^(n+1)+...+xm^(n+1) |
67 | . . . . |
68 | . . . . |
69 | . . . . |
70 |x0^n+x1^n+...+xm^n x0^(n+1)+x1^(n+1)+...+xm^(n+1) x0^(n+2)+x1^(n+2)+...+xm^(n+2) .... x0^(2n)+x1^(2n)+...+xm^(2n) |
71 |__ __|
72 
73 and VTY = transpose(V)*Y =
74  __ __
75 | ∑(i=0..m)yi |
76 | ∑(i=0..m)yi*xi |
77 | . |
78 | . |
79 | . |
80 |∑(i=0..m)yi*xi^n|
81 |__ __|
82 
83 */
84 
85 /*
86 Polygon linear fit
87 Author: Siddharth Bharat Purohit
88 */
89 
90 #pragma once
91 #include <px4_platform_common/px4_config.h>
92 #include <px4_platform_common/defines.h>
93 #include <px4_platform_common/tasks.h>
94 #include <px4_platform_common/posix.h>
95 #include <px4_platform_common/time.h>
96 #include <stdio.h>
97 #include <stdlib.h>
98 #include <string.h>
99 #include <unistd.h>
100 #include <fcntl.h>
101 #include <errno.h>
102 #include <math.h>
103 #include <poll.h>
104 #include <time.h>
105 #include <float.h>
106 #include <matrix/math.hpp>
107 
108 #define DEBUG 0
109 #if DEBUG
110 #define PF_DEBUG(fmt, ...) printf(fmt, ##__VA_ARGS__);
111 #else
112 #define PF_DEBUG(fmt, ...)
113 #endif
114 
115 template<int _forder>
117 {
118 public:
120 
121  void update(double x, double y)
122  {
123  update_VTV(x);
124  update_VTY(x, y);
125  }
126 
127  bool fit(double res[])
128  {
129  //Do inverse of VTV
131 
132  IVTV = _VTV.I();
133 
134  for (int i = 0; i < _forder; i++) {
135  for (int j = 0; j < _forder; j++) {
136  PF_DEBUG("%.10f ", (double)IVTV(i, j));
137  }
138 
139  PF_DEBUG("\n");
140  }
141 
142  for (int i = 0; i < _forder; i++) {
143  res[i] = 0.0;
144 
145  for (int j = 0; j < _forder; j++) {
146  res[i] += IVTV(i, j) * (double)_VTY(j);
147  }
148 
149  PF_DEBUG("%.10f ", res[i]);
150  }
151 
152  return true;
153  }
154 
155 private:
158 
159  void update_VTY(double x, double y)
160  {
161  double temp = 1.0;
162  PF_DEBUG("O %.6f\n", (double)x);
163 
164  for (int i = _forder - 1; i >= 0; i--) {
165  _VTY(i) += y * temp;
166  temp *= x;
167  PF_DEBUG("%.6f ", (double)_VTY(i));
168  }
169 
170  PF_DEBUG("\n");
171  }
172 
173  void update_VTV(double x)
174  {
175  double temp = 1.0;
176  int8_t z;
177 
178  for (int i = 0; i < _forder; i++) {
179  for (int j = 0; j < _forder; j++) {
180  PF_DEBUG("%.10f ", (double)_VTV(i, j));
181  }
182 
183  PF_DEBUG("\n");
184  }
185 
186  for (int i = 2 * _forder - 2; i >= 0; i--) {
187  if (i < _forder) {
188  z = 0.0f;
189 
190  } else {
191  z = i - _forder + 1;
192  }
193 
194  for (int j = i - z; j >= z; j--) {
195  int row = j;
196  int col = i - j;
197  _VTV(row, col) += (double)temp;
198  }
199 
200  temp *= x;
201  }
202  }
203 };
#define PF_DEBUG(fmt,...)
Definition: polyfit.hpp:112
matrix::Vector< double, _forder > _VTY
Definition: polyfit.hpp:157
bool fit(double res[])
Definition: polyfit.hpp:127
void update_VTY(double x, double y)
Definition: polyfit.hpp:159
SquareMatrix< Type, M > I() const
void update(double x, double y)
Definition: polyfit.hpp:121
void update_VTV(double x)
Definition: polyfit.hpp:173
matrix::SquareMatrix< double, _forder > _VTV
Definition: polyfit.hpp:156