block_solver.hpp
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 "graph_optimizer_sparse.h"
00018 #include <Eigen/LU>
00019 #include <fstream>
00020 #include <iomanip>
00021 
00022 #include "g2o/stuff/timeutil.h"
00023 
00024 namespace g2o {
00025   using namespace std;
00026   using namespace Eigen;
00027 
00028 template <typename Traits>
00029 BlockSolver<Traits>::BlockSolver
00030 (
00031    SparseOptimizer* optimizer, LinearSolverType* linearSolver
00032 ):
00033    Solver(optimizer), _linearSolver(linearSolver)
00034 {
00035    // workspace
00036    _Hpp=0;
00037    _Hll=0;
00038    _Hpl=0;
00039    _Hschur=0;
00040    _DInvSchur=0;
00041    _coefficients=0;
00042    _bschur = 0;
00043    _xSize=0;
00044    _numPoses=0;
00045    _numLandmarks=0;
00046    _sizePoses=0;
00047    _sizeLandmarks=0;
00048    _doSchur=true;
00049 }
00050 
00051 /******************************************************************************/
00052 
00053 template <typename Traits>
00054 void BlockSolver<Traits>::resize
00055 (
00056    int* blockPoseIndices, int numPoseBlocks,
00057    int* blockLandmarkIndices, int numLandmarkBlocks, int s
00058 )
00059 {
00060    delete[] _coefficients;
00061    _coefficients = 0;
00062 
00063    // Definida en solver.[h-cpp]. Reserva espacio a los vectores
00064    // 'x' y 'b'.   (H+lambda*I) * x = -b; size(b) == size(x)
00065    resizeVector(s);
00066    delete _Hpp;
00067    _Hpp=0;
00068    delete _Hll;
00069    _Hll=0;
00070    delete _Hpl;
00071    _Hpl = 0;
00072    delete _Hschur;
00073    _Hschur=0;
00074    delete _DInvSchur;
00075    _DInvSchur=0;
00076 
00077    if (_doSchur)
00078    {
00079       // TODO the following two are only used in schur, actually too large...
00080       _coefficients = new double [s];
00081       _bschur = new double[s];
00082    }
00083 
00084    // SparseBlockMatrix: Una matriz de bloques dispersa esta compuesta por
00085    //    bloques densos que siguen un patron de dispersion no aleatorio.
00086    //    El patron se especifica con una particion de filas y columnas de la
00087    //    matriz. Los bloques densos se representan por una Eigen::Matrix y se
00088    //    pueden declarar estatica o dinamicamente. Todos los bloques de una
00089    //    matriz de bloques estaticos son del mismo tamanio y el tamanio del
00090    //    r-esimo bloque esta especificado por el argumento de la plantilla.
00091    //    Para manejar bloques de diferentes tamanios hay que declarar los
00092    //    bloques de la matriz dinamicos (argumento de plantilla por defecto).
00093    //
00094    // SparseBlockMatrix(int *rbi, int *cbi, int rb, int cb, bool hasStorage)
00095    //    rbi: Vector de enteros. Disposicion en filas de los bloques.
00096    //         El componente i-esimo contiene la 1a fila del bloque i+1.
00097    //    cbi: Vector de enteros. Disposicion en cols de los bloques.
00098    //         El componente i-esimo contiene la 1a col del bloque i+1.
00099    //    rb:  numero de bloques fila
00100    //    cb:  numero de bloques columna
00101    //    hasStorage: true (defecto) si la matriz contiene los bloques.
00102    //                false si la matriz solo contiene referencias a los bloques,
00103    //                es decir, la matriz "ve" bloques ue viven en otro lado.
00104 
00105 
00106    // PoseHessianType == SparseBlockMatrix<PoseMatrixType>
00107    // PoseMatrixType == Matrix<double, 6, 6>
00108    _Hpp = new
00109       PoseHessianType
00110       (
00111          blockPoseIndices, blockPoseIndices, numPoseBlocks, numPoseBlocks
00112       );
00113    if (_doSchur)
00114    {
00115       _Hschur = new
00116          PoseHessianType
00117          (
00118             blockPoseIndices, blockPoseIndices, numPoseBlocks, numPoseBlocks
00119          );
00120 
00121       // LandmarkHessianType == SparseBlockMatrix<LandmarkMatrixType>
00122       // LandmarkMatrixType == Matrix<double, 3, 3>
00123       _Hll = new
00124          LandmarkHessianType
00125          (
00126             blockLandmarkIndices, blockLandmarkIndices,
00127             numLandmarkBlocks, numLandmarkBlocks
00128          );
00129 
00130       _DInvSchur = new
00131          LandmarkHessianType
00132          (
00133             blockLandmarkIndices, blockLandmarkIndices,
00134             numLandmarkBlocks, numLandmarkBlocks
00135          );
00136 
00137       // PoseLandmarkHessianType == SparseBlockMatrix<PoseLandmarkMatrixType>
00138       // PoseLandmarkMatrixType == Matrix<double, 6, 3>
00139       _Hpl=new
00140          PoseLandmarkHessianType
00141          (
00142             blockPoseIndices, blockLandmarkIndices,
00143             numPoseBlocks, numLandmarkBlocks
00144          );
00145    }
00146 }
00147 
00148 /******************************************************************************/
00149 
00150 template <typename Traits>
00151 BlockSolver<Traits>::~BlockSolver()
00152 {
00153    delete _linearSolver;
00154    if (_Hpp)
00155    {
00156       delete _Hpp;
00157       _Hpp=0;
00158    }
00159    if (_Hll)
00160    {
00161       delete _Hll;
00162       _Hll=0;
00163    }
00164    if (_Hpl)
00165    {
00166       delete _Hpl;
00167       _Hpl = 0;
00168    }
00169    if (_Hschur){
00170       delete _Hschur;
00171       _Hschur=0;
00172    }
00173    if (_DInvSchur){
00174       delete _DInvSchur;
00175       _DInvSchur=0;
00176    }
00177    if (_coefficients) {
00178       delete[] _coefficients;
00179       _coefficients = 0;
00180    }
00181    delete[] _bschur;
00182    _bschur = 0;
00183 }
00184 
00185 /******************************************************************************/
00186 
00187 template <typename Traits>
00188 bool BlockSolver<Traits>::buildStructure(bool zeroBlocks)
00189 {
00190    assert(_optimizer);
00191 
00192    size_t sparseDim = 0;
00193    _numPoses=0;
00194    _numLandmarks=0;
00195    _sizePoses=0;
00196    _sizeLandmarks=0;
00197 
00198 
00199 // Dimensionamiento de las matrices Hpp, Hll, Hpl y otras
00200 // No tienen memoria asignada, solo se ha definido el patron
00201    // _optimizer->indexMapping() vector con todos los vertices no fijos.
00202    // Los vertices fijos tienen como indice temporal un -1 y no estan dentro
00203    // de este vector.
00204    int blockPoseIndices[_optimizer->indexMapping().size()];
00205    int blockLandmarkIndices[_optimizer->indexMapping().size()];
00206 
00207 
00208    for (size_t i = 0; i < _optimizer->indexMapping().size(); ++i)
00209    {
00210       OptimizableGraph::Vertex* v = _optimizer->indexMapping()[i];
00211       int dim = v->dimension();
00212 
00213       if (! v->marginalized())
00214       {
00215          v->setColInHessian(_sizePoses);
00216          _sizePoses += dim;
00217          blockPoseIndices[_numPoses] = _sizePoses;
00218          _numPoses++;
00219       } else
00220       {
00221          v->setColInHessian(_sizeLandmarks);
00222          _sizeLandmarks += dim;
00223          blockLandmarkIndices[_numLandmarks] = _sizeLandmarks;
00224          _numLandmarks++;
00225       }
00226       sparseDim += dim;
00227    }
00228 
00229    resize
00230    (
00231       blockPoseIndices, _numPoses, blockLandmarkIndices,
00232       _numLandmarks, sparseDim
00233    );
00234 
00235 
00236 // Asignacion de memoria para los bloques de la diagonal principal y mapeo
00237 // de esos bloques en sus correspondientes vertices.
00238    // allocate the diagonal on Hpp and Hll
00239    int poseIdx = 0;
00240    int landmarkIdx = 0;
00241    for (size_t i = 0; i < _optimizer->indexMapping().size(); ++i)
00242    {
00243       OptimizableGraph::Vertex* v = _optimizer->indexMapping()[i];
00244       if (! v->marginalized())
00245       {
00246          //assert(poseIdx == v->tempIndex());
00247          // PoseMatrixType == Matrix<double, 6, 6>
00248          PoseMatrixType* m = _Hpp->block(poseIdx, poseIdx, true);
00249          if (zeroBlocks)   m->setZero();
00250          v->mapHessianMemory(m->data());
00251          ++poseIdx;
00252       } else
00253       {
00254          LandmarkMatrixType* m = _Hll->block(landmarkIdx, landmarkIdx, true);
00255          if (zeroBlocks)   m->setZero();
00256          v->mapHessianMemory(m->data());
00257          _DInvSchur->block(landmarkIdx, landmarkIdx, true);
00258          ++landmarkIdx;
00259       }
00260    }
00261    assert(poseIdx == _numPoses && landmarkIdx == _numLandmarks);
00262 
00263 // Asignacion de memoria para el resto de los bloques y mapeo
00264 // de esos bloques en sus correspondientes edges.
00265 // Al final, los vertices que no estan relacionados tienen sus correspondientes
00266 // bloques sin asignar
00267 
00268    // here we assume that the landmark indices start after the pose ones
00269    // create the structure in Hpp, Hll and in Hpl
00270    for (SparseOptimizer::EdgeContainer::const_iterator
00271         it  = _optimizer->activeEdges().begin();
00272         it != _optimizer->activeEdges().end();
00273         ++it)
00274    {
00275       OptimizableGraph::Edge* e = *it;
00276 
00277       for (size_t viIdx = 0; viIdx < e->vertices().size(); ++viIdx)
00278       {
00279          OptimizableGraph::Vertex* v1 =
00280             (OptimizableGraph::Vertex*) e->vertices()[viIdx];
00281 
00282          int ind1 = v1->tempIndex();
00283          // Si el vertice es fijo se ignora
00284          if (ind1 == -1)   continue;
00285          int indexV1Bak = ind1;
00286 
00287          for (size_t vjIdx = viIdx + 1; vjIdx < e->vertices().size(); ++vjIdx)
00288          {
00289             OptimizableGraph::Vertex* v2 =
00290                (OptimizableGraph::Vertex*) e->vertices()[vjIdx];
00291 
00292             int ind2 = v2->tempIndex();
00293             // Si el vertice es fijo se ignora
00294             if (ind2 == -1)   continue;
00295             ind1 = indexV1Bak;
00296 
00297             // make sure, we allocate the upper triangle block
00298             bool transposedBlock = ind1 > ind2;
00299             if(transposedBlock)   swap(ind1, ind2);
00300 
00301             if (! v1->marginalized() && !v2->marginalized())
00302             // Si los 2 vertices son Poses
00303             {
00304                PoseMatrixType* m = _Hpp->block(ind1, ind2, true);
00305                if (zeroBlocks)   m->setZero();
00306                e->mapHessianMemory(m->data(), viIdx, vjIdx, transposedBlock);
00307 
00308                // assume this is only needed in case
00309                // we solve with the schur complement
00310                if (_Hschur)   _Hschur->block(ind1, ind2, true);
00311 
00312             }else if (v1->marginalized() && v2->marginalized())
00313             // Si los 2 vertices son Landmarks
00314             // En nuestro caso esto no tiene que ocurrir,
00315             // si ocurre algo esta mal
00316             {
00317                // RAINER hmm.... should we ever reach this here????
00318                LandmarkMatrixType* m =
00319                   _Hll->block(ind1-_numPoses, ind2-_numPoses, true);
00320                if (zeroBlocks)   m->setZero();
00321                e->mapHessianMemory(m->data(), viIdx, vjIdx, false);
00322 
00323             }else
00324             // Si una Pose con un Landmark
00325             {
00326                if (v1->marginalized())
00327                // v1 es Landmark
00328                {
00329                   PoseLandmarkMatrixType* m =
00330                      _Hpl->block
00331                         (v2->tempIndex(),v1->tempIndex()-_numPoses, true);
00332                   if (zeroBlocks)   m->setZero();
00333 
00334                   // transpose the block before writing to it
00335                   e->mapHessianMemory(m->data(), viIdx, vjIdx, true);
00336                }else
00337                // v1 es Pose
00338                {
00339                   PoseLandmarkMatrixType* m =
00340                      _Hpl->block
00341                         (v1->tempIndex(),v2->tempIndex()-_numPoses, true);
00342                   if (zeroBlocks)   m->setZero();
00343 
00344                   // directly the block
00345                   e->mapHessianMemory(m->data(), viIdx, vjIdx, false);
00346                }
00347             }
00348          }
00349       }
00350    }
00351 
00352    if (! _doSchur)   return true;
00353 
00354 
00355 
00356 // Asignacion de memoria para la matriz de Schur
00358    // allocate the blocks for the schurr complement
00359    for (size_t i = 0; i < _optimizer->indexMapping().size(); ++i)
00360    {
00361       OptimizableGraph::Vertex* v = _optimizer->indexMapping()[i];
00362       if (v->marginalized())
00363       {
00364          const HyperGraph::EdgeSet& vedges = v->edges();
00365          for (HyperGraph::EdgeSet::const_iterator
00366               it1  = vedges.begin();
00367               it1 != vedges.end();
00368               it1++)
00369          {
00370 // OSCAR //
00371 
00372             for(size_t i = 0; i < (*it1)->vertices().size(); i++)
00373             {
00374                OptimizableGraph::Vertex* v1;
00375                v1 = (OptimizableGraph::Vertex*) (*it1)->vertices()[i];
00376                //if (v1 == v || v1->tempIndex() == -1)   continue;
00377                if(v1->marginalized() || v1->tempIndex() == -1)   continue;
00378 
00379                for(HyperGraph::EdgeSet::const_iterator
00380                    it2  = vedges.begin();
00381                    it2 != vedges.end();
00382                    it2++)
00383                {
00384                   for(size_t i = 0; i < (*it1)->vertices().size(); i++)
00385                   {
00386                      OptimizableGraph::Vertex* v2;
00387                      v2 = (OptimizableGraph::Vertex*) (*it2)->vertices()[i];
00388                      //if (v2 == v || v2->tempIndex() == -1)   continue;
00389                      if(v2->marginalized() || v2->tempIndex() == -1)   continue;
00390 
00391                      int i1 = v1->tempIndex();
00392                      int i2 = v2->tempIndex();
00393                      if (i1 <= i2)   _Hschur->block(i1,i2,true)->setZero();
00394                   }
00395                }
00396             }
00397 
00398 // FIN OSCAR //
00399 /*
00400             OptimizableGraph::Vertex* v1 =
00401                (OptimizableGraph::Vertex*) (*it1)->vertices()[0];
00402             if (v1 == v)
00403                v1 = (OptimizableGraph::Vertex*) (*it1)->vertices()[1];
00404             if (v1->tempIndex() == -1)   continue;
00405 
00406             for(HyperGraph::EdgeSet::const_iterator
00407                 it2  = vedges.begin();
00408                 it2 != vedges.end();
00409                 it2++)
00410             {
00411                OptimizableGraph::Vertex* v2 =
00412                   (OptimizableGraph::Vertex*) (*it2)->vertices()[0];
00413                if (v2 == v)
00414                   v2 = (OptimizableGraph::Vertex*) (*it2)->vertices()[1];
00415                if (v2->tempIndex() == -1)   continue;
00416 
00417                int i1 = v1->tempIndex();
00418                int i2 = v2->tempIndex();
00419                if (i1 <= i2)   _Hschur->block(i1,i2,true)->setZero();
00420             }
00421 */
00422          }
00423       }
00424    }
00425    return true;
00426 }
00427 
00428 /******************************************************************************/
00429 
00430 // Redimensionamiento y remapeo en memoria para las Hessianas de las Poses
00431 // y, si no se aplica Schur, de los landmarks.
00432 
00433 template <typename Traits>
00434 bool BlockSolver<Traits>::updateStructure
00435 (
00436    const std::vector<HyperGraph::Vertex*>& vset,
00437    const HyperGraph::EdgeSet& edges
00438 )
00439 {
00440    for (std::vector<HyperGraph::Vertex*>::const_iterator
00441         vit = vset.begin();
00442         vit != vset.end();
00443         ++vit)
00444    {
00445       OptimizableGraph::Vertex* v =
00446          static_cast<OptimizableGraph::Vertex*>(*vit);
00447       int dim = v->dimension();
00448       if (! v->marginalized())
00449       {
00450          // Pose
00451          v->setColInHessian(_sizePoses);
00452          _sizePoses += dim;
00453          _Hpp->rowBlockIndices().push_back(_sizePoses);
00454          _Hpp->colBlockIndices().push_back(_sizePoses);
00455          _Hpp->blockCols().push_back
00456          (
00457             typename SparseBlockMatrix<PoseMatrixType>::IntBlockMap()
00458          );
00459          _numPoses++;
00460          int ind = v->tempIndex();
00461          PoseMatrixType* m = _Hpp->block(ind, ind, true);
00462          v->mapHessianMemory(m->data());
00463       }else
00464       {
00465          std::cerr << "updateStructure(): Schur not supported" << std::endl;
00466          abort();
00467       }
00468    }
00469    resizeVector(_sizePoses + _sizeLandmarks);
00470 
00471 
00472    for (HyperGraph::EdgeSet::const_iterator
00473         it = edges.begin();
00474         it != edges.end();
00475         ++it)
00476    {
00477       OptimizableGraph::Edge* e = static_cast<OptimizableGraph::Edge*>(*it);
00478 
00479       for (size_t viIdx = 0; viIdx < e->vertices().size(); ++viIdx)
00480       {
00481          OptimizableGraph::Vertex* v1 =
00482             (OptimizableGraph::Vertex*) e->vertices()[viIdx];
00483 
00484          int ind1 = v1->tempIndex();
00485          int indexV1Bak = ind1;
00486          // Si el vertice es fijo se ignora
00487          if (ind1 == -1)   continue;
00488 
00489          for (size_t vjIdx = viIdx + 1; vjIdx < e->vertices().size(); ++vjIdx)
00490          {
00491             OptimizableGraph::Vertex* v2 =
00492                (OptimizableGraph::Vertex*) e->vertices()[vjIdx];
00493 
00494             int ind2 = v2->tempIndex();
00495             // Si el vertice es fijo se ignora
00496             if (ind2 == -1)   continue;
00497             ind1 = indexV1Bak;
00498 
00499             bool transposedBlock = ind1 > ind2;
00500             // make sure, we allocate the upper triangular block
00501             if (transposedBlock)   swap(ind1, ind2);
00502 
00503             if (! v1->marginalized() && !v2->marginalized())
00504             {
00505                // Ambos vertices son Poses
00506                PoseMatrixType* m = _Hpp->block(ind1, ind2, true);
00507                e->mapHessianMemory(m->data(), viIdx, vjIdx, transposedBlock);
00508             }else
00509             {
00510                std::cerr << __PRETTY_FUNCTION__ << ": not supported\n";
00511             }
00512          }
00513       }
00514    }
00515 
00516    return true;
00517 }
00518 
00519 /******************************************************************************/
00520 
00521 // Resuelve el sistema H * x = -b
00522 template <typename Traits>
00523 bool BlockSolver<Traits>::solve()
00524 {
00525    //cerr << __PRETTY_FUNCTION__ << endl;
00526    if (! _doSchur)
00527    {
00528       // Resolucion del sistema completo
00529       double t=get_time();
00530       bool ok = _linearSolver->solve(*_Hpp, _x, _b);
00531       if (globalStats)
00532       {
00533          globalStats->timeLinearSolver = get_time() - t;
00534          globalStats->hessianDimension =
00535             globalStats->hessianPoseDimension =
00536             _Hpp->cols();
00537       }
00538       return ok;
00539    }
00540 
00541    char fich[] = "Hpp.m";
00542    _Hpp->writeOctave(fich, false);
00543     fich[2] = 'l';
00544    _Hpl->writeOctave(fich, false);
00545     fich[1] = 'l';
00546    _Hll->writeOctave(fich, false);
00547 
00548 /*
00549    cerr << "Pausa. Presiona Enter para continuar.\n";
00550    char a;
00551    cin >> a;
00552 */
00553    // Resolucion mediante el complemento de Schur
00554    // schur thing
00555 
00556    // backup the coefficient matrix
00557    double t=get_time();
00558    _Hschur->clear();
00559    _Hpp->add(_Hschur);
00560    _DInvSchur->clear();
00561    memset(_coefficients, 0, _xSize*sizeof(double));
00562 
00563    for (size_t i = 0; i < _optimizer->indexMapping().size(); ++i)
00564    {
00565       OptimizableGraph::Vertex* v = _optimizer->indexMapping()[i];
00566       if (v->marginalized())
00567       {
00568          // El vertice es un landmark
00569          int landmarkIndex = i - _numPoses;
00570          const HyperGraph::EdgeSet& vedges = v->edges();
00571 
00572          const LandmarkMatrixType *D = _Hll->block(landmarkIndex,landmarkIndex);
00573          assert (D && D->rows()==D->cols());
00574 
00575          LandmarkMatrixType Dinv = D->inverse();
00576          LandmarkMatrixType *_DInvSchurBlock =
00577             _DInvSchur->block(landmarkIndex, landmarkIndex, false);
00578          assert( _DInvSchurBlock
00579               && _DInvSchurBlock->rows() == D->rows()
00580               && _DInvSchurBlock->cols() == D->cols());
00581 
00582          *_DInvSchurBlock = Dinv;
00583          LandmarkVectorType  db(D->rows());
00584          for (int j=0; j<D->rows(); j++)
00585          {
00586             db[j] = _b[v->colInHessian()+_sizePoses+j];
00587          }
00588 
00589          // db = inv(Hll) * bl
00590          db = Dinv * db;
00591 
00592          // helper array for OpenMP parallel
00593          size_t tmpIdx = 0;
00594 #     ifdef _MSC_VER
00595          OptimizableGraph::Edge* tmpEdges =
00596             new OptimizableGraph::Edge*[vedges.size()];
00597 #     else
00598          OptimizableGraph::Edge* tmpEdges[vedges.size()];
00599 #     endif
00600          for (HyperGraph::EdgeSet::const_iterator
00601               it2  = vedges.begin();
00602               it2 != vedges.end();
00603               ++it2)
00604          {
00605             OptimizableGraph::Edge* e2 =
00606                static_cast<OptimizableGraph::Edge*>(*it2);
00607             tmpEdges[tmpIdx++] = e2;
00608          }
00609 
00610 #     ifdef G2O_OPENMP
00611 #     pragma omp parallel for default (shared)
00612 #     endif
00613 
00615          for (size_t l=0; l < tmpIdx; ++l)
00616          {
00617             OptimizableGraph::Edge* e1 = tmpEdges[l];
00618 
00619 // OSCAR //
00620 
00621             for(size_t i = 0; i < e1->vertices().size(); i++)
00622             {
00623                OptimizableGraph::Vertex* v1;
00624                v1 = static_cast<OptimizableGraph::Vertex*>( e1->vertices()[i] );
00625 
00626                if (v1==v)   continue;
00627                assert (!v1->marginalized());
00628 
00629                int i1 = v1->tempIndex();
00630                // Si el vertice es fijo lo ignoramos.
00631                if (i1<0)   continue;
00632 
00633                const PoseLandmarkMatrixType* Bi = _Hpl->block(i1,landmarkIndex);
00634                assert(Bi);
00635 
00636                // Bd = Hpl * inv(Hll) * bl
00637                PoseVectorType Bb = (*Bi)*db;
00638 
00639                v1->lockQuadraticForm();
00640                // coefficients = Hpl * inv(Hll) * bl
00641                for (int j=0; j<Bb.rows(); j++)
00642                {
00643                   _coefficients[v1->colInHessian()+j] += Bb(j);
00644                }
00645 
00646                // BDinv = Hpl * inv(Hll);
00647                PoseLandmarkMatrixType BDinv = (*Bi)*(Dinv);
00648 
00649                for (size_t k =0; k < tmpIdx; ++k)
00650                {
00651                   OptimizableGraph::Edge* e2 = tmpEdges[k];
00652                   for(size_t i = 0; i < e1->vertices().size(); i++)
00653                   {
00654                      OptimizableGraph::Vertex* v2;
00655                      v2 = (OptimizableGraph::Vertex*) e2->vertices()[i];
00656 
00657                      if(v2==v)  continue;;
00658                      assert (!v2->marginalized());
00659 
00660                      int i2 = v2->tempIndex();
00661                      // Si el vertice es fijo o ya esta aniadido por un edge
00662                      // anterior entonces se ignora
00663                      if (i2<0 || i1>i2)  continue;
00664 
00665                      const PoseLandmarkMatrixType* Bj =
00666                         _Hpl->block(i2,landmarkIndex);
00667                      assert(Bj);
00668 
00669                      PoseMatrixType* Hi1i2 = _Hschur->block(i1,i2);
00670                      assert(Hi1i2);
00671                      // HSchur = Hpp - Hpl * inv(Hll) * Hpl'
00672                      (*Hi1i2).noalias() -= BDinv * Bj->transpose();
00673                   }
00674                }
00675                v1->unlockQuadraticForm();
00676             }
00677 // FIN OSCAR //
00678 
00679 /*
00680             OptimizableGraph::Vertex* v1 =
00681                static_cast<OptimizableGraph::Vertex*>( e1->vertices()[0] );
00682 
00683             if (v1==v)   v1 = (OptimizableGraph::Vertex*) e1->vertices()[1];
00684             assert (!v1->marginalized());
00685 
00686             int i1 = v1->tempIndex();
00687             // Si el vertice es fijo lo ignoramos
00688             if (i1<0)   continue;
00689 
00690             const PoseLandmarkMatrixType* Bi = _Hpl->block(i1,landmarkIndex);
00691             assert(Bi);
00692 
00693             // Bd = Hpl * inv(Hll) * bl
00694             PoseVectorType Bb = (*Bi)*db;
00695 
00696             v1->lockQuadraticForm();
00697             // coefficients = Hpl * inv(Hll) * bl
00698             for (int j=0; j<Bb.rows(); j++)
00699             {
00700                _coefficients[v1->colInHessian()+j] += Bb(j);
00701             }
00702 
00703             // BDinv = Hpl * inv(Hll);
00704             PoseLandmarkMatrixType BDinv = (*Bi)*(Dinv);
00705 
00706             for (size_t k =0; k < tmpIdx; ++k)
00707             {
00708                OptimizableGraph::Edge* e2 = tmpEdges[k];
00709                OptimizableGraph::Vertex* v2 =
00710                   (OptimizableGraph::Vertex*) e2->vertices()[0];
00711 
00712                if (v2==v)   v2 = (OptimizableGraph::Vertex*) e2->vertices()[1];
00713                assert (!v2->marginalized());
00714 
00715                int i2 = v2->tempIndex();
00716                // Si el vertice es fijo o ya esta aniadido por un edge anterior
00717                // entonces se ignora
00718                if (i2<0)   continue;
00719                if (i1>i2)  continue;
00720 
00721                const PoseLandmarkMatrixType* Bj = _Hpl->block(i2,landmarkIndex);
00722                assert(Bj);
00723 
00724                PoseMatrixType* Hi1i2 = _Hschur->block(i1,i2);
00725                assert(Hi1i2);
00726                // HSchur = Hpp - Hpl * inv(Hll) * Hpl'
00727                (*Hi1i2).noalias() -= BDinv * Bj->transpose();
00728             }
00729             v1->unlockQuadraticForm();
00730 */
00731          }
00732 #     ifdef _MSC_VER
00733          delete[] tmpEdges;
00734 #     endif
00735       }
00736    }
00737    //cerr << "Solve [marginalize] = " <<  get_time()-t << endl;
00738 
00739 
00740 
00741    // bSchur = -bp + Hpl * inv(Hll) * bl
00742    // _bschur = _b for calling solver, and not touching _b
00743    memcpy(_bschur, _b, _xSize * sizeof(double));
00744    for (int i=0; i<_sizePoses; i++)   _bschur[i] -= _coefficients[i];
00745 
00746    if (globalStats)   globalStats->timeSchurrComplement = get_time() - t;
00747    t = get_time();
00748 
00749    // Resolucion de las poses
00750    // HSchur = Hpp - Hpl * inv(Hll) * Hpl'
00751    // bSchur = -bp + Hpl * inv(Hll) * bl
00752    bool solvedPoses = _linearSolver->solve(*_Hschur, _x, _bschur);
00753 
00754    if (globalStats)
00755    {
00756       globalStats->timeLinearSolver = get_time() - t;
00757       globalStats->hessianPoseDimension = _Hpp->cols();
00758       globalStats->hessianLandmarkDimension = _Hll->cols();
00759       globalStats->hessianDimension =
00760          globalStats->hessianPoseDimension
00761        + globalStats->hessianLandmarkDimension;
00762    }
00763    //cerr << "Solve [decompose and solve] = " <<  get_time()-t << endl;
00764 
00765    if (! solvedPoses)   return false;
00766 
00767 
00768 
00769    // Resolucion de los landmarks
00770 
00771    // _x contains the solution for the poses, now applying it to the landmark
00772    // s to get the new part of the solution;
00773    double* xp = _x;
00774    double* cp = _coefficients;
00775 
00776    double* xl = _x + _sizePoses;
00777    double* cl = _coefficients + _sizePoses;
00778    double* bl = _b + _sizePoses;
00779 
00780    // cp = -xp
00781    for (int i=0; i<_sizePoses; i++)   cp[i] = -xp[i];
00782 
00783    // cl = bl
00784    memcpy(cl, bl,_sizeLandmarks * sizeof(double));
00785 
00786    // cl = bl - Bt * xp
00787    //Bt->multiply(cl, cp);
00788    _Hpl->rightMultiply(cl, cp);
00789 
00790    // xl = Dinv * cl
00791    memset(xl, 0, _sizeLandmarks * sizeof(double));
00792    //_DInvSchur->multiply(xl,cl);
00793    _DInvSchur->rightMultiply(xl,cl);
00794    //cerr << "Solve [landmark delta] = " <<  get_time()-t << endl;
00795 
00796    return true;
00797 }
00798 
00799 /******************************************************************************/
00800 
00801 template <typename Traits>
00802 bool BlockSolver<Traits>::computeMarginals()
00803 {
00804    double t = get_time();
00805    double** blocks =  new double*[_optimizer->indexMapping().size()];
00806 
00807    for (size_t i = 0; i < _optimizer->indexMapping().size(); ++i)
00808    {
00809       OptimizableGraph::Vertex* v = _optimizer->indexMapping()[i];
00810       assert(v->uncertaintyData());
00811       blocks[i] = v->uncertaintyData();
00812    }
00813    bool ok = _linearSolver->solveBlocks(blocks, *_Hpp);
00814    delete [] blocks;
00815 
00816    if (globalStats)  globalStats->timeMarginals = get_time() - t;
00817    return ok;
00818 }
00819 
00820 /******************************************************************************/
00821 
00822 template <typename Traits>
00823 bool BlockSolver<Traits>::computeMarginals
00824 (
00825    SparseBlockMatrix<MatrixXd>& spinv,
00826    const std::vector<std::pair<int, int> >& blockIndices
00827 )
00828 {
00829    double t = get_time();
00830    bool ok = _linearSolver->solvePattern(spinv, blockIndices, *_Hpp);
00831    if (globalStats)   globalStats->timeMarginals = get_time() - t;
00832    return ok;
00833 }
00834 
00835 /******************************************************************************/
00836 
00837 // Calcula la Hessiana y -b y se hace una copia local de -b que se usara al
00838 // resolver el sistema
00839 template <typename Traits>
00840 bool BlockSolver<Traits>::buildSystem()
00841 {
00842    // clear b vector
00843 # ifdef G2O_OPENMP
00844 # pragma omp parallel for default (shared) \
00845      if (_optimizer->indexMapping().size() > 1000)
00846 # endif
00847    for (int i = 0; i < static_cast<int>(_optimizer->indexMapping().size()); ++i)
00848    {
00849       OptimizableGraph::Vertex* v = _optimizer->indexMapping()[i];
00850       assert(v);
00851       // H * x = -b =>
00852       // clearQuadraticForm() => b = 0
00853       v->clearQuadraticForm();
00854    }
00855 
00856    _Hpp->clear();
00857 
00858    if (_doSchur)
00859    {
00860       _Hll->clear();
00861       _Hpl->clear();
00862    }
00863 
00864   // resetting the terms for the pairwise constraints
00865   // built up the current system by storing the Hessian
00866   // blocks in the edges and vertices
00867 # ifdef G2O_OPENMP
00868 # pragma omp parallel for default (shared) \
00869      if (_optimizer->activeEdges().size() > 100)
00870 # endif
00871    for (int k = 0; k < static_cast<int>(_optimizer->activeEdges().size()); ++k)
00872    {
00873       OptimizableGraph::Edge* e = _optimizer->activeEdges()[k];
00874       // Calculo de la Hessiana H y -b del sistema
00875       e->constructQuadraticForm();
00876    }
00877 
00878    // flush the current system in a sparse block matrix
00879 # ifdef G2O_OPENMP
00880 # pragma omp parallel for default (shared) \
00881      if (_optimizer->indexMapping().size() > 1000)
00882 # endif
00883    for (int i = 0; i < static_cast<int>(_optimizer->indexMapping().size()); ++i)
00884    {
00885       OptimizableGraph::Vertex* v = _optimizer->indexMapping()[i];
00886       int iBase = v->colInHessian();
00887 
00888       // Hace una copia local de b del vertice en b del sistema
00889       // Construye el vector b
00890       if (v->marginalized())   iBase += _sizePoses;
00891       v->copyB( _b+iBase );
00892    }
00893 
00894    //cerr << *_Hpp << endl;
00895    //cerr << "\n***************************\n";
00896    //cerr << *_Hll << endl;
00897    //cerr << *_Hpl << endl;
00898 
00899    return 0;
00900 }
00901 
00902 /******************************************************************************/
00903 
00904 // Suma lambda a la diagonal principal (Levenberg–Marquardt)
00905 template <typename Traits>
00906 bool BlockSolver<Traits>::setLambda(double lambda)
00907 {
00908 # ifdef G2O_OPENMP
00909 # pragma omp parallel for default (shared) if (_numPoses > 100)
00910 # endif
00911    for (int i = 0; i < _numPoses; i++)
00912    {
00913       PoseMatrixType *b = _Hpp->block(i,i);
00914       b->diagonal().array() += lambda;
00915    }
00916 # ifdef G2O_OPENMP
00917 # pragma omp parallel for default (shared) if (_numLandmarks > 100)
00918 # endif
00919    for (int i = 0; i < _numLandmarks; i++)
00920    {
00921       LandmarkMatrixType *b=_Hll->block(i,i);
00922       b->diagonal().array() += lambda;
00923    }
00924    return true;
00925 }
00926 
00927 /******************************************************************************/
00928 
00929 template <typename Traits>
00930 bool BlockSolver<Traits>::init(bool online)
00931 {
00932    if (! online)
00933    {
00934       if (_Hpp)   _Hpp->clear();
00935       if (_Hpl)   _Hpl->clear();
00936       if (_Hll)   _Hll->clear();
00937    }
00938    _linearSolver->init();
00939    return true;
00940 }
00941 
00942 /******************************************************************************/
00943 
00944 } // end namespace


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