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
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
00052
00053
00054
00055
00056
00057 class MAPS_IMPEXP CAngularObservationMesh:public CRenderizableDisplayList {
00058 DEFINE_SERIALIZABLE(CAngularObservationMesh)
00059 public:
00060
00061
00062
00063 struct MAPS_IMPEXP TDoubleRange {
00064 private:
00065
00066
00067
00068
00069
00070
00071 char rangeType;
00072
00073
00074
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
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
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
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
00120
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
00128
00129 inline static TDoubleRange CreateFromAmount(double initial,double final,size_t amount) {
00130 return TDoubleRange(initial,final,amount);
00131 }
00132
00133
00134
00135 inline static TDoubleRange CreateFromAperture(double aperture,size_t amount,bool negToPos=true) {
00136 return TDoubleRange(aperture,amount,negToPos);
00137 }
00138
00139
00140
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
00152
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
00164
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
00176
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
00188
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
00200
00201
00202 void values(std::vector<double> &vals) const;
00203
00204
00205
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
00219
00220 void updateMesh() const;
00221
00222
00223
00224 virtual ~CAngularObservationMesh() {}
00225
00226
00227
00228 mutable std::vector<CSetOfTriangles::TTriangle> triangles;
00229
00230
00231
00232 void addTriangle(const TPoint3D &p1,const TPoint3D &p2,const TPoint3D &p3) const;
00233
00234
00235
00236 bool mWireframe;
00237
00238
00239
00240 mutable bool meshUpToDate;
00241
00242
00243
00244 bool mEnableTransparency;
00245
00246
00247
00248 mutable mrpt::math::CMatrixTemplate<TPoint3D> actualMesh;
00249
00250
00251
00252 mutable mrpt::math::CMatrixB validityMatrix;
00253
00254
00255
00256 std::vector<double> pitchBounds;
00257
00258
00259
00260 std::vector<CObservation2DRangeScan> scanSet;
00261
00262
00263
00264 CAngularObservationMesh():mWireframe(true),meshUpToDate(false),mEnableTransparency(true),actualMesh(0,0),validityMatrix(0,0),pitchBounds(),scanSet() {}
00265 public:
00266
00267
00268
00269 inline bool isWireframe() const {
00270 return mWireframe;
00271 }
00272
00273
00274
00275 inline void setWireframe(bool enabled=true) {
00276 mWireframe=enabled;
00277 CRenderizableDisplayList::notifyChange();
00278 }
00279
00280
00281
00282 inline bool isTransparencyEnabled() const {
00283 return mEnableTransparency;
00284 }
00285
00286
00287
00288 inline void enableTransparency(bool enabled=true) {
00289 mEnableTransparency=enabled;
00290 CRenderizableDisplayList::notifyChange();
00291 }
00292
00293
00294
00295
00296 virtual void render_dl() const;
00297
00298
00299
00300
00301 virtual bool traceRay(const mrpt::poses::CPose3D &o,double &dist) const;
00302
00303
00304
00305 void setPitchBounds(const double initial,const double final);
00306
00307
00308
00309 void setPitchBounds(const std::vector<double> bounds);
00310
00311
00312
00313 void getPitchBounds(double &initial,double &final) const;
00314
00315
00316
00317 void getPitchBounds(std::vector<double> &bounds) const;
00318
00319
00320
00321 void getScanSet(std::vector<CObservation2DRangeScan> &scans) const;
00322
00323
00324
00325 bool setScanSet(const std::vector<CObservation2DRangeScan> &scans);
00326
00327
00328
00329
00330 void generateSetOfTriangles(CSetOfTrianglesPtr &res) const;
00331
00332
00333
00334 void generatePointCloud(CPointsMap *out_map) const;
00335
00336
00337
00338
00339 void getTracedRays(CSetOfLinesPtr &res) const;
00340
00341
00342
00343
00344 void getUntracedRays(CSetOfLinesPtr &res,double dist) const;
00345
00346
00347
00348
00349 void generateSetOfTriangles(std::vector<TPolygon3D> &res) const;
00350
00351
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
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
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
00419
00420
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
00435
00436
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