bool pinv_damped(const MatrixD &A, MatrixD *invA, Scalar lambda_max, Scalar eps) { //A (m x n) usually comes from a redundant task jacobian, therfore we consider m<n int m = A.rows() - 1; VectorD sigma; //vector of singular values Scalar lambda2; int r = 0; JacobiSVD<MatrixD> svd_A(A.transpose(), ComputeThinU | ComputeThinV); sigma = svd_A.singularValues(); if (((m > 0) && (sigma(m) > eps)) || ((m == 0) && (A.array().abs() > eps).any())) { for (int i = 0; i <= m; i++) { sigma(i) = 1.0 / sigma(i); } (*invA) = svd_A.matrixU() * sigma.asDiagonal() * svd_A.matrixV().transpose(); return true; } else { lambda2 = (1 - (sigma(m) / eps) * (sigma(m) / eps)) * lambda_max * lambda_max; for (int i = 0; i <= m; i++) { if (sigma(i) > EPSQ) r++; sigma(i) = (sigma(i) / (sigma(i) * sigma(i) + lambda2)); } //only U till the rank MatrixD subU = svd_A.matrixU().block(0, 0, A.cols(), r); MatrixD subV = svd_A.matrixV().block(0, 0, A.rows(), r); (*invA) = subU * sigma.asDiagonal() * subV.transpose(); return false; } }
bool pinv_QR_Z(const MatrixD &A, const MatrixD &Z0, MatrixD *invA, MatrixD *Z, Scalar lambda_max, Scalar eps) { VectorD sigma; //vector of singular values Scalar lambda2; MatrixD AZ0t = (A * Z0).transpose(); HouseholderQR < MatrixD > qr = AZ0t.householderQr(); int m = A.rows(); int p = Z0.cols(); MatrixD Rt = MatrixD::Zero(m, m); bool invertible; MatrixD hR = (MatrixD) qr.matrixQR(); MatrixD Y = ((MatrixD) qr.householderQ()).leftCols(m); //take the useful part of R for (int i = 0; i < m; i++) { for (int j = 0; j <= i; j++) Rt(i, j) = hR(j, i); } FullPivLU < MatrixD > invRt(Rt); invertible = fabs(invRt.determinant()) > eps; if (invertible) { *invA = Z0 * Y * invRt.inverse(); *Z = Z0 * (((MatrixD) qr.householderQ()).rightCols(p - m)); return true; } else { MatrixD R = MatrixD::Zero(m, m); //take the useful part of R for (int i = 0; i < m; i++) { for (int j = i; j < m; j++) // TODO: is starting at i correct? R(i, j) = hR(i, j); } //perform the SVD of R JacobiSVD<MatrixD> svd_R(R, ComputeThinU | ComputeThinV); sigma = svd_R.singularValues(); lambda2 = (1 - (sigma(m - 1) / eps) * (sigma(m - 1) / eps)) * lambda_max * lambda_max; for (int i = 0; i < m; i++) { sigma(i) = sigma(i) / (sigma(i) * sigma(i) + lambda2); } (*invA) = Z0 * Y * svd_R.matrixU() * sigma.asDiagonal() * svd_R.matrixV().transpose(); *Z = Z0 * (((MatrixD) qr.householderQ()).rightCols(p - m)); return false; } }
bool pinv(const MatrixD &A, MatrixD *invA, Scalar eps) { //A (m x n) usually comes from a redundant task jacobian, therfore we consider m<n int m = A.rows() - 1; VectorD sigma; //vector of singular values JacobiSVD<MatrixD> svd_A(A.transpose(), ComputeThinU | ComputeThinV); sigma = svd_A.singularValues(); if (((m > 0) && (sigma(m) > eps)) || ((m == 0) && (A.array().abs() > eps).any())) { for (int i = 0; i <= m; i++) { sigma(i) = 1.0 / sigma(i); } (*invA) = svd_A.matrixU() * sigma.asDiagonal() * svd_A.matrixV().transpose(); return true; } else { return false; } }