SRBA: Sparser Relative Bundle Adjustment
srba/impl/export_opengl.h
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends