-
Notifications
You must be signed in to change notification settings - Fork 17.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
AC_AttitudeControl: Add function to limit target attitude thrust angle #28316
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -275,6 +275,78 @@ void AC_AttitudeControl::landed_gain_reduction(bool landed) | |
set_angle_P_scale_mult(scale_mult); | ||
} | ||
|
||
// limit_target_thrust_angle - | ||
bool AC_AttitudeControl::limit_target_thrust_angle(float thrust_angle_max_cd) | ||
{ | ||
float thrust_angle_max_rad = radians(thrust_angle_max_cd * 0.01f); | ||
|
||
// attitude_body represents a quaternion rotation in NED frame to the body | ||
Quaternion attitude_body; | ||
_ahrs.get_quat_body_to_ned(attitude_body); | ||
|
||
Vector3f gyro = _ahrs.get_gyro_latest(); | ||
|
||
// angle_delta is the estimated rotation that the aircraft will experience during the correction | ||
Vector3f angle_delta = Vector3f{gyro.x / get_angle_roll_p().kP(), gyro.y / get_angle_pitch_p().kP(), gyro.z / get_angle_yaw_p().kP() }; | ||
|
||
// attitude_update represents a quaternion rotation representing the expected rotation in the next time_constant | ||
Quaternion attitude_update; | ||
attitude_update.from_axis_angle(angle_delta); | ||
attitude_body *= attitude_update; | ||
|
||
// The direction of thrust is [0,0,-1] is any body-fixed frame, inc. body frame and target frame. | ||
const Vector3f thrust_vector_up{0.0f, 0.0f, -1.0f}; | ||
|
||
// Rotating [0,0,-1] by attitude_body expresses (gets a view of) the thrust vector in the inertial frame | ||
Vector3f thrust_vec = attitude_body * thrust_vector_up; | ||
|
||
// the dot product is used to calculate the current lean angle | ||
float thrust_correction_angle = acosf(constrain_float(thrust_vec * thrust_vector_up, -1.0f, 1.0f)); | ||
|
||
if (abs(thrust_correction_angle) <= thrust_angle_max_rad) { | ||
return false; | ||
} | ||
|
||
// the cross product of the current thrust vector and vertical thrust vector defines the rotation vector | ||
Vector3f thrust_vec_cross = thrust_vec % thrust_vector_up; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you confirm that this vector is intended to be the target rotation vector to get back to upright? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK, I figured it out. The subsequent usage is consistent with that definition. |
||
|
||
// Normalize the thrust rotation vector | ||
if (thrust_vec_cross.is_zero()) { | ||
thrust_vec_cross.xy() = gyro.xy(); | ||
thrust_vec_cross.z = 0.0; | ||
if (thrust_vec_cross.is_zero()) { | ||
// choose recovery in the pitch axis | ||
const Vector3f y_axis{0.0f, 1.0f, 0.0f}; | ||
thrust_vec_cross = _attitude_target * y_axis; | ||
} else { | ||
// choose recovery in the current rotation direction | ||
thrust_vec_cross.normalize(); | ||
} | ||
} else { | ||
thrust_vec_cross.normalize(); | ||
} | ||
|
||
// subtract the maximum lean angle from the current thrust angle | ||
thrust_correction_angle -= constrain_float(thrust_correction_angle, -thrust_angle_max_rad, thrust_angle_max_rad); | ||
|
||
// calculate the closest _attitude_target using roll and pitch only, with a thrust angle of thrust_angle_max_rad | ||
Quaternion attitude_target_offset; | ||
attitude_target_offset.from_axis_angle(thrust_vec_cross, thrust_correction_angle); | ||
_attitude_target = attitude_target_offset * attitude_body; | ||
|
||
// Set angular velocity targets when further than 1.25 * thrust_angle_max_cd | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Based on my reading of this code this would be more accurately described as:
|
||
// this ensures small angles past thrust_angle_max_cd do not zero angular velocity targets and prevent full recovery | ||
// angular velocity targets must be zeroed at large thrust angles to prevent them from preventing efficient recovery | ||
float ang_vel_scalar = 0.0; | ||
if (!is_zero(thrust_angle_max_rad)) { | ||
ang_vel_scalar = MAX( 0.0, 1.0f - (abs(thrust_correction_angle) / (0.25 * thrust_angle_max_rad))); | ||
} | ||
_ang_vel_target *= ang_vel_scalar; | ||
ang_vel_to_euler_rate(_attitude_target, _ang_vel_target, _euler_rate_target); | ||
|
||
return true; | ||
} | ||
|
||
// The attitude controller works around the concept of the desired attitude, target attitude | ||
// and measured attitude. The desired attitude is the attitude input into the attitude controller | ||
// that expresses where the higher level code would like the aircraft to move to. The target attitude is moved | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we be using the new
_rate_gyro
variable that was recently added?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe so.