00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifndef opengl_CAngularObservationMesh_H
00029 #define opengl_CAngularObservationMesh_H
00030 #include <mrpt/opengl/CRenderizable.h>
00031 #include <mrpt/opengl/CSetOfTriangles.h>
00032 #include <mrpt/math/CMatrixTemplate.h>
00033 #include <mrpt/math/CMatrixB.h>
00034 #include <mrpt/utils/stl_extensions.h>
00035 #include <mrpt/slam/CObservation2DRangeScan.h>
00036 #include <mrpt/slam/CPointsMap.h>
00037 #include <mrpt/opengl/CSetOfLines.h>
00038
00039 #include <mrpt/math/geometry.h>
00040
00041 namespace mrpt {
00042 namespace opengl {
00043 using namespace mrpt::utils;
00044 using namespace mrpt::slam;
00045 using namespace mrpt::poses;
00046
00047 DEFINE_SERIALIZABLE_PRE_CUSTOM_BASE_LINKAGE(CAngularObservationMesh,CRenderizable, MAPS_IMPEXP)
00048
00049
00050
00051
00052
00053
00054
00055 class MAPS_IMPEXP CAngularObservationMesh:public CRenderizable {
00056 DEFINE_SERIALIZABLE(CAngularObservationMesh)
00057 public:
00058
00059
00060
00061 struct MAPS_IMPEXP TDoubleRange {
00062 private:
00063
00064
00065
00066
00067
00068
00069 char rangeType;
00070
00071
00072
00073
00074 union rd {
00075 struct {
00076 double initial;
00077 double final;
00078 double increment;
00079 } mode0;
00080 struct {
00081 double initial;
00082 double final;
00083 size_t amount;
00084 } mode1;
00085 struct {
00086 double aperture;
00087 size_t amount;
00088 bool negToPos;
00089 } mode2;
00090 } rangeData;
00091
00092
00093
00094 TDoubleRange(double a,double b,double c):rangeType(0) {
00095 rangeData.mode0.initial=a;
00096 rangeData.mode0.final=b;
00097 rangeData.mode0.increment=c;
00098 }
00099
00100
00101
00102 TDoubleRange(double a,double b,size_t c):rangeType(1) {
00103 rangeData.mode1.initial=a;
00104 rangeData.mode1.final=b;
00105 rangeData.mode1.amount=c;
00106 }
00107
00108
00109
00110 TDoubleRange(double a,size_t b,bool c):rangeType(2) {
00111 rangeData.mode2.aperture=a;
00112 rangeData.mode2.amount=b;
00113 rangeData.mode2.negToPos=c;
00114 }
00115 public:
00116
00117
00118
00119
00120 inline static TDoubleRange CreateFromIncrement(double initial,double final,double increment) {
00121 if (increment==0) throw std::logic_error("Invalid increment value.");
00122 return TDoubleRange(initial,final,increment);
00123 }
00124
00125
00126
00127 inline static TDoubleRange CreateFromAmount(double initial,double final,size_t amount) {
00128 return TDoubleRange(initial,final,amount);
00129 }
00130
00131
00132
00133 inline static TDoubleRange CreateFromAperture(double aperture,size_t amount,bool negToPos=true) {
00134 return TDoubleRange(aperture,amount,negToPos);
00135 }
00136
00137
00138
00139
00140 inline double aperture() const {
00141 switch (rangeType) {
00142 case 0:return (sign(rangeData.mode0.increment)==sign(rangeData.mode0.final-rangeData.mode0.initial))?fabs(rangeData.mode0.final-rangeData.mode0.initial):0;
00143 case 1:return rangeData.mode1.final-rangeData.mode1.initial;
00144 case 2:return rangeData.mode2.aperture;
00145 default:throw std::logic_error("Unknown range type.");
00146 }
00147 }
00148
00149
00150
00151
00152 inline double initialValue() const {
00153 switch (rangeType) {
00154 case 0:
00155 case 1:return rangeData.mode0.initial;
00156 case 2:return rangeData.mode2.negToPos?-rangeData.mode2.aperture/2:rangeData.mode2.aperture/2;
00157 default:throw std::logic_error("Unknown range type.");
00158 }
00159 }
00160
00161
00162
00163
00164 inline double finalValue() const {
00165 switch (rangeType) {
00166 case 0:return (sign(rangeData.mode0.increment)==sign(rangeData.mode0.final-rangeData.mode0.initial))?rangeData.mode0.final:rangeData.mode0.initial;
00167 case 1:return rangeData.mode1.final;
00168 case 2:return rangeData.mode2.negToPos?rangeData.mode2.aperture/2:-rangeData.mode2.aperture/2;
00169 default:throw std::logic_error("Unknown range type.");
00170 }
00171 }
00172
00173
00174
00175
00176 inline double increment() const {
00177 switch (rangeType) {
00178 case 0:return rangeData.mode0.increment;
00179 case 1:return (rangeData.mode1.final-rangeData.mode1.initial)/static_cast<double>(rangeData.mode1.amount-1);
00180 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);
00181 default:throw std::logic_error("Unknown range type.");
00182 }
00183 }
00184
00185
00186
00187
00188 inline size_t amount() const {
00189 switch (rangeType) {
00190 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;
00191 case 1:return rangeData.mode1.amount;
00192 case 2:return rangeData.mode2.amount;
00193 default:throw std::logic_error("Unknown range type.");
00194 }
00195 }
00196
00197
00198
00199
00200 void values(vector_double &vals) const;
00201
00202
00203
00204
00205 inline bool negToPos() const {
00206 switch (rangeType) {
00207 case 0:return sign(rangeData.mode0.increment)>0;
00208 case 1:return sign(rangeData.mode1.final-rangeData.mode1.initial)>0;
00209 case 2:return rangeData.mode2.negToPos;
00210 default:throw std::logic_error("Unknown range type.");
00211 }
00212 }
00213 };
00214 protected:
00215
00216
00217
00218 void updateMesh() const;
00219
00220
00221
00222 virtual ~CAngularObservationMesh() {}
00223
00224
00225
00226 mutable std::vector<CSetOfTriangles::TTriangle> triangles;
00227
00228
00229
00230 void addTriangle(const TPoint3D &p1,const TPoint3D &p2,const TPoint3D &p3) const;
00231
00232
00233
00234 bool mWireframe;
00235
00236
00237
00238 mutable bool meshUpToDate;
00239
00240
00241
00242 bool mEnableTransparency;
00243
00244
00245
00246 mutable mrpt::math::CMatrixTemplate<TPoint3D> actualMesh;
00247
00248
00249
00250 mutable mrpt::math::CMatrixB validityMatrix;
00251
00252
00253
00254 vector<double> pitchBounds;
00255
00256
00257
00258 vector<CObservation2DRangeScan> scanSet;
00259
00260
00261
00262 CAngularObservationMesh():mWireframe(true),meshUpToDate(false),mEnableTransparency(true),actualMesh(0,0),validityMatrix(0,0),pitchBounds(),scanSet() {}
00263 public:
00264
00265
00266
00267 inline bool isWireframe() const {
00268 return mWireframe;
00269 }
00270
00271
00272
00273 inline void setWireframe(bool enabled=true) {
00274 mWireframe=enabled;
00275 }
00276
00277
00278
00279 inline bool isTransparencyEnabled() const {
00280 return mEnableTransparency;
00281 }
00282
00283
00284
00285 inline void enableTransparency(bool enabled=true) {
00286 mEnableTransparency=enabled;
00287 }
00288
00289
00290
00291
00292 virtual void render() const;
00293
00294
00295
00296
00297 virtual bool traceRay(const mrpt::poses::CPose3D &o,double &dist) const;
00298
00299
00300
00301 void setPitchBounds(const double initial,const double final);
00302
00303
00304
00305 void setPitchBounds(const std::vector<double> bounds);
00306
00307
00308
00309 void getPitchBounds(double &initial,double &final) const;
00310
00311
00312
00313 void getPitchBounds(std::vector<double> &bounds) const;
00314
00315
00316
00317 void getScanSet(std::vector<CObservation2DRangeScan> &scans) const;
00318
00319
00320
00321 bool setScanSet(const std::vector<CObservation2DRangeScan> &scans);
00322
00323
00324
00325
00326 void generateSetOfTriangles(CSetOfTrianglesPtr &res) const;
00327
00328
00329
00330 void generatePointCloud(CPointsMap *out_map) const;
00331
00332
00333
00334
00335 void getTracedRays(CSetOfLinesPtr &res) const;
00336
00337
00338
00339
00340 void getUntracedRays(CSetOfLinesPtr &res,double dist) const;
00341
00342
00343
00344
00345 void generateSetOfTriangles(std::vector<TPolygon3D> &res) const;
00346
00347
00348
00349 void getActualMesh(mrpt::math::CMatrixTemplate<mrpt::math::TPoint3D> &pts,mrpt::math::CMatrixBool &validity) const {
00350 if (!meshUpToDate) updateMesh();
00351 pts=actualMesh;
00352 validity=validityMatrix;
00353 }
00354 private:
00355
00356
00357
00358 template<class T> class FTrace1D {
00359 protected:
00360 const CPose3D &initial;
00361 const T &e;
00362 vector<double> &values;
00363 std::vector<char> &valid;
00364 public:
00365 FTrace1D(const T &s,const CPose3D &p,vector_double &v,std::vector<char> &v2):initial(p),e(s),values(v),valid(v2) {}
00366 void operator()(double yaw) {
00367 double dist;
00368 const CPose3D pNew=initial+CPose3D(0.0,0.0,0.0,yaw,0.0,0.0);
00369 if (e->traceRay(pNew,dist)) {
00370 values.push_back(dist);
00371 valid.push_back(1);
00372 } else {
00373 values.push_back(0);
00374 valid.push_back(0);
00375 }
00376 }
00377 };
00378
00379
00380
00381 template<class T> class FTrace2D {
00382 protected:
00383 const T &e;
00384 const CPose3D &initial;
00385 CAngularObservationMeshPtr &caom;
00386 const CAngularObservationMesh::TDoubleRange &yaws;
00387 std::vector<CObservation2DRangeScan> &vObs;
00388 const CPose3D &pBase;
00389 public:
00390 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) {}
00391 void operator()(double pitch) {
00392 vector_double yValues;
00393 yaws.values(yValues);
00394 CObservation2DRangeScan o=CObservation2DRangeScan();
00395 const CPose3D pNew=initial+CPose3D(0,0,0,0,pitch,0);
00396 vector_double values;
00397 std::vector<char> valid;
00398 size_t nY=yValues.size();
00399 values.reserve(nY);
00400 valid.reserve(nY);
00401 for_each(yValues.begin(),yValues.end(),FTrace1D<T>(e,pNew,values,valid));
00402 o.aperture=yaws.aperture();
00403 o.rightToLeft=yaws.negToPos();
00404 o.maxRange=10000;
00405 o.sensorPose=pNew;
00406 o.deltaPitch=0;
00407 mrpt::utils::copy_container_typecasting(values,o.scan);
00408 o.validRange=valid;
00409 vObs.push_back(o);
00410 }
00411 };
00412 public:
00413
00414
00415
00416
00417
00418 template<class T> static void trace2DSetOfRays(const T &e,const CPose3D &initial,CAngularObservationMeshPtr &caom,const TDoubleRange &pitchs,const TDoubleRange &yaws) {
00419 vector_double pValues;
00420 pitchs.values(pValues);
00421 std::vector<CObservation2DRangeScan> vObs;
00422 vObs.reserve(pValues.size());
00423 for_each(pValues.begin(),pValues.end(),FTrace2D<T>(e,initial,caom,yaws,vObs,initial));
00424 caom->mWireframe=false;
00425 caom->mEnableTransparency=false;
00426 caom->setPitchBounds(pValues);
00427 caom->setScanSet(vObs);
00428 }
00429
00430
00431
00432
00433
00434 template<class T> static void trace1DSetOfRays(const T &e,const CPose3D &initial,CObservation2DRangeScan &obs,const TDoubleRange &yaws) {
00435 vector_double yValues;
00436 yaws.values(yValues);
00437 vector_double scanValues;
00438 std::vector<char> valid;
00439 size_t nV=yaws.amount();
00440 scanValues.reserve(nV);
00441 valid.reserve(nV);
00442 for_each(yValues.begin(),yValues.end(),FTrace1D<T>(e,initial,scanValues,valid));
00443 obs.aperture=yaws.aperture();
00444 obs.rightToLeft=yaws.negToPos();
00445 obs.maxRange=10000;
00446 obs.sensorPose=initial;
00447 obs.deltaPitch=0;
00448 obs.scan=scanValues;
00449 obs.validRange=valid;
00450 }
00451 };
00452 }
00453 }
00454 #endif