|
|
|
@ -1,6 +1,7 @@
@@ -1,6 +1,7 @@
|
|
|
|
|
#include "AC_AttitudeControl.h" |
|
|
|
|
#include <AP_HAL/AP_HAL.h> |
|
|
|
|
#include <AP_Math/AP_Math.h> |
|
|
|
|
|
|
|
|
|
extern const AP_HAL::HAL& hal; |
|
|
|
|
|
|
|
|
|
#if APM_BUILD_TYPE(APM_BUILD_ArduPlane) |
|
|
|
|
// default gains for Plane
|
|
|
|
@ -1007,3 +1008,68 @@ float AC_AttitudeControl::max_rate_step_bf_yaw()
@@ -1007,3 +1008,68 @@ float AC_AttitudeControl::max_rate_step_bf_yaw()
|
|
|
|
|
float throttle_hover = constrain_float(_motors.get_throttle_hover(), 0.1f, 0.5f); |
|
|
|
|
return 2.0f*throttle_hover*AC_ATTITUDE_RATE_YAW_CONTROLLER_OUT_MAX/((alpha_remaining*alpha_remaining*alpha_remaining*alpha*get_rate_yaw_pid().kD())/_dt + get_rate_yaw_pid().kP()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool AC_AttitudeControl::pre_arm_checks(const char *param_prefix, |
|
|
|
|
char *failure_msg, |
|
|
|
|
const uint8_t failure_msg_len) |
|
|
|
|
{ |
|
|
|
|
// validate AC_P members:
|
|
|
|
|
const struct { |
|
|
|
|
const char *pid_name; |
|
|
|
|
AC_P &p; |
|
|
|
|
} ps[] = { |
|
|
|
|
{ "ANG_PIT", get_angle_pitch_p() }, |
|
|
|
|
{ "ANG_RLL", get_angle_roll_p() }, |
|
|
|
|
{ "ANG_YAW", get_angle_yaw_p() } |
|
|
|
|
}; |
|
|
|
|
for (uint8_t i=0; i<ARRAY_SIZE(ps); i++) { |
|
|
|
|
// all AC_P's must have a positive P value:
|
|
|
|
|
if (!is_positive(ps[i].p.kP())) { |
|
|
|
|
hal.util->snprintf(failure_msg, failure_msg_len, "%s_%s_P must be > 0", param_prefix, ps[i].pid_name); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// validate AC_PID members:
|
|
|
|
|
const struct { |
|
|
|
|
const char *pid_name; |
|
|
|
|
AC_PID &pid; |
|
|
|
|
} pids[] = { |
|
|
|
|
{ "RAT_RLL", get_rate_roll_pid() }, |
|
|
|
|
{ "RAT_PIT", get_rate_pitch_pid() }, |
|
|
|
|
{ "RAT_YAW", get_rate_yaw_pid() }, |
|
|
|
|
}; |
|
|
|
|
for (uint8_t i=0; i<ARRAY_SIZE(pids); i++) { |
|
|
|
|
// if the PID has a positive FF then we just ensure kP and
|
|
|
|
|
// kI aren't negative
|
|
|
|
|
AC_PID &pid = pids[i].pid; |
|
|
|
|
const char *pid_name = pids[i].pid_name; |
|
|
|
|
if (is_positive(pid.ff())) { |
|
|
|
|
// kP and kI must be non-negative:
|
|
|
|
|
if (is_negative(pid.kP())) { |
|
|
|
|
hal.util->snprintf(failure_msg, failure_msg_len, "%s_%s_P must be >= 0", param_prefix, pid_name); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
if (is_negative(pid.kI())) { |
|
|
|
|
hal.util->snprintf(failure_msg, failure_msg_len, "%s_%s_I must be >= 0", param_prefix, pid_name); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
// kP and kI must be positive:
|
|
|
|
|
if (!is_positive(pid.kP())) { |
|
|
|
|
hal.util->snprintf(failure_msg, failure_msg_len, "%s_%s_P must be > 0", param_prefix, pid_name); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
if (!is_positive(pid.kI())) { |
|
|
|
|
hal.util->snprintf(failure_msg, failure_msg_len, "%s_%s_I must be > 0", param_prefix, pid_name); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
// never allow a negative D term (but zero is allowed)
|
|
|
|
|
if (is_negative(pid.kD())) { |
|
|
|
|
hal.util->snprintf(failure_msg, failure_msg_len, "%s_%s_D must be >= 0", param_prefix, pid_name); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|