9 #ifndef CONSTRAINED_POSE_NETWORK_IMPL_H    10 #define CONSTRAINED_POSE_NETWORK_IMPL_H    58                         template <
class graph_t>
    64                                         f << 
"VERTEX2 " << 
id << 
" " << 
p.x() << 
" " << 
p.y() << 
" " << 
p.phi();
    70                                         f << 
"VERTEX3 " << 
id << 
" " << 
p.x() << 
" " << 
p.y() << 
" " << 
p.z()<< 
" " << 
p.roll()<< 
" " << 
p.pitch()<< 
" " << 
p.yaw();
    78                                         f << 
"EDGE2 " << edgeIDs.first << 
" " << edgeIDs.second << 
" " <<
    88                                         f << 
"EDGE3 " << edgeIDs.first << 
" " << edgeIDs.second << 
" " <<
   102                                         write_EDGE_line(edgeIDs,
p,f);
   108                                         write_EDGE_line(edgeIDs,
p,f);
   114                                         p.cov_inv.unit(3,1.0);
   115                                         write_EDGE_line(edgeIDs,
p,f);
   121                                         p.cov_inv.unit(6,1.0);
   122                                         write_EDGE_line(edgeIDs,
p,f);
   138                                                         itNod = 
g->nodes.begin();
   139                                                         itNod!=
g->nodes.end();
   141                                                 write_VERTEX_line(itNod->first, itNod->second, f);
   144                                                 f << 
" | " << itNod->second.retAnnotsAsString() << endl;
   150                                                 if (it->first.first!=it->first.second)  
   151                                                         write_EDGE_line(it->first, it->second, f);
   167                                         out << 
g->nodes << 
g->edges << 
g->root;
   178                                         in >> sStoredClassName;
   183                                         in >> stored_version;
   186                                         switch (stored_version)
   189                                                 in >> 
g->nodes >> 
g->edges >> 
g->root;
   204                                         typedef typename graph_t::constraint_t CPOSE;
   206                                         set<string>  alreadyWarnedUnknowns; 
   213                                         const bool graph_is_3D = CPOSE::is_3D();
   222                                         map<TNodeID,TNodeID> lstEquivs; 
   229                                                 const string lin = 
s.str();
   232                                                 if (!(
s >> key) || key.empty())
   239                                                         if (!(
s>> id1 >> id2))
   241                                                         lstEquivs[std::max(id1,id2)] = 
std::min(id1,id2);
   254                                                 const string lin = 
s.str();
   267                                                 if (!(
s >> key) || key.empty())
   274                                                         if (!(
s>> 
id >> p2D.
x >> p2D.
y >> p2D.
phi))
   278                                                         if (
g->nodes.find(
id)!=
g->nodes.end())
   279                                                                 THROW_EXCEPTION(
format(
"Line %u: Error, duplicated verted ID %u in line: '%s'", lineNum, static_cast<unsigned int>(
id), lin.c_str()));
   284                                                                 if (itEq!=lstEquivs.end()) 
id = itEq->second;
   288                                                         if (
g->nodes.find(
id)==
g->nodes.end())
   292                                                                 newNode = pose_t(
CPose2D(p2D)); 
   295                                                 else if (
strCmpI(key,
"VERTEX3"))
   304                                                         if (!(
s>> 
id >> p3D.
x >> p3D.
y >> p3D.
z >> p3D.
roll >> p3D.
pitch >> p3D.
yaw))
   308                                                         if (
g->nodes.find(
id)!=
g->nodes.end())
   309                                                                 THROW_EXCEPTION(
format(
"Line %u: Error, duplicated verted ID %u in line: '%s'", lineNum, static_cast<unsigned int>(
id), lin.c_str()));
   314                                                                 if (itEq!=lstEquivs.end()) 
id = itEq->second;
   318                                                         if (
g->nodes.find(
id)==
g->nodes.end())
   323                                                 else if (
strCmpI(key,
"VERTEX_SE3:QUAT"))
   326                                                                 THROW_EXCEPTION(
format(
"Line %u: Try to load VERTEX_SE3:QUAT into a 2D graph: '%s'", lineNum, lin.c_str()));
   331                                                         if (!(
s>> 
id >> p3D.
x >> p3D.
y >> p3D.
z >> p3D.
qx >> p3D.
qy >> p3D.
qz >> p3D.
qr))
   335                                                         if (
g->nodes.find(
id)!=
g->nodes.end())
   336                                                                 THROW_EXCEPTION(
format(
"Line %u: Error, duplicated verted ID %u in line: '%s'", lineNum, static_cast<unsigned int>(
id), lin.c_str()));
   341                                                                 if (itEq!=lstEquivs.end()) 
id = itEq->second;
   345                                                         if (
g->nodes.find(
id)==
g->nodes.end())
   360                                                         if (!(
s>> from_id >> to_id))
   366                                                                 if (itEq!=lstEquivs.end()) to_id = itEq->second;
   370                                                                 if (itEq!=lstEquivs.end()) from_id = itEq->second;
   378                                                                                 Ap_mean.
x >> Ap_mean.
y >> Ap_mean.
phi >>
   379                                                                                 Ap_cov_inv(0,0) >> Ap_cov_inv(0,1) >> Ap_cov_inv(1,1) >>
   380                                                                                 Ap_cov_inv(2,2) >> Ap_cov_inv(0,2) >> Ap_cov_inv(1,2)))
   384                                                                 Ap_cov_inv(1,0) = Ap_cov_inv(0,1);
   385                                                                 Ap_cov_inv(2,0) = Ap_cov_inv(0,2);
   386                                                                 Ap_cov_inv(2,1) = Ap_cov_inv(1,2);
   391                                                                 g->insertEdge(from_id, to_id, newEdge);
   401                                                         if (!(
s>> from_id >> to_id))
   407                                                                 if (itEq!=lstEquivs.end()) to_id = itEq->second;
   411                                                                 if (itEq!=lstEquivs.end()) from_id = itEq->second;
   419                                                                 if (!(
s>> Ap_mean.
x >> Ap_mean.
y >> Ap_mean.
z >> Ap_mean.
roll >> Ap_mean.
pitch >> Ap_mean.
yaw))
   424                                                                                 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) >>
   425                                                                                 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) >>
   426                                                                                 Ap_cov_inv(2,2) >> Ap_cov_inv(2,5) >> Ap_cov_inv(2,4) >> Ap_cov_inv(2,3) >>
   427                                                                                 Ap_cov_inv(5,5) >> Ap_cov_inv(5,4) >> Ap_cov_inv(5,3) >>
   428                                                                                 Ap_cov_inv(4,4) >> Ap_cov_inv(4,3) >>
   432                                                                         Ap_cov_inv.unit(6,1.0);
   434                                                                         if (alreadyWarnedUnknowns.find(
"MISSING_3D")==alreadyWarnedUnknowns.end())
   436                                                                                 alreadyWarnedUnknowns.insert(
"MISSING_3D");
   437                                                                                 cerr << 
"[CNetworkOfPoses::loadFromTextFile] " << fil << 
":" << lineNum << 
": Warning: Information matrix missing, assuming unity.\n";
   443                                                                         for (
size_t r=1;
r<6;
r++)
   444                                                                                 for (
size_t c=0;
c<
r;
c++)
   445                                                                                         Ap_cov_inv(
r,
c) = Ap_cov_inv(
c,
r);
   451                                                                 g->insertEdge(from_id, to_id, newEdge);
   454                                                 else if (
strCmpI(key,
"EDGE_SE3:QUAT"))
   462                                                         if (!(
s>> from_id >> to_id))
   468                                                                 if (itEq!=lstEquivs.end()) to_id = itEq->second;
   472                                                                 if (itEq!=lstEquivs.end()) from_id = itEq->second;
   479                                                                 if (!(
s>> Ap_mean.
x >> Ap_mean.
y >> Ap_mean.
z >> Ap_mean.
qx >> Ap_mean.
qy >> Ap_mean.
qz >> Ap_mean.
qr))
   484                                                                                 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) >>
   485                                                                                 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) >>
   486                                                                                 Ap_cov_inv(2,2) >> Ap_cov_inv(2,5) >> Ap_cov_inv(2,4) >> Ap_cov_inv(2,3) >>
   487                                                                                 Ap_cov_inv(5,5) >> Ap_cov_inv(5,4) >> Ap_cov_inv(5,3) >>
   488                                                                                 Ap_cov_inv(4,4) >> Ap_cov_inv(4,3) >>
   492                                                                         Ap_cov_inv.unit(6,1.0);
   494                                                                         if (alreadyWarnedUnknowns.find(
"MISSING_3D")==alreadyWarnedUnknowns.end())
   496                                                                                 alreadyWarnedUnknowns.insert(
"MISSING_3D");
   497                                                                                 cerr << 
"[CNetworkOfPoses::loadFromTextFile] " << fil << 
":" << lineNum << 
": Warning: Information matrix missing, assuming unity.\n";
   503                                                                         for (
size_t r=1;
r<6;
r++)
   504                                                                                 for (
size_t c=0;
c<
r;
c++)
   505                                                                                         Ap_cov_inv(
r,
c) = Ap_cov_inv(
c,
r);
   511                                                                 g->insertEdge(from_id, to_id, newEdge);
   520                                                         if (alreadyWarnedUnknowns.find(key)==alreadyWarnedUnknowns.end())
   522                                                                 alreadyWarnedUnknowns.insert(key);
   523                                                                 cerr << 
"[CNetworkOfPoses::loadFromTextFile] " << fil << 
":" << lineNum << 
": Warning: unknown entry type: " << key << endl;
   545                                         typedef map<pair<TNodeID,TNodeID>, vector<TEdgeIterator> > TListAllEdges; 
   546                                         TListAllEdges lstAllEdges;
   549                                         for (TEdgeIterator itEd=
g->edges.begin();itEd!=
g->edges.end();++itEd)
   552                                                 const pair<TNodeID,TNodeID> arc_id = make_pair(
std::min(itEd->first.first,itEd->first.second),std::max(itEd->first.first,itEd->first.second));
   554                                                 vector<TEdgeIterator> &lstEdges = lstAllEdges[arc_id];
   556                                                 lstEdges.push_back(itEd);
   563                                                 const size_t N = it->second.size();
   564                                                 for (
size_t i=1;i<N;i++)  
   565                                                         g->edges.erase(it->second[i]);
   567                                                 if (N>=2) nRemoved+=N-1;
   587                                         typedef typename graph_t::constraint_t  constraint_t;
   590                                         dijkstra_t dijkstra(*
g, 
g->root);
   594                                         typename dijkstra_t::tree_graph_t  treeView;
   595                                         dijkstra.getTreeGraph(treeView);
   598                                         struct VisitorComputePoses : 
public dijkstra_t::tree_graph_t::Visitor
   602                                                 VisitorComputePoses(graph_t *
g) : m_g(
g) { }
   603                                                 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) 
MRPT_OVERRIDE   606                                                         const TNodeID  child_id = edge_to_child.id;
   611                                                         if ((!edge_to_child.reverse && !m_g->edges_store_inverse_poses) ||
   612                                                                  (edge_to_child.reverse &&  m_g->edges_store_inverse_poses)
   615                                                                 m_g->nodes[child_id].composeFrom(m_g->nodes[parent_id],  edge_to_child.data->getPoseMean());
   619                                                                 m_g->nodes[child_id].composeFrom(m_g->nodes[parent_id], - edge_to_child.data->getPoseMean());
   628                                         bool empty_node_annots = 
g->nodes.begin()->second.is_node_annots_empty;
   629                                         map<const TNodeID, TNodeAnnotations*> nodeID_to_annots;
   630                                         if (!empty_node_annots) {
   632                                                                 poses_cit = 
g->nodes.begin();
   633                                                                 poses_cit != 
g->nodes.end();
   636                                                         nodeID_to_annots.insert(
   638                                                                                 poses_cit->first, poses_cit->second.getCopyOfAnnots()));
   643                                         g->nodes[
g->root] = 
typename constraint_t::type_value(); 
   646                                         VisitorComputePoses  myVisitor(
g);
   647                                         treeView.visitBreadthFirst(treeView.root, myVisitor);
   650                                         if (!empty_node_annots) {
   652                                                                 poses_cit = 
g->nodes.begin();
   653                                                                 poses_cit != 
g->nodes.end();
   657                                                         bool res = poses_cit->second.setAnnots(*node_annots);
   665                                                                                 "Setting annotations for nodeID \"%lu\" was unsuccessful",
   666                                                                                 static_cast<unsigned long>(poses_cit->first)));
   736                                         bool ignoreCovariances)
   741                                         const TNodeID from_id = itEdge->first.first;
   742                                         const TNodeID to_id   = itEdge->first.second;
   747                                         ASSERTMSG_(itPoseFrom!=
g->nodes.end(), 
format(
"Node %u doesn't have a global pose in 'nodes'.", static_cast<unsigned int>(from_id)))
   748                                         ASSERTMSG_(itPoseTo!=
g->nodes.end(), 
format(
"Node %u doesn't have a global pose in 'nodes'.", static_cast<unsigned int>(to_id)))
   751                                         typedef typename graph_t::constraint_t constraint_t;
   753                                         const typename constraint_t::type_value &from_mean = itPoseFrom->second;
   754                                         const typename constraint_t::type_value &to_mean   = itPoseTo->second;
   757                                         const constraint_t &edge_delta_pose = itEdge->second;
   758                                         const typename constraint_t::type_value &edge_delta_pose_mean = edge_delta_pose.getPoseMean();
   760                                         if (ignoreCovariances)
   764                                                 from_plus_delta.composeFrom(from_mean, edge_delta_pose_mean);
   767                                                 return auxEuclid2Dist(from_plus_delta,to_mean);
   773                                                 constraint_t from_plus_delta = edge_delta_pose;
   774                                                 from_plus_delta.changeCoordinatesReference(from_mean);
   782                                                         err[i] = from_plus_delta.getPoseMean()[i] - to_mean[i];
   785                                                 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...
static double auxMaha2Dist(VEC &err, const CPosePDFGaussian &p)
double x() const
Common members of all points & poses classes. 
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL. 
A template to obtain the type of its argument as a string at compile time. 
Abstract class from which NodeAnnotations related classes can be implemented. 
#define MRPT_OVERRIDE
C++11 "override" for virtuals: 
bool getNextLine(std::string &out_str)
Reads from the file and return the next (non-comment) line, as a std::string. 
double roll
Roll coordinate (rotation angle over X coordinate). 
static double auxMaha2Dist(VEC &err, const mrpt::poses::CPose2D &p)
#define THROW_EXCEPTION(msg)
Abstract graph and tree data structures, plus generic graph algorithms. 
#define THROW_EXCEPTION_FMT(_FORMAT_STRING,...)
mrpt::math::CMatrixDouble66 cov_inv
The inverse of the 6x6 covariance matrix. 
double pitch() const
Get the PITCH angle (in radians) 
double yaw() const
Get the YAW angle (in radians) 
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)
static void graph_of_poses_dijkstra_init(graph_t *g)
T square(const T x)
Inline function for the square of a number. 
A directed graph of pose constraints, with edges being the relative poses between pairs of nodes iden...
void rewind()
Reset the read pointer to the beginning of the file. 
static void copyFrom2D(CPose2D &p, const CPosePDFGaussianInf &pdf)
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. 
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)
Declares a class that represents a Probability Density function (PDF) of a 2D pose ...
uint64_t TNodeID
The type for node IDs in graphs of different types. 
#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. 
std::string BASE_IMPEXP format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf. 
std::pair< TNodeID, TNodeID > TPairNodeIDs
A pair of node IDs. 
static double auxMaha2Dist(VEC &err, const CPose3DPDFGaussian &p)
CPose3D mean
The mean value. 
A class used to store a 3D pose as a translation (x,y,z) and a quaternion (qr,qx,qy,qz). 
A class for parsing text files, returning each non-empty and non-comment line, along its line number...
std::string BASE_IMPEXP format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf. 
double qz
Unit quaternion part, qr,qx,qy,qz. 
GLsizei const GLchar ** string
T wrapToPi(T a)
Modifies the given angle to translate it into the ]-pi,pi] range. 
Classes for 2D/3D geometry representation, both of single values and probability density distribution...
double roll() const
Get the ROLL angle (in radians) 
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)
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...
GLdouble GLdouble GLdouble r
CPose2D mean
The mean value. 
A class used to store a 2D pose, including the 2D coordinate point and a heading (phi) angle...
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)
const double & phi() const
Get the phi angle of the 2D pose (in radians) 
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...
A partial specialization of CArrayNumeric for double numbers. 
Declares a class that represents a Probability Density function (PDF) of a 3D pose ...
size_t getCurrentLineNumber() const
Return the line number of the last line returned with getNextLine. 
static void load_graph_of_poses_from_text_file(graph_t *g, const std::string &fil)
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)
bool BASE_IMPEXP strCmpI(const std::string &s1, const std::string &s2)
Return true if the two strings are equal (case insensitive) 
unsigned __int32 uint32_t
static void write_VERTEX_line(const TNodeID id, const mrpt::poses::CPose2D &p, std::ofstream &f)
#define ASSERTMSG_(f, __ERROR_MSG)
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)
static double auxMaha2Dist(VEC &err, const mrpt::poses::CPose3D &p)