Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Copter Fence Fixes #25875

Merged
merged 49 commits into from
Jul 23, 2024
Merged
Show file tree
Hide file tree
Changes from 48 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
a0a81de
Copter: notify when fence breach has cleared
andyp1per Jan 2, 2024
9817344
GCS_MAVLink: use bitmask based enablement for fences
andyp1per Jan 13, 2024
4ce89c8
AP_Mission: add comment about new fence API
andyp1per Jan 13, 2024
5f51be6
AC_Avoidance: take into account minimum altitude fence when calculati…
andyp1per Jan 15, 2024
694c6a0
AP_Arming: do not enable minimim altitude fence on arming
andyp1per Jan 19, 2024
fe40fbb
Plane: output user-friendly fence messages
andyp1per Jan 19, 2024
427e81e
AP_Common: fix initialization of ExpandingString so that it can be us…
andyp1per Jan 27, 2024
a540f1d
AP_Frsky_Telem: use fence enable_configured()
andyp1per Feb 8, 2024
ae95da6
RC_Channel: use fence enable_configured()
andyp1per Feb 8, 2024
a433d74
Plane: use fence enable_configured()
andyp1per Feb 8, 2024
642ebab
Rover: use fence enable_configured()
andyp1per Feb 8, 2024
ead7383
Plane: prevent Mode Takeoff calling fence autoenable more than once
Hwurzburg Feb 16, 2024
9b5890a
AP_Logger: add events for all fence types
andyp1per Feb 17, 2024
e00be28
AC_Fence: add ability to auto-enable fence floor while doing fence ch…
andyp1per Dec 4, 2023
1aebd67
AC_Fence: ensure fence enablement on arming is inverted on disarming
andyp1per Mar 11, 2024
cda9de2
AP_Arming: ensure fence enablement on arming is inverted on disarming
andyp1per Mar 11, 2024
4117288
AC_Fence: clear breach of disabled fence
peterbarker May 19, 2024
7b57930
autotest: add test for auto-disabling min alt fence breaches on disar…
andyp1per Dec 22, 2023
bb8f98f
AC_Fence: add reset_fence_floor_enable() and use it in plane when lan…
andyp1per May 31, 2024
5c9deab
Plane: use reset_fence_floor_enable()
andyp1per May 31, 2024
cbd8c60
autotest: test aborted landing with fence correctly
andyp1per May 31, 2024
d19fd9c
AC_Fence: disable fences for landing by suppressing in the fence chec…
andyp1per May 31, 2024
ef8f182
Plane: disable fences for landing by suppressing in the fence check r…
andyp1per May 31, 2024
807b1d0
Copter: disable fences for landing by suppressing in the fence check …
andyp1per May 31, 2024
24ec111
AP_Mission: generic fence handling in missions
andyp1per May 31, 2024
e94dcf2
Plane: use generic fence handling in missions
andyp1per May 31, 2024
4c06ac5
Copter: use generic fence handling in missions
andyp1per May 31, 2024
d64f5ea
Rover: use generic fence handling in missions
andyp1per May 31, 2024
11441b3
AC_Fence: always disable Min Alt fence on landing
andyp1per Jun 22, 2024
a42d7ae
AP_Arming: allow precise wording of fence pre-arm messages
andyp1per Jun 22, 2024
6cbbd88
Copter: don't breach auto-fences when landed
andyp1per Jun 22, 2024
0963060
autotest: fix fence autotests
andyp1per May 31, 2024
bb7384e
AC_Avoidance: correctly set back away speed for minimum alt fences
andyp1per Jun 24, 2024
b12c39b
autotest: add test for minimum altitude avoidance fence
andyp1per Jun 24, 2024
d338e3e
Copter: only disable fences when in landing phase
andyp1per Jun 25, 2024
df04765
Plane: only disable fences when in landing phase
andyp1per Jun 25, 2024
0f98294
Copter: don't print fence cleared messages when sitting on the ground
andyp1per Jun 25, 2024
4c6ef82
AC_Fence: support FENCE_OPTIONS on copter
andyp1per Jun 26, 2024
61f462b
Copter: support FENCE_OPTIONS on copter
andyp1per Jun 26, 2024
43566e0
Plane: reject guided destinations outside the fence
andyp1per Jul 16, 2024
f676d41
AC_Fence: fixed FENCE_AUTOENABLE=2
tridge Jul 17, 2024
fdae0dd
Plane: reset previous mode fence breach when disarmed
tridge Jul 18, 2024
d0b7aff
autotest: test for circle exclusion fence using AUTOENABLE=2
andyp1per Jul 18, 2024
398fe33
Plane: fixed re-enable of fence for FENCE_AUTOENABLE=1
tridge Jul 20, 2024
89e7220
AP_Mission: address minor review comments
andyp1per Jul 21, 2024
768f780
AC_Fence: address minor review comments
andyp1per Jul 21, 2024
96d9985
Copter: address minor review comments
andyp1per Jul 21, 2024
8d7db72
Plane: address minor review comments
andyp1per Jul 21, 2024
166cb48
Copter: fully honour FENCE_OPTION to disable mode changes
tridge Jul 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions ArduCopter/fence.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ void Copter::fence_check()
{
const uint8_t orig_breaches = fence.get_breaches();

bool is_landing_or_landed = flightmode->is_landing() || ap.land_complete || !motors->armed();

// check for new breaches; new_breaches is bitmask of fence types breached
const uint8_t new_breaches = fence.check();
const uint8_t new_breaches = fence.check(is_landing_or_landed);

// we still don't do anything when disarmed, but we do check for fence breaches.
// fence pre-arm check actually checks if any fence has been breached
Expand All @@ -24,7 +26,7 @@ void Copter::fence_check()
if (new_breaches) {

if (!copter.ap.land_complete) {
GCS_SEND_TEXT(MAV_SEVERITY_NOTICE, "Fence Breached");
fence.print_fence_message("breached", new_breaches);
}

// if the user wants some kind of response and motors are armed
Expand Down Expand Up @@ -81,7 +83,10 @@ void Copter::fence_check()

LOGGER_WRITE_ERROR(LogErrorSubsystem::FAILSAFE_FENCE, LogErrorCode(new_breaches));

} else if (orig_breaches) {
} else if (orig_breaches && fence.get_breaches() == 0) {
if (!copter.ap.land_complete) {
GCS_SEND_TEXT(MAV_SEVERITY_NOTICE, "Fence breach cleared");
}
// record clearing of breach
LOGGER_WRITE_ERROR(LogErrorSubsystem::FAILSAFE_FENCE, LogErrorCode::ERROR_RESOLVED);
}
Expand Down
25 changes: 21 additions & 4 deletions ArduCopter/mode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,21 @@ bool Copter::set_mode(Mode::Number mode, ModeReason reason)
return false;
}

#if AP_FENCE_ENABLED
// may not be allowed to change mode if recovering from fence breach
andyp1per marked this conversation as resolved.
Show resolved Hide resolved
if (!ignore_checks &&
andyp1per marked this conversation as resolved.
Show resolved Hide resolved
fence.enabled() &&
fence.option_enabled(AC_Fence::OPTIONS::DISABLE_MODE_CHANGE) &&
fence.get_breaches() &&
!flightmode->is_landing() &&
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can change mode if the current mode is landing? This is not what plane does.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think its a no-op. You would have to be landing in breach.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you cab change mode if autolanding, even if the autoland is a breach action

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

andyp1per#34 makes this change

motors->armed() &&
get_control_mode_reason() == ModeReason::FENCE_BREACHED &&
!ap.land_complete) {
mode_change_failed(new_flightmode, "in fence recovery");
return false;
}
#endif

if (!new_flightmode->init(ignore_checks)) {
mode_change_failed(new_flightmode, "init failed");
return false;
Expand All @@ -371,10 +386,12 @@ bool Copter::set_mode(Mode::Number mode, ModeReason reason)
#endif

#if AP_FENCE_ENABLED
// pilot requested flight mode change during a fence breach indicates pilot is attempting to manually recover
// this flight mode change could be automatic (i.e. fence, battery, GPS or GCS failsafe)
// but it should be harmless to disable the fence temporarily in these situations as well
fence.manual_recovery_start();
if (fence.get_action() != AC_FENCE_ACTION_REPORT_ONLY) {
// pilot requested flight mode change during a fence breach indicates pilot is attempting to manually recover
// this flight mode change could be automatic (i.e. fence, battery, GPS or GCS failsafe)
// but it should be harmless to disable the fence temporarily in these situations as well
fence.manual_recovery_start();
}
#endif

#if AP_CAMERA_ENABLED
Expand Down
17 changes: 0 additions & 17 deletions ArduCopter/mode_auto.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -480,11 +480,6 @@ void ModeAuto::land_start()
copter.landinggear.deploy_for_landing();
#endif

#if AP_FENCE_ENABLED
// disable the fence on landing
copter.fence.auto_disable_fence_for_landing();
#endif

// reset flag indicating if pilot has applied roll or pitch inputs during landing
copter.ap.land_repo_active = false;

Expand Down Expand Up @@ -779,18 +774,6 @@ bool ModeAuto::start_command(const AP_Mission::Mission_Command& cmd)
// point the camera to a specified angle
do_mount_control(cmd);
break;

case MAV_CMD_DO_FENCE_ENABLE:
#if AP_FENCE_ENABLED
if (cmd.p1 == 0) { //disable
copter.fence.enable(false);
gcs().send_text(MAV_SEVERITY_INFO, "Fence Disabled");
} else { //enable fence
copter.fence.enable(true);
gcs().send_text(MAV_SEVERITY_INFO, "Fence Enabled");
}
#endif //AP_FENCE_ENABLED
break;

#if AC_NAV_GUIDED == ENABLED
case MAV_CMD_DO_GUIDED_LIMITS: // 220 accept guided mode limits
Expand Down
3 changes: 3 additions & 0 deletions ArduCopter/mode_guided.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,9 @@ void ModeGuided::takeoff_run()
auto_takeoff.run();
if (auto_takeoff.complete && !takeoff_complete) {
takeoff_complete = true;
#if AP_FENCE_ENABLED
copter.fence.auto_enable_fence_after_takeoff();
#endif
#if AP_LANDINGGEAR_ENABLED
// optionally retract landing gear
copter.landinggear.retract_after_takeoff();
Expand Down
5 changes: 0 additions & 5 deletions ArduCopter/mode_land.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,6 @@ bool ModeLand::init(bool ignore_checks)
copter.landinggear.deploy_for_landing();
#endif

#if AP_FENCE_ENABLED
// disable the fence on landing
copter.fence.auto_disable_fence_for_landing();
#endif

#if AC_PRECLAND_ENABLED
// initialise precland state machine
copter.precland_statemachine.init();
Expand Down
10 changes: 0 additions & 10 deletions ArduCopter/mode_rtl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,11 +255,6 @@ void ModeRTL::descent_start()
// optionally deploy landing gear
copter.landinggear.deploy_for_landing();
#endif

#if AP_FENCE_ENABLED
// disable the fence on landing
copter.fence.auto_disable_fence_for_landing();
#endif
}

// rtl_descent_run - implements the final descent to the RTL_ALT
Expand Down Expand Up @@ -347,11 +342,6 @@ void ModeRTL::land_start()
// optionally deploy landing gear
copter.landinggear.deploy_for_landing();
#endif

#if AP_FENCE_ENABLED
// disable the fence on landing
copter.fence.auto_disable_fence_for_landing();
#endif
}

bool ModeRTL::is_landing() const
Expand Down
8 changes: 8 additions & 0 deletions ArduPlane/GCS_Mavlink.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -841,6 +841,14 @@ MAV_RESULT GCS_MAVLINK_Plane::handle_command_int_do_reposition(const mavlink_com
return MAV_RESULT_DENIED;
}

#if AP_FENCE_ENABLED
// reject destination if outside the fence
if (!plane.fence.check_destination_within_fence(requested_position)) {
LOGGER_WRITE_ERROR(LogErrorSubsystem::NAVIGATION, LogErrorCode::DEST_OUTSIDE_FENCE);
return MAV_RESULT_DENIED;
}
#endif

// location is valid load and set
if (((int32_t)packet.param2 & MAV_DO_REPOSITION_FLAGS_CHANGE_MODE) ||
(plane.control_mode == &plane.mode_guided)) {
Expand Down
3 changes: 3 additions & 0 deletions ArduPlane/Plane.h
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,9 @@ class Plane : public AP_Vehicle {

// are we currently in long failsafe but have postponed it in MODE TAKEOFF until min level alt is reached
bool long_failsafe_pending;

//flag that we have already called autoenable fences once in MODE TAKEOFF
bool have_autoenabled_fences;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be an attribute of fence not plane.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic is just too convoluted to make that feasible

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At least it should be a private variable in mode takeoff?


// GCS selection
GCS_Plane _gcs; // avoid using this; use gcs()
Expand Down
19 changes: 0 additions & 19 deletions ArduPlane/commands_logic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,21 +144,6 @@ bool Plane::start_command(const AP_Mission::Mission_Command& cmd)
case MAV_CMD_DO_LAND_START:
break;

case MAV_CMD_DO_FENCE_ENABLE:
#if AP_FENCE_ENABLED
if (cmd.p1 == 0) { // disable fence
plane.fence.enable(false);
gcs().send_text(MAV_SEVERITY_INFO, "Fence disabled");
} else if (cmd.p1 == 1) { // enable fence
plane.fence.enable(true);
gcs().send_text(MAV_SEVERITY_INFO, "Fence enabled");
} else if (cmd.p1 == 2) { // disable fence floor only
plane.fence.disable_floor();
gcs().send_text(MAV_SEVERITY_INFO, "Fence floor disabled");
}
#endif
break;

case MAV_CMD_DO_AUTOTUNE_ENABLE:
autotune_enable(cmd.p1);
break;
Expand Down Expand Up @@ -434,10 +419,6 @@ void Plane::do_land(const AP_Mission::Mission_Command& cmd)
// if we were in an abort we need to explicitly move out of the abort state, as it's sticky
set_flight_stage(AP_FixedWing::FlightStage::LAND);
}

#if AP_FENCE_ENABLED
plane.fence.auto_disable_fence_for_landing();
#endif
}

#if HAL_QUADPLANE_ENABLED
Expand Down
32 changes: 28 additions & 4 deletions ArduPlane/fence.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,32 @@
void Plane::fence_check()
{
const uint8_t orig_breaches = fence.get_breaches();
const bool armed = arming.is_armed();

uint16_t mission_id = plane.mission.get_current_nav_cmd().id;
bool landing_or_landed = plane.flight_stage == AP_FixedWing::FlightStage::LAND
|| !armed
#if HAL_QUADPLANE_ENABLED
|| control_mode->mode_number() == Mode::Number::QLAND
|| quadplane.in_vtol_land_descent()
#endif
|| (plane.is_land_command(mission_id) && plane.mission.state() == AP_Mission::MISSION_RUNNING);

// check for new breaches; new_breaches is bitmask of fence types breached
const uint8_t new_breaches = fence.check();
const uint8_t new_breaches = fence.check(landing_or_landed);

/*
if we are either disarmed or we are currently not in breach and
we are not flying then clear the state associated with the
previous mode breach handling. This allows the fence state
machine to reset at the end of a fence breach action such as an
RTL and autoland
*/
if (plane.previous_mode_reason == ModeReason::FENCE_BREACHED) {
if (!armed || ((new_breaches == 0 && orig_breaches == 0) && !plane.is_flying())) {
plane.previous_mode_reason = ModeReason::UNKNOWN;
}
}

if (!fence.enabled()) {
// Switch back to the chosen control mode if still in
Expand All @@ -34,7 +57,7 @@ void Plane::fence_check()
// we still don't do anything when disarmed, but we do check for fence breaches.
// fence pre-arm check actually checks if any fence has been breached
// that's not ever going to be true if we don't call check on AP_Fence while disarmed
if (!arming.is_armed()) {
if (!armed) {
return;
}

Expand All @@ -50,7 +73,7 @@ void Plane::fence_check()
}

if (new_breaches) {
GCS_SEND_TEXT(MAV_SEVERITY_NOTICE, "Fence Breached");
fence.print_fence_message("breached", new_breaches);

// if the user wants some kind of response and motors are armed
const uint8_t fence_act = fence.get_action();
Expand Down Expand Up @@ -115,7 +138,8 @@ void Plane::fence_check()
}

LOGGER_WRITE_ERROR(LogErrorSubsystem::FAILSAFE_FENCE, LogErrorCode(new_breaches));
} else if (orig_breaches) {
} else if (orig_breaches && fence.get_breaches() == 0) {
GCS_SEND_TEXT(MAV_SEVERITY_NOTICE, "Fence breach cleared");
// record clearing of breach
LOGGER_WRITE_ERROR(LogErrorSubsystem::FAILSAFE_FENCE, LogErrorCode::ERROR_RESOLVED);
}
Expand Down
3 changes: 0 additions & 3 deletions ArduPlane/mode_qland.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@ bool ModeQLand::_enter()
#if AP_LANDINGGEAR_ENABLED
plane.g2.landing_gear.deploy_for_landing();
#endif
#if AP_FENCE_ENABLED
plane.fence.auto_disable_fence_for_landing();
#endif

return true;
}
Expand Down
6 changes: 5 additions & 1 deletion ArduPlane/mode_takeoff.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ ModeTakeoff::ModeTakeoff() :
bool ModeTakeoff::_enter()
{
takeoff_mode_setup = false;
plane.have_autoenabled_fences = false;

return true;
}
Expand Down Expand Up @@ -154,7 +155,10 @@ void ModeTakeoff::update()
} else {
if ((altitude_cm >= alt * 100 - 200)) { //within 2m of TKOFF_ALT ,or above and loitering
#if AP_FENCE_ENABLED
plane.fence.auto_enable_fence_after_takeoff();
if (!plane.have_autoenabled_fences) {
plane.fence.auto_enable_fence_after_takeoff();
plane.have_autoenabled_fences = true;
}
#endif
plane.calc_nav_roll();
plane.calc_nav_pitch();
Expand Down
3 changes: 0 additions & 3 deletions ArduPlane/quadplane.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3554,9 +3554,6 @@ bool QuadPlane::verify_vtol_land(void)
poscontrol.pilot_correction_done = false;
pos_control->set_lean_angle_max_cd(0);
poscontrol.xy_correction.zero();
#if AP_FENCE_ENABLED
plane.fence.auto_disable_fence_for_landing();
#endif
#if AP_LANDINGGEAR_ENABLED
plane.g2.landing_gear.deploy_for_landing();
#endif
Expand Down
12 changes: 0 additions & 12 deletions Rover/mode_auto.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -593,18 +593,6 @@ bool ModeAuto::start_command(const AP_Mission::Mission_Command& cmd)
do_set_reverse(cmd);
break;

case MAV_CMD_DO_FENCE_ENABLE:
#if AP_FENCE_ENABLED
if (cmd.p1 == 0) { //disable
rover.fence.enable(false);
gcs().send_text(MAV_SEVERITY_INFO, "Fence Disabled");
} else { //enable fence
rover.fence.enable(true);
gcs().send_text(MAV_SEVERITY_INFO, "Fence Enabled");
}
#endif
break;

case MAV_CMD_DO_GUIDED_LIMITS:
do_guided_limits(cmd);
break;
Expand Down
6 changes: 6 additions & 0 deletions Tools/autotest/Generic_Missions/CMAC-fence.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
-35.363720 149.163651
-35.358738 149.165070
-35.359295 149.154434
-35.372292 149.157135
-35.368290 149.166809
-35.358738 149.165070
Loading
Loading