* control_hybrid.pde - init and run calls for hybrid flight mode
* hybrid tries to improve upon regular loiter by mixing the pilot input with the loiter controller
*/
#define SPEED_0 10
#define NAV_HYBRID 1
#define NAV_NONE 0
#define LOITER_STAB_TIMER 300 // ST-JD : Must be higher than BRAKE_LOIT_MIX_TIMER (twice is a good deal) set it from 100 to 500, the number of centiseconds between loiter engage and getting wind_comp (once loiter stabilized)
#define BRAKE_LOIT_MIX_TIMER 150 // ST-JD : Must be lower than LOITER_STAB_TIMER set it from 100 to 200, the number of centiseconds brake and loiter commands are mixed to make a smooth transition.
#define LOITER_MAN_MIX_TIMER 50 // ST-JD : set it from 100 to 200, the number of centiseconds loiter and manual commands are mixed to make a smooth transition.
@ -14,15 +14,19 @@
@@ -14,15 +14,19 @@
#define THROTTLE_HYBRID_AH 1
#define THROTTLE_HYBRID_BK 3
//#define MX1HYBRID // Alt Hold when throttle in deadband, manual otherwise
#define MX2HYBRID // Alt Hold when throttle from 0 to deadband_high, manual otherwise (above deadband)
//#define MXHYBRID // switch Alt Hold <-> Throttle Assist
//define AHHYBRID // only Alt Hold
//define TAHYBRID // only Throttle Assist
//define JDHYBRID // stick at center=vertical brake and alt-hold when vertical speed is near zero. Stick out from deadband (+70/-70) manual throttle (throttle assist for both!)
// mission state enumeration
enum hybrid_rp_mode {
HYBRID_PILOT_OVERRIDE=0,
HYBRID_BRAKE=1,
HYBRID_LOITER=2
};
static struct {
hybrid_rp_mode roll_mode : 2; // roll mode: pilot override, brake or loiter
hybrid_rp_mode pitch_mode : 2; // pitch mode: pilot override, brake or loiter
uint8_t loiter_engaged : 1; // 1 if loiter target has been set and loiter controller is running
// roll stick input detected set roll mode to pilot override
hybrid.roll_mode = HYBRID_PILOT_OVERRIDE; // Set stab roll mode
} else {
// stick released from stab and copter horizontal (at wind comp) => transition mode
if ((hybrid.roll_mode == HYBRID_PILOT_OVERRIDE) && (abs(brake_roll) < 2*wp_nav._brake_rate)) {
hybrid.roll_mode = HYBRID_BRAKE; // Set brake roll mode
brake_roll = 0; // this avoid false brake_timeout computing
timeout_roll = 600; // seconds*0.01 - time allowed for the braking to complete, updated at half-braking
timeout_roll_updated = false; // Allow the timeout to be updated only once
brake_max_roll = 0; // used to detect half braking
}else{ // manage brake-to-loiter transition
}else{ // manage brake-to-loiter transition
// brake timeout
if (timeout_roll>0) timeout_roll--;
if (timeout_roll > 0) {
timeout_roll--;
}
// Changed loiter engage : not once speed_0 reached but after a little delay that let the copter stabilize if it remains some rate. (maybe compare omega.x/y rather)
if ((fabs(vel_right)<SPEED_0) && (timeout_roll>50)) timeout_roll = 50; // let 0.5s between brake reaches speed_0 and loiter engage
if ((hybrid_mode_roll == 2) && (timeout_roll==0)){ //stick released and transition finished (speed 0) or brake timeout => loiter mode
hybrid_mode_roll = 3; // Set loiter roll mode
if ((fabs(vel_right) < SPEED_0) && (timeout_roll>50)) {
timeout_roll = 50; // let 0.5s between brake reaches speed_0 and loiter engage
}
if ((hybrid.roll_mode == HYBRID_BRAKE) && (timeout_roll==0)){ //stick released and transition finished (speed 0) or brake timeout => loiter mode
hybrid.roll_mode = HYBRID_LOITER; // Set loiter roll mode
}
}
}
//get pitch stick input and update new pitch mode
if (abs(target_pitch) > LOITER_DEADBAND){ //stick input detected => direct to stab mode
hybrid_mode_pitch = 1; // Set stab pitch mode
// get pitch stick input
if (target_pitch != 0) {
// pitch stick input detected set pitch mode to pilot override
hybrid.pitch_mode = HYBRID_PILOT_OVERRIDE; // Set stab pitch mode
}else{
if((hybrid_mode_pitch == 1) && (abs(brake_pitch) < 2*wp_nav._brake_rate)){ // stick released from stab and copter horizontal (at wind_comp) => transition mode
hybrid_mode_pitch = 2; // Set brake pitch mode
if((hybrid.pitch_mode == HYBRID_PILOT_OVERRIDE) && (abs(brake_pitch) < 2*wp_nav._brake_rate)){ // stick released from stab and copter horizontal (at wind_comp) => transition mode
hybrid.pitch_mode = HYBRID_BRAKE; // Set brake pitch mode
brake_pitch = 0; // this avoid false brake_timeout computing
timeout_pitch=600; // seconds*0.01 - time allowed for the braking to complete, updated at half-braking
timeout_pitch_updated = false; // Allow the timeout to be updated only once
// Changed loiter engage : not once speed_0 reached but after a little delay that let the copter stabilize if it remains some rate. (maybe compare omega.x/y rather)
if((fabs(vel_fw)<SPEED_0) && (timeout_pitch>50)) timeout_pitch = 50; // let 0.5s between brake reaches speed_0 and loiter engage
if ((hybrid_mode_pitch == 2) && (timeout_pitch==0)) {
hybrid_mode_pitch = 3; // Set loiter pitch mode
if ((fabs(vel_fw)<SPEED_0) && (timeout_pitch>50)) {
timeout_pitch = 50; // let 0.5s between brake reaches speed_0 and loiter engage
}
if ((hybrid.pitch_mode == HYBRID_BRAKE) && (timeout_pitch == 0)) {
hybrid.pitch_mode = HYBRID_LOITER; // Set loiter pitch mode
}
}
}
// manual roll/pitch with smooth decrease filter
// roll
if (hybrid_mode_roll == 1){
if (((long)brake_roll*(long)target_roll>=0)&&(abs(target_roll)<STICK_RELEASE_SMOOTH_ANGLE)){ //Smooth decrease only when we want to stop, not if we have to quickly change direction
if (brake_roll>0){ // we use brake_roll to save mem usage and also because it will be natural transition with brake mode.
brake_roll=max(brake_roll,target_roll); // use the max value if we increase and because we could have a smoother manual decrease than this computed value
if (hybrid.roll_mode == HYBRID_PILOT_OVERRIDE) {
if (((long)brake_roll*(long)target_roll>=0) && (abs(target_roll)<STICK_RELEASE_SMOOTH_ANGLE)) {
// Smooth decrease only when we want to stop, not if we have to quickly change direction
if (brake_roll > 0){ // we use brake_roll to save mem usage and also because it will be natural transition with brake mode.
if (((long)brake_pitch*(long)target_pitch>=0)&&(abs(target_pitch)<STICK_RELEASE_SMOOTH_ANGLE)){ //Smooth decrease only when we want to stop, not if we have to quickly change direction
if (brake_pitch>0){ // we use brake_pitch to save mem usage and also because it will be natural transition with brake mode.
if (abs(brake_roll)>brake_max_roll) { // detect half braking and update timeout
brake_max_roll=abs(brake_roll);
if (abs(brake_roll) > brake_max_roll) { // detect half braking and update timeout
brake_max_roll=abs(brake_roll);
} else if (!timeout_roll_updated){
timeout_roll = 1+(uint16_t)(15L*(long)(abs(brake_roll))/(10L*(long)wp_nav._brake_rate)); // the 1.2 (12/10) factor has to be tuned in flight, here it means 120% of the "normal" time.
timeout_roll_updated = true;
}
}
// braking update: pitch
if (hybrid_mode_pitch>=2) { // Pitch: allow braking update to run also during loiter
if (hybrid.pitch_mode>=HYBRID_BRAKE) { // Pitch: allow braking update to run also during loiter
if (vel_fw>=0) { // positive pitch = go backward, negative pitch = go forward