qr最小平方分解法求解a*w=b

fcipmucu  于 2021-06-27  发布在  Java
关注(0)|答案(0)|浏览(227)

我试图实现qr24算法来校准法兰/工具和机器人/世界,这是floris ernst(2012)的论文。
我需要解一个方程 M_i*X - Y*N_i = 0 哪里 M_i 以及 N_i 已知和我从1到的测量次数和 X 以及 Y 是未知矩阵。
在论文中,他们把这个方程组合成一个线性方程组 A*w = b ,其中a由12*个测量行和24列组成,因此我有一个具有24个参数的线性方程组,其中我需要至少2个测量值来解这个系统。
为了解这个方程,我需要使用最小二乘意义上的qr分解,因为随着测量的增多,这个系统的方程比参数多。
我用的是 OLSMultipleLinearRegression 从apache commons数学库中求解方程组:

OLSMultipleLinearRegression regression = new OLSMultipleLinearRegression();
regression.setNoIntercept(true);
regression.newSampleData(B.toArray(), A.getData());
RealVector w = new ArrayRealVector(regression.estimateRegressionParameters());

这个 RealVector w 现在应该包含未知矩阵x和y的条目(没有最后一行,它总是 [0 0 0 1] ,因为这些矩阵是齐次变换矩阵)。
我用denavit hartenberg在纸上手工生成了一些测试测量数据,因为我目前无法访问我想要使用的机器人和跟踪系统,因为电晕。
然而,我得到的结果x和y矩阵(向量w)总是非常荒谬,离我期望的结果非常遥远。例如,当我使用没有任何平移或旋转误差的精确变换矩阵时(除了我的计算机的计算误差),我得到的矩阵旋转部分的值超过10^14(这显然不可能是真的),而平移部分的值超过10^17,而不是预期的100左右。
当我向矩阵中添加一些测量误差时(例如+-0.01° 在旋转和+-0.01(对于平移部分),我没有得到那些超高的值,但是对于旋转部分的值不可能是真的。
你知道为什么这些值是如此的错误吗,或者你有什么建议如何在这个库中使用最小平方意义上的qr分解吗?
下面是我的代码,用于使用mïi和nïi度量创建a的每个条目/子矩阵ai:

private RealMatrix createAi(RealMatrix m,RealMatrix n, boolean invert) {
    RealMatrix M = new Array2DRowRealMatrix();
    if(invert) {
         M = new QRDecomposition(m).getSolver().getInverse();
    }else {
        M = m.copy();
    }
    // getRot is a method i wrote to get the rotational part of a matrix
    RealMatrix RM = getRot(M);

    RealMatrix N = n.copy();
    // 12 equations per Measurement and 24 parameters to solve for
    RealMatrix Ai = new Array2DRowRealMatrix(12,24);
    RealMatrix Zero = new Array2DRowRealMatrix(3,3);
    RealMatrix Identity12 = MatrixUtils.createRealIdentityMatrix(12);

    // first column
    Ai.setSubMatrix(RM.scalarMultiply(N.getEntry(0, 0)).getData(), 0, 0);
    Ai.setSubMatrix(RM.scalarMultiply(N.getEntry(0, 1)).getData(), 3, 0);
    Ai.setSubMatrix(RM.scalarMultiply(N.getEntry(0, 2)).getData(), 6, 0);
    Ai.setSubMatrix(RM.scalarMultiply(N.getEntry(0, 3)).getData(), 9, 0);

    // secondcolumn
    Ai.setSubMatrix(RM.scalarMultiply(N.getEntry(1, 0)).getData(), 0, 3);
    Ai.setSubMatrix(RM.scalarMultiply(N.getEntry(1, 1)).getData(), 3, 3);
    Ai.setSubMatrix(RM.scalarMultiply(N.getEntry(1, 2)).getData(), 6, 3);
    Ai.setSubMatrix(RM.scalarMultiply(N.getEntry(1, 3)).getData(), 9, 3);

    // third column
    Ai.setSubMatrix(RM.scalarMultiply(N.getEntry(2, 0)).getData(), 0, 6);
    Ai.setSubMatrix(RM.scalarMultiply(N.getEntry(2, 1)).getData(), 3, 6);
    Ai.setSubMatrix(RM.scalarMultiply(N.getEntry(2, 2)).getData(), 6, 6);
    Ai.setSubMatrix(RM.scalarMultiply(N.getEntry(2, 3)).getData(), 9, 6);

    // fourth column
    Ai.setSubMatrix(Zero.getData(), 0, 9);
    Ai.setSubMatrix(Zero.getData(), 3, 9);
    Ai.setSubMatrix(Zero.getData(), 6, 9);
    Ai.setSubMatrix(RM.getData(), 9, 9);

    // fifth column
    Ai.setSubMatrix(Identity12.scalarMultiply(-1d).getData(), 0, 12);
    return Ai;
}

下面是我的代码,用mïi度量创建b的每个条目/子向量bi:

private RealVector createBEntry(RealMatrix m, boolean invert) {
    RealMatrix bi = new Array2DRowRealMatrix(1,12);
    RealMatrix negative_M = new Array2DRowRealMatrix();
    // getTrans is a method i wrote to get the translational part of a matrix
    if(invert) {
        negative_M = getTrans(new QRDecomposition(m).getSolver().getInverse()).scalarMultiply(-1d); 
    }else {
        negative_M = getTrans(m).scalarMultiply(-1d);
    }       
    bi.setSubMatrix(negative_M.getData(), 0, 9);

    return bi.getRowVector(0);
}

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题