예제 #1
0
// Resets the baro so that it reads zero at the current height
// Resets the EKF height to zero
// Adjusts the EKf origin height so that the EKF height + origin height is the same as before
// Returns true if the height datum reset has been performed
// If using a range finder for height no reset is performed and it returns false
bool AP_AHRS_NavEKF::resetHeightDatum(void)
{
    // support locked access functions to AHRS data
    WITH_SEMAPHORE(_rsem);
    
    switch (ekf_type()) {

    case 2:
    default: {
        EKF3.resetHeightDatum();
        return EKF2.resetHeightDatum();
    }

    case 3: {
        EKF2.resetHeightDatum();
        return EKF3.resetHeightDatum();
    }

#if CONFIG_HAL_BOARD == HAL_BOARD_SITL
    case EKF_TYPE_SITL:
        return false;
#endif
    }
    return false;
}
예제 #2
0
// run a full DCM update round
void
AP_AHRS_DCM::update(bool skip_ins_update)
{
    // support locked access functions to AHRS data
    WITH_SEMAPHORE(_rsem);
    
    float delta_t;

    if (_last_startup_ms == 0) {
        _last_startup_ms = AP_HAL::millis();
        load_watchdog_home();
    }

    if (!skip_ins_update) {
        // tell the IMU to grab some data
        AP::ins().update();
    }

    const AP_InertialSensor &_ins = AP::ins();

    // ask the IMU how much time this sensor reading represents
    delta_t = _ins.get_delta_time();

    // if the update call took more than 0.2 seconds then discard it,
    // otherwise we may move too far. This happens when arming motors
    // in ArduCopter
    if (delta_t > 0.2f) {
        memset((void *)&_ra_sum[0], 0, sizeof(_ra_sum));
        _ra_deltat = 0;
        return;
    }

    // Integrate the DCM matrix using gyro inputs
    matrix_update(delta_t);

    // Normalize the DCM matrix
    normalize();

    // Perform drift correction
    drift_correction(delta_t);

    // paranoid check for bad values in the DCM matrix
    check_matrix();

    // Calculate pitch, roll, yaw for stabilization and navigation
    euler_angles();

    // update trig values including _cos_roll, cos_pitch
    update_trig();

    // update AOA and SSA
    update_AOA_SSA();

    backup_attitude();
}
예제 #3
0
// reset the current gyro drift estimate
//  should be called if gyro offsets are recalculated
void AP_AHRS_NavEKF::reset_gyro_drift(void)
{
    // support locked access functions to AHRS data
    WITH_SEMAPHORE(_rsem);
    
    // update DCM
    AP_AHRS_DCM::reset_gyro_drift();

    // reset the EKF gyro bias states
    EKF2.resetGyroBias();
    EKF3.resetGyroBias();
}
예제 #4
0
// reset the current attitude, used on new IMU calibration
void AP_AHRS_NavEKF::reset_attitude(const float &_roll, const float &_pitch, const float &_yaw)
{
    // support locked access functions to AHRS data
    WITH_SEMAPHORE(_rsem);
    
    AP_AHRS_DCM::reset_attitude(_roll, _pitch, _yaw);
    _dcm_attitude(roll, pitch, yaw);
    if (_ekf2_started) {
        _ekf2_started = EKF2.InitialiseFilter();
    }
    if (_ekf3_started) {
        _ekf3_started = EKF3.InitialiseFilter();
    }
}
예제 #5
0
void AP_AHRS_NavEKF::reset(bool recover_eulers)
{
    // support locked access functions to AHRS data
    WITH_SEMAPHORE(_rsem);
    
    AP_AHRS_DCM::reset(recover_eulers);
    _dcm_attitude(roll, pitch, yaw);
    if (_ekf2_started) {
        _ekf2_started = EKF2.InitialiseFilter();
    }
    if (_ekf3_started) {
        _ekf3_started = EKF3.InitialiseFilter();
    }
}
예제 #6
0
// vel is north/east/down!
void AP_Avoidance::add_obstacle(const uint32_t obstacle_timestamp_ms,
                                const MAV_COLLISION_SRC src,
                                const uint32_t src_id,
                                const Location &loc,
                                const Vector3f &vel_ned)
{
    if (! check_startup()) {
        return;
    }
    uint32_t oldest_timestamp = std::numeric_limits<uint32_t>::max();
    uint8_t oldest_index = 255; // avoid compiler warning with initialisation
    int16_t index = -1;
    uint8_t i;
    for (i=0; i<_obstacle_count; i++) {
        if (_obstacles[i].src_id == src_id &&
            _obstacles[i].src == src) {
            // pre-existing obstacle found; we will update its information
            index = i;
            break;
        }
        if (_obstacles[i].timestamp_ms < oldest_timestamp) {
            oldest_timestamp = _obstacles[i].timestamp_ms;
            oldest_index = i;
        }
    }
    WITH_SEMAPHORE(_rsem);
    
    if (index == -1) {
        // existing obstacle not found.  See if we can store it anyway:
        if (i <_obstacles_allocated) {
            // have room to store more vehicles...
            index = _obstacle_count++;
        } else if (oldest_timestamp < obstacle_timestamp_ms) {
            // replace this very old entry with this new data
            index = oldest_index;
        } else {
            // no room for this (old?!) data
            return;
        }

        _obstacles[index].src = src;
        _obstacles[index].src_id = src_id;
    }

    _obstacles[index]._location = loc;
    _obstacles[index]._velocity = vel_ned;
    _obstacles[index].timestamp_ms = obstacle_timestamp_ms;
}
예제 #7
0
void AP_AHRS_NavEKF::update(bool skip_ins_update)
{
    // support locked access functions to AHRS data
    WITH_SEMAPHORE(_rsem);
    
    // drop back to normal priority if we were boosted by the INS
    // calling delay_microseconds_boost()
    hal.scheduler->boost_end();
    
    // EKF1 is no longer supported - handle case where it is selected
    if (_ekf_type == 1) {
        _ekf_type.set(2);
    }

    update_DCM(skip_ins_update);

#if CONFIG_HAL_BOARD == HAL_BOARD_SITL
    update_SITL();
#endif

    if (_ekf_type == 2) {
        // if EK2 is primary then run EKF2 first to give it CPU
        // priority
        update_EKF2();
        update_EKF3();
    } else {
        // otherwise run EKF3 first
        update_EKF3();
        update_EKF2();
    }

#if AP_MODULE_SUPPORTED
    // call AHRS_update hook if any
    AP_Module::call_hook_AHRS_update(*this);
#endif

    // push gyros if optical flow present
    if (hal.opticalflow) {
        const Vector3f &exported_gyro_bias = get_gyro_drift();
        hal.opticalflow->push_gyro_bias(exported_gyro_bias.x, exported_gyro_bias.y);
    }

    if (_view != nullptr) {
        // update optional alternative attitude view
        _view->update(skip_ins_update);
    }
}
예제 #8
0
/*
 *  reset the DCM matrix and omega. Used on ground start, and on
 *  extreme errors in the matrix
 */
void
AP_AHRS_DCM::reset(bool recover_eulers)
{
    // support locked access functions to AHRS data
    WITH_SEMAPHORE(_rsem);
    
    // reset the integration terms
    _omega_I.zero();
    _omega_P.zero();
    _omega_yaw_P.zero();
    _omega.zero();

    // if the caller wants us to try to recover to the current
    // attitude then calculate the dcm matrix from the current
    // roll/pitch/yaw values
    if (hal.util->was_watchdog_reset() && AP_HAL::millis() < 10000) {
        const AP_HAL::Util::PersistentData &pd = hal.util->persistent_data;
        roll = pd.roll_rad;
        pitch = pd.pitch_rad;
        yaw = pd.yaw_rad;
        _dcm_matrix.from_euler(roll, pitch, yaw);
        gcs().send_text(MAV_SEVERITY_INFO, "Restored watchdog attitude %.0f %.0f %.0f",
                        degrees(roll), degrees(pitch), degrees(yaw));
    } else if (recover_eulers && !isnan(roll) && !isnan(pitch) && !isnan(yaw)) {
        _dcm_matrix.from_euler(roll, pitch, yaw);
    } else {

        // Use the measured accel due to gravity to calculate an initial
        // roll and pitch estimate

        AP_InertialSensor &_ins = AP::ins();

        // Get body frame accel vector
        Vector3f initAccVec = _ins.get_accel();
        uint8_t counter = 0;

        // the first vector may be invalid as the filter starts up
        while ((initAccVec.length() < 9.0f || initAccVec.length() > 11) && counter++ < 20) {
            _ins.wait_for_sample();
            _ins.update();
            initAccVec = _ins.get_accel();
        }

        // normalise the acceleration vector
        if (initAccVec.length() > 5.0f) {
            // calculate initial pitch angle
            pitch = atan2f(initAccVec.x, norm(initAccVec.y, initAccVec.z));
            // calculate initial roll angle
            roll = atan2f(-initAccVec.y, -initAccVec.z);
        } else {
            // If we can't use the accel vector, then align flat
            roll = 0.0f;
            pitch = 0.0f;
        }
        _dcm_matrix.from_euler(roll, pitch, 0);

    }

    if (_last_startup_ms == 0) {
        load_watchdog_home();
    }
    _last_startup_ms = AP_HAL::millis();
}