如何控制Eigen精度?附Eigen 3x3旋转矩阵转四元数代码求助
我来帮你搞定这两个问题——把Eigen的3x3旋转矩阵转成四元数,还有怎么控制Eigen的精度。先结合你的代码场景一步步说:
一、旋转矩阵转四元数
你的代码里已经从仿射矩阵中提取出了rotationMatrix(3x3的Eigen矩阵),Eigen的Quaternion类直接支持从旋转矩阵构造,非常省心:
// 从旋转矩阵直接构造四元数 Eigen::Quaterniond quat(rotationMatrix); // 可选:归一化操作——如果旋转矩阵因为计算误差有微小的非正交问题,这一步能修正 quat.normalize();
不过要注意:只有纯旋转矩阵(正交、行列式为1)才能正确转成四元数。如果你的rotationMatrix里还包含缩放(你代码里提到了scaleX,看来是有缩放的),那得先把缩放部分剥离,再提取纯旋转矩阵:
// 先提取各轴的缩放因子 Eigen::Vector3d scaleFactors; scaleFactors[0] = rotationMatrix.col(0).norm(); // X轴缩放 scaleFactors[1] = rotationMatrix.col(1).norm(); // Y轴缩放 scaleFactors[2] = rotationMatrix.col(2).norm(); // Z轴缩放 // 去除缩放,得到纯旋转矩阵 Eigen::Matrix3d pureRotationMatrix = rotationMatrix; pureRotationMatrix.col(0) /= scaleFactors[0]; pureRotationMatrix.col(1) /= scaleFactors[1]; pureRotationMatrix.col(2) /= scaleFactors[2]; // 再转四元数 Eigen::Quaterniond quat(pureRotationMatrix); quat.normalize();
二、控制Eigen的精度
Eigen的精度控制分两种常见场景,看你需要哪一种:
1. 控制输出精度(打印/保存时的小数位数)
如果是要让矩阵、四元数输出时显示更多/更少的小数位,直接用C++标准库的流控制就行,记得包含<iomanip>头文件:
#include <iomanip> // 设置输出为固定小数格式,精度为8位(你可以改成自己需要的位数,比如10) std::cout << std::fixed << std::setprecision(8); // 输出四元数或矩阵 std::cout << "转换后的四元数(w,x,y,z): " << quat.w() << ", " << quat.x() << ", " << quat.y() << ", " << quat.z() << std::endl; std::cout << "旋转矩阵:\n" << pureRotationMatrix << std::endl;
2. 控制运算/存储的精度
Eigen默认用double(64位浮点数)做运算和存储,如果需要更低精度(比如32位浮点数,节省内存),直接换对应的类型就行:
- 用
Eigen::Matrix3f代替Matrix3d - 用
Eigen::Quaternionf代替Quaterniond
如果需要更高精度,Eigen也支持长双精度(long double):
- 对应类型是
Eigen::Matrix3ld、Eigen::Quaternionld
另外,你从VTK矩阵映射到Eigen矩阵时,只要保证两者的数值类型匹配(VTK的vtkMatrix4x4默认是double,对应Eigen的Matrix4d),就不会有额外的精度损失。
最后给你补全后的完整代码参考:
// 从VTK矩阵映射到Eigen 4x4矩阵 m_transformationMatrix = Eigen::Map<Eigen::Matrix4d>(m_labelMatrix); m_transformationMatrix.transposeInPlace(); // VTK和Eigen的存储顺序不同,转置是正确操作 // 转换为仿射矩阵 Eigen::Affine3d m_affinedMatrix = m_transformationMatrix; auto label_pos = m_affinedMatrix.translation(); auto rotationMatrix = m_affinedMatrix.linear(); // 提取缩放因子 Eigen::Vector3d scaleFactors; scaleFactors << rotationMatrix.col(0).norm(), rotationMatrix.col(1).norm(), rotationMatrix.col(2).norm(); // 剥离缩放,得到纯旋转矩阵 Eigen::Matrix3d pureRotationMatrix = rotationMatrix; pureRotationMatrix.col(0) /= scaleFactors[0]; pureRotationMatrix.col(1) /= scaleFactors[1]; pureRotationMatrix.col(2) /= scaleFactors[2]; // 转换为四元数 Eigen::Quaterniond quat(pureRotationMatrix); quat.normalize(); // 设置输出精度并打印结果 #include <iomanip> std::cout << std::fixed << std::setprecision(8); std::cout << "平移向量: " << label_pos << std::endl; std::cout << "缩放因子: " << scaleFactors << std::endl; std::cout << "四元数(w,x,y,z): " << quat.w() << ", " << quat.x() << ", " << quat.y() << ", " << quat.z() << std::endl;
内容的提问来源于stack exchange,提问作者user5725581




