Main MRPT website > C++ reference
MRPT logo
CAngularObservationMesh.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 opengl_CAngularObservationMesh_H
00029 #define opengl_CAngularObservationMesh_H
00030 
00031 #include <mrpt/opengl/CRenderizableDisplayList.h>
00032 #include <mrpt/opengl/CSetOfTriangles.h>
00033 #include <mrpt/math/CMatrixTemplate.h>
00034 #include <mrpt/math/CMatrixB.h>
00035 #include <mrpt/utils/stl_extensions.h>
00036 #include <mrpt/slam/CObservation2DRangeScan.h>
00037 #include <mrpt/slam/CPointsMap.h>
00038 #include <mrpt/opengl/CSetOfLines.h>
00039 
00040 #include <mrpt/math/geometry.h>
00041 
00042 namespace mrpt  {
00043 namespace opengl        {
00044         using namespace mrpt::utils;
00045         using namespace mrpt::slam;
00046         using namespace mrpt::poses;
00047 
00048         DEFINE_SERIALIZABLE_PRE_CUSTOM_BASE_LINKAGE(CAngularObservationMesh,CRenderizableDisplayList, MAPS_IMPEXP)
00049 
00050         /**
00051           * A mesh built from a set of 2D laser scan observations.
00052           * Each element of this set is a single scan through the yaw, given a specific pitch.
00053           * Each scan has a CPose3D identifying the origin of the scan, which ideally is the
00054           * same for every one of them.
00055           * \ingroup mrpt_maps_grp
00056           */
00057         class MAPS_IMPEXP CAngularObservationMesh:public CRenderizableDisplayList       {
00058                 DEFINE_SERIALIZABLE(CAngularObservationMesh)
00059         public:
00060                 /**
00061                   * Range specification type, with several uses.
00062                   */
00063                 struct MAPS_IMPEXP TDoubleRange {
00064                 private:
00065                         /**
00066                           * Range type. 
00067                           * If 0, it's specified by an initial and a final value, and an increment.
00068                           * If 1, it's specified by an initial and a final value, and a fixed size of samples.
00069                           * If 2, it's specified by an aperture, a fixed size of samples and a boolean variable controlling direction. This type is always zero-centered.
00070                           */
00071                         char rangeType;
00072                         /**
00073                           * Union type with the actual data.
00074                           * \sa rangeType
00075                           */
00076                         union rd        {
00077                                 struct  {
00078                                         double initial;
00079                                         double final;
00080                                         double increment;
00081                                 }       mode0;
00082                                 struct  {
00083                                         double initial;
00084                                         double final;
00085                                         size_t amount;
00086                                 }       mode1;
00087                                 struct  {
00088                                         double aperture;
00089                                         size_t amount;
00090                                         bool negToPos;
00091                                 }       mode2;
00092                         }       rangeData;
00093                         /**
00094                           * Constructor from initial value, final value and range.
00095                           */
00096                         TDoubleRange(double a,double b,double c):rangeType(0)   {
00097                                 rangeData.mode0.initial=a;
00098                                 rangeData.mode0.final=b;
00099                                 rangeData.mode0.increment=c;
00100                         }
00101                         /**
00102                           * Constructor from initial value, final value and amount of samples.
00103                           */
00104                         TDoubleRange(double a,double b,size_t c):rangeType(1)   {
00105                                 rangeData.mode1.initial=a;
00106                                 rangeData.mode1.final=b;
00107                                 rangeData.mode1.amount=c;
00108                         }
00109                         /**
00110                           * Constructor from aperture, amount of samples and scan direction.
00111                           */
00112                         TDoubleRange(double a,size_t b,bool c):rangeType(2)     {
00113                                 rangeData.mode2.aperture=a;
00114                                 rangeData.mode2.amount=b;
00115                                 rangeData.mode2.negToPos=c;
00116                         }
00117                 public:
00118                         /**
00119                           * Creates a range of values from the initial value, the final value and the increment.
00120                           * \throw std::logic_error if the increment is zero.
00121                           */
00122                         inline static TDoubleRange CreateFromIncrement(double initial,double final,double increment)    {
00123                                 if (increment==0) throw std::logic_error("Invalid increment value.");
00124                                 return TDoubleRange(initial,final,increment);
00125                         }
00126                         /**
00127                           * Creates a range of values from the initial value, the final value and a desired amount of samples.
00128                           */
00129                         inline static TDoubleRange CreateFromAmount(double initial,double final,size_t amount)  {
00130                                 return TDoubleRange(initial,final,amount);
00131                         }
00132                         /**
00133                           * Creates a zero-centered range of values from an aperture, an amount of samples and a direction.
00134                           */
00135                         inline static TDoubleRange CreateFromAperture(double aperture,size_t amount,bool negToPos=true) {
00136                                 return TDoubleRange(aperture,amount,negToPos);
00137                         }
00138                         /**
00139                           * Returns the total aperture of the range.
00140                           * \throw std::logic_error on invalid range type.
00141                           */
00142                         inline double aperture() const  {
00143                                 switch (rangeType)      {
00144                                         case 0:return (sign(rangeData.mode0.increment)==sign(rangeData.mode0.final-rangeData.mode0.initial))?fabs(rangeData.mode0.final-rangeData.mode0.initial):0;
00145                                         case 1:return rangeData.mode1.final-rangeData.mode1.initial;
00146                                         case 2:return rangeData.mode2.aperture;
00147                                         default:throw std::logic_error("Unknown range type.");
00148                                 }
00149                         }
00150                         /**
00151                           * Returns the first value of the range.
00152                           * \throw std::logic_error on invalid range type.
00153                           */
00154                         inline double initialValue() const      {
00155                                 switch (rangeType)      {
00156                                         case 0:
00157                                         case 1:return rangeData.mode0.initial;
00158                                         case 2:return rangeData.mode2.negToPos?-rangeData.mode2.aperture/2:rangeData.mode2.aperture/2;
00159                                         default:throw std::logic_error("Unknown range type.");
00160                                 }
00161                         }
00162                         /**
00163                           * Returns the last value of the range.
00164                           * \throw std::logic_error on invalid range type.
00165                           */
00166                         inline double finalValue() const        {
00167                                 switch (rangeType)      {
00168                                         case 0:return (sign(rangeData.mode0.increment)==sign(rangeData.mode0.final-rangeData.mode0.initial))?rangeData.mode0.final:rangeData.mode0.initial;
00169                                         case 1:return rangeData.mode1.final;
00170                                         case 2:return rangeData.mode2.negToPos?rangeData.mode2.aperture/2:-rangeData.mode2.aperture/2;
00171                                         default:throw std::logic_error("Unknown range type.");
00172                                 }
00173                         }
00174                         /**
00175                           * Returns the increment between two consecutive values of the range.
00176                           * \throw std::logic_error on invalid range type.
00177                           */
00178                         inline double increment() const {
00179                                 switch (rangeType)      {
00180                                         case 0:return rangeData.mode0.increment;
00181                                         case 1:return (rangeData.mode1.final-rangeData.mode1.initial)/static_cast<double>(rangeData.mode1.amount-1);
00182                                         case 2:return rangeData.mode2.negToPos?rangeData.mode2.aperture/static_cast<double>(rangeData.mode2.amount-1):-rangeData.mode2.aperture/static_cast<double>(rangeData.mode2.amount-1);
00183                                         default:throw std::logic_error("Unknown range type.");
00184                                 }
00185                         }
00186                         /**
00187                           * Returns the total amount of values in this range.
00188                           * \throw std::logic_error on invalid range type.
00189                           */
00190                         inline size_t amount() const    {
00191                                 switch (rangeType)      {
00192                                         case 0:return (sign(rangeData.mode0.increment)==sign(rangeData.mode0.final-rangeData.mode0.initial))?1+static_cast<size_t>(ceil((rangeData.mode0.final-rangeData.mode0.initial)/rangeData.mode0.increment)):1;
00193                                         case 1:return rangeData.mode1.amount;
00194                                         case 2:return rangeData.mode2.amount;
00195                                         default:throw std::logic_error("Unknown range type.");
00196                                 }
00197                         }
00198                         /**
00199                           * Gets a vector with every value in the range.
00200                           * \throw std::logic_error on invalid range type.
00201                           */
00202                         void values(std::vector<double> &vals) const;
00203                         /**
00204                           * Returns the direction of the scan. True if the increment is positive, false otherwise.
00205                           * \throw std::logic_error on invalid range type.
00206                           */
00207                         inline bool negToPos() const    {
00208                                 switch (rangeType)      {
00209                                         case 0:return sign(rangeData.mode0.increment)>0;
00210                                         case 1:return sign(rangeData.mode1.final-rangeData.mode1.initial)>0;
00211                                         case 2:return rangeData.mode2.negToPos;
00212                                         default:throw std::logic_error("Unknown range type.");
00213                                 }
00214                         }
00215                 };
00216         protected:
00217                 /**
00218                   * Updates the mesh, if needed. It's a const method, but modifies mutable content.
00219                   */
00220                 void updateMesh() const;
00221                 /**
00222                   * Empty destructor.
00223                   */
00224                 virtual ~CAngularObservationMesh()      {}
00225                 /**
00226                   * Actual set of triangles to be displayed.
00227                   */
00228                 mutable std::vector<CSetOfTriangles::TTriangle> triangles;
00229                 /**
00230                   * Internal method to add a triangle to the mutable mesh.
00231                   */
00232                 void addTriangle(const TPoint3D &p1,const TPoint3D &p2,const TPoint3D &p3) const;
00233                 /**
00234                   * Whether the mesh will be displayed wireframe or solid.
00235                   */
00236                 bool mWireframe;
00237                 /**
00238                   * Mutable variable which controls if the object has suffered any change since last time the mesh was updated.
00239                   */
00240                 mutable bool meshUpToDate;
00241                 /**
00242                   * Whether the object may present transparencies or not.
00243                   */
00244                 bool mEnableTransparency;
00245                 /**
00246                   * Mutable object with the mesh's points.
00247                   */
00248                 mutable mrpt::math::CMatrixTemplate<TPoint3D> actualMesh;
00249                 /**
00250                   * Scan validity matrix.
00251                   */
00252                 mutable mrpt::math::CMatrixB validityMatrix;
00253                 /**
00254                   * Observation pitch range. When containing exactly two elements, they represent the bounds.
00255                   */
00256                 std::vector<double> pitchBounds;
00257                 /**
00258                   * Actual scan set which is used to generate the mesh.
00259                   */
00260                 std::vector<CObservation2DRangeScan> scanSet;
00261                 /**
00262                   * Basic constructor.
00263                   */
00264                 CAngularObservationMesh():mWireframe(true),meshUpToDate(false),mEnableTransparency(true),actualMesh(0,0),validityMatrix(0,0),pitchBounds(),scanSet()    {}
00265         public:
00266                 /**
00267                   * Returns whether the object is configured as wireframe or solid.
00268                   */
00269                 inline bool isWireframe() const {
00270                         return mWireframe;
00271                 }
00272                 /**
00273                   * Sets the display mode for the object. True=wireframe, False=solid.
00274                   */
00275                 inline void setWireframe(bool enabled=true)     {
00276                         mWireframe=enabled;
00277                         CRenderizableDisplayList::notifyChange();
00278                 }
00279                 /**
00280                   * Returns whether the object may be transparent or not.
00281                   */
00282                 inline bool isTransparencyEnabled() const       {
00283                         return mEnableTransparency;
00284                 }
00285                 /**
00286                   * Enables or disables transparencies.
00287                   */
00288                 inline void enableTransparency(bool enabled=true)       {
00289                         mEnableTransparency=enabled;
00290                         CRenderizableDisplayList::notifyChange();
00291                 }
00292                 /**
00293                   * Renderizes the object.
00294                   * \sa mrpt::opengl::CRenderizable
00295                   */
00296                 virtual void render_dl() const;
00297                 /**
00298                   * Traces a ray to the object, returning the distance to a given pose through its X axis.
00299                   * \sa mrpt::opengl::CRenderizable,trace2DSetOfRays,trace1DSetOfRays
00300                   */
00301                 virtual bool traceRay(const mrpt::poses::CPose3D &o,double &dist) const;
00302                 /**
00303                   * Sets the pitch bounds for this range.
00304                   */
00305                 void setPitchBounds(const double initial,const double final);
00306                 /**
00307                   * Sets the pitch bounds for this range.
00308                   */
00309                 void setPitchBounds(const std::vector<double> bounds);
00310                 /**
00311                   * Gets the initial and final pitch bounds for this range.
00312                   */
00313                 void getPitchBounds(double &initial,double &final) const;
00314                 /**
00315                   * Gets the pitch bounds for this range.
00316                   */
00317                 void getPitchBounds(std::vector<double> &bounds) const;
00318                 /**
00319                   * Gets the scan set.
00320                   */
00321                 void getScanSet(std::vector<CObservation2DRangeScan> &scans) const;
00322                 /**
00323                   * Sets the scan set.
00324                   */
00325                 bool setScanSet(const std::vector<CObservation2DRangeScan> &scans);
00326                 /**
00327                   * Gets the mesh as a set of triangles, for displaying them.
00328                   * \sa generateSetOfTriangles(std::vector<TPolygon3D> &),mrpt::opengl::CSetOfTriangles,mrpt::opengl::CSetOfTriangles::TTriangle
00329                   */
00330                 void generateSetOfTriangles(CSetOfTrianglesPtr &res) const;
00331                 /**
00332                   * Returns the scanned points as a 3D point cloud. The target pointmap must be passed as a pointer to allow the use of any derived class.
00333                   */
00334                 void generatePointCloud(CPointsMap *out_map) const;
00335                 /**
00336                   * Gets a set of lines containing the traced rays, for displaying them.
00337                   * \sa getUntracedRays,mrpt::opengl::CSetOfLines
00338                   */
00339                 void getTracedRays(CSetOfLinesPtr &res) const;
00340                 /**
00341                   * Gets a set of lines containing the untraced rays, up to a specified distance, for displaying them.
00342                   * \sa getTracedRays,mrpt::opengl::CSetOfLines
00343                   */
00344                 void getUntracedRays(CSetOfLinesPtr &res,double dist) const;
00345                 /**
00346                   * Gets the mesh as a set of polygons, to work with them.
00347                   * \sa generateSetOfTriangles(mrpt::opengl::CSetOfTriangles &)
00348                   */
00349                 void generateSetOfTriangles(std::vector<TPolygon3D> &res) const;
00350                 /**
00351                   * Retrieves the full mesh, along with the validity matrix.
00352                   */
00353                 void getActualMesh(mrpt::math::CMatrixTemplate<mrpt::math::TPoint3D> &pts,mrpt::math::CMatrixBool &validity) const      {
00354                         if (!meshUpToDate) updateMesh();
00355                         pts=actualMesh;
00356                         validity=validityMatrix;
00357                 }
00358         private:
00359                 /**
00360                   * Internal functor class to trace a ray.
00361                   */
00362                 template<class T> class FTrace1D        {
00363                 protected:
00364                         const CPose3D &initial;
00365                         const T &e;
00366                         std::vector<double> &values;
00367                         std::vector<char> &valid;
00368                 public:
00369                         FTrace1D(const T &s,const CPose3D &p,std::vector<double> &v,std::vector<char> &v2):initial(p),e(s),values(v),valid(v2)  {}
00370                         void operator()(double yaw)     {
00371                                 double dist;
00372                                 const CPose3D pNew=initial+CPose3D(0.0,0.0,0.0,yaw,0.0,0.0);
00373                                 if (e->traceRay(pNew,dist))     {
00374                                         values.push_back(dist);
00375                                         valid.push_back(1);
00376                                 }       else    {
00377                                         values.push_back(0);
00378                                         valid.push_back(0);
00379                                 }
00380                         }
00381                 };
00382                 /**
00383                   * Internal functor class to trace a set of rays.
00384                   */
00385                 template<class T> class FTrace2D        {
00386                 protected:
00387                         const T &e;
00388                         const CPose3D &initial;
00389                         CAngularObservationMeshPtr &caom;
00390                         const CAngularObservationMesh::TDoubleRange &yaws;
00391                         std::vector<CObservation2DRangeScan> &vObs;
00392                         const CPose3D &pBase;
00393                 public:
00394                         FTrace2D(const T &s,const CPose3D &p,CAngularObservationMeshPtr &om,const CAngularObservationMesh::TDoubleRange &y,std::vector<CObservation2DRangeScan> &obs,const CPose3D &b):e(s),initial(p),caom(om),yaws(y),vObs(obs),pBase(b)      {}
00395                         void operator()(double pitch)   {
00396                                 std::vector<double> yValues;
00397                                 yaws.values(yValues);
00398                                 CObservation2DRangeScan o=CObservation2DRangeScan();
00399                                 const CPose3D pNew=initial+CPose3D(0,0,0,0,pitch,0);
00400                                 std::vector<double> values;
00401                                 std::vector<char> valid;
00402                                 size_t nY=yValues.size();
00403                                 values.reserve(nY);
00404                                 valid.reserve(nY);
00405                                 for_each(yValues.begin(),yValues.end(),FTrace1D<T>(e,pNew,values,valid));
00406                                 o.aperture=yaws.aperture();
00407                                 o.rightToLeft=yaws.negToPos();
00408                                 o.maxRange=10000;
00409                                 o.sensorPose=pNew;
00410                                 o.deltaPitch=0;
00411                                 mrpt::utils::copy_container_typecasting(values,o.scan);
00412                                 o.validRange=valid;
00413                                 vObs.push_back(o);
00414                         }
00415                 };
00416         public:
00417                 /**
00418                   * 2D ray tracing (will generate a 3D mesh). Given an object and two ranges, realizes a scan from the initial pose and stores it in a CAngularObservationMesh object.
00419                   * The objective may be a COpenGLScene, a CRenderizable or any children of its.
00420                   * \sa mrpt::opengl::CRenderizable,mrpt::opengl::COpenGLScene.
00421                   */
00422                 template<class T> static void trace2DSetOfRays(const T &e,const CPose3D &initial,CAngularObservationMeshPtr &caom,const TDoubleRange &pitchs,const TDoubleRange &yaws)  {
00423                         std::vector<double> pValues;
00424                         pitchs.values(pValues);
00425                         std::vector<CObservation2DRangeScan> vObs;
00426                         vObs.reserve(pValues.size());
00427                         for_each(pValues.begin(),pValues.end(),FTrace2D<T>(e,initial,caom,yaws,vObs,initial));
00428                         caom->mWireframe=false;
00429                         caom->mEnableTransparency=false;
00430                         caom->setPitchBounds(pValues);
00431                         caom->setScanSet(vObs);
00432                 }
00433                 /**
00434                   * 2D ray tracing (will generate a vectorial mesh inside a plane). Given an object and a range, realizes a scan from the initial pose and stores it in a CObservation2DRangeScan object.
00435                   * The objective may be a COpenGLScene, a CRenderizable or any children of its.
00436                   * \sa mrpt::opengl::CRenderizable,mrpt::opengl::COpenGLScene.
00437                   */
00438                 template<class T> static void trace1DSetOfRays(const T &e,const CPose3D &initial,CObservation2DRangeScan &obs,const TDoubleRange &yaws) {
00439                         std::vector<double> yValues;
00440                         yaws.values(yValues);
00441                         std::vector<double> scanValues;
00442                         std::vector<char> valid;
00443                         size_t nV=yaws.amount();
00444                         scanValues.reserve(nV);
00445                         valid.reserve(nV);
00446                         for_each(yValues.begin(),yValues.end(),FTrace1D<T>(e,initial,scanValues,valid));
00447                         obs.aperture=yaws.aperture();
00448                         obs.rightToLeft=yaws.negToPos();
00449                         obs.maxRange=10000;
00450                         obs.sensorPose=initial;
00451                         obs.deltaPitch=0;
00452                         obs.scan=scanValues;
00453                         obs.validRange=valid;
00454                 }
00455         };
00456 }
00457 }
00458 #endif



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