From 6f63cf14a64432751f0179ebe39776d467755ef2 Mon Sep 17 00:00:00 2001 From: Andrii Anoshyn Date: Sun, 24 May 2026 15:02:48 +0300 Subject: [PATCH 1/2] fix(navigator): honor NAV_LAND mission item abort altitude (param1) A NAV_CMD_LAND mission item's param1 (minimum abort altitude above the landing point) was parsed and dropped with a long-standing TODO, so an aborted landing always climbed to the global MIS_LND_ABRT_ALT regardless of the per-item value. Carry param1 in the otherwise-unused time_inside field on upload, and in do_abort_landing() use it as the climb-above-landing-point height when set (> 0), falling back to MIS_LND_ABRT_ALT otherwise. The value also now round-trips on mission download. Items without a specified abort altitude (param1 = 0), including missions stored by older firmware, keep using the parameter default. Fixes #27290 Signed-off-by: Andrii Anoshyn --- src/modules/mavlink/mavlink_mission.cpp | 6 ++++-- src/modules/navigator/mission_base.cpp | 12 ++++++++++-- src/modules/navigator/mission_params.yaml | 2 ++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/modules/mavlink/mavlink_mission.cpp b/src/modules/mavlink/mavlink_mission.cpp index 601109653a6d..bbc93d06183e 100644 --- a/src/modules/mavlink/mavlink_mission.cpp +++ b/src/modules/mavlink/mavlink_mission.cpp @@ -1471,7 +1471,9 @@ MavlinkMissionManager::parse_mavlink_mission_item(const mavlink_mission_item_t * case MAV_CMD_NAV_LAND: mission_item->nav_cmd = NAV_CMD_LAND; - // TODO: abort alt param1 + // param1 is the minimum abort altitude above the landing point (0 = use the + // MIS_LND_ABRT_ALT default). Carry it in the otherwise-unused time_inside field. + mission_item->time_inside = mavlink_mission_item->param1; mission_item->yaw = wrap_2pi(math::radians(mavlink_mission_item->param4)); mission_item->land_precision = mavlink_mission_item->param2; break; @@ -1802,7 +1804,7 @@ MavlinkMissionManager::format_mavlink_mission_item(const struct mission_item_s * break; case NAV_CMD_LAND: - // TODO: param1 abort alt + mavlink_mission_item->param1 = mission_item->time_inside; // minimum abort altitude (0 = default) mavlink_mission_item->param2 = mission_item->land_precision; mavlink_mission_item->param4 = math::degrees(mission_item->yaw); break; diff --git a/src/modules/navigator/mission_base.cpp b/src/modules/navigator/mission_base.cpp index 8253c3b94992..3c863efba952 100644 --- a/src/modules/navigator/mission_base.cpp +++ b/src/modules/navigator/mission_base.cpp @@ -873,8 +873,16 @@ MissionBase::do_abort_landing() } const float alt_landing = get_absolute_altitude_for_item(_mission_item); - const float alt_sp = math::max(alt_landing + _navigator->get_landing_abort_min_alt(), - _global_pos_sub.get().alt); + + // Use the landing item's per-item abort altitude (NAV_CMD_LAND param1, carried in time_inside) + // if specified, otherwise fall back to the global MIS_LND_ABRT_ALT parameter. + float abort_min_alt = _navigator->get_landing_abort_min_alt(); + + if (_mission_item.time_inside > FLT_EPSILON) { + abort_min_alt = _mission_item.time_inside; + } + + const float alt_sp = math::max(alt_landing + abort_min_alt, _global_pos_sub.get().alt); // turn current landing waypoint into an indefinite loiter _mission_item.nav_cmd = NAV_CMD_LOITER_UNLIMITED; diff --git a/src/modules/navigator/mission_params.yaml b/src/modules/navigator/mission_params.yaml index 87666631687b..68d5cfd43394 100644 --- a/src/modules/navigator/mission_params.yaml +++ b/src/modules/navigator/mission_params.yaml @@ -92,6 +92,8 @@ parameters: long: |- Minimum altitude above landing point that the vehicle will climb to after an aborted landing. Then vehicle will loiter in this altitude until further command is received. + Used as the default when the landing mission item does not specify its own abort altitude + (MAV_CMD_NAV_LAND param1). Only applies to fixed-wing vehicles. type: int32 default: 30 From 3b1708866874418fded70e8fb1f1e5fc6fbb7230 Mon Sep 17 00:00:00 2001 From: Andrii Anoshyn Date: Sat, 30 May 2026 15:36:52 +0300 Subject: [PATCH 2/2] fix(navigator): clarify land abort altitude storage --- src/modules/mavlink/mavlink_mission.cpp | 7 +++---- src/modules/navigator/mission_base.cpp | 8 ++++---- src/modules/navigator/navigation.h | 1 + 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/modules/mavlink/mavlink_mission.cpp b/src/modules/mavlink/mavlink_mission.cpp index bbc93d06183e..00001019172f 100644 --- a/src/modules/mavlink/mavlink_mission.cpp +++ b/src/modules/mavlink/mavlink_mission.cpp @@ -1471,9 +1471,8 @@ MavlinkMissionManager::parse_mavlink_mission_item(const mavlink_mission_item_t * case MAV_CMD_NAV_LAND: mission_item->nav_cmd = NAV_CMD_LAND; - // param1 is the minimum abort altitude above the landing point (0 = use the - // MIS_LND_ABRT_ALT default). Carry it in the otherwise-unused time_inside field. - mission_item->time_inside = mavlink_mission_item->param1; + // param1 is the minimum abort altitude above the landing point (0 = use the MIS_LND_ABRT_ALT default). + mission_item->land_abort_min_alt = mavlink_mission_item->param1; mission_item->yaw = wrap_2pi(math::radians(mavlink_mission_item->param4)); mission_item->land_precision = mavlink_mission_item->param2; break; @@ -1804,7 +1803,7 @@ MavlinkMissionManager::format_mavlink_mission_item(const struct mission_item_s * break; case NAV_CMD_LAND: - mavlink_mission_item->param1 = mission_item->time_inside; // minimum abort altitude (0 = default) + mavlink_mission_item->param1 = mission_item->land_abort_min_alt; // minimum abort altitude (0 = default) mavlink_mission_item->param2 = mission_item->land_precision; mavlink_mission_item->param4 = math::degrees(mission_item->yaw); break; diff --git a/src/modules/navigator/mission_base.cpp b/src/modules/navigator/mission_base.cpp index 3c863efba952..1cdb4e9f068c 100644 --- a/src/modules/navigator/mission_base.cpp +++ b/src/modules/navigator/mission_base.cpp @@ -874,12 +874,12 @@ MissionBase::do_abort_landing() const float alt_landing = get_absolute_altitude_for_item(_mission_item); - // Use the landing item's per-item abort altitude (NAV_CMD_LAND param1, carried in time_inside) - // if specified, otherwise fall back to the global MIS_LND_ABRT_ALT parameter. + // Use the landing item's per-item abort altitude (NAV_CMD_LAND param1) if specified, + // otherwise fall back to the global MIS_LND_ABRT_ALT parameter. float abort_min_alt = _navigator->get_landing_abort_min_alt(); - if (_mission_item.time_inside > FLT_EPSILON) { - abort_min_alt = _mission_item.time_inside; + if (PX4_ISFINITE(_mission_item.land_abort_min_alt) && _mission_item.land_abort_min_alt > FLT_EPSILON) { + abort_min_alt = _mission_item.land_abort_min_alt; } const float alt_sp = math::max(alt_landing + abort_min_alt, _global_pos_sub.get().alt); diff --git a/src/modules/navigator/navigation.h b/src/modules/navigator/navigation.h index a6b9977dfcef..a12e7aeaf5b7 100644 --- a/src/modules/navigator/navigation.h +++ b/src/modules/navigator/navigation.h @@ -151,6 +151,7 @@ struct mission_item_s { union { float time_inside; /**< time that the MAV should stay inside the radius before advancing in seconds */ float circle_radius; /**< geofence circle radius in meters (only used for NAV_CMD_NAV_FENCE_CIRCLE*) */ + float land_abort_min_alt; /**< minimum abort altitude above landing point in meters (only used for NAV_CMD_LAND) */ }; float acceptance_radius; /**< default radius in which the mission is accepted as reached in meters */ float loiter_radius; /**< loiter radius in meters, 0 for a VTOL to hover, negative for counter-clockwise */