g2o
Loading...
Searching...
No Matches
estimate_propagator.cpp
Go to the documentation of this file.
1// g2o - General Graph Optimization
2// Copyright (C) 2011 R. Kuemmerle, G. Grisetti, 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 "estimate_propagator.h"
28
29#include <algorithm>
30#include <cassert>
31#include <fstream>
32#include <iostream>
33#include <queue>
34#include <vector>
35
36// #define DEBUG_ESTIMATE_PROPAGATOR
37#ifdef DEBUG_ESTIMATE_PROPAGATOR
38#include "g2o/stuff/logger.h"
39#endif
40
41using namespace std;
42
43namespace g2o {
44
45#ifdef DEBUG_ESTIMATE_PROPAGATOR
46struct FrontierLevelCmp {
47 bool operator()(EstimatePropagator::AdjacencyMapEntry* e1,
48 EstimatePropagator::AdjacencyMapEntry* e2) const {
49 return e1->frontierLevel() < e2->frontierLevel();
50 }
51};
52#endif
53
55
57 _child = 0;
58 _parent.clear();
59 _edge = 0;
60 _distance = numeric_limits<double>::max();
61 _frontierLevel = -1;
62 inQueue = false;
63}
64
66 for (OptimizableGraph::VertexIDMap::const_iterator it =
67 _graph->vertices().begin();
68 it != _graph->vertices().end(); ++it) {
70 entry._child = static_cast<OptimizableGraph::Vertex*>(it->second);
71 _adjacencyMap.insert(make_pair(entry.child(), entry));
72 }
73}
74
76 for (OptimizableGraph::VertexSet::iterator it = _visited.begin();
77 it != _visited.end(); ++it) {
79 AdjacencyMap::iterator at = _adjacencyMap.find(v);
80 assert(at != _adjacencyMap.end());
81 at->second.reset();
82 }
83 _visited.clear();
84}
85
88 const EstimatePropagator::PropagateAction& action, double maxDistance,
89 double maxEdgeCost) {
91 vset.insert(v);
92 propagate(vset, cost, action, maxDistance, maxEdgeCost);
93}
94
98 const EstimatePropagator::PropagateAction& action, double maxDistance,
99 double maxEdgeCost) {
100 reset();
101
102 PriorityQueue frontier;
103 for (OptimizableGraph::VertexSet::iterator vit = vset.begin();
104 vit != vset.end(); ++vit) {
105 OptimizableGraph::Vertex* v = static_cast<OptimizableGraph::Vertex*>(*vit);
106 AdjacencyMap::iterator it = _adjacencyMap.find(v);
107 assert(it != _adjacencyMap.end());
108 it->second._distance = 0.;
109 it->second._parent.clear();
110 it->second._frontierLevel = 0;
111 frontier.push(&it->second);
112 }
113
114 while (!frontier.empty()) {
115 AdjacencyMapEntry* entry = frontier.pop();
116 OptimizableGraph::Vertex* u = entry->child();
117 double uDistance = entry->distance();
118
119 // initialize the vertex
120 if (entry->_frontierLevel > 0) {
121 action(entry->edge(), entry->parent(), u);
122 }
123
124 /* std::pair< OptimizableGraph::VertexSet::iterator, bool> insertResult = */
125 _visited.insert(u);
126 OptimizableGraph::EdgeSet::iterator et = u->edges().begin();
127 while (et != u->edges().end()) {
128 OptimizableGraph::Edge* edge = static_cast<OptimizableGraph::Edge*>(*et);
129 ++et;
130
131 int maxFrontier = -1;
132 OptimizableGraph::VertexSet initializedVertices;
133 for (size_t i = 0; i < edge->vertices().size(); ++i) {
135 static_cast<OptimizableGraph::Vertex*>(edge->vertex(i));
136 if (!z) continue;
137 AdjacencyMap::iterator ot = _adjacencyMap.find(z);
138 if (ot->second._distance != numeric_limits<double>::max()) {
139 initializedVertices.insert(z);
140 maxFrontier = (max)(maxFrontier, ot->second._frontierLevel);
141 }
142 }
143 assert(maxFrontier >= 0);
144
145 for (size_t i = 0; i < edge->vertices().size(); ++i) {
147 static_cast<OptimizableGraph::Vertex*>(edge->vertex(i));
148 if (!z) continue;
149 if (z == u) continue;
150 size_t wasInitialized = initializedVertices.erase(z);
151
152 double edgeDistance = cost(edge, initializedVertices, z);
153 if (edgeDistance > 0. &&
154 edgeDistance != std::numeric_limits<double>::max() &&
155 edgeDistance < maxEdgeCost) {
156 double zDistance = uDistance + edgeDistance;
157
158 AdjacencyMap::iterator ot = _adjacencyMap.find(z);
159 assert(ot != _adjacencyMap.end());
160
161 if (zDistance < ot->second.distance() && zDistance < maxDistance) {
162 ot->second._distance = zDistance;
163 ot->second._parent = initializedVertices;
164 ot->second._edge = edge;
165 ot->second._frontierLevel = maxFrontier + 1;
166 frontier.push(&ot->second);
167 }
168 }
169
170 if (wasInitialized > 0) initializedVertices.insert(z);
171 }
172 }
173 }
174
175 // writing debug information like cost for reaching each vertex and the parent
176 // used to initialize
177#ifdef DEBUG_ESTIMATE_PROPAGATOR
178 G2O_DEBUG("Writing cost.dat");
179 ofstream costStream("cost.dat");
180 for (AdjacencyMap::const_iterator it = _adjacencyMap.begin();
181 it != _adjacencyMap.end(); ++it) {
182 HyperGraph::Vertex* u = it->second.child();
183 costStream << "vertex " << u->id() << " cost " << it->second._distance
184 << endl;
185 }
186 G2O_DEBUG("Writing init.dat");
187 ofstream initStream("init.dat");
188 vector<AdjacencyMapEntry*> frontierLevels;
189 for (AdjacencyMap::iterator it = _adjacencyMap.begin();
190 it != _adjacencyMap.end(); ++it) {
191 if (it->second._frontierLevel > 0) frontierLevels.push_back(&it->second);
192 }
193 sort(frontierLevels.begin(), frontierLevels.end(), FrontierLevelCmp());
194 for (vector<AdjacencyMapEntry*>::const_iterator it = frontierLevels.begin();
195 it != frontierLevels.end(); ++it) {
196 AdjacencyMapEntry* entry = *it;
197 OptimizableGraph::Vertex* to = entry->child();
198
199 initStream << "calling init level = " << entry->_frontierLevel << "\t (";
200 for (OptimizableGraph::VertexSet::iterator pit = entry->parent().begin();
201 pit != entry->parent().end(); ++pit) {
202 initStream << " " << (*pit)->id();
203 }
204 initStream << " ) -> " << to->id() << endl;
205 }
206#endif
207}
208
210 assert(entry != NULL);
211 if (entry->inQueue) {
212 assert(entry->queueIt->second == entry);
213 erase(entry->queueIt);
214 }
215
216 entry->queueIt = insert(std::make_pair(entry->distance(), entry));
217 assert(entry->queueIt != end());
218 entry->inQueue = true;
219}
220
223 assert(!empty());
224 iterator it = begin();
225 AdjacencyMapEntry* entry = it->second;
226 erase(it);
227
228 assert(entry != NULL);
229 entry->queueIt = end();
230 entry->inQueue = false;
231 return entry;
232}
233
236
239 OptimizableGraph::Vertex* to_) const {
240 OptimizableGraph::Edge* e = dynamic_cast<OptimizableGraph::Edge*>(edge);
241 OptimizableGraph::Vertex* to = dynamic_cast<OptimizableGraph::Vertex*>(to_);
242 SparseOptimizer::EdgeContainer::const_iterator it = _graph->findActiveEdge(e);
243 if (it == _graph->activeEdges().end()) // it has to be an active edge
244 return std::numeric_limits<double>::max();
245 return e->initialEstimatePossible(from, to);
246}
247
251
254 OptimizableGraph::Vertex* to_) const {
255 OptimizableGraph::Edge* e = dynamic_cast<OptimizableGraph::Edge*>(edge);
257 dynamic_cast<OptimizableGraph::Vertex*>(*from_.begin());
258 OptimizableGraph::Vertex* to = dynamic_cast<OptimizableGraph::Vertex*>(to_);
259 if (std::abs(from->id() - to->id()) !=
260 1) // simple method to identify odometry edges in a pose graph
261 return std::numeric_limits<double>::max();
262 SparseOptimizer::EdgeContainer::const_iterator it = _graph->findActiveEdge(e);
263 if (it == _graph->activeEdges().end()) // it has to be an active edge
264 return std::numeric_limits<double>::max();
265 return e->initialEstimatePossible(from_, to);
266}
267
268} // namespace g2o
double operator()(OptimizableGraph::Edge *edge, const OptimizableGraph::VertexSet &from_, OptimizableGraph::Vertex *to_) const override
EstimatePropagatorCostOdometry(SparseOptimizer *graph)
cost for traversing along active edges in the optimizer
virtual double operator()(OptimizableGraph::Edge *edge, const OptimizableGraph::VertexSet &from, OptimizableGraph::Vertex *to_) const
EstimatePropagatorCost(SparseOptimizer *graph)
data structure for loopuk during Dijkstra
const OptimizableGraph::VertexSet & parent() const
OptimizableGraph::Vertex * child() const
priority queue for AdjacencyMapEntry
OptimizableGraph::VertexSet _visited
OptimizableGraph * graph()
void propagate(OptimizableGraph::Vertex *v, const EstimatePropagator::PropagateCost &cost, const EstimatePropagator::PropagateAction &action=PropagateAction(), double maxDistance=std::numeric_limits< double >::max(), double maxEdgeCost=std::numeric_limits< double >::max())
EstimatePropagator(OptimizableGraph *g)
const VertexContainer & vertices() const
const Vertex * vertex(size_t i) const
abstract Vertex, your types must derive from that one
int id() const
returns the id
const EdgeSet & edges() const
returns the set of hyper-edges that are leaving/entering in this vertex
std::set< Vertex * > VertexSet
const VertexIDMap & vertices() const
virtual double initialEstimatePossible(const OptimizableGraph::VertexSet &from, OptimizableGraph::Vertex *to)
A general case Vertex for optimization.
const EdgeContainer & activeEdges() const
the edges active in the current optimization
EdgeContainer::const_iterator findActiveEdge(const OptimizableGraph::Edge *e) const
#define G2O_DEBUG(...)
Definition logger.h:90
Definition jet.h:876
Applying the action for propagating.