forked from AutoLidarPerception/common_lib
-
Notifications
You must be signed in to change notification settings - Fork 0
/
common.hpp
160 lines (137 loc) · 5.38 KB
/
common.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/*
* Copyright (C) 2019 by AutoSense Organization. All rights reserved.
* Gary Chan <[email protected]>
*/
#ifndef COMMON_INCLUDE_COMMON_COMMON_HPP_
#define COMMON_INCLUDE_COMMON_COMMON_HPP_
#include <ros/ros.h>
#include <pcl/common/centroid.h> // pcl::compute3DCentroid
#include <pcl/common/transforms.h> // pcl::transformPointCloud
#include <pcl/io/pcd_io.h> // pcl::io::savePCDFileASCII
#include <Eigen/Core>
#include <cmath> // sqrt, pow
#include <string>
#include <utility>
#include <vector>
#include "common/types/type.h"
namespace autosense {
namespace common {
// float precision
const float EPSILON = 1e-9;
//----------------------------------- sort compare function
template <typename PointType>
bool sortByAxisXAsc(PointType p1, PointType p2) {
return p1.x < p2.x;
}
template <typename PointType>
bool sortByAxisZAsc(PointType p1, PointType p2) {
return p1.z < p2.z;
}
template <typename ObjType>
bool sortByObjSizeDesc(ObjType obj1, ObjType obj2) {
return obj1->cloud->size() > obj2->cloud->size();
}
/// \brief Utility function for swapping two values.
template <typename T>
bool swap_if_gt(T& a, T& b) { // NOLINT
if (a > b) {
std::swap(a, b);
return true;
}
return false;
}
//----------------------------------- *.pcd
static void savePCDModel(PointICloudConstPtr pc,
const std::string& model_name) {
// std::string pcd_model_file = "model.pcd";
pcl::io::savePCDFileASCII(model_name, *pc);
ROS_INFO_STREAM("PCD Model " << model_name << " saved.");
}
static void loadPCDModel(PointICloudPtr pc, const std::string& model_name) {
pcl::io::loadPCDFile<PointI>(model_name, *pc);
ROS_INFO_STREAM("PCD Model " << model_name << " loaded.");
}
static bool loadPCDModel(PointCloudPtr pc,
Eigen::Affine3f& model2world) { // NOLINT
std::string pcd_model_file =
"/home/gary/Workspace/intern_ws/pcl_learning/model.pcd";
if (pcl::io::loadPCDFile<Point>(pcd_model_file, *pc) == -1) {
return false;
} else {
ROS_INFO_STREAM("PCD Model " << pcd_model_file << " loaded");
model2world = Eigen::Affine3f::Identity();
Eigen::Vector4f model_centroid;
pcl::compute3DCentroid<Point>(*pc, model_centroid);
model2world.translation().matrix() = Eigen::Vector3f(
model_centroid[0], model_centroid[1], model_centroid[2]);
pcl::transformPointCloud(*pc, *pc, model2world.inverse());
return true;
}
}
/**
* @brief convert PointI cloud in indices to PointD cloud
* @param cloud
* @param indices
* @param trans_cloud
*/
static void convertPointCloud(PointICloudPtr icloud,
const std::vector<int>& indices,
PointDCloud* dcloud) {
if (dcloud->size() != indices.size()) {
dcloud->resize(indices.size());
}
for (size_t i = 0u; i < indices.size(); ++i) {
const PointI& p = icloud->at(indices[i]);
Eigen::Vector3d v(p.x, p.y, p.z);
PointD& tp = dcloud->at(i);
tp.x = v.x();
tp.y = v.y();
tp.z = v.z();
tp.intensity = p.intensity;
}
}
//----------------------------------- print information
static void displayPerformances(unsigned int tp,
unsigned int tn,
unsigned int fp,
unsigned int fn) {
ROS_INFO_STREAM("TP: " << tp << ", TN: " << tn << ", FP: " << fp
<< ", FN: " << fn << ".");
const double true_positive_rate =
static_cast<double>(tp) / static_cast<double>(tp + fn);
const double true_negative_rate =
static_cast<double>(tn) / static_cast<double>(fp + tn);
const double false_positive_rate = 1.0 - true_negative_rate;
ROS_INFO_STREAM(
"Accuracy (ACC): " << static_cast<double>(tp + tn) /
static_cast<double>(tp + fp + tn + fn));
ROS_INFO_STREAM("Sensitivity (TPR): " << true_positive_rate);
ROS_INFO_STREAM("Specificity (TNR): " << true_negative_rate);
ROS_INFO_STREAM("Precision: " << static_cast<double>(tp) /
static_cast<double>(tp + fp));
ROS_INFO_STREAM("Positive likelyhood ratio: " << true_positive_rate /
false_positive_rate);
}
static void displayGroundTruth(const Eigen::Vector3f& center,
const Eigen::Vector3f& size,
double yaw_rad) {
ROS_INFO("-------- Bounding Box --------");
ROS_INFO_STREAM("\tSize: " << size(0) << " x " << size(1) << " x "
<< size(2));
ROS_INFO_STREAM("\tCenter: (" << center(0) << ", " << center(1) << ", "
<< center(2) << ")");
ROS_INFO_STREAM("\tYaw(rad): " << yaw_rad);
ROS_INFO("-------- Bounding Box --------");
}
template <typename VolumetricModelType>
static void displayModelInfo(const VolumetricModelType& model) {
ROS_INFO(
"Model:\t length[%.2f..%.2f]/width[%.2f..%.2f]/height[%.2f..%.2f]\n",
model.l_min, model.l_max, model.w_min, model.w_max, model.h_min,
model.h_max);
}
//----------------------------------- math utils
static float toRad(float degree) { return degree * (M_PI / 180.f); }
} // namespace common
} // namespace autosense
#endif // COMMON_INCLUDE_COMMON_COMMON_HPP_