/**************************************************************************** * * Copyright (c) 2018 PX4 Development Team. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * 3. Neither the name PX4 nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************/ /** * @file FailureDetector.hpp * Base class for failure detection logic based on vehicle states * for failsafe triggering. * * @author Mathieu Bresciani * */ #pragma once #include #include #include #include #include // subscriptions #include #include #include #include #include #include #include #include #include #include #include #include #include union failure_detector_status_u { struct { uint16_t roll : 1; uint16_t pitch : 1; uint16_t alt : 1; uint16_t ext : 1; uint16_t arm_escs : 1; uint16_t battery : 1; uint16_t imbalanced_prop : 1; uint16_t motor : 1; } flags; uint16_t value {0}; }; using uORB::SubscriptionData; class FailureInjector { public: void update(); void manipulateEscStatus(esc_status_s &status); private: uORB::Subscription _vehicle_command_sub{ORB_ID(vehicle_command)}; uORB::Publication _command_ack_pub{ORB_ID(vehicle_command_ack)}; uint32_t _esc_blocked{}; uint32_t _esc_wrong{}; }; class FailureDetector : public ModuleParams { public: FailureDetector(ModuleParams *parent); ~FailureDetector() = default; bool update(const vehicle_status_s &vehicle_status, const vehicle_control_mode_s &vehicle_control_mode); const failure_detector_status_u &getStatus() const { return _status; } const decltype(failure_detector_status_u::flags) &getStatusFlags() const { return _status.flags; } float getImbalancedPropMetric() const { return _imbalanced_prop_lpf.getState(); } uint16_t getMotorFailures() const { return _motor_failure_esc_timed_out_mask | _motor_failure_esc_under_current_mask; } private: void updateAttitudeStatus(); void updateExternalAtsStatus(); void updateEscsStatus(const vehicle_status_s &vehicle_status, const esc_status_s &esc_status); void updateMotorStatus(const vehicle_status_s &vehicle_status, const esc_status_s &esc_status); void updateImbalancedPropStatus(); failure_detector_status_u _status{}; systemlib::Hysteresis _roll_failure_hysteresis{false}; systemlib::Hysteresis _pitch_failure_hysteresis{false}; systemlib::Hysteresis _ext_ats_failure_hysteresis{false}; systemlib::Hysteresis _esc_failure_hysteresis{false}; static constexpr float _imbalanced_prop_lpf_time_constant{5.f}; AlphaFilter _imbalanced_prop_lpf{}; uint32_t _selected_accel_device_id{0}; hrt_abstime _imu_status_timestamp_prev{0}; // Motor failure check uint8_t _motor_failure_esc_valid_current_mask{}; // ESC 1-8, true if ESC telemetry was valid at some point uint8_t _motor_failure_esc_timed_out_mask{}; // ESC telemetry no longer available -> failure uint8_t _motor_failure_esc_under_current_mask{}; // ESC drawing too little current -> failure bool _motor_failure_escs_have_current{false}; // true if some ESC had non-zero current (some don't support it) hrt_abstime _motor_failure_undercurrent_start_time[actuator_motors_s::NUM_CONTROLS] {}; uORB::Subscription _vehicle_attitude_sub{ORB_ID(vehicle_attitude)}; uORB::Subscription _esc_status_sub{ORB_ID(esc_status)}; // TODO: multi-instance uORB::Subscription _pwm_input_sub{ORB_ID(pwm_input)}; uORB::Subscription _sensor_selection_sub{ORB_ID(sensor_selection)}; uORB::Subscription _vehicle_imu_status_sub{ORB_ID(vehicle_imu_status)}; uORB::Subscription _actuator_motors_sub{ORB_ID(actuator_motors)}; FailureInjector _failure_injector; DEFINE_PARAMETERS( (ParamInt) _param_fd_fail_p, (ParamInt) _param_fd_fail_r, (ParamFloat) _param_fd_fail_r_ttri, (ParamFloat) _param_fd_fail_p_ttri, (ParamBool) _param_fd_ext_ats_en, (ParamInt) _param_fd_ext_ats_trig, (ParamInt) _param_escs_en, (ParamInt) _param_fd_imb_prop_thr, // Actuator failure (ParamBool) _param_fd_actuator_en, (ParamFloat) _param_fd_motor_throttle_thres, (ParamFloat) _param_fd_motor_current2throttle_thres, (ParamInt) _param_fd_motor_time_thres ) };