47 #include <px4_platform_common/defines.h> 48 #include <px4_platform_common/module.h> 49 #include <px4_platform_common/module_params.h> 50 #include <px4_platform_common/posix.h> 51 #include <px4_platform_common/px4_work_queue/ScheduledWorkItem.hpp> 52 #include <px4_platform_common/time.h> 84 #define BLEND_MASK_USE_SPD_ACC 1 85 #define BLEND_MASK_USE_HPOS_ACC 2 86 #define BLEND_MASK_USE_VPOS_ACC 4 89 #define GPS_MAX_RECEIVERS 2 90 #define GPS_BLENDED_INSTANCE 2 95 class Ekf2 final :
public ModuleBase<Ekf2>,
public ModuleParams,
public px4::WorkItem
98 explicit Ekf2(
bool replay_mode =
false);
102 static int task_spawn(
int argc,
char *argv[]);
105 static int custom_command(
int argc,
char *argv[]);
108 static int print_usage(
const char *reason =
nullptr);
117 int getRangeSubIndex();
124 void resetPreFlightChecks();
126 template<
typename Param>
127 void update_mag_bias(Param &mag_bias_param,
int axis_index);
129 template<
typename Param>
130 bool update_mag_decl(Param &mag_decl_param);
133 bool publish_wind_estimate(
const hrt_abstime ×tamp);
143 bool blend_gps_data();
150 void update_gps_blend_states();
157 void update_gps_offsets();
162 void apply_gps_offsets();
167 void calc_gps_blend_output();
172 float filter_altitude_ellipsoid(
float amsl_hgt);
177 uint64_t _integrated_time_us = 0;
178 uint64_t _start_time_us = 0;
179 int64_t _last_time_slip_us = 0;
184 uint8_t _invalid_mag_id_count = 0;
187 float _mag_data_sum[3] = {};
188 uint64_t _mag_time_sum_ms = 0;
189 uint8_t _mag_sample_count = 0;
190 int32_t _mag_time_ms_last_used = 0;
193 float _balt_data_sum = 0.0f;
194 uint64_t _balt_time_sum_ms = 0;
195 uint8_t _balt_sample_count = 0;
196 uint32_t _balt_time_ms_last_used =
203 float _last_valid_mag_cal[3] = {};
204 bool _valid_cal_available[3] = {};
205 float _last_valid_variance[3] = {};
208 bool _mag_decl_saved =
false;
212 static constexpr
float ep_max_std_dev = 100.0f;
213 static constexpr
float eo_max_std_dev = 100.0f;
225 uint8_t _gps_best_index = 0;
226 uint8_t _gps_select_index = 0;
227 uint8_t _gps_time_ref_index =
229 uint8_t _gps_oldest_index = 0;
230 uint8_t _gps_newest_index = 0;
231 uint8_t _gps_slowest_index = 0;
233 bool _gps_new_output_data =
false;
234 bool _had_valid_terrain =
false;
238 float _wgs84_hgt_offset = 0;
240 bool _imu_bias_reset_request{
false};
243 bool new_ev_data_received =
false;
261 int _range_finder_sub_index = -1;
288 (ParamExtInt<px4::params::EKF2_MIN_OBS_DT>)
289 _param_ekf2_min_obs_dt,
290 (ParamExtFloat<px4::params::EKF2_MAG_DELAY>)
291 _param_ekf2_mag_delay,
292 (ParamExtFloat<px4::params::EKF2_BARO_DELAY>)
293 _param_ekf2_baro_delay,
294 (ParamExtFloat<px4::params::EKF2_GPS_DELAY>)
295 _param_ekf2_gps_delay,
296 (ParamExtFloat<px4::params::EKF2_OF_DELAY>)
297 _param_ekf2_of_delay,
298 (ParamExtFloat<px4::params::EKF2_RNG_DELAY>)
299 _param_ekf2_rng_delay,
300 (ParamExtFloat<px4::params::EKF2_ASP_DELAY>)
301 _param_ekf2_asp_delay,
302 (ParamExtFloat<px4::params::EKF2_EV_DELAY>)
303 _param_ekf2_ev_delay,
304 (ParamExtFloat<px4::params::EKF2_AVEL_DELAY>)
305 _param_ekf2_avel_delay,
307 (ParamExtFloat<px4::params::EKF2_GYR_NOISE>)
308 _param_ekf2_gyr_noise,
309 (ParamExtFloat<px4::params::EKF2_ACC_NOISE>)
310 _param_ekf2_acc_noise,
313 (ParamExtFloat<px4::params::EKF2_GYR_B_NOISE>)
314 _param_ekf2_gyr_b_noise,
315 (ParamExtFloat<px4::params::EKF2_ACC_B_NOISE>)
316 _param_ekf2_acc_b_noise,
317 (ParamExtFloat<px4::params::EKF2_MAG_E_NOISE>)
318 _param_ekf2_mag_e_noise,
319 (ParamExtFloat<px4::params::EKF2_MAG_B_NOISE>)
320 _param_ekf2_mag_b_noise,
321 (ParamExtFloat<px4::params::EKF2_WIND_NOISE>)
322 _param_ekf2_wind_noise,
323 (ParamExtFloat<px4::params::EKF2_TERR_NOISE>) _param_ekf2_terr_noise,
324 (ParamExtFloat<px4::params::EKF2_TERR_GRAD>)
325 _param_ekf2_terr_grad,
327 (ParamExtFloat<px4::params::EKF2_GPS_V_NOISE>)
328 _param_ekf2_gps_v_noise,
329 (ParamExtFloat<px4::params::EKF2_GPS_P_NOISE>)
330 _param_ekf2_gps_p_noise,
331 (ParamExtFloat<px4::params::EKF2_NOAID_NOISE>)
332 _param_ekf2_noaid_noise,
333 (ParamExtFloat<px4::params::EKF2_BARO_NOISE>)
334 _param_ekf2_baro_noise,
335 (ParamExtFloat<px4::params::EKF2_BARO_GATE>)
336 _param_ekf2_baro_gate,
337 (ParamExtFloat<px4::params::EKF2_GND_EFF_DZ>)
338 _param_ekf2_gnd_eff_dz,
339 (ParamExtFloat<px4::params::EKF2_GND_MAX_HGT>)
340 _param_ekf2_gnd_max_hgt,
341 (ParamExtFloat<px4::params::EKF2_GPS_P_GATE>)
342 _param_ekf2_gps_p_gate,
343 (ParamExtFloat<px4::params::EKF2_GPS_V_GATE>)
344 _param_ekf2_gps_v_gate,
345 (ParamExtFloat<px4::params::EKF2_TAS_GATE>)
346 _param_ekf2_tas_gate,
349 (ParamExtFloat<px4::params::EKF2_HEAD_NOISE>)
350 _param_ekf2_head_noise,
351 (ParamExtFloat<px4::params::EKF2_MAG_NOISE>)
352 _param_ekf2_mag_noise,
353 (ParamExtFloat<px4::params::EKF2_EAS_NOISE>)
354 _param_ekf2_eas_noise,
355 (ParamExtFloat<px4::params::EKF2_BETA_GATE>)
356 _param_ekf2_beta_gate,
357 (ParamExtFloat<px4::params::EKF2_BETA_NOISE>) _param_ekf2_beta_noise,
358 (ParamExtFloat<px4::params::EKF2_MAG_DECL>) _param_ekf2_mag_decl,
359 (ParamExtFloat<px4::params::EKF2_HDG_GATE>)
360 _param_ekf2_hdg_gate,
361 (ParamExtFloat<px4::params::EKF2_MAG_GATE>)
362 _param_ekf2_mag_gate,
363 (ParamExtInt<px4::params::EKF2_DECL_TYPE>)
364 _param_ekf2_decl_type,
365 (ParamExtInt<px4::params::EKF2_MAG_TYPE>)
366 _param_ekf2_mag_type,
367 (ParamExtFloat<px4::params::EKF2_MAG_ACCLIM>)
368 _param_ekf2_mag_acclim,
369 (ParamExtFloat<px4::params::EKF2_MAG_YAWLIM>)
370 _param_ekf2_mag_yawlim,
372 (ParamExtInt<px4::params::EKF2_GPS_CHECK>)
373 _param_ekf2_gps_check,
374 (ParamExtFloat<px4::params::EKF2_REQ_EPH>) _param_ekf2_req_eph,
375 (ParamExtFloat<px4::params::EKF2_REQ_EPV>) _param_ekf2_req_epv,
376 (ParamExtFloat<px4::params::EKF2_REQ_SACC>) _param_ekf2_req_sacc,
377 (ParamExtInt<px4::params::EKF2_REQ_NSATS>) _param_ekf2_req_nsats,
378 (ParamExtFloat<px4::params::EKF2_REQ_PDOP>)
379 _param_ekf2_req_pdop,
380 (ParamExtFloat<px4::params::EKF2_REQ_HDRIFT>)
381 _param_ekf2_req_hdrift,
382 (ParamExtFloat<px4::params::EKF2_REQ_VDRIFT>) _param_ekf2_req_vdrift,
385 (ParamExtInt<px4::params::EKF2_AID_MASK>)
386 _param_ekf2_aid_mask,
387 (ParamExtInt<px4::params::EKF2_HGT_MODE>) _param_ekf2_hgt_mode,
388 (ParamExtInt<px4::params::EKF2_NOAID_TOUT>)
389 _param_ekf2_noaid_tout,
392 (ParamExtFloat<px4::params::EKF2_RNG_NOISE>)
393 _param_ekf2_rng_noise,
394 (ParamExtFloat<px4::params::EKF2_RNG_SFE>) _param_ekf2_rng_sfe,
395 (ParamExtFloat<px4::params::EKF2_RNG_GATE>)
396 _param_ekf2_rng_gate,
397 (ParamExtFloat<px4::params::EKF2_MIN_RNG>) _param_ekf2_min_rng,
398 (ParamExtFloat<px4::params::EKF2_RNG_PITCH>) _param_ekf2_rng_pitch,
399 (ParamExtInt<px4::params::EKF2_RNG_AID>)
401 (ParamExtFloat<px4::params::EKF2_RNG_A_VMAX>)
402 _param_ekf2_rng_a_vmax,
403 (ParamExtFloat<px4::params::EKF2_RNG_A_HMAX>)
404 _param_ekf2_rng_a_hmax,
405 (ParamExtFloat<px4::params::EKF2_RNG_A_IGATE>)
406 _param_ekf2_rng_a_igate,
409 (ParamInt<px4::params::EKF2_EV_NOISE_MD>)
410 _param_ekf2_ev_noise_md,
411 (ParamFloat<px4::params::EKF2_EVP_NOISE>)
412 _param_ekf2_evp_noise,
413 (ParamFloat<px4::params::EKF2_EVV_NOISE>)
414 _param_ekf2_evv_noise,
415 (ParamFloat<px4::params::EKF2_EVA_NOISE>)
416 _param_ekf2_eva_noise,
417 (ParamExtFloat<px4::params::EKF2_EVV_GATE>)
418 _param_ekf2_evv_gate,
419 (ParamExtFloat<px4::params::EKF2_EVP_GATE>)
420 _param_ekf2_evp_gate,
423 (ParamExtFloat<px4::params::EKF2_OF_N_MIN>)
424 _param_ekf2_of_n_min,
425 (ParamExtFloat<px4::params::EKF2_OF_N_MAX>)
426 _param_ekf2_of_n_max,
427 (ParamExtInt<px4::params::EKF2_OF_QMIN>)
429 (ParamExtFloat<px4::params::EKF2_OF_GATE>)
433 (ParamExtFloat<px4::params::EKF2_IMU_POS_X>) _param_ekf2_imu_pos_x,
434 (ParamExtFloat<px4::params::EKF2_IMU_POS_Y>) _param_ekf2_imu_pos_y,
435 (ParamExtFloat<px4::params::EKF2_IMU_POS_Z>) _param_ekf2_imu_pos_z,
436 (ParamExtFloat<px4::params::EKF2_GPS_POS_X>) _param_ekf2_gps_pos_x,
437 (ParamExtFloat<px4::params::EKF2_GPS_POS_Y>) _param_ekf2_gps_pos_y,
438 (ParamExtFloat<px4::params::EKF2_GPS_POS_Z>) _param_ekf2_gps_pos_z,
439 (ParamExtFloat<px4::params::EKF2_RNG_POS_X>) _param_ekf2_rng_pos_x,
440 (ParamExtFloat<px4::params::EKF2_RNG_POS_Y>) _param_ekf2_rng_pos_y,
441 (ParamExtFloat<px4::params::EKF2_RNG_POS_Z>) _param_ekf2_rng_pos_z,
442 (ParamExtFloat<px4::params::EKF2_OF_POS_X>)
443 _param_ekf2_of_pos_x,
444 (ParamExtFloat<px4::params::EKF2_OF_POS_Y>)
445 _param_ekf2_of_pos_y,
446 (ParamExtFloat<px4::params::EKF2_OF_POS_Z>)
447 _param_ekf2_of_pos_z,
448 (ParamExtFloat<px4::params::EKF2_EV_POS_X>)
449 _param_ekf2_ev_pos_x,
450 (ParamExtFloat<px4::params::EKF2_EV_POS_Y>)
451 _param_ekf2_ev_pos_y,
452 (ParamExtFloat<px4::params::EKF2_EV_POS_Z>)
453 _param_ekf2_ev_pos_z,
456 (ParamFloat<px4::params::EKF2_ARSP_THR>)
457 _param_ekf2_arsp_thr,
458 (ParamInt<px4::params::EKF2_FUSE_BETA>)
459 _param_ekf2_fuse_beta,
462 (ParamExtFloat<px4::params::EKF2_TAU_VEL>)
464 (ParamExtFloat<px4::params::EKF2_TAU_POS>)
468 (ParamExtFloat<px4::params::EKF2_GBIAS_INIT>)
469 _param_ekf2_gbias_init,
470 (ParamExtFloat<px4::params::EKF2_ABIAS_INIT>)
471 _param_ekf2_abias_init,
472 (ParamExtFloat<px4::params::EKF2_ANGERR_INIT>)
473 _param_ekf2_angerr_init,
476 (ParamFloat<px4::params::EKF2_MAGBIAS_X>) _param_ekf2_magbias_x,
477 (ParamFloat<px4::params::EKF2_MAGBIAS_Y>) _param_ekf2_magbias_y,
478 (ParamFloat<px4::params::EKF2_MAGBIAS_Z>) _param_ekf2_magbias_z,
479 (ParamInt<px4::params::EKF2_MAGBIAS_ID>)
480 _param_ekf2_magbias_id,
481 (ParamFloat<px4::params::EKF2_MAGB_VREF>)
482 _param_ekf2_magb_vref,
483 (ParamFloat<px4::params::EKF2_MAGB_K>)
487 (ParamExtFloat<px4::params::EKF2_ABL_LIM>) _param_ekf2_abl_lim,
488 (ParamExtFloat<px4::params::EKF2_ABL_ACCLIM>)
489 _param_ekf2_abl_acclim,
490 (ParamExtFloat<px4::params::EKF2_ABL_GYRLIM>)
491 _param_ekf2_abl_gyrlim,
492 (ParamExtFloat<px4::params::EKF2_ABL_TAU>)
496 (ParamExtFloat<px4::params::EKF2_DRAG_NOISE>)
497 _param_ekf2_drag_noise,
498 (ParamExtFloat<px4::params::EKF2_BCOEF_X>) _param_ekf2_bcoef_x,
499 (ParamExtFloat<px4::params::EKF2_BCOEF_Y>) _param_ekf2_bcoef_y,
503 (ParamFloat<px4::params::EKF2_ASPD_MAX>)
504 _param_ekf2_aspd_max,
505 (ParamFloat<px4::params::EKF2_PCOEF_XP>)
506 _param_ekf2_pcoef_xp,
507 (ParamFloat<px4::params::EKF2_PCOEF_XN>)
508 _param_ekf2_pcoef_xn,
509 (ParamFloat<px4::params::EKF2_PCOEF_YP>)
510 _param_ekf2_pcoef_yp,
511 (ParamFloat<px4::params::EKF2_PCOEF_YN>)
512 _param_ekf2_pcoef_yn,
513 (ParamFloat<px4::params::EKF2_PCOEF_Z>)
517 (ParamInt<px4::params::EKF2_GPS_MASK>)
518 _param_ekf2_gps_mask,
519 (ParamFloat<px4::params::EKF2_GPS_TAU>)
523 (ParamExtFloat<px4::params::EKF2_MOVE_TEST>)
524 _param_ekf2_move_test,
526 (ParamFloat<px4::params::EKF2_REQ_GPS_H>) _param_ekf2_req_gps_h,
527 (ParamExtInt<px4::params::EKF2_MAG_CHECK>) _param_ekf2_mag_check
534 ModuleParams(nullptr),
535 WorkItem(MODULE_NAME,
px4::wq_configurations::att_pos_ctrl),
536 _replay_mode(replay_mode),
538 _params(_ekf.getParamHandle()),
539 _param_ekf2_min_obs_dt(_params->sensor_interval_min_ms),
540 _param_ekf2_mag_delay(_params->mag_delay_ms),
541 _param_ekf2_baro_delay(_params->baro_delay_ms),
542 _param_ekf2_gps_delay(_params->gps_delay_ms),
543 _param_ekf2_of_delay(_params->flow_delay_ms),
544 _param_ekf2_rng_delay(_params->range_delay_ms),
545 _param_ekf2_asp_delay(_params->airspeed_delay_ms),
546 _param_ekf2_ev_delay(_params->ev_delay_ms),
547 _param_ekf2_avel_delay(_params->auxvel_delay_ms),
548 _param_ekf2_gyr_noise(_params->gyro_noise),
549 _param_ekf2_acc_noise(_params->accel_noise),
550 _param_ekf2_gyr_b_noise(_params->gyro_bias_p_noise),
551 _param_ekf2_acc_b_noise(_params->accel_bias_p_noise),
552 _param_ekf2_mag_e_noise(_params->mage_p_noise),
553 _param_ekf2_mag_b_noise(_params->magb_p_noise),
554 _param_ekf2_wind_noise(_params->wind_vel_p_noise),
555 _param_ekf2_terr_noise(_params->terrain_p_noise),
556 _param_ekf2_terr_grad(_params->terrain_gradient),
557 _param_ekf2_gps_v_noise(_params->gps_vel_noise),
558 _param_ekf2_gps_p_noise(_params->gps_pos_noise),
559 _param_ekf2_noaid_noise(_params->pos_noaid_noise),
560 _param_ekf2_baro_noise(_params->baro_noise),
561 _param_ekf2_baro_gate(_params->baro_innov_gate),
562 _param_ekf2_gnd_eff_dz(_params->gnd_effect_deadzone),
563 _param_ekf2_gnd_max_hgt(_params->gnd_effect_max_hgt),
564 _param_ekf2_gps_p_gate(_params->gps_pos_innov_gate),
565 _param_ekf2_gps_v_gate(_params->gps_vel_innov_gate),
566 _param_ekf2_tas_gate(_params->tas_innov_gate),
567 _param_ekf2_head_noise(_params->mag_heading_noise),
568 _param_ekf2_mag_noise(_params->mag_noise),
569 _param_ekf2_eas_noise(_params->eas_noise),
570 _param_ekf2_beta_gate(_params->beta_innov_gate),
571 _param_ekf2_beta_noise(_params->beta_noise),
572 _param_ekf2_mag_decl(_params->mag_declination_deg),
573 _param_ekf2_hdg_gate(_params->heading_innov_gate),
574 _param_ekf2_mag_gate(_params->mag_innov_gate),
575 _param_ekf2_decl_type(_params->mag_declination_source),
576 _param_ekf2_mag_type(_params->mag_fusion_type),
577 _param_ekf2_mag_acclim(_params->mag_acc_gate),
578 _param_ekf2_mag_yawlim(_params->mag_yaw_rate_gate),
579 _param_ekf2_gps_check(_params->gps_check_mask),
580 _param_ekf2_req_eph(_params->req_hacc),
581 _param_ekf2_req_epv(_params->req_vacc),
582 _param_ekf2_req_sacc(_params->req_sacc),
583 _param_ekf2_req_nsats(_params->req_nsats),
584 _param_ekf2_req_pdop(_params->req_pdop),
585 _param_ekf2_req_hdrift(_params->req_hdrift),
586 _param_ekf2_req_vdrift(_params->req_vdrift),
587 _param_ekf2_aid_mask(_params->fusion_mode),
588 _param_ekf2_hgt_mode(_params->vdist_sensor_type),
589 _param_ekf2_noaid_tout(_params->valid_timeout_max),
590 _param_ekf2_rng_noise(_params->range_noise),
591 _param_ekf2_rng_sfe(_params->range_noise_scaler),
592 _param_ekf2_rng_gate(_params->range_innov_gate),
593 _param_ekf2_min_rng(_params->rng_gnd_clearance),
594 _param_ekf2_rng_pitch(_params->rng_sens_pitch),
595 _param_ekf2_rng_aid(_params->range_aid),
596 _param_ekf2_rng_a_vmax(_params->max_vel_for_range_aid),
597 _param_ekf2_rng_a_hmax(_params->max_hagl_for_range_aid),
598 _param_ekf2_rng_a_igate(_params->range_aid_innov_gate),
599 _param_ekf2_evv_gate(_params->ev_vel_innov_gate),
600 _param_ekf2_evp_gate(_params->ev_pos_innov_gate),
601 _param_ekf2_of_n_min(_params->flow_noise),
602 _param_ekf2_of_n_max(_params->flow_noise_qual_min),
603 _param_ekf2_of_qmin(_params->flow_qual_min),
604 _param_ekf2_of_gate(_params->flow_innov_gate),
605 _param_ekf2_imu_pos_x(_params->imu_pos_body(0)),
606 _param_ekf2_imu_pos_y(_params->imu_pos_body(1)),
607 _param_ekf2_imu_pos_z(_params->imu_pos_body(2)),
608 _param_ekf2_gps_pos_x(_params->gps_pos_body(0)),
609 _param_ekf2_gps_pos_y(_params->gps_pos_body(1)),
610 _param_ekf2_gps_pos_z(_params->gps_pos_body(2)),
611 _param_ekf2_rng_pos_x(_params->rng_pos_body(0)),
612 _param_ekf2_rng_pos_y(_params->rng_pos_body(1)),
613 _param_ekf2_rng_pos_z(_params->rng_pos_body(2)),
614 _param_ekf2_of_pos_x(_params->flow_pos_body(0)),
615 _param_ekf2_of_pos_y(_params->flow_pos_body(1)),
616 _param_ekf2_of_pos_z(_params->flow_pos_body(2)),
617 _param_ekf2_ev_pos_x(_params->ev_pos_body(0)),
618 _param_ekf2_ev_pos_y(_params->ev_pos_body(1)),
619 _param_ekf2_ev_pos_z(_params->ev_pos_body(2)),
620 _param_ekf2_tau_vel(_params->vel_Tau),
621 _param_ekf2_tau_pos(_params->pos_Tau),
622 _param_ekf2_gbias_init(_params->switch_on_gyro_bias),
623 _param_ekf2_abias_init(_params->switch_on_accel_bias),
624 _param_ekf2_angerr_init(_params->initial_tilt_err),
625 _param_ekf2_abl_lim(_params->acc_bias_lim),
626 _param_ekf2_abl_acclim(_params->acc_bias_learn_acc_lim),
627 _param_ekf2_abl_gyrlim(_params->acc_bias_learn_gyr_lim),
628 _param_ekf2_abl_tau(_params->acc_bias_learn_tc),
629 _param_ekf2_drag_noise(_params->drag_noise),
630 _param_ekf2_bcoef_x(_params->bcoef_x),
631 _param_ekf2_bcoef_y(_params->bcoef_y),
632 _param_ekf2_move_test(_params->is_moving_scaler),
633 _param_ekf2_mag_check(_params->check_mag_strength)
650 PX4_ERR(
"sensor combined callback registration failed!");
662 PX4_INFO(
"time slip: %" PRId64
" us", _last_time_slip_us);
669 template<
typename Param>
672 if (_valid_cal_available[axis_index]) {
675 const float weighting =
constrain(_param_ekf2_magb_vref.get() / (_param_ekf2_magb_vref.get() +
676 _last_valid_variance[axis_index]), 0.0
f, _param_ekf2_magb_k.get());
677 const float mag_bias_saved = mag_bias_param.get();
679 _last_valid_mag_cal[axis_index] = weighting * _last_valid_mag_cal[axis_index] + mag_bias_saved;
681 mag_bias_param.set(_last_valid_mag_cal[axis_index]);
682 mag_bias_param.commit_no_notification();
684 _valid_cal_available[axis_index] =
false;
688 template<
typename Param>
692 float declination_deg;
695 mag_decl_param.set(declination_deg);
696 mag_decl_param.commit_no_notification();
729 ekf2_timestamps.airspeed_timestamp_rel = ekf2_timestamps_s::RELATIVE_TIMESTAMP_INVALID;
730 ekf2_timestamps.distance_sensor_timestamp_rel = ekf2_timestamps_s::RELATIVE_TIMESTAMP_INVALID;
731 ekf2_timestamps.gps_timestamp_rel = ekf2_timestamps_s::RELATIVE_TIMESTAMP_INVALID;
732 ekf2_timestamps.optical_flow_timestamp_rel = ekf2_timestamps_s::RELATIVE_TIMESTAMP_INVALID;
733 ekf2_timestamps.vehicle_air_data_timestamp_rel = ekf2_timestamps_s::RELATIVE_TIMESTAMP_INVALID;
734 ekf2_timestamps.vehicle_magnetometer_timestamp_rel = ekf2_timestamps_s::RELATIVE_TIMESTAMP_INVALID;
735 ekf2_timestamps.visual_odometry_timestamp_rel = ekf2_timestamps_s::RELATIVE_TIMESTAMP_INVALID;
756 PX4_WARN(
"accel id changed, resetting IMU bias");
761 PX4_WARN(
"gyro id changed, resetting IMU bias");
800 if (_invalid_mag_id_count < 200) {
801 _invalid_mag_id_count++;
805 if (_invalid_mag_id_count > 0) {
806 _invalid_mag_id_count--;
813 _param_ekf2_magbias_x.set(0.
f);
814 _param_ekf2_magbias_x.commit_no_notification();
815 _param_ekf2_magbias_y.set(0.
f);
816 _param_ekf2_magbias_y.commit_no_notification();
817 _param_ekf2_magbias_z.set(0.
f);
818 _param_ekf2_magbias_z.commit_no_notification();
820 _param_ekf2_magbias_id.commit();
822 _invalid_mag_id_count = 0;
824 PX4_INFO(
"Mag sensor ID changed to %i", _param_ekf2_magbias_id.get());
829 _mag_time_sum_ms += magnetometer.
timestamp / 1000;
839 float mag_data_avg_ga[3] = {_mag_data_sum[0] *mag_sample_count_inv - _param_ekf2_magbias_x.get(),
840 _mag_data_sum[1] *mag_sample_count_inv - _param_ekf2_magbias_y.get(),
841 _mag_data_sum[2] *mag_sample_count_inv - _param_ekf2_magbias_z.get()
844 _ekf.
setMagData(1000 * (uint64_t)mag_time_ms, mag_data_avg_ga);
846 _mag_time_ms_last_used = mag_time_ms;
847 _mag_time_sum_ms = 0;
848 _mag_sample_count = 0;
849 _mag_data_sum[0] = 0.0f;
850 _mag_data_sum[1] = 0.0f;
851 _mag_data_sum[2] = 0.0f;
854 ekf2_timestamps.vehicle_magnetometer_timestamp_rel = (int16_t)((int64_t)magnetometer.
timestamp / 100 -
855 (int64_t)ekf2_timestamps.timestamp / 100);
866 _balt_time_sum_ms += airdata.
timestamp / 1000;
867 _balt_sample_count++;
873 float balt_data_avg = _balt_data_sum / (float)_balt_sample_count;
882 float K_pstatic_coef_x;
884 if (vel_body_wind(0) >= 0.0
f) {
885 K_pstatic_coef_x = _param_ekf2_pcoef_xp.get();
888 K_pstatic_coef_x = _param_ekf2_pcoef_xn.get();
891 float K_pstatic_coef_y;
893 if (vel_body_wind(1) >= 0.0
f) {
894 K_pstatic_coef_y = _param_ekf2_pcoef_yp.get();
897 K_pstatic_coef_y = _param_ekf2_pcoef_yn.get();
900 const float max_airspeed_sq = _param_ekf2_aspd_max.get() * _param_ekf2_aspd_max.get();
901 const float x_v2 = fminf(vel_body_wind(0) * vel_body_wind(0), max_airspeed_sq);
902 const float y_v2 = fminf(vel_body_wind(1) * vel_body_wind(1), max_airspeed_sq);
903 const float z_v2 = fminf(vel_body_wind(2) * vel_body_wind(2), max_airspeed_sq);
905 const float pstatic_err = 0.5f * airdata.
rho * (
906 K_pstatic_coef_x * x_v2 + K_pstatic_coef_y * y_v2 + _param_ekf2_pcoef_z.get() * z_v2);
912 _ekf.
setBaroData(1000 * (uint64_t)balt_time_ms, balt_data_avg);
914 _balt_time_ms_last_used = balt_time_ms;
915 _balt_time_sum_ms = 0;
916 _balt_sample_count = 0;
917 _balt_data_sum = 0.0f;
920 ekf2_timestamps.vehicle_air_data_timestamp_rel = (int16_t)((int64_t)airdata.
timestamp / 100 -
921 (int64_t)ekf2_timestamps.timestamp / 100);
935 ekf2_timestamps.gps_timestamp_rel = (int16_t)((int64_t)gps.
timestamp / 100 - (int64_t)ekf2_timestamps.timestamp / 100);
951 if ((_param_ekf2_gps_mask.get() == 0) && gps1_updated) {
955 }
else if ((_param_ekf2_gps_mask.get() > 0) && (gps1_updated || gps2_updated)) {
963 _gps_select_index = 0;
967 _gps_select_index = 1;
969 }
else if (_gps_select_index == 2) {
972 _gps_select_index = 0;
974 }
else if (gps2_updated) {
975 _gps_select_index = 1;
980 _gps_new_output_data = (gps1_updated && _gps_select_index == 0) ||
981 (gps2_updated && _gps_select_index == 1);
984 if (_gps_new_output_data) {
989 if (_gps_select_index == 2) {
1020 _gps_new_output_data =
false;
1035 ekf2_timestamps.airspeed_timestamp_rel = (int16_t)((int64_t)airspeed.
timestamp / 100 -
1036 (int64_t)ekf2_timestamps.timestamp / 100);
1063 ekf2_timestamps.optical_flow_timestamp_rel = (int16_t)((int64_t)optical_flow.
timestamp / 100 -
1064 (int64_t)ekf2_timestamps.timestamp / 100);
1068 if (_range_finder_sub_index >= 0) {
1079 ekf2_timestamps.distance_sensor_timestamp_rel = (int16_t)((int64_t)range_finder.
timestamp / 100 -
1080 (int64_t)ekf2_timestamps.timestamp / 100);
1090 new_ev_data_received =
false;
1093 new_ev_data_received =
true;
1108 ev_data.
velErr = fmaxf(_param_ekf2_evv_noise.get(),
1114 ev_data.
velErr = _param_ekf2_evv_noise.get();
1126 ev_data.
posErr = fmaxf(_param_ekf2_evp_noise.get(),
1129 ev_data.
hgtErr = fmaxf(_param_ekf2_evp_noise.get(),
1133 ev_data.
posErr = _param_ekf2_evp_noise.get();
1134 ev_data.
hgtErr = _param_ekf2_evp_noise.get();
1143 if (!_param_ekf2_ev_noise_md.get()
1145 ev_data.
angErr = fmaxf(_param_ekf2_eva_noise.get(),
1149 ev_data.
angErr = _param_ekf2_eva_noise.get();
1154 if (ev_data.
posErr < ep_max_std_dev && ev_data.
angErr < eo_max_std_dev) {
1159 ekf2_timestamps.visual_odometry_timestamp_rel = (int16_t)((int64_t)
_ev_odom.
timestamp / 100 -
1160 (int64_t)ekf2_timestamps.timestamp / 100);
1165 if (vehicle_land_detected_updated) {
1188 const bool updated = _ekf.
update();
1192 if (_start_time_us == 0) {
1193 _start_time_us = now;
1194 _last_time_slip_us = 0;
1196 }
else if (_start_time_us > 0) {
1198 _last_time_slip_us = (now -
_start_time_us) - _integrated_time_us;
1217 odom.local_frame = odom.LOCAL_FRAME_NED;
1222 const float lpos_x_prev = lpos.
x;
1223 const float lpos_y_prev = lpos.
y;
1226 lpos.
z = position[2];
1236 lpos.
vx = velocity[0];
1237 lpos.
vy = velocity[1];
1238 lpos.
vz = velocity[2];
1251 lpos.
ax = vel_deriv[0];
1252 lpos.
ay = vel_deriv[1];
1253 lpos.
az = vel_deriv[2];
1263 uint64_t origin_time;
1270 if (ekf_origin_valid && (origin_time > lpos.
ref_timestamp)) {
1287 odom.rollspeed = sensors.
gyro_rad[0] - gyro_bias[0];
1288 odom.pitchspeed = sensors.
gyro_rad[1] - gyro_bias[1];
1289 odom.yawspeed = sensors.
gyro_rad[2] - gyro_bias[2];
1298 if (lpos.
dist_bottom < _param_ekf2_min_rng.get()) {
1302 if (!_had_valid_terrain) {
1316 }
else if (vehicle_land_detected_updated && !_had_valid_terrain) {
1340 if (!PX4_ISFINITE(lpos.
vxy_max)) {
1344 if (!PX4_ISFINITE(lpos.
vz_max)) {
1348 if (!PX4_ISFINITE(lpos.
hagl_min)) {
1352 if (!PX4_ISFINITE(lpos.
hagl_max)) {
1357 float covariances[24];
1361 const size_t POS_URT_SIZE =
sizeof(odom.pose_covariance) /
sizeof(odom.pose_covariance[0]);
1362 const size_t VEL_URT_SIZE =
sizeof(odom.velocity_covariance) /
sizeof(odom.velocity_covariance[0]);
1365 for (
size_t i = 0; i < POS_URT_SIZE; i++) {
1366 odom.pose_covariance[i] = 0.0;
1370 odom.pose_covariance[odom.COVARIANCE_MATRIX_X_VARIANCE] = covariances[7];
1371 odom.pose_covariance[odom.COVARIANCE_MATRIX_Y_VARIANCE] = covariances[8];
1372 odom.pose_covariance[odom.COVARIANCE_MATRIX_Z_VARIANCE] = covariances[9];
1378 for (
size_t i = 0; i < VEL_URT_SIZE; i++) {
1379 odom.velocity_covariance[i] = 0.0;
1383 odom.velocity_covariance[odom.COVARIANCE_MATRIX_VX_VARIANCE] = covariances[4];
1384 odom.velocity_covariance[odom.COVARIANCE_MATRIX_VY_VARIANCE] = covariances[5];
1385 odom.velocity_covariance[odom.COVARIANCE_MATRIX_VZ_VARIANCE] = covariances[6];
1394 if (new_ev_data_received) {
1397 Quatf quat_ev2ekf(q_ev2ekf);
1398 Dcmf ev_rot_mat(quat_ev2ekf);
1404 aligned_ev_odom.
x = aligned_pos(0);
1405 aligned_ev_odom.
y = aligned_pos(1);
1406 aligned_ev_odom.
z = aligned_pos(2);
1409 aligned_ev_odom.
vx = aligned_vel(0);
1410 aligned_ev_odom.
vy = aligned_vel(1);
1411 aligned_ev_odom.
vz = aligned_vel(2);
1415 ev_quat_aligned.normalize();
1417 ev_quat_aligned.copyTo(aligned_ev_odom.
q);
1418 quat_ev2ekf.copyTo(aligned_ev_odom.
q_offset);
1445 global_pos.
yaw = lpos.
yaw;
1474 bias.mag_bias[0] = _last_valid_mag_cal[0];
1475 bias.mag_bias[1] = _last_valid_mag_cal[1];
1476 bias.mag_bias[2] = _last_valid_mag_cal[2];
1502 status.
time_slip = _last_time_slip_us / 1e6f;
1522 drift_data.
hspd = gps_drift[2];
1537 if (_last_magcal_us == 0) {
1538 _last_magcal_us = now;
1542 _last_magcal_us = now;
1548 _total_cal_time_us = 0;
1550 for (
bool &cal_available : _valid_cal_available) {
1551 cal_available =
false;
1556 if (_total_cal_time_us > 120_s) {
1559 const float max_var_allowed = 100.0f * _param_ekf2_magb_vref.get();
1560 const float min_var_allowed = 0.01f * _param_ekf2_magb_vref.get();
1563 bool all_estimates_invalid =
false;
1565 for (uint8_t axis_index = 0; axis_index <= 2; axis_index++) {
1566 if (status.
covariances[axis_index + 19] < min_var_allowed
1567 || status.
covariances[axis_index + 19] > max_var_allowed) {
1568 all_estimates_invalid =
true;
1573 if (!all_estimates_invalid) {
1574 for (uint8_t axis_index = 0; axis_index <= 2; axis_index++) {
1575 _last_valid_mag_cal[axis_index] = status.
states[axis_index + 19];
1576 _valid_cal_available[axis_index] =
true;
1577 _last_valid_variance[axis_index] = status.
covariances[axis_index + 19];
1592 _total_cal_time_us = 0;
1672 const bool can_observe_heading_in_flight = (vehicle_status.
vehicle_type != vehicle_status_s::VEHICLE_TYPE_ROTARY_WING);
1679 _preflt_checker.
update(dt, innov);
1684 _preflt_checker.
reset();
1694 if (report.orientation == distance_sensor_s::ROTATION_DOWNWARD_FACING) {
1695 PX4_INFO(
"Found range finder with instance %d", i);
1720 }
else if (_replay_mode) {
1735 float velNE_wind[2];
1743 wind_estimate.timestamp = timestamp;
1744 wind_estimate.windspeed_north = velNE_wind[0];
1745 wind_estimate.windspeed_east = velNE_wind[1];
1746 wind_estimate.variance_north = wind_var[0];
1747 wind_estimate.variance_east = wind_var[1];
1748 wind_estimate.tas_scale = 0.0f;
1770 float velNE_wind[2];
1773 Vector3f v_wind_comp = {velocity[0] - velNE_wind[0], velocity[1] - velNE_wind[1], velocity[2]};
1775 return R_to_body * v_wind_comp;
1781 memset(&_blend_weights, 0,
sizeof(_blend_weights));
1792 float dt_max = 0.0f;
1793 float dt_min = 0.3f;
1796 float raw_dt = 0.001f * (float)(
_gps_state[i].time_usec - _time_prev_us[i]);
1798 if (raw_dt > 0.0
f && raw_dt < 0.3
f) {
1799 _gps_dt[i] = 0.1f * raw_dt + 0.9f * _gps_dt[i];
1802 if (_gps_dt[i] > dt_max) {
1803 dt_max = _gps_dt[i];
1804 _gps_slowest_index = i;
1807 if (_gps_dt[i] < dt_min) {
1808 dt_min = _gps_dt[i];
1813 uint64_t max_us = 0;
1814 uint64_t min_us = -1;
1820 _gps_newest_index = i;
1825 _gps_oldest_index = i;
1829 if ((max_us - min_us) > 300000) {
1843 if ((dt_max - dt_min) < 0.2f * dt_min) {
1845 if ((max_us - min_us) < (uint64_t)(5e5f * dt_min)) {
1848 _gps_new_output_data =
true;
1855 if (
_gps_state[_gps_time_ref_index].time_usec > _time_prev_us[_gps_time_ref_index]) {
1857 _gps_new_output_data =
true;
1861 if (_gps_new_output_data) {
1865 float speed_accuracy_sum_sq = 0.0f;
1874 speed_accuracy_sum_sq = 0.0f;
1881 float horizontal_accuracy_sum_sq = 0.0f;
1890 horizontal_accuracy_sum_sq = 0.0f;
1897 float vertical_accuracy_sum_sq = 0.0f;
1906 vertical_accuracy_sum_sq = 0.0f;
1913 bool can_do_blending = (horizontal_accuracy_sum_sq > 0.0f || vertical_accuracy_sum_sq > 0.0f
1914 || speed_accuracy_sum_sq > 0.0f);
1917 if (!can_do_blending) {
1921 float sum_of_all_weights = 0.0f;
1928 float sum_of_spd_weights = 0.0f;
1933 sum_of_spd_weights += spd_blend_weights[i];
1938 if (sum_of_spd_weights > 0.0
f) {
1940 spd_blend_weights[i] = spd_blend_weights[i] / sum_of_spd_weights;
1943 sum_of_all_weights += 1.0f;
1952 float sum_of_hpos_weights = 0.0f;
1957 sum_of_hpos_weights += hpos_blend_weights[i];
1962 if (sum_of_hpos_weights > 0.0
f) {
1964 hpos_blend_weights[i] = hpos_blend_weights[i] / sum_of_hpos_weights;
1967 sum_of_all_weights += 1.0f;
1976 float sum_of_vpos_weights = 0.0f;
1981 sum_of_vpos_weights += vpos_blend_weights[i];
1986 if (sum_of_vpos_weights > 0.0
f) {
1988 vpos_blend_weights[i] = vpos_blend_weights[i] / sum_of_vpos_weights;
1991 sum_of_all_weights += 1.0f;
1997 _blend_weights[i] = (hpos_blend_weights[i] + vpos_blend_weights[i] + spd_blend_weights[i]) / sum_of_all_weights;
2004 _gps_select_index = 2;
2036 _blended_antenna_offset.zero();
2056 if (_blend_weights[i] > 0.0
f) {
2102 float best_weight = 0.0f;
2105 if (_blend_weights[i] > best_weight) {
2106 best_weight = _blend_weights[i];
2107 _gps_best_index = i;
2116 blended_NE_offset_m.zero();
2117 float blended_alt_offset_mm = 0.0f;
2120 if ((_blend_weights[i] > 0.0
f) && (i != _gps_best_index)) {
2125 &horiz_offset(0), &horiz_offset(1));
2128 blended_NE_offset_m += horiz_offset * _blend_weights[i];
2134 blended_alt_offset_mm += vert_offset * _blend_weights[i];
2141 double lat_deg_res, lon_deg_res;
2149 uint8_t gps_best_yaw_index = 0;
2153 if (PX4_ISFINITE(
_gps_state[i].yaw) && (_blend_weights[i] > best_weight)) {
2154 best_weight = _blend_weights[i];
2155 gps_best_yaw_index = i;
2175 float omega_lpf = 1.0f / fmaxf(_param_ekf2_gps_tau.get(), 1.0f);
2178 if (
_gps_state[i].time_usec - _time_prev_us[i] > 0) {
2180 float min_alpha =
constrain(omega_lpf * 1e-6
f * (
float)(
_gps_state[i].time_usec - _time_prev_us[i]),
2184 if (_blend_weights[i] > min_alpha) {
2185 alpha[i] = min_alpha / _blend_weights[i];
2200 _NE_pos_offset_m[i] = offset * alpha[i] + _NE_pos_offset_m[i] * (1.0f - alpha[i]);
2202 _hgt_offset_mm[i] * (1.0f - alpha[i]);
2207 float max_alt_offset = 0;
2215 max_ne_offset(0) = fmaxf(max_ne_offset(0), fabsf(offset(0)));
2216 max_ne_offset(1) = fmaxf(max_ne_offset(1), fabsf(offset(1)));
2224 _NE_pos_offset_m[i](0) =
constrain(_NE_pos_offset_m[i](0), -max_ne_offset(0), max_ne_offset(0));
2225 _NE_pos_offset_m[i](1) =
constrain(_NE_pos_offset_m[i](1), -max_ne_offset(1), max_ne_offset(1));
2226 _hgt_offset_mm[i] =
constrain(_hgt_offset_mm[i], -max_alt_offset, max_alt_offset);
2240 double lat_deg_now = (double)
_gps_state[i].lat * 1.0e-7;
2241 double lon_deg_now = (double)
_gps_state[i].lon * 1.0e-7;
2242 double lat_deg_res, lon_deg_res;
2276 blended_NE_offset_m.zero();
2277 float blended_alt_offset_mm = 0.0f;
2280 if (_blend_weights[i] > 0.0
f) {
2291 blended_NE_offset_m += horiz_offset * _blend_weights[i];
2297 blended_alt_offset_mm += vert_offset * _blend_weights[i];
2304 double lat_deg_res, lon_deg_res;
2336 _wgs84_hgt_offset = height_diff;
2358 bool replay_mode =
false;
2360 if (argc > 1 && !strcmp(argv[1],
"-r")) {
2361 PX4_INFO(
"replay mode enabled");
2368 _object.store(instance);
2369 _task_id = task_id_is_work_queue;
2371 if (instance->
init()) {
2376 PX4_ERR(
"alloc failed");
2380 _object.store(
nullptr);
2389 PX4_WARN(
"%s\n", reason);
2392 PRINT_MODULE_DESCRIPTION(
2395 Attitude and position estimator using an Extended Kalman Filter. It is used for Multirotors and Fixed-Wing. 2397 The documentation can be found on the [ECL/EKF Overview & Tuning](https://docs.px4.io/en/advanced_config/tuning_the_ecl_ekf.html) page. 2399 ekf2 can be started in replay mode (`-r`): in this mode it does not access the system time, but only uses the 2400 timestamps from the sensor topics. 2404 PRINT_MODULE_USAGE_NAME("ekf2",
"estimator");
2405 PRINT_MODULE_USAGE_COMMAND(
"start");
2406 PRINT_MODULE_USAGE_PARAM_FLAG(
'r',
"Enable replay mode",
true);
2407 PRINT_MODULE_USAGE_DEFAULT_COMMANDS();
#define VEHICLE_TYPE_FIXED_WING
int getRangeSubIndex()
get subscription index of first downward-facing range sensor
void setIMUData(const imuSample &imu_sample)
constexpr _Tp constrain(_Tp val, _Tp min_val, _Tp max_val)
uORB::Publication< ekf_gps_drift_s > _ekf_gps_drift_pub
void setMagData(uint64_t time_usec, float(&data)[3])
struct estimator::filter_control_status_u::@60 flags
bool hasHeightFailed() const
float eph
GPS horizontal position accuracy in m.
uORB::Subscription _parameter_update_sub
Vector3f delta_ang
delta angle in body frame (integrated gyro measurements) (rad)
void setUsingFlowAiding(bool val)
float yaw_offset
Heading/Yaw offset for dual antenna GPS - refer to description for GPS_YAW_OFFSET.
hrt_abstime _last_magcal_us
last time the EKF was operating a mode that estimates magnetomer biases (uSec)
uint32_t control_mode_flags
uORB::Publication< sensor_bias_s > _sensor_bias_pub
#define BLEND_MASK_USE_HPOS_ACC
float epv
GPS vertical position accuracy in m.
uORB::Subscription _airdata_sub
void get_hagl_innov(float *hagl_innov)
static struct vehicle_status_s status
void get_ekf_vel_accuracy(float *ekf_evh, float *ekf_evv) override
void setExtVisionData(uint64_t time_usec, ext_vision_message *evdata)
float gyro_x_rate_integral
uint8_t nsats
number of satellites used
measure the time elapsed performing an event
float _wgs84_hgt_offset
height offset between AMSL and WGS84
void setAuxVelData(uint64_t time_usec, float(&data)[2], float(&variance)[2])
void set_optical_flow_limits(float max_flow_rate, float min_distance, float max_distance)
float vel_m_s
GPS ground speed (m/sec)
Quatf calculate_quaternion() const
bool update(void *dst)
Copy the struct if updated.
uORB::PublicationData< vehicle_global_position_s > _vehicle_global_position_pub
uORB::Subscription _landing_target_pose_sub
bool get_ekf_origin(uint64_t *origin_time, map_projection_reference_s *origin_pos, float *origin_alt) override
uORB::Publication< vehicle_odometry_s > _vehicle_odometry_pub
uORB::Subscription _sensor_selection_sub
bool is_fixed_wing(const struct vehicle_status_s *current_status)
void get_state_delayed(float *state) override
void get_heading_innov(float *heading_innov) override
void get_terrain_vert_pos(float *ret)
float pixel_flow_y_integral
void get_vector_to_next_waypoint(double lat_now, double lon_now, double lat_next, double lon_next, float *v_n, float *v_e)
uORB::Subscription _range_finder_subs[ORB_MULTI_MAX_INSTANCES]
bool update_mag_decl(Param &mag_decl_param)
bool pre_flt_fail_innov_vel_horiz
void runPreFlightChecks(float dt, const filter_control_status_u &control_status, const vehicle_status_s &vehicle_status, const ekf2_innovations_s &innov)
void set_is_fixed_wing(bool is_fixed_wing)
int main(int argc, char **argv)
void get_gyro_bias(float bias[3]) override
uORB::Publication< ekf_gps_position_s > _blended_gps_pub
void get_output_tracking_error(float error[3]) override
uint8_t vxy_reset_counter
float sacc
GPS speed accuracy in m/s.
void get_drag_innov_var(float drag_innov_var[2]) override
void get_mag_innov_var(float mag_innov_var[3]) override
Vector3f gyrodata
Gyro rates about the XYZ body axes (rad/sec)
void set_fuse_beta_flag(bool fuse_beta)
const bool _replay_mode
true when we use replay data from a log
void set_gnd_effect_flag(bool gnd_effect)
#define GPS_MAX_RECEIVERS
uint8_t fix_type
0-1: no fix, 2: 2D fix, 3: 3D fix, 4: RTCM code differential, 5: Real-Time Kinematic ...
void calc_gps_blend_output()
uint32_t mag_field_disturbed
16 - true when the mag field does not match the expected strength
float min_ground_distance
float pixel_flow_x_integral
int print_status() override
uint16_t filter_fault_flags
float accelerometer_m_s2[3]
Ekf2(bool replay_mode=false)
float pdop
position dilution of precision
static int print_usage(const char *reason=nullptr)
static void print_usage()
void get_imu_vibe_metrics(float vibe[3]) override
void get_velocity(float *vel)
void setGpsData(uint64_t time_usec, const gps_message &gps)
uORB::Publication< ekf2_innovations_s > _estimator_innovations_pub
uORB::SubscriptionCallbackWorkItem _sensors_sub
float vel_ned[3]
GPS ground speed NED.
void setUsingGpsAiding(bool val)
void get_flow_innov_var(float flow_innov_var[2]) override
void update_mag_bias(Param &mag_bias_param, int axis_index)
uint32_t dt
integration time of flow samples (sec)
void copyTo(Type dst[M *N]) const
High-resolution timer with callouts and timekeeping.
void get_wind_velocity(float *wind) override
uint8_t quality
Quality of Flow data.
static constexpr float CONSTANTS_ONE_G
void get_control_mode(uint32_t *val)
uORB::PublicationData< vehicle_local_position_s > _vehicle_local_position_pub
void update(float dt, const ekf2_innovations_s &innov)
void update_gps_offsets()
#define BLEND_MASK_USE_VPOS_ACC
bool pre_flt_fail_innov_vel_vert
uint8_t _gps_slowest_index
index of the physical receiver with the slowest update rate
uORB::Subscription _gps_subs[GPS_MAX_RECEIVERS]
static char msg[NUM_MSG][CONFIG_USART1_TXBUFSIZE]
float max_ground_distance
void resetPreFlightChecks()
vehicle_status_s _vehicle_status
uORB::Subscription _ev_odom_sub
gps_message _gps_output[GPS_MAX_RECEIVERS+1]
output state data for the physical and blended GPS
void get_airspeed_innov_var(float *airspeed_innov_var) override
float velErr
1-Sigma velocity accuracy (m/sec)
#define ORB_ID(_name)
Generates a pointer to the uORB metadata structure for a given topic.
void get_accel_bias(float bias[3]) override
bool hasHorizVelFailed() const
bool pre_flt_fail_innov_heading
PreFlightChecker _preflt_checker
float hgtErr
1-Sigma height accuracy (m)
bool publish(const T &data)
Publish the struct.
void get_heading_innov_var(float *heading_innov_var) override
__EXPORT int ekf2_main(int argc, char *argv[])
void update_gps_blend_states()
uint64_t _gps_alttitude_ellipsoid_previous_timestamp[GPS_MAX_RECEIVERS]
storage for previous timestamp to compute dt
void perf_free(perf_counter_t handle)
Free a counter.
int map_projection_reproject(const struct map_projection_reference_s *ref, float x, float y, double *lat, double *lon)
Transforms a point in the local azimuthal equidistant plane to the geographic coordinate system using...
void init()
Activates/configures the hardware registers.
bool vel_ned_valid
GPS ground speed is valid.
bool publish_wind_estimate(const hrt_abstime ×tamp)
void get_velD_reset(float *delta, uint8_t *counter) override
void setBaroData(uint64_t time_usec, float data)
uint8_t _gps_time_ref_index
index of the receiver that is used as the timing reference for the blending update ...
void get_vel_pos_innov_var(float vel_pos_innov_var[6]) override
void get_posNE_reset(float delta[2], uint8_t *counter) override
float vel_pos_innov_var[6]
parameters * _params
pointer to ekf parameter struct (located in _ekf class instance)
uint16_t solution_status_flags
bool reset_imu_bias() override
uORB::Publication< ekf2_timestamps_s > _ekf2_timestamps_pub
uint64_t time_us
timestamp of the measurement (uSec)
void get_ekf_gpos_accuracy(float *ekf_eph, float *ekf_epv) override
uORB::Subscription _airspeed_sub
void get_vel_deriv_ned(float *vel_deriv)
#define BLEND_MASK_USE_SPD_ACC
void get_filter_fault_status(uint16_t *val)
perf_counter_t perf_alloc_once(enum perf_counter_type type, const char *name)
Get the reference to an existing counter or create a new one if it does not exist.
Vector< float, 6 > f(float t, const Matrix< float, 6, 1 > &, const Matrix< float, 3, 1 > &)
bool get_gps_drift_metrics(float drift[3], bool *blocked) override
Vector2< float > Vector2f
void add_vector_to_global_position(double lat_now, double lon_now, float v_n, float v_e, double *lat_res, double *lon_res)
int32_t _gps_alttitude_ellipsoid[GPS_MAX_RECEIVERS]
altitude in 1E-3 meters (millimeters) above ellipsoid
Vector3f pos
XYZ position in earth frame (m) - Z must be aligned with down axis.
void get_airspeed_innov(float *airspeed_innov) override
bool hasHorizFailed() const
float indicated_airspeed_m_s
gps_message _gps_state[GPS_MAX_RECEIVERS]
internal state data for the physical GPS
int32_t lat
Latitude in 1E-7 degrees.
void get_hagl_innov_var(float *hagl_innov_var)
vehicle_odometry_s _ev_odom
bool pre_flt_fail_mag_field_disturbed
void get_ev2ekf_quaternion(float *quat) override
void get_ekf_ctrl_limits(float *vxy_max, float *vz_max, float *hagl_min, float *hagl_max) override
uORB::PublicationMulti< wind_estimate_s > _wind_pub
void get_ekf_lpos_accuracy(float *ekf_eph, float *ekf_epv) override
void perf_end(perf_counter_t handle)
End a performance event.
void get_ekf_soln_status(uint16_t *status) override
uORB::Publication< estimator_status_s > _estimator_status_pub
uint32_t gyro_integral_dt
bool updated()
Check if there is a new update.
void get_posD_reset(float *delta, uint8_t *counter) override
__BEGIN_DECLS typedef uint64_t hrt_abstime
Absolute time, in microsecond units.
void setAirspeedData(uint64_t time_usec, float true_airspeed, float eas2tas)
gps_message _gps_blended_state
internal state data for the blended GPS
uint8_t _mag_sample_count
number of magnetometer measurements summed during downsampling
Vector2f flowdata
Optical flow rates about the X and Y body axes (rad/sec)
void get_flow_innov(float flow_innov[2]) override
void setVehicleCanObserveHeadingInFlight(bool val)
static int custom_command(int argc, char *argv[])
void get_mag_innov(float mag_innov[3]) override
bool get_mag_decl_deg(float *val)
void get_aux_vel_innov(float aux_vel_innov[2]) override
Vector3f vel
XYZ velocity in earth frame (m/sec) - Z must be aligned with down axis.
Vector3< float > Vector3f
float yaw
yaw angle. NaN if not set (used for dual antenna GPS), (rad, [-PI, PI])
bool local_position_is_valid()
void setRangeData(uint64_t time_usec, float data, int8_t quality)
uint32_t opt_flow
3 - true if optical flow measurements are being fused
Quaternion inversed() const
Invert quaternion.
void set_rangefinder_limits(float min_distance, float max_distance)
matrix::Vector< float, 24 > covariances_diagonal() const
void get_velNE_reset(float delta[2], uint8_t *counter) override
static int task_spawn(int argc, char *argv[])
uint8_t quat_reset_counter
bool hasVertFailed() const
uint32_t mag_3D
5 - true if 3-axis magnetometer measurement are being fused
uORB::Publication< vehicle_attitude_s > _att_pub
Quaternion< float > Quatf
void set_min_required_gps_health_time(uint32_t time_us)
float angErr
1-Sigma angular error (rad)
vehicle_land_detected_s _vehicle_land_detected
float pose_covariance[21]
void get_vel_pos_innov(float vel_pos_innov[6]) override
void perf_print_counter(perf_counter_t handle)
Print one performance counter to stdout.
#define ORB_MULTI_MAX_INSTANCES
Maximum number of multi topic instances.
Class handling the EKF2 innovation pre flight checks.
int32_t alt
Altitude in 1E-3 meters (millimeters) above MSL.
#define GPS_BLENDED_INSTANCE
void unregisterCallback()
perf_counter_t _ekf_update_perf
int32_t sensor_interval_min_ms
minimum time of arrival difference between non IMU sensor updates. Sets the size of the observation b...
uint16_t gps_check_fail_flags
uint32_t integration_timespan
const Vector3f get_vel_body_wind()
bool publish_attitude(const sensor_combined_s &sensors, const hrt_abstime &now)
void setUsingEvPosAiding(bool val)
void get_gps_check_status(uint16_t *val) override
Quatf quat
quaternion defining rotation from body to earth frame
sensor_selection_s _sensor_selection
uint32_t ev_pos
12 - true when local position data from external vision is being fused
uint8_t lat_lon_reset_counter
uint8_t _gps_newest_index
index of the physical receiver with the newest data
void get_pos_d_deriv(float *pos_d_deriv)
void fillGpsMsgWithVehicleGpsPosData(gps_message &msg, const vehicle_gps_position_s &data)
uORB::Subscription _vehicle_land_detected_sub
void set_in_air_status(bool in_air)
bool update(void *dst)
Update the struct.
bool pre_flt_fail_innov_height
uint32_t gps
2 - true if GPS measurements are being fused
void get_wind_velocity_var(float *wind_var) override
bool inertial_dead_reckoning()
uint32_t tilt_align
0 - true if the filter tilt alignment is complete
float gyro_z_rate_integral
void get_quat_reset(float delta_quat[4], uint8_t *counter) override
float filter_altitude_ellipsoid(float amsl_hgt)
bool _imu_bias_reset_request
float gyro_y_rate_integral
bool publish(const T &data)
Publish the struct.
uint8_t _gps_select_index
0 = GPS1, 1 = GPS2, 2 = blended
void get_beta_innov(float *beta_innov) override
Vector3f delta_vel
delta velocity in body frame (integrated accelerometer measurements) (m/sec)
void get_innovation_test_status(uint16_t *status, float *mag, float *vel, float *pos, float *hgt, float *tas, float *hagl, float *beta) override
uint16_t innovation_check_flags
bool copy(void *dst)
Copy the struct.
float delta_ang_dt
delta angle integration period (sec)
void get_drag_innov(float drag_innov[2]) override
bool hasVertVelFailed() const
Class for core functions for ekf attitude and position estimator.
bool hasHeadingFailed() const
float output_tracking_error[3]
void set_air_density(float air_density)
void perf_begin(perf_counter_t handle)
Begin a performance event.
void get_beta_innov_var(float *beta_innov_var) override
uORB::Subscription _optical_flow_sub
uint32_t accelerometer_integral_dt
float delta_vel_dt
delta velocity integration period (sec)
bool global_position_is_valid() override
int32_t gps_check_mask
bitmask used to control which GPS quality checks are used
uint64_t _start_time_us
system time at EKF start (uSec)
const matrix::Quatf & get_quaternion() const
int32_t lon
Longitude in 1E-7 degrees.
float posErr
1-Sigma horizontal position accuracy (m)
uORB::Subscription _status_sub
void get_position(float *pos)
uint8_t _balt_sample_count
number of barometric altitude measurements summed
Performance measuring tools.
uORB::Subscription _magnetometer_sub
uORB::PublicationData< vehicle_odometry_s > _vehicle_visual_odometry_aligned_pub
void setOpticalFlowData(uint64_t time_usec, flow_message *flow)