SRBA: Sparser Relative Bundle Adjustment
|
00001 /* +---------------------------------------------------------------------------+ 00002 | Mobile Robot Programming Toolkit (MRPT) | 00003 | http://www.mrpt.org/ | 00004 | | 00005 | Copyright (c) 2005-2015, Individual contributors, see AUTHORS file | 00006 | See: http://www.mrpt.org/Authors - All rights reserved. | 00007 | Released under BSD License. See details in http://www.mrpt.org/License | 00008 +---------------------------------------------------------------------------+ */ 00009 00010 #pragma once 00011 00012 #include <mrpt/opengl/CSetOfObjects.h> 00013 #include <mrpt/opengl/stock_objects.h> 00014 #include <mrpt/opengl/CDisk.h> 00015 #include <mrpt/opengl/CSetOfLines.h> 00016 00017 #include "export_opengl_landmark_renderers.h" // Declare LandmarkRendererBase<> specializations 00018 00019 namespace srba { 00020 // 00021 // RbaEngine<>::build_opengl_representation 00022 // 00023 template <class KF2KF_POSE_TYPE,class LM_TYPE,class OBS_TYPE,class RBA_OPTIONS> 00024 void RbaEngine<KF2KF_POSE_TYPE,LM_TYPE,OBS_TYPE,RBA_OPTIONS>::build_opengl_representation( 00025 const srba::TKeyFrameID root_keyframe, 00026 const TOpenGLRepresentationOptions &options, 00027 mrpt::opengl::CSetOfObjectsPtr out_scene, 00028 mrpt::opengl::CSetOfObjectsPtr out_root_tree 00029 ) const 00030 { 00031 using namespace std; 00032 using namespace mrpt::utils; 00033 using mrpt::poses::CPose3D; 00034 00035 // Generate 3D scene: 00036 // ------------------------------ 00037 if (out_scene) 00038 { 00039 out_scene->clear(); 00040 00041 if (!rba_state.keyframes.empty()) 00042 { 00043 // Use a spanning tree to estimate the global pose of every node 00044 // starting (root) at the given keyframe: 00045 00046 frameid2pose_map_t spantree; 00047 create_complete_spanning_tree(root_keyframe,spantree, options.span_tree_max_depth ); 00048 00049 // For each key-frame, add a 3D corner: 00050 for (typename frameid2pose_map_t::const_iterator itP = spantree.begin();itP!=spantree.end();++itP) 00051 { 00052 if (root_keyframe==itP->first) continue; 00053 00054 const CPose3D p = itP->second.pose; 00055 00056 const bool is_elevated_hiearchical_kf = (options.draw_kf_hierarchical && rba_state.keyframes[itP->first].adjacent_k2k_edges.size()>=2); 00057 00058 mrpt::opengl::CSetOfObjectsPtr o = mrpt::opengl::stock_objects::CornerXYZSimple(is_elevated_hiearchical_kf ? 3.0 : 0.75, is_elevated_hiearchical_kf ? 4.0 : 2.0); 00059 if (options.draw_kf_hierarchical) { 00060 // Hierarchical map: 00061 CPose3D p_mod = p; 00062 if (is_elevated_hiearchical_kf) 00063 p_mod.z_incr( options.draw_kf_hierarchical_height ); 00064 o->setPose(p_mod); 00065 } else { 00066 // Flat map: 00067 o->setPose(p); 00068 } 00069 o->setName( mrpt::format("%d",int(itP->first)).c_str() ); 00070 o->enableShowName(); 00071 out_scene->insert(o); 00072 } 00073 // And a bigger one for the root: 00074 { 00075 mrpt::opengl::CSetOfObjectsPtr o = mrpt::opengl::stock_objects::CornerXYZSimple(1.0,4.0); 00076 //o->setPose(...); // At the origin 00077 out_scene->insert(o); 00078 } 00079 00080 // Draw all edges between frames: 00081 mrpt::opengl::CSetOfLinesPtr gl_edges = mrpt::opengl::CSetOfLines::Create(); 00082 gl_edges->setColor(1,0,1); // Magenta, in order to not confuse them with the standard lines of a grid plane 00083 for (typename rba_problem_state_t::k2k_edges_deque_t::const_iterator itEdge = rba_state.k2k_edges.begin();itEdge!=rba_state.k2k_edges.end();++itEdge) 00084 { 00085 CPose3D p1; 00086 if (itEdge->from!=root_keyframe) 00087 { 00088 typename frameid2pose_map_t::const_iterator itN1 = spantree.find(itEdge->from); 00089 if(itN1==spantree.end()) 00090 continue; 00091 p1 = itN1->second.pose; 00092 if (options.draw_kf_hierarchical && rba_state.keyframes[itEdge->from].adjacent_k2k_edges.size()>=2) 00093 p1.z_incr( options.draw_kf_hierarchical_height ); 00094 } 00095 CPose3D p2; 00096 if (itEdge->to!=root_keyframe) 00097 { 00098 typename frameid2pose_map_t::const_iterator itN2 = spantree.find(itEdge->to); 00099 if(itN2==spantree.end()) 00100 continue; 00101 p2 = itN2->second.pose; 00102 if (options.draw_kf_hierarchical && rba_state.keyframes[itEdge->to].adjacent_k2k_edges.size()>=2) 00103 p2.z_incr( options.draw_kf_hierarchical_height ); 00104 } 00105 gl_edges->appendLine(p1.x(),p1.y(),p1.z(), p2.x(),p2.y(),p2.z()); 00106 } 00107 out_scene->insert(gl_edges); 00108 00109 // Render landmarks: 00110 LandmarkRendererBase<typename landmark_t::render_mode_t>::render(*this,root_keyframe,spantree, options,*out_scene); 00111 00112 } // end if graph is not empty 00113 00114 } // end of "out_scene" 00115 00116 00117 // Generate 2D tree: 00118 // ------------------------------ 00119 if (out_root_tree) 00120 { 00121 out_root_tree->clear(); 00122 00123 const float NODE_RADIUS = 1; 00124 const float ROW_HEIGHT = 4*NODE_RADIUS; 00125 const float COL_WIDTH = 3*NODE_RADIUS; 00126 00127 typename rba_problem_state_t::TSpanningTree::next_edge_maps_t::const_iterator it_st_root = rba_state.spanning_tree.sym.next_edge.find(root_keyframe); 00128 ASSERT_(it_st_root != rba_state.spanning_tree.sym.next_edge.end()) 00129 00130 const std::map<TKeyFrameID,TSpanTreeEntry> & st_root = it_st_root->second; 00131 00132 std::map<TKeyFrameID,topo_dist_t> children_depths; 00133 std::map<topo_dist_t,std::vector<TKeyFrameID> > children_by_depth; 00134 00135 // roots are not in spanning trees ("spanning_tree.sym.next_edge") 00136 children_depths[root_keyframe]=0; 00137 children_by_depth[0].push_back(root_keyframe); 00138 00139 // Go thru the tree to realize of its size: 00140 //size_t max_nodes_per_level = 1; 00141 size_t max_depth = 0; 00142 for (std::map<TKeyFrameID,TSpanTreeEntry>::const_iterator it=st_root.begin();it!=st_root.end();++it) 00143 { 00144 const topo_dist_t depth = it->second.distance; 00145 children_depths[it->first] = depth; 00146 mrpt::utils::keep_max(max_depth, depth); 00147 00148 std::vector<TKeyFrameID> & v = children_by_depth[depth]; 00149 v.push_back(it->first); 00150 //mrpt::utils::keep_max(max_nodes_per_level, v.size()); 00151 } 00152 00153 // Generate (x,y) coords for each node: 00154 std::map<TKeyFrameID, mrpt::math::TPoint3Df> node_coords; 00155 00156 for (size_t d=0;d<=max_depth;d++) 00157 { 00158 const float y = -(d*ROW_HEIGHT); 00159 00160 std::vector<TKeyFrameID> & v = children_by_depth[d]; 00161 const float row_width = v.size()*COL_WIDTH; 00162 00163 for (size_t i=0;i<v.size();i++) 00164 { 00165 const float x = - 0.5f*row_width + COL_WIDTH*i; 00166 node_coords[v[i]] = mrpt::math::TPoint3Df(x,y,0); 00167 } 00168 } 00169 00170 // Draw edges in tree: 00171 mrpt::opengl::CSetOfLinesPtr gl_edges = mrpt::opengl::CSetOfLines::Create(); 00172 gl_edges->setLineWidth(1.5); 00173 gl_edges->setColor_u8(mrpt::utils::TColor(0xff,0xff,0x00)); 00174 out_root_tree->insert(gl_edges); 00175 00176 typename rba_problem_state_t::TSpanningTree::all_edges_maps_t::const_iterator it_edges_from_root = rba_state.spanning_tree.sym.all_edges.find(root_keyframe); 00177 ASSERT_(it_edges_from_root != rba_state.spanning_tree.sym.all_edges.end()) 00178 00179 const std::map<TKeyFrameID, typename rba_problem_state_t::k2k_edge_vector_t> edges_from_root = it_edges_from_root->second; 00180 00181 for (typename std::map<TKeyFrameID, typename rba_problem_state_t::k2k_edge_vector_t>::const_iterator it=edges_from_root.begin();it!=edges_from_root.end();++it) 00182 { 00183 const typename rba_problem_state_t::k2k_edge_vector_t & edges_to_j = it->second; 00184 for (size_t k=0;k<edges_to_j.size();k++) 00185 { 00186 const TKeyFrameID id1 = edges_to_j[k]->from; 00187 const TKeyFrameID id2 = edges_to_j[k]->to; 00188 00189 gl_edges->appendLine(node_coords[id1], node_coords[id2]); 00190 } 00191 } 00192 00193 // And on the top, draw the nodes: 00194 for (std::map<TKeyFrameID, mrpt::math::TPoint3Df>::const_iterator it=node_coords.begin();it!=node_coords.end();++it) 00195 gl_aux_draw_node(*out_root_tree, mrpt::format("%u", static_cast<unsigned int>(it->first) ), it->second.x, it->second.y); 00196 00197 } // end render "2D tree" 00198 00199 } 00200 00201 00202 template <class KF2KF_POSE_TYPE,class LM_TYPE,class OBS_TYPE,class RBA_OPTIONS> 00203 void RbaEngine<KF2KF_POSE_TYPE,LM_TYPE,OBS_TYPE,RBA_OPTIONS>::gl_aux_draw_node(mrpt::opengl::CSetOfObjects &soo, const std::string &label, const float x, const float y) const 00204 { 00205 { 00206 mrpt::opengl::CDiskPtr obj = mrpt::opengl::CDisk::Create(); 00207 obj->setDiskRadius(1,0); 00208 obj->setColor_u8(mrpt::utils::TColor(0x00,0x00,0x00, 0xa0)); 00209 obj->setLocation(x,y,0); 00210 soo.insert(obj); 00211 } 00212 00213 { 00214 mrpt::opengl::CText3DPtr obj = mrpt::opengl::CText3D::Create(label); 00215 obj->setFont("sans"); 00216 obj->setColor_u8(mrpt::utils::TColor(0xff,0xff,0xff)); 00217 obj->setScale(0.9); 00218 obj->setLocation(x-0.5,y-0.5,0); 00219 soo.insert(obj); 00220 } 00221 00222 } 00223 00224 } // End of namespaces