You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何控制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::Matrix3ldEigen::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

火山引擎 最新活动