arrow_overlay.cpp
Go to the documentation of this file.
00001 #include <numeric>
00002 #include <ros/ros.h>
00003 #include <algorithm>
00004 
00005 #include <tf/transform_listener.h>
00006 #include <cv_bridge/cv_bridge.h>
00007 #include <image_transport/image_transport.h>
00008 #include <sensor_msgs/image_encodings.h>
00009 #include <geometry_msgs/PoseArray.h>
00010 #include <geometry_msgs/PolygonStamped.h>
00011 #include <geometry_msgs/Point.h>
00012 #include <visualization_msgs/Marker.h>
00013 #include <std_srvs/Empty.h>
00014 #include <std_msgs/Bool.h>
00015 #include <std_msgs/Int32.h>
00016 #include <cv_bridge/cv_bridge.h>
00017 #include <opencv/cv.h>
00018 #include <sensor_msgs/image_encodings.h>
00019 #include <image_geometry/pinhole_camera_model.h>
00020 
00021 #include <hrl_clickable_display/ArrowOverlayCmd.h>
00022 
00023 using namespace std;
00024 
00025 namespace hrl_clickable_display {
00026 
00027     class ArrowOverlay {
00028         public:
00029             ros::NodeHandle nh;
00030             ros::Subscriber command_sub;
00031             ros::Subscriber pixel3d_sub;
00032             image_transport::ImageTransport img_trans;
00033             image_transport::CameraSubscriber camera_sub;
00034             image_transport::Publisher overlay_pub;
00035             image_geometry::PinholeCameraModel cam_model;
00036             tf::TransformListener tf_listener;
00037             double ARROW_POINTS[7][3];
00038             bool auto_clear;
00039 
00040             std::vector<geometry_msgs::PoseStamped> arrows;
00041 
00042             ArrowOverlay();
00043             ~ArrowOverlay();
00044             void onInit();
00045             void doOverlay(const sensor_msgs::ImageConstPtr& img_msg,
00046                            const sensor_msgs::CameraInfoConstPtr& info_msg);
00047             void processCommand(const ArrowOverlayCmd& msg);
00048             void pixelCallback(const geometry_msgs::PoseStamped& msg);
00049     };
00050 
00051     ArrowOverlay::ArrowOverlay() : nh("~"), img_trans(nh) {
00052     }
00053 
00054     ArrowOverlay::~ArrowOverlay() {
00055     }
00056 
00057     void ArrowOverlay::onInit() {
00058         double A, B, C;
00059         bool debug;
00060         nh.param<double>("shaft_size", A, 0.1);
00061         nh.param<double>("head_width", B, 0.03);
00062         nh.param<double>("head_length", C, 0.03);
00063         nh.param<bool>("debug_mode", debug, false);
00064         nh.param<bool>("auto_clear", auto_clear, false);
00065         ARROW_POINTS[0][0] = 0;    ARROW_POINTS[0][1] = 0;    ARROW_POINTS[0][2] = 0;
00066         ARROW_POINTS[1][0] = 0;    ARROW_POINTS[1][1] = 0;    ARROW_POINTS[1][2] = A;
00067         ARROW_POINTS[2][0] = -B/2; ARROW_POINTS[2][1] = -B/2; ARROW_POINTS[2][2] = A;
00068         ARROW_POINTS[3][0] =  B/2; ARROW_POINTS[3][1] = -B/2; ARROW_POINTS[3][2] = A;
00069         ARROW_POINTS[4][0] =  B/2; ARROW_POINTS[4][1] =  B/2; ARROW_POINTS[4][2] = A;
00070         ARROW_POINTS[5][0] = -B/2; ARROW_POINTS[5][1] =  B/2; ARROW_POINTS[5][2] = A;
00071         ARROW_POINTS[6][0] = 0;    ARROW_POINTS[6][1] = 0;    ARROW_POINTS[6][2] = A+C;
00072 
00073         camera_sub = img_trans.subscribeCamera<ArrowOverlay>
00074                                               ("/image_in", 1, 
00075                                                &ArrowOverlay::doOverlay, this);
00076         overlay_pub = img_trans.advertise("/image_out", 1);
00077 
00078         command_sub = nh.subscribe("arrow_command", 1, 
00079                                            &ArrowOverlay::processCommand, this);
00080 
00081         if(debug) {
00082             pixel3d_sub = nh.subscribe("/pixel3d", 1, 
00083                                                &ArrowOverlay::pixelCallback, this);
00084         }
00085         ROS_INFO("[display_manager] ArrowOverlay loaded.");
00086     }
00087 
00088     void ArrowOverlay::doOverlay(const sensor_msgs::ImageConstPtr& img_msg,
00089                                    const sensor_msgs::CameraInfoConstPtr& info_msg) {
00090 
00091         // convert camera image into opencv
00092         cam_model.fromCameraInfo(info_msg);
00093         cv_bridge::CvImagePtr cv_img = cv_bridge::toCvCopy(img_msg, sensor_msgs::image_encodings::RGB8);
00094 
00095         for(uint32_t i=0;i<arrows.size();i++) {
00096             // get arrow's rotation matrix
00097             tf::Pose arrow_pose;
00098             tf::poseMsgToTF(arrows[i].pose, arrow_pose);
00099             std::vector<cv::Point> cv_pts;
00100             for(int j=0;j<7;j++) {
00101                 //geometry_msgs::PointStamped arr_pt;
00102                 btVector4 arr_pt;
00103                 arr_pt.setX(ARROW_POINTS[j][0]);
00104                 arr_pt.setY(ARROW_POINTS[j][1]);
00105                 arr_pt.setZ(ARROW_POINTS[j][2]);
00106                 arr_pt.setW(1);
00107                 tf::Vector3 arr_pt_rot = arrow_pose * arr_pt;
00108                 cv::Point3d proj_pt_cv(arr_pt_rot.getX(), arr_pt_rot.getY(), arr_pt_rot.getZ());
00109                 cv::Point pt2d = cam_model.project3dToPixel(proj_pt_cv);
00110                 cv_pts.push_back(pt2d);
00111             }
00112             const cv::Point** cv_poly_list = new const cv::Point*[6];
00113             cv::Point* shaft = new cv::Point[2];
00114             shaft[0] = cv_pts[0]; shaft[1] = cv_pts[1]; 
00115             cv::Point* base = new cv::Point[5];
00116             base[0] = cv_pts[2]; base[1] = cv_pts[3]; base[2] = cv_pts[4]; 
00117             base[3] = cv_pts[5];  base[4] = cv_pts[2]; 
00118             cv::Point* pyrm1 = new cv::Point[2];
00119             pyrm1[0] = cv_pts[2]; pyrm1[1] = cv_pts[6]; 
00120             cv::Point* pyrm2 = new cv::Point[2];
00121             pyrm2[0] = cv_pts[3]; pyrm2[1] = cv_pts[6]; 
00122             cv::Point* pyrm3 = new cv::Point[2];
00123             pyrm3[0] = cv_pts[4]; pyrm3[1] = cv_pts[6]; 
00124             cv::Point* pyrm4 = new cv::Point[2];
00125             pyrm4[0] = cv_pts[5]; pyrm4[1] = cv_pts[6]; 
00126             cv_poly_list[0] = shaft; cv_poly_list[1] = base; cv_poly_list[2] = pyrm1;
00127             cv_poly_list[3] = pyrm2; cv_poly_list[4] = pyrm3; cv_poly_list[5] = pyrm4;
00128             cv::Scalar color = CV_RGB(255, 0, 0);
00129             int npts[6] = {2, 5, 2, 2, 2, 2};
00130             cv::polylines(cv_img->image, cv_poly_list, npts, 6, 0, color, 1);
00131         }
00132 
00133         overlay_pub.publish(cv_img->toImageMsg());
00134     }
00135 
00136     void ArrowOverlay::processCommand(const ArrowOverlayCmd& msg) {
00137         if(msg.clear_arrows)
00138             arrows.clear();
00139         else {
00140             for(uint32_t i=0;i<msg.arrows.size();i++) {
00141                 geometry_msgs::PoseStamped new_arrow;
00142                 tf_listener.transformPose(cam_model.tfFrame(), ros::Time(0), msg.arrows[i], msg.arrows[i].header.frame_id, new_arrow);
00143                 arrows.push_back(new_arrow);
00144             }
00145         }
00146     }
00147 
00148     void ArrowOverlay::pixelCallback(const geometry_msgs::PoseStamped& msg) {
00149         if(auto_clear)
00150             arrows.clear();
00151         geometry_msgs::PoseStamped new_arrow;
00152         tf_listener.transformPose(cam_model.tfFrame(), ros::Time(0), msg, msg.header.frame_id, new_arrow);
00153         arrows.push_back(new_arrow);
00154     }
00155 
00156 };
00157 
00158 using namespace hrl_clickable_display;
00159 
00160 int main(int argc, char **argv)
00161 {
00162     ros::init(argc, argv, "arrow_overlay");
00163     ArrowOverlay ao;
00164     ao.onInit();
00165     ros::spin();
00166     return 0;
00167 }


hrl_clickable_display
Author(s): Author: Kelsey Hawkins, Advisor: Prof. Charlie Kemp (Healthcare Robotics Lab at Georgia Tech)
autogenerated on Wed Nov 27 2013 12:07:49