2013-10-29 10:11:48 -03:00
/// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
2015-05-29 23:12:49 -03:00
# include "Copter.h"
2013-10-29 10:11:48 -03:00
// Code to detect a crash main ArduCopter code
# ifndef CRASH_CHECK_ITERATIONS_MAX
2013-10-30 01:27:06 -03:00
# define CRASH_CHECK_ITERATIONS_MAX 20 // 2 second (ie. 10 iterations at 10hz) inverted indicates a crash
2013-10-29 10:11:48 -03:00
# endif
# ifndef CRASH_CHECK_ANGLE_DEVIATION_CD
2013-10-30 01:27:06 -03:00
# define CRASH_CHECK_ANGLE_DEVIATION_CD 2000 // 20 degrees beyond angle max is signal we are inverted
# endif
# ifndef CRASH_CHECK_ALT_CHANGE_LIMIT_CM
# define CRASH_CHECK_ALT_CHANGE_LIMIT_CM 50 // baro altitude must not change by more than 50cm
2013-10-29 10:11:48 -03:00
# endif
// crash_check - disarms motors if a crash has been detected
// crashes are detected by the vehicle being more than 20 degrees beyond it's angle limits continuously for more than 1 second
// should be called at 10hz
2015-05-29 23:12:49 -03:00
void Copter : : crash_check ( )
2013-10-29 10:11:48 -03:00
{
static uint8_t inverted_count ; // number of iterations we have been inverted
2013-10-30 01:27:06 -03:00
static int32_t baro_alt_prev ;
2013-10-29 10:11:48 -03:00
2014-04-02 12:20:20 -03:00
# if PARACHUTE == ENABLED
// check parachute
parachute_check ( ) ;
# endif
2013-10-30 01:27:06 -03:00
// return immediately if motors are not armed or pilot's throttle is above zero
2014-10-07 12:29:24 -03:00
if ( ! motors . armed ( ) | | ( ! ap . throttle_zero & & ! failsafe . radio ) ) {
2013-10-29 10:11:48 -03:00
inverted_count = 0 ;
return ;
}
// return immediately if we are not in an angle stabilize flight mode or we are flipping
2014-02-03 03:25:11 -04:00
if ( control_mode = = ACRO | | control_mode = = FLIP ) {
2013-10-29 10:11:48 -03:00
inverted_count = 0 ;
return ;
}
// check angles
2013-10-18 05:03:31 -03:00
int32_t lean_max = aparm . angle_max + CRASH_CHECK_ANGLE_DEVIATION_CD ;
2013-10-29 10:11:48 -03:00
if ( labs ( ahrs . roll_sensor ) > lean_max | | labs ( ahrs . pitch_sensor ) > lean_max ) {
inverted_count + + ;
2013-10-30 01:27:06 -03:00
// if we have just become inverted record the baro altitude
if ( inverted_count = = 1 ) {
baro_alt_prev = baro_alt ;
// exit if baro altitude change indicates we are moving (probably falling)
} else if ( labs ( baro_alt - baro_alt_prev ) > CRASH_CHECK_ALT_CHANGE_LIMIT_CM ) {
inverted_count = 0 ;
return ;
// check if inverted for 2 seconds
} else if ( inverted_count > = CRASH_CHECK_ITERATIONS_MAX ) {
2013-10-29 10:11:48 -03:00
// log an error in the dataflash
Log_Write_Error ( ERROR_SUBSYSTEM_CRASH_CHECK , ERROR_CODE_CRASH_CHECK_CRASH ) ;
// send message to gcs
2013-10-30 01:27:06 -03:00
gcs_send_text_P ( SEVERITY_HIGH , PSTR ( " Crash: Disarming " ) ) ;
2013-10-29 10:11:48 -03:00
// disarm motors
init_disarm_motors ( ) ;
}
2013-10-30 01:27:06 -03:00
} else {
// we are not inverted so reset counter
inverted_count = 0 ;
2013-10-29 10:11:48 -03:00
}
}
2014-04-02 12:20:20 -03:00
# if PARACHUTE == ENABLED
// Code to detect a crash main ArduCopter code
# ifndef PARACHUTE_CHECK_ITERATIONS_MAX
# define PARACHUTE_CHECK_ITERATIONS_MAX 10 // 1 second (ie. 10 iterations at 10hz) of loss of control triggers the parachute
# endif
# ifndef PARACHUTE_CHECK_ANGLE_DEVIATION_CD
# define PARACHUTE_CHECK_ANGLE_DEVIATION_CD 3000 // 30 degrees off from target indicates a loss of control
# endif
// parachute_check - disarms motors and triggers the parachute if serious loss of control has been detected
// vehicle is considered to have a "serious loss of control" by the vehicle being more than 30 degrees off from the target roll and pitch angles continuously for 1 second
// should be called at 10hz
2015-05-29 23:12:49 -03:00
void Copter : : parachute_check ( )
2014-04-02 12:20:20 -03:00
{
static uint8_t control_loss_count ; // number of iterations we have been out of control
static int32_t baro_alt_start ;
// exit immediately if parachute is not enabled
if ( ! parachute . enabled ( ) ) {
return ;
}
2014-04-02 21:56:30 -03:00
// call update to give parachute a chance to move servo or relay back to off position
parachute . update ( ) ;
2014-04-02 12:20:20 -03:00
// return immediately if motors are not armed or pilot's throttle is above zero
if ( ! motors . armed ( ) ) {
control_loss_count = 0 ;
return ;
}
// return immediately if we are not in an angle stabilize flight mode or we are flipping
if ( control_mode = = ACRO | | control_mode = = FLIP ) {
control_loss_count = 0 ;
return ;
}
2014-04-03 05:55:34 -03:00
// ensure we are flying
if ( ap . land_complete ) {
2014-04-02 21:56:30 -03:00
control_loss_count = 0 ;
return ;
}
2014-04-03 05:55:34 -03:00
// ensure the first control_loss event is from above the min altitude
2015-05-12 09:49:44 -03:00
if ( control_loss_count = = 0 & & parachute . alt_min ( ) ! = 0 & & ( current_loc . alt < ( int32_t ) parachute . alt_min ( ) * 100 ) ) {
2014-04-03 05:55:34 -03:00
return ;
}
2014-04-02 12:20:20 -03:00
// get desired lean angles
const Vector3f & target_angle = attitude_control . angle_ef_targets ( ) ;
// check roll and pitch angles
if ( labs ( ahrs . roll_sensor - target_angle . x ) > CRASH_CHECK_ANGLE_DEVIATION_CD | |
labs ( ahrs . pitch_sensor - target_angle . y ) > CRASH_CHECK_ANGLE_DEVIATION_CD ) {
control_loss_count + + ;
2014-04-02 21:56:30 -03:00
// don't let control_loss_count get too high
if ( control_loss_count > PARACHUTE_CHECK_ITERATIONS_MAX ) {
control_loss_count = PARACHUTE_CHECK_ITERATIONS_MAX ;
}
2014-04-03 05:55:34 -03:00
// record baro alt if we have just started losing control
2014-04-02 12:20:20 -03:00
if ( control_loss_count = = 1 ) {
baro_alt_start = baro_alt ;
// exit if baro altitude change indicates we are not falling
} else if ( baro_alt > = baro_alt_start ) {
control_loss_count = 0 ;
return ;
// To-Do: add check that the vehicle is actually falling
// check if loss of control for at least 1 second
} else if ( control_loss_count > = PARACHUTE_CHECK_ITERATIONS_MAX ) {
2014-04-02 21:56:30 -03:00
// reset control loss counter
control_loss_count = 0 ;
2014-04-03 05:55:34 -03:00
// log an error in the dataflash
Log_Write_Error ( ERROR_SUBSYSTEM_CRASH_CHECK , ERROR_CODE_CRASH_CHECK_LOSS_OF_CONTROL ) ;
2014-04-02 21:56:30 -03:00
// release parachute
2014-04-02 12:20:20 -03:00
parachute_release ( ) ;
}
} else {
// we are not inverted so reset counter
control_loss_count = 0 ;
}
}
// parachute_release - trigger the release of the parachute, disarm the motors and notify the user
2015-05-29 23:12:49 -03:00
void Copter : : parachute_release ( )
2014-04-02 12:20:20 -03:00
{
2014-04-03 05:55:34 -03:00
// send message to gcs and dataflash
2014-04-02 12:20:20 -03:00
gcs_send_text_P ( SEVERITY_HIGH , PSTR ( " Parachute: Released! " ) ) ;
2014-04-03 05:55:34 -03:00
Log_Write_Event ( DATA_PARACHUTE_RELEASED ) ;
2014-04-02 12:20:20 -03:00
// disarm motors
init_disarm_motors ( ) ;
// release parachute
parachute . release ( ) ;
}
2014-04-02 21:56:30 -03:00
// parachute_manual_release - trigger the release of the parachute, after performing some checks for pilot error
// checks if the vehicle is landed
2015-05-29 23:12:49 -03:00
void Copter : : parachute_manual_release ( )
2014-04-02 21:56:30 -03:00
{
2014-04-07 00:16:57 -03:00
// exit immediately if parachute is not enabled
if ( ! parachute . enabled ( ) ) {
return ;
}
2015-05-12 09:54:07 -03:00
// do not release if vehicle is landed
2014-04-02 21:56:30 -03:00
// do not release if we are landed or below the minimum altitude above home
2015-05-12 09:54:07 -03:00
if ( ap . land_complete ) {
// warn user of reason for failure
gcs_send_text_P ( SEVERITY_HIGH , PSTR ( " Parachute: Landed " ) ) ;
// log an error in the dataflash
Log_Write_Error ( ERROR_SUBSYSTEM_PARACHUTE , ERROR_CODE_PARACHUTE_LANDED ) ;
return ;
}
// do not release if we are landed or below the minimum altitude above home
if ( ( parachute . alt_min ( ) ! = 0 & & ( current_loc . alt < ( int32_t ) parachute . alt_min ( ) * 100 ) ) ) {
2014-04-02 21:56:30 -03:00
// warn user of reason for failure
2014-04-03 05:55:34 -03:00
gcs_send_text_P ( SEVERITY_HIGH , PSTR ( " Parachute: Too Low " ) ) ;
// log an error in the dataflash
Log_Write_Error ( ERROR_SUBSYSTEM_PARACHUTE , ERROR_CODE_PARACHUTE_TOO_LOW ) ;
2014-04-02 21:56:30 -03:00
return ;
}
// if we get this far release parachute
parachute_release ( ) ;
}
2014-04-03 05:55:34 -03:00
2014-04-06 23:18:54 -03:00
# endif // PARACHUTE == ENABLED