@@ -24,11 +24,17 @@ target_link_libraries(ground_plane_segmentation ${catkin_LIBRARIES})
2424#include < pcl_ros/filters/voxel_grid.h>
2525#include < pcl_ros/filters/extract_indices.h>
2626#include < pcl_conversions/pcl_conversions.h>
27+ #include < pcl/common/centroid.h>
28+ #include < tf/tf.h>
29+ #include < tf/transform_broadcaster.h>
2730
2831// Publishers
2932ros::Publisher pcl_pub;
3033ros::Publisher pcl_pub_top;
3134ros::Publisher coef_pub;
35+ ros::Publisher normal_x_pub;
36+ ros::Publisher normal_y_pub;
37+ ros::Publisher normal_z_pub;
3238
3339// Topics
3440bool invert;
@@ -41,16 +47,53 @@ std::string coefficients_topic;
4147// Debug flag
4248bool debug = false ;
4349
50+ struct planeSegementationOutput
51+ {
52+ pcl_msgs::ModelCoefficients plane_normal;
53+ pcl::PCLPointCloud2::Ptr leftover_pc;
54+ pcl::PCLPointCloud2::Ptr plane_pc;
55+ Eigen::Vector4f midpoint;
56+ int num_of_points;
57+ };
58+
59+
4460pcl::ModelCoefficients::Ptr coefficients (new pcl::ModelCoefficients);
4561
62+ void convert_icp_eigen_to_tf (Eigen::Matrix4f Tm)
63+ {
64+ // Set translation
65+ tf::Vector3 origin;
66+ origin.setValue (Tm (0 , 3 ), Tm (1 , 3 ), Tm (2 , 3 ));
67+
68+ // Set rotation
69+ tf::Quaternion quaternion;
70+ tf::Matrix3x3 rotation_matrix;
71+ rotation_matrix.setValue (Tm (0 , 0 ), Tm (0 , 1 ), Tm (0 , 2 ),
72+ Tm (1 , 0 ), Tm (1 , 1 ), Tm (1 , 2 ),
73+ Tm (2 , 0 ), Tm (2 , 1 ), Tm (2 , 2 ));
74+ rotation_matrix.getRotation (quaternion);
75+
76+ // Make tf transform message
77+ tf::Transform transform;
78+ transform.setOrigin (origin);
79+ transform.setRotation (quaternion);
80+
81+ // Broadcast the transforms
82+ tf::TransformBroadcaster br;
83+ std::cerr<<" Publishing TF" <<std::endl;
84+ br.sendTransform (tf::StampedTransform (transform, ros::Time::now (), " camera_depth_frame" , " cuboid_frame" ));
85+ }
86+
4687void coefficients_callback (const pcl_msgs::ModelCoefficients& input)
4788{
4889 pcl_conversions::toPCL (input, *coefficients);
4990}
5091
51- std::pair<pcl_msgs::ModelCoefficients, pcl::PCLPointCloud2::Ptr> getNormal (pcl::PCLPointCloud2::Ptr cloud_ptr,
92+ planeSegementationOutput getNormal (pcl::PCLPointCloud2::Ptr cloud_ptr,
5293pcl::SacModel model, Eigen::Vector3f plane_normal, bool invert_local)
5394{
95+ planeSegementationOutput plane;
96+
5497 // Setup ground plane segmentation
5598 // pcl::ModelCoefficients::Ptr coefficients(new pcl::ModelCoefficients);
5699 pcl::PointIndices::Ptr inliers (new pcl::PointIndices);
@@ -82,13 +125,33 @@ pcl::SacModel model, Eigen::Vector3f plane_normal, bool invert_local)
82125 pcl::ExtractIndices<pcl::PCLPointCloud2> extract;
83126 extract.setInputCloud (cloud_ptr);
84127 extract.setIndices (inliers);
85- extract.setNegative (invert_local);
128+ extract.setNegative (! invert_local);
86129 extract.filter (*plane_cloud_ptr);
87130
131+ pcl::PCLPointCloud2::Ptr not_plane_cloud_ptr (new pcl::PCLPointCloud2);
132+ pcl::ExtractIndices<pcl::PCLPointCloud2> extract_;
133+ extract_.setInputCloud (cloud_ptr);
134+ extract_.setIndices (inliers);
135+ extract_.setNegative (invert_local);
136+ extract_.filter (*not_plane_cloud_ptr);
137+
138+ // Convert to the templated PointCloud
139+ pcl::PointCloud<pcl::PointXYZ>::Ptr plane_xyz_cloud_ptr (new pcl::PointCloud<pcl::PointXYZ>);
140+ pcl::fromPCLPointCloud2 (*plane_cloud_ptr, *plane_xyz_cloud_ptr);
141+
88142 std::pair<pcl_msgs::ModelCoefficients, pcl::PCLPointCloud2::Ptr> plane_info;
89143 plane_info = make_pair (ros_coefficients, plane_cloud_ptr);
90144
91- return plane_info;
145+ Eigen::Vector4f centroid;
146+ pcl::compute3DCentroid (*plane_xyz_cloud_ptr, centroid);
147+
148+ plane.plane_normal = ros_coefficients;
149+ plane.leftover_pc = not_plane_cloud_ptr;
150+ plane.plane_pc = plane_cloud_ptr;
151+ plane.midpoint = centroid;
152+ plane.num_of_points = (int ) plane_xyz_cloud_ptr->points .size ();
153+
154+ return plane;
92155}
93156
94157void callback (const sensor_msgs::PointCloud2ConstPtr& input)
@@ -103,33 +166,57 @@ void callback(const sensor_msgs::PointCloud2ConstPtr& input)
103166 pcl_conversions::toPCL (*input, *cloud_ptr);
104167 if (debug) std::cerr << " PointCloud before filtering: " << cloud_ptr->width << " " << cloud_ptr->height << " data points." << std::endl;
105168
106- std::pair<pcl_msgs::ModelCoefficients, pcl::PCLPointCloud2::Ptr> plane1;
107- pcl::PCLPointCloud2::Ptr plane_cloud_ptr_1 (new pcl::PCLPointCloud2);
108- plane1 = getNormal (cloud_ptr, pcl::SACMODEL_PERPENDICULAR_PLANE, plane_normal, invert);
109- plane_cloud_ptr_1 = plane1.second ;
110- Eigen::Vector3f normal_z (plane1.first .values [0 ],plane1.first .values [1 ],plane1.first .values [2 ]);
111-
112- std::pair<pcl_msgs::ModelCoefficients, pcl::PCLPointCloud2::Ptr> plane2;
113- pcl::PCLPointCloud2::Ptr plane_cloud_ptr_2 (new pcl::PCLPointCloud2);
114- plane2 = getNormal (plane_cloud_ptr_1, pcl::SACMODEL_PARALLEL_PLANE, plane_normal, invert);
115- plane_cloud_ptr_2 = plane2.second ;
116- Eigen::Vector3f normal_y (plane2.first .values [0 ],plane2.first .values [1 ],plane2.first .values [2 ]);
117-
118- std::pair<pcl_msgs::ModelCoefficients, pcl::PCLPointCloud2::Ptr> plane3;
119- pcl::PCLPointCloud2::Ptr plane_cloud_ptr_3 (new pcl::PCLPointCloud2);
120- plane3 = getNormal (plane_cloud_ptr_2, pcl::SACMODEL_PARALLEL_PLANE, plane_normal, !invert);
121- plane_cloud_ptr_3 = plane3.second ;
122- Eigen::Vector3f normal_x (plane3.first .values [0 ],plane3.first .values [1 ],plane3.first .values [2 ]);
169+ planeSegementationOutput planes[3 ];
170+ Eigen::Vector3f normals[3 ];
171+
172+ for (int i = 0 ; i < 3 ; i++)
173+ {
174+ if (i==0 )
175+ planes[i] = getNormal (cloud_ptr, pcl::SACMODEL_PERPENDICULAR_PLANE, plane_normal, invert);
176+ else
177+ planes[i] = getNormal (cloud_ptr, pcl::SACMODEL_PARALLEL_PLANE, plane_normal, invert);
178+ cloud_ptr = planes[i].leftover_pc ;
179+ normals[i] << planes[i].plane_normal .values [0 ], planes[i].plane_normal .values [1 ], planes[i].plane_normal .values [2 ];
180+ }
123181
182+ for (int i = 0 ; i< 3 ; i++)
183+ {
184+ for (int j = i; j< 3 ; j++)
185+ {
186+ if (planes[i].num_of_points < planes[j].num_of_points )
187+ {
188+ planeSegementationOutput temp_plane = planes[i];
189+ planes[i] = planes[j];
190+ planes[j] = temp_plane;
191+ }
192+ }
193+ }
194+
195+ if (normals[2 ].dot (normals[1 ].cross (normals[0 ])) < 0 )
196+ {
197+ normals[2 ] = -normals[2 ];
198+ }
199+
200+ // Projection of midpoint of y,z on z.
201+ float proj = normals[0 ].dot (planes[0 ].midpoint .head <3 >() - planes[1 ].midpoint .head <3 >());
202+ Eigen::Vector3f centroid = planes[0 ].midpoint .head <3 >() - (proj*normals[0 ]);
203+
204+ Eigen::Matrix4f Rt;
205+ Rt << normals[2 ](0 ), normals[1 ](0 ), normals[0 ](0 ), centroid (0 ),
206+ normals[2 ](1 ), normals[1 ](1 ), normals[0 ](1 ), centroid (1 ),
207+ normals[2 ](2 ), normals[1 ](2 ), normals[0 ](2 ), centroid (2 ),
208+ 0 ,0 ,0 ,1 ;
124209
125- std::cerr << " X Y Dot product: " << normal_x.dot (normal_y) << std::endl;
126- std::cerr << " Y Z Dot product: " << normal_y.dot (normal_z) << std::endl;
127- std::cerr << " Z X Dot product: " << normal_z.dot (normal_x) << std::endl;
210+ convert_icp_eigen_to_tf (Rt);
128211
129212 // Convert to ROS data type
130213 sensor_msgs::PointCloud2 output;
131- pcl_conversions::fromPCL (*plane_cloud_ptr_3 , output);
214+ pcl_conversions::fromPCL (*cloud_ptr , output);
132215 pcl_pub.publish (output);
216+
217+ normal_x_pub.publish (planes[2 ].plane_normal );
218+ normal_y_pub.publish (planes[1 ].plane_normal );
219+ normal_z_pub.publish (planes[0 ].plane_normal );
133220}
134221
135222int main (int argc, char ** argv)
@@ -170,6 +257,9 @@ int main(int argc, char** argv)
170257 pcl_pub = nh.advertise <sensor_msgs::PointCloud2>(output_topic, 1 );
171258 pcl_pub_top = nh.advertise <sensor_msgs::PointCloud2>(output_topic, 1 );
172259 coef_pub = nh.advertise <pcl_msgs::ModelCoefficients>(coefficients_topic, 1 );
260+ normal_x_pub = nh.advertise <pcl_msgs::ModelCoefficients>(" /surface_segmentation/normal_x_coefficients" , 1 );
261+ normal_y_pub = nh.advertise <pcl_msgs::ModelCoefficients>(" /surface_segmentation/normal_y_coefficients" , 1 );
262+ normal_z_pub = nh.advertise <pcl_msgs::ModelCoefficients>(" /surface_segmentation/normal_z_coefficients" , 1 );
173263
174264 // Spin
175265 ros::spin ();
0 commit comments