2013-11-27 22:18:14 -04:00
/// -*- 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 < http : //www.gnu.org/licenses/>.
*/
# include <AP_Arming.h>
# include <AP_Notify.h>
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.
2014-01-09 15:34:58 -04:00
// @Values: 0:Disabled,1:THR_MIN PWM when disarmed,2:0 PWM when disarmed
2013-11-27 22:18:14 -04:00
// @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.
2014-01-09 15:34:58 -04:00
// @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
2013-11-27 22:18:14 -04:00
// @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 ,
2013-12-11 02:02:25 -04:00
const bool & home_set , gcs_send_t_p gcs_print_func )
2013-11-27 22:18:14 -04:00
: 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 ) ;
}
2013-12-11 02:02:25 -04:00
bool AP_Arming : : is_armed ( )
{
return require = = NONE | | armed ;
}
2013-11-27 22:18:14 -04:00
2013-12-11 02:02:25 -04:00
uint16_t AP_Arming : : get_enabled_checks ( )
{
2013-11-27 22:18:14 -04:00
return checks_to_perform ;
}
void AP_Arming : : set_enabled_checks ( uint16_t ap ) {
checks_to_perform = ap ;
}
2013-12-11 02:02:25 -04:00
bool AP_Arming : : barometer_checks ( )
{
if ( ( checks_to_perform & ARMING_CHECK_ALL ) | |
( checks_to_perform & ARMING_CHECK_BARO ) ) {
2013-11-27 22:18:14 -04:00
if ( ! barometer . healthy ) {
gcs_send_text_P ( SEVERITY_HIGH , PSTR ( " PreArm: Baro not healthy! " ) ) ;
return false ;
}
}
return true ;
}
2013-12-11 02:02:25 -04:00
bool AP_Arming : : compass_checks ( )
{
if ( ( checks_to_perform ) & ARMING_CHECK_ALL | |
( checks_to_perform ) & ARMING_CHECK_COMPASS ) {
2013-11-27 22:18:14 -04:00
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 ;
}
2013-12-11 00:22:43 -04:00
if ( ! compass - > healthy ( ) ) {
2013-11-27 22:18:14 -04:00
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 ;
}
2013-12-11 02:02:25 -04:00
bool AP_Arming : : gps_checks ( )
{
if ( ( checks_to_perform & ARMING_CHECK_ALL ) | |
( checks_to_perform & ARMING_CHECK_GPS ) ) {
2013-11-27 22:18:14 -04:00
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 | |
2013-12-11 02:02:25 -04:00
AP_Notify : : flags . gps_glitching | |
AP_Notify : : flags . failsafe_gps ) {
2013-11-27 22:18:14 -04:00
gcs_send_text_P ( SEVERITY_HIGH , PSTR ( " PreArm: Bad GPS Pos " ) ) ;
return false ;
}
}
return true ;
}
2013-12-11 02:02:25 -04:00
bool AP_Arming : : battery_checks ( )
{
if ( ( checks_to_perform & ARMING_CHECK_ALL ) | |
( checks_to_perform & ARMING_CHECK_BATTERY ) ) {
2013-11-27 22:18:14 -04:00
if ( AP_Notify : : flags . failsafe_battery ) {
gcs_send_text_P ( SEVERITY_HIGH , PSTR ( " PreArm: Battery failsafe on. " ) ) ;
return false ;
}
}
return true ;
}
2013-12-11 02:02:25 -04:00
bool AP_Arming : : hardware_safety_check ( )
{
2013-11-27 22:18:14 -04:00
// 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 ;
}
2013-12-11 02:02:25 -04:00
bool AP_Arming : : manual_transmitter_checks ( )
{
if ( ( checks_to_perform & ARMING_CHECK_ALL ) | |
( checks_to_perform & ARMING_CHECK_RC ) ) {
2013-11-27 22:18:14 -04:00
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 ;
}
2013-12-11 02:02:25 -04:00
bool AP_Arming : : pre_arm_checks ( )
{
2013-11-27 22:18:14 -04:00
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
2013-12-11 02:02:25 -04:00
bool AP_Arming : : arm ( uint8_t method )
{
2013-11-27 22:18:14 -04:00
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
2013-12-11 02:02:25 -04:00
bool AP_Arming : : disarm ( )
{
2013-11-27 22:18:14 -04:00
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 ;
}
2013-12-11 02:02:25 -04:00
AP_Arming : : ArmingRequired AP_Arming : : arming_required ( )
{
return ( AP_Arming : : ArmingRequired ) require . get ( ) ;
2013-11-27 22:18:14 -04:00
}
2013-12-11 02:02:25 -04:00
bool AP_Arming : : rudder_arming_enabled ( )
{
2013-11-27 22:18:14 -04:00
if ( disable_rudder_arm = = 0 )
return true ;
return false ;
}