Skip to content

Commit ab3411a

Browse files
authored
Merge pull request iNavFlight#10903 from breadoven/abo_fw_alt_cont_use_pos
Option to use position for fixed wing nav altitude control
2 parents c28a468 + 4d63f88 commit ab3411a

6 files changed

Lines changed: 95 additions & 20 deletions

File tree

docs/Settings.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3152,6 +3152,16 @@ Adjusts the deceleration response of fixed wing altitude control as the target a
31523152

31533153
---
31543154

3155+
### nav_fw_alt_use_position
3156+
3157+
Use position for fixed wing altitude control rather than velocity (default method).
3158+
3159+
| Default | Min | Max |
3160+
| --- | --- | --- |
3161+
| OFF | OFF | ON |
3162+
3163+
---
3164+
31553165
### nav_fw_auto_climb_rate
31563166

31573167
Maximum climb/descent rate that UAV is allowed to reach during navigation modes. [cm/s]
@@ -3634,11 +3644,11 @@ D gain of altitude PID controller (Fixedwing)
36343644

36353645
### nav_fw_pos_z_ff
36363646

3637-
FF gain of altitude PID controller (Fixedwing)
3647+
FF gain of altitude PID controller. Not used if nav_fw_alt_use_position is set ON (Fixedwing)
36383648

36393649
| Default | Min | Max |
36403650
| --- | --- | --- |
3641-
| 10 | 0 | 255 |
3651+
| 30 | 0 | 255 |
36423652

36433653
---
36443654

src/main/fc/settings.yaml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2160,8 +2160,8 @@ groups:
21602160
min: 0
21612161
max: 255
21622162
- name: nav_fw_pos_z_ff
2163-
description: "FF gain of altitude PID controller (Fixedwing)"
2164-
default_value: 10
2163+
description: "FF gain of altitude PID controller. Not used if nav_fw_alt_use_position is set ON (Fixedwing)"
2164+
default_value: 30
21652165
field: bank_fw.pid[PID_POS_Z].FF
21662166
min: 0
21672167
max: 255
@@ -2171,6 +2171,11 @@ groups:
21712171
field: fwAltControlResponseFactor
21722172
min: 5
21732173
max: 100
2174+
- name: nav_fw_alt_use_position
2175+
description: "Use position for fixed wing altitude control rather than velocity (default method)."
2176+
default_value: OFF
2177+
field: fwAltControlUsePos
2178+
type: bool
21742179
- name: nav_fw_pos_xy_p
21752180
description: "P gain of 2D trajectory PID controller. Play with this to get a straight line between waypoints or a straight RTH"
21762181
default_value: 75

src/main/flight/pid.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ static EXTENDED_FASTRAM bool angleHoldIsLevel = false;
179179
static EXTENDED_FASTRAM float fixedWingLevelTrim;
180180
static EXTENDED_FASTRAM pidController_t fixedWingLevelTrimController;
181181

182-
PG_REGISTER_PROFILE_WITH_RESET_TEMPLATE(pidProfile_t, pidProfile, PG_PID_PROFILE, 10);
182+
PG_REGISTER_PROFILE_WITH_RESET_TEMPLATE(pidProfile_t, pidProfile, PG_PID_PROFILE, 11);
183183

184184
PG_RESET_TEMPLATE(pidProfile_t, pidProfile,
185185
.bank_mc = {
@@ -308,6 +308,7 @@ PG_RESET_TEMPLATE(pidProfile_t, pidProfile,
308308
.fixedWingLevelTrimGain = SETTING_FW_LEVEL_PITCH_GAIN_DEFAULT,
309309

310310
.fwAltControlResponseFactor = SETTING_NAV_FW_ALT_CONTROL_RESPONSE_DEFAULT,
311+
.fwAltControlUsePos = SETTING_NAV_FW_ALT_USE_POSITION_DEFAULT,
311312
#ifdef USE_SMITH_PREDICTOR
312313
.smithPredictorStrength = SETTING_SMITH_PREDICTOR_STRENGTH_DEFAULT,
313314
.smithPredictorDelay = SETTING_SMITH_PREDICTOR_DELAY_DEFAULT,

src/main/flight/pid.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ typedef struct pidProfile_s {
150150
float fixedWingLevelTrimGain;
151151

152152
uint8_t fwAltControlResponseFactor;
153+
bool fwAltControlUsePos;
153154
#ifdef USE_SMITH_PREDICTOR
154155
float smithPredictorStrength;
155156
float smithPredictorDelay;

src/main/navigation/navigation.c

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4956,13 +4956,23 @@ void navigationUsePIDs(void)
49564956
0.0f
49574957
);
49584958

4959-
navPidInit(&posControl.pids.fw_alt, (float)pidProfile()->bank_fw.pid[PID_POS_Z].P / 100.0f,
4960-
(float)pidProfile()->bank_fw.pid[PID_POS_Z].I / 100.0f,
4961-
(float)pidProfile()->bank_fw.pid[PID_POS_Z].D / 300.0f,
4962-
(float)pidProfile()->bank_fw.pid[PID_POS_Z].FF / 100.0f,
4963-
NAV_DTERM_CUT_HZ,
4964-
0.0f
4965-
);
4959+
if (pidProfile()->fwAltControlUsePos) {
4960+
navPidInit(&posControl.pids.fw_alt, (float)pidProfile()->bank_fw.pid[PID_POS_Z].P / 100.0f,
4961+
(float)pidProfile()->bank_fw.pid[PID_POS_Z].I / 100.0f,
4962+
(float)pidProfile()->bank_fw.pid[PID_POS_Z].D / 100.0f,
4963+
0.0f,
4964+
NAV_DTERM_CUT_HZ,
4965+
0.0f
4966+
);
4967+
} else {
4968+
navPidInit(&posControl.pids.fw_alt, (float)pidProfile()->bank_fw.pid[PID_POS_Z].P / 100.0f,
4969+
(float)pidProfile()->bank_fw.pid[PID_POS_Z].I / 100.0f,
4970+
(float)pidProfile()->bank_fw.pid[PID_POS_Z].D / 300.0f,
4971+
(float)pidProfile()->bank_fw.pid[PID_POS_Z].FF / 100.0f,
4972+
NAV_DTERM_CUT_HZ,
4973+
0.0f
4974+
);
4975+
}
49664976

49674977
navPidInit(&posControl.pids.fw_heading, (float)pidProfile()->bank_fw.pid[PID_POS_HEADING].P / 10.0f,
49684978
(float)pidProfile()->bank_fw.pid[PID_POS_HEADING].I / 10.0f,

src/main/navigation/navigation_fixedwing.c

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -131,25 +131,74 @@ bool adjustFixedWingAltitudeFromRCInput(void)
131131
// Position to velocity controller for Z axis
132132
static void updateAltitudeVelocityAndPitchController_FW(timeDelta_t deltaMicros)
133133
{
134-
static pt1Filter_t velzFilterState;
134+
static pt1Filter_t pitchFilterState;
135135

136136
float desiredClimbRate = getDesiredClimbRate(posControl.desiredState.pos.z, deltaMicros);
137137

138138
// Reduce max allowed climb rate by 2/3 if performing loiter (stall prevention)
139-
if (needToCalculateCircularLoiter && desiredClimbRate > 0.67f * navConfig()->fw.max_auto_climb_rate) {
139+
if (navGetCurrentStateFlags() & NAV_CTL_HOLD && desiredClimbRate > 0.67f * navConfig()->fw.max_auto_climb_rate) {
140140
desiredClimbRate = 0.67f * navConfig()->fw.max_auto_climb_rate;
141141
}
142142

143143
// Here we use negative values for dive for better clarity
144144
const float maxClimbDeciDeg = DEGREES_TO_DECIDEGREES(navConfig()->fw.max_climb_angle);
145145
const float minDiveDeciDeg = -DEGREES_TO_DECIDEGREES(navConfig()->fw.max_dive_angle);
146146

147-
// PID controller to translate desired climb rate error into pitch angle [decideg]
148-
float currentClimbRate = navGetCurrentActualPositionAndVelocity()->vel.z;
149-
float targetPitchAngle = navPidApply2(&posControl.pids.fw_alt, desiredClimbRate, currentClimbRate, US2S(deltaMicros), minDiveDeciDeg, maxClimbDeciDeg, PID_DTERM_FROM_ERROR);
147+
// Default control based on climb rate (velocity)
148+
float targetValue = desiredClimbRate;
149+
float measuredValue = navGetCurrentActualPositionAndVelocity()->vel.z;
150+
151+
// Optional control based on altitude (position)
152+
if (pidProfile()->fwAltControlUsePos) {
153+
static float currentDesiredPosZ = 0.0f;
154+
static float trackingAltitude = 0.0f;
155+
static bool altitudeRateControlActive = false;
156+
157+
float desiredAltitude = posControl.desiredState.pos.z;
158+
float currentAltitude = navGetCurrentActualPositionAndVelocity()->pos.z;
159+
160+
/* Determine if altitude rate control required based on magnitude of change in target altitude.
161+
* No rate control used during trackback to allow max climb rates based on pitch limits */
162+
if (fabsf(currentDesiredPosZ - desiredAltitude) > 100.0f || !isPitchAdjustmentValid) {
163+
altitudeRateControlActive = desiredClimbRate && fabsf(desiredAltitude - currentAltitude) > navConfig()->fw.max_auto_climb_rate &&
164+
!posControl.flags.rthTrackbackActive;
165+
trackingAltitude = currentAltitude;
166+
}
167+
currentDesiredPosZ = desiredAltitude;
168+
169+
if (posControl.flags.rocToAltMode == ROC_TO_ALT_CONSTANT || altitudeRateControlActive) {
170+
/* Adjustment factor based on vertical acceleration used to better control altitude position change
171+
* driving vertical velocity control. Helps avoid lag induced overcontrol by PID loop. */
172+
static float absLastClimbRate = 0.0f;
173+
float absClimbRate = fabsf(measuredValue);
174+
float accelerationZ = (absClimbRate - absLastClimbRate) / US2S(deltaMicros);
175+
absLastClimbRate = absClimbRate;
176+
float adjustmentFactor = constrainf(scaleRangef(accelerationZ, 0.0f, 200.0f, 1.0f, 0.0f), 0.0f, 1.0f);
177+
178+
if (posControl.flags.rocToAltMode == ROC_TO_ALT_CONSTANT) {
179+
posControl.desiredState.pos.z += adjustmentFactor * desiredClimbRate * US2S(deltaMicros);
180+
desiredAltitude = posControl.desiredState.pos.z;
181+
} else {
182+
/* Disable rate control if no longer required, i.e. remaining altitude change is small */
183+
altitudeRateControlActive = fabsf(desiredAltitude - currentAltitude) > MAX(fabsf(desiredClimbRate), 50.0f);
184+
185+
/* Tracking altitude used to control altitude rate where changing posControl.desiredState.pos.z not possible */
186+
trackingAltitude += adjustmentFactor * desiredClimbRate * US2S(deltaMicros);
187+
desiredAltitude = trackingAltitude;
188+
}
189+
} else {
190+
desiredClimbRate = 0;
191+
}
192+
193+
targetValue = desiredAltitude;
194+
measuredValue = currentAltitude;
195+
}
196+
197+
// PID controller to translate desired target error (velocity or position) into pitch angle [decideg]
198+
float targetPitchAngle = navPidApply2(&posControl.pids.fw_alt, targetValue, measuredValue, US2S(deltaMicros), minDiveDeciDeg, maxClimbDeciDeg, 0);
150199

151200
// Apply low-pass filter to prevent rapid correction
152-
targetPitchAngle = pt1FilterApply4(&velzFilterState, targetPitchAngle, getSmoothnessCutoffFreq(NAV_FW_BASE_PITCH_CUTOFF_FREQUENCY_HZ), US2S(deltaMicros));
201+
targetPitchAngle = pt1FilterApply4(&pitchFilterState, targetPitchAngle, getSmoothnessCutoffFreq(NAV_FW_BASE_PITCH_CUTOFF_FREQUENCY_HZ), US2S(deltaMicros));
153202

154203
// Reconstrain pitch angle (> 0 - climb, < 0 - dive)
155204
targetPitchAngle = constrainf(targetPitchAngle, minDiveDeciDeg, maxClimbDeciDeg);
@@ -171,6 +220,7 @@ void applyFixedWingAltitudeAndThrottleController(timeUs_t currentTimeUs)
171220
// Check if last correction was not too long ago
172221
if (deltaMicrosPositionUpdate < MAX_POSITION_UPDATE_INTERVAL_US) {
173222
updateAltitudeVelocityAndPitchController_FW(deltaMicrosPositionUpdate);
223+
isPitchAdjustmentValid = true;
174224
}
175225
else {
176226
// Position update has not occurred in time (first iteration or glitch), reset altitude controller
@@ -180,8 +230,6 @@ void applyFixedWingAltitudeAndThrottleController(timeUs_t currentTimeUs)
180230
// Indicate that information is no longer usable
181231
posControl.flags.verticalPositionDataConsumed = true;
182232
}
183-
184-
isPitchAdjustmentValid = true;
185233
}
186234
else {
187235
// No valid altitude sensor data, don't adjust pitch automatically, rcCommand[PITCH] is passed through to PID controller

0 commit comments

Comments
 (0)