velo2cam_utils.h
Go to the documentation of this file.
1 /*
2  velo2cam_calibration - Automatic calibration algorithm for extrinsic parameters of a stereo camera and a velodyne
3  Copyright (C) 2017-2018 Jorge Beltran, Carlos Guindel
4 
5  This file is part of velo2cam_calibration.
6 
7  velo2cam_calibration is free software: you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation, either version 2 of the License, or
10  (at your option) any later version.
11 
12  velo2cam_calibration is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with velo2cam_calibration. If not, see <http://www.gnu.org/licenses/>.
19 */
20 
21 #ifndef velo2cam_utils_H
22 #define velo2cam_utils_H
23 
24 #define PCL_NO_PRECOMPILE
25 #define DEBUG 0
26 
27 #include <vector>
28 #include <cmath>
29 #include <unistd.h>
30 #include <pcl/point_cloud.h>
31 #include <pcl/point_types.h>
32 #include <pcl/kdtree/kdtree.h>
33 #include <pcl/segmentation/extract_clusters.h>
34 #include <pcl/common/eigen.h>
35 #include <pcl/common/transforms.h>
36 #include <ros/ros.h>
37 
38 using namespace std;
39 
40 static const int RINGS_COUNT = 16; // TODO AS FUNCTION PARAM
41 
42 namespace Velodyne {
43  struct Point
44  {
45  PCL_ADD_POINT4D; // quad-word XYZ
46  float intensity;
47  uint16_t ring;
48  float range;
49  EIGEN_MAKE_ALIGNED_OPERATOR_NEW // ensure proper alignment
51 
52  void addRange(pcl::PointCloud<Velodyne::Point> & pc){
53  for (pcl::PointCloud<Point>::iterator pt = pc.points.begin(); pt < pc.points.end(); pt++)
54  {
55  pt->range = sqrt(pt->x * pt->x + pt->y * pt->y + pt->z * pt->z);
56  }
57  }
58 
59  vector<vector<Point*> > getRings(pcl::PointCloud<Velodyne::Point> & pc)
60  {
61  vector<vector<Point*> > rings(RINGS_COUNT);
62  for (pcl::PointCloud<Point>::iterator pt = pc.points.begin(); pt < pc.points.end(); pt++)
63  {
64  rings[pt->ring].push_back(&(*pt));
65  }
66  return rings;
67  }
68 
69  // all intensities to range min-max
70  void normalizeIntensity(pcl::PointCloud<Point> & pc, float minv, float maxv)
71  {
72  float min_found = INFINITY;
73  float max_found = -INFINITY;
74 
75  for (pcl::PointCloud<Point>::iterator pt = pc.points.begin(); pt < pc.points.end(); pt++)
76  {
77  max_found = max(max_found, pt->intensity);
78  min_found = min(min_found, pt->intensity);
79  }
80 
81  for (pcl::PointCloud<Point>::iterator pt = pc.points.begin(); pt < pc.points.end(); pt++)
82  {
83  pt->intensity = (pt->intensity - min_found) / (max_found - min_found) * (maxv - minv) + minv;
84  }
85  }
86 }
87 
89  Velodyne::Point, (float, x, x) (float, y, y) (float, z, z)
90  (float, intensity, intensity) (uint16_t, ring, ring) (float, range, range));
91 
92 void sortPatternCentersXY(pcl::PointCloud<pcl::PointXYZ>::Ptr pc, vector<pcl::PointXYZ> &v){
93  double avg_x = 0, avg_y = 0;
94  for(pcl::PointCloud<pcl::PointXYZ>::iterator it=pc->points.begin(); it<pc->points.end(); it++){
95  avg_x += (*it).x;
96  avg_y += (*it).y;
97  }
98 
99  pcl::PointXYZ center;
100  center.x = avg_x/4.;
101  center.y = avg_y/4.;
102 
103  for(pcl::PointCloud<pcl::PointXYZ>::iterator it=pc->points.begin(); it<pc->points.end(); it++){
104  double x_dif = (*it).x - center.x;
105  double y_dif = (*it).y - center.y;
106 
107  if(x_dif < 0 && y_dif < 0){
108  v[0] = (*it);
109  }else if(x_dif > 0 && y_dif < 0){
110  v[1] = (*it);
111  }else if(x_dif > 0 && y_dif > 0){
112  v[2] = (*it);
113  }else{
114  v[3] = (*it);
115  }
116  }
117 }
118 
119 void sortPatternCentersYZ(pcl::PointCloud<pcl::PointXYZ>::Ptr pc, vector<pcl::PointXYZ> &v){
120  double avg_y = 0, avg_z = 0;
121  for(pcl::PointCloud<pcl::PointXYZ>::iterator it=pc->points.begin(); it<pc->points.end(); it++){
122  avg_y += (*it).y;
123  avg_z += (*it).z;
124  }
125 
126  pcl::PointXYZ center;
127  center.y = avg_y/4.;
128  center.z = avg_z/4.;
129 
130  for(pcl::PointCloud<pcl::PointXYZ>::iterator it=pc->points.begin(); it<pc->points.end(); it++){
131  double y_dif = (*it).y - center.y;
132  double z_dif = (*it).z - center.z;
133 
134  if(y_dif > 0 && z_dif > 0){
135  v[0] = (*it);
136  }else if(y_dif < 0 && z_dif > 0){
137  v[1] = (*it);
138  }else if(y_dif < 0 && z_dif < 0){
139  v[2] = (*it);
140  }else{
141  v[3] = (*it);
142  }
143  }
144 }
145 
146 void colourCenters(const pcl::PointCloud<pcl::PointXYZ>::Ptr pc, pcl::PointCloud<pcl::PointXYZI>::Ptr coloured){
147  double avg_x = 0, avg_y = 0;
148  for(pcl::PointCloud<pcl::PointXYZ>::iterator it=pc->points.begin(); it<pc->points.end(); it++){
149  avg_x += (*it).x;
150  avg_y += (*it).y;
151  }
152 
153  pcl::PointXYZ center;
154  center.x = avg_x/4.;
155  center.y = avg_y/4.;
156 
157  for(pcl::PointCloud<pcl::PointXYZ>::iterator it=pc->points.begin(); it<pc->points.end(); it++){
158  double x_dif = (*it).x - center.x;
159  double y_dif = (*it).y - center.y;
160 
161 
162  pcl::PointXYZI cc;
163  cc.x = (*it).x;
164  cc.y = (*it).y;
165  cc.z = (*it).z;
166 
167  if(x_dif < 0 && y_dif < 0){
168  cc.intensity = 0;
169  }else if(x_dif > 0 && y_dif < 0){
170  cc.intensity = 0.3;
171  }else if(x_dif > 0 && y_dif > 0){
172  cc.intensity = 0.6;
173  }else{
174  cc.intensity = 1;
175  }
176  coloured->push_back(cc);
177  }
178 }
179 
180 void getCenterClusters(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_in, pcl::PointCloud<pcl::PointXYZ>::Ptr centers_cloud,
181  double cluster_tolerance = 0.10, int min_cluster_size = 15, int max_cluster_size = 200, bool verbosity=true){
182 
183  pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ>);
184  tree->setInputCloud (cloud_in);
185 
186  std::vector<pcl::PointIndices> cluster_indices;
187  pcl::EuclideanClusterExtraction<pcl::PointXYZ> euclidean_cluster;
188  euclidean_cluster.setClusterTolerance (cluster_tolerance);
189  euclidean_cluster.setMinClusterSize (min_cluster_size);
190  euclidean_cluster.setMaxClusterSize (max_cluster_size);
191  euclidean_cluster.setSearchMethod (tree);
192  euclidean_cluster.setInputCloud (cloud_in);
193  euclidean_cluster.extract (cluster_indices);
194 
195  if(DEBUG && verbosity) cout << cluster_indices.size() << " clusters found from " << cloud_in->points.size() << " points in cloud" << endl;
196 
197  for (std::vector<pcl::PointIndices>::iterator it=cluster_indices.begin(); it<cluster_indices.end(); it++) {
198  float accx = 0., accy = 0., accz = 0.;
199  for(vector<int>::iterator it2=it->indices.begin(); it2<it->indices.end(); it2++){
200  accx+=cloud_in->at(*it2).x;
201  accy+=cloud_in->at(*it2).y;
202  accz+=cloud_in->at(*it2).z;
203  }
204  // Compute and add center to clouds
205  pcl::PointXYZ center;
206  center.x = accx/it->indices.size();
207  center.y = accy/it->indices.size();
208  center.z = accz/it->indices.size();
209  centers_cloud->push_back(center);
210  }
211 }
212 
213 Eigen::Affine3f getRotationMatrix(Eigen::Vector3f source, Eigen::Vector3f target){
214  Eigen::Vector3f rotation_vector = target.cross(source);
215  rotation_vector.normalize();
216  double theta = acos(source[2]/sqrt( pow(source[0],2)+ pow(source[1],2) + pow(source[2],2)));
217 
218  if(DEBUG) ROS_INFO("Rot. vector: (%lf %lf %lf) / Angle: %lf", rotation_vector[0], rotation_vector[1], rotation_vector[2], theta);
219 
220  Eigen::Matrix3f rotation = Eigen::AngleAxis<float>(theta, rotation_vector) * Eigen::Scaling(1.0f);
221  Eigen::Affine3f rot(rotation);
222  return rot;
223 }
224 
225 #endif
void sortPatternCentersXY(pcl::PointCloud< pcl::PointXYZ >::Ptr pc, vector< pcl::PointXYZ > &v)
void sortPatternCentersYZ(pcl::PointCloud< pcl::PointXYZ >::Ptr pc, vector< pcl::PointXYZ > &v)
vector< vector< Point * > > getRings(pcl::PointCloud< Velodyne::Point > &pc)
f
float intensity
laser intensity reading
POINT_CLOUD_REGISTER_POINT_STRUCT(Velodyne::Point,(float, x, x)(float, y, y)(float, z, z)(float, intensity, intensity)(uint16_t, ring, ring)(float, range, range))
struct Velodyne::Point EIGEN_ALIGN16
uint16_t ring
laser ring number
TFSIMD_FORCE_INLINE const tfScalar & y() const
#define DEBUG
void normalizeIntensity(pcl::PointCloud< Point > &pc, float minv, float maxv)
#define ROS_INFO(...)
void addRange(pcl::PointCloud< Velodyne::Point > &pc)
TFSIMD_FORCE_INLINE const tfScalar & x() const
double min(double a, double b)
INLINE Rall1d< T, V, S > sqrt(const Rall1d< T, V, S > &arg)
Eigen::Affine3f getRotationMatrix(Eigen::Vector3f source, Eigen::Vector3f target)
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)
TFSIMD_FORCE_INLINE const tfScalar & z() const
INLINE Rall1d< T, V, S > pow(const Rall1d< T, V, S > &arg, double m)
INLINE Rall1d< T, V, S > acos(const Rall1d< T, V, S > &x)
void colourCenters(const pcl::PointCloud< pcl::PointXYZ >::Ptr pc, pcl::PointCloud< pcl::PointXYZI >::Ptr coloured)
double max(double a, double b)
static const int RINGS_COUNT


velo2cam_calibration
Author(s): Jorge Beltran , Carlos Guindel
autogenerated on Thu Feb 28 2019 03:24:25