9 #ifndef CONSTRAINED_POSE_NETWORK_IMPL_H
10 #define CONSTRAINED_POSE_NETWORK_IMPL_H
40 template <
class POSE_PDF>
78 template <
class graph_t>
85 f <<
"VERTEX2 " <<
id <<
" " <<
p.x() <<
" " <<
p.y() <<
" " <<
p.phi();
93 f <<
"VERTEX3 " <<
id <<
" " <<
p.x() <<
" " <<
p.y() <<
" " <<
p.z()
94 <<
" " <<
p.roll() <<
" " <<
p.pitch() <<
" " <<
p.yaw();
105 f <<
"EDGE2 " << edgeIDs.first <<
" " << edgeIDs.second <<
" "
121 f <<
"EDGE3 " << edgeIDs.first <<
" " << edgeIDs.second <<
" "
142 write_EDGE_line(edgeIDs,
p, f);
150 write_EDGE_line(edgeIDs,
p, f);
158 p.cov_inv.unit(3, 1.0);
159 write_EDGE_line(edgeIDs,
p, f);
167 p.cov_inv.unit(6, 1.0);
168 write_EDGE_line(edgeIDs,
p, f);
181 "Error opening file '%s' for writing", fil.c_str());
186 itNod !=
g->nodes.end(); ++itNod)
188 write_VERTEX_line(itNod->first, itNod->second, f);
191 f <<
" | " << itNod->second.retAnnotsAsString() << endl;
197 if (it->first.first != it->first.second)
201 write_EDGE_line(it->first, it->second, f);
219 out <<
g->nodes <<
g->edges <<
g->root;
232 in >> sStoredClassName;
237 in >> stored_version;
240 switch (stored_version)
243 in >>
g->nodes >>
g->edges >>
g->root;
259 using CPOSE =
typename graph_t::constraint_t;
261 set<string> alreadyWarnedUnknowns;
270 const bool graph_is_3D = CPOSE::is_3D();
280 map<TNodeID, TNodeID> lstEquivs;
289 const string lin =
s.str();
292 if (!(
s >> key) || key.empty())
294 "Line %u: Can't read string for entry type in: '%s'",
295 lineNum, lin.c_str()));
301 if (!(
s >> id1 >> id2))
303 "Line %u: Can't read id1 & id2 in EQUIV line: '%s'",
304 lineNum, lin.c_str()));
305 lstEquivs[std::max(id1, id2)] =
std::min(id1, id2);
318 const string lin =
s.str();
334 if (!(
s >> key) || key.empty())
336 "Line %u: Can't read string for entry type in: '%s'",
337 lineNum, lin.c_str()));
344 if (!(
s >>
id >> p2D.
x >> p2D.
y >> p2D.
phi))
346 "Line %u: Error parsing VERTEX2 line: '%s'", lineNum,
350 if (
g->nodes.find(
id) !=
g->nodes.end())
352 "Line %u: Error, duplicated verted ID %u in line: "
354 lineNum,
static_cast<unsigned int>(
id), lin.c_str()));
360 if (itEq != lstEquivs.end())
id = itEq->second;
364 if (
g->nodes.find(
id) ==
g->nodes.end())
367 CPOSE>::constraint_t::type_value;
373 else if (
strCmpI(key,
"VERTEX3"))
377 "Line %u: Try to load VERTEX3 into a 2D graph: "
379 lineNum, lin.c_str()));
386 if (!(
s >>
id >> p3D.
x >> p3D.
y >> p3D.
z >> p3D.
roll >>
389 "Line %u: Error parsing VERTEX3 line: '%s'", lineNum,
393 if (
g->nodes.find(
id) !=
g->nodes.end())
395 "Line %u: Error, duplicated verted ID %u in line: "
397 lineNum,
static_cast<unsigned int>(
id), lin.c_str()));
403 if (itEq != lstEquivs.end())
id = itEq->second;
407 if (
g->nodes.find(
id) ==
g->nodes.end())
414 else if (
strCmpI(key,
"VERTEX_SE3:QUAT"))
418 "Line %u: Try to load VERTEX_SE3:QUAT into a 2D "
420 lineNum, lin.c_str()));
425 if (!(
s >>
id >> p3D.
x >> p3D.
y >> p3D.
z >> p3D.
qx >> p3D.
qy >>
428 "Line %u: Error parsing VERTEX_SE3:QUAT line: '%s'",
429 lineNum, lin.c_str()));
432 if (
g->nodes.find(
id) !=
g->nodes.end())
434 "Line %u: Error, duplicated verted ID %u in line: "
436 lineNum,
static_cast<unsigned int>(
id), lin.c_str()));
442 if (itEq != lstEquivs.end())
id = itEq->second;
446 if (
g->nodes.find(
id) ==
g->nodes.end())
468 if (!(
s >> from_id >> to_id))
470 "Line %u: Error parsing EDGE2 line: '%s'", lineNum,
476 lstEquivs.find(to_id);
477 if (itEq != lstEquivs.end()) to_id = itEq->second;
481 lstEquivs.find(from_id);
482 if (itEq != lstEquivs.end()) from_id = itEq->second;
485 if (from_id != to_id)
490 if (!(
s >> Ap_mean.
x >> Ap_mean.
y >> Ap_mean.
phi >>
491 Ap_cov_inv(0, 0) >> Ap_cov_inv(0, 1) >>
492 Ap_cov_inv(1, 1) >> Ap_cov_inv(2, 2) >>
493 Ap_cov_inv(0, 2) >> Ap_cov_inv(1, 2)))
495 "Line %u: Error parsing EDGE2 line: '%s'", lineNum,
499 Ap_cov_inv(1, 0) = Ap_cov_inv(0, 1);
500 Ap_cov_inv(2, 0) = Ap_cov_inv(0, 2);
501 Ap_cov_inv(2, 1) = Ap_cov_inv(1, 2);
508 g->insertEdge(from_id, to_id, newEdge);
511 else if (
strCmpI(key,
"EDGE3"))
515 "Line %u: Try to load EDGE3 into a 2D graph: '%s'",
516 lineNum, lin.c_str()));
521 if (!(
s >> from_id >> to_id))
523 "Line %u: Error parsing EDGE3 line: '%s'", lineNum,
529 lstEquivs.find(to_id);
530 if (itEq != lstEquivs.end()) to_id = itEq->second;
534 lstEquivs.find(from_id);
535 if (itEq != lstEquivs.end()) from_id = itEq->second;
538 if (from_id != to_id)
545 if (!(
s >> Ap_mean.
x >> Ap_mean.
y >> Ap_mean.
z >>
548 "Line %u: Error parsing EDGE3 line: '%s'", lineNum,
553 if (!(
s >> Ap_cov_inv(0, 0) >> Ap_cov_inv(0, 1) >>
554 Ap_cov_inv(0, 2) >> Ap_cov_inv(0, 5) >>
555 Ap_cov_inv(0, 4) >> Ap_cov_inv(0, 3) >>
556 Ap_cov_inv(1, 1) >> Ap_cov_inv(1, 2) >>
557 Ap_cov_inv(1, 5) >> Ap_cov_inv(1, 4) >>
558 Ap_cov_inv(1, 3) >> Ap_cov_inv(2, 2) >>
559 Ap_cov_inv(2, 5) >> Ap_cov_inv(2, 4) >>
560 Ap_cov_inv(2, 3) >> Ap_cov_inv(5, 5) >>
561 Ap_cov_inv(5, 4) >> Ap_cov_inv(5, 3) >>
562 Ap_cov_inv(4, 4) >> Ap_cov_inv(4, 3) >>
566 Ap_cov_inv.unit(6, 1.0);
568 if (alreadyWarnedUnknowns.find(
"MISSING_3D") ==
569 alreadyWarnedUnknowns.end())
571 alreadyWarnedUnknowns.insert(
"MISSING_3D");
572 cerr <<
"[CNetworkOfPoses::loadFromTextFile] "
573 << fil <<
":" << lineNum
574 <<
": Warning: Information matrix missing, "
581 for (
size_t r = 1;
r < 6;
r++)
582 for (
size_t c = 0;
c <
r;
c++)
583 Ap_cov_inv(
r,
c) = Ap_cov_inv(
c,
r);
591 g->insertEdge(from_id, to_id, newEdge);
594 else if (
strCmpI(key,
"EDGE_SE3:QUAT"))
598 "Line %u: Try to load EDGE3 into a 2D graph: '%s'",
599 lineNum, lin.c_str()));
606 if (!(
s >> from_id >> to_id))
608 "Line %u: Error parsing EDGE_SE3:QUAT line: '%s'",
609 lineNum, lin.c_str()));
614 lstEquivs.find(to_id);
615 if (itEq != lstEquivs.end()) to_id = itEq->second;
619 lstEquivs.find(from_id);
620 if (itEq != lstEquivs.end()) from_id = itEq->second;
623 if (from_id != to_id)
628 if (!(
s >> Ap_mean.
x >> Ap_mean.
y >> Ap_mean.
z >>
629 Ap_mean.
qx >> Ap_mean.
qy >> Ap_mean.
qz >> Ap_mean.
qr))
631 "Line %u: Error parsing EDGE_SE3:QUAT line: "
633 lineNum, lin.c_str()));
637 if (!(
s >> Ap_cov_inv(0, 0) >> Ap_cov_inv(0, 1) >>
638 Ap_cov_inv(0, 2) >> Ap_cov_inv(0, 5) >>
639 Ap_cov_inv(0, 4) >> Ap_cov_inv(0, 3) >>
640 Ap_cov_inv(1, 1) >> Ap_cov_inv(1, 2) >>
641 Ap_cov_inv(1, 5) >> Ap_cov_inv(1, 4) >>
642 Ap_cov_inv(1, 3) >> Ap_cov_inv(2, 2) >>
643 Ap_cov_inv(2, 5) >> Ap_cov_inv(2, 4) >>
644 Ap_cov_inv(2, 3) >> Ap_cov_inv(5, 5) >>
645 Ap_cov_inv(5, 4) >> Ap_cov_inv(5, 3) >>
646 Ap_cov_inv(4, 4) >> Ap_cov_inv(4, 3) >>
650 Ap_cov_inv.unit(6, 1.0);
652 if (alreadyWarnedUnknowns.find(
"MISSING_3D") ==
653 alreadyWarnedUnknowns.end())
655 alreadyWarnedUnknowns.insert(
"MISSING_3D");
656 cerr <<
"[CNetworkOfPoses::loadFromTextFile] "
657 << fil <<
":" << lineNum
658 <<
": Warning: Information matrix missing, "
665 for (
size_t r = 1;
r < 6;
r++)
666 for (
size_t c = 0;
c <
r;
c++)
667 Ap_cov_inv(
r,
c) = Ap_cov_inv(
c,
r);
676 g->insertEdge(from_id, to_id, newEdge);
679 else if (
strCmpI(key,
"EQUIV"))
685 if (alreadyWarnedUnknowns.find(key) ==
686 alreadyWarnedUnknowns.end())
688 alreadyWarnedUnknowns.insert(key);
689 cerr <<
"[CNetworkOfPoses::loadFromTextFile] " << fil <<
":"
690 << lineNum <<
": Warning: unknown entry type: " << key
715 using TListAllEdges =
716 map<pair<TNodeID, TNodeID>,
717 vector<TEdgeIterator>>;
720 TListAllEdges lstAllEdges;
723 for (TEdgeIterator itEd =
g->edges.begin(); itEd !=
g->edges.end();
727 const pair<TNodeID, TNodeID> arc_id = make_pair(
728 std::min(itEd->first.first, itEd->first.second),
729 std::max(itEd->first.first, itEd->first.second));
731 vector<TEdgeIterator>& lstEdges = lstAllEdges[arc_id];
733 lstEdges.push_back(itEd);
739 it != lstAllEdges.end(); ++it)
741 const size_t N = it->second.size();
742 for (
size_t i = 1; i < N; i++)
743 g->edges.erase(it->second[i]);
745 if (N >= 2) nRemoved += N - 1;
769 using constraint_t =
typename graph_t::constraint_t;
772 dijkstra_t dijkstra(*
g,
g->root);
776 typename dijkstra_t::tree_graph_t treeView;
777 dijkstra.getTreeGraph(treeView);
780 struct VisitorComputePoses :
public dijkstra_t::tree_graph_t::Visitor
784 VisitorComputePoses(graph_t*
g) : m_g(
g) {}
785 virtual void OnVisitNode(
787 const typename dijkstra_t::tree_graph_t::Visitor::tree_t::
788 TEdgeInfo& edge_to_child,
789 const size_t depth_level)
override
792 const TNodeID child_id = edge_to_child.id;
798 if ((!edge_to_child.reverse &&
799 !m_g->edges_store_inverse_poses) ||
800 (edge_to_child.reverse && m_g->edges_store_inverse_poses))
802 m_g->nodes[child_id].composeFrom(
803 m_g->nodes[parent_id],
804 edge_to_child.data->getPoseMean());
808 m_g->nodes[child_id].composeFrom(
809 m_g->nodes[parent_id],
810 -edge_to_child.data->getPoseMean());
820 bool empty_node_annots =
g->nodes.begin()->second.is_node_annots_empty;
821 map<const TNodeID, TNodeAnnotations*> nodeID_to_annots;
822 if (!empty_node_annots)
826 poses_cit !=
g->nodes.end(); ++poses_cit)
828 nodeID_to_annots.insert(make_pair(
829 poses_cit->first, poses_cit->second.getCopyOfAnnots()));
835 typename constraint_t::type_value();
838 VisitorComputePoses myVisitor(
g);
839 treeView.visitBreadthFirst(treeView.root, myVisitor);
842 if (!empty_node_annots)
846 poses_cit !=
g->nodes.end(); ++poses_cit)
849 nodeID_to_annots.at(poses_cit->first);
850 bool res = poses_cit->second.setAnnots(*node_annots);
859 "Setting annotations for nodeID \"%lu\" was "
861 static_cast<unsigned long>(poses_cit->first)));
950 bool ignoreCovariances)
955 const TNodeID from_id = itEdge->first.first;
956 const TNodeID to_id = itEdge->first.second;
960 g->nodes.find(from_id);
962 g->nodes.find(to_id);
964 itPoseFrom !=
g->nodes.end(),
966 "Node %u doesn't have a global pose in 'nodes'.",
967 static_cast<unsigned int>(from_id)));
969 itPoseTo !=
g->nodes.end(),
971 "Node %u doesn't have a global pose in 'nodes'.",
972 static_cast<unsigned int>(to_id)));
975 using constraint_t =
typename graph_t::constraint_t;
977 const typename constraint_t::type_value& from_mean = itPoseFrom->second;
978 const typename constraint_t::type_value& to_mean = itPoseTo->second;
981 const constraint_t& edge_delta_pose = itEdge->second;
982 const typename constraint_t::type_value& edge_delta_pose_mean =
983 edge_delta_pose.getPoseMean();
985 if (ignoreCovariances)
988 typename constraint_t::type_value from_plus_delta(
990 from_plus_delta.composeFrom(from_mean, edge_delta_pose_mean);
993 return auxEuclid2Dist(from_plus_delta, to_mean);
999 constraint_t from_plus_delta = edge_delta_pose;
1000 from_plus_delta.changeCoordinatesReference(from_mean);
1009 err[i] = from_plus_delta.getPoseMean()[i] - to_mean[i];
1012 return auxMaha2Dist(err, from_plus_delta);