ShapeTracker.cpp
Go to the documentation of this file.
00001 #include "shape_tracker/ShapeTracker.h"
00002 
00003 #include <pcl_conversions/pcl_conversions.h>
00004 
00005 #include <shape_reconstruction/RangeImagePlanar.hpp>
00006 
00007 // Need to include the pcl ros utilities
00008 #include "pcl_ros/point_cloud.h"
00009 
00010 #include "pcl/filters/approximate_voxel_grid.h"
00011 
00012 #include "opencv2/imgproc/imgproc.hpp"
00013 
00014 using namespace omip;
00015 
00016 #define BB_FILTER_BEFORE_ICP
00017 
00018 // Extract the indices that correspond to non-zero pixels of the image
00019 void Image8u2IndicesOfOrganizedPC(const cv::Mat& image_8u, pcl::PointIndices::Ptr indices_ptr)
00020 {
00021     indices_ptr->indices.clear();
00022     for(int j=0; j<image_8u.rows; j++)
00023     {
00024         for(int i=0; i<image_8u.cols; i++)
00025         {
00026             if(image_8u.at<uchar>(j,i))
00027             {
00028                 indices_ptr->indices.push_back(j*image_8u.cols + i);
00029             }
00030         }
00031     }
00032 }
00033 
00034 // Generate a binary image with non-zero for the given indices
00035 void IndicesOfOrganizedPC2Image8u(pcl::PointIndices::Ptr indices_ptr, cv::Mat& image_8u)
00036 {
00037     for(int k=0; k<indices_ptr->indices.size(); k++)
00038     {
00039         image_8u.at<uchar>(std::floor(indices_ptr->indices[k]/640), indices_ptr->indices[k]%640) = 255;
00040     }
00041 }
00042 
00043 ShapeTracker::ShapeTracker(omip::RB_id_t rb_id)
00044     : _rb_id(rb_id),
00045       _new_model(false),
00046       _current_dm(480, 640, CV_32FC1),
00047       _segment_of_current(480,640,CV_8U),
00048       _segment_of_current_dilated(480,640,CV_8U)
00049 {
00050 
00051     _rb_model.reset(new pcl::PointCloud<pcl::PointXYZ >());
00052 
00053     _icp.setMaxCorrespondenceDistance(1);
00054     _icp.setEuclideanFitnessEpsilon(1e-6);
00055     _icp.setMaximumIterations(1000);
00056     _icp.setTransformationEpsilon(0.0);
00057 
00058     std::stringstream pub_topic_name;
00059     pub_topic_name << "/shape_tracker/segment_rb" << this->_rb_id;
00060     _segment_pub = _nh.advertise<pcl::PointCloud<pcl::PointXYZ> >(pub_topic_name.str(), 1);
00061 
00062     int dilation_type = cv::MORPH_RECT;
00063     int dilation_size = 2;
00064     _dilation_element = cv::getStructuringElement( dilation_type,
00065                                                    cv::Size( 2*dilation_size + 1, 2*dilation_size+1 ),
00066                                                    cv::Point( dilation_size, dilation_size ) );
00067 
00068 #ifdef USE_LIBPOINTMATCHER_ICP
00069     _icp_lpm = new PM::ICP();
00070 
00071     PointMatcherSupport::Parametrizable::Parameters params;
00072     std::string name;
00073 
00074     name = "MaxPointCountDataPointsFilter";
00075     params["maxCount"] = "1000";
00076     PM::DataPointsFilter* maxCount_read =
00077             PM::get().DataPointsFilterRegistrar.create(name, params);
00078     params.clear();
00079 
00080     name = "BoundingBoxDataPointsFilter";
00081     params["xMin"] = "-inf";
00082     params["xMax"] = "inf";
00083     params["yMin"] = "-inf";
00084     params["yMax"] = "inf";
00085     params["zMin"] = "-inf";
00086     params["zMax"] = "inf";
00087     params["removeInside"] = "0";
00088     PM::DataPointsFilter* bb_read =
00089             PM::get().DataPointsFilterRegistrar.create(name, params);
00090     params.clear();
00091 
00092     // Prepare matching function
00093     name = "KDTreeMatcher";
00094     params["knn"] = "1";
00095     params["epsilon"] = "0";
00096     params["maxDist"] = "0.02";
00097     params["searchType"] = "1";
00098     PM::Matcher* kdtree =
00099             PM::get().MatcherRegistrar.create(name, params);
00100     params.clear();
00101 
00102     // Prepare outlier filters
00103     name = "TrimmedDistOutlierFilter";
00104     params["ratio"] = "0.75";
00105     PM::OutlierFilter* trim =
00106             PM::get().OutlierFilterRegistrar.create(name, params);
00107     params.clear();
00108 
00109     // Prepare error minimization
00110     name = "PointToPointErrorMinimizer";
00111     PM::ErrorMinimizer* pointToPoint =
00112             PM::get().ErrorMinimizerRegistrar.create(name);
00113 
00114     // Prepare outlier filters
00115     name = "CounterTransformationChecker";
00116     params["maxIterationCount"] = "10";
00117     PM::TransformationChecker* maxIter =
00118             PM::get().TransformationCheckerRegistrar.create(name, params);
00119     params.clear();
00120 
00121     name = "DifferentialTransformationChecker";
00122     params["minDiffRotErr"] = "0.01";
00123     params["minDiffTransErr"] = "0.01";
00124     params["smoothLength"] = "1";
00125     PM::TransformationChecker* diff =
00126             PM::get().TransformationCheckerRegistrar.create(name, params);
00127     params.clear();
00128 
00129     // Prepare inspector
00130     PM::Inspector* nullInspect =
00131             PM::get().InspectorRegistrar.create("NullInspector");
00132 
00133     // Prepare transformation
00134     PM::Transformation* rigidTrans =
00135             PM::get().TransformationRegistrar.create("RigidTransformation");
00136 
00137     // Build ICP solution
00138     _icp_lpm->readingDataPointsFilters.push_back(maxCount_read);
00139     _icp_lpm->referenceDataPointsFilters.push_back(bb_read);
00140     _icp_lpm->referenceDataPointsFilters.push_back(maxCount_read);
00141     _icp_lpm->matcher.reset(kdtree);
00142     _icp_lpm->outlierFilters.push_back(trim);
00143     _icp_lpm->errorMinimizer.reset(pointToPoint);
00144     _icp_lpm->transformationCheckers.push_back(maxIter);
00145     _icp_lpm->transformationCheckers.push_back(diff);
00146     _icp_lpm->inspector.reset(nullInspect);
00147     _icp_lpm->transformations.push_back(rigidTrans);
00148 #endif
00149 }
00150 
00151 ShapeTracker::ShapeTracker(const ShapeTracker &sr)
00152 {
00153     ROS_ERROR_STREAM_NAMED("ShapeTracker.ShapeTracker", "Do not use this copy constructor! It is not complete!");
00154 
00155     this->_rb_id = sr._rb_id;
00156     this->_rb_model = sr._rb_model;
00157 }
00158 
00159 ShapeTracker::~ShapeTracker()
00160 {
00161 }
00162 
00163 void ShapeTracker::setCameraInfo(const sensor_msgs::CameraInfo& camera_info)
00164 {
00165     this->_ci = sensor_msgs::CameraInfo(camera_info);
00166 }
00167 
00168 void OrganizedPC2DepthMap2(const pcl::PointCloud<pcl::PointXYZ >::Ptr organized_pc, cv::Mat& depth_map_mat)
00169 {
00170     float* data_ptr = (float*)depth_map_mat.data;
00171     size_t elem_step = depth_map_mat.step / sizeof(float);
00172 
00173     for(int v=0; v< organized_pc->height; v++)
00174     {
00175         for(int u=0; u< organized_pc->width; u++)
00176         {
00177             if(pcl::isFinite(organized_pc->points[v*organized_pc->width + u]))
00178                 data_ptr[v*elem_step + u] = organized_pc->points[v*organized_pc->width + u].z;
00179             else
00180                 data_ptr[v*elem_step + u] = nanf("");
00181         }
00182     }
00183 }
00184 
00185 
00186 void ShapeTracker::step(const sensor_msgs::PointCloud2ConstPtr &pc_msg,
00187                         const omip_msgs::RigidBodyPoseAndVelMsg& tracked_rbm,
00188                         omip_msgs::ShapeTrackerState& st_state)
00189 {
00190     if(this->_rb_model->points.size() != 0)
00191     {
00192         ros::WallTime t1 = ros::WallTime::now();
00193 
00194         // Convert from exponential coordinates to transformation matrix
00195         Eigen::Twistd pose_twist2;
00196         ROSTwist2EigenTwist(tracked_rbm.pose_wc.twist, pose_twist2);
00197         Eigen::Matrix4d pose_matrix;
00198         Twist2TransformMatrix(pose_twist2, pose_matrix);
00199 
00200         // I can move the model to the current pose (using the pose_matrix) and estimate its bounding box. Then update the
00201         // parameters of the bounding box filter for the input point cloud
00202         pcl::PointCloud<pcl::PointXYZ >::Ptr rb_model_current_pose(new pcl::PointCloud<pcl::PointXYZ >);
00203         pcl::transformPointCloud<pcl::PointXYZ>(*this->_rb_model, *rb_model_current_pose, pose_matrix.cast<float>());
00204         pcl::PointXYZ min_pt;
00205         pcl::PointXYZ max_pt;
00206         pcl::getMinMax3D<pcl::PointXYZ>(*rb_model_current_pose, min_pt, max_pt);
00207         double safety_margin = 0.01;
00208         _icp_lpm->referenceDataPointsFilters.at(0)->parameters["xMin"] = min_pt.x - safety_margin;
00209         _icp_lpm->referenceDataPointsFilters.at(0)->parameters["xMax"] = max_pt.x + safety_margin;
00210         _icp_lpm->referenceDataPointsFilters.at(0)->parameters["yMin"] = min_pt.y - safety_margin;
00211         _icp_lpm->referenceDataPointsFilters.at(0)->parameters["yMax"] = max_pt.y + safety_margin;
00212         _icp_lpm->referenceDataPointsFilters.at(0)->parameters["zMin"] = min_pt.z - safety_margin;
00213         _icp_lpm->referenceDataPointsFilters.at(0)->parameters["zMax"] = max_pt.z + safety_margin;
00214 
00215         sensor_msgs::PointCloud2 model_now;
00216         pcl::toROSMsg(*rb_model_current_pose, model_now);
00217         model_now.header.frame_id = "/camera_rgb_optical_frame";
00218         this->_segment_pub.publish(model_now);
00219 
00220         ros::WallTime t4 = ros::WallTime::now();
00221 
00222         ros::WallTime t5 = ros::WallTime::now();
00223 
00224         bool lpm_converged = true;
00225 
00226         // Convert current point cloud into libpointmatcher
00227         boost::shared_ptr<DP> current_segment_of_pc_extended_lpm(new DP(PointMatcher_ros::rosMsgToPointMatcherCloud<float>(*pc_msg)));
00228 
00229         ros::WallTime t6 = ros::WallTime::now();
00230 
00231         // Compute the transformation to express data in ref
00232         PM::TransformationParameters T;
00233         try{
00234             std::cout << pose_matrix << std::endl;
00235             // Call libpointmatcher passing as initial guess for the transformation the received one
00236             T = _icp_lpm->operator()(*_rb_model_lpm, *current_segment_of_pc_extended_lpm, pose_matrix.cast<float>());
00237             std::cout << T << std::endl;
00238         }catch(...)
00239         {
00240             ROS_ERROR_STREAM("[RB" << this->_rb_id << "] Libmatchpoint ICP did not converge!");
00241             lpm_converged = false;
00242             st_state.fitness_score = 1;
00243         }
00244 
00245         ros::WallTime t7 = ros::WallTime::now();
00246 
00247         ROS_INFO_STREAM_NAMED("ShapeReconstruction._RemoveInconsistentPointsFromRBModel",
00248                               "[RB" << this->_rb_id << " Estimated LPM ICP refinement: " << std::endl << T);
00249 
00250         ROS_INFO_STREAM_NAMED("ShapeReconstruction.step",
00251                               "t4 - t1: " <<  t4 - t1  );
00252         ROS_INFO_STREAM_NAMED("ShapeReconstruction.step",
00253                               "t5 - t4: " <<  t5 - t4  );
00254         ROS_INFO_STREAM_NAMED("ShapeReconstruction.step",
00255                               "t6 - t5: " <<  t6 - t5  );
00256         ROS_INFO_STREAM_NAMED("ShapeReconstruction.step",
00257                               "t7 - t6: " <<  t7 - t6  );
00258 
00259         // Using LPM ICP results
00260         if(lpm_converged)
00261         {
00262             Eigen::Twistd compound_twist;
00263             TransformMatrix2Twist( T.cast<double>(), compound_twist);
00264 
00265             EigenTwist2GeometryMsgsTwist(compound_twist, st_state.pose_wc.twist);
00266 
00267             st_state.rb_id = this->_rb_id;
00268             //st_state.fitness_score = this->_icp.getFitnessScore();
00269             st_state.fitness_score = 0;
00270 
00271             for (unsigned int i = 0; i < 6; i++)
00272             {
00273                 for (unsigned int j = 0; j < 6; j++)
00274                 {
00275                     st_state.pose_wc.covariance[6 * i + j] = this->_icp_lpm->errorMinimizer->getCovariance()(i, j);
00276                 }
00277             }
00278             //std::cout  << this->_icp_lpm->errorMinimizer->getWeightedPointUsedRatio() << std::endl;
00279 
00280             //st_state.number_of_points_of_model = _icp.getInputSource()->points.size();
00281             st_state.number_of_points_of_model = this->_icp_lpm->getPrefilteredReadingPtsCount();
00282             std::cout << this->_icp_lpm->getPrefilteredReadingPtsCount() << std::endl;
00283             //st_state.number_of_points_of_current_pc = _icp.getInputTarget()->points.size();
00284             st_state.number_of_points_of_current_pc = this->_icp_lpm->getPrefilteredReferencePtsCount();
00285             std::cout << this->_icp_lpm->getPrefilteredReferencePtsCount() << std::endl;
00286 
00287         }else{
00288             st_state.pose_wc.twist = tracked_rbm.pose_wc.twist;
00289             st_state.number_of_points_of_model = 0;
00290             st_state.number_of_points_of_current_pc =0;
00291         }
00292 
00293         ROS_WARN_STREAM("Before refinement: \t" << tracked_rbm.pose_wc.twist.linear.x << " " <<
00294                         tracked_rbm.pose_wc.twist.linear.y << " " <<
00295                         tracked_rbm.pose_wc.twist.linear.z << " " <<
00296                         tracked_rbm.pose_wc.twist.angular.x << " " <<
00297                         tracked_rbm.pose_wc.twist.angular.y << " " <<
00298                         tracked_rbm.pose_wc.twist.angular.z );
00299 
00300         ROS_WARN_STREAM("After refinement: \t" <<st_state.pose_wc.twist.linear.x << " " <<
00301                         st_state.pose_wc.twist.linear.y << " " <<
00302                         st_state.pose_wc.twist.linear.z << " " <<
00303                         st_state.pose_wc.twist.angular.x << " " <<
00304                         st_state.pose_wc.twist.angular.y << " " <<
00305                         st_state.pose_wc.twist.angular.z );
00306 
00307         st_state.probabilistic_value = 1.0;
00308     }else{
00309         st_state.pose_wc.twist = tracked_rbm.pose_wc.twist;
00310         ROS_WARN_STREAM("Model is empty! Same twist as the input: " << st_state.pose_wc.twist.linear.x << " " <<
00311                         st_state.pose_wc.twist.linear.y << " " <<
00312                         st_state.pose_wc.twist.linear.z << " " <<
00313                         st_state.pose_wc.twist.angular.x << " " <<
00314                         st_state.pose_wc.twist.angular.y << " " <<
00315                         st_state.pose_wc.twist.angular.z );
00316 
00317         st_state.rb_id = this->_rb_id;
00318         st_state.fitness_score = std::numeric_limits<float>::infinity();
00319 
00320         st_state.probabilistic_value = 1.0;
00321 
00322         st_state.number_of_points_of_model = 0;
00323         st_state.number_of_points_of_current_pc = 0;
00324     }
00325 }
00326 
00327 void ShapeTracker::setShapeModel(const sensor_msgs::PointCloud2& model)
00328 {
00329     // Convert ROS PC message into a pcl point cloud
00330     pcl::fromROSMsg(model, *this->_rb_model);
00331 
00332     // If the model is new we convert it into libpointmatcher
00333     sensor_msgs::PointCloud2 rb_model_ros;
00334     pcl::toROSMsg(*this->_rb_model, rb_model_ros);
00335     _rb_model_lpm.reset(new DP(PointMatcher_ros::rosMsgToPointMatcherCloud<float>(rb_model_ros)));
00336 }
00337 
00338 void ShapeTracker::_RemoveInconsistentPointsFromRBModel(pcl::PointCloud<pcl::PointXYZ >::Ptr model_current_pose,
00339                                                         pcl::PointCloud<pcl::PointXYZ >::Ptr current_pc,
00340                                                         pcl::PointCloud<pcl::PointXYZ >::Ptr& rb_segment,
00341                                                         pcl::PointCloud<pcl::PointXYZ >::Ptr& current_pc_extended_segment)
00342 {
00343     // Estimate the depth map from the current point cloud (organized)
00344     OrganizedPC2DepthMap2(current_pc, this->_current_dm);
00345 
00346     pcl::PointIndicesPtr indices_to_remove(new pcl::PointIndices);
00347 
00348     // These are the points in the current pc that are consistent with the moved model
00349     // -> the current visible segment
00350     pcl::PointIndicesPtr indices_matching_in_current(new pcl::PointIndices);
00351 
00352     // These are the points of the model that are visible now
00353     pcl::PointIndicesPtr indices_matching_in_model(new pcl::PointIndices);
00354 
00355     // Find points that are inconsistent between moved rb_shape and current depth image
00356     // Detect the points of the current PC and of the moved model that have neighbors
00357     _FindInconsistentPoints(model_current_pose, // input
00358                             this->_current_dm, // input
00359                             indices_to_remove, // output
00360                             indices_matching_in_model, // output
00361                             indices_matching_in_current // output
00362                             );
00363 
00364     ROS_INFO_STREAM_NAMED("ShapeReconstruction._RemoveInconsistentPointsFromRBModel",
00365                           "Matched points in current point cloud: " << indices_matching_in_current->indices.size());
00366     ROS_INFO_STREAM_NAMED("ShapeReconstruction._RemoveInconsistentPointsFromRBModel",
00367                           "Matched points in model: " << indices_matching_in_model->indices.size());
00368 
00369     // Convert the indices in a binary image (white == current segment)
00370     this->_segment_of_current.setTo(0);
00371     IndicesOfOrganizedPC2Image8u(indices_matching_in_current, this->_segment_of_current);
00372 
00373     // Dilate the current segment -> Covers more area for ICP
00374     cv::dilate(this->_segment_of_current, this->_segment_of_current_dilated, this->_dilation_element);
00375 
00376     // Convert the dilated binary image into a set of point indices (of the current pc)
00377     pcl::PointIndicesPtr indices_matching_in_current_extended(new pcl::PointIndices);
00378     Image8u2IndicesOfOrganizedPC(this->_segment_of_current_dilated, indices_matching_in_current_extended);
00379 
00380     ROS_INFO_STREAM_NAMED("ShapeReconstruction._RemoveInconsistentPointsFromRBModel",
00381                           "Matched points in current point cloud extended: " << indices_matching_in_current_extended->indices.size());
00382 
00383     // Extract the part of the model that have neighbors (moved to current frame)
00384     _extractor.setNegative(false);
00385     _extractor.setInputCloud(model_current_pose);
00386     _extractor.setIndices(indices_matching_in_model);
00387     _extractor.setKeepOrganized(false);
00388     _extractor.filter(*rb_segment);
00389 
00390     // Extract the part of the point cloud that have neighbors, extended with the dilate operation
00391     _extractor.setInputCloud(current_pc);
00392     _extractor.setIndices(indices_matching_in_current_extended);
00393     _extractor.setKeepOrganized(false);
00394     _extractor.filter(*current_pc_extended_segment);
00395 }
00396 
00397 void ShapeTracker::_FindInconsistentPoints(const pcl::PointCloud<pcl::PointXYZ >::Ptr& pc_source,
00398                                            const cv::Mat & dm_true,
00399                                            pcl::PointIndicesPtr& indices_to_remove,
00400                                            pcl::PointIndicesPtr& indices_matching_in_true,
00401                                            pcl::PointIndicesPtr& indices_matching_in_dm,
00402                                            const double min_depth_error)
00403 {
00404     indices_to_remove->indices.clear();
00405 
00406     using ::shape_reconstruction::RangeImagePlanar;
00407     RangeImagePlanar::Ptr dm_source_rip(new RangeImagePlanar);
00408 
00409     Eigen::Affine3f sensor_pose;
00410     sensor_pose.matrix() = Eigen::Matrix4f::Identity();
00411     pcl::RangeImagePlanar::CoordinateFrame coordinate_frame = pcl::RangeImagePlanar::CAMERA_FRAME;
00412 
00413     int width = dm_true.cols, height = dm_true.rows;
00414     dm_source_rip->matchPointCloudAndImage (*pc_source,
00415                                             width,
00416                                             height,
00417                                             this->_ci.P[2], //width/2 -0.5, //319.5, // 329.245223575443,
00418             this->_ci.P[6], //height/2 - 0.5, // 239.5, //  239.458
00419             this->_ci.P[0], // fx
00420             this->_ci.P[5], // fy
00421             sensor_pose,
00422             coordinate_frame,
00423             dm_true,
00424             min_depth_error,
00425             indices_matching_in_true,
00426             indices_matching_in_dm,
00427             indices_to_remove
00428             );
00429 
00430 }
00431 
00432 /*************************************
00433  * The inputs for this function are
00434  * data_pi --> the corresponding points in the data_cloud or source cloud or Pi
00435  * model_qi --> the correspondences in the model or target or Qi
00436  * RT --> the transformation matrix as returned by ICP
00437  * Output is a 6x6 matrix which is the COVARIANCE of ICP in [x,y,z,a,b,c]
00438  * [a b c] are Yaw, Pitch and Roll respectively
00439 ***************************************/
00440 void calculate_ICP_COV(pcl::PointCloud<pcl::PointXYZ>& data_pi, pcl::PointCloud<pcl::PointXYZ>& model_qi, Eigen::Matrix4f& transform, Eigen::MatrixXd& ICP_COV)
00441 {
00442 
00443     double Tx = transform(0,3);
00444     double Ty = transform(1,3);
00445     double Tz = transform(2,3);
00446     double roll  = atan2f(transform(2,1), transform(2,2));
00447     double pitch = asinf(-transform(2,0));
00448     double yaw   = atan2f(transform(1,0), transform(0,0));
00449 
00450     double x, y, z, a, b, c;
00451     x = Tx; y = Ty; z = Tz;
00452     a = yaw; b = pitch; c = roll;// important // According to the rotation matrix I used and after verification, it is Yaw Pitch ROLL = [a,b,c]== [R] matrix used in the MatLab also :)
00453 
00454     /* Flushing out in the form of XYZ ABC */
00455     std::cout << "\nPrinting out [x, y, z, a, b, c] =  " <<x<<"    "<<y<<"    "<<z<<"    "<<a<<"    "<<b<<"    "<<c<<std::endl;
00456 
00457     //Matrix initialization
00458     Eigen::MatrixXd d2J_dX2(6,6);
00459     d2J_dX2 = Eigen::MatrixXd::Zero(6,6);
00460 
00461     /****  Calculating d2J_dX2  ****/
00462     for (size_t s = 0; s < data_pi.points.size(); ++s )
00463     {
00464         double pix = data_pi.points[s].x;
00465         double piy = data_pi.points[s].y;
00466         double piz = data_pi.points[s].z;
00467         double qix = model_qi.points[s].x;
00468         double qiy = model_qi.points[s].y;
00469         double qiz = model_qi.points[s].z;
00470 
00471         /************************************************************
00472 
00473 d2J_dX2 -- X is the [R|T] in the form of [x, y, z, a, b, c]
00474 x, y, z is the translation part
00475 a, b, c is the rotation part in Euler format
00476 [x, y, z, a, b, c] is acquired from the Transformation Matrix returned by ICP.
00477 
00478 Now d2J_dX2 is a 6x6 matrix of the form
00479 
00480 d2J_dx2
00481 d2J_dxdy    d2J_dy2
00482 d2J_dxdz    d2J_dydz    d2J_dz2
00483 d2J_dxda    d2J_dyda    d2J_dzda   d2J_da2
00484 d2J_dxdb    d2J_dydb    d2J_dzdb   d2J_dadb   d2J_db2
00485 d2J_dxdc    d2J_dydc    d2J_dzdc   d2J_dadc   d2J_dbdc   d2J_dc2
00486 
00487 
00488 *************************************************************/
00489 
00490         double d2J_dx2,     d2J_dydx,     d2J_dzdx,   d2J_dadx,   d2J_dbdx,     d2J_dcdx,
00491                 d2J_dxdy,    d2J_dy2,     d2J_dzdy,   d2J_dady,   d2J_dbdy,     d2J_dcdy,
00492                 d2J_dxdz,    d2J_dydz,    d2J_dz2,    d2J_dadz,   d2J_dbdz,     d2J_dcdz,
00493                 d2J_dxda,    d2J_dyda,    d2J_dzda,   d2J_da2,    d2J_dbda,     d2J_dcda,
00494                 d2J_dxdb,    d2J_dydb,    d2J_dzdb,   d2J_dadb,   d2J_db2,      d2J_dcdb,
00495                 d2J_dxdc,    d2J_dydc,    d2J_dzdc,   d2J_dadc,   d2J_dbdc,     d2J_dc2;
00496 
00497         // These terms are generated from the provided Matlab scipts. We just have to copy
00498         // the expressions from the matlab output with two very simple changes.
00499         // The first one being the the sqaure of a number 'a' is shown as a^2 in matlab,
00500         // which is converted to pow(a,2) in the below expressions.
00501         // The second change is to add ';' at the end of each expression :)
00502         // In this way, matlab can be used to generate these terms for various objective functions of ICP
00503         // and they can simply be copied to the C++ files and with appropriate changes to ICP estimation,
00504         // its covariance can be easily estimated.
00505         d2J_dx2 = 2;
00506 
00507         d2J_dy2 = 2;
00508 
00509         d2J_dz2 = 2;
00510 
00511         d2J_dydx = 0;
00512 
00513         d2J_dxdy = 0;
00514 
00515         d2J_dzdx = 0;
00516 
00517         d2J_dxdz = 0;
00518 
00519         d2J_dydz = 0;
00520 
00521         d2J_dzdy = 0;
00522 
00523         d2J_da2 = (piz*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) - piy*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c)) + pix*cos(a)*cos(b))*(2*piz*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) - 2*piy*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c)) + 2*pix*cos(a)*cos(b)) - (2*piy*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c)) - 2*piz*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) + 2*pix*cos(b)*sin(a))*(y - qiy + piy*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c)) - piz*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) + pix*cos(b)*sin(a)) + (piy*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c)) - piz*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) + pix*cos(b)*sin(a))*(2*piy*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c)) - 2*piz*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) + 2*pix*cos(b)*sin(a)) - (2*piz*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) - 2*piy*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c)) + 2*pix*cos(a)*cos(b))*(x - qix - piy*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c)) + piz*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) + pix*cos(a)*cos(b));
00524 
00525         d2J_db2 = (pix*cos(b) + piz*cos(c)*sin(b) + piy*sin(b)*sin(c))*(2*pix*cos(b) + 2*piz*cos(c)*sin(b) + 2*piy*sin(b)*sin(c)) - (2*piz*cos(b)*cos(c) - 2*pix*sin(b) + 2*piy*cos(b)*sin(c))*(z - qiz - pix*sin(b) + piz*cos(b)*cos(c) + piy*cos(b)*sin(c)) - (2*pix*cos(a)*cos(b) + 2*piz*cos(a)*cos(c)*sin(b) + 2*piy*cos(a)*sin(b)*sin(c))*(x - qix - piy*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c)) + piz*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) + pix*cos(a)*cos(b)) + (piz*cos(a)*cos(b)*cos(c) - pix*cos(a)*sin(b) + piy*cos(a)*cos(b)*sin(c))*(2*piz*cos(a)*cos(b)*cos(c) - 2*pix*cos(a)*sin(b) + 2*piy*cos(a)*cos(b)*sin(c)) - (2*pix*cos(b)*sin(a) + 2*piz*cos(c)*sin(a)*sin(b) + 2*piy*sin(a)*sin(b)*sin(c))*(y - qiy + piy*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c)) - piz*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) + pix*cos(b)*sin(a)) + (piz*cos(b)*cos(c)*sin(a) - pix*sin(a)*sin(b) + piy*cos(b)*sin(a)*sin(c))*(2*piz*cos(b)*cos(c)*sin(a) - 2*pix*sin(a)*sin(b) + 2*piy*cos(b)*sin(a)*sin(c));
00526 
00527         d2J_dc2 = (piy*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) + piz*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c)))*(2*piy*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) + 2*piz*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c))) + (piy*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) + piz*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c)))*(2*piy*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) + 2*piz*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c))) - (2*piz*cos(b)*cos(c) + 2*piy*cos(b)*sin(c))*(z - qiz - pix*sin(b) + piz*cos(b)*cos(c) + piy*cos(b)*sin(c)) + (2*piy*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c)) - 2*piz*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)))*(x - qix - piy*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c)) + piz*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) + pix*cos(a)*cos(b)) + (piy*cos(b)*cos(c) - piz*cos(b)*sin(c))*(2*piy*cos(b)*cos(c) - 2*piz*cos(b)*sin(c)) - (2*piy*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c)) - 2*piz*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)))*(y - qiy + piy*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c)) - piz*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) + pix*cos(b)*sin(a));
00528 
00529         d2J_dxda = 2*piz*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) - 2*piy*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c)) - 2*pix*cos(b)*sin(a);
00530 
00531         d2J_dadx = 2*piz*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) - 2*piy*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c)) - 2*pix*cos(b)*sin(a);
00532 
00533         d2J_dyda = 2*piz*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) - 2*piy*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c)) + 2*pix*cos(a)*cos(b);
00534 
00535         d2J_dady = 2*piz*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) - 2*piy*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c)) + 2*pix*cos(a)*cos(b);
00536 
00537         d2J_dzda = 0;
00538 
00539         d2J_dadz = 0;
00540 
00541         d2J_dxdb = 2*piz*cos(a)*cos(b)*cos(c) - 2*pix*cos(a)*sin(b) + 2*piy*cos(a)*cos(b)*sin(c);
00542 
00543         d2J_dbdx = 2*piz*cos(a)*cos(b)*cos(c) - 2*pix*cos(a)*sin(b) + 2*piy*cos(a)*cos(b)*sin(c);
00544 
00545         d2J_dydb = 2*piz*cos(b)*cos(c)*sin(a) - 2*pix*sin(a)*sin(b) + 2*piy*cos(b)*sin(a)*sin(c);
00546 
00547         d2J_dbdy = 2*piz*cos(b)*cos(c)*sin(a) - 2*pix*sin(a)*sin(b) + 2*piy*cos(b)*sin(a)*sin(c);
00548 
00549         d2J_dzdb = - 2*pix*cos(b) - 2*piz*cos(c)*sin(b) - 2*piy*sin(b)*sin(c);
00550 
00551         d2J_dbdz = - 2*pix*cos(b) - 2*piz*cos(c)*sin(b) - 2*piy*sin(b)*sin(c);
00552 
00553         d2J_dxdc = 2*piy*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) + 2*piz*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c));
00554 
00555         d2J_dcdx = 2*piy*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) + 2*piz*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c));
00556 
00557         d2J_dydc = - 2*piy*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) - 2*piz*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c));
00558 
00559         d2J_dcdy = - 2*piy*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) - 2*piz*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c));
00560 
00561         d2J_dzdc = 2*piy*cos(b)*cos(c) - 2*piz*cos(b)*sin(c);
00562 
00563         d2J_dcdz = 2*piy*cos(b)*cos(c) - 2*piz*cos(b)*sin(c);
00564 
00565         d2J_dadb = (2*piz*cos(b)*cos(c)*sin(a) - 2*pix*sin(a)*sin(b) + 2*piy*cos(b)*sin(a)*sin(c))*(piz*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) - piy*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c)) + pix*cos(a)*cos(b)) - (2*piz*cos(a)*cos(b)*cos(c) - 2*pix*cos(a)*sin(b) + 2*piy*cos(a)*cos(b)*sin(c))*(piy*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c)) - piz*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) + pix*cos(b)*sin(a)) + (2*piz*cos(a)*cos(b)*cos(c) - 2*pix*cos(a)*sin(b) + 2*piy*cos(a)*cos(b)*sin(c))*(y - qiy + piy*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c)) - piz*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) + pix*cos(b)*sin(a)) - (2*piz*cos(b)*cos(c)*sin(a) - 2*pix*sin(a)*sin(b) + 2*piy*cos(b)*sin(a)*sin(c))*(x - qix - piy*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c)) + piz*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) + pix*cos(a)*cos(b));
00566 
00567         d2J_dbda = (piz*cos(b)*cos(c)*sin(a) - pix*sin(a)*sin(b) + piy*cos(b)*sin(a)*sin(c))*(2*piz*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) - 2*piy*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c)) + 2*pix*cos(a)*cos(b)) - (piz*cos(a)*cos(b)*cos(c) - pix*cos(a)*sin(b) + piy*cos(a)*cos(b)*sin(c))*(2*piy*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c)) - 2*piz*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) + 2*pix*cos(b)*sin(a)) + (2*piz*cos(a)*cos(b)*cos(c) - 2*pix*cos(a)*sin(b) + 2*piy*cos(a)*cos(b)*sin(c))*(y - qiy + piy*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c)) - piz*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) + pix*cos(b)*sin(a)) - (2*piz*cos(b)*cos(c)*sin(a) - 2*pix*sin(a)*sin(b) + 2*piy*cos(b)*sin(a)*sin(c))*(x - qix - piy*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c)) + piz*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) + pix*cos(a)*cos(b));
00568 
00569         d2J_dbdc = (2*piy*cos(a)*cos(b)*cos(c) - 2*piz*cos(a)*cos(b)*sin(c))*(x - qix - piy*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c)) + piz*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) + pix*cos(a)*cos(b)) + (2*piy*cos(b)*cos(c)*sin(a) - 2*piz*cos(b)*sin(a)*sin(c))*(y - qiy + piy*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c)) - piz*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) + pix*cos(b)*sin(a)) - (2*piy*cos(b)*cos(c) - 2*piz*cos(b)*sin(c))*(pix*cos(b) + piz*cos(c)*sin(b) + piy*sin(b)*sin(c)) - (2*piy*cos(c)*sin(b) - 2*piz*sin(b)*sin(c))*(z - qiz - pix*sin(b) + piz*cos(b)*cos(c) + piy*cos(b)*sin(c)) + (2*piy*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) + 2*piz*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c)))*(piz*cos(a)*cos(b)*cos(c) - pix*cos(a)*sin(b) + piy*cos(a)*cos(b)*sin(c)) - (2*piy*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) + 2*piz*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c)))*(piz*cos(b)*cos(c)*sin(a) - pix*sin(a)*sin(b) + piy*cos(b)*sin(a)*sin(c));
00570 
00571         d2J_dcdb = (2*piy*cos(a)*cos(b)*cos(c) - 2*piz*cos(a)*cos(b)*sin(c))*(x - qix - piy*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c)) + piz*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) + pix*cos(a)*cos(b)) + (2*piy*cos(b)*cos(c)*sin(a) - 2*piz*cos(b)*sin(a)*sin(c))*(y - qiy + piy*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c)) - piz*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) + pix*cos(b)*sin(a)) - (piy*cos(b)*cos(c) - piz*cos(b)*sin(c))*(2*pix*cos(b) + 2*piz*cos(c)*sin(b) + 2*piy*sin(b)*sin(c)) - (2*piy*cos(c)*sin(b) - 2*piz*sin(b)*sin(c))*(z - qiz - pix*sin(b) + piz*cos(b)*cos(c) + piy*cos(b)*sin(c)) + (piy*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) + piz*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c)))*(2*piz*cos(a)*cos(b)*cos(c) - 2*pix*cos(a)*sin(b) + 2*piy*cos(a)*cos(b)*sin(c)) - (piy*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) + piz*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c)))*(2*piz*cos(b)*cos(c)*sin(a) - 2*pix*sin(a)*sin(b) + 2*piy*cos(b)*sin(a)*sin(c));
00572 
00573         d2J_dcda = (2*piy*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) + 2*piz*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c)))*(x - qix - piy*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c)) + piz*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) + pix*cos(a)*cos(b)) - (piy*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) + piz*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c)))*(2*piy*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c)) - 2*piz*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) + 2*pix*cos(b)*sin(a)) - (piy*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) + piz*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c)))*(2*piz*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) - 2*piy*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c)) + 2*pix*cos(a)*cos(b)) + (2*piy*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) + 2*piz*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c)))*(y - qiy + piy*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c)) - piz*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) + pix*cos(b)*sin(a));
00574 
00575         d2J_dadc = (2*piy*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) + 2*piz*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c)))*(x - qix - piy*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c)) + piz*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) + pix*cos(a)*cos(b)) - (2*piy*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) + 2*piz*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c)))*(piy*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c)) - piz*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) + pix*cos(b)*sin(a)) - (2*piy*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) + 2*piz*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c)))*(piz*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) - piy*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c)) + pix*cos(a)*cos(b)) + (2*piy*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) + 2*piz*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c)))*(y - qiy + piy*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c)) - piz*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) + pix*cos(b)*sin(a));
00576 
00577         Eigen::MatrixXd d2J_dX2_temp(6,6);
00578 
00579         d2J_dX2_temp << d2J_dx2,     d2J_dydx,    d2J_dzdx,   d2J_dadx,   d2J_dbdx,     d2J_dzdx,
00580                 d2J_dxdy,    d2J_dy2,     d2J_dzdy,   d2J_dady,   d2J_dbdy,     d2J_dcdy,
00581                 d2J_dxdz,    d2J_dydz,    d2J_dz2,    d2J_dadz,   d2J_dbdz,     d2J_dcdz,
00582                 d2J_dxda,    d2J_dyda,    d2J_dzda,   d2J_da2,    d2J_dbda,     d2J_dcda,
00583                 d2J_dxdb,    d2J_dydb,    d2J_dzdb,   d2J_dadb,   d2J_db2,      d2J_dcdb,
00584                 d2J_dxdc,    d2J_dydc,    d2J_dzdc,   d2J_dadc,   d2J_dbdc,     d2J_dc2;
00585 
00586         d2J_dX2 = d2J_dX2 + d2J_dX2_temp;
00587 
00588     }// End of the FOR loop!!!
00589 
00590     std::cout << "\n**************\n Successfully Computed d2J_dX2 \n**************\n" << std::endl;
00591 
00592     // Now its time to calculate d2J_dZdX , where Z are the measurements Pi and Qi, X = [x,y,z,a,b,c]
00593 
00594     // n is the number of correspondences
00595     int n = data_pi.points.size();
00596 
00597     if (n > 200) n = 200;
00598 
00599     std::cout << "\nNumber of Correspondences used for ICP's covariance estimation = " << n << std::endl;
00600 
00601     Eigen::MatrixXd d2J_dZdX(6,6*n);
00602 
00603     for (int k = 0; k < n ; ++k) // row
00604     {
00605         //here the current correspondences are loaded into Pi and Qi
00606         double pix = data_pi.points[k].x;
00607         double piy = data_pi.points[k].y;
00608         double piz = data_pi.points[k].z;
00609         double qix = model_qi.points[k].x;
00610         double qiy = model_qi.points[k].y;
00611         double qiz = model_qi.points[k].z;
00612 
00613         Eigen::MatrixXd d2J_dZdX_temp(6,6);
00614 
00615 
00616         double  d2J_dpix_dx,    d2J_dpiy_dx,    d2J_dpiz_dx,       d2J_dqix_dx,    d2J_dqiy_dx,    d2J_dqiz_dx,
00617                 d2J_dpix_dy,    d2J_dpiy_dy,    d2J_dpiz_dy,       d2J_dqix_dy,    d2J_dqiy_dy,    d2J_dqiz_dy,
00618                 d2J_dpix_dz,    d2J_dpiy_dz,    d2J_dpiz_dz,       d2J_dqix_dz,    d2J_dqiy_dz,    d2J_dqiz_dz,
00619                 d2J_dpix_da,    d2J_dpiy_da,    d2J_dpiz_da,       d2J_dqix_da,    d2J_dqiy_da,    d2J_dqiz_da,
00620                 d2J_dpix_db,    d2J_dpiy_db,    d2J_dpiz_db,       d2J_dqix_db,    d2J_dqiy_db,    d2J_dqiz_db,
00621                 d2J_dpix_dc,    d2J_dpiy_dc,    d2J_dpiz_dc,       d2J_dqix_dc,    d2J_dqiy_dc,    d2J_dqiz_dc;
00622 
00623         d2J_dpix_dx = 2*cos(a)*cos(b);
00624 
00625         d2J_dpix_dy = 2*cos(b)*sin(a);
00626 
00627         d2J_dpix_dz = -2*sin(b);
00628 
00629         d2J_dpix_da = cos(b)*sin(a)*(2*piz*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) - 2*piy*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c)) + 2*pix*cos(a)*cos(b)) - cos(a)*cos(b)*(2*piy*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c)) - 2*piz*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) + 2*pix*cos(b)*sin(a)) - 2*cos(b)*sin(a)*(x - qix - piy*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c)) + piz*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) + pix*cos(a)*cos(b)) + 2*cos(a)*cos(b)*(y - qiy + piy*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c)) - piz*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) + pix*cos(b)*sin(a));
00630 
00631         d2J_dpix_db = sin(b)*(2*pix*cos(b) + 2*piz*cos(c)*sin(b) + 2*piy*sin(b)*sin(c)) - 2*cos(b)*(z - qiz - pix*sin(b) + piz*cos(b)*cos(c) + piy*cos(b)*sin(c)) + cos(a)*cos(b)*(2*piz*cos(a)*cos(b)*cos(c) - 2*pix*cos(a)*sin(b) + 2*piy*cos(a)*cos(b)*sin(c)) - 2*sin(a)*sin(b)*(y - qiy + piy*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c)) - piz*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) + pix*cos(b)*sin(a)) + cos(b)*sin(a)*(2*piz*cos(b)*cos(c)*sin(a) - 2*pix*sin(a)*sin(b) + 2*piy*cos(b)*sin(a)*sin(c)) - 2*cos(a)*sin(b)*(x - qix - piy*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c)) + piz*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) + pix*cos(a)*cos(b));
00632 
00633         d2J_dpix_dc = cos(a)*cos(b)*(2*piy*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) + 2*piz*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c))) - sin(b)*(2*piy*cos(b)*cos(c) - 2*piz*cos(b)*sin(c)) - cos(b)*sin(a)*(2*piy*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) + 2*piz*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c)));
00634 
00635         d2J_dpiy_dx = 2*cos(a)*sin(b)*sin(c) - 2*cos(c)*sin(a);
00636 
00637         d2J_dpiy_dy = 2*cos(a)*cos(c) + 2*sin(a)*sin(b)*sin(c);
00638 
00639         d2J_dpiy_dz = 2*cos(b)*sin(c);
00640 
00641         d2J_dpiy_da = (cos(a)*cos(c) + sin(a)*sin(b)*sin(c))*(2*piz*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) - 2*piy*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c)) + 2*pix*cos(a)*cos(b)) + (cos(c)*sin(a) - cos(a)*sin(b)*sin(c))*(2*piy*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c)) - 2*piz*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) + 2*pix*cos(b)*sin(a)) - (2*cos(a)*cos(c) + 2*sin(a)*sin(b)*sin(c))*(x - qix - piy*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c)) + piz*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) + pix*cos(a)*cos(b)) - (2*cos(c)*sin(a) - 2*cos(a)*sin(b)*sin(c))*(y - qiy + piy*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c)) - piz*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) + pix*cos(b)*sin(a));
00642 
00643         d2J_dpiy_db = (cos(a)*cos(c) + sin(a)*sin(b)*sin(c))*(2*piz*cos(b)*cos(c)*sin(a) - 2*pix*sin(a)*sin(b) + 2*piy*cos(b)*sin(a)*sin(c)) - (cos(c)*sin(a) - cos(a)*sin(b)*sin(c))*(2*piz*cos(a)*cos(b)*cos(c) - 2*pix*cos(a)*sin(b) + 2*piy*cos(a)*cos(b)*sin(c)) - 2*sin(b)*sin(c)*(z - qiz - pix*sin(b) + piz*cos(b)*cos(c) + piy*cos(b)*sin(c)) - cos(b)*sin(c)*(2*pix*cos(b) + 2*piz*cos(c)*sin(b) + 2*piy*sin(b)*sin(c)) + 2*cos(a)*cos(b)*sin(c)*(x - qix - piy*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c)) + piz*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) + pix*cos(a)*cos(b)) + 2*cos(b)*sin(a)*sin(c)*(y - qiy + piy*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c)) - piz*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) + pix*cos(b)*sin(a));
00644 
00645         d2J_dpiy_dc = (2*sin(a)*sin(c) + 2*cos(a)*cos(c)*sin(b))*(x - qix - piy*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c)) + piz*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) + pix*cos(a)*cos(b)) - (2*cos(a)*sin(c) - 2*cos(c)*sin(a)*sin(b))*(y - qiy + piy*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c)) - piz*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) + pix*cos(b)*sin(a)) - (cos(a)*cos(c) + sin(a)*sin(b)*sin(c))*(2*piy*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) + 2*piz*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c))) - (cos(c)*sin(a) - cos(a)*sin(b)*sin(c))*(2*piy*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) + 2*piz*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c))) + 2*cos(b)*cos(c)*(z - qiz - pix*sin(b) + piz*cos(b)*cos(c) + piy*cos(b)*sin(c)) + cos(b)*sin(c)*(2*piy*cos(b)*cos(c) - 2*piz*cos(b)*sin(c));
00646 
00647         d2J_dpiz_dx = 2*sin(a)*sin(c) + 2*cos(a)*cos(c)*sin(b);
00648 
00649         d2J_dpiz_dy = 2*cos(c)*sin(a)*sin(b) - 2*cos(a)*sin(c);
00650 
00651         d2J_dpiz_dz = 2*cos(b)*cos(c);
00652 
00653         d2J_dpiz_da = (2*cos(a)*sin(c) - 2*cos(c)*sin(a)*sin(b))*(x - qix - piy*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c)) + piz*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) + pix*cos(a)*cos(b)) - (sin(a)*sin(c) + cos(a)*cos(c)*sin(b))*(2*piy*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c)) - 2*piz*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) + 2*pix*cos(b)*sin(a)) - (cos(a)*sin(c) - cos(c)*sin(a)*sin(b))*(2*piz*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) - 2*piy*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c)) + 2*pix*cos(a)*cos(b)) + (2*sin(a)*sin(c) + 2*cos(a)*cos(c)*sin(b))*(y - qiy + piy*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c)) - piz*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) + pix*cos(b)*sin(a));
00654 
00655         d2J_dpiz_db = (sin(a)*sin(c) + cos(a)*cos(c)*sin(b))*(2*piz*cos(a)*cos(b)*cos(c) - 2*pix*cos(a)*sin(b) + 2*piy*cos(a)*cos(b)*sin(c)) - (cos(a)*sin(c) - cos(c)*sin(a)*sin(b))*(2*piz*cos(b)*cos(c)*sin(a) - 2*pix*sin(a)*sin(b) + 2*piy*cos(b)*sin(a)*sin(c)) - 2*cos(c)*sin(b)*(z - qiz - pix*sin(b) + piz*cos(b)*cos(c) + piy*cos(b)*sin(c)) - cos(b)*cos(c)*(2*pix*cos(b) + 2*piz*cos(c)*sin(b) + 2*piy*sin(b)*sin(c)) + 2*cos(a)*cos(b)*cos(c)*(x - qix - piy*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c)) + piz*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) + pix*cos(a)*cos(b)) + 2*cos(b)*cos(c)*sin(a)*(y - qiy + piy*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c)) - piz*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) + pix*cos(b)*sin(a));
00656 
00657         d2J_dpiz_dc = (2*cos(c)*sin(a) - 2*cos(a)*sin(b)*sin(c))*(x - qix - piy*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c)) + piz*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) + pix*cos(a)*cos(b)) - (2*cos(a)*cos(c) + 2*sin(a)*sin(b)*sin(c))*(y - qiy + piy*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c)) - piz*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) + pix*cos(b)*sin(a)) + (sin(a)*sin(c) + cos(a)*cos(c)*sin(b))*(2*piy*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) + 2*piz*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c))) + (cos(a)*sin(c) - cos(c)*sin(a)*sin(b))*(2*piy*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) + 2*piz*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c))) + cos(b)*cos(c)*(2*piy*cos(b)*cos(c) - 2*piz*cos(b)*sin(c)) - 2*cos(b)*sin(c)*(z - qiz - pix*sin(b) + piz*cos(b)*cos(c) + piy*cos(b)*sin(c));
00658 
00659         d2J_dqix_dx = -2;
00660 
00661         d2J_dqix_dy = 0;
00662 
00663         d2J_dqix_dz = 0;
00664 
00665         d2J_dqix_da = 2*piy*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c)) - 2*piz*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) + 2*pix*cos(b)*sin(a);
00666 
00667         d2J_dqix_db = 2*pix*cos(a)*sin(b) - 2*piz*cos(a)*cos(b)*cos(c) - 2*piy*cos(a)*cos(b)*sin(c);
00668 
00669         d2J_dqix_dc = - 2*piy*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) - 2*piz*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c));
00670 
00671         d2J_dqiy_dx = 0;
00672 
00673         d2J_dqiy_dy = -2;
00674 
00675         d2J_dqiy_dz = 0;
00676 
00677         d2J_dqiy_da = 2*piy*(cos(c)*sin(a) - cos(a)*sin(b)*sin(c)) - 2*piz*(sin(a)*sin(c) + cos(a)*cos(c)*sin(b)) - 2*pix*cos(a)*cos(b);
00678 
00679         d2J_dqiy_db = 2*pix*sin(a)*sin(b) - 2*piz*cos(b)*cos(c)*sin(a) - 2*piy*cos(b)*sin(a)*sin(c);
00680 
00681         d2J_dqiy_dc = 2*piy*(cos(a)*sin(c) - cos(c)*sin(a)*sin(b)) + 2*piz*(cos(a)*cos(c) + sin(a)*sin(b)*sin(c));
00682 
00683         d2J_dqiz_dx = 0;
00684 
00685         d2J_dqiz_dy = 0;
00686 
00687         d2J_dqiz_dz = -2;
00688 
00689         d2J_dqiz_da = 0;
00690 
00691         d2J_dqiz_db =  2*pix*cos(b) + 2*piz*cos(c)*sin(b) + 2*piy*sin(b)*sin(c);
00692 
00693         d2J_dqiz_dc =  2*piz*cos(b)*sin(c) - 2*piy*cos(b)*cos(c);
00694 
00695         d2J_dZdX_temp <<    d2J_dpix_dx,    d2J_dpiy_dx,        d2J_dpiz_dx,       d2J_dqix_dx,    d2J_dqiy_dx,    d2J_dqiz_dx,
00696                 d2J_dpix_dy,    d2J_dpiy_dy,    d2J_dpiz_dy,       d2J_dqix_dy,    d2J_dqiy_dy,    d2J_dqiz_dy,
00697                 d2J_dpix_dz,    d2J_dpiy_dz,        d2J_dpiz_dz,       d2J_dqix_dz,    d2J_dqiy_dz,    d2J_dqiz_dz,
00698                 d2J_dpix_da,    d2J_dpiy_da,        d2J_dpiz_da,       d2J_dqix_da,    d2J_dqiy_da,    d2J_dqiz_da,
00699                 d2J_dpix_db,    d2J_dpiy_db,        d2J_dpiz_db,       d2J_dqix_db,    d2J_dqiy_db,    d2J_dqiz_db,
00700                 d2J_dpix_dc,    d2J_dpiy_dc,        d2J_dpiz_dc,       d2J_dqix_dc,    d2J_dqiy_dc,    d2J_dqiz_dc;
00701 
00702 
00703         d2J_dZdX.block<6,6>(0,6*k) = d2J_dZdX_temp;
00704     }
00705 
00706     /**************************************
00707      *
00708      * Here we create the matrix cov(z) as mentioned in Section 3.3 in the paper, "Covariance of ICP with 3D Point to Point and Point to Plane Error Metrics"
00709      *
00710      * ************************************/
00711 
00712     Eigen::MatrixXd cov_z(6*n,6*n);
00713     cov_z = 0.01 * Eigen::MatrixXd::Identity(6*n,6*n);
00714 
00715     ICP_COV =  d2J_dX2.inverse() * d2J_dZdX * cov_z * d2J_dZdX.transpose() * d2J_dX2.inverse();
00716 
00717     std::cout << "\n\n********************** \n\n" << "ICP_COV = \n" << ICP_COV <<"\n*******************\n\n"<< std::endl;
00718 
00719     std::cout << "\nSuccessfully Computed the ICP's Covariance !!!\n" << std::endl;
00720 }


shape_tracker
Author(s): Roberto Martín-Martín
autogenerated on Sat Jun 8 2019 18:54:11