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/>.
25 #include "build/debug.h"
27 #include "common/axis.h"
28 #include "common/maths.h"
30 #include "config/feature.h"
32 #include "pg/pg_ids.h"
35 #include "drivers/accgyro/accgyro.h"
36 #include "drivers/compass/compass.h"
37 #include "drivers/sensor.h"
39 #include "fc/rc_controls.h"
40 #include "fc/rc_modes.h"
41 #include "fc/runtime_config.h"
43 #include "flight/mixer.h"
44 #include "flight/pid.h"
45 #include "flight/imu.h"
46 #include "flight/position.h"
52 #include "sensors/acceleration.h"
53 #include "sensors/barometer.h"
54 #include "sensors/compass.h"
55 #include "sensors/gyro.h"
56 #include "sensors/sensors.h"
58 void imuComputeRotationMatrix(void);
59 void imuUpdateEulerAngles(void);
62 extern float rMat
[3][3];
63 extern bool attitudeIsEstablished
;
65 PG_REGISTER(rcControlsConfig_t
, rcControlsConfig
, PG_RC_CONTROLS_CONFIG
, 0);
66 PG_REGISTER(barometerConfig_t
, barometerConfig
, PG_BAROMETER_CONFIG
, 0);
68 PG_RESET_TEMPLATE(featureConfig_t
, featureConfig
,
73 #include "unittest_macros.h"
74 #include "gtest/gtest.h"
76 const float sqrt2over2
= sqrtf(2) / 2.0f
;
78 TEST(FlightImuTest
, TestCalculateRotationMatrix
)
88 imuComputeRotationMatrix();
90 EXPECT_FLOAT_EQ(1.0f
, rMat
[0][0]);
91 EXPECT_FLOAT_EQ(0.0f
, rMat
[0][1]);
92 EXPECT_FLOAT_EQ(0.0f
, rMat
[0][2]);
93 EXPECT_FLOAT_EQ(0.0f
, rMat
[1][0]);
94 EXPECT_FLOAT_EQ(1.0f
, rMat
[1][1]);
95 EXPECT_FLOAT_EQ(0.0f
, rMat
[1][2]);
96 EXPECT_FLOAT_EQ(0.0f
, rMat
[2][0]);
97 EXPECT_FLOAT_EQ(0.0f
, rMat
[2][1]);
98 EXPECT_FLOAT_EQ(1.0f
, rMat
[2][2]);
100 // 90 degrees around Z axis
106 imuComputeRotationMatrix();
108 EXPECT_NEAR(0.0f
, rMat
[0][0], TOL
);
109 EXPECT_NEAR(-1.0f
, rMat
[0][1], TOL
);
110 EXPECT_NEAR(0.0f
, rMat
[0][2], TOL
);
111 EXPECT_NEAR(1.0f
, rMat
[1][0], TOL
);
112 EXPECT_NEAR(0.0f
, rMat
[1][1], TOL
);
113 EXPECT_NEAR(0.0f
, rMat
[1][2], TOL
);
114 EXPECT_NEAR(0.0f
, rMat
[2][0], TOL
);
115 EXPECT_NEAR(0.0f
, rMat
[2][1], TOL
);
116 EXPECT_NEAR(1.0f
, rMat
[2][2], TOL
);
118 // 60 degrees around X axis
124 imuComputeRotationMatrix();
126 EXPECT_NEAR(1.0f
, rMat
[0][0], TOL
);
127 EXPECT_NEAR(0.0f
, rMat
[0][1], TOL
);
128 EXPECT_NEAR(0.0f
, rMat
[0][2], TOL
);
129 EXPECT_NEAR(0.0f
, rMat
[1][0], TOL
);
130 EXPECT_NEAR(0.5f
, rMat
[1][1], TOL
);
131 EXPECT_NEAR(-0.866f
, rMat
[1][2], TOL
);
132 EXPECT_NEAR(0.0f
, rMat
[2][0], TOL
);
133 EXPECT_NEAR(0.866f
, rMat
[2][1], TOL
);
134 EXPECT_NEAR(0.5f
, rMat
[2][2], TOL
);
137 TEST(FlightImuTest
, TestUpdateEulerAngles
)
140 memset(rMat
, 0.0, sizeof(float) * 9);
142 imuUpdateEulerAngles();
144 EXPECT_EQ(0, attitude
.values
.roll
);
145 EXPECT_EQ(0, attitude
.values
.pitch
);
146 EXPECT_EQ(0, attitude
.values
.yaw
);
149 memset(rMat
, 0.0, sizeof(float) * 9);
150 rMat
[0][0] = sqrt2over2
;
151 rMat
[0][1] = sqrt2over2
;
152 rMat
[1][0] = -sqrt2over2
;
153 rMat
[1][1] = sqrt2over2
;
155 imuUpdateEulerAngles();
157 EXPECT_EQ(0, attitude
.values
.roll
);
158 EXPECT_EQ(0, attitude
.values
.pitch
);
159 EXPECT_EQ(450, attitude
.values
.yaw
);
162 TEST(FlightImuTest
, TestSmallAngle
)
164 const float r1
= 0.898;
165 const float r2
= 0.438;
168 imuConfigMutable()->small_angle
= 25;
170 attitudeIsEstablished
= true;
173 memset(rMat
, 0.0, sizeof(float) * 9);
176 imuComputeRotationMatrix();
179 EXPECT_FALSE(isUpright());
188 imuComputeRotationMatrix();
191 EXPECT_FALSE(isUpright());
194 memset(rMat
, 0.0, sizeof(float) * 9);
197 imuComputeRotationMatrix();
200 EXPECT_FALSE(isUpright());
206 boxBitmask_t rcModeActivationMask
;
208 float rcData
[MAX_SUPPORTED_RC_CHANNEL_COUNT
];
214 gpsSolutionData_t gpsSol
;
215 int16_t GPS_verticalSpeedInCmS
;
218 int16_t debug
[DEBUG16_VALUE_COUNT
];
221 uint16_t flightModeFlags
;
224 pidProfile_t
*currentPidProfile
;
226 uint16_t enableFlightMode(flightModeFlags_e mask
) {
227 return flightModeFlags
|= (mask
);
230 uint16_t disableFlightMode(flightModeFlags_e mask
) {
231 return flightModeFlags
&= ~(mask
);
234 bool sensors(uint32_t mask
) {
235 return mask
& SENSOR_ACC
;
238 uint32_t millis(void) { return 0; }
239 uint32_t micros(void) { return 0; }
241 bool compassIsHealthy(void) { return true; }
242 bool baroIsCalibrated(void) { return true; }
243 void performBaroCalibrationCycle(void) {}
244 float baroCalculateAltitude(void) { return 0; }
245 bool gyroGetAccumulationAverage(float *) { return false; }
246 bool accGetAccumulationAverage(float *) { return false; }
247 void mixerSetThrottleAngleCorrection(int) {};
248 bool gpsRescueIsRunning(void) { return false; }
249 bool isFixedWing(void) { return false; }
250 void pinioBoxTaskControl(void) {}
251 void schedulerIgnoreTaskExecTime(void) {}
252 void schedulerIgnoreTaskStateTime(void) {}
253 void schedulerSetNextStateTime(timeDelta_t
) {}
254 bool schedulerGetIgnoreTaskExecTime() { return false; }
255 float gyroGetFilteredDownsampled(int) { return 0.0f
; }
256 float baroUpsampleAltitude() { return 0.0f
; }
257 float pt2FilterGain(float, float) { return 0.0f
; }
259 void pt2FilterInit(pt2Filter_t
*baroDerivativeLpf
, float) {
260 UNUSED(baroDerivativeLpf
);
262 float pt2FilterApply(pt2Filter_t
*baroDerivativeLpf
, float) {
263 UNUSED(baroDerivativeLpf
);