12 namespace mrpt {
namespace srba {
15 template <
class KF2KF_POSE_TYPE,
class LM_TYPE,
class OBS_TYPE,
class RBA_OPTIONS>
19 std::vector<TNewEdgeInfo> &new_k2k_edge_ids )
22 switch (parameters.srba.edge_creation_policy)
30 const pose_t init_inv_pose;
35 nei.
id = this->create_kf2kf_edge(new_kf_id,
TPairKeyFrameID( new_kf_id-1, new_kf_id), obs, init_inv_pose);
37 new_k2k_edge_ids.push_back(nei);
48 const size_t MINIMUM_OBS_TO_LOOP_CLOSURE = parameters.srba.min_obs_to_loop_closure;
49 const size_t SUBMAP_SIZE = parameters.srba.submap_size;
50 const TKeyFrameID cur_localmap_center = SUBMAP_SIZE*((new_kf_id-1)/SUBMAP_SIZE);
53 if (0!=(new_kf_id)%SUBMAP_SIZE)
58 nei.
id = this->create_kf2kf_edge(new_kf_id,
TPairKeyFrameID( cur_localmap_center, new_kf_id), obs );
60 if (0==((new_kf_id-1)%SUBMAP_SIZE))
64 this->rba_state.k2k_edges[nei.
id]
65 #ifdef SRBA_WORKAROUND_MSVC9_DEQUE_BUG
76 #ifdef SRBA_WORKAROUND_MSVC9_DEQUE_BUG
77 this->rba_state.k2k_edges[nei.
id]->inv_pose = this->rba_state.k2k_edges[nei.
id-1]->inv_pose;
79 this->rba_state.k2k_edges[nei.
id].inv_pose = this->rba_state.k2k_edges[nei.
id-1].inv_pose;
83 new_k2k_edge_ids.push_back(nei);
85 VERBOSE_LEVEL(2) <<
"[edge_creation_policy] Created edge #"<< nei.
id <<
": "<< cur_localmap_center<<
"->"<< new_kf_id << endl;
95 make_ordered_list_base_kfs(obs, obs_for_each_base_sorted);
98 map<TKeyFrameID,size_t> obs_for_each_area;
101 const size_t num_obs_this_base = it->first;
104 const TKeyFrameID this_localmap_center = SUBMAP_SIZE*(base_id/SUBMAP_SIZE);
106 obs_for_each_area[this_localmap_center] += num_obs_this_base;
112 obs_for_each_area_sorted.insert( make_pair(it->second,it->first) );
117 const size_t num_obs_this_base = it->first;
120 VERBOSE_LEVEL(2) <<
"[edge_creation_policy] Consider: area central kf#"<< central_kf_id <<
" with #obs:"<< num_obs_this_base << endl;
130 topo_dist_t found_distance = numeric_limits<topo_dist_t>::max();
132 if (it_from != rba_state.spanning_tree.sym.next_edge.end())
134 const map<TKeyFrameID,TSpanTreeEntry> &from_Ds = it_from->second;
137 if (it_to_dist != from_Ds.end())
138 found_distance = it_to_dist->second.distance;
146 if ( found_distance>=parameters.srba.max_optimize_depth)
148 if (num_obs_this_base>=MINIMUM_OBS_TO_LOOP_CLOSURE)
153 nei.
id = this->create_kf2kf_edge(new_kf_id,
TPairKeyFrameID( central_kf_id, new_kf_id), obs);
156 #ifdef SRBA_WORKAROUND_MSVC9_DEQUE_BUG
157 this->rba_state.k2k_edges[nei.
id]->inv_pose = this->rba_state.k2k_edges[nei.
id-1]->inv_pose;
159 this->rba_state.k2k_edges[nei.
id].inv_pose = this->rba_state.k2k_edges[nei.
id-1].inv_pose;
161 new_k2k_edge_ids.push_back(nei);
163 VERBOSE_LEVEL(2) <<
"[edge_creation_policy] Created extra edge #"<< nei.
id <<
": "<< central_kf_id <<
"->"<<new_kf_id <<
" with #obs: "<< num_obs_this_base<< endl;
167 VERBOSE_LEVEL(1) <<
"[edge_creation_policy] Skipped extra edge " << central_kf_id <<
"->"<<new_kf_id <<
" with #obs: "<< num_obs_this_base <<
" for too few shared obs!" << endl;
173 if (new_k2k_edge_ids.empty())
176 if (!obs_for_each_base_sorted.empty())
178 const size_t most_connected_nObs = obs_for_each_base_sorted.begin()->first;
179 const TKeyFrameID most_connected_kf_id = obs_for_each_base_sorted.begin()->second;
180 if (most_connected_nObs>=MINIMUM_OBS_TO_LOOP_CLOSURE)
184 nei.
id = this->create_kf2kf_edge(new_kf_id,
TPairKeyFrameID( most_connected_kf_id, new_kf_id), obs);
186 new_k2k_edge_ids.push_back(nei);
188 VERBOSE_LEVEL(0) <<
"[edge_creation_policy] Created edge of last resort #"<< nei.
id <<
": "<< most_connected_kf_id <<
"->"<<new_kf_id <<
" with #obs: "<< most_connected_nObs<< endl;
194 ASSERTMSG_(new_k2k_edge_ids.size()>=1,
mrpt::format(
"Error for new KF#%u: no suitable linking KF found with a minimum of %u common observation: the node becomes isolated of the graph!", static_cast<unsigned int>(new_kf_id),static_cast<unsigned int>(MINIMUM_OBS_TO_LOOP_CLOSURE) ))
197 if (new_k2k_edge_ids.size()>1 && m_verbose_level>=1)
199 cout <<
"\n[edge_creation_policy] Loop closure detected for KF#"<< new_kf_id <<
", edges: ";
200 for (
size_t j=0;j<new_k2k_edge_ids.size();j++)
202 #ifdef SRBA_WORKAROUND_MSVC9_DEQUE_BUG
203 cout << rba_state.k2k_edges[new_k2k_edge_ids[j].id]->from <<
"->"<<rba_state.k2k_edges[new_k2k_edge_ids[j].id]->to<<
", ";
205 cout << rba_state.k2k_edges[new_k2k_edge_ids[j].id].from <<
"->"<<rba_state.k2k_edges[new_k2k_edge_ids[j].id].to<<
", ";
225 const bool this_is_first = this->rba_state.k2k_edges.empty();
231 if (!this_is_first) {
233 #ifdef SRBA_WORKAROUND_MSVC9_DEQUE_BUG
234 this->rba_state.k2k_edges[nei.
id]->inv_pose = this->rba_state.k2k_edges[nei.
id-1]->inv_pose;
236 this->rba_state.k2k_edges[nei.
id].inv_pose = this->rba_state.k2k_edges[nei.
id-1].inv_pose;
243 new_k2k_edge_ids.push_back(nei);
248 THROW_EXCEPTION(
"Unknown value for 'parameters.edge_creation_policy'!")
255 template <
class KF2KF_POSE_TYPE,
class LM_TYPE,
class OBS_TYPE,
class RBA_OPTIONS>
259 std::map<TKeyFrameID,size_t> *out_obs_for_each_base )
const
264 map<TKeyFrameID,size_t> obs_for_each_base;
269 if (lm_id>=rba_state.all_lms.size())
continue;
272 if (!lme.rfp)
continue;
274 const TKeyFrameID base_id = lme.rfp->id_frame_base;
275 obs_for_each_base[base_id]++;
280 obs_for_each_base_sorted.insert( make_pair(it->second,it->first) );
282 if (out_obs_for_each_base)
283 out_obs_for_each_base->swap(obs_for_each_base);
virtual void edge_creation_policy(const TKeyFrameID new_kf_id, const typename traits_t::new_kf_observations_t &obs, std::vector< TNewEdgeInfo > &new_k2k_edge_ids)
Implements the edge-creation policy, by default depending on "parameters.edge_creation_policy" if the...
uint64_t TLandmarkID
Numeric IDs for landmarks.
#define THROW_EXCEPTION(msg)
The sub-map method introduced in the ICRA2013 paper.
const Scalar * const_iterator
KF2KF_POSE_TYPE::pose_t pose_t
The type of relative poses (e.g. mrpt::poses::CPose3D)
bool has_aprox_init_val
Whether the edge was assigned an approximated initial value.
uint64_t topo_dist_t
Unsigned integral type for topological distances in a graph/tree.
std::deque< new_kf_observation_t > new_kf_observations_t
A set of all the observations made from a new KF, as provided by the user.
std::string BASE_IMPEXP format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
Each keyframe is only connected to its predecessor (no loop closures)
void make_ordered_list_base_kfs(const typename traits_t::new_kf_observations_t &obs, base_sorted_lst_t &obs_for_each_base_sorted, std::map< TKeyFrameID, size_t > *out_obs_for_each_base=NULL) const
Make a list of base KFs of my new observations, ordered in descending order by # of shared observatio...
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
std::pair< TKeyFrameID, TKeyFrameID > TPairKeyFrameID
Used to represent the IDs of a directed edge (first –> second)
The argument "LM_TRAITS" can be any of those defined in srba/models/landmarks.h (typically, either landmarks::Euclidean3D or landmarks::Euclidean2D).
#define VERBOSE_LEVEL(_LEVEL)
size_t id
The new edge ID.
Used in TNewKeyFrameInfo.
std::multimap< size_t, TKeyFrameID, std::greater< size_t > > base_sorted_lst_t
All keyframes are connected to the first one (it can be used to emulate global coordinates) ...
#define ASSERTMSG_(f, __ERROR_MSG)
uint64_t TKeyFrameID
Numeric IDs for key-frames (KFs)