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
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
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
00044 ros::WallTimer check_synced_timer_;
00045 int left_received_, right_received_, left_info_received_, right_info_received_, all_received_;
00046
00047
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
00060 ++all_received_;
00061
00062
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
00104 ros::NodeHandle local_nh("~");
00105
00106
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
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
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
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 }
00163
00164 #endif
00165