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 unpublish(const std::string& publisherID, bool internal);
248 
256  void unpublish(const std::string& channelID, const std::string& publisherID, bool internal);
257 
262  void unsubscribe(const std::string& subscriberID);
263 
269  void unsubscribe(const std::string& channelID, const std::string& subscriberID);
270 
278  template<typename T>
279  ConcreteChannel<T>* getConcreteChannel(const std::string& channelID)
280  {
281  return channel_cast<T>(getAbstractChannel(channelID));
282  }
283 
284 public:
285 
289  std::set<std::string> getChannels() const;
290 
302  std::set<std::string> getChannelList(bool publishedOnly = false,
303  bool subscribedOnly = false) const;
304 
311  std::set<std::string> getSubscribedChannels(bool includeInternal = false) const;
312 
322  std::set<std::string> getSubscribedChannelsBy(const std::string& subscriberID) const;
323 
327  bool isSubscribedOn(const std::string& subscriberID,
328  const std::string& channelID) const;
329 
336  std::map<std::string, Typename> getPublishedChannels(bool includeInternal = false) const;
337 
347  std::set<std::string> getPublishedChannelsBy(const std::string& publisherID) const;
348 
352  bool hasPublished(const std::string& publisherID, const std::string& channelID) const;
353 
360  std::list<std::pair<std::string, Typename>> getChannelsOfType(const Typename& type) const;
361 
368  template <typename T>
369  std::list<std::pair<std::string, Typename>> getChannelsOfType() const {
370  return getChannelsOfType(typeName<T>());
371  }
372 
380  bool hasSubscriber(const std::string& channelID) const;
381 
389  bool hasPublisher(const std::string& channelID, bool includeInternal) const;
390 
394  uint32 getNrPublishers(const std::string& channelID) const;
395 
399  std::set<std::string> getPublishers(const std::string& channelID,
400  bool includeInternal = false) const;
401 
405  uint32 getNrSubscribers(const std::string& channelID) const;
406 
410  std::set<std::string> getSubscribers(const std::string& channelID,
411  bool includeInternal = false) const;
412 
417  bool hasChannel(const std::string& channelID) const;
418 
423  int getTypeId(const std::string& channelID) const;
424 
428  void setTypename(const std::string& channelID, const Typename& typenam);
429 
434  Typename getTypename(const std::string& channelID) const;
435 
440  void setTypeMeta(const std::string& channelID, TypeMetaPtr meta);
441 
445  TypeMetaPtr getTypeMeta(const std::string& channelID) const;
446 
452  Time getLastSlotTime(const std::string& channelID) const;
453 
457  std::size_t getNrOfSlots(const std::string& channelID) const;
458 
463  uint64 getNrOfDataChanges(const std::string& channelID) const;
464 
465 public:
466 
471  void ensureChannel(const std::string& channelID)
472  {
473  obtainConcreteChannel<void>(channelID);
474  }
475 
481  void setStorageDuration(const std::string& channelID, const Duration& storageDuration);
482 
488  void setAutoIncreaseStorageDuration(const std::string& channelID, bool increase);
489 
495  void setMinSlots(const std::string& channelID, std::size_t minSlots);
496 
502  void setMaxSlots(const std::string& channelID, std::size_t maxSlots);
503 
505  Duration getStorageDuration(const std::string& channelID);
506 
508  bool isAutoIncreasingStorageDuration(const std::string& channelID);
509 
511  std::size_t getMinSlots(const std::string& channelID);
512 
514  std::size_t getMaxSlots(const std::string& channelID);
515 
516 public:
517 
521  void writeChannel(const std::string& channelID,
522  const json::Value& value,
523  const Time& time = Time::now());
524 
529  json::Value readChannel(const std::string& channelID);
530 
531 private:
532 
539  const AbstractChannel* getAbstractChannel(const std::string& channelID) const;
540 
547  AbstractChannelPtr getAbstractChannel(const std::string& channelID);
548 
555  AbstractChannelPtr getAbstractChannelNoLocking(const std::string& channelID);
556 
563  const AbstractChannel* getAbstractChannelNoLocking(const std::string& channelID) const;
564 
572  template<typename T>
573  ConcreteChannel<T>* obtainConcreteChannel(const std::string& channelID)
574  {
575  boost::mutex::scoped_lock lock(mChannelsMutex);
576 
577  ConcreteChannel<T>* channel = NULL;
578  try
579  {
580  channel = channel_cast<T>(getAbstractChannelNoLocking(channelID));
581  }
582  catch (XUnknownChannel&)
583  {
584  // if we reach here, the channel does not exist, so create a new one
585  channel = new ConcreteChannel<T>(channelID);
586  mChannels.insert(ChannelMap::value_type(channelID, channel));
587  }
588  return channel;
589  }
590 
593  void remotePublishChannel(const std::string& channelID, const Typename& type);
594  void remoteUnpublishChannel(const std::string& channelID);
595  void remoteSubscribeChannel(const std::string& channelID);
596  void remoteUnsubscribeChannel(const std::string& channelID);
598 
599 
600 private:
601 
602  void insertPublishedChannel(const std::string& channelID, const ChannelInfo& info);
603  void insertSubscribedChannel(const std::string& channelID, const ChannelInfo& info);
604 
605 private:
606 
607  typedef std::map<std::string, AbstractChannelPtr > ChannelMap;
608  ChannelMap mChannels;
609  mutable boost::mutex mChannelsMutex;
610 
611  class Pimpl;
612  Pimpl* p;
613 
614  mutable boost::mutex mSubscriberMutex;
615  mutable boost::mutex mPublisherMutex;
616 
617  bool mAutoPromoteChannels;
618  bool mCheckChannelRegistrations;
619 
620 };
621 
623 
624 }
625 
626 #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:369
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:471
ConcreteChannel< T > * getConcreteChannel(const std::string &channelID)
Returns the existing channel with the given id.
Definition: ChannelManager.h:279