我正在使用Eigen库作为大型项目的一部分,并且我遇到了两个Matrix4d
对象相乘会产生数学上不正确的结果的情况。
但是,只有当矩阵用作类变量 AND 时才会产生不正确的结果仅在较大程序的一部分时。< / p>
相关代码简化为基本部分: 结果(在我演示错误的大型程序中)产生的是: 我不知道为什么一个计算是正确的而另一个是错误的。 上面的代码与大型项目的一部分大致相同,唯一的区别是m1 / m2的值是使用数据文件中的值设置的,而不是显式设置的。然而,当我完全按照上面所示的那样执行代码时,在它自己的程序中,结果矩阵在两种情况下都是相同的(即C1和C2都是正确的)。 我已经有几位同事查看我的代码并尝试调试它,但没有成功。我还没有在Eigen bugzilla site或Stack Overflow上找到任何解释甚至是类似的问题。我发现的最接近的线索是In which cases do functions taking a plain Matrix or Array argument fail?上的Eigen文档,这表明编译器无法阻止您将特征矩阵复制到临时变量。但是,我的编译器并没有失败,正如我所说的,当上面的代码以它自己的程序运行时,C1和C2都是正确的。 不幸的是,我无法分享我的完整代码,无论如何要求任何人调试它都是不公平的。因此,我只是就可能导致此问题或任何类似问题的建议寻求建议。任何我可以研究的领导都将非常感激。 编辑1:我做的挖掘越多,内存对齐问题就越重要,以及当 编辑2: Valgrind没有在代码的这一部分附近报告任何异常情况。 GDB也没有发现任何异常。两个矩阵(A和B)在代码的所有阶段都保持正确的值,因此在乘法运算期间肯定会发生错误。 编辑3:我发现使用class MatrixContainer
{
public:
Eigen::Matrix4d m1;
Eigen::Matrix4d m2;
};
class DummyClass
{
public:
MatrixContainer matrices;
void multiplyMatrices()
{
print4x4Matrix("C1 = AB =", matrices.m1*matrices.m2);
}
};
void print4x4MatrixEnhanced (string inputs, const Eigen::Matrix4d & matrix)
{
string blanks(inputs.length(), ' ');
printf ("\n");
cout << blanks; printf (" | %6.3f %6.3f %6.3f %6.3f | \n", matrix (0, 0), matrix (0, 1), matrix (0, 2), matrix (0, 3));
cout << inputs; printf (" | %6.3f %6.3f %6.3f %6.3f | \n", matrix (1, 0), matrix (1, 1), matrix (1, 2), matrix (1, 3));
cout << blanks; printf (" | %6.3f %6.3f %6.3f %6.3f | \n", matrix (2, 0), matrix (2, 1), matrix (2, 2), matrix (2, 3));
cout << blanks; printf (" | 0 0 0 1 | \n");
printf ("\n");
}
int main()
{
Eigen::Matrix4d tmp_m1;
Eigen::Matrix4d tmp_m2;
tmp_m1 << 0.401, -0.916, 0.007, 628491.906,
0.916, 0.401, 0.000, 5177400.650,
-0.003, 0.007, 1.000, 28.036,
0, 0, 0, 1;
tmp_m2 << 1.000, 0.012, 0.018, 4.603,
-0.012, 1.000, 0.005, 2.428,
-0.018, -0.006, 1.000, 0.005,
0, 0, 0, 1;
MatrixContainer test_matrices;
test_matrices.m1 = tmp_m1;
test_matrices.m2 = tmp_m2;
DummyClass test_class;
test_class.matrices = test_matrices;
print4x4Matrix("A =", test_class.matrices.m1);
print4x4Matrix("B =", test_class.matrices.m2);
cout << "Multiplied and printed within the class function (incorrect)" << endl;
test_class.multiplyMatrices();
cout << "Multiplied and printed outside the class function (correct)" << endl;
print4x4Matrix("C2 = AB =", tmp_m1*tmp_m2);
return 0;
}
| 0.401 -0.916 0.007 628491.906 |
A = | 0.916 0.401 0.000 5177400.650 |
| -0.003 0.007 1.000 28.036 |
| 0 0 0 1 |
| 1.000 0.012 0.018 4.603 |
B = | -0.012 1.000 0.005 2.428 |
| -0.018 -0.006 1.000 0.005 |
| 0 0 0 1 |
Multiplied and printed within the class function (incorrect)
| 0.413 -0.911 0.009 -0.379 |
C1 = AB = | 0.911 0.413 0.018 5.190 |
| -0.020 0.001 1.000 0.007 |
| 0 0 0 1 |
Multiplied and printed outside the class function (correct)
| 0.412 -0.911 0.010 628491.528 |
C2 = AB = | 0.911 0.412 0.018 5177405.840 |
| -0.021 0.001 1.000 28.044 |
| 0 0 0 1 |
Eigen
矩阵存储在类对象中时如何执行。在演示错误的代码中,我实际上使用嵌套对象 - 一个对象包含所有矩阵(MatrixContainer
),另一个对象存储此对象类型的变量和一堆无关数据(DummyClass
)。当我运行上面的缩减示例时,两个结果都是正确的(即C1 = C2),这就是为什么我当时认为它不重要的原因。但是我现在意识到可能不是这样,所以我已经改变了缩减的例子,以更准确地估计出错的版本正在做什么。 Affine3d
Eigen对象代替Matrix4d
似乎可以避免这个问题。因此,如果我重复完全相同的操作并使用相同的函数,Affine3d
乘法将产生正确的结果,而Matrix4d
乘法则不会。