2012-08-04 15:12:36 -07:00
/****************************************************************************
*
2014-04-27 02:26:09 +02:00
* Copyright ( C ) 2013 - 2014 PX4 Development Team . All rights reserved .
2012-08-04 15:12:36 -07:00
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
*
* 1. Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* 2. Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in
* the documentation and / or other materials provided with the
* distribution .
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* " AS IS " AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT
* LIMITED TO , THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED . IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT , INDIRECT ,
* INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING ,
* BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS
* OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT
* LIABILITY , OR TORT ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/**
2013-07-20 13:47:51 +02:00
* @ file commander . cpp
2014-05-27 21:56:32 +02:00
* Main fail - safe handling .
2012-10-23 13:15:36 +02:00
*
2014-05-27 21:56:32 +02:00
* @ author Petri Tanskanen < petri . tanskanen @ inf . ethz . ch >
* @ author Lorenz Meier < lm @ inf . ethz . ch >
* @ author Thomas Gubler < thomasgubler @ student . ethz . ch >
* @ author Julian Oes < julian @ oes . ch >
* @ author Anton Babushkin < anton . babushkin @ me . com >
2012-08-04 15:12:36 -07:00
*/
# include <nuttx/config.h>
# include <pthread.h>
# include <stdio.h>
# include <stdlib.h>
# include <stdbool.h>
# include <string.h>
# include <unistd.h>
# include <fcntl.h>
# include <errno.h>
2013-09-05 13:24:21 +02:00
# include <systemlib/err.h>
2014-05-25 20:34:32 +02:00
# include <systemlib/circuit_breaker.h>
2012-08-04 15:12:36 -07:00
# include <debug.h>
# include <sys/prctl.h>
2013-08-17 15:47:42 +02:00
# include <sys/stat.h>
2012-08-04 15:12:36 -07:00
# include <string.h>
# include <math.h>
# include <poll.h>
2014-05-06 11:22:18 +02:00
# include <float.h>
2013-03-11 10:39:57 -07:00
2012-08-04 15:12:36 -07:00
# include <uORB/uORB.h>
# include <uORB/topics/sensor_combined.h>
2013-01-01 13:30:24 +01:00
# include <uORB/topics/battery_status.h>
2012-09-21 12:55:41 +02:00
# include <uORB/topics/manual_control_setpoint.h>
# include <uORB/topics/offboard_control_setpoint.h>
2013-01-19 14:46:26 +01:00
# include <uORB/topics/home_position.h>
2012-12-13 10:23:02 +01:00
# include <uORB/topics/vehicle_global_position.h>
# include <uORB/topics/vehicle_local_position.h>
2014-04-03 20:23:34 +04:00
# include <uORB/topics/position_setpoint_triplet.h>
2013-01-19 14:46:26 +01:00
# include <uORB/topics/vehicle_gps_position.h>
2012-08-04 15:12:36 -07:00
# include <uORB/topics/vehicle_command.h>
2012-08-24 00:01:23 +02:00
# include <uORB/topics/subsystem_info.h>
2012-09-05 11:37:17 +02:00
# include <uORB/topics/actuator_controls.h>
2015-01-25 13:39:34 +01:00
# include <uORB/topics/actuator_controls_0.h>
# include <uORB/topics/actuator_controls_1.h>
# include <uORB/topics/actuator_controls_2.h>
# include <uORB/topics/actuator_controls_3.h>
2013-07-15 22:15:15 +02:00
# include <uORB/topics/actuator_armed.h>
2012-12-13 10:23:02 +01:00
# include <uORB/topics/parameter_update.h>
2013-02-24 21:57:38 +01:00
# include <uORB/topics/differential_pressure.h>
2013-07-15 22:15:15 +02:00
# include <uORB/topics/safety.h>
2014-05-25 08:22:54 +02:00
# include <uORB/topics/system_power.h>
2014-06-13 23:40:48 +02:00
# include <uORB/topics/mission.h>
2014-05-27 21:56:32 +02:00
# include <uORB/topics/mission_result.h>
2014-12-19 22:26:31 +00:00
# include <uORB/topics/geofence_result.h>
2014-06-16 17:34:21 +02:00
# include <uORB/topics/telemetry_status.h>
2014-12-02 10:47:07 +01:00
# include <uORB/topics/vtol_vehicle_status.h>
2015-01-06 12:25:18 +01:00
# include <uORB/topics/vehicle_land_detected.h>
2012-09-25 10:31:19 +02:00
2013-03-11 10:39:57 -07:00
# include <drivers/drv_led.h>
# include <drivers/drv_hrt.h>
# include <drivers/drv_tone_alarm.h>
# include <mavlink/mavlink_log.h>
2012-08-20 23:52:13 +02:00
# include <systemlib/param/param.h>
2012-08-04 15:12:36 -07:00
# include <systemlib/systemlib.h>
2012-09-11 23:35:01 +02:00
# include <systemlib/err.h>
2013-03-11 10:39:57 -07:00
# include <systemlib/cpuload.h>
2013-08-25 16:33:14 +02:00
# include <systemlib/rc_check.h>
2014-05-05 15:37:53 +02:00
# include <geo/geo.h>
2014-05-27 21:56:32 +02:00
# include <systemlib/state_table.h>
2014-06-13 23:40:48 +02:00
# include <dataman/dataman.h>
2013-03-11 10:39:57 -07:00
2013-08-14 10:59:22 +02:00
# include "px4_custom_mode.h"
2013-06-25 16:30:35 +02:00
# include "commander_helper.h"
2013-03-11 10:39:57 -07:00
# include "state_machine_helper.h"
2012-10-21 15:36:29 +02:00
# include "calibration_routines.h"
2013-04-25 23:59:46 +04:00
# include "accelerometer_calibration.h"
2013-06-25 16:30:35 +02:00
# include "gyro_calibration.h"
# include "mag_calibration.h"
# include "baro_calibration.h"
# include "rc_calibration.h"
# include "airspeed_calibration.h"
2012-09-11 23:35:01 +02:00
2013-07-20 13:47:51 +02:00
/* oddly, ERROR is not defined for c++ */
# ifdef ERROR
# undef ERROR
# endif
static const int ERROR = - 1 ;
2013-03-11 10:39:57 -07:00
2012-08-04 15:12:36 -07:00
extern struct system_load_s system_load ;
/* Decouple update interval and hysteris counters, all depends on intervals */
# define COMMANDER_MONITORING_INTERVAL 50000
# define COMMANDER_MONITORING_LOOPSPERMSEC (1 / (COMMANDER_MONITORING_INTERVAL / 1000.0f))
2013-11-05 19:56:33 +01:00
# define MAVLINK_OPEN_INTERVAL 50000
2014-04-03 20:23:34 +04:00
# define STICK_ON_OFF_LIMIT 0.9f
2012-08-04 15:12:36 -07:00
# define STICK_ON_OFF_HYSTERESIS_TIME_MS 1000
# define STICK_ON_OFF_COUNTER_LIMIT (STICK_ON_OFF_HYSTERESIS_TIME_MS*COMMANDER_MONITORING_LOOPSPERMSEC)
2014-07-27 23:43:39 +02:00
# define POSITION_TIMEOUT (2 * 1000 * 1000) /**< consider the local or global position estimate invalid after 600ms */
2014-05-07 08:42:57 +02:00
# define FAILSAFE_DEFAULT_TIMEOUT (3 * 1000 * 1000) /**< hysteresis time - the failsafe will trigger after 3 seconds in this state */
2014-05-16 12:12:43 +02:00
# define OFFBOARD_TIMEOUT 500000
2014-05-07 08:42:57 +02:00
# define DIFFPRESS_TIMEOUT 2000000
2013-03-11 10:39:57 -07:00
2013-07-31 20:58:27 +04:00
# define PRINT_INTERVAL 5000000
# define PRINT_MODE_REJECT_INTERVAL 2000000
enum MAV_MODE_FLAG {
MAV_MODE_FLAG_CUSTOM_MODE_ENABLED = 1 , /* 0b00000001 Reserved for future use. | */
MAV_MODE_FLAG_TEST_ENABLED = 2 , /* 0b00000010 system has a test mode enabled. This flag is intended for temporary system tests and should not be used for stable implementations. | */
MAV_MODE_FLAG_AUTO_ENABLED = 4 , /* 0b00000100 autonomous mode enabled, system finds its own goal positions. Guided flag can be set or not, depends on the actual implementation. | */
MAV_MODE_FLAG_GUIDED_ENABLED = 8 , /* 0b00001000 guided mode enabled, system flies MISSIONs / mission items. | */
MAV_MODE_FLAG_STABILIZE_ENABLED = 16 , /* 0b00010000 system stabilizes electronically its attitude (and optionally position). It needs however further control inputs to move around. | */
MAV_MODE_FLAG_HIL_ENABLED = 32 , /* 0b00100000 hardware in the loop simulation. All motors / actuators are blocked, but internal software is full operational. | */
MAV_MODE_FLAG_MANUAL_INPUT_ENABLED = 64 , /* 0b01000000 remote control input is enabled. | */
MAV_MODE_FLAG_SAFETY_ARMED = 128 , /* 0b10000000 MAV safety set to armed. Motors are enabled / running / can start. Ready to fly. | */
MAV_MODE_FLAG_ENUM_END = 129 , /* | */
} ;
2013-08-07 20:21:49 +02:00
2013-07-16 09:24:21 +02:00
/* Mavlink file descriptors */
2014-03-16 21:38:23 -07:00
static int mavlink_fd = 0 ;
2013-02-16 13:40:09 -08:00
2014-12-02 10:47:07 +01:00
/* Syste autostart ID */
static int autostart_id ;
2013-02-16 13:40:09 -08:00
/* flags */
2012-08-04 15:12:36 -07:00
static bool commander_initialized = false ;
2013-09-08 20:05:15 +02:00
static volatile bool thread_should_exit = false ; /**< daemon exit flag */
static volatile bool thread_running = false ; /**< daemon status flag */
2013-02-16 13:40:09 -08:00
static int daemon_task ; /**< Handle of daemon task / thread */
2013-07-31 20:58:27 +04:00
static unsigned int leds_counter ;
/* To remember when last notification was sent */
static uint64_t last_print_mode_reject_time = 0 ;
2013-08-17 15:47:42 +02:00
/* if connected via USB */
static bool on_usb_power = false ;
2013-07-31 20:58:27 +04:00
2013-08-30 10:11:24 +02:00
static float takeoff_alt = 5.0f ;
2014-02-13 16:08:49 +01:00
static int parachute_enabled = 0 ;
2014-07-29 17:50:52 +02:00
static float eph_threshold = 5.0f ;
static float epv_threshold = 10.0f ;
2012-09-21 12:55:41 +02:00
2014-01-16 10:58:05 +01:00
static struct vehicle_status_s status ;
static struct actuator_armed_s armed ;
static struct safety_s safety ;
2014-01-30 17:23:10 +01:00
static struct vehicle_control_mode_s control_mode ;
2014-02-17 16:50:00 +04:00
static struct offboard_control_setpoint_s sp_offboard ;
2014-01-16 10:58:05 +01:00
2013-03-25 14:53:54 -07:00
/* tasks waiting for low prio thread */
2013-07-31 20:58:27 +04:00
typedef enum {
2013-03-25 14:53:54 -07:00
LOW_PRIO_TASK_NONE = 0 ,
LOW_PRIO_TASK_PARAM_SAVE ,
LOW_PRIO_TASK_PARAM_LOAD ,
LOW_PRIO_TASK_GYRO_CALIBRATION ,
LOW_PRIO_TASK_MAG_CALIBRATION ,
LOW_PRIO_TASK_ALTITUDE_CALIBRATION ,
LOW_PRIO_TASK_RC_CALIBRATION ,
LOW_PRIO_TASK_ACCEL_CALIBRATION ,
LOW_PRIO_TASK_AIRSPEED_CALIBRATION
2013-07-31 20:58:27 +04:00
} low_prio_task_t ;
2013-03-25 14:53:54 -07:00
2013-07-31 20:58:27 +04:00
static low_prio_task_t low_prio_task = LOW_PRIO_TASK_NONE ;
2012-08-04 15:12:36 -07:00
2013-07-16 09:24:21 +02:00
/**
2013-07-16 09:35:31 +02:00
* The daemon app only briefly exists to start
* the background job . The stack size assigned in the
* Makefile does only apply to this management task .
*
* The actual stack size should be set in the call
* to task_create ( ) .
2013-07-20 13:47:51 +02:00
*
* @ ingroup apps
2013-07-16 09:24:21 +02:00
*/
2013-07-20 13:47:51 +02:00
extern " C " __EXPORT int commander_main ( int argc , char * argv [ ] ) ;
2012-08-04 15:12:36 -07:00
2012-08-20 23:52:13 +02:00
/**
2013-07-16 09:35:31 +02:00
* Print the correct usage .
2012-08-20 23:52:13 +02:00
*/
2013-07-16 09:35:31 +02:00
void usage ( const char * reason ) ;
2012-08-20 23:52:13 +02:00
2013-07-16 09:24:21 +02:00
/**
* React to commands that are sent e . g . from the mavlink module .
*/
2014-10-23 16:17:20 +02:00
bool handle_command ( struct vehicle_status_s * status , const struct safety_s * safety , struct vehicle_command_s * cmd ,
struct actuator_armed_s * armed , struct home_position_s * home , struct vehicle_global_position_s * global_pos ,
orb_advert_t * home_pub ) ;
2012-08-20 23:52:13 +02:00
/**
2013-07-16 09:35:31 +02:00
* Mainloop of commander .
2012-08-20 23:52:13 +02:00
*/
2013-07-16 09:35:31 +02:00
int commander_thread_main ( int argc , char * argv [ ] ) ;
2013-11-01 09:05:28 +01:00
void control_status_leds ( vehicle_status_s * status , const actuator_armed_s * actuator_armed , bool changed ) ;
2013-08-27 23:08:00 +02:00
2013-08-17 12:37:41 +02:00
void check_valid ( hrt_abstime timestamp , hrt_abstime timeout , bool valid_in , bool * valid_out , bool * changed ) ;
2013-07-31 20:58:27 +04:00
2014-04-03 20:23:34 +04:00
transition_result_t set_main_state_rc ( struct vehicle_status_s * status , struct manual_control_setpoint_s * sp_man ) ;
2013-07-28 23:12:16 +04:00
2014-01-27 20:49:17 +01:00
void set_control_mode ( ) ;
2014-02-01 13:21:51 +01:00
void print_reject_mode ( struct vehicle_status_s * current_status , const char * msg ) ;
2013-08-27 23:08:00 +02:00
2013-08-16 09:23:39 +02:00
void print_reject_arm ( const char * msg ) ;
2013-07-31 20:58:27 +04:00
2013-08-17 15:47:42 +02:00
void print_status ( ) ;
2014-10-23 16:17:20 +02:00
transition_result_t check_navigation_state_machine ( struct vehicle_status_s * status ,
struct vehicle_control_mode_s * control_mode , struct vehicle_local_position_s * local_pos ) ;
2013-07-28 23:12:16 +04:00
2014-05-11 13:36:51 +02:00
transition_result_t arm_disarm ( bool arm , const int mavlink_fd , const char * armedBy ) ;
2014-03-16 21:38:23 -07:00
2015-01-16 16:43:11 +01:00
/**
* @ brief This function initializes the home position of the vehicle . This happens first time we get a good GPS fix and each
* time the vehicle is armed with a good GPS fix .
* */
2015-01-16 16:46:16 +01:00
static void commander_set_home_position ( orb_advert_t & homePub , home_position_s & home ,
const vehicle_local_position_s & localPosition , const vehicle_global_position_s & globalPosition ) ;
2015-01-16 16:43:11 +01:00
2013-07-16 09:35:31 +02:00
/**
* Loop that runs at a lower rate and priority for calibration and parameter tasks .
*/
void * commander_low_prio_loop ( void * arg ) ;
2013-08-27 23:08:00 +02:00
void answer_command ( struct vehicle_command_s & cmd , enum VEHICLE_CMD_RESULT result ) ;
2013-07-16 09:35:31 +02:00
int commander_main ( int argc , char * argv [ ] )
{
2014-05-11 13:36:51 +02:00
if ( argc < 1 ) {
2013-07-16 09:35:31 +02:00
usage ( " missing command " ) ;
2014-05-11 13:36:51 +02:00
}
2013-07-16 09:35:31 +02:00
if ( ! strcmp ( argv [ 1 ] , " start " ) ) {
if ( thread_running ) {
2013-09-08 20:05:15 +02:00
warnx ( " commander already running " ) ;
2013-07-16 09:35:31 +02:00
/* this is not an error */
exit ( 0 ) ;
}
thread_should_exit = false ;
daemon_task = task_spawn_cmd ( " commander " ,
2013-07-28 23:12:16 +04:00
SCHED_DEFAULT ,
SCHED_PRIORITY_MAX - 40 ,
2014-10-29 17:55:53 +01:00
3200 ,
2013-07-28 23:12:16 +04:00
commander_thread_main ,
2014-12-22 17:09:43 -05:00
( argv ) ? ( char * const * ) & argv [ 2 ] : ( char * const * ) NULL ) ;
2013-09-08 20:05:15 +02:00
while ( ! thread_running ) {
usleep ( 200 ) ;
}
2013-07-16 09:35:31 +02:00
exit ( 0 ) ;
}
2012-08-04 15:12:36 -07:00
2013-07-16 09:35:31 +02:00
if ( ! strcmp ( argv [ 1 ] , " stop " ) ) {
2013-09-08 20:05:15 +02:00
2014-05-11 13:36:51 +02:00
if ( ! thread_running ) {
2013-09-08 20:05:15 +02:00
errx ( 0 , " commander already stopped " ) ;
2014-05-11 13:36:51 +02:00
}
2013-09-08 20:05:15 +02:00
2013-07-16 09:35:31 +02:00
thread_should_exit = true ;
2013-09-08 20:05:15 +02:00
while ( thread_running ) {
usleep ( 200000 ) ;
warnx ( " . " ) ;
}
warnx ( " terminated. " ) ;
2013-07-16 09:35:31 +02:00
exit ( 0 ) ;
}
2013-03-25 14:53:54 -07:00
2014-07-11 14:51:13 +02:00
/* commands needing the app to run below */
if ( ! thread_running ) {
warnx ( " \t commander not started " ) ;
exit ( 1 ) ;
}
2013-07-16 09:35:31 +02:00
2014-07-11 14:51:13 +02:00
if ( ! strcmp ( argv [ 1 ] , " status " ) ) {
print_status ( ) ;
exit ( 0 ) ;
}
2013-07-16 09:35:31 +02:00
2014-07-11 14:51:13 +02:00
if ( ! strcmp ( argv [ 1 ] , " check " ) ) {
2014-07-11 15:10:11 +02:00
int mavlink_fd_local = open ( MAVLINK_LOG_DEVICE , 0 ) ;
int checkres = prearm_check ( & status , mavlink_fd_local ) ;
close ( mavlink_fd_local ) ;
2014-07-11 14:51:13 +02:00
warnx ( " FINAL RESULT: %s " , ( checkres = = 0 ) ? " OK " : " FAILED " ) ;
2013-07-16 09:35:31 +02:00
exit ( 0 ) ;
}
2014-01-16 10:58:05 +01:00
if ( ! strcmp ( argv [ 1 ] , " arm " ) ) {
2014-11-22 15:08:54 +01:00
int mavlink_fd_local = open ( MAVLINK_LOG_DEVICE , 0 ) ;
arm_disarm ( true , mavlink_fd_local , " command line " ) ;
close ( mavlink_fd_local ) ;
2014-01-16 10:58:05 +01:00
exit ( 0 ) ;
}
2014-07-11 14:55:46 +02:00
if ( ! strcmp ( argv [ 1 ] , " disarm " ) ) {
2014-11-22 15:08:54 +01:00
int mavlink_fd_local = open ( MAVLINK_LOG_DEVICE , 0 ) ;
arm_disarm ( false , mavlink_fd_local , " command line " ) ;
close ( mavlink_fd_local ) ;
2014-01-16 10:58:05 +01:00
exit ( 0 ) ;
}
2013-07-16 09:35:31 +02:00
usage ( " unrecognized command " ) ;
exit ( 1 ) ;
}
void usage ( const char * reason )
{
2014-05-11 13:36:51 +02:00
if ( reason ) {
2013-07-16 09:35:31 +02:00
fprintf ( stderr , " %s \n " , reason ) ;
2014-05-11 13:36:51 +02:00
}
2013-07-16 09:35:31 +02:00
fprintf ( stderr , " usage: daemon {start|stop|status} [-p <additional params>] \n \n " ) ;
exit ( 1 ) ;
}
2013-02-24 21:57:38 +01:00
2013-08-27 23:08:00 +02:00
void print_status ( )
{
2014-07-11 15:10:11 +02:00
warnx ( " type: %s " , ( status . is_rotary_wing ) ? " ROTARY " : " PLANE " ) ;
2013-08-17 15:47:42 +02:00
warnx ( " usb powered: %s " , ( on_usb_power ) ? " yes " : " no " ) ;
2014-07-30 19:54:40 +02:00
warnx ( " avionics rail: %6.2f V " , ( double ) status . avionics_power_rail_voltage ) ;
2013-08-18 12:42:24 +02:00
/* read all relevant states */
int state_sub = orb_subscribe ( ORB_ID ( vehicle_status ) ) ;
struct vehicle_status_s state ;
orb_copy ( ORB_ID ( vehicle_status ) , state_sub , & state ) ;
2013-08-27 23:08:00 +02:00
const char * armed_str ;
2013-08-18 12:42:24 +02:00
switch ( state . arming_state ) {
2013-08-27 23:08:00 +02:00
case ARMING_STATE_INIT :
armed_str = " INIT " ;
break ;
case ARMING_STATE_STANDBY :
armed_str = " STANDBY " ;
break ;
case ARMING_STATE_ARMED :
armed_str = " ARMED " ;
break ;
case ARMING_STATE_ARMED_ERROR :
armed_str = " ARMED_ERROR " ;
break ;
case ARMING_STATE_STANDBY_ERROR :
armed_str = " STANDBY_ERROR " ;
break ;
case ARMING_STATE_REBOOT :
armed_str = " REBOOT " ;
break ;
case ARMING_STATE_IN_AIR_RESTORE :
armed_str = " IN_AIR_RESTORE " ;
break ;
default :
armed_str = " ERR: UNKNOWN STATE " ;
break ;
2013-08-18 12:42:24 +02:00
}
2013-09-01 10:29:30 +02:00
close ( state_sub ) ;
2013-08-18 12:42:24 +02:00
warnx ( " arming: %s " , armed_str ) ;
2013-08-17 15:47:42 +02:00
}
2013-09-08 21:06:55 +02:00
static orb_advert_t status_pub ;
2014-06-30 12:19:08 +02:00
transition_result_t arm_disarm ( bool arm , const int mavlink_fd_local , const char * armedBy )
2014-01-16 10:58:05 +01:00
{
2014-05-11 13:36:51 +02:00
transition_result_t arming_res = TRANSITION_NOT_CHANGED ;
// Transition the armed state. By passing mavlink_fd to arming_state_transition it will
// output appropriate error messages if the state cannot transition.
2014-10-23 16:17:20 +02:00
arming_res = arming_state_transition ( & status , & safety , arm ? ARMING_STATE_ARMED : ARMING_STATE_STANDBY , & armed ,
true /* fRunPreArmChecks */ , mavlink_fd_local ) ;
2014-05-11 13:36:51 +02:00
if ( arming_res = = TRANSITION_CHANGED & & mavlink_fd ) {
2014-06-30 12:19:08 +02:00
mavlink_log_info ( mavlink_fd_local , " [cmd] %s by %s " , arm ? " ARMED " : " DISARMED " , armedBy ) ;
2014-05-11 13:36:51 +02:00
} else if ( arming_res = = TRANSITION_DENIED ) {
tune_negative ( true ) ;
}
return arming_res ;
2014-01-16 10:58:05 +01:00
}
2014-07-13 11:41:39 +02:00
bool handle_command ( struct vehicle_status_s * status_local , const struct safety_s * safety_local ,
2014-10-23 16:17:20 +02:00
struct vehicle_command_s * cmd , struct actuator_armed_s * armed_local ,
struct home_position_s * home , struct vehicle_global_position_s * global_pos , orb_advert_t * home_pub )
2012-08-04 15:12:36 -07:00
{
2014-04-08 17:06:52 +02:00
/* only handle commands that are meant to be handled by this system and component */
2014-10-23 16:17:20 +02:00
if ( cmd - > target_system ! = status_local - > system_id | | ( ( cmd - > target_component ! = status_local - > component_id )
& & ( cmd - > target_component ! = 0 ) ) ) { // component_id 0: valid for all components
2014-04-08 17:06:52 +02:00
return false ;
}
2014-05-27 21:56:32 +02:00
/* result of the command */
enum VEHICLE_CMD_RESULT cmd_result = VEHICLE_CMD_RESULT_UNSUPPORTED ;
2013-08-17 18:39:46 +02:00
2012-08-04 15:12:36 -07:00
/* request to set different system mode */
switch ( cmd - > command ) {
2013-07-31 20:58:27 +04:00
case VEHICLE_CMD_DO_SET_MODE : {
2014-05-27 21:56:32 +02:00
uint8_t base_mode = ( uint8_t ) cmd - > param1 ;
uint8_t custom_main_mode = ( uint8_t ) cmd - > param2 ;
2013-08-07 20:21:49 +02:00
2014-05-27 21:56:32 +02:00
transition_result_t arming_ret = TRANSITION_NOT_CHANGED ;
2013-10-21 20:07:47 +02:00
2014-05-27 21:56:32 +02:00
transition_result_t main_ret = TRANSITION_NOT_CHANGED ;
2014-01-26 11:52:33 +01:00
2014-05-27 21:56:32 +02:00
/* set HIL state */
hil_state_t new_hil_state = ( base_mode & MAV_MODE_FLAG_HIL_ENABLED ) ? HIL_STATE_ON : HIL_STATE_OFF ;
2014-07-13 11:41:39 +02:00
transition_result_t hil_ret = hil_state_transition ( new_hil_state , status_pub , status_local , mavlink_fd ) ;
2013-09-08 21:06:55 +02:00
2014-05-27 21:56:32 +02:00
// Transition the arming state
arming_ret = arm_disarm ( base_mode & MAV_MODE_FLAG_SAFETY_ARMED , mavlink_fd , " set mode command " ) ;
2012-08-04 15:12:36 -07:00
2014-05-27 21:56:32 +02:00
if ( base_mode & MAV_MODE_FLAG_CUSTOM_MODE_ENABLED ) {
/* use autopilot-specific mode */
if ( custom_main_mode = = PX4_CUSTOM_MAIN_MODE_MANUAL ) {
/* MANUAL */
2014-07-13 11:41:39 +02:00
main_ret = main_state_transition ( status_local , MAIN_STATE_MANUAL ) ;
2013-08-07 20:21:49 +02:00
2014-05-11 13:35:05 +02:00
} else if ( custom_main_mode = = PX4_CUSTOM_MAIN_MODE_ALTCTL ) {
/* ALTCTL */
2014-07-13 11:41:39 +02:00
main_ret = main_state_transition ( status_local , MAIN_STATE_ALTCTL ) ;
2012-12-27 17:13:48 +01:00
2014-05-11 13:35:05 +02:00
} else if ( custom_main_mode = = PX4_CUSTOM_MAIN_MODE_POSCTL ) {
/* POSCTL */
2014-07-13 11:41:39 +02:00
main_ret = main_state_transition ( status_local , MAIN_STATE_POSCTL ) ;
2012-12-27 17:13:48 +01:00
2013-08-25 20:17:42 +02:00
} else if ( custom_main_mode = = PX4_CUSTOM_MAIN_MODE_AUTO ) {
2013-08-07 20:21:49 +02:00
/* AUTO */
2014-07-13 11:41:39 +02:00
main_ret = main_state_transition ( status_local , MAIN_STATE_AUTO_MISSION ) ;
2014-05-20 00:03:00 +02:00
} else if ( custom_main_mode = = PX4_CUSTOM_MAIN_MODE_ACRO ) {
/* ACRO */
2014-07-13 11:41:39 +02:00
main_ret = main_state_transition ( status_local , MAIN_STATE_ACRO ) ;
2014-05-21 10:40:58 +02:00
2014-01-29 21:21:16 +01:00
} else if ( custom_main_mode = = PX4_CUSTOM_MAIN_MODE_OFFBOARD ) {
/* OFFBOARD */
2014-07-13 11:41:39 +02:00
main_ret = main_state_transition ( status_local , MAIN_STATE_OFFBOARD ) ;
2013-08-07 20:21:49 +02:00
}
2012-12-27 17:13:48 +01:00
2014-05-27 21:56:32 +02:00
} else {
2013-08-07 20:21:49 +02:00
/* use base mode */
if ( base_mode & MAV_MODE_FLAG_AUTO_ENABLED ) {
/* AUTO */
2014-07-13 11:41:39 +02:00
main_ret = main_state_transition ( status_local , MAIN_STATE_AUTO_MISSION ) ;
2013-08-07 20:21:49 +02:00
} else if ( base_mode & MAV_MODE_FLAG_MANUAL_INPUT_ENABLED ) {
if ( base_mode & MAV_MODE_FLAG_GUIDED_ENABLED ) {
2014-05-11 13:35:05 +02:00
/* POSCTL */
2014-07-13 11:41:39 +02:00
main_ret = main_state_transition ( status_local , MAIN_STATE_POSCTL ) ;
2013-08-07 20:21:49 +02:00
} else if ( base_mode & MAV_MODE_FLAG_STABILIZE_ENABLED ) {
2013-07-31 20:58:27 +04:00
/* MANUAL */
2014-07-13 11:41:39 +02:00
main_ret = main_state_transition ( status_local , MAIN_STATE_MANUAL ) ;
2013-07-31 20:58:27 +04:00
}
2013-02-19 12:32:47 -08:00
}
2013-07-31 20:58:27 +04:00
}
2014-01-26 11:52:33 +01:00
2014-05-27 21:56:32 +02:00
if ( hil_ret ! = TRANSITION_DENIED & & arming_ret ! = TRANSITION_DENIED & & main_ret ! = TRANSITION_DENIED ) {
cmd_result = VEHICLE_CMD_RESULT_ACCEPTED ;
2012-08-29 14:20:55 +02:00
2014-05-27 21:56:32 +02:00
} else {
cmd_result = VEHICLE_CMD_RESULT_TEMPORARILY_REJECTED ;
}
2013-07-31 20:58:27 +04:00
}
2014-04-27 02:26:09 +02:00
break ;
2013-10-21 20:07:47 +02:00
case VEHICLE_CMD_COMPONENT_ARM_DISARM : {
2014-07-13 11:41:39 +02:00
// Adhere to MAVLink specs, but base on knowledge that these fundamentally encode ints
// for logic state parameters
if ( static_cast < int > ( cmd - > param1 + 0.5f ) ! = 0 & & static_cast < int > ( cmd - > param1 + 0.5f ) ! = 1 ) {
mavlink_log_critical ( mavlink_fd , " Unsupported ARM_DISARM param: %.3f " , ( double ) cmd - > param1 ) ;
2014-05-06 14:57:06 +02:00
2014-05-11 13:36:51 +02:00
} else {
2014-07-13 11:41:39 +02:00
bool cmd_arms = ( static_cast < int > ( cmd - > param1 + 0.5f ) = = 1 ) ;
2014-05-11 13:36:51 +02:00
// Flick to inair restore first if this comes from an onboard system
2014-07-13 11:41:39 +02:00
if ( cmd - > source_system = = status_local - > system_id & & cmd - > source_component = = status_local - > component_id ) {
status_local - > arming_state = ARMING_STATE_IN_AIR_RESTORE ;
2014-05-11 13:36:51 +02:00
}
2014-07-13 11:41:39 +02:00
transition_result_t arming_res = arm_disarm ( cmd_arms , mavlink_fd , " arm/disarm component command " ) ;
2014-05-11 13:36:51 +02:00
if ( arming_res = = TRANSITION_DENIED ) {
2014-07-13 11:41:39 +02:00
mavlink_log_critical ( mavlink_fd , " REJECTING component arm cmd " ) ;
2014-05-27 21:56:32 +02:00
cmd_result = VEHICLE_CMD_RESULT_TEMPORARILY_REJECTED ;
2014-05-11 13:36:51 +02:00
} else {
2014-05-27 21:56:32 +02:00
cmd_result = VEHICLE_CMD_RESULT_ACCEPTED ;
2014-05-11 13:36:51 +02:00
}
}
2013-09-22 14:43:12 +02:00
}
2013-07-31 20:58:27 +04:00
break ;
2013-01-11 07:42:09 +01:00
2013-12-29 22:38:22 +04:00
case VEHICLE_CMD_OVERRIDE_GOTO : {
2014-01-26 11:52:33 +01:00
// TODO listen vehicle_command topic directly from navigator (?)
2014-07-13 11:41:39 +02:00
// Increase by 0.5f and rely on the integer cast
// implicit floor(). This is the *safest* way to
// convert from floats representing small ints to actual ints.
unsigned int mav_goto = ( cmd - > param1 + 0.5f ) ;
2014-01-26 11:52:33 +01:00
2013-12-29 22:38:22 +04:00
if ( mav_goto = = 0 ) { // MAV_GOTO_DO_HOLD
2014-07-13 11:41:39 +02:00
status_local - > nav_state = NAVIGATION_STATE_AUTO_LOITER ;
mavlink_log_critical ( mavlink_fd , " Pause mission cmd " ) ;
2014-05-27 21:56:32 +02:00
cmd_result = VEHICLE_CMD_RESULT_ACCEPTED ;
2013-12-29 22:38:22 +04:00
} else if ( mav_goto = = 1 ) { // MAV_GOTO_DO_CONTINUE
2014-07-13 11:41:39 +02:00
status_local - > nav_state = NAVIGATION_STATE_AUTO_MISSION ;
mavlink_log_critical ( mavlink_fd , " Continue mission cmd " ) ;
2014-05-27 21:56:32 +02:00
cmd_result = VEHICLE_CMD_RESULT_ACCEPTED ;
2013-12-29 22:38:22 +04:00
} else {
2014-07-13 11:41:39 +02:00
mavlink_log_critical ( mavlink_fd , " REJ CMD: %.1f %.1f %.1f %.1f %.1f %.1f %.1f %.1f " ,
2014-10-23 16:17:20 +02:00
( double ) cmd - > param1 ,
( double ) cmd - > param2 ,
( double ) cmd - > param3 ,
( double ) cmd - > param4 ,
( double ) cmd - > param5 ,
( double ) cmd - > param6 ,
( double ) cmd - > param7 ) ;
2013-12-29 22:38:22 +04:00
}
}
break ;
2015-01-16 16:46:16 +01:00
/* Flight termination */
2014-07-19 14:39:41 +02:00
case VEHICLE_CMD_DO_FLIGHTTERMINATION : {
if ( cmd - > param1 > 0.5f ) {
//XXX update state machine?
armed_local - > force_failsafe = true ;
2014-08-15 00:07:38 +02:00
warnx ( " forcing failsafe (termination) " ) ;
2014-10-23 16:17:20 +02:00
2013-12-08 16:52:41 +01:00
} else {
2014-07-19 14:39:41 +02:00
armed_local - > force_failsafe = false ;
2014-08-15 00:07:38 +02:00
warnx ( " disabling failsafe (termination) " ) ;
2013-12-08 16:52:41 +01:00
}
2014-10-23 16:17:20 +02:00
2014-08-14 22:38:48 +02:00
/* param2 is currently used for other failsafe modes */
status_local - > engine_failure_cmd = false ;
status_local - > data_link_lost_cmd = false ;
status_local - > gps_failure_cmd = false ;
status_local - > rc_signal_lost_cmd = false ;
2014-10-23 16:17:20 +02:00
2014-08-14 22:38:48 +02:00
if ( ( int ) cmd - > param2 < = 0 ) {
/* reset all commanded failure modes */
2014-08-23 14:02:22 +02:00
warnx ( " reset all non-flighttermination failsafe commands " ) ;
2014-10-23 16:17:20 +02:00
2014-08-14 22:38:48 +02:00
} else if ( ( int ) cmd - > param2 = = 1 ) {
/* trigger engine failure mode */
status_local - > engine_failure_cmd = true ;
warnx ( " engine failure mode commanded " ) ;
2014-10-23 16:17:20 +02:00
2014-08-14 22:38:48 +02:00
} else if ( ( int ) cmd - > param2 = = 2 ) {
/* trigger data link loss mode */
status_local - > data_link_lost_cmd = true ;
warnx ( " data link loss mode commanded " ) ;
2014-10-23 16:17:20 +02:00
2014-08-14 22:38:48 +02:00
} else if ( ( int ) cmd - > param2 = = 3 ) {
/* trigger gps loss mode */
status_local - > gps_failure_cmd = true ;
warnx ( " gps loss mode commanded " ) ;
2014-10-23 16:17:20 +02:00
2014-08-14 22:38:48 +02:00
} else if ( ( int ) cmd - > param2 = = 4 ) {
/* trigger rc loss mode */
status_local - > rc_signal_lost_cmd = true ;
warnx ( " rc loss mode commanded " ) ;
2013-12-08 16:52:41 +01:00
}
2014-10-23 16:17:20 +02:00
2014-07-19 14:39:41 +02:00
cmd_result = VEHICLE_CMD_RESULT_ACCEPTED ;
2013-12-08 16:52:41 +01:00
}
break ;
2014-04-02 16:53:22 +04:00
case VEHICLE_CMD_DO_SET_HOME : {
bool use_current = cmd - > param1 > 0.5f ;
2014-05-11 13:36:51 +02:00
2014-04-02 16:53:22 +04:00
if ( use_current ) {
/* use current position */
2014-07-13 11:41:39 +02:00
if ( status_local - > condition_global_position_valid ) {
2014-04-02 16:53:22 +04:00
home - > lat = global_pos - > lat ;
home - > lon = global_pos - > lon ;
home - > alt = global_pos - > alt ;
home - > timestamp = hrt_absolute_time ( ) ;
2014-05-27 21:56:32 +02:00
cmd_result = VEHICLE_CMD_RESULT_ACCEPTED ;
2014-04-02 16:53:22 +04:00
} else {
2014-05-27 21:56:32 +02:00
cmd_result = VEHICLE_CMD_RESULT_TEMPORARILY_REJECTED ;
2014-04-02 16:53:22 +04:00
}
} else {
/* use specified position */
home - > lat = cmd - > param5 ;
home - > lon = cmd - > param6 ;
home - > alt = cmd - > param7 ;
home - > timestamp = hrt_absolute_time ( ) ;
2014-05-27 21:56:32 +02:00
cmd_result = VEHICLE_CMD_RESULT_ACCEPTED ;
2014-04-02 16:53:22 +04:00
}
2014-05-27 21:56:32 +02:00
if ( cmd_result = = VEHICLE_CMD_RESULT_ACCEPTED ) {
2014-04-02 16:53:22 +04:00
warnx ( " home: lat = %.7f, lon = %.7f, alt = %.2f " , home - > lat , home - > lon , ( double ) home - > alt ) ;
mavlink_log_info ( mavlink_fd , " [cmd] home: %.7f, %.7f, %.2f " , home - > lat , home - > lon , ( double ) home - > alt ) ;
/* announce new home position */
if ( * home_pub > 0 ) {
2014-04-05 16:59:01 +04:00
orb_publish ( ORB_ID ( home_position ) , * home_pub , home ) ;
2014-04-02 16:53:22 +04:00
} else {
2014-04-05 16:59:01 +04:00
* home_pub = orb_advertise ( ORB_ID ( home_position ) , home ) ;
2014-04-02 16:53:22 +04:00
}
/* mark home position as set */
2014-07-13 11:41:39 +02:00
status_local - > condition_home_position_valid = true ;
2014-04-02 16:53:22 +04:00
}
}
break ;
2014-10-23 16:17:20 +02:00
2014-07-14 11:19:06 +02:00
case VEHICLE_CMD_NAV_GUIDED_ENABLE : {
transition_result_t res = TRANSITION_DENIED ;
static main_state_t main_state_pre_offboard = MAIN_STATE_MANUAL ;
2014-10-23 16:17:20 +02:00
2014-07-14 11:19:06 +02:00
if ( status_local - > main_state ! = MAIN_STATE_OFFBOARD ) {
main_state_pre_offboard = status_local - > main_state ;
}
2014-10-23 16:17:20 +02:00
2014-07-14 11:19:06 +02:00
if ( cmd - > param1 > 0.5f ) {
res = main_state_transition ( status_local , MAIN_STATE_OFFBOARD ) ;
2014-10-23 16:17:20 +02:00
2014-07-14 11:19:06 +02:00
if ( res = = TRANSITION_DENIED ) {
print_reject_mode ( status_local , " OFFBOARD " ) ;
2014-07-16 09:38:57 +02:00
status_local - > offboard_control_set_by_command = false ;
2014-10-23 16:17:20 +02:00
2014-07-16 09:38:57 +02:00
} else {
/* Set flag that offboard was set via command, main state is not overridden by rc */
status_local - > offboard_control_set_by_command = true ;
2014-07-14 11:19:06 +02:00
}
2014-10-23 16:17:20 +02:00
2014-07-14 11:19:06 +02:00
} else {
/* If the mavlink command is used to enable or disable offboard control:
* switch back to previous mode when disabling */
res = main_state_transition ( status_local , main_state_pre_offboard ) ;
2014-07-16 09:38:57 +02:00
status_local - > offboard_control_set_by_command = false ;
2014-07-14 11:19:06 +02:00
}
}
break ;
2014-10-23 16:17:20 +02:00
2013-12-29 12:16:49 +04:00
case VEHICLE_CMD_PREFLIGHT_REBOOT_SHUTDOWN :
case VEHICLE_CMD_PREFLIGHT_CALIBRATION :
case VEHICLE_CMD_PREFLIGHT_SET_SENSOR_OFFSETS :
case VEHICLE_CMD_PREFLIGHT_STORAGE :
2014-08-26 10:14:36 +02:00
case VEHICLE_CMD_CUSTOM_0 :
case VEHICLE_CMD_CUSTOM_1 :
case VEHICLE_CMD_CUSTOM_2 :
case VEHICLE_CMD_PAYLOAD_PREPARE_DEPLOY :
case VEHICLE_CMD_PAYLOAD_CONTROL_DEPLOY :
2013-12-29 12:16:49 +04:00
/* ignore commands that handled in low prio loop */
break ;
2013-05-17 11:24:02 +02:00
default :
2014-04-07 21:42:19 +02:00
/* Warn about unsupported commands, this makes sense because only commands
* to this component ID ( or all ) are passed by mavlink . */
2013-12-29 12:16:49 +04:00
answer_command ( * cmd , VEHICLE_CMD_RESULT_UNSUPPORTED ) ;
2012-08-04 15:12:36 -07:00
break ;
}
2014-05-11 13:36:51 +02:00
2014-05-27 21:56:32 +02:00
if ( cmd_result ! = VEHICLE_CMD_RESULT_UNSUPPORTED ) {
2014-04-07 21:42:19 +02:00
/* already warned about unsupported commands in "default" case */
2014-05-27 21:56:32 +02:00
answer_command ( * cmd , cmd_result ) ;
2014-04-07 21:42:19 +02:00
}
2012-08-04 15:12:36 -07:00
/* send any requested ACKs */
2014-05-27 21:56:32 +02:00
if ( cmd - > confirmation > 0 & & cmd_result ! = VEHICLE_CMD_RESULT_UNSUPPORTED ) {
2012-08-04 15:12:36 -07:00
/* send acknowledge command */
2012-08-24 00:01:23 +02:00
// XXX TODO
2012-08-04 15:12:36 -07:00
}
2014-06-29 13:55:55 -07:00
return true ;
2012-08-04 15:12:36 -07:00
}
2015-01-16 16:43:11 +01:00
/**
* @ brief This function initializes the home position of the vehicle . This happens first time we get a good GPS fix and each
* time the vehicle is armed with a good GPS fix .
* */
2015-01-16 16:46:16 +01:00
static void commander_set_home_position ( orb_advert_t & homePub , home_position_s & home ,
const vehicle_local_position_s & localPosition , const vehicle_global_position_s & globalPosition )
2015-01-16 16:43:11 +01:00
{
//Need global position fix to be able to set home
2015-01-16 16:46:16 +01:00
if ( ! status . condition_global_position_valid ) {
2015-01-16 16:43:11 +01:00
return ;
}
//Ensure that the GPS accuracy is good enough for intializing home
2015-01-16 16:46:16 +01:00
if ( globalPosition . eph > eph_threshold | | globalPosition . epv > epv_threshold ) {
2015-01-16 16:43:11 +01:00
return ;
}
//Set home position
home . timestamp = hrt_absolute_time ( ) ;
home . lat = globalPosition . lat ;
home . lon = globalPosition . lon ;
home . alt = globalPosition . alt ;
home . x = localPosition . x ;
home . y = localPosition . y ;
home . z = localPosition . z ;
warnx ( " home: lat = %.7f, lon = %.7f, alt = %.2f " , home . lat , home . lon , ( double ) home . alt ) ;
mavlink_log_info ( mavlink_fd , " home: %.7f, %.7f, %.2f " , home . lat , home . lon , ( double ) home . alt ) ;
/* announce new home position */
if ( homePub > 0 ) {
orb_publish ( ORB_ID ( home_position ) , homePub , & home ) ;
} else {
homePub = orb_advertise ( ORB_ID ( home_position ) , & home ) ;
}
//Play tune first time we initialize HOME
2015-01-16 16:46:16 +01:00
if ( ! status . condition_home_position_valid ) {
2015-01-16 16:43:11 +01:00
tune_positive ( true ) ;
}
/* mark home position as set */
status . condition_home_position_valid = true ;
}
2012-08-20 23:52:13 +02:00
int commander_thread_main ( int argc , char * argv [ ] )
2012-08-04 15:12:36 -07:00
{
/* not yet initialized */
commander_initialized = false ;
2013-06-25 13:15:38 +02:00
bool arm_tune_played = false ;
2014-04-02 11:57:41 +04:00
bool was_armed = false ;
2013-06-25 13:15:38 +02:00
2012-09-21 12:55:41 +02:00
/* set parameters */
2012-12-31 12:31:31 -08:00
param_t _param_sys_type = param_find ( " MAV_TYPE " ) ;
2013-02-17 16:06:33 +01:00
param_t _param_system_id = param_find ( " MAV_SYS_ID " ) ;
param_t _param_component_id = param_find ( " MAV_COMP_ID " ) ;
2013-08-30 10:11:24 +02:00
param_t _param_takeoff_alt = param_find ( " NAV_TAKEOFF_ALT " ) ;
2014-02-13 16:08:49 +01:00
param_t _param_enable_parachute = param_find ( " NAV_PARACHUTE_EN " ) ;
2014-06-18 19:01:41 +02:00
param_t _param_enable_datalink_loss = param_find ( " COM_DL_LOSS_EN " ) ;
2014-07-20 17:53:04 +02:00
param_t _param_datalink_loss_timeout = param_find ( " COM_DL_LOSS_T " ) ;
2014-09-05 12:06:05 +02:00
param_t _param_rc_loss_timeout = param_find ( " COM_RC_LOSS_T " ) ;
2014-07-24 08:57:58 +02:00
param_t _param_datalink_regain_timeout = param_find ( " COM_DL_REG_T " ) ;
2014-09-05 08:59:00 +02:00
param_t _param_ef_throttle_thres = param_find ( " COM_EF_THROT " ) ;
param_t _param_ef_current2throttle_thres = param_find ( " COM_EF_C2T " ) ;
param_t _param_ef_time_thres = param_find ( " COM_EF_TIME " ) ;
2014-12-02 10:47:07 +01:00
param_t _param_autostart_id = param_find ( " SYS_AUTOSTART " ) ;
2012-12-13 10:23:02 +01:00
2014-07-05 13:35:12 -07:00
const char * main_states_str [ MAIN_STATE_MAX ] ;
2014-06-17 13:19:50 +02:00
main_states_str [ MAIN_STATE_MANUAL ] = " MANUAL " ;
main_states_str [ MAIN_STATE_ALTCTL ] = " ALTCTL " ;
main_states_str [ MAIN_STATE_POSCTL ] = " POSCTL " ;
2014-06-18 19:01:41 +02:00
main_states_str [ MAIN_STATE_AUTO_MISSION ] = " AUTO_MISSION " ;
main_states_str [ MAIN_STATE_AUTO_LOITER ] = " AUTO_LOITER " ;
main_states_str [ MAIN_STATE_AUTO_RTL ] = " AUTO_RTL " ;
2014-06-17 13:19:50 +02:00
main_states_str [ MAIN_STATE_ACRO ] = " ACRO " ;
2014-06-20 18:18:39 +02:00
main_states_str [ MAIN_STATE_OFFBOARD ] = " OFFBOARD " ;
2014-01-25 23:37:26 +01:00
2014-07-05 13:35:12 -07:00
const char * arming_states_str [ ARMING_STATE_MAX ] ;
2014-06-17 13:19:50 +02:00
arming_states_str [ ARMING_STATE_INIT ] = " INIT " ;
arming_states_str [ ARMING_STATE_STANDBY ] = " STANDBY " ;
arming_states_str [ ARMING_STATE_ARMED ] = " ARMED " ;
arming_states_str [ ARMING_STATE_ARMED_ERROR ] = " ARMED_ERROR " ;
2014-06-18 19:01:41 +02:00
arming_states_str [ ARMING_STATE_STANDBY_ERROR ] = " STANDBY_ERROR " ;
2014-06-17 13:19:50 +02:00
arming_states_str [ ARMING_STATE_REBOOT ] = " REBOOT " ;
2014-06-18 19:01:41 +02:00
arming_states_str [ ARMING_STATE_IN_AIR_RESTORE ] = " IN_AIR_RESTORE " ;
2014-06-17 13:19:50 +02:00
2014-07-05 13:35:12 -07:00
const char * nav_states_str [ NAVIGATION_STATE_MAX ] ;
2014-06-18 19:01:41 +02:00
nav_states_str [ NAVIGATION_STATE_MANUAL ] = " MANUAL " ;
nav_states_str [ NAVIGATION_STATE_ALTCTL ] = " ALTCTL " ;
nav_states_str [ NAVIGATION_STATE_POSCTL ] = " POSCTL " ;
nav_states_str [ NAVIGATION_STATE_AUTO_MISSION ] = " AUTO_MISSION " ;
nav_states_str [ NAVIGATION_STATE_AUTO_LOITER ] = " AUTO_LOITER " ;
2014-06-17 13:19:50 +02:00
nav_states_str [ NAVIGATION_STATE_AUTO_RTL ] = " AUTO_RTL " ;
2014-11-10 21:38:13 +10:00
nav_states_str [ NAVIGATION_STATE_AUTO_RCRECOVER ] = " AUTO_RCRECOVER " ;
2014-06-19 10:26:56 +02:00
nav_states_str [ NAVIGATION_STATE_AUTO_RTGS ] = " AUTO_RTGS " ;
2014-11-10 21:38:13 +10:00
nav_states_str [ NAVIGATION_STATE_AUTO_LANDENGFAIL ] = " AUTO_LANDENGFAIL " ;
nav_states_str [ NAVIGATION_STATE_AUTO_LANDGPSFAIL ] = " AUTO_LANDGPSFAIL " ;
2014-06-17 13:19:50 +02:00
nav_states_str [ NAVIGATION_STATE_ACRO ] = " ACRO " ;
nav_states_str [ NAVIGATION_STATE_LAND ] = " LAND " ;
nav_states_str [ NAVIGATION_STATE_DESCEND ] = " DESCEND " ;
2014-06-18 19:01:41 +02:00
nav_states_str [ NAVIGATION_STATE_TERMINATION ] = " TERMINATION " ;
2014-06-21 12:24:37 +02:00
nav_states_str [ NAVIGATION_STATE_OFFBOARD ] = " OFFBOARD " ;
2014-01-25 23:37:26 +01:00
2013-07-16 09:24:21 +02:00
/* pthread for slow low prio thread */
2013-03-25 14:53:54 -07:00
pthread_t commander_low_prio_thread ;
2012-08-04 15:12:36 -07:00
/* initialize */
if ( led_init ( ) ! = 0 ) {
2014-07-13 11:42:02 +02:00
warnx ( " ERROR: LED INIT FAIL " ) ;
2012-08-04 15:12:36 -07:00
}
2013-06-25 16:30:35 +02:00
if ( buzzer_init ( ) ! = OK ) {
2014-07-13 11:42:02 +02:00
warnx ( " ERROR: BUZZER INIT FAIL " ) ;
2012-08-04 15:12:36 -07:00
}
mavlink_fd = open ( MAVLINK_LOG_DEVICE , 0 ) ;
2014-01-27 20:49:17 +01:00
/* vehicle status topic */
2013-07-28 23:12:16 +04:00
memset ( & status , 0 , sizeof ( status ) ) ;
2013-08-16 23:36:49 +02:00
status . condition_landed = true ; // initialize to safe value
2014-02-01 13:21:51 +01:00
// We want to accept RC inputs as default
status . rc_input_blocked = false ;
2013-07-28 23:12:16 +04:00
status . main_state = MAIN_STATE_MANUAL ;
2014-06-16 17:34:21 +02:00
status . nav_state = NAVIGATION_STATE_MANUAL ;
2013-07-28 23:12:16 +04:00
status . arming_state = ARMING_STATE_INIT ;
status . hil_state = HIL_STATE_OFF ;
2014-06-16 17:34:21 +02:00
status . failsafe = false ;
2013-02-16 13:40:09 -08:00
2012-10-02 13:02:57 +02:00
/* neither manual nor offboard control commands have been received */
2013-07-28 23:12:16 +04:00
status . offboard_control_signal_found_once = false ;
status . rc_signal_found_once = false ;
2013-02-16 13:40:09 -08:00
2012-10-02 13:02:57 +02:00
/* mark all signals lost as long as they haven't been found */
2013-07-28 23:12:16 +04:00
status . rc_signal_lost = true ;
status . offboard_control_signal_lost = true ;
2014-06-16 17:34:21 +02:00
status . data_link_lost = true ;
2013-02-16 13:40:09 -08:00
2013-01-08 21:19:23 +01:00
/* set battery warning flag */
2013-07-28 23:12:16 +04:00
status . battery_warning = VEHICLE_BATTERY_WARNING_NONE ;
2013-08-15 17:27:29 +02:00
status . condition_battery_voltage_valid = false ;
2013-07-28 23:12:16 +04:00
2013-02-17 23:07:07 -08:00
// XXX for now just set sensors as initialized
2013-07-28 23:12:16 +04:00
status . condition_system_sensors_initialized = true ;
2013-02-17 23:07:07 -08:00
2013-07-28 23:12:16 +04:00
status . counter + + ;
status . timestamp = hrt_absolute_time ( ) ;
2014-01-27 20:49:17 +01:00
2014-05-25 08:22:54 +02:00
status . condition_power_input_valid = true ;
status . avionics_power_rail_voltage = - 1.0f ;
2014-05-25 20:34:32 +02:00
// CIRCUIT BREAKERS
status . circuit_breaker_engaged_power_check = false ;
2014-07-26 17:48:45 +02:00
status . circuit_breaker_engaged_airspd_check = false ;
2014-09-30 13:40:03 +02:00
status . circuit_breaker_engaged_enginefailure_check = false ;
status . circuit_breaker_engaged_gpsfailure_check = false ;
2014-05-25 20:34:32 +02:00
2014-01-27 20:49:17 +01:00
/* publish initial state */
status_pub = orb_advertise ( ORB_ID ( vehicle_status ) , & status ) ;
2014-10-23 16:17:20 +02:00
2014-06-13 23:40:48 +02:00
if ( status_pub < 0 ) {
warnx ( " ERROR: orb_advertise for topic vehicle_status failed (uorb app running?). \n " ) ;
warnx ( " exiting. " ) ;
exit ( ERROR ) ;
}
2014-01-27 20:49:17 +01:00
/* armed topic */
orb_advert_t armed_pub ;
/* Initialize armed with all false */
memset ( & armed , 0 , sizeof ( armed ) ) ;
/* vehicle control mode topic */
memset ( & control_mode , 0 , sizeof ( control_mode ) ) ;
orb_advert_t control_mode_pub = orb_advertise ( ORB_ID ( vehicle_control_mode ) , & control_mode ) ;
2013-06-25 16:30:35 +02:00
2013-07-15 22:15:15 +02:00
armed_pub = orb_advertise ( ORB_ID ( actuator_armed ) , & armed ) ;
2013-06-25 13:15:38 +02:00
2013-01-19 14:46:26 +01:00
/* home position */
orb_advert_t home_pub = - 1 ;
struct home_position_s home ;
memset ( & home , 0 , sizeof ( home ) ) ;
2014-06-14 23:57:29 +02:00
/* init mission state, do it here to allow navigator to use stored mission even if mavlink failed to start */
orb_advert_t mission_pub = - 1 ;
2014-06-13 23:40:48 +02:00
mission_s mission ;
2014-10-23 16:17:20 +02:00
2014-06-13 23:40:48 +02:00
if ( dm_read ( DM_KEY_MISSION_STATE , 0 , & mission , sizeof ( mission_s ) ) = = sizeof ( mission_s ) ) {
if ( mission . dataman_id > = 0 & & mission . dataman_id < = 1 ) {
2014-10-23 16:17:20 +02:00
warnx ( " loaded mission state: dataman_id=%d, count=%u, current=%d " , mission . dataman_id , mission . count ,
mission . current_seq ) ;
2014-06-14 23:57:29 +02:00
mavlink_log_info ( mavlink_fd , " [cmd] dataman_id=%d, count=%u, current=%d " ,
2014-10-23 16:17:20 +02:00
mission . dataman_id , mission . count , mission . current_seq ) ;
2014-06-13 23:40:48 +02:00
} else {
2014-07-13 11:43:56 +02:00
const char * missionfail = " reading mission state failed " ;
warnx ( " %s " , missionfail ) ;
mavlink_log_critical ( mavlink_fd , missionfail ) ;
2014-06-14 23:57:29 +02:00
/* initialize mission state in dataman */
mission . dataman_id = 0 ;
mission . count = 0 ;
mission . current_seq = 0 ;
dm_write ( DM_KEY_MISSION_STATE , 0 , DM_PERSIST_POWER_ON_RESET , & mission , sizeof ( mission_s ) ) ;
2014-06-13 23:40:48 +02:00
}
2012-08-04 15:12:36 -07:00
2014-06-14 23:57:29 +02:00
mission_pub = orb_advertise ( ORB_ID ( offboard_mission ) , & mission ) ;
orb_publish ( ORB_ID ( offboard_mission ) , mission_pub , & mission ) ;
2012-08-04 15:12:36 -07:00
}
2013-09-08 20:05:15 +02:00
int ret ;
2013-03-25 14:53:54 -07:00
pthread_attr_t commander_low_prio_attr ;
pthread_attr_init ( & commander_low_prio_attr ) ;
2014-05-15 09:02:31 +02:00
pthread_attr_setstacksize ( & commander_low_prio_attr , 2900 ) ;
2013-03-25 14:53:54 -07:00
struct sched_param param ;
2013-09-05 13:24:21 +02:00
( void ) pthread_attr_getschedparam ( & commander_low_prio_attr , & param ) ;
2013-09-08 20:05:15 +02:00
2013-03-25 14:53:54 -07:00
/* low priority */
param . sched_priority = SCHED_PRIORITY_DEFAULT - 50 ;
( void ) pthread_attr_setschedparam ( & commander_low_prio_attr , & param ) ;
pthread_create ( & commander_low_prio_thread , & commander_low_prio_attr , commander_low_prio_loop , NULL ) ;
2013-09-08 20:05:15 +02:00
pthread_attr_destroy ( & commander_low_prio_attr ) ;
2013-03-25 14:53:54 -07:00
2012-08-04 15:12:36 -07:00
/* Start monitoring loop */
2013-07-16 18:55:32 +02:00
unsigned counter = 0 ;
unsigned stick_off_counter = 0 ;
unsigned stick_on_counter = 0 ;
2012-08-04 15:12:36 -07:00
2013-08-15 17:27:29 +02:00
bool low_battery_voltage_actions_done = false ;
bool critical_battery_voltage_actions_done = false ;
2013-07-16 18:55:32 +02:00
2014-05-07 08:42:57 +02:00
hrt_abstime last_idle_time = 0 ;
2013-07-16 10:05:51 +02:00
2013-07-31 20:58:27 +04:00
bool status_changed = true ;
2013-07-16 10:05:51 +02:00
bool param_init_forced = true ;
2013-07-31 20:58:27 +04:00
bool updated = false ;
2013-07-16 10:05:51 +02:00
2014-07-06 16:51:06 -07:00
rc_calibration_check ( mavlink_fd ) ;
2013-08-25 16:33:14 +02:00
2013-07-15 22:15:15 +02:00
/* Subscribe to safety topic */
int safety_sub = orb_subscribe ( ORB_ID ( safety ) ) ;
memset ( & safety , 0 , sizeof ( safety ) ) ;
2013-08-15 09:52:22 +02:00
safety . safety_switch_available = false ;
safety . safety_off = false ;
2013-07-15 22:15:15 +02:00
2014-05-27 21:56:32 +02:00
/* Subscribe to mission result topic */
int mission_result_sub = orb_subscribe ( ORB_ID ( mission_result ) ) ;
struct mission_result_s mission_result ;
memset ( & mission_result , 0 , sizeof ( mission_result ) ) ;
2014-12-19 22:26:31 +00:00
/* Subscribe to geofence result topic */
int geofence_result_sub = orb_subscribe ( ORB_ID ( geofence_result ) ) ;
struct geofence_result_s geofence_result ;
memset ( & geofence_result , 0 , sizeof ( geofence_result ) ) ;
2012-09-21 12:55:41 +02:00
/* Subscribe to manual control data */
int sp_man_sub = orb_subscribe ( ORB_ID ( manual_control_setpoint ) ) ;
struct manual_control_setpoint_s sp_man ;
memset ( & sp_man , 0 , sizeof ( sp_man ) ) ;
/* Subscribe to offboard control data */
int sp_offboard_sub = orb_subscribe ( ORB_ID ( offboard_control_setpoint ) ) ;
memset ( & sp_offboard , 0 , sizeof ( sp_offboard ) ) ;
2012-08-04 15:12:36 -07:00
2014-07-06 16:08:37 +02:00
/* Subscribe to telemetry status topics */
int telemetry_subs [ TELEMETRY_STATUS_ORB_ID_NUM ] ;
uint64_t telemetry_last_heartbeat [ TELEMETRY_STATUS_ORB_ID_NUM ] ;
2014-07-24 08:57:58 +02:00
uint64_t telemetry_last_dl_loss [ TELEMETRY_STATUS_ORB_ID_NUM ] ;
2014-07-06 16:08:37 +02:00
bool telemetry_lost [ TELEMETRY_STATUS_ORB_ID_NUM ] ;
for ( int i = 0 ; i < TELEMETRY_STATUS_ORB_ID_NUM ; i + + ) {
telemetry_subs [ i ] = orb_subscribe ( telemetry_status_orb_id [ i ] ) ;
telemetry_last_heartbeat [ i ] = 0 ;
2014-07-24 08:57:58 +02:00
telemetry_last_dl_loss [ i ] = 0 ;
2014-07-06 16:08:37 +02:00
telemetry_lost [ i ] = true ;
}
2014-06-16 17:34:21 +02:00
2013-02-16 13:40:09 -08:00
/* Subscribe to global position */
2012-12-13 10:23:02 +01:00
int global_position_sub = orb_subscribe ( ORB_ID ( vehicle_global_position ) ) ;
struct vehicle_global_position_s global_position ;
memset ( & global_position , 0 , sizeof ( global_position ) ) ;
2014-05-07 08:42:57 +02:00
/* Init EPH and EPV */
global_position . eph = 1000.0f ;
global_position . epv = 1000.0f ;
2012-12-13 10:23:02 +01:00
2013-02-16 13:40:09 -08:00
/* Subscribe to local position data */
2012-12-13 10:23:02 +01:00
int local_position_sub = orb_subscribe ( ORB_ID ( vehicle_local_position ) ) ;
struct vehicle_local_position_s local_position ;
memset ( & local_position , 0 , sizeof ( local_position ) ) ;
2012-08-04 15:12:36 -07:00
2015-01-06 12:25:18 +01:00
/* Subscribe to land detector */
int land_detector_sub = orb_subscribe ( ORB_ID ( vehicle_land_detected ) ) ;
struct vehicle_land_detected_s land_detector ;
memset ( & land_detector , 0 , sizeof ( land_detector ) ) ;
2013-07-28 23:12:16 +04:00
/*
2013-01-19 14:46:26 +01:00
* The home position is set based on GPS only , to prevent a dependency between
* position estimator and commander . RAW GPS is more than good enough for a
* non - flying vehicle .
*/
2013-02-16 13:40:09 -08:00
/* Subscribe to GPS topic */
2013-01-19 14:46:26 +01:00
int gps_sub = orb_subscribe ( ORB_ID ( vehicle_gps_position ) ) ;
struct vehicle_gps_position_s gps_position ;
memset ( & gps_position , 0 , sizeof ( gps_position ) ) ;
2014-07-01 09:51:35 +02:00
gps_position . eph = FLT_MAX ;
gps_position . epv = FLT_MAX ;
2013-01-19 14:46:26 +01:00
2013-02-16 13:40:09 -08:00
/* Subscribe to sensor topic */
2012-08-04 15:12:36 -07:00
int sensor_sub = orb_subscribe ( ORB_ID ( sensor_combined ) ) ;
2012-08-05 22:51:31 +02:00
struct sensor_combined_s sensors ;
memset ( & sensors , 0 , sizeof ( sensors ) ) ;
2012-08-04 15:12:36 -07:00
2013-07-16 10:05:51 +02:00
/* Subscribe to differential pressure topic */
2013-04-19 18:28:06 +02:00
int diff_pres_sub = orb_subscribe ( ORB_ID ( differential_pressure ) ) ;
struct differential_pressure_s diff_pres ;
memset ( & diff_pres , 0 , sizeof ( diff_pres ) ) ;
2013-02-25 15:48:16 +01:00
2012-10-15 08:52:41 +02:00
/* Subscribe to command topic */
int cmd_sub = orb_subscribe ( ORB_ID ( vehicle_command ) ) ;
struct vehicle_command_s cmd ;
memset ( & cmd , 0 , sizeof ( cmd ) ) ;
2012-12-13 10:23:02 +01:00
/* Subscribe to parameters changed topic */
int param_changed_sub = orb_subscribe ( ORB_ID ( parameter_update ) ) ;
struct parameter_update_s param_changed ;
memset ( & param_changed , 0 , sizeof ( param_changed ) ) ;
2013-07-16 10:05:51 +02:00
/* Subscribe to battery topic */
2013-01-01 13:30:24 +01:00
int battery_sub = orb_subscribe ( ORB_ID ( battery_status ) ) ;
struct battery_status_s battery ;
memset ( & battery , 0 , sizeof ( battery ) ) ;
2013-07-16 09:24:21 +02:00
/* Subscribe to subsystem info topic */
int subsys_sub = orb_subscribe ( ORB_ID ( subsystem_info ) ) ;
struct subsystem_info_s info ;
memset ( & info , 0 , sizeof ( info ) ) ;
2014-04-03 20:23:34 +04:00
/* Subscribe to position setpoint triplet */
int pos_sp_triplet_sub = orb_subscribe ( ORB_ID ( position_setpoint_triplet ) ) ;
struct position_setpoint_triplet_s pos_sp_triplet ;
memset ( & pos_sp_triplet , 0 , sizeof ( pos_sp_triplet ) ) ;
2014-05-25 08:22:54 +02:00
/* Subscribe to system power */
int system_power_sub = orb_subscribe ( ORB_ID ( system_power ) ) ;
struct system_power_s system_power ;
memset ( & system_power , 0 , sizeof ( system_power ) ) ;
2014-07-19 14:12:33 +02:00
/* Subscribe to actuator controls (outputs) */
int actuator_controls_sub = orb_subscribe ( ORB_ID_VEHICLE_ATTITUDE_CONTROLS ) ;
struct actuator_controls_s actuator_controls ;
memset ( & actuator_controls , 0 , sizeof ( actuator_controls ) ) ;
2014-12-02 10:47:07 +01:00
/* Subscribe to vtol vehicle status topic */
int vtol_vehicle_status_sub = orb_subscribe ( ORB_ID ( vtol_vehicle_status ) ) ;
struct vtol_vehicle_status_s vtol_status ;
memset ( & vtol_status , 0 , sizeof ( vtol_status ) ) ;
vtol_status . vtol_in_rw_mode = true ; //default for vtol is rotary wing
2013-09-19 19:58:41 +02:00
control_status_leds ( & status , & armed , true ) ;
2013-08-29 16:45:33 +02:00
2012-08-04 15:12:36 -07:00
/* now initialized */
commander_initialized = true ;
2013-02-18 16:45:59 +01:00
thread_running = true ;
2012-08-04 15:12:36 -07:00
2015-01-16 16:43:11 +01:00
const hrt_abstime commander_boot_timestamp = hrt_absolute_time ( ) ;
2012-12-23 17:20:53 -08:00
2014-05-27 21:56:32 +02:00
transition_result_t arming_ret ;
2014-06-18 19:01:41 +02:00
int32_t datalink_loss_enabled = false ;
2014-07-20 17:53:04 +02:00
int32_t datalink_loss_timeout = 10 ;
2014-09-05 12:06:05 +02:00
float rc_loss_timeout = 0.5 ;
2014-07-24 08:57:58 +02:00
int32_t datalink_regain_timeout = 0 ;
2014-09-05 08:59:00 +02:00
/* Thresholds for engine failure detection */
int32_t ef_throttle_thres = 1.0f ;
int32_t ef_current2throttle_thres = 0.0f ;
int32_t ef_time_thres = 1000.0f ;
2014-09-30 13:40:03 +02:00
uint64_t timestamp_engine_healthy = 0 ; /**< absolute time when engine was healty */
2014-06-18 19:01:41 +02:00
2014-05-27 21:56:32 +02:00
/* check which state machines for changes, clear "changed" flag */
bool arming_state_changed = false ;
bool main_state_changed = false ;
2014-06-17 13:19:50 +02:00
bool failsafe_old = false ;
2014-05-27 21:56:32 +02:00
2012-08-24 00:01:23 +02:00
while ( ! thread_should_exit ) {
2012-08-04 15:12:36 -07:00
2013-11-05 19:56:33 +01:00
if ( mavlink_fd < 0 & & counter % ( 1000000 / MAVLINK_OPEN_INTERVAL ) = = 0 ) {
/* try to open the mavlink log device every once in a while */
mavlink_fd = open ( MAVLINK_LOG_DEVICE , 0 ) ;
}
2014-05-27 21:56:32 +02:00
arming_ret = TRANSITION_NOT_CHANGED ;
2013-06-09 14:09:09 +02:00
/* update parameters */
2013-07-31 20:58:27 +04:00
orb_check ( param_changed_sub , & updated ) ;
2013-06-09 14:09:09 +02:00
2013-07-31 20:58:27 +04:00
if ( updated | | param_init_forced ) {
2013-06-09 14:09:09 +02:00
param_init_forced = false ;
/* parameters changed */
orb_copy ( ORB_ID ( parameter_update ) , param_changed_sub , & param_changed ) ;
/* update parameters */
2013-07-15 22:15:15 +02:00
if ( ! armed . armed ) {
2013-07-28 23:12:16 +04:00
if ( param_get ( _param_sys_type , & ( status . system_type ) ) ! = OK ) {
2013-07-16 10:05:51 +02:00
warnx ( " failed getting new system type " ) ;
2013-06-09 14:09:09 +02:00
}
/* disable manual override for all systems that rely on electronic stabilization */
2013-07-28 23:12:16 +04:00
if ( status . system_type = = VEHICLE_TYPE_COAXIAL | |
status . system_type = = VEHICLE_TYPE_HELICOPTER | |
status . system_type = = VEHICLE_TYPE_TRICOPTER | |
status . system_type = = VEHICLE_TYPE_QUADROTOR | |
status . system_type = = VEHICLE_TYPE_HEXAROTOR | |
2014-12-02 10:47:07 +01:00
status . system_type = = VEHICLE_TYPE_OCTOROTOR | |
( status . system_type = = VEHICLE_TYPE_VTOL_DUOROTOR & & vtol_status . vtol_in_rw_mode ) | |
( status . system_type = = VEHICLE_TYPE_VTOL_QUADROTOR & & vtol_status . vtol_in_rw_mode ) ) {
2013-07-28 23:12:16 +04:00
status . is_rotary_wing = true ;
2013-06-09 14:09:09 +02:00
} else {
2013-07-28 23:12:16 +04:00
status . is_rotary_wing = false ;
2013-06-09 14:09:09 +02:00
}
2014-12-18 14:46:31 +01:00
/* set vehicle_status.is_vtol flag */
2015-01-16 16:46:16 +01:00
status . is_vtol = ( status . system_type = = VEHICLE_TYPE_VTOL_DUOROTOR ) | |
( status . system_type = = VEHICLE_TYPE_VTOL_QUADROTOR ) ;
2014-12-18 14:46:31 +01:00
2013-06-09 14:09:09 +02:00
/* check and update system / component ID */
2013-07-28 23:12:16 +04:00
param_get ( _param_system_id , & ( status . system_id ) ) ;
param_get ( _param_component_id , & ( status . component_id ) ) ;
2014-05-25 20:34:32 +02:00
2014-09-30 13:40:03 +02:00
status . circuit_breaker_engaged_power_check =
circuit_breaker_enabled ( " CBRK_SUPPLY_CHK " , CBRK_SUPPLY_CHK_KEY ) ;
status . circuit_breaker_engaged_airspd_check =
circuit_breaker_enabled ( " CBRK_AIRSPD_CHK " , CBRK_AIRSPD_CHK_KEY ) ;
status . circuit_breaker_engaged_enginefailure_check =
circuit_breaker_enabled ( " CBRK_ENGINEFAIL " , CBRK_ENGINEFAIL_KEY ) ;
status . circuit_breaker_engaged_gpsfailure_check =
circuit_breaker_enabled ( " CBRK_GPSFAIL " , CBRK_GPSFAIL_KEY ) ;
2014-05-25 20:34:32 +02:00
2013-07-31 20:58:27 +04:00
status_changed = true ;
2013-08-25 16:33:14 +02:00
2013-08-30 10:11:24 +02:00
/* re-check RC calibration */
2014-07-06 16:51:06 -07:00
rc_calibration_check ( mavlink_fd ) ;
2013-06-09 14:09:09 +02:00
}
2014-05-11 13:36:51 +02:00
2014-02-13 16:08:49 +01:00
/* navigation parameters */
param_get ( _param_takeoff_alt , & takeoff_alt ) ;
2014-12-18 14:46:31 +01:00
/* Safety parameters */
2014-02-13 16:08:49 +01:00
param_get ( _param_enable_parachute , & parachute_enabled ) ;
2014-06-18 19:01:41 +02:00
param_get ( _param_enable_datalink_loss , & datalink_loss_enabled ) ;
2014-07-20 17:53:04 +02:00
param_get ( _param_datalink_loss_timeout , & datalink_loss_timeout ) ;
2014-09-05 12:06:05 +02:00
param_get ( _param_rc_loss_timeout , & rc_loss_timeout ) ;
2014-07-24 08:57:58 +02:00
param_get ( _param_datalink_regain_timeout , & datalink_regain_timeout ) ;
2014-09-05 08:59:00 +02:00
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 ) ;
2014-12-18 14:46:31 +01:00
/* Autostart id */
2014-12-02 10:47:07 +01:00
param_get ( _param_autostart_id , & autostart_id ) ;
2013-06-09 14:09:09 +02:00
}
2013-07-31 20:58:27 +04:00
orb_check ( sp_man_sub , & updated ) ;
2013-01-11 07:42:09 +01:00
2013-07-31 20:58:27 +04:00
if ( updated ) {
2012-09-26 21:30:03 +02:00
orb_copy ( ORB_ID ( manual_control_setpoint ) , sp_man_sub , & sp_man ) ;
}
2013-07-31 20:58:27 +04:00
orb_check ( sp_offboard_sub , & updated ) ;
2013-01-11 07:42:09 +01:00
2013-07-31 20:58:27 +04:00
if ( updated ) {
2012-09-26 21:30:03 +02:00
orb_copy ( ORB_ID ( offboard_control_setpoint ) , sp_offboard_sub , & sp_offboard ) ;
}
2012-12-19 11:34:51 +01:00
2014-06-21 12:24:37 +02:00
if ( sp_offboard . timestamp ! = 0 & &
sp_offboard . timestamp + OFFBOARD_TIMEOUT > hrt_absolute_time ( ) ) {
if ( status . offboard_control_signal_lost ) {
status . offboard_control_signal_lost = false ;
status_changed = true ;
}
2014-10-23 16:17:20 +02:00
2014-06-21 12:24:37 +02:00
} else {
if ( ! status . offboard_control_signal_lost ) {
status . offboard_control_signal_lost = true ;
status_changed = true ;
}
}
2014-07-06 16:08:37 +02:00
for ( int i = 0 ; i < TELEMETRY_STATUS_ORB_ID_NUM ; i + + ) {
orb_check ( telemetry_subs [ i ] , & updated ) ;
2014-06-16 17:34:21 +02:00
2014-07-06 16:08:37 +02:00
if ( updated ) {
struct telemetry_status_s telemetry ;
memset ( & telemetry , 0 , sizeof ( telemetry ) ) ;
orb_copy ( telemetry_status_orb_id [ i ] , telemetry_subs [ i ] , & telemetry ) ;
/* perform system checks when new telemetry link connected */
if ( mavlink_fd & &
2014-10-23 16:17:20 +02:00
telemetry_last_heartbeat [ i ] = = 0 & &
telemetry . heartbeat_time > 0 & &
hrt_elapsed_time ( & telemetry . heartbeat_time ) < datalink_loss_timeout * 1e6 ) {
2014-07-06 16:08:37 +02:00
( void ) rc_calibration_check ( mavlink_fd ) ;
}
telemetry_last_heartbeat [ i ] = telemetry . heartbeat_time ;
}
2014-06-16 17:34:21 +02:00
}
2013-07-31 20:58:27 +04:00
orb_check ( sensor_sub , & updated ) ;
2013-01-11 07:42:09 +01:00
2013-07-31 20:58:27 +04:00
if ( updated ) {
2012-12-19 11:34:51 +01:00
orb_copy ( ORB_ID ( sensor_combined ) , sensor_sub , & sensors ) ;
2014-10-23 16:17:20 +02:00
2014-08-24 13:44:43 +02:00
/* Check if the barometer is healthy and issue a warning in the GCS if not so.
* Because the barometer is used for calculating AMSL altitude which is used to ensure
* vertical separation from other airtraffic the operator has to know when the
* barometer is inoperational .
* */
if ( hrt_elapsed_time ( & sensors . baro_timestamp ) < FAILSAFE_DEFAULT_TIMEOUT ) {
/* handle the case where baro was regained */
if ( status . barometer_failure ) {
status . barometer_failure = false ;
status_changed = true ;
mavlink_log_critical ( mavlink_fd , " baro healthy " ) ;
}
2014-10-23 16:17:20 +02:00
2014-08-24 13:44:43 +02:00
} else {
if ( ! status . barometer_failure ) {
status . barometer_failure = true ;
status_changed = true ;
mavlink_log_critical ( mavlink_fd , " baro failed " ) ;
}
}
2012-12-19 11:34:51 +01:00
}
2012-08-04 15:12:36 -07:00
2013-07-31 20:58:27 +04:00
orb_check ( diff_pres_sub , & updated ) ;
2013-02-25 15:48:16 +01:00
2013-07-31 20:58:27 +04:00
if ( updated ) {
2013-04-19 18:28:06 +02:00
orb_copy ( ORB_ID ( differential_pressure ) , diff_pres_sub , & diff_pres ) ;
2013-02-25 15:48:16 +01:00
}
2014-05-25 08:22:54 +02:00
orb_check ( system_power_sub , & updated ) ;
if ( updated ) {
orb_copy ( ORB_ID ( system_power ) , system_power_sub , & system_power ) ;
if ( hrt_elapsed_time ( & system_power . timestamp ) < 200000 ) {
if ( system_power . servo_valid & &
2014-10-23 16:17:20 +02:00
! system_power . brick_valid & &
! system_power . usb_connected ) {
2014-05-25 08:22:54 +02:00
/* flying only on servo rail, this is unsafe */
status . condition_power_input_valid = false ;
2014-10-23 16:17:20 +02:00
2014-05-25 08:22:54 +02:00
} else {
status . condition_power_input_valid = true ;
}
2014-06-30 14:33:56 +02:00
/* copy avionics voltage */
status . avionics_power_rail_voltage = system_power . voltage5V_v ;
2014-05-25 08:22:54 +02:00
}
}
2013-08-17 12:37:41 +02:00
check_valid ( diff_pres . timestamp , DIFFPRESS_TIMEOUT , true , & ( status . condition_airspeed_valid ) , & status_changed ) ;
2013-08-16 23:36:49 +02:00
2013-06-25 13:15:38 +02:00
/* update safety topic */
2013-07-31 20:58:27 +04:00
orb_check ( safety_sub , & updated ) ;
2013-06-25 13:15:38 +02:00
2013-07-31 20:58:27 +04:00
if ( updated ) {
2015-01-15 11:09:31 +01:00
bool previous_safety_off = safety . safety_off ;
2013-07-15 22:15:15 +02:00
orb_copy ( ORB_ID ( safety ) , safety_sub , & safety ) ;
2013-11-01 09:05:28 +01:00
2014-02-17 22:45:54 +04:00
/* disarm if safety is now on and still armed */
2014-03-03 21:24:59 +04:00
if ( status . hil_state = = HIL_STATE_OFF & & safety . safety_switch_available & & ! safety . safety_off & & armed . armed ) {
2014-10-23 16:17:20 +02:00
arming_state_t new_arming_state = ( status . arming_state = = ARMING_STATE_ARMED ? ARMING_STATE_STANDBY :
ARMING_STATE_STANDBY_ERROR ) ;
2014-05-11 13:36:51 +02:00
2014-10-23 16:17:20 +02:00
if ( TRANSITION_CHANGED = = arming_state_transition ( & status , & safety , new_arming_state , & armed ,
true /* fRunPreArmChecks */ , mavlink_fd ) ) {
2014-07-13 11:43:56 +02:00
mavlink_log_info ( mavlink_fd , " DISARMED by safety switch " ) ;
2014-05-27 21:56:32 +02:00
arming_state_changed = true ;
2014-02-17 22:45:54 +04:00
}
}
2015-01-15 11:09:31 +01:00
//Notify the user if the status of the safety switch changes
2015-01-16 16:46:16 +01:00
if ( safety . safety_switch_available & & previous_safety_off ! = safety . safety_off ) {
2015-01-15 11:09:31 +01:00
2015-01-16 16:46:16 +01:00
if ( safety . safety_off ) {
2015-01-15 11:09:31 +01:00
set_tune ( TONE_NOTIFY_POSITIVE_TUNE ) ;
2015-01-16 16:46:16 +01:00
} else {
2015-01-15 11:09:31 +01:00
tune_neutral ( true ) ;
}
status_changed = true ;
}
2013-06-25 13:15:38 +02:00
}
2014-12-02 10:47:07 +01:00
/* update vtol vehicle status*/
orb_check ( vtol_vehicle_status_sub , & updated ) ;
if ( updated ) {
/* vtol status changed */
orb_copy ( ORB_ID ( vtol_vehicle_status ) , vtol_vehicle_status_sub , & vtol_status ) ;
2014-12-31 16:25:15 +01:00
status . vtol_fw_permanent_stab = vtol_status . fw_permanent_stab ;
2015-01-16 16:46:16 +01:00
2014-12-02 10:47:07 +01:00
/* Make sure that this is only adjusted if vehicle realy is of type vtol*/
2015-01-19 13:22:44 +01:00
if ( ( status . system_type = = VEHICLE_TYPE_VTOL_DUOROTOR ) | | ( status . system_type = = VEHICLE_TYPE_VTOL_QUADROTOR ) ) {
2014-12-02 10:47:07 +01:00
status . is_rotary_wing = vtol_status . vtol_in_rw_mode ;
}
}
2012-12-13 10:23:02 +01:00
/* update global position estimate */
2013-07-31 20:58:27 +04:00
orb_check ( global_position_sub , & updated ) ;
2013-01-11 07:42:09 +01:00
2013-07-31 20:58:27 +04:00
if ( updated ) {
2012-12-13 10:23:02 +01:00
/* position changed */
orb_copy ( ORB_ID ( vehicle_global_position ) , global_position_sub , & global_position ) ;
}
/* update local position estimate */
2013-07-31 20:58:27 +04:00
orb_check ( local_position_sub , & updated ) ;
2013-01-11 07:42:09 +01:00
2013-07-31 20:58:27 +04:00
if ( updated ) {
2012-12-13 10:23:02 +01:00
/* position changed */
orb_copy ( ORB_ID ( vehicle_local_position ) , local_position_sub , & local_position ) ;
}
2013-08-17 12:37:41 +02:00
/* update condition_global_position_valid */
2014-04-07 17:24:39 +04:00
/* hysteresis for EPH/EPV */
2014-07-29 17:50:52 +02:00
bool eph_good ;
2014-05-11 13:36:51 +02:00
2014-04-07 17:16:43 +04:00
if ( status . condition_global_position_valid ) {
2014-07-29 17:50:52 +02:00
if ( global_position . eph > eph_threshold * 2.5f ) {
eph_good = false ;
2014-05-11 13:36:51 +02:00
2014-05-07 08:42:57 +02:00
} else {
2014-07-29 17:50:52 +02:00
eph_good = true ;
2014-04-07 17:16:43 +04:00
}
} else {
2014-07-29 17:50:52 +02:00
if ( global_position . eph < eph_threshold ) {
eph_good = true ;
2014-05-11 13:36:51 +02:00
2014-05-07 08:42:57 +02:00
} else {
2014-07-29 17:50:52 +02:00
eph_good = false ;
2014-04-07 17:16:43 +04:00
}
}
2014-05-11 13:36:51 +02:00
2014-10-23 16:17:20 +02:00
check_valid ( global_position . timestamp , POSITION_TIMEOUT , eph_good , & ( status . condition_global_position_valid ) ,
& status_changed ) ;
2014-03-27 00:27:11 +04:00
2013-08-18 23:05:26 +02:00
/* update condition_local_position_valid and condition_local_altitude_valid */
2014-05-16 22:12:07 +02:00
/* hysteresis for EPH */
bool local_eph_good ;
2014-07-29 17:50:52 +02:00
if ( status . condition_local_position_valid ) {
if ( local_position . eph > eph_threshold * 2.5f ) {
2014-05-16 22:12:07 +02:00
local_eph_good = false ;
} else {
local_eph_good = true ;
}
} else {
2014-07-29 17:50:52 +02:00
if ( local_position . eph < eph_threshold ) {
2014-05-16 22:12:07 +02:00
local_eph_good = true ;
} else {
local_eph_good = false ;
}
}
2014-10-23 16:17:20 +02:00
check_valid ( local_position . timestamp , POSITION_TIMEOUT , local_position . xy_valid
& & local_eph_good , & ( status . condition_local_position_valid ) , & status_changed ) ;
check_valid ( local_position . timestamp , POSITION_TIMEOUT , local_position . z_valid ,
& ( status . condition_local_altitude_valid ) , & status_changed ) ;
2013-08-27 23:08:00 +02:00
2015-01-06 12:25:18 +01:00
/* Update land detector */
orb_check ( land_detector_sub , & updated ) ;
if ( updated ) {
orb_copy ( ORB_ID ( vehicle_land_detected ) , land_detector_sub , & land_detector ) ;
}
2014-04-21 17:36:59 +02:00
if ( status . condition_local_altitude_valid ) {
2015-01-06 12:25:18 +01:00
if ( status . condition_landed ! = land_detector . landed ) {
status . condition_landed = land_detector . landed ;
2013-08-20 12:17:15 +02:00
status_changed = true ;
2013-08-27 23:08:00 +02:00
2013-08-20 12:17:15 +02:00
if ( status . condition_landed ) {
2014-07-13 11:43:56 +02:00
mavlink_log_critical ( mavlink_fd , " LANDED MODE " ) ;
2013-08-27 23:08:00 +02:00
2013-08-20 12:17:15 +02:00
} else {
2014-07-13 11:43:56 +02:00
mavlink_log_critical ( mavlink_fd , " IN AIR MODE " ) ;
2013-08-20 12:17:15 +02:00
}
}
}
2013-03-11 10:39:57 -07:00
2013-01-12 00:38:49 +01:00
/* update battery status */
2013-07-31 20:58:27 +04:00
orb_check ( battery_sub , & updated ) ;
2013-07-28 23:12:16 +04:00
2013-07-31 20:58:27 +04:00
if ( updated ) {
2013-01-01 13:30:24 +01:00
orb_copy ( ORB_ID ( battery_status ) , battery_sub , & battery ) ;
2014-07-19 14:12:33 +02:00
orb_copy ( ORB_ID_VEHICLE_ATTITUDE_CONTROLS , actuator_controls_sub , & actuator_controls ) ;
2014-01-26 11:52:33 +01:00
2013-11-11 22:02:55 +04:00
/* only consider battery voltage if system has been running 2s and battery voltage is valid */
2015-01-16 16:43:11 +01:00
if ( hrt_absolute_time ( ) > commander_boot_timestamp + 2000000 & & battery . voltage_filtered_v > 0.0f ) {
2013-11-11 22:02:55 +04:00
status . battery_voltage = battery . voltage_filtered_v ;
2013-11-08 21:30:10 +04:00
status . battery_current = battery . current_a ;
2013-08-15 17:27:29 +02:00
status . condition_battery_voltage_valid = true ;
2014-07-19 14:12:33 +02:00
/* get throttle (if armed), as we only care about energy negative throttle also counts */
float throttle = ( armed . armed ) ? fabsf ( actuator_controls . control [ 3 ] ) : 0.0f ;
2014-10-23 16:17:20 +02:00
status . battery_remaining = battery_remaining_estimate_voltage ( battery . voltage_filtered_v , battery . discharged_mah ,
throttle ) ;
2013-08-15 17:27:29 +02:00
}
2012-09-05 18:05:11 +02:00
}
2012-08-04 15:12:36 -07:00
2013-07-16 09:24:21 +02:00
/* update subsystem */
2013-07-31 20:58:27 +04:00
orb_check ( subsys_sub , & updated ) ;
2013-07-28 23:12:16 +04:00
2013-07-31 20:58:27 +04:00
if ( updated ) {
2013-07-16 09:24:21 +02:00
orb_copy ( ORB_ID ( subsystem_info ) , subsys_sub , & info ) ;
2015-01-20 22:28:58 +01:00
//warnx("subsystem changed: %d\n", (int)info.subsystem_type);
2013-07-16 09:24:21 +02:00
/* mark / unmark as present */
if ( info . present ) {
2013-07-28 23:12:16 +04:00
status . onboard_control_sensors_present | = info . subsystem_type ;
2013-07-16 09:24:21 +02:00
} else {
2013-07-28 23:12:16 +04:00
status . onboard_control_sensors_present & = ~ info . subsystem_type ;
2013-07-16 09:24:21 +02:00
}
/* mark / unmark as enabled */
if ( info . enabled ) {
2013-07-28 23:12:16 +04:00
status . onboard_control_sensors_enabled | = info . subsystem_type ;
2013-07-16 09:24:21 +02:00
} else {
2013-07-28 23:12:16 +04:00
status . onboard_control_sensors_enabled & = ~ info . subsystem_type ;
2013-07-16 09:24:21 +02:00
}
/* mark / unmark as ok */
if ( info . ok ) {
2013-07-28 23:12:16 +04:00
status . onboard_control_sensors_health | = info . subsystem_type ;
2013-07-16 09:24:21 +02:00
} else {
2013-07-28 23:12:16 +04:00
status . onboard_control_sensors_health & = ~ info . subsystem_type ;
2013-07-16 09:24:21 +02:00
}
2012-08-04 15:12:36 -07:00
2013-07-31 20:58:27 +04:00
status_changed = true ;
2013-02-16 13:40:09 -08:00
}
2012-08-04 15:12:36 -07:00
2014-04-23 19:01:05 +02:00
/* update position setpoint triplet */
2014-04-03 20:23:34 +04:00
orb_check ( pos_sp_triplet_sub , & updated ) ;
if ( updated ) {
orb_copy ( ORB_ID ( position_setpoint_triplet ) , pos_sp_triplet_sub , & pos_sp_triplet ) ;
}
2013-02-16 13:40:09 -08:00
if ( counter % ( 1000000 / COMMANDER_MONITORING_INTERVAL ) = = 0 ) {
/* compute system load */
uint64_t interval_runtime = system_load . tasks [ 0 ] . total_runtime - last_idle_time ;
2012-08-04 15:12:36 -07:00
2014-05-11 13:36:51 +02:00
if ( last_idle_time > 0 ) {
status . load = 1.0f - ( ( float ) interval_runtime / 1e6 f ) ; //system load is time spent in non-idle
}
2012-08-04 15:12:36 -07:00
2013-02-16 13:40:09 -08:00
last_idle_time = system_load . tasks [ 0 ] . total_runtime ;
2013-08-17 15:47:42 +02:00
/* check if board is connected via USB */
2014-10-31 08:58:58 +01:00
struct stat statbuf ;
on_usb_power = ( stat ( " /dev/ttyACM0 " , & statbuf ) = = 0 ) ;
2012-08-04 15:12:36 -07:00
}
2012-09-05 18:05:11 +02:00
/* if battery voltage is getting lower, warn using buzzer, etc. */
2014-07-19 14:34:19 +02:00
if ( status . condition_battery_voltage_valid & & status . battery_remaining < 0.18f & & ! low_battery_voltage_actions_done ) {
2013-11-11 22:02:55 +04:00
low_battery_voltage_actions_done = true ;
2014-07-13 11:43:56 +02:00
mavlink_log_critical ( mavlink_fd , " LOW BATTERY, RETURN TO LAND ADVISED " ) ;
2013-11-11 22:02:55 +04:00
status . battery_warning = VEHICLE_BATTERY_WARNING_LOW ;
status_changed = true ;
2012-09-05 18:05:11 +02:00
2014-10-31 08:58:58 +01:00
} else if ( ! on_usb_power & & status . condition_battery_voltage_valid & & status . battery_remaining < 0.09f
2014-10-23 16:17:20 +02:00
& & ! critical_battery_voltage_actions_done & & low_battery_voltage_actions_done ) {
2013-07-31 20:58:27 +04:00
/* critical battery voltage, this is rather an emergency, change state machine */
2013-11-11 22:02:55 +04:00
critical_battery_voltage_actions_done = true ;
2014-07-13 11:43:56 +02:00
mavlink_log_emergency ( mavlink_fd , " CRITICAL BATTERY, LAND IMMEDIATELY " ) ;
2013-11-11 22:02:55 +04:00
status . battery_warning = VEHICLE_BATTERY_WARNING_CRITICAL ;
2013-08-16 09:27:05 +02:00
2013-11-11 22:02:55 +04:00
if ( armed . armed ) {
2014-10-23 16:17:20 +02:00
arming_ret = arming_state_transition ( & status , & safety , ARMING_STATE_ARMED_ERROR , & armed , true /* fRunPreArmChecks */ ,
mavlink_fd ) ;
2014-05-27 21:56:32 +02:00
if ( arming_ret = = TRANSITION_CHANGED ) {
arming_state_changed = true ;
}
2013-10-21 20:07:47 +02:00
2013-11-11 22:02:55 +04:00
} else {
2014-10-23 16:17:20 +02:00
arming_ret = arming_state_transition ( & status , & safety , ARMING_STATE_STANDBY_ERROR , & armed , true /* fRunPreArmChecks */ ,
mavlink_fd ) ;
2012-09-05 18:05:11 +02:00
2014-05-27 21:56:32 +02:00
if ( arming_ret = = TRANSITION_CHANGED ) {
arming_state_changed = true ;
}
}
2014-10-23 16:17:20 +02:00
2013-11-11 22:02:55 +04:00
status_changed = true ;
2012-09-05 18:05:11 +02:00
}
/* End battery voltage check */
2013-02-18 16:35:34 -08:00
/* If in INIT state, try to proceed to STANDBY state */
2013-07-31 20:58:27 +04:00
if ( status . arming_state = = ARMING_STATE_INIT & & low_prio_task = = LOW_PRIO_TASK_NONE ) {
2014-05-27 21:56:32 +02:00
/* TODO: check for sensors */
2014-10-23 16:17:20 +02:00
arming_ret = arming_state_transition ( & status , & safety , ARMING_STATE_STANDBY , & armed , true /* fRunPreArmChecks */ ,
mavlink_fd ) ;
2014-05-27 21:56:32 +02:00
if ( arming_ret = = TRANSITION_CHANGED ) {
arming_state_changed = true ;
}
2013-07-28 23:12:16 +04:00
2013-02-18 16:35:34 -08:00
} else {
2014-05-27 21:56:32 +02:00
/* TODO: Add emergency stuff if sensors are lost */
2013-02-18 16:35:34 -08:00
}
2012-12-19 14:20:40 +01:00
/*
* Check for valid position information .
*
* If the system has a valid position source from an onboard
* position estimator , it is safe to operate it autonomously .
* The flag_vector_flight_mode_ok flag indicates that a minimum
* set of position measurements is available .
*/
2013-07-31 20:58:27 +04:00
orb_check ( gps_sub , & updated ) ;
2012-12-13 10:23:02 +01:00
2013-07-31 20:58:27 +04:00
if ( updated ) {
2013-01-19 14:46:26 +01:00
orb_copy ( ORB_ID ( vehicle_gps_position ) , gps_sub , & gps_position ) ;
}
2012-08-04 15:12:36 -07:00
2014-05-05 16:42:52 +02:00
/* Initialize map projection if gps is valid */
if ( ! map_projection_global_initialized ( )
2014-10-23 16:17:20 +02:00
& & ( gps_position . eph < eph_threshold )
& & ( gps_position . epv < epv_threshold )
& & hrt_elapsed_time ( ( hrt_abstime * ) & gps_position . timestamp_position ) < 1e6 ) {
2014-05-06 14:43:23 +02:00
/* set reference for global coordinates <--> local coordiantes conversion and map_projection */
2014-10-23 16:17:20 +02:00
globallocalconverter_init ( ( double ) gps_position . lat * 1.0e-7 , ( double ) gps_position . lon * 1.0e-7 ,
( float ) gps_position . alt * 1.0e-3 f , hrt_absolute_time ( ) ) ;
2014-05-05 16:42:52 +02:00
}
2014-09-21 13:32:47 +02:00
/* check if GPS fix is ok */
2014-09-30 13:40:03 +02:00
if ( status . circuit_breaker_engaged_gpsfailure_check | |
2014-10-23 16:17:20 +02:00
( gps_position . fix_type > = 3 & &
hrt_elapsed_time ( & gps_position . timestamp_position ) < FAILSAFE_DEFAULT_TIMEOUT ) ) {
2014-09-21 13:32:47 +02:00
/* handle the case where gps was regained */
if ( status . gps_failure ) {
status . gps_failure = false ;
status_changed = true ;
mavlink_log_critical ( mavlink_fd , " gps regained " ) ;
}
2014-10-23 16:17:20 +02:00
2014-09-21 13:32:47 +02:00
} else {
if ( ! status . gps_failure ) {
status . gps_failure = true ;
status_changed = true ;
mavlink_log_critical ( mavlink_fd , " gps fix lost " ) ;
}
}
2014-07-01 09:34:26 +02:00
/* start mission result check */
2014-05-27 21:56:32 +02:00
orb_check ( mission_result_sub , & updated ) ;
if ( updated ) {
orb_copy ( ORB_ID ( mission_result ) , mission_result_sub , & mission_result ) ;
2014-12-19 22:26:31 +00:00
}
2014-08-24 17:45:15 +02:00
2014-12-19 22:26:31 +00:00
/* start geofence result check */
orb_check ( geofence_result_sub , & updated ) ;
2014-10-23 16:17:20 +02:00
2014-12-19 22:26:31 +00:00
if ( updated ) {
orb_copy ( ORB_ID ( geofence_result ) , geofence_result_sub , & geofence_result ) ;
2014-05-27 21:56:32 +02:00
}
2014-12-19 22:26:31 +00:00
/* 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 */
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 , " GF violation: flight termination " ) ;
flight_termination_printed = true ;
}
if ( counter % ( 1000000 / COMMANDER_MONITORING_INTERVAL ) = = 0 ) {
mavlink_log_critical ( mavlink_fd , " GF violation: flight termination " ) ;
}
} // no reset is done here on purpose, on geofence violation we want to stay in flighttermination
2014-06-16 17:34:21 +02:00
/* RC input check */
2014-09-05 12:06:05 +02:00
if ( ! status . rc_input_blocked & & sp_man . timestamp ! = 0 & &
2014-10-23 16:17:20 +02:00
hrt_absolute_time ( ) < sp_man . timestamp + ( uint64_t ) ( rc_loss_timeout * 1e6 f ) ) {
2014-01-26 14:12:27 +01:00
/* handle the case where RC signal was regained */
if ( ! status . rc_signal_found_once ) {
status . rc_signal_found_once = true ;
2014-07-13 11:43:56 +02:00
mavlink_log_critical ( mavlink_fd , " detected RC signal first time " ) ;
2014-01-26 14:12:27 +01:00
status_changed = true ;
2013-02-20 10:38:06 -08:00
2014-01-26 14:12:27 +01:00
} else {
if ( status . rc_signal_lost ) {
2015-01-16 16:46:16 +01:00
mavlink_log_critical ( mavlink_fd , " RC SIGNAL REGAINED after %llums " ,
( hrt_absolute_time ( ) - status . rc_signal_lost_timestamp ) / 1000 ) ;
2014-01-26 14:12:27 +01:00
status_changed = true ;
2013-02-20 10:38:06 -08:00
}
2014-01-26 14:12:27 +01:00
}
2012-12-27 18:27:08 +01:00
2014-01-26 14:12:27 +01:00
status . rc_signal_lost = false ;
2012-12-27 18:27:08 +01:00
2014-04-29 20:51:04 -07:00
/* check if left stick is in lower left position and we are in MANUAL or AUTO_READY mode or (ASSIST mode and landed) -> disarm
2014-01-26 14:12:27 +01:00
* do it only for rotary wings */
if ( status . is_rotary_wing & &
2014-01-26 15:46:14 +01:00
( status . arming_state = = ARMING_STATE_ARMED | | status . arming_state = = ARMING_STATE_ARMED_ERROR ) & &
2014-05-20 16:42:11 +02:00
( status . main_state = = MAIN_STATE_MANUAL | | status . main_state = = MAIN_STATE_ACRO | | status . condition_landed ) & &
2014-05-12 09:21:27 +02:00
sp_man . r < - STICK_ON_OFF_LIMIT & & sp_man . z < 0.1f ) {
2013-07-31 20:58:27 +04:00
2014-01-26 14:12:27 +01:00
if ( stick_off_counter > STICK_ON_OFF_COUNTER_LIMIT ) {
/* disarm to STANDBY if ARMED or to STANDBY_ERROR if ARMED_ERROR */
2014-10-23 16:17:20 +02:00
arming_state_t new_arming_state = ( status . arming_state = = ARMING_STATE_ARMED ? ARMING_STATE_STANDBY :
ARMING_STATE_STANDBY_ERROR ) ;
arming_ret = arming_state_transition ( & status , & safety , new_arming_state , & armed , true /* fRunPreArmChecks */ ,
mavlink_fd ) ;
2014-05-27 21:56:32 +02:00
if ( arming_ret = = TRANSITION_CHANGED ) {
arming_state_changed = true ;
}
2014-10-23 16:17:20 +02:00
2014-01-26 14:12:27 +01:00
stick_off_counter = 0 ;
2013-08-27 23:08:00 +02:00
2013-08-24 20:31:01 +02:00
} else {
2014-01-26 14:12:27 +01:00
stick_off_counter + + ;
2013-07-22 21:48:21 +04:00
}
2014-01-26 14:12:27 +01:00
} else {
stick_off_counter = 0 ;
}
2013-09-14 08:55:45 +02:00
2014-01-26 14:12:27 +01:00
/* check if left stick is in lower right position and we're in MANUAL mode -> arm */
if ( status . arming_state = = ARMING_STATE_STANDBY & &
2014-05-12 09:21:27 +02:00
sp_man . r > STICK_ON_OFF_LIMIT & & sp_man . z < 0.1f ) {
2014-01-26 14:12:27 +01:00
if ( stick_on_counter > STICK_ON_OFF_COUNTER_LIMIT ) {
2013-09-14 08:55:45 +02:00
2014-06-26 12:14:49 +02:00
/* we check outside of the transition function here because the requirement
* 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 ! = MAIN_STATE_MANUAL ) {
2014-07-13 11:43:56 +02:00
print_reject_arm ( " NOT ARMING: Switch to MANUAL mode first. " ) ;
2014-10-23 16:17:20 +02:00
2013-07-28 23:12:16 +04:00
} else {
2014-10-23 16:17:20 +02:00
arming_ret = arming_state_transition ( & status , & safety , ARMING_STATE_ARMED , & armed , true /* fRunPreArmChecks */ ,
mavlink_fd ) ;
2014-05-27 21:56:32 +02:00
if ( arming_ret = = TRANSITION_CHANGED ) {
arming_state_changed = true ;
}
2013-07-28 23:12:16 +04:00
}
2013-08-24 20:31:01 +02:00
stick_on_counter = 0 ;
2014-01-26 14:12:27 +01:00
} else {
stick_on_counter + + ;
2013-07-28 23:12:16 +04:00
}
2013-02-16 13:40:09 -08:00
2014-01-26 14:12:27 +01:00
} else {
stick_on_counter = 0 ;
}
2013-02-16 13:40:09 -08:00
2014-05-27 21:56:32 +02:00
if ( arming_ret = = TRANSITION_CHANGED ) {
2014-01-26 14:12:27 +01:00
if ( status . arming_state = = ARMING_STATE_ARMED ) {
2014-07-13 11:43:56 +02:00
mavlink_log_info ( mavlink_fd , " ARMED by RC " ) ;
2013-08-16 23:36:49 +02:00
2014-01-26 14:12:27 +01:00
} else {
2014-07-13 11:43:56 +02:00
mavlink_log_info ( mavlink_fd , " DISARMED by RC " ) ;
2013-02-20 10:38:06 -08:00
}
2014-10-23 16:17:20 +02:00
2014-05-27 21:56:32 +02:00
arming_state_changed = true ;
2013-02-20 10:38:06 -08:00
2014-05-27 21:56:32 +02:00
} else if ( arming_ret = = TRANSITION_DENIED ) {
2014-07-20 14:28:05 +02:00
/*
* the arming transition can be denied to a number of reasons :
* - pre - flight check failed ( sensors not ok or not calibrated )
* - safety not disabled
* - system not in manual mode
*/
2014-06-30 16:58:05 +02:00
tune_negative ( true ) ;
2014-01-26 14:12:27 +01:00
}
2014-01-26 11:52:33 +01:00
2014-01-26 14:12:27 +01:00
/* evaluate the main state machine according to mode switches */
2014-05-11 18:10:02 +02:00
transition_result_t main_res = set_main_state_rc ( & status , & sp_man ) ;
2013-07-28 23:12:16 +04:00
2014-02-11 00:24:40 +01:00
/* play tune on mode change only if armed, blink LED always */
2014-05-11 18:10:02 +02:00
if ( main_res = = TRANSITION_CHANGED ) {
2014-02-11 00:24:40 +01:00
tune_positive ( armed . armed ) ;
2014-05-27 21:56:32 +02:00
main_state_changed = true ;
2012-08-04 15:12:36 -07:00
2014-05-11 18:10:02 +02:00
} else if ( main_res = = TRANSITION_DENIED ) {
2014-01-26 14:12:27 +01:00
/* DENIED here indicates bug in the commander */
2014-07-13 11:43:56 +02:00
mavlink_log_critical ( mavlink_fd , " main state transition denied " ) ;
2014-01-26 14:12:27 +01:00
}
2012-08-08 18:47:46 +02:00
2014-01-26 14:12:27 +01:00
} else {
if ( ! status . rc_signal_lost ) {
2015-01-16 16:46:16 +01:00
mavlink_log_critical ( mavlink_fd , " RC SIGNAL LOST (at t=%llums) " , hrt_absolute_time ( ) / 1000 ) ;
2014-01-26 14:12:27 +01:00
status . rc_signal_lost = true ;
2015-01-16 16:46:16 +01:00
status . rc_signal_lost_timestamp = sp_man . timestamp ;
2014-01-26 14:12:27 +01:00
status_changed = true ;
2012-08-08 18:47:46 +02:00
}
2013-12-14 11:03:02 +01:00
}
2014-07-06 16:08:37 +02:00
/* data links check */
bool have_link = false ;
2014-10-23 16:17:20 +02:00
2014-07-06 16:08:37 +02:00
for ( int i = 0 ; i < TELEMETRY_STATUS_ORB_ID_NUM ; i + + ) {
2014-07-24 08:57:58 +02:00
if ( telemetry_last_heartbeat [ i ] ! = 0 & &
2014-10-23 16:17:20 +02:00
hrt_elapsed_time ( & telemetry_last_heartbeat [ i ] ) < datalink_loss_timeout * 1e6 ) {
2014-07-24 08:57:58 +02:00
/* handle the case where data link was regained,
* accept datalink as healthy only after datalink_regain_timeout seconds
* */
if ( telemetry_lost [ i ] & &
2014-10-23 16:17:20 +02:00
hrt_elapsed_time ( & telemetry_last_dl_loss [ i ] ) > datalink_regain_timeout * 1e6 ) {
2014-07-24 08:57:58 +02:00
2014-12-12 22:36:01 +01:00
mavlink_log_info ( mavlink_fd , " data link %i regained " , i ) ;
2014-07-06 16:08:37 +02:00
telemetry_lost [ i ] = false ;
2014-09-13 16:23:28 +02:00
have_link = true ;
2014-10-23 16:17:20 +02:00
2014-09-13 16:23:28 +02:00
} else if ( ! telemetry_lost [ i ] ) {
2014-08-16 10:52:01 +02:00
/* telemetry was healthy also in last iteration
2014-09-13 16:23:28 +02:00
* we don ' t have to check a timeout */
2014-08-16 10:52:01 +02:00
have_link = true ;
2014-07-04 21:00:05 -04:00
}
} else {
2014-07-24 08:57:58 +02:00
telemetry_last_dl_loss [ i ] = hrt_absolute_time ( ) ;
2014-10-23 16:17:20 +02:00
2014-07-06 16:08:37 +02:00
if ( ! telemetry_lost [ i ] ) {
2014-12-12 22:36:01 +01:00
mavlink_log_info ( mavlink_fd , " data link %i lost " , i ) ;
2014-07-06 16:08:37 +02:00
telemetry_lost [ i ] = true ;
2014-07-04 21:00:05 -04:00
}
2013-12-14 11:03:02 +01:00
}
}
2014-07-06 16:08:37 +02:00
if ( have_link ) {
2014-06-18 19:01:41 +02:00
/* handle the case where data link was regained */
2014-06-16 17:34:21 +02:00
if ( status . data_link_lost ) {
status . data_link_lost = false ;
status_changed = true ;
}
} else {
if ( ! status . data_link_lost ) {
2014-12-12 22:36:01 +01:00
mavlink_log_info ( mavlink_fd , " ALL DATA LINKS LOST " ) ;
2014-06-18 19:01:41 +02:00
status . data_link_lost = true ;
2014-07-20 18:23:41 +02:00
status . data_link_lost_counter + + ;
2014-06-16 17:34:21 +02:00
status_changed = true ;
2014-06-06 23:08:11 +02:00
}
}
2014-09-05 08:59:00 +02:00
/* Check engine failure
* only for fixed wing for now
*/
2014-09-30 13:40:03 +02:00
if ( ! status . circuit_breaker_engaged_enginefailure_check & &
2014-10-23 16:17:20 +02:00
status . is_rotary_wing = = false & &
armed . armed & &
( ( actuator_controls . control [ 3 ] > ef_throttle_thres & &
battery . current_a / actuator_controls . control [ 3 ] <
ef_current2throttle_thres ) | |
( status . engine_failure ) ) ) {
2014-09-05 08:59:00 +02:00
/* potential failure, measure time */
if ( timestamp_engine_healthy > 0 & &
2014-10-23 16:17:20 +02:00
hrt_elapsed_time ( & timestamp_engine_healthy ) >
ef_time_thres * 1e6 & &
! status . engine_failure ) {
status . engine_failure = true ;
status_changed = true ;
mavlink_log_critical ( mavlink_fd , " Engine Failure " ) ;
2014-09-05 08:59:00 +02:00
}
2014-10-23 16:17:20 +02:00
2014-09-05 08:59:00 +02:00
} else {
/* no failure reset flag */
timestamp_engine_healthy = hrt_absolute_time ( ) ;
2014-10-23 16:17:20 +02:00
2014-09-05 08:59:00 +02:00
if ( status . engine_failure ) {
status . engine_failure = false ;
status_changed = true ;
}
}
2013-09-22 14:58:06 +02:00
/* handle commands last, as the system needs to be updated to handle them */
orb_check ( cmd_sub , & updated ) ;
if ( updated ) {
/* got command */
orb_copy ( ORB_ID ( vehicle_command ) , cmd_sub , & cmd ) ;
/* handle it */
2014-05-11 13:36:51 +02:00
if ( handle_command ( & status , & safety , & cmd , & armed , & home , & global_position , & home_pub ) ) {
2013-12-29 22:38:22 +04:00
status_changed = true ;
2014-05-11 13:36:51 +02:00
}
2013-07-31 20:58:27 +04:00
}
2013-06-25 13:15:38 +02:00
2014-08-22 21:40:58 +02:00
/* Check for failure combinations which lead to flight termination */
2014-08-23 13:00:28 +02:00
if ( armed . armed ) {
/* At this point the data link and the gps system have been checked
2014-08-26 23:12:28 +02:00
* If we are not in a manual ( RC stick controlled mode )
* and both failed we want to terminate the flight */
if ( status . main_state ! = MAIN_STATE_MANUAL & &
2014-10-23 16:17:20 +02:00
status . main_state ! = MAIN_STATE_ACRO & &
status . main_state ! = MAIN_STATE_ALTCTL & &
status . main_state ! = MAIN_STATE_POSCTL & &
( ( status . data_link_lost & & status . gps_failure ) | |
( status . data_link_lost_cmd & & status . gps_failure_cmd ) ) ) {
2014-08-23 13:00:28 +02:00
armed . force_failsafe = true ;
status_changed = true ;
2014-08-25 23:17:56 +02:00
static bool flight_termination_printed = false ;
2014-10-23 16:17:20 +02:00
2014-08-25 23:17:56 +02:00
if ( ! flight_termination_printed ) {
warnx ( " Flight termination because of data link loss && gps failure " ) ;
2014-09-07 15:29:53 +02:00
mavlink_log_critical ( mavlink_fd , " DL and GPS lost: flight termination " ) ;
2014-08-25 23:17:56 +02:00
flight_termination_printed = true ;
}
2014-10-23 16:17:20 +02:00
if ( counter % ( 1000000 / COMMANDER_MONITORING_INTERVAL ) = = 0 ) {
2014-09-07 15:29:53 +02:00
mavlink_log_critical ( mavlink_fd , " DL and GPS lost: flight termination " ) ;
}
2014-08-23 13:00:28 +02:00
}
2014-08-22 21:02:33 +02:00
2014-08-23 13:00:28 +02:00
/* At this point the rc signal and the gps system have been checked
* If we are in manual ( controlled with RC ) :
* if both failed we want to terminate the flight */
if ( ( status . main_state = = MAIN_STATE_ACRO | |
2014-10-23 16:17:20 +02:00
status . main_state = = MAIN_STATE_MANUAL | |
status . main_state = = MAIN_STATE_ALTCTL | |
status . main_state = = MAIN_STATE_POSCTL ) & &
( ( status . rc_signal_lost & & status . gps_failure ) | |
( status . rc_signal_lost_cmd & & status . gps_failure_cmd ) ) ) {
2014-08-23 13:00:28 +02:00
armed . force_failsafe = true ;
status_changed = true ;
2014-08-25 23:17:56 +02:00
static bool flight_termination_printed = false ;
2014-10-23 16:17:20 +02:00
2014-08-25 23:17:56 +02:00
if ( ! flight_termination_printed ) {
warnx ( " Flight termination because of RC signal loss && gps failure " ) ;
flight_termination_printed = true ;
}
2014-10-23 16:17:20 +02:00
if ( counter % ( 1000000 / COMMANDER_MONITORING_INTERVAL ) = = 0 ) {
2014-09-07 15:29:53 +02:00
mavlink_log_critical ( mavlink_fd , " RC and GPS lost: flight termination " ) ;
}
2014-08-23 13:00:28 +02:00
}
2014-08-22 21:40:58 +02:00
}
2015-01-16 15:51:57 +01:00
//Get current timestamp
const hrt_abstime now = hrt_absolute_time ( ) ;
2013-08-17 12:37:41 +02:00
2015-01-16 16:43:11 +01:00
//First time home position update
2015-01-16 16:46:16 +01:00
if ( ! status . condition_home_position_valid ) {
commander_set_home_position ( home_pub , home , local_position , global_position ) ;
2015-01-16 16:43:11 +01:00
}
/* update home position on arming if at least 2s from commander start spent to avoid setting home on in-air restart */
2015-01-16 16:46:16 +01:00
else if ( arming_state_changed & & armed . armed & & ! was_armed & & now > commander_boot_timestamp + 2000000 ) {
commander_set_home_position ( home_pub , home , local_position , global_position ) ;
2015-01-16 16:43:11 +01:00
}
2014-01-25 23:37:26 +01:00
/* print new state */
if ( arming_state_changed ) {
status_changed = true ;
mavlink_log_info ( mavlink_fd , " [cmd] arming state: %s " , arming_states_str [ status . arming_state ] ) ;
2014-05-27 21:56:32 +02:00
arming_state_changed = false ;
2014-01-25 23:37:26 +01:00
}
2014-05-11 13:36:51 +02:00
2014-04-02 11:57:41 +04:00
was_armed = armed . armed ;
2014-01-25 23:37:26 +01:00
2014-06-16 17:34:21 +02:00
/* now set navigation state according to failsafe and main state */
2014-06-18 19:01:41 +02:00
bool nav_state_changed = set_nav_state ( & status , ( bool ) datalink_loss_enabled ,
2014-07-23 22:58:19 +02:00
mission_result . finished ,
mission_result . stay_in_failsafe ) ;
2014-05-27 21:56:32 +02:00
2014-06-17 13:19:50 +02:00
// TODO handle mode changes by commands
2014-01-25 23:37:26 +01:00
if ( main_state_changed ) {
status_changed = true ;
2014-06-17 13:19:50 +02:00
warnx ( " main state: %s " , main_states_str [ status . main_state ] ) ;
2014-01-25 23:37:26 +01:00
mavlink_log_info ( mavlink_fd , " [cmd] main state: %s " , main_states_str [ status . main_state ] ) ;
2014-05-27 21:56:32 +02:00
main_state_changed = false ;
2014-01-25 23:37:26 +01:00
}
2014-06-17 13:19:50 +02:00
if ( status . failsafe ! = failsafe_old ) {
2013-10-07 22:16:57 +02:00
status_changed = true ;
2015-01-16 16:46:16 +01:00
2014-11-10 21:38:46 +10:00
if ( status . failsafe ) {
2014-11-11 09:18:31 +10:00
mavlink_log_critical ( mavlink_fd , " failsafe mode on " ) ;
2015-01-16 16:46:16 +01:00
2014-11-10 21:38:46 +10:00
} else {
2014-11-11 09:18:31 +10:00
mavlink_log_critical ( mavlink_fd , " failsafe mode off " ) ;
2014-11-10 21:38:46 +10:00
}
2015-01-16 16:46:16 +01:00
2014-06-17 13:19:50 +02:00
failsafe_old = status . failsafe ;
}
if ( nav_state_changed ) {
status_changed = true ;
warnx ( " nav state: %s " , nav_states_str [ status . nav_state ] ) ;
mavlink_log_info ( mavlink_fd , " [cmd] nav state: %s " , nav_states_str [ status . nav_state ] ) ;
2013-07-31 20:58:27 +04:00
}
2013-03-26 10:44:49 -07:00
2013-08-18 12:42:24 +02:00
/* publish states (armed, control mode, vehicle status) at least with 5 Hz */
if ( counter % ( 200000 / COMMANDER_MONITORING_INTERVAL ) = = 0 | | status_changed ) {
2014-01-27 20:49:17 +01:00
set_control_mode ( ) ;
2015-01-16 15:51:57 +01:00
control_mode . timestamp = now ;
2014-01-27 20:49:17 +01:00
orb_publish ( ORB_ID ( vehicle_control_mode ) , control_mode_pub , & control_mode ) ;
2015-01-16 15:51:57 +01:00
status . timestamp = now ;
2013-07-28 23:12:16 +04:00
orb_publish ( ORB_ID ( vehicle_status ) , status_pub , & status ) ;
2014-01-27 20:49:17 +01:00
2015-01-16 15:51:57 +01:00
armed . timestamp = now ;
2013-08-18 12:42:24 +02:00
orb_publish ( ORB_ID ( actuator_armed ) , armed_pub , & armed ) ;
2012-08-16 15:49:56 +02:00
}
2013-07-31 20:58:27 +04:00
/* play arming and battery warning tunes */
2014-10-23 16:17:20 +02:00
if ( ! arm_tune_played & & armed . armed & & ( ! safety . safety_switch_available | | ( safety . safety_switch_available
& & safety . safety_off ) ) ) {
2013-07-31 20:58:27 +04:00
/* play tune when armed */
2014-02-11 00:24:40 +01:00
set_tune ( TONE_ARMING_WARNING_TUNE ) ;
2014-02-11 18:24:20 +01:00
arm_tune_played = true ;
2013-07-28 23:12:16 +04:00
2013-08-29 16:41:59 +02:00
} else if ( status . battery_warning = = VEHICLE_BATTERY_WARNING_CRITICAL ) {
2013-07-31 20:58:27 +04:00
/* play tune on battery critical */
2014-02-11 00:24:40 +01:00
set_tune ( TONE_BATTERY_WARNING_FAST_TUNE ) ;
2013-07-28 23:12:16 +04:00
2014-06-16 17:34:21 +02:00
} else if ( status . battery_warning = = VEHICLE_BATTERY_WARNING_LOW | | status . failsafe ) {
2014-02-11 09:13:51 +01:00
/* play tune on battery warning or failsafe */
set_tune ( TONE_BATTERY_WARNING_SLOW_TUNE ) ;
2013-07-28 23:12:16 +04:00
2014-02-11 18:24:20 +01:00
} else {
2014-02-11 00:24:40 +01:00
set_tune ( TONE_STOP_TUNE ) ;
2013-06-25 13:15:38 +02:00
}
/* reset arm_tune_played when disarmed */
2014-02-11 18:24:20 +01:00
if ( ! armed . armed | | ( safety . safety_switch_available & & ! safety . safety_off ) ) {
2015-01-15 11:09:31 +01:00
//Notify the user that it is safe to approach the vehicle
2015-01-16 16:46:16 +01:00
if ( arm_tune_played ) {
2015-01-15 11:09:31 +01:00
tune_neutral ( true ) ;
}
2013-06-25 13:15:38 +02:00
arm_tune_played = false ;
}
2012-08-04 15:12:36 -07:00
fflush ( stdout ) ;
counter + + ;
2013-08-16 18:05:59 +02:00
2013-09-19 19:58:41 +02:00
int blink_state = blink_msg_state ( ) ;
2013-10-21 20:07:47 +02:00
2013-09-19 19:58:41 +02:00
if ( blink_state > 0 ) {
/* blinking LED message, don't touch LEDs */
if ( blink_state = = 2 ) {
/* blinking LED message completed, restore normal state */
control_status_leds ( & status , & armed , true ) ;
}
2013-10-21 20:07:47 +02:00
2013-09-19 19:58:41 +02:00
} else {
/* normal state */
control_status_leds ( & status , & armed , status_changed ) ;
}
status_changed = false ;
2013-08-16 18:05:59 +02:00
2012-08-04 15:12:36 -07:00
usleep ( COMMANDER_MONITORING_INTERVAL ) ;
}
/* wait for threads to complete */
2013-09-08 20:05:15 +02:00
ret = pthread_join ( commander_low_prio_thread , NULL ) ;
2013-09-14 08:55:45 +02:00
2013-09-08 20:05:15 +02:00
if ( ret ) {
2013-10-21 20:07:47 +02:00
warn ( " join failed: %d " , ret ) ;
2013-09-08 20:05:15 +02:00
}
rgbled_set_mode ( RGBLED_MODE_OFF ) ;
2012-08-04 15:12:36 -07:00
/* close fds */
led_deinit ( ) ;
buzzer_deinit ( ) ;
2012-09-21 12:55:41 +02:00
close ( sp_man_sub ) ;
close ( sp_offboard_sub ) ;
2013-07-16 10:05:51 +02:00
close ( local_position_sub ) ;
2012-12-13 10:23:02 +01:00
close ( global_position_sub ) ;
2013-07-16 10:05:51 +02:00
close ( gps_sub ) ;
2012-08-24 00:01:23 +02:00
close ( sensor_sub ) ;
2013-07-15 22:15:15 +02:00
close ( safety_sub ) ;
2012-10-15 08:52:41 +02:00
close ( cmd_sub ) ;
2013-07-16 09:24:21 +02:00
close ( subsys_sub ) ;
2013-07-16 10:05:51 +02:00
close ( diff_pres_sub ) ;
close ( param_changed_sub ) ;
close ( battery_sub ) ;
2014-06-14 23:57:29 +02:00
close ( mission_pub ) ;
2012-08-24 00:01:23 +02:00
2012-08-20 23:52:13 +02:00
thread_running = false ;
2012-08-04 15:12:36 -07:00
return 0 ;
}
2013-03-25 14:53:54 -07:00
2013-08-19 09:53:00 +02:00
void
check_valid ( hrt_abstime timestamp , hrt_abstime timeout , bool valid_in , bool * valid_out , bool * changed )
{
hrt_abstime t = hrt_absolute_time ( ) ;
bool valid_new = ( t < timestamp + timeout & & t > timeout & & valid_in ) ;
if ( * valid_out ! = valid_new ) {
* valid_out = valid_new ;
* changed = true ;
}
}
2013-07-31 20:58:27 +04:00
void
2014-07-13 11:44:27 +02:00
control_status_leds ( vehicle_status_s * status_local , const actuator_armed_s * actuator_armed , bool changed )
2013-07-31 20:58:27 +04:00
{
2013-09-19 19:58:41 +02:00
/* driving rgbled */
if ( changed ) {
bool set_normal_color = false ;
2013-10-21 20:07:47 +02:00
2013-09-19 19:58:41 +02:00
/* set mode */
2014-07-13 11:44:27 +02:00
if ( status_local - > arming_state = = ARMING_STATE_ARMED ) {
2013-09-19 19:58:41 +02:00
rgbled_set_mode ( RGBLED_MODE_ON ) ;
set_normal_color = true ;
2014-07-13 11:44:27 +02:00
} else if ( status_local - > arming_state = = ARMING_STATE_ARMED_ERROR ) {
2013-09-19 19:58:41 +02:00
rgbled_set_mode ( RGBLED_MODE_BLINK_FAST ) ;
rgbled_set_color ( RGBLED_COLOR_RED ) ;
2014-07-13 11:44:27 +02:00
} else if ( status_local - > arming_state = = ARMING_STATE_STANDBY ) {
2013-09-19 19:58:41 +02:00
rgbled_set_mode ( RGBLED_MODE_BREATHE ) ;
set_normal_color = true ;
} else { // STANDBY_ERROR and other states
rgbled_set_mode ( RGBLED_MODE_BLINK_NORMAL ) ;
rgbled_set_color ( RGBLED_COLOR_RED ) ;
}
if ( set_normal_color ) {
/* set color */
2014-07-13 11:44:27 +02:00
if ( status_local - > battery_warning = = VEHICLE_BATTERY_WARNING_LOW | | status_local - > failsafe ) {
2014-02-11 09:13:51 +01:00
rgbled_set_color ( RGBLED_COLOR_AMBER ) ;
2013-09-19 19:58:41 +02:00
/* VEHICLE_BATTERY_WARNING_CRITICAL handled as ARMING_STATE_ARMED_ERROR / ARMING_STATE_STANDBY_ERROR */
} else {
2014-07-13 11:44:27 +02:00
if ( status_local - > condition_local_position_valid ) {
2013-09-19 19:58:41 +02:00
rgbled_set_color ( RGBLED_COLOR_GREEN ) ;
} else {
rgbled_set_color ( RGBLED_COLOR_BLUE ) ;
}
}
}
}
2013-08-16 18:05:59 +02:00
# ifdef CONFIG_ARCH_BOARD_PX4FMU_V1
2013-08-27 23:08:00 +02:00
2013-08-16 18:05:59 +02:00
/* this runs at around 20Hz, full cycle is 16 ticks = 10/16Hz */
2013-11-01 09:05:28 +01:00
if ( actuator_armed - > armed ) {
2013-08-16 18:05:59 +02:00
/* armed, solid */
led_on ( LED_BLUE ) ;
2013-11-01 09:05:28 +01:00
} else if ( actuator_armed - > ready_to_arm ) {
2013-08-16 18:05:59 +02:00
/* ready to arm, blink at 1Hz */
2014-05-11 13:36:51 +02:00
if ( leds_counter % 20 = = 0 ) {
2013-08-16 18:05:59 +02:00
led_toggle ( LED_BLUE ) ;
2014-05-11 13:36:51 +02:00
}
2013-08-27 23:08:00 +02:00
2013-08-16 18:05:59 +02:00
} else {
/* not ready to arm, blink at 10Hz */
2014-05-11 13:36:51 +02:00
if ( leds_counter % 2 = = 0 ) {
2013-08-16 18:05:59 +02:00
led_toggle ( LED_BLUE ) ;
2014-05-11 13:36:51 +02:00
}
2013-08-16 18:05:59 +02:00
}
2013-08-27 23:08:00 +02:00
2013-08-16 18:05:59 +02:00
# endif
/* give system warnings on error LED, XXX maybe add memory usage warning too */
2014-07-13 11:44:27 +02:00
if ( status_local - > load > 0.95f ) {
2014-05-11 13:36:51 +02:00
if ( leds_counter % 2 = = 0 ) {
2013-08-16 18:05:59 +02:00
led_toggle ( LED_AMBER ) ;
2014-05-11 13:36:51 +02:00
}
2013-08-27 23:08:00 +02:00
2013-08-16 18:05:59 +02:00
} else {
led_off ( LED_AMBER ) ;
2013-07-31 20:58:27 +04:00
}
leds_counter + + ;
}
2013-07-28 23:12:16 +04:00
transition_result_t
2014-07-13 11:45:02 +02:00
set_main_state_rc ( struct vehicle_status_s * status_local , struct manual_control_setpoint_s * sp_man )
2013-07-28 23:12:16 +04:00
{
2014-01-27 20:49:17 +01:00
/* set main state according to RC switches */
2013-07-28 23:12:16 +04:00
transition_result_t res = TRANSITION_DENIED ;
2014-07-16 09:38:57 +02:00
/* if offboard is set allready by a mavlink command, abort */
if ( status . offboard_control_set_by_command ) {
return main_state_transition ( status_local , MAIN_STATE_OFFBOARD ) ;
}
2014-01-29 21:21:16 +01:00
/* offboard switch overrides main switch */
2014-05-16 12:12:43 +02:00
if ( sp_man - > offboard_switch = = SWITCH_POS_ON ) {
2014-07-13 11:45:02 +02:00
res = main_state_transition ( status_local , MAIN_STATE_OFFBOARD ) ;
2014-10-23 16:17:20 +02:00
2014-01-29 21:21:16 +01:00
if ( res = = TRANSITION_DENIED ) {
2014-07-13 11:45:02 +02:00
print_reject_mode ( status_local , " OFFBOARD " ) ;
2013-07-28 23:12:16 +04:00
2014-01-29 21:21:16 +01:00
} else {
return res ;
}
}
2013-07-28 23:12:16 +04:00
2014-05-16 12:12:43 +02:00
/* offboard switched off or denied, check main mode switch */
2014-04-03 20:23:34 +04:00
switch ( sp_man - > mode_switch ) {
case SWITCH_POS_NONE :
2014-04-06 20:04:18 +04:00
res = TRANSITION_NOT_CHANGED ;
break ;
2014-04-03 20:23:34 +04:00
case SWITCH_POS_OFF : // MANUAL
2014-05-20 00:03:00 +02:00
if ( sp_man - > acro_switch = = SWITCH_POS_ON ) {
2014-07-13 11:45:02 +02:00
res = main_state_transition ( status_local , MAIN_STATE_ACRO ) ;
2014-05-20 00:03:00 +02:00
2014-01-31 22:44:05 +01:00
} else {
2014-07-13 11:45:02 +02:00
res = main_state_transition ( status_local , MAIN_STATE_MANUAL ) ;
2014-01-31 22:44:05 +01:00
}
2014-10-23 16:17:20 +02:00
2013-07-28 23:12:16 +04:00
// TRANSITION_DENIED is not possible here
break ;
2014-04-29 20:51:04 -07:00
case SWITCH_POS_MIDDLE : // ASSIST
2014-05-11 13:35:05 +02:00
if ( sp_man - > posctl_switch = = SWITCH_POS_ON ) {
2014-07-13 11:45:02 +02:00
res = main_state_transition ( status_local , MAIN_STATE_POSCTL ) ;
2013-07-28 23:12:16 +04:00
2014-04-03 20:23:34 +04:00
if ( res ! = TRANSITION_DENIED ) {
2013-07-28 23:12:16 +04:00
break ; // changed successfully or already in this state
2014-04-03 20:23:34 +04:00
}
2013-07-28 23:12:16 +04:00
2014-07-13 11:45:02 +02:00
print_reject_mode ( status_local , " POSCTL " ) ;
2013-07-28 23:12:16 +04:00
}
2014-10-23 16:17:20 +02:00
// fallback to ALTCTL
2014-07-13 11:45:02 +02:00
res = main_state_transition ( status_local , MAIN_STATE_ALTCTL ) ;
2013-07-28 23:12:16 +04:00
2014-04-03 20:23:34 +04:00
if ( res ! = TRANSITION_DENIED ) {
2013-07-28 23:12:16 +04:00
break ; // changed successfully or already in this mode
2014-04-03 20:23:34 +04:00
}
2013-07-28 23:12:16 +04:00
2014-05-11 13:35:05 +02:00
if ( sp_man - > posctl_switch ! = SWITCH_POS_ON ) {
2014-07-13 11:45:02 +02:00
print_reject_mode ( status_local , " ALTCTL " ) ;
2014-04-03 20:23:34 +04:00
}
2013-07-31 20:58:27 +04:00
2014-06-25 17:56:11 +02:00
// fallback to MANUAL
2014-07-13 11:45:02 +02:00
res = main_state_transition ( status_local , MAIN_STATE_MANUAL ) ;
2013-07-28 23:12:16 +04:00
// TRANSITION_DENIED is not possible here
break ;
2014-04-03 20:23:34 +04:00
case SWITCH_POS_ON : // AUTO
2014-05-27 23:24:01 +02:00
if ( sp_man - > return_switch = = SWITCH_POS_ON ) {
2014-07-13 11:45:02 +02:00
res = main_state_transition ( status_local , MAIN_STATE_AUTO_RTL ) ;
2013-07-28 23:12:16 +04:00
2014-05-27 23:24:01 +02:00
if ( res ! = TRANSITION_DENIED ) {
break ; // changed successfully or already in this state
}
2014-06-25 17:56:11 +02:00
2014-10-23 16:17:20 +02:00
print_reject_mode ( status_local , " AUTO_RTL " ) ;
2014-06-25 17:56:11 +02:00
2014-10-23 16:17:20 +02:00
// fallback to LOITER if home position not set
res = main_state_transition ( status_local , MAIN_STATE_AUTO_LOITER ) ;
2014-06-25 17:56:11 +02:00
2014-10-23 16:17:20 +02:00
if ( res ! = TRANSITION_DENIED ) {
break ; // changed successfully or already in this state
}
2014-06-25 17:56:11 +02:00
2014-05-27 23:24:01 +02:00
} else if ( sp_man - > loiter_switch = = SWITCH_POS_ON ) {
2014-07-13 11:45:02 +02:00
res = main_state_transition ( status_local , MAIN_STATE_AUTO_LOITER ) ;
2014-05-27 23:24:01 +02:00
if ( res ! = TRANSITION_DENIED ) {
break ; // changed successfully or already in this state
}
2014-06-25 17:56:11 +02:00
2014-10-23 16:17:20 +02:00
print_reject_mode ( status_local , " AUTO_LOITER " ) ;
2014-06-25 17:56:11 +02:00
2014-05-27 23:24:01 +02:00
} else {
2014-07-13 11:45:02 +02:00
res = main_state_transition ( status_local , MAIN_STATE_AUTO_MISSION ) ;
2014-05-27 23:24:01 +02:00
if ( res ! = TRANSITION_DENIED ) {
break ; // changed successfully or already in this state
}
2014-06-25 17:56:11 +02:00
2014-10-23 16:17:20 +02:00
print_reject_mode ( status_local , " AUTO_MISSION " ) ;
2014-07-06 21:37:26 +02:00
2014-10-23 16:17:20 +02:00
// fallback to LOITER if home position not set
res = main_state_transition ( status_local , MAIN_STATE_AUTO_LOITER ) ;
2014-07-06 21:37:26 +02:00
2014-10-23 16:17:20 +02:00
if ( res ! = TRANSITION_DENIED ) {
break ; // changed successfully or already in this state
}
2014-04-03 20:23:34 +04:00
}
2013-07-28 23:12:16 +04:00
2014-10-23 16:17:20 +02:00
// fallback to POSCTL
res = main_state_transition ( status_local , MAIN_STATE_POSCTL ) ;
2014-06-25 17:56:11 +02:00
2014-10-23 16:17:20 +02:00
if ( res ! = TRANSITION_DENIED ) {
break ; // changed successfully or already in this state
}
2014-06-25 17:56:11 +02:00
// fallback to ALTCTL
2014-07-13 11:45:02 +02:00
res = main_state_transition ( status_local , MAIN_STATE_ALTCTL ) ;
2013-07-28 23:12:16 +04:00
2014-04-03 20:23:34 +04:00
if ( res ! = TRANSITION_DENIED ) {
2013-07-28 23:12:16 +04:00
break ; // changed successfully or already in this state
2014-04-03 20:23:34 +04:00
}
2013-07-28 23:12:16 +04:00
2014-06-25 17:56:11 +02:00
// fallback to MANUAL
2014-07-13 11:45:02 +02:00
res = main_state_transition ( status_local , MAIN_STATE_MANUAL ) ;
2013-07-28 23:12:16 +04:00
// TRANSITION_DENIED is not possible here
break ;
default :
break ;
}
return res ;
}
2014-01-27 20:49:17 +01:00
void
set_control_mode ( )
{
2014-05-27 21:56:32 +02:00
/* set vehicle_control_mode according to set_navigation_state */
2014-01-27 20:49:17 +01:00
control_mode . flag_armed = armed . armed ;
2014-12-23 21:50:16 +01:00
control_mode . flag_external_manual_override_ok = ( ! status . is_rotary_wing & & ! status . is_vtol ) ;
2014-01-27 20:49:17 +01:00
control_mode . flag_system_hil_enabled = status . hil_state = = HIL_STATE_ON ;
2014-02-17 16:50:00 +04:00
control_mode . flag_control_offboard_enabled = false ;
2014-01-27 20:49:17 +01:00
2014-06-16 17:34:21 +02:00
switch ( status . nav_state ) {
2014-05-27 21:56:32 +02:00
case NAVIGATION_STATE_MANUAL :
control_mode . flag_control_manual_enabled = true ;
control_mode . flag_control_auto_enabled = false ;
2014-12-31 16:25:15 +01:00
control_mode . flag_control_rates_enabled = ( status . is_rotary_wing | | status . vtol_fw_permanent_stab ) ;
control_mode . flag_control_attitude_enabled = ( status . is_rotary_wing | | status . vtol_fw_permanent_stab ) ;
2014-05-27 21:56:32 +02:00
control_mode . flag_control_altitude_enabled = false ;
control_mode . flag_control_climb_rate_enabled = false ;
control_mode . flag_control_position_enabled = false ;
control_mode . flag_control_velocity_enabled = false ;
control_mode . flag_control_termination_enabled = false ;
break ;
2014-12-04 14:23:19 +01:00
2014-05-27 21:56:32 +02:00
case NAVIGATION_STATE_ALTCTL :
control_mode . flag_control_manual_enabled = true ;
control_mode . flag_control_auto_enabled = false ;
control_mode . flag_control_rates_enabled = true ;
control_mode . flag_control_attitude_enabled = true ;
control_mode . flag_control_altitude_enabled = true ;
control_mode . flag_control_climb_rate_enabled = true ;
control_mode . flag_control_position_enabled = false ;
control_mode . flag_control_velocity_enabled = false ;
control_mode . flag_control_termination_enabled = false ;
break ;
2014-01-27 20:49:17 +01:00
2014-05-27 21:56:32 +02:00
case NAVIGATION_STATE_POSCTL :
control_mode . flag_control_manual_enabled = true ;
control_mode . flag_control_auto_enabled = false ;
control_mode . flag_control_rates_enabled = true ;
control_mode . flag_control_attitude_enabled = true ;
control_mode . flag_control_altitude_enabled = true ;
control_mode . flag_control_climb_rate_enabled = true ;
control_mode . flag_control_position_enabled = true ;
control_mode . flag_control_velocity_enabled = true ;
control_mode . flag_control_termination_enabled = false ;
2014-01-27 20:49:17 +01:00
break ;
2014-05-27 21:56:32 +02:00
case NAVIGATION_STATE_AUTO_MISSION :
case NAVIGATION_STATE_AUTO_LOITER :
case NAVIGATION_STATE_AUTO_RTL :
2014-11-13 09:44:17 +10:00
case NAVIGATION_STATE_AUTO_RCRECOVER :
2014-06-19 10:26:56 +02:00
case NAVIGATION_STATE_AUTO_RTGS :
2014-08-22 00:40:45 +02:00
case NAVIGATION_STATE_AUTO_LANDENGFAIL :
2014-05-27 21:56:32 +02:00
control_mode . flag_control_manual_enabled = false ;
control_mode . flag_control_auto_enabled = true ;
control_mode . flag_control_rates_enabled = true ;
control_mode . flag_control_attitude_enabled = true ;
control_mode . flag_control_altitude_enabled = true ;
control_mode . flag_control_climb_rate_enabled = true ;
control_mode . flag_control_position_enabled = true ;
control_mode . flag_control_velocity_enabled = true ;
control_mode . flag_control_termination_enabled = false ;
2014-01-27 20:49:17 +01:00
break ;
2014-08-22 00:40:45 +02:00
case NAVIGATION_STATE_AUTO_LANDGPSFAIL :
control_mode . flag_control_manual_enabled = false ;
control_mode . flag_control_auto_enabled = false ;
control_mode . flag_control_rates_enabled = true ;
control_mode . flag_control_attitude_enabled = true ;
control_mode . flag_control_altitude_enabled = false ;
control_mode . flag_control_climb_rate_enabled = true ;
control_mode . flag_control_position_enabled = false ;
control_mode . flag_control_velocity_enabled = false ;
control_mode . flag_control_termination_enabled = false ;
break ;
2014-11-13 09:43:51 +10:00
case NAVIGATION_STATE_ACRO :
control_mode . flag_control_manual_enabled = true ;
control_mode . flag_control_auto_enabled = false ;
control_mode . flag_control_rates_enabled = true ;
control_mode . flag_control_attitude_enabled = false ;
control_mode . flag_control_altitude_enabled = false ;
control_mode . flag_control_climb_rate_enabled = false ;
control_mode . flag_control_position_enabled = false ;
control_mode . flag_control_velocity_enabled = false ;
control_mode . flag_control_termination_enabled = false ;
break ;
2014-05-27 21:56:32 +02:00
case NAVIGATION_STATE_LAND :
control_mode . flag_control_manual_enabled = false ;
control_mode . flag_control_auto_enabled = true ;
control_mode . flag_control_rates_enabled = true ;
control_mode . flag_control_attitude_enabled = true ;
/* in failsafe LAND mode position may be not available */
control_mode . flag_control_position_enabled = status . condition_local_position_valid ;
control_mode . flag_control_velocity_enabled = status . condition_local_position_valid ;
control_mode . flag_control_altitude_enabled = true ;
control_mode . flag_control_climb_rate_enabled = true ;
control_mode . flag_control_termination_enabled = false ;
2014-01-27 20:49:17 +01:00
break ;
2014-11-13 09:43:51 +10:00
case NAVIGATION_STATE_DESCEND :
/* TODO: check if this makes sense */
control_mode . flag_control_manual_enabled = false ;
control_mode . flag_control_auto_enabled = true ;
control_mode . flag_control_rates_enabled = true ;
control_mode . flag_control_attitude_enabled = true ;
control_mode . flag_control_position_enabled = false ;
control_mode . flag_control_velocity_enabled = false ;
control_mode . flag_control_altitude_enabled = false ;
control_mode . flag_control_climb_rate_enabled = true ;
control_mode . flag_control_termination_enabled = false ;
break ;
2014-05-27 21:56:32 +02:00
case NAVIGATION_STATE_TERMINATION :
2014-01-27 20:49:17 +01:00
/* disable all controllers on termination */
control_mode . flag_control_manual_enabled = false ;
control_mode . flag_control_auto_enabled = false ;
control_mode . flag_control_rates_enabled = false ;
control_mode . flag_control_attitude_enabled = false ;
control_mode . flag_control_position_enabled = false ;
control_mode . flag_control_velocity_enabled = false ;
control_mode . flag_control_altitude_enabled = false ;
control_mode . flag_control_climb_rate_enabled = false ;
control_mode . flag_control_termination_enabled = true ;
break ;
2014-11-13 09:43:51 +10:00
case NAVIGATION_STATE_OFFBOARD :
control_mode . flag_control_manual_enabled = false ;
control_mode . flag_control_auto_enabled = false ;
control_mode . flag_control_offboard_enabled = true ;
switch ( sp_offboard . mode ) {
case OFFBOARD_CONTROL_MODE_DIRECT_RATES :
control_mode . flag_control_rates_enabled = true ;
control_mode . flag_control_attitude_enabled = false ;
control_mode . flag_control_altitude_enabled = false ;
control_mode . flag_control_climb_rate_enabled = false ;
control_mode . flag_control_position_enabled = false ;
control_mode . flag_control_velocity_enabled = false ;
break ;
case OFFBOARD_CONTROL_MODE_DIRECT_ATTITUDE :
control_mode . flag_control_rates_enabled = true ;
control_mode . flag_control_attitude_enabled = true ;
control_mode . flag_control_altitude_enabled = false ;
control_mode . flag_control_climb_rate_enabled = false ;
control_mode . flag_control_position_enabled = false ;
control_mode . flag_control_velocity_enabled = false ;
break ;
case OFFBOARD_CONTROL_MODE_DIRECT_FORCE :
control_mode . flag_control_rates_enabled = true ;
control_mode . flag_control_attitude_enabled = false ;
control_mode . flag_control_force_enabled = true ;
control_mode . flag_control_altitude_enabled = false ;
control_mode . flag_control_climb_rate_enabled = false ;
control_mode . flag_control_position_enabled = false ;
control_mode . flag_control_velocity_enabled = false ;
break ;
case OFFBOARD_CONTROL_MODE_DIRECT_LOCAL_NED :
case OFFBOARD_CONTROL_MODE_DIRECT_LOCAL_OFFSET_NED :
case OFFBOARD_CONTROL_MODE_DIRECT_BODY_NED :
case OFFBOARD_CONTROL_MODE_DIRECT_BODY_OFFSET_NED :
control_mode . flag_control_rates_enabled = true ;
control_mode . flag_control_attitude_enabled = true ;
control_mode . flag_control_altitude_enabled = true ;
control_mode . flag_control_climb_rate_enabled = true ;
control_mode . flag_control_position_enabled = true ;
control_mode . flag_control_velocity_enabled = true ;
//XXX: the flags could depend on sp_offboard.ignore
break ;
default :
control_mode . flag_control_rates_enabled = false ;
control_mode . flag_control_attitude_enabled = false ;
control_mode . flag_control_altitude_enabled = false ;
control_mode . flag_control_climb_rate_enabled = false ;
control_mode . flag_control_position_enabled = false ;
control_mode . flag_control_velocity_enabled = false ;
}
2015-01-16 16:46:16 +01:00
2014-11-13 09:43:51 +10:00
break ;
2014-01-27 20:49:17 +01:00
default :
break ;
}
}
2013-07-31 20:58:27 +04:00
void
2014-07-13 11:43:56 +02:00
print_reject_mode ( struct vehicle_status_s * status_local , const char * msg )
2013-07-31 20:58:27 +04:00
{
hrt_abstime t = hrt_absolute_time ( ) ;
if ( t - last_print_mode_reject_time > PRINT_MODE_REJECT_INTERVAL ) {
last_print_mode_reject_time = t ;
2014-07-13 11:43:56 +02:00
mavlink_log_critical ( mavlink_fd , " REJECT %s " , msg ) ;
2014-02-01 13:21:51 +01:00
2014-02-11 00:24:40 +01:00
/* only buzz if armed, because else we're driving people nuts indoors
they really need to look at the leds as well . */
tune_negative ( armed . armed ) ;
2013-07-31 20:58:27 +04:00
}
}
2013-08-16 09:23:39 +02:00
void
print_reject_arm ( const char * msg )
{
hrt_abstime t = hrt_absolute_time ( ) ;
if ( t - last_print_mode_reject_time > PRINT_MODE_REJECT_INTERVAL ) {
last_print_mode_reject_time = t ;
2014-07-13 11:43:56 +02:00
mavlink_log_critical ( mavlink_fd , msg ) ;
2014-02-11 00:24:40 +01:00
tune_negative ( true ) ;
2013-08-16 09:23:39 +02:00
}
}
2013-08-22 15:57:17 +02:00
void answer_command ( struct vehicle_command_s & cmd , enum VEHICLE_CMD_RESULT result )
{
switch ( result ) {
2013-08-27 23:08:00 +02:00
case VEHICLE_CMD_RESULT_ACCEPTED :
2015-01-16 16:46:16 +01:00
tune_positive ( true ) ;
2013-08-27 23:08:00 +02:00
break ;
case VEHICLE_CMD_RESULT_DENIED :
2014-07-13 11:43:56 +02:00
mavlink_log_critical ( mavlink_fd , " command denied: %u " , cmd . command ) ;
2014-02-11 00:24:40 +01:00
tune_negative ( true ) ;
2013-08-27 23:08:00 +02:00
break ;
case VEHICLE_CMD_RESULT_FAILED :
2014-07-13 11:43:56 +02:00
mavlink_log_critical ( mavlink_fd , " command failed: %u " , cmd . command ) ;
2014-02-11 00:24:40 +01:00
tune_negative ( true ) ;
2013-08-27 23:08:00 +02:00
break ;
case VEHICLE_CMD_RESULT_TEMPORARILY_REJECTED :
2014-05-23 15:02:24 +02:00
/* this needs additional hints to the user - so let other messages pass and be spoken */
mavlink_log_critical ( mavlink_fd , " command temporarily rejected: %u " , cmd . command ) ;
2014-02-11 00:24:40 +01:00
tune_negative ( true ) ;
2013-08-27 23:08:00 +02:00
break ;
case VEHICLE_CMD_RESULT_UNSUPPORTED :
2014-07-13 11:43:56 +02:00
mavlink_log_critical ( mavlink_fd , " command unsupported: %u " , cmd . command ) ;
2014-02-11 00:24:40 +01:00
tune_negative ( true ) ;
2013-08-27 23:08:00 +02:00
break ;
default :
break ;
2013-08-22 15:57:17 +02:00
}
}
2013-03-26 10:44:49 -07:00
void * commander_low_prio_loop ( void * arg )
2013-03-25 14:53:54 -07:00
{
/* Set thread name */
2013-07-31 20:58:27 +04:00
prctl ( PR_SET_NAME , " commander_low_prio " , getpid ( ) ) ;
2013-03-25 14:53:54 -07:00
2013-08-17 18:39:46 +02:00
/* Subscribe to command topic */
int cmd_sub = orb_subscribe ( ORB_ID ( vehicle_command ) ) ;
struct vehicle_command_s cmd ;
memset ( & cmd , 0 , sizeof ( cmd ) ) ;
/* wakeup source(s) */
struct pollfd fds [ 1 ] ;
/* use the gyro to pace output - XXX BROKEN if we are using the L3GD20 */
fds [ 0 ] . fd = cmd_sub ;
fds [ 0 ] . events = POLLIN ;
2013-08-15 09:52:22 +02:00
2013-03-25 14:53:54 -07:00
while ( ! thread_should_exit ) {
2013-10-21 20:07:47 +02:00
/* wait for up to 200ms for data */
2013-09-08 20:05:15 +02:00
int pret = poll ( & fds [ 0 ] , ( sizeof ( fds ) / sizeof ( fds [ 0 ] ) ) , 200 ) ;
2013-03-25 14:53:54 -07:00
2013-10-21 20:07:47 +02:00
/* timed out - periodic check for thread_should_exit, etc. */
2014-05-11 13:36:51 +02:00
if ( pret = = 0 ) {
2013-08-17 18:39:46 +02:00
continue ;
2014-05-11 13:36:51 +02:00
}
2013-03-25 14:53:54 -07:00
2013-08-17 18:39:46 +02:00
/* this is undesirable but not much we can do - might want to flag unhappy status */
if ( pret < 0 ) {
warn ( " poll error %d, %d " , pret , errno ) ;
continue ;
}
2013-08-07 20:21:49 +02:00
2013-08-17 18:39:46 +02:00
/* if we reach here, we have a valid command */
orb_copy ( ORB_ID ( vehicle_command ) , cmd_sub , & cmd ) ;
2013-03-25 14:53:54 -07:00
2013-08-17 18:39:46 +02:00
/* ignore commands the high-prio loop handles */
if ( cmd . command = = VEHICLE_CMD_DO_SET_MODE | |
2013-08-24 20:31:01 +02:00
cmd . command = = VEHICLE_CMD_COMPONENT_ARM_DISARM | |
2013-12-08 16:52:41 +01:00
cmd . command = = VEHICLE_CMD_NAV_TAKEOFF | |
2014-05-11 13:36:51 +02:00
cmd . command = = VEHICLE_CMD_DO_SET_SERVO ) {
2013-08-17 18:39:46 +02:00
continue ;
2014-05-11 13:36:51 +02:00
}
2013-03-25 14:53:54 -07:00
2013-08-17 18:39:46 +02:00
/* only handle low-priority commands here */
switch ( cmd . command ) {
2013-08-07 20:21:49 +02:00
2013-08-17 18:39:46 +02:00
case VEHICLE_CMD_PREFLIGHT_REBOOT_SHUTDOWN :
2013-08-22 15:57:17 +02:00
if ( is_safe ( & status , & safety , & armed ) ) {
if ( ( ( int ) ( cmd . param1 ) ) = = 1 ) {
answer_command ( cmd , VEHICLE_CMD_RESULT_ACCEPTED ) ;
2013-09-05 13:24:21 +02:00
usleep ( 100000 ) ;
2013-08-22 15:57:17 +02:00
/* reboot */
systemreset ( false ) ;
2013-08-27 23:08:00 +02:00
2013-08-22 15:57:17 +02:00
} else if ( ( ( int ) ( cmd . param1 ) ) = = 3 ) {
answer_command ( cmd , VEHICLE_CMD_RESULT_ACCEPTED ) ;
2013-09-05 13:24:21 +02:00
usleep ( 100000 ) ;
2013-08-22 15:57:17 +02:00
/* reboot to bootloader */
systemreset ( true ) ;
2013-08-27 23:08:00 +02:00
2013-08-17 18:39:46 +02:00
} else {
2013-08-22 15:57:17 +02:00
answer_command ( cmd , VEHICLE_CMD_RESULT_DENIED ) ;
2013-08-17 18:39:46 +02:00
}
2013-03-25 14:53:54 -07:00
2013-08-22 15:57:17 +02:00
} else {
answer_command ( cmd , VEHICLE_CMD_RESULT_DENIED ) ;
}
2013-08-27 23:08:00 +02:00
break ;
2013-03-25 14:53:54 -07:00
2013-08-22 15:57:17 +02:00
case VEHICLE_CMD_PREFLIGHT_CALIBRATION : {
2013-03-25 14:53:54 -07:00
2013-08-27 23:08:00 +02:00
int calib_ret = ERROR ;
2013-03-25 14:53:54 -07:00
2013-08-27 23:08:00 +02:00
/* try to go to INIT/PREFLIGHT arming state */
2014-10-23 16:17:20 +02:00
if ( TRANSITION_DENIED = = arming_state_transition ( & status , & safety , ARMING_STATE_INIT , & armed ,
true /* fRunPreArmChecks */ , mavlink_fd ) ) {
2013-08-27 23:08:00 +02:00
answer_command ( cmd , VEHICLE_CMD_RESULT_DENIED ) ;
break ;
}
2013-03-25 14:53:54 -07:00
2013-08-27 23:08:00 +02:00
if ( ( int ) ( cmd . param1 ) = = 1 ) {
/* gyro calibration */
answer_command ( cmd , VEHICLE_CMD_RESULT_ACCEPTED ) ;
calib_ret = do_gyro_calibration ( mavlink_fd ) ;
2013-08-22 15:57:17 +02:00
2013-08-27 23:08:00 +02:00
} else if ( ( int ) ( cmd . param2 ) = = 1 ) {
/* magnetometer calibration */
answer_command ( cmd , VEHICLE_CMD_RESULT_ACCEPTED ) ;
calib_ret = do_mag_calibration ( mavlink_fd ) ;
2013-08-22 15:57:17 +02:00
2013-08-27 23:08:00 +02:00
} else if ( ( int ) ( cmd . param3 ) = = 1 ) {
/* zero-altitude pressure calibration */
answer_command ( cmd , VEHICLE_CMD_RESULT_DENIED ) ;
2013-08-22 15:57:17 +02:00
2013-08-27 23:08:00 +02:00
} else if ( ( int ) ( cmd . param4 ) = = 1 ) {
/* RC calibration */
2013-10-21 20:07:47 +02:00
answer_command ( cmd , VEHICLE_CMD_RESULT_ACCEPTED ) ;
2014-02-01 13:21:51 +01:00
/* disable RC control input completely */
status . rc_input_blocked = true ;
calib_ret = OK ;
mavlink_log_info ( mavlink_fd , " CAL: Disabling RC IN " ) ;
} else if ( ( int ) ( cmd . param4 ) = = 2 ) {
/* RC trim calibration */
answer_command ( cmd , VEHICLE_CMD_RESULT_ACCEPTED ) ;
calib_ret = do_trim_calibration ( mavlink_fd ) ;
2013-08-22 15:57:17 +02:00
2013-08-27 23:08:00 +02:00
} else if ( ( int ) ( cmd . param5 ) = = 1 ) {
/* accelerometer calibration */
answer_command ( cmd , VEHICLE_CMD_RESULT_ACCEPTED ) ;
calib_ret = do_accel_calibration ( mavlink_fd ) ;
2013-08-22 15:57:17 +02:00
2013-08-27 23:08:00 +02:00
} else if ( ( int ) ( cmd . param6 ) = = 1 ) {
/* airspeed calibration */
answer_command ( cmd , VEHICLE_CMD_RESULT_ACCEPTED ) ;
calib_ret = do_airspeed_calibration ( mavlink_fd ) ;
2014-05-11 13:36:51 +02:00
2014-02-01 13:21:51 +01:00
} else if ( ( int ) ( cmd . param4 ) = = 0 ) {
/* RC calibration ended - have we been in one worth confirming? */
if ( status . rc_input_blocked ) {
answer_command ( cmd , VEHICLE_CMD_RESULT_ACCEPTED ) ;
/* enable RC control input */
status . rc_input_blocked = false ;
mavlink_log_info ( mavlink_fd , " CAL: Re-enabling RC IN " ) ;
}
/* this always succeeds */
calib_ret = OK ;
2013-08-27 23:08:00 +02:00
}
2013-03-25 14:53:54 -07:00
2014-05-11 13:36:51 +02:00
if ( calib_ret = = OK ) {
2014-02-11 00:24:40 +01:00
tune_positive ( true ) ;
2014-05-11 13:36:51 +02:00
} else {
2014-02-11 00:24:40 +01:00
tune_negative ( true ) ;
2014-05-11 13:36:51 +02:00
}
2013-03-25 14:53:54 -07:00
2014-08-04 09:40:38 -07:00
arming_state_transition ( & status , & safety , ARMING_STATE_STANDBY , & armed , true /* fRunPreArmChecks */ , mavlink_fd ) ;
2013-03-25 14:53:54 -07:00
2013-08-27 23:08:00 +02:00
break ;
}
2013-07-28 23:12:16 +04:00
2013-08-17 18:39:46 +02:00
case VEHICLE_CMD_PREFLIGHT_STORAGE : {
2013-07-28 23:12:16 +04:00
2013-08-27 23:08:00 +02:00
if ( ( ( int ) ( cmd . param1 ) ) = = 0 ) {
2013-09-05 13:24:21 +02:00
int ret = param_load_default ( ) ;
2013-09-14 08:55:45 +02:00
2013-09-05 13:24:21 +02:00
if ( ret = = OK ) {
2013-08-27 23:08:00 +02:00
mavlink_log_info ( mavlink_fd , " [cmd] parameters loaded " ) ;
answer_command ( cmd , VEHICLE_CMD_RESULT_ACCEPTED ) ;
2013-08-17 18:39:46 +02:00
2013-08-27 23:08:00 +02:00
} else {
2013-10-28 14:47:37 +01:00
mavlink_log_critical ( mavlink_fd , " #audio: parameters load ERROR " ) ;
2013-09-14 08:55:45 +02:00
2013-09-05 13:24:21 +02:00
/* convenience as many parts of NuttX use negative errno */
2014-05-11 13:36:51 +02:00
if ( ret < 0 ) {
2013-09-05 13:24:21 +02:00
ret = - ret ;
2014-05-11 13:36:51 +02:00
}
2013-09-05 13:24:21 +02:00
2014-05-11 13:36:51 +02:00
if ( ret < 1000 ) {
2013-10-28 14:47:37 +01:00
mavlink_log_critical ( mavlink_fd , " #audio: %s " , strerror ( ret ) ) ;
2014-05-11 13:36:51 +02:00
}
2013-09-14 08:55:45 +02:00
2013-08-27 23:08:00 +02:00
answer_command ( cmd , VEHICLE_CMD_RESULT_FAILED ) ;
}
2013-08-17 18:39:46 +02:00
2013-08-27 23:08:00 +02:00
} else if ( ( ( int ) ( cmd . param1 ) ) = = 1 ) {
2013-09-05 13:24:21 +02:00
int ret = param_save_default ( ) ;
2013-09-14 08:55:45 +02:00
2013-09-05 13:24:21 +02:00
if ( ret = = OK ) {
2013-08-27 23:08:00 +02:00
mavlink_log_info ( mavlink_fd , " [cmd] parameters saved " ) ;
answer_command ( cmd , VEHICLE_CMD_RESULT_ACCEPTED ) ;
2013-08-17 18:39:46 +02:00
2013-08-27 23:08:00 +02:00
} else {
2013-10-28 14:47:37 +01:00
mavlink_log_critical ( mavlink_fd , " #audio: parameters save error " ) ;
2013-09-14 08:55:45 +02:00
2013-09-05 13:24:21 +02:00
/* convenience as many parts of NuttX use negative errno */
2014-05-11 13:36:51 +02:00
if ( ret < 0 ) {
2013-09-05 13:24:21 +02:00
ret = - ret ;
2014-05-11 13:36:51 +02:00
}
2013-09-05 13:24:21 +02:00
2014-05-11 13:36:51 +02:00
if ( ret < 1000 ) {
2013-10-28 14:47:37 +01:00
mavlink_log_critical ( mavlink_fd , " #audio: %s " , strerror ( ret ) ) ;
2014-05-11 13:36:51 +02:00
}
2013-09-14 08:55:45 +02:00
2013-08-27 23:08:00 +02:00
answer_command ( cmd , VEHICLE_CMD_RESULT_FAILED ) ;
}
2013-08-17 18:39:46 +02:00
}
2013-08-27 23:08:00 +02:00
break ;
2013-08-17 18:39:46 +02:00
}
2013-03-25 14:53:54 -07:00
2014-02-01 23:13:41 +01:00
case VEHICLE_CMD_START_RX_PAIR :
2014-05-11 13:36:51 +02:00
/* handled in the IO driver */
break ;
2014-02-01 23:13:41 +01:00
2013-08-22 15:57:17 +02:00
default :
2013-12-29 12:16:49 +04:00
/* don't answer on unsupported commands, it will be done in main loop */
2013-08-22 15:57:17 +02:00
break ;
2013-08-17 18:39:46 +02:00
}
/* send any requested ACKs */
if ( cmd . confirmation > 0 & & cmd . command ! = VEHICLE_CMD_DO_SET_MODE
2013-08-27 23:08:00 +02:00
& & cmd . command ! = VEHICLE_CMD_COMPONENT_ARM_DISARM ) {
2013-08-17 18:39:46 +02:00
/* send acknowledge command */
// XXX TODO
}
2013-03-25 14:53:54 -07:00
}
2013-09-01 10:29:30 +02:00
close ( cmd_sub ) ;
2013-09-08 20:05:15 +02:00
return NULL ;
2013-03-25 14:53:54 -07:00
}