Line data Source code
1 : #include "Copter.h" 2 : 3 : #if MODE_ACRO_ENABLED 4 : 5 : #if FRAME_CONFIG == HELI_FRAME 6 : /* 7 : * Init and run calls for acro flight mode for trad heli 8 : */ 9 : 10 : // heli_acro_init - initialise acro controller 11 1 : bool ModeAcro_Heli::init(bool ignore_checks) 12 : { 13 : // set stab collective false to use full collective pitch range 14 1 : copter.input_manager.set_use_stab_col(false); 15 : 16 : // always successfully enter acro 17 1 : return true; 18 : } 19 : 20 : // heli_acro_run - runs the acro controller 21 : // should be called at 100hz or more 22 1200 : void ModeAcro_Heli::run() 23 : { 24 : float target_roll_rads, target_pitch_rads, target_yaw_rads; 25 : float pilot_throttle_scaled; 26 : 27 : // Tradheli should not reset roll, pitch, yaw targets when motors are not runup while flying, because 28 : // we may be in autorotation flight. This is so that the servos move in a realistic fashion while disarmed 29 : // for operational checks. Also, unlike multicopters we do not set throttle (i.e. collective pitch) to zero 30 : // so the swash servos move. 31 : 32 : // Request throttle unlimited. The setter enforces safety constraints: 33 : // - Disarmed: held at SHUT_DOWN until armed 34 : // - Armed without interlock: limited to GROUND_IDLE (swash can move, rotor stopped) 35 : // - Armed with interlock: THROTTLE_UNLIMITED granted 36 1200 : motors->set_desired_spool_state(AP_Motors::DesiredSpoolState::THROTTLE_UNLIMITED); 37 : 38 1200 : switch (motors->get_spool_state()) { 39 798 : case AP_Motors::SpoolState::SHUT_DOWN: 40 : // Motors Stopped 41 798 : attitude_control->reset_target_and_rate(false); 42 798 : attitude_control->reset_rate_controller_I_terms(); 43 798 : break; 44 402 : case AP_Motors::SpoolState::GROUND_IDLE: 45 : // If aircraft is landed, set target heading to current and reset the integrator 46 : // Otherwise motors could be at ground idle for practice autorotation 47 402 : if ((motors->init_targets_on_arming() && motors->using_leaky_integrator()) || (copter.ap.land_complete && !motors->using_leaky_integrator())) { 48 402 : attitude_control->reset_target_and_rate(false); 49 402 : attitude_control->reset_rate_controller_I_terms_smoothly(); 50 : } 51 402 : break; 52 0 : case AP_Motors::SpoolState::THROTTLE_UNLIMITED: 53 0 : if (copter.ap.land_complete && !motors->using_leaky_integrator()) { 54 0 : attitude_control->reset_rate_controller_I_terms_smoothly(); 55 : } 56 0 : break; 57 0 : case AP_Motors::SpoolState::SPOOLING_UP: 58 : case AP_Motors::SpoolState::SPOOLING_DOWN: 59 : // do nothing 60 0 : break; 61 : } 62 : 63 : // convert the input to the desired body frame rate 64 1200 : get_pilot_desired_rates_rads(target_roll_rads, target_pitch_rads, target_yaw_rads); 65 : // only mimic flybar response when trainer mode is disabled 66 1200 : if ((Trainer)g.acro_trainer.get() == Trainer::OFF) { 67 : // while landed always leak off target attitude to current attitude 68 0 : if (copter.ap.land_complete) { 69 0 : virtual_flybar(target_roll_rads, target_pitch_rads, target_yaw_rads, 3.0f, 3.0f); 70 : // while flying use acro balance parameters for leak rate 71 : } else { 72 0 : virtual_flybar(target_roll_rads, target_pitch_rads, target_yaw_rads, g.acro_balance_pitch, g.acro_balance_roll); 73 : } 74 : } 75 : 76 : // run attitude controller 77 1200 : if (g2.acro_options.get() & uint8_t(AcroOptions::RATE_LOOP_ONLY)) { 78 0 : attitude_control->input_rate_bf_roll_pitch_yaw_2_rads(target_roll_rads, target_pitch_rads, target_yaw_rads); 79 : } else { 80 1200 : attitude_control->input_rate_bf_roll_pitch_yaw_rads(target_roll_rads, target_pitch_rads, target_yaw_rads); 81 : } 82 : 83 : // get pilot's desired throttle 84 1200 : pilot_throttle_scaled = copter.input_manager.get_pilot_desired_collective(channel_throttle->get_control_in()); 85 : 86 : // output pilot's throttle without angle boost 87 1200 : attitude_control->set_throttle_out(pilot_throttle_scaled, false, g.throttle_filt); 88 1200 : } 89 : 90 : 91 : // virtual_flybar - acts like a flybar by leaking target atttitude back to current attitude 92 0 : void ModeAcro_Heli::virtual_flybar( float &roll_out_rads, float &pitch_out_rads, float &yaw_out_rads, float pitch_leak, float roll_leak) 93 : { 94 0 : Vector3f rate_ef_level_rads, rate_bf_level_rads; 95 : 96 : // get attitude targets 97 0 : const Vector3f& att_target_rad = attitude_control->get_att_target_euler_rad(); 98 : 99 : // Calculate earth frame rate command for roll leak to current attitude 100 0 : rate_ef_level_rads.x = -wrap_PI(att_target_rad.x - ahrs.get_roll_rad()) * roll_leak; 101 : 102 : // Calculate earth frame rate command for pitch leak to current attitude 103 0 : rate_ef_level_rads.y = -wrap_PI(att_target_rad.y - ahrs.get_pitch_rad()) * pitch_leak; 104 : 105 : // Calculate earth frame rate command for yaw 106 0 : rate_ef_level_rads.z = 0; 107 : 108 : // convert earth-frame leak rates to body-frame leak rates 109 0 : attitude_control->euler_derivative_to_body(attitude_control->get_attitude_target_quat(), rate_ef_level_rads, rate_bf_level_rads); 110 : 111 : // combine earth frame rate corrections with rate requests 112 0 : roll_out_rads += rate_bf_level_rads.x; 113 0 : pitch_out_rads += rate_bf_level_rads.y; 114 0 : yaw_out_rads += rate_bf_level_rads.z; 115 : 116 0 : } 117 : #endif //HELI_FRAME 118 : #endif //MODE_ACRO_ENABLED