g2o
edge_labeler.cpp
Go to the documentation of this file.
1 #include <Eigen/Dense>
2 #include "edge_labeler.h"
3 #include "g2o/stuff/unscented.h"
4 
5 namespace g2o {
6 
7  using namespace std;
8  using namespace Eigen;
9 
11 
13  _optimizer = optimizer;
14  }
15 
16  int EdgeLabeler::labelEdges(std::set<OptimizableGraph::Edge*>& edges){
17  // assume the system is "solved"
18  // compute the sparse pattern of the inverse
19  std::set<std::pair<int, int> > pattern;
20  for (std::set<OptimizableGraph::Edge*>::iterator it=edges.begin(); it!=edges.end(); it++){
21  augmentSparsePattern(pattern, *it);
22  }
23 
24 
26 
27  bool result = computePartialInverse(spInv, pattern);
28  //cerr << "partial inverse computed = " << result << endl;
29  //cerr << "non zero blocks" << spInv.nonZeroBlocks() << endl;
30 
31  if (! result ){
32  return -1;
33  }
34  int count=0;
35  for (std::set<OptimizableGraph::Edge*>::iterator it=edges.begin(); it!=edges.end(); it++){
36  count += labelEdge(spInv, *it) ? 1 : 0;
37  }
38  return count;
39  }
40 
41  void EdgeLabeler::augmentSparsePattern(std::set<std::pair<int, int> >& pattern, OptimizableGraph::Edge* e){
42  for (size_t i=0; i<e->vertices().size(); i++){
44  int ti=v->hessianIndex();
45  if (ti==-1)
46  continue;
47  for (size_t j=i; j<e->vertices().size(); j++){
49  int tj = v->hessianIndex();
50  if (tj==-1)
51  continue;
52  if(tj<ti)
53  swap(ti,tj);
54  pattern.insert(std::make_pair(ti, tj));
55  }
56  }
57  }
58 
59  bool EdgeLabeler::computePartialInverse(SparseBlockMatrix<MatrixXd>& spinv, const std::set<std::pair<int,int> >& pattern){
60  std::vector<std::pair<int, int> > blockIndices(pattern.size());
61  // Why this does not work???
62  //std::copy(pattern.begin(),pattern.end(),blockIndices.begin());
63 
64  int k=0;
65  for(std::set<std::pair<int, int> >::const_iterator it= pattern.begin(); it!=pattern.end(); it++){
66  blockIndices[k++]=*it;
67  }
68 
69  //cerr << "sparse pattern contains " << blockIndices.size() << " blocks" << endl;
70  return _optimizer->computeMarginals(spinv, blockIndices);
71  }
72 
74 
75  Eigen::Map<MatrixXd> info(e->informationData(), e->dimension(), e->dimension());
76  // cerr << "original information matrix" << endl;
77  // cerr << info << endl;
78 
79  int maxDim=0;
80  for (size_t i=0; i<e->vertices().size(); i++){
82  int ti=v->hessianIndex();
83  if (ti==-1)
84  continue;
85  maxDim+=v->minimalEstimateDimension();
86  }
87 
88 
89  //cerr << "maxDim= " << maxDim << endl;
90  MatrixXd cov(maxDim, maxDim);
91  int cumRow=0;
92  for (size_t i=0; i<e->vertices().size(); i++){
94  int ti=vr->hessianIndex();
95  if (ti>-1) {
96  int cumCol=0;
97  for (size_t j=0; j<e->vertices().size(); j++){
99  int tj = vc->hessianIndex();
100  if (tj>-1){
101  // cerr << "ti=" << ti << " tj=" << tj
102  // << " cumRow=" << cumRow << " cumCol=" << cumCol << endl;
103  if (ti<=tj){
104  assert(spinv.block(ti, tj));
105  // cerr << "cblock_ptr" << spinv.block(ti, tj) << endl;
106  // cerr << "cblock.size=" << spinv.block(ti, tj)->rows() << "," << spinv.block(ti, tj)->cols() << endl;
107  // cerr << "cblock" << endl;
108  // cerr << *spinv.block(ti, tj) << endl;
109  cov.block(cumRow, cumCol, vr->minimalEstimateDimension(), vc->minimalEstimateDimension()) =
110  *spinv.block(ti, tj);
111  } else {
112  assert(spinv.block(tj, ti));
113  // cerr << "cblock.size=" << spinv.block(tj, ti)->cols() << "," << spinv.block(tj, ti)->rows() << endl;
114  // cerr << "cblock" << endl;
115  // cerr << spinv.block(tj, ti)->transpose() << endl;
116  cov.block(cumRow, cumCol, vr->minimalEstimateDimension(), vc->minimalEstimateDimension()) =
117  spinv.block(tj, ti)->transpose();
118  }
119  cumCol += vc->minimalEstimateDimension();
120  }
121  }
122  cumRow += vr->minimalEstimateDimension();
123  }
124  }
125 
126  // cerr << "covariance assembled" << endl;
127  // cerr << cov << endl;
128  // now cov contains the aggregate marginals of the state variables in the edge
129  VectorXd incMean(maxDim);
130  incMean.fill(0);
131  std::vector<MySigmaPoint, Eigen::aligned_allocator<MySigmaPoint> > incrementPoints;
132  if (! sampleUnscented(incrementPoints, incMean, cov)){
133  cerr << "sampleUnscented fail" << endl;
134  return false;
135  }
136  // now determine the zero-error measure by applying the error function of the edge
137  // with a zero measurement
138  // TODO!!!
139  bool smss = e->setMeasurementFromState();
140  if (! smss) {
141  cerr << "FATAL: Edge::setMeasurementFromState() not implemented" << endl;
142  }
143  assert(smss && "Edge::setMeasurementFromState() not implemented");
144 
145  //std::vector<MySigmaPoint> globalPoints(incrementPoints.size());
146  std::vector<MySigmaPoint, Eigen::aligned_allocator<MySigmaPoint> > errorPoints(incrementPoints.size());
147 
148  // for each sigma point, project it to the global space, by considering those variables
149  // that are involved
150  //cerr << "sigma points are extracted, remapping to measurement space" << endl;
151  for (size_t i=0; i<incrementPoints.size(); i++) {
152  int cumPos=0;
153  //VectorXd globalPoint(maxDim);
154 
155  // push all the "active" state variables
156  for (size_t j=0; j<e->vertices().size(); j++){
158  int tj=vr->hessianIndex();
159  if (tj==-1)
160  continue;
161  vr->push();
162  }
163 
164  for (size_t j=0; j<e->vertices().size(); j++){
166  int tj=vr->hessianIndex();
167  if (tj==-1)
168  continue;
169  vr->oplus(&incrementPoints[i]._sample[cumPos]);
170  //assert(vr->getMinimalEstimateData(&globalPoint[cumPos]) && "Vertex::getMinimalEstimateData(...) not implemented");
171  cumPos+=vr->minimalEstimateDimension();
172  }
173 
174  // construct the sigma point in the global space
175  // globalPoints[i]._sample=globalPoint;
176  // globalPoints[i]._wi=incrementPoints[i]._wi;
177  // globalPoints[i]._wp=incrementPoints[i]._wp;
178 
179  // construct the sigma point in the error space
180  e->computeError();
181  Map<VectorXd> errorPoint(e->errorData(),e->dimension());
182 
183  errorPoints[i]._sample=errorPoint;
184  errorPoints[i]._wi=incrementPoints[i]._wi;
185  errorPoints[i]._wp=incrementPoints[i]._wp;
186 
187  // pop all the "active" state variables
188  for (size_t j=0; j<e->vertices().size(); j++){
190  int tj=vr->hessianIndex();
191  if (tj==-1)
192  continue;
193  vr->pop();
194  }
195 
196  }
197 
198  // reconstruct the covariance of the error by the sigma points
199  MatrixXd errorCov(e->dimension(), e->dimension());
200  VectorXd errorMean(e->dimension());
201  reconstructGaussian(errorMean, errorCov, errorPoints);
202  info=errorCov.inverse();
203 
204  // cerr << "remapped information matrix" << endl;
205  // cerr << info << endl;
206  return true;
207  }
208 
209 }
int labelEdges(std::set< OptimizableGraph::Edge * > &edges)
virtual const double * errorData() const =0
returns the error vector cached after calling the computeError;
int dimension() const
returns the dimensions of the error function
SparseMatrixBlock * block(int r, int c, bool alloc=false)
returns the block at location r,c. if alloc=true he block is created if it does not exist ...
void reconstructGaussian(SampleType &mean, CovarianceType &covariance, const std::vector< SigmaPoint< SampleType >, Eigen::aligned_allocator< SigmaPoint< SampleType > > > &sigmaPoints)
Definition: unscented.h:78
EdgeLabeler(SparseOptimizer *optimizer)
int hessianIndex() const
temporary index of this node in the parameter vector obtained from linearization
virtual const double * informationData() const =0
returns the memory of the information matrix, usable for example with a Eigen::Map<MatrixXD> ...
const VertexContainer & vertices() const
Definition: hyper_graph.h:178
virtual void computeError()=0
void augmentSparsePattern(std::set< std::pair< int, int > > &pattern, OptimizableGraph::Edge *e)
virtual void push()=0
backup the position of the vertex to a stack
virtual void pop()=0
restore the position of the vertex by retrieving the position from the stack
virtual int minimalEstimateDimension() const
bool labelEdge(const SparseBlockMatrix< Eigen::MatrixXd > &spinv, OptimizableGraph::Edge *e)
bool sampleUnscented(std::vector< SigmaPoint< SampleType >, Eigen::aligned_allocator< SigmaPoint< SampleType > > > &sigmaPoints, const SampleType &mean, const CovarianceType &covariance)
Definition: unscented.h:49
A general case Vertex for optimization.
bool computePartialInverse(SparseBlockMatrix< Eigen::MatrixXd > &spinv, const std::set< std::pair< int, int > > &pattern)
SigmaPoint< VectorXd > MySigmaPoint
Sparse matrix which uses blocks.