26 #ifndef velo2cam_utils_H 27 #define velo2cam_utils_H 29 #define PCL_NO_PRECOMPILE 32 #include <pcl/search/kdtree.h> 33 #include <pcl/segmentation/extract_clusters.h> 35 #define TARGET_NUM_CIRCLES 4 36 #define TARGET_RADIUS 0.12 37 #define GEOMETRY_TOLERANCE 0.06 47 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
50 void addRange(pcl::PointCloud<Velodyne::Point> &pc) {
51 for (pcl::PointCloud<Point>::iterator pt = pc.points.begin();
52 pt < pc.points.end(); pt++) {
53 pt->range =
sqrt(pt->x * pt->x + pt->y * pt->y + pt->z * pt->z);
57 vector<vector<Point *>>
getRings(pcl::PointCloud<Velodyne::Point> &pc,
59 vector<vector<Point *>> rings(rings_count);
60 for (pcl::PointCloud<Point>::iterator pt = pc.points.begin();
61 pt < pc.points.end(); pt++) {
62 rings[pt->ring].push_back(&(*pt));
69 float min_found = INFINITY;
70 float max_found = -INFINITY;
72 for (pcl::PointCloud<Point>::iterator pt = pc.points.begin();
73 pt < pc.points.end(); pt++) {
74 max_found =
max(max_found, pt->intensity);
75 min_found =
min(min_found, pt->intensity);
78 for (pcl::PointCloud<Point>::iterator pt = pc.points.begin();
79 pt < pc.points.end(); pt++) {
81 (pt->intensity - min_found) / (max_found - min_found) * (maxv - minv) +
88 (
float,
x,
x)(
float,
y,
y)(
float,
z,
z)(
90 intensity)(std::uint16_t, ring,
91 ring)(
float, range, range));
94 vector<pcl::PointXYZ> &v) {
104 pcl::PointCloud<pcl::PointXYZ>::Ptr spherical_centers(
105 new pcl::PointCloud<pcl::PointXYZ>());
108 for (pcl::PointCloud<pcl::PointXYZ>::iterator pt = pc->points.begin();
109 pt < pc->points.end(); pt++, index++) {
110 pcl::PointXYZ spherical_center;
111 spherical_center.x =
atan2(pt->y, pt->x);
113 atan2(
sqrt(pt->x * pt->x + pt->y * pt->y), pt->z);
115 sqrt(pt->x * pt->x + pt->y * pt->y + pt->z * pt->z);
116 spherical_centers->push_back(spherical_center);
118 if (spherical_center.y < spherical_centers->points[top_pt].y) {
124 vector<double> distances;
125 for (
int i = 0; i < 4; i++) {
126 pcl::PointXYZ pt = pc->points[i];
127 pcl::PointXYZ upper_pt = pc->points[top_pt];
128 distances.push_back(
sqrt(
pow(pt.x - upper_pt.x, 2) +
129 pow(pt.y - upper_pt.y, 2) +
130 pow(pt.z - upper_pt.z, 2)));
134 int min_dist = (top_pt + 1) % 4, max_dist = top_pt;
135 for (
int i = 0; i < 4; i++) {
136 if (i == top_pt)
continue;
137 if (distances[i] > distances[max_dist]) {
140 if (distances[i] < distances[min_dist]) {
146 int top_pt2 = 6 - (top_pt + max_dist + min_dist);
149 int lefttop_pt = top_pt;
150 int righttop_pt = top_pt2;
152 if (spherical_centers->points[top_pt].x <
153 spherical_centers->points[top_pt2].x) {
154 int aux = lefttop_pt;
155 lefttop_pt = righttop_pt;
160 double angle_diff = spherical_centers->points[lefttop_pt].x -
161 spherical_centers->points[righttop_pt].x;
162 if (angle_diff > M_PI - spherical_centers->points[lefttop_pt].x) {
163 int aux = lefttop_pt;
164 lefttop_pt = righttop_pt;
169 int leftbottom_pt = min_dist;
170 int rightbottom_pt = max_dist;
173 if (righttop_pt == top_pt) {
174 leftbottom_pt = max_dist;
175 rightbottom_pt = min_dist;
179 v[0] = pc->points[lefttop_pt];
180 v[1] = pc->points[righttop_pt];
181 v[2] = pc->points[rightbottom_pt];
182 v[3] = pc->points[leftbottom_pt];
186 pcl::PointCloud<pcl::PointXYZI>::Ptr coloured) {
188 for (
int i = 0; i < 4; i++) {
194 cc.intensity = intensity;
195 coloured->push_back(cc);
201 pcl::PointCloud<pcl::PointXYZ>::Ptr centers_cloud,
202 double cluster_tolerance = 0.10,
203 int min_cluster_size = 15,
int max_cluster_size = 200,
204 bool verbosity =
true) {
205 pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(
206 new pcl::search::KdTree<pcl::PointXYZ>);
207 tree->setInputCloud(cloud_in);
209 std::vector<pcl::PointIndices> cluster_indices;
210 pcl::EuclideanClusterExtraction<pcl::PointXYZ> euclidean_cluster;
211 euclidean_cluster.setClusterTolerance(cluster_tolerance);
212 euclidean_cluster.setMinClusterSize(min_cluster_size);
213 euclidean_cluster.setMaxClusterSize(max_cluster_size);
214 euclidean_cluster.setSearchMethod(tree);
215 euclidean_cluster.setInputCloud(cloud_in);
216 euclidean_cluster.extract(cluster_indices);
218 if (
DEBUG && verbosity)
219 cout << cluster_indices.size() <<
" clusters found from " 220 << cloud_in->points.size() <<
" points in cloud" << endl;
222 for (std::vector<pcl::PointIndices>::iterator it = cluster_indices.begin();
223 it < cluster_indices.end(); it++) {
224 float accx = 0., accy = 0., accz = 0.;
225 for (vector<int>::iterator it2 = it->indices.begin();
226 it2 < it->indices.end(); it2++) {
227 accx += cloud_in->at(*it2).x;
228 accy += cloud_in->at(*it2).y;
229 accz += cloud_in->at(*it2).z;
232 pcl::PointXYZ center;
233 center.x = accx / it->indices.size();
234 center.y = accy / it->indices.size();
235 center.z = accz / it->indices.size();
236 centers_cloud->push_back(center);
241 Eigen::Vector3f target) {
242 Eigen::Vector3f rotation_vector = target.cross(source);
243 rotation_vector.normalize();
244 double theta =
acos(source[2] /
sqrt(
pow(source[0], 2) +
pow(source[1], 2) +
248 cout <<
"Rot. vector: " << rotation_vector <<
" / Angle: " << theta << endl;
250 Eigen::Matrix3f rotation =
251 Eigen::AngleAxis<float>(theta, rotation_vector) * Eigen::Scaling(1.0
f);
252 Eigen::Affine3f rot(rotation);
263 Square(std::vector<pcl::PointXYZ> candidates,
float width,
float height) {
264 _candidates = candidates;
265 _target_width = width;
266 _target_height = height;
267 _target_diagonal =
sqrt(
pow(width, 2) +
pow(height, 2));
270 for (
int i = 0; i < candidates.size(); ++i) {
271 _center.x += candidates[i].x;
272 _center.y += candidates[i].y;
273 _center.z += candidates[i].z;
276 _center.x /= candidates.size();
277 _center.y /= candidates.size();
278 _center.z /= candidates.size();
281 float distance(pcl::PointXYZ pt1, pcl::PointXYZ pt2) {
282 return sqrt(
pow(pt1.x - pt2.x, 2) +
pow(pt1.y - pt2.y, 2) +
283 pow(pt1.z - pt2.z, 2));
289 for (
int i = 0; i < 4; ++i) {
290 perimeter +=
distance(_candidates[i], _candidates[(i + 1) % 4]);
295 pcl::PointXYZ
at(
int i) {
296 assert(0 <= i && i < 4);
297 return _candidates[i];
301 pcl::PointCloud<pcl::PointXYZ>::Ptr candidates_cloud(
302 new pcl::PointCloud<pcl::PointXYZ>());
304 for (
int i = 0; i < _candidates.size(); ++i) {
305 candidates_cloud->push_back(_candidates[i]);
306 float d =
distance(_center, _candidates[i]);
307 if (fabs(d - _target_diagonal / 2.) / (_target_diagonal / 2.) >
313 std::vector<pcl::PointXYZ> sorted_centers;
316 for (
int i = 0; i < sorted_centers.size(); ++i) {
318 sorted_centers[i], sorted_centers[(i + 1) % sorted_centers.size()]);
320 if (fabs(current_distance - _target_height) / _target_height >
325 if (fabs(current_distance - _target_width) / _target_width >
330 perimeter += current_distance;
332 float ideal_perimeter = (2 * _target_width + 2 * _target_height);
333 if (fabs((perimeter - ideal_perimeter) / ideal_perimeter >
343 void comb(
int N,
int K, std::vector<std::vector<int>> &groups) {
344 int upper_factorial = 1;
345 int lower_factorial = 1;
347 for (
int i = 0; i < K; i++) {
348 upper_factorial *= (N - i);
349 lower_factorial *= (K - i);
351 int n_permutations = upper_factorial / lower_factorial;
354 cout << N <<
" centers found. Iterating over " << n_permutations
355 <<
" possible sets of candidates" << endl;
357 std::string bitmask(K, 1);
358 bitmask.resize(N, 0);
362 std::vector<int> group;
363 for (
int i = 0; i < N; ++i)
369 groups.push_back(group);
370 }
while (std::prev_permutation(bitmask.begin(), bitmask.end()));
372 assert(groups.size() == n_permutations);
376 time_t now = time(0);
379 tstruct = *localtime(&now);
380 strftime(buf,
sizeof(buf),
"%Y-%m-%d.%X", &tstruct);
struct Velodyne::Point EIGEN_ALIGN16
float intensity
laser intensity reading
Square(std::vector< pcl::PointXYZ > candidates, float width, float height)
TFSIMD_FORCE_INLINE tfScalar distance(const Vector3 &v) const
TFSIMD_FORCE_INLINE const tfScalar & y() const
POINT_CLOUD_REGISTER_POINT_STRUCT(Velodyne::Point,(float, x, x)(float, y, y)(float, z, z)(float, intensity, intensity)(std::uint16_t, ring, ring)(float, range, range))
void normalizeIntensity(pcl::PointCloud< Point > &pc, float minv, float maxv)
float distance(pcl::PointXYZ pt1, pcl::PointXYZ pt2)
vector< vector< Point * > > getRings(pcl::PointCloud< Velodyne::Point > &pc, int rings_count)
#define GEOMETRY_TOLERANCE
void addRange(pcl::PointCloud< Velodyne::Point > &pc)
TFSIMD_FORCE_INLINE const tfScalar & x() const
double min(double a, double b)
std::vector< pcl::PointXYZ > _candidates
INLINE Rall1d< T, V, S > sqrt(const Rall1d< T, V, S > &arg)
void colourCenters(const std::vector< pcl::PointXYZ > pc, pcl::PointCloud< pcl::PointXYZI >::Ptr coloured)
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)
void sortPatternCenters(pcl::PointCloud< pcl::PointXYZ >::Ptr pc, vector< pcl::PointXYZ > &v)
std::uint16_t ring
laser ring number
INLINE Rall1d< T, V, S > acos(const Rall1d< T, V, S > &x)
const std::string currentDateTime()
INLINE Rall1d< T, V, S > atan2(const Rall1d< T, V, S > &y, const Rall1d< T, V, S > &x)
double max(double a, double b)
void comb(int N, int K, std::vector< std::vector< int >> &groups)