12 namespace mrpt {
namespace srba {
15 #define SYM_ST_SUPER_VERBOSE 0
20 template <
class KF2KF_POSE_TYPE,
class LM_TYPE,
class OBS_TYPE,
class RBA_OPTIONS>
25 const bool check_all_obs_are_connected,
33 std::set<TPairKeyFrameID> kfs_with_modified_next_edge;
44 const map<TKeyFrameID,TSpanTreeEntry> & st_ik = sym.next_edge[ik];
45 vector<pair<TKeyFrameID,topo_dist_t> > tk;
47 if (it->second.distance<max_depth)
48 tk.push_back( make_pair(it->first,it->second.distance) );
49 tk.push_back( make_pair(ik,0) );
53 const map<TKeyFrameID,TSpanTreeEntry> & st_n = sym.next_edge[new_node_id];
54 vector<pair<TKeyFrameID,const TSpanTreeEntry*> > STn;
56 STn.push_back( make_pair(it->first,&it->second) );
57 STn.push_back( pair<TKeyFrameID,const TSpanTreeEntry*>(new_node_id,static_cast<const TSpanTreeEntry*>(NULL)) );
60 for (
size_t r_idx=0;r_idx<STn.size();r_idx++)
66 map<TKeyFrameID,TSpanTreeEntry> & st_r = sym.next_edge[r];
73 ste_r2n = &it->second;
77 for (
size_t s_idx=0;s_idx<tk.size();s_idx++)
83 map<TKeyFrameID,TSpanTreeEntry> & st_s = sym.next_edge[s];
90 ste_s2ik = &it_ik_inSTs->second;
94 const topo_dist_t new_dist = dist_r2n + dist_s2ik + 1;
98 if (it_s_inSTr != st_r.end())
101 if (new_dist < it_s_inSTr->second.distance)
103 #if SYM_ST_SUPER_VERBOSE
104 cout <<
"ST: Shorter path ST["<<r<<
"]["<<s<<
"].N was "<<it_s_inSTr->second.next <<
" => "<<(ste_r2n ? ste_r2n->
next : ik) <<
"[D:"<<it_s_inSTr->second.distance<<
"=>"<<new_dist<<
"]"<<endl;
105 cout <<
"ST: Shorter path ST["<<s<<
"]["<<r<<
"].N was "<<st_s[r].next <<
" => "<<(ste_s2ik ? ste_s2ik->
next : new_node_id) <<
"[D:"<<st_s[r].distance<<
"=>"<<new_dist<<
"]"<<endl;
109 it_s_inSTr->second.distance = new_dist;
110 it_s_inSTr->second.next = ste_r2n ? ste_r2n->
next : ik;
116 ste_r_inSTs.
next = ste_s2ik ? ste_s2ik->
next : new_node_id;
120 kfs_with_modified_next_edge.insert( make_pair(s,r) );
121 kfs_with_modified_next_edge.insert( make_pair(r,s) );
127 if (new_dist<=max_depth)
129 #if SYM_ST_SUPER_VERBOSE
130 cout <<
"ST: New path ST["<<r<<
"]["<<s<<
"].N ="<<(ste_r2n ? ste_r2n->
next : ik) <<
"[D:"<<dist_r2n + dist_s2ik + 1<<
"]"<<endl;
131 cout <<
"ST: New path ST["<<s<<
"]["<<r<<
"].N ="<<(ste_s2ik ? ste_s2ik->
next : new_node_id) <<
"[D:"<<dist_r2n + dist_s2ik + 1<<
"]"<<endl;
138 ste_s_inSTr.distance = new_dist;
139 ste_s_inSTr.next = ste_r2n ? ste_r2n->
next : ik;
145 ste_r_inSTs.
next = ste_s2ik ? ste_s2ik->
next : new_node_id;
149 kfs_with_modified_next_edge.insert(make_pair(r,s));
150 kfs_with_modified_next_edge.insert(make_pair(s,r));
161 if (check_all_obs_are_connected)
166 std::set<TPairKeyFrameID> pending_checks;
168 for (
size_t i=0;i<obs->size();i++)
183 std::set<TPairKeyFrameID> done_checks;
184 while (!pending_checks.empty())
188 pending_checks.erase(pending_checks.begin());
190 if (done_checks.find(ft)!=done_checks.end())
194 std::map<TKeyFrameID,TSpanTreeEntry> & span_trees_from = sym.next_edge[ft.first];
196 if ( span_trees_from.find(ft.second)==span_trees_from.end() )
201 vector<TKeyFrameID> found_path;
203 bool found = m_parent->find_path_bfs(
208 ASSERT_(found && !found_path.empty())
212 ste.distance = found_path.size();
213 ste.next = *found_path.rbegin();
216 for (
size_t i=0;i<found_path.size();i++)
217 if (found_path[i]!=ft.second)
221 kfs_with_modified_next_edge.insert( ft );
225 done_checks.insert(ft);
231 #if defined(SYM_ST_SUPER_VERBOSE_SAVE_ALL_SPANNING_TREES)
234 const std::string sFil =
mrpt::format(
"debug_spantree_%05i.txt",i);
235 const std::string sFilDot =
mrpt::format(
"debug_spantree_%05i.dot",i);
236 const std::string sFilPng =
mrpt::format(
"debug_spantree_%05i.png",i);
237 this->dump_as_text_to_file(sFil);
238 this->save_as_dot_file(sFilDot);
239 ::system(
mrpt::format(
"dot %s -o %s -Tpng",sFilDot.c_str(), sFilPng.c_str() ).c_str());
249 const std::map<TKeyFrameID,TSpanTreeEntry> & Ds = sym.next_edge[ kf_id ];
257 const TKeyFrameID from = std::max(dst_kf_id, kf_id);
263 bool path_found = m_parent->find_path_bfs(from,to, NULL, &path);
268 #if defined(SYM_ST_EXTRA_SECURITY_CHECKS)
274 if (it->second.distance>max_depth)
277 s <<
"CONSISTENCY ERROR: Spanning tree of kf #" << it1->first <<
" has kf #" << it->first
278 <<
" at depth=" << it->second.distance <<
" > Max=" << max_depth << endl;
279 s <<
"After updating symbolic spanning trees for new kf #" << new_node_id <<
" with new edges: ";
280 for (
size_t i=0;i<new_edges.size();i++) s << new_edges[i].first <<
"->" << new_edges[i].second <<
", ";
288 template <class k2k_edge_t>
302 template <
class KF2KF_POSE_TYPE,
class LM_TYPE,
class OBS_TYPE,
class RBA_OPTIONS>
306 std::vector<TKeyFrameID> * out_path_IDs,
309 if (out_path_IDs) out_path_IDs->clear();
310 if (out_path_edges) out_path_edges->clear();
311 if (cur_node==trg_node)
return true;
313 std::set<TKeyFrameID> visited;
314 std::queue<TKeyFrameID> pending;
315 std::map<TKeyFrameID,TBFSEntry<k2k_edge_t> > preceding;
318 pending.push(cur_node);
319 visited.insert(cur_node);
320 preceding[cur_node].dist = 0;
322 while (!pending.empty())
330 if (next_kf==trg_node)
334 if (out_path_IDs) out_path_IDs->resize(dist);
335 if (out_path_edges) out_path_edges->resize(dist);
337 while (path_node != cur_node)
340 if (out_path_IDs) (*out_path_IDs)[--dist] = path_node;
342 typename std::map<TKeyFrameID,TBFSEntry<k2k_edge_t> >
::const_iterator it_prec = preceding.find(path_node);
343 ASSERT_(it_prec != preceding.end())
344 path_node = it_prec->second.prev;
346 if (out_path_edges) (*out_path_edges)[--dist] = it_prec->second.prev_edge;
355 for (
size_t i=0;i<kfi.adjacent_k2k_edges.size();i++)
357 const k2k_edge_t* ed = kfi.adjacent_k2k_edges[i];
359 if (!visited.count(new_kf))
361 pending.push(new_kf);
362 visited.insert(new_kf);
366 if (p.
dist>cur_dist+1)
TLandmarkID feat_id
Observed what.
rba_joint_parameterization_traits_t< KF2KF_POSE_TYPE, LM_TYPE, OBS_TYPE >::new_kf_observations_t new_kf_observations_t
vec_t::const_iterator const_iterator
#define THROW_EXCEPTION(msg)
const Scalar * const_iterator
Keyframe-to-keyframe edge: an unknown of the problem.
uint64_t topo_dist_t
Unsigned integral type for topological distances in a graph/tree.
TKeyFrameID next
The next keyframe in the tree.
obs_traits_t::observation_t obs
The argument "POSE_TRAITS" can be any of those defined in srba/models/kf2kf_poses.h (typically, either kf2kf_poses::SE3 or kf2kf_poses::SE2).
Observations, as provided by the user.
void update_symbolic_new_node(const TKeyFrameID new_node_id, const TPairKeyFrameID &new_edge, const topo_dist_t max_depth, const bool check_all_obs_are_connected=false, const new_kf_observations_t *obs=NULL)
Incremental update of spanning trees after the insertion of ONE new node and ONE OR MORE edges...
std::string BASE_IMPEXP format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
Used in TRBA_Problem_state.
V getTheOtherFromPair(const V one, const PAIR &p)
Aux function for getting, from a std::pair, "the other" element which is different to a known given o...
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
#define ASSERTDEB_(f)
Defines an assertion mechanism - only when compiled in debug.
#define ASSERT_NOT_EQUAL_(__A, __B)
std::pair< TKeyFrameID, TKeyFrameID > TPairKeyFrameID
Used to represent the IDs of a directed edge (first –> second)
bool find_path_bfs(const TKeyFrameID from, const TKeyFrameID to, std::vector< TKeyFrameID > *out_path_IDs, typename kf2kf_pose_traits< KF2KF_POSE_TYPE >::k2k_edge_vector_t *out_path_edges=NULL) const
Auxiliary, brute force (BFS) method for finding the shortest path between any two Keyframes...
Information per key-frame needed for RBA.
topo_dist_t distance
Remaining distance until the given target from this point.
V getTheOtherFromPair2(const V one, const K2K_EDGE &p)
For usage with K2K_EDGE = typename kf2kf_pose_traits
::k2k_edge_t.
uint64_t TKeyFrameID
Numeric IDs for key-frames (KFs)