MIRA
ChannelManager.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012 by
3  * MetraLabs GmbH (MLAB), GERMANY
4  * and
5  * Neuroinformatics and Cognitive Robotics Labs (NICR) at TU Ilmenau, GERMANY
6  * All rights reserved.
7  *
8  * Contact: info@mira-project.org
9  *
10  * Commercial Usage:
11  * Licensees holding valid commercial licenses may use this file in
12  * accordance with the commercial license agreement provided with the
13  * software or, alternatively, in accordance with the terms contained in
14  * a written agreement between you and MLAB or NICR.
15  *
16  * GNU General Public License Usage:
17  * Alternatively, this file may be used under the terms of the GNU
18  * General Public License version 3.0 as published by the Free Software
19  * Foundation and appearing in the file LICENSE.GPL3 included in the
20  * packaging of this file. Please review the following information to
21  * ensure the GNU General Public License version 3.0 requirements will be
22  * met: http://www.gnu.org/copyleft/gpl.html.
23  * Alternatively you may (at your option) use any later version of the GNU
24  * General Public License if such license has been publicly approved by
25  * MLAB and NICR (or its successors, if any).
26  *
27  * IN NO EVENT SHALL "MLAB" OR "NICR" BE LIABLE TO ANY PARTY FOR DIRECT,
28  * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF
29  * THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF "MLAB" OR
30  * "NICR" HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  * "MLAB" AND "NICR" SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING,
33  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
34  * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
35  * ON AN "AS IS" BASIS, AND "MLAB" AND "NICR" HAVE NO OBLIGATION TO
36  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS OR MODIFICATIONS.
37  */
38 
47 #ifndef _MIRA_CHANNELMANAGER_H_
48 #define _MIRA_CHANNELMANAGER_H_
49 
50 #include <platform/Types.h>
51 #include <error/Exceptions.h>
52 #include <thread/Thread.h>
53 #include <transform/Pose.h>
54 
55 #include <fw/Channel.h>
56 
57 namespace mira {
58 
60 
64 MIRA_DEFINE_SERIALIZABLE_EXCEPTION(XUnknownChannel, XRuntime)
65 
66 
76 {
77 public:
79  struct ChannelInfo
80  {
82 
83  ChannelInfo(const std::string& iID, bool iInternal = false) :
84  id(iID),
85  internal(iInternal) {}
86 
87  bool operator<(const ChannelInfo& other) const
88  {
89  return id < other.id;
90  }
91 
92  bool operator==(const ChannelInfo& other) const
93  {
94  return id == other.id;
95  }
96 
97  std::string id;
98  bool internal;
99  };
100 
101  ChannelManager();
102  ~ChannelManager();
103 
105  template<typename Reflector>
106  void reflect(Reflector& r)
107  {
108  r.interface("IChannelManager");
109  r.method("writeChannel", &ChannelManager::writeChannel, this,
110  "Writes a json representation to a channel of type T",
111  "channelID", "ID of channel to write to", "/robot/RobotFrame",
112  "value", "value to write", JSONSerializer().serialize(Pose2()),
113  "time", "data timestamp", Time::now());
114  r.method("readChannel", &ChannelManager::readChannel, this,
115  "Reads the latest channel data as json representation",
116  "channelID", "ID of channel to read", "/robot/RobotFrame");
117  r.method("getChannelList", &ChannelManager::getChannelList, this,
118  "get list of channels",
119  "publishedOnly", "if true, include only channels with (local) publishers", false,
120  "subscribedOnly", "if true, include only channels with (local) subscribers", false);
121  }
122 
123 public:
144  template<typename T>
145  ConcreteChannel<T>* publish(const std::string& channelID,
146  const std::string& publisherID,
147  bool internal, const Typename& type,
148  bool noAutoPromoteCheck = false)
149  {
150  // If exists && id and T are not the same throw Exception
151  ConcreteChannel<T>* channel = obtainConcreteChannel<T>(channelID);
152  channel->fixateType(); // fixate the type
153 
154  if ( channel->isTyped() ) {
155  Typename channelType = channel->getTypename();
156  if ((channelType != type) &&
157  // typed publish to polymorphic channel might specify a different type
158  // (when the polymorphic channel is typed, its type has been fixated),
159  // so untyped publish must match it)
160  ((channelType[channelType.size()-1] != '*') || (typeName<T>() == "void")))
161  MIRA_THROW(XBadCast, "Invalid publish<void> to typed channel '" << channelID <<
162  "'. Typename does not match. ('" <<
163  type << "' != '" << channel->getTypename() << "')");
164 
165  if (mCheckChannelRegistrations && !noAutoPromoteCheck)
166  ChannelPromoteByTypename::instance().checkForPromoter(channel);
167  } else {
168  if (!channel->getTypename().empty() && (channel->getTypename() != type))
169  MIRA_THROW(XBadCast, "Invalid publish<void> to untyped channel '" << channelID <<
170  "' (with set typename). Typename does not match. ('" <<
171  type << "' != '" << channel->getTypename() << "')");
172 
173  channel->setTypename(type);
174  }
175 
176  {
177  insertPublishedChannel(channelID, ChannelInfo(publisherID, internal));
178  MIRA_LOG(DEBUG) << "'" << publisherID << "' published channel '" << channelID << "'";
179  }
180 
181  if (!internal)
182  remotePublishChannel(channelID, type);
183 
184  return channel;
185  }
186 
188  void enableAutoPromoteChannels(bool enable) { mAutoPromoteChannels = enable; }
189 
191  bool autoPromoteChannelsEnabled() { return mAutoPromoteChannels; }
192 
196  void enableCheckChannelRegistrations(bool enable) { mCheckChannelRegistrations = enable; }
197 
199  bool checkChannelRegistrationsEnabled() { return mCheckChannelRegistrations; }
200 
201 public:
202 
223  template<typename T>
224  ConcreteChannel<T>* subscribe(const std::string& channelID,
225  const std::string& subscriberID,
226  const Duration& storageDuration, bool internal)
227  {
228  ConcreteChannel<T>* channel = obtainConcreteChannel<T>(channelID);
229 
230  assert(channel->getBuffer()!=NULL);
231  channel->getBuffer()->setStorageDuration(storageDuration);
232  insertSubscribedChannel(channelID, ChannelInfo(subscriberID, internal));
233  MIRA_LOG(DEBUG) << "'" << subscriberID << "' subscribed to channel '" << channelID << "'";
234 
235  if (!internal)
236  remoteSubscribeChannel(channelID);
237 
238  return channel;
239  }
240 
247  void removePublisherFromAllChannels(const std::string& publisherID, bool internal);
248 
256  void removePublisher(const std::string& channelID, const std::string& publisherID, bool internal);
257 
262  void removeSubscriberFromAllChannels(const std::string& subscriberID);
263 
269  void removeSubscriber(const std::string& channelID, const std::string& subscriberID);
270 
276  void deductNumSubscribers(const std::string& channelID);
277 
285  template<typename T>
286  ConcreteChannel<T>* getConcreteChannel(const std::string& channelID)
287  {
288  return channel_cast<T>(getAbstractChannel(channelID));
289  }
290 
291 public:
292 
296  std::set<std::string> getChannels() const;
297 
309  std::set<std::string> getChannelList(bool publishedOnly = false,
310  bool subscribedOnly = false) const;
311 
318  std::set<std::string> getSubscribedChannels(bool includeInternal = false) const;
319 
329  std::set<std::string> getSubscribedChannelsBy(const std::string& subscriberID) const;
330 
334  bool isSubscribedOn(const std::string& subscriberID,
335  const std::string& channelID) const;
336 
343  std::map<std::string, Typename> getPublishedChannels(bool includeInternal = false) const;
344 
354  std::set<std::string> getPublishedChannelsBy(const std::string& publisherID) const;
355 
359  bool hasPublished(const std::string& publisherID, const std::string& channelID) const;
360 
367  std::list<std::pair<std::string, Typename>> getChannelsOfType(const Typename& type) const;
368 
375  template <typename T>
376  std::list<std::pair<std::string, Typename>> getChannelsOfType() const {
377  return getChannelsOfType(typeName<T>());
378  }
379 
387  bool hasSubscriber(const std::string& channelID) const;
388 
396  bool hasPublisher(const std::string& channelID, bool includeInternal) const;
397 
401  uint32 getNrPublishers(const std::string& channelID) const;
402 
406  std::set<std::string> getPublishers(const std::string& channelID,
407  bool includeInternal = false) const;
408 
412  uint32 getNrSubscribers(const std::string& channelID) const;
413 
417  std::set<std::string> getSubscribers(const std::string& channelID,
418  bool includeInternal = false) const;
419 
424  bool hasChannel(const std::string& channelID) const;
425 
430  int getTypeId(const std::string& channelID) const;
431 
435  void setTypename(const std::string& channelID, const Typename& typenam);
436 
441  Typename getTypename(const std::string& channelID) const;
442 
447  void setTypeMeta(const std::string& channelID, TypeMetaPtr meta);
448 
452  TypeMetaPtr getTypeMeta(const std::string& channelID) const;
453 
459  Time getLastSlotTime(const std::string& channelID) const;
460 
464  std::size_t getNrOfSlots(const std::string& channelID) const;
465 
470  uint64 getNrOfDataChanges(const std::string& channelID) const;
471 
472 public:
473 
478  void ensureChannel(const std::string& channelID)
479  {
480  obtainConcreteChannel<void>(channelID);
481  }
482 
488  void setStorageDuration(const std::string& channelID, const Duration& storageDuration);
489 
495  void setAutoIncreaseStorageDuration(const std::string& channelID, bool increase);
496 
502  void setMinSlots(const std::string& channelID, std::size_t minSlots);
503 
509  void setMaxSlots(const std::string& channelID, std::size_t maxSlots);
510 
512  Duration getStorageDuration(const std::string& channelID);
513 
515  bool isAutoIncreasingStorageDuration(const std::string& channelID);
516 
518  std::size_t getMinSlots(const std::string& channelID);
519 
521  std::size_t getMaxSlots(const std::string& channelID);
522 
523 public:
524 
528  void writeChannel(const std::string& channelID,
529  const json::Value& value,
530  const Time& time = Time::now());
531 
536  json::Value readChannel(const std::string& channelID);
537 
538 private:
539 
546  const AbstractChannel* getAbstractChannel(const std::string& channelID) const;
547 
554  AbstractChannelPtr getAbstractChannel(const std::string& channelID);
555 
562  AbstractChannelPtr getAbstractChannelNoLocking(const std::string& channelID);
563 
570  const AbstractChannel* getAbstractChannelNoLocking(const std::string& channelID) const;
571 
579  template<typename T>
580  ConcreteChannel<T>* obtainConcreteChannel(const std::string& channelID)
581  {
582  boost::mutex::scoped_lock lock(mChannelsMutex);
583 
584  ConcreteChannel<T>* channel = NULL;
585  try
586  {
587  channel = channel_cast<T>(getAbstractChannelNoLocking(channelID));
588  }
589  catch (XUnknownChannel&)
590  {
591  // if we reach here, the channel does not exist, so create a new one
592  channel = new ConcreteChannel<T>(channelID);
593  mChannels.insert(ChannelMap::value_type(channelID, channel));
594  }
595  return channel;
596  }
597 
600  void remotePublishChannel(const std::string& channelID, const Typename& type);
601  void remoteUnpublishChannel(const std::string& channelID);
602  void remoteSubscribeChannel(const std::string& channelID);
603  void remoteUnsubscribeChannel(const std::string& channelID);
605 
606 
607 private:
608 
609  void insertPublishedChannel(const std::string& channelID, const ChannelInfo& info);
610  void insertSubscribedChannel(const std::string& channelID, const ChannelInfo& info);
611 
612 private:
613 
614  typedef std::map<std::string, AbstractChannelPtr > ChannelMap;
615  ChannelMap mChannels;
616  mutable boost::mutex mChannelsMutex;
617 
618  class Pimpl;
619  Pimpl* p;
620 
621  mutable boost::mutex mSubscriberMutex;
622  mutable boost::mutex mPublisherMutex;
623 
624  bool mAutoPromoteChannels;
625  bool mCheckChannelRegistrations;
626 
627 };
628 
630 
631 }
632 
633 #endif
Serializer for serializing objects in JSON format.
Definition: JSONSerializer.h:93
bool operator==(const ChannelInfo &other) const
Definition: ChannelManager.h:92
Typedefs for OS independent basic data types.
specialize cv::DataType for our ImgPixel and inherit from cv::DataType<Vec>
Definition: IOService.h:67
std::string Typename
Definition: Typename.h:60
#define MIRA_LOG(level)
Use this macro to log data.
Definition: LoggingCore.h:528
bool checkChannelRegistrationsEnabled()
Query if check for channel registrations in publish<T>(...) is enabled.
Definition: ChannelManager.h:199
#define MIRA_DEFINE_SERIALIZABLE_EXCEPTION(Ex, Base)
Macro for easily defining a new serializable exception class.
Definition: Exceptions.h:66
json::Value readChannel(const std::string &channelID)
Reads data from the channel with given id.
Definition: ChannelReadWrite.h:65
#define MIRA_THROW(ex, msg)
Macro for throwing an exception.
Definition: Exception.h:81
ConcreteChannel< T > * publish(const std::string &channelID, const std::string &publisherID, bool internal, const Typename &type, bool noAutoPromoteCheck=false)
Publishes a channel with the given id.
Definition: ChannelManager.h:145
Wrapper class for boost::posix_time::ptime for adding more functionality to it.
Definition: Time.h:421
void enableAutoPromoteChannels(bool enable)
Enable/disable automatic promotion of channel to typed in publish<void>(...)
Definition: ChannelManager.h:188
std::set< std::string > getChannelList(bool publishedOnly=false, bool subscribedOnly=false) const
Get a list of all channels managed by this manager, can be filtered for only those that have subscrib...
RigidTransform< float, 2 > Pose2
A 2D pose consisting of a translation and rotation.
Definition: Pose.h:62
ChannelInfo()
Definition: ChannelManager.h:81
void enableCheckChannelRegistrations(bool enable)
Enable/disable check for registration of channel types in publish<T>(...) (T!=void) ...
Definition: ChannelManager.h:196
void reflect(Reflector &r)
Reflect method for serialization.
Definition: ChannelManager.h:106
void writeChannel(const std::string &channelID, const json::Value &value, const Time &time=Time::now())
Writes a json value to the channel with given id.
Commonly used exception classes.
Includes, defines and functions for threads.
std::string id
Definition: ChannelManager.h:97
#define MIRA_FRAMEWORK_EXPORT
Definition: FrameworkExports.h:61
PropertyHint type(const std::string &t)
Sets the attribute "type" to the specified value.
Definition: PropertyHint.h:295
Definition: AbstractChannel.h:70
Use this class to represent time durations.
Definition: Time.h:104
bool autoPromoteChannelsEnabled()
Query if automatic promotion of channel to typed in publish<void>(...) is enabled.
Definition: ChannelManager.h:191
ChannelInfo(const std::string &iID, bool iInternal=false)
Definition: ChannelManager.h:83
ConcreteChannel< T > * subscribe(const std::string &channelID, const std::string &subscriberID, const Duration &storageDuration, bool internal)
Subscribes to a channel with the given id.
Definition: ChannelManager.h:224
boost::shared_ptr< TypeMeta > TypeMetaPtr
Definition: MetaSerializer.h:309
Framework channel classes.
Informations about a channel that also provides ordering of channels by id.
Definition: ChannelManager.h:79
json_spirit::mValue Value
A value is an abstract description of data in JSON (underlying data can either be one of the JSON bas...
Definition: JSON.h:176
static Time now() static Time eternity()
Returns the current utc based time.
Definition: Time.h:484
An exception that occurred whenever a channel does not exist.
Definition: ChannelManager.h:75
Typedefs for different Pose datatypes that are internally RigidTransforms.
Definition: LoggingCore.h:77
std::list< std::pair< std::string, Typename > > getChannelsOfType() const
Returns a list of all channels that match the specified type.
Definition: ChannelManager.h:376
bool operator<(const ChannelInfo &other) const
Definition: ChannelManager.h:87
void ensureChannel(const std::string &channelID)
Just make sure the specified channel exists (by creating it if needed), without changing any attribut...
Definition: ChannelManager.h:478
ConcreteChannel< T > * getConcreteChannel(const std::string &channelID)
Returns the existing channel with the given id.
Definition: ChannelManager.h:286