diff --git a/src/main/navigation/navigation_pos_estimator.c b/src/main/navigation/navigation_pos_estimator.c index d991ec6ee97..ab979446237 100755 --- a/src/main/navigation/navigation_pos_estimator.c +++ b/src/main/navigation/navigation_pos_estimator.c @@ -356,11 +356,11 @@ static void restartGravityCalibration(void) } static bool gravityCalibrationComplete(void) -{ +{ if (!gyroConfig()->init_gyro_cal_enabled) { return true; } - + return zeroCalibrationIsCompleteS(&posEstimator.imu.gravityCalibration); } @@ -686,6 +686,20 @@ static bool estimationCalculateCorrection_XY_GPS(estimationContext_t * ctx) return false; } +static void estimationCalculateGroundCourse(timeUs_t currentTimeUs) +{ + if (STATE(GPS_FIX) && navIsHeadingUsable()) { + static timeUs_t lastUpdateTimeUs = 0; + + if (currentTimeUs - lastUpdateTimeUs >= HZ2US(INAV_COG_UPDATE_RATE_HZ)) { // limit update rate + const float dt = US2S(currentTimeUs - lastUpdateTimeUs); + uint32_t groundCourse = wrap_36000(RADIANS_TO_CENTIDEGREES(atan2_approx(posEstimator.est.vel.y * dt, posEstimator.est.vel.x * dt))); + posEstimator.est.cog = CENTIDEGREES_TO_DECIDEGREES(groundCourse); + lastUpdateTimeUs = currentTimeUs; + } + } +} + /** * Calculate next estimate using IMU and apply corrections from reference sensors (GPS, BARO etc) * Function is called at main loop rate @@ -758,6 +772,9 @@ static void updateEstimatedTopic(timeUs_t currentTimeUs) } } + /* Update ground course */ + estimationCalculateGroundCourse(currentTimeUs); + /* Update uncertainty */ posEstimator.est.eph = ctx.newEPH; posEstimator.est.epv = ctx.newEPV; @@ -774,8 +791,10 @@ static void publishEstimatedTopic(timeUs_t currentTimeUs) { static navigationTimer_t posPublishTimer; - /* IMU operates in decidegrees while INAV operates in deg*100 */ - updateActualHeading(navIsHeadingUsable(), DECIDEGREES_TO_CENTIDEGREES(attitude.values.yaw)); + /* IMU operates in decidegrees while INAV operates in deg*100 + * Use course over ground for fixed wing navigation yaw/"heading" */ + int16_t yawValue = isGPSHeadingValid() && STATE(AIRPLANE) ? posEstimator.est.cog : attitude.values.yaw; + updateActualHeading(navIsHeadingUsable(), DECIDEGREES_TO_CENTIDEGREES(yawValue)); /* Position and velocity are published with INAV_POSITION_PUBLISH_RATE_HZ */ if (updateTimer(&posPublishTimer, HZ2US(INAV_POSITION_PUBLISH_RATE_HZ), currentTimeUs)) { diff --git a/src/main/navigation/navigation_pos_estimator_private.h b/src/main/navigation/navigation_pos_estimator_private.h index 80c66d2fc01..dd171fa8e62 100644 --- a/src/main/navigation/navigation_pos_estimator_private.h +++ b/src/main/navigation/navigation_pos_estimator_private.h @@ -39,6 +39,7 @@ #define INAV_POSITION_PUBLISH_RATE_HZ 50 // Publish position updates at this rate #define INAV_PITOT_UPDATE_RATE 10 +#define INAV_COG_UPDATE_RATE_HZ 20 // ground course update rate #define INAV_GPS_TIMEOUT_MS 1500 // GPS timeout #define INAV_BARO_TIMEOUT_MS 200 // Baro timeout @@ -125,6 +126,9 @@ typedef struct { // FLOW float flowCoordinates[2]; + + // COURSE + int16_t cog; // course over ground (decidegrees) } navPositionEstimatorESTIMATE_t; typedef struct {