LCOV - code coverage report
Current view: top level - AP_Follow - AP_Follow.h (source / functions) Hit Total Coverage
Test: lcov.info Lines: 8 11 72.7 %
Date: 2026-09-09 11:02:08 Functions: 7 10 70.0 %

          Line data    Source code
       1             : /*
       2             :    This program is free software: you can redistribute it and/or modify
       3             :    it under the terms of the GNU General Public License as published by
       4             :    the Free Software Foundation, either version 3 of the License, or
       5             :    (at your option) any later version.
       6             : 
       7             :    This program is distributed in the hope that it will be useful,
       8             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
       9             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      10             :    GNU General Public License for more details.
      11             : 
      12             :    You should have received a copy of the GNU General Public License
      13             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      14             :  */
      15             : #pragma once
      16             : #include "AP_Follow_config.h"
      17             : 
      18             : #if AP_FOLLOW_ENABLED
      19             : 
      20             : #include <AP_Common/AP_Common.h>
      21             : #include <AP_Common/Location.h>
      22             : #include <AP_HAL/AP_HAL.h>
      23             : #include <AP_Param/AP_Param.h>
      24             : #include <AP_Math/AP_Math.h>
      25             : #include <GCS_MAVLink/GCS_MAVLink.h>
      26             : #include <AC_PID/AC_P.h>
      27             : #include <AP_RTC/JitterCorrection.h>
      28             : 
      29             : //==============================================================================
      30             : // AP_Follow Class
      31             : // Target Following Logic for ArduPilot Vehicles
      32             : //==============================================================================
      33             : 
      34             : class AP_Follow
      35             : {
      36             : 
      37             : public:
      38             :     //==========================================================================
      39             :     // Public Enums
      40             :     //==========================================================================
      41             : 
      42             :     // enum for FOLLOW_OPTIONS parameter
      43             :     enum class Option {
      44             :         MOUNT_FOLLOW_ON_ENTER = 1
      45             :     };
      46             : 
      47             :     // enum for YAW_BEHAVE parameter
      48             :     enum YawBehave {
      49             :         YAW_BEHAVE_NONE = 0,
      50             :         YAW_BEHAVE_FACE_LEAD_VEHICLE = 1,
      51             :         YAW_BEHAVE_SAME_AS_LEAD_VEHICLE = 2,
      52             :         YAW_BEHAVE_DIR_OF_FLIGHT = 3
      53             :     };
      54             : 
      55             :     //==========================================================================
      56             :     // Constructor and Singleton Access
      57             :     //==========================================================================
      58             : 
      59             :     // constructor
      60             :     AP_Follow();
      61             : 
      62             :     // enable as singleton
      63     2645702 :     static AP_Follow *get_singleton(void) {
      64     2645702 :         return _singleton;
      65             :     }
      66             : 
      67             :     // returns true if library is enabled
      68       87756 :     bool enabled() const { return _enabled; }
      69             : 
      70             :     // set which target to follow
      71           0 :     void set_target_sysid(uint8_t sysid) { _sysid.set(sysid); }
      72             : 
      73             :     // Resets the follow mode offsets to zero if they were automatically initialized. Should be called when exiting Follow mode.
      74             :     void clear_offsets_if_required();
      75             : 
      76             :     //==========================================================================
      77             :     // Target Estimation and Tracking Methods
      78             :     //==========================================================================
      79             : 
      80             :     // Returns true if a usable estimate of the configured target is available.  Every accessor
      81             :     // below is gated on this, but a true return does not guarantee they will succeed, so callers
      82             :     // must still check what each accessor returns.
      83             :     bool have_target() const;
      84             : 
      85             :     // Projects the target’s position, velocity, and heading forward using the latest updates, smoothing with input shaping if necessary 
      86             :     void update_estimates();
      87             : 
      88             :     // Retrieves the estimated target position, velocity, and acceleration in the NED frame relative to the origin (units: meters and meters/second).
      89             :     bool get_target_pos_vel_accel_NED_m(Vector3p &pos_ned_m, Vector3f &vel_ned_ms, Vector3f &accel_ned_mss) const;
      90             : 
      91             :     // Retrieves the estimated target position, velocity, and acceleration in the NED frame, including configured positional offsets.
      92             :     bool get_ofs_pos_vel_accel_NED_m(Vector3p &pos_ofs_ned_m, Vector3f &vel_ofs_ned_ms, Vector3f &accel_ofs_ned_mss) const;
      93             : 
      94             :     // Retrieves the estimated target heading and heading rate in radians.
      95             :     bool get_heading_heading_rate_rad(float &heading_rad, float &heading_rate_rads) const;
      96             : 
      97             :     //==========================================================================
      98             :     // Global Location and Velocity Retrieval (LUA Bindings)
      99             :     //==========================================================================
     100             : 
     101             :     // Retrieves the estimated global location and velocity of the target
     102             :     bool get_target_location_and_velocity(Location &loc, Vector3f &vel_ned);
     103             : 
     104             :     // Retrieves the estimated global location including configured positional offsets and velocity of the target,  (for LUA bindings).
     105             :     bool get_target_location_and_velocity_ofs(Location &loc, Vector3f &vel_ned);
     106             : 
     107             :     // Retrieves the estimated target heading in degrees (0° = North, 90° = East) for LUA bindings.
     108             :     bool get_target_heading_deg(float &heading);
     109             : 
     110             :     // Retrieves the estimated target heading rate in degrees per second.
     111             :     bool get_target_heading_rate_degs(float &_target_heading_rate_degs);
     112             : 
     113             :     // Retrieves the distance vector to the target, the distance vector including configured offsets, and the target’s velocity in the NED frame (units: meters).
     114             :     bool get_target_dist_and_vel_NED_m(Vector3f &dist_ned, Vector3f &dist_with_ofs, Vector3f &vel_ned);
     115             : 
     116             :     //==========================================================================
     117             :     // Accessor Methods
     118             :     //==========================================================================
     119             : 
     120             :     // get target sysid as a 32 bit number to allow for future expansion of MAV_SYSID
     121           7 :     uint32_t get_target_sysid() const { return (uint32_t)_sysid.get(); }
     122             : 
     123             :     // get position controller.  this controller is not used within this library but it is convenient to hold it here
     124           0 :     const AC_P& get_pos_p() const { return _p_pos; }
     125             : 
     126             :     // get user defined yaw behaviour
     127       15272 :     YawBehave get_yaw_behave() const { return (YawBehave)_yaw_behave.get(); }
     128             : 
     129             :     // initialise offsets to provided distance vector to other vehicle (in meters in NED frame) if required
     130             :     void init_offsets_if_required();
     131             : 
     132             :     //==========================================================================
     133             :     // MAVLink Message Handling
     134             :     //==========================================================================
     135             : 
     136             :     // parse mavlink messages which may hold target's position, velocity and attitude
     137             :     void handle_msg(const mavlink_message_t &msg);
     138             : 
     139             :     //==========================================================================
     140             :     // GCS Reporting Methods
     141             :     //==========================================================================
     142             : 
     143             :     // get horizontal distance to target (including offset) in meters (for reporting purposes)
     144         243 :     float get_distance_to_target_m() const { return _dist_to_target_m; }
     145             : 
     146             :     // get bearing to target (including offset) in degrees (for reporting purposes)
     147         243 :     float get_bearing_to_target_deg() const { return _bearing_to_target_deg; }
     148             : 
     149             :     // get system time of last position update
     150             :     // LUA bindings
     151           0 :     uint32_t get_last_update_ms() const { return _last_location_update_ms; }
     152             : 
     153             :     // returns true if a follow option enabled
     154           7 :     bool option_is_enabled(Option option) const { return (_options.get() & (uint16_t)option) != 0; }
     155             : 
     156             :     //==========================================================================
     157             :     // Parameter Group Info
     158             :     //==========================================================================
     159             : 
     160             :     // parameter list
     161             :     static const struct AP_Param::GroupInfo var_info[];
     162             : 
     163             : private:
     164             :     //==========================================================================
     165             :     // Private Helper Functions and Singleton
     166             :     //==========================================================================
     167             : 
     168             :     // Singleton instance of the AP_Follow class.
     169             :     static AP_Follow *_singleton;
     170             : 
     171             :     // returns true if we should extract information from msg
     172             :     bool should_handle_message(const mavlink_message_t &msg) const;
     173             : 
     174             :     // Returns true if the target data we hold is fresh and was supplied by the configured system.
     175             :     bool have_target_data() const;
     176             : 
     177             :     // Checks whether the current estimate should be reset based on position and velocity errors.
     178             :     bool estimate_error_too_large() const;
     179             :     
     180             :     // Calculates max velocity change under trapezoidal or triangular acceleration profile (jerk-limited).
     181             :     float calc_max_velocity_change(float accel_max, float jerk_max, float timeout_sec) const;
     182             : 
     183             :     // Rotates a 3D vector clockwise by the specified angle in degrees.
     184             :     Vector3f rotate_vector(const Vector3f &vec, float angle_deg) const;
     185             : 
     186             :     // Resets the recorded distance and bearing to the target to zero.
     187             :     void clear_dist_and_bearing_to_target();
     188             :     void update_dist_and_bearing_to_target();
     189             : 
     190             :     // handle various mavlink messages supplying position:
     191             :     bool handle_global_position_int_message(const mavlink_message_t &msg);
     192             :     bool handle_follow_target_message(const mavlink_message_t &msg);
     193             : 
     194             :     // write out an onboard-log message to help diagnose follow problems:
     195             :     void Log_Write_FOLL();
     196             : 
     197             :     //==========================================================================
     198             :     // Parameters
     199             :     //==========================================================================
     200             : 
     201             :     AP_Int8     _enabled;           // 1 = Follow mode is enabled; 0 = disabled
     202             :     AP_Int16    _sysid;             // MAVLink system ID of the target (0 = no target selected)
     203             :     AP_Float    _dist_max_m;        // Maximum allowed distance to target in meters; if exceeded, estimation is rejected
     204             :     AP_Int8     _offset_type;       // Offset frame type: 0 = NED, 1 = relative to lead vehicle heading
     205             :     AP_Vector3f _offset_m;          // Offset from lead vehicle (meters), in NED or FRD frame depending on _offset_type
     206             :     AP_Int8     _yaw_behave;        // Yaw behavior mode (see YawBehave enum)
     207             :     AP_Enum<Location::AltFrame>    _alt_type;          // altitude source for follow mode
     208             :     AC_P        _p_pos;             // Position error P-controller for optional altitude following
     209             :     AP_Int16    _options;           // Bitmask of follow behavior options (e.g., mount follow, etc.)
     210             :     AP_Float    _timeout;           // position estimate timeout after x milliseconds
     211             : 
     212             :     AP_Float    _accel_max_ne_mss;  // Max horizontal acceleration for kinematic shaping (m/s²)
     213             :     AP_Float    _jerk_max_ne_msss;  // Max horizontal jerk for kinematic shaping (m/s³)
     214             :     AP_Float    _accel_max_d_mss;   // Max vertical acceleration for kinematic shaping (m/s²)
     215             :     AP_Float    _jerk_max_d_msss;   // Max vertical jerk for kinematic shaping (m/s³)
     216             :     AP_Float    _accel_max_h_degss; // Max angular acceleration for heading shaping (deg/s²)
     217             :     AP_Float    _jerk_max_h_degsss; // Max angular jerk for heading shaping (deg/s³)
     218             : 
     219             :     //==========================================================================
     220             :     // Internal State Variables
     221             :     //==========================================================================
     222             : 
     223             :     uint32_t    _last_location_update_ms;       // Time of last target position update (ms)
     224             :     uint32_t    _last_estimation_update_ms;     // Time of last estimate update (ms)
     225             : 
     226             :     Vector3p    _target_pos_ned_m;              // Latest received target position (NED frame, meters)
     227             :     Vector3f    _target_vel_ned_ms;             // Latest received target velocity (NED frame, m/s)
     228             :     Vector3f    _target_accel_ned_mss;          // Latest received target acceleration (NED frame, m/s²)
     229             :     float       _target_heading_deg;            // Latest received target heading (degrees, 0 = North)
     230             :     float       _target_heading_rate_degs;      // Latest received target yaw rate (deg/s)
     231             : 
     232             :     bool        _estimate_valid;                // True if internal estimate is valid and in sync with updates
     233             :     Vector3p    _estimate_pos_ned_m;            // Estimated target position (NED frame, meters)
     234             :     Vector3f    _estimate_vel_ned_ms;           // Estimated target velocity (NED frame, m/s)
     235             :     Vector3f    _estimate_accel_ned_mss;        // Estimated target acceleration (NED frame, m/s²)
     236             :     float       _estimate_heading_rad;          // Estimated heading (radians, range -PI to PI)
     237             :     float       _estimate_heading_rate_rads;    // Estimated heading rate (rad/s)
     238             :     float       _estimate_heading_accel_radss;  // Estimated heading acceleration (rad/s²)
     239             : 
     240             :     Vector3p    _ofs_estimate_pos_ned_m;        // Estimated position with offsets applied (NED frame)
     241             :     Vector3f    _ofs_estimate_vel_ned_ms;       // Estimated velocity with offsets applied (NED frame)
     242             :     Vector3f    _ofs_estimate_accel_ned_mss;    // Estimated acceleration with offsets applied (NED frame)
     243             : 
     244             :     int16_t     _sysid_of_data;                    // sysid that supplied the target data we currently hold
     245             :     float       _dist_to_target_m;              // Horizontal distance to target, for reporting (meters)
     246             :     float       _bearing_to_target_deg;         // Bearing to target from vehicle (degrees, 0 = North)
     247             :     bool        _offsets_were_zero;             // True if initial offset was zero before being initialized
     248             :     bool        _using_follow_target;           // True if FOLLOW_TARGET messages are being used instead of GLOBAL_POSITION_INT
     249             : 
     250             :     HAL_Semaphore   _follow_sem;                // semaphore for multi-thread use of update_estimates and LUA calls
     251             : 
     252             :     //==========================================================================
     253             :     // Utilities
     254             :     //==========================================================================
     255             : 
     256             :     // Jitter correction helper for smoothing offboard timestamps.
     257             :     JitterCorrection _jitter{500};
     258             : };
     259             : 
     260             : //==============================================================================
     261             : // AP_Follow Accessor
     262             : //==============================================================================
     263             : 
     264             : namespace AP {
     265             :     AP_Follow &follow();
     266             : };
     267             : 
     268             : #endif

Generated by: LCOV version 1.14