simple_publisher_plugin.h
Go to the documentation of this file.
00001 #ifndef IMAGE_TRANSPORT_SIMPLE_PUBLISHER_PLUGIN_H
00002 #define IMAGE_TRANSPORT_SIMPLE_PUBLISHER_PLUGIN_H
00003 
00004 #include "image_transport/publisher_plugin.h"
00005 #include <boost/scoped_ptr.hpp>
00006 
00007 namespace image_transport {
00008 
00026 template <class M>
00027 class SimplePublisherPlugin : public PublisherPlugin
00028 {
00029 public:
00030   virtual ~SimplePublisherPlugin() {}
00031 
00032   virtual uint32_t getNumSubscribers() const
00033   {
00034     if (simple_impl_) return simple_impl_->pub_.getNumSubscribers();
00035     return 0;
00036   }
00037 
00038   virtual std::string getTopic() const
00039   {
00040     if (simple_impl_) return simple_impl_->pub_.getTopic();
00041     return std::string();
00042   }
00043 
00044   virtual void publish(const sensor_msgs::Image& message) const
00045   {
00046     if (!simple_impl_ || !simple_impl_->pub_) {
00047       ROS_ASSERT_MSG(false, "Call to publish() on an invalid image_transport::SimplePublisherPlugin");
00048       return;
00049     }
00050     
00051     publish(message, bindInternalPublisher(simple_impl_->pub_));
00052   }
00053 
00054   virtual void shutdown()
00055   {
00056     if (simple_impl_) simple_impl_->pub_.shutdown();
00057   }
00058 
00059 protected:
00060   virtual void advertiseImpl(ros::NodeHandle& nh, const std::string& base_topic, uint32_t queue_size,
00061                              const SubscriberStatusCallback& user_connect_cb,
00062                              const SubscriberStatusCallback& user_disconnect_cb,
00063                              const ros::VoidPtr& tracked_object, bool latch)
00064   {
00065     std::string transport_topic = getTopicToAdvertise(base_topic);
00066     ros::NodeHandle param_nh(transport_topic);
00067     simple_impl_.reset(new SimplePublisherPluginImpl(param_nh));
00068     simple_impl_->pub_ = nh.advertise<M>(transport_topic, queue_size,
00069                                          bindCB(user_connect_cb, &SimplePublisherPlugin::connectCallback),
00070                                          bindCB(user_disconnect_cb, &SimplePublisherPlugin::disconnectCallback),
00071                                          tracked_object, latch);
00072   }
00073 
00075   typedef boost::function<void(const M&)> PublishFn;
00076 
00085   virtual void publish(const sensor_msgs::Image& message, const PublishFn& publish_fn) const = 0;
00086 
00092   virtual std::string getTopicToAdvertise(const std::string& base_topic) const
00093   {
00094     return base_topic + "/" + getTransportName();
00095   }
00096 
00102   virtual void connectCallback(const ros::SingleSubscriberPublisher& pub) {}
00103 
00109   virtual void disconnectCallback(const ros::SingleSubscriberPublisher& pub) {}
00110 
00114   const ros::NodeHandle& nh() const
00115   {
00116     return simple_impl_->param_nh_;
00117   }
00118 
00125   const ros::Publisher& getPublisher() const
00126   {
00127     ROS_ASSERT(simple_impl_);
00128     return simple_impl_->pub_;
00129   }
00130 
00131 private:
00132   struct SimplePublisherPluginImpl
00133   {
00134     SimplePublisherPluginImpl(const ros::NodeHandle& nh)
00135       : param_nh_(nh)
00136     {
00137     }
00138     
00139     const ros::NodeHandle param_nh_;
00140     ros::Publisher pub_;
00141   };
00142   
00143   boost::scoped_ptr<SimplePublisherPluginImpl> simple_impl_;
00144 
00145   typedef void (SimplePublisherPlugin::*SubscriberStatusMemFn)(const ros::SingleSubscriberPublisher& pub);
00146   
00151   ros::SubscriberStatusCallback bindCB(const SubscriberStatusCallback& user_cb,
00152                                        SubscriberStatusMemFn internal_cb_fn)
00153   {
00154     ros::SubscriberStatusCallback internal_cb = boost::bind(internal_cb_fn, this, _1);
00155     if (user_cb)
00156       return boost::bind(&SimplePublisherPlugin::subscriberCB, this, _1, user_cb, internal_cb);
00157     else
00158       return internal_cb;
00159   }
00160   
00166   void subscriberCB(const ros::SingleSubscriberPublisher& ros_ssp,
00167                     const SubscriberStatusCallback& user_cb,
00168                     const ros::SubscriberStatusCallback& internal_cb)
00169   {
00170     // First call the internal callback (for sending setup headers, etc.)
00171     internal_cb(ros_ssp);
00172     
00173     // Construct a function object for publishing sensor_msgs::Image through the
00174     // subclass-implemented publish() using the ros::SingleSubscriberPublisher to send
00175     // messages of the transport-specific type.
00176     typedef void (SimplePublisherPlugin::*PublishMemFn)(const sensor_msgs::Image&, const PublishFn&) const;
00177     PublishMemFn pub_mem_fn = &SimplePublisherPlugin::publish;
00178     ImagePublishFn image_publish_fn = boost::bind(pub_mem_fn, this, _1, bindInternalPublisher(ros_ssp));
00179     
00180     SingleSubscriberPublisher ssp(ros_ssp.getSubscriberName(), getTopic(),
00181                                   boost::bind(&SimplePublisherPlugin::getNumSubscribers, this),
00182                                   image_publish_fn);
00183     user_cb(ssp);
00184   }
00185 
00186   typedef boost::function<void(const sensor_msgs::Image&)> ImagePublishFn;
00187 
00194   template <class PubT>
00195   PublishFn bindInternalPublisher(const PubT& pub) const
00196   {
00197     // Bind PubT::publish(const Message&) as PublishFn
00198     typedef void (PubT::*InternalPublishMemFn)(const M&) const;
00199     InternalPublishMemFn internal_pub_mem_fn = &PubT::publish;
00200     return boost::bind(internal_pub_mem_fn, &pub, _1);
00201   }
00202 };
00203 
00204 } //namespace image_transport
00205 
00206 #endif


image_transport
Author(s): Patrick Mihelich
autogenerated on Fri Jan 3 2014 11:24:08