From 0246892708759f16d6910e6e570f7b5ce5acc582 Mon Sep 17 00:00:00 2001 From: breadoven <56191411+breadoven@users.noreply.github.com> Date: Tue, 7 Nov 2023 23:20:49 +0000 Subject: [PATCH 01/14] initial build --- src/main/navigation/navigation.c | 109 ++++++++++--------- src/main/navigation/navigation_fixedwing.c | 46 +++----- src/main/navigation/navigation_multicopter.c | 35 +++--- src/main/navigation/navigation_private.h | 6 +- 4 files changed, 92 insertions(+), 104 deletions(-) diff --git a/src/main/navigation/navigation.c b/src/main/navigation/navigation.c index c566c94bfad..57a6ba5c066 100644 --- a/src/main/navigation/navigation.c +++ b/src/main/navigation/navigation.c @@ -2927,8 +2927,7 @@ void setDesiredPosition(const fpVector3_t * pos, int32_t yaw, navSetWaypointFlag // Z-position if ((useMask & NAV_POS_UPDATE_Z) != 0) { - updateClimbRateToAltitudeController(0, 0, ROC_TO_ALT_RESET); // Reset RoC/RoD -> altitude controller - posControl.desiredState.pos.z = pos->z; + updateClimbRateToAltitudeController(navConfig()->general.max_auto_climb_rate, pos->z, ROC_TO_ALT_TARGET); } // Heading @@ -3036,66 +3035,68 @@ bool isProbablyStillFlying(void) /*----------------------------------------------------------- * Z-position controller *-----------------------------------------------------------*/ -void updateClimbRateToAltitudeController(float desiredClimbRate, float targetAltitude, climbRateToAltitudeControllerMode_e mode) +static bool isMaxAltitudeLimitExceeded(void) { -#define MIN_TARGET_CLIMB_RATE 100.0f // cm/s + return navGetCurrentActualPositionAndVelocity()->pos.z >= navConfig()->general.max_altitude; +} - static timeUs_t lastUpdateTimeUs; - timeUs_t currentTimeUs = micros(); +int32_t getDesiredClimbRate(float targetAltitude, timeDelta_t deltaMicros) +{ + if (navConfig()->general.max_altitude && isMaxAltitudeLimitExceeded()) { + targetAltitude = MIN(targetAltitude, navConfig()->general.max_altitude); + } - // Terrain following uses different altitude measurement - const float altitudeToUse = navGetCurrentActualPositionAndVelocity()->pos.z; + const bool emergLandingIsActive = navigationIsExecutingAnEmergencyLanding(); - if (mode != ROC_TO_ALT_RESET && desiredClimbRate) { - /* ROC_TO_ALT_CONSTANT - constant climb rate - * ROC_TO_ALT_TARGET - constant climb rate until close to target altitude reducing to min rate when altitude reached - * Rate reduction starts at distance from target altitude of 5 x climb rate for FW, 1 x climb rate for MC */ + float maxClimbRate = navConfig()->general.max_auto_climb_rate; + if (emergLandingIsActive) { + maxClimbRate = navConfig()->general.emerg_descent_rate; + } else if (posControl.flags.isAdjustingAltitude) { + maxClimbRate = navConfig()->general.max_manual_climb_rate; + } + const float targetAltitudeError = targetAltitude - navGetCurrentActualPositionAndVelocity()->pos.z; + float targetVel = 0.0f; - if (mode == ROC_TO_ALT_TARGET && fabsf(desiredClimbRate) > MIN_TARGET_CLIMB_RATE) { - const int8_t direction = desiredClimbRate > 0 ? 1 : -1; - const float absClimbRate = fabsf(desiredClimbRate); - const uint16_t maxRateCutoffAlt = STATE(AIRPLANE) ? absClimbRate * 5 : absClimbRate; - const float verticalVelScaled = scaleRangef(navGetCurrentActualPositionAndVelocity()->pos.z - targetAltitude, - 0.0f, -maxRateCutoffAlt * direction, MIN_TARGET_CLIMB_RATE, absClimbRate); + if (STATE(MULTIROTOR)) { + targetVel = getSqrtControllerVelocity(targetAltitude, deltaMicros); + } else { + targetVel = scaleRangef(targetAltitudeError, 0.0f, maxClimbRate * 5, 0.0f, maxClimbRate); + } - desiredClimbRate = direction * constrainf(verticalVelScaled, MIN_TARGET_CLIMB_RATE, absClimbRate); - } + if (emergLandingIsActive && targetAltitudeError > -50) { + return -100; + } else { + return constrainf(targetVel, -maxClimbRate, maxClimbRate); + } +} - /* - * If max altitude is set, reset climb rate if altitude is reached and climb rate is > 0 - * In other words, when altitude is reached, allow it only to shrink - */ - if (navConfig()->general.max_altitude > 0 && altitudeToUse >= navConfig()->general.max_altitude && desiredClimbRate > 0) { - desiredClimbRate = 0; - } +void updateClimbRateToAltitudeController(float desiredClimbRate, float targetAltitude, climbRateToAltitudeControllerMode_e mode) +{ + /* ROC_TO_ALT_CONSTANT - constant climb rate. desiredClimbRate direction (+ or -) is required + * ROC_TO_ALT_TARGET - constant climb rate until close to target altitude reducing to min rate when altitude reached + * Rate reduction starts at distance from target altitude of 5 x climb rate for FW, 1 x climb rate for MC. + * desiredClimbRate direction isn't required, set by target altitude direction instead + * NAV_IMPOSSIBLE_ALTITUDE_TARGET simply uses posControl.desiredState.pos.z to set a constant climb rate */ - if (STATE(FIXED_WING_LEGACY)) { - // Fixed wing climb rate controller is open-loop. We simply move the known altitude target - float timeDelta = US2S(currentTimeUs - lastUpdateTimeUs); - static bool targetHoldActive = false; - - if (timeDelta <= HZ2S(MIN_POSITION_UPDATE_RATE_HZ) && desiredClimbRate) { - // Update target altitude only if actual altitude moving in same direction and lagging by < 5 m, otherwise hold target - if (navGetCurrentActualPositionAndVelocity()->vel.z * desiredClimbRate >= 0 && fabsf(posControl.desiredState.pos.z - altitudeToUse) < 500) { - posControl.desiredState.pos.z += desiredClimbRate * timeDelta; - targetHoldActive = false; - } else if (!targetHoldActive) { // Reset and hold target to actual + climb rate boost until actual catches up - posControl.desiredState.pos.z = altitudeToUse + desiredClimbRate; - targetHoldActive = true; - } - } else { - targetHoldActive = false; - } - } - else { - // Multicopter climb-rate control is closed-loop, it's possible to directly calculate desired altitude setpoint to yield the required RoC/RoD - posControl.desiredState.pos.z = altitudeToUse + (desiredClimbRate / posControl.pids.pos[Z].param.kP); - } - } else { // ROC_TO_ALT_RESET or zero desired climbrate + // Terrain following uses different altitude measurement + const float altitudeToUse = navGetCurrentActualPositionAndVelocity()->pos.z; + + if (mode == ROC_TO_ALT_RESET) { posControl.desiredState.pos.z = altitudeToUse; + } else if (mode == ROC_TO_ALT_TARGET) { + posControl.desiredState.pos.z = targetAltitude; + } else { // ROC_TO_ALT_CONSTANT + posControl.desiredState.pos.z = NAV_IMPOSSIBLE_ALTITUDE_TARGET; + } + + /* + * If max altitude is set and altitude limit reached reset altitude target to max altitude unless desired climb rate is -ve + */ + if (navConfig()->general.max_altitude && isMaxAltitudeLimitExceeded() && desiredClimbRate >= 0.0f) { + posControl.desiredState.pos.z = MIN(posControl.desiredState.pos.z, navConfig()->general.max_altitude); } - lastUpdateTimeUs = currentTimeUs; + posControl.desiredState.vel.z = desiredClimbRate; } static void resetAltitudeController(bool useTerrainFollowing) @@ -4317,9 +4318,9 @@ void navigationUsePIDs(void) 0.0f ); - navPidInit(&posControl.pids.fw_alt, (float)pidProfile()->bank_fw.pid[PID_POS_Z].P / 10.0f, - (float)pidProfile()->bank_fw.pid[PID_POS_Z].I / 10.0f, - (float)pidProfile()->bank_fw.pid[PID_POS_Z].D / 10.0f, + navPidInit(&posControl.pids.fw_alt, (float)pidProfile()->bank_fw.pid[PID_POS_Z].P / 100.0f, + (float)pidProfile()->bank_fw.pid[PID_POS_Z].I / 100.0f, + (float)pidProfile()->bank_fw.pid[PID_POS_Z].D / 100.0f, 0.0f, NAV_DTERM_CUT_HZ, 0.0f diff --git a/src/main/navigation/navigation_fixedwing.c b/src/main/navigation/navigation_fixedwing.c index e6084e0972e..c5dde6dba48 100755 --- a/src/main/navigation/navigation_fixedwing.c +++ b/src/main/navigation/navigation_fixedwing.c @@ -123,7 +123,7 @@ bool adjustFixedWingAltitudeFromRCInput(void) else { // Adjusting finished - reset desired position to stay exactly where pilot released the stick if (posControl.flags.isAdjustingAltitude) { - updateClimbRateToAltitudeController(0, 0, ROC_TO_ALT_RESET); + updateClimbRateToAltitudeController(navConfig()->general.max_auto_climb_rate, 0, ROC_TO_ALT_RESET); } return false; } @@ -134,46 +134,34 @@ static void updateAltitudeVelocityAndPitchController_FW(timeDelta_t deltaMicros) { static pt1Filter_t velzFilterState; - // On a fixed wing we might not have a reliable climb rate source (if no BARO available), so we can't apply PID controller to - // velocity error. We use PID controller on altitude error and calculate desired pitch angle + float desiredClimbRate = posControl.desiredState.vel.z; - // Update energies - const float demSPE = (posControl.desiredState.pos.z * 0.01f) * GRAVITY_MSS; - const float demSKE = 0.0f; - - const float estSPE = (navGetCurrentActualPositionAndVelocity()->pos.z * 0.01f) * GRAVITY_MSS; - const float estSKE = 0.0f; - - // speedWeight controls balance between potential and kinetic energy used for pitch controller - // speedWeight = 1.0 : pitch will only control airspeed and won't control altitude - // speedWeight = 0.5 : pitch will be used to control both airspeed and altitude - // speedWeight = 0.0 : pitch will only control altitude - const float speedWeight = 0.0f; // no speed sensing for now - - const float demSEB = demSPE * (1.0f - speedWeight) - demSKE * speedWeight; - const float estSEB = estSPE * (1.0f - speedWeight) - estSKE * speedWeight; + if (posControl.desiredState.pos.z != NAV_IMPOSSIBLE_ALTITUDE_TARGET) { + desiredClimbRate = getDesiredClimbRate(posControl.desiredState.pos.z, deltaMicros); + } - // SEB to pitch angle gain to account for airspeed (with respect to specified reference (tuning) speed - const float pitchGainInv = 1.0f / 1.0f; + // Reduce max allowed climb pitch if performing loiter (stall prevention) + if (needToCalculateCircularLoiter && desiredClimbRate > 0.0f) { + desiredClimbRate *= 0.67f; + } // Here we use negative values for dive for better clarity - float maxClimbDeciDeg = DEGREES_TO_DECIDEGREES(navConfig()->fw.max_climb_angle); + const float maxClimbDeciDeg = DEGREES_TO_DECIDEGREES(navConfig()->fw.max_climb_angle); const float minDiveDeciDeg = -DEGREES_TO_DECIDEGREES(navConfig()->fw.max_dive_angle); - // Reduce max allowed climb pitch if performing loiter (stall prevention) - if (needToCalculateCircularLoiter) { - maxClimbDeciDeg = maxClimbDeciDeg * 0.67f; - } - - // PID controller to translate energy balance error [J] into pitch angle [decideg] - float targetPitchAngle = navPidApply3(&posControl.pids.fw_alt, demSEB, estSEB, US2S(deltaMicros), minDiveDeciDeg, maxClimbDeciDeg, 0, pitchGainInv, 1.0f); + // PID controller to translate desired climb rate error into pitch angle [decideg] + float currentClimbRate = navGetCurrentActualPositionAndVelocity()->vel.z; + float targetPitchAngle = navPidApply2(&posControl.pids.fw_alt, desiredClimbRate, currentClimbRate, US2S(deltaMicros), minDiveDeciDeg, maxClimbDeciDeg, PID_DTERM_FROM_ERROR); // Apply low-pass filter to prevent rapid correction targetPitchAngle = pt1FilterApply4(&velzFilterState, targetPitchAngle, getSmoothnessCutoffFreq(NAV_FW_BASE_PITCH_CUTOFF_FREQUENCY_HZ), US2S(deltaMicros)); - // Reconstrain pitch angle ( >0 - climb, <0 - dive) + // Reconstrain pitch angle (> 0 - climb, < 0 - dive) targetPitchAngle = constrainf(targetPitchAngle, minDiveDeciDeg, maxClimbDeciDeg); posControl.rcAdjustment[PITCH] = targetPitchAngle; + + posControl.desiredState.vel.z = desiredClimbRate; + navDesiredVelocity[Z] = constrain(lrintf(posControl.desiredState.vel.z), -32678, 32767); } void applyFixedWingAltitudeAndThrottleController(timeUs_t currentTimeUs) diff --git a/src/main/navigation/navigation_multicopter.c b/src/main/navigation/navigation_multicopter.c index 2264d842014..935665ee60e 100644 --- a/src/main/navigation/navigation_multicopter.c +++ b/src/main/navigation/navigation_multicopter.c @@ -63,28 +63,26 @@ static pt1Filter_t altholdThrottleFilterState; static bool prepareForTakeoffOnReset = false; static sqrt_controller_t alt_hold_sqrt_controller; -// Position to velocity controller for Z axis -static void updateAltitudeVelocityController_MC(timeDelta_t deltaMicros) +float getSqrtControllerVelocity(float targetAltitude, timeDelta_t deltaMicros) { - float targetVel = sqrtControllerApply( - &alt_hold_sqrt_controller, - posControl.desiredState.pos.z, - navGetCurrentActualPositionAndVelocity()->pos.z, - US2S(deltaMicros) + return sqrtControllerApply( + &alt_hold_sqrt_controller, + targetAltitude, + navGetCurrentActualPositionAndVelocity()->pos.z, + US2S(deltaMicros) ); +} - // hard limit desired target velocity to max_climb_rate - float vel_max_z = 0.0f; +// Position to velocity controller for Z axis +static void updateAltitudeVelocityController_MC(timeDelta_t deltaMicros) +{ + float targetVel = posControl.desiredState.vel.z; - if (posControl.flags.isAdjustingAltitude) { - vel_max_z = navConfig()->general.max_manual_climb_rate; - } else { - vel_max_z = navConfig()->general.max_auto_climb_rate; + if (posControl.desiredState.pos.z != NAV_IMPOSSIBLE_ALTITUDE_TARGET) { + targetVel = getDesiredClimbRate(posControl.desiredState.pos.z, deltaMicros); } - targetVel = constrainf(targetVel, -vel_max_z, vel_max_z); - - posControl.pids.pos[Z].output_constrained = targetVel; + posControl.pids.pos[Z].output_constrained = targetVel; // only used for Blackbox and OSD info // Limit max up/down acceleration target const float smallVelChange = US2S(deltaMicros) * (GRAVITY_CMSS * 0.1f); @@ -132,8 +130,7 @@ bool adjustMulticopterAltitudeFromRCInput(void) // In terrain follow mode we apply different logic for terrain control if (posControl.flags.estAglStatus == EST_TRUSTED && altTarget > 10.0f) { // We have solid terrain sensor signal - directly map throttle to altitude - updateClimbRateToAltitudeController(0, 0, ROC_TO_ALT_RESET); - posControl.desiredState.pos.z = altTarget; + updateClimbRateToAltitudeController(navConfig()->general.max_manual_climb_rate, altTarget, ROC_TO_ALT_TARGET); } else { updateClimbRateToAltitudeController(-50.0f, 0, ROC_TO_ALT_CONSTANT); @@ -165,7 +162,7 @@ bool adjustMulticopterAltitudeFromRCInput(void) else { // Adjusting finished - reset desired position to stay exactly where pilot released the stick if (posControl.flags.isAdjustingAltitude) { - updateClimbRateToAltitudeController(0, 0, ROC_TO_ALT_RESET); + updateClimbRateToAltitudeController(navConfig()->general.max_auto_climb_rate, 0, ROC_TO_ALT_RESET); } return false; diff --git a/src/main/navigation/navigation_private.h b/src/main/navigation/navigation_private.h index c408f109c9b..35e5492c6f1 100644 --- a/src/main/navigation/navigation_private.h +++ b/src/main/navigation/navigation_private.h @@ -47,6 +47,8 @@ #define NAV_RTH_TRACKBACK_POINTS 50 // max number RTH trackback points +#define NAV_IMPOSSIBLE_ALTITUDE_TARGET 10000000 // 100km in cm. Serves as a flag for vertical velocity control + #define MAX_POSITION_UPDATE_INTERVAL_US HZ2US(MIN_POSITION_UPDATE_RATE_HZ) // convenience macro _Static_assert(MAX_POSITION_UPDATE_INTERVAL_US <= TIMEDELTA_MAX, "deltaMicros can overflow!"); @@ -481,6 +483,7 @@ bool isWaypointNavTrackingActive(void); void updateActualHeading(bool headingValid, int32_t newHeading, int32_t newGroundCourse); void updateActualHorizontalPositionAndVelocity(bool estPosValid, bool estVelValid, float newX, float newY, float newVelX, float newVelY); void updateActualAltitudeAndClimbRate(bool estimateValid, float newAltitude, float newVelocity, float surfaceDistance, float surfaceVelocity, navigationEstimateStatus_e surfaceStatus, float gpsCfEstimatedAltitudeError); +int32_t getDesiredClimbRate(float targetAltitude, timeDelta_t deltaMicros); bool checkForPositionSensorTimeout(void); @@ -499,10 +502,9 @@ bool adjustMulticopterHeadingFromRCInput(void); bool adjustMulticopterPositionFromRCInput(int16_t rcPitchAdjustment, int16_t rcRollAdjustment); void applyMulticopterNavigationController(navigationFSMStateFlags_t navStateFlags, timeUs_t currentTimeUs); - bool isMulticopterLandingDetected(void); - void calculateMulticopterInitialHoldPosition(fpVector3_t * pos); +float getSqrtControllerVelocity(float targetAltitude, timeDelta_t deltaMicros); /* Fixed-wing specific functions */ void setupFixedWingAltitudeController(void); From 7ae41ad928348b0d253b6df49eace47138e0358c Mon Sep 17 00:00:00 2001 From: breadoven <56191411+breadoven@users.noreply.github.com> Date: Wed, 8 Nov 2023 22:48:33 +0000 Subject: [PATCH 02/14] cleanup + add roc to alt flag --- src/main/navigation/navigation.c | 26 +++++++++++--------- src/main/navigation/navigation_fixedwing.c | 6 ++--- src/main/navigation/navigation_multicopter.c | 9 +++---- src/main/navigation/navigation_private.h | 4 +-- 4 files changed, 24 insertions(+), 21 deletions(-) diff --git a/src/main/navigation/navigation.c b/src/main/navigation/navigation.c index 57a6ba5c066..f18c1cdc567 100644 --- a/src/main/navigation/navigation.c +++ b/src/main/navigation/navigation.c @@ -2927,7 +2927,7 @@ void setDesiredPosition(const fpVector3_t * pos, int32_t yaw, navSetWaypointFlag // Z-position if ((useMask & NAV_POS_UPDATE_Z) != 0) { - updateClimbRateToAltitudeController(navConfig()->general.max_auto_climb_rate, pos->z, ROC_TO_ALT_TARGET); + updateClimbRateToAltitudeController(0, pos->z, ROC_TO_ALT_TARGET); } // Heading @@ -3060,11 +3060,12 @@ int32_t getDesiredClimbRate(float targetAltitude, timeDelta_t deltaMicros) if (STATE(MULTIROTOR)) { targetVel = getSqrtControllerVelocity(targetAltitude, deltaMicros); } else { - targetVel = scaleRangef(targetAltitudeError, 0.0f, maxClimbRate * 5, 0.0f, maxClimbRate); + // 0.2f relates to climb rate starting to reduce from maxClimbRate at a distance of 5 x maxClimbRate from targetAltitude + targetVel = 0.2f * targetAltitudeError; } if (emergLandingIsActive && targetAltitudeError > -50) { - return -100; + return -100; // maintain 1 m/s descent during emerg landing when approaching T/O altitude } else { return constrainf(targetVel, -maxClimbRate, maxClimbRate); } @@ -3072,11 +3073,14 @@ int32_t getDesiredClimbRate(float targetAltitude, timeDelta_t deltaMicros) void updateClimbRateToAltitudeController(float desiredClimbRate, float targetAltitude, climbRateToAltitudeControllerMode_e mode) { - /* ROC_TO_ALT_CONSTANT - constant climb rate. desiredClimbRate direction (+ or -) is required - * ROC_TO_ALT_TARGET - constant climb rate until close to target altitude reducing to min rate when altitude reached - * Rate reduction starts at distance from target altitude of 5 x climb rate for FW, 1 x climb rate for MC. - * desiredClimbRate direction isn't required, set by target altitude direction instead - * NAV_IMPOSSIBLE_ALTITUDE_TARGET simply uses posControl.desiredState.pos.z to set a constant climb rate */ + /* ROC_TO_ALT_TARGET - constant climb rate until close to target altitude reducing to 0 when reached. + * Rate reduction starts at distance from target altitude of 5 x climb rate for Fixed wing. + * No climb rate required, set by target altitude direction instead. + * + * ROC_TO_ALT_RESET - similar to ROC_TO_ALT_TARGET except target altitude set to current altitude. + * No climb rate or altitude target required. + * + * ROC_TO_ALT_CONSTANT - constant climb rate. Climb rate and direction required. Target alt not required. */ // Terrain following uses different altitude measurement const float altitudeToUse = navGetCurrentActualPositionAndVelocity()->pos.z; @@ -3085,10 +3089,10 @@ void updateClimbRateToAltitudeController(float desiredClimbRate, float targetAlt posControl.desiredState.pos.z = altitudeToUse; } else if (mode == ROC_TO_ALT_TARGET) { posControl.desiredState.pos.z = targetAltitude; - } else { // ROC_TO_ALT_CONSTANT - posControl.desiredState.pos.z = NAV_IMPOSSIBLE_ALTITUDE_TARGET; } + posControl.flags.rocToAltMode = mode; + /* * If max altitude is set and altitude limit reached reset altitude target to max altitude unless desired climb rate is -ve */ @@ -3096,7 +3100,7 @@ void updateClimbRateToAltitudeController(float desiredClimbRate, float targetAlt posControl.desiredState.pos.z = MIN(posControl.desiredState.pos.z, navConfig()->general.max_altitude); } - posControl.desiredState.vel.z = desiredClimbRate; + posControl.desiredState.vel.z = desiredClimbRate; // only used for ROC_TO_ALT_CONSTANT } static void resetAltitudeController(bool useTerrainFollowing) diff --git a/src/main/navigation/navigation_fixedwing.c b/src/main/navigation/navigation_fixedwing.c index c5dde6dba48..0272df114c7 100755 --- a/src/main/navigation/navigation_fixedwing.c +++ b/src/main/navigation/navigation_fixedwing.c @@ -123,7 +123,7 @@ bool adjustFixedWingAltitudeFromRCInput(void) else { // Adjusting finished - reset desired position to stay exactly where pilot released the stick if (posControl.flags.isAdjustingAltitude) { - updateClimbRateToAltitudeController(navConfig()->general.max_auto_climb_rate, 0, ROC_TO_ALT_RESET); + updateClimbRateToAltitudeController(0, 0, ROC_TO_ALT_RESET); } return false; } @@ -136,7 +136,7 @@ static void updateAltitudeVelocityAndPitchController_FW(timeDelta_t deltaMicros) float desiredClimbRate = posControl.desiredState.vel.z; - if (posControl.desiredState.pos.z != NAV_IMPOSSIBLE_ALTITUDE_TARGET) { + if (posControl.flags.rocToAltMode != ROC_TO_ALT_CONSTANT) { desiredClimbRate = getDesiredClimbRate(posControl.desiredState.pos.z, deltaMicros); } @@ -757,7 +757,7 @@ void applyFixedWingEmergencyLandingController(timeUs_t currentTimeUs) if (posControl.flags.estAltStatus >= EST_USABLE) { // target min descent rate 10m above takeoff altitude - updateClimbRateToAltitudeController(-navConfig()->general.emerg_descent_rate, 1000.0f, ROC_TO_ALT_TARGET); + updateClimbRateToAltitudeController(0, 1000.0f, ROC_TO_ALT_TARGET); applyFixedWingAltitudeAndThrottleController(currentTimeUs); int16_t pitchCorrection = constrain(posControl.rcAdjustment[PITCH], -DEGREES_TO_DECIDEGREES(navConfig()->fw.max_dive_angle), DEGREES_TO_DECIDEGREES(navConfig()->fw.max_climb_angle)); diff --git a/src/main/navigation/navigation_multicopter.c b/src/main/navigation/navigation_multicopter.c index 935665ee60e..559898eadfd 100644 --- a/src/main/navigation/navigation_multicopter.c +++ b/src/main/navigation/navigation_multicopter.c @@ -78,7 +78,7 @@ static void updateAltitudeVelocityController_MC(timeDelta_t deltaMicros) { float targetVel = posControl.desiredState.vel.z; - if (posControl.desiredState.pos.z != NAV_IMPOSSIBLE_ALTITUDE_TARGET) { + if (posControl.flags.rocToAltMode != ROC_TO_ALT_CONSTANT) { targetVel = getDesiredClimbRate(posControl.desiredState.pos.z, deltaMicros); } @@ -130,7 +130,7 @@ bool adjustMulticopterAltitudeFromRCInput(void) // In terrain follow mode we apply different logic for terrain control if (posControl.flags.estAglStatus == EST_TRUSTED && altTarget > 10.0f) { // We have solid terrain sensor signal - directly map throttle to altitude - updateClimbRateToAltitudeController(navConfig()->general.max_manual_climb_rate, altTarget, ROC_TO_ALT_TARGET); + updateClimbRateToAltitudeController(0, altTarget, ROC_TO_ALT_TARGET); } else { updateClimbRateToAltitudeController(-50.0f, 0, ROC_TO_ALT_CONSTANT); @@ -162,7 +162,7 @@ bool adjustMulticopterAltitudeFromRCInput(void) else { // Adjusting finished - reset desired position to stay exactly where pilot released the stick if (posControl.flags.isAdjustingAltitude) { - updateClimbRateToAltitudeController(navConfig()->general.max_auto_climb_rate, 0, ROC_TO_ALT_RESET); + updateClimbRateToAltitudeController(0, 0, ROC_TO_ALT_RESET); } return false; @@ -249,7 +249,6 @@ static void applyMulticopterAltitudeController(timeUs_t currentTimeUs) if (prepareForTakeoffOnReset) { const navEstimatedPosVel_t *posToUse = navGetCurrentActualPositionAndVelocity(); - posControl.desiredState.vel.z = -navConfig()->general.max_manual_climb_rate; posControl.desiredState.pos.z = posToUse->pos.z - (navConfig()->general.max_manual_climb_rate / posControl.pids.pos[Z].param.kP); posControl.pids.vel[Z].integrator = -500.0f; pt1FilterReset(&altholdThrottleFilterState, -500.0f); @@ -930,7 +929,7 @@ static void applyMulticopterEmergencyLandingController(timeUs_t currentTimeUs) // Check if last correction was not too long ago if (deltaMicrosPositionUpdate < MAX_POSITION_UPDATE_INTERVAL_US) { // target min descent rate 5m above takeoff altitude - updateClimbRateToAltitudeController(-navConfig()->general.emerg_descent_rate, 500.0f, ROC_TO_ALT_TARGET); + updateClimbRateToAltitudeController(0, 500.0f, ROC_TO_ALT_TARGET); updateAltitudeVelocityController_MC(deltaMicrosPositionUpdate); updateAltitudeThrottleController_MC(deltaMicrosPositionUpdate); } diff --git a/src/main/navigation/navigation_private.h b/src/main/navigation/navigation_private.h index 35e5492c6f1..8452650ffaa 100644 --- a/src/main/navigation/navigation_private.h +++ b/src/main/navigation/navigation_private.h @@ -47,8 +47,6 @@ #define NAV_RTH_TRACKBACK_POINTS 50 // max number RTH trackback points -#define NAV_IMPOSSIBLE_ALTITUDE_TARGET 10000000 // 100km in cm. Serves as a flag for vertical velocity control - #define MAX_POSITION_UPDATE_INTERVAL_US HZ2US(MIN_POSITION_UPDATE_RATE_HZ) // convenience macro _Static_assert(MAX_POSITION_UPDATE_INTERVAL_US <= TIMEDELTA_MAX, "deltaMicros can overflow!"); @@ -95,6 +93,8 @@ typedef struct navigationFlags_s { navigationEstimateStatus_e estHeadingStatus; // Indicate valid heading - wither mag or GPS at certain speed on airplane bool gpsCfEstimatedAltitudeMismatch; // Indicates a mismatch between GPS altitude and estimated altitude + climbRateToAltitudeControllerMode_e rocToAltMode; + bool isAdjustingPosition; bool isAdjustingAltitude; bool isAdjustingHeading; From a8079c28423d74ae592cbd9c51a3911ad7f0b0e7 Mon Sep 17 00:00:00 2001 From: breadoven <56191411+breadoven@users.noreply.github.com> Date: Thu, 9 Nov 2023 11:24:37 +0000 Subject: [PATCH 03/14] fixes --- src/main/navigation/navigation.c | 8 +++----- src/main/navigation/navigation_private.h | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/main/navigation/navigation.c b/src/main/navigation/navigation.c index f18c1cdc567..7505260c889 100644 --- a/src/main/navigation/navigation.c +++ b/src/main/navigation/navigation.c @@ -3040,7 +3040,7 @@ static bool isMaxAltitudeLimitExceeded(void) return navGetCurrentActualPositionAndVelocity()->pos.z >= navConfig()->general.max_altitude; } -int32_t getDesiredClimbRate(float targetAltitude, timeDelta_t deltaMicros) +float getDesiredClimbRate(float targetAltitude, timeDelta_t deltaMicros) { if (navConfig()->general.max_altitude && isMaxAltitudeLimitExceeded()) { targetAltitude = MIN(targetAltitude, navConfig()->general.max_altitude); @@ -3082,11 +3082,8 @@ void updateClimbRateToAltitudeController(float desiredClimbRate, float targetAlt * * ROC_TO_ALT_CONSTANT - constant climb rate. Climb rate and direction required. Target alt not required. */ - // Terrain following uses different altitude measurement - const float altitudeToUse = navGetCurrentActualPositionAndVelocity()->pos.z; - if (mode == ROC_TO_ALT_RESET) { - posControl.desiredState.pos.z = altitudeToUse; + posControl.desiredState.pos.z = navGetCurrentActualPositionAndVelocity()->pos.z; } else if (mode == ROC_TO_ALT_TARGET) { posControl.desiredState.pos.z = targetAltitude; } @@ -3098,6 +3095,7 @@ void updateClimbRateToAltitudeController(float desiredClimbRate, float targetAlt */ if (navConfig()->general.max_altitude && isMaxAltitudeLimitExceeded() && desiredClimbRate >= 0.0f) { posControl.desiredState.pos.z = MIN(posControl.desiredState.pos.z, navConfig()->general.max_altitude); + posControl.flags.rocToAltMode = ROC_TO_ALT_TARGET; } posControl.desiredState.vel.z = desiredClimbRate; // only used for ROC_TO_ALT_CONSTANT diff --git a/src/main/navigation/navigation_private.h b/src/main/navigation/navigation_private.h index 8452650ffaa..428b54cd4f4 100644 --- a/src/main/navigation/navigation_private.h +++ b/src/main/navigation/navigation_private.h @@ -483,7 +483,7 @@ bool isWaypointNavTrackingActive(void); void updateActualHeading(bool headingValid, int32_t newHeading, int32_t newGroundCourse); void updateActualHorizontalPositionAndVelocity(bool estPosValid, bool estVelValid, float newX, float newY, float newVelX, float newVelY); void updateActualAltitudeAndClimbRate(bool estimateValid, float newAltitude, float newVelocity, float surfaceDistance, float surfaceVelocity, navigationEstimateStatus_e surfaceStatus, float gpsCfEstimatedAltitudeError); -int32_t getDesiredClimbRate(float targetAltitude, timeDelta_t deltaMicros); +float getDesiredClimbRate(float targetAltitude, timeDelta_t deltaMicros); bool checkForPositionSensorTimeout(void); From 1fcac6134a0fa3ad7a27ad1cc16d5096e5082ffd Mon Sep 17 00:00:00 2001 From: breadoven <56191411+breadoven@users.noreply.github.com> Date: Fri, 10 Nov 2023 22:29:19 +0000 Subject: [PATCH 04/14] fix multirotor velocity z --- src/main/navigation/navigation.c | 4 ++-- src/main/navigation/navigation_fixedwing.c | 2 +- src/main/navigation/navigation_multicopter.c | 3 ++- src/main/navigation/navigation_private.h | 1 + 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/navigation/navigation.c b/src/main/navigation/navigation.c index 7505260c889..ded835919dd 100644 --- a/src/main/navigation/navigation.c +++ b/src/main/navigation/navigation.c @@ -3086,6 +3086,8 @@ void updateClimbRateToAltitudeController(float desiredClimbRate, float targetAlt posControl.desiredState.pos.z = navGetCurrentActualPositionAndVelocity()->pos.z; } else if (mode == ROC_TO_ALT_TARGET) { posControl.desiredState.pos.z = targetAltitude; + } else { // ROC_TO_ALT_CONSTANT + posControl.desiredState.climbRateDemand = desiredClimbRate; } posControl.flags.rocToAltMode = mode; @@ -3097,8 +3099,6 @@ void updateClimbRateToAltitudeController(float desiredClimbRate, float targetAlt posControl.desiredState.pos.z = MIN(posControl.desiredState.pos.z, navConfig()->general.max_altitude); posControl.flags.rocToAltMode = ROC_TO_ALT_TARGET; } - - posControl.desiredState.vel.z = desiredClimbRate; // only used for ROC_TO_ALT_CONSTANT } static void resetAltitudeController(bool useTerrainFollowing) diff --git a/src/main/navigation/navigation_fixedwing.c b/src/main/navigation/navigation_fixedwing.c index 0272df114c7..f5c3fb159ae 100755 --- a/src/main/navigation/navigation_fixedwing.c +++ b/src/main/navigation/navigation_fixedwing.c @@ -134,7 +134,7 @@ static void updateAltitudeVelocityAndPitchController_FW(timeDelta_t deltaMicros) { static pt1Filter_t velzFilterState; - float desiredClimbRate = posControl.desiredState.vel.z; + float desiredClimbRate = posControl.desiredState.climbRateDemand; if (posControl.flags.rocToAltMode != ROC_TO_ALT_CONSTANT) { desiredClimbRate = getDesiredClimbRate(posControl.desiredState.pos.z, deltaMicros); diff --git a/src/main/navigation/navigation_multicopter.c b/src/main/navigation/navigation_multicopter.c index 559898eadfd..b35d88c6093 100644 --- a/src/main/navigation/navigation_multicopter.c +++ b/src/main/navigation/navigation_multicopter.c @@ -76,7 +76,7 @@ float getSqrtControllerVelocity(float targetAltitude, timeDelta_t deltaMicros) // Position to velocity controller for Z axis static void updateAltitudeVelocityController_MC(timeDelta_t deltaMicros) { - float targetVel = posControl.desiredState.vel.z; + float targetVel = posControl.desiredState.climbRateDemand; if (posControl.flags.rocToAltMode != ROC_TO_ALT_CONSTANT) { targetVel = getDesiredClimbRate(posControl.desiredState.pos.z, deltaMicros); @@ -249,6 +249,7 @@ static void applyMulticopterAltitudeController(timeUs_t currentTimeUs) if (prepareForTakeoffOnReset) { const navEstimatedPosVel_t *posToUse = navGetCurrentActualPositionAndVelocity(); + posControl.desiredState.vel.z = -navConfig()->general.max_manual_climb_rate; posControl.desiredState.pos.z = posToUse->pos.z - (navConfig()->general.max_manual_climb_rate / posControl.pids.pos[Z].param.kP); posControl.pids.vel[Z].integrator = -500.0f; pt1FilterReset(&altholdThrottleFilterState, -500.0f); diff --git a/src/main/navigation/navigation_private.h b/src/main/navigation/navigation_private.h index 428b54cd4f4..cf4698a24c8 100644 --- a/src/main/navigation/navigation_private.h +++ b/src/main/navigation/navigation_private.h @@ -140,6 +140,7 @@ typedef struct { fpVector3_t pos; fpVector3_t vel; int32_t yaw; + int16_t climbRateDemand; } navigationDesiredState_t; typedef enum { From 87faeb11ee6c25f024cf38832ec22746b9f6ce74 Mon Sep 17 00:00:00 2001 From: breadoven <56191411+breadoven@users.noreply.github.com> Date: Thu, 16 Nov 2023 11:13:21 +0000 Subject: [PATCH 05/14] WP Linear climb + Update max alt limter --- src/main/navigation/navigation.c | 38 ++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/src/main/navigation/navigation.c b/src/main/navigation/navigation.c index ded835919dd..2fd1cfd3256 100644 --- a/src/main/navigation/navigation.c +++ b/src/main/navigation/navigation.c @@ -1691,10 +1691,20 @@ static navigationFSMEvent_t navOnEnteringState_NAV_STATE_WAYPOINT_IN_PROGRESS(na fpVector3_t tmpWaypoint; tmpWaypoint.x = posControl.activeWaypoint.pos.x; tmpWaypoint.y = posControl.activeWaypoint.pos.y; - tmpWaypoint.z = scaleRangef(constrainf(posControl.wpDistance, posControl.wpInitialDistance / 10.0f, posControl.wpInitialDistance), - posControl.wpInitialDistance, posControl.wpInitialDistance / 10.0f, - posControl.wpInitialAltitude, posControl.activeWaypoint.pos.z); - setDesiredPosition(&tmpWaypoint, 0, NAV_POS_UPDATE_XY | NAV_POS_UPDATE_Z | NAV_POS_UPDATE_BEARING); + setDesiredPosition(&tmpWaypoint, 0, NAV_POS_UPDATE_XY | NAV_POS_UPDATE_BEARING); + + // Use linear climb bewtween WPs until within 10% of total distance to current active WP + float linearClimbDistRemaining = posControl.wpDistance - 0.1f * posControl.wpInitialDistance; + if (linearClimbDistRemaining > 0) { + int16_t climbRate = constrainf(posControl.actualState.velXY * + (posControl.activeWaypoint.pos.z - posControl.actualState.abs.pos.z) / linearClimbDistRemaining, + -navConfig()->general.max_auto_climb_rate, + navConfig()->general.max_auto_climb_rate); + updateClimbRateToAltitudeController(climbRate, 0, ROC_TO_ALT_CONSTANT); + } else { + updateClimbRateToAltitudeController(0, posControl.activeWaypoint.pos.z, ROC_TO_ALT_TARGET); + } + if(STATE(MULTIROTOR)) { switch (wpHeadingControl.mode) { case NAV_WP_HEAD_MODE_NONE: @@ -3035,17 +3045,8 @@ bool isProbablyStillFlying(void) /*----------------------------------------------------------- * Z-position controller *-----------------------------------------------------------*/ -static bool isMaxAltitudeLimitExceeded(void) -{ - return navGetCurrentActualPositionAndVelocity()->pos.z >= navConfig()->general.max_altitude; -} - float getDesiredClimbRate(float targetAltitude, timeDelta_t deltaMicros) { - if (navConfig()->general.max_altitude && isMaxAltitudeLimitExceeded()) { - targetAltitude = MIN(targetAltitude, navConfig()->general.max_altitude); - } - const bool emergLandingIsActive = navigationIsExecutingAnEmergencyLanding(); float maxClimbRate = navConfig()->general.max_auto_climb_rate; @@ -3093,11 +3094,16 @@ void updateClimbRateToAltitudeController(float desiredClimbRate, float targetAlt posControl.flags.rocToAltMode = mode; /* - * If max altitude is set and altitude limit reached reset altitude target to max altitude unless desired climb rate is -ve + * If max altitude is set and altitude limit reached reset altitude target to max altitude unless desired climb rate is -ve. + * Inhibit during RTH mode and also WP mode with altitude enforce active to avoid climbs getting stuck at max alt limit. */ - if (navConfig()->general.max_altitude && isMaxAltitudeLimitExceeded() && desiredClimbRate >= 0.0f) { + if (navConfig()->general.max_altitude && !FLIGHT_MODE(NAV_RTH_MODE) && !(FLIGHT_MODE(NAV_WP_MODE) && navConfig()->general.waypoint_enforce_altitude)) { posControl.desiredState.pos.z = MIN(posControl.desiredState.pos.z, navConfig()->general.max_altitude); - posControl.flags.rocToAltMode = ROC_TO_ALT_TARGET; + + if (navGetCurrentActualPositionAndVelocity()->pos.z >= navConfig()->general.max_altitude && desiredClimbRate >= 0.0f) { + posControl.desiredState.pos.z = navConfig()->general.max_altitude; + posControl.flags.rocToAltMode = ROC_TO_ALT_TARGET; + } } } From f521f9895f7781724f37a17ef5a90464a18e5b45 Mon Sep 17 00:00:00 2001 From: breadoven <56191411+breadoven@users.noreply.github.com> Date: Sat, 18 Nov 2023 20:50:04 +0000 Subject: [PATCH 06/14] WP linear climb improvements --- src/main/navigation/navigation.c | 35 +++++++++++++++++--------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/src/main/navigation/navigation.c b/src/main/navigation/navigation.c index 2fd1cfd3256..eae0be28756 100644 --- a/src/main/navigation/navigation.c +++ b/src/main/navigation/navigation.c @@ -1694,16 +1694,13 @@ static navigationFSMEvent_t navOnEnteringState_NAV_STATE_WAYPOINT_IN_PROGRESS(na setDesiredPosition(&tmpWaypoint, 0, NAV_POS_UPDATE_XY | NAV_POS_UPDATE_BEARING); // Use linear climb bewtween WPs until within 10% of total distance to current active WP - float linearClimbDistRemaining = posControl.wpDistance - 0.1f * posControl.wpInitialDistance; - if (linearClimbDistRemaining > 0) { - int16_t climbRate = constrainf(posControl.actualState.velXY * - (posControl.activeWaypoint.pos.z - posControl.actualState.abs.pos.z) / linearClimbDistRemaining, - -navConfig()->general.max_auto_climb_rate, - navConfig()->general.max_auto_climb_rate); - updateClimbRateToAltitudeController(climbRate, 0, ROC_TO_ALT_CONSTANT); - } else { - updateClimbRateToAltitudeController(0, posControl.activeWaypoint.pos.z, ROC_TO_ALT_TARGET); + float climbRate = posControl.actualState.velXY * (posControl.activeWaypoint.pos.z - posControl.wpInitialAltitude) / + (0.9f * posControl.wpInitialDistance); + + if (fabsf(climbRate) >= navConfig()->general.max_auto_climb_rate) { + climbRate = 0; } + updateClimbRateToAltitudeController(climbRate, posControl.activeWaypoint.pos.z, ROC_TO_ALT_TARGET); if(STATE(MULTIROTOR)) { switch (wpHeadingControl.mode) { @@ -3050,11 +3047,14 @@ float getDesiredClimbRate(float targetAltitude, timeDelta_t deltaMicros) const bool emergLandingIsActive = navigationIsExecutingAnEmergencyLanding(); float maxClimbRate = navConfig()->general.max_auto_climb_rate; - if (emergLandingIsActive) { + if (posControl.desiredState.climbRateDemand) { + maxClimbRate = ABS(posControl.desiredState.climbRateDemand); + } else if (emergLandingIsActive) { maxClimbRate = navConfig()->general.emerg_descent_rate; } else if (posControl.flags.isAdjustingAltitude) { maxClimbRate = navConfig()->general.max_manual_climb_rate; } + const float targetAltitudeError = targetAltitude - navGetCurrentActualPositionAndVelocity()->pos.z; float targetVel = 0.0f; @@ -3076,7 +3076,7 @@ void updateClimbRateToAltitudeController(float desiredClimbRate, float targetAlt { /* ROC_TO_ALT_TARGET - constant climb rate until close to target altitude reducing to 0 when reached. * Rate reduction starts at distance from target altitude of 5 x climb rate for Fixed wing. - * No climb rate required, set by target altitude direction instead. + * Any non zero climb rate sets the max allowed climb rate. Default max climb rate limits are used when set to 0. * * ROC_TO_ALT_RESET - similar to ROC_TO_ALT_TARGET except target altitude set to current altitude. * No climb rate or altitude target required. @@ -3087,21 +3087,24 @@ void updateClimbRateToAltitudeController(float desiredClimbRate, float targetAlt posControl.desiredState.pos.z = navGetCurrentActualPositionAndVelocity()->pos.z; } else if (mode == ROC_TO_ALT_TARGET) { posControl.desiredState.pos.z = targetAltitude; - } else { // ROC_TO_ALT_CONSTANT - posControl.desiredState.climbRateDemand = desiredClimbRate; } + posControl.desiredState.climbRateDemand = desiredClimbRate; posControl.flags.rocToAltMode = mode; /* - * If max altitude is set and altitude limit reached reset altitude target to max altitude unless desired climb rate is -ve. + * If max altitude is set limit desired altitude and impose altitude limit for constant climbs unless climb rate is -ve. * Inhibit during RTH mode and also WP mode with altitude enforce active to avoid climbs getting stuck at max alt limit. */ if (navConfig()->general.max_altitude && !FLIGHT_MODE(NAV_RTH_MODE) && !(FLIGHT_MODE(NAV_WP_MODE) && navConfig()->general.waypoint_enforce_altitude)) { posControl.desiredState.pos.z = MIN(posControl.desiredState.pos.z, navConfig()->general.max_altitude); - if (navGetCurrentActualPositionAndVelocity()->pos.z >= navConfig()->general.max_altitude && desiredClimbRate >= 0.0f) { - posControl.desiredState.pos.z = navConfig()->general.max_altitude; + if (mode == ROC_TO_ALT_TARGET || (mode == ROC_TO_ALT_CONSTANT && desiredClimbRate < 0.0f)) { + return; + } + + if (navGetCurrentActualPositionAndVelocity()->pos.z > navConfig()->general.max_altitude) { + posControl.desiredState.climbRateDemand = 0; posControl.flags.rocToAltMode = ROC_TO_ALT_TARGET; } } From 49715f8c22ac154d7cfc0486fcf540cfbb3c8be8 Mon Sep 17 00:00:00 2001 From: breadoven <56191411+breadoven@users.noreply.github.com> Date: Sun, 19 Nov 2023 21:52:58 +0000 Subject: [PATCH 07/14] Improvements --- src/main/navigation/navigation.c | 17 ++++++++++------- src/main/navigation/navigation_private.h | 1 - 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/main/navigation/navigation.c b/src/main/navigation/navigation.c index eae0be28756..b10a7dc6fe4 100644 --- a/src/main/navigation/navigation.c +++ b/src/main/navigation/navigation.c @@ -1627,7 +1627,6 @@ static navigationFSMEvent_t navOnEnteringState_NAV_STATE_WAYPOINT_PRE_ACTION(nav case NAV_WP_ACTION_LAND: calculateAndSetActiveWaypoint(&posControl.waypointList[posControl.activeWaypointIndex]); posControl.wpInitialDistance = calculateDistanceToDestination(&posControl.activeWaypoint.pos); - posControl.wpInitialAltitude = posControl.actualState.abs.pos.z; posControl.wpAltitudeReached = false; return NAV_FSM_EVENT_SUCCESS; // will switch to NAV_STATE_WAYPOINT_IN_PROGRESS @@ -1693,9 +1692,13 @@ static navigationFSMEvent_t navOnEnteringState_NAV_STATE_WAYPOINT_IN_PROGRESS(na tmpWaypoint.y = posControl.activeWaypoint.pos.y; setDesiredPosition(&tmpWaypoint, 0, NAV_POS_UPDATE_XY | NAV_POS_UPDATE_BEARING); - // Use linear climb bewtween WPs until within 10% of total distance to current active WP - float climbRate = posControl.actualState.velXY * (posControl.activeWaypoint.pos.z - posControl.wpInitialAltitude) / - (0.9f * posControl.wpInitialDistance); + // Use linear climb between WPs arriving at WP altitude when within 10% of total distance to WP + // Update climbrate until within 25% of total distance to WP, then hold constant + static float climbRate = 0; + if (posControl.wpDistance > 0.25f * posControl.wpInitialDistance) { + climbRate = posControl.actualState.velXY * (posControl.activeWaypoint.pos.z - posControl.actualState.abs.pos.z) / + (posControl.wpDistance - 0.1f * posControl.wpInitialDistance); + } if (fabsf(climbRate) >= navConfig()->general.max_auto_climb_rate) { climbRate = 0; @@ -3099,12 +3102,12 @@ void updateClimbRateToAltitudeController(float desiredClimbRate, float targetAlt if (navConfig()->general.max_altitude && !FLIGHT_MODE(NAV_RTH_MODE) && !(FLIGHT_MODE(NAV_WP_MODE) && navConfig()->general.waypoint_enforce_altitude)) { posControl.desiredState.pos.z = MIN(posControl.desiredState.pos.z, navConfig()->general.max_altitude); - if (mode == ROC_TO_ALT_TARGET || (mode == ROC_TO_ALT_CONSTANT && desiredClimbRate < 0.0f)) { + if (mode != ROC_TO_ALT_CONSTANT || (mode == ROC_TO_ALT_CONSTANT && desiredClimbRate < 0.0f)) { return; } - if (navGetCurrentActualPositionAndVelocity()->pos.z > navConfig()->general.max_altitude) { - posControl.desiredState.climbRateDemand = 0; + if (posControl.flags.isAdjustingAltitude) { + posControl.desiredState.pos.z = navConfig()->general.max_altitude; posControl.flags.rocToAltMode = ROC_TO_ALT_TARGET; } } diff --git a/src/main/navigation/navigation_private.h b/src/main/navigation/navigation_private.h index cf4698a24c8..3a669443835 100644 --- a/src/main/navigation/navigation_private.h +++ b/src/main/navigation/navigation_private.h @@ -423,7 +423,6 @@ typedef struct { #endif navWaypointPosition_t activeWaypoint; // Local position, current bearing and turn angle to next WP, filled on waypoint activation int8_t activeWaypointIndex; - float wpInitialAltitude; // Altitude at start of WP float wpInitialDistance; // Distance when starting flight to WP float wpDistance; // Distance to active WP timeMs_t wpReachedTime; // Time the waypoint was reached From d6de35bf8b334032c9eb44264ed6baa8e98967ae Mon Sep 17 00:00:00 2001 From: breadoven <56191411+breadoven@users.noreply.github.com> Date: Wed, 6 Dec 2023 22:46:06 +0000 Subject: [PATCH 08/14] add control response setting --- docs/Settings.md | 10 ++++++++++ src/main/fc/settings.yaml | 6 ++++++ src/main/flight/pid.c | 9 +++++---- src/main/flight/pid.h | 2 ++ src/main/navigation/navigation.c | 6 ++---- 5 files changed, 25 insertions(+), 8 deletions(-) diff --git a/docs/Settings.md b/docs/Settings.md index 17384f92732..7b58d96cdbe 100644 --- a/docs/Settings.md +++ b/docs/Settings.md @@ -2842,6 +2842,16 @@ Enable the possibility to manually increase the throttle in auto throttle contro --- +### nav_fw_alt_control_response + +Adjusts the deceleration response of fixed wing altitude control as the target altitude is approached. Decrease value to help avoid overshooting the target altitude. + +| Default | Min | Max | +| --- | --- | --- | +| 20 | 5 | 100 | + +--- + ### nav_fw_bank_angle Max roll angle when rolling / turning in GPS assisted modes, is also restrained by global max_angle_inclination_rll diff --git a/src/main/fc/settings.yaml b/src/main/fc/settings.yaml index 4f870fa8f7a..8ce69c23123 100644 --- a/src/main/fc/settings.yaml +++ b/src/main/fc/settings.yaml @@ -2087,6 +2087,12 @@ groups: field: bank_fw.pid[PID_POS_Z].D min: 0 max: 255 + - name: nav_fw_alt_control_response + description: "Adjusts the deceleration response of fixed wing altitude control as the target altitude is approached. Decrease value to help avoid overshooting the target altitude." + default_value: 20 + field: fwAltControlResponseFactor + min: 5 + max: 100 - name: nav_fw_pos_xy_p description: "P gain of 2D trajectory PID controller. Play with this to get a straight line between waypoints or a straight RTH" default_value: 75 diff --git a/src/main/flight/pid.c b/src/main/flight/pid.c index bc794735eb2..9bae1799e45 100644 --- a/src/main/flight/pid.c +++ b/src/main/flight/pid.c @@ -170,7 +170,7 @@ static EXTENDED_FASTRAM bool angleHoldIsLevel = false; static EXTENDED_FASTRAM float fixedWingLevelTrim; static EXTENDED_FASTRAM pidController_t fixedWingLevelTrimController; -PG_REGISTER_PROFILE_WITH_RESET_TEMPLATE(pidProfile_t, pidProfile, PG_PID_PROFILE, 6); +PG_REGISTER_PROFILE_WITH_RESET_TEMPLATE(pidProfile_t, pidProfile, PG_PID_PROFILE, 7); PG_RESET_TEMPLATE(pidProfile_t, pidProfile, .bank_mc = { @@ -231,9 +231,9 @@ PG_RESET_TEMPLATE(pidProfile_t, pidProfile, }, [PID_HEADING] = { SETTING_NAV_FW_HEADING_P_DEFAULT, 0, 0, 0 }, [PID_POS_Z] = { - .P = SETTING_NAV_FW_POS_Z_P_DEFAULT, // FW_POS_Z_P * 10 - .I = SETTING_NAV_FW_POS_Z_I_DEFAULT, // FW_POS_Z_I * 10 - .D = SETTING_NAV_FW_POS_Z_D_DEFAULT, // FW_POS_Z_D * 10 + .P = SETTING_NAV_FW_POS_Z_P_DEFAULT, // FW_POS_Z_P * 100 + .I = SETTING_NAV_FW_POS_Z_I_DEFAULT, // FW_POS_Z_I * 100 + .D = SETTING_NAV_FW_POS_Z_D_DEFAULT, // FW_POS_Z_D * 100 .FF = 0, }, [PID_POS_XY] = { @@ -301,6 +301,7 @@ PG_RESET_TEMPLATE(pidProfile_t, pidProfile, .fixedWingLevelTrim = SETTING_FW_LEVEL_PITCH_TRIM_DEFAULT, .fixedWingLevelTrimGain = SETTING_FW_LEVEL_PITCH_GAIN_DEFAULT, + .fwAltControlResponseFactor = SETTING_NAV_FW_ALT_CONTROL_RESPONSE_DEFAULT, #ifdef USE_SMITH_PREDICTOR .smithPredictorStrength = SETTING_SMITH_PREDICTOR_STRENGTH_DEFAULT, .smithPredictorDelay = SETTING_SMITH_PREDICTOR_DELAY_DEFAULT, diff --git a/src/main/flight/pid.h b/src/main/flight/pid.h index e0a8b9d310b..3f3658ae162 100644 --- a/src/main/flight/pid.h +++ b/src/main/flight/pid.h @@ -151,6 +151,8 @@ typedef struct pidProfile_s { float fixedWingLevelTrim; float fixedWingLevelTrimGain; + + uint8_t fwAltControlResponseFactor; #ifdef USE_SMITH_PREDICTOR float smithPredictorStrength; float smithPredictorDelay; diff --git a/src/main/navigation/navigation.c b/src/main/navigation/navigation.c index b10a7dc6fe4..8fbe4c07854 100644 --- a/src/main/navigation/navigation.c +++ b/src/main/navigation/navigation.c @@ -3064,8 +3064,7 @@ float getDesiredClimbRate(float targetAltitude, timeDelta_t deltaMicros) if (STATE(MULTIROTOR)) { targetVel = getSqrtControllerVelocity(targetAltitude, deltaMicros); } else { - // 0.2f relates to climb rate starting to reduce from maxClimbRate at a distance of 5 x maxClimbRate from targetAltitude - targetVel = 0.2f * targetAltitudeError; + targetVel = pidProfile()->fwAltControlResponseFactor * targetAltitudeError / 100.0f; } if (emergLandingIsActive && targetAltitudeError > -50) { @@ -3077,8 +3076,7 @@ float getDesiredClimbRate(float targetAltitude, timeDelta_t deltaMicros) void updateClimbRateToAltitudeController(float desiredClimbRate, float targetAltitude, climbRateToAltitudeControllerMode_e mode) { - /* ROC_TO_ALT_TARGET - constant climb rate until close to target altitude reducing to 0 when reached. - * Rate reduction starts at distance from target altitude of 5 x climb rate for Fixed wing. + /* ROC_TO_ALT_TARGET - constant climb rate until close to target altitude then reducing down as altitude is reached. * Any non zero climb rate sets the max allowed climb rate. Default max climb rate limits are used when set to 0. * * ROC_TO_ALT_RESET - similar to ROC_TO_ALT_TARGET except target altitude set to current altitude. From 3378bcd8179296790969cf35ba0e6083280270f4 Mon Sep 17 00:00:00 2001 From: breadoven <56191411+breadoven@users.noreply.github.com> Date: Mon, 11 Dec 2023 10:48:52 +0000 Subject: [PATCH 09/14] change alt reset to alt current --- src/main/navigation/navigation.c | 6 +++--- src/main/navigation/navigation_fixedwing.c | 2 +- src/main/navigation/navigation_multicopter.c | 2 +- src/main/navigation/navigation_private.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/navigation/navigation.c b/src/main/navigation/navigation.c index 8fbe4c07854..3ca2d126e99 100644 --- a/src/main/navigation/navigation.c +++ b/src/main/navigation/navigation.c @@ -1474,7 +1474,7 @@ static navigationFSMEvent_t navOnEnteringState_NAV_STATE_RTH_HOVER_PRIOR_TO_LAND // Wait until target heading is reached for MR (with 15 deg margin for error), or continue for Fixed Wing if ((ABS(wrap_18000(posControl.rthState.homePosition.heading - posControl.actualState.yaw)) < DEGREES_TO_CENTIDEGREES(15)) || STATE(FIXED_WING_LEGACY)) { resetLandingDetector(); // force reset landing detector just in case - updateClimbRateToAltitudeController(0, 0, ROC_TO_ALT_RESET); + updateClimbRateToAltitudeController(0, 0, ROC_TO_ALT_CURRENT); return navigationRTHAllowsLanding() ? NAV_FSM_EVENT_SUCCESS : NAV_FSM_EVENT_SWITCH_TO_RTH_HOVER_ABOVE_HOME; // success = land } else { fpVector3_t * tmpHomePos = rthGetHomeTargetPosition(RTH_HOME_ENROUTE_FINAL); @@ -3079,12 +3079,12 @@ void updateClimbRateToAltitudeController(float desiredClimbRate, float targetAlt /* ROC_TO_ALT_TARGET - constant climb rate until close to target altitude then reducing down as altitude is reached. * Any non zero climb rate sets the max allowed climb rate. Default max climb rate limits are used when set to 0. * - * ROC_TO_ALT_RESET - similar to ROC_TO_ALT_TARGET except target altitude set to current altitude. + * ROC_TO_ALT_CURRENT - similar to ROC_TO_ALT_TARGET except target altitude set to current altitude. * No climb rate or altitude target required. * * ROC_TO_ALT_CONSTANT - constant climb rate. Climb rate and direction required. Target alt not required. */ - if (mode == ROC_TO_ALT_RESET) { + if (mode == ROC_TO_ALT_CURRENT) { posControl.desiredState.pos.z = navGetCurrentActualPositionAndVelocity()->pos.z; } else if (mode == ROC_TO_ALT_TARGET) { posControl.desiredState.pos.z = targetAltitude; diff --git a/src/main/navigation/navigation_fixedwing.c b/src/main/navigation/navigation_fixedwing.c index f5c3fb159ae..3d66f7d7d32 100755 --- a/src/main/navigation/navigation_fixedwing.c +++ b/src/main/navigation/navigation_fixedwing.c @@ -123,7 +123,7 @@ bool adjustFixedWingAltitudeFromRCInput(void) else { // Adjusting finished - reset desired position to stay exactly where pilot released the stick if (posControl.flags.isAdjustingAltitude) { - updateClimbRateToAltitudeController(0, 0, ROC_TO_ALT_RESET); + updateClimbRateToAltitudeController(0, 0, ROC_TO_ALT_CURRENT); } return false; } diff --git a/src/main/navigation/navigation_multicopter.c b/src/main/navigation/navigation_multicopter.c index b35d88c6093..d2bc457f340 100644 --- a/src/main/navigation/navigation_multicopter.c +++ b/src/main/navigation/navigation_multicopter.c @@ -162,7 +162,7 @@ bool adjustMulticopterAltitudeFromRCInput(void) else { // Adjusting finished - reset desired position to stay exactly where pilot released the stick if (posControl.flags.isAdjustingAltitude) { - updateClimbRateToAltitudeController(0, 0, ROC_TO_ALT_RESET); + updateClimbRateToAltitudeController(0, 0, ROC_TO_ALT_CURRENT); } return false; diff --git a/src/main/navigation/navigation_private.h b/src/main/navigation/navigation_private.h index 3a669443835..664787decff 100644 --- a/src/main/navigation/navigation_private.h +++ b/src/main/navigation/navigation_private.h @@ -60,7 +60,7 @@ typedef enum { } navSetWaypointFlags_t; typedef enum { - ROC_TO_ALT_RESET, + ROC_TO_ALT_CURRENT, ROC_TO_ALT_CONSTANT, ROC_TO_ALT_TARGET } climbRateToAltitudeControllerMode_e; From 93f98a089f3855752a287f40b5acc7f27e7289dc Mon Sep 17 00:00:00 2001 From: breadoven <56191411+breadoven@users.noreply.github.com> Date: Sun, 10 Mar 2024 23:55:10 +0000 Subject: [PATCH 10/14] update --- docs/Settings.md | 10 ++++++ src/main/cms/cms_menu_imu.c | 2 ++ src/main/fc/fc_msp.c | 44 +++++++++++++----------- src/main/fc/settings.yaml | 10 ++++-- src/main/navigation/navigation.c | 9 ++--- src/main/navigation/navigation.h | 5 +-- src/main/navigation/navigation_private.h | 3 +- 7 files changed, 54 insertions(+), 29 deletions(-) diff --git a/docs/Settings.md b/docs/Settings.md index 740a7d0914f..0efeaf8de15 100644 --- a/docs/Settings.md +++ b/docs/Settings.md @@ -2862,6 +2862,16 @@ Adjusts the deceleration response of fixed wing altitude control as the target a --- +### nav_fw_auto_climb_rate + +Maximum climb/descent rate that UAV is allowed to reach during navigation modes. [cm/s] + +| Default | Min | Max | +| --- | --- | --- | +| 500 | 10 | 2000 | + +--- + ### nav_fw_bank_angle Max roll angle when rolling / turning in GPS assisted modes, is also restrained by global max_angle_inclination_rll diff --git a/src/main/cms/cms_menu_imu.c b/src/main/cms/cms_menu_imu.c index 7612ec44181..45e9b34b94b 100644 --- a/src/main/cms/cms_menu_imu.c +++ b/src/main/cms/cms_menu_imu.c @@ -198,6 +198,8 @@ static const OSD_Entry cmsx_menuPidAltMagEntries[] = { OSD_LABEL_DATA_ENTRY("-- ALT&MAG --", profileIndexString), + OSD_SETTING_ENTRY("FW ALT RESPONSE", SETTING_NAV_FW_ALT_CONTROL_RESPONSE), + OTHER_PIDFF_ENTRY("ALT P", &cmsx_pidPosZ.P), OTHER_PIDFF_ENTRY("ALT I", &cmsx_pidPosZ.I), OTHER_PIDFF_ENTRY("ALT D", &cmsx_pidPosZ.D), diff --git a/src/main/fc/fc_msp.c b/src/main/fc/fc_msp.c index 2c3f40dfe45..5e9b498874c 100644 --- a/src/main/fc/fc_msp.c +++ b/src/main/fc/fc_msp.c @@ -1113,7 +1113,7 @@ static bool mspFcProcessOutCommand(uint16_t cmdMSP, sbuf_t *dst, mspPostProcessF legacyLedConfig |= ledConfig->led_function << shiftCount; shiftCount += 4; legacyLedConfig |= (ledConfig->led_overlay & 0x3F) << (shiftCount); - shiftCount += 6; + shiftCount += 6; legacyLedConfig |= (ledConfig->led_color) << (shiftCount); shiftCount += 4; legacyLedConfig |= (ledConfig->led_direction) << (shiftCount); @@ -1340,9 +1340,9 @@ static bool mspFcProcessOutCommand(uint16_t cmdMSP, sbuf_t *dst, mspPostProcessF case MSP_NAV_POSHOLD: sbufWriteU8(dst, navConfig()->general.flags.user_control_mode); sbufWriteU16(dst, navConfig()->general.max_auto_speed); - sbufWriteU16(dst, navConfig()->mc.max_auto_climb_rate); + sbufWriteU16(dst, mixerConfig()->platformType == PLATFORM_AIRPLANE ? navConfig()->fw.max_auto_climb_rate : navConfig()->mc.max_auto_climb_rate); sbufWriteU16(dst, navConfig()->general.max_manual_speed); - sbufWriteU16(dst, mixerConfig()->platformType != PLATFORM_AIRPLANE ? navConfig()->mc.max_manual_climb_rate:navConfig()->fw.max_manual_climb_rate); + sbufWriteU16(dst, mixerConfig()->platformType == PLATFORM_AIRPLANE ? navConfig()->fw.max_manual_climb_rate : navConfig()->mc.max_manual_climb_rate); sbufWriteU8(dst, navConfig()->mc.max_bank_angle); sbufWriteU8(dst, navConfig()->mc.althold_throttle_type); sbufWriteU16(dst, currentBatteryProfile->nav.mc.hover_throttle); @@ -1590,7 +1590,7 @@ static bool mspFcProcessOutCommand(uint16_t cmdMSP, sbuf_t *dst, mspPostProcessF sbufWriteU8(dst, timerHardware[i].usageFlags); } break; - + case MSP2_INAV_MC_BRAKING: #ifdef USE_MR_BRAKING_MODE sbufWriteU16(dst, navConfig()->mc.braking_speed_threshold); @@ -2394,12 +2394,16 @@ static mspResult_e mspFcProcessInCommand(uint16_t cmdMSP, sbuf_t *src) if (dataSize == 13) { navConfigMutable()->general.flags.user_control_mode = sbufReadU8(src); navConfigMutable()->general.max_auto_speed = sbufReadU16(src); - navConfigMutable()->mc.max_auto_climb_rate = sbufReadU16(src); + if (mixerConfig()->platformType == PLATFORM_AIRPLANE) { + navConfigMutable()->fw.max_auto_climb_rate = sbufReadU16(src); + } else { + navConfigMutable()->mc.max_auto_climb_rate = sbufReadU16(src); + } navConfigMutable()->general.max_manual_speed = sbufReadU16(src); - if (mixerConfig()->platformType != PLATFORM_AIRPLANE) { - navConfigMutable()->mc.max_manual_climb_rate = sbufReadU16(src); - }else{ + if (mixerConfig()->platformType == PLATFORM_AIRPLANE) { navConfigMutable()->fw.max_manual_climb_rate = sbufReadU16(src); + } else { + navConfigMutable()->mc.max_manual_climb_rate = sbufReadU16(src); } navConfigMutable()->mc.max_bank_angle = sbufReadU8(src); navConfigMutable()->mc.althold_throttle_type = sbufReadU8(src); @@ -2729,7 +2733,7 @@ static mspResult_e mspFcProcessInCommand(uint16_t cmdMSP, sbuf_t *src) case MSP_SET_WP: if (dataSize == 21) { - + const uint8_t msp_wp_no = sbufReadU8(src); // get the waypoint number navWaypoint_t msp_wp; msp_wp.action = sbufReadU8(src); // action @@ -2943,7 +2947,7 @@ static mspResult_e mspFcProcessInCommand(uint16_t cmdMSP, sbuf_t *src) ledConfig->led_position = legacyConfig & 0xFF; ledConfig->led_function = (legacyConfig >> 8) & 0xF; ledConfig->led_overlay = (legacyConfig >> 12) & 0x3F; - ledConfig->led_color = (legacyConfig >> 18) & 0xF; + ledConfig->led_color = (legacyConfig >> 18) & 0xF; ledConfig->led_direction = (legacyConfig >> 22) & 0x3F; ledConfig->led_params = (legacyConfig >> 28) & 0xF; @@ -3233,7 +3237,7 @@ static mspResult_e mspFcProcessInCommand(uint16_t cmdMSP, sbuf_t *src) fwAutolandApproachConfigMutable(i)->approachAlt = sbufReadU32(src); fwAutolandApproachConfigMutable(i)->landAlt = sbufReadU32(src); fwAutolandApproachConfigMutable(i)->approachDirection = sbufReadU8(src); - + int16_t head1 = 0, head2 = 0; if (sbufReadI16Safe(&head1, src)) { fwAutolandApproachConfigMutable(i)->landApproachHeading1 = head1; @@ -3283,12 +3287,12 @@ static mspResult_e mspFcProcessInCommand(uint16_t cmdMSP, sbuf_t *src) ((controlRateConfig_t*)currentControlRateProfile)->rateDynamics.correctionEnd = sbufReadU8(src); ((controlRateConfig_t*)currentControlRateProfile)->rateDynamics.weightCenter = sbufReadU8(src); ((controlRateConfig_t*)currentControlRateProfile)->rateDynamics.weightEnd = sbufReadU8(src); - + } else { return MSP_RESULT_ERROR; } - break; + break; #endif #ifdef USE_PROGRAMMING_FRAMEWORK @@ -3582,7 +3586,7 @@ void mspWriteSimulatorOSD(sbuf_t *dst) static uint8_t osdPos_x = 0; //indicate new format hitl 1.4.0 - sbufWriteU8(dst, 255); + sbufWriteU8(dst, 255); if (isOSDTypeSupportedBySimulator()) { @@ -3788,7 +3792,7 @@ bool mspFCProcessInOutCommand(uint16_t cmdMSP, sbuf_t *dst, sbuf_t *src, mspResu #ifdef USE_SIMULATOR case MSP_SIMULATOR: tmp_u8 = sbufReadU8(src); // Get the Simulator MSP version - + // Check the MSP version of simulator if (tmp_u8 != SIMULATOR_MSP_VERSION) { break; @@ -3883,7 +3887,7 @@ bool mspFCProcessInOutCommand(uint16_t cmdMSP, sbuf_t *dst, sbuf_t *src, mspResu } else { sbufAdvance(src, sizeof(uint16_t) * XYZ_AXIS_COUNT); } - + // Get the acceleration in 1G units acc.accADCf[X] = ((int16_t)sbufReadU16(src)) / 1000.0f; acc.accADCf[Y] = ((int16_t)sbufReadU16(src)) / 1000.0f; @@ -3891,7 +3895,7 @@ bool mspFCProcessInOutCommand(uint16_t cmdMSP, sbuf_t *dst, sbuf_t *src, mspResu acc.accVibeSq[X] = 0.0f; acc.accVibeSq[Y] = 0.0f; acc.accVibeSq[Z] = 0.0f; - + // Get the angular velocity in DPS gyro.gyroADCf[X] = ((int16_t)sbufReadU16(src)) / 16.0f; gyro.gyroADCf[Y] = ((int16_t)sbufReadU16(src)) / 16.0f; @@ -3922,7 +3926,7 @@ bool mspFCProcessInOutCommand(uint16_t cmdMSP, sbuf_t *dst, sbuf_t *src, mspResu simulatorData.airSpeed = sbufReadU16(src); } else { if (SIMULATOR_HAS_OPTION(HITL_EXTENDED_FLAGS)) { - sbufReadU16(src); + sbufReadU16(src); } } @@ -3997,8 +4001,8 @@ bool mspFCProcessInOutCommand(uint16_t cmdMSP, sbuf_t *dst, sbuf_t *src, mspResu *ret = MSP_RESULT_ERROR; } break; -#endif - +#endif + default: // Not handled return false; diff --git a/src/main/fc/settings.yaml b/src/main/fc/settings.yaml index 61b0c23bbe4..c215f402a7d 100644 --- a/src/main/fc/settings.yaml +++ b/src/main/fc/settings.yaml @@ -2334,7 +2334,7 @@ groups: field: w_z_surface_p min: 0 max: 100 - default_value: 3.5 + default_value: 3.5 - name: inav_w_z_surface_v field: w_z_surface_v min: 0 @@ -2801,6 +2801,12 @@ groups: field: fw.max_bank_angle min: 5 max: 80 + - name: nav_fw_auto_climb_rate + description: "Maximum climb/descent rate that UAV is allowed to reach during navigation modes. [cm/s]" + default_value: 500 + field: fw.max_auto_climb_rate + min: 10 + max: 2000 - name: nav_fw_manual_climb_rate description: "Maximum climb/descent rate firmware is allowed when processing pilot input for ALTHOLD control mode [cm/s]" default_value: 300 @@ -4143,7 +4149,7 @@ groups: type: navFwAutolandConfig_t headers: ["navigation/navigation.h"] condition: USE_FW_AUTOLAND - members: + members: - name: nav_fw_land_approach_length description: "Length of the final approach" default_value: 35000 diff --git a/src/main/navigation/navigation.c b/src/main/navigation/navigation.c index b721ee4817d..51047974ca8 100644 --- a/src/main/navigation/navigation.c +++ b/src/main/navigation/navigation.c @@ -204,6 +204,7 @@ PG_RESET_TEMPLATE(navConfig_t, navConfig, // Fixed wing .fw = { .max_bank_angle = SETTING_NAV_FW_BANK_ANGLE_DEFAULT, // degrees + .max_auto_climb_rate = SETTING_NAV_FW_AUTO_CLIMB_RATE_DEFAULT, // 5 m/s .max_manual_climb_rate = SETTING_NAV_FW_MANUAL_CLIMB_RATE_DEFAULT, // 3 m/s .max_climb_angle = SETTING_NAV_FW_CLIMB_ANGLE_DEFAULT, // degrees .max_dive_angle = SETTING_NAV_FW_DIVE_ANGLE_DEFAULT, // degrees @@ -1891,7 +1892,7 @@ static navigationFSMEvent_t navOnEnteringState_NAV_STATE_WAYPOINT_IN_PROGRESS(na (posControl.wpDistance - 0.1f * posControl.wpInitialDistance); } - if (fabsf(climbRate) >= navConfig()->general.max_auto_climb_rate) { + if (fabsf(climbRate) >= (STATE(AIRPLANE) ? navConfig()->fw.max_auto_climb_rate : navConfig()->mc.max_auto_climb_rate)) { climbRate = 0; } updateClimbRateToAltitudeController(climbRate, posControl.activeWaypoint.pos.z, ROC_TO_ALT_TARGET); @@ -2212,7 +2213,7 @@ static navigationFSMEvent_t navOnEnteringState_NAV_STATE_FW_LANDING_CLIMB_TO_LOI } if (ABS(getEstimatedActualPosition(Z) - posControl.fwLandState.landAproachAltAgl) < (navConfig()->general.waypoint_enforce_altitude > 0 ? navConfig()->general.waypoint_enforce_altitude : FW_LAND_LOITER_ALT_TOLERANCE)) { - updateClimbRateToAltitudeController(0, 0, ROC_TO_ALT_RESET); + updateClimbRateToAltitudeController(0, 0, ROC_TO_ALT_CURRENT); posControl.fwLandState.landState = FW_AUTOLAND_STATE_LOITER; return NAV_FSM_EVENT_SUCCESS; } @@ -3379,13 +3380,13 @@ float getDesiredClimbRate(float targetAltitude, timeDelta_t deltaMicros) { const bool emergLandingIsActive = navigationIsExecutingAnEmergencyLanding(); - float maxClimbRate = navConfig()->general.max_auto_climb_rate; + float maxClimbRate = STATE(MULTIROTOR) ? navConfig()->mc.max_auto_climb_rate : navConfig()->fw.max_auto_climb_rate; if (posControl.desiredState.climbRateDemand) { maxClimbRate = ABS(posControl.desiredState.climbRateDemand); } else if (emergLandingIsActive) { maxClimbRate = navConfig()->general.emerg_descent_rate; } else if (posControl.flags.isAdjustingAltitude) { - maxClimbRate = navConfig()->general.max_manual_climb_rate; + maxClimbRate = STATE(MULTIROTOR) ? navConfig()->mc.max_manual_climb_rate : navConfig()->fw.max_manual_climb_rate; } const float targetAltitudeError = targetAltitude - navGetCurrentActualPositionAndVelocity()->pos.z; diff --git a/src/main/navigation/navigation.h b/src/main/navigation/navigation.h index 84e5390d43e..d02a69d060c 100644 --- a/src/main/navigation/navigation.h +++ b/src/main/navigation/navigation.h @@ -265,7 +265,7 @@ typedef struct positionEstimationConfig_s { #ifdef USE_GPS_FIX_ESTIMATION uint8_t allow_gps_fix_estimation; -#endif +#endif } positionEstimationConfig_t; PG_DECLARE(positionEstimationConfig_t, positionEstimationConfig); @@ -329,7 +329,7 @@ typedef struct navConfig_s { struct { uint8_t max_bank_angle; // multicopter max banking angle (deg) - uint16_t max_auto_climb_rate; // max vertical speed limitation cm/sec + uint16_t max_auto_climb_rate; // max vertical speed limitation nav modes cm/sec uint16_t max_manual_climb_rate; // manual velocity control max vertical speed #ifdef USE_MR_BRAKING_MODE @@ -351,6 +351,7 @@ typedef struct navConfig_s { struct { uint8_t max_bank_angle; // Fixed wing max banking angle (deg) + uint16_t max_auto_climb_rate; // max vertical speed limitation nav modes cm/sec uint16_t max_manual_climb_rate; // manual velocity control max vertical speed uint8_t max_climb_angle; // Fixed wing max banking angle (deg) uint8_t max_dive_angle; // Fixed wing max banking angle (deg) diff --git a/src/main/navigation/navigation_private.h b/src/main/navigation/navigation_private.h index f0d6a5c7068..95953c948cf 100644 --- a/src/main/navigation/navigation_private.h +++ b/src/main/navigation/navigation_private.h @@ -288,7 +288,7 @@ typedef enum { NAV_STATE_CRUISE_INITIALIZE, NAV_STATE_CRUISE_IN_PROGRESS, NAV_STATE_CRUISE_ADJUSTING, - + NAV_STATE_FW_LANDING_CLIMB_TO_LOITER, NAV_STATE_FW_LANDING_LOITER, NAV_STATE_FW_LANDING_APPROACH, @@ -462,6 +462,7 @@ typedef struct { #endif navWaypointPosition_t activeWaypoint; // Local position, current bearing and turn angle to next WP, filled on waypoint activation int8_t activeWaypointIndex; + float wpInitialAltitude; // Altitude at start of WP float wpInitialDistance; // Distance when starting flight to WP float wpDistance; // Distance to active WP timeMs_t wpReachedTime; // Time the waypoint was reached From a29d0a464b8d7ec571f0543701fd6eb8130cad13 Mon Sep 17 00:00:00 2001 From: breadoven <56191411+breadoven@users.noreply.github.com> Date: Mon, 11 Mar 2024 12:03:57 +0000 Subject: [PATCH 11/14] Update sitl.cmake --- cmake/sitl.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/sitl.cmake b/cmake/sitl.cmake index 78697f98a9d..ee43aa9a93a 100644 --- a/cmake/sitl.cmake +++ b/cmake/sitl.cmake @@ -34,7 +34,7 @@ set(SITL_LINK_OPTIONS -Wl,-L${STM32_LINKER_DIR} ) -if(${WIN32} OR ${CYGWIN}) +if(${CYGWIN}) set(SITL_LINK_OPTIONS ${SITL_LINK_OPTIONS} "-static-libgcc") endif() @@ -131,7 +131,7 @@ function (target_sitl name) target_link_options(${exe_target} PRIVATE -T${script_path}) endif() - if(${WIN32} OR ${CYGWIN}) + if(${CYGWIN}) set(exe_filename ${CMAKE_BINARY_DIR}/${binary_name}.exe) else() set(exe_filename ${CMAKE_BINARY_DIR}/${binary_name}) From d40bc0dc0cdfe055690f4fa53ef820046bae9715 Mon Sep 17 00:00:00 2001 From: breadoven <56191411+breadoven@users.noreply.github.com> Date: Fri, 3 May 2024 21:44:09 +0100 Subject: [PATCH 12/14] improvements --- src/main/navigation/navigation.c | 29 +++++++++++--------- src/main/navigation/navigation_fixedwing.c | 10 ++----- src/main/navigation/navigation_multicopter.c | 11 +++----- 3 files changed, 23 insertions(+), 27 deletions(-) diff --git a/src/main/navigation/navigation.c b/src/main/navigation/navigation.c index 09271e5f10f..bef708ecb1b 100644 --- a/src/main/navigation/navigation.c +++ b/src/main/navigation/navigation.c @@ -1898,16 +1898,12 @@ static navigationFSMEvent_t navOnEnteringState_NAV_STATE_WAYPOINT_IN_PROGRESS(na setDesiredPosition(&tmpWaypoint, 0, NAV_POS_UPDATE_XY | NAV_POS_UPDATE_BEARING); // Use linear climb between WPs arriving at WP altitude when within 10% of total distance to WP - // Update climbrate until within 25% of total distance to WP, then hold constant - static float climbRate = 0; - if (posControl.wpDistance > 0.25f * posControl.wpInitialDistance) { + // Update climb rate until within 100cm of total climb xy distance to WP, then hold constant + float climbRate = 0.0f; + if (posControl.wpDistance - 0.1f * posControl.wpInitialDistance > 100.0f) { climbRate = posControl.actualState.velXY * (posControl.activeWaypoint.pos.z - posControl.actualState.abs.pos.z) / (posControl.wpDistance - 0.1f * posControl.wpInitialDistance); } - - if (fabsf(climbRate) >= (STATE(AIRPLANE) ? navConfig()->fw.max_auto_climb_rate : navConfig()->mc.max_auto_climb_rate)) { - climbRate = 0; - } updateClimbRateToAltitudeController(climbRate, posControl.activeWaypoint.pos.z, ROC_TO_ALT_TARGET); if(STATE(MULTIROTOR)) { @@ -3401,14 +3397,20 @@ bool isProbablyStillFlying(void) float getDesiredClimbRate(float targetAltitude, timeDelta_t deltaMicros) { const bool emergLandingIsActive = navigationIsExecutingAnEmergencyLanding(); - float maxClimbRate = STATE(MULTIROTOR) ? navConfig()->mc.max_auto_climb_rate : navConfig()->fw.max_auto_climb_rate; + + if (posControl.flags.rocToAltMode == ROC_TO_ALT_CONSTANT) { + if (posControl.flags.isAdjustingAltitude) { + maxClimbRate = STATE(MULTIROTOR) ? navConfig()->mc.max_manual_climb_rate : navConfig()->fw.max_manual_climb_rate; + } + + return constrainf(posControl.desiredState.climbRateDemand, -maxClimbRate, maxClimbRate); + } + if (posControl.desiredState.climbRateDemand) { - maxClimbRate = ABS(posControl.desiredState.climbRateDemand); + maxClimbRate = constrainf(ABS(posControl.desiredState.climbRateDemand), 0.0f, maxClimbRate); } else if (emergLandingIsActive) { maxClimbRate = navConfig()->general.emerg_descent_rate; - } else if (posControl.flags.isAdjustingAltitude) { - maxClimbRate = STATE(MULTIROTOR) ? navConfig()->mc.max_manual_climb_rate : navConfig()->fw.max_manual_climb_rate; } const float targetAltitudeError = targetAltitude - navGetCurrentActualPositionAndVelocity()->pos.z; @@ -3420,8 +3422,8 @@ float getDesiredClimbRate(float targetAltitude, timeDelta_t deltaMicros) targetVel = pidProfile()->fwAltControlResponseFactor * targetAltitudeError / 100.0f; } - if (emergLandingIsActive && targetAltitudeError > -50) { - return -100; // maintain 1 m/s descent during emerg landing when approaching T/O altitude + if (emergLandingIsActive && targetAltitudeError > -50.0f) { + return -100.0f; // maintain 1 m/s descent during emerg landing when within 50cm of min speed landing altitude target } else { return constrainf(targetVel, -maxClimbRate, maxClimbRate); } @@ -3439,6 +3441,7 @@ void updateClimbRateToAltitudeController(float desiredClimbRate, float targetAlt if (mode == ROC_TO_ALT_CURRENT) { posControl.desiredState.pos.z = navGetCurrentActualPositionAndVelocity()->pos.z; + desiredClimbRate = 0.0f; } else if (mode == ROC_TO_ALT_TARGET) { posControl.desiredState.pos.z = targetAltitude; } diff --git a/src/main/navigation/navigation_fixedwing.c b/src/main/navigation/navigation_fixedwing.c index 0eaa41ef165..68714ca4803 100755 --- a/src/main/navigation/navigation_fixedwing.c +++ b/src/main/navigation/navigation_fixedwing.c @@ -133,11 +133,7 @@ static void updateAltitudeVelocityAndPitchController_FW(timeDelta_t deltaMicros) { static pt1Filter_t velzFilterState; - float desiredClimbRate = posControl.desiredState.climbRateDemand; - - if (posControl.flags.rocToAltMode != ROC_TO_ALT_CONSTANT) { - desiredClimbRate = getDesiredClimbRate(posControl.desiredState.pos.z, deltaMicros); - } + float desiredClimbRate = getDesiredClimbRate(posControl.desiredState.pos.z, deltaMicros); // Reduce max allowed climb pitch if performing loiter (stall prevention) if (needToCalculateCircularLoiter && desiredClimbRate > 0.0f) { @@ -770,8 +766,8 @@ void applyFixedWingEmergencyLandingController(timeUs_t currentTimeUs) rcCommand[THROTTLE] = setDesiredThrottle(currentBatteryProfile->failsafe_throttle, true); if (posControl.flags.estAltStatus >= EST_USABLE) { - // target min descent rate 10m above takeoff altitude - updateClimbRateToAltitudeController(0, 1000.0f, ROC_TO_ALT_TARGET); + // target min descent rate at distance 2 x emerg descent rate above takeoff altitude + updateClimbRateToAltitudeController(0, 2.0f * navConfig()->general.emerg_descent_rate, ROC_TO_ALT_TARGET); applyFixedWingAltitudeAndThrottleController(currentTimeUs); int16_t pitchCorrection = constrain(posControl.rcAdjustment[PITCH], -DEGREES_TO_DECIDEGREES(navConfig()->fw.max_dive_angle), DEGREES_TO_DECIDEGREES(navConfig()->fw.max_climb_angle)); diff --git a/src/main/navigation/navigation_multicopter.c b/src/main/navigation/navigation_multicopter.c index 41d1f7a5642..b108ef6aa31 100644 --- a/src/main/navigation/navigation_multicopter.c +++ b/src/main/navigation/navigation_multicopter.c @@ -76,11 +76,7 @@ float getSqrtControllerVelocity(float targetAltitude, timeDelta_t deltaMicros) // Position to velocity controller for Z axis static void updateAltitudeVelocityController_MC(timeDelta_t deltaMicros) { - float targetVel = posControl.desiredState.climbRateDemand; - - if (posControl.flags.rocToAltMode != ROC_TO_ALT_CONSTANT) { - targetVel = getDesiredClimbRate(posControl.desiredState.pos.z, deltaMicros); - } + float targetVel = getDesiredClimbRate(posControl.desiredState.pos.z, deltaMicros); posControl.pids.pos[Z].output_constrained = targetVel; // only used for Blackbox and OSD info @@ -141,6 +137,7 @@ bool adjustMulticopterAltitudeFromRCInput(void) } else { const int16_t rcThrottleAdjustment = applyDeadbandRescaled(rcCommand[THROTTLE] - altHoldThrottleRCZero, rcControlsConfig()->alt_hold_deadband, -500, 500); + if (rcThrottleAdjustment) { // set velocity proportional to stick movement float rcClimbRate; @@ -928,8 +925,8 @@ static void applyMulticopterEmergencyLandingController(timeUs_t currentTimeUs) // Check if last correction was not too long ago if (deltaMicrosPositionUpdate < MAX_POSITION_UPDATE_INTERVAL_US) { - // target min descent rate 5m above takeoff altitude - updateClimbRateToAltitudeController(0, 500.0f, ROC_TO_ALT_TARGET); + // target min descent rate at distance 2 x emerg descent rate above takeoff altitude + updateClimbRateToAltitudeController(0, 2.0f * navConfig()->general.emerg_descent_rate, ROC_TO_ALT_TARGET); updateAltitudeVelocityController_MC(deltaMicrosPositionUpdate); updateAltitudeThrottleController_MC(deltaMicrosPositionUpdate); } From 01303686fd19e8e51925e860ba8f146850ba2915 Mon Sep 17 00:00:00 2001 From: breadoven <56191411+breadoven@users.noreply.github.com> Date: Tue, 7 May 2024 22:47:44 +0100 Subject: [PATCH 13/14] fixes --- src/main/flight/pid.c | 2 +- src/main/navigation/navigation.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/flight/pid.c b/src/main/flight/pid.c index 944dcd7db41..e647fe475e3 100644 --- a/src/main/flight/pid.c +++ b/src/main/flight/pid.c @@ -169,7 +169,7 @@ static EXTENDED_FASTRAM bool angleHoldIsLevel = false; static EXTENDED_FASTRAM float fixedWingLevelTrim; static EXTENDED_FASTRAM pidController_t fixedWingLevelTrimController; -PG_REGISTER_PROFILE_WITH_RESET_TEMPLATE(pidProfile_t, pidProfile, PG_PID_PROFILE, 7); +PG_REGISTER_PROFILE_WITH_RESET_TEMPLATE(pidProfile_t, pidProfile, PG_PID_PROFILE, 8); PG_RESET_TEMPLATE(pidProfile_t, pidProfile, .bank_mc = { diff --git a/src/main/navigation/navigation.c b/src/main/navigation/navigation.c index 8ea4a9a3713..19178ddb1bd 100644 --- a/src/main/navigation/navigation.c +++ b/src/main/navigation/navigation.c @@ -1664,7 +1664,7 @@ static navigationFSMEvent_t navOnEnteringState_NAV_STATE_RTH_LOITER_PRIOR_TO_LAN if (!pauseLanding && ((ABS(wrap_18000(posControl.rthState.homePosition.heading - posControl.actualState.yaw)) < DEGREES_TO_CENTIDEGREES(15)) || STATE(FIXED_WING_LEGACY))) { resetLandingDetector(); // force reset landing detector just in case updateClimbRateToAltitudeController(0, 0, ROC_TO_ALT_CURRENT); - return navigationRTHAllowsLanding() ? NAV_FSM_EVENT_SUCCESS : NAV_FSM_EVENT_SWITCH_TO_RTH_HOVER_ABOVE_HOME; // success = land + return navigationRTHAllowsLanding() ? NAV_FSM_EVENT_SUCCESS : NAV_FSM_EVENT_SWITCH_TO_RTH_LOITER_ABOVE_HOME; // success = land } else { fpVector3_t * tmpHomePos = rthGetHomeTargetPosition(RTH_HOME_ENROUTE_FINAL); setDesiredPosition(tmpHomePos, posControl.rthState.homePosition.heading, NAV_POS_UPDATE_XY | NAV_POS_UPDATE_Z | NAV_POS_UPDATE_HEADING); @@ -1920,7 +1920,7 @@ static navigationFSMEvent_t navOnEnteringState_NAV_STATE_WAYPOINT_IN_PROGRESS(na setDesiredPosition(&tmpWaypoint, 0, NAV_POS_UPDATE_XY | NAV_POS_UPDATE_BEARING); // Use linear climb between WPs arriving at WP altitude when within 10% of total distance to WP - // Update climb rate until within 100cm of total climb xy distance to WP, then hold constant + // Update climb rate until within 100cm of total climb xy distance to WP float climbRate = 0.0f; if (posControl.wpDistance - 0.1f * posControl.wpInitialDistance > 100.0f) { climbRate = posControl.actualState.velXY * (posControl.activeWaypoint.pos.z - posControl.actualState.abs.pos.z) / From 35ce764405515216a6742cecdc36f81a755de0f6 Mon Sep 17 00:00:00 2001 From: breadoven <56191411+breadoven@users.noreply.github.com> Date: Sat, 11 May 2024 21:29:58 +0100 Subject: [PATCH 14/14] Fix max climb rate during loiter --- src/main/navigation/navigation_fixedwing.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/navigation/navigation_fixedwing.c b/src/main/navigation/navigation_fixedwing.c index db9f4d67283..71a7f99fc34 100755 --- a/src/main/navigation/navigation_fixedwing.c +++ b/src/main/navigation/navigation_fixedwing.c @@ -135,9 +135,9 @@ static void updateAltitudeVelocityAndPitchController_FW(timeDelta_t deltaMicros) float desiredClimbRate = getDesiredClimbRate(posControl.desiredState.pos.z, deltaMicros); - // Reduce max allowed climb pitch if performing loiter (stall prevention) - if (needToCalculateCircularLoiter && desiredClimbRate > 0.0f) { - desiredClimbRate *= 0.67f; + // Reduce max allowed climb rate by 2/3 if performing loiter (stall prevention) + if (needToCalculateCircularLoiter && desiredClimbRate > 0.67f * navConfig()->fw.max_auto_climb_rate) { + desiredClimbRate = 0.67f * navConfig()->fw.max_auto_climb_rate; } // Here we use negative values for dive for better clarity