28 #ifndef CONSTRAINED_POSE_NETWORK_IMPL_H
29 #define CONSTRAINED_POSE_NETWORK_IMPL_H
43 using namespace mrpt::utils;
44 using namespace mrpt::poses;
45 using namespace mrpt::graphs;
64 template <
class graph_t>
67 static void write_VERTEX_line(
const TNodeID id,
const CPose2D &p, std::ofstream &f)
70 f <<
"VERTEX2 " <<
id <<
" " << p.
x() <<
" " << p.
y() <<
" " << p.
phi() << endl;
72 static void write_VERTEX_line(
const TNodeID id,
const CPose3D &p, std::ofstream &f)
76 f <<
"VERTEX3 " <<
id <<
" " << p.
x() <<
" " << p.
y() <<
" " << p.z()<<
" " << p.
roll()<<
" " << p.
pitch()<<
" " << p.
yaw() << endl;
84 f <<
"EDGE2 " << edgeIDs.first <<
" " << edgeIDs.second <<
" " <<
94 f <<
"EDGE3 " << edgeIDs.first <<
" " << edgeIDs.second <<
" " <<
108 write_EDGE_line(edgeIDs,p,f);
114 write_EDGE_line(edgeIDs,p,f);
121 write_EDGE_line(edgeIDs,p,f);
128 write_EDGE_line(edgeIDs,p,f);
135 static void save_graph_of_poses_from_text_file(
const graph_t *g,
const std::string &fil)
137 typedef typename graph_t::constraint_t CPOSE;
146 write_VERTEX_line(itNod->first, itNod->second, f);
150 if (it->first.first!=it->first.second)
151 write_EDGE_line( it->first, it->second, f);
159 static void load_graph_of_poses_from_text_file(graph_t *g,
const std::string &fil)
161 typedef typename graph_t::constraint_t CPOSE;
163 set<string> alreadyWarnedUnknowns;
170 const bool graph_is_3D = CPOSE::is_3D();
179 map<TNodeID,TNodeID> lstEquivs;
186 const string lin = s.str();
189 if ( !(s >> key) || key.empty() )
190 THROW_EXCEPTION(
format(
"Line %u: Can't read string for entry type in: '%s'", lineNum, lin.c_str() ) );
196 if (!(s>> id1 >> id2))
197 THROW_EXCEPTION(
format(
"Line %u: Can't read id1 & id2 in EQUIV line: '%s'", lineNum, lin.c_str() ) );
198 lstEquivs[std::max(id1,id2)] = std::min(id1,id2);
211 const string lin = s.str();
220 if ( !(s >> key) || key.empty() )
221 THROW_EXCEPTION(
format(
"Line %u: Can't read string for entry type in: '%s'", lineNum, lin.c_str() ) );
227 if (!(s>>
id >> p2D.x >> p2D.y >> p2D.phi))
231 if (g->nodes.find(
id)!=g->nodes.end())
232 THROW_EXCEPTION(
format(
"Line %u: Error, duplicated verted ID %u in line: '%s'", lineNum, static_cast<unsigned int>(
id), lin.c_str() ) );
237 if (itEq!=lstEquivs.end())
id = itEq->second;
241 if (g->nodes.find(
id)==g->nodes.end())
247 else if (
strCmpI(key,
"VERTEX3") )
250 THROW_EXCEPTION(
format(
"Line %u: Try to load VERTEX3 into a 2D graph: '%s'", lineNum, lin.c_str() ) );
257 if (!(s>>
id >> p3D.x >> p3D.y >> p3D.z >> p3D.roll >> p3D.pitch >> p3D.yaw ))
261 if (g->nodes.find(
id)!=g->nodes.end())
262 THROW_EXCEPTION(
format(
"Line %u: Error, duplicated verted ID %u in line: '%s'", lineNum, static_cast<unsigned int>(
id), lin.c_str() ) );
267 if (itEq!=lstEquivs.end())
id = itEq->second;
271 if (g->nodes.find(
id)==g->nodes.end())
286 if (!(s>> from_id >> to_id ))
292 if (itEq!=lstEquivs.end()) to_id = itEq->second;
296 if (itEq!=lstEquivs.end()) from_id = itEq->second;
304 Ap_mean.x >> Ap_mean.y >> Ap_mean.phi >>
305 Ap_cov_inv(0,0) >> Ap_cov_inv(0,1) >> Ap_cov_inv(1,1) >>
306 Ap_cov_inv(2,2) >> Ap_cov_inv(0,2) >> Ap_cov_inv(1,2) ))
310 Ap_cov_inv(1,0) = Ap_cov_inv(0,1);
311 Ap_cov_inv(2,0) = Ap_cov_inv(0,2);
312 Ap_cov_inv(2,1) = Ap_cov_inv(1,2);
317 g->insertEdge(from_id, to_id, newEdge);
320 else if (
strCmpI(key,
"EDGE3") )
327 if (!(s>> from_id >> to_id ))
333 if (itEq!=lstEquivs.end()) to_id = itEq->second;
337 if (itEq!=lstEquivs.end()) from_id = itEq->second;
345 if (!(s>> Ap_mean.x >> Ap_mean.y >> Ap_mean.z >> Ap_mean.roll >> Ap_mean.pitch >> Ap_mean.yaw ))
350 Ap_cov_inv(0,0) >> Ap_cov_inv(0,1) >> Ap_cov_inv(0,2) >> Ap_cov_inv(0,5) >> Ap_cov_inv(0,4) >> Ap_cov_inv(0,3) >>
351 Ap_cov_inv(1,1) >> Ap_cov_inv(1,2) >> Ap_cov_inv(1,5) >> Ap_cov_inv(1,4) >> Ap_cov_inv(1,3) >>
352 Ap_cov_inv(2,2) >> Ap_cov_inv(2,5) >> Ap_cov_inv(2,4) >> Ap_cov_inv(2,3) >>
353 Ap_cov_inv(5,5) >> Ap_cov_inv(5,4) >> Ap_cov_inv(5,3) >>
354 Ap_cov_inv(4,4) >> Ap_cov_inv(4,3) >>
358 Ap_cov_inv.unit(6,1.0);
360 if (alreadyWarnedUnknowns.find(
"MISSING_3D")==alreadyWarnedUnknowns.end())
362 alreadyWarnedUnknowns.insert(
"MISSING_3D");
363 cerr <<
"[CNetworkOfPoses::loadFromTextFile] " << fil <<
":" << lineNum <<
": Warning: Information matrix missing, assuming unity.\n";
369 for (
size_t r=1;r<6;r++)
370 for (
size_t c=0;c<r;c++)
371 Ap_cov_inv(r,c) = Ap_cov_inv(c,r);
377 g->insertEdge(from_id, to_id, newEdge);
380 else if (
strCmpI(key,
"EQUIV") )
386 if (alreadyWarnedUnknowns.find(key)==alreadyWarnedUnknowns.end())
388 alreadyWarnedUnknowns.insert(key);
389 cerr <<
"[CNetworkOfPoses::loadFromTextFile] " << fil <<
":" << lineNum <<
": Warning: unknown entry type: " << key << endl;
404 static size_t graph_of_poses_collapse_dup_edges(graph_t *g)
411 typedef map<pair<TNodeID,TNodeID>, vector<TEdgeIterator> > TListAllEdges;
412 TListAllEdges lstAllEdges;
415 for (TEdgeIterator itEd=g->edges.begin();itEd!=g->edges.end();++itEd)
418 const pair<TNodeID,TNodeID> arc_id = make_pair( std::min(itEd->first.first,itEd->first.second),std::max(itEd->first.first,itEd->first.second) );
420 vector<TEdgeIterator> &lstEdges = lstAllEdges[arc_id];
422 lstEdges.push_back(itEd);
429 const size_t N = it->second.size();
430 for (
size_t i=1;i<N;i++)
431 g->edges.erase( it->second[i] );
433 if (N>=2) nRemoved+=N-1;
446 static void graph_of_poses_dijkstra_init(graph_t *g)
452 typedef typename graph_t::constraint_t constraint_t;
454 dijkstra_t dijkstra(*g, g->root);
458 typename dijkstra_t::tree_graph_t treeView;
459 dijkstra.getTreeGraph(treeView);
462 struct VisitorComputePoses :
public dijkstra_t::tree_graph_t::Visitor
466 VisitorComputePoses(graph_t *g) : m_g(g) { }
467 virtual void OnVisitNode(
const TNodeID parent_id,
const typename dijkstra_t::tree_graph_t::Visitor::tree_t::TEdgeInfo &edge_to_child,
const size_t depth_level )
469 const TNodeID child_id = edge_to_child.id;
473 if ( (!edge_to_child.reverse && !m_g->edges_store_inverse_poses) ||
474 ( edge_to_child.reverse && m_g->edges_store_inverse_poses)
477 m_g->nodes[child_id].composeFrom( m_g->nodes[parent_id], edge_to_child.data->getPoseMean() );
481 m_g->nodes[child_id].composeFrom( m_g->nodes[parent_id], - edge_to_child.data->getPoseMean() );
488 g->nodes[g->root] =
typename constraint_t::type_value();
491 VisitorComputePoses myVisitor(g);
492 treeView.visitBreadthFirst(treeView.root, myVisitor);
557 static double graph_edge_sqerror(
560 bool ignoreCovariances )
565 const TNodeID from_id = itEdge->first.first;
566 const TNodeID to_id = itEdge->first.second;
571 ASSERTMSG_(itPoseFrom!=g->nodes.end(),
format(
"Node %u doesn't have a global pose in 'nodes'.", static_cast<unsigned int>(from_id)))
572 ASSERTMSG_(itPoseTo!=g->nodes.end(),
format(
"Node %u doesn't have a global pose in 'nodes'.", static_cast<unsigned int>(to_id)))
575 typedef typename graph_t::constraint_t constraint_t;
577 const typename constraint_t::type_value &from_mean = itPoseFrom->second;
578 const typename constraint_t::type_value &to_mean = itPoseTo->second;
581 const constraint_t &edge_delta_pose = itEdge->second;
582 const typename constraint_t::type_value &edge_delta_pose_mean = edge_delta_pose.getPoseMean();
584 if (ignoreCovariances)
588 from_plus_delta.composeFrom(from_mean, edge_delta_pose_mean);
591 return auxEuclid2Dist(from_plus_delta,to_mean);
597 constraint_t from_plus_delta = edge_delta_pose;
598 from_plus_delta.changeCoordinatesReference(from_mean);
604 CArrayDouble<constraint_t::type_value::static_size> err;
606 err[i] = from_plus_delta.getPoseMean()[i] - to_mean[i];
609 return auxMaha2Dist(err,from_plus_delta);