Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Ardupilot
GitHub Repository: Ardupilot/ardupilot
Path: blob/master/libraries/AC_WPNav/AC_Circle.h
9784 views
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
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
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
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
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
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
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
float get_rate_degs() const { return _rate_parm_degs; }
70
71
// Returns the current angular velocity in degrees per second.
72
// May be lower than the configured maximum due to ramp constraints.
73
float get_rate_current() const { return degrees(_angular_vel_rads); }
74
75
// Sets the target circle rate in degrees per second.
76
// Positive values result in clockwise rotation; negative for counter-clockwise.
77
void set_rate_degs(float rate_degs);
78
79
// Returns the total angle, in radians, that the vehicle has traveled along the circular path.
80
float get_angle_total_rad() const { return _angle_total_rad; }
81
82
// Updates the circle controller using a climb rate in cm/s.
83
// See update_ms() for full implementation details.
84
bool update_cms(float climb_rate_cms = 0.0f) WARN_IF_UNUSED;
85
86
// Updates the circle controller using a climb rate in m/s.
87
// Computes new angular position, yaw, and vertical trajectory, then updates the position controller.
88
// Returns false if terrain data is required but unavailable.
89
bool update_ms(float climb_rate_ms = 0.0f) WARN_IF_UNUSED;
90
91
// Returns the desired roll angle in centidegrees from the position controller.
92
// Should be passed to the attitude controller as a stabilization input.
93
float get_roll_cd() const { return rad_to_cd(_pos_control.get_roll_rad()); }
94
95
// Returns the desired pitch angle in centidegrees from the position controller.
96
// Should be passed to the attitude controller as a stabilization input.
97
float get_pitch_cd() const { return rad_to_cd(_pos_control.get_pitch_rad()); }
98
99
// Returns the desired yaw angle in centidegrees computed by the circle controller.
100
// May be oriented toward the circle center or along the path depending on configuration.
101
float get_yaw_cd() const { return rad_to_cd(_yaw_rad); }
102
103
// Returns the desired yaw angle in radians.
104
// Used for directional control based on circle configuration.
105
float get_yaw_rad() const { return _yaw_rad; }
106
107
// Returns the desired thrust vector (unit vector in body frame) from the position controller.
108
// Can be used by the attitude controller to align thrust direction.
109
Vector3f get_thrust_vector() const { return _pos_control.get_thrust_vector(); }
110
111
// Returns true if the circle controller's update() function has run recently.
112
// Used by vehicle code to determine if yaw and position outputs are valid.
113
bool is_active() const;
114
115
// Returns the closest point on the circle to the vehicle's current position in centimeters.
116
// See get_closest_point_on_circle_NED_m() for full details.
117
void get_closest_point_on_circle_NEU_cm(Vector3f& result_neu_cm, float& dist_cm) const;
118
119
// Returns the closest point on the circle to the vehicle's stopping point in meters.
120
// The result vector is updated with the NED position of the closest point on the circle.
121
// The altitude (z) is set to match the circle center's altitude.
122
// dist_m is updated with the 3D distance to the circle edge from the stopping point.
123
// If the vehicle is at the center, the point directly behind the vehicle (based on yaw) is returned.
124
void get_closest_point_on_circle_NED_m(Vector3p& result_ned_m, float& dist_m) const;
125
126
// Returns the horizontal distance to the circle target in meters.
127
// Calculated using the position controller’s NE position error norm.
128
float get_distance_to_target_m() const { return _pos_control.get_pos_error_NE_m(); }
129
130
// Returns the bearing from the vehicle to the circle target in radians.
131
// Bearing is measured clockwise from North (0 = North).
132
float get_bearing_to_target_rad() const { return _pos_control.get_bearing_to_target_rad(); }
133
134
// Returns true if pilot stick control of circle radius and rate is enabled.
135
// See pilot_control_enabled() for flag logic.
136
bool pilot_control_enabled() const { return (_options.get() & CircleOptions::MANUAL_CONTROL) != 0; }
137
138
// Returns true if the mount ROI is fixed at the circle center.
139
// See roi_at_center() for flag logic.
140
bool roi_at_center() const { return (_options.get() & CircleOptions::ROI_AT_CENTER) != 0; }
141
142
// Sets rangefinder terrain offset (in centimeters) above EKF origin.
143
// See set_rangefinder_terrain_U_m() for full details.
144
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;}
145
146
// Sets rangefinder terrain offset (in meters) above EKF origin.
147
// Used for terrain-relative altitude tracking during circular flight.
148
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;}
149
150
// Checks if the circle radius parameter has changed.
151
// If so, updates internal `_radius_m` and stores the new parameter value.
152
void check_param_change();
153
154
// perform any required parameter conversions
155
void convert_parameters();
156
157
static const struct AP_Param::GroupInfo var_info[];
158
159
private:
160
161
// Calculates angular velocity and acceleration limits based on the configured radius and rate.
162
// Should be called whenever radius or rate changes.
163
// If `init_velocity` is true, resets angular velocity to zero (used on controller startup).
164
void calc_velocities(bool init_velocity);
165
166
// Sets the initial angle around the circle and resets the accumulated angle.
167
// If `use_heading` is true, uses vehicle heading to initialize angle for minimal yaw motion.
168
// If false, uses position relative to circle center to set angle.
169
void init_start_angle(bool use_heading);
170
171
// Returns the expected source of terrain data for the circle controller.
172
// Used to determine whether terrain offset comes from rangefinder, terrain database, or is unavailable.
173
enum class TerrainSource {
174
TERRAIN_UNAVAILABLE,
175
TERRAIN_FROM_RANGEFINDER,
176
TERRAIN_FROM_TERRAINDATABASE,
177
};
178
AC_Circle::TerrainSource get_terrain_source() const;
179
180
// Returns terrain offset in meters above the EKF origin at the current position.
181
// Positive values indicate terrain is above the EKF origin altitude.
182
// Terrain source may be rangefinder or terrain database.
183
bool get_terrain_U_m(float& terrain_u_m);
184
185
// references to inertial nav and ahrs libraries
186
const AP_AHRS_View& _ahrs;
187
AC_PosControl& _pos_control;
188
189
enum CircleOptions {
190
MANUAL_CONTROL = 1U << 0, // Enables pilot stick input to adjust circle radius and turn rate.
191
FACE_DIRECTION_OF_TRAVEL = 1U << 1, // Yaw aligns with direction of travel (tangent to circle path).
192
INIT_AT_CENTER = 1U << 2, // Initializes circle with center at current position (instead of radius ahead).
193
ROI_AT_CENTER = 1U << 3, // Sets camera mount ROI to circle center during circle mode.
194
};
195
196
// parameters
197
AP_Float _radius_parm_m; // Circle radius in meters, loaded from parameters.
198
AP_Float _rate_parm_degs; // Circle rotation rate in degrees per second, loaded from parameters.
199
AP_Int16 _options; // Bitmask of CircleOptions (e.g. manual control, ROI at center, etc.).
200
201
// internal variables
202
Vector3p _center_ned_m; // Center of the circle in meters from EKF origin (NED frame).
203
float _radius_m; // Current circle radius in meters.
204
float _rotation_rate_max_rads; // Requested circle turn rate in rad/s (+ve = CW, -ve = CCW).
205
float _yaw_rad; // Desired yaw heading in radians (typically toward circle center or tangent).
206
float _angle_rad; // Current angular position around the circle in radians (0 = due north of center).
207
float _angle_total_rad; // Accumulated angle travelled in radians (used for full rotations).
208
float _angular_vel_rads; // Current angular velocity in rad/s.
209
float _angular_vel_max_rads; // Maximum allowed angular velocity in rad/s.
210
float _angular_accel_radss; // Angular acceleration limit in rad/s².
211
uint32_t _last_update_ms; // Timestamp (in milliseconds) of the last update() call.
212
float _last_radius_param_m; // Cached copy of radius parameter (m) to detect parameter changes.
213
214
// terrain following variables
215
bool _is_terrain_alt; // True if _center_ned_m.z is relative to terrain height; false if relative to EKF origin.
216
bool _rangefinder_available; // True if rangefinder is available and enabled.
217
bool _rangefinder_healthy; // True if rangefinder reading is within valid operating range.
218
float _rangefinder_terrain_u_m; // Terrain height above EKF origin (meters), from rangefinder or terrain database.
219
};
220
221