Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "polled_camera/publication_server.h"
00036 #include <image_transport/image_transport.h>
00037
00038 namespace polled_camera {
00039
00041
00042 class PublicationServer::Impl
00043 {
00044 public:
00045 ros::ServiceServer srv_server_;
00046 DriverCallback driver_cb_;
00047 ros::VoidPtr tracked_object_;
00048 image_transport::ImageTransport it_;
00049 std::map<std::string, image_transport::CameraPublisher> client_map_;
00050 bool unadvertised_;
00051 double constructed_;
00052
00053 Impl(const ros::NodeHandle& nh)
00054 : it_(nh),
00055 unadvertised_(false),
00056 constructed_(ros::WallTime::now().toSec())
00057 {
00058 }
00059
00060 ~Impl()
00061 {
00062 if (ros::WallTime::now().toSec() - constructed_ < 0.001)
00063 ROS_WARN("PublicationServer destroyed immediately after creation. Did you forget to store the handle?");
00064 unadvertise();
00065 }
00066
00067 bool isValid() const
00068 {
00069 return !unadvertised_;
00070 }
00071
00072 void unadvertise()
00073 {
00074 if (!unadvertised_) {
00075 unadvertised_ = true;
00076 srv_server_.shutdown();
00077 client_map_.clear();
00078 }
00079 }
00080
00081 bool requestCallback(polled_camera::GetPolledImage::Request& req,
00082 polled_camera::GetPolledImage::Response& rsp)
00083 {
00084 std::string image_topic = req.response_namespace + "/image_raw";
00085 image_transport::CameraPublisher& pub = client_map_[image_topic];
00086 if (!pub) {
00087
00088 pub = it_.advertiseCamera(image_topic, 1, image_transport::SubscriberStatusCallback(),
00089 boost::bind(&Impl::disconnectCallback, this, _1),
00090 ros::SubscriberStatusCallback(), ros::SubscriberStatusCallback(),
00091 ros::VoidPtr(), true );
00092 ROS_INFO("Advertising %s", pub.getTopic().c_str());
00093 }
00094
00095
00096 req.binning_x = std::max(req.binning_x, (uint32_t)1);
00097 req.binning_y = std::max(req.binning_y, (uint32_t)1);
00098
00100 sensor_msgs::Image image;
00101 sensor_msgs::CameraInfo info;
00102 driver_cb_(req, rsp, image, info);
00103
00104 if (rsp.success) {
00105 assert(image.header.stamp == info.header.stamp);
00106 rsp.stamp = image.header.stamp;
00107 pub.publish(image, info);
00108 }
00109 else {
00110 ROS_ERROR("Failed to capture requested image, status message: '%s'",
00111 rsp.status_message.c_str());
00112 }
00113
00114 return true;
00115 }
00116
00117 void disconnectCallback(const image_transport::SingleSubscriberPublisher& ssp)
00118 {
00119
00120 if (ssp.getNumSubscribers() == 0) {
00121 ROS_INFO("Shutting down %s", ssp.getTopic().c_str());
00122 client_map_.erase(ssp.getTopic());
00123 }
00124 }
00125 };
00126
00128
00129 PublicationServer::PublicationServer(const std::string& service, ros::NodeHandle& nh,
00130 const DriverCallback& cb, const ros::VoidPtr& tracked_object)
00131 : impl_(new Impl(nh))
00132 {
00133 impl_->driver_cb_ = cb;
00134 impl_->tracked_object_ = tracked_object;
00135 impl_->srv_server_ = nh.advertiseService<>(service, &Impl::requestCallback, impl_);
00136 }
00137
00138 void PublicationServer::shutdown()
00139 {
00140 if (impl_) impl_->unadvertise();
00141 }
00142
00143 std::string PublicationServer::getService() const
00144 {
00145 if (impl_) return impl_->srv_server_.getService();
00146 return std::string();
00147 }
00148
00149 PublicationServer::operator void*() const
00150 {
00151 return (impl_ && impl_->isValid()) ? (void*)1 : (void*)0;
00152 }
00153
00154 PublicationServer advertise(ros::NodeHandle& nh, const std::string& service,
00155 const PublicationServer::DriverCallback& cb,
00156 const ros::VoidPtr& tracked_object)
00157 {
00158 return PublicationServer(service, nh, cb, tracked_object);
00159 }
00160
00161 }