用Eigen库编写了一个3D向量在空间中进行变换的代码,结果编译时遇到如下报错:
usr/include/eigen3/Eigen/src/Core/GeneralProduct.h:
In instantiation of ‘const Eigen::Product<Derived, OtherDerived>
Eigen::MatrixBase<Derived>::operator*(const Eigen::MatrixBase<OtherDerived>&)
const [with OtherDerived = Eigen::Matrix<double, 3, 1>;
Derived = Eigen::Matrix<double, 4, 4>]’:
usr/include/eigen3/Eigen/src/Core/GeneralProduct.h:410:3:
error: static assertion failed: INVALID_MATRIX_PRODUCT
410 | EIGEN_STATIC_ASSERT(ProductIsValid || SameSizes, INVALID_MATRIX_PRODUCT)
/usr/include/eigen3/Eigen/src/Core/AssignEvaluator.h:833:3:
error: static assertion failed: YOU_MIXED_MATRICES_OF_DIFFERENT_SIZES
833 | EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(ActualDstTypeCleaned,Src)
根据报错信息发现是矩阵相乘维度不统一的错误,一个矩阵是Derived = Eigen::Matrix<double, 4, 4>,另外一个矩阵是Eigen::Matrix<double, 3, 1>。然后根据报错信息定位到出问题的源码
Eigen::Vector3d point_src;
Vector6d se3;//typedef Eigen::Matrix<double, 6, 1> Vector6d;
//Matrix只能这样初始化, 不能像Vector3d v(0, 0 ,1)这样初始化
se3<<parameters[0][0], parameters[0][1], parameters[0][2], parameters[0][3], parameters[0][4], parameters[0][5];
Sophus::SE3d SE3_d = Sophus::SE3d::exp(se3);
Eigen::Matrix4d T = SE3_d.matrix();
//下面这行是出错的地方
Eigen::Vector3d point_trans = T*point_src;//point_src通过T(se3对应的齐次转换矩阵)转换得到点云point_trans
T是齐次转换矩阵,维度是
4
∗
4
4*4
4∗4。 point_src维度是
3
∗
1
3*1
3∗1。所以两个相乘会出错。这个错误看着很低级,如果是自己平时用笔计算肯定不会出现。之所以出现是Eigen库中其它几种空间变换表达形式弄混了。
Eigen可以表示空间转换的还有两种形式,一个是Eigen::Affine3d, 另一个是Eigen::Isometry3d。它们之间的区别在于它们所表示的变换类型和所包含的自由度。
- Eigen::Matrix4d:
Eigen::Matrix4d是一个4x4的双精度浮点数矩阵,用于表示一般的仿射变换或投影变换。它是一个通用的矩阵类型,可以用于表示任意的线性变换和平移变换。 - Eigen::Affine3d:
Eigen::Affine3d是一个3D仿射变换矩阵,它包含一个3x3的旋转矩阵和一个3维的平移向量,用于表示没有缩放的仿射变换。 - Eigen::Isometry3d:、
Eigen::Isometry3d是一个3D等距变换矩阵,它也包含一个3x3的旋转矩阵和一个3维的平移向量,用于表示没有缩放的等距变换。等距变换是一种特殊的仿射变换,保持了向量的长度和角度的大小。
他们之间的转换如下:
#include <iostream>
#include <Eigen/Dense>
int main()
{
// 创建一个4x4的双精度浮点数矩阵
Eigen::Matrix4d matrix = Eigen::Matrix4d::Identity();
// 将Matrix4d转换为Affine3d
Eigen::Affine3d affine_transform(matrix);
// 将Matrix4d转换为Isometry3d
Eigen::Isometry3d isometry_transform(matrix);
// 将Affine3d转换为Matrix4d
Eigen::Matrix4d matrix_from_affine = affine_transform.matrix();
// 将Isometry3d转换为Matrix4d
Eigen::Matrix4d matrix_from_isometry = isometry_transform.matrix();
std::cout << "Affine transform matrix:\n" << affine_transform.matrix() << std::endl;
std::cout << "Isometry transform matrix:\n" << isometry_transform.matrix() << std::endl;
std::cout << "Matrix from Affine transform:\n" << matrix_from_affine << std::endl;
std::cout << "Matrix from Isometry transform:\n" << matrix_from_isometry << std::endl;
return 0;
}
Eigen::Isometry3D 和Eigen::Affine3D是可以和3维向量直接相乘的。空间欧式变换一般用Eigen::Isometry3D,所以代码做如下更改即可:
Eigen::Matrix4d T = SE3_d.matrix();
Eigen::Isometry3d isometry_transform(T) ;
Eigen::Vector3d point_trans = isometry_transform*point_src;//point_src通过T(se3对应的齐次转换矩阵)转换得到点云point_trans