Point Cloud Library (PCL) 1.12.1
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/exceptions.h>
50#include <boost/signals2.hpp> // for connection, signal, ...
51
52namespace 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 indicates whether a signal with given parameter-type exists or not
102 * \return true if signal exists, false otherwise
103 */
104 template<typename T> bool
105 providesCallback () const noexcept;
106
107 /** \brief For devices that are streaming, the streams are started by calling this method.
108 * Trigger-based devices, just trigger the device once for each call of start.
109 */
110 virtual void
111 start () = 0;
112
113 /** \brief For devices that are streaming, the streams are stopped.
114 * This method has no effect for triggered devices.
115 */
116 virtual void
117 stop () = 0;
118
119 /** \brief For devices that are streaming, stopped streams are started and running stream are stopped.
120 * For triggered devices, the behavior is not defined.
121 * \return true if grabber is running / streaming. False otherwise.
122 */
123 inline bool
124 toggle ();
125
126 /** \brief returns the name of the concrete subclass.
127 * \return the name of the concrete driver.
128 */
129 virtual std::string
130 getName () const = 0;
131
132 /** \brief Indicates whether the grabber is streaming or not. This value is not defined for triggered devices.
133 * \return true if grabber is running / streaming. False otherwise.
134 */
135 virtual bool
136 isRunning () const = 0;
137
138 /** \brief returns fps. 0 if trigger based. */
139 virtual float
140 getFramesPerSecond () const = 0;
141
142 protected:
143
144 virtual void
145 signalsChanged () { }
146
147 template<typename T> boost::signals2::signal<T>*
148 find_signal () const noexcept;
149
150 template<typename T> int
151 num_slots () const noexcept;
152
153 template<typename T> void
154 disconnect_all_slots ();
155
156 template<typename T> void
157 block_signal ();
158
159 template<typename T> void
160 unblock_signal ();
161
162 inline void
163 block_signals ();
164
165 inline void
166 unblock_signals ();
167
168 template<typename T> boost::signals2::signal<T>*
169 createSignal ();
170
171 std::map<std::string, std::unique_ptr<boost::signals2::signal_base>> signals_;
172 std::map<std::string, std::vector<boost::signals2::connection> > connections_;
173 std::map<std::string, std::vector<boost::signals2::shared_connection_block> > shared_connections_;
174 } ;
175
176 bool
177 Grabber::toggle ()
178 {
179 if (isRunning ())
180 {
181 stop ();
182 } else
183 {
184 start ();
185 }
186 return isRunning ();
187 }
188
189 template<typename T> boost::signals2::signal<T>*
190 Grabber::find_signal () const noexcept
191 {
192 using Signal = boost::signals2::signal<T>;
193
194 const auto signal_it = signals_.find (typeid (T).name ());
195 if (signal_it != signals_.end ())
196 {
197 return (static_cast<Signal*> (signal_it->second.get ()));
198 }
199 return nullptr;
200 }
201
202 template<typename T> void
204 {
205 const auto signal = find_signal<T> ();
206 if (signal != nullptr)
207 {
208 signal->disconnect_all_slots ();
209 }
210 }
211
212 template<typename T> void
214 {
215 if (connections_.find (typeid (T).name ()) != connections_.end ())
216 for (auto &connection : shared_connections_[typeid (T).name ()])
217 connection.block ();
218 }
219
220 template<typename T> void
222 {
223 if (connections_.find (typeid (T).name ()) != connections_.end ())
224 for (auto &connection : shared_connections_[typeid (T).name ()])
225 connection.unblock ();
226 }
227
228 void
230 {
231 for (const auto &signal : signals_)
232 for (auto &connection : shared_connections_[signal.first])
233 connection.block ();
234 }
235
236 void
238 {
239 for (const auto &signal : signals_)
240 for (auto &connection : shared_connections_[signal.first])
241 connection.unblock ();
242 }
243
244 template<typename T> int
245 Grabber::num_slots () const noexcept
246 {
247 const auto signal = find_signal<T> ();
248 if (signal != nullptr)
249 {
250 return static_cast<int> (signal->num_slots ());
251 }
252 return 0;
253 }
254
255 template<typename T> boost::signals2::signal<T>*
257 {
258 using Signal = boost::signals2::signal<T>;
259 using Base = boost::signals2::signal_base;
260 // DefferedPtr serves 2 purposes:
261 // * allows MSVC to copy it around, can't do that with unique_ptr<T>
262 // * performs dynamic allocation only when required. If the key is found, this
263 // struct is a no-op, otherwise it allocates when implicit conversion operator
264 // is called inside emplace/try_emplace
265 struct DefferedPtr {
266 operator std::unique_ptr<Base>() const { return std::make_unique<Signal>(); }
267 };
268 // TODO: remove later for C++17 features: structured bindings and try_emplace
269 #ifdef __cpp_structured_bindings
270 const auto [iterator, success] =
271 #else
272 typename decltype(signals_)::const_iterator iterator;
273 bool success;
274 std::tie (iterator, success) =
275 #endif
276
277 #ifdef __cpp_lib_map_try_emplace
278 signals_.try_emplace (
279 #else
280 signals_.emplace (
281 #endif
282 std::string (typeid (T).name ()), DefferedPtr ());
283 if (!success)
284 {
285 return nullptr;
286 }
287 return static_cast<Signal*> (iterator->second.get ());
288 }
289
290 template<typename T> boost::signals2::connection
291 Grabber::registerCallback (const std::function<T> & callback)
292 {
293 const auto signal = find_signal<T> ();
294 if (signal == nullptr)
295 {
296 std::stringstream sstream;
297
298 sstream << "no callback for type:" << typeid (T).name ();
299
300 PCL_THROW_EXCEPTION (pcl::IOException, "[" << getName () << "] " << sstream.str ());
301 //return (boost::signals2::connection ());
302 }
303 boost::signals2::connection ret = signal->connect (callback);
304
305 connections_[typeid (T).name ()].push_back (ret);
306 shared_connections_[typeid (T).name ()].push_back (boost::signals2::shared_connection_block (connections_[typeid (T).name ()].back (), false));
307 signalsChanged ();
308 return (ret);
309 }
310
311 template<typename T> bool
313 {
314 return find_signal<T> ();
315 }
316
317} // namespace
Grabber interface for PCL 1.x device drivers.
Definition: grabber.h:60
void block_signals()
Definition: grabber.h:229
Grabber(Grabber &&)=default
Move ctor.
void unblock_signal()
Definition: grabber.h:221
bool providesCallback() const noexcept
indicates whether a signal with given parameter-type exists or not
Definition: grabber.h:312
boost::signals2::signal< T > * find_signal() const noexcept
Definition: grabber.h:190
Grabber(const Grabber &)=delete
No copy ctor since Grabber can't be copied.
int num_slots() const noexcept
Definition: grabber.h:245
boost::signals2::signal< T > * createSignal()
Definition: grabber.h:256
Grabber()=default
Default ctor.
void unblock_signals()
Definition: grabber.h:237
virtual ~Grabber() noexcept=default
virtual destructor.
Grabber & operator=(const Grabber &)=delete
No copy assign operator since Grabber can't be copied.
void disconnect_all_slots()
Definition: grabber.h:203
void block_signal()
Definition: grabber.h:213
boost::signals2::connection registerCallback(const std::function< T > &callback)
registers a callback function/method to a signal with the corresponding signature
Definition: grabber.h:291
Grabber & operator=(Grabber &&)=default
Move assign operator.
An exception that is thrown during an IO error (typical read/write errors)
Definition: exceptions.h:179
Defines all the PCL and non-PCL macros used.
#define PCL_EXPORTS
Definition: pcl_macros.h:323