main.cpp
Go to the documentation of this file.
00001 //Includes all the headers necessary to use the most common public pieces of the ROS system.
00002 #include <ros/ros.h>
00003 //Use image_transport for publishing and subscribing to images in ROS
00004 #include <image_transport/image_transport.h>
00005 //Use cv_bridge to convert between ROS and OpenCV Image formats
00006 #include <cv_bridge/cv_bridge.h>
00007 //Include some useful constants for image encoding. Refer to: http://www.ros.org/doc/api/sensor_msgs/html/namespacesensor__msgs_1_1image__encodings.html for more info.
00008 #include <sensor_msgs/image_encodings.h>
00009 //Include headers for OpenCV Image processing
00010 #include <opencv2/imgproc/imgproc.hpp>
00011 //Include headers for OpenCV GUI handling
00012 #include <opencv2/highgui/highgui.hpp>
00013 
00014 #include <geometry_msgs/PoseStamped.h>
00015 
00016 #include "aruco/aruco.h"
00017 #include "aruco/cvdrawingutils.h"
00018 #include "MarkersConfig.h"
00019 #include <iostream>
00020 #include <fstream>
00021 #include <sstream>
00022 
00023 #include <tf/transform_broadcaster.h>
00024 
00025 
00026 using namespace cv;
00027 using namespace aruco;
00028 
00029 
00030 
00031 double TheMarkerSize=0.057;
00032 MarkerDetector MDetector;
00033 vector<Marker> TheMarkers;
00034 Mat TheInputImage,TheInputImageCopy;
00035 CameraParameters TheCameraParameters;
00036 geometry_msgs::PoseStamped t_camera_pose;
00037 geometry_msgs::PointStamped t_pixel_disp;
00038 //tf::TransformBroadcaster t_br_camera_pose;
00039 
00040 std::string _camera_image;
00041 
00042 
00043 
00044 bool want2watch=0;
00045 string watch="";
00046 
00047 
00048 //Store all constants for image encodings in the enc namespace to be used later.
00049 namespace enc = sensor_msgs::image_encodings;
00050  
00051 //Declare a string with the name of the window that we will create using OpenCV where processed images will be displayed.
00052 static const char WINDOW[] = "Image Processed";
00053  
00054 //Use method of ImageTransport to create image publisher
00055 image_transport::Publisher pub_img;
00056 ros::Publisher pub_pose, pub_pose_all;
00057 ros::Publisher pub_pixels_disp;
00058 MarkersConfig Markers_Sizes;
00059 geometry_msgs::PoseStamped camera_pose_mean;
00060 
00061 
00062 //This function is called everytime a new image is published
00063 void imageCallback(const sensor_msgs::ImageConstPtr& original_image)
00064 {
00065     cv_bridge::CvImagePtr cv_ptr;    //Convert from the ROS image message to a CvImage suitable for working with OpenCV for processing
00066 
00067 
00068 
00069 
00070     try
00071     {
00072         //Always copy, returning a mutable CvImage
00073         //OpenCV expects color images to use BGR channel order.
00074         cv_ptr = cv_bridge::toCvCopy(original_image, enc::BGR8);
00075 
00076     }
00077     catch (cv_bridge::Exception& e)
00078     {
00079         ROS_ERROR("tutorialROSOpenCV::main.cpp::cv_bridge exception: %s", e.what());
00080         return;
00081     }
00082 
00083 
00085     TheInputImage = cv_ptr->image;
00086     MDetector.detect2(TheInputImage,TheMarkers,TheCameraParameters,Markers_Sizes.msize,Markers_Sizes.mposition, false);
00087 
00088     TheInputImage.copyTo(TheInputImageCopy);
00089     for (unsigned int i=0;i<TheMarkers.size();i++) {
00090 //        ROS_INFO("Cenas: " << TheMarkers[i]<<endl);
00091         TheMarkers[i].draw_size(TheInputImageCopy,Scalar(0,0,255),1);
00092     }
00093 
00094 //    std::cout << "Has value - " << std::boolalpha <<  TheCameraParameters.isValid() << endl;
00095 
00096     if (  TheCameraParameters.isValid())
00097         for (unsigned int i=0;i<TheMarkers.size();i++) {
00098             CvDrawingUtils::draw3dAxis(TheInputImageCopy,TheMarkers[i],TheCameraParameters);
00099             CvDrawingUtils::draw3dCube_z(TheInputImageCopy,TheMarkers[i],TheCameraParameters);
00100             cv::circle(TheInputImageCopy,TheMarkers[i].marker_center_img,5, Scalar(0,255,255,255),5);
00101         }
00102 
00103     cv_ptr->image = TheInputImageCopy;
00105 
00106 
00107 
00108 
00109 
00110  
00111     //Display the image using OpenCV
00112     if(want2watch){
00113         cv::imshow(WINDOW, cv_ptr->image);
00114         //Add some delay in miliseconds. The function only works if there is at least one HighGUI window created and the window is active. If there are several HighGUI windows, any of them can be active.
00115         cv::waitKey(3);
00122         //Convert the CvImage to a ROS image message and publish it on the "camera/image_processed" topic.
00123         pub_img.publish(cv_ptr->toImageMsg());
00124     }
00125 
00127 
00128 //    if (TheMarkers.size() != 1) {
00129 //        if (TheMarkers.size() > 1) cout << ros::Time::now() << " Ahhhhhh <=> " << TheMarkers.size() << endl;
00130 //        return;
00131 //    }
00132 
00133 
00134 
00135     cv::Mat Rotation_cam(3,3,CV_32FC1);
00136     cv::Mat Position_cam(3,1,CV_32FC1);
00137 
00138 
00139     // to keep the mean
00140     geometry_msgs::PoseStamped cam_pose_aux;
00141     cam_pose_aux.pose.position.x=cam_pose_aux.pose.position.y=cam_pose_aux.pose.position.z=0.0;
00142     cam_pose_aux.pose.orientation.w=cam_pose_aux.pose.orientation.x=cam_pose_aux.pose.orientation.y=cam_pose_aux.pose.orientation.z=0.0;
00143 
00144     if (  TheCameraParameters.isValid()){
00145         for (unsigned int i=0;i<TheMarkers.size();i++) {
00146             // Ts * Rodrigues(Rs)
00147             cv::Rodrigues( TheMarkers[i].Rvec,Rotation_cam );
00148             Position_cam = -TheMarkers[i].Tvec.t() * Rotation_cam;
00149 //            Position_cam = -Rotation_cam.t() * TheMarkers[i].Tvec;
00150             Position_cam = Position_cam.t();
00151 
00152 
00153 
00155 
00156             double qw = sqrt(1 + Rotation_cam.at<double>(0,0) + Rotation_cam.at<double>(1,1) + Rotation_cam.at<double>(2,2))/2;
00157         //    double qx = (Rotation_cam.at<double>(2,1) - Rotation_cam.at<double>(1,2))/( 4 *qw);
00158         //    double qy = (Rotation_cam.at<double>(0,2) - Rotation_cam.at<double>(2,0))/( 4 *qw);
00159         //    double qz = (Rotation_cam.at<double>(1,0) - Rotation_cam.at<double>(0,1))/( 4 *qw);
00160             double qx = (Rotation_cam.at<double>(1,2) - Rotation_cam.at<double>(2,1))/( 4 *qw);
00161             double qy = (Rotation_cam.at<double>(2,0) - Rotation_cam.at<double>(0,2))/( 4 *qw);
00162             double qz = (Rotation_cam.at<double>(0,1) - Rotation_cam.at<double>(1,0))/( 4 *qw);
00163 
00165 
00166             // To use in mean
00167             cam_pose_aux.pose.orientation.w  += qw;
00168             cam_pose_aux.pose.orientation.x  += qx;
00169             cam_pose_aux.pose.orientation.y  += qy;
00170             cam_pose_aux.pose.orientation.z  += qz;
00171             cam_pose_aux.pose.position.x     += Position_cam.at<double>(0,0);
00172             cam_pose_aux.pose.position.y     += Position_cam.at<double>(0,1);
00173             cam_pose_aux.pose.position.z     += Position_cam.at<double>(0,2);
00175 
00176 
00177             t_camera_pose.header.frame_id="quad_cam" +  boost::lexical_cast<string>(TheMarkers[i].id) ;
00178             t_camera_pose.header.stamp = ros::Time::now();
00179             t_camera_pose.pose.position.x = Position_cam.at<double>(0,0);
00180             t_camera_pose.pose.position.y = Position_cam.at<double>(0,1);
00181             t_camera_pose.pose.position.z = Position_cam.at<double>(0,2);
00182             t_camera_pose.pose.orientation.x = qx;
00183             t_camera_pose.pose.orientation.y = qy;
00184             t_camera_pose.pose.orientation.z = qz;
00185             t_camera_pose.pose.orientation.w = qw;
00186 
00187 
00188             // isto não está a funcionar!!!
00189 
00190             if (  TheCameraParameters.isValid()){
00191                 double y_sum=0, x_sum=0;
00192                 for (uint i=0; i < TheMarkers.size(); i++){
00193                     x_sum+= TheMarkers[i].marker_center_img.x;
00194                     y_sum+= TheMarkers[i].marker_center_img.y;
00195                 }
00196                 x_sum /= TheMarkers.size();
00197                 y_sum /= TheMarkers.size();
00198 
00199                 t_pixel_disp.header.frame_id = "Displacement_in_img";
00200                 t_pixel_disp.header.stamp = ros::Time::now();
00201                 t_pixel_disp.point.x = (double) x_sum/TheMarkers.size() - (double) TheCameraParameters.CamSize.width/2;
00202                 t_pixel_disp.point.y = (double) y_sum/TheMarkers.size() - (double)  TheCameraParameters.CamSize.height/2;
00203             }
00204 
00205             ROS_INFO("%lf  %lf",t_pixel_disp.point.x, t_pixel_disp.point.y);
00206 
00207             pub_pixels_disp.publish(t_pixel_disp);
00208 
00210 
00211             pub_pose_all.publish(t_camera_pose);
00212 
00213 
00214             static tf::TransformBroadcaster t_br_camera_pose;
00215             tf::Transform tf_quad;
00216 
00217             // adds the translation of each marker
00218             tf_quad.setOrigin( tf::Vector3(t_camera_pose.pose.position.x+Markers_Sizes.mposition.at(TheMarkers[i].id).x,
00219                                            t_camera_pose.pose.position.y+Markers_Sizes.mposition.at(TheMarkers[i].id).y,
00220                                            t_camera_pose.pose.position.z+Markers_Sizes.mposition.at(TheMarkers[i].id).z) );
00221 //            tf_quad.setOrigin( tf::Vector3(t_camera_pose.pose.position.x,
00222 //                                           t_camera_pose.pose.position.y,
00223 //                                           t_camera_pose.pose.position.z) );
00224             tf_quad.setRotation( (const tf::Quaternion&) t_camera_pose.pose.orientation);
00225 
00226             t_br_camera_pose.sendTransform(tf::StampedTransform(tf_quad, ros::Time::now(), "ref_marker", boost::lexical_cast<string>(TheMarkers[i].id)));
00227 
00228 
00229             // debug:
00230             ROS_INFO_STREAM("published id="<<TheMarkers[i].id);
00231         }
00232 
00233 
00234         cam_pose_aux.header.frame_id="quad_cam_mean_no_detect";
00235         cam_pose_aux.header.stamp = ros::Time::now();
00236 
00237         if (TheMarkers.size() > 0){
00238             // Calculate mean position
00239 
00240             cam_pose_aux.header.frame_id="quad_cam_mean";
00241             cam_pose_aux.pose.orientation.w  /= TheMarkers.size();
00242             cam_pose_aux.pose.orientation.x  /= TheMarkers.size();
00243             cam_pose_aux.pose.orientation.y  /= TheMarkers.size();
00244             cam_pose_aux.pose.orientation.z  /= TheMarkers.size();
00245             cam_pose_aux.pose.position.x     /= TheMarkers.size();
00246             cam_pose_aux.pose.position.y     /= TheMarkers.size();
00247             cam_pose_aux.pose.position.z     /= TheMarkers.size();
00248 
00249             camera_pose_mean = cam_pose_aux;
00250 
00251 
00252             static tf::TransformBroadcaster t_br_camera_pose_mean;
00253             tf::Transform tf_quad_mean;
00254 
00255             // adds the translation of each marker
00256             tf_quad_mean.setOrigin( tf::Vector3(cam_pose_aux.pose.position.x,
00257                                            cam_pose_aux.pose.position.y,
00258                                            cam_pose_aux.pose.position.z ));
00259             tf_quad_mean.setRotation( (const tf::Quaternion&) t_camera_pose.pose.orientation);
00260 
00261             t_br_camera_pose_mean.sendTransform(tf::StampedTransform(tf_quad_mean, ros::Time::now(), "ref_marker", "cam_pose_mean"));
00262 
00263 
00264         }
00265 
00266         pub_pose.publish(camera_pose_mean);
00267 
00268     }
00269 }
00270  
00271 
00272 
00273 int main(int argc, char **argv)
00274 {
00275 
00276     ros::init(argc, argv, "camera_pose_aruco");
00277     ros::NodeHandle nh("~");
00278 
00279     //Create an ImageTransport instance, initializing it with our NodeHandle.
00280     image_transport::ImageTransport it(nh);
00281 
00282     std::string _markers_config_file;
00283     std::string _camara_calib_file;
00284 
00285 
00286     nh.param<std::string>("markers_config_file",_markers_config_file,"markers_sizes_aruco.txt");
00287     nh.param<std::string>("camara_calib_file",_camara_calib_file,"cam_parameters_aruco.txt");
00288     nh.param<std::string>("image",_camera_image,"usb_cam/image_raw");
00289 
00290     ROS_INFO_STREAM(_markers_config_file << " " << _camara_calib_file << " " << _camera_image);
00291 
00292     Markers_Sizes.parse_from_file(_markers_config_file,0.057);
00293     TheCameraParameters.readFromFile(_camara_calib_file);
00294 
00295     if(!TheCameraParameters.isValid())
00296         cout << "Warning! The file with camera parameters was NOT detected" << endl;
00297     else
00298         cout << "The file with camera parameters was correctly read." << endl << "Starting to publish pose_cam" << endl;
00299 
00300     MDetector.setThresholdParams(7, 7);
00301     MDetector.setCornerRefinementMethod(MarkerDetector::LINES);
00302 
00303 
00304     if(watch.compare("true")){ want2watch=true;}
00305 
00306     if(want2watch)
00307         cv::namedWindow(WINDOW, CV_WINDOW_AUTOSIZE);
00308 
00309     image_transport::Subscriber sub = it.subscribe(_camera_image, 1, imageCallback);
00310 
00311     if(want2watch)
00312         cv::destroyWindow(WINDOW);
00313 
00314     if(want2watch)
00315         pub_img = it.advertise("image_processed", 1);
00316 
00317     pub_pose_all = nh.advertise<geometry_msgs::PoseStamped>("pose_cam_all",15);
00318     pub_pose = nh.advertise<geometry_msgs::PoseStamped>("pose_cam",5);
00319     pub_pixels_disp = nh.advertise<geometry_msgs::PointStamped>("pixel_disp",5);
00320 
00321     ros::spin();
00322     ROS_INFO("tutorialROSOpenCV::main.cpp::No error.");
00323 
00324 
00325     return 0;
00326 }


camera_pose_aruco
Author(s): tcarreira
autogenerated on Mon Jan 6 2014 11:47:56