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 #include <mrpt/opengl/CSetOfObjects.h> 00012 #include <mrpt/opengl/stock_objects.h> 00013 #include <mrpt/opengl/CSetOfLines.h> 00014 #include <mrpt/opengl/CPointCloud.h> 00015 #include <mrpt/opengl/CEllipsoid.h> 00016 #include <mrpt/opengl/CText3D.h> 00017 #include <mrpt/math/lightweight_geom_data.h> 00018 #include <srba/landmark_render_models.h> 00019 00020 namespace srba { 00021 00022 // Specializations for rendering each kind of landmark: 00023 template <class landmark_t> 00024 struct LandmarkRendererBase { }; 00025 00027 template <> struct LandmarkRendererBase<landmark_rendering_as_point> 00028 { 00029 template <class RBA> 00030 static void render( 00031 const RBA &rba, 00032 const srba::TKeyFrameID root_keyframe, 00033 const typename RBA::frameid2pose_map_t &spantree, 00034 const typename RBA::TOpenGLRepresentationOptions &options, 00035 mrpt::opengl::CSetOfObjects& scene) 00036 { 00037 using namespace mrpt::math; 00038 using mrpt::utils::DEG2RAD; 00039 using mrpt::poses::CPose3D; 00040 00041 // For each fixed known LM, add a point to a point cloud 00042 // and a text label with the landmark ID: 00043 mrpt::opengl::CPointCloudPtr gl_lms = mrpt::opengl::CPointCloud::Create(); 00044 gl_lms->setPointSize(5); 00045 gl_lms->setColor(0,0,1); 00046 00047 scene.insert(gl_lms); 00048 00049 vector<typename RBA::TRelativeLandmarkPosMap::const_iterator> lms_to_draw; 00050 vector<const typename RBA::hessian_traits_t::TSparseBlocksHessian_f::matrix_t *> lms_to_draw_inf_covs; 00051 00052 for (typename RBA::TRelativeLandmarkPosMap::const_iterator itLM = rba.get_rba_state().known_lms.begin();itLM != rba.get_rba_state().known_lms.end();++itLM) 00053 { 00054 lms_to_draw.push_back(itLM); 00055 lms_to_draw_inf_covs.push_back( NULL ); 00056 } 00057 00058 const size_t nKnown = lms_to_draw.size(); 00059 00060 if (options.draw_unknown_feats) 00061 { 00062 for (typename RBA::TRelativeLandmarkPosMap::const_iterator itLM = rba.get_rba_state().unknown_lms.begin();itLM != rba.get_rba_state().unknown_lms.end();++itLM) 00063 { 00064 lms_to_draw.push_back(itLM); 00065 00066 typename RBA::hessian_traits_t::landmarks2infmatrix_t::const_iterator it_inf = rba.get_rba_state().unknown_lms_inf_matrices.find(itLM->first); 00067 00068 if (it_inf != rba.get_rba_state().unknown_lms_inf_matrices.end()) 00069 lms_to_draw_inf_covs.push_back( &it_inf->second ); 00070 else lms_to_draw_inf_covs.push_back(NULL); 00071 } 00072 } 00073 00074 const mrpt::utils::TColorf col_known_lms(1.f,1.f,0.f); 00075 const mrpt::utils::TColorf col_unknown_lms(1.f,0.f,0.f); 00076 00077 for (size_t i=0;i<lms_to_draw.size();i++) 00078 { 00079 const typename RBA::TRelativeLandmarkPosMap::const_iterator &itLM = lms_to_draw[i]; 00080 const bool is_known = (i<nKnown); 00081 00082 // Don't draw those unknown LMs which hasn't been estimated not even once: 00083 //if (!is_known && lms_to_draw_inf_covs[i]==NULL) continue; 00084 00085 mrpt::poses::CPose3D base_pose; 00086 if (itLM->second.id_frame_base!=root_keyframe) 00087 { 00088 typename RBA::frameid2pose_map_t::const_iterator itBaseNode = spantree.find(itLM->second.id_frame_base); 00089 if(itBaseNode==spantree.end()) 00090 continue; 00091 base_pose = itBaseNode->second.pose; // Inverse! 00092 } 00093 else 00094 { 00095 // It's the origin. 00096 } 00097 00098 // If landmark_t defines this kind of renderer, we 00099 mrpt::math::TPoint3D p_wrt_base; 00100 RBA::landmark_t::relativeEuclideanLocation(itLM->second.pos, p_wrt_base); 00101 00102 mrpt::math::TPoint3D p_global; 00103 base_pose.composePoint(p_wrt_base,p_global); 00104 00105 gl_lms->insertPoint(p_global.x,p_global.y,p_global.z); 00106 00107 if( options.show_unknown_feats_ids ) 00108 { 00109 // Add text label: 00110 mrpt::opengl::CText3DPtr gl_txt = mrpt::opengl::CText3D::Create( 00111 mrpt::format("%u",static_cast<unsigned int>( itLM->first)), 00112 "mono", 0.15, 00113 mrpt::opengl::NICE ); 00114 gl_txt->setPose(CPose3D(p_global.x,p_global.y,p_global.z,DEG2RAD(-90),DEG2RAD(0),DEG2RAD(90))); 00115 gl_txt->setColor( is_known ? col_known_lms : col_unknown_lms ); 00116 00117 scene.insert(gl_txt); 00118 } 00119 00120 // Uncertainty ellipse? 00121 if (options.draw_unknown_feats_ellipses && lms_to_draw_inf_covs[i] ) 00122 { 00123 double min_inf_diag=std::numeric_limits<double>::max(); 00124 for (size_t k=0;k<RBA::LM_DIMS;k++) 00125 mrpt::utils::keep_min(min_inf_diag, (*lms_to_draw_inf_covs[i])(k,k)); 00126 if (min_inf_diag<1e-5) continue; // Too large covariance! 00127 00128 mrpt::math::CMatrixFixedNumeric<double,RBA::LM_DIMS,RBA::LM_DIMS> cov(mrpt::math::UNINITIALIZED_MATRIX); 00129 lms_to_draw_inf_covs[i]->inv(cov); 00130 00131 mrpt::opengl::CEllipsoidPtr gl_ellip = mrpt::opengl::CEllipsoid::Create(); 00132 gl_ellip->setQuantiles( options.draw_unknown_feats_ellipses_quantiles ); 00133 gl_ellip->enableDrawSolid3D(false); 00134 00135 gl_ellip->setCovMatrix(cov); 00136 CPose3D ellip_pose = base_pose; 00137 ellip_pose.x(p_global.x); 00138 ellip_pose.y(p_global.y); 00139 ellip_pose.z(p_global.z); 00140 00141 gl_ellip->setPose(ellip_pose); 00142 scene.insert(gl_ellip); 00143 } 00144 } 00145 } 00146 }; 00147 00149 template <> struct LandmarkRendererBase<landmark_rendering_as_pose_constraints> 00150 { 00151 template <class RBA> 00152 static void render( 00153 const RBA &rba, 00154 const srba::TKeyFrameID root_keyframe, 00155 const typename RBA::frameid2pose_map_t &spantree, 00156 const typename RBA::TOpenGLRepresentationOptions &options, 00157 mrpt::opengl::CSetOfObjects& scene) 00158 { 00159 MRPT_UNUSED_PARAM(options); 00160 MRPT_UNUSED_PARAM(root_keyframe); 00161 using namespace mrpt::math; 00162 00163 mrpt::opengl::CSetOfLinesPtr gl_edges = mrpt::opengl::CSetOfLines::Create(); 00164 gl_edges->setLineWidth(1); 00165 gl_edges->setColor(0,0,1); 00166 00167 scene.insert(gl_edges); 00168 00169 // For each KF: check all its "observations" 00170 for (typename RBA::frameid2pose_map_t::const_iterator it=spantree.begin();it!=spantree.end();++it) 00171 { 00172 const TKeyFrameID kf_id = it->first; 00173 const typename RBA::pose_flag_t & pf = it->second; 00174 00175 const typename RBA::keyframe_info &kfi = rba.get_rba_state().keyframes[kf_id]; 00176 00177 for (size_t i=0;i<kfi.adjacent_k2f_edges.size();i++) 00178 { 00179 const typename RBA::k2f_edge_t * k2f = kfi.adjacent_k2f_edges[i]; 00180 const TKeyFrameID other_kf_id = k2f->feat_rel_pos->id_frame_base; 00181 if (kf_id==other_kf_id) 00182 continue; // It's not an constraint with ANOTHER keyframe 00183 00184 // Is the other KF in the spanning tree? 00185 typename RBA::frameid2pose_map_t::const_iterator other_it=spantree.find(other_kf_id); 00186 if (other_it==spantree.end()) continue; 00187 00188 const typename RBA::pose_flag_t & other_pf = other_it->second; 00189 00190 // Add edge between the two KFs to represent the pose constraint: 00191 mrpt::poses::CPose3D p1 = mrpt::poses::CPose3D(pf.pose); // Convert to 3D 00192 mrpt::poses::CPose3D p2 = mrpt::poses::CPose3D(other_pf.pose); 00193 00194 gl_edges->appendLine( p1.x(),p1.y(),p1.z()+0.10, p2.x(),p2.y(),p2.z()+0.10 ); 00195 } 00196 00197 } // end for each KF 00198 } 00199 }; 00200 00202 template <> struct LandmarkRendererBase<landmark_rendering_none> 00203 { 00204 template <class RBA> 00205 static void render( 00206 const RBA &rba, 00207 const srba::TKeyFrameID root_keyframe, 00208 const typename RBA::frameid2pose_map_t &spantree, 00209 const typename RBA::TOpenGLRepresentationOptions &options, 00210 mrpt::opengl::CSetOfObjects& scene) 00211 { 00212 MRPT_UNUSED_PARAM(rba); 00213 MRPT_UNUSED_PARAM(root_keyframe); 00214 MRPT_UNUSED_PARAM(spantree); 00215 MRPT_UNUSED_PARAM(options); 00216 MRPT_UNUSED_PARAM(scene); 00217 // Nothing to render 00218 } 00219 }; 00220 00221 } // End of namespaces