mirror of https://github.com/ArduPilot/ardupilot
Sub: big mode refactor
This commit is contained in:
parent
d31f0d2312
commit
9b70ac1286
|
@ -134,7 +134,7 @@ bool AP_Arming_Sub::arm(AP_Arming::Method method, bool do_arming_checks)
|
||||||
sub.motors.armed(true);
|
sub.motors.armed(true);
|
||||||
|
|
||||||
// log flight mode in case it was changed while vehicle was disarmed
|
// log flight mode in case it was changed while vehicle was disarmed
|
||||||
AP::logger().Write_Mode(sub.control_mode, sub.control_mode_reason);
|
AP::logger().Write_Mode((uint8_t)sub.control_mode, sub.control_mode_reason);
|
||||||
|
|
||||||
// reenable failsafe
|
// reenable failsafe
|
||||||
sub.mainloop_failsafe_enable();
|
sub.mainloop_failsafe_enable();
|
||||||
|
|
|
@ -140,7 +140,7 @@ void Sub::run_rate_controller()
|
||||||
pos_control.set_dt(last_loop_time_s);
|
pos_control.set_dt(last_loop_time_s);
|
||||||
|
|
||||||
//don't run rate controller in manual or motordetection modes
|
//don't run rate controller in manual or motordetection modes
|
||||||
if (control_mode != MANUAL && control_mode != MOTOR_DETECT) {
|
if (control_mode != Mode::Number::MANUAL && control_mode != Mode::Number::MOTOR_DETECT) {
|
||||||
// run low level rate controllers that only require IMU data and set loop time
|
// run low level rate controllers that only require IMU data and set loop time
|
||||||
attitude_control.rate_controller_run();
|
attitude_control.rate_controller_run();
|
||||||
}
|
}
|
||||||
|
@ -201,7 +201,7 @@ void Sub::ten_hz_logging_loop()
|
||||||
if (should_log(MASK_LOG_RCOUT)) {
|
if (should_log(MASK_LOG_RCOUT)) {
|
||||||
logger.Write_RCOUT();
|
logger.Write_RCOUT();
|
||||||
}
|
}
|
||||||
if (should_log(MASK_LOG_NTUN) && (mode_requires_GPS(control_mode) || !mode_has_manual_throttle(control_mode))) {
|
if (should_log(MASK_LOG_NTUN) && (sub.flightmode->requires_GPS() || !sub.flightmode->has_manual_throttle())) {
|
||||||
pos_control.write_log();
|
pos_control.write_log();
|
||||||
}
|
}
|
||||||
if (should_log(MASK_LOG_IMU) || should_log(MASK_LOG_IMU_FAST) || should_log(MASK_LOG_IMU_RAW)) {
|
if (should_log(MASK_LOG_IMU) || should_log(MASK_LOG_IMU_FAST) || should_log(MASK_LOG_IMU_RAW)) {
|
||||||
|
|
|
@ -21,10 +21,10 @@ MAV_MODE GCS_MAVLINK_Sub::base_mode() const
|
||||||
// the APM flight mode and has a well defined meaning in the
|
// the APM flight mode and has a well defined meaning in the
|
||||||
// ArduPlane documentation
|
// ArduPlane documentation
|
||||||
switch (sub.control_mode) {
|
switch (sub.control_mode) {
|
||||||
case AUTO:
|
case Mode::Number::AUTO:
|
||||||
case GUIDED:
|
case Mode::Number::GUIDED:
|
||||||
case CIRCLE:
|
case Mode::Number::CIRCLE:
|
||||||
case POSHOLD:
|
case Mode::Number::POSHOLD:
|
||||||
_base_mode |= MAV_MODE_FLAG_GUIDED_ENABLED;
|
_base_mode |= MAV_MODE_FLAG_GUIDED_ENABLED;
|
||||||
// note that MAV_MODE_FLAG_AUTO_ENABLED does not match what
|
// note that MAV_MODE_FLAG_AUTO_ENABLED does not match what
|
||||||
// APM does in any mode, as that is defined as "system finds its own goal
|
// APM does in any mode, as that is defined as "system finds its own goal
|
||||||
|
@ -50,7 +50,7 @@ MAV_MODE GCS_MAVLINK_Sub::base_mode() const
|
||||||
|
|
||||||
uint32_t GCS_Sub::custom_mode() const
|
uint32_t GCS_Sub::custom_mode() const
|
||||||
{
|
{
|
||||||
return sub.control_mode;
|
return (uint32_t)sub.control_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
MAV_STATE GCS_MAVLINK_Sub::vehicle_system_status() const
|
MAV_STATE GCS_MAVLINK_Sub::vehicle_system_status() const
|
||||||
|
@ -448,7 +448,7 @@ MAV_RESULT GCS_MAVLINK_Sub::handle_command_do_set_roi(const Location &roi_loc)
|
||||||
if (!roi_loc.check_latlng()) {
|
if (!roi_loc.check_latlng()) {
|
||||||
return MAV_RESULT_FAILED;
|
return MAV_RESULT_FAILED;
|
||||||
}
|
}
|
||||||
sub.set_auto_yaw_roi(roi_loc);
|
sub.mode_auto.set_auto_yaw_roi(roi_loc);
|
||||||
return MAV_RESULT_ACCEPTED;
|
return MAV_RESULT_ACCEPTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -464,13 +464,13 @@ MAV_RESULT GCS_MAVLINK_Sub::handle_command_long_packet(const mavlink_command_lon
|
||||||
{
|
{
|
||||||
switch (packet.command) {
|
switch (packet.command) {
|
||||||
case MAV_CMD_NAV_LOITER_UNLIM:
|
case MAV_CMD_NAV_LOITER_UNLIM:
|
||||||
if (!sub.set_mode(POSHOLD, ModeReason::GCS_COMMAND)) {
|
if (!sub.set_mode(Mode::Number::POSHOLD, ModeReason::GCS_COMMAND)) {
|
||||||
return MAV_RESULT_FAILED;
|
return MAV_RESULT_FAILED;
|
||||||
}
|
}
|
||||||
return MAV_RESULT_ACCEPTED;
|
return MAV_RESULT_ACCEPTED;
|
||||||
|
|
||||||
case MAV_CMD_NAV_LAND:
|
case MAV_CMD_NAV_LAND:
|
||||||
if (!sub.set_mode(SURFACE, ModeReason::GCS_COMMAND)) {
|
if (!sub.set_mode(Mode::Number::SURFACE, ModeReason::GCS_COMMAND)) {
|
||||||
return MAV_RESULT_FAILED;
|
return MAV_RESULT_FAILED;
|
||||||
}
|
}
|
||||||
return MAV_RESULT_ACCEPTED;
|
return MAV_RESULT_ACCEPTED;
|
||||||
|
@ -483,7 +483,7 @@ MAV_RESULT GCS_MAVLINK_Sub::handle_command_long_packet(const mavlink_command_lon
|
||||||
if ((packet.param1 >= 0.0f) &&
|
if ((packet.param1 >= 0.0f) &&
|
||||||
(packet.param1 <= 360.0f) &&
|
(packet.param1 <= 360.0f) &&
|
||||||
(is_zero(packet.param4) || is_equal(packet.param4,1.0f))) {
|
(is_zero(packet.param4) || is_equal(packet.param4,1.0f))) {
|
||||||
sub.set_auto_yaw_look_at_heading(packet.param1, packet.param2, (int8_t)packet.param3, (uint8_t)packet.param4);
|
sub.mode_auto.set_auto_yaw_look_at_heading(packet.param1, packet.param2, (int8_t)packet.param3, (uint8_t)packet.param4);
|
||||||
return MAV_RESULT_ACCEPTED;
|
return MAV_RESULT_ACCEPTED;
|
||||||
}
|
}
|
||||||
return MAV_RESULT_FAILED;
|
return MAV_RESULT_FAILED;
|
||||||
|
@ -500,7 +500,7 @@ MAV_RESULT GCS_MAVLINK_Sub::handle_command_long_packet(const mavlink_command_lon
|
||||||
return MAV_RESULT_FAILED;
|
return MAV_RESULT_FAILED;
|
||||||
|
|
||||||
case MAV_CMD_MISSION_START:
|
case MAV_CMD_MISSION_START:
|
||||||
if (sub.motors.armed() && sub.set_mode(AUTO, ModeReason::GCS_COMMAND)) {
|
if (sub.motors.armed() && sub.set_mode(Mode::Number::AUTO, ModeReason::GCS_COMMAND)) {
|
||||||
return MAV_RESULT_ACCEPTED;
|
return MAV_RESULT_ACCEPTED;
|
||||||
}
|
}
|
||||||
return MAV_RESULT_FAILED;
|
return MAV_RESULT_FAILED;
|
||||||
|
@ -588,7 +588,7 @@ void GCS_MAVLINK_Sub::handleMessage(const mavlink_message_t &msg)
|
||||||
// descend at up to WPNAV_SPEED_DN
|
// descend at up to WPNAV_SPEED_DN
|
||||||
climb_rate_cms = (packet.thrust - 0.5f) * 2.0f * sub.wp_nav.get_default_speed_down();
|
climb_rate_cms = (packet.thrust - 0.5f) * 2.0f * sub.wp_nav.get_default_speed_down();
|
||||||
}
|
}
|
||||||
sub.guided_set_angle(Quaternion(packet.q[0],packet.q[1],packet.q[2],packet.q[3]), climb_rate_cms);
|
sub.mode_guided.guided_set_angle(Quaternion(packet.q[0],packet.q[1],packet.q[2],packet.q[3]), climb_rate_cms);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -598,7 +598,7 @@ void GCS_MAVLINK_Sub::handleMessage(const mavlink_message_t &msg)
|
||||||
mavlink_msg_set_position_target_local_ned_decode(&msg, &packet);
|
mavlink_msg_set_position_target_local_ned_decode(&msg, &packet);
|
||||||
|
|
||||||
// exit if vehicle is not in Guided mode or Auto-Guided mode
|
// exit if vehicle is not in Guided mode or Auto-Guided mode
|
||||||
if ((sub.control_mode != GUIDED) && !(sub.control_mode == AUTO && sub.auto_mode == Auto_NavGuided)) {
|
if ((sub.control_mode != Mode::Number::GUIDED) && !(sub.control_mode == Mode::Number::AUTO && sub.auto_mode == Auto_NavGuided)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -652,11 +652,11 @@ void GCS_MAVLINK_Sub::handleMessage(const mavlink_message_t &msg)
|
||||||
|
|
||||||
// send request
|
// send request
|
||||||
if (!pos_ignore && !vel_ignore && acc_ignore) {
|
if (!pos_ignore && !vel_ignore && acc_ignore) {
|
||||||
sub.guided_set_destination_posvel(pos_vector, vel_vector);
|
sub.mode_guided.guided_set_destination_posvel(pos_vector, vel_vector);
|
||||||
} else if (pos_ignore && !vel_ignore && acc_ignore) {
|
} else if (pos_ignore && !vel_ignore && acc_ignore) {
|
||||||
sub.guided_set_velocity(vel_vector);
|
sub.mode_guided.guided_set_velocity(vel_vector);
|
||||||
} else if (!pos_ignore && vel_ignore && acc_ignore) {
|
} else if (!pos_ignore && vel_ignore && acc_ignore) {
|
||||||
sub.guided_set_destination(pos_vector);
|
sub.mode_guided.guided_set_destination(pos_vector);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -668,9 +668,9 @@ void GCS_MAVLINK_Sub::handleMessage(const mavlink_message_t &msg)
|
||||||
mavlink_msg_set_position_target_global_int_decode(&msg, &packet);
|
mavlink_msg_set_position_target_global_int_decode(&msg, &packet);
|
||||||
|
|
||||||
// exit if vehicle is not in Guided, Auto-Guided, or Depth Hold modes
|
// exit if vehicle is not in Guided, Auto-Guided, or Depth Hold modes
|
||||||
if ((sub.control_mode != GUIDED)
|
if ((sub.control_mode != Mode::Number::GUIDED)
|
||||||
&& !(sub.control_mode == AUTO && sub.auto_mode == Auto_NavGuided)
|
&& !(sub.control_mode == Mode::Number::AUTO && sub.auto_mode == Auto_NavGuided)
|
||||||
&& !(sub.control_mode == ALT_HOLD)) {
|
&& !(sub.control_mode == Mode::Number::ALT_HOLD)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -686,7 +686,7 @@ void GCS_MAVLINK_Sub::handleMessage(const mavlink_message_t &msg)
|
||||||
* bool yaw_rate_ignore = packet.type_mask & MAVLINK_SET_POS_TYPE_MASK_YAW_RATE_IGNORE;
|
* bool yaw_rate_ignore = packet.type_mask & MAVLINK_SET_POS_TYPE_MASK_YAW_RATE_IGNORE;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!z_ignore && sub.control_mode == ALT_HOLD) { // Control only target depth when in ALT_HOLD
|
if (!z_ignore && sub.control_mode == Mode::Number::ALT_HOLD) { // Control only target depth when in ALT_HOLD
|
||||||
sub.pos_control.set_pos_target_z_cm(packet.alt*100);
|
sub.pos_control.set_pos_target_z_cm(packet.alt*100);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -715,11 +715,11 @@ void GCS_MAVLINK_Sub::handleMessage(const mavlink_message_t &msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pos_ignore && !vel_ignore && acc_ignore) {
|
if (!pos_ignore && !vel_ignore && acc_ignore) {
|
||||||
sub.guided_set_destination_posvel(pos_neu_cm, Vector3f(packet.vx * 100.0f, packet.vy * 100.0f, -packet.vz * 100.0f));
|
sub.mode_guided.guided_set_destination_posvel(pos_neu_cm, Vector3f(packet.vx * 100.0f, packet.vy * 100.0f, -packet.vz * 100.0f));
|
||||||
} else if (pos_ignore && !vel_ignore && acc_ignore) {
|
} else if (pos_ignore && !vel_ignore && acc_ignore) {
|
||||||
sub.guided_set_velocity(Vector3f(packet.vx * 100.0f, packet.vy * 100.0f, -packet.vz * 100.0f));
|
sub.mode_guided.guided_set_velocity(Vector3f(packet.vx * 100.0f, packet.vy * 100.0f, -packet.vz * 100.0f));
|
||||||
} else if (!pos_ignore && vel_ignore && acc_ignore) {
|
} else if (!pos_ignore && vel_ignore && acc_ignore) {
|
||||||
sub.guided_set_destination(pos_neu_cm);
|
sub.mode_guided.guided_set_destination(pos_neu_cm);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -794,7 +794,7 @@ int16_t GCS_MAVLINK_Sub::high_latency_target_altitude() const
|
||||||
UNUSED_RESULT(ahrs.get_location(global_position_current));
|
UNUSED_RESULT(ahrs.get_location(global_position_current));
|
||||||
|
|
||||||
//return units are m
|
//return units are m
|
||||||
if (sub.control_mode == AUTO || sub.control_mode == GUIDED) {
|
if (sub.control_mode == Mode::Number::AUTO || sub.control_mode == Mode::Number::GUIDED) {
|
||||||
return 0.01 * (global_position_current.alt + sub.pos_control.get_pos_error_z_cm());
|
return 0.01 * (global_position_current.alt + sub.pos_control.get_pos_error_z_cm());
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -804,7 +804,7 @@ int16_t GCS_MAVLINK_Sub::high_latency_target_altitude() const
|
||||||
uint8_t GCS_MAVLINK_Sub::high_latency_tgt_heading() const
|
uint8_t GCS_MAVLINK_Sub::high_latency_tgt_heading() const
|
||||||
{
|
{
|
||||||
// return units are deg/2
|
// return units are deg/2
|
||||||
if (sub.control_mode == AUTO || sub.control_mode == GUIDED) {
|
if (sub.control_mode == Mode::Number::AUTO || sub.control_mode == Mode::Number::GUIDED) {
|
||||||
// need to convert -18000->18000 to 0->360/2
|
// need to convert -18000->18000 to 0->360/2
|
||||||
return wrap_360_cd(sub.wp_nav.get_wp_bearing_to_destination()) / 200;
|
return wrap_360_cd(sub.wp_nav.get_wp_bearing_to_destination()) / 200;
|
||||||
}
|
}
|
||||||
|
@ -814,7 +814,7 @@ uint8_t GCS_MAVLINK_Sub::high_latency_tgt_heading() const
|
||||||
uint16_t GCS_MAVLINK_Sub::high_latency_tgt_dist() const
|
uint16_t GCS_MAVLINK_Sub::high_latency_tgt_dist() const
|
||||||
{
|
{
|
||||||
// return units are dm
|
// return units are dm
|
||||||
if (sub.control_mode == AUTO || sub.control_mode == GUIDED) {
|
if (sub.control_mode == Mode::Number::AUTO || sub.control_mode == Mode::Number::GUIDED) {
|
||||||
return MIN(sub.wp_nav.get_wp_distance_to_destination() * 0.001, UINT16_MAX);
|
return MIN(sub.wp_nav.get_wp_distance_to_destination() * 0.001, UINT16_MAX);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -823,7 +823,7 @@ uint16_t GCS_MAVLINK_Sub::high_latency_tgt_dist() const
|
||||||
uint8_t GCS_MAVLINK_Sub::high_latency_tgt_airspeed() const
|
uint8_t GCS_MAVLINK_Sub::high_latency_tgt_airspeed() const
|
||||||
{
|
{
|
||||||
// return units are m/s*5
|
// return units are m/s*5
|
||||||
if (sub.control_mode == AUTO || sub.control_mode == GUIDED) {
|
if (sub.control_mode == Mode::Number::AUTO || sub.control_mode == Mode::Number::GUIDED) {
|
||||||
return MIN((sub.pos_control.get_vel_desired_cms().length()/100) * 5, UINT8_MAX);
|
return MIN((sub.pos_control.get_vel_desired_cms().length()/100) * 5, UINT8_MAX);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -30,12 +30,12 @@ void GCS_Sub::update_vehicle_sensor_status_flags()
|
||||||
MAV_SYS_STATUS_SENSOR_XY_POSITION_CONTROL;
|
MAV_SYS_STATUS_SENSOR_XY_POSITION_CONTROL;
|
||||||
|
|
||||||
switch (sub.control_mode) {
|
switch (sub.control_mode) {
|
||||||
case ALT_HOLD:
|
case Mode::Number::ALT_HOLD:
|
||||||
case AUTO:
|
case Mode::Number::AUTO:
|
||||||
case GUIDED:
|
case Mode::Number::GUIDED:
|
||||||
case CIRCLE:
|
case Mode::Number::CIRCLE:
|
||||||
case SURFACE:
|
case Mode::Number::SURFACE:
|
||||||
case POSHOLD:
|
case Mode::Number::POSHOLD:
|
||||||
control_sensors_enabled |= MAV_SYS_STATUS_SENSOR_Z_ALTITUDE_CONTROL;
|
control_sensors_enabled |= MAV_SYS_STATUS_SENSOR_Z_ALTITUDE_CONTROL;
|
||||||
control_sensors_health |= MAV_SYS_STATUS_SENSOR_Z_ALTITUDE_CONTROL;
|
control_sensors_health |= MAV_SYS_STATUS_SENSOR_Z_ALTITUDE_CONTROL;
|
||||||
control_sensors_enabled |= MAV_SYS_STATUS_SENSOR_XY_POSITION_CONTROL;
|
control_sensors_enabled |= MAV_SYS_STATUS_SENSOR_XY_POSITION_CONTROL;
|
||||||
|
|
|
@ -278,7 +278,7 @@ const struct LogStructure Sub::log_structure[] = {
|
||||||
void Sub::Log_Write_Vehicle_Startup_Messages()
|
void Sub::Log_Write_Vehicle_Startup_Messages()
|
||||||
{
|
{
|
||||||
// only 200(?) bytes are guaranteed by AP_Logger
|
// only 200(?) bytes are guaranteed by AP_Logger
|
||||||
logger.Write_Mode(control_mode, control_mode_reason);
|
logger.Write_Mode((uint8_t)control_mode, control_mode_reason);
|
||||||
ahrs.Log_Write_Home_And_Origin();
|
ahrs.Log_Write_Home_And_Origin();
|
||||||
gps.Write_AP_Logger_Log_Startup_messages();
|
gps.Write_AP_Logger_Log_Startup_messages();
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ const AP_HAL::HAL& hal = AP_HAL::get_HAL();
|
||||||
*/
|
*/
|
||||||
Sub::Sub()
|
Sub::Sub()
|
||||||
: logger(g.log_bitmask),
|
: logger(g.log_bitmask),
|
||||||
control_mode(MANUAL),
|
control_mode(Mode::Number::MANUAL),
|
||||||
motors(MAIN_LOOP_RATE),
|
motors(MAIN_LOOP_RATE),
|
||||||
auto_mode(Auto_WP),
|
auto_mode(Auto_WP),
|
||||||
guided_mode(Guided_WP),
|
guided_mode(Guided_WP),
|
||||||
|
@ -37,7 +37,8 @@ Sub::Sub()
|
||||||
wp_nav(inertial_nav, ahrs_view, pos_control, attitude_control),
|
wp_nav(inertial_nav, ahrs_view, pos_control, attitude_control),
|
||||||
loiter_nav(inertial_nav, ahrs_view, pos_control, attitude_control),
|
loiter_nav(inertial_nav, ahrs_view, pos_control, attitude_control),
|
||||||
circle_nav(inertial_nav, ahrs_view, pos_control),
|
circle_nav(inertial_nav, ahrs_view, pos_control),
|
||||||
param_loader(var_info)
|
param_loader(var_info),
|
||||||
|
flightmode(&mode_manual)
|
||||||
{
|
{
|
||||||
#if CONFIG_HAL_BOARD != HAL_BOARD_SITL
|
#if CONFIG_HAL_BOARD != HAL_BOARD_SITL
|
||||||
failsafe.pilot_input = true;
|
failsafe.pilot_input = true;
|
||||||
|
|
108
ArduSub/Sub.h
108
ArduSub/Sub.h
|
@ -71,6 +71,7 @@
|
||||||
#include "Parameters.h"
|
#include "Parameters.h"
|
||||||
#include "AP_Arming_Sub.h"
|
#include "AP_Arming_Sub.h"
|
||||||
#include "GCS_Sub.h"
|
#include "GCS_Sub.h"
|
||||||
|
#include "mode.h"
|
||||||
|
|
||||||
#include <AP_OpticalFlow/AP_OpticalFlow.h> // Optical Flow library
|
#include <AP_OpticalFlow/AP_OpticalFlow.h> // Optical Flow library
|
||||||
|
|
||||||
|
@ -108,6 +109,17 @@ public:
|
||||||
friend class ParametersG2;
|
friend class ParametersG2;
|
||||||
friend class AP_Arming_Sub;
|
friend class AP_Arming_Sub;
|
||||||
friend class RC_Channels_Sub;
|
friend class RC_Channels_Sub;
|
||||||
|
friend class Mode;
|
||||||
|
friend class ModeManual;
|
||||||
|
friend class ModeStabilize;
|
||||||
|
friend class ModeAcro;
|
||||||
|
friend class ModeAlthold;
|
||||||
|
friend class ModeGuided;
|
||||||
|
friend class ModePoshold;
|
||||||
|
friend class ModeAuto;
|
||||||
|
friend class ModeCircle;
|
||||||
|
friend class ModeSurface;
|
||||||
|
friend class ModeMotordetect;
|
||||||
|
|
||||||
Sub(void);
|
Sub(void);
|
||||||
|
|
||||||
|
@ -190,9 +202,9 @@ private:
|
||||||
|
|
||||||
// This is the state of the flight control system
|
// This is the state of the flight control system
|
||||||
// There are multiple states defined such as STABILIZE, ACRO,
|
// There are multiple states defined such as STABILIZE, ACRO,
|
||||||
control_mode_t control_mode;
|
Mode::Number control_mode;
|
||||||
|
|
||||||
control_mode_t prev_control_mode;
|
Mode::Number prev_control_mode;
|
||||||
|
|
||||||
#if RCMAP_ENABLED == ENABLED
|
#if RCMAP_ENABLED == ENABLED
|
||||||
RCMapper rcmap;
|
RCMapper rcmap;
|
||||||
|
@ -234,12 +246,6 @@ private:
|
||||||
|
|
||||||
AP_Motors6DOF motors;
|
AP_Motors6DOF motors;
|
||||||
|
|
||||||
// Auto
|
|
||||||
AutoMode auto_mode; // controls which auto controller is run
|
|
||||||
|
|
||||||
// Guided
|
|
||||||
GuidedMode guided_mode; // controls which controller is run (pos or vel)
|
|
||||||
|
|
||||||
// Circle
|
// Circle
|
||||||
bool circle_pilot_yaw_override; // true if pilot is overriding yaw
|
bool circle_pilot_yaw_override; // true if pilot is overriding yaw
|
||||||
|
|
||||||
|
@ -416,61 +422,7 @@ private:
|
||||||
bool verify_wait_delay();
|
bool verify_wait_delay();
|
||||||
bool verify_within_distance();
|
bool verify_within_distance();
|
||||||
bool verify_yaw();
|
bool verify_yaw();
|
||||||
bool acro_init(void);
|
|
||||||
void acro_run();
|
|
||||||
void get_pilot_desired_angle_rates(int16_t roll_in, int16_t pitch_in, int16_t yaw_in, float &roll_out, float &pitch_out, float &yaw_out);
|
|
||||||
bool althold_init(void);
|
|
||||||
void althold_run();
|
|
||||||
bool auto_init(void);
|
|
||||||
void auto_run();
|
|
||||||
void auto_wp_start(const Vector3f& destination);
|
|
||||||
void auto_wp_start(const Location& dest_loc);
|
|
||||||
void auto_wp_run();
|
|
||||||
void auto_circle_movetoedge_start(const Location &circle_center, float radius_m, bool ccw_turn);
|
|
||||||
void auto_circle_start();
|
|
||||||
void auto_circle_run();
|
|
||||||
void auto_nav_guided_start();
|
|
||||||
void auto_nav_guided_run();
|
|
||||||
bool auto_loiter_start();
|
|
||||||
void auto_loiter_run();
|
|
||||||
uint8_t get_default_auto_yaw_mode(bool rtl) const;
|
|
||||||
void set_auto_yaw_mode(uint8_t yaw_mode);
|
|
||||||
void set_auto_yaw_look_at_heading(float angle_deg, float turn_rate_dps, int8_t direction, uint8_t relative_angle);
|
|
||||||
void set_auto_yaw_roi(const Location &roi_location);
|
|
||||||
float get_auto_heading(void);
|
|
||||||
bool circle_init(void);
|
|
||||||
void circle_run();
|
|
||||||
bool guided_init(bool ignore_checks = false);
|
|
||||||
void guided_pos_control_start();
|
|
||||||
void guided_vel_control_start();
|
|
||||||
void guided_posvel_control_start();
|
|
||||||
void guided_angle_control_start();
|
|
||||||
bool guided_set_destination(const Vector3f& destination);
|
|
||||||
bool guided_set_destination(const Location& dest_loc);
|
|
||||||
void guided_set_velocity(const Vector3f& velocity);
|
|
||||||
bool guided_set_destination_posvel(const Vector3f& destination, const Vector3f& velocity);
|
|
||||||
void guided_set_angle(const Quaternion &q, float climb_rate_cms);
|
|
||||||
void guided_run();
|
|
||||||
void guided_pos_control_run();
|
|
||||||
void guided_vel_control_run();
|
|
||||||
void guided_posvel_control_run();
|
|
||||||
void guided_angle_control_run();
|
|
||||||
void guided_limit_clear();
|
|
||||||
void guided_limit_set(uint32_t timeout_ms, float alt_min_cm, float alt_max_cm, float horiz_max_cm);
|
|
||||||
void guided_limit_init_time_and_pos();
|
|
||||||
bool guided_limit_check();
|
|
||||||
|
|
||||||
bool poshold_init(void);
|
|
||||||
void poshold_run();
|
|
||||||
|
|
||||||
bool motordetect_init();
|
|
||||||
void motordetect_run();
|
|
||||||
|
|
||||||
bool stabilize_init(void);
|
|
||||||
void stabilize_run();
|
|
||||||
void control_depth();
|
|
||||||
bool manual_init(void);
|
|
||||||
void manual_run();
|
|
||||||
void failsafe_sensors_check(void);
|
void failsafe_sensors_check(void);
|
||||||
void failsafe_crash_check();
|
void failsafe_crash_check();
|
||||||
void failsafe_ekf_check(void);
|
void failsafe_ekf_check(void);
|
||||||
|
@ -484,15 +436,12 @@ private:
|
||||||
void mainloop_failsafe_enable();
|
void mainloop_failsafe_enable();
|
||||||
void mainloop_failsafe_disable();
|
void mainloop_failsafe_disable();
|
||||||
void fence_check();
|
void fence_check();
|
||||||
bool set_mode(control_mode_t mode, ModeReason reason);
|
bool set_mode(Mode::Number mode, ModeReason reason);
|
||||||
bool set_mode(const uint8_t mode, const ModeReason reason) override;
|
bool set_mode(const uint8_t new_mode, const ModeReason reason) override;
|
||||||
uint8_t get_mode() const override { return (uint8_t)control_mode; }
|
uint8_t get_mode() const override { return (uint8_t)control_mode; }
|
||||||
void update_flight_mode();
|
void update_flight_mode();
|
||||||
void exit_mode(control_mode_t old_control_mode, control_mode_t new_control_mode);
|
void exit_mode(Mode::Number old_control_mode, Mode::Number new_control_mode);
|
||||||
bool mode_requires_GPS(control_mode_t mode);
|
void notify_flight_mode();
|
||||||
bool mode_has_manual_throttle(control_mode_t mode);
|
|
||||||
bool mode_allows_arming(control_mode_t mode, bool arming_from_gcs);
|
|
||||||
void notify_flight_mode(control_mode_t mode);
|
|
||||||
void read_inertia();
|
void read_inertia();
|
||||||
void update_surface_and_bottom_detector();
|
void update_surface_and_bottom_detector();
|
||||||
void set_surfaced(bool at_surface);
|
void set_surfaced(bool at_surface);
|
||||||
|
@ -563,8 +512,7 @@ private:
|
||||||
void failsafe_internal_temperature_check();
|
void failsafe_internal_temperature_check();
|
||||||
|
|
||||||
void failsafe_terrain_act(void);
|
void failsafe_terrain_act(void);
|
||||||
bool auto_terrain_recover_start(void);
|
|
||||||
void auto_terrain_recover_run(void);
|
|
||||||
|
|
||||||
void translate_wpnav_rp(float &lateral_out, float &forward_out);
|
void translate_wpnav_rp(float &lateral_out, float &forward_out);
|
||||||
void translate_circle_nav_rp(float &lateral_out, float &forward_out);
|
void translate_circle_nav_rp(float &lateral_out, float &forward_out);
|
||||||
|
@ -610,6 +558,24 @@ private:
|
||||||
static_assert(_failsafe_priorities[ARRAY_SIZE(_failsafe_priorities) - 1] == -1,
|
static_assert(_failsafe_priorities[ARRAY_SIZE(_failsafe_priorities) - 1] == -1,
|
||||||
"_failsafe_priorities is missing the sentinel");
|
"_failsafe_priorities is missing the sentinel");
|
||||||
|
|
||||||
|
Mode *mode_from_mode_num(const Mode::Number num);
|
||||||
|
void exit_mode(Mode *&old_flightmode, Mode *&new_flightmode);
|
||||||
|
|
||||||
|
Mode *flightmode;
|
||||||
|
ModeManual mode_manual;
|
||||||
|
ModeStabilize mode_stabilize;
|
||||||
|
ModeAcro mode_acro;
|
||||||
|
ModeAlthold mode_althold;
|
||||||
|
ModeAuto mode_auto;
|
||||||
|
ModeGuided mode_guided;
|
||||||
|
ModePoshold mode_poshold;
|
||||||
|
ModeCircle mode_circle;
|
||||||
|
ModeSurface mode_surface;
|
||||||
|
ModeMotordetect mode_motordetect;
|
||||||
|
|
||||||
|
// Auto
|
||||||
|
AutoSubMode auto_mode; // controls which auto controller is run
|
||||||
|
GuidedSubMode guided_mode;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void mainloop_failsafe_check();
|
void mainloop_failsafe_check();
|
||||||
|
|
|
@ -124,7 +124,7 @@ bool Sub::start_command(const AP_Mission::Mission_Command& cmd)
|
||||||
// called by mission library in mission.update()
|
// called by mission library in mission.update()
|
||||||
bool Sub::verify_command_callback(const AP_Mission::Mission_Command& cmd)
|
bool Sub::verify_command_callback(const AP_Mission::Mission_Command& cmd)
|
||||||
{
|
{
|
||||||
if (control_mode == AUTO) {
|
if (control_mode == Mode::Number::AUTO) {
|
||||||
bool cmd_complete = verify_command(cmd);
|
bool cmd_complete = verify_command(cmd);
|
||||||
|
|
||||||
// send message to GCS
|
// send message to GCS
|
||||||
|
@ -207,8 +207,8 @@ void Sub::exit_mission()
|
||||||
AP_Notify::events.mission_complete = 1;
|
AP_Notify::events.mission_complete = 1;
|
||||||
|
|
||||||
// Try to enter loiter, if that fails, go to depth hold
|
// Try to enter loiter, if that fails, go to depth hold
|
||||||
if (!auto_loiter_start()) {
|
if (!mode_auto.auto_loiter_start()) {
|
||||||
set_mode(ALT_HOLD, ModeReason::MISSION_END);
|
set_mode(Mode::Number::ALT_HOLD, ModeReason::MISSION_END);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,7 +243,7 @@ void Sub::do_nav_wp(const AP_Mission::Mission_Command& cmd)
|
||||||
loiter_time_max = cmd.p1;
|
loiter_time_max = cmd.p1;
|
||||||
|
|
||||||
// Set wp navigation target
|
// Set wp navigation target
|
||||||
auto_wp_start(target_loc);
|
mode_auto.auto_wp_start(target_loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
// do_surface - initiate surface procedure
|
// do_surface - initiate surface procedure
|
||||||
|
@ -279,12 +279,12 @@ void Sub::do_surface(const AP_Mission::Mission_Command& cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Go to wp location
|
// Go to wp location
|
||||||
auto_wp_start(target_location);
|
mode_auto.auto_wp_start(target_location);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sub::do_RTL()
|
void Sub::do_RTL()
|
||||||
{
|
{
|
||||||
auto_wp_start(ahrs.get_home());
|
mode_auto.auto_wp_start(ahrs.get_home());
|
||||||
}
|
}
|
||||||
|
|
||||||
// do_loiter_unlimited - start loitering with no end conditions
|
// do_loiter_unlimited - start loitering with no end conditions
|
||||||
|
@ -323,7 +323,7 @@ void Sub::do_loiter_unlimited(const AP_Mission::Mission_Command& cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
// start way point navigator and provide it the desired location
|
// start way point navigator and provide it the desired location
|
||||||
auto_wp_start(target_loc);
|
mode_auto.auto_wp_start(target_loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
// do_circle - initiate moving in a circle
|
// do_circle - initiate moving in a circle
|
||||||
|
@ -362,7 +362,7 @@ void Sub::do_circle(const AP_Mission::Mission_Command& cmd)
|
||||||
const bool circle_direction_ccw = cmd.content.location.loiter_ccw;
|
const bool circle_direction_ccw = cmd.content.location.loiter_ccw;
|
||||||
|
|
||||||
// move to edge of circle (verify_circle) will ensure we begin circling once we reach the edge
|
// move to edge of circle (verify_circle) will ensure we begin circling once we reach the edge
|
||||||
auto_circle_movetoedge_start(circle_center, circle_radius_m, circle_direction_ccw);
|
mode_auto.auto_circle_movetoedge_start(circle_center, circle_radius_m, circle_direction_ccw);
|
||||||
}
|
}
|
||||||
|
|
||||||
// do_loiter_time - initiate loitering at a point for a given time period
|
// do_loiter_time - initiate loitering at a point for a given time period
|
||||||
|
@ -383,10 +383,10 @@ void Sub::do_nav_guided_enable(const AP_Mission::Mission_Command& cmd)
|
||||||
{
|
{
|
||||||
if (cmd.p1 > 0) {
|
if (cmd.p1 > 0) {
|
||||||
// initialise guided limits
|
// initialise guided limits
|
||||||
guided_limit_init_time_and_pos();
|
mode_auto.guided_limit_init_time_and_pos();
|
||||||
|
|
||||||
// set navigation target
|
// set navigation target
|
||||||
auto_nav_guided_start();
|
mode_auto.auto_nav_guided_start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // NAV_GUIDED
|
#endif // NAV_GUIDED
|
||||||
|
@ -410,7 +410,7 @@ void Sub::do_nav_delay(const AP_Mission::Mission_Command& cmd)
|
||||||
// do_guided_limits - pass guided limits to guided controller
|
// do_guided_limits - pass guided limits to guided controller
|
||||||
void Sub::do_guided_limits(const AP_Mission::Mission_Command& cmd)
|
void Sub::do_guided_limits(const AP_Mission::Mission_Command& cmd)
|
||||||
{
|
{
|
||||||
guided_limit_set(cmd.p1 * 1000, // convert seconds to ms
|
mode_guided.guided_limit_set(cmd.p1 * 1000, // convert seconds to ms
|
||||||
cmd.content.guided_limits.alt_min * 100.0f, // convert meters to cm
|
cmd.content.guided_limits.alt_min * 100.0f, // convert meters to cm
|
||||||
cmd.content.guided_limits.alt_max * 100.0f, // convert meters to cm
|
cmd.content.guided_limits.alt_max * 100.0f, // convert meters to cm
|
||||||
cmd.content.guided_limits.horiz_max * 100.0f); // convert meters to cm
|
cmd.content.guided_limits.horiz_max * 100.0f); // convert meters to cm
|
||||||
|
@ -459,7 +459,7 @@ bool Sub::verify_surface(const AP_Mission::Mission_Command& cmd)
|
||||||
// TODO get xy target from current wp destination, because current location may be acceptance-radius away from original destination
|
// TODO get xy target from current wp destination, because current location may be acceptance-radius away from original destination
|
||||||
Location target_location(cmd.content.location.lat, cmd.content.location.lng, 0, Location::AltFrame::ABOVE_HOME);
|
Location target_location(cmd.content.location.lat, cmd.content.location.lng, 0, Location::AltFrame::ABOVE_HOME);
|
||||||
|
|
||||||
auto_wp_start(target_location);
|
mode_auto.auto_wp_start(target_location);
|
||||||
|
|
||||||
// advance to next state
|
// advance to next state
|
||||||
auto_surface_state = AUTO_SURFACE_STATE_ASCEND;
|
auto_surface_state = AUTO_SURFACE_STATE_ASCEND;
|
||||||
|
@ -529,13 +529,13 @@ bool Sub::verify_circle(const AP_Mission::Mission_Command& cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
// start circling
|
// start circling
|
||||||
auto_circle_start();
|
mode_auto.auto_circle_start();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if we have completed circling
|
// check if we have completed circling
|
||||||
return fabsf(circle_nav.get_angle_total()/M_2PI) >= LOWBYTE(cmd.p1);
|
return fabsf(sub.circle_nav.get_angle_total()/M_2PI) >= LOWBYTE(cmd.p1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if NAV_GUIDED == ENABLED
|
#if NAV_GUIDED == ENABLED
|
||||||
|
@ -548,7 +548,7 @@ bool Sub::verify_nav_guided_enable(const AP_Mission::Mission_Command& cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
// check time and position limits
|
// check time and position limits
|
||||||
return guided_limit_check();
|
return mode_auto.guided_limit_check();
|
||||||
}
|
}
|
||||||
#endif // NAV_GUIDED
|
#endif // NAV_GUIDED
|
||||||
|
|
||||||
|
@ -579,7 +579,7 @@ void Sub::do_within_distance(const AP_Mission::Mission_Command& cmd)
|
||||||
|
|
||||||
void Sub::do_yaw(const AP_Mission::Mission_Command& cmd)
|
void Sub::do_yaw(const AP_Mission::Mission_Command& cmd)
|
||||||
{
|
{
|
||||||
set_auto_yaw_look_at_heading(
|
sub.mode_auto.set_auto_yaw_look_at_heading(
|
||||||
cmd.content.yaw.angle_deg,
|
cmd.content.yaw.angle_deg,
|
||||||
cmd.content.yaw.turn_rate_dps,
|
cmd.content.yaw.turn_rate_dps,
|
||||||
cmd.content.yaw.direction,
|
cmd.content.yaw.direction,
|
||||||
|
@ -614,7 +614,7 @@ bool Sub::verify_yaw()
|
||||||
{
|
{
|
||||||
// set yaw mode if it has been changed (the waypoint controller often retakes control of yaw as it executes a new waypoint command)
|
// set yaw mode if it has been changed (the waypoint controller often retakes control of yaw as it executes a new waypoint command)
|
||||||
if (auto_yaw_mode != AUTO_YAW_LOOK_AT_HEADING) {
|
if (auto_yaw_mode != AUTO_YAW_LOOK_AT_HEADING) {
|
||||||
set_auto_yaw_mode(AUTO_YAW_LOOK_AT_HEADING);
|
sub.mode_auto.set_auto_yaw_mode(AUTO_YAW_LOOK_AT_HEADING);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if we are within 2 degrees of the target heading
|
// check if we are within 2 degrees of the target heading
|
||||||
|
@ -629,7 +629,7 @@ bool Sub::verify_yaw()
|
||||||
bool Sub::do_guided(const AP_Mission::Mission_Command& cmd)
|
bool Sub::do_guided(const AP_Mission::Mission_Command& cmd)
|
||||||
{
|
{
|
||||||
// only process guided waypoint if we are in guided mode
|
// only process guided waypoint if we are in guided mode
|
||||||
if (control_mode != GUIDED && !(control_mode == AUTO && auto_mode == Auto_NavGuided)) {
|
if (control_mode != Mode::Number::GUIDED && !(control_mode == Mode::Number::AUTO && auto_mode == Auto_NavGuided)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -638,7 +638,7 @@ bool Sub::do_guided(const AP_Mission::Mission_Command& cmd)
|
||||||
|
|
||||||
case MAV_CMD_NAV_WAYPOINT: {
|
case MAV_CMD_NAV_WAYPOINT: {
|
||||||
// set wp_nav's destination
|
// set wp_nav's destination
|
||||||
return guided_set_destination(cmd.content.location);
|
return sub.mode_guided.guided_set_destination(cmd.content.location);
|
||||||
}
|
}
|
||||||
|
|
||||||
case MAV_CMD_CONDITION_YAW:
|
case MAV_CMD_CONDITION_YAW:
|
||||||
|
@ -681,7 +681,7 @@ void Sub::do_set_home(const AP_Mission::Mission_Command& cmd)
|
||||||
// TO-DO: add support for other features of MAV_CMD_DO_SET_ROI including pointing at a given waypoint
|
// TO-DO: add support for other features of MAV_CMD_DO_SET_ROI including pointing at a given waypoint
|
||||||
void Sub::do_roi(const AP_Mission::Mission_Command& cmd)
|
void Sub::do_roi(const AP_Mission::Mission_Command& cmd)
|
||||||
{
|
{
|
||||||
set_auto_yaw_roi(cmd.content.location);
|
sub.mode_auto.set_auto_yaw_roi(cmd.content.location);
|
||||||
}
|
}
|
||||||
|
|
||||||
// point the camera to a specified angle
|
// point the camera to a specified angle
|
||||||
|
|
|
@ -1,34 +1,30 @@
|
||||||
#include "Sub.h"
|
#include "Sub.h"
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* control_acro.pde - init and run calls for acro flight mode
|
|
||||||
*/
|
|
||||||
|
|
||||||
// acro_init - initialise acro controller
|
#include "Sub.h"
|
||||||
bool Sub::acro_init()
|
|
||||||
{
|
|
||||||
|
bool ModeAcro::init(bool ignore_checks) {
|
||||||
// set target altitude to zero for reporting
|
// set target altitude to zero for reporting
|
||||||
pos_control.set_pos_target_z_cm(0);
|
position_control->set_pos_target_z_cm(0);
|
||||||
|
|
||||||
// attitude hold inputs become thrust inputs in acro mode
|
// attitude hold inputs become thrust inputs in acro mode
|
||||||
// set to neutral to prevent chaotic behavior (esp. roll/pitch)
|
// set to neutral to prevent chaotic behavior (esp. roll/pitch)
|
||||||
set_neutral_controls();
|
sub.set_neutral_controls();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// acro_run - runs the acro controller
|
void ModeAcro::run()
|
||||||
// should be called at 100hz or more
|
|
||||||
void Sub::acro_run()
|
|
||||||
{
|
{
|
||||||
float target_roll, target_pitch, target_yaw;
|
float target_roll, target_pitch, target_yaw;
|
||||||
|
|
||||||
// if not armed set throttle to zero and exit immediately
|
// if not armed set throttle to zero and exit immediately
|
||||||
if (!motors.armed()) {
|
if (!motors.armed()) {
|
||||||
motors.set_desired_spool_state(AP_Motors::DesiredSpoolState::GROUND_IDLE);
|
motors.set_desired_spool_state(AP_Motors::DesiredSpoolState::GROUND_IDLE);
|
||||||
attitude_control.set_throttle_out(0,true,g.throttle_filt);
|
attitude_control->set_throttle_out(0,true,g.throttle_filt);
|
||||||
attitude_control.relax_attitude_controllers();
|
attitude_control->relax_attitude_controllers();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,125 +34,13 @@ void Sub::acro_run()
|
||||||
get_pilot_desired_angle_rates(channel_roll->get_control_in(), channel_pitch->get_control_in(), channel_yaw->get_control_in(), target_roll, target_pitch, target_yaw);
|
get_pilot_desired_angle_rates(channel_roll->get_control_in(), channel_pitch->get_control_in(), channel_yaw->get_control_in(), target_roll, target_pitch, target_yaw);
|
||||||
|
|
||||||
// run attitude controller
|
// run attitude controller
|
||||||
attitude_control.input_rate_bf_roll_pitch_yaw(target_roll, target_pitch, target_yaw);
|
attitude_control->input_rate_bf_roll_pitch_yaw(target_roll, target_pitch, target_yaw);
|
||||||
|
|
||||||
// output pilot's throttle without angle boost
|
// output pilot's throttle without angle boost
|
||||||
attitude_control.set_throttle_out(channel_throttle->norm_input(), false, g.throttle_filt);
|
attitude_control->set_throttle_out(channel_throttle->norm_input(), false, g.throttle_filt);
|
||||||
|
|
||||||
//control_in is range 0-1000
|
//control_in is range 0-1000
|
||||||
//radio_in is raw pwm value
|
//radio_in is raw pwm value
|
||||||
motors.set_forward(channel_forward->norm_input());
|
motors.set_forward(channel_forward->norm_input());
|
||||||
motors.set_lateral(channel_lateral->norm_input());
|
motors.set_lateral(channel_lateral->norm_input());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// get_pilot_desired_angle_rates - transform pilot's roll pitch and yaw input into a desired lean angle rates
|
|
||||||
// returns desired angle rates in centi-degrees-per-second
|
|
||||||
void Sub::get_pilot_desired_angle_rates(int16_t roll_in, int16_t pitch_in, int16_t yaw_in, float &roll_out, float &pitch_out, float &yaw_out)
|
|
||||||
{
|
|
||||||
float rate_limit;
|
|
||||||
Vector3f rate_ef_level, rate_bf_level, rate_bf_request;
|
|
||||||
|
|
||||||
// apply circular limit to pitch and roll inputs
|
|
||||||
float total_in = norm(pitch_in, roll_in);
|
|
||||||
|
|
||||||
if (total_in > ROLL_PITCH_INPUT_MAX) {
|
|
||||||
float ratio = (float)ROLL_PITCH_INPUT_MAX / total_in;
|
|
||||||
roll_in *= ratio;
|
|
||||||
pitch_in *= ratio;
|
|
||||||
}
|
|
||||||
|
|
||||||
// calculate roll, pitch rate requests
|
|
||||||
if (g.acro_expo <= 0) {
|
|
||||||
rate_bf_request.x = roll_in * g.acro_rp_p;
|
|
||||||
rate_bf_request.y = pitch_in * g.acro_rp_p;
|
|
||||||
} else {
|
|
||||||
// expo variables
|
|
||||||
float rp_in, rp_in3, rp_out;
|
|
||||||
|
|
||||||
// range check expo
|
|
||||||
if (g.acro_expo > 1.0f) {
|
|
||||||
g.acro_expo.set(1.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
// roll expo
|
|
||||||
rp_in = float(roll_in)/ROLL_PITCH_INPUT_MAX;
|
|
||||||
rp_in3 = rp_in*rp_in*rp_in;
|
|
||||||
rp_out = (g.acro_expo * rp_in3) + ((1 - g.acro_expo) * rp_in);
|
|
||||||
rate_bf_request.x = ROLL_PITCH_INPUT_MAX * rp_out * g.acro_rp_p;
|
|
||||||
|
|
||||||
// pitch expo
|
|
||||||
rp_in = float(pitch_in)/ROLL_PITCH_INPUT_MAX;
|
|
||||||
rp_in3 = rp_in*rp_in*rp_in;
|
|
||||||
rp_out = (g.acro_expo * rp_in3) + ((1 - g.acro_expo) * rp_in);
|
|
||||||
rate_bf_request.y = ROLL_PITCH_INPUT_MAX * rp_out * g.acro_rp_p;
|
|
||||||
}
|
|
||||||
|
|
||||||
// calculate yaw rate request
|
|
||||||
rate_bf_request.z = yaw_in * g.acro_yaw_p;
|
|
||||||
|
|
||||||
// calculate earth frame rate corrections to pull the vehicle back to level while in ACRO mode
|
|
||||||
|
|
||||||
if (g.acro_trainer != ACRO_TRAINER_DISABLED) {
|
|
||||||
// Calculate trainer mode earth frame rate command for roll
|
|
||||||
int32_t roll_angle = wrap_180_cd(ahrs.roll_sensor);
|
|
||||||
rate_ef_level.x = -constrain_int32(roll_angle, -ACRO_LEVEL_MAX_ANGLE, ACRO_LEVEL_MAX_ANGLE) * g.acro_balance_roll;
|
|
||||||
|
|
||||||
// Calculate trainer mode earth frame rate command for pitch
|
|
||||||
int32_t pitch_angle = wrap_180_cd(ahrs.pitch_sensor);
|
|
||||||
rate_ef_level.y = -constrain_int32(pitch_angle, -ACRO_LEVEL_MAX_ANGLE, ACRO_LEVEL_MAX_ANGLE) * g.acro_balance_pitch;
|
|
||||||
|
|
||||||
// Calculate trainer mode earth frame rate command for yaw
|
|
||||||
rate_ef_level.z = 0;
|
|
||||||
|
|
||||||
// Calculate angle limiting earth frame rate commands
|
|
||||||
if (g.acro_trainer == ACRO_TRAINER_LIMITED) {
|
|
||||||
if (roll_angle > aparm.angle_max) {
|
|
||||||
rate_ef_level.x -= g.acro_balance_roll*(roll_angle-aparm.angle_max);
|
|
||||||
} else if (roll_angle < -aparm.angle_max) {
|
|
||||||
rate_ef_level.x -= g.acro_balance_roll*(roll_angle+aparm.angle_max);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pitch_angle > aparm.angle_max) {
|
|
||||||
rate_ef_level.y -= g.acro_balance_pitch*(pitch_angle-aparm.angle_max);
|
|
||||||
} else if (pitch_angle < -aparm.angle_max) {
|
|
||||||
rate_ef_level.y -= g.acro_balance_pitch*(pitch_angle+aparm.angle_max);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// convert earth-frame level rates to body-frame level rates
|
|
||||||
attitude_control.euler_rate_to_ang_vel(attitude_control.get_att_target_euler_cd()*radians(0.01f), rate_ef_level, rate_bf_level);
|
|
||||||
|
|
||||||
// combine earth frame rate corrections with rate requests
|
|
||||||
if (g.acro_trainer == ACRO_TRAINER_LIMITED) {
|
|
||||||
rate_bf_request.x += rate_bf_level.x;
|
|
||||||
rate_bf_request.y += rate_bf_level.y;
|
|
||||||
rate_bf_request.z += rate_bf_level.z;
|
|
||||||
} else {
|
|
||||||
float acro_level_mix = constrain_float(1-MAX(MAX(abs(roll_in), abs(pitch_in)), abs(yaw_in))/4500.0, 0, 1)*ahrs.cos_pitch();
|
|
||||||
|
|
||||||
// Scale leveling rates by stick input
|
|
||||||
rate_bf_level = rate_bf_level*acro_level_mix;
|
|
||||||
|
|
||||||
// Calculate rate limit to prevent change of rate through inverted
|
|
||||||
rate_limit = fabsf(fabsf(rate_bf_request.x)-fabsf(rate_bf_level.x));
|
|
||||||
rate_bf_request.x += rate_bf_level.x;
|
|
||||||
rate_bf_request.x = constrain_float(rate_bf_request.x, -rate_limit, rate_limit);
|
|
||||||
|
|
||||||
// Calculate rate limit to prevent change of rate through inverted
|
|
||||||
rate_limit = fabsf(fabsf(rate_bf_request.y)-fabsf(rate_bf_level.y));
|
|
||||||
rate_bf_request.y += rate_bf_level.y;
|
|
||||||
rate_bf_request.y = constrain_float(rate_bf_request.y, -rate_limit, rate_limit);
|
|
||||||
|
|
||||||
// Calculate rate limit to prevent change of rate through inverted
|
|
||||||
rate_limit = fabsf(fabsf(rate_bf_request.z)-fabsf(rate_bf_level.z));
|
|
||||||
rate_bf_request.z += rate_bf_level.z;
|
|
||||||
rate_bf_request.z = constrain_float(rate_bf_request.z, -rate_limit, rate_limit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// hand back rate request
|
|
||||||
roll_out = rate_bf_request.x;
|
|
||||||
pitch_out = rate_bf_request.y;
|
|
||||||
yaw_out = rate_bf_request.z;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,46 +1,40 @@
|
||||||
#include "Sub.h"
|
#include "Sub.h"
|
||||||
|
|
||||||
|
|
||||||
/*
|
bool ModeAlthold::init(bool ignore_checks) {
|
||||||
* control_althold.pde - init and run calls for althold, flight mode
|
if(!sub.control_check_barometer()) {
|
||||||
*/
|
|
||||||
|
|
||||||
// althold_init - initialise althold controller
|
|
||||||
bool Sub::althold_init()
|
|
||||||
{
|
|
||||||
if(!control_check_barometer()) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialize vertical maximum speeds and acceleration
|
// initialize vertical maximum speeds and acceleration
|
||||||
// sets the maximum speed up and down returned by position controller
|
// sets the maximum speed up and down returned by position controller
|
||||||
pos_control.set_max_speed_accel_z(-get_pilot_speed_dn(), g.pilot_speed_up, g.pilot_accel_z);
|
position_control->set_max_speed_accel_z(-sub.get_pilot_speed_dn(), g.pilot_speed_up, g.pilot_accel_z);
|
||||||
pos_control.set_correction_speed_accel_z(-get_pilot_speed_dn(), g.pilot_speed_up, g.pilot_accel_z);
|
position_control->set_correction_speed_accel_z(-sub.get_pilot_speed_dn(), g.pilot_speed_up, g.pilot_accel_z);
|
||||||
|
|
||||||
// initialise position and desired velocity
|
// initialise position and desired velocity
|
||||||
pos_control.init_z_controller();
|
position_control->init_z_controller();
|
||||||
|
|
||||||
last_pilot_heading = ahrs.yaw_sensor;
|
sub.last_pilot_heading = ahrs.yaw_sensor;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// althold_run - runs the althold controller
|
// althold_run - runs the althold controller
|
||||||
// should be called at 100hz or more
|
// should be called at 100hz or more
|
||||||
void Sub::althold_run()
|
void ModeAlthold::run()
|
||||||
{
|
{
|
||||||
uint32_t tnow = AP_HAL::millis();
|
uint32_t tnow = AP_HAL::millis();
|
||||||
|
|
||||||
// initialize vertical speeds and acceleration
|
// initialize vertical speeds and acceleration
|
||||||
pos_control.set_max_speed_accel_z(-get_pilot_speed_dn(), g.pilot_speed_up, g.pilot_accel_z);
|
position_control->set_max_speed_accel_z(-sub.get_pilot_speed_dn(), g.pilot_speed_up, g.pilot_accel_z);
|
||||||
|
|
||||||
if (!motors.armed()) {
|
if (!motors.armed()) {
|
||||||
motors.set_desired_spool_state(AP_Motors::DesiredSpoolState::GROUND_IDLE);
|
motors.set_desired_spool_state(AP_Motors::DesiredSpoolState::GROUND_IDLE);
|
||||||
// Sub vehicles do not stabilize roll/pitch/yaw when not auto-armed (i.e. on the ground, pilot has never raised throttle)
|
// Sub vehicles do not stabilize roll/pitch/yaw when not auto-armed (i.e. on the ground, pilot has never raised throttle)
|
||||||
attitude_control.set_throttle_out(0.5,true,g.throttle_filt);
|
attitude_control->set_throttle_out(0.5,true,g.throttle_filt);
|
||||||
attitude_control.relax_attitude_controllers();
|
attitude_control->relax_attitude_controllers();
|
||||||
pos_control.relax_z_controller(motors.get_throttle_hover());
|
position_control->relax_z_controller(motors.get_throttle_hover());
|
||||||
last_pilot_heading = ahrs.yaw_sensor;
|
sub.last_pilot_heading = ahrs.yaw_sensor;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +47,7 @@ void Sub::althold_run()
|
||||||
if (tnow - sub.set_attitude_target_no_gps.last_message_ms < 5000) {
|
if (tnow - sub.set_attitude_target_no_gps.last_message_ms < 5000) {
|
||||||
float target_yaw;
|
float target_yaw;
|
||||||
Quaternion(
|
Quaternion(
|
||||||
set_attitude_target_no_gps.packet.q
|
sub.set_attitude_target_no_gps.packet.q
|
||||||
).to_euler(
|
).to_euler(
|
||||||
target_roll,
|
target_roll,
|
||||||
target_pitch,
|
target_pitch,
|
||||||
|
@ -63,34 +57,34 @@ void Sub::althold_run()
|
||||||
target_pitch = degrees(target_pitch);
|
target_pitch = degrees(target_pitch);
|
||||||
target_yaw = degrees(target_yaw);
|
target_yaw = degrees(target_yaw);
|
||||||
|
|
||||||
attitude_control.input_euler_angle_roll_pitch_yaw(target_roll * 1e2f, target_pitch * 1e2f, target_yaw * 1e2f, true);
|
attitude_control->input_euler_angle_roll_pitch_yaw(target_roll * 1e2f, target_pitch * 1e2f, target_yaw * 1e2f, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
get_pilot_desired_lean_angles(channel_roll->get_control_in(), channel_pitch->get_control_in(), target_roll, target_pitch, attitude_control.get_althold_lean_angle_max_cd());
|
sub.get_pilot_desired_lean_angles(channel_roll->get_control_in(), channel_pitch->get_control_in(), target_roll, target_pitch, attitude_control->get_althold_lean_angle_max_cd());
|
||||||
|
|
||||||
// get pilot's desired yaw rate
|
// get pilot's desired yaw rate
|
||||||
float target_yaw_rate = get_pilot_desired_yaw_rate(channel_yaw->get_control_in());
|
float target_yaw_rate = sub.get_pilot_desired_yaw_rate(channel_yaw->get_control_in());
|
||||||
|
|
||||||
// call attitude controller
|
// call attitude controller
|
||||||
if (!is_zero(target_yaw_rate)) { // call attitude controller with rate yaw determined by pilot input
|
if (!is_zero(target_yaw_rate)) { // call attitude controller with rate yaw determined by pilot input
|
||||||
attitude_control.input_euler_angle_roll_pitch_euler_rate_yaw(target_roll, target_pitch, target_yaw_rate);
|
attitude_control->input_euler_angle_roll_pitch_euler_rate_yaw(target_roll, target_pitch, target_yaw_rate);
|
||||||
last_pilot_heading = ahrs.yaw_sensor;
|
sub.last_pilot_heading = ahrs.yaw_sensor;
|
||||||
last_pilot_yaw_input_ms = tnow; // time when pilot last changed heading
|
sub.last_pilot_yaw_input_ms = tnow; // time when pilot last changed heading
|
||||||
|
|
||||||
} else { // hold current heading
|
} else { // hold current heading
|
||||||
|
|
||||||
// this check is required to prevent bounce back after very fast yaw maneuvers
|
// this check is required to prevent bounce back after very fast yaw maneuvers
|
||||||
// the inertia of the vehicle causes the heading to move slightly past the point when pilot input actually stopped
|
// the inertia of the vehicle causes the heading to move slightly past the point when pilot input actually stopped
|
||||||
if (tnow < last_pilot_yaw_input_ms + 250) { // give 250ms to slow down, then set target heading
|
if (tnow < sub.last_pilot_yaw_input_ms + 250) { // give 250ms to slow down, then set target heading
|
||||||
target_yaw_rate = 0; // Stop rotation on yaw axis
|
target_yaw_rate = 0; // Stop rotation on yaw axis
|
||||||
|
|
||||||
// call attitude controller with target yaw rate = 0 to decelerate on yaw axis
|
// call attitude controller with target yaw rate = 0 to decelerate on yaw axis
|
||||||
attitude_control.input_euler_angle_roll_pitch_euler_rate_yaw(target_roll, target_pitch, target_yaw_rate);
|
attitude_control->input_euler_angle_roll_pitch_euler_rate_yaw(target_roll, target_pitch, target_yaw_rate);
|
||||||
last_pilot_heading = ahrs.yaw_sensor; // update heading to hold
|
sub.last_pilot_heading = ahrs.yaw_sensor; // update heading to hold
|
||||||
|
|
||||||
} else { // call attitude controller holding absolute absolute bearing
|
} else { // call attitude controller holding absolute absolute bearing
|
||||||
attitude_control.input_euler_angle_roll_pitch_yaw(target_roll, target_pitch, last_pilot_heading, true);
|
attitude_control->input_euler_angle_roll_pitch_yaw(target_roll, target_pitch, sub.last_pilot_heading, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,21 +94,21 @@ void Sub::althold_run()
|
||||||
motors.set_lateral(channel_lateral->norm_input());
|
motors.set_lateral(channel_lateral->norm_input());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sub::control_depth() {
|
void ModeAlthold::control_depth() {
|
||||||
float target_climb_rate_cm_s = get_pilot_desired_climb_rate(channel_throttle->get_control_in());
|
float target_climb_rate_cm_s = sub.get_pilot_desired_climb_rate(channel_throttle->get_control_in());
|
||||||
target_climb_rate_cm_s = constrain_float(target_climb_rate_cm_s, -get_pilot_speed_dn(), g.pilot_speed_up);
|
target_climb_rate_cm_s = constrain_float(target_climb_rate_cm_s, -sub.get_pilot_speed_dn(), g.pilot_speed_up);
|
||||||
|
|
||||||
// desired_climb_rate returns 0 when within the deadzone.
|
// desired_climb_rate returns 0 when within the deadzone.
|
||||||
//we allow full control to the pilot, but as soon as there's no input, we handle being at surface/bottom
|
//we allow full control to the pilot, but as soon as there's no input, we handle being at surface/bottom
|
||||||
if (fabsf(target_climb_rate_cm_s) < 0.05f) {
|
if (fabsf(target_climb_rate_cm_s) < 0.05f) {
|
||||||
if (ap.at_surface) {
|
if (sub.ap.at_surface) {
|
||||||
pos_control.set_pos_target_z_cm(MIN(pos_control.get_pos_target_z_cm(), g.surface_depth - 5.0f)); // set target to 5 cm below surface level
|
position_control->set_pos_target_z_cm(MIN(position_control->get_pos_target_z_cm(), g.surface_depth - 5.0f)); // set target to 5 cm below surface level
|
||||||
} else if (ap.at_bottom) {
|
} else if (sub.ap.at_bottom) {
|
||||||
pos_control.set_pos_target_z_cm(MAX(inertial_nav.get_position_z_up_cm() + 10.0f, pos_control.get_pos_target_z_cm())); // set target to 10 cm above bottom
|
position_control->set_pos_target_z_cm(MAX(inertial_nav.get_position_z_up_cm() + 10.0f, position_control->get_pos_target_z_cm())); // set target to 10 cm above bottom
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pos_control.set_pos_target_z_from_climb_rate_cm(target_climb_rate_cm_s);
|
position_control->set_pos_target_z_from_climb_rate_cm(target_climb_rate_cm_s);
|
||||||
pos_control.update_z_controller();
|
position_control->update_z_controller();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,42 +7,38 @@
|
||||||
* While in the auto flight mode, navigation or do/now commands can be run.
|
* While in the auto flight mode, navigation or do/now commands can be run.
|
||||||
* Code in this file implements the navigation commands
|
* Code in this file implements the navigation commands
|
||||||
*/
|
*/
|
||||||
|
bool ModeAuto::init(bool ignore_checks) {
|
||||||
// auto_init - initialise auto controller
|
if (!sub.position_ok() || sub.mission.num_commands() < 2) {
|
||||||
bool Sub::auto_init()
|
|
||||||
{
|
|
||||||
if (!position_ok() || mission.num_commands() < 2) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto_mode = Auto_Loiter;
|
sub.auto_mode = Auto_Loiter;
|
||||||
|
|
||||||
// stop ROI from carrying over from previous runs of the mission
|
// stop ROI from carrying over from previous runs of the mission
|
||||||
// To-Do: reset the yaw as part of auto_wp_start when the previous command was not a wp command to remove the need for this special ROI check
|
// To-Do: reset the yaw as part of auto_wp_start when the previous command was not a wp command to remove the need for this special ROI check
|
||||||
if (auto_yaw_mode == AUTO_YAW_ROI) {
|
if (sub.auto_yaw_mode == AUTO_YAW_ROI) {
|
||||||
set_auto_yaw_mode(AUTO_YAW_HOLD);
|
set_auto_yaw_mode(AUTO_YAW_HOLD);
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialise waypoint controller
|
// initialise waypoint controller
|
||||||
wp_nav.wp_and_spline_init();
|
sub.wp_nav.wp_and_spline_init();
|
||||||
|
|
||||||
// clear guided limits
|
// clear guided limits
|
||||||
guided_limit_clear();
|
guided_limit_clear();
|
||||||
|
|
||||||
// start/resume the mission (based on MIS_RESTART parameter)
|
// start/resume the mission (based on MIS_RESTART parameter)
|
||||||
mission.start_or_resume();
|
sub.mission.start_or_resume();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// auto_run - runs the appropriate auto controller
|
// auto_run - runs the appropriate auto controller
|
||||||
// according to the current auto_mode
|
// according to the current auto_mode
|
||||||
// should be called at 100hz or more
|
void ModeAuto::run()
|
||||||
void Sub::auto_run()
|
|
||||||
{
|
{
|
||||||
mission.update();
|
sub.mission.update();
|
||||||
|
|
||||||
// call the correct auto controller
|
// call the correct auto controller
|
||||||
switch (auto_mode) {
|
switch (sub.auto_mode) {
|
||||||
|
|
||||||
case Auto_WP:
|
case Auto_WP:
|
||||||
case Auto_CircleMoveToEdge:
|
case Auto_CircleMoveToEdge:
|
||||||
|
@ -70,42 +66,42 @@ void Sub::auto_run()
|
||||||
}
|
}
|
||||||
|
|
||||||
// auto_wp_start - initialises waypoint controller to implement flying to a particular destination
|
// auto_wp_start - initialises waypoint controller to implement flying to a particular destination
|
||||||
void Sub::auto_wp_start(const Vector3f& destination)
|
void ModeAuto::auto_wp_start(const Vector3f& destination)
|
||||||
{
|
{
|
||||||
auto_mode = Auto_WP;
|
sub.auto_mode = Auto_WP;
|
||||||
|
|
||||||
// initialise wpnav (no need to check return status because terrain data is not used)
|
// initialise wpnav (no need to check return status because terrain data is not used)
|
||||||
wp_nav.set_wp_destination(destination, false);
|
sub.wp_nav.set_wp_destination(destination, false);
|
||||||
|
|
||||||
// initialise yaw
|
// initialise yaw
|
||||||
// To-Do: reset the yaw only when the previous navigation command is not a WP. this would allow removing the special check for ROI
|
// To-Do: reset the yaw only when the previous navigation command is not a WP. this would allow removing the special check for ROI
|
||||||
if (auto_yaw_mode != AUTO_YAW_ROI) {
|
if (sub.auto_yaw_mode != AUTO_YAW_ROI) {
|
||||||
set_auto_yaw_mode(get_default_auto_yaw_mode(false));
|
set_auto_yaw_mode(get_default_auto_yaw_mode(false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// auto_wp_start - initialises waypoint controller to implement flying to a particular destination
|
// auto_wp_start - initialises waypoint controller to implement flying to a particular destination
|
||||||
void Sub::auto_wp_start(const Location& dest_loc)
|
void ModeAuto::auto_wp_start(const Location& dest_loc)
|
||||||
{
|
{
|
||||||
auto_mode = Auto_WP;
|
sub.auto_mode = Auto_WP;
|
||||||
|
|
||||||
// send target to waypoint controller
|
// send target to waypoint controller
|
||||||
if (!wp_nav.set_wp_destination_loc(dest_loc)) {
|
if (!sub.wp_nav.set_wp_destination_loc(dest_loc)) {
|
||||||
// failure to set destination can only be because of missing terrain data
|
// failure to set destination can only be because of missing terrain data
|
||||||
failsafe_terrain_on_event();
|
sub.failsafe_terrain_on_event();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialise yaw
|
// initialise yaw
|
||||||
// To-Do: reset the yaw only when the previous navigation command is not a WP. this would allow removing the special check for ROI
|
// To-Do: reset the yaw only when the previous navigation command is not a WP. this would allow removing the special check for ROI
|
||||||
if (auto_yaw_mode != AUTO_YAW_ROI) {
|
if (sub.auto_yaw_mode != AUTO_YAW_ROI) {
|
||||||
set_auto_yaw_mode(get_default_auto_yaw_mode(false));
|
set_auto_yaw_mode(get_default_auto_yaw_mode(false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// auto_wp_run - runs the auto waypoint controller
|
// auto_wp_run - runs the auto waypoint controller
|
||||||
// called by auto_run at 100hz or more
|
// called by auto_run at 100hz or more
|
||||||
void Sub::auto_wp_run()
|
void ModeAuto::auto_wp_run()
|
||||||
{
|
{
|
||||||
// if not armed set throttle to zero and exit immediately
|
// if not armed set throttle to zero and exit immediately
|
||||||
if (!motors.armed()) {
|
if (!motors.armed()) {
|
||||||
|
@ -114,17 +110,17 @@ void Sub::auto_wp_run()
|
||||||
// call attitude controller
|
// call attitude controller
|
||||||
// Sub vehicles do not stabilize roll/pitch/yaw when disarmed
|
// Sub vehicles do not stabilize roll/pitch/yaw when disarmed
|
||||||
motors.set_desired_spool_state(AP_Motors::DesiredSpoolState::GROUND_IDLE);
|
motors.set_desired_spool_state(AP_Motors::DesiredSpoolState::GROUND_IDLE);
|
||||||
attitude_control.set_throttle_out(0,true,g.throttle_filt);
|
attitude_control->set_throttle_out(0,true,g.throttle_filt);
|
||||||
attitude_control.relax_attitude_controllers();
|
attitude_control->relax_attitude_controllers();
|
||||||
wp_nav.wp_and_spline_init(); // Reset xy target
|
sub.wp_nav.wp_and_spline_init(); // Reset xy target
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// process pilot's yaw input
|
// process pilot's yaw input
|
||||||
float target_yaw_rate = 0;
|
float target_yaw_rate = 0;
|
||||||
if (!failsafe.pilot_input) {
|
if (!sub.failsafe.pilot_input) {
|
||||||
// get pilot's desired yaw rate
|
// get pilot's desired yaw rate
|
||||||
target_yaw_rate = get_pilot_desired_yaw_rate(channel_yaw->get_control_in());
|
target_yaw_rate = sub.get_pilot_desired_yaw_rate(channel_yaw->get_control_in());
|
||||||
if (!is_zero(target_yaw_rate)) {
|
if (!is_zero(target_yaw_rate)) {
|
||||||
set_auto_yaw_mode(AUTO_YAW_HOLD);
|
set_auto_yaw_mode(AUTO_YAW_HOLD);
|
||||||
}
|
}
|
||||||
|
@ -137,13 +133,13 @@ void Sub::auto_wp_run()
|
||||||
// TODO logic for terrain tracking target going below fence limit
|
// TODO logic for terrain tracking target going below fence limit
|
||||||
// TODO implement waypoint radius individually for each waypoint based on cmd.p2
|
// TODO implement waypoint radius individually for each waypoint based on cmd.p2
|
||||||
// TODO fix auto yaw heading to switch to something appropriate when mission complete and switches to loiter
|
// TODO fix auto yaw heading to switch to something appropriate when mission complete and switches to loiter
|
||||||
failsafe_terrain_set_status(wp_nav.update_wpnav());
|
sub.failsafe_terrain_set_status(sub.wp_nav.update_wpnav());
|
||||||
|
|
||||||
///////////////////////
|
///////////////////////
|
||||||
// update xy outputs //
|
// update xy outputs //
|
||||||
|
|
||||||
float lateral_out, forward_out;
|
float lateral_out, forward_out;
|
||||||
translate_wpnav_rp(lateral_out, forward_out);
|
sub.translate_wpnav_rp(lateral_out, forward_out);
|
||||||
|
|
||||||
// Send to forward/lateral outputs
|
// Send to forward/lateral outputs
|
||||||
motors.set_lateral(lateral_out);
|
motors.set_lateral(lateral_out);
|
||||||
|
@ -151,52 +147,52 @@ void Sub::auto_wp_run()
|
||||||
|
|
||||||
// WP_Nav has set the vertical position control targets
|
// WP_Nav has set the vertical position control targets
|
||||||
// run the vertical position controller and set output throttle
|
// run the vertical position controller and set output throttle
|
||||||
pos_control.update_z_controller();
|
position_control->update_z_controller();
|
||||||
|
|
||||||
////////////////////////////
|
////////////////////////////
|
||||||
// update attitude output //
|
// update attitude output //
|
||||||
|
|
||||||
// get pilot desired lean angles
|
// get pilot desired lean angles
|
||||||
float target_roll, target_pitch;
|
float target_roll, target_pitch;
|
||||||
get_pilot_desired_lean_angles(channel_roll->get_control_in(), channel_pitch->get_control_in(), target_roll, target_pitch, aparm.angle_max);
|
sub.get_pilot_desired_lean_angles(channel_roll->get_control_in(), channel_pitch->get_control_in(), target_roll, target_pitch, sub.aparm.angle_max);
|
||||||
|
|
||||||
// call attitude controller
|
// call attitude controller
|
||||||
if (auto_yaw_mode == AUTO_YAW_HOLD) {
|
if (sub.auto_yaw_mode == AUTO_YAW_HOLD) {
|
||||||
// roll & pitch & yaw rate from pilot
|
// roll & pitch & yaw rate from pilot
|
||||||
attitude_control.input_euler_angle_roll_pitch_euler_rate_yaw(target_roll, target_pitch, target_yaw_rate);
|
attitude_control->input_euler_angle_roll_pitch_euler_rate_yaw(target_roll, target_pitch, target_yaw_rate);
|
||||||
} else {
|
} else {
|
||||||
// roll, pitch from pilot, yaw heading from auto_heading()
|
// roll, pitch from pilot, yaw heading from auto_heading()
|
||||||
attitude_control.input_euler_angle_roll_pitch_yaw(target_roll, target_pitch, get_auto_heading(), true);
|
attitude_control->input_euler_angle_roll_pitch_yaw(target_roll, target_pitch, get_auto_heading(), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// auto_circle_movetoedge_start - initialise waypoint controller to move to edge of a circle with it's center at the specified location
|
// auto_circle_movetoedge_start - initialise waypoint controller to move to edge of a circle with it's center at the specified location
|
||||||
// we assume the caller has set the circle's circle with circle_nav.set_center()
|
// we assume the caller has set the circle's circle with sub.circle_nav.set_center()
|
||||||
// we assume the caller has performed all required GPS_ok checks
|
// we assume the caller has performed all required GPS_ok checks
|
||||||
void Sub::auto_circle_movetoedge_start(const Location &circle_center, float radius_m, bool ccw_turn)
|
void ModeAuto::auto_circle_movetoedge_start(const Location &circle_center, float radius_m, bool ccw_turn)
|
||||||
{
|
{
|
||||||
// set circle center
|
// set circle center
|
||||||
circle_nav.set_center(circle_center);
|
sub.circle_nav.set_center(circle_center);
|
||||||
|
|
||||||
// set circle radius
|
// set circle radius
|
||||||
if (!is_zero(radius_m)) {
|
if (!is_zero(radius_m)) {
|
||||||
circle_nav.set_radius_cm(radius_m * 100.0f);
|
sub.circle_nav.set_radius_cm(radius_m * 100.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
// set circle direction by using rate
|
// set circle direction by using rate
|
||||||
float current_rate = circle_nav.get_rate();
|
float current_rate = sub.circle_nav.get_rate();
|
||||||
current_rate = ccw_turn ? -fabsf(current_rate) : fabsf(current_rate);
|
current_rate = ccw_turn ? -fabsf(current_rate) : fabsf(current_rate);
|
||||||
circle_nav.set_rate(current_rate);
|
sub.circle_nav.set_rate(current_rate);
|
||||||
|
|
||||||
// check our distance from edge of circle
|
// check our distance from edge of circle
|
||||||
Vector3f circle_edge_neu;
|
Vector3f circle_edge_neu;
|
||||||
circle_nav.get_closest_point_on_circle(circle_edge_neu);
|
sub.circle_nav.get_closest_point_on_circle(circle_edge_neu);
|
||||||
float dist_to_edge = (inertial_nav.get_position_neu_cm() - circle_edge_neu).length();
|
float dist_to_edge = (inertial_nav.get_position_neu_cm() - circle_edge_neu).length();
|
||||||
|
|
||||||
// if more than 3m then fly to edge
|
// if more than 3m then fly to edge
|
||||||
if (dist_to_edge > 300.0f) {
|
if (dist_to_edge > 300.0f) {
|
||||||
// set the state to move to the edge of the circle
|
// set the state to move to the edge of the circle
|
||||||
auto_mode = Auto_CircleMoveToEdge;
|
sub.auto_mode = Auto_CircleMoveToEdge;
|
||||||
|
|
||||||
// convert circle_edge_neu to Location
|
// convert circle_edge_neu to Location
|
||||||
Location circle_edge(circle_edge_neu, Location::AltFrame::ABOVE_ORIGIN);
|
Location circle_edge(circle_edge_neu, Location::AltFrame::ABOVE_ORIGIN);
|
||||||
|
@ -205,14 +201,14 @@ void Sub::auto_circle_movetoedge_start(const Location &circle_center, float radi
|
||||||
circle_edge.set_alt_cm(circle_center.alt, circle_center.get_alt_frame());
|
circle_edge.set_alt_cm(circle_center.alt, circle_center.get_alt_frame());
|
||||||
|
|
||||||
// initialise wpnav to move to edge of circle
|
// initialise wpnav to move to edge of circle
|
||||||
if (!wp_nav.set_wp_destination_loc(circle_edge)) {
|
if (!sub.wp_nav.set_wp_destination_loc(circle_edge)) {
|
||||||
// failure to set destination can only be because of missing terrain data
|
// failure to set destination can only be because of missing terrain data
|
||||||
failsafe_terrain_on_event();
|
sub.failsafe_terrain_on_event();
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we are outside the circle, point at the edge, otherwise hold yaw
|
// if we are outside the circle, point at the edge, otherwise hold yaw
|
||||||
float dist_to_center = get_horizontal_distance_cm(inertial_nav.get_position_xy_cm().topostype(), circle_nav.get_center().xy());
|
float dist_to_center = get_horizontal_distance_cm(inertial_nav.get_position_xy_cm().topostype(), sub.circle_nav.get_center().xy());
|
||||||
if (dist_to_center > circle_nav.get_radius() && dist_to_center > 500) {
|
if (dist_to_center > sub.circle_nav.get_radius() && dist_to_center > 500) {
|
||||||
set_auto_yaw_mode(get_default_auto_yaw_mode(false));
|
set_auto_yaw_mode(get_default_auto_yaw_mode(false));
|
||||||
} else {
|
} else {
|
||||||
// vehicle is within circle so hold yaw to avoid spinning as we move to edge of circle
|
// vehicle is within circle so hold yaw to avoid spinning as we move to edge of circle
|
||||||
|
@ -225,23 +221,23 @@ void Sub::auto_circle_movetoedge_start(const Location &circle_center, float radi
|
||||||
|
|
||||||
// auto_circle_start - initialises controller to fly a circle in AUTO flight mode
|
// auto_circle_start - initialises controller to fly a circle in AUTO flight mode
|
||||||
// assumes that circle_nav object has already been initialised with circle center and radius
|
// assumes that circle_nav object has already been initialised with circle center and radius
|
||||||
void Sub::auto_circle_start()
|
void ModeAuto::auto_circle_start()
|
||||||
{
|
{
|
||||||
auto_mode = Auto_Circle;
|
sub.auto_mode = Auto_Circle;
|
||||||
|
|
||||||
// initialise circle controller
|
// initialise circle controller
|
||||||
circle_nav.init(circle_nav.get_center(), circle_nav.center_is_terrain_alt(), circle_nav.get_rate());
|
sub.circle_nav.init(sub.circle_nav.get_center(), sub.circle_nav.center_is_terrain_alt(), sub.circle_nav.get_rate());
|
||||||
}
|
}
|
||||||
|
|
||||||
// auto_circle_run - circle in AUTO flight mode
|
// auto_circle_run - circle in AUTO flight mode
|
||||||
// called by auto_run at 100hz or more
|
// called by auto_run at 100hz or more
|
||||||
void Sub::auto_circle_run()
|
void ModeAuto::auto_circle_run()
|
||||||
{
|
{
|
||||||
// call circle controller
|
// call circle controller
|
||||||
failsafe_terrain_set_status(circle_nav.update());
|
sub.failsafe_terrain_set_status(sub.circle_nav.update());
|
||||||
|
|
||||||
float lateral_out, forward_out;
|
float lateral_out, forward_out;
|
||||||
translate_circle_nav_rp(lateral_out, forward_out);
|
sub.translate_circle_nav_rp(lateral_out, forward_out);
|
||||||
|
|
||||||
// Send to forward/lateral outputs
|
// Send to forward/lateral outputs
|
||||||
motors.set_lateral(lateral_out);
|
motors.set_lateral(lateral_out);
|
||||||
|
@ -249,50 +245,47 @@ void Sub::auto_circle_run()
|
||||||
|
|
||||||
// WP_Nav has set the vertical position control targets
|
// WP_Nav has set the vertical position control targets
|
||||||
// run the vertical position controller and set output throttle
|
// run the vertical position controller and set output throttle
|
||||||
pos_control.update_z_controller();
|
position_control->update_z_controller();
|
||||||
|
|
||||||
// roll & pitch from waypoint controller, yaw rate from pilot
|
// roll & pitch from waypoint controller, yaw rate from pilot
|
||||||
attitude_control.input_euler_angle_roll_pitch_yaw(channel_roll->get_control_in(), channel_pitch->get_control_in(), circle_nav.get_yaw(), true);
|
attitude_control->input_euler_angle_roll_pitch_yaw(channel_roll->get_control_in(), channel_pitch->get_control_in(), sub.circle_nav.get_yaw(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if NAV_GUIDED == ENABLED
|
#if NAV_GUIDED == ENABLED
|
||||||
// auto_nav_guided_start - hand over control to external navigation controller in AUTO mode
|
// auto_nav_guided_start - hand over control to external navigation controller in AUTO mode
|
||||||
void Sub::auto_nav_guided_start()
|
void ModeAuto::auto_nav_guided_start()
|
||||||
{
|
{
|
||||||
auto_mode = Auto_NavGuided;
|
sub.mode_guided.init(true);
|
||||||
|
sub.auto_mode = Auto_NavGuided;
|
||||||
// call regular guided flight mode initialisation
|
|
||||||
guided_init(true);
|
|
||||||
|
|
||||||
// initialise guided start time and position as reference for limit checking
|
// initialise guided start time and position as reference for limit checking
|
||||||
guided_limit_init_time_and_pos();
|
sub.mode_auto.guided_limit_init_time_and_pos();
|
||||||
}
|
}
|
||||||
|
|
||||||
// auto_nav_guided_run - allows control by external navigation controller
|
// auto_nav_guided_run - allows control by external navigation controller
|
||||||
// called by auto_run at 100hz or more
|
// called by auto_run at 100hz or more
|
||||||
void Sub::auto_nav_guided_run()
|
void ModeAuto::auto_nav_guided_run()
|
||||||
{
|
{
|
||||||
// call regular guided flight mode run function
|
// call regular guided flight mode run function
|
||||||
guided_run();
|
sub.mode_guided.run();
|
||||||
}
|
}
|
||||||
#endif // NAV_GUIDED
|
#endif // NAV_GUIDED
|
||||||
|
|
||||||
// auto_loiter_start - initialises loitering in auto mode
|
// auto_loiter_start - initialises loitering in auto mode
|
||||||
// returns success/failure because this can be called by exit_mission
|
// returns success/failure because this can be called by exit_mission
|
||||||
bool Sub::auto_loiter_start()
|
bool ModeAuto::auto_loiter_start()
|
||||||
{
|
{
|
||||||
// return failure if GPS is bad
|
// return failure if GPS is bad
|
||||||
if (!position_ok()) {
|
if (!sub.position_ok()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
auto_mode = Auto_Loiter;
|
sub.auto_mode = Auto_Loiter;
|
||||||
|
|
||||||
// calculate stopping point
|
// calculate stopping point
|
||||||
Vector3f stopping_point;
|
Vector3f stopping_point;
|
||||||
wp_nav.get_wp_stopping_point(stopping_point);
|
sub.wp_nav.get_wp_stopping_point(stopping_point);
|
||||||
|
|
||||||
// initialise waypoint controller target to stopping point
|
// initialise waypoint controller target to stopping point
|
||||||
wp_nav.set_wp_destination(stopping_point);
|
sub.wp_nav.set_wp_destination(stopping_point);
|
||||||
|
|
||||||
// hold yaw at current heading
|
// hold yaw at current heading
|
||||||
set_auto_yaw_mode(AUTO_YAW_HOLD);
|
set_auto_yaw_mode(AUTO_YAW_HOLD);
|
||||||
|
@ -302,35 +295,35 @@ bool Sub::auto_loiter_start()
|
||||||
|
|
||||||
// auto_loiter_run - loiter in AUTO flight mode
|
// auto_loiter_run - loiter in AUTO flight mode
|
||||||
// called by auto_run at 100hz or more
|
// called by auto_run at 100hz or more
|
||||||
void Sub::auto_loiter_run()
|
void ModeAuto::auto_loiter_run()
|
||||||
{
|
{
|
||||||
// if not armed set throttle to zero and exit immediately
|
// if not armed set throttle to zero and exit immediately
|
||||||
if (!motors.armed()) {
|
if (!motors.armed()) {
|
||||||
motors.set_desired_spool_state(AP_Motors::DesiredSpoolState::GROUND_IDLE);
|
motors.set_desired_spool_state(AP_Motors::DesiredSpoolState::GROUND_IDLE);
|
||||||
// Sub vehicles do not stabilize roll/pitch/yaw when disarmed
|
// Sub vehicles do not stabilize roll/pitch/yaw when disarmed
|
||||||
attitude_control.set_throttle_out(0,true,g.throttle_filt);
|
attitude_control->set_throttle_out(0,true,g.throttle_filt);
|
||||||
attitude_control.relax_attitude_controllers();
|
attitude_control->relax_attitude_controllers();
|
||||||
|
|
||||||
wp_nav.wp_and_spline_init(); // Reset xy target
|
sub.wp_nav.wp_and_spline_init(); // Reset xy target
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// accept pilot input of yaw
|
// accept pilot input of yaw
|
||||||
float target_yaw_rate = 0;
|
float target_yaw_rate = 0;
|
||||||
if (!failsafe.pilot_input) {
|
if (!sub.failsafe.pilot_input) {
|
||||||
target_yaw_rate = get_pilot_desired_yaw_rate(channel_yaw->get_control_in());
|
target_yaw_rate = sub.get_pilot_desired_yaw_rate(channel_yaw->get_control_in());
|
||||||
}
|
}
|
||||||
|
|
||||||
// set motors to full range
|
// set motors to full range
|
||||||
motors.set_desired_spool_state(AP_Motors::DesiredSpoolState::THROTTLE_UNLIMITED);
|
motors.set_desired_spool_state(AP_Motors::DesiredSpoolState::THROTTLE_UNLIMITED);
|
||||||
|
|
||||||
// run waypoint and z-axis position controller
|
// run waypoint and z-axis position controller
|
||||||
failsafe_terrain_set_status(wp_nav.update_wpnav());
|
sub.failsafe_terrain_set_status(sub.wp_nav.update_wpnav());
|
||||||
|
|
||||||
///////////////////////
|
///////////////////////
|
||||||
// update xy outputs //
|
// update xy outputs //
|
||||||
float lateral_out, forward_out;
|
float lateral_out, forward_out;
|
||||||
translate_wpnav_rp(lateral_out, forward_out);
|
sub.translate_wpnav_rp(lateral_out, forward_out);
|
||||||
|
|
||||||
// Send to forward/lateral outputs
|
// Send to forward/lateral outputs
|
||||||
motors.set_lateral(lateral_out);
|
motors.set_lateral(lateral_out);
|
||||||
|
@ -338,102 +331,33 @@ void Sub::auto_loiter_run()
|
||||||
|
|
||||||
// WP_Nav has set the vertical position control targets
|
// WP_Nav has set the vertical position control targets
|
||||||
// run the vertical position controller and set output throttle
|
// run the vertical position controller and set output throttle
|
||||||
pos_control.update_z_controller();
|
position_control->update_z_controller();
|
||||||
|
|
||||||
// get pilot desired lean angles
|
// get pilot desired lean angles
|
||||||
float target_roll, target_pitch;
|
float target_roll, target_pitch;
|
||||||
get_pilot_desired_lean_angles(channel_roll->get_control_in(), channel_pitch->get_control_in(), target_roll, target_pitch, aparm.angle_max);
|
sub.get_pilot_desired_lean_angles(channel_roll->get_control_in(), channel_pitch->get_control_in(), target_roll, target_pitch, sub.aparm.angle_max);
|
||||||
|
|
||||||
// roll & pitch & yaw rate from pilot
|
// roll & pitch & yaw rate from pilot
|
||||||
attitude_control.input_euler_angle_roll_pitch_euler_rate_yaw(target_roll, target_pitch, target_yaw_rate);
|
attitude_control->input_euler_angle_roll_pitch_euler_rate_yaw(target_roll, target_pitch, target_yaw_rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
// get_default_auto_yaw_mode - returns auto_yaw_mode based on WP_YAW_BEHAVIOR parameter
|
|
||||||
// set rtl parameter to true if this is during an RTL
|
|
||||||
uint8_t Sub::get_default_auto_yaw_mode(bool rtl) const
|
|
||||||
{
|
|
||||||
switch (g.wp_yaw_behavior) {
|
|
||||||
|
|
||||||
case WP_YAW_BEHAVIOR_NONE:
|
|
||||||
return AUTO_YAW_HOLD;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WP_YAW_BEHAVIOR_LOOK_AT_NEXT_WP_EXCEPT_RTL:
|
|
||||||
if (rtl) {
|
|
||||||
return AUTO_YAW_HOLD;
|
|
||||||
} else {
|
|
||||||
return AUTO_YAW_LOOK_AT_NEXT_WP;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WP_YAW_BEHAVIOR_LOOK_AHEAD:
|
|
||||||
return AUTO_YAW_LOOK_AHEAD;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WP_YAW_BEHAVIOR_CORRECT_XTRACK:
|
|
||||||
return AUTO_YAW_CORRECT_XTRACK;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WP_YAW_BEHAVIOR_LOOK_AT_NEXT_WP:
|
|
||||||
default:
|
|
||||||
return AUTO_YAW_LOOK_AT_NEXT_WP;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// set_auto_yaw_mode - sets the yaw mode for auto
|
|
||||||
void Sub::set_auto_yaw_mode(uint8_t yaw_mode)
|
|
||||||
{
|
|
||||||
// return immediately if no change
|
|
||||||
if (auto_yaw_mode == yaw_mode) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto_yaw_mode = yaw_mode;
|
|
||||||
|
|
||||||
// perform initialisation
|
|
||||||
switch (auto_yaw_mode) {
|
|
||||||
|
|
||||||
case AUTO_YAW_LOOK_AT_NEXT_WP:
|
|
||||||
// wpnav will initialise heading when wpnav's set_destination method is called
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AUTO_YAW_ROI:
|
|
||||||
// point towards a location held in yaw_look_at_WP
|
|
||||||
yaw_look_at_WP_bearing = ahrs.yaw_sensor;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AUTO_YAW_LOOK_AT_HEADING:
|
|
||||||
// keep heading pointing in the direction held in yaw_look_at_heading
|
|
||||||
// caller should set the yaw_look_at_heading
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AUTO_YAW_LOOK_AHEAD:
|
|
||||||
// Commanded Yaw to automatically look ahead.
|
|
||||||
yaw_look_ahead_bearing = ahrs.yaw_sensor;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AUTO_YAW_RESETTOARMEDYAW:
|
|
||||||
// initial_armed_bearing will be set during arming so no init required
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// set_auto_yaw_look_at_heading - sets the yaw look at heading for auto mode
|
// set_auto_yaw_look_at_heading - sets the yaw look at heading for auto mode
|
||||||
void Sub::set_auto_yaw_look_at_heading(float angle_deg, float turn_rate_dps, int8_t direction, uint8_t relative_angle)
|
void ModeAuto::set_auto_yaw_look_at_heading(float angle_deg, float turn_rate_dps, int8_t direction, uint8_t relative_angle)
|
||||||
{
|
{
|
||||||
// get current yaw target
|
// get current yaw target
|
||||||
int32_t curr_yaw_target = attitude_control.get_att_target_euler_cd().z;
|
int32_t curr_yaw_target = attitude_control->get_att_target_euler_cd().z;
|
||||||
|
|
||||||
// get final angle, 1 = Relative, 0 = Absolute
|
// get final angle, 1 = Relative, 0 = Absolute
|
||||||
if (relative_angle == 0) {
|
if (relative_angle == 0) {
|
||||||
// absolute angle
|
// absolute angle
|
||||||
yaw_look_at_heading = wrap_360_cd(angle_deg * 100);
|
sub.yaw_look_at_heading = wrap_360_cd(angle_deg * 100);
|
||||||
} else {
|
} else {
|
||||||
// relative angle
|
// relative angle
|
||||||
if (direction < 0) {
|
if (direction < 0) {
|
||||||
angle_deg = -angle_deg;
|
angle_deg = -angle_deg;
|
||||||
}
|
}
|
||||||
yaw_look_at_heading = wrap_360_cd((angle_deg*100+curr_yaw_target));
|
sub.yaw_look_at_heading = wrap_360_cd((angle_deg*100+curr_yaw_target));
|
||||||
}
|
}
|
||||||
|
|
||||||
// get turn speed
|
// get turn speed
|
||||||
|
@ -441,10 +365,10 @@ void Sub::set_auto_yaw_look_at_heading(float angle_deg, float turn_rate_dps, int
|
||||||
// see AP_Float _slew_yaw in AC_AttitudeControl
|
// see AP_Float _slew_yaw in AC_AttitudeControl
|
||||||
if (is_zero(turn_rate_dps)) {
|
if (is_zero(turn_rate_dps)) {
|
||||||
// default to regular auto slew rate
|
// default to regular auto slew rate
|
||||||
yaw_look_at_heading_slew = AUTO_YAW_SLEW_RATE;
|
sub.yaw_look_at_heading_slew = AUTO_YAW_SLEW_RATE;
|
||||||
} else {
|
} else {
|
||||||
int32_t turn_rate = (wrap_180_cd(yaw_look_at_heading - curr_yaw_target) / 100) / turn_rate_dps;
|
int32_t turn_rate = (wrap_180_cd(sub.yaw_look_at_heading - curr_yaw_target) / 100) / turn_rate_dps;
|
||||||
yaw_look_at_heading_slew = constrain_int32(turn_rate, 1, 360); // deg / sec
|
sub.yaw_look_at_heading_slew = constrain_int32(turn_rate, 1, 360); // deg / sec
|
||||||
}
|
}
|
||||||
|
|
||||||
// set yaw mode
|
// set yaw mode
|
||||||
|
@ -454,7 +378,7 @@ void Sub::set_auto_yaw_look_at_heading(float angle_deg, float turn_rate_dps, int
|
||||||
}
|
}
|
||||||
|
|
||||||
// set_auto_yaw_roi - sets the yaw to look at roi for auto mode
|
// set_auto_yaw_roi - sets the yaw to look at roi for auto mode
|
||||||
void Sub::set_auto_yaw_roi(const Location &roi_location)
|
void ModeAuto::set_auto_yaw_roi(const Location &roi_location)
|
||||||
{
|
{
|
||||||
// if location is zero lat, lon and altitude turn off ROI
|
// if location is zero lat, lon and altitude turn off ROI
|
||||||
if (roi_location.alt == 0 && roi_location.lat == 0 && roi_location.lng == 0) {
|
if (roi_location.alt == 0 && roi_location.lat == 0 && roi_location.lng == 0) {
|
||||||
|
@ -462,20 +386,20 @@ void Sub::set_auto_yaw_roi(const Location &roi_location)
|
||||||
set_auto_yaw_mode(get_default_auto_yaw_mode(false));
|
set_auto_yaw_mode(get_default_auto_yaw_mode(false));
|
||||||
#if HAL_MOUNT_ENABLED
|
#if HAL_MOUNT_ENABLED
|
||||||
// switch off the camera tracking if enabled
|
// switch off the camera tracking if enabled
|
||||||
if (camera_mount.get_mode() == MAV_MOUNT_MODE_GPS_POINT) {
|
if (sub.camera_mount.get_mode() == MAV_MOUNT_MODE_GPS_POINT) {
|
||||||
camera_mount.set_mode_to_default();
|
sub.camera_mount.set_mode_to_default();
|
||||||
}
|
}
|
||||||
#endif // HAL_MOUNT_ENABLED
|
#endif // HAL_MOUNT_ENABLED
|
||||||
} else {
|
} else {
|
||||||
#if HAL_MOUNT_ENABLED
|
#if HAL_MOUNT_ENABLED
|
||||||
// check if mount type requires us to rotate the sub
|
// check if mount type requires us to rotate the sub
|
||||||
if (!camera_mount.has_pan_control()) {
|
if (!sub.camera_mount.has_pan_control()) {
|
||||||
if (roi_location.get_vector_from_origin_NEU(roi_WP)) {
|
if (roi_location.get_vector_from_origin_NEU(sub.roi_WP)) {
|
||||||
set_auto_yaw_mode(AUTO_YAW_ROI);
|
set_auto_yaw_mode(AUTO_YAW_ROI);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// send the command to the camera mount
|
// send the command to the camera mount
|
||||||
camera_mount.set_roi_target(roi_location);
|
sub.camera_mount.set_roi_target(roi_location);
|
||||||
|
|
||||||
// TO-DO: expand handling of the do_nav_roi to support all modes of the MAVLink. Currently we only handle mode 4 (see below)
|
// TO-DO: expand handling of the do_nav_roi to support all modes of the MAVLink. Currently we only handle mode 4 (see below)
|
||||||
// 0: do nothing
|
// 0: do nothing
|
||||||
|
@ -485,70 +409,18 @@ void Sub::set_auto_yaw_roi(const Location &roi_location)
|
||||||
// 4: point at a target given a target id (can't be implemented)
|
// 4: point at a target given a target id (can't be implemented)
|
||||||
#else
|
#else
|
||||||
// if we have no camera mount aim the sub at the location
|
// if we have no camera mount aim the sub at the location
|
||||||
if (roi_location.get_vector_from_origin_NEU(roi_WP)) {
|
if (roi_location.get_vector_from_origin_NEU(sub.roi_WP)) {
|
||||||
set_auto_yaw_mode(AUTO_YAW_ROI);
|
set_auto_yaw_mode(AUTO_YAW_ROI);
|
||||||
}
|
}
|
||||||
#endif // HAL_MOUNT_ENABLED
|
#endif // HAL_MOUNT_ENABLED
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// get_auto_heading - returns target heading depending upon auto_yaw_mode
|
|
||||||
// 100hz update rate
|
|
||||||
float Sub::get_auto_heading()
|
|
||||||
{
|
|
||||||
switch (auto_yaw_mode) {
|
|
||||||
|
|
||||||
case AUTO_YAW_ROI:
|
|
||||||
// point towards a location held in roi_WP
|
|
||||||
return get_roi_yaw();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AUTO_YAW_LOOK_AT_HEADING:
|
|
||||||
// keep heading pointing in the direction held in yaw_look_at_heading with no pilot input allowed
|
|
||||||
return yaw_look_at_heading;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AUTO_YAW_LOOK_AHEAD:
|
|
||||||
// Commanded Yaw to automatically look ahead.
|
|
||||||
return get_look_ahead_yaw();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AUTO_YAW_RESETTOARMEDYAW:
|
|
||||||
// changes yaw to be same as when quad was armed
|
|
||||||
return initial_armed_bearing;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AUTO_YAW_CORRECT_XTRACK: {
|
|
||||||
// TODO return current yaw if not in appropriate mode
|
|
||||||
// Bearing of current track (centidegrees)
|
|
||||||
float track_bearing = get_bearing_cd(wp_nav.get_wp_origin().xy(), wp_nav.get_wp_destination().xy());
|
|
||||||
|
|
||||||
// Bearing from current position towards intermediate position target (centidegrees)
|
|
||||||
const Vector2f target_vel_xy{pos_control.get_vel_target_cms().x, pos_control.get_vel_target_cms().y};
|
|
||||||
float angle_error = 0.0f;
|
|
||||||
if (target_vel_xy.length() >= pos_control.get_max_speed_xy_cms() * 0.1f) {
|
|
||||||
const float desired_angle_cd = degrees(target_vel_xy.angle()) * 100.0f;
|
|
||||||
angle_error = wrap_180_cd(desired_angle_cd - track_bearing);
|
|
||||||
}
|
|
||||||
float angle_limited = constrain_float(angle_error, -g.xtrack_angle_limit * 100.0f, g.xtrack_angle_limit * 100.0f);
|
|
||||||
return wrap_360_cd(track_bearing + angle_limited);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AUTO_YAW_LOOK_AT_NEXT_WP:
|
|
||||||
default:
|
|
||||||
// point towards next waypoint.
|
|
||||||
// we don't use wp_bearing because we don't want the vehicle to turn too much during flight
|
|
||||||
return wp_nav.get_yaw();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return true if it is possible to recover from a rangefinder failure
|
// Return true if it is possible to recover from a rangefinder failure
|
||||||
bool Sub::auto_terrain_recover_start()
|
bool ModeAuto::auto_terrain_recover_start()
|
||||||
{
|
{
|
||||||
// Check rangefinder status to see if recovery is possible
|
// Check rangefinder status to see if recovery is possible
|
||||||
switch (rangefinder.status_orient(ROTATION_PITCH_270)) {
|
switch (sub.rangefinder.status_orient(ROTATION_PITCH_270)) {
|
||||||
|
|
||||||
case RangeFinder::Status::OutOfRangeLow:
|
case RangeFinder::Status::OutOfRangeLow:
|
||||||
case RangeFinder::Status::OutOfRangeHigh:
|
case RangeFinder::Status::OutOfRangeHigh:
|
||||||
|
@ -556,7 +428,7 @@ bool Sub::auto_terrain_recover_start()
|
||||||
// RangeFinder::Good if just one valid sample was obtained recently, but ::rangefinder_state.alt_healthy
|
// RangeFinder::Good if just one valid sample was obtained recently, but ::rangefinder_state.alt_healthy
|
||||||
// requires several consecutive valid readings for wpnav to accept rangefinder data
|
// requires several consecutive valid readings for wpnav to accept rangefinder data
|
||||||
case RangeFinder::Status::Good:
|
case RangeFinder::Status::Good:
|
||||||
auto_mode = Auto_TerrainRecover;
|
sub.auto_mode = Auto_TerrainRecover;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Not connected or no data
|
// Not connected or no data
|
||||||
|
@ -565,21 +437,21 @@ bool Sub::auto_terrain_recover_start()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize recovery timeout time
|
// Initialize recovery timeout time
|
||||||
fs_terrain_recover_start_ms = AP_HAL::millis();
|
sub.fs_terrain_recover_start_ms = AP_HAL::millis();
|
||||||
|
|
||||||
// Stop mission
|
// Stop mission
|
||||||
mission.stop();
|
sub.mission.stop();
|
||||||
|
|
||||||
// Reset xy target
|
// Reset xy target
|
||||||
loiter_nav.clear_pilot_desired_acceleration();
|
sub.loiter_nav.clear_pilot_desired_acceleration();
|
||||||
loiter_nav.init_target();
|
sub.loiter_nav.init_target();
|
||||||
|
|
||||||
// Reset z axis controller
|
// Reset z axis controller
|
||||||
pos_control.relax_z_controller(motors.get_throttle_hover());
|
position_control->relax_z_controller(motors.get_throttle_hover());
|
||||||
|
|
||||||
// initialize vertical maximum speeds and acceleration
|
// initialize vertical maximum speeds and acceleration
|
||||||
pos_control.set_max_speed_accel_z(wp_nav.get_default_speed_down(), wp_nav.get_default_speed_up(), wp_nav.get_accel_z());
|
position_control->set_max_speed_accel_z(sub.wp_nav.get_default_speed_down(), sub.wp_nav.get_default_speed_up(), sub.wp_nav.get_accel_z());
|
||||||
pos_control.set_correction_speed_accel_z(wp_nav.get_default_speed_down(), wp_nav.get_default_speed_up(), wp_nav.get_accel_z());
|
position_control->set_correction_speed_accel_z(sub.wp_nav.get_default_speed_down(), sub.wp_nav.get_default_speed_up(), sub.wp_nav.get_accel_z());
|
||||||
|
|
||||||
gcs().send_text(MAV_SEVERITY_WARNING, "Attempting auto failsafe recovery");
|
gcs().send_text(MAV_SEVERITY_WARNING, "Attempting auto failsafe recovery");
|
||||||
return true;
|
return true;
|
||||||
|
@ -588,7 +460,7 @@ bool Sub::auto_terrain_recover_start()
|
||||||
// Attempt recovery from terrain failsafe
|
// Attempt recovery from terrain failsafe
|
||||||
// If recovery is successful resume mission
|
// If recovery is successful resume mission
|
||||||
// If recovery fails revert to failsafe action
|
// If recovery fails revert to failsafe action
|
||||||
void Sub::auto_terrain_recover_run()
|
void ModeAuto::auto_terrain_recover_run()
|
||||||
{
|
{
|
||||||
float target_climb_rate = 0;
|
float target_climb_rate = 0;
|
||||||
static uint32_t rangefinder_recovery_ms = 0;
|
static uint32_t rangefinder_recovery_ms = 0;
|
||||||
|
@ -596,23 +468,23 @@ void Sub::auto_terrain_recover_run()
|
||||||
// if not armed set throttle to zero and exit immediately
|
// if not armed set throttle to zero and exit immediately
|
||||||
if (!motors.armed()) {
|
if (!motors.armed()) {
|
||||||
motors.set_desired_spool_state(AP_Motors::DesiredSpoolState::GROUND_IDLE);
|
motors.set_desired_spool_state(AP_Motors::DesiredSpoolState::GROUND_IDLE);
|
||||||
attitude_control.set_throttle_out(0,true,g.throttle_filt);
|
attitude_control->set_throttle_out(0,true,g.throttle_filt);
|
||||||
attitude_control.relax_attitude_controllers();
|
attitude_control->relax_attitude_controllers();
|
||||||
|
|
||||||
loiter_nav.init_target(); // Reset xy target
|
sub.loiter_nav.init_target(); // Reset xy target
|
||||||
pos_control.relax_z_controller(motors.get_throttle_hover()); // Reset z axis controller
|
position_control->relax_z_controller(motors.get_throttle_hover()); // Reset z axis controller
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (rangefinder.status_orient(ROTATION_PITCH_270)) {
|
switch (sub.rangefinder.status_orient(ROTATION_PITCH_270)) {
|
||||||
|
|
||||||
case RangeFinder::Status::OutOfRangeLow:
|
case RangeFinder::Status::OutOfRangeLow:
|
||||||
target_climb_rate = wp_nav.get_default_speed_up();
|
target_climb_rate = sub.wp_nav.get_default_speed_up();
|
||||||
rangefinder_recovery_ms = 0;
|
rangefinder_recovery_ms = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RangeFinder::Status::OutOfRangeHigh:
|
case RangeFinder::Status::OutOfRangeHigh:
|
||||||
target_climb_rate = wp_nav.get_default_speed_down();
|
target_climb_rate = sub.wp_nav.get_default_speed_down();
|
||||||
rangefinder_recovery_ms = 0;
|
rangefinder_recovery_ms = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -620,21 +492,21 @@ void Sub::auto_terrain_recover_run()
|
||||||
|
|
||||||
target_climb_rate = 0; // Attempt to hold current depth
|
target_climb_rate = 0; // Attempt to hold current depth
|
||||||
|
|
||||||
if (rangefinder_state.alt_healthy) {
|
if (sub.rangefinder_state.alt_healthy) {
|
||||||
|
|
||||||
// Start timer as soon as rangefinder is healthy
|
// Start timer as soon as rangefinder is healthy
|
||||||
if (rangefinder_recovery_ms == 0) {
|
if (rangefinder_recovery_ms == 0) {
|
||||||
rangefinder_recovery_ms = AP_HAL::millis();
|
rangefinder_recovery_ms = AP_HAL::millis();
|
||||||
pos_control.relax_z_controller(motors.get_throttle_hover()); // Reset alt hold targets
|
position_control->relax_z_controller(motors.get_throttle_hover()); // Reset alt hold targets
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1.5 seconds of healthy rangefinder means we can resume mission with terrain enabled
|
// 1.5 seconds of healthy rangefinder means we can resume mission with terrain enabled
|
||||||
if (AP_HAL::millis() > rangefinder_recovery_ms + 1500) {
|
if (AP_HAL::millis() > rangefinder_recovery_ms + 1500) {
|
||||||
gcs().send_text(MAV_SEVERITY_INFO, "Terrain failsafe recovery successful!");
|
gcs().send_text(MAV_SEVERITY_INFO, "Terrain failsafe recovery successful!");
|
||||||
failsafe_terrain_set_status(true); // Reset failsafe timers
|
sub.failsafe_terrain_set_status(true); // Reset failsafe timers
|
||||||
failsafe.terrain = false; // Clear flag
|
sub.failsafe.terrain = false; // Clear flag
|
||||||
auto_mode = Auto_Loiter; // Switch back to loiter for next iteration
|
sub.auto_mode = Auto_Loiter; // Switch back to loiter for next iteration
|
||||||
mission.resume(); // Resume mission
|
sub.mission.resume(); // Resume mission
|
||||||
rangefinder_recovery_ms = 0; // Reset for subsequent recoveries
|
rangefinder_recovery_ms = 0; // Reset for subsequent recoveries
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -646,25 +518,25 @@ void Sub::auto_terrain_recover_run()
|
||||||
// Terrain failsafe recovery has failed, terrain data is not available
|
// Terrain failsafe recovery has failed, terrain data is not available
|
||||||
// and rangefinder is not connected, or has stopped responding
|
// and rangefinder is not connected, or has stopped responding
|
||||||
gcs().send_text(MAV_SEVERITY_CRITICAL, "Terrain failsafe recovery failure: No Rangefinder!");
|
gcs().send_text(MAV_SEVERITY_CRITICAL, "Terrain failsafe recovery failure: No Rangefinder!");
|
||||||
failsafe_terrain_act();
|
sub.failsafe_terrain_act();
|
||||||
rangefinder_recovery_ms = 0;
|
rangefinder_recovery_ms = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// exit on failure (timeout)
|
// exit on failure (timeout)
|
||||||
if (AP_HAL::millis() > fs_terrain_recover_start_ms + FS_TERRAIN_RECOVER_TIMEOUT_MS) {
|
if (AP_HAL::millis() > sub.fs_terrain_recover_start_ms + FS_TERRAIN_RECOVER_TIMEOUT_MS) {
|
||||||
// Recovery has failed, revert to failsafe action
|
// Recovery has failed, revert to failsafe action
|
||||||
gcs().send_text(MAV_SEVERITY_CRITICAL, "Terrain failsafe recovery timeout!");
|
gcs().send_text(MAV_SEVERITY_CRITICAL, "Terrain failsafe recovery timeout!");
|
||||||
failsafe_terrain_act();
|
sub.failsafe_terrain_act();
|
||||||
}
|
}
|
||||||
|
|
||||||
// run loiter controller
|
// run loiter controller
|
||||||
loiter_nav.update();
|
sub.loiter_nav.update();
|
||||||
|
|
||||||
///////////////////////
|
///////////////////////
|
||||||
// update xy targets //
|
// update xy targets //
|
||||||
float lateral_out, forward_out;
|
float lateral_out, forward_out;
|
||||||
translate_wpnav_rp(lateral_out, forward_out);
|
sub.translate_wpnav_rp(lateral_out, forward_out);
|
||||||
|
|
||||||
// Send to forward/lateral outputs
|
// Send to forward/lateral outputs
|
||||||
motors.set_lateral(lateral_out);
|
motors.set_lateral(lateral_out);
|
||||||
|
@ -672,8 +544,8 @@ void Sub::auto_terrain_recover_run()
|
||||||
|
|
||||||
/////////////////////
|
/////////////////////
|
||||||
// update z target //
|
// update z target //
|
||||||
pos_control.set_pos_target_z_from_climb_rate_cm(target_climb_rate);
|
position_control->set_pos_target_z_from_climb_rate_cm(target_climb_rate);
|
||||||
pos_control.update_z_controller();
|
position_control->update_z_controller();
|
||||||
|
|
||||||
////////////////////////////
|
////////////////////////////
|
||||||
// update angular targets //
|
// update angular targets //
|
||||||
|
@ -681,11 +553,11 @@ void Sub::auto_terrain_recover_run()
|
||||||
float target_pitch = 0;
|
float target_pitch = 0;
|
||||||
|
|
||||||
// convert pilot input to lean angles
|
// convert pilot input to lean angles
|
||||||
// To-Do: convert get_pilot_desired_lean_angles to return angles as floats
|
// To-Do: convert sub.get_pilot_desired_lean_angles to return angles as floats
|
||||||
get_pilot_desired_lean_angles(channel_roll->get_control_in(), channel_pitch->get_control_in(), target_roll, target_pitch, aparm.angle_max);
|
sub.get_pilot_desired_lean_angles(channel_roll->get_control_in(), channel_pitch->get_control_in(), target_roll, target_pitch, sub.aparm.angle_max);
|
||||||
|
|
||||||
float target_yaw_rate = 0;
|
float target_yaw_rate = 0;
|
||||||
|
|
||||||
// call attitude controller
|
// call attitude controller
|
||||||
attitude_control.input_euler_angle_roll_pitch_euler_rate_yaw(target_roll, target_pitch, target_yaw_rate);
|
attitude_control->input_euler_angle_roll_pitch_euler_rate_yaw(target_roll, target_pitch, target_yaw_rate);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,82 +5,82 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// circle_init - initialise circle controller flight mode
|
// circle_init - initialise circle controller flight mode
|
||||||
bool Sub::circle_init()
|
bool ModeCircle::init(bool ignore_checks)
|
||||||
{
|
{
|
||||||
if (!position_ok()) {
|
if (!sub.position_ok()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
circle_pilot_yaw_override = false;
|
sub.circle_pilot_yaw_override = false;
|
||||||
|
|
||||||
// initialize speeds and accelerations
|
// initialize speeds and accelerations
|
||||||
pos_control.set_max_speed_accel_xy(wp_nav.get_default_speed_xy(), wp_nav.get_wp_acceleration());
|
position_control->set_max_speed_accel_xy(sub.wp_nav.get_default_speed_xy(), sub.wp_nav.get_wp_acceleration());
|
||||||
pos_control.set_correction_speed_accel_xy(wp_nav.get_default_speed_xy(), wp_nav.get_wp_acceleration());
|
position_control->set_correction_speed_accel_xy(sub.wp_nav.get_default_speed_xy(), sub.wp_nav.get_wp_acceleration());
|
||||||
pos_control.set_max_speed_accel_z(-get_pilot_speed_dn(), g.pilot_speed_up, g.pilot_accel_z);
|
position_control->set_max_speed_accel_z(-sub.get_pilot_speed_dn(), g.pilot_speed_up, g.pilot_accel_z);
|
||||||
pos_control.set_correction_speed_accel_z(-get_pilot_speed_dn(), g.pilot_speed_up, g.pilot_accel_z);
|
position_control->set_correction_speed_accel_z(-sub.get_pilot_speed_dn(), g.pilot_speed_up, g.pilot_accel_z);
|
||||||
|
|
||||||
// initialise circle controller including setting the circle center based on vehicle speed
|
// initialise circle controller including setting the circle center based on vehicle speed
|
||||||
circle_nav.init();
|
sub.circle_nav.init();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// circle_run - runs the circle flight mode
|
// circle_run - runs the circle flight mode
|
||||||
// should be called at 100hz or more
|
// should be called at 100hz or more
|
||||||
void Sub::circle_run()
|
void ModeCircle::run()
|
||||||
{
|
{
|
||||||
float target_yaw_rate = 0;
|
float target_yaw_rate = 0;
|
||||||
float target_climb_rate = 0;
|
float target_climb_rate = 0;
|
||||||
|
|
||||||
// update parameters, to allow changing at runtime
|
// update parameters, to allow changing at runtime
|
||||||
pos_control.set_max_speed_accel_xy(wp_nav.get_default_speed_xy(), wp_nav.get_wp_acceleration());
|
position_control->set_max_speed_accel_xy(sub.wp_nav.get_default_speed_xy(), sub.wp_nav.get_wp_acceleration());
|
||||||
pos_control.set_max_speed_accel_z(-get_pilot_speed_dn(), g.pilot_speed_up, g.pilot_accel_z);
|
position_control->set_max_speed_accel_z(-sub.get_pilot_speed_dn(), g.pilot_speed_up, g.pilot_accel_z);
|
||||||
|
|
||||||
// if not armed set throttle to zero and exit immediately
|
// if not armed set throttle to zero and exit immediately
|
||||||
if (!motors.armed()) {
|
if (!motors.armed()) {
|
||||||
// To-Do: add some initialisation of position controllers
|
// To-Do: add some initialisation of position controllers
|
||||||
motors.set_desired_spool_state(AP_Motors::DesiredSpoolState::GROUND_IDLE);
|
motors.set_desired_spool_state(AP_Motors::DesiredSpoolState::GROUND_IDLE);
|
||||||
// Sub vehicles do not stabilize roll/pitch/yaw when disarmed
|
// Sub vehicles do not stabilize roll/pitch/yaw when disarmed
|
||||||
attitude_control.set_throttle_out(0,true,g.throttle_filt);
|
attitude_control->set_throttle_out(0,true,g.throttle_filt);
|
||||||
attitude_control.relax_attitude_controllers();
|
attitude_control->relax_attitude_controllers();
|
||||||
circle_nav.init();
|
sub.circle_nav.init();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// process pilot inputs
|
// process pilot inputs
|
||||||
// get pilot's desired yaw rate
|
// get pilot's desired yaw rate
|
||||||
target_yaw_rate = get_pilot_desired_yaw_rate(channel_yaw->get_control_in());
|
target_yaw_rate = sub.get_pilot_desired_yaw_rate(channel_yaw->get_control_in());
|
||||||
if (!is_zero(target_yaw_rate)) {
|
if (!is_zero(target_yaw_rate)) {
|
||||||
circle_pilot_yaw_override = true;
|
sub.circle_pilot_yaw_override = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get pilot desired climb rate
|
// get pilot desired climb rate
|
||||||
target_climb_rate = get_pilot_desired_climb_rate(channel_throttle->get_control_in());
|
target_climb_rate = sub.get_pilot_desired_climb_rate(channel_throttle->get_control_in());
|
||||||
|
|
||||||
// set motors to full range
|
// set motors to full range
|
||||||
motors.set_desired_spool_state(AP_Motors::DesiredSpoolState::THROTTLE_UNLIMITED);
|
motors.set_desired_spool_state(AP_Motors::DesiredSpoolState::THROTTLE_UNLIMITED);
|
||||||
|
|
||||||
// run circle controller
|
// run circle controller
|
||||||
failsafe_terrain_set_status(circle_nav.update());
|
sub.failsafe_terrain_set_status(sub.circle_nav.update());
|
||||||
|
|
||||||
///////////////////////
|
///////////////////////
|
||||||
// update xy outputs //
|
// update xy outputs //
|
||||||
|
|
||||||
float lateral_out, forward_out;
|
float lateral_out, forward_out;
|
||||||
translate_circle_nav_rp(lateral_out, forward_out);
|
sub.translate_circle_nav_rp(lateral_out, forward_out);
|
||||||
|
|
||||||
// Send to forward/lateral outputs
|
// Send to forward/lateral outputs
|
||||||
motors.set_lateral(lateral_out);
|
motors.set_lateral(lateral_out);
|
||||||
motors.set_forward(forward_out);
|
motors.set_forward(forward_out);
|
||||||
|
|
||||||
// call attitude controller
|
// call attitude controller
|
||||||
if (circle_pilot_yaw_override) {
|
if (sub.circle_pilot_yaw_override) {
|
||||||
attitude_control.input_euler_angle_roll_pitch_euler_rate_yaw(channel_roll->get_control_in(), channel_pitch->get_control_in(), target_yaw_rate);
|
attitude_control->input_euler_angle_roll_pitch_euler_rate_yaw(channel_roll->get_control_in(), channel_pitch->get_control_in(), target_yaw_rate);
|
||||||
} else {
|
} else {
|
||||||
attitude_control.input_euler_angle_roll_pitch_yaw(channel_roll->get_control_in(), channel_pitch->get_control_in(), circle_nav.get_yaw(), true);
|
attitude_control->input_euler_angle_roll_pitch_yaw(channel_roll->get_control_in(), channel_pitch->get_control_in(), sub.circle_nav.get_yaw(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// update altitude target and call position controller
|
// update altitude target and call position controller
|
||||||
pos_control.set_pos_target_z_from_climb_rate_cm(target_climb_rate);
|
position_control->set_pos_target_z_from_climb_rate_cm(target_climb_rate);
|
||||||
pos_control.update_z_controller();
|
position_control->update_z_controller();
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,9 +29,9 @@ struct Guided_Limit {
|
||||||
} guided_limit;
|
} guided_limit;
|
||||||
|
|
||||||
// guided_init - initialise guided controller
|
// guided_init - initialise guided controller
|
||||||
bool Sub::guided_init(bool ignore_checks)
|
bool ModeGuided::init(bool ignore_checks)
|
||||||
{
|
{
|
||||||
if (!position_ok() && !ignore_checks) {
|
if (!sub.position_ok() && !ignore_checks) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,73 +40,107 @@ bool Sub::guided_init(bool ignore_checks)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get_default_auto_yaw_mode - returns auto_yaw_mode based on WP_YAW_BEHAVIOR parameter
|
||||||
|
// set rtl parameter to true if this is during an RTL
|
||||||
|
autopilot_yaw_mode ModeGuided::get_default_auto_yaw_mode(bool rtl) const
|
||||||
|
{
|
||||||
|
switch (g.wp_yaw_behavior) {
|
||||||
|
|
||||||
|
case WP_YAW_BEHAVIOR_NONE:
|
||||||
|
return AUTO_YAW_HOLD;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WP_YAW_BEHAVIOR_LOOK_AT_NEXT_WP_EXCEPT_RTL:
|
||||||
|
if (rtl) {
|
||||||
|
return AUTO_YAW_HOLD;
|
||||||
|
} else {
|
||||||
|
return AUTO_YAW_LOOK_AT_NEXT_WP;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WP_YAW_BEHAVIOR_LOOK_AHEAD:
|
||||||
|
return AUTO_YAW_LOOK_AHEAD;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WP_YAW_BEHAVIOR_CORRECT_XTRACK:
|
||||||
|
return AUTO_YAW_CORRECT_XTRACK;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WP_YAW_BEHAVIOR_LOOK_AT_NEXT_WP:
|
||||||
|
default:
|
||||||
|
return AUTO_YAW_LOOK_AT_NEXT_WP;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// initialise guided mode's position controller
|
// initialise guided mode's position controller
|
||||||
void Sub::guided_pos_control_start()
|
void ModeGuided::guided_pos_control_start()
|
||||||
{
|
{
|
||||||
// set to position control mode
|
// set to position control mode
|
||||||
guided_mode = Guided_WP;
|
sub.guided_mode = Guided_WP;
|
||||||
|
|
||||||
// initialise waypoint controller
|
// initialise waypoint controller
|
||||||
wp_nav.wp_and_spline_init();
|
sub.wp_nav.wp_and_spline_init();
|
||||||
|
|
||||||
// initialise wpnav to stopping point at current altitude
|
// initialise wpnav to stopping point at current altitude
|
||||||
// To-Do: set to current location if disarmed?
|
// To-Do: set to current location if disarmed?
|
||||||
// To-Do: set to stopping point altitude?
|
// To-Do: set to stopping point altitude?
|
||||||
Vector3f stopping_point;
|
Vector3f stopping_point;
|
||||||
wp_nav.get_wp_stopping_point(stopping_point);
|
sub.wp_nav.get_wp_stopping_point(stopping_point);
|
||||||
|
|
||||||
// no need to check return status because terrain data is not used
|
// no need to check return status because terrain data is not used
|
||||||
wp_nav.set_wp_destination(stopping_point, false);
|
sub.wp_nav.set_wp_destination(stopping_point, false);
|
||||||
|
|
||||||
// initialise yaw
|
// initialise yaw
|
||||||
set_auto_yaw_mode(get_default_auto_yaw_mode(false));
|
set_auto_yaw_mode(get_default_auto_yaw_mode(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialise guided mode's velocity controller
|
// initialise guided mode's velocity controller
|
||||||
void Sub::guided_vel_control_start()
|
void ModeGuided::guided_vel_control_start()
|
||||||
{
|
{
|
||||||
// set guided_mode to velocity controller
|
// set guided_mode to velocity controller
|
||||||
guided_mode = Guided_Velocity;
|
sub.guided_mode = Guided_Velocity;
|
||||||
|
|
||||||
// initialize vertical maximum speeds and acceleration
|
// initialize vertical maximum speeds and acceleration
|
||||||
pos_control.set_max_speed_accel_z(-get_pilot_speed_dn(), g.pilot_speed_up, g.pilot_accel_z);
|
position_control->set_max_speed_accel_z(-sub.get_pilot_speed_dn(), g.pilot_speed_up, g.pilot_accel_z);
|
||||||
pos_control.set_correction_speed_accel_z(-get_pilot_speed_dn(), g.pilot_speed_up, g.pilot_accel_z);
|
position_control->set_correction_speed_accel_z(-sub.get_pilot_speed_dn(), g.pilot_speed_up, g.pilot_accel_z);
|
||||||
|
|
||||||
// initialise velocity controller
|
// initialise velocity controller
|
||||||
pos_control.init_z_controller();
|
position_control->init_z_controller();
|
||||||
pos_control.init_xy_controller();
|
position_control->init_xy_controller();
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialise guided mode's posvel controller
|
// initialise guided mode's posvel controller
|
||||||
void Sub::guided_posvel_control_start()
|
void ModeGuided::guided_posvel_control_start()
|
||||||
{
|
{
|
||||||
// set guided_mode to velocity controller
|
// set guided_mode to velocity controller
|
||||||
guided_mode = Guided_PosVel;
|
sub.guided_mode = Guided_PosVel;
|
||||||
|
|
||||||
// set vertical speed and acceleration
|
// set vertical speed and acceleration
|
||||||
pos_control.set_max_speed_accel_z(wp_nav.get_default_speed_down(), wp_nav.get_default_speed_up(), wp_nav.get_accel_z());
|
position_control->set_max_speed_accel_z(sub.wp_nav.get_default_speed_down(), sub.wp_nav.get_default_speed_up(), sub.wp_nav.get_accel_z());
|
||||||
pos_control.set_correction_speed_accel_z(wp_nav.get_default_speed_down(), wp_nav.get_default_speed_up(), wp_nav.get_accel_z());
|
position_control->set_correction_speed_accel_z(sub.wp_nav.get_default_speed_down(), sub.wp_nav.get_default_speed_up(), sub.wp_nav.get_accel_z());
|
||||||
|
|
||||||
// initialise velocity controller
|
// initialise velocity controller
|
||||||
pos_control.init_z_controller();
|
position_control->init_z_controller();
|
||||||
pos_control.init_xy_controller();
|
position_control->init_xy_controller();
|
||||||
|
|
||||||
// pilot always controls yaw
|
// pilot always controls yaw
|
||||||
set_auto_yaw_mode(AUTO_YAW_HOLD);
|
set_auto_yaw_mode(AUTO_YAW_HOLD);
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialise guided mode's angle controller
|
// initialise guided mode's angle controller
|
||||||
void Sub::guided_angle_control_start()
|
void ModeGuided::guided_angle_control_start()
|
||||||
{
|
{
|
||||||
// set guided_mode to velocity controller
|
// set guided_mode to velocity controller
|
||||||
guided_mode = Guided_Angle;
|
sub.guided_mode = Guided_Angle;
|
||||||
|
|
||||||
// set vertical speed and acceleration
|
// set vertical speed and acceleration
|
||||||
pos_control.set_max_speed_accel_z(wp_nav.get_default_speed_down(), wp_nav.get_default_speed_up(), wp_nav.get_accel_z());
|
position_control->set_max_speed_accel_z(sub.wp_nav.get_default_speed_down(), sub.wp_nav.get_default_speed_up(), sub.wp_nav.get_accel_z());
|
||||||
pos_control.set_correction_speed_accel_z(wp_nav.get_default_speed_down(), wp_nav.get_default_speed_up(), wp_nav.get_accel_z());
|
position_control->set_correction_speed_accel_z(sub.wp_nav.get_default_speed_down(), sub.wp_nav.get_default_speed_up(), sub.wp_nav.get_accel_z());
|
||||||
|
|
||||||
// initialise velocity controller
|
// initialise velocity controller
|
||||||
pos_control.init_z_controller();
|
position_control->init_z_controller();
|
||||||
|
|
||||||
// initialise targets
|
// initialise targets
|
||||||
guided_angle_state.update_time_ms = AP_HAL::millis();
|
guided_angle_state.update_time_ms = AP_HAL::millis();
|
||||||
|
@ -122,17 +156,17 @@ void Sub::guided_angle_control_start()
|
||||||
// guided_set_destination - sets guided mode's target destination
|
// guided_set_destination - sets guided mode's target destination
|
||||||
// Returns true if the fence is enabled and guided waypoint is within the fence
|
// Returns true if the fence is enabled and guided waypoint is within the fence
|
||||||
// else return false if the waypoint is outside the fence
|
// else return false if the waypoint is outside the fence
|
||||||
bool Sub::guided_set_destination(const Vector3f& destination)
|
bool ModeGuided::guided_set_destination(const Vector3f& destination)
|
||||||
{
|
{
|
||||||
// ensure we are in position control mode
|
// ensure we are in position control mode
|
||||||
if (guided_mode != Guided_WP) {
|
if (sub.guided_mode != Guided_WP) {
|
||||||
guided_pos_control_start();
|
guided_pos_control_start();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if AP_FENCE_ENABLED
|
#if AP_FENCE_ENABLED
|
||||||
// reject destination if outside the fence
|
// reject destination if outside the fence
|
||||||
const Location dest_loc(destination, Location::AltFrame::ABOVE_ORIGIN);
|
const Location dest_loc(destination, Location::AltFrame::ABOVE_ORIGIN);
|
||||||
if (!fence.check_destination_within_fence(dest_loc)) {
|
if (!sub.fence.check_destination_within_fence(dest_loc)) {
|
||||||
AP::logger().Write_Error(LogErrorSubsystem::NAVIGATION, LogErrorCode::DEST_OUTSIDE_FENCE);
|
AP::logger().Write_Error(LogErrorSubsystem::NAVIGATION, LogErrorCode::DEST_OUTSIDE_FENCE);
|
||||||
// failure is propagated to GCS with NAK
|
// failure is propagated to GCS with NAK
|
||||||
return false;
|
return false;
|
||||||
|
@ -140,34 +174,34 @@ bool Sub::guided_set_destination(const Vector3f& destination)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// no need to check return status because terrain data is not used
|
// no need to check return status because terrain data is not used
|
||||||
wp_nav.set_wp_destination(destination, false);
|
sub.wp_nav.set_wp_destination(destination, false);
|
||||||
|
|
||||||
// log target
|
// log target
|
||||||
Log_Write_GuidedTarget(guided_mode, destination, Vector3f());
|
sub.Log_Write_GuidedTarget(sub.guided_mode, destination, Vector3f());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// sets guided mode's target from a Location object
|
// sets guided mode's target from a Location object
|
||||||
// returns false if destination could not be set (probably caused by missing terrain data)
|
// returns false if destination could not be set (probably caused by missing terrain data)
|
||||||
// or if the fence is enabled and guided waypoint is outside the fence
|
// or if the fence is enabled and guided waypoint is outside the fence
|
||||||
bool Sub::guided_set_destination(const Location& dest_loc)
|
bool ModeGuided::guided_set_destination(const Location& dest_loc)
|
||||||
{
|
{
|
||||||
// ensure we are in position control mode
|
// ensure we are in position control mode
|
||||||
if (guided_mode != Guided_WP) {
|
if (sub.guided_mode != Guided_WP) {
|
||||||
guided_pos_control_start();
|
guided_pos_control_start();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if AP_FENCE_ENABLED
|
#if AP_FENCE_ENABLED
|
||||||
// reject destination outside the fence.
|
// reject destination outside the fence.
|
||||||
// Note: there is a danger that a target specified as a terrain altitude might not be checked if the conversion to alt-above-home fails
|
// Note: there is a danger that a target specified as a terrain altitude might not be checked if the conversion to alt-above-home fails
|
||||||
if (!fence.check_destination_within_fence(dest_loc)) {
|
if (!sub.fence.check_destination_within_fence(dest_loc)) {
|
||||||
AP::logger().Write_Error(LogErrorSubsystem::NAVIGATION, LogErrorCode::DEST_OUTSIDE_FENCE);
|
AP::logger().Write_Error(LogErrorSubsystem::NAVIGATION, LogErrorCode::DEST_OUTSIDE_FENCE);
|
||||||
// failure is propagated to GCS with NAK
|
// failure is propagated to GCS with NAK
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!wp_nav.set_wp_destination_loc(dest_loc)) {
|
if (!sub.wp_nav.set_wp_destination_loc(dest_loc)) {
|
||||||
// failure to set destination can only be because of missing terrain data
|
// failure to set destination can only be because of missing terrain data
|
||||||
AP::logger().Write_Error(LogErrorSubsystem::NAVIGATION, LogErrorCode::FAILED_TO_SET_DESTINATION);
|
AP::logger().Write_Error(LogErrorSubsystem::NAVIGATION, LogErrorCode::FAILED_TO_SET_DESTINATION);
|
||||||
// failure is propagated to GCS with NAK
|
// failure is propagated to GCS with NAK
|
||||||
|
@ -175,36 +209,36 @@ bool Sub::guided_set_destination(const Location& dest_loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// log target
|
// log target
|
||||||
Log_Write_GuidedTarget(guided_mode, Vector3f(dest_loc.lat, dest_loc.lng, dest_loc.alt),Vector3f());
|
sub.Log_Write_GuidedTarget(sub.guided_mode, Vector3f(dest_loc.lat, dest_loc.lng, dest_loc.alt),Vector3f());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// guided_set_velocity - sets guided mode's target velocity
|
// guided_set_velocity - sets guided mode's target velocity
|
||||||
void Sub::guided_set_velocity(const Vector3f& velocity)
|
void ModeGuided::guided_set_velocity(const Vector3f& velocity)
|
||||||
{
|
{
|
||||||
// check we are in velocity control mode
|
// check we are in velocity control mode
|
||||||
if (guided_mode != Guided_Velocity) {
|
if (sub.guided_mode != Guided_Velocity) {
|
||||||
guided_vel_control_start();
|
guided_vel_control_start();
|
||||||
}
|
}
|
||||||
|
|
||||||
update_time_ms = AP_HAL::millis();
|
update_time_ms = AP_HAL::millis();
|
||||||
|
|
||||||
// set position controller velocity target
|
// set position controller velocity target
|
||||||
pos_control.set_vel_desired_cms(velocity);
|
position_control->set_vel_desired_cms(velocity);
|
||||||
}
|
}
|
||||||
|
|
||||||
// set guided mode posvel target
|
// set guided mode posvel target
|
||||||
bool Sub::guided_set_destination_posvel(const Vector3f& destination, const Vector3f& velocity)
|
bool ModeGuided::guided_set_destination_posvel(const Vector3f& destination, const Vector3f& velocity)
|
||||||
{
|
{
|
||||||
// check we are in velocity control mode
|
// check we are in velocity control mode
|
||||||
if (guided_mode != Guided_PosVel) {
|
if (sub.guided_mode != Guided_PosVel) {
|
||||||
guided_posvel_control_start();
|
guided_posvel_control_start();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if AP_FENCE_ENABLED
|
#if AP_FENCE_ENABLED
|
||||||
// reject destination if outside the fence
|
// reject destination if outside the fence
|
||||||
const Location dest_loc(destination, Location::AltFrame::ABOVE_ORIGIN);
|
const Location dest_loc(destination, Location::AltFrame::ABOVE_ORIGIN);
|
||||||
if (!fence.check_destination_within_fence(dest_loc)) {
|
if (!sub.fence.check_destination_within_fence(dest_loc)) {
|
||||||
AP::logger().Write_Error(LogErrorSubsystem::NAVIGATION, LogErrorCode::DEST_OUTSIDE_FENCE);
|
AP::logger().Write_Error(LogErrorSubsystem::NAVIGATION, LogErrorCode::DEST_OUTSIDE_FENCE);
|
||||||
// failure is propagated to GCS with NAK
|
// failure is propagated to GCS with NAK
|
||||||
return false;
|
return false;
|
||||||
|
@ -215,21 +249,21 @@ bool Sub::guided_set_destination_posvel(const Vector3f& destination, const Vecto
|
||||||
posvel_pos_target_cm = destination.topostype();
|
posvel_pos_target_cm = destination.topostype();
|
||||||
posvel_vel_target_cms = velocity;
|
posvel_vel_target_cms = velocity;
|
||||||
|
|
||||||
pos_control.input_pos_vel_accel_xy(posvel_pos_target_cm.xy(), posvel_vel_target_cms.xy(), Vector2f());
|
position_control->input_pos_vel_accel_xy(posvel_pos_target_cm.xy(), posvel_vel_target_cms.xy(), Vector2f());
|
||||||
float dz = posvel_pos_target_cm.z;
|
float dz = posvel_pos_target_cm.z;
|
||||||
pos_control.input_pos_vel_accel_z(dz, posvel_vel_target_cms.z, 0);
|
position_control->input_pos_vel_accel_z(dz, posvel_vel_target_cms.z, 0);
|
||||||
posvel_pos_target_cm.z = dz;
|
posvel_pos_target_cm.z = dz;
|
||||||
|
|
||||||
// log target
|
// log target
|
||||||
Log_Write_GuidedTarget(guided_mode, destination, velocity);
|
sub.Log_Write_GuidedTarget(sub.guided_mode, destination, velocity);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// set guided mode angle target
|
// set guided mode angle target
|
||||||
void Sub::guided_set_angle(const Quaternion &q, float climb_rate_cms)
|
void ModeGuided::guided_set_angle(const Quaternion &q, float climb_rate_cms)
|
||||||
{
|
{
|
||||||
// check we are in velocity control mode
|
// check we are in velocity control mode
|
||||||
if (guided_mode != Guided_Angle) {
|
if (sub.guided_mode != Guided_Angle) {
|
||||||
guided_angle_control_start();
|
guided_angle_control_start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,10 +279,10 @@ void Sub::guided_set_angle(const Quaternion &q, float climb_rate_cms)
|
||||||
|
|
||||||
// guided_run - runs the guided controller
|
// guided_run - runs the guided controller
|
||||||
// should be called at 100hz or more
|
// should be called at 100hz or more
|
||||||
void Sub::guided_run()
|
void ModeGuided::run()
|
||||||
{
|
{
|
||||||
// call the correct auto controller
|
// call the correct auto controller
|
||||||
switch (guided_mode) {
|
switch (sub.guided_mode) {
|
||||||
|
|
||||||
case Guided_WP:
|
case Guided_WP:
|
||||||
// run position controller
|
// run position controller
|
||||||
|
@ -274,23 +308,23 @@ void Sub::guided_run()
|
||||||
|
|
||||||
// guided_pos_control_run - runs the guided position controller
|
// guided_pos_control_run - runs the guided position controller
|
||||||
// called from guided_run
|
// called from guided_run
|
||||||
void Sub::guided_pos_control_run()
|
void ModeGuided::guided_pos_control_run()
|
||||||
{
|
{
|
||||||
// if motors not enabled set throttle to zero and exit immediately
|
// if motors not enabled set throttle to zero and exit immediately
|
||||||
if (!motors.armed()) {
|
if (!motors.armed()) {
|
||||||
motors.set_desired_spool_state(AP_Motors::DesiredSpoolState::GROUND_IDLE);
|
motors.set_desired_spool_state(AP_Motors::DesiredSpoolState::GROUND_IDLE);
|
||||||
// Sub vehicles do not stabilize roll/pitch/yaw when disarmed
|
// Sub vehicles do not stabilize roll/pitch/yaw when disarmed
|
||||||
attitude_control.set_throttle_out(0,true,g.throttle_filt);
|
attitude_control->set_throttle_out(0,true,g.throttle_filt);
|
||||||
attitude_control.relax_attitude_controllers();
|
attitude_control->relax_attitude_controllers();
|
||||||
wp_nav.wp_and_spline_init();
|
sub.wp_nav.wp_and_spline_init();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// process pilot's yaw input
|
// process pilot's yaw input
|
||||||
float target_yaw_rate = 0;
|
float target_yaw_rate = 0;
|
||||||
if (!failsafe.pilot_input) {
|
if (!sub.failsafe.pilot_input) {
|
||||||
// get pilot's desired yaw rate
|
// get pilot's desired yaw rate
|
||||||
target_yaw_rate = get_pilot_desired_yaw_rate(channel_yaw->get_control_in());
|
target_yaw_rate = sub.get_pilot_desired_yaw_rate(channel_yaw->get_control_in());
|
||||||
if (!is_zero(target_yaw_rate)) {
|
if (!is_zero(target_yaw_rate)) {
|
||||||
set_auto_yaw_mode(AUTO_YAW_HOLD);
|
set_auto_yaw_mode(AUTO_YAW_HOLD);
|
||||||
}
|
}
|
||||||
|
@ -300,10 +334,10 @@ void Sub::guided_pos_control_run()
|
||||||
motors.set_desired_spool_state(AP_Motors::DesiredSpoolState::THROTTLE_UNLIMITED);
|
motors.set_desired_spool_state(AP_Motors::DesiredSpoolState::THROTTLE_UNLIMITED);
|
||||||
|
|
||||||
// run waypoint controller
|
// run waypoint controller
|
||||||
failsafe_terrain_set_status(wp_nav.update_wpnav());
|
sub.failsafe_terrain_set_status(sub.wp_nav.update_wpnav());
|
||||||
|
|
||||||
float lateral_out, forward_out;
|
float lateral_out, forward_out;
|
||||||
translate_wpnav_rp(lateral_out, forward_out);
|
sub.translate_wpnav_rp(lateral_out, forward_out);
|
||||||
|
|
||||||
// Send to forward/lateral outputs
|
// Send to forward/lateral outputs
|
||||||
motors.set_lateral(lateral_out);
|
motors.set_lateral(lateral_out);
|
||||||
|
@ -311,39 +345,39 @@ void Sub::guided_pos_control_run()
|
||||||
|
|
||||||
// WP_Nav has set the vertical position control targets
|
// WP_Nav has set the vertical position control targets
|
||||||
// run the vertical position controller and set output throttle
|
// run the vertical position controller and set output throttle
|
||||||
pos_control.update_z_controller();
|
position_control->update_z_controller();
|
||||||
|
|
||||||
// call attitude controller
|
// call attitude controller
|
||||||
if (auto_yaw_mode == AUTO_YAW_HOLD) {
|
if (sub.auto_yaw_mode == AUTO_YAW_HOLD) {
|
||||||
// roll & pitch & yaw rate from pilot
|
// roll & pitch & yaw rate from pilot
|
||||||
attitude_control.input_euler_angle_roll_pitch_euler_rate_yaw(channel_roll->get_control_in(), channel_pitch->get_control_in(), target_yaw_rate);
|
attitude_control->input_euler_angle_roll_pitch_euler_rate_yaw(channel_roll->get_control_in(), channel_pitch->get_control_in(), target_yaw_rate);
|
||||||
} else {
|
} else {
|
||||||
// roll, pitch from pilot, yaw heading from auto_heading()
|
// roll, pitch from pilot, yaw heading from auto_heading()
|
||||||
attitude_control.input_euler_angle_roll_pitch_yaw(channel_roll->get_control_in(), channel_pitch->get_control_in(), get_auto_heading(), true);
|
attitude_control->input_euler_angle_roll_pitch_yaw(channel_roll->get_control_in(), channel_pitch->get_control_in(), get_auto_heading(), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// guided_vel_control_run - runs the guided velocity controller
|
// guided_vel_control_run - runs the guided velocity controller
|
||||||
// called from guided_run
|
// called from guided_run
|
||||||
void Sub::guided_vel_control_run()
|
void ModeGuided::guided_vel_control_run()
|
||||||
{
|
{
|
||||||
// ifmotors not enabled set throttle to zero and exit immediately
|
// ifmotors not enabled set throttle to zero and exit immediately
|
||||||
if (!motors.armed()) {
|
if (!motors.armed()) {
|
||||||
motors.set_desired_spool_state(AP_Motors::DesiredSpoolState::GROUND_IDLE);
|
motors.set_desired_spool_state(AP_Motors::DesiredSpoolState::GROUND_IDLE);
|
||||||
// Sub vehicles do not stabilize roll/pitch/yaw when disarmed
|
// Sub vehicles do not stabilize roll/pitch/yaw when disarmed
|
||||||
attitude_control.set_throttle_out(0,true,g.throttle_filt);
|
attitude_control->set_throttle_out(0,true,g.throttle_filt);
|
||||||
attitude_control.relax_attitude_controllers();
|
attitude_control->relax_attitude_controllers();
|
||||||
// initialise velocity controller
|
// initialise velocity controller
|
||||||
pos_control.init_z_controller();
|
position_control->init_z_controller();
|
||||||
pos_control.init_xy_controller();
|
position_control->init_xy_controller();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// process pilot's yaw input
|
// process pilot's yaw input
|
||||||
float target_yaw_rate = 0;
|
float target_yaw_rate = 0;
|
||||||
if (!failsafe.pilot_input) {
|
if (!sub.failsafe.pilot_input) {
|
||||||
// get pilot's desired yaw rate
|
// get pilot's desired yaw rate
|
||||||
target_yaw_rate = get_pilot_desired_yaw_rate(channel_yaw->get_control_in());
|
target_yaw_rate = sub.get_pilot_desired_yaw_rate(channel_yaw->get_control_in());
|
||||||
if (!is_zero(target_yaw_rate)) {
|
if (!is_zero(target_yaw_rate)) {
|
||||||
set_auto_yaw_mode(AUTO_YAW_HOLD);
|
set_auto_yaw_mode(AUTO_YAW_HOLD);
|
||||||
}
|
}
|
||||||
|
@ -354,54 +388,54 @@ void Sub::guided_vel_control_run()
|
||||||
|
|
||||||
// set velocity to zero if no updates received for 3 seconds
|
// set velocity to zero if no updates received for 3 seconds
|
||||||
uint32_t tnow = AP_HAL::millis();
|
uint32_t tnow = AP_HAL::millis();
|
||||||
if (tnow - update_time_ms > GUIDED_POSVEL_TIMEOUT_MS && !pos_control.get_vel_desired_cms().is_zero()) {
|
if (tnow - update_time_ms > GUIDED_POSVEL_TIMEOUT_MS && !position_control->get_vel_desired_cms().is_zero()) {
|
||||||
pos_control.set_vel_desired_cms(Vector3f(0,0,0));
|
position_control->set_vel_desired_cms(Vector3f(0,0,0));
|
||||||
}
|
}
|
||||||
|
|
||||||
pos_control.stop_pos_xy_stabilisation();
|
position_control->stop_pos_xy_stabilisation();
|
||||||
// call velocity controller which includes z axis controller
|
// call velocity controller which includes z axis controller
|
||||||
pos_control.update_xy_controller();
|
position_control->update_xy_controller();
|
||||||
pos_control.update_z_controller();
|
position_control->update_z_controller();
|
||||||
|
|
||||||
float lateral_out, forward_out;
|
float lateral_out, forward_out;
|
||||||
translate_pos_control_rp(lateral_out, forward_out);
|
sub.translate_pos_control_rp(lateral_out, forward_out);
|
||||||
|
|
||||||
// Send to forward/lateral outputs
|
// Send to forward/lateral outputs
|
||||||
motors.set_lateral(lateral_out);
|
motors.set_lateral(lateral_out);
|
||||||
motors.set_forward(forward_out);
|
motors.set_forward(forward_out);
|
||||||
|
|
||||||
// call attitude controller
|
// call attitude controller
|
||||||
if (auto_yaw_mode == AUTO_YAW_HOLD) {
|
if (sub.auto_yaw_mode == AUTO_YAW_HOLD) {
|
||||||
// roll & pitch & yaw rate from pilot
|
// roll & pitch & yaw rate from pilot
|
||||||
attitude_control.input_euler_angle_roll_pitch_euler_rate_yaw(channel_roll->get_control_in(), channel_pitch->get_control_in(), target_yaw_rate);
|
attitude_control->input_euler_angle_roll_pitch_euler_rate_yaw(channel_roll->get_control_in(), channel_pitch->get_control_in(), target_yaw_rate);
|
||||||
} else {
|
} else {
|
||||||
// roll, pitch from pilot, yaw heading from auto_heading()
|
// roll, pitch from pilot, yaw heading from auto_heading()
|
||||||
attitude_control.input_euler_angle_roll_pitch_yaw(channel_roll->get_control_in(), channel_pitch->get_control_in(), get_auto_heading(), true);
|
attitude_control->input_euler_angle_roll_pitch_yaw(channel_roll->get_control_in(), channel_pitch->get_control_in(), get_auto_heading(), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// guided_posvel_control_run - runs the guided posvel controller
|
// guided_posvel_control_run - runs the guided posvel controller
|
||||||
// called from guided_run
|
// called from guided_run
|
||||||
void Sub::guided_posvel_control_run()
|
void ModeGuided::guided_posvel_control_run()
|
||||||
{
|
{
|
||||||
// if motors not enabled set throttle to zero and exit immediately
|
// if motors not enabled set throttle to zero and exit immediately
|
||||||
if (!motors.armed()) {
|
if (!motors.armed()) {
|
||||||
motors.set_desired_spool_state(AP_Motors::DesiredSpoolState::GROUND_IDLE);
|
motors.set_desired_spool_state(AP_Motors::DesiredSpoolState::GROUND_IDLE);
|
||||||
// Sub vehicles do not stabilize roll/pitch/yaw when disarmed
|
// Sub vehicles do not stabilize roll/pitch/yaw when disarmed
|
||||||
attitude_control.set_throttle_out(0,true,g.throttle_filt);
|
attitude_control->set_throttle_out(0,true,g.throttle_filt);
|
||||||
attitude_control.relax_attitude_controllers();
|
attitude_control->relax_attitude_controllers();
|
||||||
// initialise velocity controller
|
// initialise velocity controller
|
||||||
pos_control.init_z_controller();
|
position_control->init_z_controller();
|
||||||
pos_control.init_xy_controller();
|
position_control->init_xy_controller();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// process pilot's yaw input
|
// process pilot's yaw input
|
||||||
float target_yaw_rate = 0;
|
float target_yaw_rate = 0;
|
||||||
|
|
||||||
if (!failsafe.pilot_input) {
|
if (!sub.failsafe.pilot_input) {
|
||||||
// get pilot's desired yaw rate
|
// get pilot's desired yaw rate
|
||||||
target_yaw_rate = get_pilot_desired_yaw_rate(channel_yaw->get_control_in());
|
target_yaw_rate = sub.get_pilot_desired_yaw_rate(channel_yaw->get_control_in());
|
||||||
if (!is_zero(target_yaw_rate)) {
|
if (!is_zero(target_yaw_rate)) {
|
||||||
set_auto_yaw_mode(AUTO_YAW_HOLD);
|
set_auto_yaw_mode(AUTO_YAW_HOLD);
|
||||||
}
|
}
|
||||||
|
@ -417,47 +451,47 @@ void Sub::guided_posvel_control_run()
|
||||||
}
|
}
|
||||||
|
|
||||||
// advance position target using velocity target
|
// advance position target using velocity target
|
||||||
posvel_pos_target_cm += (posvel_vel_target_cms * pos_control.get_dt()).topostype();
|
posvel_pos_target_cm += (posvel_vel_target_cms * position_control->get_dt()).topostype();
|
||||||
|
|
||||||
// send position and velocity targets to position controller
|
// send position and velocity targets to position controller
|
||||||
pos_control.input_pos_vel_accel_xy(posvel_pos_target_cm.xy(), posvel_vel_target_cms.xy(), Vector2f());
|
position_control->input_pos_vel_accel_xy(posvel_pos_target_cm.xy(), posvel_vel_target_cms.xy(), Vector2f());
|
||||||
float pz = posvel_pos_target_cm.z;
|
float pz = posvel_pos_target_cm.z;
|
||||||
pos_control.input_pos_vel_accel_z(pz, posvel_vel_target_cms.z, 0);
|
position_control->input_pos_vel_accel_z(pz, posvel_vel_target_cms.z, 0);
|
||||||
posvel_pos_target_cm.z = pz;
|
posvel_pos_target_cm.z = pz;
|
||||||
|
|
||||||
// run position controller
|
// run position controller
|
||||||
pos_control.update_xy_controller();
|
position_control->update_xy_controller();
|
||||||
pos_control.update_z_controller();
|
position_control->update_z_controller();
|
||||||
|
|
||||||
float lateral_out, forward_out;
|
float lateral_out, forward_out;
|
||||||
translate_pos_control_rp(lateral_out, forward_out);
|
sub.translate_pos_control_rp(lateral_out, forward_out);
|
||||||
|
|
||||||
// Send to forward/lateral outputs
|
// Send to forward/lateral outputs
|
||||||
motors.set_lateral(lateral_out);
|
motors.set_lateral(lateral_out);
|
||||||
motors.set_forward(forward_out);
|
motors.set_forward(forward_out);
|
||||||
|
|
||||||
// call attitude controller
|
// call attitude controller
|
||||||
if (auto_yaw_mode == AUTO_YAW_HOLD) {
|
if (sub.auto_yaw_mode == AUTO_YAW_HOLD) {
|
||||||
// roll & pitch & yaw rate from pilot
|
// roll & pitch & yaw rate from pilot
|
||||||
attitude_control.input_euler_angle_roll_pitch_euler_rate_yaw(channel_roll->get_control_in(), channel_pitch->get_control_in(), target_yaw_rate);
|
attitude_control->input_euler_angle_roll_pitch_euler_rate_yaw(channel_roll->get_control_in(), channel_pitch->get_control_in(), target_yaw_rate);
|
||||||
} else {
|
} else {
|
||||||
// roll, pitch from pilot, yaw heading from auto_heading()
|
// roll, pitch from pilot, yaw heading from auto_heading()
|
||||||
attitude_control.input_euler_angle_roll_pitch_yaw(channel_roll->get_control_in(), channel_pitch->get_control_in(), get_auto_heading(), true);
|
attitude_control->input_euler_angle_roll_pitch_yaw(channel_roll->get_control_in(), channel_pitch->get_control_in(), get_auto_heading(), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// guided_angle_control_run - runs the guided angle controller
|
// guided_angle_control_run - runs the guided angle controller
|
||||||
// called from guided_run
|
// called from guided_run
|
||||||
void Sub::guided_angle_control_run()
|
void ModeGuided::guided_angle_control_run()
|
||||||
{
|
{
|
||||||
// if motors not enabled set throttle to zero and exit immediately
|
// if motors not enabled set throttle to zero and exit immediately
|
||||||
if (!motors.armed()) {
|
if (!motors.armed()) {
|
||||||
motors.set_desired_spool_state(AP_Motors::DesiredSpoolState::GROUND_IDLE);
|
motors.set_desired_spool_state(AP_Motors::DesiredSpoolState::GROUND_IDLE);
|
||||||
// Sub vehicles do not stabilize roll/pitch/yaw when disarmed
|
// Sub vehicles do not stabilize roll/pitch/yaw when disarmed
|
||||||
attitude_control.set_throttle_out(0.0f,true,g.throttle_filt);
|
attitude_control->set_throttle_out(0.0f,true,g.throttle_filt);
|
||||||
attitude_control.relax_attitude_controllers();
|
attitude_control->relax_attitude_controllers();
|
||||||
// initialise velocity controller
|
// initialise velocity controller
|
||||||
pos_control.init_z_controller();
|
position_control->init_z_controller();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -465,7 +499,7 @@ void Sub::guided_angle_control_run()
|
||||||
float roll_in = guided_angle_state.roll_cd;
|
float roll_in = guided_angle_state.roll_cd;
|
||||||
float pitch_in = guided_angle_state.pitch_cd;
|
float pitch_in = guided_angle_state.pitch_cd;
|
||||||
float total_in = norm(roll_in, pitch_in);
|
float total_in = norm(roll_in, pitch_in);
|
||||||
float angle_max = MIN(attitude_control.get_althold_lean_angle_max_cd(), aparm.angle_max);
|
float angle_max = MIN(attitude_control->get_althold_lean_angle_max_cd(), sub.aparm.angle_max);
|
||||||
if (total_in > angle_max) {
|
if (total_in > angle_max) {
|
||||||
float ratio = angle_max / total_in;
|
float ratio = angle_max / total_in;
|
||||||
roll_in *= ratio;
|
roll_in *= ratio;
|
||||||
|
@ -476,7 +510,7 @@ void Sub::guided_angle_control_run()
|
||||||
float yaw_in = wrap_180_cd(guided_angle_state.yaw_cd);
|
float yaw_in = wrap_180_cd(guided_angle_state.yaw_cd);
|
||||||
|
|
||||||
// constrain climb rate
|
// constrain climb rate
|
||||||
float climb_rate_cms = constrain_float(guided_angle_state.climb_rate_cms, -wp_nav.get_default_speed_down(), wp_nav.get_default_speed_up());
|
float climb_rate_cms = constrain_float(guided_angle_state.climb_rate_cms, -sub.wp_nav.get_default_speed_down(), sub.wp_nav.get_default_speed_up());
|
||||||
|
|
||||||
// check for timeout - set lean angles and climb rate to zero if no updates received for 3 seconds
|
// check for timeout - set lean angles and climb rate to zero if no updates received for 3 seconds
|
||||||
uint32_t tnow = AP_HAL::millis();
|
uint32_t tnow = AP_HAL::millis();
|
||||||
|
@ -490,17 +524,17 @@ void Sub::guided_angle_control_run()
|
||||||
motors.set_desired_spool_state(AP_Motors::DesiredSpoolState::THROTTLE_UNLIMITED);
|
motors.set_desired_spool_state(AP_Motors::DesiredSpoolState::THROTTLE_UNLIMITED);
|
||||||
|
|
||||||
// call attitude controller
|
// call attitude controller
|
||||||
attitude_control.input_euler_angle_roll_pitch_yaw(roll_in, pitch_in, yaw_in, true);
|
attitude_control->input_euler_angle_roll_pitch_yaw(roll_in, pitch_in, yaw_in, true);
|
||||||
|
|
||||||
// call position controller
|
// call position controller
|
||||||
pos_control.set_pos_target_z_from_climb_rate_cm(climb_rate_cms);
|
position_control->set_pos_target_z_from_climb_rate_cm(climb_rate_cms);
|
||||||
pos_control.update_z_controller();
|
position_control->update_z_controller();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Guided Limit code
|
// Guided Limit code
|
||||||
|
|
||||||
// guided_limit_clear - clear/turn off guided limits
|
// guided_limit_clear - clear/turn off guided limits
|
||||||
void Sub::guided_limit_clear()
|
void ModeGuided::guided_limit_clear()
|
||||||
{
|
{
|
||||||
guided_limit.timeout_ms = 0;
|
guided_limit.timeout_ms = 0;
|
||||||
guided_limit.alt_min_cm = 0.0f;
|
guided_limit.alt_min_cm = 0.0f;
|
||||||
|
@ -508,8 +542,97 @@ void Sub::guided_limit_clear()
|
||||||
guided_limit.horiz_max_cm = 0.0f;
|
guided_limit.horiz_max_cm = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// set_auto_yaw_mode - sets the yaw mode for auto
|
||||||
|
void ModeGuided::set_auto_yaw_mode(autopilot_yaw_mode yaw_mode)
|
||||||
|
{
|
||||||
|
// return immediately if no change
|
||||||
|
if (sub.auto_yaw_mode == yaw_mode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sub.auto_yaw_mode = yaw_mode;
|
||||||
|
|
||||||
|
// perform initialisation
|
||||||
|
switch (sub.auto_yaw_mode) {
|
||||||
|
|
||||||
|
case AUTO_YAW_LOOK_AT_NEXT_WP:
|
||||||
|
// wpnav will initialise heading when wpnav's set_destination method is called
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AUTO_YAW_ROI:
|
||||||
|
// point towards a location held in yaw_look_at_WP
|
||||||
|
sub.yaw_look_at_WP_bearing = ahrs.yaw_sensor;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AUTO_YAW_LOOK_AT_HEADING:
|
||||||
|
// keep heading pointing in the direction held in yaw_look_at_heading
|
||||||
|
// caller should set the yaw_look_at_heading
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AUTO_YAW_LOOK_AHEAD:
|
||||||
|
// Commanded Yaw to automatically look ahead.
|
||||||
|
sub.yaw_look_ahead_bearing = ahrs.yaw_sensor;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AUTO_YAW_RESETTOARMEDYAW:
|
||||||
|
// initial_armed_bearing will be set during arming so no init required
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// get_auto_heading - returns target heading depending upon auto_yaw_mode
|
||||||
|
// 100hz update rate
|
||||||
|
float ModeGuided::get_auto_heading()
|
||||||
|
{
|
||||||
|
switch (sub.auto_yaw_mode) {
|
||||||
|
|
||||||
|
case AUTO_YAW_ROI:
|
||||||
|
// point towards a location held in roi_WP
|
||||||
|
return sub.get_roi_yaw();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AUTO_YAW_LOOK_AT_HEADING:
|
||||||
|
// keep heading pointing in the direction held in yaw_look_at_heading with no pilot input allowed
|
||||||
|
return sub.yaw_look_at_heading;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AUTO_YAW_LOOK_AHEAD:
|
||||||
|
// Commanded Yaw to automatically look ahead.
|
||||||
|
return sub.get_look_ahead_yaw();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AUTO_YAW_RESETTOARMEDYAW:
|
||||||
|
// changes yaw to be same as when quad was armed
|
||||||
|
return sub.initial_armed_bearing;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AUTO_YAW_CORRECT_XTRACK: {
|
||||||
|
// TODO return current yaw if not in appropriate mode
|
||||||
|
// Bearing of current track (centidegrees)
|
||||||
|
float track_bearing = get_bearing_cd(sub.wp_nav.get_wp_origin().xy(), sub.wp_nav.get_wp_destination().xy());
|
||||||
|
|
||||||
|
// Bearing from current position towards intermediate position target (centidegrees)
|
||||||
|
const Vector2f target_vel_xy{position_control->get_vel_target_cms().x, position_control->get_vel_target_cms().y};
|
||||||
|
float angle_error = 0.0f;
|
||||||
|
if (target_vel_xy.length() >= position_control->get_max_speed_xy_cms() * 0.1f) {
|
||||||
|
const float desired_angle_cd = degrees(target_vel_xy.angle()) * 100.0f;
|
||||||
|
angle_error = wrap_180_cd(desired_angle_cd - track_bearing);
|
||||||
|
}
|
||||||
|
float angle_limited = constrain_float(angle_error, -g.xtrack_angle_limit * 100.0f, g.xtrack_angle_limit * 100.0f);
|
||||||
|
return wrap_360_cd(track_bearing + angle_limited);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AUTO_YAW_LOOK_AT_NEXT_WP:
|
||||||
|
default:
|
||||||
|
// point towards next waypoint.
|
||||||
|
// we don't use wp_bearing because we don't want the vehicle to turn too much during flight
|
||||||
|
return sub.wp_nav.get_yaw();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
// guided_limit_set - set guided timeout and movement limits
|
// guided_limit_set - set guided timeout and movement limits
|
||||||
void Sub::guided_limit_set(uint32_t timeout_ms, float alt_min_cm, float alt_max_cm, float horiz_max_cm)
|
void ModeGuided::guided_limit_set(uint32_t timeout_ms, float alt_min_cm, float alt_max_cm, float horiz_max_cm)
|
||||||
{
|
{
|
||||||
guided_limit.timeout_ms = timeout_ms;
|
guided_limit.timeout_ms = timeout_ms;
|
||||||
guided_limit.alt_min_cm = alt_min_cm;
|
guided_limit.alt_min_cm = alt_min_cm;
|
||||||
|
@ -519,7 +642,7 @@ void Sub::guided_limit_set(uint32_t timeout_ms, float alt_min_cm, float alt_max_
|
||||||
|
|
||||||
// guided_limit_init_time_and_pos - initialise guided start time and position as reference for limit checking
|
// guided_limit_init_time_and_pos - initialise guided start time and position as reference for limit checking
|
||||||
// only called from AUTO mode's auto_nav_guided_start function
|
// only called from AUTO mode's auto_nav_guided_start function
|
||||||
void Sub::guided_limit_init_time_and_pos()
|
void ModeGuided::guided_limit_init_time_and_pos()
|
||||||
{
|
{
|
||||||
// initialise start time
|
// initialise start time
|
||||||
guided_limit.start_time = AP_HAL::millis();
|
guided_limit.start_time = AP_HAL::millis();
|
||||||
|
@ -530,7 +653,7 @@ void Sub::guided_limit_init_time_and_pos()
|
||||||
|
|
||||||
// guided_limit_check - returns true if guided mode has breached a limit
|
// guided_limit_check - returns true if guided mode has breached a limit
|
||||||
// used when guided is invoked from the NAV_GUIDED_ENABLE mission command
|
// used when guided is invoked from the NAV_GUIDED_ENABLE mission command
|
||||||
bool Sub::guided_limit_check()
|
bool ModeGuided::guided_limit_check()
|
||||||
{
|
{
|
||||||
// check if we have passed the timeout
|
// check if we have passed the timeout
|
||||||
if ((guided_limit.timeout_ms > 0) && (AP_HAL::millis() - guided_limit.start_time >= guided_limit.timeout_ms)) {
|
if ((guided_limit.timeout_ms > 0) && (AP_HAL::millis() - guided_limit.start_time >= guided_limit.timeout_ms)) {
|
||||||
|
|
|
@ -1,36 +1,35 @@
|
||||||
#include "Sub.h"
|
#include "Sub.h"
|
||||||
|
|
||||||
// manual_init - initialise manual controller
|
|
||||||
bool Sub::manual_init()
|
bool ModeManual::init(bool ignore_checks) {
|
||||||
{
|
|
||||||
// set target altitude to zero for reporting
|
// set target altitude to zero for reporting
|
||||||
pos_control.set_pos_target_z_cm(0);
|
position_control->set_pos_target_z_cm(0);
|
||||||
|
|
||||||
// attitude hold inputs become thrust inputs in manual mode
|
// attitude hold inputs become thrust inputs in manual mode
|
||||||
// set to neutral to prevent chaotic behavior (esp. roll/pitch)
|
// set to neutral to prevent chaotic behavior (esp. roll/pitch)
|
||||||
set_neutral_controls();
|
sub.set_neutral_controls();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// manual_run - runs the manual (passthrough) controller
|
// manual_run - runs the manual (passthrough) controller
|
||||||
// should be called at 100hz or more
|
// should be called at 100hz or more
|
||||||
void Sub::manual_run()
|
void ModeManual::run()
|
||||||
{
|
{
|
||||||
// if not armed set throttle to zero and exit immediately
|
// if not armed set throttle to zero and exit immediately
|
||||||
if (!motors.armed()) {
|
if (!sub.motors.armed()) {
|
||||||
motors.set_desired_spool_state(AP_Motors::DesiredSpoolState::GROUND_IDLE);
|
sub.motors.set_desired_spool_state(AP_Motors::DesiredSpoolState::GROUND_IDLE);
|
||||||
attitude_control.set_throttle_out(0,true,g.throttle_filt);
|
attitude_control->set_throttle_out(0,true,g.throttle_filt);
|
||||||
attitude_control.relax_attitude_controllers();
|
attitude_control->relax_attitude_controllers();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
motors.set_desired_spool_state(AP_Motors::DesiredSpoolState::THROTTLE_UNLIMITED);
|
sub.motors.set_desired_spool_state(AP_Motors::DesiredSpoolState::THROTTLE_UNLIMITED);
|
||||||
|
|
||||||
motors.set_roll(channel_roll->norm_input());
|
sub.motors.set_roll(channel_roll->norm_input());
|
||||||
motors.set_pitch(channel_pitch->norm_input());
|
sub.motors.set_pitch(channel_pitch->norm_input());
|
||||||
motors.set_yaw(channel_yaw->norm_input() * g.acro_yaw_p / ACRO_YAW_P);
|
sub.motors.set_yaw(channel_yaw->norm_input() * g.acro_yaw_p / ACRO_YAW_P);
|
||||||
motors.set_throttle(channel_throttle->norm_input());
|
sub.motors.set_throttle(channel_throttle->norm_input());
|
||||||
motors.set_forward(channel_forward->norm_input());
|
sub.motors.set_forward(channel_forward->norm_input());
|
||||||
motors.set_lateral(channel_lateral->norm_input());
|
sub.motors.set_lateral(channel_lateral->norm_input());
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ namespace {
|
||||||
static int16_t current_direction;
|
static int16_t current_direction;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Sub::motordetect_init()
|
bool ModeMotordetect::init(bool ignore_checks)
|
||||||
{
|
{
|
||||||
current_motor = 0;
|
current_motor = 0;
|
||||||
md_state = STANDBY;
|
md_state = STANDBY;
|
||||||
|
@ -53,7 +53,7 @@ bool Sub::motordetect_init()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sub::motordetect_run()
|
void ModeMotordetect::run()
|
||||||
{
|
{
|
||||||
// if not armed set throttle to zero and exit immediately
|
// if not armed set throttle to zero and exit immediately
|
||||||
if (!motors.armed()) {
|
if (!motors.armed()) {
|
||||||
|
@ -167,8 +167,8 @@ void Sub::motordetect_run()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DONE:
|
case DONE:
|
||||||
control_mode = prev_control_mode;
|
set_mode(sub.prev_control_mode, ModeReason::MISSION_END);
|
||||||
arming.disarm(AP_Arming::Method::MOTORDETECTDONE);
|
sub.arming.disarm(AP_Arming::Method::MOTORDETECTDONE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,47 +7,47 @@
|
||||||
#if POSHOLD_ENABLED == ENABLED
|
#if POSHOLD_ENABLED == ENABLED
|
||||||
|
|
||||||
// poshold_init - initialise PosHold controller
|
// poshold_init - initialise PosHold controller
|
||||||
bool Sub::poshold_init()
|
bool ModePoshold::init(bool ignore_checks)
|
||||||
{
|
{
|
||||||
// fail to initialise PosHold mode if no GPS lock
|
// fail to initialise PosHold mode if no GPS lock
|
||||||
if (!position_ok()) {
|
if (!sub.position_ok()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialize vertical speeds and acceleration
|
// initialize vertical speeds and acceleration
|
||||||
pos_control.set_max_speed_accel_xy(wp_nav.get_default_speed_xy(), wp_nav.get_wp_acceleration());
|
position_control->set_max_speed_accel_xy(sub.wp_nav.get_default_speed_xy(), sub.wp_nav.get_wp_acceleration());
|
||||||
pos_control.set_correction_speed_accel_xy(wp_nav.get_default_speed_xy(), wp_nav.get_wp_acceleration());
|
position_control->set_correction_speed_accel_xy(sub.wp_nav.get_default_speed_xy(), sub.wp_nav.get_wp_acceleration());
|
||||||
pos_control.set_max_speed_accel_z(-get_pilot_speed_dn(), g.pilot_speed_up, g.pilot_accel_z);
|
position_control->set_max_speed_accel_z(-sub.get_pilot_speed_dn(), g.pilot_speed_up, g.pilot_accel_z);
|
||||||
pos_control.set_correction_speed_accel_z(-get_pilot_speed_dn(), g.pilot_speed_up, g.pilot_accel_z);
|
position_control->set_correction_speed_accel_z(-sub.get_pilot_speed_dn(), g.pilot_speed_up, g.pilot_accel_z);
|
||||||
|
|
||||||
// initialise position and desired velocity
|
// initialise position and desired velocity
|
||||||
pos_control.init_xy_controller_stopping_point();
|
position_control->init_xy_controller_stopping_point();
|
||||||
pos_control.init_z_controller();
|
position_control->init_z_controller();
|
||||||
|
|
||||||
// Stop all thrusters
|
// Stop all thrusters
|
||||||
attitude_control.set_throttle_out(0.5f ,true, g.throttle_filt);
|
attitude_control->set_throttle_out(0.5f ,true, g.throttle_filt);
|
||||||
attitude_control.relax_attitude_controllers();
|
attitude_control->relax_attitude_controllers();
|
||||||
pos_control.relax_z_controller(0.5f);
|
position_control->relax_z_controller(0.5f);
|
||||||
|
|
||||||
last_pilot_heading = ahrs.yaw_sensor;
|
sub.last_pilot_heading = ahrs.yaw_sensor;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// poshold_run - runs the PosHold controller
|
// poshold_run - runs the PosHold controller
|
||||||
// should be called at 100hz or more
|
// should be called at 100hz or more
|
||||||
void Sub::poshold_run()
|
void ModePoshold::run()
|
||||||
{
|
{
|
||||||
uint32_t tnow = AP_HAL::millis();
|
uint32_t tnow = AP_HAL::millis();
|
||||||
// When unarmed, disable motors and stabilization
|
// When unarmed, disable motors and stabilization
|
||||||
if (!motors.armed()) {
|
if (!motors.armed()) {
|
||||||
motors.set_desired_spool_state(AP_Motors::DesiredSpoolState::GROUND_IDLE);
|
motors.set_desired_spool_state(AP_Motors::DesiredSpoolState::GROUND_IDLE);
|
||||||
// Sub vehicles do not stabilize roll/pitch/yaw when not auto-armed (i.e. on the ground, pilot has never raised throttle)
|
// Sub vehicles do not stabilize roll/pitch/yaw when not auto-armed (i.e. on the ground, pilot has never raised throttle)
|
||||||
attitude_control.set_throttle_out(0.5f ,true, g.throttle_filt);
|
attitude_control->set_throttle_out(0.5f ,true, g.throttle_filt);
|
||||||
attitude_control.relax_attitude_controllers();
|
attitude_control->relax_attitude_controllers();
|
||||||
pos_control.init_xy_controller_stopping_point();
|
position_control->init_xy_controller_stopping_point();
|
||||||
pos_control.relax_z_controller(0.5f);
|
position_control->relax_z_controller(0.5f);
|
||||||
last_pilot_heading = ahrs.yaw_sensor;
|
sub.last_pilot_heading = ahrs.yaw_sensor;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,15 +62,15 @@ void Sub::poshold_run()
|
||||||
float lateral_out = 0;
|
float lateral_out = 0;
|
||||||
float forward_out = 0;
|
float forward_out = 0;
|
||||||
|
|
||||||
if (position_ok()) {
|
if (sub.position_ok()) {
|
||||||
// Allow pilot to reposition the sub
|
// Allow pilot to reposition the sub
|
||||||
if (fabsf(pilot_lateral) > 0.1 || fabsf(pilot_forward) > 0.1) {
|
if (fabsf(pilot_lateral) > 0.1 || fabsf(pilot_forward) > 0.1) {
|
||||||
pos_control.init_xy_controller_stopping_point();
|
position_control->init_xy_controller_stopping_point();
|
||||||
}
|
}
|
||||||
translate_pos_control_rp(lateral_out, forward_out);
|
sub.translate_pos_control_rp(lateral_out, forward_out);
|
||||||
pos_control.update_xy_controller();
|
position_control->update_xy_controller();
|
||||||
} else {
|
} else {
|
||||||
pos_control.init_xy_controller_stopping_point();
|
position_control->init_xy_controller_stopping_point();
|
||||||
}
|
}
|
||||||
motors.set_forward(forward_out + pilot_forward);
|
motors.set_forward(forward_out + pilot_forward);
|
||||||
motors.set_lateral(lateral_out + pilot_lateral);
|
motors.set_lateral(lateral_out + pilot_lateral);
|
||||||
|
@ -78,32 +78,32 @@ void Sub::poshold_run()
|
||||||
// Update attitude //
|
// Update attitude //
|
||||||
|
|
||||||
// get pilot's desired yaw rate
|
// get pilot's desired yaw rate
|
||||||
float target_yaw_rate = get_pilot_desired_yaw_rate(channel_yaw->get_control_in());
|
float target_yaw_rate = sub.get_pilot_desired_yaw_rate(channel_yaw->get_control_in());
|
||||||
|
|
||||||
// convert pilot input to lean angles
|
// convert pilot input to lean angles
|
||||||
// To-Do: convert get_pilot_desired_lean_angles to return angles as floats
|
// To-Do: convert get_pilot_desired_lean_angles to return angles as floats
|
||||||
float target_roll, target_pitch;
|
float target_roll, target_pitch;
|
||||||
get_pilot_desired_lean_angles(channel_roll->get_control_in(), channel_pitch->get_control_in(), target_roll, target_pitch, aparm.angle_max);
|
sub.get_pilot_desired_lean_angles(channel_roll->get_control_in(), channel_pitch->get_control_in(), target_roll, target_pitch, sub.aparm.angle_max);
|
||||||
|
|
||||||
// update attitude controller targets
|
// update attitude controller targets
|
||||||
if (!is_zero(target_yaw_rate)) { // call attitude controller with rate yaw determined by pilot input
|
if (!is_zero(target_yaw_rate)) { // call attitude controller with rate yaw determined by pilot input
|
||||||
attitude_control.input_euler_angle_roll_pitch_euler_rate_yaw(target_roll, target_pitch, target_yaw_rate);
|
attitude_control->input_euler_angle_roll_pitch_euler_rate_yaw(target_roll, target_pitch, target_yaw_rate);
|
||||||
last_pilot_heading = ahrs.yaw_sensor;
|
sub.last_pilot_heading = ahrs.yaw_sensor;
|
||||||
last_pilot_yaw_input_ms = tnow; // time when pilot last changed heading
|
sub.last_pilot_yaw_input_ms = tnow; // time when pilot last changed heading
|
||||||
|
|
||||||
} else { // hold current heading
|
} else { // hold current heading
|
||||||
|
|
||||||
// this check is required to prevent bounce back after very fast yaw maneuvers
|
// this check is required to prevent bounce back after very fast yaw maneuvers
|
||||||
// the inertia of the vehicle causes the heading to move slightly past the point when pilot input actually stopped
|
// the inertia of the vehicle causes the heading to move slightly past the point when pilot input actually stopped
|
||||||
if (tnow < last_pilot_yaw_input_ms + 250) { // give 250ms to slow down, then set target heading
|
if (tnow < sub.last_pilot_yaw_input_ms + 250) { // give 250ms to slow down, then set target heading
|
||||||
target_yaw_rate = 0; // Stop rotation on yaw axis
|
target_yaw_rate = 0; // Stop rotation on yaw axis
|
||||||
|
|
||||||
// call attitude controller with target yaw rate = 0 to decelerate on yaw axis
|
// call attitude controller with target yaw rate = 0 to decelerate on yaw axis
|
||||||
attitude_control.input_euler_angle_roll_pitch_euler_rate_yaw(target_roll, target_pitch, target_yaw_rate);
|
attitude_control->input_euler_angle_roll_pitch_euler_rate_yaw(target_roll, target_pitch, target_yaw_rate);
|
||||||
last_pilot_heading = ahrs.yaw_sensor; // update heading to hold
|
sub.last_pilot_heading = ahrs.yaw_sensor; // update heading to hold
|
||||||
|
|
||||||
} else { // call attitude controller holding absolute absolute bearing
|
} else { // call attitude controller holding absolute absolute bearing
|
||||||
attitude_control.input_euler_angle_roll_pitch_yaw(target_roll, target_pitch, last_pilot_heading, true);
|
attitude_control->input_euler_angle_roll_pitch_yaw(target_roll, target_pitch, sub.last_pilot_heading, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,18 +1,16 @@
|
||||||
#include "Sub.h"
|
#include "Sub.h"
|
||||||
|
|
||||||
// stabilize_init - initialise stabilize controller
|
|
||||||
bool Sub::stabilize_init()
|
|
||||||
{
|
|
||||||
// set target altitude to zero for reporting
|
|
||||||
pos_control.set_pos_target_z_cm(0);
|
|
||||||
last_pilot_heading = ahrs.yaw_sensor;
|
|
||||||
|
|
||||||
|
bool ModeStabilize::init(bool ignore_checks) {
|
||||||
|
// set target altitude to zero for reporting
|
||||||
|
position_control->set_pos_target_z_cm(0);
|
||||||
|
sub.last_pilot_heading = ahrs.yaw_sensor;
|
||||||
|
|
||||||
|
return true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// stabilize_run - runs the main stabilize controller
|
void ModeStabilize::run()
|
||||||
// should be called at 100hz or more
|
|
||||||
void Sub::stabilize_run()
|
|
||||||
{
|
{
|
||||||
uint32_t tnow = AP_HAL::millis();
|
uint32_t tnow = AP_HAL::millis();
|
||||||
float target_roll, target_pitch;
|
float target_roll, target_pitch;
|
||||||
|
@ -20,47 +18,48 @@ void Sub::stabilize_run()
|
||||||
// if not armed set throttle to zero and exit immediately
|
// if not armed set throttle to zero and exit immediately
|
||||||
if (!motors.armed()) {
|
if (!motors.armed()) {
|
||||||
motors.set_desired_spool_state(AP_Motors::DesiredSpoolState::GROUND_IDLE);
|
motors.set_desired_spool_state(AP_Motors::DesiredSpoolState::GROUND_IDLE);
|
||||||
attitude_control.set_throttle_out(0,true,g.throttle_filt);
|
attitude_control->set_throttle_out(0,true,g.throttle_filt);
|
||||||
attitude_control.relax_attitude_controllers();
|
attitude_control->relax_attitude_controllers();
|
||||||
last_pilot_heading = ahrs.yaw_sensor;
|
sub.last_pilot_heading = ahrs.yaw_sensor;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
motors.set_desired_spool_state(AP_Motors::DesiredSpoolState::THROTTLE_UNLIMITED);
|
motors.set_desired_spool_state(AP_Motors::DesiredSpoolState::THROTTLE_UNLIMITED);
|
||||||
|
|
||||||
// convert pilot input to lean angles
|
// convert pilot input to lean angles
|
||||||
// To-Do: convert get_pilot_desired_lean_angles to return angles as floats
|
// To-Do: convert sub.get_pilot_desired_lean_angles to return angles as floats
|
||||||
get_pilot_desired_lean_angles(channel_roll->get_control_in(), channel_pitch->get_control_in(), target_roll, target_pitch, aparm.angle_max);
|
// TODO2: move into mode.h
|
||||||
|
sub.get_pilot_desired_lean_angles(channel_roll->get_control_in(), channel_pitch->get_control_in(), target_roll, target_pitch, sub.aparm.angle_max);
|
||||||
|
|
||||||
// get pilot's desired yaw rate
|
// get pilot's desired yaw rate
|
||||||
float target_yaw_rate = get_pilot_desired_yaw_rate(channel_yaw->get_control_in());
|
float target_yaw_rate = sub.get_pilot_desired_yaw_rate(channel_yaw->get_control_in());
|
||||||
|
|
||||||
// call attitude controller
|
// call attitude controller
|
||||||
// update attitude controller targets
|
// update attitude controller targets
|
||||||
|
|
||||||
if (!is_zero(target_yaw_rate)) { // call attitude controller with rate yaw determined by pilot input
|
if (!is_zero(target_yaw_rate)) { // call attitude controller with rate yaw determined by pilot input
|
||||||
attitude_control.input_euler_angle_roll_pitch_euler_rate_yaw(target_roll, target_pitch, target_yaw_rate);
|
attitude_control->input_euler_angle_roll_pitch_euler_rate_yaw(target_roll, target_pitch, target_yaw_rate);
|
||||||
last_pilot_heading = ahrs.yaw_sensor;
|
sub.last_pilot_heading = ahrs.yaw_sensor;
|
||||||
last_pilot_yaw_input_ms = tnow; // time when pilot last changed heading
|
sub.last_pilot_yaw_input_ms = tnow; // time when pilot last changed heading
|
||||||
|
|
||||||
} else { // hold current heading
|
} else { // hold current heading
|
||||||
|
|
||||||
// this check is required to prevent bounce back after very fast yaw maneuvers
|
// this check is required to prevent bounce back after very fast yaw maneuvers
|
||||||
// the inertia of the vehicle causes the heading to move slightly past the point when pilot input actually stopped
|
// the inertia of the vehicle causes the heading to move slightly past the point when pilot input actually stopped
|
||||||
if (tnow < last_pilot_yaw_input_ms + 250) { // give 250ms to slow down, then set target heading
|
if (tnow < sub.last_pilot_yaw_input_ms + 250) { // give 250ms to slow down, then set target heading
|
||||||
target_yaw_rate = 0; // Stop rotation on yaw axis
|
target_yaw_rate = 0; // Stop rotation on yaw axis
|
||||||
|
|
||||||
// call attitude controller with target yaw rate = 0 to decelerate on yaw axis
|
// call attitude controller with target yaw rate = 0 to decelerate on yaw axis
|
||||||
attitude_control.input_euler_angle_roll_pitch_euler_rate_yaw(target_roll, target_pitch, target_yaw_rate);
|
attitude_control->input_euler_angle_roll_pitch_euler_rate_yaw(target_roll, target_pitch, target_yaw_rate);
|
||||||
last_pilot_heading = ahrs.yaw_sensor; // update heading to hold
|
sub.last_pilot_heading = ahrs.yaw_sensor; // update heading to hold
|
||||||
|
|
||||||
} else { // call attitude controller holding absolute absolute bearing
|
} else { // call attitude controller holding absolute absolute bearing
|
||||||
attitude_control.input_euler_angle_roll_pitch_yaw(target_roll, target_pitch, last_pilot_heading, true);
|
attitude_control->input_euler_angle_roll_pitch_yaw(target_roll, target_pitch, sub.last_pilot_heading, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// output pilot's throttle
|
// output pilot's throttle
|
||||||
attitude_control.set_throttle_out(channel_throttle->norm_input(), false, g.throttle_filt);
|
attitude_control->set_throttle_out(channel_throttle->norm_input(), false, g.throttle_filt);
|
||||||
|
|
||||||
//control_in is range -1000-1000
|
//control_in is range -1000-1000
|
||||||
//radio_in is raw pwm value
|
//radio_in is raw pwm value
|
||||||
|
|
|
@ -1,24 +1,24 @@
|
||||||
#include "Sub.h"
|
#include "Sub.h"
|
||||||
|
|
||||||
|
|
||||||
bool Sub::surface_init()
|
bool ModeSurface::init(bool ignore_checks)
|
||||||
{
|
{
|
||||||
if(!control_check_barometer()) {
|
if(!sub.control_check_barometer()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialize vertical speeds and acceleration
|
// initialize vertical speeds and acceleration
|
||||||
pos_control.set_max_speed_accel_z(-get_pilot_speed_dn(), g.pilot_speed_up, g.pilot_accel_z);
|
position_control->set_max_speed_accel_z(-sub.get_pilot_speed_dn(), g.pilot_speed_up, g.pilot_accel_z);
|
||||||
pos_control.set_correction_speed_accel_z(-get_pilot_speed_dn(), g.pilot_speed_up, g.pilot_accel_z);
|
position_control->set_correction_speed_accel_z(-sub.get_pilot_speed_dn(), g.pilot_speed_up, g.pilot_accel_z);
|
||||||
|
|
||||||
// initialise position and desired velocity
|
// initialise position and desired velocity
|
||||||
pos_control.init_z_controller();
|
position_control->init_z_controller();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sub::surface_run()
|
void ModeSurface::run()
|
||||||
{
|
{
|
||||||
float target_roll, target_pitch;
|
float target_roll, target_pitch;
|
||||||
|
|
||||||
|
@ -26,36 +26,36 @@ void Sub::surface_run()
|
||||||
if (!motors.armed()) {
|
if (!motors.armed()) {
|
||||||
motors.output_min();
|
motors.output_min();
|
||||||
motors.set_desired_spool_state(AP_Motors::DesiredSpoolState::GROUND_IDLE);
|
motors.set_desired_spool_state(AP_Motors::DesiredSpoolState::GROUND_IDLE);
|
||||||
attitude_control.set_throttle_out(0,true,g.throttle_filt);
|
attitude_control->set_throttle_out(0,true,g.throttle_filt);
|
||||||
attitude_control.relax_attitude_controllers();
|
attitude_control->relax_attitude_controllers();
|
||||||
pos_control.init_z_controller();
|
position_control->init_z_controller();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Already at surface, hold depth at surface
|
// Already at surface, hold depth at surface
|
||||||
if (ap.at_surface) {
|
if (sub.ap.at_surface) {
|
||||||
set_mode(ALT_HOLD, ModeReason::SURFACE_COMPLETE);
|
set_mode(Mode::Number::ALT_HOLD, ModeReason::SURFACE_COMPLETE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert pilot input to lean angles
|
// convert pilot input to lean angles
|
||||||
// To-Do: convert get_pilot_desired_lean_angles to return angles as floats
|
// To-Do: convert sub.get_pilot_desired_lean_angles to return angles as floats
|
||||||
get_pilot_desired_lean_angles(channel_roll->get_control_in(), channel_pitch->get_control_in(), target_roll, target_pitch, aparm.angle_max);
|
sub.get_pilot_desired_lean_angles(channel_roll->get_control_in(), channel_pitch->get_control_in(), target_roll, target_pitch, sub.aparm.angle_max);
|
||||||
|
|
||||||
// get pilot's desired yaw rate
|
// get pilot's desired yaw rate
|
||||||
float target_yaw_rate = get_pilot_desired_yaw_rate(channel_yaw->get_control_in());
|
float target_yaw_rate = sub.get_pilot_desired_yaw_rate(channel_yaw->get_control_in());
|
||||||
|
|
||||||
// call attitude controller
|
// call attitude controller
|
||||||
attitude_control.input_euler_angle_roll_pitch_euler_rate_yaw(target_roll, target_pitch, target_yaw_rate);
|
attitude_control->input_euler_angle_roll_pitch_euler_rate_yaw(target_roll, target_pitch, target_yaw_rate);
|
||||||
|
|
||||||
// set target climb rate
|
// set target climb rate
|
||||||
float cmb_rate = constrain_float(fabsf(wp_nav.get_default_speed_up()), 1, pos_control.get_max_speed_up_cms());
|
float cmb_rate = constrain_float(fabsf(sub.wp_nav.get_default_speed_up()), 1, position_control->get_max_speed_up_cms());
|
||||||
|
|
||||||
// record desired climb rate for logging
|
// record desired climb rate for logging
|
||||||
desired_climb_rate = cmb_rate;
|
sub.desired_climb_rate = cmb_rate;
|
||||||
|
|
||||||
// update altitude target and call position controller
|
// update altitude target and call position controller
|
||||||
pos_control.set_pos_target_z_from_climb_rate_cm(cmb_rate);
|
position_control->set_pos_target_z_from_climb_rate_cm(cmb_rate);
|
||||||
pos_control.update_z_controller();
|
position_control->update_z_controller();
|
||||||
|
|
||||||
// pilot has control for repositioning
|
// pilot has control for repositioning
|
||||||
motors.set_forward(channel_forward->norm_input());
|
motors.set_forward(channel_forward->norm_input());
|
||||||
|
|
|
@ -29,20 +29,6 @@ enum autopilot_yaw_mode {
|
||||||
AUTO_YAW_CORRECT_XTRACK = 6 // steer the sub in order to correct for crosstrack error during line following
|
AUTO_YAW_CORRECT_XTRACK = 6 // steer the sub in order to correct for crosstrack error during line following
|
||||||
};
|
};
|
||||||
|
|
||||||
// Auto Pilot Modes enumeration
|
|
||||||
enum control_mode_t : uint8_t {
|
|
||||||
STABILIZE = 0, // manual angle with manual depth/throttle
|
|
||||||
ACRO = 1, // manual body-frame angular rate with manual depth/throttle
|
|
||||||
ALT_HOLD = 2, // manual angle with automatic depth/throttle
|
|
||||||
AUTO = 3, // fully automatic waypoint control using mission commands
|
|
||||||
GUIDED = 4, // fully automatic fly to coordinate or fly at velocity/direction using GCS immediate commands
|
|
||||||
CIRCLE = 7, // automatic circular flight with automatic throttle
|
|
||||||
SURFACE = 9, // automatically return to surface, pilot maintains horizontal control
|
|
||||||
POSHOLD = 16, // automatic position hold with manual override, with automatic throttle
|
|
||||||
MANUAL = 19, // Pass-through input with no stabilization
|
|
||||||
MOTOR_DETECT = 20 // Automatically detect motors orientation
|
|
||||||
};
|
|
||||||
|
|
||||||
// Acro Trainer types
|
// Acro Trainer types
|
||||||
#define ACRO_TRAINER_DISABLED 0
|
#define ACRO_TRAINER_DISABLED 0
|
||||||
#define ACRO_TRAINER_LEVELING 1
|
#define ACRO_TRAINER_LEVELING 1
|
||||||
|
@ -55,32 +41,7 @@ enum control_mode_t : uint8_t {
|
||||||
#define WP_YAW_BEHAVIOR_LOOK_AHEAD 3 // auto pilot will look ahead during missions and rtl (primarily meant for traditional helicotpers)
|
#define WP_YAW_BEHAVIOR_LOOK_AHEAD 3 // auto pilot will look ahead during missions and rtl (primarily meant for traditional helicotpers)
|
||||||
#define WP_YAW_BEHAVIOR_CORRECT_XTRACK 4 // point towards intermediate position target during line following
|
#define WP_YAW_BEHAVIOR_CORRECT_XTRACK 4 // point towards intermediate position target during line following
|
||||||
|
|
||||||
// Auto modes
|
|
||||||
enum AutoMode {
|
|
||||||
Auto_WP,
|
|
||||||
Auto_CircleMoveToEdge,
|
|
||||||
Auto_Circle,
|
|
||||||
Auto_NavGuided,
|
|
||||||
Auto_Loiter,
|
|
||||||
Auto_TerrainRecover
|
|
||||||
};
|
|
||||||
|
|
||||||
// Guided modes
|
|
||||||
enum GuidedMode {
|
|
||||||
Guided_WP,
|
|
||||||
Guided_Velocity,
|
|
||||||
Guided_PosVel,
|
|
||||||
Guided_Angle,
|
|
||||||
};
|
|
||||||
|
|
||||||
// RTL states
|
|
||||||
enum RTLState {
|
|
||||||
RTL_InitialClimb,
|
|
||||||
RTL_ReturnHome,
|
|
||||||
RTL_LoiterAtHome,
|
|
||||||
RTL_FinalDescent,
|
|
||||||
RTL_Land
|
|
||||||
};
|
|
||||||
|
|
||||||
// Logging parameters - only 32 messages are available to the vehicle here.
|
// Logging parameters - only 32 messages are available to the vehicle here.
|
||||||
enum LoggingParameters {
|
enum LoggingParameters {
|
||||||
|
|
|
@ -88,9 +88,9 @@ void Sub::failsafe_sensors_check()
|
||||||
gcs().send_text(MAV_SEVERITY_CRITICAL, "Depth sensor error!");
|
gcs().send_text(MAV_SEVERITY_CRITICAL, "Depth sensor error!");
|
||||||
AP::logger().Write_Error(LogErrorSubsystem::FAILSAFE_SENSORS, LogErrorCode::BAD_DEPTH);
|
AP::logger().Write_Error(LogErrorSubsystem::FAILSAFE_SENSORS, LogErrorCode::BAD_DEPTH);
|
||||||
|
|
||||||
if (control_mode == ALT_HOLD || control_mode == SURFACE || mode_requires_GPS(control_mode)) {
|
if (control_mode == Mode::Number::ALT_HOLD || control_mode == Mode::Number::SURFACE || sub.flightmode->requires_GPS()) {
|
||||||
// This should always succeed
|
// This should always succeed
|
||||||
if (!set_mode(MANUAL, ModeReason::BAD_DEPTH)) {
|
if (!set_mode(Mode::Number::MANUAL, ModeReason::BAD_DEPTH)) {
|
||||||
// We should never get here
|
// We should never get here
|
||||||
arming.disarm(AP_Arming::Method::BADFLOWOFCONTROL);
|
arming.disarm(AP_Arming::Method::BADFLOWOFCONTROL);
|
||||||
}
|
}
|
||||||
|
@ -156,7 +156,7 @@ void Sub::handle_battery_failsafe(const char* type_str, const int8_t action)
|
||||||
|
|
||||||
switch((Failsafe_Action)action) {
|
switch((Failsafe_Action)action) {
|
||||||
case Failsafe_Action_Surface:
|
case Failsafe_Action_Surface:
|
||||||
set_mode(SURFACE, ModeReason::BATTERY_FAILSAFE);
|
set_mode(Mode::Number::SURFACE, ModeReason::BATTERY_FAILSAFE);
|
||||||
break;
|
break;
|
||||||
case Failsafe_Action_Disarm:
|
case Failsafe_Action_Disarm:
|
||||||
arming.disarm(AP_Arming::Method::BATTERYFAILSAFE);
|
arming.disarm(AP_Arming::Method::BATTERYFAILSAFE);
|
||||||
|
@ -299,7 +299,7 @@ void Sub::failsafe_leak_check()
|
||||||
|
|
||||||
// Handle failsafe action
|
// Handle failsafe action
|
||||||
if (failsafe.leak && g.failsafe_leak == FS_LEAK_SURFACE && motors.armed()) {
|
if (failsafe.leak && g.failsafe_leak == FS_LEAK_SURFACE && motors.armed()) {
|
||||||
set_mode(SURFACE, ModeReason::LEAK_FAILSAFE);
|
set_mode(Mode::Number::SURFACE, ModeReason::LEAK_FAILSAFE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,11 +352,11 @@ void Sub::failsafe_gcs_check()
|
||||||
if (g.failsafe_gcs == FS_GCS_DISARM) {
|
if (g.failsafe_gcs == FS_GCS_DISARM) {
|
||||||
arming.disarm(AP_Arming::Method::GCSFAILSAFE);
|
arming.disarm(AP_Arming::Method::GCSFAILSAFE);
|
||||||
} else if (g.failsafe_gcs == FS_GCS_HOLD && motors.armed()) {
|
} else if (g.failsafe_gcs == FS_GCS_HOLD && motors.armed()) {
|
||||||
if (!set_mode(ALT_HOLD, ModeReason::GCS_FAILSAFE)) {
|
if (!set_mode(Mode::Number::ALT_HOLD, ModeReason::GCS_FAILSAFE)) {
|
||||||
arming.disarm(AP_Arming::Method::GCS_FAILSAFE_HOLDFAILED);
|
arming.disarm(AP_Arming::Method::GCS_FAILSAFE_HOLDFAILED);
|
||||||
}
|
}
|
||||||
} else if (g.failsafe_gcs == FS_GCS_SURFACE && motors.armed()) {
|
} else if (g.failsafe_gcs == FS_GCS_SURFACE && motors.armed()) {
|
||||||
if (!set_mode(SURFACE, ModeReason::GCS_FAILSAFE)) {
|
if (!set_mode(Mode::Number::SURFACE, ModeReason::GCS_FAILSAFE)) {
|
||||||
arming.disarm(AP_Arming::Method::GCS_FAILSAFE_SURFACEFAILED);
|
arming.disarm(AP_Arming::Method::GCS_FAILSAFE_SURFACEFAILED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -380,7 +380,7 @@ void Sub::failsafe_crash_check()
|
||||||
}
|
}
|
||||||
|
|
||||||
// return immediately if we are not in an angle stabilized flight mode
|
// return immediately if we are not in an angle stabilized flight mode
|
||||||
if (control_mode == ACRO || control_mode == MANUAL) {
|
if (control_mode == Mode::Number::ACRO || control_mode == Mode::Number::MANUAL) {
|
||||||
last_crash_check_pass_ms = tnow;
|
last_crash_check_pass_ms = tnow;
|
||||||
failsafe.crash = false;
|
failsafe.crash = false;
|
||||||
return;
|
return;
|
||||||
|
@ -425,7 +425,7 @@ void Sub::failsafe_crash_check()
|
||||||
void Sub::failsafe_terrain_check()
|
void Sub::failsafe_terrain_check()
|
||||||
{
|
{
|
||||||
// trigger with 5 seconds of failures while in AUTO mode
|
// trigger with 5 seconds of failures while in AUTO mode
|
||||||
bool valid_mode = (control_mode == AUTO || control_mode == GUIDED);
|
bool valid_mode = (control_mode == Mode::Number::AUTO || control_mode == Mode::Number::GUIDED);
|
||||||
bool timeout = (failsafe.terrain_last_failure_ms - failsafe.terrain_first_failure_ms) > FS_TERRAIN_TIMEOUT_MS;
|
bool timeout = (failsafe.terrain_last_failure_ms - failsafe.terrain_first_failure_ms) > FS_TERRAIN_TIMEOUT_MS;
|
||||||
bool trigger_event = valid_mode && timeout;
|
bool trigger_event = valid_mode && timeout;
|
||||||
|
|
||||||
|
@ -470,7 +470,7 @@ void Sub::failsafe_terrain_on_event()
|
||||||
AP::logger().Write_Error(LogErrorSubsystem::FAILSAFE_TERRAIN, LogErrorCode::FAILSAFE_OCCURRED);
|
AP::logger().Write_Error(LogErrorSubsystem::FAILSAFE_TERRAIN, LogErrorCode::FAILSAFE_OCCURRED);
|
||||||
|
|
||||||
// If rangefinder is enabled, we can recover from this failsafe
|
// If rangefinder is enabled, we can recover from this failsafe
|
||||||
if (!rangefinder_state.enabled || !auto_terrain_recover_start()) {
|
if (!rangefinder_state.enabled || !sub.mode_auto.auto_terrain_recover_start()) {
|
||||||
failsafe_terrain_act();
|
failsafe_terrain_act();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -482,14 +482,14 @@ void Sub::failsafe_terrain_act()
|
||||||
{
|
{
|
||||||
switch (g.failsafe_terrain) {
|
switch (g.failsafe_terrain) {
|
||||||
case FS_TERRAIN_HOLD:
|
case FS_TERRAIN_HOLD:
|
||||||
if (!set_mode(POSHOLD, ModeReason::TERRAIN_FAILSAFE)) {
|
if (!set_mode(Mode::Number::POSHOLD, ModeReason::TERRAIN_FAILSAFE)) {
|
||||||
set_mode(ALT_HOLD, ModeReason::TERRAIN_FAILSAFE);
|
set_mode(Mode::Number::ALT_HOLD, ModeReason::TERRAIN_FAILSAFE);
|
||||||
}
|
}
|
||||||
AP_Notify::events.failsafe_mode_change = 1;
|
AP_Notify::events.failsafe_mode_change = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FS_TERRAIN_SURFACE:
|
case FS_TERRAIN_SURFACE:
|
||||||
set_mode(SURFACE, ModeReason::TERRAIN_FAILSAFE);
|
set_mode(Mode::Number::SURFACE, ModeReason::TERRAIN_FAILSAFE);
|
||||||
AP_Notify::events.failsafe_mode_change = 1;
|
AP_Notify::events.failsafe_mode_change = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ void Sub::fence_check()
|
||||||
const uint8_t orig_breaches = fence.get_breaches();
|
const uint8_t orig_breaches = fence.get_breaches();
|
||||||
|
|
||||||
// check for new breaches; new_breaches is bitmask of fence types breached
|
// check for new breaches; new_breaches is bitmask of fence types breached
|
||||||
const uint8_t new_breaches = fence.check();
|
const uint8_t new_breaches = sub.fence.check();
|
||||||
|
|
||||||
// if there is a new breach take action
|
// if there is a new breach take action
|
||||||
if (new_breaches) {
|
if (new_breaches) {
|
||||||
|
|
|
@ -1,230 +0,0 @@
|
||||||
#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, ModeReason 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;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
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 AP_CAMERA_ENABLED
|
|
||||||
camera.set_is_auto_mode(control_mode == AUTO);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if AP_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;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Sub::set_mode(const uint8_t new_mode, const ModeReason reason)
|
|
||||||
{
|
|
||||||
static_assert(sizeof(control_mode_t) == sizeof(new_mode), "The new mode can't be mapped to the vehicles mode number");
|
|
||||||
return sub.set_mode((control_mode_t)new_mode, reason);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
|
|
||||||
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 HAL_MOUNT_ENABLED
|
|
||||||
camera_mount.set_mode_to_default();
|
|
||||||
#endif // HAL_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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "Sub.h"
|
#include "Sub.h"
|
||||||
|
#include "mode.h"
|
||||||
|
|
||||||
// Functions that will handle joystick/gamepad input
|
// Functions that will handle joystick/gamepad input
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
@ -34,7 +35,7 @@ void Sub::init_joystick()
|
||||||
lights1 = RC_Channels::rc_channel(8)->get_radio_min();
|
lights1 = RC_Channels::rc_channel(8)->get_radio_min();
|
||||||
lights2 = RC_Channels::rc_channel(9)->get_radio_min();
|
lights2 = RC_Channels::rc_channel(9)->get_radio_min();
|
||||||
|
|
||||||
set_mode(MANUAL, ModeReason::RC_COMMAND); // Initialize flight mode
|
set_mode(Mode::Number::MANUAL, ModeReason::RC_COMMAND); // Initialize flight mode
|
||||||
|
|
||||||
if (g.numGainSettings < 1) {
|
if (g.numGainSettings < 1) {
|
||||||
g.numGainSettings.set_and_save(1);
|
g.numGainSettings.set_and_save(1);
|
||||||
|
@ -157,28 +158,28 @@ void Sub::handle_jsbutton_press(uint8_t _button, bool shift, bool held)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case JSButton::button_function_t::k_mode_manual:
|
case JSButton::button_function_t::k_mode_manual:
|
||||||
set_mode(MANUAL, ModeReason::RC_COMMAND);
|
set_mode(Mode::Number::MANUAL, ModeReason::RC_COMMAND);
|
||||||
break;
|
break;
|
||||||
case JSButton::button_function_t::k_mode_stabilize:
|
case JSButton::button_function_t::k_mode_stabilize:
|
||||||
set_mode(STABILIZE, ModeReason::RC_COMMAND);
|
set_mode(Mode::Number::STABILIZE, ModeReason::RC_COMMAND);
|
||||||
break;
|
break;
|
||||||
case JSButton::button_function_t::k_mode_depth_hold:
|
case JSButton::button_function_t::k_mode_depth_hold:
|
||||||
set_mode(ALT_HOLD, ModeReason::RC_COMMAND);
|
set_mode(Mode::Number::ALT_HOLD, ModeReason::RC_COMMAND);
|
||||||
break;
|
break;
|
||||||
case JSButton::button_function_t::k_mode_auto:
|
case JSButton::button_function_t::k_mode_auto:
|
||||||
set_mode(AUTO, ModeReason::RC_COMMAND);
|
set_mode(Mode::Number::AUTO, ModeReason::RC_COMMAND);
|
||||||
break;
|
break;
|
||||||
case JSButton::button_function_t::k_mode_guided:
|
case JSButton::button_function_t::k_mode_guided:
|
||||||
set_mode(GUIDED, ModeReason::RC_COMMAND);
|
set_mode(Mode::Number::GUIDED, ModeReason::RC_COMMAND);
|
||||||
break;
|
break;
|
||||||
case JSButton::button_function_t::k_mode_circle:
|
case JSButton::button_function_t::k_mode_circle:
|
||||||
set_mode(CIRCLE, ModeReason::RC_COMMAND);
|
set_mode(Mode::Number::CIRCLE, ModeReason::RC_COMMAND);
|
||||||
break;
|
break;
|
||||||
case JSButton::button_function_t::k_mode_acro:
|
case JSButton::button_function_t::k_mode_acro:
|
||||||
set_mode(ACRO, ModeReason::RC_COMMAND);
|
set_mode(Mode::Number::ACRO, ModeReason::RC_COMMAND);
|
||||||
break;
|
break;
|
||||||
case JSButton::button_function_t::k_mode_poshold:
|
case JSButton::button_function_t::k_mode_poshold:
|
||||||
set_mode(POSHOLD, ModeReason::RC_COMMAND);
|
set_mode(Mode::Number::POSHOLD, ModeReason::RC_COMMAND);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case JSButton::button_function_t::k_mount_center:
|
case JSButton::button_function_t::k_mount_center:
|
||||||
|
|
|
@ -0,0 +1,292 @@
|
||||||
|
#include "Sub.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
constructor for Mode object
|
||||||
|
*/
|
||||||
|
Mode::Mode(void) :
|
||||||
|
g(sub.g),
|
||||||
|
g2(sub.g2),
|
||||||
|
inertial_nav(sub.inertial_nav),
|
||||||
|
ahrs(sub.ahrs),
|
||||||
|
motors(sub.motors),
|
||||||
|
channel_roll(sub.channel_roll),
|
||||||
|
channel_pitch(sub.channel_pitch),
|
||||||
|
channel_throttle(sub.channel_throttle),
|
||||||
|
channel_yaw(sub.channel_yaw),
|
||||||
|
channel_forward(sub.channel_forward),
|
||||||
|
channel_lateral(sub.channel_lateral),
|
||||||
|
position_control(&sub.pos_control),
|
||||||
|
attitude_control(&sub.attitude_control),
|
||||||
|
G_Dt(sub.G_Dt)
|
||||||
|
{ };
|
||||||
|
|
||||||
|
// return the static controller object corresponding to supplied mode
|
||||||
|
Mode *Sub::mode_from_mode_num(const Mode::Number mode)
|
||||||
|
{
|
||||||
|
Mode *ret = nullptr;
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case Mode::Number::MANUAL:
|
||||||
|
ret = &mode_manual;
|
||||||
|
break;
|
||||||
|
case Mode::Number::STABILIZE:
|
||||||
|
ret = &mode_stabilize;
|
||||||
|
break;
|
||||||
|
case Mode::Number::ACRO:
|
||||||
|
ret = &mode_acro;
|
||||||
|
break;
|
||||||
|
case Mode::Number::ALT_HOLD:
|
||||||
|
ret = &mode_althold;
|
||||||
|
break;
|
||||||
|
case Mode::Number::POSHOLD:
|
||||||
|
ret = &mode_poshold;
|
||||||
|
break;
|
||||||
|
case Mode::Number::AUTO:
|
||||||
|
ret = &mode_auto;
|
||||||
|
break;
|
||||||
|
case Mode::Number::GUIDED:
|
||||||
|
ret = &mode_guided;
|
||||||
|
break;
|
||||||
|
case Mode::Number::CIRCLE:
|
||||||
|
ret = &mode_circle;
|
||||||
|
break;
|
||||||
|
case Mode::Number::SURFACE:
|
||||||
|
ret = &mode_surface;
|
||||||
|
break;
|
||||||
|
case Mode::Number::MOTOR_DETECT:
|
||||||
|
ret = &mode_motordetect;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// set_mode - change flight mode and perform any necessary initialisation
|
||||||
|
// optional force parameter used to force the flight mode change (used only first time mode is set)
|
||||||
|
// returns true if mode was successfully set
|
||||||
|
// Some modes can always be set successfully but the return state of other flight modes should be checked and the caller should deal with failures appropriately
|
||||||
|
bool Sub::set_mode(Mode::Number mode, ModeReason reason)
|
||||||
|
{
|
||||||
|
|
||||||
|
// return immediately if we are already in the desired mode
|
||||||
|
if (mode == control_mode) {
|
||||||
|
control_mode_reason = reason;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mode *new_flightmode = mode_from_mode_num((Mode::Number)mode);
|
||||||
|
if (new_flightmode == nullptr) {
|
||||||
|
notify_no_such_mode((uint8_t)mode);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_flightmode->requires_GPS() &&
|
||||||
|
!sub.position_ok()) {
|
||||||
|
gcs().send_text(MAV_SEVERITY_WARNING, "Mode change failed: %s requires position", new_flightmode->name());
|
||||||
|
AP::logger().Write_Error(LogErrorSubsystem::FLIGHT_MODE, LogErrorCode(mode));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for valid altitude if old mode did not require it but new one does
|
||||||
|
// we only want to stop changing modes if it could make things worse
|
||||||
|
if (!sub.control_check_barometer() && // maybe use ekf_alt_ok() instead?
|
||||||
|
flightmode->has_manual_throttle() &&
|
||||||
|
!new_flightmode->has_manual_throttle()) {
|
||||||
|
gcs().send_text(MAV_SEVERITY_WARNING, "Mode change failed: %s need alt estimate", new_flightmode->name());
|
||||||
|
AP::logger().Write_Error(LogErrorSubsystem::FLIGHT_MODE, LogErrorCode(mode));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!new_flightmode->init(false)) {
|
||||||
|
gcs().send_text(MAV_SEVERITY_WARNING,"Flight mode change failed %s", new_flightmode->name());
|
||||||
|
AP::logger().Write_Error(LogErrorSubsystem::FLIGHT_MODE, LogErrorCode(mode));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// perform any cleanup required by previous flight mode
|
||||||
|
exit_mode(flightmode, new_flightmode);
|
||||||
|
|
||||||
|
// store previous flight mode (only used by tradeheli's autorotation)
|
||||||
|
prev_control_mode = control_mode;
|
||||||
|
|
||||||
|
// update flight mode
|
||||||
|
flightmode = new_flightmode;
|
||||||
|
control_mode = mode;
|
||||||
|
control_mode_reason = reason;
|
||||||
|
logger.Write_Mode((uint8_t)control_mode, reason);
|
||||||
|
gcs().send_message(MSG_HEARTBEAT);
|
||||||
|
|
||||||
|
// update notify object
|
||||||
|
notify_flight_mode();
|
||||||
|
|
||||||
|
// return success
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// exit_mode - high level call to organise cleanup as a flight mode is exited
|
||||||
|
void Sub::exit_mode(Mode::Number old_control_mode, Mode::Number new_control_mode)
|
||||||
|
{
|
||||||
|
// stop mission when we leave auto mode
|
||||||
|
if (old_control_mode == Mode::Number::AUTO) {
|
||||||
|
if (mission.state() == AP_Mission::MISSION_RUNNING) {
|
||||||
|
mission.stop();
|
||||||
|
}
|
||||||
|
#if HAL_MOUNT_ENABLED
|
||||||
|
camera_mount.set_mode_to_default();
|
||||||
|
#endif // HAL_MOUNT_ENABLED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Sub::set_mode(const uint8_t new_mode, const ModeReason reason)
|
||||||
|
{
|
||||||
|
static_assert(sizeof(Mode::Number) == sizeof(new_mode), "The new mode can't be mapped to the vehicles mode number");
|
||||||
|
return sub.set_mode(static_cast<Mode::Number>(new_mode), reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
// update_flight_mode - calls the appropriate attitude controllers based on flight mode
|
||||||
|
// called at 100hz or more
|
||||||
|
void Sub::update_flight_mode()
|
||||||
|
{
|
||||||
|
flightmode->run();
|
||||||
|
}
|
||||||
|
|
||||||
|
// exit_mode - high level call to organise cleanup as a flight mode is exited
|
||||||
|
void Sub::exit_mode(Mode *&old_flightmode, Mode *&new_flightmode){
|
||||||
|
#if HAL_MOUNT_ENABLED
|
||||||
|
camera_mount.set_mode_to_default();
|
||||||
|
#endif // HAL_MOUNT_ENABLED
|
||||||
|
}
|
||||||
|
|
||||||
|
// notify_flight_mode - sets notify object based on current flight mode. Only used for OreoLED notify device
|
||||||
|
void Sub::notify_flight_mode()
|
||||||
|
{
|
||||||
|
AP_Notify::flags.autopilot_mode = flightmode->is_autopilot();
|
||||||
|
AP_Notify::flags.flight_mode = (uint8_t)control_mode;
|
||||||
|
notify.set_flight_mode_str(flightmode->name4());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// get_pilot_desired_angle_rates - transform pilot's roll pitch and yaw input into a desired lean angle rates
|
||||||
|
// returns desired angle rates in centi-degrees-per-second
|
||||||
|
void Mode::get_pilot_desired_angle_rates(int16_t roll_in, int16_t pitch_in, int16_t yaw_in, float &roll_out, float &pitch_out, float &yaw_out)
|
||||||
|
{
|
||||||
|
float rate_limit;
|
||||||
|
Vector3f rate_ef_level, rate_bf_level, rate_bf_request;
|
||||||
|
|
||||||
|
// apply circular limit to pitch and roll inputs
|
||||||
|
float total_in = norm(pitch_in, roll_in);
|
||||||
|
|
||||||
|
if (total_in > ROLL_PITCH_INPUT_MAX) {
|
||||||
|
float ratio = (float)ROLL_PITCH_INPUT_MAX / total_in;
|
||||||
|
roll_in *= ratio;
|
||||||
|
pitch_in *= ratio;
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate roll, pitch rate requests
|
||||||
|
if (g.acro_expo <= 0) {
|
||||||
|
rate_bf_request.x = roll_in * g.acro_rp_p;
|
||||||
|
rate_bf_request.y = pitch_in * g.acro_rp_p;
|
||||||
|
} else {
|
||||||
|
// expo variables
|
||||||
|
float rp_in, rp_in3, rp_out;
|
||||||
|
|
||||||
|
// range check expo
|
||||||
|
if (g.acro_expo > 1.0f) {
|
||||||
|
g.acro_expo.set(1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
// roll expo
|
||||||
|
rp_in = float(roll_in)/ROLL_PITCH_INPUT_MAX;
|
||||||
|
rp_in3 = rp_in*rp_in*rp_in;
|
||||||
|
rp_out = (g.acro_expo * rp_in3) + ((1 - g.acro_expo) * rp_in);
|
||||||
|
rate_bf_request.x = ROLL_PITCH_INPUT_MAX * rp_out * g.acro_rp_p;
|
||||||
|
|
||||||
|
// pitch expo
|
||||||
|
rp_in = float(pitch_in)/ROLL_PITCH_INPUT_MAX;
|
||||||
|
rp_in3 = rp_in*rp_in*rp_in;
|
||||||
|
rp_out = (g.acro_expo * rp_in3) + ((1 - g.acro_expo) * rp_in);
|
||||||
|
rate_bf_request.y = ROLL_PITCH_INPUT_MAX * rp_out * g.acro_rp_p;
|
||||||
|
}
|
||||||
|
|
||||||
|
// calculate yaw rate request
|
||||||
|
rate_bf_request.z = yaw_in * g.acro_yaw_p;
|
||||||
|
|
||||||
|
// calculate earth frame rate corrections to pull the vehicle back to level while in ACRO mode
|
||||||
|
|
||||||
|
if (g.acro_trainer != ACRO_TRAINER_DISABLED) {
|
||||||
|
// Calculate trainer mode earth frame rate command for roll
|
||||||
|
int32_t roll_angle = wrap_180_cd(ahrs.roll_sensor);
|
||||||
|
rate_ef_level.x = -constrain_int32(roll_angle, -ACRO_LEVEL_MAX_ANGLE, ACRO_LEVEL_MAX_ANGLE) * g.acro_balance_roll;
|
||||||
|
|
||||||
|
// Calculate trainer mode earth frame rate command for pitch
|
||||||
|
int32_t pitch_angle = wrap_180_cd(ahrs.pitch_sensor);
|
||||||
|
rate_ef_level.y = -constrain_int32(pitch_angle, -ACRO_LEVEL_MAX_ANGLE, ACRO_LEVEL_MAX_ANGLE) * g.acro_balance_pitch;
|
||||||
|
|
||||||
|
// Calculate trainer mode earth frame rate command for yaw
|
||||||
|
rate_ef_level.z = 0;
|
||||||
|
|
||||||
|
// Calculate angle limiting earth frame rate commands
|
||||||
|
if (g.acro_trainer == ACRO_TRAINER_LIMITED) {
|
||||||
|
if (roll_angle > sub.aparm.angle_max) {
|
||||||
|
rate_ef_level.x -= g.acro_balance_roll*(roll_angle-sub.aparm.angle_max);
|
||||||
|
} else if (roll_angle < -sub.aparm.angle_max) {
|
||||||
|
rate_ef_level.x -= g.acro_balance_roll*(roll_angle+sub.aparm.angle_max);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pitch_angle > sub.aparm.angle_max) {
|
||||||
|
rate_ef_level.y -= g.acro_balance_pitch*(pitch_angle-sub.aparm.angle_max);
|
||||||
|
} else if (pitch_angle < -sub.aparm.angle_max) {
|
||||||
|
rate_ef_level.y -= g.acro_balance_pitch*(pitch_angle+sub.aparm.angle_max);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert earth-frame level rates to body-frame level rates
|
||||||
|
attitude_control->euler_rate_to_ang_vel(attitude_control->get_att_target_euler_cd()*radians(0.01f), rate_ef_level, rate_bf_level);
|
||||||
|
|
||||||
|
// combine earth frame rate corrections with rate requests
|
||||||
|
if (g.acro_trainer == ACRO_TRAINER_LIMITED) {
|
||||||
|
rate_bf_request.x += rate_bf_level.x;
|
||||||
|
rate_bf_request.y += rate_bf_level.y;
|
||||||
|
rate_bf_request.z += rate_bf_level.z;
|
||||||
|
} else {
|
||||||
|
float acro_level_mix = constrain_float(1-MAX(MAX(abs(roll_in), abs(pitch_in)), abs(yaw_in))/4500.0, 0, 1)*ahrs.cos_pitch();
|
||||||
|
|
||||||
|
// Scale leveling rates by stick input
|
||||||
|
rate_bf_level = rate_bf_level*acro_level_mix;
|
||||||
|
|
||||||
|
// Calculate rate limit to prevent change of rate through inverted
|
||||||
|
rate_limit = fabsf(fabsf(rate_bf_request.x)-fabsf(rate_bf_level.x));
|
||||||
|
rate_bf_request.x += rate_bf_level.x;
|
||||||
|
rate_bf_request.x = constrain_float(rate_bf_request.x, -rate_limit, rate_limit);
|
||||||
|
|
||||||
|
// Calculate rate limit to prevent change of rate through inverted
|
||||||
|
rate_limit = fabsf(fabsf(rate_bf_request.y)-fabsf(rate_bf_level.y));
|
||||||
|
rate_bf_request.y += rate_bf_level.y;
|
||||||
|
rate_bf_request.y = constrain_float(rate_bf_request.y, -rate_limit, rate_limit);
|
||||||
|
|
||||||
|
// Calculate rate limit to prevent change of rate through inverted
|
||||||
|
rate_limit = fabsf(fabsf(rate_bf_request.z)-fabsf(rate_bf_level.z));
|
||||||
|
rate_bf_request.z += rate_bf_level.z;
|
||||||
|
rate_bf_request.z = constrain_float(rate_bf_request.z, -rate_limit, rate_limit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// hand back rate request
|
||||||
|
roll_out = rate_bf_request.x;
|
||||||
|
pitch_out = rate_bf_request.y;
|
||||||
|
yaw_out = rate_bf_request.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Mode::set_mode(Mode::Number mode, ModeReason reason)
|
||||||
|
{
|
||||||
|
return sub.set_mode(mode, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
GCS_Sub &Mode::gcs()
|
||||||
|
{
|
||||||
|
return sub.gcs();
|
||||||
|
}
|
|
@ -0,0 +1,444 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Sub.h"
|
||||||
|
class Parameters;
|
||||||
|
class ParametersG2;
|
||||||
|
|
||||||
|
class GCS_Sub;
|
||||||
|
|
||||||
|
// Guided modes
|
||||||
|
enum GuidedSubMode {
|
||||||
|
Guided_WP,
|
||||||
|
Guided_Velocity,
|
||||||
|
Guided_PosVel,
|
||||||
|
Guided_Angle,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Auto modes
|
||||||
|
enum AutoSubMode {
|
||||||
|
Auto_WP,
|
||||||
|
Auto_CircleMoveToEdge,
|
||||||
|
Auto_Circle,
|
||||||
|
Auto_NavGuided,
|
||||||
|
Auto_Loiter,
|
||||||
|
Auto_TerrainRecover
|
||||||
|
};
|
||||||
|
|
||||||
|
// RTL states
|
||||||
|
enum RTLState {
|
||||||
|
RTL_InitialClimb,
|
||||||
|
RTL_ReturnHome,
|
||||||
|
RTL_LoiterAtHome,
|
||||||
|
RTL_FinalDescent,
|
||||||
|
RTL_Land
|
||||||
|
};
|
||||||
|
|
||||||
|
class Mode
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Auto Pilot Modes enumeration
|
||||||
|
enum class Number : uint8_t {
|
||||||
|
STABILIZE = 0, // manual angle with manual depth/throttle
|
||||||
|
ACRO = 1, // manual body-frame angular rate with manual depth/throttle
|
||||||
|
ALT_HOLD = 2, // manual angle with automatic depth/throttle
|
||||||
|
AUTO = 3, // fully automatic waypoint control using mission commands
|
||||||
|
GUIDED = 4, // fully automatic fly to coordinate or fly at velocity/direction using GCS immediate commands
|
||||||
|
CIRCLE = 7, // automatic circular flight with automatic throttle
|
||||||
|
SURFACE = 9, // automatically return to surface, pilot maintains horizontal control
|
||||||
|
POSHOLD = 16, // automatic position hold with manual override, with automatic throttle
|
||||||
|
MANUAL = 19, // Pass-through input with no stabilization
|
||||||
|
MOTOR_DETECT = 20 // Automatically detect motors orientation
|
||||||
|
};
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
Mode(void);
|
||||||
|
|
||||||
|
// do not allow copying
|
||||||
|
CLASS_NO_COPY(Mode);
|
||||||
|
|
||||||
|
// child classes should override these methods
|
||||||
|
virtual bool init(bool ignore_checks) { return true; }
|
||||||
|
virtual void run() = 0;
|
||||||
|
virtual bool requires_GPS() const = 0;
|
||||||
|
virtual bool has_manual_throttle() const = 0;
|
||||||
|
virtual bool allows_arming(bool from_gcs) const = 0;
|
||||||
|
virtual bool is_autopilot() const { return false; }
|
||||||
|
virtual bool in_guided_mode() const { return false; }
|
||||||
|
|
||||||
|
// return a string for this flightmode
|
||||||
|
virtual const char *name() const = 0;
|
||||||
|
virtual const char *name4() const = 0;
|
||||||
|
|
||||||
|
// functions for reporting to GCS
|
||||||
|
virtual bool get_wp(Location &loc) { return false; }
|
||||||
|
virtual int32_t wp_bearing() const { return 0; }
|
||||||
|
virtual uint32_t wp_distance() const { return 0; }
|
||||||
|
virtual float crosstrack_error() const { return 0.0f; }
|
||||||
|
|
||||||
|
|
||||||
|
// pilot input processing
|
||||||
|
void get_pilot_desired_accelerations(float &right_out, float &front_out) const;
|
||||||
|
void get_pilot_desired_angle_rates(int16_t roll_in, int16_t pitch_in, int16_t yaw_in, float &roll_out, float &pitch_out, float &yaw_out);
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// navigation support functions
|
||||||
|
virtual void run_autopilot() {}
|
||||||
|
|
||||||
|
// helper functions
|
||||||
|
bool is_disarmed_or_landed() const;
|
||||||
|
|
||||||
|
// functions to control landing
|
||||||
|
// in modes that support landing
|
||||||
|
void land_run_horizontal_control();
|
||||||
|
void land_run_vertical_control(bool pause_descent = false);
|
||||||
|
|
||||||
|
// convenience references to avoid code churn in conversion:
|
||||||
|
Parameters &g;
|
||||||
|
ParametersG2 &g2;
|
||||||
|
AP_InertialNav &inertial_nav;
|
||||||
|
AP_AHRS &ahrs;
|
||||||
|
AP_Motors6DOF &motors;
|
||||||
|
RC_Channel *&channel_roll;
|
||||||
|
RC_Channel *&channel_pitch;
|
||||||
|
RC_Channel *&channel_throttle;
|
||||||
|
RC_Channel *&channel_yaw;
|
||||||
|
RC_Channel *&channel_forward;
|
||||||
|
RC_Channel *&channel_lateral;
|
||||||
|
AC_PosControl *position_control;
|
||||||
|
AC_AttitudeControl_Sub *attitude_control;
|
||||||
|
// TODO: channels
|
||||||
|
float &G_Dt;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Navigation Yaw control
|
||||||
|
class AutoYaw
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
// mode(): current method of determining desired yaw:
|
||||||
|
autopilot_yaw_mode mode() const
|
||||||
|
{
|
||||||
|
return (autopilot_yaw_mode)_mode;
|
||||||
|
}
|
||||||
|
void set_mode_to_default(bool rtl);
|
||||||
|
void set_mode(autopilot_yaw_mode new_mode);
|
||||||
|
autopilot_yaw_mode default_mode(bool rtl) const;
|
||||||
|
|
||||||
|
void set_rate(float new_rate_cds);
|
||||||
|
|
||||||
|
// set_roi(...): set a "look at" location:
|
||||||
|
void set_roi(const Location &roi_location);
|
||||||
|
|
||||||
|
void set_fixed_yaw(float angle_deg,
|
||||||
|
float turn_rate_dps,
|
||||||
|
int8_t direction,
|
||||||
|
bool relative_angle);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// yaw_cd(): main product of AutoYaw; the heading:
|
||||||
|
float yaw_cd();
|
||||||
|
|
||||||
|
// rate_cds(): desired yaw rate in centidegrees/second:
|
||||||
|
float rate_cds();
|
||||||
|
|
||||||
|
float look_ahead_yaw();
|
||||||
|
float roi_yaw();
|
||||||
|
|
||||||
|
// auto flight mode's yaw mode
|
||||||
|
uint8_t _mode = AUTO_YAW_LOOK_AT_NEXT_WP;
|
||||||
|
|
||||||
|
// Yaw will point at this location if mode is set to AUTO_YAW_ROI
|
||||||
|
Vector3f roi;
|
||||||
|
|
||||||
|
// bearing from current location to the ROI
|
||||||
|
float _roi_yaw;
|
||||||
|
|
||||||
|
// yaw used for YAW_FIXED yaw_mode
|
||||||
|
int32_t _fixed_yaw;
|
||||||
|
|
||||||
|
// Deg/s we should turn
|
||||||
|
int16_t _fixed_yaw_slewrate;
|
||||||
|
|
||||||
|
// heading when in yaw_look_ahead_yaw
|
||||||
|
float _look_ahead_yaw;
|
||||||
|
|
||||||
|
// used to reduce update rate to 100hz:
|
||||||
|
uint8_t roi_yaw_counter;
|
||||||
|
|
||||||
|
GuidedSubMode guided_mode;
|
||||||
|
|
||||||
|
};
|
||||||
|
static AutoYaw auto_yaw;
|
||||||
|
|
||||||
|
// pass-through functions to reduce code churn on conversion;
|
||||||
|
// these are candidates for moving into the Mode base
|
||||||
|
// class.
|
||||||
|
bool set_mode(Mode::Number mode, ModeReason reason);
|
||||||
|
GCS_Sub &gcs();
|
||||||
|
|
||||||
|
// end pass-through functions
|
||||||
|
};
|
||||||
|
|
||||||
|
class ModeManual : public Mode
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
// inherit constructor
|
||||||
|
using Mode::Mode;
|
||||||
|
virtual void run() override;
|
||||||
|
bool init(bool ignore_checks) override;
|
||||||
|
bool requires_GPS() const override { return false; }
|
||||||
|
bool has_manual_throttle() const override { return true; }
|
||||||
|
bool allows_arming(bool from_gcs) const override { return true; }
|
||||||
|
bool is_autopilot() const override { return false; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
const char *name() const override { return "MANUAL"; }
|
||||||
|
const char *name4() const override { return "MANU"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class ModeAcro : public Mode
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
// inherit constructor
|
||||||
|
using Mode::Mode;
|
||||||
|
|
||||||
|
virtual void run() override;
|
||||||
|
|
||||||
|
bool init(bool ignore_checks) override;
|
||||||
|
bool requires_GPS() const override { return false; }
|
||||||
|
bool has_manual_throttle() const override { return true; }
|
||||||
|
bool allows_arming(bool from_gcs) const override { return true; }
|
||||||
|
bool is_autopilot() const override { return false; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
const char *name() const override { return "ACRO"; }
|
||||||
|
const char *name4() const override { return "ACRO"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class ModeStabilize : public Mode
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
// inherit constructor
|
||||||
|
using Mode::Mode;
|
||||||
|
|
||||||
|
virtual void run() override;
|
||||||
|
|
||||||
|
bool init(bool ignore_checks) override;
|
||||||
|
bool requires_GPS() const override { return false; }
|
||||||
|
bool has_manual_throttle() const override { return true; }
|
||||||
|
bool allows_arming(bool from_gcs) const override { return true; }
|
||||||
|
bool is_autopilot() const override { return false; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
const char *name() const override { return "STABILIZE"; }
|
||||||
|
const char *name4() const override { return "STAB"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class ModeAlthold : public Mode
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
// inherit constructor
|
||||||
|
using Mode::Mode;
|
||||||
|
|
||||||
|
virtual void run() override;
|
||||||
|
|
||||||
|
bool init(bool ignore_checks) override;
|
||||||
|
bool requires_GPS() const override { return false; }
|
||||||
|
bool has_manual_throttle() const override { return false; }
|
||||||
|
bool allows_arming(bool from_gcs) const override { return true; }
|
||||||
|
bool is_autopilot() const override { return false; }
|
||||||
|
void control_depth();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
const char *name() const override { return "ALT_HOLD"; }
|
||||||
|
const char *name4() const override { return "ALTH"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class ModeGuided : public Mode
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
// inherit constructor
|
||||||
|
using Mode::Mode;
|
||||||
|
|
||||||
|
virtual void run() override;
|
||||||
|
|
||||||
|
bool init(bool ignore_checks) override;
|
||||||
|
bool requires_GPS() const override { return true; }
|
||||||
|
bool has_manual_throttle() const override { return false; }
|
||||||
|
bool allows_arming(bool from_gcs) const override { return true; }
|
||||||
|
bool is_autopilot() const override { return true; }
|
||||||
|
bool guided_limit_check();
|
||||||
|
void guided_limit_init_time_and_pos();
|
||||||
|
void guided_set_angle(const Quaternion &q, float climb_rate_cms, bool use_yaw_rate, float yaw_rate_rads);
|
||||||
|
void guided_set_angle(const Quaternion&, float);
|
||||||
|
void guided_limit_set(uint32_t timeout_ms, float alt_min_cm, float alt_max_cm, float horiz_max_cm);
|
||||||
|
bool guided_set_destination_posvel(const Vector3f& destination, const Vector3f& velocity);
|
||||||
|
bool guided_set_destination(const Vector3f& destination);
|
||||||
|
bool guided_set_destination(const Location&);
|
||||||
|
void guided_set_velocity(const Vector3f& velocity);
|
||||||
|
float get_auto_heading();
|
||||||
|
void guided_limit_clear();
|
||||||
|
void set_auto_yaw_mode(autopilot_yaw_mode yaw_mode);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
const char *name() const override { return "GUIDED"; }
|
||||||
|
const char *name4() const override { return "GUID"; }
|
||||||
|
autopilot_yaw_mode get_default_auto_yaw_mode(bool rtl) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void guided_pos_control_run();
|
||||||
|
void guided_vel_control_run();
|
||||||
|
void guided_posvel_control_run();
|
||||||
|
void guided_angle_control_run();
|
||||||
|
void guided_takeoff_run();
|
||||||
|
void guided_pos_control_start();
|
||||||
|
void guided_vel_control_start();
|
||||||
|
void guided_posvel_control_start();
|
||||||
|
void guided_angle_control_start();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class ModeAuto : public ModeGuided
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
// inherit constructor
|
||||||
|
using ModeGuided::ModeGuided;
|
||||||
|
|
||||||
|
virtual void run() override;
|
||||||
|
|
||||||
|
bool init(bool ignore_checks) override;
|
||||||
|
bool requires_GPS() const override { return true; }
|
||||||
|
bool has_manual_throttle() const override { return false; }
|
||||||
|
bool allows_arming(bool from_gcs) const override { return true; }
|
||||||
|
bool is_autopilot() const override { return true; }
|
||||||
|
bool auto_loiter_start();
|
||||||
|
void auto_wp_start(const Vector3f& destination);
|
||||||
|
void auto_wp_start(const Location& dest_loc);
|
||||||
|
void auto_circle_movetoedge_start(const Location &circle_center, float radius_m, bool ccw_turn);
|
||||||
|
void auto_circle_start();
|
||||||
|
void auto_nav_guided_start();
|
||||||
|
void set_auto_yaw_roi(const Location &roi_location);
|
||||||
|
void set_auto_yaw_look_at_heading(float angle_deg, float turn_rate_dps, int8_t direction, uint8_t relative_angle);
|
||||||
|
bool auto_terrain_recover_start();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
const char *name() const override { return "AUTO"; }
|
||||||
|
const char *name4() const override { return "AUTO"; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void auto_wp_run();
|
||||||
|
void auto_circle_run();
|
||||||
|
void auto_nav_guided_run();
|
||||||
|
void auto_loiter_run();
|
||||||
|
void auto_terrain_recover_run();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class ModePoshold : public ModeAlthold
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
// inherit constructor
|
||||||
|
using ModeAlthold::ModeAlthold;
|
||||||
|
|
||||||
|
virtual void run() override;
|
||||||
|
|
||||||
|
bool init(bool ignore_checks) override;
|
||||||
|
|
||||||
|
bool requires_GPS() const override { return false; }
|
||||||
|
bool has_manual_throttle() const override { return false; }
|
||||||
|
bool allows_arming(bool from_gcs) const override { return true; }
|
||||||
|
bool is_autopilot() const override { return true; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
const char *name() const override { return "POSHOLD"; }
|
||||||
|
const char *name4() const override { return "POSH"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class ModeCircle : public Mode
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
// inherit constructor
|
||||||
|
using Mode::Mode;
|
||||||
|
|
||||||
|
virtual void run() override;
|
||||||
|
|
||||||
|
bool init(bool ignore_checks) override;
|
||||||
|
bool requires_GPS() const override { return true; }
|
||||||
|
bool has_manual_throttle() const override { return false; }
|
||||||
|
bool allows_arming(bool from_gcs) const override { return true; }
|
||||||
|
bool is_autopilot() const override { return true; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
const char *name() const override { return "CIRCLE"; }
|
||||||
|
const char *name4() const override { return "CIRC"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class ModeSurface : public Mode
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
// inherit constructor
|
||||||
|
using Mode::Mode;
|
||||||
|
|
||||||
|
virtual void run() override;
|
||||||
|
|
||||||
|
bool init(bool ignore_checks) override;
|
||||||
|
bool requires_GPS() const override { return true; }
|
||||||
|
bool has_manual_throttle() const override { return false; }
|
||||||
|
bool allows_arming(bool from_gcs) const override { return true; }
|
||||||
|
bool is_autopilot() const override { return true; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
const char *name() const override { return "SURFACE"; }
|
||||||
|
const char *name4() const override { return "SURF"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class ModeMotordetect : public Mode
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
// inherit constructor
|
||||||
|
using Mode::Mode;
|
||||||
|
|
||||||
|
virtual void run() override;
|
||||||
|
|
||||||
|
bool init(bool ignore_checks) override;
|
||||||
|
bool requires_GPS() const override { return true; }
|
||||||
|
bool has_manual_throttle() const override { return false; }
|
||||||
|
bool allows_arming(bool from_gcs) const override { return true; }
|
||||||
|
bool is_autopilot() const override { return true; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
const char *name() const override { return "MOTORDETECT"; }
|
||||||
|
const char *name4() const override { return "DETE"; }
|
||||||
|
};
|
|
@ -10,7 +10,7 @@ void Sub::enable_motor_output()
|
||||||
void Sub::motors_output()
|
void Sub::motors_output()
|
||||||
{
|
{
|
||||||
// Motor detection mode controls the thrusters directly
|
// Motor detection mode controls the thrusters directly
|
||||||
if (control_mode == MOTOR_DETECT){
|
if (control_mode == Mode::Number::MOTOR_DETECT){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// check if we are performing the motor test
|
// check if we are performing the motor test
|
||||||
|
|
Loading…
Reference in New Issue