LCOV - code coverage report
Current view: top level - home/pbarker/rc/ardupilot/ArduCopter - mode_acro_heli.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 22 43 51.2 %
Date: 2026-09-09 11:02:08 Functions: 2 3 66.7 %

          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

Generated by: LCOV version 1.14