LCOV - code coverage report
Current view: top level - home/pbarker/rc/ardupilot/ArduSub - Attitude.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 45 71 63.4 %
Date: 2026-09-09 11:02:08 Functions: 6 9 66.7 %

          Line data    Source code
       1             : #include "Sub.h"
       2             : 
       3             : // get_pilot_desired_angle - transform pilot's roll or pitch input into a desired lean angle
       4             : // returns desired angle in centi-degrees
       5      709827 : void Sub::get_pilot_desired_lean_angles(float roll_in, float pitch_in, float &roll_out, float &pitch_out, float angle_max)
       6             : {
       7             :     // sanity check angle max parameter
       8      709827 :     const float angle_max_cd = attitude_control.lean_angle_max_cd();
       9             : 
      10             :     // limit max lean angle
      11      709827 :     angle_max = constrain_float(angle_max, 1000, angle_max_cd);
      12             : 
      13             :     // scale roll_in, pitch_in to ATC_ANGLE_MAX parameter range
      14      709827 :     float scaler = angle_max_cd/(float)ROLL_PITCH_INPUT_MAX;
      15      709827 :     roll_in *= scaler;
      16      709827 :     pitch_in *= scaler;
      17             : 
      18             :     // do circular limit
      19      709827 :     float total_in = norm(pitch_in, roll_in);
      20      709827 :     if (total_in > angle_max) {
      21           0 :         float ratio = angle_max / total_in;
      22           0 :         roll_in *= ratio;
      23           0 :         pitch_in *= ratio;
      24             :     }
      25             : 
      26             :     // do lateral tilt to euler roll conversion
      27      709827 :     roll_in = (18000/M_PI) * atanf(cosf(pitch_in*(M_PI/18000))*tanf(roll_in*(M_PI/18000)));
      28             : 
      29             :     // return
      30      709827 :     roll_out = roll_in;
      31      709827 :     pitch_out = pitch_in;
      32      709827 : }
      33             : 
      34             : // get_pilot_desired_heading - transform pilot's yaw input into a
      35             : // desired yaw rate
      36             : // returns desired yaw rate in centi-degrees per second
      37      867550 : float Sub::get_pilot_desired_yaw_rate(int16_t stick_angle) const
      38             : {
      39             :     // convert pilot input to the desired yaw rate
      40      867550 :     return stick_angle * g.acro_yaw_p;
      41             : }
      42             : 
      43             : // check for ekf yaw reset and adjust target heading
      44     2180683 : void Sub::check_ekf_yaw_reset()
      45             : {
      46     2180683 :     const uint16_t new_ahrs_yaw_reset_count = ahrs.get_yaw_reset_count();
      47     2180683 :     if (new_ahrs_yaw_reset_count != ahrs_yaw_reset_count) {
      48         353 :         attitude_control.inertial_frame_reset();
      49         353 :         ahrs_yaw_reset_count = new_ahrs_yaw_reset_count;
      50             :     }
      51     2180683 : }
      52             : 
      53             : /*************************************************************
      54             :  * yaw controllers
      55             :  *************************************************************/
      56             : 
      57             : // get_roi_yaw - returns heading towards location held in roi_WP
      58             : // should be called at 100hz
      59           0 : float Sub::get_roi_yaw()
      60             : {
      61             :     static uint8_t roi_yaw_counter = 0;     // used to reduce update rate to 100hz
      62             : 
      63           0 :     roi_yaw_counter++;
      64           0 :     if (roi_yaw_counter >= 4) {
      65           0 :         roi_yaw_counter = 0;
      66           0 :         yaw_look_at_WP_bearing = get_bearing_cd((pos_control.get_pos_estimate_NED_m().xy() * 100.0f).tofloat(), roi_WP_neu_cm.xy());
      67             :     }
      68             : 
      69           0 :     return yaw_look_at_WP_bearing;
      70             : }
      71             : 
      72           0 : float Sub::get_look_ahead_yaw()
      73             : {
      74           0 :     Vector3f vel = (pos_control.get_vel_estimate_NED_ms() * 100.0f).tofloat();
      75           0 :     vel.z = -vel.z;
      76           0 :     const float speed_sq = vel.xy().length_squared();
      77             :     // Commanded Yaw to automatically look ahead.
      78           0 :     if (position_ok() && (speed_sq > (YAW_LOOK_AHEAD_MIN_SPEED * YAW_LOOK_AHEAD_MIN_SPEED))) {
      79           0 :         yaw_look_ahead_bearing = degrees(atan2f(vel.y,vel.x))*100.0f;
      80             :     }
      81           0 :     return yaw_look_ahead_bearing;
      82             : }
      83             : 
      84             : /*************************************************************
      85             :  *  throttle control
      86             :  ****************************************************************/
      87             : 
      88             : // get_pilot_desired_climb_rate - transform pilot's throttle input to climb rate in cm/s
      89             : // without any deadzone at the bottom
      90      364062 : float Sub::get_pilot_desired_climb_rate(float throttle_control)
      91             : {
      92             :     // throttle failsafe check
      93      364062 :     if (failsafe.pilot_input) {
      94           0 :         return 0.0f;
      95             :     }
      96             : 
      97             :     // ensure a reasonable throttle value
      98      364062 :     throttle_control = constrain_float(throttle_control,0.0f,1000.0f);
      99             : 
     100             :     // ensure a reasonable deadzone
     101      364062 :     g.throttle_deadzone.set(constrain_int16(g.throttle_deadzone, 0, 400));
     102             : 
     103      364062 :     float mid_stick = channel_throttle->get_control_mid();
     104      364062 :     float deadband_top = mid_stick + g.throttle_deadzone * gain;
     105      364062 :     float deadband_bottom = mid_stick - g.throttle_deadzone * gain;
     106             : 
     107             :     // check throttle is above, below or in the deadband
     108      364062 :     if (throttle_control < deadband_bottom) {
     109             :         // below the deadband
     110       98651 :         return get_pilot_speed_dn() * (throttle_control-deadband_bottom) / deadband_bottom;
     111      265411 :     } else if (throttle_control > deadband_top) {
     112             :         // above the deadband
     113       20491 :         return g.pilot_speed_up * (throttle_control-deadband_top) / (1000.0f-deadband_top);
     114             :     } else {
     115             :         // must be in the deadband
     116      244920 :         return 0.0f;
     117             :     }
     118             : }
     119             : 
     120             : // behavior is similar to Sub::get_pilot_desired_climb_rate
     121      160058 : float Sub::get_pilot_desired_horizontal_rate(RC_Channel *channel) const
     122             : {
     123      160058 :     if (failsafe.pilot_input) {
     124           0 :         return 0;
     125             :     }
     126             : 
     127             :     // forward and lateral sticks have center trim, unlike throttle
     128      160058 :     auto control = channel->norm_input();
     129             : 
     130             :     // normalize deadzone
     131      160058 :     auto dz = (float)g.throttle_deadzone * 2.0f / (float)(channel->get_radio_max() - channel->get_radio_min());
     132      160058 :     auto deadband_top = dz * gain;
     133      160058 :     auto deadband_bottom = -dz * gain;
     134             : 
     135      160058 :     if (control < deadband_bottom) {
     136             :         // below the deadband
     137           0 :         return (float)g.pilot_speed * (control - deadband_bottom);
     138      160058 :     } else if (control > deadband_top) {
     139             :         // above the deadband
     140       31108 :         return (float)g.pilot_speed * (control - deadband_top);
     141             :     } else {
     142             :         // must be in the deadband
     143      128950 :         return 0;
     144             :     }
     145             : }
     146             : 
     147             : // rotate vector from vehicle's perspective to North-East frame
     148           0 : void Sub::rotate_body_frame_to_NE(float &x, float &y)
     149             : {
     150           0 :     float ne_x = x*ahrs.cos_yaw() - y*ahrs.sin_yaw();
     151           0 :     float ne_y = x*ahrs.sin_yaw() + y*ahrs.cos_yaw();
     152           0 :     x = ne_x;
     153           0 :     y = ne_y;
     154           0 : }
     155             : 
     156             : // It will return the PILOT_SPEED_DN value if non zero, otherwise if zero it returns the PILOT_SPEED_UP value.
     157      753145 : uint16_t Sub::get_pilot_speed_dn() const
     158             : {
     159      753145 :     if (g.pilot_speed_dn == 0) {
     160      753145 :         return abs(g.pilot_speed_up);
     161             :     }
     162           0 :     return abs(g.pilot_speed_dn);
     163             : }

Generated by: LCOV version 1.14