123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495 |
- #include "Sub.h"
- static bool failsafe_enabled = false;
- static uint16_t failsafe_last_ticks;
- static uint32_t failsafe_last_timestamp;
- static bool in_failsafe;
- void Sub::mainloop_failsafe_enable()
- {
- failsafe_enabled = true;
- failsafe_last_timestamp = AP_HAL::micros();
- }
- void Sub::mainloop_failsafe_disable()
- {
- failsafe_enabled = false;
- }
- void Sub::mainloop_failsafe_check()
- {
- uint32_t tnow = AP_HAL::micros();
- const uint16_t ticks = scheduler.ticks();
- if (ticks != failsafe_last_ticks) {
-
- failsafe_last_ticks = ticks;
- failsafe_last_timestamp = tnow;
- if (in_failsafe) {
- in_failsafe = false;
- AP::logger().Write_Error(LogErrorSubsystem::CPU,LogErrorCode::FAILSAFE_RESOLVED);
- }
- return;
- }
- if (!in_failsafe && failsafe_enabled && tnow - failsafe_last_timestamp > 2000000) {
-
-
-
- in_failsafe = true;
-
- if (motors.armed()) {
- motors.output_min();
- }
- AP::logger().Write_Error(LogErrorSubsystem::CPU,LogErrorCode::FAILSAFE_OCCURRED);
- }
- if (failsafe_enabled && in_failsafe && tnow - failsafe_last_timestamp > 1000000) {
-
- failsafe_last_timestamp = tnow;
- if (motors.armed()) {
- arming.disarm();
- motors.output();
- }
- }
- }
- void Sub::failsafe_sensors_check()
- {
- if (!ap.depth_sensor_present) {
- return;
- }
-
- if (sensor_health.depth) {
- if (failsafe.sensor_health) {
- AP::logger().Write_Error(LogErrorSubsystem::FAILSAFE_SENSORS, LogErrorCode::ERROR_RESOLVED);
- failsafe.sensor_health = false;
- }
- return;
- }
-
- if (failsafe.sensor_health) {
- return;
- }
- failsafe.sensor_health = true;
- gcs().send_text(MAV_SEVERITY_CRITICAL, "Depth sensor error!");
- AP::logger().Write_Error(LogErrorSubsystem::FAILSAFE_SENSORS, LogErrorCode::BAD_DEPTH);
- if (control_mode == ALT_HOLD || control_mode == SURFACE || mode_requires_GPS(control_mode)) {
-
- if (!set_mode(MANUAL, MODE_REASON_BAD_DEPTH)) {
-
- arming.disarm();
- }
- }
- }
- void Sub::failsafe_ekf_check()
- {
- static uint32_t last_ekf_good_ms = 0;
- if (g.fs_ekf_action == FS_EKF_ACTION_DISABLED) {
- last_ekf_good_ms = AP_HAL::millis();
- failsafe.ekf = false;
- AP_Notify::flags.ekf_bad = false;
- return;
- }
- float posVar, hgtVar, tasVar;
- Vector3f magVar;
- Vector2f offset;
- float compass_variance;
- float vel_variance;
- ahrs.get_variances(vel_variance, posVar, hgtVar, magVar, tasVar, offset);
- compass_variance = magVar.length();
- if (compass_variance < g.fs_ekf_thresh && vel_variance < g.fs_ekf_thresh) {
- last_ekf_good_ms = AP_HAL::millis();
- failsafe.ekf = false;
- AP_Notify::flags.ekf_bad = false;
- return;;
- }
-
- if (AP_HAL::millis() < last_ekf_good_ms + 2000) {
- failsafe.ekf = false;
- AP_Notify::flags.ekf_bad = false;
- return;
- }
-
- if (failsafe.ekf) {
- return;
- }
- failsafe.ekf = true;
- AP_Notify::flags.ekf_bad = true;
- AP::logger().Write_Error(LogErrorSubsystem::EKFCHECK, LogErrorCode::EKFCHECK_BAD_VARIANCE);
- if (AP_HAL::millis() > failsafe.last_ekf_warn_ms + 20000) {
- failsafe.last_ekf_warn_ms = AP_HAL::millis();
- gcs().send_text(MAV_SEVERITY_WARNING, "EKF bad");
- }
- if (g.fs_ekf_action == FS_EKF_ACTION_DISARM) {
- arming.disarm();
- }
- }
- void Sub::handle_battery_failsafe(const char* type_str, const int8_t action)
- {
- AP::logger().Write_Error(LogErrorSubsystem::FAILSAFE_BATT, LogErrorCode::FAILSAFE_OCCURRED);
- switch((Failsafe_Action)action) {
- case Failsafe_Action_Surface:
- set_mode(SURFACE, MODE_REASON_BATTERY_FAILSAFE);
- break;
- case Failsafe_Action_Disarm:
- arming.disarm();
- break;
- case Failsafe_Action_Warn:
- case Failsafe_Action_None:
- break;
- }
- }
- void Sub::failsafe_pilot_input_check()
- {
- #if CONFIG_HAL_BOARD != HAL_BOARD_SITL
- if (g.failsafe_pilot_input == FS_PILOT_INPUT_DISABLED) {
- failsafe.pilot_input = false;
- return;
- }
- if (AP_HAL::millis() < failsafe.last_pilot_input_ms + g.failsafe_pilot_input_timeout * 1000.0f) {
- failsafe.pilot_input = false;
- return;
- }
- if (failsafe.pilot_input) {
- return;
- }
- failsafe.pilot_input = true;
- AP::logger().Write_Error(LogErrorSubsystem::PILOT_INPUT, LogErrorCode::FAILSAFE_OCCURRED);
- gcs().send_text(MAV_SEVERITY_CRITICAL, "Lost manual control");
- set_neutral_controls();
- if(g.failsafe_pilot_input == FS_PILOT_INPUT_DISARM) {
- arming.disarm();
- }
- #endif
- }
- void Sub::failsafe_internal_pressure_check()
- {
- if (g.failsafe_pressure == FS_PRESS_DISABLED) {
- return;
- }
- uint32_t tnow = AP_HAL::millis();
- static uint32_t last_pressure_warn_ms;
- static uint32_t last_pressure_good_ms;
- if (barometer.get_pressure(0) < g.failsafe_pressure_max) {
- last_pressure_good_ms = tnow;
- last_pressure_warn_ms = tnow;
- failsafe.internal_pressure = false;
- return;
- }
-
- if (tnow > last_pressure_good_ms + 2000) {
- failsafe.internal_pressure = true;
- }
-
- if (failsafe.internal_pressure && tnow > last_pressure_warn_ms + 30000) {
- last_pressure_warn_ms = tnow;
- gcs().send_text(MAV_SEVERITY_WARNING, "Internal pressure critical!");
- }
- }
- void Sub::failsafe_internal_temperature_check()
- {
- if (g.failsafe_temperature == FS_TEMP_DISABLED) {
- return;
- }
- uint32_t tnow = AP_HAL::millis();
- static uint32_t last_temperature_warn_ms;
- static uint32_t last_temperature_good_ms;
- if (barometer.get_temperature(0) < g.failsafe_temperature_max) {
- last_temperature_good_ms = tnow;
- last_temperature_warn_ms = tnow;
- failsafe.internal_temperature = false;
- return;
- }
-
- if (tnow > last_temperature_good_ms + 2000) {
- failsafe.internal_temperature = true;
- }
-
- if (failsafe.internal_temperature && tnow > last_temperature_warn_ms + 30000) {
- last_temperature_warn_ms = tnow;
- gcs().send_text(MAV_SEVERITY_WARNING, "Internal temperature critical!");
- }
- }
- void Sub::failsafe_leak_check()
- {
- bool status = leak_detector.get_status();
-
- if (status == false || g.failsafe_leak == FS_LEAK_DISABLED) {
- if (failsafe.leak) {
- AP::logger().Write_Error(LogErrorSubsystem::FAILSAFE_LEAK, LogErrorCode::FAILSAFE_RESOLVED);
- }
- AP_Notify::flags.leak_detected = false;
- failsafe.leak = false;
- return;
- }
- AP_Notify::flags.leak_detected = status;
- uint32_t tnow = AP_HAL::millis();
-
-
- if (tnow > failsafe.last_leak_warn_ms + 20000) {
- failsafe.last_leak_warn_ms = tnow;
- gcs().send_text(MAV_SEVERITY_CRITICAL, "Leak Detected");
- }
-
- if (failsafe.leak) {
- return;
- }
- failsafe.leak = true;
- AP::logger().Write_Error(LogErrorSubsystem::FAILSAFE_LEAK, LogErrorCode::FAILSAFE_OCCURRED);
-
- if (failsafe.leak && g.failsafe_leak == FS_LEAK_SURFACE && motors.armed()) {
- set_mode(SURFACE, MODE_REASON_LEAK_FAILSAFE);
- }
- }
- void Sub::failsafe_gcs_check()
- {
-
-
- if (failsafe.last_heartbeat_ms == 0 || (!g.failsafe_gcs && g.failsafe_gcs == FS_GCS_DISABLED)) {
- return;
- }
- uint32_t tnow = AP_HAL::millis();
-
- if (tnow - failsafe.last_heartbeat_ms < FS_GCS_TIMEOUT_MS) {
-
- if (failsafe.gcs) {
- AP::logger().Write_Error(LogErrorSubsystem::FAILSAFE_GCS, LogErrorCode::FAILSAFE_RESOLVED);
- }
- failsafe.gcs = false;
- return;
- }
-
-
-
-
- if (tnow - failsafe.last_gcs_warn_ms > 30000) {
- failsafe.last_gcs_warn_ms = tnow;
- gcs().send_text(MAV_SEVERITY_WARNING, "MYGCS: %u, heartbeat lost", g.sysid_my_gcs.get());
- }
-
- if (failsafe.gcs || !motors.armed()) {
- return;
- }
- failsafe.gcs = true;
- AP::logger().Write_Error(LogErrorSubsystem::FAILSAFE_GCS, LogErrorCode::FAILSAFE_OCCURRED);
-
- if (g.failsafe_gcs == FS_GCS_DISARM) {
- arming.disarm();
- } else if (g.failsafe_gcs == FS_GCS_HOLD && motors.armed()) {
- if (!set_mode(ALT_HOLD, MODE_REASON_GCS_FAILSAFE)) {
- arming.disarm();
- }
- } else if (g.failsafe_gcs == FS_GCS_SURFACE && motors.armed()) {
- if (!set_mode(SURFACE, MODE_REASON_GCS_FAILSAFE)) {
- arming.disarm();
- }
- }
- }
- #define CRASH_CHECK_TRIGGER_MS 2000
- #define CRASH_CHECK_ANGLE_DEVIATION_DEG 30.0f
- void Sub::failsafe_crash_check()
- {
- static uint32_t last_crash_check_pass_ms;
- uint32_t tnow = AP_HAL::millis();
-
- if (!motors.armed() || g.fs_crash_check == FS_CRASH_DISABLED) {
- last_crash_check_pass_ms = tnow;
- failsafe.crash = false;
- return;
- }
-
- if (control_mode == ACRO || control_mode == MANUAL) {
- last_crash_check_pass_ms = tnow;
- failsafe.crash = false;
- return;
- }
-
- const float angle_error = attitude_control.get_att_error_angle_deg();
- if (angle_error <= CRASH_CHECK_ANGLE_DEVIATION_DEG) {
- last_crash_check_pass_ms = tnow;
- failsafe.crash = false;
- return;
- }
- if (tnow < last_crash_check_pass_ms + CRASH_CHECK_TRIGGER_MS) {
- return;
- }
-
-
- if (tnow > failsafe.last_crash_warn_ms + 20000) {
- failsafe.last_crash_warn_ms = tnow;
- gcs().send_text(MAV_SEVERITY_WARNING,"Crash detected");
- }
-
- if (failsafe.crash) {
- return;
- }
- failsafe.crash = true;
- AP::logger().Write_Error(LogErrorSubsystem::CRASH_CHECK, LogErrorCode::CRASH_CHECK_CRASH);
-
- if (g.fs_crash_check == FS_CRASH_DISARM) {
- arming.disarm();
- }
- }
- void Sub::failsafe_terrain_check()
- {
-
- bool valid_mode = (control_mode == AUTO || control_mode == GUIDED);
- bool timeout = (failsafe.terrain_last_failure_ms - failsafe.terrain_first_failure_ms) > FS_TERRAIN_TIMEOUT_MS;
- bool trigger_event = valid_mode && timeout;
-
- if (trigger_event != failsafe.terrain) {
- if (trigger_event) {
- gcs().send_text(MAV_SEVERITY_CRITICAL,"Failsafe terrain triggered");
- failsafe_terrain_on_event();
- } else {
- AP::logger().Write_Error(LogErrorSubsystem::FAILSAFE_TERRAIN, LogErrorCode::ERROR_RESOLVED);
- failsafe.terrain = false;
- }
- }
- }
- void Sub::failsafe_terrain_set_status(bool data_ok)
- {
- uint32_t now = AP_HAL::millis();
-
- if (!data_ok) {
- failsafe.terrain_last_failure_ms = now;
- if (failsafe.terrain_first_failure_ms == 0) {
- failsafe.terrain_first_failure_ms = now;
- }
- } else {
-
- if (now - failsafe.terrain_last_failure_ms > 100) {
- failsafe.terrain_last_failure_ms = 0;
- failsafe.terrain_first_failure_ms = 0;
- }
- }
- }
- void Sub::failsafe_terrain_on_event()
- {
- failsafe.terrain = true;
- AP::logger().Write_Error(LogErrorSubsystem::FAILSAFE_TERRAIN, LogErrorCode::FAILSAFE_OCCURRED);
-
- if (!rangefinder_state.enabled || !auto_terrain_recover_start()) {
- failsafe_terrain_act();
- }
- }
- void Sub::failsafe_terrain_act()
- {
- switch (g.failsafe_terrain) {
- case FS_TERRAIN_HOLD:
- if (!set_mode(POSHOLD, MODE_REASON_TERRAIN_FAILSAFE)) {
- set_mode(ALT_HOLD, MODE_REASON_TERRAIN_FAILSAFE);
- }
- AP_Notify::events.failsafe_mode_change = 1;
- break;
- case FS_TERRAIN_SURFACE:
- set_mode(SURFACE, MODE_REASON_TERRAIN_FAILSAFE);
- AP_Notify::events.failsafe_mode_change = 1;
- break;
- case FS_TERRAIN_DISARM:
- default:
- arming.disarm();
- }
- }
|