g2o
Loading...
Searching...
No Matches
edge_labeler.cpp
Go to the documentation of this file.
1// g2o - General Graph Optimization
2// Copyright (C) 2011 R. Kuemmerle, G. Grisetti, H. Strasdat, W. Burgard
3// All rights reserved.
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
8//
9// * Redistributions of source code must retain the above copyright notice,
10// this list of conditions and the following disclaimer.
11// * Redistributions in binary form must reproduce the above copyright
12// notice, this list of conditions and the following disclaimer in the
13// documentation and/or other materials provided with the distribution.
14//
15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
16// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
17// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
18// PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
21// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27#include "edge_labeler.h"
28
29#include <Eigen/Dense>
30#include <cassert>
31
32#include "g2o/stuff/unscented.h"
33
34namespace g2o {
35
36using namespace std;
37using namespace Eigen;
38
40
42
43int EdgeLabeler::labelEdges(std::set<OptimizableGraph::Edge*>& edges) {
44 // assume the system is "solved"
45 // compute the sparse pattern of the inverse
46 std::set<std::pair<int, int> > pattern;
47 for (std::set<OptimizableGraph::Edge*>::iterator it = edges.begin();
48 it != edges.end(); ++it) {
49 augmentSparsePattern(pattern, *it);
50 }
51
53
54 bool result = computePartialInverse(spInv, pattern);
55 // cerr << "partial inverse computed = " << result << endl;
56 // cerr << "non zero blocks" << spInv.nonZeroBlocks() << endl;
57
58 if (!result) {
59 return -1;
60 }
61 int count = 0;
62 for (std::set<OptimizableGraph::Edge*>::iterator it = edges.begin();
63 it != edges.end(); ++it) {
64 count += labelEdge(spInv, *it) ? 1 : 0;
65 }
66 return count;
67}
68
69void EdgeLabeler::augmentSparsePattern(std::set<std::pair<int, int> >& pattern,
71 for (size_t i = 0; i < e->vertices().size(); i++) {
73 (const OptimizableGraph::Vertex*)e->vertices()[i];
74 int ti = v->hessianIndex();
75 if (ti == -1) continue;
76 for (size_t j = i; j < e->vertices().size(); j++) {
78 (const OptimizableGraph::Vertex*)e->vertices()[j];
79 int tj = v->hessianIndex();
80 if (tj == -1) continue;
81 if (tj < ti) swap(ti, tj);
82 pattern.insert(std::make_pair(ti, tj));
83 }
84 }
85}
86
89 const std::set<std::pair<int, int> >& pattern) {
90 std::vector<std::pair<int, int> > blockIndices(pattern.size());
91 // Why this does not work???
92 // std::copy(pattern.begin(),pattern.end(),blockIndices.begin());
93
94 int k = 0;
95 for (std::set<std::pair<int, int> >::const_iterator it = pattern.begin();
96 it != pattern.end(); ++it) {
97 blockIndices[k++] = *it;
98 }
99
100 // cerr << "sparse pattern contains " << blockIndices.size() << " blocks" <<
101 // endl;
102 return _optimizer->computeMarginals(spinv, blockIndices);
103}
104
107 Eigen::Map<MatrixXd> info(e->informationData(), e->dimension(),
108 e->dimension());
109 // cerr << "original information matrix" << endl;
110 // cerr << info << endl;
111
112 int maxDim = 0;
113 for (size_t i = 0; i < e->vertices().size(); i++) {
114 const OptimizableGraph::Vertex* v =
115 (const OptimizableGraph::Vertex*)e->vertices()[i];
116 int ti = v->hessianIndex();
117 if (ti == -1) continue;
118 maxDim += v->minimalEstimateDimension();
119 }
120
121 // cerr << "maxDim= " << maxDim << endl;
122 MatrixXd cov(maxDim, maxDim);
123 int cumRow = 0;
124 for (size_t i = 0; i < e->vertices().size(); i++) {
125 const OptimizableGraph::Vertex* vr =
126 (const OptimizableGraph::Vertex*)e->vertices()[i];
127 int ti = vr->hessianIndex();
128 if (ti > -1) {
129 int cumCol = 0;
130 for (size_t j = 0; j < e->vertices().size(); j++) {
131 const OptimizableGraph::Vertex* vc =
132 (const OptimizableGraph::Vertex*)e->vertices()[j];
133 int tj = vc->hessianIndex();
134 if (tj > -1) {
135 // cerr << "ti=" << ti << " tj=" << tj
136 // << " cumRow=" << cumRow << " cumCol=" << cumCol << endl;
137 if (ti <= tj) {
138 assert(spinv.block(ti, tj));
139 // cerr << "cblock_ptr" << spinv.block(ti, tj) << endl;
140 // cerr << "cblock.size=" << spinv.block(ti, tj)->rows() << "," <<
141 // spinv.block(ti, tj)->cols() << endl; cerr << "cblock" << endl;
142 // cerr << *spinv.block(ti, tj) << endl;
143 cov.block(cumRow, cumCol, vr->minimalEstimateDimension(),
144 vc->minimalEstimateDimension()) = *spinv.block(ti, tj);
145 } else {
146 assert(spinv.block(tj, ti));
147 // cerr << "cblock.size=" << spinv.block(tj, ti)->cols() << "," <<
148 // spinv.block(tj, ti)->rows() << endl; cerr << "cblock" << endl;
149 // cerr << spinv.block(tj, ti)->transpose() << endl;
150 cov.block(cumRow, cumCol, vr->minimalEstimateDimension(),
152 spinv.block(tj, ti)->transpose();
153 }
154 cumCol += vc->minimalEstimateDimension();
155 }
156 }
157 cumRow += vr->minimalEstimateDimension();
158 }
159 }
160
161 // cerr << "covariance assembled" << endl;
162 // cerr << cov << endl;
163 // now cov contains the aggregate marginals of the state variables in the edge
164 VectorXd incMean(maxDim);
165 incMean.fill(0);
166 std::vector<MySigmaPoint> incrementPoints;
167 if (!sampleUnscented(incrementPoints, incMean, cov)) {
168 cerr << "sampleUnscented fail" << endl;
169 return false;
170 }
171 // now determine the zero-error measure by applying the error function of the
172 // edge with a zero measurement
173 // TODO!!!
174 bool smss = e->setMeasurementFromState();
175 if (!smss) {
176 cerr << "FATAL: Edge::setMeasurementFromState() not implemented" << endl;
177 }
178 assert(smss && "Edge::setMeasurementFromState() not implemented");
179
180 // std::vector<MySigmaPoint> globalPoints(incrementPoints.size());
181 std::vector<MySigmaPoint> errorPoints(incrementPoints.size());
182
183 // for each sigma point, project it to the global space, by considering those
184 // variables that are involved
185 // cerr << "sigma points are extracted, remapping to measurement space" <<
186 // endl;
187 for (size_t i = 0; i < incrementPoints.size(); i++) {
188 int cumPos = 0;
189 // VectorXd globalPoint(maxDim);
190
191 // push all the "active" state variables
192 for (size_t j = 0; j < e->vertices().size(); j++) {
195 int tj = vr->hessianIndex();
196 if (tj == -1) continue;
197 vr->push();
198 }
199
200 for (size_t j = 0; j < e->vertices().size(); j++) {
203 int tj = vr->hessianIndex();
204 if (tj == -1) continue;
205 vr->oplus(&incrementPoints[i]._sample[cumPos]);
206 // assert(vr->getMinimalEstimateData(&globalPoint[cumPos]) &&
207 // "Vertex::getMinimalEstimateData(...) not implemented");
208 cumPos += vr->minimalEstimateDimension();
209 }
210
211 // construct the sigma point in the global space
212 // globalPoints[i]._sample=globalPoint;
213 // globalPoints[i]._wi=incrementPoints[i]._wi;
214 // globalPoints[i]._wp=incrementPoints[i]._wp;
215
216 // construct the sigma point in the error space
217 e->computeError();
218 Map<VectorXd> errorPoint(e->errorData(), e->dimension());
219
220 errorPoints[i]._sample = errorPoint;
221 errorPoints[i]._wi = incrementPoints[i]._wi;
222 errorPoints[i]._wp = incrementPoints[i]._wp;
223
224 // pop all the "active" state variables
225 for (size_t j = 0; j < e->vertices().size(); j++) {
228 int tj = vr->hessianIndex();
229 if (tj == -1) continue;
230 vr->pop();
231 }
232 }
233
234 // reconstruct the covariance of the error by the sigma points
235 MatrixXd errorCov(e->dimension(), e->dimension());
236 VectorXd errorMean(e->dimension());
237 reconstructGaussian(errorMean, errorCov, errorPoints);
238
239 // info=errorCov.inverse();
240 // cerr << "remapped information matrix" << endl;
241 // cerr << info << endl;
242 return true;
243}
244
245} // namespace g2o
const VertexContainer & vertices() const
int dimension() const
returns the dimensions of the error function
virtual void computeError()=0
virtual const double * errorData() const =0
returns the error vector cached after calling the computeError;
virtual const double * informationData() const =0
A general case Vertex for optimization.
virtual void push()=0
backup the position of the vertex to a stack
virtual int minimalEstimateDimension() const
Sparse matrix which uses blocks.
SparseMatrixBlock * block(int r, int c, bool alloc=false)
bool computeMarginals(SparseBlockMatrix< MatrixX > &spinv, const std::vector< std::pair< int, int > > &blockIndices)
Definition jet.h:938
void reconstructGaussian(SampleType &mean, CovarianceType &covariance, const std::vector< SigmaPoint< SampleType > > &sigmaPoints)
Definition unscented.h:77
bool sampleUnscented(std::vector< SigmaPoint< SampleType > > &sigmaPoints, const SampleType &mean, const CovarianceType &covariance)
Definition unscented.h:48
SigmaPoint< VectorXd > MySigmaPoint
Definition jet.h:876
void augmentSparsePattern(std::set< std::pair< int, int > > &pattern, OptimizableGraph::Edge *e)
bool computePartialInverse(SparseBlockMatrix< Eigen::MatrixXd > &spinv, const std::set< std::pair< int, int > > &pattern)
bool labelEdge(const SparseBlockMatrix< Eigen::MatrixXd > &spinv, OptimizableGraph::Edge *e)
int labelEdges(std::set< OptimizableGraph::Edge * > &edges)
EdgeLabeler(SparseOptimizer *optimizer)
SparseOptimizer * _optimizer