コード例 #1
0
// return a ground speed estimate in m/s
Vector2f BC_AHRS::groundspeed_vector(void)
{
    // Generate estimate of ground speed vector using air data system
    Vector2f gndVelADS;
    Vector2f gndVelGPS;
    float airspeed;
    bool gotAirspeed = airspeed_estimate_true(&airspeed);
    bool gotGPS = (_gps.status() >= AP_GPS::GPS_OK_FIX_2D);
    if (gotAirspeed) {
	    Vector3f wind = wind_estimate();
	    Vector2f wind2d = Vector2f(wind.x, wind.y);
	    Vector2f airspeed_vector = Vector2f(cosf(yaw), sinf(yaw)) * airspeed;
	    gndVelADS = airspeed_vector - wind2d;
    }
    
    // Generate estimate of ground speed vector using GPS
    if (gotGPS) {
        float cog = radians(_gps.ground_course_cd()*0.01f);
        gndVelGPS = Vector2f(cosf(cog), sinf(cog)) * _gps.ground_speed();
    }
    // If both ADS and GPS data is available, apply a complementary filter
    if (gotAirspeed && gotGPS) {
	    // The LPF is applied to the GPS and the HPF is applied to the air data estimate
	    // before the two are summed
	    //Define filter coefficients
	    // alpha and beta must sum to one
	    // beta = dt/Tau, where
	    // dt = filter time step (0.1 sec if called by nav loop)
	    // Tau = cross-over time constant (nominal 2 seconds)
	    // More lag on GPS requires Tau to be bigger, less lag allows it to be smaller
	    // To-Do - set Tau as a function of GPS lag.
	    const float alpha = 1.0f - beta; 
	    // Run LP filters
	    _lp = gndVelGPS * beta  + _lp * alpha;
	    // Run HP filters
	    _hp = (gndVelADS - _lastGndVelADS) + _hp * alpha;
	    // Save the current ADS ground vector for the next time step
	    _lastGndVelADS = gndVelADS;
	    // Sum the HP and LP filter outputs
	    return _hp + _lp;
    }
    // Only ADS data is available return ADS estimate
    if (gotAirspeed && !gotGPS) {
	    return gndVelADS;
    }
    // Only GPS data is available so return GPS estimate
    if (!gotAirspeed && gotGPS) {
	    return gndVelGPS;
    }
    return Vector2f(0.0f, 0.0f);
}
コード例 #2
0
ファイル: AP_AHRS.cpp プロジェクト: BrendanSmith/ardupilot
/*
 * Update AOA and SSA estimation based on airspeed, velocity vector and wind vector
 *
 * Based on:
 * "On estimation of wind velocity, angle-of-attack and sideslip angle of small UAVs using standard sensors" by
 * Tor A. Johansen, Andrea Cristofaro, Kim Sorensen, Jakob M. Hansen, Thor I. Fossen
 *
 * "Multi-Stage Fusion Algorithm for Estimation of Aerodynamic Angles in Mini Aerial Vehicle" by
 * C.Ramprasadh and Hemendra Arya
 *
 * "ANGLE OF ATTACK AND SIDESLIP ESTIMATION USING AN INERTIAL REFERENCE PLATFORM" by
 * JOSEPH E. ZEIS, JR., CAPTAIN, USAF
 */
void AP_AHRS::update_AOA_SSA(void)
{
#if APM_BUILD_TYPE(APM_BUILD_ArduPlane)
    const uint32_t now = AP_HAL::millis();
    if (now - _last_AOA_update_ms < 50) {
        // don't update at more than 20Hz
        return;
    }
    _last_AOA_update_ms = now;
    
    Vector3f aoa_velocity, aoa_wind;

    // get velocity and wind
    if (get_velocity_NED(aoa_velocity) == false) {
        return;
    }

    aoa_wind = wind_estimate();

    // Rotate vectors to the body frame and calculate velocity and wind
    const Matrix3f &rot = get_rotation_body_to_ned();
    aoa_velocity = rot.mul_transpose(aoa_velocity);
    aoa_wind = rot.mul_transpose(aoa_wind);

    // calculate relative velocity in body coordinates
    aoa_velocity = aoa_velocity - aoa_wind;
    const float vel_len = aoa_velocity.length();

    // do not calculate if speed is too low
    if (vel_len < 2.0) {
        _AOA = 0;
        _SSA = 0;
        return;
    }

    // Calculate AOA and SSA
    if (aoa_velocity.x > 0) {
        _AOA = degrees(atanf(aoa_velocity.z / aoa_velocity.x));
    } else {
        _AOA = 0;
    }

    _SSA = degrees(safe_asin(aoa_velocity.y / vel_len));
#endif
}
コード例 #3
0
ファイル: AP_AHRS.cpp プロジェクト: rubdub/ArduPilot
// correct a bearing in centi-degrees for wind
void AP_AHRS::wind_correct_bearing(int32_t &nav_bearing_cd)
{
    if (!use_compass() || !_flags.wind_estimation) {
        // we are not using the compass - no wind correction,
        // as GPS gives course over ground already
        return;
    }

    // if we are using a compass for navigation, then adjust the
    // heading to account for wind
    Vector3f wind = wind_estimate();
    Vector2f wind2d = Vector2f(wind.x, wind.y);
    float speed;
    if (airspeed_estimate(&speed)) {
        Vector2f nav_vector = Vector2f(cos(radians(nav_bearing_cd*0.01)), sin(radians(nav_bearing_cd*0.01))) * speed;
        Vector2f nav_adjusted = nav_vector - wind2d;
        nav_bearing_cd = degrees(atan2(nav_adjusted.y, nav_adjusted.x)) * 100;
    }
}