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"
29 #include "common/vector.h"
32 #include "unittest_macros.h"
33 #include "gtest/gtest.h"
35 TEST(MathsUnittest
, TestConstrain
)
38 EXPECT_EQ(constrain(0, 0, 0), 0);
39 EXPECT_EQ(constrain(1, 1, 1), 1);
40 EXPECT_EQ(constrain(1, 0, 2), 1);
42 // Equal to bottom bound.
43 EXPECT_EQ(constrain(1, 1, 2), 1);
44 // Equal to top bound.
45 EXPECT_EQ(constrain(1, 0, 1), 1);
47 // Equal to both bottom and top bound.
48 EXPECT_EQ(constrain(1, 1, 1), 1);
51 EXPECT_EQ(constrain(2, 0, 1), 1);
52 // Below bottom bound.
53 EXPECT_EQ(constrain(0, 1, 2), 1);
56 TEST(MathsUnittest
, TestConstrainNegatives
)
59 EXPECT_EQ(constrain(-1, -1, -1), -1);
60 EXPECT_EQ(constrain(-1, -2, 0), -1);
62 // Equal to bottom bound.
63 EXPECT_EQ(constrain(-1, -1, 0), -1);
64 // Equal to top bound.
65 EXPECT_EQ(constrain(-1, -2, -1), -1);
67 // Equal to both bottom and top bound.
68 EXPECT_EQ(constrain(-1, -1, -1), -1);
71 EXPECT_EQ(constrain(-1, -3, -2), -2);
72 // Below bottom bound.
73 EXPECT_EQ(constrain(-3, -2, -1), -2);
76 TEST(MathsUnittest
, TestConstrainf
)
79 EXPECT_FLOAT_EQ(constrainf(1.0f
, 0.0f
, 2.0f
), 1.0f
);
81 // Equal to bottom bound.
82 EXPECT_FLOAT_EQ(constrainf(1.0f
, 1.0f
, 2.0f
), 1.0f
);
83 // Equal to top bound.
84 EXPECT_FLOAT_EQ(constrainf(1.0f
, 0.0f
, 1.0f
), 1.0f
);
86 // Equal to both bottom and top bound.
87 EXPECT_FLOAT_EQ(constrainf(1.0f
, 1.0f
, 1.0f
), 1.0f
);
90 EXPECT_FLOAT_EQ(constrainf(2.0f
, 0.0f
, 1.0f
), 1.0f
);
91 // Below bottom bound.
92 EXPECT_FLOAT_EQ(constrainf(0, 1.0f
, 2.0f
), 1.0f
);
94 // Above bouth bounds.
95 EXPECT_FLOAT_EQ(constrainf(2.0f
, 0.0f
, 1.0f
), 1.0f
);
96 // Below bouth bounds.
97 EXPECT_FLOAT_EQ(constrainf(0, 1.0f
, 2.0f
), 1.0f
);
100 TEST(MathsUnittest
, TestDegreesToRadians
)
102 EXPECT_FLOAT_EQ(degreesToRadians(0), 0.0f
);
103 EXPECT_FLOAT_EQ(degreesToRadians(90), 0.5f
* M_PIf
);
104 EXPECT_FLOAT_EQ(degreesToRadians(180), M_PIf
);
105 EXPECT_FLOAT_EQ(degreesToRadians(-180), - M_PIf
);
108 TEST(MathsUnittest
, TestApplyDeadband
)
110 EXPECT_EQ(applyDeadband(0, 0), 0);
111 EXPECT_EQ(applyDeadband(1, 0), 1);
112 EXPECT_EQ(applyDeadband(-1, 0), -1);
114 EXPECT_EQ(applyDeadband(0, 10), 0);
115 EXPECT_EQ(applyDeadband(1, 10), 0);
116 EXPECT_EQ(applyDeadband(10, 10), 0);
118 EXPECT_EQ(applyDeadband(11, 10), 1);
119 EXPECT_EQ(applyDeadband(-11, 10), -1);
122 void expectVectorsAreEqual(fpVector3_t
*a
, fpVector3_t
*b
)
124 EXPECT_FLOAT_EQ(a
->x
, b
->x
);
125 EXPECT_FLOAT_EQ(a
->y
, b
->y
);
126 EXPECT_FLOAT_EQ(a
->z
, b
->z
);
129 TEST(MathsUnittest
, TestRotateVectorWithNoAngle
)
131 fpVector3_t vector
= { .x
= 1.0f
, .y
= 0.0f
, .z
= 0.0f
};
132 fp_angles_t euler_angles
= {.raw
={0.0f
, 0.0f
, 0.0f
}};
135 rotationMatrixFromAngles(&rmat
, &euler_angles
);
136 rotationMatrixRotateVector(&vector
, &vector
, &rmat
);
138 fpVector3_t expected_result
= { .x
= 1.0f
, .y
= 0.0f
, .z
= 0.0f
};
139 expectVectorsAreEqual(&vector
, &expected_result
);
142 TEST(MathsUnittest
, TestRotateVectorAroundAxis
)
144 // Rotate a vector <1, 0, 0> around an each axis x y and z.
145 fpVector3_t vector
= { .x
= 1.0f
, .y
= 0.0f
, .z
= 0.0f
};
146 fp_angles_t euler_angles
= {.raw
={90.0f
, 0.0f
, 0.0f
}};
149 rotationMatrixFromAngles(&rmat
, &euler_angles
);
150 rotationMatrixRotateVector(&vector
, &vector
, &rmat
);
152 fpVector3_t expected_result
= { .x
= 1.0f
, .y
= 0.0f
, .z
= 0.0f
};
153 expectVectorsAreEqual(&vector
, &expected_result
);
156 #if defined(FAST_MATH) || defined(VERY_FAST_MATH)
157 TEST(MathsUnittest
, TestFastTrigonometrySinCos
)
159 EXPECT_NEAR(sin_approx(0.0f
), 0.0f
, 1e-6);
160 EXPECT_NEAR(sin_approx(M_PIf
/ 2), 1.0f
, 1e-6);
161 EXPECT_NEAR(sin_approx(-M_PIf
/ 2), -1.0f
, 1e-6);
162 EXPECT_NEAR(sin_approx(M_PIf
), 0.0f
, 1e-6);
163 EXPECT_NEAR(sin_approx(-M_PIf
), 0.0f
, 1e-6);
164 EXPECT_NEAR(sin_approx(3 * M_PIf
/ 2), -1.0f
, 1e-6);
165 EXPECT_NEAR(sin_approx(-3 * M_PIf
/ 2), 1.0f
, 1e-6);
166 EXPECT_NEAR(sin_approx(2 * M_PIf
), 0.0f
, 1e-6);
167 EXPECT_NEAR(sin_approx(-2 * M_PIf
), 0.0f
, 1e-6);
168 EXPECT_NEAR(sin_approx(3 * M_PIf
/ 4), 0.707106781f
, 1e-6);
169 EXPECT_NEAR(sin_approx(-3 * M_PIf
/ 4), -0.707106781f
, 1e-6);
170 EXPECT_NEAR(sin_approx(2 * M_PIf
+ 3 * M_PIf
/ 4), 0.707106781f
, 1e-6);
171 EXPECT_NEAR(sin_approx(-2 * M_PIf
- 3 * M_PIf
/ 4), -0.707106781f
, 1e-6);
173 EXPECT_NEAR(cos_approx(0.0f
), 1.0f
, 1e-6);
174 EXPECT_NEAR(cos_approx(M_PIf
/ 2), 0.0f
, 1e-6);
175 EXPECT_NEAR(cos_approx(-M_PIf
/ 2), 0.0f
, 1e-6);
176 EXPECT_NEAR(cos_approx(M_PIf
), -1.0f
, 1e-6);
177 EXPECT_NEAR(cos_approx(-M_PIf
), -1.0f
, 1e-6);
178 EXPECT_NEAR(cos_approx(3 * M_PIf
/ 2), 0.0f
, 1e-6);
179 EXPECT_NEAR(cos_approx(-3 * M_PIf
/ 2), 0.0f
, 1e-6);
180 EXPECT_NEAR(cos_approx(2 * M_PIf
), 1.0f
, 1e-6);
181 EXPECT_NEAR(cos_approx(-2 * M_PIf
), 1.0f
, 1e-6);
182 EXPECT_NEAR(cos_approx(3 * M_PIf
/ 4), -0.707106781f
, 1e-6);
183 EXPECT_NEAR(cos_approx(-3 * M_PIf
/ 4), -0.707106781f
, 1e-6);
184 EXPECT_NEAR(cos_approx(2 * M_PIf
+ 3 * M_PIf
/ 4), -0.707106781f
, 1e-6);
185 EXPECT_NEAR(cos_approx(-2 * M_PIf
- 3 * M_PIf
/ 4), -0.707106781f
, 1e-6);
188 TEST(MathsUnittest
, TestFastTrigonometryATan2
)
190 EXPECT_NEAR(atan2_approx(1, 1), M_PIf
/ 4, 1e-6);
191 EXPECT_NEAR(atan2_approx(-1, 1), -M_PIf
/ 4, 1e-6);
192 EXPECT_NEAR(atan2_approx(1, -1), 3 * M_PIf
/ 4, 1e-6);
193 EXPECT_NEAR(atan2_approx(-1, -1), -3 * M_PIf
/ 4, 1e-6);
194 EXPECT_NEAR(atan2_approx(0, 1), 0, 1e-6);
195 EXPECT_NEAR(atan2_approx(0, -1), M_PIf
, 1e-6);
196 EXPECT_NEAR(atan2_approx(1, 0), M_PIf
/ 2, 1e-6);
197 EXPECT_NEAR(atan2_approx(-1, 0), -M_PIf
/ 2, 1e-6);
200 TEST(MathsUnittest
, TestFastTrigonometryACos
)
202 EXPECT_NEAR(acos_approx(0.0f
), M_PIf
/ 2, 1e-4);
203 EXPECT_NEAR(acos_approx(1.0f
), 0, 1e-4);
204 EXPECT_NEAR(acos_approx(-1.0f
), M_PIf
, 1e-4);
205 EXPECT_NEAR(acos_approx(0.707106781f
), M_PIf
/ 4, 1e-4);
206 EXPECT_NEAR(acos_approx(-0.707106781f
), 3 * M_PIf
/ 4, 1e-4);
210 TEST(MathsUnittest, TestSensorScaleUnitTest)
212 sensorCalibrationState_t calState;
215 int16_t samples[6][3] = {
224 sensorCalibrationResetState(&calState);
225 sensorCalibrationPushSampleForScaleCalculation(&calState, 0, samples[0], 4096 );
226 sensorCalibrationPushSampleForScaleCalculation(&calState, 0, samples[1], 4096 );
227 sensorCalibrationPushSampleForScaleCalculation(&calState, 1, samples[2], 4096 );
228 sensorCalibrationPushSampleForScaleCalculation(&calState, 1, samples[3], 4096 );
229 sensorCalibrationPushSampleForScaleCalculation(&calState, 2, samples[4], 4096 );
230 sensorCalibrationPushSampleForScaleCalculation(&calState, 2, samples[5], 4096 );
231 sensorCalibrationSolveForScale(&calState, result);
233 EXPECT_NEAR(result[0], 1, 1e-4);
234 EXPECT_NEAR(result[1], 1, 1e-4);
235 EXPECT_NEAR(result[2], 1, 1e-4);