2012-07-14 23:26:17 -03:00
// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
/// @file ap_limits.cpp
/// @brief Imposes limits on location (geofence), altitude and other parameters.
/// Each breach will trigger an action or set of actions to recover. Adapted from geofence.
/// @author Andrew Tridgell
/// Andreas Antonopoulos
# include <AP_Limits.h>
# include <AP_Limit_Module.h>
const AP_Param : : GroupInfo AP_Limits : : var_info [ ] PROGMEM = {
// @Param: ENABLED
// @DisplayName: Enable Limits Library
// @Description: Setting this to Enabled(1) will enable the limits system
// @Values: 0:Disabled,1:Enabled
// @User: Standard
2012-08-06 22:02:14 -03:00
AP_GROUPINFO ( " ENABLED " , 0 , AP_Limits , _enabled , 0 ) ,
2012-07-14 23:26:17 -03:00
// @Param: REQUIRED
// @DisplayName: Limits Library Required
// @Description: Setting this to 1 will enable the limits pre-arm checklist
// @Values: 0:Disabled,1:Enabled
// @User: Standard
2012-08-06 22:02:14 -03:00
AP_GROUPINFO ( " REQUIRED " , 1 , AP_Limits , _required , 0 ) ,
2012-07-14 23:26:17 -03:00
// @Param: DEBUG
// @DisplayName: Enable Limits Debug
// @Description: Setting this to 1 will turn on debugging messages on the console and via MAVLink STATUSTEXT messages
// @Values: 0:Disabled,1:Enabled
// @User: Standard
2012-08-06 22:02:14 -03:00
AP_GROUPINFO ( " DEBUG " , 2 , AP_Limits , _debug , 0 ) ,
2012-07-14 23:26:17 -03:00
// @Param: SAFETIME
// @DisplayName: Limits Safetime
// @Description: Automatic return of controls to pilot. Set to 0 to disable (full RTL) or a number of seconds after complete recovery to return the controls to the pilot in STABILIZE
// @Values: 0:Disabled,1-255:Seconds before returning control
// @User: Standard
2012-08-06 22:02:14 -03:00
AP_GROUPINFO ( " SAFETIME " , 3 , AP_Limits , _safetime , 0 ) ,
2012-07-14 23:26:17 -03:00
// @Param: CHANNEL
// @DisplayName: Limits Channel
// @Description: Channel for Limits on/off control. If channel exceeds LIMITS_ENABLE_PWM, it turns limits on, and vice-versa.
// @Range: 1-8
// @User: Standard
2012-08-06 22:02:14 -03:00
AP_GROUPINFO ( " CHANNEL " , 4 , AP_Limits , _channel , 0 ) ,
2012-07-14 23:26:17 -03:00
2012-07-31 22:39:58 -03:00
// @Param: RECMODE
// @DisplayName: Limits Recovery Mode
// @Description: Select how Limits should "recover". Set to 0 for RTL-like mode, where the vehicle navigates back to home until it is "safe". Set to 1, for bounce-mode, where the vehicle will hold position when it hits a limit. RTL mode is better for large fenced areas, Bounce mode for smaller spaces. Note: RTL mode will cause the vehicle to yaw 180 degrees (turn around) to navigate towards home when it hits a limit.
// @Values: 0:RTL mode, 1: Bounce mode
// @User: Standard
2012-08-06 22:02:14 -03:00
AP_GROUPINFO ( " RECMODE " , 5 , AP_Limits , _recmode , 0 ) ,
2012-07-31 22:39:58 -03:00
AP_GROUPEND
2012-07-14 23:26:17 -03:00
} ;
AP_Limits : : AP_Limits ( ) {
last_trigger = 0 ;
last_action = 0 ;
last_recovery = 0 ;
last_clear = 0 ;
last_status_update = 0 ;
breach_count = 0 ;
mods_enabled = 0 ;
mods_required = 0 ;
mods_triggered = 0 ;
mods_recovering = 0 ;
old_mode_switch = 0 ;
_channel = 0 ;
_state = LIMITS_INIT ;
}
void AP_Limits : : modules ( AP_Limit_Module * m )
{
_modules_head = m ;
}
bool AP_Limits : : init ( ) {
AP_Limit_Module * m = modules_first ( ) ;
while ( m ) {
m - > init ( ) ;
m = modules_next ( ) ;
}
return true ;
}
bool AP_Limits : : enabled ( ) {
return _enabled ;
}
bool AP_Limits : : debug ( ) {
return _debug ;
}
AP_Limit_Module * AP_Limits : : modules_first ( ) {
_modules_current = _modules_head ; // reset current to head of list
return _modules_head ;
}
AP_Limit_Module * AP_Limits : : modules_current ( ) {
return _modules_current ;
}
AP_Limit_Module * AP_Limits : : modules_next ( ) {
if ( _modules_current ) {
_modules_current = _modules_current - > next ( ) ; // move to "next" (which might be NULL)
}
return _modules_current ;
}
uint8_t AP_Limits : : modules_count ( ) {
_modules_count = 0 ;
AP_Limit_Module * m = _modules_head ;
while ( m ) {
_modules_count + + ;
m = m - > next ( ) ;
}
return _modules_count ;
}
AP_Limit_Module * AP_Limits : : modules_last ( ) {
AP_Limit_Module * m = _modules_head ;
while ( m & & m - > next ( ) ) {
m = m - > next ( ) ;
}
return m ;
}
void AP_Limits : : modules_add ( AP_Limit_Module * m ) {
if ( _modules_head ) { // if there is a module linked
modules_last ( ) - > link ( m ) ; // add to the end of the list
}
else {
_modules_head = m ; // otherwise, this will be the "head"
}
}
bool AP_Limits : : required ( ) {
return _required ;
}
bool AP_Limits : : check_all ( ) {
return ( bool ) check_triggered ( false ) ; // required=false, means "all"
}
bool AP_Limits : : check_required ( ) {
return ( bool ) check_triggered ( true ) ; // required=true, means "only required modules"
}
bool AP_Limits : : check_triggered ( bool only_required ) {
// check all enabled modules for triggered limits
AP_Limit_Module * mod = _modules_head ;
// reset bit fields
mods_triggered = 0 ;
mods_enabled = 0 ;
mods_required = 0 ;
while ( mod ) {
unsigned module_id = mod - > get_module_id ( ) ;
// We check enabled, triggered and required across all modules
// We set all the bit-fields each time we check, keeping them up to date
if ( mod - > enabled ( ) ) {
mods_enabled | = module_id ;
if ( mod - > required ( ) ) mods_required | = module_id ;
if ( mod - > triggered ( ) ) mods_triggered | = module_id ;
}
mod = mod - > next ( ) ;
}
if ( only_required ) {
return ( bool ) ( mods_required & mods_triggered ) ; // just modules that are both required AND triggered. (binary AND)
}
else return ( bool ) ( mods_triggered ) ;
}
AP_Int8 AP_Limits : : state ( ) {
return _state ;
}
AP_Int8 AP_Limits : : safetime ( ) {
return _safetime ;
}
void AP_Limits : : set_state ( int s ) {
_state = ( int ) s ;
}
AP_Int8 AP_Limits : : channel ( ) {
return _channel ;
}
2012-07-31 22:39:58 -03:00
AP_Int8 AP_Limits : : recmode ( ) {
return _recmode ;
}