Main MRPT website > C++ reference
MRPT logo
CPointsMap.h
Go to the documentation of this file.
00001 /* +---------------------------------------------------------------------------+
00002    |          The Mobile Robot Programming Toolkit (MRPT) C++ library          |
00003    |                                                                           |
00004    |                       http://www.mrpt.org/                                |
00005    |                                                                           |
00006    |   Copyright (C) 2005-2011  University of Malaga                           |
00007    |                                                                           |
00008    |    This software was written by the Machine Perception and Intelligent    |
00009    |      Robotics Lab, University of Malaga (Spain).                          |
00010    |    Contact: Jose-Luis Blanco  <jlblanco@ctima.uma.es>                     |
00011    |                                                                           |
00012    |  This file is part of the MRPT project.                                   |
00013    |                                                                           |
00014    |     MRPT is free software: you can redistribute it and/or modify          |
00015    |     it under the terms of the GNU General Public License as published by  |
00016    |     the Free Software Foundation, either version 3 of the License, or     |
00017    |     (at your option) any later version.                                   |
00018    |                                                                           |
00019    |   MRPT is distributed in the hope that it will be useful,                 |
00020    |     but WITHOUT ANY WARRANTY; without even the implied warranty of        |
00021    |     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         |
00022    |     GNU General Public License for more details.                          |
00023    |                                                                           |
00024    |     You should have received a copy of the GNU General Public License     |
00025    |     along with MRPT.  If not, see <http://www.gnu.org/licenses/>.         |
00026    |                                                                           |
00027    +---------------------------------------------------------------------------+ */
00028 #ifndef CPOINTSMAP_H
00029 #define CPOINTSMAP_H
00030 
00031 #include <mrpt/slam/CMetricMap.h>
00032 #include <mrpt/utils/CSerializable.h>
00033 #include <mrpt/math/CMatrix.h>
00034 #include <mrpt/utils/CLoadableOptions.h>
00035 #include <mrpt/utils/safe_pointers.h>
00036 #include <mrpt/math/KDTreeCapable.h>
00037 #include <mrpt/slam/CSinCosLookUpTableFor2DScans.h>
00038 #include <mrpt/poses/CPoint2D.h>
00039 #include <mrpt/math/lightweight_geom_data.h>
00040 #include <mrpt/utils/PLY_import_export.h>
00041 
00042 #include <mrpt/maps/link_pragmas.h>
00043 
00044 namespace mrpt
00045 {
00046 /** \ingroup mrpt_maps_grp */
00047 namespace slam
00048 {
00049         // Fordward declarations:
00050         class CSimplePointsMap;
00051         class CObservation2DRangeScan;
00052         class CObservation3DRangeScan;
00053 
00054         using namespace mrpt::poses;
00055         using namespace mrpt::math;
00056 
00057         DEFINE_SERIALIZABLE_PRE_CUSTOM_BASE_LINKAGE( CPointsMap , CMetricMap, MAPS_IMPEXP )
00058 
00059         // Forward decls. needed to make its static methods friends of CPointsMap
00060         namespace detail {
00061                 template <class Derived> struct loadFromRangeImpl;
00062                 template <class Derived> struct pointmap_traits;
00063         }
00064 
00065 
00066         /** A cloud of points in 2D or 3D, which can be built from a sequence of laser scans or other sensors.
00067          *  This is a virtual class, thus only a derived class can be instantiated by the user. The user most usually wants to use CSimplePointsMap.
00068          *
00069          *  This class implements generic version of mrpt::slam::CMetric::insertObservation() accepting these types of sensory data:
00070          *              - mrpt::slam::CObservation2DRangeScan: 2D range scans
00071          *              - mrpt::slam::CObservation3DRangeScan: 3D range scans (Kinect, etc...)
00072          *              - mrpt::slam::CObservationRange: IRs, Sonars, etc.
00073          *
00074          * \sa CMetricMap, CPoint, mrpt::utils::CSerializable
00075           * \ingroup mrpt_maps_grp
00076          */
00077         class MAPS_IMPEXP CPointsMap :
00078                 public CMetricMap,
00079                 public mrpt::utils::KDTreeCapable<CPointsMap>,
00080                 public mrpt::utils::PLY_Importer,
00081                 public mrpt::utils::PLY_Exporter
00082         {
00083                 // This must be added to any CSerializable derived class:
00084                 DEFINE_VIRTUAL_SERIALIZABLE( CPointsMap )
00085 
00086         protected:
00087                 /** Helper struct used for \a internal_loadFromRangeScan2D_prepareOneRange() */
00088                 struct MAPS_IMPEXP TLaserRange2DInsertContext {
00089                         TLaserRange2DInsertContext(const CObservation2DRangeScan  &_rangeScan) : HM(UNINITIALIZED_MATRIX), rangeScan(_rangeScan)
00090                         { }
00091                         CMatrixDouble44 HM;  //!< Homog matrix of the local sensor pose within the robot
00092                         const CObservation2DRangeScan  &rangeScan;
00093                         std::vector<float>         fVars;  //!< Extra variables to be used as desired by the derived class.
00094                         std::vector<unsigned int>  uVars;
00095                         std::vector<uint8_t>       bVars;
00096                 };
00097 
00098                 /** Helper struct used for \a internal_loadFromRangeScan3D_prepareOneRange() */
00099                 struct MAPS_IMPEXP TLaserRange3DInsertContext {
00100                         TLaserRange3DInsertContext(const CObservation3DRangeScan  &_rangeScan) : HM(UNINITIALIZED_MATRIX), rangeScan(_rangeScan)
00101                         { }
00102                         CMatrixDouble44 HM;  //!< Homog matrix of the local sensor pose within the robot
00103                         const CObservation3DRangeScan  &rangeScan;
00104                         float scan_x, scan_y,scan_z; //!< In \a internal_loadFromRangeScan3D_prepareOneRange, these are the local coordinates of the scan points being inserted right now.
00105                         std::vector<float>         fVars;  //!< Extra variables to be used as desired by the derived class.
00106                         std::vector<unsigned int>  uVars;
00107                         std::vector<uint8_t>       bVars;
00108                 };
00109 
00110          public:
00111                  CPointsMap();            //!< Ctor
00112                  virtual ~CPointsMap();   //!< Virtual destructor.
00113 
00114 
00115                 // --------------------------------------------
00116                 /** @name Pure virtual interfaces to be implemented by any class derived from CPointsMap
00117                     @{ */
00118 
00119                 /** Reserves memory for a given number of points: the size of the map does not change, it only reserves the memory.
00120                   *  This is useful for situations where it is approximately known the final size of the map. This method is more
00121                   *  efficient than constantly increasing the size of the buffers. Refer to the STL C++ library's "reserve" methods.
00122                   */
00123                 virtual void reserve(size_t newLength) = 0;
00124 
00125                 /** Resizes all point buffers so they can hold the given number of points: newly created points are set to default values,
00126                   *  and old contents are not changed.
00127                   * \sa reserve, setPoint, setPointFast, setSize
00128                   */
00129                 virtual void resize(size_t newLength) = 0;
00130 
00131                 /** Resizes all point buffers so they can hold the given number of points, *erasing* all previous contents
00132                   *  and leaving all points to default values.
00133                   * \sa reserve, setPoint, setPointFast, setSize
00134                   */
00135                 virtual void setSize(size_t newLength) = 0;
00136 
00137                 /** Changes the coordinates of the given point (0-based index), *without* checking for out-of-bounds and *without* calling mark_as_modified()  \sa setPoint */
00138                 virtual void  setPointFast(size_t index,float x, float y, float z)=0;
00139 
00140                 /** The virtual method for \a insertPoint() *without* calling mark_as_modified()   */
00141                 virtual void  insertPointFast( float x, float y, float z = 0 ) = 0;
00142 
00143                  /** Virtual assignment operator, copies as much common data (XYZ, color,...) as possible from the source map into this one. */
00144                  virtual void  copyFrom(const CPointsMap &obj) = 0;
00145 
00146                 /** Get all the data fields for one point as a vector: depending on the implementation class this can be [X Y Z] or [X Y Z R G B], etc...
00147                   *  Unlike getPointAllFields(), this method does not check for index out of bounds
00148                   * \sa getPointAllFields, setPointAllFields, setPointAllFieldsFast
00149                   */
00150                 virtual void  getPointAllFieldsFast( const size_t index, std::vector<float> & point_data ) const = 0;
00151 
00152                 /** Set all the data fields for one point as a vector: depending on the implementation class this can be [X Y Z] or [X Y Z R G B], etc...
00153                   *  Unlike setPointAllFields(), this method does not check for index out of bounds
00154                   * \sa setPointAllFields, getPointAllFields, getPointAllFieldsFast
00155                   */
00156                 virtual void  setPointAllFieldsFast( const size_t index, const std::vector<float> & point_data ) = 0;
00157 
00158         protected:
00159 
00160                 /** Auxiliary method called from within \a addFrom() automatically, to finish the copying of class-specific data  */
00161                 virtual void  addFrom_classSpecific(const CPointsMap &anotherMap, const size_t nPreviousPoints) = 0;
00162 
00163         public:
00164 
00165                 /** @} */
00166                 // --------------------------------------------
00167 
00168 
00169                 /** Returns the square distance from the 2D point (x0,y0) to the closest correspondence in the map.
00170                   */
00171                 virtual float squareDistanceToClosestCorrespondence(
00172                         float   x0,
00173                         float   y0 ) const;
00174 
00175                 inline float squareDistanceToClosestCorrespondenceT(const TPoint2D &p0) const   {
00176                         return squareDistanceToClosestCorrespondence(static_cast<float>(p0.x),static_cast<float>(p0.y));
00177                 }
00178 
00179 
00180                  /** With this struct options are provided to the observation insertion process.
00181                   * \sa CObservation::insertIntoPointsMap
00182                   */
00183                  struct MAPS_IMPEXP TInsertionOptions : public utils::CLoadableOptions
00184                  {
00185                         /** Initilization of default parameters */
00186                         TInsertionOptions( );
00187                         /** See utils::CLoadableOptions */
00188                         void  loadFromConfigFile(const mrpt::utils::CConfigFileBase  &source,const std::string &section);
00189                         /** See utils::CLoadableOptions */
00190                         void  dumpToTextStream(CStream  &out) const;
00191 
00192                         float   minDistBetweenLaserPoints;   //!< The minimum distance between points (in 3D): If two points are too close, one of them is not inserted into the map. Default is 0.02 meters.
00193                         bool    addToExistingPointsMap;      //!< Applicable to "loadFromRangeScan" only! If set to false, the points from the scan are loaded, clearing all previous content. Default is false.
00194                         bool    also_interpolate;            //!< If set to true, far points (<1m) are interpolated with samples at "minDistSqrBetweenLaserPoints" intervals (Default is false).
00195                         bool    disableDeletion;             //!< If set to false (default=true) points in the same plane as the inserted scan and inside the free space, are erased: i.e. they don't exist yet.
00196                         bool    fuseWithExisting;            //!< If set to true (default=false), inserted points are "fused" with previously existent ones. This shrink the size of the points map, but its slower.
00197                         bool    isPlanarMap;                 //!< If set to true, only HORIZONTAL (in the XY plane) measurements will be inserted in the map (Default value is false, thus 3D maps are generated). \sa  horizontalTolerance
00198                         float   horizontalTolerance;         //!< The tolerance in rads in pitch & roll for a laser scan to be considered horizontal, considered only when isPlanarMap=true (default=0).
00199                         float   maxDistForInterpolatePoints; //!< The maximum distance between two points to interpolate between them (ONLY when also_interpolate=true)
00200 
00201                  };
00202 
00203                 TInsertionOptions insertionOptions; //!< The options used when inserting observations in the map
00204 
00205                  /** Options used when evaluating "computeObservationLikelihood" in the derived classes.
00206                   * \sa CObservation::computeObservationLikelihood
00207                   */
00208                  struct MAPS_IMPEXP TLikelihoodOptions: public utils::CLoadableOptions
00209                  {
00210                         /** Initilization of default parameters
00211                          */
00212                         TLikelihoodOptions( );
00213                         virtual ~TLikelihoodOptions() {}
00214 
00215                         /** See utils::CLoadableOptions */
00216                         void  loadFromConfigFile(
00217                                 const mrpt::utils::CConfigFileBase  &source,
00218                                 const std::string &section);
00219 
00220                         /** See utils::CLoadableOptions */
00221                         void  dumpToTextStream(CStream  &out) const;
00222 
00223                         void writeToStream(CStream &out) const;         //!< Binary dump to stream - for usage in derived classes' serialization
00224                         void readFromStream(CStream &in);                       //!< Binary dump to stream - for usage in derived classes' serialization
00225 
00226                         double          sigma_dist; //!< Sigma (standard deviation, in meters) of the exponential used to model the likelihood (default= 0.5meters)
00227                         double          max_corr_distance; //!< Maximum distance in meters to consider for the numerator divided by "sigma_dist", so that each point has a minimum (but very small) likelihood to avoid underflows (default=1.0 meters)
00228                         uint32_t        decimation; //!< Speed up the likelihood computation by considering only one out of N rays (default=10)
00229                  };
00230 
00231                  TLikelihoodOptions  likelihoodOptions;
00232 
00233 
00234                 /** Adds all the points from \a anotherMap to this map, without fusing.
00235                   *  This operation can be also invoked via the "+=" operator, for example:
00236                   *  \code
00237                   *   CSimplePointsMap m1, m2;
00238                   *   ...
00239                   *   m1.addFrom( m2 );  // Add all points of m2 to m1
00240                   *   m1 += m2;          // Exactly the same than above
00241                   *  \endcode
00242                   * \note The method in CPointsMap is generic but derived classes may redefine this virtual method to another one more optimized.
00243                   */
00244                 virtual void  addFrom(const CPointsMap &anotherMap);
00245 
00246                 /** This operator is synonymous with \a addFrom. \sa addFrom */
00247                 inline void operator +=(const CPointsMap &anotherMap)
00248                 {
00249                         this->addFrom(anotherMap);
00250                 }
00251 
00252                 /** Insert the contents of another map into this one with some geometric transformation, without fusing close points.
00253                  * \param otherMap The other map whose points are to be inserted into this one.
00254                  * \param otherPose The pose of the other map in the coordinates of THIS map
00255                  * \sa fuseWith, addFrom
00256                  */
00257                 void  insertAnotherMap(
00258                         const CPointsMap        *otherMap,
00259                         const CPose3D           &otherPose);
00260 
00261                 // --------------------------------------------------
00262                 /** @name File input/output methods
00263                     @{ */
00264 
00265                 /** Load from a text file. Each line should contain an "X Y" coordinate pair, separated by whitespaces.
00266                  *   Returns false if any error occured, true elsewere.
00267                  */
00268                 inline bool  load2D_from_text_file(const std::string &file) { return load2Dor3D_from_text_file(file,false); }
00269 
00270                 /** Load from a text file. Each line should contain an "X Y Z" coordinate tuple, separated by whitespaces.
00271                  *   Returns false if any error occured, true elsewere.
00272                  */
00273                 inline bool  load3D_from_text_file(const std::string &file) { return load2Dor3D_from_text_file(file,true); }
00274 
00275                 /** 2D or 3D generic implementation of \a load2D_from_text_file and load3D_from_text_file */
00276                 bool  load2Dor3D_from_text_file(const std::string &file, const bool is_3D);
00277 
00278                 /**  Save to a text file. Each line will contain "X Y" point coordinates.
00279                  *              Returns false if any error occured, true elsewere.
00280                  */
00281                 bool  save2D_to_text_file(const std::string &file) const;
00282 
00283                 /**  Save to a text file. Each line will contain "X Y Z" point coordinates.
00284                  *     Returns false if any error occured, true elsewere.
00285                  */
00286                 bool  save3D_to_text_file(const std::string &file)const;
00287 
00288                 /** This virtual method saves the map to a file "filNamePrefix"+< some_file_extension >, as an image or in any other applicable way (Notice that other methods to save the map may be implemented in classes implementing this virtual interface).
00289                   */
00290                 void  saveMetricMapRepresentationToFile(
00291                         const std::string       &filNamePrefix
00292                         )const
00293                 {
00294                         std::string             fil( filNamePrefix + std::string(".txt") );
00295                         save3D_to_text_file( fil );
00296                 }
00297 
00298         /** Save the point cloud as a PCL PCD file, in either ASCII or binary format (requires MRPT built against PCL) \return false on any error */
00299         virtual bool savePCDFile(const std::string &filename, bool save_as_binary) const;
00300 
00301                 /** @} */ // End of: File input/output methods
00302                 // --------------------------------------------------
00303 
00304                 /** Returns the number of stored points in the map.
00305                  */
00306                 inline size_t size() const { return x.size(); }
00307 
00308                 /** Returns the number of stored points in the map (DEPRECATED, use "size()" instead better)
00309                  */
00310                 inline size_t getPointsCount() const { return size(); }
00311 
00312                 /** Access to a given point from map, as a 2D point. First index is 0.
00313                  * \return The return value is the weight of the point (the times it has been fused), or 1 if weights are not used.
00314                  * \exception Throws std::exception on index out of bound.
00315                  * \sa setPoint, getPointFast
00316                  */
00317                 unsigned long  getPoint(size_t index,float &x,float &y,float &z) const;
00318                 /// \overload
00319                 unsigned long  getPoint(size_t index,float &x,float &y) const;
00320                 /// \overload
00321                 unsigned long  getPoint(size_t index,double &x,double &y,double &z) const;
00322                 /// \overload
00323                 unsigned long  getPoint(size_t index,double &x,double &y) const;
00324                 /// \overload
00325                 inline unsigned long  getPoint(size_t index,CPoint2D &p) const { return getPoint(index,p.x(),p.y()); }
00326                 /// \overload
00327                 inline unsigned long  getPoint(size_t index,CPoint3D &p) const  { return getPoint(index,p.x(),p.y(),p.z()); }
00328                 /// \overload
00329                 inline unsigned long  getPoint(size_t index,mrpt::math::TPoint2D &p) const  { return getPoint(index,p.x,p.y); }
00330                 /// \overload
00331                 inline unsigned long  getPoint(size_t index,mrpt::math::TPoint3D &p) const  { return getPoint(index,p.x,p.y,p.z); }
00332 
00333                 /** Access to a given point from map, and its colors, if the map defines them (othersise, R=G=B=1.0). First index is 0.
00334                  * \return The return value is the weight of the point (the times it has been fused)
00335                  * \exception Throws std::exception on index out of bound.
00336                  */
00337                 virtual void getPoint( size_t index, float &x, float &y, float &z, float &R, float &G, float &B ) const
00338                 {
00339                         getPoint(index,x,y,z);
00340                         R=G=B=1;
00341                 }
00342 
00343                 /** Just like \a getPoint() but without checking out-of-bound index and without returning the point weight, just XYZ.
00344                  */
00345                 inline void getPointFast(size_t index,float &x,float &y,float &z) const { x=this->x[index]; y=this->y[index]; z=this->z[index]; }
00346 
00347                 /** Returns true if the point map has a color field for each point */
00348                 virtual bool hasColorPoints() const { return false; }
00349 
00350                 /** Changes a given point from map, with Z defaulting to 0 if not provided.
00351                  * \exception Throws std::exception on index out of bound.
00352                  */
00353                 inline void  setPoint(size_t index,float x, float y, float z) {
00354                         ASSERT_BELOW_(index,this->size())
00355                         setPointFast(index,x,y,z);
00356                         mark_as_modified();
00357                 }
00358                 /// \overload
00359                 inline void  setPoint(size_t index,CPoint2D &p) {  setPoint(index,p.x(),p.y(),0); }
00360                 /// \overload
00361                 inline void  setPoint(size_t index,CPoint3D &p)  { setPoint(index,p.x(),p.y(),p.z()); }
00362                 /// \overload
00363                 inline void  setPoint(size_t index,float x, float y) { setPoint(index,x,y,0); }
00364                 /// \overload (RGB data is ignored in classes without color information)
00365                 virtual void setPoint(size_t index,float x, float y, float z, float R, float G, float B) { setPoint(index,x,y,z); }
00366 
00367                 /// Sets the point weight, which is ignored in all classes but those which actually store that field (Note: No checks are done for out-of-bounds index). \sa getPointWeight
00368                 virtual void setPointWeight(size_t index,unsigned long w) {  }
00369                 /// Gets the point weight, which is ignored in all classes (defaults to 1) but in those which actually store that field (Note: No checks are done for out-of-bounds index).  \sa setPointWeight
00370                 virtual unsigned int getPointWeight(size_t index) const { return 1; }
00371 
00372 
00373                 /** Provides a direct access to points buffer, or NULL if there is no points in the map.
00374                   */
00375                 void  getPointsBuffer( size_t &outPointsCount, const float *&xs, const float *&ys, const float *&zs ) const;
00376 
00377                 /** Provides a direct access to a read-only reference of the internal point buffer. \sa getAllPoints */
00378                 inline const std::vector<float> & getPointsBufferRef_x() const { return x; }
00379                 /** Provides a direct access to a read-only reference of the internal point buffer. \sa getAllPoints */
00380                 inline const std::vector<float> & getPointsBufferRef_y() const { return y; }
00381                 /** Provides a direct access to a read-only reference of the internal point buffer. \sa getAllPoints */
00382                 inline const std::vector<float> & getPointsBufferRef_z() const { return z; }
00383 
00384                 /** Returns a copy of the 2D/3D points as a std::vector of float coordinates.
00385                   * If decimation is greater than 1, only 1 point out of that number will be saved in the output, effectively performing a subsampling of the points.
00386                   * \sa getPointsBufferRef_x, getPointsBufferRef_y, getPointsBufferRef_z
00387                   * \tparam VECTOR can be std::vector<float or double> or any row/column Eigen::Array or Eigen::Matrix (this includes mrpt::vector_float and mrpt::vector_double).
00388                   */
00389                 template <class VECTOR>
00390                 void  getAllPoints( VECTOR &xs, VECTOR &ys, VECTOR &zs, size_t decimation = 1 ) const
00391                 {
00392                         MRPT_START
00393                         ASSERT_(decimation>0)
00394                         const size_t Nout = x.size() / decimation;
00395                         xs.resize(Nout);
00396                         ys.resize(Nout);
00397                         zs.resize(Nout);
00398                         size_t idx_in, idx_out;
00399                         for (idx_in=0,idx_out=0;idx_out<Nout;idx_in+=decimation,++idx_out)
00400                         {
00401                                 xs[idx_out]=x[idx_in];
00402                                 ys[idx_out]=y[idx_in];
00403                                 zs[idx_out]=z[idx_in];
00404                         }
00405                         MRPT_END
00406                 }
00407 
00408                 inline void getAllPoints(std::vector<TPoint3D> &ps,size_t decimation=1) const   {
00409                         std::vector<float> dmy1,dmy2,dmy3;
00410                         getAllPoints(dmy1,dmy2,dmy3,decimation);
00411                         ps.resize(dmy1.size());
00412                         for (size_t i=0;i<dmy1.size();i++)      {
00413                                 ps[i].x=static_cast<double>(dmy1[i]);
00414                                 ps[i].y=static_cast<double>(dmy2[i]);
00415                                 ps[i].z=static_cast<double>(dmy3[i]);
00416                         }
00417                 }
00418 
00419                 /** Returns a copy of the 2D/3D points as a std::vector of float coordinates.
00420                   * If decimation is greater than 1, only 1 point out of that number will be saved in the output, effectively performing a subsampling of the points.
00421                   * \sa setAllPoints
00422                   */
00423                 void  getAllPoints( std::vector<float> &xs, std::vector<float> &ys, size_t decimation = 1 ) const;
00424 
00425                 inline void getAllPoints(std::vector<TPoint2D> &ps,size_t decimation=1) const   {
00426                         std::vector<float> dmy1,dmy2;
00427                         getAllPoints(dmy1,dmy2,decimation);
00428                         ps.resize(dmy1.size());
00429                         for (size_t i=0;i<dmy1.size();i++)      {
00430                                 ps[i].x=static_cast<double>(dmy1[i]);
00431                                 ps[i].y=static_cast<double>(dmy2[i]);
00432                         }
00433                 }
00434 
00435                 /** Provides a way to insert (append) individual points into the map: the missing fields of child
00436                   * classes (color, weight, etc) are left to their default values
00437                   */
00438                 inline void  insertPoint( float x, float y, float z=0 ) { insertPointFast(x,y,z); mark_as_modified(); }
00439                 /// \overload of \a insertPoint()
00440                 inline void  insertPoint( const CPoint3D &p ) { insertPoint(p.x(),p.y(),p.z()); }
00441                 /// \overload
00442                 inline void  insertPoint( const mrpt::math::TPoint3D &p ) { insertPoint(p.x,p.y,p.z); }
00443                 /// \overload (RGB data is ignored in classes without color information)
00444                 virtual void  insertPoint( float x, float y, float z, float R, float G, float B ) { insertPoint(x,y,z); }
00445 
00446                 /** Set all the points at once from vectors with X,Y and Z coordinates (if Z is not provided, it will be set to all zeros).
00447                   * \tparam VECTOR can be mrpt::vector_float or std::vector<float> or any other column or row Eigen::Matrix.
00448                   */
00449                 template <typename VECTOR>
00450                 inline void setAllPointsTemplate(const VECTOR &X,const VECTOR &Y,const VECTOR &Z = VECTOR())
00451                 {
00452                         const size_t N = X.size();
00453                         ASSERT_EQUAL_(X.size(),Y.size())
00454                         ASSERT_(Z.size()==0 || Z.size()==X.size())
00455                         this->setSize(N);
00456                         const bool z_valid = !Z.empty();
00457                         if (z_valid) for (size_t i=0;i<N;i++) { this->setPointFast(i,X[i],Y[i],Z[i]); }
00458                         else         for (size_t i=0;i<N;i++) { this->setPointFast(i,X[i],Y[i],0); }
00459                         mark_as_modified();
00460                 }
00461 
00462                 /** Set all the points at once from vectors with X,Y and Z coordinates. \sa getAllPoints */
00463                 inline void setAllPoints(const std::vector<float> &X,const std::vector<float> &Y,const std::vector<float> &Z) {
00464                         setAllPointsTemplate(X,Y,Z);
00465                 }
00466 
00467                 /** Set all the points at once from vectors with X and Y coordinates (Z=0). \sa getAllPoints */
00468                 inline void setAllPoints(const std::vector<float> &X,const std::vector<float> &Y) {
00469                         setAllPointsTemplate(X,Y);
00470                 }
00471 
00472                 /** Get all the data fields for one point as a vector: depending on the implementation class this can be [X Y Z] or [X Y Z R G B], etc...
00473                   * \sa getPointAllFieldsFast, setPointAllFields, setPointAllFieldsFast
00474                   */
00475                 void  getPointAllFields( const size_t index, std::vector<float> & point_data ) const {
00476                         ASSERT_BELOW_(index,this->size())
00477                         getPointAllFieldsFast(index,point_data);
00478                 }
00479 
00480                 /** Set all the data fields for one point as a vector: depending on the implementation class this can be [X Y Z] or [X Y Z R G B], etc...
00481                   *  Unlike setPointAllFields(), this method does not check for index out of bounds
00482                   * \sa setPointAllFields, getPointAllFields, getPointAllFieldsFast
00483                   */
00484                 void  setPointAllFields( const size_t index, const std::vector<float> & point_data ){
00485                         ASSERT_BELOW_(index,this->size())
00486                         setPointAllFieldsFast(index,point_data);
00487                 }
00488 
00489 
00490                 /** Delete points out of the given "z" axis range have been removed.
00491                   */
00492                 void  clipOutOfRangeInZ(float zMin, float zMax);
00493 
00494                 /** Delete points which are more far than "maxRange" away from the given "point".
00495                   */
00496                 void  clipOutOfRange(const CPoint2D     &point, float maxRange);
00497 
00498                 /** Remove from the map the points marked in a bool's array as "true".
00499                   * \exception std::exception If mask size is not equal to points count.
00500                   */
00501                 void  applyDeletionMask( const std::vector<bool> &mask );
00502 
00503                 /** Computes the matchings between this and another 2D/3D points map.
00504                    This includes finding:
00505                                 - The set of points pairs in each map
00506                                 - The mean squared distance between corresponding pairs.
00507                    This method is the most time critical one into the ICP algorithm.
00508 
00509                  * \param  otherMap                                       [IN] The other map to compute the matching with.
00510                  * \param  otherMapPose                           [IN] The pose of the other map as seen from "this".
00511                  * \param  maxDistForCorrespondence [IN] Maximum 2D distance between two points to be matched.
00512                  * \param  maxAngularDistForCorrespondence [IN] Maximum angular distance in radians to allow far points to be matched.
00513                  * \param  angularDistPivotPoint      [IN] The point from which to measure the "angular distances"
00514                  * \param  correspondences                        [OUT] The detected matchings pairs.
00515                  * \param  correspondencesRatio           [OUT] The number of correct correspondences.
00516                  * \param  sumSqrDist                             [OUT] The sum of all matched points squared distances.If undesired, set to NULL, as default.
00517                  * \param  covariance                             [OUT] The resulting matching covariance 3x3 matrix, or NULL if undesired.
00518                  * \param  onlyKeepTheClosest             [OUT] Returns only the closest correspondence (default=false)
00519                  *
00520                  * \sa computeMatching3DWith
00521                  */
00522                 void  computeMatchingWith2D(
00523                                 const CMetricMap     *otherMap,
00524                                 const CPose2D        &otherMapPose,
00525                                 float                maxDistForCorrespondence,
00526                                 float                maxAngularDistForCorrespondence,
00527                                 const CPose2D        &angularDistPivotPoint,
00528                                 TMatchingPairList    &correspondences,
00529                                 float                &correspondencesRatio,
00530                                 float                *sumSqrDist        = NULL,
00531                                 bool                  onlyKeepTheClosest = false,
00532                                 bool                  onlyUniqueRobust = false,
00533                                 const size_t          decimation_other_map_points = 1,
00534                                 const size_t          offset_other_map_points = 0 ) const;
00535 
00536                 /** Computes the matchings between this and another 3D points map - method used in 3D-ICP.
00537                    This method finds the set of point pairs in each map.
00538 
00539                    The method is the most time critical one into the ICP algorithm.
00540 
00541                  * \param  otherMap                                       [IN] The other map to compute the matching with.
00542                  * \param  otherMapPose                           [IN] The pose of the other map as seen from "this".
00543                  * \param  maxDistForCorrespondence   [IN] Maximum 2D linear distance between two points to be matched.
00544                  * \param  maxAngularDistForCorrespondence [IN] In radians: The aim is to allow larger distances to more distant correspondences.
00545                  * \param  angularDistPivotPoint      [IN] The point used to calculate distances from in both maps.
00546                  * \param  correspondences                        [OUT] The detected matchings pairs.
00547                  * \param  correspondencesRatio           [OUT] The ratio [0,1] of points in otherMap with at least one correspondence.
00548                  * \param  sumSqrDist                             [OUT] The sum of all matched points squared distances.If undesired, set to NULL, as default.
00549                  * \param  onlyKeepTheClosest         [IN] If set to true, only the closest correspondence will be returned. If false (default) all are returned.
00550                  *
00551                  * \sa compute3DMatchingRatio
00552                  */
00553                 void  computeMatchingWith3D(
00554                         const CMetricMap                                                *otherMap,
00555                         const CPose3D                                                   &otherMapPose,
00556                         float                                                                   maxDistForCorrespondence,
00557                         float                                                                   maxAngularDistForCorrespondence,
00558                         const CPoint3D                                                  &angularDistPivotPoint,
00559                         TMatchingPairList                                               &correspondences,
00560                         float                                                                   &correspondencesRatio,
00561                         float                                                                   *sumSqrDist     = NULL,
00562                         bool                                                                    onlyKeepTheClosest = true,
00563                         bool                                                                    onlyUniqueRobust = false,
00564                         const size_t          decimation_other_map_points = 1,
00565                         const size_t                            offset_other_map_points = 0 ) const;
00566 
00567                 /** Computes the ratio in [0,1] of correspondences between "this" and the "otherMap" map, whose 6D pose relative to "this" is "otherMapPose"
00568                  *   In the case of a multi-metric map, this returns the average between the maps. This method always return 0 for grid maps.
00569                  * \param  otherMap                                       [IN] The other map to compute the matching with.
00570                  * \param  otherMapPose                           [IN] The 6D pose of the other map as seen from "this".
00571                  * \param  minDistForCorr                         [IN] The minimum distance between 2 non-probabilistic map elements for counting them as a correspondence.
00572                  * \param  minMahaDistForCorr             [IN] The minimum Mahalanobis distance between 2 probabilistic map elements for counting them as a correspondence.
00573                  *
00574                  * \return The matching ratio [0,1]
00575                  * \sa computeMatchingWith2D
00576                  */
00577                 float  compute3DMatchingRatio(
00578                                 const CMetricMap                                                *otherMap,
00579                                 const CPose3D                                                   &otherMapPose,
00580                                 float                                                                   minDistForCorr = 0.10f,
00581                                 float                                                                   minMahaDistForCorr = 2.0f
00582                                 ) const;
00583 
00584                 /** Transform the range scan into a set of cartessian coordinated
00585                   *      points. The options in "insertionOptions" are considered in this method.
00586                   * \param rangeScan The scan to be inserted into this map
00587                   * \param robotPose The robot 3D pose, default to (0,0,0|0deg,0deg,0deg). It is used to compute the sensor pose relative to the robot actual pose. Recall sensor pose is embeded in the observation class.
00588                   *
00589                   *  Only ranges marked as "valid=true" in the observation will be inserted
00590                   *
00591                   *  \note Each derived class may enrich points in different ways (color, weight, etc..), so please refer to the description of the specific
00592                   *         implementation of mrpt::slam::CPointsMap you are using.
00593                   *  \note The actual generic implementation of this file lives in <src>/CPointsMap_crtp_common.h, but specific instantiations are generated at each derived class.
00594                   *
00595                   * \sa CObservation2DRangeScan, CObservation3DRangeScan
00596                   */
00597                 virtual void  loadFromRangeScan(
00598                                 const CObservation2DRangeScan &rangeScan,
00599                                 const CPose3D                             *robotPose = NULL ) = 0;
00600 
00601                 /** Overload of \a loadFromRangeScan() for 3D range scans (for example, Kinect observations).
00602                   *
00603                   * \param rangeScan The scan to be inserted into this map
00604                   * \param robotPose The robot 3D pose, default to (0,0,0|0deg,0deg,0deg). It is used to compute the sensor pose relative to the robot actual pose. Recall sensor pose is embeded in the observation class.
00605                   *
00606                   *  \note Each derived class may enrich points in different ways (color, weight, etc..), so please refer to the description of the specific
00607                   *         implementation of mrpt::slam::CPointsMap you are using.
00608                   *  \note The actual generic implementation of this file lives in <src>/CPointsMap_crtp_common.h, but specific instantiations are generated at each derived class.
00609                   */
00610                 virtual void  loadFromRangeScan(
00611                                 const CObservation3DRangeScan &rangeScan,
00612                                 const CPose3D                             *robotPose = NULL ) = 0;
00613 
00614                 /** Insert the contents of another map into this one, fusing the previous content with the new one.
00615                  *    This means that points very close to existing ones will be "fused", rather than "added". This prevents
00616                  *     the unbounded increase in size of these class of maps.
00617                  *              NOTICE that "otherMap" is neither translated nor rotated here, so if this is desired it must done
00618                  *               before calling this method.
00619                  * \param otherMap The other map whose points are to be inserted into this one.
00620                  * \param minDistForFuse Minimum distance (in meters) between two points, each one in a map, to be considered the same one and be fused rather than added.
00621                  * \param notFusedPoints If a pointer is supplied, this list will contain at output a list with a "bool" value per point in "this" map. This will be false/true according to that point having been fused or not.
00622                  * \sa loadFromRangeScan, addFrom
00623                  */
00624                 void  fuseWith(
00625                         CPointsMap                      *anotherMap,
00626                         float                           minDistForFuse  = 0.02f,
00627                         std::vector<bool>       *notFusedPoints = NULL);
00628 
00629                 /** Replace each point \f$ p_i \f$ by \f$ p'_i = b \oplus p_i \f$ (pose compounding operator).
00630                   */
00631                 void   changeCoordinatesReference(const CPose2D &b);
00632 
00633                 /** Replace each point \f$ p_i \f$ by \f$ p'_i = b \oplus p_i \f$ (pose compounding operator).
00634                   */
00635                 void   changeCoordinatesReference(const CPose3D &b);
00636 
00637                 /** Copy all the points from "other" map to "this", replacing each point \f$ p_i \f$ by \f$ p'_i = b \oplus p_i \f$ (pose compounding operator).
00638                   */
00639                 void   changeCoordinatesReference(const CPointsMap &other, const CPose3D &b);
00640 
00641                 /** Returns true if the map is empty/no observation has been inserted.
00642                    */
00643                 virtual bool isEmpty() const;
00644 
00645                 /** STL-like method to check whether the map is empty: */
00646                 inline bool  empty() const { return isEmpty(); }
00647 
00648                 /** Returns a 3D object representing the map.
00649                   *  The color of the points is given by the static variables: COLOR_3DSCENE_R,COLOR_3DSCENE_G,COLOR_3DSCENE_B
00650                   * \sa mrpt::global_settings::POINTSMAPS_3DOBJECT_POINTSIZE
00651                   */
00652                 virtual void  getAs3DObject ( mrpt::opengl::CSetOfObjectsPtr    &outObj ) const;
00653 
00654                 /** If the map is a simple points map or it's a multi-metric map that contains EXACTLY one simple points map, return it.
00655                         * Otherwise, return NULL
00656                         */
00657                 virtual const CSimplePointsMap * getAsSimplePointsMap() const { return NULL; }
00658                 virtual       CSimplePointsMap * getAsSimplePointsMap()       { return NULL; }
00659 
00660 
00661                 /** This method returns the largest distance from the origin to any of the points, such as a sphere centered at the origin with this radius cover ALL the points in the map (the results are buffered, such as, if the map is not modified, the second call will be much faster than the first one). */
00662                 float  getLargestDistanceFromOrigin() const;
00663 
00664                 /** Like \a getLargestDistanceFromOrigin() but returns in \a output_is_valid = false if the distance was not already computed, skipping its computation then, unlike getLargestDistanceFromOrigin() */
00665                 float  getLargestDistanceFromOriginNoRecompute(bool &output_is_valid) const {
00666                         output_is_valid = m_largestDistanceFromOriginIsUpdated;
00667                         return m_largestDistanceFromOrigin;
00668                 }
00669 
00670                 /** Computes the bounding box of all the points, or (0,0 ,0,0, 0,0) if there are no points.
00671                   *  Results are cached unless the map is somehow modified to avoid repeated calculations.
00672                   */
00673                 void boundingBox( float &min_x,float &max_x,float &min_y,float &max_y,float &min_z,float &max_z ) const;
00674 
00675                 inline void boundingBox(TPoint3D &pMin,TPoint3D &pMax) const    {
00676                         float dmy1,dmy2,dmy3,dmy4,dmy5,dmy6;
00677                         boundingBox(dmy1,dmy2,dmy3,dmy4,dmy5,dmy6);
00678                         pMin.x=dmy1;
00679                         pMin.y=dmy2;
00680                         pMin.z=dmy3;
00681                         pMax.x=dmy4;
00682                         pMax.y=dmy5;
00683                         pMax.z=dmy6;
00684                 }
00685 
00686                 void extractCylinder( const CPoint2D &center, const double radius, const double zmin, const double zmax, CPointsMap *outMap );
00687 
00688                 /** @name Filter-by-height stuff
00689                         @{ */
00690 
00691                 /** Enable/disable the filter-by-height functionality \sa setHeightFilterLevels \note Default upon construction is disabled. */
00692                 inline void enableFilterByHeight(bool enable=true) { m_heightfilter_enabled=enable; }
00693                 /** Return whether filter-by-height is enabled \sa enableFilterByHeight */
00694                 inline bool isFilterByHeightEnabled() const  { return m_heightfilter_enabled; }
00695 
00696                 /** Set the min/max Z levels for points to be actually inserted in the map (only if \a enableFilterByHeight() was called before). */
00697                 inline void setHeightFilterLevels(const double _z_min, const double _z_max) { m_heightfilter_z_min=_z_min; m_heightfilter_z_max=_z_max; }
00698                 /** Get the min/max Z levels for points to be actually inserted in the map \sa enableFilterByHeight, setHeightFilterLevels */
00699                 inline void getHeightFilterLevels(double &_z_min, double &_z_max) const { _z_min=m_heightfilter_z_min; _z_max=m_heightfilter_z_max; }
00700 
00701                 /** @} */
00702 
00703                 /** The color [0,1] of points when extracted from getAs3DObject (default=blue) */
00704                 static float COLOR_3DSCENE_R;
00705                 static float COLOR_3DSCENE_G;
00706                 static float COLOR_3DSCENE_B;
00707 
00708 
00709                 /** Computes the likelihood of taking a given observation from a given pose in the world being modeled with this map.
00710                  * \param takenFrom The robot's pose the observation is supposed to be taken from.
00711                  * \param obs The observation.
00712                  * \return This method returns a likelihood in the range [0,1].
00713                  *
00714                  * \sa Used in particle filter algorithms, see: CMultiMetricMapPDF
00715                  * \note In CPointsMap this method is virtual so it can be redefined in derived classes, if desired.
00716                  */
00717                 virtual double computeObservationLikelihood( const CObservation *obs, const CPose3D &takenFrom );
00718 
00719         /** @name PCL library support
00720             @{ */
00721 
00722 
00723         /** Use to convert this MRPT point cloud object into a PCL point cloud object.
00724           *  Usage example:
00725           *  \code
00726           *    mrpt::slam::CPointsCloud       pc;
00727           *    pcl::PointCloud<pcl::PointXYZ> cloud;
00728           *
00729           *    pc.getPCLPointCloud(cloud);
00730           *  \endcode
00731           */
00732         template <class POINTCLOUD>
00733         void getPCLPointCloud(POINTCLOUD &cloud) const
00734         {
00735             const size_t nThis = this->size();
00736             // Fill in the cloud data
00737             cloud.width    = nThis;
00738             cloud.height   = 1;
00739             cloud.is_dense = false;
00740             cloud.points.resize(cloud.width * cloud.height);
00741             for (size_t i = 0; i < nThis; ++i) {
00742                 cloud.points[i].x =this->x[i];
00743                 cloud.points[i].y =this->y[i];
00744                 cloud.points[i].z =this->z[i];
00745             }
00746         }
00747 
00748         /** @} */
00749 
00750                 /** @name Methods that MUST be implemented by children classes of KDTreeCapable
00751                         @{ */
00752 
00753                 /// Must return the number of data points
00754                 inline size_t kdtree_get_point_count() const {  return this->size(); }
00755 
00756                 /// Returns the dim'th component of the idx'th point in the class:
00757                 inline float kdtree_get_pt(const size_t idx, int dim) const {
00758                         if (dim==0) return this->x[idx];
00759                         else if (dim==1) return this->y[idx];
00760                         else if (dim==2) return this->z[idx]; else return 0;
00761                 }
00762 
00763                 /// Returns the distance between the vector "p1[0:size-1]" and the data point with index "idx_p2" stored in the class:
00764                 inline float kdtree_distance(const float *p1, const size_t idx_p2,size_t size) const
00765                 {
00766                         if (size==2)
00767                         {
00768                                 const float d0 = p1[0]-x[idx_p2];
00769                                 const float d1 = p1[1]-y[idx_p2];
00770                                 return d0*d0+d1*d1;
00771                         }
00772                         else
00773                         {
00774                                 const float d0 = p1[0]-x[idx_p2];
00775                                 const float d1 = p1[1]-y[idx_p2];
00776                                 const float d2 = p1[2]-z[idx_p2];
00777                                 return d0*d0+d1*d1+d2*d2;
00778                         }
00779                 }
00780 
00781                 // Optional bounding-box computation: return false to default to a standard bbox computation loop.
00782                 //   Return true if the BBOX was already computed by the class and returned in "bb" so it can be avoided to redo it again.
00783                 //   Look at bb.size() to find out the expected dimensionality (e.g. 2 or 3 for point clouds)
00784                 template <typename BBOX>
00785                 bool kdtree_get_bbox(BBOX &bb) const
00786                 {
00787                         float min_z,max_z;
00788                         this->boundingBox(
00789                                 bb[0].low, bb[0].high,
00790                                 bb[1].low, bb[1].high,
00791                                 min_z,max_z);
00792                         if (bb.size()==3) {
00793                                 bb[2].low = min_z; bb[2].high = max_z;
00794                         }
00795                         return true;
00796                 }
00797 
00798 
00799                 /** @} */
00800 
00801         protected:
00802                 std::vector<float>     x,y,z;        //!< The point coordinates
00803 
00804                 CSinCosLookUpTableFor2DScans  m_scans_sincos_cache; //!< Cache of sin/cos values for the latest 2D scan geometries.
00805 
00806                 /** Auxiliary variables used in "getLargestDistanceFromOrigin"
00807                   * \sa getLargestDistanceFromOrigin
00808                   */
00809                 mutable float   m_largestDistanceFromOrigin;
00810 
00811                 /** Auxiliary variables used in "getLargestDistanceFromOrigin"
00812                   * \sa getLargestDistanceFromOrigin
00813                   */
00814                 mutable bool    m_largestDistanceFromOriginIsUpdated;
00815 
00816                 mutable bool    m_boundingBoxIsUpdated;
00817                 mutable float   m_bb_min_x,m_bb_max_x, m_bb_min_y,m_bb_max_y, m_bb_min_z,m_bb_max_z;
00818 
00819 
00820                 /** Called only by this class or children classes, set m_largestDistanceFromOriginIsUpdated=false and such. */
00821                 inline void mark_as_modified() const
00822                 {
00823                         m_largestDistanceFromOriginIsUpdated=false;
00824                         m_boundingBoxIsUpdated = false;
00825                         kdtree_mark_as_outdated();
00826                 }
00827 
00828                 /** This is a common version of CMetricMap::insertObservation() for point maps (actually, CMetricMap::internal_insertObservation),
00829                   *   so derived classes don't need to worry implementing that method unless something special is really necesary.
00830                   * See mrpt::slam::CPointsMap for the enumeration of types of observations which are accepted.
00831                   */
00832                 bool  internal_insertObservation(
00833                         const CObservation      *obs,
00834                         const CPose3D *robotPose);
00835 
00836                 /** Helper method for ::copyFrom() */
00837                 void  base_copyFrom(const CPointsMap &obj);
00838 
00839 
00840                 /** @name PLY Import virtual methods to implement in base classes
00841                         @{ */
00842                 /** In a base class, reserve memory to prepare subsequent calls to PLY_import_set_face */
00843                 virtual void PLY_import_set_face_count(const size_t N) {  }
00844 
00845                 /** In a base class, will be called after PLY_import_set_vertex_count() once for each loaded point.
00846                   *  \param pt_color Will be NULL if the loaded file does not provide color info.
00847                   */
00848                 virtual void PLY_import_set_vertex(const size_t idx, const mrpt::math::TPoint3Df &pt, const mrpt::utils::TColorf *pt_color = NULL);
00849                 /** @} */
00850 
00851                 /** @name PLY Export virtual methods to implement in base classes
00852                         @{ */
00853 
00854                 /** In a base class, return the number of vertices */
00855                 virtual size_t PLY_export_get_vertex_count() const;
00856 
00857                 /** In a base class, return the number of faces */
00858                 virtual size_t PLY_export_get_face_count() const { return 0; }
00859 
00860                 /** In a base class, will be called after PLY_export_get_vertex_count() once for each exported point.
00861                   *  \param pt_color Will be NULL if the loaded file does not provide color info.
00862                   */
00863                 virtual void PLY_export_get_vertex(
00864                         const size_t idx,
00865                         mrpt::math::TPoint3Df &pt,
00866                         bool &pt_has_color,
00867                         mrpt::utils::TColorf &pt_color) const;
00868 
00869                 /** @} */
00870 
00871                 /** The minimum and maximum height for a certain laser scan to be inserted into this map
00872                    * \sa m_heightfilter_enabled */
00873                 double m_heightfilter_z_min, m_heightfilter_z_max;
00874 
00875                 /** Whether or not (default=not) filter the input points by height
00876                   * \sa m_heightfilter_z_min, m_heightfilter_z_max */
00877                 bool m_heightfilter_enabled;
00878 
00879 
00880                 // Friend methods:
00881                 template <class Derived> friend struct detail::loadFromRangeImpl;
00882                 template <class Derived> friend struct detail::pointmap_traits;
00883 
00884 
00885         }; // End of class def.
00886 
00887         } // End of namespace
00888 
00889         namespace global_settings
00890         {
00891                 /** The size of points when exporting with getAs3DObject() (default=3.0)
00892                   * Affects to:
00893                   *             - mrpt::slam::CPointsMap and all its children classes.
00894                   */
00895                 extern MAPS_IMPEXP float POINTSMAPS_3DOBJECT_POINTSIZE;
00896         }
00897 } // End of namespace
00898 
00899 #endif



Page generated by Doxygen 1.7.5 for MRPT 0.9.5 SVN: at Thu Oct 13 21:25:36 UTC 2011