base_multi_edge.hpp
Go to the documentation of this file.
00001 // g2o - General Graph Optimization
00002 // Copyright (C) 2011 R. Kuemmerle, G. Grisetti, H. Strasdat, 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 namespace {
00018   inline int computeUpperTriangleIndex(int i, int j)
00019   {
00020     int elemsUpToCol = ((j-1) * j) / 2;
00021     return elemsUpToCol + i;
00022   }
00023 }
00024 
00025 /******************************************************************************/
00026 
00027 // Sistema:
00028 // 0 = error' * omega * error 
00029 //   + 2 * error' * omega * J * x   +   x' * J' * omega * J * x
00030 // Minimizando con respecto a x:
00031 // 0 = error' * omega * J  +  J' * omega * J * x =>
00032 // 0 =           b'        +         H * x       =>
00033 // H * x = -b'
00034 // 
00035 // Esta funcion calcula H y -b.
00036 
00037 template <int D, typename E>
00038 void BaseMultiEdge<D, E>::constructQuadraticForm()
00039 {
00040    const InformationType& omega = _information;
00041    Matrix<double, D, 1> omega_r = - omega * _error;
00042 
00043    //cerr << "OMEGA: " << omega << endl;
00044    for (size_t i = 0; i < _vertices.size(); ++i)
00045    {
00046       OptimizableGraph::Vertex* from =
00047          static_cast<OptimizableGraph::Vertex*>(_vertices[i]);
00048       bool istatus = !(from->fixed());
00049 
00050       if (istatus)
00051       {
00052          // A = Jacobiana de i con i = Jii
00053          const MatrixXd& A = _jacobianOplus[i];
00054 
00055          MatrixXd AtO = A.transpose() * omega;
00056          int fromDim = from->dimension();
00057          Map<MatrixXd> fromMap(from->hessianData(), fromDim, fromDim);
00058          Map<VectorXd> fromB(from->bData(), fromDim);
00059 
00060          // ii block in the hessian
00061 #ifdef G2O_OPENMP
00062          from->lockQuadraticForm();
00063 #endif
00064          // H * x = -b
00065 
00066          // Hii = A' * omega * A
00067          fromMap.noalias() += AtO * A;
00068 
00069          // -b' = -A' * omega * error
00070          fromB.noalias() += A.transpose() * omega_r;
00071 
00072          // compute the off-diagonal blocks ij for all j
00073          for (size_t j = i+1; j < _vertices.size(); ++j)
00074          {
00075             OptimizableGraph::Vertex* to =
00076                static_cast<OptimizableGraph::Vertex*>(_vertices[j]);
00077 #ifdef G2O_OPENMP
00078             to->lockQuadraticForm();
00079 #endif
00080             bool jstatus = !(to->fixed());
00081             if (jstatus)
00082             {
00083                // B = Jacobiana de i con j = Jij
00084                const MatrixXd& B = _jacobianOplus[j];
00085 
00086                int idx = computeUpperTriangleIndex(i, j);
00087                assert(idx < (int)_hessian.size());
00088 
00089                // Hij = A' * omega * B
00090                HessianHelper& hhelper = _hessian[idx];
00091                if (hhelper.transposed)
00092                {
00093                   // we have to write to the block as transposed
00094                   // Hji = B' * omega' * A
00095                   hhelper.matrix.noalias() += B.transpose() * AtO.transpose();
00096                } else
00097                {
00098                   // Hij = A' * omega * B
00099                   hhelper.matrix.noalias() += AtO * B;
00100                }
00101             }
00102 #ifdef G2O_OPENMP
00103             to->unlockQuadraticForm();
00104 #endif
00105          }
00106 
00107 #ifdef G2O_OPENMP
00108          from->unlockQuadraticForm();
00109 #endif
00110       }
00111    }
00112 }
00113 
00114 /******************************************************************************/
00115 
00116 // Calculo de las jacobiana de forma numerica
00117 
00118 template <int D, typename E>
00119 void BaseMultiEdge<D, E>::linearizeOplus()
00120 {
00121 #ifdef G2O_OPENMP
00122    for (size_t i = 0; i < _vertices.size(); ++i)
00123    {
00124       OptimizableGraph::Vertex* v = 
00125          static_cast<OptimizableGraph::Vertex*>(_vertices[i]);
00126       v->lockQuadraticForm();
00127    }
00128 #endif
00129 
00130    const double delta = 1e-9;
00131    const double scalar = 1.0 / (2*delta);
00132    ErrorVector errorBak;
00133    ErrorVector errorBeforeNumeric = _error;
00134 
00135    for (size_t i = 0; i < _vertices.size(); ++i)
00136    {
00137       // Xi - estimate the jacobian numerically
00138       OptimizableGraph::Vertex* vi = 
00139          static_cast<OptimizableGraph::Vertex*>(_vertices[i]);
00140 
00141       if (vi->fixed())   continue;
00142 
00143       int vi_dim = vi->dimension();
00144       double add_vi[vi_dim];
00145       std::fill(add_vi, add_vi + vi_dim, 0.0);
00146       if  (_jacobianOplus[i].rows() != _dimension 
00147         || _jacobianOplus[i].cols() != vi_dim)
00148          _jacobianOplus[i].resize(_dimension, vi_dim);
00149 
00150       // Add small step along the unit vector in each dimension
00151       for (int d = 0; d < vi_dim; ++d)
00152       {
00153        // if(vi->tempIndex() == 3 && d == 0)
00154        //     std::cerr << " + + + + + + + ++  ++ \n" << std::fixed << std::setprecision(15);
00155          vi->push();
00156          add_vi[d] = delta;
00157          vi->oplus(add_vi);
00158          computeError();
00159          errorBak = _error;
00160          vi->pop();
00161          vi->push();
00162          add_vi[d] = -delta;
00163          vi->oplus(add_vi);
00164          computeError();
00165          errorBak -= _error;
00166          vi->pop();
00167          add_vi[d] = 0.0;
00168 
00169          _jacobianOplus[i].col(d) = scalar * errorBak;
00170          //if(vi->tempIndex() == 3 && d == 0)
00171          //{
00172          //   std::cerr << "Jfx: " << _jacobianOplus[i].col(d).transpose() 
00173          //             << "   delta: " << delta << std::endl;
00174          //   std::cerr << "-----------------------------------------\n" <<  std::resetiosflags (std::ios_base::showbase);
00175          //}
00176       } // end dimension
00177    }
00178    _error = errorBeforeNumeric;
00179 
00180 #ifdef G2O_OPENMP
00181    for (int i = (int)(_vertices.size()) - 1; i >= 0; --i)
00182    {
00183       OptimizableGraph::Vertex* v =
00184          static_cast<OptimizableGraph::Vertex*>(_vertices[i]);
00185       v->unlockQuadraticForm();
00186    }
00187 #endif
00188 }
00189 
00190 /******************************************************************************/
00191 
00192 // Mapea una zona de memoria con la Hessiana ij
00193 template <int D, typename E>
00194 void BaseMultiEdge<D, E>::mapHessianMemory
00195    (double* d, int i, int j, bool rowMajor)
00196 {
00197    int idx = computeUpperTriangleIndex(i, j);
00198    assert(idx < (int)_hessian.size());
00199 
00200    OptimizableGraph::Vertex* vi =
00201       static_cast<OptimizableGraph::Vertex*>(_vertices[i]);
00202 
00203    OptimizableGraph::Vertex* vj =
00204       static_cast<OptimizableGraph::Vertex*>(_vertices[j]);
00205 
00206    HessianHelper& h = _hessian[idx];
00207    if (rowMajor)
00208    {
00209       if (h.matrix.data() != d || h.transposed != rowMajor)
00210          new (&h.matrix) HessianBlockType(d, vj->dimension(), vi->dimension());
00211    }else
00212    {
00213       if (h.matrix.data() != d || h.transposed != rowMajor)
00214          new (&h.matrix) HessianBlockType(d, vi->dimension(), vj->dimension());
00215    }
00216    h.transposed = rowMajor;
00217 }
00218 
00219 /******************************************************************************/
00220 
00221 template <int D, typename E>
00222 void BaseMultiEdge<D, E>::resize(size_t size)
00223 {
00224    BaseEdge<D,E>::resize(size);
00225    int n = (int)_vertices.size();
00226    int maxIdx = (n * (n-1))/2;
00227    assert(maxIdx >= 0);
00228    _hessian.resize(maxIdx);
00229    _jacobianOplus.resize(size);
00230 }


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