コード例 #1
0
ファイル: AP_AHRS_MPU6000.cpp プロジェクト: Bieghe/Arduino
//
// drift_correction_yaw - yaw drift correction using the compass
//
void
AP_AHRS_MPU6000::drift_correction_yaw(void)
{
    static float yaw_last_uncorrected = HEADING_UNKNOWN;
    static float yaw_corrected = HEADING_UNKNOWN;
    float yaw_delta = 0;
    bool new_value = false;
    float yaw_error;
    static float heading;

    // we assume the DCM matrix is completely uncorrect for yaw
    // retrieve how much heading has changed according to non-corrected dcm
    if( yaw_last_uncorrected != HEADING_UNKNOWN ) {
        yaw_delta = wrap_PI(yaw - yaw_last_uncorrected);                // the change in heading according to the gyros only since the last interation
        yaw_last_uncorrected = yaw;
    }

    // initialise yaw_corrected (if necessary)
    if( yaw_corrected != HEADING_UNKNOWN ) {
        yaw_corrected = yaw;
    }else{
        yaw_corrected = wrap_PI(yaw_corrected + yaw_delta);             // best guess of current yaw is previous iterations corrected yaw + yaw change from gyro
        _dcm_matrix.from_euler(roll, pitch, yaw_corrected);                     // rebuild dcm matrix with best guess at current yaw
    }

    // if we have new compass data
    if( _compass && _compass->use_for_yaw() ) {
        if (_compass->last_update != _compass_last_update) {
            _compass_last_update = _compass->last_update;
            heading = _compass->calculate_heading(_dcm_matrix);
            if( !_have_initial_yaw ) {
                yaw_corrected = heading;
                _have_initial_yaw = true;
                _dcm_matrix.from_euler(roll, pitch, yaw_corrected);                             // rebuild dcm matrix with best guess at current yaw
            }
            new_value = true;
        }
    }

    // perform the yaw correction
    if( new_value ) {
        yaw_error = yaw_error_compass();
        // the yaw error is a vector in earth frame
        //Vector3f error = Vector3f(0,0, yaw_error);

        // convert the error vector to body frame
        //error = _dcm_matrix.mul_transpose(error);

        // Update the differential component to reduce the error (it´s like a P control)
        yaw_corrected += wrap_PI(yaw_error * _kp_yaw.get());                    // probably completely wrong

        // rebuild the dcm matrix yet again
        _dcm_matrix.from_euler(roll, pitch, yaw_corrected);
    }
}
コード例 #2
0
ファイル: AP_AHRS_DCM.cpp プロジェクト: TimothyGold/ardupilot
// yaw drift correction using the compass or GPS
// this function prodoces the _omega_yaw_P vector, and also
// contributes to the _omega_I.z long term yaw drift estimate
void
AP_AHRS_DCM::drift_correction_yaw(void)
{
    bool new_value = false;
    float yaw_error;
    float yaw_deltat;

    if (AP_AHRS_DCM::use_compass()) {
        /*
          we are using compass for yaw
         */
        if (_compass->last_update_usec() != _compass_last_update) {
            yaw_deltat = (_compass->last_update_usec() - _compass_last_update) * 1.0e-6f;
            _compass_last_update = _compass->last_update_usec();
            // we force an additional compass read()
            // here. This has the effect of throwing away
            // the first compass value, which can be bad
            if (!_flags.have_initial_yaw && _compass->read()) {
                float heading = _compass->calculate_heading(_dcm_matrix);
                _dcm_matrix.from_euler(roll, pitch, heading);
                _omega_yaw_P.zero();
                _flags.have_initial_yaw = true;
            }
            new_value = true;
            yaw_error = yaw_error_compass();

            // also update the _gps_last_update, so if we later
            // disable the compass due to significant yaw error we
            // don't suddenly change yaw with a reset
            _gps_last_update = _gps.last_fix_time_ms();
        }
    } else if (_flags.fly_forward && have_gps()) {
        /*
          we are using GPS for yaw
         */
        if (_gps.last_fix_time_ms() != _gps_last_update &&
                _gps.ground_speed() >= GPS_SPEED_MIN) {
            yaw_deltat = (_gps.last_fix_time_ms() - _gps_last_update) * 1.0e-3f;
            _gps_last_update = _gps.last_fix_time_ms();
            new_value = true;
            float gps_course_rad = ToRad(_gps.ground_course_cd() * 0.01f);
            float yaw_error_rad = wrap_PI(gps_course_rad - yaw);
            yaw_error = sinf(yaw_error_rad);

            /* reset yaw to match GPS heading under any of the
               following 3 conditions:

               1) if we have reached GPS_SPEED_MIN and have never had
               yaw information before

               2) if the last time we got yaw information from the GPS
               is more than 20 seconds ago, which means we may have
               suffered from considerable gyro drift

               3) if we are over 3*GPS_SPEED_MIN (which means 9m/s)
               and our yaw error is over 60 degrees, which means very
               poor yaw. This can happen on bungee launch when the
               operator pulls back the plane rapidly enough then on
               release the GPS heading changes very rapidly
            */
            if (!_flags.have_initial_yaw ||
                    yaw_deltat > 20 ||
                    (_gps.ground_speed() >= 3*GPS_SPEED_MIN && fabsf(yaw_error_rad) >= 1.047f)) {
                // reset DCM matrix based on current yaw
                _dcm_matrix.from_euler(roll, pitch, gps_course_rad);
                _omega_yaw_P.zero();
                _flags.have_initial_yaw = true;
                yaw_error = 0;
            }
        }
    }

    if (!new_value) {
        // we don't have any new yaw information
        // slowly decay _omega_yaw_P to cope with loss
        // of our yaw source
        _omega_yaw_P *= 0.97f;
        return;
    }

    // convert the error vector to body frame
    float error_z = _dcm_matrix.c.z * yaw_error;

    // the spin rate changes the P gain, and disables the
    // integration at higher rates
    float spin_rate = _omega.length();

    // sanity check _kp_yaw
    if (_kp_yaw < AP_AHRS_YAW_P_MIN) {
        _kp_yaw = AP_AHRS_YAW_P_MIN;
    }

    // update the proportional control to drag the
    // yaw back to the right value. We use a gain
    // that depends on the spin rate. See the fastRotations.pdf
    // paper from Bill Premerlani
    // We also adjust the gain depending on the rate of change of horizontal velocity which
    // is proportional to how observable the heading is from the acceerations and GPS velocity
    // The accelration derived heading will be more reliable in turns than compass or GPS

    _omega_yaw_P.z = error_z * _P_gain(spin_rate) * _kp_yaw * _yaw_gain();
    if (use_fast_gains()) {
        _omega_yaw_P.z *= 8;
    }

    // don't update the drift term if we lost the yaw reference
    // for more than 2 seconds
    if (yaw_deltat < 2.0f && spin_rate < ToRad(SPIN_RATE_LIMIT)) {
        // also add to the I term
        _omega_I_sum.z += error_z * _ki_yaw * yaw_deltat;
    }

    _error_yaw = 0.8f * _error_yaw + 0.2f * fabsf(yaw_error);
}
コード例 #3
0
ファイル: AP_AHRS_DCM.cpp プロジェクト: icer1/QuadPID
// yaw drift correction using the compass or GPS
// this function prodoces the _omega_yaw_P vector, and also
// contributes to the _omega_I.z long term yaw drift estimate
void
AP_AHRS_DCM::drift_correction_yaw(void)
{
	bool new_value = false;
	float yaw_error;
	float yaw_deltat;

	if (_compass && _compass->use_for_yaw()) {
		if (_compass->last_update != _compass_last_update) {
			yaw_deltat = (_compass->last_update - _compass_last_update) * 1.0e-6;
			_compass_last_update = _compass->last_update;
			if (!_have_initial_yaw) {
				float heading = _compass->calculate_heading(_dcm_matrix);
				_dcm_matrix.from_euler(roll, pitch, heading);
				_omega_yaw_P.zero();
				_have_initial_yaw = true;
			}
			new_value = true;
			yaw_error = yaw_error_compass();
		}
	} else if (_fly_forward && _gps && _gps->status() == GPS::GPS_OK) {
		if (_gps->last_fix_time != _gps_last_update &&
		    _gps->ground_speed >= GPS_SPEED_MIN) {
			yaw_deltat = (_gps->last_fix_time - _gps_last_update) * 1.0e-3;
			_gps_last_update = _gps->last_fix_time;
			if (!_have_initial_yaw) {
				_dcm_matrix.from_euler(roll, pitch, ToRad(_gps->ground_course*0.01));
				_omega_yaw_P.zero();
				_have_initial_yaw = true;
			}
			new_value = true;
			yaw_error = yaw_error_gps();
		}
	}

	if (!new_value) {
		// we don't have any new yaw information
		// slowly decay _omega_yaw_P to cope with loss
		// of our yaw source
		_omega_yaw_P *= 0.97;
		return;
	}

	// the yaw error is a vector in earth frame
	Vector3f error = Vector3f(0,0, yaw_error);

	// convert the error vector to body frame
	error = _dcm_matrix.mul_transpose(error);

	// the spin rate changes the P gain, and disables the
	// integration at higher rates
	float spin_rate = _omega.length();

	// update the proportional control to drag the
	// yaw back to the right value. We use a gain
	// that depends on the spin rate. See the fastRotations.pdf
	// paper from Bill Premerlani

	_omega_yaw_P.z = error.z * _P_gain(spin_rate) * _kp_yaw.get();

	// don't update the drift term if we lost the yaw reference
	// for more than 2 seconds
	if (yaw_deltat < 2.0 && spin_rate < ToRad(SPIN_RATE_LIMIT)) {
		// also add to the I term
		_omega_I_sum.z += error.z * _ki_yaw * yaw_deltat;
	}

	_error_yaw_sum += fabs(yaw_error);
	_error_yaw_count++;
}