object_detection.cpp
Go to the documentation of this file.
1 #include <ros/ros.h>
2 #include <sensor_msgs/PointCloud2.h>
5 #include <geometry_msgs/TransformStamped.h>
6 #include <pcl_ros/transforms.h>
8 #include <visualization_msgs/Marker.h>
9 #include <visualization_msgs/MarkerArray.h>
10 
11 #include <pcl/point_cloud.h>
12 #include <pcl/point_types.h>
13 #include <pcl/common/common.h>
14 #include <pcl/filters/passthrough.h>
15 #include <pcl/filters/voxel_grid.h>
16 #include <pcl/kdtree/kdtree.h>
17 #include <pcl/segmentation/extract_clusters.h>
18 
21 
22 
23 void convert_to_marker(visualization_msgs::Marker *marker, const int marker_id,
24  const std::string &frame_id,
25  const pcl::PointXYZRGB &min_pt, const pcl::PointXYZRGB &max_pt)
26 {
27  // pcl::Pointの最大最小値をBox型のマーカに変換する
28 
29  marker->header.frame_id = frame_id;
30  marker->header.stamp = ros::Time();
31  marker->ns = "/sciurus17/example";
32  marker->id = marker_id;
33  marker->type = visualization_msgs::Marker::CUBE;
34  marker->action = visualization_msgs::Marker::ADD;
35  marker->lifetime = ros::Duration(0.5);
36 
37  marker->pose.position.x = (max_pt.x + min_pt.x) * 0.5;
38  marker->pose.position.y = (max_pt.y + min_pt.y) * 0.5;
39  marker->pose.position.z = (max_pt.z + min_pt.z) * 0.5;
40  marker->pose.orientation.x = 0.0;
41  marker->pose.orientation.y = 0.0;
42  marker->pose.orientation.z = 0.0;
43  marker->pose.orientation.w = 1.0;
44  marker->scale.x = (max_pt.x - min_pt.x);
45  marker->scale.y = (max_pt.y - min_pt.y);
46  marker->scale.z = (max_pt.z - min_pt.z);
47  marker->color.a = 1.0;
48  marker->color.r = 1.0;
49  marker->color.g = 1.0;
50  marker->color.b = 1.0;
51 }
52 
53 
54 void cloud_cb (const sensor_msgs::PointCloud2ConstPtr& cloud_msg)
55 {
56  const static std::string FRAME_ID = "base_link";
58  static tf::StampedTransform transform;
59  enum COLOR_RGB{
60  RED=0,
61  GREEN,
62  BLUE,
63  COLOR_MAX
64  };
65  const int CLUSTER_MAX = 10;
66  const int CLUSTER_COLOR[CLUSTER_MAX][COLOR_MAX] = {
67  {230, 0, 18},{243, 152, 18}, {255, 251, 0},
68  {143, 195, 31},{0, 153, 68}, {0, 158, 150},
69  {0, 160, 233},{0, 104, 183}, {29, 32, 136},
70  {146, 7, 131}
71  };
72 
73  sensor_msgs::PointCloud2 cloud_transformed;
74 
75  // point cloudの座標を変換
76  // base_linkとカメラ間のTFを取得する
77  while(true){
78  try{
79  listener.lookupTransform(FRAME_ID, cloud_msg->header.frame_id, ros::Time(0), transform);
80  break;
81  }
82  catch(tf::TransformException ex){
83  ROS_ERROR("%s",ex.what());
84  ros::Duration(1.0).sleep();
85  }
86  }
87  pcl_ros::transformPointCloud(FRAME_ID, transform, *cloud_msg, cloud_transformed);
88 
89  // sensor_msgs/PointCloud2からpcl/PointCloudに変換
90  pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZRGB>());
91  pcl::fromROSMsg(cloud_transformed, *cloud);
92 
93  // Z方向の範囲でフィルタリング
94  pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_passthrough (new pcl::PointCloud<pcl::PointXYZRGB>());
95  pcl::PassThrough<pcl::PointXYZRGB> pass;
96  pass.setInputCloud (cloud);
97  pass.setFilterFieldName ("z");
98  pass.setFilterLimits (0.02, 1.0);
99  pass.filter (*cloud_passthrough);
100 
101  // voxelgridでダウンサンプリング
102  pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_voxelgrid (new pcl::PointCloud<pcl::PointXYZRGB>());
103  pcl::VoxelGrid<pcl::PointXYZRGB> voxelgrid;
104  voxelgrid.setInputCloud (cloud_passthrough);
105  voxelgrid.setLeafSize (0.01, 0.01, 0.01);
106  voxelgrid.filter (*cloud_voxelgrid);
107 
108  // pointがなければ処理を抜ける
109  if(cloud_voxelgrid->size() <= 0){
110  return;
111  }
112 
113  // クラスタ抽出のためKdTreeオブジェクトを作成
114  pcl::search::KdTree<pcl::PointXYZRGB>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZRGB>());
115  tree->setInputCloud (cloud_voxelgrid);
116 
117  std::vector<pcl::PointIndices> cluster_indices;
118  pcl::EuclideanClusterExtraction<pcl::PointXYZRGB> ec;
119  ec.setClusterTolerance (0.02);
120  ec.setMinClusterSize (10);
121  ec.setMaxClusterSize (250);
122  ec.setSearchMethod (tree);
123  ec.setInputCloud (cloud_voxelgrid);
124  ec.extract (cluster_indices);
125 
126  int cluster_i=0;
127  visualization_msgs::MarkerArray markers;
128 
129  // クラスタごとにPointのRGB値を変更する
130  // クラスタをもとにMarkerを生成する
131  pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_output (new pcl::PointCloud<pcl::PointXYZRGB>());
132  for (std::vector<pcl::PointIndices>::const_iterator it = cluster_indices.begin ();
133  it != cluster_indices.end (); ++it)
134  {
135  pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_cluster (new pcl::PointCloud<pcl::PointXYZRGB>());
136  // クラスタ内のPointRGB値を変更
137  for (std::vector<int>::const_iterator pit = it->indices.begin ();
138  pit != it->indices.end (); ++pit){
139  cloud_voxelgrid->points[*pit].r = CLUSTER_COLOR[cluster_i][RED];
140  cloud_voxelgrid->points[*pit].g = CLUSTER_COLOR[cluster_i][GREEN];
141  cloud_voxelgrid->points[*pit].b = CLUSTER_COLOR[cluster_i][BLUE];
142  cloud_cluster->points.push_back (cloud_voxelgrid->points[*pit]); //*
143  }
144  // Unorganized datasetsとしてwidth, heightを入力
145  cloud_cluster->width = cloud_cluster->points.size ();
146  cloud_cluster->height = 1;
147  // 無効なpointがないのでis_denseはtrue
148  cloud_cluster->is_dense = true;
149  *cloud_output += *cloud_cluster;
150 
151  // Markerの作成
152  visualization_msgs::Marker marker;
153  pcl::PointXYZRGB min_pt, max_pt;
154  pcl::getMinMax3D(*cloud_cluster, min_pt, max_pt);
155  convert_to_marker(&marker, cluster_i, FRAME_ID, min_pt, max_pt);
156  markers.markers.push_back(marker);
157 
158  cluster_i++;
159  if(cluster_i >= CLUSTER_MAX){
160  break;
161  }
162  }
163 
164  // pcl/PointCloudからsensor_msgs/PointCloud2に変換
165  sensor_msgs::PointCloud2 output;
166  // pcl::toROSMsg(*cloud, output);
167  // pcl::toROSMsg(*cloud_passthrough, output);
168  // pcl::toROSMsg(*cloud_voxelgrid, output);
169  pcl::toROSMsg(*cloud_output, output);
170  output.header.frame_id = FRAME_ID;
171 
172  _pub_point_cloud.publish(output);
173  _pub_marker_array.publish(markers);
174 }
175 
176 
177 int main (int argc, char** argv)
178 {
179  ros::init (argc, argv, "object_detection");
180  ros::NodeHandle nh("~");
181 
182  _pub_point_cloud = nh.advertise<sensor_msgs::PointCloud2> ("/sciurus17/example/points", 1);
183  _pub_marker_array = nh.advertise<visualization_msgs::MarkerArray>("/sciurus17/example/markers", 1);
184 
185  ros::Subscriber sub = nh.subscribe("/sciurus17/camera/depth_registered/points", 1, cloud_cb);
186 
187  ros::spin ();
188 }
189 
void cloud_cb(const sensor_msgs::PointCloud2ConstPtr &cloud_msg)
static ros::Publisher _pub_point_cloud
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
RED
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
GREEN
void fromROSMsg(const sensor_msgs::PointCloud2 &cloud, pcl::PointCloud< T > &pcl_cloud)
#define ROS_ERROR(...)
void publish(const boost::shared_ptr< M > &message) const
void convert_to_marker(visualization_msgs::Marker *marker, const int marker_id, const std::string &frame_id, const pcl::PointXYZRGB &min_pt, const pcl::PointXYZRGB &max_pt)
tree
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
ROSCPP_DECL void spin()
static ros::Publisher _pub_marker_array
int main(int argc, char **argv)
void lookupTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, StampedTransform &transform) const
void transformPointCloud(const pcl::PointCloud< PointT > &cloud_in, pcl::PointCloud< PointT > &cloud_out, const tf::Transform &transform)
BLUE
void toROSMsg(const sensor_msgs::PointCloud2 &cloud, sensor_msgs::Image &image)
bool sleep() const


sciurus17_examples
Author(s): Daisuke Sato , Hiroyuki Nomura
autogenerated on Sun Oct 2 2022 02:21:39