#pragma once
#include "Copter.h"
#include <AP_Math/chirp.h>
#include <AP_ExternalControl/AP_ExternalControl_config.h>
#include <AP_HAL/Semaphores.h>
#if AP_COPTER_ADVANCED_FAILSAFE_ENABLED
#include "afs_copter.h"
#endif
class Parameters;
class ParametersG2;
class GCS_Copter;
class _AutoTakeoff {
public:
void run();
void start_m(float complete_alt_m, bool is_terrain_alt);
bool get_completion_pos_ned_m(Vector3p& pos_ned_m);
bool complete;
private:
bool no_nav_active;
float no_nav_alt_m;
float complete_alt_m;
bool is_terrain_alt;
Vector3p complete_pos_ned_m;
};
#if AC_PAYLOAD_PLACE_ENABLED
class PayloadPlace {
public:
void run();
void start_descent();
bool verify();
enum class State : uint8_t {
FlyToLocation,
Descent_Start,
Descent,
Release,
Releasing,
Delay,
Ascent_Start,
Ascent,
Done,
};
State state = State::Descent_Start;
float descent_max_m;
private:
uint32_t descent_established_time_ms;
uint32_t place_start_time_ms;
float descent_thrust_level;
float descent_start_altitude_m;
float descent_speed_ms;
};
#endif
class Mode {
friend class PayloadPlace;
public:
enum class Number : uint8_t {
STABILIZE = 0,
ACRO = 1,
ALT_HOLD = 2,
AUTO = 3,
GUIDED = 4,
LOITER = 5,
RTL = 6,
CIRCLE = 7,
LAND = 9,
DRIFT = 11,
SPORT = 13,
FLIP = 14,
AUTOTUNE = 15,
POSHOLD = 16,
BRAKE = 17,
THROW = 18,
AVOID_ADSB = 19,
GUIDED_NOGPS = 20,
SMART_RTL = 21,
FLOWHOLD = 22,
FOLLOW = 23,
ZIGZAG = 24,
SYSTEMID = 25,
AUTOROTATE = 26,
AUTO_RTL = 27,
TURTLE = 28,
};
Mode(void);
CLASS_NO_COPY(Mode);
friend class _AutoTakeoff;
virtual Number mode_number() const = 0;
virtual bool init(bool ignore_checks) {
return true;
}
virtual void exit() {};
virtual void run() = 0;
virtual bool requires_position() const = 0;
virtual bool has_manual_throttle() const = 0;
virtual bool allows_arming(AP_Arming::Method method) const = 0;
virtual bool is_autopilot() const = 0;
virtual bool has_user_takeoff(bool must_navigate) const { return false; }
virtual bool in_guided_mode() const { return false; }
virtual bool logs_attitude() const { return false; }
virtual bool allows_save_trim() const { return false; }
virtual bool allows_auto_trim() const { return false; }
virtual bool allows_autotune() const { return false; }
virtual bool allows_flip() const { return false; }
virtual bool crash_check_enabled() const { return true; }
virtual bool move_vehicle_on_ekf_reset() const { return false; }
virtual bool allows_entry_in_rc_failsafe() const { return true; }
#if AP_COPTER_ADVANCED_FAILSAFE_ENABLED
virtual AP_AdvancedFailsafe_Copter::control_mode afs_mode() const { return AP_AdvancedFailsafe_Copter::control_mode::AFS_STABILIZED; }
#endif
virtual bool allows_GCS_or_SCR_arming_with_throttle_high() const { return false; }
#if FRAME_CONFIG == HELI_FRAME
virtual bool allows_inverted() const { return false; };
#endif
virtual const char *name() const = 0;
virtual const char *name4() const = 0;
bool do_user_takeoff_U_m(float takeoff_alt_m, bool must_navigate);
virtual bool is_taking_off() const;
static void takeoff_stop() { takeoff.stop(); }
virtual bool is_landing() const { return false; }
virtual bool requires_terrain_failsafe() const { return false; }
virtual bool get_wp(Location &loc) const { return false; };
virtual float wp_bearing_deg() const { return 0; }
virtual float wp_distance_m() const { return 0.0f; }
virtual float crosstrack_error_m() const { return 0.0f;}
virtual bool set_speed_NE_ms(float speed_ne_ms) {return false;}
virtual bool set_speed_up_ms(float speed_up_ms) {return false;}
virtual bool set_speed_down_ms(float speed_down_ms) {return false;}
virtual float get_alt_above_ground_m(void) const;
void get_pilot_desired_lean_angles_rad(float &roll_out_rad, float &pitch_out_rad, float angle_max_rad, float angle_limit_rad) const;
float get_pilot_desired_yaw_rate_rads() const;
Vector2f get_pilot_desired_velocity(float vel_max) const;
float get_pilot_desired_throttle() const;
float get_avoidance_adjusted_climbrate_ms(float target_rate_ms);
virtual void output_to_motors();
virtual bool use_pilot_yaw() const {return true; }
virtual bool pause() { return false; };
virtual bool resume() { return false; };
void make_safe_ground_handling(bool force_throttle_unlimited = false);
#if WEATHERVANE_ENABLED
virtual bool allows_weathervaning() const { return false; }
#endif
protected:
bool is_disarmed_or_landed() const;
void zero_throttle_and_relax_ac(bool spool_up = false);
void zero_throttle_and_hold_attitude();
Location get_stopping_point() const;
void land_run_horizontal_control();
void land_run_vertical_control(bool pause_descent = false);
void land_run_horiz_and_vert_control(bool pause_descent = false) {
land_run_horizontal_control();
land_run_vertical_control(pause_descent);
}
#if AC_PAYLOAD_PLACE_ENABLED
static PayloadPlace payload_place;
#endif
void land_run_normal_or_precland(bool pause_descent = false);
#if AC_PRECLAND_ENABLED
void precland_retry_position(const Vector3p &retry_pos);
void precland_run();
#endif
virtual float throttle_hover() const;
enum class AltHoldModeState {
MotorStopped,
Takeoff,
Landed_Ground_Idle,
Landed_Pre_Takeoff,
Flying
};
AltHoldModeState get_alt_hold_state_D_ms(float target_climb_rate_ms);
Parameters &g;
ParametersG2 &g2;
AC_WPNav *&wp_nav;
AC_Loiter *&loiter_nav;
AC_PosControl *&pos_control;
AP_AHRS &ahrs;
AC_AttitudeControl *&attitude_control;
MOTOR_CLASS *&motors;
RC_Channel *&channel_roll;
RC_Channel *&channel_pitch;
RC_Channel *&channel_throttle;
RC_Channel *&channel_yaw;
float &G_Dt;
class _TakeOff {
public:
void start_m(float alt_m);
void stop();
void do_pilot_takeoff_ms(float pilot_climb_rate_ms);
bool triggered_ms(float target_climb_rate_ms) const;
bool running() const { return _running; }
private:
bool _running;
float take_off_start_alt_m;
float take_off_complete_alt_m;
};
static _TakeOff takeoff;
virtual bool do_user_takeoff_start_m(float takeoff_alt_m);
static _AutoTakeoff auto_takeoff;
public:
class AutoYaw {
public:
enum class Mode {
HOLD = 0,
LOOK_AT_NEXT_WP = 1,
ROI = 2,
FIXED = 3,
LOOK_AHEAD = 4,
RESET_TO_ARMED_YAW = 5,
ANGLE_RATE = 6,
RATE = 7,
CIRCLE = 8,
PILOT_RATE = 9,
WEATHERVANE = 10,
};
Mode mode() const { return _mode; }
void set_mode_to_default(bool rtl);
void set_mode(Mode new_mode);
Mode default_mode(bool rtl) const;
void set_rate_rad(float turn_rate_rads);
void set_roi(const Location &roi_location);
void set_fixed_yaw_rad(float angle_rad,
float turn_rate_rads,
int8_t direction,
bool relative_angle);
void set_yaw_angle_and_rate_rad(float yaw_angle_rad, float yaw_rate_rads);
void set_yaw_angle_offset_deg(const float yaw_angle_offset_deg);
bool reached_fixed_yaw_target();
#if WEATHERVANE_ENABLED
void update_weathervane(const float pilot_yaw_rads);
#endif
AC_AttitudeControl::HeadingCommand get_heading();
private:
float yaw_rad();
float rate_rads();
float look_ahead_yaw_rad();
float roi_yaw_rad() const;
Mode _mode = Mode::LOOK_AT_NEXT_WP;
Mode _last_mode;
Vector3f roi_ned_m;
float _fixed_yaw_offset_rad;
float _fixed_yaw_slewrate_rads;
uint32_t _last_update_ms;
float _look_ahead_yaw_rad;
float _yaw_angle_rad;
float _yaw_rate_rads;
float _pilot_yaw_rate_rads;
};
static AutoYaw auto_yaw;
float get_pilot_desired_climb_rate_ms() const;
float get_non_takeoff_throttle() const;
void update_simple_mode();
bool set_mode(Mode::Number mode, ModeReason reason);
void set_land_complete(bool b);
GCS_Copter &gcs() const;
float get_pilot_speed_up_ms() const;
float get_pilot_speed_dn_ms() const;
float get_pilot_accel_D_mss() const;
};
#if MODE_ACRO_ENABLED
class ModeAcro : public Mode {
public:
using Mode::Mode;
Number mode_number() const override { return Number::ACRO; }
enum class Trainer {
OFF = 0,
LEVELING = 1,
LIMITED = 2,
};
enum class AcroOptions {
AIR_MODE = 1 << 0,
RATE_LOOP_ONLY = 1 << 1,
};
virtual void run() override;
bool requires_position() const override { return false; }
bool has_manual_throttle() const override { return true; }
bool allows_arming(AP_Arming::Method method) const override { return true; };
bool is_autopilot() const override { return false; }
bool init(bool ignore_checks) override;
void exit() override;
void air_mode_aux_changed();
bool allows_save_trim() const override { return true; }
bool allows_flip() const override { return true; }
bool crash_check_enabled() const override { return false; }
bool allows_entry_in_rc_failsafe() const override { return false; }
protected:
const char *name() const override { return "Acro"; }
const char *name4() const override { return "ACRO"; }
void get_pilot_desired_rates_rads(float &roll_out_rads, float &pitch_out_rads, float &yaw_out_rads);
float throttle_hover() const override;
private:
bool disable_air_mode_reset;
};
#endif
#if FRAME_CONFIG == HELI_FRAME
class ModeAcro_Heli : public ModeAcro {
public:
using ModeAcro::Mode;
bool init(bool ignore_checks) override;
void run() override;
void virtual_flybar( float &roll_out_rads, float &pitch_out_rads, float &yaw_out_rads, float pitch_leak, float roll_leak);
protected:
private:
};
#endif
class ModeAltHold : public Mode {
public:
using Mode::Mode;
Number mode_number() const override { return Number::ALT_HOLD; }
bool init(bool ignore_checks) override;
void run() override;
bool requires_position() const override { return false; }
bool has_manual_throttle() const override { return false; }
bool allows_arming(AP_Arming::Method method) const override { return true; };
bool is_autopilot() const override { return false; }
bool has_user_takeoff(bool must_navigate) const override {
return !must_navigate;
}
bool allows_autotune() const override { return true; }
bool allows_flip() const override { return true; }
bool allows_auto_trim() const override { return true; }
bool allows_save_trim() const override { return true; }
#if FRAME_CONFIG == HELI_FRAME
bool allows_inverted() const override { return true; };
#endif
protected:
const char *name() const override { return "Altitude Hold"; }
const char *name4() const override { return "ALTH"; }
private:
};
class ModeAuto : public Mode {
public:
friend class PayloadPlace;
using Mode::Mode;
Number mode_number() const override { return auto_RTL? Number::AUTO_RTL : Number::AUTO; }
bool init(bool ignore_checks) override;
void exit() override;
void run() override;
bool requires_position() const override;
bool has_manual_throttle() const override { return false; }
bool allows_arming(AP_Arming::Method method) const override;
bool is_autopilot() const override { return true; }
bool in_guided_mode() const override { return _mode == SubMode::NAVGUIDED || _mode == SubMode::NAV_SCRIPT_TIME; }
#if FRAME_CONFIG == HELI_FRAME
bool allows_inverted() const override { return true; };
#endif
bool move_vehicle_on_ekf_reset() const override;
#if AP_COPTER_ADVANCED_FAILSAFE_ENABLED
AP_AdvancedFailsafe_Copter::control_mode afs_mode() const override { return AP_AdvancedFailsafe_Copter::control_mode::AFS_AUTO; }
#endif
bool allows_GCS_or_SCR_arming_with_throttle_high() const override { return true; }
enum class SubMode : uint8_t {
TAKEOFF,
WP,
LAND,
RTL,
CIRCLE_MOVE_TO_EDGE,
CIRCLE,
NAVGUIDED,
LOITER,
LOITER_TO_ALT,
#if AP_MISSION_NAV_PAYLOAD_PLACE_ENABLED && AC_PAYLOAD_PLACE_ENABLED
NAV_PAYLOAD_PLACE,
#endif
NAV_SCRIPT_TIME,
NAV_ATTITUDE_TIME,
};
void set_submode(SubMode new_submode);
bool pause() override;
bool resume() override;
bool paused() const;
bool loiter_start();
void rtl_start();
void takeoff_start(const Location& dest_loc);
bool wp_start(const Location& dest_loc);
void land_start();
void circle_movetoedge_start(const Location &circle_center, float radius_m, bool ccw_turn);
void circle_start();
void nav_guided_start();
bool is_landing() const override;
bool is_taking_off() const override;
bool use_pilot_yaw() const override;
bool set_speed_NE_ms(float speed_ne_ms) override;
bool set_speed_up_ms(float speed_up_ms) override;
bool set_speed_down_ms(float speed_down_ms) override;
bool requires_terrain_failsafe() const override { return true; }
void payload_place_start();
bool do_guided(const AP_Mission::Mission_Command& cmd);
bool jump_to_landing_sequence_auto_RTL(ModeReason reason);
bool return_path_start_auto_RTL(ModeReason reason);
bool return_path_or_jump_to_landing_sequence_auto_RTL(ModeReason reason);
bool nav_script_time(uint16_t &id, uint8_t &cmd, float &arg1, float &arg2, int16_t &arg3, int16_t &arg4);
void nav_script_time_done(uint16_t id);
AP_Mission mission{
FUNCTOR_BIND_MEMBER(&ModeAuto::start_command, bool, const AP_Mission::Mission_Command &),
FUNCTOR_BIND_MEMBER(&ModeAuto::verify_command, bool, const AP_Mission::Mission_Command &),
FUNCTOR_BIND_MEMBER(&ModeAuto::exit_mission, void)};
AP_Mission_ChangeDetector mis_change_detector;
#if WEATHERVANE_ENABLED
bool allows_weathervaning(void) const override;
#endif
float get_alt_above_ground_m() const override;
protected:
const char *name() const override { return auto_RTL? "Auto RTL" : "Auto"; }
const char *name4() const override { return auto_RTL? "ARTL" : "AUTO"; }
float wp_distance_m() const override;
float wp_bearing_deg() const override;
float crosstrack_error_m() const override { return wp_nav->crosstrack_error_m();}
bool get_wp(Location &loc) const override;
private:
enum class Option : int32_t {
AllowArming = (1 << 0U),
AllowTakeOffWithoutRaisingThrottle = (1 << 1U),
IgnorePilotYaw = (1 << 2U),
AllowWeatherVaning = (1 << 7U),
};
bool option_is_enabled(Option option) const;
bool enter_auto_rtl(ModeReason reason);
bool start_command(const AP_Mission::Mission_Command& cmd);
bool verify_command(const AP_Mission::Mission_Command& cmd);
void exit_mission();
bool check_for_mission_change();
void takeoff_run();
void wp_run();
void land_run();
void rtl_run();
void circle_run();
void nav_guided_run();
void loiter_run();
void loiter_to_alt_run();
void nav_attitude_time_run();
Location loc_from_cmd(const AP_Mission::Mission_Command& cmd, const Location& default_loc) const;
SubMode _mode = SubMode::TAKEOFF;
bool shift_alt_to_current_alt(Location& target_loc) const;
void subtract_pos_offsets(Location& target_loc) const;
void do_takeoff(const AP_Mission::Mission_Command& cmd);
void do_nav_wp(const AP_Mission::Mission_Command& cmd);
bool set_next_wp(const AP_Mission::Mission_Command& current_cmd, const Location &default_loc);
void do_land(const AP_Mission::Mission_Command& cmd);
void do_loiter_unlimited(const AP_Mission::Mission_Command& cmd);
void do_circle(const AP_Mission::Mission_Command& cmd);
void do_loiter_time(const AP_Mission::Mission_Command& cmd);
void do_loiter_to_alt(const AP_Mission::Mission_Command& cmd);
void do_spline_wp(const AP_Mission::Mission_Command& cmd);
void get_spline_from_cmd(const AP_Mission::Mission_Command& cmd, const Location& default_loc, Location& dest_loc, Location& next_dest_loc, bool& next_dest_loc_is_spline);
#if AC_NAV_GUIDED
void do_nav_guided_enable(const AP_Mission::Mission_Command& cmd);
void do_guided_limits(const AP_Mission::Mission_Command& cmd);
#endif
void do_nav_delay(const AP_Mission::Mission_Command& cmd);
void do_wait_delay(const AP_Mission::Mission_Command& cmd);
void do_within_distance(const AP_Mission::Mission_Command& cmd);
void do_yaw(const AP_Mission::Mission_Command& cmd);
void do_change_speed(const AP_Mission::Mission_Command& cmd);
void do_set_home(const AP_Mission::Mission_Command& cmd);
void do_roi(const AP_Mission::Mission_Command& cmd);
void do_mount_control(const AP_Mission::Mission_Command& cmd);
#if HAL_PARACHUTE_ENABLED
void do_parachute(const AP_Mission::Mission_Command& cmd);
#endif
#if AP_WINCH_ENABLED
void do_winch(const AP_Mission::Mission_Command& cmd);
#endif
void do_payload_place(const AP_Mission::Mission_Command& cmd);
void do_RTL(void);
#if AP_SCRIPTING_ENABLED
void do_nav_script_time(const AP_Mission::Mission_Command& cmd);
#endif
void do_nav_attitude_time(const AP_Mission::Mission_Command& cmd);
bool verify_takeoff();
bool verify_land();
bool verify_payload_place();
bool verify_loiter_unlimited();
bool verify_loiter_time(const AP_Mission::Mission_Command& cmd);
bool verify_loiter_to_alt() const;
bool verify_RTL();
bool verify_wait_delay();
bool verify_within_distance();
bool verify_yaw();
bool verify_nav_wp(const AP_Mission::Mission_Command& cmd);
bool verify_circle(const AP_Mission::Mission_Command& cmd);
bool verify_spline_wp(const AP_Mission::Mission_Command& cmd);
#if AC_NAV_GUIDED
bool verify_nav_guided_enable(const AP_Mission::Mission_Command& cmd);
#endif
bool verify_nav_delay(const AP_Mission::Mission_Command& cmd);
#if AP_SCRIPTING_ENABLED
bool verify_nav_script_time();
#endif
bool verify_nav_attitude_time(const AP_Mission::Mission_Command& cmd);
uint16_t loiter_time_max;
uint32_t loiter_time;
struct {
bool reached_destination_xy : 1;
bool loiter_start_done : 1;
bool reached_alt : 1;
float alt_error_m;
float alt_m;
} loiter_to_alt;
uint32_t nav_delay_time_max_ms;
uint32_t nav_delay_time_start_ms;
int32_t condition_value;
uint32_t condition_start;
enum class State {
FlyToLocation = 0,
Descending = 1
};
State state = State::FlyToLocation;
bool waiting_to_start;
bool auto_RTL;
#if AP_SCRIPTING_ENABLED
struct {
bool done;
uint16_t id;
uint32_t start_ms;
uint8_t command;
uint8_t timeout_s;
float arg1;
float arg2;
int16_t arg3;
int16_t arg4;
} nav_scripting;
#endif
struct {
int16_t roll_deg;
int8_t pitch_deg;
int16_t yaw_deg;
float climb_rate_ms;
uint32_t start_ms;
} nav_attitude_time;
struct {
float xy;
float up;
float down;
} desired_speed_override_ms;
float circle_last_num_complete;
};
#if AUTOTUNE_ENABLED
#if FRAME_CONFIG == HELI_FRAME
class AutoTune : public AC_AutoTune_Heli
#else
class AutoTune : public AC_AutoTune_Multi
#endif
{
public:
bool init() override;
void run() override;
protected:
bool position_ok() override;
float get_desired_climb_rate_ms(void) const override;
void get_pilot_desired_rp_yrate_rad(float &des_roll_rad, float &des_pitch_rad, float &des_yaw_rate_rads) override;
void init_z_limits() override;
#if HAL_LOGGING_ENABLED
void log_pids() override;
#endif
};
class ModeAutoTune : public Mode {
friend class ParametersG2;
public:
using Mode::Mode;
Number mode_number() const override { return Number::AUTOTUNE; }
bool init(bool ignore_checks) override;
void exit() override;
void run() override;
bool requires_position() const override { return false; }
bool has_manual_throttle() const override { return false; }
bool allows_arming(AP_Arming::Method method) const override { return false; }
bool is_autopilot() const override { return false; }
AutoTune autotune;
protected:
const char *name() const override { return "Autotune"; }
const char *name4() const override { return "ATUN"; }
};
#endif
class ModeBrake : public Mode {
public:
using Mode::Mode;
Number mode_number() const override { return Number::BRAKE; }
bool init(bool ignore_checks) override;
void run() override;
bool requires_position() const override { return true; }
bool has_manual_throttle() const override { return false; }
bool allows_arming(AP_Arming::Method method) const override { return false; };
bool is_autopilot() const override { return true; }
void timeout_to_loiter_ms(uint32_t timeout_ms);
protected:
const char *name() const override { return "Brake"; }
const char *name4() const override { return "BRAK"; }
private:
uint32_t _timeout_start;
uint32_t _timeout_ms;
};
class ModeCircle : public Mode {
public:
using Mode::Mode;
Number mode_number() const override { return Number::CIRCLE; }
bool init(bool ignore_checks) override;
void run() override;
bool requires_position() const override { return true; }
bool has_manual_throttle() const override { return false; }
bool allows_arming(AP_Arming::Method method) const override { return false; };
bool is_autopilot() const override { return true; }
protected:
const char *name() const override { return "Circle"; }
const char *name4() const override { return "CIRC"; }
float wp_distance_m() const override;
float wp_bearing_deg() const override;
private:
bool speed_changing = false;
};
class ModeDrift : public Mode {
public:
using Mode::Mode;
Number mode_number() const override { return Number::DRIFT; }
bool init(bool ignore_checks) override;
void run() override;
bool requires_position() const override { return true; }
bool has_manual_throttle() const override { return false; }
bool allows_arming(AP_Arming::Method method) const override { return true; };
bool is_autopilot() const override { return false; }
bool allows_entry_in_rc_failsafe() const override { return false; }
protected:
const char *name() const override { return "Drift"; }
const char *name4() const override { return "DRIF"; }
private:
float get_throttle_assist(float vel_d_ms, float pilot_throttle_scaled);
};
class ModeFlip : public Mode {
public:
using Mode::Mode;
Number mode_number() const override { return Number::FLIP; }
bool init(bool ignore_checks) override;
void run() override;
bool requires_position() const override { return false; }
bool has_manual_throttle() const override { return false; }
bool allows_arming(AP_Arming::Method method) const override { return false; };
bool is_autopilot() const override { return false; }
bool crash_check_enabled() const override { return false; }
protected:
const char *name() const override { return "Flip"; }
const char *name4() const override { return "FLIP"; }
private:
Vector3f orig_attitude_euler_rad;
enum class FlipState : uint8_t {
Start,
Roll,
Pitch_A,
Pitch_B,
Recover,
Abandon
};
FlipState _state;
Mode::Number orig_control_mode;
uint32_t start_time_ms;
int8_t roll_dir;
int8_t pitch_dir;
};
#if MODE_FLOWHOLD_ENABLED
class ModeFlowHold : public Mode {
public:
ModeFlowHold(void);
Number mode_number() const override { return Number::FLOWHOLD; }
bool init(bool ignore_checks) override;
void run(void) override;
bool requires_position() const override { return false; }
bool has_manual_throttle() const override { return false; }
bool allows_arming(AP_Arming::Method method) const override { return true; };
bool is_autopilot() const override { return false; }
bool has_user_takeoff(bool must_navigate) const override {
return !must_navigate;
}
bool allows_flip() const override { return true; }
static const struct AP_Param::GroupInfo var_info[];
protected:
const char *name() const override { return "Flow Hold"; }
const char *name4() const override { return "FHLD"; }
private:
enum FlowHoldModeState {
FlowHold_MotorStopped,
FlowHold_Takeoff,
FlowHold_Flying,
FlowHold_Landed
};
void flow_to_angle(Vector2f &bf_angle);
LowPassFilterConstDtVector2f flow_filter;
bool flowhold_init(bool ignore_checks);
void flowhold_run();
void flowhold_flow_to_angle(Vector2f &bf_angles_rad, bool stick_input);
void update_height_estimate(void);
const float height_min_m = 0.1f;
const float height_max = 3.0f;
AP_Float flow_max;
AC_PI_2D flow_pi_xy{0.2f, 0.3f, 3000, 5, 0.0025f};
AP_Float flow_filter_hz;
AP_Int8 flow_min_quality;
AP_Int8 brake_rate_dps;
float quality_filtered;
uint8_t log_counter;
bool limited;
Vector2f xy_I;
Vector2f delta_velocity_ne_ms;
Vector2f last_flow_rate_rads;
uint32_t last_flow_ms;
float last_ins_height_m;
float height_offset_m;
bool braking;
uint32_t last_stick_input_ms;
};
#endif
class ModeGuided : public Mode {
public:
#if AP_EXTERNAL_CONTROL_ENABLED
friend class AP_ExternalControl_Copter;
#endif
using Mode::Mode;
Number mode_number() const override { return Number::GUIDED; }
bool init(bool ignore_checks) override;
void run() override;
bool requires_position() const override { return true; }
bool has_manual_throttle() const override { return false; }
bool allows_arming(AP_Arming::Method method) const override;
bool is_autopilot() const override { return true; }
bool has_user_takeoff(bool must_navigate) const override { return true; }
bool in_guided_mode() const override { return true; }
bool move_vehicle_on_ekf_reset() const override;
bool requires_terrain_failsafe() const override { return true; }
#if AP_COPTER_ADVANCED_FAILSAFE_ENABLED
AP_AdvancedFailsafe_Copter::control_mode afs_mode() const override { return AP_AdvancedFailsafe_Copter::control_mode::AFS_AUTO; }
#endif
bool allows_GCS_or_SCR_arming_with_throttle_high() const override { return true; }
void set_angle(const Quaternion &attitude_quat, const Vector3f &ang_vel, float climb_rate_ms_or_thrust, bool use_thrust);
void hold_position();
bool set_pos_NED_m(const Vector3p& pos_ned_m, bool use_yaw = false, float yaw_rad = 0.0, bool use_yaw_rate = false, float yaw_rate_rads = 0.0, bool yaw_relative = false, bool is_terrain_alt = false);
bool set_destination(const Location& dest_loc, bool use_yaw = false, float yaw_rad = 0.0, bool use_yaw_rate = false, float yaw_rate_rads = 0.0, bool yaw_relative = false);
bool get_wp(Location &loc) const override;
void set_accel_NED_mss(const Vector3f& accel_ned_mss, bool use_yaw = false, float yaw_rad = 0.0, bool use_yaw_rate = false, float yaw_rate_rads = 0.0, bool yaw_relative = false, bool log_request = true);
void set_vel_NED_ms(const Vector3f& vel_ned_ms, bool use_yaw = false, float yaw_rad = 0.0, bool use_yaw_rate = false, float yaw_rate_rads = 0.0, bool yaw_relative = false, bool log_request = true);
void set_vel_accel_NED_m(const Vector3f& vel_ned_ms, const Vector3f& accel_ned_mss, bool use_yaw = false, float yaw_rad = 0.0, bool use_yaw_rate = false, float yaw_rate_rads = 0.0, bool yaw_relative = false, bool log_request = true);
bool set_pos_vel_NED_m(const Vector3p& pos_ned_m, const Vector3f& vel_ned_ms, bool use_yaw = false, float yaw_rad = 0.0, bool use_yaw_rate = false, float yaw_rate_rads = 0.0, bool yaw_relative = false);
bool set_pos_vel_accel_NED_m(const Vector3p& pos_ned_m, const Vector3f& vel_ned_ms, const Vector3f& accel_ned_mss, bool use_yaw = false, float yaw_rad = 0.0, bool use_yaw_rate = false, float yaw_rate_rads = 0.0, bool yaw_relative = false);
const Vector3p& get_target_pos_NED_m() const;
const Vector3f& get_target_vel_NED_ms() const;
const Vector3f& get_target_accel_NED_mss() const;
bool set_attitude_target_provides_thrust() const;
bool stabilizing_pos_NE() const;
bool stabilizing_vel_NE() const;
bool use_wpnav_for_position_control() const;
void limit_clear();
void limit_init_time_and_pos();
void limit_set(uint32_t timeout_ms, float alt_min_m, float alt_max_m, float horiz_max_m);
bool limit_check();
bool is_taking_off() const override;
bool set_speed_NE_ms(float speed_ne_ms) override;
bool set_speed_up_ms(float speed_up_ms) override;
bool set_speed_down_ms(float speed_down_ms) override;
bool do_user_takeoff_start_m(float takeoff_alt_m) override;
enum class SubMode {
TakeOff,
WP,
Pos,
PosVelAccel,
VelAccel,
Accel,
Angle,
};
SubMode submode() const { return guided_mode; }
void angle_control_start();
void angle_control_run();
uint32_t get_timeout_ms() const;
bool use_pilot_yaw() const override;
bool pause() override;
bool resume() override;
#if WEATHERVANE_ENABLED
bool allows_weathervaning(void) const override;
#endif
protected:
const char *name() const override { return "Guided"; }
const char *name4() const override { return "GUID"; }
float wp_distance_m() const override;
float wp_bearing_deg() const override;
float crosstrack_error_m() const override;
private:
enum class Option : uint32_t {
AllowArmingFromTX = (1U << 0),
IgnorePilotYaw = (1U << 2),
SetAttitudeTarget_ThrustAsThrust = (1U << 3),
DoNotStabilizePositionXY = (1U << 4),
DoNotStabilizeVelocityXY = (1U << 5),
WPNavUsedForPosControl = (1U << 6),
AllowWeatherVaning = (1U << 7)
};
bool option_is_enabled(Option option) const;
void wp_control_start();
void wp_control_run();
void pva_control_start();
void pos_control_start();
void accel_control_start();
void velaccel_control_start();
void posvelaccel_control_start();
void takeoff_run();
void pos_control_run();
void accel_control_run();
void velaccel_control_run();
void pause_control_run();
void posvelaccel_control_run();
void set_yaw_state_rad(bool use_yaw, float yaw_rad, bool use_yaw_rate, float yaw_rate_rads, bool relative_angle);
static SubMode guided_mode;
static bool send_notification;
static bool takeoff_complete;
static bool _paused;
};
#if AP_SCRIPTING_ENABLED
class ModeGuidedCustom : public ModeGuided {
public:
ModeGuidedCustom(const Number _number, const char* _full_name, const char* _short_name);
bool init(bool ignore_checks) override;
Number mode_number() const override { return number; }
const char *name() const override { return full_name; }
const char *name4() const override { return short_name; }
AP_Vehicle::custom_mode_state state;
private:
const Number number;
const char* full_name;
const char* short_name;
};
#endif
class ModeGuidedNoGPS : public ModeGuided {
public:
using ModeGuided::Mode;
Number mode_number() const override { return Number::GUIDED_NOGPS; }
bool init(bool ignore_checks) override;
void run() override;
bool requires_position() const override { return false; }
bool has_manual_throttle() const override { return false; }
bool is_autopilot() const override { return true; }
protected:
const char *name() const override { return "Guided No GPS"; }
const char *name4() const override { return "GNGP"; }
private:
};
class ModeLand : public Mode {
public:
ModeLand(void);
Number mode_number() const override { return Number::LAND; }
bool init(bool ignore_checks) override;
void run() override;
bool requires_position() const override { return false; }
bool has_manual_throttle() const override { return false; }
bool allows_arming(AP_Arming::Method method) const override { return false; };
bool is_autopilot() const override { return true; }
bool is_landing() const override { return true; };
#if AP_COPTER_ADVANCED_FAILSAFE_ENABLED
AP_AdvancedFailsafe_Copter::control_mode afs_mode() const override { return AP_AdvancedFailsafe_Copter::control_mode::AFS_AUTO; }
#endif
void do_not_use_GPS();
bool controlling_position() const { return control_position; }
void set_land_pause(bool new_value) { land_pause = new_value; }
float get_land_speed_ms() const { return land_speed_ms.get(); }
float get_land_speed_high_ms() const { return land_speed_high_ms.get(); }
float get_land_alt_low_m() const { return land_alt_low_m.get(); }
void convert_params();
static const struct AP_Param::GroupInfo var_info[];
protected:
const char *name() const override { return "Land"; }
const char *name4() const override { return "LAND"; }
private:
void gps_run();
void nogps_run();
bool control_position;
AP_Float land_speed_ms;
AP_Float land_speed_high_ms;
AP_Float land_alt_low_m;
uint32_t land_start_time;
bool land_pause;
};
class ModeLoiter : public Mode {
public:
using Mode::Mode;
Number mode_number() const override { return Number::LOITER; }
bool init(bool ignore_checks) override;
void run() override;
bool requires_position() const override { return true; }
bool has_manual_throttle() const override { return false; }
bool allows_arming(AP_Arming::Method method) const override { return true; };
bool is_autopilot() const override { return false; }
bool has_user_takeoff(bool must_navigate) const override { return true; }
bool allows_autotune() const override { return true; }
bool allows_auto_trim() const override { return true; }
#if FRAME_CONFIG == HELI_FRAME
bool allows_inverted() const override { return true; };
#endif
#if AC_PRECLAND_ENABLED
void set_precision_loiter_enabled(bool value) { _precision_loiter_enabled = value; }
#endif
protected:
const char *name() const override { return "Loiter"; }
const char *name4() const override { return "LOIT"; }
float wp_distance_m() const override;
float wp_bearing_deg() const override;
float crosstrack_error_m() const override { return pos_control->crosstrack_error_m();}
#if AC_PRECLAND_ENABLED
bool do_precision_loiter();
void precision_loiter_xy();
#endif
private:
#if AC_PRECLAND_ENABLED
bool _precision_loiter_enabled;
bool _precision_loiter_active;
#endif
};
class ModePosHold : public Mode {
public:
using Mode::Mode;
Number mode_number() const override { return Number::POSHOLD; }
bool init(bool ignore_checks) override;
void run() override;
bool requires_position() const override { return true; }
bool has_manual_throttle() const override { return false; }
bool allows_arming(AP_Arming::Method method) const override { return true; };
bool is_autopilot() const override { return false; }
bool has_user_takeoff(bool must_navigate) const override { return true; }
bool allows_autotune() const override { return true; }
bool allows_auto_trim() const override { return true; }
protected:
const char *name() const override { return "Position Hold"; }
const char *name4() const override { return "PHLD"; }
private:
void update_pilot_lean_angle_rad(float &lean_angle_filtered_rad, float &lean_angle_raw_rad);
float mix_controls(float mix_ratio, float first_control, float second_control);
void update_brake_angle_from_velocity(float &brake_angle_rad, float velocity_ms);
void init_wind_comp_estimate();
void update_wind_comp_estimate();
void get_wind_comp_lean_angles_rad(float &roll_angle_rad, float &pitch_angle_rad);
void roll_controller_to_pilot_override();
void pitch_controller_to_pilot_override();
enum class RPMode {
PILOT_OVERRIDE=0,
BRAKE,
BRAKE_READY_TO_LOITER,
BRAKE_TO_LOITER,
LOITER,
CONTROLLER_TO_PILOT_OVERRIDE
};
RPMode roll_mode;
RPMode pitch_mode;
float pilot_roll_rad;
float pilot_pitch_rad;
struct {
bool time_updated_roll;
bool time_updated_pitch;
float gain;
float roll_rad;
float pitch_rad;
uint32_t start_time_roll_ms;
uint32_t start_time_pitch_ms;
float angle_max_roll_rad;
float angle_max_pitch_rad;
uint32_t loiter_transition_start_time_ms;
} brake;
uint32_t controller_to_pilot_start_time_roll_ms;
uint32_t controller_to_pilot_start_time_pitch_ms;
float controller_final_roll_rad;
float controller_final_pitch_rad;
Vector2f wind_comp_ne_mss;
float wind_comp_roll_rad;
float wind_comp_pitch_rad;
uint32_t wind_comp_start_time_ms;
float roll_rad;
float pitch_rad;
};
class ModeRTL : public Mode {
public:
ModeRTL(void);
Number mode_number() const override { return Number::RTL; }
bool init(bool ignore_checks) override;
void run() override {
return run(true);
}
void run(bool disarm_on_land);
bool requires_position() const override { return true; }
bool has_manual_throttle() const override { return false; }
bool allows_arming(AP_Arming::Method method) const override { return false; };
bool is_autopilot() const override { return true; }
bool requires_terrain_failsafe() const override { return true; }
#if AP_COPTER_ADVANCED_FAILSAFE_ENABLED
AP_AdvancedFailsafe_Copter::control_mode afs_mode() const override { return AP_AdvancedFailsafe_Copter::control_mode::AFS_AUTO; }
#endif
bool get_wp(Location &loc) const override;
bool use_pilot_yaw() const override;
bool set_speed_NE_ms(float speed_ne_ms) override;
bool set_speed_up_ms(float speed_up_ms) override;
bool set_speed_down_ms(float speed_down_ms) override;
enum class SubMode : uint8_t {
STARTING,
INITIAL_CLIMB,
RETURN_HOME,
LOITER_AT_HOME,
FINAL_DESCENT,
LAND
};
SubMode state() { return _state; }
bool state_complete() const { return _state_complete; }
virtual bool is_landing() const override;
void restart_without_terrain();
enum class RTLAltType : int8_t {
RELATIVE = 0,
TERRAIN = 1
};
ModeRTL::RTLAltType get_alt_type() const;
float get_altitude_m() const { return altitude_m.get(); }
float get_speed_ms() const { return speed_ms.get(); }
float get_alt_final_m() const { return alt_final_m.get(); }
float get_climb_min_m() const { return climb_min_m.get(); }
void convert_params();
static const struct AP_Param::GroupInfo var_info[];
protected:
const char *name() const override { return "RTL"; }
const char *name4() const override { return "RTL "; }
float wp_distance_m() const override;
float wp_bearing_deg() const override;
float crosstrack_error_m() const override { return wp_nav->crosstrack_error_m();}
void descent_start();
void descent_run();
void land_start();
void land_run(bool disarm_on_land);
void set_descent_target_alt(uint32_t alt) { rtl_path.descent_target.alt = alt; }
private:
void climb_start();
void return_start();
void climb_return_run();
void loiterathome_start();
void loiterathome_run();
void build_path();
void compute_return_target();
AP_Float altitude_m;
AP_Float speed_ms;
AP_Float alt_final_m;
AP_Float climb_min_m;
SubMode _state = SubMode::INITIAL_CLIMB;
bool _state_complete = false;
struct {
Location origin_point;
Location climb_target;
Location return_target;
Location descent_target;
bool land;
} rtl_path;
enum class ReturnTargetAltType {
RELATIVE = 0,
RANGEFINDER = 1,
TERRAINDATABASE = 2
};
uint32_t _loiter_start_time;
bool terrain_following_allowed;
enum class Option : int32_t {
IgnorePilotYaw = (1U << 2),
};
bool option_is_enabled(Option option) const;
};
class ModeSmartRTL : public ModeRTL {
public:
using ModeRTL::Mode;
Number mode_number() const override { return Number::SMART_RTL; }
bool init(bool ignore_checks) override;
void run() override;
bool requires_position() const override { return true; }
bool has_manual_throttle() const override { return false; }
bool allows_arming(AP_Arming::Method method) const override { return false; }
bool is_autopilot() const override { return true; }
void save_position();
void exit() override;
bool is_landing() const override;
bool use_pilot_yaw() const override;
enum class SubMode : uint8_t {
WAIT_FOR_PATH_CLEANUP,
PATH_FOLLOW,
PRELAND_POSITION,
DESCEND,
LAND
};
protected:
const char *name() const override { return "Smart RTL"; }
const char *name4() const override { return "SRTL"; }
bool get_wp(Location &loc) const override;
float wp_distance_m() const override;
float wp_bearing_deg() const override;
float crosstrack_error_m() const override { return wp_nav->crosstrack_error_m();}
private:
void wait_cleanup_run();
void path_follow_run();
void pre_land_position_run();
void land();
SubMode smart_rtl_state = SubMode::PATH_FOLLOW;
uint32_t path_follow_last_pop_fail_ms;
Vector3p dest_NED_backup;
};
class ModeSport : public Mode {
public:
using Mode::Mode;
Number mode_number() const override { return Number::SPORT; }
bool init(bool ignore_checks) override;
void run() override;
bool requires_position() const override { return false; }
bool has_manual_throttle() const override { return false; }
bool allows_arming(AP_Arming::Method method) const override { return true; };
bool is_autopilot() const override { return false; }
bool has_user_takeoff(bool must_navigate) const override {
return !must_navigate;
}
protected:
const char *name() const override { return "Sport"; }
const char *name4() const override { return "SPRT"; }
private:
};
class ModeStabilize : public Mode {
public:
using Mode::Mode;
Number mode_number() const override { return Number::STABILIZE; }
virtual void run() override;
bool requires_position() const override { return false; }
bool has_manual_throttle() const override { return true; }
bool allows_arming(AP_Arming::Method method) const override { return true; };
bool is_autopilot() const override { return false; }
bool allows_save_trim() const override { return true; }
bool allows_auto_trim() const override { return true; }
bool allows_autotune() const override { return true; }
bool allows_flip() const override { return true; }
bool allows_entry_in_rc_failsafe() const override { return false; }
protected:
const char *name() const override { return "Stabilize"; }
const char *name4() const override { return "STAB"; }
private:
};
#if FRAME_CONFIG == HELI_FRAME
class ModeStabilize_Heli : public ModeStabilize {
public:
using ModeStabilize::Mode;
bool init(bool ignore_checks) override;
void run() override;
bool allows_inverted() const override { return true; };
protected:
private:
};
#endif
class ModeSystemId : public Mode {
public:
ModeSystemId(void);
Number mode_number() const override { return Number::SYSTEMID; }
bool init(bool ignore_checks) override;
void run() override;
void exit() override;
bool requires_position() const override { return false; }
bool has_manual_throttle() const override { return true; }
bool allows_arming(AP_Arming::Method method) const override { return false; };
bool is_autopilot() const override { return false; }
bool logs_attitude() const override { return true; }
void set_magnitude(float input) { waveform_magnitude.set(input); }
static const struct AP_Param::GroupInfo var_info[];
Chirp chirp_input;
protected:
const char *name() const override { return "SystemID"; }
const char *name4() const override { return "SYSI"; }
private:
void log_data() const;
bool is_poscontrol_axis_type() const;
enum class AxisType {
NONE = 0,
INPUT_ROLL = 1,
INPUT_PITCH = 2,
INPUT_YAW = 3,
RECOVER_ROLL = 4,
RECOVER_PITCH = 5,
RECOVER_YAW = 6,
RATE_ROLL = 7,
RATE_PITCH = 8,
RATE_YAW = 9,
MIX_ROLL = 10,
MIX_PITCH = 11,
MIX_YAW = 12,
MIX_THROTTLE = 13,
DISTURB_POS_LAT = 14,
DISTURB_POS_LONG = 15,
DISTURB_VEL_LAT = 16,
DISTURB_VEL_LONG = 17,
INPUT_VEL_LAT = 18,
INPUT_VEL_LONG = 19,
};
AP_Int8 axis;
AP_Float waveform_magnitude;
AP_Float frequency_start;
AP_Float frequency_stop;
AP_Float time_fade_in;
AP_Float time_record;
AP_Float time_fade_out;
bool att_bf_feedforward;
float waveform_time;
float waveform_sample;
float waveform_freq_rads;
float time_const_freq;
int8_t log_subsample;
Vector2f target_vel_ne_ms;
Vector2p target_pos_ne_m;
Vector2f input_vel_last_ne_ms;
enum class SystemIDModeState {
SYSTEMID_STATE_STOPPED,
SYSTEMID_STATE_TESTING
} systemid_state;
};
class ModeThrow : public Mode {
public:
using Mode::Mode;
Number mode_number() const override { return Number::THROW; }
bool init(bool ignore_checks) override;
void run() override;
bool requires_position() const override { return true; }
bool has_manual_throttle() const override { return false; }
bool allows_arming(AP_Arming::Method method) const override { return true; };
bool is_autopilot() const override { return false; }
enum class ThrowType {
Upward = 0,
Drop = 1
};
enum class PreThrowMotorState {
STOPPED = 0,
RUNNING = 1,
};
protected:
const char *name() const override { return "Throw"; }
const char *name4() const override { return "THRW"; }
private:
bool throw_detected();
bool throw_position_good() const;
bool throw_height_good() const;
bool throw_attitude_good() const;
enum ThrowModeStage {
Throw_Disarmed,
Throw_Detecting,
Throw_Wait_Throttle_Unlimited,
Throw_Uprighting,
Throw_HgtStabilise,
Throw_PosHold
};
ThrowModeStage stage = Throw_Disarmed;
ThrowModeStage prev_stage = Throw_Disarmed;
uint32_t last_log_ms;
bool nextmode_attempted;
uint32_t free_fall_start_ms;
float free_fall_start_vel_u_ms;
};
#if MODE_TURTLE_ENABLED
class ModeTurtle : public Mode {
public:
using Mode::Mode;
Number mode_number() const override { return Number::TURTLE; }
bool init(bool ignore_checks) override;
void run() override;
void exit() override;
bool requires_position() const override { return false; }
bool has_manual_throttle() const override { return true; }
bool allows_arming(AP_Arming::Method method) const override;
bool is_autopilot() const override { return false; }
void change_motor_direction(bool reverse);
void output_to_motors() override;
bool allows_entry_in_rc_failsafe() const override { return false; }
protected:
const char *name() const override { return "Turtle"; }
const char *name4() const override { return "TRTL"; }
private:
void arm_motors();
void disarm_motors();
float motors_output;
Vector2f motors_input;
uint32_t last_throttle_warning_output_ms;
HAL_Semaphore msem;
bool shutdown;
};
#endif
#if AP_ADSB_AVOIDANCE_ENABLED
class ModeAvoidADSB : public ModeGuided {
public:
using ModeGuided::Mode;
Number mode_number() const override { return Number::AVOID_ADSB; }
bool init(bool ignore_checks) override;
void run() override;
bool requires_position() const override { return true; }
bool has_manual_throttle() const override { return false; }
bool allows_arming(AP_Arming::Method method) const override { return false; }
bool is_autopilot() const override { return true; }
bool set_velocity_NEU_ms(const Vector3f& velocity_neu_cms);
protected:
const char *name() const override { return "Avoid ADSB"; }
const char *name4() const override { return "AVOI"; }
private:
};
#endif
#if MODE_FOLLOW_ENABLED
class ModeFollow : public ModeGuided {
public:
using ModeGuided::Mode;
Number mode_number() const override { return Number::FOLLOW; }
bool init(bool ignore_checks) override;
void exit() override;
void run() override;
bool requires_position() const override { return true; }
bool has_manual_throttle() const override { return false; }
bool allows_arming(AP_Arming::Method method) const override { return false; }
bool is_autopilot() const override { return true; }
protected:
const char *name() const override { return "Follow"; }
const char *name4() const override { return "FOLL"; }
bool get_wp(Location &loc) const override;
float wp_distance_m() const override;
float wp_bearing_deg() const override;
uint32_t last_log_ms;
};
#endif
class ModeZigZag : public Mode {
public:
ModeZigZag(void);
using Mode::Mode;
Number mode_number() const override { return Number::ZIGZAG; }
enum class Destination : uint8_t {
A,
B,
};
enum class Direction : uint8_t {
FORWARD,
RIGHT,
BACKWARD,
LEFT,
} zigzag_direction;
bool init(bool ignore_checks) override;
void exit() override;
void run() override;
void run_auto();
void suspend_auto();
void init_auto();
bool requires_position() const override { return true; }
bool has_manual_throttle() const override { return false; }
bool allows_arming(AP_Arming::Method method) const override { return true; }
bool is_autopilot() const override { return true; }
bool has_user_takeoff(bool must_navigate) const override { return true; }
void save_or_move_to_destination(Destination ab_dest);
void return_to_manual_control(bool maintain_target);
static const struct AP_Param::GroupInfo var_info[];
protected:
const char *name() const override { return "ZigZag"; }
const char *name4() const override { return "ZIGZ"; }
float wp_distance_m() const override;
float wp_bearing_deg() const override;
float crosstrack_error_m() const override;
private:
void auto_control();
void manual_control();
bool reached_destination();
bool calculate_next_dest_m(Destination ab_dest, bool use_wpnav_alt, Vector3p& next_dest, bool& is_terrain_alt) const;
void spray(bool b);
bool calculate_side_dest_m(Vector3p& next_dest_ned_m, bool& is_terrain_alt) const;
void move_to_side();
Vector2p dest_A_ne_m;
Vector2p dest_B_ne_m;
Vector3p current_dest_ned_m;
bool current_is_terr_alt;
AP_Int8 _auto_enabled;
#if HAL_SPRAYER_ENABLED
AP_Int8 _spray_enabled;
#endif
AP_Int8 _wp_delay_s;
AP_Float _side_dist_m;
AP_Int8 _direction;
AP_Int16 _line_num;
enum ZigZagState {
STORING_POINTS,
AUTO,
MANUAL_REGAIN
} stage;
enum AutoState {
MANUAL,
AB_MOVING,
SIDEWAYS,
} auto_stage;
uint32_t reach_wp_time_ms = 0;
Destination ab_dest_stored;
bool is_auto;
uint16_t line_count = 0;
int16_t line_num = 0;
bool is_suspended;
};
#if MODE_AUTOROTATE_ENABLED
class ModeAutorotate : public Mode {
public:
using Mode::Mode;
Number mode_number() const override { return Number::AUTOROTATE; }
bool init(bool ignore_checks) override;
void run() override;
bool is_autopilot() const override { return true; }
bool requires_position() const override { return false; }
bool has_manual_throttle() const override { return false; }
bool allows_arming(AP_Arming::Method method) const override { return false; };
static const struct AP_Param::GroupInfo var_info[];
protected:
const char *name() const override { return "Autorotate"; }
const char *name4() const override { return "AROT"; }
private:
uint32_t _entry_time_start_ms;
uint32_t _last_logged_ms;
enum class Phase {
ENTRY_INIT,
ENTRY,
GLIDE_INIT,
GLIDE,
FLARE_INIT,
FLARE,
TOUCH_DOWN_INIT,
TOUCH_DOWN,
LANDED_INIT,
LANDED,
} current_phase;
};
#endif