26 #include <sensor_msgs/PointCloud2.h> 27 #include <pcl_msgs/PointIndices.h> 28 #include <pcl_msgs/ModelCoefficients.h> 33 #include <pcl/ModelCoefficients.h> 34 #include <pcl/sample_consensus/method_types.h> 35 #include <pcl/sample_consensus/model_types.h> 36 #include <pcl/sample_consensus/sac_model_plane.h> 37 #include <pcl/sample_consensus/sac_model_line.h> 38 #include <pcl/segmentation/sac_segmentation.h> 39 #include <pcl/segmentation/extract_clusters.h> 40 #include <pcl/filters/extract_indices.h> 41 #include <dynamic_reconfigure/server.h> 43 #include <velo2cam_calibration/CameraConfig.h> 45 #include <velo2cam_calibration/ClusterCentroids.h> 86 sensor_msgs::PointCloud2 ros_cloud;
93 const pcl_msgs::ModelCoefficients::ConstPtr& cam_plane_coeffs){
101 pcl::PointCloud<pcl::PointXYZ>::Ptr cam_cloud (
new pcl::PointCloud<pcl::PointXYZ> ());
108 ROS_WARN(
"[Camera] Estimated plane is not valid.");
113 Eigen::VectorXf coefficients_v(4);
114 coefficients_v(0) = cam_plane_coeffs->values[0];
115 coefficients_v(1) = cam_plane_coeffs->values[1];
116 coefficients_v(2) = cam_plane_coeffs->values[2];
117 coefficients_v(3) = cam_plane_coeffs->values[3];
119 pcl::PointCloud<pcl::PointXYZ>::Ptr cam_plane_cloud (
new pcl::PointCloud<pcl::PointXYZ> ());
120 pcl::SampleConsensusModelPlane<pcl::PointXYZ>::Ptr dit (
new pcl::SampleConsensusModelPlane<pcl::PointXYZ> (cam_cloud));
121 std::vector<int> plane_inliers;
123 pcl::copyPointCloud<pcl::PointXYZ>(*cam_cloud, plane_inliers, *cam_plane_cloud);
126 PointCloud2 plane_edges_ros;
128 plane_edges_ros.header = camera_cloud->header;
129 plane_edges_pub.
publish(plane_edges_ros);
133 pcl::PointCloud<pcl::PointXYZ>::Ptr temp_line_cloud(
new pcl::PointCloud<pcl::PointXYZ>);
134 pcl::PointCloud<pcl::PointXYZ>::Ptr temp_cloud(
new pcl::PointCloud<pcl::PointXYZ>);
135 pcl::ModelCoefficients::Ptr coefficients (
new pcl::ModelCoefficients);
136 pcl::PointIndices::Ptr inliers (
new pcl::PointIndices);
137 pcl::SACSegmentation<pcl::PointXYZ> lineseg;
138 pcl::ExtractIndices<pcl::PointXYZ> extract;
139 std::vector<pcl::ModelCoefficients> out_lines;
141 lineseg.setModelType (pcl::SACMODEL_LINE);
143 lineseg.setMethodType (pcl::SAC_RANSAC);
144 lineseg.setOptimizeCoefficients (
true);
145 lineseg.setMaxIterations(1000);
147 pcl::copyPointCloud<pcl::PointXYZ>(*cam_plane_cloud, *temp_line_cloud);
149 float first_line_x = -1.0, first_line_y = -1.0;
153 lineseg.setInputCloud (temp_line_cloud);
154 lineseg.segment (*inliers, *coefficients);
155 if (inliers->indices.size () == 0)
157 if (
DEBUG)
ROS_INFO(
"Could not estimate a line model for the given dataset.");
161 last_inliers = inliers->indices.size ();
168 extract.setInputCloud (temp_line_cloud);
169 extract.setIndices (inliers);
172 extract.setNegative (
true);
173 extract.filter(*temp_cloud);
174 temp_line_cloud.swap(temp_cloud);
184 if (first_line_x<0.0) first_line_x = coefficients->values[0];
190 if (first_line_y<0.0) first_line_y = coefficients->values[1];
197 if(
DEBUG)
ROS_INFO(
"[Camera] Removed line: %d inliers / orientation: %f %f %f",
198 last_inliers, coefficients->values[3], coefficients->values[4],
199 coefficients->values[5]);
201 out_lines.push_back(*coefficients);
205 pcl::PointCloud<pcl::PointXYZ>::Ptr cam_plane_wol_cloud (
new pcl::PointCloud<pcl::PointXYZ> ());
208 for (vector<pcl::ModelCoefficients>::iterator it=out_lines.begin(); it<out_lines.end(); ++it){
210 pcl::PointIndices::Ptr line_ind (
new pcl::PointIndices);
211 pcl::SampleConsensusModelLine<pcl::PointXYZ>::Ptr dil (
new pcl::SampleConsensusModelLine<pcl::PointXYZ> (cam_plane_cloud));
212 Eigen::VectorXf coefficients_l(6);
213 for(
int j=0; j<6; j++){
214 coefficients_l(j) = it->values[j];
216 std::vector<int> line_inliers;
219 line_ind->indices.resize(line_inliers.size());
221 std::copy(line_inliers.begin(), line_inliers.end(), line_ind->indices.begin());
224 extract.setInputCloud (cam_plane_cloud);
225 extract.setIndices (line_ind);
226 extract.setNegative (
true);
227 extract.filter (*cam_plane_wol_cloud);
229 cam_plane_wol_cloud.swap(cam_plane_cloud);
232 PointCloud2 circles_ros;
234 circles_ros.header = camera_cloud->header;
235 circles_pub.
publish(circles_ros);
238 pcl::PointCloud<pcl::PointXYZ>::Ptr xy_cloud(
new pcl::PointCloud<pcl::PointXYZ>);
239 Eigen::Vector3f xy_plane_normal_vector, floor_plane_normal_vector;
240 xy_plane_normal_vector[0] = 0.0;
241 xy_plane_normal_vector[1] = 0.0;
242 xy_plane_normal_vector[2] = -1.0;
244 floor_plane_normal_vector[0] = cam_plane_coeffs->values[0];
245 floor_plane_normal_vector[1] = cam_plane_coeffs->values[1];
246 floor_plane_normal_vector[2] = cam_plane_coeffs->values[2];
248 std::vector<int> indices;
249 pcl::removeNaNFromPointCloud (*cam_plane_cloud, *cam_plane_cloud, indices);
251 Eigen::Affine3f rotation =
getRotationMatrix(floor_plane_normal_vector, xy_plane_normal_vector);
252 pcl::transformPointCloud(*cam_plane_cloud, *xy_cloud, rotation);
254 pcl::PointCloud<pcl::PointXYZ>::Ptr aux_cloud(
new pcl::PointCloud<pcl::PointXYZ>);
255 pcl::PointXYZ aux_point;
258 aux_point.z = (-coefficients_v(3)/coefficients_v(2));
259 aux_cloud->push_back(aux_point);
261 pcl::PointCloud<pcl::PointXYZ>::Ptr auxrotated_cloud(
new pcl::PointCloud<pcl::PointXYZ>);
262 pcl::transformPointCloud(*aux_cloud, *auxrotated_cloud, rotation);
264 sensor_msgs::PointCloud2 ros_auxpoint;
266 ros_auxpoint.header = camera_cloud->header;
267 auxpoint_pub.
publish(ros_auxpoint);
269 double zcoord_xyplane = auxrotated_cloud->at(0).z;
272 for (pcl::PointCloud<pcl::PointXYZ>::iterator pt = xy_cloud->points.begin();
273 pt < xy_cloud->points.end(); ++pt){
274 pt->z = zcoord_xyplane;
277 PointCloud2 xy_pattern_ros;
279 xy_pattern_ros.header = camera_cloud->header;
280 xy_pattern_pub.
publish(xy_pattern_ros);
283 pcl::SACSegmentation<pcl::PointXYZ> seg;
285 seg.setModelType (pcl::SACMODEL_CIRCLE2D);
287 seg.setMethodType (pcl::SAC_RANSAC);
288 seg.setOptimizeCoefficients (
true);
289 seg.setMaxIterations(1000);
290 seg.setRadiusLimits(0.11,0.13);
292 pcl::PointCloud<pcl::PointXYZ>::Ptr circle_cloud(
new pcl::PointCloud<pcl::PointXYZ>);
294 std::vector< std::vector<float> > found_centers;
299 seg.setInputCloud (xy_cloud);
300 seg.segment (*inliers, *coefficients);
301 if (inliers->indices.size () == 0)
303 ROS_WARN (
"[Camera] Could not estimate a circle model for the given dataset.");
306 if(
DEBUG)
ROS_INFO (
"[Camera] Found circle: %lu inliers", inliers->indices.size ());
310 extract.setInputCloud (xy_cloud);
311 extract.setIndices (inliers);
312 extract.setNegative (
false);
313 extract.filter (*circle_cloud);
316 pcl::PointXYZ center;
317 center.x = *coefficients->values.begin();
318 center.y = *(coefficients->values.begin()+1);
319 for(std::vector<std::vector <float> >::iterator it = found_centers.begin(); it != found_centers.end(); ++it) {
320 if (
sqrt(
pow(fabs((*it)[0]-center.x),2) +
pow(fabs((*it)[1]-center.y),2))<0.25){
325 center.z = zcoord_xyplane;
328 std::vector<float> found_center;
329 found_center.push_back(center.x);
330 found_center.push_back(center.y);
331 found_center.push_back(center.z);
332 found_centers.push_back(found_center);
336 extract.setNegative (
true);
337 extract.filter(*temp_cloud);
338 xy_cloud.swap(temp_cloud);
340 PointCloud2 no_circles_ros;
342 no_circles_ros.header = camera_cloud->header;
343 no_circles_pub.
publish(no_circles_ros);
345 }
while(found_centers.size() < 4 && valid);
348 ROS_WARN(
"Not enough centers: %ld", found_centers.size());
351 for (std::vector<std::vector<float> >::iterator it = found_centers.begin(); it < found_centers.end(); ++it){
352 pcl::PointXYZ center;
355 center.z = (*it)[2];;
356 pcl::PointXYZ center_rotated_back = pcl::transformPoint(center, rotation.inverse());
357 center_rotated_back.z = (-cam_plane_coeffs->values[0]*center_rotated_back.x - cam_plane_coeffs->values[1]*center_rotated_back.y - cam_plane_coeffs->values[3])/cam_plane_coeffs->values[2];
364 cum_ros.header = camera_cloud->header;
365 cumulative_pub.
publish(cum_ros);
367 pcl_msgs::PointIndices p_ind;
370 p_ind.header = camera_cloud->header;
372 pcl_msgs::ModelCoefficients m_coeff;
375 m_coeff.header = camera_cloud->header;
382 ROS_INFO(
"[Camera] %d/%d frames: %ld pts in cloud",
384 pcl::PointCloud<pcl::PointXYZ>::Ptr final_cloud(
new pcl::PointCloud<pcl::PointXYZ>);
387 if (final_cloud->points.size()>4){
391 if (final_cloud->points.size()==4){
393 sensor_msgs::PointCloud2 final_ros;
395 final_ros.header = camera_cloud->header;
397 velo2cam_calibration::ClusterCentroids to_send;
398 to_send.header = camera_cloud->header;
401 to_send.cloud = final_ros;
414 int main(
int argc,
char **argv){
421 camera_cloud_sub_.
subscribe(nh_,
"cloud2", 1);
422 cam_plane_coeffs_sub_.
subscribe(nh_,
"cam_plane_coeffs", 1);
424 inliers_pub = nh_.
advertise<pcl_msgs::PointIndices> (
"inliers", 1);
425 coeff_pub = nh_.
advertise<pcl_msgs::ModelCoefficients> (
"model", 1);
426 plane_edges_pub = nh_.
advertise<PointCloud2> (
"plane_edges_cloud", 1);
427 circles_pub = nh_.
advertise<PointCloud2> (
"circles_cloud", 1);
428 xy_pattern_pub = nh_.
advertise<PointCloud2> (
"xy_pattern", 1);
429 no_circles_pub = nh_.
advertise<PointCloud2> (
"no_circles", 1);
430 cumulative_pub = nh_.
advertise<PointCloud2> (
"cumulative_cloud", 1);
431 final_pub = nh_.
advertise<velo2cam_calibration::ClusterCentroids> (
"centers_cloud", 1);
432 transf_pub = nh_.
advertise<PointCloud2> (
"transf_cam", 1);
433 auxpoint_pub= nh_.
advertise<PointCloud2> (
"aux_point", 1);
435 cumulative_cloud = pcl::PointCloud<pcl::PointXYZ>::Ptr(
new pcl::PointCloud<pcl::PointXYZ>);
451 dynamic_reconfigure::Server<velo2cam_calibration::CameraConfig> server;
452 dynamic_reconfigure::Server<velo2cam_calibration::CameraConfig>::CallbackType
f;
454 server.setCallback(f);
ros::Publisher occluded_edges_pub
pcl::PointCloud< pcl::PointXYZ >::Ptr camera_cloud
ros::Publisher inliers_pub
void publish(const boost::shared_ptr< M > &message) const
image_transport::Publisher pub
ros::Publisher circles_pub
ros::Publisher plane_edges_pub
void param_callback(velo2cam_calibration::CameraConfig &config, uint32_t level)
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
ros::Publisher no_circles_pub
void fromROSMsg(const sensor_msgs::PointCloud2 &cloud, pcl::PointCloud< T > &pcl_cloud)
double min_distance_between_borders_y_
void callback(const PointCloud2::ConstPtr &camera_cloud, const pcl_msgs::ModelCoefficients::ConstPtr &cam_plane_coeffs)
ROSCPP_DECL void spin(Spinner &spinner)
ros::Publisher high_curvature_edges_pub
double plane_distance_inliers_
Connection registerCallback(C &callback)
ros::Publisher occluding_edges_pub
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
double min_plane_normal_z_
ros::Publisher boundary_edges_pub
ros::Publisher cumulative_pub
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
INLINE Rall1d< T, V, S > sqrt(const Rall1d< T, V, S > &arg)
Eigen::Affine3f getRotationMatrix(Eigen::Vector3f source, Eigen::Vector3f target)
double min_distance_between_borders_x_
void getCenterClusters(pcl::PointCloud< pcl::PointXYZ >::Ptr cloud_in, pcl::PointCloud< pcl::PointXYZ >::Ptr centers_cloud, double cluster_tolerance=0.10, int min_cluster_size=15, int max_cluster_size=200, bool verbosity=true)
ros::Publisher rgb_edges_pub
ros::Publisher xy_pattern_pub
INLINE Rall1d< T, V, S > pow(const Rall1d< T, V, S > &arg, double m)
double border_distance_inliers_
void subscribe(ros::NodeHandle &nh, const std::string &topic, uint32_t queue_size, const ros::TransportHints &transport_hints=ros::TransportHints(), ros::CallbackQueueInterface *callback_queue=0)
int main(int argc, char **argv)
void toROSMsg(const sensor_msgs::PointCloud2 &cloud, sensor_msgs::Image &image)
pcl::PointCloud< pcl::PointXYZ >::Ptr cumulative_cloud
void moveFromPCL(pcl::PCLImage &pcl_image, sensor_msgs::Image &image)
ros::Publisher transf_pub
ros::Publisher auxpoint_pub
void publish_cloud(pcl::PointCloud< pcl::PointXYZ >::Ptr input_cloud, ros::Publisher pub)