00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include <opspace/pseudo_inverse.hpp>
00027 #include <Eigen/LU>
00028 #include <Eigen/SVD>
00029
00030 using namespace std;
00031
00032 namespace opspace {
00033
00034 void pseudoInverse(Matrix const & matrix,
00035 double sigmaThreshold,
00036 Matrix & invMatrix,
00037 Vector * opt_sigmaOut)
00038 {
00039 if ((1 == matrix.rows()) && (1 == matrix.cols())) {
00040
00041 invMatrix.resize(1, 1);
00042 if (matrix.coeff(0, 0) > sigmaThreshold) {
00043 invMatrix.coeffRef(0, 0) = 1.0 / matrix.coeff(0, 0);
00044 }
00045 else {
00046 invMatrix.coeffRef(0, 0) = 0.0;
00047 }
00048 if (opt_sigmaOut) {
00049 opt_sigmaOut->resize(1);
00050 opt_sigmaOut->coeffRef(0) = matrix.coeff(0, 0);
00051 }
00052 return;
00053 }
00054
00055 Eigen::SVD<Matrix> svd(matrix);
00056
00057 int const nrows(svd.singularValues().rows());
00058 Matrix invS;
00059 invS = Matrix::Zero(nrows, nrows);
00060 for (int ii(0); ii < nrows; ++ii) {
00061 if (svd.singularValues().coeff(ii) > sigmaThreshold) {
00062 invS.coeffRef(ii, ii) = 1.0 / svd.singularValues().coeff(ii);
00063 }
00064 }
00065 invMatrix = svd.matrixU() * invS * svd.matrixU().transpose();
00066 if (opt_sigmaOut) {
00067 *opt_sigmaOut = svd.singularValues();
00068 }
00069 }
00070
00071 }