Skip to content

Commit

Permalink
AP_L1_Control: make reached_loiter_target() more reliable
Browse files Browse the repository at this point in the history
if our target loiter radius is unachievable then we can reach the
loiter target on initial capture but be unable to maintain it. This
ensures that once we capture we return true on reached_loiter_target()

This is critical for any mission type where we take an action on
reached_loiter_target() and another condition (such as being lined up
for a waypoint). Otherwise we may continue loitering forever
  • Loading branch information
tridge committed Sep 29, 2024
1 parent b606e77 commit b325569
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 1 deletion.
26 changes: 25 additions & 1 deletion libraries/AP_L1_Control/AP_L1_Control.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ void AP_L1_Control::update_waypoint(const Location &prev_WP, const Location &nex

// Waypoint capture status is always false during waypoint following
_WPcircle = false;
last_reached_loiter_target_ms = 0;

_bearing_error = Nu; // bearing error angle (radians), +ve to left of track

Expand Down Expand Up @@ -442,18 +443,39 @@ void AP_L1_Control::update_loiter(const Location &center_WP, float radius, int8_
// Perform switchover between 'capture' and 'circle' modes at the
// point where the commands cross over to achieve a seamless transfer
// Only fly 'capture' mode if outside the circle
const uint32_t now_ms = AP_HAL::millis();
if (xtrackErrCirc > 0.0f && loiter_direction * latAccDemCap < loiter_direction * latAccDemCirc) {
_latAccDem = latAccDemCap;
_WPcircle = false;

/*
if we were previously on the circle and the target has not
changed then keep _WPcircle true. This prevents
reached_loiter_target() from going false due to a gust of
wind or an unachievable loiter radius
*/
if (_WPcircle &&
last_reached_loiter_target_ms != 0 &&
now_ms - last_reached_loiter_target_ms < 200U &&
center_WP.same_loc_as(last_center_WP)) {
// same location, within 200ms, keep the _WPcircle status as true
last_reached_loiter_target_ms = now_ms;
} else {
_WPcircle = false;
last_reached_loiter_target_ms = 0;
}

_bearing_error = Nu; // angle between demanded and achieved velocity vector, +ve to left of track
_nav_bearing = atan2f(-A_air_unit.y , -A_air_unit.x); // bearing (radians) from AC to L1 point
} else {
_latAccDem = latAccDemCirc;
_WPcircle = true;
last_reached_loiter_target_ms = now_ms;
_bearing_error = 0.0f; // bearing error (radians), +ve to left of track
_nav_bearing = atan2f(-A_air_unit.y , -A_air_unit.x); // bearing (radians)from AC to L1 point
}

last_center_WP = center_WP;

_data_is_stale = false; // status are correctly updated with current waypoint data
}

Expand Down Expand Up @@ -487,6 +509,7 @@ void AP_L1_Control::update_heading_hold(int32_t navigation_heading_cd)

// Waypoint capture status is always false during heading hold
_WPcircle = false;
last_reached_loiter_target_ms = 0;

_crosstrack_error = 0;

Expand All @@ -510,6 +533,7 @@ void AP_L1_Control::update_level_flight(void)

// Waypoint capture status is always false during heading hold
_WPcircle = false;
last_reached_loiter_target_ms = 0;

_latAccDem = 0;

Expand Down
4 changes: 4 additions & 0 deletions libraries/AP_L1_Control/AP_L1_Control.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,10 @@ class AP_L1_Control : public AP_Navigation {

AP_Float _loiter_bank_limit;

// remember reached_loiter_target decision
uint32_t last_reached_loiter_target_ms;
Location last_center_WP;

bool _reverse = false;
float get_yaw() const;
int32_t get_yaw_sensor() const;
Expand Down

0 comments on commit b325569

Please sign in to comment.