LCOV - code coverage report
Current view: top level - home/pbarker/rc/ardupilot/Rover - failsafe.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 42 79 53.2 %
Date: 2026-09-09 11:02:08 Functions: 2 3 66.7 %

          Line data    Source code
       1             : /*
       2             :   failsafe support
       3             :   Andrew Tridgell, December 2011
       4             :  */
       5             : 
       6             : #include "Rover.h"
       7             : 
       8             : #include <stdio.h>
       9             : 
      10             : /*
      11             :   our failsafe strategy is to detect main loop lockup and disarm.
      12             :  */
      13             : 
      14             : /*
      15             :   this failsafe_check function is called from the core timer interrupt
      16             :   at 1kHz.
      17             :  */
      18    15369390 : void Rover::failsafe_check()
      19             : {
      20             :     static uint16_t last_ticks;
      21             :     static uint32_t last_timestamp;
      22    15369390 :     const uint32_t tnow = AP_HAL::micros();
      23             : 
      24    15369390 :     const uint16_t ticks = scheduler.ticks();
      25    15369390 :     if (ticks != last_ticks) {
      26             :         // the main loop is running, all is OK
      27      629048 :         last_ticks = ticks;
      28      629048 :         last_timestamp = tnow;
      29      629048 :         return;
      30             :     }
      31             : 
      32    14740342 :     if (tnow - last_timestamp > 200000) {
      33             :         // we have gone at least 0.2 seconds since the main loop
      34             :         // ran. That means we're in trouble, or perhaps are in
      35             :         // an initialisation routine or log erase. disarm the motors
      36             :         // To-Do: log error
      37      215675 :         if (arming.is_armed()) {
      38             :             // disarm motors
      39           0 :             arming.disarm(AP_Arming::Method::CPUFAILSAFE);
      40             :         }
      41             :     }
      42             : }
      43             : 
      44             : /*
      45             :   called to set/unset a failsafe event.
      46             :  */
      47      618038 : void Rover::failsafe_trigger(uint8_t failsafe_type, const char* type_str, bool on)
      48             : {
      49      618038 :     uint8_t old_bits = failsafe.bits;
      50      618038 :     if (on) {
      51        2758 :         failsafe.bits |= failsafe_type;
      52             :     } else {
      53      615280 :         failsafe.bits &= ~failsafe_type;
      54             :     }
      55      618038 :     if (old_bits == 0 && failsafe.bits != 0) {
      56             :         // a failsafe event has started
      57          13 :         failsafe.start_time = millis();
      58             :     }
      59      618038 :     if (failsafe.triggered != 0 && failsafe.bits == 0) {
      60             :         // a failsafe event has ended
      61           8 :         GCS_SEND_TEXT(MAV_SEVERITY_INFO, "%s Failsafe Cleared", type_str);
      62             :     }
      63             : 
      64      618038 :     failsafe.triggered &= failsafe.bits;
      65             : 
      66      618038 :     if (failsafe_type == FAILSAFE_EVENT_GCS) {
      67        2010 :         AP_Notify::flags.failsafe_gcs = on;
      68             :     }
      69             : 
      70     1852127 :     if ((failsafe.triggered == 0) &&
      71      616051 :         (failsafe.bits != 0) &&
      72         771 :         (millis() - failsafe.start_time > g.fs_timeout * 1000) &&
      73     1234335 :         (control_mode != &mode_rtl) &&
      74         246 :         ((control_mode != &mode_hold || (g2.fs_options & (uint32_t)Failsafe_Options::Failsafe_Option_Active_In_Hold)))) {
      75           8 :         failsafe.triggered = failsafe.bits;
      76           8 :         GCS_SEND_TEXT(MAV_SEVERITY_WARNING, "%s Failsafe", type_str);
      77             : 
      78             :         // clear rc overrides
      79           8 :         RC_Channels::clear_overrides();
      80             : 
      81           9 :         if ((control_mode == &mode_auto) &&
      82           1 :             ((failsafe_type == FAILSAFE_EVENT_THROTTLE && g.fs_throttle_enabled == FS_THR_ENABLED_CONTINUE_MISSION) ||
      83           1 :              (failsafe_type == FAILSAFE_EVENT_GCS && g.fs_gcs_enabled == FS_GCS_ENABLED_CONTINUE_MISSION))) {
      84             :             // continue with mission in auto mode
      85           1 :             GCS_SEND_TEXT(MAV_SEVERITY_WARNING, "Failsafe - Continuing Auto Mode");
      86             :         } else {
      87           7 :             switch ((FailsafeAction)g.fs_action.get()) {
      88           1 :             case FailsafeAction::None:
      89           1 :                 break;
      90           0 :             case FailsafeAction::SmartRTL:
      91           0 :                 if (set_mode(mode_smartrtl, ModeReason::FAILSAFE)) {
      92           0 :                     break;
      93             :                 }
      94             :                 FALLTHROUGH;
      95             :             case FailsafeAction::RTL:
      96           4 :                 if (set_mode(mode_rtl, ModeReason::FAILSAFE)) {
      97           4 :                     break;
      98             :                 }
      99             :                 FALLTHROUGH;
     100             :             case FailsafeAction::Hold:
     101           0 :                 set_mode(mode_hold, ModeReason::FAILSAFE);
     102           0 :                 break;
     103           0 :             case FailsafeAction::SmartRTL_Hold:
     104           0 :                 if (!set_mode(mode_smartrtl, ModeReason::FAILSAFE)) {
     105           0 :                     set_mode(mode_hold, ModeReason::FAILSAFE);
     106             :                 }
     107           0 :                 break;
     108           2 :             case FailsafeAction::Loiter_Hold:
     109           2 :                 if (!set_mode(mode_loiter, ModeReason::FAILSAFE)) {
     110           0 :                     set_mode(mode_hold, ModeReason::FAILSAFE);
     111             :                 }
     112           2 :                 break;
     113           0 :             case FailsafeAction::Terminate:
     114           0 :                 arming.disarm(AP_Arming::Method::FAILSAFE_ACTION_TERMINATE);
     115           0 :                 break;
     116             :             }
     117             :         }
     118             :     }
     119      618038 : }
     120             : 
     121           0 : void Rover::handle_battery_failsafe(const char* type_str, const int8_t action)
     122             : {
     123           0 :         switch ((FailsafeAction)action) {
     124           0 :             case FailsafeAction::None:
     125           0 :                 break;
     126           0 :             case FailsafeAction::SmartRTL:
     127           0 :                 if (set_mode(mode_smartrtl, ModeReason::BATTERY_FAILSAFE)) {
     128           0 :                     break;
     129             :                 }
     130             :                 FALLTHROUGH;
     131             :             case FailsafeAction::RTL:
     132           0 :                 if (set_mode(mode_rtl, ModeReason::BATTERY_FAILSAFE)) {
     133           0 :                     break;
     134             :                 }
     135             :                 FALLTHROUGH;
     136             :             case FailsafeAction::Hold:
     137           0 :                 set_mode(mode_hold, ModeReason::BATTERY_FAILSAFE);
     138           0 :                 break;
     139           0 :             case FailsafeAction::Loiter_Hold:
     140           0 :                 if (!set_mode(mode_loiter, ModeReason::BATTERY_FAILSAFE)) {
     141           0 :                     set_mode(mode_hold, ModeReason::BATTERY_FAILSAFE);
     142             :                 }
     143           0 :                 break;
     144           0 :             case FailsafeAction::SmartRTL_Hold:
     145           0 :                 if (!set_mode(mode_smartrtl, ModeReason::BATTERY_FAILSAFE)) {
     146           0 :                     set_mode(mode_hold, ModeReason::BATTERY_FAILSAFE);
     147             :                 }
     148           0 :                 break;
     149           0 :             case FailsafeAction::Terminate:
     150             : #if AP_ROVER_ADVANCED_FAILSAFE_ENABLED
     151             :                 char battery_type_str[17];
     152             :                 snprintf(battery_type_str, 17, "%s battery", type_str);
     153             :                 g2.afs.gcs_terminate(true, battery_type_str);
     154             : #else
     155           0 :                 arming.disarm(AP_Arming::Method::BATTERYFAILSAFE);
     156             : #endif // AP_ROVER_ADVANCED_FAILSAFE_ENABLED
     157           0 :                 break;
     158             :         }
     159           0 : }
     160             : 
     161             : #if AP_ROVER_ADVANCED_FAILSAFE_ENABLED
     162             : /*
     163             :    check for AFS failsafe check
     164             :  */
     165             : void Rover::afs_fs_check(void)
     166             : {
     167             :     // perform AFS failsafe checks
     168             :     g2.afs.check(failsafe.last_valid_rc_ms);
     169             : }
     170             : #endif

Generated by: LCOV version 1.14