Point Cloud Library (PCL)
1.7.0
|
00001 /* 00002 * Software License Agreement (BSD License) 00003 * 00004 * Copyright (c) 2011, Willow Garage, Inc. 00005 * All rights reserved. 00006 * 00007 * Redistribution and use in source and binary forms, with or without 00008 * modification, are permitted provided that the following conditions 00009 * are met: 00010 * 00011 * * Redistributions of source code must retain the above copyright 00012 * notice, this list of conditions and the following disclaimer. 00013 * * Redistributions in binary form must reproduce the above 00014 * copyright notice, this list of conditions and the following 00015 * disclaimer in the documentation and/or other materials provided 00016 * with the distribution. 00017 * * Neither the name of the copyright holder(s) nor the names of its 00018 * contributors may be used to endorse or promote products derived 00019 * from this software without specific prior written permission. 00020 * 00021 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00022 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00023 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00024 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00025 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00026 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00027 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00028 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00029 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00030 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00031 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00032 * POSSIBILITY OF SUCH DAMAGE. 00033 */ 00034 00035 #include <pcl/pcl_config.h> 00036 00037 #ifndef __PCL_IO_GRABBER__ 00038 #define __PCL_IO_GRABBER__ 00039 00040 // needed for the grabber interface / observers 00041 #include <map> 00042 #include <iostream> 00043 #include <string> 00044 #include <typeinfo> 00045 #include <vector> 00046 #include <sstream> 00047 #include <pcl/pcl_macros.h> 00048 #include <pcl/io/boost.h> 00049 #include <pcl/exceptions.h> 00050 00051 namespace pcl 00052 { 00053 00054 /** \brief Grabber interface for PCL 1.x device drivers 00055 * \author Suat Gedikli <gedikli@willowgarage.com> 00056 * \ingroup io 00057 */ 00058 class PCL_EXPORTS Grabber 00059 { 00060 public: 00061 00062 /** \brief Constructor. */ 00063 Grabber () : signals_ (), connections_ (), shared_connections_ () {} 00064 00065 /** \brief virtual desctructor. */ 00066 virtual inline ~Grabber () throw (); 00067 00068 /** \brief registers a callback function/method to a signal with the corresponding signature 00069 * \param[in] callback: the callback function/method 00070 * \return Connection object, that can be used to disconnect the callback method from the signal again. 00071 */ 00072 template<typename T> boost::signals2::connection 00073 registerCallback (const boost::function<T>& callback); 00074 00075 /** \brief indicates whether a signal with given parameter-type exists or not 00076 * \return true if signal exists, false otherwise 00077 */ 00078 template<typename T> bool 00079 providesCallback () const; 00080 00081 /** \brief For devices that are streaming, the streams are started by calling this method. 00082 * Trigger-based devices, just trigger the device once for each call of start. 00083 */ 00084 virtual void 00085 start () = 0; 00086 00087 /** \brief For devices that are streaming, the streams are stopped. 00088 * This method has no effect for triggered devices. 00089 */ 00090 virtual void 00091 stop () = 0; 00092 00093 /** \brief returns the name of the concrete subclass. 00094 * \return the name of the concrete driver. 00095 */ 00096 virtual std::string 00097 getName () const = 0; 00098 00099 /** \brief Indicates whether the grabber is streaming or not. This value is not defined for triggered devices. 00100 * \return true if grabber is running / streaming. False otherwise. 00101 */ 00102 virtual bool 00103 isRunning () const = 0; 00104 00105 /** \brief returns fps. 0 if trigger based. */ 00106 virtual float 00107 getFramesPerSecond () const = 0; 00108 00109 protected: 00110 00111 virtual void 00112 signalsChanged () { } 00113 00114 template<typename T> boost::signals2::signal<T>* 00115 find_signal () const; 00116 00117 template<typename T> int 00118 num_slots () const; 00119 00120 template<typename T> void 00121 disconnect_all_slots (); 00122 00123 template<typename T> void 00124 block_signal (); 00125 00126 template<typename T> void 00127 unblock_signal (); 00128 00129 inline void 00130 block_signals (); 00131 00132 inline void 00133 unblock_signals (); 00134 00135 template<typename T> boost::signals2::signal<T>* 00136 createSignal (); 00137 00138 std::map<std::string, boost::signals2::signal_base*> signals_; 00139 std::map<std::string, std::vector<boost::signals2::connection> > connections_; 00140 std::map<std::string, std::vector<boost::signals2::shared_connection_block> > shared_connections_; 00141 } ; 00142 00143 Grabber::~Grabber () throw () 00144 { 00145 for (std::map<std::string, boost::signals2::signal_base*>::iterator signal_it = signals_.begin (); signal_it != signals_.end (); ++signal_it) 00146 delete signal_it->second; 00147 } 00148 00149 template<typename T> boost::signals2::signal<T>* 00150 Grabber::find_signal () const 00151 { 00152 typedef boost::signals2::signal<T> Signal; 00153 00154 std::map<std::string, boost::signals2::signal_base*>::const_iterator signal_it = signals_.find (typeid (T).name ()); 00155 if (signal_it != signals_.end ()) 00156 return (dynamic_cast<Signal*> (signal_it->second)); 00157 00158 return (NULL); 00159 } 00160 00161 template<typename T> void 00162 Grabber::disconnect_all_slots () 00163 { 00164 typedef boost::signals2::signal<T> Signal; 00165 00166 if (signals_.find (typeid (T).name ()) != signals_.end ()) 00167 { 00168 Signal* signal = dynamic_cast<Signal*> (signals_[typeid (T).name ()]); 00169 signal->disconnect_all_slots (); 00170 } 00171 } 00172 00173 template<typename T> void 00174 Grabber::block_signal () 00175 { 00176 if (connections_.find (typeid (T).name ()) != connections_.end ()) 00177 for (std::vector<boost::signals2::shared_connection_block>::iterator cIt = shared_connections_[typeid (T).name ()].begin (); cIt != shared_connections_[typeid (T).name ()].end (); ++cIt) 00178 cIt->block (); 00179 } 00180 00181 template<typename T> void 00182 Grabber::unblock_signal () 00183 { 00184 if (connections_.find (typeid (T).name ()) != connections_.end ()) 00185 for (std::vector<boost::signals2::shared_connection_block>::iterator cIt = shared_connections_[typeid (T).name ()].begin (); cIt != shared_connections_[typeid (T).name ()].end (); ++cIt) 00186 cIt->unblock (); 00187 } 00188 00189 void 00190 Grabber::block_signals () 00191 { 00192 for (std::map<std::string, boost::signals2::signal_base*>::iterator signal_it = signals_.begin (); signal_it != signals_.end (); ++signal_it) 00193 for (std::vector<boost::signals2::shared_connection_block>::iterator cIt = shared_connections_[signal_it->first].begin (); cIt != shared_connections_[signal_it->first].end (); ++cIt) 00194 cIt->block (); 00195 } 00196 00197 void 00198 Grabber::unblock_signals () 00199 { 00200 for (std::map<std::string, boost::signals2::signal_base*>::iterator signal_it = signals_.begin (); signal_it != signals_.end (); ++signal_it) 00201 for (std::vector<boost::signals2::shared_connection_block>::iterator cIt = shared_connections_[signal_it->first].begin (); cIt != shared_connections_[signal_it->first].end (); ++cIt) 00202 cIt->unblock (); 00203 } 00204 00205 template<typename T> int 00206 Grabber::num_slots () const 00207 { 00208 typedef boost::signals2::signal<T> Signal; 00209 00210 // see if we have a signal for this type 00211 std::map<std::string, boost::signals2::signal_base*>::const_iterator signal_it = signals_.find (typeid (T).name ()); 00212 if (signal_it != signals_.end ()) 00213 { 00214 Signal* signal = dynamic_cast<Signal*> (signal_it->second); 00215 return (static_cast<int> (signal->num_slots ())); 00216 } 00217 return (0); 00218 } 00219 00220 template<typename T> boost::signals2::signal<T>* 00221 Grabber::createSignal () 00222 { 00223 typedef boost::signals2::signal<T> Signal; 00224 00225 if (signals_.find (typeid (T).name ()) == signals_.end ()) 00226 { 00227 Signal* signal = new Signal (); 00228 signals_[typeid (T).name ()] = signal; 00229 return (signal); 00230 } 00231 return (0); 00232 } 00233 00234 template<typename T> boost::signals2::connection 00235 Grabber::registerCallback (const boost::function<T> & callback) 00236 { 00237 typedef boost::signals2::signal<T> Signal; 00238 if (signals_.find (typeid (T).name ()) == signals_.end ()) 00239 { 00240 std::stringstream sstream; 00241 00242 sstream << "no callback for type:" << typeid (T).name (); 00243 /* 00244 sstream << "registered Callbacks are:" << std::endl; 00245 for( std::map<std::string, boost::signals2::signal_base*>::const_iterator cIt = signals_.begin (); 00246 cIt != signals_.end (); ++cIt) 00247 { 00248 sstream << cIt->first << std::endl; 00249 }*/ 00250 00251 PCL_THROW_EXCEPTION (pcl::IOException, "[" << getName () << "] " << sstream.str ()); 00252 //return (boost::signals2::connection ()); 00253 } 00254 Signal* signal = dynamic_cast<Signal*> (signals_[typeid (T).name ()]); 00255 boost::signals2::connection ret = signal->connect (callback); 00256 00257 connections_[typeid (T).name ()].push_back (ret); 00258 shared_connections_[typeid (T).name ()].push_back (boost::signals2::shared_connection_block (connections_[typeid (T).name ()].back (), false)); 00259 signalsChanged (); 00260 return (ret); 00261 } 00262 00263 template<typename T> bool 00264 Grabber::providesCallback () const 00265 { 00266 if (signals_.find (typeid (T).name ()) == signals_.end ()) 00267 return (false); 00268 return (true); 00269 } 00270 00271 } // namespace 00272 00273 #endif