1
0
Fork 0
mirror of https://github.com/iNavFlight/inav.git synced 2025-07-18 05:45:28 +03:00

Loiter direction (#4036)

* Loiter direction
https://github.com/iNavFlight/inav/issues/3002
This commit is contained in:
hali9 2019-01-08 08:26:06 +01:00 committed by Konstantin Sharlaimov
parent 61654d8ce8
commit 69970a2b95
8 changed files with 40 additions and 3 deletions

View file

@ -339,6 +339,7 @@ After restoring it's always a good idea to `dump` or `diff` the settings once ag
| fw_iterm_throw_limit | 165 | Limits max/min I-term value in stabilization PID controller in case of Fixed Wing. It solves the problem of servo saturation before take-off/throwing the airplane into the air. By default, error accumulated in I-term can not exceed 1/3 of servo throw (around 165us). Set 0 to disable completely. | | fw_iterm_throw_limit | 165 | Limits max/min I-term value in stabilization PID controller in case of Fixed Wing. It solves the problem of servo saturation before take-off/throwing the airplane into the air. By default, error accumulated in I-term can not exceed 1/3 of servo throw (around 165us). Set 0 to disable completely. |
| fw_reference_airspeed | 1000 | Reference airspeed. Set this to airspeed at which PIDs were tuned. Usually should be set to cruise airspeed. Also used for coordinated turn calculation if airspeed sensor is not present. | | fw_reference_airspeed | 1000 | Reference airspeed. Set this to airspeed at which PIDs were tuned. Usually should be set to cruise airspeed. Also used for coordinated turn calculation if airspeed sensor is not present. |
| fw_turn_assist_yaw_gain | 1 | Gain required to keep the yaw rate consistent with the turn rate for a coordinated turn (in TURN_ASSIST mode). Value significantly different from 1.0 indicates a problem with the airspeed calibration (if present) or value of `fw_reference_airspeed` parameter | | fw_turn_assist_yaw_gain | 1 | Gain required to keep the yaw rate consistent with the turn rate for a coordinated turn (in TURN_ASSIST mode). Value significantly different from 1.0 indicates a problem with the airspeed calibration (if present) or value of `fw_reference_airspeed` parameter |
| fw_loiter_direction | RIGHT | Direction of loitering: center point on right wing (clockwise - default), or center point on left wing (counterclockwise). If equal YAW then can be changed in flight using a yaw stick. |
| mode_range_logic_operator | OR | Control how Mode selection works in flight modes. If you example have Angle mode configured on two different Aux channels, this controls if you need both activated ( AND ) or if you only need one activated ( OR ) to active angle mode. | | mode_range_logic_operator | OR | Control how Mode selection works in flight modes. If you example have Angle mode configured on two different Aux channels, this controls if you need both activated ( AND ) or if you only need one activated ( OR ) to active angle mode. |
| default_rate_profile | 0 | Default = profile number | | default_rate_profile | 0 | Default = profile number |
| mag_declination | 0 | Current location magnetic declination in format. For example, -6deg 37min = -637 for Japan. Leading zero in ddd not required. Get your local magnetic declination here: http://magnetic-declination.com/ . Not in use if inav_auto_mag_decl is turned on and you acquire valid GPS fix. | | mag_declination | 0 | Current location magnetic declination in format. For example, -6deg 37min = -637 for Japan. Leading zero in ddd not required. Get your local magnetic declination here: http://magnetic-declination.com/ . Not in use if inav_auto_mag_decl is turned on and you acquire valid GPS fix. |

View file

@ -84,6 +84,7 @@ static const box_t boxes[CHECKBOX_ITEM_COUNT + 1] = {
{ BOXBRAKING, "MC BRAKING", 46 }, { BOXBRAKING, "MC BRAKING", 46 },
{ BOXUSER1, "USER1", 47 }, { BOXUSER1, "USER1", 47 },
{ BOXUSER2, "USER2", 48 }, { BOXUSER2, "USER2", 48 },
{ BOXLOITERDIRCHN, "LOITER CHANGE", 49 },
{ CHECKBOX_ITEM_COUNT, NULL, 0xFF } { CHECKBOX_ITEM_COUNT, NULL, 0xFF }
}; };
@ -195,6 +196,9 @@ void initActiveBoxIds(void)
const bool navFlowDeadReckoning = sensors(SENSOR_OPFLOW) && sensors(SENSOR_ACC) && positionEstimationConfig()->allow_dead_reckoning; const bool navFlowDeadReckoning = sensors(SENSOR_OPFLOW) && sensors(SENSOR_ACC) && positionEstimationConfig()->allow_dead_reckoning;
if (navFlowDeadReckoning || navReadyQuads || navReadyPlanes) { if (navFlowDeadReckoning || navReadyQuads || navReadyPlanes) {
activeBoxIds[activeBoxIdCount++] = BOXNAVPOSHOLD; activeBoxIds[activeBoxIdCount++] = BOXNAVPOSHOLD;
if (STATE(FIXED_WING)) {
activeBoxIds[activeBoxIdCount++] = BOXLOITERDIRCHN;
}
} }
if (navReadyQuads || navReadyPlanes) { if (navReadyQuads || navReadyPlanes) {
@ -343,6 +347,7 @@ void packBoxModeFlags(boxBitmask_t * mspBoxModeFlags)
CHECK_ACTIVE_BOX(IS_ENABLED(IS_RC_MODE_ACTIVE(BOXBRAKING)), BOXBRAKING); CHECK_ACTIVE_BOX(IS_ENABLED(IS_RC_MODE_ACTIVE(BOXBRAKING)), BOXBRAKING);
CHECK_ACTIVE_BOX(IS_ENABLED(IS_RC_MODE_ACTIVE(BOXUSER1)), BOXUSER1); CHECK_ACTIVE_BOX(IS_ENABLED(IS_RC_MODE_ACTIVE(BOXUSER1)), BOXUSER1);
CHECK_ACTIVE_BOX(IS_ENABLED(IS_RC_MODE_ACTIVE(BOXUSER2)), BOXUSER2); CHECK_ACTIVE_BOX(IS_ENABLED(IS_RC_MODE_ACTIVE(BOXUSER2)), BOXUSER2);
CHECK_ACTIVE_BOX(IS_ENABLED(IS_RC_MODE_ACTIVE(BOXLOITERDIRCHN)),BOXLOITERDIRCHN);
memset(mspBoxModeFlags, 0, sizeof(boxBitmask_t)); memset(mspBoxModeFlags, 0, sizeof(boxBitmask_t));
for (uint32_t i = 0; i < activeBoxIdCount; i++) { for (uint32_t i = 0; i < activeBoxIdCount; i++) {

View file

@ -66,6 +66,7 @@ typedef enum {
BOXUSER1 = 37, BOXUSER1 = 37,
BOXUSER2 = 38, BOXUSER2 = 38,
BOXFPVANGLEMIX = 39, BOXFPVANGLEMIX = 39,
BOXLOITERDIRCHN = 40,
CHECKBOX_ITEM_COUNT CHECKBOX_ITEM_COUNT
} boxId_e; } boxId_e;

View file

@ -49,6 +49,8 @@ tables:
enum: gpsDynModel_e enum: gpsDynModel_e
- name: reset_type - name: reset_type
values: ["NEVER", "FIRST_ARM", "EACH_ARM"] values: ["NEVER", "FIRST_ARM", "EACH_ARM"]
- name: direction
values: ["RIGHT", "LEFT", "YAW"]
- name: nav_user_control_mode - name: nav_user_control_mode
values: ["ATTI", "CRUISE"] values: ["ATTI", "CRUISE"]
- name: nav_rth_alt_mode - name: nav_rth_alt_mode
@ -951,6 +953,10 @@ groups:
field: fixedWingItermThrowLimit field: fixedWingItermThrowLimit
min: FW_ITERM_THROW_LIMIT_MIN min: FW_ITERM_THROW_LIMIT_MIN
max: FW_ITERM_THROW_LIMIT_MAX max: FW_ITERM_THROW_LIMIT_MAX
- name: fw_loiter_direction
field: loiter_direction
condition: USE_NAV
table: direction
- name: fw_reference_airspeed - name: fw_reference_airspeed
field: fixedWingReferenceAirspeed field: fixedWingReferenceAirspeed
min: 1 min: 1

View file

@ -194,6 +194,8 @@ PG_RESET_TEMPLATE(pidProfile_t, pidProfile,
.fixedWingReferenceAirspeed = 1000, .fixedWingReferenceAirspeed = 1000,
.fixedWingCoordinatedYawGain = 1.0f, .fixedWingCoordinatedYawGain = 1.0f,
.fixedWingItermLimitOnStickPosition = 0.5f, .fixedWingItermLimitOnStickPosition = 0.5f,
.loiter_direction = NAV_LOITER_RIGHT,
); );
void pidInit(void) void pidInit(void)

View file

@ -105,6 +105,8 @@ typedef struct pidProfile_s {
float fixedWingReferenceAirspeed; // Reference tuning airspeed for the airplane - the speed for which PID gains are tuned float fixedWingReferenceAirspeed; // Reference tuning airspeed for the airplane - the speed for which PID gains are tuned
float fixedWingCoordinatedYawGain; // This is the gain of the yaw rate required to keep the yaw rate consistent with the turn rate for a coordinated turn. float fixedWingCoordinatedYawGain; // This is the gain of the yaw rate required to keep the yaw rate consistent with the turn rate for a coordinated turn.
float fixedWingItermLimitOnStickPosition; //Do not allow Iterm to grow when stick position is above this point float fixedWingItermLimitOnStickPosition; //Do not allow Iterm to grow when stick position is above this point
uint8_t loiter_direction; // Direction of loitering center point on right wing (clockwise - as before), or center point on left wing (counterclockwise)
} pidProfile_t; } pidProfile_t;
typedef struct pidAutotuneConfig_s { typedef struct pidAutotuneConfig_s {

View file

@ -54,6 +54,12 @@ enum {
NAV_GPS_CRUISE = 1 // Pitch/roll stick controls velocity (forward/right speed) NAV_GPS_CRUISE = 1 // Pitch/roll stick controls velocity (forward/right speed)
}; };
enum {
NAV_LOITER_RIGHT = 0, // Loitering direction right
NAV_LOITER_LEFT = 1, // Loitering direction left
NAV_LOITER_YAW = 2
};
enum { enum {
NAV_RTH_NO_ALT = 0, // Maintain current altitude NAV_RTH_NO_ALT = 0, // Maintain current altitude
NAV_RTH_EXTRA_ALT = 1, // Maintain current altitude + predefined safety margin NAV_RTH_EXTRA_ALT = 1, // Maintain current altitude + predefined safety margin

View file

@ -43,6 +43,7 @@
#include "fc/config.h" #include "fc/config.h"
#include "fc/controlrate_profile.h" #include "fc/controlrate_profile.h"
#include "fc/rc_controls.h" #include "fc/rc_controls.h"
#include "fc/rc_modes.h"
#include "fc/runtime_config.h" #include "fc/runtime_config.h"
#include "navigation/navigation.h" #include "navigation/navigation.h"
@ -63,6 +64,7 @@ static bool isRollAdjustmentValid = false;
static float throttleSpeedAdjustment = 0; static float throttleSpeedAdjustment = 0;
static bool isAutoThrottleManuallyIncreased = false; static bool isAutoThrottleManuallyIncreased = false;
static int32_t navHeadingError; static int32_t navHeadingError;
static int8_t loiterDirYaw = 1;
/*----------------------------------------------------------- /*-----------------------------------------------------------
@ -213,6 +215,18 @@ void resetFixedWingPositionController(void)
pt1FilterReset(&fwPosControllerCorrectionFilterState, 0.0f); pt1FilterReset(&fwPosControllerCorrectionFilterState, 0.0f);
} }
static int8_t loiterDirection(void) {
int8_t dir = 1; //NAV_LOITER_RIGHT
if (pidProfile()->loiter_direction == NAV_LOITER_LEFT) dir = -1;
if (pidProfile()->loiter_direction == NAV_LOITER_YAW) {
if (rcCommand[YAW] < -250) loiterDirYaw = 1; //RIGHT //yaw is contrariwise
if (rcCommand[YAW] > 250) loiterDirYaw = -1; //LEFT //see annexCode in fc_core.c
dir = loiterDirYaw;
}
if (IS_RC_MODE_ACTIVE(BOXLOITERDIRCHN)) dir *= -1;
return dir;
}
static void calculateVirtualPositionTarget_FW(float trackingPeriod) static void calculateVirtualPositionTarget_FW(float trackingPeriod)
{ {
float posErrorX = posControl.desiredState.pos.x - navGetCurrentActualPositionAndVelocity()->pos.x; float posErrorX = posControl.desiredState.pos.x - navGetCurrentActualPositionAndVelocity()->pos.x;
@ -233,7 +247,7 @@ static void calculateVirtualPositionTarget_FW(float trackingPeriod)
// Calculate virtual position for straight movement // Calculate virtual position for straight movement
if (needToCalculateCircularLoiter) { if (needToCalculateCircularLoiter) {
// We are closing in on a waypoint, calculate circular loiter // We are closing in on a waypoint, calculate circular loiter
float loiterAngle = atan2_approx(-posErrorY, -posErrorX) + DEGREES_TO_RADIANS(45.0f); float loiterAngle = atan2_approx(-posErrorY, -posErrorX) + DEGREES_TO_RADIANS(loiterDirection() * 45.0f);
float loiterTargetX = posControl.desiredState.pos.x + navConfig()->fw.loiter_radius * cos_approx(loiterAngle); float loiterTargetX = posControl.desiredState.pos.x + navConfig()->fw.loiter_radius * cos_approx(loiterAngle);
float loiterTargetY = posControl.desiredState.pos.y + navConfig()->fw.loiter_radius * sin_approx(loiterAngle); float loiterTargetY = posControl.desiredState.pos.y + navConfig()->fw.loiter_radius * sin_approx(loiterAngle);
@ -292,7 +306,7 @@ static void updatePositionHeadingController_FW(timeUs_t currentTimeUs, timeDelta
// If forced turn direction flag is enabled we fix the sign of the direction // If forced turn direction flag is enabled we fix the sign of the direction
if (forceTurnDirection) { if (forceTurnDirection) {
navHeadingError = ABS(navHeadingError); navHeadingError = loiterDirection() * ABS(navHeadingError);
} }
// Slow error monitoring (2Hz rate) // Slow error monitoring (2Hz rate)
@ -308,7 +322,7 @@ static void updatePositionHeadingController_FW(timeUs_t currentTimeUs, timeDelta
// Only allow PID integrator to shrink if error is decreasing over time // Only allow PID integrator to shrink if error is decreasing over time
const pidControllerFlags_e pidFlags = PID_DTERM_FROM_ERROR | (errorIsDecreasing ? PID_SHRINK_INTEGRATOR : 0); const pidControllerFlags_e pidFlags = PID_DTERM_FROM_ERROR | (errorIsDecreasing ? PID_SHRINK_INTEGRATOR : 0);
// Input error in (deg*100), output pitch angle (deg*100) // Input error in (deg*100), output roll angle (deg*100)
float rollAdjustment = navPidApply2(&posControl.pids.fw_nav, posControl.actualState.yaw + navHeadingError, posControl.actualState.yaw, US2S(deltaMicros), float rollAdjustment = navPidApply2(&posControl.pids.fw_nav, posControl.actualState.yaw + navHeadingError, posControl.actualState.yaw, US2S(deltaMicros),
-DEGREES_TO_CENTIDEGREES(navConfig()->fw.max_bank_angle), -DEGREES_TO_CENTIDEGREES(navConfig()->fw.max_bank_angle),
DEGREES_TO_CENTIDEGREES(navConfig()->fw.max_bank_angle), DEGREES_TO_CENTIDEGREES(navConfig()->fw.max_bank_angle),