Jafar
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
display.hpp
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     // bufferized slam object data
00034     // +
00035     // display objects
00036       ViewerAbstract *viewer;
00037     public:
00038       DisplayDataAbstract(ViewerAbstract *viewer_): viewer(viewer_) {}
00039       virtual ~DisplayDataAbstract() {}
00040       //virtual void bufferize() = 0; // not virtual, we want to allow inlining, and we are using templates
00041       //virtual void render() = 0; 
00042   };
00043   
00047   class WorldDisplay : public DisplayDataAbstract
00048   {
00049     public:
00050       rtslam::WorldAbstract *slamWor_; // cannot use shared_ptr or it will never be freed
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   // TODO can I give the viewer instead of the parent ? it may decide
00164   //template<class Render = RenderAbstract>
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         // add the object to the list
00177         slamObjects_.push_back(slamObject);
00178         // if the array hasn't been created
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         // if the object hasn't been created
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         // bufferize the object
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       //static kernel::IdFactory idFactory_;
00213       //kernel::IdFactory::storage_t id_;
00214       
00215     public:
00216       //ViewerAbstract(): id_(idFactory().getId()-1) {}
00217       //virtual ~ViewerAbstract() { idFactory().releaseId(id_); }
00218       virtual ~ViewerAbstract() {}
00223       //virtual void bufferize(rtslam::map_ptr_t _map) = 0;
00224 //      virtual void render() = 0;
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       //template<class RobotDisplayType, class SensorDisplayType, class LandmarkDisplayType, class ObservationDisplayType>
00273       class Render : public boost::static_visitor<>// : public RenderAbstract
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       //virtual void garbageCollect() = 0;
00333       
00337       inline void bufferize(rtslam::world_ptr_t wor)
00338       {
00339         // bufferize world
00340         if (!boost::is_same<WorldDisplayType,WorldDisplay>::value) // bufferize world
00341           bufferizeObject<WorldDisplayType, WorldDisplayType, world_ptr_t, world_ptr_t>(wor, wor, id());
00342         // bufferize maps
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         // bufferize map
00350         if (!boost::is_same<MapDisplayType,MapDisplay>::value)
00351           bufferizeObject<MapDisplayType, WorldDisplayType, map_ptr_t, world_ptr_t>(map, wor, id());
00352         // bufferize robots
00353         for(MapAbstract::RobotList::iterator rob = map->robotList().begin(); rob != map->robotList().end(); ++rob)
00354           bufferize(*rob,map);
00355         // bufferize landmarks
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         // bufferize robot
00364         if (!boost::is_same<RobotDisplayType,RobotDisplay>::value)
00365           bufferizeObject<RobotDisplayType, MapDisplayType, robot_ptr_t, map_ptr_t>(rob, map, id());
00366         // bufferize exteroceptive sensors
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         // bufferize sensor
00378         if (!boost::is_same<SensorDisplayType,SensorDisplay>::value)
00379           bufferizeObject<SensorDisplayType, RobotDisplayType, sensorext_ptr_t, robot_ptr_t>(sen, rob, id());
00380         // bufferize observations
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         // bufferize observationbufferizeObject
00389         if (!boost::is_same<ObservationDisplayType,ObservationDisplay>::value) // bufferize observation
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         // bufferize landmark
00396         if (!boost::is_same<LandmarkDisplayType,LandmarkDisplay>::value) // bufferize landmark
00397           bufferizeObject<LandmarkDisplayType, MapDisplayType, landmark_ptr_t, map_ptr_t>(lmk, map, id());
00398       }
00399       
00400       
00401 
00406       void render()
00407       {
00408         /*
00409         We need to clear at the end, because we must clear before bufferize, 
00410         and bufferize is called by the slam thread so it cannot call it.
00411         But then when if a landmark is destroyed, it is immediatly destroyed
00412         as it is not retained by this list, so the display object is also destroyed,
00413         and it is not thread safe. So when the display object is destroyed, display lib objects
00414         are just moved to the garbage collector, and destroyed by this thread before the next rendering.
00415         Anyway destroying the object can be long so it is better to do it here.
00416         Maybe it is not neccessary anymore to have a vector of variants here, but just
00417         a vector of display data.
00418         */
00419         this->garbageCollect(); // strange, the "this" is necessary...
00420         for(SlamObjectsList::iterator it = slamObjects_.begin(); it != slamObjects_.end(); ++it)
00421         {
00422           boost::apply_visitor(Render(), *it);
00423         }
00424         // clear viewer
00425         clear();
00426       }
00427       
00428   };
00429 
00430   /*
00431     typedef enum lmk_state {
00432       lmk_state_init,
00433       lmk_state_converged
00434     } lmk_state ;
00435 
00436     typedef enum lmk_events {
00437       lmk_events_not_predicted,
00438       lmk_events_predicted,
00439       lmk_events_matched,
00440       lmk_events_updated
00441     } lmk_events ;
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     static color getColorObject_prediction(lmk_state lmk_state, lmk_events lmk_events) {
00516 
00517       if (lmk_state==lmk_state_init) {
00518         switch (lmk_events) {
00519           case lmk_events_not_predicted:
00520             return color_transparency;
00521           case lmk_events_predicted:
00522             return color_magenta;
00523           case lmk_events_matched:
00524             return color_magenta;
00525           case lmk_events_updated:
00526             return color_red;
00527           default:
00528             std::cout << __FILE__ << ":" << __LINE__ << "Unknown lmk lmk_events " << lmk_events << std::endl;
00529             break;
00530         }
00531       }
00532       if (lmk_state==lmk_state_converged) {
00533         switch (lmk_events) {
00534           case lmk_events_not_predicted:
00535             return color_transparency;
00536           case lmk_events_predicted:
00537             return color_blue;
00538           case lmk_events_matched:
00539             return color_blue;
00540           case lmk_events_updated:
00541             return color_cyan;
00542           default:
00543             std::cout << __FILE__ << ":" << __LINE__ << "Unknown lmk lmk_events " << lmk_events << std::endl;
00544             break;
00545         }
00546       }
00547       cout << "warning color undefined for object types in display" << endl ;
00548       return color_transparency;
00549     }
00550 
00551     static color getColorObject_measure    (lmk_state lmk_state, lmk_events lmk_events) {
00552       if (lmk_state==lmk_state_init) {
00553         switch (lmk_events) {
00554           case lmk_events_not_predicted:
00555             return color_yellow;
00556           case lmk_events_predicted:
00557             return color_orange;
00558           case lmk_events_matched:
00559             return color_yellow;
00560           case lmk_events_updated:
00561             return color_yellow;
00562           default:
00563             std::cout << __FILE__ << ":" << __LINE__ << " Unknown lmk lmk_events " << lmk_events << std::endl;
00564             break;
00565         }
00566       }
00567       if (lmk_state==lmk_state_converged) {
00568         switch (lmk_events) {
00569           case lmk_events_not_predicted:
00570             return color_transparency;
00571           case lmk_events_predicted:
00572             return color_orange;
00573           case lmk_events_matched:
00574             return color_yellow;
00575           case lmk_events_updated:
00576             return color_yellow;
00577           default:
00578             std::cout << __FILE__ << ":" << __LINE__ << " Unknown lmk lmk_events " << lmk_events << std::endl;
00579             break;
00580         }
00581       }
00582       cout << "warning color undefined for object types in display" << endl ;
00583       return color_transparency;
00584     }
00585 */
00586     colorRGB getColorRGB(color colorOrigin);
00587 
00588 }}}
00589 
00590 
00591 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on Wed Oct 15 2014 00:37:18 for Jafar by doxygen 1.7.6.1
LAAS-CNRS