LCOV - code coverage report
Current view: top level - AP_Landing - AP_Landing.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 225 286 78.7 %
Date: 2026-09-09 11:02:08 Functions: 27 30 90.0 %

          Line data    Source code
       1             : /*
       2             :    This program is free software: you can redistribute it and/or modify
       3             :    it under the terms of the GNU General Public License as published by
       4             :    the Free Software Foundation, either version 3 of the License, or
       5             :    (at your option) any later version.
       6             : 
       7             :    This program is distributed in the hope that it will be useful,
       8             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
       9             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      10             :    GNU General Public License for more details.
      11             : 
      12             :    You should have received a copy of the GNU General Public License
      13             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      14             :  */
      15             : 
      16             : /*
      17             :  *   AP_Landing.cpp - Landing logic handler for ArduPlane
      18             :  */
      19             : 
      20             : #include "AP_Landing.h"
      21             : #include <GCS_MAVLink/GCS.h>
      22             : #include <AP_AHRS/AP_AHRS.h>
      23             : #include <AC_Fence/AC_Fence.h>
      24             : #include <AP_InternalError/AP_InternalError.h>
      25             : 
      26             : // table of user settable parameters
      27             : const AP_Param::GroupInfo AP_Landing::var_info[] = {
      28             : 
      29             :     // @Param: SLOPE_RCALC
      30             :     // @DisplayName: Landing slope re-calc threshold
      31             :     // @Description: This parameter is used when using a rangefinder during landing for altitude correction from baro drift (RNGFND_LANDING=1) and the altitude correction indicates your altitude is lower than the intended slope path. This value is the threshold of the correction to re-calculate the landing approach slope. Set to zero to keep the original slope all the way down and any detected baro drift will be corrected by pitching/throttling up to snap back to resume the original slope path. Otherwise, when a rangefinder altitude correction exceeds this threshold it will trigger a slope re-calculate to give a shallower slope. This also smoothes out the approach when flying over objects such as trees. Recommend a value of 2m.
      32             :     // @Range: 0 5
      33             :     // @Units: m
      34             :     // @Increment: 0.5
      35             :     // @User: Advanced
      36             :     AP_GROUPINFO("SLOPE_RCALC", 1, AP_Landing, slope_recalc_shallow_threshold, 2.0f),
      37             : 
      38             :     // @Param: ABORT_DEG
      39             :     // @DisplayName: Landing auto-abort slope threshold
      40             :     // @Description: This parameter is used when using a rangefinder during landing for altitude correction from baro drift (RNGFND_LANDING=1) and the altitude correction indicates your actual altitude is higher than the intended slope path. Normally it would pitch down steeply but that can result in a crash with high airspeed so this allows remembering the baro offset and self-abort the landing and come around for another landing with the correct baro offset applied for a perfect slope. An auto-abort go-around will only happen once, next attempt will not auto-abort again. This operation happens entirely automatically in AUTO mode. This value is the delta degrees threshold to trigger the go-around compared to the original slope. Example: if set to 5 deg and the mission planned slope is 15 deg then if the new slope is 21 then it will go-around. Set to 0 to disable. Requires LAND_SLOPE_RCALC > 0.
      41             :     // @Range: 0 90
      42             :     // @Units: deg
      43             :     // @Increment: 0.1
      44             :     // @User: Advanced
      45             :     AP_GROUPINFO("ABORT_DEG", 2, AP_Landing, slope_recalc_steep_threshold_to_abort, 0),
      46             : 
      47             :     // @Param: PITCH_DEG
      48             :     // @DisplayName: Landing Pitch
      49             :     // @Description: Used in autoland to give the minimum pitch in the final stage of landing (after the flare). This parameter can be used to ensure that the final landing attitude is appropriate for the type of undercarriage on the aircraft. Note that it is a minimum pitch only - the landing code will control pitch above this value to try to achieve the configured landing sink rate.
      50             :     // @Units: deg
      51             :     // @Range: -20 20
      52             :     // @Increment: 10
      53             :     // @User: Advanced
      54             :     AP_GROUPINFO("PITCH_DEG", 3, AP_Landing, pitch_deg, 0),
      55             : 
      56             :     // @Param: FLARE_ALT
      57             :     // @DisplayName: Landing flare altitude
      58             :     // @Description: Altitude in autoland at which to lock heading and flare to the LAND_PITCH_DEG pitch. Note that this option is secondary to LAND_FLARE_SEC. For a good landing it preferable that the flare is triggered by LAND_FLARE_SEC.
      59             :     // @Units: m
      60             :     // @Range: 0 30
      61             :     // @Increment: 0.1
      62             :     // @User: Advanced
      63             :     AP_GROUPINFO("FLARE_ALT", 4, AP_Landing, flare_alt, 3.0f),
      64             : 
      65             :     // @Param: FLARE_SEC
      66             :     // @DisplayName: Landing flare time
      67             :     // @Description: Vertical time before landing point at which to lock heading and flare with the motor stopped. This is vertical time, and is calculated based solely on the current height above the ground and the current descent rate.  Set to 0 if you only wish to flare based on altitude (see LAND_FLARE_ALT).
      68             :     // @Units: s
      69             :     // @Range: 0 10
      70             :     // @Increment: 0.1
      71             :     // @User: Advanced
      72             :     AP_GROUPINFO("FLARE_SEC", 5, AP_Landing, flare_sec, 2.0f),
      73             : 
      74             :     // @Param: PF_ALT
      75             :     // @DisplayName: Landing pre-flare altitude
      76             :     // @Description: Altitude to trigger pre-flare flight stage where LAND_PF_ARSPD controls airspeed. The pre-flare flight stage trigger works just like LAND_FLARE_ALT but higher. Disabled when LAND_PF_ARSPD is 0.
      77             :     // @Units: m
      78             :     // @Range: 0 30
      79             :     // @Increment: 0.1
      80             :     // @User: Advanced
      81             :     AP_GROUPINFO("PF_ALT", 6, AP_Landing, pre_flare_alt, 10.0f),
      82             : 
      83             :     // @Param: PF_SEC
      84             :     // @DisplayName: Landing pre-flare time
      85             :     // @Description: Vertical time to ground to trigger pre-flare flight stage where LAND_PF_ARSPD controls airspeed. This pre-flare flight stage trigger works just like LAND_FLARE_SEC but earlier. Disabled when LAND_PF_ARSPD is 0.
      86             :     // @Units: s
      87             :     // @Range: 0 10
      88             :     // @Increment: 0.1
      89             :     // @User: Advanced
      90             :     AP_GROUPINFO("PF_SEC", 7, AP_Landing, pre_flare_sec, 6.0f),
      91             : 
      92             :     // @Param: PF_ARSPD
      93             :     // @DisplayName: Landing pre-flare airspeed
      94             :     // @Description: Desired airspeed during pre-flare flight stage. This is useful to reduce airspeed just before the flare. Use 0 to disable.
      95             :     // @Units: m/s
      96             :     // @Range: 0 30
      97             :     // @Increment: 0.1
      98             :     // @User: Advanced
      99             :     AP_GROUPINFO("PF_ARSPD", 8, AP_Landing, pre_flare_airspeed, 0),
     100             : 
     101             :     // @Param: THR_SLEW
     102             :     // @DisplayName: Landing throttle slew rate
     103             :     // @Description: This parameter sets the slew rate for the throttle during auto landing. When this is zero the THR_SLEWRATE parameter is used during landing. The value is a percentage throttle change per second, so a value of 20 means to advance the throttle over 5 seconds on landing. Values below 50 are not recommended as it may cause a stall when airspeed is low and you can not throttle up fast enough.
     104             :     // @Units: %/s
     105             :     // @Range: 0 500
     106             :     // @Increment: 1
     107             :     // @User: Standard
     108             :     AP_GROUPINFO("THR_SLEW", 9, AP_Landing, throttle_slewrate, 0),
     109             : 
     110             :     // @Param: DISARMDELAY
     111             :     // @DisplayName: Landing disarm delay
     112             :     // @Description: After a landing has completed using a LAND waypoint, automatically disarm after this many seconds have passed. Use 0 to not disarm.
     113             :     // @Units: s
     114             :     // @Increment: 1
     115             :     // @Range: 0 127
     116             :     // @User: Advanced
     117             :     AP_GROUPINFO("DISARMDELAY", 10, AP_Landing, disarm_delay, 20),
     118             : 
     119             :     // @Param: THEN_NEUTRL
     120             :     // @DisplayName: Set servos to neutral after landing
     121             :     // @Description: When enabled, after an autoland and auto-disarm via LAND_DISARMDELAY happens then set all servos to neutral. This is helpful when an aircraft has a rough landing upside down or a crazy angle causing the servos to strain.
     122             :     // @Values: 0:Disabled, 1:Servos to Neutral, 2:Servos to Zero PWM
     123             :     // @User: Advanced
     124             :     AP_GROUPINFO("THEN_NEUTRL", 11, AP_Landing, then_servos_neutral, 0),
     125             : 
     126             :     // @Param: ABORT_THR
     127             :     // @DisplayName: Landing abort using throttle
     128             :     // @Description: Allow a landing abort to trigger with an input throttle >= 90%. This works with or without stick-mixing enabled.
     129             :     // @Values: 0:Disabled, 1:Enabled
     130             :     // @User: Advanced
     131             :     AP_GROUPINFO("ABORT_THR", 12, AP_Landing, abort_throttle_enable, 0),
     132             : 
     133             :     // @Param: FLAP_PERCNT
     134             :     // @DisplayName: Landing flap percentage
     135             :     // @Description: The amount of flaps (as a percentage) to apply in the landing approach and flare of an automatic landing
     136             :     // @Range: 0 100
     137             :     // @Units: %
     138             :     // @Increment: 1
     139             :     // @User: Advanced
     140             :     AP_GROUPINFO("FLAP_PERCNT", 13, AP_Landing, flap_percent, 0),
     141             : 
     142             :     // @Param: OPTIONS
     143             :     // @DisplayName: Landing options bitmask
     144             :     // @Description: Bitmask of options to use with landing.
     145             :     // @Bitmask: 0: honor min throttle during landing flare,1: Increase Target landing airspeed constraint From Trim Airspeed to AIRSPEED_MAX
     146             :     // @User: Advanced
     147             :     AP_GROUPINFO("OPTIONS", 16, AP_Landing, _options, 0),
     148             : 
     149             :     // @Param: FLARE_AIM
     150             :     // @DisplayName: Flare aim point adjustment percentage.
     151             :     // @Description: This parameter controls how much the aim point is moved to allow for the time spent in the flare manoeuvre. When set to 100% the aim point is adjusted on the assumption that the flare sink rate controller instantly achieves the sink rate set by TECS_LAND_SINK. when set to 0%, no aim point adjustment is made. If the plane consistently touches down short of the aim point reduce the parameter and vice verse.
     152             :     // @Range: 0 100
     153             :     // @Units: %
     154             :     // @Increment: 1
     155             :     // @User: Advanced
     156             :     AP_GROUPINFO("FLARE_AIM", 17, AP_Landing, flare_effectivness_pct, 50),
     157             : 
     158             :     // @Param: WIND_COMP
     159             :     // @DisplayName: Headwind Compensation when Landing
     160             :     // @Description: This param controls how much headwind compensation is used when landing.  Headwind speed component multiplied by this parameter is added to TECS_LAND_ARSPD command.  Set to Zero to disable.  Note:  The target landing airspeed command is still limited to AIRSPEED_MAX.
     161             :     // @Range: 0 100
     162             :     // @Units: %
     163             :     // @Increment: 1
     164             :     // @User: Advanced
     165             :     AP_GROUPINFO("WIND_COMP", 18, AP_Landing, wind_comp, 50),
     166             : 
     167             :     // @Param: TYPE
     168             :     // @DisplayName: Auto-landing type
     169             :     // @Description: Specifies the auto-landing type to use
     170             :     // @Values: 0:Standard Glide Slope, 1:Deepstall
     171             :     // @User: Standard
     172             :     AP_GROUPINFO_FLAGS("TYPE",    14, AP_Landing, type, TYPE_STANDARD_GLIDE_SLOPE, AP_PARAM_FLAG_ENABLE),
     173             : 
     174             : #if HAL_LANDING_DEEPSTALL_ENABLED
     175             :     // @Group: DS_
     176             :     // @Path: AP_Landing_Deepstall.cpp
     177             :     AP_SUBGROUPINFO(deepstall, "DS_", 15, AP_Landing, AP_Landing_Deepstall),
     178             : #endif
     179             : 
     180             :     // additional global params should be placed in the list above TYPE to avoid the enable flag hiding the deepstall params
     181             : 
     182             :     AP_GROUPEND
     183             : };
     184             : 
     185             :     // constructor
     186         692 : AP_Landing::AP_Landing(AP_Mission &_mission, AP_AHRS &_ahrs, AP_TECS *_tecs_Controller, AP_Navigation *_nav_controller, AP_FixedWing &_aparm,
     187             :                        set_target_altitude_proportion_fn_t _set_target_altitude_proportion_fn,
     188             :                        constrain_target_altitude_location_fn_t _constrain_target_altitude_location_fn,
     189             :                        adjusted_altitude_cm_fn_t _adjusted_altitude_cm_fn,
     190             :                        adjusted_relative_altitude_cm_fn_t _adjusted_relative_altitude_cm_fn,
     191             :                        disarm_if_autoland_complete_fn_t _disarm_if_autoland_complete_fn,
     192         692 :                        update_flight_stage_fn_t _update_flight_stage_fn) :
     193         692 :     mission(_mission)
     194         692 :     ,ahrs(_ahrs)
     195         692 :     ,tecs_Controller(_tecs_Controller)
     196         692 :     ,nav_controller(_nav_controller)
     197         692 :     ,aparm(_aparm)
     198         692 :     ,set_target_altitude_proportion_fn(_set_target_altitude_proportion_fn)
     199         692 :     ,constrain_target_altitude_location_fn(_constrain_target_altitude_location_fn)
     200         692 :     ,adjusted_altitude_cm_fn(_adjusted_altitude_cm_fn)
     201         692 :     ,adjusted_relative_altitude_cm_fn(_adjusted_relative_altitude_cm_fn)
     202         692 :     ,disarm_if_autoland_complete_fn(_disarm_if_autoland_complete_fn)
     203         692 :     ,update_flight_stage_fn(_update_flight_stage_fn)
     204             : #if HAL_LANDING_DEEPSTALL_ENABLED
     205         692 :     ,deepstall(*this)
     206             : #endif
     207             : {
     208         692 :     AP_Param::setup_object_defaults(this, var_info);
     209         692 : }
     210             : 
     211             : /*
     212             :   return a location alt in cm as AMSL
     213             :   assumes loc frame is either AMSL or ABOVE_TERRAIN
     214             : */
     215       24153 : int32_t AP_Landing::loc_alt_AMSL_cm(const Location &loc) const
     216             : {
     217             :     int32_t alt_cm;
     218             :     // try first with full conversion
     219       24153 :     if (loc.get_alt_cm(Location::AltFrame::ABSOLUTE, alt_cm)) {
     220       24153 :         return alt_cm;
     221             :     }
     222           0 :     if (loc.get_alt_frame() == Location::AltFrame::ABOVE_TERRAIN) {
     223             :         // if we can't get true terrain then assume flat terrain
     224             :         // around home
     225           0 :         return loc.alt + ahrs.get_home().alt;
     226             :     }
     227             : 
     228             :     // this should not happen, but return a value
     229           0 :     INTERNAL_ERROR(AP_InternalError::error_t::flow_of_control);
     230           0 :     return loc.alt;
     231             : }
     232             : 
     233         114 : void AP_Landing::do_land(const AP_Mission::Mission_Command& cmd, const float relative_altitude)
     234             : {
     235         114 :     Log(); // log old state so we get a nice transition from old to new here
     236             : 
     237         114 :     flags.commanded_go_around = false;
     238             : 
     239         114 :     switch (type) {
     240         113 :     case TYPE_STANDARD_GLIDE_SLOPE:
     241         113 :         type_slope_do_land(cmd, relative_altitude);
     242         113 :         break;
     243             : #if HAL_LANDING_DEEPSTALL_ENABLED
     244           1 :     case TYPE_DEEPSTALL:
     245           1 :         deepstall.do_land(cmd, relative_altitude);
     246           1 :         break;
     247             : #endif
     248           0 :     default:
     249             :         // a incorrect type is handled in the verify_land
     250           0 :         break;
     251             :     }
     252             : 
     253         114 :     Log();
     254         114 : }
     255             : 
     256             : /*
     257             :   update navigation for landing. Called when on landing approach or
     258             :   final flare
     259             :  */
     260       38886 : bool AP_Landing::verify_land(const Location &prev_WP_loc, Location &next_WP_loc, const Location &current_loc,
     261             :         const float height, const float sink_rate, const float wp_proportion, const uint32_t last_flying_ms, const bool is_armed, const bool is_flying, const bool rangefinder_state_in_range)
     262             : {
     263       38886 :     bool success = true;
     264             : 
     265       38886 :     switch (type) {
     266       37991 :     case TYPE_STANDARD_GLIDE_SLOPE:
     267       37991 :         success = type_slope_verify_land(prev_WP_loc, next_WP_loc, current_loc,
     268             :                 height, sink_rate, wp_proportion, last_flying_ms, is_armed, is_flying, rangefinder_state_in_range);
     269       37991 :         break;
     270             : #if HAL_LANDING_DEEPSTALL_ENABLED
     271         895 :     case TYPE_DEEPSTALL:
     272         895 :         success = deepstall.verify_land(prev_WP_loc, next_WP_loc, current_loc,
     273             :                                              height, sink_rate, wp_proportion, last_flying_ms, is_armed, is_flying, rangefinder_state_in_range);
     274         895 :         break;
     275             : #endif
     276           0 :     default:
     277             :         // returning TRUE while executing verify_land() will increment the
     278             :         // mission index which in many cases will trigger an RTL for end-of-mission
     279           0 :         GCS_SEND_TEXT(MAV_SEVERITY_CRITICAL, "Landing configuration error, invalid LAND_TYPE");
     280           0 :         success = true;
     281           0 :         break;
     282             :     }
     283       38886 :     Log();
     284       38886 :     return success;
     285             : }
     286             : 
     287         247 : bool AP_Landing::verify_abort_landing(const Location &prev_WP_loc, Location &next_WP_loc, const Location &current_loc,
     288             :     const int32_t auto_state_takeoff_altitude_rel_cm, bool &throttle_suppressed)
     289             : {
     290         247 :     switch (type) {
     291         247 :     case TYPE_STANDARD_GLIDE_SLOPE:
     292         247 :         type_slope_verify_abort_landing(prev_WP_loc, next_WP_loc, throttle_suppressed);
     293         247 :         break;
     294             : #if HAL_LANDING_DEEPSTALL_ENABLED
     295           0 :     case TYPE_DEEPSTALL:
     296           0 :         deepstall.verify_abort_landing(prev_WP_loc, next_WP_loc, throttle_suppressed);
     297           0 :         break;
     298             : #endif
     299           0 :     default:
     300           0 :         break;
     301             :     }
     302             : 
     303             :     // see if we have reached abort altitude
     304         247 :      if (adjusted_relative_altitude_cm_fn() > auto_state_takeoff_altitude_rel_cm) {
     305           2 :          next_WP_loc = current_loc;
     306           2 :          mission.stop();
     307           2 :          if (restart_landing_sequence()) {
     308           2 :              mission.resume();
     309             :          }
     310             :          // else we're in AUTO with a stopped mission and handle_auto_mode() will set RTL
     311             : #if AP_FENCE_ENABLED
     312           2 :         AC_Fence *fence = AP::fence();
     313           2 :         if (fence) {
     314           2 :             fence->auto_enable_fence_after_takeoff();
     315             :         }
     316             : #endif
     317             :      }
     318             : 
     319         247 :      Log();
     320             : 
     321             :      // make sure to always return false so it leaves the mission index alone
     322         247 :      return false;
     323             : }
     324             : 
     325        6253 : void AP_Landing::adjust_landing_slope_for_rangefinder_bump(AP_FixedWing::Rangefinder_State &rangefinder_state, Location &prev_WP_loc, Location &next_WP_loc, const Location &current_loc, const float wp_distance, int32_t &target_altitude_offset_cm)
     326             : {
     327        6253 :     switch (type) {
     328        6097 :     case TYPE_STANDARD_GLIDE_SLOPE:
     329        6097 :         type_slope_adjust_landing_slope_for_rangefinder_bump(rangefinder_state, prev_WP_loc, next_WP_loc, current_loc, wp_distance, target_altitude_offset_cm);
     330        6097 :         break;
     331             : #if HAL_LANDING_DEEPSTALL_ENABLED
     332         156 :     case TYPE_DEEPSTALL:
     333             : #endif
     334             :     default:
     335         156 :         break;
     336             :     }
     337        6253 : }
     338             : 
     339             : // send out any required mavlink messages
     340      552407 : bool AP_Landing::send_landing_message(mavlink_channel_t chan) {
     341      552407 :     if (!flags.in_progress) {
     342      516325 :         return false;
     343             :     }
     344             : 
     345       36082 :     switch (type) {
     346             : #if HAL_LANDING_DEEPSTALL_ENABLED
     347         894 :     case TYPE_DEEPSTALL:
     348         894 :         return deepstall.send_deepstall_message(chan);
     349             : #endif
     350       35188 :     case TYPE_STANDARD_GLIDE_SLOPE:
     351             :     default:
     352       35188 :         return false;
     353             :     }
     354             : }
     355             : 
     356    21786200 : bool AP_Landing::is_flaring(void) const
     357             : {
     358    21786200 :     if (!flags.in_progress) {
     359    20910225 :         return false;
     360             :     }
     361             : 
     362      875975 :     switch (type) {
     363      858102 :     case TYPE_STANDARD_GLIDE_SLOPE:
     364      858102 :         return type_slope_is_flaring();
     365             : #if HAL_LANDING_DEEPSTALL_ENABLED
     366       17873 :     case TYPE_DEEPSTALL:
     367             : #endif
     368             :     default:
     369       17873 :         return false;
     370             :     }
     371             : }
     372             : 
     373             : // return true if the landing is at the pre-flare stage or later
     374     1657292 : bool AP_Landing::is_on_final(void) const
     375             : {
     376     1657292 :     if (!flags.in_progress) {
     377     1476766 :         return false;
     378             :     }
     379             : 
     380      180526 :     switch (type) {
     381      176056 :     case TYPE_STANDARD_GLIDE_SLOPE:
     382      176056 :         return type_slope_is_on_final();
     383             : #if HAL_LANDING_DEEPSTALL_ENABLED
     384        4470 :     case TYPE_DEEPSTALL:
     385             : #endif
     386             :     default:
     387        4470 :         return false;
     388             :     }
     389             : }
     390             : 
     391             : // return true while the aircraft is performing a landing approach
     392             : // when true the vehicle will:
     393             : //   - disable ground steering
     394             : //   - call setup_landing_glide_slope() and adjust_landing_slope_for_rangefinder_bump()
     395             : //   - will be considered flying if sink rate > 0.2, and can trigger crash detection
     396     1720549 : bool AP_Landing::is_on_approach(void) const
     397             : {
     398     1720549 :     if (!flags.in_progress) {
     399     1572040 :         return false;
     400             :     }
     401             : 
     402      148509 :     switch (type) {
     403      143697 :     case TYPE_STANDARD_GLIDE_SLOPE:
     404      143697 :         return type_slope_is_on_approach();
     405             : #if HAL_LANDING_DEEPSTALL_ENABLED
     406        4812 :     case TYPE_DEEPSTALL:
     407        4812 :         return deepstall.is_on_approach();
     408             : #endif
     409           0 :     default:
     410           0 :         return false;
     411             :     }
     412             : }
     413             : 
     414             : // return true while the aircraft is allowed to perform ground steering
     415     6174463 : bool AP_Landing::is_ground_steering_allowed(void) const
     416             : {
     417     6174463 :     if (!flags.in_progress) {
     418     6099912 :         return true;
     419             :     }
     420             : 
     421       74551 :     switch (type) {
     422       70081 :     case TYPE_STANDARD_GLIDE_SLOPE:
     423       70081 :         return type_slope_is_on_approach();
     424             : #if HAL_LANDING_DEEPSTALL_ENABLED
     425        4470 :     case TYPE_DEEPSTALL:
     426        4470 :         return false;
     427             : #endif
     428           0 :     default:
     429           0 :         return true;
     430             :     }
     431             : }
     432             : 
     433             : // return true when at the last stages of a land when an impact with the ground is expected soon
     434             : // when true is_flying knows that the vehicle was expecting to stop flying, possibly because of a hard impact
     435        5688 : bool AP_Landing::is_expecting_impact(void) const
     436             : {
     437        5688 :     if (!flags.in_progress) {
     438        4998 :         return false;
     439             :     }
     440             : 
     441         690 :     switch (type) {
     442         690 :     case TYPE_STANDARD_GLIDE_SLOPE:
     443         690 :         return type_slope_is_expecting_impact();
     444             : #if HAL_LANDING_DEEPSTALL_ENABLED
     445           0 :     case TYPE_DEEPSTALL:
     446             : #endif
     447             :     default:
     448           0 :         return false;
     449             :     }
     450             : }
     451             : 
     452             : // returns true when the landing library has overriden any servos
     453      197641 : bool AP_Landing::override_servos(void) {
     454      197641 :     if (!flags.in_progress) {
     455           0 :         return false;
     456             :     }
     457             : 
     458      197641 :     switch (type) {
     459             : #if HAL_LANDING_DEEPSTALL_ENABLED
     460        4470 :     case TYPE_DEEPSTALL:
     461        4470 :         return deepstall.override_servos();
     462             : #endif
     463      193171 :     case TYPE_STANDARD_GLIDE_SLOPE:
     464             :     default:
     465      193171 :         return false;
     466             :     }
     467             : }
     468             : 
     469             : // returns a PID_Info object if there is one available for the selected landing
     470             : // type, otherwise returns a nullptr, indicating no data to be logged/sent
     471           0 : const AP_PIDInfo* AP_Landing::get_pid_info(void) const
     472             : {
     473           0 :     switch (type) {
     474             : #if HAL_LANDING_DEEPSTALL_ENABLED
     475           0 :     case TYPE_DEEPSTALL:
     476           0 :         return &deepstall.get_pid_info();
     477             : #endif
     478           0 :     case TYPE_STANDARD_GLIDE_SLOPE:
     479             :     default:
     480           0 :         return nullptr;
     481             :     }
     482             : }
     483             : 
     484             : /*
     485             :   a special glide slope calculation for the landing approach
     486             : 
     487             :   During the land approach use a linear glide slope to a point
     488             :   projected through the landing point. We don't use the landing point
     489             :   itself as that leads to discontinuities close to the landing point,
     490             :   which can lead to erratic pitch control
     491             :  */
     492             : 
     493        6253 : void AP_Landing::setup_landing_glide_slope(const Location &prev_WP_loc, const Location &next_WP_loc, const Location &current_loc, int32_t &target_altitude_offset_cm)
     494             : {
     495        6253 :     switch (type) {
     496        6097 :     case TYPE_STANDARD_GLIDE_SLOPE:
     497        6097 :         type_slope_setup_landing_glide_slope(prev_WP_loc, next_WP_loc, current_loc, target_altitude_offset_cm);
     498        6097 :         break;
     499             : #if HAL_LANDING_DEEPSTALL_ENABLED
     500         156 :     case TYPE_DEEPSTALL:
     501             : #endif
     502             :     default:
     503         156 :         break;
     504             :     }
     505        6253 : }
     506             : 
     507             : /*
     508             :   reset landing state
     509             :  */
     510        1929 : void AP_Landing::reset(void)
     511             : {
     512        1929 :     initial_slope = 0;
     513        1929 :     slope = 0;
     514        1929 :     type_slope_flags.post_stats = false;
     515        1929 :     type_slope_flags.has_aborted_due_to_slope_recalc = false;
     516        1929 :     type_slope_stage = SlopeStage::NORMAL;
     517        1929 : }
     518             : 
     519             : /*
     520             :      Restart a landing by first checking for a DO_LAND_START and
     521             :      jump there. Otherwise decrement waypoint so we would re-start
     522             :      from the top with same glide slope. Return true if successful.
     523             :  */
     524          58 : bool AP_Landing::restart_landing_sequence()
     525             : {
     526          58 :     if (mission.get_current_nav_cmd().id != MAV_CMD_NAV_LAND) {
     527           0 :         return false;
     528             :     }
     529             : 
     530          58 :     uint16_t do_land_start_index = 0;
     531          58 :     Location loc;
     532          58 :     if (ahrs.get_location(loc)) {
     533          58 :         do_land_start_index = mission.get_landing_sequence_start(loc);
     534             :     }
     535          58 :     uint16_t prev_cmd_with_wp_index = mission.get_prev_nav_cmd_with_wp_index();
     536          58 :     bool success = false;
     537          58 :     uint16_t current_index = mission.get_current_nav_index();
     538          58 :     AP_Mission::Mission_Command cmd;
     539             : 
     540          58 :     if (mission.read_cmd_from_storage(current_index+1,cmd) &&
     541           3 :             cmd.id == MAV_CMD_NAV_CONTINUE_AND_CHANGE_ALT &&
     542          61 :             (cmd.p1 == 0 || cmd.p1 == 1) &&
     543           0 :             mission.set_current_cmd(current_index+1))
     544             :     {
     545             :         // if the next immediate command is MAV_CMD_NAV_CONTINUE_AND_CHANGE_ALT to climb, do it
     546           0 :         GCS_SEND_TEXT(MAV_SEVERITY_NOTICE, "Restarted landing sequence. Climbing to %dm", (signed)cmd.content.location.alt/100);
     547           0 :         success =  true;
     548             :     }
     549          64 :     else if (do_land_start_index != 0 &&
     550           6 :             mission.set_current_cmd(do_land_start_index))
     551             :     {
     552             :         // look for a DO_LAND_START and use that index
     553           6 :         GCS_SEND_TEXT(MAV_SEVERITY_NOTICE, "Restarted landing via DO_LAND_START: %d",do_land_start_index);
     554           6 :         success =  true;
     555             :     }
     556         104 :     else if (prev_cmd_with_wp_index != AP_MISSION_CMD_INDEX_NONE &&
     557          52 :                mission.set_current_cmd(prev_cmd_with_wp_index))
     558             :     {
     559             :         // if a suitable navigation waypoint was just executed, one that contains lat/lng/alt, then
     560             :         // repeat that cmd to restart the landing from the top of approach to repeat intended glide slope
     561           0 :         GCS_SEND_TEXT(MAV_SEVERITY_NOTICE, "Restarted landing sequence at waypoint %d", prev_cmd_with_wp_index);
     562           0 :         success =  true;
     563             :     } else {
     564          52 :         GCS_SEND_TEXT(MAV_SEVERITY_WARNING, "Unable to restart landing sequence");
     565          52 :         success =  false;
     566             :     }
     567             : 
     568          58 :     if (success) {
     569             :         // exit landing stages if we're no longer executing NAV_LAND
     570           6 :         update_flight_stage_fn();
     571             :     }
     572             : 
     573          58 :     Log();
     574          58 :     return success;
     575             : }
     576             : 
     577      207583 : int32_t AP_Landing::constrain_roll(const int32_t desired_roll_cd, const int32_t level_roll_limit_cd)
     578             : {
     579      207583 :     switch (type) {
     580      203106 :     case TYPE_STANDARD_GLIDE_SLOPE:
     581      203106 :         return type_slope_constrain_roll(desired_roll_cd, level_roll_limit_cd);
     582             : #if HAL_LANDING_DEEPSTALL_ENABLED
     583        4477 :     case TYPE_DEEPSTALL:
     584             : #endif
     585             :     default:
     586        4477 :         return desired_roll_cd;
     587             :     }
     588             : }
     589             : 
     590             : // returns true if landing provided a Location structure with the current target altitude
     591      497799 : bool AP_Landing::get_target_altitude_location(Location &location)
     592             : {
     593      497799 :     if (!flags.in_progress) {
     594      491092 :         return false;
     595             :     }
     596             : 
     597        6707 :     switch (type) {
     598             : #if HAL_LANDING_DEEPSTALL_ENABLED
     599         739 :     case TYPE_DEEPSTALL:
     600         739 :         return deepstall.get_target_altitude_location(location);
     601             : #endif
     602        5968 :     case TYPE_STANDARD_GLIDE_SLOPE:
     603             :     default:
     604        5968 :         return false;
     605             :     }
     606             : }
     607             : 
     608             : /*
     609             :  * returns target airspeed in m/s depending on flight stage
     610             :  */
     611       36337 : float AP_Landing::get_target_airspeed_ms(void)
     612             : {
     613       36337 :     if (!flags.in_progress) {
     614             :         // not landing, use regular cruise airspeed
     615           0 :         return aparm.airspeed_cruise;
     616             :     }
     617             : 
     618       36337 :     switch (type) {
     619       35442 :     case TYPE_STANDARD_GLIDE_SLOPE:
     620       35442 :         return type_slope_get_target_airspeed_ms();
     621             : #if HAL_LANDING_DEEPSTALL_ENABLED
     622         895 :     case TYPE_DEEPSTALL:
     623         895 :         return deepstall.get_target_airspeed_ms();
     624             : #endif
     625           0 :     default:
     626             :         // don't return the landing airspeed, because if type is invalid we have
     627             :         // no postive indication that the land airspeed has been configured or
     628             :         // how it was meant to be utilized
     629           0 :         return tecs_Controller->get_target_airspeed();
     630             :     }
     631             : }
     632             : 
     633             : /*
     634             :  * request a landing abort given the landing type
     635             :  * return true on success
     636             :  */
     637           2 : bool AP_Landing::request_go_around(void)
     638             : {
     639           2 :     bool success = false;
     640             : 
     641           2 :     switch (type) {
     642           2 :     case TYPE_STANDARD_GLIDE_SLOPE:
     643           2 :         success = type_slope_request_go_around();
     644           2 :         break;
     645             : #if HAL_LANDING_DEEPSTALL_ENABLED
     646           0 :     case TYPE_DEEPSTALL:
     647           0 :         success = deepstall.request_go_around();
     648           0 :         break;
     649             : #endif
     650           0 :     default:
     651           0 :         break;
     652             :     }
     653             : 
     654           2 :     Log();
     655           2 :     return success;
     656             : }
     657             : 
     658        8085 : void AP_Landing::handle_flight_stage_change(const bool _in_landing_stage)
     659             : {
     660        8085 :     Log(); // log old value to plot discrete transitions
     661        8085 :     flags.in_progress = _in_landing_stage;
     662        8085 :     flags.commanded_go_around = false;
     663        8085 :     Log();
     664        8085 : }
     665             : 
     666             : /*
     667             :  * returns true when a landing is complete, usually used to disable throttle
     668             :  */
     669           0 : bool AP_Landing::is_complete(void) const
     670             : {
     671           0 :     switch (type) {
     672           0 :     case TYPE_STANDARD_GLIDE_SLOPE:
     673           0 :         return type_slope_is_complete();
     674             : #if HAL_LANDING_DEEPSTALL_ENABLED
     675           0 :     case TYPE_DEEPSTALL:
     676           0 :         return false;
     677             : #endif
     678           0 :     default:
     679           0 :         return true;
     680             :     }
     681             : }
     682             : 
     683       55591 : void AP_Landing::Log(void) const
     684             : {
     685             : #if HAL_LOGGING_ENABLED
     686       55591 :     switch (type) {
     687       54686 :     case TYPE_STANDARD_GLIDE_SLOPE:
     688       54686 :         type_slope_log();
     689       54686 :         break;
     690             : #if HAL_LANDING_DEEPSTALL_ENABLED
     691         905 :     case TYPE_DEEPSTALL:
     692         905 :         deepstall.Log();
     693         905 :         break;
     694             : #endif
     695           0 :     default:
     696           0 :         break;
     697             :     }
     698             : #endif
     699       55591 : }
     700             : 
     701             : /*
     702             :  * returns true when throttle should be suppressed while landing
     703             :  */
     704     7998449 : bool AP_Landing::is_throttle_suppressed(void) const
     705             : {
     706     7998449 :     if (!flags.in_progress) {
     707     7603167 :         return false;
     708             :     }
     709             : 
     710      395282 :     switch (type) {
     711      386342 :     case TYPE_STANDARD_GLIDE_SLOPE:
     712      386342 :         return type_slope_is_throttle_suppressed();
     713             : #if HAL_LANDING_DEEPSTALL_ENABLED
     714        8940 :     case TYPE_DEEPSTALL:
     715        8940 :         return deepstall.is_throttle_suppressed();
     716             : #endif
     717           0 :     default:
     718           0 :         return false;
     719             :     }
     720             : }
     721             : 
     722             : //defaults to false, but _options bit zero enables it.
     723      123090 : bool AP_Landing::use_thr_min_during_flare(void) const
     724             : {
     725      123090 :     return (OptionsMask::ON_LANDING_FLARE_USE_THR_MIN & _options) != 0;
     726             : }
     727             : 
     728             : //defaults to false, but _options bit zero enables it.
     729       35442 : bool AP_Landing::allow_max_airspeed_on_land(void) const
     730             : {
     731       35442 :     return (OptionsMask::ON_LANDING_USE_ARSPD_MAX & _options) != 0;
     732             : }
     733             : 
     734             : /*
     735             :  * returns false when the vehicle might not be flying forward while landing
     736             :  */
     737      197641 : bool AP_Landing::is_flying_forward(void) const
     738             : {
     739      197641 :     if (!flags.in_progress) {
     740           0 :         return true;
     741             :     }
     742             : 
     743      197641 :     switch (type) {
     744             : #if HAL_LANDING_DEEPSTALL_ENABLED
     745        4470 :     case TYPE_DEEPSTALL:
     746        4470 :         return deepstall.is_flying_forward();
     747             : #endif
     748      193171 :     case TYPE_STANDARD_GLIDE_SLOPE:
     749             :     default:
     750      193171 :         return true;
     751             :     }
     752             : }
     753             : 
     754             : /*
     755             :  * attempt to terminate flight with an immediate landing
     756             :  * returns true if the landing library can and is terminating the landing
     757             :  */
     758           0 : bool AP_Landing::terminate(void) {
     759           0 :     switch (type) {
     760             : #if HAL_LANDING_DEEPSTALL_ENABLED
     761           0 :     case TYPE_DEEPSTALL:
     762           0 :         return deepstall.terminate();
     763             : #endif
     764           0 :     case TYPE_STANDARD_GLIDE_SLOPE:
     765             :     default:
     766           0 :         return false;
     767             :     }
     768             : }
     769             : 
     770             : /*
     771             :   run parameter conversions
     772             :  */
     773         692 : void AP_Landing::convert_parameters(void)
     774             : {
     775             :     // PARAMETER_CONVERSION - Added: Jan-2024 for ArduPilot-4.5
     776         692 :     pitch_deg.convert_centi_parameter(AP_PARAM_INT16);
     777             : 
     778             :     // PARAMETER_CONVERSION - Added: Mar-2026 for THR_SLEWRATE width change
     779             :     // Convert throttle slewrate from int8 to int16 to support higher slew rates
     780         692 :     throttle_slewrate.convert_parameter_width(AP_PARAM_INT8);
     781         692 : }

Generated by: LCOV version 1.14