Path: blob/master/libraries/AC_AttitudeControl/AC_PosControl.h
9451 views
#pragma once12#include <AP_Common/AP_Common.h>3#include <AP_Param/AP_Param.h>4#include <AP_Math/AP_Math.h>5#include <AC_PID/AC_P.h> // P library6#include <AC_PID/AC_PID.h> // PID library7#include <AC_PID/AC_P_1D.h> // P library (1-axis)8#include <AC_PID/AC_P_2D.h> // P library (2-axis)9#include <AC_PID/AC_PI_2D.h> // PI library (2-axis)10#include <AC_PID/AC_PID_Basic.h> // PID library (1-axis)11#include <AC_PID/AC_PID_2D.h> // PID library (2-axis)12#include <AP_Scripting/AP_Scripting_config.h>13#include "AC_AttitudeControl.h" // Attitude control library1415#include <AP_Logger/LogStructure.h>1617// position controller default definitions18#define POSCONTROL_ACCEL_NE_MSS 1.0f // default horizontal acceleration in m/s². This is overwritten by waypoint and loiter controllers19#define POSCONTROL_JERK_NE_MSSS 5.0f // default horizontal jerk m/s³2021#define POSCONTROL_STOPPING_DIST_UP_MAX_M 3.0f // max stopping distance (in m) vertically while climbing22#define POSCONTROL_STOPPING_DIST_DOWN_MAX_M 2.0f // max stopping distance (in m) vertically while descending2324#define POSCONTROL_SPEED_MS 5.0f // default horizontal speed in m/s25#define POSCONTROL_SPEED_DOWN_MS 1.5f // default descent rate in m/s26#define POSCONTROL_SPEED_UP_MS 2.5f // default climb rate in m/s2728#define POSCONTROL_ACCEL_D_MSS 2.5f // default vertical acceleration in m/s²29#define POSCONTROL_JERK_D_MSSS 5.0f // default vertical jerk m/s³3031#define POSCONTROL_THROTTLE_CUTOFF_FREQ_HZ 2.0f // low-pass filter on acceleration error (unit: Hz)3233#define POSCONTROL_OVERSPEED_GAIN_U 2.0f // gain controlling rate at which z-axis speed is brought back within SPEED_UP and SPEED_DOWN range3435#define POSCONTROL_RELAX_TC 0.16f // This is used to decay the I term to 5% in half a second3637class AC_PosControl38{39public:4041/// Constructor42AC_PosControl(AP_AHRS_View& ahrs, const class AP_Motors& motors, AC_AttitudeControl& attitude_control);4344// do not allow copying45CLASS_NO_COPY(AC_PosControl);4647// Sets the timestep between controller updates (seconds).48// This should match the IMU sample time used by the controller.49void set_dt_s(float dt) { _dt_s = dt; }5051// Returns the timestep used in the controller update (seconds).52float get_dt_s() const { return _dt_s; }5354// Updates internal NED position and velocity estimates from AHRS.55// Falls back to vertical-only data if horizontal velocity or position is invalid or vibration forces it.56// When high_vibes is true, forces use of vertical fallback for velocity.57void update_estimates(bool high_vibes = false);5859// Returns the jerk limit for horizontal path shaping in m/s³.60// Used to constrain acceleration changes in trajectory generation.61float get_shaping_jerk_NE_msss() const { return _shaping_jerk_ne_msss; }626364///65/// 3D position shaper66///6768// Sets a new NED position target in meters and computes a jerk-limited trajectory.69// Updates internal acceleration commands using a smooth kinematic path constrained70// by configured acceleration and jerk limits.71// The path can be offset vertically to follow the terrain by providing the current72// terrain level in the NED frame and the terrain margin. Terrain margin is used to73// constrain horizontal velocity to avoid vertical buffer violation.74void input_pos_NED_m(const Vector3p& pos_ned_m, float pos_terrain_target_d_m, float terrain_margin_m);7576// Returns a scaling factor for horizontal velocity in m/s to ensure77// the vertical controller maintains a safe distance above terrain.78float terrain_scaler_D_m(float pos_terrain_d_m, float terrain_margin_m) const;7980///81/// Lateral position controller82///8384// Sets maximum horizontal speed (cm/s) and acceleration (cm/s²) for NE-axis shaping.85// Can be called anytime; transitions are handled smoothly.86// All arguments should be positive.87// See NE_set_max_speed_accel_m() for full details.88void NE_set_max_speed_accel_cm(float speed_cms, float accel_cmss);8990// Sets maximum horizontal speed (m/s) and acceleration (m/s²) for NE-axis shaping.91// These values constrain the kinematic trajectory used by the lateral controller.92// All arguments should be positive.93void NE_set_max_speed_accel_m(float speed_ms, float accel_mss);9495// Sets horizontal correction limits for velocity (cm/s) and acceleration (cm/s²).96// Should be called only during initialization to avoid control discontinuities.97// All arguments should be positive.98// See NE_set_correction_speed_accel_m() for full details.99void NE_set_correction_speed_accel_cm(float speed_cms, float accel_cmss);100101// Sets horizontal correction limits for velocity (m/s) and acceleration (m/s²).102// These values constrain the PID correction path, not the desired trajectory.103// All arguments should be positive.104void NE_set_correction_speed_accel_m(float speed_ms, float accel_mss);105106// Returns maximum horizontal speed in cm/s.107// See NE_get_max_speed_ms() for full details.108float NE_get_max_speed_cms() const { return NE_get_max_speed_ms() * 100.0; }109110// Returns maximum horizontal speed in m/s used for shaping the trajectory.111float NE_get_max_speed_ms() const { return _vel_max_ne_ms; }112113// Returns maximum horizontal acceleration in m/s² used for trajectory shaping.114float NE_get_max_accel_mss() const { return _accel_max_ne_mss; }115116// Sets maximum allowed horizontal position error in meters.117// Used to constrain the output of the horizontal position P controller.118void NE_set_pos_error_max_m(float error_max_m) { _p_pos_ne_m.set_error_max(error_max_m); }119120// Returns maximum allowed horizontal position error in meters.121float NE_get_pos_error_max_m() const { return _p_pos_ne_m.get_error_max(); }122123// Initializes NE controller to a stationary stopping point with zero velocity and acceleration.124// Use when the expected trajectory begins at rest but the starting position is unspecified.125// The starting position can be retrieved with get_pos_target_NED_m().126void NE_init_controller_stopping_point();127128// Smoothly decays NE acceleration over time to zero while maintaining current velocity and position.129// Reduces output acceleration by ~95% over 0.5 seconds to avoid abrupt transitions.130void NE_relax_velocity_controller();131132// Softens NE controller for landing by reducing position error and suppressing I-term windup.133// Used to make descent behavior more stable near ground contact.134void NE_soften_for_landing();135136// Fully initializes the NE controller with current position, velocity, acceleration, and attitude.137// Intended for normal startup when the full state is known.138// Private function shared by other NE initializers.139void NE_init_controller();140141// Sets the desired NE-plane acceleration in m/s² using jerk-limited shaping.142// Smoothly transitions to the specified acceleration from current kinematic state.143// Constraints: max acceleration and jerk set via NE_set_max_speed_accel_m().144void input_accel_NE_m(const Vector2f& accel_ne_msss);145146// Sets desired NE-plane velocity and acceleration (cm/s, cm/s²) using jerk-limited shaping.147// See input_vel_accel_NE_m() for full details.148void input_vel_accel_NE_cm(Vector2f& vel_ne_cms, const Vector2f& accel_ne_cmss, bool limit_output = true);149150// Sets desired NE-plane velocity and acceleration (m/s, m/s²) using jerk-limited shaping.151// Calculates target acceleration using current kinematics constrained by acceleration and jerk limits.152// If `limit_output` is true, applies limits to total command (desired + correction).153void input_vel_accel_NE_m(Vector2f& vel_ne_ms, const Vector2f& accel_ne_mss, bool limit_output = true);154155// Sets desired NE position, velocity, and acceleration (cm, cm/s, cm/s²) with jerk-limited shaping.156// See input_pos_vel_accel_NE_m() for full details.157void input_pos_vel_accel_NE_cm(Vector2p& pos_ne_cm, Vector2f& vel_ne_cms, const Vector2f& accel_ne_cmss, bool limit_output = true);158159// Sets desired NE position, velocity, and acceleration (m, m/s, m/s²) with jerk-limited shaping.160// Calculates acceleration trajectory based on current kinematics and constraints.161// If `limit_output` is true, limits apply to full command (desired + correction).162void input_pos_vel_accel_NE_m(Vector2p& pos_ne_m, Vector2f& vel_ne_ms, const Vector2f& accel_ne_mss, bool limit_output = true);163164// Returns true if the NE position controller has run in the last 5 control loop cycles.165bool NE_is_active() const;166167// Disables NE position correction by setting the target position to the current position.168// Useful to freeze positional control without disrupting velocity control.169void NE_stop_pos_stabilisation();170171// Disables NE position and velocity correction by setting target values to current state.172// Useful to prevent further corrections and freeze motion stabilization in NE axes.173void NE_stop_vel_stabilisation();174175// Applies a scalar multiplier to the NE control loop.176// Set to 0 to disable lateral control; 1 for full authority.177void NE_set_control_scale_factor(float ne_control_scale_factor) {178_ne_control_scale_factor = ne_control_scale_factor;179}180181// Runs the NE-axis position controller, computing output acceleration from position and velocity errors.182// Uses P and PID controllers to generate corrections which are added to feedforward velocity/acceleration.183// Requires all desired targets to be pre-set using the input_* or set_* methods.184void NE_update_controller();185186///187/// Vertical position controller188///189190// Sets maximum climb/descent rate (cm/s) and vertical acceleration (cm/s²) for the U-axis.191// Descent rate may be positive or negative and is always interpreted as a descent.192// See D_set_max_speed_accel_m() for full details.193// All values must be positive.194void D_set_max_speed_accel_cm(float decent_speed_max_cms, float climb_speed_max_cms, float accel_max_u_cmss);195196// Sets maximum climb/descent rate (m/s) and vertical acceleration (m/s²) for the U-axis.197// These values are used for jerk-limited kinematic shaping of the vertical trajectory.198// All values must be positive.199void D_set_max_speed_accel_m(float decent_speed_max_ms, float climb_speed_max_ms, float accel_max_d_mss);200201// Sets vertical correction velocity and acceleration limits (cm/s, cm/s²).202// Should only be called during initialization to avoid discontinuities.203// See D_set_correction_speed_accel_m() for full details.204// All values must be positive.205void D_set_correction_speed_accel_cm(float decent_speed_max_cms, float climb_speed_max_cms, float accel_max_u_cmss);206207// Sets vertical correction velocity and acceleration limits (m/s, m/s²).208// These values constrain the correction output of the PID controller.209// All values must be positive.210void D_set_correction_speed_accel_m(float decent_speed_max_ms, float climb_speed_max_ms, float accel_max_d_mss);211212// Returns maximum vertical acceleration in m/s² used for shaping the climb/descent trajectory.213float D_get_max_accel_mss() const { return _accel_max_d_mss; }214215// Returns maximum allowed positive (upward) position error in meters.216float get_pos_error_up_m() const { return _p_pos_d_m.get_error_min(); }217218// Returns maximum allowed negative (downward) position error in meters.219float get_pos_error_down_m() const { return _p_pos_d_m.get_error_max(); }220221// Returns maximum climb rate in cm/s.222// See get_max_speed_up_ms() for full details.223float get_max_speed_up_cms() const { return get_max_speed_up_ms() * 100.0; }224225// Returns maximum climb rate in m/s used for shaping the vertical trajectory.226float get_max_speed_up_ms() const { return _vel_max_up_ms; }227228/// Returns maximum descent rate in m/s (zero or positive).229float get_max_speed_down_ms() const { return _vel_max_down_ms; }230231// Initializes U-axis controller to current position, velocity, and acceleration, disallowing descent.232// Used for takeoff or hold scenarios where downward motion is prohibited.233void D_init_controller_no_descent();234235// Initializes U-axis controller to a stationary stopping point with zero velocity and acceleration.236// Used when the trajectory starts at rest but the initial altitude is unspecified.237// The resulting position target can be retrieved with get_pos_target_NED_m().238void D_init_controller_stopping_point();239240// Smoothly decays U-axis acceleration to zero over time while maintaining current vertical velocity.241// Reduces requested acceleration by ~95% every 0.5 seconds to avoid abrupt transitions.242// `throttle_setting` is used to determine whether to preserve positive acceleration in low-thrust cases.243void D_relax_controller(float throttle_setting);244245// Fully initializes the U-axis controller with current position, velocity, acceleration, and attitude.246// Used during standard controller activation when full state is known.247// Private function shared by other vertical initializers.248void D_init_controller();249250// Sets the desired vertical acceleration in m/s² using jerk-limited shaping.251// Smoothly transitions to the target acceleration from current kinematic state.252// Constraints: max acceleration and jerk set via D_set_max_speed_accel_m().253void input_accel_D_m(float accel_d_mss);254255// Sets desired vertical velocity and acceleration (m/s, m/s²) using jerk-limited shaping.256// Calculates required acceleration using current vertical kinematics.257// If `limit_output` is true, limits apply to the combined (desired + correction) command.258void input_vel_accel_D_m(float &vel_d_ms, float accel_d_mss, bool limit_output = true);259260// Generates a vertical trajectory using the given climb rate in cm/s and jerk-limited shaping.261// Adjusts the internal target altitude based on integrated climb rate.262// See D_set_pos_target_from_climb_rate_ms() for full details.263void D_set_pos_target_from_climb_rate_cms(float climb_rate_cms);264265// Generates a vertical trajectory using the given climb rate in m/s and jerk-limited shaping.266// Target altitude is updated over time by integrating the climb rate.267void D_set_pos_target_from_climb_rate_ms(float climb_rate_ms, bool ignore_descent_limit = false);268269// Sets vertical position, velocity, and acceleration in cm using jerk-limited shaping.270// See input_pos_vel_accel_D_m() for full details.271void input_pos_vel_accel_U_cm(float &pos_u_cm, float &vel_u_cms, float accel_u_cmss, bool limit_output = true);272273// Sets vertical position, velocity, and acceleration in meters using jerk-limited shaping.274// Calculates required acceleration using current state and constraints.275// If `limit_output` is true, limits are applied to combined (desired + correction) command.276void input_pos_vel_accel_D_m(float &pos_d_m, float &vel_d_ms, float accel_d_mss, bool limit_output = true);277278// Sets target altitude in cm using jerk-limited shaping to gradually move to the new position.279// See D_set_alt_target_with_slew_m() for full details.280void set_alt_target_with_slew_cm(float pos_u_cm);281282// Sets target altitude in meters using jerk-limited shaping.283void D_set_alt_target_with_slew_m(float pos_u_m);284285// Returns true if the U-axis controller has run in the last 5 control loop cycles.286bool D_is_active() const;287288// Runs the vertical (U-axis) position controller.289// Computes output acceleration based on position and velocity errors using PID correction.290// Feedforward velocity and acceleration are combined with corrections to produce a smooth vertical command.291// Desired position, velocity, and acceleration must be set before calling.292void D_update_controller();293294295296///297/// Accessors298///299300// Sets externally computed NED position, velocity, and acceleration in meters, m/s, and m/s².301// Use when path planning or shaping is done outside this controller.302void set_pos_vel_accel_NED_m(const Vector3p& pos_ned_m, const Vector3f& vel_ned_ms, const Vector3f& accel_ned_mss);303304// Sets externally computed NE position, velocity, and acceleration in meters, m/s, and m/s².305// Use when path planning or shaping is done outside this controller.306void set_pos_vel_accel_NE_m(const Vector2p& pos_ne_m, const Vector2f& vel_ne_ms, const Vector2f& accel_ne_mss);307308309/// Position310311// Returns the estimated position in NED frame, in meters relative to EKF origin.312const Vector3p& get_pos_estimate_NED_m() const { return _pos_estimate_ned_m; }313314// Returns estimated altitude above EKF origin in meters.315float get_pos_estimate_U_m() const { return -_pos_estimate_ned_m.z; }316317// Returns the target position in NED frame, in meters relative to EKF origin.318const Vector3p& get_pos_target_NED_m() const { return _pos_target_ned_m; }319320// Sets the desired NE position in meters relative to EKF origin.321void set_pos_desired_NE_m(const Vector2p& pos_desired_ne_m) { _pos_desired_ned_m.xy() = pos_desired_ne_m; }322323// Returns the desired position in NED frame, in meters relative to EKF origin.324const Vector3p& get_pos_desired_NED_m() const { return _pos_desired_ned_m; }325326// Returns target altitude above EKF origin in centimeters.327// See get_pos_target_U_m() for full details.328float get_pos_target_U_cm() const { return get_pos_target_U_m() * 100.0; }329330// Returns target altitude above EKF origin in meters.331float get_pos_target_U_m() const { return -_pos_target_ned_m.z; }332333// Sets desired altitude above EKF origin in centimeters.334// See set_pos_desired_U_m() for full details.335void set_pos_desired_U_cm(float pos_desired_u_cm) { set_pos_desired_U_m(pos_desired_u_cm * 0.01); }336337// Sets desired altitude above EKF origin in meters.338void set_pos_desired_U_m(float pos_desired_u_m) { _pos_desired_ned_m.z = -pos_desired_u_m; }339340// Returns desired altitude above EKF origin in centimeters.341// See get_pos_desired_U_m() for full details.342float get_pos_desired_U_cm() const { return get_pos_desired_U_m() * 100.0; }343344// Returns desired altitude above EKF origin in meters.345float get_pos_desired_U_m() const { return -_pos_desired_ned_m.z; }346347348/// Stopping Point349350// Computes NE stopping point in meters based on current position, velocity, and acceleration.351void get_stopping_point_NE_m(Vector2p &stopping_point_ne_m) const;352353// Computes vertical stopping point relative to EKF origin in meters, Down-positive. based on current velocity and acceleration.354void get_stopping_point_D_m(postype_t &stopping_point_d_m) const;355356357/// Position Error358359// Returns NED position error vector in meters between current and target positions.360const Vector3f get_pos_error_NED_m() const { return Vector3f{_p_pos_ne_m.get_error().x, _p_pos_ne_m.get_error().y, _p_pos_d_m.get_error()}; }361362// Returns total NE-plane position error magnitude in meters.363float get_pos_error_NE_m() const { return _p_pos_ne_m.get_error().length(); }364365// Returns vertical position error (altitude) in centimeters.366// See get_pos_error_D_m() for full details.367float get_pos_error_U_cm() const { return -get_pos_error_D_m() * 100.0; }368369// Returns vertical position error (altitude) in meters.370float get_pos_error_D_m() const { return _p_pos_d_m.get_error(); }371372373/// Velocity374375// Returns current velocity estimate in NED frame in m/s.376const Vector3f& get_vel_estimate_NED_ms() const { return _vel_estimate_ned_ms; }377378// Returns current velocity estimate (Up) in m/s.379float get_vel_estimate_U_ms() const { return -_vel_estimate_ned_ms.z; }380381// Sets desired velocity in NED frame in cm/s.382// See set_vel_desired_NED_ms() for full details.383void set_vel_desired_NEU_cms(const Vector3f &vel_desired_neu_cms) { set_vel_desired_NED_ms(Vector3f{vel_desired_neu_cms.x, vel_desired_neu_cms.y, -vel_desired_neu_cms.z} * 0.01); }384385// Sets desired velocity in NED frame in m/s.386void set_vel_desired_NED_ms(const Vector3f &vel_desired_ned_ms) { _vel_desired_ned_ms = vel_desired_ned_ms; }387388// Sets desired horizontal (NE) velocity in m/s.389void set_vel_desired_NE_ms(const Vector2f &vel_desired_ne_ms) { _vel_desired_ned_ms.xy() = vel_desired_ne_ms; }390391// Returns desired velocity in NEU frame in cm/s.392// See get_vel_desired_NED_ms() for full details.393const Vector3f get_vel_desired_NEU_cms() const { return Vector3f{_vel_desired_ned_ms.x, _vel_desired_ned_ms.y, -_vel_desired_ned_ms.z} * 100.0; }394395// Returns desired velocity in NED frame in m/s.396const Vector3f& get_vel_desired_NED_ms() const { return _vel_desired_ned_ms; }397398// Returns desired velocity (Up) in m/s.399float get_vel_desired_U_ms() const { return -_vel_desired_ned_ms.z; }400401// Returns velocity target in NEU frame in cm/s.402// See get_vel_target_NED_ms() for full details.403const Vector3f get_vel_target_NEU_cms() const { return Vector3f{_vel_target_ned_ms.x, _vel_target_ned_ms.y, -_vel_target_ned_ms.z} * 100.0; }404405// Returns velocity target in NED frame in m/s.406const Vector3f& get_vel_target_NED_ms() const { return _vel_target_ned_ms; }407408// Sets desired vertical velocity (Up) in m/s.409void set_vel_desired_D_ms(float vel_desired_d_ms) { _vel_desired_ned_ms.z = vel_desired_d_ms; }410411// Returns vertical velocity target (Up) in cm/s.412// See get_vel_target_U_ms() for full details.413float get_vel_target_U_cms() const { return get_vel_target_U_ms() * 100.0; }414415// Returns vertical velocity target (Up) in m/s.416float get_vel_target_U_ms() const { return -_vel_target_ned_ms.z; }417418419/// Acceleration420421// Sets desired horizontal acceleration in m/s².422void set_accel_desired_NE_mss(const Vector2f &accel_desired_ne_mss) { _accel_desired_ned_mss.xy() = accel_desired_ne_mss; }423424// Returns target NED acceleration in m/s².425const Vector3f& get_accel_target_NED_mss() const { return _accel_target_ned_mss; }426427428/// Terrain429430// Sets both the terrain altitude and terrain target to the same value431// (altitude above EKF origin in centimeters, Up-positive).432// See set_pos_terrain_target_D_m() for full description.433void set_pos_terrain_target_U_cm(float pos_terrain_target_u_cm) { set_pos_terrain_target_D_m(-pos_terrain_target_u_cm * 0.01); }434435// Sets both the terrain altitude and terrain target to the same value436// (relative to EKF origin in meters, Down-positive).437void set_pos_terrain_target_D_m(float pos_terrain_target_d_m) { _pos_terrain_target_d_m = pos_terrain_target_d_m; }438439// Initializes both the terrain altitude and terrain target to the same value440// (altitude above EKF origin in centimeters, Up-positive).441// See init_pos_terrain_D_m() for full description.442void init_pos_terrain_U_cm(float pos_terrain_u_cm);443444// Initializes both the terrain altitude and terrain target to the same value445// (relative to EKF origin in meters, Down-positive).446void init_pos_terrain_D_m(float pos_terrain_d_m);447448// Returns the current terrain altitude (Down-positive, relative to EKF origin, in meters).449float get_pos_terrain_D_m() const { return _pos_terrain_d_m; }450451452/// Offset453454#if AP_SCRIPTING_ENABLED455// Sets additional position, velocity, and acceleration offsets in meters (NED frame) for scripting.456// Offsets are added to the controller’s internal target.457// Used in LUA458bool set_posvelaccel_offset(const Vector3f &pos_offset_NED_m, const Vector3f &vel_offset_NED_ms, const Vector3f &accel_offset_NED_mss);459460// Retrieves current scripted offsets in meters (NED frame).461// Used in LUA462463bool get_posvelaccel_offset(Vector3f &pos_offset_NED_m, Vector3f &vel_offset_NED_ms, Vector3f &accel_offset_NED_mss);464465// Retrieves current target velocity (NED frame, m/s) including any scripted offset.466// Used in LUA467bool get_vel_target(Vector3f &vel_target_NED_ms);468469// Retrieves current target acceleration (NED frame, m/s²) including any scripted offset.470// Used in LUA471bool get_accel_target(Vector3f &accel_target_NED_mss);472#endif473474// Sets NE offset targets in meters, m/s, and m/s².475void set_posvelaccel_offset_target_NE_m(const Vector2p& pos_offset_target_ne_m, const Vector2f& vel_offset_target_ne_ms, const Vector2f& accel_offset_target_ne_mss);476477// Sets vertical offset targets (m, m/s, m/s²) relative to EKF origin in meters, Down-positive.478void set_posvelaccel_offset_target_D_m(float pos_offset_target_d_m, float vel_offset_target_d_ms, float accel_offset_target_d_mss);479480// Returns current NED position offset in meters.481const Vector3p& get_pos_offset_NED_m() const { return _pos_offset_ned_m; }482483// Returns current NED velocity offset in m/s.484const Vector3f& get_vel_offset_NED_ms() const { return _vel_offset_ned_ms; }485486// Returns current NED acceleration offset in m/s².487const Vector3f& get_accel_offset_NED_mss() const { return _accel_offset_ned_mss; }488489// Sets vertical position offset in meters relative to EKF origin in meters, Down-positive.490void set_pos_offset_D_m(float pos_offset_d_m) { _pos_offset_ned_m.z = pos_offset_d_m; }491492// Returns vertical position offset in meters relative to EKF origin in meters, Down-positive.493float get_pos_offset_U_m() const { return -_pos_offset_ned_m.z; }494495// Returns vertical velocity offset in m/s.496float get_vel_offset_D_ms() const { return _vel_offset_ned_ms.z; }497498// Returns vertical acceleration offset in m/s².499float get_accel_offset_D_mss() const { return _accel_offset_ned_mss.z; }500501/// Outputs502503// Returns desired roll angle in radians for the attitude controller504float get_roll_rad() const { return _roll_target_rad; }505506// Returns desired pitch angle in radians for the attitude controller.507float get_pitch_rad() const { return _pitch_target_rad; }508509// Returns desired yaw angle in radians for the attitude controller.510float get_yaw_rad() const { return _yaw_target_rad; }511512// Returns desired yaw rate in radians/second for the attitude controller.513float get_yaw_rate_rads() const { return _yaw_rate_target_rads; }514515// Returns desired roll angle in centidegrees for the attitude controller.516// See get_roll_rad() for full details.517float get_roll_cd() const { return rad_to_cd(_roll_target_rad); }518519// Returns desired pitch angle in centidegrees for the attitude controller.520// See get_pitch_rad() for full details.521float get_pitch_cd() const { return rad_to_cd(_pitch_target_rad); }522523// Returns desired thrust direction as a unit vector in the body frame.524Vector3f get_thrust_vector() const;525526// Returns bearing from current position to position target in radians.527// 0 = North, positive = clockwise.528float get_bearing_to_target_rad() const;529530// Returns the maximum allowed roll/pitch angle in radians.531float get_lean_angle_max_rad() const;532533// Overrides the maximum allowed roll/pitch angle in radians.534// A value of 0 reverts to using the ANGLE_MAX parameter.535void set_lean_angle_max_rad(float angle_max_rad) { _angle_max_override_rad = angle_max_rad; }536537// Overrides the maximum allowed roll/pitch angle in degrees.538// See set_lean_angle_max_rad() for full details.539void set_lean_angle_max_deg(const float angle_max_deg) { set_lean_angle_max_rad(radians(angle_max_deg)); }540541// Overrides the maximum allowed roll/pitch angle in centidegrees.542// See set_lean_angle_max_rad() for full details.543void set_lean_angle_max_cd(const float angle_max_cd) { set_lean_angle_max_rad(cd_to_rad(angle_max_cd)); }544545/// Other546547// Returns reference to the NE position P controller.548AC_P_2D& NE_get_pos_p() { return _p_pos_ne_m; }549550// Returns reference to the D (vertical) position P controller.551AC_P_1D& D_get_pos_p() { return _p_pos_d_m; }552553// Returns reference to the NE velocity PID controller.554AC_PID_2D& NE_get_vel_pid() { return _pid_vel_ne_m; }555556// Returns reference to the D (vertical) velocity PID controller.557AC_PID_Basic& D_get_vel_pid() { return _pid_vel_d_m; }558559// Returns reference to the D acceleration PID controller.560AC_PID& D_get_accel_pid() { return _pid_accel_d_m; }561562// Marks that NE acceleration has been externally limited.563// Prevents I-term windup by storing the current target direction.564void NE_set_externally_limited() { _limit_vector_ned.x = _accel_target_ned_mss.x; _limit_vector_ned.y = _accel_target_ned_mss.y; }565566// Converts lean angles (rad) to NED acceleration in m/s².567Vector3f lean_angles_rad_to_accel_NED_mss(const Vector3f& att_target_euler_rad) const;568569// Writes position controller diagnostic logs (PSCN, PSCE, etc).570void write_log();571572// Performs pre-arm checks for position control parameters and EKF readiness.573// Returns false if failure_msg is populated.574bool pre_arm_checks(const char *param_prefix,575char *failure_msg,576const uint8_t failure_msg_len);577578// Enables or disables vibration compensation mode.579// When enabled, disables use of horizontal velocity estimates.580void set_vibe_comp(bool on_off) { _vibe_comp_enabled = on_off; }581582// Reset handling method583enum class EKFResetMethod : uint8_t {584MoveTarget = 0, // the target position is reset so the vehicle does not physically move585MoveVehicle = 1 // the target position is smoothly transitioned so the vehicle moves to its previous position coordinates586};587void set_reset_handling_method(EKFResetMethod reset_method) { _ekf_reset_method = reset_method; }588589// Returns confidence (0–1) in vertical control authority based on output usage.590// Used to assess throttle margin and PID effectiveness.591float get_vel_D_control_ratio() const { return constrain_float(_vel_d_control_ratio, 0.0f, 1.0f); }592593// Returns lateral distance to closest point on active trajectory in meters.594// Used to assess horizontal deviation from path.595float crosstrack_error_m() const;596597// Resets NED position controller state to prevent transients when exiting standby.598// Zeros I-terms and aligns targets to current position.599void NED_standby_reset();600601// Returns measured vertical (Down) acceleration in m/s² (Earth frame, gravity-compensated).602// Positive = downward acceleration.603float get_estimated_accel_D_mss() const { return _ahrs.get_accel_ef().z + GRAVITY_MSS; }604605// Returns measured vertical (Up) acceleration in m/s² (Earth frame, gravity-compensated).606// Positive = upward acceleration.607float get_estimated_accel_U_mss() const { return -get_estimated_accel_D_mss(); }608609// Returns true if the requested forward pitch is limited by the configured tilt constraint.610bool get_fwd_pitch_is_limited() const;611612// Sets artificial NE position disturbance in meters.613void set_disturb_pos_NE_m(const Vector2f& disturb_pos_m) { _disturb_pos_ne_m = disturb_pos_m; }614615// Sets artificial NE velocity disturbance in m/s.616void set_disturb_vel_NE_ms(const Vector2f& disturb_vel_ms) { _disturb_vel_ne_ms = disturb_vel_ms; }617618// Logs position controller state along the North axis to PSCN..619// Logs desired, target, and actual position [m], velocity [m/s], and acceleration [m/s²].620static void Write_PSCN(float pos_desired_m, float pos_target_m, float pos_m, float vel_desired_ms, float vel_target_ms, float vel_ms, float accel_desired_mss, float accel_target_mss, float accel_mss);621622// Logs position controller state along the East axis to PSCE.623// Logs desired, target, and actual values for position [m], velocity [m/s], and acceleration [m/s²].624static void Write_PSCE(float pos_desired_m, float pos_target_m, float pos_m, float vel_desired_ms, float vel_target_ms, float vel_ms, float accel_desired_mss, float accel_target_mss, float accel_mss);625626// Logs position controller state along the Down (vertical) axis to PSCD.627// Logs desired, target, and actual values for position [m], velocity [m/s], and acceleration [m/s²].628static void Write_PSCD(float pos_desired_m, float pos_target_m, float pos_m, float vel_desired_ms, float vel_target_ms, float vel_ms, float accel_desired_mss, float accel_target_mss, float accel_mss);629630// Logs offset tracking along the North axis to PSON.631// Logs target and actual offset for position [m], velocity [m/s], and acceleration [m/s²].632static void Write_PSON(float pos_target_offset_m, float pos_offset_m, float vel_target_offset_ms, float vel_offset_ms, float accel_target_offset_mss, float accel_offset_mss);633634// Logs offset tracking along the East axis to PSOE.635// Logs target and actual offset for position [m], velocity [m/s], and acceleration [m/s²].636static void Write_PSOE(float pos_target_offset_m, float pos_offset_m, float vel_target_offset_ms, float vel_offset_ms, float accel_target_offset_mss, float accel_offset_mss);637638// Logs offset tracking along the Down axis to PSOD.639// Logs target and actual offset for position [m], velocity [m/s], and acceleration [m/s²].640static void Write_PSOD(float pos_target_offset_m, float pos_offset_m, float vel_target_offset_ms, float vel_offset_ms, float accel_target_offset_mss, float accel_offset_mss);641642// Logs terrain-following offset tracking along the Down axis to PSOT.643// Logs target and actual offset for position [m], velocity [m/s], and acceleration [m/s²].644static void Write_PSOT(float pos_target_offset_m, float pos_offset_m, float vel_target_offset_ms, float vel_offset_ms, float accel_target_offset_mss, float accel_offset_mss);645646// perform any required parameter conversions647void convert_parameters();648649// Returns pointer to the global AC_PosControl singleton.650static AC_PosControl *get_singleton(void) { return _singleton; }651652static const struct AP_Param::GroupInfo var_info[];653654protected:655656// Calculates vertical throttle using vibration-resistant feedforward estimation.657// Returns throttle output using manual feedforward gain for vibration compensation mode.658// Integrator is adjusted using velocity error when PID is being overridden.659float get_throttle_with_vibration_override();660661// Converts horizontal acceleration (m/s²) to roll/pitch lean angles in radians.662void accel_NE_mss_to_lean_angles_rad(float accel_n_mss, float accel_e_mss, float& roll_target_rad, float& pitch_target_rad) const;663664// Converts current target lean angles to NE acceleration in m/s².665void lean_angles_to_accel_NE_mss(float& accel_n_mss, float& accel_e_mss) const;666667// Computes desired yaw and yaw rate based on the NE acceleration and velocity vectors.668// Aligns yaw with the direction of travel if speed exceeds 5% of maximum.669void calculate_yaw_and_rate_yaw();670671// Computes scaling factor to increase max vertical accel/jerk if vertical speed exceeds configured limits.672float calculate_overspeed_gain();673674675/// Terrain Following676677// Initializes terrain position, velocity, and acceleration to match the terrain target.678void init_terrain();679680// Updates terrain estimate (_pos_terrain_d_m) toward target using filter time constants.681void update_terrain();682683684/// Offsets685686// Initializes NE position/velocity/acceleration offsets to match their respective targets.687void NE_init_offsets();688689// Initializes vertical (D) offsets to match their respective targets.690void D_init_offsets();691692// Updates NE offsets by gradually moving them toward their targets.693void NE_update_offsets();694695// Updates vertical (D) offsets by gradually moving them toward their targets.696void D_update_offsets();697698// Initializes tracking of NE EKF position resets.699void NE_init_ekf_reset();700701// Handles NE position reset detection and response (e.g., clearing accumulated errors).702void NE_handle_ekf_reset();703704// Initializes tracking of vertical (D) EKF resets.705void D_init_ekf_reset();706707// Handles the vertical (D) EKF reset detection and response.708void D_handle_ekf_reset();709710// references to inertial nav and ahrs libraries711AP_AHRS_View& _ahrs;712const class AP_Motors& _motors;713AC_AttitudeControl& _attitude_control;714715// parameters716AP_Float _lean_angle_max_deg; // Maximum autopilot commanded angle (in degrees). Set to zero for Angle Max717AP_Float _shaping_jerk_ne_msss; // Jerk limit of the ne kinematic path generation in m/s³ used to determine how quickly the aircraft varies the acceleration target718AP_Float _shaping_jerk_d_msss; // Jerk limit of the u kinematic path generation in m/s³ used to determine how quickly the aircraft varies the acceleration target719AC_P_2D _p_pos_ne_m; // XY axis position controller to convert target distance (m) to target velocity (m/s)720AC_P_1D _p_pos_d_m; // Z axis position controller to convert target altitude (m) to target climb rate (m/s)721AC_PID_2D _pid_vel_ne_m; // XY axis velocity controller to convert target velocity (m/s) to target acceleration (m/s²)722AC_PID_Basic _pid_vel_d_m; // Z axis velocity controller to convert target climb rate (m/s) to target acceleration (m/s²)723AC_PID _pid_accel_d_m; // Z axis acceleration controller to convert target acceleration (in units of gravity) to normalised throttle output724725// internal variables726float _dt_s; // time difference (in seconds) since the last loop time727uint32_t _last_update_ne_ticks; // ticks of last NE_update_controller call728uint32_t _last_update_d_ticks; // ticks of last update_z_controller call729float _vel_max_ne_ms; // max horizontal speed in m/s used for kinematic shaping730float _vel_max_up_ms; // max climb rate in m/s used for kinematic shaping731float _vel_max_down_ms; // max descent rate in m/s used for kinematic shaping732float _accel_max_ne_mss; // max horizontal acceleration in m/s² used for kinematic shaping733float _accel_max_d_mss; // max vertical acceleration in m/s² used for kinematic shaping734float _jerk_max_ne_msss; // Jerk limit of the ne kinematic path generation in m/s³ used to determine how quickly the aircraft varies the acceleration target735float _jerk_max_d_msss; // Jerk limit of the z kinematic path generation in m/s³ used to determine how quickly the aircraft varies the acceleration target736float _vel_d_control_ratio = 2.0f;// confidence that we have control in the vertical axis737Vector2f _disturb_pos_ne_m; // position disturbance generated by system ID mode738Vector2f _disturb_vel_ne_ms; // velocity disturbance generated by system ID mode739float _ne_control_scale_factor = 1.0; // single loop scale factor for XY control740741// output from controller742float _roll_target_rad; // desired roll angle in radians calculated by position controller743float _pitch_target_rad; // desired roll pitch in radians calculated by position controller744float _yaw_target_rad; // desired yaw in radians calculated by position controller745float _yaw_rate_target_rads; // desired yaw rate in radians per second calculated by position controller746747// position controller internal variables748Vector3p _pos_estimate_ned_m; // estimated location, frame NED in m relative to the EKF origin.749Vector3p _pos_desired_ned_m; // desired location, frame NED in m relative to the EKF origin. This is equal to the _pos_target_ned_m minus offsets750Vector3p _pos_target_ned_m; // target location, frame NED in m relative to the EKF origin. This is equal to the _pos_desired_ned_m plus offsets751Vector3f _vel_estimate_ned_ms; // estimated velocity in NED m/s752Vector3f _vel_desired_ned_ms; // desired velocity in NED m/s753Vector3f _vel_target_ned_ms; // velocity target in NED m/s calculated by pos_to_rate step754Vector3f _accel_desired_ned_mss; // desired acceleration in NED m/s² (feed forward)755Vector3f _accel_target_ned_mss; // acceleration target in NED m/s²756// todo: seperate the limit vector into ne and u. ne is based on acceleration while u is set +-1 based on throttle saturation. Together they don't form a direction vector because the units are different.757Vector3f _limit_vector_ned; // the direction that the position controller is limited, zero when not limited758759// terrain handling variables760float _pos_terrain_target_d_m; // position terrain target in m relative to the EKF origin in NED frame761float _pos_terrain_d_m; // position terrain in m from the EKF origin in NED frame. This terrain moves towards _pos_terrain_target_d_m762float _vel_terrain_d_ms; // velocity terrain in NED m/s calculated by pos_to_rate step. This terrain moves towards _vel_terrain_target763float _accel_terrain_d_mss; // acceleration terrain in NED m/s²764765// offset handling variables766Vector3p _pos_offset_target_ned_m; // position offset target in m relative to the EKF origin in NED frame767Vector3p _pos_offset_ned_m; // position offset in m from the EKF origin in NED frame. This offset moves towards _pos_offset_target_ned_m768Vector3f _vel_offset_target_ned_ms; // velocity offset target in m/s in NED frame769Vector3f _vel_offset_ned_ms; // velocity offset in NED m/s calculated by pos_to_rate step. This offset moves towards _vel_offset_target_ned_ms770Vector3f _accel_offset_target_ned_mss; // acceleration offset target in m/s² in NED frame771Vector3f _accel_offset_ned_mss; // acceleration offset in NED m/s²772uint32_t _posvelaccel_offset_target_ne_ms; // system time that pos, vel, accel targets were set (used to implement timeouts)773uint32_t _posvelaccel_offset_target_d_ms; // system time that pos, vel, accel targets were set (used to implement timeouts)774775// ekf reset handling776uint32_t _ekf_ne_reset_ms; // system time of last recorded ekf ne position reset777uint32_t _ekf_d_reset_ms; // system time of last recorded ekf altitude reset778EKFResetMethod _ekf_reset_method = EKFResetMethod::MoveTarget; // EKF reset handling method. Loiter should use MoveTarget, Auto should use MoveVehicle779780// high vibration handling781bool _vibe_comp_enabled; // true when high vibration compensation is on782783// angle max override, if zero then use ANGLE_MAX parameter784float _angle_max_override_rad;785786// return true if on a real vehicle or SITL with lock-step scheduling787bool has_good_timing(void) const;788789private:790// Internal log writer for PSCx (North, East, Down tracking).791// Reduces duplication between Write_PSCN, PSCE, and PSCD.792// Used for logging desired/target/actual position, velocity, and acceleration per axis.793static void Write_PSCx(LogMessages ID, float pos_desired_m, float pos_target_m, float pos_m,794float vel_desired_ms, float vel_target_ms, float vel_ms,795float accel_desired_mss, float accel_target_mss, float accel_mss);796797// Internal log writer for PSOx (North, East, Down tracking).798// Reduces duplication between Write_PSON, PSOE, and PSOD.799// Used for logging the target/actual position, velocity, and acceleration offset per axis.800static void Write_PSOx(LogMessages id, float pos_target_offset_m, float pos_offset_m,801float vel_target_offset_ms, float vel_offset_ms,802float accel_target_offset_mss, float accel_offset_mss);803804// singleton805static AC_PosControl *_singleton;806};807808809