parking_detection.cpp
Go to the documentation of this file.
1 /**************************************************************************************************
2  Software License Agreement (BSD License)
3 
4  Copyright (c) 2011-2013, LAR toolkit developers - University of Aveiro - http://lars.mec.ua.pt
5  All rights reserved.
6 
7  Redistribution and use in source and binary forms, with or without modification, are permitted
8  provided that the following conditions are met:
9 
10  *Redistributions of source code must retain the above copyright notice, this list of
11  conditions and the following disclaimer.
12  *Redistributions in binary form must reproduce the above copyright notice, this list of
13  conditions and the following disclaimer in the documentation and/or other materials provided
14  with the distribution.
15  *Neither the name of the University of Aveiro nor the names of its contributors may be used to
16  endorse or promote products derived from this software without specific prior written permission.
17 
18  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
19  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
21  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
24  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 ***************************************************************************************************/
34 #include <stdio.h>
35 #include <ros/ros.h>
36 #include <visualization_msgs/Marker.h>
37 #include <sensor_msgs/LaserScan.h>
38 #include <sensor_msgs/PointCloud2.h>
39 #include <tf/transform_listener.h>
40 #include <pcl_ros/transforms.h>
41 #include <pcl/conversions.h>
42 #include <pcl/point_cloud.h>
43 #include <pcl/point_types.h>
44 #include <pcl/segmentation/extract_polygonal_prism_data.h>
45 #include <pcl/filters/extract_indices.h>
46 #include <pcl/filters/project_inliers.h>
47 #include <pcl/filters/voxel_grid.h>
48 #include <points_from_volume/points_from_volume.h>
49 #include <trajectory_planner/coordinates.h>
50 
51 // Defines
52 #define PFLN printf("FILE %s LINE %d\n",__FILE__, __LINE__);
53 
54 // Namespaces
55 using namespace std;
56 
57 // Global vars
58 ros::NodeHandle* p_n;
60 tf::TransformListener *p_listener;
61 pcl::PointCloud<pcl::PointXYZ> convex_hull1, convex_hull2, convex_hull3;
63 points_from_volume<pcl::PointXYZ> pfv, pfv2, pfv3, pfv4;
64 trajectory_planner::coordinates message;
65 
66 double spot_length=1.5; // Length of vehicle (parking spot) was 1.2
67 double spot_wide=0.45; // Wide
68 double spot_high=0.6; // High
69 double spot_distance=0.125; // distance from (between) vehicles -> this must be bigger (0.225 i guess)
70 double SpotDetected=0;
71 
77 void cloud_cb (const sensor_msgs::PointCloud2ConstPtr & pcmsg_in)
78 {
79  // STEP 1: Create the point_cloud input
80  pcl::PointCloud<pcl::PointXYZ> pc_in;
81  pcl::fromROSMsg(*pcmsg_in,pc_in);
82 
83 
84  //STEP 2: Query for the transwformation to use
85  tf::StampedTransform transform;
86  try
87  {
88  p_listener->lookupTransform(pcmsg_in->header.frame_id, "/vehicle_odometry", ros::Time(0), transform);
89  }
90  catch (tf::TransformException ex)
91  {
92  ROS_ERROR("%s",ex.what());
93  }
94 
95 
96  //STEP3: transform pc_in using the queried transform
97  pcl::PointCloud<pcl::PointXYZ> pc_transformed;
98  pcl::PointCloud<pcl::PointXYZ> pc_ahead, pc_spot, pc_behind, pc_ground;
99  pcl_ros::transformPointCloud(pc_in,pc_transformed, transform.inverse());
100  pc_transformed.header.frame_id = "/vehicle_odometry";
101 
102 
103  // STEP 4: Aplying the ConvexHull class
104  pfv.convexhull_function(pc_transformed, 0.0, -0.6, false);
105  pc_ahead=pfv.get_pc_in_volume();
106  pc_ahead.header.frame_id = "/vehicle_odometry";
107 
108  pfv2.convexhull_function(pc_transformed, 0.0, -0.6, false);
109  pc_spot=pfv2.get_pc_in_volume();
110  pc_spot.header.frame_id = "/vehicle_odometry";
111 
112  pfv3.convexhull_function(pc_transformed, 0.0, -0.6, false);
113  pc_behind=pfv3.get_pc_in_volume();
114  pc_behind.header.frame_id = "/vehicle_odometry";
115 
116  pfv4.convexhull_function(pc_transformed, 0.07, 0.0, false);
117  pc_ground=pfv4.get_pc_in_volume();
118  pc_ground.header.frame_id = "/vehicle_odometry";
119 
120 
121  // STEP 5: Convert to ROSMsg
122  sensor_msgs::PointCloud2 pcmsg_out;
123  pcl::toROSMsg(pc_ahead, pcmsg_out);
124 
125  sensor_msgs::PointCloud2 pcmsg_out2;
126  pcl::toROSMsg(pc_spot, pcmsg_out2);
127 
128  sensor_msgs::PointCloud2 pcmsg_out3;
129  pcl::toROSMsg(pc_behind, pcmsg_out3);
130 
131  sensor_msgs::PointCloud2 pcmsg_out4;
132  pcl::toROSMsg(pc_ground, pcmsg_out4);
133 
134 
135  // STEP 6: Markers
136  // Marker car
137  visualization_msgs::Marker marker_car;
138  marker_car.header.frame_id = "/vehicle_odometry"; // Frame name
139  marker_car.header.stamp = ros::Time();
140  marker_car.ns = "my_namespace";
141  marker_car.id = 0;
142  marker_car.type = visualization_msgs::Marker::CUBE; // Marker type
143  marker_car.action = visualization_msgs::Marker::ADD;
144  marker_car.scale.x = 0.8;
145  marker_car.scale.y = spot_wide;
146  marker_car.scale.z = spot_high;
147  marker_car.pose.position.x = 0.8/2; // Position
148  marker_car.pose.position.y = 0;
149  marker_car.pose.position.z = spot_high/2;
150  marker_car.pose.orientation.x = 0.0; // Orientation related to the frame
151  marker_car.pose.orientation.y = 0.0;
152  marker_car.pose.orientation.z = 0.0;
153  marker_car.pose.orientation.w = 1.0;
154  marker_car.color.a = 0.2;
155  marker_car.color.r = 0.0;
156  marker_car.color.g = 0.0;
157  marker_car.color.b = 1.0;
158 
159  int condition=0;
160  // Marker 1
161  visualization_msgs::Marker marker;
162  marker.header.frame_id = "/vehicle_odometry"; // Frame name
163  marker.header.stamp = ros::Time();
164  marker.ns = "my_namespace";
165  marker.id = 0;
166  marker.type = visualization_msgs::Marker::CUBE; // Marker type
167  marker.action = visualization_msgs::Marker::ADD;
168  marker.scale.x = spot_length;
169  marker.scale.y = spot_wide;
170  marker.scale.z = spot_high;
171  marker.pose.position.x = spot_length/2; // Position
172  marker.pose.position.y = spot_wide + spot_distance;
173  marker.pose.position.z = spot_high/2;
174  marker.pose.orientation.x = 0.0; // Orientation related to the frame
175  marker.pose.orientation.y = 0.0;
176  marker.pose.orientation.z = 0.0;
177  marker.pose.orientation.w = 1.0;
178  marker.color.a = 0.3;
179  if(pc_ahead.points.size()<5)
180  {
181  marker.color.r = 0.0;
182  marker.color.g = 1.0;
183  marker.color.b = 0.0;
184  condition=condition+0.5;
185  }
186  else
187  {
188  marker.color.r = 1.0;
189  marker.color.g = 1.0;
190  marker.color.b = 0.0;
191  }
192 
193  // Marker 2
194  visualization_msgs::Marker marker2;
195  marker2.header.frame_id = "/vehicle_odometry"; // Frame name
196  marker2.header.stamp = ros::Time();
197  marker2.ns = "my_namespace";
198  marker2.id = 0;
199  marker2.type = visualization_msgs::Marker::CUBE; // Marker type
200  marker2.action = visualization_msgs::Marker::ADD;
201  marker2.scale.x = spot_length;
202  marker2.scale.y = spot_wide;
203  marker2.scale.z = spot_high;
204  marker2.pose.position.x = -spot_length/2; // Position
205  marker2.pose.position.y = spot_wide + spot_distance;
206  marker2.pose.position.z = spot_high/2;
207  marker2.pose.orientation.x = 0.0; // Orientation related to the frame
208  marker2.pose.orientation.y = 0.0;
209  marker2.pose.orientation.z = 0.0;
210  marker2.pose.orientation.w = 1.0;
211  marker2.color.a = 0.3;
212  if(pc_spot.points.size()<5)
213  {
214  marker2.color.r = 0.0;
215  marker2.color.g = 1.0;
216  marker2.color.b = 0.0;
217  condition=condition+1;
218  }
219  else
220  {
221  marker2.color.r = 1.0;
222  marker2.color.g = 0.0;
223  marker2.color.b = 0.0;
224  }
225 
226  // Marker 3
227  visualization_msgs::Marker marker3;
228  marker3.header.frame_id = "/vehicle_odometry"; // Frame name
229  marker3.header.stamp = ros::Time();
230  marker3.ns = "my_namespace";
231  marker3.id = 0;
232  marker3.type = visualization_msgs::Marker::CUBE; // Marker type
233  marker3.action = visualization_msgs::Marker::ADD;
234  marker3.scale.x = spot_length;
235  marker3.scale.y = spot_wide;
236  marker3.scale.z = spot_high;
237  marker3.pose.position.x = -spot_length - spot_length/2; // Position
238  marker3.pose.position.y = spot_wide + spot_distance;
239  marker3.pose.position.z = spot_high/2;
240  marker3.pose.orientation.x = 0.0; // Orientation related to the frame
241  marker3.pose.orientation.y = 0.0;
242  marker3.pose.orientation.z = 0.0;
243  marker3.pose.orientation.w = 1.0;
244  marker3.color.a = 0.3;
245  if(pc_behind.points.size()<5)
246  {
247  marker3.color.r = 1.0;
248  marker3.color.g = 0.0;
249  marker3.color.b = 0.0;
250  }
251  else
252  {
253  marker3.color.r = 0.0;
254  marker3.color.g = 1.0;
255  marker3.color.b = 0.0;
256  condition=condition+1;
257  }
258 
259  // Marker 4
260  visualization_msgs::Marker marker4;
261  marker4.header.frame_id = "/vehicle_odometry"; // Frame name
262  marker4.header.stamp = ros::Time();
263  marker4.ns = "my_namespace";
264  marker4.id = 0;
265  marker4.type = visualization_msgs::Marker::CUBE; // Marker type
266  marker4.action = visualization_msgs::Marker::ADD;
267  marker4.scale.x = spot_length;
268  marker4.scale.y = spot_wide;
269  marker4.scale.z = 0.05;
270  marker4.pose.position.x = - spot_length/2; // Position
271  marker4.pose.position.y = spot_wide + spot_distance;
272  marker4.pose.position.z = -0.025;
273  marker4.pose.orientation.x = 0.0; // Orientation related to the frame
274  marker4.pose.orientation.y = 0.0;
275  marker4.pose.orientation.z = 0.0;
276  marker4.pose.orientation.w = 1.0;
277  marker4.color.a = 0.6;
278  marker4.color.r = 0.4;
279  marker4.color.g = 0.8;
280  marker4.color.b = 0.9;
281  if(pc_ground.points.size()<5)
282  {
283  marker4.color.r = 1.0;
284  marker4.color.g = 0.0;
285  marker4.color.b = 0.0;
286  }
287  else
288  {
289  marker4.color.r = 0.0;
290  marker4.color.g = 1.0;
291  marker4.color.b = 0.0;
292  condition=condition+1;
293  }
294 
295 
296  // STEP 7: Publish markers and PClouds
297  car_pub.publish(marker_car);
298  vis_pub.publish(marker);
299  vis_pub2.publish(marker2);
300  vis_pub3.publish(marker3);
301  vis_pub4.publish(marker4);
302 
303  cloud_pub.publish(pcmsg_out);
304  cloud_pub2.publish(pcmsg_out2);
305  cloud_pub3.publish(pcmsg_out3);
306  cloud_pub4.publish(pcmsg_out4);
307 
308 
309  // STEP 8: Send empty space coordinates
310  double xpos=marker2.pose.position.x;
311  double ypos=marker2.pose.position.y;
312  double zpos=0.0;
313 
314  tf::StampedTransform transform2;
315 
316  try
317  {
318  p_listener->lookupTransform("/vehicle_odometry", "/world", ros::Time(0), transform2);
319  }
320  catch (tf::TransformException ex)
321  {
322  ROS_ERROR("%s",ex.what());
323 // return 0;
324  }
325 
326  pcl::PointCloud<pcl::PointXYZ> pc_spot_coordinate_in;
327  pcl::PointCloud<pcl::PointXYZ> pc_spot_coordinate_out;
328 
329  pcl::PointXYZ pt1;
330  pt1.x = xpos-0.50;
331  pt1.y= ypos+0.14;//cheat
332  pt1.z= zpos;
333  pc_spot_coordinate_in.points.push_back(pt1);
334 
335  pcl_ros::transformPointCloud(pc_spot_coordinate_in,pc_spot_coordinate_out, transform2.inverse());
336  pc_spot_coordinate_out.header.frame_id = "/world";
337 
338  double orix;
339  double oriy;
340  double oriz;
341  double oriw;
342 
343  orix=transform2.getRotation()[0];
344  oriy=transform2.getRotation()[1];
345  oriz=transform2.getRotation()[2];
346  oriw=transform2.getRotation()[3];
347 
348  double thheta=atan2(2*(oriw*oriz+orix*oriy),1-2*(oriy*oriy+oriz*oriz));
349 // cout<<"CENASS "<<orix<<" "<<oriy<<" "<<oriz<<" "<<oriw<<" "<<endl;
350 // cout<<"CENASS "<<thheta<<endl;
351 
352  // ______________________
353  //| |
354  //| Parking condition |
355  //|______________________|
356  if(condition>=3 && SpotDetected==0)
357  {
358 
359  // Send message
360  message.x=(pc_spot_coordinate_out.points[0].x);//-0.3*cos(thehta);
361  message.y=(pc_spot_coordinate_out.points[0].y);//-0.3*sin(thheta);
362  message.theta=-thheta;
363 
364  printf("Parking in: %f %f \n",pc_spot_coordinate_out.points[0].x,pc_spot_coordinate_out.points[0].y);
365 
366  sensor_msgs::PointCloud2 pcmsg_parking_place;
367  pcl::toROSMsg(pc_spot_coordinate_out, pcmsg_parking_place);
368  cloud_pub5.publish(pcmsg_parking_place);
369 
370 
371 
372 
373 
374  Publisher.publish(message);
375  SpotDetected=1;
376 
377  }
378 }
379 
386 int main(int argc, char **argv)
387 {
388  ros::init(argc, argv, "pc_transformer_node");
389  ros::NodeHandle n;
390  tf::TransformListener listener(n,ros::Duration(10));
391  p_listener=&listener;
392  p_n=&n;
393  Publisher = n.advertise<trajectory_planner::coordinates>("/msg_coordinates", 1000);
394 
395  // ______________________
396  //| |
397  //| Markers |
398  //|______________________|
399  car_pub = n.advertise<visualization_msgs::Marker>( "car", 0 );
400  vis_pub = n.advertise<visualization_msgs::Marker>( "parking_ahead", 0 );
401  vis_pub2 = n.advertise<visualization_msgs::Marker>( "parking_spot", 0 );
402  vis_pub3 = n.advertise<visualization_msgs::Marker>( "parking_behind", 0 );
403  vis_pub4 = n.advertise<visualization_msgs::Marker>( "ground", 0 );
404 
405  // ______________________
406  //| |
407  //| ConvexHulls |
408  //|______________________|
409  // ConvexHull 1
410  convex_hull1.header.frame_id="/vehicle_odometry";
411  pcl::PointXYZ pt1;
412  pt1.x = spot_length/2 + spot_length/2; pt1.y= (spot_wide + spot_distance) + spot_wide/2; pt1.z= 0.02;
413  convex_hull1.points.push_back(pt1);
414  pt1.x = spot_length/2 + spot_length/2; pt1.y= (spot_wide + spot_distance) - spot_wide/2; pt1.z= 0.02;
415  convex_hull1.points.push_back(pt1);
416  pt1.x = spot_length/2 - spot_length/2; pt1.y= (spot_wide + spot_distance) - spot_wide/2; pt1.z= 0.02;
417  convex_hull1.points.push_back(pt1);
418  pt1.x = spot_length/2 - spot_length/2; pt1.y= (spot_wide + spot_distance) + spot_wide/2; pt1.z= 0.02;
419  convex_hull1.points.push_back(pt1);
420  pfv.set_convex_hull(convex_hull1);
421 
422  // ConvexHull 2
423  convex_hull2.header.frame_id="/vehicle_odometry";
424  pcl::PointXYZ pt2;
425  pt2.x = spot_length/2 - spot_length/2; pt2.y= (spot_wide + spot_distance) + spot_wide/2; pt2.z= 0.02;
426  convex_hull2.points.push_back(pt2);
427  pt2.x = spot_length/2 - spot_length/2; pt2.y= (spot_wide + spot_distance) - spot_wide/2; pt2.z= 0.02;
428  convex_hull2.points.push_back(pt2);
429  pt2.x = - spot_length; pt2.y= (spot_wide + spot_distance) - spot_wide/2; pt2.z= 0.02;
430  convex_hull2.points.push_back(pt2);
431  pt2.x = - spot_length; pt2.y= (spot_wide + spot_distance) + spot_wide/2; pt2.z= 0.02;
432  convex_hull2.points.push_back(pt2);
433  pfv2.set_convex_hull(convex_hull2);
434 
435  // ConvexHull 3
436  convex_hull3.header.frame_id="/vehicle_odometry";
437  pcl::PointXYZ pt3;
438  pt3.x = - spot_length; pt3.y= (spot_wide + spot_distance) + spot_wide/2; pt3.z= 0.02;
439  convex_hull3.points.push_back(pt3);
440  pt3.x = - spot_length; pt3.y= (spot_wide + spot_distance) - spot_wide/2; pt3.z= 0.02;
441  convex_hull3.points.push_back(pt3);
442  pt3.x = - spot_length - spot_length; pt3.y= (spot_wide + spot_distance) - spot_wide/2; pt3.z= 0.02;
443  convex_hull3.points.push_back(pt3);
444  pt3.x = - spot_length - spot_length; pt3.y= (spot_wide + spot_distance) + spot_wide/2; pt3.z= 0.02;
445  convex_hull3.points.push_back(pt3);
446  pfv3.set_convex_hull(convex_hull3);
447 
448  pfv4.set_convex_hull(convex_hull2);
449 
450  // ______________________
451  //| |
452  //| PointCloud |
453  //|______________________|
454  //Point Cloud publications
455  cloud_pub = n.advertise<sensor_msgs::PointCloud2>("/pc_ahead", 1);
456  cloud_pub2 = n.advertise<sensor_msgs::PointCloud2>("/pc_spot", 1);
457  cloud_pub3 = n.advertise<sensor_msgs::PointCloud2>("/pc_behind", 1);
458  cloud_pub4 = n.advertise<sensor_msgs::PointCloud2>("/pc_ground", 1);
459  cloud_pub5 = n.advertise<sensor_msgs::PointCloud2>("/pc_parking_location", 1);
460 
461  // ______________________
462  //| |
463  //| PCL subscr. |
464  //|______________________|
465  // Creates a ROS subscriber for the input point cloud
466  ros::Subscriber sub = n.subscribe ("/pc_out_pointcloud", 1, cloud_cb);
467 
468  ros::Rate loop_rate(30);
469  ros::spin();
470 }
ros::Publisher car_pub
points_from_volume< pcl::PointXYZ > pfv2
ros::Publisher cloud_pub5
ros::Publisher vis_pub3
pcl::PointCloud< pcl::PointXYZ > convex_hull2
ros::Publisher cloud_pub4
ros::Publisher cloud_pub3
double spot_high
ros::Publisher cloud_pub2
ros::Publisher vis_pub4
ros::Publisher vis_pub2
double spot_length
pcl::PointCloud< pcl::PointXYZ > convex_hull3
ros::Publisher Publisher
ros::Publisher cloud_pub
double SpotDetected
double spot_distance
double spot_wide
ros::NodeHandle * p_n
ros::Publisher vis_pub
points_from_volume< pcl::PointXYZ > pfv4
trajectory_planner::coordinates message
int main(int argc, char **argv)
Main function of the parking detection node.
points_from_volume< pcl::PointXYZ > pfv3
void cloud_cb(const sensor_msgs::PointCloud2ConstPtr &pcmsg_in)
Publishes filtered pcl & extruded pcl.
pcl::PointCloud< pcl::PointXYZ > convex_hull1
points_from_volume< pcl::PointXYZ > pfv
tf::TransformListener * p_listener


parking_detection
Author(s): Joel Pereira
autogenerated on Mon Mar 2 2015 01:32:31