Point Cloud Library (PCL)  1.11.1-dev
grabber.h
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2011, Willow Garage, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above
14  * copyright notice, this list of conditions and the following
15  * disclaimer in the documentation and/or other materials provided
16  * with the distribution.
17  * * Neither the name of the copyright holder(s) nor the names of its
18  * contributors may be used to endorse or promote products derived
19  * from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 #pragma once
36 
37 #include <pcl/pcl_config.h>
38 
39 // needed for the grabber interface / observers
40 #include <map>
41 #include <memory>
42 #include <iostream>
43 #include <string>
44 #include <typeinfo>
45 #include <tuple>
46 #include <vector>
47 #include <sstream>
48 #include <pcl/pcl_macros.h>
49 #include <pcl/io/boost.h>
50 #include <pcl/exceptions.h>
51 
52 namespace pcl
53 {
54 
55  /** \brief Grabber interface for PCL 1.x device drivers
56  * \author Suat Gedikli <gedikli@willowgarage.com>
57  * \ingroup io
58  */
60  {
61  public:
62  /**
63  * \brief Default ctor
64  */
65  Grabber() = default;
66 
67  /**
68  * \brief No copy ctor since Grabber can't be copied
69  */
70  Grabber(const Grabber&) = delete;
71 
72  /**
73  * \brief No copy assign operator since Grabber can't be copied
74  */
75  Grabber& operator=(const Grabber&) = delete;
76 
77  /**
78  * \brief Move ctor
79  */
80  Grabber(Grabber&&) = default;
81 
82  /**
83  * \brief Move assign operator
84  */
85  Grabber& operator=(Grabber&&) = default;
86 
87  /** \brief virtual destructor. */
88  #if defined(_MSC_VER)
89  virtual inline ~Grabber () noexcept {}
90  #else
91  virtual inline ~Grabber () noexcept = default;
92  #endif
93 
94  /** \brief registers a callback function/method to a signal with the corresponding signature
95  * \param[in] callback: the callback function/method
96  * \return Connection object, that can be used to disconnect the callback method from the signal again.
97  */
98  template<typename T> boost::signals2::connection
99  registerCallback (const std::function<T>& callback);
100 
101  /** \brief registers a callback function/method to a signal with the corresponding signature
102  * \param[in] callback: the callback function/method
103  * \return Connection object, that can be used to disconnect the callback method from the signal again.
104  */
105  template<typename T, template<typename> class FunctionT>
106  PCL_DEPRECATED (1, 12, "please assign the callback to a std::function.")
107  boost::signals2::connection
108  registerCallback (const FunctionT<T>& callback)
109  {
110  return registerCallback (std::function<T> (callback));
111  }
112 
113  /** \brief indicates whether a signal with given parameter-type exists or not
114  * \return true if signal exists, false otherwise
115  */
116  template<typename T> bool
117  providesCallback () const noexcept;
118 
119  /** \brief For devices that are streaming, the streams are started by calling this method.
120  * Trigger-based devices, just trigger the device once for each call of start.
121  */
122  virtual void
123  start () = 0;
124 
125  /** \brief For devices that are streaming, the streams are stopped.
126  * This method has no effect for triggered devices.
127  */
128  virtual void
129  stop () = 0;
130 
131  /** \brief For devices that are streaming, stopped streams are started and running stream are stopped.
132  * For triggered devices, the behavior is not defined.
133  * \return true if grabber is running / streaming. False otherwise.
134  */
135  inline bool
136  toggle ();
137 
138  /** \brief returns the name of the concrete subclass.
139  * \return the name of the concrete driver.
140  */
141  virtual std::string
142  getName () const = 0;
143 
144  /** \brief Indicates whether the grabber is streaming or not. This value is not defined for triggered devices.
145  * \return true if grabber is running / streaming. False otherwise.
146  */
147  virtual bool
148  isRunning () const = 0;
149 
150  /** \brief returns fps. 0 if trigger based. */
151  virtual float
152  getFramesPerSecond () const = 0;
153 
154  protected:
155 
156  virtual void
157  signalsChanged () { }
158 
159  template<typename T> boost::signals2::signal<T>*
160  find_signal () const noexcept;
161 
162  template<typename T> int
163  num_slots () const noexcept;
164 
165  template<typename T> void
166  disconnect_all_slots ();
167 
168  template<typename T> void
169  block_signal ();
170 
171  template<typename T> void
172  unblock_signal ();
173 
174  inline void
175  block_signals ();
176 
177  inline void
178  unblock_signals ();
179 
180  template<typename T> boost::signals2::signal<T>*
181  createSignal ();
182 
183  std::map<std::string, std::unique_ptr<boost::signals2::signal_base>> signals_;
184  std::map<std::string, std::vector<boost::signals2::connection> > connections_;
185  std::map<std::string, std::vector<boost::signals2::shared_connection_block> > shared_connections_;
186  } ;
187 
188  bool
189  Grabber::toggle ()
190  {
191  if (isRunning ())
192  {
193  stop ();
194  } else
195  {
196  start ();
197  }
198  return isRunning ();
199  }
200 
201  template<typename T> boost::signals2::signal<T>*
202  Grabber::find_signal () const noexcept
203  {
204  using Signal = boost::signals2::signal<T>;
205 
206  const auto signal_it = signals_.find (typeid (T).name ());
207  if (signal_it != signals_.end ())
208  {
209  return (static_cast<Signal*> (signal_it->second.get ()));
210  }
211  return nullptr;
212  }
213 
214  template<typename T> void
216  {
217  const auto signal = find_signal<T> ();
218  if (signal != nullptr)
219  {
220  signal->disconnect_all_slots ();
221  }
222  }
223 
224  template<typename T> void
226  {
227  if (connections_.find (typeid (T).name ()) != connections_.end ())
228  for (auto &connection : shared_connections_[typeid (T).name ()])
229  connection.block ();
230  }
231 
232  template<typename T> void
234  {
235  if (connections_.find (typeid (T).name ()) != connections_.end ())
236  for (auto &connection : shared_connections_[typeid (T).name ()])
237  connection.unblock ();
238  }
239 
240  void
242  {
243  for (const auto &signal : signals_)
244  for (auto &connection : shared_connections_[signal.first])
245  connection.block ();
246  }
247 
248  void
250  {
251  for (const auto &signal : signals_)
252  for (auto &connection : shared_connections_[signal.first])
253  connection.unblock ();
254  }
255 
256  template<typename T> int
257  Grabber::num_slots () const noexcept
258  {
259  const auto signal = find_signal<T> ();
260  if (signal != nullptr)
261  {
262  return static_cast<int> (signal->num_slots ());
263  }
264  return 0;
265  }
266 
267  template<typename T> boost::signals2::signal<T>*
269  {
270  using Signal = boost::signals2::signal<T>;
271  using Base = boost::signals2::signal_base;
272  // DefferedPtr serves 2 purposes:
273  // * allows MSVC to copy it around, can't do that with unique_ptr<T>
274  // * performs dynamic allocation only when required. If the key is found, this
275  // struct is a no-op, otherwise it allocates when implicit conversion operator
276  // is called inside emplace/try_emplace
277  struct DefferedPtr {
278  operator std::unique_ptr<Base>() const { return std::make_unique<Signal>(); }
279  };
280  // TODO: remove later for C++17 features: structured bindings and try_emplace
281  #ifdef __cpp_structured_bindings
282  const auto [iterator, success] =
283  #else
284  typename decltype(signals_)::const_iterator iterator;
285  bool success;
286  std::tie (iterator, success) =
287  #endif
288 
289  #ifdef __cpp_lib_map_try_emplace
290  signals_.try_emplace (
291  #else
292  signals_.emplace (
293  #endif
294  std::string (typeid (T).name ()), DefferedPtr ());
295  if (!success)
296  {
297  return nullptr;
298  }
299  return static_cast<Signal*> (iterator->second.get ());
300  }
301 
302  template<typename T> boost::signals2::connection
303  Grabber::registerCallback (const std::function<T> & callback)
304  {
305  const auto signal = find_signal<T> ();
306  if (signal == nullptr)
307  {
308  std::stringstream sstream;
309 
310  sstream << "no callback for type:" << typeid (T).name ();
311 
312  PCL_THROW_EXCEPTION (pcl::IOException, "[" << getName () << "] " << sstream.str ());
313  //return (boost::signals2::connection ());
314  }
315  boost::signals2::connection ret = signal->connect (callback);
316 
317  connections_[typeid (T).name ()].push_back (ret);
318  shared_connections_[typeid (T).name ()].push_back (boost::signals2::shared_connection_block (connections_[typeid (T).name ()].back (), false));
319  signalsChanged ();
320  return (ret);
321  }
322 
323  template<typename T> bool
324  Grabber::providesCallback () const noexcept
325  {
326  return find_signal<T> ();
327  }
328 
329 } // namespace
pcl_macros.h
Defines all the PCL and non-PCL macros used.
pcl
Definition: convolution.h:46
pcl::Grabber::providesCallback
bool providesCallback() const noexcept
indicates whether a signal with given parameter-type exists or not
Definition: grabber.h:324
pcl::Grabber::unblock_signal
void unblock_signal()
Definition: grabber.h:233
boost
Definition: boost_graph.h:46
pcl::Grabber::registerCallback
boost::signals2::connection registerCallback(const std::function< T > &callback)
registers a callback function/method to a signal with the corresponding signature
Definition: grabber.h:303
pcl::Grabber
Grabber interface for PCL 1.x device drivers.
Definition: grabber.h:59
PCL_DEPRECATED
#define PCL_DEPRECATED(Major, Minor, Message)
macro for compatibility across compilers and help remove old deprecated items for the Major....
Definition: pcl_macros.h:156
pcl::Grabber::block_signal
void block_signal()
Definition: grabber.h:225
pcl::Grabber::find_signal
boost::signals2::signal< T > * find_signal() const noexcept
Definition: grabber.h:202
pcl::Grabber::createSignal
boost::signals2::signal< T > * createSignal()
Definition: grabber.h:268
pcl::Grabber::unblock_signals
void unblock_signals()
Definition: grabber.h:249
pcl::IOException
An exception that is thrown during an IO error (typical read/write errors)
Definition: exceptions.h:178
pcl::Grabber::num_slots
int num_slots() const noexcept
Definition: grabber.h:257
pcl::Grabber::block_signals
void block_signals()
Definition: grabber.h:241
pcl::Grabber::disconnect_all_slots
void disconnect_all_slots()
Definition: grabber.h:215
PCL_EXPORTS
#define PCL_EXPORTS
Definition: pcl_macros.h:323
pcl::Grabber::registerCallback
boost::signals2::connection registerCallback(const FunctionT< T > &callback)
registers a callback function/method to a signal with the corresponding signature
Definition: grabber.h:108