@@ -90,10 +90,10 @@ void EkfGpsHeadingTest::runConvergenceScenario(float yaw_offset_rad, float anten
90
90
checkConvergence (gps_heading, 0 .05f );
91
91
}
92
92
93
- void EkfGpsHeadingTest::checkConvergence (float truth, float tolerance )
93
+ void EkfGpsHeadingTest::checkConvergence (float truth, float tolerance_deg )
94
94
{
95
95
const float yaw_est = _ekf_wrapper.getYawAngle ();
96
- EXPECT_NEAR ( yaw_est, truth, math::radians (tolerance ))
96
+ EXPECT_LT ( fabsf ( matrix::wrap_pi ( yaw_est - truth)) , math::radians (tolerance_deg ))
97
97
<< " yaw est: " << math::degrees (yaw_est) << " gps yaw: " << math::degrees (truth);
98
98
}
99
99
@@ -213,7 +213,50 @@ TEST_F(EkfGpsHeadingTest, fallBackToMag)
213
213
EXPECT_EQ (_ekf_wrapper.getQuaternionResetCounter (), initial_quat_reset_counter + 1 );
214
214
}
215
215
216
- TEST_F (EkfGpsHeadingTest, yaw_jump_on_ground)
216
+ TEST_F (EkfGpsHeadingTest, fallBackToYawEmergencyEstimator)
217
+ {
218
+ // GIVEN: an initial GPS yaw, not aligned with the current one (e.g.: wrong orientation of the antenna array) and no mag.
219
+ _ekf_wrapper.setMagFuseTypeNone ();
220
+ _sensor_simulator.runSeconds (6 );
221
+
222
+ float gps_heading = math::radians (90 .f );
223
+ const float true_heading = math::radians (-20 .f );
224
+
225
+ _sensor_simulator._gps .setYaw (gps_heading);
226
+ _sensor_simulator.runSeconds (10 );
227
+
228
+ const Vector3f accel_frd{-1.0 , -1 .5f , 0 .f };
229
+ _sensor_simulator._imu .setAccelData (accel_frd + Vector3f (0 .f , 0 .f , -CONSTANTS_ONE_G));
230
+ const float dt = 0 .5f ;
231
+ const Dcmf R_to_earth{Eulerf (0 .f , 0 .f , true_heading)};
232
+
233
+ // needed to record takeoff time
234
+ _ekf->set_in_air_status (false );
235
+ _ekf->set_in_air_status (true );
236
+
237
+ // WHEN: The drone starts to accelerate
238
+ Vector3f simulated_velocity{};
239
+
240
+ for (int i = 0 ; i < 10 ; i++) {
241
+ _sensor_simulator.runSeconds (dt);
242
+
243
+ const Vector3f accel_ned = R_to_earth * accel_frd;
244
+
245
+ simulated_velocity += accel_ned * dt;
246
+ _sensor_simulator._gps .setVelocity (simulated_velocity);
247
+ }
248
+
249
+ // THEN: the yaw emergency detects the yaw issue,
250
+ // the GNSS yaw aiding is stopped and the heading
251
+ // is reset to the emergency yaw estimate
252
+ EXPECT_FALSE (_ekf_wrapper.isIntendingGpsHeadingFusion ());
253
+ EXPECT_FALSE (_ekf_wrapper.isIntendingMagHeadingFusion ());
254
+ EXPECT_TRUE (_ekf_wrapper.isIntendingGpsFusion ());
255
+
256
+ checkConvergence (true_heading, 5 .f );
257
+ }
258
+
259
+ TEST_F (EkfGpsHeadingTest, yawJmpOnGround)
217
260
{
218
261
// GIVEN: the GPS yaw fusion activated
219
262
float gps_heading = _ekf_wrapper.getYawAngle ();
@@ -233,7 +276,7 @@ TEST_F(EkfGpsHeadingTest, yaw_jump_on_ground)
233
276
EXPECT_LT (fabsf (matrix::wrap_pi (_ekf_wrapper.getYawAngle () - gps_heading)), math::radians (1 .f ));
234
277
}
235
278
236
- TEST_F (EkfGpsHeadingTest, yaw_jump_in_air )
279
+ TEST_F (EkfGpsHeadingTest, yawJumpInAir )
237
280
{
238
281
// GIVEN: the GPS yaw fusion activated
239
282
float gps_heading = _ekf_wrapper.getYawAngle ();
@@ -261,7 +304,7 @@ TEST_F(EkfGpsHeadingTest, yaw_jump_in_air)
261
304
EXPECT_TRUE (_ekf_wrapper.isIntendingMagHeadingFusion ());
262
305
}
263
306
264
- TEST_F (EkfGpsHeadingTest, stop_on_ground )
307
+ TEST_F (EkfGpsHeadingTest, stopOnGround )
265
308
{
266
309
// GIVEN: the GPS yaw fusion activated and there is no mag data
267
310
_sensor_simulator._mag .stop ();
0 commit comments