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
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
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
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
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
00134 cv::fillPoly(button_raster_back, cv_poly_list, npts, 1, cv::Scalar(i+1));
00135
00136
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
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
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
00181 if(button_id != 0) {
00182 ROS_INFO("Num buttons: %d", (int) buttons.size());
00183
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 }