Go to the documentation of this file.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
00027
00028
00029
00030
00031
00032
00033
00034
00037
00038
00039
00040
00041 #ifndef KDL_MATRIXINVERTER_H
00042 #define KDL_MATRIXINVERTER_H
00043
00044
00045 #include <algorithm>
00046 #include <cassert>
00047
00048
00049 #include <boost/shared_ptr.hpp>
00050
00051
00052 #include <Eigen/Dense>
00053
00054
00055 namespace Eigen
00056 {
00057 namespace internal
00058 {
00059 template<typename MatrixType> class LsInverseReturnType;
00060 template<typename MatrixType> class DlsInverseReturnType;
00061 template<typename MatrixType> class LsSolveReturnType;
00062 template<typename MatrixType> class DlsSolveReturnType;
00063 }
00064 }
00065
00066 namespace KDL
00067 {
00068
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121 template <typename MatrixType>
00122 class MatrixInverter
00123 {
00124 public:
00125 typedef MatrixType Matrix;
00126 typedef boost::shared_ptr<Matrix> MatrixPtr;
00127 typedef typename Eigen::internal::plain_col_type<Matrix>::type Vector;
00128 typedef typename Matrix::Index Index;
00129 typedef typename Matrix::Scalar Scalar;
00130 typedef typename Eigen::JacobiSVD<Matrix, Eigen::ColPivHouseholderQRPreconditioner> SVD;
00131 typedef Eigen::internal::LsInverseReturnType<Matrix> LsInverseReturnType;
00132 typedef Eigen::internal::DlsInverseReturnType<Matrix> DlsInverseReturnType;
00133 typedef Eigen::internal::LsSolveReturnType<Matrix> LsSolveReturnType;
00134 typedef Eigen::internal::DlsSolveReturnType<Matrix> DlsSolveReturnType;
00135
00139 MatrixInverter(const Index rows, const Index cols);
00140
00154 MatrixInverter(const Matrix& A);
00155
00158 MatrixInverter& compute(const Matrix& A);
00159
00162 LsInverseReturnType inverse() {return lsInverse();}
00163
00168 LsInverseReturnType lsInverse() {return LsInverseReturnType(*this);}
00169
00174 DlsInverseReturnType dlsInverse() {return DlsInverseReturnType(*this);}
00175
00178 LsSolveReturnType solve(const Vector& b) {return lsSolve(b);}
00179
00182 LsSolveReturnType lsSolve(const Vector& b) {return LsSolveReturnType(b, *this);}
00183
00186 DlsSolveReturnType dlsSolve(const Vector& b) {return DlsSolveReturnType(b, *this);}
00187
00190 void setLsInverseThreshold(const Scalar eps) {lsEps_ = eps;}
00191
00194 Scalar getLsInverseThreshold() const {return lsEps_;}
00195
00211 void setDlsInverseThreshold(const Scalar dampEps) {dlsEps_ = dampEps;}
00212
00215 Scalar getDlsInverseThreshold() const {return dlsEps_;}
00216
00219 void setMaxDamping(const Scalar dampMax) {dampMax_ = dampMax;}
00220
00223 Scalar getMaxDamping() const {return dampMax_;}
00224
00225 private:
00226 SVD svd_;
00227 Scalar lsEps_;
00228 Scalar dlsEps_;
00229 Scalar dampMax_;
00230
00231
00232 Matrix pinv_;
00233 Vector solve1_;
00234 Vector solve2_;
00235
00237 void allocate(const Index rows, const Index cols);
00238
00240 Index nonzeroSingularValues() const;
00241
00244 Scalar computeDampingSq(const Vector& S) const;
00245
00246 friend class Eigen::internal::LsInverseReturnType<MatrixType>;
00247 friend class Eigen::internal::DlsInverseReturnType<MatrixType>;
00248 friend class Eigen::internal::LsSolveReturnType<MatrixType>;
00249 friend class Eigen::internal::DlsSolveReturnType<MatrixType>;
00250 };
00251
00252 template <typename MatrixType>
00253 MatrixInverter<MatrixType>::MatrixInverter(const Index rows, const Index cols)
00254 {
00255 allocate(rows, cols);
00256 }
00257
00258 template <typename MatrixType>
00259 MatrixInverter<MatrixType>::MatrixInverter(const Matrix& A)
00260 {
00261 allocate(A.rows(), A.cols());
00262 compute(A);
00263 }
00264
00265 template <typename MatrixType>
00266 inline void MatrixInverter<MatrixType>::allocate(const Index rows, const Index cols)
00267 {
00268 if (rows == 0 || cols == 0) throw;
00269
00270 svd_ = SVD(rows, cols, Eigen::ComputeThinU | Eigen::ComputeThinV);
00271 lsEps_ = Eigen::NumTraits<Scalar>::epsilon();
00272 dlsEps_ = 1e3 * Eigen::NumTraits<Scalar>::epsilon();
00273 dampMax_ = 0.1;
00274 const Index minDim = std::min(rows, cols);
00275 pinv_ = Matrix(minDim, minDim);
00276 solve1_ = Vector(minDim);
00277 solve2_ = Vector(minDim);
00278 }
00279
00280 template <typename MatrixType>
00281 inline MatrixInverter<MatrixType>& MatrixInverter<MatrixType>::compute(const Matrix& A)
00282 {
00283
00284 assert(A.rows() == svd_.rows() && A.cols() == svd_.cols() &&
00285 "Size mismatch between MatrixInverter and input matrix.");
00286
00287
00288 svd_.compute(A);
00289 return *this;
00290 }
00291
00292 template <typename MatrixType>
00293 inline typename MatrixInverter<MatrixType>::Index MatrixInverter<MatrixType>::nonzeroSingularValues() const
00294 {
00295 const SVD& svd = svd_;
00296 const Vector& S = svd.singularValues();
00297 const Index end = svd.nonzeroSingularValues();
00298
00299 Index id;
00300
00301 for (id = end; id > 0; --id) { if (S(id -1) >= lsEps_ ) {break;} }
00302 return id;
00303 }
00304
00305 template <typename MatrixType>
00306 inline typename MatrixInverter<MatrixType>::Scalar
00307 MatrixInverter<MatrixType>::computeDampingSq(const Vector& S) const
00308 {
00309 const Scalar Smin = S(S.size() - 1);
00310 return (Smin >= dlsEps_) ? 0.0 : (1.0 - (Smin * Smin) / (dlsEps_ * dlsEps_)) * (dampMax_ * dampMax_);
00311 }
00312
00313 }
00314
00315
00316 namespace Eigen
00317 {
00318 namespace internal
00319 {
00320
00321 template<typename MatrixType>
00322 struct traits<LsInverseReturnType<MatrixType> > {typedef typename MatrixType::PlainObject ReturnType;};
00323
00328 template<typename MatrixType>
00329 class LsInverseReturnType : public Eigen::ReturnByValue<LsInverseReturnType<MatrixType> >
00330 {
00331 public:
00332 typedef MatrixType Matrix;
00333 typedef typename Matrix::Index Index;
00334 typedef typename Matrix::Scalar Scalar;
00335 typedef typename KDL::MatrixInverter<MatrixType> MatrixInverter;
00336 typedef typename MatrixInverter::Vector Vector;
00337 typedef typename MatrixInverter::SVD SVD;
00338
00340 LsInverseReturnType(MatrixInverter& inverter) : inverter_(inverter) {}
00341
00343 template <typename ResultType> void evalTo(ResultType& result) const;
00344
00345 Index rows() const { return inverter_.svd_.cols(); }
00346 Index cols() const { return inverter_.svd_.rows(); }
00347
00348 private:
00349 MatrixInverter& inverter_;
00350 };
00351
00352 template<typename MatrixType>
00353 struct traits<DlsInverseReturnType<MatrixType> > {typedef typename MatrixType::PlainObject ReturnType;};
00354
00359 template<typename MatrixType>
00360 class DlsInverseReturnType : public Eigen::ReturnByValue<DlsInverseReturnType<MatrixType> >
00361 {
00362 public:
00363 typedef MatrixType Matrix;
00364 typedef typename Matrix::Index Index;
00365 typedef typename Matrix::Scalar Scalar;
00366 typedef typename KDL::MatrixInverter<MatrixType> MatrixInverter;
00367 typedef typename MatrixInverter::Vector Vector;
00368 typedef typename MatrixInverter::SVD SVD;
00369
00371 DlsInverseReturnType(MatrixInverter& inverter) : inverter_(inverter) {}
00372
00374 template <typename ResultType> void evalTo(ResultType& result) const;
00375
00376 Index rows() const { return inverter_.svd_.cols(); }
00377 Index cols() const { return inverter_.svd_.rows(); }
00378
00379 private:
00380 MatrixInverter& inverter_;
00381 };
00382
00383 template<typename MatrixType>
00384 struct traits<LsSolveReturnType<MatrixType> > {typedef typename MatrixType::PlainObject ReturnType;};
00385
00390 template<typename MatrixType>
00391 class LsSolveReturnType : public Eigen::ReturnByValue<LsSolveReturnType<MatrixType> >
00392 {
00393 public:
00394 typedef MatrixType Matrix;
00395 typedef typename Matrix::Index Index;
00396 typedef typename Matrix::Scalar Scalar;
00397 typedef typename KDL::MatrixInverter<MatrixType> MatrixInverter;
00398 typedef typename MatrixInverter::Vector Vector;
00399 typedef typename MatrixInverter::SVD SVD;
00400
00403 LsSolveReturnType(const Vector& b,
00404 MatrixInverter& inverter) : b_(b), inverter_(inverter) {}
00405
00407 template <typename ResultType> void evalTo(ResultType& result) const;
00408
00409 Index rows() const { return inverter_.svd_.cols(); }
00410 Index cols() const { return 1; }
00411
00412 private:
00413 const Vector& b_;
00414 MatrixInverter& inverter_;
00415 };
00416
00417 template<typename MatrixType>
00418 struct traits<DlsSolveReturnType<MatrixType> > {typedef typename MatrixType::PlainObject ReturnType;};
00419
00424 template<typename MatrixType>
00425 class DlsSolveReturnType : public Eigen::ReturnByValue<DlsSolveReturnType<MatrixType> >
00426 {
00427 public:
00428 typedef MatrixType Matrix;
00429 typedef typename Matrix::Index Index;
00430 typedef typename Matrix::Scalar Scalar;
00431 typedef typename KDL::MatrixInverter<MatrixType> MatrixInverter;
00432 typedef typename MatrixInverter::Vector Vector;
00433 typedef typename MatrixInverter::SVD SVD;
00434
00437 DlsSolveReturnType(const Vector& b,
00438 MatrixInverter& inverter) : b_(b), inverter_(inverter) {}
00439
00441 template <typename ResultType> void evalTo(ResultType& result) const;
00442
00443 Index rows() const { return inverter_.svd_.cols(); }
00444 Index cols() const { return 1; }
00445
00446 private:
00447 const Vector& b_;
00448 MatrixInverter& inverter_;
00449 };
00450
00451 template <typename MatrixType> template <typename ResultType>
00452 void LsInverseReturnType<MatrixType>::evalTo(ResultType& result) const
00453 {
00454
00455 Matrix& T = inverter_.pinv_;
00456
00457
00458 const SVD& svd = inverter_.svd_;
00459 const Index rows = svd.rows();
00460 const Index cols = svd.cols();
00461
00462 const Vector& S = svd.singularValues();
00463 const Matrix& U = svd.matrixU();
00464 const Matrix& V = svd.matrixV();
00465
00466
00467
00468
00469
00470 const Index cutoffSize = inverter_.nonzeroSingularValues();
00471 if (rows < cols)
00472 {
00473 T.topLeftCorner(cutoffSize, rows).noalias() =
00474 S.head(cutoffSize).array().inverse().matrix().asDiagonal() * U.leftCols(cutoffSize).transpose();
00475 result.noalias() = V.leftCols(cutoffSize) * T.topLeftCorner(cutoffSize, rows);
00476 }
00477 else
00478 {
00479 T.topLeftCorner(cols, cutoffSize).noalias() =
00480 V.leftCols(cutoffSize) * S.head(cutoffSize).array().inverse().matrix().asDiagonal();
00481 result.noalias() = T.topLeftCorner(cols, cutoffSize) * U.leftCols(cutoffSize).transpose();
00482 }
00483 }
00484
00485 template <typename MatrixType> template <typename ResultType>
00486 void DlsInverseReturnType<MatrixType>::evalTo(ResultType& result) const
00487 {
00488
00489 Matrix& T = inverter_.pinv_;
00490
00491
00492 const SVD& svd = inverter_.svd_;
00493 const Index rows = svd.rows();
00494 const Index cols = svd.cols();
00495
00496 const Vector& S = svd.singularValues();
00497 const Matrix& U = svd.matrixU();
00498 const Matrix& V = svd.matrixV();
00499
00500
00501 const Scalar dampSq = inverter_.computeDampingSq(S);
00502 const Index minDim = std::min(rows, cols);
00503 if (rows < cols)
00504 {
00505 T.topLeftCorner(minDim, minDim).noalias() =
00506 (S.array() / (S.array().square() + dampSq)).matrix().asDiagonal() * U.transpose();
00507 result.noalias() = V * T.topLeftCorner(minDim, minDim);
00508 }
00509 else
00510 {
00511 T.topLeftCorner(minDim, minDim).noalias() =
00512 V * (S.array() / (S.array().square() + dampSq)).matrix().asDiagonal();
00513 result.noalias() = T.topLeftCorner(minDim, minDim) * U.transpose();
00514 }
00515 }
00516
00517 template <typename MatrixType> template <typename ResultType>
00518 inline void LsSolveReturnType<MatrixType>::evalTo(ResultType& result) const
00519 {
00520
00521 Vector& vec1 = inverter_.solve1_;
00522 Vector& vec2 = inverter_.solve2_;
00523
00524
00525 const SVD& svd = inverter_.svd_;
00526 const Vector& S = svd.singularValues();
00527 const Matrix& U = svd.matrixU();
00528 const Matrix& V = svd.matrixV();
00529
00530
00531
00532
00533
00534 const Index cutoffSize = inverter_.nonzeroSingularValues();
00535
00536 vec1.head(cutoffSize).noalias() = U.leftCols(cutoffSize).transpose() * b_;
00537 vec2.head(cutoffSize).noalias() = S.head(cutoffSize).array().inverse().matrix().asDiagonal() *
00538 vec1.head(cutoffSize);
00539 result.noalias() = V.leftCols(cutoffSize) * vec2.head(cutoffSize);
00540 }
00541
00542 template <typename MatrixType> template <typename ResultType>
00543 inline void DlsSolveReturnType<MatrixType>::evalTo(ResultType& result) const
00544 {
00545
00546 Vector& vec1 = inverter_.solve1_;
00547 Vector& vec2 = inverter_.solve2_;
00548
00549
00550 const SVD& svd = inverter_.svd_;
00551 const Vector& S = svd.singularValues();
00552 const Matrix& U = svd.matrixU();
00553 const Matrix& V = svd.matrixV();
00554
00555
00556
00557 const Scalar dampSq = inverter_.computeDampingSq(S);
00558
00559 vec1.noalias() = U.transpose() * b_;
00560 vec2.noalias() = (S.array() / (S.array().square() + dampSq)).matrix().asDiagonal() * vec1;
00561 result.noalias() = V * vec2;
00562 }
00563
00564 }
00565 }
00566
00567 #endif // KDL_MATRIXINVERTER_H