EKF Check

SCHED_TASK(ekf_check, 10, 75) 10hz开始。

// ekf_check - detects if ekf variance are out of tolerance and triggers failsafe
// should be called at 10hz
// 检查ekf协方差是否超过容忍限度并且触发失效保护。
void Copter::ekf_check()
{
    // exit immediately if ekf has no origin yet - this assumes the origin can never become unset
    Location temp_loc;
   // 若是没能获得原点位置则不记录,为啥get_origin()能知道没有记录原点?
    if (!ahrs.get_origin(temp_loc)) {
        return;
    }

    // return immediately if motors are not armed, or ekf check is disabled
    // 若是马达没解锁或者ekf检查被disable则立刻退出。
    // fs_ekf_thresh 可通过地面站去设置,并且此时此值为0.8
    if (!motors->armed() || (g.fs_ekf_thresh <= 0.0f)) {
        ekf_check_state.fail_count = 0;
        ekf_check_state.bad_variance = false;
        AP_Notify::flags.ekf_bad = ekf_check_state.bad_variance;
        failsafe_ekf_off_event();   // clear failsafe
        return;
    }

    // compare compass and velocity variance vs threshold
    // 与阈值对比罗盘和速度的协方差。
    if (ekf_over_threshold()) {
        // if compass is not yet flagged as bad
        // 若是罗盘
        if (!ekf_check_state.bad_variance) {
            // increase counter
            ekf_check_state.fail_count++;
            // if counter above max then trigger failsafe
            // 若是超过10次则开始触发这个ekf_variance.
            if (ekf_check_state.fail_count >= EKF_CHECK_ITERATIONS_MAX) {
                // limit count from climbing too high
                ekf_check_state.fail_count = EKF_CHECK_ITERATIONS_MAX;
                ekf_check_state.bad_variance = true;
                // log an error in the dataflash
                Log_Write_Error(ERROR_SUBSYSTEM_EKFCHECK, ERROR_CODE_EKFCHECK_BAD_VARIANCE);
                // send message to gcs
                if ((AP_HAL::millis() - ekf_check_state.last_warn_time) > EKF_CHECK_WARNING_TIME) {
                    gcs().send_text(MAV_SEVERITY_CRITICAL,"EKF variance");
                    ekf_check_state.last_warn_time = AP_HAL::millis();
                }
                failsafe_ekf_event();
            }
        }
    } else { //若是有一次则减一次
        // reduce counter
        if (ekf_check_state.fail_count > 0) {
            ekf_check_state.fail_count--;
            
            // if compass is flagged as bad and the counter reaches zero then clear flag
            // 若是减到最后为0,则清除状态,回归正路。
            if (ekf_check_state.bad_variance && ekf_check_state.fail_count == 0) {
                ekf_check_state.bad_variance = false;
                // log recovery in the dataflash
                Log_Write_Error(ERROR_SUBSYSTEM_EKFCHECK, ERROR_CODE_EKFCHECK_VARIANCE_CLEARED);
                // clear failsafe
                failsafe_ekf_off_event();
            }
        }
    }

    // set AP_Notify flags
    AP_Notify::flags.ekf_bad = ekf_check_state.bad_variance;

    // To-Do: add ekf variances to extended status
}

比较ekf协方差是否超过阈值。若是超过阈值则返回真。

// ekf_over_threshold - returns true if the ekf's variance are over the tolerance
bool Copter::ekf_over_threshold()
{
    // return false immediately if disabled
    if (g.fs_ekf_thresh <= 0.0f) {
        return false;
    }

    // use EKF to get variance
    // 用EKF去获得协方差
    // 分别为位置协方差、速度协方差、高度协方差、真空速协方差。
    float position_variance, vel_variance, height_variance, tas_variance;
    // mag 三轴协方差。
    Vector3f mag_variance;
    // 补偿
    Vector2f offset;
    ahrs.get_variances(vel_variance, position_variance, height_variance, mag_variance, tas_variance, offset);

    // return true if two of compass, velocity and position variances are over the threshold
    // 若是同时mag_variance.length()、vel_variance 和 position_variance中有两个大于0.8既判断ekf的协方差变大为真。
    uint8_t over_thresh_count = 0;
    if (mag_variance.length() >= g.fs_ekf_thresh) {
        over_thresh_count++;
    }
    if (vel_variance >= g.fs_ekf_thresh) {
        over_thresh_count++;
    }
    if (position_variance >= g.fs_ekf_thresh) {
        over_thresh_count++;
    }

    if (over_thresh_count >= 2) {
        return true;
    }

    // either optflow relative or absolute position estimate OK
    // 若是前面不触发,则开始检查ekf位置是否OK,若是不OK则为真,反之为假。
    // 位置超时时候也是可以让ekf_position_ok为0;
    if (optflow_position_ok() || ekf_position_ok()) {
        return false;
    }
    return true;
}

// 返回更新一致性测试比率(协方差???)。

// return the innovation consistency test ratios for the velocity, position, magnetometer and true airspeed measurements
// this indicates the amount of margin available when tuning the various error traps
// also return the delta in position due to the last position reset
void  NavEKF2_core::getVariances(float &velVar, float &posVar, float &hgtVar, Vector3f &magVar, float &tasVar, Vector2f &offset) const
{
    velVar   = sqrtf(velTestRatio);
    posVar   = sqrtf(posTestRatio);
    hgtVar   = sqrtf(hgtTestRatio);
    // If we are using simple compass yaw fusion, populate all three components with the yaw test ratio to provide an equivalent output
    magVar.x = sqrtf(MAX(magTestRatio.x,yawTestRatio));
    magVar.y = sqrtf(MAX(magTestRatio.y,yawTestRatio));
    magVar.z = sqrtf(MAX(magTestRatio.z,yawTestRatio));
    tasVar   = sqrtf(tasTestRatio);
    offset   = posResetNE;
}

// 检查ekf位置估计是否正确。

// ekf_position_ok - returns true if the ekf claims it's horizontal absolute position estimate is ok and home position is set
bool Copter::ekf_position_ok()
{
    if (!ahrs.have_inertial_nav()) {
        // do not allow navigation with dcm position
        return false;
    }

    // with EKF use filter status and ekf check
    nav_filter_status filt_status = inertial_nav.get_filter_status();
	// Disarmed(锁定) Auto Armed(自动解锁)
    // if disarmed we accept a predicted horizontal position
    if (!motors->armed()) {
        return ((filt_status.flags.horiz_pos_abs || filt_status.flags.pred_horiz_pos_abs));
    } else {
        // once armed we require a good absolute position and EKF must not be in const_pos_mode
        // horiz_pos_abs 如果绝对水平位置估计有效,则为真
        //  filterStatus.flags.horiz_pos_abs = doingNormalGpsNav && filterHealthy; 
        //     bool doingNormalGpsNav = !posTimeout && (PV_AidingMode == AID_ABSOLUTE);
        /*     enum AidingMode {AID_ABSOLUTE=0,    // GPS or some other form of absolute position reference aiding is being used (optical flow may also be used in parallel) so position estimates are absolute.
                     AID_NONE=1,       // no aiding is being used so only attitude and height estimates are available. Either constVelMode or constPosMode must be used to constrain tilt drift.
                     AID_RELATIVE=2    // only optical flow aiding is being used so position estimates will be relative }; */
        // const_pos_mode 如果我们处于常量位置模式,则为真。
        //  filterStatus.flags.const_pos_mode = (PV_AidingMode == AID_NONE) && filterHealthy;
        return (filt_status.flags.horiz_pos_abs && !filt_status.flags.const_pos_mode);
    }
}

接下来去查下大多数协方差过大都是由于哪一项造成的?

发布了97 篇原创文章 · 获赞 56 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/hanjuefu5827/article/details/100023743
EKF