123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240 |
- #include "Sub.h"
- // change flight mode and perform any necessary initialisation
- // returns true if mode was successfully set
- bool Sub::set_mode(control_mode_t mode, mode_reason_t reason)
- {
- // boolean to record if flight mode could be set
- bool success = false;
- // return immediately if we are already in the desired mode
- if (mode == control_mode) {
- prev_control_mode = control_mode;
- prev_control_mode_reason = control_mode_reason;
- control_mode_reason = reason;
- return true;
- }
- switch (mode) {
- case ACRO:
- success = acro_init();
- break;
- case STABILIZE:
- success = stabilize_init();
- break;
- case ALT_HOLD:
- success = althold_init();
- break;
- case AUTO:
- success = auto_init();
- break;
- case CIRCLE:
- success = circle_init();
- break;
- case GUIDED:
- success = guided_init();
- break;
- case SURFACE:
- success = surface_init();
- break;
- #if POSHOLD_ENABLED == ENABLED
- case POSHOLD:
- success = poshold_init();
- break;
- #endif
- case MANUAL:
- success = manual_init();
- break;
- case MOTOR_DETECT:
- success = motordetect_init();
- break;
- case CLEAN:
- success = clean_init();
- break;
- case SPORT:
- success = sport_init();
- break;
- default:
- success = false;
- break;
- }
- // update flight mode
- if (success) {
- // perform any cleanup required by previous flight mode
- exit_mode(control_mode, mode);
- prev_control_mode = control_mode;
- prev_control_mode_reason = control_mode_reason;
- control_mode = mode;
- control_mode_reason = reason;
- logger.Write_Mode(control_mode, control_mode_reason);
- gcs().send_message(MSG_HEARTBEAT);
- // update notify object
- notify_flight_mode(control_mode);
- #if CAMERA == ENABLED
- camera.set_is_auto_mode(control_mode == AUTO);
- #endif
- #if AC_FENCE == ENABLED
- // pilot requested flight mode change during a fence breach indicates pilot is attempting to manually recover
- // this flight mode change could be automatic (i.e. fence, battery, GPS or GCS failsafe)
- // but it should be harmless to disable the fence temporarily in these situations as well
- fence.manual_recovery_start();
- #endif
- } else {
- // Log error that we failed to enter desired flight mode
- AP::logger().Write_Error(LogErrorSubsystem::FLIGHT_MODE, LogErrorCode(mode));
- }
- // return success or failure
- return success;
- }
- // update_flight_mode - calls the appropriate attitude controllers based on flight mode
- // called at 100hz or more
- void Sub::update_flight_mode()
- {
- switch (control_mode) {
- case ACRO:
- acro_run();
- break;
- case STABILIZE:
- stabilize_run();
- break;
- case ALT_HOLD:
- althold_run();
- break;
- case AUTO:
- auto_run();
- break;
- case CIRCLE:
- circle_run();
- break;
- case GUIDED:
- guided_run();
- break;
- case SURFACE:
- surface_run();
- break;
- #if POSHOLD_ENABLED == ENABLED
- case POSHOLD:
- poshold_run();
- break;
- #endif
- case MANUAL:
- manual_run();
- break;
- case MOTOR_DETECT:
- motordetect_run();
- break;
- case CLEAN:
- clean_run();
- break;
- case SPORT:
- //sport_run();
- sport_run_alt();
- break;
- default:
- break;
- }
- }
- // exit_mode - high level call to organise cleanup as a flight mode is exited
- void Sub::exit_mode(control_mode_t old_control_mode, control_mode_t new_control_mode)
- {
- // stop mission when we leave auto mode
- if (old_control_mode == AUTO) {
- if (mission.state() == AP_Mission::MISSION_RUNNING) {
- mission.stop();
- }
- #if MOUNT == ENABLED
- camera_mount.set_mode_to_default();
- #endif // MOUNT == ENABLED
- }
- }
- // returns true or false whether mode requires GPS
- bool Sub::mode_requires_GPS(control_mode_t mode)
- {
- switch (mode) {
- case AUTO:
- case GUIDED:
- case CIRCLE:
- case POSHOLD:
- return true;
- default:
- return false;
- }
- return false;
- }
- // mode_has_manual_throttle - returns true if the flight mode has a manual throttle (i.e. pilot directly controls throttle)
- bool Sub::mode_has_manual_throttle(control_mode_t mode)
- {
- switch (mode) {
- case ACRO:
- case STABILIZE:
- case MANUAL:
- return true;
- default:
- return false;
- }
- return false;
- }
- // mode_allows_arming - returns true if vehicle can be armed in the specified mode
- // arming_from_gcs should be set to true if the arming request comes from the ground station
- bool Sub::mode_allows_arming(control_mode_t mode, bool arming_from_gcs)
- {
- return (mode_has_manual_throttle(mode)
- || mode == ALT_HOLD
- || mode == POSHOLD
- || (arming_from_gcs&& mode == GUIDED)
- );
- }
- // notify_flight_mode - sets notify object based on flight mode. Only used for OreoLED notify device
- void Sub::notify_flight_mode(control_mode_t mode)
- {
- switch (mode) {
- case AUTO:
- case GUIDED:
- case CIRCLE:
- case SURFACE:
- // autopilot modes
- AP_Notify::flags.autopilot_mode = true;
- break;
- default:
- // all other are manual flight modes
- AP_Notify::flags.autopilot_mode = false;
- break;
- }
- }
|