-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathICP.cpp
More file actions
137 lines (125 loc) · 3.87 KB
/
ICP.cpp
File metadata and controls
137 lines (125 loc) · 3.87 KB
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
#include "ICP.h"
#include <algorithm>
#include "GoICP\ConfigMap.hpp"
using namespace std;
ICP::ICP()
{
}
ICP::~ICP()
{
delete(pModel);
delete(pData);
}
bool isEqual_float(float x, float y) {
const float EPSILON = 0.001f;
return (fabs(x - y) < EPSILON);
}
/*
struct {
bool operator()(const POINT3D &p1,const POINT3D &p2) {
if (p1.x != p2.x) return p1.x < p2.x;
else if (p1.y != p2.y) return p1.y < p2.y;
else if (p1.z != p2.z) return p1.z < p2.z;
}
} compare_POINTS3D;
*/
bool compare_POINTS3D(const POINT3D &p1,const POINT3D &p2) {
if (isEqual_float(p1.x, p2.x)) {
if (isEqual_float(p1.y, p2.y)) {
return p1.z < p2.z;
}
return p1.y < p2.y;
}
return p1.x < p2.x;
}
bool isEqual_POINTS3D(const POINT3D &p1,const POINT3D &p2) {
return (isEqual_float(p1.x, p2.x)&isEqual_float(p1.y, p2.y)&isEqual_float(p1.z, p2.z));
}
void ICP::load_points(const std::vector<float> &vModel, const std::vector<float> &vData) {
vector<POINT3D> temp_points;
for (auto itt = vModel.begin(); itt != vModel.end(); itt += 3) {
POINT3D temp_point;
temp_point.x = *itt;
temp_point.y = *(itt + 1);
temp_point.z = *(itt + 2);
temp_points.push_back(temp_point);
}
std::sort(temp_points.begin(), temp_points.end(), compare_POINTS3D);
auto trim_head = unique(temp_points.begin(), temp_points.end(), isEqual_POINTS3D);
temp_points.erase(trim_head, temp_points.end());
pModel = (POINT3D *)malloc(sizeof(POINT3D) * temp_points.size());
for (auto i = 0; i < temp_points.size(); i++) {
pModel[i] = temp_points.at(i);
}
Nm = int(temp_points.size());
temp_points.clear();
for (auto itt = vData.begin(); itt != vData.end(); itt += 3) {
POINT3D temp_point;
temp_point.x = *itt;
temp_point.y = *(itt + 1);
temp_point.z = *(itt + 2);
temp_points.push_back(temp_point);
}
std::sort(temp_points.begin(), temp_points.end(), compare_POINTS3D);
trim_head = unique(temp_points.begin(), temp_points.end(), isEqual_POINTS3D);
temp_points.erase(trim_head, temp_points.end());
pData = (POINT3D *)malloc(sizeof(POINT3D) * temp_points.size());
for (auto i = 0; i < temp_points.size(); i++) {
pData[i] = temp_points.at(i);
}
Nd = int(temp_points.size());
temp_points.clear();
}
void ICP::readConfig(string FName)
{
// Open and parse the associated config file
ConfigMap config(FName.c_str());
goicp.MSEThresh = config.getF("MSEThresh");
goicp.initNodeRot.a = config.getF("rotMinX");
goicp.initNodeRot.b = config.getF("rotMinY");
goicp.initNodeRot.c = config.getF("rotMinZ");
goicp.initNodeRot.w = config.getF("rotWidth");
goicp.initNodeTrans.x = config.getF("transMinX");
goicp.initNodeTrans.y = config.getF("transMinY");
goicp.initNodeTrans.z = config.getF("transMinZ");
goicp.initNodeTrans.w = config.getF("transWidth");
goicp.trimFraction = config.getF("trimFraction");
// If < 0.1% trimming specified, do no trimming
if (goicp.trimFraction < 0.001)
{
goicp.doTrim = false;
}
goicp.dt.SIZE = config.getI("distTransSize");
goicp.dt.expandFactor = config.getF("distTransExpandFactor");
cout << "CONFIG:" << endl;
config.print();
//cout << "(doTrim)->(" << goicp.doTrim << ")" << endl;
cout << endl;
}
void ICP::run() {
goicp.pModel = pModel;
goicp.Nm = Nm;
goicp.pData = pData;
goicp.Nd = Nd;
// Build Distance Transform
goicp.BuildDT();
int NdDownsampled = min(1000, Nd);
// Run GO-ICP
if (NdDownsampled > 0)
{
goicp.Nd = NdDownsampled; // Only use first NdDownsampled data points (assumes data points are randomly ordered)
}
goicp.Register();
cout << "Optimal Rotation Matrix:" << endl;
cout << goicp.optR << endl;
cout << "Optimal Translation Vector:" << endl;
cout << goicp.optT << endl;
string outputFname = "result/icp_output.txt";
ofstream ofile;
ofile.open(outputFname.c_str(), ofstream::out);
ofile << "#time " << time << endl;
ofile << "#optR " << goicp.optR << endl;
ofile << "#optT " << goicp.optT << endl;
ofile << "#Error " << goicp.optError << endl;
ofile.close();
}