@ -195,13 +195,7 @@ static struct offboard_control_mode_s offboard_control_mode;
@@ -195,13 +195,7 @@ static struct offboard_control_mode_s offboard_control_mode;
static struct home_position_s _home ;
static unsigned _last_mission_instance = 0 ;
static uint64_t last_manual_input = 0 ;
static switch_pos_t last_offboard_switch = 0 ;
static switch_pos_t last_return_switch = 0 ;
static switch_pos_t last_mode_switch = 0 ;
static switch_pos_t last_acro_switch = 0 ;
static switch_pos_t last_posctl_switch = 0 ;
static switch_pos_t last_loiter_switch = 0 ;
static manual_control_setpoint_s _last_sp_man ;
struct vtol_vehicle_status_s vtol_status ;
@ -922,6 +916,7 @@ int commander_thread_main(int argc, char *argv[])
@@ -922,6 +916,7 @@ int commander_thread_main(int argc, char *argv[])
param_t _param_rc_in_off = param_find ( " COM_RC_IN_MODE " ) ;
param_t _param_eph = param_find ( " COM_HOME_H_T " ) ;
param_t _param_epv = param_find ( " COM_HOME_V_T " ) ;
param_t _param_geofence_action = param_find ( " GF_ACTION " ) ;
// const char *main_states_str[vehicle_status_s::MAIN_STATE_MAX];
// main_states_str[vehicle_status_s::MAIN_STATE_MANUAL] = "MANUAL";
@ -1260,6 +1255,8 @@ int commander_thread_main(int argc, char *argv[])
@@ -1260,6 +1255,8 @@ int commander_thread_main(int argc, char *argv[])
float rc_loss_timeout = 0.5 ;
int32_t datalink_regain_timeout = 0 ;
uint8_t geofence_action = 0 ;
/* Thresholds for engine failure detection */
int32_t ef_throttle_thres = 1.0f ;
int32_t ef_current2throttle_thres = 0.0f ;
@ -1346,6 +1343,7 @@ int commander_thread_main(int argc, char *argv[])
@@ -1346,6 +1343,7 @@ int commander_thread_main(int argc, char *argv[])
param_get ( _param_ef_throttle_thres , & ef_throttle_thres ) ;
param_get ( _param_ef_current2throttle_thres , & ef_current2throttle_thres ) ;
param_get ( _param_ef_time_thres , & ef_time_thres ) ;
param_get ( _param_geofence_action , & geofence_action ) ;
/* Autostart id */
param_get ( _param_autostart_id , & autostart_id ) ;
@ -1835,24 +1833,106 @@ int commander_thread_main(int argc, char *argv[])
@@ -1835,24 +1833,106 @@ int commander_thread_main(int argc, char *argv[])
orb_copy ( ORB_ID ( geofence_result ) , geofence_result_sub , & geofence_result ) ;
}
/* Check for geofence violation */
if ( armed . armed & & ( geofence_result . geofence_violated | | mission_result . flight_termination ) ) {
//XXX: make this configurable to select different actions (e.g. navigation modes)
/* this will only trigger if geofence is activated via param and a geofence file is present, also there is a circuit breaker to disable the actual flight termination in the px4io driver */
// Geofence actions
if ( armed . armed & & ( geofence_result . geofence_action ! = geofence_result_s : : GF_ACTION_NONE ) ) {
static bool geofence_loiter_on = false ;
static bool geofence_rtl_on = false ;
static uint8_t geofence_main_state_before_violation = vehicle_status_s : : MAIN_STATE_MAX ;
// check for geofence violation
if ( geofence_result . geofence_violated ) {
static hrt_abstime last_geofence_violation = 0 ;
const hrt_abstime geofence_violation_action_interval = 10000000 ; // 10 seconds
if ( hrt_elapsed_time ( & last_geofence_violation ) > geofence_violation_action_interval ) {
last_geofence_violation = hrt_absolute_time ( ) ;
switch ( geofence_result . geofence_action ) {
case ( geofence_result_s : : GF_ACTION_NONE ) : {
// do nothing
break ;
}
case ( geofence_result_s : : GF_ACTION_WARN ) : {
// do nothing, mavlink critical messages are sent by navigator
break ;
}
case ( geofence_result_s : : GF_ACTION_LOITER ) : {
if ( TRANSITION_CHANGED = = main_state_transition ( & status , vehicle_status_s : : MAIN_STATE_AUTO_LOITER ) ) {
geofence_loiter_on = true ;
}
break ;
}
case ( geofence_result_s : : GF_ACTION_RTL ) : {
if ( TRANSITION_CHANGED = = main_state_transition ( & status , vehicle_status_s : : MAIN_STATE_AUTO_RTL ) ) {
geofence_rtl_on = true ;
}
break ;
}
case ( geofence_result_s : : GF_ACTION_TERMINATE ) : {
warnx ( " Flight termination because of geofence " ) ;
mavlink_log_critical ( mavlink_fd , " Geofence violation: flight termination " ) ;
armed . force_failsafe = true ;
status_changed = true ;
break ;
}
}
}
}
// reset if no longer in LOITER or if manually switched to LOITER
geofence_loiter_on = geofence_loiter_on
& & ( status . main_state = = vehicle_status_s : : MAIN_STATE_AUTO_LOITER )
& & ( sp_man . loiter_switch = = manual_control_setpoint_s : : SWITCH_POS_OFF ) ;
// reset if no longer in RTL or if manually switched to RTL
geofence_rtl_on = geofence_rtl_on
& & ( status . main_state = = vehicle_status_s : : MAIN_STATE_AUTO_RTL )
& & ( sp_man . return_switch = = manual_control_setpoint_s : : SWITCH_POS_OFF ) ;
if ( ! geofence_loiter_on & & ! geofence_rtl_on ) {
// store the last good main_state when not in a geofence triggered action (LOITER or RTL)
geofence_main_state_before_violation = status . main_state ;
}
// revert geofence failsafe transition if sticks are moved and we were previously in MANUAL or ASSIST
if ( ( geofence_loiter_on | | geofence_rtl_on ) & &
( geofence_main_state_before_violation = = vehicle_status_s : : MAIN_STATE_MANUAL | |
geofence_main_state_before_violation = = vehicle_status_s : : MAIN_STATE_ALTCTL | |
geofence_main_state_before_violation = = vehicle_status_s : : MAIN_STATE_POSCTL | |
geofence_main_state_before_violation = = vehicle_status_s : : MAIN_STATE_ACRO | |
geofence_main_state_before_violation = = vehicle_status_s : : MAIN_STATE_STAB ) ) {
// transition to previous state if sticks are increased
const float min_stick_change = 0.2 ;
if ( ( _last_sp_man . timestamp ! = sp_man . timestamp ) & &
( ( fabsf ( sp_man . x ) - fabsf ( _last_sp_man . x ) > min_stick_change ) | |
( fabsf ( sp_man . y ) - fabsf ( _last_sp_man . y ) > min_stick_change ) | |
( fabsf ( sp_man . z ) - fabsf ( _last_sp_man . z ) > min_stick_change ) | |
( fabsf ( sp_man . r ) - fabsf ( _last_sp_man . r ) > min_stick_change ) ) ) {
main_state_transition ( & status , geofence_main_state_before_violation ) ;
}
}
}
/* Check for mission flight termination */
if ( armed . armed & & mission_result . flight_termination ) {
armed . force_failsafe = true ;
status_changed = true ;
static bool flight_termination_printed = false ;
if ( ! flight_termination_printed ) {
warnx ( " Flight termination because of navigator request or geofence " ) ;
mavlink_log_critical ( mavlink_fd , " Geofence violation: flight termination " ) ;
warnx ( " Flight termination because of navigator request " ) ;
flight_termination_printed = true ;
}
if ( counter % ( 1000000 / COMMANDER_MONITORING_INTERVAL ) = = 0 ) {
mavlink_log_critical ( mavlink_fd , " Flight termination active " ) ;
}
} // no reset is done here on purpose, on geofence violation we want to stay in flighttermination
}
/* Only evaluate mission state if home is set,
* this prevents false positives for the mission
@ -1937,10 +2017,15 @@ int commander_thread_main(int argc, char *argv[])
@@ -1937,10 +2017,15 @@ int commander_thread_main(int argc, char *argv[])
* for being in manual mode only applies to manual arming actions .
* the system can be armed in auto if armed via the GCS .
*/
if ( ( status . main_state ! = vehicle_status_s : : MAIN_STATE_MANUAL ) & &
( status . main_state ! = vehicle_status_s : : MAIN_STATE_STAB ) ) {
print_reject_arm ( " NOT ARMING: Switch to MANUAL mode first. " ) ;
} else if ( ! status . condition_home_position_valid & &
geofence_action = = geofence_result_s : : GF_ACTION_RTL ) {
print_reject_arm ( " NOT ARMING: Geofence RTL requires valid home " ) ;
} else if ( status . arming_state = = vehicle_status_s : : ARMING_STATE_STANDBY ) {
arming_ret = arming_state_transition ( & status , & safety , vehicle_status_s : : ARMING_STATE_ARMED , & armed , true /* fRunPreArmChecks */ ,
mavlink_fd ) ;
@ -2107,7 +2192,7 @@ int commander_thread_main(int argc, char *argv[])
@@ -2107,7 +2192,7 @@ int commander_thread_main(int argc, char *argv[])
/* Check for failure combinations which lead to flight termination */
if ( armed . armed ) {
/* At this point the data link and the gps system have been checked
* If we are not in a manual ( RC stick controlled mode )
* If we are not in a manual ( RC stick controlled mode )
* and both failed we want to terminate the flight */
if ( status . main_state ! = vehicle_status_s : : MAIN_STATE_MANUAL & &
status . main_state ! = vehicle_status_s : : MAIN_STATE_ACRO & &
@ -2422,31 +2507,32 @@ set_main_state_rc(struct vehicle_status_s *status_local, struct manual_control_s
@@ -2422,31 +2507,32 @@ set_main_state_rc(struct vehicle_status_s *status_local, struct manual_control_s
/* set main state according to RC switches */
transition_result_t res = TRANSITION_DENIED ;
/* if offboard is set all ready by a mavlink command, abort */
/* if offboard is set already by a mavlink command, abort */
if ( status . offboard_control_set_by_command ) {
return main_state_transition ( status_local , vehicle_status_s : : MAIN_STATE_OFFBOARD ) ;
}
/* manual setpoint has not updated, do not re-evaluate it */
if ( ( last_manual_input = = sp_man - > timestamp ) | |
( ( last_offboard_switch = = sp_man - > offboard_switch ) & &
( last_return_switch = = sp_man - > return_switch ) & &
( last_mode_switch = = sp_man - > mode_switch ) & &
( last_acro_switch = = sp_man - > acro_switch ) & &
( last_posctl_switch = = sp_man - > posctl_switch ) & &
( last_loiter_switch = = sp_man - > loiter_switch ) ) ) {
if ( ( _last_sp_man . timestamp = = sp_man - > timestamp ) | |
( ( _last_sp_man . offboard_switch = = sp_man - > offboard_switch ) & &
( _last_sp_man . return_switch = = sp_man - > return_switch ) & &
( _last_sp_man . mode_switch = = sp_man - > mode_switch ) & &
( _last_sp_man . acro_switch = = sp_man - > acro_switch ) & &
( _last_sp_man . posctl_switch = = sp_man - > posctl_switch ) & &
( _last_sp_man . loiter_switch = = sp_man - > loiter_switch ) ) ) {
// update these fields for the geofence system
_last_sp_man . timestamp = sp_man - > timestamp ;
_last_sp_man . x = sp_man - > x ;
_last_sp_man . y = sp_man - > y ;
_last_sp_man . z = sp_man - > z ;
_last_sp_man . r = sp_man - > r ;
/* no timestamp change or no switch change -> nothing changed */
return TRANSITION_NOT_CHANGED ;
}
last_manual_input = sp_man - > timestamp ;
last_offboard_switch = sp_man - > offboard_switch ;
last_return_switch = sp_man - > return_switch ;
last_mode_switch = sp_man - > mode_switch ;
last_acro_switch = sp_man - > acro_switch ;
last_posctl_switch = sp_man - > posctl_switch ;
last_loiter_switch = sp_man - > loiter_switch ;
_last_sp_man = * sp_man ;
/* offboard switch overrides main switch */
if ( sp_man - > offboard_switch = = manual_control_setpoint_s : : SWITCH_POS_ON ) {