Skip to content

Conversation

@andyp1per
Copy link
Contributor

this allows for fence altitudes to be above ground level, absolute, origin or above home (the default and current behaviour)

This is a rebase of #29761 which I could not push to

this allows for fence altitudes to be above ground level, absolute,
origin or above home (the default and current behaviour)
@andyp1per andyp1per changed the title AC_Fence: added FENCE_ALT_TYPE AC_Fence: added FENCE_ALT_MIN_TP and FENCE_ALT_MAX_TP Nov 29, 2025
@andyp1per andyp1per added the WikiNeeded needs wiki update label Nov 29, 2025
@IamPete1
Copy link
Member

Copter avoidance and plane FBWB altitude control will need updating to respect the new frames.

@andyp1per
Copy link
Contributor Author

@IamPete1 I have done OA and copter but its not clear to me that there is anything reasonable to do for plane. Plane appears to already be guessing something reasonable. LMK what change in behaviour you would like to see.

@IamPete1
Copy link
Member

IamPete1 commented Dec 1, 2025

Plane needs a update here:

// taking fence max and min altitude (with margin)
const uint8_t enabled_fences = plane.fence.get_enabled_fences();
if ((enabled_fences & AC_FENCE_TYPE_ALT_MIN) != 0) {
min_alt_cm = plane.fence.get_safe_alt_min_m()*100.0;
should_check_min = true;
}
if ((enabled_fences & AC_FENCE_TYPE_ALT_MAX) != 0) {
max_alt_cm = plane.fence.get_safe_alt_max_m()*100.0;
should_check_max = true;
}

Probably better to either remove the get_safe_alt_max_m/get_safe_alt_min_m methods or update them to convert to above home alt frame so all the current users are automatically correct.

@rmackay9
Copy link
Contributor

rmackay9 commented Dec 3, 2025

I'd like to give this a test. I just want to be sure that we've tested all the edge cases. Some things to worry about:

  • RTL alt-frame change when the vehicle is already above or below the fence
  • When terrain altitude cannot be retrieved
  • Loiter mode's stopping climbing at the fence. What happens when the vehicle moves forward the terrain falls away below it

Copy link
Contributor

@peterbarker peterbarker left a comment

Choose a reason for hiding this comment

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

Needs autotests.

@andyp1per
Copy link
Contributor Author

andyp1per commented Dec 3, 2025

Probably better to either remove the get_safe_alt_max_m/get_safe_alt_min_m methods or update them to convert to above home alt frame so all the current users are automatically correct.

Converted to relative frame

actually @IamPete1 this turns out to be the wrong change. The maths and checks are much, much simpler if everything is done in the configured frame. The odd one out are these plane methods that require a relative frame, so I have added methods that are specifically relative frame to cope with this particular use case.

@andyp1per andyp1per requested a review from peterbarker December 3, 2025 17:02
pre-arm check for terrain frames
update safe alt min appropriately
only enable terrain checks if terrain is available
introduce get_relative_safe_alt_max_m and get_relative_safe_alt_min_m methods
@andyp1per andyp1per force-pushed the pr-fence-AGL-update branch from 737bf0c to d8e78e8 Compare December 6, 2025 19:57
Copy link
Contributor

@timtuxworth timtuxworth left a comment

Choose a reason for hiding this comment

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

Some thoughts and suggestions.

get our altitude in the FENCE_ALT_TYPE frame
return false if not available
*/
bool AC_Fence::get_alt_U_in_frame(float &alt, Location::AltFrame alt_frame) const
Copy link
Contributor

Choose a reason for hiding this comment

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

What is the "U" here? Up? If it's up, altitude is always up isn't it? So not needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yeah I could change it, it was just getting very confusing to track the places where things were down instead.

hal.util->snprintf(failure_msg, failure_msg_len, "Invalid FENCE_ALT_MIN value");
return false;
}
#if AP_TERRAIN_AVAILABLE
Copy link
Contributor

Choose a reason for hiding this comment

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

This isn't correct; you want this prearm check to fail if your require the terrain database but it isn't available because it is compiled out.

Consider adding it into AP_Arming::terrain_checks instead - it will slot in right next to where we do the same stuff for mission.

}

/*
get our altitude in the FENCE_ALT_TYPE frame
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
get our altitude in the FENCE_ALT_TYPE frame
get our altitude in the supplied frame

*/
bool AC_Fence::get_alt_U_in_frame(float &alt, Location::AltFrame alt_frame) const
{
const auto &ahrs = AP::ahrs();
Copy link
Contributor

Choose a reason for hiding this comment

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

Why aren't you just getting the current location and then asking that for your height in the frame you want?

return true;
}

// update safe alt min
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// update safe alt min
// update safe alt min - home *must* be set before this function is called

(and in the header file)

... or assert it is set in SITL somehow. Or both.

if (_alt_min_type == Location::AltFrame::ABSOLUTE) {
float home_alt;
UNUSED_RESULT(AP::ahrs().get_home().get_alt_m(Location::AltFrame::ABSOLUTE, home_alt));
_safe_alt_min_m = _alt_min_m - home_alt - _margin_m;
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
_safe_alt_min_m = _alt_min_m - home_alt - _margin_m;
_safe_relhome_alt_min_m = _alt_min_m - home_alt - _margin_m;

#endif

// get altitude in alt max frame
bool get_alt_U_in_alt_max_frame(float &alt) const { return get_alt_U_in_frame(alt, (Location::AltFrame)_alt_max_type.get()); }
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we still need the casts here?

home_loc = self.mav.location()

self.max_alt_fence_frame(0, home_loc.alt + 100) # absolute
self.max_alt_fence_frame(1, 100) # above home
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we do a little bit of setup here so home and origin are different altitudes, please?

That really should just be a set_home call.

'''Test Max Alt Fence'''
self.takeoff(10, mode="LOITER")
"""Hold loiter position."""
def max_alt_fence_frame(self, frame, alt, terrain=0):
Copy link
Contributor

Choose a reason for hiding this comment

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

Please pass in an absolute altitude that you expect the vehicle to be close to (+/-5 metres?) when the breach happens and make sure that's about where the vehicle is when it breaches.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants