display_manager.cpp
Go to the documentation of this file.
00001 
00002 #include <numeric>
00003 #include <ros/ros.h>
00004 #include <algorithm>
00005 
00006 #include <tf/transform_listener.h>
00007 #include <cv_bridge/cv_bridge.h>
00008 #include <image_transport/image_transport.h>
00009 #include <sensor_msgs/image_encodings.h>
00010 #include <geometry_msgs/PoseArray.h>
00011 #include <geometry_msgs/PolygonStamped.h>
00012 #include <geometry_msgs/Point.h>
00013 #include <visualization_msgs/Marker.h>
00014 #include <std_srvs/Empty.h>
00015 #include <std_msgs/Bool.h>
00016 #include <std_msgs/Int32.h>
00017 #include <cv_bridge/cv_bridge.h>
00018 #include <opencv/cv.h>
00019 #include <sensor_msgs/image_encodings.h>
00020 #include <image_geometry/pinhole_camera_model.h>
00021 
00022 #include <hrl_clickable_world/ClickImage.h>
00023 #include <hrl_clickable_world/DisplayButtons.h>
00024 #include <hrl_clickable_world/ButtonAction.h>
00025 #include <pixel_2_3d/Pixel23d.h>
00026 
00027 using namespace std;
00028 
00029 namespace hrl_clickable_world {
00030 
00031     class DisplayManager {
00032         public:
00033             ros::Publisher button_pushed_pub, perceive_pub;
00034             ros::ServiceServer display_buttons_srv, clear_buttons_srv, image_click_srv;
00035             ros::ServiceClient button_action_srv, pixel23d_srv;
00036             ros::Subscriber l_image_click_sub, r_image_click_sub;
00037             ros::NodeHandle nhdl;
00038             image_transport::ImageTransport img_trans;
00039             image_transport::CameraSubscriber camera_sub;
00040             image_transport::Publisher overlay_pub, button_pub;
00041             image_geometry::PinholeCameraModel cam_model;
00042             tf::TransformListener tf_listener;
00043             boost::shared_ptr<boost::thread> img_click_thread;
00044             boost::mutex img_click_lock;
00045 
00046             bool buttons_on;
00047             vector<visualization_msgs::Marker> buttons;
00048             vector<uint32_t> button_inds;
00049             vector<cv::Mat> button_rasters;
00050 
00051             DisplayManager();
00052             ~DisplayManager();
00053             void onInit();
00054             void doOverlay(const sensor_msgs::ImageConstPtr& img_msg,
00055                            const sensor_msgs::CameraInfoConstPtr& info_msg);
00056             bool imageClickSrvCB(ClickImage::Request& req, ClickImage::Response& resp);
00057             void lImageClickCB(const geometry_msgs::PointStamped& msg);
00058             void rImageClickCB(const geometry_msgs::PointStamped& msg);
00059             void doLImageClickCB(const geometry_msgs::PointStamped& msg);
00060             bool displayButtonsCB(DisplayButtons::Request& req, DisplayButtons::Response& resp);
00061             void displayButtonsCB(std::vector<visualization_msgs::Marker>& buttons_msg);
00062             bool clearButtonsCB(std_srvs::Empty::Request& req, std_srvs::Empty::Response& resp);
00063         
00064     };
00065 
00066     DisplayManager::DisplayManager() : nhdl("/clickable_world"), img_trans(nhdl) {
00067         onInit();
00068     }
00069 
00070     DisplayManager::~DisplayManager() {
00071     }
00072 
00073     void DisplayManager::onInit() {
00074         buttons_on = false;
00075         camera_sub = img_trans.subscribeCamera<DisplayManager>
00076                                               ("/image", 1, 
00077                                                &DisplayManager::doOverlay, this);
00078         overlay_pub = img_trans.advertise("image_buttons", 1);
00079         button_pub = img_trans.advertise("image_buttons_mask", 1);
00080         button_pushed_pub = nhdl.advertise<std_msgs::Int32>("button_pushed", 1);
00081         perceive_pub = nhdl.advertise<std_msgs::Bool>("perceive_buttons", 1);
00082         image_click_srv = nhdl.advertiseService("click_image", 
00083                                                 &DisplayManager::imageClickSrvCB, this);
00084         l_image_click_sub = nhdl.subscribe("l_mouse_click", 1, 
00085                                            &DisplayManager::lImageClickCB, this);
00086         r_image_click_sub = nhdl.subscribe("r_mouse_click", 1, 
00087                                            &DisplayManager::rImageClickCB, this);
00088 
00089         display_buttons_srv = nhdl.advertiseService("display_buttons", 
00090                                                 &DisplayManager::displayButtonsCB, this);
00091         button_action_srv = nhdl.serviceClient<ButtonAction>("button_action");
00092         pixel23d_srv = nhdl.serviceClient<pixel_2_3d::Pixel23d>("/pixel_2_3d");
00093         ROS_INFO("[display_manager] DisplayManager loaded.");
00094     }
00095 
00096     void DisplayManager::doOverlay(const sensor_msgs::ImageConstPtr& img_msg,
00097                                    const sensor_msgs::CameraInfoConstPtr& info_msg) {
00098 
00099         // convert camera image into opencv
00100         cam_model.fromCameraInfo(info_msg);
00101         cv_bridge::CvImagePtr cv_img = cv_bridge::toCvCopy(img_msg, sensor_msgs::image_encodings::RGB8);
00102         if(!buttons_on) {
00103             // buttons turned off so we don't do anything to the image
00104             overlay_pub.publish(cv_img->toImageMsg());
00105             return;
00106         }
00107 
00108         cv::Size resolution = cam_model.fullResolution();
00109         cv::Mat button_raster_back = cv::Mat::zeros(resolution.width, resolution.height, CV_8UC1);
00110         for(uint32_t i=0;i<buttons.size();i++) {
00111             visualization_msgs::Marker button = buttons[i];
00112             cv::Scalar color = CV_RGB(button.color.r, button.color.g, button.color.b);
00113 
00114             // project polygon onto image
00115             cv::Point* cv_poly = new cv::Point[button.points.size()];
00116             for(uint32_t j=0;j<button.points.size();j++) {
00117                 geometry_msgs::PointStamped cur_pt, proj_pt;
00118                 cur_pt.header = button.header; cur_pt.point = button.points[j];
00119                 cur_pt.header.stamp = ros::Time(0);
00120                 tf_listener.transformPoint(cam_model.tfFrame(), cur_pt, proj_pt);
00121                 cv::Point3d proj_pt_cv(proj_pt.point.x, proj_pt.point.y, proj_pt.point.z);
00122                 cv_poly[j] = cam_model.project3dToPixel(proj_pt_cv);
00123                 if(cv_poly[j].x < 0) cv_poly[j].x = 0;
00124                 if(cv_poly[j].y < 0) cv_poly[j].y = 0;
00125                 if(cv_poly[j].x >= resolution.width-1) cv_poly[j].x = resolution.width-2;
00126                 if(cv_poly[j].y >= resolution.height-1) cv_poly[j].y = resolution.height-2;
00127             }
00128 
00129             // fill a raster image with this button
00130             const cv::Point** cv_poly_list = new const cv::Point*[1]; 
00131             cv_poly_list[0] = cv_poly;
00132             int* npts = new int[1]; npts[0] = button.points.size()-1;
00133             //cv::Mat button_raster_cur = cv::Mat::zeros(resolution.width, resolution.height, CV_8UC3);
00134             cv::fillPoly(button_raster_back, cv_poly_list, npts, 1, cv::Scalar(i+1));
00135             //cv::max(button_raster_back, button_raster_cur, button_raster_back);
00136             // etch polygon on image
00137             cv::polylines(cv_img->image, cv_poly_list, npts, 1, 1, color, 2);
00138             delete[] npts; delete[] cv_poly; delete[] cv_poly_list;
00139             button_rasters[i] = button_raster_back;
00140         }
00141         overlay_pub.publish(cv_img->toImageMsg());
00142         //button_pub.publish(cv_img->toImageMsg());
00143     }
00144 
00145     bool DisplayManager::imageClickSrvCB(ClickImage::Request& req, ClickImage::Response& resp) {
00146         lImageClickCB(req.image_click);
00147         return true;
00148     }
00149     
00150     void DisplayManager::lImageClickCB(const geometry_msgs::PointStamped& image_click) {
00151         if(img_click_lock.try_lock())
00152             img_click_thread = boost::shared_ptr<boost::thread>(
00153                                       new boost::thread(
00154                                           boost::bind(&DisplayManager::doLImageClickCB,
00155                                                       this, image_click)));
00156     }
00157 
00158     void DisplayManager::rImageClickCB(const geometry_msgs::PointStamped& msg) {
00159         if(img_click_lock.try_lock()) {
00160             std_msgs::Bool bool_msg;
00161             perceive_pub.publish(bool_msg);
00162             img_click_lock.unlock();
00163         }
00164     }
00165     
00166     void DisplayManager::doLImageClickCB(const geometry_msgs::PointStamped& image_click) {
00167         if(buttons_on) {
00168             buttons_on = false;
00169             //figure out which button was clicked on
00170             uint8_t button_id = 0;
00171             for(uint32_t i=0;i<button_rasters.size();i++) {
00172                 button_id = button_rasters[i].at<uint8_t>(image_click.point.y, 
00173                                                           image_click.point.x);
00174                 if(button_id != 0)
00175                     break;
00176             }
00177             ROS_INFO("[display_manager] Image click recieved: (Pix_X: %f, Pix_Y: %f, ID: %d)", 
00178                                                  image_click.point.x, image_click.point.y, 
00179                                                  (int) button_id);
00180             // don't process a click not on a button
00181             if(button_id != 0) {
00182                 ROS_INFO("Num buttons: %d", (int) buttons.size());
00183                 // Make button action given known information about button press.
00184                 ButtonAction::Request ba_req;
00185                 ba_req.pixel_x = image_click.point.x; ba_req.pixel_y = image_click.point.y;
00186                 ba_req.camera_frame = cam_model.tfFrame();
00187                 ba_req.button_id = buttons[button_id-1].id;
00188                 ba_req.button_type = buttons[button_id-1].id; 
00189                 pixel_2_3d::Pixel23d::Request p3d_req; pixel_2_3d::Pixel23d::Response p3d_resp;
00190                 p3d_req.pixel.point.x = image_click.point.x; p3d_req.pixel.point.y = image_click.point.y; 
00191                 pixel23d_srv.call(p3d_req, p3d_resp);
00192                 ba_req.pixel3d.header.frame_id = p3d_resp.pixel3d.header.frame_id;
00193                 ba_req.pixel3d.header.stamp = p3d_resp.pixel3d.header.stamp;
00194                 ba_req.pixel3d.point.x = p3d_resp.pixel3d.point.x;
00195                 ba_req.pixel3d.point.y = p3d_resp.pixel3d.point.y;
00196                 ba_req.pixel3d.point.z = p3d_resp.pixel3d.point.z;
00197                 ButtonAction::Response ba_resp;
00198                 button_action_srv.call(ba_req, ba_resp);
00199             }
00200         }
00201         img_click_lock.unlock();
00202     }
00203 
00204     bool DisplayManager::displayButtonsCB(DisplayButtons::Request& req, 
00205                                           DisplayButtons::Response& resp) {
00206         displayButtonsCB(req.buttons);
00207         return true;
00208     }
00209 
00210     void DisplayManager::displayButtonsCB(std::vector<visualization_msgs::Marker>& buttons_msg) {
00211         buttons = buttons_msg;
00212         buttons_on = true;
00213         button_rasters.resize(buttons.size());
00214         cv::Size resolution = cam_model.fullResolution();
00215         for(uint32_t i=0;i<buttons.size();i++)
00216             button_rasters[i] = cv::Mat::zeros(resolution.width, resolution.height, CV_8UC1);
00217     }
00218 
00219     bool DisplayManager::clearButtonsCB(std_srvs::Empty::Request& req, std_srvs::Empty::Response& resp) {
00220         buttons_on = false;
00221         return true;
00222     }
00223 
00224 };
00225 
00226 using namespace hrl_clickable_world;
00227 
00228 int main(int argc, char **argv)
00229 {
00230     ros::init(argc, argv, "display_manager");
00231     DisplayManager dm;
00232     ros::spin();
00233     return 0;
00234 }


hrl_clickable_world
Author(s): Kelsey Hawkins, Advisor: Prof. Charlie Kemp (Healthcare Robotics Lab at Georgia Tech)
autogenerated on Wed Nov 27 2013 11:54:29