opspace/src/pseudo_inverse.cpp

Go to the documentation of this file.
00001 /*
00002  * Shared copyright notice and LGPLv3 license statement.
00003  *
00004  * Copyright (C) 2010 The Board of Trustees of The Leland Stanford Junior University. All rights reserved.
00005  * Copyright (C) 2010 University of Texas at Austin. All rights reserved.
00006  *
00007  * Authors: Roland Philippsen (Stanford) and Luis Sentis (UT Austin)
00008  *          http://cs.stanford.edu/group/manips/
00009  *          http://www.me.utexas.edu/~hcrl/
00010  *
00011  * This program is free software: you can redistribute it and/or
00012  * modify it under the terms of the GNU Lesser General Public License
00013  * as published by the Free Software Foundation, either version 3 of
00014  * the License, or (at your option) any later version.
00015  *
00016  * This program is distributed in the hope that it will be useful, but
00017  * WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019  * Lesser General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU Lesser General Public
00022  * License along with this program.  If not, see
00023  * <http://www.gnu.org/licenses/>
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       // workaround for Eigen2
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     // not sure if we need to svd.sort()... probably not
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 }

Generated on Fri Aug 26 01:31:17 2011 for Stanford Whole-Body Control Framework by  doxygen 1.5.4