/// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- /* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include extern const AP_HAL::HAL& hal; const AP_Param::GroupInfo AP_Arming::var_info[] PROGMEM = { // @Param: REQUIRE // @DisplayName: Require Arming Motors // @Description: Arming disabled until some requirements are met. If 0, there are no requirements (arm immediately). If 1, require rudder stick or GCS arming before arming motors and send THR_MIN PWM to throttle channel when disarmed. If 2, require rudder stick or GCS arming and send 0 PWM to throttle channel when disarmed. See the ARMING_CHECK_* parameters to see what checks are done before arming. Note, if setting this parameter to 0 a reboot is required to arm the plane. Also note, even with this parameter at 0, if ARMING_CHECK parameter is not also zero the plane may fail to arm throttle at boot due to a pre-arm check failure. // @Values: 0:Disabled,1:THR_MIN PWM when disarmed,2:0 PWM when disarmed // @User: Advanced AP_GROUPINFO("REQUIRE", 0, AP_Arming, require, 0), // @Param: DIS_RUD // @DisplayName: Disable Rudder Arming // @Description: Do not allow arming via the rudder input stick. // @Values: 0:Disabled (Rudder Arming Allowed),1:Enabled(No Rudder Arming) // @User: Advanced AP_GROUPINFO("DIS_RUD", 1, AP_Arming, disable_rudder_arm, 0), // @Param: CHECK // @DisplayName: Arm Checks to Peform (bitmask) // @Description: Checks prior to arming motor. // @Values: 0:None,1:All,2:Barometer,4:Compass,8:GPS,16:INS,32:Parameters,64:Manual RC Trasmitter,128:Board voltage,256:Battery Level // @User: Advanced AP_GROUPINFO("CHECK", 2, AP_Arming, checks_to_perform, 0), AP_GROUPEND }; //The function point is particularly hacky, hacky, tacky //but I don't want to reimplement messaging to GCS at the moment: AP_Arming::AP_Arming(const AP_AHRS &ahrs_ref, const AP_Baro &baro, const bool &home_set, gcs_send_t_p gcs_print_func) : armed(false) , arming_method(NONE) , ahrs(ahrs_ref) , barometer(baro) , home_is_set(home_set) , gcs_send_text_P(gcs_print_func) { AP_Param::setup_object_defaults(this, var_info); } bool AP_Arming::is_armed() { return require == NONE || armed; } uint16_t AP_Arming::get_enabled_checks() { return checks_to_perform; } void AP_Arming::set_enabled_checks(uint16_t ap) { checks_to_perform = ap; } bool AP_Arming::barometer_checks() { if ((checks_to_perform & ARMING_CHECK_ALL) || (checks_to_perform & ARMING_CHECK_BARO)) { if (! barometer.healthy) { gcs_send_text_P(SEVERITY_HIGH,PSTR("PreArm: Baro not healthy!")); return false; } } return true; } bool AP_Arming::compass_checks() { if ((checks_to_perform) & ARMING_CHECK_ALL || (checks_to_perform) & ARMING_CHECK_COMPASS) { const Compass* compass = ahrs.get_compass(); //if there is no compass and the user has specifically asked to check //the compass, then there is a problem if (compass == NULL && (checks_to_perform & ARMING_CHECK_COMPASS)) { gcs_send_text_P(SEVERITY_HIGH,PSTR("PreArm: No compass detected.")); return false; } else if (compass == NULL) { //if the user's not asking to check and there isn't a compass //then skip compass checks return true; } if (! compass->healthy()) { gcs_send_text_P(SEVERITY_HIGH,PSTR("PreArm: Compass not healthy!")); return false; } // check compass learning is on or offsets have been set Vector3f offsets = compass->get_offsets(); if(!compass->_learn && offsets.length() == 0) { gcs_send_text_P(SEVERITY_HIGH,PSTR("PreArm: Compass not calibrated")); return false; } } return true; } bool AP_Arming::gps_checks() { if ((checks_to_perform & ARMING_CHECK_ALL) || (checks_to_perform & ARMING_CHECK_GPS)) { const GPS *gps = ahrs.get_gps(); //If no GPS and the user has specifically asked to check GPS, then //there is a problem if (gps == NULL && (checks_to_perform & ARMING_CHECK_GPS)) { gcs_send_text_P(SEVERITY_HIGH,PSTR("PreArm: No GPS detected.")); return false; } else if (gps == NULL) { //assume the user doesn't have a GPS on purpose return true; } //GPS OK? if (!home_is_set || gps->status() != GPS::GPS_OK_FIX_3D || AP_Notify::flags.gps_glitching || AP_Notify::flags.failsafe_gps) { gcs_send_text_P(SEVERITY_HIGH,PSTR("PreArm: Bad GPS Pos")); return false; } } return true; } bool AP_Arming::battery_checks() { if ((checks_to_perform & ARMING_CHECK_ALL) || (checks_to_perform & ARMING_CHECK_BATTERY)) { if (AP_Notify::flags.failsafe_battery) { gcs_send_text_P(SEVERITY_HIGH,PSTR("PreArm: Battery failsafe on.")); return false; } } return true; } bool AP_Arming::hardware_safety_check() { // check if safety switch has been pushed if (hal.util->safety_switch_state() == AP_HAL::Util::SAFETY_DISARMED) { gcs_send_text_P(SEVERITY_HIGH,PSTR("PreArm: Hardware Safety Switch")); return false; } return true; } bool AP_Arming::manual_transmitter_checks() { if ((checks_to_perform & ARMING_CHECK_ALL) || (checks_to_perform & ARMING_CHECK_RC)) { if (AP_Notify::flags.failsafe_radio) { gcs_send_text_P(SEVERITY_HIGH,PSTR("PreArm: Radio failsafe on.")); return false; } //TODO verify radio calibration //Requires access to Parameters ... which are implemented a little //differently for Rover, Plane, and Copter. } return true; } bool AP_Arming::pre_arm_checks() { if (! hardware_safety_check()) return false; if (! barometer_checks()) return false; if (! compass_checks()) return false; if (! gps_checks()) return false; if (! battery_checks()) return false; if (! manual_transmitter_checks()) return false; //all checks passed, allow arming! return true; } //returns true if arming occured successfully bool AP_Arming::arm(uint8_t method) { if (armed) { //already armed return false; } //are arming checks disabled? if (checks_to_perform == ARMING_CHECK_NONE) { armed = true; arming_method = NONE; gcs_send_text_P(SEVERITY_HIGH,PSTR("Throttle armed!")); return true; } if (pre_arm_checks()) { armed = true; arming_method = method; gcs_send_text_P(SEVERITY_HIGH,PSTR("Throttle armed!")); //TODO: Log motor arming to the dataflash //Can't do this from this class until there is a unified logging library } else { armed = false; arming_method = NONE; } return armed; } //returns true if disarming occurred successfully bool AP_Arming::disarm() { if (! armed) { // already disarmed return false; } armed = false; gcs_send_text_P(SEVERITY_HIGH,PSTR("Throttle disarmed!")); //TODO: Log motor disarming to the dataflash //Can't do this from this class until there is a unified logging library. return true; } AP_Arming::ArmingRequired AP_Arming::arming_required() { return (AP_Arming::ArmingRequired)require.get(); } bool AP_Arming::rudder_arming_enabled() { if (disable_rudder_arm == 0) return true; return false; }