Skip to content

Commit 75b70d1

Browse files
committed
Adding surface normals being published
1 parent 9fcb9b5 commit 75b70d1

File tree

1 file changed

+114
-24
lines changed

1 file changed

+114
-24
lines changed

cuboid_detection/src/surface_normal_estimation.cpp

Lines changed: 114 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -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
2932
ros::Publisher pcl_pub;
3033
ros::Publisher pcl_pub_top;
3134
ros::Publisher coef_pub;
35+
ros::Publisher normal_x_pub;
36+
ros::Publisher normal_y_pub;
37+
ros::Publisher normal_z_pub;
3238

3339
// Topics
3440
bool invert;
@@ -41,16 +47,53 @@ std::string coefficients_topic;
4147
// Debug flag
4248
bool 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+
4460
pcl::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+
4687
void 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,
5293
pcl::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

94157
void 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

135222
int 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

Comments
 (0)