-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Add airspeed TPA support (backport from #11042) via merge from master #11197
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Merge Maintenance 9.x to master
Add airspeed TPA support
|
You are nearing your monthly Qodo Merge usage quota. For more information, please visit here. PR Compliance Guide 🔍All compliance sections have been disabled in the configurations. |
| } else if (throttle < getMaxThrottle()) { | ||
| tpaFactor = (100 - (uint16_t)currentControlProfile->throttle.dynPID * (throttle - currentControlProfile->throttle.pa_breakpoint) / (float)(getMaxThrottle() - currentControlProfile->throttle.pa_breakpoint)) / 100.0f; | ||
| } else { | ||
| tpaFactor = (100 - currentControlProfile->throttle.dynPID) / 100.0f; | ||
| tpaFactor = (100 - constrain(currentControlProfile->throttle.dynPID, 0, 100)) / 100.0f; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: Clamp the multirotor tpaFactor to the range [0.0f, 1.0f] to prevent negative values when dynPID is greater than 100. [possible issue, importance: 8]
| } else if (throttle < getMaxThrottle()) { | |
| tpaFactor = (100 - (uint16_t)currentControlProfile->throttle.dynPID * (throttle - currentControlProfile->throttle.pa_breakpoint) / (float)(getMaxThrottle() - currentControlProfile->throttle.pa_breakpoint)) / 100.0f; | |
| } else { | |
| tpaFactor = (100 - currentControlProfile->throttle.dynPID) / 100.0f; | |
| tpaFactor = (100 - constrain(currentControlProfile->throttle.dynPID, 0, 100)) / 100.0f; | |
| } | |
| if (throttle < getMaxThrottle()) { | |
| tpaFactor = (100 - (uint16_t)currentControlProfile->throttle.dynPID | |
| * (throttle - currentControlProfile->throttle.pa_breakpoint) | |
| / (float)(getMaxThrottle() - currentControlProfile->throttle.pa_breakpoint)) | |
| / 100.0f; | |
| tpaFactor = constrainf(tpaFactor, 0.0f, 1.0f); | |
| } else { | |
| tpaFactor = (100 - constrain(currentControlProfile->throttle.dynPID, 0, 100)) / 100.0f; | |
| tpaFactor = constrainf(tpaFactor, 0.0f, 1.0f); | |
| } |
| static float calculateFixedWingAirspeedTPAFactor(void){ | ||
| const float airspeed = getAirspeedEstimate(); // in cm/s | ||
| const float referenceAirspeed = pidProfile()->fixedWingReferenceAirspeed; // in cm/s | ||
| float tpaFactor= powf(referenceAirspeed/(airspeed+0.01f), currentControlProfile->throttle.apa_pow/100.0f); | ||
| tpaFactor= constrainf(tpaFactor, 0.3f, 2.0f); | ||
| return tpaFactor; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: Validate airspeed and referenceAirspeed are positive (and apa_pow is in-range) and return a safe neutral factor (1.0) when invalid, instead of relying on an arbitrary epsilon that can still yield extreme results. [Learned best practice, importance: 6]
| static float calculateFixedWingAirspeedTPAFactor(void){ | |
| const float airspeed = getAirspeedEstimate(); // in cm/s | |
| const float referenceAirspeed = pidProfile()->fixedWingReferenceAirspeed; // in cm/s | |
| float tpaFactor= powf(referenceAirspeed/(airspeed+0.01f), currentControlProfile->throttle.apa_pow/100.0f); | |
| tpaFactor= constrainf(tpaFactor, 0.3f, 2.0f); | |
| return tpaFactor; | |
| } | |
| static float calculateFixedWingAirspeedTPAFactor(void) | |
| { | |
| const float airspeed = getAirspeedEstimate(); // cm/s | |
| const float referenceAirspeed = pidProfile()->fixedWingReferenceAirspeed; // cm/s | |
| if (airspeed <= 0.0f || referenceAirspeed <= 0.0f) { | |
| return 1.0f; | |
| } | |
| const float apaPow = constrainf(currentControlProfile->throttle.apa_pow / 100.0f, 0.0f, 2.0f); | |
| float tpaFactor = powf(referenceAirspeed / airspeed, apaPow); | |
| return constrainf(tpaFactor, 0.3f, 2.0f); | |
| } |
| float groundCos = vectorDotProduct(&vForward, &vDown); | ||
| int16_t throttleAdjustment = currentControlProfile->throttle.tpa_pitch_compensation * groundCos * 90.0f / 1.57079632679f; //when 1deg pitch up, increase throttle by pitch(deg)_to_throttle. cos(89 deg)*90/(pi/2)=0.99995,cos(80 deg)*90/(pi/2)=9.9493, | ||
| uint16_t throttleAdjusted = rcCommand[THROTTLE] + constrain(throttleAdjustment, -1000, 1000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: groundCos is a cosine, not an angle; compute a pitch/tilt angle in radians (e.g., via acosf with clamping), then convert to degrees once before applying tpa_pitch_compensation. [Learned best practice, importance: 5]
| float groundCos = vectorDotProduct(&vForward, &vDown); | |
| int16_t throttleAdjustment = currentControlProfile->throttle.tpa_pitch_compensation * groundCos * 90.0f / 1.57079632679f; //when 1deg pitch up, increase throttle by pitch(deg)_to_throttle. cos(89 deg)*90/(pi/2)=0.99995,cos(80 deg)*90/(pi/2)=9.9493, | |
| uint16_t throttleAdjusted = rcCommand[THROTTLE] + constrain(throttleAdjustment, -1000, 1000); | |
| float groundCos = vectorDotProduct(&vForward, &vDown); | |
| groundCos = constrainf(groundCos, -1.0f, 1.0f); | |
| const float tiltRad = acosf(groundCos); | |
| const float tiltDegFromLevel = (tiltRad - (float)M_PI_2) * (180.0f / (float)M_PI); | |
| const int16_t throttleAdjustment = | |
| (int16_t)(currentControlProfile->throttle.tpa_pitch_compensation * tiltDegFromLevel); | |
| uint16_t throttleAdjusted = rcCommand[THROTTLE] + constrain(throttleAdjustment, -1000, 1000); |
User description
Merges #11042 from master into maintenance-9.x
PR Type
Enhancement, New Feature
Description
Add airspeed-based TPA (Throttle PID Attenuation) support for fixed-wing aircraft
apa_powparameter to enable airspeed-based PID scaling instead of throttle positionRefactor TPA calculation logic for improved flexibility
Enhance PID coefficient update mechanism
pidGainsUpdateRequiredto true for proper startup behaviorExpand TPA range and add validation
tpa_ratemax value from 100 to 200pitotValidForAirspeed()validation function for sensor health checksDiagram Walkthrough
flowchart LR A["Throttle/Airspeed Input"] --> B{"PID Type?"} B -->|Fixed Wing| C["Check apa_pow enabled"] B -->|Multirotor| D["Multirotor TPA"] C -->|Airspeed Valid| E["Airspeed-based TPA"] C -->|Disabled/Invalid| F["Throttle-based TPA"] F --> G["Apply Pitch Compensation"] G --> H["Filter & Constrain"] E --> I["Calculate TPA Factor"] D --> I H --> I I --> J["Update PID Coefficients"]File Walkthrough
control_profile.c
Add airspeed TPA and pitch compensation config fieldssrc/main/fc/control_profile.c
apa_powandtpa_pitch_compensationfunction
settings.yaml
Configure airspeed TPA and pitch compensation settingssrc/main/fc/settings.yaml
apa_powsetting definition with default value 120 and range 0-200tpa_pitch_compensationsetting definition with default value 8 andrange 0-20
tpa_ratemax value from 100 to 200tpa_ratedescription to include airspeed TPA detailscontrol_profile_config_struct.h
Define new throttle control structure fieldssrc/main/fc/control_profile_config_struct.h
apa_powfield (uint16_t) for airspeed-based TPA power parametertpa_pitch_compensationfield (uint8_t) for pitch angle throttlecompensation
pid.c
Implement airspeed TPA and pitch compensation logicsrc/main/flight/pid.c
pidGainsUpdateRequiredto true for proper startup behaviorcalculateFixedWingAirspeedTPAFactor()function for airspeed-basedTPA calculation
calculateTPAThtrottle()function for filtered throttle with pitchcompensation
calculateMultirotorTPAFactor()to accept throttle parameterupdatePIDCoefficients()to use TPA factor comparison insteadof throttle comparison
pitotmeter.c
Add airspeed validation function for TPAsrc/main/sensors/pitotmeter.c
pitotValidForAirspeed()function to validate pitot sensor healthsensors
pitotmeter.h
Declare airspeed validation functionsrc/main/sensors/pitotmeter.h
pitotValidForAirspeed()Settings.md
Document airspeed TPA and pitch compensation settingsdocs/Settings.md
apa_powparameter with formula and range (0-200)tpa_pitch_compensationparameter with range(0-20)
tpa_ratedescription to clarify throttle-based PID attenuationbehavior
tpa_ratemax value from 100 to 200