1
0
Fork 0
mirror of https://github.com/betaflight/betaflight.git synced 2025-07-23 16:25:31 +03:00

Launch Control

Adds a race start assistance system that allows the pilot to pitch forward and then release the sticks with the quad holding position for the race start.
This commit is contained in:
Bruce Luckcuck 2018-10-09 19:25:59 -04:00
parent 8609346f21
commit e4dc93b128
14 changed files with 377 additions and 17 deletions

View file

@ -101,7 +101,8 @@ enum {
enum {
ARMING_DELAYED_DISARMED = 0,
ARMING_DELAYED_NORMAL = 1,
ARMING_DELAYED_CRASHFLIP = 2
ARMING_DELAYED_CRASHFLIP = 2,
ARMING_DELAYED_LAUNCH_CONTROL = 3
};
#define GYRO_WATCHDOG_DELAY 80 // delay for gyro sync
@ -145,6 +146,20 @@ static timeUs_t runawayTakeoffTriggerUs = 0;
static bool runawayTakeoffTemporarilyDisabled = false;
#endif
#ifdef USE_LAUNCH_CONTROL
static launchControlState_e launchControlState = LAUNCH_CONTROL_DISABLED;
const char * const osdLaunchControlModeNames[] = {
"NORMAL",
"PITCHONLY",
"FULL"
};
const char * const osdLaunchControlTriggerModeNames[] = {
"MULTIPLE",
"SINGLE"
};
#endif
PG_REGISTER_WITH_RESET_TEMPLATE(throttleCorrectionConfig_t, throttleCorrectionConfig, PG_THROTTLE_CORRECTION_CONFIG, 0);
PG_RESET_TEMPLATE(throttleCorrectionConfig_t, throttleCorrectionConfig,
@ -173,6 +188,23 @@ static bool isCalibrating(void)
return (!accIsCalibrationComplete() && sensors(SENSOR_ACC)) || (!isGyroCalibrationComplete());
}
#ifdef USE_LAUNCH_CONTROL
bool canUseLaunchControl(void)
{
if (!STATE(FIXED_WING)
&& !isUsingSticksForArming() // require switch arming for safety
&& IS_RC_MODE_ACTIVE(BOXLAUNCHCONTROL)
&& (!featureIsEnabled(FEATURE_MOTOR_STOP) || airmodeIsEnabled()) // can't use when motors are stopped
&& !featureIsEnabled(FEATURE_3D) // pitch control is not 3D aware
&& (flightModeFlags == 0)) { // don't want to use unless in acro mode
return true;
} else {
return false;
}
}
#endif
void resetArmingDisabled(void)
{
lastArmingDisabledReason = 0;
@ -346,6 +378,10 @@ void tryArm(void)
if (tryingToArm == ARMING_DELAYED_DISARMED) {
if (isModeActivationConditionPresent(BOXFLIPOVERAFTERCRASH) && IS_RC_MODE_ACTIVE(BOXFLIPOVERAFTERCRASH)) {
tryingToArm = ARMING_DELAYED_CRASHFLIP;
#ifdef USE_LAUNCH_CONTROL
} else if (canUseLaunchControl()) {
tryingToArm = ARMING_DELAYED_LAUNCH_CONTROL;
#endif
} else {
tryingToArm = ARMING_DELAYED_NORMAL;
}
@ -370,6 +406,14 @@ void tryArm(void)
}
#endif
#ifdef USE_LAUNCH_CONTROL
if (!flipOverAfterCrashMode && (canUseLaunchControl() || (tryingToArm == ARMING_DELAYED_LAUNCH_CONTROL))) {
if (launchControlState == LAUNCH_CONTROL_DISABLED) { // only activate if it hasn't already been triggered
launchControlState = LAUNCH_CONTROL_ACTIVE;
}
}
#endif
ENABLE_ARMING_FLAG(ARMED);
ENABLE_ARMING_FLAG(WAS_EVER_ARMED);
@ -577,8 +621,10 @@ bool processRx(timeUs_t currentTimeUs)
const throttleStatus_e throttleStatus = calculateThrottleStatus();
const uint8_t throttlePercent = calculateThrottlePercent();
const bool launchControlActive = isLaunchControlActive();
if (airmodeIsEnabled() && ARMING_FLAG(ARMED)) {
if (airmodeIsEnabled() && ARMING_FLAG(ARMED) && !launchControlActive) {
if (throttlePercent >= rxConfig()->airModeActivateThreshold) {
airmodeIsActivated = true; // Prevent iterm from being reset
}
@ -588,7 +634,7 @@ bool processRx(timeUs_t currentTimeUs)
/* In airmode iterm should be prevented to grow when Low thottle and Roll + Pitch Centered.
This is needed to prevent iterm winding on the ground, but keep full stabilisation on 0 throttle while in air */
if (throttleStatus == THROTTLE_LOW && !airmodeIsActivated) {
if (throttleStatus == THROTTLE_LOW && !airmodeIsActivated && !launchControlActive) {
pidResetIterm();
if (currentPidProfile->pidAtMinThrottle)
pidStabilisationState(PID_STABILISATION_ON);
@ -666,6 +712,29 @@ bool processRx(timeUs_t currentTimeUs)
}
#endif
#ifdef USE_LAUNCH_CONTROL
if (ARMING_FLAG(ARMED)) {
if (launchControlActive && (throttlePercent > currentPidProfile->launchControlThrottlePct)) {
// throttle limit trigger reached, launch triggered
// reset the iterms as they may be at high values from holding the launch position
launchControlState = LAUNCH_CONTROL_TRIGGERED;
pidResetIterm();
}
} else {
if (launchControlState == LAUNCH_CONTROL_TRIGGERED) {
// If trigger mode is MULTIPLE then reset the state when disarmed
// and the mode switch is turned off.
// For trigger mode SINGLE we never reset the state and only a single
// launch is allowed until a reboot.
if ((currentPidProfile->launchControlTriggerMode == LAUNCH_CONTROL_TRIGGER_MODE_MULTIPLE) && !IS_RC_MODE_ACTIVE(BOXLAUNCHCONTROL)) {
launchControlState = LAUNCH_CONTROL_DISABLED;
}
} else {
launchControlState = LAUNCH_CONTROL_DISABLED;
}
}
#endif
// When armed and motors aren't spinning, do beeps and then disarm
// board after delay so users without buzzer won't lose fingers.
// mixTable constrains motor commands, so checking throttleStatus is enough
@ -1044,3 +1113,12 @@ void resetTryingToArm()
{
tryingToArm = ARMING_DELAYED_DISARMED;
}
bool isLaunchControlActive(void)
{
#ifdef USE_LAUNCH_CONTROL
return launchControlState == LAUNCH_CONTROL_ACTIVE;
#else
return false;
#endif
}