00001 #include "image_transport/camera_subscriber.h"
00002 #include "image_transport/subscriber_filter.h"
00003 #include "image_transport/camera_common.h"
00004 #include <message_filters/subscriber.h>
00005 #include <message_filters/time_synchronizer.h>
00006
00007 void increment(int* value)
00008 {
00009 ++(*value);
00010 }
00011
00012 namespace image_transport {
00013
00014 struct CameraSubscriber::Impl
00015 {
00016 Impl(uint32_t queue_size)
00017 : sync_(queue_size),
00018 unsubscribed_(false),
00019 image_received_(0), info_received_(0), both_received_(0)
00020 {}
00021
00022 ~Impl()
00023 {
00024 shutdown();
00025 }
00026
00027 bool isValid() const
00028 {
00029 return !unsubscribed_;
00030 }
00031
00032 void shutdown()
00033 {
00034 if (!unsubscribed_) {
00035 unsubscribed_ = true;
00036 image_sub_.unsubscribe();
00037 info_sub_.unsubscribe();
00038 }
00039 }
00040
00041 void checkImagesSynchronized()
00042 {
00043 int threshold = 3 * both_received_;
00044 if (image_received_ > threshold || info_received_ > threshold) {
00045 ROS_WARN("[image_transport] Topics '%s' and '%s' do not appear to be synchronized. "
00046 "In the last 10s:\n"
00047 "\tImage messages received: %d\n"
00048 "\tCameraInfo messages received: %d\n"
00049 "\tSynchronized pairs: %d",
00050 image_sub_.getTopic().c_str(), info_sub_.getTopic().c_str(),
00051 image_received_, info_received_, both_received_);
00052 }
00053 image_received_ = info_received_ = both_received_ = 0;
00054 }
00055
00056 SubscriberFilter image_sub_;
00057 message_filters::Subscriber<sensor_msgs::CameraInfo> info_sub_;
00058 message_filters::TimeSynchronizer<sensor_msgs::Image, sensor_msgs::CameraInfo> sync_;
00059 bool unsubscribed_;
00060
00061 ros::WallTimer check_synced_timer_;
00062 int image_received_, info_received_, both_received_;
00063 };
00064
00065 CameraSubscriber::CameraSubscriber(ImageTransport& image_it, ros::NodeHandle& info_nh,
00066 const std::string& base_topic, uint32_t queue_size,
00067 const Callback& callback, const ros::VoidPtr& tracked_object,
00068 const TransportHints& transport_hints)
00069 : impl_(new Impl(queue_size))
00070 {
00071
00072
00073 std::string image_topic = info_nh.resolveName(base_topic);
00074 std::string info_topic = getCameraInfoTopic(image_topic);
00075 impl_->image_sub_.subscribe(image_it, image_topic, queue_size, transport_hints);
00076 impl_->info_sub_ .subscribe(info_nh, info_topic, queue_size, transport_hints.getRosHints());
00077 impl_->sync_.connectInput(impl_->image_sub_, impl_->info_sub_);
00078
00079 impl_->sync_.registerCallback(boost::bind(callback, _1, _2));
00080
00081
00082 impl_->image_sub_.registerCallback(boost::bind(increment, &impl_->image_received_));
00083 impl_->info_sub_.registerCallback(boost::bind(increment, &impl_->info_received_));
00084 impl_->sync_.registerCallback(boost::bind(increment, &impl_->both_received_));
00085 impl_->check_synced_timer_ = info_nh.createWallTimer(ros::WallDuration(10.0),
00086 boost::bind(&Impl::checkImagesSynchronized, impl_));
00087 }
00088
00089 std::string CameraSubscriber::getTopic() const
00090 {
00091 if (impl_) return impl_->image_sub_.getTopic();
00092 return std::string();
00093 }
00094
00095 std::string CameraSubscriber::getInfoTopic() const
00096 {
00097 if (impl_) return impl_->info_sub_.getTopic();
00098 return std::string();
00099 }
00100
00101 uint32_t CameraSubscriber::getNumPublishers() const
00102 {
00104
00105 if (impl_) return impl_->image_sub_.getNumPublishers();
00106 return 0;
00107 }
00108
00109 std::string CameraSubscriber::getTransport() const
00110 {
00111 if (impl_) return impl_->image_sub_.getTransport();
00112 return std::string();
00113 }
00114
00115 void CameraSubscriber::shutdown()
00116 {
00117 if (impl_) impl_->shutdown();
00118 }
00119
00120 CameraSubscriber::operator void*() const
00121 {
00122 return (impl_ && impl_->isValid()) ? (void*)1 : (void*)0;
00123 }
00124
00125 }