LCOV - code coverage report
Current view: top level - home/pbarker/rc/ardupilot/ArduCopter - mode_drift.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 40 51 78.4 %
Date: 2026-09-09 11:02:08 Functions: 3 3 100.0 %

          Line data    Source code
       1             : #include "Copter.h"
       2             : 
       3             : #if MODE_DRIFT_ENABLED
       4             : 
       5             : /*
       6             :  * Drift flight mode — meters/second and radians version
       7             :  */
       8             : //   Converted: 8 [cd/(cm/s)] * (π/18000 rad/cd) * (100 cm/m) = 0.13962634 rad/(m/s)
       9             : #ifndef DRIFT_SPEEDGAIN_RAD
      10             :  # define DRIFT_SPEEDGAIN_RAD 0.13962634f
      11             : #endif
      12             : #ifdef DRIFT_SPEEDGAIN
      13             :     #error please convert to radians and use DRIFT_SPEEDGAIN_RAD
      14             : #endif
      15             : 
      16             : #ifndef DRIFT_SPEEDLIMIT_MS
      17             :  # define DRIFT_SPEEDLIMIT_MS 5.60f
      18             : #endif
      19             : #ifdef DRIFT_SPEEDLIMIT
      20             :     #error please convert to meters per second and use DRIFT_SPEEDLIMIT_MS
      21             : #endif
      22             : 
      23             : #ifndef DRIFT_VEL_FORWARD_MIN_MS
      24             :  # define DRIFT_VEL_FORWARD_MIN_MS 20.0f
      25             : #endif
      26             : #ifdef DRIFT_VEL_FORWARD_MIN
      27             :     #error please convert to meters per second and use DRIFT_VEL_FORWARD_MIN_MS
      28             : #endif
      29             : 
      30             : #ifndef DRIFT_THR_ASSIST_GAIN_MS
      31             :  # define DRIFT_THR_ASSIST_GAIN_MS 0.18f
      32             : #endif
      33             : #ifdef DRIFT_THR_ASSIST_GAIN
      34             :     #error please convert to meters per second and use DRIFT_THR_ASSIST_GAIN_MS
      35             : #endif
      36             : 
      37             : #ifndef DRIFT_THR_ASSIST_MAX
      38             :  # define DRIFT_THR_ASSIST_MAX  0.3f      // maximum assistance throttle assist will provide
      39             : #endif
      40             : 
      41             : #ifndef DRIFT_THR_MIN
      42             :  # define DRIFT_THR_MIN         0.213f
      43             : #endif
      44             : #ifndef DRIFT_THR_MAX
      45             :  # define DRIFT_THR_MAX         0.787f
      46             : #endif
      47             : 
      48             : // drift_init - initialise drift controller
      49           2 : bool ModeDrift::init(bool ignore_checks)
      50             : {
      51           2 :     return true;
      52             : }
      53             : 
      54             : // drift_run - runs the drift controller
      55             : // should be called at 100hz or more
      56       37839 : void ModeDrift::run()
      57             : {
      58             :     static float braker = 0.0f;
      59             :     static float roll_input_rad = 0.0f;
      60             : 
      61             :     // convert pilot input to lean angles (already radians)
      62             :     float target_roll_rad, target_pitch_rad;
      63       37839 :     get_pilot_desired_lean_angles_rad(target_roll_rad, target_pitch_rad, attitude_control->lean_angle_max_rad(), attitude_control->get_althold_lean_angle_max_rad());
      64             : 
      65             :     // Grab inertial velocity (already m/s)
      66       37839 :     const Vector3f& vel_ned_ms = pos_control->get_vel_estimate_NED_ms();
      67             : 
      68             :     // rotate roll, pitch input from north facing to vehicle's perspective
      69             :     // body-frame components in m/s
      70       37839 :     float vel_right_ms   =  vel_ned_ms.y * ahrs.cos_yaw() - vel_ned_ms.x * ahrs.sin_yaw(); // body roll axis
      71       37839 :     float vel_forward_ms =  vel_ned_ms.y * ahrs.sin_yaw() + vel_ned_ms.x * ahrs.cos_yaw(); // body pitch axis
      72             : 
      73             :     // gain scheduling for yaw
      74       37839 :     const float vel_forward_2_ms = MIN(fabsf(vel_forward_ms), DRIFT_VEL_FORWARD_MIN_MS);
      75             : 
      76             :     // yaw-rate schedule:
      77       37839 :     const float yaw_rate_max_rads = radians(g2.command_model_acro_y.get_rate());
      78       37839 :     const float target_yaw_rate_rads = (target_roll_rad / radians(45.0f)) * yaw_rate_max_rads * (1.0f - (vel_forward_2_ms / 50.0f));
      79             : 
      80             :     // Constrain body velocities
      81       37839 :     vel_right_ms   = constrain_float(vel_right_ms,   -DRIFT_SPEEDLIMIT_MS, DRIFT_SPEEDLIMIT_MS);
      82       37839 :     vel_forward_ms = constrain_float(vel_forward_ms, -DRIFT_SPEEDLIMIT_MS, DRIFT_SPEEDLIMIT_MS);
      83             : 
      84             :     // roll_input from yaw stick (convert centidegrees -> radians before LP)
      85             :     // (channel_yaw->get_control_in() returns centidegrees)
      86       37839 :     const float yaw_stick_rad = cd_to_rad((float)channel_yaw->get_control_in());
      87       37839 :     roll_input_rad = roll_input_rad * 0.96f + yaw_stick_rad * 0.04f;
      88             : 
      89             :     // convert user input into desired roll velocity term (m/s equivalent)
      90       37839 :     float roll_vel_error_ms = vel_right_ms - (roll_input_rad / DRIFT_SPEEDGAIN_RAD);
      91             : 
      92             :     // roll velocity is fed into roll angle to minimize slip
      93       37839 :     target_roll_rad = roll_vel_error_ms * -DRIFT_SPEEDGAIN_RAD;
      94             : 
      95             :     // constrain to ±45 deg
      96       37839 :     target_roll_rad = constrain_float(target_roll_rad, -radians(45.0f), radians(45.0f));
      97             : 
      98             :     // If we let go of sticks, bring us to a stop
      99       37839 :     if (is_zero(target_pitch_rad)) {
     100             :         // Clamp to the same coupling constant, now in rad/(m/s)
     101       37839 :         braker += 0.03f;
     102       37839 :         braker = MIN(braker, DRIFT_SPEEDGAIN_RAD);
     103       37839 :         target_pitch_rad = vel_forward_ms * braker;
     104             :     } else {
     105           0 :         braker = 0.0f;
     106             :     }
     107             : 
     108             :     // Determine desired spool state based on pilot throttle input.
     109             :     // The setter enforces that disarmed aircraft are held at SHUT_DOWN until armed.
     110       37839 :     if (copter.ap.throttle_zero) {
     111       37839 :         motors->set_desired_spool_state(AP_Motors::DesiredSpoolState::GROUND_IDLE);
     112             :     } else {
     113           0 :         motors->set_desired_spool_state(AP_Motors::DesiredSpoolState::THROTTLE_UNLIMITED);
     114             :     }
     115             : 
     116       37839 :     switch (motors->get_spool_state()) {
     117       37041 :     case AP_Motors::SpoolState::SHUT_DOWN:
     118       37041 :         attitude_control->reset_yaw_target_and_rate(false);
     119       37041 :         attitude_control->reset_rate_controller_I_terms();
     120       37041 :         break;
     121             : 
     122         798 :     case AP_Motors::SpoolState::GROUND_IDLE:
     123         798 :         attitude_control->reset_yaw_target_and_rate();
     124         798 :         attitude_control->reset_rate_controller_I_terms_smoothly();
     125         798 :         break;
     126             : 
     127           0 :     case AP_Motors::SpoolState::THROTTLE_UNLIMITED:
     128           0 :         if (!motors->limit.throttle_lower) {
     129           0 :             set_land_complete(false);
     130             :         }
     131           0 :         break;
     132             : 
     133           0 :     case AP_Motors::SpoolState::SPOOLING_UP:
     134             :     case AP_Motors::SpoolState::SPOOLING_DOWN:
     135           0 :         break;
     136             :     }
     137             : 
     138             :     // call attitude controller (already expects radians)
     139       37839 :     attitude_control->input_euler_angle_roll_pitch_euler_rate_yaw_rad(
     140             :         target_roll_rad, target_pitch_rad, target_yaw_rate_rads);
     141             : 
     142             :     // output pilot's throttle with angle boost (velz now m/s)
     143       37839 :     const float assisted_throttle = get_throttle_assist(vel_ned_ms.z, get_pilot_desired_throttle());
     144       37839 :     attitude_control->set_throttle_out(assisted_throttle, true, g.throttle_filt);
     145       37839 : }
     146             : 
     147             : // get_throttle_assist - return throttle output (range 0 ~ 1) based on pilot input and D-axis velocity (positive down)
     148       37839 : float ModeDrift::get_throttle_assist(float vel_d_ms, float pilot_throttle_scaled)
     149             : {
     150             :     // throttle assist - adjusts throttle to slow the vehicle's vertical velocity
     151             :     //      Only active when pilot's throttle is between 0.213 ~ 0.787
     152             :     //      Assistance is strongest at mid, drops linearly to no assistance at 0.213 and 0.787
     153       37839 :     float thr_assist = 0.0f;
     154       37839 :     if (pilot_throttle_scaled > DRIFT_THR_MIN && pilot_throttle_scaled < DRIFT_THR_MAX) {
     155             :         // calculate throttle assist gain
     156           0 :         thr_assist = 1.2f - ((float)fabsf(pilot_throttle_scaled - 0.5f) / 0.24f);
     157           0 :         thr_assist = constrain_float(thr_assist, 0.0f, 1.0f) * DRIFT_THR_ASSIST_GAIN_MS * vel_d_ms;
     158             : 
     159             :         // ensure throttle assist never adjusts the throttle by more than 0.3 (≈300 pwm)
     160           0 :         thr_assist = constrain_float(thr_assist, -DRIFT_THR_ASSIST_MAX, DRIFT_THR_ASSIST_MAX);
     161             :     }
     162             : 
     163       37839 :     return constrain_float(pilot_throttle_scaled + thr_assist, 0.0f, 1.0f);
     164             : }
     165             : #endif

Generated by: LCOV version 1.14