diff --git a/src/modules/mc_pos_control/PositionControl/ControlMath.cpp b/src/modules/mc_pos_control/PositionControl/ControlMath.cpp index b4eba96115..346a53f79e 100644 --- a/src/modules/mc_pos_control/PositionControl/ControlMath.cpp +++ b/src/modules/mc_pos_control/PositionControl/ControlMath.cpp @@ -44,9 +44,20 @@ using namespace matrix; namespace ControlMath { + void thrustToAttitude(const Vector3f &thr_sp, const float yaw_sp, vehicle_attitude_setpoint_s &att_sp) { - bodyzToAttitude(-thr_sp, yaw_sp, att_sp); + const Quatf q = bodyzToQuaternion(thr_sp, yaw_sp); + + // copy quaternion setpoint to attitude setpoint topic + q.copyTo(att_sp.q_d); + + // calculate euler angles, for logging only, must not be used for control + const Eulerf euler{q}; + att_sp.roll_body = euler.phi(); + att_sp.pitch_body = euler.theta(); + att_sp.yaw_body = euler.psi(); + att_sp.thrust_body[2] = -thr_sp.length(); } @@ -67,56 +78,16 @@ void limitTilt(Vector3f &body_unit, const Vector3f &world_unit, const float max_ body_unit = cosf(angle) * world_unit + sinf(angle) * rejection.unit(); } -void bodyzToAttitude(Vector3f body_z, const float yaw_sp, vehicle_attitude_setpoint_s &att_sp) +Quatf bodyzToQuaternion(Vector3f body_z, const float yaw_sp) { // zero vector, no direction, set safe level value if (body_z.norm_squared() < FLT_EPSILON) { - body_z(2) = 1.f; + body_z(2) = -1.f; } - body_z.normalize(); - - // vector of desired yaw direction in XY plane, rotated by PI/2 - const Vector3f y_C{-sinf(yaw_sp), cosf(yaw_sp), 0.f}; - - // desired body_x axis, orthogonal to body_z - Vector3f body_x = y_C % body_z; - - // keep nose to front while inverted upside down - if (body_z(2) < 0.f) { - body_x = -body_x; - } - - if (fabsf(body_z(2)) < 0.000001f) { - // desired thrust is in XY plane, set X downside to construct correct matrix, - // but yaw component will not be used actually - body_x.zero(); - body_x(2) = 1.f; - } - - body_x.normalize(); - - // desired body_y axis - const Vector3f body_y = body_z % body_x; - - Dcmf R_sp; - - // fill rotation matrix - for (int i = 0; i < 3; i++) { - R_sp(i, 0) = body_x(i); - R_sp(i, 1) = body_y(i); - R_sp(i, 2) = body_z(i); - } - - // copy quaternion setpoint to attitude setpoint topic - const Quatf q_sp{R_sp}; - q_sp.copyTo(att_sp.q_d); - - // calculate euler angles, for logging only, must not be used for control - const Eulerf euler{R_sp}; - att_sp.roll_body = euler.phi(); - att_sp.pitch_body = euler.theta(); - att_sp.yaw_body = euler.psi(); + const Quatf q{Vector3f(0.f, 0.f, -1.f), body_z}; + const Quatf q_yaw{cosf(yaw_sp / 2.f), 0.f, 0.f, sinf(yaw_sp / 2.f)}; + return q * q_yaw; } Vector2f constrainXY(const Vector2f &v0, const Vector2f &v1, const float &max) diff --git a/src/modules/mc_pos_control/PositionControl/ControlMath.hpp b/src/modules/mc_pos_control/PositionControl/ControlMath.hpp index c2d9b8b7f8..cef360144b 100644 --- a/src/modules/mc_pos_control/PositionControl/ControlMath.hpp +++ b/src/modules/mc_pos_control/PositionControl/ControlMath.hpp @@ -69,6 +69,8 @@ void limitTilt(matrix::Vector3f &body_unit, const matrix::Vector3f &world_unit, */ void bodyzToAttitude(matrix::Vector3f body_z, const float yaw_sp, vehicle_attitude_setpoint_s &att_sp); +matrix::Quatf bodyzToQuaternion(matrix::Vector3f body_z, const float yaw_sp); + /** * Outputs the sum of two vectors but respecting the limits and priority. * The sum of two vectors are constraint such that v0 has priority over v1.