23 #ifndef MAV_MSGS_COMMON_H 24 #define MAV_MSGS_COMMON_H 26 #include <geometry_msgs/Point.h> 27 #include <geometry_msgs/Quaternion.h> 28 #include <geometry_msgs/Vector3.h> 29 #include <Eigen/Geometry> 30 #include <boost/algorithm/clamp.hpp> 40 const double latitude_radians) {
42 const double kGravity_0 = 9.780327;
43 const double kGravity_a = 0.0053024;
44 const double kGravity_b = 0.0000058;
45 const double kGravity_c = 3.155 * 1e-7;
47 double sin_squared_latitude = std::sin(latitude_radians) * std::sin(latitude_radians);
48 double sin_squared_twice_latitude =
49 std::sin(2 * latitude_radians) * std::sin(2 * latitude_radians);
50 return kGravity_0 * ((1 + kGravity_a * sin_squared_latitude -
51 kGravity_b * sin_squared_twice_latitude) -
56 return Eigen::Vector3d(msg.x, msg.y, msg.z);
60 return Eigen::Vector3d(msg.x, msg.y, msg.z);
64 const geometry_msgs::Quaternion& msg) {
67 Eigen::Quaterniond quaternion(msg.w, msg.x, msg.y, msg.z);
68 if (quaternion.norm() < std::numeric_limits<double>::epsilon()) {
69 quaternion.setIdentity();
71 quaternion.normalize();
77 geometry_msgs::Vector3* msg) {
85 geometry_msgs::Point* msg) {
93 geometry_msgs::Quaternion* msg) {
108 return std::atan2(2.0 * (q.w() * q.z() + q.x() * q.y()),
109 1.0 - 2.0 * (q.y() * q.y() + q.z() * q.z()));
113 return Eigen::Quaterniond(Eigen::AngleAxisd(yaw, Eigen::Vector3d::UnitZ()));
117 geometry_msgs::Quaternion* msg) {
127 geometry_msgs::Vector3* msg) {
135 Eigen::Vector3d* euler_angles) {
137 assert(euler_angles != NULL);
139 *euler_angles << std::atan2(2.0 * (q.w() * q.x() + q.y() * q.z()),
140 1.0 - 2.0 * (q.x() * q.x() + q.y() * q.y())),
141 std::asin(2.0 * (q.w() * q.y() - q.z() * q.x())),
142 std::atan2(2.0 * (q.w() * q.z() + q.x() * q.y()),
143 1.0 - 2.0 * (q.y() * q.y() + q.z() * q.z()));
148 Eigen::Matrix3d* vec_skew) {
150 *vec_skew << 0.0f, -vec(2), vec(1), vec(2), 0.0f, -vec(0), -vec(1), vec(0),
155 Eigen::Vector3d* vec) {
158 *vec << vec_skew(2,1), vec_skew(0,2), vec_skew(1,0);
161 std::cerr <<
"[mav_msgs] Matrix is not skew-symmetric." << std::endl;
162 *vec = Eigen::Vector3d::Zero();
169 if ((mat.transpose() * mat - Eigen::Matrix3d::Identity()).norm() >
kSmallValueCheck){
170 std::cerr <<
"[mav_msgs::common] Rotation matrix requirement violated (R^T * R = I)" << std::endl;
175 std::cerr <<
"[mav_msgs::common] Rotation matrix requirement violated (det(R) = 1)" << std::endl;
185 Eigen::Matrix3d* mat) {
189 double r_norm = vec.norm();
190 Eigen::Matrix3d vec_skew_norm = Eigen::Matrix3d::Zero();
195 *mat = Eigen::Matrix3d::Identity() + vec_skew_norm * std::sin(r_norm) +
196 vec_skew_norm * vec_skew_norm * (1 - std::cos(r_norm));
203 Eigen::Vector3d* vec) {
210 std::cerr <<
"[mav_msgs::common] Not a rotation matrix." << std::endl;
214 if ((mat - Eigen::Matrix3d::Identity()).norm() < kSmallValueCheck){
215 *vec = Eigen::Vector3d::Zero();
220 double cos_phi = (mat.trace() - 1.0) / 2.0;
221 double cos_phi_clamped = boost::algorithm::clamp(cos_phi, -1.0, 1.0);
222 double phi = std::acos(cos_phi_clamped);
224 if (phi < kSmallValueCheck){
225 *vec = Eigen::Vector3d::Zero();
227 Eigen::Matrix3d vec_skew = (mat - mat.transpose()) * phi / (2.0 * std::sin(phi));
228 Eigen::Vector3d vec_unskewed;
243 const Eigen::Vector3d& rot_vec,
const Eigen::Vector3d& rot_vec_vel)
245 double phi = rot_vec.norm();
246 if (std::abs(phi) < 1.0e-3) {
251 double phi_inv = 1.0 / phi;
252 double phi_2_inv = phi_inv / phi;
253 double phi_3_inv = phi_2_inv / phi;
256 Eigen::Matrix3d phi_skew;
261 W = Eigen::MatrixXd::Identity(3, 3) + phi_skew * (1 - std::cos(phi)) * phi_2_inv +
262 phi_skew * phi_skew * (phi - std::sin(phi)) * phi_3_inv;
263 return W * rot_vec_vel;
270 const Eigen::Vector3d& rot_vec,
const Eigen::Vector3d& rot_vec_vel,
271 const Eigen::Vector3d& rot_vec_acc)
273 double phi = rot_vec.norm();
274 if (std::abs(phi) < 1.0e-3) {
279 double phi_dot = rot_vec.dot(rot_vec_vel) / phi;
281 double phi_inv = 1.0 / phi;
282 double phi_2_inv = phi_inv / phi;
283 double phi_3_inv = phi_2_inv / phi;
284 double phi_4_inv = phi_3_inv / phi;
288 Eigen::Matrix3d phi_skew;
289 Eigen::Matrix3d phi_dot_skew;
295 Eigen::Matrix3d W_vel;
296 Eigen::Matrix3d W_acc;
297 W_vel = phi_skew * (phi * std::sin(phi) - 2.0f + 2.0f * std::cos(phi)) * phi_dot *
299 phi_skew * phi_skew *
300 (-2.0f * phi - phi * std::cos(phi) + 3.0f * std::sin(phi)) * phi_dot *
302 phi_dot_skew * phi_skew * (phi - std::sin(phi)) * phi_3_inv;
304 W_acc = Eigen::MatrixXd::Identity(3, 3) +
305 phi_skew * (1.0f - std::cos(phi)) * phi_2_inv +
306 phi_skew * phi_skew * (phi - std::sin(phi)) * phi_3_inv;
308 return W_vel * rot_vec_vel + W_acc * rot_vec_acc;
335 const Eigen::MatrixXd& allocation_inv,
const Eigen::Vector3d& inertia,
336 double mass,
const Eigen::Vector3d& angular_velocity_B,
337 const Eigen::Vector3d& angular_acceleration_B,
338 const Eigen::Vector3d& acceleration_B,
339 Eigen::VectorXd* rotor_rates_squared) {
340 const Eigen::Vector3d torque =
341 inertia.asDiagonal() * angular_acceleration_B +
342 angular_velocity_B.cross(inertia.asDiagonal() * angular_velocity_B);
343 const double thrust_force = mass * acceleration_B.norm();
344 Eigen::Vector4d input;
345 input << torque, thrust_force;
346 *rotor_rates_squared = allocation_inv * input;
355 int64_t nanoseconds =
362 #endif // MAV_MSGS_COMMON_H void quaternionEigenToMsg(const Eigen::Quaterniond &eigen, geometry_msgs::Quaternion *msg)
double MagnitudeOfGravity(const double height, const double latitude_radians)
bool vectorFromRotationMatrix(const Eigen::Matrix3d &mat, Eigen::Vector3d *vec)
void setAngularVelocityMsgFromYawRate(double yaw_rate, geometry_msgs::Vector3 *msg)
Eigen::Vector3d omegaFromRotationVector(const Eigen::Vector3d &rot_vec, const Eigen::Vector3d &rot_vec_vel)
void getSquaredRotorSpeedsFromAllocationAndState(const Eigen::MatrixXd &allocation_inv, const Eigen::Vector3d &inertia, double mass, const Eigen::Vector3d &angular_velocity_B, const Eigen::Vector3d &angular_acceleration_B, const Eigen::Vector3d &acceleration_B, Eigen::VectorXd *rotor_rates_squared)
void skewMatrixFromVector(const Eigen::Vector3d &vec, Eigen::Matrix3d *vec_skew)
Eigen::Vector3d vector3FromMsg(const geometry_msgs::Vector3 &msg)
void setQuaternionMsgFromYaw(double yaw, geometry_msgs::Quaternion *msg)
const double kNumNanosecondsPerSecond
void getEulerAnglesFromQuaternion(const Eigen::Quaternion< double > &q, Eigen::Vector3d *euler_angles)
bool vectorFromSkewMatrix(const Eigen::Matrix3d &vec_skew, Eigen::Vector3d *vec)
bool isRotationMatrix(const Eigen::Matrix3d &mat)
int64_t secondsToNanoseconds(double seconds)
double nanosecondsToSeconds(int64_t nanoseconds)
double yawFromQuaternion(const Eigen::Quaterniond &q)
Extracts the yaw part from a quaternion, using RPY / euler (z-y'-z'') angles. RPY rotates about the f...
void vectorEigenToMsg(const Eigen::Vector3d &eigen, geometry_msgs::Vector3 *msg)
Eigen::Quaterniond quaternionFromMsg(const geometry_msgs::Quaternion &msg)
const double kSmallValueCheck
Eigen::Vector3d vector3FromPointMsg(const geometry_msgs::Point &msg)
Eigen::Quaterniond quaternionFromYaw(double yaw)
void matrixFromRotationVector(const Eigen::Vector3d &vec, Eigen::Matrix3d *mat)
Eigen::Vector3d omegaDotFromRotationVector(const Eigen::Vector3d &rot_vec, const Eigen::Vector3d &rot_vec_vel, const Eigen::Vector3d &rot_vec_acc)
void pointEigenToMsg(const Eigen::Vector3d &eigen, geometry_msgs::Point *msg)