LCOV - code coverage report
Current view: top level - AC_InputManager - AC_InputManager_Heli.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 44 50 88.0 %
Date: 2026-09-09 11:02:08 Functions: 2 2 100.0 %

          Line data    Source code
       1             : #include "AC_InputManager_Heli.h"
       2             : #include <AP_Math/AP_Math.h>
       3             : #include <AP_HAL/AP_HAL.h>
       4             : #include <GCS_MAVLink/GCS.h>
       5             : 
       6             : extern const AP_HAL::HAL& hal;
       7             : 
       8             : const AP_Param::GroupInfo AC_InputManager_Heli::var_info[] = {
       9             : 
      10             :     // parameters from parent vehicle
      11             :     AP_NESTEDGROUPINFO(AC_InputManager, 0),
      12             : 
      13             :     // Indicies 1-4 (STAB_COL_1 thru STAB_COL_4) have been replaced. 
      14             : 
      15             :     // @Param: ACRO_COL_EXP
      16             :     // @DisplayName: Acro Mode Collective Expo
      17             :     // @Description: Used to soften collective pitch inputs near center point in Acro mode.
      18             :     // @Values: 0:Disabled,0.1:Very Low,0.2:Low,0.3:Medium,0.4:High,0.5:Very High
      19             :     // @Range: -0.5 0.95
      20             :     // @User: Advanced
      21             :     AP_GROUPINFO("ACRO_COL_EXP",    5, AC_InputManager_Heli, _acro_col_expo, 0),
      22             : 
      23             :     // @Param: STB_COL_1
      24             :     // @DisplayName: Stabilize Collective Low
      25             :     // @Description: Helicopter's minimum collective pitch setting at zero collective stick input in Stabilize mode.  Set this as a percent of collective range given by H_COL_MAX minus H_COL_MIN.
      26             :     // @Range: 0 100
      27             :     // @Units: %
      28             :     // @Increment: 1
      29             :     // @User: Standard
      30             :     AP_GROUPINFO("STB_COL_1",    6, AC_InputManager_Heli, _heli_stab_col_min, AC_ATTITUDE_HELI_STAB_COLLECTIVE_MIN_DEFAULT),
      31             : 
      32             :     // @Param: STB_COL_2
      33             :     // @DisplayName: Stabilize Collective Mid-Low
      34             :     // @Description: Helicopter's collective pitch setting at mid-low (40%) collective stick input in Stabilize mode. Set this as a percent of collective range given by H_COL_MAX minus H_COL_MIN.
      35             :     // @Range: 0 100
      36             :     // @Units: %
      37             :     // @Increment: 1
      38             :     // @User: Standard
      39             :     AP_GROUPINFO("STB_COL_2",    7, AC_InputManager_Heli, _heli_stab_col_low, AC_ATTITUDE_HELI_STAB_COLLECTIVE_LOW_DEFAULT),
      40             : 
      41             :     // @Param: STB_COL_3
      42             :     // @DisplayName: Stabilize Collective Mid-High
      43             :     // @Description: Helicopter's collective pitch setting at mid-high (60%) collective stick input in Stabilize mode. Set this as a percent of collective range given by H_COL_MAX minus H_COL_MIN.
      44             :     // @Range: 0 100
      45             :     // @Units: %
      46             :     // @Increment: 1
      47             :     // @User: Standard
      48             :     AP_GROUPINFO("STB_COL_3",    8, AC_InputManager_Heli, _heli_stab_col_high, AC_ATTITUDE_HELI_STAB_COLLECTIVE_HIGH_DEFAULT),
      49             : 
      50             :     // @Param: STB_COL_4
      51             :     // @DisplayName: Stabilize Collective High
      52             :     // @Description: Helicopter's maximum collective pitch setting at full collective stick input in Stabilize mode. Set this as a percent of collective range given by H_COL_MAX minus H_COL_MIN.
      53             :     // @Range: 0 100
      54             :     // @Units: %
      55             :     // @Increment: 1
      56             :     // @User: Standard
      57             :     AP_GROUPINFO("STB_COL_4",    9, AC_InputManager_Heli, _heli_stab_col_max, AC_ATTITUDE_HELI_STAB_COLLECTIVE_MAX_DEFAULT),
      58             : 
      59             :     AP_GROUPEND
      60             : };
      61             : 
      62             : // get_pilot_desired_collective - rescale's pilot collective pitch input in Stabilize and Acro modes
      63     1059136 : float AC_InputManager_Heli::get_pilot_desired_collective(int16_t control_in)
      64             : {
      65             :     float slope_low, slope_high, slope_range, slope_run, scalar;
      66             :     float stab_col_out, acro_col_out;
      67             : 
      68             :     // calculate stabilize collective value which scales pilot input to reduced collective range
      69             :     // code implements a 3-segment curve with knee points at 40% and 60% throttle input
      70     1059136 :     if (control_in < 400){  // control_in ranges from 0 to 1000
      71      917091 :         slope_low = _heli_stab_col_min * 0.01f;
      72      917091 :         slope_high = _heli_stab_col_low * 0.01f;
      73      917091 :         slope_range = 0.4f;
      74      917091 :         slope_run = control_in * 0.001f;
      75      142045 :     } else if(control_in <600){  // control_in ranges from 0 to 1000
      76       11001 :         slope_low = _heli_stab_col_low * 0.01f;
      77       11001 :         slope_high = _heli_stab_col_high * 0.01f;
      78       11001 :         slope_range = 0.2f;
      79       11001 :         slope_run = (control_in - 400) * 0.001f;  // control_in ranges from 0 to 1000
      80             :     } else {
      81      131044 :         slope_low = _heli_stab_col_high * 0.01f;
      82      131044 :         slope_high = _heli_stab_col_max * 0.01f;
      83      131044 :         slope_range = 0.4f;
      84      131044 :         slope_run = (control_in - 600) * 0.001f;  // control_in ranges from 0 to 1000
      85             :     }    
      86             : 
      87     1059136 :     scalar = (slope_high - slope_low)/slope_range;
      88     1059136 :     stab_col_out = slope_low + slope_run * scalar;
      89     1059136 :     stab_col_out = constrain_float(stab_col_out, 0.0f, 1.0f);
      90             : 
      91             :     //
      92             :     // calculate expo-scaled acro collective
      93             :     // range check expo
      94     1059136 :     if (_acro_col_expo > 1.0f) {
      95           0 :         _acro_col_expo.set(1.0f);
      96             :     }
      97             : 
      98     1059136 :     if (_acro_col_expo <= 0.0f) {
      99           0 :         acro_col_out = control_in * 0.001f;  // control_in ranges from 0 to 1000
     100             :     } else {
     101             :         // expo variables
     102             :         float col_in, col_in3, col_out;
     103     1059136 :         col_in = (float)(control_in-500)/500.0f;  // control_in ranges from 0 to 1000
     104     1059136 :         col_in3 = col_in*col_in*col_in;
     105     1059136 :         col_out = (_acro_col_expo * col_in3) + ((1.0f-_acro_col_expo)*col_in);
     106     1059136 :         acro_col_out = 0.5f + col_out*0.5f;
     107             :     }
     108     1059136 :     acro_col_out = constrain_float(acro_col_out, 0.0f, 1.0f);
     109             : 
     110             :     // ramp function
     111     1059136 :     if (is_positive(_ramp)) {
     112        2964 :         float dt = 1/(float)_loop_rate;
     113             :         // factor 2 to transition over a time span of 0.5s
     114        2964 :         _ramp -= 2*dt;
     115        2964 :         _ramp = constrain_float(_ramp, 0.0f, 1.0f);
     116             :     }
     117             : 
     118             :     //set Stabilize or Acro collective output
     119             :     float new_flightmode_col_output;
     120     1059136 :     if (_im_flags_heli.use_stab_col) {
     121     1057936 :         new_flightmode_col_output = stab_col_out;
     122             :     } else {
     123        1200 :         new_flightmode_col_output = acro_col_out;
     124             :     }
     125             : 
     126             :     // scale collective output smoothly between previous and current mode output
     127             :     float collective_out;
     128     1059136 :     collective_out = new_flightmode_col_output * (1.0 - _ramp) + _ramp * _old_flightmode_col_output;
     129     1059136 :     collective_out = constrain_float(collective_out, 0.0f, 1.0f);
     130             : 
     131     1059136 :     return collective_out;
     132             : }
     133             : 
     134             : // parameter_check - check if input manager specific parameters are sensible
     135        2149 : bool AC_InputManager_Heli::parameter_check(char* fail_msg, uint8_t fail_msg_len) const
     136             : {
     137             : 
     138             :     const struct StabCheck {
     139             :         const char *name;
     140             :         int16_t value;
     141        2149 :     } stab_checks[] = {
     142             :         {"IM_STB_COL_1", _heli_stab_col_min },
     143             :         {"IM_STB_COL_2", _heli_stab_col_low },
     144             :         {"IM_STB_COL_3", _heli_stab_col_high },
     145             :         {"IM_STB_COL_4", _heli_stab_col_max },
     146        2149 :     };
     147             : 
     148             :     // check values are within valid range
     149       10745 :     for (uint8_t i=0; i<ARRAY_SIZE(stab_checks); i++) {
     150        8596 :         const StabCheck check = stab_checks[i];
     151        8596 :         if ((check.value < 0) || (check.value > 100)){
     152           0 :             hal.util->snprintf(fail_msg, fail_msg_len, "%s out of range", check.name);
     153           0 :             return false;
     154             :         }
     155             :     }
     156             :     // check values are in correct order
     157        8596 :     for (uint8_t i=1; i<ARRAY_SIZE(stab_checks); i++) {
     158        6447 :         if ((stab_checks[i-1].value >= stab_checks[i].value)){
     159           0 :             hal.util->snprintf(fail_msg, fail_msg_len, "%s must be < %s", stab_checks[i-1].name, stab_checks[i].name);
     160           0 :             return false;
     161             :         }
     162             :     }
     163             :     // all other cases parameters are OK
     164        2149 :     return true;
     165             : }
     166             : 

Generated by: LCOV version 1.14