00001 #include "zyonz_find_leaf_probing_points_alg_node.h"
00002
00003
00004 bool MyDataSortPredicate(const geometry_msgs::Pose& d1, const geometry_msgs::Pose& d2)
00005 {
00006 return d1.position.y < d2.position.y;
00007 }
00008
00009 ZyonzFindLeafProbingPointsAlgNode::ZyonzFindLeafProbingPointsAlgNode(void) :
00010 algorithm_base::IriBaseAlgorithm<ZyonzFindLeafProbingPointsAlgorithm>(),
00011 data_processed_(false)
00012 {
00013
00014
00015
00016
00017 poses_publisher_ = public_node_handle_.advertise<geometry_msgs::PoseArray>("poses", 10);
00018 output_marker_publisher_ = public_node_handle_.advertise<visualization_msgs::Marker>("output_marker", 10);
00019 output_pointcloud_publisher_ = public_node_handle_.advertise<sensor_msgs::PointCloud2>("output_pointcloud", 10);
00020
00021
00022 input_subscriber_ = public_node_handle_.subscribe("input", 10, &ZyonzFindLeafProbingPointsAlgNode::input_callback, this);
00023
00024
00025 get_pose_array_server_ = public_node_handle_.advertiseService("get_pose_array", &ZyonzFindLeafProbingPointsAlgNode::get_pose_arrayCallback, this);
00026
00027
00028
00029
00030
00031
00032 }
00033
00034 ZyonzFindLeafProbingPointsAlgNode::~ZyonzFindLeafProbingPointsAlgNode(void)
00035 {
00036
00037 }
00038
00039 void ZyonzFindLeafProbingPointsAlgNode::mainNodeThread(void)
00040 {
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 }
00055
00056
00057 void ZyonzFindLeafProbingPointsAlgNode::input_callback(const sensor_msgs::PointCloud2::ConstPtr& msg)
00058 {
00059
00060
00061
00062 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
00063 pcl::fromROSMsg (*msg, *cloud);
00064
00065
00066
00067
00068
00069 pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients);
00070 pcl::PointIndices::Ptr inliers (new pcl::PointIndices);
00071
00072 pcl::SACSegmentation<pcl::PointXYZ> seg;
00073
00074 seg.setOptimizeCoefficients (true);
00075
00076 seg.setModelType (pcl::SACMODEL_PLANE);
00077 seg.setMethodType (pcl::SAC_RANSAC);
00078 seg.setDistanceThreshold (0.01);
00079 seg.setInputCloud (cloud);
00080 seg.segment (*inliers, *coefficients);
00081
00082
00083
00084
00085 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_projected (new pcl::PointCloud<pcl::PointXYZ>);
00086 pcl::ProjectInliers<pcl::PointXYZ> proj;
00087 proj.setModelType (pcl::SACMODEL_PLANE);
00088 proj.setInputCloud (cloud);
00089 proj.setModelCoefficients (coefficients);
00090 proj.filter (*cloud_projected);
00091
00092
00093
00094
00095 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_hull (new pcl::PointCloud<pcl::PointXYZ>);
00096 pcl::ConcaveHull<pcl::PointXYZ> chull;
00097
00098 chull.setInputCloud (cloud_projected);
00099 chull.setAlpha (0.1);
00100 chull.reconstruct (*cloud_hull);
00101
00102
00103 Eigen::Vector4f centroid;
00104 pcl::compute3DCentroid (*cloud, centroid);
00105
00106
00107
00108
00109 Eigen::MatrixXf B(cloud->points.size(),3);
00110 int aa = 0;
00111 for (pcl::PointCloud<pcl::PointXYZ>::iterator it = cloud->begin(); it != cloud->end(); ++it, ++aa){
00112 B.row(aa)[0] = it->x - centroid(0);
00113 B.row(aa)[1] = it->y - centroid(1);
00114 B.row(aa)[2] = it->z - centroid(2);
00115
00116 }
00117 Eigen::Matrix3f C = (B.transpose()*B)/cloud->points.size();
00118
00119
00120
00121 Eigen::SelfAdjointEigenSolver<Eigen::Matrix3f> eigensolver(C);
00122 if (eigensolver.info() != Eigen::Success)
00123 ROS_ERROR("EigenVectors not found :'(");
00124 std::cout << "Eigenvalues are: \n" << eigensolver.eigenvalues() << std::endl << "Eigenvectors are: \n" << eigensolver.eigenvectors() << std::endl;
00125 std::cout << "1st EigenVector: (" << eigensolver.eigenvectors()(0,0) << ", " << eigensolver.eigenvectors()(0,1) << ", " << eigensolver.eigenvectors()(0,2) << ")" << std::endl;
00126
00127
00128 Eigen::Matrix3f rot_m;
00129 rot_m << -eigensolver.eigenvectors()(0,1), -eigensolver.eigenvectors()(0,2), eigensolver.eigenvectors()(0,0),
00130 -eigensolver.eigenvectors()(1,1), -eigensolver.eigenvectors()(1,2), eigensolver.eigenvectors()(1,0),
00131 -eigensolver.eigenvectors()(2,1), -eigensolver.eigenvectors()(2,2), eigensolver.eigenvectors()(2,0);
00132
00133
00134 Eigen::Quaternionf pose_c(rot_m);
00135
00136
00137
00138 Eigen::Vector3f translation (-centroid(0), -centroid(1), -centroid(2));
00139 pcl::PointCloud<pcl::PointXYZ>::Ptr trasl_cluster (new pcl::PointCloud<pcl::PointXYZ>);
00140 pcl::PointCloud<pcl::PointXYZ>::Ptr trasl_rot_cluster (new pcl::PointCloud<pcl::PointXYZ>);
00141
00142 pcl::transformPointCloud(*cloud_hull, *trasl_cluster, translation, Eigen::Quaternionf(1, 0, 0, 0));
00143 pcl::transformPointCloud(*trasl_cluster, *trasl_rot_cluster, Eigen::Vector3f(0,0,0), pose_c.conjugate());
00144
00145
00146 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_cluster_right (new pcl::PointCloud<pcl::PointXYZ>);
00147 pcl::PassThrough<pcl::PointXYZ> pass2;
00148 pass2.setInputCloud (trasl_rot_cluster);
00149 pass2.setFilterFieldName ("x");
00150 pass2.setFilterLimits (0, +20.0);
00151 pass2.filter (*cloud_cluster_right);
00152
00153
00154
00155 pcl::VoxelGrid<pcl::PointXYZ> sor;
00156 sor.setInputCloud (cloud_cluster_right);
00157 sor.setLeafSize (0.1f, 0.1f, 0.1f);
00158 sor.filter (*cloud_cluster_right);
00159
00160
00161 for (pcl::PointCloud<pcl::PointXYZ>::iterator it = cloud_cluster_right->begin(); it != cloud_cluster_right->end(); ++it){
00162 Eigen::Vector3f point(it->x, it->y, it->z);
00163 it->x = point.x()*(point.norm()-0.02)/point.norm();
00164 it->y = point.y()*(point.norm()-0.02)/point.norm();
00165 it->z = point.z()*(point.norm()-0.02)/point.norm();
00166 }
00167
00168
00169 translation = Eigen::Vector3f(centroid(0), centroid(1), centroid(2));
00170
00171 pcl::transformPointCloud(*cloud_cluster_right, *trasl_cluster, Eigen::Vector3f(0, 0, 0), pose_c);
00172 pcl::transformPointCloud(*trasl_cluster, *cloud_cluster_right, translation, Eigen::Quaternionf(1, 0, 0, 0));
00173
00174 static tf::TransformBroadcaster br;
00175 tf::Transform transform;
00176 transform.setOrigin( tf::Vector3(centroid(0), centroid(1), centroid(2)) );
00177 transform.setRotation( tf::Quaternion(pose_c.x(), pose_c.y(), pose_c.z(), pose_c.w()) );
00178 br.sendTransform(tf::StampedTransform(transform, ros::Time::now(), "/camboard_frame", "centroid"));
00179
00180
00181 uint32_t shape = visualization_msgs::Marker::SPHERE;
00182
00183
00184 Marker_msg_.header.frame_id = msg->header.frame_id;
00185 Marker_msg_.header.stamp = ros::Time::now();
00186 Marker_msg_.ns = "basic_shapes";
00187 Marker_msg_.id = 0;
00188 Marker_msg_.type = shape;
00189 Marker_msg_.action = visualization_msgs::Marker::ADD;
00190 Marker_msg_.pose.position.x = centroid.x();
00191 Marker_msg_.pose.position.y = centroid.y();
00192 Marker_msg_.pose.position.z = centroid.z();
00193 Marker_msg_.pose.orientation.x = pose_c.x();
00194 Marker_msg_.pose.orientation.y = pose_c.y();
00195 Marker_msg_.pose.orientation.z = pose_c.z();
00196 Marker_msg_.pose.orientation.w = pose_c.w();
00197 Marker_msg_.scale.x = eigensolver.eigenvalues()[1]*10;
00198 Marker_msg_.scale.y = eigensolver.eigenvalues()[2]*10;
00199 Marker_msg_.scale.z = eigensolver.eigenvalues()[0]*10;
00200 Marker_msg_.color.r = 0.0f;
00201 Marker_msg_.color.g = 1.0f;
00202 Marker_msg_.color.b = 0.0f;
00203 Marker_msg_.color.a = 1.0;
00204 Marker_msg_.lifetime = ros::Duration();
00205
00206
00207 geometry_msgs::PoseArray leaf_pose_array;
00208 leaf_pose_array.poses.clear();
00209 leaf_pose_array.header.stamp = ros::Time::now();
00210 leaf_pose_array.header.frame_id = msg->header.frame_id;
00211 for (pcl::PointCloud<pcl::PointXYZ>::iterator it = cloud_cluster_right->begin(); it != cloud_cluster_right->end(); ++it){
00212
00213 Eigen::Vector3f vx (it->x-centroid.x(), it->y-centroid.y(), it->z-centroid.z());
00214 Eigen::Vector3f vy (-eigensolver.eigenvectors()(0,2),-eigensolver.eigenvectors()(1,2), -eigensolver.eigenvectors()(2,2));
00215 Eigen::Vector3f vz (-eigensolver.eigenvectors()(0,0),-eigensolver.eigenvectors()(1,0), -eigensolver.eigenvectors()(2,0));
00216 vx = vx/vx.norm();
00217 vz = vx.cross(vy);
00218 vz = vz/vz.norm();
00219 vy = vz.cross(vx);
00220 vy = vy/vy.norm();
00221
00222 Eigen::Matrix3f rot_mm;
00223 rot_mm << vx.x(), vy.x(), vz.x(),
00224 vx.y(), vy.y(), vz.y(),
00225 vx.z(), vy.z(), vz.z();
00226 Eigen::Quaternionf pose_cc(rot_mm);
00227
00228 geometry_msgs::Pose pose;
00229 pose.position.x = it->x;
00230 pose.position.y = it->y;
00231 pose.position.z = it->z;
00232 pose.orientation.x = pose_cc.x();
00233 pose.orientation.y = pose_cc.y();
00234 pose.orientation.z = pose_cc.z();
00235 pose.orientation.w = pose_cc.w();
00236 leaf_pose_array.poses.push_back(pose);
00237 }
00238 std::sort(leaf_pose_array.poses.begin(), leaf_pose_array.poses.end(), MyDataSortPredicate);
00239
00240
00241 geometry_msgs::Pose initial_pose;
00242 initial_pose = leaf_pose_array.poses.front();
00243 Eigen::Vector3f initial_point;
00244 initial_point.x() = initial_pose.position.x - centroid.x();
00245 initial_point.y() = initial_pose.position.y - centroid.y();
00246 initial_point.z() = initial_pose.position.z - centroid.z();
00247 initial_point.x() = initial_point.x()*(initial_point.norm()+0.1)/initial_point.norm();
00248 initial_point.y() = initial_point.y()*(initial_point.norm()+0.1)/initial_point.norm();
00249 initial_point.z() = initial_point.z()*(initial_point.norm()+0.1)/initial_point.norm();
00250 initial_pose.position.x = initial_point.x() + centroid.x();
00251 initial_pose.position.y = initial_point.y() + centroid.y();
00252 initial_pose.position.z = initial_point.z() + centroid.z();
00253
00254
00255 geometry_msgs::Pose final_pose;
00256 final_pose = leaf_pose_array.poses.back();
00257 Eigen::Vector3f final_point;
00258 final_point.x() = final_pose.position.x - centroid.x();
00259 final_point.y() = final_pose.position.y - centroid.y();
00260 final_point.z() = final_pose.position.z - centroid.z();
00261 final_point.x() = final_point.x()*(final_point.norm()+0.1)/final_point.norm();
00262 final_point.y() = final_point.y()*(final_point.norm()+0.1)/final_point.norm();
00263 final_point.z() = final_point.z()*(final_point.norm()+0.1)/final_point.norm();
00264 final_pose.position.x = final_point.x()+centroid.x();
00265 final_pose.position.y = final_point.y()+centroid.y();
00266 final_pose.position.z = final_point.z()+centroid.z();
00267
00268
00269 pose_array_.poses.clear();
00270 pose_array_.header.stamp = ros::Time::now();
00271 pose_array_.header.frame_id = msg->header.frame_id;
00272 pose_array_.poses.push_back(initial_pose);
00273 for (std::vector<geometry_msgs::Pose>::iterator it = leaf_pose_array.poses.begin(); it < leaf_pose_array.poses.end(); ++it){
00274 pose_array_.poses.push_back(*it);
00275 }
00276 pose_array_.poses.push_back(final_pose);
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294 output_marker_publisher_.publish(Marker_msg_);
00295 output_pointcloud_publisher_.publish(*cloud_cluster_right);
00296 poses_publisher_.publish(pose_array_);
00297 data_processed_ = true;
00298 }
00299
00300
00301 bool ZyonzFindLeafProbingPointsAlgNode::get_pose_arrayCallback(zyonz_msgs::GetPoseArray::Request &req, zyonz_msgs::GetPoseArray::Response &res)
00302 {
00303 ROS_INFO("ZyonzFindLeafProbingPointsAlgNode::get_pose_arrayCallback: New Request Received!");
00304
00305
00306
00307
00308
00309 if(data_processed_)
00310 {
00311 ROS_INFO("ZyonzFindLeafProbingPointsAlgNode::get_pose_arrayCallback: Processing New Request!");
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325 res.data = pose_array_;
00326
00327 }
00328 else
00329 {
00330 ROS_INFO("ZyonzFindLeafProbingPointsAlgNode::get_pose_arrayCallback: ERROR: alg has no data to request yet.");
00331 }
00332
00333
00334
00335
00336
00337 return true;
00338 }
00339
00340
00341
00342
00343 void ZyonzFindLeafProbingPointsAlgNode::node_config_update(Config &config, uint32_t level)
00344 {
00345 this->alg_.lock();
00346
00347 this->alg_.unlock();
00348 }
00349
00350 void ZyonzFindLeafProbingPointsAlgNode::addNodeDiagnostics(void)
00351 {
00352 }
00353
00354
00355 int main(int argc,char *argv[])
00356 {
00357 return algorithm_base::main<ZyonzFindLeafProbingPointsAlgNode>(argc, argv, "zyonz_find_leaf_probing_points_alg_node");
00358 }