LCOV - code coverage report
Current view: top level - home/pbarker/rc/ardupilot/ArduPlane - RC_Channel_Plane.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 98 282 34.8 %
Date: 2026-09-09 11:02:08 Functions: 8 11 72.7 %

          Line data    Source code
       1             : #include "Plane.h"
       2             : 
       3             : #include "RC_Channel_Plane.h"
       4             : #include "qautotune.h"
       5             : 
       6             : // defining these two macros and including the RC_Channels_VarInfo
       7             : // header defines the parameter information common to all vehicle
       8             : // types
       9             : #define RC_CHANNELS_SUBCLASS RC_Channels_Plane
      10             : #define RC_CHANNEL_SUBCLASS RC_Channel_Plane
      11             : 
      12             : #include <RC_Channel/RC_Channels_VarInfo.h>
      13             : 
      14             : // note that this callback is not presently used on Plane:
      15      392073 : int8_t RC_Channels_Plane::flight_mode_channel_number() const
      16             : {
      17      392073 :     return plane.g.flight_mode_channel.get();
      18             : }
      19             : 
      20    32281030 : bool RC_Channels_Plane::in_rc_failsafe() const
      21             : {
      22    32281030 :     return (plane.rc_failsafe_active() || plane.failsafe.rc_failsafe);
      23             : }
      24             : 
      25    30412576 : bool RC_Channels_Plane::has_valid_input() const
      26             : {
      27    30412576 :     if (in_rc_failsafe()) {
      28       45006 :         return false;
      29             :     }
      30    30367570 :     if (plane.failsafe.throttle_counter != 0) {
      31        1379 :         return false;
      32             :     }
      33    30366191 :     return RC_Channels::has_valid_input();
      34             : }
      35             : 
      36     2764019 : RC_Channel * RC_Channels_Plane::get_arming_channel(void) const
      37             : {
      38     2764019 :     return plane.channel_rudder;
      39             : }
      40             : 
      41           9 : void RC_Channel_Plane::do_aux_function_change_mode(const Mode::Number number,
      42             :                                                    const AuxSwitchPos ch_flag)
      43             : {
      44           9 :     switch(ch_flag) {
      45           4 :     case AuxSwitchPos::HIGH: {
      46             :         // engage mode (if not possible we remain in current flight mode)
      47           4 :         plane.set_mode_by_number(number, ModeReason::AUX_FUNCTION);
      48           4 :         break;
      49             :     }
      50           5 :     default:
      51             :         // return to flight mode switch's flight mode if we are currently
      52             :         // in this mode
      53           5 :         if (plane.control_mode->mode_number() == number) {
      54           2 :             rc().reset_mode_switch();
      55             :         }
      56             :     }
      57           9 : }
      58             : 
      59             : #if HAL_QUADPLANE_ENABLED
      60           0 : void RC_Channel_Plane::do_aux_function_q_assist_state(AuxSwitchPos ch_flag)
      61             : {
      62           0 :     switch(ch_flag) {
      63           0 :         case AuxSwitchPos::HIGH:
      64           0 :             gcs().send_text(MAV_SEVERITY_INFO, "QAssist: Force enabled");
      65           0 :             plane.quadplane.assist.set_state(VTOL_Assist::STATE::FORCE_ENABLED);
      66           0 :             break;
      67             : 
      68           0 :         case AuxSwitchPos::MIDDLE:
      69           0 :             gcs().send_text(MAV_SEVERITY_INFO, "QAssist: Enabled");
      70           0 :             plane.quadplane.assist.set_state(VTOL_Assist::STATE::ASSIST_ENABLED);
      71           0 :             break;
      72             : 
      73           0 :         case AuxSwitchPos::LOW:
      74           0 :             gcs().send_text(MAV_SEVERITY_INFO, "QAssist: Disabled");
      75           0 :             plane.quadplane.assist.set_state(VTOL_Assist::STATE::ASSIST_DISABLED);
      76           0 :             break;
      77             :     }
      78           0 : }
      79             : #endif  // HAL_QUADPLANE_ENABLED
      80             : 
      81           0 : void RC_Channel_Plane::do_aux_function_crow_mode(AuxSwitchPos ch_flag)
      82             : {
      83           0 :         switch(ch_flag) {
      84           0 :         case AuxSwitchPos::HIGH:
      85           0 :             plane.crow_mode = Plane::CrowMode::CROW_DISABLED;
      86           0 :             gcs().send_text(MAV_SEVERITY_INFO, "Crow Flaps Disabled");
      87           0 :             break;
      88           0 :         case AuxSwitchPos::MIDDLE:
      89           0 :             gcs().send_text(MAV_SEVERITY_INFO, "Progressive Crow Flaps"); 
      90           0 :             plane.crow_mode = Plane::CrowMode::PROGRESSIVE;   
      91           0 :             break;
      92           0 :         case AuxSwitchPos::LOW:
      93           0 :             plane.crow_mode = Plane::CrowMode::NORMAL;
      94           0 :             gcs().send_text(MAV_SEVERITY_INFO, "Normal Crow Flaps");
      95           0 :             break;
      96             :         }    
      97           0 : }
      98             : 
      99             : #if HAL_SOARING_ENABLED
     100          17 : void RC_Channel_Plane::do_aux_function_soaring_3pos(AuxSwitchPos ch_flag)
     101             : {
     102          17 :     SoaringController::ActiveStatus desired_state = SoaringController::ActiveStatus::SOARING_DISABLED;
     103             : 
     104          17 :     switch (ch_flag) {
     105           8 :         case AuxSwitchPos::LOW:
     106           8 :             desired_state = SoaringController::ActiveStatus::SOARING_DISABLED;
     107           8 :             break;
     108           8 :         case AuxSwitchPos::MIDDLE:
     109           8 :             desired_state = SoaringController::ActiveStatus::MANUAL_MODE_CHANGE;
     110           8 :             break;
     111           1 :         case AuxSwitchPos::HIGH:
     112           1 :             desired_state = SoaringController::ActiveStatus::AUTO_MODE_CHANGE;
     113           1 :             break;
     114             :         }
     115             : 
     116          17 :     plane.g2.soaring_controller.set_pilot_desired_state(desired_state);
     117          17 : }
     118             : #endif
     119             : 
     120           0 : void RC_Channel_Plane::do_aux_function_flare(AuxSwitchPos ch_flag)
     121             : {
     122           0 :         switch(ch_flag) {
     123           0 :         case AuxSwitchPos::HIGH:
     124           0 :             plane.flare_mode = Plane::FlareMode::ENABLED_PITCH_TARGET;
     125           0 :             break;
     126           0 :         case AuxSwitchPos::MIDDLE:
     127           0 :             plane.flare_mode = Plane::FlareMode::ENABLED_NO_PITCH_TARGET;
     128           0 :             break;
     129           0 :         case AuxSwitchPos::LOW:
     130           0 :             plane.flare_mode = Plane::FlareMode::FLARE_DISABLED;
     131           0 :             break;
     132             :         }    
     133           0 : }
     134             : 
     135             : 
     136       11072 : void RC_Channel_Plane::init_aux_function(const RC_Channel::AUX_FUNC ch_option,
     137             :                                          const RC_Channel::AuxSwitchPos ch_flag)
     138             : {
     139       11072 :     switch(ch_option) {
     140             :     // the following functions do not need to be initialised:
     141           2 :     case AUX_FUNC::AUTO:
     142             :     case AUX_FUNC::CIRCLE:
     143             :     case AUX_FUNC::ACRO:
     144             :     case AUX_FUNC::TRAINING:
     145             :     case AUX_FUNC::FLAP:
     146             :     case AUX_FUNC::GUIDED:
     147             :     case AUX_FUNC::INVERTED:
     148             :     case AUX_FUNC::LOITER:
     149             :     case AUX_FUNC::MANUAL:
     150             :     case AUX_FUNC::RTL:
     151             :     case AUX_FUNC::TAKEOFF:
     152             :     case AUX_FUNC::FBWA:
     153             :     case AUX_FUNC::AIRBRAKE:
     154             : #if HAL_QUADPLANE_ENABLED
     155             :     case AUX_FUNC::QRTL:
     156             :     case AUX_FUNC::QSTABILIZE:
     157             : #endif
     158             :     case AUX_FUNC::FBWA_TAILDRAGGER:
     159             :     case AUX_FUNC::FWD_THR:
     160             :     case AUX_FUNC::LANDING_FLARE:
     161             : #if HAL_PARACHUTE_ENABLED
     162             :     case AUX_FUNC::PARACHUTE_RELEASE:
     163             : #endif
     164             :     case AUX_FUNC::MODE_SWITCH_RESET:
     165             :     case AUX_FUNC::CRUISE:
     166             : #if HAL_QUADPLANE_ENABLED
     167             :     case AUX_FUNC::ARMDISARM_AIRMODE:
     168             : #endif
     169             :     case AUX_FUNC::PLANE_AUTO_LANDING_ABORT:
     170             :     case AUX_FUNC::TRIM_TO_CURRENT_SERVO_RC:
     171             :     case AUX_FUNC::EMERGENCY_LANDING_EN:
     172             :     case AUX_FUNC::FW_AUTOTUNE:
     173             :     case AUX_FUNC::VFWD_THR_OVERRIDE:
     174             :     case AUX_FUNC::PRECISION_LOITER:
     175             : #if QAUTOTUNE_ENABLED
     176             :     case AUX_FUNC::AUTOTUNE_TEST_GAINS:
     177             : #endif
     178             : #if AP_QUICKTUNE_ENABLED
     179             :     case AUX_FUNC::QUICKTUNE:
     180             : #endif
     181             : #if MODE_AUTOLAND_ENABLED
     182             :     case AUX_FUNC::AUTOLAND:
     183             : #endif
     184             : #if AP_PLANE_SYSTEMID_ENABLED
     185             :     case AUX_FUNC::SYSTEMID:
     186             : #endif
     187           2 :         break;
     188          14 :     case AUX_FUNC::SOARING:
     189             : #if HAL_QUADPLANE_ENABLED
     190             :     case AUX_FUNC::Q_ASSIST:
     191             :     case AUX_FUNC::AIRMODE:
     192             :     case AUX_FUNC::WEATHER_VANE_ENABLE:
     193             : #endif
     194             : #if AP_AIRSPEED_AUTOCAL_ENABLE
     195             :     case AUX_FUNC::ARSPD_CALIBRATE:
     196             : #endif
     197             :     case AUX_FUNC::TER_DISABLE:
     198             :     case AUX_FUNC::CROW_SELECT:
     199             : #if AP_ICENGINE_ENABLED
     200             :     case AUX_FUNC::ICE_START_STOP:
     201             : #endif
     202          14 :         run_aux_function(ch_option, ch_flag, AuxFuncTrigger::Source::INIT, ch_in);
     203          14 :         break;
     204             : 
     205           0 :     case AUX_FUNC::REVERSE_THROTTLE:
     206           0 :         plane.have_reverse_throttle_rc_option = true;
     207             :         // setup input throttle as a range. This is needed as init_aux_function is called
     208             :         // after set_control_channels()
     209           0 :         if (plane.channel_throttle) {
     210           0 :             plane.channel_throttle->set_range(100);
     211             :         }
     212             :         // note that we don't call do_aux_function() here as we don't
     213             :         // want to startup with reverse thrust
     214           0 :         break;
     215             : 
     216       11056 :     default:
     217             :         // handle in parent class
     218       11056 :         RC_Channel::init_aux_function(ch_option, ch_flag);
     219       11056 :         break;
     220             :     }
     221       11072 : }
     222             : 
     223             : // do_aux_function - implement the function invoked by auxiliary switches
     224         207 : bool RC_Channel_Plane::do_aux_function(const AuxFuncTrigger &trigger)
     225             : {
     226         207 :     const AUX_FUNC &ch_option = trigger.func;
     227         207 :     const AuxSwitchPos &ch_flag = trigger.pos;
     228             : 
     229         207 :     switch(ch_option) {
     230           2 :     case AUX_FUNC::INVERTED:
     231           2 :         plane.inverted_flight = (ch_flag == AuxSwitchPos::HIGH);
     232           2 :         break;
     233             : 
     234           4 :     case AUX_FUNC::REVERSE_THROTTLE:
     235           4 :         plane.reversed_throttle = (ch_flag == AuxSwitchPos::HIGH);
     236           4 :         gcs().send_text(MAV_SEVERITY_INFO, "RevThrottle: %s", plane.reversed_throttle?"ENABLE":"DISABLE");
     237           4 :         break;
     238             : 
     239           0 :     case AUX_FUNC::AUTO:
     240           0 :         do_aux_function_change_mode(Mode::Number::AUTO, ch_flag);
     241           0 :         break;
     242             : 
     243           0 :     case AUX_FUNC::CIRCLE:
     244           0 :         do_aux_function_change_mode(Mode::Number::CIRCLE, ch_flag);
     245           0 :         break;
     246             : 
     247           0 :     case AUX_FUNC::ACRO:
     248           0 :         do_aux_function_change_mode(Mode::Number::ACRO, ch_flag);
     249           0 :         break;
     250             : 
     251           0 :     case AUX_FUNC::TRAINING:
     252           0 :         do_aux_function_change_mode(Mode::Number::TRAINING, ch_flag);
     253           0 :         break;
     254             :         
     255           0 :     case AUX_FUNC::LOITER:
     256           0 :         do_aux_function_change_mode(Mode::Number::LOITER, ch_flag);
     257           0 :         break;        
     258             : 
     259           5 :     case AUX_FUNC::GUIDED:
     260           5 :         do_aux_function_change_mode(Mode::Number::GUIDED, ch_flag);
     261           5 :         break;
     262             : 
     263           0 :     case AUX_FUNC::MANUAL:
     264           0 :         do_aux_function_change_mode(Mode::Number::MANUAL, ch_flag);
     265           0 :         break;
     266             : 
     267           4 :     case AUX_FUNC::RTL:
     268           4 :         do_aux_function_change_mode(Mode::Number::RTL, ch_flag);
     269           4 :         break;
     270             : 
     271           0 :     case AUX_FUNC::TAKEOFF:
     272           0 :         do_aux_function_change_mode(Mode::Number::TAKEOFF, ch_flag);
     273           0 :         break;
     274             : 
     275           0 :     case AUX_FUNC::FBWA:
     276           0 :         do_aux_function_change_mode(Mode::Number::FLY_BY_WIRE_A, ch_flag);
     277           0 :         break;
     278             : 
     279             : #if HAL_QUADPLANE_ENABLED
     280           0 :     case AUX_FUNC::QRTL:
     281           0 :         do_aux_function_change_mode(Mode::Number::QRTL, ch_flag);
     282           0 :         break;
     283             : 
     284           0 :     case AUX_FUNC::QSTABILIZE:
     285           0 :         do_aux_function_change_mode(Mode::Number::QSTABILIZE, ch_flag);
     286           0 :         break;
     287             : 
     288           0 :     case AUX_FUNC::VFWD_THR_OVERRIDE: {
     289           0 :         const bool enable = (ch_flag == AuxSwitchPos::HIGH);
     290           0 :         if (enable != plane.quadplane.vfwd_enable_active) {
     291           0 :             plane.quadplane.vfwd_enable_active = enable;
     292           0 :             gcs().send_text(MAV_SEVERITY_INFO, "QFwdThr: %s", enable?"ON":"OFF");
     293             :         }
     294           0 :         break;
     295             :     }
     296             : #endif
     297             : 
     298             : #if HAL_SOARING_ENABLED
     299          17 :     case AUX_FUNC::SOARING:
     300          17 :         do_aux_function_soaring_3pos(ch_flag);
     301          17 :         break;
     302             : #endif
     303             : 
     304           5 :     case AUX_FUNC::FLAP:
     305             :     case AUX_FUNC::FBWA_TAILDRAGGER:
     306             :     case AUX_FUNC::AIRBRAKE:
     307           5 :         break; // input labels, nothing to do
     308             : 
     309             : #if HAL_QUADPLANE_ENABLED
     310           0 :     case AUX_FUNC::Q_ASSIST:
     311           0 :         do_aux_function_q_assist_state(ch_flag);
     312           0 :         break;
     313             : #endif
     314             : 
     315           0 :     case AUX_FUNC::FWD_THR:
     316           0 :         break; // VTOL forward throttle input label, nothing to do
     317             : 
     318           0 :     case AUX_FUNC::TER_DISABLE:
     319           0 :             switch (ch_flag) {
     320           0 :             case AuxSwitchPos::HIGH:
     321           0 :                 plane.non_auto_terrain_disable = true;
     322           0 :                 if (plane.control_mode->allows_terrain_disable()) {
     323           0 :                     plane.set_target_altitude_current();
     324             :                 }
     325           0 :                 break;
     326           0 :             case AuxSwitchPos::MIDDLE:
     327           0 :                 break;
     328           0 :             case AuxSwitchPos::LOW:
     329           0 :                 plane.non_auto_terrain_disable = false;
     330           0 :                 if (plane.control_mode->allows_terrain_disable()) {
     331           0 :                     plane.set_target_altitude_current();
     332             :                 }
     333           0 :                 break;
     334             :             }
     335           0 :             gcs().send_text(MAV_SEVERITY_INFO, "NON AUTO TERRN: %s", plane.non_auto_terrain_disable?"OFF":"ON");
     336           0 :         break;
     337             : 
     338           0 :     case AUX_FUNC::CROW_SELECT:
     339           0 :         do_aux_function_crow_mode(ch_flag);
     340           0 :         break;
     341             : 
     342             : #if HAL_QUADPLANE_ENABLED
     343           6 :     case AUX_FUNC::AIRMODE:
     344           6 :         switch (ch_flag) {
     345           3 :         case AuxSwitchPos::HIGH:
     346           3 :             plane.quadplane.air_mode = AirMode::ON;
     347           3 :             plane.quadplane.throttle_wait = false;
     348           3 :             break;
     349           1 :         case AuxSwitchPos::MIDDLE:
     350           1 :             break;
     351           2 :         case AuxSwitchPos::LOW:
     352           2 :             plane.quadplane.air_mode = AirMode::OFF;
     353           2 :             break;
     354             :         }
     355           6 :         break;
     356             : #endif
     357             : 
     358             : #if AP_AIRSPEED_AUTOCAL_ENABLE
     359           0 :     case AUX_FUNC::ARSPD_CALIBRATE:
     360           0 :         switch (ch_flag) {
     361           0 :         case AuxSwitchPos::HIGH:
     362           0 :             plane.airspeed.set_calibration_enabled(true);
     363           0 :             break;
     364           0 :         case AuxSwitchPos::MIDDLE:
     365           0 :             break;
     366           0 :         case AuxSwitchPos::LOW:
     367           0 :             plane.airspeed.set_calibration_enabled(false);
     368           0 :             break;
     369             :         }
     370           0 :         break;
     371             : #endif
     372             : 
     373           0 :     case AUX_FUNC::LANDING_FLARE:
     374           0 :         do_aux_function_flare(ch_flag);
     375           0 :         break;
     376             : 
     377             : #if HAL_PARACHUTE_ENABLED
     378           0 :     case AUX_FUNC::PARACHUTE_RELEASE:
     379           0 :         if (ch_flag == AuxSwitchPos::HIGH) {
     380           0 :             plane.parachute_manual_release();
     381             :         }
     382           0 :         break;
     383             : #endif
     384             : 
     385           2 :     case AUX_FUNC::MODE_SWITCH_RESET:
     386           2 :         rc().reset_mode_switch();
     387           2 :         break;
     388             : 
     389           0 :     case AUX_FUNC::CRUISE:
     390           0 :         do_aux_function_change_mode(Mode::Number::CRUISE, ch_flag);
     391           0 :         break;
     392             : 
     393             : #if HAL_QUADPLANE_ENABLED
     394          32 :     case AUX_FUNC::ARMDISARM_AIRMODE:
     395          32 :         RC_Channel::do_aux_function_armdisarm(ch_flag);
     396          32 :         if (plane.arming.is_armed()) {
     397          16 :             plane.quadplane.air_mode = AirMode::ON;
     398          16 :             plane.quadplane.throttle_wait = false;
     399             :         }
     400          32 :         break;
     401             : 
     402           0 :     case AUX_FUNC::WEATHER_VANE_ENABLE: {
     403           0 :         if (plane.quadplane.weathervane != nullptr) {
     404           0 :             switch (ch_flag) {
     405           0 :                 case AuxSwitchPos::HIGH:
     406           0 :                     plane.quadplane.weathervane->allow_weathervaning(true);
     407           0 :                     break;
     408           0 :                 case AuxSwitchPos::MIDDLE:
     409             :                     // nothing
     410           0 :                     break;
     411           0 :                 case AuxSwitchPos::LOW:
     412           0 :                     plane.quadplane.weathervane->allow_weathervaning(false);
     413           0 :                     break;
     414             :             }
     415             :         }
     416           0 :         break;
     417             :     }
     418             : #endif
     419             : 
     420           0 :     case AUX_FUNC::PLANE_AUTO_LANDING_ABORT:
     421           0 :         switch(ch_flag) {
     422           0 :         case AuxSwitchPos::HIGH:
     423           0 :             IGNORE_RETURN(plane.trigger_land_abort(0));
     424           0 :             break;
     425           0 :         case AuxSwitchPos::MIDDLE:
     426             :         case AuxSwitchPos::LOW:
     427           0 :             break;
     428             :         }
     429           0 :         break;
     430             : 
     431           0 :     case AUX_FUNC::TRIM_TO_CURRENT_SERVO_RC:
     432           0 :         if (ch_flag == AuxSwitchPos::HIGH) {
     433           0 :             plane.trim_radio();
     434             :         }
     435           0 :         break;
     436             : 
     437           0 :     case AUX_FUNC::EMERGENCY_LANDING_EN:
     438           0 :         switch (ch_flag) {
     439           0 :         case AuxSwitchPos::HIGH:
     440           0 :             plane.emergency_landing = true;
     441           0 :             break;
     442           0 :         case AuxSwitchPos::MIDDLE:
     443           0 :             break;
     444           0 :         case AuxSwitchPos::LOW:
     445           0 :             plane.emergency_landing = false;
     446           0 :             break;
     447             :         }
     448           0 :         break;
     449             : 
     450           0 :     case AUX_FUNC::FW_AUTOTUNE:
     451           0 :         if (ch_flag == AuxSwitchPos::HIGH && plane.control_mode->mode_allows_autotuning()) {
     452           0 :            plane.autotune_enable(true);
     453           0 :         } else if (ch_flag == AuxSwitchPos::HIGH) {
     454           0 :            GCS_SEND_TEXT(MAV_SEVERITY_WARNING, "Autotuning not allowed in this mode!");
     455             :         } else {
     456           0 :            plane.autotune_enable(false); 
     457             :         }
     458           0 :         break;
     459             : 
     460           0 :     case AUX_FUNC::PRECISION_LOITER:
     461             :         // handled by lua scripting, just ignore here
     462           0 :         break;
     463             : 
     464             : #if QAUTOTUNE_ENABLED
     465           0 :     case AUX_FUNC::AUTOTUNE_TEST_GAINS:
     466           0 :         plane.quadplane.qautotune.do_aux_function(ch_flag);
     467           0 :         break;
     468             : #endif
     469             : 
     470             : #if AP_QUICKTUNE_ENABLED
     471           5 :     case AUX_FUNC::QUICKTUNE:
     472           5 :         plane.quicktune.update_switch_pos(ch_flag);
     473           5 :         break;
     474             : #endif
     475             : 
     476             : #if AP_PLANE_SYSTEMID_ENABLED
     477           0 :     case AUX_FUNC::SYSTEMID:
     478           0 :         if (ch_flag == AuxSwitchPos::HIGH) {
     479           0 :             plane.g2.systemid.start();
     480           0 :         } else if (ch_flag == AuxSwitchPos::LOW) {
     481           0 :             plane.g2.systemid.stop();
     482             :         }
     483           0 :         break;
     484             : #endif
     485             : 
     486             : #if AP_ICENGINE_ENABLED
     487          28 :     case AUX_FUNC::ICE_START_STOP:
     488          28 :         plane.g2.ice_control.do_aux_function(trigger);
     489          28 :         break;
     490             : #endif
     491             : 
     492             : #if MODE_AUTOLAND_ENABLED
     493           0 :     case AUX_FUNC::AUTOLAND:
     494           0 :         do_aux_function_change_mode(Mode::Number::AUTOLAND, ch_flag);
     495           0 :         break;
     496             : 
     497             : #endif
     498             : 
     499          97 :     default:
     500          97 :         return RC_Channel::do_aux_function(trigger);
     501             :     }
     502             : 
     503         110 :     return true;
     504             : }

Generated by: LCOV version 1.14