-
特殊正交群R和Phi=theta_n之间的转换
-
特殊欧式群T和epsilon=(p, theta_n)之间的转换
3. 代码实现以上李群和李代数之间的转换计算
#include
#include
#include
#include
using namespace std;
class Lie_group_algebra
{
public:
Lie_group_algebra(){}
void R_2_Phi(const Eigen::Matrix3d& R, Eigen::Vector3d& Phi);
void Phi_2_R(const Eigen::Vector3d& Phi, Eigen::Matrix3d& R);
void T_2_epsilon(const Eigen::Isometry3d& T, Eigen::Matrix<double, 6, 1>& epsilon);
void epsilon_2_T(const Eigen::Matrix<double,6,1>& epsilon, Eigen::Isometry3d& T);
};
int main(int argc, char** argv)
{
Lie_group_algebra Lie;
Eigen::Matrix3d R = Eigen::AngleAxisd( - 12 * M_PI, Eigen::Vector3d(4, 5, 7).normalized()).toRotationMatrix();
Eigen::Vector3d t(11, 33, 99);
cout << "验证R 和 theta_n(Phi)之间的转换是否正确\n";
cout << "原始R = \n" << R << endl;
Eigen::Vector3d Phi;
Lie.R_2_Phi(R, Phi);
cout << "计算Phi = \n" << Phi << endl;
Sophus::SO3d SO3_R(R);
Eigen::Vector3d so3_Phi = SO3_R.log();
cout << "验证so3_Phi = 利用Sophus的对数映射计算的, 理应等于Phi\n" << so3_Phi << endl;
cout << "------------" << endl;
Eigen::Matrix3d my_R;
Lie.Phi_2_R(Phi, my_R);
cout << "验证 my_R = 理应等于R\n" << my_R << endl;
Sophus::SO3d Sophus_R = Sophus::SO3d::exp(Phi);
cout << "Sophus_R = \n" << Sophus_R.matrix() << endl;
cout << "R - my_R = 理应等于0矩阵\n" << R - my_R << endl;
cout << "\n----------------------------------------------------";
cout << "\n验证T 和 epsilon = (p, theta_n(Phi))之间的转换是否正确\n\n";
Eigen::Isometry3d T(R);
T.pretranslate(t);
cout << "原始T = \n" << T.matrix() << endl;
Eigen::Matrix<double,6,1> epsilon;
Lie.T_2_epsilon(T, epsilon);
cout << "计算epsilon = \n" << epsilon << endl;
Sophus::SE3d SE3_T(R, t);
Eigen::Matrix<double,6,1> se3_epsilon = SE3_T.log();
cout << "验证se3_epsilon = 利用Sophus的对数映射计算的, 理应等于epsilon \n" << se3_epsilon << endl;
Eigen::Isometry3d my_T = Eigen::Isometry3d::Identity();
Lie.epsilon_2_T(epsilon, my_T);
cout << "验证 my_T = 理应等于T \n" << my_T.matrix() << endl;
Sophus::SE3d Sophus_T = Sophus::SE3d::exp(epsilon);
cout << "Sophus_T = \n" << Sophus_T.matrix() << endl;
cout << "T - my_T = 理应等于0矩阵 \n" << T.matrix() - my_T.matrix() << endl;
return 0;
}
void Lie_group_algebra::R_2_Phi(const Eigen::Matrix3d& R, Eigen::Vector3d& Phi)
{
double cos_theta = (R.trace() - 1.0) / 2;
double theta = acos(cos_theta);
double sin_theta = sqrt(1.0 - cos_theta * cos_theta);
if(fabs(cos_theta - 1.0) < 0.000001)
{
cout << "Situation: theta = 0\n";
Eigen::Vector3d n(1,0,0);
cout << "theta = " << theta << endl;
cout << "n不唯一, 任意皆满足, 这里给n = \n" << n << endl;
Phi = theta * n;
return;
}
else if(fabs(cos_theta + 1.0) < 0.000001)
{
cout << "Situation: theta = PI\n";
Eigen::EigenSolver<Eigen::Matrix3d> es(R);
Eigen::Vector3d eigen_values = es.pseudoEigenvalueMatrix().diagonal();
Eigen::Matrix3d eigen_vectors = es.pseudoEigenvectors();
Eigen::Vector3d is_one = (eigen_values - Eigen::Vector3d::Ones()).cwiseAbs();
Eigen::Vector3d::Index k;
is_one.minCoeff(&k);
Eigen::Vector3d n = eigen_vectors.block<3,1>(0,k);
n = -n;
cout << "theta = " << theta << endl;
cout << "此时正负n皆可 n = \n" << n << endl;
n.normalize();
Phi = theta * n;
return;
}
else
{
Eigen::Matrix3d n_hat = (R - R.transpose()) / (2 * sin_theta);
Eigen::Vector3d n(-n_hat(1,2), n_hat(0,2), -n_hat(0,1));
cout << "theta = " << theta << endl;
cout << "n = \n" << n << endl;
Phi = theta * n;
}
}
void Lie_group_algebra::Phi_2_R(const Eigen::Vector3d& Phi, Eigen::Matrix3d& R)
{
double theta = Phi.norm();
Eigen::Vector3d n = Phi.normalized();
R.setZero();
R(1,2) = -n(0); R(0,2) = n(1); R(0,1) = -n(2);
R(2,1) = n(0); R(2,0) = -n(1); R(1,0) = n(2);
R = R * sin(theta);
R = R + cos(theta) * Eigen::Matrix3d::Identity() + (1.0 - cos(theta)) * n * n.transpose();
}
void Lie_group_algebra::T_2_epsilon(const Eigen::Isometry3d& T, Eigen::Matrix<double, 6, 1>& epsilon)
{
Eigen::Matrix3d R = T.rotation();
Eigen::Vector3d t = T.translation();
Eigen::Vector3d Phi;
R_2_Phi(R, Phi);
double theta = Phi.norm();
if(fabs(theta) < 0.000001)
{
Eigen::Vector3d p = t;
epsilon.block<3,1>(0,0) = p;
epsilon.block<3,1>(3,0) = Phi;
return;
}
Eigen::Vector3d n = Phi.normalized();
Eigen::Matrix3d J = Eigen::Matrix3d::Zero();
J(1,2) = -n(0); J(0,2) = n(1); J(0,1) = -n(2);
J(2,1) = n(0); J(2,0) = -n(1); J(1,0) = n(2);
J = J *(1.0 - cos(theta)) / theta;
J = J + Eigen::Matrix3d::Identity() * sin(theta) / theta + (1.0 - sin(theta)/theta) * n * n.transpose();
Eigen::Vector3d p = J.inverse() * t;
epsilon.block<3,1>(0,0) = p;
epsilon.block<3,1>(3,0) = Phi;
}
void Lie_group_algebra::epsilon_2_T(const Eigen::Matrix<double,6,1>& epsilon, Eigen::Isometry3d& T)
{
Eigen::Vector3d p = epsilon.block<3,1>(0,0);
Eigen::Vector3d Phi = epsilon.block<3,1>(3,0);
double theta = Phi.norm();
Eigen::Vector3d n = Phi.normalized();
Eigen::Matrix3d R;
Phi_2_R(Phi, R);
Eigen::Matrix3d J = Eigen::Matrix3d::Zero();
if(fabs(theta) < 0.000001)
{
Eigen::Vector3d t = p;
T = Eigen::Isometry3d::Identity();
T.rotate(R);
T.pretranslate(t);
return;
}
J(1,2) = -n(0); J(0,2) = n(1); J(0,1) = -n(2);
J(2,1) = n(0); J(2,0) = -n(1); J(1,0) = n(2);
J = J *(1.0 - cos(theta)) / theta;
J = J + Eigen::Matrix3d::Identity() * sin(theta) / theta + (1.0 - sin(theta)/theta) * n * n.transpose();
Eigen::Vector3d t = J * p;
T = Eigen::Isometry3d::Identity();
T.rotate(R);
T.pretranslate(t);
}