2013-11-27 22:18:14 -04:00
/*
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/>.
*/
2015-08-11 03:28:42 -03:00
# include "AP_Arming.h"
2018-08-11 11:09:57 -03:00
# include <AP_HAL/AP_HAL.h>
2018-12-20 04:22:10 -04:00
# include <AP_BoardConfig/AP_BoardConfig.h>
# include <AP_BattMonitor/AP_BattMonitor.h>
2015-08-11 03:28:42 -03:00
# include <AP_Notify/AP_Notify.h>
2015-09-08 00:54:25 -03:00
# include <GCS_MAVLink/GCS.h>
2018-12-20 04:22:10 -04:00
# include <GCS_MAVLink/GCS_MAVLink.h>
2018-12-25 01:19:02 -04:00
# include <AP_Mission/AP_Mission.h>
2019-05-29 23:28:33 -03:00
# include <AP_Proximity/AP_Proximity.h>
2018-12-25 01:19:02 -04:00
# include <AP_Rally/AP_Rally.h>
2018-12-20 04:22:10 -04:00
# include <SRV_Channel/SRV_Channel.h>
2019-03-05 19:09:55 -04:00
# include <AC_Fence/AC_Fence.h>
2019-04-24 21:57:24 -03:00
# include <AP_InternalError/AP_InternalError.h>
2019-06-13 23:59:26 -03:00
# include <AP_GPS/AP_GPS.h>
2019-08-27 17:06:02 -03:00
# include <AP_Airspeed/AP_Airspeed.h>
# include <AP_AHRS/AP_AHRS.h>
2019-06-26 23:30:12 -03:00
# include <AP_Baro/AP_Baro.h>
2019-04-10 04:32:30 -03:00
# include <AP_RangeFinder/AP_RangeFinder.h>
2020-10-22 14:15:41 -03:00
# include <AP_Generator/AP_Generator.h>
2019-11-06 22:04:07 -04:00
# include <AP_Terrain/AP_Terrain.h>
2020-10-28 10:45:05 -03:00
# include <AP_ADSB/AP_ADSB.h>
2019-11-26 02:31:36 -04:00
# include <AP_Scripting/AP_Scripting.h>
2019-12-06 13:52:12 -04:00
# include <AP_Camera/AP_RunCam.h>
2020-01-01 16:34:39 -04:00
# include <AP_GyroFFT/AP_GyroFFT.h>
2020-03-30 19:24:07 -03:00
# include <AP_RCMapper/AP_RCMapper.h>
2020-03-30 00:30:20 -03:00
# include <AP_VisualOdom/AP_VisualOdom.h>
2020-04-26 11:37:49 -03:00
# include <AP_OSD/AP_OSD.h>
2013-11-27 22:18:14 -04:00
2020-05-31 09:02:10 -03:00
# if HAL_MAX_CAN_PROTOCOL_DRIVERS
# include <AP_CANManager/AP_CANManager.h>
2018-08-11 11:09:57 -03:00
# include <AP_Common/AP_Common.h>
# include <AP_Vehicle/AP_Vehicle.h>
2019-12-09 00:31:29 -04:00
# include <AP_PiccoloCAN/AP_PiccoloCAN.h>
2018-08-11 11:09:57 -03:00
// To be replaced with macro saying if KDECAN library is included
# if APM_BUILD_TYPE(APM_BUILD_ArduCopter) || APM_BUILD_TYPE(APM_BUILD_ArduPlane) || APM_BUILD_TYPE(APM_BUILD_ArduSub)
# include <AP_KDECAN/AP_KDECAN.h>
# endif
2019-10-04 04:12:10 -03:00
# include <AP_UAVCAN/AP_UAVCAN.h>
2018-08-11 11:09:57 -03:00
# endif
2019-04-04 07:44:42 -03:00
# include <AP_Logger/AP_Logger.h>
2016-08-17 05:15:38 -03:00
# define AP_ARMING_COMPASS_MAGFIELD_EXPECTED 530
2015-10-16 00:09:39 -03:00
# define AP_ARMING_COMPASS_MAGFIELD_MIN 185 // 0.35 * 530 milligauss
# define AP_ARMING_COMPASS_MAGFIELD_MAX 875 // 1.65 * 530 milligauss
2015-10-16 00:13:53 -03:00
# define AP_ARMING_BOARD_VOLTAGE_MAX 5.8f
2015-12-21 17:51:12 -04:00
# define AP_ARMING_ACCEL_ERROR_THRESHOLD 0.75f
2017-09-18 00:14:52 -03:00
# define AP_ARMING_AHRS_GPS_ERROR_MAX 10 // accept up to 10m difference between AHRS and GPS
2015-10-16 00:13:53 -03:00
2018-09-08 00:30:21 -03:00
# if APM_BUILD_TYPE(APM_BUILD_ArduPlane)
2019-03-06 23:12:39 -04:00
# define ARMING_RUDDER_DEFAULT (uint8_t)RudderArming::ARMONLY
2018-09-08 00:30:21 -03:00
# else
2019-03-06 23:12:39 -04:00
# define ARMING_RUDDER_DEFAULT (uint8_t)RudderArming::ARMDISARM
2018-09-08 00:30:21 -03:00
# endif
2013-11-27 22:18:14 -04:00
extern const AP_HAL : : HAL & hal ;
2015-10-25 14:03:46 -03:00
const AP_Param : : GroupInfo AP_Arming : : var_info [ ] = {
2016-12-28 01:41:21 -04:00
2020-06-29 11:53:26 -03:00
// @Param{Plane, Rover}: REQUIRE
2013-11-27 22:18:14 -04:00
// @DisplayName: Require Arming Motors
2018-04-11 18:27:59 -03:00
// @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 sends the minimum throttle PWM value to the 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
2017-02-07 19:47:01 -04:00
AP_GROUPINFO_FLAGS_FRAME ( " REQUIRE " , 0 , AP_Arming , require , 1 ,
2020-12-15 23:51:17 -04:00
AP_PARAM_FLAG_NO_SHIFT ,
2017-02-07 19:47:01 -04:00
AP_PARAM_FRAME_PLANE | AP_PARAM_FRAME_ROVER ) ,
2013-11-27 22:18:14 -04:00
2019-04-10 04:32:30 -03:00
// 2 was the CHECK paramter stored in a AP_Int16
2013-11-27 22:18:14 -04:00
2015-12-21 17:51:12 -04:00
// @Param: ACCTHRESH
// @DisplayName: Accelerometer error threshold
// @Description: Accelerometer error threshold used to determine inconsistent accelerometers. Compares this error range to other accelerometers to detect a hardware or calibration error. Lower value means tighter check and harder to pass arming check. Not all accelerometers are created equal.
// @Units: m/s/s
// @Range: 0.25 3.0
// @User: Advanced
AP_GROUPINFO ( " ACCTHRESH " , 3 , AP_Arming , accel_error_threshold , AP_ARMING_ACCEL_ERROR_THRESHOLD ) ,
2018-09-12 19:28:13 -03:00
// index 4 was VOLT_MIN, moved to AP_BattMonitor
// index 5 was VOLT2_MIN, moved to AP_BattMonitor
2016-02-09 19:31:12 -04:00
2018-09-08 00:30:21 -03:00
// @Param: RUDDER
// @DisplayName: Arming with Rudder enable/disable
// @Description: Allow arm/disarm by rudder input. When enabled arming can be done with right rudder, disarming with left rudder. Rudder arming only works in manual throttle modes with throttle at zero +- deadzone (RCx_DZ)
// @Values: 0:Disabled,1:ArmingOnly,2:ArmOrDisarm
// @User: Advanced
AP_GROUPINFO_FRAME ( " RUDDER " , 6 , AP_Arming , _rudder_arming , ARMING_RUDDER_DEFAULT , AP_PARAM_FRAME_PLANE |
AP_PARAM_FRAME_ROVER |
AP_PARAM_FRAME_COPTER |
AP_PARAM_FRAME_TRICOPTER |
AP_PARAM_FRAME_HELI ) ,
2018-12-25 01:19:02 -04:00
// @Param: MIS_ITEMS
// @DisplayName: Required mission items
// @Description: Bitmask of mission items that are required to be planned in order to arm the aircraft
// @Bitmask: 0:Land,1:VTOL Land,2:DO_LAND_START,3:Takeoff,4:VTOL Takeoff,5:Rallypoint
// @User: Advanced
AP_GROUPINFO ( " MIS_ITEMS " , 7 , AP_Arming , _required_mission_items , 0 ) ,
2019-04-10 04:32:30 -03:00
// @Param: CHECK
2019-11-26 23:19:31 -04:00
// @DisplayName: Arm Checks to Perform (bitmask)
2021-05-05 04:01:20 -03:00
// @Description: Checks prior to arming motor. This is a bitmask of checks that will be performed before allowing arming. For most users it is recommended to leave this at the default of 1 (all checks enabled). You can select whatever checks you prefer by adding together the values of each check type to set this parameter. For example, to only allow arming when you have GPS lock and no RC failsafe you would set ARMING_CHECK to 72.
2020-03-27 19:06:43 -03:00
// @Bitmask: 0:All,1:Barometer,2:Compass,3:GPS lock,4:INS,5:Parameters,6:RC Channels,7:Board voltage,8:Battery Level,10:Logging Available,11:Hardware safety switch,12:GPS Configuration,13:System,14:Mission,15:Rangefinder,16:Camera,17:AuxAuth,18:VisualOdometry,19:FFT
// @Bitmask{Plane}: 0:All,1:Barometer,2:Compass,3:GPS lock,4:INS,5:Parameters,6:RC Channels,7:Board voltage,8:Battery Level,9:Airspeed,10:Logging Available,11:Hardware safety switch,12:GPS Configuration,13:System,14:Mission,15:Rangefinder,16:Camera,17:AuxAuth,19:FFT
2019-04-10 04:32:30 -03:00
// @User: Standard
AP_GROUPINFO ( " CHECK " , 8 , AP_Arming , checks_to_perform , ARMING_CHECK_ALL ) ,
2013-11-27 22:18:14 -04:00
AP_GROUPEND
} ;
2018-10-30 21:05:45 -03:00
# if HAL_WITH_IO_MCU
# include <AP_IOMCU/AP_IOMCU.h>
extern AP_IOMCU iomcu ;
# endif
2018-06-23 20:01:42 -03:00
AP_Arming : : AP_Arming ( )
2013-11-27 22:18:14 -04:00
{
2019-05-06 00:33:15 -03:00
if ( _singleton ) {
AP_HAL : : panic ( " Too many AP_Arming instances " ) ;
}
_singleton = this ;
2013-11-27 22:18:14 -04:00
AP_Param : : setup_object_defaults ( this , var_info ) ;
}
2016-08-17 05:15:38 -03:00
uint16_t AP_Arming : : compass_magfield_expected ( ) const
{
return AP_ARMING_COMPASS_MAGFIELD_EXPECTED ;
}
2015-10-12 02:29:27 -03:00
bool AP_Arming : : is_armed ( )
2016-12-28 01:41:21 -04:00
{
2019-03-06 23:12:39 -04:00
return ( Required ) require . get ( ) = = Required : : NO | | armed ;
2013-12-11 02:02:25 -04:00
}
2013-11-27 22:18:14 -04:00
2020-02-11 21:24:36 -04:00
uint32_t AP_Arming : : get_enabled_checks ( ) const
2013-12-11 02:02:25 -04:00
{
2013-11-27 22:18:14 -04:00
return checks_to_perform ;
}
2017-08-01 00:09:27 -03:00
bool AP_Arming : : check_enabled ( const enum AP_Arming : : ArmingChecks check ) const
{
if ( checks_to_perform & ARMING_CHECK_ALL ) {
return true ;
}
return ( checks_to_perform & check ) ;
}
MAV_SEVERITY AP_Arming : : check_severity ( const enum AP_Arming : : ArmingChecks check ) const
{
2019-10-04 18:49:20 -03:00
if ( check_enabled ( check ) ) {
2017-08-01 00:09:27 -03:00
return MAV_SEVERITY_CRITICAL ;
}
return MAV_SEVERITY_DEBUG ; // technically should be NOTICE, but will annoy users at that level
}
void AP_Arming : : check_failed ( const enum AP_Arming : : ArmingChecks check , bool report , const char * fmt , . . . ) const
{
if ( ! report ) {
return ;
}
char taggedfmt [ MAVLINK_MSG_STATUSTEXT_FIELD_TEXT_LEN + 1 ] ;
2018-09-05 23:21:35 -03:00
hal . util - > snprintf ( taggedfmt , sizeof ( taggedfmt ) , " PreArm: %s " , fmt ) ;
2017-08-01 00:09:27 -03:00
MAV_SEVERITY severity = check_severity ( check ) ;
va_list arg_list ;
va_start ( arg_list , fmt ) ;
gcs ( ) . send_textv ( severity , taggedfmt , arg_list ) ;
va_end ( arg_list ) ;
}
2019-10-04 18:49:20 -03:00
void AP_Arming : : check_failed ( bool report , const char * fmt , . . . ) const
{
if ( ! report ) {
return ;
}
char taggedfmt [ MAVLINK_MSG_STATUSTEXT_FIELD_TEXT_LEN + 1 ] ;
hal . util - > snprintf ( taggedfmt , sizeof ( taggedfmt ) , " PreArm: %s " , fmt ) ;
va_list arg_list ;
va_start ( arg_list , fmt ) ;
gcs ( ) . send_textv ( MAV_SEVERITY_CRITICAL , taggedfmt , arg_list ) ;
va_end ( arg_list ) ;
}
2015-10-12 02:29:27 -03:00
bool AP_Arming : : barometer_checks ( bool report )
2013-12-11 02:02:25 -04:00
{
if ( ( checks_to_perform & ARMING_CHECK_ALL ) | |
( checks_to_perform & ARMING_CHECK_BARO ) ) {
2018-03-05 16:35:06 -04:00
if ( ! AP : : baro ( ) . all_healthy ( ) ) {
2017-08-01 00:09:27 -03:00
check_failed ( ARMING_CHECK_BARO , report , " Barometer not healthy " ) ;
2013-11-27 22:18:14 -04:00
return false ;
}
}
return true ;
}
2015-10-12 02:29:27 -03:00
bool AP_Arming : : airspeed_checks ( bool report )
2015-01-19 20:27:13 -04:00
{
if ( ( checks_to_perform & ARMING_CHECK_ALL ) | |
( checks_to_perform & ARMING_CHECK_AIRSPEED ) ) {
2018-06-25 00:42:39 -03:00
const AP_Airspeed * airspeed = AP_Airspeed : : get_singleton ( ) ;
2016-10-30 02:24:21 -03:00
if ( airspeed = = nullptr ) {
2015-01-19 20:27:13 -04:00
// not an airspeed capable vehicle
return true ;
}
2017-11-03 05:26:02 -03:00
for ( uint8_t i = 0 ; i < AIRSPEED_MAX_SENSORS ; i + + ) {
if ( airspeed - > enabled ( i ) & & airspeed - > use ( i ) & & ! airspeed - > healthy ( i ) ) {
2018-11-24 22:00:10 -04:00
check_failed ( ARMING_CHECK_AIRSPEED , report , " Airspeed %d not healthy " , i + 1 ) ;
2017-11-03 05:26:02 -03:00
return false ;
2015-01-19 20:27:13 -04:00
}
}
}
return true ;
}
2015-10-12 02:29:27 -03:00
bool AP_Arming : : logging_checks ( bool report )
2015-02-06 03:38:53 -04:00
{
if ( ( checks_to_perform & ARMING_CHECK_ALL ) | |
( checks_to_perform & ARMING_CHECK_LOGGING ) ) {
2019-01-17 04:11:08 -04:00
if ( ! AP : : logger ( ) . logging_present ( ) ) {
// Logging is disabled, so nothing to check.
return true ;
}
2019-01-18 00:24:08 -04:00
if ( AP : : logger ( ) . logging_failed ( ) ) {
2017-08-01 00:09:27 -03:00
check_failed ( ARMING_CHECK_LOGGING , report , " Logging failed " ) ;
2016-11-05 20:23:14 -03:00
return false ;
2016-11-05 19:05:36 -03:00
}
2019-01-18 00:24:08 -04:00
if ( ! AP : : logger ( ) . CardInserted ( ) ) {
2017-08-01 00:09:27 -03:00
check_failed ( ARMING_CHECK_LOGGING , report , " No SD card " ) ;
2015-02-06 03:38:53 -04:00
return false ;
}
}
return true ;
}
2017-07-27 01:16:38 -03:00
bool AP_Arming : : ins_accels_consistent ( const AP_InertialSensor & ins )
{
2018-06-15 20:06:53 -03:00
const uint8_t accel_count = ins . get_accel_count ( ) ;
if ( accel_count < = 1 ) {
2017-07-27 01:16:38 -03:00
return true ;
}
const Vector3f & prime_accel_vec = ins . get_accel ( ) ;
2018-06-15 19:46:31 -03:00
const uint32_t now = AP_HAL : : millis ( ) ;
2018-06-15 20:06:53 -03:00
for ( uint8_t i = 0 ; i < accel_count ; i + + ) {
2017-07-27 01:16:38 -03:00
if ( ! ins . use_accel ( i ) ) {
continue ;
}
// get next accel vector
const Vector3f & accel_vec = ins . get_accel ( i ) ;
Vector3f vec_diff = accel_vec - prime_accel_vec ;
// allow for user-defined difference, typically 0.75 m/s/s. Has to pass in last 10 seconds
float threshold = accel_error_threshold ;
if ( i > = 2 ) {
/*
we allow for a higher threshold for IMU3 as it
runs at a different temperature to IMU1 / IMU2 ,
and is not used for accel data in the EKF
*/
threshold * = 3 ;
}
// EKF is less sensitive to Z-axis error
vec_diff . z * = 0.5f ;
if ( vec_diff . length ( ) < = threshold ) {
2018-06-15 19:46:31 -03:00
last_accel_pass_ms [ i ] = now ;
2017-07-27 01:16:38 -03:00
}
2018-06-15 19:46:31 -03:00
if ( now - last_accel_pass_ms [ i ] > 10000 ) {
2017-07-27 01:16:38 -03:00
return false ;
}
}
return true ;
}
2017-07-27 01:25:06 -03:00
bool AP_Arming : : ins_gyros_consistent ( const AP_InertialSensor & ins )
{
2018-06-15 20:06:53 -03:00
const uint8_t gyro_count = ins . get_gyro_count ( ) ;
if ( gyro_count < = 1 ) {
2017-07-27 01:25:06 -03:00
return true ;
}
const Vector3f & prime_gyro_vec = ins . get_gyro ( ) ;
2018-06-15 19:46:31 -03:00
const uint32_t now = AP_HAL : : millis ( ) ;
2018-06-15 20:06:53 -03:00
for ( uint8_t i = 0 ; i < gyro_count ; i + + ) {
2017-07-27 01:25:06 -03:00
if ( ! ins . use_gyro ( i ) ) {
continue ;
}
// get next gyro vector
const Vector3f & gyro_vec = ins . get_gyro ( i ) ;
2018-12-20 04:23:39 -04:00
const Vector3f vec_diff = gyro_vec - prime_gyro_vec ;
2017-07-27 01:25:06 -03:00
// allow for up to 5 degrees/s difference. Pass if it has
// been OK in last 10 seconds
if ( vec_diff . length ( ) < = radians ( 5 ) ) {
2018-06-15 19:46:31 -03:00
last_gyro_pass_ms [ i ] = now ;
2017-07-27 01:25:06 -03:00
}
2018-06-15 19:46:31 -03:00
if ( now - last_gyro_pass_ms [ i ] > 10000 ) {
2017-07-27 01:25:06 -03:00
return false ;
}
}
return true ;
}
2015-10-12 02:29:27 -03:00
bool AP_Arming : : ins_checks ( bool report )
2015-01-19 20:27:13 -04:00
{
if ( ( checks_to_perform & ARMING_CHECK_ALL ) | |
( checks_to_perform & ARMING_CHECK_INS ) ) {
2018-03-10 05:35:13 -04:00
const AP_InertialSensor & ins = AP : : ins ( ) ;
2015-10-12 02:29:27 -03:00
if ( ! ins . get_gyro_health_all ( ) ) {
2017-08-01 00:09:27 -03:00
check_failed ( ARMING_CHECK_INS , report , " Gyros not healthy " ) ;
2015-01-20 04:47:15 -04:00
return false ;
}
2015-09-17 09:33:41 -03:00
if ( ! ins . gyro_calibrated_ok_all ( ) ) {
2017-08-01 00:09:27 -03:00
check_failed ( ARMING_CHECK_INS , report , " Gyros not calibrated " ) ;
2015-01-20 04:47:15 -04:00
return false ;
}
2015-10-12 02:29:27 -03:00
if ( ! ins . get_accel_health_all ( ) ) {
2017-08-01 00:09:27 -03:00
check_failed ( ARMING_CHECK_INS , report , " Accels not healthy " ) ;
2015-01-19 20:27:13 -04:00
return false ;
}
2015-05-12 03:19:29 -03:00
if ( ! ins . accel_calibrated_ok_all ( ) ) {
2017-08-01 00:09:27 -03:00
check_failed ( ARMING_CHECK_INS , report , " 3D Accel calibration needed " ) ;
2015-01-31 22:31:59 -04:00
return false ;
}
2015-12-29 00:33:40 -04:00
//check if accelerometers have calibrated and require reboot
if ( ins . accel_cal_requires_reboot ( ) ) {
2017-08-01 00:09:27 -03:00
check_failed ( ARMING_CHECK_INS , report , " Accels calibrated requires reboot " ) ;
2015-12-29 00:33:40 -04:00
return false ;
}
2015-10-14 12:44:35 -03:00
2015-01-19 20:27:13 -04:00
// check all accelerometers point in roughly same direction
2017-07-27 01:16:38 -03:00
if ( ! ins_accels_consistent ( ins ) ) {
2017-08-01 00:09:27 -03:00
check_failed ( ARMING_CHECK_INS , report , " Accels inconsistent " ) ;
2017-07-27 01:16:38 -03:00
return false ;
2015-01-19 20:27:13 -04:00
}
// check all gyros are giving consistent readings
2017-07-27 01:25:06 -03:00
if ( ! ins_gyros_consistent ( ins ) ) {
2017-08-01 00:09:27 -03:00
check_failed ( ARMING_CHECK_INS , report , " Gyros inconsistent " ) ;
2017-07-27 01:25:06 -03:00
return false ;
2015-01-19 20:27:13 -04:00
}
2019-02-19 23:53:12 -04:00
2021-01-10 16:26:49 -04:00
// no arming while doing temp cal
if ( ins . temperature_cal_running ( ) ) {
check_failed ( ARMING_CHECK_INS , report , " temperature cal running " ) ;
return false ;
}
2019-02-19 23:53:12 -04:00
// check AHRS attitudes are consistent
2019-03-06 02:50:32 -04:00
char failure_msg [ 50 ] = { } ;
if ( ! AP : : ahrs ( ) . attitudes_consistent ( failure_msg , ARRAY_SIZE ( failure_msg ) ) ) {
2019-03-06 22:29:28 -04:00
check_failed ( ARMING_CHECK_INS , report , " %s " , failure_msg ) ;
2019-02-19 23:53:12 -04:00
return false ;
}
2020-01-01 16:34:39 -04:00
# if HAL_GYROFFT_ENABLED
2020-03-27 19:06:43 -03:00
// gyros are healthy so check the FFT
if ( ( checks_to_perform & ARMING_CHECK_ALL ) | |
( checks_to_perform & ARMING_CHECK_FFT ) ) {
// Check that the noise analyser works
AP_GyroFFT * fft = AP : : fft ( ) ;
char fail_msg [ MAVLINK_MSG_STATUSTEXT_FIELD_TEXT_LEN + 1 ] ;
if ( fft ! = nullptr & & ! fft - > pre_arm_check ( fail_msg , ARRAY_SIZE ( fail_msg ) ) ) {
check_failed ( ARMING_CHECK_INS , report , " %s " , fail_msg ) ;
return false ;
}
}
2020-01-01 16:34:39 -04:00
# endif
2015-01-19 20:27:13 -04:00
}
return true ;
}
2015-10-12 02:29:27 -03:00
bool AP_Arming : : compass_checks ( bool report )
2013-12-11 02:02:25 -04:00
{
2019-02-19 22:03:22 -04:00
Compass & _compass = AP : : compass ( ) ;
// check if compass is calibrating
if ( _compass . is_calibrating ( ) ) {
2019-10-04 18:49:20 -03:00
check_failed ( report , " Compass calibration running " ) ;
2019-02-19 22:03:22 -04:00
return false ;
}
// check if compass has calibrated and requires reboot
if ( _compass . compass_cal_requires_reboot ( ) ) {
2019-10-04 18:49:20 -03:00
check_failed ( report , " Compass calibrated requires reboot " ) ;
2019-02-19 22:03:22 -04:00
return false ;
}
2013-12-11 02:02:25 -04:00
if ( ( checks_to_perform ) & ARMING_CHECK_ALL | |
( checks_to_perform ) & ARMING_CHECK_COMPASS ) {
2013-11-27 22:18:14 -04:00
2018-06-21 22:07:34 -03:00
// avoid Compass::use_for_yaw(void) as it implicitly calls healthy() which can
// incorrectly skip the remaining checks, pass the primary instance directly
2019-11-19 03:11:37 -04:00
if ( ! _compass . use_for_yaw ( 0 ) ) {
2015-01-19 20:33:39 -04:00
// compass use is disabled
return true ;
}
2014-07-10 10:47:59 -03:00
if ( ! _compass . healthy ( ) ) {
2017-08-01 00:09:27 -03:00
check_failed ( ARMING_CHECK_COMPASS , report , " Compass not healthy " ) ;
2013-11-27 22:18:14 -04:00
return false ;
}
// check compass learning is on or offsets have been set
2019-11-20 01:07:39 -04:00
if ( ! _compass . learn_offsets_enabled ( ) ) {
char failure_msg [ 50 ] = { } ;
if ( ! _compass . configured ( failure_msg , ARRAY_SIZE ( failure_msg ) ) ) {
check_failed ( ARMING_CHECK_COMPASS , report , " %s " , failure_msg ) ;
return false ;
}
2013-11-27 22:18:14 -04:00
}
2015-01-19 20:27:13 -04:00
// check for unreasonable compass offsets
2018-12-20 04:23:39 -04:00
const Vector3f offsets = _compass . get_offsets ( ) ;
2017-04-03 19:38:36 -03:00
if ( offsets . length ( ) > _compass . get_offsets_max ( ) ) {
2017-08-01 00:09:27 -03:00
check_failed ( ARMING_CHECK_COMPASS , report , " Compass offsets too high " ) ;
2015-01-19 20:27:13 -04:00
return false ;
}
// check for unreasonable mag field length
2018-12-20 04:23:39 -04:00
const float mag_field = _compass . get_field ( ) . length ( ) ;
2015-10-16 00:09:39 -03:00
if ( mag_field > AP_ARMING_COMPASS_MAGFIELD_MAX | | mag_field < AP_ARMING_COMPASS_MAGFIELD_MIN ) {
2020-01-04 04:56:46 -04:00
check_failed ( ARMING_CHECK_COMPASS , report , " Check mag field: %4.0f, max %d, min %d " , ( double ) mag_field , AP_ARMING_COMPASS_MAGFIELD_MAX , AP_ARMING_COMPASS_MAGFIELD_MIN ) ;
2015-01-19 20:27:13 -04:00
return false ;
}
2015-10-16 00:09:39 -03:00
// check all compasses point in roughly same direction
if ( ! _compass . consistent ( ) ) {
2017-08-01 00:09:27 -03:00
check_failed ( ARMING_CHECK_COMPASS , report , " Compasses inconsistent " ) ;
2015-10-16 00:09:39 -03:00
return false ;
}
2013-11-27 22:18:14 -04:00
}
return true ;
}
2015-10-12 02:29:27 -03:00
bool AP_Arming : : gps_checks ( bool report )
2013-12-11 02:02:25 -04:00
{
2017-10-25 00:59:05 -03:00
const AP_GPS & gps = AP : : gps ( ) ;
2016-02-02 03:45:41 -04:00
if ( ( checks_to_perform & ARMING_CHECK_ALL ) | | ( checks_to_perform & ARMING_CHECK_GPS ) ) {
2013-11-27 22:18:14 -04:00
2020-12-28 09:59:33 -04:00
// Any failure messages from GPS backends
if ( ( checks_to_perform & ARMING_CHECK_ALL ) | |
( checks_to_perform & ARMING_CHECK_GPS ) ) {
char failure_msg [ 50 ] = { } ;
if ( ! AP : : gps ( ) . backends_healthy ( failure_msg , ARRAY_SIZE ( failure_msg ) ) ) {
if ( failure_msg [ 0 ] ! = ' \0 ' ) {
check_failed ( ARMING_CHECK_GPS , report , " %s " , failure_msg ) ;
}
return false ;
}
}
2013-11-27 22:18:14 -04:00
//GPS OK?
2018-03-15 22:06:04 -03:00
if ( ! AP : : ahrs ( ) . home_is_set ( ) | |
2015-03-12 23:03:04 -03:00
gps . status ( ) < AP_GPS : : GPS_OK_FIX_3D ) {
2017-08-01 00:09:27 -03:00
check_failed ( ARMING_CHECK_GPS , report , " Bad GPS Position " ) ;
2013-11-27 22:18:14 -04:00
return false ;
2015-10-12 02:29:27 -03:00
}
2017-07-08 20:07:24 -03:00
//GPS update rate acceptable
if ( ! gps . is_healthy ( ) ) {
2017-08-01 00:09:27 -03:00
check_failed ( ARMING_CHECK_GPS , report , " GPS is not healthy " ) ;
2017-07-08 20:07:24 -03:00
return false ;
}
2017-03-08 20:47:57 -04:00
2017-08-29 17:33:33 -03:00
// check GPSs are within 50m of each other and that blending is healthy
2017-03-08 20:47:57 -04:00
float distance_m ;
if ( ! gps . all_consistent ( distance_m ) ) {
2017-08-01 00:09:27 -03:00
check_failed ( ARMING_CHECK_GPS , report , " GPS positions differ by %4.1fm " ,
( double ) distance_m ) ;
2017-03-08 20:47:57 -04:00
return false ;
}
2017-03-10 04:12:46 -04:00
if ( ! gps . blend_health_check ( ) ) {
2017-08-01 00:09:27 -03:00
check_failed ( ARMING_CHECK_GPS , report , " GPS blending unhealthy " ) ;
2017-03-08 20:47:57 -04:00
return false ;
}
2017-09-18 00:14:52 -03:00
// check AHRS and GPS are within 10m of each other
2018-12-20 04:23:39 -04:00
const Location gps_loc = gps . location ( ) ;
2017-09-18 00:14:52 -03:00
Location ahrs_loc ;
2018-06-25 00:42:39 -03:00
if ( AP : : ahrs ( ) . get_position ( ahrs_loc ) ) {
2019-04-08 10:16:13 -03:00
const float distance = gps_loc . get_distance ( ahrs_loc ) ;
2017-09-18 00:14:52 -03:00
if ( distance > AP_ARMING_AHRS_GPS_ERROR_MAX ) {
2018-08-25 20:26:48 -03:00
check_failed ( ARMING_CHECK_GPS , report , " GPS and AHRS differ by %4.1fm " , ( double ) distance ) ;
2017-09-18 00:14:52 -03:00
return false ;
}
}
2017-03-08 20:47:57 -04:00
}
2017-08-29 17:33:33 -03:00
if ( ( checks_to_perform & ARMING_CHECK_ALL ) | | ( checks_to_perform & ARMING_CHECK_GPS_CONFIG ) ) {
2019-07-23 03:21:14 -03:00
uint8_t first_unconfigured ;
if ( gps . first_unconfigured_gps ( first_unconfigured ) ) {
2018-08-25 20:26:48 -03:00
check_failed ( ARMING_CHECK_GPS_CONFIG ,
report ,
" GPS %d failing configuration checks " ,
first_unconfigured + 1 ) ;
2017-08-29 17:33:33 -03:00
if ( report ) {
gps . broadcast_first_configuration_failure_reason ( ) ;
}
return false ;
}
}
2013-11-27 22:18:14 -04:00
return true ;
}
2015-10-12 02:29:27 -03:00
bool AP_Arming : : battery_checks ( bool report )
2013-12-11 02:02:25 -04:00
{
if ( ( checks_to_perform & ARMING_CHECK_ALL ) | |
( checks_to_perform & ARMING_CHECK_BATTERY ) ) {
2013-11-27 22:18:14 -04:00
2018-09-12 19:28:13 -03:00
char buffer [ MAVLINK_MSG_STATUSTEXT_FIELD_TEXT_LEN + 1 ] { } ;
if ( ! AP : : battery ( ) . arming_checks ( sizeof ( buffer ) , buffer ) ) {
2019-03-06 22:29:28 -04:00
check_failed ( ARMING_CHECK_BATTERY , report , " %s " , buffer ) ;
2013-11-27 22:18:14 -04:00
return false ;
}
2016-02-09 19:31:12 -04:00
}
2013-11-27 22:18:14 -04:00
return true ;
}
2014-01-23 06:39:55 -04:00
bool AP_Arming : : hardware_safety_check ( bool report )
2013-12-11 02:02:25 -04:00
{
2015-12-21 02:34:00 -04:00
if ( ( checks_to_perform & ARMING_CHECK_ALL ) | |
( checks_to_perform & ARMING_CHECK_SWITCH ) ) {
// check if safety switch has been pushed
if ( hal . util - > safety_switch_state ( ) = = AP_HAL : : Util : : SAFETY_DISARMED ) {
2017-08-01 00:09:27 -03:00
check_failed ( ARMING_CHECK_SWITCH , report , " Hardware safety switch " ) ;
2015-12-21 02:34:00 -04:00
return false ;
}
2013-11-27 22:18:14 -04:00
}
return true ;
}
2020-03-30 19:24:07 -03:00
bool AP_Arming : : rc_arm_checks ( AP_Arming : : Method method )
{
// don't check the trims if we are in a failsafe
if ( ! rc ( ) . has_valid_input ( ) ) {
return true ;
}
2020-07-06 10:36:26 -03:00
// only check if we've received some form of input within the last second
2020-03-30 19:24:07 -03:00
// this is a protection against a vehicle having never enabled an input
uint32_t last_input_ms = rc ( ) . last_input_ms ( ) ;
if ( ( last_input_ms = = 0 ) | | ( ( AP_HAL : : millis ( ) - last_input_ms ) > 1000 ) ) {
return true ;
}
bool check_passed = true ;
2020-05-27 16:04:00 -03:00
// ensure all rc channels have different functions
if ( rc ( ) . duplicate_options_exist ( ) ) {
check_failed ( ARMING_CHECK_PARAMETERS , true , " Duplicate Aux Switch Options " ) ;
check_passed = false ;
}
2021-06-16 22:14:31 -03:00
if ( rc ( ) . flight_mode_channel_conflicts_with_rc_option ( ) ) {
check_failed ( ARMING_CHECK_PARAMETERS , true , " Mode channel and RC%d_OPTION conflict " , rc ( ) . flight_mode_channel_number ( ) ) ;
check_passed = false ;
}
2020-03-30 19:24:07 -03:00
const RCMapper * rcmap = AP : : rcmap ( ) ;
if ( rcmap ! = nullptr ) {
if ( ! rc ( ) . arming_skip_checks_rpy ( ) ) {
const char * names [ 3 ] = { " Roll " , " Pitch " , " Yaw " } ;
const uint8_t channels [ 3 ] = { rcmap - > roll ( ) , rcmap - > pitch ( ) , rcmap - > yaw ( ) } ;
for ( uint8_t i = 0 ; i < ARRAY_SIZE ( channels ) ; i + + ) {
const RC_Channel * c = rc ( ) . channel ( channels [ i ] - 1 ) ;
if ( c = = nullptr ) {
continue ;
}
2020-05-18 14:27:47 -03:00
if ( c - > get_control_in ( ) ! = 0 ) {
2020-03-30 19:24:07 -03:00
if ( ( method ! = Method : : RUDDER ) | | ( c ! = rc ( ) . get_arming_channel ( ) ) ) { // ignore the yaw input channel if rudder arming
check_failed ( ARMING_CHECK_RC , true , " %s (RC%d) is not neutral " , names [ i ] , channels [ i ] ) ;
check_passed = false ;
}
}
}
}
2020-07-06 10:36:26 -03:00
// if throttle check is enabled, require zero input
2020-03-30 19:24:07 -03:00
if ( rc ( ) . arming_check_throttle ( ) ) {
2020-06-09 19:03:31 -03:00
RC_Channel * c = rc ( ) . channel ( rcmap - > throttle ( ) - 1 ) ;
2020-03-30 19:24:07 -03:00
if ( c ! = nullptr ) {
if ( c - > get_control_in ( ) ! = 0 ) {
check_failed ( ARMING_CHECK_RC , true , " Throttle (RC%d) is not neutral " , rcmap - > throttle ( ) ) ;
check_passed = false ;
}
}
2020-06-09 19:03:31 -03:00
c = rc ( ) . find_channel_for_option ( RC_Channel : : AUX_FUNC : : FWD_THR ) ;
if ( c ! = nullptr ) {
uint8_t fwd_thr = c - > percent_input ( ) ;
// require channel input within 2% of minimum
if ( fwd_thr > 2 ) {
check_failed ( ARMING_CHECK_RC , true , " VTOL Fwd Throttle is not zero " ) ;
check_passed = false ;
}
}
2020-03-30 19:24:07 -03:00
}
}
return check_passed ;
}
2017-09-04 01:16:12 -03:00
bool AP_Arming : : rc_calibration_checks ( bool report )
{
2018-04-19 16:59:35 -03:00
bool check_passed = true ;
2018-07-22 18:05:23 -03:00
const uint8_t num_channels = RC_Channels : : get_valid_channel_count ( ) ;
2018-04-19 16:59:35 -03:00
for ( uint8_t i = 0 ; i < NUM_RC_CHANNELS ; i + + ) {
2018-10-11 20:44:00 -03:00
const RC_Channel * c = rc ( ) . channel ( i ) ;
if ( c = = nullptr ) {
2018-04-19 16:59:35 -03:00
continue ;
}
2018-10-11 20:44:00 -03:00
if ( i > = num_channels & & ! ( c - > has_override ( ) ) ) {
2018-07-22 18:05:23 -03:00
continue ;
}
2018-10-11 20:44:00 -03:00
const uint16_t trim = c - > get_radio_trim ( ) ;
if ( c - > get_radio_min ( ) > trim ) {
2020-04-23 09:47:24 -03:00
check_failed ( ARMING_CHECK_RC , report , " RC%d_MIN is greater than RC%d_TRIM " , i + 1 , i + 1 ) ;
2018-04-19 16:59:35 -03:00
check_passed = false ;
}
2018-10-11 20:44:00 -03:00
if ( c - > get_radio_max ( ) < trim ) {
2020-04-23 09:47:24 -03:00
check_failed ( ARMING_CHECK_RC , report , " RC%d_MAX is less than RC%d_TRIM " , i + 1 , i + 1 ) ;
2018-04-19 16:59:35 -03:00
check_passed = false ;
}
}
return check_passed ;
2017-09-04 01:16:12 -03:00
}
2015-10-12 02:29:27 -03:00
bool AP_Arming : : manual_transmitter_checks ( bool report )
2013-12-11 02:02:25 -04:00
{
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 ) {
2017-08-01 00:09:27 -03:00
check_failed ( ARMING_CHECK_RC , report , " Radio failsafe on " ) ;
2013-11-27 22:18:14 -04:00
return false ;
}
2017-09-04 01:16:12 -03:00
if ( ! rc_calibration_checks ( report ) ) {
return false ;
}
2013-11-27 22:18:14 -04:00
}
return true ;
}
2018-12-25 01:19:02 -04:00
bool AP_Arming : : mission_checks ( bool report )
{
if ( ( ( checks_to_perform & ARMING_CHECK_ALL ) | | ( checks_to_perform & ARMING_CHECK_MISSION ) ) & &
_required_mission_items ) {
AP_Mission * mission = AP : : mission ( ) ;
if ( mission = = nullptr ) {
check_failed ( ARMING_CHECK_MISSION , report , " No mission library present " ) ;
# if CONFIG_HAL_BOARD == HAL_BOARD_SITL
AP_HAL : : panic ( " Mission checks requested, but no mission was allocated " ) ;
# endif // CONFIG_HAL_BOARD == HAL_BOARD_SITL
return false ;
}
AP_Rally * rally = AP : : rally ( ) ;
if ( rally = = nullptr ) {
check_failed ( ARMING_CHECK_MISSION , report , " No rally library present " ) ;
# if CONFIG_HAL_BOARD == HAL_BOARD_SITL
AP_HAL : : panic ( " Mission checks requested, but no rally was allocated " ) ;
# endif // CONFIG_HAL_BOARD == HAL_BOARD_SITL
return false ;
}
const struct MisItemTable {
MIS_ITEM_CHECK check ;
MAV_CMD mis_item_type ;
const char * type ;
} misChecks [ 5 ] = {
{ MIS_ITEM_CHECK_LAND , MAV_CMD_NAV_LAND , " land " } ,
{ MIS_ITEM_CHECK_VTOL_LAND , MAV_CMD_NAV_VTOL_LAND , " vtol land " } ,
{ MIS_ITEM_CHECK_DO_LAND_START , MAV_CMD_DO_LAND_START , " do land start " } ,
{ MIS_ITEM_CHECK_TAKEOFF , MAV_CMD_NAV_TAKEOFF , " takeoff " } ,
{ MIS_ITEM_CHECK_VTOL_TAKEOFF , MAV_CMD_NAV_VTOL_TAKEOFF , " vtol takeoff " } ,
} ;
for ( uint8_t i = 0 ; i < ARRAY_SIZE ( misChecks ) ; i + + ) {
if ( _required_mission_items & misChecks [ i ] . check ) {
if ( ! mission - > contains_item ( misChecks [ i ] . mis_item_type ) ) {
check_failed ( ARMING_CHECK_MISSION , report , " Missing mission item: %s " , misChecks [ i ] . type ) ;
return false ;
}
}
}
if ( _required_mission_items & MIS_ITEM_CHECK_RALLY ) {
Location ahrs_loc ;
if ( ! AP : : ahrs ( ) . get_position ( ahrs_loc ) ) {
check_failed ( ARMING_CHECK_MISSION , report , " Can't check rally without position " ) ;
return false ;
}
RallyLocation rally_loc = { } ;
if ( ! rally - > find_nearest_rally_point ( ahrs_loc , rally_loc ) ) {
check_failed ( ARMING_CHECK_MISSION , report , " No sufficently close rally point located " ) ;
return false ;
}
}
}
return true ;
}
2019-04-10 04:32:30 -03:00
bool AP_Arming : : rangefinder_checks ( bool report )
{
if ( ( checks_to_perform & ARMING_CHECK_ALL ) | | ( checks_to_perform & ARMING_CHECK_RANGEFINDER ) ) {
RangeFinder * range = RangeFinder : : get_singleton ( ) ;
if ( range = = nullptr ) {
return true ;
}
char buffer [ MAVLINK_MSG_STATUSTEXT_FIELD_TEXT_LEN + 1 ] ;
if ( ! range - > prearm_healthy ( buffer , ARRAY_SIZE ( buffer ) ) ) {
check_failed ( ARMING_CHECK_RANGEFINDER , report , " %s " , buffer ) ;
return false ;
}
}
return true ;
}
2018-04-19 17:10:39 -03:00
bool AP_Arming : : servo_checks ( bool report ) const
{
bool check_passed = true ;
for ( uint8_t i = 0 ; i < NUM_SERVO_CHANNELS ; i + + ) {
2018-10-11 20:44:00 -03:00
const SRV_Channel * c = SRV_Channels : : srv_channel ( i ) ;
if ( c = = nullptr | | c - > get_function ( ) = = SRV_Channel : : k_none ) {
2018-04-19 17:10:39 -03:00
continue ;
}
2018-10-11 20:44:00 -03:00
const uint16_t trim = c - > get_trim ( ) ;
if ( c - > get_output_min ( ) > trim ) {
2020-04-23 09:47:24 -03:00
check_failed ( report , " SERVO%d_MIN is greater than SERVO%d_TRIM " , i + 1 , i + 1 ) ;
2018-04-19 17:10:39 -03:00
check_passed = false ;
}
2018-10-11 20:44:00 -03:00
if ( c - > get_output_max ( ) < trim ) {
2020-04-23 09:47:24 -03:00
check_failed ( report , " SERVO%d_MAX is less than SERVO%d_TRIM " , i + 1 , i + 1 ) ;
2018-04-19 17:10:39 -03:00
check_passed = false ;
}
}
2018-10-30 21:05:45 -03:00
# if HAL_WITH_IO_MCU
if ( ! iomcu . healthy ( ) ) {
2019-10-04 18:49:20 -03:00
check_failed ( report , " IOMCU is unhealthy " ) ;
2018-10-30 21:05:45 -03:00
check_passed = false ;
}
# endif
2019-04-24 21:57:24 -03:00
2018-04-19 17:10:39 -03:00
return check_passed ;
}
2015-10-16 00:13:53 -03:00
bool AP_Arming : : board_voltage_checks ( bool report )
{
// check board voltage
if ( ( checks_to_perform & ARMING_CHECK_ALL ) | | ( checks_to_perform & ARMING_CHECK_VOLTAGE ) ) {
2018-11-06 22:29:30 -04:00
# if HAL_HAVE_BOARD_VOLTAGE
const float bus_voltage = hal . analogin - > board_voltage ( ) ;
const float vbus_min = AP_BoardConfig : : get_minimum_board_voltage ( ) ;
if ( ( ( bus_voltage < vbus_min ) | | ( bus_voltage > AP_ARMING_BOARD_VOLTAGE_MAX ) ) ) {
2018-11-14 07:40:46 -04:00
check_failed ( ARMING_CHECK_VOLTAGE , report , " Board (%1.1fv) out of range %1.1f-%1.1fv " , ( double ) bus_voltage , ( double ) vbus_min , ( double ) AP_ARMING_BOARD_VOLTAGE_MAX ) ;
2015-10-16 00:13:53 -03:00
return false ;
}
2018-11-06 22:29:30 -04:00
# endif // HAL_HAVE_BOARD_VOLTAGE
# if HAL_HAVE_SERVO_VOLTAGE
const float vservo_min = AP_BoardConfig : : get_minimum_servo_voltage ( ) ;
if ( is_positive ( vservo_min ) ) {
const float servo_voltage = hal . analogin - > servorail_voltage ( ) ;
if ( servo_voltage < vservo_min ) {
2018-11-14 07:40:46 -04:00
check_failed ( ARMING_CHECK_VOLTAGE , report , " Servo voltage to low (%1.2fv < %1.2fv) " , ( double ) servo_voltage , ( double ) vservo_min ) ;
2018-11-06 22:29:30 -04:00
return false ;
}
}
# endif // HAL_HAVE_SERVO_VOLTAGE
2015-10-16 00:13:53 -03:00
}
2018-11-06 22:29:30 -04:00
2015-10-16 00:13:53 -03:00
return true ;
}
2018-06-29 20:23:08 -03:00
/*
check base system operations
*/
bool AP_Arming : : system_checks ( bool report )
{
2018-06-30 06:11:34 -03:00
if ( check_enabled ( ARMING_CHECK_SYSTEM ) ) {
2018-06-29 20:23:08 -03:00
if ( ! hal . storage - > healthy ( ) ) {
check_failed ( ARMING_CHECK_SYSTEM , report , " Param storage failed " ) ;
2018-08-11 13:37:17 -03:00
return false ;
2018-06-29 20:23:08 -03:00
}
2019-11-06 22:04:07 -04:00
# if AP_TERRAIN_AVAILABLE
const AP_Terrain * terrain = AP_Terrain : : get_singleton ( ) ;
if ( ( terrain ! = nullptr ) & & terrain - > init_failed ( ) ) {
check_failed ( ARMING_CHECK_SYSTEM , report , " Terrain out of memory " ) ;
return false ;
}
2019-11-26 02:31:36 -04:00
# endif
# ifdef ENABLE_SCRIPTING
const AP_Scripting * scripting = AP_Scripting : : get_singleton ( ) ;
if ( ( scripting ! = nullptr ) & & scripting - > enabled ( ) & & scripting - > init_failed ( ) ) {
check_failed ( ARMING_CHECK_SYSTEM , report , " Scripting out of memory " ) ;
return false ;
}
2020-10-28 10:45:05 -03:00
# endif
# if HAL_ADSB_ENABLED
AP_ADSB * adsb = AP : : ADSB ( ) ;
if ( ( adsb ! = nullptr ) & & adsb - > enabled ( ) & & adsb - > init_failed ( ) ) {
check_failed ( ARMING_CHECK_SYSTEM , report , " ADSB out of memory " ) ;
return false ;
}
2019-11-06 22:04:07 -04:00
# endif
2018-06-29 20:23:08 -03:00
}
2019-04-24 21:57:24 -03:00
if ( AP : : internalerror ( ) . errors ( ) ! = 0 ) {
2020-04-30 02:09:40 -03:00
uint8_t buffer [ 32 ] ;
AP : : internalerror ( ) . errors_as_string ( buffer , ARRAY_SIZE ( buffer ) ) ;
2020-04-30 02:09:40 -03:00
check_failed ( report , " Internal errors 0x%x l:%u %s " , ( unsigned int ) AP : : internalerror ( ) . errors ( ) , AP : : internalerror ( ) . last_error_line ( ) , buffer ) ;
2019-04-24 21:57:24 -03:00
return false ;
}
2018-06-29 20:23:08 -03:00
return true ;
}
2019-05-29 23:28:33 -03:00
// check nothing is too close to vehicle
bool AP_Arming : : proximity_checks ( bool report ) const
{
2021-03-25 05:05:36 -03:00
# if HAL_PROXIMITY_ENABLED
2019-05-29 23:28:33 -03:00
const AP_Proximity * proximity = AP : : proximity ( ) ;
// return true immediately if no sensor present
if ( proximity = = nullptr ) {
return true ;
}
2019-09-27 05:59:26 -03:00
if ( proximity - > get_status ( ) = = AP_Proximity : : Status : : NotConnected ) {
2019-05-29 23:28:33 -03:00
return true ;
}
// return false if proximity sensor unhealthy
2019-09-27 05:59:26 -03:00
if ( proximity - > get_status ( ) < AP_Proximity : : Status : : Good ) {
2019-10-04 18:49:20 -03:00
check_failed ( report , " check proximity sensor " ) ;
2019-05-29 23:28:33 -03:00
return false ;
}
2021-03-25 05:05:36 -03:00
# endif
2019-05-29 23:28:33 -03:00
return true ;
}
2018-08-11 11:09:57 -03:00
bool AP_Arming : : can_checks ( bool report )
{
2020-05-31 09:02:10 -03:00
# if HAL_MAX_CAN_PROTOCOL_DRIVERS
2018-08-11 11:09:57 -03:00
if ( check_enabled ( ARMING_CHECK_SYSTEM ) ) {
2019-10-04 04:12:10 -03:00
char fail_msg [ 50 ] = { } ;
2018-08-11 11:09:57 -03:00
uint8_t num_drivers = AP : : can ( ) . get_num_drivers ( ) ;
for ( uint8_t i = 0 ; i < num_drivers ; i + + ) {
2020-05-31 09:02:10 -03:00
switch ( AP : : can ( ) . get_driver_type ( i ) ) {
case AP_CANManager : : Driver_Type_KDECAN : {
2018-08-11 11:09:57 -03:00
// To be replaced with macro saying if KDECAN library is included
# if APM_BUILD_TYPE(APM_BUILD_ArduCopter) || APM_BUILD_TYPE(APM_BUILD_ArduPlane) || APM_BUILD_TYPE(APM_BUILD_ArduSub)
AP_KDECAN * ap_kdecan = AP_KDECAN : : get_kdecan ( i ) ;
2019-10-04 04:12:10 -03:00
if ( ap_kdecan ! = nullptr & & ! ap_kdecan - > pre_arm_check ( fail_msg , ARRAY_SIZE ( fail_msg ) ) ) {
2020-05-01 02:19:59 -03:00
check_failed ( ARMING_CHECK_SYSTEM , report , " KDECAN: %s " , fail_msg ) ;
2018-08-11 11:09:57 -03:00
return false ;
}
2019-12-09 00:31:29 -04:00
# endif
2020-03-07 12:33:49 -04:00
break ;
2019-12-09 00:31:29 -04:00
}
2020-05-31 09:02:10 -03:00
case AP_CANManager : : Driver_Type_PiccoloCAN : {
2019-12-09 00:31:29 -04:00
# if HAL_PICCOLO_CAN_ENABLE
AP_PiccoloCAN * ap_pcan = AP_PiccoloCAN : : get_pcan ( i ) ;
if ( ap_pcan ! = nullptr & & ! ap_pcan - > pre_arm_check ( fail_msg , ARRAY_SIZE ( fail_msg ) ) ) {
2020-05-01 02:19:59 -03:00
check_failed ( ARMING_CHECK_SYSTEM , report , " PiccoloCAN: %s " , fail_msg ) ;
2019-12-09 00:31:29 -04:00
return false ;
}
# else
check_failed ( ARMING_CHECK_SYSTEM , report , " PiccoloCAN not enabled " ) ;
return false ;
2018-08-11 11:09:57 -03:00
# endif
2020-03-07 12:33:49 -04:00
break ;
2018-08-11 11:09:57 -03:00
}
2020-05-31 09:02:10 -03:00
case AP_CANManager : : Driver_Type_UAVCAN :
2019-10-04 04:12:10 -03:00
{
2019-10-25 00:03:23 -03:00
if ( ! AP : : uavcan_dna_server ( ) . prearm_check ( fail_msg , ARRAY_SIZE ( fail_msg ) ) ) {
2020-05-01 02:19:59 -03:00
check_failed ( ARMING_CHECK_SYSTEM , report , " UAVCAN: %s " , fail_msg ) ;
2019-10-04 04:12:10 -03:00
return false ;
}
2020-03-07 12:33:49 -04:00
break ;
2019-10-04 04:12:10 -03:00
}
2020-05-31 09:02:10 -03:00
case AP_CANManager : : Driver_Type_ToshibaCAN :
2020-05-01 02:19:59 -03:00
{
// toshibacan doesn't currently have any prearm
// checks. Theres scope for adding a "not
// initialised" prearm check.
break ;
}
2020-05-31 09:02:10 -03:00
case AP_CANManager : : Driver_Type_CANTester :
{
check_failed ( ARMING_CHECK_SYSTEM , report , " TestCAN: No Arming with TestCAN enabled " ) ;
break ;
}
2020-12-31 18:26:58 -04:00
case AP_CANManager : : Driver_Type_EFI_NWPMU :
2020-12-31 20:10:03 -04:00
case AP_CANManager : : Driver_Type_USD1 :
2021-04-22 15:03:25 -03:00
case AP_CANManager : : Driver_Type_MPPT_PacketDigital :
2020-05-31 09:02:10 -03:00
case AP_CANManager : : Driver_Type_None :
2018-08-11 11:09:57 -03:00
break ;
}
}
}
# endif
return true ;
}
2019-03-05 19:09:55 -04:00
bool AP_Arming : : fence_checks ( bool display_failure )
{
const AC_Fence * fence = AP : : fence ( ) ;
if ( fence = = nullptr ) {
return true ;
}
// check fence is ready
const char * fail_msg = nullptr ;
if ( fence - > pre_arm_check ( fail_msg ) ) {
return true ;
}
if ( fail_msg = = nullptr ) {
2019-10-04 18:49:20 -03:00
check_failed ( display_failure , " Check fence " ) ;
2019-03-05 19:09:55 -04:00
} else {
2019-10-04 18:49:20 -03:00
check_failed ( display_failure , " %s " , fail_msg ) ;
2019-03-05 19:09:55 -04:00
}
return false ;
}
2019-12-06 13:52:12 -04:00
bool AP_Arming : : camera_checks ( bool display_failure )
{
if ( ( checks_to_perform & ARMING_CHECK_ALL ) | | ( checks_to_perform & ARMING_CHECK_CAMERA ) ) {
# if HAL_RUNCAM_ENABLED
AP_RunCam * runcam = AP : : runcam ( ) ;
if ( runcam = = nullptr ) {
return true ;
}
// check camera is ready
char fail_msg [ MAVLINK_MSG_STATUSTEXT_FIELD_TEXT_LEN + 1 ] ;
if ( ! runcam - > pre_arm_check ( fail_msg , ARRAY_SIZE ( fail_msg ) ) ) {
check_failed ( ARMING_CHECK_CAMERA , display_failure , " %s " , fail_msg ) ;
return false ;
}
# endif
}
return true ;
}
2020-04-26 11:37:49 -03:00
bool AP_Arming : : osd_checks ( bool display_failure ) const
{
2020-11-17 12:39:17 -04:00
# if OSD_PARAM_ENABLED && OSD_ENABLED
2020-04-26 11:37:49 -03:00
if ( ( checks_to_perform & ARMING_CHECK_ALL ) | | ( checks_to_perform & ARMING_CHECK_CAMERA ) ) {
const AP_OSD * osd = AP : : osd ( ) ;
if ( osd = = nullptr ) {
return true ;
}
// check camera is ready
char fail_msg [ MAVLINK_MSG_STATUSTEXT_FIELD_TEXT_LEN + 1 ] ;
if ( ! osd - > pre_arm_check ( fail_msg , ARRAY_SIZE ( fail_msg ) ) ) {
check_failed ( ARMING_CHECK_CAMERA , display_failure , " %s " , fail_msg ) ;
return false ;
}
}
# endif
return true ;
}
2020-02-12 00:50:07 -04:00
// request an auxiliary authorisation id. This id should be used in subsequent calls to set_aux_auth_passed/failed
// returns true on success
bool AP_Arming : : get_aux_auth_id ( uint8_t & auth_id )
{
WITH_SEMAPHORE ( aux_auth_sem ) ;
// check we have enough room to allocate another id
if ( aux_auth_count > = aux_auth_count_max ) {
aux_auth_error = true ;
return false ;
}
// allocate buffer for failure message
if ( aux_auth_fail_msg = = nullptr ) {
aux_auth_fail_msg = ( char * ) calloc ( aux_auth_str_len , sizeof ( char ) ) ;
if ( aux_auth_fail_msg = = nullptr ) {
aux_auth_error = true ;
return false ;
}
}
auth_id = aux_auth_count ;
aux_auth_count + + ;
return true ;
}
// set auxiliary authorisation passed
void AP_Arming : : set_aux_auth_passed ( uint8_t auth_id )
{
WITH_SEMAPHORE ( aux_auth_sem ) ;
// sanity check auth_id
if ( auth_id > = aux_auth_count ) {
return ;
}
aux_auth_state [ auth_id ] = AuxAuthStates : : AUTH_PASSED ;
}
// set auxiliary authorisation failed and provide failure message
void AP_Arming : : set_aux_auth_failed ( uint8_t auth_id , const char * fail_msg )
{
WITH_SEMAPHORE ( aux_auth_sem ) ;
// sanity check auth_id
if ( auth_id > = aux_auth_count ) {
return ;
}
// update state
aux_auth_state [ auth_id ] = AuxAuthStates : : AUTH_FAILED ;
// store failure message if this authoriser has the lowest auth_id
for ( uint8_t i = 0 ; i < auth_id ; i + + ) {
if ( aux_auth_state [ i ] = = AuxAuthStates : : AUTH_FAILED ) {
return ;
}
}
if ( aux_auth_fail_msg ! = nullptr ) {
if ( fail_msg = = nullptr ) {
strncpy ( aux_auth_fail_msg , " Auxiliary authorisation refused " , aux_auth_str_len ) ;
} else {
strncpy ( aux_auth_fail_msg , fail_msg , aux_auth_str_len ) ;
}
aux_auth_fail_msg_source = auth_id ;
}
}
bool AP_Arming : : aux_auth_checks ( bool display_failure )
{
// handle error cases
if ( aux_auth_error ) {
if ( aux_auth_fail_msg = = nullptr ) {
check_failed ( ARMING_CHECK_AUX_AUTH , display_failure , " memory low for auxiliary authorisation " ) ;
} else {
check_failed ( ARMING_CHECK_AUX_AUTH , display_failure , " Too many auxiliary authorisers " ) ;
}
return false ;
}
WITH_SEMAPHORE ( aux_auth_sem ) ;
// check results for each auxiliary authorisation id
bool some_failures = false ;
bool failure_msg_sent = false ;
bool waiting_for_responses = false ;
for ( uint8_t i = 0 ; i < aux_auth_count ; i + + ) {
switch ( aux_auth_state [ i ] ) {
case AuxAuthStates : : NO_RESPONSE :
waiting_for_responses = true ;
break ;
case AuxAuthStates : : AUTH_FAILED :
some_failures = true ;
if ( i = = aux_auth_fail_msg_source ) {
check_failed ( ARMING_CHECK_AUX_AUTH , display_failure , " %s " , aux_auth_fail_msg ) ;
failure_msg_sent = true ;
}
break ;
case AuxAuthStates : : AUTH_PASSED :
break ;
}
}
// send failure or waiting message
2020-11-10 20:42:50 -04:00
if ( some_failures ) {
if ( ! failure_msg_sent ) {
check_failed ( ARMING_CHECK_AUX_AUTH , display_failure , " Auxiliary authorisation refused " ) ;
}
2020-02-12 00:50:07 -04:00
return false ;
} else if ( waiting_for_responses ) {
check_failed ( ARMING_CHECK_AUX_AUTH , display_failure , " Waiting for auxiliary authorisation " ) ;
return false ;
}
// if we got this far all auxiliary checks must have passed
return true ;
}
2019-11-27 03:44:03 -04:00
bool AP_Arming : : generator_checks ( bool display_failure ) const
{
# if GENERATOR_ENABLED
2020-10-22 14:15:41 -03:00
const AP_Generator * generator = AP : : generator ( ) ;
2019-11-27 03:44:03 -04:00
if ( generator = = nullptr ) {
return true ;
}
char failure_msg [ 50 ] = { } ;
if ( ! generator - > pre_arm_check ( failure_msg , sizeof ( failure_msg ) ) ) {
check_failed ( display_failure , " Generator: %s " , failure_msg ) ;
return false ;
}
# endif
return true ;
}
2015-10-12 02:29:27 -03:00
bool AP_Arming : : pre_arm_checks ( bool report )
2013-12-11 02:02:25 -04:00
{
2016-12-28 01:41:21 -04:00
# if !APM_BUILD_TYPE(APM_BUILD_ArduCopter)
2019-03-06 23:12:39 -04:00
if ( armed | | require = = ( uint8_t ) Required : : NO ) {
2014-01-23 06:39:55 -04:00
// if we are already armed or don't need any arming checks
// then skip the checks
return true ;
}
2016-12-28 01:41:21 -04:00
# endif
2014-01-23 06:39:55 -04:00
2016-12-03 08:30:46 -04:00
return hardware_safety_check ( report )
& barometer_checks ( report )
& ins_checks ( report )
& compass_checks ( report )
& gps_checks ( report )
& battery_checks ( report )
& logging_checks ( report )
& manual_transmitter_checks ( report )
2018-12-25 01:19:02 -04:00
& mission_checks ( report )
2019-04-10 04:32:30 -03:00
& rangefinder_checks ( report )
2018-04-19 17:10:39 -03:00
& servo_checks ( report )
2018-06-29 20:23:08 -03:00
& board_voltage_checks ( report )
2018-08-11 11:09:57 -03:00
& system_checks ( report )
2019-05-29 23:28:33 -03:00
& can_checks ( report )
2019-11-27 03:44:03 -04:00
& generator_checks ( report )
2019-12-06 13:52:12 -04:00
& proximity_checks ( report )
2020-02-12 00:50:07 -04:00
& camera_checks ( report )
2020-04-26 11:37:49 -03:00
& osd_checks ( report )
2020-03-30 00:30:20 -03:00
& visodom_checks ( report )
2020-04-30 11:57:44 -03:00
& aux_auth_checks ( report )
2020-08-31 21:56:12 -03:00
& disarm_switch_checks ( report )
& fence_checks ( report ) ;
2013-11-27 22:18:14 -04:00
}
2019-03-06 23:12:39 -04:00
bool AP_Arming : : arm_checks ( AP_Arming : : Method method )
2016-11-05 20:23:14 -03:00
{
2020-03-30 19:24:07 -03:00
if ( ( checks_to_perform & ARMING_CHECK_ALL ) | |
( checks_to_perform & ARMING_CHECK_RC ) ) {
if ( ! rc_arm_checks ( method ) ) {
return false ;
}
}
2020-03-27 19:06:43 -03:00
# if HAL_GYROFFT_ENABLED
// make sure the FFT subsystem is enabled if arming checks have been disabled
AP_GyroFFT * fft = AP : : fft ( ) ;
if ( fft ! = nullptr ) {
fft - > prepare_for_arming ( ) ;
}
# endif
2017-10-19 22:16:37 -03:00
// ensure the GPS drivers are ready on any final changes
if ( ( checks_to_perform & ARMING_CHECK_ALL ) | |
( checks_to_perform & ARMING_CHECK_GPS_CONFIG ) ) {
2017-10-25 00:59:05 -03:00
if ( ! AP : : gps ( ) . prepare_for_arming ( ) ) {
2017-10-19 22:16:37 -03:00
return false ;
}
}
2020-08-31 21:56:12 -03:00
AC_Fence * fence = AP : : fence ( ) ;
if ( fence ! = nullptr ) {
// If a fence is set to auto-enable, turn on the fence
if ( fence - > auto_enabled ( ) = = AC_Fence : : AutoEnable : : ONLY_WHEN_ARMED ) {
fence - > enable ( true ) ;
}
}
2018-06-29 20:23:08 -03:00
2019-01-18 00:23:42 -04:00
// note that this will prepare AP_Logger to start logging
2017-06-30 09:31:08 -03:00
// so should be the last check to be done before arming
2019-01-17 04:11:08 -04:00
// Note also that we need to PrepForArming() regardless of whether
// the arming check flag is set - disabling the arming check
// should not stop logging from working.
2019-02-11 04:16:10 -04:00
AP_Logger * logger = AP_Logger : : get_singleton ( ) ;
if ( logger - > logging_present ( ) ) {
2019-01-17 04:11:08 -04:00
// If we're configured to log, prep it
2019-02-11 04:16:10 -04:00
logger - > PrepForArming ( ) ;
if ( ! logger - > logging_started ( ) & &
2019-01-17 04:11:08 -04:00
( ( checks_to_perform & ARMING_CHECK_ALL ) | |
( checks_to_perform & ARMING_CHECK_LOGGING ) ) ) {
2017-08-01 00:09:27 -03:00
check_failed ( ARMING_CHECK_LOGGING , true , " Logging not started " ) ;
2016-11-05 20:23:14 -03:00
return false ;
}
}
return true ;
}
2016-05-12 13:51:51 -03:00
//returns true if arming occurred successfully
2019-03-06 23:12:39 -04:00
bool AP_Arming : : arm ( AP_Arming : : Method method , const bool do_arming_checks )
2013-12-11 02:02:25 -04:00
{
2013-11-27 22:18:14 -04:00
if ( armed ) { //already armed
return false ;
}
2019-11-29 02:18:19 -04:00
if ( ( ! do_arming_checks & & mandatory_checks ( true ) ) | | ( pre_arm_checks ( true ) & & arm_checks ( method ) ) ) {
2013-11-27 22:18:14 -04:00
armed = true ;
2020-01-07 01:04:01 -04:00
Log_Write_Arm ( ! do_arming_checks , method ) ; // note Log_Write_Armed takes forced not do_arming_checks
2013-11-27 22:18:14 -04:00
} else {
2019-06-10 18:55:44 -03:00
AP : : logger ( ) . arming_failure ( ) ;
2013-11-27 22:18:14 -04:00
armed = false ;
}
return armed ;
}
//returns true if disarming occurred successfully
2021-01-05 20:15:47 -04:00
bool AP_Arming : : disarm ( const AP_Arming : : Method method , bool do_disarm_checks )
2013-12-11 02:02:25 -04:00
{
2015-10-12 02:29:27 -03:00
if ( ! armed ) { // already disarmed
2013-11-27 22:18:14 -04:00
return false ;
}
armed = false ;
2020-07-15 23:52:11 -03:00
_last_disarm_method = method ;
2013-11-27 22:18:14 -04:00
2020-02-21 09:09:57 -04:00
Log_Write_Disarm ( method ) ; // should be able to pass through force here?
2020-01-07 01:04:01 -04:00
2018-12-30 04:46:22 -04:00
# if HAL_HAVE_SAFETY_SWITCH
2019-02-10 14:33:16 -04:00
AP_BoardConfig * board_cfg = AP_BoardConfig : : get_singleton ( ) ;
2018-12-30 04:46:22 -04:00
if ( ( board_cfg ! = nullptr ) & &
( board_cfg - > get_safety_button_options ( ) & AP_BoardConfig : : BOARD_SAFETY_OPTION_SAFETY_ON_DISARM ) ) {
hal . rcout - > force_safety_on ( ) ;
}
# endif // HAL_HAVE_SAFETY_SWITCH
2020-01-01 16:34:39 -04:00
# if HAL_GYROFFT_ENABLED
AP_GyroFFT * fft = AP : : fft ( ) ;
if ( fft ! = nullptr ) {
fft - > save_params_on_disarm ( ) ;
}
# endif
2020-08-31 21:56:12 -03:00
AC_Fence * fence = AP : : fence ( ) ;
if ( fence ! = nullptr ) {
if ( fence - > auto_enabled ( ) = = AC_Fence : : AutoEnable : : ONLY_WHEN_ARMED ) {
fence - > enable ( false ) ;
}
}
2013-11-27 22:18:14 -04:00
return true ;
}
2019-03-06 23:12:39 -04:00
AP_Arming : : Required AP_Arming : : arming_required ( )
2013-12-11 02:02:25 -04:00
{
2019-03-06 23:12:39 -04:00
return ( AP_Arming : : Required ) require . get ( ) ;
2013-11-27 22:18:14 -04:00
}
2017-08-09 20:11:22 -03:00
// Copter and sub share the same RC input limits
2017-08-14 14:53:20 -03:00
// Copter checks that min and max have been configured by default, Sub does not
2018-12-20 04:23:02 -04:00
bool AP_Arming : : rc_checks_copter_sub ( const bool display_failure , const RC_Channel * channels [ 4 ] ) const
2017-08-09 20:11:22 -03:00
{
// set rc-checks to success if RC checks are disabled
if ( ( checks_to_perform ! = ARMING_CHECK_ALL ) & & ! ( checks_to_perform & ARMING_CHECK_RC ) ) {
return true ;
}
bool ret = true ;
const char * channel_names [ ] = { " Roll " , " Pitch " , " Throttle " , " Yaw " } ;
for ( uint8_t i = 0 ; i < ARRAY_SIZE ( channel_names ) ; i + + ) {
const RC_Channel * channel = channels [ i ] ;
const char * channel_name = channel_names [ i ] ;
// check if radio has been calibrated
2021-02-03 10:35:57 -04:00
if ( channel - > get_radio_min ( ) > RC_Channel : : RC_CALIB_MIN_LIMIT_PWM ) {
2017-08-01 00:09:27 -03:00
check_failed ( ARMING_CHECK_RC , display_failure , " %s radio min too high " , channel_name ) ;
2017-08-09 20:11:22 -03:00
ret = false ;
}
2021-02-03 10:35:57 -04:00
if ( channel - > get_radio_max ( ) < RC_Channel : : RC_CALIB_MAX_LIMIT_PWM ) {
2017-08-01 00:09:27 -03:00
check_failed ( ARMING_CHECK_RC , display_failure , " %s radio max too low " , channel_name ) ;
2017-08-09 20:11:22 -03:00
ret = false ;
}
2017-08-09 20:14:31 -03:00
bool fail = true ;
2017-08-09 20:11:22 -03:00
if ( i = = 2 ) {
// skip checking trim for throttle as older code did not check it
2017-08-09 20:14:31 -03:00
fail = false ;
2017-08-09 20:11:22 -03:00
}
if ( channel - > get_radio_trim ( ) < channel - > get_radio_min ( ) ) {
2017-08-01 00:09:27 -03:00
check_failed ( ARMING_CHECK_RC , display_failure , " %s radio trim below min " , channel_name ) ;
2017-08-09 20:14:31 -03:00
if ( fail ) {
ret = false ;
}
2017-08-09 20:11:22 -03:00
}
if ( channel - > get_radio_trim ( ) > channel - > get_radio_max ( ) ) {
2017-08-01 00:09:27 -03:00
check_failed ( ARMING_CHECK_RC , display_failure , " %s radio trim above max " , channel_name ) ;
2017-08-09 20:14:31 -03:00
if ( fail ) {
ret = false ;
}
2017-08-09 20:11:22 -03:00
}
}
return ret ;
}
2019-05-06 00:33:15 -03:00
2020-03-30 00:30:20 -03:00
// check visual odometry is working
bool AP_Arming : : visodom_checks ( bool display_failure ) const
{
if ( ( checks_to_perform ! = ARMING_CHECK_ALL ) & & ! ( checks_to_perform & ARMING_CHECK_VISION ) ) {
return true ;
}
# if HAL_VISUALODOM_ENABLED
AP_VisualOdom * visual_odom = AP : : visualodom ( ) ;
if ( visual_odom ! = nullptr ) {
char fail_msg [ MAVLINK_MSG_STATUSTEXT_FIELD_TEXT_LEN + 1 ] ;
if ( ! visual_odom - > pre_arm_check ( fail_msg , ARRAY_SIZE ( fail_msg ) ) ) {
2020-07-26 11:11:59 -03:00
check_failed ( ARMING_CHECK_VISION , display_failure , " VisOdom: %s " , fail_msg ) ;
2020-03-30 00:30:20 -03:00
return false ;
}
}
# endif
return true ;
}
2020-04-30 11:57:44 -03:00
// check disarm switch is asserted
bool AP_Arming : : disarm_switch_checks ( bool display_failure ) const
{
const RC_Channel * chan = rc ( ) . find_channel_for_option ( RC_Channel : : AUX_FUNC : : DISARM ) ;
if ( chan ! = nullptr & &
2020-06-02 23:21:50 -03:00
chan - > get_aux_switch_pos ( ) = = RC_Channel : : AuxSwitchPos : : HIGH & &
2020-04-30 11:57:44 -03:00
( checks_to_perform & ARMING_CHECK_ALL ) ) {
check_failed ( display_failure , " Disarm Switch on " ) ;
return false ;
}
return true ;
}
2020-01-07 01:04:01 -04:00
void AP_Arming : : Log_Write_Arm ( const bool forced , const AP_Arming : : Method method )
{
const struct log_Arm_Disarm pkt {
LOG_PACKET_HEADER_INIT ( LOG_ARM_DISARM_MSG ) ,
time_us : AP_HAL : : micros64 ( ) ,
arm_state : is_armed ( ) ,
arm_checks : get_enabled_checks ( ) ,
forced : forced ,
method : ( uint8_t ) method ,
} ;
AP : : logger ( ) . WriteCriticalBlock ( & pkt , sizeof ( pkt ) ) ;
2020-01-07 23:51:57 -04:00
AP : : logger ( ) . Write_Event ( LogEvent : : ARMED ) ;
2020-01-07 01:04:01 -04:00
}
2020-02-21 09:09:57 -04:00
void AP_Arming : : Log_Write_Disarm ( const AP_Arming : : Method method )
2019-05-03 08:15:46 -03:00
{
2020-01-07 01:04:01 -04:00
const struct log_Arm_Disarm pkt {
2019-05-03 08:15:46 -03:00
LOG_PACKET_HEADER_INIT ( LOG_ARM_DISARM_MSG ) ,
time_us : AP_HAL : : micros64 ( ) ,
arm_state : is_armed ( ) ,
2020-01-07 01:04:01 -04:00
arm_checks : 0 ,
forced : 0 ,
2020-02-21 09:09:57 -04:00
method : ( uint8_t ) method
2019-05-03 08:15:46 -03:00
} ;
AP : : logger ( ) . WriteCriticalBlock ( & pkt , sizeof ( pkt ) ) ;
2020-01-07 23:51:57 -04:00
AP : : logger ( ) . Write_Event ( LogEvent : : DISARMED ) ;
2019-05-03 08:15:46 -03:00
}
2019-05-06 00:33:15 -03:00
AP_Arming * AP_Arming : : _singleton = nullptr ;
/*
* Get the AP_InertialSensor singleton
*/
AP_Arming * AP_Arming : : get_singleton ( )
{
return AP_Arming : : _singleton ;
}
namespace AP {
AP_Arming & arming ( )
{
return * AP_Arming : : get_singleton ( ) ;
}
} ;