9 #ifndef CONSTRAINED_POSE_NETWORK_IMPL_H
10 #define CONSTRAINED_POSE_NETWORK_IMPL_H
56 template <
class graph_t>
62 f <<
"VERTEX2 " <<
id <<
" " << p.
x() <<
" " << p.
y() <<
" " << p.
phi() << endl;
68 f <<
"VERTEX3 " <<
id <<
" " << p.
x() <<
" " << p.
y() <<
" " << p.z()<<
" " << p.
roll()<<
" " << p.
pitch()<<
" " << p.
yaw() << endl;
76 f <<
"EDGE2 " << edgeIDs.first <<
" " << edgeIDs.second <<
" " <<
86 f <<
"EDGE3 " << edgeIDs.first <<
" " << edgeIDs.second <<
" " <<
100 write_EDGE_line(edgeIDs,p,f);
106 write_EDGE_line(edgeIDs,p,f);
113 write_EDGE_line(edgeIDs,p,f);
120 write_EDGE_line(edgeIDs,p,f);
136 write_VERTEX_line(itNod->first, itNod->second, f);
140 if (it->first.first!=it->first.second)
141 write_EDGE_line( it->first, it->second, f);
155 const uint32_t version = 0;
157 out << g->nodes << g->edges << g->root;
167 std::string sStoredClassName;
168 in >> sStoredClassName;
172 uint32_t stored_version;
173 in >> stored_version;
176 switch (stored_version)
179 in >> g->nodes >> g->edges >> g->root;
194 typedef typename graph_t::constraint_t CPOSE;
196 set<string> alreadyWarnedUnknowns;
203 const bool graph_is_3D = CPOSE::is_3D();
212 map<TNodeID,TNodeID> lstEquivs;
219 const string lin = s.str();
222 if ( !(s >> key) || key.empty() )
223 THROW_EXCEPTION(
format(
"Line %u: Can't read string for entry type in: '%s'", lineNum, lin.c_str() ) );
229 if (!(s>> id1 >> id2))
230 THROW_EXCEPTION(
format(
"Line %u: Can't read id1 & id2 in EQUIV line: '%s'", lineNum, lin.c_str() ) );
231 lstEquivs[std::max(id1,id2)] = std::min(id1,id2);
244 const string lin = s.str();
257 if ( !(s >> key) || key.empty() )
258 THROW_EXCEPTION(
format(
"Line %u: Can't read string for entry type in: '%s'", lineNum, lin.c_str() ) );
264 if (!(s>>
id >> p2D.
x >> p2D.
y >> p2D.
phi))
268 if (g->nodes.find(
id)!=g->nodes.end())
269 THROW_EXCEPTION(
format(
"Line %u: Error, duplicated verted ID %u in line: '%s'", lineNum, static_cast<unsigned int>(
id), lin.c_str() ) );
274 if (itEq!=lstEquivs.end())
id = itEq->second;
278 if (g->nodes.find(
id)==g->nodes.end())
284 else if (
strCmpI(key,
"VERTEX3") )
287 THROW_EXCEPTION(
format(
"Line %u: Try to load VERTEX3 into a 2D graph: '%s'", lineNum, lin.c_str() ) );
293 if (!(s>>
id >> p3D.
x >> p3D.
y >> p3D.
z >> p3D.
roll >> p3D.
pitch >> p3D.
yaw ))
297 if (g->nodes.find(
id)!=g->nodes.end())
298 THROW_EXCEPTION(
format(
"Line %u: Error, duplicated verted ID %u in line: '%s'", lineNum, static_cast<unsigned int>(
id), lin.c_str() ) );
303 if (itEq!=lstEquivs.end())
id = itEq->second;
307 if (g->nodes.find(
id)==g->nodes.end())
312 else if (
strCmpI(key,
"VERTEX_SE3:QUAT") )
315 THROW_EXCEPTION(
format(
"Line %u: Try to load VERTEX_SE3:QUAT into a 2D graph: '%s'", lineNum, lin.c_str() ) );
320 if (!(s>>
id >> p3D.
x >> p3D.
y >> p3D.
z >> p3D.
qx >> p3D.
qy >> p3D.
qz >> p3D.
qr ))
321 THROW_EXCEPTION(
format(
"Line %u: Error parsing VERTEX_SE3:QUAT line: '%s'", lineNum, lin.c_str() ) );
324 if (g->nodes.find(
id)!=g->nodes.end())
325 THROW_EXCEPTION(
format(
"Line %u: Error, duplicated verted ID %u in line: '%s'", lineNum, static_cast<unsigned int>(
id), lin.c_str() ) );
330 if (itEq!=lstEquivs.end())
id = itEq->second;
334 if (g->nodes.find(
id)==g->nodes.end())
349 if (!(s>> from_id >> to_id ))
355 if (itEq!=lstEquivs.end()) to_id = itEq->second;
359 if (itEq!=lstEquivs.end()) from_id = itEq->second;
367 Ap_mean.
x >> Ap_mean.
y >> Ap_mean.
phi >>
368 Ap_cov_inv(0,0) >> Ap_cov_inv(0,1) >> Ap_cov_inv(1,1) >>
369 Ap_cov_inv(2,2) >> Ap_cov_inv(0,2) >> Ap_cov_inv(1,2) ))
373 Ap_cov_inv(1,0) = Ap_cov_inv(0,1);
374 Ap_cov_inv(2,0) = Ap_cov_inv(0,2);
375 Ap_cov_inv(2,1) = Ap_cov_inv(1,2);
380 g->insertEdge(from_id, to_id, newEdge);
383 else if (
strCmpI(key,
"EDGE3") )
390 if (!(s>> from_id >> to_id ))
396 if (itEq!=lstEquivs.end()) to_id = itEq->second;
400 if (itEq!=lstEquivs.end()) from_id = itEq->second;
408 if (!(s>> Ap_mean.
x >> Ap_mean.
y >> Ap_mean.
z >> Ap_mean.
roll >> Ap_mean.
pitch >> Ap_mean.
yaw ))
413 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) >>
414 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) >>
415 Ap_cov_inv(2,2) >> Ap_cov_inv(2,5) >> Ap_cov_inv(2,4) >> Ap_cov_inv(2,3) >>
416 Ap_cov_inv(5,5) >> Ap_cov_inv(5,4) >> Ap_cov_inv(5,3) >>
417 Ap_cov_inv(4,4) >> Ap_cov_inv(4,3) >>
421 Ap_cov_inv.unit(6,1.0);
423 if (alreadyWarnedUnknowns.find(
"MISSING_3D")==alreadyWarnedUnknowns.end())
425 alreadyWarnedUnknowns.insert(
"MISSING_3D");
426 cerr <<
"[CNetworkOfPoses::loadFromTextFile] " << fil <<
":" << lineNum <<
": Warning: Information matrix missing, assuming unity.\n";
432 for (
size_t r=1;r<6;r++)
433 for (
size_t c=0;c<r;c++)
434 Ap_cov_inv(r,c) = Ap_cov_inv(c,r);
440 g->insertEdge(from_id, to_id, newEdge);
443 else if (
strCmpI(key,
"EDGE_SE3:QUAT") )
451 if (!(s>> from_id >> to_id ))
457 if (itEq!=lstEquivs.end()) to_id = itEq->second;
461 if (itEq!=lstEquivs.end()) from_id = itEq->second;
468 if (!(s>> Ap_mean.
x >> Ap_mean.
y >> Ap_mean.
z >> Ap_mean.
qx >> Ap_mean.
qy >> Ap_mean.
qz >> Ap_mean.
qr ))
473 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) >>
474 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) >>
475 Ap_cov_inv(2,2) >> Ap_cov_inv(2,5) >> Ap_cov_inv(2,4) >> Ap_cov_inv(2,3) >>
476 Ap_cov_inv(5,5) >> Ap_cov_inv(5,4) >> Ap_cov_inv(5,3) >>
477 Ap_cov_inv(4,4) >> Ap_cov_inv(4,3) >>
481 Ap_cov_inv.unit(6,1.0);
483 if (alreadyWarnedUnknowns.find(
"MISSING_3D")==alreadyWarnedUnknowns.end())
485 alreadyWarnedUnknowns.insert(
"MISSING_3D");
486 cerr <<
"[CNetworkOfPoses::loadFromTextFile] " << fil <<
":" << lineNum <<
": Warning: Information matrix missing, assuming unity.\n";
492 for (
size_t r=1;r<6;r++)
493 for (
size_t c=0;c<r;c++)
494 Ap_cov_inv(r,c) = Ap_cov_inv(c,r);
500 g->insertEdge(from_id, to_id, newEdge);
503 else if (
strCmpI(key,
"EQUIV") )
509 if (alreadyWarnedUnknowns.find(key)==alreadyWarnedUnknowns.end())
511 alreadyWarnedUnknowns.insert(key);
512 cerr <<
"[CNetworkOfPoses::loadFromTextFile] " << fil <<
":" << lineNum <<
": Warning: unknown entry type: " << key << endl;
534 typedef map<pair<TNodeID,TNodeID>, vector<TEdgeIterator> > TListAllEdges;
535 TListAllEdges lstAllEdges;
538 for (TEdgeIterator itEd=g->edges.begin();itEd!=g->edges.end();++itEd)
541 const pair<TNodeID,TNodeID> arc_id = make_pair( std::min(itEd->first.first,itEd->first.second),std::max(itEd->first.first,itEd->first.second) );
543 vector<TEdgeIterator> &lstEdges = lstAllEdges[arc_id];
545 lstEdges.push_back(itEd);
552 const size_t N = it->second.size();
553 for (
size_t i=1;i<N;i++)
554 g->edges.erase( it->second[i] );
556 if (N>=2) nRemoved+=N-1;
575 typedef typename graph_t::constraint_t constraint_t;
577 dijkstra_t dijkstra(*g, g->root);
581 typename dijkstra_t::tree_graph_t treeView;
582 dijkstra.getTreeGraph(treeView);
585 struct VisitorComputePoses :
public dijkstra_t::tree_graph_t::Visitor
589 VisitorComputePoses(graph_t *g) : m_g(g) { }
590 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 )
593 const TNodeID child_id = edge_to_child.id;
597 if ( (!edge_to_child.reverse && !m_g->edges_store_inverse_poses) ||
598 ( edge_to_child.reverse && m_g->edges_store_inverse_poses)
601 m_g->nodes[child_id].composeFrom( m_g->nodes[parent_id], edge_to_child.data->getPoseMean() );
605 m_g->nodes[child_id].composeFrom( m_g->nodes[parent_id], - edge_to_child.data->getPoseMean() );
612 g->nodes[g->root] =
typename constraint_t::type_value();
615 VisitorComputePoses myVisitor(g);
616 treeView.visitBreadthFirst(treeView.root, myVisitor);
684 bool ignoreCovariances )
689 const TNodeID from_id = itEdge->first.first;
690 const TNodeID to_id = itEdge->first.second;
695 ASSERTMSG_(itPoseFrom!=g->nodes.end(),
format(
"Node %u doesn't have a global pose in 'nodes'.", static_cast<unsigned int>(from_id)))
696 ASSERTMSG_(itPoseTo!=g->nodes.end(),
format(
"Node %u doesn't have a global pose in 'nodes'.", static_cast<unsigned int>(to_id)))
699 typedef typename graph_t::constraint_t constraint_t;
701 const typename constraint_t::type_value &from_mean = itPoseFrom->second;
702 const typename constraint_t::type_value &to_mean = itPoseTo->second;
705 const constraint_t &edge_delta_pose = itEdge->second;
706 const typename constraint_t::type_value &edge_delta_pose_mean = edge_delta_pose.getPoseMean();
708 if (ignoreCovariances)
712 from_plus_delta.composeFrom(from_mean, edge_delta_pose_mean);
715 return auxEuclid2Dist(from_plus_delta,to_mean);
721 constraint_t from_plus_delta = edge_delta_pose;
722 from_plus_delta.changeCoordinatesReference(from_mean);
730 err[i] = from_plus_delta.getPoseMean()[i] - to_mean[i];
733 return auxMaha2Dist(err,from_plus_delta);
#define ASSERT_EQUAL_(__A, __B)
A directed graph with the argument of the template specifying the type of the annotations in the edge...
double roll() const
Get the ROLL angle (in radians)
static double auxMaha2Dist(VEC &err, const CPosePDFGaussian &p)
size_t getCurrentLineNumber() const
Return the line number of the last line returned with getNextLine.
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
const double & phi() const
Get the phi angle of the 2D pose (in radians)
A template to obtain the type of its argument as a string at compile time.
bool getNextLine(std::string &out_str)
Reads from the file and return the next (non-comment) line, as a std::string.
void copyFrom(const CPosePDF &o)
Copy operator, translating if necesary (for example, between particles and gaussian representations) ...
double roll
Roll coordinate (rotation angle over X coordinate).
static double auxMaha2Dist(VEC &err, const mrpt::poses::CPose2D &p)
std::string BASE_IMPEXP format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
#define THROW_EXCEPTION(msg)
Abstract graph and tree data structures, plus generic graph algorithms.
mrpt::math::CMatrixDouble66 cov_inv
The inverse of the 6x6 covariance matrix.
This file implements miscelaneous matrix and matrix/vector operations, and internal functions in mrpt...
MAT_C::Scalar multiply_HCHt_scalar(const VECTOR_H &H, const MAT_C &C)
r (a scalar) = H * C * H^t (with a vector H and a symmetric matrix C)
static void write_EDGE_line(const TPairNodeIDs &edgeIDs, const CPose3DPDFGaussianInf &edge, std::ofstream &f)
const Scalar * const_iterator
double yaw
Yaw coordinate (rotation angle over Z axis).
static double auxMaha2Dist(VEC &err, const CPosePDFGaussianInf &p)
static void read_graph_of_poses_from_binary_file(graph_t *g, mrpt::utils::CStream &in)
static void write_EDGE_line(const TPairNodeIDs &edgeIDs, const CPose3DPDFGaussian &edge, std::ofstream &f)
static double auxEuclid2Dist(const mrpt::poses::CPose2D &p1, const mrpt::poses::CPose2D &p2)
static double auxEuclid2Dist(const mrpt::poses::CPose3D &p1, const mrpt::poses::CPose3D &p2)
mrpt::math::CMatrixDouble33 cov
The 3x3 covariance matrix.
static void graph_of_poses_dijkstra_init(graph_t *g)
A directed graph of pose constraints, with edges being the relative pose between pairs of nodes inden...
void rewind()
Reset the read pointer to the beginning of the file.
static void copyFrom2D(CPose2D &p, const CPosePDFGaussianInf &pdf)
double yaw() const
Get the YAW angle (in radians)
static void write_EDGE_line(const TPairNodeIDs &edgeIDs, const CPosePDFGaussian &edge, std::ofstream &f)
This base class is used to provide a unified interface to files,memory buffers,..Please see the deriv...
void wrapToPiInPlace(T &a)
Modifies the given angle to translate it into the ]-pi,pi] range.
A numeric matrix of compile-time fixed size.
This base provides a set of functions for maths stuff.
static void save_graph_of_poses_to_binary_file(const graph_t *g, mrpt::utils::CStream &out)
double x() const
Common members of all points & poses classes.
Declares a class that represents a Probability Density function (PDF) of a 2D pose ...
#define MRPT_UNUSED_PARAM(a)
Can be used to avoid "not used parameters" warnings from the compiler.
static void write_EDGE_line(const TPairNodeIDs &edgeIDs, const mrpt::poses::CPose3D &edge, std::ofstream &f)
static void copyFrom2D(POSE_PDF &p, const CPosePDFGaussianInf &pdf)
#define MRPT_THROW_UNKNOWN_SERIALIZATION_VERSION(__V)
For use in CSerializable implementations.
static void copyFrom2D(CPose3D &p, const CPosePDFGaussianInf &pdf)
double z
Translation in x,y,z.
bool BASE_IMPEXP strCmpI(const std::string &s1, const std::string &s2)
Return true if the two strings are equal (case insensitive)
static double auxMaha2Dist(VEC &err, const CPose3DPDFGaussian &p)
CPose3D mean
The mean value.
A class for parsing text files, returning each non-empty and non-comment line, along its line number...
double qz
Unit quaternion part, qr,qx,qy,qz.
T wrapToPi(T a)
Modifies the given angle to translate it into the ]-pi,pi] range.
class BASE_IMPEXP CPose3DQuat
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
double pitch
Pitch coordinate (rotation angle over Y axis).
Lightweight 3D pose (three spatial coordinates, plus a quaternion ).
static size_t graph_of_poses_collapse_dup_edges(graph_t *g)
static void save_graph_of_poses_to_text_file(const graph_t *g, const std::string &fil)
mrpt::math::CMatrixDouble66 cov
The 6x6 covariance matrix.
T square(const T x)
Inline function for the square of a number.
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
A Probability Density function (PDF) of a 2D pose as a Gaussian with a mean and the inverse of the c...
CPose2D mean
The mean value.
A class used to store a 2D pose.
uint64_t TNodeID
The type for node IDs in graphs of different types.
A class used to store a 3D pose (a 3D translation + a rotation in 3D).
This file implements matrix/vector text and binary serialization.
static double graph_edge_sqerror(const graph_t *g, const typename mrpt::graphs::CDirectedGraph< typename graph_t::constraint_t >::edges_map_t::const_iterator &itEdge, bool ignoreCovariances)
static void copyFrom3D(CPose3D &p, const CPose3DPDFGaussianInf &pdf)
Lightweight 3D pose (three spatial coordinates, plus three angular coordinates).
Declares a class that represents a Probability Density function (PDF) of a 3D pose as a Gaussian des...
double pitch() const
Get the PITCH angle (in radians)
A partial specialization of CArrayNumeric for double numbers.
Declares a class that represents a Probability Density function (PDF) of a 3D pose ...
static void load_graph_of_poses_from_text_file(graph_t *g, const std::string &fil)
void copyFrom(const CPose3DPDF &o)
Copy operator, translating if necesary (for example, between particles and gaussian representations) ...
global_poses_t nodes
The nodes (vertices) of the graph, with their estimated "global" (with respect to root) position...
static double auxMaha2Dist(VEC &err, const CPose3DPDFGaussianInf &p)
The Dijkstra algorithm for finding the shortest path between a given source node in a (weighted) dire...
static void copyFrom3D(CPose2D &p, const CPose3DPDFGaussianInf &pdf)
static void write_EDGE_line(const TPairNodeIDs &edgeIDs, const mrpt::poses::CPose2D &edge, std::ofstream &f)
static void copyFrom3D(POSE_PDF &p, const CPose3DPDFGaussianInf &pdf)
static void write_VERTEX_line(const TNodeID id, const mrpt::poses::CPose2D &p, std::ofstream &f)
#define ASSERTMSG_(f, __ERROR_MSG)
#define THROW_EXCEPTION_CUSTOM_MSG1(msg, param1)
double phi
Orientation (rads)
mrpt::math::CMatrixDouble33 cov_inv
The inverse of the 3x3 covariance matrix (the "information" matrix)
static void write_EDGE_line(const TPairNodeIDs &edgeIDs, const CPosePDFGaussianInf &edge, std::ofstream &f)
static void write_VERTEX_line(const TNodeID id, const mrpt::poses::CPose3D &p, std::ofstream &f)
std::pair< TNodeID, TNodeID > TPairNodeIDs
A pair of node IDs.
static double auxMaha2Dist(VEC &err, const mrpt::poses::CPose3D &p)