LCOV - code coverage report
Current view: top level - AC_WPNav - AC_Circle.h (source / functions) Hit Total Coverage
Test: lcov.info Lines: 20 20 100.0 %
Date: 2026-09-09 11:02:08 Functions: 20 20 100.0 %

          Line data    Source code
       1             : #pragma once
       2             : 
       3             : #include <AP_Common/AP_Common.h>
       4             : #include <AP_Param/AP_Param.h>
       5             : #include <AP_Math/AP_Math.h>
       6             : #include <AC_AttitudeControl/AC_PosControl.h>      // Position control library
       7             : 
       8             : class AC_Circle
       9             : {
      10             : public:
      11             : 
      12             :     /// Constructor
      13             :     AC_Circle(const AP_AHRS_View& ahrs, AC_PosControl& pos_control);
      14             : 
      15             :     // Initializes circle flight using a center position in centimeters relative to the EKF origin.
      16             :     // See init_NED_m() for full details.
      17             :     void init_NEU_cm(const Vector3p& center_neu_cm, bool is_terrain_alt, float rate_degs);
      18             : 
      19             :     // Initializes circle flight mode using a specified center position in meters.
      20             :     // Parameters:
      21             :     //  - center_ned_m: Center of the circle in NED frame (meters, relative to EKF origin)
      22             :     // - is_terrain_alt: If true, center_ned_m.z is interpreted as relative to terrain; otherwise, above EKF origin
      23             :     //  - rate_degs: Desired turn rate in degrees per second (positive = clockwise, negative = counter-clockwise)
      24             :     // Caller must preconfigure the position controller's speed and acceleration settings before calling.
      25             :     void init_NED_m(const Vector3p& center_ned_m, bool is_terrain_alt, float rate_degs);
      26             : 
      27             :     // Initializes the circle flight mode using the current stopping point as a reference.
      28             :     // If the INIT_AT_CENTER option is not set, the circle center is projected one radius ahead along the vehicle's heading.
      29             :     // Caller must configure position controller speeds and accelerations beforehand.
      30             :     void init();
      31             : 
      32             :     // Sets the circle center using a Location object.
      33             :     // Automatically determines whether the location uses terrain-relative or origin-relative altitude.
      34             :     // If conversion fails, defaults to current position and logs a navigation error.
      35             :     void set_center(const Location& center);
      36             : 
      37             :     // Sets the circle center using a NED position vector in meters from the EKF origin.
      38             :     // - is_terrain_alt: If true, center_ned_m.z is interpreted as relative to terrain; otherwise, above EKF origin
      39           7 :     void set_center_NED_m(const Vector3p& center_ned_m, bool is_terrain_alt) { _center_ned_m = center_ned_m; _is_terrain_alt = is_terrain_alt; }
      40             : 
      41             :     // Returns the circle center in centimeters from the EKF origin.
      42             :     // See get_center_NED_m() for full details.
      43           4 :     const Vector3p get_center_NEU_cm() const { return Vector3p(_center_ned_m.x, _center_ned_m.y, -_center_ned_m.z) * 100.0; }
      44             : 
      45             :     // Returns the circle center in meters from the EKF origin.
      46             :     // Altitude frame is determined by `center_is_terrain_alt()`.
      47       46679 :     const Vector3p& get_center_NED_m() const { return _center_ned_m; }
      48             : 
      49             :     // Returns true if the circle center altitude is relative to terrain height.
      50          11 :     bool center_is_terrain_alt() const { return _is_terrain_alt; }
      51             : 
      52             :     // Returns the circle radius in centimeters.
      53             :     // See get_radius_m() for full details.
      54           2 :     float get_radius_cm() const { return get_radius_m() * 100.0; }
      55             : 
      56             :     // Returns the circle radius in meters.
      57             :     // If `_radius_m` is non-positive, falls back to the RADIUS parameter.
      58      116089 :     float get_radius_m() const { return is_positive(_radius_m) ? _radius_m : _radius_parm_m; }
      59             : 
      60             :     // Sets the circle radius in centimeters.
      61             :     // See set_radius_m() for full details.
      62             :     void set_radius_cm(float radius_cm);
      63             : 
      64             :     // Sets the circle radius in meters.
      65             :     // Radius is constrained to AC_CIRCLE_RADIUS_MAX_M.
      66             :     void set_radius_m(float radius_m);
      67             : 
      68             :     // Returns the configured circle turn rate in degrees per second from the RATE parameter.
      69       15766 :     float get_rate_degs() const { return _rate_parm_degs; }
      70             : 
      71             :     // Returns the commanded turn-rate target in degrees per second.
      72             :     // This is the rate the controller ramps towards (set by the RATE
      73             :     // parameter or set_rate_degs()).
      74       15761 :     float get_rate_target_degs() const { return degrees(_rotation_rate_max_rads); }
      75             : 
      76             :     // Sets the target circle rate in degrees per second.
      77             :     // Positive values result in clockwise rotation; negative for counter-clockwise.
      78             :     void set_rate_degs(float rate_degs);
      79             : 
      80             :     // Returns the total angle, in radians, that the vehicle has traveled along the circular path.
      81      127104 :     float get_angle_total_rad() const { return _angle_total_rad; }
      82             : 
      83             :     // Updates the circle controller using a climb rate in cm/s.
      84             :     // See update_ms() for full implementation details.
      85             :     bool update_cms(float climb_rate_cms = 0.0f) WARN_IF_UNUSED;
      86             : 
      87             :     // Updates the circle controller using a climb rate in m/s.
      88             :     // Computes new angular position, yaw, and vertical trajectory, then updates the position controller.
      89             :     // Returns false if terrain data is required but unavailable.
      90             :     bool update_ms(float climb_rate_ms = 0.0f) WARN_IF_UNUSED;
      91             : 
      92             :     // Returns the desired roll angle in centidegrees from the position controller.
      93             :     // Should be passed to the attitude controller as a stabilization input.
      94      127956 :     float get_roll_cd() const { return rad_to_cd(_pos_control.get_roll_rad()); }
      95             : 
      96             :     // Returns the desired pitch angle in centidegrees from the position controller.
      97             :     // Should be passed to the attitude controller as a stabilization input.
      98      127956 :     float get_pitch_cd() const { return rad_to_cd(_pos_control.get_pitch_rad()); }
      99             : 
     100             :     // Returns the desired yaw angle in centidegrees computed by the circle controller.
     101             :     // May be oriented toward the circle center or along the path depending on configuration.
     102      127956 :     float get_yaw_cd() const { return rad_to_cd(_yaw_rad); }
     103             : 
     104             :     // Returns the desired yaw angle in radians.
     105             :     // Used for directional control based on circle configuration.
     106      109881 :     float get_yaw_rad() const { return _yaw_rad; }
     107             : 
     108             :     // Returns the desired thrust vector (unit vector in body frame) from the position controller.
     109             :     // Can be used by the attitude controller to align thrust direction.
     110             :     Vector3f get_thrust_vector() const { return _pos_control.get_thrust_vector(); }
     111             : 
     112             :     // Returns true if the circle controller's update() function has run recently.
     113             :     // Used by vehicle code to determine if yaw and position outputs are valid.
     114             :     bool is_active() const;
     115             : 
     116             :     // Returns the closest point on the circle to the vehicle's current position in centimeters.
     117             :     // See get_closest_point_on_circle_NED_m() for full details.
     118             :     void get_closest_point_on_circle_NEU_cm(Vector3f& result_neu_cm, float& dist_cm) const;
     119             : 
     120             :     // Returns the closest point on the circle to the vehicle's stopping point in meters.
     121             :     // The result vector is updated with the NED position of the closest point on the circle.
     122             :     // The altitude (z) is set to match the circle center's altitude.
     123             :     // dist_m is updated with the 3D distance to the circle edge from the stopping point.
     124             :     // If the vehicle is at the center, the point directly behind the vehicle (based on yaw) is returned.
     125             :     void get_closest_point_on_circle_NED_m(Vector3p& result_ned_m, float& dist_m) const;
     126             : 
     127             :     // Returns the horizontal distance to the circle target in meters.
     128             :     // Calculated using the position controller’s NE position error norm.
     129        1724 :     float get_distance_to_target_m() const { return _pos_control.get_pos_error_NE_m(); }
     130             : 
     131             :     // Returns the bearing from the vehicle to the circle target in radians.
     132             :     // Bearing is measured clockwise from North (0 = North).
     133        1724 :     float get_bearing_to_target_rad() const { return _pos_control.get_bearing_to_target_rad(); }
     134             : 
     135             :     // Returns true if pilot stick control of circle radius and rate is enabled.
     136             :     // See pilot_control_enabled() for flag logic.
     137      115671 :     bool pilot_control_enabled() const { return (_options.get() & CircleOptions::MANUAL_CONTROL) != 0; }
     138             : 
     139             :     // Returns true if the mount ROI is fixed at the circle center.
     140             :     // See roi_at_center() for flag logic.
     141          22 :     bool roi_at_center() const { return (_options.get() & CircleOptions::ROI_AT_CENTER) != 0; }
     142             : 
     143             :     // Returns true if the vehicle yaw should align with the direction of travel (tangent)
     144             :     // rather than facing the circle center.
     145       46670 :     bool face_direction_of_travel() const { return (_options.get() & CircleOptions::FACE_DIRECTION_OF_TRAVEL) != 0; }
     146             : 
     147             :     // Sets rangefinder terrain offset (in centimeters) above EKF origin.
     148             :     // See set_rangefinder_terrain_U_m() for full details.
     149      109016 :     void set_rangefinder_terrain_U_cm(bool use, bool healthy, float terrain_u_cm) { _rangefinder_available = use; _rangefinder_healthy = healthy; _rangefinder_terrain_u_m = terrain_u_cm * 0.01;}
     150             : 
     151             :     // Sets rangefinder terrain offset (in meters) above EKF origin.
     152             :     // Used for terrain-relative altitude tracking during circular flight.
     153    30392688 :     void set_rangefinder_terrain_U_m(bool use, bool healthy, float terrain_u_m) { _rangefinder_available = use; _rangefinder_healthy = healthy; _rangefinder_terrain_u_m = terrain_u_m;}
     154             : 
     155             :     // Checks if the circle radius parameter has changed.
     156             :     // If so, updates internal `_radius_m` and stores the new parameter value.
     157             :     void check_param_change();
     158             : 
     159             :     // perform any required parameter conversions
     160             :     void convert_parameters();
     161             : 
     162             :     static const struct AP_Param::GroupInfo var_info[];
     163             : 
     164             : private:
     165             : 
     166             :     // Calculates angular velocity and acceleration limits based on the configured radius and rate.
     167             :     // Should be called whenever radius or rate changes.
     168             :     // If `init_velocity` is true, resets angular velocity to zero (used on controller startup).
     169             :     void calc_velocities(bool init_velocity);
     170             : 
     171             :     // Sets the initial angle around the circle and resets the accumulated angle.
     172             :     // If `use_heading` is true, uses vehicle heading to initialize angle for minimal yaw motion.
     173             :     // If false, uses position relative to circle center to set angle.
     174             :     void init_start_angle(bool use_heading);
     175             : 
     176             :     // Returns the expected source of terrain data for the circle controller.
     177             :     // Used to determine whether terrain offset comes from rangefinder, terrain database, or is unavailable.
     178             :     enum class TerrainSource {
     179             :         TERRAIN_UNAVAILABLE,
     180             :         TERRAIN_FROM_RANGEFINDER,
     181             :         TERRAIN_FROM_TERRAINDATABASE,
     182             :     };
     183             :     AC_Circle::TerrainSource get_terrain_source() const;
     184             : 
     185             :     // Returns terrain offset in meters above the EKF origin at the current position.
     186             :     // Positive values indicate terrain is above the EKF origin altitude.
     187             :     // Terrain source may be rangefinder or terrain database.
     188             :     bool get_terrain_U_m(float& terrain_u_m);
     189             : 
     190             :     // references to inertial nav and ahrs libraries
     191             :     const AP_AHRS_View&         _ahrs;
     192             :     AC_PosControl&              _pos_control;
     193             : 
     194             :     enum CircleOptions {
     195             :         MANUAL_CONTROL           = 1U << 0, // Enables pilot stick input to adjust circle radius and turn rate.
     196             :         FACE_DIRECTION_OF_TRAVEL = 1U << 1, // Yaw aligns with direction of travel (tangent to circle path).
     197             :         INIT_AT_CENTER           = 1U << 2, // Initializes circle with center at current position (instead of radius ahead).
     198             :         ROI_AT_CENTER            = 1U << 3, // Sets camera mount ROI to circle center during circle mode.
     199             :     };
     200             : 
     201             :     // parameters
     202             :     AP_Float _radius_parm_m;      // Circle radius in meters, loaded from parameters.
     203             :     AP_Float _rate_parm_degs;     // Circle rotation rate in degrees per second, loaded from parameters.
     204             :     AP_Int16 _options;            // Bitmask of CircleOptions (e.g. manual control, ROI at center, etc.).
     205             : 
     206             :     // internal variables
     207             :     Vector3p _center_ned_m;             // Center of the circle in meters from EKF origin (NED frame).
     208             :     float    _radius_m;                 // Current circle radius in meters.
     209             :     float    _rotation_rate_max_rads;   // Requested circle turn rate in rad/s (+ve = CW, -ve = CCW).
     210             :     float    _yaw_rad;                  // Desired yaw heading in radians (typically toward circle center or tangent).
     211             :     float    _angle_rad;                // Current angular position around the circle in radians (0 = due north of center).
     212             :     float    _angle_total_rad;          // Accumulated angle travelled in radians (used for full rotations).
     213             :     float    _angular_vel_rads;         // Current angular velocity in rad/s.
     214             :     float    _angular_vel_max_rads;     // Maximum allowed angular velocity in rad/s.
     215             :     float    _angular_accel_radss;      // Angular acceleration limit in rad/s².
     216             :     uint32_t _last_update_ms;           // Timestamp (in milliseconds) of the last update() call.
     217             :     float    _last_radius_param_m;      // Cached copy of radius parameter (m) to detect parameter changes.
     218             : 
     219             :     // terrain following variables
     220             :     bool  _is_terrain_alt;               // True if _center_ned_m.z is relative to terrain height; false if relative to EKF origin.
     221             :     bool  _rangefinder_available;        // True if rangefinder is available and enabled.
     222             :     bool  _rangefinder_healthy;          // True if rangefinder reading is within valid operating range.
     223             :     float _rangefinder_terrain_u_m; // Terrain height above EKF origin (meters), from rangefinder or terrain database.
     224             : };

Generated by: LCOV version 1.14