00001
00002 #include <ros/ros.h>
00003
00004 #include <image_transport/image_transport.h>
00005
00006 #include <cv_bridge/cv_bridge.h>
00007
00008 #include <sensor_msgs/image_encodings.h>
00009
00010 #include <opencv2/imgproc/imgproc.hpp>
00011
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
00039
00040 std::string _camera_image;
00041
00042
00043
00044 bool want2watch=0;
00045 string watch="";
00046
00047
00048
00049 namespace enc = sensor_msgs::image_encodings;
00050
00051
00052 static const char WINDOW[] = "Image Processed";
00053
00054
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
00063 void imageCallback(const sensor_msgs::ImageConstPtr& original_image)
00064 {
00065 cv_bridge::CvImagePtr cv_ptr;
00066
00067
00068
00069
00070 try
00071 {
00072
00073
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
00091 TheMarkers[i].draw_size(TheInputImageCopy,Scalar(0,0,255),1);
00092 }
00093
00094
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
00112 if(want2watch){
00113 cv::imshow(WINDOW, cv_ptr->image);
00114
00115 cv::waitKey(3);
00122
00123 pub_img.publish(cv_ptr->toImageMsg());
00124 }
00125
00127
00128
00129
00130
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
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
00147 cv::Rodrigues( TheMarkers[i].Rvec,Rotation_cam );
00148 Position_cam = -TheMarkers[i].Tvec.t() * Rotation_cam;
00149
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
00158
00159
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
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
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
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
00222
00223
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
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
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
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
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 }