00001 #ifndef ALGORITHMS_HPP
00002 #define ALGORITHMS_HPP
00003
00004 #include <boost/graph/depth_first_search.hpp>
00005 #include <boost/graph/undirected_dfs.hpp>
00006 #include <boost/graph/reverse_graph.hpp>
00007 #include <boost/graph/copy.hpp>
00008 #include <boost/graph/adjacency_list.hpp>
00009
00010 #include <graphmap/transformation.hpp>
00011 #include <graphmap/graphmapException.hpp>
00012
00013 #include <rtslam/quatTools.hpp>
00014
00015 #include <iostream>
00016 #include <algorithm>
00017
00018 namespace jafar{
00019 namespace graphmap {
00020
00021 template <typename OutputIterator, typename OutputIteratorValueType>
00022 class path_to_back_edge_recorder : public boost::default_dfs_visitor
00023 {
00024 public:
00025 path_to_back_edge_recorder(OutputIterator out) :
00026 m_out(out), m_path()
00027 { }
00028
00029 template <class Edge, class Graph>
00030 void tree_edge(Edge e, Graph&) { m_path.push_back(e); }
00031 template <class Vertex, class Graph>
00032 void finish_vertex(Vertex, Graph&){ if(!m_path.empty()) m_path.pop_back(); }
00033 template <class Edge, class Graph>
00034 void back_edge(Edge e, Graph&)
00035 {
00036 if(e == m_path.back()) return;
00037
00038 m_path.push_back(e);
00039 *m_out++ = m_path;
00040 m_path.pop_back();
00041 }
00042
00043 private:
00044 OutputIterator m_out;
00045 OutputIteratorValueType m_path;
00046 };
00047
00048
00049 template <typename BackInsertionSequence>
00050 path_to_back_edge_recorder< std::back_insert_iterator<BackInsertionSequence>, typename BackInsertionSequence::value_type >
00051 make_path_to_back_edge_recorder(BackInsertionSequence& backinsertersequence) {
00052 return path_to_back_edge_recorder<std::back_insert_iterator<BackInsertionSequence>, typename BackInsertionSequence::value_type >(std::back_inserter(backinsertersequence));
00053 }
00054
00055 template <typename OutputIterator, typename OutputIteratorValueType, typename Vertex>
00056 class path_to_target_recorder : public boost::default_dfs_visitor
00057 {
00058 public:
00059 path_to_target_recorder(OutputIterator out, Vertex target) :
00060 m_out(out), m_path(), m_target(target)
00061 { }
00062
00063 template <class Edge, class Graph>
00064 void tree_edge(Edge e, Graph&) { m_path.push_back(e); }
00065 template <class Graph>
00066 void finish_vertex(Vertex, Graph&){ if(!m_path.empty()) m_path.pop_back(); }
00067 template <class Graph>
00068 void discover_vertex(Vertex u, Graph& g) {
00069 if(u == m_target){
00070 *m_out++ = m_path;
00071 }
00072 }
00073 private:
00074 OutputIterator m_out;
00075 OutputIteratorValueType m_path;
00076 Vertex m_source, m_target;
00077 };
00078
00079
00080 template <typename BackInsertionSequence, typename Vertex>
00081 path_to_target_recorder< std::back_insert_iterator<BackInsertionSequence>, typename BackInsertionSequence::value_type, Vertex >
00082 make_path_to_target_recorder(BackInsertionSequence& backinsertersequence, Vertex target) {
00083 return path_to_target_recorder<std::back_insert_iterator<BackInsertionSequence>, typename BackInsertionSequence::value_type, Vertex >(std::back_inserter(backinsertersequence),target);
00084 }
00085
00086
00087 template<typename Loop,typename Graph>
00088 void tag_loop(Loop &loop, Graph &g)
00089 {
00090 typename Loop::iterator it = loop.begin();
00091 std::vector<unsigned int> common_ids, intersection;
00092
00093 common_ids = g[(*it)].loop_ids; it++;
00094
00095 for( ; it != loop.end(); ++it)
00096 {
00097 std::set_intersection (g[(*it)].loop_ids.begin(),g[(*it)].loop_ids.end(),
00098 common_ids.begin(),common_ids.end(),
00099 std::back_inserter(intersection));
00100 if(intersection.empty())
00101 {
00102 unsigned int new_id = g[boost::graph_bundle].loopIdFactory.getId();
00103 JFR_DEBUG("New loop! ID: " << new_id << std::endl);
00104 for(typename Loop::iterator it2 = loop.begin(); it2 != loop.end(); ++it2)
00105 g[(*it2)].loop_ids.push_back(new_id);
00106 return;
00107 }else
00108 {
00109 common_ids = intersection;
00110 intersection.clear();
00111 }
00112 }
00113
00114 JFR_DEBUG_COND(common_ids.size() == 1,"Old loop... ID: " << common_ids.front() << std::endl);
00115 JFR_PRED_ERROR(common_ids.size() != 1, GraphmapException, GraphmapException::LOOP_WITH_MULTIPLE_IDS, "loop has " << common_ids.size() << " ids");
00116 }
00117
00118 template <typename Path, typename Graph>
00119 void compute_loop_from_path(Path& path, Graph& g)
00120 {
00121 using namespace boost;
00122
00123 typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
00124 typedef typename graph_traits<Graph>::edge_descriptor Edge;
00125
00126 Edge back_edge = path.back();
00127 Vertex loop_head = target(back_edge,g);
00128
00129 if(source(path.front(),g) != loop_head){
00130 typename Path::iterator it;
00131 for(it = path.begin(); it != path.end(); ++it)
00132 if(source(*it,g) == loop_head){
00133 path.erase(path.begin(),it);
00134 return;
00135 }
00136 }
00137 }
00138
00142 template <typename Graph, typename Loops>
00143 void find_all_loops(
00144 typename boost::graph_traits<Graph>::vertex_descriptor entry,
00145 Graph& g,
00146 Loops& loops)
00147 {
00148 using namespace boost;
00149
00150 function_requires< BidirectionalGraphConcept<Graph> >();
00151 typedef typename graph_traits<Graph>::edge_descriptor Edge;
00152 typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
00153
00154
00155
00157
00158 depth_first_search(g,visitor(make_path_to_back_edge_recorder(loops)));
00160
00161
00162
00163 for(typename Loops::iterator it = loops.begin();
00164 it != loops.end(); ++it)
00165 {
00166 compute_loop_from_path(*it,g);
00167 tag_loop(*it,g);
00168 }
00169
00171
00172 }
00173
00181 template <typename Graph, typename Loops>
00182 void find_loops_from_edge(
00183 typename boost::graph_traits<Graph>::edge_descriptor entry_edge,
00184 Graph& g,
00185 Loops& loops)
00186 {
00187 using namespace boost;
00188
00189 function_requires< BidirectionalGraphConcept<Graph> >();
00190 typedef typename graph_traits<Graph>::edge_descriptor Edge;
00191 typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
00192 typedef typename graph_traits<Graph>::edge_iterator EdgeIterator;
00193 typedef adjacency_list<listS, vecS, undirectedS> UndirectedGraph;
00194 typedef typename graph_traits<UndirectedGraph>::edge_descriptor UndirectedEdge;
00195 typedef typename graph_traits<UndirectedGraph>::vertex_descriptor UndirectedVertex;
00196 typedef typename std::list<UndirectedEdge> UndirectedEdgeList;
00197 typedef typename std::vector<UndirectedEdgeList> UndirectedLoops;
00198
00199 UndirectedLoops und_loops;
00200 UndirectedGraph undirected_g;
00201 std::map<Edge,UndirectedEdge> direct_to_undirect_edge_map;
00202 std::map<UndirectedEdge,Edge> undirect_to_direct_edge_map;
00203
00204
00205 EdgeIterator ei, ei_end;
00206 UndirectedEdge und_e;
00207 for (tie(ei, ei_end) = edges(g); ei != ei_end; ++ei){
00208 tie(und_e,boost::tuples::ignore) = add_edge(source(*ei, g),target(*ei, g),undirected_g);
00209 direct_to_undirect_edge_map[*ei] = und_e;
00210 undirect_to_direct_edge_map[und_e] = *ei;
00211 }
00212
00213
00214 UndirectedVertex source_v = source(direct_to_undirect_edge_map[entry_edge],undirected_g);
00215 UndirectedVertex target_v = target(direct_to_undirect_edge_map[entry_edge],undirected_g);
00216
00217
00218 remove_edge(direct_to_undirect_edge_map[entry_edge],undirected_g);
00219
00220
00221 std::vector < default_color_type > color_map(num_vertices(undirected_g));
00222 depth_first_visit(undirected_g, source_v,
00223 make_path_to_target_recorder(und_loops,target_v),
00224 make_iterator_property_map(color_map.begin(),
00225 get(vertex_index, undirected_g), color_map[0]));
00226
00227
00228 for(typename UndirectedLoops::iterator it = und_loops.begin();
00229 it != und_loops.end(); ++it)
00230 {
00231 typename Loops::value_type directed_loop;
00232 for(typename UndirectedEdgeList::iterator it2 = it->begin();
00233 it2 != it->end(); ++it2)
00234 {
00235 directed_loop.push_back(undirect_to_direct_edge_map[*it2]);
00236 }
00237 directed_loop.push_back(entry_edge);
00238 loops.push_back(directed_loop);
00239 }
00240
00241
00242 for(typename Loops::iterator it = loops.begin(); it != loops.end(); ++it)
00243 {
00244 tag_loop(*it,g);
00245 }
00246
00247 }
00248
00249 template <typename TransformationPairVector>
00250 void optimize(TransformationPairVector &t_pair_vector, double threshold)
00251 {
00252 unsigned int loop_size = t_pair_vector.size();
00253
00254
00255 int t_size = t_pair_vector[0].first.size();
00256 int opt_vec_size = t_size * loop_size;
00257
00258 jblas::vec x_u(opt_vec_size);
00259 jblas::sym_mat P_u(opt_vec_size,opt_vec_size);
00260 jblas::vec x_prev(opt_vec_size);
00261 jblas::vec x_pos(opt_vec_size);
00262
00263
00264 for(unsigned int i=0; i < loop_size; ++i)
00265 {
00266 ublas::subrange(x_u,i*t_size,(i+1)*t_size) = t_pair_vector[i].first.x();
00267 ublas::subrange(P_u,i*t_size,(i+1)*t_size,i*t_size,(i+1)*t_size) = t_pair_vector[i].first.P();
00268 ublas::subrange(x_prev,i*t_size,(i+1)*t_size) = t_pair_vector[i].second.x();
00269 }
00270
00271 bool converged = false;
00272
00273
00274 jblas::mat H_i(t_size,opt_vec_size);
00275
00276
00277 jblas::vec a(opt_vec_size);
00278 jblas::vec b(opt_vec_size);
00279 jblas::vec c(t_size);
00280 jblas::mat d(t_size,t_size);
00281 jblas::mat d_inv(t_size,t_size);
00282 jblas::mat e(opt_vec_size,t_size);
00283 jblas::mat f(opt_vec_size,t_size);
00284 jblas::vec g(opt_vec_size);
00285
00286 jblas::vec h_i = jblas::zero_vec(t_size);
00287 jblas::vec h_k(t_size);
00288 jblas::vec x_k(t_size);
00289
00290 jblas::mat J_1(t_size,t_size), J_2(t_size,t_size);
00291
00292
00293 jblas::mat dummy_J(t_size,t_size);
00294 jblas::vec dummy_C(t_size);
00295
00296
00297 jblas::vec h_k_inv(t_size), h_k_inv_h_i(t_size), x_k_inv(t_size), h_k_x_k_inv(t_size);
00298
00299 while(!converged){
00300
00301 for(unsigned int i=0; i < loop_size; ++i){
00302 x_k = ublas::subrange(x_prev,i*t_size,(i+1)*t_size);
00303 h_i = rtslam::quaternion::composeFrames(h_i, x_k);
00304 }
00305
00306 h_k = jblas::zero_vec(t_size);
00307 for(unsigned int i=0; i < t_pair_vector.size(); ++i)
00308 {
00309 x_k = ublas::subrange(x_prev,i*t_size,(i+1)*t_size);
00310 h_k = rtslam::quaternion::composeFrames(h_k,x_k);
00311
00312 h_k_inv = rtslam::quaternion::invertFrame(h_k);
00313 h_k_inv_h_i = rtslam::quaternion::composeFrames(h_k_inv,h_i);
00314 rtslam::quaternion::composeFrames(h_k, h_k_inv_h_i, dummy_C, J_1, dummy_J);
00315
00316 x_k_inv = rtslam::quaternion::invertFrame(x_k);
00317 h_k_x_k_inv = rtslam::quaternion::composeFrames(h_k,x_k_inv);
00318 rtslam::quaternion::composeFrames(h_k_x_k_inv, x_k,dummy_C, dummy_J, J_2);
00319
00320 ublas::subrange(H_i,0,t_size,i*t_size,(i+1)*t_size) = ublas::prod(J_1,J_2);
00321 }
00322
00323
00324
00325
00326
00327
00328
00329 a = x_prev - x_u;
00330 b = ublas::prod(H_i,a);
00331 c = b - h_i;
00332 d = jmath::ublasExtra::prod_JPJt(P_u,H_i);
00333 jmath::ublasExtra::lu_inv(d, d_inv);
00334 e = ublas::prod(P_u,ublas::trans(H_i));
00335 f = ublas::prod(e,d_inv);
00336 g = ublas::prod(f,c);
00337 x_pos = x_u + g;
00338
00340 if( ublas::norm_2(x_pos - x_prev) < threshold)
00341 converged = true;
00342
00343 x_prev = x_pos;
00344 }
00345
00346
00347 for(unsigned int i=0; i < t_pair_vector.size(); ++i)
00348 {
00349 t_pair_vector[i].second.x() = ublas::subrange(x_pos,i*t_size,(i+1)*t_size);
00350
00351 }
00352 }
00353
00354 template<class VecG, class VecL, class VecC, class CovMatG, class CovMatL, class CovMatC>
00355 void composeFramesWithCov(const VecG & G, const VecL & L, VecC & C,
00356 const CovMatG & PG, const CovMatL & PL, CovMatC & PC){
00357
00358 jblas::mat C_g(7,7), C_l(7,7);
00359 rtslam::quaternion::composeFrames(G, L, C, C_g, C_l);
00360 PC = jmath::ublasExtra::prod_JPJt(PG,C_g) +
00361 jmath::ublasExtra::prod_JPJt(PL,C_l);
00362 }
00363
00364 }
00365 }
00366
00367 #endif // ALGORITHMS_HPP