LCOV - code coverage report
Current view: top level - AC_AttitudeControl - AC_AttitudeControl.h (source / functions) Hit Total Coverage
Test: lcov.info Lines: 64 91 70.3 %
Date: 2026-09-09 11:02:08 Functions: 50 76 65.8 %

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : /// @file    AC_AttitudeControl.h
       4             : /// @brief   ArduCopter attitude control library
       5             : 
       6             : #include <AP_Common/AP_Common.h>
       7             : #include <AP_Param/AP_Param.h>
       8             : #include <AP_Math/AP_Math.h>
       9             : #include <AP_AHRS/AP_AHRS_View.h>
      10             : #include <AP_Motors/AP_Motors.h>
      11             : #include <AC_PID/AC_PID.h>
      12             : #include <AC_PID/AC_P.h>
      13             : #include <AP_BoardConfig/AP_BoardConfig.h>
      14             : 
      15             : #define AC_ATTITUDE_CONTROL_ANGLE_P                     4.5f             // default angle P gain for roll, pitch and yaw
      16             : 
      17             : #define AC_ATTITUDE_ACCEL_RP_CONTROLLER_MIN_RADSS       radians(40.0f)   // minimum body-frame acceleration limit for the stability controller (for roll and pitch axis)
      18             : #define AC_ATTITUDE_ACCEL_RP_CONTROLLER_MAX_RADSS       radians(720.0f)  // maximum body-frame acceleration limit for the stability controller (for roll and pitch axis)
      19             : #define AC_ATTITUDE_ACCEL_Y_CONTROLLER_MIN_RADSS        radians(10.0f)   // minimum body-frame acceleration limit for the stability controller (for yaw axis)
      20             : #define AC_ATTITUDE_ACCEL_Y_CONTROLLER_MAX_RADSS        radians(120.0f)  // maximum body-frame acceleration limit for the stability controller (for yaw axis)
      21             : #define AC_ATTITUDE_CONTROL_RATE_WPY_MAX_DEFAULT        60.0f     // default yaw slew rate in deg/s
      22             : #define AC_ATTITUDE_CONTROL_ACCEL_RP_MAX_DEFAULT_DEGSS  1100.0f   // default maximum acceleration for roll/pitch axis in deg/s/s
      23             : #define AC_ATTITUDE_CONTROL_ACCEL_Y_MAX_DEFAULT_DEGSS   270.0f    // default maximum acceleration for yaw axis in deg/s/s
      24             : 
      25             : #define AC_ATTITUDE_RATE_RP_CONTROLLER_OUT_MAX          1.0f    // body-frame rate controller maximum output (for roll-pitch axis)
      26             : #define AC_ATTITUDE_RATE_YAW_CONTROLLER_OUT_MAX         1.0f    // body-frame rate controller maximum output (for yaw axis)
      27             : #define AC_ATTITUDE_RATE_RELAX_TC                       0.16f   // This is used to decay the rate I term to 5% in half a second.
      28             : 
      29             : #define AC_ATTITUDE_THRUST_ERROR_ANGLE_RAD              radians(30.0f) // Thrust angle error above which yaw corrections are limited
      30             : #define AC_ATTITUDE_YAW_MAX_ERROR_ANGLE_RAD             radians(45.0f) // Thrust angle error above which yaw corrections are limited
      31             : 
      32             : #define AC_ATTITUDE_CONTROL_RATE_BF_FF_DEFAULT          1       // body-frame rate feedforward enabled by default
      33             : 
      34             : #define AC_ATTITUDE_CONTROL_ANGLE_LIMIT_TC_DEFAULT      1.0f    // Time constant used to limit lean angle so that vehicle does not lose altitude
      35             : #define AC_ATTITUDE_CONTROL_ANGLE_LIMIT_THROTTLE_MAX    0.8f    // Max throttle used to limit lean angle so that vehicle does not lose altitude
      36             : 
      37             : #define AC_ATTITUDE_CONTROL_MIN_DEFAULT                 0.1f    // minimum throttle mix default
      38             : #define AC_ATTITUDE_CONTROL_MAN_DEFAULT                 0.1f    // manual throttle mix default
      39             : #define AC_ATTITUDE_CONTROL_MAX_DEFAULT                 0.5f    // maximum throttle mix default
      40             : #define AC_ATTITUDE_CONTROL_MIN_LIMIT                   0.5f    // min throttle mix upper limit
      41             : #define AC_ATTITUDE_CONTROL_MAN_LIMIT                   4.0f    // man throttle mix upper limit
      42             : #define AC_ATTITUDE_CONTROL_MAX                         5.0f    // maximum throttle mix default
      43             : 
      44             : #define AC_ATTITUDE_CONTROL_THR_MIX_DEFAULT             0.5f  // ratio controlling the max throttle output during competing requests of low throttle from the pilot (or autopilot) and higher throttle for attitude control.  Higher favours Attitude over pilot input
      45             : #define AC_ATTITUDE_CONTROL_THR_G_BOOST_THRESH          1.0f  // default angle-p/pd throttle boost threshold
      46             : 
      47             : class AC_AttitudeControl {
      48             : public:
      49        1285 :     AC_AttitudeControl(AP_AHRS_View &ahrs,
      50        1285 :                        AP_Motors& motors) :
      51        1285 :         _p_angle_roll(AC_ATTITUDE_CONTROL_ANGLE_P),
      52        1285 :         _p_angle_pitch(AC_ATTITUDE_CONTROL_ANGLE_P),
      53        1285 :         _p_angle_yaw(AC_ATTITUDE_CONTROL_ANGLE_P),
      54        1285 :         _angle_boost(0),
      55        1285 :         _use_sqrt_controller(true),
      56        1285 :         _throttle_rpy_mix_desired(AC_ATTITUDE_CONTROL_THR_MIX_DEFAULT),
      57        1285 :         _throttle_rpy_mix(AC_ATTITUDE_CONTROL_THR_MIX_DEFAULT),
      58        1285 :         _ahrs(ahrs),
      59        2570 :         _motors(motors)
      60             :         {
      61        1285 :             _singleton = this;
      62        1285 :             AP_Param::setup_object_defaults(this, var_info);
      63        1285 :         }
      64             : 
      65       29402 :     static AC_AttitudeControl *get_singleton(void) {
      66       29402 :         return _singleton;
      67             :     }
      68             : 
      69             :     // Empty destructor to suppress compiler warning
      70          14 :     virtual ~AC_AttitudeControl() {}
      71             : 
      72             :     // Sets the internal controller timestep (in seconds).
      73             :     // This is the elapsed time since the last controller update and is used in rate and smoothing calculations.
      74    35255076 :     void set_dt_s(float dt_s) { _dt_s = dt_s; }
      75             : 
      76             :     // Returns the internal controller timestep (in seconds).
      77     4579903 :     float get_dt_s() const { return _dt_s; }
      78             : 
      79             :     // pid accessors
      80      408932 :     AC_P& get_angle_roll_p() { return _p_angle_roll; }
      81      408924 :     AC_P& get_angle_pitch_p() { return _p_angle_pitch; }
      82      103640 :     AC_P& get_angle_yaw_p() { return _p_angle_yaw; }
      83             :     virtual AC_PID& get_rate_roll_pid() = 0;
      84             :     virtual AC_PID& get_rate_pitch_pid() = 0;
      85             :     virtual AC_PID& get_rate_yaw_pid() = 0;
      86             :     virtual const AC_PID& get_rate_roll_pid() const = 0;
      87             :     virtual const AC_PID& get_rate_pitch_pid() const = 0;
      88             :     virtual const AC_PID& get_rate_yaw_pid() const = 0;
      89             : 
      90             :     // get the roll acceleration limit in radians/s/s
      91   104140968 :     float get_accel_roll_max_radss() const { return radians(_accel_roll_max_degss); }
      92             : 
      93             :     // Sets the roll acceleration limit in radians/s/s
      94         131 :     void set_accel_roll_max_radss(float accel_roll_max_radss) { _accel_roll_max_degss.set(degrees(accel_roll_max_radss)); }
      95             : 
      96             :     // Sets and saves the roll acceleration limit in radians/s/s
      97           3 :     void save_accel_roll_max_radss(float accel_roll_max_radss) { _accel_roll_max_degss.set_and_save(degrees(accel_roll_max_radss)); }
      98             : 
      99             :     // get the pitch acceleration limit in radians/s/s
     100   104084383 :     float get_accel_pitch_max_radss() const { return radians(_accel_pitch_max_degss); }
     101             : 
     102             :     // Sets the pitch acceleration limit in radians/s/s
     103         130 :     void set_accel_pitch_max_radss(float accel_pitch_max_radss) { _accel_pitch_max_degss.set(degrees(accel_pitch_max_radss)); }
     104             : 
     105             :     // Sets and saves the pitch acceleration limit in radians/s/s
     106           3 :     void save_accel_pitch_max_radss(float accel_pitch_max_radss) { _accel_pitch_max_degss.set_and_save(degrees(accel_pitch_max_radss)); }
     107             : 
     108             :     // get the yaw acceleration limit in radians/s/s
     109   130850216 :     float get_accel_yaw_max_radss() const { return radians(_accel_yaw_max_degss); }
     110             : 
     111             :     // Sets the yaw acceleration limit in radians/s/s
     112         137 :     void set_accel_yaw_max_radss(float accel_yaw_max_radss) { _accel_yaw_max_degss.set(degrees(accel_yaw_max_radss)); }
     113             : 
     114             :     // Sets and saves the yaw acceleration limit in radians/s/s
     115           3 :     void save_accel_yaw_max_radss(float accel_yaw_max_radss) { _accel_yaw_max_degss.set_and_save(degrees(accel_yaw_max_radss)); }
     116             : 
     117             :     // get the roll angular velocity limit in radians/s
     118     1492408 :     float get_ang_vel_roll_max_rads() const { return radians(_ang_vel_roll_max_degs); }
     119             : 
     120             :     // set the roll angular velocity limit in radians/s
     121         119 :     void set_ang_vel_roll_max_rads(float vel_roll_max_rads) { _ang_vel_roll_max_degs.set(degrees(vel_roll_max_rads)); }
     122             : 
     123             :     // get the pitch angular velocity limit in radians/s
     124     1492404 :     float get_ang_vel_pitch_max_rads() const { return radians(_ang_vel_pitch_max_degs); }
     125             : 
     126             :     // set the pitch angular velocity limit in radians/s
     127         118 :     void set_ang_vel_pitch_max_rads(float vel_pitch_max_rads) { _ang_vel_pitch_max_degs.set(degrees(vel_pitch_max_rads)); }
     128             : 
     129             :     // get the yaw angular velocity limit in radians/s
     130         219 :     float get_ang_vel_yaw_max_rads() const { return radians(_ang_vel_yaw_max_degs); }
     131             : 
     132             :     // set the yaw angular velocity limit in radians/s
     133         123 :     void set_ang_vel_yaw_max_rads(float vel_yaw_max_rads) { _ang_vel_yaw_max_degs.set(degrees(vel_yaw_max_rads)); }
     134             : 
     135             :     // get the slew yaw rate limit in radians/s
     136             :     float get_slew_yaw_max_rads() const;
     137             : 
     138             :     // get the rate control input smoothing time constant
     139       15182 :     float get_input_tc() const { return _input_tc; }
     140             : 
     141             :     // set the rate control input smoothing time constant
     142           0 :     void set_input_tc(float input_tc) { _input_tc.set(constrain_float(input_tc, 0.0f, 1.0f)); }
     143             : 
     144             :     // rate loop visible functions
     145             :     // Ensure attitude controller have zero errors to relax rate controller output
     146             :     void relax_attitude_controllers();
     147             : 
     148             :     // Used by child class AC_AttitudeControl_TS to change behaviour for tailsitter quadplanes
     149           0 :     virtual void relax_attitude_controllers(bool exclude_pitch) { relax_attitude_controllers(); }
     150             : 
     151             :     // reset rate controller I terms
     152             :     void reset_rate_controller_I_terms();
     153             : 
     154             :     // Smoothly decays I-term to zero over ~0.5s. Useful for transitions to prevent overshoot.
     155             :     void reset_rate_controller_I_terms_smoothly();
     156             : 
     157             :     // Reduce attitude control gains while landed to stop ground resonance
     158             :     void landed_gain_reduction(bool landed);
     159             : 
     160             :     // Sets the attitude and angular rate targets to the current vehicle state.
     161             :     // If reset_rate is false, only the attitude target is reset and current rate targets are preserved.
     162             :     void reset_target_and_rate(bool reset_rate = true);
     163             : 
     164             :     // Sets the yaw angle target to the vehicle's current heading. Optionally resets yaw rate to zero.
     165             :     void reset_yaw_target_and_rate(bool reset_rate = true);
     166             : 
     167             :     // handle reset of attitude from EKF since the last iteration
     168             :     void inertial_frame_reset();
     169             : 
     170             :     // Commands a body-frame roll angle (in centidegrees), an euler pitch angle (in centidegrees), and a yaw rate (in centidegrees/s).
     171             :     // See input_euler_rate_yaw_euler_angle_pitch_bf_roll_rad() for full details.
     172             :     // (implemented only in AC_AttitudeControl_TS for tailsitter quadplanes)
     173           0 :     virtual void input_euler_rate_yaw_euler_angle_pitch_bf_roll_cd(bool plane_controls, float euler_roll_angle_cd, 
     174           0 :         float euler_pitch_angle_cd, float euler_yaw_rate_cds) {}
     175             : 
     176             :     // Commands a body-frame roll angle (in radians), an euler pitch angle (in radians), and a yaw rate (in radians/s).
     177             :     // Used by tailsitter quadplanes. Optionally swaps roll and yaw effects as pitch nears 90° if plane_controls is true.
     178             :     // (implemented only in AC_AttitudeControl_TS for tailsitter quadplanes)
     179           0 :     virtual void input_euler_rate_yaw_euler_angle_pitch_bf_roll_rad(bool plane_controls, float euler_roll_angle_rad, 
     180           0 :         float euler_pitch_angle_rad, float euler_yaw_rate_rads) {}
     181             : 
     182             :     ////// begin rate update functions //////
     183             :     // These functions all update _ang_vel_body_rads which is used as the rate target by the rate controller.
     184             :     // Since _ang_vel_body_rads can be seen by the rate controller thread all these functions only set it
     185             :     // at the end once all of the calculations have been performed. This avoids intermediate results being
     186             :     // used by the rate controller when running concurrently. _ang_vel_body_rads is accessed so commonly that
     187             :     // locking proves to be moderately expensive, however since this is changing incrementally values combining 
     188             :     // previous and current elements are safe and do not have an impact on control.
     189             :     // Any additional functions that are added to manipulate _ang_vel_body_rads should follow this pattern.
     190             : 
     191             :     // Calculates the body frame angular velocities to follow the target attitude
     192             :     // This is used by most of the subsequent functions
     193             :     void attitude_controller_run_quat();
     194             : 
     195             :     // Sets an attitude target using a quaternion and a body-frame angular velocity input (rad/s).
     196             :     // The desired quaternion is incrementally advanced each timestep using the (limited) angular velocity input.
     197             :     // If body-frame rate feedforward shaping is enabled, rate/accel targets are generated with acceleration limits
     198             :     // and input time constants; otherwise the targets are set directly.
     199             :     virtual void input_quaternion(Quaternion& attitude_desired_quat, Vector3f ang_vel_body_rads);
     200             : 
     201             :     // Sets the desired roll and pitch angles (in centidegrees) and yaw rate (in centidegrees/s).
     202             :     // See input_euler_angle_roll_pitch_euler_rate_yaw_rad() for full details.
     203             :     void input_euler_angle_roll_pitch_euler_rate_yaw_cd(float euler_roll_angle_cd, float euler_pitch_angle_cd, float euler_yaw_rate_cds);
     204             : 
     205             :     // Sets the desired roll and pitch angle inputs (radians) and a yaw rate input (radians/s).
     206             :     // Used when roll/pitch stabilization is required while yaw is controlled as a rate.
     207             :     // If body-frame rate feedforward shaping is enabled, shapes Euler rate/acceleration targets
     208             :     // with configured limits and time constants and converts them back to body-frame targets.
     209             :     // Otherwise, updates the attitude target directly and zeros rate/accel feedforward targets.
     210             :     virtual void input_euler_angle_roll_pitch_euler_rate_yaw_rad(float euler_roll_angle_rad, float euler_pitch_angle_rad, float euler_yaw_rate_rads);
     211             : 
     212             :     // Sets the desired roll, pitch, and yaw angles (in centidegrees).
     213             :     // See input_euler_angle_roll_pitch_yaw_rad() for full details.
     214             :     void input_euler_angle_roll_pitch_yaw_cd(float euler_roll_angle_cd, float euler_pitch_angle_cd, float euler_yaw_angle_cd, bool slew_yaw);
     215             : 
     216             :     // Sets the desired roll, pitch, and yaw angle inputs (radians) to follow an absolute attitude setpoint.
     217             :     // Optional yaw slew limiting constrains the rate of change of the yaw target.
     218             :     // If body-frame rate feedforward shaping is enabled, shapes Euler rate/acceleration targets
     219             :     // with configured limits and time constants and converts them back to body-frame targets.
     220             :     // Otherwise, updates the attitude target directly (with optional yaw slew) and zeros rate/accel feedforward targets.
     221             :     virtual void input_euler_angle_roll_pitch_yaw_rad(float euler_roll_angle_rad, float euler_pitch_angle_rad, float euler_yaw_angle_rad, bool slew_yaw);
     222             : 
     223             :     // Sets the desired roll, pitch, and yaw Euler angle rate inputs (radians/s).
     224             :     // If body-frame rate feedforward shaping is enabled, the inputs are shaped using acceleration limits
     225             :     // and time constants to generate Euler rate/acceleration targets, which are then converted into
     226             :     // body-frame angular velocity/acceleration targets for the rate controller.
     227             :     // Otherwise, Euler angle targets are integrated directly from the rate inputs and feedforward targets are zeroed.
     228             :     virtual void input_euler_rate_roll_pitch_yaw_rads(float euler_roll_rate_rads, float euler_pitch_rate_rads, float euler_yaw_rate_rads);
     229             : 
     230             :     // Sets the desired roll, pitch, and yaw angular rates (in centidegrees/s).
     231             :     // See input_rate_bf_roll_pitch_yaw_rads() for full details.
     232             :     void input_rate_bf_roll_pitch_yaw_cds(float roll_rate_bf_cds, float pitch_rate_bf_cds, float yaw_rate_bf_cds);
     233             : 
     234             :     // Sets the desired roll, pitch, and yaw body-frame angular rate inputs (radians/s).
     235             :     // Used by fully stabilized acro modes.
     236             :     // If body-frame rate feedforward shaping is enabled, the inputs are shaped using acceleration limits
     237             :     // and time constants to generate body-frame angular velocity/acceleration targets for the rate controller.
     238             :     // Otherwise, the attitude target is incrementally rotated using the rate inputs and feedforward targets are zeroed.
     239             :     virtual void input_rate_bf_roll_pitch_yaw_rads(float roll_rate_bf_rads, float pitch_rate_bf_rads, float yaw_rate_bf_rads);
     240             : 
     241             :     // Sets the desired roll, pitch, and yaw angular rates in body-frame (in centidegrees/s).
     242             :     // See input_rate_bf_roll_pitch_yaw_2_rads() for full details.
     243             :     void input_rate_bf_roll_pitch_yaw_2_cds(float roll_rate_bf_cds, float pitch_rate_bf_cds, float yaw_rate_bf_cds);
     244             : 
     245             :     // Sets the desired roll, pitch, and yaw body-frame angular rate inputs (radians/s).
     246             :     // Used by Copter's rate-only acro mode.
     247             :     // Shapes the body-frame rate inputs using acceleration limits and time constants to produce
     248             :     // body-frame angular velocity/acceleration targets for the rate controller.
     249             :     // Attitude targets are updated from the current AHRS attitude to keep target state coherent for mode transitions.
     250             :     virtual void input_rate_bf_roll_pitch_yaw_2_rads(float roll_rate_bf_rads, float pitch_rate_bf_rads, float yaw_rate_bf_rads);
     251             : 
     252             :     // Sets the desired roll, pitch, and yaw angular rates in body-frame (in centidegrees/s).
     253             :     // See input_rate_bf_roll_pitch_yaw_3_rads() for full details.
     254             :     void input_rate_bf_roll_pitch_yaw_3_cds(float roll_rate_bf_cds, float pitch_rate_bf_cds, float yaw_rate_bf_cds);
     255             : 
     256             :     // Sets the desired roll, pitch, and yaw body-frame angular rate inputs (radians/s).
     257             :     // Used by Plane's acro mode with rate error integration.
     258             :     // Maintains an integrated attitude error quaternion using (target_rate - gyro) and combines it
     259             :     // with shaped rate inputs to form the final body-frame angular velocity target for the rate controller.
     260             :     virtual void input_rate_bf_roll_pitch_yaw_3_rads(float roll_rate_bf_rads, float pitch_rate_bf_rads, float yaw_rate_bf_rads);
     261             : 
     262             :     // Directly sets the body-frame angular rates without smoothing (in centidegrees/s).
     263             :     // See input_rate_bf_roll_pitch_yaw_no_shaping_rads() for full details.
     264             :     void input_rate_bf_roll_pitch_yaw_no_shaping_cds(float roll_rate_bf_cds, float pitch_rate_bf_cds, float yaw_rate_bf_cds);
     265             : 
     266             :     // Directly sets body-frame angular rate targets (radians/s) without shaping.
     267             :     // Used when an external controller (e.g. fixed-wing controller) provides VTOL body rates.
     268             :     // No smoothing, acceleration limiting, or input shaping is applied.
     269             :     void input_rate_bf_roll_pitch_yaw_no_shaping_rads(float roll_rate_bf_rads, float pitch_rate_bf_rads, float yaw_rate_bf_rads);
     270             : 
     271             :     // Applies a one-time angular offset in body-frame roll/pitch/yaw angles (in radians).
     272             :     // Used for initiating step responses during autotuning or manual test inputs.
     273             :     virtual void input_angle_step_bf_roll_pitch_yaw_rad(float roll_angle_step_bf_rad, float pitch_angle_step_bf_rad, float yaw_angle_step_bf_rad);
     274             :     
     275             :     // Applies a one-time body-frame angular rate step (radians/s) in roll, pitch, and yaw.
     276             :     // Used to inject discrete disturbances or step inputs for system identification.
     277             :     // This sets the body-frame rate command directly for this update; no shaping is applied.
     278             :     virtual void input_rate_step_bf_roll_pitch_yaw_rads(float roll_rate_step_bf_rads, float pitch_rate_step_bf_rads, float yaw_rate_step_bf_rads);
     279             : 
     280             :     // Sets the desired thrust vector and a yaw/heading rate input (radians/s).
     281             :     // Used for tilt-based navigation with independent yaw control.
     282             :     // The thrust vector determines the desired tilt (attitude) while the heading rate commands yaw.
     283             :     // Optional yaw slew limiting constrains the heading rate input.
     284             :     virtual void input_thrust_vector_rate_heading_rads(const Vector3f& thrust_vector, float heading_rate_rads, bool slew_yaw = true);
     285             : 
     286             :     // Sets the desired thrust vector, heading angle (radians), and heading rate input (radians/s).
     287             :     // Used when thrust direction (tilt) is commanded independently from yaw/heading.
     288             :     // Heading rate is constrained using the configured yaw slew rate limit (0 disables limiting).
     289             :     virtual void input_thrust_vector_heading_rad(const Vector3f& thrust_vector, float heading_angle_rad, float heading_rate_rads);
     290             : 
     291             :     // Sets the desired thrust vector and heading (in centidegrees), with zero heading rate.
     292             :     // See input_thrust_vector_heading_rad() for full details.
     293             :     void input_thrust_vector_heading_rad(const Vector3f& thrust_vector, float heading_rad) {input_thrust_vector_heading_rad(thrust_vector, heading_rad, 0.0f);}
     294             : 
     295             :     ////// end rate update functions //////
     296             : 
     297             :     // Converts a thrust vector and heading angle to a body-to-NED quaternion attitude
     298             :     Quaternion attitude_from_thrust_vector(Vector3f thrust_vector, float heading_angle_rad) const;
     299             : 
     300             :     // Run angular velocity controller and send outputs to the motors
     301             :     virtual void rate_controller_run() = 0;
     302             : 
     303             :     // reset the rate controller target loop updates
     304             :     void rate_controller_target_reset();
     305             : 
     306             :     // Run the angular velocity controller with a specified timestep. Must be implemented by derived class.
     307           0 :     virtual void rate_controller_run_dt(const Vector3f& gyro_rads, float dt) { AP_BoardConfig::config_error("rate_controller_run_dt() must be defined"); };
     308             : 
     309             :     // euler_derivative_to_body - transform euler angle derivative to body-frame
     310             :     // Converts euler derivatives (rate, acceleration, etc.) to body-frame equivalents.
     311             :     // The same transformation applies regardless of derivative order.
     312             :     // Uses the kinematic relationship for 321 (yaw-pitch-roll) euler sequence.
     313             :     void euler_derivative_to_body(const Quaternion& att, const Vector3f& euler_derivative_rads, Vector3f& body_derivative_rads);
     314             : 
     315             :     // body_to_euler_derivative - transform body-frame derivative to euler angle derivative
     316             :     // Converts body-frame derivatives (rate, acceleration, etc.) to euler equivalents.
     317             :     // The same transformation applies regardless of derivative order.
     318             :     // Uses the kinematic relationship for 321 (yaw-pitch-roll) euler sequence.
     319             :     // Returns false if the vehicle is pitched 90 degrees up or down (gimbal lock)
     320             :     bool body_to_euler_derivative(const Quaternion& att, const Vector3f& body_derivative_rads, Vector3f& euler_derivative_rads);
     321             : 
     322             :     // Specifies whether the attitude controller should use the square root controller in the attitude correction.
     323             :     // This is used during Autotune to ensure the P term is tuned without being influenced by the acceleration limit of the square root controller.
     324        4698 :     void use_sqrt_controller(bool use_sqrt_cont) { _use_sqrt_controller = use_sqrt_cont; }
     325             : 
     326             :     // Return 321-intrinsic euler angles in centidegrees representing the rotation from NED earth frame to the
     327             :     // attitude controller's target attitude.
     328             :     // **NOTE** Using vector3f*deg(100) is more efficient than deg(vector3f)*100 or deg(vector3d*100) because it gives the
     329             :     // same result with the fewest multiplications. Even though it may look like a bug, it is intentional. See issue 4895.
     330      624141 :     Vector3f get_att_target_euler_cd() const { return _euler_angle_target_rad * degrees(100.0f); }
     331    65417834 :     const Vector3f & get_att_target_euler_rad() const { return _euler_angle_target_rad; }
     332             : 
     333             :     // Returns the target attitude quaternion used by the attitude controller.
     334             :     // This represents the desired orientation in NED earth frame.
     335      223475 :     Quaternion get_attitude_target_quat() const { return _attitude_target; }
     336             : 
     337             :     // Return the angular velocity of the target (setpoint) [rad/s] in the target attitude frame
     338     4516220 :     const Vector3f& get_attitude_target_ang_vel() const { return _ang_vel_target_rads;}
     339             : 
     340             :     // Return the angle between the target thrust vector and the current thrust vector.
     341    22485066 :     float get_att_error_angle_deg() const { return degrees(_thrust_error_angle_rad); }
     342             : 
     343             :     // Returns the current attitude target as 321 Euler angles in centidegrees.
     344             :     // Note: Centidegrees are used for legacy compatibility with older messaging formats.
     345      374475 :     void rate_bf_yaw_target(float rate_cds) { _ang_vel_body_rads.z = cd_to_rad(rate_cds); }
     346             : 
     347             :     // Set x-axis system identification angular velocity in radians/s
     348           0 :     void rate_bf_roll_sysid_rads(float rate_rads) { _sysid_ang_vel_body_rads.x = rate_rads; }
     349             : 
     350             :     // Set y-axis system identification angular velocity in radians/s
     351           0 :     void rate_bf_pitch_sysid_rads(float rate_rads) { _sysid_ang_vel_body_rads.y = rate_rads; }
     352             : 
     353             :     // Set z-axis system identification angular velocity in radians/s
     354           0 :     void rate_bf_yaw_sysid_rads(float rate_rads) { _sysid_ang_vel_body_rads.z = rate_rads; }
     355             : 
     356             :     // Set x-axis system identification actuator
     357           0 :     void actuator_roll_sysid(float command) { _actuator_sysid.x = command; }
     358             : 
     359             :     // Set y-axis system identification actuator
     360           0 :     void actuator_pitch_sysid(float command) { _actuator_sysid.y = command; }
     361             : 
     362             :     // Set z-axis system identification actuator
     363           0 :     void actuator_yaw_sysid(float command) { _actuator_sysid.z = command; }
     364             : 
     365             :     // Return roll rate step size in radians/s that results in maximum output after 4 time steps
     366             :     float max_rate_step_bf_roll();
     367             : 
     368             :     // Return pitch rate step size in radians/s that results in maximum output after 4 time steps
     369             :     float max_rate_step_bf_pitch();
     370             : 
     371             :     // Return yaw rate step size in radians/s that results in maximum output after 4 time steps
     372             :     float max_rate_step_bf_yaw();
     373             : 
     374             :     // Return roll step size in radians that results in maximum output after 4 time steps
     375         393 :     float max_angle_step_bf_roll() { return max_rate_step_bf_roll() / _p_angle_roll.kP(); }
     376             : 
     377             :     // Return pitch step size in radians that results in maximum output after 4 time steps
     378         386 :     float max_angle_step_bf_pitch() { return max_rate_step_bf_pitch() / _p_angle_pitch.kP(); }
     379             : 
     380             :     // Return yaw step size in radians that results in maximum output after 4 time steps
     381        1403 :     float max_angle_step_bf_yaw() { return max_rate_step_bf_yaw() / _p_angle_yaw.kP(); }
     382             : 
     383             :     // Return the body-frame angular velocity (in rad/s) used by the angular velocity controller.
     384     5193374 :     Vector3f rate_bf_targets() const { return _ang_vel_body_rads + _sysid_ang_vel_body_rads; }
     385             : 
     386             :     // return the angular velocity of the target (setpoint) attitude rad/s
     387      928202 :     const Vector3f& get_rate_ef_target_rads() const { return _euler_rate_target_rads; }
     388             : 
     389             :     // Enable or disable body-frame feed forward
     390        2523 :     void bf_feedforward(bool enable_or_disable) { _rate_bf_ff_enabled.set(enable_or_disable); }
     391             : 
     392             :     // Enable or disable body-frame feed forward and save
     393           0 :     void bf_feedforward_save(bool enable_or_disable) { _rate_bf_ff_enabled.set_and_save(enable_or_disable); }
     394             : 
     395             :     // Return body-frame feed forward setting
     396     2772565 :     bool get_bf_feedforward() { return _rate_bf_ff_enabled; }
     397             : 
     398             :     // Enable or disable body-frame feed forward
     399             :     void accel_limiting(bool enable_or_disable);
     400             : 
     401             :     // Update Alt_Hold angle maximum
     402             :     virtual void update_althold_lean_angle_max(float throttle_in) = 0;
     403             : 
     404             :     // Set output throttle
     405             :     virtual void set_throttle_out(float throttle_in, bool apply_angle_boost, float filt_cutoff) = 0;
     406             : 
     407             :     // get throttle passed into attitude controller (i.e. throttle_in provided to set_throttle_out)
     408    26127671 :     float get_throttle_in() const { return _throttle_in; }
     409             : 
     410             :     // Return throttle increase applied for tilt compensation
     411      986292 :     float angle_boost() const { return _angle_boost; }
     412             : 
     413             :     // Returns maximum allowable tilt angle (in radians) for pilot input when in altitude hold mode.
     414             :     // Used to limit lean angle based on available thrust margin, prioritising altitude stability.
     415             :     virtual float get_althold_lean_angle_max_rad() const;
     416             : 
     417             :     // Returns maximum allowable tilt angle (in centidegrees) for pilot input when in altitude hold mode.
     418             :     // See get_althold_lean_angle_max_rad() for full details.
     419             :     float get_althold_lean_angle_max_cd() const;
     420             : 
     421             :     // Return configured tilt angle limit in centidegrees
     422             :     float lean_angle_max_cd() const;
     423             : 
     424             :     // Return configured tilt angle limit in radians
     425             :     float lean_angle_max_rad() const;
     426             : 
     427             :     // Return tilt angle in degrees
     428      855370 :     float lean_angle_deg() const { return degrees(_thrust_angle_rad); }
     429           0 :     float lean_angle_rad() const { return _thrust_angle_rad; }
     430             : 
     431             :     // Calculates the velocity correction from an angle error, applying acceleration/deceleration limits and a simple jerk-limiting mechanism via the smoothing gain.
     432             :     void attitude_command_model(float error_angle, float desired_ang_vel, float& target_ang_vel, float& target_ang_accel, float max_ang_vel, float accel_max, float input_tc, float dt) const;
     433             : 
     434             :     // calculates the expected angular velocity correction from an angle error based on the AC_AttitudeControl settings.
     435             :     // This function can be used to predict the delay associated with angle requests.
     436             :     void command_model_rate_predictor(const Vector2f &error_angle_rad, Vector2f& target_ang_vel_rads, Vector2f& target_ang_accel_rads, float dt) const;
     437             : 
     438             :     // Limits angular velocity in roll, pitch, and yaw.
     439             :     // Roll and pitch are coupled: when both limits are set, they are scaled
     440             :     // proportionally as a 2D vector, preserving their ratio. Yaw is clamped independently
     441             :     void ang_vel_limit(Vector3f& euler_rad, float ang_vel_roll_max_rads, float ang_vel_pitch_max_rads, float ang_vel_yaw_max_rads) const;
     442             : 
     443             :     // translates body frame rotation rates and acceleration limits to the euler axis
     444             :     Vector3f body_to_euler_limit(const Quaternion &att, const Vector3f &body_limit);
     445             : 
     446             :     // Calculates the body frame angular velocities to follow the target attitude
     447             :     void update_attitude_target();
     448             : 
     449             :     // thrust_heading_rotation_angles - calculates two ordered rotations to move the attitude_body quaternion to the attitude_target quaternion.
     450             :     // The maximum error in the yaw axis is limited based on the angle yaw P value and acceleration.
     451             :     void thrust_heading_rotation_angles(Quaternion& attitude_target, const Quaternion& attitude_body, Vector3f& attitude_error_rad, float& thrust_angle_rad, float& thrust_error_angle_rad) const;
     452             : 
     453             :     // thrust_vector_rotation_angles - calculates two ordered rotations to move the attitude_body quaternion to the attitude_target quaternion.
     454             :     // The first rotation corrects the thrust vector and the second rotation corrects the heading vector.
     455             :     void thrust_vector_rotation_angles(const Quaternion& attitude_target, const Quaternion& attitude_body, Quaternion& thrust_vector_correction, Vector3f& attitude_error_rad, float& thrust_angle_rad, float& thrust_error_angle_rad) const;
     456             : 
     457             :     // sanity check parameters.  should be called once before take-off
     458          83 :     virtual void parameter_sanity_check() {}
     459             : 
     460             :     // Optional override: sets the notch filter sample rate for rate PID controllers (if supported).
     461             :     // Default implementation is empty.
     462           0 :     virtual void set_notch_sample_rate(float sample_rate) {}
     463             : 
     464             :     // Returns true if throttle RPY mix is at its minimum value.
     465             :     // Used to determine if attitude control should be reduced in favor of vertical thrust.
     466           0 :     virtual bool is_throttle_mix_min() const { return true; }
     467             : 
     468             :     // control rpy throttle mix
     469           0 :     virtual void set_throttle_mix_min() {}
     470           0 :     virtual void set_throttle_mix_man() {}
     471           0 :     virtual void set_throttle_mix_max(float ratio) {}
     472           0 :     virtual void set_throttle_mix_value(float value) {}
     473           0 :     virtual float get_throttle_mix(void) const { return 0; }
     474             : 
     475             :         // use_leaky_i - controls whether we use leaky i term for body-frame to motor output stage on heli
     476           0 :         virtual void use_leaky_i(bool leaky_i) {}
     477             : 
     478             :     // set_hover_roll_scalar - scales Hover Roll Trim parameter. To be used by vehicle code according to vehicle condition.
     479           0 :     virtual void set_hover_roll_trim_scalar(float scalar) {}
     480             : 
     481             :     // Return angle in centidegrees to be added to roll angle for hover collective learn. Used by heli to counteract
     482             :     // tail rotor thrust in hover. Overloaded by AC_Attitude_Heli to return angle.
     483    16641328 :     virtual float get_roll_trim_cd() { return 0;}
     484             : 
     485             :     // Return angle in radians to be added to roll angle. Used by heli to counteract
     486             :     // tail rotor thrust in hover. Overloaded by AC_Attitude_Heli to return angle.
     487    19261155 :     float get_roll_trim_rad() { return cd_to_rad(get_roll_trim_cd()); }
     488             : 
     489             :     // provide feedback on whether arming would be a good idea right now:
     490             :     bool pre_arm_checks(const char *param_prefix,
     491             :                         char *failure_msg,
     492             :                         const uint8_t failure_msg_len);
     493             : 
     494             :     // enable inverted flight on backends that support it
     495           0 :     virtual void set_inverted_flight(bool inverted) {}
     496             : 
     497             :     // enable accessor for inverted flight flag on backends that support it
     498           0 :     virtual bool get_inverted_flight() { return false;}
     499             : 
     500             :     // get the slew rate value for roll, pitch and yaw, for oscillation detection in lua scripts
     501             :     void get_rpy_srate(float &roll_srate, float &pitch_srate, float &yaw_srate);
     502             :     
     503             :     // Sets the roll and pitch rate shaping time constant
     504        1267 :     void set_roll_pitch_rate_tc(float input_tc) { _rate_rp_tc = input_tc; }
     505             : 
     506             :     // Sets the yaw rate shaping time constant
     507     2597625 :     void set_yaw_rate_tc(float input_tc) { _rate_y_tc = input_tc; }
     508             : 
     509             :     // setup a one loop angle P scale multiplier. This replaces any previous scale applied
     510             :     // so should only be used when only one source of scaling is needed
     511      201445 :     void set_angle_P_scale(const Vector3f &angle_P_scale) { _angle_P_scale = angle_P_scale; }
     512             : 
     513             :     // setup a one loop angle P scale multiplier, multiplying by any
     514             :     // previously applied scale from this loop. This allows for more
     515             :     // than one type of scale factor to be applied for different
     516             :     // purposes
     517    30664814 :     void set_angle_P_scale_mult(const Vector3f &angle_P_scale) { _angle_P_scale *= angle_P_scale; }
     518             : 
     519             :     // get the value of the angle P scale that was used in the last loop
     520     4724142 :     const Vector3f &get_last_angle_P_scale(void) const { return _angle_P_scale_used; }
     521             :     
     522             :     // setup a one loop PD scale multiplier, multiplying by any
     523             :     // previously applied scale from this loop. This allows for more
     524             :     // than one type of scale factor to be applied for different
     525             :     // purposes
     526    30664814 :     void set_PD_scale_mult(const Vector3f &pd_scale) { _pd_scale *= pd_scale; }
     527             : 
     528             :     // setup a one loop I scale multiplier, multiplying by any
     529             :     // previously applied scale from this loop. This allows for more
     530             :     // than one type of scale factor to be applied for different
     531             :     // purposes
     532           0 :     void set_I_scale_mult(const Vector3f &i_scale) { _i_scale *= i_scale; }
     533             : 
     534             :     // scale I to represent the control given by angle P
     535             :     void scale_I_to_angle_P();
     536             : 
     537             :     // write RATE message
     538             :     void Write_Rate(const AC_PosControl &pos_control) const;
     539             : 
     540             :     // write ANG message
     541             :     void Write_ANG() const;
     542             : 
     543             :     // perform any required parameter conversions
     544             :     void convert_parameters();
     545             : 
     546             :     // User settable parameters
     547             :     static const struct AP_Param::GroupInfo var_info[];
     548             : 
     549             :     static constexpr Vector3f VECTORF_111{1.0f,1.0f,1.0f};
     550             : 
     551             : protected:
     552             : 
     553             :     // Update rate_target_ang_vel using attitude_error_rot_vec_rad
     554             :     Vector3f update_ang_vel_target_from_att_error(const Vector3f &attitude_error_rot_vec_rad);
     555             : 
     556             :     // Returns the most recent angular velocity reading (rad/s) for the rate controller.
     557             :     // Ensures minimum latency when rate control is run before or after attitude control.
     558             :     const Vector3f get_latest_gyro() const;
     559             : 
     560             :     // Maximum rate the yaw target can be updated in Loiter, RTL, Auto flight modes
     561             :     AP_Float            _rate_wp_yaw_max_degs;
     562             : 
     563             :     // Maximum angular velocity (in degrees/second) for earth-frame roll, pitch and yaw axis
     564             :     AP_Float            _ang_vel_roll_max_degs;
     565             :     AP_Float            _ang_vel_pitch_max_degs;
     566             :     AP_Float            _ang_vel_yaw_max_degs;
     567             : 
     568             :     // Maximum rotation acceleration for earth-frame roll axis
     569             :     AP_Float            _accel_roll_max_degss;
     570             : 
     571             :     // Maximum rotation acceleration for earth-frame pitch axis
     572             :     AP_Float            _accel_pitch_max_degss;
     573             : 
     574             :     // Maximum rotation acceleration for earth-frame yaw axis
     575             :     AP_Float            _accel_yaw_max_degss;
     576             : 
     577             :     // Enable/Disable body frame rate feed forward
     578             :     AP_Int8             _rate_bf_ff_enabled;
     579             : 
     580             :     // Enable/Disable angle boost
     581             :     AP_Int8             _angle_boost_enabled;
     582             : 
     583             :     // angle controller P objects
     584             :     AC_P                _p_angle_roll;
     585             :     AC_P                _p_angle_pitch;
     586             :     AC_P                _p_angle_yaw;
     587             : 
     588             :     // Angle limit time constant (to maintain altitude)
     589             :     AP_Float            _angle_limit_tc;
     590             : 
     591             :     // Time constant [s] used to smooth user/control input changes before being passed to the rate controller. 
     592             :     // Affects angular response stiffness.
     593             :     AP_Float            _input_tc;
     594             : 
     595             :     // Controller gain multiplyer to be used when landed
     596             :     AP_Float            _land_roll_mult;
     597             :     AP_Float            _land_pitch_mult;
     598             :     AP_Float            _land_yaw_mult;
     599             : 
     600             :     // Angle limit
     601             :     AP_Float            _angle_max_deg;
     602             : 
     603             :     // Latest body-frame gyro measurement (rad/s) used by rate controller
     604             :     Vector3f            _rate_gyro_rads;
     605             :     // timestamp of the latest gyro measurement (in microseconds) value used by the rate controller
     606             :     uint64_t            _rate_gyro_time_us;
     607             : 
     608             :     // Intersampling period in seconds
     609             :     float               _dt_s;
     610             : 
     611             :     // This represents a 321-intrinsic rotation in NED frame to the target (setpoint)
     612             :     // attitude used in the attitude controller, in radians.
     613             :     Vector3f            _euler_angle_target_rad;
     614             : 
     615             :     // This represents the angular velocity of the target (setpoint) attitude used in
     616             :     // the attitude controller as 321-intrinsic euler angle derivatives, in radians per
     617             :     // second.
     618             :     Vector3f            _euler_rate_target_rads;
     619             : 
     620             :     // This represents a quaternion rotation in NED frame to the target (setpoint)
     621             :     // attitude used in the attitude controller.
     622             :     Quaternion          _attitude_target;
     623             : 
     624             :     // This represents the angular velocity of the target (setpoint) attitude used in
     625             :     // the attitude controller as an angular velocity vector, in radians per second in
     626             :     // the target attitude frame.
     627             :     Vector3f            _ang_vel_target_rads;
     628             :     Vector3f            _ang_accel_target_rads;
     629             : 
     630             :     // This represents the angular velocity in radians per second in the body frame, used in the angular
     631             :     // velocity controller and most importantly the rate controller.
     632             :     Vector3f            _ang_vel_body_rads;
     633             : 
     634             :     // This is the angular velocity in radians per second in the body frame, added to the output angular
     635             :     // attitude controller by the System Identification Mode.
     636             :     // It is reset to zero immediately after it is used.
     637             :     Vector3f            _sysid_ang_vel_body_rads;
     638             : 
     639             :     // System Identification actuator override applied to motor commands. 
     640             :     // This is a unitless signal added post-PID for excitation purposes and is reset every loop.
     641             :     // It is reset to zero immediately after it is used.
     642             :     Vector3f            _actuator_sysid;
     643             : 
     644             :     // This represents a quaternion attitude error in the body frame, used for inertial frame reset handling.
     645             :     Quaternion          _attitude_ang_error;
     646             : 
     647             :     // The angle between the target thrust vector and the current thrust vector.
     648             :     float               _thrust_angle_rad;
     649             : 
     650             :     // The angle between the target thrust vector and the current thrust vector.
     651             :     float               _thrust_error_angle_rad;
     652             : 
     653             :     // throttle provided as input to attitude controller.  This does not include angle boost.
     654             :     float               _throttle_in = 0.0f;
     655             : 
     656             :     // Throttle increase applied to maintain vertical thrust during attitude tilt. 
     657             :     // Used logging for logging and diagnostics.
     658             :     float               _angle_boost;
     659             : 
     660             :     // Specifies whether the attitude controller should use the square root controller in the attitude correction.
     661             :     // This is used during Autotune to ensure the P term is tuned without being influenced by the acceleration limit of the square root controller.
     662             :     bool                _use_sqrt_controller;
     663             : 
     664             :     // Filtered Alt_Hold lean angle max - used to limit lean angle when throttle is saturated using Alt_Hold
     665             :     float               _althold_lean_angle_max_rad = 0.0f;
     666             : 
     667             :     // desired throttle_low_comp value, actual throttle_low_comp is slewed towards this value over 1~2 seconds
     668             :     float               _throttle_rpy_mix_desired;
     669             : 
     670             :     // mix between throttle and hover throttle for 0 to 1 and ratio above hover throttle for >1
     671             :     float               _throttle_rpy_mix;
     672             : 
     673             :     // Yaw feed forward percent to allow zero yaw actuator output during extreme roll and pitch corrections
     674             :     float               _feedforward_scalar = 1.0f;
     675             : 
     676             :     // Rate controller input smoothing time constants
     677             :     // Time constant for shaping roll/pitch rate input [s]
     678             :     float               _rate_rp_tc;
     679             :     // Time constant for shaping yaw rate input [s]
     680             :     float               _rate_y_tc;
     681             : 
     682             :     // Active scaling applied to Angle P gains for roll, pitch, yaw
     683             :     Vector3f            _angle_P_scale{1,1,1};
     684             : 
     685             :     // Active scaling applied to Angle P gains this loop (for logging/debugging)
     686             :     Vector3f            _angle_P_scale_used;
     687             : 
     688             :     // Proportional-Derivative gains applied dynamically per axis
     689             :     Vector3f            _pd_scale{1,1,1};
     690             : 
     691             :     // Proportional-Derivative gains this loop (for logging/debugging)
     692             :     Vector3f            _pd_scale_used;
     693             : 
     694             :     // Integrator gains applied dynamically per axis
     695             :     Vector3f            _i_scale{1,1,1};
     696             : 
     697             :     // Integrator gains this loop (for logging/debugging)
     698             :     Vector3f            _i_scale_used;
     699             : 
     700             :     // Ratio of normal to reduced rate controller gain when landed to suppress ground resonance
     701             :     float               _landed_gain_ratio;
     702             : 
     703             :     // References to external libraries
     704             :     const AP_AHRS_View&  _ahrs;
     705             :     AP_Motors&          _motors;
     706             : 
     707             :     static AC_AttitudeControl *_singleton;
     708             : 
     709             : public:
     710             :     // structure for angle and/or rate target
     711             :     enum class HeadingMode {
     712             :         Angle_Only,
     713             :         Angle_And_Rate,
     714             :         Rate_Only
     715             :     };
     716             :     struct HeadingCommand {
     717             :         float yaw_angle_rad;
     718             :         float yaw_rate_rads;
     719             :         HeadingMode heading_mode;
     720             :     };
     721             :     void input_thrust_vector_heading(const Vector3f& thrust_vector, HeadingCommand heading);
     722             : };

Generated by: LCOV version 1.14