object_detection.cpp
Go to the documentation of this file.
1 // Copyright 2019 RT Corporation
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <ros/ros.h>
16 #include <sensor_msgs/PointCloud2.h>
19 #include <geometry_msgs/TransformStamped.h>
20 #include <pcl_ros/transforms.h>
22 #include <visualization_msgs/Marker.h>
23 #include <visualization_msgs/MarkerArray.h>
24 
25 #include <pcl/point_cloud.h>
26 #include <pcl/point_types.h>
27 #include <pcl/common/common.h>
28 #include <pcl/filters/passthrough.h>
29 #include <pcl/filters/voxel_grid.h>
30 #include <pcl/kdtree/kdtree.h>
31 #include <pcl/segmentation/extract_clusters.h>
32 
35 
36 
37 void convert_to_marker(visualization_msgs::Marker *marker, const int marker_id,
38  const std::string &frame_id,
39  const pcl::PointXYZRGB &min_pt, const pcl::PointXYZRGB &max_pt)
40 {
41  // pcl::Pointの最大最小値をBox型のマーカに変換する
42  // Converts the max/min of the pcl::Point to a Box-type marker
43 
44  marker->header.frame_id = frame_id;
45  marker->header.stamp = ros::Time();
46  marker->ns = "/sciurus17/example";
47  marker->id = marker_id;
48  marker->type = visualization_msgs::Marker::CUBE;
49  marker->action = visualization_msgs::Marker::ADD;
50  marker->lifetime = ros::Duration(0.5);
51 
52  marker->pose.position.x = (max_pt.x + min_pt.x) * 0.5;
53  marker->pose.position.y = (max_pt.y + min_pt.y) * 0.5;
54  marker->pose.position.z = (max_pt.z + min_pt.z) * 0.5;
55  marker->pose.orientation.x = 0.0;
56  marker->pose.orientation.y = 0.0;
57  marker->pose.orientation.z = 0.0;
58  marker->pose.orientation.w = 1.0;
59  marker->scale.x = (max_pt.x - min_pt.x);
60  marker->scale.y = (max_pt.y - min_pt.y);
61  marker->scale.z = (max_pt.z - min_pt.z);
62  marker->color.a = 1.0;
63  marker->color.r = 1.0;
64  marker->color.g = 1.0;
65  marker->color.b = 1.0;
66 }
67 
68 
69 void cloud_cb (const sensor_msgs::PointCloud2ConstPtr& cloud_msg)
70 {
71  const static std::string FRAME_ID = "base_link";
74  enum COLOR_RGB{
75  RED=0,
76  GREEN,
77  BLUE,
78  COLOR_MAX
79  };
80  const int CLUSTER_MAX = 10;
81  const int CLUSTER_COLOR[CLUSTER_MAX][COLOR_MAX] = {
82  {230, 0, 18},{243, 152, 18}, {255, 251, 0},
83  {143, 195, 31},{0, 153, 68}, {0, 158, 150},
84  {0, 160, 233},{0, 104, 183}, {29, 32, 136},
85  {146, 7, 131}
86  };
87 
88  sensor_msgs::PointCloud2 cloud_transformed;
89 
90  // point cloudの座標を変換
91  // base_linkとカメラ間のTFを取得する
92  // Converts the point cloud coordinates
93  // Recieves the TF between base_link and camera
94  while(true){
95  try{
96  listener.lookupTransform(FRAME_ID, cloud_msg->header.frame_id, ros::Time(0), transform);
97  break;
98  }
99  catch(tf::TransformException ex){
100  ROS_ERROR("%s",ex.what());
101  ros::Duration(1.0).sleep();
102  }
103  }
104  pcl_ros::transformPointCloud(FRAME_ID, transform, *cloud_msg, cloud_transformed);
105 
106  // sensor_msgs/PointCloud2からpcl/PointCloudに変換
107  // Converts sensor_msgs/PointCloud2 to pcl/PointCloud
108  pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZRGB>());
109  pcl::fromROSMsg(cloud_transformed, *cloud);
110 
111  // Z方向の範囲でフィルタリング
112  // Filters in Z-axis
113  pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_passthrough (new pcl::PointCloud<pcl::PointXYZRGB>());
114  pcl::PassThrough<pcl::PointXYZRGB> pass;
115  pass.setInputCloud (cloud);
116  pass.setFilterFieldName ("z");
117  pass.setFilterLimits (0.02, 1.0);
118  pass.filter (*cloud_passthrough);
119 
120  // voxelgridでダウンサンプリング
121  // Down samples with voxelgrid
122  pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_voxelgrid (new pcl::PointCloud<pcl::PointXYZRGB>());
123  pcl::VoxelGrid<pcl::PointXYZRGB> voxelgrid;
124  voxelgrid.setInputCloud (cloud_passthrough);
125  voxelgrid.setLeafSize (0.01, 0.01, 0.01);
126  voxelgrid.filter (*cloud_voxelgrid);
127 
128  // pointがなければ処理を抜ける
129  // Exits the process if there's no point
130  if(cloud_voxelgrid->size() <= 0){
131  return;
132  }
133 
134  // クラスタ抽出のためKdTreeオブジェクトを作成
135  // Creates KdTree object for cluster extraction
136  pcl::search::KdTree<pcl::PointXYZRGB>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZRGB>());
137  tree->setInputCloud (cloud_voxelgrid);
138 
139  std::vector<pcl::PointIndices> cluster_indices;
140  pcl::EuclideanClusterExtraction<pcl::PointXYZRGB> ec;
141  ec.setClusterTolerance (0.02);
142  ec.setMinClusterSize (10);
143  ec.setMaxClusterSize (250);
144  ec.setSearchMethod (tree);
145  ec.setInputCloud (cloud_voxelgrid);
146  ec.extract (cluster_indices);
147 
148  int cluster_i=0;
149  visualization_msgs::MarkerArray markers;
150 
151  // クラスタごとにPointのRGB値を変更する
152  // クラスタをもとにMarkerを生成する
153  // Changes the RGBs of the Point in each clusters
154  // Creates the Marker based on the cluster
155  pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_output (new pcl::PointCloud<pcl::PointXYZRGB>());
156  for (std::vector<pcl::PointIndices>::const_iterator it = cluster_indices.begin ();
157  it != cluster_indices.end (); ++it)
158  {
159  pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_cluster (new pcl::PointCloud<pcl::PointXYZRGB>());
160  // クラスタ内のPointRGB値を変更
161  // Changes the PointRGB within the cluster
162  for (std::vector<int>::const_iterator pit = it->indices.begin ();
163  pit != it->indices.end (); ++pit){
164  cloud_voxelgrid->points[*pit].r = CLUSTER_COLOR[cluster_i][RED];
165  cloud_voxelgrid->points[*pit].g = CLUSTER_COLOR[cluster_i][GREEN];
166  cloud_voxelgrid->points[*pit].b = CLUSTER_COLOR[cluster_i][BLUE];
167  cloud_cluster->points.push_back (cloud_voxelgrid->points[*pit]); //*
168  }
169  // Unorganized datasetsとしてwidth, heightを入力
170  // Inserts the width and height as unorganized datasets
171  cloud_cluster->width = cloud_cluster->points.size ();
172  cloud_cluster->height = 1;
173  // 無効なpointがないのでis_denseはtrue
174  // is_dense is true since there's no invalid points
175  cloud_cluster->is_dense = true;
176  *cloud_output += *cloud_cluster;
177 
178  // Markerの作成
179  // Creates the marker
180  visualization_msgs::Marker marker;
181  pcl::PointXYZRGB min_pt, max_pt;
182  pcl::getMinMax3D(*cloud_cluster, min_pt, max_pt);
183  convert_to_marker(&marker, cluster_i, FRAME_ID, min_pt, max_pt);
184  markers.markers.push_back(marker);
185 
186  cluster_i++;
187  if(cluster_i >= CLUSTER_MAX){
188  break;
189  }
190  }
191 
192  // pcl/PointCloudからsensor_msgs/PointCloud2に変換
193  // Converts the pcl/PointCloud to sensor_msgs/PointCloud2
194  sensor_msgs::PointCloud2 output;
195  // pcl::toROSMsg(*cloud, output);
196  // pcl::toROSMsg(*cloud_passthrough, output);
197  // pcl::toROSMsg(*cloud_voxelgrid, output);
198  pcl::toROSMsg(*cloud_output, output);
199  output.header.frame_id = FRAME_ID;
200 
201  _pub_point_cloud.publish(output);
202  _pub_marker_array.publish(markers);
203 }
204 
205 
206 int main (int argc, char** argv)
207 {
208  ros::init (argc, argv, "object_detection");
209  ros::NodeHandle nh("~");
210 
211  _pub_point_cloud = nh.advertise<sensor_msgs::PointCloud2> ("/sciurus17/example/points", 1);
212  _pub_marker_array = nh.advertise<visualization_msgs::MarkerArray>("/sciurus17/example/markers", 1);
213 
214  ros::Subscriber sub = nh.subscribe("/sciurus17/camera/depth_registered/points", 1, cloud_cb);
215 
216  ros::spin ();
217 }
218 
_pub_point_cloud
static ros::Publisher _pub_point_cloud
Definition: object_detection.cpp:33
ros::Publisher
ros::init
ROSCPP_DECL void init(const M_string &remappings, const std::string &name, uint32_t options=0)
ros.h
transform
template Halfspace< double > transform(const Halfspace< double > &a, const Transform3< double > &tf)
tf::StampedTransform
pcl::fromROSMsg
void fromROSMsg(const sensor_msgs::PointCloud2 &cloud, pcl::PointCloud< T > &pcl_cloud)
ros::Publisher::publish
void publish(const boost::shared_ptr< M > &message) const
ros::NodeHandle::advertise
Publisher advertise(AdvertiseOptions &ops)
transform_broadcaster.h
transforms.h
tree
tree
frame_id
frame_id
Quaternion.h
convert_to_marker
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)
Definition: object_detection.cpp:37
ROS_ERROR
#define ROS_ERROR(...)
BLUE
BLUE
_pub_marker_array
static ros::Publisher _pub_marker_array
Definition: object_detection.cpp:34
main
int main(int argc, char **argv)
Definition: object_detection.cpp:206
ros::NodeHandle::subscribe
Subscriber subscribe(const std::string &topic, uint32_t queue_size, const boost::function< void(C)> &callback, const VoidConstPtr &tracked_object=VoidConstPtr(), const TransportHints &transport_hints=TransportHints())
GREEN
GREEN
pcl_ros::transformPointCloud
void transformPointCloud(const Eigen::Matrix4f &transform, const sensor_msgs::PointCloud2 &in, sensor_msgs::PointCloud2 &out)
ros::Time
tf::TransformListener
pcl::toROSMsg
void toROSMsg(const pcl::PointCloud< T > &cloud, sensor_msgs::Image &msg)
ros::spin
ROSCPP_DECL void spin()
ros::Duration::sleep
bool sleep() const
tf2::TransformException
ros::Duration
hand_position_publisher_example.listener
listener
Definition: hand_position_publisher_example.py:26
cloud_cb
void cloud_cb(const sensor_msgs::PointCloud2ConstPtr &cloud_msg)
Definition: object_detection.cpp:69
RED
RED
ros::NodeHandle
ros::Subscriber
pcl_conversions.h


sciurus17_examples
Author(s): Daisuke Sato , Hiroyuki Nomura
autogenerated on Fri Aug 2 2024 08:37:20