marginal_covariance_cholesky.cpp
Go to the documentation of this file.
00001 // g2o - General Graph Optimization
00002 // Copyright (C) 2011 R. Kuemmerle, G. Grisetti, W. Burgard
00003 // 
00004 // g2o is free software: you can redistribute it and/or modify
00005 // it under the terms of the GNU Lesser General Public License as published
00006 // by the Free Software Foundation, either version 3 of the License, or
00007 // (at your option) any later version.
00008 // 
00009 // g2o is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 // GNU Lesser General Public License for more details.
00013 // 
00014 // You should have received a copy of the GNU Lesser General Public License
00015 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
00016 
00017 #include "marginal_covariance_cholesky.h"
00018 
00019 #include <algorithm>
00020 #include <cassert>
00021 using namespace std;
00022 
00023 namespace g2o {
00024 
00025 struct MatrixElem
00026 {
00027   int r, c;
00028   MatrixElem(int r_, int c_) : r(r_), c(c_) {}
00029   bool operator<(const MatrixElem& other) const
00030   {
00031     return c > other.c || (c == other.c && r > other.r);
00032   }
00033 };
00034 
00035 MarginalCovarianceCholesky::MarginalCovarianceCholesky() :
00036   _n(0), _Ap(0), _Ai(0), _Ax(0), _perm(0)
00037 {
00038 }
00039 
00040 MarginalCovarianceCholesky::~MarginalCovarianceCholesky()
00041 {
00042 }
00043 
00044 void MarginalCovarianceCholesky::setCholeskyFactor(int n, int* Lp, int* Li, double* Lx, int* permInv)
00045 {
00046   _n = n;
00047   _Ap = Lp;
00048   _Ai = Li;
00049   _Ax = Lx;
00050   _perm = permInv;
00051 
00052   // pre-compute reciprocal values of the diagonal of L
00053   _diag.resize(n);
00054   for (int r = 0; r < n; ++r) {
00055     const int& sc = _Ap[r]; // L is lower triangular, thus the first elem in the column is the diagonal entry
00056     assert(r == _Ai[sc] && "Error in CCS storage of L");
00057     _diag[r] = 1.0 / _Ax[sc];
00058   }
00059 }
00060 
00061 void MarginalCovarianceCholesky::computeCovariance(const std::vector<OptimizableGraph::Vertex*>& vertices)
00062 {
00063   int maxDimension = -1;
00064   _map.clear();
00065   vector<MatrixElem> elemsToCompute;
00066   for (size_t i = 0; i < vertices.size(); ++i) {
00067     OptimizableGraph::Vertex* v = vertices[i];
00068     int vdim = v->dimension();
00069     int base = v->colInHessian();
00070     maxDimension = std::max(vdim, maxDimension);
00071     for (int rr = 0; rr < vdim; ++rr)
00072       for (int cc = rr; cc < vdim; ++cc) {
00073         int r = _perm ? _perm[rr + base] : rr + base; // apply permutation
00074         int c = _perm ? _perm[cc + base] : cc + base;
00075         if (r > c)
00076           swap(r, c);
00077         elemsToCompute.push_back(MatrixElem(r, c));
00078       }
00079   }
00080 
00081   // sort the elems to reduce the number of recursive calls
00082   sort(elemsToCompute.begin(), elemsToCompute.end());
00083 
00084   // compute the inverse elements we need
00085   for (size_t i = 0; i < elemsToCompute.size(); ++i) {
00086     const MatrixElem& me = elemsToCompute[i];
00087     computeEntry(me.r, me.c);
00088   }
00089 
00090 #ifdef _MSC_VER
00091   double* cov = new double[maxDimension * maxDimension];
00092 #else // allocation from the stack
00093   double cov[maxDimension * maxDimension];
00094 #endif
00095 
00096   // set the marginal covariance for the vertices
00097   for (size_t i = 0; i < vertices.size(); ++i) {
00098     OptimizableGraph::Vertex* v = vertices[i];
00099     int vdim = v->dimension();
00100     int base = v->colInHessian();
00101     for (int rr = 0; rr < vdim; ++rr)
00102       for (int cc = rr; cc < vdim; ++cc) {
00103         int r = _perm ? _perm[rr + base] : rr + base; // apply permutation
00104         int c = _perm ? _perm[cc + base] : cc + base;
00105         if (r > c)
00106           swap(r, c);
00107         int idx = computeIndex(r, c);
00108         LookupMap::const_iterator foundIt = _map.find(idx);
00109         assert(foundIt != _map.end());
00110         cov[rr*vdim + cc] = foundIt->second;
00111         if (rr != cc)
00112           cov[cc*vdim + rr] = foundIt->second;
00113       }
00114     v->setUncertainty(cov);
00115   }
00116 #ifdef _MSC_VER
00117   delete[] cov;
00118 #endif
00119 }
00120 
00121 double MarginalCovarianceCholesky::computeEntry(int r, int c)
00122 {
00123   assert(r <= c);
00124   int idx = computeIndex(r, c);
00125 
00126   LookupMap::const_iterator foundIt = _map.find(idx);
00127   if (foundIt != _map.end()) {
00128     return foundIt->second;
00129   }
00130 
00131   // compute the summation over column r
00132   double s = 0.;
00133   const int& sc = _Ap[r];
00134   const int& ec = _Ap[r+1];
00135   for (int j = sc+1; j < ec; ++j) { // sum over row r while skipping the element on the diagonal
00136     const int& rr = _Ai[j];
00137     double val = rr < c ? computeEntry(rr, c) : computeEntry(c, rr);
00138     s += val * _Ax[j];
00139   }
00140 
00141   double result;
00142   if (r == c) {
00143     const double& diagElem = _diag[r];
00144     result = diagElem * (diagElem - s);
00145   } else {
00146     result = -s * _diag[r];
00147   }
00148   _map[idx] = result;
00149   return result;
00150 }
00151 
00152 void MarginalCovarianceCholesky::computeCovariance(double** covBlocks, const std::vector<int>& blockIndices)
00153 {
00154   _map.clear();
00155   int base = 0;
00156   vector<MatrixElem> elemsToCompute;
00157   for (size_t i = 0; i < blockIndices.size(); ++i) {
00158     int nbase = blockIndices[i];
00159     int vdim = nbase - base;
00160     for (int rr = 0; rr < vdim; ++rr)
00161       for (int cc = rr; cc < vdim; ++cc) {
00162         int r = _perm ? _perm[rr + base] : rr + base; // apply permutation
00163         int c = _perm ? _perm[cc + base] : cc + base;
00164         if (r > c) // make sure it's still upper triangular after applying the permutation
00165           swap(r, c);
00166         elemsToCompute.push_back(MatrixElem(r, c));
00167       }
00168     base = nbase;
00169   }
00170 
00171   // sort the elems to reduce the recursive calls
00172   sort(elemsToCompute.begin(), elemsToCompute.end());
00173 
00174   // compute the inverse elements we need
00175   for (size_t i = 0; i < elemsToCompute.size(); ++i) {
00176     const MatrixElem& me = elemsToCompute[i];
00177     computeEntry(me.r, me.c);
00178   }
00179 
00180   // set the marginal covariance for the vertices, by writing to the blocks memory
00181   base = 0;
00182   for (size_t i = 0; i < blockIndices.size(); ++i) {
00183     int nbase = blockIndices[i];
00184     int vdim = nbase - base;
00185     double* cov = covBlocks[i];
00186     for (int rr = 0; rr < vdim; ++rr)
00187       for (int cc = rr; cc < vdim; ++cc) {
00188         int r = _perm ? _perm[rr + base] : rr + base; // apply permutation
00189         int c = _perm ? _perm[cc + base] : cc + base;
00190         if (r > c) // upper triangle
00191           swap(r, c);
00192         int idx = computeIndex(r, c);
00193         LookupMap::const_iterator foundIt = _map.find(idx);
00194         assert(foundIt != _map.end());
00195         cov[rr*vdim + cc] = foundIt->second;
00196         if (rr != cc)
00197           cov[cc*vdim + rr] = foundIt->second;
00198       }
00199     base = nbase;
00200   }
00201 }
00202 
00203 
00204   void MarginalCovarianceCholesky::computeCovariance(SparseBlockMatrix<MatrixXd>& spinv, const std::vector<int>& rowBlockIndices, const std::vector< std::pair<int, int> >& blockIndices)
00205 {
00206   // allocate the sparse
00207   spinv = SparseBlockMatrix<MatrixXd>(&rowBlockIndices[0], 
00208                                       &rowBlockIndices[0], 
00209                                       rowBlockIndices.size(),
00210                                       rowBlockIndices.size(), true);
00211   _map.clear();
00212   vector<MatrixElem> elemsToCompute;
00213   for (size_t i = 0; i < blockIndices.size(); ++i) {
00214     int blockRow=blockIndices[i].first;    
00215     int blockCol=blockIndices[i].second;
00216     assert (blockRow>=0);
00217     assert (blockRow < (int)rowBlockIndices.size());
00218     assert (blockCol>=0);
00219     assert (blockCol < (int)rowBlockIndices.size());
00220 
00221     int rowBase=spinv.rowBaseOfBlock(blockRow);
00222     int colBase=spinv.colBaseOfBlock(blockCol);
00223     
00224     MatrixXd *block=spinv.block(blockRow, blockCol, true);
00225     assert(block);
00226     for (int iRow=0; iRow<block->rows(); iRow++)
00227       for (int iCol=0; iCol<block->cols(); iCol++){
00228         int rr=rowBase+iRow;
00229         int cc=colBase+iCol;
00230         int r = _perm ? _perm[rr] : rr; // apply permutation
00231         int c = _perm ? _perm[cc] : cc;
00232         if (r > c)
00233           swap(r, c);
00234         elemsToCompute.push_back(MatrixElem(r, c));
00235       }
00236   }
00237 
00238   // sort the elems to reduce the number of recursive calls
00239   sort(elemsToCompute.begin(), elemsToCompute.end());
00240 
00241   // compute the inverse elements we need
00242   for (size_t i = 0; i < elemsToCompute.size(); ++i) {
00243     const MatrixElem& me = elemsToCompute[i];
00244     computeEntry(me.r, me.c);
00245   }
00246 
00247   // set the marginal covariance 
00248   for (size_t i = 0; i < blockIndices.size(); ++i) {
00249     int blockRow=blockIndices[i].first;    
00250     int blockCol=blockIndices[i].second;
00251     int rowBase=spinv.rowBaseOfBlock(blockRow);
00252     int colBase=spinv.colBaseOfBlock(blockCol);
00253     
00254     MatrixXd *block=spinv.block(blockRow, blockCol);
00255     assert(block);
00256     for (int iRow=0; iRow<block->rows(); iRow++)
00257       for (int iCol=0; iCol<block->cols(); iCol++){
00258         int rr=rowBase+iRow;
00259         int cc=colBase+iCol;
00260         int r = _perm ? _perm[rr] : rr; // apply permutation
00261         int c = _perm ? _perm[cc] : cc;
00262         if (r > c)
00263           swap(r, c);
00264         int idx = computeIndex(r, c);
00265         LookupMap::const_iterator foundIt = _map.find(idx);
00266         assert(foundIt != _map.end());
00267         (*block)(iRow, iCol) = foundIt->second;
00268       }
00269   }
00270 }
00271 
00272 } // end namespace


re_vision
Author(s): Dorian Galvez-Lopez
autogenerated on Sun Jan 5 2014 11:31:52