forked from ClayFlannigan/icp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
test.py
115 lines (78 loc) · 3.15 KB
/
test.py
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
import numpy as np
import time
import icp
# Constants
N = 10 # number of random points in the dataset
num_tests = 100 # number of test iterations
dim = 3 # number of dimensions of the points
noise_sigma = .01 # standard deviation error to be added
translation = .1 # max translation of the test set
rotation = .1 # max rotation (radians) of the test set
def rotation_matrix(axis, theta):
axis = axis/np.sqrt(np.dot(axis, axis))
a = np.cos(theta/2.)
b, c, d = -axis*np.sin(theta/2.)
return np.array([[a*a+b*b-c*c-d*d, 2*(b*c-a*d), 2*(b*d+a*c)],
[2*(b*c+a*d), a*a+c*c-b*b-d*d, 2*(c*d-a*b)],
[2*(b*d-a*c), 2*(c*d+a*b), a*a+d*d-b*b-c*c]])
def test_best_fit():
# Generate a random dataset
A = np.random.rand(N, dim)
total_time = 0
for i in range(num_tests):
B = np.copy(A)
# Translate
t = np.random.rand(dim)*translation
B += t
# Rotate
R = rotation_matrix(np.random.rand(dim), np.random.rand()*rotation)
B = np.dot(R, B.T).T
# Add noise
B += np.random.randn(N, dim) * noise_sigma
# Find best fit transform
start = time.time()
T, R1, t1 = icp.best_fit_transform(B, A)
total_time += time.time() - start
# Make C a homogeneous representation of B
C = np.ones((N, 4))
C[:,0:3] = B
# Transform C
C = np.dot(T, C.T).T
assert np.allclose(C[:,0:3], A, atol=6*noise_sigma) # T should transform B (or C) to A
assert np.allclose(-t1, t, atol=6*noise_sigma) # t and t1 should be inverses
assert np.allclose(R1.T, R, atol=6*noise_sigma) # R and R1 should be inverses
print('best fit time: {:.3}'.format(total_time/num_tests))
return
def test_icp():
# Generate a random dataset
A = np.random.rand(N, dim)
total_time = 0
for i in range(num_tests):
B = np.copy(A)
# Translate
t = np.random.rand(dim)*translation
B += t
# Rotate
R = rotation_matrix(np.random.rand(dim), np.random.rand() * rotation)
B = np.dot(R, B.T).T
# Add noise
B += np.random.randn(N, dim) * noise_sigma
# Shuffle to disrupt correspondence
np.random.shuffle(B)
# Run ICP
start = time.time()
T, distances, iterations = icp.icp(B, A, tolerance=0.000001)
total_time += time.time() - start
# Make C a homogeneous representation of B
C = np.ones((N, 4))
C[:,0:3] = np.copy(B)
# Transform C
C = np.dot(T, C.T).T
assert np.mean(distances) < 6*noise_sigma # mean error should be small
assert np.allclose(T[0:3,0:3].T, R, atol=6*noise_sigma) # T and R should be inverses
assert np.allclose(-T[0:3,3], t, atol=6*noise_sigma) # T and t should be inverses
print('icp time: {:.3}'.format(total_time/num_tests))
return
if __name__ == "__main__":
test_best_fit()
test_icp()