Skip to content

Commit 1b7dcca

Browse files
Merge pull request #11197 from iNavFlight/master
Add airspeed TPA support (backport from #11042) via merge from master
2 parents 3c4b8ff + 2747993 commit 1b7dcca

File tree

7 files changed

+104
-32
lines changed

7 files changed

+104
-32
lines changed

docs/Settings.md

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,16 @@ Max Antigravity gain. `1` means Antigravity is disabled, `2` means Iterm is allo
432432

433433
---
434434

435+
### apa_pow
436+
437+
Use airspeed instead of throttle position for PID attenuation if airspeed is available on fixedwing. pid_multiplier = (referenceAirspeed/airspeed)**(apa_pow/100). Set to 0 will disable this feature and use throttle based PID attenuation;
438+
439+
| Default | Min | Max |
440+
| --- | --- | --- |
441+
| 120 | 0 | 200 |
442+
443+
---
444+
435445
### applied_defaults
436446

437447
Internal (configurator) hint. Should not be changed manually
@@ -6442,13 +6452,23 @@ Throttle PID attenuation also reduces influence on YAW for multi-rotor, Should b
64426452

64436453
---
64446454

6455+
### tpa_pitch_compensation
6456+
6457+
Pitch angle based throttle compensation for fixed wing. Positive values will increase throttle when pitching up, and decrease throttle when pitching down.
6458+
6459+
| Default | Min | Max |
6460+
| --- | --- | --- |
6461+
| 8 | 0 | 20 |
6462+
6463+
---
6464+
64456465
### tpa_rate
64466466

6447-
Throttle PID attenuation reduces influence of PDFF on ROLL and PITCH of multi-rotor, PIDFF on ROLL,PITCH,YAW OF fixed_wing as throttle increases. For every 1% throttle after the TPA breakpoint, P is reduced by the TPA rate.
6467+
Throttle based PID attenuation(TPA) reduces influence of PDFF on ROLL and PITCH of multi-rotor, PIDFF on ROLL,PITCH,YAW OF fixed_wing as throttle increases. On multirotor, For every 1% throttle after the TPA breakpoint, P is reduced by the TPA rate. for fixedwing modifies PIDFF. See **PID Attenuation and scaling** Wiki for full details.
64486468

64496469
| Default | Min | Max |
64506470
| --- | --- | --- |
6451-
| 0 | 0 | 100 |
6471+
| 0 | 0 | 200 |
64526472

64536473
---
64546474

src/main/fc/control_profile.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,9 @@ void pgResetFn_controlProfiles(controlConfig_t *instance)
4545
.dynPID = SETTING_TPA_RATE_DEFAULT,
4646
.dynPID_on_YAW = SETTING_TPA_ON_YAW_DEFAULT,
4747
.pa_breakpoint = SETTING_TPA_BREAKPOINT_DEFAULT,
48-
.fixedWingTauMs = SETTING_FW_TPA_TIME_CONSTANT_DEFAULT
48+
.fixedWingTauMs = SETTING_FW_TPA_TIME_CONSTANT_DEFAULT,
49+
.apa_pow = SETTING_APA_POW_DEFAULT,
50+
.tpa_pitch_compensation = SETTING_TPA_PITCH_COMPENSATION_DEFAULT
4951
},
5052

5153
.stabilized = {

src/main/fc/control_profile_config_struct.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ typedef struct controlConfig_s {
3232
bool dynPID_on_YAW;
3333
uint16_t pa_breakpoint; // Breakpoint where TPA is activated
3434
uint16_t fixedWingTauMs; // Time constant of airplane TPA PT1-filter
35+
uint16_t apa_pow; // Use airspeed instead of throttle position for TPA calculation,0 to disable
36+
uint8_t tpa_pitch_compensation; // Pitch angle based throttle compensation for fixed wing
3537
} throttle;
3638

3739
struct {

src/main/fc/settings.yaml

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1379,18 +1379,31 @@ groups:
13791379
field: throttle.rcExpo8
13801380
min: 0
13811381
max: 100
1382+
- name: apa_pow
1383+
description: "Use airspeed instead of throttle position for PID attenuation if airspeed is available on fixedwing. pid_multiplier = (referenceAirspeed/airspeed)**(apa_pow/100). Set to 0 will disable this feature and use throttle based PID attenuation;"
1384+
type: uint16_t
1385+
field: throttle.apa_pow
1386+
default_value: 120
1387+
min: 0
1388+
max: 200
13821389
- name: tpa_rate
1383-
description: "Throttle PID attenuation reduces influence of PDFF on ROLL and PITCH of multi-rotor, PIDFF on ROLL,PITCH,YAW OF fixed_wing as throttle increases. For every 1% throttle after the TPA breakpoint, P is reduced by the TPA rate."
1390+
description: "Throttle based PID attenuation(TPA) reduces influence of PDFF on ROLL and PITCH of multi-rotor, PIDFF on ROLL,PITCH,YAW OF fixed_wing as throttle increases. On multirotor, For every 1% throttle after the TPA breakpoint, P is reduced by the TPA rate. for fixedwing modifies PIDFF. See **PID Attenuation and scaling** Wiki for full details."
13841391
default_value: 0
13851392
field: throttle.dynPID
13861393
min: 0
1387-
max: 100
1394+
max: 200
13881395
- name: tpa_breakpoint
13891396
description: "See tpa_rate."
13901397
default_value: 1500
13911398
field: throttle.pa_breakpoint
13921399
min: PWM_RANGE_MIN
13931400
max: PWM_RANGE_MAX
1401+
- name: tpa_pitch_compensation
1402+
description: "Pitch angle based throttle compensation for fixed wing. Positive values will increase throttle when pitching up, and decrease throttle when pitching down."
1403+
default_value: 8
1404+
field: throttle.tpa_pitch_compensation
1405+
min: 0
1406+
max: 20
13941407
- name: tpa_on_yaw
13951408
description: "Throttle PID attenuation also reduces influence on YAW for multi-rotor, Should be set to ON for tilting rotors."
13961409
type: bool

src/main/flight/pid.c

Lines changed: 52 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ static EXTENDED_FASTRAM pt1Filter_t headingHoldRateFilter;
126126
static EXTENDED_FASTRAM pt1Filter_t fixedWingTpaFilter;
127127

128128
// Thrust PID Attenuation factor. 0.0f means fully attenuated, 1.0f no attenuation is applied
129-
STATIC_FASTRAM bool pidGainsUpdateRequired;
129+
STATIC_FASTRAM bool pidGainsUpdateRequired= true;
130130
FASTRAM int16_t axisPID[FLIGHT_DYNAMICS_INDEX_COUNT];
131131

132132
#ifdef USE_BLACKBOX
@@ -442,6 +442,14 @@ float pidRcCommandToRate(int16_t stick, uint8_t rate)
442442
return scaleRangef((float) stick, -500.0f, 500.0f, -maxRateDPS, maxRateDPS);
443443
}
444444

445+
static float calculateFixedWingAirspeedTPAFactor(void){
446+
const float airspeed = getAirspeedEstimate(); // in cm/s
447+
const float referenceAirspeed = pidProfile()->fixedWingReferenceAirspeed; // in cm/s
448+
float tpaFactor= powf(referenceAirspeed/(airspeed+0.01f), currentControlProfile->throttle.apa_pow/100.0f);
449+
tpaFactor= constrainf(tpaFactor, 0.3f, 2.0f);
450+
return tpaFactor;
451+
}
452+
445453
static float calculateFixedWingTPAFactor(uint16_t throttle)
446454
{
447455
float tpaFactor;
@@ -452,16 +460,15 @@ static float calculateFixedWingTPAFactor(uint16_t throttle)
452460
if (throttle > getThrottleIdleValue()) {
453461
// Calculate TPA according to throttle
454462
tpaFactor = 0.5f + ((float)(currentControlProfile->throttle.pa_breakpoint - getThrottleIdleValue()) / (throttle - getThrottleIdleValue()) / 2.0f);
455-
456-
// Limit to [0.5; 2] range
457-
tpaFactor = constrainf(tpaFactor, 0.5f, 2.0f);
458463
}
459464
else {
460465
tpaFactor = 2.0f;
461466
}
462467

463468
// Attenuate TPA curve according to configured amount
464469
tpaFactor = 1.0f + (tpaFactor - 1.0f) * (currentControlProfile->throttle.dynPID / 100.0f);
470+
// Limit to [0.5; 2] range
471+
tpaFactor = constrainf(tpaFactor, 0.3f, 2.0f);
465472
}
466473
else {
467474
tpaFactor = 1.0f;
@@ -470,45 +477,48 @@ static float calculateFixedWingTPAFactor(uint16_t throttle)
470477
return tpaFactor;
471478
}
472479

473-
static float calculateMultirotorTPAFactor(void)
480+
static float calculateMultirotorTPAFactor(uint16_t throttle)
474481
{
475482
float tpaFactor;
476483

477484
// TPA should be updated only when TPA is actually set
478-
if (currentControlProfile->throttle.dynPID == 0 || rcCommand[THROTTLE] < currentControlProfile->throttle.pa_breakpoint) {
485+
if (currentControlProfile->throttle.dynPID == 0 || throttle < currentControlProfile->throttle.pa_breakpoint) {
479486
tpaFactor = 1.0f;
480-
} else if (rcCommand[THROTTLE] < getMaxThrottle()) {
481-
tpaFactor = (100 - (uint16_t)currentControlProfile->throttle.dynPID * (rcCommand[THROTTLE] - currentControlProfile->throttle.pa_breakpoint) / (float)(getMaxThrottle() - currentControlProfile->throttle.pa_breakpoint)) / 100.0f;
487+
} else if (throttle < getMaxThrottle()) {
488+
tpaFactor = (100 - (uint16_t)currentControlProfile->throttle.dynPID * (throttle - currentControlProfile->throttle.pa_breakpoint) / (float)(getMaxThrottle() - currentControlProfile->throttle.pa_breakpoint)) / 100.0f;
482489
} else {
483-
tpaFactor = (100 - currentControlProfile->throttle.dynPID) / 100.0f;
490+
tpaFactor = (100 - constrain(currentControlProfile->throttle.dynPID, 0, 100)) / 100.0f;
484491
}
485492

486493
return tpaFactor;
487494
}
488495

496+
static float calculateTPAThtrottle(void)
497+
{
498+
uint16_t tpaThrottle = 0;
499+
static const fpVector3_t vDown = { .v = { 0.0f, 0.0f, 1.0f } };
500+
501+
if (usedPidControllerType == PID_TYPE_PIFF && (currentControlProfile->throttle.fixedWingTauMs > 0)) { //fixed wing TPA with filtering
502+
fpVector3_t vForward = { .v = { HeadVecEFFiltered.x, -HeadVecEFFiltered.y, -HeadVecEFFiltered.z } };
503+
float groundCos = vectorDotProduct(&vForward, &vDown);
504+
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,
505+
uint16_t throttleAdjusted = rcCommand[THROTTLE] + constrain(throttleAdjustment, -1000, 1000);
506+
tpaThrottle = pt1FilterApply(&fixedWingTpaFilter, constrain(throttleAdjusted, 1000, 2000));
507+
}
508+
else {
509+
tpaThrottle = rcCommand[THROTTLE]; //multirotor TPA without filtering
510+
}
511+
return tpaThrottle;
512+
}
513+
489514
void schedulePidGainsUpdate(void)
490515
{
491516
pidGainsUpdateRequired = true;
492517
}
493518

494519
void updatePIDCoefficients(void)
495520
{
496-
STATIC_FASTRAM uint16_t prevThrottle = 0;
497-
498-
// Check if throttle changed. Different logic for fixed wing vs multirotor
499-
if (usedPidControllerType == PID_TYPE_PIFF && (currentControlProfile->throttle.fixedWingTauMs > 0)) {
500-
uint16_t filteredThrottle = pt1FilterApply(&fixedWingTpaFilter, rcCommand[THROTTLE]);
501-
if (filteredThrottle != prevThrottle) {
502-
prevThrottle = filteredThrottle;
503-
pidGainsUpdateRequired = true;
504-
}
505-
}
506-
else {
507-
if (rcCommand[THROTTLE] != prevThrottle) {
508-
prevThrottle = rcCommand[THROTTLE];
509-
pidGainsUpdateRequired = true;
510-
}
511-
}
521+
STATIC_FASTRAM float tpaFactorprev=-1.0f;
512522

513523
#ifdef USE_ANTIGRAVITY
514524
if (usedPidControllerType == PID_TYPE_PID) {
@@ -523,14 +533,29 @@ void updatePIDCoefficients(void)
523533
for (int axis = 0; axis < 3; axis++) {
524534
pidState[axis].stickPosition = constrain(rxGetChannelValue(axis) - PWM_RANGE_MIDDLE, -500, 500) / 500.0f;
525535
}
536+
537+
float tpaFactor=1.0f;
538+
if(usedPidControllerType == PID_TYPE_PIFF){ // Fixed wing TPA calculation
539+
if(currentControlProfile->throttle.apa_pow>0 && pitotValidForAirspeed()){
540+
tpaFactor = calculateFixedWingAirspeedTPAFactor();
541+
}else{
542+
tpaFactor = calculateFixedWingTPAFactor(calculateTPAThtrottle());
543+
}
544+
} else {
545+
tpaFactor = calculateMultirotorTPAFactor(calculateTPAThtrottle());
546+
}
547+
if (tpaFactor != tpaFactorprev) {
548+
pidGainsUpdateRequired = true;
549+
}
550+
tpaFactorprev = tpaFactor;
526551

552+
527553
// If nothing changed - don't waste time recalculating coefficients
528554
if (!pidGainsUpdateRequired) {
529555
return;
530556
}
531557

532-
const float tpaFactor = usedPidControllerType == PID_TYPE_PIFF ? calculateFixedWingTPAFactor(prevThrottle) : calculateMultirotorTPAFactor();
533-
558+
534559
// PID coefficients can be update only with THROTTLE and TPA or inflight PID adjustments
535560
//TODO: Next step would be to update those only at THROTTLE or inflight adjustments change
536561
for (int axis = 0; axis < 3; axis++) {

src/main/sensors/pitotmeter.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,4 +312,13 @@ bool pitotIsHealthy(void)
312312
return (millis() - pitot.lastSeenHealthyMs) < PITOT_HARDWARE_TIMEOUT_MS;
313313
}
314314

315+
bool pitotValidForAirspeed(void)
316+
{
317+
bool ret = false;
318+
ret = pitotIsHealthy() && pitotIsCalibrationComplete();
319+
if (detectedSensors[SENSOR_INDEX_PITOT] == PITOT_VIRTUAL) {
320+
ret = ret && STATE(GPS_FIX);
321+
}
322+
return ret;
323+
}
315324
#endif /* PITOT */

src/main/sensors/pitotmeter.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,5 +69,6 @@ void pitotStartCalibration(void);
6969
void pitotUpdate(void);
7070
float getAirspeedEstimate(void);
7171
bool pitotIsHealthy(void);
72+
bool pitotValidForAirspeed(void);
7273

7374
#endif

0 commit comments

Comments
 (0)