2 * This file is part of Cleanflight.
4 * Cleanflight is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * Cleanflight is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.
28 #include "common/maths.h"
31 #include "unittest_macros.h"
32 #include "gtest/gtest.h"
35 TEST(MathsUnittest
, TestScaleRange
)
38 EXPECT_EQ(scaleRange(0, 0, 10, 0, 100), 0);
39 EXPECT_EQ(scaleRange(10, 0, 10, 0, 100), 100);
40 EXPECT_EQ(scaleRange(0, 0, 100, 0, 10), 0);
41 EXPECT_EQ(scaleRange(100, 0, 100, 0, 10), 10);
44 EXPECT_EQ(scaleRange(1, 0, 10, 0, 100), 10);
45 EXPECT_EQ(scaleRange(2, 0, 10, 0, 100), 20);
46 EXPECT_EQ(scaleRange(5, 0, 10, 0, 100), 50);
49 EXPECT_EQ(scaleRange(10, 0, 100, 0, 10), 1);
50 EXPECT_EQ(scaleRange(20, 0, 100, 0, 10), 2);
51 EXPECT_EQ(scaleRange(50, 0, 100, 0, 10), 5);
54 TEST(MathsUnittest
, TestScaleRangeNegatives
)
57 EXPECT_EQ(scaleRange(0, -10, 0, -100, 0), 0);
58 EXPECT_EQ(scaleRange(-10, -10, 0, -100, 0), -100);
59 EXPECT_EQ(scaleRange(0, -100, 0, -10, 0), 0);
60 EXPECT_EQ(scaleRange(-100, -100, 0, -10, 0), -10);
63 EXPECT_EQ(scaleRange(-1, -10, 0, -100, 0), -10);
64 EXPECT_EQ(scaleRange(-2, -10, 0, -100, 0), -20);
65 EXPECT_EQ(scaleRange(-5, -10, 0, -100, 0), -50);
68 EXPECT_EQ(scaleRange(-10, -100, 0, -10, 0), -1);
69 EXPECT_EQ(scaleRange(-20, -100, 0, -10, 0), -2);
70 EXPECT_EQ(scaleRange(-50, -100, 0, -10, 0), -5);
73 TEST(MathsUnittest
, TestScaleRangeNegativePositive
)
76 EXPECT_EQ(scaleRange(0, -10, 0, 0, 100), 100);
77 EXPECT_EQ(scaleRange(-10, -10, 0, 0, 100), 0);
78 EXPECT_EQ(scaleRange(0, -100, 0, 0, 10), 10);
79 EXPECT_EQ(scaleRange(-100, -100, 0, 0, 10), 0);
82 EXPECT_EQ(scaleRange(-1, -10, 0, 0, 100), 90);
83 EXPECT_EQ(scaleRange(-2, -10, 0, 0, 100), 80);
84 EXPECT_EQ(scaleRange(-5, -10, 0, 0, 100), 50);
87 EXPECT_EQ(scaleRange(-10, -100, 0, 0, 10), 9);
88 EXPECT_EQ(scaleRange(-20, -100, 0, 0, 10), 8);
89 EXPECT_EQ(scaleRange(-50, -100, 0, 0, 10), 5);
92 TEST(MathsUnittest
, TestScaleRangeReverse
)
95 EXPECT_EQ(scaleRange(0, 0, 10, 100, 0), 100);
96 EXPECT_EQ(scaleRange(10, 0, 10, 100, 0), 0);
97 EXPECT_EQ(scaleRange(0, 0, 100, 10, 0), 10);
98 EXPECT_EQ(scaleRange(100, 0, 100, 10, 0), 0);
101 EXPECT_EQ(scaleRange(1, 0, 10, 100, 0), 90);
102 EXPECT_EQ(scaleRange(2, 0, 10, 100, 0), 80);
103 EXPECT_EQ(scaleRange(5, 0, 10, 100, 0), 50);
106 EXPECT_EQ(scaleRange(10, 0, 100, 10, 0), 9);
107 EXPECT_EQ(scaleRange(20, 0, 100, 10, 0), 8);
108 EXPECT_EQ(scaleRange(50, 0, 100, 10, 0), 5);
111 TEST(MathsUnittest
, TestConstrain
)
114 EXPECT_EQ(constrain(0, 0, 0), 0);
115 EXPECT_EQ(constrain(1, 1, 1), 1);
116 EXPECT_EQ(constrain(1, 0, 2), 1);
118 // Equal to bottom bound.
119 EXPECT_EQ(constrain(1, 1, 2), 1);
120 // Equal to top bound.
121 EXPECT_EQ(constrain(1, 0, 1), 1);
123 // Equal to both bottom and top bound.
124 EXPECT_EQ(constrain(1, 1, 1), 1);
127 EXPECT_EQ(constrain(2, 0, 1), 1);
128 // Below bottom bound.
129 EXPECT_EQ(constrain(0, 1, 2), 1);
132 TEST(MathsUnittest
, TestConstrainNegatives
)
135 EXPECT_EQ(constrain(-1, -1, -1), -1);
136 EXPECT_EQ(constrain(-1, -2, 0), -1);
138 // Equal to bottom bound.
139 EXPECT_EQ(constrain(-1, -1, 0), -1);
140 // Equal to top bound.
141 EXPECT_EQ(constrain(-1, -2, -1), -1);
143 // Equal to both bottom and top bound.
144 EXPECT_EQ(constrain(-1, -1, -1), -1);
147 EXPECT_EQ(constrain(-1, -3, -2), -2);
148 // Below bottom bound.
149 EXPECT_EQ(constrain(-3, -2, -1), -2);
152 TEST(MathsUnittest
, TestConstrainf
)
155 EXPECT_FLOAT_EQ(constrainf(1.0f
, 0.0f
, 2.0f
), 1.0f
);
157 // Equal to bottom bound.
158 EXPECT_FLOAT_EQ(constrainf(1.0f
, 1.0f
, 2.0f
), 1.0f
);
159 // Equal to top bound.
160 EXPECT_FLOAT_EQ(constrainf(1.0f
, 0.0f
, 1.0f
), 1.0f
);
162 // Equal to both bottom and top bound.
163 EXPECT_FLOAT_EQ(constrainf(1.0f
, 1.0f
, 1.0f
), 1.0f
);
166 EXPECT_FLOAT_EQ(constrainf(2.0f
, 0.0f
, 1.0f
), 1.0f
);
167 // Below bottom bound.
168 EXPECT_FLOAT_EQ(constrainf(0, 1.0f
, 2.0f
), 1.0f
);
170 // Above bouth bounds.
171 EXPECT_FLOAT_EQ(constrainf(2.0f
, 0.0f
, 1.0f
), 1.0f
);
172 // Below bouth bounds.
173 EXPECT_FLOAT_EQ(constrainf(0, 1.0f
, 2.0f
), 1.0f
);
176 TEST(MathsUnittest
, TestDegreesToRadians
)
178 EXPECT_FLOAT_EQ(degreesToRadians(0), 0.0f
);
179 EXPECT_FLOAT_EQ(degreesToRadians(90), 0.5f
* M_PIf
);
180 EXPECT_FLOAT_EQ(degreesToRadians(180), M_PIf
);
181 EXPECT_FLOAT_EQ(degreesToRadians(-180), - M_PIf
);
184 TEST(MathsUnittest
, TestApplyDeadband
)
186 EXPECT_EQ(applyDeadband(0, 0), 0);
187 EXPECT_EQ(applyDeadband(1, 0), 1);
188 EXPECT_EQ(applyDeadband(-1, 0), -1);
190 EXPECT_EQ(applyDeadband(0, 10), 0);
191 EXPECT_EQ(applyDeadband(1, 10), 0);
192 EXPECT_EQ(applyDeadband(10, 10), 0);
194 EXPECT_EQ(applyDeadband(11, 10), 1);
195 EXPECT_EQ(applyDeadband(-11, 10), -1);
198 void expectVectorsAreEqual(struct fp_vector
*a
, struct fp_vector
*b
, float absTol
)
200 EXPECT_NEAR(a
->X
, b
->X
, absTol
);
201 EXPECT_NEAR(a
->Y
, b
->Y
, absTol
);
202 EXPECT_NEAR(a
->Z
, b
->Z
, absTol
);
205 #if defined(FAST_MATH) || defined(VERY_FAST_MATH)
206 TEST(MathsUnittest
, TestFastTrigonometrySinCos
)
209 for (float x
= -10 * M_PI
; x
< 10 * M_PI
; x
+= M_PI
/ 300) {
210 float approxResult
= sin_approx(x
);
211 double libmResult
= sin(x
);
212 sinError
= MAX(sinError
, fabs(approxResult
- libmResult
));
214 printf("sin_approx maximum absolute error = %e\n", sinError
);
215 EXPECT_LE(sinError
, 3e-6);
218 for (float x
= -10 * M_PI
; x
< 10 * M_PI
; x
+= M_PI
/ 300) {
219 float approxResult
= cos_approx(x
);
220 double libmResult
= cos(x
);
221 cosError
= MAX(cosError
, fabs(approxResult
- libmResult
));
223 printf("cos_approx maximum absolute error = %e\n", cosError
);
224 EXPECT_LE(cosError
, 3.5e-6);
227 TEST(MathsUnittest
, TestFastTrigonometryATan2
)
230 for (float x
= -1.0f
; x
< 1.0f
; x
+= 0.01) {
231 for (float y
= -1.0f
; x
< 1.0f
; x
+= 0.001) {
232 float approxResult
= atan2_approx(y
, x
);
233 double libmResult
= atan2(y
, x
);
234 error
= MAX(error
, fabs(approxResult
- libmResult
));
237 printf("atan2_approx maximum absolute error = %e rads (%e degree)\n", error
, error
/ M_PI
* 180.0f
);
238 EXPECT_LE(error
, 1e-6);
241 TEST(MathsUnittest
, TestFastTrigonometryACos
)
244 for (float x
= -1.0f
; x
< 1.0f
; x
+= 0.001) {
245 float approxResult
= acos_approx(x
);
246 double libmResult
= acos(x
);
247 error
= MAX(error
, fabs(approxResult
- libmResult
));
249 printf("acos_approx maximum absolute error = %e rads (%e degree)\n", error
, error
/ M_PI
* 180.0f
);
250 EXPECT_LE(error
, 1e-4);