源码
网上查找了挺久机器人位姿与齐次矩阵之间的变换算法,但一直没找到理想的,这里自己做了实现,做过简单验证,但还可能存在问题,欢迎大家评论区指正讨论~
跳过理论,直接放代码了:
common.h
#ifndef COMMON_H
#define COMMON_H
#include <math.h>
#ifndef M_PI
#define M_PI std::acos(-1)
#endif // !M_PI
/// <summary>
/// 旋转角顺序
/// </summary>
enum class E_ROTATION_SEQUENCE
{
E_SEQ_XYZ = 0,
E_SEQ_ZYX = 1
};
/// <summary>
/// 旋转角角度单位类型(degree/radian)
/// </summary>
enum class E_ANGLE_TYPE
{
E_TYPE_DEGREE = 0,
E_TYPE_RADIAN = 1
};
/// <summary>
/// 位姿结构体
/// </summary>
struct S_POSE
{
public:
explicit S_POSE(double x, double y, double z, double rx, double ry, double rz)
:X(x), Y(y), Z(z), Rx(rx), Ry(ry), Rz(rz) {};
public:
double X; double Y; double Z;
double Rx; double Ry; double Rz;
};
#endif // !COMMON_H
transformation_eg.h
/*****************************************************************************
* @file transformation_eg.h *
* @brief 用Eigen实现三维空间中位姿与矩阵之间的变换 *
* Details. 具体包括旋转角、旋转矩阵、齐次矩阵之间的变换 *
* 在固定角坐标系下描述旋转角顺序 *
* *
* @author Chan_XM *
* @email chan_xm14@163.com *
* @version V1.0 *
* @date 2024/11/16 *
* @license NON *
*****************************************************************************/
#ifndef TRANSFORMATION_EG_H
#define TRANSFORMATION_EG_H
#include <Eigen/Dense>
#include <Eigen/Geometry>
#include "common.h"
class CTransformation_EG
{
public:
/// <summary>
/// 角度转弧度
/// </summary>
/// <param name="degree">角度(-180 180)</param>
/// <returns>弧度(-3.14 3.14)</returns>
static double degree2Radian(const double& degree);
/// <summary>
/// 弧度转角度
/// </summary>
/// <param name="radian">弧度(-3.14 3.14)</param>
/// <returns>角度(-180 180)</returns>
static double radian2Degree(const double& radian);
/// <summary>
/// 旋转角(degree)-> 旋转矩阵 默认按照X-Y-Z固定角坐标系(或Z-Y-X欧拉角坐标系 二者等价)转换
/// </summary>
/// <param name="rx">绕X轴旋转角</param>
/// <param name="ry">绕Y轴旋转角</param>
/// <param name="rz">绕Z轴旋转角</param>
/// <param name="rotSeq">固定角坐标系描述下的旋转顺序(与欧拉角坐标系反向)</param>
/// <returns>旋转矩阵(3x3)</returns>
static Eigen::Matrix3d rotDegree2Matrix(double rx, double ry, double rz, const E_ROTATION_SEQUENCE& rotSeq = E_ROTATION_SEQUENCE::E_SEQ_XYZ);
/// <summary>
/// 旋转角(radian)-> 旋转矩阵 默认按照X-Y-Z固定角坐标系(或Z-Y-X欧拉角坐标系 二者等价)转换
/// </summary>
/// <param name="rx">绕X轴旋转角</param>
/// <param name="ry">绕Y轴旋转角</param>
/// <param name="rz">绕Z轴旋转角</param>
/// <param name="rotSeq">固定角坐标系描述下的旋转顺序(与欧拉角坐标系反向)</param>
/// <returns>旋转矩阵(3x3)</returns>
static Eigen::Matrix3d rotRadian2Matrix(double rx, double ry, double rz, const E_ROTATION_SEQUENCE& rotSeq = E_ROTATION_SEQUENCE::E_SEQ_XYZ);
/// <summary>
/// 旋转矩阵 -> 旋转角(degree)默认按照X-Y-Z固定角坐标系(或Z-Y-X欧拉角坐标系 二者等价)转换
/// </summary>
/// <param name="matrix">旋转矩阵</param>
/// <param name="rotSeq">固定角坐标系描述下的旋转顺序(与欧拉角坐标系反向)</param>
/// <returns>旋转角(degree)</returns>
static Eigen::Vector3d rotMatrix2RotDegree(const Eigen::Matrix3d& matrix, const E_ROTATION_SEQUENCE& rotSeq = E_ROTATION_SEQUENCE::E_SEQ_XYZ);
/// <summary>
/// 旋转矩阵 -> 旋转角(Radian)默认按照X-Y-Z固定角坐标系(或Z-Y-X欧拉角坐标系 二者等价)转换
/// </summary>
/// <param name="matrix">旋转矩阵</param>
/// <param name="rotSeq">固定角坐标系描述下的旋转顺序(与欧拉角坐标系反向)</param>
/// <returns>旋转角(Radian)</returns>
static Eigen::Vector3d rotMatrix2RotRadian(const Eigen::Matrix3d& matrix, const E_ROTATION_SEQUENCE& rotSeq = E_ROTATION_SEQUENCE::E_SEQ_XYZ);
/// <summary>
/// 位姿 -> 齐次矩阵
/// </summary>
/// <param name="x">X</param>
/// <param name="y">Y</param>
/// <param name="z">Z</param>
/// <param name="rx">Rx</param>
/// <param name="ry">Ry</param>
/// <param name="rz">Rz</param>
/// <param name="rotSeq">旋转角顺序 默认按照X-Y-Z固定角坐标系(或Z-Y-X欧拉角坐标系 二者等价) </param>
/// <param name="angleType">角度单位 默认为degree</param>
/// <returns>齐次矩阵(4x4)</returns>
static Eigen::Matrix4d pose2HmMatrix(double x, double y, double z, double rx, double ry, double rz,
const E_ROTATION_SEQUENCE& rotSeq = E_ROTATION_SEQUENCE::E_SEQ_XYZ,
const E_ANGLE_TYPE& angleType = E_ANGLE_TYPE::E_TYPE_DEGREE);
/// <summary>
/// 位姿转齐次矩阵
/// </summary>
/// <param name="pose">位姿(包含X Y Z Rx Ry Rz)</param>
/// <param name="rotSeq">旋转角顺序 默认按照X-Y-Z固定角坐标系(或Z-Y-X欧拉角坐标系 二者等价)</param>
/// <param name="angleType">角度单位 默认为degree</param>
/// <returns>齐次矩阵(4x4)</returns>
static Eigen::Matrix4d pose2HmMatrix(const S_POSE& pose,
const E_ROTATION_SEQUENCE& rotSeq = E_ROTATION_SEQUENCE::E_SEQ_XYZ,
const E_ANGLE_TYPE& angleType = E_ANGLE_TYPE::E_TYPE_DEGREE);
/// <summary>
/// 齐次矩阵转为位姿
/// </summary>
/// <param name="hmMatrix">齐次矩阵(4x4)</param>
/// <param name="rotSeq">旋转角顺序 默认按照X-Y-Z固定角坐标系(或Z-Y-X欧拉角坐标系 二者等价)</param>
/// <param name="angleType">角度单位 默认为degree</param>
/// <returns>位姿(包含X Y Z Rx Ry Rz)</returns>
static S_POSE hmMatrix2Pose(const Eigen::Matrix4d& hmMatrix,
const E_ROTATION_SEQUENCE& rotSeq = E_ROTATION_SEQUENCE::E_SEQ_XYZ,
const E_ANGLE_TYPE& angleType = E_ANGLE_TYPE::E_TYPE_DEGREE);
};
#endif // !TRANSFORMATION_EG_H
transformation_eg.cpp
/*****************************************************************************
* @file transformation_eg.cpp *
* @brief 用Eigen实现三维空间中位姿与矩阵之间的变换 *
* *
* @author Chan_XM *
* @email chan_xm14@163.com *
* @version V1.0 *
* @date 2024/11/16 *
* @license NON *
*****************************************************************************/
#include "transformation_eg.h"
#include <iostream>
double CTransformation_EG::degree2Radian(const double& degree)
{
return degree * M_PI / 180;
}
double CTransformation_EG::radian2Degree(const double& radian)
{
return radian * 180 / M_PI;
}
Eigen::Matrix3d CTransformation_EG::rotDegree2Matrix(double rx, double ry, double rz, const E_ROTATION_SEQUENCE& rotSeq)
{
rx = degree2Radian(rx);
ry = degree2Radian(ry);
rz = degree2Radian(rz);
return CTransformation_EG::rotRadian2Matrix(rx, ry, rz, rotSeq);
}
Eigen::Matrix3d CTransformation_EG::rotRadian2Matrix(double rx, double ry, double rz, const E_ROTATION_SEQUENCE& rotSeq)
{
Eigen::Matrix3d rotationMatrix;
Eigen::AngleAxisd rotX(Eigen::AngleAxisd(rx, Eigen::Vector3d::UnitX()));
Eigen::AngleAxisd rotY(Eigen::AngleAxisd(ry, Eigen::Vector3d::UnitY()));
Eigen::AngleAxisd rotZ(Eigen::AngleAxisd(rz, Eigen::Vector3d::UnitZ()));
if (rotSeq == E_ROTATION_SEQUENCE::E_SEQ_XYZ)
{
rotationMatrix = rotZ * rotY * rotX;
}
else
{
rotationMatrix = rotX * rotY * rotZ;
}
return rotationMatrix;
}
Eigen::Vector3d CTransformation_EG::rotMatrix2RotDegree(const Eigen::Matrix3d& matrix, const E_ROTATION_SEQUENCE& rotSeq)
{
return rotMatrix2RotRadian(matrix, rotSeq) * 180 / M_PI;
}
Eigen::Vector3d CTransformation_EG::rotMatrix2RotRadian(const Eigen::Matrix3d& matrix, const E_ROTATION_SEQUENCE& rotSeq)
{
double R11, R12, R13, R21, R22, R23, R31, R32, R33;
R11 = matrix(0, 0); R12 = matrix(0, 1); R13 = matrix(0, 2);
R21 = matrix(1, 0); R22 = matrix(1, 1); R23 = matrix(1, 2);
R31 = matrix(2, 0); R32 = matrix(2, 1); R33 = matrix(2, 2);
double alfa = 0.0, beta = 0.0, gama = 0.0;
if (rotSeq == E_ROTATION_SEQUENCE::E_SEQ_XYZ)
{
beta = std::atan2(-R31, std::sqrt(R11 * R11 + R21 * R21));
if (std::abs(beta - M_PI / 2) < 1e-6)
{
beta = M_PI / 2;
alfa = 0.0;
gama = std::atan2(R12, R22);
}
else if (std::abs(beta + M_PI / 2) < 1e-6)
{
beta = -M_PI / 2;
alfa = 0.0;
gama = -std::atan2(R12, R22);
}
else
{
alfa = std::atan2(R21 / std::cos(beta), R11 / std::cos(beta));
gama = std::atan2(R32 / std::cos(beta), R33 / std::cos(beta));
}
Eigen::Vector3d rotDegree = { gama, beta,alfa };
return rotDegree;
}
else if (rotSeq == E_ROTATION_SEQUENCE::E_SEQ_ZYX) // 未考虑到R11、R13为0时,解存在退化的问题
{
beta = std::atan2(R13, std::sqrt(R11 * R11 + R12 * R12));
if (std::abs(beta - M_PI / 2) < 1e-6)
{
beta = M_PI / 2;
alfa = 0.0;
gama = std::atan2(R32, R22);
}
else if (std::abs(beta + M_PI / 2) < 1e-6)
{
beta = -M_PI / 2;
alfa = 0.0;
gama = -std::atan2(R32, R22);
}
else
{
alfa = std::atan2(-R23 / std::cos(beta), R33 / std::cos(beta));
gama = std::atan2(-R12 / std::cos(beta), R11 / std::cos(beta));
}
Eigen::Vector3d rotDegree = { alfa, beta, gama };
return rotDegree;
}
else
{
return Eigen::Vector3d();
}
}
Eigen::Matrix4d CTransformation_EG::pose2HmMatrix(double x, double y, double z, double rx, double ry, double rz, const E_ROTATION_SEQUENCE& rotSeq, const E_ANGLE_TYPE& angleType)
{
Eigen::Matrix4d hmMatrix = Eigen::Matrix4d::Identity();
Eigen::Matrix3d rotMatrix;
if (angleType == E_ANGLE_TYPE::E_TYPE_DEGREE)
{
rotMatrix = rotDegree2Matrix(rx, ry, rz, rotSeq);
}
else
{
rotMatrix = rotRadian2Matrix(rx, ry, rz, rotSeq);
}
hmMatrix.block<3, 3>(0, 0) = rotMatrix;
hmMatrix(0, 3) = x;
hmMatrix(1, 3) = y;
hmMatrix(2, 3) = z;
return hmMatrix;
}
Eigen::Matrix4d CTransformation_EG::pose2HmMatrix(const S_POSE& pose, const E_ROTATION_SEQUENCE& rotSeq, const E_ANGLE_TYPE& angleType)
{
return pose2HmMatrix(pose.X, pose.Y, pose.Z, pose.Rx, pose.Ry, pose.Rz, rotSeq, angleType);
}
S_POSE CTransformation_EG::hmMatrix2Pose(const Eigen::Matrix4d& hmMatrix, const E_ROTATION_SEQUENCE& rotSeq, const E_ANGLE_TYPE& angleType)
{
Eigen::Matrix3d rotMatrix = hmMatrix.block<3, 3>(0, 0);
Eigen::Vector3d rotAnagles;
if (angleType == E_ANGLE_TYPE::E_TYPE_DEGREE)
{
rotAnagles = rotMatrix2RotDegree(rotMatrix, rotSeq);
}
else
{
rotAnagles = rotMatrix2RotRadian(rotMatrix, rotSeq);
}
double x = hmMatrix(0, 3);
double y = hmMatrix(1, 3);
double z = hmMatrix(2, 3);
double rx = rotAnagles[0];
double ry = rotAnagles[1];
double rz = rotAnagles[2];
return S_POSE(x, y, z, rx, ry, rz);
}
也可以访问GitHub仓库内容:https://github.com/Chan-XM/Transformation.git
transformation_cv.h
更新OpenCV版本实现位姿转换内容:
/*****************************************************************************
* @file transformation_cv.h *
* @brief 用OpenCV实现三维空间中位姿与矩阵之间的变换 *
* Details. 具体包括旋转角、旋转矩阵、齐次矩阵之间的变换 *
* 在固定角坐标系下描述旋转角顺序 *
* *
* @author Chan_XM *
* @email chan_xm14@163.com *
* @version V1.0 *
* @date 2024/11/20 *
* @license NON *
*****************************************************************************/
#ifndef TRANSFORMATION_CV_H
#define TRANSFORMATION_CV_H
#include "common.h"
#include <opencv2/opencv.hpp>
class CTransformation_CV
{
public:
/// <summary>
/// 角度转弧度
/// </summary>
/// <param name="degree">角度(-180 180)</param>
/// <returns>弧度(-3.14 3.14)</returns>
static double degree2Radian(const double& degree);
/// <summary>
/// 弧度转角度
/// </summary>
/// <param name="radian">弧度(-3.14 3.14)</param>
/// <returns>角度(-180 180)</returns>
static double radian2Degree(const double& radian);
/// <summary>
/// 旋转角(degree)-> 旋转矩阵 默认按照X-Y-Z固定角坐标系(或Z-Y-X欧拉角坐标系 二者等价)转换
/// </summary>
/// <param name="rx">绕X轴旋转角</param>
/// <param name="ry">绕Y轴旋转角</param>
/// <param name="rz">绕Z轴旋转角</param>
/// <param name="rotSeq">固定角坐标系描述下的旋转顺序(与欧拉角坐标系反向)</param>
/// <returns>旋转矩阵(3x3)</returns>
static cv::Mat rotDegree2Matrix(double rx, double ry, double rz, const E_ROTATION_SEQUENCE& rotSeq = E_ROTATION_SEQUENCE::E_SEQ_XYZ);
/// <summary>
/// 旋转角(radian)-> 旋转矩阵 默认按照X-Y-Z固定角坐标系(或Z-Y-X欧拉角坐标系 二者等价)转换
/// </summary>
/// <param name="rx">绕X轴旋转角</param>
/// <param name="ry">绕Y轴旋转角</param>
/// <param name="rz">绕Z轴旋转角</param>
/// <param name="rotSeq">固定角坐标系描述下的旋转顺序(与欧拉角坐标系反向)</param>
/// <returns>旋转矩阵(3x3)</returns>
static cv::Mat rotRadian2Matrix(double rx, double ry, double rz, const E_ROTATION_SEQUENCE& rotSeq = E_ROTATION_SEQUENCE::E_SEQ_XYZ);
/// <summary>
/// 旋转矩阵 -> 旋转角(degree)默认按照X-Y-Z固定角坐标系(或Z-Y-X欧拉角坐标系 二者等价)转换
/// </summary>
/// <param name="matrix">旋转矩阵</param>
/// <param name="rotSeq">固定角坐标系描述下的旋转顺序(与欧拉角坐标系反向)</param>
/// <returns>旋转角(degree)</returns>
static cv::Vec3d rotMatrix2RotDegree(const cv::Mat& matrix, const E_ROTATION_SEQUENCE& rotSeq = E_ROTATION_SEQUENCE::E_SEQ_XYZ);
/// <summary>
/// 旋转矩阵 -> 旋转角(Radian)默认按照X-Y-Z固定角坐标系(或Z-Y-X欧拉角坐标系 二者等价)转换
/// </summary>
/// <param name="matrix">旋转矩阵</param>
/// <param name="rotSeq">固定角坐标系描述下的旋转顺序(与欧拉角坐标系反向)</param>
/// <returns>旋转角(Radian)</returns>
static cv::Vec3d rotMatrix2RotRadian(const cv::Mat& matrix, const E_ROTATION_SEQUENCE& rotSeq = E_ROTATION_SEQUENCE::E_SEQ_XYZ);
/// <summary>
/// 位姿 -> 齐次矩阵
/// </summary>
/// <param name="x">X</param>
/// <param name="y">Y</param>
/// <param name="z">Z</param>
/// <param name="rx">Rx</param>
/// <param name="ry">Ry</param>
/// <param name="rz">Rz</param>
/// <param name="rotSeq">旋转角顺序 默认按照X-Y-Z固定角坐标系(或Z-Y-X欧拉角坐标系 二者等价) </param>
/// <param name="angleType">角度单位 默认为degree</param>
/// <returns>齐次矩阵(4x4)</returns>
static cv::Mat pose2HmMatrix(double x, double y, double z, double rx, double ry, double rz,
const E_ROTATION_SEQUENCE& rotSeq = E_ROTATION_SEQUENCE::E_SEQ_XYZ,
const E_ANGLE_TYPE& angleType = E_ANGLE_TYPE::E_TYPE_DEGREE);
/// <summary>
/// 位姿转齐次矩阵
/// </summary>
/// <param name="pose">位姿(包含X Y Z Rx Ry Rz)</param>
/// <param name="rotSeq">旋转角顺序 默认按照X-Y-Z固定角坐标系(或Z-Y-X欧拉角坐标系 二者等价)</param>
/// <param name="angleType">角度单位 默认为degree</param>
/// <returns>齐次矩阵(4x4)</returns>
static cv::Mat pose2HmMatrix(const S_POSE& pose,
const E_ROTATION_SEQUENCE& rotSeq = E_ROTATION_SEQUENCE::E_SEQ_XYZ,
const E_ANGLE_TYPE& angleType = E_ANGLE_TYPE::E_TYPE_DEGREE);
/// <summary>
/// 齐次矩阵转为位姿
/// </summary>
/// <param name="hmMatrix">齐次矩阵(4x4)</param>
/// <param name="rotSeq">旋转角顺序 默认按照X-Y-Z固定角坐标系(或Z-Y-X欧拉角坐标系 二者等价)</param>
/// <param name="angleType">角度单位 默认为degree</param>
/// <returns>位姿(包含X Y Z Rx Ry Rz)</returns>
static S_POSE hmMatrix2Pose(const cv::Mat& hmMatrix,
const E_ROTATION_SEQUENCE& rotSeq = E_ROTATION_SEQUENCE::E_SEQ_XYZ,
const E_ANGLE_TYPE& angleType = E_ANGLE_TYPE::E_TYPE_DEGREE);
};
#endif // !TRANSFORMATION_CV_H
transformation_cv.cpp
/*****************************************************************************
* @file transformation_cv.cpp *
* @brief 用OpenCV实现三维空间中位姿与矩阵之间的变换 *
* *
* @author Chan_XM *
* @email chan_xm14@163.com *
* @version V1.0 *
* @date 2024/11/16 *
* @license NON *
*****************************************************************************/
#include "transformation_cv.h"
double CTransformation_CV::degree2Radian(const double& degree)
{
return degree * M_PI / 180.0;
}
double CTransformation_CV::radian2Degree(const double& radian)
{
return radian * 180.0 / M_PI;
}
cv::Mat CTransformation_CV::rotDegree2Matrix(double rx, double ry, double rz, const E_ROTATION_SEQUENCE& rotSeq)
{
rx = degree2Radian(rx);
ry = degree2Radian(ry);
rz = degree2Radian(rz);
return rotRadian2Matrix(rx, ry, rz, rotSeq);
}
cv::Mat CTransformation_CV::rotRadian2Matrix(double rx, double ry, double rz, const E_ROTATION_SEQUENCE& rotSeq)
{
cv::Mat rotX = (cv::Mat_<double>(3, 3) <<
1, 0, 0,
0, cos(rx), -sin(rx),
0, sin(rx), cos(rx));
cv::Mat rotY = (cv::Mat_<double>(3, 3) <<
cos(ry), 0, sin(ry),
0, 1, 0,
-sin(ry), 0, cos(ry));
cv::Mat rotZ = (cv::Mat_<double>(3, 3) <<
cos(rz), -sin(rz), 0,
sin(rz), cos(rz), 0,
0, 0, 1);
cv::Mat rotationMatrix;
if (rotSeq == E_ROTATION_SEQUENCE::E_SEQ_XYZ) {
rotationMatrix = rotZ * rotY * rotX;
}
else {
rotationMatrix = rotX * rotY * rotZ;
}
return rotationMatrix;
}
cv::Vec3d CTransformation_CV::rotMatrix2RotDegree(const cv::Mat& matrix, const E_ROTATION_SEQUENCE& rotSeq)
{
return rotMatrix2RotRadian(matrix, rotSeq) * 180 / M_PI;
}
cv::Vec3d CTransformation_CV::rotMatrix2RotRadian(const cv::Mat& matrix, const E_ROTATION_SEQUENCE& rotSeq)
{
if (matrix.cols != 3 || matrix.rows != 3)
{
std::cerr << "rotMatrix2RotRadian() matrix != 3x3" << std::endl;
return cv::Vec3d();
}
if (matrix.channels() != 1)
{
std::cerr << "rotMatrix2RotDegree() matrix channels != 1" << std::endl;
return cv::Vec3d();
}
double R11, R12, R13, R21, R22, R23, R31, R32, R33;
switch (CV_MAT_DEPTH(matrix.type()))
{
case CV_32F:
{
R11 = matrix.at<float>(0, 0); R12 = matrix.at<float>(0, 1); R13 = matrix.at<float>(0, 2);
R21 = matrix.at<float>(1, 0); R22 = matrix.at<float>(1, 1); R23 = matrix.at<float>(1, 2);
R31 = matrix.at<float>(2, 0); R32 = matrix.at<float>(2, 1); R33 = matrix.at<float>(2, 2);
break;
}
case CV_64F:
{
R11 = matrix.at<double>(0, 0); R12 = matrix.at<double>(0, 1); R13 = matrix.at<double>(0, 2);
R21 = matrix.at<double>(1, 0); R22 = matrix.at<double>(1, 1); R23 = matrix.at<double>(1, 2);
R31 = matrix.at<double>(2, 0); R32 = matrix.at<double>(2, 1); R33 = matrix.at<double>(2, 2);
break;
}
default:
{
std::cerr << "rotMatrix2RotDegree() matrix type != float/double" << std::endl;
return cv::Vec3d();
}
}
double alfa = 0.0, beta = 0.0, gama = 0.0;
if (rotSeq == E_ROTATION_SEQUENCE::E_SEQ_XYZ)
{
beta = std::atan2(-R31, std::sqrt(R11 * R11 + R21 * R21));
if (std::abs(beta - M_PI / 2) < 1e-6)
{
beta = M_PI / 2;
alfa = 0.0;
gama = std::atan2(R12, R22);
}
else if (std::abs(beta + M_PI / 2) < 1e-6)
{
beta = -M_PI / 2;
alfa = 0.0;
gama = -std::atan2(R12, R22);
}
else
{
alfa = std::atan2(R21 / std::cos(beta), R11 / std::cos(beta));
gama = std::atan2(R32 / std::cos(beta), R33 / std::cos(beta));
}
cv::Vec3d rotRadian = { gama, beta,alfa };
return rotRadian;
}
else if (rotSeq == E_ROTATION_SEQUENCE::E_SEQ_ZYX)
{
beta = std::atan2(R13, std::sqrt(R11 * R11 + R12 * R12));
if (std::abs(beta - M_PI / 2) < 1e-6)
{
beta = M_PI / 2;
alfa = 0.0;
gama = std::atan2(R32, R22);
}
else if (std::abs(beta + M_PI / 2) < 1e-6)
{
beta = -M_PI / 2;
alfa = 0.0;
gama = -std::atan2(R32, R22);
}
else
{
alfa = std::atan2(-R23 / std::cos(beta), R33 / std::cos(beta));
gama = std::atan2(-R12 / std::cos(beta), R11 / std::cos(beta));
}
cv::Vec3d rotRadian = { alfa, beta, gama };
return rotRadian;
}
else
{
return cv::Vec3d();
}
}
cv::Mat CTransformation_CV::pose2HmMatrix(double x, double y, double z, double rx, double ry, double rz, const E_ROTATION_SEQUENCE& rotSeq, const E_ANGLE_TYPE& angleType)
{
cv::Mat hmMatrix = cv::Mat::eye(4, 4, CV_64F);
cv::Mat rotMatrix;
if (angleType == E_ANGLE_TYPE::E_TYPE_DEGREE)
{
rotMatrix = rotDegree2Matrix(rx, ry, rz, rotSeq);
}
else
{
rotMatrix = rotRadian2Matrix(rx, ry, rz, rotSeq);
}
rotMatrix.copyTo(hmMatrix(cv::Rect(0, 0, 3, 3)));
hmMatrix.at<double>(0, 3) = x;
hmMatrix.at<double>(1, 3) = y;
hmMatrix.at<double>(2, 3) = z;
return hmMatrix;
}
cv::Mat CTransformation_CV::pose2HmMatrix(const S_POSE& pose, const E_ROTATION_SEQUENCE& rotSeq, const E_ANGLE_TYPE& angleType)
{
return pose2HmMatrix(pose.X, pose.Y, pose.Z, pose.Rx, pose.Ry, pose.Rz, rotSeq, angleType);
}
S_POSE CTransformation_CV::hmMatrix2Pose(const cv::Mat& hmMatrix, const E_ROTATION_SEQUENCE& rotSeq, const E_ANGLE_TYPE& angleType)
{
double x = 0.0, y = 0.0, z = 0.0, rx = 0.0, ry = 0.0, rz = 0.0;
if (hmMatrix.cols != 4 || hmMatrix.rows != 4)
{
std::cerr << "hmMatrix2Pose() hmMatrix != 4x4" << std::endl;
return S_POSE(x, y, z, rx, ry, rz);
}
if (hmMatrix.channels() != 1)
{
std::cerr << "hmMatrix2Pose() hmMatrix channels != 1" << std::endl;
return S_POSE(x, y, z, rx, ry, rz);
}
cv::Mat rotMatrix = hmMatrix(cv::Range(0, 3), cv::Range(0, 3));
std::cout << "rotMatrix = " << rotMatrix << std::endl << std::endl;
cv::Vec3d angles;
if (angleType == E_ANGLE_TYPE::E_TYPE_DEGREE)
{
angles = rotMatrix2RotDegree(rotMatrix, rotSeq);
}
else
{
angles = rotMatrix2RotRadian(rotMatrix, rotSeq);
}
rx = angles[0]; ry = angles[1]; rz = angles[2];
switch (CV_MAT_DEPTH(hmMatrix.type()))
{
case CV_32F:
{
x = hmMatrix.at<float>(0, 3);
y = hmMatrix.at<float>(1, 3);
z = hmMatrix.at<float>(2, 3);
break;
}
case CV_64F:
{
x = hmMatrix.at<double>(0, 3);
y = hmMatrix.at<double>(1, 3);
z = hmMatrix.at<double>(2, 3);
break;
}
default:
{
std::cerr << "hmMatrix2Pose() matrix type != float/double" << std::endl;
return S_POSE(x, y, z, rx, ry, rz);
}
}
return S_POSE(x, y, z, rx, ry, rz);
}
参考
放几个关于欧拉角/旋转矩阵的参考链接,有兴趣的可以移步学习:
- 欧拉角:https://en.wikipedia.org/wiki/Euler_angles
- 旋转矩阵:https://en.wikipedia.org/wiki/Rotation_matrix
- 演算工具(3D Rotation Converter): 3D Rotation Converter
- 《机器人学导论》自行查找
后续
当前通过Eigen实现了在固定角坐标系下按照XYZ/ZYX两种方式,旋转角与旋转矩阵之间的互逆变换,后续有时间将会追加一下内容的实现:
- 用OpenCV的cv::Mat实现上述内容 - 已完成
- 补充其它旋转顺序(如ZYZ/XZX等);
- 补充Eigen/OpenCV两个框架下Rodrigues变换操作。
6640

被折叠的 条评论
为什么被折叠?



