datamatrix_calculations_node.cpp
Go to the documentation of this file.
00001 /**************************************************************************************************
00002  Software License Agreement (BSD License)
00003 
00004  Copyright (c) 2011-2014, LAR toolkit developers - University of Aveiro - http://lars.mec.ua.pt
00005  All rights reserved.
00006 
00007  Redistribution and use in source and binary forms, with or without modification, are permitted
00008  provided that the following conditions are met:
00009 
00010   *Redistributions of source code must retain the above copyright notice, this list of
00011    conditions and the following disclaimer.
00012   *Redistributions in binary form must reproduce the above copyright notice, this list of
00013    conditions and the following disclaimer in the documentation and/or other materials provided
00014    with the distribution.
00015   *Neither the name of the University of Aveiro nor the names of its contributors may be used to
00016    endorse or promote products derived from this software without specific prior written permission.
00017  
00018  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
00019  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
00020  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
00021  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
00024  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
00025  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026 ***************************************************************************************************/
00027 
00028 #include <iostream>
00029 #include <string>
00030 
00031 #include <ros/ros.h>
00032 
00033 #include <datamatrix_detection/DatamatrixMsg.h>
00034 
00035 #include <image_transport/image_transport.h>
00036 #include <cv_bridge/cv_bridge.h>
00037 #include <sensor_msgs/image_encodings.h>
00038 
00039 #include <opencv2/imgproc/imgproc.hpp>
00040 #include <opencv2/highgui/highgui.hpp>
00041 
00042 #include <boost/format.hpp>
00043 #include <boost/shared_ptr.hpp>
00044 
00045 #include <cmath>
00046 
00047 // 
00048 
00049 // class my_super_vector 
00050 // {
00051 //     public:
00052 //         std::vector<double> data;
00053 //         std::vector<double> timestamp;
00054 //     
00055 //         void push_back(double val)
00056 //         {
00057 //             data.push_back(val);
00058 //         }
00059 //         
00060 //         double operator[](int i)
00061 //         {
00062 //             return data[i];
00063 //         }
00064 //         
00065 //         double meanPos(int size)
00066 //         {
00067 // //             for
00068 //         }
00069 //         
00070 // };
00071 // 
00072 // my_super_vector vec;
00073 // 
00074 // vec.push_back(4);
00075 // cout<<"vopc_: "<< vec.timestamp[0]<<endl
00076 
00077 class GlobalPosition: public cv::Point2d
00078 {
00079     public:
00080         
00081         GlobalPosition()
00082         {
00083             phi = 0;
00084             x = 0;
00085             y = 0;
00086         }
00087         
00088         GlobalPosition(double x_,double y_,double phi_):
00089         Point_(x_,y_)
00090         {
00091             phi = phi_;
00092         }
00093         
00094         GlobalPosition operator=(const cv::Point2d& p)
00095         {
00096             return GlobalPosition(p.x,p.y,0);
00097         }
00098         
00099         typedef boost::shared_ptr<GlobalPosition> Ptr;
00100         
00101         double phi;
00102 };
00103 
00104 
00105 GlobalPosition operator+(const GlobalPosition& p1,const GlobalPosition& p2)
00106 {
00107     cv::Point2d po = static_cast<cv::Point2d>(p1)+static_cast<cv::Point2d>(p2);
00108  
00109     return GlobalPosition(po.x,po.y,p1.phi+p2.phi);
00110 }
00111 
00112 GlobalPosition::Ptr operator+(const GlobalPosition::Ptr& p1,const GlobalPosition::Ptr& p2)
00113 {
00114     return boost::make_shared<GlobalPosition>(*p1 + *p2);
00115 }
00116 
00117 GlobalPosition operator/(const GlobalPosition& p1, double i)
00118 {
00119     return GlobalPosition(p1.x / i,p1.y / i ,p1.phi / i);
00120 }
00121 
00122 GlobalPosition::Ptr operator/(const GlobalPosition::Ptr& p1, double i)
00123 {
00124     return boost::make_shared<GlobalPosition>(*p1/i);
00125 }
00126 
00127 GlobalPosition operator*(const GlobalPosition& p1, double i)
00128 {
00129     return GlobalPosition(p1.x * i,p1.y * i ,p1.phi * i);
00130 }
00131 
00132 GlobalPosition::Ptr operator*(const GlobalPosition::Ptr& p1, double i)
00133 {
00134     return boost::make_shared<GlobalPosition>(*p1 * i);
00135 }
00136 
00137 class DataMatrixPosition
00138 {
00139   ros::NodeHandle nh_;
00140   ros::Subscriber datamatrix_sub;
00141   ros::Subscriber camera_info_sub;
00142   
00143 //   Image transport handler and subscriber
00144   image_transport::ImageTransport it_;
00145   image_transport::Subscriber image_sub_;  
00146   
00147 //   Images Vector
00148   std::list<cv_bridge::CvImagePtr> frame_list;
00149 //   Incoming message types
00150   datamatrix_detection::DatamatrixMsg datamatrix_msg;
00151   sensor_msgs::CameraInfo cam_info;
00152   
00153 //   Global variables
00154   cv::Mat plant;
00155   cv::Mat plant_img;
00156   cv::Point image_center;
00157   double plant_width;             //  [cm] -> same as the markers position
00158   double matrix_real_height;      //   [19.2 cm]
00159   double focal_length;
00160   
00161   std::vector<double> distance;
00162   std::vector<double> alpha;
00163   std::vector<cv::Point2d> matrix_coordinates;
00164 //   std::vector<double> beta;
00165   
00166   typedef std::list<std::pair<double,GlobalPosition::Ptr> > DataList;
00167   
00168   std::vector<GlobalPosition::Ptr> my_positions;
00169   DataList position_data;
00170   
00171     public:    
00172     DataMatrixPosition(const std::string& path, const double& mat_height, const double width)
00173         :it_(nh_)
00174     {
00175         
00176         plant = cv::imread(path, CV_LOAD_IMAGE_COLOR);
00177         matrix_real_height = mat_height;    // [m] -> same as the distance
00178         plant_width = width;  //  [cm] -> same as the markers position
00179         
00180         SetupMessaging();
00181         
00182     }
00183     
00184     void SetupMessaging()
00185     {
00186         // Subscribe to input video feed
00187         image_sub_ = it_.subscribe("usb_cam_reader/image_rect_color", 1,
00188         &DataMatrixPosition::imageCallback, this);
00189         
00190         camera_info_sub = nh_.subscribe("usb_cam_reader/camera_info", 1, &DataMatrixPosition::CameraInfoCallback, this);
00191         datamatrix_sub = nh_.subscribe("datamatrix_detection/datamatrix_msg", 1,&DataMatrixPosition::DataMatrixReceiveCallback, this);
00192     }
00193     
00194     void CameraInfoCallback(const sensor_msgs::CameraInfo& cam_info_msg)
00195     {
00196     //       Runs once!!!!
00197         cam_info = cam_info_msg;
00198         std::cout << cam_info_msg << std::endl;
00199             
00200     //           Center of the image
00201         image_center.x = cam_info.width/2;
00202         image_center.y = cam_info.height/2;
00203         focal_length = (cam_info.P[0] + cam_info.P[5])/2;
00204         
00205     //     Shuts the subscriber so the callback is only called once
00206         camera_info_sub.shutdown();
00207     }
00208     
00209     void imageCallback(const sensor_msgs::ImageConstPtr& msg)
00210     {
00211         cv_bridge::CvImagePtr cv_ptr;
00212         try
00213         {
00214         cv_ptr = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8);
00215         }
00216         catch (cv_bridge::Exception& e)
00217         {
00218         ROS_ERROR("cv_bridge exception: %s", e.what());
00219         return;
00220         }
00221 //         cv::Mat rot_img;
00222 //         cv::Mat rot_mat = getRotationMatrix2D(cv::Point(cv_ptr->image.cols/2, cv_ptr->image.rows/2), 180, 1);
00223 //         cv::warpAffine(cv_ptr->image, rot_img, rot_mat, cv_ptr->image.size());
00224 //         cv_ptr->image = rot_img;
00225         
00226         frame_list.push_back(cv_ptr);
00227     //     Necessary for memory management, otherwise the computer runs out of memory when not detecting datamatrix
00228         if (frame_list.size() > 200 ) frame_list.pop_front();
00229         
00230     }
00231     
00232     void DataMatrixReceiveCallback(const datamatrix_detection::DatamatrixMsg& msg_data)
00233     {
00234         datamatrix_msg = msg_data;
00235         static int i = 0;
00236         for ( std::list<cv_bridge::CvImagePtr>::iterator it = frame_list.begin() ; it != frame_list.end(); it++)
00237         {
00238             cv_bridge::CvImagePtr img_ptr = *it;
00239             if (datamatrix_msg.header.stamp == img_ptr->header.stamp)
00240             {
00241                 GetMatrixData();
00242                 ImageDrawing(img_ptr->image);
00243                 GetGlobalPositioning();
00244                 GlobalPositioningView();
00245                 
00246     //               std::cout << "output " << i++ << ": " << datamatrix_msg.code << std::endl;
00247                 cv::imshow("Imagem1",img_ptr->image);
00248                 cv::imshow("Planta",plant_img);
00249                 cv::waitKey(3);
00250                 frame_list.erase(frame_list.begin(),it);
00251                 distance.clear();
00252                 alpha.clear();
00253                 matrix_coordinates.clear();
00254     //               beta.clear();
00255                 datamatrix_msg.decoded_matrices.clear();
00256                 break;
00257             }
00258         }
00259     }
00260 
00261     void GetMatrixData()
00262     {       
00263         
00264         for (auto it = datamatrix_msg.decoded_matrices.begin(); it!=datamatrix_msg.decoded_matrices.end();)
00265         {
00266 //             Gets the matrix coordinates
00267             if ( it->code.size() % 2 == 0 )
00268             {
00269                 std::string string_x = it->code.substr(0, it->code.size()/2);
00270                 std::string string_y = it->code.substr(it->code.size()/2);
00271                 
00272                 cv::Point matrix_coord(atoi(string_x.c_str()), atoi(string_y.c_str()) - 50 );
00273                 matrix_coordinates.push_back(matrix_coord);
00274                 
00275                 GetMatrixGeometry(it);
00276                 GetMatrixDistance(it);
00277                 GetMatrixAngle(it);
00278 //                 CalculateMatrixGeometry(i);
00279                 
00280                 it++;
00281             }
00282             else
00283             {
00284                 it = datamatrix_msg.decoded_matrices.erase(it);
00285                 
00286             }
00287         }
00288     }
00289     
00290     void GetMatrixGeometry(std::vector<datamatrix_detection::DatamatrixData>::iterator it)
00291     {
00292       it->matrix_center.x = (it->right.x + it->top.x)/2;
00293       it->matrix_center.y = (it->right.y + it->top.y)/2;
00294       it->matrix_center.z = 0;
00295       
00296       cv::Point bottom_mean_point;
00297       bottom_mean_point.x = (it->right.x + it->bottom.x)/2;
00298       bottom_mean_point.y = (it->right.y + it->bottom.y)/2;
00299       
00300       cv::Point left_mean_point;
00301       left_mean_point.x = (it->top.x + it->bottom.x)/2;
00302       left_mean_point.y = (it->top.y + it->bottom.y)/2;
00303       
00304 //       Calculates the matrix height
00305       it->matrix_height = sqrt((bottom_mean_point.x - it->matrix_center.x)*(bottom_mean_point.x - it->matrix_center.x) + (bottom_mean_point.y - it->matrix_center.y)*(bottom_mean_point.y - it->matrix_center.y)) * 2;
00306       
00307 //       Calculates the matrix width
00308       it->matrix_width = sqrt((left_mean_point.x - it->matrix_center.x)*(left_mean_point.x - it->matrix_center.x) + (left_mean_point.y - it->matrix_center.y)*(left_mean_point.y - it->matrix_center.y)) * 2;
00309     }
00310     
00311     void GetMatrixDistance(std::vector<datamatrix_detection::DatamatrixData>::iterator it)
00312     {
00313     //     Gets the distance to the left side of the matrix
00314         if ( cam_info.P[0] != 0 )
00315             distance.push_back(matrix_real_height * focal_length/it->matrix_height);
00316     }
00317 
00318     void GetMatrixAngle(std::vector<datamatrix_detection::DatamatrixData>::iterator it)
00319     {
00320     //     Gets the angle to the center of the matrix
00321         if ( cam_info.P[0] != 0)
00322         {
00323             double center_dist_pix = image_center.x - it->matrix_center.x;
00324             alpha.push_back(( center_dist_pix/focal_length) * 180/M_PI);
00325         }
00326     }
00327 
00328     void ImageDrawing(cv::Mat& cv_img)
00329     {
00330         for ( uint i = 0 ; i < datamatrix_msg.decoded_matrices.size(); i++)
00331         {
00332     //         drawing the 4 direct message points
00333             cv::circle(cv_img, cv::Point (datamatrix_msg.decoded_matrices[i].left.x, datamatrix_msg.decoded_matrices[i].left.y), 10, CV_RGB(255,0,0));
00334             cv::circle(cv_img, cv::Point (datamatrix_msg.decoded_matrices[i].right.x, datamatrix_msg.decoded_matrices[i].right.y), 10, CV_RGB(255,0,0));
00335             cv::circle(cv_img, cv::Point (datamatrix_msg.decoded_matrices[i].top.x, datamatrix_msg.decoded_matrices[i].top.y), 10, CV_RGB(255,0,0));
00336             cv::circle(cv_img, cv::Point (datamatrix_msg.decoded_matrices[i].bottom.x, datamatrix_msg.decoded_matrices[i].bottom.y), 10, CV_RGB(255,0,0));    
00337             cv::circle(cv_img, cv::Point (datamatrix_msg.decoded_matrices[i].matrix_center.x, datamatrix_msg.decoded_matrices[i].matrix_center.y), 10, CV_RGB(255,0,0));
00338             
00339             cv::Point top_right;
00340             
00341         //     Estimate the top_right point
00342             double left_angle;
00343             double top_left_distance = sqrt((datamatrix_msg.decoded_matrices[i].top.x - datamatrix_msg.decoded_matrices[i].left.x)*(datamatrix_msg.decoded_matrices[i].top.x - datamatrix_msg.decoded_matrices[i].left.x) + (datamatrix_msg.decoded_matrices[i].top.y - datamatrix_msg.decoded_matrices[i].left.y)*(datamatrix_msg.decoded_matrices[i].top.y - datamatrix_msg.decoded_matrices[i].left.y));
00344             
00345         //     if( top_left_distance > 20)
00346                 left_angle = atan2(datamatrix_msg.decoded_matrices[i].top.y - datamatrix_msg.decoded_matrices[i].left.y, datamatrix_msg.decoded_matrices[i].top.x - datamatrix_msg.decoded_matrices[i].left.x);
00347         //     else
00348         //         left_angle = atan2(datamatrix_msg.top.y - datamatrix_msg.bottom.y,datamatrix_msg.top.x - datamatrix_msg.bottom.x);
00349             
00350             top_right.x = datamatrix_msg.decoded_matrices[i].right.x + round(datamatrix_msg.decoded_matrices[i].matrix_height*cos(left_angle));
00351             top_right.y = datamatrix_msg.decoded_matrices[i].right.y + round(datamatrix_msg.decoded_matrices[i].matrix_height*sin(left_angle));
00352             
00353             cv::circle(cv_img, image_center, 10, CV_RGB(0,255,0));
00354             cv::circle(cv_img, top_right, 10, CV_RGB(0,255,0));
00355             
00356         //     Chosing the which point to connect the line
00357             if ( datamatrix_msg.decoded_matrices[i].top.y > datamatrix_msg.decoded_matrices[i].right.y && top_left_distance > 30)
00358             {
00359                 cv::line(cv_img, cv::Point (datamatrix_msg.decoded_matrices[i].top.x, datamatrix_msg.decoded_matrices[i].top.y), cv::Point (datamatrix_msg.decoded_matrices[i].left.x, datamatrix_msg.decoded_matrices[i].left.y), cv::Scalar(0,255,0));
00360                 cv::line(cv_img, cv::Point (datamatrix_msg.decoded_matrices[i].left.x, datamatrix_msg.decoded_matrices[i].left.y), cv::Point (datamatrix_msg.decoded_matrices[i].right.x, datamatrix_msg.decoded_matrices[i].right.y), cv::Scalar(0,255,0));        
00361             }else{
00362                 cv::line(cv_img, cv::Point (datamatrix_msg.decoded_matrices[i].top.x, datamatrix_msg.decoded_matrices[i].top.y), cv::Point (datamatrix_msg.decoded_matrices[i].bottom.x, datamatrix_msg.decoded_matrices[i].bottom.y), cv::Scalar(0,255,0));
00363                 cv::line(cv_img, cv::Point (datamatrix_msg.decoded_matrices[i].bottom.x, datamatrix_msg.decoded_matrices[i].bottom.y), cv::Point (datamatrix_msg.decoded_matrices[i].right.x, datamatrix_msg.decoded_matrices[i].right.y), cv::Scalar(0,255,0));
00364             }
00365             cv::line(cv_img, cv::Point (datamatrix_msg.decoded_matrices[i].right.x, datamatrix_msg.decoded_matrices[i].right.y), top_right, cv::Scalar(0,255,0));
00366             cv::line(cv_img, top_right, cv::Point (datamatrix_msg.decoded_matrices[i].top.x, datamatrix_msg.decoded_matrices[i].top.y), cv::Scalar(0,255,0));
00367             cv::line(cv_img, cv::Point (1,cv_img.rows/2), cv::Point (cv_img.cols,cv_img.rows/2), cv::Scalar(255,0,0));
00368             
00369         //     Matrix code display on image
00370             std::string leitura = "Leitura: " + datamatrix_msg.decoded_matrices[i].code;
00371             cv::putText(cv_img, leitura, cv::Point (datamatrix_msg.decoded_matrices[i].top.x, datamatrix_msg.decoded_matrices[i].top.y - 15), cv::FONT_HERSHEY_SIMPLEX, 0.6, cv::Scalar(0,255,0), 2, 8);
00372             
00373         //     Matrix distance display
00374             boost::format dist_str("Distancia: %1$.3f [m]");    //  Format the output string
00375             dist_str % distance[i];                                //  Assign distance to the output string
00376             cv::putText(cv_img, dist_str.str(), cv::Point (datamatrix_msg.decoded_matrices[i].right.x + 15, datamatrix_msg.decoded_matrices[i].right.y), cv::FONT_HERSHEY_SIMPLEX, 0.6, cv::Scalar(0,255,0), 2, 8);
00377             
00378         //     Matrix angle display
00379             boost::format ang_str("Angulo: %1$.3f [deg]");    //  Format the output string
00380             ang_str % alpha[i];                                //  Assign alpha to the output string
00381             cv::putText(cv_img, ang_str.str(), cv::Point (datamatrix_msg.decoded_matrices[i].bottom.x, datamatrix_msg.decoded_matrices[i].bottom.y + 20), cv::FONT_HERSHEY_SIMPLEX, 0.6, cv::Scalar(0,255,0), 2, 8);
00382         }
00383     }
00384     
00385 
00386     void GetGlobalPositioning()
00387     {
00388         if ( datamatrix_msg.decoded_matrices.size() >= 2 )
00389         {
00390             
00391             GlobalPosition::Ptr my_estimated_position_ptr = EstimatePosition();
00392             
00393 //             Doing the mean of the previous x positions
00394             static ros::Time prev_time;
00395             if ( prev_time.sec != 0 && my_estimated_position_ptr->x >= 0)
00396                 position_data.push_front(std::make_pair((datamatrix_msg.header.stamp - prev_time).toSec(), my_estimated_position_ptr));
00397             if ( position_data.size() > 10 )
00398                 position_data.pop_back();
00399             prev_time = datamatrix_msg.header.stamp;
00400             
00401 // //             Simple moving average
00402 //             GlobalPosition::Ptr my_position_ptr = meanPosition(position_data);
00403 // //             Exponential Moving Average
00404             GlobalPosition::Ptr my_position_ptr = EMAPosition(position_data);
00405 // //             weighted moving average
00406 //             GlobalPosition::Ptr my_position_ptr = WMAPosition(position_data);
00407             
00408 //             GlobalPosition::Ptr my_position_ptr = my_estimated_position_ptr;
00409 //             std::cout << "x,y,phi " << my_position_ptr->x << ", " << my_position_ptr->y << ", " << my_position_ptr->phi << std::endl;
00410             my_positions.push_back(my_position_ptr);
00411             
00412         }else{
00413 //             Do some interesting stuff with kalman filter :)
00414         }
00415     }    
00416     
00417     void GlobalPositioningView()
00418     {
00419         plant_img = plant.clone();
00420             
00421         double plant_cm_pix_ratio = plant_img.cols/plant_width;
00422         
00423         if ( my_positions.size() > 0 )
00424         {
00425             GlobalPosition::Ptr my_position = my_positions.back();
00426             cv::circle(plant_img, cv::Point( plant_img.cols - (my_position->x * plant_cm_pix_ratio), my_position->y * plant_cm_pix_ratio), 3, CV_RGB(255,0,0));
00427             plant = plant_img.clone();
00428                 
00429             int arrow_size = 500;
00430             cv::Point arrow_end(plant_img.cols - (my_position->x + arrow_size * cos(my_position->phi)) * plant_cm_pix_ratio, (my_position->y + arrow_size * sin(my_position->phi)) * plant_cm_pix_ratio);
00431             cv::line(plant_img, cv::Point( plant_img.cols - (my_position->x * plant_cm_pix_ratio), my_position->y * plant_cm_pix_ratio), arrow_end, cv::Scalar(0,255,0), 3, CV_AA);
00432         }
00433         
00434         for ( uint i = 0 ; i < datamatrix_msg.decoded_matrices.size(); i++)
00435         {
00436                 
00437             cv::Point matrix_pos(plant_img.cols - (matrix_coordinates[i].x * plant_cm_pix_ratio), matrix_coordinates[i].y * plant_cm_pix_ratio);
00438             cv::circle(plant_img, matrix_pos, distance[i] * 100 * plant_cm_pix_ratio, CV_RGB(255,0,0));
00439             cv::circle(plant_img, matrix_pos, 5, CV_RGB(255,0,0));
00440                     
00441         }
00442         
00443     //     cv::imshow("Planta",plant_img);
00444     //     cv::waitKey(3);
00445     }
00446     
00447     GlobalPosition::Ptr meanPosition(const DataList& data)
00448     {
00449         GlobalPosition::Ptr mean_pos(new GlobalPosition);
00450         
00451         for(auto it = data.begin();it!=data.end();it++)
00452             mean_pos = mean_pos + it->second;
00453         
00454         return mean_pos / data.size();
00455     }
00456     
00457     GlobalPosition::Ptr EMAPosition(const DataList& data)
00458     {
00459 //         cout<<__FUNCTION__<<endl;
00460 //         The greater the alpha value is the most responsive the algorithm will be
00461         double denominator, alpha = 0.2;
00462         GlobalPosition::Ptr ema_pos (new GlobalPosition);
00463         int i = 0;
00464         for ( auto it = data.begin();it != data.end();it++)
00465         {
00466             double mult = pow((1-alpha),i++);
00467             ema_pos = ema_pos + it->second * mult;
00468             denominator = denominator + mult;
00469         }
00470         
00471 //         std::cout << "x, y, phi: " << ema_pos->x/denominator << ", " << ema_pos->y/denominator << ", " << ema_pos->phi/denominator << std::endl;
00472         
00473 //         cout<<"out of "<<__FUNCTION__<<endl;
00474         return ema_pos / denominator;
00475     }
00476     
00477     GlobalPosition::Ptr WMAPosition(const DataList& data)
00478     {
00479         GlobalPosition::Ptr wma_pos (new GlobalPosition);
00480         double denominator;
00481         for ( auto it = data.begin();it != data.end();it++)
00482         {
00483             wma_pos = wma_pos + it->second * it->first;
00484             denominator = denominator + it->first;
00485         }
00486 //         std::cout << "deno: " << denominator << std::endl;
00487         return wma_pos / denominator;
00488     }
00489     
00490     GlobalPosition::Ptr EstimatePosition()
00491     {
00492 
00493         std::vector<GlobalPosition::Ptr> my_intermediate_positions;
00494         GlobalPosition::Ptr sum(new GlobalPosition);
00495         for ( uint j = 0; j < datamatrix_msg.decoded_matrices.size() - 1; j++)
00496         {
00497             for ( uint k = j + 1; k < datamatrix_msg.decoded_matrices.size(); k++ )
00498             {
00499                 GlobalPosition::Ptr my_intermediate_position_ptr = CalculateCircleIntersection( j, k );
00500                 if (!std::isnan(my_intermediate_position_ptr->x) && !std::isnan(my_intermediate_position_ptr->y) && !std::isnan(my_intermediate_position_ptr->phi))
00501                 {
00502                     my_intermediate_positions.push_back(my_intermediate_position_ptr);
00503                     sum = sum + my_intermediate_position_ptr;
00504                 }
00505             }
00506         }
00507 
00508         return sum / my_intermediate_positions.size();
00509     }
00510     
00511     
00512     GlobalPosition::Ptr CalculateCircleIntersection( uint first, uint second)
00513     {
00514         
00515         double a, dx, dy, d, h, rx, ry;
00516         double x2, y2;
00517 
00518 //         My matrices coordinates
00519         double x0 = matrix_coordinates[first].x;
00520         double y0 = matrix_coordinates[first].y;
00521         double r0 = distance[first]*100;
00522         
00523         double x1 = matrix_coordinates[second].x;
00524         double y1 = matrix_coordinates[second].y;
00525         double r1 = distance[second]*100;
00526         
00527         /* dx and dy are the vertical and horizontal distances between
00528         * the circle centers.
00529         */
00530         dx = x1 - x0;
00531         dy = y1 - y0;
00532 
00533         /* Determine the straight-line distance between the centers. */
00534         //d = sqrt((dy*dy) + (dx*dx));
00535         d = hypot(dx,dy); // Suggested by Keith Briggs
00536         
00537 //         /* Check for solvability. */
00538 //         if (d > (r0 + r1))
00539 //         {
00540 //             /* no solution. circles do not intersect. */
00541 //             return GlobalPosition::Ptr (new GlobalPosition(-100,-100,0));
00542 //         }
00543 //         if (d < fabs(r0 - r1))
00544 //         {
00545 //             /* no solution. one circle is contained in the other */
00546 //             return GlobalPosition::Ptr (new GlobalPosition(-100,-100,0));
00547 //         }
00548 
00549         /* 'point 2' is the point where the line through the circle
00550         * intersection points crosses the line between the circle
00551         * centers.
00552         */
00553 
00554         /* Determine the distance from point 0 to point 2. */
00555         a = ((r0*r0) - (r1*r1) + (d*d)) / (2.0 * d) ;
00556 
00557         /* Determine the coordinates of point 2. */
00558         x2 = x0 + (dx * a/d);
00559         y2 = y0 + (dy * a/d);
00560 
00561         /* Determine the distance from point 2 to either of the
00562         * intersection points.
00563         */
00564         h = sqrt((r0*r0) - (a*a));
00565 
00566         /* Now determine the offsets of the intersection points from
00567         * point 2.
00568         */
00569         rx = -dy * (h/d);
00570         ry = dx * (h/d);
00571 
00572         /* Determine the absolute intersection points.*/
00573 //         Coordinates are in centimeters -----------------------------------------!!!
00574         cv::Point2d int_point1(x2 + rx, y2 + ry);
00575         cv::Point2d int_point2(x2 - rx, y2 - ry);
00576         
00577 //         std::cout << "x,y: " << int_point1.x << ", " << int_point1.y << std::endl;
00578 //         std::cout << "x,y: " << int_point2.x << ", " << int_point2.y << std::endl;
00579         
00580 //         Determine the correct intersection point based on the angle of view to a known matrix
00581 //         In order to determine to which side is one matrix relatively to the other we calculate the vector product between the vectors from the intersection point to each matrix position that will give the signal of the angle
00582         
00583         cv::Point vetor_i1_m1 = matrix_coordinates[first] - int_point1;
00584         cv::Point vetor_i1_m2 = matrix_coordinates[second] - int_point1;
00585         int angle_direction_i1 = vetor_i1_m1.cross(vetor_i1_m2)/abs(vetor_i1_m1.cross(vetor_i1_m2));
00586         
00587 //         std::cout << "angle 1: " << angle_direction_i1 << std::endl; 
00588         
00589         cv::Point vetor_i2_m1 = matrix_coordinates[first] - int_point2;
00590         cv::Point vetor_i2_m2 = matrix_coordinates[second] - int_point2;
00591         int angle_direction_i2 = vetor_i2_m1.cross(vetor_i2_m2)/abs(vetor_i2_m1.cross(vetor_i2_m2));
00592         
00593 //         std::cout << "angle 2: " << angle_direction_i2 << std::endl;
00594         
00595         int real_angle_direction = (alpha[second] - alpha[first])/(abs(alpha[second] - alpha[first]));
00596         
00597 //         std::cout << "real angle: " << real_angle_direction << std::endl;
00598         
00599         GlobalPosition::Ptr my_position_ptr(new GlobalPosition);
00600         if ( real_angle_direction / angle_direction_i1 == 1 )
00601         {
00602             my_position_ptr->x = int_point1.x;
00603             my_position_ptr->y = int_point1.y;
00604         }else if ( real_angle_direction / angle_direction_i2 == 1 )
00605         {
00606             my_position_ptr->x = int_point2.x;
00607             my_position_ptr->y = int_point2.y;
00608         }
00609         
00610 //         In order to get the global orientation we need to calculate the angle from our pos to 1 of the matrices and then subtract the measured angle
00611 //         Angle from our position to the first matrix
00612         double dx_ = matrix_coordinates[first].x - my_position_ptr->x;
00613         double dy_ = matrix_coordinates[first].y - my_position_ptr->y;
00614         
00615         double int_mat1_angle = atan2( dy_,dx_ );
00616         
00617         my_position_ptr->phi = int_mat1_angle - (alpha[first] * M_PI/180 );
00618         
00619 //         std::cout << "x,y,phi: " << my_position_ptr->x << ", " <<my_position_ptr->y << ", " << my_position_ptr->phi << std::endl;
00620         return my_position_ptr;
00621         
00622 //         std::cout << "angulo: " << my_position_ptr.phi * 180 / M_PI << std::endl;
00623         
00624     }
00625     
00626 
00627 };
00628 
00629 int main(int argc, char** argv)
00630 {
00631     
00632 //     cv::Point2d p1(1,2.2);
00633 //     double timestamp1 = 123545656;
00634 //     
00635 //     cv::Point2d p2(123,2.42);
00636 //     double timestamp2 = 132565465;
00637 //     
00638 //     std::vector<std::pair<cv::Point2d,double> > data;
00639 //     
00640 //     std::pair<cv::Point2d,double> par;
00641 //     
00642 //     par.first = p1;
00643 //     
00644 //     data.push_back(std::make_pair(p1,timestamp1));
00645 //     data.push_back(std::make_pair(p2,timestamp2));
00646 //     
00647 //     for(uint i=0;i<data.size();i++)
00648 //     {
00649 //         std::cout<<"data["<<i<<"] = "<<data[i].first;
00650 //         std::cout<<", t = "<<data[i].second<<std::endl;
00651 //         
00652 //     }
00653 //     
00654 //     return 0;
00655     
00656 //     cout<<"Init"<<endl;
00657 //     
00658 //     PointTheta p1(0.2,1.5,8);
00659 //     PointTheta p2(0.3,2,4);
00660 //     PointTheta p3 = p1 +p2;
00661 //     
00662 //     double c = p1.cross(p2);
00663 //     double d = p1.dot(p2);
00664 //     
00665 //     
00666 //     cout<<"P1: "<<p1<<", "<<p1.phi<<endl;
00667 //     cout<<"P2: "<<p2<<", "<<p2.phi<<endl;
00668 //     cout<<"P3: "<<p3<<", "<<p3.phi<<endl;
00669 //     
00670 //     cout<<"Cross: "<<p1.cross(p2)<<endl;
00671 //     
00672 //     return 0;
00673   ros::init(argc, argv, "datamatrix_calculations");
00674   ros::NodeHandle nh("~");
00675   
00676   std::string path;
00677   nh.param<std::string>("plant_path",path,"");
00678   
00679   double real_height;
00680   nh.param<double>("matrix_height",real_height,0);
00681   
00682   double plant_width;
00683   nh.param<double>("plant_width",plant_width,0);
00684   
00685   DataMatrixPosition datamatrix_pos(path, real_height, plant_width);
00686   ros::spin();
00687   return 0;
00688 }


datamatrix_detection
Author(s): Luís Pedras Carrão
autogenerated on Fri Jun 6 2014 18:36:26