/*1This program is free software: you can redistribute it and/or modify2it under the terms of the GNU General Public License as published by3the Free Software Foundation, either version 3 of the License, or4(at your option) any later version.56This program is distributed in the hope that it will be useful,7but WITHOUT ANY WARRANTY; without even the implied warranty of8MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the9GNU General Public License for more details.1011You should have received a copy of the GNU General Public License12along with this program. If not, see <http://www.gnu.org/licenses/>.13*/14#pragma once15#include "AP_Follow_config.h"1617#if AP_FOLLOW_ENABLED1819#include <AP_Common/AP_Common.h>20#include <AP_Common/Location.h>21#include <AP_HAL/AP_HAL.h>22#include <AP_Param/AP_Param.h>23#include <AP_Math/AP_Math.h>24#include <GCS_MAVLink/GCS_MAVLink.h>25#include <AC_PID/AC_P.h>26#include <AP_RTC/JitterCorrection.h>2728//==============================================================================29// AP_Follow Class30// Target Following Logic for ArduPilot Vehicles31//==============================================================================3233class AP_Follow34{3536public:37//==========================================================================38// Public Enums39//==========================================================================4041// enum for FOLLOW_OPTIONS parameter42enum class Option {43MOUNT_FOLLOW_ON_ENTER = 144};4546// enum for YAW_BEHAVE parameter47enum YawBehave {48YAW_BEHAVE_NONE = 0,49YAW_BEHAVE_FACE_LEAD_VEHICLE = 1,50YAW_BEHAVE_SAME_AS_LEAD_VEHICLE = 2,51YAW_BEHAVE_DIR_OF_FLIGHT = 352};5354//==========================================================================55// Constructor and Singleton Access56//==========================================================================5758// constructor59AP_Follow();6061// enable as singleton62static AP_Follow *get_singleton(void) {63return _singleton;64}6566// returns true if library is enabled67bool enabled() const { return _enabled; }6869// set which target to follow70void set_target_sysid(uint8_t sysid) { _sysid.set(sysid); }7172// Resets the follow mode offsets to zero if they were automatically initialized. Should be called when exiting Follow mode.73void clear_offsets_if_required();7475//==========================================================================76// Target Estimation and Tracking Methods77//==========================================================================7879// Returns true if following is enabled and a recent target location update has been received.80bool have_target() const;8182// Projects the target’s position, velocity, and heading forward using the latest updates, smoothing with input shaping if necessary83void update_estimates();8485// Retrieves the estimated target position, velocity, and acceleration in the NED frame relative to the origin (units: meters and meters/second).86bool get_target_pos_vel_accel_NED_m(Vector3p &pos_ned_m, Vector3f &vel_ned_ms, Vector3f &accel_ned_mss) const;8788// Retrieves the estimated target position, velocity, and acceleration in the NED frame, including configured positional offsets.89bool get_ofs_pos_vel_accel_NED_m(Vector3p &pos_ofs_ned_m, Vector3f &vel_ofs_ned_ms, Vector3f &accel_ofs_ned_mss) const;9091// Retrieves the estimated target heading and heading rate in radians.92bool get_heading_heading_rate_rad(float &heading_rad, float &heading_rate_rads) const;9394//==========================================================================95// Global Location and Velocity Retrieval (LUA Bindings)96//==========================================================================9798// Retrieves the estimated global location and velocity of the target99bool get_target_location_and_velocity(Location &loc, Vector3f &vel_ned);100101// Retrieves the estimated global location including configured positional offsets and velocity of the target, (for LUA bindings).102bool get_target_location_and_velocity_ofs(Location &loc, Vector3f &vel_ned);103104// Retrieves the estimated target heading in degrees (0° = North, 90° = East) for LUA bindings.105bool get_target_heading_deg(float &heading);106107// Retrieves the estimated target heading rate in degrees per second.108bool get_target_heading_rate_degs(float &_target_heading_rate_degs);109110// Retrieves the distance vector to the target, the distance vector including configured offsets, and the target’s velocity in the NED frame (units: meters).111bool get_target_dist_and_vel_NED_m(Vector3f &dist_ned, Vector3f &dist_with_ofs, Vector3f &vel_ned);112113//==========================================================================114// Accessor Methods115//==========================================================================116117// get target sysid as a 32 bit number to allow for future expansion of MAV_SYSID118uint32_t get_target_sysid() const { return (uint32_t)_sysid.get(); }119120// get position controller. this controller is not used within this library but it is convenient to hold it here121const AC_P& get_pos_p() const { return _p_pos; }122123// get user defined yaw behaviour124YawBehave get_yaw_behave() const { return (YawBehave)_yaw_behave.get(); }125126// initialise offsets to provided distance vector to other vehicle (in meters in NED frame) if required127void init_offsets_if_required();128129//==========================================================================130// MAVLink Message Handling131//==========================================================================132133// parse mavlink messages which may hold target's position, velocity and attitude134void handle_msg(const mavlink_message_t &msg);135136//==========================================================================137// GCS Reporting Methods138//==========================================================================139140// get horizontal distance to target (including offset) in meters (for reporting purposes)141float get_distance_to_target_m() const { return _dist_to_target_m; }142143// get bearing to target (including offset) in degrees (for reporting purposes)144float get_bearing_to_target_deg() const { return _bearing_to_target_deg; }145146// get system time of last position update147// LUA bindings148uint32_t get_last_update_ms() const { return _last_location_update_ms; }149150// returns true if a follow option enabled151bool option_is_enabled(Option option) const { return (_options.get() & (uint16_t)option) != 0; }152153//==========================================================================154// Parameter Group Info155//==========================================================================156157// parameter list158static const struct AP_Param::GroupInfo var_info[];159160private:161//==========================================================================162// Private Helper Functions and Singleton163//==========================================================================164165// Singleton instance of the AP_Follow class.166static AP_Follow *_singleton;167168// returns true if we should extract information from msg169bool should_handle_message(const mavlink_message_t &msg) const;170171// Checks whether the current estimate should be reset based on position and velocity errors.172bool estimate_error_too_large() const;173174// Calculates max velocity change under trapezoidal or triangular acceleration profile (jerk-limited).175float calc_max_velocity_change(float accel_max, float jerk_max, float timeout_sec) const;176177// Rotates a 3D vector clockwise by the specified angle in degrees.178Vector3f rotate_vector(const Vector3f &vec, float angle_deg) const;179180// Resets the recorded distance and bearing to the target to zero.181void clear_dist_and_bearing_to_target();182void update_dist_and_bearing_to_target();183184// handle various mavlink messages supplying position:185bool handle_global_position_int_message(const mavlink_message_t &msg);186bool handle_follow_target_message(const mavlink_message_t &msg);187188// write out an onboard-log message to help diagnose follow problems:189void Log_Write_FOLL();190191//==========================================================================192// Parameters193//==========================================================================194195AP_Int8 _enabled; // 1 = Follow mode is enabled; 0 = disabled196AP_Int16 _sysid; // MAVLink system ID of the target (0 = auto-select first sender)197AP_Float _dist_max_m; // Maximum allowed distance to target in meters; if exceeded, estimation is rejected198AP_Int8 _offset_type; // Offset frame type: 0 = NED, 1 = relative to lead vehicle heading199AP_Vector3f _offset_m; // Offset from lead vehicle (meters), in NED or FRD frame depending on _offset_type200AP_Int8 _yaw_behave; // Yaw behavior mode (see YawBehave enum)201AP_Enum<Location::AltFrame> _alt_type; // altitude source for follow mode202AC_P _p_pos; // Position error P-controller for optional altitude following203AP_Int16 _options; // Bitmask of follow behavior options (e.g., mount follow, etc.)204AP_Float _timeout; // position estimate timeout after x milliseconds205206AP_Float _accel_max_ne_mss; // Max horizontal acceleration for kinematic shaping (m/s²)207AP_Float _jerk_max_ne_msss; // Max horizontal jerk for kinematic shaping (m/s³)208AP_Float _accel_max_d_mss; // Max vertical acceleration for kinematic shaping (m/s²)209AP_Float _jerk_max_d_msss; // Max vertical jerk for kinematic shaping (m/s³)210AP_Float _accel_max_h_degss; // Max angular acceleration for heading shaping (deg/s²)211AP_Float _jerk_max_h_degsss; // Max angular jerk for heading shaping (deg/s³)212213//==========================================================================214// Internal State Variables215//==========================================================================216217uint32_t _last_location_update_ms; // Time of last target position update (ms)218uint32_t _last_estimation_update_ms; // Time of last estimate update (ms)219220Vector3p _target_pos_ned_m; // Latest received target position (NED frame, meters)221Vector3f _target_vel_ned_ms; // Latest received target velocity (NED frame, m/s)222Vector3f _target_accel_ned_mss; // Latest received target acceleration (NED frame, m/s²)223float _target_heading_deg; // Latest received target heading (degrees, 0 = North)224float _target_heading_rate_degs; // Latest received target yaw rate (deg/s)225226bool _estimate_valid; // True if internal estimate is valid and in sync with updates227Vector3p _estimate_pos_ned_m; // Estimated target position (NED frame, meters)228Vector3f _estimate_vel_ned_ms; // Estimated target velocity (NED frame, m/s)229Vector3f _estimate_accel_ned_mss; // Estimated target acceleration (NED frame, m/s²)230float _estimate_heading_rad; // Estimated heading (radians, range -PI to PI)231float _estimate_heading_rate_rads; // Estimated heading rate (rad/s)232float _estimate_heading_accel_radss; // Estimated heading acceleration (rad/s²)233234Vector3p _ofs_estimate_pos_ned_m; // Estimated position with offsets applied (NED frame)235Vector3f _ofs_estimate_vel_ned_ms; // Estimated velocity with offsets applied (NED frame)236Vector3f _ofs_estimate_accel_ned_mss; // Estimated acceleration with offsets applied (NED frame)237238bool _automatic_sysid; // True if target sysid was automatically selected239int16_t _sysid_used; // Currently active sysid used for updates240float _dist_to_target_m; // Horizontal distance to target, for reporting (meters)241float _bearing_to_target_deg; // Bearing to target from vehicle (degrees, 0 = North)242bool _offsets_were_zero; // True if initial offset was zero before being initialized243bool _using_follow_target; // True if FOLLOW_TARGET messages are being used instead of GLOBAL_POSITION_INT244245HAL_Semaphore _follow_sem; // semaphore for multi-thread use of update_estimates and LUA calls246247//==========================================================================248// Utilities249//==========================================================================250251// Jitter correction helper for smoothing offboard timestamps.252JitterCorrection _jitter{500};253};254255//==============================================================================256// AP_Follow Accessor257//==============================================================================258259namespace AP {260AP_Follow &follow();261};262263#endif264265266