Program Listing for File euler.hpp
↰ Return to documentation for file (include/bitbots_splines/euler.hpp
)
/*
This code is largely based on the original code by Quentin "Leph" Rouxel and Team Rhoban.
The original files can be found at:
https://github.com/Rhoban/model/
*/
#ifndef EULER_H
#define EULER_H
#include <Eigen/Dense>
#include <Eigen/Geometry>
#include <stdexcept>
namespace bitbots_splines {
enum EulerType {
EulerYawPitchRoll,
EulerYawRollPitch,
EulerRollPitchYaw,
EulerRollYawPitch,
EulerPitchRollYaw,
EulerPitchYawRoll,
};
inline bool CheckEulerBounds(const Eigen::Vector3d &angles) {
return (angles(0) >= -M_PI && angles(0) <= M_PI) &&
((angles(1) > -M_PI / 2.0 && angles(1) < M_PI / 2.0) ||
(angles(0) == 0 && angles(2) == 0 && (angles(1) == -M_PI / 2.0 || angles(1) == M_PI / 2.0))) &&
(angles(2) >= 0.0 && angles(2) <= M_PI);
}
inline Eigen::Matrix3d EulerToMatrix(const Eigen::Vector3d &angles, EulerType eulerType) {
Eigen::Quaternion<double> quat;
switch (eulerType) {
case EulerYawPitchRoll: {
Eigen::AngleAxisd yawRot(angles(0), Eigen::Vector3d::UnitZ());
Eigen::AngleAxisd pitchRot(angles(1), Eigen::Vector3d::UnitY());
Eigen::AngleAxisd rollRot(angles(2), Eigen::Vector3d::UnitX());
quat = rollRot * pitchRot * yawRot;
} break;
case EulerYawRollPitch: {
Eigen::AngleAxisd yawRot(angles(0), Eigen::Vector3d::UnitZ());
Eigen::AngleAxisd pitchRot(angles(2), Eigen::Vector3d::UnitY());
Eigen::AngleAxisd rollRot(angles(1), Eigen::Vector3d::UnitX());
quat = pitchRot * rollRot * yawRot;
} break;
case EulerRollPitchYaw: {
Eigen::AngleAxisd yawRot(angles(2), Eigen::Vector3d::UnitZ());
Eigen::AngleAxisd pitchRot(angles(1), Eigen::Vector3d::UnitY());
Eigen::AngleAxisd rollRot(angles(0), Eigen::Vector3d::UnitX());
quat = yawRot * pitchRot * rollRot;
} break;
case EulerRollYawPitch: {
Eigen::AngleAxisd yawRot(angles(1), Eigen::Vector3d::UnitZ());
Eigen::AngleAxisd pitchRot(angles(2), Eigen::Vector3d::UnitY());
Eigen::AngleAxisd rollRot(angles(0), Eigen::Vector3d::UnitX());
quat = pitchRot * yawRot * rollRot;
} break;
case EulerPitchRollYaw: {
Eigen::AngleAxisd yawRot(angles(2), Eigen::Vector3d::UnitZ());
Eigen::AngleAxisd pitchRot(angles(0), Eigen::Vector3d::UnitY());
Eigen::AngleAxisd rollRot(angles(1), Eigen::Vector3d::UnitX());
quat = yawRot * rollRot * pitchRot;
} break;
case EulerPitchYawRoll: {
Eigen::AngleAxisd yawRot(angles(1), Eigen::Vector3d::UnitZ());
Eigen::AngleAxisd pitchRot(angles(0), Eigen::Vector3d::UnitY());
Eigen::AngleAxisd rollRot(angles(2), Eigen::Vector3d::UnitX());
quat = rollRot * yawRot * pitchRot;
} break;
default: {
throw std::logic_error("Euler invalid type");
}
}
return quat.matrix();
}
inline Eigen::Vector3d MatrixToEuler(const Eigen::Matrix3d &mat, EulerType eulerType) {
Eigen::Vector3d tmp(0.0, 0.0, 0.0);
switch (eulerType) {
case EulerYawPitchRoll: {
tmp = mat.eulerAngles(0, 1, 2);
} break;
case EulerYawRollPitch: {
tmp = mat.eulerAngles(1, 0, 2);
} break;
case EulerRollPitchYaw: {
tmp = mat.eulerAngles(2, 1, 0);
} break;
case EulerRollYawPitch: {
tmp = mat.eulerAngles(1, 2, 0);
} break;
case EulerPitchRollYaw: {
tmp = mat.eulerAngles(2, 0, 1);
} break;
case EulerPitchYawRoll: {
tmp = mat.eulerAngles(0, 2, 1);
} break;
}
Eigen::Vector3d angles;
angles(0) = tmp(2);
angles(1) = tmp(1);
angles(2) = tmp(0);
return angles;
}
inline Eigen::Vector3d MatrixToEulerIntrinsic(const Eigen::Matrix3d &mat) {
// Eigen euler angles and with better range)
Eigen::Vector3d angles;
// Roll
angles.x() = atan2(mat(2, 1), mat(2, 2));
// Pitch
angles.y() = atan2(-mat(2, 0), sqrt(mat(0, 0) * mat(0, 0) + mat(1, 0) * mat(1, 0)));
// Yaw
angles.z() = atan2(mat(1, 0), mat(0, 0));
return angles;
}
inline Eigen::Matrix3d EulerIntrinsicToMatrix(const Eigen::Vector3d &angles) {
Eigen::AngleAxisd yawRot(angles.z(), Eigen::Vector3d::UnitZ());
Eigen::AngleAxisd pitchRot(angles.y(), Eigen::Vector3d::UnitY());
Eigen::AngleAxisd rollRot(angles.x(), Eigen::Vector3d::UnitX());
Eigen::Quaternion<double> quat = yawRot * pitchRot * rollRot;
return quat.matrix();
}
} // namespace bitbots_splines
#endif