diff --git a/src/modules/mc_att_control_vector/mc_att_control_vector_main.cpp b/src/modules/mc_att_control_vector/mc_att_control_vector_main.cpp index 93806165d2..bc75885c2d 100644 --- a/src/modules/mc_att_control_vector/mc_att_control_vector_main.cpp +++ b/src/modules/mc_att_control_vector/mc_att_control_vector_main.cpp @@ -540,21 +540,24 @@ MulticopterAttitudeControl::task_main() math::Vector3 rates(_att.rollspeed, _att.pitchspeed, _att.yawspeed); /* try to move thrust vector shortest way, because yaw response is slower than roll/pitch */ - /* angle error between current and desired thrust vectors (Z axes) */ + /* sin(angle error) between current and desired thrust vectors (Z axes) */ math::Vector3 R_z(R(0, 2), R(1, 2), R(2, 2)); math::Vector3 R_z_des(R_des(0, 2), R_des(1, 2), R_des(2, 2)); - math::Vector3 e_R = R_z.cross(R_z_des); + math::Vector3 e_R = R.transpose() * R_z.cross(R_z_des); - /* convert angle error from NED to bady frame */ - e_R = R.transpose() * e_R; + /* calculate angle error */ + float e_R_sin = e_R.norm(); + float e_R_cos = R_z * R_z_des; + float angle = atan2f(e_R_sin, e_R_cos); /* e_R has zero Z component, set it according to yaw */ /* calculate rotation matrix after roll/pitch only rotation */ math::Matrix R_rp(3, 3); - float e_R_angle = e_R.norm(); - if (e_R_angle > 0.0f) { + + if (e_R_sin > 0.0f) { /* get axis-angle representation */ - math::Vector3 e_R_axis = e_R / e_R_angle; + math::Vector3 e_R_axis = e_R / e_R_sin; + /* cross product matrix for e_R_axis */ math::Matrix e_R_cp(3, 3); e_R_cp.setAll(0.0f); @@ -564,13 +567,14 @@ MulticopterAttitudeControl::task_main() e_R_cp(1, 2) = -e_R_axis(0); e_R_cp(2, 0) = -e_R_axis(1); e_R_cp(2, 1) = e_R_axis(0); + /* rotation matrix for roll/pitch only rotation */ math::Matrix I(3, 3); I.setAll(0.0f); I(0, 0) = 1.0f; I(1, 1) = 1.0f; I(2, 2) = 1.0f; - R_rp = R * (I + e_R_cp * sinf(e_R_angle) + e_R_cp * e_R_cp * (1.0f - cosf(e_R_angle))); + R_rp = R * (I + e_R_cp * e_R_sin + e_R_cp * e_R_cp * (1.0f - e_R_cos)); } else { /* zero roll/pitch rotation */ R_rp = R; @@ -582,6 +586,9 @@ MulticopterAttitudeControl::task_main() math::Vector3 R_rp_x(R_rp(0, 0), R_rp(1, 0), R_rp(2, 0)); e_R(2) = R_rp_x.cross(R_des_x) * R_des_z; + /* don't try to control yaw when thrust vector has opposite direction to desired */ + e_R(2) *= (e_R_cos > 0.0f ? 1.0f : e_R_sin); + /* angular rates setpoint*/ math::Vector3 rates_sp = _K * e_R; /* feed forward yaw setpoint rate */