Go to the documentation of this file.00001 #include <ros/ros.h>
00002 #include <sensor_msgs/Image.h>
00003 #include <sensor_msgs/image_encodings.h>
00004 #include "sensor_msgs/fill_image.h"
00005
00006 #include <message_filters/subscriber.h>
00007 #include <message_filters/time_synchronizer.h>
00008 #include <image_transport/subscriber_filter.h>
00009
00010 #include <boost/thread.hpp>
00011
00012 namespace enc = sensor_msgs::image_encodings;
00013
00014 void increment(int* value)
00015 {
00016 ++(*value);
00017 }
00018
00019 class Anaglyph3D
00020 {
00021 private:
00022 image_transport::ImageTransport it_;
00023 image_transport::SubscriberFilter left_sub_, right_sub_;
00024 message_filters::TimeSynchronizer<sensor_msgs::Image, sensor_msgs::Image> sync_;
00025 image_transport::Publisher pub_anaglyph_;
00026
00027 sensor_msgs::ImageConstPtr last_left_, last_right_;
00028 boost::mutex image_mutex_;
00029 sensor_msgs::Image img_ana_;
00030
00031 ros::WallTimer check_synced_timer_;
00032 int left_received_, right_received_, all_received_;
00033
00034 public:
00035 Anaglyph3D(ros::NodeHandle& nh)
00036 : it_(nh), sync_(2), left_received_(0),
00037 right_received_(0), all_received_(0)
00038 {
00039 ros::NodeHandle local_nh("~");
00040
00041 std::string stereo_ns = nh.resolveName("stereo");
00042 std::string left_topic = ros::names::clean(stereo_ns + "/left/" + nh.resolveName("image"));
00043 std::string right_topic = ros::names::clean(stereo_ns + "/right/" + nh.resolveName("image"));
00044 ROS_INFO("Subscribing to:\n\t* %s\n\t* %s\n\t* %s", left_topic.c_str(), right_topic.c_str());
00045
00046 left_sub_.subscribe(it_, left_topic, 3);
00047 right_sub_.subscribe(it_, right_topic, 3);
00048 sync_.connectInput(left_sub_, right_sub_);
00049 sync_.registerCallback(boost::bind(&Anaglyph3D::imageCB, this, _1, _2));
00050
00051 pub_anaglyph_ = it_.advertise(stereo_ns + "anaglyph3D", 1);
00052
00053
00054 left_sub_.registerCallback(boost::bind(increment, &left_received_));
00055 right_sub_.registerCallback(boost::bind(increment, &right_received_));
00056 sync_.registerCallback(boost::bind(increment, &all_received_));
00057 check_synced_timer_ = nh.createWallTimer(ros::WallDuration(30.0),
00058 boost::bind(&Anaglyph3D::checkInputsSynchronized, this));
00059 }
00060
00061 void imageCB(const sensor_msgs::ImageConstPtr& left, const sensor_msgs::ImageConstPtr& right)
00062 {
00063 {
00064 boost::lock_guard<boost::mutex> guard(image_mutex_);
00065
00066
00067 last_left_ = left;
00068 last_right_ = right;
00069 }
00070
00071 if (last_left_->encoding == enc::BGR8) {
00072 uint8_t* data_anaglyph = (uint8_t*) calloc(3*last_left_->height*last_left_->width, sizeof(uint8_t));
00073 for(int row = 0; row < last_left_->height; row++)
00074 for(int col = 0; col < last_left_->width; col++) {
00075 data_anaglyph[row*last_right_->step + 3*col + 0] = last_right_->data[row*last_right_->step + 3*col + 0];
00076 data_anaglyph[row*last_right_->step + 3*col + 1] = last_right_->data[row*last_right_->step + 3*col + 1];
00077 data_anaglyph[row*last_left_->step + 3*col + 2] = last_left_->data[row*last_left_->step + 3*col + 2];
00078 }
00079
00080 fillImage(img_ana_, "bgr8", last_left_->height, last_left_->width, last_left_->step, const_cast<uint8_t*>(data_anaglyph));
00081 pub_anaglyph_.publish(img_ana_);
00082 free(data_anaglyph);
00083 }
00084
00085
00086 }
00087
00088 void checkInputsSynchronized()
00089 {
00090 int threshold = 2 * all_received_;
00091 if (left_received_ > threshold || right_received_ > threshold) {
00092 ROS_WARN("[anaglyph] Low number of synchronized left/right/disparity triplets received.\n"
00093 "Left images received: %d\n"
00094 "Right images received: %d\n"
00095 "Synchronized doublets: %d\n"
00096 "Possible issues:\n"
00097 "\t* stereo_image_proc is not running.\n"
00098 "\t* The cameras are not synchronized.\n"
00099 "\t* The network is too slow. One or more images are dropped from each triplet.",
00100 left_received_, right_received_, all_received_);
00101 }
00102 }
00103 };
00104
00105 int main(int argc, char **argv)
00106 {
00107 ros::init(argc, argv, "anaglyph", ros::init_options::AnonymousName);
00108 ros::NodeHandle nh;
00109 if (ros::names::remap("stereo") == "stereo") {
00110 ROS_WARN("[stereo_view] stereo has not been remapped! Example command-line usage:\n"
00111 "\t$ rosrun image_view stereo_view stereo:=narrow_stereo image:=image_color");
00112 }
00113 if (ros::names::remap("image") == "/image_raw") {
00114 ROS_WARN("[stereo_view] There is a delay between when the camera drivers publish the raw "
00115 "images and when stereo_image_proc publishes the computed point cloud. stereo_view "
00116 "may fail to synchronize these topics.");
00117 }
00118
00119 Anaglyph3D ana(nh);
00120
00121 ros::spin();
00122 return 0;
00123 }