00001
00009 #ifndef DISPLAY_HPP_
00010 #define DISPLAY_HPP_
00011
00012 #include "rtslam/observationPinHoleEuclideanPoint.hpp"
00013 #include "rtslam/landmarkEuclideanPoint.hpp"
00014 #include "rtslam/sensorPinhole.hpp"
00015 #include "rtslam/robotAbstract.hpp"
00016
00017 #include "kernel/IdFactory.hpp"
00018 #include "boost/variant.hpp"
00019 #include <boost/type_traits/is_same.hpp>
00020
00021 namespace jafar {
00022 namespace rtslam {
00023 namespace display {
00024
00025 class ViewerAbstract;
00026
00031 class DisplayDataAbstract
00032 {
00033
00034
00035
00036 ViewerAbstract *viewer;
00037 public:
00038 DisplayDataAbstract(ViewerAbstract *viewer_): viewer(viewer_) {}
00039 virtual ~DisplayDataAbstract() {}
00040
00041
00042 };
00043
00047 class WorldDisplay : public DisplayDataAbstract
00048 {
00049 public:
00050 rtslam::WorldAbstract *slamWor_;
00051 WorldDisplay(ViewerAbstract *viewer_, rtslam::WorldAbstract *_slamWor, WorldDisplay *_garbage):
00052 DisplayDataAbstract(viewer_), slamWor_(_slamWor) {}
00053 };
00054
00058 class MapDisplay : public DisplayDataAbstract
00059 {
00060 public:
00061 rtslam::MapAbstract *slamMap_;
00062 WorldDisplay *dispWorld_;
00063 MapDisplay(ViewerAbstract *viewer_, rtslam::MapAbstract *_slamMap, WorldDisplay *_dispWorld):
00064 DisplayDataAbstract(viewer_), slamMap_(_slamMap), dispWorld_(_dispWorld) {}
00065 };
00066
00072 class RobotDisplay : public DisplayDataAbstract
00073 {
00074 public:
00075 rtslam::RobotAbstract *slamRob_;
00076 MapDisplay *dispMap_;
00077 RobotDisplay(ViewerAbstract *viewer_, rtslam::RobotAbstract *_slamRob, MapDisplay *_dispMap):
00078 DisplayDataAbstract(viewer_), slamRob_(_slamRob), dispMap_(_dispMap) {}
00079 };
00080
00086 class SensorDisplay : public DisplayDataAbstract
00087 {
00088 public:
00089 rtslam::SensorExteroAbstract *slamSen_;
00090 RobotDisplay *dispRobot_;
00091 SensorAbstract::type_enum type_;
00092 SensorDisplay(ViewerAbstract *viewer_, rtslam::SensorExteroAbstract *_slamSen, RobotDisplay *_dispRobot):
00093 DisplayDataAbstract(viewer_), slamSen_(_slamSen), dispRobot_(_dispRobot), type_(_slamSen->type) {}
00094 };
00095
00101 class LandmarkDisplay : public DisplayDataAbstract
00102 {
00103 public:
00104 rtslam::LandmarkAbstract *slamLmk_;
00105 MapDisplay *dispMap_;
00106 enum Type { ltPoint, ltSeg };
00107 enum Phase { init, converged };
00108 Type type_;
00109 Phase phase_;
00110 static Type convertType(rtslam::LandmarkAbstract *_slamLmk)
00111 {
00112 switch (_slamLmk->getGeomType())
00113 {
00114 case rtslam::LandmarkAbstract::POINT:
00115 return ltPoint;
00116 case rtslam::LandmarkAbstract::LINE:
00117 return ltSeg;
00118 default:
00119 JFR_ERROR(RtslamException, RtslamException::UNKNOWN_FEATURE_TYPE, "Don't know how to display this type of landmark" << _slamLmk->getGeomType());
00120 }
00121 }
00122 static Phase convertPhase(rtslam::LandmarkAbstract *_slamLmk)
00123 {
00124 switch (_slamLmk->type)
00125 {
00126 case rtslam::LandmarkAbstract::PNT_EUC:
00127 return converged;
00128 default:
00129 return init;
00130 }
00131 }
00132 LandmarkDisplay(ViewerAbstract *viewer_, rtslam::LandmarkAbstract *_slamLmk, MapDisplay *_dispMap):
00133 DisplayDataAbstract(viewer_), slamLmk_(_slamLmk), dispMap_(_dispMap),
00134 type_(convertType(_slamLmk)), phase_(convertPhase(_slamLmk)) {}
00135 };
00136
00137
00143 class ObservationDisplay : public DisplayDataAbstract
00144 {
00145 public:
00146 rtslam::ObservationAbstract *slamObs_;
00147 SensorDisplay *dispSen_;
00148 SensorAbstract::type_enum sensorType_;
00149 LandmarkDisplay::Type landmarkGeomType_;
00150 LandmarkDisplay::Phase landmarkPhase_;
00151 ObservationDisplay(ViewerAbstract *viewer_, rtslam::ObservationAbstract *_slamObs, SensorDisplay *_dispSen):
00152 DisplayDataAbstract(viewer_), slamObs_(_slamObs), dispSen_(_dispSen)
00153 {
00154 sensorType_ = _slamObs->sensorPtr()->type;
00155 landmarkGeomType_ = LandmarkDisplay::convertType(&*_slamObs->landmarkPtr());
00156 landmarkPhase_ = LandmarkDisplay::convertPhase(&*_slamObs->landmarkPtr());
00157 }
00158 };
00159
00160
00164
00165 class ViewerAbstract
00166 {
00167 protected:
00168 typedef boost::variant<rtslam::world_ptr_t, rtslam::map_ptr_t, rtslam::robot_ptr_t,
00169 rtslam::sensorext_ptr_t, rtslam::landmark_ptr_t, rtslam::observation_ptr_t> SlamObjectPtr;
00170 typedef std::vector<SlamObjectPtr> SlamObjectsList;
00171 SlamObjectsList slamObjects_;
00172
00173 template<class DisplayType, class ParentDisplayType, class SlamPtrType, class ParentSlamPtrType>
00174 inline void bufferizeObject(SlamPtrType slamObject, ParentSlamPtrType parentSlam, unsigned int id)
00175 {
00176
00177 slamObjects_.push_back(slamObject);
00178
00179 if (slamObject->displayData.size() <= id)
00180 {
00181 int oldsize = slamObject->displayData.size();
00182 slamObject->displayData.resize(id+1);
00183 for(unsigned int i = oldsize; i <= id; ++i)
00184 slamObject->displayData[i] = NULL;
00185 }
00186
00187 if (slamObject->displayData[id] == NULL)
00188 {
00189 ParentDisplayType *parentDisp;
00190 if (boost::is_same<ParentDisplayType,MapDisplay>::value)
00191 parentDisp = NULL;
00192 else
00193 {
00194 if (parentSlam->displayData.size() <= id)
00195 parentDisp = NULL;
00196 else
00197 parentDisp = PTR_CAST<ParentDisplayType*>(parentSlam->displayData[id]);
00198 }
00199 slamObject->displayData[id] = new DisplayType(this, &*slamObject, parentDisp);
00200 }
00201
00202 DisplayType *objDisp = PTR_CAST<DisplayType*>(slamObject->displayData[id]);
00203 objDisp->bufferize();
00204 }
00205
00206 public:
00207 static IdFactory& idFactory()
00208 {
00209 static IdFactory idFactory_;
00210 return idFactory_;
00211 }
00212
00213
00214
00215 public:
00216
00217
00218 virtual ~ViewerAbstract() {}
00223
00224
00225 };
00226
00227
00233 template <typename T>
00234 class ThreadSafeGarbageCollector
00235 {
00236 private:
00237 int gcn;
00238 std::vector<T> gc[2];
00239 boost::mutex m;
00240 struct Destroy : public boost::static_visitor<>
00241 { template<typename U> void operator()(U *item) const { delete item; } };
00242 public:
00243 ThreadSafeGarbageCollector(): gcn(0) {}
00244 template<typename U> void release(U *item)
00245 {
00246 boost::unique_lock<boost::mutex> lock(m);
00247 gc[gcn].push_back(item);
00248 }
00249 void garbageCollect()
00250 {
00251 boost::unique_lock<boost::mutex> lock(m);
00252 std::vector<T> &mygc = gc[gcn];
00253 gcn = 1-gcn;
00254 lock.unlock();
00255
00256 for(typename std::vector<T>::iterator it = mygc.begin(); it != mygc.end(); ++it)
00257 boost::apply_visitor(Destroy(), *it);
00258 mygc.clear();
00259 }
00260 };
00261
00262
00267 template<class WorldDisplayType, class MapDisplayType, class RobotDisplayType,
00268 class SensorDisplayType, class LandmarkDisplayType, class ObservationDisplayType, class GarbageType>
00269 class Viewer : public ViewerAbstract, public ThreadSafeGarbageCollector<GarbageType>
00270 {
00271 protected:
00272
00273 class Render : public boost::static_visitor<>
00274 {
00275 public:
00276 typedef Viewer<WorldDisplayType, MapDisplayType, RobotDisplayType,
00277 SensorDisplayType, LandmarkDisplayType, ObservationDisplayType, GarbageType> MyViewer;
00278
00279 void operator()(rtslam::world_ptr_t const &wor) const {
00280 if (!boost::is_same<WorldDisplayType,WorldDisplay>::value) {
00281 WorldDisplayType &worDisp = *PTR_CAST<WorldDisplayType*>(wor->displayData[MyViewer::id()]);
00282 worDisp.render();
00283 }
00284 }
00285 void operator()(rtslam::map_ptr_t const &map) const {
00286 if (!boost::is_same<MapDisplayType,MapDisplay>::value) {
00287 MapDisplayType &mapDisp = *PTR_CAST<MapDisplayType*>(map->displayData[MyViewer::id()]);
00288 mapDisp.render();
00289 }
00290 }
00291 void operator()(rtslam::robot_ptr_t const &rob) const {
00292 if (!boost::is_same<RobotDisplayType,RobotDisplay>::value) {
00293 RobotDisplayType &robDisp = *PTR_CAST<RobotDisplayType*>(rob->displayData[MyViewer::id()]);
00294 robDisp.render();
00295 }
00296 }
00297 void operator()(rtslam::sensorext_ptr_t const &sen) const {
00298 if (!boost::is_same<SensorDisplayType,SensorDisplay>::value) {
00299 SensorDisplayType &senDisp = *PTR_CAST<SensorDisplayType*>(sen->displayData[MyViewer::id()]);
00300 senDisp.render();
00301 }
00302 }
00303 void operator()(rtslam::landmark_ptr_t const &lmk) const {
00304 if (!boost::is_same<LandmarkDisplayType,LandmarkDisplay>::value) {
00305 LandmarkDisplayType &lmkDisp = *PTR_CAST<LandmarkDisplayType*>(lmk->displayData[MyViewer::id()]);
00306 lmkDisp.render();
00307 }
00308 }
00309 void operator()(rtslam::observation_ptr_t const &obs) const {
00310 if (!boost::is_same<ObservationDisplayType,ObservationDisplay>::value) {
00311 ObservationDisplayType &obsDisp = *PTR_CAST<ObservationDisplayType*>(obs->displayData[MyViewer::id()]);
00312 obsDisp.render();
00313 }
00314 }
00315 };
00316
00317
00318 public:
00319 static IdFactory::storage_t& id()
00320 {
00321 static IdFactory::storage_t id = ViewerAbstract::idFactory().getId()-1;
00322 return id;
00323 }
00324
00325 public:
00326 ~Viewer() { this->garbageCollect(); }
00327 inline void clear()
00328 {
00329 slamObjects_.clear();
00330 }
00331
00332
00333
00337 inline void bufferize(rtslam::world_ptr_t wor)
00338 {
00339
00340 if (!boost::is_same<WorldDisplayType,WorldDisplay>::value)
00341 bufferizeObject<WorldDisplayType, WorldDisplayType, world_ptr_t, world_ptr_t>(wor, wor, id());
00342
00343 for(WorldAbstract::MapList::iterator map = wor->mapList().begin(); map != wor->mapList().end(); ++map)
00344 bufferize(*map, wor);
00345 }
00346
00347 inline void bufferize(rtslam::map_ptr_t map, rtslam::world_ptr_t wor)
00348 {
00349
00350 if (!boost::is_same<MapDisplayType,MapDisplay>::value)
00351 bufferizeObject<MapDisplayType, WorldDisplayType, map_ptr_t, world_ptr_t>(map, wor, id());
00352
00353 for(MapAbstract::RobotList::iterator rob = map->robotList().begin(); rob != map->robotList().end(); ++rob)
00354 bufferize(*rob,map);
00355
00356 for(MapAbstract::MapManagerList::iterator mm = map->mapManagerList().begin(); mm!=map->mapManagerList().end(); ++mm )
00357 for(MapManagerAbstract::LandmarkList::iterator lmk = (*mm)->landmarkList().begin(); lmk != (*mm)->landmarkList().end(); ++lmk)
00358 bufferize(*lmk,map);
00359 }
00360
00361 inline void bufferize(rtslam::robot_ptr_t rob, rtslam::map_ptr_t map)
00362 {
00363
00364 if (!boost::is_same<RobotDisplayType,RobotDisplay>::value)
00365 bufferizeObject<RobotDisplayType, MapDisplayType, robot_ptr_t, map_ptr_t>(rob, map, id());
00366
00367 for(RobotAbstract::SensorList::iterator sen = rob->sensorList().begin(); sen != rob->sensorList().end(); ++sen)
00368 if ((*sen)->kind == SensorAbstract::EXTEROCEPTIVE)
00369 {
00370 sensorext_ptr_t senPtr = SPTR_CAST<SensorExteroAbstract>(*sen);
00371 bufferize(senPtr,rob);
00372 }
00373 }
00374
00375 inline void bufferize(rtslam::sensorext_ptr_t sen, rtslam::robot_ptr_t rob)
00376 {
00377
00378 if (!boost::is_same<SensorDisplayType,SensorDisplay>::value)
00379 bufferizeObject<SensorDisplayType, RobotDisplayType, sensorext_ptr_t, robot_ptr_t>(sen, rob, id());
00380
00381 for(SensorExteroAbstract::DataManagerList::iterator dma = sen->dataManagerList().begin(); dma!=sen->dataManagerList().end();++dma)
00382 for(LandmarkAbstract::ObservationList::iterator obs = (*dma)->observationList().begin(); obs != (*dma)->observationList().end(); ++obs)
00383 bufferize(*obs,sen);
00384 }
00385
00386 inline void bufferize(rtslam::observation_ptr_t obs, rtslam::sensorext_ptr_t sen)
00387 {
00388
00389 if (!boost::is_same<ObservationDisplayType,ObservationDisplay>::value)
00390 bufferizeObject<ObservationDisplayType, SensorDisplayType, observation_ptr_t, sensorext_ptr_t>(obs, sen, id());
00391 }
00392
00393 inline void bufferize(rtslam::landmark_ptr_t lmk, rtslam::map_ptr_t map)
00394 {
00395
00396 if (!boost::is_same<LandmarkDisplayType,LandmarkDisplay>::value)
00397 bufferizeObject<LandmarkDisplayType, MapDisplayType, landmark_ptr_t, map_ptr_t>(lmk, map, id());
00398 }
00399
00400
00401
00406 void render()
00407 {
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419 this->garbageCollect();
00420 for(SlamObjectsList::iterator it = slamObjects_.begin(); it != slamObjects_.end(); ++it)
00421 {
00422 boost::apply_visitor(Render(), *it);
00423 }
00424
00425 clear();
00426 }
00427
00428 };
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443 typedef enum color {
00444 color_transparency,
00445 color_yellow,
00446 color_magenta,
00447 color_darkred,
00448 color_blue,
00449 color_red,
00450 color_cyan,
00451 color_pink,
00452 color_orange
00453
00454 } color ;
00455
00456 typedef struct colorRGB {
00457 int R, G, B;
00458 void set(int R_, int G_, int B_) { R=R_; G=G_; B=B_; }
00459 } colorRGB ;
00460
00461 class ColorManager
00462 {
00463 public:
00464
00465 static color getColorObject_prediction(LandmarkDisplay::Phase lmk_phase, ObservationAbstract::Events &events)
00466 {
00467 switch(lmk_phase)
00468 {
00469 case LandmarkDisplay::init: {
00470 if (!events.visible) return color_darkred;
00471 if (events.updated) return color_magenta;
00472 if (events.matched) return color_darkred;
00473 if (events.measured) return color_darkred;
00474 if (events.predicted) return color_magenta;
00475 return color_yellow;
00476 }
00477 case LandmarkDisplay::converged: {
00478 if (!events.visible) return color_blue;
00479 if (events.updated) return color_cyan;
00480 if (events.matched) return color_blue;
00481 if (events.measured) return color_blue;
00482 if (events.predicted) return color_cyan;
00483 return color_transparency;
00484 }
00485 default:
00486 std::cout << "getColorObject_prediction: Warning: undefined phase " << lmk_phase << std::endl ;
00487 return color_transparency;
00488 }
00489 }
00490
00491 static color getColorObject_measure(LandmarkDisplay::Phase lmk_phase, ObservationAbstract::Events &events)
00492 {
00493 switch(lmk_phase)
00494 {
00495 case LandmarkDisplay::init: {
00496 if (events.updated) return color_yellow;
00497 if (events.matched) return color_yellow;
00498 if (events.predicted) return color_orange;
00499 return color_yellow;
00500 }
00501 case LandmarkDisplay::converged: {
00502 if (events.updated) return color_yellow;
00503 if (events.matched) return color_yellow;
00504 if (events.predicted) return color_orange;
00505 return color_transparency;
00506 }
00507 default:
00508 std::cout << "getColorObject_measure: Warning: undefined phase " << lmk_phase << std::endl ;
00509 return color_transparency;
00510 }
00511 }
00512 };
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586 colorRGB getColorRGB(color colorOrigin);
00587
00588 }}}
00589
00590
00591 #endif