mirror of
https://github.com/betaflight/betaflight.git
synced 2025-07-26 09:45:37 +03:00
Block yaw, allow in CLI, option to apply yaw correction code
This commit is contained in:
parent
5e81ff6977
commit
c856485727
6 changed files with 68 additions and 34 deletions
|
@ -1862,6 +1862,8 @@ const clivalue_t valueTable[] = {
|
||||||
{ PARAM_NAME_POSITION_D, VAR_UINT8 | MASTER_VALUE, .config.minmaxUnsigned = { 0, 200 }, PG_AUTOPILOT, offsetof(autopilotConfig_t, position_D) },
|
{ PARAM_NAME_POSITION_D, VAR_UINT8 | MASTER_VALUE, .config.minmaxUnsigned = { 0, 200 }, PG_AUTOPILOT, offsetof(autopilotConfig_t, position_D) },
|
||||||
{ PARAM_NAME_POSITION_A, VAR_UINT8 | MASTER_VALUE, .config.minmaxUnsigned = { 0, 200 }, PG_AUTOPILOT, offsetof(autopilotConfig_t, position_A) },
|
{ PARAM_NAME_POSITION_A, VAR_UINT8 | MASTER_VALUE, .config.minmaxUnsigned = { 0, 200 }, PG_AUTOPILOT, offsetof(autopilotConfig_t, position_A) },
|
||||||
{ PARAM_NAME_POSITION_CUTOFF, VAR_UINT8 | MASTER_VALUE, .config.minmaxUnsigned = { 10, 250 }, PG_AUTOPILOT, offsetof(autopilotConfig_t, position_cutoff) },
|
{ PARAM_NAME_POSITION_CUTOFF, VAR_UINT8 | MASTER_VALUE, .config.minmaxUnsigned = { 10, 250 }, PG_AUTOPILOT, offsetof(autopilotConfig_t, position_cutoff) },
|
||||||
|
{ "position_allow_yaw", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_OFF_ON }, PG_AUTOPILOT, offsetof(autopilotConfig_t, position_allow_yaw) },
|
||||||
|
{ "position_test_yaw_fix", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_OFF_ON }, PG_AUTOPILOT, offsetof(autopilotConfig_t, position_test_yaw_fix) },
|
||||||
|
|
||||||
// PG_MODE_ACTIVATION_CONFIG
|
// PG_MODE_ACTIVATION_CONFIG
|
||||||
#if defined(USE_CUSTOM_BOX_NAMES)
|
#if defined(USE_CUSTOM_BOX_NAMES)
|
||||||
|
|
|
@ -49,6 +49,7 @@
|
||||||
|
|
||||||
#include "pg/rx.h"
|
#include "pg/rx.h"
|
||||||
#include "pg/pos_hold.h"
|
#include "pg/pos_hold.h"
|
||||||
|
#include "pg/autopilot.h"
|
||||||
|
|
||||||
#include "rx/rx.h"
|
#include "rx/rx.h"
|
||||||
|
|
||||||
|
@ -715,6 +716,11 @@ FAST_CODE void processRcCommand(void)
|
||||||
float rcCommandf;
|
float rcCommandf;
|
||||||
if (axis == FD_YAW) {
|
if (axis == FD_YAW) {
|
||||||
rcCommandf = rcCommand[axis] / rcCommandYawDivider;
|
rcCommandf = rcCommand[axis] / rcCommandYawDivider;
|
||||||
|
#ifdef USE_POS_HOLD_MODE
|
||||||
|
if (FLIGHT_MODE(POS_HOLD_MODE) && !autopilotConfig()->position_allow_yaw) {
|
||||||
|
rcCommandf = 0.0f;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
rcCommandf = rcCommand[axis] / rcCommandDivider;
|
rcCommandf = rcCommand[axis] / rcCommandDivider;
|
||||||
}
|
}
|
||||||
|
|
|
@ -278,6 +278,13 @@ bool positionControl(void) {
|
||||||
const float pitchP = pitchProportion * posHold.distanceCm * positionPidCoeffs.Kp;
|
const float pitchP = pitchProportion * posHold.distanceCm * positionPidCoeffs.Kp;
|
||||||
|
|
||||||
// derivative and acceleration
|
// derivative and acceleration
|
||||||
|
// note: velocity sign reverses when moving away, vs moving towards, the target
|
||||||
|
// and the proportioning factor reverses on overshooting
|
||||||
|
// net effect is that the sign of the correction stays correct
|
||||||
|
// accumulated velocity on one axis can only go to zero if velocity on that axis goes to zero
|
||||||
|
// hence we don't rotate the filtered D and A, only the input
|
||||||
|
// the delayed component of the filtered output should be rotated if the quad yaws (not done yet)
|
||||||
|
|
||||||
// roll
|
// roll
|
||||||
float velocityRoll = rollProportion * velocity;
|
float velocityRoll = rollProportion * velocity;
|
||||||
float accelerationRoll = rollProportion * acceleration;
|
float accelerationRoll = rollProportion * acceleration;
|
||||||
|
@ -302,44 +309,59 @@ bool positionControl(void) {
|
||||||
float pitchA = accelerationPitch * positionPidCoeffs.Kf;
|
float pitchA = accelerationPitch * positionPidCoeffs.Kf;
|
||||||
|
|
||||||
// iTerm
|
// iTerm
|
||||||
|
// Note: accumulated iTerm opposes wind.
|
||||||
|
// The accumulated amount of iTerm on each axis does not care about bearing error
|
||||||
|
// But accumulated iTerm should be rotated if the craft yaws (not done yet)
|
||||||
|
// For that I think we need to accumulate iTerm with an iTerm vector angle to North
|
||||||
|
// then we get separate pitch and roll values by comparing craft heading and iTerm vector
|
||||||
|
// current code assumes no yaw input and does not rotate the accumulated iTerm to preserve its direction
|
||||||
if (!posHold.isStarting){
|
if (!posHold.isStarting){
|
||||||
// hold previous iTerm while starting up
|
// don't change accumulated iTerm while adjusting position or during startup phase
|
||||||
posHold.rollI += rollProportion * posHold.distanceCm * positionPidCoeffs.Ki * gpsDataIntervalS;
|
posHold.rollI += rollProportion * posHold.distanceCm * positionPidCoeffs.Ki * gpsDataIntervalS;
|
||||||
posHold.pitchI += pitchProportion * posHold.distanceCm * positionPidCoeffs.Ki * gpsDataIntervalS;
|
posHold.pitchI += pitchProportion * posHold.distanceCm * positionPidCoeffs.Ki * gpsDataIntervalS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// calculate rotation change from the initial heading, and rotate the roll and pitch proportions accordingly
|
// ** test code to handle user yaw inputs ** //
|
||||||
const float currentHeadingDeg = attitude.values.yaw * 0.1f;
|
|
||||||
float deltaHeading = currentHeadingDeg - posHold.initialHeadingDeg;
|
|
||||||
|
|
||||||
// Normalize deltaHeading
|
if (autopilotConfig()->position_allow_yaw) {
|
||||||
if (deltaHeading > 180.0f) {
|
// code that we know is effective for fixing user yaw inputs (none at present lol)
|
||||||
deltaHeading -= 360.0f; // Wrap around if greater than 180
|
if (autopilotConfig()->position_test_yaw_fix) {
|
||||||
} else if (deltaHeading < -180.0f) {
|
// test code that might fix user yaw inputs
|
||||||
deltaHeading += 360.0f; // Wrap around if less than -180
|
|
||||||
|
// calculate rotation change from the initial heading
|
||||||
|
const float currentHeadingDeg = attitude.values.yaw * 0.1f;
|
||||||
|
float deltaHeading = currentHeadingDeg - posHold.initialHeadingDeg;
|
||||||
|
|
||||||
|
// Normalize deltaHeading
|
||||||
|
if (deltaHeading > 180.0f) {
|
||||||
|
deltaHeading -= 360.0f; // Wrap around if greater than 180
|
||||||
|
} else if (deltaHeading < -180.0f) {
|
||||||
|
deltaHeading += 360.0f; // Wrap around if less than -180
|
||||||
|
}
|
||||||
|
const float deltaHeadingRadians = deltaHeading * RAD;
|
||||||
|
|
||||||
|
float cosDeltaHeading = cos_approx(deltaHeadingRadians);
|
||||||
|
float sinDeltaHeading = sin_approx(deltaHeadingRadians);
|
||||||
|
|
||||||
|
// rotate iTerm if heading changes from original heading
|
||||||
|
const float rotatedRollI = posHold.rollI * cosDeltaHeading + posHold.pitchI * sinDeltaHeading;
|
||||||
|
const float rotatedPitchI = posHold.pitchI * cosDeltaHeading - posHold.rollI * sinDeltaHeading;
|
||||||
|
|
||||||
|
posHold.rollI = rotatedRollI;
|
||||||
|
posHold.pitchI = rotatedPitchI;
|
||||||
|
|
||||||
|
// rotate smoothed DA factors (doesn't work since inverts D sign inappropriately)
|
||||||
|
// const float rotatedRollD = rollD * cosDeltaHeading + pitchD * sinDeltaHeading;
|
||||||
|
// const float rotatedPitchD = pitchD * cosDeltaHeading - rollD * sinDeltaHeading;
|
||||||
|
// rollD = rotatedRollD;
|
||||||
|
// pitchD = rotatedPitchD;
|
||||||
|
//
|
||||||
|
// const float rotatedRollA = rollA * cosDeltaHeading + pitchA * sinDeltaHeading;
|
||||||
|
// const float rotatedPitchA = pitchA * cosDeltaHeading - rollA * sinDeltaHeading;
|
||||||
|
// rollA = rotatedRollA;
|
||||||
|
// pitchA = rotatedPitchA;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const float deltaHeadingRadians = deltaHeading * RAD;
|
|
||||||
|
|
||||||
float cosDeltaHeading = cos_approx(deltaHeadingRadians);
|
|
||||||
float sinDeltaHeading = sin_approx(deltaHeadingRadians);
|
|
||||||
|
|
||||||
// rotate iTerm if heading changes from original heading
|
|
||||||
const float rotatedRollI = posHold.rollI * cosDeltaHeading + posHold.pitchI * sinDeltaHeading;
|
|
||||||
const float rotatedPitchI = posHold.pitchI * cosDeltaHeading - posHold.rollI * sinDeltaHeading;
|
|
||||||
|
|
||||||
posHold.rollI = rotatedRollI;
|
|
||||||
posHold.pitchI = rotatedPitchI;
|
|
||||||
|
|
||||||
// rotate smoothed DA factors
|
|
||||||
// const float rotatedRollD = rollD * cosDeltaHeading + pitchD * sinDeltaHeading;
|
|
||||||
// const float rotatedPitchD = pitchD * cosDeltaHeading - rollD * sinDeltaHeading;
|
|
||||||
// rollD = rotatedRollD;
|
|
||||||
// pitchD = rotatedPitchD;
|
|
||||||
//
|
|
||||||
// const float rotatedRollA = rollA * cosDeltaHeading + pitchA * sinDeltaHeading;
|
|
||||||
// const float rotatedPitchA = pitchA * cosDeltaHeading - rollA * sinDeltaHeading;
|
|
||||||
// rollA = rotatedRollA;
|
|
||||||
// pitchA = rotatedPitchA;
|
|
||||||
|
|
||||||
// limit sum of D and A because otherwise too aggressive if entering at speed
|
// limit sum of D and A because otherwise too aggressive if entering at speed
|
||||||
float rollDA = rollD + rollA;
|
float rollDA = rollD + rollA;
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
|
|
||||||
#include "autopilot.h"
|
#include "autopilot.h"
|
||||||
|
|
||||||
PG_REGISTER_WITH_RESET_TEMPLATE(autopilotConfig_t, autopilotConfig, PG_AUTOPILOT, 1);
|
PG_REGISTER_WITH_RESET_TEMPLATE(autopilotConfig_t, autopilotConfig, PG_AUTOPILOT, 2);
|
||||||
|
|
||||||
PG_RESET_TEMPLATE(autopilotConfig_t, autopilotConfig,
|
PG_RESET_TEMPLATE(autopilotConfig_t, autopilotConfig,
|
||||||
.landing_altitude_m = 4,
|
.landing_altitude_m = 4,
|
||||||
|
@ -44,4 +44,6 @@ PG_RESET_TEMPLATE(autopilotConfig_t, autopilotConfig,
|
||||||
.position_D = 30,
|
.position_D = 30,
|
||||||
.position_A = 30,
|
.position_A = 30,
|
||||||
.position_cutoff = 80,
|
.position_cutoff = 80,
|
||||||
|
.position_allow_yaw = false, // for testing
|
||||||
|
.position_test_yaw_fix = false, // for testing
|
||||||
);
|
);
|
||||||
|
|
|
@ -39,6 +39,8 @@ typedef struct autopilotConfig_s {
|
||||||
uint8_t position_D;
|
uint8_t position_D;
|
||||||
uint8_t position_A;
|
uint8_t position_A;
|
||||||
uint8_t position_cutoff;
|
uint8_t position_cutoff;
|
||||||
|
bool position_allow_yaw;
|
||||||
|
bool position_test_yaw_fix;
|
||||||
} autopilotConfig_t;
|
} autopilotConfig_t;
|
||||||
|
|
||||||
PG_DECLARE(autopilotConfig_t, autopilotConfig);
|
PG_DECLARE(autopilotConfig_t, autopilotConfig);
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
PG_REGISTER_WITH_RESET_TEMPLATE(posHoldConfig_t, posHoldConfig, PG_POSHOLD_CONFIG, 0);
|
PG_REGISTER_WITH_RESET_TEMPLATE(posHoldConfig_t, posHoldConfig, PG_POSHOLD_CONFIG, 0);
|
||||||
|
|
||||||
PG_RESET_TEMPLATE(posHoldConfig_t, posHoldConfig,
|
PG_RESET_TEMPLATE(posHoldConfig_t, posHoldConfig,
|
||||||
.pos_hold_without_mag = false, // position hold within this percentage stick deflection
|
.pos_hold_without_mag = false, // position hold within this percentage stick deflection
|
||||||
.pos_hold_deadband = 5, // deadband in percent of stick travel for roll and pitch. Must be non-zero, and exceeded, for target location to be changed with sticks
|
.pos_hold_deadband = 5, // deadband in percent of stick travel for roll and pitch. Must be non-zero, and exceeded, for target location to be changed with sticks
|
||||||
);
|
);
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue