stereo_processor.h
Go to the documentation of this file.
00001 #ifndef STEREO_PROCESSOR_H_
00002 #define STEREO_PROCESSOR_H_
00003 
00004 #include <ros/ros.h>
00005 #include <sensor_msgs/Image.h>
00006 #include <sensor_msgs/CameraInfo.h>
00007 
00008 #include <message_filters/subscriber.h>
00009 #include <message_filters/synchronizer.h>
00010 #include <message_filters/sync_policies/exact_time.h>
00011 #include <message_filters/sync_policies/approximate_time.h>
00012 #include <image_transport/subscriber_filter.h>
00013 
00014 // Ref frame change methods
00015 #define REF_FRAME_CHANGE_MOTION 1
00016 #define REF_FRAME_CHANGE_INLIERS 2
00017 
00018 namespace viso2_ros
00019 {
00020 
00027 class StereoProcessor
00028 {
00029 
00030 private:
00031 
00032   // subscriber
00033   image_transport::SubscriberFilter left_sub_, right_sub_;
00034   message_filters::Subscriber<sensor_msgs::CameraInfo> left_info_sub_, right_info_sub_;
00035   typedef message_filters::sync_policies::ExactTime<sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo, sensor_msgs::CameraInfo> ExactPolicy;
00036   typedef message_filters::sync_policies::ApproximateTime<sensor_msgs::Image, sensor_msgs::Image, sensor_msgs::CameraInfo, sensor_msgs::CameraInfo> ApproximatePolicy;
00037   typedef message_filters::Synchronizer<ExactPolicy> ExactSync;
00038   typedef message_filters::Synchronizer<ApproximatePolicy> ApproximateSync;
00039   boost::shared_ptr<ExactSync> exact_sync_;
00040   boost::shared_ptr<ApproximateSync> approximate_sync_;
00041   int queue_size_;
00042 
00043   // for sync checking
00044   ros::WallTimer check_synced_timer_;
00045   int left_received_, right_received_, left_info_received_, right_info_received_, all_received_;
00046 
00047   // for sync checking
00048   static void increment(int* value)
00049   {
00050     ++(*value);
00051   }
00052 
00053   void dataCb(const sensor_msgs::ImageConstPtr& l_image_msg,
00054               const sensor_msgs::ImageConstPtr& r_image_msg,
00055               const sensor_msgs::CameraInfoConstPtr& l_info_msg,
00056               const sensor_msgs::CameraInfoConstPtr& r_info_msg)
00057   {
00058  
00059     // For sync error checking
00060     ++all_received_; 
00061 
00062     // call implementation
00063     imageCallback(l_image_msg, r_image_msg, l_info_msg, r_info_msg);
00064   }
00065 
00066   void checkInputsSynchronized()
00067   {
00068     int threshold = 3 * all_received_;
00069     if (left_received_ >= threshold || right_received_ >= threshold || 
00070         left_info_received_ >= threshold || right_info_received_ >= threshold) {
00071       ROS_WARN("[stereo_processor] Low number of synchronized left/right/left_info/right_info tuples received.\n"
00072                "Left images received:       %d (topic '%s')\n"
00073                "Right images received:      %d (topic '%s')\n"
00074                "Left camera info received:  %d (topic '%s')\n"
00075                "Right camera info received: %d (topic '%s')\n"
00076                "Synchronized tuples: %d\n"
00077                "Possible issues:\n"
00078                "\t* stereo_image_proc is not running.\n"
00079                "\t  Does `rosnode info %s` show any connections?\n"
00080                "\t* The cameras are not synchronized.\n"
00081                "\t  Try restarting the node with parameter _approximate_sync:=True\n"
00082                "\t* The network is too slow. One or more images are dropped from each tuple.\n"
00083                "\t  Try restarting the node, increasing parameter 'queue_size' (currently %d)",
00084                left_received_, left_sub_.getTopic().c_str(),
00085                right_received_, right_sub_.getTopic().c_str(),
00086                left_info_received_, left_info_sub_.getTopic().c_str(),
00087                right_info_received_, right_info_sub_.getTopic().c_str(),
00088                all_received_, ros::this_node::getName().c_str(), queue_size_);
00089     }
00090   }
00091 
00092 
00093 protected:
00094 
00100   StereoProcessor(const std::string& transport) :
00101     left_received_(0), right_received_(0), left_info_received_(0), right_info_received_(0), all_received_(0)
00102   {
00103     // Read local parameters
00104     ros::NodeHandle local_nh("~");
00105 
00106     // Resolve topic names
00107     ros::NodeHandle nh;
00108     std::string stereo_ns = nh.resolveName("stereo");
00109     std::string left_topic = ros::names::clean(stereo_ns + "/left/" + nh.resolveName("image"));
00110     std::string right_topic = ros::names::clean(stereo_ns + "/right/" + nh.resolveName("image"));
00111 
00112     std::string left_info_topic = stereo_ns + "/left/camera_info";
00113     std::string right_info_topic = stereo_ns + "/right/camera_info";
00114 
00115     // Subscribe to four input topics.
00116     ROS_INFO("Subscribing to:\n\t* %s\n\t* %s\n\t* %s\n\t* %s", 
00117         left_topic.c_str(), right_topic.c_str(),
00118         left_info_topic.c_str(), right_info_topic.c_str());
00119 
00120     image_transport::ImageTransport it(nh);
00121     left_sub_.subscribe(it, left_topic, 1, transport);
00122     right_sub_.subscribe(it, right_topic, 1, transport);
00123     left_info_sub_.subscribe(nh, left_info_topic, 1);
00124     right_info_sub_.subscribe(nh, right_info_topic, 1);
00125 
00126     // Complain every 15s if the topics appear unsynchronized
00127     left_sub_.registerCallback(boost::bind(StereoProcessor::increment, &left_received_));
00128     right_sub_.registerCallback(boost::bind(StereoProcessor::increment, &right_received_));
00129     left_info_sub_.registerCallback(boost::bind(StereoProcessor::increment, &left_info_received_));
00130     right_info_sub_.registerCallback(boost::bind(StereoProcessor::increment, &right_info_received_));
00131     check_synced_timer_ = nh.createWallTimer(ros::WallDuration(15.0),
00132                                              boost::bind(&StereoProcessor::checkInputsSynchronized, this));
00133 
00134     // Synchronize input topics. Optionally do approximate synchronization.
00135     local_nh.param("queue_size", queue_size_, 5);
00136     bool approx;
00137     local_nh.param("approximate_sync", approx, false);
00138     if (approx)
00139     {
00140       approximate_sync_.reset(new ApproximateSync(ApproximatePolicy(queue_size_),
00141                                                   left_sub_, right_sub_, left_info_sub_, right_info_sub_) );
00142       approximate_sync_->registerCallback(boost::bind(&StereoProcessor::dataCb, this, _1, _2, _3, _4));
00143     }
00144     else
00145     {
00146       exact_sync_.reset(new ExactSync(ExactPolicy(queue_size_),
00147                                       left_sub_, right_sub_, left_info_sub_, right_info_sub_) );
00148       exact_sync_->registerCallback(boost::bind(&StereoProcessor::dataCb, this, _1, _2, _3, _4));
00149     }
00150   }
00151 
00155   virtual void imageCallback(const sensor_msgs::ImageConstPtr& l_image_msg,
00156                              const sensor_msgs::ImageConstPtr& r_image_msg,
00157                              const sensor_msgs::CameraInfoConstPtr& l_info_msg,
00158                              const sensor_msgs::CameraInfoConstPtr& r_info_msg) = 0;
00159 
00160 };
00161 
00162 } // end of namespace
00163 
00164 #endif
00165 


viso2_ros
Author(s): Stephan Wirth
autogenerated on Tue Jan 7 2014 11:42:16