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 namespace srba { 00013 00014 template <class KF2KF_POSE_TYPE,class LM_TYPE,class OBS_TYPE,class RBA_OPTIONS> 00015 double RbaEngine<KF2KF_POSE_TYPE,LM_TYPE,OBS_TYPE,RBA_OPTIONS>::eval_overall_squared_error() const 00016 { 00017 using namespace std; 00018 using namespace mrpt::utils; 00019 00020 m_profiler.enter("eval_overall_squared_error"); 00021 00022 double sqerr = 0; 00023 00024 // --------------------------------------------------------------------------- 00025 // Make a list of all the observing & base KFs needed by all observations: 00026 // --------------------------------------------------------------------------- 00027 vector<bool> base_ids(rba_state.keyframes.size(), false); 00028 map<TKeyFrameID, set<TKeyFrameID> > ob_pairs; // Minimum ID first index. 00029 00030 for (typename rba_problem_state_t::all_observations_deque_t::const_iterator itO=rba_state.all_observations.begin();itO!=rba_state.all_observations.end();++itO) 00031 { 00032 const TKeyFrameID obs_id = itO->obs.kf_id; 00033 const TKeyFrameID base_id = itO->feat_rel_pos->id_frame_base; 00034 00035 base_ids[base_id] = true; 00036 ob_pairs[ std::min(obs_id,base_id) ].insert( std::max(obs_id,base_id) ); 00037 } 00038 00039 // --------------------------------------------------------------------------- 00040 // Build all the needed shortest paths: 00041 // --------------------------------------------------------------------------- 00042 // all_rel_poses[SOURCE] |--> map[TARGET] = CPose3D of TARGET as seen from SOURCE 00043 TRelativePosesForEachTarget all_rel_poses; 00044 for (map<TKeyFrameID, set<TKeyFrameID> >::const_iterator it1=ob_pairs.begin();it1!=ob_pairs.end();++it1) 00045 { 00046 const TKeyFrameID root = it1->first; 00047 00048 // Build S.T. from this root: 00049 m_profiler.enter("eval_overall_squared_error.complete_ST"); 00050 00051 frameid2pose_map_t span_tree; 00052 this->create_complete_spanning_tree(root,span_tree); 00053 00054 m_profiler.leave("eval_overall_squared_error.complete_ST"); 00055 00056 // Look for the "set_intersection": 00057 typename frameid2pose_map_t::const_iterator it_have = span_tree.begin(); 00058 const typename frameid2pose_map_t::const_iterator it_have_end = span_tree.end(); 00059 00060 set<TKeyFrameID>::const_iterator it_want = it1->second.begin(); 00061 const set<TKeyFrameID>::const_iterator it_want_end = it1->second.end(); 00062 00063 while (it_have!=it_have_end && it_want!=it_want_end) 00064 { 00065 if (it_have->first<*it_want) 00066 ++it_have; 00067 else if (*it_want<it_have->first) 00068 ++it_want; 00069 else 00070 { 00071 // This means we need 1 or both of the poses: 00072 // root -> *it_want 00073 // *it_want -> root 00074 all_rel_poses[root][*it_want] = it_have->second; 00075 all_rel_poses[*it_want][root] = pose_flag_t(-it_have->second.pose, it_have->second.updated); 00076 00077 ++it_have; 00078 ++it_want; 00079 } 00080 } 00081 } 00082 00083 // --------------------------------------------------------------------------- 00084 // Evaluate errors: 00085 // --------------------------------------------------------------------------- 00086 for (typename rba_problem_state_t::all_observations_deque_t::const_iterator itO=rba_state.all_observations.begin();itO!=rba_state.all_observations.end();++itO) 00087 { 00088 // Actually measured pixel coords: observations[i]->obs.px 00089 00090 const TKeyFrameID obs_frame_id = itO->obs.kf_id; 00091 const TKeyFrameID base_id = itO->feat_rel_pos->id_frame_base; 00092 const TRelativeLandmarkPos *feat_rel_pos = itO->feat_rel_pos; 00093 ASSERTDEB_(feat_rel_pos!=NULL) 00094 00095 pose_t const * base_pose_wrt_observer=NULL; 00096 00097 // This case can occur with feats with unknown rel.pos: 00098 if (base_id==obs_frame_id) 00099 { 00100 base_pose_wrt_observer = &aux_null_pose; 00101 } 00102 else 00103 { 00104 // num[SOURCE] |--> map[TARGET] = CPose3D of TARGET as seen from SOURCE 00105 const typename TRelativePosesForEachTarget::const_iterator itPoseMap_for_base_id = all_rel_poses.find(obs_frame_id); 00106 ASSERT_( itPoseMap_for_base_id != all_rel_poses.end() ) 00107 00108 const typename frameid2pose_map_t::const_iterator itRelPose = itPoseMap_for_base_id->second.find(base_id); 00109 ASSERT_( itRelPose != itPoseMap_for_base_id->second.end() ) 00110 00111 base_pose_wrt_observer = &itRelPose->second.pose; 00112 } 00113 00114 // Sensor pose: base_pose_wrt_sensor = robot_pose (+) sensor_pose_on_the_robot 00115 typename options::internal::resulting_pose_t<typename RBA_OPTIONS::sensor_pose_on_robot_t,REL_POSE_DIMS>::pose_t base_pose_wrt_sensor(mrpt::poses::UNINITIALIZED_POSE); 00116 RBA_OPTIONS::sensor_pose_on_robot_t::robot2sensor( *base_pose_wrt_observer, base_pose_wrt_sensor, this->parameters.sensor_pose ); 00117 00118 // Stored observation: 00119 const array_obs_t & z_real = itO->obs.obs_arr; 00120 00121 // Predict observation and compare to real obs: 00122 residual_t delta; 00123 sensor_model_t::observe_error( 00124 delta, 00125 z_real, 00126 base_pose_wrt_sensor, 00127 feat_rel_pos->pos, // Position of LM wrt its base_id 00128 this->parameters.sensor 00129 ); 00130 00131 sqerr+= delta.squaredNorm(); 00132 } 00133 00134 m_profiler.leave("eval_overall_squared_error"); 00135 00136 return sqerr; 00137 } 00138 00139 } // end namespaces