|
|
|
@ -540,21 +540,24 @@ MulticopterAttitudeControl::task_main()
@@ -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()
@@ -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()
@@ -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 */ |
|
|
|
|