-
Notifications
You must be signed in to change notification settings - Fork 1
/
RotationParams.m
141 lines (106 loc) · 3.38 KB
/
RotationParams.m
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
function [alpha_1, beta_1, alpha_2] = RotationParams(pc)
direction = 'x';
% Bring the point cloud center to the origin
pc = pc - mean(pc);
% %%%This section align u normal vector along z-direction
% Obtain the eigenvector of the highest eigenvalue
u1 = pcaEig(pc, 'max');
u2 = pcaEig(pc, 'middle');
u3 = pcaEig(pc, 'min');
if abs(u1(3)) > 0.5
% istadeh
if u1(3) < 0
u1 = -1*(u1);
end
else
% khabideh
if u1(2)<0
u1 = -1*(u1);
end
end
if abs(u2(1)) > 0.5
% khabideh
if u2(1)<0
u2 = -1*(u2);
end
else
% istadeh
if u2(2)<0
u2 = -1*(u2);
end
end
if abs(u3(3)) > 0.5
if u3(3)<0
u3 = -1*(u3);
end
else
if u3(1)<0
u3 = -1*(u3);
end
end
% Calculate the angles of the normal vector
[alpha_1, beta_1] = unitVectorToAngle(u1);
% Align the point cloud along x-axis followed by aligning along z-axis
% YOU CAN REMOVE THE PI IF YOU WANT TO FLIP THE POINT CLOUD ALONG
% Z-DIRECTION
[~, Ry, Rz] = rotationalMatrix(-alpha_1, pi-beta_1);
pc2 = rotatePC(pc, Ry, Rz);
% %%%This section align v normal vector along x or y direction
switch direction
case 'x'
offset = 0;
case 'y'
offset = pi/2;
end
% Obtain the eigenvector of the 3nd highest eigenvalue
% Calculate the angle of the projected v-vector along the xy-plane
% with respect to the x-axis
[alpha_2, ~] = unitVectorToAngle(u2);
% Calculate the rotational matrix for the angle
[~, Ry, Rz] = rotationalMatrix(offset - alpha_2, 0);
% Rotate the point cloud
pc2 = rotatePC(pc2, Ry, Rz);
% pc2 = pc2 + PcMean;
end
function [Rx, Ry, Rz] = rotationalMatrix(alpha, beta)
Rx = [1 0 0; 0 cos(beta) -sin(beta); 0 sin(beta) cos(beta)];
Ry = [cos(beta) 0 sin(beta); 0 1 0; -sin(beta) 0 cos(beta)];
Rz = [cos(alpha) -sin(alpha) 0; sin(alpha) cos(alpha) 0; 0 0 1];
end
function u = pcaEig(pc, magnitude)
% Obtain the covariance matrix
covariance = cov([pc(:, 1) pc(:, 2) pc(:, 3)]);
% Calculate the eigenvectors and obtain the normal vector
[V, D] = eig(covariance);
diagonalEigenvalues = diag(D);
% Output the normal vector
% Sort the eigenvectors based on size of eigenvalues
[~, I] = sort(diagonalEigenvalues);
V = V(:, I);
switch magnitude
case 'max'
% Choose the eigenvector of the highest eigenvalue
u = V(:, 3);
case 'middle'
% Choose the eigenvector of the middle eigenvalue
u = V(:, 2);
case 'min'
% Choose the eigenvector of the lowest eigenvalue
u = V(:, 1);
end
end
function [alpha, beta] = unitVectorToAngle(u)
% Rotational angle between the projected u on the xy plane and the x-axis
alpha = atan2(u(2), u(1));
% Rotational angle between the u vector and the z-axis
beta = atan2(sqrt(u(1)^2 + u(2)^2), u(3));
end
function pc2 = rotatePC(pc, Ry, Rz)
% Convert the point cloud to 3 * N format
matrix = pc';
% rotation around z axis to align point cloud along x axis
matrix2 = Rz*matrix;
matrix2 = Ry*matrix2;
% Ouput the point cloud
pc2 = matrix2';
end