main.cpp
Go to the documentation of this file.
3 #include "opencv2/video/tracking.hpp"
4 #include "pcl_ros/point_cloud.h"
5 #include <algorithm>
6 #include <fstream>
7 #include <geometry_msgs/Point.h>
8 #include <iostream>
9 #include <iterator>
10 #include <opencv2/core/core.hpp>
11 #include <opencv2/highgui/highgui.hpp>
12 #include <opencv2/imgproc/imgproc.hpp>
13 #include <opencv2/video/video.hpp>
14 #include <pcl/io/pcd_io.h>
15 #include <pcl/point_types.h>
16 #include <ros/ros.h>
17 #include <std_msgs/Float32MultiArray.h>
18 #include <std_msgs/Int32MultiArray.h>
19 #include <string.h>
20 
21 #include <pcl/common/centroid.h>
22 #include <pcl/common/geometry.h>
23 #include <pcl/features/normal_3d.h>
24 #include <pcl/filters/extract_indices.h>
25 #include <pcl/filters/voxel_grid.h>
26 #include <pcl/kdtree/kdtree.h>
27 #include <pcl/point_cloud.h>
28 #include <pcl/point_types.h>
29 #include <pcl/sample_consensus/method_types.h>
30 #include <pcl/sample_consensus/model_types.h>
31 #include <pcl/segmentation/extract_clusters.h>
32 #include <pcl/segmentation/sac_segmentation.h>
34 #include <sensor_msgs/PointCloud2.h>
35 
36 #include <limits>
37 #include <utility>
38 #include <visualization_msgs/Marker.h>
39 #include <visualization_msgs/MarkerArray.h>
40 
41 using namespace std;
42 using namespace cv;
43 
45 
46 // KF init
47 int stateDim = 4; // [x,y,v_x,v_y]//,w,h]
48 int measDim = 2; // [z_x,z_y,z_w,z_h]
49 int ctrlDim = 0;
50 cv::KalmanFilter KF0(stateDim, measDim, ctrlDim, CV_32F);
51 cv::KalmanFilter KF1(stateDim, measDim, ctrlDim, CV_32F);
52 cv::KalmanFilter KF2(stateDim, measDim, ctrlDim, CV_32F);
53 cv::KalmanFilter KF3(stateDim, measDim, ctrlDim, CV_32F);
54 cv::KalmanFilter KF4(stateDim, measDim, ctrlDim, CV_32F);
55 cv::KalmanFilter KF5(stateDim, measDim, ctrlDim, CV_32F);
56 
63 
65 
66 std::vector<geometry_msgs::Point> prevClusterCenters;
67 
68 cv::Mat state(stateDim, 1, CV_32F);
69 cv::Mat_<float> measurement(2, 1);
70 
71 std::vector<int> objID; // Output of the data association using KF
72  // measurement.setTo(Scalar(0));
73 
74 bool firstFrame = true;
75 
76 // calculate euclidean distance of two points
77 double euclidean_distance(geometry_msgs::Point &p1, geometry_msgs::Point &p2) {
78  return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y) +
79  (p1.z - p2.z) * (p1.z - p2.z));
80 }
81 /*
82 //Count unique object IDs. just to make sure same ID has not been assigned to
83 two KF_Trackers. int countIDs(vector<int> v)
84 {
85  transform(v.begin(), v.end(), v.begin(), abs); // O(n) where n =
86 distance(v.end(), v.begin()) sort(v.begin(), v.end()); // Average case O(n log
87 n), worst case O(n^2) (usually implemented as quicksort.
88  // To guarantee worst case O(n log n) replace with make_heap, then
89 sort_heap.
90 
91  // Unique will take a sorted range, and move things around to get duplicated
92  // items to the back and returns an iterator to the end of the unique
93 section of the range auto unique_end = unique(v.begin(), v.end()); // Again n
94 comparisons return distance(unique_end, v.begin()); // Constant time for random
95 access iterators (like vector's)
96 }
97 */
98 
99 /*
100 
101 objID: vector containing the IDs of the clusters that should be associated with
102 each KF_Tracker objID[0] corresponds to KFT0, objID[1] corresponds to KFT1 etc.
103 */
104 
105 std::pair<int, int> findIndexOfMin(std::vector<std::vector<float>> distMat) {
106  cout << "findIndexOfMin cALLED\n";
107  std::pair<int, int> minIndex;
108  float minEl = std::numeric_limits<float>::max();
109  cout << "minEl=" << minEl << "\n";
110  for (int i = 0; i < distMat.size(); i++)
111  for (int j = 0; j < distMat.at(0).size(); j++) {
112  if (distMat[i][j] < minEl) {
113  minEl = distMat[i][j];
114  minIndex = std::make_pair(i, j);
115  }
116  }
117  cout << "minIndex=" << minIndex.first << "," << minIndex.second << "\n";
118  return minIndex;
119 }
120 void KFT(const std_msgs::Float32MultiArray ccs) {
121 
122  // First predict, to update the internal statePre variable
123 
124  std::vector<cv::Mat> pred{KF0.predict(), KF1.predict(), KF2.predict(),
125  KF3.predict(), KF4.predict(), KF5.predict()};
126  // cout<<"Pred successfull\n";
127 
128  // cv::Point predictPt(prediction.at<float>(0),prediction.at<float>(1));
129  // cout<<"Prediction 1
130  // ="<<prediction.at<float>(0)<<","<<prediction.at<float>(1)<<"\n";
131 
132  // Get measurements
133  // Extract the position of the clusters forom the multiArray. To check if the
134  // data coming in, check the .z (every third) coordinate and that will be 0.0
135  std::vector<geometry_msgs::Point> clusterCenters; // clusterCenters
136 
137  int i = 0;
138  for (std::vector<float>::const_iterator it = ccs.data.begin();
139  it != ccs.data.end(); it += 3) {
140  geometry_msgs::Point pt;
141  pt.x = *it;
142  pt.y = *(it + 1);
143  pt.z = *(it + 2);
144 
145  clusterCenters.push_back(pt);
146  }
147 
148  // cout<<"CLusterCenters Obtained"<<"\n";
149  std::vector<geometry_msgs::Point> KFpredictions;
150  i = 0;
151  for (auto it = pred.begin(); it != pred.end(); it++) {
152  geometry_msgs::Point pt;
153  pt.x = (*it).at<float>(0);
154  pt.y = (*it).at<float>(1);
155  pt.z = (*it).at<float>(2);
156 
157  KFpredictions.push_back(pt);
158  }
159  // cout<<"Got predictions"<<"\n";
160 
161  // Find the cluster that is more probable to be belonging to a given KF.
162  objID.clear(); // Clear the objID vector
163  objID.resize(6); // Allocate default elements so that [i] doesnt segfault.
164  // Should be done better
165  // Copy clusterCentres for modifying it and preventing multiple assignments of
166  // the same ID
167  std::vector<geometry_msgs::Point> copyOfClusterCenters(clusterCenters);
168  std::vector<std::vector<float>> distMat;
169 
170  for (int filterN = 0; filterN < 6; filterN++) {
171  std::vector<float> distVec;
172  for (int n = 0; n < 6; n++) {
173  distVec.push_back(
174  euclidean_distance(KFpredictions[filterN], copyOfClusterCenters[n]));
175  }
176 
177  distMat.push_back(distVec);
178  /*// Based on distVec instead of distMat (global min). Has problems with the
179  person's leg going out of scope int
180  ID=std::distance(distVec.begin(),min_element(distVec.begin(),distVec.end()));
181  //cout<<"finterlN="<<filterN<<" minID="<<ID
182  objID.push_back(ID);
183  // Prevent assignment of the same object ID to multiple clusters
184  copyOfClusterCenters[ID].x=100000;// A large value so that this center is
185  not assigned to another cluster copyOfClusterCenters[ID].y=10000;
186  copyOfClusterCenters[ID].z=10000;
187  */
188  cout << "filterN=" << filterN << "\n";
189  }
190 
191  cout << "distMat.size()" << distMat.size() << "\n";
192  cout << "distMat[0].size()" << distMat.at(0).size() << "\n";
193  // DEBUG: print the distMat
194  for (const auto &row : distMat) {
195  for (const auto &s : row)
196  std::cout << s << ' ';
197  std::cout << std::endl;
198  }
199 
200  for (int clusterCount = 0; clusterCount < 6; clusterCount++) {
201  // 1. Find min(distMax)==> (i,j);
202  std::pair<int, int> minIndex(findIndexOfMin(distMat));
203  cout << "Received minIndex=" << minIndex.first << "," << minIndex.second
204  << "\n";
205  // 2. objID[i]=clusterCenters[j]; counter++
206  objID[minIndex.first] = minIndex.second;
207 
208  // 3. distMat[i,:]=10000; distMat[:,j]=10000
209  distMat[minIndex.first] =
210  std::vector<float>(6, 10000.0); // Set the row to a high number.
211  for (int row = 0; row < distMat.size();
212  row++) // set the column to a high number
213  {
214  distMat[row][minIndex.second] = 10000.0;
215  }
216  // 4. if(counter<6) got to 1.
217  cout << "clusterCount=" << clusterCount << "\n";
218  }
219 
220  // cout<<"Got object IDs"<<"\n";
221  // countIDs(objID);// for verif/corner cases
222 
223  // display objIDs
224  /* DEBUG
225  cout<<"objID= ";
226  for(auto it=objID.begin();it!=objID.end();it++)
227  cout<<*it<<" ,";
228  cout<<"\n";
229  */
230 
231  visualization_msgs::MarkerArray clusterMarkers;
232 
233  for (int i = 0; i < 6; i++) {
234  visualization_msgs::Marker m;
235 
236  m.id = i;
237  m.type = visualization_msgs::Marker::CUBE;
238  m.header.frame_id = "map";
239  m.scale.x = 0.3;
240  m.scale.y = 0.3;
241  m.scale.z = 0.3;
242  m.action = visualization_msgs::Marker::ADD;
243  m.color.a = 1.0;
244  m.color.r = i % 2 ? 1 : 0;
245  m.color.g = i % 3 ? 1 : 0;
246  m.color.b = i % 4 ? 1 : 0;
247 
248  // geometry_msgs::Point clusterC(clusterCenters.at(objID[i]));
249  geometry_msgs::Point clusterC(KFpredictions[i]);
250  m.pose.position.x = clusterC.x;
251  m.pose.position.y = clusterC.y;
252  m.pose.position.z = clusterC.z;
253 
254  clusterMarkers.markers.push_back(m);
255  }
256 
257  prevClusterCenters = clusterCenters;
258 
259  markerPub.publish(clusterMarkers);
260 
261  std_msgs::Int32MultiArray obj_id;
262  for (auto it = objID.begin(); it != objID.end(); it++)
263  obj_id.data.push_back(*it);
264  // Publish the object IDs
265  objID_pub.publish(obj_id);
266  // convert clusterCenters from geometry_msgs::Point to floats
267  std::vector<std::vector<float>> cc;
268  for (int i = 0; i < 6; i++) {
269  vector<float> pt;
270  pt.push_back(clusterCenters[objID[i]].x);
271  pt.push_back(clusterCenters[objID[i]].y);
272  pt.push_back(clusterCenters[objID[i]].z);
273 
274  cc.push_back(pt);
275  }
276  // cout<<"cc[5][0]="<<cc[5].at(0)<<"cc[5][1]="<<cc[5].at(1)<<"cc[5][2]="<<cc[5].at(2)<<"\n";
277  float meas0[2] = {cc[0].at(0), cc[0].at(1)};
278  float meas1[2] = {cc[1].at(0), cc[1].at(1)};
279  float meas2[2] = {cc[2].at(0), cc[2].at(1)};
280  float meas3[2] = {cc[3].at(0), cc[3].at(1)};
281  float meas4[2] = {cc[4].at(0), cc[4].at(1)};
282  float meas5[2] = {cc[5].at(0), cc[5].at(1)};
283 
284  // The update phase
285  cv::Mat meas0Mat = cv::Mat(2, 1, CV_32F, meas0);
286  cv::Mat meas1Mat = cv::Mat(2, 1, CV_32F, meas1);
287  cv::Mat meas2Mat = cv::Mat(2, 1, CV_32F, meas2);
288  cv::Mat meas3Mat = cv::Mat(2, 1, CV_32F, meas3);
289  cv::Mat meas4Mat = cv::Mat(2, 1, CV_32F, meas4);
290  cv::Mat meas5Mat = cv::Mat(2, 1, CV_32F, meas5);
291 
292  // cout<<"meas0Mat"<<meas0Mat<<"\n";
293  if (!(meas0Mat.at<float>(0, 0) == 0.0f || meas0Mat.at<float>(1, 0) == 0.0f))
294  Mat estimated0 = KF0.correct(meas0Mat);
295  if (!(meas1[0] == 0.0f || meas1[1] == 0.0f))
296  Mat estimated1 = KF1.correct(meas1Mat);
297  if (!(meas2[0] == 0.0f || meas2[1] == 0.0f))
298  Mat estimated2 = KF2.correct(meas2Mat);
299  if (!(meas3[0] == 0.0f || meas3[1] == 0.0f))
300  Mat estimated3 = KF3.correct(meas3Mat);
301  if (!(meas4[0] == 0.0f || meas4[1] == 0.0f))
302  Mat estimated4 = KF4.correct(meas4Mat);
303  if (!(meas5[0] == 0.0f || meas5[1] == 0.0f))
304  Mat estimated5 = KF5.correct(meas5Mat);
305 
306  // Publish the point clouds belonging to each clusters
307 
308  // cout<<"estimate="<<estimated.at<float>(0)<<","<<estimated.at<float>(1)<<"\n";
309  // Point statePt(estimated.at<float>(0),estimated.at<float>(1));
310  // cout<<"DONE KF_TRACKER\n";
311 }
313  pcl::PointCloud<pcl::PointXYZ>::Ptr cluster) {
314  sensor_msgs::PointCloud2::Ptr clustermsg(new sensor_msgs::PointCloud2);
315  pcl::toROSMsg(*cluster, *clustermsg);
316  clustermsg->header.frame_id = "map";
317  clustermsg->header.stamp = ros::Time::now();
318  pub.publish(*clustermsg);
319 }
320 
321 void cloud_cb(const sensor_msgs::PointCloud2ConstPtr &input)
322 
323 {
324  // cout<<"IF firstFrame="<<firstFrame<<"\n";
325  // If this is the first frame, initialize kalman filters for the clustered
326  // objects
327  if (firstFrame) {
328  // Initialize 6 Kalman Filters; Assuming 6 max objects in the dataset.
329  // Could be made generic by creating a Kalman Filter only when a new object
330  // is detected
331 
332  float dvx = 0.01f; // 1.0
333  float dvy = 0.01f; // 1.0
334  float dx = 1.0f;
335  float dy = 1.0f;
336  KF0.transitionMatrix = (Mat_<float>(4, 4) << dx, 0, 1, 0, 0, dy, 0, 1, 0, 0,
337  dvx, 0, 0, 0, 0, dvy);
338  KF1.transitionMatrix = (Mat_<float>(4, 4) << dx, 0, 1, 0, 0, dy, 0, 1, 0, 0,
339  dvx, 0, 0, 0, 0, dvy);
340  KF2.transitionMatrix = (Mat_<float>(4, 4) << dx, 0, 1, 0, 0, dy, 0, 1, 0, 0,
341  dvx, 0, 0, 0, 0, dvy);
342  KF3.transitionMatrix = (Mat_<float>(4, 4) << dx, 0, 1, 0, 0, dy, 0, 1, 0, 0,
343  dvx, 0, 0, 0, 0, dvy);
344  KF4.transitionMatrix = (Mat_<float>(4, 4) << dx, 0, 1, 0, 0, dy, 0, 1, 0, 0,
345  dvx, 0, 0, 0, 0, dvy);
346  KF5.transitionMatrix = (Mat_<float>(4, 4) << dx, 0, 1, 0, 0, dy, 0, 1, 0, 0,
347  dvx, 0, 0, 0, 0, dvy);
348 
349  cv::setIdentity(KF0.measurementMatrix);
350  cv::setIdentity(KF1.measurementMatrix);
351  cv::setIdentity(KF2.measurementMatrix);
352  cv::setIdentity(KF3.measurementMatrix);
353  cv::setIdentity(KF4.measurementMatrix);
354  cv::setIdentity(KF5.measurementMatrix);
355  // Process Noise Covariance Matrix Q
356  // [ Ex 0 0 0 0 0 ]
357  // [ 0 Ey 0 0 0 0 ]
358  // [ 0 0 Ev_x 0 0 0 ]
359  // [ 0 0 0 1 Ev_y 0 ]
362  float sigmaP = 0.01;
363  float sigmaQ = 0.1;
364  setIdentity(KF0.processNoiseCov, Scalar::all(sigmaP));
365  setIdentity(KF1.processNoiseCov, Scalar::all(sigmaP));
366  setIdentity(KF2.processNoiseCov, Scalar::all(sigmaP));
367  setIdentity(KF3.processNoiseCov, Scalar::all(sigmaP));
368  setIdentity(KF4.processNoiseCov, Scalar::all(sigmaP));
369  setIdentity(KF5.processNoiseCov, Scalar::all(sigmaP));
370  // Meas noise cov matrix R
371  cv::setIdentity(KF0.measurementNoiseCov, cv::Scalar(sigmaQ)); // 1e-1
372  cv::setIdentity(KF1.measurementNoiseCov, cv::Scalar(sigmaQ));
373  cv::setIdentity(KF2.measurementNoiseCov, cv::Scalar(sigmaQ));
374  cv::setIdentity(KF3.measurementNoiseCov, cv::Scalar(sigmaQ));
375  cv::setIdentity(KF4.measurementNoiseCov, cv::Scalar(sigmaQ));
376  cv::setIdentity(KF5.measurementNoiseCov, cv::Scalar(sigmaQ));
377 
378  // Process the point cloud
379  pcl::PointCloud<pcl::PointXYZ>::Ptr input_cloud(
380  new pcl::PointCloud<pcl::PointXYZ>);
381  pcl::PointCloud<pcl::PointXYZ>::Ptr clustered_cloud(
382  new pcl::PointCloud<pcl::PointXYZ>);
383  /* Creating the KdTree from input point cloud*/
384  pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(
385  new pcl::search::KdTree<pcl::PointXYZ>);
386 
387  pcl::fromROSMsg(*input, *input_cloud);
388 
389  tree->setInputCloud(input_cloud);
390 
391  std::vector<pcl::PointIndices> cluster_indices;
392  pcl::EuclideanClusterExtraction<pcl::PointXYZ> ec;
393  ec.setClusterTolerance(0.08);
394  ec.setMinClusterSize(10);
395  ec.setMaxClusterSize(600);
396  ec.setSearchMethod(tree);
397  ec.setInputCloud(input_cloud);
398  /* Extract the clusters out of pc and save indices in cluster_indices.*/
399  ec.extract(cluster_indices);
400 
401  std::vector<pcl::PointIndices>::const_iterator it;
402  std::vector<int>::const_iterator pit;
403  // Vector of cluster pointclouds
404  std::vector<pcl::PointCloud<pcl::PointXYZ>::Ptr> cluster_vec;
405  // Cluster centroids
406  std::vector<pcl::PointXYZ> clusterCentroids;
407 
408  for (it = cluster_indices.begin(); it != cluster_indices.end(); ++it) {
409 
410  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_cluster(
411  new pcl::PointCloud<pcl::PointXYZ>);
412  float x = 0.0;
413  float y = 0.0;
414  int numPts = 0;
415  for (pit = it->indices.begin(); pit != it->indices.end(); pit++) {
416 
417  cloud_cluster->points.push_back(input_cloud->points[*pit]);
418  x += input_cloud->points[*pit].x;
419  y += input_cloud->points[*pit].y;
420  numPts++;
421 
422  // dist_this_point = pcl::geometry::distance(input_cloud->points[*pit],
423  // origin);
424  // mindist_this_cluster = std::min(dist_this_point,
425  // mindist_this_cluster);
426  }
427 
428  pcl::PointXYZ centroid;
429  centroid.x = x / numPts;
430  centroid.y = y / numPts;
431  centroid.z = 0.0;
432 
433  cluster_vec.push_back(cloud_cluster);
434 
435  // Get the centroid of the cluster
436  clusterCentroids.push_back(centroid);
437  }
438 
439  // Ensure at least 6 clusters exist to publish (later clusters may be empty)
440  while (cluster_vec.size() < 6) {
441  pcl::PointCloud<pcl::PointXYZ>::Ptr empty_cluster(
442  new pcl::PointCloud<pcl::PointXYZ>);
443  empty_cluster->points.push_back(pcl::PointXYZ(0, 0, 0));
444  cluster_vec.push_back(empty_cluster);
445  }
446 
447  while (clusterCentroids.size() < 6) {
448  pcl::PointXYZ centroid;
449  centroid.x = 0.0;
450  centroid.y = 0.0;
451  centroid.z = 0.0;
452 
453  clusterCentroids.push_back(centroid);
454  }
455 
456  // Set initial state
457  KF0.statePre.at<float>(0) = clusterCentroids.at(0).x;
458  KF0.statePre.at<float>(1) = clusterCentroids.at(0).y;
459  KF0.statePre.at<float>(2) = 0; // initial v_x
460  KF0.statePre.at<float>(3) = 0; // initial v_y
461 
462  // Set initial state
463  KF1.statePre.at<float>(0) = clusterCentroids.at(1).x;
464  KF1.statePre.at<float>(1) = clusterCentroids.at(1).y;
465  KF1.statePre.at<float>(2) = 0; // initial v_x
466  KF1.statePre.at<float>(3) = 0; // initial v_y
467 
468  // Set initial state
469  KF2.statePre.at<float>(0) = clusterCentroids.at(2).x;
470  KF2.statePre.at<float>(1) = clusterCentroids.at(2).y;
471  KF2.statePre.at<float>(2) = 0; // initial v_x
472  KF2.statePre.at<float>(3) = 0; // initial v_y
473 
474  // Set initial state
475  KF3.statePre.at<float>(0) = clusterCentroids.at(3).x;
476  KF3.statePre.at<float>(1) = clusterCentroids.at(3).y;
477  KF3.statePre.at<float>(2) = 0; // initial v_x
478  KF3.statePre.at<float>(3) = 0; // initial v_y
479 
480  // Set initial state
481  KF4.statePre.at<float>(0) = clusterCentroids.at(4).x;
482  KF4.statePre.at<float>(1) = clusterCentroids.at(4).y;
483  KF4.statePre.at<float>(2) = 0; // initial v_x
484  KF4.statePre.at<float>(3) = 0; // initial v_y
485 
486  // Set initial state
487  KF5.statePre.at<float>(0) = clusterCentroids.at(5).x;
488  KF5.statePre.at<float>(1) = clusterCentroids.at(5).y;
489  KF5.statePre.at<float>(2) = 0; // initial v_x
490  KF5.statePre.at<float>(3) = 0; // initial v_y
491 
492  firstFrame = false;
493 
494  for (int i = 0; i < 6; i++) {
495  geometry_msgs::Point pt;
496  pt.x = clusterCentroids.at(i).x;
497  pt.y = clusterCentroids.at(i).y;
498  prevClusterCenters.push_back(pt);
499  }
500  /* // Print the initial state of the kalman filter for debugging
501  cout<<"KF0.satePre="<<KF0.statePre.at<float>(0)<<","<<KF0.statePre.at<float>(1)<<"\n";
502  cout<<"KF1.satePre="<<KF1.statePre.at<float>(0)<<","<<KF1.statePre.at<float>(1)<<"\n";
503  cout<<"KF2.satePre="<<KF2.statePre.at<float>(0)<<","<<KF2.statePre.at<float>(1)<<"\n";
504  cout<<"KF3.satePre="<<KF3.statePre.at<float>(0)<<","<<KF3.statePre.at<float>(1)<<"\n";
505  cout<<"KF4.satePre="<<KF4.statePre.at<float>(0)<<","<<KF4.statePre.at<float>(1)<<"\n";
506  cout<<"KF5.satePre="<<KF5.statePre.at<float>(0)<<","<<KF5.statePre.at<float>(1)<<"\n";
507 
508  //cin.ignore();// To be able to see the printed initial state of the
509  KalmanFilter
510  */
511  }
512 
513  else {
514  // cout<<"ELSE firstFrame="<<firstFrame<<"\n";
515  pcl::PointCloud<pcl::PointXYZ>::Ptr input_cloud(
516  new pcl::PointCloud<pcl::PointXYZ>);
517  pcl::PointCloud<pcl::PointXYZ>::Ptr clustered_cloud(
518  new pcl::PointCloud<pcl::PointXYZ>);
519  /* Creating the KdTree from input point cloud*/
520  pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(
521  new pcl::search::KdTree<pcl::PointXYZ>);
522 
523  pcl::fromROSMsg(*input, *input_cloud);
524 
525  tree->setInputCloud(input_cloud);
526 
527  /* Here we are creating a vector of PointIndices, which contains the actual
528  * index information in a vector<int>. The indices of each detected cluster
529  * are saved here. Cluster_indices is a vector containing one instance of
530  * PointIndices for each detected cluster. Cluster_indices[0] contain all
531  * indices of the first cluster in input point cloud.
532  */
533  std::vector<pcl::PointIndices> cluster_indices;
534  pcl::EuclideanClusterExtraction<pcl::PointXYZ> ec;
535  ec.setClusterTolerance(0.3);
536  ec.setMinClusterSize(10);
537  ec.setMaxClusterSize(600);
538  ec.setSearchMethod(tree);
539  ec.setInputCloud(input_cloud);
540  // cout<<"PCL init successfull\n";
541  /* Extract the clusters out of pc and save indices in cluster_indices.*/
542  ec.extract(cluster_indices);
543  // cout<<"PCL extract successfull\n";
544  /* To separate each cluster out of the vector<PointIndices> we have to
545  * iterate through cluster_indices, create a new PointCloud for each
546  * entry and write all points of the current cluster in the PointCloud.
547  */
548  // pcl::PointXYZ origin (0,0,0);
549  // float mindist_this_cluster = 1000;
550  // float dist_this_point = 1000;
551 
552  std::vector<pcl::PointIndices>::const_iterator it;
553  std::vector<int>::const_iterator pit;
554  // Vector of cluster pointclouds
555  std::vector<pcl::PointCloud<pcl::PointXYZ>::Ptr> cluster_vec;
556 
557  // Cluster centroids
558  std::vector<pcl::PointXYZ> clusterCentroids;
559 
560  for (it = cluster_indices.begin(); it != cluster_indices.end(); ++it) {
561  float x = 0.0;
562  float y = 0.0;
563  int numPts = 0;
564  pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_cluster(
565  new pcl::PointCloud<pcl::PointXYZ>);
566  for (pit = it->indices.begin(); pit != it->indices.end(); pit++) {
567 
568  cloud_cluster->points.push_back(input_cloud->points[*pit]);
569 
570  x += input_cloud->points[*pit].x;
571  y += input_cloud->points[*pit].y;
572  numPts++;
573 
574  // dist_this_point = pcl::geometry::distance(input_cloud->points[*pit],
575  // origin);
576  // mindist_this_cluster = std::min(dist_this_point,
577  // mindist_this_cluster);
578  }
579 
580  pcl::PointXYZ centroid;
581  centroid.x = x / numPts;
582  centroid.y = y / numPts;
583  centroid.z = 0.0;
584 
585  cluster_vec.push_back(cloud_cluster);
586 
587  // Get the centroid of the cluster
588  clusterCentroids.push_back(centroid);
589  }
590  // cout<<"cluster_vec got some clusters\n";
591 
592  // Ensure at least 6 clusters exist to publish (later clusters may be empty)
593  while (cluster_vec.size() < 6) {
594  pcl::PointCloud<pcl::PointXYZ>::Ptr empty_cluster(
595  new pcl::PointCloud<pcl::PointXYZ>);
596  empty_cluster->points.push_back(pcl::PointXYZ(0, 0, 0));
597  cluster_vec.push_back(empty_cluster);
598  }
599 
600  while (clusterCentroids.size() < 6) {
601  pcl::PointXYZ centroid;
602  centroid.x = 0.0;
603  centroid.y = 0.0;
604  centroid.z = 0.0;
605 
606  clusterCentroids.push_back(centroid);
607  }
608 
609  std_msgs::Float32MultiArray cc;
610  for (int i = 0; i < 6; i++) {
611  cc.data.push_back(clusterCentroids.at(i).x);
612  cc.data.push_back(clusterCentroids.at(i).y);
613  cc.data.push_back(clusterCentroids.at(i).z);
614  }
615  // cout<<"6 clusters initialized\n";
616 
617  // cc_pos.publish(cc);// Publish cluster mid-points.
618  KFT(cc);
619  int i = 0;
620  bool publishedCluster[6];
621  for (auto it = objID.begin(); it != objID.end();
622  it++) { // cout<<"Inside the for loop\n";
623 
624  switch (i) {
625  cout << "Inside the switch case\n";
626  case 0: {
627  publish_cloud(pub_cluster0, cluster_vec[*it]);
628  publishedCluster[i] =
629  true; // Use this flag to publish only once for a given obj ID
630  i++;
631  break;
632  }
633  case 1: {
634  publish_cloud(pub_cluster1, cluster_vec[*it]);
635  publishedCluster[i] =
636  true; // Use this flag to publish only once for a given obj ID
637  i++;
638  break;
639  }
640  case 2: {
641  publish_cloud(pub_cluster2, cluster_vec[*it]);
642  publishedCluster[i] =
643  true; // Use this flag to publish only once for a given obj ID
644  i++;
645  break;
646  }
647  case 3: {
648  publish_cloud(pub_cluster3, cluster_vec[*it]);
649  publishedCluster[i] =
650  true; // Use this flag to publish only once for a given obj ID
651  i++;
652  break;
653  }
654  case 4: {
655  publish_cloud(pub_cluster4, cluster_vec[*it]);
656  publishedCluster[i] =
657  true; // Use this flag to publish only once for a given obj ID
658  i++;
659  break;
660  }
661 
662  case 5: {
663  publish_cloud(pub_cluster5, cluster_vec[*it]);
664  publishedCluster[i] =
665  true; // Use this flag to publish only once for a given obj ID
666  i++;
667  break;
668  }
669  default:
670  break;
671  }
672  }
673  }
674 }
675 
676 int main(int argc, char **argv) {
677  // ROS init
678  ros::init(argc, argv, "kf_tracker");
679  ros::NodeHandle nh;
680 
681  // Publishers to publish the state of the objects (pos and vel)
682  // objState1=nh.advertise<geometry_msgs::Twist> ("obj_1",1);
683 
684  cout << "About to setup callback\n";
685 
686  // Create a ROS subscriber for the input point cloud
687  ros::Subscriber sub = nh.subscribe("filtered_cloud", 1, cloud_cb);
688  // Create a ROS publisher for the output point cloud
689  pub_cluster0 = nh.advertise<sensor_msgs::PointCloud2>("cluster_0", 1);
690  pub_cluster1 = nh.advertise<sensor_msgs::PointCloud2>("cluster_1", 1);
691  pub_cluster2 = nh.advertise<sensor_msgs::PointCloud2>("cluster_2", 1);
692  pub_cluster3 = nh.advertise<sensor_msgs::PointCloud2>("cluster_3", 1);
693  pub_cluster4 = nh.advertise<sensor_msgs::PointCloud2>("cluster_4", 1);
694  pub_cluster5 = nh.advertise<sensor_msgs::PointCloud2>("cluster_5", 1);
695  // Subscribe to the clustered pointclouds
696  // ros::Subscriber c1=nh.subscribe("ccs",100,KFT);
697  objID_pub = nh.advertise<std_msgs::Int32MultiArray>("obj_id", 1);
698  /* Point cloud clustering
699  */
700 
701  // cc_pos=nh.advertise<std_msgs::Float32MultiArray>("ccs",100);//clusterCenter1
702  markerPub = nh.advertise<visualization_msgs::MarkerArray>("viz", 1);
703 
704  /* Point cloud clustering
705  */
706 
707  ros::spin();
708 }
pub_cluster2
ros::Publisher pub_cluster2
Definition: main.cpp:59
pub_cluster1
ros::Publisher pub_cluster1
Definition: main.cpp:58
KF1
cv::KalmanFilter KF1(stateDim, measDim, ctrlDim, CV_32F)
pub_cluster5
ros::Publisher pub_cluster5
Definition: main.cpp:62
KF3
cv::KalmanFilter KF3(stateDim, measDim, ctrlDim, CV_32F)
ros::Publisher
KF2
cv::KalmanFilter KF2(stateDim, measDim, ctrlDim, CV_32F)
stateDim
int stateDim
Definition: main.cpp:47
ros::init
ROSCPP_DECL void init(const M_string &remappings, const std::string &name, uint32_t options=0)
s
XmlRpcServer s
ros.h
objID
std::vector< int > objID
Definition: main.cpp:71
main
int main(int argc, char **argv)
Definition: main.cpp:676
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
pub_cluster3
ros::Publisher pub_cluster3
Definition: main.cpp:60
ros::NodeHandle::advertise
Publisher advertise(AdvertiseOptions &ops)
point_cloud.h
measurement
cv::Mat_< float > measurement(2, 1)
f
f
firstFrame
bool firstFrame
Definition: main.cpp:74
KF5
cv::KalmanFilter KF5(stateDim, measDim, ctrlDim, CV_32F)
featureDetection.h
cloud_cb
void cloud_cb(const sensor_msgs::PointCloud2ConstPtr &input)
Definition: main.cpp:321
KF0
cv::KalmanFilter KF0(stateDim, measDim, ctrlDim, CV_32F)
prevClusterCenters
std::vector< geometry_msgs::Point > prevClusterCenters
Definition: main.cpp:66
pub_cluster4
ros::Publisher pub_cluster4
Definition: main.cpp:61
state
cv::Mat state(stateDim, 1, CV_32F)
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())
markerPub
ros::Publisher markerPub
Definition: main.cpp:64
objID_pub
ros::Publisher objID_pub
Definition: main.cpp:44
measDim
int measDim
Definition: main.cpp:48
std
ctrlDim
int ctrlDim
Definition: main.cpp:49
publish_cloud
void publish_cloud(ros::Publisher &pub, pcl::PointCloud< pcl::PointXYZ >::Ptr cluster)
Definition: main.cpp:312
pub_cluster0
ros::Publisher pub_cluster0
Definition: main.cpp:57
KF4
cv::KalmanFilter KF4(stateDim, measDim, ctrlDim, CV_32F)
setIdentity
void setIdentity(geometry_msgs::Transform &tx)
pcl::toROSMsg
void toROSMsg(const pcl::PointCloud< T > &cloud, sensor_msgs::Image &msg)
ros::spin
ROSCPP_DECL void spin()
KFT
void KFT(const std_msgs::Float32MultiArray ccs)
Definition: main.cpp:120
CKalmanFilter.h
euclidean_distance
double euclidean_distance(geometry_msgs::Point &p1, geometry_msgs::Point &p2)
Definition: main.cpp:77
ros::NodeHandle
ros::Subscriber
findIndexOfMin
std::pair< int, int > findIndexOfMin(std::vector< std::vector< float >> distMat)
Definition: main.cpp:105
ros::Time::now
static Time now()
pcl_conversions.h


multi_object_tracking_lidar
Author(s): Praveen Palanisamy
autogenerated on Wed Mar 2 2022 00:40:33